summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.codeclimate.yml40
-rw-r--r--.eslintignore2
-rw-r--r--.eslintrc.yml21
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml3
-rw-r--r--.gitlab/CODEOWNERS13
-rw-r--r--.gitlab/ci/cache-repo.gitlab-ci.yml63
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml24
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml14
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml30
-rw-r--r--.gitlab/ci/qa-report.gitlab-ci.yml15
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml54
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml280
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml12
-rw-r--r--.gitlab/ci/review-apps/main.gitlab-ci.yml7
-rw-r--r--.gitlab/ci/review-apps/qa.gitlab-ci.yml40
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml244
-rw-r--r--.gitlab/ci/setup.gitlab-ci.yml32
-rw-r--r--.gitlab/ci/static-analysis.gitlab-ci.yml92
-rw-r--r--.gitlab/ci/workhorse.gitlab-ci.yml15
-rw-r--r--.gitlab/ci/yaml.gitlab-ci.yml2
-rw-r--r--.gitlab/issue_templates/Audit Event Proposal.md2
-rw-r--r--.gitlab/issue_templates/Bug.md6
-rw-r--r--.gitlab/issue_templates/Deprecations.md6
-rw-r--r--.gitlab/issue_templates/Empty state.md80
-rw-r--r--.gitlab/issue_templates/Experiment Implementation.md25
-rw-r--r--.gitlab/issue_templates/Experiment Rollout.md11
-rw-r--r--.gitlab/issue_templates/Experiment Successful Cleanup.md5
-rw-r--r--.gitlab/issue_templates/Experimentation.md25
-rw-r--r--.gitlab/issue_templates/Feature Flag Roll Out.md26
-rw-r--r--.gitlab/issue_templates/Feature Proposal - basic.md10
-rw-r--r--.gitlab/issue_templates/Feature Proposal - lean.md93
-rw-r--r--.gitlab/issue_templates/Feature proposal - detailed.md12
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new Git repository type.md278
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new blob type.md275
-rw-r--r--.gitlab/issue_templates/InfraDev.md2
-rw-r--r--.gitlab/issue_templates/Problem Validation.md8
-rw-r--r--.gitlab/issue_templates/Productivity Improvement.md2
-rw-r--r--.gitlab/issue_templates/Refactoring.md4
-rw-r--r--.gitlab/issue_templates/Security developer workflow.md2
-rw-r--r--.gitlab/issue_templates/Technical Evaluation.md2
-rw-r--r--.gitlab/merge_request_templates/Deprecations.md27
-rw-r--r--.gitlab/merge_request_templates/Documentation.md4
-rw-r--r--.gitlab/merge_request_templates/New End To End Test.md4
-rw-r--r--.gitlab/merge_request_templates/Pipeline Configuration.md4
-rw-r--r--.gitlab/merge_request_templates/Quarantine End to End Test.md2
-rw-r--r--.gitpod.yml9
-rw-r--r--.haml-lint.yml1
-rw-r--r--.nvmrc2
-rw-r--r--.rubocop.yml58
-rw-r--r--.rubocop_manual_todo.yml130
-rw-r--r--.rubocop_todo.yml6
-rw-r--r--.stylelintrc21
-rw-r--r--CHANGELOG.md73
-rw-r--r--Dangerfile17
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_KAS_VERSION2
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--Gemfile24
-rw-r--r--Gemfile.lock55
-rw-r--r--Guardfile4
-rw-r--r--README.md2
-rw-r--r--app/assets/images/auth_buttons/dingtalk_64.pngbin0 -> 1623 bytes
-rw-r--r--app/assets/images/emoji.pngbin1219696 -> 1356857 bytes
-rw-r--r--app/assets/images/emoji/100.pngbin793 -> 0 bytes
-rw-r--r--app/assets/images/emoji/1234.pngbin676 -> 0 bytes
-rw-r--r--app/assets/images/emoji/8ball.pngbin810 -> 0 bytes
-rw-r--r--app/assets/images/emoji/a.pngbin469 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ab.pngbin505 -> 0 bytes
-rw-r--r--app/assets/images/emoji/abc.pngbin646 -> 0 bytes
-rw-r--r--app/assets/images/emoji/abcd.pngbin670 -> 0 bytes
-rw-r--r--app/assets/images/emoji/accept.pngbin491 -> 0 bytes
-rw-r--r--app/assets/images/emoji/aerial_tramway.pngbin759 -> 0 bytes
-rw-r--r--app/assets/images/emoji/airplane.pngbin1152 -> 0 bytes
-rw-r--r--app/assets/images/emoji/airplane_arriving.pngbin1101 -> 0 bytes
-rw-r--r--app/assets/images/emoji/airplane_departure.pngbin1111 -> 0 bytes
-rw-r--r--app/assets/images/emoji/airplane_small.pngbin1229 -> 0 bytes
-rw-r--r--app/assets/images/emoji/alarm_clock.pngbin1044 -> 0 bytes
-rw-r--r--app/assets/images/emoji/alembic.pngbin953 -> 0 bytes
-rw-r--r--app/assets/images/emoji/alien.pngbin839 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ambulance.pngbin1238 -> 0 bytes
-rw-r--r--app/assets/images/emoji/amphora.pngbin1044 -> 0 bytes
-rw-r--r--app/assets/images/emoji/anchor.pngbin779 -> 0 bytes
-rw-r--r--app/assets/images/emoji/angel.pngbin2077 -> 0 bytes
-rw-r--r--app/assets/images/emoji/angel_tone1.pngbin2088 -> 0 bytes
-rw-r--r--app/assets/images/emoji/angel_tone2.pngbin2075 -> 0 bytes
-rw-r--r--app/assets/images/emoji/angel_tone3.pngbin2078 -> 0 bytes
-rw-r--r--app/assets/images/emoji/angel_tone4.pngbin2076 -> 0 bytes
-rw-r--r--app/assets/images/emoji/angel_tone5.pngbin2078 -> 0 bytes
-rw-r--r--app/assets/images/emoji/anger.pngbin594 -> 0 bytes
-rw-r--r--app/assets/images/emoji/anger_right.pngbin551 -> 0 bytes
-rw-r--r--app/assets/images/emoji/angry.pngbin845 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ant.pngbin1412 -> 0 bytes
-rw-r--r--app/assets/images/emoji/apple.pngbin655 -> 0 bytes
-rw-r--r--app/assets/images/emoji/aquarius.pngbin648 -> 0 bytes
-rw-r--r--app/assets/images/emoji/aries.pngbin711 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_backward.pngbin429 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_double_down.pngbin543 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_double_up.pngbin535 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_down.pngbin512 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_down_small.pngbin455 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_forward.pngbin429 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_heading_down.pngbin563 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_heading_up.pngbin559 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_left.pngbin471 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_lower_left.pngbin520 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_lower_right.pngbin526 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_right.pngbin468 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_right_hook.pngbin644 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_up.pngbin507 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_up_down.pngbin474 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_up_small.pngbin454 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_upper_left.pngbin521 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrow_upper_right.pngbin524 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrows_clockwise.pngbin519 -> 0 bytes
-rw-r--r--app/assets/images/emoji/arrows_counterclockwise.pngbin693 -> 0 bytes
-rw-r--r--app/assets/images/emoji/art.pngbin1455 -> 0 bytes
-rw-r--r--app/assets/images/emoji/articulated_lorry.pngbin1710 -> 0 bytes
-rw-r--r--app/assets/images/emoji/asterisk.pngbin627 -> 0 bytes
-rw-r--r--app/assets/images/emoji/astonished.pngbin862 -> 0 bytes
-rw-r--r--app/assets/images/emoji/athletic_shoe.pngbin1595 -> 0 bytes
-rw-r--r--app/assets/images/emoji/atm.pngbin1397 -> 0 bytes
-rw-r--r--app/assets/images/emoji/atom.pngbin912 -> 0 bytes
-rw-r--r--app/assets/images/emoji/avocado.pngbin1520 -> 0 bytes
-rw-r--r--app/assets/images/emoji/b.pngbin391 -> 0 bytes
-rw-r--r--app/assets/images/emoji/baby.pngbin1380 -> 0 bytes
-rw-r--r--app/assets/images/emoji/baby_bottle.pngbin818 -> 0 bytes
-rw-r--r--app/assets/images/emoji/baby_chick.pngbin1181 -> 0 bytes
-rw-r--r--app/assets/images/emoji/baby_symbol.pngbin665 -> 0 bytes
-rw-r--r--app/assets/images/emoji/baby_tone1.pngbin1392 -> 0 bytes
-rw-r--r--app/assets/images/emoji/baby_tone2.pngbin1392 -> 0 bytes
-rw-r--r--app/assets/images/emoji/baby_tone3.pngbin1403 -> 0 bytes
-rw-r--r--app/assets/images/emoji/baby_tone4.pngbin1413 -> 0 bytes
-rw-r--r--app/assets/images/emoji/baby_tone5.pngbin1405 -> 0 bytes
-rw-r--r--app/assets/images/emoji/back.pngbin562 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bacon.pngbin2148 -> 0 bytes
-rw-r--r--app/assets/images/emoji/badminton.pngbin1253 -> 0 bytes
-rw-r--r--app/assets/images/emoji/baggage_claim.pngbin490 -> 0 bytes
-rw-r--r--app/assets/images/emoji/balloon.pngbin501 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ballot_box.pngbin1355 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ballot_box_with_check.pngbin639 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bamboo.pngbin1946 -> 0 bytes
-rw-r--r--app/assets/images/emoji/banana.pngbin1157 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bangbang.pngbin390 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bank.pngbin1358 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bar_chart.pngbin408 -> 0 bytes
-rw-r--r--app/assets/images/emoji/barber.pngbin820 -> 0 bytes
-rw-r--r--app/assets/images/emoji/baseball.pngbin1185 -> 0 bytes
-rw-r--r--app/assets/images/emoji/basketball.pngbin1546 -> 0 bytes
-rw-r--r--app/assets/images/emoji/basketball_player.pngbin1491 -> 0 bytes
-rw-r--r--app/assets/images/emoji/basketball_player_tone1.pngbin1492 -> 0 bytes
-rw-r--r--app/assets/images/emoji/basketball_player_tone2.pngbin1493 -> 0 bytes
-rw-r--r--app/assets/images/emoji/basketball_player_tone3.pngbin1492 -> 0 bytes
-rw-r--r--app/assets/images/emoji/basketball_player_tone4.pngbin1491 -> 0 bytes
-rw-r--r--app/assets/images/emoji/basketball_player_tone5.pngbin1474 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bat.pngbin1190 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bath.pngbin1238 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bath_tone1.pngbin1235 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bath_tone2.pngbin1231 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bath_tone3.pngbin1236 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bath_tone4.pngbin1252 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bath_tone5.pngbin1239 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bathtub.pngbin767 -> 0 bytes
-rw-r--r--app/assets/images/emoji/battery.pngbin228 -> 0 bytes
-rw-r--r--app/assets/images/emoji/beach.pngbin942 -> 0 bytes
-rw-r--r--app/assets/images/emoji/beach_umbrella.pngbin1486 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bear.pngbin1023 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bed.pngbin1572 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bee.pngbin1378 -> 0 bytes
-rw-r--r--app/assets/images/emoji/beer.pngbin1338 -> 0 bytes
-rw-r--r--app/assets/images/emoji/beers.pngbin2100 -> 0 bytes
-rw-r--r--app/assets/images/emoji/beetle.pngbin1288 -> 0 bytes
-rw-r--r--app/assets/images/emoji/beginner.pngbin545 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bell.pngbin1496 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bellhop.pngbin891 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bento.pngbin1127 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bicyclist.pngbin1911 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bicyclist_tone1.pngbin1860 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bicyclist_tone2.pngbin1866 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bicyclist_tone3.pngbin1851 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bicyclist_tone4.pngbin1852 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bicyclist_tone5.pngbin1840 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bike.pngbin1505 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bikini.pngbin613 -> 0 bytes
-rw-r--r--app/assets/images/emoji/biohazard.pngbin794 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bird.pngbin1068 -> 0 bytes
-rw-r--r--app/assets/images/emoji/birthday.pngbin2219 -> 0 bytes
-rw-r--r--app/assets/images/emoji/black_circle.pngbin374 -> 0 bytes
-rw-r--r--app/assets/images/emoji/black_heart.pngbin435 -> 0 bytes
-rw-r--r--app/assets/images/emoji/black_joker.pngbin1091 -> 0 bytes
-rw-r--r--app/assets/images/emoji/black_large_square.pngbin110 -> 0 bytes
-rw-r--r--app/assets/images/emoji/black_medium_small_square.pngbin110 -> 0 bytes
-rw-r--r--app/assets/images/emoji/black_medium_square.pngbin108 -> 0 bytes
-rw-r--r--app/assets/images/emoji/black_nib.pngbin620 -> 0 bytes
-rw-r--r--app/assets/images/emoji/black_small_square.pngbin108 -> 0 bytes
-rw-r--r--app/assets/images/emoji/black_square_button.pngbin122 -> 0 bytes
-rw-r--r--app/assets/images/emoji/blossom.pngbin867 -> 0 bytes
-rw-r--r--app/assets/images/emoji/blowfish.pngbin1620 -> 0 bytes
-rw-r--r--app/assets/images/emoji/blue_book.pngbin1347 -> 0 bytes
-rw-r--r--app/assets/images/emoji/blue_car.pngbin1275 -> 0 bytes
-rw-r--r--app/assets/images/emoji/blue_heart.pngbin435 -> 0 bytes
-rw-r--r--app/assets/images/emoji/blush.pngbin812 -> 0 bytes
-rw-r--r--app/assets/images/emoji/boar.pngbin1366 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bomb.pngbin702 -> 0 bytes
-rw-r--r--app/assets/images/emoji/book.pngbin1716 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bookmark.pngbin747 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bookmark_tabs.pngbin1395 -> 0 bytes
-rw-r--r--app/assets/images/emoji/books.pngbin2474 -> 0 bytes
-rw-r--r--app/assets/images/emoji/boom.pngbin1110 -> 0 bytes
-rw-r--r--app/assets/images/emoji/boot.pngbin662 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bouquet.pngbin1662 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bow.pngbin1394 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bow_and_arrow.pngbin1402 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bow_tone1.pngbin1394 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bow_tone2.pngbin1394 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bow_tone3.pngbin1394 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bow_tone4.pngbin1394 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bow_tone5.pngbin1394 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bowling.pngbin1426 -> 0 bytes
-rw-r--r--app/assets/images/emoji/boxing_glove.pngbin1575 -> 0 bytes
-rw-r--r--app/assets/images/emoji/boy.pngbin881 -> 0 bytes
-rw-r--r--app/assets/images/emoji/boy_tone1.pngbin876 -> 0 bytes
-rw-r--r--app/assets/images/emoji/boy_tone2.pngbin876 -> 0 bytes
-rw-r--r--app/assets/images/emoji/boy_tone3.pngbin876 -> 0 bytes
-rw-r--r--app/assets/images/emoji/boy_tone4.pngbin870 -> 0 bytes
-rw-r--r--app/assets/images/emoji/boy_tone5.pngbin873 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bread.pngbin1419 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bride_with_veil.pngbin2452 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bride_with_veil_tone1.pngbin2464 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bride_with_veil_tone2.pngbin2457 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bride_with_veil_tone3.pngbin2463 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bride_with_veil_tone4.pngbin2463 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bride_with_veil_tone5.pngbin2462 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bridge_at_night.pngbin637 -> 0 bytes
-rw-r--r--app/assets/images/emoji/briefcase.pngbin1275 -> 0 bytes
-rw-r--r--app/assets/images/emoji/broken_heart.pngbin556 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bug.pngbin1599 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bulb.pngbin805 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bullettrain_front.pngbin1450 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bullettrain_side.pngbin1538 -> 0 bytes
-rw-r--r--app/assets/images/emoji/burrito.pngbin2938 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bus.pngbin1086 -> 0 bytes
-rw-r--r--app/assets/images/emoji/busstop.pngbin626 -> 0 bytes
-rw-r--r--app/assets/images/emoji/bust_in_silhouette.pngbin426 -> 0 bytes
-rw-r--r--app/assets/images/emoji/busts_in_silhouette.pngbin526 -> 0 bytes
-rw-r--r--app/assets/images/emoji/butterfly.pngbin1981 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cactus.pngbin628 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cake.pngbin2266 -> 0 bytes
-rw-r--r--app/assets/images/emoji/calendar.pngbin2077 -> 0 bytes
-rw-r--r--app/assets/images/emoji/calendar_spiral.pngbin1491 -> 0 bytes
-rw-r--r--app/assets/images/emoji/call_me.pngbin894 -> 0 bytes
-rw-r--r--app/assets/images/emoji/call_me_tone1.pngbin893 -> 0 bytes
-rw-r--r--app/assets/images/emoji/call_me_tone2.pngbin891 -> 0 bytes
-rw-r--r--app/assets/images/emoji/call_me_tone3.pngbin891 -> 0 bytes
-rw-r--r--app/assets/images/emoji/call_me_tone4.pngbin891 -> 0 bytes
-rw-r--r--app/assets/images/emoji/call_me_tone5.pngbin893 -> 0 bytes
-rw-r--r--app/assets/images/emoji/calling.pngbin815 -> 0 bytes
-rw-r--r--app/assets/images/emoji/camel.pngbin1190 -> 0 bytes
-rw-r--r--app/assets/images/emoji/camera.pngbin1783 -> 0 bytes
-rw-r--r--app/assets/images/emoji/camera_with_flash.pngbin2097 -> 0 bytes
-rw-r--r--app/assets/images/emoji/camping.pngbin1513 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cancer.pngbin729 -> 0 bytes
-rw-r--r--app/assets/images/emoji/candle.pngbin1250 -> 0 bytes
-rw-r--r--app/assets/images/emoji/candy.pngbin1054 -> 0 bytes
-rw-r--r--app/assets/images/emoji/canoe.pngbin1244 -> 0 bytes
-rw-r--r--app/assets/images/emoji/capital_abcd.pngbin805 -> 0 bytes
-rw-r--r--app/assets/images/emoji/capricorn.pngbin688 -> 0 bytes
-rw-r--r--app/assets/images/emoji/card_box.pngbin1523 -> 0 bytes
-rw-r--r--app/assets/images/emoji/card_index.pngbin1929 -> 0 bytes
-rw-r--r--app/assets/images/emoji/carousel_horse.pngbin1739 -> 0 bytes
-rw-r--r--app/assets/images/emoji/carrot.pngbin1236 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cartwheel.pngbin1233 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cartwheel_tone1.pngbin1234 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cartwheel_tone2.pngbin1235 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cartwheel_tone3.pngbin1229 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cartwheel_tone4.pngbin1227 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cartwheel_tone5.pngbin1214 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cat.pngbin1354 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cat2.pngbin1781 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cd.pngbin908 -> 0 bytes
-rw-r--r--app/assets/images/emoji/chains.pngbin708 -> 0 bytes
-rw-r--r--app/assets/images/emoji/champagne.pngbin1205 -> 0 bytes
-rw-r--r--app/assets/images/emoji/champagne_glass.pngbin1984 -> 0 bytes
-rw-r--r--app/assets/images/emoji/chart.pngbin724 -> 0 bytes
-rw-r--r--app/assets/images/emoji/chart_with_downwards_trend.pngbin709 -> 0 bytes
-rw-r--r--app/assets/images/emoji/chart_with_upwards_trend.pngbin688 -> 0 bytes
-rw-r--r--app/assets/images/emoji/checkered_flag.pngbin787 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cheese.pngbin1697 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cherries.pngbin1211 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cherry_blossom.pngbin1129 -> 0 bytes
-rw-r--r--app/assets/images/emoji/chestnut.pngbin1337 -> 0 bytes
-rw-r--r--app/assets/images/emoji/chicken.pngbin1267 -> 0 bytes
-rw-r--r--app/assets/images/emoji/children_crossing.pngbin778 -> 0 bytes
-rw-r--r--app/assets/images/emoji/chipmunk.pngbin1454 -> 0 bytes
-rw-r--r--app/assets/images/emoji/chocolate_bar.pngbin771 -> 0 bytes
-rw-r--r--app/assets/images/emoji/christmas_tree.pngbin1542 -> 0 bytes
-rw-r--r--app/assets/images/emoji/church.pngbin1298 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cinema.pngbin585 -> 0 bytes
-rw-r--r--app/assets/images/emoji/circus_tent.pngbin1369 -> 0 bytes
-rw-r--r--app/assets/images/emoji/city_dusk.pngbin431 -> 0 bytes
-rw-r--r--app/assets/images/emoji/city_sunset.pngbin997 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cityscape.pngbin599 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cl.pngbin393 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clap.pngbin1456 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clap_tone1.pngbin1458 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clap_tone2.pngbin1458 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clap_tone3.pngbin1458 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clap_tone4.pngbin1458 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clap_tone5.pngbin1444 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clapper.pngbin1535 -> 0 bytes
-rw-r--r--app/assets/images/emoji/classical_building.pngbin1006 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clipboard.pngbin1345 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock.pngbin592 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock1.pngbin586 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock10.pngbin593 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock1030.pngbin530 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock11.pngbin590 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock1130.pngbin583 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock12.pngbin480 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock1230.pngbin579 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock130.pngbin526 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock2.pngbin591 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock230.pngbin576 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock3.pngbin482 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock330.pngbin568 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock4.pngbin592 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock430.pngbin531 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock5.pngbin585 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock530.pngbin552 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock6.pngbin466 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock630.pngbin536 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock7.pngbin581 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock730.pngbin531 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock8.pngbin590 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock830.pngbin570 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock9.pngbin484 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clock930.pngbin576 -> 0 bytes
-rw-r--r--app/assets/images/emoji/closed_book.pngbin1359 -> 0 bytes
-rw-r--r--app/assets/images/emoji/closed_lock_with_key.pngbin1250 -> 0 bytes
-rw-r--r--app/assets/images/emoji/closed_umbrella.pngbin1002 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cloud.pngbin626 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cloud_lightning.pngbin767 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cloud_rain.pngbin876 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cloud_snow.pngbin823 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cloud_tornado.pngbin1519 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clown.pngbin1818 -> 0 bytes
-rw-r--r--app/assets/images/emoji/clubs.pngbin458 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cocktail.pngbin1027 -> 0 bytes
-rw-r--r--app/assets/images/emoji/coffee.pngbin1679 -> 0 bytes
-rw-r--r--app/assets/images/emoji/coffin.pngbin2195 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cold_sweat.pngbin971 -> 0 bytes
-rw-r--r--app/assets/images/emoji/comet.pngbin1819 -> 0 bytes
-rw-r--r--app/assets/images/emoji/compression.pngbin1612 -> 0 bytes
-rw-r--r--app/assets/images/emoji/computer.pngbin369 -> 0 bytes
-rw-r--r--app/assets/images/emoji/confetti_ball.pngbin1703 -> 0 bytes
-rw-r--r--app/assets/images/emoji/confounded.pngbin844 -> 0 bytes
-rw-r--r--app/assets/images/emoji/confused.pngbin647 -> 0 bytes
-rw-r--r--app/assets/images/emoji/congratulations.pngbin729 -> 0 bytes
-rw-r--r--app/assets/images/emoji/construction.pngbin1083 -> 0 bytes
-rw-r--r--app/assets/images/emoji/construction_site.pngbin668 -> 0 bytes
-rw-r--r--app/assets/images/emoji/construction_worker.pngbin1126 -> 0 bytes
-rw-r--r--app/assets/images/emoji/construction_worker_tone1.pngbin1102 -> 0 bytes
-rw-r--r--app/assets/images/emoji/construction_worker_tone2.pngbin1102 -> 0 bytes
-rw-r--r--app/assets/images/emoji/construction_worker_tone3.pngbin1102 -> 0 bytes
-rw-r--r--app/assets/images/emoji/construction_worker_tone4.pngbin1095 -> 0 bytes
-rw-r--r--app/assets/images/emoji/construction_worker_tone5.pngbin1119 -> 0 bytes
-rw-r--r--app/assets/images/emoji/control_knobs.pngbin1104 -> 0 bytes
-rw-r--r--app/assets/images/emoji/convenience_store.pngbin528 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cookie.pngbin1351 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cooking.pngbin764 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cool.pngbin396 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cop.pngbin1440 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cop_tone1.pngbin1421 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cop_tone2.pngbin1424 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cop_tone3.pngbin1419 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cop_tone4.pngbin1417 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cop_tone5.pngbin1433 -> 0 bytes
-rw-r--r--app/assets/images/emoji/copyright.pngbin530 -> 0 bytes
-rw-r--r--app/assets/images/emoji/corn.pngbin1547 -> 0 bytes
-rw-r--r--app/assets/images/emoji/couch.pngbin1362 -> 0 bytes
-rw-r--r--app/assets/images/emoji/couple.pngbin1537 -> 0 bytes
-rw-r--r--app/assets/images/emoji/couple_mm.pngbin1091 -> 0 bytes
-rw-r--r--app/assets/images/emoji/couple_with_heart.pngbin1285 -> 0 bytes
-rw-r--r--app/assets/images/emoji/couple_ww.pngbin1034 -> 0 bytes
-rw-r--r--app/assets/images/emoji/couplekiss.pngbin1380 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cow.pngbin1640 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cow2.pngbin1810 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cowboy.pngbin1353 -> 0 bytes
-rw-r--r--app/assets/images/emoji/crab.pngbin1475 -> 0 bytes
-rw-r--r--app/assets/images/emoji/crayon.pngbin633 -> 0 bytes
-rw-r--r--app/assets/images/emoji/credit_card.pngbin1012 -> 0 bytes
-rw-r--r--app/assets/images/emoji/crescent_moon.pngbin446 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cricket.pngbin1060 -> 0 bytes
-rw-r--r--app/assets/images/emoji/crocodile.pngbin2408 -> 0 bytes
-rw-r--r--app/assets/images/emoji/croissant.pngbin1313 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cross.pngbin408 -> 0 bytes
-rw-r--r--app/assets/images/emoji/crossed_flags.pngbin1239 -> 0 bytes
-rw-r--r--app/assets/images/emoji/crossed_swords.pngbin1591 -> 0 bytes
-rw-r--r--app/assets/images/emoji/crown.pngbin1534 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cruise_ship.pngbin2272 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cry.pngbin1123 -> 0 bytes
-rw-r--r--app/assets/images/emoji/crying_cat_face.pngbin1875 -> 0 bytes
-rw-r--r--app/assets/images/emoji/crystal_ball.pngbin1913 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cucumber.pngbin1357 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cupid.pngbin846 -> 0 bytes
-rw-r--r--app/assets/images/emoji/curly_loop.pngbin545 -> 0 bytes
-rw-r--r--app/assets/images/emoji/currency_exchange.pngbin576 -> 0 bytes
-rw-r--r--app/assets/images/emoji/curry.pngbin1754 -> 0 bytes
-rw-r--r--app/assets/images/emoji/custard.pngbin1273 -> 0 bytes
-rw-r--r--app/assets/images/emoji/customs.pngbin648 -> 0 bytes
-rw-r--r--app/assets/images/emoji/cyclone.pngbin797 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dagger.pngbin916 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dancer.pngbin1405 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dancer_tone1.pngbin1420 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dancer_tone2.pngbin1423 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dancer_tone3.pngbin1429 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dancer_tone4.pngbin1428 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dancer_tone5.pngbin1418 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dancers.pngbin1872 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dango.pngbin802 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dark_sunglasses.pngbin829 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dart.pngbin1374 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dash.pngbin840 -> 0 bytes
-rw-r--r--app/assets/images/emoji/date.pngbin788 -> 0 bytes
-rw-r--r--app/assets/images/emoji/deciduous_tree.pngbin1267 -> 0 bytes
-rw-r--r--app/assets/images/emoji/deer.pngbin1606 -> 0 bytes
-rw-r--r--app/assets/images/emoji/department_store.pngbin673 -> 0 bytes
-rw-r--r--app/assets/images/emoji/desert.pngbin1443 -> 0 bytes
-rw-r--r--app/assets/images/emoji/desktop.pngbin311 -> 0 bytes
-rw-r--r--app/assets/images/emoji/diamond_shape_with_a_dot_inside.pngbin693 -> 0 bytes
-rw-r--r--app/assets/images/emoji/diamonds.pngbin247 -> 0 bytes
-rw-r--r--app/assets/images/emoji/disappointed.pngbin757 -> 0 bytes
-rw-r--r--app/assets/images/emoji/disappointed_relieved.pngbin835 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dividers.pngbin810 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dizzy.pngbin795 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dizzy_face.pngbin710 -> 0 bytes
-rw-r--r--app/assets/images/emoji/do_not_litter.pngbin1010 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dog.pngbin1674 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dog2.pngbin2085 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dollar.pngbin405 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dolls.pngbin2249 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dolphin.pngbin1697 -> 0 bytes
-rw-r--r--app/assets/images/emoji/door.pngbin1105 -> 0 bytes
-rw-r--r--app/assets/images/emoji/doughnut.pngbin1322 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dove.pngbin967 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dragon.pngbin1574 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dragon_face.pngbin1769 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dress.pngbin1001 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dromedary_camel.pngbin1515 -> 0 bytes
-rw-r--r--app/assets/images/emoji/drooling_face.pngbin1049 -> 0 bytes
-rw-r--r--app/assets/images/emoji/droplet.pngbin411 -> 0 bytes
-rw-r--r--app/assets/images/emoji/drum.pngbin1870 -> 0 bytes
-rw-r--r--app/assets/images/emoji/duck.pngbin1729 -> 0 bytes
-rw-r--r--app/assets/images/emoji/dvd.pngbin933 -> 0 bytes
-rw-r--r--app/assets/images/emoji/e-mail.pngbin1196 -> 0 bytes
-rw-r--r--app/assets/images/emoji/eagle.pngbin2222 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ear.pngbin860 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ear_of_rice.pngbin1422 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ear_tone1.pngbin860 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ear_tone2.pngbin860 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ear_tone3.pngbin860 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ear_tone4.pngbin860 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ear_tone5.pngbin860 -> 0 bytes
-rw-r--r--app/assets/images/emoji/earth_africa.pngbin978 -> 0 bytes
-rw-r--r--app/assets/images/emoji/earth_americas.pngbin1031 -> 0 bytes
-rw-r--r--app/assets/images/emoji/earth_asia.pngbin966 -> 0 bytes
-rw-r--r--app/assets/images/emoji/egg.pngbin710 -> 0 bytes
-rw-r--r--app/assets/images/emoji/eggplant.pngbin773 -> 0 bytes
-rw-r--r--app/assets/images/emoji/eight.pngbin608 -> 0 bytes
-rw-r--r--app/assets/images/emoji/eight_pointed_black_star.pngbin493 -> 0 bytes
-rw-r--r--app/assets/images/emoji/eight_spoked_asterisk.pngbin493 -> 0 bytes
-rw-r--r--app/assets/images/emoji/eject.pngbin548 -> 0 bytes
-rw-r--r--app/assets/images/emoji/electric_plug.pngbin548 -> 0 bytes
-rw-r--r--app/assets/images/emoji/elephant.pngbin1293 -> 0 bytes
-rw-r--r--app/assets/images/emoji/end.pngbin393 -> 0 bytes
-rw-r--r--app/assets/images/emoji/envelope.pngbin916 -> 0 bytes
-rw-r--r--app/assets/images/emoji/envelope_with_arrow.pngbin1062 -> 0 bytes
-rw-r--r--app/assets/images/emoji/euro.pngbin460 -> 0 bytes
-rw-r--r--app/assets/images/emoji/european_castle.pngbin965 -> 0 bytes
-rw-r--r--app/assets/images/emoji/european_post_office.pngbin551 -> 0 bytes
-rw-r--r--app/assets/images/emoji/evergreen_tree.pngbin719 -> 0 bytes
-rw-r--r--app/assets/images/emoji/exclamation.pngbin354 -> 0 bytes
-rw-r--r--app/assets/images/emoji/expressionless.pngbin438 -> 0 bytes
-rw-r--r--app/assets/images/emoji/eye.pngbin664 -> 0 bytes
-rw-r--r--app/assets/images/emoji/eye_in_speech_bubble.pngbin698 -> 0 bytes
-rw-r--r--app/assets/images/emoji/eyeglasses.pngbin577 -> 0 bytes
-rw-r--r--app/assets/images/emoji/eyes.pngbin791 -> 0 bytes
-rw-r--r--app/assets/images/emoji/face_palm.pngbin1523 -> 0 bytes
-rw-r--r--app/assets/images/emoji/face_palm_tone1.pngbin1563 -> 0 bytes
-rw-r--r--app/assets/images/emoji/face_palm_tone2.pngbin1547 -> 0 bytes
-rw-r--r--app/assets/images/emoji/face_palm_tone3.pngbin1550 -> 0 bytes
-rw-r--r--app/assets/images/emoji/face_palm_tone4.pngbin1553 -> 0 bytes
-rw-r--r--app/assets/images/emoji/face_palm_tone5.pngbin1532 -> 0 bytes
-rw-r--r--app/assets/images/emoji/factory.pngbin936 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fallen_leaf.pngbin951 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family.pngbin1433 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_mmb.pngbin1206 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_mmbb.pngbin1349 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_mmg.pngbin1361 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_mmgb.pngbin1626 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_mmgg.pngbin1448 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_mwbb.pngbin1638 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_mwg.pngbin1554 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_mwgb.pngbin1837 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_mwgg.pngbin1738 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_wwb.pngbin1155 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_wwbb.pngbin1289 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_wwg.pngbin1286 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_wwgb.pngbin1550 -> 0 bytes
-rw-r--r--app/assets/images/emoji/family_wwgg.pngbin1374 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fast_forward.pngbin523 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fax.pngbin1188 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fearful.pngbin1002 -> 0 bytes
-rw-r--r--app/assets/images/emoji/feet.pngbin603 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fencer.pngbin1342 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ferris_wheel.pngbin2185 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ferry.pngbin528 -> 0 bytes
-rw-r--r--app/assets/images/emoji/field_hockey.pngbin947 -> 0 bytes
-rw-r--r--app/assets/images/emoji/file_cabinet.pngbin1420 -> 0 bytes
-rw-r--r--app/assets/images/emoji/file_folder.pngbin1445 -> 0 bytes
-rw-r--r--app/assets/images/emoji/film_frames.pngbin560 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fingers_crossed.pngbin1050 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fingers_crossed_tone1.pngbin1047 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fingers_crossed_tone2.pngbin1050 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fingers_crossed_tone3.pngbin1050 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fingers_crossed_tone4.pngbin1046 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fingers_crossed_tone5.pngbin1050 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fire.pngbin1020 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fire_engine.pngbin1656 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fireworks.pngbin1364 -> 0 bytes
-rw-r--r--app/assets/images/emoji/first_place.pngbin1419 -> 0 bytes
-rw-r--r--app/assets/images/emoji/first_quarter_moon.pngbin1152 -> 0 bytes
-rw-r--r--app/assets/images/emoji/first_quarter_moon_with_face.pngbin1068 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fish.pngbin1080 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fish_cake.pngbin1245 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fishing_pole_and_fish.pngbin1442 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fist.pngbin1014 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fist_tone1.pngbin1014 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fist_tone2.pngbin1014 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fist_tone3.pngbin1014 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fist_tone4.pngbin1014 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fist_tone5.pngbin1014 -> 0 bytes
-rw-r--r--app/assets/images/emoji/five.pngbin577 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ac.pngbin1934 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ad.pngbin1285 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ae.pngbin544 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_af.pngbin942 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ag.pngbin913 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ai.pngbin1056 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_al.pngbin905 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_am.pngbin514 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ao.pngbin997 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_aq.pngbin657 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ar.pngbin975 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_as.pngbin1489 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_at.pngbin430 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_au.pngbin962 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_aw.pngbin709 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ax.pngbin496 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_az.pngbin709 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ba.pngbin848 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bb.pngbin789 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bd.pngbin490 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_be.pngbin444 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bf.pngbin717 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bg.pngbin513 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bh.pngbin593 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bi.pngbin795 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bj.pngbin554 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bl.pngbin1691 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_black.pngbin702 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bm.pngbin1374 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bn.pngbin1355 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bo.pngbin1132 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bq.pngbin1144 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_br.pngbin819 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bs.pngbin448 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bt.pngbin1213 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bv.pngbin495 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bw.pngbin391 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_by.pngbin1120 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_bz.pngbin1595 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ca.pngbin755 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cc.pngbin851 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cd.pngbin707 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cf.pngbin673 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cg.pngbin586 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ch.pngbin390 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ci.pngbin440 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ck.pngbin1083 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cl.pngbin748 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cm.pngbin627 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cn.pngbin676 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_co.pngbin524 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cp.pngbin443 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cr.pngbin419 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cu.pngbin586 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cv.pngbin642 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cw.pngbin665 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cx.pngbin1142 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cy.pngbin830 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_cz.pngbin600 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_de.pngbin502 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_dg.pngbin1911 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_dj.pngbin753 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_dk.pngbin450 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_dm.pngbin1075 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_do.pngbin1135 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_dz.pngbin734 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ea.pngbin1337 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ec.pngbin1431 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ee.pngbin512 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_eg.pngbin818 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_eh.pngbin742 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_er.pngbin1218 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_es.pngbin1337 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_et.pngbin947 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_eu.pngbin760 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_fi.pngbin487 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_fj.pngbin1381 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_fk.pngbin1558 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_fm.pngbin554 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_fo.pngbin495 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_fr.pngbin443 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ga.pngbin512 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gb.pngbin919 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gd.pngbin1017 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ge.pngbin583 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gf.pngbin865 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gg.pngbin521 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gh.pngbin723 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gi.pngbin1053 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gl.pngbin700 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gm.pngbin501 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gn.pngbin434 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gp.pngbin1587 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gq.pngbin1132 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gr.pngbin549 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gs.pngbin2115 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gt.pngbin1087 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gu.pngbin1045 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gw.pngbin705 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_gy.pngbin690 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_hk.pngbin759 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_hm.pngbin1036 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_hn.pngbin513 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_hr.pngbin1411 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ht.pngbin1205 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_hu.pngbin513 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ic.pngbin1330 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_id.pngbin498 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ie.pngbin478 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_il.pngbin658 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_im.pngbin976 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_in.pngbin773 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_io.pngbin1911 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_iq.pngbin811 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ir.pngbin1036 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_is.pngbin491 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_it.pngbin472 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_je.pngbin956 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_jm.pngbin837 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_jo.pngbin740 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_jp.pngbin455 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ke.pngbin1160 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_kg.pngbin1080 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_kh.pngbin872 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ki.pngbin1369 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_km.pngbin783 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_kn.pngbin1316 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_kp.pngbin696 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_kr.pngbin967 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_kw.pngbin560 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ky.pngbin1671 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_kz.pngbin1136 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_la.pngbin479 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_lb.pngbin740 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_lc.pngbin561 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_li.pngbin946 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_lk.pngbin974 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_lr.pngbin772 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ls.pngbin775 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_lt.pngbin510 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_lu.pngbin512 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_lv.pngbin388 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ly.pngbin685 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ma.pngbin626 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mc.pngbin528 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_md.pngbin1170 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_me.pngbin1074 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mf.pngbin443 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mg.pngbin556 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mh.pngbin1138 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mk.pngbin1023 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ml.pngbin440 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mm.pngbin937 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mn.pngbin698 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mo.pngbin792 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mp.pngbin1797 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mq.pngbin780 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mr.pngbin657 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ms.pngbin1477 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mt.pngbin799 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mu.pngbin544 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mv.pngbin598 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mw.pngbin825 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mx.pngbin951 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_my.pngbin775 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_mz.pngbin1159 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_na.pngbin1249 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_nc.pngbin1148 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ne.pngbin593 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_nf.pngbin877 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ng.pngbin438 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ni.pngbin823 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_nl.pngbin499 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_no.pngbin484 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_np.pngbin802 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_nr.pngbin529 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_nu.pngbin1128 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_nz.pngbin1099 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_om.pngbin754 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_pa.pngbin830 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_pe.pngbin439 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_pf.pngbin1091 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_pg.pngbin1076 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ph.pngbin867 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_pk.pngbin753 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_pl.pngbin522 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_pm.pngbin2314 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_pn.pngbin1895 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_pr.pngbin605 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ps.pngbin574 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_pt.pngbin1055 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_pw.pngbin475 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_py.pngbin1085 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_qa.pngbin657 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_re.pngbin837 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ro.pngbin441 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_rs.pngbin1237 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ru.pngbin496 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_rw.pngbin940 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sa.pngbin781 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sb.pngbin1102 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sc.pngbin1073 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sd.pngbin578 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_se.pngbin455 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sg.pngbin730 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sh.pngbin1369 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_si.pngbin1030 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sj.pngbin495 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sk.pngbin780 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sl.pngbin510 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sm.pngbin2000 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sn.pngbin621 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_so.pngbin609 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sr.pngbin650 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ss.pngbin722 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_st.pngbin562 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sv.pngbin1125 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sx.pngbin1195 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sy.pngbin696 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_sz.pngbin1102 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ta.pngbin1907 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tc.pngbin1538 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_td.pngbin443 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tf.pngbin857 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tg.pngbin790 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_th.pngbin421 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tj.pngbin906 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tk.pngbin835 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tl.pngbin849 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tm.pngbin1178 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tn.pngbin625 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_to.pngbin553 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tr.pngbin576 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tt.pngbin604 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tv.pngbin1120 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tw.pngbin761 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_tz.pngbin1061 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ua.pngbin528 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ug.pngbin887 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_um.pngbin776 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_us.pngbin776 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_uy.pngbin966 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_uz.pngbin750 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_va.pngbin1331 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_vc.pngbin897 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ve.pngbin748 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_vg.pngbin1789 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_vi.pngbin1378 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_vn.pngbin583 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_vu.pngbin844 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_wf.pngbin443 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_white.pngbin699 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ws.pngbin634 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_xk.pngbin722 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_ye.pngbin507 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_yt.pngbin1623 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_za.pngbin676 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_zm.pngbin881 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flag_zw.pngbin993 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flags.pngbin1722 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flashlight.pngbin964 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fleur-de-lis.pngbin632 -> 0 bytes
-rw-r--r--app/assets/images/emoji/floppy_disk.pngbin258 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flower_playing_cards.pngbin449 -> 0 bytes
-rw-r--r--app/assets/images/emoji/flushed.pngbin1127 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fog.pngbin713 -> 0 bytes
-rw-r--r--app/assets/images/emoji/foggy.pngbin1069 -> 0 bytes
-rw-r--r--app/assets/images/emoji/football.pngbin956 -> 0 bytes
-rw-r--r--app/assets/images/emoji/footprints.pngbin621 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fork_and_knife.pngbin668 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fork_knife_plate.pngbin976 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fountain.pngbin1768 -> 0 bytes
-rw-r--r--app/assets/images/emoji/four.pngbin497 -> 0 bytes
-rw-r--r--app/assets/images/emoji/four_leaf_clover.pngbin1156 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fox.pngbin1556 -> 0 bytes
-rw-r--r--app/assets/images/emoji/frame_photo.pngbin514 -> 0 bytes
-rw-r--r--app/assets/images/emoji/free.pngbin370 -> 0 bytes
-rw-r--r--app/assets/images/emoji/french_bread.pngbin1551 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fried_shrimp.pngbin1241 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fries.pngbin1873 -> 0 bytes
-rw-r--r--app/assets/images/emoji/frog.pngbin897 -> 0 bytes
-rw-r--r--app/assets/images/emoji/frowning.pngbin633 -> 0 bytes
-rw-r--r--app/assets/images/emoji/frowning2.pngbin589 -> 0 bytes
-rw-r--r--app/assets/images/emoji/fuelpump.pngbin864 -> 0 bytes
-rw-r--r--app/assets/images/emoji/full_moon.pngbin841 -> 0 bytes
-rw-r--r--app/assets/images/emoji/full_moon_with_face.pngbin1186 -> 0 bytes
-rw-r--r--app/assets/images/emoji/game_die.pngbin1136 -> 0 bytes
-rw-r--r--app/assets/images/emoji/gay_pride_flag.pngbin2340 -> 0 bytes
-rw-r--r--app/assets/images/emoji/gear.pngbin747 -> 0 bytes
-rw-r--r--app/assets/images/emoji/gem.pngbin715 -> 0 bytes
-rw-r--r--app/assets/images/emoji/gemini.pngbin547 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ghost.pngbin1465 -> 0 bytes
-rw-r--r--app/assets/images/emoji/gift.pngbin1966 -> 0 bytes
-rw-r--r--app/assets/images/emoji/gift_heart.pngbin1141 -> 0 bytes
-rw-r--r--app/assets/images/emoji/girl.pngbin1261 -> 0 bytes
-rw-r--r--app/assets/images/emoji/girl_tone1.pngbin1259 -> 0 bytes
-rw-r--r--app/assets/images/emoji/girl_tone2.pngbin1255 -> 0 bytes
-rw-r--r--app/assets/images/emoji/girl_tone3.pngbin1255 -> 0 bytes
-rw-r--r--app/assets/images/emoji/girl_tone4.pngbin1241 -> 0 bytes
-rw-r--r--app/assets/images/emoji/girl_tone5.pngbin1245 -> 0 bytes
-rw-r--r--app/assets/images/emoji/globe_with_meridians.pngbin796 -> 0 bytes
-rw-r--r--app/assets/images/emoji/goal.pngbin1242 -> 0 bytes
-rw-r--r--app/assets/images/emoji/goat.pngbin981 -> 0 bytes
-rw-r--r--app/assets/images/emoji/golf.pngbin823 -> 0 bytes
-rw-r--r--app/assets/images/emoji/golfer.pngbin1189 -> 0 bytes
-rw-r--r--app/assets/images/emoji/gorilla.pngbin1090 -> 0 bytes
-rw-r--r--app/assets/images/emoji/grapes.pngbin1552 -> 0 bytes
-rw-r--r--app/assets/images/emoji/green_apple.pngbin656 -> 0 bytes
-rw-r--r--app/assets/images/emoji/green_book.pngbin1366 -> 0 bytes
-rw-r--r--app/assets/images/emoji/green_heart.pngbin435 -> 0 bytes
-rw-r--r--app/assets/images/emoji/grey_exclamation.pngbin354 -> 0 bytes
-rw-r--r--app/assets/images/emoji/grey_question.pngbin449 -> 0 bytes
-rw-r--r--app/assets/images/emoji/grimacing.pngbin694 -> 0 bytes
-rw-r--r--app/assets/images/emoji/grin.pngbin767 -> 0 bytes
-rw-r--r--app/assets/images/emoji/grinning.pngbin810 -> 0 bytes
-rw-r--r--app/assets/images/emoji/guardsman.pngbin1140 -> 0 bytes
-rw-r--r--app/assets/images/emoji/guardsman_tone1.pngbin1122 -> 0 bytes
-rw-r--r--app/assets/images/emoji/guardsman_tone2.pngbin1160 -> 0 bytes
-rw-r--r--app/assets/images/emoji/guardsman_tone3.pngbin1160 -> 0 bytes
-rw-r--r--app/assets/images/emoji/guardsman_tone4.pngbin1157 -> 0 bytes
-rw-r--r--app/assets/images/emoji/guardsman_tone5.pngbin1165 -> 0 bytes
-rw-r--r--app/assets/images/emoji/guitar.pngbin1056 -> 0 bytes
-rw-r--r--app/assets/images/emoji/gun.pngbin1859 -> 0 bytes
-rw-r--r--app/assets/images/emoji/haircut.pngbin1935 -> 0 bytes
-rw-r--r--app/assets/images/emoji/haircut_tone1.pngbin1945 -> 0 bytes
-rw-r--r--app/assets/images/emoji/haircut_tone2.pngbin1935 -> 0 bytes
-rw-r--r--app/assets/images/emoji/haircut_tone3.pngbin1923 -> 0 bytes
-rw-r--r--app/assets/images/emoji/haircut_tone4.pngbin1904 -> 0 bytes
-rw-r--r--app/assets/images/emoji/haircut_tone5.pngbin1920 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hamburger.pngbin1973 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hammer.pngbin834 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hammer_pick.pngbin1068 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hamster.pngbin1279 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hand_splayed.pngbin1081 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hand_splayed_tone1.pngbin1081 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hand_splayed_tone2.pngbin1081 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hand_splayed_tone3.pngbin1081 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hand_splayed_tone4.pngbin1081 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hand_splayed_tone5.pngbin1081 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handbag.pngbin1285 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handball.pngbin1634 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handball_tone1.pngbin1645 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handball_tone2.pngbin1628 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handball_tone3.pngbin1639 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handball_tone4.pngbin1634 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handball_tone5.pngbin1606 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handshake.pngbin1366 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handshake_tone1.pngbin1381 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handshake_tone2.pngbin1381 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handshake_tone3.pngbin1381 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handshake_tone4.pngbin1381 -> 0 bytes
-rw-r--r--app/assets/images/emoji/handshake_tone5.pngbin1381 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hash.pngbin604 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hatched_chick.pngbin1174 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hatching_chick.pngbin1598 -> 0 bytes
-rw-r--r--app/assets/images/emoji/head_bandage.pngbin1199 -> 0 bytes
-rw-r--r--app/assets/images/emoji/headphones.pngbin1202 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hear_no_evil.pngbin1210 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heart.pngbin435 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heart_decoration.pngbin557 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heart_exclamation.pngbin471 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heart_eyes.pngbin1069 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heart_eyes_cat.pngbin1512 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heartbeat.pngbin699 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heartpulse.pngbin675 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hearts.pngbin449 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heavy_check_mark.pngbin438 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heavy_division_sign.pngbin204 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heavy_dollar_sign.pngbin429 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heavy_minus_sign.pngbin108 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heavy_multiplication_x.pngbin298 -> 0 bytes
-rw-r--r--app/assets/images/emoji/heavy_plus_sign.pngbin115 -> 0 bytes
-rw-r--r--app/assets/images/emoji/helicopter.pngbin1098 -> 0 bytes
-rw-r--r--app/assets/images/emoji/helmet_with_cross.pngbin1014 -> 0 bytes
-rw-r--r--app/assets/images/emoji/herb.pngbin886 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hibiscus.pngbin1815 -> 0 bytes
-rw-r--r--app/assets/images/emoji/high_brightness.pngbin474 -> 0 bytes
-rw-r--r--app/assets/images/emoji/high_heel.pngbin1008 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hockey.pngbin1010 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hole.pngbin1390 -> 0 bytes
-rw-r--r--app/assets/images/emoji/homes.pngbin981 -> 0 bytes
-rw-r--r--app/assets/images/emoji/honey_pot.pngbin1217 -> 0 bytes
-rw-r--r--app/assets/images/emoji/horse.pngbin1694 -> 0 bytes
-rw-r--r--app/assets/images/emoji/horse_racing.pngbin2096 -> 0 bytes
-rw-r--r--app/assets/images/emoji/horse_racing_tone1.pngbin2099 -> 0 bytes
-rw-r--r--app/assets/images/emoji/horse_racing_tone2.pngbin2103 -> 0 bytes
-rw-r--r--app/assets/images/emoji/horse_racing_tone3.pngbin2090 -> 0 bytes
-rw-r--r--app/assets/images/emoji/horse_racing_tone4.pngbin2090 -> 0 bytes
-rw-r--r--app/assets/images/emoji/horse_racing_tone5.pngbin2085 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hospital.pngbin530 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hot_pepper.pngbin677 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hotdog.pngbin1770 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hotel.pngbin1322 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hotsprings.pngbin733 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hourglass.pngbin800 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hourglass_flowing_sand.pngbin847 -> 0 bytes
-rw-r--r--app/assets/images/emoji/house.pngbin863 -> 0 bytes
-rw-r--r--app/assets/images/emoji/house_abandoned.pngbin1606 -> 0 bytes
-rw-r--r--app/assets/images/emoji/house_with_garden.pngbin1613 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hugging.pngbin1425 -> 0 bytes
-rw-r--r--app/assets/images/emoji/hushed.pngbin634 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ice_cream.pngbin1779 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ice_skate.pngbin1574 -> 0 bytes
-rw-r--r--app/assets/images/emoji/icecream.pngbin1496 -> 0 bytes
-rw-r--r--app/assets/images/emoji/id.pngbin348 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ideograph_advantage.pngbin716 -> 0 bytes
-rw-r--r--app/assets/images/emoji/imp.pngbin1988 -> 0 bytes
-rw-r--r--app/assets/images/emoji/inbox_tray.pngbin1029 -> 0 bytes
-rw-r--r--app/assets/images/emoji/incoming_envelope.pngbin1129 -> 0 bytes
-rw-r--r--app/assets/images/emoji/information_desk_person.pngbin1580 -> 0 bytes
-rw-r--r--app/assets/images/emoji/information_desk_person_tone1.pngbin1597 -> 0 bytes
-rw-r--r--app/assets/images/emoji/information_desk_person_tone2.pngbin1590 -> 0 bytes
-rw-r--r--app/assets/images/emoji/information_desk_person_tone3.pngbin1580 -> 0 bytes
-rw-r--r--app/assets/images/emoji/information_desk_person_tone4.pngbin1572 -> 0 bytes
-rw-r--r--app/assets/images/emoji/information_desk_person_tone5.pngbin1588 -> 0 bytes
-rw-r--r--app/assets/images/emoji/information_source.pngbin506 -> 0 bytes
-rw-r--r--app/assets/images/emoji/innocent.pngbin935 -> 0 bytes
-rw-r--r--app/assets/images/emoji/interrobang.pngbin601 -> 0 bytes
-rw-r--r--app/assets/images/emoji/iphone.pngbin695 -> 0 bytes
-rw-r--r--app/assets/images/emoji/island.pngbin1273 -> 0 bytes
-rw-r--r--app/assets/images/emoji/izakaya_lantern.pngbin1227 -> 0 bytes
-rw-r--r--app/assets/images/emoji/jack_o_lantern.pngbin2289 -> 0 bytes
-rw-r--r--app/assets/images/emoji/japan.pngbin539 -> 0 bytes
-rw-r--r--app/assets/images/emoji/japanese_castle.pngbin1404 -> 0 bytes
-rw-r--r--app/assets/images/emoji/japanese_goblin.pngbin1561 -> 0 bytes
-rw-r--r--app/assets/images/emoji/japanese_ogre.pngbin1864 -> 0 bytes
-rw-r--r--app/assets/images/emoji/jeans.pngbin1158 -> 0 bytes
-rw-r--r--app/assets/images/emoji/joy.pngbin1136 -> 0 bytes
-rw-r--r--app/assets/images/emoji/joy_cat.pngbin1633 -> 0 bytes
-rw-r--r--app/assets/images/emoji/joystick.pngbin1039 -> 0 bytes
-rw-r--r--app/assets/images/emoji/juggling.pngbin1165 -> 0 bytes
-rw-r--r--app/assets/images/emoji/juggling_tone1.pngbin1171 -> 0 bytes
-rw-r--r--app/assets/images/emoji/juggling_tone2.pngbin1160 -> 0 bytes
-rw-r--r--app/assets/images/emoji/juggling_tone3.pngbin1170 -> 0 bytes
-rw-r--r--app/assets/images/emoji/juggling_tone4.pngbin1167 -> 0 bytes
-rw-r--r--app/assets/images/emoji/juggling_tone5.pngbin1161 -> 0 bytes
-rw-r--r--app/assets/images/emoji/kaaba.pngbin1251 -> 0 bytes
-rw-r--r--app/assets/images/emoji/key.pngbin770 -> 0 bytes
-rw-r--r--app/assets/images/emoji/key2.pngbin593 -> 0 bytes
-rw-r--r--app/assets/images/emoji/keyboard.pngbin429 -> 0 bytes
-rw-r--r--app/assets/images/emoji/kimono.pngbin1527 -> 0 bytes
-rw-r--r--app/assets/images/emoji/kiss.pngbin842 -> 0 bytes
-rw-r--r--app/assets/images/emoji/kiss_mm.pngbin1269 -> 0 bytes
-rw-r--r--app/assets/images/emoji/kiss_ww.pngbin1149 -> 0 bytes
-rw-r--r--app/assets/images/emoji/kissing.pngbin738 -> 0 bytes
-rw-r--r--app/assets/images/emoji/kissing_cat.pngbin1468 -> 0 bytes
-rw-r--r--app/assets/images/emoji/kissing_closed_eyes.pngbin888 -> 0 bytes
-rw-r--r--app/assets/images/emoji/kissing_heart.pngbin843 -> 0 bytes
-rw-r--r--app/assets/images/emoji/kissing_smiling_eyes.pngbin648 -> 0 bytes
-rw-r--r--app/assets/images/emoji/kiwi.pngbin1892 -> 0 bytes
-rw-r--r--app/assets/images/emoji/knife.pngbin616 -> 0 bytes
-rw-r--r--app/assets/images/emoji/koala.pngbin1428 -> 0 bytes
-rw-r--r--app/assets/images/emoji/koko.pngbin266 -> 0 bytes
-rw-r--r--app/assets/images/emoji/label.pngbin669 -> 0 bytes
-rw-r--r--app/assets/images/emoji/large_blue_circle.pngbin371 -> 0 bytes
-rw-r--r--app/assets/images/emoji/large_blue_diamond.pngbin245 -> 0 bytes
-rw-r--r--app/assets/images/emoji/large_orange_diamond.pngbin248 -> 0 bytes
-rw-r--r--app/assets/images/emoji/last_quarter_moon.pngbin1180 -> 0 bytes
-rw-r--r--app/assets/images/emoji/last_quarter_moon_with_face.pngbin1030 -> 0 bytes
-rw-r--r--app/assets/images/emoji/laughing.pngbin901 -> 0 bytes
-rw-r--r--app/assets/images/emoji/leaves.pngbin993 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ledger.pngbin1528 -> 0 bytes
-rw-r--r--app/assets/images/emoji/left_facing_fist.pngbin972 -> 0 bytes
-rw-r--r--app/assets/images/emoji/left_facing_fist_tone1.pngbin960 -> 0 bytes
-rw-r--r--app/assets/images/emoji/left_facing_fist_tone2.pngbin972 -> 0 bytes
-rw-r--r--app/assets/images/emoji/left_facing_fist_tone3.pngbin960 -> 0 bytes
-rw-r--r--app/assets/images/emoji/left_facing_fist_tone4.pngbin960 -> 0 bytes
-rw-r--r--app/assets/images/emoji/left_facing_fist_tone5.pngbin976 -> 0 bytes
-rw-r--r--app/assets/images/emoji/left_luggage.pngbin576 -> 0 bytes
-rw-r--r--app/assets/images/emoji/left_right_arrow.pngbin495 -> 0 bytes
-rw-r--r--app/assets/images/emoji/leftwards_arrow_with_hook.pngbin643 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lemon.pngbin1033 -> 0 bytes
-rw-r--r--app/assets/images/emoji/leo.pngbin745 -> 0 bytes
-rw-r--r--app/assets/images/emoji/leopard.pngbin2222 -> 0 bytes
-rw-r--r--app/assets/images/emoji/level_slider.pngbin454 -> 0 bytes
-rw-r--r--app/assets/images/emoji/levitate.pngbin914 -> 0 bytes
-rw-r--r--app/assets/images/emoji/libra.pngbin657 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lifter.pngbin1356 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lifter_tone1.pngbin1346 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lifter_tone2.pngbin1347 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lifter_tone3.pngbin1339 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lifter_tone4.pngbin1343 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lifter_tone5.pngbin1337 -> 0 bytes
-rw-r--r--app/assets/images/emoji/light_rail.pngbin902 -> 0 bytes
-rw-r--r--app/assets/images/emoji/link.pngbin477 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lion_face.pngbin1728 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lips.pngbin599 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lipstick.pngbin549 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lizard.pngbin1709 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lock.pngbin986 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lock_with_ink_pen.pngbin1123 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lollipop.pngbin2164 -> 0 bytes
-rw-r--r--app/assets/images/emoji/loop.pngbin550 -> 0 bytes
-rw-r--r--app/assets/images/emoji/loud_sound.pngbin977 -> 0 bytes
-rw-r--r--app/assets/images/emoji/loudspeaker.pngbin1316 -> 0 bytes
-rw-r--r--app/assets/images/emoji/love_hotel.pngbin372 -> 0 bytes
-rw-r--r--app/assets/images/emoji/love_letter.pngbin923 -> 0 bytes
-rw-r--r--app/assets/images/emoji/low_brightness.pngbin431 -> 0 bytes
-rw-r--r--app/assets/images/emoji/lying_face.pngbin1103 -> 0 bytes
-rw-r--r--app/assets/images/emoji/m.pngbin500 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mag.pngbin1240 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mag_right.pngbin1251 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mahjong.pngbin951 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mailbox.pngbin1166 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mailbox_closed.pngbin1192 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mailbox_with_mail.pngbin1307 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mailbox_with_no_mail.pngbin960 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man.pngbin1092 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_dancing.pngbin1400 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_dancing_tone1.pngbin1404 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_dancing_tone2.pngbin1402 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_dancing_tone3.pngbin1409 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_dancing_tone4.pngbin1421 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_dancing_tone5.pngbin1418 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_in_tuxedo.pngbin1307 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_in_tuxedo_tone1.pngbin1307 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_in_tuxedo_tone2.pngbin1307 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_in_tuxedo_tone3.pngbin1307 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_in_tuxedo_tone4.pngbin1307 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_in_tuxedo_tone5.pngbin1302 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_tone1.pngbin1069 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_tone2.pngbin1069 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_tone3.pngbin1069 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_tone4.pngbin1069 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_tone5.pngbin1087 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_with_gua_pi_mao.pngbin1339 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_with_gua_pi_mao_tone1.pngbin1328 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_with_gua_pi_mao_tone2.pngbin1332 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_with_gua_pi_mao_tone3.pngbin1329 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_with_gua_pi_mao_tone4.pngbin1325 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_with_gua_pi_mao_tone5.pngbin1337 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_with_turban.pngbin1618 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_with_turban_tone1.pngbin1584 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_with_turban_tone2.pngbin1588 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_with_turban_tone3.pngbin1584 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_with_turban_tone4.pngbin1583 -> 0 bytes
-rw-r--r--app/assets/images/emoji/man_with_turban_tone5.pngbin1605 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mans_shoe.pngbin1649 -> 0 bytes
-rw-r--r--app/assets/images/emoji/map.pngbin2352 -> 0 bytes
-rw-r--r--app/assets/images/emoji/maple_leaf.pngbin1117 -> 0 bytes
-rw-r--r--app/assets/images/emoji/martial_arts_uniform.pngbin1412 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mask.pngbin1322 -> 0 bytes
-rw-r--r--app/assets/images/emoji/massage.pngbin1571 -> 0 bytes
-rw-r--r--app/assets/images/emoji/massage_tone1.pngbin1578 -> 0 bytes
-rw-r--r--app/assets/images/emoji/massage_tone2.pngbin1565 -> 0 bytes
-rw-r--r--app/assets/images/emoji/massage_tone3.pngbin1553 -> 0 bytes
-rw-r--r--app/assets/images/emoji/massage_tone4.pngbin1546 -> 0 bytes
-rw-r--r--app/assets/images/emoji/massage_tone5.pngbin1557 -> 0 bytes
-rw-r--r--app/assets/images/emoji/meat_on_bone.pngbin1465 -> 0 bytes
-rw-r--r--app/assets/images/emoji/medal.pngbin1700 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mega.pngbin1751 -> 0 bytes
-rw-r--r--app/assets/images/emoji/melon.pngbin2005 -> 0 bytes
-rw-r--r--app/assets/images/emoji/menorah.pngbin1279 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mens.pngbin561 -> 0 bytes
-rw-r--r--app/assets/images/emoji/metal.pngbin894 -> 0 bytes
-rw-r--r--app/assets/images/emoji/metal_tone1.pngbin894 -> 0 bytes
-rw-r--r--app/assets/images/emoji/metal_tone2.pngbin888 -> 0 bytes
-rw-r--r--app/assets/images/emoji/metal_tone3.pngbin894 -> 0 bytes
-rw-r--r--app/assets/images/emoji/metal_tone4.pngbin888 -> 0 bytes
-rw-r--r--app/assets/images/emoji/metal_tone5.pngbin894 -> 0 bytes
-rw-r--r--app/assets/images/emoji/metro.pngbin1020 -> 0 bytes
-rw-r--r--app/assets/images/emoji/microphone.pngbin1165 -> 0 bytes
-rw-r--r--app/assets/images/emoji/microphone2.pngbin839 -> 0 bytes
-rw-r--r--app/assets/images/emoji/microscope.pngbin1113 -> 0 bytes
-rw-r--r--app/assets/images/emoji/middle_finger.pngbin893 -> 0 bytes
-rw-r--r--app/assets/images/emoji/middle_finger_tone1.pngbin892 -> 0 bytes
-rw-r--r--app/assets/images/emoji/middle_finger_tone2.pngbin892 -> 0 bytes
-rw-r--r--app/assets/images/emoji/middle_finger_tone3.pngbin892 -> 0 bytes
-rw-r--r--app/assets/images/emoji/middle_finger_tone4.pngbin892 -> 0 bytes
-rw-r--r--app/assets/images/emoji/middle_finger_tone5.pngbin892 -> 0 bytes
-rw-r--r--app/assets/images/emoji/military_medal.pngbin949 -> 0 bytes
-rw-r--r--app/assets/images/emoji/milk.pngbin1224 -> 0 bytes
-rw-r--r--app/assets/images/emoji/milky_way.pngbin622 -> 0 bytes
-rw-r--r--app/assets/images/emoji/minibus.pngbin1256 -> 0 bytes
-rw-r--r--app/assets/images/emoji/minidisc.pngbin522 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mobile_phone_off.pngbin621 -> 0 bytes
-rw-r--r--app/assets/images/emoji/money_mouth.pngbin967 -> 0 bytes
-rw-r--r--app/assets/images/emoji/money_with_wings.pngbin2327 -> 0 bytes
-rw-r--r--app/assets/images/emoji/moneybag.pngbin2310 -> 0 bytes
-rw-r--r--app/assets/images/emoji/monkey.pngbin1348 -> 0 bytes
-rw-r--r--app/assets/images/emoji/monkey_face.pngbin1022 -> 0 bytes
-rw-r--r--app/assets/images/emoji/monorail.pngbin1068 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mortar_board.pngbin710 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mosque.pngbin984 -> 0 bytes
-rw-r--r--app/assets/images/emoji/motor_scooter.pngbin1207 -> 0 bytes
-rw-r--r--app/assets/images/emoji/motorboat.pngbin990 -> 0 bytes
-rw-r--r--app/assets/images/emoji/motorcycle.pngbin2081 -> 0 bytes
-rw-r--r--app/assets/images/emoji/motorway.pngbin1102 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mount_fuji.pngbin881 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mountain.pngbin1409 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mountain_bicyclist.pngbin2288 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mountain_bicyclist_tone1.pngbin2294 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mountain_bicyclist_tone2.pngbin2298 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mountain_bicyclist_tone3.pngbin2284 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mountain_bicyclist_tone4.pngbin2288 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mountain_bicyclist_tone5.pngbin2281 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mountain_cableway.pngbin811 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mountain_railway.pngbin1317 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mountain_snow.pngbin1193 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mouse.pngbin1245 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mouse2.pngbin1324 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mouse_three_button.pngbin934 -> 0 bytes
-rw-r--r--app/assets/images/emoji/movie_camera.pngbin576 -> 0 bytes
-rw-r--r--app/assets/images/emoji/moyai.pngbin1593 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mrs_claus.pngbin3338 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mrs_claus_tone1.pngbin1999 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mrs_claus_tone2.pngbin2006 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mrs_claus_tone3.pngbin2017 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mrs_claus_tone4.pngbin2016 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mrs_claus_tone5.pngbin2016 -> 0 bytes
-rw-r--r--app/assets/images/emoji/muscle.pngbin1012 -> 0 bytes
-rw-r--r--app/assets/images/emoji/muscle_tone1.pngbin1012 -> 0 bytes
-rw-r--r--app/assets/images/emoji/muscle_tone2.pngbin1012 -> 0 bytes
-rw-r--r--app/assets/images/emoji/muscle_tone3.pngbin1012 -> 0 bytes
-rw-r--r--app/assets/images/emoji/muscle_tone4.pngbin1012 -> 0 bytes
-rw-r--r--app/assets/images/emoji/muscle_tone5.pngbin1012 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mushroom.pngbin1024 -> 0 bytes
-rw-r--r--app/assets/images/emoji/musical_keyboard.pngbin1695 -> 0 bytes
-rw-r--r--app/assets/images/emoji/musical_note.pngbin419 -> 0 bytes
-rw-r--r--app/assets/images/emoji/musical_score.pngbin1289 -> 0 bytes
-rw-r--r--app/assets/images/emoji/mute.pngbin823 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nail_care.pngbin1639 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nail_care_tone1.pngbin1712 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nail_care_tone2.pngbin1711 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nail_care_tone3.pngbin1727 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nail_care_tone4.pngbin1728 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nail_care_tone5.pngbin1716 -> 0 bytes
-rw-r--r--app/assets/images/emoji/name_badge.pngbin632 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nauseated_face.pngbin965 -> 0 bytes
-rw-r--r--app/assets/images/emoji/necktie.pngbin995 -> 0 bytes
-rw-r--r--app/assets/images/emoji/negative_squared_cross_mark.pngbin370 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nerd.pngbin975 -> 0 bytes
-rw-r--r--app/assets/images/emoji/neutral_face.pngbin517 -> 0 bytes
-rw-r--r--app/assets/images/emoji/new.pngbin486 -> 0 bytes
-rw-r--r--app/assets/images/emoji/new_moon.pngbin829 -> 0 bytes
-rw-r--r--app/assets/images/emoji/new_moon_with_face.pngbin975 -> 0 bytes
-rw-r--r--app/assets/images/emoji/newspaper.pngbin1178 -> 0 bytes
-rw-r--r--app/assets/images/emoji/newspaper2.pngbin1046 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ng.pngbin445 -> 0 bytes
-rw-r--r--app/assets/images/emoji/night_with_stars.pngbin835 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nine.pngbin607 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_bell.pngbin823 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_bicycles.pngbin998 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_entry.pngbin377 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_entry_sign.pngbin555 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_good.pngbin1750 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_good_tone1.pngbin1767 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_good_tone2.pngbin1756 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_good_tone3.pngbin1766 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_good_tone4.pngbin1782 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_good_tone5.pngbin1784 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_mobile_phones.pngbin790 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_mouth.pngbin465 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_pedestrians.pngbin875 -> 0 bytes
-rw-r--r--app/assets/images/emoji/no_smoking.pngbin1136 -> 0 bytes
-rw-r--r--app/assets/images/emoji/non-potable_water.pngbin827 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nose.pngbin703 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nose_tone1.pngbin703 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nose_tone2.pngbin703 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nose_tone3.pngbin703 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nose_tone4.pngbin703 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nose_tone5.pngbin703 -> 0 bytes
-rw-r--r--app/assets/images/emoji/notebook.pngbin1215 -> 0 bytes
-rw-r--r--app/assets/images/emoji/notebook_with_decorative_cover.pngbin1782 -> 0 bytes
-rw-r--r--app/assets/images/emoji/notepad_spiral.pngbin1377 -> 0 bytes
-rw-r--r--app/assets/images/emoji/notes.pngbin501 -> 0 bytes
-rw-r--r--app/assets/images/emoji/nut_and_bolt.pngbin899 -> 0 bytes
-rw-r--r--app/assets/images/emoji/o.pngbin475 -> 0 bytes
-rw-r--r--app/assets/images/emoji/o2.pngbin425 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ocean.pngbin1018 -> 0 bytes
-rw-r--r--app/assets/images/emoji/octagonal_sign.pngbin260 -> 0 bytes
-rw-r--r--app/assets/images/emoji/octopus.pngbin1188 -> 0 bytes
-rw-r--r--app/assets/images/emoji/oden.pngbin794 -> 0 bytes
-rw-r--r--app/assets/images/emoji/office.pngbin524 -> 0 bytes
-rw-r--r--app/assets/images/emoji/oil.pngbin674 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok.pngbin511 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok_hand.pngbin979 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok_hand_tone1.pngbin979 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok_hand_tone2.pngbin979 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok_hand_tone3.pngbin979 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok_hand_tone4.pngbin979 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok_hand_tone5.pngbin979 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok_woman.pngbin1696 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok_woman_tone1.pngbin1696 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok_woman_tone2.pngbin1694 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok_woman_tone3.pngbin1675 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok_woman_tone4.pngbin1684 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ok_woman_tone5.pngbin1696 -> 0 bytes
-rw-r--r--app/assets/images/emoji/older_man.pngbin1253 -> 0 bytes
-rw-r--r--app/assets/images/emoji/older_man_tone1.pngbin1253 -> 0 bytes
-rw-r--r--app/assets/images/emoji/older_man_tone2.pngbin1253 -> 0 bytes
-rw-r--r--app/assets/images/emoji/older_man_tone3.pngbin1253 -> 0 bytes
-rw-r--r--app/assets/images/emoji/older_man_tone4.pngbin1254 -> 0 bytes
-rw-r--r--app/assets/images/emoji/older_man_tone5.pngbin1254 -> 0 bytes
-rw-r--r--app/assets/images/emoji/older_woman.pngbin1472 -> 0 bytes
-rw-r--r--app/assets/images/emoji/older_woman_tone1.pngbin1562 -> 0 bytes
-rw-r--r--app/assets/images/emoji/older_woman_tone2.pngbin1564 -> 0 bytes
-rw-r--r--app/assets/images/emoji/older_woman_tone3.pngbin1555 -> 0 bytes
-rw-r--r--app/assets/images/emoji/older_woman_tone4.pngbin1562 -> 0 bytes
-rw-r--r--app/assets/images/emoji/older_woman_tone5.pngbin1544 -> 0 bytes
-rw-r--r--app/assets/images/emoji/om_symbol.pngbin773 -> 0 bytes
-rw-r--r--app/assets/images/emoji/on.pngbin459 -> 0 bytes
-rw-r--r--app/assets/images/emoji/oncoming_automobile.pngbin1238 -> 0 bytes
-rw-r--r--app/assets/images/emoji/oncoming_bus.pngbin964 -> 0 bytes
-rw-r--r--app/assets/images/emoji/oncoming_police_car.pngbin1547 -> 0 bytes
-rw-r--r--app/assets/images/emoji/oncoming_taxi.pngbin1405 -> 0 bytes
-rw-r--r--app/assets/images/emoji/one.pngbin442 -> 0 bytes
-rw-r--r--app/assets/images/emoji/open_file_folder.pngbin755 -> 0 bytes
-rw-r--r--app/assets/images/emoji/open_hands.pngbin1053 -> 0 bytes
-rw-r--r--app/assets/images/emoji/open_hands_tone1.pngbin1053 -> 0 bytes
-rw-r--r--app/assets/images/emoji/open_hands_tone2.pngbin1053 -> 0 bytes
-rw-r--r--app/assets/images/emoji/open_hands_tone3.pngbin1053 -> 0 bytes
-rw-r--r--app/assets/images/emoji/open_hands_tone4.pngbin1053 -> 0 bytes
-rw-r--r--app/assets/images/emoji/open_hands_tone5.pngbin1053 -> 0 bytes
-rw-r--r--app/assets/images/emoji/open_mouth.pngbin575 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ophiuchus.pngbin723 -> 0 bytes
-rw-r--r--app/assets/images/emoji/orange_book.pngbin1329 -> 0 bytes
-rw-r--r--app/assets/images/emoji/orthodox_cross.pngbin239 -> 0 bytes
-rw-r--r--app/assets/images/emoji/outbox_tray.pngbin1002 -> 0 bytes
-rw-r--r--app/assets/images/emoji/owl.pngbin2045 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ox.pngbin1436 -> 0 bytes
-rw-r--r--app/assets/images/emoji/package.pngbin950 -> 0 bytes
-rw-r--r--app/assets/images/emoji/page_facing_up.pngbin1110 -> 0 bytes
-rw-r--r--app/assets/images/emoji/page_with_curl.pngbin1157 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pager.pngbin553 -> 0 bytes
-rw-r--r--app/assets/images/emoji/paintbrush.pngbin950 -> 0 bytes
-rw-r--r--app/assets/images/emoji/palm_tree.pngbin1450 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pancakes.pngbin3661 -> 0 bytes
-rw-r--r--app/assets/images/emoji/panda_face.pngbin1478 -> 0 bytes
-rw-r--r--app/assets/images/emoji/paperclip.pngbin439 -> 0 bytes
-rw-r--r--app/assets/images/emoji/paperclips.pngbin642 -> 0 bytes
-rw-r--r--app/assets/images/emoji/park.pngbin929 -> 0 bytes
-rw-r--r--app/assets/images/emoji/parking.pngbin385 -> 0 bytes
-rw-r--r--app/assets/images/emoji/part_alternation_mark.pngbin521 -> 0 bytes
-rw-r--r--app/assets/images/emoji/partly_sunny.pngbin977 -> 0 bytes
-rw-r--r--app/assets/images/emoji/passport_control.pngbin683 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pause_button.pngbin395 -> 0 bytes
-rw-r--r--app/assets/images/emoji/peace.pngbin933 -> 0 bytes
-rw-r--r--app/assets/images/emoji/peach.pngbin1189 -> 0 bytes
-rw-r--r--app/assets/images/emoji/peanuts.pngbin3266 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pear.pngbin747 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pen_ballpoint.pngbin696 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pen_fountain.pngbin623 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pencil.pngbin1624 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pencil2.pngbin654 -> 0 bytes
-rw-r--r--app/assets/images/emoji/penguin.pngbin1034 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pensive.pngbin718 -> 0 bytes
-rw-r--r--app/assets/images/emoji/performing_arts.pngbin1971 -> 0 bytes
-rw-r--r--app/assets/images/emoji/persevere.pngbin891 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_frowning.pngbin1148 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_frowning_tone1.pngbin1141 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_frowning_tone2.pngbin1141 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_frowning_tone3.pngbin1141 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_frowning_tone4.pngbin1109 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_frowning_tone5.pngbin1114 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_with_blond_hair.pngbin1205 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_with_blond_hair_tone1.pngbin1181 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_with_blond_hair_tone2.pngbin1181 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_with_blond_hair_tone3.pngbin1181 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_with_blond_hair_tone4.pngbin1189 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_with_blond_hair_tone5.pngbin1214 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_with_pouting_face.pngbin1297 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_with_pouting_face_tone1.pngbin1309 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_with_pouting_face_tone2.pngbin1292 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_with_pouting_face_tone3.pngbin1305 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_with_pouting_face_tone4.pngbin1296 -> 0 bytes
-rw-r--r--app/assets/images/emoji/person_with_pouting_face_tone5.pngbin1303 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pick.pngbin1023 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pig.pngbin1138 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pig2.pngbin1548 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pig_nose.pngbin820 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pill.pngbin442 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pineapple.pngbin1642 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ping_pong.pngbin823 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pisces.pngbin678 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pizza.pngbin2008 -> 0 bytes
-rw-r--r--app/assets/images/emoji/place_of_worship.pngbin487 -> 0 bytes
-rw-r--r--app/assets/images/emoji/play_pause.pngbin509 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_down.pngbin853 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_down_tone1.pngbin856 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_down_tone2.pngbin856 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_down_tone3.pngbin858 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_down_tone4.pngbin856 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_down_tone5.pngbin856 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_left.pngbin825 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_left_tone1.pngbin832 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_left_tone2.pngbin830 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_left_tone3.pngbin830 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_left_tone4.pngbin830 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_left_tone5.pngbin832 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_right.pngbin805 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_right_tone1.pngbin805 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_right_tone2.pngbin805 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_right_tone3.pngbin805 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_right_tone4.pngbin805 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_right_tone5.pngbin805 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_up.pngbin819 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_up_2.pngbin822 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_up_2_tone1.pngbin822 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_up_2_tone2.pngbin822 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_up_2_tone3.pngbin871 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_up_2_tone4.pngbin822 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_up_2_tone5.pngbin822 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_up_tone1.pngbin820 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_up_tone2.pngbin820 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_up_tone3.pngbin820 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_up_tone4.pngbin820 -> 0 bytes
-rw-r--r--app/assets/images/emoji/point_up_tone5.pngbin820 -> 0 bytes
-rw-r--r--app/assets/images/emoji/police_car.pngbin1431 -> 0 bytes
-rw-r--r--app/assets/images/emoji/poodle.pngbin1531 -> 0 bytes
-rw-r--r--app/assets/images/emoji/poop.pngbin1273 -> 0 bytes
-rw-r--r--app/assets/images/emoji/popcorn.pngbin1843 -> 0 bytes
-rw-r--r--app/assets/images/emoji/post_office.pngbin676 -> 0 bytes
-rw-r--r--app/assets/images/emoji/postal_horn.pngbin809 -> 0 bytes
-rw-r--r--app/assets/images/emoji/postbox.pngbin1077 -> 0 bytes
-rw-r--r--app/assets/images/emoji/potable_water.pngbin633 -> 0 bytes
-rw-r--r--app/assets/images/emoji/potato.pngbin1246 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pouch.pngbin1259 -> 0 bytes
-rw-r--r--app/assets/images/emoji/poultry_leg.pngbin925 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pound.pngbin452 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pouting_cat.pngbin1675 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pray.pngbin1122 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pray_tone1.pngbin1131 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pray_tone2.pngbin1134 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pray_tone3.pngbin1137 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pray_tone4.pngbin1126 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pray_tone5.pngbin1117 -> 0 bytes
-rw-r--r--app/assets/images/emoji/prayer_beads.pngbin1059 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pregnant_woman.pngbin1252 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pregnant_woman_tone1.pngbin1255 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pregnant_woman_tone2.pngbin1246 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pregnant_woman_tone3.pngbin1237 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pregnant_woman_tone4.pngbin1246 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pregnant_woman_tone5.pngbin1235 -> 0 bytes
-rw-r--r--app/assets/images/emoji/prince.pngbin1616 -> 0 bytes
-rw-r--r--app/assets/images/emoji/prince_tone1.pngbin1618 -> 0 bytes
-rw-r--r--app/assets/images/emoji/prince_tone2.pngbin1621 -> 0 bytes
-rw-r--r--app/assets/images/emoji/prince_tone3.pngbin1619 -> 0 bytes
-rw-r--r--app/assets/images/emoji/prince_tone4.pngbin1619 -> 0 bytes
-rw-r--r--app/assets/images/emoji/prince_tone5.pngbin1616 -> 0 bytes
-rw-r--r--app/assets/images/emoji/princess.pngbin1812 -> 0 bytes
-rw-r--r--app/assets/images/emoji/princess_tone1.pngbin1812 -> 0 bytes
-rw-r--r--app/assets/images/emoji/princess_tone2.pngbin1805 -> 0 bytes
-rw-r--r--app/assets/images/emoji/princess_tone3.pngbin1805 -> 0 bytes
-rw-r--r--app/assets/images/emoji/princess_tone4.pngbin1813 -> 0 bytes
-rw-r--r--app/assets/images/emoji/princess_tone5.pngbin1812 -> 0 bytes
-rw-r--r--app/assets/images/emoji/printer.pngbin926 -> 0 bytes
-rw-r--r--app/assets/images/emoji/projector.pngbin943 -> 0 bytes
-rw-r--r--app/assets/images/emoji/punch.pngbin838 -> 0 bytes
-rw-r--r--app/assets/images/emoji/punch_tone1.pngbin838 -> 0 bytes
-rw-r--r--app/assets/images/emoji/punch_tone2.pngbin838 -> 0 bytes
-rw-r--r--app/assets/images/emoji/punch_tone3.pngbin838 -> 0 bytes
-rw-r--r--app/assets/images/emoji/punch_tone4.pngbin838 -> 0 bytes
-rw-r--r--app/assets/images/emoji/punch_tone5.pngbin838 -> 0 bytes
-rw-r--r--app/assets/images/emoji/purple_heart.pngbin435 -> 0 bytes
-rw-r--r--app/assets/images/emoji/purse.pngbin1558 -> 0 bytes
-rw-r--r--app/assets/images/emoji/pushpin.pngbin640 -> 0 bytes
-rw-r--r--app/assets/images/emoji/put_litter_in_its_place.pngbin650 -> 0 bytes
-rw-r--r--app/assets/images/emoji/question.pngbin449 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rabbit.pngbin1660 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rabbit2.pngbin1805 -> 0 bytes
-rw-r--r--app/assets/images/emoji/race_car.pngbin2140 -> 0 bytes
-rw-r--r--app/assets/images/emoji/racehorse.pngbin1401 -> 0 bytes
-rw-r--r--app/assets/images/emoji/radio.pngbin851 -> 0 bytes
-rw-r--r--app/assets/images/emoji/radio_button.pngbin674 -> 0 bytes
-rw-r--r--app/assets/images/emoji/radioactive.pngbin858 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rage.pngbin845 -> 0 bytes
-rw-r--r--app/assets/images/emoji/railway_car.pngbin847 -> 0 bytes
-rw-r--r--app/assets/images/emoji/railway_track.pngbin1550 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rainbow.pngbin1299 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_back_of_hand.pngbin848 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_back_of_hand_tone1.pngbin848 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_back_of_hand_tone2.pngbin848 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_back_of_hand_tone3.pngbin848 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_back_of_hand_tone4.pngbin848 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_back_of_hand_tone5.pngbin848 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_hand.pngbin791 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_hand_tone1.pngbin791 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_hand_tone2.pngbin791 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_hand_tone3.pngbin791 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_hand_tone4.pngbin791 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_hand_tone5.pngbin791 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_hands.pngbin1098 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_hands_tone1.pngbin1098 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_hands_tone2.pngbin1098 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_hands_tone3.pngbin1098 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_hands_tone4.pngbin1098 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raised_hands_tone5.pngbin1098 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raising_hand.pngbin1664 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raising_hand_tone1.pngbin1678 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raising_hand_tone2.pngbin1665 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raising_hand_tone3.pngbin1657 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raising_hand_tone4.pngbin1657 -> 0 bytes
-rw-r--r--app/assets/images/emoji/raising_hand_tone5.pngbin1661 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ram.pngbin1951 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ramen.pngbin1992 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rat.pngbin1193 -> 0 bytes
-rw-r--r--app/assets/images/emoji/record_button.pngbin475 -> 0 bytes
-rw-r--r--app/assets/images/emoji/recycle.pngbin914 -> 0 bytes
-rw-r--r--app/assets/images/emoji/red_car.pngbin1065 -> 0 bytes
-rw-r--r--app/assets/images/emoji/red_circle.pngbin374 -> 0 bytes
-rw-r--r--app/assets/images/emoji/registered.pngbin547 -> 0 bytes
-rw-r--r--app/assets/images/emoji/relaxed.pngbin636 -> 0 bytes
-rw-r--r--app/assets/images/emoji/relieved.pngbin785 -> 0 bytes
-rw-r--r--app/assets/images/emoji/reminder_ribbon.pngbin921 -> 0 bytes
-rw-r--r--app/assets/images/emoji/repeat.pngbin644 -> 0 bytes
-rw-r--r--app/assets/images/emoji/repeat_one.pngbin688 -> 0 bytes
-rw-r--r--app/assets/images/emoji/restroom.pngbin676 -> 0 bytes
-rw-r--r--app/assets/images/emoji/revolving_hearts.pngbin920 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rewind.pngbin523 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rhino.pngbin1558 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ribbon.pngbin968 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rice.pngbin1195 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rice_ball.pngbin1091 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rice_cracker.pngbin1443 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rice_scene.pngbin1349 -> 0 bytes
-rw-r--r--app/assets/images/emoji/right_facing_fist.pngbin975 -> 0 bytes
-rw-r--r--app/assets/images/emoji/right_facing_fist_tone1.pngbin964 -> 0 bytes
-rw-r--r--app/assets/images/emoji/right_facing_fist_tone2.pngbin964 -> 0 bytes
-rw-r--r--app/assets/images/emoji/right_facing_fist_tone3.pngbin964 -> 0 bytes
-rw-r--r--app/assets/images/emoji/right_facing_fist_tone4.pngbin964 -> 0 bytes
-rw-r--r--app/assets/images/emoji/right_facing_fist_tone5.pngbin964 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ring.pngbin1113 -> 0 bytes
-rw-r--r--app/assets/images/emoji/robot.pngbin1228 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rocket.pngbin1639 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rofl.pngbin1760 -> 0 bytes
-rw-r--r--app/assets/images/emoji/roller_coaster.pngbin1723 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rolling_eyes.pngbin743 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rooster.pngbin1333 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rose.pngbin1182 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rosette.pngbin1023 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rotating_light.pngbin1969 -> 0 bytes
-rw-r--r--app/assets/images/emoji/round_pushpin.pngbin455 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rowboat.pngbin1963 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rowboat_tone1.pngbin1971 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rowboat_tone2.pngbin1972 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rowboat_tone3.pngbin1967 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rowboat_tone4.pngbin1974 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rowboat_tone5.pngbin1971 -> 0 bytes
-rw-r--r--app/assets/images/emoji/rugby_football.pngbin1618 -> 0 bytes
-rw-r--r--app/assets/images/emoji/runner.pngbin1161 -> 0 bytes
-rw-r--r--app/assets/images/emoji/runner_tone1.pngbin1163 -> 0 bytes
-rw-r--r--app/assets/images/emoji/runner_tone2.pngbin1162 -> 0 bytes
-rw-r--r--app/assets/images/emoji/runner_tone3.pngbin1151 -> 0 bytes
-rw-r--r--app/assets/images/emoji/runner_tone4.pngbin1156 -> 0 bytes
-rw-r--r--app/assets/images/emoji/runner_tone5.pngbin1145 -> 0 bytes
-rw-r--r--app/assets/images/emoji/running_shirt_with_sash.pngbin784 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sa.pngbin420 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sagittarius.pngbin602 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sailboat.pngbin1274 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sake.pngbin826 -> 0 bytes
-rw-r--r--app/assets/images/emoji/salad.pngbin2398 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sandal.pngbin1180 -> 0 bytes
-rw-r--r--app/assets/images/emoji/santa.pngbin1585 -> 0 bytes
-rw-r--r--app/assets/images/emoji/santa_tone1.pngbin1585 -> 0 bytes
-rw-r--r--app/assets/images/emoji/santa_tone2.pngbin1578 -> 0 bytes
-rw-r--r--app/assets/images/emoji/santa_tone3.pngbin1578 -> 0 bytes
-rw-r--r--app/assets/images/emoji/santa_tone4.pngbin1578 -> 0 bytes
-rw-r--r--app/assets/images/emoji/santa_tone5.pngbin1578 -> 0 bytes
-rw-r--r--app/assets/images/emoji/satellite.pngbin1173 -> 0 bytes
-rw-r--r--app/assets/images/emoji/satellite_orbital.pngbin762 -> 0 bytes
-rw-r--r--app/assets/images/emoji/saxophone.pngbin1442 -> 0 bytes
-rw-r--r--app/assets/images/emoji/scales.pngbin1181 -> 0 bytes
-rw-r--r--app/assets/images/emoji/school.pngbin1234 -> 0 bytes
-rw-r--r--app/assets/images/emoji/school_satchel.pngbin1490 -> 0 bytes
-rw-r--r--app/assets/images/emoji/scissors.pngbin937 -> 0 bytes
-rw-r--r--app/assets/images/emoji/scooter.pngbin1228 -> 0 bytes
-rw-r--r--app/assets/images/emoji/scorpion.pngbin1503 -> 0 bytes
-rw-r--r--app/assets/images/emoji/scorpius.pngbin612 -> 0 bytes
-rw-r--r--app/assets/images/emoji/scream.pngbin1583 -> 0 bytes
-rw-r--r--app/assets/images/emoji/scream_cat.pngbin2120 -> 0 bytes
-rw-r--r--app/assets/images/emoji/scroll.pngbin989 -> 0 bytes
-rw-r--r--app/assets/images/emoji/seat.pngbin884 -> 0 bytes
-rw-r--r--app/assets/images/emoji/second_place.pngbin1511 -> 0 bytes
-rw-r--r--app/assets/images/emoji/secret.pngbin857 -> 0 bytes
-rw-r--r--app/assets/images/emoji/see_no_evil.pngbin1227 -> 0 bytes
-rw-r--r--app/assets/images/emoji/seedling.pngbin749 -> 0 bytes
-rw-r--r--app/assets/images/emoji/selfie.pngbin1160 -> 0 bytes
-rw-r--r--app/assets/images/emoji/selfie_tone1.pngbin1166 -> 0 bytes
-rw-r--r--app/assets/images/emoji/selfie_tone2.pngbin1167 -> 0 bytes
-rw-r--r--app/assets/images/emoji/selfie_tone3.pngbin1154 -> 0 bytes
-rw-r--r--app/assets/images/emoji/selfie_tone4.pngbin1153 -> 0 bytes
-rw-r--r--app/assets/images/emoji/selfie_tone5.pngbin1148 -> 0 bytes
-rw-r--r--app/assets/images/emoji/seven.pngbin522 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shallow_pan_of_food.pngbin1738 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shamrock.pngbin1023 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shark.pngbin1811 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shaved_ice.pngbin997 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sheep.pngbin1372 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shell.pngbin1497 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shield.pngbin1602 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shinto_shrine.pngbin579 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ship.pngbin1405 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shirt.pngbin670 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shopping_bags.pngbin1234 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shopping_cart.pngbin1072 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shower.pngbin2537 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shrimp.pngbin1376 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shrug.pngbin1671 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shrug_tone1.pngbin1676 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shrug_tone2.pngbin1671 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shrug_tone3.pngbin1675 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shrug_tone4.pngbin1641 -> 0 bytes
-rw-r--r--app/assets/images/emoji/shrug_tone5.pngbin1634 -> 0 bytes
-rw-r--r--app/assets/images/emoji/signal_strength.pngbin445 -> 0 bytes
-rw-r--r--app/assets/images/emoji/six.pngbin612 -> 0 bytes
-rw-r--r--app/assets/images/emoji/six_pointed_star.pngbin540 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ski.pngbin1762 -> 0 bytes
-rw-r--r--app/assets/images/emoji/skier.pngbin1539 -> 0 bytes
-rw-r--r--app/assets/images/emoji/skull.pngbin628 -> 0 bytes
-rw-r--r--app/assets/images/emoji/skull_crossbones.pngbin726 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sleeping.pngbin1075 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sleeping_accommodation.pngbin926 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sleepy.pngbin1185 -> 0 bytes
-rw-r--r--app/assets/images/emoji/slight_frown.pngbin580 -> 0 bytes
-rw-r--r--app/assets/images/emoji/slight_smile.pngbin600 -> 0 bytes
-rw-r--r--app/assets/images/emoji/slot_machine.pngbin1648 -> 0 bytes
-rw-r--r--app/assets/images/emoji/small_blue_diamond.pngbin191 -> 0 bytes
-rw-r--r--app/assets/images/emoji/small_orange_diamond.pngbin194 -> 0 bytes
-rw-r--r--app/assets/images/emoji/small_red_triangle.pngbin273 -> 0 bytes
-rw-r--r--app/assets/images/emoji/small_red_triangle_down.pngbin291 -> 0 bytes
-rw-r--r--app/assets/images/emoji/smile.pngbin737 -> 0 bytes
-rw-r--r--app/assets/images/emoji/smile_cat.pngbin1405 -> 0 bytes
-rw-r--r--app/assets/images/emoji/smiley.pngbin686 -> 0 bytes
-rw-r--r--app/assets/images/emoji/smiley_cat.pngbin1669 -> 0 bytes
-rw-r--r--app/assets/images/emoji/smiling_imp.pngbin1078 -> 0 bytes
-rw-r--r--app/assets/images/emoji/smirk.pngbin775 -> 0 bytes
-rw-r--r--app/assets/images/emoji/smirk_cat.pngbin1663 -> 0 bytes
-rw-r--r--app/assets/images/emoji/smoking.pngbin417 -> 0 bytes
-rw-r--r--app/assets/images/emoji/snail.pngbin1731 -> 0 bytes
-rw-r--r--app/assets/images/emoji/snake.pngbin1575 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sneezing_face.pngbin1289 -> 0 bytes
-rw-r--r--app/assets/images/emoji/snowboarder.pngbin2020 -> 0 bytes
-rw-r--r--app/assets/images/emoji/snowflake.pngbin691 -> 0 bytes
-rw-r--r--app/assets/images/emoji/snowman.pngbin1481 -> 0 bytes
-rw-r--r--app/assets/images/emoji/snowman2.pngbin2176 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sob.pngbin1236 -> 0 bytes
-rw-r--r--app/assets/images/emoji/soccer.pngbin1034 -> 0 bytes
-rw-r--r--app/assets/images/emoji/soon.pngbin483 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sos.pngbin604 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sound.pngbin690 -> 0 bytes
-rw-r--r--app/assets/images/emoji/space_invader.pngbin1325 -> 0 bytes
-rw-r--r--app/assets/images/emoji/spades.pngbin454 -> 0 bytes
-rw-r--r--app/assets/images/emoji/spaghetti.pngbin1796 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sparkle.pngbin663 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sparkler.pngbin910 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sparkles.pngbin651 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sparkling_heart.pngbin821 -> 0 bytes
-rw-r--r--app/assets/images/emoji/speak_no_evil.pngbin1497 -> 0 bytes
-rw-r--r--app/assets/images/emoji/speaker.pngbin575 -> 0 bytes
-rw-r--r--app/assets/images/emoji/speaking_head.pngbin531 -> 0 bytes
-rw-r--r--app/assets/images/emoji/speech_balloon.pngbin384 -> 0 bytes
-rw-r--r--app/assets/images/emoji/speech_left.pngbin390 -> 0 bytes
-rw-r--r--app/assets/images/emoji/speedboat.pngbin1255 -> 0 bytes
-rw-r--r--app/assets/images/emoji/spider.pngbin1724 -> 0 bytes
-rw-r--r--app/assets/images/emoji/spider_web.pngbin929 -> 0 bytes
-rw-r--r--app/assets/images/emoji/spoon.pngbin700 -> 0 bytes
-rw-r--r--app/assets/images/emoji/spy.pngbin1650 -> 0 bytes
-rw-r--r--app/assets/images/emoji/spy_tone1.pngbin1639 -> 0 bytes
-rw-r--r--app/assets/images/emoji/spy_tone2.pngbin1632 -> 0 bytes
-rw-r--r--app/assets/images/emoji/spy_tone3.pngbin1645 -> 0 bytes
-rw-r--r--app/assets/images/emoji/spy_tone4.pngbin1639 -> 0 bytes
-rw-r--r--app/assets/images/emoji/spy_tone5.pngbin1639 -> 0 bytes
-rw-r--r--app/assets/images/emoji/squid.pngbin1394 -> 0 bytes
-rw-r--r--app/assets/images/emoji/stadium.pngbin1515 -> 0 bytes
-rw-r--r--app/assets/images/emoji/star.pngbin456 -> 0 bytes
-rw-r--r--app/assets/images/emoji/star2.pngbin732 -> 0 bytes
-rw-r--r--app/assets/images/emoji/star_and_crescent.pngbin490 -> 0 bytes
-rw-r--r--app/assets/images/emoji/star_of_david.pngbin491 -> 0 bytes
-rw-r--r--app/assets/images/emoji/stars.pngbin1048 -> 0 bytes
-rw-r--r--app/assets/images/emoji/station.pngbin1336 -> 0 bytes
-rw-r--r--app/assets/images/emoji/statue_of_liberty.pngbin1145 -> 0 bytes
-rw-r--r--app/assets/images/emoji/steam_locomotive.pngbin1736 -> 0 bytes
-rw-r--r--app/assets/images/emoji/stew.pngbin1960 -> 0 bytes
-rw-r--r--app/assets/images/emoji/stop_button.pngbin385 -> 0 bytes
-rw-r--r--app/assets/images/emoji/stopwatch.pngbin1329 -> 0 bytes
-rw-r--r--app/assets/images/emoji/straight_ruler.pngbin1406 -> 0 bytes
-rw-r--r--app/assets/images/emoji/strawberry.pngbin1206 -> 0 bytes
-rw-r--r--app/assets/images/emoji/stuck_out_tongue.pngbin752 -> 0 bytes
-rw-r--r--app/assets/images/emoji/stuck_out_tongue_closed_eyes.pngbin867 -> 0 bytes
-rw-r--r--app/assets/images/emoji/stuck_out_tongue_winking_eye.pngbin1061 -> 0 bytes
-rw-r--r--app/assets/images/emoji/stuffed_flatbread.pngbin2160 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sun_with_face.pngbin741 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sunflower.pngbin1915 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sunglasses.pngbin824 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sunny.pngbin746 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sunrise.pngbin812 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sunrise_over_mountains.pngbin1576 -> 0 bytes
-rw-r--r--app/assets/images/emoji/surfer.pngbin1777 -> 0 bytes
-rw-r--r--app/assets/images/emoji/surfer_tone1.pngbin1781 -> 0 bytes
-rw-r--r--app/assets/images/emoji/surfer_tone2.pngbin1769 -> 0 bytes
-rw-r--r--app/assets/images/emoji/surfer_tone3.pngbin1777 -> 0 bytes
-rw-r--r--app/assets/images/emoji/surfer_tone4.pngbin1784 -> 0 bytes
-rw-r--r--app/assets/images/emoji/surfer_tone5.pngbin1782 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sushi.pngbin2101 -> 0 bytes
-rw-r--r--app/assets/images/emoji/suspension_railway.pngbin927 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sweat.pngbin861 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sweat_drops.pngbin549 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sweat_smile.pngbin851 -> 0 bytes
-rw-r--r--app/assets/images/emoji/sweet_potato.pngbin951 -> 0 bytes
-rw-r--r--app/assets/images/emoji/swimmer.pngbin1184 -> 0 bytes
-rw-r--r--app/assets/images/emoji/swimmer_tone1.pngbin1184 -> 0 bytes
-rw-r--r--app/assets/images/emoji/swimmer_tone2.pngbin1184 -> 0 bytes
-rw-r--r--app/assets/images/emoji/swimmer_tone3.pngbin1184 -> 0 bytes
-rw-r--r--app/assets/images/emoji/swimmer_tone4.pngbin1184 -> 0 bytes
-rw-r--r--app/assets/images/emoji/swimmer_tone5.pngbin1184 -> 0 bytes
-rw-r--r--app/assets/images/emoji/symbols.pngbin746 -> 0 bytes
-rw-r--r--app/assets/images/emoji/synagogue.pngbin1309 -> 0 bytes
-rw-r--r--app/assets/images/emoji/syringe.pngbin737 -> 0 bytes
-rw-r--r--app/assets/images/emoji/taco.pngbin3045 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tada.pngbin1778 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tanabata_tree.pngbin1479 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tangerine.pngbin1184 -> 0 bytes
-rw-r--r--app/assets/images/emoji/taurus.pngbin701 -> 0 bytes
-rw-r--r--app/assets/images/emoji/taxi.pngbin1230 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tea.pngbin1297 -> 0 bytes
-rw-r--r--app/assets/images/emoji/telephone.pngbin1760 -> 0 bytes
-rw-r--r--app/assets/images/emoji/telephone_receiver.pngbin941 -> 0 bytes
-rw-r--r--app/assets/images/emoji/telescope.pngbin1256 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ten.pngbin621 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tennis.pngbin1561 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tent.pngbin1684 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thermometer.pngbin759 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thermometer_face.pngbin1503 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thinking.pngbin1345 -> 0 bytes
-rw-r--r--app/assets/images/emoji/third_place.pngbin1529 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thought_balloon.pngbin489 -> 0 bytes
-rw-r--r--app/assets/images/emoji/three.pngbin602 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thumbsdown.pngbin815 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thumbsdown_tone1.pngbin815 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thumbsdown_tone2.pngbin815 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thumbsdown_tone3.pngbin815 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thumbsdown_tone4.pngbin815 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thumbsdown_tone5.pngbin815 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thumbsup.pngbin814 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thumbsup_tone1.pngbin814 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thumbsup_tone2.pngbin814 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thumbsup_tone3.pngbin814 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thumbsup_tone4.pngbin814 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thumbsup_tone5.pngbin814 -> 0 bytes
-rw-r--r--app/assets/images/emoji/thunder_cloud_rain.pngbin1020 -> 0 bytes
-rw-r--r--app/assets/images/emoji/ticket.pngbin763 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tickets.pngbin1750 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tiger.pngbin2104 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tiger2.pngbin2623 -> 0 bytes
-rw-r--r--app/assets/images/emoji/timer.pngbin1897 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tired_face.pngbin1126 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tm.pngbin300 -> 0 bytes
-rw-r--r--app/assets/images/emoji/toilet.pngbin726 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tokyo_tower.pngbin765 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tomato.pngbin1055 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tone1.pngbin372 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tone2.pngbin372 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tone3.pngbin375 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tone4.pngbin374 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tone5.pngbin374 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tongue.pngbin599 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tools.pngbin1225 -> 0 bytes
-rw-r--r--app/assets/images/emoji/top.pngbin389 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tophat.pngbin845 -> 0 bytes
-rw-r--r--app/assets/images/emoji/track_next.pngbin551 -> 0 bytes
-rw-r--r--app/assets/images/emoji/track_previous.pngbin549 -> 0 bytes
-rw-r--r--app/assets/images/emoji/trackball.pngbin892 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tractor.pngbin1192 -> 0 bytes
-rw-r--r--app/assets/images/emoji/traffic_light.pngbin590 -> 0 bytes
-rw-r--r--app/assets/images/emoji/train.pngbin1031 -> 0 bytes
-rw-r--r--app/assets/images/emoji/train2.pngbin1499 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tram.pngbin1065 -> 0 bytes
-rw-r--r--app/assets/images/emoji/triangular_flag_on_post.pngbin415 -> 0 bytes
-rw-r--r--app/assets/images/emoji/triangular_ruler.pngbin369 -> 0 bytes
-rw-r--r--app/assets/images/emoji/trident.pngbin668 -> 0 bytes
-rw-r--r--app/assets/images/emoji/triumph.pngbin1529 -> 0 bytes
-rw-r--r--app/assets/images/emoji/trolleybus.pngbin1168 -> 0 bytes
-rw-r--r--app/assets/images/emoji/trophy.pngbin863 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tropical_drink.pngbin1428 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tropical_fish.pngbin1676 -> 0 bytes
-rw-r--r--app/assets/images/emoji/truck.pngbin1366 -> 0 bytes
-rw-r--r--app/assets/images/emoji/trumpet.pngbin1281 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tulip.pngbin1065 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tumbler_glass.pngbin2312 -> 0 bytes
-rw-r--r--app/assets/images/emoji/turkey.pngbin1240 -> 0 bytes
-rw-r--r--app/assets/images/emoji/turtle.pngbin1515 -> 0 bytes
-rw-r--r--app/assets/images/emoji/tv.pngbin776 -> 0 bytes
-rw-r--r--app/assets/images/emoji/twisted_rightwards_arrows.pngbin574 -> 0 bytes
-rw-r--r--app/assets/images/emoji/two.pngbin567 -> 0 bytes
-rw-r--r--app/assets/images/emoji/two_hearts.pngbin493 -> 0 bytes
-rw-r--r--app/assets/images/emoji/two_men_holding_hands.pngbin1347 -> 0 bytes
-rw-r--r--app/assets/images/emoji/two_women_holding_hands.pngbin1544 -> 0 bytes
-rw-r--r--app/assets/images/emoji/u5272.pngbin411 -> 0 bytes
-rw-r--r--app/assets/images/emoji/u5408.pngbin484 -> 0 bytes
-rw-r--r--app/assets/images/emoji/u55b6.pngbin460 -> 0 bytes
-rw-r--r--app/assets/images/emoji/u6307.pngbin504 -> 0 bytes
-rw-r--r--app/assets/images/emoji/u6708.pngbin409 -> 0 bytes
-rw-r--r--app/assets/images/emoji/u6709.pngbin434 -> 0 bytes
-rw-r--r--app/assets/images/emoji/u6e80.pngbin564 -> 0 bytes
-rw-r--r--app/assets/images/emoji/u7121.pngbin534 -> 0 bytes
-rw-r--r--app/assets/images/emoji/u7533.pngbin306 -> 0 bytes
-rw-r--r--app/assets/images/emoji/u7981.pngbin584 -> 0 bytes
-rw-r--r--app/assets/images/emoji/u7a7a.pngbin456 -> 0 bytes
-rw-r--r--app/assets/images/emoji/umbrella.pngbin1229 -> 0 bytes
-rw-r--r--app/assets/images/emoji/umbrella2.pngbin897 -> 0 bytes
-rw-r--r--app/assets/images/emoji/unamused.pngbin632 -> 0 bytes
-rw-r--r--app/assets/images/emoji/underage.pngbin863 -> 0 bytes
-rw-r--r--app/assets/images/emoji/unicorn.pngbin2107 -> 0 bytes
-rw-r--r--app/assets/images/emoji/unlock.pngbin856 -> 0 bytes
-rw-r--r--app/assets/images/emoji/up.pngbin405 -> 0 bytes
-rw-r--r--app/assets/images/emoji/upside_down.pngbin602 -> 0 bytes
-rw-r--r--app/assets/images/emoji/urn.pngbin742 -> 0 bytes
-rw-r--r--app/assets/images/emoji/v.pngbin1009 -> 0 bytes
-rw-r--r--app/assets/images/emoji/v_tone1.pngbin1009 -> 0 bytes
-rw-r--r--app/assets/images/emoji/v_tone2.pngbin1009 -> 0 bytes
-rw-r--r--app/assets/images/emoji/v_tone3.pngbin1009 -> 0 bytes
-rw-r--r--app/assets/images/emoji/v_tone4.pngbin1009 -> 0 bytes
-rw-r--r--app/assets/images/emoji/v_tone5.pngbin1009 -> 0 bytes
-rw-r--r--app/assets/images/emoji/vertical_traffic_light.pngbin752 -> 0 bytes
-rw-r--r--app/assets/images/emoji/vhs.pngbin632 -> 0 bytes
-rw-r--r--app/assets/images/emoji/vibration_mode.pngbin683 -> 0 bytes
-rw-r--r--app/assets/images/emoji/video_camera.pngbin1611 -> 0 bytes
-rw-r--r--app/assets/images/emoji/video_game.pngbin765 -> 0 bytes
-rw-r--r--app/assets/images/emoji/violin.pngbin1156 -> 0 bytes
-rw-r--r--app/assets/images/emoji/virgo.pngbin618 -> 0 bytes
-rw-r--r--app/assets/images/emoji/volcano.pngbin1257 -> 0 bytes
-rw-r--r--app/assets/images/emoji/volleyball.pngbin1202 -> 0 bytes
-rw-r--r--app/assets/images/emoji/vs.pngbin604 -> 0 bytes
-rw-r--r--app/assets/images/emoji/vulcan.pngbin1083 -> 0 bytes
-rw-r--r--app/assets/images/emoji/vulcan_tone1.pngbin1083 -> 0 bytes
-rw-r--r--app/assets/images/emoji/vulcan_tone2.pngbin1083 -> 0 bytes
-rw-r--r--app/assets/images/emoji/vulcan_tone3.pngbin1083 -> 0 bytes
-rw-r--r--app/assets/images/emoji/vulcan_tone4.pngbin1083 -> 0 bytes
-rw-r--r--app/assets/images/emoji/vulcan_tone5.pngbin1083 -> 0 bytes
-rw-r--r--app/assets/images/emoji/walking.pngbin1082 -> 0 bytes
-rw-r--r--app/assets/images/emoji/walking_tone1.pngbin1084 -> 0 bytes
-rw-r--r--app/assets/images/emoji/walking_tone2.pngbin1084 -> 0 bytes
-rw-r--r--app/assets/images/emoji/walking_tone3.pngbin1066 -> 0 bytes
-rw-r--r--app/assets/images/emoji/walking_tone4.pngbin1075 -> 0 bytes
-rw-r--r--app/assets/images/emoji/walking_tone5.pngbin1065 -> 0 bytes
-rw-r--r--app/assets/images/emoji/waning_crescent_moon.pngbin1213 -> 0 bytes
-rw-r--r--app/assets/images/emoji/waning_gibbous_moon.pngbin1208 -> 0 bytes
-rw-r--r--app/assets/images/emoji/warning.pngbin565 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wastebasket.pngbin2414 -> 0 bytes
-rw-r--r--app/assets/images/emoji/watch.pngbin785 -> 0 bytes
-rw-r--r--app/assets/images/emoji/water_buffalo.pngbin1536 -> 0 bytes
-rw-r--r--app/assets/images/emoji/water_polo.pngbin1755 -> 0 bytes
-rw-r--r--app/assets/images/emoji/water_polo_tone1.pngbin1758 -> 0 bytes
-rw-r--r--app/assets/images/emoji/water_polo_tone2.pngbin1756 -> 0 bytes
-rw-r--r--app/assets/images/emoji/water_polo_tone3.pngbin1760 -> 0 bytes
-rw-r--r--app/assets/images/emoji/water_polo_tone4.pngbin1749 -> 0 bytes
-rw-r--r--app/assets/images/emoji/water_polo_tone5.pngbin1748 -> 0 bytes
-rw-r--r--app/assets/images/emoji/watermelon.pngbin1275 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wave.pngbin1300 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wave_tone1.pngbin1300 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wave_tone2.pngbin1300 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wave_tone3.pngbin1295 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wave_tone4.pngbin1300 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wave_tone5.pngbin1300 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wavy_dash.pngbin359 -> 0 bytes
-rw-r--r--app/assets/images/emoji/waxing_crescent_moon.pngbin1199 -> 0 bytes
-rw-r--r--app/assets/images/emoji/waxing_gibbous_moon.pngbin1229 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wc.pngbin752 -> 0 bytes
-rw-r--r--app/assets/images/emoji/weary.pngbin871 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wedding.pngbin1260 -> 0 bytes
-rw-r--r--app/assets/images/emoji/whale.pngbin1572 -> 0 bytes
-rw-r--r--app/assets/images/emoji/whale2.pngbin1196 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wheel_of_dharma.pngbin666 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wheelchair.pngbin683 -> 0 bytes
-rw-r--r--app/assets/images/emoji/white_check_mark.pngbin547 -> 0 bytes
-rw-r--r--app/assets/images/emoji/white_circle.pngbin351 -> 0 bytes
-rw-r--r--app/assets/images/emoji/white_flower.pngbin941 -> 0 bytes
-rw-r--r--app/assets/images/emoji/white_large_square.pngbin110 -> 0 bytes
-rw-r--r--app/assets/images/emoji/white_medium_small_square.pngbin110 -> 0 bytes
-rw-r--r--app/assets/images/emoji/white_medium_square.pngbin108 -> 0 bytes
-rw-r--r--app/assets/images/emoji/white_small_square.pngbin108 -> 0 bytes
-rw-r--r--app/assets/images/emoji/white_square_button.pngbin122 -> 0 bytes
-rw-r--r--app/assets/images/emoji/white_sun_cloud.pngbin968 -> 0 bytes
-rw-r--r--app/assets/images/emoji/white_sun_rain_cloud.pngbin1161 -> 0 bytes
-rw-r--r--app/assets/images/emoji/white_sun_small_cloud.pngbin989 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wilted_rose.pngbin1349 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wind_blowing_face.pngbin1827 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wind_chime.pngbin1046 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wine_glass.pngbin655 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wink.pngbin746 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wolf.pngbin1528 -> 0 bytes
-rw-r--r--app/assets/images/emoji/woman.pngbin1212 -> 0 bytes
-rw-r--r--app/assets/images/emoji/woman_tone1.pngbin1212 -> 0 bytes
-rw-r--r--app/assets/images/emoji/woman_tone2.pngbin1212 -> 0 bytes
-rw-r--r--app/assets/images/emoji/woman_tone3.pngbin1202 -> 0 bytes
-rw-r--r--app/assets/images/emoji/woman_tone4.pngbin1195 -> 0 bytes
-rw-r--r--app/assets/images/emoji/woman_tone5.pngbin1202 -> 0 bytes
-rw-r--r--app/assets/images/emoji/womans_clothes.pngbin1042 -> 0 bytes
-rw-r--r--app/assets/images/emoji/womans_hat.pngbin1553 -> 0 bytes
-rw-r--r--app/assets/images/emoji/womens.pngbin577 -> 0 bytes
-rw-r--r--app/assets/images/emoji/worried.pngbin715 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wrench.pngbin418 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wrestlers.pngbin2556 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wrestlers_tone1.pngbin2563 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wrestlers_tone2.pngbin2553 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wrestlers_tone3.pngbin2541 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wrestlers_tone4.pngbin2553 -> 0 bytes
-rw-r--r--app/assets/images/emoji/wrestlers_tone5.pngbin2542 -> 0 bytes
-rw-r--r--app/assets/images/emoji/writing_hand.pngbin1001 -> 0 bytes
-rw-r--r--app/assets/images/emoji/writing_hand_tone1.pngbin988 -> 0 bytes
-rw-r--r--app/assets/images/emoji/writing_hand_tone2.pngbin987 -> 0 bytes
-rw-r--r--app/assets/images/emoji/writing_hand_tone3.pngbin977 -> 0 bytes
-rw-r--r--app/assets/images/emoji/writing_hand_tone4.pngbin973 -> 0 bytes
-rw-r--r--app/assets/images/emoji/writing_hand_tone5.pngbin970 -> 0 bytes
-rw-r--r--app/assets/images/emoji/x.pngbin298 -> 0 bytes
-rw-r--r--app/assets/images/emoji/yellow_heart.pngbin435 -> 0 bytes
-rw-r--r--app/assets/images/emoji/yen.pngbin421 -> 0 bytes
-rw-r--r--app/assets/images/emoji/yin_yang.pngbin776 -> 0 bytes
-rw-r--r--app/assets/images/emoji/yum.pngbin896 -> 0 bytes
-rw-r--r--app/assets/images/emoji/zap.pngbin413 -> 0 bytes
-rw-r--r--app/assets/images/emoji/zero.pngbin560 -> 0 bytes
-rw-r--r--app/assets/images/emoji/zipper_mouth.pngbin722 -> 0 bytes
-rw-r--r--app/assets/images/emoji/zzz.pngbin540 -> 0 bytes
-rw-r--r--app/assets/images/emoji@2x.pngbin2977099 -> 3624162 bytes
-rw-r--r--app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql2
-rw-r--r--app/assets/javascripts/access_tokens/index.js2
-rw-r--r--app/assets/javascripts/admin/deploy_keys/components/table.vue54
-rw-r--r--app/assets/javascripts/admin/deploy_keys/index.js23
-rw-r--r--app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue2
-rw-r--r--app/assets/javascripts/admin/users/index.js2
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_table.vue6
-rw-r--r--app/assets/javascripts/alert_management/list.js3
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue4
-rw-r--r--app/assets/javascripts/alerts_settings/graphql.js1
-rw-r--r--app/assets/javascripts/analytics/devops_report/constants.js11
-rw-r--r--app/assets/javascripts/analytics/devops_reports/components/devops_score.vue (renamed from app/assets/javascripts/analytics/devops_report/components/devops_score.vue)0
-rw-r--r--app/assets/javascripts/analytics/devops_reports/components/devops_score_callout.vue (renamed from app/assets/javascripts/analytics/devops_report/components/devops_score_callout.vue)0
-rw-r--r--app/assets/javascripts/analytics/devops_reports/components/service_ping_disabled.vue (renamed from app/assets/javascripts/analytics/devops_report/components/service_ping_disabled.vue)0
-rw-r--r--app/assets/javascripts/analytics/devops_reports/constants.js11
-rw-r--r--app/assets/javascripts/analytics/devops_reports/devops_score.js (renamed from app/assets/javascripts/analytics/devops_report/devops_score.js)0
-rw-r--r--app/assets/javascripts/analytics/devops_reports/devops_score_disabled_service_ping.js (renamed from app/assets/javascripts/analytics/devops_report/devops_score_disabled_service_ping.js)0
-rw-r--r--app/assets/javascripts/analytics/shared/graphql/projects.query.graphql2
-rw-r--r--app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue4
-rw-r--r--app/assets/javascripts/analytics/usage_trends/index.js2
-rw-r--r--app/assets/javascripts/api/namespaces_api.js13
-rw-r--r--app/assets/javascripts/artifacts_settings/index.js2
-rw-r--r--app/assets/javascripts/authentication/two_factor_auth/components/manage_two_factor_form.vue133
-rw-r--r--app/assets/javascripts/badges/components/badge_settings.vue6
-rw-r--r--app/assets/javascripts/batch_comments/components/draft_note.vue10
-rw-r--r--app/assets/javascripts/batch_comments/components/preview_dropdown.vue4
-rw-r--r--app/assets/javascripts/blob/components/blob_content.vue2
-rw-r--r--app/assets/javascripts/blob/components/blob_header.vue15
-rw-r--r--app/assets/javascripts/blob/components/table_contents.vue5
-rw-r--r--app/assets/javascripts/blob/pipeline_tour_success_modal.vue4
-rw-r--r--app/assets/javascripts/boards/boards_util.js4
-rw-r--r--app/assets/javascripts/boards/components/board_card.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_content_sidebar.vue36
-rw-r--r--app/assets/javascripts/boards/components/board_filtered_search.vue160
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue82
-rw-r--r--app/assets/javascripts/boards/components/board_list_header.vue33
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue88
-rw-r--r--app/assets/javascripts/boards/components/issue_board_filtered_search.vue53
-rw-r--r--app/assets/javascripts/boards/components/new_board_button.vue47
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue6
-rw-r--r--app/assets/javascripts/boards/graphql.js1
-rw-r--r--app/assets/javascripts/boards/graphql/board_list_create.mutation.graphql2
-rw-r--r--app/assets/javascripts/boards/graphql/board_lists.query.graphql2
-rw-r--r--app/assets/javascripts/boards/graphql/board_scope.fragment.graphql6
-rw-r--r--app/assets/javascripts/boards/graphql/group_board.query.graphql9
-rw-r--r--app/assets/javascripts/boards/graphql/group_board_iterations.query.graphql10
-rw-r--r--app/assets/javascripts/boards/graphql/group_projects.query.graphql2
-rw-r--r--app/assets/javascripts/boards/graphql/issue_move_list.mutation.graphql2
-rw-r--r--app/assets/javascripts/boards/graphql/lists_issues.query.graphql2
-rw-r--r--app/assets/javascripts/boards/graphql/project_board.query.graphql9
-rw-r--r--app/assets/javascripts/boards/graphql/project_board_iterations.query.graphql10
-rw-r--r--app/assets/javascripts/boards/graphql/project_milestones.query.graphql2
-rw-r--r--app/assets/javascripts/boards/index.js8
-rw-r--r--app/assets/javascripts/boards/mount_filtered_search_issue_boards.js5
-rw-r--r--app/assets/javascripts/boards/mount_multiple_boards_switcher.js19
-rw-r--r--app/assets/javascripts/boards/new_board.js29
-rw-r--r--app/assets/javascripts/boards/stores/actions.js95
-rw-r--r--app/assets/javascripts/boards/stores/mutation_types.js5
-rw-r--r--app/assets/javascripts/boards/stores/mutations.js18
-rw-r--r--app/assets/javascripts/boards/stores/state.js1
-rw-r--r--app/assets/javascripts/breadcrumb.js18
-rw-r--r--app/assets/javascripts/chronic_duration.js417
-rw-r--r--app/assets/javascripts/ci_lint/index.js4
-rw-r--r--app/assets/javascripts/clusters/agents/components/show.vue1
-rw-r--r--app/assets/javascripts/clusters/agents/index.js2
-rw-r--r--app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue32
-rw-r--r--app/assets/javascripts/clusters_list/clusters_util.js4
-rw-r--r--app/assets/javascripts/clusters_list/components/agent_empty_state.vue81
-rw-r--r--app/assets/javascripts/clusters_list/components/agent_table.vue162
-rw-r--r--app/assets/javascripts/clusters_list/components/agents.vue36
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters.vue54
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters_actions.vue44
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters_empty_state.vue76
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters_main_view.vue73
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters_view_all.vue218
-rw-r--r--app/assets/javascripts/clusters_list/components/install_agent_modal.vue52
-rw-r--r--app/assets/javascripts/clusters_list/constants.js94
-rw-r--r--app/assets/javascripts/clusters_list/graphql/cache_update.js29
-rw-r--r--app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql10
-rw-r--r--app/assets/javascripts/clusters_list/graphql/mutations/create_agent.mutation.graphql4
-rw-r--r--app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql12
-rw-r--r--app/assets/javascripts/clusters_list/index.js4
-rw-r--r--app/assets/javascripts/clusters_list/load_agents.js44
-rw-r--r--app/assets/javascripts/clusters_list/load_clusters.js7
-rw-r--r--app/assets/javascripts/clusters_list/load_main_view.js50
-rw-r--r--app/assets/javascripts/clusters_list/store/actions.js16
-rw-r--r--app/assets/javascripts/clusters_list/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/clusters_list/store/mutations.js5
-rw-r--r--app/assets/javascripts/clusters_list/store/state.js7
-rw-r--r--app/assets/javascripts/confirm_danger_modal.js10
-rw-r--r--app/assets/javascripts/content_editor/components/content_editor.vue6
-rw-r--r--app/assets/javascripts/content_editor/components/content_editor_alert.vue33
-rw-r--r--app/assets/javascripts/content_editor/components/content_editor_error.vue31
-rw-r--r--app/assets/javascripts/content_editor/components/editor_state_observer.vue2
-rw-r--r--app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue22
-rw-r--r--app/assets/javascripts/content_editor/components/wrappers/table_cell_body.vue4
-rw-r--r--app/assets/javascripts/content_editor/components/wrappers/table_cell_header.vue4
-rw-r--r--app/assets/javascripts/content_editor/extensions/blockquote.js12
-rw-r--r--app/assets/javascripts/content_editor/extensions/description_list.js9
-rw-r--r--app/assets/javascripts/content_editor/extensions/details.js9
-rw-r--r--app/assets/javascripts/content_editor/extensions/emoji.js36
-rw-r--r--app/assets/javascripts/content_editor/extensions/frontmatter.js3
-rw-r--r--app/assets/javascripts/content_editor/extensions/horizontal_rule.js6
-rw-r--r--app/assets/javascripts/content_editor/extensions/html_marks.js8
-rw-r--r--app/assets/javascripts/content_editor/extensions/inline_diff.js18
-rw-r--r--app/assets/javascripts/content_editor/extensions/link.js18
-rw-r--r--app/assets/javascripts/content_editor/extensions/math_inline.js6
-rw-r--r--app/assets/javascripts/content_editor/extensions/subscript.js8
-rw-r--r--app/assets/javascripts/content_editor/extensions/superscript.js8
-rw-r--r--app/assets/javascripts/content_editor/extensions/table.js43
-rw-r--r--app/assets/javascripts/content_editor/extensions/table_cell.js3
-rw-r--r--app/assets/javascripts/content_editor/extensions/table_header.js3
-rw-r--r--app/assets/javascripts/content_editor/extensions/table_of_contents.js21
-rw-r--r--app/assets/javascripts/content_editor/extensions/word_break.js6
-rw-r--r--app/assets/javascripts/content_editor/services/feature_flags.js3
-rw-r--r--app/assets/javascripts/content_editor/services/serialization_helpers.js16
-rw-r--r--app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js23
-rw-r--r--app/assets/javascripts/content_editor/services/upload_helpers.js10
-rw-r--r--app/assets/javascripts/contextual_sidebar.js5
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue2
-rw-r--r--app/assets/javascripts/create_merge_request_dropdown.js40
-rw-r--r--app/assets/javascripts/crm/components/contacts_root.vue80
-rw-r--r--app/assets/javascripts/crm/components/organizations_root.vue71
-rw-r--r--app/assets/javascripts/crm/components/queries/get_group_contacts.query.graphql22
-rw-r--r--app/assets/javascripts/crm/components/queries/get_group_organizations.query.graphql15
-rw-r--r--app/assets/javascripts/crm/contacts_bundle.js27
-rw-r--r--app/assets/javascripts/crm/organizations_bundle.js27
-rw-r--r--app/assets/javascripts/cycle_analytics/components/base.vue17
-rw-r--r--app/assets/javascripts/cycle_analytics/components/metric_popover.vue61
-rw-r--r--app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue49
-rw-r--r--app/assets/javascripts/cycle_analytics/constants.js7
-rw-r--r--app/assets/javascripts/cycle_analytics/index.js49
-rw-r--r--app/assets/javascripts/cycle_analytics/store/actions.js69
-rw-r--r--app/assets/javascripts/cycle_analytics/utils.js60
-rw-r--r--app/assets/javascripts/deploy_tokens/components/revoke_button.vue2
-rw-r--r--app/assets/javascripts/design_management/graphql.js1
-rw-r--r--app/assets/javascripts/design_management/pages/index.vue18
-rw-r--r--app/assets/javascripts/diffs/components/app.vue15
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue12
-rw-r--r--app/assets/javascripts/diffs/components/diff_comment_cell.vue6
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue11
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_note_form.vue31
-rw-r--r--app/assets/javascripts/diffs/components/diff_view.vue15
-rw-r--r--app/assets/javascripts/diffs/components/tree_list.vue2
-rw-r--r--app/assets/javascripts/diffs/index.js2
-rw-r--r--app/assets/javascripts/diffs/store/actions.js34
-rw-r--r--app/assets/javascripts/diffs/store/mutation_types.js3
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js6
-rw-r--r--app/assets/javascripts/diffs/utils/diff_line.js10
-rw-r--r--app/assets/javascripts/diffs/utils/discussions.js76
-rw-r--r--app/assets/javascripts/diffs/utils/file_reviews.js2
-rw-r--r--app/assets/javascripts/dropzone_input.js41
-rw-r--r--app/assets/javascripts/editor/constants.js36
-rw-r--r--app/assets/javascripts/editor/extensions/example_source_editor_extension.js116
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_extension_base.js39
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js293
-rw-r--r--app/assets/javascripts/editor/schema/ci.json49
-rw-r--r--app/assets/javascripts/editor/source_editor_extension.js17
-rw-r--r--app/assets/javascripts/editor/source_editor_instance.js271
-rw-r--r--app/assets/javascripts/emoji/index.js1
-rw-r--r--app/assets/javascripts/environments/components/delete_environment_modal.vue4
-rw-r--r--app/assets/javascripts/environments/components/new_environment_folder.vue69
-rw-r--r--app/assets/javascripts/environments/components/new_environments_app.vue47
-rw-r--r--app/assets/javascripts/environments/components/rollback_modal_manager.vue5
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_bundle.js2
-rw-r--r--app/assets/javascripts/environments/graphql/client.js25
-rw-r--r--app/assets/javascripts/environments/graphql/mutations/cancel_auto_stop.mutation.graphql5
-rw-r--r--app/assets/javascripts/environments/graphql/mutations/delete_environment.mutation.graphql5
-rw-r--r--app/assets/javascripts/environments/graphql/mutations/rollback_environment.mutation.graphql5
-rw-r--r--app/assets/javascripts/environments/graphql/mutations/stop_environment.mutation.graphql5
-rw-r--r--app/assets/javascripts/environments/graphql/mutations/update_canary_ingress.mutation.graphql2
-rw-r--r--app/assets/javascripts/environments/graphql/queries/environmentApp.query.graphql8
-rw-r--r--app/assets/javascripts/environments/graphql/queries/folder.query.graphql7
-rw-r--r--app/assets/javascripts/environments/graphql/resolvers.js50
-rw-r--r--app/assets/javascripts/environments/graphql/typedefs.graphql35
-rw-r--r--app/assets/javascripts/environments/index.js69
-rw-r--r--app/assets/javascripts/environments/mixins/environments_mixin.js6
-rw-r--r--app/assets/javascripts/environments/new_index.js38
-rw-r--r--app/assets/javascripts/error_tracking/components/stacktrace_entry.vue5
-rw-r--r--app/assets/javascripts/experimentation/utils.js23
-rw-r--r--app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue1
-rw-r--r--app/assets/javascripts/flash.js4
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue3
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js24
-rw-r--r--app/assets/javascripts/google_cloud/components/app.vue50
-rw-r--r--app/assets/javascripts/google_cloud/components/incubation_banner.vue44
-rw-r--r--app/assets/javascripts/google_cloud/components/service_accounts.vue65
-rw-r--r--app/assets/javascripts/google_cloud/index.js11
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/iteration.fragment.graphql4
-rw-r--r--app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql5
-rw-r--r--app/assets/javascripts/graphql_shared/queries/project_user_members_search.query.graphql1
-rw-r--r--app/assets/javascripts/graphql_shared/queries/users_search.query.graphql2
-rw-r--r--app/assets/javascripts/graphql_shared/utils.js8
-rw-r--r--app/assets/javascripts/group.js4
-rw-r--r--app/assets/javascripts/group_settings/components/shared_runners_form.vue41
-rw-r--r--app/assets/javascripts/group_settings/constants.js5
-rw-r--r--app/assets/javascripts/group_settings/mount_shared_runners.js21
-rw-r--r--app/assets/javascripts/groups/components/item_caret.vue2
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail.vue5
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue4
-rw-r--r--app/assets/javascripts/ide/components/pipelines/list.vue2
-rw-r--r--app/assets/javascripts/ide/components/shared/commit_message_field.vue137
-rw-r--r--app/assets/javascripts/ide/constants.js2
-rw-r--r--app/assets/javascripts/import_entities/components/group_dropdown.vue2
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue33
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_source_cell.vue14
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_table.vue310
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue84
-rw-r--r--app/assets/javascripts/import_entities/import_groups/constants.js15
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js406
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_item.fragment.graphql23
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/mutations/add_validation_error.mutation.graphql9
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql9
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/mutations/remove_validation_error.mutation.graphql9
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/mutations/set_import_progress.mutation.graphql23
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/mutations/set_import_target.mutation.graphql13
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/queries/available_namespaces.query.graphql2
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_group.query.graphql7
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/queries/group_and_project.query.graphql9
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js74
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js87
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js35
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql52
-rw-r--r--app/assets/javascripts/import_entities/import_groups/index.js4
-rw-r--r--app/assets/javascripts/import_entities/import_groups/services/status_poller.js39
-rw-r--r--app/assets/javascripts/import_entities/import_groups/utils.js23
-rw-r--r--app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue6
-rw-r--r--app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue10
-rw-r--r--app/assets/javascripts/incidents/components/incidents_list.vue11
-rw-r--r--app/assets/javascripts/incidents/constants.js5
-rw-r--r--app/assets/javascripts/incidents/list.js4
-rw-r--r--app/assets/javascripts/init_confirm_danger.js38
-rw-r--r--app/assets/javascripts/integrations/constants.js8
-rw-r--r--app/assets/javascripts/integrations/edit/components/dynamic_field.vue10
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue53
-rw-r--r--app/assets/javascripts/integrations/integration_settings_form.js16
-rw-r--r--app/assets/javascripts/invite_members/components/confetti.vue33
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue232
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_trigger.vue27
-rw-r--r--app/assets/javascripts/invite_members/constants.js127
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_modal.js19
-rw-r--r--app/assets/javascripts/issuable/components/issuable_by_email.vue2
-rw-r--r--app/assets/javascripts/issuable_suggestions/index.js7
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue29
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue14
-rw-r--r--app/assets/javascripts/issue_show/components/fields/type.vue17
-rw-r--r--app/assets/javascripts/issue_show/components/header_actions.vue7
-rw-r--r--app/assets/javascripts/issue_show/constants.js7
-rw-r--r--app/assets/javascripts/issue_show/incident.js56
-rw-r--r--app/assets/javascripts/issue_show/issue.js7
-rw-r--r--app/assets/javascripts/issues_list/components/issues_list_app.vue26
-rw-r--r--app/assets/javascripts/issues_list/components/new_issue_dropdown.vue7
-rw-r--r--app/assets/javascripts/issues_list/constants.js28
-rw-r--r--app/assets/javascripts/issues_list/index.js6
-rw-r--r--app/assets/javascripts/issues_list/queries/get_issues.query.graphql10
-rw-r--r--app/assets/javascripts/issues_list/queries/get_issues_counts.query.graphql22
-rw-r--r--app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql2
-rw-r--r--app/assets/javascripts/issues_list/queries/iteration.fragment.graphql6
-rw-r--r--app/assets/javascripts/issues_list/queries/search_projects.query.graphql1
-rw-r--r--app/assets/javascripts/issues_list/service_desk_helper.js8
-rw-r--r--app/assets/javascripts/issues_list/utils.js34
-rw-r--r--app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql2
-rw-r--r--app/assets/javascripts/jira_connect/branches/index.js7
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_button.vue24
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal.vue26
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue (renamed from app/assets/javascripts/jira_connect/subscriptions/components/groups_list.vue)0
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue85
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/app.vue112
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/groups_list_item.vue85
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue36
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/subscriptions_list.vue54
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/constants.js2
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/index.js16
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/utils.js15
-rw-r--r--app/assets/javascripts/jira_import/index.js2
-rw-r--r--app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql2
-rw-r--r--app/assets/javascripts/jira_import/queries/get_jira_user_mapping.mutation.graphql2
-rw-r--r--app/assets/javascripts/jira_import/queries/initiate_jira_import.mutation.graphql2
-rw-r--r--app/assets/javascripts/jira_import/queries/search_project_members.query.graphql2
-rw-r--r--app/assets/javascripts/jobs/components/manual_variables_form.vue229
-rw-r--r--app/assets/javascripts/jobs/components/trigger_block.vue8
-rw-r--r--app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js4
-rw-r--r--app/assets/javascripts/lib/graphql.js5
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js27
-rw-r--r--app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue47
-rw-r--r--app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js55
-rw-r--r--app/assets/javascripts/lib/utils/constants.js2
-rw-r--r--app/assets/javascripts/lib/utils/datetime/date_format_utility.js48
-rw-r--r--app/assets/javascripts/lib/utils/file_upload.js20
-rw-r--r--app/assets/javascripts/lib/utils/rails_ujs.js38
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js2
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js6
-rw-r--r--app/assets/javascripts/logs/components/environment_logs.vue2
-rw-r--r--app/assets/javascripts/members/components/app.vue5
-rw-r--r--app/assets/javascripts/monitoring/components/alert_widget.vue285
-rw-r--r--app/assets/javascripts/monitoring/components/alert_widget_form.vue324
-rw-r--r--app/assets/javascripts/monitoring/components/charts/empty_chart.vue7
-rw-r--r--app/assets/javascripts/monitoring/components/charts/time_series.vue6
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue6
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel.vue106
-rw-r--r--app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue2
-rw-r--r--app/assets/javascripts/monitoring/monitoring_app.js6
-rw-r--r--app/assets/javascripts/monitoring/utils.js1
-rw-r--r--app/assets/javascripts/mr_notes/index.js4
-rw-r--r--app/assets/javascripts/mr_popover/index.js7
-rw-r--r--app/assets/javascripts/nav/components/responsive_home.vue1
-rw-r--r--app/assets/javascripts/nav/components/top_nav_new_dropdown.vue1
-rw-r--r--app/assets/javascripts/network/branch_graph.js2
-rw-r--r--app/assets/javascripts/notebook/cells/output/latex.vue11
-rw-r--r--app/assets/javascripts/notes/components/discussion_counter.vue4
-rw-r--r--app/assets/javascripts/notes/components/discussion_notes.vue90
-rw-r--r--app/assets/javascripts/notes/components/multiline_comment_form.vue6
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue13
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue32
-rw-r--r--app/assets/javascripts/notes/components/notes_app.vue18
-rw-r--r--app/assets/javascripts/notes/mixins/discussion_navigation.js56
-rw-r--r--app/assets/javascripts/notes/stores/actions.js46
-rw-r--r--app/assets/javascripts/notes/stores/mutation_types.js2
-rw-r--r--app/assets/javascripts/notes/stores/mutations.js41
-rw-r--r--app/assets/javascripts/packages/list/components/package_search.vue57
-rw-r--r--app/assets/javascripts/packages/list/components/package_title.vue47
-rw-r--r--app/assets/javascripts/packages/list/components/packages_list_app.vue28
-rw-r--r--app/assets/javascripts/packages/list/components/tokens/package_type_token.vue26
-rw-r--r--app/assets/javascripts/packages/list/constants.js6
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/delete_button.vue (renamed from app/assets/javascripts/registry/explorer/components/delete_button.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/delete_image.vue (renamed from app/assets/javascripts/registry/explorer/components/delete_image.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/delete_alert.vue (renamed from app/assets/javascripts/registry/explorer/components/details_page/delete_alert.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/delete_modal.vue (renamed from app/assets/javascripts/registry/explorer/components/details_page/delete_modal.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue (renamed from app/assets/javascripts/registry/explorer/components/details_page/details_header.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/empty_state.vue (renamed from app/assets/javascripts/registry/explorer/components/details_page/empty_state.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert.vue (renamed from app/assets/javascripts/registry/explorer/components/details_page/partial_cleanup_alert.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/status_alert.vue (renamed from app/assets/javascripts/registry/explorer/components/details_page/status_alert.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue (renamed from app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue (renamed from app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue (renamed from app/assets/javascripts/registry/explorer/components/details_page/tags_loader.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue (renamed from app/assets/javascripts/registry/explorer/components/list_page/cleanup_status.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cli_commands.vue (renamed from app/assets/javascripts/registry/explorer/components/list_page/cli_commands.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state.vue (renamed from app/assets/javascripts/registry/explorer/components/list_page/group_empty_state.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list.vue (renamed from app/assets/javascripts/registry/explorer/components/list_page/image_list.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue (renamed from app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state.vue (renamed from app/assets/javascripts/registry/explorer/components/list_page/project_empty_state.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue (renamed from app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/registry_breadcrumb.vue (renamed from app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/common.js (renamed from app/assets/javascripts/registry/explorer/constants/common.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/details.js (renamed from app/assets/javascripts/registry/explorer/constants/details.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/expiration_policies.js (renamed from app/assets/javascripts/registry/explorer/constants/expiration_policies.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/index.js (renamed from app/assets/javascripts/registry/explorer/constants/index.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/list.js (renamed from app/assets/javascripts/registry/explorer/constants/list.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/quick_start.js (renamed from app/assets/javascripts/registry/explorer/constants/quick_start.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/index.js14
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql (renamed from app/assets/javascripts/registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql (renamed from app/assets/javascripts/registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repositories_details.query.graphql (renamed from app/assets/javascripts/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql (renamed from app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_details.query.graphql)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql (renamed from app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_tags.query.graphql)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags_count.query.graphql (renamed from app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_tags_count.query.graphql)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js (renamed from app/assets/javascripts/registry/explorer/index.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue (renamed from app/assets/javascripts/registry/explorer/pages/details.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/index.vue (renamed from app/assets/javascripts/registry/explorer/pages/index.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue (renamed from app/assets/javascripts/registry/explorer/pages/list.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/router.js (renamed from app/assets/javascripts/registry/explorer/router.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue87
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifest_row.vue49
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue52
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/constants.js1
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/index.js7
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql19
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue86
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/functional/delete_package.vue62
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/list/app.vue116
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue2
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/list/package_title.vue10
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue100
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/list/tokens/package_type_token.vue6
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/constants.js63
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js1
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql31
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/utils.js8
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue1
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js7
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/graphql/index.js7
-rw-r--r--app/assets/javascripts/pages/admin/deploy_keys/index/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/dev_ops_report/index.js4
-rw-r--r--app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue4
-rw-r--r--app/assets/javascripts/pages/dashboard/todos/index/todos.js8
-rw-r--r--app/assets/javascripts/pages/groups/crm/contacts/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/crm/organizations/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/new/components/app.vue2
-rw-r--r--app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue2
-rw-r--r--app/assets/javascripts/pages/groups/new/fetch_group_path_availability.js12
-rw-r--r--app/assets/javascripts/pages/groups/new/group_path_validator.js4
-rw-r--r--app/assets/javascripts/pages/groups/packages/index/index.js11
-rw-r--r--app/assets/javascripts/pages/groups/registry/repositories/index.js2
-rw-r--r--app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue4
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/edit/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/environments/index/index.js10
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue6
-rw-r--r--app/assets/javascripts/pages/projects/google_cloud/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/issues/show.js6
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue14
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue1
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/index/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js1
-rw-r--r--app/assets/javascripts/pages/projects/packages/packages/index/index.js11
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue6
-rw-r--r--app/assets/javascripts/pages/projects/project.js8
-rw-r--r--app/assets/javascripts/pages/projects/registry/repositories/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue17
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue7
-rw-r--r--app/assets/javascripts/pages/projects/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/work_items/index.js (renamed from app/assets/javascripts/pages/projects/work_items/index/index.js)0
-rw-r--r--app/assets/javascripts/pages/shared/mount_runner_instructions.js7
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue18
-rw-r--r--app/assets/javascripts/pages/shared/wikis/constants.js5
-rw-r--r--app/assets/javascripts/pages/users/activity_calendar.js11
-rw-r--r--app/assets/javascripts/pages/users/terms/index/index.js4
-rw-r--r--app/assets/javascripts/performance_bar/components/detailed_metric.vue4
-rw-r--r--app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue16
-rw-r--r--app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue23
-rw-r--r--app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue14
-rw-r--r--app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue49
-rw-r--r--app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue18
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue1
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_mini_graph.vue52
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue56
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue2
-rw-r--r--app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue53
-rw-r--r--app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_messages.vue7
-rw-r--r--app/assets/javascripts/pipeline_editor/components/walkthrough_popover.vue83
-rw-r--r--app/assets/javascripts/pipeline_editor/constants.js17
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/update_app_status.mutation.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/update_pipeline_etag.mutation.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/is_new_ci_config_file.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql5
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/resolvers.js23
-rw-r--r--app/assets/javascripts/pipeline_editor/index.js11
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue51
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue70
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue58
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue8
-rw-r--r--app/assets/javascripts/pipelines/constants.js2
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql3
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines_mixin.js7
-rw-r--r--app/assets/javascripts/pipelines/pipeline_shared_client.js1
-rw-r--r--app/assets/javascripts/profile/account/components/delete_account_modal.vue4
-rw-r--r--app/assets/javascripts/profile/account/components/update_username.vue6
-rw-r--r--app/assets/javascripts/project_visibility.js62
-rw-r--r--app/assets/javascripts/projects/commit/components/form_modal.vue10
-rw-r--r--app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js3
-rw-r--r--app/assets/javascripts/projects/commit/init_revert_commit_modal.js3
-rw-r--r--app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js7
-rw-r--r--app/assets/javascripts/projects/components/project_delete_button.vue58
-rw-r--r--app/assets/javascripts/projects/default_project_templates.js4
-rw-r--r--app/assets/javascripts/projects/details/upload_button.vue7
-rw-r--r--app/assets/javascripts/projects/new/components/app.vue2
-rw-r--r--app/assets/javascripts/projects/new/components/new_project_url_select.vue27
-rw-r--r--app/assets/javascripts/projects/new/index.js2
-rw-r--r--app/assets/javascripts/projects/new/queries/search_namespaces_where_user_can_create_projects.query.graphql3
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/app.vue12
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/index.js4
-rw-r--r--app/assets/javascripts/projects/project_delete_button.js16
-rw-r--r--app/assets/javascripts/projects/project_new.js7
-rw-r--r--app/assets/javascripts/projects/settings/topics/components/topics_token_selector.vue92
-rw-r--r--app/assets/javascripts/projects/settings/topics/index.js51
-rw-r--r--app/assets/javascripts/projects/settings/topics/queries/project_topics_search.query.graphql9
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue7
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue60
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_template_dropdown.vue115
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/index.js2
-rw-r--r--app/assets/javascripts/projects/storage_counter/components/storage_table.vue62
-rw-r--r--app/assets/javascripts/projects/storage_counter/components/storage_type_icon.vue35
-rw-r--r--app/assets/javascripts/projects/storage_counter/constants.js12
-rw-r--r--app/assets/javascripts/projects/storage_counter/index.js2
-rw-r--r--app/assets/javascripts/projects/storage_counter/utils.js4
-rw-r--r--app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue2
-rw-r--r--app/assets/javascripts/projects/upload_file.js33
-rw-r--r--app/assets/javascripts/projects/upload_file_experiment.js33
-rw-r--r--app/assets/javascripts/projects/upload_file_experiment_tracking.js9
-rw-r--r--app/assets/javascripts/ref/constants.js4
-rw-r--r--app/assets/javascripts/registry/explorer/graphql/index.js15
-rw-r--r--app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue87
-rw-r--r--app/assets/javascripts/related_merge_requests/store/actions.js4
-rw-r--r--app/assets/javascripts/releases/components/tag_field_new.vue7
-rw-r--r--app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql2
-rw-r--r--app/assets/javascripts/releases/mount_index.js1
-rw-r--r--app/assets/javascripts/releases/mount_show.js7
-rw-r--r--app/assets/javascripts/repository/components/blob_content_viewer.vue19
-rw-r--r--app/assets/javascripts/repository/components/delete_blob_modal.vue13
-rw-r--r--app/assets/javascripts/repository/components/last_commit.vue19
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue4
-rw-r--r--app/assets/javascripts/repository/components/tree_content.vue27
-rw-r--r--app/assets/javascripts/repository/components/upload_blob_modal.vue4
-rw-r--r--app/assets/javascripts/repository/graphql.js1
-rw-r--r--app/assets/javascripts/repository/mixins/preload.js3
-rw-r--r--app/assets/javascripts/repository/queries/blob_info.query.graphql1
-rw-r--r--app/assets/javascripts/rest_api.js1
-rw-r--r--app/assets/javascripts/right_sidebar.js7
-rw-r--r--app/assets/javascripts/runner/admin_runners/admin_runners_app.vue87
-rw-r--r--app/assets/javascripts/runner/admin_runners/index.js29
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_actions_cell.vue4
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_status_cell.vue40
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_summary_cell.vue27
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_type_cell.vue47
-rw-r--r--app/assets/javascripts/runner/components/helpers/masked_value.vue60
-rw-r--r--app/assets/javascripts/runner/components/registration/registration_dropdown.vue112
-rw-r--r--app/assets/javascripts/runner/components/registration/registration_token.vue83
-rw-r--r--app/assets/javascripts/runner/components/registration/registration_token_reset_dropdown_item.vue113
-rw-r--r--app/assets/javascripts/runner/components/runner_contacted_state_badge.vue69
-rw-r--r--app/assets/javascripts/runner/components/runner_filtered_search_bar.vue27
-rw-r--r--app/assets/javascripts/runner/components/runner_list.vue39
-rw-r--r--app/assets/javascripts/runner/components/runner_manual_setup_help.vue108
-rw-r--r--app/assets/javascripts/runner/components/runner_paused_badge.vue (renamed from app/assets/javascripts/runner/components/runner_state_paused_badge.vue)0
-rw-r--r--app/assets/javascripts/runner/components/runner_registration_token_reset.vue114
-rw-r--r--app/assets/javascripts/runner/components/runner_state_locked_badge.vue25
-rw-r--r--app/assets/javascripts/runner/components/runner_tag.vue35
-rw-r--r--app/assets/javascripts/runner/components/runner_tags.vue10
-rw-r--r--app/assets/javascripts/runner/components/runner_type_alert.vue5
-rw-r--r--app/assets/javascripts/runner/components/runner_type_badge.vue5
-rw-r--r--app/assets/javascripts/runner/components/runner_type_tabs.vue66
-rw-r--r--app/assets/javascripts/runner/components/search_tokens/status_token_config.js28
-rw-r--r--app/assets/javascripts/runner/components/search_tokens/type_token_config.js20
-rw-r--r--app/assets/javascripts/runner/constants.js16
-rw-r--r--app/assets/javascripts/runner/graphql/runner_actions_update.mutation.graphql14
-rw-r--r--app/assets/javascripts/runner/graphql/runner_node.fragment.graphql3
-rw-r--r--app/assets/javascripts/runner/graphql/runner_update.mutation.graphql3
-rw-r--r--app/assets/javascripts/runner/group_runners/group_runners_app.vue24
-rw-r--r--app/assets/javascripts/runner/group_runners/index.js9
-rw-r--r--app/assets/javascripts/runner/runner_details/index.js7
-rw-r--r--app/assets/javascripts/runner/runner_search_utils.js88
-rw-r--r--app/assets/javascripts/search/sidebar/components/app.vue6
-rw-r--r--app/assets/javascripts/search/sidebar/components/radio_filter.vue4
-rw-r--r--app/assets/javascripts/search/sidebar/constants/state_filter_data.js2
-rw-r--r--app/assets/javascripts/search/store/actions.js10
-rw-r--r--app/assets/javascripts/search/store/constants.js5
-rw-r--r--app/assets/javascripts/search/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/search/store/mutations.js3
-rw-r--r--app/assets/javascripts/search/store/state.js3
-rw-r--r--app/assets/javascripts/search/store/utils.js12
-rw-r--r--app/assets/javascripts/security_configuration/components/app.vue22
-rw-r--r--app/assets/javascripts/security_configuration/components/constants.js51
-rw-r--r--app/assets/javascripts/security_configuration/components/feature_card.vue6
-rw-r--r--app/assets/javascripts/security_configuration/graphql/configure_iac.mutation.graphql6
-rw-r--r--app/assets/javascripts/security_configuration/index.js2
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees.vue10
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue50
-rw-r--r--app/assets/javascripts/sidebar/components/attention_requested_toggle.vue74
-rw-r--r--app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue9
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/reviewers.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue17
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_editable_item.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/report.vue8
-rw-r--r--app/assets/javascripts/sidebar/constants.js28
-rw-r--r--app/assets/javascripts/sidebar/graphql.js1
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js4
-rw-r--r--app/assets/javascripts/sidebar/queries/sidebarDetails.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/toggle_attention_requested.mutation.graphql7
-rw-r--r--app/assets/javascripts/sidebar/queries/updateStatus.mutation.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/update_epic_confidential.mutation.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/update_epic_subscription.mutation.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/update_issue_subscription.mutation.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql1
-rw-r--r--app/assets/javascripts/sidebar/services/sidebar_service.js12
-rw-r--r--app/assets/javascripts/sidebar/sidebar_mediator.js43
-rw-r--r--app/assets/javascripts/sidebar/stores/sidebar_store.js12
-rw-r--r--app/assets/javascripts/snippets/index.js1
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/index.js1
-rw-r--r--app/assets/javascripts/static_site_editor/pages/success.vue2
-rw-r--r--app/assets/javascripts/task_list.js2
-rw-r--r--app/assets/javascripts/terms/components/app.vue117
-rw-r--r--app/assets/javascripts/terms/index.js23
-rw-r--r--app/assets/javascripts/token_access/index.js2
-rw-r--r--app/assets/javascripts/user_lists/components/user_lists_table.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue77
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue74
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/messages.js4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_list.vue3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue28
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue5
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue24
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue28
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue41
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/new_ready_to_merge.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue254
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue16
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue32
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/constants.js6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues.js12
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/index.js7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue13
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/work_in_progress.query.graphql9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/toggle_wip.mutation.graphql10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js6
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue7
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql2
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/index.js1
-rw-r--r--app/assets/javascripts/vue_shared/components/alerts_deprecation_warning.vue46
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_badge_link.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue54
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.stories.js28
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue104
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_danger/constants.js12
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue97
-rw-r--r--app/assets/javascripts/vue_shared/components/file_icon.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js1
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue65
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue85
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue60
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue14
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue65
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/title_area.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/constants.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue29
-rw-r--r--app/assets/javascripts/vue_shared/components/settings/settings_block.vue17
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js7
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/constants.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue106
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue49
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue64
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_footer.vue35
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue82
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql7
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql7
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql15
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/group_labels.query.graphql10
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql7
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql14
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql8
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue184
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_timelogs.query.graphql2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_timelogs.query.graphql2
-rw-r--r--app/assets/javascripts/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.vue4
-rw-r--r--app/assets/javascripts/vue_shared/constants.js3
-rw-r--r--app/assets/javascripts/vue_shared/directives/validation.js6
-rw-r--r--app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue2
-rw-r--r--app/assets/javascripts/vue_shared/security_configuration/provider.js2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue10
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/constants.js1
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js1
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js1
-rw-r--r--app/assets/javascripts/work_items/components/app.vue10
-rw-r--r--app/assets/javascripts/work_items/constants.js3
-rw-r--r--app/assets/javascripts/work_items/graphql/fragmentTypes.json1
-rw-r--r--app/assets/javascripts/work_items/graphql/provider.js55
-rw-r--r--app/assets/javascripts/work_items/graphql/resolvers.js0
-rw-r--r--app/assets/javascripts/work_items/graphql/typedefs.graphql38
-rw-r--r--app/assets/javascripts/work_items/graphql/widget.fragment.graphql3
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item.query.graphql16
-rw-r--r--app/assets/javascripts/work_items/index.js4
-rw-r--r--app/assets/javascripts/work_items/pages/work_item_root.vue48
-rw-r--r--app/assets/javascripts/work_items/router/index.js14
-rw-r--r--app/assets/javascripts/work_items/router/routes.js8
-rw-r--r--app/assets/stylesheets/emoji_sprites.scss54
-rw-r--r--app/assets/stylesheets/framework.scss1
-rw-r--r--app/assets/stylesheets/framework/files.scss32
-rw-r--r--app/assets/stylesheets/framework/kbd.scss16
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss6
-rw-r--r--app/assets/stylesheets/framework/terms.scss60
-rw-r--r--app/assets/stylesheets/highlight/common.scss9
-rw-r--r--app/assets/stylesheets/mailer.scss4
-rw-r--r--app/assets/stylesheets/page_bundles/boards.scss4
-rw-r--r--app/assets/stylesheets/page_bundles/jira_connect.scss2
-rw-r--r--app/assets/stylesheets/page_bundles/terms.scss64
-rw-r--r--app/assets/stylesheets/pages/clusters.scss29
-rw-r--r--app/assets/stylesheets/pages/deploy_keys.scss9
-rw-r--r--app/assets/stylesheets/pages/issuable.scss2
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss4
-rw-r--r--app/assets/stylesheets/startup/_cloaking.scss2
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss12
-rw-r--r--app/assets/stylesheets/startup/startup-general.scss2
-rw-r--r--app/assets/stylesheets/startup/startup-signin.scss2
-rw-r--r--app/assets/stylesheets/themes/dark_mode_overrides.scss22
-rw-r--r--app/assets/stylesheets/themes/theme_blue.scss2
-rw-r--r--app/assets/stylesheets/themes/theme_dark.scss2
-rw-r--r--app/assets/stylesheets/themes/theme_green.scss2
-rw-r--r--app/assets/stylesheets/themes/theme_indigo.scss2
-rw-r--r--app/assets/stylesheets/themes/theme_light.scss2
-rw-r--r--app/assets/stylesheets/themes/theme_light_blue.scss2
-rw-r--r--app/assets/stylesheets/themes/theme_light_green.scss2
-rw-r--r--app/assets/stylesheets/themes/theme_light_indigo.scss2
-rw-r--r--app/assets/stylesheets/themes/theme_light_red.scss2
-rw-r--r--app/assets/stylesheets/themes/theme_red.scss2
-rw-r--r--app/assets/stylesheets/utilities.scss16
-rw-r--r--app/controllers/admin/application_settings_controller.rb4
-rw-r--r--app/controllers/admin/applications_controller.rb3
-rw-r--r--app/controllers/admin/hook_logs_controller.rb3
-rw-r--r--app/controllers/admin/hooks_controller.rb5
-rw-r--r--app/controllers/admin/integrations_controller.rb2
-rw-r--r--app/controllers/admin/labels_controller.rb2
-rw-r--r--app/controllers/admin/runners_controller.rb10
-rw-r--r--app/controllers/application_controller.rb3
-rw-r--r--app/controllers/autocomplete_controller.rb2
-rw-r--r--app/controllers/boards/issues_controller.rb2
-rw-r--r--app/controllers/boards/lists_controller.rb2
-rw-r--r--app/controllers/concerns/gitlab_recaptcha.rb22
-rw-r--r--app/controllers/concerns/group_tree.rb8
-rw-r--r--app/controllers/concerns/hooks_execution.rb47
-rw-r--r--app/controllers/concerns/integrations/actions.rb73
-rw-r--r--app/controllers/concerns/integrations/hooks_execution.rb47
-rw-r--r--app/controllers/concerns/integrations/params.rb4
-rw-r--r--app/controllers/concerns/integrations_actions.rb71
-rw-r--r--app/controllers/concerns/issuable_actions.rb35
-rw-r--r--app/controllers/concerns/oauth_applications.rb10
-rw-r--r--app/controllers/concerns/one_trust_csp.rb2
-rw-r--r--app/controllers/concerns/workhorse_authorization.rb6
-rw-r--r--app/controllers/confirmations_controller.rb10
-rw-r--r--app/controllers/dashboard/labels_controller.rb2
-rw-r--r--app/controllers/dashboard/milestones_controller.rb2
-rw-r--r--app/controllers/dashboard/todos_controller.rb2
-rw-r--r--app/controllers/dashboard_controller.rb2
-rw-r--r--app/controllers/explore/projects_controller.rb22
-rw-r--r--app/controllers/graphql_controller.rb1
-rw-r--r--app/controllers/groups/autocomplete_sources_controller.rb2
-rw-r--r--app/controllers/groups/boards_controller.rb6
-rw-r--r--app/controllers/groups/crm_controller.rb30
-rw-r--r--app/controllers/groups/dependency_proxy_for_containers_controller.rb88
-rw-r--r--app/controllers/groups/email_campaigns_controller.rb7
-rw-r--r--app/controllers/groups/labels_controller.rb2
-rw-r--r--app/controllers/groups/milestones_controller.rb2
-rw-r--r--app/controllers/groups/packages_controller.rb4
-rw-r--r--app/controllers/groups/settings/applications_controller.rb3
-rw-r--r--app/controllers/groups/settings/integrations_controller.rb2
-rw-r--r--app/controllers/groups_controller.rb10
-rw-r--r--app/controllers/help_controller.rb2
-rw-r--r--app/controllers/import/bitbucket_controller.rb4
-rw-r--r--app/controllers/invites_controller.rb2
-rw-r--r--app/controllers/jira_connect/app_descriptor_controller.rb2
-rw-r--r--app/controllers/jira_connect/application_controller.rb4
-rw-r--r--app/controllers/jira_connect/events_controller.rb7
-rw-r--r--app/controllers/jira_connect/subscriptions_controller.rb4
-rw-r--r--app/controllers/jwks_controller.rb10
-rw-r--r--app/controllers/oauth/applications_controller.rb6
-rw-r--r--app/controllers/passwords_controller.rb10
-rw-r--r--app/controllers/profiles/two_factor_auths_controller.rb4
-rw-r--r--app/controllers/profiles_controller.rb2
-rw-r--r--app/controllers/projects/alert_management_controller.rb4
-rw-r--r--app/controllers/projects/alerting/notifications_controller.rb6
-rw-r--r--app/controllers/projects/autocomplete_sources_controller.rb2
-rw-r--r--app/controllers/projects/badges_controller.rb3
-rw-r--r--app/controllers/projects/blame_controller.rb1
-rw-r--r--app/controllers/projects/blob_controller.rb1
-rw-r--r--app/controllers/projects/boards_controller.rb6
-rw-r--r--app/controllers/projects/branches_controller.rb4
-rw-r--r--app/controllers/projects/ci/pipeline_editor_controller.rb9
-rw-r--r--app/controllers/projects/cluster_agents_controller.rb6
-rw-r--r--app/controllers/projects/commit_controller.rb1
-rw-r--r--app/controllers/projects/commits_controller.rb7
-rw-r--r--app/controllers/projects/compare_controller.rb1
-rw-r--r--app/controllers/projects/cycle_analytics_controller.rb12
-rw-r--r--app/controllers/projects/discussions_controller.rb2
-rw-r--r--app/controllers/projects/environments_controller.rb4
-rw-r--r--app/controllers/projects/find_file_controller.rb1
-rw-r--r--app/controllers/projects/forks_controller.rb1
-rw-r--r--app/controllers/projects/google_cloud_controller.rb26
-rw-r--r--app/controllers/projects/graphs_controller.rb5
-rw-r--r--app/controllers/projects/hook_logs_controller.rb3
-rw-r--r--app/controllers/projects/hooks_controller.rb5
-rw-r--r--app/controllers/projects/issue_links_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb7
-rw-r--r--app/controllers/projects/jobs_controller.rb8
-rw-r--r--app/controllers/projects/labels_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests_controller.rb6
-rw-r--r--app/controllers/projects/metrics_dashboard_controller.rb1
-rw-r--r--app/controllers/projects/milestones_controller.rb2
-rw-r--r--app/controllers/projects/network_controller.rb1
-rw-r--r--app/controllers/projects/notes_controller.rb10
-rw-r--r--app/controllers/projects/packages/packages_controller.rb4
-rw-r--r--app/controllers/projects/prometheus/alerts_controller.rb6
-rw-r--r--app/controllers/projects/refs_controller.rb1
-rw-r--r--app/controllers/projects/releases/evidences_controller.rb1
-rw-r--r--app/controllers/projects/releases_controller.rb3
-rw-r--r--app/controllers/projects/services_controller.rb1
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb3
-rw-r--r--app/controllers/projects/settings/repository_controller.rb1
-rw-r--r--app/controllers/projects/tags_controller.rb26
-rw-r--r--app/controllers/projects/templates_controller.rb1
-rw-r--r--app/controllers/projects/todos_controller.rb2
-rw-r--r--app/controllers/projects/tree_controller.rb3
-rw-r--r--app/controllers/projects/usage_quotas_controller.rb7
-rw-r--r--app/controllers/projects/wikis_controller.rb6
-rw-r--r--app/controllers/projects_controller.rb16
-rw-r--r--app/controllers/registrations/welcome_controller.rb17
-rw-r--r--app/controllers/repositories/lfs_api_controller.rb1
-rw-r--r--app/controllers/repositories/lfs_storage_controller.rb2
-rw-r--r--app/controllers/search_controller.rb3
-rw-r--r--app/experiments/change_continuous_onboarding_link_urls_experiment.rb9
-rw-r--r--app/experiments/templates/new_project_readme_content/readme_advanced.md.tt4
-rw-r--r--app/finders/autocomplete/routes_finder.rb2
-rw-r--r--app/finders/award_emojis_finder.rb2
-rw-r--r--app/finders/ci/pipelines_finder.rb17
-rw-r--r--app/finders/ci/pipelines_for_merge_request_finder.rb66
-rw-r--r--app/finders/clusters/agent_authorizations_finder.rb65
-rw-r--r--app/finders/environments/environments_by_deployments_finder.rb16
-rw-r--r--app/finders/events_finder.rb5
-rw-r--r--app/finders/issuables/label_filter.rb8
-rw-r--r--app/finders/members_finder.rb15
-rw-r--r--app/finders/packages/group_packages_finder.rb2
-rw-r--r--app/finders/packages/package_finder.rb2
-rw-r--r--app/finders/packages/packages_finder.rb3
-rw-r--r--app/finders/security/security_jobs_finder.rb2
-rw-r--r--app/finders/snippets_finder.rb27
-rw-r--r--app/finders/tags_finder.rb35
-rw-r--r--app/graphql/gitlab_schema.rb8
-rw-r--r--app/graphql/mutations/customer_relations/contacts/create.rb4
-rw-r--r--app/graphql/mutations/customer_relations/contacts/update.rb4
-rw-r--r--app/graphql/mutations/customer_relations/organizations/create.rb4
-rw-r--r--app/graphql/mutations/customer_relations/organizations/update.rb4
-rw-r--r--app/graphql/mutations/issues/create.rb9
-rw-r--r--app/graphql/mutations/issues/set_crm_contacts.rb48
-rw-r--r--app/graphql/mutations/merge_requests/set_wip.rb35
-rw-r--r--app/graphql/mutations/merge_requests/toggle_attention_requested.rb27
-rw-r--r--app/graphql/mutations/security/ci_configuration/configure_sast_iac.rb21
-rw-r--r--app/graphql/queries/epic/epic_children.query.graphql1
-rw-r--r--app/graphql/resolvers/base_issues_resolver.rb61
-rw-r--r--app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb25
-rw-r--r--app/graphql/resolvers/concerns/issue_resolver_arguments.rb26
-rw-r--r--app/graphql/resolvers/concerns/resolves_groups.rb34
-rw-r--r--app/graphql/resolvers/concerns/resolves_pipelines.rb3
-rw-r--r--app/graphql/resolvers/group_issues_resolver.rb12
-rw-r--r--app/graphql/resolvers/groups_resolver.rb12
-rw-r--r--app/graphql/resolvers/issue_status_counts_resolver.rb1
-rw-r--r--app/graphql/resolvers/issues_resolver.rb59
-rw-r--r--app/graphql/resolvers/merge_requests_resolver.rb6
-rw-r--r--app/graphql/resolvers/topics_resolver.rb19
-rw-r--r--app/graphql/resolvers/users/groups_resolver.rb17
-rw-r--r--app/graphql/types/ci/job_artifact_type.rb4
-rw-r--r--app/graphql/types/ci/pipeline_scope_enum.rb21
-rw-r--r--app/graphql/types/ci/pipeline_status_enum.rb22
-rw-r--r--app/graphql/types/ci/pipeline_type.rb9
-rw-r--r--app/graphql/types/ci/runner_setup_type.rb2
-rw-r--r--app/graphql/types/commit_type.rb7
-rw-r--r--app/graphql/types/customer_relations/contact_type.rb2
-rw-r--r--app/graphql/types/customer_relations/organization_type.rb2
-rw-r--r--app/graphql/types/dependency_proxy/manifest_type.rb1
-rw-r--r--app/graphql/types/evidence_type.rb2
-rw-r--r--app/graphql/types/group_type.rb10
-rw-r--r--app/graphql/types/issues/negated_issue_filter_input_type.rb3
-rw-r--r--app/graphql/types/merge_request_type.rb6
-rw-r--r--app/graphql/types/mutation_type.rb6
-rw-r--r--app/graphql/types/packages/file_metadata_type.rb5
-rw-r--r--app/graphql/types/packages/helm/dependency_type.rb28
-rw-r--r--app/graphql/types/packages/helm/file_metadatum_type.rb19
-rw-r--r--app/graphql/types/packages/helm/maintainer_type.rb18
-rw-r--r--app/graphql/types/packages/helm/metadata_type.rb32
-rw-r--r--app/graphql/types/packages/package_file_type.rb2
-rw-r--r--app/graphql/types/project_type.rb7
-rw-r--r--app/graphql/types/projects/topic_type.rb28
-rw-r--r--app/graphql/types/query_type.rb5
-rw-r--r--app/graphql/types/release_links_type.rb17
-rw-r--r--app/graphql/types/release_tag_wildcard_id_enum.rb11
-rw-r--r--app/graphql/types/release_type.rb3
-rw-r--r--app/graphql/types/repository/blob_type.rb3
-rw-r--r--app/graphql/types/repository_type.rb3
-rw-r--r--app/helpers/admin/deploy_key_helper.rb14
-rw-r--r--app/helpers/appearances_helper.rb4
-rw-r--r--app/helpers/application_settings_helper.rb4
-rw-r--r--app/helpers/auth_helper.rb1
-rw-r--r--app/helpers/boards_helper.rb2
-rw-r--r--app/helpers/breadcrumbs_helper.rb8
-rw-r--r--app/helpers/ci/pipelines_helper.rb11
-rw-r--r--app/helpers/ci/runners_helper.rb40
-rw-r--r--app/helpers/clusters_helper.rb37
-rw-r--r--app/helpers/emoji_helper.rb5
-rw-r--r--app/helpers/environments_helper.rb8
-rw-r--r--app/helpers/graph_helper.rb4
-rw-r--r--app/helpers/groups/settings_helper.rb20
-rw-r--r--app/helpers/groups_helper.rb4
-rw-r--r--app/helpers/icons_helper.rb4
-rw-r--r--app/helpers/integrations_helper.rb14
-rw-r--r--app/helpers/invite_members_helper.rb23
-rw-r--r--app/helpers/issuables_description_templates_helper.rb13
-rw-r--r--app/helpers/issuables_helper.rb9
-rw-r--r--app/helpers/issues_helper.rb4
-rw-r--r--app/helpers/learn_gitlab_helper.rb44
-rw-r--r--app/helpers/members_helper.rb8
-rw-r--r--app/helpers/nav/top_nav_helper.rb1
-rw-r--r--app/helpers/notes_helper.rb9
-rw-r--r--app/helpers/one_trust_helper.rb3
-rw-r--r--app/helpers/projects/alert_management_helper.rb5
-rw-r--r--app/helpers/projects/incidents_helper.rb3
-rw-r--r--app/helpers/projects/security/configuration_helper.rb2
-rw-r--r--app/helpers/projects_helper.rb36
-rw-r--r--app/helpers/recaptcha_helper.rb3
-rw-r--r--app/helpers/reminder_emails_helper.rb3
-rw-r--r--app/helpers/routing/pseudonymization_helper.rb100
-rw-r--r--app/helpers/storage_helper.rb3
-rw-r--r--app/helpers/tab_helper.rb12
-rw-r--r--app/helpers/terms_helper.rb20
-rw-r--r--app/helpers/time_zone_helper.rb8
-rw-r--r--app/helpers/todos_helper.rb1
-rw-r--r--app/helpers/user_callouts_helper.rb21
-rw-r--r--app/helpers/wiki_helper.rb6
-rw-r--r--app/helpers/workhorse_helper.rb4
-rw-r--r--app/mailers/emails/members.rb6
-rw-r--r--app/mailers/emails/pipelines.rb21
-rw-r--r--app/models/analytics/cycle_analytics/issue_stage_event.rb13
-rw-r--r--app/models/analytics/cycle_analytics/merge_request_stage_event.rb13
-rw-r--r--app/models/application_record.rb8
-rw-r--r--app/models/application_setting.rb12
-rw-r--r--app/models/application_setting_implementation.rb7
-rw-r--r--app/models/audit_event.rb6
-rw-r--r--app/models/award_emoji.rb2
-rw-r--r--app/models/blob_viewer/package_json.rb14
-rw-r--r--app/models/bulk_imports/entity.rb4
-rw-r--r--app/models/chat_name.rb4
-rw-r--r--app/models/ci/application_record.rb5
-rw-r--r--app/models/ci/build.rb58
-rw-r--r--app/models/ci/build_metadata.rb12
-rw-r--r--app/models/ci/build_need.rb8
-rw-r--r--app/models/ci/build_runner_session.rb2
-rw-r--r--app/models/ci/build_trace_chunk.rb1
-rw-r--r--app/models/ci/ci_database_record.rb17
-rw-r--r--app/models/ci/instance_variable.rb2
-rw-r--r--app/models/ci/job_artifact.rb22
-rw-r--r--app/models/ci/pipeline.rb110
-rw-r--r--app/models/ci/runner.rb34
-rw-r--r--app/models/ci/sources/pipeline.rb3
-rw-r--r--app/models/ci/stage.rb1
-rw-r--r--app/models/ci/trigger.rb4
-rw-r--r--app/models/clusters/agents/group_authorization.rb2
-rw-r--r--app/models/clusters/agents/project_authorization.rb2
-rw-r--r--app/models/clusters/applications/runner.rb4
-rw-r--r--app/models/clusters/cluster.rb8
-rw-r--r--app/models/clusters/integrations/prometheus.rb7
-rw-r--r--app/models/commit_status.rb2
-rw-r--r--app/models/concerns/alert_event_lifecycle.rb2
-rw-r--r--app/models/concerns/analytics/cycle_analytics/stage_event_model.rb28
-rw-r--r--app/models/concerns/cascading_namespace_setting_attribute.rb6
-rw-r--r--app/models/concerns/ci/contextable.rb33
-rw-r--r--app/models/concerns/ci/has_status.rb17
-rw-r--r--app/models/concerns/ci/metadatable.rb3
-rw-r--r--app/models/concerns/clusters/agents/authorization_config_scopes.rb25
-rw-r--r--app/models/concerns/database_reflection.rb21
-rw-r--r--app/models/concerns/enums/vulnerability.rb13
-rw-r--r--app/models/concerns/file_store_mounter.rb8
-rw-r--r--app/models/concerns/has_integrations.rb19
-rw-r--r--app/models/concerns/has_user_type.rb1
-rw-r--r--app/models/concerns/integrations/push_data_validations.rb44
-rw-r--r--app/models/concerns/integrations/reactively_cached.rb15
-rw-r--r--app/models/concerns/issuable.rb1
-rw-r--r--app/models/concerns/legacy_bulk_insert.rb54
-rw-r--r--app/models/concerns/loaded_in_group_list.rb2
-rw-r--r--app/models/concerns/loose_foreign_key.rb22
-rw-r--r--app/models/concerns/merge_request_reviewer_state.rb25
-rw-r--r--app/models/concerns/milestoneable.rb3
-rw-r--r--app/models/concerns/noteable.rb33
-rw-r--r--app/models/concerns/reactive_service.rb13
-rw-r--r--app/models/concerns/security/latest_pipeline_information.rb36
-rw-r--r--app/models/concerns/service_push_data_validations.rb43
-rw-r--r--app/models/concerns/sha256_attribute.rb2
-rw-r--r--app/models/concerns/sha_attribute.rb2
-rw-r--r--app/models/concerns/strip_attribute.rb3
-rw-r--r--app/models/concerns/timebox.rb16
-rw-r--r--app/models/concerns/transactions.rb28
-rw-r--r--app/models/concerns/ttl_expirable.rb7
-rw-r--r--app/models/concerns/update_highest_role.rb2
-rw-r--r--app/models/concerns/x509_serial_number_attribute.rb2
-rw-r--r--app/models/custom_emoji.rb2
-rw-r--r--app/models/customer_relations/contact.rb3
-rw-r--r--app/models/customer_relations/issue_contact.rb20
-rw-r--r--app/models/data_list.rb14
-rw-r--r--app/models/dependency_proxy/blob.rb2
-rw-r--r--app/models/dependency_proxy/manifest.rb12
-rw-r--r--app/models/deploy_key.rb8
-rw-r--r--app/models/deployment.rb20
-rw-r--r--app/models/design_management/version.rb2
-rw-r--r--app/models/email.rb12
-rw-r--r--app/models/environment.rb8
-rw-r--r--app/models/error_tracking/error.rb7
-rw-r--r--app/models/error_tracking/error_event.rb8
-rw-r--r--app/models/event.rb3
-rw-r--r--app/models/gpg_signature.rb3
-rw-r--r--app/models/group.rb30
-rw-r--r--app/models/integration.rb4
-rw-r--r--app/models/integrations/bamboo.rb2
-rw-r--r--app/models/integrations/base_chat_notification.rb7
-rw-r--r--app/models/integrations/buildkite.rb2
-rw-r--r--app/models/integrations/discord.rb7
-rw-r--r--app/models/integrations/drone_ci.rb4
-rw-r--r--app/models/integrations/emails_on_push.rb9
-rw-r--r--app/models/integrations/hangouts_chat.rb7
-rw-r--r--app/models/integrations/jira.rb15
-rw-r--r--app/models/integrations/microsoft_teams.rb7
-rw-r--r--app/models/integrations/pipelines_email.rb18
-rw-r--r--app/models/integrations/shimo.rb47
-rw-r--r--app/models/integrations/teamcity.rb4
-rw-r--r--app/models/integrations/unify_circuit.rb7
-rw-r--r--app/models/integrations/webex_teams.rb7
-rw-r--r--app/models/integrations/zentao.rb34
-rw-r--r--app/models/issue.rb10
-rw-r--r--app/models/key.rb2
-rw-r--r--app/models/label_link.rb12
-rw-r--r--app/models/loose_foreign_keys/deleted_record.rb29
-rw-r--r--app/models/loose_foreign_keys/modification_tracker.rb51
-rw-r--r--app/models/member.rb11
-rw-r--r--app/models/members/member_task.rb43
-rw-r--r--app/models/members/project_member.rb1
-rw-r--r--app/models/merge_request.rb27
-rw-r--r--app/models/merge_request_assignee.rb6
-rw-r--r--app/models/merge_request_context_commit.rb2
-rw-r--r--app/models/merge_request_context_commit_diff_file.rb2
-rw-r--r--app/models/merge_request_diff.rb8
-rw-r--r--app/models/merge_request_diff_commit.rb25
-rw-r--r--app/models/merge_request_reviewer.rb13
-rw-r--r--app/models/namespace.rb59
-rw-r--r--app/models/namespaces/project_namespace.rb2
-rw-r--r--app/models/namespaces/traversal/linear.rb3
-rw-r--r--app/models/namespaces/traversal/linear_scopes.rb78
-rw-r--r--app/models/namespaces/traversal/recursive_scopes.rb7
-rw-r--r--app/models/namespaces/user_namespace.rb20
-rw-r--r--app/models/note.rb1
-rw-r--r--app/models/packages/npm.rb4
-rw-r--r--app/models/packages/npm/metadatum.rb25
-rw-r--r--app/models/packages/package.rb8
-rw-r--r--app/models/packages/package_file.rb3
-rw-r--r--app/models/preloaders/group_policy_preloader.rb23
-rw-r--r--app/models/preloaders/group_root_ancestor_preloader.rb32
-rw-r--r--app/models/preloaders/user_max_access_level_in_groups_preloader.rb29
-rw-r--r--app/models/project.rb80
-rw-r--r--app/models/project_authorization.rb5
-rw-r--r--app/models/project_setting.rb2
-rw-r--r--app/models/project_team.rb6
-rw-r--r--app/models/projects/topic.rb2
-rw-r--r--app/models/push_event_payload.rb3
-rw-r--r--app/models/release.rb1
-rw-r--r--app/models/repository.rb41
-rw-r--r--app/models/suggestion.rb1
-rw-r--r--app/models/todo.rb8
-rw-r--r--app/models/upload.rb11
-rw-r--r--app/models/uploads/fog.rb14
-rw-r--r--app/models/uploads/local.rb2
-rw-r--r--app/models/user.rb103
-rw-r--r--app/models/user_status.rb4
-rw-r--r--app/models/users/credit_card_validation.rb3
-rw-r--r--app/models/users/in_product_marketing_email.rb3
-rw-r--r--app/models/users_statistics.rb36
-rw-r--r--app/models/webauthn_registration.rb3
-rw-r--r--app/policies/group_policy.rb17
-rw-r--r--app/policies/issue_policy.rb7
-rw-r--r--app/policies/packages/helm/file_metadatum_policy.rb8
-rw-r--r--app/policies/project_policy.rb15
-rw-r--r--app/presenters/award_emoji_presenter.rb10
-rw-r--r--app/presenters/blob_presenter.rb33
-rw-r--r--app/presenters/ci/build_runner_presenter.rb6
-rw-r--r--app/presenters/packages/npm/package_presenter.rb38
-rw-r--r--app/presenters/project_presenter.rb38
-rw-r--r--app/presenters/release_presenter.rb4
-rw-r--r--app/serializers/alert_management/alert_entity.rb8
-rw-r--r--app/serializers/alert_management/alert_serializer.rb7
-rw-r--r--app/serializers/analytics_summary_entity.rb1
-rw-r--r--app/serializers/merge_request_sidebar_extras_entity.rb4
-rw-r--r--app/serializers/merge_request_user_entity.rb18
-rw-r--r--app/serializers/merge_request_widget_entity.rb17
-rw-r--r--app/serializers/note_entity.rb4
-rw-r--r--app/serializers/service_field_entity.rb2
-rw-r--r--app/services/alert_management/process_prometheus_alert_service.rb7
-rw-r--r--app/services/audit_event_service.rb5
-rw-r--r--app/services/authorized_project_update/project_access_changed_service.rb19
-rw-r--r--app/services/award_emojis/base_service.rb2
-rw-r--r--app/services/base_service.rb8
-rw-r--r--app/services/bulk_imports/file_download_service.rb12
-rw-r--r--app/services/bulk_update_integration_service.rb7
-rw-r--r--app/services/ci/create_pipeline_service.rb1
-rw-r--r--app/services/ci/destroy_pipeline_service.rb4
-rw-r--r--app/services/ci/external_pull_requests/create_pipeline_service.rb11
-rw-r--r--app/services/ci/generate_kubeconfig_service.rb62
-rw-r--r--app/services/ci/job_artifacts/create_service.rb41
-rw-r--r--app/services/ci/job_artifacts/destroy_all_expired_service.rb18
-rw-r--r--app/services/ci/job_artifacts/destroy_batch_service.rb23
-rw-r--r--app/services/ci/parse_dotenv_artifact_service.rb19
-rw-r--r--app/services/ci/retry_build_service.rb7
-rw-r--r--app/services/ci/unlock_artifacts_service.rb100
-rw-r--r--app/services/ci/update_build_state_service.rb4
-rw-r--r--app/services/clusters/agents/refresh_authorization_service.rb2
-rw-r--r--app/services/clusters/applications/prometheus_health_check_service.rb87
-rw-r--r--app/services/clusters/cleanup/project_namespace_service.rb6
-rw-r--r--app/services/clusters/cleanup/service_account_service.rb5
-rw-r--r--app/services/clusters/integrations/prometheus_health_check_service.rb101
-rw-r--r--app/services/concerns/alert_management/responses.rb26
-rw-r--r--app/services/concerns/issues/issue_type_helpers.rb12
-rw-r--r--app/services/concerns/members/bulk_create_users.rb6
-rw-r--r--app/services/customer_relations/contacts/base_service.rb2
-rw-r--r--app/services/customer_relations/organizations/base_service.rb2
-rw-r--r--app/services/dependency_proxy/find_or_create_blob_service.rb3
-rw-r--r--app/services/dependency_proxy/find_or_create_manifest_service.rb30
-rw-r--r--app/services/dependency_proxy/head_manifest_service.rb5
-rw-r--r--app/services/dependency_proxy/pull_manifest_service.rb8
-rw-r--r--app/services/deployments/archive_in_project_service.rb27
-rw-r--r--app/services/deployments/link_merge_requests_service.rb2
-rw-r--r--app/services/design_management/copy_design_collection/copy_service.rb12
-rw-r--r--app/services/emails/destroy_service.rb2
-rw-r--r--app/services/error_tracking/collect_error_service.rb15
-rw-r--r--app/services/google_cloud/service_accounts_service.rb40
-rw-r--r--app/services/groups/create_service.rb12
-rw-r--r--app/services/groups/import_export/import_service.rb2
-rw-r--r--app/services/groups/transfer_service.rb19
-rw-r--r--app/services/import/github/notes/create_service.rb15
-rw-r--r--app/services/issuable/clone/attributes_rewriter.rb2
-rw-r--r--app/services/issuable_links/list_service.rb7
-rw-r--r--app/services/issues/base_service.rb9
-rw-r--r--app/services/issues/build_service.rb2
-rw-r--r--app/services/issues/close_service.rb9
-rw-r--r--app/services/issues/create_service.rb6
-rw-r--r--app/services/issues/set_crm_contacts_service.rb90
-rw-r--r--app/services/issues/update_service.rb2
-rw-r--r--app/services/jira/requests/base.rb20
-rw-r--r--app/services/labels/transfer_service.rb35
-rw-r--r--app/services/loose_foreign_keys/batch_cleaner_service.rb61
-rw-r--r--app/services/loose_foreign_keys/cleaner_service.rb99
-rw-r--r--app/services/loose_foreign_keys/process_deleted_records_service.rb74
-rw-r--r--app/services/members/create_service.rb19
-rw-r--r--app/services/members/creator_service.rb18
-rw-r--r--app/services/members/invite_service.rb5
-rw-r--r--app/services/merge_requests/outdated_discussion_diff_lines_service.rb61
-rw-r--r--app/services/merge_requests/retarget_chain_service.rb2
-rw-r--r--app/services/merge_requests/toggle_attention_requested_service.rb49
-rw-r--r--app/services/namespaces/in_product_marketing_email_records.rb26
-rw-r--r--app/services/namespaces/in_product_marketing_emails_service.rb31
-rw-r--r--app/services/namespaces/invite_team_email_service.rb62
-rw-r--r--app/services/notes/create_service.rb6
-rw-r--r--app/services/notification_service.rb4
-rw-r--r--app/services/packages/create_dependency_service.rb10
-rw-r--r--app/services/packages/npm/create_package_service.rb10
-rw-r--r--app/services/packages/nuget/create_dependency_service.rb2
-rw-r--r--app/services/packages/rubygems/create_dependencies_service.rb2
-rw-r--r--app/services/packages/update_tags_service.rb2
-rw-r--r--app/services/projects/alerting/notify_service.rb15
-rw-r--r--app/services/projects/all_issues_count_service.rb15
-rw-r--r--app/services/projects/all_merge_requests_count_service.rb15
-rw-r--r--app/services/projects/container_repository/cache_tags_created_at_service.rb70
-rw-r--r--app/services/projects/container_repository/cleanup_tags_service.rb5
-rw-r--r--app/services/projects/create_service.rb10
-rw-r--r--app/services/projects/destroy_service.rb9
-rw-r--r--app/services/projects/detect_repository_languages_service.rb2
-rw-r--r--app/services/projects/import_export/export_service.rb11
-rw-r--r--app/services/projects/lfs_pointers/lfs_link_service.rb2
-rw-r--r--app/services/projects/participants_service.rb10
-rw-r--r--app/services/projects/prometheus/alerts/notify_service.rb19
-rw-r--r--app/services/resource_events/base_synthetic_notes_builder_service.rb12
-rw-r--r--app/services/resource_events/change_labels_service.rb2
-rw-r--r--app/services/resource_events/synthetic_label_notes_builder_service.rb4
-rw-r--r--app/services/resource_events/synthetic_milestone_notes_builder_service.rb4
-rw-r--r--app/services/resource_events/synthetic_state_notes_builder_service.rb4
-rw-r--r--app/services/search_service.rb4
-rw-r--r--app/services/security/ci_configuration/sast_iac_create_service.rb25
-rw-r--r--app/services/snippets/update_service.rb2
-rw-r--r--app/services/spam/spam_verdict_service.rb12
-rw-r--r--app/services/suggestions/create_service.rb2
-rw-r--r--app/services/system_note_service.rb4
-rw-r--r--app/services/system_notes/incident_service.rb6
-rw-r--r--app/services/system_notes/issuables_service.rb8
-rw-r--r--app/services/tasks_to_be_done/base_service.rb55
-rw-r--r--app/services/tasks_to_be_done/create_ci_task_service.rb44
-rw-r--r--app/services/tasks_to_be_done/create_code_task_service.rb52
-rw-r--r--app/services/tasks_to_be_done/create_issues_task_service.rb43
-rw-r--r--app/services/todo_service.rb5
-rw-r--r--app/services/users/destroy_service.rb5
-rw-r--r--app/services/users/refresh_authorized_projects_service.rb6
-rw-r--r--app/services/users/upsert_credit_card_validation_service.rb1
-rw-r--r--app/uploaders/bulk_imports/export_uploader.rb2
-rw-r--r--app/uploaders/file_uploader.rb9
-rw-r--r--app/uploaders/import_export_uploader.rb4
-rw-r--r--app/validators/gitlab/emoji_name_validator.rb19
-rw-r--r--app/validators/json_schemas/error_tracking_event_payload.json13
-rw-r--r--app/validators/json_schemas/helm_metadata.json18
-rw-r--r--app/validators/json_schemas/npm_package_json.json26
-rw-r--r--app/views/admin/application_settings/_performance_bar.html.haml2
-rw-r--r--app/views/admin/application_settings/_protected_paths.html.haml20
-rw-r--r--app/views/admin/application_settings/_sentry.html.haml22
-rw-r--r--app/views/admin/application_settings/_usage.html.haml2
-rw-r--r--app/views/admin/application_settings/_visibility_and_access.html.haml8
-rw-r--r--app/views/admin/application_settings/general.html.haml2
-rw-r--r--app/views/admin/application_settings/metrics_and_profiling.html.haml14
-rw-r--r--app/views/admin/application_settings/network.html.haml8
-rw-r--r--app/views/admin/application_settings/reporting.html.haml3
-rw-r--r--app/views/admin/applications/show.html.haml1
-rw-r--r--app/views/admin/dashboard/index.html.haml4
-rw-r--r--app/views/admin/dashboard/stats.html.haml63
-rw-r--r--app/views/admin/deploy_keys/index.html.haml65
-rw-r--r--app/views/admin/dev_ops_report/_score.html.haml (renamed from app/views/admin/dev_ops_report/_report.html.haml)0
-rw-r--r--app/views/admin/dev_ops_report/show.html.haml4
-rw-r--r--app/views/admin/runners/index.html.haml2
-rw-r--r--app/views/admin/topics/_topic.html.haml2
-rw-r--r--app/views/admin/users/_tabs.html.haml10
-rw-r--r--app/views/admin/users/_users.html.haml72
-rw-r--r--app/views/clusters/clusters/_cluster_list.html.haml8
-rw-r--r--app/views/clusters/clusters/_empty_state.html.haml14
-rw-r--r--app/views/clusters/clusters/aws/_new.html.haml2
-rw-r--r--app/views/clusters/clusters/gcp/_form.html.haml4
-rw-r--r--app/views/clusters/clusters/index.html.haml20
-rw-r--r--app/views/clusters/clusters/new.html.haml38
-rw-r--r--app/views/clusters/clusters/show.html.haml2
-rw-r--r--app/views/dashboard/_projects_head.html.haml14
-rw-r--r--app/views/dashboard/_projects_nav.html.haml13
-rw-r--r--app/views/dashboard/_snippets_head.html.haml10
-rw-r--r--app/views/dashboard/projects/_nav.html.haml8
-rw-r--r--app/views/dashboard/todos/index.html.haml20
-rw-r--r--app/views/devise/confirmations/new.html.haml7
-rw-r--r--app/views/devise/passwords/new.html.haml7
-rw-r--r--app/views/doorkeeper/applications/show.html.haml5
-rw-r--r--app/views/errors/omniauth_error.html.haml2
-rw-r--r--app/views/explore/groups/_nav.html.haml6
-rw-r--r--app/views/explore/projects/_nav.html.haml14
-rw-r--r--app/views/explore/projects/topic.html.haml31
-rw-r--r--app/views/explore/projects/topics.html.haml12
-rw-r--r--app/views/explore/topics/_head.html.haml9
-rw-r--r--app/views/groups/_invite_members_side_nav_link.html.haml8
-rw-r--r--app/views/groups/boards/show.html.haml2
-rw-r--r--app/views/groups/crm/contacts.html.haml4
-rw-r--r--app/views/groups/crm/organizations.html.haml4
-rw-r--r--app/views/groups/dependency_proxies/show.html.haml4
-rw-r--r--app/views/groups/new.html.haml2
-rw-r--r--app/views/groups/settings/_advanced.html.haml5
-rw-r--r--app/views/groups/settings/_membership.html.haml1
-rw-r--r--app/views/groups/settings/_permanent_deletion.html.haml6
-rw-r--r--app/views/groups/settings/_remove.html.haml7
-rw-r--r--app/views/groups/settings/_remove_button.html.haml4
-rw-r--r--app/views/groups/settings/_transfer.html.haml2
-rw-r--r--app/views/groups/settings/applications/show.html.haml5
-rw-r--r--app/views/groups/show.html.haml2
-rw-r--r--app/views/help/index.html.haml4
-rw-r--r--app/views/import/github/new.html.haml2
-rw-r--r--app/views/issues/_issues_calendar.ics.ruby3
-rw-r--r--app/views/jira_connect/branches/new.html.haml1
-rw-r--r--app/views/jira_connect/subscriptions/index.html.haml15
-rw-r--r--app/views/layouts/_head.html.haml2
-rw-r--r--app/views/layouts/_loading_hints.html.haml6
-rw-r--r--app/views/layouts/_published_experiments.html.haml4
-rw-r--r--app/views/layouts/_snowplow.html.haml3
-rw-r--r--app/views/layouts/application.html.haml1
-rw-r--r--app/views/layouts/header/_default.html.haml2
-rw-r--r--app/views/layouts/header/_help_dropdown.html.haml2
-rw-r--r--app/views/layouts/header/_logo_with_title.html.haml4
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml4
-rw-r--r--app/views/layouts/nav/_top_nav_responsive.html.haml3
-rw-r--r--app/views/layouts/nav/breadcrumbs/_collapsed_dropdown.html.haml11
-rw-r--r--app/views/layouts/nav/breadcrumbs/_collapsed_inline_list.html.haml11
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml4
-rw-r--r--app/views/layouts/terms.html.haml9
-rw-r--r--app/views/notify/in_product_marketing_email.html.haml15
-rw-r--r--app/views/notify/in_product_marketing_email.text.erb4
-rw-r--r--app/views/notify/member_access_denied_email.html.haml9
-rw-r--r--app/views/notify/member_access_granted_email.html.haml6
-rw-r--r--app/views/notify/member_invited_email.html.haml5
-rw-r--r--app/views/profiles/_event_table.html.haml11
-rw-r--r--app/views/profiles/audit_log.html.haml2
-rw-r--r--app/views/profiles/emails/index.html.haml2
-rw-r--r--app/views/profiles/show.html.haml2
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml4
-rw-r--r--app/views/projects/_invite_members_side_nav_link.html.haml8
-rw-r--r--app/views/projects/_merge_request_merge_commit_template.html.haml17
-rw-r--r--app/views/projects/_merge_request_settings.html.haml2
-rw-r--r--app/views/projects/_new_project_fields.html.haml11
-rw-r--r--app/views/projects/_remove.html.haml4
-rw-r--r--app/views/projects/_remove_fork.html.haml2
-rw-r--r--app/views/projects/_service_desk_settings.html.haml3
-rw-r--r--app/views/projects/_transfer.html.haml2
-rw-r--r--app/views/projects/_visibility_modal.html.haml6
-rw-r--r--app/views/projects/blame/show.html.haml2
-rw-r--r--app/views/projects/blob/_header.html.haml2
-rw-r--r--app/views/projects/blob/edit.html.haml10
-rw-r--r--app/views/projects/blob/viewers/_changelog.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_readme.html.haml2
-rw-r--r--app/views/projects/branches/_branch.html.haml2
-rw-r--r--app/views/projects/commit/_ci_menu.html.haml16
-rw-r--r--app/views/projects/commit/_multiple_signatures_signature_badge.html.haml6
-rw-r--r--app/views/projects/confluences/show.html.haml7
-rw-r--r--app/views/projects/cycle_analytics/show.html.haml4
-rw-r--r--app/views/projects/deployments/_deployment.html.haml2
-rw-r--r--app/views/projects/edit.html.haml2
-rw-r--r--app/views/projects/empty.html.haml2
-rw-r--r--app/views/projects/environments/index.html.haml25
-rw-r--r--app/views/projects/google_cloud/index.html.haml79
-rw-r--r--app/views/projects/hook_logs/show.html.haml16
-rw-r--r--app/views/projects/issues/_discussion.html.haml3
-rw-r--r--app/views/projects/issues/_issues.html.haml2
-rw-r--r--app/views/projects/issues/_service_desk_empty_state.html.haml2
-rw-r--r--app/views/projects/issues/_service_desk_info_content.html.haml5
-rw-r--r--app/views/projects/learn_gitlab/index.html.haml9
-rw-r--r--app/views/projects/merge_requests/_widget.html.haml4
-rw-r--r--app/views/projects/mirrors/_instructions.html.haml2
-rw-r--r--app/views/projects/new.html.haml2
-rw-r--r--app/views/projects/pages/_no_domains.html.haml2
-rw-r--r--app/views/projects/pipeline_schedules/_tabs.html.haml26
-rw-r--r--app/views/projects/pipelines/_info.html.haml79
-rw-r--r--app/views/projects/pipelines/charts.html.haml3
-rw-r--r--app/views/projects/pipelines/show.html.haml4
-rw-r--r--app/views/projects/product_analytics/_links.html.haml15
-rw-r--r--app/views/projects/settings/_general.html.haml7
-rw-r--r--app/views/projects/work_items/index.html.haml2
-rw-r--r--app/views/registrations/welcome/show.html.haml3
-rw-r--r--app/views/search/_category.html.haml2
-rw-r--r--app/views/shared/_confirm_modal.html.haml6
-rw-r--r--app/views/shared/_default_branch_protection.html.haml7
-rw-r--r--app/views/shared/_issues.html.haml2
-rw-r--r--app/views/shared/_md_preview.html.haml2
-rw-r--r--app/views/shared/_new_commit_form.html.haml4
-rw-r--r--app/views/shared/_no_password.html.haml16
-rw-r--r--app/views/shared/_no_ssh.html.haml14
-rw-r--r--app/views/shared/_project_creation_levels.html.haml7
-rw-r--r--app/views/shared/_visibility_radios.html.haml1
-rw-r--r--app/views/shared/alerts/_positioning_disabled.html.haml2
-rw-r--r--app/views/shared/boards/_switcher.html.haml7
-rw-r--r--app/views/shared/deploy_tokens/_form.html.haml2
-rw-r--r--app/views/shared/doorkeeper/applications/_show.html.haml9
-rw-r--r--app/views/shared/hook_logs/_content.html.haml59
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml1
-rw-r--r--app/views/shared/issuable/form/_branch_chooser.html.haml2
-rw-r--r--app/views/shared/issuable/form/_type_selector.html.haml18
-rw-r--r--app/views/shared/labels/_nav.html.haml10
-rw-r--r--app/views/shared/nav/_sidebar_menu.html.haml13
-rw-r--r--app/views/shared/nav/_sidebar_submenu.html.haml12
-rw-r--r--app/views/shared/projects/_topics.html.haml4
-rw-r--r--app/views/shared/runners/_shared_runners_description.html.haml3
-rw-r--r--app/views/shared/topics/_list.html.haml9
-rw-r--r--app/views/shared/topics/_topic.html.haml16
-rw-r--r--app/views/shared/web_hooks/_index.html.haml2
-rw-r--r--app/views/users/_overview.html.haml17
-rw-r--r--app/views/users/calendar_activities.html.haml4
-rw-r--r--app/views/users/terms/index.html.haml37
-rw-r--r--app/workers/all_queues.yml130
-rw-r--r--app/workers/authorized_project_update/project_recalculate_worker.rb2
-rw-r--r--app/workers/authorized_projects_worker.rb4
-rw-r--r--app/workers/build_hooks_worker.rb2
-rw-r--r--app/workers/build_queue_worker.rb4
-rw-r--r--app/workers/build_success_worker.rb4
-rw-r--r--app/workers/chat_notification_worker.rb4
-rw-r--r--app/workers/ci/archive_trace_worker.rb4
-rw-r--r--app/workers/ci/build_finished_worker.rb2
-rw-r--r--app/workers/ci/build_trace_chunk_flush_worker.rb4
-rw-r--r--app/workers/ci/pipeline_success_unlock_artifacts_worker.rb5
-rw-r--r--app/workers/ci/ref_delete_unlock_artifacts_worker.rb5
-rw-r--r--app/workers/ci/resource_groups/assign_resource_from_resource_group_worker.rb2
-rw-r--r--app/workers/cluster_update_app_worker.rb4
-rw-r--r--app/workers/clusters/applications/check_prometheus_health_worker.rb33
-rw-r--r--app/workers/clusters/integrations/check_prometheus_health_worker.rb32
-rw-r--r--app/workers/concerns/application_worker.rb95
-rw-r--r--app/workers/concerns/gitlab/github_import/rescheduling_methods.rb4
-rw-r--r--app/workers/concerns/gitlab/github_import/stage_methods.rb6
-rw-r--r--app/workers/concerns/gitlab/jira_import/import_worker.rb2
-rw-r--r--app/workers/concerns/limited_capacity/worker.rb2
-rw-r--r--app/workers/concerns/new_issuable.rb8
-rw-r--r--app/workers/concerns/todos_destroyer_queue.rb2
-rw-r--r--app/workers/container_expiration_policies/cleanup_container_repository_worker.rb5
-rw-r--r--app/workers/create_commit_signature_worker.rb4
-rw-r--r--app/workers/database/drop_detached_partitions_worker.rb2
-rw-r--r--app/workers/database/partition_management_worker.rb2
-rw-r--r--app/workers/delete_container_repository_worker.rb6
-rw-r--r--app/workers/dependency_proxy/image_ttl_group_policy_worker.rb5
-rw-r--r--app/workers/deployments/archive_in_project_worker.rb19
-rw-r--r--app/workers/detect_repository_languages_worker.rb4
-rw-r--r--app/workers/email_receiver_worker.rb6
-rw-r--r--app/workers/emails_on_push_worker.rb17
-rw-r--r--app/workers/expire_build_instance_artifacts_worker.rb6
-rw-r--r--app/workers/expire_job_cache_worker.rb4
-rw-r--r--app/workers/expire_pipeline_cache_worker.rb4
-rw-r--r--app/workers/export_csv_worker.rb2
-rw-r--r--app/workers/gitlab/jira_import/import_issue_worker.rb4
-rw-r--r--app/workers/gitlab/jira_import/stage/start_import_worker.rb2
-rw-r--r--app/workers/hashed_storage/project_migrate_worker.rb4
-rw-r--r--app/workers/hashed_storage/project_rollback_worker.rb4
-rw-r--r--app/workers/import_issues_csv_worker.rb2
-rw-r--r--app/workers/integrations/create_external_cross_reference_worker.rb47
-rw-r--r--app/workers/invalid_gpg_signature_update_worker.rb4
-rw-r--r--app/workers/issuable/label_links_destroy_worker.rb2
-rw-r--r--app/workers/issuable_export_csv_worker.rb2
-rw-r--r--app/workers/issuables/clear_groups_issue_counter_worker.rb2
-rw-r--r--app/workers/issue_due_scheduler_worker.rb2
-rw-r--r--app/workers/issue_placement_worker.rb5
-rw-r--r--app/workers/issue_rebalancing_worker.rb6
-rw-r--r--app/workers/issues/placement_worker.rb67
-rw-r--r--app/workers/issues/rebalancing_worker.rb51
-rw-r--r--app/workers/issues/reschedule_stuck_issue_rebalances_worker.rb36
-rw-r--r--app/workers/loose_foreign_keys/cleanup_worker.rb25
-rw-r--r--app/workers/mail_scheduler/issue_due_worker.rb2
-rw-r--r--app/workers/mail_scheduler/notification_service_worker.rb2
-rw-r--r--app/workers/namespaces/invite_team_email_worker.rb22
-rw-r--r--app/workers/new_issue_worker.rb2
-rw-r--r--app/workers/new_note_worker.rb6
-rw-r--r--app/workers/pages_domain_verification_worker.rb4
-rw-r--r--app/workers/pages_worker.rb4
-rw-r--r--app/workers/pipeline_hooks_worker.rb4
-rw-r--r--app/workers/pipeline_metrics_worker.rb8
-rw-r--r--app/workers/pipeline_process_worker.rb4
-rw-r--r--app/workers/post_receive.rb1
-rw-r--r--app/workers/project_cache_worker.rb4
-rw-r--r--app/workers/propagate_service_template_worker.rb4
-rw-r--r--app/workers/run_pipeline_schedule_worker.rb6
-rw-r--r--app/workers/ssh_keys/expired_notification_worker.rb4
-rw-r--r--app/workers/tasks_to_be_done/create_worker.rb31
-rw-r--r--app/workers/update_highest_role_worker.rb6
-rw-r--r--app/workers/update_merge_requests_worker.rb6
-rw-r--r--app/workers/update_project_statistics_worker.rb4
-rwxr-xr-xbin/background_jobs7
-rwxr-xr-xbin/pngquant2
-rwxr-xr-xbin/sidekiq-cluster8
-rw-r--r--config/application.rb54
-rw-r--r--config/boot.rb4
-rw-r--r--config/dependency_decisions.yml89
-rw-r--r--config/environments/development.rb2
-rw-r--r--config/environments/test.rb6
-rw-r--r--config/feature_categories.yml9
-rw-r--r--config/feature_flags/development/add_actor_based_user_to_snowplow_tracking.yml8
-rw-r--r--config/feature_flags/development/add_namespace_and_project_to_snowplow_tracking.yml8
-rw-r--r--config/feature_flags/development/additional_snowplow_tracking.yml8
-rw-r--r--config/feature_flags/development/admin_deploy_keys_vue.yml8
-rw-r--r--config/feature_flags/development/api_v3_commits_skip_diff_files.yml8
-rw-r--r--config/feature_flags/development/atomic_sidekiq_scheduler.yml8
-rw-r--r--config/feature_flags/development/between_commits_via_list_commits.yml8
-rw-r--r--config/feature_flags/development/block_anonymous_global_searches.yml8
-rw-r--r--config/feature_flags/development/bootstrap_confirmation_modals.yml8
-rw-r--r--config/feature_flags/development/broadcast_issue_updates.yml4
-rw-r--r--config/feature_flags/development/cached_issues_state_count.yml8
-rw-r--r--config/feature_flags/development/cached_loading_hints.yml8
-rw-r--r--config/feature_flags/development/ci_create_external_pr_pipeline_async.yml8
-rw-r--r--config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml8
-rw-r--r--config/feature_flags/development/ci_new_artifact_file_reader.yml8
-rw-r--r--config/feature_flags/development/ci_predefined_vars_in_builder.yml8
-rw-r--r--config/feature_flags/development/ci_store_trace_outside_transaction.yml8
-rw-r--r--config/feature_flags/development/ci_synchronous_artifact_parsing.yml8
-rw-r--r--config/feature_flags/development/ci_update_unlocked_job_artifacts.yml8
-rw-r--r--config/feature_flags/development/ci_validate_job_length.yml8
-rw-r--r--config/feature_flags/development/cluster_vulnerabilities.yml8
-rw-r--r--config/feature_flags/development/configure_iac_scanning_via_mr.yml8
-rw-r--r--config/feature_flags/development/configure_sentry_in_application_settings.yml8
-rw-r--r--config/feature_flags/development/container_registry_expiration_policies_caching.yml8
-rw-r--r--config/feature_flags/development/content_editor_block_tables.yml8
-rw-r--r--config/feature_flags/development/create_project_namespace_on_project_create.yml8
-rw-r--r--config/feature_flags/development/dast_view_scans.yml2
-rw-r--r--config/feature_flags/development/decomposed_ci_query_in_pipelines_for_merge_request_finder.yml8
-rw-r--r--config/feature_flags/development/dependency_proxy_manifest_workhorse.yml8
-rw-r--r--config/feature_flags/development/dependency_proxy_workhorse.yml2
-rw-r--r--config/feature_flags/development/deployments_archive.yml8
-rw-r--r--config/feature_flags/development/detect_cross_database_modification.yml8
-rw-r--r--config/feature_flags/development/display_outdated_line_diff.yml8
-rw-r--r--config/feature_flags/development/environments_by_deployments_finder_exists_optimization.yml8
-rw-r--r--config/feature_flags/development/finding_ci_pipeline_disable_joins.yml8
-rw-r--r--config/feature_flags/development/github_importer_use_diff_note_with_suggestions.yml8
-rw-r--r--config/feature_flags/development/group_authorized_agents.yml8
-rw-r--r--config/feature_flags/development/jira_connect_asymmetric_jwt.yml8
-rw-r--r--config/feature_flags/development/jira_issue_details_edit_labels.yml8
-rw-r--r--config/feature_flags/development/jira_issue_details_edit_status.yml8
-rw-r--r--config/feature_flags/development/jira_use_first_ref_by_oid.yml8
-rw-r--r--config/feature_flags/development/jupyter_clean_diffs.yml8
-rw-r--r--config/feature_flags/development/linear_application_setting_ancestor_scopes.yml8
-rw-r--r--config/feature_flags/development/linear_ee_group_ancestor_scopes.yml8
-rw-r--r--config/feature_flags/development/linear_group_ancestor_scopes.yml8
-rw-r--r--config/feature_flags/development/linear_group_plans_preloaded_ancestor_scopes.yml8
-rw-r--r--config/feature_flags/development/linear_group_tree_ancestor_scopes.yml8
-rw-r--r--config/feature_flags/development/linear_members_finder_ancestor_scopes.yml8
-rw-r--r--config/feature_flags/development/linear_participants_service_ancestor_scopes.yml8
-rw-r--r--config/feature_flags/development/loose_foreign_key_cleanup.yml8
-rw-r--r--config/feature_flags/development/managed_alerts_deprecation.yml8
-rw-r--r--config/feature_flags/development/mr_attention_requests.yml8
-rw-r--r--config/feature_flags/development/mr_changes_fluid_layout.yml2
-rw-r--r--config/feature_flags/development/multiple_gpg_signatures.yml8
-rw-r--r--config/feature_flags/development/new_customersdot_staging_url.yml8
-rw-r--r--config/feature_flags/development/new_environments_table.yml8
-rw-r--r--config/feature_flags/development/new_graphql_keyset_pagination.yml2
-rw-r--r--config/feature_flags/development/package_list_apollo.yml8
-rw-r--r--config/feature_flags/development/packages_npm_abbreviated_metadata.yml8
-rw-r--r--config/feature_flags/development/paginated_issue_discussions.yml8
-rw-r--r--config/feature_flags/development/paginated_tree_graphql_query.yml8
-rw-r--r--config/feature_flags/development/pipeline_editor_mini_graph.yml8
-rw-r--r--config/feature_flags/development/project_storage_ui.yml8
-rw-r--r--config/feature_flags/development/query_analyzer_gitlab_schema_metrics.yml8
-rw-r--r--config/feature_flags/development/query_project_ci_feature_usages_for_coverage.yml8
-rw-r--r--config/feature_flags/development/real_time_issue_sidebar.yml2
-rw-r--r--config/feature_flags/development/release_evidence.yml8
-rw-r--r--config/feature_flags/development/report_on_long_redis_durations.yml8
-rw-r--r--config/feature_flags/development/request_apdex_counters.yml8
-rw-r--r--config/feature_flags/development/retarget_merge_requests.yml8
-rw-r--r--config/feature_flags/development/security_finding_build_disable_joins.yml8
-rw-r--r--config/feature_flags/development/show_relevant_approval_rule_approvers.yml2
-rw-r--r--config/feature_flags/development/sidekiq_push_bulk_in_batches.yml8
-rw-r--r--config/feature_flags/development/specialized_service_for_project_member_auth_refresh.yml8
-rw-r--r--config/feature_flags/development/suppress_apollo_errors_during_navigation.yml8
-rw-r--r--config/feature_flags/development/surface_environment_creation_failure.yml2
-rw-r--r--config/feature_flags/development/tag_list_keyset_pagination.yml8
-rw-r--r--config/feature_flags/development/tags_finder_gitaly.yml8
-rw-r--r--config/feature_flags/development/terms_of_service_vue.yml8
-rw-r--r--config/feature_flags/development/traversal_ids_btree.yml8
-rw-r--r--config/feature_flags/development/update_deployment_after_transaction_commit.yml8
-rw-r--r--config/feature_flags/development/usage_data_instrumentation.yml8
-rw-r--r--config/feature_flags/development/use_cmark_renderer.yml8
-rw-r--r--config/feature_flags/development/use_model_load_balancing.yml8
-rw-r--r--config/feature_flags/development/use_multi_store.yml8
-rw-r--r--config/feature_flags/development/use_optimized_group_labels_query.yml8
-rw-r--r--config/feature_flags/development/use_traversal_ids_roots.yml8
-rw-r--r--config/feature_flags/development/use_vsa_aggregated_tables.yml8
-rw-r--r--config/feature_flags/development/variable_inside_variable.yml8
-rw-r--r--config/feature_flags/development/workhorse_use_sidechannel.yml2
-rw-r--r--config/feature_flags/experiment/bypass_registration.yml8
-rw-r--r--config/feature_flags/experiment/change_continuous_onboarding_link_urls.yml8
-rw-r--r--config/feature_flags/experiment/confetti_post_signup.yml8
-rw-r--r--config/feature_flags/experiment/empty_repo_upload.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_for_task.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_in_side_nav.yml8
-rw-r--r--config/feature_flags/experiment/invite_team_email.yml8
-rw-r--r--config/feature_flags/experiment/pipeline_editor_walkthrough.yml8
-rw-r--r--config/feature_flags/experiment/prominent_create_board_btn.yml8
-rw-r--r--config/feature_flags/ops/additional_snowplow_tracking.yml8
-rw-r--r--config/feature_flags/ops/block_anonymous_global_searches.yml8
-rw-r--r--config/feature_flags/ops/product_analytics_tracking.yml8
-rw-r--r--config/gitlab.yml.example6
-rw-r--r--config/initializers/00_active_record_gitlab_schema.rb10
-rw-r--r--config/initializers/0_acts_as_taggable.rb19
-rw-r--r--config/initializers/0_marginalia.rb5
-rw-r--r--config/initializers/0_postgresql_types.rb17
-rw-r--r--config/initializers/1_acts_as_taggable.rb17
-rw-r--r--config/initializers/1_postgresql_only.rb2
-rw-r--r--config/initializers/1_settings.rb11
-rw-r--r--config/initializers/7_prometheus_metrics.rb2
-rw-r--r--config/initializers/action_cable.rb3
-rw-r--r--config/initializers/action_view.rb7
-rw-r--r--config/initializers/active_record_lifecycle.rb2
-rw-r--r--config/initializers/console_message.rb4
-rw-r--r--config/initializers/cookies_serializer.rb1
-rw-r--r--config/initializers/database_config.rb2
-rw-r--r--config/initializers/database_query_analyzers.rb15
-rw-r--r--config/initializers/direct_upload_support.rb10
-rw-r--r--config/initializers/elastic_client_setup.rb17
-rw-r--r--config/initializers/forbid_sidekiq_in_transactions.rb2
-rw-r--r--config/initializers/load_balancing.rb2
-rw-r--r--config/initializers/new_framework_defaults.rb24
-rw-r--r--config/initializers/postgres_partitioning.rb27
-rw-r--r--config/initializers/session_store.rb38
-rw-r--r--config/initializers/sidekiq.rb3
-rw-r--r--config/initializers/zz_metrics.rb2
-rw-r--r--config/initializers_before_autoloader/000_inflections.rb1
-rw-r--r--config/initializers_before_autoloader/100_patch_omniauth_oauth2.rb28
-rw-r--r--config/known_invalid_graphql_queries.yml4
-rw-r--r--config/metrics/aggregates/code_review.yml12
-rw-r--r--config/metrics/counts_28d/20210216183203_product_analytics_test_metrics_union.yml2
-rw-r--r--config/metrics/counts_28d/20210216183648_github.yml2
-rw-r--r--config/metrics/counts_28d/20210216183650_bitbucket.yml2
-rw-r--r--config/metrics/counts_28d/20210216183652_bitbucket_server.yml2
-rw-r--r--config/metrics/counts_28d/20210216184312_i_code_review_user_toggled_task_item_status_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184322_i_code_review_user_approve_mr_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184326_i_code_review_user_unapprove_mr_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184330_i_code_review_user_resolve_thread_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184334_i_code_review_user_unresolve_thread_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184338_i_code_review_edit_mr_title_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184342_i_code_review_edit_mr_desc_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184353_i_code_review_user_create_review_note_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184357_i_code_review_user_publish_review_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184401_i_code_review_user_create_multiline_mr_comment_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184405_i_code_review_user_edit_multiline_mr_comment_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184409_i_code_review_user_remove_multiline_mr_comment_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184418_i_code_review_user_assigned_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184422_i_code_review_user_marked_as_draft_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184426_i_code_review_user_unmarked_as_draft_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184430_i_code_review_user_review_requested_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184434_i_code_review_user_approval_rule_added_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184438_i_code_review_user_approval_rule_deleted_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184442_i_code_review_user_approval_rule_edited_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184446_i_code_review_user_vs_code_api_request_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184450_i_code_review_user_create_mr_from_issue_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210929102434_p_ci_templates_implicit_jobs_build_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210929102736_p_ci_templates_implicit_jobs_deploy_latest_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210929103010_p_ci_templates_implicit_jobs_deploy_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20211015154445_p_ci_templates_kaniko_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211102141250_i_quickactions_promote_to_incident_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211102205024_p_ci_templates_security_sast_iac_latest_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20211102205223_p_ci_templates_implicit_security_sast_iac_latest_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20211102213704_p_ci_templates_jobs_sast_iac_latest_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20211102213921_p_ci_templates_implicit_jobs_sast_iac_latest_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20211104154357_i_code_review_widget_nothing_merge_click_new_file_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211111162103_i_code_review_post_merge_delete_branch_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211111162422_i_code_review_post_merge_click_revert_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211112102446_i_code_review_post_merge_click_cherry_pick_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211112114333_i_code_review_post_merge_submit_revert_modal_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211112115144_i_code_review_post_merge_submit_cherry_pick_modal_monthly.yml25
-rw-r--r--config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216181347_g_project_management_issue_cross_referenced_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210216184310_i_code_review_user_toggled_task_item_status_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184320_i_code_review_user_approve_mr_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184324_i_code_review_user_unapprove_mr_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184328_i_code_review_user_resolve_thread_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184332_i_code_review_user_unresolve_thread_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184336_i_code_review_edit_mr_title_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184340_i_code_review_edit_mr_desc_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184351_i_code_review_user_create_review_note_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184355_i_code_review_user_publish_review_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184359_i_code_review_user_create_multiline_mr_comment_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184403_i_code_review_user_edit_multiline_mr_comment_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184407_i_code_review_user_remove_multiline_mr_comment_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184416_i_code_review_user_assigned_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184420_i_code_review_user_marked_as_draft_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184424_i_code_review_user_unmarked_as_draft_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184428_i_code_review_user_review_requested_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184432_i_code_review_user_approval_rule_added_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184436_i_code_review_user_approval_rule_deleted_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184440_i_code_review_user_approval_rule_edited_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184444_i_code_review_user_vs_code_api_request_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184448_i_code_review_user_create_mr_from_issue_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml3
-rw-r--r--config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20211015154445_p_ci_templates_kaniko_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211102141244_i_quickactions_promote_to_incident_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211102202454_p_ci_templates_security_sast_iac_latest_weekly.yml27
-rw-r--r--config/metrics/counts_7d/20211102204352_p_ci_templates_implicit_security_sast_iac_latest_weekly.yml26
-rw-r--r--config/metrics/counts_7d/20211102213112_p_ci_templates_jobs_sast_iac_latest_weekly.yml26
-rw-r--r--config/metrics/counts_7d/20211102213417_p_ci_templates_implicit_jobs_sast_iac_latest_weekly.yml26
-rw-r--r--config/metrics/counts_7d/20211104154352_i_code_review_widget_nothing_merge_click_new_file_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211111162058_i_code_review_post_merge_delete_branch_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211111162417_i_code_review_post_merge_click_revert_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211112102440_i_code_review_post_merge_click_cherry_pick_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211112114327_i_code_review_post_merge_submit_revert_modal_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211112115138_i_code_review_post_merge_submit_cherry_pick_modal_weekly.yml25
-rw-r--r--config/metrics/counts_all/20210216174902_g_analytics_merge_request.yml2
-rw-r--r--config/metrics/counts_all/20210216175316_kubernetes_agents.yml21
-rw-r--r--config/metrics/counts_all/20210216175318_kubernetes_agents_with_token.yml21
-rw-r--r--config/metrics/counts_all/20210216180754_events.yml3
-rw-r--r--config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml22
-rw-r--r--config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml2
-rw-r--r--config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml2
-rw-r--r--config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml2
-rw-r--r--config/metrics/counts_all/20210715094459_releases_with_milestones.yml2
-rw-r--r--config/metrics/counts_all/20210730011801_projects_zentao_active.yml22
-rw-r--r--config/metrics/counts_all/20210730011802_groups_zentao_active.yml22
-rw-r--r--config/metrics/counts_all/20210730011804_instances_zentao_active.yml22
-rw-r--r--config/metrics/counts_all/20210730011805_projects_inheriting_zentao_active.yml22
-rw-r--r--config/metrics/counts_all/20210730011806_groups_inheriting_zentao_active.yml22
-rw-r--r--config/metrics/counts_all/20211028210001_projects_shimo_active.yml22
-rw-r--r--config/metrics/counts_all/20211028210002_groups_shimo_active.yml22
-rw-r--r--config/metrics/counts_all/20211028210003_instances_shimo_active.yml22
-rw-r--r--config/metrics/counts_all/20211028210004_projects_inheriting_shimo_active.yml22
-rw-r--r--config/metrics/counts_all/20211028210005_groups_inheriting_shimo_active.yml22
-rw-r--r--config/metrics/schema.json6
-rw-r--r--config/plugins/graphql_known_operations_plugin.js112
-rw-r--r--config/routes.rb11
-rw-r--r--config/routes/explore.rb2
-rw-r--r--config/routes/group.rb9
-rw-r--r--config/routes/project.rb9
-rw-r--r--config/sidekiq_queues.yml16
-rw-r--r--config/webpack.config.js4
-rw-r--r--danger/database/Dangerfile4
-rw-r--r--danger/feature_flag/Dangerfile4
-rw-r--r--danger/metadata/Dangerfile42
-rw-r--r--danger/pipeline/Dangerfile2
-rw-r--r--danger/product_intelligence/Dangerfile12
-rw-r--r--danger/roulette/Dangerfile13
-rw-r--r--danger/specialization_labels/Dangerfile17
-rw-r--r--danger/specs/Dangerfile2
-rw-r--r--danger/z_metadata/Dangerfile39
-rw-r--r--data/deprecations/ runner-s3-authenticationtype-nonexplicit-config-deprecation.yml12
-rw-r--r--data/deprecations/14-0-nfs-fot-git-repository-storage.yml4
-rw-r--r--data/deprecations/14-2-deprecation-task-runner.yml4
-rw-r--r--data/deprecations/14-3-package-container-registry-api-group-update.yml12
-rw-r--r--data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml19
-rw-r--r--data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml11
-rw-r--r--data/deprecations/14-5-deprecate-opensuse-15-2.yml9
-rw-r--r--data/deprecations/14-5-deprecation-vsa-announce-deprecation-of-vsa-filtering-calculation.yml13
-rw-r--r--data/deprecations/14-5-geo-deprecate-promote-db.yml25
-rw-r--r--data/deprecations/14-5-geo-deprecate-promote-to-primary-node.yml25
-rw-r--r--data/deprecations/14-5-runner-api-status-does-contain-paused.yml17
-rw-r--r--data/deprecations/15-0-deprecate-sles-12sp2.yml6
-rw-r--r--data/deprecations/15-0-deprecation-versions-packagetype.yml12
-rw-r--r--data/deprecations/15-0-remove-dependency-proxy-permissions-flag.yml11
-rw-r--r--data/deprecations/15-0-remove-package-pipelines-api.yml11
-rw-r--r--data/deprecations/15-0-remove-pipelines-from-version-field.yml14
-rw-r--r--data/deprecations/deprecate-defaultMergeCommitMessageWithDescription-graphql.yml14
-rw-r--r--data/deprecations/disable_strict_host_key_checking.yml12
-rw-r--r--data/deprecations/templates/_deprecation_template.md.erb16
-rw-r--r--data/deprecations/templates/example.yml7
-rw-r--r--data/deprecations/vsa_warning.pngbin0 -> 57804 bytes
-rw-r--r--db/fixtures/development/15_award_emoji.rb6
-rw-r--r--db/fixtures/development/17_cycle_analytics.rb11
-rw-r--r--db/fixtures/development/20_nested_groups.rb5
-rw-r--r--db/fixtures/development/98_gitlab_instance_administration_project.rb4
-rw-r--r--db/init_structure.sql15539
-rw-r--r--db/migrate/20200102140148_add_expanded_environment_name_to_ci_build_metadata.rb15
-rw-r--r--db/migrate/20200102170221_add_storage_version_index_to_projects.rb17
-rw-r--r--db/migrate/20200103190741_add_column_for_instance_administrators_group.rb12
-rw-r--r--db/migrate/20200103192859_add_fk_for_instance_administrators_group.rb22
-rw-r--r--db/migrate/20200103192914_add_index_for_instance_administrators_group.rb17
-rw-r--r--db/migrate/20200103195205_add_autoclose_referenced_issues_to_projects.rb9
-rw-r--r--db/migrate/20200104113850_add_forking_access_level_to_project_feature.rb9
-rw-r--r--db/migrate/20200106085831_add_timestamps_to_packages_tags.rb23
-rw-r--r--db/migrate/20200107172020_add_timestamp_softwarelicensespolicy.rb15
-rw-r--r--db/migrate/20200108100603_update_project_hooks_limit.rb23
-rw-r--r--db/migrate/20200108155731_create_indexes_for_project_api_created_at_order.rb21
-rw-r--r--db/migrate/20200108233040_remove_index_project_mirror_data_on_jid.rb17
-rw-r--r--db/migrate/20200109030418_add_sorting_index_to_packages.rb21
-rw-r--r--db/migrate/20200109085206_create_approval_project_rules_protected_branches.rb19
-rw-r--r--db/migrate/20200109233938_remove_project_id_index_from_packages.rb17
-rw-r--r--db/migrate/20200110089001_fix_invalid_epic_sourcing_milestone_ids.rb24
-rw-r--r--db/migrate/20200110090153_validate_foreign_key_epic_start_date_sourcing_milestone.rb15
-rw-r--r--db/migrate/20200110144316_add_indexes_for_projects_api.rb31
-rw-r--r--db/migrate/20200110203532_validate_foreign_key_epic_due_date_sourcing_milestone.rb15
-rw-r--r--db/migrate/20200113133352_add_indexes_for_projects_api_authenticated.rb45
-rw-r--r--db/migrate/20200114140305_add_fields_to_application_settings_for_merge_requests_approvals.rb29
-rw-r--r--db/migrate/20200114204949_add_index_to_sentry_issues_sentry_issue_identifier.rb17
-rw-r--r--db/migrate/20200115135132_add_retry_count_and_group_id_to_import_failures.rb11
-rw-r--r--db/migrate/20200115135234_add_group_index_and_fk_to_import_failures.rb22
-rw-r--r--db/migrate/20200116051619_drop_background_migration_jobs.rb18
-rw-r--r--db/migrate/20200116175538_update_timestamp_softwarelicensespolicy.rb28
-rw-r--r--db/migrate/20200117112554_update_project_index_to_import_failures.rb22
-rw-r--r--db/migrate/20200117194830_add_iid_to_operations_feature_flags.rb13
-rw-r--r--db/migrate/20200117194840_add_index_on_operations_feature_flags_iid.rb17
-rw-r--r--db/migrate/20200121132641_update_timestamp_softwarelicensespolicy_not_null.rb15
-rw-r--r--db/migrate/20200121192942_create_geo_events.rb16
-rw-r--r--db/migrate/20200121194000_add_geo_event_id_to_geo_event_log.rb9
-rw-r--r--db/migrate/20200121194048_add_geo_event_id_index_to_geo_event_log.rb20
-rw-r--r--db/migrate/20200121194154_add_geo_events_foreign_key.rb20
-rw-r--r--db/migrate/20200121200203_create_group_deploy_tokens.rb16
-rw-r--r--db/migrate/20200122161638_add_deploy_token_type_to_deploy_tokens.rb17
-rw-r--r--db/migrate/20200123040535_add_multi_column_index_on_lfs_objects_projects.rb17
-rw-r--r--db/migrate/20200123045415_remove_project_id_index_on_lfs_objects_projects.rb17
-rw-r--r--db/migrate/20200123090839_remove_analytics_repository_table_fks_on_projects.rb30
-rw-r--r--db/migrate/20200123091422_remove_analytics_repository_files_fk_on_other_analytics_tables.rb25
-rw-r--r--db/migrate/20200123091622_drop_analytics_repository_files_table.rb23
-rw-r--r--db/migrate/20200123091734_drop_analytics_repository_file_commits_table.rb29
-rw-r--r--db/migrate/20200123091854_drop_analytics_repository_file_edits_table.rb29
-rw-r--r--db/migrate/20200124053531_add_source_to_import_failures.rb11
-rw-r--r--db/migrate/20200124143014_add_restrict_deployment_order_to_project_ci_cd_settings.rb9
-rw-r--r--db/migrate/20200128105731_add_duration_to_merge_trains.rb10
-rw-r--r--db/migrate/20200128141125_add_index_web_hooks_on_group_id.rb17
-rw-r--r--db/migrate/20200128184209_add_usage_to_pages_domains.rb18
-rw-r--r--db/migrate/20200129034515_update_indexes_of_pages_domains_add_usage_domain_wildcard_remove_domain.rb21
-rw-r--r--db/migrate/20200129035446_rename_pages_domains_domain_type_to_scope.rb17
-rw-r--r--db/migrate/20200129133716_add_resource_milestone_events_table.rb27
-rw-r--r--db/migrate/20200129172428_add_index_on_audit_events_id_desc.rb24
-rw-r--r--db/migrate/20200130134335_add_cert_and_key_to_serverless_domain_cluster.rb17
-rw-r--r--db/migrate/20200130161817_drop_unneeded_indexes_for_projects_api_requests.rb31
-rw-r--r--db/migrate/20200131140428_create_index_on_auto_stop_in.rb17
-rw-r--r--db/migrate/20200131181354_add_health_status_to_epics.rb9
-rw-r--r--db/migrate/20200131191754_add_health_status_to_issues.rb9
-rw-r--r--db/migrate/20200202100932_add_service_desk_project_key.rb11
-rw-r--r--db/migrate/20200203015140_add_id_to_design_management_designs_versions.rb9
-rw-r--r--db/migrate/20200203025400_default_lock_version_to_zero_for_merge_requests.rb23
-rw-r--r--db/migrate/20200203025602_default_lock_version_to_zero_for_issues.rb23
-rw-r--r--db/migrate/20200203025619_default_lock_version_to_zero_for_epics.rb23
-rw-r--r--db/migrate/20200203025744_default_lock_version_to_zero_for_ci_builds.rb23
-rw-r--r--db/migrate/20200203025801_default_lock_version_to_zero_for_ci_stages.rb23
-rw-r--r--db/migrate/20200203025821_default_lock_version_to_zero_for_ci_pipelines.rb23
-rw-r--r--db/migrate/20200203173508_add_confirmed_attributes_to_vulnerabilities.rb10
-rw-r--r--db/migrate/20200203183508_add_index_for_vulnerability_confirmed_by.rb19
-rw-r--r--db/migrate/20200203232433_create_security_scan.rb24
-rw-r--r--db/migrate/20200204070729_add_elasticsearch_indexed_field_length_limit_to_application_settings.rb17
-rw-r--r--db/migrate/20200204131054_change_broadcast_message_index.rb19
-rw-r--r--db/migrate/20200204131831_create_daily_report_results.rb24
-rw-r--r--db/migrate/20200205143231_add_dissmised_at_to_user_callouts.rb9
-rw-r--r--db/migrate/20200206112850_create_snippet_repository_table.rb15
-rw-r--r--db/migrate/20200206141511_change_saml_provider_outer_forks_default.rb15
-rw-r--r--db/migrate/20200207062728_add_default_branch_protection_to_namespaces.rb19
-rw-r--r--db/migrate/20200207090921_add_nuget_index_to_packages_packages.rb18
-rw-r--r--db/migrate/20200207132752_add_es_bulk_config.rb11
-rw-r--r--db/migrate/20200207151640_create_deployment_clusters.rb18
-rw-r--r--db/migrate/20200207182131_replace_conan_metadata_index.rb25
-rw-r--r--db/migrate/20200209131152_add_feature_filter_type_to_user_preferences.rb9
-rw-r--r--db/migrate/20200210135504_remove_packages_deprecated_dependencies.rb13
-rw-r--r--db/migrate/20200210184410_create_operations_strategies_table.rb15
-rw-r--r--db/migrate/20200210184420_create_operations_scopes_table.rb16
-rw-r--r--db/migrate/20200211174946_add_auto_renew_to_gitlab_subscriptions.rb10
-rw-r--r--db/migrate/20200212014653_rename_security_dashboard_feature_flag_to_instance_security_dashboard.rb25
-rw-r--r--db/migrate/20200212133945_add_group_hooks_to_plan_limits.rb9
-rw-r--r--db/migrate/20200212134201_insert_group_hooks_plan_limits.rb23
-rw-r--r--db/migrate/20200213093702_add_email_restrictions_to_application_settings.rb17
-rw-r--r--db/migrate/20200213100530_add_verification_columns_to_packages.rb15
-rw-r--r--db/migrate/20200213155311_add_npm_package_requests_forwarding_to_application_settings.rb20
-rw-r--r--db/migrate/20200213224220_add_sprints.rb35
-rw-r--r--db/migrate/20200214025454_add_canonical_emails.rb26
-rw-r--r--db/migrate/20200214085940_clean_grafana_url.rb22
-rw-r--r--db/migrate/20200215222507_drop_forked_project_links_fk.rb26
-rw-r--r--db/migrate/20200215225103_drop_forked_project_links_table.rb21
-rw-r--r--db/migrate/20200218113721_add_indexes_to_package_file.rb19
-rw-r--r--db/migrate/20200219105209_add_filepath_to_release_links.rb8
-rw-r--r--db/migrate/20200219133859_add_environment_id_to_deployment_merge_requests.rb9
-rw-r--r--db/migrate/20200219135440_add_limit_metric_type_to_list.rb9
-rw-r--r--db/migrate/20200219141307_add_environment_id_fk_to_deployment_merge_requests.rb17
-rw-r--r--db/migrate/20200219142522_add_environment_id_merge_request_id_uniq_idx_to_deployment_merge_requests.rb17
-rw-r--r--db/migrate/20200220180944_add_keep_divergent_refs.rb11
-rw-r--r--db/migrate/20200221023320_add_index_on_pages_domain_on_domain_lowercase.rb19
-rw-r--r--db/migrate/20200221074028_add_mr_metrics_first_approved_at.rb13
-rw-r--r--db/migrate/20200221100514_create_users_statistics.rb19
-rw-r--r--db/migrate/20200221105436_update_application_setting_npm_package_requests_forwarding_default.rb17
-rw-r--r--db/migrate/20200221144534_drop_activate_prometheus_services_background_jobs.rb26
-rw-r--r--db/migrate/20200222055543_add_confidential_to_note.rb18
-rw-r--r--db/migrate/20200224020219_add_status_page_settings.rb20
-rw-r--r--db/migrate/20200224163804_add_version_to_feature_flags_table.rb23
-rw-r--r--db/migrate/20200224185814_add_project_subscriptions_to_plan_limits.rb9
-rw-r--r--db/migrate/20200225111018_add_index_for_group_and_iid_search_to_epics.rb22
-rw-r--r--db/migrate/20200225123228_insert_project_subscriptions_plan_limits.rb25
-rw-r--r--db/migrate/20200226100614_create_requirements.rb30
-rw-r--r--db/migrate/20200226100624_requirements_add_project_fk.rb19
-rw-r--r--db/migrate/20200226100634_requirements_add_author_fk.rb19
-rw-r--r--db/migrate/20200226162156_rename_closed_at_to_dismissed_at_in_vulnerabilities.rb17
-rw-r--r--db/migrate/20200226162634_rename_closed_by_to_dismissed_by_in_vulnerabilities.rb17
-rw-r--r--db/migrate/20200227164113_create_scim_identities.rb20
-rw-r--r--db/migrate/20200227165129_create_user_details.rb26
-rw-r--r--db/migrate/20200228160542_create_ci_sources_projects.rb17
-rw-r--r--db/migrate/20200229171700_create_custom_emojis.rb31
-rw-r--r--db/migrate/20200302152516_add_wiki_slug.rb24
-rw-r--r--db/migrate/20200303055348_add_expires_at_to_keys.rb9
-rw-r--r--db/migrate/20200303074328_add_index_on_snippet_description.rb18
-rw-r--r--db/migrate/20200303181648_add_healthy_to_clusters_applications_prometheus.rb15
-rw-r--r--db/migrate/20200304023245_add_sprint_to_issues.rb20
-rw-r--r--db/migrate/20200304023851_add_sprint_to_merge_requests.rb20
-rw-r--r--db/migrate/20200304024025_add_sprint_id_index_to_issues.rb21
-rw-r--r--db/migrate/20200304024042_add_sprint_id_index_to_merge_requests.rb21
-rw-r--r--db/migrate/20200304085423_add_user_type.rb19
-rw-r--r--db/migrate/20200304090155_add_user_type_index.rb17
-rw-r--r--db/migrate/20200304121828_add_ci_sources_project_pipeline_foreign_key.rb19
-rw-r--r--db/migrate/20200304121844_add_ci_sources_project_source_project_foreign_key.rb19
-rw-r--r--db/migrate/20200304124406_add_unlock_membership_to_ldap_of_groups.rb19
-rw-r--r--db/migrate/20200304160800_add_index_services_on_template.rb19
-rw-r--r--db/migrate/20200304160801_delete_template_services_duplicated_by_type.rb25
-rw-r--r--db/migrate/20200304160823_add_index_to_service_unique_template_per_type.rb17
-rw-r--r--db/migrate/20200305020458_add_label_restore_table.rb31
-rw-r--r--db/migrate/20200305020459_add_label_restore_foreign_keys.rb35
-rw-r--r--db/migrate/20200305121159_add_merge_request_metrics_first_reassigned_at.rb19
-rw-r--r--db/migrate/20200305151736_delete_template_project_services.rb19
-rw-r--r--db/migrate/20200305200641_create_terraform_states.rb16
-rw-r--r--db/migrate/20200306095654_add_merge_request_assignee_created_at.rb19
-rw-r--r--db/migrate/20200306160521_add_index_on_author_id_and_created_at_to_events.rb18
-rw-r--r--db/migrate/20200306170211_add_index_on_author_id_and_id_and_created_at_to_issues.rb17
-rw-r--r--db/migrate/20200306170321_add_index_on_user_id_and_created_at_to_ci_pipelines.rb19
-rw-r--r--db/migrate/20200306170531_add_index_on_author_id_and_created_at_to_todos.rb16
-rw-r--r--db/migrate/20200306192548_add_index_on_project_id_and_type_to_services.rb22
-rw-r--r--db/migrate/20200306193236_add_index_on_creator_id_and_created_at_to_projects.rb22
-rw-r--r--db/migrate/20200309140540_add_index_on_project_id_and_repository_access_level_to_project_features.rb18
-rw-r--r--db/migrate/20200309162244_add_open_project_tracker_data.rb25
-rw-r--r--db/migrate/20200309195209_add_index_on_project_id_and_builds_access_level_to_project_features.rb18
-rw-r--r--db/migrate/20200309195710_add_index_on_mirror_and_creator_id_and_created_at_to_projects.rb18
-rw-r--r--db/migrate/20200310123229_add_index_on_enabled_and_provider_type_and_id_to_clusters.rb19
-rw-r--r--db/migrate/20200310132654_add_instance_to_services.rb21
-rw-r--r--db/migrate/20200310133822_add_index_on_author_id_and_id_and_created_at_to_notes.rb19
-rw-r--r--db/migrate/20200310135823_add_index_to_service_unique_instance_per_type.rb17
-rw-r--r--db/migrate/20200310145304_add_runtime_created_to_ci_job_variables.rb19
-rw-r--r--db/migrate/20200311074438_migrate_bot_type_to_user_type.rb13
-rw-r--r--db/migrate/20200311082301_add_user_state_index.rb21
-rw-r--r--db/migrate/20200311084025_add_index_on_user_id_status_created_at_to_deployments.rb17
-rw-r--r--db/migrate/20200311093210_create_user_highest_roles.rb25
-rw-r--r--db/migrate/20200311094020_add_index_on_id_and_status_to_deployments.rb17
-rw-r--r--db/migrate/20200311141053_add_ci_pipeline_schedules_to_plan_limits.rb17
-rw-r--r--db/migrate/20200311141943_insert_ci_pipeline_schedules_plan_limits.rb25
-rw-r--r--db/migrate/20200311154110_create_vulnerability_exports.rb26
-rw-r--r--db/migrate/20200311165635_create_project_export_jobs.rb21
-rw-r--r--db/migrate/20200311214912_add_modsecurity_mode_to_ingress_application.rb19
-rw-r--r--db/migrate/20200312053852_populate_canonical_emails.rb35
-rw-r--r--db/migrate/20200312125121_add_index_on_active_and_template_and_type_and_id_to_services.rb18
-rw-r--r--db/migrate/20200312160532_add_index_on_mirror_and_id_to_projects.rb21
-rw-r--r--db/migrate/20200312163407_add_index_on_id_and_service_desk_enabled_to_projects.rb18
-rw-r--r--db/migrate/20200313101649_fill_ghost_user_type.rb13
-rw-r--r--db/migrate/20200313123934_add_index_on_user_id_type_source_type_ldap_and_created_at_to_members.rb18
-rw-r--r--db/migrate/20200313202430_add_index_chat_name_service_id.rb17
-rw-r--r--db/migrate/20200313203525_add_invalid_foreign_key_from_chat_name_to_service.rb16
-rw-r--r--db/migrate/20200314060834_add_scanned_resources_count_to_security_scan.rb16
-rw-r--r--db/migrate/20200316111759_add_index_on_id_and_ldap_key_to_keys.rb18
-rw-r--r--db/migrate/20200316162648_add_index_on_namespace_id_and_id_to_projects.rb19
-rw-r--r--db/migrate/20200316173312_add_vulnerability_export_project_foreign_key.rb19
-rw-r--r--db/migrate/20200317110602_add_migrating_user_highest_roles_table_index_to_users.rb24
-rw-r--r--db/migrate/20200317142110_add_vulnerability_export_user_foreign_key.rb19
-rw-r--r--db/migrate/20200318140400_create_vulnerability_user_mentions.rb19
-rw-r--r--db/migrate/20200318152134_adds_sha256_to_package_files.rb9
-rw-r--r--db/migrate/20200318162148_add_external_key_to_issues_table.rb19
-rw-r--r--db/migrate/20200318163148_add_index_on_external_key_to_issues_table.rb17
-rw-r--r--db/migrate/20200318164448_add_external_key_to_epics_table.rb19
-rw-r--r--db/migrate/20200318165448_add_index_on_external_key_to_epics_table.rb17
-rw-r--r--db/migrate/20200318175008_add_index_on_id_and_archived_and_pending_delete_to_projects.rb18
-rw-r--r--db/migrate/20200318183553_create_pypi_package_metadata.rb14
-rw-r--r--db/migrate/20200319123041_update_plan_limits_defaults.rb19
-rw-r--r--db/migrate/20200319124127_create_metrics_dashboard_annotations.rb26
-rw-r--r--db/migrate/20200319203901_add_index_on_users_unlock_token.rb18
-rw-r--r--db/migrate/20200320112455_add_cost_factor_fileds_to_ci_runners.rb19
-rw-r--r--db/migrate/20200320123839_add_letsencrypt_errors_to_pages_domains.rb20
-rw-r--r--db/migrate/20200320212400_add_project_show_default_award_emojis.rb11
-rw-r--r--db/migrate/20200323071918_add_bio_to_user_details.rb21
-rw-r--r--db/migrate/20200323074147_add_temp_index_on_users_bio.rb18
-rw-r--r--db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb19
-rw-r--r--db/migrate/20200323122201_add_index_on_user_and_created_at_to_ci_builds.rb19
-rw-r--r--db/migrate/20200323134519_add_api_indexes_for_archived_projects.rb27
-rw-r--r--db/migrate/20200324093258_add_index_on_id_creator_id_and_created_at_to_projects_table.rb18
-rw-r--r--db/migrate/20200324115359_add_namespace_storage_size_limit_to_application_settings.rb16
-rw-r--r--db/migrate/20200325094612_add_allow_merge_on_skipped_pipeline_to_project_settings.rb9
-rw-r--r--db/migrate/20200325104755_add_push_rules_id_to_project_settings.rb19
-rw-r--r--db/migrate/20200325104756_add_push_rules_foreign_key_to_project_settings.rb18
-rw-r--r--db/migrate/20200325104833_add_push_rules_id_to_application_settings.rb19
-rw-r--r--db/migrate/20200325104834_add_push_rules_foreign_key_to_application_settings.rb18
-rw-r--r--db/migrate/20200325111432_add_issues_create_limit_to_application_settings.rb9
-rw-r--r--db/migrate/20200325152327_add_seat_link_enabled_to_application_settings.rb20
-rw-r--r--db/migrate/20200325160952_add_index_on_name_type_eq_ci_build_to_ci_builds.rb21
-rw-r--r--db/migrate/20200325183636_add_api_index_for_internal_projects.rb21
-rw-r--r--db/migrate/20200326114443_create_jira_imports_table.rb31
-rw-r--r--db/migrate/20200326122700_create_diff_note_positions.rb35
-rw-r--r--db/migrate/20200326124443_add_projects_fk_to_jira_imports_table.rb19
-rw-r--r--db/migrate/20200326134443_add_users_fk_to_jira_imports_table.rb19
-rw-r--r--db/migrate/20200326135443_add_users_fk_index_on_jira_imports_table.rb17
-rw-r--r--db/migrate/20200326144443_add_labels_fk_to_jira_imports_table.rb19
-rw-r--r--db/migrate/20200326145443_add_labels_fk_index_on_jira_imports_table.rb17
-rw-r--r--db/migrate/20200330074719_add_index_for_group_vsm_usage_ping.rb18
-rw-r--r--db/migrate/20200330121000_add_confidential_attribute_to_epics.rb17
-rw-r--r--db/migrate/20200330123739_remove_index_ci_builds_on_name_for_security_reports_values.rb22
-rw-r--r--db/migrate/20200330132913_add_index_on_author_id_and_created_at_and_id_to_notes.rb19
-rw-r--r--db/migrate/20200330203826_drop_fk_in_ci_ref.rb32
-rw-r--r--db/migrate/20200330203837_recreate_ci_ref.rb43
-rw-r--r--db/migrate/20200331103637_add_ci_ref_id_to_ci_pipelines.rb19
-rw-r--r--db/migrate/20200331113728_add_index_to_ci_ref_id.rb16
-rw-r--r--db/migrate/20200331113738_add_fk_to_ci_ref_id.rb18
-rw-r--r--db/migrate/20200331132103_add_project_compliance_framework_settings_table.rb22
-rw-r--r--db/migrate/20200331195952_add_container_expiration_policies_enable_historic_entries_to_application_settings.rb22
-rw-r--r--db/migrate/20200331220930_enable_container_expiration_policies_by_default.rb19
-rw-r--r--db/migrate/20200401095430_add_jsonb_to_geo_node_status_table.rb14
-rw-r--r--db/migrate/20200401211005_create_operations_user_lists.rb18
-rw-r--r--db/migrate/20200402001106_add_cluster_type_index_to_clusters.rb19
-rw-r--r--db/migrate/20200402115013_add_index_on_modsecurity_to_ingress.rb18
-rw-r--r--db/migrate/20200402115623_add_index_on_successful_deployment_and_environment_id_to_deployments.rb18
-rw-r--r--db/migrate/20200402123926_add_line_metrics_to_mr_metrics.rb21
-rw-r--r--db/migrate/20200402124802_add_correlation_id_to_project_import_state.rb21
-rw-r--r--db/migrate/20200402135250_add_delete_status_to_container_repository.rb13
-rw-r--r--db/migrate/20200402185044_create_clusters_applications_fluentd.rb20
-rw-r--r--db/migrate/20200403184110_add_partial_index_on_id_to_ci_job_artifacts.rb18
-rw-r--r--db/migrate/20200403185127_add_partial_index_on_id_to_lfs_objects.rb18
-rw-r--r--db/migrate/20200403185422_add_partial_index_on_id_to_uploads.rb18
-rw-r--r--db/migrate/20200406095930_add_needs_ssl_renewal_user_provided_pages_domains_index.rb20
-rw-r--r--db/migrate/20200406100909_add_needs_ssl_renewal_valid_not_after_pages_domains_index.rb20
-rw-r--r--db/migrate/20200406102111_add_index_to_deployments_where_cluster_id_is_not_null.rb17
-rw-r--r--db/migrate/20200406132529_add_resource_state_events_table.rb20
-rw-r--r--db/migrate/20200406135648_add_index_to_created_at_on_resource_milestone_events.rb19
-rw-r--r--db/migrate/20200406141452_add_index_to_issue_id_and_created_at_on_resource_weight_events.rb19
-rw-r--r--db/migrate/20200406192059_add_write_registry_to_deploy_tokens.rb17
-rw-r--r--db/migrate/20200407120000_add_push_rule_id_to_groups.rb19
-rw-r--r--db/migrate/20200407121321_add_push_rule_foreign_key_to_groups.rb18
-rw-r--r--db/migrate/20200407171133_add_protected_tag_create_access_levels_user_id_foreign_key.rb32
-rw-r--r--db/migrate/20200407171417_validate_protected_tag_create_access_levels_user_id_foreign_key.rb16
-rw-r--r--db/migrate/20200407182205_create_partitioned_foreign_keys.rb31
-rw-r--r--db/migrate/20200407222647_create_project_repository_storage_moves.rb31
-rw-r--r--db/migrate/20200408125046_create_ci_freeze_periods.rb30
-rw-r--r--db/migrate/20200408133211_add_index_on_route_path_trigram.rb18
-rw-r--r--db/migrate/20200408153842_add_index_on_creator_id_and_id_on_projects.rb17
-rw-r--r--db/migrate/20200408154331_add_protected_branch_merge_access_levels_user_id_foreign_key.rb32
-rw-r--r--db/migrate/20200408154349_validate_protected_branch_merge_access_levels_user_id_foreign_key.rb16
-rw-r--r--db/migrate/20200408154411_add_path_locks_user_id_foreign_key.rb32
-rw-r--r--db/migrate/20200408154428_validate_path_locks_user_id_foreign_key.rb16
-rw-r--r--db/migrate/20200408154455_add_protected_branch_push_access_levels_user_id_foreign_key.rb32
-rw-r--r--db/migrate/20200408154533_validate_protected_branch_push_access_levels_user_id_foreign_key.rb16
-rw-r--r--db/migrate/20200408154604_add_u2f_registrations_user_id_foreign_key.rb32
-rw-r--r--db/migrate/20200408154624_validate_u2f_registrations_user_id_foreign_key.rb16
-rw-r--r--db/migrate/20200408175424_add_index_on_creator_id_created_at_id_to_projects_table.rb17
-rw-r--r--db/migrate/20200408212219_add_status_page_url_to_status_page_settings.rb18
-rw-r--r--db/migrate/20200409085956_add_partial_index_on_import_failures_retry_count.rb17
-rw-r--r--db/migrate/20200409105455_change_verification_checksum_field_type_in_package_file.rb17
-rw-r--r--db/migrate/20200409105456_add_checksum_index_to_package_file.rb17
-rw-r--r--db/migrate/20200410104828_add_comment_detail_to_services.rb13
-rw-r--r--db/migrate/20200410232012_add_metrics_dashboard_access_level_to_project_feature.rb19
-rw-r--r--db/migrate/20200411125656_add_package_scopes_to_deploy_tokens.rb19
-rw-r--r--db/migrate/20200413072059_add_group_owners_can_manage_default_branch_protection_to_application_settings.rb19
-rw-r--r--db/migrate/20200413230056_add_waf_and_cilium_logs_to_applications_fluentd.rb29
-rw-r--r--db/migrate/20200414112444_add_group_id_to_vulnerability_exports.rb10
-rw-r--r--db/migrate/20200414114611_add_group_id_index_and_fk_to_vulnerability_exports.rb20
-rw-r--r--db/migrate/20200414115801_change_project_index_on_vulnerability_exports.rb21
-rw-r--r--db/migrate/20200414144547_remove_index_projects_on_creator_id_and_created_at_from_projects.rb18
-rw-r--r--db/migrate/20200415153154_add_unique_index_on_plan_name.rb19
-rw-r--r--db/migrate/20200415160722_remove_not_null_lfs_objects_constraint.rb19
-rw-r--r--db/migrate/20200415161021_remove_not_null_ci_job_artifacts_constraint.rb19
-rw-r--r--db/migrate/20200415161206_remove_not_null_uploads_constraint.rb19
-rw-r--r--db/migrate/20200415192656_add_name_regex_keep_to_container_expiration_policies.rb21
-rw-r--r--db/migrate/20200415203024_add_offset_pagination_plan_limit.rb9
-rw-r--r--db/migrate/20200416005331_create_status_page_published_incidents.rb20
-rw-r--r--db/migrate/20200416120128_add_columns_to_terraform_state.rb19
-rw-r--r--db/migrate/20200416120354_add_locked_by_user_id_foreign_key_to_terraform_state.rb19
-rw-r--r--db/migrate/20200417044453_create_alert_management_alerts.rb44
-rw-r--r--db/migrate/20200417075843_remove_and_add_foreign_key_to_project_settings.rb19
-rw-r--r--db/migrate/20200417145946_add_locked_to_ci_job_artifact.rb19
-rw-r--r--db/migrate/20200420092011_add_profile_image_guidelines_to_appearances.rb21
-rw-r--r--db/migrate/20200420104303_add_group_import_states_table.rb25
-rw-r--r--db/migrate/20200420104323_add_text_limit_to_group_import_states.rb19
-rw-r--r--db/migrate/20200420115948_create_metrics_users_starred_dashboard.rb25
-rw-r--r--db/migrate/20200420141733_add_index_on_enabled_clusters.rb18
-rw-r--r--db/migrate/20200420172113_add_text_limit_to_sprints_title.rb19
-rw-r--r--db/migrate/20200420172752_add_sprints_foreign_key_to_projects.rb19
-rw-r--r--db/migrate/20200420172927_add_sprints_foreign_key_to_groups.rb19
-rw-r--r--db/migrate/20200420201933_add_check_constraint_to_sprint_must_belong_to_project_or_group.rb19
-rw-r--r--db/migrate/20200421054930_remove_index_on_pipeline_id_from_ci_pipeline_variables.rb18
-rw-r--r--db/migrate/20200421054948_remove_index_on_pipeline_id_from_ci_variables.rb18
-rw-r--r--db/migrate/20200421092907_add_index_container_repository_on_name_trigram_to_container_repository.rb18
-rw-r--r--db/migrate/20200421111005_create_daily_build_group_report_results.rb21
-rw-r--r--db/migrate/20200421233150_add_foreign_keys_for_alert_management_alerts.rb19
-rw-r--r--db/migrate/20200422091541_create_ci_instance_variables.rb31
-rw-r--r--db/migrate/20200422213749_create_operations_strategies_user_lists.rb14
-rw-r--r--db/migrate/20200423075720_add_user_id_foreign_key_to_resource_state_events.rb19
-rw-r--r--db/migrate/20200423080334_add_issue_id_foreign_key_to_resource_state_events.rb19
-rw-r--r--db/migrate/20200423080607_add_merge_request_id_foreign_key_to_resource_state_events.rb19
-rw-r--r--db/migrate/20200423081409_add_constraint_to_resource_state_events_must_belong_to_issue_or_merge_request.rb19
-rw-r--r--db/migrate/20200423081441_add_foreign_key_from_users_to_metrics_users_starred_dashboars.rb18
-rw-r--r--db/migrate/20200423081519_add_foreign_key_from_projects_to_metrics_users_starred_dashboars.rb18
-rw-r--r--db/migrate/20200423101529_add_scheduled_at_to_jira_imports.rb9
-rw-r--r--db/migrate/20200424050250_remove_orphaned_invited_members.rb13
-rw-r--r--db/migrate/20200424101920_add_text_limit_to_metrics_users_starred_dashboards_dashboard_path.rb16
-rw-r--r--db/migrate/20200424102023_add_shared_runners_enabled_and_override_to_namespaces.rb21
-rw-r--r--db/migrate/20200424135319_create_nuget_dependency_link_metadata.rb26
-rw-r--r--db/migrate/20200429001827_sprint_rename_state_to_state_enum.rb17
-rw-r--r--db/migrate/20200429015603_add_fk_to_project_repository_storage_moves.rb19
-rw-r--r--db/migrate/20200429023324_add_composer_metadata.rb12
-rw-r--r--db/migrate/20200429181335_add_default_value_for_file_store_to_lfs_objects.rb19
-rw-r--r--db/migrate/20200429181955_add_default_value_for_file_store_to_ci_job_artifacts.rb19
-rw-r--r--db/migrate/20200429182245_add_default_value_for_store_to_uploads.rb19
-rw-r--r--db/migrate/20200430103158_create_group_wiki_repositories.rb15
-rw-r--r--db/migrate/20200430123614_create_project_access_tokens.rb14
-rw-r--r--db/migrate/20200430130048_create_packages_nuget_metadata.rb34
-rw-r--r--db/migrate/20200430174637_create_group_deploy_keys.rb36
-rw-r--r--db/migrate/20200504191813_add_fingerprint_to_events.rb36
-rw-r--r--db/migrate/20200504200709_add_index_on_fingerprint_and_target_type_to_events.rb19
-rw-r--r--db/migrate/20200505164958_add_registry_settings_to_application_settings.rb30
-rw-r--r--db/migrate/20200505171834_add_text_limit_to_container_registry_vendor.rb17
-rw-r--r--db/migrate/20200505172405_add_text_limit_to_container_registry_version.rb17
-rw-r--r--db/migrate/20200507221434_add_container_registry_features_to_application_settings.rb13
-rw-r--r--db/migrate/20200508021128_remove_ultraauth_provider_from_identities.rb18
-rw-r--r--db/migrate/20200508050301_add_spam_check_endpoint_to_application_settings.rb34
-rw-r--r--db/migrate/20200508140959_add_elasticsearch_pause_indexing_to_application_settings.rb19
-rw-r--r--db/migrate/20200508203901_add_repository_storages_weighted_to_application_settings.rb39
-rw-r--r--db/migrate/20200509203901_reseed_repository_storages_weighted.rb37
-rw-r--r--db/migrate/20200510181937_add_web_authn_xid_to_user_details.rb12
-rw-r--r--db/migrate/20200510182218_add_text_limit_to_user_details_webauthn_xid.rb16
-rw-r--r--db/migrate/20200510182556_add_text_limit_to_webauthn_registrations_name.rb16
-rw-r--r--db/migrate/20200510182824_add_text_limit_to_webauthn_registrations_credential_xid.rb16
-rw-r--r--db/migrate/20200510183128_add_foreign_key_from_webauthn_registrations_to_users.rb21
-rw-r--r--db/migrate/20200511092246_add_epic_id_to_resource_state_events.rb17
-rw-r--r--db/migrate/20200511092505_add_foreign_key_to_epic_id_on_resource_state_events.rb19
-rw-r--r--db/migrate/20200511115430_add_inherit_from_to_services.rb9
-rw-r--r--db/migrate/20200511115431_add_index_inherit_from_id_to_services.rb21
-rw-r--r--db/migrate/20200511121549_add_group_wiki_repositories_shard_id_foreign_key.rb19
-rw-r--r--db/migrate/20200511121610_add_group_wiki_repositories_group_id_foreign_key.rb19
-rw-r--r--db/migrate/20200511121620_add_group_wiki_repositories_disk_path_limit.rb18
-rw-r--r--db/migrate/20200511130129_remove_deprecated_jenkins_service_records.rb17
-rw-r--r--db/migrate/20200511181027_create_test_reports.rb18
-rw-r--r--db/migrate/20200511191027_add_author_foreign_key_to_test_reports.rb19
-rw-r--r--db/migrate/20200511208012_add_pipeline_foreign_key_to_test_reports.rb19
-rw-r--r--db/migrate/20200512085150_change_default_value_of_protected_ci_variables_of_application_settings_to_true.rb9
-rw-r--r--db/migrate/20200512160004_add_index_to_ci_job_artifacts_for_terraform_reports.rb18
-rw-r--r--db/migrate/20200512164334_sprint_make_state_enum_not_null_and_default.rb15
-rw-r--r--db/migrate/20200512195442_update_index_on_name_type_eq_ci_build_to_ci_builds.rb36
-rw-r--r--db/migrate/20200513160930_fix_not_null_check_constraint_inconsistency.rb20
-rw-r--r--db/migrate/20200513224143_add_section_to_approval_merge_request_rule.rb21
-rw-r--r--db/migrate/20200513234502_fill_file_store_lfs_objects.rb19
-rw-r--r--db/migrate/20200513235347_fill_store_uploads.rb19
-rw-r--r--db/migrate/20200513235532_fill_file_store_ci_job_artifacts.rb21
-rw-r--r--db/migrate/20200515152649_enable_btree_gist_extension.rb15
-rw-r--r--db/migrate/20200515153633_iteration_date_range_constraint.rb39
-rw-r--r--db/migrate/20200515155620_add_index_non_requested_project_members_on_source_id_source_type.rb17
-rw-r--r--db/migrate/20200518091745_add_index_to_personal_access_token_impersonation.rb26
-rw-r--r--db/migrate/20200519074709_update_resource_state_events_constraint_to_support_epic_id.rb24
-rw-r--r--db/migrate/20200519101002_add_error_message_column_to_jira_imports.rb22
-rw-r--r--db/migrate/20200519115908_add_epics_confidential_index.rb17
-rw-r--r--db/migrate/20200519141534_add_instance_level_variables_column_to_plan_limits.rb9
-rw-r--r--db/migrate/20200519194042_update_container_expiration_policies_defaults.rb23
-rw-r--r--db/migrate/20200520103514_add_todo_resolved_by_action.rb19
-rw-r--r--db/migrate/20200521022725_add_experience_level_to_user_preferences.rb9
-rw-r--r--db/migrate/20200521225327_create_alert_management_alert_assignees.rb22
-rw-r--r--db/migrate/20200521225337_add_foreign_key_to_user_id_on_alert_management_alert_assignees.rb19
-rw-r--r--db/migrate/20200521225346_add_foreign_key_to_alert_id_on_alert_mangagement_alert_assignees.rb19
-rw-r--r--db/migrate/20200522205606_create_group_deploy_keys_group.rb25
-rw-r--r--db/migrate/20200522235146_add_index_on_snippet_type_and_id.rb17
-rw-r--r--db/migrate/20200524104346_add_source_to_resource_state_event.rb21
-rw-r--r--db/migrate/20200525114553_rename_user_type_index.rb19
-rw-r--r--db/migrate/20200526013844_add_alert_events_to_services.rb19
-rw-r--r--db/migrate/20200526120714_change_partial_indexes_on_services.rb26
-rw-r--r--db/migrate/20200526142550_drop_null_constraint_on_group_import_state_jid.rb13
-rw-r--r--db/migrate/20200526153844_add_issues_last_edited_by_id_index.rb19
-rw-r--r--db/migrate/20200526164946_create_operations_feature_flags_issues.rb15
-rw-r--r--db/migrate/20200526164947_add_foreign_key_to_ops_feature_flags_issues.rb19
-rw-r--r--db/migrate/20200526193555_add_squash_option_to_project.rb9
-rw-r--r--db/migrate/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type.rb116
-rw-r--r--db/migrate/20200527092027_add_link_type_to_release_links.rb19
-rw-r--r--db/migrate/20200527135313_add_requirements_build_reference.rb23
-rw-r--r--db/migrate/20200527151413_create_ci_build_report_results_table.rb13
-rw-r--r--db/migrate/20200527152116_add_foreign_key_to_build_id_on_build_report_results.rb19
-rw-r--r--db/migrate/20200527152657_add_foreign_key_to_project_id_on_build_report_results.rb19
-rw-r--r--db/migrate/20200527170649_create_alert_management_alert_user_mentions.rb20
-rw-r--r--db/migrate/20200527211000_add_max_import_size.rb15
-rw-r--r--db/migrate/20200527211605_add_locked_to_ci_pipelines.rb19
-rw-r--r--db/migrate/20200528054112_add_index_to_package_name.rb19
-rw-r--r--db/migrate/20200528125905_add_project_id_user_id_status_ref_index_to_ci_pipelines.rb27
-rw-r--r--db/migrate/20200528171933_remove_not_null_from_external_dashboard_url.rb12
-rw-r--r--db/migrate/20200601210148_add_dashboard_timezone_to_project_metrics_setting.rb12
-rw-r--r--db/migrate/20200603073101_change_constraint_name_on_resource_state_events.rb16
-rw-r--r--db/migrate/20200603180338_add_enforce_pat_expiration_to_application_settings.rb9
-rw-r--r--db/migrate/20200604001128_add_secrets_to_ci_builds_metadata.rb19
-rw-r--r--db/migrate/20200604143628_create_project_security_settings.rb27
-rw-r--r--db/migrate/20200604145731_create_board_user_preferences.rb20
-rw-r--r--db/migrate/20200604174544_add_users_foreign_key_to_board_user_preferences.rb19
-rw-r--r--db/migrate/20200604174558_add_boards_foreign_key_to_board_user_preferences.rb19
-rw-r--r--db/migrate/20200605003204_add_foreign_key_to_alert_management_alert_user_mentions.rb19
-rw-r--r--db/migrate/20200605093113_add_ip_address_to_audit_events.rb9
-rw-r--r--db/migrate/20200605160806_add_index_on_repository_size_and_project_id_to_project_statistics.rb17
-rw-r--r--db/migrate/20200605160836_add_index_on_storage_size_and_project_id_to_project_statistics.rb17
-rw-r--r--db/migrate/20200605160851_add_index_on_wiki_size_and_project_id_to_project_statistics.rb17
-rw-r--r--db/migrate/20200607223047_create_cluster_agents.rb31
-rw-r--r--db/migrate/20200607235435_create_cluster_agent_tokens.rb27
-rw-r--r--db/migrate/20200608214008_change_column_default_project_incident_management_settings.rb13
-rw-r--r--db/migrate/20200609012539_add_traversal_ids_to_namespaces.rb19
-rw-r--r--db/migrate/20200609142506_remove_not_null_constraint_from_weight_events_table.rb9
-rw-r--r--db/migrate/20200609142507_remove_not_null_constraint_from_milestone_events_table.rb9
-rw-r--r--db/migrate/20200609142508_remove_not_null_constraint_from_state_events_table.rb9
-rw-r--r--db/migrate/20200609212701_add_incident_settings_to_all_existing_projects.rb40
-rw-r--r--db/migrate/20200610033228_create_terraform_state_versions.rb28
-rw-r--r--db/migrate/20200610040615_add_versioning_enabled_to_terraform_states.rb9
-rw-r--r--db/migrate/20200610130002_create_vulnerability_statistics.rb30
-rw-r--r--db/migrate/20200611013227_add_users_foreign_key_to_terraform_state_versions.rb19
-rw-r--r--db/migrate/20200613104045_add_compliance_frameworks_to_application_settings.rb19
-rw-r--r--db/migrate/20200615083635_add_composer_json_to_metadata.rb9
-rw-r--r--db/migrate/20200615121217_add_projects_foreign_key_to_project_access_tokens.rb17
-rw-r--r--db/migrate/20200615123055_add_personal_access_token_foreign_key_to_project_access_tokens.rb17
-rw-r--r--db/migrate/20200615141554_add_closed_by_fields_to_resource_state_events.rb17
-rw-r--r--db/migrate/20200615193524_add_verify_known_sign_in_to_application_settings.rb9
-rw-r--r--db/migrate/20200615232735_add_index_to_composer_metadata.rb17
-rw-r--r--db/migrate/20200615234047_create_clusters_applications_cilium.rb14
-rw-r--r--db/migrate/20200616124338_add_plan_limits_for_max_size_per_artifact_type.rb48
-rw-r--r--db/migrate/20200616145031_add_author_id_index_to_audit_events.rb22
-rw-r--r--db/migrate/20200617000757_clean_up_file_store_lfs_objects.rb21
-rw-r--r--db/migrate/20200617001001_clean_up_store_uploads.rb21
-rw-r--r--db/migrate/20200617001118_clean_up_file_store_ci_job_artifacts.rb23
-rw-r--r--db/migrate/20200617150041_create_namespace_limits.rb22
-rw-r--r--db/migrate/20200617205000_add_deploy_key_id_to_push_access_levels.rb22
-rw-r--r--db/migrate/20200618105638_add_index_on_id_and_created_at_to_snippets.rb17
-rw-r--r--db/migrate/20200618134223_restore_previous_schema_without_lock_version_null_constraint.rb20
-rw-r--r--db/migrate/20200618134723_restore_previous_schema_with_lock_version_indices.rb22
-rw-r--r--db/migrate/20200619000316_add_has_confluence_to_project_settings.rb19
-rw-r--r--db/migrate/20200619154527_add_project_key_to_jira_tracker_data.rb12
-rw-r--r--db/migrate/20200619154528_add_text_limit_to_jira_tracker_data_project_key.rb17
-rw-r--r--db/migrate/20200622040750_add_prometheus_alert_id_to_alert_management_alerts.rb16
-rw-r--r--db/migrate/20200622070606_add_vendor_to_vulnerability_scanners.rb23
-rw-r--r--db/migrate/20200622070620_add_limit_to_vulnerability_scanners_vendor.rb17
-rw-r--r--db/migrate/20200622095419_add_snippets_size_to_project_statistics.rb9
-rw-r--r--db/migrate/20200622103836_create_snippet_statistics.rb24
-rw-r--r--db/migrate/20200622104923_create_ci_pipeline_messages_table.rb27
-rw-r--r--db/migrate/20200622235737_remove_index_ci_job_artifacts_file_store_is_null.rb18
-rw-r--r--db/migrate/20200623000148_remove_index_lfs_objects_file_store_is_null.rb18
-rw-r--r--db/migrate/20200623000320_remove_index_uploads_store_is_null.rb18
-rw-r--r--db/migrate/20200623073431_add_source_merge_request_id_to_resource_state_events.rb33
-rw-r--r--db/migrate/20200623090030_add_author_name_to_audit_event.rb22
-rw-r--r--db/migrate/20200623121135_create_dynamic_partitions_schema.rb19
-rw-r--r--db/migrate/20200623141217_add_view_diffs_file_by_file_to_user_preferences.rb21
-rw-r--r--db/migrate/20200623141544_create_elastic_reindexing_task.rb33
-rw-r--r--db/migrate/20200623170000_create_static_partitions_schema.rb19
-rw-r--r--db/migrate/20200623185440_add_product_analytics_table.rb202
-rw-r--r--db/migrate/20200624075411_add_storage_size_limit_to_plan_limit.rb9
-rw-r--r--db/migrate/20200624142107_create_analytics_cycle_analytics_group_value_streams.rb33
-rw-r--r--db/migrate/20200624142207_add_group_value_stream_to_cycle_analytics_group_stages.rb19
-rw-r--r--db/migrate/20200624222443_add_default_branch_name_to_application_settings.rb12
-rw-r--r--db/migrate/20200625045442_add_idx_and_fk_for_prometheus_and_environment_to_alert_management_alerts.rb25
-rw-r--r--db/migrate/20200625082258_add_snippets_size_to_root_storage_statistics.rb19
-rw-r--r--db/migrate/20200625113337_add_last_used_to_personal_access_tokens.rb19
-rw-r--r--db/migrate/20200625174052_add_partial_index_to_locked_pipelines.rb17
-rw-r--r--db/migrate/20200625190458_add_limit_to_default_branch_name_to_application_settings.rb17
-rw-r--r--db/migrate/20200625193358_increase_size_on_instance_level_variable_values.rb21
-rw-r--r--db/migrate/20200626130220_drop_partitions_dynamic_schema_if_exists.rb14
-rw-r--r--db/migrate/20200628210938_add_maintenance_mode_application_to_settings.rb29
-rw-r--r--db/migrate/20200629134747_add_extra_index_to_label_links.rb26
-rw-r--r--db/migrate/20200629192638_add_uniq_index_on_metric_identifier_and_project_id.rb17
-rw-r--r--db/migrate/20200630091656_add_bio_html_to_user_details.rb24
-rw-r--r--db/migrate/20200630110826_add_documents_count_target_to_elastic_reindexing_tasks.rb9
-rw-r--r--db/migrate/20200701064756_add_not_valid_foreign_key_to_cycle_analytics_group_stages.rb22
-rw-r--r--db/migrate/20200701093859_add_import_export_limits_to_application_settings.rb15
-rw-r--r--db/migrate/20200701190523_add_delayed_project_removal_to_namespaces.rb19
-rw-r--r--db/migrate/20200701205710_create_background_migration_jobs.rb29
-rw-r--r--db/migrate/20200701221303_change_default_value_of_ci_max_artifact_size_terraform_of_plan_limits_from_0_to_5.rb21
-rw-r--r--db/migrate/20200702123805_change_project_id_index_to_be_unique_on_vulnerability_statistics_table.rb17
-rw-r--r--db/migrate/20200702201039_change_prometheus_metrics_identifier_index.rb22
-rw-r--r--db/migrate/20200703035021_add_notes_to_timelogs.rb25
-rw-r--r--db/migrate/20200703121557_remove_f_keys_from_ci_daily_report_results_table.rb21
-rw-r--r--db/migrate/20200703124823_create_namespace_settings.rb22
-rw-r--r--db/migrate/20200703154822_add_issues_enabled_to_jira_tracker_data.rb9
-rw-r--r--db/migrate/20200706005325_remove_elastic_batch_project_indexer_worker_queue.rb11
-rw-r--r--db/migrate/20200706035141_adjust_unique_index_alert_management_alerts.rb35
-rw-r--r--db/migrate/20200706170536_add_temporary_storage_increase_to_namespace_limits.rb9
-rw-r--r--db/migrate/20200707071941_drop_old_non_unique_index_on_mr_metrics.rb18
-rw-r--r--db/migrate/20200707094341_add_browser_performance_to_plan_limits.rb9
-rw-r--r--db/migrate/20200707095849_add_load_performance_to_plan_limits.rb9
-rw-r--r--db/migrate/20200708080631_add_pager_duty_integration_columns_to_project_incident_management_settings.rb13
-rw-r--r--db/migrate/20200710105332_change_issues_create_limit_default.rb19
-rw-r--r--db/migrate/20200710113437_add_container_registry_delete_tags_service_timeout_to_application_settings.rb19
-rw-r--r--db/migrate/20200710130234_add_limit_constraints_to_project_incident_management_settings_token.rb18
-rw-r--r--db/migrate/20200710152642_add_verification_state_to_terraform_states.rb19
-rw-r--r--db/migrate/20200710153009_add_verification_failure_limit_and_index_to_terraform_states.rb21
-rw-r--r--db/migrate/20200712084655_create_dast_sites.rb27
-rw-r--r--db/migrate/20200712235622_create_dast_site_profiles.rb28
-rw-r--r--db/migrate/20200713141854_add_wiki_page_max_content_bytes_to_application_settings.rb9
-rw-r--r--db/migrate/20200713152443_add_background_migration_job_index_for_partitioning_migrations.rb18
-rw-r--r--db/migrate/20200715124210_add_target_details_to_audit_event.rb21
-rw-r--r--db/migrate/20200715135130_create_vulnerability_historical_statistics.rb34
-rw-r--r--db/migrate/20200715171155_add_deployment_type_to_tracker.rb9
-rw-r--r--db/migrate/20200715202659_add_index_on_package_files_file_store.rb17
-rw-r--r--db/migrate/20200716044023_add_entity_path_to_audit_events.rb21
-rw-r--r--db/migrate/20200716120000_partition_audit_events.rb19
-rw-r--r--db/migrate/20200716120419_add_text_limit_on_entity_path_to_audit_events.rb17
-rw-r--r--db/migrate/20200716145156_add_text_limit_to_audit_event_target_details.rb17
-rw-r--r--db/migrate/20200717040735_change_aws_roles_role_arn_null.rb15
-rw-r--r--db/migrate/20200717080257_add_prevent_forking_to_namespace_settings.rb9
-rw-r--r--db/migrate/20200717163656_add_moved_project_to_notification_settings.rb9
-rw-r--r--db/migrate/20200718040100_add_index_on_merge_request_diffs_external_diff_store.rb17
-rw-r--r--db/migrate/20200718040200_add_index_on_terraform_states_file_store.rb17
-rw-r--r--db/migrate/20200718040300_add_index_on_vulnerability_exports_file_store.rb17
-rw-r--r--db/migrate/20200720053909_add_elasticsearch_indexed_file_size_limit_kb_to_application_settings.rb13
-rw-r--r--db/migrate/20200720154007_create_vulnerabilities_export_verification_status.rb42
-rw-r--r--db/migrate/20200720154123_add_external_to_custom_emoji.rb9
-rw-r--r--db/migrate/20200720191134_add_blocking_issues_count_to_issues.rb28
-rw-r--r--db/migrate/20200721034536_add_issue_type_to_issues.rb20
-rw-r--r--db/migrate/20200721043502_add_issue_type_index_to_issues.rb21
-rw-r--r--db/migrate/20200721052853_create_dast_scanner_profile.rb32
-rw-r--r--db/migrate/20200721230558_add_index_to_projects_aimed_for_deletion.rb27
-rw-r--r--db/migrate/20200722075411_add_ci_needs_size_limit_to_plan_limit.rb9
-rw-r--r--db/migrate/20200722084623_add_default_membership_role_to_saml_provider.rb11
-rw-r--r--db/migrate/20200722091435_add_relative_position_to_design_management_designs.rb9
-rw-r--r--db/migrate/20200722131241_create_resource_iteration_events_table.rb16
-rw-r--r--db/migrate/20200722132040_add_users_fk_to_resource_iteration_events_table.rb19
-rw-r--r--db/migrate/20200722132540_add_issues_fk_to_resource_iteration_events_table.rb19
-rw-r--r--db/migrate/20200722133040_add_merge_requests_fk_to_resource_iteration_events_table.rb19
-rw-r--r--db/migrate/20200722133540_add_iterations_fk_to_resource_iteration_events_table.rb19
-rw-r--r--db/migrate/20200723125205_add_target_project_id_to_mr_metrics.rb19
-rw-r--r--db/migrate/20200723128332_add_fk_to_metrics_target_project_id.rb19
-rw-r--r--db/migrate/20200724100123_add_index_on_vulnerability_historical_statistics_date.rb17
-rw-r--r--db/migrate/20200727082309_remove_index_chat_name_service_id.rb17
-rw-r--r--db/migrate/20200727142337_update_defaults_for_sca_artifacts.rb21
-rw-r--r--db/migrate/20200728080250_replace_unique_index_on_cycle_analytics_stages.rb43
-rw-r--r--db/migrate/20200728163009_add_deployment_events_to_web_hooks.rb9
-rw-r--r--db/migrate/20200728174137_add_index_on_design_management_designs_issue_id_and_relative_position_and_id.rb18
-rw-r--r--db/migrate/20200728175710_add_enforce_namespace_storage_limit_to_application_settings.rb9
-rw-r--r--db/migrate/20200728182311_add_o_auth_paths_to_protected_paths.rb62
-rw-r--r--db/migrate/20200729151021_add_after_expiry_notification_delivered_to_personal_access_tokens.rb11
-rw-r--r--db/migrate/20200729175935_add_dashboard_path_to_prometheus_metrics.rb14
-rw-r--r--db/migrate/20200729180539_add_can_push_to_group_deploy_keys_groups.rb9
-rw-r--r--db/migrate/20200729181641_add_index_to_resource_milestone_events_add_events.rb21
-rw-r--r--db/migrate/20200729191227_add_runbook_to_prometheus_alert.rb14
-rw-r--r--db/migrate/20200729200808_add_text_limit_to_runbook_on_prometheus_alerts.rb16
-rw-r--r--db/migrate/20200729202222_add_index_to_ci_pipeline_project_id_created_at.rb17
-rw-r--r--db/migrate/20200730044810_add_indexes_to_resource_label_events_to_support_vsa.rb31
-rw-r--r--db/migrate/20200730083043_replace_index_for_service_usage_data.rb23
-rw-r--r--db/migrate/20200730131946_add_hide_lists_to_boards.rb10
-rw-r--r--db/migrate/20200730210506_add_text_limit_to_dashboard_path.rb17
-rw-r--r--db/migrate/20200731085019_create_experiment.rb25
-rw-r--r--db/migrate/20200731090553_create_experiment_user.rb21
-rw-r--r--db/migrate/20200731201408_add_foreign_key_to_experiment_on_experiment_users.rb20
-rw-r--r--db/migrate/20200731201834_add_foreign_key_to_user_on_experiment_users.rb20
-rw-r--r--db/migrate/20200803111512_add_group_id_to_services.rb9
-rw-r--r--db/migrate/20200803112806_add_index_group_id_to_services.rb22
-rw-r--r--db/migrate/20200803125340_create_raw_usage_data.rb24
-rw-r--r--db/migrate/20200804041018_add_default_value_for_external_diff_store_to_merge_request_diffs.rb19
-rw-r--r--db/migrate/20200804222543_add_resolved_on_default_branch_into_vulnerabilities_table.rb11
-rw-r--r--db/migrate/20200805071842_add_index_on_end_date_and_namespace_id_to_gitlab_subscriptions.rb18
-rw-r--r--db/migrate/20200805150316_create_ci_pipeline_artifact.rb32
-rw-r--r--db/migrate/20200805151001_add_foreign_key_to_pipeline_id_on_pipeline_artifact.rb19
-rw-r--r--db/migrate/20200805151726_add_foreign_key_to_project_id_on_pipeline_artifact.rb19
-rw-r--r--db/migrate/20200806004232_add_default_value_for_file_store_to_package_files.rb19
-rw-r--r--db/migrate/20200807070820_add_index_for_compliance_merged_merge_request_to_events.rb20
-rw-r--r--db/migrate/20200807132726_add_delete_original_index_at_to_reindexing_tasks.rb19
-rw-r--r--db/migrate/20200807150937_add_file_count_to_merge_request_diffs.rb22
-rw-r--r--db/migrate/20200810152043_add_expire_at_to_ci_pipeline_artifact.rb9
-rw-r--r--db/migrate/20200811055018_remove_not_null_constraint_on_type_from_audit_events.rb25
-rw-r--r--db/migrate/20200811154630_add_gitpod_application_settings.rb13
-rw-r--r--db/migrate/20200811154631_add_gitpod_application_settings_text_limit.rb16
-rw-r--r--db/migrate/20200811154632_add_gitpod_user_preferences.rb9
-rw-r--r--db/migrate/20200811194848_add_default_value_for_file_store_to_pipeline_artifact.rb20
-rw-r--r--db/migrate/20200812112204_add_index_to_mr_metrics_target_project_id.rb18
-rw-r--r--db/migrate/20200812150810_add_verification_state_to_snippet_repository.rb18
-rw-r--r--db/migrate/20200812150811_add_verification_failure_to_snippet_repository.rb19
-rw-r--r--db/migrate/20200812150812_add_verification_failure_index_to_snippet_repository.rb19
-rw-r--r--db/migrate/20200813135558_create_ci_deleted_objects.rb29
-rw-r--r--db/migrate/20200813143304_add_new_external_diff_migration_index.rb23
-rw-r--r--db/migrate/20200813143356_remove_old_external_diff_migration_index.rb25
-rw-r--r--db/migrate/20200816133024_add_cve_id_request_project_setting.rb13
-rw-r--r--db/migrate/20200817142800_add_pipeline_artifacts_size_to_project_statistics.rb19
-rw-r--r--db/migrate/20200817195628_add_modified_to_approval_merge_request_rule.rb9
-rw-r--r--db/migrate/20200818052219_add_kubernetes_version_to_cluster_providers_aws.rb28
-rw-r--r--db/migrate/20200818092401_add_checksum_to_build_chunk.rb9
-rw-r--r--db/migrate/20200818171229_add_package_max_file_size_to_plan_limits.rb13
-rw-r--r--db/migrate/20200819192143_add_emails_user_id_foreign_key.rb20
-rw-r--r--db/migrate/20200820105408_add_index_to_container_scanning_findings.rb20
-rw-r--r--db/migrate/20200820130839_add_auto_close_incident_to_project_incident_management_settings.rb13
-rw-r--r--db/migrate/20200820204041_create_ci_platform_metrics.rb31
-rw-r--r--db/migrate/20200821034419_add_unique_index_for_generic_packages.rb20
-rw-r--r--db/migrate/20200821194920_create_atlassian_identities.rb39
-rw-r--r--db/migrate/20200824045812_add_generic_package_max_file_size_to_plan_limits.rb9
-rw-r--r--db/migrate/20200824124623_create_issuable_severities.rb22
-rw-r--r--db/migrate/20200825071735_create_merge_request_reviewers.rb22
-rw-r--r--db/migrate/20200825081025_boards_epic_user_preferences.rb23
-rw-r--r--db/migrate/20200825081035_boards_epic_user_preferences_fk_board.rb19
-rw-r--r--db/migrate/20200825081045_boards_epic_user_preferences_fk_user.rb19
-rw-r--r--db/migrate/20200825081055_boards_epic_user_preferences_fk_epic.rb19
-rw-r--r--db/migrate/20200825084819_create_security_findings_table.rb27
-rw-r--r--db/migrate/20200825154237_update_package_file_size_plan_limits_defaults.rb13
-rw-r--r--db/migrate/20200825180050_add_pipeline_artifacts_size_to_root_storage_statistics.rb19
-rw-r--r--db/migrate/20200826073745_add_default_to_ci_pipeline_locked.rb23
-rw-r--r--db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb21
-rw-r--r--db/migrate/20200826212800_add_index_on_merge_request_id_and_rule_type_to_approval_merge_request_rule.rb23
-rw-r--r--db/migrate/20200827005322_add_creator_id_to_packages.rb9
-rw-r--r--db/migrate/20200827060911_add_merge_request_foreign_key_to_merge_request_reviewers.rb22
-rw-r--r--db/migrate/20200827060932_add_user_foreign_key_to_merge_request_reviewers.rb22
-rw-r--r--db/migrate/20200827085101_add_seats_currently_in_use_in_gitlab_subscriptions.rb21
-rw-r--r--db/migrate/20200827102234_add_ci_job_artifact_id_to_pages_metadata.rb9
-rw-r--r--db/migrate/20200827104432_add_foreign_key_to_artifacts_archive_id_in_pages_metadata.rb21
-rw-r--r--db/migrate/20200827114902_create_analytics_instance_statistics_measurements.rb16
-rw-r--r--db/migrate/20200827142811_create_merge_request_diff_details.rb30
-rw-r--r--db/migrate/20200827150057_add_index_expire_at_to_pipeline_artifacts.rb18
-rw-r--r--db/migrate/20200828155134_add_foreign_key_on_scan_id_to_security_scans.rb19
-rw-r--r--db/migrate/20200828155205_add_foreign_key_on_scanner_id_to_vulnerability_scanners.rb19
-rw-r--r--db/migrate/20200830201204_add_index_to_package_creator.rb21
-rw-r--r--db/migrate/20200831204646_add_project_feature_flags_to_plan_limits.rb9
-rw-r--r--db/migrate/20200831222347_insert_project_feature_flags_plan_limits.rb25
-rw-r--r--db/migrate/20200901203055_add_id_created_at_index_to_packages.rb19
-rw-r--r--db/migrate/20200901214416_change_pypi_python_version_type.rb18
-rw-r--r--db/migrate/20200902135542_update_package_max_file_size_plan_limits.rb45
-rw-r--r--db/migrate/20200903054946_add_elasticsearch_client_timeout.rb12
-rw-r--r--db/migrate/20200903092241_add_index_to_resource_iteration_events_add_events.rb21
-rw-r--r--db/migrate/20200904092131_add_merge_ref_sha_to_merge_requests.rb19
-rw-r--r--db/migrate/20200904131544_create_ci_build_pending_states.rb25
-rw-r--r--db/migrate/20200905013247_add_golang_package_max_file_size_to_plan_limits.rb9
-rw-r--r--db/migrate/20200907021256_create_dast_site_tokens.rb34
-rw-r--r--db/migrate/20200907062101_create_dast_site_validations.rb40
-rw-r--r--db/migrate/20200907092610_add_user_id_to_group_import_states.rb26
-rw-r--r--db/migrate/20200908033805_add_dast_site_validation_id_to_dast_site.rb33
-rw-r--r--db/migrate/20200908094810_add_new_setting_to_namespace_setting.rb19
-rw-r--r--db/migrate/20200908100053_create_authentication_events.rb33
-rw-r--r--db/migrate/20200908183231_add_check_positive_constraint_to_ci_platform_metrics.rb19
-rw-r--r--db/migrate/20200908212414_add_feature_flag_events_to_web_hooks.rb9
-rw-r--r--db/migrate/20200909040555_create_package_events.rb19
-rw-r--r--db/migrate/20200909083339_add_change_reviewer_merge_request_to_notification_settings.rb9
-rw-r--r--db/migrate/20200911120132_create_pages_deployments.rb28
-rw-r--r--db/migrate/20200911121027_add_pages_deployment_project_foreign_key.rb19
-rw-r--r--db/migrate/20200911121048_add_pages_deployment_ci_build_foreign_key.rb19
-rw-r--r--db/migrate/20200912152943_rename_admin_notification_email_application_setting.rb17
-rw-r--r--db/migrate/20200912193210_add_scheduling_issues_temp_indexes.rb21
-rw-r--r--db/migrate/20200913115700_add_kroki_application_settings.rb16
-rw-r--r--db/migrate/20200914070140_add_expiration_policy_started_at_to_container_repositories.rb13
-rw-r--r--db/migrate/20200914091326_change_build_pending_state_enums.rb15
-rw-r--r--db/migrate/20200914104642_modify_merge_request_api_index.rb20
-rw-r--r--db/migrate/20200914105202_remove_old_merge_request_api_index.rb17
-rw-r--r--db/migrate/20200914155135_add_deduplicated_flag_into_security_findings_table.rb9
-rw-r--r--db/migrate/20200914183227_add_index_on_deduplicated_column_of_security_findings.rb18
-rw-r--r--db/migrate/20200914184212_remove_index_on_security_findings_scan_id.rb18
-rw-r--r--db/migrate/20200915134004_add_indices_to_approval_project_rules.rb25
-rw-r--r--db/migrate/20200915152641_add_verification_state_to_terraform_state_version.rb18
-rw-r--r--db/migrate/20200915164448_add_verification_failure_limit_to_terraform_state_version.rb19
-rw-r--r--db/migrate/20200915164844_add_verification_failure_index_to_terraform_state_version.rb25
-rw-r--r--db/migrate/20200916120837_add_index_to_members_for_unaccepted_invitations.rb20
-rw-r--r--db/migrate/20200916135044_add_state_id_index_to_merge_requests.rb17
-rw-r--r--db/migrate/20200916151442_add_result_index_to_authentication_events.rb18
-rw-r--r--db/migrate/20200916165232_add_debian_max_file_size_to_plan_limits.rb9
-rw-r--r--db/migrate/20200917121650_add_help_page_documentation_url_to_application_settings.rb12
-rw-r--r--db/migrate/20200919200318_add_default_branch_name_to_namespace_settings.rb15
-rw-r--r--db/migrate/20200919204155_add_text_limit_to_namespace_settings_default_branch_name.rb19
-rw-r--r--db/migrate/20200920130356_add_container_expiration_policy_worker_settings_to_application_settings.rb19
-rw-r--r--db/migrate/20200921093826_add_index_to_user_preferences.rb17
-rw-r--r--db/migrate/20200921113722_add_text_limit_to_help_page_documentation_url.rb16
-rw-r--r--db/migrate/20200921130028_add_pages_deployment_id_to_pages_metadata.rb9
-rw-r--r--db/migrate/20200921131313_add_foreign_key_to_pages_deployment_id_in_project_pages_metadata.rb20
-rw-r--r--db/migrate/20200921203231_remove_duplicate_cluster_agents_index.rb18
-rw-r--r--db/migrate/20200922052316_create_issue_email_participants.rb32
-rw-r--r--db/migrate/20200922075244_add_compliance_framework_model.rb32
-rw-r--r--db/migrate/20200922093004_add_postgres_index_view.rb33
-rw-r--r--db/migrate/20200922133949_create_bulk_import.rb26
-rw-r--r--db/migrate/20200923071622_add_description_to_requirements.rb15
-rw-r--r--db/migrate/20200923071644_add_text_limit_to_requirements_description.rb17
-rw-r--r--db/migrate/20200923102312_update_programming_language_colors.rb21
-rw-r--r--db/migrate/20200923130057_remove_tmp_container_scanning_index.rb20
-rw-r--r--db/migrate/20200923140404_add_postgres_reindex_actions_table.rb26
-rw-r--r--db/migrate/20200924035825_add_options_to_dast_scanner_profile.rb13
-rw-r--r--db/migrate/20200925112104_create_bulk_import_configurations.rb27
-rw-r--r--db/migrate/20200925114522_create_bulk_import_entities.rb38
-rw-r--r--db/migrate/20200925125321_add_u2f_id_to_webauthn_registration.rb11
-rw-r--r--db/migrate/20200925153423_add_bulk_import_foreign_key_to_bulk_import_entities.rb17
-rw-r--r--db/migrate/20200925193815_add_parent_foreign_key_to_bulk_import_entities.rb17
-rw-r--r--db/migrate/20200925193906_add_namespace_foreign_key_to_bulk_import_entities.rb19
-rw-r--r--db/migrate/20200925194006_add_project_foreign_key_to_bulk_import_entities.rb19
-rw-r--r--db/migrate/20200927224750_add_incident_issue_type_index_to_issues.rb20
-rw-r--r--db/migrate/20200928095732_add_state_to_dast_site_validation.rb12
-rw-r--r--db/migrate/20200928100408_add_text_limit_to_dast_site_validation_state.rb17
-rw-r--r--db/migrate/20200928123510_add_expiration_policy_cleanup_status_to_container_repositories.rb26
-rw-r--r--db/migrate/20200928125258_add_foreign_key_to_u2f_reg_id_in_webauthn_regs.rb20
-rw-r--r--db/migrate/20200928131934_create_required_code_owners_sections.rb26
-rw-r--r--db/migrate/20200928164807_add_index_on_vulnerabilities_state_case.rb21
-rw-r--r--db/migrate/20200928203531_create_alert_management_http_integrations.rb37
-rw-r--r--db/migrate/20200928210524_add_http_integrations_project_foreign_key.rb19
-rw-r--r--db/migrate/20200928233632_remove_terraform_state_verification_indexes.rb21
-rw-r--r--db/migrate/20200929032729_add_sla_minutes_to_project_incident_management_settings.rb10
-rw-r--r--db/migrate/20200929063159_add_require_admin_approval_after_user_signup_to_application_settings.rb9
-rw-r--r--db/migrate/20200930094812_update_postgres_indexes_view.rb54
-rw-r--r--db/migrate/20200930131343_add_index_on_project_id_and_sha_to_deployments.rb20
-rw-r--r--db/migrate/20200930132319_add_api_fuzzing_to_plan_limits.rb9
-rw-r--r--db/migrate/20201002012659_add_issuable_sla_table.rb12
-rw-r--r--db/migrate/20201004163918_remove_project_id_and_id_index_from_vulnerabilities_table.rb19
-rw-r--r--db/migrate/20201005092703_add_namespace_column_to_frameworks.rb26
-rw-r--r--db/migrate/20201005092709_remove_compliance_frameworks_group_id_fk.rb39
-rw-r--r--db/migrate/20201005092753_add_framework_id_to_project_framework_settings.rb34
-rw-r--r--db/migrate/20201006014605_add_automatic_purchased_storage_allocation_to_application_settings.rb9
-rw-r--r--db/migrate/20201007033527_add_daily_invites_to_plan_limits.rb9
-rw-r--r--db/migrate/20201007033723_insert_daily_invites_plan_limits.rb25
-rw-r--r--db/migrate/20201007115209_add_lock_version_to_ci_build_trace_chunk.rb9
-rw-r--r--db/migrate/20201008011523_add_ci_jwt_signing_key_to_application_settings.rb13
-rw-r--r--db/migrate/20201008011937_add_text_limit_to_application_settings_encrypted_ci_jwt_signing_key_iv.rb17
-rw-r--r--db/migrate/20201008013434_generate_ci_jwt_signing_key.rb32
-rw-r--r--db/migrate/20201008075620_add_releases_events_to_web_hooks.rb9
-rw-r--r--db/migrate/20201008125643_create_csv_issue_imports.rb18
-rw-r--r--db/migrate/20201008144854_set_regex_defaults_on_container_expiration_policies.rb21
-rw-r--r--db/migrate/20201008224441_add_position_into_security_findings.rb19
-rw-r--r--db/migrate/20201009090954_add_index_with_project_id_to_container_expiration_policies.rb19
-rw-r--r--db/migrate/20201011005400_add_text_limit_to_application_settings_kroki_url.rb19
-rw-r--r--db/migrate/20201012073022_remove_not_null_constraint_on_framework.rb33
-rw-r--r--db/migrate/20201012122428_add_container_registry_expiration_policies_worker_capacity_constraint.rb22
-rw-r--r--db/migrate/20201012134230_create_ci_test_cases.rb27
-rw-r--r--db/migrate/20201012135330_create_ci_test_case_failures.rb22
-rw-r--r--db/migrate/20201012140110_add_projects_fk_to_ci_test_cases.rb19
-rw-r--r--db/migrate/20201012140452_add_ci_builds_fk_to_ci_test_case_failures.rb19
-rw-r--r--db/migrate/20201012194936_create_saml_group_links.rb30
-rw-r--r--db/migrate/20201014163633_specify_primary_key_where_missing.rb46
-rw-r--r--db/migrate/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs.rb25
-rw-r--r--db/migrate/20201015121805_add_project_foreign_key_to_csv_issue_imports.rb19
-rw-r--r--db/migrate/20201015121825_add_user_foreign_key_to_csv_issue_imports.rb19
-rw-r--r--db/migrate/20201015194852_add_index_on_state_for_dast_site_validations.rb22
-rw-r--r--db/migrate/20201015231049_add_ci_build_id_to_terraform_state_versions.rb28
-rw-r--r--db/migrate/20201016074302_add_index_project_id_and_id_to_container_repositories.rb18
-rw-r--r--db/migrate/20201019091307_add_unique_index_on_scan_id_and_position_of_security_findings.rb18
-rw-r--r--db/migrate/20201019101549_add_es_custom_analyzers_settings.rb12
-rw-r--r--db/migrate/20201019111952_add_sha256_and_filecount_to_pages_deployments.rb22
-rw-r--r--db/migrate/20201019113009_add_new_user_signups_cap_to_application_settings.rb9
-rw-r--r--db/migrate/20201019130244_remove_license_compliance_temp_index.rb18
-rw-r--r--db/migrate/20201019152046_add_default_branch_to_daily_build_group_report_result.rb11
-rw-r--r--db/migrate/20201019161924_add_partitioned_table_view.rb44
-rw-r--r--db/migrate/20201019172704_add_partitions_view.rb39
-rw-r--r--db/migrate/20201021085007_create_analytics_devops_adoption_segments.rb24
-rw-r--r--db/migrate/20201021101956_add_index_route_on_name_trigram_to_route.rb18
-rw-r--r--db/migrate/20201021102554_create_analytics_devops_adoption_segment_selections.rb17
-rw-r--r--db/migrate/20201021105347_add_foreign_key_project_id_to_segment_selection.rb19
-rw-r--r--db/migrate/20201021105600_add_foreign_key_group_id_to_segment_selection.rb19
-rw-r--r--db/migrate/20201021105959_add_check_constraint_to_segment_selection.rb19
-rw-r--r--db/migrate/20201021142812_add_index_to_ci_daily_build_group_report_results.rb24
-rw-r--r--db/migrate/20201021152210_add_secret_detection_token_revocation_application_settings.rb21
-rw-r--r--db/migrate/20201021155606_add_analytics_access_level_to_project_features.rb23
-rw-r--r--db/migrate/20201021190539_add_text_limit_to_secret_detection_token_revocation_application_settings.rb17
-rw-r--r--db/migrate/20201021220101_add_merge_trains_enabled.rb9
-rw-r--r--db/migrate/20201022080802_add_repository_read_only_to_snippets.rb9
-rw-r--r--db/migrate/20201022094845_add_historical_data_recorded_at.rb13
-rw-r--r--db/migrate/20201022094846_update_historical_data_recorded_at.rb31
-rw-r--r--db/migrate/20201022103304_add_availability_to_user_statuses.rb9
-rw-r--r--db/migrate/20201022144501_create_snippet_repository_storage_move.rb32
-rw-r--r--db/migrate/20201022191817_add_has_vulnerabilities_into_project_settings.rb19
-rw-r--r--db/migrate/20201022192254_index_project_settings_on_project_id_partially.rb18
-rw-r--r--db/migrate/20201023114628_create_merge_request_cleanup_schedules.rb27
-rw-r--r--db/migrate/20201026200736_seed_merge_trains_enabled.rb19
-rw-r--r--db/migrate/20201027002551_migrate_services_to_http_integrations.rb51
-rw-r--r--db/migrate/20201027101010_create_user_follow_users.rb24
-rw-r--r--db/migrate/20201027135651_add_auto_rollback_setting.rb19
-rw-r--r--db/migrate/20201027210127_add_index_to_oauth_access_grants_resource_owner_id.rb18
-rw-r--r--db/migrate/20201027211138_increase_default_diff_max_patch_bytes.rb9
-rw-r--r--db/migrate/20201028160831_add_temporary_index_to_vulnerabilities_table.rb18
-rw-r--r--db/migrate/20201028184640_add_helm_major_version_to_clusters.rb12
-rw-r--r--db/migrate/20201028204306_migrate_default_diff_max_patch_bytes_to_minimum_200kb.rb20
-rw-r--r--db/migrate/20201029143650_rename_application_settings_to_allow_deny_names.rb21
-rw-r--r--db/migrate/20201029144444_create_vulnerability_finding_links.rb25
-rw-r--r--db/migrate/20201029144524_add_index_to_releases.rb18
-rw-r--r--db/migrate/20201030092151_add_requirements_access_level_to_project_features.rb19
-rw-r--r--db/migrate/20201030200115_add_iid_to_design_management_design.rb9
-rw-r--r--db/migrate/20201030200539_add_index_on_design_management_designs_iid_project_id.rb21
-rw-r--r--db/migrate/20201030223933_add_ci_pipeline_deployments_to_plan_limits.rb9
-rw-r--r--db/migrate/20201102184743_add_index_to_incident_issues_on_project_and_created_at.rb30
-rw-r--r--db/migrate/20201103045515_add_issuable_metric_images.rb32
-rw-r--r--db/migrate/20201103095752_add_issues_closed_at_index.rb17
-rw-r--r--db/migrate/20201103171537_add_index_active_billable_users_to_user.rb21
-rw-r--r--db/migrate/20201103184333_create_packages_package_file_build_infos.rb30
-rw-r--r--db/migrate/20201103202213_update_packages_build_infos_index.rb22
-rw-r--r--db/migrate/20201104142036_add_index_to_merge_request_metrics_target_project_id.rb18
-rw-r--r--db/migrate/20201104204739_create_bulk_import_trackers.rb42
-rw-r--r--db/migrate/20201105021637_add_uploads_size_to_project_statistics.rb13
-rw-r--r--db/migrate/20201105024127_add_uploads_size_to_namespace_root_storage_statistics.rb13
-rw-r--r--db/migrate/20201105135051_change_default_value_of_ci_max_artifact_size_lsif_of_plan_limits_from20_to100.rb21
-rw-r--r--db/migrate/20201105143211_add_vulnerabilities_enabled_and_issuetype_to_jira_tracker_data.rb13
-rw-r--r--db/migrate/20201105143312_add_text_limit_to_jira_tracker_data_issuetype.rb17
-rw-r--r--db/migrate/20201106134139_add_pipelines_created_index.rb19
-rw-r--r--db/migrate/20201106135608_remove_redundant_pipelines_index.rb17
-rw-r--r--db/migrate/20201106193452_add_converted_at_to_experiment_users.rb9
-rw-r--r--db/migrate/20201107032257_add_default_true_require_admin_approval_after_user_signup_to_application_settings.rb9
-rw-r--r--db/migrate/20201108134919_add_finding_fingerprint_table.rb40
-rw-r--r--db/migrate/20201109080645_create_vulnerability_remediations_table.rb26
-rw-r--r--db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb18
-rw-r--r--db/migrate/20201109144634_add_region_field_to_aws_role.rb21
-rw-r--r--db/migrate/20201109180311_add_secret_detection_revocation_token_types_application_settings.rb13
-rw-r--r--db/migrate/20201109184023_add_text_limit_to_secret_detection_revocation_token_types_application_settings.rb17
-rw-r--r--db/migrate/20201110035029_created_index_for_vulnerability_occurrences_on_project_fingerprint.rb18
-rw-r--r--db/migrate/20201110110454_extend_postgres_indexes_view.rb55
-rw-r--r--db/migrate/20201110133629_change_index_mr_metrics_target_project_id.rb20
-rw-r--r--db/migrate/20201110221400_create_experiment_subjects.rb25
-rw-r--r--db/migrate/20201111051655_add_foreign_key_to_experiment_subjects_on_user.rb19
-rw-r--r--db/migrate/20201111051847_add_foreign_key_to_experiment_subjects_on_group.rb19
-rw-r--r--db/migrate/20201111051904_add_foreign_key_to_experiment_subjects_on_project.rb19
-rw-r--r--db/migrate/20201111100136_create_analytics_devops_adoption_snapshots.rb21
-rw-r--r--db/migrate/20201111110318_add_cloud_license_auth_token_to_settings.rb13
-rw-r--r--db/migrate/20201111110918_add_cloud_license_auth_token_application_settings_text_limit.rb17
-rw-r--r--db/migrate/20201111115414_create_incident_management_oncall_schedules.rb36
-rw-r--r--db/migrate/20201111145317_add_relation_to_indexes_view.rb58
-rw-r--r--db/migrate/20201111152859_add_missing_expression_indexes.rb43
-rw-r--r--db/migrate/20201112132808_create_bulk_import_failures.rb39
-rw-r--r--db/migrate/20201112173532_add_verification_state_to_package_files.rb10
-rw-r--r--db/migrate/20201112173911_add_index_on_verification_state_on_package_files.rb18
-rw-r--r--db/migrate/20201112195322_reseed_merge_trains_enabled.rb19
-rw-r--r--db/migrate/20201112215028_add_partitioned_audit_event_indexes.rb29
-rw-r--r--db/migrate/20201112215132_swap_partitioned_audit_events.rb15
-rw-r--r--db/migrate/20201116090328_add_regulated_to_compliance_frameworks.rb9
-rw-r--r--db/migrate/20201116211829_create_user_permission_export_uploads.rb33
-rw-r--r--db/migrate/20201117054609_add_cloud_license_enabled_to_settings.rb9
-rw-r--r--db/migrate/20201117075742_change_webauthn_xid_length.rb18
-rw-r--r--db/migrate/20201117153333_add_index_on_package_size_and_project_id_to_project_statistics.rb19
-rw-r--r--db/migrate/20201117184334_add_index_to_project_repositories_shard_id_project_id.rb17
-rw-r--r--db/migrate/20201117203224_add_iteration_id_to_boards_table.rb19
-rw-r--r--db/migrate/20201117213024_add_iteration_id_index_to_boards_table.rb18
-rw-r--r--db/migrate/20201118093135_create_namespace_onboarding_actions.rb23
-rw-r--r--db/migrate/20201119031515_add_iteration_id_to_lists.rb9
-rw-r--r--db/migrate/20201119053603_add_iteration_lists_foreign_key.rb21
-rw-r--r--db/migrate/20201119125730_add_web_hooks_service_foreign_key.rb23
-rw-r--r--db/migrate/20201119133534_add_personal_access_token_prefix_to_application_setting.rb12
-rw-r--r--db/migrate/20201119133604_add_text_limit_to_application_setting_personal_access_token_prefix.rb16
-rw-r--r--db/migrate/20201119162801_change_services_inherit_from_id_foreign_key.rb19
-rw-r--r--db/migrate/20201119164605_add_checksum_into_vulnerability_remediations.rb11
-rw-r--r--db/migrate/20201119213406_change_terraform_versioning_enabled_default.rb9
-rw-r--r--db/migrate/20201120092000_add_kroki_formats_to_application_settings_table.rb11
-rw-r--r--db/migrate/20201120125953_replace_unused_labels_index.rb22
-rw-r--r--db/migrate/20201120144823_create_tokens_with_iv.rb18
-rw-r--r--db/migrate/20201123081307_add_operations_project_feature_to_metrics.rb19
-rw-r--r--db/migrate/20201123161611_add_provisioned_by_group_to_user_details.rb29
-rw-r--r--db/migrate/20201124030537_create_incident_management_on_call_rotations.rb35
-rw-r--r--db/migrate/20201124075951_create_vulnerability_external_links.rb42
-rw-r--r--db/migrate/20201125030847_create_dependency_proxy_manifests.rb33
-rw-r--r--db/migrate/20201125233219_add_incident_management_on_call_participants.rb33
-rw-r--r--db/migrate/20201126165919_add_epic_boards.rb29
-rw-r--r--db/migrate/20201126172030_add_feed_token_off_to_settings.rb9
-rw-r--r--db/migrate/20201126190039_add_epic_board_labels.rb24
-rw-r--r--db/migrate/20201127104228_add_index_to_security_scans_on_created_at_and_id.rb18
-rw-r--r--db/migrate/20201127141433_add_other_role_to_user_details.rb25
-rw-r--r--db/migrate/20201127170848_add_index_bloat_estimate_view.rb109
-rw-r--r--db/migrate/20201128210000_add_service_desk_reply_to_is_not_null_index_on_issues_fix.rb18
-rw-r--r--db/migrate/20201201033202_add_verification_indexes_for_package_files.rb24
-rw-r--r--db/migrate/20201201034258_add_index_for_non_system_noteables.rb24
-rw-r--r--db/migrate/20201201161655_add_primary_key_to_elastic_search_indexed_projects.rb31
-rw-r--r--db/migrate/20201201163227_add_finding_uuid_to_vulnerability_feedback.rb10
-rw-r--r--db/migrate/20201201175656_add_index_vulnerabilities_on_project_id_and_state_and_severity.rb18
-rw-r--r--db/migrate/20201201190002_add_other_context_to_experiment_user.rb19
-rw-r--r--db/migrate/20201201192112_add_primary_key_to_elastic_search_indexed_namespaces.rb38
-rw-r--r--db/migrate/20201202003042_add_epic_board_positions.rb27
-rw-r--r--db/migrate/20201202025644_add_column_to_security_findings.rb9
-rw-r--r--db/migrate/20201202025937_add_index_to_security_findings_uuid.rb18
-rw-r--r--db/migrate/20201202133606_add_sorted_to_merge_request_diffs.rb19
-rw-r--r--db/migrate/20201202142751_drop_index_vulnerabilities_on_project_id.rb18
-rw-r--r--db/migrate/20201202150001_add_details_to_vulnerability_findings.rb19
-rw-r--r--db/migrate/20201202155913_add_primary_key_to_merge_request_context_commit_diff_files.rb31
-rw-r--r--db/migrate/20201202160105_add_group_file_name_index_to_dependency_proxy_manifests.rb22
-rw-r--r--db/migrate/20201202161021_remove_redundant_index_on_merge_request_context_commit_diff_files.rb17
-rw-r--r--db/migrate/20201203123524_add_domain_enum_to_alerts.rb19
-rw-r--r--db/migrate/20201203144655_add_allow_to_edit_commit_to_project_settings.rb15
-rw-r--r--db/migrate/20201203171631_add_index_to_domain.rb17
-rw-r--r--db/migrate/20201204085522_add_project_id_into_vulnerability_remediations.rb19
-rw-r--r--db/migrate/20201204090855_add_compound_index_to_vulnerability_remediations_table.rb28
-rw-r--r--db/migrate/20201204105300_create_packages_debian_file_metadata.rb29
-rw-r--r--db/migrate/20201204110700_create_packages_debian_project_distributions.rb62
-rw-r--r--db/migrate/20201204110800_create_packages_debian_group_distributions.rb62
-rw-r--r--db/migrate/20201204111000_create_packages_debian_project_architectures.rb38
-rw-r--r--db/migrate/20201204111100_create_packages_debian_group_architectures.rb38
-rw-r--r--db/migrate/20201204111200_create_packages_debian_project_components.rb35
-rw-r--r--db/migrate/20201204111300_create_packages_debian_group_components.rb35
-rw-r--r--db/migrate/20201204111400_create_packages_debian_project_component_files.rb41
-rw-r--r--db/migrate/20201204111500_create_packages_debian_group_component_files.rb41
-rw-r--r--db/migrate/20201204111600_create_packages_debian_publications.rb19
-rw-r--r--db/migrate/20201204141038_add_trace_bytesize_to_ci_build_pending_states.rb9
-rw-r--r--db/migrate/20201204193952_keep_latest_artifact_project_level.rb19
-rw-r--r--db/migrate/20201204205814_add_member_events_to_web_hooks.rb9
-rw-r--r--db/migrate/20201204215353_add_pull_mirror_interval_to_plan_limits.rb9
-rw-r--r--db/migrate/20201208081429_update_internal_ids_last_value_for_epics_renamed.rb27
-rw-r--r--db/migrate/20201208143911_add_approvals_created_at_index.rb19
-rw-r--r--db/migrate/20201208181411_remove_temporary_blocking_issues_index.rb21
-rw-r--r--db/migrate/20201208210209_create_incident_management_oncall_shifts.rb35
-rw-r--r--db/migrate/20201209154746_expand_ci_pipelines_index_on_ci_ref_id.rb24
-rw-r--r--db/migrate/20201209163113_recreate_index_issue_email_participants_on_issue_id_and_email.rb23
-rw-r--r--db/migrate/20201209163958_add_code_challenge_to_oauth_access_grants.rb26
-rw-r--r--db/migrate/20201209193551_add_version_sha_cache_to_composer_metadata.rb19
-rw-r--r--db/migrate/20201210101250_add_index_projects_on_import_type_and_creator_id.rb19
-rw-r--r--db/migrate/20201210175044_add_index_to_snippet_on_project_id.rb17
-rw-r--r--db/migrate/20201211042306_add_deployments_finder_by_finished_at_index.rb24
-rw-r--r--db/migrate/20210629031900_associate_existing_dast_builds_with_variables.rb1
-rw-r--r--db/migrate/20211004122540_create_member_tasks.rb13
-rw-r--r--db/migrate/20211005112404_add_member_id_foreign_key_to_member_tasks.rb15
-rw-r--r--db/migrate/20211005112645_add_project_id_foreign_key_to_member_tasks.rb15
-rw-r--r--db/migrate/20211008193137_add_health_status_column_on_clusters_integration_prometheus.rb8
-rw-r--r--db/migrate/20211011004242_create_content_blocked_states.rb15
-rw-r--r--db/migrate/20211012015903_next_traversal_ids_sibling_function.rb30
-rw-r--r--db/migrate/20211012134316_clean_up_migrate_merge_request_diff_commit_users.rb35
-rw-r--r--db/migrate/20211013014228_add_content_validation_endpoint_to_application_settings.rb20
-rw-r--r--db/migrate/20211013080714_add_network_to_user_credit_card_validations.rb9
-rw-r--r--db/migrate/20211013080715_limit_network_on_user_credit_card_validations.rb13
-rw-r--r--db/migrate/20211013080716_index_include_network_on_user_credit_card_validations.rb17
-rw-r--r--db/migrate/20211013192749_add_states_into_approval_project_rules.rb11
-rw-r--r--db/migrate/20211015021114_add_merge_commit_template_to_project_settings.rb9
-rw-r--r--db/migrate/20211015024135_add_merge_commit_template_limit_to_project_settings.rb13
-rw-r--r--db/migrate/20211018101034_add_tmp_project_id_column_to_namespaces.rb11
-rw-r--r--db/migrate/20211018161447_fix_double_entries_in_postgres_index_view.rb59
-rw-r--r--db/migrate/20211019153615_add_state_to_merge_request_assignees.rb8
-rw-r--r--db/migrate/20211020030948_add_runtime_runner_features_to_ci_builds_metadata.rb9
-rw-r--r--db/migrate/20211020095357_add_group_traversal_id_index.rb15
-rw-r--r--db/migrate/20211021125908_add_sentry_settings_to_application_settings.rb12
-rw-r--r--db/migrate/20211021134458_add_limits_to_sentry_settings_on_application_settings.rb17
-rw-r--r--db/migrate/20211025103744_add_state_id_to_vsa_issue_stage_events.rb7
-rw-r--r--db/migrate/20211025103758_add_state_id_to_vsa_merge_request_stage_events.rb7
-rw-r--r--db/migrate/20211026143238_remove_index_releases_on_author_id.rb15
-rw-r--r--db/migrate/20211027203950_add_updated_index_for_dormant_users.rb17
-rw-r--r--db/migrate/20211028132247_create_packages_npm_metadata.rb22
-rw-r--r--db/migrate/20211028212259_add_default_to_personal_access_tokens_prefix.rb7
-rw-r--r--db/migrate/20211101132310_add_reindexing_queue.rb16
-rw-r--r--db/migrate/20211103062728_add_with_highest_role_minimal_access_to_users_statistics.rb7
-rw-r--r--db/migrate/20211104012209_add_text_limit_to_application_settings_content_validation_endpoint_url.rb13
-rw-r--r--db/migrate/20211105010101_add_archived_column_to_deployments.rb9
-rw-r--r--db/migrate/20211105125756_add_read_at_to_dependency_proxy_manifests.rb7
-rw-r--r--db/migrate/20211105125813_add_read_at_to_dependency_proxy_blobs.rb7
-rw-r--r--db/migrate/20211105160316_create_dotenv_application_limits.rb8
-rw-r--r--db/migrate/20211105161404_insert_dotenv_application_limits.rb27
-rw-r--r--db/migrate/20211108154510_create_pipeline_triggers_application_limits.rb7
-rw-r--r--db/migrate/20211108154841_insert_pipeline_triggers_application_limits.rb23
-rw-r--r--db/migrate/20211108203248_update_dependency_proxy_indexes_with_read_at.rb27
-rw-r--r--db/migrate/20211108211434_remove_index_for_resource_group.rb17
-rw-r--r--db/migrate/20211109100050_add_consume_after_to_loose_fk_deleted_records.rb13
-rw-r--r--db/migrate/20211109101010_support_partition_query_in_loose_fk_table.rb20
-rw-r--r--db/migrate/20211110010101_add_index_on_unarchived_deployments.rb15
-rw-r--r--db/migrate/20211110100050_add_has_shimo_to_project_settings.rb9
-rw-r--r--db/migrate/20211112155416_populate_default_value_for_personal_access_tokens_prefix.rb20
-rw-r--r--db/post_migrate/20200106071113_update_fingerprint_sha256_within_keys.rb22
-rw-r--r--db/post_migrate/20200110121314_schedule_update_existing_subgroup_to_match_visibility_level_of_parent.rb56
-rw-r--r--db/post_migrate/20200113151354_remove_creations_in_gitlab_subscription_histories.rb24
-rw-r--r--db/post_migrate/20200114112932_add_temporary_partial_index_on_project_id_to_services.rb22
-rw-r--r--db/post_migrate/20200114113341_patch_prometheus_services_for_shared_cluster_applications.rb11
-rw-r--r--db/post_migrate/20200117194850_backfill_operations_feature_flags_iid.rb24
-rw-r--r--db/post_migrate/20200117194900_delete_internal_ids_where_feature_flags_usage.rb19
-rw-r--r--db/post_migrate/20200120083607_remove_storage_version_column_from_snippets.rb30
-rw-r--r--db/post_migrate/20200122123016_backfill_project_settings.rb29
-rw-r--r--db/post_migrate/20200122144759_drop_kibana_column.rb9
-rw-r--r--db/post_migrate/20200123155929_remove_invalid_jira_data.rb25
-rw-r--r--db/post_migrate/20200124110831_migrate_design_notes_mentions_to_db.rb61
-rw-r--r--db/post_migrate/20200127090233_remove_invalid_issue_tracker_data.rb24
-rw-r--r--db/post_migrate/20200127111840_fix_projects_without_project_feature.rb22
-rw-r--r--db/post_migrate/20200128132510_add_temporary_index_for_notes_with_mentions.rb29
-rw-r--r--db/post_migrate/20200128133510_cleanup_empty_commit_user_mentions.rb28
-rw-r--r--db/post_migrate/20200128134110_migrate_commit_notes_mentions_to_db.rb37
-rw-r--r--db/post_migrate/20200128210353_cleanup_optimistic_locking_nulls.rb44
-rw-r--r--db/post_migrate/20200129035708_cleanup_rename_pages_domains_domain_type_to_scope.rb17
-rw-r--r--db/post_migrate/20200130145430_reschedule_migrate_issue_trackers_data.rb44
-rw-r--r--db/post_migrate/20200203104214_services_remove_temporary_index_on_project_id.rb22
-rw-r--r--db/post_migrate/20200204113223_schedule_recalculate_project_authorizations.rb43
-rw-r--r--db/post_migrate/20200204113224_schedule_recalculate_project_authorizations_second_run.rb32
-rw-r--r--db/post_migrate/20200204113225_schedule_recalculate_project_authorizations_third_run.rb28
-rw-r--r--db/post_migrate/20200206091544_migrate_create_commit_signature_worker_sidekiq_queue.rb15
-rw-r--r--db/post_migrate/20200206135203_udpate_index_ci_builds_on_name_for_security_products.rb33
-rw-r--r--db/post_migrate/20200207184023_add_temporary_index_to_promotion_notes.rb23
-rw-r--r--db/post_migrate/20200207185149_schedule_fix_orphan_promoted_issues.rb35
-rw-r--r--db/post_migrate/20200210062432_schedule_link_lfs_objects.rb17
-rw-r--r--db/post_migrate/20200210092405_save_instance_administrators_group_id.rb42
-rw-r--r--db/post_migrate/20200211152410_remove_instance_from_services.rb19
-rw-r--r--db/post_migrate/20200211155000_cleanup_empty_merge_request_mentions.rb27
-rw-r--r--db/post_migrate/20200211155100_add_temporary_merge_request_with_mentions_index.rb20
-rw-r--r--db/post_migrate/20200211155539_migrate_merge_request_mentions_to_db.rb35
-rw-r--r--db/post_migrate/20200212052620_readd_template_column_to_services.rb25
-rw-r--r--db/post_migrate/20200213204737_remove_unnecessary_milestone_join_tables.rb30
-rw-r--r--db/post_migrate/20200213220159_migrate_store_security_reports_sidekiq_queue.rb15
-rw-r--r--db/post_migrate/20200213220211_migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue.rb17
-rw-r--r--db/post_migrate/20200214034836_remove_security_dashboard_feature_flag.rb25
-rw-r--r--db/post_migrate/20200214214934_create_environment_for_self_monitoring_project.rb28
-rw-r--r--db/post_migrate/20200217210353_cleanup_optimistic_locking_nulls_pt2.rb7
-rw-r--r--db/post_migrate/20200217223651_add_index_to_job_artifact_secure_reports.rb24
-rw-r--r--db/post_migrate/20200217225719_schedule_migrate_security_scans.rb31
-rw-r--r--db/post_migrate/20200219183456_remove_issue_state_indexes.rb40
-rw-r--r--db/post_migrate/20200219184219_remove_merge_request_state_indexes.rb39
-rw-r--r--db/post_migrate/20200219193058_remove_state_from_issues.rb30
-rw-r--r--db/post_migrate/20200219193117_remove_state_from_merge_requests.rb30
-rw-r--r--db/post_migrate/20200220115023_fix_projects_without_prometheus_service.rb27
-rw-r--r--db/post_migrate/20200221142216_remove_repository_storage_from_snippets.rb28
-rw-r--r--db/post_migrate/20200226124757_remove_health_status_from_epics.rb19
-rw-r--r--db/post_migrate/20200226162239_cleanup_closed_at_rename_in_vulnerabilities.rb17
-rw-r--r--db/post_migrate/20200226162723_cleanup_closed_by_rename_in_vulnerabilities.rb17
-rw-r--r--db/post_migrate/20200227140242_update_occurrence_severity_column.rb34
-rw-r--r--db/post_migrate/20200302142052_update_vulnerability_severity_column.rb31
-rw-r--r--db/post_migrate/20200304211738_remove_file_type_from_packages_package_files.rb9
-rw-r--r--db/post_migrate/20200305082754_remove_duplicate_labels_from_project.rb132
-rw-r--r--db/post_migrate/20200305082858_add_uniqueness_index_to_label_title_and_project.rb21
-rw-r--r--db/post_migrate/20200310075115_schedule_link_lfs_objects_projects.rb29
-rw-r--r--db/post_migrate/20200310135818_remove_temporary_promoted_notes_index.rb22
-rw-r--r--db/post_migrate/20200310215714_migrate_saml_identities_to_scim_identities.rb29
-rw-r--r--db/post_migrate/20200311130802_schedule_populate_user_highest_roles_table.rb37
-rw-r--r--db/post_migrate/20200311192351_add_index_on_noteable_type_and_noteable_id_to_sent_notifications.rb21
-rw-r--r--db/post_migrate/20200312134637_backfill_environment_id_on_deployment_merge_requests.rb27
-rw-r--r--db/post_migrate/20200313203550_remove_orphaned_chat_names.rb13
-rw-r--r--db/post_migrate/20200313204021_validate_foreign_key_from_chat_name_to_service.rb14
-rw-r--r--db/post_migrate/20200319071702_consume_remaining_link_lfs_objects_projects_jobs.rb15
-rw-r--r--db/post_migrate/20200323011225_complete_migrate_security_scans.rb13
-rw-r--r--db/post_migrate/20200323011955_remove_index_used_for_scan_migration.rb24
-rw-r--r--db/post_migrate/20200323080714_trigger_background_migration_for_users_bio.rb31
-rw-r--r--db/post_migrate/20200325162730_schedule_backfill_push_rules_id_in_projects.rb39
-rw-r--r--db/post_migrate/20200401091051_remove_reference_columns_from_resource_milestone_events.rb11
-rw-r--r--db/post_migrate/20200403132349_remove_old_index_pages_domains_need_auto_ssl_renewal.rb21
-rw-r--r--db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb34
-rw-r--r--db/post_migrate/20200406193427_add_index_to_issues_health_status.rb23
-rw-r--r--db/post_migrate/20200407094005_drop_vulnerability_severity_index.rb18
-rw-r--r--db/post_migrate/20200407094923_drop_vulnerabilities_severity_index.rb18
-rw-r--r--db/post_migrate/20200408110856_add_nginx_five_hundred_percentage_metric.rb13
-rw-r--r--db/post_migrate/20200408132152_remove_namespaces_trial_ends_on.rb27
-rw-r--r--db/post_migrate/20200409211607_migrate_legacy_attachments.rb30
-rw-r--r--db/post_migrate/20200416111111_migrate_vulnerability_dismissals.rb37
-rw-r--r--db/post_migrate/20200420094444_backfill_snippet_repositories.rb30
-rw-r--r--db/post_migrate/20200420162730_remove_additional_application_settings_rows.rb17
-rw-r--r--db/post_migrate/20200421195234_backfill_status_page_published_incidents.rb48
-rw-r--r--db/post_migrate/20200424043515_drop_namespaces_plan_id.rb26
-rw-r--r--db/post_migrate/20200427064130_cleanup_optimistic_locking_nulls_pt2_fixed.rb47
-rw-r--r--db/post_migrate/20200428134356_remove_elastic_experimental_indexer_from_application_settings.rb8
-rw-r--r--db/post_migrate/20200429002150_cleanup_sprints_state_rename.rb17
-rw-r--r--db/post_migrate/20200506085748_update_undefined_confidence_from_occurrences.rb35
-rw-r--r--db/post_migrate/20200506125731_cleanup_user_highest_roles_population.rb23
-rw-r--r--db/post_migrate/20200506154421_migrate_scim_identities_to_saml_for_new_users.rb37
-rw-r--r--db/post_migrate/20200508091106_remove_bot_type.rb29
-rw-r--r--db/post_migrate/20200511080113_add_projects_foreign_key_to_namespaces.rb27
-rw-r--r--db/post_migrate/20200511083541_cleanup_projects_with_missing_namespace.rb261
-rw-r--r--db/post_migrate/20200511092714_update_undefined_confidence_from_vulnerabilities.rb35
-rw-r--r--db/post_migrate/20200511130130_ensure_deprecated_jenkins_service_records_removal.rb17
-rw-r--r--db/post_migrate/20200511145545_change_variable_interpolation_format_in_common_metrics.rb15
-rw-r--r--db/post_migrate/20200511162057_add_missing_instance_to_servicess.rb30
-rw-r--r--db/post_migrate/20200511162115_add_missing_index_to_service_unique_instance_per_type.rb25
-rw-r--r--db/post_migrate/20200511220023_validate_projects_foreign_key_to_namespaces.rb21
-rw-r--r--db/post_migrate/20200513171959_enable_hashed_storage.rb17
-rw-r--r--db/post_migrate/20200514000009_add_not_null_constraint_on_file_store_to_lfs_objects.rb17
-rw-r--r--db/post_migrate/20200514000132_add_not_null_constraint_on_store_to_uploads.rb17
-rw-r--r--db/post_migrate/20200514000340_add_not_null_constraint_on_file_store_to_ci_jobs_artifacts.rb17
-rw-r--r--db/post_migrate/20200518114540_schedule_fix_ruby_object_in_audit_events.rb41
-rw-r--r--db/post_migrate/20200518133123_add_index_on_starting_ending_at_to_metrics_dashboard_annotations.rb18
-rw-r--r--db/post_migrate/20200519171058_update_index_ci_builds_on_commit_id_and_artifacts_expireatandidpartial.rb35
-rw-r--r--db/post_migrate/20200519201128_migrate_vulnerability_dismissal_feedback.rb36
-rw-r--r--db/post_migrate/20200525121014_drop_users_ghost_column.rb29
-rw-r--r--db/post_migrate/20200525144525_migrate_stuck_import_jobs_queue_to_stuck_project_import_jobs.rb15
-rw-r--r--db/post_migrate/20200526000407_seed_repository_storages_weighted.rb30
-rw-r--r--db/post_migrate/20200526115436_dedup_mr_metrics.rb65
-rw-r--r--db/post_migrate/20200527094322_drop_vulnerability_confidence_index.rb20
-rw-r--r--db/post_migrate/20200527095401_drop_vulnerability_occurrence_confidence_index.rb20
-rw-r--r--db/post_migrate/20200528123703_add_merge_request_partial_index_to_events.rb24
-rw-r--r--db/post_migrate/20200601120434_migrate_all_merge_request_user_mentions_to_db.rb37
-rw-r--r--db/post_migrate/20200602013900_add_limit_to_designs_filename.rb17
-rw-r--r--db/post_migrate/20200602013901_cap_designs_filename_length_to_new_limit.rb40
-rw-r--r--db/post_migrate/20200602143020_update_routes_for_lost_and_found_group_and_orphaned_projects.rb188
-rw-r--r--db/post_migrate/20200608072931_backfill_imported_snippet_repositories.rb47
-rw-r--r--db/post_migrate/20200608075553_add_index_on_user_id_and_created_at_and_source_to_ci_pipelines.rb19
-rw-r--r--db/post_migrate/20200608195222_set_lock_version_not_null_constraint.rb23
-rw-r--r--db/post_migrate/20200608203426_set_proper_lock_version_indices.rb29
-rw-r--r--db/post_migrate/20200608205813_set_lock_version_to_not_null.rb31
-rw-r--r--db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb18
-rw-r--r--db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb18
-rw-r--r--db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb18
-rw-r--r--db/post_migrate/20200608212652_lock_version_cleanup_for_ci_stages.rb18
-rw-r--r--db/post_migrate/20200608212807_lock_version_cleanup_for_ci_builds.rb18
-rw-r--r--db/post_migrate/20200608212824_lock_version_cleanup_for_ci_pipelines.rb18
-rw-r--r--db/post_migrate/20200609002841_add_partial_index_on_locked_state_id_to_merge_requests.rb19
-rw-r--r--db/post_migrate/20200615111857_unconfirm_wrongfully_verified_emails.rb40
-rw-r--r--db/post_migrate/20200617001637_validate_file_store_not_null_constraint_on_lfs_objects.rb17
-rw-r--r--db/post_migrate/20200617001848_validate_store_not_null_constraint_uploads.rb17
-rw-r--r--db/post_migrate/20200617002030_validate_file_store_not_null_constraint_on_ci_job_artifacts.rb17
-rw-r--r--db/post_migrate/20200618152212_update_secure_smau_index.rb23
-rw-r--r--db/post_migrate/20200623142159_remove_gitlab_issue_tracker_service_records.rb28
-rw-r--r--db/post_migrate/20200626060151_add_disable_overriding_approvers_per_merge_request_indices.rb26
-rw-r--r--db/post_migrate/20200701070435_add_default_value_stream_to_groups_with_group_stages.rb55
-rw-r--r--db/post_migrate/20200701091253_validate_foreign_key_on_cycle_analytics_group_stages.rb19
-rw-r--r--db/post_migrate/20200703064117_generate_missing_routes_for_bots.rb92
-rw-r--r--db/post_migrate/20200703125016_backfill_namespace_settings.rb29
-rw-r--r--db/post_migrate/20200703165434_drop_temporary_table_untracked_files_for_uploads_if_exists.rb13
-rw-r--r--db/post_migrate/20200704143633_add_index_on_user_id_and_created_at_where_source_to_ci_pipelines.rb17
-rw-r--r--db/post_migrate/20200704161600_add_index_on_id_and_status_and_created_at_to_deployments.rb19
-rw-r--r--db/post_migrate/20200706154619_drop_ci_daily_report_results_table.rb24
-rw-r--r--db/post_migrate/20200709101408_schedule_populate_project_snippet_statistics.rb30
-rw-r--r--db/post_migrate/20200710102418_delete_user_callout_alerts_moved.rb28
-rw-r--r--db/post_migrate/20200710102846_drop_index_ruby_objects_in_details_on_audit_events.rb18
-rw-r--r--db/post_migrate/20200713071042_confirm_project_bot_users.rb30
-rw-r--r--db/post_migrate/20200714075739_schedule_populate_personal_snippet_statistics.rb29
-rw-r--r--db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb135
-rw-r--r--db/post_migrate/20200716234518_add_uniqueness_index_to_label_title_and_group.rb21
-rw-r--r--db/post_migrate/20200721140507_update_index_for_coverage_fuzzing_telemetry.rb38
-rw-r--r--db/post_migrate/20200722202318_backfill_partitioned_audit_events.rb21
-rw-r--r--db/post_migrate/20200723040950_migrate_incident_issues_to_incident_type.rb47
-rw-r--r--db/post_migrate/20200723132258_schedule_copy_of_mr_target_project_id_to_mr_metrics.rb33
-rw-r--r--db/post_migrate/20200724100421_remove_updated_at_from_audit_events.rb119
-rw-r--r--db/post_migrate/20200724130639_backfill_designs_relative_position.rb19
-rw-r--r--db/post_migrate/20200727100631_remove_again_gitlab_issue_tracker_service_records.rb28
-rw-r--r--db/post_migrate/20200727114147_remove_title_and_description_from_services.rb10
-rw-r--r--db/post_migrate/20200730133730_remove_table_vulnerability_export_verification_status.rb16
-rw-r--r--db/post_migrate/20200804035230_add_partial_index_on_id_to_merge_request_diffs.rb18
-rw-r--r--db/post_migrate/20200804041930_add_not_null_constraint_on_external_diff_store_to_merge_request_diffs.rb17
-rw-r--r--db/post_migrate/20200805152108_migrate_null_external_diff_store_to_local_value.rb41
-rw-r--r--db/post_migrate/20200806004742_add_not_null_constraint_on_file_store_to_package_files.rb17
-rw-r--r--db/post_migrate/20200806172909_add_partial_index_on_id_to_package_files.rb18
-rw-r--r--db/post_migrate/20200806173633_migrate_null_package_files_file_store_to_local_value.rb43
-rw-r--r--db/post_migrate/20200807110237_add_migration_index_to_vulnerabilities_occurrences.rb20
-rw-r--r--db/post_migrate/20200807152315_backfill_merge_request_diffs_files_counts.rb30
-rw-r--r--db/post_migrate/20200808221641_add_index_for_license_compliance_artifacts.rb18
-rw-r--r--db/post_migrate/20200809221641_migrate_license_management_artifacts_to_license_scanning.rb49
-rw-r--r--db/post_migrate/20200810100921_add_target_type_to_audit_event.rb121
-rw-r--r--db/post_migrate/20200810101029_add_text_limit_to_audit_event_target_type.rb20
-rw-r--r--db/post_migrate/20200810160355_add_not_null_constraint_to_ci_pipeline_artifact_file.rb17
-rw-r--r--db/post_migrate/20200810191256_remove_pipeline_id_from_test_reports.rb19
-rw-r--r--db/post_migrate/20200811130000_create_index_vulnerabilities_feedback_issue_id_not_null.rb19
-rw-r--r--db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb48
-rw-r--r--db/post_migrate/20200811211536_add_index_to_ci_job_artifacts_for_terraform_reports_id.rb18
-rw-r--r--db/post_migrate/20200813153434_import_latest_common_metrics.rb22
-rw-r--r--db/post_migrate/20200817070126_update_index_secure_for_coverage_fuzzing_telemetry.rb27
-rw-r--r--db/post_migrate/20200817100710_add_section_and_created_at_codeowner_approval_merge_request_index.rb22
-rw-r--r--db/post_migrate/20200819082334_remove_default_from_services.rb19
-rw-r--r--db/post_migrate/20200819113644_add_target_id_to_audit_events.rb125
-rw-r--r--db/post_migrate/20200819202048_remove_orphaned_emails.rb20
-rw-r--r--db/post_migrate/20200819202222_validate_emails_user_id_foreign_key.rb16
-rw-r--r--db/post_migrate/20200821224343_schedule_populate_vulnerability_historical_statistics.rb30
-rw-r--r--db/post_migrate/20200824130028_remove_index_on_users_bio.rb20
-rw-r--r--db/post_migrate/20200824130447_remove_users_bio_column.rb19
-rw-r--r--db/post_migrate/20200826053152_add_index_on_ci_pipelines_source_for_on_demand_dast.rb29
-rw-r--r--db/post_migrate/20200826121552_remove_ci_job_artifacts_locked.rb19
-rw-r--r--db/post_migrate/20200826220745_add_compound_index_on_vulnerabilities_for_background_migration.rb18
-rw-r--r--db/post_migrate/20200826220746_schedule_populate_resolved_on_default_branch_column.rb28
-rw-r--r--db/post_migrate/20200831065320_add_not_valid_not_null_constraint_to_mr_metrics.rb17
-rw-r--r--db/post_migrate/20200831065322_add_tmp_index_to_target_project_id.rb18
-rw-r--r--db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb49
-rw-r--r--db/post_migrate/20200831074356_validate_not_null_constraint_on_mr_metrics.rb20
-rw-r--r--db/post_migrate/20200831224343_populate_vulnerability_historical_statistics_for_year.rb30
-rw-r--r--db/post_migrate/20200901170135_backfill_modified_column_for_approval_merge_request_rules.rb17
-rw-r--r--db/post_migrate/20200901212304_drop_code_owner_column_from_approval_merge_request_rule.rb36
-rw-r--r--db/post_migrate/20200903064431_add_created_at_index_to_audit_events.rb22
-rw-r--r--db/post_migrate/20200904174901_backfill_cleanup_for_partitioned_audit_events.rb17
-rw-r--r--db/post_migrate/20200907092715_add_not_null_constraint_to_user_on_group_import_states.rb17
-rw-r--r--db/post_migrate/20200907124300_complete_namespace_settings_migration.rb35
-rw-r--r--db/post_migrate/20200908064229_add_partial_index_to_ci_builds_table_on_user_id_name.rb37
-rw-r--r--db/post_migrate/20200908095446_update_location_fingerprint_column_for_cs.rb30
-rw-r--r--db/post_migrate/20200909161624_cleanup_group_import_states_with_null_user_id.rb80
-rw-r--r--db/post_migrate/20200909194014_change_pypi_python_version_type_cleanup.rb18
-rw-r--r--db/post_migrate/20200909194524_increase_pypi_version_size.rb17
-rw-r--r--db/post_migrate/20200910131217_tmp_index_for_fixing_inconsistent_vulnerability_occurrences.rb20
-rw-r--r--db/post_migrate/20200910131218_remove_duplicated_cs_findings.rb31
-rw-r--r--db/post_migrate/20200910155617_backfill_jira_tracker_deployment_type.rb19
-rw-r--r--db/post_migrate/20200910170908_ensure_filled_external_diff_store_on_merge_request_diffs.rb31
-rw-r--r--db/post_migrate/20200910175553_validate_not_null_external_diff_store_on_merge_request_diffs.rb21
-rw-r--r--db/post_migrate/20200912153218_cleanup_admin_notification_email_application_setting_rename.rb17
-rw-r--r--db/post_migrate/20200915044225_schedule_migration_to_hashed_storage.rb17
-rw-r--r--db/post_migrate/20200915185707_ensure_filled_file_store_on_package_files.rb33
-rw-r--r--db/post_migrate/20200915191156_validate_not_null_file_store_on_package_files.rb21
-rw-r--r--db/post_migrate/20200916081749_remove_cycle_analytics_total_stage_data.rb14
-rw-r--r--db/post_migrate/20200917135802_remove_duplicated_cs_findings_without_vulnerability_id.rb30
-rw-r--r--db/post_migrate/20200917165525_update_index_on_namespaces_for_type_and_id.rb23
-rw-r--r--db/post_migrate/20200922054642_drop_snowplow_iglu_registry_url_from_application_settings.rb9
-rw-r--r--db/post_migrate/20200922095954_remove_instance_statistics_visibility_private_from_application_settings.rb13
-rw-r--r--db/post_migrate/20200922170907_change_index_on_pipeline_status.rb21
-rw-r--r--db/post_migrate/20200922231755_remove_created_by_user_id_from_cluster_providers_aws.rb26
-rw-r--r--db/post_migrate/20200929052138_create_initial_versions_for_pre_versioning_terraform_states.rb18
-rw-r--r--db/post_migrate/20200929113254_remove_type_from_audit_events.rb125
-rw-r--r--db/post_migrate/20200929114107_schedule_migrate_u2f_webauthn.rb31
-rw-r--r--db/post_migrate/20200930144340_set_job_waiter_ttl.rb31
-rw-r--r--db/post_migrate/20201001022100_validate_designs_filename_text_limit.rb16
-rw-r--r--db/post_migrate/20201001101136_remove_index_on_issues_relative_position.rb18
-rw-r--r--db/post_migrate/20201002094617_remove_container_scanning_report_type_index.rb24
-rw-r--r--db/post_migrate/20201002175953_add_index_for_merged_merge_requests.rb21
-rw-r--r--db/post_migrate/20201005094331_migrate_compliance_framework_enum_to_database_framework_record.rb102
-rw-r--r--db/post_migrate/20201005153955_add_not_null_constraint_to_compliance_project_settings.rb21
-rw-r--r--db/post_migrate/20201014142521_schedule_sync_blocking_issues_count.rb46
-rw-r--r--db/post_migrate/20201015073808_schedule_blocked_by_links_replacement.rb28
-rw-r--r--db/post_migrate/20201015154527_add_index_on_services_for_usage_data.rb18
-rw-r--r--db/post_migrate/20201019094741_rename_sitemap_root_namespaces.rb24
-rw-r--r--db/post_migrate/20201020102551_remove_index_service_for_usage_data.rb18
-rw-r--r--db/post_migrate/20201026051643_remove_scanned_resources_count_from_security_scans.rb13
-rw-r--r--db/post_migrate/20201026182253_schedule_populate_vulnerability_feedback_pipeline_id.rb33
-rw-r--r--db/post_migrate/20201026185514_ensure_u2f_registrations_migrated.rb37
-rw-r--r--db/post_migrate/20201028160832_schedule_populate_missing_dismissal_information_for_vulnerabilities.rb23
-rw-r--r--db/post_migrate/20201028182809_backfill_jira_tracker_deployment_type2.rb32
-rw-r--r--db/post_migrate/20201029052241_migrate_geo_blob_verification_primary_worker_sidekiq_queue.rb18
-rw-r--r--db/post_migrate/20201029144157_cleanup_application_settings_to_allow_deny_rename.rb19
-rw-r--r--db/post_migrate/20201030121314_schedule_update_existing_users_that_require_two_factor_auth.rb37
-rw-r--r--db/post_migrate/20201030203854_backfill_design_iids.rb27
-rw-r--r--db/post_migrate/20201102073808_schedule_blocked_by_links_replacement_second_try.rb30
-rw-r--r--db/post_migrate/20201102112206_rename_sitemap_namespace.rb24
-rw-r--r--db/post_migrate/20201102114018_remove_storage_size_limit_from_application_settings.rb13
-rw-r--r--db/post_migrate/20201102152554_add_not_null_check_on_iid_on_design_manangement_designs.rb17
-rw-r--r--db/post_migrate/20201102152945_truncate_security_findings_table.rb19
-rw-r--r--db/post_migrate/20201103013242_remove_terraform_state_verification_columns.rb29
-rw-r--r--db/post_migrate/20201103110018_schedule_merge_request_cleanup_schedules_backfill.rb30
-rw-r--r--db/post_migrate/20201103192526_schedule_populate_has_vulnerabilities.rb24
-rw-r--r--db/post_migrate/20201104124300_ensure_namespace_settings_creation.rb40
-rw-r--r--db/post_migrate/20201106082723_add_merge_request_jira_reference_indexes.rb44
-rw-r--r--db/post_migrate/20201106134950_deduplicate_epic_iids.rb121
-rw-r--r--db/post_migrate/20201109114603_schedule_remove_inaccessible_epic_todos.rb29
-rw-r--r--db/post_migrate/20201110161542_cleanup_transfered_projects_shared_runners.rb30
-rw-r--r--db/post_migrate/20201112130710_schedule_remove_duplicate_vulnerabilities_findings.rb38
-rw-r--r--db/post_migrate/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences.rb37
-rw-r--r--db/post_migrate/20201112145311_add_index_on_sha_for_initial_deployments.rb21
-rw-r--r--db/post_migrate/20201113105000_update_index_secure_for_api_fuzzing_telemetry.rb27
-rw-r--r--db/post_migrate/20201119092319_schedule_repopulate_historical_vulnerability_statistics.rb31
-rw-r--r--db/post_migrate/20201120071303_drop_feature_filter_type_from_user_preferences.rb21
-rw-r--r--db/post_migrate/20201120140210_add_runner_id_and_id_desc_index_to_ci_builds.rb21
-rw-r--r--db/post_migrate/20201124122817_populate_remaining_missing_dismissal_information_for_vulnerabilities.rb21
-rw-r--r--db/post_migrate/20201124185639_remove_unused_indexes.rb27
-rw-r--r--db/post_migrate/20201128210234_schedule_populate_issue_email_participants.rb31
-rw-r--r--db/post_migrate/20201130103926_schedule_populate_dismissed_state_for_vulnerabilities.rb62
-rw-r--r--db/post_migrate/20201203123201_remove_orphan_service_hooks.rb31
-rw-r--r--db/post_migrate/20201207151651_truncate_security_findings_table_2.rb7
-rw-r--r--db/post_migrate/20201207165956_remove_duplicate_services.rb14
-rw-r--r--db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb44
-rw-r--r--db/post_migrate/20210622041846_finalize_push_event_payloads_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210622045705_finalize_events_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210701033622_finalize_ci_builds_needs_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210701141346_finalize_ci_builds_stage_id_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210706212710_finalize_ci_job_artifacts_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb4
-rw-r--r--db/post_migrate/20210713042153_finalize_ci_sources_pipelines_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210714015537_finalize_ci_build_trace_chunks_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210722155635_finalize_convert_geo_job_artifact_deleted_events_bigint.rb2
-rw-r--r--db/post_migrate/20210802043253_finalize_push_event_payloads_bigint_conversion_3.rb2
-rw-r--r--db/post_migrate/20210802131812_finalize_convert_deployments_bigint.rb2
-rw-r--r--db/post_migrate/20210805131510_finalize_ci_builds_runner_session_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210806131706_finalize_taggins_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210809143931_finalize_job_id_conversion_to_bigint_for_ci_job_artifacts.rb2
-rw-r--r--db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb2
-rw-r--r--db/post_migrate/20210907211557_finalize_ci_builds_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210923192648_remove_foreign_keys_from_open_project_data_table.rb17
-rw-r--r--db/post_migrate/20210923192649_remove_open_project_data_table.rb22
-rw-r--r--db/post_migrate/20210930211936_backfill_user_namespace.rb26
-rw-r--r--db/post_migrate/20211004120135_schedule_add_primary_email_to_emails_if_user_confirmed.rb30
-rw-r--r--db/post_migrate/20211005194425_schedule_requirements_migration.rb35
-rw-r--r--db/post_migrate/20211011104843_add_new_loose_fk_index.rb20
-rw-r--r--db/post_migrate/20211012051221_add_index_btree_namespaces_traversal_ids.rb15
-rw-r--r--db/post_migrate/20211012143815_remove_merge_request_diff_commit_columns.rb13
-rw-r--r--db/post_migrate/20211013125341_create_index_security_ci_builds_on_name_and_id_parser_features.rb26
-rw-r--r--db/post_migrate/20211018101552_add_index_to_tmp_project_id_column_on_namespaces_table.rb15
-rw-r--r--db/post_migrate/20211018101852_add_fk_to_tmp_project_id_column_on_namespaces_table.rb13
-rw-r--r--db/post_migrate/20211018102252_add_index_to_group_id_column_on_webhooks_table.rb15
-rw-r--r--db/post_migrate/20211018123316_remove_not_null_constraint_and_default_for_public_email.rb15
-rw-r--r--db/post_migrate/20211018152654_schedule_remove_duplicate_vulnerabilities_findings3.rb22
-rw-r--r--db/post_migrate/20211021131217_add_deployments_environment_id_and_ref_index.rb15
-rw-r--r--db/post_migrate/20211021140426_remove_geo_upload_deprecated_fields.rb27
-rw-r--r--db/post_migrate/20211021141930_drop_geo_upload_deleted_events_table.rb17
-rw-r--r--db/post_migrate/20211022112202_add_cluster_id_location_index_to_vulnerability_occurrences.rb18
-rw-r--r--db/post_migrate/20211022113000_drop_index_security_ci_builds_on_name_and_id_parser_features_broken.rb26
-rw-r--r--db/post_migrate/20211022160154_remove_outdated_fields_from_geo_node_status.rb12
-rw-r--r--db/post_migrate/20211027064021_track_deletions_in_ci_runners.rb15
-rw-r--r--db/post_migrate/20211027064156_track_deletions_in_chat_names.rb15
-rw-r--r--db/post_migrate/20211027112901_drop_index_keys_on_expires_at_and_before_expiry_notification_undelivered.rb17
-rw-r--r--db/post_migrate/20211027204011_remove_index_for_dormant_users.rb17
-rw-r--r--db/post_migrate/20211028085926_add_occurrence_id_id_desc_index_to_vulnerability_occurrence_pipelines.rb23
-rw-r--r--db/post_migrate/20211028100303_tmp_index_for_delete_issue_merge_request_taggings_records.rb16
-rw-r--r--db/post_migrate/20211028100843_delete_issue_merge_request_taggings_records.rb19
-rw-r--r--db/post_migrate/20211028123412_add_async_index_on_events_using_btree_created_at_id.rb16
-rw-r--r--db/post_migrate/20211028155449_schedule_fix_merge_request_diff_commit_users_migration.rb55
-rw-r--r--db/post_migrate/20211029102822_add_open_source_plan.rb39
-rw-r--r--db/post_migrate/20211031152417_add_indexes_to_issue_stage_events.rb41
-rw-r--r--db/post_migrate/20211031154919_add_indexes_to_merge_request_stage_events.rb41
-rw-r--r--db/post_migrate/20211102103127_add_temp_index_to_vulnerability_occurrences.rb15
-rw-r--r--db/post_migrate/20211102114802_update_vulnerability_occurrences_location.rb24
-rw-r--r--db/post_migrate/20211103162025_add_index_on_events_using_btree_created_at_id.rb17
-rw-r--r--db/post_migrate/20211104044453_remove_redundant_events_index.rb13
-rw-r--r--db/post_migrate/20211105135157_drop_ci_build_trace_sections.rb99
-rw-r--r--db/post_migrate/20211109112454_drop_old_loose_fk_deleted_records_index.rb20
-rw-r--r--db/post_migrate/20211112113300_remove_ci_pipeline_chat_data_fk_on_chat_names.rb22
-rw-r--r--db/post_migrate/20211115151704_add_index_on_projects_import_type_id.rb15
-rw-r--r--db/schema_migrations/202001021401481
-rw-r--r--db/schema_migrations/202001021702211
-rw-r--r--db/schema_migrations/202001031907411
-rw-r--r--db/schema_migrations/202001031928591
-rw-r--r--db/schema_migrations/202001031929141
-rw-r--r--db/schema_migrations/202001031952051
-rw-r--r--db/schema_migrations/202001041138501
-rw-r--r--db/schema_migrations/202001060711131
-rw-r--r--db/schema_migrations/202001060858311
-rw-r--r--db/schema_migrations/202001071720201
-rw-r--r--db/schema_migrations/202001081006031
-rw-r--r--db/schema_migrations/202001081557311
-rw-r--r--db/schema_migrations/202001082330401
-rw-r--r--db/schema_migrations/202001090304181
-rw-r--r--db/schema_migrations/202001090852061
-rw-r--r--db/schema_migrations/202001092339381
-rw-r--r--db/schema_migrations/202001100890011
-rw-r--r--db/schema_migrations/202001100901531
-rw-r--r--db/schema_migrations/202001101213141
-rw-r--r--db/schema_migrations/202001101443161
-rw-r--r--db/schema_migrations/202001102035321
-rw-r--r--db/schema_migrations/202001131333521
-rw-r--r--db/schema_migrations/202001131513541
-rw-r--r--db/schema_migrations/202001141129321
-rw-r--r--db/schema_migrations/202001141133411
-rw-r--r--db/schema_migrations/202001141403051
-rw-r--r--db/schema_migrations/202001142049491
-rw-r--r--db/schema_migrations/202001151351321
-rw-r--r--db/schema_migrations/202001151352341
-rw-r--r--db/schema_migrations/202001160516191
-rw-r--r--db/schema_migrations/202001161755381
-rw-r--r--db/schema_migrations/202001171125541
-rw-r--r--db/schema_migrations/202001171948301
-rw-r--r--db/schema_migrations/202001171948401
-rw-r--r--db/schema_migrations/202001171948501
-rw-r--r--db/schema_migrations/202001171949001
-rw-r--r--db/schema_migrations/202001200836071
-rw-r--r--db/schema_migrations/202001211326411
-rw-r--r--db/schema_migrations/202001211929421
-rw-r--r--db/schema_migrations/202001211940001
-rw-r--r--db/schema_migrations/202001211940481
-rw-r--r--db/schema_migrations/202001211941541
-rw-r--r--db/schema_migrations/202001212002031
-rw-r--r--db/schema_migrations/202001221230161
-rw-r--r--db/schema_migrations/202001221447591
-rw-r--r--db/schema_migrations/202001221616381
-rw-r--r--db/schema_migrations/202001230405351
-rw-r--r--db/schema_migrations/202001230454151
-rw-r--r--db/schema_migrations/202001230908391
-rw-r--r--db/schema_migrations/202001230914221
-rw-r--r--db/schema_migrations/202001230916221
-rw-r--r--db/schema_migrations/202001230917341
-rw-r--r--db/schema_migrations/202001230918541
-rw-r--r--db/schema_migrations/202001231559291
-rw-r--r--db/schema_migrations/202001240535311
-rw-r--r--db/schema_migrations/202001241108311
-rw-r--r--db/schema_migrations/202001241430141
-rw-r--r--db/schema_migrations/202001270902331
-rw-r--r--db/schema_migrations/202001271118401
-rw-r--r--db/schema_migrations/202001281057311
-rw-r--r--db/schema_migrations/202001281325101
-rw-r--r--db/schema_migrations/202001281335101
-rw-r--r--db/schema_migrations/202001281341101
-rw-r--r--db/schema_migrations/202001281411251
-rw-r--r--db/schema_migrations/202001281842091
-rw-r--r--db/schema_migrations/202001282103531
-rw-r--r--db/schema_migrations/202001290345151
-rw-r--r--db/schema_migrations/202001290354461
-rw-r--r--db/schema_migrations/202001290357081
-rw-r--r--db/schema_migrations/202001291337161
-rw-r--r--db/schema_migrations/202001291724281
-rw-r--r--db/schema_migrations/202001301343351
-rw-r--r--db/schema_migrations/202001301454301
-rw-r--r--db/schema_migrations/202001301618171
-rw-r--r--db/schema_migrations/202001311404281
-rw-r--r--db/schema_migrations/202001311813541
-rw-r--r--db/schema_migrations/202001311917541
-rw-r--r--db/schema_migrations/202002021009321
-rw-r--r--db/schema_migrations/202002030151401
-rw-r--r--db/schema_migrations/202002030254001
-rw-r--r--db/schema_migrations/202002030256021
-rw-r--r--db/schema_migrations/202002030256191
-rw-r--r--db/schema_migrations/202002030257441
-rw-r--r--db/schema_migrations/202002030258011
-rw-r--r--db/schema_migrations/202002030258211
-rw-r--r--db/schema_migrations/202002031042141
-rw-r--r--db/schema_migrations/202002031735081
-rw-r--r--db/schema_migrations/202002031835081
-rw-r--r--db/schema_migrations/202002032324331
-rw-r--r--db/schema_migrations/202002040707291
-rw-r--r--db/schema_migrations/202002041132231
-rw-r--r--db/schema_migrations/202002041132241
-rw-r--r--db/schema_migrations/202002041132251
-rw-r--r--db/schema_migrations/202002041310541
-rw-r--r--db/schema_migrations/202002041318311
-rw-r--r--db/schema_migrations/202002051432311
-rw-r--r--db/schema_migrations/202002060915441
-rw-r--r--db/schema_migrations/202002061128501
-rw-r--r--db/schema_migrations/202002061352031
-rw-r--r--db/schema_migrations/202002061415111
-rw-r--r--db/schema_migrations/202002070627281
-rw-r--r--db/schema_migrations/202002070909211
-rw-r--r--db/schema_migrations/202002071327521
-rw-r--r--db/schema_migrations/202002071516401
-rw-r--r--db/schema_migrations/202002071821311
-rw-r--r--db/schema_migrations/202002071840231
-rw-r--r--db/schema_migrations/202002071851491
-rw-r--r--db/schema_migrations/202002091311521
-rw-r--r--db/schema_migrations/202002100624321
-rw-r--r--db/schema_migrations/202002100924051
-rw-r--r--db/schema_migrations/202002101355041
-rw-r--r--db/schema_migrations/202002101844101
-rw-r--r--db/schema_migrations/202002101844201
-rw-r--r--db/schema_migrations/202002111524101
-rw-r--r--db/schema_migrations/202002111550001
-rw-r--r--db/schema_migrations/202002111551001
-rw-r--r--db/schema_migrations/202002111555391
-rw-r--r--db/schema_migrations/202002111749461
-rw-r--r--db/schema_migrations/202002120146531
-rw-r--r--db/schema_migrations/202002120526201
-rw-r--r--db/schema_migrations/202002121339451
-rw-r--r--db/schema_migrations/202002121342011
-rw-r--r--db/schema_migrations/202002130937021
-rw-r--r--db/schema_migrations/202002131005301
-rw-r--r--db/schema_migrations/202002131553111
-rw-r--r--db/schema_migrations/202002132047371
-rw-r--r--db/schema_migrations/202002132201591
-rw-r--r--db/schema_migrations/202002132202111
-rw-r--r--db/schema_migrations/202002132242201
-rw-r--r--db/schema_migrations/202002140254541
-rw-r--r--db/schema_migrations/202002140348361
-rw-r--r--db/schema_migrations/202002140859401
-rw-r--r--db/schema_migrations/202002142149341
-rw-r--r--db/schema_migrations/202002152225071
-rw-r--r--db/schema_migrations/202002152251031
-rw-r--r--db/schema_migrations/202002172103531
-rw-r--r--db/schema_migrations/202002172236511
-rw-r--r--db/schema_migrations/202002172257191
-rw-r--r--db/schema_migrations/202002181137211
-rw-r--r--db/schema_migrations/202002191052091
-rw-r--r--db/schema_migrations/202002191338591
-rw-r--r--db/schema_migrations/202002191354401
-rw-r--r--db/schema_migrations/202002191413071
-rw-r--r--db/schema_migrations/202002191425221
-rw-r--r--db/schema_migrations/202002191834561
-rw-r--r--db/schema_migrations/202002191842191
-rw-r--r--db/schema_migrations/202002191930581
-rw-r--r--db/schema_migrations/202002191931171
-rw-r--r--db/schema_migrations/202002201150231
-rw-r--r--db/schema_migrations/202002201809441
-rw-r--r--db/schema_migrations/202002210233201
-rw-r--r--db/schema_migrations/202002210740281
-rw-r--r--db/schema_migrations/202002211005141
-rw-r--r--db/schema_migrations/202002211054361
-rw-r--r--db/schema_migrations/202002211422161
-rw-r--r--db/schema_migrations/202002211445341
-rw-r--r--db/schema_migrations/202002220555431
-rw-r--r--db/schema_migrations/202002240202191
-rw-r--r--db/schema_migrations/202002241638041
-rw-r--r--db/schema_migrations/202002241858141
-rw-r--r--db/schema_migrations/202002251110181
-rw-r--r--db/schema_migrations/202002251232281
-rw-r--r--db/schema_migrations/202002261006141
-rw-r--r--db/schema_migrations/202002261006241
-rw-r--r--db/schema_migrations/202002261006341
-rw-r--r--db/schema_migrations/202002261247571
-rw-r--r--db/schema_migrations/202002261621561
-rw-r--r--db/schema_migrations/202002261622391
-rw-r--r--db/schema_migrations/202002261626341
-rw-r--r--db/schema_migrations/202002261627231
-rw-r--r--db/schema_migrations/202002271402421
-rw-r--r--db/schema_migrations/202002271641131
-rw-r--r--db/schema_migrations/202002271651291
-rw-r--r--db/schema_migrations/202002281605421
-rw-r--r--db/schema_migrations/202002291717001
-rw-r--r--db/schema_migrations/202003021420521
-rw-r--r--db/schema_migrations/202003021525161
-rw-r--r--db/schema_migrations/202003030553481
-rw-r--r--db/schema_migrations/202003030743281
-rw-r--r--db/schema_migrations/202003031816481
-rw-r--r--db/schema_migrations/202003040232451
-rw-r--r--db/schema_migrations/202003040238511
-rw-r--r--db/schema_migrations/202003040240251
-rw-r--r--db/schema_migrations/202003040240421
-rw-r--r--db/schema_migrations/202003040854231
-rw-r--r--db/schema_migrations/202003040901551
-rw-r--r--db/schema_migrations/202003041218281
-rw-r--r--db/schema_migrations/202003041218441
-rw-r--r--db/schema_migrations/202003041244061
-rw-r--r--db/schema_migrations/202003041608001
-rw-r--r--db/schema_migrations/202003041608011
-rw-r--r--db/schema_migrations/202003041608231
-rw-r--r--db/schema_migrations/202003042117381
-rw-r--r--db/schema_migrations/202003050204581
-rw-r--r--db/schema_migrations/202003050204591
-rw-r--r--db/schema_migrations/202003050827541
-rw-r--r--db/schema_migrations/202003050828581
-rw-r--r--db/schema_migrations/202003051211591
-rw-r--r--db/schema_migrations/202003051517361
-rw-r--r--db/schema_migrations/202003052006411
-rw-r--r--db/schema_migrations/202003060956541
-rw-r--r--db/schema_migrations/202003061605211
-rw-r--r--db/schema_migrations/202003061702111
-rw-r--r--db/schema_migrations/202003061703211
-rw-r--r--db/schema_migrations/202003061705311
-rw-r--r--db/schema_migrations/202003061925481
-rw-r--r--db/schema_migrations/202003061932361
-rw-r--r--db/schema_migrations/202003091405401
-rw-r--r--db/schema_migrations/202003091622441
-rw-r--r--db/schema_migrations/202003091952091
-rw-r--r--db/schema_migrations/202003091957101
-rw-r--r--db/schema_migrations/202003100751151
-rw-r--r--db/schema_migrations/202003101232291
-rw-r--r--db/schema_migrations/202003101326541
-rw-r--r--db/schema_migrations/202003101338221
-rw-r--r--db/schema_migrations/202003101358181
-rw-r--r--db/schema_migrations/202003101358231
-rw-r--r--db/schema_migrations/202003101453041
-rw-r--r--db/schema_migrations/202003102157141
-rw-r--r--db/schema_migrations/202003110744381
-rw-r--r--db/schema_migrations/202003110823011
-rw-r--r--db/schema_migrations/202003110840251
-rw-r--r--db/schema_migrations/202003110932101
-rw-r--r--db/schema_migrations/202003110940201
-rw-r--r--db/schema_migrations/202003111308021
-rw-r--r--db/schema_migrations/202003111410531
-rw-r--r--db/schema_migrations/202003111419431
-rw-r--r--db/schema_migrations/202003111541101
-rw-r--r--db/schema_migrations/202003111656351
-rw-r--r--db/schema_migrations/202003111923511
-rw-r--r--db/schema_migrations/202003112149121
-rw-r--r--db/schema_migrations/202003120538521
-rw-r--r--db/schema_migrations/202003121251211
-rw-r--r--db/schema_migrations/202003121346371
-rw-r--r--db/schema_migrations/202003121605321
-rw-r--r--db/schema_migrations/202003121634071
-rw-r--r--db/schema_migrations/202003131016491
-rw-r--r--db/schema_migrations/202003131239341
-rw-r--r--db/schema_migrations/202003132024301
-rw-r--r--db/schema_migrations/202003132035251
-rw-r--r--db/schema_migrations/202003132035501
-rw-r--r--db/schema_migrations/202003132040211
-rw-r--r--db/schema_migrations/202003140608341
-rw-r--r--db/schema_migrations/202003161117591
-rw-r--r--db/schema_migrations/202003161626481
-rw-r--r--db/schema_migrations/202003161733121
-rw-r--r--db/schema_migrations/202003171106021
-rw-r--r--db/schema_migrations/202003171421101
-rw-r--r--db/schema_migrations/202003181404001
-rw-r--r--db/schema_migrations/202003181521341
-rw-r--r--db/schema_migrations/202003181621481
-rw-r--r--db/schema_migrations/202003181631481
-rw-r--r--db/schema_migrations/202003181644481
-rw-r--r--db/schema_migrations/202003181654481
-rw-r--r--db/schema_migrations/202003181750081
-rw-r--r--db/schema_migrations/202003181835531
-rw-r--r--db/schema_migrations/202003190717021
-rw-r--r--db/schema_migrations/202003191230411
-rw-r--r--db/schema_migrations/202003191241271
-rw-r--r--db/schema_migrations/202003192039011
-rw-r--r--db/schema_migrations/202003201124551
-rw-r--r--db/schema_migrations/202003201238391
-rw-r--r--db/schema_migrations/202003202124001
-rw-r--r--db/schema_migrations/202003230112251
-rw-r--r--db/schema_migrations/202003230119551
-rw-r--r--db/schema_migrations/202003230719181
-rw-r--r--db/schema_migrations/202003230741471
-rw-r--r--db/schema_migrations/202003230750431
-rw-r--r--db/schema_migrations/202003230807141
-rw-r--r--db/schema_migrations/202003231222011
-rw-r--r--db/schema_migrations/202003231345191
-rw-r--r--db/schema_migrations/202003240932581
-rw-r--r--db/schema_migrations/202003241153591
-rw-r--r--db/schema_migrations/202003250946121
-rw-r--r--db/schema_migrations/202003251047551
-rw-r--r--db/schema_migrations/202003251047561
-rw-r--r--db/schema_migrations/202003251048331
-rw-r--r--db/schema_migrations/202003251048341
-rw-r--r--db/schema_migrations/202003251114321
-rw-r--r--db/schema_migrations/202003251523271
-rw-r--r--db/schema_migrations/202003251609521
-rw-r--r--db/schema_migrations/202003251627301
-rw-r--r--db/schema_migrations/202003251836361
-rw-r--r--db/schema_migrations/202003261144431
-rw-r--r--db/schema_migrations/202003261227001
-rw-r--r--db/schema_migrations/202003261244431
-rw-r--r--db/schema_migrations/202003261344431
-rw-r--r--db/schema_migrations/202003261354431
-rw-r--r--db/schema_migrations/202003261444431
-rw-r--r--db/schema_migrations/202003261454431
-rw-r--r--db/schema_migrations/202003300747191
-rw-r--r--db/schema_migrations/202003301210001
-rw-r--r--db/schema_migrations/202003301237391
-rw-r--r--db/schema_migrations/202003301329131
-rw-r--r--db/schema_migrations/202003302038261
-rw-r--r--db/schema_migrations/202003302038371
-rw-r--r--db/schema_migrations/202003311036371
-rw-r--r--db/schema_migrations/202003311137281
-rw-r--r--db/schema_migrations/202003311137381
-rw-r--r--db/schema_migrations/202003311321031
-rw-r--r--db/schema_migrations/202003311959521
-rw-r--r--db/schema_migrations/202003312209301
-rw-r--r--db/schema_migrations/202004010910511
-rw-r--r--db/schema_migrations/202004010954301
-rw-r--r--db/schema_migrations/202004012110051
-rw-r--r--db/schema_migrations/202004020011061
-rw-r--r--db/schema_migrations/202004021150131
-rw-r--r--db/schema_migrations/202004021156231
-rw-r--r--db/schema_migrations/202004021239261
-rw-r--r--db/schema_migrations/202004021248021
-rw-r--r--db/schema_migrations/202004021352501
-rw-r--r--db/schema_migrations/202004021850441
-rw-r--r--db/schema_migrations/202004031323491
-rw-r--r--db/schema_migrations/202004031841101
-rw-r--r--db/schema_migrations/202004031851271
-rw-r--r--db/schema_migrations/202004031854221
-rw-r--r--db/schema_migrations/202004060959301
-rw-r--r--db/schema_migrations/202004061009091
-rw-r--r--db/schema_migrations/202004061021111
-rw-r--r--db/schema_migrations/202004061021201
-rw-r--r--db/schema_migrations/202004061325291
-rw-r--r--db/schema_migrations/202004061356481
-rw-r--r--db/schema_migrations/202004061414521
-rw-r--r--db/schema_migrations/202004061920591
-rw-r--r--db/schema_migrations/202004061934271
-rw-r--r--db/schema_migrations/202004070940051
-rw-r--r--db/schema_migrations/202004070949231
-rw-r--r--db/schema_migrations/202004071200001
-rw-r--r--db/schema_migrations/202004071213211
-rw-r--r--db/schema_migrations/202004071711331
-rw-r--r--db/schema_migrations/202004071714171
-rw-r--r--db/schema_migrations/202004071822051
-rw-r--r--db/schema_migrations/202004072226471
-rw-r--r--db/schema_migrations/202004081108561
-rw-r--r--db/schema_migrations/202004081250461
-rw-r--r--db/schema_migrations/202004081321521
-rw-r--r--db/schema_migrations/202004081332111
-rw-r--r--db/schema_migrations/202004081538421
-rw-r--r--db/schema_migrations/202004081543311
-rw-r--r--db/schema_migrations/202004081543491
-rw-r--r--db/schema_migrations/202004081544111
-rw-r--r--db/schema_migrations/202004081544281
-rw-r--r--db/schema_migrations/202004081544551
-rw-r--r--db/schema_migrations/202004081545331
-rw-r--r--db/schema_migrations/202004081546041
-rw-r--r--db/schema_migrations/202004081546241
-rw-r--r--db/schema_migrations/202004081754241
-rw-r--r--db/schema_migrations/202004082122191
-rw-r--r--db/schema_migrations/202004090859561
-rw-r--r--db/schema_migrations/202004091054551
-rw-r--r--db/schema_migrations/202004091054561
-rw-r--r--db/schema_migrations/202004092116071
-rw-r--r--db/schema_migrations/202004101048281
-rw-r--r--db/schema_migrations/202004102320121
-rw-r--r--db/schema_migrations/202004111256561
-rw-r--r--db/schema_migrations/202004130720591
-rw-r--r--db/schema_migrations/202004132300561
-rw-r--r--db/schema_migrations/202004141124441
-rw-r--r--db/schema_migrations/202004141146111
-rw-r--r--db/schema_migrations/202004141158011
-rw-r--r--db/schema_migrations/202004141445471
-rw-r--r--db/schema_migrations/202004151531541
-rw-r--r--db/schema_migrations/202004151607221
-rw-r--r--db/schema_migrations/202004151610211
-rw-r--r--db/schema_migrations/202004151612061
-rw-r--r--db/schema_migrations/202004151926561
-rw-r--r--db/schema_migrations/202004152030241
-rw-r--r--db/schema_migrations/202004160053311
-rw-r--r--db/schema_migrations/202004161111111
-rw-r--r--db/schema_migrations/202004161201281
-rw-r--r--db/schema_migrations/202004161203541
-rw-r--r--db/schema_migrations/202004170444531
-rw-r--r--db/schema_migrations/202004170758431
-rw-r--r--db/schema_migrations/202004171459461
-rw-r--r--db/schema_migrations/202004200920111
-rw-r--r--db/schema_migrations/202004200944441
-rw-r--r--db/schema_migrations/202004201043031
-rw-r--r--db/schema_migrations/202004201043231
-rw-r--r--db/schema_migrations/202004201159481
-rw-r--r--db/schema_migrations/202004201417331
-rw-r--r--db/schema_migrations/202004201627301
-rw-r--r--db/schema_migrations/202004201721131
-rw-r--r--db/schema_migrations/202004201727521
-rw-r--r--db/schema_migrations/202004201729271
-rw-r--r--db/schema_migrations/202004202019331
-rw-r--r--db/schema_migrations/202004210549301
-rw-r--r--db/schema_migrations/202004210549481
-rw-r--r--db/schema_migrations/202004210929071
-rw-r--r--db/schema_migrations/202004211110051
-rw-r--r--db/schema_migrations/202004211952341
-rw-r--r--db/schema_migrations/202004212331501
-rw-r--r--db/schema_migrations/202004220915411
-rw-r--r--db/schema_migrations/202004222137491
-rw-r--r--db/schema_migrations/202004230757201
-rw-r--r--db/schema_migrations/202004230803341
-rw-r--r--db/schema_migrations/202004230806071
-rw-r--r--db/schema_migrations/202004230814091
-rw-r--r--db/schema_migrations/202004230814411
-rw-r--r--db/schema_migrations/202004230815191
-rw-r--r--db/schema_migrations/202004231015291
-rw-r--r--db/schema_migrations/202004240435151
-rw-r--r--db/schema_migrations/202004240502501
-rw-r--r--db/schema_migrations/202004241019201
-rw-r--r--db/schema_migrations/202004241020231
-rw-r--r--db/schema_migrations/202004241353191
-rw-r--r--db/schema_migrations/202004270641301
-rw-r--r--db/schema_migrations/202004281343561
-rw-r--r--db/schema_migrations/202004290018271
-rw-r--r--db/schema_migrations/202004290021501
-rw-r--r--db/schema_migrations/202004290156031
-rw-r--r--db/schema_migrations/202004290233241
-rw-r--r--db/schema_migrations/202004291813351
-rw-r--r--db/schema_migrations/202004291819551
-rw-r--r--db/schema_migrations/202004291822451
-rw-r--r--db/schema_migrations/202004301031581
-rw-r--r--db/schema_migrations/202004301236141
-rw-r--r--db/schema_migrations/202004301300481
-rw-r--r--db/schema_migrations/202004301746371
-rw-r--r--db/schema_migrations/202005041918131
-rw-r--r--db/schema_migrations/202005042007091
-rw-r--r--db/schema_migrations/202005051649581
-rw-r--r--db/schema_migrations/202005051718341
-rw-r--r--db/schema_migrations/202005051724051
-rw-r--r--db/schema_migrations/202005060857481
-rw-r--r--db/schema_migrations/202005061257311
-rw-r--r--db/schema_migrations/202005061544211
-rw-r--r--db/schema_migrations/202005072214341
-rw-r--r--db/schema_migrations/202005080211281
-rw-r--r--db/schema_migrations/202005080503011
-rw-r--r--db/schema_migrations/202005080911061
-rw-r--r--db/schema_migrations/202005081409591
-rw-r--r--db/schema_migrations/202005082039011
-rw-r--r--db/schema_migrations/202005092039011
-rw-r--r--db/schema_migrations/202005101819371
-rw-r--r--db/schema_migrations/202005101822181
-rw-r--r--db/schema_migrations/202005101825561
-rw-r--r--db/schema_migrations/202005101828241
-rw-r--r--db/schema_migrations/202005101831281
-rw-r--r--db/schema_migrations/202005110801131
-rw-r--r--db/schema_migrations/202005110835411
-rw-r--r--db/schema_migrations/202005110922461
-rw-r--r--db/schema_migrations/202005110925051
-rw-r--r--db/schema_migrations/202005110927141
-rw-r--r--db/schema_migrations/202005111154301
-rw-r--r--db/schema_migrations/202005111154311
-rw-r--r--db/schema_migrations/202005111215491
-rw-r--r--db/schema_migrations/202005111216101
-rw-r--r--db/schema_migrations/202005111216201
-rw-r--r--db/schema_migrations/202005111301291
-rw-r--r--db/schema_migrations/202005111301301
-rw-r--r--db/schema_migrations/202005111455451
-rw-r--r--db/schema_migrations/202005111620571
-rw-r--r--db/schema_migrations/202005111621151
-rw-r--r--db/schema_migrations/202005111810271
-rw-r--r--db/schema_migrations/202005111910271
-rw-r--r--db/schema_migrations/202005112080121
-rw-r--r--db/schema_migrations/202005112200231
-rw-r--r--db/schema_migrations/202005120851501
-rw-r--r--db/schema_migrations/202005121600041
-rw-r--r--db/schema_migrations/202005121643341
-rw-r--r--db/schema_migrations/202005121954421
-rw-r--r--db/schema_migrations/202005131609301
-rw-r--r--db/schema_migrations/202005131719591
-rw-r--r--db/schema_migrations/202005132241431
-rw-r--r--db/schema_migrations/202005132345021
-rw-r--r--db/schema_migrations/202005132353471
-rw-r--r--db/schema_migrations/202005132355321
-rw-r--r--db/schema_migrations/202005140000091
-rw-r--r--db/schema_migrations/202005140001321
-rw-r--r--db/schema_migrations/202005140003401
-rw-r--r--db/schema_migrations/202005151526491
-rw-r--r--db/schema_migrations/202005151536331
-rw-r--r--db/schema_migrations/202005151556201
-rw-r--r--db/schema_migrations/202005180917451
-rw-r--r--db/schema_migrations/202005181145401
-rw-r--r--db/schema_migrations/202005181331231
-rw-r--r--db/schema_migrations/202005190747091
-rw-r--r--db/schema_migrations/202005191010021
-rw-r--r--db/schema_migrations/202005191159081
-rw-r--r--db/schema_migrations/202005191415341
-rw-r--r--db/schema_migrations/202005191710581
-rw-r--r--db/schema_migrations/202005191940421
-rw-r--r--db/schema_migrations/202005192011281
-rw-r--r--db/schema_migrations/202005201035141
-rw-r--r--db/schema_migrations/202005210227251
-rw-r--r--db/schema_migrations/202005212253271
-rw-r--r--db/schema_migrations/202005212253371
-rw-r--r--db/schema_migrations/202005212253461
-rw-r--r--db/schema_migrations/202005222056061
-rw-r--r--db/schema_migrations/202005222351461
-rw-r--r--db/schema_migrations/202005241043461
-rw-r--r--db/schema_migrations/202005251145531
-rw-r--r--db/schema_migrations/202005251210141
-rw-r--r--db/schema_migrations/202005251445251
-rw-r--r--db/schema_migrations/202005260004071
-rw-r--r--db/schema_migrations/202005260138441
-rw-r--r--db/schema_migrations/202005261154361
-rw-r--r--db/schema_migrations/202005261207141
-rw-r--r--db/schema_migrations/202005261425501
-rw-r--r--db/schema_migrations/202005261538441
-rw-r--r--db/schema_migrations/202005261649461
-rw-r--r--db/schema_migrations/202005261649471
-rw-r--r--db/schema_migrations/202005261935551
-rw-r--r--db/schema_migrations/202005262314211
-rw-r--r--db/schema_migrations/202005270920271
-rw-r--r--db/schema_migrations/202005270943221
-rw-r--r--db/schema_migrations/202005270954011
-rw-r--r--db/schema_migrations/202005271353131
-rw-r--r--db/schema_migrations/202005271514131
-rw-r--r--db/schema_migrations/202005271521161
-rw-r--r--db/schema_migrations/202005271526571
-rw-r--r--db/schema_migrations/202005271706491
-rw-r--r--db/schema_migrations/202005272110001
-rw-r--r--db/schema_migrations/202005272116051
-rw-r--r--db/schema_migrations/202005280541121
-rw-r--r--db/schema_migrations/202005281237031
-rw-r--r--db/schema_migrations/202005281259051
-rw-r--r--db/schema_migrations/202005281719331
-rw-r--r--db/schema_migrations/202006011204341
-rw-r--r--db/schema_migrations/202006012101481
-rw-r--r--db/schema_migrations/202006020139001
-rw-r--r--db/schema_migrations/202006020139011
-rw-r--r--db/schema_migrations/202006021430201
-rw-r--r--db/schema_migrations/202006030731011
-rw-r--r--db/schema_migrations/202006031803381
-rw-r--r--db/schema_migrations/202006040011281
-rw-r--r--db/schema_migrations/202006041436281
-rw-r--r--db/schema_migrations/202006041457311
-rw-r--r--db/schema_migrations/202006041745441
-rw-r--r--db/schema_migrations/202006041745581
-rw-r--r--db/schema_migrations/202006050032041
-rw-r--r--db/schema_migrations/202006050931131
-rw-r--r--db/schema_migrations/202006051608061
-rw-r--r--db/schema_migrations/202006051608361
-rw-r--r--db/schema_migrations/202006051608511
-rw-r--r--db/schema_migrations/202006072230471
-rw-r--r--db/schema_migrations/202006072354351
-rw-r--r--db/schema_migrations/202006080729311
-rw-r--r--db/schema_migrations/202006080755531
-rw-r--r--db/schema_migrations/202006081952221
-rw-r--r--db/schema_migrations/202006082034261
-rw-r--r--db/schema_migrations/202006082058131
-rw-r--r--db/schema_migrations/202006082120301
-rw-r--r--db/schema_migrations/202006082124351
-rw-r--r--db/schema_migrations/202006082125491
-rw-r--r--db/schema_migrations/202006082126521
-rw-r--r--db/schema_migrations/202006082128071
-rw-r--r--db/schema_migrations/202006082128241
-rw-r--r--db/schema_migrations/202006082140081
-rw-r--r--db/schema_migrations/202006090028411
-rw-r--r--db/schema_migrations/202006090125391
-rw-r--r--db/schema_migrations/202006091425061
-rw-r--r--db/schema_migrations/202006091425071
-rw-r--r--db/schema_migrations/202006091425081
-rw-r--r--db/schema_migrations/202006092127011
-rw-r--r--db/schema_migrations/202006100332281
-rw-r--r--db/schema_migrations/202006100406151
-rw-r--r--db/schema_migrations/202006101300021
-rw-r--r--db/schema_migrations/202006110132271
-rw-r--r--db/schema_migrations/202006131040451
-rw-r--r--db/schema_migrations/202006150836351
-rw-r--r--db/schema_migrations/202006151118571
-rw-r--r--db/schema_migrations/202006151212171
-rw-r--r--db/schema_migrations/202006151230551
-rw-r--r--db/schema_migrations/202006151415541
-rw-r--r--db/schema_migrations/202006151935241
-rw-r--r--db/schema_migrations/202006152327351
-rw-r--r--db/schema_migrations/202006152340471
-rw-r--r--db/schema_migrations/202006161243381
-rw-r--r--db/schema_migrations/202006161450311
-rw-r--r--db/schema_migrations/202006170007571
-rw-r--r--db/schema_migrations/202006170010011
-rw-r--r--db/schema_migrations/202006170011181
-rw-r--r--db/schema_migrations/202006170016371
-rw-r--r--db/schema_migrations/202006170018481
-rw-r--r--db/schema_migrations/202006170020301
-rw-r--r--db/schema_migrations/202006171500411
-rw-r--r--db/schema_migrations/202006172050001
-rw-r--r--db/schema_migrations/202006181056381
-rw-r--r--db/schema_migrations/202006181342231
-rw-r--r--db/schema_migrations/202006181347231
-rw-r--r--db/schema_migrations/202006181522121
-rw-r--r--db/schema_migrations/202006190003161
-rw-r--r--db/schema_migrations/202006191545271
-rw-r--r--db/schema_migrations/202006191545281
-rw-r--r--db/schema_migrations/202006220407501
-rw-r--r--db/schema_migrations/202006220706061
-rw-r--r--db/schema_migrations/202006220706201
-rw-r--r--db/schema_migrations/202006220954191
-rw-r--r--db/schema_migrations/202006221038361
-rw-r--r--db/schema_migrations/202006221049231
-rw-r--r--db/schema_migrations/202006222357371
-rw-r--r--db/schema_migrations/202006230001481
-rw-r--r--db/schema_migrations/202006230003201
-rw-r--r--db/schema_migrations/202006230734311
-rw-r--r--db/schema_migrations/202006230900301
-rw-r--r--db/schema_migrations/202006231211351
-rw-r--r--db/schema_migrations/202006231412171
-rw-r--r--db/schema_migrations/202006231415441
-rw-r--r--db/schema_migrations/202006231421591
-rw-r--r--db/schema_migrations/202006231700001
-rw-r--r--db/schema_migrations/202006231854401
-rw-r--r--db/schema_migrations/202006240754111
-rw-r--r--db/schema_migrations/202006241421071
-rw-r--r--db/schema_migrations/202006241422071
-rw-r--r--db/schema_migrations/202006242224431
-rw-r--r--db/schema_migrations/202006250454421
-rw-r--r--db/schema_migrations/202006250822581
-rw-r--r--db/schema_migrations/202006251133371
-rw-r--r--db/schema_migrations/202006251740521
-rw-r--r--db/schema_migrations/202006251904581
-rw-r--r--db/schema_migrations/202006251933581
-rw-r--r--db/schema_migrations/202006260601511
-rw-r--r--db/schema_migrations/202006261302201
-rw-r--r--db/schema_migrations/202006282109381
-rw-r--r--db/schema_migrations/202006291347471
-rw-r--r--db/schema_migrations/202006291926381
-rw-r--r--db/schema_migrations/202006300916561
-rw-r--r--db/schema_migrations/202006301108261
-rw-r--r--db/schema_migrations/202007010647561
-rw-r--r--db/schema_migrations/202007010704351
-rw-r--r--db/schema_migrations/202007010912531
-rw-r--r--db/schema_migrations/202007010938591
-rw-r--r--db/schema_migrations/202007011905231
-rw-r--r--db/schema_migrations/202007012057101
-rw-r--r--db/schema_migrations/202007012213031
-rw-r--r--db/schema_migrations/202007021238051
-rw-r--r--db/schema_migrations/202007022010391
-rw-r--r--db/schema_migrations/202007030350211
-rw-r--r--db/schema_migrations/202007030641171
-rw-r--r--db/schema_migrations/202007031215571
-rw-r--r--db/schema_migrations/202007031248231
-rw-r--r--db/schema_migrations/202007031250161
-rw-r--r--db/schema_migrations/202007031548221
-rw-r--r--db/schema_migrations/202007031654341
-rw-r--r--db/schema_migrations/202007041436331
-rw-r--r--db/schema_migrations/202007041616001
-rw-r--r--db/schema_migrations/202007060053251
-rw-r--r--db/schema_migrations/202007060351411
-rw-r--r--db/schema_migrations/202007061546191
-rw-r--r--db/schema_migrations/202007061705361
-rw-r--r--db/schema_migrations/202007070719411
-rw-r--r--db/schema_migrations/202007070943411
-rw-r--r--db/schema_migrations/202007070958491
-rw-r--r--db/schema_migrations/202007080806311
-rw-r--r--db/schema_migrations/202007091014081
-rw-r--r--db/schema_migrations/202007101024181
-rw-r--r--db/schema_migrations/202007101028461
-rw-r--r--db/schema_migrations/202007101053321
-rw-r--r--db/schema_migrations/202007101134371
-rw-r--r--db/schema_migrations/202007101302341
-rw-r--r--db/schema_migrations/202007101526421
-rw-r--r--db/schema_migrations/202007101530091
-rw-r--r--db/schema_migrations/202007120846551
-rw-r--r--db/schema_migrations/202007122356221
-rw-r--r--db/schema_migrations/202007130710421
-rw-r--r--db/schema_migrations/202007131418541
-rw-r--r--db/schema_migrations/202007131524431
-rw-r--r--db/schema_migrations/202007140757391
-rw-r--r--db/schema_migrations/202007151242101
-rw-r--r--db/schema_migrations/202007151351301
-rw-r--r--db/schema_migrations/202007151711551
-rw-r--r--db/schema_migrations/202007152026591
-rw-r--r--db/schema_migrations/202007160440231
-rw-r--r--db/schema_migrations/202007161200001
-rw-r--r--db/schema_migrations/202007161204191
-rw-r--r--db/schema_migrations/202007161451561
-rw-r--r--db/schema_migrations/202007162342591
-rw-r--r--db/schema_migrations/202007162345181
-rw-r--r--db/schema_migrations/202007170407351
-rw-r--r--db/schema_migrations/202007170802571
-rw-r--r--db/schema_migrations/202007171636561
-rw-r--r--db/schema_migrations/202007180401001
-rw-r--r--db/schema_migrations/202007180402001
-rw-r--r--db/schema_migrations/202007180403001
-rw-r--r--db/schema_migrations/202007200539091
-rw-r--r--db/schema_migrations/202007201540071
-rw-r--r--db/schema_migrations/202007201541231
-rw-r--r--db/schema_migrations/202007201911341
-rw-r--r--db/schema_migrations/202007210345361
-rw-r--r--db/schema_migrations/202007210435021
-rw-r--r--db/schema_migrations/202007210528531
-rw-r--r--db/schema_migrations/202007211405071
-rw-r--r--db/schema_migrations/202007212305581
-rw-r--r--db/schema_migrations/202007220754111
-rw-r--r--db/schema_migrations/202007220846231
-rw-r--r--db/schema_migrations/202007220914351
-rw-r--r--db/schema_migrations/202007221312411
-rw-r--r--db/schema_migrations/202007221320401
-rw-r--r--db/schema_migrations/202007221325401
-rw-r--r--db/schema_migrations/202007221330401
-rw-r--r--db/schema_migrations/202007221335401
-rw-r--r--db/schema_migrations/202007222023181
-rw-r--r--db/schema_migrations/202007230409501
-rw-r--r--db/schema_migrations/202007231252051
-rw-r--r--db/schema_migrations/202007231283321
-rw-r--r--db/schema_migrations/202007231322581
-rw-r--r--db/schema_migrations/202007241001231
-rw-r--r--db/schema_migrations/202007241004211
-rw-r--r--db/schema_migrations/202007241306391
-rw-r--r--db/schema_migrations/202007270823091
-rw-r--r--db/schema_migrations/202007271006311
-rw-r--r--db/schema_migrations/202007271141471
-rw-r--r--db/schema_migrations/202007271423371
-rw-r--r--db/schema_migrations/202007280802501
-rw-r--r--db/schema_migrations/202007281630091
-rw-r--r--db/schema_migrations/202007281741371
-rw-r--r--db/schema_migrations/202007281757101
-rw-r--r--db/schema_migrations/202007281823111
-rw-r--r--db/schema_migrations/202007291510211
-rw-r--r--db/schema_migrations/202007291759351
-rw-r--r--db/schema_migrations/202007291805391
-rw-r--r--db/schema_migrations/202007291816411
-rw-r--r--db/schema_migrations/202007291912271
-rw-r--r--db/schema_migrations/202007292008081
-rw-r--r--db/schema_migrations/202007292022221
-rw-r--r--db/schema_migrations/202007300448101
-rw-r--r--db/schema_migrations/202007300830431
-rw-r--r--db/schema_migrations/202007301319461
-rw-r--r--db/schema_migrations/202007301337301
-rw-r--r--db/schema_migrations/202007302105061
-rw-r--r--db/schema_migrations/202007310850191
-rw-r--r--db/schema_migrations/202007310905531
-rw-r--r--db/schema_migrations/202007312014081
-rw-r--r--db/schema_migrations/202007312018341
-rw-r--r--db/schema_migrations/202008031115121
-rw-r--r--db/schema_migrations/202008031128061
-rw-r--r--db/schema_migrations/202008031253401
-rw-r--r--db/schema_migrations/202008040352301
-rw-r--r--db/schema_migrations/202008040410181
-rw-r--r--db/schema_migrations/202008040419301
-rw-r--r--db/schema_migrations/202008042225431
-rw-r--r--db/schema_migrations/202008050718421
-rw-r--r--db/schema_migrations/202008051503161
-rw-r--r--db/schema_migrations/202008051510011
-rw-r--r--db/schema_migrations/202008051517261
-rw-r--r--db/schema_migrations/202008051521081
-rw-r--r--db/schema_migrations/202008060042321
-rw-r--r--db/schema_migrations/202008060047421
-rw-r--r--db/schema_migrations/202008061729091
-rw-r--r--db/schema_migrations/202008061736331
-rw-r--r--db/schema_migrations/202008070708201
-rw-r--r--db/schema_migrations/202008071102371
-rw-r--r--db/schema_migrations/202008071327261
-rw-r--r--db/schema_migrations/202008071509371
-rw-r--r--db/schema_migrations/202008071523151
-rw-r--r--db/schema_migrations/202008082216411
-rw-r--r--db/schema_migrations/202008092216411
-rw-r--r--db/schema_migrations/202008101009211
-rw-r--r--db/schema_migrations/202008101010291
-rw-r--r--db/schema_migrations/202008101520431
-rw-r--r--db/schema_migrations/202008101603551
-rw-r--r--db/schema_migrations/202008101912561
-rw-r--r--db/schema_migrations/202008110550181
-rw-r--r--db/schema_migrations/202008111300001
-rw-r--r--db/schema_migrations/202008111304331
-rw-r--r--db/schema_migrations/202008111546301
-rw-r--r--db/schema_migrations/202008111546311
-rw-r--r--db/schema_migrations/202008111546321
-rw-r--r--db/schema_migrations/202008111948481
-rw-r--r--db/schema_migrations/202008112115361
-rw-r--r--db/schema_migrations/202008121122041
-rw-r--r--db/schema_migrations/202008121508101
-rw-r--r--db/schema_migrations/202008121508111
-rw-r--r--db/schema_migrations/202008121508121
-rw-r--r--db/schema_migrations/202008131355581
-rw-r--r--db/schema_migrations/202008131433041
-rw-r--r--db/schema_migrations/202008131433561
-rw-r--r--db/schema_migrations/202008131534341
-rw-r--r--db/schema_migrations/202008161330241
-rw-r--r--db/schema_migrations/202008170701261
-rw-r--r--db/schema_migrations/202008171007101
-rw-r--r--db/schema_migrations/202008171428001
-rw-r--r--db/schema_migrations/202008171956281
-rw-r--r--db/schema_migrations/202008180522191
-rw-r--r--db/schema_migrations/202008180924011
-rw-r--r--db/schema_migrations/202008181712291
-rw-r--r--db/schema_migrations/202008190823341
-rw-r--r--db/schema_migrations/202008191136441
-rw-r--r--db/schema_migrations/202008191921431
-rw-r--r--db/schema_migrations/202008192020481
-rw-r--r--db/schema_migrations/202008192022221
-rw-r--r--db/schema_migrations/202008201054081
-rw-r--r--db/schema_migrations/202008201308391
-rw-r--r--db/schema_migrations/202008202040411
-rw-r--r--db/schema_migrations/202008210344191
-rw-r--r--db/schema_migrations/202008211949201
-rw-r--r--db/schema_migrations/202008212243431
-rw-r--r--db/schema_migrations/202008240458121
-rw-r--r--db/schema_migrations/202008241246231
-rw-r--r--db/schema_migrations/202008241300281
-rw-r--r--db/schema_migrations/202008241304471
-rw-r--r--db/schema_migrations/202008250717351
-rw-r--r--db/schema_migrations/202008250810251
-rw-r--r--db/schema_migrations/202008250810351
-rw-r--r--db/schema_migrations/202008250810451
-rw-r--r--db/schema_migrations/202008250810551
-rw-r--r--db/schema_migrations/202008250848191
-rw-r--r--db/schema_migrations/202008251542371
-rw-r--r--db/schema_migrations/202008251800501
-rw-r--r--db/schema_migrations/202008260531521
-rw-r--r--db/schema_migrations/202008260737451
-rw-r--r--db/schema_migrations/202008260923241
-rw-r--r--db/schema_migrations/202008261215521
-rw-r--r--db/schema_migrations/202008262128001
-rw-r--r--db/schema_migrations/202008262207451
-rw-r--r--db/schema_migrations/202008262207461
-rw-r--r--db/schema_migrations/202008270053221
-rw-r--r--db/schema_migrations/202008270609111
-rw-r--r--db/schema_migrations/202008270609321
-rw-r--r--db/schema_migrations/202008270851011
-rw-r--r--db/schema_migrations/202008271022341
-rw-r--r--db/schema_migrations/202008271044321
-rw-r--r--db/schema_migrations/202008271149021
-rw-r--r--db/schema_migrations/202008271428111
-rw-r--r--db/schema_migrations/202008271500571
-rw-r--r--db/schema_migrations/202008281551341
-rw-r--r--db/schema_migrations/202008281552051
-rw-r--r--db/schema_migrations/202008302012041
-rw-r--r--db/schema_migrations/202008310653201
-rw-r--r--db/schema_migrations/202008310653221
-rw-r--r--db/schema_migrations/202008310657051
-rw-r--r--db/schema_migrations/202008310743561
-rw-r--r--db/schema_migrations/202008312046461
-rw-r--r--db/schema_migrations/202008312223471
-rw-r--r--db/schema_migrations/202008312243431
-rw-r--r--db/schema_migrations/202009011701351
-rw-r--r--db/schema_migrations/202009012030551
-rw-r--r--db/schema_migrations/202009012123041
-rw-r--r--db/schema_migrations/202009012144161
-rw-r--r--db/schema_migrations/202009021355421
-rw-r--r--db/schema_migrations/202009030549461
-rw-r--r--db/schema_migrations/202009030644311
-rw-r--r--db/schema_migrations/202009030922411
-rw-r--r--db/schema_migrations/202009040921311
-rw-r--r--db/schema_migrations/202009041315441
-rw-r--r--db/schema_migrations/202009041749011
-rw-r--r--db/schema_migrations/202009050132471
-rw-r--r--db/schema_migrations/202009070212561
-rw-r--r--db/schema_migrations/202009070621011
-rw-r--r--db/schema_migrations/202009070926101
-rw-r--r--db/schema_migrations/202009070927151
-rw-r--r--db/schema_migrations/202009071243001
-rw-r--r--db/schema_migrations/202009080338051
-rw-r--r--db/schema_migrations/202009080642291
-rw-r--r--db/schema_migrations/202009080948101
-rw-r--r--db/schema_migrations/202009080954461
-rw-r--r--db/schema_migrations/202009081000531
-rw-r--r--db/schema_migrations/202009081832311
-rw-r--r--db/schema_migrations/202009082124141
-rw-r--r--db/schema_migrations/202009090405551
-rw-r--r--db/schema_migrations/202009090833391
-rw-r--r--db/schema_migrations/202009091616241
-rw-r--r--db/schema_migrations/202009091940141
-rw-r--r--db/schema_migrations/202009091945241
-rw-r--r--db/schema_migrations/202009101312171
-rw-r--r--db/schema_migrations/202009101312181
-rw-r--r--db/schema_migrations/202009101556171
-rw-r--r--db/schema_migrations/202009101709081
-rw-r--r--db/schema_migrations/202009101755531
-rw-r--r--db/schema_migrations/202009111201321
-rw-r--r--db/schema_migrations/202009111210271
-rw-r--r--db/schema_migrations/202009111210481
-rw-r--r--db/schema_migrations/202009121529431
-rw-r--r--db/schema_migrations/202009121532181
-rw-r--r--db/schema_migrations/202009121932101
-rw-r--r--db/schema_migrations/202009131157001
-rw-r--r--db/schema_migrations/202009140701401
-rw-r--r--db/schema_migrations/202009140913261
-rw-r--r--db/schema_migrations/202009141046421
-rw-r--r--db/schema_migrations/202009141052021
-rw-r--r--db/schema_migrations/202009141551351
-rw-r--r--db/schema_migrations/202009141832271
-rw-r--r--db/schema_migrations/202009141842121
-rw-r--r--db/schema_migrations/202009150442251
-rw-r--r--db/schema_migrations/202009151340041
-rw-r--r--db/schema_migrations/202009151526411
-rw-r--r--db/schema_migrations/202009151644481
-rw-r--r--db/schema_migrations/202009151648441
-rw-r--r--db/schema_migrations/202009151857071
-rw-r--r--db/schema_migrations/202009151911561
-rw-r--r--db/schema_migrations/202009160817491
-rw-r--r--db/schema_migrations/202009161208371
-rw-r--r--db/schema_migrations/202009161350441
-rw-r--r--db/schema_migrations/202009161514421
-rw-r--r--db/schema_migrations/202009161652321
-rw-r--r--db/schema_migrations/202009171216501
-rw-r--r--db/schema_migrations/202009171358021
-rw-r--r--db/schema_migrations/202009171655251
-rw-r--r--db/schema_migrations/202009192003181
-rw-r--r--db/schema_migrations/202009192041551
-rw-r--r--db/schema_migrations/202009201303561
-rw-r--r--db/schema_migrations/202009210938261
-rw-r--r--db/schema_migrations/202009211137221
-rw-r--r--db/schema_migrations/202009211300281
-rw-r--r--db/schema_migrations/202009211313131
-rw-r--r--db/schema_migrations/202009212032311
-rw-r--r--db/schema_migrations/202009220523161
-rw-r--r--db/schema_migrations/202009220546421
-rw-r--r--db/schema_migrations/202009220752441
-rw-r--r--db/schema_migrations/202009220930041
-rw-r--r--db/schema_migrations/202009220959541
-rw-r--r--db/schema_migrations/202009221339491
-rw-r--r--db/schema_migrations/202009221709071
-rw-r--r--db/schema_migrations/202009222317551
-rw-r--r--db/schema_migrations/202009230716221
-rw-r--r--db/schema_migrations/202009230716441
-rw-r--r--db/schema_migrations/202009231023121
-rw-r--r--db/schema_migrations/202009231300571
-rw-r--r--db/schema_migrations/202009231404041
-rw-r--r--db/schema_migrations/202009240358251
-rw-r--r--db/schema_migrations/202009251121041
-rw-r--r--db/schema_migrations/202009251145221
-rw-r--r--db/schema_migrations/202009251253211
-rw-r--r--db/schema_migrations/202009251534231
-rw-r--r--db/schema_migrations/202009251938151
-rw-r--r--db/schema_migrations/202009251939061
-rw-r--r--db/schema_migrations/202009251940061
-rw-r--r--db/schema_migrations/202009272247501
-rw-r--r--db/schema_migrations/202009280957321
-rw-r--r--db/schema_migrations/202009281004081
-rw-r--r--db/schema_migrations/202009281235101
-rw-r--r--db/schema_migrations/202009281252581
-rw-r--r--db/schema_migrations/202009281319341
-rw-r--r--db/schema_migrations/202009281648071
-rw-r--r--db/schema_migrations/202009282035311
-rw-r--r--db/schema_migrations/202009282105241
-rw-r--r--db/schema_migrations/202009282336321
-rw-r--r--db/schema_migrations/202009290327291
-rw-r--r--db/schema_migrations/202009290521381
-rw-r--r--db/schema_migrations/202009290631591
-rw-r--r--db/schema_migrations/202009291132541
-rw-r--r--db/schema_migrations/202009291141071
-rw-r--r--db/schema_migrations/202009300948121
-rw-r--r--db/schema_migrations/202009301313431
-rw-r--r--db/schema_migrations/202009301323191
-rw-r--r--db/schema_migrations/202009301443401
-rw-r--r--db/schema_migrations/202010010221001
-rw-r--r--db/schema_migrations/202010011011361
-rw-r--r--db/schema_migrations/202010020126591
-rw-r--r--db/schema_migrations/202010020946171
-rw-r--r--db/schema_migrations/202010021759531
-rw-r--r--db/schema_migrations/202010041639181
-rw-r--r--db/schema_migrations/202010050927031
-rw-r--r--db/schema_migrations/202010050927091
-rw-r--r--db/schema_migrations/202010050927531
-rw-r--r--db/schema_migrations/202010050943311
-rw-r--r--db/schema_migrations/202010051539551
-rw-r--r--db/schema_migrations/202010060146051
-rw-r--r--db/schema_migrations/202010070335271
-rw-r--r--db/schema_migrations/202010070337231
-rw-r--r--db/schema_migrations/202010071152091
-rw-r--r--db/schema_migrations/202010080115231
-rw-r--r--db/schema_migrations/202010080119371
-rw-r--r--db/schema_migrations/202010080134341
-rw-r--r--db/schema_migrations/202010080756201
-rw-r--r--db/schema_migrations/202010081256431
-rw-r--r--db/schema_migrations/202010081448541
-rw-r--r--db/schema_migrations/202010082244411
-rw-r--r--db/schema_migrations/202010090909541
-rw-r--r--db/schema_migrations/202010110054001
-rw-r--r--db/schema_migrations/202010120730221
-rw-r--r--db/schema_migrations/202010121224281
-rw-r--r--db/schema_migrations/202010121342301
-rw-r--r--db/schema_migrations/202010121353301
-rw-r--r--db/schema_migrations/202010121401101
-rw-r--r--db/schema_migrations/202010121404521
-rw-r--r--db/schema_migrations/202010121949361
-rw-r--r--db/schema_migrations/202010141425211
-rw-r--r--db/schema_migrations/202010141636331
-rw-r--r--db/schema_migrations/202010142053001
-rw-r--r--db/schema_migrations/202010150738081
-rw-r--r--db/schema_migrations/202010151218051
-rw-r--r--db/schema_migrations/202010151218251
-rw-r--r--db/schema_migrations/202010151545271
-rw-r--r--db/schema_migrations/202010151948521
-rw-r--r--db/schema_migrations/202010152310491
-rw-r--r--db/schema_migrations/202010160743021
-rw-r--r--db/schema_migrations/202010190913071
-rw-r--r--db/schema_migrations/202010190947411
-rw-r--r--db/schema_migrations/202010191015491
-rw-r--r--db/schema_migrations/202010191119521
-rw-r--r--db/schema_migrations/202010191130091
-rw-r--r--db/schema_migrations/202010191302441
-rw-r--r--db/schema_migrations/202010191520461
-rw-r--r--db/schema_migrations/202010191619241
-rw-r--r--db/schema_migrations/202010191727041
-rw-r--r--db/schema_migrations/202010201025511
-rw-r--r--db/schema_migrations/202010210850071
-rw-r--r--db/schema_migrations/202010211019561
-rw-r--r--db/schema_migrations/202010211025541
-rw-r--r--db/schema_migrations/202010211053471
-rw-r--r--db/schema_migrations/202010211056001
-rw-r--r--db/schema_migrations/202010211059591
-rw-r--r--db/schema_migrations/202010211428121
-rw-r--r--db/schema_migrations/202010211522101
-rw-r--r--db/schema_migrations/202010211556061
-rw-r--r--db/schema_migrations/202010211905391
-rw-r--r--db/schema_migrations/202010212201011
-rw-r--r--db/schema_migrations/202010220808021
-rw-r--r--db/schema_migrations/202010220948451
-rw-r--r--db/schema_migrations/202010220948461
-rw-r--r--db/schema_migrations/202010221033041
-rw-r--r--db/schema_migrations/202010221445011
-rw-r--r--db/schema_migrations/202010221918171
-rw-r--r--db/schema_migrations/202010221922541
-rw-r--r--db/schema_migrations/202010231146281
-rw-r--r--db/schema_migrations/202010260516431
-rw-r--r--db/schema_migrations/202010261822531
-rw-r--r--db/schema_migrations/202010261855141
-rw-r--r--db/schema_migrations/202010262007361
-rw-r--r--db/schema_migrations/202010270025511
-rw-r--r--db/schema_migrations/202010271010101
-rw-r--r--db/schema_migrations/202010271356511
-rw-r--r--db/schema_migrations/202010272101271
-rw-r--r--db/schema_migrations/202010272111381
-rw-r--r--db/schema_migrations/202010281608311
-rw-r--r--db/schema_migrations/202010281608321
-rw-r--r--db/schema_migrations/202010281828091
-rw-r--r--db/schema_migrations/202010281846401
-rw-r--r--db/schema_migrations/202010282043061
-rw-r--r--db/schema_migrations/202010290522411
-rw-r--r--db/schema_migrations/202010291436501
-rw-r--r--db/schema_migrations/202010291441571
-rw-r--r--db/schema_migrations/202010291444441
-rw-r--r--db/schema_migrations/202010291445241
-rw-r--r--db/schema_migrations/202010300921511
-rw-r--r--db/schema_migrations/202010301213141
-rw-r--r--db/schema_migrations/202010302001151
-rw-r--r--db/schema_migrations/202010302005391
-rw-r--r--db/schema_migrations/202010302038541
-rw-r--r--db/schema_migrations/202010302239331
-rw-r--r--db/schema_migrations/202011020738081
-rw-r--r--db/schema_migrations/202011021122061
-rw-r--r--db/schema_migrations/202011021140181
-rw-r--r--db/schema_migrations/202011021525541
-rw-r--r--db/schema_migrations/202011021529451
-rw-r--r--db/schema_migrations/202011021847431
-rw-r--r--db/schema_migrations/202011030132421
-rw-r--r--db/schema_migrations/202011030455151
-rw-r--r--db/schema_migrations/202011030957521
-rw-r--r--db/schema_migrations/202011031100181
-rw-r--r--db/schema_migrations/202011031715371
-rw-r--r--db/schema_migrations/202011031843331
-rw-r--r--db/schema_migrations/202011031925261
-rw-r--r--db/schema_migrations/202011032022131
-rw-r--r--db/schema_migrations/202011041243001
-rw-r--r--db/schema_migrations/202011041420361
-rw-r--r--db/schema_migrations/202011042047391
-rw-r--r--db/schema_migrations/202011050216371
-rw-r--r--db/schema_migrations/202011050241271
-rw-r--r--db/schema_migrations/202011051350511
-rw-r--r--db/schema_migrations/202011051432111
-rw-r--r--db/schema_migrations/202011051433121
-rw-r--r--db/schema_migrations/202011060827231
-rw-r--r--db/schema_migrations/202011061341391
-rw-r--r--db/schema_migrations/202011061349501
-rw-r--r--db/schema_migrations/202011061356081
-rw-r--r--db/schema_migrations/202011061934521
-rw-r--r--db/schema_migrations/202011070322571
-rw-r--r--db/schema_migrations/202011081349191
-rw-r--r--db/schema_migrations/202011090806451
-rw-r--r--db/schema_migrations/202011090806461
-rw-r--r--db/schema_migrations/202011091146031
-rw-r--r--db/schema_migrations/202011091446341
-rw-r--r--db/schema_migrations/202011091803111
-rw-r--r--db/schema_migrations/202011091840231
-rw-r--r--db/schema_migrations/202011100350291
-rw-r--r--db/schema_migrations/202011101104541
-rw-r--r--db/schema_migrations/202011101336291
-rw-r--r--db/schema_migrations/202011101615421
-rw-r--r--db/schema_migrations/202011102214001
-rw-r--r--db/schema_migrations/202011110516551
-rw-r--r--db/schema_migrations/202011110518471
-rw-r--r--db/schema_migrations/202011110519041
-rw-r--r--db/schema_migrations/202011111001361
-rw-r--r--db/schema_migrations/202011111103181
-rw-r--r--db/schema_migrations/202011111109181
-rw-r--r--db/schema_migrations/202011111154141
-rw-r--r--db/schema_migrations/202011111453171
-rw-r--r--db/schema_migrations/202011111528591
-rw-r--r--db/schema_migrations/202011121307101
-rw-r--r--db/schema_migrations/202011121307151
-rw-r--r--db/schema_migrations/202011121328081
-rw-r--r--db/schema_migrations/202011121453111
-rw-r--r--db/schema_migrations/202011121735321
-rw-r--r--db/schema_migrations/202011121739111
-rw-r--r--db/schema_migrations/202011121953221
-rw-r--r--db/schema_migrations/202011122150281
-rw-r--r--db/schema_migrations/202011122151321
-rw-r--r--db/schema_migrations/202011131050001
-rw-r--r--db/schema_migrations/202011160903281
-rw-r--r--db/schema_migrations/202011162118291
-rw-r--r--db/schema_migrations/202011170546091
-rw-r--r--db/schema_migrations/202011170757421
-rw-r--r--db/schema_migrations/202011171533331
-rw-r--r--db/schema_migrations/202011171843341
-rw-r--r--db/schema_migrations/202011172032241
-rw-r--r--db/schema_migrations/202011172130241
-rw-r--r--db/schema_migrations/202011180931351
-rw-r--r--db/schema_migrations/202011190315151
-rw-r--r--db/schema_migrations/202011190536031
-rw-r--r--db/schema_migrations/202011190923191
-rw-r--r--db/schema_migrations/202011191257301
-rw-r--r--db/schema_migrations/202011191335341
-rw-r--r--db/schema_migrations/202011191336041
-rw-r--r--db/schema_migrations/202011191628011
-rw-r--r--db/schema_migrations/202011191646051
-rw-r--r--db/schema_migrations/202011192134061
-rw-r--r--db/schema_migrations/202011200713031
-rw-r--r--db/schema_migrations/202011200920001
-rw-r--r--db/schema_migrations/202011201259531
-rw-r--r--db/schema_migrations/202011201402101
-rw-r--r--db/schema_migrations/202011201448231
-rw-r--r--db/schema_migrations/202011230813071
-rw-r--r--db/schema_migrations/202011231616111
-rw-r--r--db/schema_migrations/202011240305371
-rw-r--r--db/schema_migrations/202011240759511
-rw-r--r--db/schema_migrations/202011241228171
-rw-r--r--db/schema_migrations/202011241856391
-rw-r--r--db/schema_migrations/202011250308471
-rw-r--r--db/schema_migrations/202011252332191
-rw-r--r--db/schema_migrations/202011261659191
-rw-r--r--db/schema_migrations/202011261720301
-rw-r--r--db/schema_migrations/202011261900391
-rw-r--r--db/schema_migrations/202011271042281
-rw-r--r--db/schema_migrations/202011271414331
-rw-r--r--db/schema_migrations/202011271708481
-rw-r--r--db/schema_migrations/202011282100001
-rw-r--r--db/schema_migrations/202011282102341
-rw-r--r--db/schema_migrations/202011301039261
-rw-r--r--db/schema_migrations/202012010332021
-rw-r--r--db/schema_migrations/202012010342581
-rw-r--r--db/schema_migrations/202012011616551
-rw-r--r--db/schema_migrations/202012011632271
-rw-r--r--db/schema_migrations/202012011756561
-rw-r--r--db/schema_migrations/202012011900021
-rw-r--r--db/schema_migrations/202012011921121
-rw-r--r--db/schema_migrations/202012020030421
-rw-r--r--db/schema_migrations/202012020256441
-rw-r--r--db/schema_migrations/202012020259371
-rw-r--r--db/schema_migrations/202012021336061
-rw-r--r--db/schema_migrations/202012021427511
-rw-r--r--db/schema_migrations/202012021500011
-rw-r--r--db/schema_migrations/202012021559131
-rw-r--r--db/schema_migrations/202012021601051
-rw-r--r--db/schema_migrations/202012021610211
-rw-r--r--db/schema_migrations/202012031232011
-rw-r--r--db/schema_migrations/202012031235241
-rw-r--r--db/schema_migrations/202012031446551
-rw-r--r--db/schema_migrations/202012031716311
-rw-r--r--db/schema_migrations/202012040855221
-rw-r--r--db/schema_migrations/202012040908551
-rw-r--r--db/schema_migrations/202012041053001
-rw-r--r--db/schema_migrations/202012041107001
-rw-r--r--db/schema_migrations/202012041108001
-rw-r--r--db/schema_migrations/202012041110001
-rw-r--r--db/schema_migrations/202012041111001
-rw-r--r--db/schema_migrations/202012041112001
-rw-r--r--db/schema_migrations/202012041113001
-rw-r--r--db/schema_migrations/202012041114001
-rw-r--r--db/schema_migrations/202012041115001
-rw-r--r--db/schema_migrations/202012041116001
-rw-r--r--db/schema_migrations/202012041410381
-rw-r--r--db/schema_migrations/202012041939521
-rw-r--r--db/schema_migrations/202012042058141
-rw-r--r--db/schema_migrations/202012042153531
-rw-r--r--db/schema_migrations/202012071516511
-rw-r--r--db/schema_migrations/202012071659561
-rw-r--r--db/schema_migrations/202012080814291
-rw-r--r--db/schema_migrations/202012081439111
-rw-r--r--db/schema_migrations/202012081751171
-rw-r--r--db/schema_migrations/202012081814111
-rw-r--r--db/schema_migrations/202012082102091
-rw-r--r--db/schema_migrations/202012091547461
-rw-r--r--db/schema_migrations/202012091631131
-rw-r--r--db/schema_migrations/202012091639581
-rw-r--r--db/schema_migrations/202012091935511
-rw-r--r--db/schema_migrations/202012101012501
-rw-r--r--db/schema_migrations/202012101750441
-rw-r--r--db/schema_migrations/202012110423061
-rw-r--r--db/schema_migrations/202109231926481
-rw-r--r--db/schema_migrations/202109231926491
-rw-r--r--db/schema_migrations/202109302119361
-rw-r--r--db/schema_migrations/202110041201351
-rw-r--r--db/schema_migrations/202110041225401
-rw-r--r--db/schema_migrations/202110051124041
-rw-r--r--db/schema_migrations/202110051126451
-rw-r--r--db/schema_migrations/202110051944251
-rw-r--r--db/schema_migrations/202110081931371
-rw-r--r--db/schema_migrations/202110110042421
-rw-r--r--db/schema_migrations/202110111048431
-rw-r--r--db/schema_migrations/202110120159031
-rw-r--r--db/schema_migrations/202110120512211
-rw-r--r--db/schema_migrations/202110121343161
-rw-r--r--db/schema_migrations/202110121438151
-rw-r--r--db/schema_migrations/202110130142281
-rw-r--r--db/schema_migrations/202110130807141
-rw-r--r--db/schema_migrations/202110130807151
-rw-r--r--db/schema_migrations/202110130807161
-rw-r--r--db/schema_migrations/202110131253411
-rw-r--r--db/schema_migrations/202110131927491
-rw-r--r--db/schema_migrations/202110150211141
-rw-r--r--db/schema_migrations/202110150241351
-rw-r--r--db/schema_migrations/202110181010341
-rw-r--r--db/schema_migrations/202110181015521
-rw-r--r--db/schema_migrations/202110181018521
-rw-r--r--db/schema_migrations/202110181022521
-rw-r--r--db/schema_migrations/202110181233161
-rw-r--r--db/schema_migrations/202110181526541
-rw-r--r--db/schema_migrations/202110181614471
-rw-r--r--db/schema_migrations/202110191536151
-rw-r--r--db/schema_migrations/202110200309481
-rw-r--r--db/schema_migrations/202110200953571
-rw-r--r--db/schema_migrations/202110211259081
-rw-r--r--db/schema_migrations/202110211312171
-rw-r--r--db/schema_migrations/202110211344581
-rw-r--r--db/schema_migrations/202110211404261
-rw-r--r--db/schema_migrations/202110211419301
-rw-r--r--db/schema_migrations/202110221122021
-rw-r--r--db/schema_migrations/202110221130001
-rw-r--r--db/schema_migrations/202110221601541
-rw-r--r--db/schema_migrations/202110251037441
-rw-r--r--db/schema_migrations/202110251037581
-rw-r--r--db/schema_migrations/202110261432381
-rw-r--r--db/schema_migrations/202110270640211
-rw-r--r--db/schema_migrations/202110270641561
-rw-r--r--db/schema_migrations/202110271129011
-rw-r--r--db/schema_migrations/202110272039501
-rw-r--r--db/schema_migrations/202110272040111
-rw-r--r--db/schema_migrations/202110280859261
-rw-r--r--db/schema_migrations/202110281003031
-rw-r--r--db/schema_migrations/202110281008431
-rw-r--r--db/schema_migrations/202110281234121
-rw-r--r--db/schema_migrations/202110281322471
-rw-r--r--db/schema_migrations/202110281554491
-rw-r--r--db/schema_migrations/202110282122591
-rw-r--r--db/schema_migrations/202110291028221
-rw-r--r--db/schema_migrations/202110311524171
-rw-r--r--db/schema_migrations/202110311549191
-rw-r--r--db/schema_migrations/202111011323101
-rw-r--r--db/schema_migrations/202111021031271
-rw-r--r--db/schema_migrations/202111021148021
-rw-r--r--db/schema_migrations/202111030627281
-rw-r--r--db/schema_migrations/202111031620251
-rw-r--r--db/schema_migrations/202111040122091
-rw-r--r--db/schema_migrations/202111040444531
-rw-r--r--db/schema_migrations/202111050101011
-rw-r--r--db/schema_migrations/202111051257561
-rw-r--r--db/schema_migrations/202111051258131
-rw-r--r--db/schema_migrations/202111051351571
-rw-r--r--db/schema_migrations/202111051603161
-rw-r--r--db/schema_migrations/202111051614041
-rw-r--r--db/schema_migrations/202111081545101
-rw-r--r--db/schema_migrations/202111081548411
-rw-r--r--db/schema_migrations/202111082032481
-rw-r--r--db/schema_migrations/202111082114341
-rw-r--r--db/schema_migrations/202111091000501
-rw-r--r--db/schema_migrations/202111091010101
-rw-r--r--db/schema_migrations/202111091124541
-rw-r--r--db/schema_migrations/202111100101011
-rw-r--r--db/schema_migrations/202111101000501
-rw-r--r--db/schema_migrations/202111121133001
-rw-r--r--db/schema_migrations/202111121554161
-rw-r--r--db/schema_migrations/202111151517041
-rw-r--r--db/structure.sql1626
-rw-r--r--doc/.vale/gitlab/Acronyms.yml2
-rw-r--r--doc/.vale/gitlab/British.yml4
-rw-r--r--doc/.vale/gitlab/Substitutions.yml6
-rw-r--r--doc/.vale/gitlab/spelling-exceptions.txt8
-rw-r--r--doc/administration/audit_event_streaming.md70
-rw-r--r--doc/administration/audit_events.md42
-rw-r--r--doc/administration/auth/atlassian.md2
-rw-r--r--doc/administration/auth/authentiq.md2
-rw-r--r--doc/administration/auth/cognito.md4
-rw-r--r--doc/administration/auth/crowd.md6
-rw-r--r--doc/administration/auth/jwt.md2
-rw-r--r--doc/administration/auth/ldap/google_secure_ldap.md2
-rw-r--r--doc/administration/auth/ldap/index.md444
-rw-r--r--doc/administration/auth/ldap/ldap-troubleshooting.md51
-rw-r--r--doc/administration/auth/ldap/ldap_synchronization.md349
-rw-r--r--doc/administration/auth/oidc.md8
-rw-r--r--doc/administration/cicd.md25
-rw-r--r--doc/administration/clusters/kas.md2
-rw-r--r--doc/administration/compliance.md104
-rw-r--r--doc/administration/environment_variables.md2
-rw-r--r--doc/administration/feature_flags.md6
-rw-r--r--doc/administration/geo/disaster_recovery/bring_primary_back.md56
-rw-r--r--doc/administration/geo/disaster_recovery/index.md324
-rw-r--r--doc/administration/geo/disaster_recovery/planned_failover.md2
-rw-r--r--doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md93
-rw-r--r--doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md88
-rw-r--r--doc/administration/geo/index.md33
-rw-r--r--doc/administration/geo/replication/datatypes.md5
-rw-r--r--doc/administration/geo/replication/disable_geo.md2
-rw-r--r--doc/administration/geo/replication/troubleshooting.md42
-rw-r--r--doc/administration/geo/secondary_proxy/img/single_url_add_traffic_policy_endpoints.pngbin0 -> 23811 bytes
-rw-r--r--doc/administration/geo/secondary_proxy/img/single_url_create_policy_records_with_traffic_policy.pngbin0 -> 34039 bytes
-rw-r--r--doc/administration/geo/secondary_proxy/index.md127
-rw-r--r--doc/administration/geo/secondary_proxy/location_aware_external_url.md83
-rw-r--r--doc/administration/geo/setup/database.md32
-rw-r--r--doc/administration/geo/setup/external_database.md6
-rw-r--r--doc/administration/get_started.md6
-rw-r--r--doc/administration/gitaly/praefect.md4
-rw-r--r--doc/administration/gitaly/troubleshooting.md2
-rw-r--r--doc/administration/img/audit_events_v14_5.pngbin0 -> 33285 bytes
-rw-r--r--doc/administration/img/audit_log_v13_6.pngbin43867 -> 0 bytes
-rw-r--r--doc/administration/incoming_email.md44
-rw-r--r--doc/administration/index.md2
-rw-r--r--doc/administration/instance_limits.md111
-rw-r--r--doc/administration/integration/terminal.md9
-rw-r--r--doc/administration/load_balancer.md4
-rw-r--r--doc/administration/logs.md1
-rw-r--r--doc/administration/maintenance_mode/index.md2
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md9
-rw-r--r--doc/administration/monitoring/prometheus/index.md6
-rw-r--r--doc/administration/monitoring/prometheus/puma_exporter.md2
-rw-r--r--doc/administration/nfs.md49
-rw-r--r--doc/administration/object_storage.md15
-rw-r--r--doc/administration/operations/extra_sidekiq_processes.md39
-rw-r--r--doc/administration/operations/fast_ssh_key_lookup.md130
-rw-r--r--doc/administration/operations/moving_repositories.md4
-rw-r--r--doc/administration/operations/puma.md5
-rw-r--r--doc/administration/operations/ssh_certificates.md6
-rw-r--r--doc/administration/package_information/deprecated_os.md1
-rw-r--r--doc/administration/package_information/deprecation_policy.md10
-rw-r--r--doc/administration/pages/index.md39
-rw-r--r--doc/administration/pages/source.md29
-rw-r--r--doc/administration/postgresql/external.md2
-rw-r--r--doc/administration/postgresql/index.md27
-rw-r--r--doc/administration/postgresql/pgbouncer.md4
-rw-r--r--doc/administration/postgresql/replication_and_failover.md2
-rw-r--r--doc/administration/pseudonymizer.md85
-rw-r--r--doc/administration/raketasks/github_import.md2
-rw-r--r--doc/administration/raketasks/ldap.md6
-rw-r--r--doc/administration/raketasks/project_import_export.md3
-rw-r--r--doc/administration/reference_architectures/10k_users.md15
-rw-r--r--doc/administration/reference_architectures/1k_users.md5
-rw-r--r--doc/administration/reference_architectures/25k_users.md15
-rw-r--r--doc/administration/reference_architectures/2k_users.md15
-rw-r--r--doc/administration/reference_architectures/3k_users.md17
-rw-r--r--doc/administration/reference_architectures/50k_users.md15
-rw-r--r--doc/administration/reference_architectures/5k_users.md11
-rw-r--r--doc/administration/repository_storage_paths.md2
-rw-r--r--doc/administration/repository_storage_types.md16
-rw-r--r--doc/administration/restart_gitlab.md34
-rw-r--r--doc/administration/sidekiq.md14
-rw-r--r--doc/administration/troubleshooting/debug.md4
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md16
-rw-r--r--doc/administration/troubleshooting/kubernetes_cheat_sheet.md10
-rw-r--r--doc/administration/troubleshooting/postgresql.md3
-rw-r--r--doc/api/admin_sidekiq_queues.md2
-rw-r--r--doc/api/api_resources.md5
-rw-r--r--doc/api/dependencies.md2
-rw-r--r--doc/api/deploy_keys.md37
-rw-r--r--doc/api/deployments.md6
-rw-r--r--doc/api/dora/metrics.md2
-rw-r--r--doc/api/events.md59
-rw-r--r--doc/api/geo_nodes.md15
-rw-r--r--doc/api/graphql/reference/index.md422
-rw-r--r--doc/api/group_clusters.md8
-rw-r--r--doc/api/group_repository_storage_moves.md2
-rw-r--r--doc/api/group_wikis.md2
-rw-r--r--doc/api/groups.md14
-rw-r--r--doc/api/import.md5
-rw-r--r--doc/api/instance_clusters.md8
-rw-r--r--doc/api/integrations.md150
-rw-r--r--doc/api/invitations.md2
-rw-r--r--doc/api/jobs.md9
-rw-r--r--doc/api/lint.md39
-rw-r--r--doc/api/members.md39
-rw-r--r--doc/api/packages/debian_group_distributions.md37
-rw-r--r--doc/api/packages/debian_project_distributions.md37
-rw-r--r--doc/api/packages/maven.md14
-rw-r--r--doc/api/pipelines.md16
-rw-r--r--doc/api/project_clusters.md8
-rw-r--r--doc/api/projects.md47
-rw-r--r--doc/api/releases/index.md11
-rw-r--r--doc/api/repository_files.md6
-rw-r--r--doc/api/settings.md12
-rw-r--r--doc/api/sidekiq_metrics.md2
-rw-r--r--doc/api/todos.md2
-rw-r--r--doc/api/topics.md190
-rw-r--r--doc/architecture/blueprints/ci_scale/index.md22
-rw-r--r--doc/architecture/blueprints/consolidating_groups_and_projects/index.md23
-rw-r--r--doc/architecture/blueprints/container_registry_metadata_database/index.md20
-rw-r--r--doc/architecture/blueprints/feature_flags_development/index.md2
-rw-r--r--doc/ci/caching/index.md2
-rw-r--r--doc/ci/cloud_deployment/index.md2
-rw-r--r--doc/ci/directed_acyclic_graph/index.md4
-rw-r--r--doc/ci/docker/using_docker_build.md2
-rw-r--r--doc/ci/docker/using_docker_images.md11
-rw-r--r--doc/ci/docker/using_kaniko.md23
-rw-r--r--doc/ci/environments/index.md89
-rw-r--r--doc/ci/environments/protected_environments.md16
-rw-r--r--doc/ci/git_submodules.md5
-rw-r--r--doc/ci/index.md16
-rw-r--r--doc/ci/jobs/ci_job_token.md2
-rw-r--r--doc/ci/jobs/index.md101
-rw-r--r--doc/ci/jobs/job_control.md104
-rw-r--r--doc/ci/large_repositories/index.md16
-rw-r--r--doc/ci/lint.md3
-rw-r--r--doc/ci/pipeline_editor/index.md4
-rw-r--r--doc/ci/pipelines/index.md27
-rw-r--r--doc/ci/pipelines/merge_request_pipelines.md4
-rw-r--r--doc/ci/pipelines/multi_project_pipelines.md21
-rw-r--r--doc/ci/pipelines/parent_child_pipelines.md32
-rw-r--r--doc/ci/pipelines/pipeline_artifacts.md20
-rw-r--r--doc/ci/pipelines/schedules.md10
-rw-r--r--doc/ci/pipelines/settings.md2
-rw-r--r--doc/ci/quick_start/index.md11
-rw-r--r--doc/ci/resource_groups/index.md60
-rw-r--r--doc/ci/review_apps/index.md5
-rw-r--r--doc/ci/runners/build_cloud/linux_build_cloud.md128
-rw-r--r--doc/ci/runners/build_cloud/macos/environment.md44
-rw-r--r--doc/ci/runners/build_cloud/macos_build_cloud.md63
-rw-r--r--doc/ci/runners/build_cloud/windows_build_cloud.md156
-rw-r--r--doc/ci/runners/configure_runners.md5
-rw-r--r--doc/ci/runners/img/shared_runner_ip_address_14_1.pngbin8577 -> 0 bytes
-rw-r--r--doc/ci/runners/img/shared_runner_ip_address_14_5.pngbin0 -> 8742 bytes
-rw-r--r--doc/ci/runners/index.md4
-rw-r--r--doc/ci/runners/runner_cloud/linux_runner_cloud.md186
-rw-r--r--doc/ci/runners/runner_cloud/macos/environment.md43
-rw-r--r--doc/ci/runners/runner_cloud/macos_runner_cloud.md62
-rw-r--r--doc/ci/runners/runner_cloud/windows_runner_cloud.md155
-rw-r--r--doc/ci/services/index.md3
-rw-r--r--doc/ci/services/postgres.md6
-rw-r--r--doc/ci/test_cases/index.md20
-rw-r--r--doc/ci/triggers/index.md3
-rw-r--r--doc/ci/troubleshooting.md46
-rw-r--r--doc/ci/unit_test_reports.md18
-rw-r--r--doc/ci/variables/index.md6
-rw-r--r--doc/ci/variables/where_variables_can_be_used.md17
-rw-r--r--doc/ci/yaml/gitlab_ci_yaml.md2
-rw-r--r--doc/ci/yaml/includes.md119
-rw-r--r--doc/ci/yaml/index.md3110
-rw-r--r--doc/ci/yaml/script.md3
-rw-r--r--doc/ci/yaml/workflow.md150
-rw-r--r--doc/ci/yaml/yaml_optimization.md454
-rw-r--r--doc/development/adding_database_indexes.md13
-rw-r--r--doc/development/api_styleguide.md2
-rw-r--r--doc/development/application_slis/index.md84
-rw-r--r--doc/development/application_slis/rails_request_apdex.md200
-rw-r--r--doc/development/architecture.md5
-rw-r--r--doc/development/avoiding_downtime_in_migrations.md176
-rw-r--r--doc/development/chaos_endpoints.md2
-rw-r--r--doc/development/cicd/templates.md4
-rw-r--r--doc/development/code_review.md2
-rw-r--r--doc/development/contributing/issue_workflow.md18
-rw-r--r--doc/development/contributing/merge_request_workflow.md19
-rw-r--r--doc/development/dangerbot.md17
-rw-r--r--doc/development/database/loose_foreign_keys.md182
-rw-r--r--doc/development/database/multiple_databases.md66
-rw-r--r--doc/development/database_review.md4
-rw-r--r--doc/development/documentation/feature_flags.md15
-rw-r--r--doc/development/documentation/index.md43
-rw-r--r--doc/development/documentation/restful_api_styleguide.md31
-rw-r--r--doc/development/documentation/site_architecture/deployment_process.md187
-rw-r--r--doc/development/documentation/site_architecture/global_nav.md11
-rw-r--r--doc/development/documentation/site_architecture/index.md33
-rw-r--r--doc/development/documentation/structure.md14
-rw-r--r--doc/development/documentation/styleguide/index.md67
-rw-r--r--doc/development/documentation/styleguide/word_list.md25
-rw-r--r--doc/development/documentation/workflow.md2
-rw-r--r--doc/development/elasticsearch.md16
-rw-r--r--doc/development/experiment_guide/gitlab_experiment.md52
-rw-r--r--doc/development/fe_guide/accessibility.md11
-rw-r--r--doc/development/fe_guide/development_process.md2
-rw-r--r--doc/development/fe_guide/graphql.md21
-rw-r--r--doc/development/fe_guide/storybook.md5
-rw-r--r--doc/development/fe_guide/style/scss.md34
-rw-r--r--doc/development/fe_guide/vue.md7
-rw-r--r--doc/development/fe_guide/vue3_migration.md6
-rw-r--r--doc/development/feature_categorization/index.md4
-rw-r--r--doc/development/feature_flags/controls.md6
-rw-r--r--doc/development/feature_flags/index.md2
-rw-r--r--doc/development/gemfile.md6
-rw-r--r--doc/development/gitaly.md2
-rw-r--r--doc/development/go_guide/go_upgrade.md6
-rw-r--r--doc/development/go_guide/index.md75
-rw-r--r--doc/development/i18n/translation.md14
-rw-r--r--doc/development/index.md3
-rw-r--r--doc/development/internal_api.md830
-rw-r--r--doc/development/internal_api/index.md831
-rw-r--r--doc/development/internal_api/internal_api_allowed.md109
-rw-r--r--doc/development/iterating_tables_in_batches.md6
-rw-r--r--doc/development/jh_features_review.md8
-rw-r--r--doc/development/maintenance_mode.md2
-rw-r--r--doc/development/migration_style_guide.md13
-rw-r--r--doc/development/multi_version_compatibility.md10
-rw-r--r--doc/development/namespaces_storage_statistics.md15
-rw-r--r--doc/development/pipelines.md120
-rw-r--r--doc/development/policies.md2
-rw-r--r--doc/development/reactive_caching.md12
-rw-r--r--doc/development/redis.md6
-rw-r--r--doc/development/reusing_abstractions.md12
-rw-r--r--doc/development/ruby3_gotchas.md140
-rw-r--r--doc/development/ruby_upgrade.md2
-rw-r--r--doc/development/secure_coding_guidelines.md175
-rw-r--r--doc/development/service_ping/implement.md49
-rw-r--r--doc/development/service_ping/index.md99
-rw-r--r--doc/development/service_ping/metrics_dictionary.md16
-rw-r--r--doc/development/sidekiq_style_guide.md38
-rw-r--r--doc/development/snowplow/implementation.md79
-rw-r--r--doc/development/snowplow/index.md13
-rw-r--r--doc/development/testing_guide/best_practices.md17
-rw-r--r--doc/development/testing_guide/end_to_end/beginners_guide.md2
-rw-r--r--doc/development/testing_guide/end_to_end/feature_flags.md22
-rw-r--r--doc/development/testing_guide/end_to_end/index.md2
-rw-r--r--doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md128
-rw-r--r--doc/development/testing_guide/end_to_end/style_guide.md10
-rw-r--r--doc/development/testing_guide/frontend_testing.md3
-rw-r--r--doc/development/testing_guide/review_apps.md24
-rw-r--r--doc/development/testing_guide/testing_migrations_guide.md173
-rw-r--r--doc/development/understanding_explain_plans.md8
-rw-r--r--doc/development/uploads.md28
-rw-r--r--doc/development/verifying_database_capabilities.md4
-rw-r--r--doc/development/workspaces/index.md120
-rw-r--r--doc/gitlab-basics/feature_branch_workflow.md4
-rw-r--r--doc/index.md6
-rw-r--r--doc/install/aws/eks_clusters_aws.md3
-rw-r--r--doc/install/aws/gitlab_hybrid_on_aws.md112
-rw-r--r--doc/install/aws/gitlab_sre_for_aws.md9
-rw-r--r--doc/install/aws/index.md32
-rw-r--r--doc/install/aws/manual_install_aws.md17
-rw-r--r--doc/install/docker.md2
-rw-r--r--doc/install/google_cloud_platform/index.md13
-rw-r--r--doc/install/installation.md191
-rw-r--r--doc/install/openshift_and_gitlab/index.md46
-rw-r--r--doc/install/relative_url.md16
-rw-r--r--doc/install/requirements.md10
-rw-r--r--doc/integration/akismet.md3
-rw-r--r--doc/integration/auth0.md2
-rw-r--r--doc/integration/azure.md6
-rw-r--r--doc/integration/cas.md2
-rw-r--r--doc/integration/ding_talk.md84
-rw-r--r--doc/integration/elasticsearch.md5
-rw-r--r--doc/integration/facebook.md2
-rw-r--r--doc/integration/github.md2
-rw-r--r--doc/integration/gitlab.md2
-rw-r--r--doc/integration/gmail_action_buttons_for_gitlab.md2
-rw-r--r--doc/integration/google.md2
-rw-r--r--doc/integration/img/ding_talk_create_application.pngbin0 -> 78323 bytes
-rw-r--r--doc/integration/img/ding_talk_credentials.pngbin0 -> 86330 bytes
-rw-r--r--doc/integration/img/ding_talk_menu.pngbin0 -> 66465 bytes
-rw-r--r--doc/integration/img/ding_talk_your_application.pngbin0 -> 63323 bytes
-rw-r--r--doc/integration/img/enabled-oauth-sign-in-sources_v13_10.pngbin47979 -> 0 bytes
-rw-r--r--doc/integration/jira/connect-app.md93
-rw-r--r--doc/integration/jira/development_panel.md7
-rw-r--r--doc/integration/jira/dvcs.md95
-rw-r--r--doc/integration/jira/index.md36
-rw-r--r--doc/integration/jira/jira_cloud_configuration.md15
-rw-r--r--doc/integration/jira/jira_server_configuration.md30
-rw-r--r--doc/integration/kerberos.md4
-rw-r--r--doc/integration/mattermost/index.md4
-rw-r--r--doc/integration/oauth2_generic.md37
-rw-r--r--doc/integration/omniauth.md323
-rw-r--r--doc/integration/salesforce.md8
-rw-r--r--doc/integration/saml.md8
-rw-r--r--doc/integration/security_partners/index.md2
-rw-r--r--doc/integration/twitter.md2
-rw-r--r--doc/operations/error_tracking.md5
-rw-r--r--doc/operations/feature_flags.md78
-rw-r--r--doc/operations/incident_management/incidents.md17
-rw-r--r--doc/operations/incident_management/integrations.md21
-rw-r--r--doc/push_rules/push_rules.md2
-rw-r--r--doc/raketasks/backup_restore.md86
-rw-r--r--doc/raketasks/import.md4
-rw-r--r--doc/raketasks/spdx.md2
-rw-r--r--doc/security/rack_attack.md196
-rw-r--r--doc/security/rate_limits.md96
-rw-r--r--doc/security/token_overview.md5
-rw-r--r--doc/subscriptions/bronze_starter.md18
-rw-r--r--doc/subscriptions/gitlab_com/index.md4
-rw-r--r--doc/subscriptions/self_managed/index.md11
-rw-r--r--doc/system_hooks/system_hooks.md4
-rw-r--r--doc/topics/autodevops/customize.md29
-rw-r--r--doc/topics/autodevops/multiple_clusters_auto_devops.md4
-rw-r--r--doc/topics/autodevops/quick_start_guide.md2
-rw-r--r--doc/topics/autodevops/stages.md2
-rw-r--r--doc/topics/git/getting_started.md6
-rw-r--r--doc/topics/git/git_rebase.md85
-rw-r--r--doc/topics/git/lfs/index.md1
-rw-r--r--doc/topics/index.md25
-rw-r--r--doc/topics/plan_and_track.md1
-rw-r--r--doc/topics/release_your_application.md5
-rw-r--r--doc/topics/use_gitlab.md2
-rw-r--r--doc/update/deprecations.md176
-rw-r--r--doc/update/index.md160
-rw-r--r--doc/update/package/index.md37
-rw-r--r--doc/update/patch_versions.md9
-rw-r--r--doc/update/upgrading_from_source.md35
-rw-r--r--doc/update/zero_downtime.md52
-rw-r--r--doc/user/admin_area/analytics/dev_ops_report.md14
-rw-r--r--doc/user/admin_area/analytics/index.md2
-rw-r--r--doc/user/admin_area/img/index_runners_search_or_filter_v14_1.pngbin13248 -> 0 bytes
-rw-r--r--doc/user/admin_area/img/index_runners_search_or_filter_v14_5.pngbin0 -> 13881 bytes
-rw-r--r--doc/user/admin_area/index.md34
-rw-r--r--doc/user/admin_area/merge_requests_approvals.md39
-rw-r--r--doc/user/admin_area/moderate_users.md2
-rw-r--r--doc/user/admin_area/monitoring/background_migrations.md2
-rw-r--r--doc/user/admin_area/monitoring/health_check.md5
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md13
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md2
-rw-r--r--doc/user/admin_area/settings/deprecated_api_rate_limits.md2
-rw-r--r--doc/user/admin_area/settings/files_api_rate_limits.md2
-rw-r--r--doc/user/admin_area/settings/git_lfs_rate_limits.md2
-rw-r--r--doc/user/admin_area/settings/img/suggest_pipeline_banner.pngbin14544 -> 0 bytes
-rw-r--r--doc/user/admin_area/settings/img/suggest_pipeline_banner_v14_5.pngbin0 -> 11137 bytes
-rw-r--r--doc/user/admin_area/settings/index.md288
-rw-r--r--doc/user/admin_area/settings/instance_template_repository.md2
-rw-r--r--doc/user/admin_area/settings/protected_paths.md36
-rw-r--r--doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md4
-rw-r--r--doc/user/admin_area/settings/sign_up_restrictions.md2
-rw-r--r--doc/user/admin_area/settings/terms.md6
-rw-r--r--doc/user/admin_area/settings/user_and_ip_rate_limits.md6
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md2
-rw-r--r--doc/user/analytics/ci_cd_analytics.md6
-rw-r--r--doc/user/analytics/code_review_analytics.md2
-rw-r--r--doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.pngbin0 -> 135480 bytes
-rw-r--r--doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.pngbin0 -> 96144 bytes
-rw-r--r--doc/user/analytics/img/productivity_analytics_trendline_v14_4.pngbin0 -> 47250 bytes
-rw-r--r--doc/user/analytics/index.md132
-rw-r--r--doc/user/analytics/merge_request_analytics.md2
-rw-r--r--doc/user/analytics/productivity_analytics.md88
-rw-r--r--doc/user/analytics/repository_analytics.md2
-rw-r--r--doc/user/application_security/api_fuzzing/index.md56
-rw-r--r--doc/user/application_security/cluster_image_scanning/index.md52
-rw-r--r--doc/user/application_security/configuration/index.md24
-rw-r--r--doc/user/application_security/container_scanning/index.md4
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md4
-rw-r--r--doc/user/application_security/dast/browser_based.md2
-rw-r--r--doc/user/application_security/dast/checks/1004.1.md41
-rw-r--r--doc/user/application_security/dast/checks/16.1.md33
-rw-r--r--doc/user/application_security/dast/checks/16.2.md44
-rw-r--r--doc/user/application_security/dast/checks/16.3.md35
-rw-r--r--doc/user/application_security/dast/checks/16.4.md28
-rw-r--r--doc/user/application_security/dast/checks/16.5.md30
-rw-r--r--doc/user/application_security/dast/checks/614.1.md40
-rw-r--r--doc/user/application_security/dast/checks/693.1.md36
-rw-r--r--doc/user/application_security/dast/checks/index.md20
-rw-r--r--doc/user/application_security/dast/index.md22
-rw-r--r--doc/user/application_security/dast/run_dast_offline.md2
-rw-r--r--doc/user/application_security/dast_api/index.md58
-rw-r--r--doc/user/application_security/dependency_list/index.md4
-rw-r--r--doc/user/application_security/dependency_scanning/index.md142
-rw-r--r--doc/user/application_security/iac_scanning/index.md98
-rw-r--r--doc/user/application_security/img/vulnerability-check_v14_2.pngbin23147 -> 0 bytes
-rw-r--r--doc/user/application_security/index.md321
-rw-r--r--doc/user/application_security/offline_deployments/index.md2
-rw-r--r--doc/user/application_security/policies/index.md16
-rw-r--r--doc/user/application_security/sast/analyzers.md4
-rw-r--r--doc/user/application_security/sast/index.md25
-rw-r--r--doc/user/application_security/secret_detection/index.md47
-rw-r--r--doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_2.pngbin46428 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_4.pngbin0 -> 126412 bytes
-rw-r--r--doc/user/application_security/security_dashboard/index.md14
-rw-r--r--doc/user/application_security/threat_monitoring/index.md6
-rw-r--r--doc/user/application_security/vulnerabilities/index.md5
-rw-r--r--doc/user/application_security/vulnerability_report/img/group_vulnerability_report_v14_2.pngbin65346 -> 0 bytes
-rw-r--r--doc/user/application_security/vulnerability_report/img/project_level_vulnerability_report_v14_5.pngbin0 -> 97387 bytes
-rw-r--r--doc/user/application_security/vulnerability_report/index.md19
-rw-r--r--doc/user/clusters/agent/ci_cd_tunnel.md26
-rw-r--r--doc/user/clusters/agent/index.md445
-rw-r--r--doc/user/clusters/agent/install/index.md369
-rw-r--r--doc/user/clusters/agent/repository.md240
-rw-r--r--doc/user/clusters/applications.md2
-rw-r--r--doc/user/clusters/cost_management.md8
-rw-r--r--doc/user/clusters/crossplane.md7
-rw-r--r--doc/user/clusters/environments.md6
-rw-r--r--doc/user/clusters/img/kubernetes-agent-ui-list_v13_8.pngbin17270 -> 0 bytes
-rw-r--r--doc/user/clusters/img/kubernetes-agent-ui-list_v14_5.pngbin0 -> 31309 bytes
-rw-r--r--doc/user/clusters/integrations.md21
-rw-r--r--doc/user/clusters/management_project.md13
-rw-r--r--doc/user/clusters/management_project_template.md87
-rw-r--r--doc/user/compliance/compliance_report/index.md12
-rw-r--r--doc/user/compliance/license_compliance/index.md29
-rw-r--r--doc/user/discussions/index.md47
-rw-r--r--doc/user/gitlab_com/index.md9
-rw-r--r--doc/user/group/clusters/index.md13
-rw-r--r--doc/user/group/contribution_analytics/index.md2
-rw-r--r--doc/user/group/custom_project_templates.md2
-rw-r--r--doc/user/group/devops_adoption/index.md2
-rw-r--r--doc/user/group/epics/index.md6
-rw-r--r--doc/user/group/epics/manage_epics.md134
-rw-r--r--doc/user/group/import/index.md55
-rw-r--r--doc/user/group/index.md94
-rw-r--r--doc/user/group/insights/index.md2
-rw-r--r--doc/user/group/issues_analytics/index.md2
-rw-r--r--doc/user/group/iterations/index.md6
-rw-r--r--doc/user/group/roadmap/index.md47
-rw-r--r--doc/user/group/saml_sso/index.md32
-rw-r--r--doc/user/group/saml_sso/scim_setup.md53
-rw-r--r--doc/user/group/settings/import_export.md11
-rw-r--r--doc/user/group/subgroups/index.md2
-rw-r--r--doc/user/group/value_stream_analytics/index.md38
-rw-r--r--doc/user/index.md50
-rw-r--r--doc/user/infrastructure/clusters/connect/index.md72
-rw-r--r--doc/user/infrastructure/clusters/connect/new_gke_cluster.md11
-rw-r--r--doc/user/infrastructure/clusters/index.md123
-rw-r--r--doc/user/infrastructure/clusters/manage/clusters_health.md4
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/apparmor.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/cilium.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/falco.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/fluentd.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md2
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/vault.md6
-rw-r--r--doc/user/infrastructure/iac/mr_integration.md5
-rw-r--r--doc/user/infrastructure/iac/terraform_state.md2
-rw-r--r--doc/user/infrastructure/index.md11
-rw-r--r--doc/user/instance/clusters/index.md9
-rw-r--r--doc/user/markdown.md125
-rw-r--r--doc/user/packages/composer_repository/index.md8
-rw-r--r--doc/user/packages/conan_repository/index.md7
-rw-r--r--doc/user/packages/container_registry/index.md6
-rw-r--r--doc/user/packages/debian_repository/index.md19
-rw-r--r--doc/user/packages/dependency_proxy/index.md44
-rw-r--r--doc/user/packages/generic_packages/index.md38
-rw-r--r--doc/user/packages/go_proxy/index.md4
-rw-r--r--doc/user/packages/index.md50
-rw-r--r--doc/user/packages/infrastructure_registry/index.md2
-rw-r--r--doc/user/packages/maven_repository/index.md18
-rw-r--r--doc/user/packages/npm_registry/index.md70
-rw-r--r--doc/user/packages/nuget_repository/index.md4
-rw-r--r--doc/user/packages/package_registry/index.md66
-rw-r--r--doc/user/packages/pypi_repository/index.md4
-rw-r--r--doc/user/packages/rubygems_registry/index.md2
-rw-r--r--doc/user/packages/workflows/working_with_monorepos.md2
-rw-r--r--doc/user/permissions.md54
-rw-r--r--doc/user/profile/account/two_factor_authentication.md5
-rw-r--r--doc/user/profile/index.md22
-rw-r--r--doc/user/profile/notifications.md17
-rw-r--r--doc/user/profile/personal_access_tokens.md4
-rw-r--r--doc/user/project/badges.md17
-rw-r--r--doc/user/project/canary_deployments.md6
-rw-r--r--doc/user/project/clusters/add_eks_clusters.md15
-rw-r--r--doc/user/project/clusters/add_existing_cluster.md15
-rw-r--r--doc/user/project/clusters/add_gke_clusters.md15
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md5
-rw-r--r--doc/user/project/clusters/cluster_access.md10
-rw-r--r--doc/user/project/clusters/deploy_to_cluster.md15
-rw-r--r--doc/user/project/clusters/gitlab_managed_clusters.md8
-rw-r--r--doc/user/project/clusters/index.md15
-rw-r--r--doc/user/project/clusters/kubernetes_pod_logs.md6
-rw-r--r--doc/user/project/clusters/multiple_kubernetes_clusters.md8
-rw-r--r--doc/user/project/clusters/protect/container_host_security/index.md6
-rw-r--r--doc/user/project/clusters/protect/container_network_security/index.md6
-rw-r--r--doc/user/project/clusters/serverless/aws.md4
-rw-r--r--doc/user/project/code_owners.md4
-rw-r--r--doc/user/project/deploy_boards.md8
-rw-r--r--doc/user/project/deploy_keys/index.md14
-rw-r--r--doc/user/project/deploy_tokens/index.md21
-rw-r--r--doc/user/project/file_lock.md21
-rw-r--r--doc/user/project/img/file_lock.pngbin20461 -> 0 bytes
-rw-r--r--doc/user/project/import/bitbucket.md20
-rw-r--r--doc/user/project/import/bitbucket_server.md32
-rw-r--r--doc/user/project/import/fogbugz.md13
-rw-r--r--doc/user/project/import/gitea.md2
-rw-r--r--doc/user/project/import/github.md8
-rw-r--r--doc/user/project/import/gitlab_com.md5
-rw-r--r--doc/user/project/import/img/bitbucket_server_import_credentials.pngbin13781 -> 0 bytes
-rw-r--r--doc/user/project/import/img/bitbucket_server_import_select_project_v12_3.pngbin15839 -> 0 bytes
-rw-r--r--doc/user/project/import/img/fogbugz_import_login.pngbin13452 -> 0 bytes
-rw-r--r--doc/user/project/import/img/fogbugz_import_select_fogbogz.pngbin12283 -> 0 bytes
-rw-r--r--doc/user/project/import/img/import_projects_from_new_project_page.pngbin30489 -> 0 bytes
-rw-r--r--doc/user/project/import/index.md15
-rw-r--r--doc/user/project/import/perforce.md4
-rw-r--r--doc/user/project/import/repo_by_url.md5
-rw-r--r--doc/user/project/index.md2
-rw-r--r--doc/user/project/integrations/custom_issue_tracker.md33
-rw-r--r--doc/user/project/integrations/github.md8
-rw-r--r--doc/user/project/integrations/img/custom_issue_tracker_v14_5.pngbin0 -> 6636 bytes
-rw-r--r--doc/user/project/integrations/img/zentao_product_id.pngbin0 -> 40486 bytes
-rw-r--r--doc/user/project/integrations/mattermost.md2
-rw-r--r--doc/user/project/integrations/microsoft_teams.md23
-rw-r--r--doc/user/project/integrations/overview.md1
-rw-r--r--doc/user/project/integrations/slack.md2
-rw-r--r--doc/user/project/integrations/unify_circuit.md2
-rw-r--r--doc/user/project/integrations/webhook_events.md254
-rw-r--r--doc/user/project/integrations/webhooks.md10
-rw-r--r--doc/user/project/integrations/zentao.md42
-rw-r--r--doc/user/project/issue_board.md15
-rw-r--r--doc/user/project/issues/associate_zoom_meeting.md4
-rw-r--r--doc/user/project/issues/confidential_issues.md6
-rw-r--r--doc/user/project/issues/due_dates.md2
-rw-r--r--doc/user/project/issues/index.md1
-rw-r--r--doc/user/project/issues/managing_issues.md14
-rw-r--r--doc/user/project/issues/sorting_issue_lists.md107
-rw-r--r--doc/user/project/members/index.md4
-rw-r--r--doc/user/project/merge_requests/accessibility_testing.md3
-rw-r--r--doc/user/project/merge_requests/approvals/index.md2
-rw-r--r--doc/user/project/merge_requests/approvals/rules.md2
-rw-r--r--doc/user/project/merge_requests/approvals/settings.md38
-rw-r--r--doc/user/project/merge_requests/authorization_for_merge_requests.md2
-rw-r--r--doc/user/project/merge_requests/code_quality.md3
-rw-r--r--doc/user/project/merge_requests/commit_templates.md51
-rw-r--r--doc/user/project/merge_requests/conflicts.md177
-rw-r--r--doc/user/project/merge_requests/fast_forward_merge.md2
-rw-r--r--doc/user/project/merge_requests/getting_started.md5
-rw-r--r--doc/user/project/merge_requests/img/merge_commit_message_template_v14_5.pngbin0 -> 19690 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_tab_position_v13_11.pngbin9269 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/project_merge_requests_list_view_v13_5.pngbin87738 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/index.md83
-rw-r--r--doc/user/project/merge_requests/merge_when_pipeline_succeeds.md2
-rw-r--r--doc/user/project/merge_requests/resolve_conflicts.md86
-rw-r--r--doc/user/project/merge_requests/reviews/index.md6
-rw-r--r--doc/user/project/merge_requests/reviews/suggestions.md50
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/index.md11
-rw-r--r--doc/user/project/pages/getting_started/pages_ci_cd_template.md35
-rw-r--r--doc/user/project/pages/img/choose_ci_template_v13_1.pngbin10343 -> 0 bytes
-rw-r--r--doc/user/project/pages/img/setup_ci_v13_1.pngbin15480 -> 0 bytes
-rw-r--r--doc/user/project/pages/introduction.md43
-rw-r--r--doc/user/project/push_options.md14
-rw-r--r--doc/user/project/quick_actions.md1
-rw-r--r--doc/user/project/releases/index.md182
-rw-r--r--doc/user/project/releases/release_cli.md76
-rw-r--r--doc/user/project/repository/branches/default.md2
-rw-r--r--doc/user/project/repository/gpg_signed_commits/index.md5
-rw-r--r--doc/user/project/repository/index.md23
-rw-r--r--doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook_diff_v14_5.pngbin0 -> 249380 bytes
-rw-r--r--doc/user/project/repository/jupyter_notebooks/index.md34
-rw-r--r--doc/user/project/repository/mirror/bidirectional.md2
-rw-r--r--doc/user/project/repository/mirror/img/repository_mirroring_copy_ssh_public_key_button.pngbin11225 -> 0 bytes
-rw-r--r--doc/user/project/repository/mirror/index.md275
-rw-r--r--doc/user/project/repository/mirror/pull.md6
-rw-r--r--doc/user/project/repository/vscode.md47
-rw-r--r--doc/user/project/repository/x509_signed_commits/index.md2
-rw-r--r--doc/user/project/requirements/index.md24
-rw-r--r--doc/user/project/service_desk.md41
-rw-r--r--doc/user/project/settings/img/general_settings_v13_11.pngbin31271 -> 0 bytes
-rw-r--r--doc/user/project/settings/img/import_export_download_export.pngbin14867 -> 23285 bytes
-rw-r--r--doc/user/project/settings/img/import_export_export_button.pngbin14530 -> 31790 bytes
-rw-r--r--doc/user/project/settings/import_export.md88
-rw-r--r--doc/user/project/settings/index.md31
-rw-r--r--doc/user/project/settings/project_access_tokens.md8
-rw-r--r--doc/user/project/web_ide/index.md37
-rw-r--r--doc/user/project/wiki/group.md71
-rw-r--r--doc/user/project/wiki/index.md117
-rw-r--r--doc/user/project/working_with_projects.md23
-rw-r--r--doc/user/report_abuse.md1
-rw-r--r--doc/user/search/advanced_search.md4
-rw-r--r--doc/user/search/img/basic_search_v14_4.png (renamed from doc/user/search/img/basic_search.png)bin8344 -> 8344 bytes
-rw-r--r--doc/user/search/img/issues_mrs_shortcut.pngbin4523 -> 0 bytes
-rw-r--r--doc/user/search/img/issues_mrs_shortcut_v14_4.pngbin0 -> 6741 bytes
-rw-r--r--doc/user/search/index.md11
-rw-r--r--doc/user/shortcuts.md3
-rw-r--r--doc/user/snippets.md25
-rw-r--r--doc/user/tasks.md34
-rw-r--r--doc/user/usage_quotas.md5
-rw-r--r--doc/user/workspace/index.md4
-rw-r--r--fixtures/emojis/aliases.json1
-rw-r--r--fixtures/emojis/digests.json3609
-rw-r--r--fixtures/emojis/emoji-unicode-version-map.json2377
-rw-r--r--generator_templates/usage_metric_definition/metric_definition.yml2
-rw-r--r--jest.config.base.js1
-rw-r--r--jest.config.integration.js7
-rw-r--r--jest.config.js15
-rw-r--r--lefthook.yml5
-rw-r--r--lib/after_commit_queue.rb2
-rw-r--r--lib/api/api.rb4
-rw-r--r--lib/api/boards.rb2
-rw-r--r--lib/api/branches.rb4
-rw-r--r--lib/api/ci/jobs.rb35
-rw-r--r--lib/api/commits.rb10
-rw-r--r--lib/api/concerns/packages/debian_distribution_endpoints.rb55
-rw-r--r--lib/api/concerns/packages/debian_package_endpoints.rb10
-rw-r--r--lib/api/concerns/packages/npm_endpoints.rb4
-rw-r--r--lib/api/debian_group_packages.rb2
-rw-r--r--lib/api/deploy_keys.rb5
-rw-r--r--lib/api/discussions.rb2
-rw-r--r--lib/api/entities/alert_management/alert.rb12
-rw-r--r--lib/api/entities/ci/job_request/service.rb1
-rw-r--r--lib/api/entities/ci/lint/result.rb1
-rw-r--r--lib/api/entities/ci/runner.rb4
-rw-r--r--lib/api/entities/ci/runner_details.rb8
-rw-r--r--lib/api/entities/deploy_key.rb3
-rw-r--r--lib/api/entities/group.rb3
-rw-r--r--lib/api/entities/project.rb1
-rw-r--r--lib/api/entities/project_statistics.rb4
-rw-r--r--lib/api/entities/projects/topic.rb17
-rw-r--r--lib/api/entities/todo.rb2
-rw-r--r--lib/api/error_tracking/collector.rb24
-rw-r--r--lib/api/features.rb9
-rw-r--r--lib/api/files.rb10
-rw-r--r--lib/api/generic_packages.rb9
-rw-r--r--lib/api/github/entities.rb4
-rw-r--r--lib/api/group_boards.rb2
-rw-r--r--lib/api/group_debian_distributions.rb8
-rw-r--r--lib/api/group_labels.rb2
-rw-r--r--lib/api/group_milestones.rb2
-rw-r--r--lib/api/helpers.rb15
-rw-r--r--lib/api/helpers/award_emoji.rb2
-rw-r--r--lib/api/helpers/discussions_helpers.rb2
-rw-r--r--lib/api/helpers/file_upload_helpers.rb2
-rw-r--r--lib/api/helpers/integrations_helpers.rb41
-rw-r--r--lib/api/helpers/notes_helpers.rb2
-rw-r--r--lib/api/helpers/project_snapshots_helpers.rb2
-rw-r--r--lib/api/helpers/projects_helpers.rb13
-rw-r--r--lib/api/helpers/resource_label_events_helpers.rb2
-rw-r--r--lib/api/integrations.rb2
-rw-r--r--lib/api/internal/base.rb2
-rw-r--r--lib/api/internal/lfs.rb2
-rw-r--r--lib/api/invitations.rb2
-rw-r--r--lib/api/issue_links.rb2
-rw-r--r--lib/api/issues.rb2
-rw-r--r--lib/api/labels.rb2
-rw-r--r--lib/api/lint.rb9
-rw-r--r--lib/api/members.rb2
-rw-r--r--lib/api/merge_request_approvals.rb6
-rw-r--r--lib/api/namespaces.rb4
-rw-r--r--lib/api/package_files.rb5
-rw-r--r--lib/api/project_debian_distributions.rb8
-rw-r--r--lib/api/project_milestones.rb2
-rw-r--r--lib/api/projects.rb12
-rw-r--r--lib/api/protected_branches.rb2
-rw-r--r--lib/api/releases.rb4
-rw-r--r--lib/api/repositories.rb41
-rw-r--r--lib/api/resource_milestone_events.rb2
-rw-r--r--lib/api/resource_state_events.rb2
-rw-r--r--lib/api/snippets.rb2
-rw-r--r--lib/api/subscriptions.rb6
-rw-r--r--lib/api/tags.rb16
-rw-r--r--lib/api/terraform/modules/v1/packages.rb3
-rw-r--r--lib/api/todos.rb2
-rw-r--r--lib/api/topics.rb79
-rw-r--r--lib/api/users.rb1
-rw-r--r--lib/api/v3/github.rb32
-rw-r--r--lib/api/wikis.rb2
-rw-r--r--lib/backup/manager.rb15
-rw-r--r--lib/banzai/filter/emoji_filter.rb19
-rw-r--r--lib/banzai/filter/footnote_filter.rb56
-rw-r--r--lib/banzai/filter/markdown_engines/common_mark.rb52
-rw-r--r--lib/banzai/filter/markdown_post_escape_filter.rb18
-rw-r--r--lib/banzai/filter/plantuml_filter.rb18
-rw-r--r--lib/banzai/filter/sanitization_filter.rb9
-rw-r--r--lib/banzai/filter/syntax_highlight_filter.rb43
-rw-r--r--lib/banzai/renderer.rb42
-rw-r--r--lib/banzai/renderer/common_mark/html.rb2
-rw-r--r--lib/bulk_imports/common/extractors/ndjson_extractor.rb24
-rw-r--r--lib/bulk_imports/common/pipelines/milestones_pipeline.rb15
-rw-r--r--lib/bulk_imports/common/pipelines/uploads_pipeline.rb52
-rw-r--r--lib/bulk_imports/common/pipelines/wiki_pipeline.rb42
-rw-r--r--lib/bulk_imports/groups/graphql/get_milestones_query.rb56
-rw-r--r--lib/bulk_imports/groups/loaders/group_loader.rb27
-rw-r--r--lib/bulk_imports/groups/pipelines/milestones_pipeline.rb15
-rw-r--r--lib/bulk_imports/groups/stage.rb2
-rw-r--r--lib/bulk_imports/ndjson_pipeline.rb9
-rw-r--r--lib/bulk_imports/projects/pipelines/external_pull_requests_pipeline.rb15
-rw-r--r--lib/bulk_imports/projects/pipelines/merge_requests_pipeline.rb19
-rw-r--r--lib/bulk_imports/projects/pipelines/protected_branches_pipeline.rb15
-rw-r--r--lib/bulk_imports/projects/pipelines/repository_pipeline.rb10
-rw-r--r--lib/bulk_imports/projects/stage.rb26
-rw-r--r--lib/container_registry/client.rb4
-rw-r--r--lib/declarative_enum.rb19
-rw-r--r--lib/error_tracking/collector/payload_validator.rb13
-rw-r--r--lib/error_tracking/collector/sentry_request_parser.rb10
-rw-r--r--lib/feature.rb12
-rw-r--r--lib/feature/gitaly.rb2
-rw-r--r--lib/generators/gitlab/usage_metric_definition_generator.rb27
-rw-r--r--lib/generators/post_deployment_migration/post_deployment_migration_generator.rb14
-rw-r--r--lib/gitlab/access.rb30
-rw-r--r--lib/gitlab/action_cable/config.rb4
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb114
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb54
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/label_filter.rb31
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/median.rb36
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb116
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/stage_query_helpers.rb41
-rw-r--r--lib/gitlab/analytics/cycle_analytics/data_collector.rb26
-rw-r--r--lib/gitlab/analytics/cycle_analytics/records_fetcher.rb18
-rw-r--r--lib/gitlab/analytics/cycle_analytics/request_params.rb3
-rw-r--r--lib/gitlab/application_rate_limiter.rb34
-rw-r--r--lib/gitlab/asciidoc/syntax_highlighter/html_pipeline_adapter.rb6
-rw-r--r--lib/gitlab/auth/o_auth/provider.rb1
-rw-r--r--lib/gitlab/background_migration.rb102
-rw-r--r--lib/gitlab/background_migration/add_primary_email_to_emails_if_user_confirmed.rb58
-rw-r--r--lib/gitlab/background_migration/backfill_design_internal_ids.rb130
-rw-r--r--lib/gitlab/background_migration/backfill_project_repositories.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_user_namespace.rb38
-rw-r--r--lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb25
-rw-r--r--lib/gitlab/background_migration/fix_merge_request_diff_commit_users.rb156
-rw-r--r--lib/gitlab/background_migration/fix_orphan_promoted_issues.rb13
-rw-r--r--lib/gitlab/background_migration/fix_ruby_object_in_audit_events.rb13
-rw-r--r--lib/gitlab/background_migration/job_coordinator.rb134
-rw-r--r--lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys.rb2
-rw-r--r--lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data.rb146
-rw-r--r--lib/gitlab/background_migration/migrate_requirements_to_work_items.rb13
-rw-r--r--lib/gitlab/background_migration/migrate_users_bio_to_user_details.rb32
-rw-r--r--lib/gitlab/background_migration/populate_issue_email_participants.rb2
-rw-r--r--lib/gitlab/background_migration/populate_user_highest_roles_table.rb58
-rw-r--r--lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb151
-rw-r--r--lib/gitlab/background_migration/project_namespaces/models/namespace.rb17
-rw-r--r--lib/gitlab/background_migration/project_namespaces/models/project.rb16
-rw-r--r--lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb20
-rw-r--r--lib/gitlab/background_migration/remove_undefined_occurrence_confidence_level.rb13
-rw-r--r--lib/gitlab/background_migration/remove_undefined_occurrence_severity_level.rb13
-rw-r--r--lib/gitlab/background_migration/remove_undefined_vulnerability_severity_level.rb13
-rw-r--r--lib/gitlab/background_migration/set_default_iteration_cadences.rb60
-rw-r--r--lib/gitlab/background_migration/set_null_external_diff_store_to_local_value.rb24
-rw-r--r--lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb26
-rw-r--r--lib/gitlab/background_migration/update_vulnerabilities_to_dismissed.rb13
-rw-r--r--lib/gitlab/background_migration/update_vulnerability_confidence.rb13
-rw-r--r--lib/gitlab/background_migration/update_vulnerability_occurrences_location.rb14
-rw-r--r--lib/gitlab/bitbucket_server_import/importer.rb10
-rw-r--r--lib/gitlab/blob_helper.rb2
-rw-r--r--lib/gitlab/ci/artifact_file_reader.rb27
-rw-r--r--lib/gitlab/ci/artifacts/metrics.rb15
-rw-r--r--lib/gitlab/ci/build/auto_retry.rb4
-rw-r--r--lib/gitlab/ci/build/context/base.rb22
-rw-r--r--lib/gitlab/ci/build/image.rb9
-rw-r--r--lib/gitlab/ci/build/rules/rule/clause/exists.rb12
-rw-r--r--lib/gitlab/ci/config.rb31
-rw-r--r--lib/gitlab/ci/config/entry/include/rules/rule.rb4
-rw-r--r--lib/gitlab/ci/config/entry/job.rb8
-rw-r--r--lib/gitlab/ci/config/entry/processable.rb1
-rw-r--r--lib/gitlab/ci/config/entry/service.rb6
-rw-r--r--lib/gitlab/ci/config/external/context.rb14
-rw-r--r--lib/gitlab/ci/parsers/security/common.rb5
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schema_validator.rb2
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/sast-report-format.json (renamed from lib/gitlab/ci/parsers/security/validators/schemas/sast.json)0
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schemas/secret-detection-report-format.json (renamed from lib/gitlab/ci/parsers/security/validators/schemas/secret_detection.json)0
-rw-r--r--lib/gitlab/ci/pipeline/chain/command.rb3
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/process.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/create_cross_database_associations.rb21
-rw-r--r--lib/gitlab/ci/pipeline/metrics.rb9
-rw-r--r--lib/gitlab/ci/pipeline/seed/build.rb14
-rw-r--r--lib/gitlab/ci/pipeline/seed/stage.rb2
-rw-r--r--lib/gitlab/ci/reports/security/finding.rb40
-rw-r--r--lib/gitlab/ci/reports/security/report.rb4
-rw-r--r--lib/gitlab/ci/reports/security/reports.rb19
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/templates/Django.gitlab-ci.yml116
-rw-r--r--lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Jobs/CF-Provision.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml24
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml16
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy/EC2.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml12
-rw-r--r--lib/gitlab/ci/templates/Jobs/Helm-2to3.gitlab-ci.yml12
-rw-r--r--lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml34
-rw-r--r--lib/gitlab/ci/templates/Kaniko.gitlab-ci.yml47
-rw-r--r--lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/Cluster-Image-Scanning.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml6
-rw-r--r--lib/gitlab/ci/templates/Security/SAST-IaC.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml7
-rw-r--r--lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml16
-rw-r--r--lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/trace.rb17
-rw-r--r--lib/gitlab/ci/trace/archive.rb2
-rw-r--r--lib/gitlab/ci/trace/metrics.rb10
-rw-r--r--lib/gitlab/ci/variables/builder.rb49
-rw-r--r--lib/gitlab/ci/variables/collection.rb4
-rw-r--r--lib/gitlab/ci/yaml_processor/result.rb1
-rw-r--r--lib/gitlab/config_checker/external_database_checker.rb4
-rw-r--r--lib/gitlab/container_repository/tags/cache.rb72
-rw-r--r--lib/gitlab/content_security_policy/config_loader.rb49
-rw-r--r--lib/gitlab/content_security_policy/directives.rb21
-rw-r--r--lib/gitlab/contributions_calendar.rb17
-rw-r--r--lib/gitlab/current_settings.rb2
-rw-r--r--lib/gitlab/cycle_analytics/stage_summary.rb3
-rw-r--r--lib/gitlab/cycle_analytics/summary/base.rb4
-rw-r--r--lib/gitlab/cycle_analytics/summary/deployment_frequency.rb9
-rw-r--r--lib/gitlab/database.rb57
-rw-r--r--lib/gitlab/database/as_with_materialized.rb2
-rw-r--r--lib/gitlab/database/async_indexes/index_creator.rb2
-rw-r--r--lib/gitlab/database/async_indexes/postgres_async_index.rb2
-rw-r--r--lib/gitlab/database/background_migration_job.rb1
-rw-r--r--lib/gitlab/database/batch_counter.rb6
-rw-r--r--lib/gitlab/database/connection.rb260
-rw-r--r--lib/gitlab/database/each_database.rb39
-rw-r--r--lib/gitlab/database/gitlab_schema.rb96
-rw-r--r--lib/gitlab/database/gitlab_schemas.yml543
-rw-r--r--lib/gitlab/database/load_balancing.rb2
-rw-r--r--lib/gitlab/database/load_balancing/configuration.rb50
-rw-r--r--lib/gitlab/database/load_balancing/connection_proxy.rb7
-rw-r--r--lib/gitlab/database/load_balancing/load_balancer.rb63
-rw-r--r--lib/gitlab/database/load_balancing/primary_host.rb5
-rw-r--r--lib/gitlab/database/load_balancing/rack_middleware.rb10
-rw-r--r--lib/gitlab/database/load_balancing/setup.rb87
-rw-r--r--lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb10
-rw-r--r--lib/gitlab/database/load_balancing/sticking.rb5
-rw-r--r--lib/gitlab/database/migration_helpers.rb75
-rw-r--r--lib/gitlab/database/migration_helpers/cascading_namespace_settings.rb4
-rw-r--r--lib/gitlab/database/migrations/observation.rb3
-rw-r--r--lib/gitlab/database/migrations/observers.rb3
-rw-r--r--lib/gitlab/database/migrations/observers/transaction_duration.rb42
-rw-r--r--lib/gitlab/database/partitioning.rb83
-rw-r--r--lib/gitlab/database/partitioning/detached_partition_dropper.rb96
-rw-r--r--lib/gitlab/database/partitioning/monthly_strategy.rb4
-rw-r--r--lib/gitlab/database/partitioning/multi_database_partition_dropper.rb35
-rw-r--r--lib/gitlab/database/partitioning/multi_database_partition_manager.rb37
-rw-r--r--lib/gitlab/database/partitioning/partition_monitoring.rb18
-rw-r--r--lib/gitlab/database/partitioning/replace_table.rb7
-rw-r--r--lib/gitlab/database/partitioning/time_partition.rb2
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb4
-rw-r--r--lib/gitlab/database/postgres_foreign_key.rb6
-rw-r--r--lib/gitlab/database/postgres_hll/batch_distinct_counter.rb6
-rw-r--r--lib/gitlab/database/postgres_index.rb3
-rw-r--r--lib/gitlab/database/postgres_index_bloat_estimate.rb2
-rw-r--r--lib/gitlab/database/query_analyzer.rb129
-rw-r--r--lib/gitlab/database/query_analyzers/base.rb53
-rw-r--r--lib/gitlab/database/query_analyzers/gitlab_schemas_metrics.rb46
-rw-r--r--lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb119
-rw-r--r--lib/gitlab/database/reflection.rb115
-rw-r--r--lib/gitlab/database/reindexing.rb41
-rw-r--r--lib/gitlab/database/reindexing/index_selection.rb6
-rw-r--r--lib/gitlab/database/reindexing/queued_action.rb21
-rw-r--r--lib/gitlab/database/reindexing/reindex_action.rb2
-rw-r--r--lib/gitlab/database/reindexing/reindex_concurrently.rb10
-rw-r--r--lib/gitlab/database/shared_model.rb8
-rw-r--r--lib/gitlab/database/unidirectional_copy_trigger.rb2
-rw-r--r--lib/gitlab/diff/file.rb29
-rw-r--r--lib/gitlab/diff/highlight.rb3
-rw-r--r--lib/gitlab/diff/highlight_cache.rb2
-rw-r--r--lib/gitlab/diff/position_tracer/line_strategy.rb8
-rw-r--r--lib/gitlab/email/handler/service_desk_handler.rb36
-rw-r--r--lib/gitlab/email/message/in_product_marketing.rb3
-rw-r--r--lib/gitlab/email/message/in_product_marketing/admin_verify.rb4
-rw-r--r--lib/gitlab/email/message/in_product_marketing/base.rb37
-rw-r--r--lib/gitlab/email/message/in_product_marketing/create.rb4
-rw-r--r--lib/gitlab/email/message/in_product_marketing/experience.rb16
-rw-r--r--lib/gitlab/email/message/in_product_marketing/helper.rb9
-rw-r--r--lib/gitlab/email/message/in_product_marketing/invite_team.rb53
-rw-r--r--lib/gitlab/email/message/in_product_marketing/verify.rb4
-rw-r--r--lib/gitlab/email/receiver.rb8
-rw-r--r--lib/gitlab/email/reply_parser.rb12
-rw-r--r--lib/gitlab/emoji.rb68
-rw-r--r--lib/gitlab/etag_caching/router/restful.rb4
-rw-r--r--lib/gitlab/git.rb1
-rw-r--r--lib/gitlab/git/blob.rb3
-rw-r--r--lib/gitlab/git/commit.rb14
-rw-r--r--lib/gitlab/git/repository.rb24
-rw-r--r--lib/gitlab/gitaly_client.rb25
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/ref_service.rb25
-rw-r--r--lib/gitlab/github_import/bulk_importing.rb2
-rw-r--r--lib/gitlab/github_import/importer/diff_note_importer.rb138
-rw-r--r--lib/gitlab/github_import/importer/issue_importer.rb2
-rw-r--r--lib/gitlab/github_import/importer/label_links_importer.rb2
-rw-r--r--lib/gitlab/github_import/importer/note_importer.rb2
-rw-r--r--lib/gitlab/github_import/importer/pull_requests_merged_by_importer.rb15
-rw-r--r--lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb2
-rw-r--r--lib/gitlab/github_import/representation/diff_note.rb104
-rw-r--r--lib/gitlab/github_import/representation/diff_notes/suggestion_formatter.rb34
-rw-r--r--lib/gitlab/gon_helper.rb4
-rw-r--r--lib/gitlab/gpg/commit.rb32
-rw-r--r--lib/gitlab/grape_logging/loggers/urgency_logger.rb19
-rw-r--r--lib/gitlab/graphql/known_operations.rb45
-rw-r--r--lib/gitlab/graphql/loaders/full_path_model_loader.rb5
-rw-r--r--lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb2
-rw-r--r--lib/gitlab/graphql/query_analyzers/logger_analyzer.rb50
-rw-r--r--lib/gitlab/graphql/tracers/application_context_tracer.rb40
-rw-r--r--lib/gitlab/graphql/tracers/logger_tracer.rb58
-rw-r--r--lib/gitlab/graphql/tracers/metrics_tracer.rb48
-rw-r--r--lib/gitlab/graphql/tracers/timer_tracer.rb31
-rw-r--r--lib/gitlab/graphql/variables.rb7
-rw-r--r--lib/gitlab/health_checks/metric.rb3
-rw-r--r--lib/gitlab/health_checks/probes/status.rb3
-rw-r--r--lib/gitlab/health_checks/redis/cache_check.rb26
-rw-r--r--lib/gitlab/health_checks/redis/queues_check.rb26
-rw-r--r--lib/gitlab/health_checks/redis/rate_limiting_check.rb26
-rw-r--r--lib/gitlab/health_checks/redis/redis_abstract_check.rb41
-rw-r--r--lib/gitlab/health_checks/redis/redis_check.rb20
-rw-r--r--lib/gitlab/health_checks/redis/sessions_check.rb26
-rw-r--r--lib/gitlab/health_checks/redis/shared_state_check.rb26
-rw-r--r--lib/gitlab/health_checks/redis/trace_chunks_check.rb26
-rw-r--r--lib/gitlab/health_checks/result.rb3
-rw-r--r--lib/gitlab/http.rb2
-rw-r--r--lib/gitlab/i18n.rb18
-rw-r--r--lib/gitlab/import/database_helpers.rb4
-rw-r--r--lib/gitlab/import/metrics.rb6
-rw-r--r--lib/gitlab/import_export/attributes_permitter.rb2
-rw-r--r--lib/gitlab/import_export/base/object_builder.rb12
-rw-r--r--lib/gitlab/import_export/decompressed_archive_size_validator.rb2
-rw-r--r--lib/gitlab/import_export/group/relation_tree_restorer.rb274
-rw-r--r--lib/gitlab/import_export/project/import_export.yml434
-rw-r--r--lib/gitlab/import_export/project/object_builder.rb40
-rw-r--r--lib/gitlab/import_export/project/relation_factory.rb4
-rw-r--r--lib/gitlab/import_export/project/relation_tree_restorer.rb27
-rw-r--r--lib/gitlab/import_export/project/sample/relation_tree_restorer.rb6
-rw-r--r--lib/gitlab/import_export/project/tree_saver.rb36
-rw-r--r--lib/gitlab/import_export/relation_tree_restorer.rb280
-rw-r--r--lib/gitlab/instrumentation/redis_interceptor.rb15
-rw-r--r--lib/gitlab/instrumentation/uploads.rb32
-rw-r--r--lib/gitlab/instrumentation_helper.rb5
-rw-r--r--lib/gitlab/integrations/sti_type.rb2
-rw-r--r--lib/gitlab/issues/rebalancing/state.rb61
-rw-r--r--lib/gitlab/jira/http_client.rb1
-rw-r--r--lib/gitlab/language_detection.rb2
-rw-r--r--lib/gitlab/lfs_token.rb15
-rw-r--r--lib/gitlab/lograge/custom_options.rb17
-rw-r--r--lib/gitlab/merge_requests/merge_commit_message.rb60
-rw-r--r--lib/gitlab/metrics.rb2
-rw-r--r--lib/gitlab/metrics/background_transaction.rb17
-rw-r--r--lib/gitlab/metrics/methods.rb8
-rw-r--r--lib/gitlab/metrics/rails_slis.rb32
-rw-r--r--lib/gitlab/metrics/requests_rack_middleware.rb18
-rw-r--r--lib/gitlab/metrics/samplers/action_cable_sampler.rb23
-rw-r--r--lib/gitlab/metrics/subscribers/action_view.rb2
-rw-r--r--lib/gitlab/metrics/subscribers/external_http.rb2
-rw-r--r--lib/gitlab/metrics/subscribers/rails_cache.rb2
-rw-r--r--lib/gitlab/metrics/transaction.rb25
-rw-r--r--lib/gitlab/metrics/web_transaction.rb25
-rw-r--r--lib/gitlab/middleware/compressed_json.rb66
-rw-r--r--lib/gitlab/middleware/go.rb2
-rw-r--r--lib/gitlab/middleware/query_analyzer.rb15
-rw-r--r--lib/gitlab/middleware/release_env.rb3
-rw-r--r--lib/gitlab/pagination/gitaly_keyset_pager.rb4
-rw-r--r--lib/gitlab/patch/sidekiq_client.rb22
-rw-r--r--lib/gitlab/patch/sidekiq_cron_poller.rb17
-rw-r--r--lib/gitlab/project_template.rb1
-rw-r--r--lib/gitlab/prometheus/queries/validate_query.rb2
-rw-r--r--lib/gitlab/prometheus_client.rb8
-rw-r--r--lib/gitlab/quick_actions/issuable_actions.rb7
-rw-r--r--lib/gitlab/quick_actions/issue_actions.rb31
-rw-r--r--lib/gitlab/quick_actions/issue_and_merge_request_actions.rb14
-rw-r--r--lib/gitlab/redis/hll.rb3
-rw-r--r--lib/gitlab/redis/multi_store.rb215
-rw-r--r--lib/gitlab/redis/wrapper.rb6
-rw-r--r--lib/gitlab/runtime.rb15
-rw-r--r--lib/gitlab/saas.rb4
-rw-r--r--lib/gitlab/search_results.rb5
-rw-r--r--lib/gitlab/setup_helper.rb7
-rw-r--r--lib/gitlab/sidekiq_cluster.rb171
-rw-r--r--lib/gitlab/sidekiq_cluster/cli.rb230
-rw-r--r--lib/gitlab/sidekiq_config.rb34
-rw-r--r--lib/gitlab/sidekiq_config/cli_methods.rb1
-rw-r--r--lib/gitlab/sidekiq_config/worker.rb7
-rw-r--r--lib/gitlab/sidekiq_enq.rb80
-rw-r--r--lib/gitlab/sidekiq_logging/deduplication_logger.rb10
-rw-r--r--lib/gitlab/sidekiq_logging/json_formatter.rb2
-rw-r--r--lib/gitlab/sidekiq_middleware.rb1
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb54
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/server.rb2
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/base.rb4
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/deduplicates_when_scheduling.rb15
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed.rb3
-rw-r--r--lib/gitlab/sidekiq_middleware/query_analyzer.rb11
-rw-r--r--lib/gitlab/sidekiq_middleware/size_limiter/validator.rb39
-rw-r--r--lib/gitlab/sidekiq_status.rb6
-rw-r--r--lib/gitlab/slash_commands/result.rb3
-rw-r--r--lib/gitlab/spamcheck/client.rb18
-rw-r--r--lib/gitlab/subscription_portal.rb8
-rw-r--r--lib/gitlab/template_parser/ast.rb3
-rw-r--r--lib/gitlab/testing/request_inspector_middleware.rb4
-rw-r--r--lib/gitlab/tracking.rb27
-rw-r--r--lib/gitlab/tracking/destinations/product_analytics.rb41
-rw-r--r--lib/gitlab/tracking/destinations/snowplow.rb36
-rw-r--r--lib/gitlab/tracking/destinations/snowplow_micro.rb48
-rw-r--r--lib/gitlab/tracking/standard_context.rb15
-rw-r--r--lib/gitlab/url_blocker.rb16
-rw-r--r--lib/gitlab/usage/metric.rb4
-rw-r--r--lib/gitlab/usage/metrics/names_suggestions/generator.rb8
-rw-r--r--lib/gitlab/usage_data.rb109
-rw-r--r--lib/gitlab/usage_data_counters/known_events/ci_templates.yml20
-rw-r--r--lib/gitlab/usage_data_counters/known_events/code_review_events.yml24
-rw-r--r--lib/gitlab/usage_data_counters/known_events/quickactions.yml4
-rw-r--r--lib/gitlab/usage_data_counters/vscode_extension_activity_unique_counter.rb (renamed from lib/gitlab/usage_data_counters/vs_code_extension_activity_unique_counter.rb)0
-rw-r--r--lib/gitlab/usage_data_metrics.rb12
-rw-r--r--lib/gitlab/usage_data_non_sql_metrics.rb11
-rw-r--r--lib/gitlab/usage_data_queries.rb11
-rw-r--r--lib/gitlab/utils/usage_data.rb9
-rw-r--r--lib/gitlab/webpack/file_loader.rb65
-rw-r--r--lib/gitlab/webpack/graphql_known_operations.rb25
-rw-r--r--lib/gitlab/webpack/manifest.rb50
-rw-r--r--lib/gitlab/workhorse.rb5
-rw-r--r--lib/gitlab/x509/certificate.rb28
-rw-r--r--lib/gitlab/zentao/client.rb19
-rw-r--r--lib/gitlab/zentao/query.rb78
-rw-r--r--lib/object_storage/config.rb10
-rw-r--r--lib/security/ci_configuration/sast_iac_build_action.rb19
-rw-r--r--lib/sidebars/groups/menus/customer_relations_menu.rb60
-rw-r--r--lib/sidebars/groups/menus/invite_team_members_menu.rb46
-rw-r--r--lib/sidebars/groups/menus/packages_registries_menu.rb2
-rw-r--r--lib/sidebars/groups/panel.rb11
-rw-r--r--lib/sidebars/panel.rb1
-rw-r--r--lib/sidebars/projects/menus/confluence_menu.rb5
-rw-r--r--lib/sidebars/projects/menus/infrastructure_menu.rb4
-rw-r--r--lib/sidebars/projects/menus/invite_team_members_menu.rb47
-rw-r--r--lib/sidebars/projects/menus/settings_menu.rb4
-rw-r--r--lib/sidebars/projects/menus/zentao_menu.rb77
-rw-r--r--lib/sidebars/projects/panel.rb9
-rwxr-xr-xlib/support/init.d/gitlab8
-rw-r--r--lib/support/systemd/gitlab-gitaly.service17
-rw-r--r--lib/support/systemd/gitlab-mailroom.service19
-rw-r--r--lib/support/systemd/gitlab-pages.service19
-rw-r--r--lib/support/systemd/gitlab-puma.service26
-rw-r--r--lib/support/systemd/gitlab-sidekiq.service22
-rw-r--r--lib/support/systemd/gitlab-workhorse.service21
-rw-r--r--lib/support/systemd/gitlab.slice8
-rw-r--r--lib/support/systemd/gitlab.target6
-rw-r--r--lib/system_check/app/init_script_exists_check.rb29
-rw-r--r--lib/system_check/app/init_script_up_to_date_check.rb47
-rw-r--r--lib/system_check/app/systemd_unit_files_or_init_script_exist_check.rb39
-rw-r--r--lib/system_check/app/systemd_unit_files_or_init_script_up_to_date_check.rb80
-rw-r--r--lib/system_check/incoming_email/initd_configured_check.rb34
-rw-r--r--lib/system_check/incoming_email/mail_room_enabled_check.rb42
-rw-r--r--lib/system_check/incoming_email/mail_room_running_check.rb14
-rw-r--r--lib/system_check/incoming_email_check.rb2
-rw-r--r--lib/system_check/init_helpers.rb24
-rw-r--r--lib/system_check/rake_task/app_task.rb4
-rw-r--r--lib/system_check/sidekiq_check.rb6
-rw-r--r--lib/tasks/gemojione.rake245
-rw-r--r--lib/tasks/gitlab/db.rake45
-rw-r--r--lib/tasks/gitlab/docs/compile_deprecations.rake2
-rw-r--r--lib/tasks/gitlab/gitaly.rake3
-rw-r--r--lib/tasks/gitlab/info.rake4
-rw-r--r--lib/tasks/gitlab/sidekiq.rake7
-rw-r--r--lib/tasks/gitlab/storage.rake2
-rw-r--r--lib/tasks/haml-lint.rake11
-rw-r--r--lib/tasks/tanuki_emoji.rake260
-rw-r--r--lib/uploaded_file.rb16
-rw-r--r--locale/am_ET/gitlab.po1470
-rw-r--r--locale/ar_SA/gitlab.po1510
-rw-r--r--locale/as_IN/gitlab.po1470
-rw-r--r--locale/az_AZ/gitlab.po1470
-rw-r--r--locale/ba_RU/gitlab.po1460
-rw-r--r--locale/bg/gitlab.po1472
-rw-r--r--locale/bn_BD/gitlab.po1470
-rw-r--r--locale/bn_IN/gitlab.po1470
-rw-r--r--locale/br_FR/gitlab.po1500
-rw-r--r--locale/bs_BA/gitlab.po1480
-rw-r--r--locale/ca_ES/gitlab.po1470
-rw-r--r--locale/cs_CZ/gitlab.po1490
-rw-r--r--locale/cy_GB/gitlab.po1510
-rw-r--r--locale/da_DK/gitlab.po2374
-rw-r--r--locale/de/gitlab.po1486
-rw-r--r--locale/el_GR/gitlab.po1470
-rw-r--r--locale/eo/gitlab.po1472
-rw-r--r--locale/es/gitlab.po1526
-rw-r--r--locale/et_EE/gitlab.po1470
-rw-r--r--locale/fa_IR/gitlab.po1470
-rw-r--r--locale/fi_FI/gitlab.po1470
-rw-r--r--locale/fil_PH/gitlab.po1470
-rw-r--r--locale/fr/gitlab.po1478
-rw-r--r--locale/gitlab.pot1616
-rw-r--r--locale/gl_ES/gitlab.po1470
-rw-r--r--locale/he_IL/gitlab.po1490
-rw-r--r--locale/hi_IN/gitlab.po1470
-rw-r--r--locale/hr_HR/gitlab.po1480
-rw-r--r--locale/hu_HU/gitlab.po1470
-rw-r--r--locale/hy_AM/gitlab.po1470
-rw-r--r--locale/id_ID/gitlab.po1460
-rw-r--r--locale/ig_NG/gitlab.po1460
-rw-r--r--locale/is_IS/gitlab.po1470
-rw-r--r--locale/it/gitlab.po1474
-rw-r--r--locale/ja/gitlab.po1524
-rw-r--r--locale/ka_GE/gitlab.po1470
-rw-r--r--locale/kab/gitlab.po1470
-rw-r--r--locale/ko/gitlab.po1470
-rw-r--r--locale/ku_TR/gitlab.po1470
-rw-r--r--locale/ky_KG/gitlab.po1470
-rw-r--r--locale/lt_LT/gitlab.po1490
-rw-r--r--locale/mk_MK/gitlab.po1470
-rw-r--r--locale/mn_MN/gitlab.po1470
-rw-r--r--locale/nb_NO/gitlab.po1546
-rw-r--r--locale/nl_NL/gitlab.po1470
-rw-r--r--locale/pa_IN/gitlab.po1470
-rw-r--r--locale/pl_PL/gitlab.po1496
-rw-r--r--locale/pt_BR/gitlab.po2488
-rw-r--r--locale/pt_PT/gitlab.po1474
-rw-r--r--locale/ro_RO/gitlab.po1686
-rw-r--r--locale/ru/gitlab.po1556
-rw-r--r--locale/si_LK/gitlab.po1470
-rw-r--r--locale/sk_SK/gitlab.po1490
-rw-r--r--locale/sl_SI/gitlab.po1490
-rw-r--r--locale/sq_AL/gitlab.po1470
-rw-r--r--locale/sr_CS/gitlab.po1480
-rw-r--r--locale/sr_SP/gitlab.po1480
-rw-r--r--locale/sv_SE/gitlab.po1470
-rw-r--r--locale/sw_KE/gitlab.po1470
-rw-r--r--locale/ta_IN/gitlab.po1470
-rw-r--r--locale/tr_TR/gitlab.po1482
-rw-r--r--locale/uk/gitlab.po1852
-rw-r--r--locale/unfound_translations.rb3
-rw-r--r--locale/ur_PK/gitlab.po1470
-rw-r--r--locale/uz_UZ/gitlab.po1470
-rw-r--r--locale/vi_VN/gitlab.po1460
-rw-r--r--locale/zh_CN/gitlab.po2490
-rw-r--r--locale/zh_HK/gitlab.po1468
-rw-r--r--locale/zh_TW/gitlab.po1464
-rw-r--r--package.json70
-rw-r--r--public/-/emojis/1/emojis.json2
-rw-r--r--public/-/emojis/2/100.pngbin0 -> 3429 bytes
-rw-r--r--public/-/emojis/2/1234.pngbin0 -> 3097 bytes
-rw-r--r--public/-/emojis/2/8ball.pngbin0 -> 3702 bytes
-rw-r--r--public/-/emojis/2/a.pngbin0 -> 2804 bytes
-rw-r--r--public/-/emojis/2/ab.pngbin0 -> 3080 bytes
-rw-r--r--public/-/emojis/2/abc.pngbin0 -> 2999 bytes
-rw-r--r--public/-/emojis/2/abcd.pngbin0 -> 3352 bytes
-rw-r--r--public/-/emojis/2/accept.pngbin0 -> 3162 bytes
-rw-r--r--public/-/emojis/2/aerial_tramway.pngbin0 -> 3297 bytes
-rw-r--r--public/-/emojis/2/airplane.pngbin0 -> 5401 bytes
-rw-r--r--public/-/emojis/2/airplane_arriving.pngbin0 -> 4300 bytes
-rw-r--r--public/-/emojis/2/airplane_departure.pngbin0 -> 3980 bytes
-rw-r--r--public/-/emojis/2/airplane_small.pngbin0 -> 5373 bytes
-rw-r--r--public/-/emojis/2/alarm_clock.pngbin0 -> 6273 bytes
-rw-r--r--public/-/emojis/2/alembic.pngbin0 -> 4544 bytes
-rw-r--r--public/-/emojis/2/alien.pngbin0 -> 3191 bytes
-rw-r--r--public/-/emojis/2/ambulance.pngbin0 -> 3864 bytes
-rw-r--r--public/-/emojis/2/amphora.pngbin0 -> 4125 bytes
-rw-r--r--public/-/emojis/2/anchor.pngbin0 -> 3166 bytes
-rw-r--r--public/-/emojis/2/angel.pngbin0 -> 5329 bytes
-rw-r--r--public/-/emojis/2/angel_tone1.pngbin0 -> 5332 bytes
-rw-r--r--public/-/emojis/2/angel_tone2.pngbin0 -> 5196 bytes
-rw-r--r--public/-/emojis/2/angel_tone3.pngbin0 -> 5233 bytes
-rw-r--r--public/-/emojis/2/angel_tone4.pngbin0 -> 5068 bytes
-rw-r--r--public/-/emojis/2/angel_tone5.pngbin0 -> 5094 bytes
-rw-r--r--public/-/emojis/2/anger.pngbin0 -> 2791 bytes
-rw-r--r--public/-/emojis/2/anger_right.pngbin0 -> 4527 bytes
-rw-r--r--public/-/emojis/2/angry.pngbin0 -> 4815 bytes
-rw-r--r--public/-/emojis/2/anguished.pngbin0 -> 4897 bytes
-rw-r--r--public/-/emojis/2/ant.pngbin0 -> 4108 bytes
-rw-r--r--public/-/emojis/2/apple.pngbin0 -> 3432 bytes
-rw-r--r--public/-/emojis/2/aquarius.pngbin0 -> 5602 bytes
-rw-r--r--public/-/emojis/2/aries.pngbin0 -> 4474 bytes
-rw-r--r--public/-/emojis/2/arrow_backward.pngbin0 -> 1679 bytes
-rw-r--r--public/-/emojis/2/arrow_double_down.pngbin0 -> 2145 bytes
-rw-r--r--public/-/emojis/2/arrow_double_up.pngbin0 -> 2127 bytes
-rw-r--r--public/-/emojis/2/arrow_down.pngbin0 -> 1713 bytes
-rw-r--r--public/-/emojis/2/arrow_down_small.pngbin0 -> 1714 bytes
-rw-r--r--public/-/emojis/2/arrow_forward.pngbin0 -> 1656 bytes
-rw-r--r--public/-/emojis/2/arrow_heading_down.pngbin0 -> 2249 bytes
-rw-r--r--public/-/emojis/2/arrow_heading_up.pngbin0 -> 2328 bytes
-rw-r--r--public/-/emojis/2/arrow_left.pngbin0 -> 1690 bytes
-rw-r--r--public/-/emojis/2/arrow_lower_left.pngbin0 -> 1832 bytes
-rw-r--r--public/-/emojis/2/arrow_lower_right.pngbin0 -> 1803 bytes
-rw-r--r--public/-/emojis/2/arrow_right.pngbin0 -> 1680 bytes
-rw-r--r--public/-/emojis/2/arrow_right_hook.pngbin0 -> 2284 bytes
-rw-r--r--public/-/emojis/2/arrow_up.pngbin0 -> 1666 bytes
-rw-r--r--public/-/emojis/2/arrow_up_down.pngbin0 -> 2040 bytes
-rw-r--r--public/-/emojis/2/arrow_up_small.pngbin0 -> 1658 bytes
-rw-r--r--public/-/emojis/2/arrow_upper_left.pngbin0 -> 1784 bytes
-rw-r--r--public/-/emojis/2/arrow_upper_right.pngbin0 -> 1800 bytes
-rw-r--r--public/-/emojis/2/arrows_clockwise.pngbin0 -> 2736 bytes
-rw-r--r--public/-/emojis/2/arrows_counterclockwise.pngbin0 -> 2710 bytes
-rw-r--r--public/-/emojis/2/art.pngbin0 -> 4958 bytes
-rw-r--r--public/-/emojis/2/articulated_lorry.pngbin0 -> 3583 bytes
-rw-r--r--public/-/emojis/2/asterisk.pngbin0 -> 2668 bytes
-rw-r--r--public/-/emojis/2/astonished.pngbin0 -> 4894 bytes
-rw-r--r--public/-/emojis/2/athletic_shoe.pngbin0 -> 4116 bytes
-rw-r--r--public/-/emojis/2/atm.pngbin0 -> 3091 bytes
-rw-r--r--public/-/emojis/2/atom.pngbin0 -> 4941 bytes
-rw-r--r--public/-/emojis/2/avocado.pngbin0 -> 4585 bytes
-rw-r--r--public/-/emojis/2/b.pngbin0 -> 2390 bytes
-rw-r--r--public/-/emojis/2/baby.pngbin0 -> 3211 bytes
-rw-r--r--public/-/emojis/2/baby_bottle.pngbin0 -> 3677 bytes
-rw-r--r--public/-/emojis/2/baby_chick.pngbin0 -> 2407 bytes
-rw-r--r--public/-/emojis/2/baby_symbol.pngbin0 -> 3474 bytes
-rw-r--r--public/-/emojis/2/baby_tone1.pngbin0 -> 3341 bytes
-rw-r--r--public/-/emojis/2/baby_tone2.pngbin0 -> 3168 bytes
-rw-r--r--public/-/emojis/2/baby_tone3.pngbin0 -> 3107 bytes
-rw-r--r--public/-/emojis/2/baby_tone4.pngbin0 -> 3043 bytes
-rw-r--r--public/-/emojis/2/baby_tone5.pngbin0 -> 3127 bytes
-rw-r--r--public/-/emojis/2/back.pngbin0 -> 3529 bytes
-rw-r--r--public/-/emojis/2/bacon.pngbin0 -> 3805 bytes
-rw-r--r--public/-/emojis/2/badminton.pngbin0 -> 4891 bytes
-rw-r--r--public/-/emojis/2/baggage_claim.pngbin0 -> 2937 bytes
-rw-r--r--public/-/emojis/2/balloon.pngbin0 -> 1977 bytes
-rw-r--r--public/-/emojis/2/ballot_box.pngbin0 -> 3484 bytes
-rw-r--r--public/-/emojis/2/ballot_box_with_check.pngbin0 -> 2762 bytes
-rw-r--r--public/-/emojis/2/bamboo.pngbin0 -> 3829 bytes
-rw-r--r--public/-/emojis/2/banana.pngbin0 -> 3384 bytes
-rw-r--r--public/-/emojis/2/bangbang.pngbin0 -> 2312 bytes
-rw-r--r--public/-/emojis/2/bank.pngbin0 -> 4455 bytes
-rw-r--r--public/-/emojis/2/bar_chart.pngbin0 -> 2152 bytes
-rw-r--r--public/-/emojis/2/barber.pngbin0 -> 3154 bytes
-rw-r--r--public/-/emojis/2/baseball.pngbin0 -> 5149 bytes
-rw-r--r--public/-/emojis/2/basketball.pngbin0 -> 5158 bytes
-rw-r--r--public/-/emojis/2/basketball_player.pngbin0 -> 4215 bytes
-rw-r--r--public/-/emojis/2/basketball_player_tone1.pngbin0 -> 4273 bytes
-rw-r--r--public/-/emojis/2/basketball_player_tone2.pngbin0 -> 4256 bytes
-rw-r--r--public/-/emojis/2/basketball_player_tone3.pngbin0 -> 4236 bytes
-rw-r--r--public/-/emojis/2/basketball_player_tone4.pngbin0 -> 4274 bytes
-rw-r--r--public/-/emojis/2/basketball_player_tone5.pngbin0 -> 4291 bytes
-rw-r--r--public/-/emojis/2/bat.pngbin0 -> 3647 bytes
-rw-r--r--public/-/emojis/2/bath.pngbin0 -> 5134 bytes
-rw-r--r--public/-/emojis/2/bath_tone1.pngbin0 -> 5181 bytes
-rw-r--r--public/-/emojis/2/bath_tone2.pngbin0 -> 5127 bytes
-rw-r--r--public/-/emojis/2/bath_tone3.pngbin0 -> 5123 bytes
-rw-r--r--public/-/emojis/2/bath_tone4.pngbin0 -> 5123 bytes
-rw-r--r--public/-/emojis/2/bath_tone5.pngbin0 -> 5141 bytes
-rw-r--r--public/-/emojis/2/bathtub.pngbin0 -> 4064 bytes
-rw-r--r--public/-/emojis/2/battery.pngbin0 -> 2468 bytes
-rw-r--r--public/-/emojis/2/beach.pngbin0 -> 4471 bytes
-rw-r--r--public/-/emojis/2/beach_umbrella.pngbin0 -> 3787 bytes
-rw-r--r--public/-/emojis/2/bear.pngbin0 -> 3495 bytes
-rw-r--r--public/-/emojis/2/bed.pngbin0 -> 1635 bytes
-rw-r--r--public/-/emojis/2/bee.pngbin0 -> 4830 bytes
-rw-r--r--public/-/emojis/2/beer.pngbin0 -> 4702 bytes
-rw-r--r--public/-/emojis/2/beers.pngbin0 -> 6052 bytes
-rw-r--r--public/-/emojis/2/beetle.pngbin0 -> 5033 bytes
-rw-r--r--public/-/emojis/2/beginner.pngbin0 -> 2151 bytes
-rw-r--r--public/-/emojis/2/bell.pngbin0 -> 3524 bytes
-rw-r--r--public/-/emojis/2/bellhop.pngbin0 -> 3234 bytes
-rw-r--r--public/-/emojis/2/bento.pngbin0 -> 4736 bytes
-rw-r--r--public/-/emojis/2/bicyclist.pngbin0 -> 5822 bytes
-rw-r--r--public/-/emojis/2/bicyclist_tone1.pngbin0 -> 5879 bytes
-rw-r--r--public/-/emojis/2/bicyclist_tone2.pngbin0 -> 5865 bytes
-rw-r--r--public/-/emojis/2/bicyclist_tone3.pngbin0 -> 5852 bytes
-rw-r--r--public/-/emojis/2/bicyclist_tone4.pngbin0 -> 5872 bytes
-rw-r--r--public/-/emojis/2/bicyclist_tone5.pngbin0 -> 5889 bytes
-rw-r--r--public/-/emojis/2/bike.pngbin0 -> 5493 bytes
-rw-r--r--public/-/emojis/2/bikini.pngbin0 -> 4236 bytes
-rw-r--r--public/-/emojis/2/biohazard.pngbin0 -> 5855 bytes
-rw-r--r--public/-/emojis/2/bird.pngbin0 -> 2500 bytes
-rw-r--r--public/-/emojis/2/birthday.pngbin0 -> 5512 bytes
-rw-r--r--public/-/emojis/2/black_circle.pngbin0 -> 2741 bytes
-rw-r--r--public/-/emojis/2/black_heart.pngbin0 -> 2912 bytes
-rw-r--r--public/-/emojis/2/black_joker.pngbin0 -> 3545 bytes
-rw-r--r--public/-/emojis/2/black_large_square.pngbin0 -> 982 bytes
-rw-r--r--public/-/emojis/2/black_medium_small_square.pngbin0 -> 674 bytes
-rw-r--r--public/-/emojis/2/black_medium_square.pngbin0 -> 734 bytes
-rw-r--r--public/-/emojis/2/black_nib.pngbin0 -> 4179 bytes
-rw-r--r--public/-/emojis/2/black_small_square.pngbin0 -> 541 bytes
-rw-r--r--public/-/emojis/2/black_square_button.pngbin0 -> 1088 bytes
-rw-r--r--public/-/emojis/2/blossom.pngbin0 -> 5324 bytes
-rw-r--r--public/-/emojis/2/blowfish.pngbin0 -> 5323 bytes
-rw-r--r--public/-/emojis/2/blue_book.pngbin0 -> 1104 bytes
-rw-r--r--public/-/emojis/2/blue_car.pngbin0 -> 3663 bytes
-rw-r--r--public/-/emojis/2/blue_heart.pngbin0 -> 2994 bytes
-rw-r--r--public/-/emojis/2/blush.pngbin0 -> 5028 bytes
-rw-r--r--public/-/emojis/2/boar.pngbin0 -> 4472 bytes
-rw-r--r--public/-/emojis/2/bomb.pngbin0 -> 3413 bytes
-rw-r--r--public/-/emojis/2/book.pngbin0 -> 5014 bytes
-rw-r--r--public/-/emojis/2/bookmark.pngbin0 -> 2843 bytes
-rw-r--r--public/-/emojis/2/bookmark_tabs.pngbin0 -> 2553 bytes
-rw-r--r--public/-/emojis/2/books.pngbin0 -> 6804 bytes
-rw-r--r--public/-/emojis/2/boom.pngbin0 -> 6368 bytes
-rw-r--r--public/-/emojis/2/boot.pngbin0 -> 2652 bytes
-rw-r--r--public/-/emojis/2/bouquet.pngbin0 -> 5542 bytes
-rw-r--r--public/-/emojis/2/bow.pngbin0 -> 4683 bytes
-rw-r--r--public/-/emojis/2/bow_and_arrow.pngbin0 -> 3853 bytes
-rw-r--r--public/-/emojis/2/bow_tone1.pngbin0 -> 4868 bytes
-rw-r--r--public/-/emojis/2/bow_tone2.pngbin0 -> 4758 bytes
-rw-r--r--public/-/emojis/2/bow_tone3.pngbin0 -> 4660 bytes
-rw-r--r--public/-/emojis/2/bow_tone4.pngbin0 -> 4591 bytes
-rw-r--r--public/-/emojis/2/bow_tone5.pngbin0 -> 4676 bytes
-rw-r--r--public/-/emojis/2/bowling.pngbin0 -> 4860 bytes
-rw-r--r--public/-/emojis/2/boxing_glove.pngbin0 -> 2061 bytes
-rw-r--r--public/-/emojis/2/boy.pngbin0 -> 4356 bytes
-rw-r--r--public/-/emojis/2/boy_tone1.pngbin0 -> 4398 bytes
-rw-r--r--public/-/emojis/2/boy_tone2.pngbin0 -> 4319 bytes
-rw-r--r--public/-/emojis/2/boy_tone3.pngbin0 -> 4210 bytes
-rw-r--r--public/-/emojis/2/boy_tone4.pngbin0 -> 4045 bytes
-rw-r--r--public/-/emojis/2/boy_tone5.pngbin0 -> 4077 bytes
-rw-r--r--public/-/emojis/2/bread.pngbin0 -> 3361 bytes
-rw-r--r--public/-/emojis/2/bride_with_veil.pngbin0 -> 6663 bytes
-rw-r--r--public/-/emojis/2/bride_with_veil_tone1.pngbin0 -> 6669 bytes
-rw-r--r--public/-/emojis/2/bride_with_veil_tone2.pngbin0 -> 6360 bytes
-rw-r--r--public/-/emojis/2/bride_with_veil_tone3.pngbin0 -> 6513 bytes
-rw-r--r--public/-/emojis/2/bride_with_veil_tone4.pngbin0 -> 6409 bytes
-rw-r--r--public/-/emojis/2/bride_with_veil_tone5.pngbin0 -> 6437 bytes
-rw-r--r--public/-/emojis/2/bridge_at_night.pngbin0 -> 6752 bytes
-rw-r--r--public/-/emojis/2/briefcase.pngbin0 -> 2680 bytes
-rw-r--r--public/-/emojis/2/broken_heart.pngbin0 -> 3597 bytes
-rw-r--r--public/-/emojis/2/bug.pngbin0 -> 4362 bytes
-rw-r--r--public/-/emojis/2/bulb.pngbin0 -> 3532 bytes
-rw-r--r--public/-/emojis/2/bullettrain_front.pngbin0 -> 3061 bytes
-rw-r--r--public/-/emojis/2/bullettrain_side.pngbin0 -> 3117 bytes
-rw-r--r--public/-/emojis/2/burrito.pngbin0 -> 5742 bytes
-rw-r--r--public/-/emojis/2/bus.pngbin0 -> 3327 bytes
-rw-r--r--public/-/emojis/2/busstop.pngbin0 -> 3629 bytes
-rw-r--r--public/-/emojis/2/bust_in_silhouette.pngbin0 -> 1339 bytes
-rw-r--r--public/-/emojis/2/busts_in_silhouette.pngbin0 -> 1757 bytes
-rw-r--r--public/-/emojis/2/butterfly.pngbin0 -> 6362 bytes
-rw-r--r--public/-/emojis/2/cactus.pngbin0 -> 4517 bytes
-rw-r--r--public/-/emojis/2/cake.pngbin0 -> 4393 bytes
-rw-r--r--public/-/emojis/2/calendar.pngbin0 -> 3694 bytes
-rw-r--r--public/-/emojis/2/calendar_spiral.pngbin0 -> 5551 bytes
-rw-r--r--public/-/emojis/2/call_me.pngbin0 -> 3666 bytes
-rw-r--r--public/-/emojis/2/call_me_tone1.pngbin0 -> 3936 bytes
-rw-r--r--public/-/emojis/2/call_me_tone2.pngbin0 -> 4040 bytes
-rw-r--r--public/-/emojis/2/call_me_tone3.pngbin0 -> 3973 bytes
-rw-r--r--public/-/emojis/2/call_me_tone4.pngbin0 -> 3546 bytes
-rw-r--r--public/-/emojis/2/call_me_tone5.pngbin0 -> 3808 bytes
-rw-r--r--public/-/emojis/2/calling.pngbin0 -> 3136 bytes
-rw-r--r--public/-/emojis/2/camel.pngbin0 -> 3951 bytes
-rw-r--r--public/-/emojis/2/camera.pngbin0 -> 4170 bytes
-rw-r--r--public/-/emojis/2/camera_with_flash.pngbin0 -> 5079 bytes
-rw-r--r--public/-/emojis/2/camping.pngbin0 -> 4810 bytes
-rw-r--r--public/-/emojis/2/cancer.pngbin0 -> 5088 bytes
-rw-r--r--public/-/emojis/2/candle.pngbin0 -> 2797 bytes
-rw-r--r--public/-/emojis/2/candy.pngbin0 -> 3955 bytes
-rw-r--r--public/-/emojis/2/canoe.pngbin0 -> 2689 bytes
-rw-r--r--public/-/emojis/2/capital_abcd.pngbin0 -> 3330 bytes
-rw-r--r--public/-/emojis/2/capricorn.pngbin0 -> 4493 bytes
-rw-r--r--public/-/emojis/2/card_box.pngbin0 -> 1948 bytes
-rw-r--r--public/-/emojis/2/card_index.pngbin0 -> 3953 bytes
-rw-r--r--public/-/emojis/2/carousel_horse.pngbin0 -> 5794 bytes
-rw-r--r--public/-/emojis/2/carrot.pngbin0 -> 2795 bytes
-rw-r--r--public/-/emojis/2/cartwheel.pngbin0 -> 2970 bytes
-rw-r--r--public/-/emojis/2/cartwheel_tone1.pngbin0 -> 3043 bytes
-rw-r--r--public/-/emojis/2/cartwheel_tone2.pngbin0 -> 2979 bytes
-rw-r--r--public/-/emojis/2/cartwheel_tone3.pngbin0 -> 2968 bytes
-rw-r--r--public/-/emojis/2/cartwheel_tone4.pngbin0 -> 3002 bytes
-rw-r--r--public/-/emojis/2/cartwheel_tone5.pngbin0 -> 3012 bytes
-rw-r--r--public/-/emojis/2/cat.pngbin0 -> 4175 bytes
-rw-r--r--public/-/emojis/2/cat2.pngbin0 -> 3261 bytes
-rw-r--r--public/-/emojis/2/cd.pngbin0 -> 5270 bytes
-rw-r--r--public/-/emojis/2/chains.pngbin0 -> 4271 bytes
-rw-r--r--public/-/emojis/2/champagne.pngbin0 -> 3479 bytes
-rw-r--r--public/-/emojis/2/champagne_glass.pngbin0 -> 5376 bytes
-rw-r--r--public/-/emojis/2/chart.pngbin0 -> 4004 bytes
-rw-r--r--public/-/emojis/2/chart_with_downwards_trend.pngbin0 -> 4033 bytes
-rw-r--r--public/-/emojis/2/chart_with_upwards_trend.pngbin0 -> 4222 bytes
-rw-r--r--public/-/emojis/2/checkered_flag.pngbin0 -> 5404 bytes
-rw-r--r--public/-/emojis/2/cheese.pngbin0 -> 3157 bytes
-rw-r--r--public/-/emojis/2/cherries.pngbin0 -> 3910 bytes
-rw-r--r--public/-/emojis/2/cherry_blossom.pngbin0 -> 3387 bytes
-rw-r--r--public/-/emojis/2/chestnut.pngbin0 -> 4084 bytes
-rw-r--r--public/-/emojis/2/chicken.pngbin0 -> 3936 bytes
-rw-r--r--public/-/emojis/2/children_crossing.pngbin0 -> 3964 bytes
-rw-r--r--public/-/emojis/2/chipmunk.pngbin0 -> 4676 bytes
-rw-r--r--public/-/emojis/2/chocolate_bar.pngbin0 -> 4559 bytes
-rw-r--r--public/-/emojis/2/christmas_tree.pngbin0 -> 5452 bytes
-rw-r--r--public/-/emojis/2/church.pngbin0 -> 3873 bytes
-rw-r--r--public/-/emojis/2/cinema.pngbin0 -> 2555 bytes
-rw-r--r--public/-/emojis/2/circus_tent.pngbin0 -> 5116 bytes
-rw-r--r--public/-/emojis/2/city_dusk.pngbin0 -> 5760 bytes
-rw-r--r--public/-/emojis/2/city_sunset.pngbin0 -> 6407 bytes
-rw-r--r--public/-/emojis/2/cityscape.pngbin0 -> 5902 bytes
-rw-r--r--public/-/emojis/2/cl.pngbin0 -> 2540 bytes
-rw-r--r--public/-/emojis/2/clap.pngbin0 -> 4650 bytes
-rw-r--r--public/-/emojis/2/clap_tone1.pngbin0 -> 5025 bytes
-rw-r--r--public/-/emojis/2/clap_tone2.pngbin0 -> 4966 bytes
-rw-r--r--public/-/emojis/2/clap_tone3.pngbin0 -> 5007 bytes
-rw-r--r--public/-/emojis/2/clap_tone4.pngbin0 -> 4635 bytes
-rw-r--r--public/-/emojis/2/clap_tone5.pngbin0 -> 4828 bytes
-rw-r--r--public/-/emojis/2/clapper.pngbin0 -> 3826 bytes
-rw-r--r--public/-/emojis/2/classical_building.pngbin0 -> 3736 bytes
-rw-r--r--public/-/emojis/2/clipboard.pngbin0 -> 1924 bytes
-rw-r--r--public/-/emojis/2/clock.pngbin0 -> 4974 bytes
-rw-r--r--public/-/emojis/2/clock1.pngbin0 -> 4232 bytes
-rw-r--r--public/-/emojis/2/clock10.pngbin0 -> 4296 bytes
-rw-r--r--public/-/emojis/2/clock1030.pngbin0 -> 4284 bytes
-rw-r--r--public/-/emojis/2/clock11.pngbin0 -> 4176 bytes
-rw-r--r--public/-/emojis/2/clock1130.pngbin0 -> 4210 bytes
-rw-r--r--public/-/emojis/2/clock12.pngbin0 -> 4045 bytes
-rw-r--r--public/-/emojis/2/clock1230.pngbin0 -> 4225 bytes
-rw-r--r--public/-/emojis/2/clock130.pngbin0 -> 4250 bytes
-rw-r--r--public/-/emojis/2/clock2.pngbin0 -> 4238 bytes
-rw-r--r--public/-/emojis/2/clock230.pngbin0 -> 4203 bytes
-rw-r--r--public/-/emojis/2/clock3.pngbin0 -> 4058 bytes
-rw-r--r--public/-/emojis/2/clock330.pngbin0 -> 4248 bytes
-rw-r--r--public/-/emojis/2/clock4.pngbin0 -> 4299 bytes
-rw-r--r--public/-/emojis/2/clock430.pngbin0 -> 4257 bytes
-rw-r--r--public/-/emojis/2/clock5.pngbin0 -> 4205 bytes
-rw-r--r--public/-/emojis/2/clock530.pngbin0 -> 4176 bytes
-rw-r--r--public/-/emojis/2/clock6.pngbin0 -> 4078 bytes
-rw-r--r--public/-/emojis/2/clock630.pngbin0 -> 4182 bytes
-rw-r--r--public/-/emojis/2/clock7.pngbin0 -> 4197 bytes
-rw-r--r--public/-/emojis/2/clock730.pngbin0 -> 4235 bytes
-rw-r--r--public/-/emojis/2/clock8.pngbin0 -> 4219 bytes
-rw-r--r--public/-/emojis/2/clock830.pngbin0 -> 4216 bytes
-rw-r--r--public/-/emojis/2/clock9.pngbin0 -> 4065 bytes
-rw-r--r--public/-/emojis/2/clock930.pngbin0 -> 4240 bytes
-rw-r--r--public/-/emojis/2/closed_book.pngbin0 -> 1117 bytes
-rw-r--r--public/-/emojis/2/closed_lock_with_key.pngbin0 -> 3986 bytes
-rw-r--r--public/-/emojis/2/closed_umbrella.pngbin0 -> 3932 bytes
-rw-r--r--public/-/emojis/2/cloud.pngbin0 -> 1704 bytes
-rw-r--r--public/-/emojis/2/cloud_lightning.pngbin0 -> 2647 bytes
-rw-r--r--public/-/emojis/2/cloud_rain.pngbin0 -> 2700 bytes
-rw-r--r--public/-/emojis/2/cloud_snow.pngbin0 -> 2918 bytes
-rw-r--r--public/-/emojis/2/cloud_tornado.pngbin0 -> 4640 bytes
-rw-r--r--public/-/emojis/2/clown.pngbin0 -> 5987 bytes
-rw-r--r--public/-/emojis/2/clubs.pngbin0 -> 2188 bytes
-rw-r--r--public/-/emojis/2/cocktail.pngbin0 -> 4333 bytes
-rw-r--r--public/-/emojis/2/coffee.pngbin0 -> 4816 bytes
-rw-r--r--public/-/emojis/2/coffin.pngbin0 -> 4583 bytes
-rw-r--r--public/-/emojis/2/cold_sweat.pngbin0 -> 5402 bytes
-rw-r--r--public/-/emojis/2/comet.pngbin0 -> 5048 bytes
-rw-r--r--public/-/emojis/2/compression.pngbin0 -> 3724 bytes
-rw-r--r--public/-/emojis/2/computer.pngbin0 -> 3228 bytes
-rw-r--r--public/-/emojis/2/confetti_ball.pngbin0 -> 6051 bytes
-rw-r--r--public/-/emojis/2/confounded.pngbin0 -> 5187 bytes
-rw-r--r--public/-/emojis/2/confused.pngbin0 -> 4642 bytes
-rw-r--r--public/-/emojis/2/congratulations.pngbin0 -> 4555 bytes
-rw-r--r--public/-/emojis/2/construction.pngbin0 -> 3478 bytes
-rw-r--r--public/-/emojis/2/construction_site.pngbin0 -> 4264 bytes
-rw-r--r--public/-/emojis/2/construction_worker.pngbin0 -> 4896 bytes
-rw-r--r--public/-/emojis/2/construction_worker_tone1.pngbin0 -> 5067 bytes
-rw-r--r--public/-/emojis/2/construction_worker_tone2.pngbin0 -> 4795 bytes
-rw-r--r--public/-/emojis/2/construction_worker_tone3.pngbin0 -> 4830 bytes
-rw-r--r--public/-/emojis/2/construction_worker_tone4.pngbin0 -> 4730 bytes
-rw-r--r--public/-/emojis/2/construction_worker_tone5.pngbin0 -> 4717 bytes
-rw-r--r--public/-/emojis/2/control_knobs.pngbin0 -> 5684 bytes
-rw-r--r--public/-/emojis/2/convenience_store.pngbin0 -> 2698 bytes
-rw-r--r--public/-/emojis/2/cookie.pngbin0 -> 5938 bytes
-rw-r--r--public/-/emojis/2/cooking.pngbin0 -> 4770 bytes
-rw-r--r--public/-/emojis/2/cool.pngbin0 -> 2875 bytes
-rw-r--r--public/-/emojis/2/cop.pngbin0 -> 6019 bytes
-rw-r--r--public/-/emojis/2/cop_tone1.pngbin0 -> 6169 bytes
-rw-r--r--public/-/emojis/2/cop_tone2.pngbin0 -> 5920 bytes
-rw-r--r--public/-/emojis/2/cop_tone3.pngbin0 -> 5868 bytes
-rw-r--r--public/-/emojis/2/cop_tone4.pngbin0 -> 5772 bytes
-rw-r--r--public/-/emojis/2/cop_tone5.pngbin0 -> 5780 bytes
-rw-r--r--public/-/emojis/2/copyright.pngbin0 -> 5128 bytes
-rw-r--r--public/-/emojis/2/corn.pngbin0 -> 5563 bytes
-rw-r--r--public/-/emojis/2/couch.pngbin0 -> 2475 bytes
-rw-r--r--public/-/emojis/2/couple.pngbin0 -> 5173 bytes
-rw-r--r--public/-/emojis/2/couple_mm.pngbin0 -> 5810 bytes
-rw-r--r--public/-/emojis/2/couple_with_heart.pngbin0 -> 6553 bytes
-rw-r--r--public/-/emojis/2/couple_ww.pngbin0 -> 6149 bytes
-rw-r--r--public/-/emojis/2/couplekiss.pngbin0 -> 5525 bytes
-rw-r--r--public/-/emojis/2/cow.pngbin0 -> 4007 bytes
-rw-r--r--public/-/emojis/2/cow2.pngbin0 -> 4363 bytes
-rw-r--r--public/-/emojis/2/cowboy.pngbin0 -> 5300 bytes
-rw-r--r--public/-/emojis/2/crab.pngbin0 -> 4705 bytes
-rw-r--r--public/-/emojis/2/crayon.pngbin0 -> 2966 bytes
-rw-r--r--public/-/emojis/2/credit_card.pngbin0 -> 1178 bytes
-rw-r--r--public/-/emojis/2/crescent_moon.pngbin0 -> 2074 bytes
-rw-r--r--public/-/emojis/2/cricket.pngbin0 -> 3508 bytes
-rw-r--r--public/-/emojis/2/crocodile.pngbin0 -> 4846 bytes
-rw-r--r--public/-/emojis/2/croissant.pngbin0 -> 5061 bytes
-rw-r--r--public/-/emojis/2/cross.pngbin0 -> 1516 bytes
-rw-r--r--public/-/emojis/2/crossed_flags.pngbin0 -> 4828 bytes
-rw-r--r--public/-/emojis/2/crossed_swords.pngbin0 -> 4299 bytes
-rw-r--r--public/-/emojis/2/crown.pngbin0 -> 5591 bytes
-rw-r--r--public/-/emojis/2/cruise_ship.pngbin0 -> 4569 bytes
-rw-r--r--public/-/emojis/2/cry.pngbin0 -> 5234 bytes
-rw-r--r--public/-/emojis/2/crying_cat_face.pngbin0 -> 4784 bytes
-rw-r--r--public/-/emojis/2/crystal_ball.pngbin0 -> 6021 bytes
-rw-r--r--public/-/emojis/2/cucumber.pngbin0 -> 3510 bytes
-rw-r--r--public/-/emojis/2/cupid.pngbin0 -> 3724 bytes
-rw-r--r--public/-/emojis/2/curly_loop.pngbin0 -> 3415 bytes
-rw-r--r--public/-/emojis/2/currency_exchange.pngbin0 -> 4497 bytes
-rw-r--r--public/-/emojis/2/curry.pngbin0 -> 5423 bytes
-rw-r--r--public/-/emojis/2/custard.pngbin0 -> 4078 bytes
-rw-r--r--public/-/emojis/2/customs.pngbin0 -> 3252 bytes
-rw-r--r--public/-/emojis/2/cyclone.pngbin0 -> 2952 bytes
-rw-r--r--public/-/emojis/2/dagger.pngbin0 -> 3563 bytes
-rw-r--r--public/-/emojis/2/dancer.pngbin0 -> 4630 bytes
-rw-r--r--public/-/emojis/2/dancer_tone1.pngbin0 -> 4815 bytes
-rw-r--r--public/-/emojis/2/dancer_tone2.pngbin0 -> 4725 bytes
-rw-r--r--public/-/emojis/2/dancer_tone3.pngbin0 -> 4651 bytes
-rw-r--r--public/-/emojis/2/dancer_tone4.pngbin0 -> 4627 bytes
-rw-r--r--public/-/emojis/2/dancer_tone5.pngbin0 -> 4671 bytes
-rw-r--r--public/-/emojis/2/dancers.pngbin0 -> 7024 bytes
-rw-r--r--public/-/emojis/2/dango.pngbin0 -> 2521 bytes
-rw-r--r--public/-/emojis/2/dark_sunglasses.pngbin0 -> 2077 bytes
-rw-r--r--public/-/emojis/2/dart.pngbin0 -> 5170 bytes
-rw-r--r--public/-/emojis/2/dash.pngbin0 -> 3690 bytes
-rw-r--r--public/-/emojis/2/date.pngbin0 -> 2660 bytes
-rw-r--r--public/-/emojis/2/deciduous_tree.pngbin0 -> 3211 bytes
-rw-r--r--public/-/emojis/2/deer.pngbin0 -> 3056 bytes
-rw-r--r--public/-/emojis/2/department_store.pngbin0 -> 4122 bytes
-rw-r--r--public/-/emojis/2/desert.pngbin0 -> 4523 bytes
-rw-r--r--public/-/emojis/2/desktop.pngbin0 -> 3258 bytes
-rw-r--r--public/-/emojis/2/diamond_shape_with_a_dot_inside.pngbin0 -> 3773 bytes
-rw-r--r--public/-/emojis/2/diamonds.pngbin0 -> 1936 bytes
-rw-r--r--public/-/emojis/2/disappointed.pngbin0 -> 4443 bytes
-rw-r--r--public/-/emojis/2/disappointed_relieved.pngbin0 -> 5316 bytes
-rw-r--r--public/-/emojis/2/dividers.pngbin0 -> 1221 bytes
-rw-r--r--public/-/emojis/2/dizzy.pngbin0 -> 3519 bytes
-rw-r--r--public/-/emojis/2/dizzy_face.pngbin0 -> 5424 bytes
-rw-r--r--public/-/emojis/2/do_not_litter.pngbin0 -> 5991 bytes
-rw-r--r--public/-/emojis/2/dog.pngbin0 -> 3819 bytes
-rw-r--r--public/-/emojis/2/dog2.pngbin0 -> 4299 bytes
-rw-r--r--public/-/emojis/2/dollar.pngbin0 -> 2400 bytes
-rw-r--r--public/-/emojis/2/dolls.pngbin0 -> 6570 bytes
-rw-r--r--public/-/emojis/2/dolphin.pngbin0 -> 3429 bytes
-rw-r--r--public/-/emojis/2/door.pngbin0 -> 1048 bytes
-rw-r--r--public/-/emojis/2/doughnut.pngbin0 -> 5066 bytes
-rw-r--r--public/-/emojis/2/dove.pngbin0 -> 3487 bytes
-rw-r--r--public/-/emojis/2/dragon.pngbin0 -> 5676 bytes
-rw-r--r--public/-/emojis/2/dragon_face.pngbin0 -> 5024 bytes
-rw-r--r--public/-/emojis/2/dress.pngbin0 -> 2376 bytes
-rw-r--r--public/-/emojis/2/dromedary_camel.pngbin0 -> 3406 bytes
-rw-r--r--public/-/emojis/2/drooling_face.pngbin0 -> 5286 bytes
-rw-r--r--public/-/emojis/2/droplet.pngbin0 -> 1614 bytes
-rw-r--r--public/-/emojis/2/drum.pngbin0 -> 5433 bytes
-rw-r--r--public/-/emojis/2/duck.pngbin0 -> 3436 bytes
-rw-r--r--public/-/emojis/2/dvd.pngbin0 -> 5257 bytes
-rw-r--r--public/-/emojis/2/e-mail.pngbin0 -> 2597 bytes
-rw-r--r--public/-/emojis/2/eagle.pngbin0 -> 3506 bytes
-rw-r--r--public/-/emojis/2/ear.pngbin0 -> 3801 bytes
-rw-r--r--public/-/emojis/2/ear_of_rice.pngbin0 -> 3601 bytes
-rw-r--r--public/-/emojis/2/ear_tone1.pngbin0 -> 3643 bytes
-rw-r--r--public/-/emojis/2/ear_tone2.pngbin0 -> 3659 bytes
-rw-r--r--public/-/emojis/2/ear_tone3.pngbin0 -> 3702 bytes
-rw-r--r--public/-/emojis/2/ear_tone4.pngbin0 -> 3365 bytes
-rw-r--r--public/-/emojis/2/ear_tone5.pngbin0 -> 3432 bytes
-rw-r--r--public/-/emojis/2/earth_africa.pngbin0 -> 6073 bytes
-rw-r--r--public/-/emojis/2/earth_americas.pngbin0 -> 5651 bytes
-rw-r--r--public/-/emojis/2/earth_asia.pngbin0 -> 6108 bytes
-rw-r--r--public/-/emojis/2/egg.pngbin0 -> 2340 bytes
-rw-r--r--public/-/emojis/2/eggplant.pngbin0 -> 2665 bytes
-rw-r--r--public/-/emojis/2/eight.pngbin0 -> 2697 bytes
-rw-r--r--public/-/emojis/2/eight_pointed_black_star.pngbin0 -> 2657 bytes
-rw-r--r--public/-/emojis/2/eight_spoked_asterisk.pngbin0 -> 2695 bytes
-rw-r--r--public/-/emojis/2/eject.pngbin0 -> 1881 bytes
-rw-r--r--public/-/emojis/2/electric_plug.pngbin0 -> 3440 bytes
-rw-r--r--public/-/emojis/2/elephant.pngbin0 -> 3367 bytes
-rw-r--r--public/-/emojis/2/emojis.json10766
-rw-r--r--public/-/emojis/2/end.pngbin0 -> 2763 bytes
-rw-r--r--public/-/emojis/2/envelope.pngbin0 -> 2349 bytes
-rw-r--r--public/-/emojis/2/envelope_with_arrow.pngbin0 -> 2710 bytes
-rw-r--r--public/-/emojis/2/euro.pngbin0 -> 2357 bytes
-rw-r--r--public/-/emojis/2/european_castle.pngbin0 -> 4038 bytes
-rw-r--r--public/-/emojis/2/european_post_office.pngbin0 -> 3735 bytes
-rw-r--r--public/-/emojis/2/evergreen_tree.pngbin0 -> 4038 bytes
-rw-r--r--public/-/emojis/2/exclamation.pngbin0 -> 1320 bytes
-rw-r--r--public/-/emojis/2/expressionless.pngbin0 -> 3974 bytes
-rw-r--r--public/-/emojis/2/eye.pngbin0 -> 4113 bytes
-rw-r--r--public/-/emojis/2/eye_in_speech_bubble.pngbin0 -> 4306 bytes
-rw-r--r--public/-/emojis/2/eyeglasses.pngbin0 -> 2289 bytes
-rw-r--r--public/-/emojis/2/eyes.pngbin0 -> 4038 bytes
-rw-r--r--public/-/emojis/2/face_palm.pngbin0 -> 5371 bytes
-rw-r--r--public/-/emojis/2/face_palm_tone1.pngbin0 -> 5569 bytes
-rw-r--r--public/-/emojis/2/face_palm_tone2.pngbin0 -> 5362 bytes
-rw-r--r--public/-/emojis/2/face_palm_tone3.pngbin0 -> 5288 bytes
-rw-r--r--public/-/emojis/2/face_palm_tone4.pngbin0 -> 5135 bytes
-rw-r--r--public/-/emojis/2/face_palm_tone5.pngbin0 -> 5136 bytes
-rw-r--r--public/-/emojis/2/factory.pngbin0 -> 3573 bytes
-rw-r--r--public/-/emojis/2/fallen_leaf.pngbin0 -> 4567 bytes
-rw-r--r--public/-/emojis/2/family.pngbin0 -> 6948 bytes
-rw-r--r--public/-/emojis/2/family_mmb.pngbin0 -> 6105 bytes
-rw-r--r--public/-/emojis/2/family_mmbb.pngbin0 -> 7068 bytes
-rw-r--r--public/-/emojis/2/family_mmg.pngbin0 -> 6193 bytes
-rw-r--r--public/-/emojis/2/family_mmgb.pngbin0 -> 7166 bytes
-rw-r--r--public/-/emojis/2/family_mmgg.pngbin0 -> 7227 bytes
-rw-r--r--public/-/emojis/2/family_mwbb.pngbin0 -> 7391 bytes
-rw-r--r--public/-/emojis/2/family_mwg.pngbin0 -> 6476 bytes
-rw-r--r--public/-/emojis/2/family_mwgb.pngbin0 -> 7491 bytes
-rw-r--r--public/-/emojis/2/family_mwgg.pngbin0 -> 7567 bytes
-rw-r--r--public/-/emojis/2/family_wwb.pngbin0 -> 6449 bytes
-rw-r--r--public/-/emojis/2/family_wwbb.pngbin0 -> 7388 bytes
-rw-r--r--public/-/emojis/2/family_wwg.pngbin0 -> 6464 bytes
-rw-r--r--public/-/emojis/2/family_wwgb.pngbin0 -> 7472 bytes
-rw-r--r--public/-/emojis/2/family_wwgg.pngbin0 -> 7559 bytes
-rw-r--r--public/-/emojis/2/fast_forward.pngbin0 -> 2175 bytes
-rw-r--r--public/-/emojis/2/fax.pngbin0 -> 4402 bytes
-rw-r--r--public/-/emojis/2/fearful.pngbin0 -> 5029 bytes
-rw-r--r--public/-/emojis/2/feet.pngbin0 -> 2176 bytes
-rw-r--r--public/-/emojis/2/fencer.pngbin0 -> 4332 bytes
-rw-r--r--public/-/emojis/2/ferris_wheel.pngbin0 -> 7812 bytes
-rw-r--r--public/-/emojis/2/ferry.pngbin0 -> 4406 bytes
-rw-r--r--public/-/emojis/2/field_hockey.pngbin0 -> 3521 bytes
-rw-r--r--public/-/emojis/2/file_cabinet.pngbin0 -> 1937 bytes
-rw-r--r--public/-/emojis/2/file_folder.pngbin0 -> 1645 bytes
-rw-r--r--public/-/emojis/2/film_frames.pngbin0 -> 3374 bytes
-rw-r--r--public/-/emojis/2/fingers_crossed.pngbin0 -> 3592 bytes
-rw-r--r--public/-/emojis/2/fingers_crossed_tone1.pngbin0 -> 3952 bytes
-rw-r--r--public/-/emojis/2/fingers_crossed_tone2.pngbin0 -> 4026 bytes
-rw-r--r--public/-/emojis/2/fingers_crossed_tone3.pngbin0 -> 3880 bytes
-rw-r--r--public/-/emojis/2/fingers_crossed_tone4.pngbin0 -> 3518 bytes
-rw-r--r--public/-/emojis/2/fingers_crossed_tone5.pngbin0 -> 3678 bytes
-rw-r--r--public/-/emojis/2/fire.pngbin0 -> 3744 bytes
-rw-r--r--public/-/emojis/2/fire_engine.pngbin0 -> 3792 bytes
-rw-r--r--public/-/emojis/2/fireworks.pngbin0 -> 9670 bytes
-rw-r--r--public/-/emojis/2/first_place.pngbin0 -> 3269 bytes
-rw-r--r--public/-/emojis/2/first_quarter_moon.pngbin0 -> 3809 bytes
-rw-r--r--public/-/emojis/2/first_quarter_moon_with_face.pngbin0 -> 3386 bytes
-rw-r--r--public/-/emojis/2/fish.pngbin0 -> 3269 bytes
-rw-r--r--public/-/emojis/2/fish_cake.pngbin0 -> 5325 bytes
-rw-r--r--public/-/emojis/2/fishing_pole_and_fish.pngbin0 -> 3633 bytes
-rw-r--r--public/-/emojis/2/fist.pngbin0 -> 4433 bytes
-rw-r--r--public/-/emojis/2/fist_tone1.pngbin0 -> 4893 bytes
-rw-r--r--public/-/emojis/2/fist_tone2.pngbin0 -> 4935 bytes
-rw-r--r--public/-/emojis/2/fist_tone3.pngbin0 -> 4564 bytes
-rw-r--r--public/-/emojis/2/fist_tone4.pngbin0 -> 4289 bytes
-rw-r--r--public/-/emojis/2/fist_tone5.pngbin0 -> 4299 bytes
-rw-r--r--public/-/emojis/2/five.pngbin0 -> 2379 bytes
-rw-r--r--public/-/emojis/2/flag_ac.pngbin0 -> 5417 bytes
-rw-r--r--public/-/emojis/2/flag_ad.pngbin0 -> 3679 bytes
-rw-r--r--public/-/emojis/2/flag_ae.pngbin0 -> 2260 bytes
-rw-r--r--public/-/emojis/2/flag_af.pngbin0 -> 3840 bytes
-rw-r--r--public/-/emojis/2/flag_ag.pngbin0 -> 4348 bytes
-rw-r--r--public/-/emojis/2/flag_ai.pngbin0 -> 4868 bytes
-rw-r--r--public/-/emojis/2/flag_al.pngbin0 -> 4244 bytes
-rw-r--r--public/-/emojis/2/flag_am.pngbin0 -> 3180 bytes
-rw-r--r--public/-/emojis/2/flag_ao.pngbin0 -> 3976 bytes
-rw-r--r--public/-/emojis/2/flag_aq.pngbin0 -> 3687 bytes
-rw-r--r--public/-/emojis/2/flag_ar.pngbin0 -> 3575 bytes
-rw-r--r--public/-/emojis/2/flag_as.pngbin0 -> 4483 bytes
-rw-r--r--public/-/emojis/2/flag_at.pngbin0 -> 3109 bytes
-rw-r--r--public/-/emojis/2/flag_au.pngbin0 -> 4377 bytes
-rw-r--r--public/-/emojis/2/flag_aw.pngbin0 -> 4458 bytes
-rw-r--r--public/-/emojis/2/flag_ax.pngbin0 -> 4073 bytes
-rw-r--r--public/-/emojis/2/flag_az.pngbin0 -> 3840 bytes
-rw-r--r--public/-/emojis/2/flag_ba.pngbin0 -> 4022 bytes
-rw-r--r--public/-/emojis/2/flag_bb.pngbin0 -> 3240 bytes
-rw-r--r--public/-/emojis/2/flag_bd.pngbin0 -> 2956 bytes
-rw-r--r--public/-/emojis/2/flag_be.pngbin0 -> 2304 bytes
-rw-r--r--public/-/emojis/2/flag_bf.pngbin0 -> 3029 bytes
-rw-r--r--public/-/emojis/2/flag_bg.pngbin0 -> 3158 bytes
-rw-r--r--public/-/emojis/2/flag_bh.pngbin0 -> 3494 bytes
-rw-r--r--public/-/emojis/2/flag_bi.pngbin0 -> 5293 bytes
-rw-r--r--public/-/emojis/2/flag_bj.pngbin0 -> 2974 bytes
-rw-r--r--public/-/emojis/2/flag_bl.pngbin0 -> 5101 bytes
-rw-r--r--public/-/emojis/2/flag_black.pngbin0 -> 2831 bytes
-rw-r--r--public/-/emojis/2/flag_bm.pngbin0 -> 5562 bytes
-rw-r--r--public/-/emojis/2/flag_bn.pngbin0 -> 4677 bytes
-rw-r--r--public/-/emojis/2/flag_bo.pngbin0 -> 3130 bytes
-rw-r--r--public/-/emojis/2/flag_bq.pngbin0 -> 4110 bytes
-rw-r--r--public/-/emojis/2/flag_br.pngbin0 -> 4522 bytes
-rw-r--r--public/-/emojis/2/flag_bs.pngbin0 -> 3170 bytes
-rw-r--r--public/-/emojis/2/flag_bt.pngbin0 -> 4770 bytes
-rw-r--r--public/-/emojis/2/flag_bv.pngbin0 -> 4312 bytes
-rw-r--r--public/-/emojis/2/flag_bw.pngbin0 -> 3981 bytes
-rw-r--r--public/-/emojis/2/flag_by.pngbin0 -> 3969 bytes
-rw-r--r--public/-/emojis/2/flag_bz.pngbin0 -> 5952 bytes
-rw-r--r--public/-/emojis/2/flag_ca.pngbin0 -> 2441 bytes
-rw-r--r--public/-/emojis/2/flag_cc.pngbin0 -> 3093 bytes
-rw-r--r--public/-/emojis/2/flag_cd.pngbin0 -> 4558 bytes
-rw-r--r--public/-/emojis/2/flag_cf.pngbin0 -> 3796 bytes
-rw-r--r--public/-/emojis/2/flag_cg.pngbin0 -> 3593 bytes
-rw-r--r--public/-/emojis/2/flag_ch.pngbin0 -> 1830 bytes
-rw-r--r--public/-/emojis/2/flag_ci.pngbin0 -> 2322 bytes
-rw-r--r--public/-/emojis/2/flag_ck.pngbin0 -> 5675 bytes
-rw-r--r--public/-/emojis/2/flag_cl.pngbin0 -> 3265 bytes
-rw-r--r--public/-/emojis/2/flag_cm.pngbin0 -> 3159 bytes
-rw-r--r--public/-/emojis/2/flag_cn.pngbin0 -> 3457 bytes
-rw-r--r--public/-/emojis/2/flag_co.pngbin0 -> 3468 bytes
-rw-r--r--public/-/emojis/2/flag_cp.pngbin0 -> 2564 bytes
-rw-r--r--public/-/emojis/2/flag_cr.pngbin0 -> 3967 bytes
-rw-r--r--public/-/emojis/2/flag_cu.pngbin0 -> 4313 bytes
-rw-r--r--public/-/emojis/2/flag_cv.pngbin0 -> 4356 bytes
-rw-r--r--public/-/emojis/2/flag_cw.pngbin0 -> 3609 bytes
-rw-r--r--public/-/emojis/2/flag_cx.pngbin0 -> 4590 bytes
-rw-r--r--public/-/emojis/2/flag_cy.pngbin0 -> 3018 bytes
-rw-r--r--public/-/emojis/2/flag_cz.pngbin0 -> 3434 bytes
-rw-r--r--public/-/emojis/2/flag_de.pngbin0 -> 2217 bytes
-rw-r--r--public/-/emojis/2/flag_dg.pngbin0 -> 8831 bytes
-rw-r--r--public/-/emojis/2/flag_dj.pngbin0 -> 3765 bytes
-rw-r--r--public/-/emojis/2/flag_dk.pngbin0 -> 3547 bytes
-rw-r--r--public/-/emojis/2/flag_dm.pngbin0 -> 4407 bytes
-rw-r--r--public/-/emojis/2/flag_do.pngbin0 -> 3628 bytes
-rw-r--r--public/-/emojis/2/flag_dz.pngbin0 -> 3080 bytes
-rw-r--r--public/-/emojis/2/flag_ea.pngbin0 -> 3922 bytes
-rw-r--r--public/-/emojis/2/flag_ec.pngbin0 -> 4321 bytes
-rw-r--r--public/-/emojis/2/flag_ee.pngbin0 -> 2601 bytes
-rw-r--r--public/-/emojis/2/flag_eg.pngbin0 -> 2949 bytes
-rw-r--r--public/-/emojis/2/flag_eh.pngbin0 -> 3334 bytes
-rw-r--r--public/-/emojis/2/flag_er.pngbin0 -> 4782 bytes
-rw-r--r--public/-/emojis/2/flag_es.pngbin0 -> 3922 bytes
-rw-r--r--public/-/emojis/2/flag_et.pngbin0 -> 4771 bytes
-rw-r--r--public/-/emojis/2/flag_eu.pngbin0 -> 3474 bytes
-rw-r--r--public/-/emojis/2/flag_fi.pngbin0 -> 3009 bytes
-rw-r--r--public/-/emojis/2/flag_fj.pngbin0 -> 5649 bytes
-rw-r--r--public/-/emojis/2/flag_fk.pngbin0 -> 5268 bytes
-rw-r--r--public/-/emojis/2/flag_fm.pngbin0 -> 3552 bytes
-rw-r--r--public/-/emojis/2/flag_fo.pngbin0 -> 3753 bytes
-rw-r--r--public/-/emojis/2/flag_fr.pngbin0 -> 2564 bytes
-rw-r--r--public/-/emojis/2/flag_ga.pngbin0 -> 3416 bytes
-rw-r--r--public/-/emojis/2/flag_gb.pngbin0 -> 6636 bytes
-rw-r--r--public/-/emojis/2/flag_gd.pngbin0 -> 4878 bytes
-rw-r--r--public/-/emojis/2/flag_ge.pngbin0 -> 3036 bytes
-rw-r--r--public/-/emojis/2/flag_gf.pngbin0 -> 3584 bytes
-rw-r--r--public/-/emojis/2/flag_gg.pngbin0 -> 3414 bytes
-rw-r--r--public/-/emojis/2/flag_gh.pngbin0 -> 3656 bytes
-rw-r--r--public/-/emojis/2/flag_gi.pngbin0 -> 3416 bytes
-rw-r--r--public/-/emojis/2/flag_gl.pngbin0 -> 3523 bytes
-rw-r--r--public/-/emojis/2/flag_gm.pngbin0 -> 4338 bytes
-rw-r--r--public/-/emojis/2/flag_gn.pngbin0 -> 2866 bytes
-rw-r--r--public/-/emojis/2/flag_gp.pngbin0 -> 4367 bytes
-rw-r--r--public/-/emojis/2/flag_gq.pngbin0 -> 3911 bytes
-rw-r--r--public/-/emojis/2/flag_gr.pngbin0 -> 5192 bytes
-rw-r--r--public/-/emojis/2/flag_gs.pngbin0 -> 5561 bytes
-rw-r--r--public/-/emojis/2/flag_gt.pngbin0 -> 3411 bytes
-rw-r--r--public/-/emojis/2/flag_gu.pngbin0 -> 3457 bytes
-rw-r--r--public/-/emojis/2/flag_gw.pngbin0 -> 3274 bytes
-rw-r--r--public/-/emojis/2/flag_gy.pngbin0 -> 4879 bytes
-rw-r--r--public/-/emojis/2/flag_hk.pngbin0 -> 4245 bytes
-rw-r--r--public/-/emojis/2/flag_hm.pngbin0 -> 4377 bytes
-rw-r--r--public/-/emojis/2/flag_hn.pngbin0 -> 3320 bytes
-rw-r--r--public/-/emojis/2/flag_hr.pngbin0 -> 3448 bytes
-rw-r--r--public/-/emojis/2/flag_ht.pngbin0 -> 3418 bytes
-rw-r--r--public/-/emojis/2/flag_hu.pngbin0 -> 3128 bytes
-rw-r--r--public/-/emojis/2/flag_ic.pngbin0 -> 2379 bytes
-rw-r--r--public/-/emojis/2/flag_id.pngbin0 -> 1859 bytes
-rw-r--r--public/-/emojis/2/flag_ie.pngbin0 -> 2580 bytes
-rw-r--r--public/-/emojis/2/flag_il.pngbin0 -> 4462 bytes
-rw-r--r--public/-/emojis/2/flag_im.pngbin0 -> 3823 bytes
-rw-r--r--public/-/emojis/2/flag_in.pngbin0 -> 3492 bytes
-rw-r--r--public/-/emojis/2/flag_io.pngbin0 -> 8831 bytes
-rw-r--r--public/-/emojis/2/flag_iq.pngbin0 -> 3228 bytes
-rw-r--r--public/-/emojis/2/flag_ir.pngbin0 -> 3658 bytes
-rw-r--r--public/-/emojis/2/flag_is.pngbin0 -> 4244 bytes
-rw-r--r--public/-/emojis/2/flag_it.pngbin0 -> 2514 bytes
-rw-r--r--public/-/emojis/2/flag_je.pngbin0 -> 4803 bytes
-rw-r--r--public/-/emojis/2/flag_jm.pngbin0 -> 3939 bytes
-rw-r--r--public/-/emojis/2/flag_jo.pngbin0 -> 3327 bytes
-rw-r--r--public/-/emojis/2/flag_jp.pngbin0 -> 2594 bytes
-rw-r--r--public/-/emojis/2/flag_ke.pngbin0 -> 3724 bytes
-rw-r--r--public/-/emojis/2/flag_kg.pngbin0 -> 4093 bytes
-rw-r--r--public/-/emojis/2/flag_kh.pngbin0 -> 4306 bytes
-rw-r--r--public/-/emojis/2/flag_ki.pngbin0 -> 5861 bytes
-rw-r--r--public/-/emojis/2/flag_km.pngbin0 -> 4561 bytes
-rw-r--r--public/-/emojis/2/flag_kn.pngbin0 -> 4492 bytes
-rw-r--r--public/-/emojis/2/flag_kp.pngbin0 -> 4708 bytes
-rw-r--r--public/-/emojis/2/flag_kr.pngbin0 -> 4606 bytes
-rw-r--r--public/-/emojis/2/flag_kw.pngbin0 -> 3032 bytes
-rw-r--r--public/-/emojis/2/flag_ky.pngbin0 -> 5276 bytes
-rw-r--r--public/-/emojis/2/flag_kz.pngbin0 -> 3942 bytes
-rw-r--r--public/-/emojis/2/flag_la.pngbin0 -> 3789 bytes
-rw-r--r--public/-/emojis/2/flag_lb.pngbin0 -> 4040 bytes
-rw-r--r--public/-/emojis/2/flag_lc.pngbin0 -> 3733 bytes
-rw-r--r--public/-/emojis/2/flag_li.pngbin0 -> 3413 bytes
-rw-r--r--public/-/emojis/2/flag_lk.pngbin0 -> 4954 bytes
-rw-r--r--public/-/emojis/2/flag_lr.pngbin0 -> 5784 bytes
-rw-r--r--public/-/emojis/2/flag_ls.pngbin0 -> 3321 bytes
-rw-r--r--public/-/emojis/2/flag_lt.pngbin0 -> 3317 bytes
-rw-r--r--public/-/emojis/2/flag_lu.pngbin0 -> 2988 bytes
-rw-r--r--public/-/emojis/2/flag_lv.pngbin0 -> 3232 bytes
-rw-r--r--public/-/emojis/2/flag_ly.pngbin0 -> 2954 bytes
-rw-r--r--public/-/emojis/2/flag_ma.pngbin0 -> 3154 bytes
-rw-r--r--public/-/emojis/2/flag_mc.pngbin0 -> 2706 bytes
-rw-r--r--public/-/emojis/2/flag_md.pngbin0 -> 3617 bytes
-rw-r--r--public/-/emojis/2/flag_me.pngbin0 -> 4032 bytes
-rw-r--r--public/-/emojis/2/flag_mf.pngbin0 -> 2564 bytes
-rw-r--r--public/-/emojis/2/flag_mg.pngbin0 -> 2367 bytes
-rw-r--r--public/-/emojis/2/flag_mh.pngbin0 -> 4529 bytes
-rw-r--r--public/-/emojis/2/flag_mk.pngbin0 -> 4370 bytes
-rw-r--r--public/-/emojis/2/flag_ml.pngbin0 -> 3015 bytes
-rw-r--r--public/-/emojis/2/flag_mm.pngbin0 -> 4051 bytes
-rw-r--r--public/-/emojis/2/flag_mn.pngbin0 -> 3514 bytes
-rw-r--r--public/-/emojis/2/flag_mo.pngbin0 -> 3509 bytes
-rw-r--r--public/-/emojis/2/flag_mp.pngbin0 -> 4857 bytes
-rw-r--r--public/-/emojis/2/flag_mq.pngbin0 -> 5397 bytes
-rw-r--r--public/-/emojis/2/flag_mr.pngbin0 -> 3973 bytes
-rw-r--r--public/-/emojis/2/flag_ms.pngbin0 -> 4904 bytes
-rw-r--r--public/-/emojis/2/flag_mt.pngbin0 -> 2759 bytes
-rw-r--r--public/-/emojis/2/flag_mu.pngbin0 -> 3611 bytes
-rw-r--r--public/-/emojis/2/flag_mv.pngbin0 -> 3560 bytes
-rw-r--r--public/-/emojis/2/flag_mw.pngbin0 -> 3658 bytes
-rw-r--r--public/-/emojis/2/flag_mx.pngbin0 -> 3475 bytes
-rw-r--r--public/-/emojis/2/flag_my.pngbin0 -> 6217 bytes
-rw-r--r--public/-/emojis/2/flag_mz.pngbin0 -> 4380 bytes
-rw-r--r--public/-/emojis/2/flag_na.pngbin0 -> 4842 bytes
-rw-r--r--public/-/emojis/2/flag_nc.pngbin0 -> 4035 bytes
-rw-r--r--public/-/emojis/2/flag_ne.pngbin0 -> 3490 bytes
-rw-r--r--public/-/emojis/2/flag_nf.pngbin0 -> 3639 bytes
-rw-r--r--public/-/emojis/2/flag_ng.pngbin0 -> 2321 bytes
-rw-r--r--public/-/emojis/2/flag_ni.pngbin0 -> 3335 bytes
-rw-r--r--public/-/emojis/2/flag_nl.pngbin0 -> 3205 bytes
-rw-r--r--public/-/emojis/2/flag_no.pngbin0 -> 4312 bytes
-rw-r--r--public/-/emojis/2/flag_np.pngbin0 -> 3979 bytes
-rw-r--r--public/-/emojis/2/flag_nr.pngbin0 -> 3527 bytes
-rw-r--r--public/-/emojis/2/flag_nu.pngbin0 -> 4776 bytes
-rw-r--r--public/-/emojis/2/flag_nz.pngbin0 -> 4674 bytes
-rw-r--r--public/-/emojis/2/flag_om.pngbin0 -> 3384 bytes
-rw-r--r--public/-/emojis/2/flag_pa.pngbin0 -> 3381 bytes
-rw-r--r--public/-/emojis/2/flag_pe.pngbin0 -> 2762 bytes
-rw-r--r--public/-/emojis/2/flag_pf.pngbin0 -> 4073 bytes
-rw-r--r--public/-/emojis/2/flag_pg.pngbin0 -> 3751 bytes
-rw-r--r--public/-/emojis/2/flag_ph.pngbin0 -> 3984 bytes
-rw-r--r--public/-/emojis/2/flag_pk.pngbin0 -> 3332 bytes
-rw-r--r--public/-/emojis/2/flag_pl.pngbin0 -> 2692 bytes
-rw-r--r--public/-/emojis/2/flag_pm.pngbin0 -> 7375 bytes
-rw-r--r--public/-/emojis/2/flag_pn.pngbin0 -> 5825 bytes
-rw-r--r--public/-/emojis/2/flag_pr.pngbin0 -> 4023 bytes
-rw-r--r--public/-/emojis/2/flag_ps.pngbin0 -> 3028 bytes
-rw-r--r--public/-/emojis/2/flag_pt.pngbin0 -> 2899 bytes
-rw-r--r--public/-/emojis/2/flag_pw.pngbin0 -> 3569 bytes
-rw-r--r--public/-/emojis/2/flag_py.pngbin0 -> 3402 bytes
-rw-r--r--public/-/emojis/2/flag_qa.pngbin0 -> 2884 bytes
-rw-r--r--public/-/emojis/2/flag_re.pngbin0 -> 4952 bytes
-rw-r--r--public/-/emojis/2/flag_ro.pngbin0 -> 2870 bytes
-rw-r--r--public/-/emojis/2/flag_rs.pngbin0 -> 4417 bytes
-rw-r--r--public/-/emojis/2/flag_ru.pngbin0 -> 3165 bytes
-rw-r--r--public/-/emojis/2/flag_rw.pngbin0 -> 3669 bytes
-rw-r--r--public/-/emojis/2/flag_sa.pngbin0 -> 3905 bytes
-rw-r--r--public/-/emojis/2/flag_sb.pngbin0 -> 4590 bytes
-rw-r--r--public/-/emojis/2/flag_sc.pngbin0 -> 4103 bytes
-rw-r--r--public/-/emojis/2/flag_sd.pngbin0 -> 3020 bytes
-rw-r--r--public/-/emojis/2/flag_se.pngbin0 -> 3302 bytes
-rw-r--r--public/-/emojis/2/flag_sg.pngbin0 -> 3268 bytes
-rw-r--r--public/-/emojis/2/flag_sh.pngbin0 -> 4769 bytes
-rw-r--r--public/-/emojis/2/flag_si.pngbin0 -> 3628 bytes
-rw-r--r--public/-/emojis/2/flag_sj.pngbin0 -> 4312 bytes
-rw-r--r--public/-/emojis/2/flag_sk.pngbin0 -> 4146 bytes
-rw-r--r--public/-/emojis/2/flag_sl.pngbin0 -> 3018 bytes
-rw-r--r--public/-/emojis/2/flag_sm.pngbin0 -> 3857 bytes
-rw-r--r--public/-/emojis/2/flag_sn.pngbin0 -> 3237 bytes
-rw-r--r--public/-/emojis/2/flag_so.pngbin0 -> 3395 bytes
-rw-r--r--public/-/emojis/2/flag_sr.pngbin0 -> 4566 bytes
-rw-r--r--public/-/emojis/2/flag_ss.pngbin0 -> 4267 bytes
-rw-r--r--public/-/emojis/2/flag_st.pngbin0 -> 4037 bytes
-rw-r--r--public/-/emojis/2/flag_sv.pngbin0 -> 3683 bytes
-rw-r--r--public/-/emojis/2/flag_sx.pngbin0 -> 4158 bytes
-rw-r--r--public/-/emojis/2/flag_sy.pngbin0 -> 3140 bytes
-rw-r--r--public/-/emojis/2/flag_sz.pngbin0 -> 5784 bytes
-rw-r--r--public/-/emojis/2/flag_ta.pngbin0 -> 5942 bytes
-rw-r--r--public/-/emojis/2/flag_tc.pngbin0 -> 4778 bytes
-rw-r--r--public/-/emojis/2/flag_td.pngbin0 -> 2642 bytes
-rw-r--r--public/-/emojis/2/flag_tf.pngbin0 -> 3767 bytes
-rw-r--r--public/-/emojis/2/flag_tg.pngbin0 -> 4153 bytes
-rw-r--r--public/-/emojis/2/flag_th.pngbin0 -> 4119 bytes
-rw-r--r--public/-/emojis/2/flag_tj.pngbin0 -> 3015 bytes
-rw-r--r--public/-/emojis/2/flag_tk.pngbin0 -> 3998 bytes
-rw-r--r--public/-/emojis/2/flag_tl.pngbin0 -> 4012 bytes
-rw-r--r--public/-/emojis/2/flag_tm.pngbin0 -> 4418 bytes
-rw-r--r--public/-/emojis/2/flag_tn.pngbin0 -> 3610 bytes
-rw-r--r--public/-/emojis/2/flag_to.pngbin0 -> 2314 bytes
-rw-r--r--public/-/emojis/2/flag_tr.pngbin0 -> 3904 bytes
-rw-r--r--public/-/emojis/2/flag_tt.pngbin0 -> 4913 bytes
-rw-r--r--public/-/emojis/2/flag_tv.pngbin0 -> 5608 bytes
-rw-r--r--public/-/emojis/2/flag_tw.pngbin0 -> 2556 bytes
-rw-r--r--public/-/emojis/2/flag_tz.pngbin0 -> 4065 bytes
-rw-r--r--public/-/emojis/2/flag_ua.pngbin0 -> 2740 bytes
-rw-r--r--public/-/emojis/2/flag_ug.pngbin0 -> 3871 bytes
-rw-r--r--public/-/emojis/2/flag_um.pngbin0 -> 6869 bytes
-rw-r--r--public/-/emojis/2/flag_us.pngbin0 -> 6869 bytes
-rw-r--r--public/-/emojis/2/flag_uy.pngbin0 -> 5666 bytes
-rw-r--r--public/-/emojis/2/flag_uz.pngbin0 -> 3871 bytes
-rw-r--r--public/-/emojis/2/flag_va.pngbin0 -> 2980 bytes
-rw-r--r--public/-/emojis/2/flag_vc.pngbin0 -> 3489 bytes
-rw-r--r--public/-/emojis/2/flag_ve.pngbin0 -> 3871 bytes
-rw-r--r--public/-/emojis/2/flag_vg.pngbin0 -> 5297 bytes
-rw-r--r--public/-/emojis/2/flag_vi.pngbin0 -> 5591 bytes
-rw-r--r--public/-/emojis/2/flag_vn.pngbin0 -> 3524 bytes
-rw-r--r--public/-/emojis/2/flag_vu.pngbin0 -> 4768 bytes
-rw-r--r--public/-/emojis/2/flag_wf.pngbin0 -> 3650 bytes
-rw-r--r--public/-/emojis/2/flag_white.pngbin0 -> 3094 bytes
-rw-r--r--public/-/emojis/2/flag_ws.pngbin0 -> 3466 bytes
-rw-r--r--public/-/emojis/2/flag_xk.pngbin0 -> 4110 bytes
-rw-r--r--public/-/emojis/2/flag_ye.pngbin0 -> 2525 bytes
-rw-r--r--public/-/emojis/2/flag_yt.pngbin0 -> 5317 bytes
-rw-r--r--public/-/emojis/2/flag_za.pngbin0 -> 4932 bytes
-rw-r--r--public/-/emojis/2/flag_zm.pngbin0 -> 2816 bytes
-rw-r--r--public/-/emojis/2/flag_zw.pngbin0 -> 4175 bytes
-rw-r--r--public/-/emojis/2/flags.pngbin0 -> 6001 bytes
-rw-r--r--public/-/emojis/2/flashlight.pngbin0 -> 3717 bytes
-rw-r--r--public/-/emojis/2/fleur-de-lis.pngbin0 -> 4213 bytes
-rw-r--r--public/-/emojis/2/floppy_disk.pngbin0 -> 1145 bytes
-rw-r--r--public/-/emojis/2/flower_playing_cards.pngbin0 -> 1867 bytes
-rw-r--r--public/-/emojis/2/flushed.pngbin0 -> 5287 bytes
-rw-r--r--public/-/emojis/2/fog.pngbin0 -> 3554 bytes
-rw-r--r--public/-/emojis/2/foggy.pngbin0 -> 5564 bytes
-rw-r--r--public/-/emojis/2/football.pngbin0 -> 5526 bytes
-rw-r--r--public/-/emojis/2/footprints.pngbin0 -> 2400 bytes
-rw-r--r--public/-/emojis/2/fork_and_knife.pngbin0 -> 1967 bytes
-rw-r--r--public/-/emojis/2/fork_knife_plate.pngbin0 -> 3521 bytes
-rw-r--r--public/-/emojis/2/fountain.pngbin0 -> 5367 bytes
-rw-r--r--public/-/emojis/2/four.pngbin0 -> 1967 bytes
-rw-r--r--public/-/emojis/2/four_leaf_clover.pngbin0 -> 4088 bytes
-rw-r--r--public/-/emojis/2/fox.pngbin0 -> 4198 bytes
-rw-r--r--public/-/emojis/2/frame_photo.pngbin0 -> 3181 bytes
-rw-r--r--public/-/emojis/2/free.pngbin0 -> 2328 bytes
-rw-r--r--public/-/emojis/2/french_bread.pngbin0 -> 4176 bytes
-rw-r--r--public/-/emojis/2/fried_shrimp.pngbin0 -> 3197 bytes
-rw-r--r--public/-/emojis/2/fries.pngbin0 -> 4531 bytes
-rw-r--r--public/-/emojis/2/frog.pngbin0 -> 3157 bytes
-rw-r--r--public/-/emojis/2/frowning.pngbin0 -> 4514 bytes
-rw-r--r--public/-/emojis/2/frowning2.pngbin0 -> 4868 bytes
-rw-r--r--public/-/emojis/2/fuelpump.pngbin0 -> 4213 bytes
-rw-r--r--public/-/emojis/2/full_moon.pngbin0 -> 3799 bytes
-rw-r--r--public/-/emojis/2/full_moon_with_face.pngbin0 -> 5131 bytes
-rw-r--r--public/-/emojis/2/game_die.pngbin0 -> 4219 bytes
-rw-r--r--public/-/emojis/2/gay_pride_flag.pngbin0 -> 4447 bytes
-rw-r--r--public/-/emojis/2/gear.pngbin0 -> 3165 bytes
-rw-r--r--public/-/emojis/2/gem.pngbin0 -> 3371 bytes
-rw-r--r--public/-/emojis/2/gemini.pngbin0 -> 3896 bytes
-rw-r--r--public/-/emojis/2/ghost.pngbin0 -> 4181 bytes
-rw-r--r--public/-/emojis/2/gift.pngbin0 -> 4167 bytes
-rw-r--r--public/-/emojis/2/gift_heart.pngbin0 -> 4302 bytes
-rw-r--r--public/-/emojis/2/girl.pngbin0 -> 5150 bytes
-rw-r--r--public/-/emojis/2/girl_tone1.pngbin0 -> 5097 bytes
-rw-r--r--public/-/emojis/2/girl_tone2.pngbin0 -> 5086 bytes
-rw-r--r--public/-/emojis/2/girl_tone3.pngbin0 -> 4986 bytes
-rw-r--r--public/-/emojis/2/girl_tone4.pngbin0 -> 4701 bytes
-rw-r--r--public/-/emojis/2/girl_tone5.pngbin0 -> 4761 bytes
-rw-r--r--public/-/emojis/2/globe_with_meridians.pngbin0 -> 4630 bytes
-rw-r--r--public/-/emojis/2/goal.pngbin0 -> 5397 bytes
-rw-r--r--public/-/emojis/2/goat.pngbin0 -> 3653 bytes
-rw-r--r--public/-/emojis/2/golf.pngbin0 -> 2737 bytes
-rw-r--r--public/-/emojis/2/golfer.pngbin0 -> 3496 bytes
-rw-r--r--public/-/emojis/2/gorilla.pngbin0 -> 4435 bytes
-rw-r--r--public/-/emojis/2/grapes.pngbin0 -> 5191 bytes
-rw-r--r--public/-/emojis/2/green_apple.pngbin0 -> 3338 bytes
-rw-r--r--public/-/emojis/2/green_book.pngbin0 -> 1113 bytes
-rw-r--r--public/-/emojis/2/green_heart.pngbin0 -> 2929 bytes
-rw-r--r--public/-/emojis/2/grey_exclamation.pngbin0 -> 1314 bytes
-rw-r--r--public/-/emojis/2/grey_question.pngbin0 -> 2364 bytes
-rw-r--r--public/-/emojis/2/grimacing.pngbin0 -> 4875 bytes
-rw-r--r--public/-/emojis/2/grin.pngbin0 -> 5219 bytes
-rw-r--r--public/-/emojis/2/grinning.pngbin0 -> 5239 bytes
-rw-r--r--public/-/emojis/2/guardsman.pngbin0 -> 3910 bytes
-rw-r--r--public/-/emojis/2/guardsman_tone1.pngbin0 -> 4024 bytes
-rw-r--r--public/-/emojis/2/guardsman_tone2.pngbin0 -> 4001 bytes
-rw-r--r--public/-/emojis/2/guardsman_tone3.pngbin0 -> 3884 bytes
-rw-r--r--public/-/emojis/2/guardsman_tone4.pngbin0 -> 3777 bytes
-rw-r--r--public/-/emojis/2/guardsman_tone5.pngbin0 -> 3726 bytes
-rw-r--r--public/-/emojis/2/guitar.pngbin0 -> 4627 bytes
-rw-r--r--public/-/emojis/2/gun.pngbin0 -> 2282 bytes
-rw-r--r--public/-/emojis/2/haircut.pngbin0 -> 5526 bytes
-rw-r--r--public/-/emojis/2/haircut_tone1.pngbin0 -> 5692 bytes
-rw-r--r--public/-/emojis/2/haircut_tone2.pngbin0 -> 5496 bytes
-rw-r--r--public/-/emojis/2/haircut_tone3.pngbin0 -> 5453 bytes
-rw-r--r--public/-/emojis/2/haircut_tone4.pngbin0 -> 5330 bytes
-rw-r--r--public/-/emojis/2/haircut_tone5.pngbin0 -> 5415 bytes
-rw-r--r--public/-/emojis/2/hamburger.pngbin0 -> 6559 bytes
-rw-r--r--public/-/emojis/2/hammer.pngbin0 -> 2848 bytes
-rw-r--r--public/-/emojis/2/hammer_pick.pngbin0 -> 4505 bytes
-rw-r--r--public/-/emojis/2/hamster.pngbin0 -> 4285 bytes
-rw-r--r--public/-/emojis/2/hand_splayed.pngbin0 -> 3638 bytes
-rw-r--r--public/-/emojis/2/hand_splayed_tone1.pngbin0 -> 3809 bytes
-rw-r--r--public/-/emojis/2/hand_splayed_tone2.pngbin0 -> 3826 bytes
-rw-r--r--public/-/emojis/2/hand_splayed_tone3.pngbin0 -> 3842 bytes
-rw-r--r--public/-/emojis/2/hand_splayed_tone4.pngbin0 -> 3569 bytes
-rw-r--r--public/-/emojis/2/hand_splayed_tone5.pngbin0 -> 3589 bytes
-rw-r--r--public/-/emojis/2/handbag.pngbin0 -> 3952 bytes
-rw-r--r--public/-/emojis/2/handball.pngbin0 -> 4367 bytes
-rw-r--r--public/-/emojis/2/handball_tone1.pngbin0 -> 4413 bytes
-rw-r--r--public/-/emojis/2/handball_tone2.pngbin0 -> 4395 bytes
-rw-r--r--public/-/emojis/2/handball_tone3.pngbin0 -> 4363 bytes
-rw-r--r--public/-/emojis/2/handball_tone4.pngbin0 -> 4386 bytes
-rw-r--r--public/-/emojis/2/handball_tone5.pngbin0 -> 4440 bytes
-rw-r--r--public/-/emojis/2/handshake.pngbin0 -> 3653 bytes
-rw-r--r--public/-/emojis/2/handshake_tone1.pngbin0 -> 3974 bytes
-rw-r--r--public/-/emojis/2/handshake_tone2.pngbin0 -> 3984 bytes
-rw-r--r--public/-/emojis/2/handshake_tone3.pngbin0 -> 3872 bytes
-rw-r--r--public/-/emojis/2/handshake_tone4.pngbin0 -> 3532 bytes
-rw-r--r--public/-/emojis/2/handshake_tone5.pngbin0 -> 3738 bytes
-rw-r--r--public/-/emojis/2/hash.pngbin0 -> 2614 bytes
-rw-r--r--public/-/emojis/2/hatched_chick.pngbin0 -> 2478 bytes
-rw-r--r--public/-/emojis/2/hatching_chick.pngbin0 -> 3130 bytes
-rw-r--r--public/-/emojis/2/head_bandage.pngbin0 -> 5477 bytes
-rw-r--r--public/-/emojis/2/headphones.pngbin0 -> 4072 bytes
-rw-r--r--public/-/emojis/2/hear_no_evil.pngbin0 -> 3931 bytes
-rw-r--r--public/-/emojis/2/heart.pngbin0 -> 2771 bytes
-rw-r--r--public/-/emojis/2/heart_decoration.pngbin0 -> 2795 bytes
-rw-r--r--public/-/emojis/2/heart_exclamation.pngbin0 -> 2855 bytes
-rw-r--r--public/-/emojis/2/heart_eyes.pngbin0 -> 5144 bytes
-rw-r--r--public/-/emojis/2/heart_eyes_cat.pngbin0 -> 5410 bytes
-rw-r--r--public/-/emojis/2/heartbeat.pngbin0 -> 4506 bytes
-rw-r--r--public/-/emojis/2/heartpulse.pngbin0 -> 4016 bytes
-rw-r--r--public/-/emojis/2/hearts.pngbin0 -> 2209 bytes
-rw-r--r--public/-/emojis/2/heavy_check_mark.pngbin0 -> 2537 bytes
-rw-r--r--public/-/emojis/2/heavy_division_sign.pngbin0 -> 2077 bytes
-rw-r--r--public/-/emojis/2/heavy_dollar_sign.pngbin0 -> 3480 bytes
-rw-r--r--public/-/emojis/2/heavy_minus_sign.pngbin0 -> 661 bytes
-rw-r--r--public/-/emojis/2/heavy_multiplication_x.pngbin0 -> 3621 bytes
-rw-r--r--public/-/emojis/2/heavy_plus_sign.pngbin0 -> 1369 bytes
-rw-r--r--public/-/emojis/2/helicopter.pngbin0 -> 3722 bytes
-rw-r--r--public/-/emojis/2/helmet_with_cross.pngbin0 -> 3954 bytes
-rw-r--r--public/-/emojis/2/herb.pngbin0 -> 3941 bytes
-rw-r--r--public/-/emojis/2/hibiscus.pngbin0 -> 4720 bytes
-rw-r--r--public/-/emojis/2/high_brightness.pngbin0 -> 4362 bytes
-rw-r--r--public/-/emojis/2/high_heel.pngbin0 -> 3721 bytes
-rw-r--r--public/-/emojis/2/hockey.pngbin0 -> 2532 bytes
-rw-r--r--public/-/emojis/2/hole.pngbin0 -> 2503 bytes
-rw-r--r--public/-/emojis/2/homes.pngbin0 -> 4621 bytes
-rw-r--r--public/-/emojis/2/honey_pot.pngbin0 -> 3772 bytes
-rw-r--r--public/-/emojis/2/horse.pngbin0 -> 3539 bytes
-rw-r--r--public/-/emojis/2/horse_racing.pngbin0 -> 5233 bytes
-rw-r--r--public/-/emojis/2/horse_racing_tone1.pngbin0 -> 5275 bytes
-rw-r--r--public/-/emojis/2/horse_racing_tone2.pngbin0 -> 5251 bytes
-rw-r--r--public/-/emojis/2/horse_racing_tone3.pngbin0 -> 5249 bytes
-rw-r--r--public/-/emojis/2/horse_racing_tone4.pngbin0 -> 5216 bytes
-rw-r--r--public/-/emojis/2/horse_racing_tone5.pngbin0 -> 5218 bytes
-rw-r--r--public/-/emojis/2/hospital.pngbin0 -> 3394 bytes
-rw-r--r--public/-/emojis/2/hot_pepper.pngbin0 -> 2777 bytes
-rw-r--r--public/-/emojis/2/hotdog.pngbin0 -> 3562 bytes
-rw-r--r--public/-/emojis/2/hotel.pngbin0 -> 4353 bytes
-rw-r--r--public/-/emojis/2/hotsprings.pngbin0 -> 4638 bytes
-rw-r--r--public/-/emojis/2/hourglass.pngbin0 -> 3644 bytes
-rw-r--r--public/-/emojis/2/hourglass_flowing_sand.pngbin0 -> 4241 bytes
-rw-r--r--public/-/emojis/2/house.pngbin0 -> 4321 bytes
-rw-r--r--public/-/emojis/2/house_abandoned.pngbin0 -> 5488 bytes
-rw-r--r--public/-/emojis/2/house_with_garden.pngbin0 -> 4590 bytes
-rw-r--r--public/-/emojis/2/hugging.pngbin0 -> 6431 bytes
-rw-r--r--public/-/emojis/2/hushed.pngbin0 -> 4789 bytes
-rw-r--r--public/-/emojis/2/ice_cream.pngbin0 -> 4582 bytes
-rw-r--r--public/-/emojis/2/ice_skate.pngbin0 -> 4210 bytes
-rw-r--r--public/-/emojis/2/icecream.pngbin0 -> 3187 bytes
-rw-r--r--public/-/emojis/2/id.pngbin0 -> 2064 bytes
-rw-r--r--public/-/emojis/2/ideograph_advantage.pngbin0 -> 4578 bytes
-rw-r--r--public/-/emojis/2/imp.pngbin0 -> 5369 bytes
-rw-r--r--public/-/emojis/2/inbox_tray.pngbin0 -> 2325 bytes
-rw-r--r--public/-/emojis/2/incoming_envelope.pngbin0 -> 2582 bytes
-rw-r--r--public/-/emojis/2/information_desk_person.pngbin0 -> 5060 bytes
-rw-r--r--public/-/emojis/2/information_desk_person_tone1.pngbin0 -> 5246 bytes
-rw-r--r--public/-/emojis/2/information_desk_person_tone2.pngbin0 -> 4994 bytes
-rw-r--r--public/-/emojis/2/information_desk_person_tone3.pngbin0 -> 4974 bytes
-rw-r--r--public/-/emojis/2/information_desk_person_tone4.pngbin0 -> 4804 bytes
-rw-r--r--public/-/emojis/2/information_desk_person_tone5.pngbin0 -> 4824 bytes
-rw-r--r--public/-/emojis/2/information_source.pngbin0 -> 1537 bytes
-rw-r--r--public/-/emojis/2/innocent.pngbin0 -> 5344 bytes
-rw-r--r--public/-/emojis/2/interrobang.pngbin0 -> 3312 bytes
-rw-r--r--public/-/emojis/2/iphone.pngbin0 -> 2704 bytes
-rw-r--r--public/-/emojis/2/island.pngbin0 -> 4381 bytes
-rw-r--r--public/-/emojis/2/izakaya_lantern.pngbin0 -> 4639 bytes
-rw-r--r--public/-/emojis/2/jack_o_lantern.pngbin0 -> 4353 bytes
-rw-r--r--public/-/emojis/2/japan.pngbin0 -> 3058 bytes
-rw-r--r--public/-/emojis/2/japanese_castle.pngbin0 -> 6472 bytes
-rw-r--r--public/-/emojis/2/japanese_goblin.pngbin0 -> 6629 bytes
-rw-r--r--public/-/emojis/2/japanese_ogre.pngbin0 -> 7269 bytes
-rw-r--r--public/-/emojis/2/jeans.pngbin0 -> 2844 bytes
-rw-r--r--public/-/emojis/2/joy.pngbin0 -> 6101 bytes
-rw-r--r--public/-/emojis/2/joy_cat.pngbin0 -> 5353 bytes
-rw-r--r--public/-/emojis/2/joystick.pngbin0 -> 3192 bytes
-rw-r--r--public/-/emojis/2/juggling.pngbin0 -> 5236 bytes
-rw-r--r--public/-/emojis/2/juggling_tone1.pngbin0 -> 5329 bytes
-rw-r--r--public/-/emojis/2/juggling_tone2.pngbin0 -> 5222 bytes
-rw-r--r--public/-/emojis/2/juggling_tone3.pngbin0 -> 5193 bytes
-rw-r--r--public/-/emojis/2/juggling_tone4.pngbin0 -> 5139 bytes
-rw-r--r--public/-/emojis/2/juggling_tone5.pngbin0 -> 5127 bytes
-rw-r--r--public/-/emojis/2/kaaba.pngbin0 -> 3359 bytes
-rw-r--r--public/-/emojis/2/key.pngbin0 -> 3290 bytes
-rw-r--r--public/-/emojis/2/key2.pngbin0 -> 3953 bytes
-rw-r--r--public/-/emojis/2/keyboard.pngbin0 -> 3239 bytes
-rw-r--r--public/-/emojis/2/kimono.pngbin0 -> 6336 bytes
-rw-r--r--public/-/emojis/2/kiss.pngbin0 -> 1994 bytes
-rw-r--r--public/-/emojis/2/kiss_mm.pngbin0 -> 5116 bytes
-rw-r--r--public/-/emojis/2/kiss_ww.pngbin0 -> 5843 bytes
-rw-r--r--public/-/emojis/2/kissing.pngbin0 -> 4631 bytes
-rw-r--r--public/-/emojis/2/kissing_cat.pngbin0 -> 4854 bytes
-rw-r--r--public/-/emojis/2/kissing_closed_eyes.pngbin0 -> 5482 bytes
-rw-r--r--public/-/emojis/2/kissing_heart.pngbin0 -> 5214 bytes
-rw-r--r--public/-/emojis/2/kissing_smiling_eyes.pngbin0 -> 4661 bytes
-rw-r--r--public/-/emojis/2/kiwi.pngbin0 -> 6140 bytes
-rw-r--r--public/-/emojis/2/knife.pngbin0 -> 2527 bytes
-rw-r--r--public/-/emojis/2/koala.pngbin0 -> 3886 bytes
-rw-r--r--public/-/emojis/2/koko.pngbin0 -> 1734 bytes
-rw-r--r--public/-/emojis/2/label.pngbin0 -> 3461 bytes
-rw-r--r--public/-/emojis/2/large_blue_circle.pngbin0 -> 2907 bytes
-rw-r--r--public/-/emojis/2/large_blue_diamond.pngbin0 -> 2163 bytes
-rw-r--r--public/-/emojis/2/large_orange_diamond.pngbin0 -> 1856 bytes
-rw-r--r--public/-/emojis/2/last_quarter_moon.pngbin0 -> 3858 bytes
-rw-r--r--public/-/emojis/2/last_quarter_moon_with_face.pngbin0 -> 3463 bytes
-rw-r--r--public/-/emojis/2/laughing.pngbin0 -> 5571 bytes
-rw-r--r--public/-/emojis/2/leaves.pngbin0 -> 2772 bytes
-rw-r--r--public/-/emojis/2/ledger.pngbin0 -> 2798 bytes
-rw-r--r--public/-/emojis/2/left_facing_fist.pngbin0 -> 2921 bytes
-rw-r--r--public/-/emojis/2/left_facing_fist_tone1.pngbin0 -> 3218 bytes
-rw-r--r--public/-/emojis/2/left_facing_fist_tone2.pngbin0 -> 3382 bytes
-rw-r--r--public/-/emojis/2/left_facing_fist_tone3.pngbin0 -> 3153 bytes
-rw-r--r--public/-/emojis/2/left_facing_fist_tone4.pngbin0 -> 3051 bytes
-rw-r--r--public/-/emojis/2/left_facing_fist_tone5.pngbin0 -> 3079 bytes
-rw-r--r--public/-/emojis/2/left_luggage.pngbin0 -> 2814 bytes
-rw-r--r--public/-/emojis/2/left_right_arrow.pngbin0 -> 2108 bytes
-rw-r--r--public/-/emojis/2/leftwards_arrow_with_hook.pngbin0 -> 2369 bytes
-rw-r--r--public/-/emojis/2/lemon.pngbin0 -> 2862 bytes
-rw-r--r--public/-/emojis/2/leo.pngbin0 -> 4555 bytes
-rw-r--r--public/-/emojis/2/leopard.pngbin0 -> 5202 bytes
-rw-r--r--public/-/emojis/2/level_slider.pngbin0 -> 2629 bytes
-rw-r--r--public/-/emojis/2/levitate.pngbin0 -> 2902 bytes
-rw-r--r--public/-/emojis/2/libra.pngbin0 -> 4663 bytes
-rw-r--r--public/-/emojis/2/lifter.pngbin0 -> 4338 bytes
-rw-r--r--public/-/emojis/2/lifter_tone1.pngbin0 -> 4417 bytes
-rw-r--r--public/-/emojis/2/lifter_tone2.pngbin0 -> 4380 bytes
-rw-r--r--public/-/emojis/2/lifter_tone3.pngbin0 -> 4345 bytes
-rw-r--r--public/-/emojis/2/lifter_tone4.pngbin0 -> 4364 bytes
-rw-r--r--public/-/emojis/2/lifter_tone5.pngbin0 -> 4354 bytes
-rw-r--r--public/-/emojis/2/light_rail.pngbin0 -> 3096 bytes
-rw-r--r--public/-/emojis/2/link.pngbin0 -> 3539 bytes
-rw-r--r--public/-/emojis/2/lion_face.pngbin0 -> 4220 bytes
-rw-r--r--public/-/emojis/2/lips.pngbin0 -> 2561 bytes
-rw-r--r--public/-/emojis/2/lipstick.pngbin0 -> 2562 bytes
-rw-r--r--public/-/emojis/2/lizard.pngbin0 -> 4208 bytes
-rw-r--r--public/-/emojis/2/lock.pngbin0 -> 2401 bytes
-rw-r--r--public/-/emojis/2/lock_with_ink_pen.pngbin0 -> 4901 bytes
-rw-r--r--public/-/emojis/2/lollipop.pngbin0 -> 6431 bytes
-rw-r--r--public/-/emojis/2/loop.pngbin0 -> 4041 bytes
-rw-r--r--public/-/emojis/2/loud_sound.pngbin0 -> 5112 bytes
-rw-r--r--public/-/emojis/2/loudspeaker.pngbin0 -> 4557 bytes
-rw-r--r--public/-/emojis/2/love_hotel.pngbin0 -> 4943 bytes
-rw-r--r--public/-/emojis/2/love_letter.pngbin0 -> 2802 bytes
-rw-r--r--public/-/emojis/2/low_brightness.pngbin0 -> 3767 bytes
-rw-r--r--public/-/emojis/2/lying_face.pngbin0 -> 4932 bytes
-rw-r--r--public/-/emojis/2/m.pngbin0 -> 4118 bytes
-rw-r--r--public/-/emojis/2/mag.pngbin0 -> 4524 bytes
-rw-r--r--public/-/emojis/2/mag_right.pngbin0 -> 4430 bytes
-rw-r--r--public/-/emojis/2/mahjong.pngbin0 -> 2833 bytes
-rw-r--r--public/-/emojis/2/mailbox.pngbin0 -> 2341 bytes
-rw-r--r--public/-/emojis/2/mailbox_closed.pngbin0 -> 2162 bytes
-rw-r--r--public/-/emojis/2/mailbox_with_mail.pngbin0 -> 3167 bytes
-rw-r--r--public/-/emojis/2/mailbox_with_no_mail.pngbin0 -> 2159 bytes
-rw-r--r--public/-/emojis/2/man.pngbin0 -> 3977 bytes
-rw-r--r--public/-/emojis/2/man_dancing.pngbin0 -> 3863 bytes
-rw-r--r--public/-/emojis/2/man_dancing_tone1.pngbin0 -> 3862 bytes
-rw-r--r--public/-/emojis/2/man_dancing_tone2.pngbin0 -> 3871 bytes
-rw-r--r--public/-/emojis/2/man_dancing_tone3.pngbin0 -> 3872 bytes
-rw-r--r--public/-/emojis/2/man_dancing_tone4.pngbin0 -> 3833 bytes
-rw-r--r--public/-/emojis/2/man_dancing_tone5.pngbin0 -> 3870 bytes
-rw-r--r--public/-/emojis/2/man_in_tuxedo.pngbin0 -> 5576 bytes
-rw-r--r--public/-/emojis/2/man_in_tuxedo_tone1.pngbin0 -> 5679 bytes
-rw-r--r--public/-/emojis/2/man_in_tuxedo_tone2.pngbin0 -> 5524 bytes
-rw-r--r--public/-/emojis/2/man_in_tuxedo_tone3.pngbin0 -> 5439 bytes
-rw-r--r--public/-/emojis/2/man_in_tuxedo_tone4.pngbin0 -> 5358 bytes
-rw-r--r--public/-/emojis/2/man_in_tuxedo_tone5.pngbin0 -> 5379 bytes
-rw-r--r--public/-/emojis/2/man_tone1.pngbin0 -> 4081 bytes
-rw-r--r--public/-/emojis/2/man_tone2.pngbin0 -> 3984 bytes
-rw-r--r--public/-/emojis/2/man_tone3.pngbin0 -> 3858 bytes
-rw-r--r--public/-/emojis/2/man_tone4.pngbin0 -> 3681 bytes
-rw-r--r--public/-/emojis/2/man_tone5.pngbin0 -> 3730 bytes
-rw-r--r--public/-/emojis/2/man_with_gua_pi_mao.pngbin0 -> 4881 bytes
-rw-r--r--public/-/emojis/2/man_with_gua_pi_mao_tone1.pngbin0 -> 5086 bytes
-rw-r--r--public/-/emojis/2/man_with_gua_pi_mao_tone2.pngbin0 -> 4860 bytes
-rw-r--r--public/-/emojis/2/man_with_gua_pi_mao_tone3.pngbin0 -> 4779 bytes
-rw-r--r--public/-/emojis/2/man_with_gua_pi_mao_tone4.pngbin0 -> 4689 bytes
-rw-r--r--public/-/emojis/2/man_with_gua_pi_mao_tone5.pngbin0 -> 4689 bytes
-rw-r--r--public/-/emojis/2/man_with_turban.pngbin0 -> 5188 bytes
-rw-r--r--public/-/emojis/2/man_with_turban_tone1.pngbin0 -> 5267 bytes
-rw-r--r--public/-/emojis/2/man_with_turban_tone2.pngbin0 -> 4987 bytes
-rw-r--r--public/-/emojis/2/man_with_turban_tone3.pngbin0 -> 5024 bytes
-rw-r--r--public/-/emojis/2/man_with_turban_tone4.pngbin0 -> 5003 bytes
-rw-r--r--public/-/emojis/2/man_with_turban_tone5.pngbin0 -> 5022 bytes
-rw-r--r--public/-/emojis/2/mans_shoe.pngbin0 -> 2850 bytes
-rw-r--r--public/-/emojis/2/map.pngbin0 -> 5412 bytes
-rw-r--r--public/-/emojis/2/maple_leaf.pngbin0 -> 4187 bytes
-rw-r--r--public/-/emojis/2/martial_arts_uniform.pngbin0 -> 6113 bytes
-rw-r--r--public/-/emojis/2/mask.pngbin0 -> 4679 bytes
-rw-r--r--public/-/emojis/2/massage.pngbin0 -> 4900 bytes
-rw-r--r--public/-/emojis/2/massage_tone1.pngbin0 -> 5194 bytes
-rw-r--r--public/-/emojis/2/massage_tone2.pngbin0 -> 4766 bytes
-rw-r--r--public/-/emojis/2/massage_tone3.pngbin0 -> 4834 bytes
-rw-r--r--public/-/emojis/2/massage_tone4.pngbin0 -> 4717 bytes
-rw-r--r--public/-/emojis/2/massage_tone5.pngbin0 -> 4693 bytes
-rw-r--r--public/-/emojis/2/meat_on_bone.pngbin0 -> 4272 bytes
-rw-r--r--public/-/emojis/2/medal.pngbin0 -> 3268 bytes
-rw-r--r--public/-/emojis/2/mega.pngbin0 -> 4291 bytes
-rw-r--r--public/-/emojis/2/melon.pngbin0 -> 6709 bytes
-rw-r--r--public/-/emojis/2/menorah.pngbin0 -> 5397 bytes
-rw-r--r--public/-/emojis/2/mens.pngbin0 -> 2254 bytes
-rw-r--r--public/-/emojis/2/metal.pngbin0 -> 3185 bytes
-rw-r--r--public/-/emojis/2/metal_tone1.pngbin0 -> 3404 bytes
-rw-r--r--public/-/emojis/2/metal_tone2.pngbin0 -> 3452 bytes
-rw-r--r--public/-/emojis/2/metal_tone3.pngbin0 -> 3389 bytes
-rw-r--r--public/-/emojis/2/metal_tone4.pngbin0 -> 3047 bytes
-rw-r--r--public/-/emojis/2/metal_tone5.pngbin0 -> 3244 bytes
-rw-r--r--public/-/emojis/2/metro.pngbin0 -> 5833 bytes
-rw-r--r--public/-/emojis/2/microphone.pngbin0 -> 3348 bytes
-rw-r--r--public/-/emojis/2/microphone2.pngbin0 -> 5368 bytes
-rw-r--r--public/-/emojis/2/microscope.pngbin0 -> 4623 bytes
-rw-r--r--public/-/emojis/2/middle_finger.pngbin0 -> 2086 bytes
-rw-r--r--public/-/emojis/2/middle_finger_tone1.pngbin0 -> 2282 bytes
-rw-r--r--public/-/emojis/2/middle_finger_tone2.pngbin0 -> 2266 bytes
-rw-r--r--public/-/emojis/2/middle_finger_tone3.pngbin0 -> 2252 bytes
-rw-r--r--public/-/emojis/2/middle_finger_tone4.pngbin0 -> 2135 bytes
-rw-r--r--public/-/emojis/2/middle_finger_tone5.pngbin0 -> 2111 bytes
-rw-r--r--public/-/emojis/2/military_medal.pngbin0 -> 2798 bytes
-rw-r--r--public/-/emojis/2/milk.pngbin0 -> 3379 bytes
-rw-r--r--public/-/emojis/2/milky_way.pngbin0 -> 6311 bytes
-rw-r--r--public/-/emojis/2/minibus.pngbin0 -> 3124 bytes
-rw-r--r--public/-/emojis/2/minidisc.pngbin0 -> 5502 bytes
-rw-r--r--public/-/emojis/2/mobile_phone_off.pngbin0 -> 2710 bytes
-rw-r--r--public/-/emojis/2/money_mouth.pngbin0 -> 5760 bytes
-rw-r--r--public/-/emojis/2/money_with_wings.pngbin0 -> 5929 bytes
-rw-r--r--public/-/emojis/2/moneybag.pngbin0 -> 3729 bytes
-rw-r--r--public/-/emojis/2/monkey.pngbin0 -> 4705 bytes
-rw-r--r--public/-/emojis/2/monkey_face.pngbin0 -> 3541 bytes
-rw-r--r--public/-/emojis/2/monorail.pngbin0 -> 3324 bytes
-rw-r--r--public/-/emojis/2/mortar_board.pngbin0 -> 3435 bytes
-rw-r--r--public/-/emojis/2/mosque.pngbin0 -> 4307 bytes
-rw-r--r--public/-/emojis/2/motor_scooter.pngbin0 -> 4661 bytes
-rw-r--r--public/-/emojis/2/motorboat.pngbin0 -> 3003 bytes
-rw-r--r--public/-/emojis/2/motorcycle.pngbin0 -> 4778 bytes
-rw-r--r--public/-/emojis/2/motorway.pngbin0 -> 6009 bytes
-rw-r--r--public/-/emojis/2/mount_fuji.pngbin0 -> 3436 bytes
-rw-r--r--public/-/emojis/2/mountain.pngbin0 -> 4169 bytes
-rw-r--r--public/-/emojis/2/mountain_bicyclist.pngbin0 -> 6246 bytes
-rw-r--r--public/-/emojis/2/mountain_bicyclist_tone1.pngbin0 -> 6255 bytes
-rw-r--r--public/-/emojis/2/mountain_bicyclist_tone2.pngbin0 -> 6181 bytes
-rw-r--r--public/-/emojis/2/mountain_bicyclist_tone3.pngbin0 -> 6168 bytes
-rw-r--r--public/-/emojis/2/mountain_bicyclist_tone4.pngbin0 -> 6198 bytes
-rw-r--r--public/-/emojis/2/mountain_bicyclist_tone5.pngbin0 -> 6243 bytes
-rw-r--r--public/-/emojis/2/mountain_cableway.pngbin0 -> 3797 bytes
-rw-r--r--public/-/emojis/2/mountain_railway.pngbin0 -> 5247 bytes
-rw-r--r--public/-/emojis/2/mountain_snow.pngbin0 -> 4437 bytes
-rw-r--r--public/-/emojis/2/mouse.pngbin0 -> 3427 bytes
-rw-r--r--public/-/emojis/2/mouse2.pngbin0 -> 3171 bytes
-rw-r--r--public/-/emojis/2/mouse_three_button.pngbin0 -> 2529 bytes
-rw-r--r--public/-/emojis/2/movie_camera.pngbin0 -> 3494 bytes
-rw-r--r--public/-/emojis/2/moyai.pngbin0 -> 4229 bytes
-rw-r--r--public/-/emojis/2/mrs_claus.pngbin0 -> 5177 bytes
-rw-r--r--public/-/emojis/2/mrs_claus_tone1.pngbin0 -> 5073 bytes
-rw-r--r--public/-/emojis/2/mrs_claus_tone2.pngbin0 -> 5088 bytes
-rw-r--r--public/-/emojis/2/mrs_claus_tone3.pngbin0 -> 5135 bytes
-rw-r--r--public/-/emojis/2/mrs_claus_tone4.pngbin0 -> 5167 bytes
-rw-r--r--public/-/emojis/2/mrs_claus_tone5.pngbin0 -> 5262 bytes
-rw-r--r--public/-/emojis/2/muscle.pngbin0 -> 3278 bytes
-rw-r--r--public/-/emojis/2/muscle_tone1.pngbin0 -> 3499 bytes
-rw-r--r--public/-/emojis/2/muscle_tone2.pngbin0 -> 3604 bytes
-rw-r--r--public/-/emojis/2/muscle_tone3.pngbin0 -> 3520 bytes
-rw-r--r--public/-/emojis/2/muscle_tone4.pngbin0 -> 3247 bytes
-rw-r--r--public/-/emojis/2/muscle_tone5.pngbin0 -> 3411 bytes
-rw-r--r--public/-/emojis/2/mushroom.pngbin0 -> 3692 bytes
-rw-r--r--public/-/emojis/2/musical_keyboard.pngbin0 -> 1637 bytes
-rw-r--r--public/-/emojis/2/musical_note.pngbin0 -> 1158 bytes
-rw-r--r--public/-/emojis/2/musical_score.pngbin0 -> 2446 bytes
-rw-r--r--public/-/emojis/2/mute.pngbin0 -> 5449 bytes
-rw-r--r--public/-/emojis/2/nail_care.pngbin0 -> 5573 bytes
-rw-r--r--public/-/emojis/2/nail_care_tone1.pngbin0 -> 5858 bytes
-rw-r--r--public/-/emojis/2/nail_care_tone2.pngbin0 -> 5766 bytes
-rw-r--r--public/-/emojis/2/nail_care_tone3.pngbin0 -> 5589 bytes
-rw-r--r--public/-/emojis/2/nail_care_tone4.pngbin0 -> 5449 bytes
-rw-r--r--public/-/emojis/2/nail_care_tone5.pngbin0 -> 5477 bytes
-rw-r--r--public/-/emojis/2/name_badge.pngbin0 -> 3595 bytes
-rw-r--r--public/-/emojis/2/nauseated_face.pngbin0 -> 5393 bytes
-rw-r--r--public/-/emojis/2/necktie.pngbin0 -> 3757 bytes
-rw-r--r--public/-/emojis/2/negative_squared_cross_mark.pngbin0 -> 3087 bytes
-rw-r--r--public/-/emojis/2/nerd.pngbin0 -> 6275 bytes
-rw-r--r--public/-/emojis/2/neutral_face.pngbin0 -> 4235 bytes
-rw-r--r--public/-/emojis/2/new.pngbin0 -> 2672 bytes
-rw-r--r--public/-/emojis/2/new_moon.pngbin0 -> 3594 bytes
-rw-r--r--public/-/emojis/2/new_moon_with_face.pngbin0 -> 5492 bytes
-rw-r--r--public/-/emojis/2/newspaper.pngbin0 -> 2911 bytes
-rw-r--r--public/-/emojis/2/newspaper2.pngbin0 -> 5370 bytes
-rw-r--r--public/-/emojis/2/ng.pngbin0 -> 2864 bytes
-rw-r--r--public/-/emojis/2/night_with_stars.pngbin0 -> 6402 bytes
-rw-r--r--public/-/emojis/2/nine.pngbin0 -> 2515 bytes
-rw-r--r--public/-/emojis/2/no_bell.pngbin0 -> 6195 bytes
-rw-r--r--public/-/emojis/2/no_bicycles.pngbin0 -> 6930 bytes
-rw-r--r--public/-/emojis/2/no_entry.pngbin0 -> 2993 bytes
-rw-r--r--public/-/emojis/2/no_entry_sign.pngbin0 -> 3714 bytes
-rw-r--r--public/-/emojis/2/no_good.pngbin0 -> 5141 bytes
-rw-r--r--public/-/emojis/2/no_good_tone1.pngbin0 -> 5264 bytes
-rw-r--r--public/-/emojis/2/no_good_tone2.pngbin0 -> 5245 bytes
-rw-r--r--public/-/emojis/2/no_good_tone3.pngbin0 -> 5172 bytes
-rw-r--r--public/-/emojis/2/no_good_tone4.pngbin0 -> 5049 bytes
-rw-r--r--public/-/emojis/2/no_good_tone5.pngbin0 -> 5141 bytes
-rw-r--r--public/-/emojis/2/no_mobile_phones.pngbin0 -> 5254 bytes
-rw-r--r--public/-/emojis/2/no_mouth.pngbin0 -> 4108 bytes
-rw-r--r--public/-/emojis/2/no_pedestrians.pngbin0 -> 6025 bytes
-rw-r--r--public/-/emojis/2/no_smoking.pngbin0 -> 5308 bytes
-rw-r--r--public/-/emojis/2/non-potable_water.pngbin0 -> 6044 bytes
-rw-r--r--public/-/emojis/2/nose.pngbin0 -> 2560 bytes
-rw-r--r--public/-/emojis/2/nose_tone1.pngbin0 -> 2719 bytes
-rw-r--r--public/-/emojis/2/nose_tone2.pngbin0 -> 2655 bytes
-rw-r--r--public/-/emojis/2/nose_tone3.pngbin0 -> 2686 bytes
-rw-r--r--public/-/emojis/2/nose_tone4.pngbin0 -> 2527 bytes
-rw-r--r--public/-/emojis/2/nose_tone5.pngbin0 -> 2584 bytes
-rw-r--r--public/-/emojis/2/notebook.pngbin0 -> 6651 bytes
-rw-r--r--public/-/emojis/2/notebook_with_decorative_cover.pngbin0 -> 1693 bytes
-rw-r--r--public/-/emojis/2/notepad_spiral.pngbin0 -> 3343 bytes
-rw-r--r--public/-/emojis/2/notes.pngbin0 -> 2021 bytes
-rw-r--r--public/-/emojis/2/nut_and_bolt.pngbin0 -> 4134 bytes
-rw-r--r--public/-/emojis/2/o.pngbin0 -> 3903 bytes
-rw-r--r--public/-/emojis/2/o2.pngbin0 -> 3178 bytes
-rw-r--r--public/-/emojis/2/ocean.pngbin0 -> 4573 bytes
-rw-r--r--public/-/emojis/2/octagonal_sign.pngbin0 -> 1433 bytes
-rw-r--r--public/-/emojis/2/octopus.pngbin0 -> 5073 bytes
-rw-r--r--public/-/emojis/2/oden.pngbin0 -> 4554 bytes
-rw-r--r--public/-/emojis/2/office.pngbin0 -> 3224 bytes
-rw-r--r--public/-/emojis/2/oil.pngbin0 -> 3648 bytes
-rw-r--r--public/-/emojis/2/ok.pngbin0 -> 3253 bytes
-rw-r--r--public/-/emojis/2/ok_hand.pngbin0 -> 3675 bytes
-rw-r--r--public/-/emojis/2/ok_hand_tone1.pngbin0 -> 3914 bytes
-rw-r--r--public/-/emojis/2/ok_hand_tone2.pngbin0 -> 4012 bytes
-rw-r--r--public/-/emojis/2/ok_hand_tone3.pngbin0 -> 4000 bytes
-rw-r--r--public/-/emojis/2/ok_hand_tone4.pngbin0 -> 3636 bytes
-rw-r--r--public/-/emojis/2/ok_hand_tone5.pngbin0 -> 3828 bytes
-rw-r--r--public/-/emojis/2/ok_woman.pngbin0 -> 5058 bytes
-rw-r--r--public/-/emojis/2/ok_woman_tone1.pngbin0 -> 5439 bytes
-rw-r--r--public/-/emojis/2/ok_woman_tone2.pngbin0 -> 4948 bytes
-rw-r--r--public/-/emojis/2/ok_woman_tone3.pngbin0 -> 5049 bytes
-rw-r--r--public/-/emojis/2/ok_woman_tone4.pngbin0 -> 4958 bytes
-rw-r--r--public/-/emojis/2/ok_woman_tone5.pngbin0 -> 4971 bytes
-rw-r--r--public/-/emojis/2/older_man.pngbin0 -> 4097 bytes
-rw-r--r--public/-/emojis/2/older_man_tone1.pngbin0 -> 4087 bytes
-rw-r--r--public/-/emojis/2/older_man_tone2.pngbin0 -> 4094 bytes
-rw-r--r--public/-/emojis/2/older_man_tone3.pngbin0 -> 4047 bytes
-rw-r--r--public/-/emojis/2/older_man_tone4.pngbin0 -> 3948 bytes
-rw-r--r--public/-/emojis/2/older_man_tone5.pngbin0 -> 4168 bytes
-rw-r--r--public/-/emojis/2/older_woman.pngbin0 -> 4684 bytes
-rw-r--r--public/-/emojis/2/older_woman_tone1.pngbin0 -> 4662 bytes
-rw-r--r--public/-/emojis/2/older_woman_tone2.pngbin0 -> 4584 bytes
-rw-r--r--public/-/emojis/2/older_woman_tone3.pngbin0 -> 4478 bytes
-rw-r--r--public/-/emojis/2/older_woman_tone4.pngbin0 -> 4414 bytes
-rw-r--r--public/-/emojis/2/older_woman_tone5.pngbin0 -> 4598 bytes
-rw-r--r--public/-/emojis/2/om_symbol.pngbin0 -> 4522 bytes
-rw-r--r--public/-/emojis/2/on.pngbin0 -> 3208 bytes
-rw-r--r--public/-/emojis/2/oncoming_automobile.pngbin0 -> 4047 bytes
-rw-r--r--public/-/emojis/2/oncoming_bus.pngbin0 -> 3702 bytes
-rw-r--r--public/-/emojis/2/oncoming_police_car.pngbin0 -> 4042 bytes
-rw-r--r--public/-/emojis/2/oncoming_taxi.pngbin0 -> 4096 bytes
-rw-r--r--public/-/emojis/2/one.pngbin0 -> 1464 bytes
-rw-r--r--public/-/emojis/2/open_file_folder.pngbin0 -> 1871 bytes
-rw-r--r--public/-/emojis/2/open_hands.pngbin0 -> 3865 bytes
-rw-r--r--public/-/emojis/2/open_hands_tone1.pngbin0 -> 4024 bytes
-rw-r--r--public/-/emojis/2/open_hands_tone2.pngbin0 -> 4190 bytes
-rw-r--r--public/-/emojis/2/open_hands_tone3.pngbin0 -> 4103 bytes
-rw-r--r--public/-/emojis/2/open_hands_tone4.pngbin0 -> 3659 bytes
-rw-r--r--public/-/emojis/2/open_hands_tone5.pngbin0 -> 3941 bytes
-rw-r--r--public/-/emojis/2/open_mouth.pngbin0 -> 4562 bytes
-rw-r--r--public/-/emojis/2/ophiuchus.pngbin0 -> 4242 bytes
-rw-r--r--public/-/emojis/2/orange_book.pngbin0 -> 1120 bytes
-rw-r--r--public/-/emojis/2/orthodox_cross.pngbin0 -> 2447 bytes
-rw-r--r--public/-/emojis/2/outbox_tray.pngbin0 -> 2302 bytes
-rw-r--r--public/-/emojis/2/owl.pngbin0 -> 5134 bytes
-rw-r--r--public/-/emojis/2/ox.pngbin0 -> 3627 bytes
-rw-r--r--public/-/emojis/2/package.pngbin0 -> 3114 bytes
-rw-r--r--public/-/emojis/2/page_facing_up.pngbin0 -> 1186 bytes
-rw-r--r--public/-/emojis/2/page_with_curl.pngbin0 -> 1207 bytes
-rw-r--r--public/-/emojis/2/pager.pngbin0 -> 3441 bytes
-rw-r--r--public/-/emojis/2/paintbrush.pngbin0 -> 2635 bytes
-rw-r--r--public/-/emojis/2/palm_tree.pngbin0 -> 3932 bytes
-rw-r--r--public/-/emojis/2/pancakes.pngbin0 -> 7014 bytes
-rw-r--r--public/-/emojis/2/panda_face.pngbin0 -> 5397 bytes
-rw-r--r--public/-/emojis/2/paperclip.pngbin0 -> 5483 bytes
-rw-r--r--public/-/emojis/2/paperclips.pngbin0 -> 6905 bytes
-rw-r--r--public/-/emojis/2/park.pngbin0 -> 6976 bytes
-rw-r--r--public/-/emojis/2/parking.pngbin0 -> 1911 bytes
-rw-r--r--public/-/emojis/2/part_alternation_mark.pngbin0 -> 3247 bytes
-rw-r--r--public/-/emojis/2/partly_sunny.pngbin0 -> 2686 bytes
-rw-r--r--public/-/emojis/2/passport_control.pngbin0 -> 3363 bytes
-rw-r--r--public/-/emojis/2/pause_button.pngbin0 -> 1129 bytes
-rw-r--r--public/-/emojis/2/peace.pngbin0 -> 3962 bytes
-rw-r--r--public/-/emojis/2/peach.pngbin0 -> 4907 bytes
-rw-r--r--public/-/emojis/2/peanuts.pngbin0 -> 3417 bytes
-rw-r--r--public/-/emojis/2/pear.pngbin0 -> 2445 bytes
-rw-r--r--public/-/emojis/2/pen_ballpoint.pngbin0 -> 3639 bytes
-rw-r--r--public/-/emojis/2/pen_fountain.pngbin0 -> 3827 bytes
-rw-r--r--public/-/emojis/2/pencil.pngbin0 -> 4593 bytes
-rw-r--r--public/-/emojis/2/pencil2.pngbin0 -> 3004 bytes
-rw-r--r--public/-/emojis/2/penguin.pngbin0 -> 3286 bytes
-rw-r--r--public/-/emojis/2/pensive.pngbin0 -> 4716 bytes
-rw-r--r--public/-/emojis/2/performing_arts.pngbin0 -> 4317 bytes
-rw-r--r--public/-/emojis/2/persevere.pngbin0 -> 5289 bytes
-rw-r--r--public/-/emojis/2/person_frowning.pngbin0 -> 4403 bytes
-rw-r--r--public/-/emojis/2/person_frowning_tone1.pngbin0 -> 4543 bytes
-rw-r--r--public/-/emojis/2/person_frowning_tone2.pngbin0 -> 4309 bytes
-rw-r--r--public/-/emojis/2/person_frowning_tone3.pngbin0 -> 4310 bytes
-rw-r--r--public/-/emojis/2/person_frowning_tone4.pngbin0 -> 4190 bytes
-rw-r--r--public/-/emojis/2/person_frowning_tone5.pngbin0 -> 4247 bytes
-rw-r--r--public/-/emojis/2/person_with_blond_hair.pngbin0 -> 3983 bytes
-rw-r--r--public/-/emojis/2/person_with_blond_hair_tone1.pngbin0 -> 4280 bytes
-rw-r--r--public/-/emojis/2/person_with_blond_hair_tone2.pngbin0 -> 4305 bytes
-rw-r--r--public/-/emojis/2/person_with_blond_hair_tone3.pngbin0 -> 4318 bytes
-rw-r--r--public/-/emojis/2/person_with_blond_hair_tone4.pngbin0 -> 4234 bytes
-rw-r--r--public/-/emojis/2/person_with_blond_hair_tone5.pngbin0 -> 4366 bytes
-rw-r--r--public/-/emojis/2/person_with_pouting_face.pngbin0 -> 4824 bytes
-rw-r--r--public/-/emojis/2/person_with_pouting_face_tone1.pngbin0 -> 5056 bytes
-rw-r--r--public/-/emojis/2/person_with_pouting_face_tone2.pngbin0 -> 4856 bytes
-rw-r--r--public/-/emojis/2/person_with_pouting_face_tone3.pngbin0 -> 4770 bytes
-rw-r--r--public/-/emojis/2/person_with_pouting_face_tone4.pngbin0 -> 4675 bytes
-rw-r--r--public/-/emojis/2/person_with_pouting_face_tone5.pngbin0 -> 4807 bytes
-rw-r--r--public/-/emojis/2/pick.pngbin0 -> 2789 bytes
-rw-r--r--public/-/emojis/2/pig.pngbin0 -> 3649 bytes
-rw-r--r--public/-/emojis/2/pig2.pngbin0 -> 3112 bytes
-rw-r--r--public/-/emojis/2/pig_nose.pngbin0 -> 2677 bytes
-rw-r--r--public/-/emojis/2/pill.pngbin0 -> 2705 bytes
-rw-r--r--public/-/emojis/2/pineapple.pngbin0 -> 3974 bytes
-rw-r--r--public/-/emojis/2/ping_pong.pngbin0 -> 2968 bytes
-rw-r--r--public/-/emojis/2/pisces.pngbin0 -> 4576 bytes
-rw-r--r--public/-/emojis/2/pizza.pngbin0 -> 4654 bytes
-rw-r--r--public/-/emojis/2/place_of_worship.pngbin0 -> 3414 bytes
-rw-r--r--public/-/emojis/2/play_pause.pngbin0 -> 1906 bytes
-rw-r--r--public/-/emojis/2/point_down.pngbin0 -> 2314 bytes
-rw-r--r--public/-/emojis/2/point_down_tone1.pngbin0 -> 2519 bytes
-rw-r--r--public/-/emojis/2/point_down_tone2.pngbin0 -> 2513 bytes
-rw-r--r--public/-/emojis/2/point_down_tone3.pngbin0 -> 2413 bytes
-rw-r--r--public/-/emojis/2/point_down_tone4.pngbin0 -> 2301 bytes
-rw-r--r--public/-/emojis/2/point_down_tone5.pngbin0 -> 2356 bytes
-rw-r--r--public/-/emojis/2/point_left.pngbin0 -> 2143 bytes
-rw-r--r--public/-/emojis/2/point_left_tone1.pngbin0 -> 2330 bytes
-rw-r--r--public/-/emojis/2/point_left_tone2.pngbin0 -> 2309 bytes
-rw-r--r--public/-/emojis/2/point_left_tone3.pngbin0 -> 2386 bytes
-rw-r--r--public/-/emojis/2/point_left_tone4.pngbin0 -> 2210 bytes
-rw-r--r--public/-/emojis/2/point_left_tone5.pngbin0 -> 2312 bytes
-rw-r--r--public/-/emojis/2/point_right.pngbin0 -> 2175 bytes
-rw-r--r--public/-/emojis/2/point_right_tone1.pngbin0 -> 2344 bytes
-rw-r--r--public/-/emojis/2/point_right_tone2.pngbin0 -> 2325 bytes
-rw-r--r--public/-/emojis/2/point_right_tone3.pngbin0 -> 2276 bytes
-rw-r--r--public/-/emojis/2/point_right_tone4.pngbin0 -> 2143 bytes
-rw-r--r--public/-/emojis/2/point_right_tone5.pngbin0 -> 2172 bytes
-rw-r--r--public/-/emojis/2/point_up.pngbin0 -> 3044 bytes
-rw-r--r--public/-/emojis/2/point_up_2.pngbin0 -> 2272 bytes
-rw-r--r--public/-/emojis/2/point_up_2_tone1.pngbin0 -> 2457 bytes
-rw-r--r--public/-/emojis/2/point_up_2_tone2.pngbin0 -> 2442 bytes
-rw-r--r--public/-/emojis/2/point_up_2_tone3.pngbin0 -> 2385 bytes
-rw-r--r--public/-/emojis/2/point_up_2_tone4.pngbin0 -> 2290 bytes
-rw-r--r--public/-/emojis/2/point_up_2_tone5.pngbin0 -> 2351 bytes
-rw-r--r--public/-/emojis/2/point_up_tone1.pngbin0 -> 3231 bytes
-rw-r--r--public/-/emojis/2/point_up_tone2.pngbin0 -> 3255 bytes
-rw-r--r--public/-/emojis/2/point_up_tone3.pngbin0 -> 3176 bytes
-rw-r--r--public/-/emojis/2/point_up_tone4.pngbin0 -> 2818 bytes
-rw-r--r--public/-/emojis/2/point_up_tone5.pngbin0 -> 3005 bytes
-rw-r--r--public/-/emojis/2/police_car.pngbin0 -> 3987 bytes
-rw-r--r--public/-/emojis/2/poodle.pngbin0 -> 4467 bytes
-rw-r--r--public/-/emojis/2/poop.pngbin0 -> 3452 bytes
-rw-r--r--public/-/emojis/2/popcorn.pngbin0 -> 5674 bytes
-rw-r--r--public/-/emojis/2/post_office.pngbin0 -> 2559 bytes
-rw-r--r--public/-/emojis/2/postal_horn.pngbin0 -> 3491 bytes
-rw-r--r--public/-/emojis/2/postbox.pngbin0 -> 2569 bytes
-rw-r--r--public/-/emojis/2/potable_water.pngbin0 -> 3165 bytes
-rw-r--r--public/-/emojis/2/potato.pngbin0 -> 3683 bytes
-rw-r--r--public/-/emojis/2/pouch.pngbin0 -> 2529 bytes
-rw-r--r--public/-/emojis/2/poultry_leg.pngbin0 -> 2702 bytes
-rw-r--r--public/-/emojis/2/pound.pngbin0 -> 2390 bytes
-rw-r--r--public/-/emojis/2/pouting_cat.pngbin0 -> 4361 bytes
-rw-r--r--public/-/emojis/2/pray.pngbin0 -> 3399 bytes
-rw-r--r--public/-/emojis/2/pray_tone1.pngbin0 -> 3406 bytes
-rw-r--r--public/-/emojis/2/pray_tone2.pngbin0 -> 3437 bytes
-rw-r--r--public/-/emojis/2/pray_tone3.pngbin0 -> 3309 bytes
-rw-r--r--public/-/emojis/2/pray_tone4.pngbin0 -> 3278 bytes
-rw-r--r--public/-/emojis/2/pray_tone5.pngbin0 -> 3332 bytes
-rw-r--r--public/-/emojis/2/prayer_beads.pngbin0 -> 5496 bytes
-rw-r--r--public/-/emojis/2/pregnant_woman.pngbin0 -> 3089 bytes
-rw-r--r--public/-/emojis/2/pregnant_woman_tone1.pngbin0 -> 3104 bytes
-rw-r--r--public/-/emojis/2/pregnant_woman_tone2.pngbin0 -> 3095 bytes
-rw-r--r--public/-/emojis/2/pregnant_woman_tone3.pngbin0 -> 3038 bytes
-rw-r--r--public/-/emojis/2/pregnant_woman_tone4.pngbin0 -> 2988 bytes
-rw-r--r--public/-/emojis/2/pregnant_woman_tone5.pngbin0 -> 3042 bytes
-rw-r--r--public/-/emojis/2/prince.pngbin0 -> 4988 bytes
-rw-r--r--public/-/emojis/2/prince_tone1.pngbin0 -> 5158 bytes
-rw-r--r--public/-/emojis/2/prince_tone2.pngbin0 -> 4951 bytes
-rw-r--r--public/-/emojis/2/prince_tone3.pngbin0 -> 4971 bytes
-rw-r--r--public/-/emojis/2/prince_tone4.pngbin0 -> 4911 bytes
-rw-r--r--public/-/emojis/2/prince_tone5.pngbin0 -> 4979 bytes
-rw-r--r--public/-/emojis/2/princess.pngbin0 -> 5591 bytes
-rw-r--r--public/-/emojis/2/princess_tone1.pngbin0 -> 5621 bytes
-rw-r--r--public/-/emojis/2/princess_tone2.pngbin0 -> 5429 bytes
-rw-r--r--public/-/emojis/2/princess_tone3.pngbin0 -> 5535 bytes
-rw-r--r--public/-/emojis/2/princess_tone4.pngbin0 -> 5461 bytes
-rw-r--r--public/-/emojis/2/princess_tone5.pngbin0 -> 5534 bytes
-rw-r--r--public/-/emojis/2/printer.pngbin0 -> 3128 bytes
-rw-r--r--public/-/emojis/2/projector.pngbin0 -> 5684 bytes
-rw-r--r--public/-/emojis/2/punch.pngbin0 -> 3271 bytes
-rw-r--r--public/-/emojis/2/punch_tone1.pngbin0 -> 3011 bytes
-rw-r--r--public/-/emojis/2/punch_tone2.pngbin0 -> 3165 bytes
-rw-r--r--public/-/emojis/2/punch_tone3.pngbin0 -> 3592 bytes
-rw-r--r--public/-/emojis/2/punch_tone4.pngbin0 -> 3215 bytes
-rw-r--r--public/-/emojis/2/punch_tone5.pngbin0 -> 3327 bytes
-rw-r--r--public/-/emojis/2/purple_heart.pngbin0 -> 3051 bytes
-rw-r--r--public/-/emojis/2/purse.pngbin0 -> 3661 bytes
-rw-r--r--public/-/emojis/2/pushpin.pngbin0 -> 3160 bytes
-rw-r--r--public/-/emojis/2/put_litter_in_its_place.pngbin0 -> 3446 bytes
-rw-r--r--public/-/emojis/2/question.pngbin0 -> 2342 bytes
-rw-r--r--public/-/emojis/2/rabbit.pngbin0 -> 4230 bytes
-rw-r--r--public/-/emojis/2/rabbit2.pngbin0 -> 3614 bytes
-rw-r--r--public/-/emojis/2/race_car.pngbin0 -> 3228 bytes
-rw-r--r--public/-/emojis/2/racehorse.pngbin0 -> 4442 bytes
-rw-r--r--public/-/emojis/2/radio.pngbin0 -> 3597 bytes
-rw-r--r--public/-/emojis/2/radio_button.pngbin0 -> 4227 bytes
-rw-r--r--public/-/emojis/2/radioactive.pngbin0 -> 4640 bytes
-rw-r--r--public/-/emojis/2/rage.pngbin0 -> 5128 bytes
-rw-r--r--public/-/emojis/2/railway_car.pngbin0 -> 2707 bytes
-rw-r--r--public/-/emojis/2/railway_track.pngbin0 -> 4420 bytes
-rw-r--r--public/-/emojis/2/rainbow.pngbin0 -> 3488 bytes
-rw-r--r--public/-/emojis/2/raised_back_of_hand.pngbin0 -> 2913 bytes
-rw-r--r--public/-/emojis/2/raised_back_of_hand_tone1.pngbin0 -> 3126 bytes
-rw-r--r--public/-/emojis/2/raised_back_of_hand_tone2.pngbin0 -> 3156 bytes
-rw-r--r--public/-/emojis/2/raised_back_of_hand_tone3.pngbin0 -> 3053 bytes
-rw-r--r--public/-/emojis/2/raised_back_of_hand_tone4.pngbin0 -> 2886 bytes
-rw-r--r--public/-/emojis/2/raised_back_of_hand_tone5.pngbin0 -> 2930 bytes
-rw-r--r--public/-/emojis/2/raised_hand.pngbin0 -> 2896 bytes
-rw-r--r--public/-/emojis/2/raised_hand_tone1.pngbin0 -> 3120 bytes
-rw-r--r--public/-/emojis/2/raised_hand_tone2.pngbin0 -> 3123 bytes
-rw-r--r--public/-/emojis/2/raised_hand_tone3.pngbin0 -> 3090 bytes
-rw-r--r--public/-/emojis/2/raised_hand_tone4.pngbin0 -> 2860 bytes
-rw-r--r--public/-/emojis/2/raised_hand_tone5.pngbin0 -> 2917 bytes
-rw-r--r--public/-/emojis/2/raised_hands.pngbin0 -> 3902 bytes
-rw-r--r--public/-/emojis/2/raised_hands_tone1.pngbin0 -> 4107 bytes
-rw-r--r--public/-/emojis/2/raised_hands_tone2.pngbin0 -> 4189 bytes
-rw-r--r--public/-/emojis/2/raised_hands_tone3.pngbin0 -> 4084 bytes
-rw-r--r--public/-/emojis/2/raised_hands_tone4.pngbin0 -> 3756 bytes
-rw-r--r--public/-/emojis/2/raised_hands_tone5.pngbin0 -> 3954 bytes
-rw-r--r--public/-/emojis/2/raising_hand.pngbin0 -> 5099 bytes
-rw-r--r--public/-/emojis/2/raising_hand_tone1.pngbin0 -> 5338 bytes
-rw-r--r--public/-/emojis/2/raising_hand_tone2.pngbin0 -> 4972 bytes
-rw-r--r--public/-/emojis/2/raising_hand_tone3.pngbin0 -> 4973 bytes
-rw-r--r--public/-/emojis/2/raising_hand_tone4.pngbin0 -> 4848 bytes
-rw-r--r--public/-/emojis/2/raising_hand_tone5.pngbin0 -> 4883 bytes
-rw-r--r--public/-/emojis/2/ram.pngbin0 -> 4480 bytes
-rw-r--r--public/-/emojis/2/ramen.pngbin0 -> 5580 bytes
-rw-r--r--public/-/emojis/2/rat.pngbin0 -> 3436 bytes
-rw-r--r--public/-/emojis/2/record_button.pngbin0 -> 1872 bytes
-rw-r--r--public/-/emojis/2/recycle.pngbin0 -> 3648 bytes
-rw-r--r--public/-/emojis/2/red_car.pngbin0 -> 3692 bytes
-rw-r--r--public/-/emojis/2/red_circle.pngbin0 -> 2832 bytes
-rw-r--r--public/-/emojis/2/registered.pngbin0 -> 4675 bytes
-rw-r--r--public/-/emojis/2/relaxed.pngbin0 -> 5366 bytes
-rw-r--r--public/-/emojis/2/relieved.pngbin0 -> 4930 bytes
-rw-r--r--public/-/emojis/2/reminder_ribbon.pngbin0 -> 2344 bytes
-rw-r--r--public/-/emojis/2/repeat.pngbin0 -> 2820 bytes
-rw-r--r--public/-/emojis/2/repeat_one.pngbin0 -> 3247 bytes
-rw-r--r--public/-/emojis/2/restroom.pngbin0 -> 3589 bytes
-rw-r--r--public/-/emojis/2/revolving_hearts.pngbin0 -> 4560 bytes
-rw-r--r--public/-/emojis/2/rewind.pngbin0 -> 2223 bytes
-rw-r--r--public/-/emojis/2/rhino.pngbin0 -> 3630 bytes
-rw-r--r--public/-/emojis/2/ribbon.pngbin0 -> 4255 bytes
-rw-r--r--public/-/emojis/2/rice.pngbin0 -> 3765 bytes
-rw-r--r--public/-/emojis/2/rice_ball.pngbin0 -> 3858 bytes
-rw-r--r--public/-/emojis/2/rice_cracker.pngbin0 -> 4058 bytes
-rw-r--r--public/-/emojis/2/rice_scene.pngbin0 -> 7219 bytes
-rw-r--r--public/-/emojis/2/right_facing_fist.pngbin0 -> 2932 bytes
-rw-r--r--public/-/emojis/2/right_facing_fist_tone1.pngbin0 -> 3447 bytes
-rw-r--r--public/-/emojis/2/right_facing_fist_tone2.pngbin0 -> 3544 bytes
-rw-r--r--public/-/emojis/2/right_facing_fist_tone3.pngbin0 -> 3357 bytes
-rw-r--r--public/-/emojis/2/right_facing_fist_tone4.pngbin0 -> 3196 bytes
-rw-r--r--public/-/emojis/2/right_facing_fist_tone5.pngbin0 -> 3248 bytes
-rw-r--r--public/-/emojis/2/ring.pngbin0 -> 3808 bytes
-rw-r--r--public/-/emojis/2/robot.pngbin0 -> 3144 bytes
-rw-r--r--public/-/emojis/2/rocket.pngbin0 -> 5488 bytes
-rw-r--r--public/-/emojis/2/rofl.pngbin0 -> 6172 bytes
-rw-r--r--public/-/emojis/2/roller_coaster.pngbin0 -> 5186 bytes
-rw-r--r--public/-/emojis/2/rolling_eyes.pngbin0 -> 4685 bytes
-rw-r--r--public/-/emojis/2/rooster.pngbin0 -> 3854 bytes
-rw-r--r--public/-/emojis/2/rose.pngbin0 -> 3291 bytes
-rw-r--r--public/-/emojis/2/rosette.pngbin0 -> 4556 bytes
-rw-r--r--public/-/emojis/2/rotating_light.pngbin0 -> 4679 bytes
-rw-r--r--public/-/emojis/2/round_pushpin.pngbin0 -> 1555 bytes
-rw-r--r--public/-/emojis/2/rowboat.pngbin0 -> 4149 bytes
-rw-r--r--public/-/emojis/2/rowboat_tone1.pngbin0 -> 4210 bytes
-rw-r--r--public/-/emojis/2/rowboat_tone2.pngbin0 -> 4204 bytes
-rw-r--r--public/-/emojis/2/rowboat_tone3.pngbin0 -> 4175 bytes
-rw-r--r--public/-/emojis/2/rowboat_tone4.pngbin0 -> 4157 bytes
-rw-r--r--public/-/emojis/2/rowboat_tone5.pngbin0 -> 4183 bytes
-rw-r--r--public/-/emojis/2/rugby_football.pngbin0 -> 3937 bytes
-rw-r--r--public/-/emojis/2/runner.pngbin0 -> 3191 bytes
-rw-r--r--public/-/emojis/2/runner_tone1.pngbin0 -> 3280 bytes
-rw-r--r--public/-/emojis/2/runner_tone2.pngbin0 -> 3270 bytes
-rw-r--r--public/-/emojis/2/runner_tone3.pngbin0 -> 3231 bytes
-rw-r--r--public/-/emojis/2/runner_tone4.pngbin0 -> 3213 bytes
-rw-r--r--public/-/emojis/2/runner_tone5.pngbin0 -> 3285 bytes
-rw-r--r--public/-/emojis/2/running_shirt_with_sash.pngbin0 -> 3358 bytes
-rw-r--r--public/-/emojis/2/sa.pngbin0 -> 2386 bytes
-rw-r--r--public/-/emojis/2/sagittarius.pngbin0 -> 4468 bytes
-rw-r--r--public/-/emojis/2/sailboat.pngbin0 -> 3987 bytes
-rw-r--r--public/-/emojis/2/sake.pngbin0 -> 3311 bytes
-rw-r--r--public/-/emojis/2/salad.pngbin0 -> 5279 bytes
-rw-r--r--public/-/emojis/2/sandal.pngbin0 -> 2770 bytes
-rw-r--r--public/-/emojis/2/santa.pngbin0 -> 4289 bytes
-rw-r--r--public/-/emojis/2/santa_tone1.pngbin0 -> 4204 bytes
-rw-r--r--public/-/emojis/2/santa_tone2.pngbin0 -> 4284 bytes
-rw-r--r--public/-/emojis/2/santa_tone3.pngbin0 -> 4382 bytes
-rw-r--r--public/-/emojis/2/santa_tone4.pngbin0 -> 4409 bytes
-rw-r--r--public/-/emojis/2/santa_tone5.pngbin0 -> 4449 bytes
-rw-r--r--public/-/emojis/2/satellite.pngbin0 -> 5128 bytes
-rw-r--r--public/-/emojis/2/satellite_orbital.pngbin0 -> 4941 bytes
-rw-r--r--public/-/emojis/2/saxophone.pngbin0 -> 2954 bytes
-rw-r--r--public/-/emojis/2/scales.pngbin0 -> 4230 bytes
-rw-r--r--public/-/emojis/2/school.pngbin0 -> 4001 bytes
-rw-r--r--public/-/emojis/2/school_satchel.pngbin0 -> 5291 bytes
-rw-r--r--public/-/emojis/2/scissors.pngbin0 -> 3793 bytes
-rw-r--r--public/-/emojis/2/scooter.pngbin0 -> 3110 bytes
-rw-r--r--public/-/emojis/2/scorpion.pngbin0 -> 4502 bytes
-rw-r--r--public/-/emojis/2/scorpius.pngbin0 -> 4438 bytes
-rw-r--r--public/-/emojis/2/scream.pngbin0 -> 5649 bytes
-rw-r--r--public/-/emojis/2/scream_cat.pngbin0 -> 5280 bytes
-rw-r--r--public/-/emojis/2/scroll.pngbin0 -> 3417 bytes
-rw-r--r--public/-/emojis/2/seat.pngbin0 -> 3717 bytes
-rw-r--r--public/-/emojis/2/second_place.pngbin0 -> 3637 bytes
-rw-r--r--public/-/emojis/2/secret.pngbin0 -> 5359 bytes
-rw-r--r--public/-/emojis/2/see_no_evil.pngbin0 -> 4037 bytes
-rw-r--r--public/-/emojis/2/seedling.pngbin0 -> 2678 bytes
-rw-r--r--public/-/emojis/2/selfie.pngbin0 -> 3196 bytes
-rw-r--r--public/-/emojis/2/selfie_tone1.pngbin0 -> 3171 bytes
-rw-r--r--public/-/emojis/2/selfie_tone2.pngbin0 -> 3258 bytes
-rw-r--r--public/-/emojis/2/selfie_tone3.pngbin0 -> 3255 bytes
-rw-r--r--public/-/emojis/2/selfie_tone4.pngbin0 -> 3245 bytes
-rw-r--r--public/-/emojis/2/selfie_tone5.pngbin0 -> 3253 bytes
-rw-r--r--public/-/emojis/2/seven.pngbin0 -> 1981 bytes
-rw-r--r--public/-/emojis/2/shallow_pan_of_food.pngbin0 -> 7933 bytes
-rw-r--r--public/-/emojis/2/shamrock.pngbin0 -> 3812 bytes
-rw-r--r--public/-/emojis/2/shark.pngbin0 -> 3599 bytes
-rw-r--r--public/-/emojis/2/shaved_ice.pngbin0 -> 4374 bytes
-rw-r--r--public/-/emojis/2/sheep.pngbin0 -> 4608 bytes
-rw-r--r--public/-/emojis/2/shell.pngbin0 -> 3732 bytes
-rw-r--r--public/-/emojis/2/shield.pngbin0 -> 4162 bytes
-rw-r--r--public/-/emojis/2/shinto_shrine.pngbin0 -> 2517 bytes
-rw-r--r--public/-/emojis/2/ship.pngbin0 -> 4370 bytes
-rw-r--r--public/-/emojis/2/shirt.pngbin0 -> 2090 bytes
-rw-r--r--public/-/emojis/2/shopping_bags.pngbin0 -> 4273 bytes
-rw-r--r--public/-/emojis/2/shopping_cart.pngbin0 -> 3825 bytes
-rw-r--r--public/-/emojis/2/shower.pngbin0 -> 4662 bytes
-rw-r--r--public/-/emojis/2/shrimp.pngbin0 -> 3495 bytes
-rw-r--r--public/-/emojis/2/shrug.pngbin0 -> 4781 bytes
-rw-r--r--public/-/emojis/2/shrug_tone1.pngbin0 -> 4984 bytes
-rw-r--r--public/-/emojis/2/shrug_tone2.pngbin0 -> 4800 bytes
-rw-r--r--public/-/emojis/2/shrug_tone3.pngbin0 -> 4762 bytes
-rw-r--r--public/-/emojis/2/shrug_tone4.pngbin0 -> 4717 bytes
-rw-r--r--public/-/emojis/2/shrug_tone5.pngbin0 -> 4754 bytes
-rw-r--r--public/-/emojis/2/signal_strength.pngbin0 -> 1468 bytes
-rw-r--r--public/-/emojis/2/six.pngbin0 -> 2529 bytes
-rw-r--r--public/-/emojis/2/six_pointed_star.pngbin0 -> 3801 bytes
-rw-r--r--public/-/emojis/2/ski.pngbin0 -> 3862 bytes
-rw-r--r--public/-/emojis/2/skier.pngbin0 -> 5603 bytes
-rw-r--r--public/-/emojis/2/skull.pngbin0 -> 4059 bytes
-rw-r--r--public/-/emojis/2/skull_crossbones.pngbin0 -> 4347 bytes
-rw-r--r--public/-/emojis/2/sleeping.pngbin0 -> 5214 bytes
-rw-r--r--public/-/emojis/2/sleeping_accommodation.pngbin0 -> 2442 bytes
-rw-r--r--public/-/emojis/2/sleepy.pngbin0 -> 5248 bytes
-rw-r--r--public/-/emojis/2/slight_frown.pngbin0 -> 4636 bytes
-rw-r--r--public/-/emojis/2/slight_smile.pngbin0 -> 4644 bytes
-rw-r--r--public/-/emojis/2/slot_machine.pngbin0 -> 5163 bytes
-rw-r--r--public/-/emojis/2/small_blue_diamond.pngbin0 -> 977 bytes
-rw-r--r--public/-/emojis/2/small_orange_diamond.pngbin0 -> 950 bytes
-rw-r--r--public/-/emojis/2/small_red_triangle.pngbin0 -> 1371 bytes
-rw-r--r--public/-/emojis/2/small_red_triangle_down.pngbin0 -> 1435 bytes
-rw-r--r--public/-/emojis/2/smile.pngbin0 -> 5185 bytes
-rw-r--r--public/-/emojis/2/smile_cat.pngbin0 -> 4845 bytes
-rw-r--r--public/-/emojis/2/smiley.pngbin0 -> 5211 bytes
-rw-r--r--public/-/emojis/2/smiley_cat.pngbin0 -> 4458 bytes
-rw-r--r--public/-/emojis/2/smiling_imp.pngbin0 -> 5355 bytes
-rw-r--r--public/-/emojis/2/smirk.pngbin0 -> 4817 bytes
-rw-r--r--public/-/emojis/2/smirk_cat.pngbin0 -> 4383 bytes
-rw-r--r--public/-/emojis/2/smoking.pngbin0 -> 3110 bytes
-rw-r--r--public/-/emojis/2/snail.pngbin0 -> 4356 bytes
-rw-r--r--public/-/emojis/2/snake.pngbin0 -> 4040 bytes
-rw-r--r--public/-/emojis/2/sneezing_face.pngbin0 -> 6024 bytes
-rw-r--r--public/-/emojis/2/snowboarder.pngbin0 -> 5823 bytes
-rw-r--r--public/-/emojis/2/snowflake.pngbin0 -> 5219 bytes
-rw-r--r--public/-/emojis/2/snowman.pngbin0 -> 2907 bytes
-rw-r--r--public/-/emojis/2/snowman2.pngbin0 -> 3718 bytes
-rw-r--r--public/-/emojis/2/sob.pngbin0 -> 5597 bytes
-rw-r--r--public/-/emojis/2/soccer.pngbin0 -> 5272 bytes
-rw-r--r--public/-/emojis/2/soon.pngbin0 -> 3511 bytes
-rw-r--r--public/-/emojis/2/sos.pngbin0 -> 3896 bytes
-rw-r--r--public/-/emojis/2/sound.pngbin0 -> 3960 bytes
-rw-r--r--public/-/emojis/2/space_invader.pngbin0 -> 2411 bytes
-rw-r--r--public/-/emojis/2/spades.pngbin0 -> 2300 bytes
-rw-r--r--public/-/emojis/2/spaghetti.pngbin0 -> 5923 bytes
-rw-r--r--public/-/emojis/2/sparkle.pngbin0 -> 3257 bytes
-rw-r--r--public/-/emojis/2/sparkler.pngbin0 -> 9294 bytes
-rw-r--r--public/-/emojis/2/sparkles.pngbin0 -> 2796 bytes
-rw-r--r--public/-/emojis/2/sparkling_heart.pngbin0 -> 4578 bytes
-rw-r--r--public/-/emojis/2/speak_no_evil.pngbin0 -> 3986 bytes
-rw-r--r--public/-/emojis/2/speaker.pngbin0 -> 3686 bytes
-rw-r--r--public/-/emojis/2/speaking_head.pngbin0 -> 1746 bytes
-rw-r--r--public/-/emojis/2/speech_balloon.pngbin0 -> 3203 bytes
-rw-r--r--public/-/emojis/2/speech_left.pngbin0 -> 2709 bytes
-rw-r--r--public/-/emojis/2/speedboat.pngbin0 -> 2620 bytes
-rw-r--r--public/-/emojis/2/spider.pngbin0 -> 4025 bytes
-rw-r--r--public/-/emojis/2/spider_web.pngbin0 -> 3798 bytes
-rw-r--r--public/-/emojis/2/spoon.pngbin0 -> 2894 bytes
-rw-r--r--public/-/emojis/2/spy.pngbin0 -> 6337 bytes
-rw-r--r--public/-/emojis/2/spy_tone1.pngbin0 -> 6445 bytes
-rw-r--r--public/-/emojis/2/spy_tone2.pngbin0 -> 6304 bytes
-rw-r--r--public/-/emojis/2/spy_tone3.pngbin0 -> 6154 bytes
-rw-r--r--public/-/emojis/2/spy_tone4.pngbin0 -> 6081 bytes
-rw-r--r--public/-/emojis/2/spy_tone5.pngbin0 -> 6028 bytes
-rw-r--r--public/-/emojis/2/squid.pngbin0 -> 4763 bytes
-rw-r--r--public/-/emojis/2/stadium.pngbin0 -> 6540 bytes
-rw-r--r--public/-/emojis/2/star.pngbin0 -> 2222 bytes
-rw-r--r--public/-/emojis/2/star2.pngbin0 -> 3065 bytes
-rw-r--r--public/-/emojis/2/star_and_crescent.pngbin0 -> 3631 bytes
-rw-r--r--public/-/emojis/2/star_of_david.pngbin0 -> 3664 bytes
-rw-r--r--public/-/emojis/2/stars.pngbin0 -> 5233 bytes
-rw-r--r--public/-/emojis/2/station.pngbin0 -> 5407 bytes
-rw-r--r--public/-/emojis/2/statue_of_liberty.pngbin0 -> 5849 bytes
-rw-r--r--public/-/emojis/2/steam_locomotive.pngbin0 -> 5410 bytes
-rw-r--r--public/-/emojis/2/stew.pngbin0 -> 4054 bytes
-rw-r--r--public/-/emojis/2/stop_button.pngbin0 -> 1130 bytes
-rw-r--r--public/-/emojis/2/stopwatch.pngbin0 -> 4767 bytes
-rw-r--r--public/-/emojis/2/straight_ruler.pngbin0 -> 3199 bytes
-rw-r--r--public/-/emojis/2/strawberry.pngbin0 -> 4260 bytes
-rw-r--r--public/-/emojis/2/stuck_out_tongue.pngbin0 -> 4664 bytes
-rw-r--r--public/-/emojis/2/stuck_out_tongue_closed_eyes.pngbin0 -> 5088 bytes
-rw-r--r--public/-/emojis/2/stuck_out_tongue_winking_eye.pngbin0 -> 5175 bytes
-rw-r--r--public/-/emojis/2/stuffed_flatbread.pngbin0 -> 6153 bytes
-rw-r--r--public/-/emojis/2/sun_with_face.pngbin0 -> 5405 bytes
-rw-r--r--public/-/emojis/2/sunflower.pngbin0 -> 3686 bytes
-rw-r--r--public/-/emojis/2/sunglasses.pngbin0 -> 4783 bytes
-rw-r--r--public/-/emojis/2/sunny.pngbin0 -> 3127 bytes
-rw-r--r--public/-/emojis/2/sunrise.pngbin0 -> 5904 bytes
-rw-r--r--public/-/emojis/2/sunrise_over_mountains.pngbin0 -> 7314 bytes
-rw-r--r--public/-/emojis/2/surfer.pngbin0 -> 6505 bytes
-rw-r--r--public/-/emojis/2/surfer_tone1.pngbin0 -> 6533 bytes
-rw-r--r--public/-/emojis/2/surfer_tone2.pngbin0 -> 6530 bytes
-rw-r--r--public/-/emojis/2/surfer_tone3.pngbin0 -> 6536 bytes
-rw-r--r--public/-/emojis/2/surfer_tone4.pngbin0 -> 6551 bytes
-rw-r--r--public/-/emojis/2/surfer_tone5.pngbin0 -> 6613 bytes
-rw-r--r--public/-/emojis/2/sushi.pngbin0 -> 5586 bytes
-rw-r--r--public/-/emojis/2/suspension_railway.pngbin0 -> 4615 bytes
-rw-r--r--public/-/emojis/2/sweat.pngbin0 -> 4783 bytes
-rw-r--r--public/-/emojis/2/sweat_drops.pngbin0 -> 2832 bytes
-rw-r--r--public/-/emojis/2/sweat_smile.pngbin0 -> 5513 bytes
-rw-r--r--public/-/emojis/2/sweet_potato.pngbin0 -> 3646 bytes
-rw-r--r--public/-/emojis/2/swimmer.pngbin0 -> 2894 bytes
-rw-r--r--public/-/emojis/2/swimmer_tone1.pngbin0 -> 2968 bytes
-rw-r--r--public/-/emojis/2/swimmer_tone2.pngbin0 -> 2972 bytes
-rw-r--r--public/-/emojis/2/swimmer_tone3.pngbin0 -> 2984 bytes
-rw-r--r--public/-/emojis/2/swimmer_tone4.pngbin0 -> 2970 bytes
-rw-r--r--public/-/emojis/2/swimmer_tone5.pngbin0 -> 3002 bytes
-rw-r--r--public/-/emojis/2/symbols.pngbin0 -> 3442 bytes
-rw-r--r--public/-/emojis/2/synagogue.pngbin0 -> 4062 bytes
-rw-r--r--public/-/emojis/2/syringe.pngbin0 -> 3298 bytes
-rw-r--r--public/-/emojis/2/taco.pngbin0 -> 5095 bytes
-rw-r--r--public/-/emojis/2/tada.pngbin0 -> 5758 bytes
-rw-r--r--public/-/emojis/2/tanabata_tree.pngbin0 -> 4774 bytes
-rw-r--r--public/-/emojis/2/tangerine.pngbin0 -> 3009 bytes
-rw-r--r--public/-/emojis/2/taurus.pngbin0 -> 4716 bytes
-rw-r--r--public/-/emojis/2/taxi.pngbin0 -> 3989 bytes
-rw-r--r--public/-/emojis/2/tea.pngbin0 -> 2862 bytes
-rw-r--r--public/-/emojis/2/telephone.pngbin0 -> 3940 bytes
-rw-r--r--public/-/emojis/2/telephone_receiver.pngbin0 -> 2937 bytes
-rw-r--r--public/-/emojis/2/telescope.pngbin0 -> 3989 bytes
-rw-r--r--public/-/emojis/2/ten.pngbin0 -> 2573 bytes
-rw-r--r--public/-/emojis/2/tennis.pngbin0 -> 5650 bytes
-rw-r--r--public/-/emojis/2/tent.pngbin0 -> 2610 bytes
-rw-r--r--public/-/emojis/2/thermometer.pngbin0 -> 2433 bytes
-rw-r--r--public/-/emojis/2/thermometer_face.pngbin0 -> 5693 bytes
-rw-r--r--public/-/emojis/2/thinking.pngbin0 -> 5440 bytes
-rw-r--r--public/-/emojis/2/third_place.pngbin0 -> 3784 bytes
-rw-r--r--public/-/emojis/2/thought_balloon.pngbin0 -> 3237 bytes
-rw-r--r--public/-/emojis/2/three.pngbin0 -> 2580 bytes
-rw-r--r--public/-/emojis/2/thumbsdown.pngbin0 -> 3520 bytes
-rw-r--r--public/-/emojis/2/thumbsdown_tone1.pngbin0 -> 3749 bytes
-rw-r--r--public/-/emojis/2/thumbsdown_tone2.pngbin0 -> 3776 bytes
-rw-r--r--public/-/emojis/2/thumbsdown_tone3.pngbin0 -> 3679 bytes
-rw-r--r--public/-/emojis/2/thumbsdown_tone4.pngbin0 -> 3443 bytes
-rw-r--r--public/-/emojis/2/thumbsdown_tone5.pngbin0 -> 3501 bytes
-rw-r--r--public/-/emojis/2/thumbsup.pngbin0 -> 3475 bytes
-rw-r--r--public/-/emojis/2/thumbsup_tone1.pngbin0 -> 3754 bytes
-rw-r--r--public/-/emojis/2/thumbsup_tone2.pngbin0 -> 3737 bytes
-rw-r--r--public/-/emojis/2/thumbsup_tone3.pngbin0 -> 3670 bytes
-rw-r--r--public/-/emojis/2/thumbsup_tone4.pngbin0 -> 3403 bytes
-rw-r--r--public/-/emojis/2/thumbsup_tone5.pngbin0 -> 3474 bytes
-rw-r--r--public/-/emojis/2/thunder_cloud_rain.pngbin0 -> 3424 bytes
-rw-r--r--public/-/emojis/2/ticket.pngbin0 -> 2253 bytes
-rw-r--r--public/-/emojis/2/tickets.pngbin0 -> 1702 bytes
-rw-r--r--public/-/emojis/2/tiger.pngbin0 -> 6453 bytes
-rw-r--r--public/-/emojis/2/tiger2.pngbin0 -> 5531 bytes
-rw-r--r--public/-/emojis/2/timer.pngbin0 -> 4883 bytes
-rw-r--r--public/-/emojis/2/tired_face.pngbin0 -> 5606 bytes
-rw-r--r--public/-/emojis/2/tm.pngbin0 -> 1885 bytes
-rw-r--r--public/-/emojis/2/toilet.pngbin0 -> 2807 bytes
-rw-r--r--public/-/emojis/2/tokyo_tower.pngbin0 -> 2259 bytes
-rw-r--r--public/-/emojis/2/tomato.pngbin0 -> 3520 bytes
-rw-r--r--public/-/emojis/2/tone1.pngbin0 -> 406 bytes
-rw-r--r--public/-/emojis/2/tone2.pngbin0 -> 419 bytes
-rw-r--r--public/-/emojis/2/tone3.pngbin0 -> 414 bytes
-rw-r--r--public/-/emojis/2/tone4.pngbin0 -> 416 bytes
-rw-r--r--public/-/emojis/2/tone5.pngbin0 -> 405 bytes
-rw-r--r--public/-/emojis/2/tongue.pngbin0 -> 3705 bytes
-rw-r--r--public/-/emojis/2/tools.pngbin0 -> 5049 bytes
-rw-r--r--public/-/emojis/2/top.pngbin0 -> 2753 bytes
-rw-r--r--public/-/emojis/2/tophat.pngbin0 -> 3289 bytes
-rw-r--r--public/-/emojis/2/track_next.pngbin0 -> 2235 bytes
-rw-r--r--public/-/emojis/2/track_previous.pngbin0 -> 2252 bytes
-rw-r--r--public/-/emojis/2/trackball.pngbin0 -> 4137 bytes
-rw-r--r--public/-/emojis/2/tractor.pngbin0 -> 5972 bytes
-rw-r--r--public/-/emojis/2/traffic_light.pngbin0 -> 2502 bytes
-rw-r--r--public/-/emojis/2/train.pngbin0 -> 3318 bytes
-rw-r--r--public/-/emojis/2/train2.pngbin0 -> 4262 bytes
-rw-r--r--public/-/emojis/2/tram.pngbin0 -> 4236 bytes
-rw-r--r--public/-/emojis/2/triangular_flag_on_post.pngbin0 -> 3203 bytes
-rw-r--r--public/-/emojis/2/triangular_ruler.pngbin0 -> 3101 bytes
-rw-r--r--public/-/emojis/2/trident.pngbin0 -> 4253 bytes
-rw-r--r--public/-/emojis/2/triumph.pngbin0 -> 5870 bytes
-rw-r--r--public/-/emojis/2/trolleybus.pngbin0 -> 4107 bytes
-rw-r--r--public/-/emojis/2/trophy.pngbin0 -> 4374 bytes
-rw-r--r--public/-/emojis/2/tropical_drink.pngbin0 -> 3950 bytes
-rw-r--r--public/-/emojis/2/tropical_fish.pngbin0 -> 4411 bytes
-rw-r--r--public/-/emojis/2/truck.pngbin0 -> 3314 bytes
-rw-r--r--public/-/emojis/2/trumpet.pngbin0 -> 3443 bytes
-rw-r--r--public/-/emojis/2/tulip.pngbin0 -> 3162 bytes
-rw-r--r--public/-/emojis/2/tumbler_glass.pngbin0 -> 5194 bytes
-rw-r--r--public/-/emojis/2/turkey.pngbin0 -> 5886 bytes
-rw-r--r--public/-/emojis/2/turtle.pngbin0 -> 3718 bytes
-rw-r--r--public/-/emojis/2/tv.pngbin0 -> 2981 bytes
-rw-r--r--public/-/emojis/2/twisted_rightwards_arrows.pngbin0 -> 3645 bytes
-rw-r--r--public/-/emojis/2/two.pngbin0 -> 2368 bytes
-rw-r--r--public/-/emojis/2/two_hearts.pngbin0 -> 3543 bytes
-rw-r--r--public/-/emojis/2/two_men_holding_hands.pngbin0 -> 4990 bytes
-rw-r--r--public/-/emojis/2/two_women_holding_hands.pngbin0 -> 5302 bytes
-rw-r--r--public/-/emojis/2/u5272.pngbin0 -> 2808 bytes
-rw-r--r--public/-/emojis/2/u5408.pngbin0 -> 2840 bytes
-rw-r--r--public/-/emojis/2/u55b6.pngbin0 -> 2585 bytes
-rw-r--r--public/-/emojis/2/u6307.pngbin0 -> 2970 bytes
-rw-r--r--public/-/emojis/2/u6708.pngbin0 -> 2072 bytes
-rw-r--r--public/-/emojis/2/u6709.pngbin0 -> 2477 bytes
-rw-r--r--public/-/emojis/2/u6e80.pngbin0 -> 3696 bytes
-rw-r--r--public/-/emojis/2/u7121.pngbin0 -> 3254 bytes
-rw-r--r--public/-/emojis/2/u7533.pngbin0 -> 2115 bytes
-rw-r--r--public/-/emojis/2/u7981.pngbin0 -> 3651 bytes
-rw-r--r--public/-/emojis/2/u7a7a.pngbin0 -> 2572 bytes
-rw-r--r--public/-/emojis/2/umbrella.pngbin0 -> 4009 bytes
-rw-r--r--public/-/emojis/2/umbrella2.pngbin0 -> 2695 bytes
-rw-r--r--public/-/emojis/2/unamused.pngbin0 -> 4844 bytes
-rw-r--r--public/-/emojis/2/underage.pngbin0 -> 6503 bytes
-rw-r--r--public/-/emojis/2/unicorn.pngbin0 -> 4566 bytes
-rw-r--r--public/-/emojis/2/unlock.pngbin0 -> 2560 bytes
-rw-r--r--public/-/emojis/2/up.pngbin0 -> 2524 bytes
-rw-r--r--public/-/emojis/2/upside_down.pngbin0 -> 4771 bytes
-rw-r--r--public/-/emojis/2/urn.pngbin0 -> 3097 bytes
-rw-r--r--public/-/emojis/2/v.pngbin0 -> 3650 bytes
-rw-r--r--public/-/emojis/2/v_tone1.pngbin0 -> 3873 bytes
-rw-r--r--public/-/emojis/2/v_tone2.pngbin0 -> 3970 bytes
-rw-r--r--public/-/emojis/2/v_tone3.pngbin0 -> 3894 bytes
-rw-r--r--public/-/emojis/2/v_tone4.pngbin0 -> 3585 bytes
-rw-r--r--public/-/emojis/2/v_tone5.pngbin0 -> 3722 bytes
-rw-r--r--public/-/emojis/2/vertical_traffic_light.pngbin0 -> 2608 bytes
-rw-r--r--public/-/emojis/2/vhs.pngbin0 -> 2286 bytes
-rw-r--r--public/-/emojis/2/vibration_mode.pngbin0 -> 4065 bytes
-rw-r--r--public/-/emojis/2/video_camera.pngbin0 -> 2530 bytes
-rw-r--r--public/-/emojis/2/video_game.pngbin0 -> 3467 bytes
-rw-r--r--public/-/emojis/2/violin.pngbin0 -> 5262 bytes
-rw-r--r--public/-/emojis/2/virgo.pngbin0 -> 4848 bytes
-rw-r--r--public/-/emojis/2/volcano.pngbin0 -> 6192 bytes
-rw-r--r--public/-/emojis/2/volleyball.pngbin0 -> 6651 bytes
-rw-r--r--public/-/emojis/2/vs.pngbin0 -> 3290 bytes
-rw-r--r--public/-/emojis/2/vulcan.pngbin0 -> 3853 bytes
-rw-r--r--public/-/emojis/2/vulcan_tone1.pngbin0 -> 4142 bytes
-rw-r--r--public/-/emojis/2/vulcan_tone2.pngbin0 -> 4131 bytes
-rw-r--r--public/-/emojis/2/vulcan_tone3.pngbin0 -> 4061 bytes
-rw-r--r--public/-/emojis/2/vulcan_tone4.pngbin0 -> 3728 bytes
-rw-r--r--public/-/emojis/2/vulcan_tone5.pngbin0 -> 3878 bytes
-rw-r--r--public/-/emojis/2/walking.pngbin0 -> 2553 bytes
-rw-r--r--public/-/emojis/2/walking_tone1.pngbin0 -> 2613 bytes
-rw-r--r--public/-/emojis/2/walking_tone2.pngbin0 -> 2586 bytes
-rw-r--r--public/-/emojis/2/walking_tone3.pngbin0 -> 2547 bytes
-rw-r--r--public/-/emojis/2/walking_tone4.pngbin0 -> 2538 bytes
-rw-r--r--public/-/emojis/2/walking_tone5.pngbin0 -> 2577 bytes
-rw-r--r--public/-/emojis/2/waning_crescent_moon.pngbin0 -> 4258 bytes
-rw-r--r--public/-/emojis/2/waning_gibbous_moon.pngbin0 -> 4446 bytes
-rw-r--r--public/-/emojis/2/warning.pngbin0 -> 2659 bytes
-rw-r--r--public/-/emojis/2/wastebasket.pngbin0 -> 5979 bytes
-rw-r--r--public/-/emojis/2/watch.pngbin0 -> 4900 bytes
-rw-r--r--public/-/emojis/2/water_buffalo.pngbin0 -> 3875 bytes
-rw-r--r--public/-/emojis/2/water_polo.pngbin0 -> 4456 bytes
-rw-r--r--public/-/emojis/2/water_polo_tone1.pngbin0 -> 4577 bytes
-rw-r--r--public/-/emojis/2/water_polo_tone2.pngbin0 -> 4544 bytes
-rw-r--r--public/-/emojis/2/water_polo_tone3.pngbin0 -> 4534 bytes
-rw-r--r--public/-/emojis/2/water_polo_tone4.pngbin0 -> 4536 bytes
-rw-r--r--public/-/emojis/2/water_polo_tone5.pngbin0 -> 4593 bytes
-rw-r--r--public/-/emojis/2/watermelon.pngbin0 -> 4264 bytes
-rw-r--r--public/-/emojis/2/wave.pngbin0 -> 4474 bytes
-rw-r--r--public/-/emojis/2/wave_tone1.pngbin0 -> 4858 bytes
-rw-r--r--public/-/emojis/2/wave_tone2.pngbin0 -> 4912 bytes
-rw-r--r--public/-/emojis/2/wave_tone3.pngbin0 -> 4957 bytes
-rw-r--r--public/-/emojis/2/wave_tone4.pngbin0 -> 4639 bytes
-rw-r--r--public/-/emojis/2/wave_tone5.pngbin0 -> 4765 bytes
-rw-r--r--public/-/emojis/2/wavy_dash.pngbin0 -> 2238 bytes
-rw-r--r--public/-/emojis/2/waxing_crescent_moon.pngbin0 -> 4363 bytes
-rw-r--r--public/-/emojis/2/waxing_gibbous_moon.pngbin0 -> 4350 bytes
-rw-r--r--public/-/emojis/2/wc.pngbin0 -> 3464 bytes
-rw-r--r--public/-/emojis/2/weary.pngbin0 -> 5334 bytes
-rw-r--r--public/-/emojis/2/wedding.pngbin0 -> 5157 bytes
-rw-r--r--public/-/emojis/2/whale.pngbin0 -> 3872 bytes
-rw-r--r--public/-/emojis/2/whale2.pngbin0 -> 4330 bytes
-rw-r--r--public/-/emojis/2/wheel_of_dharma.pngbin0 -> 4707 bytes
-rw-r--r--public/-/emojis/2/wheelchair.pngbin0 -> 4014 bytes
-rw-r--r--public/-/emojis/2/white_check_mark.pngbin0 -> 2938 bytes
-rw-r--r--public/-/emojis/2/white_circle.pngbin0 -> 2714 bytes
-rw-r--r--public/-/emojis/2/white_flower.pngbin0 -> 4248 bytes
-rw-r--r--public/-/emojis/2/white_large_square.pngbin0 -> 946 bytes
-rw-r--r--public/-/emojis/2/white_medium_small_square.pngbin0 -> 657 bytes
-rw-r--r--public/-/emojis/2/white_medium_square.pngbin0 -> 693 bytes
-rw-r--r--public/-/emojis/2/white_small_square.pngbin0 -> 525 bytes
-rw-r--r--public/-/emojis/2/white_square_button.pngbin0 -> 1150 bytes
-rw-r--r--public/-/emojis/2/white_sun_cloud.pngbin0 -> 2314 bytes
-rw-r--r--public/-/emojis/2/white_sun_rain_cloud.pngbin0 -> 3147 bytes
-rw-r--r--public/-/emojis/2/white_sun_small_cloud.pngbin0 -> 3215 bytes
-rw-r--r--public/-/emojis/2/wilted_rose.pngbin0 -> 3372 bytes
-rw-r--r--public/-/emojis/2/wind_blowing_face.pngbin0 -> 4038 bytes
-rw-r--r--public/-/emojis/2/wind_chime.pngbin0 -> 3681 bytes
-rw-r--r--public/-/emojis/2/wine_glass.pngbin0 -> 3861 bytes
-rw-r--r--public/-/emojis/2/wink.pngbin0 -> 4847 bytes
-rw-r--r--public/-/emojis/2/wolf.pngbin0 -> 3840 bytes
-rw-r--r--public/-/emojis/2/woman.pngbin0 -> 4621 bytes
-rw-r--r--public/-/emojis/2/woman_tone1.pngbin0 -> 4677 bytes
-rw-r--r--public/-/emojis/2/woman_tone2.pngbin0 -> 4672 bytes
-rw-r--r--public/-/emojis/2/woman_tone3.pngbin0 -> 4448 bytes
-rw-r--r--public/-/emojis/2/woman_tone4.pngbin0 -> 4214 bytes
-rw-r--r--public/-/emojis/2/woman_tone5.pngbin0 -> 4272 bytes
-rw-r--r--public/-/emojis/2/womans_clothes.pngbin0 -> 2441 bytes
-rw-r--r--public/-/emojis/2/womans_hat.pngbin0 -> 4445 bytes
-rw-r--r--public/-/emojis/2/womens.pngbin0 -> 2469 bytes
-rw-r--r--public/-/emojis/2/worried.pngbin0 -> 4921 bytes
-rw-r--r--public/-/emojis/2/wrench.pngbin0 -> 3179 bytes
-rw-r--r--public/-/emojis/2/wrestlers.pngbin0 -> 5306 bytes
-rw-r--r--public/-/emojis/2/wrestlers_tone1.pngbin0 -> 5399 bytes
-rw-r--r--public/-/emojis/2/wrestlers_tone2.pngbin0 -> 5441 bytes
-rw-r--r--public/-/emojis/2/wrestlers_tone3.pngbin0 -> 5421 bytes
-rw-r--r--public/-/emojis/2/wrestlers_tone4.pngbin0 -> 5390 bytes
-rw-r--r--public/-/emojis/2/wrestlers_tone5.pngbin0 -> 5485 bytes
-rw-r--r--public/-/emojis/2/writing_hand.pngbin0 -> 4347 bytes
-rw-r--r--public/-/emojis/2/writing_hand_tone1.pngbin0 -> 4523 bytes
-rw-r--r--public/-/emojis/2/writing_hand_tone2.pngbin0 -> 4652 bytes
-rw-r--r--public/-/emojis/2/writing_hand_tone3.pngbin0 -> 4625 bytes
-rw-r--r--public/-/emojis/2/writing_hand_tone4.pngbin0 -> 4307 bytes
-rw-r--r--public/-/emojis/2/writing_hand_tone5.pngbin0 -> 4385 bytes
-rw-r--r--public/-/emojis/2/x.pngbin0 -> 3100 bytes
-rw-r--r--public/-/emojis/2/yellow_heart.pngbin0 -> 2958 bytes
-rw-r--r--public/-/emojis/2/yen.pngbin0 -> 2286 bytes
-rw-r--r--public/-/emojis/2/yin_yang.pngbin0 -> 3900 bytes
-rw-r--r--public/-/emojis/2/yum.pngbin0 -> 4930 bytes
-rw-r--r--public/-/emojis/2/zap.pngbin0 -> 2705 bytes
-rw-r--r--public/-/emojis/2/zero.pngbin0 -> 2234 bytes
-rw-r--r--public/-/emojis/2/zipper_mouth.pngbin0 -> 5280 bytes
-rw-r--r--public/-/emojis/2/zzz.pngbin0 -> 2030 bytes
-rw-r--r--public/robots.txt1
-rw-r--r--qa/Gemfile8
-rw-r--r--qa/Gemfile.lock68
-rw-r--r--qa/Rakefile1
-rw-r--r--qa/chemlab-library-gitlab.gemspec1
-rw-r--r--qa/lib/gitlab.rb29
-rw-r--r--qa/lib/gitlab/page/admin/subscription.rb9
-rw-r--r--qa/lib/gitlab/page/admin/subscription.stub.rb216
-rw-r--r--qa/lib/gitlab/page/main/welcome.rb13
-rw-r--r--qa/lib/gitlab/page/main/welcome.stub.rb33
-rw-r--r--qa/qa.rb3
-rw-r--r--qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb3
-rw-r--r--qa/qa/fixtures/rubygems_package/mygem.gemspec39
-rw-r--r--qa/qa/flow/login.rb7
-rw-r--r--qa/qa/mobile/page/main/menu.rb60
-rw-r--r--qa/qa/mobile/page/profile/menu.rb26
-rw-r--r--qa/qa/mobile/page/project/issue/show.rb37
-rw-r--r--qa/qa/mobile/page/project/show.rb31
-rw-r--r--qa/qa/mobile/page/sub_menus/common.rb28
-rw-r--r--qa/qa/page/base.rb29
-rw-r--r--qa/qa/page/component/issuable/sidebar.rb78
-rw-r--r--qa/qa/page/component/issue_board/show.rb19
-rw-r--r--qa/qa/page/group/bulk_import.rb2
-rw-r--r--qa/qa/page/group/settings/package_registries.rb22
-rw-r--r--qa/qa/page/group/show.rb5
-rw-r--r--qa/qa/page/main/login.rb6
-rw-r--r--qa/qa/page/main/menu.rb18
-rw-r--r--qa/qa/page/merge_request/show.rb11
-rw-r--r--qa/qa/page/profile/menu.rb4
-rw-r--r--qa/qa/page/project/fork/new.rb2
-rw-r--r--qa/qa/page/project/import/github.rb7
-rw-r--r--qa/qa/page/project/infrastructure/kubernetes/add.rb2
-rw-r--r--qa/qa/page/project/infrastructure/kubernetes/index.rb8
-rw-r--r--qa/qa/page/project/infrastructure/kubernetes/show.rb46
-rw-r--r--qa/qa/page/project/issue/show.rb5
-rw-r--r--qa/qa/page/project/job/show.rb6
-rw-r--r--qa/qa/page/project/monitor/metrics/show.rb1
-rw-r--r--qa/qa/page/project/new.rb8
-rw-r--r--qa/qa/page/project/registry/show.rb6
-rw-r--r--qa/qa/page/project/settings/deploy_tokens.rb12
-rw-r--r--qa/qa/page/project/show.rb7
-rw-r--r--qa/qa/page/project/sub_menus/common.rb4
-rw-r--r--qa/qa/page/sub_menus/common.rb4
-rw-r--r--qa/qa/resource/base.rb11
-rw-r--r--qa/qa/resource/bulk_import_group.rb12
-rw-r--r--qa/qa/resource/clusters/agent.rb13
-rw-r--r--qa/qa/resource/clusters/agent_token.rb13
-rw-r--r--qa/qa/resource/deploy_token.rb3
-rw-r--r--qa/qa/resource/file.rb2
-rw-r--r--qa/qa/resource/fork.rb8
-rw-r--r--qa/qa/resource/issue.rb47
-rw-r--r--qa/qa/resource/kubernetes_cluster/project_cluster.rb14
-rw-r--r--qa/qa/resource/merge_request_from_fork.rb2
-rw-r--r--qa/qa/resource/project.rb18
-rw-r--r--qa/qa/resource/sandbox.rb16
-rw-r--r--qa/qa/runtime/allure_report.rb9
-rw-r--r--qa/qa/runtime/browser.rb5
-rw-r--r--qa/qa/runtime/env.rb13
-rw-r--r--qa/qa/runtime/feature.rb38
-rw-r--r--qa/qa/scenario/bootable.rb16
-rw-r--r--qa/qa/scenario/shared_attributes.rb3
-rw-r--r--qa/qa/scenario/template.rb2
-rw-r--r--qa/qa/scenario/test/instance/reliable.rb16
-rw-r--r--qa/qa/scenario/test/integration/ldap_no_tls.rb3
-rw-r--r--qa/qa/scenario/test/integration/ldap_tls.rb3
-rw-r--r--qa/qa/scenario/test/integration/registry_tls.rb13
-rw-r--r--qa/qa/service/cluster_provider/gcloud.rb31
-rw-r--r--qa/qa/service/kubernetes_cluster.rb13
-rw-r--r--qa/qa/service/praefect_manager.rb94
-rw-r--r--qa/qa/specs/features/api/1_manage/bulk_import_group_spec.rb18
-rw-r--r--qa/qa/specs/features/api/1_manage/bulk_import_project_spec.rb71
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb15
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb10
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb62
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb27
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb32
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb97
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb191
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb (renamed from qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb)0
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb111
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/container_registry_omnibus_spec.rb88
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb99
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/dependency_proxy_spec.rb104
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb120
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/helm_registry_spec.rb150
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb195
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb340
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb233
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb210
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/online_garbage_collection_spec.rb108
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb (renamed from qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb)0
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb97
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb120
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb150
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb195
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb317
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb228
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb197
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb210
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb166
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb163
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb166
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/rubygems_registry_spec.rb125
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb1
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb62
-rw-r--r--qa/qa/specs/helpers/context_selector.rb4
-rw-r--r--qa/qa/support/fabrication_tracker.rb53
-rw-r--r--qa/qa/support/formatters/test_stats_formatter.rb13
-rw-r--r--qa/qa/support/helpers/plan.rb66
-rw-r--r--qa/qa/support/matchers/eventually_matcher.rb6
-rw-r--r--qa/qa/support/matchers/have_matcher.rb1
-rw-r--r--qa/qa/support/repeater.rb43
-rw-r--r--qa/qa/support/retrier.rb34
-rw-r--r--qa/qa/support/waiter.rb23
-rw-r--r--qa/qa/tools/reliable_report.rb234
-rw-r--r--qa/spec/runtime/feature_spec.rb48
-rw-r--r--qa/spec/scenario/test/instance/reliable_spec.rb7
-rw-r--r--qa/spec/spec_helper.rb12
-rw-r--r--qa/spec/specs/allure_report_spec.rb19
-rw-r--r--qa/spec/specs/helpers/context_selector_spec.rb18
-rw-r--r--qa/spec/support/formatters/test_stats_formatter_spec.rb26
-rw-r--r--qa/spec/support/repeater_spec.rb114
-rw-r--r--qa/spec/support/retrier_spec.rb71
-rw-r--r--qa/spec/support/shared_contexts/packages_registry_shared_context.rb7
-rw-r--r--qa/spec/support/waiter_spec.rb35
-rw-r--r--qa/spec/tools/reliable_report_spec.rb145
-rw-r--r--qa/tasks/reliable_report.rake21
-rw-r--r--rubocop/cop/gitlab/bulk_insert.rb6
-rw-r--r--rubocop/cop/gitlab/change_timezone.rb (renamed from rubocop/cop/gitlab/change_timzone.rb)0
-rw-r--r--rubocop/cop/gitlab/keys_first_and_values_first.rb (renamed from rubocop/cop/gitlab/keys-first-and-values-first.rb)0
-rw-r--r--rubocop/cop/gitlab/mark_used_feature_flags.rb9
-rw-r--r--rubocop/cop/qa/duplicate_testcase_link.rb46
-rw-r--r--rubocop/rubocop.rb3
-rw-r--r--scripts/api/default_options.rb7
-rwxr-xr-xscripts/changed-feature-flags59
-rwxr-xr-xscripts/docs_screenshots.rb2
-rwxr-xr-xscripts/failed_tests.rb122
-rwxr-xr-xscripts/lint-doc.sh2
-rwxr-xr-xscripts/no-dir-check9
-rwxr-xr-xscripts/no-ee-check9
-rwxr-xr-xscripts/pipeline_test_report_builder.rb153
-rwxr-xr-xscripts/regenerate-schema4
-rwxr-xr-xscripts/review_apps/review-apps.sh7
-rw-r--r--scripts/rspec_helpers.sh42
-rwxr-xr-xscripts/schema_changed.sh40
-rwxr-xr-xscripts/security-harness3
-rwxr-xr-xscripts/static-analysis6
-rwxr-xr-xscripts/trigger-build3
-rwxr-xr-xscripts/used-feature-flags16
-rw-r--r--scripts/utils.sh2
-rwxr-xr-xscripts/verify-tff-mapping4
-rw-r--r--sidekiq_cluster/cli.rb224
-rw-r--r--sidekiq_cluster/dependencies.rb6
-rw-r--r--sidekiq_cluster/sidekiq_cluster.rb184
-rw-r--r--spec/commands/sidekiq_cluster/cli_spec.rb336
-rw-r--r--spec/controllers/admin/integrations_controller_spec.rb2
-rw-r--r--spec/controllers/admin/runners_controller_spec.rb4
-rw-r--r--spec/controllers/application_controller_spec.rb32
-rw-r--r--spec/controllers/concerns/group_tree_spec.rb8
-rw-r--r--spec/controllers/concerns/import_url_params_spec.rb2
-rw-r--r--spec/controllers/concerns/renders_commits_spec.rb6
-rw-r--r--spec/controllers/confirmations_controller_spec.rb41
-rw-r--r--spec/controllers/dashboard/todos_controller_spec.rb2
-rw-r--r--spec/controllers/explore/projects_controller_spec.rb22
-rw-r--r--spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb158
-rw-r--r--spec/controllers/groups/settings/integrations_controller_spec.rb6
-rw-r--r--spec/controllers/groups_controller_spec.rb10
-rw-r--r--spec/controllers/import/bitbucket_controller_spec.rb24
-rw-r--r--spec/controllers/jira_connect/app_descriptor_controller_spec.rb12
-rw-r--r--spec/controllers/jira_connect/events_controller_spec.rb75
-rw-r--r--spec/controllers/oauth/authorizations_controller_spec.rb7
-rw-r--r--spec/controllers/passwords_controller_spec.rb43
-rw-r--r--spec/controllers/profiles/accounts_controller_spec.rb2
-rw-r--r--spec/controllers/profiles/two_factor_auths_controller_spec.rb28
-rw-r--r--spec/controllers/profiles_controller_spec.rb10
-rw-r--r--spec/controllers/projects/alerting/notifications_controller_spec.rb10
-rw-r--r--spec/controllers/projects/analytics/cycle_analytics/stages_controller_spec.rb1
-rw-r--r--spec/controllers/projects/branches_controller_spec.rb6
-rw-r--r--spec/controllers/projects/ci/pipeline_editor_controller_spec.rb20
-rw-r--r--spec/controllers/projects/commits_controller_spec.rb23
-rw-r--r--spec/controllers/projects/hooks_controller_spec.rb2
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb34
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb83
-rw-r--r--spec/controllers/projects/merge_requests/diffs_controller_spec.rb6
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb26
-rw-r--r--spec/controllers/projects/notes_controller_spec.rb29
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb2
-rw-r--r--spec/controllers/projects/prometheus/alerts_controller_spec.rb11
-rw-r--r--spec/controllers/projects/releases_controller_spec.rb13
-rw-r--r--spec/controllers/projects/services_controller_spec.rb6
-rw-r--r--spec/controllers/projects/tags_controller_spec.rb2
-rw-r--r--spec/controllers/projects_controller_spec.rb31
-rw-r--r--spec/controllers/registrations/welcome_controller_spec.rb10
-rw-r--r--spec/controllers/registrations_controller_spec.rb5
-rw-r--r--spec/db/schema_spec.rb9
-rw-r--r--spec/experiments/change_continuous_onboarding_link_urls_experiment_spec.rb53
-rw-r--r--spec/experiments/empty_repo_upload_experiment_spec.rb49
-rw-r--r--spec/factories/analytics/cycle_analytics/issue_stage_events.rb13
-rw-r--r--spec/factories/analytics/cycle_analytics/merge_request_stage_events.rb13
-rw-r--r--spec/factories/authentication_event.rb8
-rw-r--r--spec/factories/ci/builds.rb8
-rw-r--r--spec/factories/ci/job_artifacts.rb11
-rw-r--r--spec/factories/ci/pipelines.rb8
-rw-r--r--spec/factories/ci/reports/security/findings.rb4
-rw-r--r--spec/factories/ci/runner_namespaces.rb9
-rw-r--r--spec/factories/ci/runners.rb9
-rw-r--r--spec/factories/customer_relations/issue_customer_relations_contacts.rb27
-rw-r--r--spec/factories/design_management/designs.rb2
-rw-r--r--spec/factories/error_tracking/error_event.rb4
-rw-r--r--spec/factories/gitlab/database/reindexing/queued_action.rb10
-rw-r--r--spec/factories/group_members.rb13
-rw-r--r--spec/factories/integrations.rb11
-rw-r--r--spec/factories/member_tasks.rb9
-rw-r--r--spec/factories/namespaces/project_namespaces.rb2
-rw-r--r--spec/factories/operations/feature_flags/strategy.rb32
-rw-r--r--spec/factories/packages/helm/file_metadatum.rb6
-rw-r--r--spec/factories/packages/npm/metadata.rb18
-rw-r--r--spec/factories/project_members.rb10
-rw-r--r--spec/factories/user_highest_roles.rb10
-rw-r--r--spec/factories/users/credit_card_validations.rb7
-rw-r--r--spec/factories_spec.rb4
-rw-r--r--spec/features/admin/admin_appearance_spec.rb2
-rw-r--r--spec/features/admin/admin_deploy_keys_spec.rb28
-rw-r--r--spec/features/admin/admin_disables_two_factor_spec.rb1
-rw-r--r--spec/features/admin/admin_groups_spec.rb1
-rw-r--r--spec/features/admin/admin_hooks_spec.rb1
-rw-r--r--spec/features/admin/admin_labels_spec.rb1
-rw-r--r--spec/features/admin/admin_manage_applications_spec.rb1
-rw-r--r--spec/features/admin/admin_runners_spec.rb113
-rw-r--r--spec/features/admin/admin_sees_project_statistics_spec.rb2
-rw-r--r--spec/features/admin/admin_settings_spec.rb8
-rw-r--r--spec/features/admin/admin_users_impersonation_tokens_spec.rb1
-rw-r--r--spec/features/admin/admin_uses_repository_checks_spec.rb1
-rw-r--r--spec/features/admin/clusters/eks_spec.rb2
-rw-r--r--spec/features/admin/users/user_spec.rb1
-rw-r--r--spec/features/admin/users/users_spec.rb7
-rw-r--r--spec/features/alert_management/alert_management_list_spec.rb24
-rw-r--r--spec/features/boards/boards_spec.rb1
-rw-r--r--spec/features/clusters/create_agent_spec.rb44
-rw-r--r--spec/features/contextual_sidebar_spec.rb109
-rw-r--r--spec/features/cycle_analytics_spec.rb24
-rw-r--r--spec/features/dashboard/projects_spec.rb8
-rw-r--r--spec/features/explore/topics_spec.rb25
-rw-r--r--spec/features/graphql_known_operations_spec.rb29
-rw-r--r--spec/features/groups/clusters/eks_spec.rb2
-rw-r--r--spec/features/groups/clusters/user_spec.rb4
-rw-r--r--spec/features/groups/dependency_proxy_spec.rb9
-rw-r--r--spec/features/groups/issues_spec.rb47
-rw-r--r--spec/features/groups/labels/subscription_spec.rb4
-rw-r--r--spec/features/groups/members/leave_group_spec.rb1
-rw-r--r--spec/features/groups/navbar_spec.rb17
-rw-r--r--spec/features/groups/packages_spec.rb4
-rw-r--r--spec/features/groups/settings/manage_applications_spec.rb1
-rw-r--r--spec/features/incidents/user_creates_new_incident_spec.rb55
-rw-r--r--spec/features/incidents/user_views_incident_spec.rb28
-rw-r--r--spec/features/invites_spec.rb14
-rw-r--r--spec/features/issuables/markdown_references/internal_references_spec.rb15
-rw-r--r--spec/features/issue_rebalancing_spec.rb65
-rw-r--r--spec/features/issues/form_spec.rb72
-rw-r--r--spec/features/issues/issue_detail_spec.rb64
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb58
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb5
-rw-r--r--spec/features/issues/user_toggles_subscription_spec.rb2
-rw-r--r--spec/features/issues/user_uses_quick_actions_spec.rb1
-rw-r--r--spec/features/jira_connect/subscriptions_spec.rb4
-rw-r--r--spec/features/merge_request/user_approves_spec.rb2
-rw-r--r--spec/features/merge_request/user_assigns_themselves_spec.rb2
-rw-r--r--spec/features/merge_request/user_comments_on_diff_spec.rb1
-rw-r--r--spec/features/merge_request/user_customizes_merge_commit_message_spec.rb26
-rw-r--r--spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb4
-rw-r--r--spec/features/merge_request/user_posts_diff_notes_spec.rb7
-rw-r--r--spec/features/merge_request/user_posts_notes_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb1
-rw-r--r--spec/features/merge_request/user_sees_deployment_widget_spec.rb1
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_suggest_pipeline_spec.rb40
-rw-r--r--spec/features/oauth_login_spec.rb2
-rw-r--r--spec/features/profile_spec.rb2
-rw-r--r--spec/features/profiles/active_sessions_spec.rb4
-rw-r--r--spec/features/profiles/emails_spec.rb17
-rw-r--r--spec/features/profiles/oauth_applications_spec.rb1
-rw-r--r--spec/features/profiles/personal_access_tokens_spec.rb1
-rw-r--r--spec/features/profiles/two_factor_auths_spec.rb25
-rw-r--r--spec/features/profiles/user_manages_applications_spec.rb1
-rw-r--r--spec/features/profiles/user_manages_emails_spec.rb15
-rw-r--r--spec/features/profiles/user_visits_profile_spec.rb8
-rw-r--r--spec/features/project_variables_spec.rb2
-rw-r--r--spec/features/projects/branches/user_deletes_branch_spec.rb1
-rw-r--r--spec/features/projects/branches_spec.rb1
-rw-r--r--spec/features/projects/cluster_agents_spec.rb53
-rw-r--r--spec/features/projects/clusters/eks_spec.rb3
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb22
-rw-r--r--spec/features/projects/clusters/user_spec.rb6
-rw-r--r--spec/features/projects/clusters_spec.rb26
-rw-r--r--spec/features/projects/commit/comments/user_deletes_comments_spec.rb1
-rw-r--r--spec/features/projects/commit/user_comments_on_commit_spec.rb2
-rw-r--r--spec/features/projects/confluence/user_views_confluence_page_spec.rb3
-rw-r--r--spec/features/projects/environments/environment_spec.rb36
-rw-r--r--spec/features/projects/environments/environments_spec.rb3
-rw-r--r--spec/features/projects/import_export/import_file_spec.rb8
-rw-r--r--spec/features/projects/infrastructure_registry_spec.rb2
-rw-r--r--spec/features/projects/integrations/user_uses_inherited_settings_spec.rb2
-rw-r--r--spec/features/projects/jobs/user_browses_job_spec.rb27
-rw-r--r--spec/features/projects/jobs/user_triggers_manual_job_with_variables_spec.rb34
-rw-r--r--spec/features/projects/members/member_leaves_project_spec.rb1
-rw-r--r--spec/features/projects/members/user_requests_access_spec.rb1
-rw-r--r--spec/features/projects/new_project_spec.rb36
-rw-r--r--spec/features/projects/packages_spec.rb4
-rw-r--r--spec/features/projects/pages/user_adds_domain_spec.rb2
-rw-r--r--spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb1
-rw-r--r--spec/features/projects/pages/user_edits_settings_spec.rb1
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb1
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb3
-rw-r--r--spec/features/projects/releases/user_views_releases_spec.rb4
-rw-r--r--spec/features/projects/settings/access_tokens_spec.rb1
-rw-r--r--spec/features/projects/settings/packages_settings_spec.rb4
-rw-r--r--spec/features/projects/settings/service_desk_setting_spec.rb2
-rw-r--r--spec/features/projects/settings/user_searches_in_settings_spec.rb1
-rw-r--r--spec/features/projects/settings/user_tags_project_spec.rb26
-rw-r--r--spec/features/projects/show/no_password_spec.rb11
-rw-r--r--spec/features/projects/show/user_uploads_files_spec.rb28
-rw-r--r--spec/features/projects/user_changes_project_visibility_spec.rb2
-rw-r--r--spec/features/projects/user_creates_project_spec.rb8
-rw-r--r--spec/features/projects_spec.rb12
-rw-r--r--spec/features/signed_commits_spec.rb16
-rw-r--r--spec/features/snippets/notes_on_personal_snippets_spec.rb1
-rw-r--r--spec/features/snippets/user_creates_snippet_spec.rb1
-rw-r--r--spec/features/topic_show_spec.rb48
-rw-r--r--spec/features/triggers_spec.rb1
-rw-r--r--spec/features/users/confirmation_spec.rb30
-rw-r--r--spec/features/users/login_spec.rb6
-rw-r--r--spec/features/users/password_spec.rb30
-rw-r--r--spec/features/users/terms_spec.rb2
-rw-r--r--spec/finders/autocomplete/routes_finder_spec.rb57
-rw-r--r--spec/finders/branches_finder_spec.rb8
-rw-r--r--spec/finders/ci/pipelines_for_merge_request_finder_spec.rb150
-rw-r--r--spec/finders/clusters/agent_authorizations_finder_spec.rb124
-rw-r--r--spec/finders/environments/environments_by_deployments_finder_spec.rb14
-rw-r--r--spec/finders/members_finder_spec.rb8
-rw-r--r--spec/finders/tags_finder_spec.rb81
-rw-r--r--spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json3
-rw-r--r--spec/fixtures/api/schemas/graphql/packages/package_details.json4
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/deploy_key.json25
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/deploy_keys.json4
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/npm_package_version.json12
-rw-r--r--spec/fixtures/bulk_imports/gz/milestones.ndjson.gzbin402 -> 0 bytes
-rw-r--r--spec/fixtures/bulk_imports/milestones.ndjson5
-rw-r--r--spec/fixtures/emails/service_desk_all_quoted.eml22
-rw-r--r--spec/fixtures/emails/service_desk_custom_address_no_key.eml27
-rw-r--r--spec/fixtures/emails/service_desk_forwarded.eml4
-rw-r--r--spec/fixtures/error_tracking/browser_event.json1
-rw-r--r--spec/fixtures/error_tracking/go_parsed_event.json1
-rw-r--r--spec/fixtures/error_tracking/python_event.json1
-rw-r--r--spec/fixtures/gitlab/import_export/lightweight_project_export.tar.gzbin3647 -> 3758 bytes
-rw-r--r--spec/fixtures/lib/gitlab/import_export/complex/project.json308
-rw-r--r--spec/fixtures/lib/gitlab/import_export/complex/tree/project/merge_requests.ndjson16
-rw-r--r--spec/fixtures/packages/npm/payload.json3
-rw-r--r--spec/fixtures/packages/npm/payload_with_duplicated_packages.json3
-rw-r--r--spec/fixtures/scripts/test_report.json36
-rw-r--r--spec/frontend/__helpers__/experimentation_helper.js29
-rw-r--r--spec/frontend/__mocks__/@gitlab/ui.js4
-rw-r--r--spec/frontend/admin/analytics/devops_score/components/devops_score_callout_spec.js4
-rw-r--r--spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js4
-rw-r--r--spec/frontend/admin/deploy_keys/components/table_spec.js47
-rw-r--r--spec/frontend/alert_handler_spec.js12
-rw-r--r--spec/frontend/alert_management/components/alert_management_table_spec.js18
-rw-r--r--spec/frontend/alerts_settings/components/alerts_settings_form_spec.js19
-rw-r--r--spec/frontend/analytics/devops_report/components/service_ping_disabled_spec.js59
-rw-r--r--spec/frontend/analytics/devops_reports/components/service_ping_disabled_spec.js59
-rw-r--r--spec/frontend/authentication/two_factor_auth/components/manage_two_factor_form_spec.js150
-rw-r--r--spec/frontend/batch_comments/components/preview_dropdown_spec.js6
-rw-r--r--spec/frontend/behaviors/gl_emoji_spec.js6
-rw-r--r--spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap14
-rw-r--r--spec/frontend/blob/components/blob_header_spec.js2
-rw-r--r--spec/frontend/blob/components/table_contents_spec.js22
-rw-r--r--spec/frontend/boards/components/board_card_spec.js4
-rw-r--r--spec/frontend/boards/components/board_filtered_search_spec.js33
-rw-r--r--spec/frontend/boards/components/board_form_spec.js18
-rw-r--r--spec/frontend/boards/components/boards_selector_spec.js251
-rw-r--r--spec/frontend/boards/components/issue_board_filtered_search_spec.js57
-rw-r--r--spec/frontend/boards/components/new_board_button_spec.js75
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js1
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js11
-rw-r--r--spec/frontend/boards/mock_data.js87
-rw-r--r--spec/frontend/boards/stores/actions_spec.js72
-rw-r--r--spec/frontend/chronic_duration_spec.js354
-rw-r--r--spec/frontend/clusters/agents/components/show_spec.js63
-rw-r--r--spec/frontend/clusters/components/remove_cluster_confirmation_spec.js45
-rw-r--r--spec/frontend/clusters_list/components/agent_empty_state_spec.js16
-rw-r--r--spec/frontend/clusters_list/components/agent_table_spec.js9
-rw-r--r--spec/frontend/clusters_list/components/agents_spec.js40
-rw-r--r--spec/frontend/clusters_list/components/clusters_actions_spec.js55
-rw-r--r--spec/frontend/clusters_list/components/clusters_empty_state_spec.js104
-rw-r--r--spec/frontend/clusters_list/components/clusters_main_view_spec.js82
-rw-r--r--spec/frontend/clusters_list/components/clusters_spec.js60
-rw-r--r--spec/frontend/clusters_list/components/clusters_view_all_spec.js243
-rw-r--r--spec/frontend/clusters_list/components/install_agent_modal_spec.js38
-rw-r--r--spec/frontend/clusters_list/mocks/apollo.js47
-rw-r--r--spec/frontend/clusters_list/store/mutations_spec.js10
-rw-r--r--spec/frontend/commit/pipelines/pipelines_table_spec.js18
-rw-r--r--spec/frontend/confirm_modal_spec.js4
-rw-r--r--spec/frontend/content_editor/components/content_editor_alert_spec.js60
-rw-r--r--spec/frontend/content_editor/components/content_editor_error_spec.js54
-rw-r--r--spec/frontend/content_editor/components/content_editor_spec.js6
-rw-r--r--spec/frontend/content_editor/components/wrappers/table_cell_base_spec.js8
-rw-r--r--spec/frontend/content_editor/components/wrappers/table_cell_body_spec.js8
-rw-r--r--spec/frontend/content_editor/components/wrappers/table_cell_header_spec.js8
-rw-r--r--spec/frontend/content_editor/extensions/attachment_spec.js20
-rw-r--r--spec/frontend/content_editor/extensions/blockquote_spec.js46
-rw-r--r--spec/frontend/content_editor/extensions/emoji_spec.js10
-rw-r--r--spec/frontend/content_editor/extensions/frontmatter_spec.js30
-rw-r--r--spec/frontend/content_editor/extensions/horizontal_rule_spec.js49
-rw-r--r--spec/frontend/content_editor/extensions/inline_diff_spec.js60
-rw-r--r--spec/frontend/content_editor/extensions/link_spec.js91
-rw-r--r--spec/frontend/content_editor/extensions/math_inline_spec.js11
-rw-r--r--spec/frontend/content_editor/extensions/table_of_contents_spec.js32
-rw-r--r--spec/frontend/content_editor/extensions/table_spec.js102
-rw-r--r--spec/frontend/content_editor/extensions/word_break_spec.js35
-rw-r--r--spec/frontend/content_editor/services/markdown_serializer_spec.js4
-rw-r--r--spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js11
-rw-r--r--spec/frontend/content_editor/test_utils.js23
-rw-r--r--spec/frontend/create_merge_request_dropdown_spec.js5
-rw-r--r--spec/frontend/crm/contacts_root_spec.js60
-rw-r--r--spec/frontend/crm/mock_data.js81
-rw-r--r--spec/frontend/crm/organizations_root_spec.js60
-rw-r--r--spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js10
-rw-r--r--spec/frontend/cycle_analytics/metric_popover_spec.js102
-rw-r--r--spec/frontend/cycle_analytics/mock_data.js41
-rw-r--r--spec/frontend/cycle_analytics/store/actions_spec.js144
-rw-r--r--spec/frontend/cycle_analytics/store/mutations_spec.js1
-rw-r--r--spec/frontend/cycle_analytics/utils_spec.js96
-rw-r--r--spec/frontend/cycle_analytics/value_stream_metrics_spec.js58
-rw-r--r--spec/frontend/delete_label_modal_spec.js4
-rw-r--r--spec/frontend/deploy_keys/components/key_spec.js10
-rw-r--r--spec/frontend/deploy_keys/components/keys_panel_spec.js2
-rw-r--r--spec/frontend/deprecated_jquery_dropdown_spec.js6
-rw-r--r--spec/frontend/design_management/components/list/item_spec.js2
-rw-r--r--spec/frontend/design_management/pages/index_spec.js14
-rw-r--r--spec/frontend/diffs/components/app_spec.js34
-rw-r--r--spec/frontend/diffs/components/diff_discussions_spec.js4
-rw-r--r--spec/frontend/diffs/components/diff_file_header_spec.js23
-rw-r--r--spec/frontend/diffs/components/diff_line_note_form_spec.js89
-rw-r--r--spec/frontend/diffs/components/tree_list_spec.js4
-rw-r--r--spec/frontend/diffs/store/actions_spec.js51
-rw-r--r--spec/frontend/diffs/store/mutations_spec.js24
-rw-r--r--spec/frontend/diffs/utils/diff_line_spec.js30
-rw-r--r--spec/frontend/diffs/utils/discussions_spec.js133
-rw-r--r--spec/frontend/diffs/utils/file_reviews_spec.js24
-rw-r--r--spec/frontend/dropzone_input_spec.js19
-rw-r--r--spec/frontend/editor/helpers.js53
-rw-r--r--spec/frontend/editor/source_editor_extension_base_spec.js68
-rw-r--r--spec/frontend/editor/source_editor_extension_spec.js65
-rw-r--r--spec/frontend/editor/source_editor_instance_spec.js387
-rw-r--r--spec/frontend/editor/source_editor_yaml_ext_spec.js449
-rw-r--r--spec/frontend/environments/graphql/mock_data.js530
-rw-r--r--spec/frontend/environments/graphql/resolvers_spec.js91
-rw-r--r--spec/frontend/environments/new_environment_folder_spec.js74
-rw-r--r--spec/frontend/environments/new_environments_app_spec.js50
-rw-r--r--spec/frontend/experimentation/utils_spec.js198
-rw-r--r--spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js13
-rw-r--r--spec/frontend/filterable_list_spec.js5
-rw-r--r--spec/frontend/fixtures/api_markdown.yml332
-rw-r--r--spec/frontend/fixtures/projects.rb26
-rw-r--r--spec/frontend/flash_spec.js11
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js12
-rw-r--r--spec/frontend/google_cloud/components/app_spec.js66
-rw-r--r--spec/frontend/google_cloud/components/incubation_banner_spec.js60
-rw-r--r--spec/frontend/google_cloud/components/service_accounts_spec.js79
-rw-r--r--spec/frontend/graphql_shared/utils_spec.js4
-rw-r--r--spec/frontend/group_settings/components/shared_runners_form_spec.js47
-rw-r--r--spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap2
-rw-r--r--spec/frontend/ide/components/shared/commit_message_field_spec.js149
-rw-r--r--spec/frontend/ide/stores/mutations_spec.js4
-rw-r--r--spec/frontend/import_entities/components/group_dropdown_spec.js18
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js33
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_source_cell_spec.js27
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_table_spec.js235
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js96
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js442
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/fixtures.js42
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/services/local_storage_cache_spec.js61
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js64
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js102
-rw-r--r--spec/frontend/import_entities/import_groups/services/status_poller_spec.js97
-rw-r--r--spec/frontend/incidents/components/incidents_list_spec.js26
-rw-r--r--spec/frontend/integrations/edit/components/dynamic_field_spec.js229
-rw-r--r--spec/frontend/integrations/edit/components/jira_issues_fields_spec.js87
-rw-r--r--spec/frontend/integrations/integration_settings_form_spec.js303
-rw-r--r--spec/frontend/invite_members/components/confetti_spec.js28
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js210
-rw-r--r--spec/frontend/invite_members/components/invite_members_trigger_spec.js35
-rw-r--r--spec/frontend/issuable/components/csv_import_modal_spec.js8
-rw-r--r--spec/frontend/issue_show/components/app_spec.js38
-rw-r--r--spec/frontend/issue_show/components/description_spec.js22
-rw-r--r--spec/frontend/issue_show/components/fields/type_spec.js26
-rw-r--r--spec/frontend/issues_list/components/issues_list_app_spec.js2
-rw-r--r--spec/frontend/issues_list/components/new_issue_dropdown_spec.js6
-rw-r--r--spec/frontend/issues_list/mock_data.js86
-rw-r--r--spec/frontend/issues_list/utils_spec.js8
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js44
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal_spec.js36
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js112
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js303
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/app_spec.js176
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/groups_list_item_spec.js112
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/groups_list_spec.js303
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js48
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js50
-rw-r--r--spec/frontend/jira_connect/subscriptions/index_spec.js36
-rw-r--r--spec/frontend/jira_connect/subscriptions/utils_spec.js22
-rw-r--r--spec/frontend/jobs/components/manual_variables_form_spec.js152
-rw-r--r--spec/frontend/lib/apollo/suppress_network_errors_during_navigation_link_spec.js150
-rw-r--r--spec/frontend/lib/utils/common_utils_spec.js23
-rw-r--r--spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js59
-rw-r--r--spec/frontend/lib/utils/datetime_utility_spec.js10
-rw-r--r--spec/frontend/lib/utils/file_upload_spec.js28
-rw-r--r--spec/frontend/lib/utils/text_markdown_spec.js4
-rw-r--r--spec/frontend/lib/utils/url_utility_spec.js8
-rw-r--r--spec/frontend/members/mock_data.js2
-rw-r--r--spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap43
-rw-r--r--spec/frontend/monitoring/alert_widget_spec.js423
-rw-r--r--spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap2
-rw-r--r--spec/frontend/monitoring/components/alert_widget_form_spec.js242
-rw-r--r--spec/frontend/monitoring/components/charts/anomaly_spec.js4
-rw-r--r--spec/frontend/monitoring/components/charts/time_series_spec.js1
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_builder_spec.js1
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_spec.js106
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js33
-rw-r--r--spec/frontend/monitoring/components/dashboard_url_time_spec.js1
-rw-r--r--spec/frontend/monitoring/components/links_section_spec.js10
-rw-r--r--spec/frontend/monitoring/components/variables/text_field_spec.js4
-rw-r--r--spec/frontend/monitoring/pages/dashboard_page_spec.js4
-rw-r--r--spec/frontend/monitoring/router_spec.js3
-rw-r--r--spec/frontend/notes/components/discussion_counter_spec.js6
-rw-r--r--spec/frontend/notes/components/discussion_notes_spec.js4
-rw-r--r--spec/frontend/notes/components/multiline_comment_form_spec.js12
-rw-r--r--spec/frontend/notes/components/note_body_spec.js1
-rw-r--r--spec/frontend/notes/components/note_form_spec.js2
-rw-r--r--spec/frontend/notes/components/noteable_discussion_spec.js10
-rw-r--r--spec/frontend/notes/components/notes_app_spec.js59
-rw-r--r--spec/frontend/notes/mixins/discussion_navigation_spec.js61
-rw-r--r--spec/frontend/notes/stores/actions_spec.js91
-rw-r--r--spec/frontend/notes/stores/mutation_spec.js10
-rw-r--r--spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap6
-rw-r--r--spec/frontend/packages/list/components/packages_list_app_spec.js45
-rw-r--r--spec/frontend/packages/list/components/packages_search_spec.js128
-rw-r--r--spec/frontend/packages/list/components/packages_title_spec.js71
-rw-r--r--spec/frontend/packages/list/components/tokens/package_type_token_spec.js48
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap84
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/delete_button_spec.js73
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/delete_image_spec.js152
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap (renamed from spec/frontend/registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_alert_spec.js116
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_modal_spec.js152
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js304
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/empty_state_spec.js54
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert_spec.js74
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/status_alert_spec.js57
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js382
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js314
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js45
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap (renamed from spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap (renamed from spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js87
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cli_commands_spec.js94
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js37
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js223
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js88
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js45
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js135
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/registry_breadcrumb_spec.js78
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js (renamed from spec/frontend/registry/explorer/mock_data.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js521
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/index_spec.js24
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js597
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/stubs.js45
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/app_spec.js99
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js84
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/components/manifest_row_spec.js59
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/mock_data.js21
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap16
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap1
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/app_spec.js53
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/installations_commands_spec.js14
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js160
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/app_spec.js.snap57
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/app_spec.js168
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js244
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/packages_title_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js8
-rw-r--r--spec/frontend/packages_and_registries/package_registry/mock_data.js17
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/shared/mocks.js (renamed from spec/frontend/registry/shared/mocks.js)0
-rw-r--r--spec/frontend/packages_and_registries/shared/stubs.js (renamed from spec/frontend/registry/shared/stubs.js)0
-rw-r--r--spec/frontend/pages/admin/projects/components/namespace_select_spec.js8
-rw-r--r--spec/frontend/pages/dashboard/todos/index/todos_spec.js4
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap7
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js33
-rw-r--r--spec/frontend/pages/shared/wikis/components/wiki_form_spec.js26
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_form_spec.js19
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_section_spec.js16
-rw-r--r--spec/frontend/pipeline_editor/components/drawer/pipeline_editor_drawer_spec.js37
-rw-r--r--spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js38
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js39
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js72
-rw-r--r--spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js132
-rw-r--r--spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js2
-rw-r--r--spec/frontend/pipeline_editor/components/walkthrough_popover_spec.js29
-rw-r--r--spec/frontend/pipeline_editor/mock_data.js82
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_app_spec.js117
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_home_spec.js106
-rw-r--r--spec/frontend/pipelines/empty_state_spec.js2
-rw-r--r--spec/frontend/pipelines/graph/graph_component_wrapper_spec.js2
-rw-r--r--spec/frontend/pipelines/graph/graph_view_selector_spec.js2
-rw-r--r--spec/frontend/pipelines/pipelines_artifacts_spec.js83
-rw-r--r--spec/frontend/pipelines/pipelines_spec.js6
-rw-r--r--spec/frontend/pipelines/pipelines_table_spec.js6
-rw-r--r--spec/frontend/projects/commit/components/form_modal_spec.js15
-rw-r--r--spec/frontend/projects/commits/components/author_select_spec.js2
-rw-r--r--spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap41
-rw-r--r--spec/frontend/projects/components/project_delete_button_spec.js12
-rw-r--r--spec/frontend/projects/details/upload_button_spec.js7
-rw-r--r--spec/frontend/projects/new/components/new_project_url_select_spec.js39
-rw-r--r--spec/frontend/projects/pipelines/charts/components/app_spec.js24
-rw-r--r--spec/frontend/projects/projects_filterable_list_spec.js5
-rw-r--r--spec/frontend/projects/settings/topics/components/topics_token_selector_spec.js98
-rw-r--r--spec/frontend/projects/settings_service_desk/components/mock_data.js8
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js2
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js80
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_template_dropdown_spec.js80
-rw-r--r--spec/frontend/projects/storage_counter/components/storage_table_spec.js5
-rw-r--r--spec/frontend/projects/storage_counter/components/storage_type_icon_spec.js41
-rw-r--r--spec/frontend/projects/storage_counter/mock_data.js33
-rw-r--r--spec/frontend/projects/storage_counter/utils_spec.js17
-rw-r--r--spec/frontend/projects/upload_file_experiment_tracking_spec.js43
-rw-r--r--spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap72
-rw-r--r--spec/frontend/registry/explorer/components/delete_button_spec.js73
-rw-r--r--spec/frontend/registry/explorer/components/delete_image_spec.js152
-rw-r--r--spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js116
-rw-r--r--spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js152
-rw-r--r--spec/frontend/registry/explorer/components/details_page/details_header_spec.js304
-rw-r--r--spec/frontend/registry/explorer/components/details_page/empty_state_spec.js54
-rw-r--r--spec/frontend/registry/explorer/components/details_page/partial_cleanup_alert_spec.js71
-rw-r--r--spec/frontend/registry/explorer/components/details_page/status_alert_spec.js57
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js382
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_spec.js311
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js45
-rw-r--r--spec/frontend/registry/explorer/components/list_page/cleanup_status_spec.js87
-rw-r--r--spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js94
-rw-r--r--spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js37
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js223
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_spec.js88
-rw-r--r--spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js45
-rw-r--r--spec/frontend/registry/explorer/components/list_page/registry_header_spec.js135
-rw-r--r--spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js78
-rw-r--r--spec/frontend/registry/explorer/pages/details_spec.js521
-rw-r--r--spec/frontend/registry/explorer/pages/index_spec.js24
-rw-r--r--spec/frontend/registry/explorer/pages/list_spec.js597
-rw-r--r--spec/frontend/registry/explorer/stubs.js45
-rw-r--r--spec/frontend/related_merge_requests/components/related_merge_requests_spec.js4
-rw-r--r--spec/frontend/releases/components/tag_field_new_spec.js4
-rw-r--r--spec/frontend/repository/components/blob_content_viewer_spec.js399
-rw-r--r--spec/frontend/repository/components/upload_blob_modal_spec.js10
-rw-r--r--spec/frontend/repository/mock_data.js57
-rw-r--r--spec/frontend/runner/admin_runners/admin_runners_app_spec.js39
-rw-r--r--spec/frontend/runner/components/cells/runner_actions_cell_spec.js27
-rw-r--r--spec/frontend/runner/components/cells/runner_status_cell_spec.js69
-rw-r--r--spec/frontend/runner/components/cells/runner_summary_cell_spec.js39
-rw-r--r--spec/frontend/runner/components/cells/runner_type_cell_spec.js48
-rw-r--r--spec/frontend/runner/components/helpers/masked_value_spec.js51
-rw-r--r--spec/frontend/runner/components/registration/registration_dropdown_spec.js169
-rw-r--r--spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js194
-rw-r--r--spec/frontend/runner/components/registration/registration_token_spec.js109
-rw-r--r--spec/frontend/runner/components/runner_contacted_state_badge_spec.js86
-rw-r--r--spec/frontend/runner/components/runner_filtered_search_bar_spec.js60
-rw-r--r--spec/frontend/runner/components/runner_list_spec.js59
-rw-r--r--spec/frontend/runner/components/runner_manual_setup_help_spec.js122
-rw-r--r--spec/frontend/runner/components/runner_paused_badge_spec.js45
-rw-r--r--spec/frontend/runner/components/runner_registration_token_reset_spec.js189
-rw-r--r--spec/frontend/runner/components/runner_state_locked_badge_spec.js45
-rw-r--r--spec/frontend/runner/components/runner_state_paused_badge_spec.js45
-rw-r--r--spec/frontend/runner/components/runner_tag_spec.js46
-rw-r--r--spec/frontend/runner/components/runner_tags_spec.js10
-rw-r--r--spec/frontend/runner/components/runner_type_alert_spec.js14
-rw-r--r--spec/frontend/runner/components/runner_type_badge_spec.js14
-rw-r--r--spec/frontend/runner/components/runner_type_tabs_spec.js109
-rw-r--r--spec/frontend/runner/group_runners/group_runners_app_spec.js37
-rw-r--r--spec/frontend/runner/runner_search_utils_spec.js36
-rw-r--r--spec/frontend/search/sidebar/components/app_spec.js56
-rw-r--r--spec/frontend/search/store/actions_spec.js31
-rw-r--r--spec/frontend/search/store/mutations_spec.js10
-rw-r--r--spec/frontend/search/store/utils_spec.js29
-rw-r--r--spec/frontend/security_configuration/components/app_spec.js43
-rw-r--r--spec/frontend/security_configuration/components/feature_card_spec.js11
-rw-r--r--spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js21
-rw-r--r--spec/frontend/sidebar/components/attention_required_toggle_spec.js84
-rw-r--r--spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js20
-rw-r--r--spec/frontend/sidebar/components/time_tracking/report_spec.js2
-rw-r--r--spec/frontend/sidebar/sidebar_mediator_spec.js55
-rw-r--r--spec/frontend/task_list_spec.js17
-rw-r--r--spec/frontend/terms/components/app_spec.js171
-rw-r--r--spec/frontend/test_setup.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js53
-rw-r--r--spec/frontend/vue_mr_widget/components/extensions/actions_spec.js12
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js25
-rw-r--r--spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap4
-rw-r--r--spec/frontend/vue_mr_widget/components/states/__snapshots__/new_ready_to_merge_spec.js.snap4
-rw-r--r--spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js11
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js13
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js8
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js8
-rw-r--r--spec/frontend/vue_mr_widget/mock_data.js2
-rw-r--r--spec/frontend/vue_mr_widget/mr_widget_options_spec.js28
-rw-r--r--spec/frontend/vue_mr_widget/stores/get_state_key_spec.js9
-rw-r--r--spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/test_extension.js2
-rw-r--r--spec/frontend/vue_shared/components/alerts_deprecation_warning_spec.js48
-rw-r--r--spec/frontend/vue_shared/components/confirm_danger/confirm_danger_modal_spec.js99
-rw-r--r--spec/frontend/vue_shared/components/confirm_danger/confirm_danger_spec.js61
-rw-r--r--spec/frontend/vue_shared/components/content_viewer/content_viewer_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js27
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js26
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js29
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js44
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js78
-rw-r--r--spec/frontend/vue_shared/components/header_ci_component_spec.js48
-rw-r--r--spec/frontend/vue_shared/components/notes/system_note_spec.js50
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_selector_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/registry/title_area_spec.js59
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js67
-rw-r--r--spec/frontend/vue_shared/components/settings/__snapshots__/settings_block_spec.js.snap1
-rw-r--r--spec/frontend/vue_shared/components/settings/settings_block_spec.js48
-rw-r--r--spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js76
-rw-r--r--spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js119
-rw-r--r--spec/frontend/vue_shared/components/sidebar/date_picker_spec.js69
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed_spec.js121
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js72
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js18
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js19
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_spec.js69
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_footer_spec.js57
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_header_spec.js75
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js7
-rw-r--r--spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js52
-rw-r--r--spec/frontend/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list_spec.js2
-rw-r--r--spec/frontend/whats_new/utils/notification_spec.js6
-rw-r--r--spec/frontend/work_items/components/app_spec.js24
-rw-r--r--spec/frontend/work_items/mock_data.js17
-rw-r--r--spec/frontend/work_items/pages/work_item_root_spec.js70
-rw-r--r--spec/frontend/work_items/router_spec.js30
-rw-r--r--spec/graphql/mutations/customer_relations/contacts/create_spec.rb6
-rw-r--r--spec/graphql/mutations/customer_relations/contacts/update_spec.rb6
-rw-r--r--spec/graphql/mutations/customer_relations/organizations/create_spec.rb6
-rw-r--r--spec/graphql/mutations/customer_relations/organizations/update_spec.rb6
-rw-r--r--spec/graphql/mutations/discussions/toggle_resolve_spec.rb4
-rw-r--r--spec/graphql/mutations/environments/canary_ingress/update_spec.rb2
-rw-r--r--spec/graphql/mutations/merge_requests/set_wip_spec.rb55
-rw-r--r--spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb2
-rw-r--r--spec/graphql/mutations/releases/delete_spec.rb2
-rw-r--r--spec/graphql/mutations/releases/update_spec.rb4
-rw-r--r--spec/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb13
-rw-r--r--spec/graphql/resolvers/concerns/resolves_groups_spec.rb71
-rw-r--r--spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb22
-rw-r--r--spec/graphql/resolvers/group_issues_resolver_spec.rb65
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb120
-rw-r--r--spec/graphql/resolvers/merge_requests_resolver_spec.rb48
-rw-r--r--spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb5
-rw-r--r--spec/graphql/resolvers/timelog_resolver_spec.rb50
-rw-r--r--spec/graphql/resolvers/topics_resolver_spec.rb33
-rw-r--r--spec/graphql/types/alert_management/prometheus_integration_type_spec.rb2
-rw-r--r--spec/graphql/types/ci/job_artifact_type_spec.rb2
-rw-r--r--spec/graphql/types/ci/pipeline_scope_enum_spec.rb11
-rw-r--r--spec/graphql/types/ci/pipeline_status_enum_spec.rb11
-rw-r--r--spec/graphql/types/ci/pipeline_type_spec.rb4
-rw-r--r--spec/graphql/types/commit_type_spec.rb2
-rw-r--r--spec/graphql/types/customer_relations/contact_type_spec.rb2
-rw-r--r--spec/graphql/types/customer_relations/organization_type_spec.rb2
-rw-r--r--spec/graphql/types/dependency_proxy/manifest_type_spec.rb2
-rw-r--r--spec/graphql/types/evidence_type_spec.rb2
-rw-r--r--spec/graphql/types/merge_request_review_state_enum_spec.rb4
-rw-r--r--spec/graphql/types/merge_request_type_spec.rb2
-rw-r--r--spec/graphql/types/mutation_type_spec.rb8
-rw-r--r--spec/graphql/types/packages/helm/dependency_type_spec.rb15
-rw-r--r--spec/graphql/types/packages/helm/file_metadatum_type_spec.rb15
-rw-r--r--spec/graphql/types/packages/helm/maintainer_type_spec.rb15
-rw-r--r--spec/graphql/types/packages/helm/metadata_type_spec.rb15
-rw-r--r--spec/graphql/types/project_type_spec.rb4
-rw-r--r--spec/graphql/types/projects/topic_type_spec.rb17
-rw-r--r--spec/graphql/types/query_type_spec.rb1
-rw-r--r--spec/graphql/types/release_links_type_spec.rb44
-rw-r--r--spec/graphql/types/repository/blob_type_spec.rb1
-rw-r--r--spec/graphql/types/user_merge_request_interaction_type_spec.rb5
-rw-r--r--spec/helpers/admin/deploy_key_helper_spec.rb28
-rw-r--r--spec/helpers/boards_helper_spec.rb6
-rw-r--r--spec/helpers/ci/pipelines_helper_spec.rb22
-rw-r--r--spec/helpers/ci/runners_helper_spec.rb72
-rw-r--r--spec/helpers/clusters_helper_spec.rb120
-rw-r--r--spec/helpers/emoji_helper_spec.rb5
-rw-r--r--spec/helpers/environments_helper_spec.rb64
-rw-r--r--spec/helpers/graph_helper_spec.rb12
-rw-r--r--spec/helpers/groups/settings_helper_spec.rb38
-rw-r--r--spec/helpers/groups_helper_spec.rb2
-rw-r--r--spec/helpers/invite_members_helper_spec.rb79
-rw-r--r--spec/helpers/issuables_description_templates_helper_spec.rb14
-rw-r--r--spec/helpers/issuables_helper_spec.rb23
-rw-r--r--spec/helpers/issues_helper_spec.rb1
-rw-r--r--spec/helpers/learn_gitlab_helper_spec.rb155
-rw-r--r--spec/helpers/members_helper_spec.rb6
-rw-r--r--spec/helpers/nav/top_nav_helper_spec.rb5
-rw-r--r--spec/helpers/notes_helper_spec.rb12
-rw-r--r--spec/helpers/one_trust_helper_spec.rb19
-rw-r--r--spec/helpers/projects/alert_management_helper_spec.rb33
-rw-r--r--spec/helpers/projects/incidents_helper_spec.rb49
-rw-r--r--spec/helpers/projects/security/configuration_helper_spec.rb2
-rw-r--r--spec/helpers/projects_helper_spec.rb18
-rw-r--r--spec/helpers/routing/pseudonymization_helper_spec.rb220
-rw-r--r--spec/helpers/storage_helper_spec.rb19
-rw-r--r--spec/helpers/tab_helper_spec.rb28
-rw-r--r--spec/helpers/terms_helper_spec.rb44
-rw-r--r--spec/helpers/time_zone_helper_spec.rb32
-rw-r--r--spec/helpers/user_callouts_helper_spec.rb14
-rw-r--r--spec/helpers/users_helper_spec.rb2
-rw-r--r--spec/helpers/wiki_helper_spec.rb6
-rw-r--r--spec/initializers/0_postgresql_types_spec.rb16
-rw-r--r--spec/initializers/100_patch_omniauth_oauth2_spec.rb45
-rw-r--r--spec/initializers/carrierwave_patch_spec.rb3
-rw-r--r--spec/initializers/database_config_spec.rb49
-rw-r--r--spec/initializers/session_store_spec.rb37
-rw-r--r--spec/lib/api/ci/helpers/runner_spec.rb8
-rw-r--r--spec/lib/api/entities/projects/topic_spec.rb19
-rw-r--r--spec/lib/api/helpers_spec.rb2
-rw-r--r--spec/lib/atlassian/jira_connect/client_spec.rb10
-rw-r--r--spec/lib/banzai/filter/emoji_filter_spec.rb6
-rw-r--r--spec/lib/banzai/filter/footnote_filter_spec.rb88
-rw-r--r--spec/lib/banzai/filter/markdown_filter_spec.rb153
-rw-r--r--spec/lib/banzai/filter/plantuml_filter_spec.rb73
-rw-r--r--spec/lib/banzai/filter/sanitization_filter_spec.rb64
-rw-r--r--spec/lib/banzai/filter/syntax_highlight_filter_spec.rb232
-rw-r--r--spec/lib/banzai/pipeline/emoji_pipeline_spec.rb6
-rw-r--r--spec/lib/banzai/pipeline/full_pipeline_spec.rb67
-rw-r--r--spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb55
-rw-r--r--spec/lib/banzai/renderer_spec.rb18
-rw-r--r--spec/lib/bulk_imports/common/pipelines/milestones_pipeline_spec.rb154
-rw-r--r--spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb80
-rw-r--r--spec/lib/bulk_imports/common/pipelines/wiki_pipeline_spec.rb25
-rw-r--r--spec/lib/bulk_imports/groups/graphql/get_milestones_query_spec.rb35
-rw-r--r--spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb58
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb73
-rw-r--r--spec/lib/bulk_imports/groups/stage_spec.rb2
-rw-r--r--spec/lib/bulk_imports/ndjson_pipeline_spec.rb3
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/external_pull_requests_pipeline_spec.rb66
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/merge_requests_pipeline_spec.rb297
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/protected_branches_pipeline_spec.rb61
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb97
-rw-r--r--spec/lib/bulk_imports/projects/stage_spec.rb11
-rw-r--r--spec/lib/container_registry/client_spec.rb2
-rw-r--r--spec/lib/container_registry/tag_spec.rb2
-rw-r--r--spec/lib/error_tracking/collector/payload_validator_spec.rb49
-rw-r--r--spec/lib/error_tracking/collector/sentry_request_parser_spec.rb7
-rw-r--r--spec/lib/feature/gitaly_spec.rb4
-rw-r--r--spec/lib/feature_spec.rb16
-rw-r--r--spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb11
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder_spec.rb150
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb130
-rw-r--r--spec/lib/gitlab/application_rate_limiter_spec.rb132
-rw-r--r--spec/lib/gitlab/asciidoc_spec.rb1351
-rw-r--r--spec/lib/gitlab/auth/auth_finders_spec.rb64
-rw-r--r--spec/lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/add_primary_email_to_emails_if_user_confirmed_spec.rb49
-rw-r--r--spec/lib/gitlab/background_migration/backfill_artifact_expiry_date_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_design_internal_ids_spec.rb69
-rw-r--r--spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_namespace_settings_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_project_settings_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_push_rules_id_in_projects_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_user_namespace_spec.rb39
-rw-r--r--spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics_spec.rb39
-rw-r--r--spec/lib/gitlab/background_migration/drop_invalid_vulnerabilities_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/fix_merge_request_diff_commit_users_spec.rb316
-rw-r--r--spec/lib/gitlab/background_migration/fix_projects_without_project_feature_spec.rb75
-rw-r--r--spec/lib/gitlab/background_migration/fix_projects_without_prometheus_service_spec.rb234
-rw-r--r--spec/lib/gitlab/background_migration/job_coordinator_spec.rb344
-rw-r--r--spec/lib/gitlab/background_migration/link_lfs_objects_projects_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data_spec.rb327
-rw-r--r--spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/migrate_u2f_webauthn_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/migrate_users_bio_to_user_details_spec.rb85
-rw-r--r--spec/lib/gitlab/background_migration/populate_canonical_emails_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/populate_personal_snippet_statistics_spec.rb4
-rw-r--r--spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb4
-rw-r--r--spec/lib/gitlab/background_migration/populate_user_highest_roles_table_spec.rb71
-rw-r--r--spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb254
-rw-r--r--spec/lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/remove_duplicate_services_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb77
-rw-r--r--spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/set_default_iteration_cadences_spec.rb80
-rw-r--r--spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/set_null_external_diff_store_to_local_value_spec.rb33
-rw-r--r--spec/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value_spec.rb33
-rw-r--r--spec/lib/gitlab/background_migration/steal_migrate_merge_request_diff_commit_users_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb114
-rw-r--r--spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration_spec.rb257
-rw-r--r--spec/lib/gitlab/bare_repository_import/importer_spec.rb2
-rw-r--r--spec/lib/gitlab/bitbucket_server_import/importer_spec.rb74
-rw-r--r--spec/lib/gitlab/blob_helper_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/artifact_file_reader_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/artifacts/metrics_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/build/auto_retry_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/build/rules/rule/clause/exists_spec.rb28
-rw-r--r--spec/lib/gitlab/ci/config/entry/include/rules/rule_spec.rb16
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/config/extendable_spec.rb44
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/external/rules_spec.rb28
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb90
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb56
-rw-r--r--spec/lib/gitlab/ci/reports/security/report_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/reports/security/reports_spec.rb21
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb30
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb65
-rw-r--r--spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb25
-rw-r--r--spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/trace/archive_spec.rb169
-rw-r--r--spec/lib/gitlab/ci/trace/metrics_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/trace_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/variables/builder_spec.rb38
-rw-r--r--spec/lib/gitlab/ci/variables/collection_spec.rb482
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb58
-rw-r--r--spec/lib/gitlab/config_checker/external_database_checker_spec.rb6
-rw-r--r--spec/lib/gitlab/container_repository/tags/cache_spec.rb133
-rw-r--r--spec/lib/gitlab/content_security_policy/config_loader_spec.rb49
-rw-r--r--spec/lib/gitlab/contributions_calendar_spec.rb68
-rw-r--r--spec/lib/gitlab/database/async_indexes/postgres_async_index_spec.rb2
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb2
-rw-r--r--spec/lib/gitlab/database/batch_count_spec.rb2
-rw-r--r--spec/lib/gitlab/database/connection_spec.rb442
-rw-r--r--spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb3
-rw-r--r--spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb3
-rw-r--r--spec/lib/gitlab/database/each_database_spec.rb48
-rw-r--r--spec/lib/gitlab/database/gitlab_schema_spec.rb58
-rw-r--r--spec/lib/gitlab/database/load_balancing/configuration_spec.rb75
-rw-r--r--spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb45
-rw-r--r--spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb102
-rw-r--r--spec/lib/gitlab/database/load_balancing/primary_host_spec.rb6
-rw-r--r--spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb16
-rw-r--r--spec/lib/gitlab/database/load_balancing/setup_spec.rb208
-rw-r--r--spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb4
-rw-r--r--spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb6
-rw-r--r--spec/lib/gitlab/database/load_balancing/sticking_spec.rb22
-rw-r--r--spec/lib/gitlab/database/load_balancing_spec.rb14
-rw-r--r--spec/lib/gitlab/database/migration_helpers/loose_foreign_key_helpers_spec.rb10
-rw-r--r--spec/lib/gitlab/database/migration_helpers/v2_spec.rb62
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb129
-rw-r--r--spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb23
-rw-r--r--spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb106
-rw-r--r--spec/lib/gitlab/database/partitioning/detached_partition_dropper_spec.rb95
-rw-r--r--spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb42
-rw-r--r--spec/lib/gitlab/database/partitioning/multi_database_partition_dropper_spec.rb38
-rw-r--r--spec/lib/gitlab/database/partitioning/multi_database_partition_manager_spec.rb36
-rw-r--r--spec/lib/gitlab/database/partitioning/partition_manager_spec.rb2
-rw-r--r--spec/lib/gitlab/database/partitioning/partition_monitoring_spec.rb3
-rw-r--r--spec/lib/gitlab/database/partitioning/replace_table_spec.rb4
-rw-r--r--spec/lib/gitlab/database/partitioning_spec.rb173
-rw-r--r--spec/lib/gitlab/database/postgres_foreign_key_spec.rb12
-rw-r--r--spec/lib/gitlab/database/postgres_hll/batch_distinct_counter_spec.rb2
-rw-r--r--spec/lib/gitlab/database/postgres_index_bloat_estimate_spec.rb2
-rw-r--r--spec/lib/gitlab/database/postgres_index_spec.rb2
-rw-r--r--spec/lib/gitlab/database/query_analyzer_spec.rb144
-rw-r--r--spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb80
-rw-r--r--spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb167
-rw-r--r--spec/lib/gitlab/database/reflection_spec.rb280
-rw-r--r--spec/lib/gitlab/database/reindexing/index_selection_spec.rb6
-rw-r--r--spec/lib/gitlab/database/reindexing/reindex_action_spec.rb2
-rw-r--r--spec/lib/gitlab/database/reindexing/reindex_concurrently_spec.rb4
-rw-r--r--spec/lib/gitlab/database/reindexing_spec.rb112
-rw-r--r--spec/lib/gitlab/database/schema_cache_with_renamed_table_spec.rb12
-rw-r--r--spec/lib/gitlab/database/schema_migrations/context_spec.rb2
-rw-r--r--spec/lib/gitlab/database/shared_model_spec.rb32
-rw-r--r--spec/lib/gitlab/database/unidirectional_copy_trigger_spec.rb2
-rw-r--r--spec/lib/gitlab/database_spec.rb33
-rw-r--r--spec/lib/gitlab/diff/file_spec.rb42
-rw-r--r--spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb7
-rw-r--r--spec/lib/gitlab/email/handler/service_desk_handler_spec.rb123
-rw-r--r--spec/lib/gitlab/email/hook/smime_signature_interceptor_spec.rb2
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/base_spec.rb25
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/experience_spec.rb69
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/invite_team_spec.rb39
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing_spec.rb13
-rw-r--r--spec/lib/gitlab/email/reply_parser_spec.rb24
-rw-r--r--spec/lib/gitlab/emoji_spec.rb106
-rw-r--r--spec/lib/gitlab/etag_caching/middleware_spec.rb2
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb8
-rw-r--r--spec/lib/gitlab/git/object_pool_spec.rb2
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb55
-rw-r--r--spec/lib/gitlab/gitaly_client/commit_service_spec.rb37
-rw-r--r--spec/lib/gitlab/gitaly_client/ref_service_spec.rb51
-rw-r--r--spec/lib/gitlab/gitaly_client_spec.rb23
-rw-r--r--spec/lib/gitlab/github_import/bulk_importing_spec.rb8
-rw-r--r--spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb298
-rw-r--r--spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/issue_importer_spec.rb4
-rw-r--r--spec/lib/gitlab/github_import/importer/label_links_importer_spec.rb8
-rw-r--r--spec/lib/gitlab/github_import/importer/note_importer_spec.rb14
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_requests_merged_by_importer_spec.rb25
-rw-r--r--spec/lib/gitlab/github_import/representation/diff_note_spec.rb446
-rw-r--r--spec/lib/gitlab/github_import/representation/diff_notes/suggestion_formatter_spec.rb50
-rw-r--r--spec/lib/gitlab/gpg/commit_spec.rb69
-rw-r--r--spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb2
-rw-r--r--spec/lib/gitlab/grape_logging/loggers/perf_logger_spec.rb2
-rw-r--r--spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb4
-rw-r--r--spec/lib/gitlab/grape_logging/loggers/urgency_logger_spec.rb48
-rw-r--r--spec/lib/gitlab/graphql/known_operations_spec.rb80
-rw-r--r--spec/lib/gitlab/graphql/pagination/connections_spec.rb6
-rw-r--r--spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb15
-rw-r--r--spec/lib/gitlab/graphql/tracers/application_context_tracer_spec.rb43
-rw-r--r--spec/lib/gitlab/graphql/tracers/logger_tracer_spec.rb52
-rw-r--r--spec/lib/gitlab/graphql/tracers/metrics_tracer_spec.rb60
-rw-r--r--spec/lib/gitlab/graphql/tracers/timer_tracer_spec.rb44
-rw-r--r--spec/lib/gitlab/health_checks/redis/redis_check_spec.rb2
-rw-r--r--spec/lib/gitlab/import/database_helpers_spec.rb4
-rw-r--r--spec/lib/gitlab/import/metrics_spec.rb14
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml3
-rw-r--r--spec/lib/gitlab/import_export/attributes_permitter_spec.rb83
-rw-r--r--spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb88
-rw-r--r--spec/lib/gitlab/import_export/project/object_builder_spec.rb132
-rw-r--r--spec/lib/gitlab/import_export/project/relation_tree_restorer_spec.rb150
-rw-r--r--spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb48
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb3
-rw-r--r--spec/lib/gitlab/import_export/project/tree_saver_spec.rb50
-rw-r--r--spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb184
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml2
-rw-r--r--spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb41
-rw-r--r--spec/lib/gitlab/instrumentation_helper_spec.rb19
-rw-r--r--spec/lib/gitlab/issues/rebalancing/state_spec.rb29
-rw-r--r--spec/lib/gitlab/lograge/custom_options_spec.rb20
-rw-r--r--spec/lib/gitlab/merge_requests/merge_commit_message_spec.rb219
-rw-r--r--spec/lib/gitlab/metrics/background_transaction_spec.rb47
-rw-r--r--spec/lib/gitlab/metrics/method_call_spec.rb4
-rw-r--r--spec/lib/gitlab/metrics/rails_slis_spec.rb37
-rw-r--r--spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb70
-rw-r--r--spec/lib/gitlab/metrics/samplers/action_cable_sampler_spec.rb68
-rw-r--r--spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb4
-rw-r--r--spec/lib/gitlab/metrics/subscribers/external_http_spec.rb2
-rw-r--r--spec/lib/gitlab/metrics/transaction_spec.rb167
-rw-r--r--spec/lib/gitlab/metrics/web_transaction_spec.rb90
-rw-r--r--spec/lib/gitlab/middleware/compressed_json_spec.rb75
-rw-r--r--spec/lib/gitlab/middleware/go_spec.rb16
-rw-r--r--spec/lib/gitlab/middleware/query_analyzer_spec.rb61
-rw-r--r--spec/lib/gitlab/path_regex_spec.rb11
-rw-r--r--spec/lib/gitlab/project_template_spec.rb4
-rw-r--r--spec/lib/gitlab/prometheus_client_spec.rb36
-rw-r--r--spec/lib/gitlab/redis/multi_store_spec.rb474
-rw-r--r--spec/lib/gitlab/runtime_spec.rb24
-rw-r--r--spec/lib/gitlab/search_results_spec.rb12
-rw-r--r--spec/lib/gitlab/sidekiq_cluster/cli_spec.rb334
-rw-r--r--spec/lib/gitlab/sidekiq_cluster_spec.rb207
-rw-r--r--spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb15
-rw-r--r--spec/lib/gitlab/sidekiq_config/worker_spec.rb17
-rw-r--r--spec/lib/gitlab/sidekiq_enq_spec.rb93
-rw-r--r--spec/lib/gitlab/sidekiq_logging/deduplication_logger_spec.rb30
-rw-r--r--spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb2
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb285
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed_spec.rb25
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/query_analyzer_spec.rb61
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb157
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/worker_context/client_spec.rb10
-rw-r--r--spec/lib/gitlab/spamcheck/client_spec.rb2
-rw-r--r--spec/lib/gitlab/subscription_portal_spec.rb31
-rw-r--r--spec/lib/gitlab/tracking/destinations/product_analytics_spec.rb84
-rw-r--r--spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb51
-rw-r--r--spec/lib/gitlab/tracking/standard_context_spec.rb20
-rw-r--r--spec/lib/gitlab/tracking_spec.rb89
-rw-r--r--spec/lib/gitlab/usage/metric_definition_spec.rb2
-rw-r--r--spec/lib/gitlab/usage/metric_spec.rb6
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/generic_metric_spec.rb12
-rw-r--r--spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb28
-rw-r--r--spec/lib/gitlab/usage_data_counters/vscode_extenion_activity_unique_counter_spec.rb (renamed from spec/lib/gitlab/usage_data_counters/vs_code_extenion_activity_unique_counter_spec.rb)0
-rw-r--r--spec/lib/gitlab/usage_data_metrics_spec.rb16
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb191
-rw-r--r--spec/lib/gitlab/utils/usage_data_spec.rb26
-rw-r--r--spec/lib/gitlab/webpack/file_loader_spec.rb79
-rw-r--r--spec/lib/gitlab/webpack/graphql_known_operations_spec.rb47
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb18
-rw-r--r--spec/lib/gitlab/x509/certificate_spec.rb50
-rw-r--r--spec/lib/gitlab/x509/signature_spec.rb92
-rw-r--r--spec/lib/gitlab/zentao/client_spec.rb70
-rw-r--r--spec/lib/gitlab/zentao/query_spec.rb61
-rw-r--r--spec/lib/marginalia_spec.rb6
-rw-r--r--spec/lib/object_storage/config_spec.rb40
-rw-r--r--spec/lib/object_storage/direct_upload_spec.rb4
-rw-r--r--spec/lib/security/ci_configuration/sast_iac_build_action_spec.rb163
-rw-r--r--spec/lib/sidebars/groups/menus/invite_team_members_menu_spec.rb55
-rw-r--r--spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb23
-rw-r--r--spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb16
-rw-r--r--spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb52
-rw-r--r--spec/lib/sidebars/projects/menus/settings_menu_spec.rb20
-rw-r--r--spec/lib/sidebars/projects/menus/zentao_menu_spec.rb7
-rw-r--r--spec/lib/system_check/incoming_email_check_spec.rb4
-rw-r--r--spec/lib/uploaded_file_spec.rb64
-rw-r--r--spec/mailers/emails/in_product_marketing_spec.rb49
-rw-r--r--spec/mailers/emails/pipelines_spec.rb21
-rw-r--r--spec/mailers/notify_spec.rb87
-rw-r--r--spec/migrations/20200107172020_add_timestamp_softwarelicensespolicy_spec.rb23
-rw-r--r--spec/migrations/20200122123016_backfill_project_settings_spec.rb32
-rw-r--r--spec/migrations/20200123155929_remove_invalid_jira_data_spec.rb77
-rw-r--r--spec/migrations/20200127090233_remove_invalid_issue_tracker_data_spec.rb64
-rw-r--r--spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb115
-rw-r--r--spec/migrations/20200313203550_remove_orphaned_chat_names_spec.rb27
-rw-r--r--spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb50
-rw-r--r--spec/migrations/20200511145545_change_variable_interpolation_format_in_common_metrics_spec.rb39
-rw-r--r--spec/migrations/20200526115436_dedup_mr_metrics_spec.rb68
-rw-r--r--spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb175
-rw-r--r--spec/migrations/20200703125016_backfill_namespace_settings_spec.rb30
-rw-r--r--spec/migrations/20200706035141_adjust_unique_index_alert_management_alerts_spec.rb57
-rw-r--r--spec/migrations/20200728080250_replace_unique_index_on_cycle_analytics_stages_spec.rb47
-rw-r--r--spec/migrations/20200728182311_add_o_auth_paths_to_protected_paths_spec.rb52
-rw-r--r--spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb160
-rw-r--r--spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb14
-rw-r--r--spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb46
-rw-r--r--spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb58
-rw-r--r--spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb26
-rw-r--r--spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb38
-rw-r--r--spec/migrations/20201110161542_cleanup_transfered_projects_shared_runners_spec.rb32
-rw-r--r--spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb140
-rw-r--r--spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb138
-rw-r--r--spec/migrations/20210112143418_remove_duplicate_services2_spec.rb2
-rw-r--r--spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb2
-rw-r--r--spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb2
-rw-r--r--spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb2
-rw-r--r--spec/migrations/20210218040814_add_environment_scope_to_group_variables_spec.rb2
-rw-r--r--spec/migrations/20210226141517_dedup_issue_metrics_spec.rb2
-rw-r--r--spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb2
-rw-r--r--spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb2
-rw-r--r--spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb2
-rw-r--r--spec/migrations/20210423160427_schedule_drop_invalid_vulnerabilities_spec.rb2
-rw-r--r--spec/migrations/20210430134202_copy_adoption_snapshot_namespace_spec.rb2
-rw-r--r--spec/migrations/20210430135954_copy_adoption_segments_namespace_spec.rb2
-rw-r--r--spec/migrations/20210503105845_add_project_value_stream_id_to_project_stages_spec.rb2
-rw-r--r--spec/migrations/20210511142748_schedule_drop_invalid_vulnerabilities2_spec.rb2
-rw-r--r--spec/migrations/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects_spec.rb2
-rw-r--r--spec/migrations/20210601073400_fix_total_stage_in_vsa_spec.rb2
-rw-r--r--spec/migrations/20210601080039_group_protected_environments_add_index_and_constraint_spec.rb2
-rw-r--r--spec/migrations/20210603222333_remove_builds_email_service_from_services_spec.rb2
-rw-r--r--spec/migrations/20210610153556_delete_legacy_operations_feature_flags_spec.rb2
-rw-r--r--spec/migrations/2021061716138_cascade_delete_freeze_periods_spec.rb2
-rw-r--r--spec/migrations/20210708130419_reschedule_merge_request_diff_users_background_migration_spec.rb2
-rw-r--r--spec/migrations/20210722042939_update_issuable_slas_where_issue_closed_spec.rb2
-rw-r--r--spec/migrations/20210722150102_operations_feature_flags_correct_flexible_rollout_values_spec.rb2
-rw-r--r--spec/migrations/20210804150320_create_base_work_item_types_spec.rb2
-rw-r--r--spec/migrations/20210805192450_update_trial_plans_ci_daily_pipeline_schedule_triggers_spec.rb2
-rw-r--r--spec/migrations/20210811122206_update_external_project_bots_spec.rb2
-rw-r--r--spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb2
-rw-r--r--spec/migrations/20210819145000_drop_temporary_columns_and_triggers_for_ci_builds_runner_session_spec.rb2
-rw-r--r--spec/migrations/20210831203408_upsert_base_work_item_types_spec.rb2
-rw-r--r--spec/migrations/20210902144144_drop_temporary_columns_and_triggers_for_ci_build_needs_spec.rb2
-rw-r--r--spec/migrations/20210906100316_drop_temporary_columns_and_triggers_for_ci_build_trace_chunks_spec.rb2
-rw-r--r--spec/migrations/20210906130643_drop_temporary_columns_and_triggers_for_taggings_spec.rb2
-rw-r--r--spec/migrations/20210907013944_cleanup_bigint_conversion_for_ci_builds_metadata_spec.rb2
-rw-r--r--spec/migrations/20210907211557_finalize_ci_builds_bigint_conversion_spec.rb2
-rw-r--r--spec/migrations/20210910194952_update_report_type_for_existing_approval_project_rules_spec.rb2
-rw-r--r--spec/migrations/20210914095310_cleanup_orphan_project_access_tokens_spec.rb2
-rw-r--r--spec/migrations/20210915022415_cleanup_bigint_conversion_for_ci_builds_spec.rb2
-rw-r--r--spec/migrations/20210922021816_drop_int4_columns_for_ci_job_artifacts_spec.rb2
-rw-r--r--spec/migrations/20210922025631_drop_int4_column_for_ci_sources_pipelines_spec.rb2
-rw-r--r--spec/migrations/20210922082019_drop_int4_column_for_events_spec.rb2
-rw-r--r--spec/migrations/20210922091402_drop_int4_column_for_push_event_payloads_spec.rb2
-rw-r--r--spec/migrations/20211006060436_schedule_populate_topics_total_projects_count_cache_spec.rb2
-rw-r--r--spec/migrations/20211012134316_clean_up_migrate_merge_request_diff_commit_users_spec.rb48
-rw-r--r--spec/migrations/20211018152654_schedule_remove_duplicate_vulnerabilities_findings3_spec.rb168
-rw-r--r--spec/migrations/20211028155449_schedule_fix_merge_request_diff_commit_users_migration_spec.rb63
-rw-r--r--spec/migrations/add_default_value_stream_to_groups_with_group_stages_spec.rb44
-rw-r--r--spec/migrations/add_deploy_token_type_to_deploy_tokens_spec.rb24
-rw-r--r--spec/migrations/add_incident_settings_to_all_existing_projects_spec.rb93
-rw-r--r--spec/migrations/add_open_source_plan_spec.rb86
-rw-r--r--spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb22
-rw-r--r--spec/migrations/add_repository_storages_weighted_to_application_settings_spec.rb31
-rw-r--r--spec/migrations/add_temporary_partial_index_on_project_id_to_services_spec.rb22
-rw-r--r--spec/migrations/backfill_imported_snippet_repositories_spec.rb52
-rw-r--r--spec/migrations/backfill_operations_feature_flags_iid_spec.rb32
-rw-r--r--spec/migrations/backfill_snippet_repositories_spec.rb44
-rw-r--r--spec/migrations/backfill_status_page_published_incidents_spec.rb54
-rw-r--r--spec/migrations/backfill_user_namespace_spec.rb29
-rw-r--r--spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb62
-rw-r--r--spec/migrations/clean_grafana_url_spec.rb37
-rw-r--r--spec/migrations/cleanup_empty_commit_user_mentions_spec.rb36
-rw-r--r--spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb101
-rw-r--r--spec/migrations/cleanup_move_container_registry_enabled_to_project_feature_spec.rb45
-rw-r--r--spec/migrations/cleanup_move_container_registry_enabled_to_project_features_spec.rb45
-rw-r--r--spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb45
-rw-r--r--spec/migrations/cleanup_optimistic_locking_nulls_spec.rb52
-rw-r--r--spec/migrations/cleanup_projects_with_missing_namespace_spec.rb142
-rw-r--r--spec/migrations/cleanup_remaining_orphan_invites_spec.rb2
-rw-r--r--spec/migrations/complete_namespace_settings_migration_spec.rb24
-rw-r--r--spec/migrations/confirm_project_bot_users_spec.rb84
-rw-r--r--spec/migrations/create_environment_for_self_monitoring_project_spec.rb68
-rw-r--r--spec/migrations/deduplicate_epic_iids_spec.rb36
-rw-r--r--spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb42
-rw-r--r--spec/migrations/delete_template_project_services_spec.rb21
-rw-r--r--spec/migrations/delete_template_services_duplicated_by_type_spec.rb24
-rw-r--r--spec/migrations/delete_user_callout_alerts_moved_spec.rb30
-rw-r--r--spec/migrations/drop_activate_prometheus_services_background_jobs_spec.rb89
-rw-r--r--spec/migrations/drop_background_migration_jobs_spec.rb61
-rw-r--r--spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb40
-rw-r--r--spec/migrations/ensure_filled_file_store_on_package_files_spec.rb40
-rw-r--r--spec/migrations/ensure_namespace_settings_creation_spec.rb44
-rw-r--r--spec/migrations/ensure_target_project_id_is_filled_spec.rb30
-rw-r--r--spec/migrations/ensure_u2f_registrations_migrated_spec.rb41
-rw-r--r--spec/migrations/fill_file_store_ci_job_artifacts_spec.rb44
-rw-r--r--spec/migrations/fill_file_store_lfs_objects_spec.rb36
-rw-r--r--spec/migrations/fill_store_uploads_spec.rb48
-rw-r--r--spec/migrations/fix_projects_without_project_feature_spec.rb42
-rw-r--r--spec/migrations/fix_projects_without_prometheus_services_spec.rb42
-rw-r--r--spec/migrations/generate_ci_jwt_signing_key_spec.rb42
-rw-r--r--spec/migrations/generate_missing_routes_for_bots_spec.rb80
-rw-r--r--spec/migrations/insert_daily_invites_plan_limits_spec.rb55
-rw-r--r--spec/migrations/insert_project_feature_flags_plan_limits_spec.rb76
-rw-r--r--spec/migrations/migrate_all_merge_request_user_mentions_to_db_spec.rb35
-rw-r--r--spec/migrations/migrate_bot_type_to_user_type_spec.rb20
-rw-r--r--spec/migrations/migrate_commit_notes_mentions_to_db_spec.rb37
-rw-r--r--spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb52
-rw-r--r--spec/migrations/migrate_create_commit_signature_worker_sidekiq_queue_spec.rb44
-rw-r--r--spec/migrations/migrate_incident_issues_to_incident_type_spec.rb55
-rw-r--r--spec/migrations/migrate_merge_request_mentions_to_db_spec.rb31
-rw-r--r--spec/migrations/migrate_store_security_reports_sidekiq_queue_spec.rb33
-rw-r--r--spec/migrations/migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue_spec.rb33
-rw-r--r--spec/migrations/orphaned_invite_tokens_cleanup_spec.rb2
-rw-r--r--spec/migrations/populate_remaining_missing_dismissal_information_for_vulnerabilities_spec.rb31
-rw-r--r--spec/migrations/remove_additional_application_settings_rows_spec.rb27
-rw-r--r--spec/migrations/remove_deprecated_jenkins_service_records_spec.rb29
-rw-r--r--spec/migrations/remove_duplicate_labels_from_groups_spec.rb227
-rw-r--r--spec/migrations/remove_duplicate_labels_from_project_spec.rb239
-rw-r--r--spec/migrations/remove_gitlab_issue_tracker_service_records_spec.rb19
-rw-r--r--spec/migrations/remove_orphan_service_hooks_spec.rb26
-rw-r--r--spec/migrations/remove_orphaned_invited_members_spec.rb57
-rw-r--r--spec/migrations/remove_packages_deprecated_dependencies_spec.rb30
-rw-r--r--spec/migrations/remove_security_dashboard_feature_flag_spec.rb53
-rw-r--r--spec/migrations/rename_security_dashboard_feature_flag_to_instance_security_dashboard_spec.rb53
-rw-r--r--spec/migrations/rename_sitemap_namespace_spec.rb30
-rw-r--r--spec/migrations/rename_sitemap_root_namespaces_spec.rb36
-rw-r--r--spec/migrations/reschedule_set_default_iteration_cadences_spec.rb41
-rw-r--r--spec/migrations/reseed_merge_trains_enabled_spec.rb26
-rw-r--r--spec/migrations/reseed_repository_storages_weighted_spec.rb43
-rw-r--r--spec/migrations/save_instance_administrators_group_id_spec.rb99
-rw-r--r--spec/migrations/schedule_add_primary_email_to_emails_if_user_confirmed_spec.rb31
-rw-r--r--spec/migrations/schedule_backfill_push_rules_id_in_projects_spec.rb49
-rw-r--r--spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb37
-rw-r--r--spec/migrations/schedule_link_lfs_objects_projects_spec.rb76
-rw-r--r--spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb41
-rw-r--r--spec/migrations/schedule_migrate_security_scans_spec.rb67
-rw-r--r--spec/migrations/schedule_migrate_u2f_webauthn_spec.rb58
-rw-r--r--spec/migrations/schedule_populate_has_vulnerabilities_spec.rb36
-rw-r--r--spec/migrations/schedule_populate_issue_email_participants_spec.rb33
-rw-r--r--spec/migrations/schedule_populate_missing_dismissal_information_for_vulnerabilities_spec.rb37
-rw-r--r--spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb60
-rw-r--r--spec/migrations/schedule_populate_project_snippet_statistics_spec.rb61
-rw-r--r--spec/migrations/schedule_populate_user_highest_roles_table_spec.rb46
-rw-r--r--spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb28
-rw-r--r--spec/migrations/schedule_recalculate_project_authorizations_spec.rb57
-rw-r--r--spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb28
-rw-r--r--spec/migrations/schedule_repopulate_historical_vulnerability_statistics_spec.rb36
-rw-r--r--spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb79
-rw-r--r--spec/migrations/schedule_update_existing_users_that_require_two_factor_auth_spec.rb29
-rw-r--r--spec/migrations/seed_merge_trains_enabled_spec.rb28
-rw-r--r--spec/migrations/seed_repository_storages_weighted_spec.rb31
-rw-r--r--spec/migrations/services_remove_temporary_index_on_project_id_spec.rb40
-rw-r--r--spec/migrations/set_job_waiter_ttl_spec.rb30
-rw-r--r--spec/migrations/slice_merge_request_diff_commit_migrations_spec.rb2
-rw-r--r--spec/migrations/steal_merge_request_diff_commit_users_migration_spec.rb2
-rw-r--r--spec/migrations/unconfirm_wrongfully_verified_emails_spec.rb55
-rw-r--r--spec/migrations/update_application_setting_npm_package_requests_forwarding_default_spec.rb38
-rw-r--r--spec/migrations/update_fingerprint_sha256_within_keys_spec.rb30
-rw-r--r--spec/migrations/update_historical_data_recorded_at_spec.rb31
-rw-r--r--spec/migrations/update_internal_ids_last_value_for_epics_renamed_spec.rb30
-rw-r--r--spec/migrations/update_routes_for_lost_and_found_group_and_orphaned_projects_spec.rb223
-rw-r--r--spec/migrations/update_timestamp_softwarelicensespolicy_spec.rb24
-rw-r--r--spec/models/ability_spec.rb4
-rw-r--r--spec/models/acts_as_taggable_on/tag_spec.rb16
-rw-r--r--spec/models/acts_as_taggable_on/tagging_spec.rb16
-rw-r--r--spec/models/analytics/cycle_analytics/issue_stage_event_spec.rb9
-rw-r--r--spec/models/analytics/cycle_analytics/merge_request_stage_event_spec.rb9
-rw-r--r--spec/models/blob_viewer/package_json_spec.rb52
-rw-r--r--spec/models/bulk_imports/entity_spec.rb9
-rw-r--r--spec/models/bulk_imports/file_transfer/project_config_spec.rb2
-rw-r--r--spec/models/chat_name_spec.rb8
-rw-r--r--spec/models/ci/bridge_spec.rb2
-rw-r--r--spec/models/ci/build_metadata_spec.rb12
-rw-r--r--spec/models/ci/build_spec.rb267
-rw-r--r--spec/models/ci/job_artifact_spec.rb62
-rw-r--r--spec/models/ci/pipeline_schedule_spec.rb2
-rw-r--r--spec/models/ci/pipeline_spec.rb18
-rw-r--r--spec/models/ci/runner_spec.rb53
-rw-r--r--spec/models/ci/trigger_spec.rb4
-rw-r--r--spec/models/clusters/applications/runner_spec.rb6
-rw-r--r--spec/models/clusters/cluster_spec.rb6
-rw-r--r--spec/models/commit_status_spec.rb16
-rw-r--r--spec/models/concerns/bulk_insert_safe_spec.rb24
-rw-r--r--spec/models/concerns/bulk_insertable_associations_spec.rb32
-rw-r--r--spec/models/concerns/cascading_namespace_setting_attribute_spec.rb15
-rw-r--r--spec/models/concerns/clusters/agents/authorization_config_scopes_spec.rb21
-rw-r--r--spec/models/concerns/database_reflection_spec.rb18
-rw-r--r--spec/models/concerns/has_integrations_spec.rb25
-rw-r--r--spec/models/concerns/legacy_bulk_insert_spec.rb103
-rw-r--r--spec/models/concerns/loaded_in_group_list_spec.rb58
-rw-r--r--spec/models/concerns/loose_foreign_key_spec.rb29
-rw-r--r--spec/models/concerns/noteable_spec.rb64
-rw-r--r--spec/models/concerns/prometheus_adapter_spec.rb8
-rw-r--r--spec/models/concerns/reactive_caching_spec.rb2
-rw-r--r--spec/models/concerns/sha256_attribute_spec.rb2
-rw-r--r--spec/models/concerns/sha_attribute_spec.rb2
-rw-r--r--spec/models/concerns/where_composite_spec.rb2
-rw-r--r--spec/models/concerns/x509_serial_number_attribute_spec.rb2
-rw-r--r--spec/models/custom_emoji_spec.rb2
-rw-r--r--spec/models/customer_relations/contact_spec.rb3
-rw-r--r--spec/models/customer_relations/issue_contact_spec.rb48
-rw-r--r--spec/models/data_list_spec.rb31
-rw-r--r--spec/models/dependency_proxy/manifest_spec.rb21
-rw-r--r--spec/models/deploy_key_spec.rb11
-rw-r--r--spec/models/deployment_spec.rb81
-rw-r--r--spec/models/design_management/version_spec.rb2
-rw-r--r--spec/models/email_spec.rb11
-rw-r--r--spec/models/environment_spec.rb44
-rw-r--r--spec/models/error_tracking/error_event_spec.rb20
-rw-r--r--spec/models/error_tracking/error_spec.rb4
-rw-r--r--spec/models/event_spec.rb12
-rw-r--r--spec/models/fork_network_spec.rb6
-rw-r--r--spec/models/generic_commit_status_spec.rb2
-rw-r--r--spec/models/grafana_integration_spec.rb6
-rw-r--r--spec/models/group_spec.rb55
-rw-r--r--spec/models/hooks/project_hook_spec.rb2
-rw-r--r--spec/models/identity_spec.rb10
-rw-r--r--spec/models/integration_spec.rb18
-rw-r--r--spec/models/integrations/jira_spec.rb148
-rw-r--r--spec/models/integrations/pipelines_email_spec.rb38
-rw-r--r--spec/models/integrations/shimo_spec.rb41
-rw-r--r--spec/models/integrations/zentao_spec.rb6
-rw-r--r--spec/models/issue_spec.rb25
-rw-r--r--spec/models/jira_import_state_spec.rb4
-rw-r--r--spec/models/key_spec.rb4
-rw-r--r--spec/models/loose_foreign_keys/deleted_record_spec.rb35
-rw-r--r--spec/models/loose_foreign_keys/modification_tracker_spec.rb93
-rw-r--r--spec/models/member_spec.rb14
-rw-r--r--spec/models/members/member_task_spec.rb124
-rw-r--r--spec/models/members/project_member_spec.rb54
-rw-r--r--spec/models/merge_request_assignee_spec.rb4
-rw-r--r--spec/models/merge_request_diff_commit_spec.rb16
-rw-r--r--spec/models/merge_request_diff_spec.rb20
-rw-r--r--spec/models/merge_request_reviewer_spec.rb4
-rw-r--r--spec/models/merge_request_spec.rb22
-rw-r--r--spec/models/namespace_spec.rb295
-rw-r--r--spec/models/namespaces/project_namespace_spec.rb2
-rw-r--r--spec/models/note_spec.rb22
-rw-r--r--spec/models/notification_setting_spec.rb12
-rw-r--r--spec/models/operations/feature_flags/strategy_spec.rb269
-rw-r--r--spec/models/operations/feature_flags/user_list_spec.rb21
-rw-r--r--spec/models/packages/npm/metadatum_spec.rb50
-rw-r--r--spec/models/packages/package_file_spec.rb23
-rw-r--r--spec/models/packages/package_spec.rb24
-rw-r--r--spec/models/pages_domain_spec.rb4
-rw-r--r--spec/models/preloaders/group_policy_preloader_spec.rb45
-rw-r--r--spec/models/preloaders/group_root_ancestor_preloader_spec.rb63
-rw-r--r--spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb49
-rw-r--r--spec/models/project_authorization_spec.rb21
-rw-r--r--spec/models/project_spec.rb113
-rw-r--r--spec/models/project_statistics_spec.rb4
-rw-r--r--spec/models/project_team_spec.rb14
-rw-r--r--spec/models/protectable_dropdown_spec.rb2
-rw-r--r--spec/models/redirect_route_spec.rb10
-rw-r--r--spec/models/release_spec.rb14
-rw-r--r--spec/models/remote_mirror_spec.rb10
-rw-r--r--spec/models/repository_spec.rb79
-rw-r--r--spec/models/route_spec.rb14
-rw-r--r--spec/models/sentry_issue_spec.rb2
-rw-r--r--spec/models/snippet_spec.rb6
-rw-r--r--spec/models/suggestion_spec.rb8
-rw-r--r--spec/models/u2f_registration_spec.rb28
-rw-r--r--spec/models/upload_spec.rb18
-rw-r--r--spec/models/uploads/fog_spec.rb27
-rw-r--r--spec/models/user_spec.rb138
-rw-r--r--spec/models/users/credit_card_validation_spec.rb18
-rw-r--r--spec/models/users/in_product_marketing_email_spec.rb3
-rw-r--r--spec/models/users/merge_request_interaction_spec.rb5
-rw-r--r--spec/models/users_statistics_spec.rb16
-rw-r--r--spec/models/webauthn_registration_spec.rb23
-rw-r--r--spec/policies/group_policy_spec.rb33
-rw-r--r--spec/policies/namespaces/project_namespace_policy_spec.rb3
-rw-r--r--spec/policies/project_policy_spec.rb84
-rw-r--r--spec/presenters/award_emoji_presenter_spec.rb9
-rw-r--r--spec/presenters/blob_presenter_spec.rb55
-rw-r--r--spec/presenters/ci/build_runner_presenter_spec.rb57
-rw-r--r--spec/presenters/packages/npm/package_presenter_spec.rb88
-rw-r--r--spec/presenters/project_presenter_spec.rb74
-rw-r--r--spec/presenters/release_presenter_spec.rb14
-rw-r--r--spec/requests/admin/applications_controller_spec.rb18
-rw-r--r--spec/requests/api/api_spec.rb24
-rw-r--r--spec/requests/api/ci/jobs_spec.rb173
-rw-r--r--spec/requests/api/ci/runner/jobs_request_post_spec.rb6
-rw-r--r--spec/requests/api/debian_group_packages_spec.rb15
-rw-r--r--spec/requests/api/debian_project_packages_spec.rb21
-rw-r--r--spec/requests/api/deploy_keys_spec.rb54
-rw-r--r--spec/requests/api/error_tracking/collector_spec.rb51
-rw-r--r--spec/requests/api/features_spec.rb30
-rw-r--r--spec/requests/api/files_spec.rb44
-rw-r--r--spec/requests/api/generic_packages_spec.rb31
-rw-r--r--spec/requests/api/graphql/ci/pipelines_spec.rb63
-rw-r--r--spec/requests/api/graphql/gitlab_schema_spec.rb23
-rw-r--r--spec/requests/api/graphql/group/dependency_proxy_manifests_spec.rb22
-rw-r--r--spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/design_management/delete_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/issues/create_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/issues/move_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/issues/set_confidential_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb161
-rw-r--r--spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/issues/set_severity_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_draft_spec.rb79
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb79
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/update_reviewer_state_spec.rb65
-rw-r--r--spec/requests/api/graphql/mutations/releases/create_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/releases/delete_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/releases/update_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb26
-rw-r--r--spec/requests/api/graphql/namespace_query_spec.rb86
-rw-r--r--spec/requests/api/graphql/packages/helm_spec.rb59
-rw-r--r--spec/requests/api/graphql/project/issues_spec.rb4
-rw-r--r--spec/requests/api/graphql/project/merge_request_spec.rb16
-rw-r--r--spec/requests/api/graphql/project/release_spec.rb186
-rw-r--r--spec/requests/api/graphql/project/releases_spec.rb15
-rw-r--r--spec/requests/api/graphql_spec.rb30
-rw-r--r--spec/requests/api/group_debian_distributions_spec.rb16
-rw-r--r--spec/requests/api/groups_spec.rb7
-rw-r--r--spec/requests/api/internal/base_spec.rb2
-rw-r--r--spec/requests/api/invitations_spec.rb32
-rw-r--r--spec/requests/api/lint_spec.rb123
-rw-r--r--spec/requests/api/members_spec.rb54
-rw-r--r--spec/requests/api/merge_requests_spec.rb2
-rw-r--r--spec/requests/api/namespaces_spec.rb76
-rw-r--r--spec/requests/api/npm_project_packages_spec.rb20
-rw-r--r--spec/requests/api/project_attributes.yml1
-rw-r--r--spec/requests/api/project_debian_distributions_spec.rb22
-rw-r--r--spec/requests/api/project_import_spec.rb2
-rw-r--r--spec/requests/api/project_snapshots_spec.rb1
-rw-r--r--spec/requests/api/project_snippets_spec.rb1
-rw-r--r--spec/requests/api/projects_spec.rb31
-rw-r--r--spec/requests/api/releases_spec.rb32
-rw-r--r--spec/requests/api/repositories_spec.rb39
-rw-r--r--spec/requests/api/settings_spec.rb41
-rw-r--r--spec/requests/api/snippets_spec.rb1
-rw-r--r--spec/requests/api/tags_spec.rb67
-rw-r--r--spec/requests/api/terraform/modules/v1/packages_spec.rb17
-rw-r--r--spec/requests/api/todos_spec.rb12
-rw-r--r--spec/requests/api/topics_spec.rb217
-rw-r--r--spec/requests/api/users_spec.rb8
-rw-r--r--spec/requests/api/v3/github_spec.rb131
-rw-r--r--spec/requests/groups/email_campaigns_controller_spec.rb10
-rw-r--r--spec/requests/groups/settings/applications_controller_spec.rb20
-rw-r--r--spec/requests/import/gitlab_groups_controller_spec.rb2
-rw-r--r--spec/requests/jwks_controller_spec.rb14
-rw-r--r--spec/requests/oauth/applications_controller_spec.rb18
-rw-r--r--spec/requests/projects/google_cloud_controller_spec.rb94
-rw-r--r--spec/requests/projects/issues/discussions_spec.rb115
-rw-r--r--spec/requests/projects/issues_controller_spec.rb71
-rw-r--r--spec/requests/projects/usage_quotas_spec.rb50
-rw-r--r--spec/requests/rack_attack_global_spec.rb4
-rw-r--r--spec/requests/users_controller_spec.rb2
-rw-r--r--spec/routing/group_routing_spec.rb20
-rw-r--r--spec/routing/openid_connect_spec.rb12
-rw-r--r--spec/rubocop/cop/gitlab/bulk_insert_spec.rb12
-rw-r--r--spec/rubocop/cop/gitlab/change_timezone_spec.rb2
-rw-r--r--spec/rubocop/cop/qa/duplicate_testcase_link_spec.rb36
-rw-r--r--spec/scripts/changed-feature-flags_spec.rb79
-rw-r--r--spec/scripts/failed_tests_spec.rb127
-rw-r--r--spec/scripts/pipeline_test_report_builder_spec.rb185
-rw-r--r--spec/serializers/analytics_summary_serializer_spec.rb2
-rw-r--r--spec/serializers/merge_request_user_entity_spec.rb9
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb33
-rw-r--r--spec/serializers/service_field_entity_spec.rb14
-rw-r--r--spec/services/admin/propagate_integration_service_spec.rb4
-rw-r--r--spec/services/authorized_project_update/project_access_changed_service_spec.rb21
-rw-r--r--spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb4
-rw-r--r--spec/services/award_emojis/base_service_spec.rb25
-rw-r--r--spec/services/bulk_create_integration_service_spec.rb21
-rw-r--r--spec/services/bulk_update_integration_service_spec.rb41
-rw-r--r--spec/services/ci/create_pipeline_service/include_spec.rb89
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb4
-rw-r--r--spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb22
-rw-r--r--spec/services/ci/generate_kubeconfig_service_spec.rb50
-rw-r--r--spec/services/ci/job_artifacts/create_service_spec.rb14
-rw-r--r--spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb63
-rw-r--r--spec/services/ci/job_artifacts/destroy_batch_service_spec.rb3
-rw-r--r--spec/services/ci/parse_dotenv_artifact_service_spec.rb6
-rw-r--r--spec/services/ci/retry_build_service_spec.rb31
-rw-r--r--spec/services/ci/unlock_artifacts_service_spec.rb280
-rw-r--r--spec/services/ci/update_build_state_service_spec.rb22
-rw-r--r--spec/services/clusters/agents/refresh_authorization_service_spec.rb10
-rw-r--r--spec/services/clusters/applications/prometheus_health_check_service_spec.rb114
-rw-r--r--spec/services/clusters/cleanup/project_namespace_service_spec.rb13
-rw-r--r--spec/services/clusters/cleanup/service_account_service_spec.rb8
-rw-r--r--spec/services/clusters/integrations/prometheus_health_check_service_spec.rb114
-rw-r--r--spec/services/dependency_proxy/find_or_create_blob_service_spec.rb2
-rw-r--r--spec/services/dependency_proxy/find_or_create_manifest_service_spec.rb66
-rw-r--r--spec/services/dependency_proxy/head_manifest_service_spec.rb2
-rw-r--r--spec/services/dependency_proxy/pull_manifest_service_spec.rb2
-rw-r--r--spec/services/deployments/archive_in_project_service_spec.rb80
-rw-r--r--spec/services/deployments/link_merge_requests_service_spec.rb13
-rw-r--r--spec/services/emails/create_service_spec.rb5
-rw-r--r--spec/services/emails/destroy_service_spec.rb10
-rw-r--r--spec/services/error_tracking/collect_error_service_spec.rb31
-rw-r--r--spec/services/google_cloud/service_accounts_service_spec.rb58
-rw-r--r--spec/services/groups/create_service_spec.rb41
-rw-r--r--spec/services/groups/import_export/import_service_spec.rb6
-rw-r--r--spec/services/groups/transfer_service_spec.rb104
-rw-r--r--spec/services/import/github/notes/create_service_spec.rb24
-rw-r--r--spec/services/issues/build_service_spec.rb96
-rw-r--r--spec/services/issues/close_service_spec.rb44
-rw-r--r--spec/services/issues/create_service_spec.rb79
-rw-r--r--spec/services/issues/set_crm_contacts_service_spec.rb162
-rw-r--r--spec/services/issues/update_service_spec.rb42
-rw-r--r--spec/services/labels/transfer_service_spec.rb156
-rw-r--r--spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb119
-rw-r--r--spec/services/loose_foreign_keys/cleaner_service_spec.rb147
-rw-r--r--spec/services/members/create_service_spec.rb104
-rw-r--r--spec/services/members/invite_service_spec.rb5
-rw-r--r--spec/services/merge_requests/mergeability/run_checks_service_spec.rb4
-rw-r--r--spec/services/merge_requests/retarget_chain_service_spec.rb8
-rw-r--r--spec/services/merge_requests/toggle_attention_requested_service_spec.rb128
-rw-r--r--spec/services/namespaces/in_product_marketing_email_records_spec.rb55
-rw-r--r--spec/services/namespaces/invite_team_email_service_spec.rb128
-rw-r--r--spec/services/notification_service_spec.rb24
-rw-r--r--spec/services/packages/create_dependency_service_spec.rb6
-rw-r--r--spec/services/packages/npm/create_package_service_spec.rb46
-rw-r--r--spec/services/packages/update_tags_service_spec.rb2
-rw-r--r--spec/services/projects/all_issues_count_service_spec.rb24
-rw-r--r--spec/services/projects/all_merge_requests_count_service_spec.rb30
-rw-r--r--spec/services/projects/container_repository/cache_tags_created_at_service_spec.rb133
-rw-r--r--spec/services/projects/container_repository/cleanup_tags_service_spec.rb457
-rw-r--r--spec/services/projects/create_service_spec.rb35
-rw-r--r--spec/services/projects/destroy_service_spec.rb8
-rw-r--r--spec/services/projects/import_export/export_service_spec.rb12
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_service_spec.rb1
-rw-r--r--spec/services/projects/participants_service_spec.rb8
-rw-r--r--spec/services/projects/prometheus/alerts/notify_service_spec.rb3
-rw-r--r--spec/services/projects/transfer_service_spec.rb8
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb53
-rw-r--r--spec/services/resource_events/change_labels_service_spec.rb2
-rw-r--r--spec/services/resource_events/synthetic_label_notes_builder_service_spec.rb12
-rw-r--r--spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb2
-rw-r--r--spec/services/resource_events/synthetic_state_notes_builder_service_spec.rb11
-rw-r--r--spec/services/security/ci_configuration/sast_iac_create_service_spec.rb19
-rw-r--r--spec/services/spam/spam_verdict_service_spec.rb4
-rw-r--r--spec/services/system_note_service_spec.rb199
-rw-r--r--spec/services/system_notes/incident_service_spec.rb10
-rw-r--r--spec/services/system_notes/issuables_service_spec.rb17
-rw-r--r--spec/services/tasks_to_be_done/base_service_spec.rb69
-rw-r--r--spec/services/todo_service_spec.rb11
-rw-r--r--spec/services/users/update_service_spec.rb2
-rw-r--r--spec/services/users/upsert_credit_card_validation_service_spec.rb13
-rw-r--r--spec/sidekiq_cluster/sidekiq_cluster_spec.rb208
-rw-r--r--spec/spec_helper.rb20
-rw-r--r--spec/support/capybara.rb4
-rw-r--r--spec/support/database/cross-database-modification-allowlist.yml1259
-rw-r--r--spec/support/database/cross-join-allowlist.yml54
-rw-r--r--spec/support/database/gitlab_schema.rb25
-rw-r--r--spec/support/database/multiple_databases.rb27
-rw-r--r--spec/support/database/prevent_cross_database_modification.rb122
-rw-r--r--spec/support/database/prevent_cross_joins.rb4
-rw-r--r--spec/support/database/query_analyzer.rb14
-rw-r--r--spec/support/database_load_balancing.rb16
-rw-r--r--spec/support/flaky_tests.rb36
-rw-r--r--spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb4
-rw-r--r--spec/support/graphql/fake_query_type.rb15
-rw-r--r--spec/support/graphql/fake_tracer.rb15
-rw-r--r--spec/support/helpers/cycle_analytics_helpers.rb4
-rw-r--r--spec/support/helpers/features/invite_members_modal_helper.rb2
-rw-r--r--spec/support/helpers/gitaly_setup.rb2
-rw-r--r--spec/support/helpers/gpg_helpers.rb1
-rw-r--r--spec/support/helpers/graphql_helpers.rb3
-rw-r--r--spec/support/helpers/migrations_helpers.rb6
-rw-r--r--spec/support/helpers/navbar_structure_helper.rb13
-rw-r--r--spec/support/helpers/project_forks_helper.rb6
-rw-r--r--spec/support/helpers/require_migration.rb6
-rw-r--r--spec/support/helpers/stub_gitlab_calls.rb9
-rw-r--r--spec/support/helpers/stub_object_storage.rb12
-rw-r--r--spec/support/helpers/test_env.rb4
-rw-r--r--spec/support/helpers/usage_data_helpers.rb2
-rw-r--r--spec/support/helpers/workhorse_helpers.rb7
-rw-r--r--spec/support/matchers/access_matchers.rb2
-rw-r--r--spec/support/matchers/project_namespace_matcher.rb28
-rw-r--r--spec/support/patches/rspec_example_prepended_methods.rb26
-rw-r--r--spec/support/redis/redis_shared_examples.rb37
-rw-r--r--spec/support/retriable.rb7
-rw-r--r--spec/support/shared_contexts/graphql/requests/packages_shared_context.rb6
-rw-r--r--spec/support/shared_contexts/lib/gitlab/database/background_migration_job_shared_context.rb21
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb2
-rw-r--r--spec/support/shared_contexts/policies/project_policy_shared_context.rb11
-rw-r--r--spec/support/shared_contexts/requests/api/debian_repository_shared_context.rb120
-rw-r--r--spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb4
-rw-r--r--spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb5
-rw-r--r--spec/support/shared_contexts/url_shared_context.rb39
-rw-r--r--spec/support/shared_examples/bulk_imports/common/pipelines/wiki_pipeline_examples.rb31
-rw-r--r--spec/support/shared_examples/controllers/concerns/integrations/integrations_actions_shared_examples.rb59
-rw-r--r--spec/support/shared_examples/controllers/concerns/integrations_actions_shared_examples.rb59
-rw-r--r--spec/support/shared_examples/controllers/create_notes_rate_limit_shared_examples.rb58
-rw-r--r--spec/support/shared_examples/features/2fa_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/features/dependency_proxy_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/manage_applications_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/packages_shared_examples.rb30
-rw-r--r--spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb38
-rw-r--r--spec/support/shared_examples/features/sidebar_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/graphql/notes_creation_shared_examples.rb26
-rw-r--r--spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb67
-rw-r--r--spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb2
-rw-r--r--spec/support/shared_examples/lib/gitlab/database/cte_materialized_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb44
-rw-r--r--spec/support/shared_examples/lib/sidebars/projects/menus/zentao_menu_shared_examples.rb42
-rw-r--r--spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb52
-rw-r--r--spec/support/shared_examples/metrics/transaction_metrics_with_labels_shared_examples.rb219
-rw-r--r--spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb117
-rw-r--r--spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb15
-rw-r--r--spec/support/shared_examples/models/member_shared_examples.rb31
-rw-r--r--spec/support/shared_examples/models/reviewer_state_shared_examples.rb15
-rw-r--r--spec/support/shared_examples/namespaces/traversal_examples.rb22
-rw-r--r--spec/support/shared_examples/namespaces/traversal_scope_examples.rb81
-rw-r--r--spec/support/shared_examples/quick_actions/issue/promote_to_incident_quick_action_shared_examples.rb40
-rw-r--r--spec/support/shared_examples/requests/api/debian_common_shared_examples.rb17
-rw-r--r--spec/support/shared_examples/requests/api/debian_distributions_shared_examples.rb192
-rw-r--r--spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb369
-rw-r--r--spec/support/shared_examples/requests/api/graphql/mutations/destroy_list_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb18
-rw-r--r--spec/support/shared_examples/requests/api/notes_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb15
-rw-r--r--spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/requests/api/status_shared_examples.rb29
-rw-r--r--spec/support/shared_examples/requests/applications_controller_shared_examples.rb44
-rw-r--r--spec/support/shared_examples/requests/self_monitoring_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/requests/snippet_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/service_desk_issue_templates_examples.rb8
-rw-r--r--spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/services/jira/requests/base_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/services/resource_events/synthetic_notes_builder_shared_examples.rb25
-rw-r--r--spec/support/shared_examples/workers/self_monitoring_shared_examples.rb2
-rw-r--r--spec/support/stub_snowplow.rb2
-rw-r--r--spec/support/test_reports/test_reports_helper.rb6
-rw-r--r--spec/support/time_travel.rb21
-rw-r--r--spec/support_specs/database/multiple_databases_spec.rb6
-rw-r--r--spec/support_specs/database/prevent_cross_database_modification_spec.rb163
-rw-r--r--spec/support_specs/helpers/stub_feature_flags_spec.rb2
-rw-r--r--spec/support_specs/time_travel_spec.rb21
-rw-r--r--spec/tasks/gitlab/db_rake_spec.rb46
-rw-r--r--spec/tasks/gitlab/gitaly_rake_spec.rb35
-rw-r--r--spec/tasks/gitlab/storage_rake_spec.rb4
-rw-r--r--spec/tooling/danger/changelog_spec.rb4
-rw-r--r--spec/tooling/danger/product_intelligence_spec.rb83
-rw-r--r--spec/tooling/danger/project_helper_spec.rb128
-rw-r--r--spec/tooling/quality/test_level_spec.rb12
-rw-r--r--spec/validators/addressable_url_validator_spec.rb12
-rw-r--r--spec/views/groups/settings/_remove.html.haml_spec.rb4
-rw-r--r--spec/views/groups/settings/_transfer.html.haml_spec.rb6
-rw-r--r--spec/views/jira_connect/subscriptions/index.html.haml_spec.rb2
-rw-r--r--spec/views/layouts/_published_experiments.html.haml_spec.rb35
-rw-r--r--spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb24
-rw-r--r--spec/views/profiles/audit_log.html.haml_spec.rb26
-rw-r--r--spec/views/projects/edit.html.haml_spec.rb35
-rw-r--r--spec/views/projects/issues/_service_desk_info_content.html.haml_spec.rb95
-rw-r--r--spec/workers/analytics/usage_trends/counter_job_worker_spec.rb3
-rw-r--r--spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb34
-rw-r--r--spec/workers/ci/resource_groups/assign_resource_from_resource_group_worker_spec.rb4
-rw-r--r--spec/workers/clusters/applications/check_prometheus_health_worker_spec.rb19
-rw-r--r--spec/workers/clusters/integrations/check_prometheus_health_worker_spec.rb19
-rw-r--r--spec/workers/concerns/application_worker_spec.rb381
-rw-r--r--spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb5
-rw-r--r--spec/workers/database/drop_detached_partitions_worker_spec.rb8
-rw-r--r--spec/workers/database/partition_management_worker_spec.rb9
-rw-r--r--spec/workers/dependency_proxy/image_ttl_group_policy_worker_spec.rb4
-rw-r--r--spec/workers/deployments/archive_in_project_worker_spec.rb18
-rw-r--r--spec/workers/email_receiver_worker_spec.rb9
-rw-r--r--spec/workers/emails_on_push_worker_spec.rb37
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb2
-rw-r--r--spec/workers/integrations/create_external_cross_reference_worker_spec.rb128
-rw-r--r--spec/workers/issue_rebalancing_worker_spec.rb16
-rw-r--r--spec/workers/issues/placement_worker_spec.rb151
-rw-r--r--spec/workers/issues/rebalancing_worker_spec.rb90
-rw-r--r--spec/workers/issues/reschedule_stuck_issue_rebalances_worker_spec.rb26
-rw-r--r--spec/workers/loose_foreign_keys/cleanup_worker_spec.rb153
-rw-r--r--spec/workers/namespaces/invite_team_email_worker_spec.rb27
-rw-r--r--spec/workers/packages/maven/metadata/sync_worker_spec.rb3
-rw-r--r--spec/workers/post_receive_spec.rb8
-rw-r--r--spec/workers/propagate_integration_group_worker_spec.rb2
-rw-r--r--spec/workers/propagate_integration_inherit_descendant_worker_spec.rb4
-rw-r--r--spec/workers/propagate_integration_project_worker_spec.rb2
-rw-r--r--spec/workers/ssh_keys/expired_notification_worker_spec.rb6
-rw-r--r--spec/workers/tasks_to_be_done/create_worker_spec.rb36
-rw-r--r--spec/workers/users/deactivate_dormant_users_worker_spec.rb36
-rwxr-xr-xtooling/bin/find_change_diffs38
-rwxr-xr-xtooling/bin/find_changes2
-rwxr-xr-xtooling/bin/qa/package_and_qa_check45
-rw-r--r--tooling/danger/changelog.rb2
-rw-r--r--tooling/danger/product_intelligence.rb57
-rw-r--r--tooling/danger/project_helper.rb41
-rw-r--r--tooling/deprecations/docs.rb6
-rw-r--r--tooling/lib/tooling/image.rb (renamed from tooling/lib/tooling/images.rb)0
-rw-r--r--tooling/quality/test_level.rb2
-rw-r--r--tooling/rspec_flaky/report.rb2
-rw-r--r--vendor/project_templates/cluster_management.tar.gzbin14762 -> 16093 bytes
-rw-r--r--vendor/project_templates/learn_gitlab_ultimate.tar.gz (renamed from vendor/project_templates/learn_gitlab_ultimate_trial.tar.gz)bin115092 -> 115092 bytes
-rw-r--r--vendor/project_templates/tencent_serverless_framework.tar.gzbin0 -> 119482 bytes
-rw-r--r--workhorse/.tool-versions1
-rw-r--r--workhorse/Makefile31
-rw-r--r--workhorse/gitaly_integration_test.go25
-rw-r--r--workhorse/internal/dependencyproxy/dependencyproxy.go41
-rw-r--r--workhorse/internal/dependencyproxy/dependencyproxy_test.go17
-rw-r--r--workhorse/internal/filestore/file_handler.go34
-rw-r--r--workhorse/internal/filestore/file_handler_test.go1
-rw-r--r--workhorse/internal/helper/httptransport/http_transport.go37
-rw-r--r--workhorse/internal/imageresizer/image_resizer.go20
-rw-r--r--workhorse/internal/objectstore/object.go25
-rw-r--r--workhorse/internal/sendurl/sendurl.go22
-rw-r--r--workhorse/internal/upload/uploads_test.go2
-rw-r--r--workhorse/internal/upstream/roundtripper/roundtripper.go12
-rw-r--r--workhorse/internal/upstream/roundtripper/transport.go27
-rw-r--r--workhorse/internal/upstream/routes.go7
-rw-r--r--workhorse/internal/upstream/routes_test.go47
-rw-r--r--workhorse/internal/upstream/upstream_test.go32
-rw-r--r--workhorse/internal/zipartifacts/open_archive.go20
-rw-r--r--workhorse/upload_test.go4
-rw-r--r--yarn.lock908
10846 files changed, 196766 insertions, 122637 deletions
diff --git a/.codeclimate.yml b/.codeclimate.yml
index c479454285e..fe3c6056890 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -1,5 +1,6 @@
---
-engines:
+version: "2"
+plugins:
bundler-audit:
enabled: true
duplication:
@@ -8,33 +9,22 @@ engines:
languages:
- ruby
- javascript
-ratings:
- paths:
- - Gemfile.lock
- - "**.erb"
- - "**.haml"
- - "**.rb"
- - "**.rhtml"
- - "**.slim"
- - "**.inc"
- - "**.js"
- - "**.jsx"
- - "**.module"
-exclude_paths:
- - config/
- - db/
- - features/
- - node_modules/
- - spec/
- - vendor/
+ rubocop:
+ enabled: false
+exclude_patterns:
+ - "{ee/,jh/,}config/"
+ - "{ee/,jh/,}db/"
+ - "**/log/"
+ - "**/node_modules/"
+ - "**/spec/"
+ - "**/tmp/"
+ - "**/vendor/"
- .yarn-cache/
- - tmp/
+ - backups/
- builds/
- coverage/
+ - file_hooks/
+ - plugins/
- public/
- shared/
- webpack-report/
- - log/
- - backups/
- - plugins/
- - file_hooks/
diff --git a/.eslintignore b/.eslintignore
index d5f89284b53..1d069e19385 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -7,3 +7,5 @@
/tmp/
/vendor/
/sitespeed-result/
+/fixtures/**/*.graphql
+spec/fixtures/**/*.graphql
diff --git a/.eslintrc.yml b/.eslintrc.yml
index cd3cd82d4e7..623c1a66301 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -113,3 +113,24 @@ overrides:
- '*.stories.js'
rules:
filenames/match-regex: off
+ - files:
+ - '*.graphql'
+ plugins:
+ - '@graphql-eslint'
+ parserOptions:
+ parser: '@graphql-eslint/eslint-plugin'
+ operations:
+ - '{,ee/,jh/}app/**/*.graphql'
+ # You can run `bundle exec rake gitlab:graphql:schema:dump` and then uncomment this line
+ # schema: './tmp/tests/graphql/gitlab_schema.graphql'
+ rules:
+ filenames/match-regex: off
+ spaced-comment: off
+ # TODO: We need a way to include this rule + support ee_else_ce fragments
+ #'@graphql-eslint/unique-fragment-name': error
+ # TODO: Uncomment these rules when then `schema` is available
+ #'@graphql-eslint/fragments-on-composite-type': error
+ #'@graphql-eslint/known-argument-names': error
+ #'@graphql-eslint/known-type-names': error
+ '@graphql-eslint/no-anonymous-operations': error
+ '@graphql-eslint/unique-operation-name': error
diff --git a/.gitignore b/.gitignore
index 5152ef20575..bff82967fc6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -74,6 +74,7 @@ eslint-report.html
/.gitlab_kas_secret
/webpack-report/
/crystalball/
+/test_results/
/deprecations/
/knapsack/
/rspec_flaky/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b72ad359532..e810edd8133 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,6 +3,7 @@ stages:
- prepare
- build-images
- fixtures
+ - lint
- test
- post-test
- review
@@ -15,7 +16,7 @@ stages:
# in cases where jobs require Docker-in-Docker, the job
# definition must be extended with `.use-docker-in-docker`
default:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
tags:
- gitlab-org
# All jobs are interruptible by default
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 64e74dd12e6..c6a89ddfa9c 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -26,7 +26,7 @@
/doc/administration/troubleshooting @marcel.amirault @marcia @eread
/doc/api/graphql/ @msedlakjakubowski @kpaizee
/doc/api/graphql/reference/ @kpaizee
-/doc/api/group_activity_analytics.md @msedlakjakubowski
+/doc/api/group_activity_analytics.md @fneill
/doc/ci/ @marcel.amirault @sselhorn
/doc/ci/environments/ @rdickenson
/doc/ci/services/ @sselhorn
@@ -34,7 +34,7 @@
/doc/development/ @marcia
/doc/development/documentation/ @cnorris @dianalogan
/doc/development/i18n/ @ngaskill
-/doc/development/value_stream_analytics.md @msedlakjakubowski
+/doc/development/value_stream_analytics.md @fneill
/doc/gitlab-basics/ @aqualls
/doc/install/ @marcel.amirault
/doc/operations/ @ngaskill @rdickenson
@@ -45,19 +45,19 @@
/doc/topics/autodevops/ @marcia
/doc/topics/git/ @aqualls
/doc/update/ @marcel.amirault @marcia
-/doc/user/analytics/ @msedlakjakubowski @ngaskill
+/doc/user/analytics/ @fneill @ngaskill
/doc/user/application_security/ @rdickenson
/doc/user/application_security/container_scanning/ @ngaskill
/doc/user/application_security/cluster_image_scanning/ @ngaskill
/doc/user/clusters/ @marcia
/doc/user/compliance/ @rdickenson @eread
/doc/user/group/ @msedlakjakubowski
-/doc/user/group/devops_adoption/ @msedlakjakubowski
+/doc/user/group/devops_adoption/ @fneill
/doc/user/group/epics/ @msedlakjakubowski
-/doc/user/group/insights/ @msedlakjakubowski
+/doc/user/group/insights/ @fneill
/doc/user/group/iterations/ @msedlakjakubowski
/doc/user/group/roadmap/ @msedlakjakubowski
-/doc/user/group/value_stream_analytics/ @msedlakjakubowski
+/doc/user/group/value_stream_analytics/ @fneill
/doc/user/infrastructure/ @marcia
/doc/user/packages/ @ngaskill
/doc/user/packages/infrastructure_registry/ @marcia
@@ -76,6 +76,7 @@
/doc/user/project/web_ide/index.md @aqualls
/doc/user/project/wiki/index.md @aqualls
/doc/user/search/ @marcia @aqualls
+/doc/user/workspace/ @fneill
[Docs Create]
/doc/administration/file_hooks.md @aqualls
diff --git a/.gitlab/ci/cache-repo.gitlab-ci.yml b/.gitlab/ci/cache-repo.gitlab-ci.yml
deleted file mode 100644
index 98c8c72ae3a..00000000000
--- a/.gitlab/ci/cache-repo.gitlab-ci.yml
+++ /dev/null
@@ -1,63 +0,0 @@
-# Builds a cached .tar.gz of the $CI_DEFAULT_BRANCH branch with full history and
-# uploads it to Google Cloud Storage. This archive is downloaded by a
-# script defined by a CI/CD variable named CI_PRE_CLONE_SCRIPT. This has
-# two benefits:
-#
-# 1. It speeds up builds. A 800 MB download only takes seconds.
-# 2. It significantly reduces load on the file server. Smaller deltas
-# means less time spent in git pack-objects.
-#
-# Since the destination directory of the archive depends on the project
-# ID, this is only run on GitLab.com.
-#
-# CI_REPO_CACHE_CREDENTIALS contains the Google Cloud service account
-# JSON for uploading to the gitlab-ci-git-repo-cache bucket. These
-# credentials are stored in the Production vault.
-#
-# Note that this bucket should be located in the same continent as the
-# runner, or network egress charges will apply:
-# https://cloud.google.com/storage/pricing
-cache-repo:
- extends: .cache-repo:rules
- image: gcr.io/google.com/cloudsdktool/cloud-sdk:alpine
- stage: sync
- variables:
- GIT_STRATEGY: none
- SHALLOW_CLONE_TAR_FILENAME: gitlab-master-shallow.tar
- FULL_CLONE_TAR_FILENAME: gitlab-master.tar
- before_script:
- - '[ -z "$CI_REPO_CACHE_CREDENTIALS" ] || gcloud auth activate-service-account --key-file=$CI_REPO_CACHE_CREDENTIALS'
- script:
- # Enable shallow repo caching unless the $DISABLE_SHALLOW_REPO_CACHING variable exists (in the case the shallow clone caching isn't working well)
- # The `git repack` call works around a Git bug with shallow clones: https://gitlab.com/gitlab-org/git/-/issues/86
- - if [ -z "$DISABLE_SHALLOW_REPO_CACHING" ]; then
- cd .. && rm -rf $CI_PROJECT_NAME;
- today=$(date +%Y-%m-%d);
- year=$(date +%Y);
- last_year=`expr $year - 1`;
- one_year_ago=$(echo $today | sed "s/$year/$last_year/");
- echo "Cloning $CI_REPOSITORY_URL into $CI_PROJECT_NAME with commits from $one_year_ago.";
- time git clone --progress --no-checkout --shallow-since=$one_year_ago $CI_REPOSITORY_URL $CI_PROJECT_NAME;
- cd $CI_PROJECT_NAME;
- time git repack -d;
- echo "Archiving $CI_PROJECT_NAME into /tmp/$SHALLOW_CLONE_TAR_FILENAME.";
- time git remote rm origin;
- time tar cf /tmp/$SHALLOW_CLONE_TAR_FILENAME .;
- echo "GZipping /tmp/$SHALLOW_CLONE_TAR_FILENAME.";
- time gzip /tmp/$SHALLOW_CLONE_TAR_FILENAME;
- [ -z "$CI_REPO_CACHE_CREDENTIALS" ] || (echo "Uploading /tmp/$SHALLOW_CLONE_TAR_FILENAME.gz to GCloud." && time gsutil cp /tmp/$SHALLOW_CLONE_TAR_FILENAME.gz gs://gitlab-ci-git-repo-cache/project-$CI_PROJECT_ID/$SHALLOW_CLONE_TAR_FILENAME.gz);
- fi
- # Disable the full repo caching unless the $DISABLE_SHALLOW_REPO_CACHING variable exists (in the case the shallow clone caching isn't working well)
- - if [ -n "$DISABLE_SHALLOW_REPO_CACHING" ]; then
- cd .. && rm -rf $CI_PROJECT_NAME;
- echo "Cloning $CI_REPOSITORY_URL into $CI_PROJECT_NAME.";
- time git clone --progress $CI_REPOSITORY_URL $CI_PROJECT_NAME;
- cd $CI_PROJECT_NAME;
- time git repack -d;
- echo "Archiving $CI_PROJECT_NAME into /tmp/$FULL_CLONE_TAR_FILENAME.";
- time git remote rm origin;
- time tar cf /tmp/$FULL_CLONE_TAR_FILENAME .;
- echo "GZipping /tmp/$FULL_CLONE_TAR_FILENAME.";
- time gzip /tmp/$FULL_CLONE_TAR_FILENAME;
- [ -z "$CI_REPO_CACHE_CREDENTIALS" ] || (echo "Uploading /tmp/$FULL_CLONE_TAR_FILENAME.gz to GCloud." && time gsutil cp /tmp/$FULL_CLONE_TAR_FILENAME.gz gs://gitlab-ci-git-repo-cache/project-$CI_PROJECT_ID/$FULL_CLONE_TAR_FILENAME.gz);
- fi
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index f4d8698f22d..6aa3d533315 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -44,8 +44,8 @@ docs-lint markdown:
- .default-retry
- .docs:rules:docs-lint
# When updating the image version here, update it in /scripts/lint-doc.sh too.
- image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.14-vale-2.10.4-markdownlint-0.28.1
- stage: test
+ image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.14-vale-2.12.0-markdownlint-0.29.0
+ stage: lint
needs: []
script:
- scripts/lint-doc.sh
@@ -53,8 +53,8 @@ docs-lint markdown:
docs-lint links:
extends:
- .docs:rules:docs-lint
- image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-html:alpine-3.14-ruby-2.7.4-db71f027
- stage: test
+ image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-html:alpine-3.14-ruby-2.7.4-0fae0f62
+ stage: lint
needs: []
script:
# Prepare docs for build
@@ -71,7 +71,21 @@ ui-docs-links lint:
extends:
- .docs:rules:docs-lint
- .static-analysis-base
- stage: test
+ - .ruby-cache
+ stage: lint
needs: []
script:
- bundle exec haml-lint -i DocumentationLinks
+
+docs-lint deprecations:
+ variables:
+ SETUP_DB: "false"
+ extends:
+ - .default-retry
+ - .rails-cache
+ - .default-before_script
+ - .docs:rules:deprecations
+ stage: lint
+ needs: []
+ script:
+ - bundle exec rake gitlab:docs:check_deprecations
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 6974d63a49c..d3844d01213 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -11,7 +11,7 @@
- .default-retry
- .default-before_script
- .assets-compile-cache
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7-git-2.31-lfs-2.9-node-14.15-yarn-1.22-graphicsmagick-1.3.36
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7-git-2.33-lfs-2.9-node-14.15-yarn-1.22-graphicsmagick-1.3.36
variables:
SETUP_DB: "false"
WEBPACK_VENDOR_DLL: "true"
@@ -133,6 +133,7 @@ update-storybook-yarn-cache:
paths:
- tmp/tests/frontend/
- knapsack/
+ - crystalball/
# Builds FOSS, and EE fixtures in the EE project.
# Builds FOSS fixtures in the FOSS project.
@@ -193,21 +194,10 @@ graphql-schema-dump:
# Disable warnings in browserslist which can break on backports
# https://github.com/browserslist/browserslist/blob/a287ec6/node.js#L367-L384
BROWSERSLIST_IGNORE_OLD_DATA: "true"
- SETUP_DB: "false"
before_script:
- - !reference [.default-before_script, before_script]
- *yarn-install
stage: test
-eslint-as-if-foss:
- extends:
- - .frontend-test-base
- - .frontend:rules:eslint-as-if-foss
- - .as-if-foss
- needs: []
- script:
- - run_timed_command "yarn run lint:eslint:all"
-
.jest-base:
extends: .frontend-test-base
script:
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index d0c26d60066..22bd3b1e2e9 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -44,6 +44,7 @@
prefix: "gitaly-binaries"
paths:
- tmp/tests/gitaly/_build/bin/
+ - tmp/tests/gitaly/_build/deps/git/install/
- tmp/tests/gitaly/config.toml
- tmp/tests/gitaly/gitaly2.config.toml
- tmp/tests/gitaly/internal/
@@ -139,6 +140,10 @@
- <<: *gitaly-binaries-cache
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
+.ruby-cache:
+ cache:
+ - *ruby-gems-cache
+
.rails-cache:
cache:
- *ruby-gems-cache
@@ -150,7 +155,12 @@
- *node-modules-cache
- *rubocop-cache
-.static-analysis-cache-push:
+.rubocop-job-cache:
+ cache:
+ - *ruby-gems-cache
+ - *rubocop-cache
+
+.rubocop-job-cache-push:
cache:
- *ruby-gems-cache # We don't push this cache as it's already rebuilt by `update-setup-test-env-cache`
- *rubocop-cache-push
@@ -203,7 +213,7 @@
- *storybook-node-modules-cache-push
.use-pg11:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
services:
- name: postgres:11.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -212,7 +222,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36"
services:
- name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -221,7 +231,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg13:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-13-graphicsmagick-1.3.36"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-13-graphicsmagick-1.3.36"
services:
- name: postgres:13
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -230,34 +240,34 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg11-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
services:
- name: postgres:11.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:5.0-alpine
- - name: elasticsearch:7.11.1
+ - name: elasticsearch:7.14.2
command: ["elasticsearch", "-E", "discovery.type=single-node"]
variables:
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36"
services:
- name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:5.0-alpine
- - name: elasticsearch:7.11.1
+ - name: elasticsearch:7.14.2
command: ["elasticsearch", "-E", "discovery.type=single-node"]
variables:
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg13-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-13-graphicsmagick-1.3.36"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-13-graphicsmagick-1.3.36"
services:
- name: postgres:13
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:5.0-alpine
- - name: elasticsearch:7.11.1
+ - name: elasticsearch:7.14.2
command: ["elasticsearch", "-E", "discovery.type=single-node"]
variables:
POSTGRES_HOST_AUTH_METHOD: trust
diff --git a/.gitlab/ci/qa-report.gitlab-ci.yml b/.gitlab/ci/qa-report.gitlab-ci.yml
new file mode 100644
index 00000000000..61cbcfd58da
--- /dev/null
+++ b/.gitlab/ci/qa-report.gitlab-ci.yml
@@ -0,0 +1,15 @@
+test-reliability-report:
+ extends:
+ - .qa:rules:reliable-reports:schedule
+ image:
+ name: ${CI_REGISTRY_IMAGE}/gitlab-ee-qa:${CI_DEFAULT_BRANCH}
+ entrypoint: [""]
+ before_script:
+ - cd /home/gitlab/qa
+ script:
+ - echo "Generate report for 'staging-full' runs"
+ - bundle exec rake "reliable_spec_report[staging-full,30,true]"
+ - bundle exec rake "unreliable_spec_report[staging-full,30,true]"
+ - echo "Generate report for 'package-and-qa' runs"
+ - bundle exec rake "reliable_spec_report[package-and-qa,30,true]"
+ - bundle exec rake "unreliable_spec_report[package-and-qa,30,true]"
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index 88e732c2e75..74fc5f2cdc0 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -55,14 +55,18 @@ update-qa-cache:
before_script:
- source scripts/utils.sh
- install_gitlab_gem
+ - tooling/bin/find_change_diffs ${CHANGES_DIFFS_DIR}
script:
- - ./scripts/trigger-build omnibus
-
-package-and-qa:
- extends:
- - .package-and-qa-base
- - .qa:rules:package-and-qa
- # This job often times out, so temporarily use private runners and a long timeout: https://gitlab.com/gitlab-org/gitlab/-/issues/238563
+ - |
+ tooling/bin/qa/package_and_qa_check ${CHANGES_DIFFS_DIR} && exit_code=$?
+ if [ $exit_code -eq 0 ]; then
+ ./scripts/trigger-build omnibus
+ elif [ $exit_code -eq 1 ]; then
+ exit 1
+ else
+ echo "Downstream jobs will not be triggered because package_and_qa_check exited with code: $exit_code"
+ fi
+ # These jobs often time out, so temporarily use private runners and a long timeout: https://gitlab.com/gitlab-org/gitlab/-/issues/238563
tags:
- prm
timeout: 4h
@@ -71,3 +75,39 @@ package-and-qa:
artifacts: false
- job: build-assets-image
artifacts: false
+ - detect-tests
+ artifacts:
+ expire_in: 7d
+ paths:
+ - ${CHANGES_FILE}
+ - ${CHANGES_DIFFS_DIR}/*
+ variables:
+ CHANGES_FILE: tmp/changed_files.txt
+ CHANGES_DIFFS_DIR: tmp/diffs
+
+.package-and-qa-ff-base:
+ script:
+ - export GITLAB_QA_OPTIONS="--set-feature-flags $(scripts/changed-feature-flags --files $(cat $CHANGES_FILE | tr ' ' ',') --state $QA_FF_STATE)"
+ - echo $GITLAB_QA_OPTIONS
+ - ./scripts/trigger-build omnibus
+
+package-and-qa:
+ extends:
+ - .package-and-qa-base
+ - .qa:rules:package-and-qa
+
+package-and-qa-ff-enabled:
+ extends:
+ - .package-and-qa-base
+ - .package-and-qa-ff-base
+ - .qa:rules:package-and-qa:feature-flags
+ variables:
+ QA_FF_STATE: "enable"
+
+package-and-qa-ff-disabled:
+ extends:
+ - .package-and-qa-base
+ - .package-and-qa-ff-base
+ - .qa:rules:package-and-qa:feature-flags
+ variables:
+ QA_FF_STATE: "disable"
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 00f65ab7ca8..1fb1c887e56 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -6,11 +6,6 @@
- .default-before_script
- .rails-cache
-.minimal-bundle-install:
- script:
- - export BUNDLE_WITHOUT="${BUNDLE_WITHOUT}:default:test:puma:kerberos:metrics:omnibus:ed25519"
- - bundle_install_script
-
.base-script:
script:
# Only install knapsack after bundle install! Otherwise oddly some native
@@ -26,6 +21,8 @@
.decomposed-database-rspec:
variables:
DECOMPOSED_DB: "true"
+ GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: "main"
+ GITLAB_USE_MODEL_LOAD_BALANCING: "true"
.rspec-base:
extends: .rails-job-base
@@ -77,6 +74,12 @@
- .use-pg12
needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets as-if-foss", "detect-tests"]
+.rspec-base-pg12-as-if-jh:
+ extends:
+ - .rspec-base
+ - .use-pg12
+ needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets as-if-jh", "detect-tests", "add-jh-folder"]
+
.rspec-base-pg13:
extends:
- .rspec-base
@@ -92,6 +95,11 @@
- .rspec-base
- .use-pg12-ee
+.rspec-jh-base-pg12:
+ extends:
+ - .rspec-base-pg12-as-if-jh
+ - .use-pg12-ee
+
.rspec-ee-base-pg13:
extends:
- .rspec-base
@@ -113,6 +121,12 @@
- .rspec-ee-base-geo
- .use-pg12-ee
+.rspec-jh-base-geo-pg12:
+ extends:
+ - .rspec-jh-base-pg12
+ script:
+ - !reference [.rspec-ee-base-geo, script]
+
.rspec-ee-base-geo-pg13:
extends:
- .rspec-ee-base-geo
@@ -165,10 +179,9 @@ setup-test-env:
extends:
- .rails-job-base
- .setup-test-env-cache
- - .rails:rules:code-backstage-qa
+ - .rails:rules:setup-test-env
stage: prepare
variables:
- GITLAB_TEST_EAGER_LOAD: "0"
SETUP_DB: "false"
script:
- run_timed_command "scripts/setup-test-env"
@@ -181,6 +194,7 @@ setup-test-env:
paths:
- config/secrets.yml
- tmp/tests/gitaly/_build/bin/
+ - tmp/tests/gitaly/_build/deps/git/install
- tmp/tests/gitaly/config.toml
- tmp/tests/gitaly/gitaly2.config.toml
- tmp/tests/gitaly/internal/
@@ -223,11 +237,11 @@ update-gitaly-binaries-cache:
.coverage-base:
extends:
- .default-retry
- - .default-before_script
- .coverage-cache
- variables:
- SETUP_DB: "false"
- USE_BUNDLE_INSTALL: "false"
+ before_script:
+ - source scripts/utils.sh
+ - export BUNDLE_WITHOUT="${BUNDLE_WITHOUT}:default:test:puma:kerberos:metrics:omnibus:ed25519"
+ - bundle_install_script
rspec migration pg12:
extends:
@@ -324,26 +338,16 @@ rspec fast_spec_helper minimal:
- .minimal-rspec-tests
- .rails:rules:ee-and-foss-fast_spec_helper:minimal
-db:migrate:reset:
+db:rollback:
extends: .db-job-base
script:
- - bundle exec rake db:migrate:reset
-
-db:check-schema:
- extends:
- - .db-job-base
- - .rails:rules:ee-mr-and-default-branch-only
- script:
- - source scripts/schema_changed.sh
- - scripts/validate_migration_timestamps
+ - bundle exec rake db:migrate VERSION=20181228175414
+ - bundle exec rake db:migrate SKIP_SCHEMA_VERSION_CHECK=true
-db:check-migrations:
- extends:
- - .db-job-base
- - .rails:rules:ee-and-foss-mr-with-migration
+db:migrate:reset:
+ extends: .db-job-base
script:
- - scripts/validate_migration_schema
- allow_failure: true
+ - bundle exec rake db:migrate:reset
db:migrate-from-previous-major-version:
extends: .db-job-base
@@ -352,7 +356,8 @@ db:migrate-from-previous-major-version:
SETUP_DB: "false"
PROJECT_TO_CHECKOUT: "gitlab-foss"
TAG_TO_CHECKOUT: "v13.12.9"
- script:
+ before_script:
+ - !reference [.default-before_script, before_script]
- '[[ -d "ee/" ]] || export PROJECT_TO_CHECKOUT="gitlab"'
- '[[ -d "ee/" ]] || export TAG_TO_CHECKOUT="${TAG_TO_CHECKOUT}-ee"'
- retry 'git fetch https://gitlab.com/gitlab-org/$PROJECT_TO_CHECKOUT.git $TAG_TO_CHECKOUT'
@@ -361,13 +366,28 @@ db:migrate-from-previous-major-version:
- run_timed_command "bundle exec rake db:drop db:create db:structure:load db:migrate db:seed_fu"
- git checkout -f $CI_COMMIT_SHA
- SETUP_DB=false USE_BUNDLE_INSTALL=true bash scripts/prepare_build.sh
+ script:
- run_timed_command "bundle exec rake db:migrate"
-db:rollback:
- extends: .db-job-base
+db:check-schema:
+ extends:
+ - db:migrate-from-previous-major-version
+ - .rails:rules:ee-mr-and-default-branch-only
+ variables:
+ TAG_TO_CHECKOUT: "v14.4.0"
script:
- - bundle exec rake db:migrate VERSION=20181228175414
- - bundle exec rake db:migrate SKIP_SCHEMA_VERSION_CHECK=true
+ - run_timed_command "bundle exec rake db:migrate"
+ - scripts/schema_changed.sh
+ - scripts/validate_migration_timestamps
+
+db:check-migrations:
+ extends:
+ - .db-job-base
+ - .rails:rules:ee-and-foss-mr-with-migration
+ script:
+ - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME:$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --depth 20
+ - scripts/validate_migration_schema
+ allow_failure: true
db:gitlabcom-database-testing:
extends: .rails:rules:db:gitlabcom-database-testing
@@ -457,21 +477,38 @@ rspec:coverage:
# so we use `dependencies` here.
dependencies:
- setup-test-env
+ # FOSS/EE jobs
- rspec migration pg12
- rspec unit pg12
- rspec integration pg12
- rspec system pg12
+ # FOSS/EE minimal jobs
+ - rspec migration pg12 minimal
+ - rspec unit pg12 minimal
+ - rspec integration pg12 minimal
+ - rspec system pg12 minimal
+ # EE jobs
- rspec-ee migration pg12
- rspec-ee unit pg12
- rspec-ee integration pg12
- rspec-ee system pg12
+ # EE minimal jobs
+ - rspec-ee migration pg12 minimal
+ - rspec-ee unit pg12 minimal
+ - rspec-ee integration pg12 minimal
+ - rspec-ee system pg12 minimal
+ # Geo jobs
- rspec-ee unit pg12 geo
- rspec-ee integration pg12 geo
- rspec-ee system pg12 geo
+ # Geo minimal jobs
+ - rspec-ee unit pg12 geo minimal
+ - rspec-ee integration pg12 geo minimal
+ - rspec-ee system pg12 geo minimal
+ # Memory jobs
- memory-static
- memory-on-boot
script:
- - !reference [.minimal-bundle-install, script]
- run_timed_command "bundle exec scripts/merge-simplecov"
- run_timed_command "bundle exec scripts/gather-test-memory-data"
coverage: '/LOC \((\d+\.\d+%)\) covered.$/'
@@ -490,15 +527,67 @@ rspec:feature-flags:
- .coverage-base
- .rails:rules:rspec-feature-flags
stage: post-test
- needs: ["static-analysis"]
+ needs:
+ - job: "feature-flags-usage"
+ - job: "haml-lint foss"
+ - job: "haml-lint ee"
+ optional: true
script:
- - !reference [.minimal-bundle-install, script]
- if [ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]; then
run_timed_command "bundle exec scripts/used-feature-flags" || (scripts/slack master-broken "â˜ ï¸ \`${CI_JOB_NAME}\` failed! â˜ ï¸ See ${CI_JOB_URL}" ci_failing "GitLab Bot" && exit 1);
else
run_timed_command "bundle exec scripts/used-feature-flags";
fi
+rspec:skipped-flaky-tests-report:
+ extends:
+ - .default-retry
+ - .rails:rules:skipped-flaky-tests-report
+ image: ruby:2.7-alpine
+ stage: post-test
+ # We cannot use needs since it would mean needing 84 jobs (since most are parallelized)
+ # so we use `dependencies` here.
+ dependencies:
+ # FOSS/EE jobs
+ - rspec migration pg12
+ - rspec unit pg12
+ - rspec integration pg12
+ - rspec system pg12
+ # FOSS/EE minimal jobs
+ - rspec migration pg12 minimal
+ - rspec unit pg12 minimal
+ - rspec integration pg12 minimal
+ - rspec system pg12 minimal
+ # EE jobs
+ - rspec-ee migration pg12
+ - rspec-ee unit pg12
+ - rspec-ee integration pg12
+ - rspec-ee system pg12
+ # EE minimal jobs
+ - rspec-ee migration pg12 minimal
+ - rspec-ee unit pg12 minimal
+ - rspec-ee integration pg12 minimal
+ - rspec-ee system pg12 minimal
+ # Geo jobs
+ - rspec-ee unit pg12 geo
+ - rspec-ee integration pg12 geo
+ - rspec-ee system pg12 geo
+ # Geo minimal jobs
+ - rspec-ee unit pg12 geo minimal
+ - rspec-ee integration pg12 geo minimal
+ - rspec-ee system pg12 geo minimal
+ variables:
+ SKIPPED_FLAKY_TESTS_REPORT: skipped_flaky_tests_report.txt
+ before_script:
+ - 'echo "SKIP_FLAKY_TESTS_AUTOMATICALLY: $SKIP_FLAKY_TESTS_AUTOMATICALLY"'
+ - mkdir -p rspec_flaky
+ script:
+ - find rspec_flaky/ -type f -name 'skipped_flaky_tests_*_report.txt' -exec cat {} + >> "${SKIPPED_FLAKY_TESTS_REPORT}"
+ artifacts:
+ expire_in: 31d
+ paths:
+ - ${SKIPPED_FLAKY_TESTS_REPORT}
+
# EE/FOSS: default refs (MRs, default branch, schedules) jobs #
#######################################################
@@ -577,6 +666,31 @@ rspec system pg12-as-if-foss decomposed:
- .decomposed-database-rspec
- .rails:rules:decomposed-databases
+rspec migration pg12-as-if-jh:
+ extends:
+ - .rspec-base-pg12-as-if-jh
+ - .rspec-base-migration
+ - .rails:rules:as-if-jh-rspec
+ - .rspec-migration-parallel
+
+rspec unit pg12-as-if-jh:
+ extends:
+ - .rspec-base-pg12-as-if-jh
+ - .rails:rules:as-if-jh-rspec
+ - .rspec-unit-parallel
+
+rspec integration pg12-as-if-jh:
+ extends:
+ - .rspec-base-pg12-as-if-jh
+ - .rails:rules:as-if-jh-rspec
+ - .rspec-integration-parallel
+
+rspec system pg12-as-if-jh:
+ extends:
+ - .rspec-base-pg12-as-if-jh
+ - .rails:rules:as-if-jh-rspec
+ - .rspec-system-parallel
+
rspec-ee migration pg12:
extends:
- .rspec-ee-base-pg12
@@ -684,6 +798,83 @@ rspec-ee system pg12 geo minimal:
- .minimal-rspec-tests
- .rails:rules:ee-only-system:minimal
+rspec-ee migration pg12-as-if-jh:
+ extends:
+ - .rspec-jh-base-pg12
+ - .rspec-base-migration
+ - .rails:rules:as-if-jh-rspec
+ - .rspec-ee-migration-parallel
+
+rspec-ee unit pg12-as-if-jh:
+ extends:
+ - .rspec-jh-base-pg12
+ - .rails:rules:as-if-jh-rspec
+ - .rspec-ee-unit-parallel
+
+rspec-ee integration pg12-as-if-jh:
+ extends:
+ - .rspec-jh-base-pg12
+ - .rails:rules:as-if-jh-rspec
+ - .rspec-ee-integration-parallel
+
+rspec-ee system pg12-as-if-jh:
+ extends:
+ - .rspec-jh-base-pg12
+ - .rails:rules:as-if-jh-rspec
+ - .rspec-ee-system-parallel
+
+rspec-ee unit pg12-as-if-jh geo:
+ extends:
+ - .rspec-jh-base-geo-pg12
+ - .rails:rules:as-if-jh-rspec
+ - .rspec-ee-unit-geo-parallel
+
+rspec-ee integration pg12-as-if-jh geo:
+ extends:
+ - .rspec-jh-base-geo-pg12
+ - .rails:rules:as-if-jh-rspec
+
+rspec-ee system pg12-as-if-jh geo:
+ extends:
+ - .rspec-jh-base-geo-pg12
+ - .rails:rules:as-if-jh-rspec
+
+rspec-jh migration pg12-as-if-jh:
+ extends:
+ - .rspec-jh-base-pg12
+ - .rspec-base-migration
+ - .rails:rules:as-if-jh-rspec
+
+rspec-jh unit pg12-as-if-jh:
+ extends:
+ - .rspec-jh-base-pg12
+ - .rails:rules:as-if-jh-rspec
+
+rspec-jh integration pg12-as-if-jh:
+ extends:
+ - .rspec-jh-base-pg12
+ - .rails:rules:as-if-jh-rspec
+
+rspec-jh system pg12-as-if-jh:
+ extends:
+ - .rspec-jh-base-pg12
+ - .rails:rules:as-if-jh-rspec
+
+rspec-jh unit pg12-as-if-jh geo:
+ extends:
+ - .rspec-jh-base-geo-pg12
+ - .rails:rules:as-if-jh-rspec
+
+rspec-jh integration pg12-as-if-jh geo:
+ extends:
+ - .rspec-jh-base-geo-pg12
+ - .rails:rules:as-if-jh-rspec
+
+rspec-jh system pg12-as-if-jh geo:
+ extends:
+ - .rspec-jh-base-geo-pg12
+ - .rails:rules:as-if-jh-rspec
+
db:rollback geo:
extends:
- db:rollback
@@ -884,5 +1075,24 @@ fail-pipeline-early:
- install_gitlab_gem
script:
- fail_pipeline_early
+
+rspec rspec-pg12-rerun-previous-failed-tests:
+ extends:
+ - .rspec-base-pg12
+ - .rails:rules:rerun-previous-failed-tests
+ stage: test
+ needs: ["setup-test-env", "compile-test-assets", "detect-previous-failed-tests"]
+ script:
+ - !reference [.base-script, script]
+ - rspec_rerun_previous_failed_tests tmp/previous_failed_tests/rspec_failed_files.txt
+
+rspec rspec-ee-pg12-rerun-previous-failed-tests:
+ extends:
+ - "rspec rspec-pg12-rerun-previous-failed-tests"
+ - .rspec-ee-base-pg12
+ script:
+ - !reference [.base-script, script]
+ - rspec_rerun_previous_failed_tests tmp/previous_failed_tests/rspec_ee_failed_files.txt
+
# EE: Canonical MR pipelines
##################################################
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index b581cf83d56..33efc3c4788 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -9,6 +9,7 @@ code_quality:
extends:
- .default-retry
- .use-docker-in-docker
+ stage: lint
artifacts:
paths:
- gl-code-quality-report.json # GitLab-specific
@@ -20,6 +21,7 @@ code_quality:
extends:
- .default-retry
- sast
+ stage: lint
needs: []
artifacts:
paths:
@@ -54,6 +56,7 @@ gosec-sast:
.secret-analyzer:
extends: .default-retry
+ stage: lint
needs: []
artifacts:
paths:
@@ -68,6 +71,7 @@ secret_detection:
extends:
- .default-retry
- dependency_scanning
+ stage: lint
needs: []
variables:
DS_EXCLUDED_PATHS: "qa/qa/ee/fixtures/secure_premade_reports, spec, ee/spec, tmp" # GitLab-specific
@@ -92,6 +96,13 @@ retire-js-dependency_scanning:
gemnasium-python-dependency_scanning:
rules: !reference [".reports:rules:gemnasium-python-dependency_scanning", rules]
+yarn-audit-dependency_scanning:
+ extends: .ds-analyzer
+ image: "registry.gitlab.com/gitlab-org/security-products/analyzers/npm-audit:1.4.0"
+ variables:
+ TOOL: yarn
+ rules: !reference [".reports:rules:yarn-audit-dependency_scanning", rules]
+
# Analyze dependencies for malicious behavior
# See https://gitlab.com/gitlab-com/gl-security/security-research/package-hunter
.package_hunter-base:
@@ -134,6 +145,7 @@ package_hunter-bundler:
license_scanning:
extends: .default-retry
+ stage: lint
needs: []
artifacts:
expire_in: 1 week # GitLab-specific
diff --git a/.gitlab/ci/review-apps/main.gitlab-ci.yml b/.gitlab/ci/review-apps/main.gitlab-ci.yml
index 6fe9e39cb82..670175a6f11 100644
--- a/.gitlab/ci/review-apps/main.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/main.gitlab-ci.yml
@@ -35,10 +35,11 @@ review-build-cng:
extends:
- .default-retry
image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-helm3.5-kubectl1.17
+ resource_group: "review/${CI_COMMIT_REF_NAME}"
variables:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
- GITLAB_HELM_CHART_REF: "v5.2.1"
+ GITLAB_HELM_CHART_REF: "v5.4.1"
environment:
name: review/${CI_COMMIT_REF_SLUG}${FREQUENCY}
url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
@@ -51,7 +52,6 @@ review-deploy:
- .review:rules:review-deploy
stage: deploy
needs: ["review-build-cng"]
- resource_group: "review/${CI_COMMIT_REF_NAME}"
before_script:
- export GITLAB_SHELL_VERSION=$(<GITLAB_SHELL_VERSION)
- export GITALY_VERSION=$(<GITALY_SERVER_VERSION)
@@ -101,6 +101,7 @@ review-stop:
extends:
- .review-stop-base
- .review:rules:review-stop
- stage: post-qa
+ stage: deploy
+ needs: []
script:
- delete_k8s_release_namespace
diff --git a/.gitlab/ci/review-apps/qa.gitlab-ci.yml b/.gitlab/ci/review-apps/qa.gitlab-ci.yml
index 6b9d4feb3c8..07f8bd4e5fd 100644
--- a/.gitlab/ci/review-apps/qa.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/qa.gitlab-ci.yml
@@ -14,6 +14,7 @@
GITLAB_PASSWORD: "${REVIEW_APPS_ROOT_PASSWORD}"
GITLAB_ADMIN_USERNAME: "root"
GITLAB_ADMIN_PASSWORD: "${REVIEW_APPS_ROOT_PASSWORD}"
+ GITLAB_QA_ADMIN_ACCESS_TOKEN: "${REVIEW_APPS_ROOT_TOKEN}"
GITHUB_ACCESS_TOKEN: "${REVIEW_APPS_QA_GITHUB_ACCESS_TOKEN}"
EE_LICENSE: "${REVIEW_APPS_EE_LICENSE}"
SIGNUP_DISABLED: "true"
@@ -31,9 +32,23 @@
expire_in: 7 days
when: always
+.parallel-qa-base:
+ parallel: 5
+ script:
+ - export KNAPSACK_REPORT_PATH=knapsack/master_report.json
+ - export KNAPSACK_TEST_FILE_PATTERN=qa/specs/features/**/*_spec.rb
+ - |
+ bin/test "${QA_SCENARIO}" "${CI_ENVIRONMENT_URL}" \
+ -- \
+ --color --format documentation \
+ --format RspecJunitFormatter --out tmp/rspec.xml
+ artifacts:
+ reports:
+ junit: qa/tmp/rspec.xml
+
.allure-report-base:
image:
- name: ${GITLAB_DEPENDENCY_PROXY}andrcuns/allure-report-publisher:0.3.6
+ name: ${GITLAB_DEPENDENCY_PROXY}andrcuns/allure-report-publisher:0.4.1
entrypoint: [""]
stage: post-qa
variables:
@@ -64,24 +79,23 @@ review-qa-smoke:
script:
- bin/test Test::Instance::Smoke "${CI_ENVIRONMENT_URL}"
+review-qa-reliable:
+ extends:
+ - .review-qa-base
+ - .review:rules:review-qa-reliable
+ - .parallel-qa-base
+ variables:
+ QA_RUN_TYPE: review-qa-reliable
+ QA_SCENARIO: Test::Instance::Reliable
+
review-qa-all:
extends:
- .review-qa-base
- .review:rules:review-qa-all
+ - .parallel-qa-base
variables:
QA_RUN_TYPE: review-qa-all
- parallel: 5
- script:
- - export KNAPSACK_REPORT_PATH=knapsack/master_report.json
- - export KNAPSACK_TEST_FILE_PATTERN=qa/specs/features/**/*_spec.rb
- - |
- bin/test Test::Instance::All "${CI_ENVIRONMENT_URL}" \
- -- \
- --color --format documentation \
- --format RspecJunitFormatter --out tmp/rspec.xml
- artifacts:
- reports:
- junit: qa/tmp/rspec.xml
+ QA_SCENARIO: Test::Instance::All
review-performance:
extends:
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 8ddcf9c2094..cf53e810d01 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -58,6 +58,9 @@
.if-merge-request-labels-run-decomposed: &if-merge-request-labels-run-decomposed
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-decomposed/'
+.if-merge-request-labels-run-review-app: &if-merge-request-labels-run-review-app
+ if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-review-app/'
+
.if-security-merge-request: &if-security-merge-request
if: '$CI_PROJECT_NAMESPACE == "gitlab-org/security" && $CI_MERGE_REQUEST_IID'
@@ -91,9 +94,6 @@
.if-dot-com-ee-nightly-schedule-child-pipeline: &if-dot-com-ee-nightly-schedule-child-pipeline
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/gitlab" && $CI_PIPELINE_SOURCE == "parent_pipeline" && $FREQUENCY == "nightly"'
-.if-cache-credentials-schedule: &if-cache-credentials-schedule
- if: '$CI_REPO_CACHE_CREDENTIALS && $CI_PIPELINE_SOURCE == "schedule"'
-
.if-dot-com-gitlab-org-default-branch: &if-dot-com-gitlab-org-default-branch
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'
@@ -103,6 +103,9 @@
.if-dot-com-gitlab-org-and-security-merge-request: &if-dot-com-gitlab-org-and-security-merge-request
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && $CI_MERGE_REQUEST_IID'
+.if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-qa: &if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-qa
+ if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && $CI_MERGE_REQUEST_IID && $QA_MANUAL_FF_PACKAGE_AND_QA'
+
.if-dot-com-gitlab-org-and-security-tag: &if-dot-com-gitlab-org-and-security-tag
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && $CI_COMMIT_TAG'
@@ -112,6 +115,9 @@
.if-security-pipeline-merge-result: &if-security-pipeline-merge-result
if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH && $CI_PROJECT_NAMESPACE == "gitlab-org/security" && $GITLAB_USER_LOGIN == "gitlab-release-tools-bot"'
+.if-skip-flaky-tests-automatically: &if-skip-flaky-tests-automatically
+ if: '$SKIP_FLAKY_TESTS_AUTOMATICALLY == "true"'
+
####################
# Changes patterns #
####################
@@ -159,11 +165,19 @@
- ".markdownlint.yml"
- "scripts/lint-doc.sh"
+.docs-deprecations-patterns: &docs-deprecations-patterns
+ - "doc/deprecations/index.md"
+ - "data/deprecations/*.yml"
+ - "data/deprecations/templates/_deprecation_template.md.erb"
+ - "lib/tasks/gitlab/docs/compile_deprecations.rake"
+ - "tooling/deprecations/docs.rb"
+
.bundler-patterns: &bundler-patterns
- '{Gemfile.lock,*/Gemfile.lock,*/*/Gemfile.lock}'
.nodejs-patterns: &nodejs-patterns
- '{package.json,*/package.json,*/*/package.json}'
+ - '{yarn.lock,*/yarn.lock,*/*/yarn.lock}'
.python-patterns: &python-patterns
- '{requirements.txt,*/requirements.txt,*/*/requirements.txt}'
@@ -211,6 +225,7 @@
.startup-css-patterns: &startup-css-patterns
- "{,ee/,jh/}app/assets/stylesheets/startup/**/*"
+# Backend patterns + .ci-patterns
.backend-patterns: &backend-patterns
- "{,jh/}Gemfile{,.lock}"
- "Rakefile"
@@ -224,6 +239,7 @@
- ".gitlab/ci/**/*"
- "*_VERSION"
+# DB patterns + .ci-patterns
.db-patterns: &db-patterns
- "{,ee/,jh/}{,spec/}{db,migrations}/**/*"
- "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/database/**/*"
@@ -252,6 +268,11 @@
- "{,ee/,jh/}spec/**/*"
- "{,spec/}tooling/**/*"
+.qa-patterns: &qa-patterns
+ - ".dockerignore"
+ - "qa/**/*"
+
+# Code patterns + .ci-patterns + .workhorse-patterns
.code-patterns: &code-patterns
- "{package.json,yarn.lock}"
- ".browserslistrc"
@@ -260,9 +281,6 @@
- ".csscomb.json"
- "Dockerfile.assets"
- "vendor/assets/**/*"
- # CI changes
- - ".gitlab-ci.yml"
- - ".gitlab/ci/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo}.yml"
- "*_VERSION"
@@ -273,11 +291,11 @@
- "{,ee/,jh/}{app,bin,config,db,generator_templates,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
- "data/whats_new/*.yml"
+ # CI changes
+ - ".gitlab-ci.yml"
+ - ".gitlab/ci/**/*"
-.qa-patterns: &qa-patterns
- - ".dockerignore"
- - "qa/**/*"
-
+# .code-patterns + .backstage-patterns
.code-backstage-patterns: &code-backstage-patterns
- "{package.json,yarn.lock}"
- ".browserslistrc"
@@ -286,9 +304,6 @@
- ".csscomb.json"
- "Dockerfile.assets"
- "vendor/assets/**/*"
- # CI changes
- - ".gitlab-ci.yml"
- - ".gitlab/ci/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo}.yml"
- "*_VERSION"
@@ -299,6 +314,9 @@
- "{,ee/,jh/}{app,bin,config,db,generator_templates,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
- "data/whats_new/*.yml"
+ # CI changes
+ - ".gitlab-ci.yml"
+ - ".gitlab/ci/**/*"
# Backstage changes
- "Dangerfile"
- "danger/**/*"
@@ -307,6 +325,7 @@
- "{,ee/,jh/}spec/**/*"
- "{,spec/}tooling/**/*"
+# .code-patterns + .qa-patterns
.code-qa-patterns: &code-qa-patterns
- "{package.json,yarn.lock}"
- ".browserslistrc"
@@ -315,9 +334,6 @@
- ".csscomb.json"
- "Dockerfile.assets"
- "vendor/assets/**/*"
- # CI changes
- - ".gitlab-ci.yml"
- - ".gitlab/ci/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo}.yml"
- "*_VERSION"
@@ -328,10 +344,14 @@
- "{,ee/,jh/}{app,bin,config,db,generator_templates,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
- "data/whats_new/*.yml"
+ # CI changes
+ - ".gitlab-ci.yml"
+ - ".gitlab/ci/**/*"
# QA changes
- ".dockerignore"
- "qa/**/*"
+# .code-patterns + .backstage-patterns + .qa-patterns
.code-backstage-qa-patterns: &code-backstage-qa-patterns
- "{package.json,yarn.lock}"
- ".browserslistrc"
@@ -340,9 +360,39 @@
- ".csscomb.json"
- "Dockerfile.assets"
- "vendor/assets/**/*"
+ - ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo}.yml"
+ - "*_VERSION"
+ - "{,jh/}Gemfile{,.lock}"
+ - "Rakefile"
+ - "tests.yml"
+ - "config.ru"
+ - "{,ee/,jh/}{app,bin,config,db,generator_templates,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
+ - "doc/api/graphql/reference/*" # Files in this folder are auto-generated
+ - "data/whats_new/*.yml"
# CI changes
- ".gitlab-ci.yml"
- ".gitlab/ci/**/*"
+ # Backstage changes
+ - "Dangerfile"
+ - "danger/**/*"
+ - "{,ee/,jh/}fixtures/**/*"
+ - "{,ee/,jh/}rubocop/**/*"
+ - "{,ee/,jh/}spec/**/*"
+ - "{,spec/}tooling/**/*"
+ # QA changes
+ - ".dockerignore"
+ - "qa/**/*"
+
+# .code-backstage-qa-patterns + .workhorse-patterns
+.setup-test-env-patterns: &setup-test-env-patterns
+ - "{package.json,yarn.lock}"
+ - ".browserslistrc"
+ - "babel.config.js"
+ - "jest.config.{base,integration,unit}.js"
+ - ".csscomb.json"
+ - "Dockerfile.assets"
+ - "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo}.yml"
- "*_VERSION"
@@ -353,6 +403,9 @@
- "{,ee/,jh/}{app,bin,config,db,generator_templates,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
- "data/whats_new/*.yml"
+ # CI changes
+ - ".gitlab-ci.yml"
+ - ".gitlab/ci/**/*"
# Backstage changes
- "Dangerfile"
- "danger/**/*"
@@ -363,9 +416,12 @@
# QA changes
- ".dockerignore"
- "qa/**/*"
+ # Workhorse changes
+ - "GITLAB_WORKHORSE_VERSION"
+ - "workhorse/**/*"
+ - ".gitlab/ci/workhorse.gitlab-ci.yml"
-.code-backstage-danger-patterns: &code-backstage-danger-patterns
- # Backstage changes
+.danger-patterns: &danger-patterns
- "Dangerfile"
- "danger/**/*"
- "tooling/danger/**/*"
@@ -381,6 +437,9 @@
- "config/helpers/**/*.js"
- "vendor/assets/javascripts/**/*"
+.feature-flag-development-config-patterns: &feature-flag-development-config-patterns
+ - "{,ee/}config/feature_flags/{development,ops}/*.yml"
+
################
# Shared rules #
################
@@ -402,6 +461,7 @@
rules:
- <<: *if-not-ee
when: never
+ - <<: *if-merge-request-labels-run-review-app
- <<: *if-dot-com-gitlab-org-and-security-merge-request
changes: *ci-build-images-patterns
- <<: *if-dot-com-gitlab-org-and-security-merge-request
@@ -414,18 +474,11 @@
rules:
- <<: *if-not-canonical-namespace
when: never
+ - <<: *if-merge-request-labels-run-review-app
- <<: *if-auto-deploy-branches
- changes: *ci-build-images-patterns
- changes: *code-qa-patterns
-####################
-# Cache repo rules #
-####################
-.cache-repo:rules:
- rules:
- - <<: *if-cache-credentials-schedule
- allow_failure: true
-
#############
# CNG rules #
#############
@@ -476,6 +529,11 @@
changes: *docs-patterns
when: on_success
+.docs:rules:deprecations:
+ rules:
+ - <<: *if-default-refs
+ changes: *docs-deprecations-patterns
+
##################
# GraphQL rules #
##################
@@ -495,6 +553,7 @@
rules:
- <<: *if-not-canonical-namespace
when: never
+ - <<: *if-merge-request-labels-run-review-app
- <<: *if-auto-deploy-branches
- changes: *code-qa-patterns
@@ -525,8 +584,8 @@
.frontend:rules:default-frontend-jobs:
rules:
- - <<: *if-default-refs
- changes: *code-backstage-patterns
+ - <<: *if-merge-request-labels-run-all-rspec
+ - changes: *code-backstage-patterns
.frontend:rules:default-frontend-jobs-as-if-foss:
rules:
@@ -683,6 +742,9 @@
- <<: *if-not-ee
when: never
- <<: *if-dot-com-gitlab-org-and-security-merge-request
+ changes: *feature-flag-development-config-patterns
+ when: never
+ - <<: *if-dot-com-gitlab-org-and-security-merge-request
changes: *ci-qa-patterns
allow_failure: true
- <<: *if-dot-com-gitlab-org-and-security-merge-request
@@ -695,12 +757,35 @@
- <<: *if-dot-com-gitlab-org-schedule
allow_failure: true
+.qa:rules:package-and-qa:feature-flags:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-qa
+ changes: *feature-flag-development-config-patterns
+ when: manual
+ allow_failure: true
+ - <<: *if-dot-com-gitlab-org-and-security-merge-request
+ changes: *feature-flag-development-config-patterns
+ allow_failure: true
+
+.qa:rules:reliable-reports:schedule:
+ rules:
+ - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "schedule" && $QA_RELIABLE_REPORT == "true"'
+ allow_failure: true
+
###############
# Rails rules #
###############
+.rails:rules:setup-test-env:
+ rules:
+ - changes: *setup-test-env-patterns
+ - <<: *if-merge-request-labels-run-all-rspec
+
.rails:rules:decomposed-databases:
rules:
- <<: *if-merge-request-labels-run-decomposed
+ - <<: *if-default-branch-schedule-nightly
.rails:rules:ee-and-foss-migration:
rules:
@@ -1163,6 +1248,21 @@
- <<: *if-merge-request-labels-as-if-foss
changes: *code-backstage-patterns
+.rails:rules:as-if-jh-rspec:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-jh
+ when: never
+ - <<: *if-security-merge-request
+ changes: *code-backstage-patterns
+ allow_failure: true
+ - <<: *if-merge-request-labels-as-if-jh
+ allow_failure: true
+ - <<: *if-merge-request
+ changes: *ci-patterns
+ allow_failure: true
+
.rails:rules:ee-and-foss-db-library-code:
rules:
- changes: *db-library-patterns
@@ -1180,9 +1280,25 @@
.rails:rules:detect-tests:
rules:
- - changes: *code-backstage-patterns
+ - changes: *code-backstage-qa-patterns
- <<: *if-merge-request-labels-run-all-rspec
+.rails:rules:detect-previous-failed-tests:
+ rules:
+ - <<: *if-security-merge-request
+ when: never
+ - <<: *if-merge-request-labels-run-all-rspec
+ - <<: *if-merge-request
+ changes: *code-backstage-patterns
+
+.rails:rules:rerun-previous-failed-tests:
+ rules:
+ - <<: *if-security-merge-request
+ when: never
+ - <<: *if-merge-request-labels-run-all-rspec
+ - <<: *if-merge-request
+ changes: *code-backstage-patterns
+
.rails:rules:rspec-foss-impact:
rules:
- <<: *if-not-ee
@@ -1252,6 +1368,14 @@
when: never
- changes: *code-backstage-patterns
+.rails:rules:skipped-flaky-tests-report:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-skip-flaky-tests-automatically
+ changes: *code-backstage-patterns
+ - changes: *ci-patterns
+
#########################
# Static analysis rules #
#########################
@@ -1260,6 +1384,12 @@
rules:
- changes: *code-backstage-qa-patterns
+.static-analysis:rules:ee:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - changes: *code-backstage-qa-patterns
+
.static-analysis:rules:as-if-foss:
rules:
- <<: *if-not-ee
@@ -1370,6 +1500,12 @@
when: never
- changes: *python-patterns
+.reports:rules:yarn-audit-dependency_scanning:
+ rules:
+ - if: '$DEPENDENCY_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\bdependency_scanning\b/'
+ when: never
+ - changes: *nodejs-patterns
+
.reports:rules:schedule-dast:
rules:
- if: '$DAST_DISABLED || $GITLAB_FEATURES !~ /\bdast\b/'
@@ -1405,6 +1541,7 @@
rules:
- <<: *if-not-ee
when: never
+ - <<: *if-merge-request-labels-run-review-app
- <<: *if-dot-com-gitlab-org-merge-request
changes: *ci-review-patterns
- <<: *if-dot-com-gitlab-org-merge-request
@@ -1415,13 +1552,13 @@
allow_failure: true
- <<: *if-dot-com-gitlab-org-merge-request
changes: *qa-patterns
- allow_failure: true
- <<: *if-dot-com-gitlab-org-schedule
.review:rules:review-build-cng:
rules:
- <<: *if-not-ee
when: never
+ - <<: *if-merge-request-labels-run-review-app
- <<: *if-dot-com-gitlab-org-merge-request
changes: *ci-review-patterns
- <<: *if-dot-com-gitlab-org-merge-request
@@ -1431,24 +1568,22 @@
allow_failure: true
- <<: *if-dot-com-gitlab-org-merge-request
changes: *qa-patterns
- allow_failure: true
- <<: *if-dot-com-gitlab-org-schedule-child-pipeline
.review:rules:review-deploy:
rules:
- <<: *if-not-ee
when: never
+ - <<: *if-merge-request-labels-run-review-app
- <<: *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-patterns
allow_failure: true
- <<: *if-dot-com-gitlab-org-merge-request
changes: *qa-patterns
- allow_failure: true
- <<: *if-dot-com-gitlab-org-schedule-child-pipeline
allow_failure: true
@@ -1458,6 +1593,7 @@
when: never
- <<: *if-not-ee
when: never
+ - <<: *if-merge-request-labels-run-review-app
- <<: *if-dot-com-gitlab-org-merge-request
changes: *ci-review-patterns
- <<: *if-dot-com-gitlab-org-merge-request
@@ -1473,6 +1609,7 @@
rules:
- <<: *if-not-ee
when: never
+ - <<: *if-merge-request-labels-run-review-app
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-qa-patterns
@@ -1480,24 +1617,32 @@
rules:
- <<: *if-not-ee
when: never
+ - <<: *if-merge-request-labels-run-review-app
- <<: *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
+ changes: *qa-patterns
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *code-patterns
allow_failure: true
- <<: *if-dot-com-ee-schedule-child-pipeline
allow_failure: true
# The rule needs to be duplicated between `on_success` and `on_failure`
# because the jobs `needs` the previous job to complete.
+# With `when: always`, and the `review-qa-*` jobs are manual, the `allure-report-qa-*` jobs
+# would start running before the qa jobs have started.
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63844#note_599012559
.review:rules:review-qa-smoke-report:
rules:
- <<: *if-not-ee
when: never
+ - <<: *if-merge-request-labels-run-review-app
+ when: on_success
+ - <<: *if-merge-request-labels-run-review-app
+ when: on_failure
- <<: *if-dot-com-gitlab-org-merge-request
changes: *ci-review-patterns
when: on_success
@@ -1521,10 +1666,16 @@
- <<: *if-dot-com-ee-schedule-child-pipeline
when: on_failure
+.review:rules:review-qa-reliable:
+ rules:
+ - when: on_success
+ allow_failure: true
+
.review:rules:review-qa-all:
rules:
- <<: *if-not-ee
when: never
+ - <<: *if-merge-request-labels-run-review-app
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-patterns
when: manual
@@ -1537,11 +1688,17 @@
# The rule needs to be duplicated between `on_success` and `on_failure`
# because the jobs `needs` the previous job to complete.
+# With `when: always`, and the `review-qa-*` jobs are manual, the `allure-report-qa-*` jobs
+# would start running before the qa jobs have started.
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63844#note_599012559
.review:rules:review-qa-all-report:
rules:
- <<: *if-not-ee
when: never
+ - <<: *if-merge-request-labels-run-review-app
+ when: on_success
+ - <<: *if-merge-request-labels-run-review-app
+ when: on_failure
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-patterns
when: manual
@@ -1569,13 +1726,16 @@
changes: *code-qa-patterns
when: manual
allow_failure: true
- - <<: *if-dot-com-gitlab-org-schedule-child-pipeline
+ - <<: *if-dot-com-gitlab-org-schedule
allow_failure: true
.review:rules:review-stop:
rules:
- <<: *if-not-ee
when: never
+ - <<: *if-merge-request-labels-run-review-app
+ when: manual
+ allow_failure: true
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-qa-patterns
when: manual
@@ -1588,7 +1748,7 @@
.review:rules:danger-local:
rules:
- if: '$CI_MERGE_REQUEST_IID'
- changes: *code-backstage-danger-patterns
+ changes: *danger-patterns
###############
# Setup rules #
@@ -1616,7 +1776,7 @@
changes: *code-backstage-patterns
when: on_success
-.setup:rules:no_ee_check:
+.setup:rules:no-ee-check:
rules:
- <<: *if-not-foss
when: never
@@ -1624,6 +1784,14 @@
changes: *code-backstage-patterns
when: on_success
+.setup:rules:no-jh-check:
+ rules:
+ - <<: *if-jh
+ when: never
+ - <<: *if-default-refs
+ changes: *code-backstage-patterns
+ when: on_success
+
.setup:rules:verify-tests-yml:
rules:
- <<: *if-not-ee
diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml
index eb7a5afad3d..4c674f38939 100644
--- a/.gitlab/ci/setup.gitlab-ci.yml
+++ b/.gitlab/ci/setup.gitlab-ci.yml
@@ -41,13 +41,21 @@ gitlab_git_test:
script:
- spec/support/prepare-gitlab-git-test-for-commit --check-for-changes
-no_ee_check:
+no-ee-check:
extends:
- .minimal-job
- - .setup:rules:no_ee_check
+ - .setup:rules:no-ee-check
stage: test
script:
- - scripts/no-ee-check
+ - scripts/no-dir-check ee
+
+no-jh-check:
+ extends:
+ - .minimal-job
+ - .setup:rules:no-jh-check
+ stage: test
+ script:
+ - scripts/no-dir-check jh
verify-tests-yml:
extends:
@@ -102,6 +110,23 @@ detect-tests as-if-foss:
before_script:
- '[ "$FOSS_ONLY" = "1" ] && rm -rf ee/ qa/spec/ee/ qa/qa/specs/features/ee/ qa/qa/ee/ qa/qa/ee.rb'
+detect-previous-failed-tests:
+ extends:
+ - .detect-test-base
+ - .rails:rules:detect-previous-failed-tests
+ variables:
+ PREVIOUS_FAILED_TESTS_DIR: tmp/previous_failed_tests/
+ RSPEC_PG_REGEX: /rspec .+ pg12( .+)?/
+ RSPEC_EE_PG_REGEX: /rspec-ee .+ pg12( .+)?/
+ script:
+ - source ./scripts/utils.sh
+ - source ./scripts/rspec_helpers.sh
+ - retrieve_previous_failed_tests ${PREVIOUS_FAILED_TESTS_DIR} "${RSPEC_PG_REGEX}" "${RSPEC_EE_PG_REGEX}"
+ artifacts:
+ expire_in: 7d
+ paths:
+ - ${PREVIOUS_FAILED_TESTS_DIR}
+
add-jh-folder:
extends: .setup:rules:add-jh-folder
image: ${GITLAB_DEPENDENCY_PROXY}alpine:edge
@@ -112,6 +137,7 @@ add-jh-folder:
- curl --location -o "jh-folder.tar.gz" "https://gitlab.com/gitlab-jh/gitlab/-/archive/main-jh/gitlab-main-jh.tar.gz?path=jh"
- tar -xf "jh-folder.tar.gz"
- mv gitlab-main-jh-jh/jh/ ./
+ - cp Gemfile.lock jh/
- ls -l jh/
artifacts:
expire_in: 2d
diff --git a/.gitlab/ci/static-analysis.gitlab-ci.yml b/.gitlab/ci/static-analysis.gitlab-ci.yml
index 85df68e9030..ebd223c4171 100644
--- a/.gitlab/ci/static-analysis.gitlab-ci.yml
+++ b/.gitlab/ci/static-analysis.gitlab-ci.yml
@@ -2,7 +2,7 @@
extends:
- .default-retry
- .default-before_script
- - .static-analysis-cache
+ stage: lint
needs: []
variables:
SETUP_DB: "false"
@@ -14,7 +14,7 @@
update-static-analysis-cache:
extends:
- .static-analysis-base
- - .static-analysis-cache-push
+ - .rubocop-job-cache-push
- .shared:rules:update-cache
stage: prepare
script:
@@ -23,31 +23,95 @@ update-static-analysis-cache:
static-analysis:
extends:
- .static-analysis-base
+ - .static-analysis-cache
- .static-analysis:rules:ee-and-foss
- stage: test
- parallel: 4
+ parallel: 2
script:
- run_timed_command "retry yarn install --frozen-lockfile"
- scripts/static-analysis
- artifacts:
- expire_in: 31d
- when: always
- paths:
- - tmp/feature_flags/
-static-analysis-with-database:
+static-analysis as-if-foss:
+ extends:
+ - static-analysis
+ - .static-analysis:rules:as-if-foss
+ - .as-if-foss
+
+static-verification-with-database:
extends:
- .static-analysis-base
+ - .rubocop-job-cache
- .static-analysis:rules:ee-and-foss
- .use-pg12
- stage: test
script:
- bundle exec rake lint:static_verification_with_database
variables:
SETUP_DB: "true"
-static-analysis as-if-foss:
+eslint:
extends:
- - static-analysis
- - .static-analysis:rules:as-if-foss
+ - .static-analysis-base
+ - .yarn-cache
+ - .static-analysis:rules:ee
+ needs: []
+ variables:
+ USE_BUNDLE_INSTALL: "false"
+ script:
+ - run_timed_command "retry yarn install --frozen-lockfile"
+ - run_timed_command "yarn run lint:eslint:all"
+
+eslint as-if-foss:
+ extends:
+ - eslint
+ - .frontend:rules:eslint-as-if-foss
- .as-if-foss
+
+haml-lint foss:
+ extends:
+ - .static-analysis-base
+ - .ruby-cache
+ - .static-analysis:rules:ee-and-foss
+ script:
+ - run_timed_command "bin/rake 'haml_lint[app/views]'"
+ artifacts:
+ expire_in: 31d
+ when: always
+ paths:
+ - tmp/feature_flags/
+
+haml-lint ee:
+ extends:
+ - "haml-lint foss"
+ - .static-analysis:rules:ee
+ script:
+ - run_timed_command "bin/rake 'haml_lint[ee/app/views]'"
+
+rubocop:
+ extends:
+ - .static-analysis-base
+ - .rubocop-job-cache
+ - .static-analysis:rules:ee-and-foss
+ script:
+ - run_timed_command "bundle exec rubocop --parallel"
+
+qa:testcases:
+ extends:
+ - .static-analysis-base
+ - .rubocop-job-cache
+ - .static-analysis:rules:ee-and-foss
+ script:
+ - run_timed_command "bundle exec rubocop qa/qa/specs/features/**/* --only QA/DuplicateTestcaseLink"
+
+feature-flags-usage:
+ extends:
+ - .static-analysis-base
+ - .rubocop-job-cache
+ - .static-analysis:rules:ee-and-foss
+ script:
+ # We need to disable the cache for this cop since it creates files under tmp/feature_flags/*.used,
+ # the cache would prevent these files from being created.
+ - run_timed_command "bundle exec rubocop --only Gitlab/MarkUsedFeatureFlags --cache false"
+ artifacts:
+ expire_in: 31d
+ when: always
+ paths:
+ - tmp/feature_flags/
diff --git a/.gitlab/ci/workhorse.gitlab-ci.yml b/.gitlab/ci/workhorse.gitlab-ci.yml
index 0da0a334699..47b5d29ab8e 100644
--- a/.gitlab/ci/workhorse.gitlab-ci.yml
+++ b/.gitlab/ci/workhorse.gitlab-ci.yml
@@ -9,24 +9,21 @@ workhorse:verify:
.workhorse:test:
extends: .workhorse:rules:workhorse
- services:
- - name: registry.gitlab.com/gitlab-org/build/cng/gitaly:latest
- # Disable the hooks so we don't have to stub the GitLab API
- command: ["/usr/bin/env", "GITALY_TESTING_NO_GIT_HOOKS=1", "/scripts/process-wrapper"]
- alias: gitaly
variables:
- GITALY_ADDRESS: "tcp://gitaly:8075"
+ GITALY_ADDRESS: "tcp://127.0.0.1:8075"
stage: test
- needs: []
+ needs:
+ - setup-test-env
script:
- go version
- apt-get update && apt-get -y install libimage-exiftool-perl
+ - scripts/gitaly-test-build
- make -C workhorse test
workhorse:test using go 1.16:
extends: .workhorse:test
- image: ${GITLAB_DEPENDENCY_PROXY}golang:1.16
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7-golang-1.16-git-2.31
workhorse:test using go 1.17:
extends: .workhorse:test
- image: ${GITLAB_DEPENDENCY_PROXY}golang:1.17
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7-golang-1.17-git-2.31
diff --git a/.gitlab/ci/yaml.gitlab-ci.yml b/.gitlab/ci/yaml.gitlab-ci.yml
index b25ad55e0ce..590593b9d75 100644
--- a/.gitlab/ci/yaml.gitlab-ci.yml
+++ b/.gitlab/ci/yaml.gitlab-ci.yml
@@ -5,7 +5,7 @@ lint-yaml:
- .default-retry
- .yaml-lint:rules
image: pipelinecomponents/yamllint:latest
- stage: test
+ stage: lint
needs: []
variables:
LINT_PATHS: .gitlab-ci.yml .gitlab/ci lib/gitlab/ci/templates
diff --git a/.gitlab/issue_templates/Audit Event Proposal.md b/.gitlab/issue_templates/Audit Event Proposal.md
index 7a5408ca1f2..af32845bd9a 100644
--- a/.gitlab/issue_templates/Audit Event Proposal.md
+++ b/.gitlab/issue_templates/Audit Event Proposal.md
@@ -9,5 +9,5 @@
<!-- Describe the audit event you are proposing should be added, including any details of what should be captured, how, and why. -->
/label ~"Category:Audit Events"
-/label ~"feature"
+/label ~"type::feature"
/label ~"group::compliance"
diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md
index 41b694fdf2c..b9fed3745d1 100644
--- a/.gitlab/issue_templates/Bug.md
+++ b/.gitlab/issue_templates/Bug.md
@@ -2,10 +2,10 @@
Please read this!
Before opening a new issue, make sure to search for keywords in the issues
-filtered by the "regression" or "bug" label:
+filtered by the "regression" or "type::bug" label:
- https://gitlab.com/gitlab-org/gitlab/issues?label_name%5B%5D=regression
-- https://gitlab.com/gitlab-org/gitlab/issues?label_name%5B%5D=bug
+- https://gitlab.com/gitlab-org/gitlab/issues?label_name%5B%5D=type::bug
and verify the issue you're about to submit isn't a duplicate.
--->
@@ -82,4 +82,4 @@ will also determine whether the bug is fixed in a more recent version. -->
<!-- If you can, link to the line of code that might be responsible for the problem. -->
-/label ~bug
+/label ~"type::bug"
diff --git a/.gitlab/issue_templates/Deprecations.md b/.gitlab/issue_templates/Deprecations.md
index ff51699c6be..caef5c64334 100644
--- a/.gitlab/issue_templates/Deprecations.md
+++ b/.gitlab/issue_templates/Deprecations.md
@@ -41,7 +41,11 @@ Which tier is this feature available in?
### Deprecation Milestone
-<!-- In which milestone will this deprecation happen? -->
+<!-- In which milestone will this deprecation be announced ? -->
+
+### Planned Removal Milestone
+
+<!-- In which milestone will the feature or functionality be removed and announced? -->
### Links
diff --git a/.gitlab/issue_templates/Empty state.md b/.gitlab/issue_templates/Empty state.md
new file mode 100644
index 00000000000..d92ea8522e1
--- /dev/null
+++ b/.gitlab/issue_templates/Empty state.md
@@ -0,0 +1,80 @@
+<!-- Before implementing a new empty state solution, make sure to read the
+Empty State region docs in Pajamas: https://design.gitlab.com/regions/empty-states -->
+
+## Description
+
+<!-- Describe the solution you're proposing for your empty state region.
+Include links to user research (if applicable). -->
+
+## Location
+
+<!-- Provide a link and location of the new empty state solution.
+For example: https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/issues -->
+
+## Use case
+
+<!-- What is the use case for the solution you're proposing?
+Read the Empty State docs and select the use case below: https://design.gitlab.com/regions/empty-states -->
+
+- [ ] Blank content
+- [ ] Empty search results
+- [ ] Configuration required
+- [ ] Higher tier
+
+## Checklist
+
+<!-- Follow the steps below that correspond with the use case selected above.
+Follow the steps to complete this issue -->
+
+### Blank content
+
+- [ ] The solution follows the `Blank content` specifications [in Pajamas](https://design.gitlab.com/regions/empty-states#blank-content).
+- [ ] Follow the instructions from the [`After merge` section](#after-merge) below to add Snowplow tracking.
+
+### Empty search results
+
+- [ ] The solution follows the `Empty search results` specifications [in Pajamas](https://design.gitlab.com/regions/empty-states#empty-search-results).
+- [ ] Follow the instructions from the [`After merge` section](#after-merge) below to add Snowplow tracking.
+
+### Configuration required
+
+- [ ] The solution follows the `Configuration required` specifications [in Pajamas](https://design.gitlab.com/regions/empty-states#configuration-required).
+- [ ] Ask a [Growth product manager or Designer](https://about.gitlab.com/handbook/engineering/development/growth/#stable-counterparts) to review your solution.
+- [ ] Is your solution introducing a new empty states or modifying an existing one?
+ - [ ] Introducing a new empty state: Follow the instructions from the [`After merge` section](#after-merge) below to add Snowplow tracking.
+ - [ ] Modifying an existing empty state: Follow the [`Experimentation` process](#experimentation) below. _Note_: If the empty state you want to replace hasn't been updated in a long time, doesn't pitch the value of the feature, or does not contain a next step action CTA, then we recommend you skip the experimentation process to implement and add tracking to your new empty state.
+
+<!-- IF experimentation -->
+#### Experimentation
+
+- [ ] Collaborate with a [Growth product manager](https://about.gitlab.com/handbook/engineering/development/growth/#stable-counterparts) to help you determine if you can validate your solution through an experiment on SaaS.
+- [ ] If an experiment is possible, create an issue using the [experiment idea template](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Experiment%20Idea) and follow the template intructions. Otherwise, follow the instructions from the [`After merge` section](#after-merge) below to add Snowplow tracking.
+- [ ] Ask a [Growth product manager or Designer](https://about.gitlab.com/handbook/engineering/development/growth/#stable-counterparts) to review your experiment set-up.
+- [ ] Implement and monitor the experiment following the [implementation guide](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/experiment_guide/gitlab_experiment.md#implement-an-experiment).
+- [ ] Review and discuss the findings.
+- [ ] Add the findings to the [Growth experimentation knowledge](https://about.gitlab.com/direction/growth/#growth-experiments-knowledge-base---concluded-experiments).
+
+### Higher tier
+
+- [ ] The solution follows the `Higher tier` specifications [in Pajamas](https://design.gitlab.com/regions/empty-states#higher-tier).
+- [ ] Ask a Product Manager or Designer from the [Conversion group](https://about.gitlab.com/handbook/engineering/development/growth/conversion/#group-members) to review your solution.
+- [ ] Is your solution introducing a new empty states or modifying an existing one?
+ - [ ] Introducing a new empty state: follow the instructions from the [`After merge` section](#after-merge) below to add Snowplow tracking.
+ - [ ] Modifying an existing empty state, follow the [`Experimentation` process](#experimentation) below.
+
+<!-- IF experimentation -->
+#### Experimentation
+
+- [ ] Collaborate with a [Growth product manager](https://about.gitlab.com/handbook/engineering/development/growth/#stable-counterparts) to help you determine if you can validate your solution through an experiment on SaaS.
+- [ ] If an experiment is possible, create an issue using the [experiment idea template](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Experiment%20Idea) and follow the template intructions. Otherwise, follow the instructions from the [`After merge` section](#after-merge) below to add Snowplow tracking.
+- [ ] Add a ~"Category:Conversion Experiment" label to the experiment idea issue.
+- [ ] Ask a Product Manager or Designer from the [Conversion group](https://about.gitlab.com/handbook/engineering/development/growth/conversion/#group-members) to review your experiment set-up.
+- [ ] Implement and monitor the experiment following the [implementation guide](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/experiment_guide/gitlab_experiment.md#implement-an-experiment) .
+- [ ] Review and discuss the findings.
+- [ ] Add the findings to the [Growth experimentation knowledge](https://about.gitlab.com/direction/growth/#growth-experiments-knowledge-base---concluded-experiments).
+
+
+## After merge
+
+- [ ] Use the `Snowplow event tracking` [issue template](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Snowplow%20event%20tracking) and open an issue to add Snowplow event tracking to your new empty state solution.
+ - [ ] Add your ~devops:: and ~group:: labels to the new issue.
diff --git a/.gitlab/issue_templates/Experiment Implementation.md b/.gitlab/issue_templates/Experiment Implementation.md
new file mode 100644
index 00000000000..b3883f08c25
--- /dev/null
+++ b/.gitlab/issue_templates/Experiment Implementation.md
@@ -0,0 +1,25 @@
+<!-- Title suggestion: Experiment Implementation: [description] -->
+
+# Experiment Summary
+<!-- Quick rundown of what is being done -->
+
+# Design
+<!-- This should include the contexts that determine the reproducibility (stickiness) of an experiment. This means that if you want the same behavior for a user, the context would be user, or if you want all users when viewing a specific project, the context would be the project being viewed, etc. -->
+
+# Rollout strategy
+<!-- This is currently called A/B test, which isn't accurate for multi-variants. Let's call this rollout strategy. It should outline the percentages for variants and if there's more than one step to this, each of those steps and the timing for those steps (e.g. 30 days after initial rollout). -->
+
+# Inclusions and exclusions
+<!-- These would be the rules for which given context (and are limited to context or resolvable at experiment time details) is included or excluded from the test. An example of this would be to only run an experiment on groups less than N number of days old. -->
+
+# Segmentation
+<!-- Rules for always saying context with these criteria always get this variant. For instance, if you want to always give groups less than N number of days old the experiment experience, they are specified here. This is different from the exclusion rules above. -->
+
+# Tracking Details
+
+- [json schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/0-3-0) used in `gitlab-experiment` tracking.
+- see [taxonomy](https://docs.gitlab.com/ee/development/snowplow/index.html#structured-event-taxonomy) for a guide.
+
+| activity | category | action | label | context | property | value |
+| -------- | -------- | ------ | ----- | ------- | -------- | ----- |
+| | | | | json schema | | |
diff --git a/.gitlab/issue_templates/Experiment Rollout.md b/.gitlab/issue_templates/Experiment Rollout.md
index c5fdc739943..9209423ba33 100644
--- a/.gitlab/issue_templates/Experiment Rollout.md
+++ b/.gitlab/issue_templates/Experiment Rollout.md
@@ -105,5 +105,16 @@ In this rollout issue, ensure the scoped `experiment::` label is kept accurate.
/chatops run feature set <experiment-key> false
```
+## Experiment Successful Cleanup Concerns
+
+_Items to be considered if candidate experience is to become a permanent part of GitLab_
+
+<!--
+Add a list of items raised during MR review or otherwise that may need further thought/consideration
+before becoming permanent parts of the product.
+
+Example: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70451#note_727246104
+-->
+
/label ~"feature flag" ~"devops::growth" ~"growth experiment" ~"experiment-rollout" ~Engineering ~"workflow::scheduling" ~"experiment::pending"
/milestone %"Next 1-3 releases"
diff --git a/.gitlab/issue_templates/Experiment Successful Cleanup.md b/.gitlab/issue_templates/Experiment Successful Cleanup.md
index 42f26342342..1dd57332b8e 100644
--- a/.gitlab/issue_templates/Experiment Successful Cleanup.md
+++ b/.gitlab/issue_templates/Experiment Successful Cleanup.md
@@ -12,9 +12,10 @@ The changes need to become an official part of the product.
- [ ] Determine if tracking should be kept as is, removed, or modified.
- [ ] Ensure any relevant documentation has been updated.
- [ ] Consider changes to any `feature_category:` introduced by the experiment if ownership is changing (PM for Growth and PM for the new category as DRIs)
+- [ ] Check to see if the experiment introduced new design assets. Add them to the appropriate repos and document them if needed.
- [ ] Optional: Migrate experiment to a default enabled [feature flag](https://docs.gitlab.com/ee/development/feature_flags) for one milestone and add a changelog. Converting to a feature flag can be skipped at the ICs discretion if risk is deemed low with consideration to both SaaS and (if applicable) self managed
- [ ] In the next milestone, [remove the feature flag](https://docs.gitlab.com/ee/development/feature_flags/controls.html#cleaning-up) if applicable
- [ ] After the flag removal is deployed, [clean up the feature/experiment feature flags](https://docs.gitlab.com/ee/development/feature_flags/controls.html#cleaning-up) by running chatops command in `#production` channel
-- [ ] Ensure the corresponding [Experiment Tracking](https://gitlab.com/groups/gitlab-org/-/boards/1352542?label_name[]=devops%3A%3Agrowth&label_name[]=growth%20experiment&label_name[]=experiment%20tracking) issue is updated
+- [ ] Ensure the corresponding [Experiment Rollout](https://gitlab.com/groups/gitlab-org/-/boards/1352542?label_name[]=devops%3A%3Agrowth&label_name[]=growth%20experiment&label_name[]=experiment-rollout) issue is updated
-/label ~"feature" ~"feature::maintenance" ~"workflow::scheduling" ~"growth experiment" ~"feature flag"
+/label ~"type::maintenance" ~"workflow::scheduling" ~"growth experiment" ~"feature flag"
diff --git a/.gitlab/issue_templates/Experimentation.md b/.gitlab/issue_templates/Experimentation.md
deleted file mode 100644
index ba7839fb941..00000000000
--- a/.gitlab/issue_templates/Experimentation.md
+++ /dev/null
@@ -1,25 +0,0 @@
-<!-- Title suggestion: Experiment: [description] -->
-
-# Experiment Summary
-<!-- Quick rundown of what is being done -->
-
-# Design
-<!-- This should include the contexts that determine the reproducibility (stickiness) of an experiment. This means that if you want the same behavior for a user, the context would be user, or if you want all users when viewing a specific project, the context would be the project being viewed, etc. -->
-
-# Rollout strategy
-<!-- This is currently called A/B test, which isn't accurate for multi-variants. Let's call this rollout strategy. It should outline the percentages for variants and if there's more than one step to this, each of those steps and the timing for those steps (e.g. 30 days after initial rollout). -->
-
-# Inclusions and exclusions
-<!-- These would be the rules for which given context (and are limited to context or resolvable at experiment time details) is included or excluded from the test. An example of this would be to only run an experiment on groups less than N number of days old. -->
-
-# Segmentation
-<!-- Rules for always saying context with these criteria always get this variant. For instance, if you want to always give groups less than N number of days old the experiment experience, they are specified here. This is different from the exclusion rules above. -->
-
-# Tracking Details
-
-- [json schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/0-3-0) used in `gitlab-experiment` tracking.
-- see [taxonomy](https://docs.gitlab.com/ee/development/snowplow/index.html#structured-event-taxonomy) for a guide.
-
-| activity | category | action | label | context | property | value |
-| -------- | -------- | ------ | ----- | ------- | -------- | ----- |
-| | | | | json schema | | |
diff --git a/.gitlab/issue_templates/Feature Flag Roll Out.md b/.gitlab/issue_templates/Feature Flag Roll Out.md
index 00b396bac4e..bc1a23729e2 100644
--- a/.gitlab/issue_templates/Feature Flag Roll Out.md
+++ b/.gitlab/issue_templates/Feature Flag Roll Out.md
@@ -30,6 +30,17 @@ Are there any other stages or teams involved that need to be kept in the loop?
<!-- Describe the expected outcome when rolling out this feature -->
+### When is the feature viable?
+
+<!-- What are the settings we need to configure in order to have this feature viable? -->
+
+<!--
+Example below:
+
+1. Enable service ping collection
+ `ApplicationSetting.first.update(usage_ping_enabled: true)`
+-->
+
### What might happen if this goes wrong?
<!-- Should the feature flag be turned off? Any MRs that need to be rolled back? Communication that needs to happen? What are some things you can think of that could go wrong - data loss or broken pages? -->
@@ -37,6 +48,12 @@ Are there any other stages or teams involved that need to be kept in the loop?
### What can we monitor to detect problems with this?
<!-- Which dashboards from https://dashboards.gitlab.net are most relevant? -->
+_Consider mentioning checks for 5xx errors or other anomalies like an increase in redirects
+(302 HTTP response status)_
+
+### What can we check for monitoring production after rollouts?
+
+_Consider adding links to check for Sentry errors, Production logs for 5xx, 302s, etc._
## Rollout Steps
@@ -73,11 +90,14 @@ Are there any other stages or teams involved that need to be kept in the loop?
If a different developer will be covering, or an exception is needed, please inform the oncall SRE by using the `@sre-oncall` Slack alias.
- [ ] Ensure that documentation has been updated ([More info](https://docs.gitlab.com/ee/development/documentation/feature_flags.html#features-that-became-enabled-by-default)).
- [ ] Announce on [the feature issue](ISSUE LINK) an estimated time this will be enabled on GitLab.com.
-- [ ] If the feature might impact the user experience, notify `#support_gitlab-com` and your team channel ([more guidance when this is necessary in the dev docs](https://docs.gitlab.com/ee/development/feature_flags/controls.html#communicate-the-change)).
+- [ ] Notify `#support_gitlab-com` and your team channel ([more guidance when this is necessary in the dev docs](https://docs.gitlab.com/ee/development/feature_flags/controls.html#communicate-the-change)).
### Global rollout on production
-All `/chatops` commands that target production should be done in the `#production` slack channel for visibility.
+For visibility, all `/chatops` commands that target production should be:
+
+- Executed in the `#production` slack channel.
+- Cross-posted (with the command results) to the responsible team's slack channel (`#g_TEAM_NAME`).
- [ ] [Incrementally roll out](https://docs.gitlab.com/ee/development/feature_flags/controls.html#process) the feature.
- If the feature flag in code has [an actor](https://docs.gitlab.com/ee/development/feature_flags/#feature-actors), perform **actor-based** rollout.
@@ -148,5 +168,5 @@ codebase.
/chatops run feature set <feature-flag-name> false
```
-/label ~"feature flag"
+/label ~"feature flag" ~"type::feature" ~"feature::addition"
/assign DRI
diff --git a/.gitlab/issue_templates/Feature Proposal - basic.md b/.gitlab/issue_templates/Feature Proposal - basic.md
index 0c05b7a0165..980751621f0 100644
--- a/.gitlab/issue_templates/Feature Proposal - basic.md
+++ b/.gitlab/issue_templates/Feature Proposal - basic.md
@@ -1,10 +1,16 @@
<!-- This template is a great use for issues that are feature::additions or technical tasks for larger issues.-->
-### Proposal
+### Proposal
<!-- Use this section to explain the feature and how it will work. It can be helpful to add technical details, design proposals, and links to related epics or issues. -->
<!-- Consider adding related issues and epics to this issue. You can also reference the Feature Proposal Template (https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal%20-%20detailed.md) for additional details to consider adding to this issue. Additionally, as a data oriented organization, when your feature exits planning breakdown, consider adding the `What does success look like, and how can we measure that?` section.
-->
-/label ~feature::addition ~"group::" ~"section::" ~"Category:" ~"GitLab Core"/~"GitLab Premium"/~"GitLab Ultimate"
+<!-- Label reminders
+Use the following resources to find the appropriate labels:
+- https://gitlab.com/gitlab-org/gitlab/-/labels
+- https://about.gitlab.com/handbook/product/categories/features/
+-->
+
+/label ~"type::feature" ~feature::addition ~"group::" ~"section::" ~"Category:" ~"GitLab Core"/~"GitLab Premium"/~"GitLab Ultimate"
diff --git a/.gitlab/issue_templates/Feature Proposal - lean.md b/.gitlab/issue_templates/Feature Proposal - lean.md
index 9dd4bdc6b22..504bfbb03d8 100644
--- a/.gitlab/issue_templates/Feature Proposal - lean.md
+++ b/.gitlab/issue_templates/Feature Proposal - lean.md
@@ -1,33 +1,22 @@
-<!-- This issue template can be used a great starting point for feature requests. The last section "Release notes" can be used as a summary of the feature and is also required if you want to have your release post blog MR auto generated using the release post item generator: https://about.gitlab.com/handbook/marketing/blog/release-posts/#release-post-item-generator. The remaining sections are the backbone for every feature in GitLab. -->
+<!-- This issue template can be used as a great starting point for feature requests. The section "Release notes" can be used as a summary of the feature and is also required if you want to have your release post blog MR auto generated using the release post item generator: https://about.gitlab.com/handbook/marketing/blog/release-posts/#release-post-item-generator. The remaining sections are the backbone for every feature in GitLab.
-### Release notes
+The goal of this template is brevity for quick/smaller iterations. For a more thorough list of considerations for larger features or feature sets, you can leverage the detailed [feature proposal](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal%20-%20detailed.md). -->
+
+### 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
<!-- What is the user problem you are trying to solve with this issue? -->
-### Proposal
+### Proposal
<!-- Use this section to explain the feature and how it will work. It can be helpful to add technical details, design proposals, and links to related epics or issues. -->
-
-
-/label ~"feature" ~"group::" ~"section::" ~"Category::" ~"GitLab Free"/~"GitLab Premium"/~"GitLab Ultimate"
-
-
-<!--- Use the following resources to find the appropriate labels:
-- https://gitlab.com/gitlab-org/gitlab/-/labels
-- https://about.gitlab.com/handbook/product/categories/features/
-
-Consider adding related issues and epics to this issue. You can also reference the Feature Proposal Template (https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal%20-%20detailed.md) for additional details to consider adding to this issue. Additionally, as a data oriented organization, when your feature exits planning breakdown, consider adding the `What does success look like, and how can we measure that?` section.
-
-Other sections to consider adding:
-
### Intended users
-Who will use this feature? If known, include any of the following: types of users (e.g. Developer), personas, or specific company roles (e.g. Release Manager). It's okay to write "Unknown" and fill this field in later.
+<!-- Who will use this feature? If known, include any of the following: types of users (e.g. Developer), personas, or specific company roles (e.g. Release Manager). It's okay to write "Unknown" and fill this field in later.
Personas are described at https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/
@@ -39,68 +28,28 @@ Personas are described at https://about.gitlab.com/handbook/marketing/product-ma
* [Devon (DevOps Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#devon-devops-engineer)
* [Sidney (Systems Administrator)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sidney-systems-administrator)
* [Sam (Security Analyst)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sam-security-analyst)
-* [Rachel (Release Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#rachel-release-manager)
+* [Rachel (Release Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#rachel-release-manager)
* [Alex (Security Operations Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#alex-security-operations-engineer)
* [Simone (Software Engineer in Test)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#simone-software-engineer-in-test)
-* [Allison (Application Ops)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#allison-application-ops)
+* [Allison (Application Ops)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#allison-application-ops)
* [Priyanka (Platform Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#priyanka-platform-engineer)
* [Dana (Data Analyst)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#dana-data-analyst)
+* [Eddie (Content Editor)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#eddie-content-editor)
+-->
-### User experience goal
-
-What is the single user experience workflow this problem addresses?
-For example, "The user should be able to use the UI/API/.gitlab-ci.yml with GitLab to <perform a specific task>"
-https://about.gitlab.com/handbook/engineering/ux/ux-research-training/user-story-mapping/
-
-
-### Further details
-
-Include use cases, benefits, goals, or any other details that will help us understand the problem better.
+### Metrics
-### Permissions and Security
+<!-- How are you going to track uage of this feature? Think about user behavior and their interaction with the product. What indicates someone is getting value from it?
-<!-- What permissions are required to perform the described actions? Are they consistent with the existing permissions as documented for users, groups, and projects as appropriate? Is the proposed behavior consistent between the UI, API, and other access methods (e.g. email replies)?
-Consider adding checkboxes and expectations of users with certain levels of membership https://docs.gitlab.com/ee/user/permissions.html
-* [ ] Add expected impact to members with no access (0)
-* [ ] Add expected impact to Guest (10) members
-* [ ] Add expected impact to Reporter (20) members
-* [ ] Add expected impact to Developer (30) members
-* [ ] Add expected impact to Maintainer (40) members
-* [ ] Add expected impact to Owner (50) members
+Create tracking issue using the Snowplow event tracking template. See https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Snowplow%20event%20tracking.md
-### Documentation
+-->
- See the Feature Change Documentation Workflow https://docs.gitlab.com/ee/development/documentation/workflow.html#for-a-product-change
-
-* Add all known Documentation Requirements in this section. See https://docs.gitlab.com/ee/development/documentation/workflow.html
-* If this feature requires changing permissions, update the permissions document. See https://docs.gitlab.com/ee/user/permissions.html
-
-### Availability & Testing
-
-This section needs to be retained and filled in during the workflow planning breakdown phase of this feature proposal, if not earlier.
-
-What risks does this change pose to our availability? How might it affect the quality of the product? What additional test coverage or changes to tests will be needed? Will it require cross-browser testing?
-
-Please list the test areas (unit, integration and end-to-end) that needs to be added or updated to ensure that this feature will work as intended. Please use the list below as guidance.
-* Unit test changes
-* Integration test changes
-* End-to-end test change
-
-See the test engineering planning process and reach out to your counterpart Software Engineer in Test for assistance: https://about.gitlab.com/handbook/engineering/quality/test-engineering/#test-planning
-
-### What does success look like, and how can we measure that?
-
-Define both the success metrics and acceptance criteria. Note that success metrics indicate the desired business outcomes, while acceptance criteria indicate when the solution is working correctly. If there is no way to measure success, link to an issue that will implement a way to measure this.
-
-### What is the type of buyer?
-
-What is the buyer persona for this feature? See https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/buyer-persona/
-In which enterprise tier should this feature go? See https://about.gitlab.com/handbook/product/pricing/#three-tiers
-
-### Is this a cross-stage feature?
-
-Communicate if this change will affect multiple Stage Groups or product areas. We recommend always start with the assumption that a feature request will have an impact into another Group. Loop in the most relevant PM and Product Designer from that Group to provide strategic support to help align the Group's broader plan and vision, as well as to avoid UX and technical debt. https://about.gitlab.com/handbook/product/#cross-stage-features -->
+<!-- Label reminders
+Use the following resources to find the appropriate labels:
+- https://gitlab.com/gitlab-org/gitlab/-/labels
+- https://about.gitlab.com/handbook/product/categories/features/
+-->
-/label ~documentation
-/label ~direction
+/label ~"type::feature" ~"group::" ~"section::" ~"Category::" ~"GitLab Free"/~"GitLab Premium"/~"GitLab Ultimate" ~documentation ~direction
diff --git a/.gitlab/issue_templates/Feature proposal - detailed.md b/.gitlab/issue_templates/Feature proposal - detailed.md
index 9759bb7e2dc..c787fc99333 100644
--- a/.gitlab/issue_templates/Feature proposal - detailed.md
+++ b/.gitlab/issue_templates/Feature proposal - detailed.md
@@ -31,6 +31,14 @@ Personas are described at https://about.gitlab.com/handbook/marketing/product-ma
* [Eddie (Content Editor)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#eddie-content-editor)
-->
+### Metrics
+
+<!-- How are you going to track uage of this feature? Think about user behavior and their interaction with the product. What indicates someone is getting value from it?
+
+Create tracking issue using the Snowplow event tracking template. See https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Snowplow%20event%20tracking.md
+
+-->
+
### User experience goal
<!-- What is the single user experience workflow this problem addresses?
@@ -112,6 +120,4 @@ Use the following resources to find the appropriate labels:
-->
/label ~devops:: ~group: ~Category:
/label ~"GitLab Free"/~"GitLab Premium"/~"GitLab Ultimate"
-/label ~feature
-/label ~documentation
-/label ~direction
+/label ~"type::feature" ~documentation ~direction
diff --git a/.gitlab/issue_templates/Geo Replicate a new Git repository type.md b/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
index 0d822945798..71a962d1789 100644
--- a/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
@@ -111,115 +111,9 @@ Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org
- [ ] Be sure to commit the relevant changes in `ee/db/geo/structure.sql`
-### Add verification state fields on the Geo primary site
+### Add verification state to the Model
-The Geo primary site needs to checksum every replicable in order for secondaries to verify their own checksums. To do this, Geo requires fields on the Model. There are two ways to add the necessary verification state fields. If the table is large and wide, then it may be a good idea to add verification state fields to a separate table (Option 2). Consult a database expert if needed.
-
-#### Add verification state fields to the model table (Option 1)
-
-- [ ] Create the migration file in `db/migrate`:
-
- ```shell
- bin/rails generate migration AddVerificationStateToCoolWidgets
- ```
-
-- [ ] Replace the contents of the migration file with:
-
- ```ruby
- # frozen_string_literal: true
-
- class AddVerificationStateToCoolWidgets < ActiveRecord::Migration[6.0]
- def change
- change_table(:cool_widgets) do |t|
- t.integer :verification_state, default: 0, limit: 2, null: false
- t.column :verification_started_at, :datetime_with_timezone
- t.integer :verification_retry_count, limit: 2, null: false
- t.column :verification_retry_at, :datetime_with_timezone
- t.column :verified_at, :datetime_with_timezone
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
-
- t.text :verification_failure # rubocop:disable Migration/AddLimitToTextColumns
- end
- end
- end
- ```
-
-- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
-- [ ] If `cool_widgets` is a high-traffic table, follow [the database documentation to use `with_lock_retries`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/migration_style_guide.md#when-to-use-the-helper-method)
-- [ ] Adding a `text` column also [requires](../database/strings_and_the_text_data_type.md#add-a-text-column-to-an-existing-table) setting a limit. Create the migration file in `db/migrate`:
-
- ```shell
- bin/rails generate migration AddVerificationFailureLimitToCoolWidgets
- ```
-
-- [ ] Replace the contents of the migration file with:
-
- ```ruby
- # frozen_string_literal: true
-
- class AddVerificationFailureLimitToCoolWidgets < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'cool_widget_verification_failure_text_limit'
-
- def up
- add_text_limit :cool_widget, :verification_failure, 255, constraint_name: CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint(:cool_widget, CONSTRAINT_NAME)
- end
- end
- ```
-
-- [ ] Add indexes on verification fields to ensure verification can be performed efficiently. Some or all of these indexes can be omitted if the table is guaranteed to be small. Ask a database expert if you are considering omitting indexes. Create the migration file in `db/migrate`:
-
- ```shell
- bin/rails generate migration AddVerificationIndexesToCoolWidgets
- ```
-
-- [ ] Replace the contents of the migration file with:
-
- ```ruby
- # frozen_string_literal: true
-
- class AddVerificationIndexesToCoolWidgets < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- VERIFICATION_STATE_INDEX_NAME = "index_cool_widgets_on_verification_state"
- PENDING_VERIFICATION_INDEX_NAME = "index_cool_widgets_pending_verification"
- FAILED_VERIFICATION_INDEX_NAME = "index_cool_widgets_failed_verification"
- NEEDS_VERIFICATION_INDEX_NAME = "index_cool_widgets_needs_verification"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :cool_widgets, :verification_state, name: VERIFICATION_STATE_INDEX_NAME
- add_concurrent_index :cool_widgets, :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
- add_concurrent_index :cool_widgets, :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
- add_concurrent_index :cool_widgets, :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :cool_widgets, VERIFICATION_STATE_INDEX_NAME
- remove_concurrent_index_by_name :cool_widgets, PENDING_VERIFICATION_INDEX_NAME
- remove_concurrent_index_by_name :cool_widgets, FAILED_VERIFICATION_INDEX_NAME
- remove_concurrent_index_by_name :cool_widgets, NEEDS_VERIFICATION_INDEX_NAME
- end
- end
- ```
-
-- [ ] Run database migrations:
-
- ```shell
- bin/rake db:migrate
- ```
-
-- [ ] Be sure to commit the relevant changes in `db/structure.sql`
-
-#### Add verification state fields to a separate table (Option 2)
+The Geo primary site needs to checksum every replicable so secondaries can verify their own checksums. To do this, Geo requires the Model to have an associated table to track verification state.
- [ ] Create the migration file in `db/migrate`:
@@ -273,6 +167,7 @@ The Geo primary site needs to checksum every replicable in order for secondaries
```
- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
+
- [ ] Run database migrations:
```shell
@@ -287,7 +182,14 @@ That's all of the required database changes.
#### Step 1. Implement replication and verification
-- [ ] Include `Gitlab::Geo::ReplicableModel` in the `CoolWidget` class, and specify the Replicator class `with_replicator Geo::CoolWidgetReplicator`.
+- [ ] Add the following lines to the `cool_widget` model to accomplish some important tasks:
+ - Include `Gitlab::Geo::ReplicableModel` in the `CoolWidget` class, and specify the Replicator class `with_replicator Geo::CoolWidgetReplicator`.
+ - Include the `::Gitlab::Geo::VerificationState` concern.
+ - Delegate verification related methods to the `cool_widget_state` model.
+ - For verification, override some scopes to use the `cool_widget_states` table instead of the model table.
+ - Implement the `verification_state_object` method to return the object that holds
+ the verification details
+ - Override some methods to use the `cool_widget_states` table in verification-related queries.
Pay some attention to method `pool_repository`. Not every repository type uses repository pooling. As Geo prefers to use repository snapshotting, it can lead to data loss. Make sure to overwrite `pool_repository` so it returns nil for repositories that do not have pools.
@@ -297,6 +199,7 @@ That's all of the required database changes.
# frozen_string_literal: true
class CoolWidget < ApplicationRecord
+ ...
include ::Gitlab::Geo::ReplicableModel
include ::Gitlab::Geo::VerificationState
@@ -304,31 +207,62 @@ That's all of the required database changes.
mount_uploader :file, CoolWidgetUploader
+ has_one :cool_widget_state, autosave: false, inverse_of: :cool_widget, class_name: 'Geo::CoolWidgetState'
+
+ delegate :verification_retry_at, :verification_retry_at=,
+ :verified_at, :verified_at=,
+ :verification_checksum, :verification_checksum=,
+ :verification_failure, :verification_failure=,
+ :verification_retry_count, :verification_retry_count=,
+ :verification_state=, :verification_state,
+ :verification_started_at=, :verification_started_at,
+ to: :cool_widget_state
+ ...
+
+ scope :with_verification_state, ->(state) { joins(:cool_widget_state).where(cool_widget_states: { verification_state: verification_state_value(state) }) }
+ scope :checksummed, -> { joins(:cool_widget_state).where.not(cool_widget_states: { verification_checksum: nil } ) }
+ scope :not_checksummed, -> { joins(:cool_widget_state).where(cool_widget_states: { verification_checksum: nil } ) }
+
# Override the `all` default if not all records can be replicated. For an
# example of an existing Model that needs to do this, see
# `EE::MergeRequestDiff`.
# scope :available_replicables, -> { all }
- # @param primary_key_in [Range, CoolWidget] arg to pass to primary_key_in scope
- # @return [ActiveRecord::Relation<CoolWidget>] everything that should be synced to this node, restricted by primary key
- def self.replicables_for_current_secondary(primary_key_in)
- # This issue template does not help you write this method.
- #
- # This method is called only on Geo secondary sites. It is called when
- # we want to know which records to replicate. This is not easy to automate
- # because for example:
- #
- # * The "selective sync" feature allows admins to choose which namespaces # to replicate, per secondary site. Most Models are scoped to a
- # namespace, but the nature of the relationship to a namespace varies
- # between Models.
- # * The "selective sync" feature allows admins to choose which shards to
- # replicate, per secondary site. Repositories are associated with
- # shards. Most blob types are not, but Project Uploads are.
- # * Remote stored replicables are not replicated, by default. But the
- # setting `sync_object_storage` enables replication of remote stored
- # replicables.
- #
- # Search the codebase for examples, and consult a Geo expert if needed.
+ def verification_state_object
+ cool_widget_state
+ end
+ ...
+
+ class_methods do
+ extend ::Gitlab::Utils::Override
+ ...
+
+ # @param primary_key_in [Range, CoolWidget] arg to pass to primary_key_in scope
+ # @return [ActiveRecord::Relation<CoolWidget>] everything that should be synced to this node, restricted by primary key
+ def replicables_for_current_secondary(primary_key_in)
+ # This issue template does not help you write this method.
+ #
+ # This method is called only on Geo secondary sites. It is called when
+ # we want to know which records to replicate. This is not easy to automate
+ # because for example:
+ #
+ # * The "selective sync" feature allows admins to choose which namespaces # to replicate, per secondary site. Most Models are scoped to a
+ # namespace, but the nature of the relationship to a namespace varies
+ # between Models.
+ # * The "selective sync" feature allows admins to choose which shards to
+ # replicate, per secondary site. Repositories are associated with
+ # shards. Most blob types are not, but Project Uploads are.
+ # * Remote stored replicables are not replicated, by default. But the
+ # setting `sync_object_storage` enables replication of remote stored
+ # replicables.
+ #
+ # Search the codebase for examples, and consult a Geo expert if needed.
+ end
+
+ override :verification_state_table_class
+ def verification_state_table_class
+ CoolWidgetState
+ end
end
# Geo checks this method in FrameworkRepositorySyncService to avoid
@@ -336,6 +270,11 @@ That's all of the required database changes.
def pool_repository
nil
end
+ ...
+
+ def cool_widget_state
+ super || build_cool_widget_state
+ end
...
end
@@ -343,6 +282,15 @@ That's all of the required database changes.
- [ ] Implement `CoolWidget.replicables_for_current_secondary` above.
- [ ] Ensure `CoolWidget.replicables_for_current_secondary` is well-tested. Search the codebase for `replicables_for_current_secondary` to find examples of parameterized table specs. You may need to add more `FactoryBot` traits.
+- [ ] Add the following shared examples to `ee/spec/models/ee/cool_widget_spec.rb`:
+
+ ```ruby
+ include_examples 'a replicable model with a separate table for verification state' do
+ let(:verifiable_model_record) { build(:cool_widget) } # add extra params if needed to make sure the record is included in `available_verifiables`
+ let(:unverifiable_model_record) { build(:cool_widget) } # add extra params if needed to make sure the record is NOT included in `available_verifiables`
+ end
+ ```
+
- [ ] Create `ee/app/replicators/geo/cool_widget_replicator.rb`. Implement the `#repository` method which should return a `<Repository>` instance, and implement the class method `.model` to return the `CoolWidget` class:
```ruby
@@ -365,6 +313,10 @@ That's all of the required database changes.
::Gitlab::GitAccessCoolWidget
end
+ def self.no_repo_message
+ git_access_class.error_message(:no_repo)
+ end
+
# The feature flag follows the format `geo_#{replicable_name}_replication`,
# so here it would be `geo_cool_widget_replication`
def self.replication_enabled_by_default?
@@ -403,6 +355,9 @@ That's all of the required database changes.
```
- [ ] Make sure a Geo secondary site can request and download Cool Widgets on the Geo primary site. You may need to make some changes to `Gitlab::GitAccessCoolWidget`. For example, see [this change for Group-level Wikis](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54914/diffs?commit_id=0f2b36f66697b4addbc69bd377ee2818f648dd33).
+
+- [ ] Make sure a Geo secondary site can replicate Cool Widgets where repository does not exist on the Geo primary site. The only way to know about this is to parse the error text. You may need to make some changes to `Gitlab::CoolWidgetReplicator.no_repo_message` to return the proper error message. For example, see [this change for Group-level Wikis](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74133).
+
- [ ] Generate the feature flag definition file by running the feature flag command and following the command prompts:
```shell
@@ -529,13 +484,7 @@ That's all of the required database changes.
- [ ] Make sure the factory also allows setting a `project` attribute. If the model does not have a direct relation to a project, you can use a `transient` attribute. Check out `spec/factories/merge_request_diffs.rb` for an example.
-##### If you added verification state fields to a separate table (option 2 above), then you need to make additional model and factory changes
-
-If you did not add verification state fields to a separate table, `cool_widget_states`, then skip to [Step 2. Implement metrics gathering](#step-2-implement-metrics-gathering).
-
-Otherwise, you can follow [the example of Merge Request Diffs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63309).
-
-- [ ] Add a `Geo::CoolWidgetState` model in `ee/app/models/geo/cool_widget_state.rb`:
+- [ ] Following [the example of Merge Request Diffs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63309) add a `Geo::CoolWidgetState` model in `ee/app/models/ee/geo/cool_widget_state.rb`:
``` ruby
# frozen_string_literal: true
@@ -569,63 +518,6 @@ Otherwise, you can follow [the example of Merge Request Diffs](https://gitlab.co
end
```
-- [ ] Add the following lines to the `cool_widget` model to accomplish some important tasks:
- - Include the `::Gitlab::Geo::VerificationState` concern.
- - Delegate verification related methods to the `cool_widget_state` model.
- - Override some scopes to use the `cool_widget_states` table instead of the model table, for verification.
- - Override some methods to use the `cool_widget_states` table in verification related queries.
-
- ```ruby
- class CoolWidget < ApplicationRecord
- ...
- include ::Gitlab::Geo::VerificationState
-
- has_one :cool_widget_state, autosave: true, inverse_of: :cool_widget, class_name: 'Geo::CoolWidgetState'
-
- delegate :verification_retry_at, :verification_retry_at=,
- :verified_at, :verified_at=,
- :verification_checksum, :verification_checksum=,
- :verification_failure, :verification_failure=,
- :verification_retry_count, :verification_retry_count=,
- :verification_state=, :verification_state,
- :verification_started_at=, :verification_started_at,
- to: :cool_widget_state
- ...
-
- scope :with_verification_state, ->(state) { joins(:cool_widget_state).where(cool_widget_states: { verification_state: verification_state_value(state) }) }
- scope :checksummed, -> { joins(:cool_widget_state).where.not(cool_widget_states: { verification_checksum: nil } ) }
- scope :not_checksummed, -> { joins(:cool_widget_state).where(cool_widget_states: { verification_checksum: nil } ) }
-
- ...
-
- class_methods do
- extend ::Gitlab::Utils::Override
- ...
- override :verification_state_table_name
- def verification_state_table_name
- 'cool_widget_states'
- end
-
- override :verification_state_model_key
- def verification_state_model_key
- 'cool_widget_id'
- end
-
- override :verification_arel_table
- def verification_arel_table
- CoolWidgetState.arel_table
- end
- end
- ...
-
- def cool_widget_state
- super || build_cool_widget_state
- end
-
- ...
- end
- ```
-
#### Step 2. Implement metrics gathering
Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in `GeoNodeStatus` for display in the UI, and sent to Prometheus:
diff --git a/.gitlab/issue_templates/Geo Replicate a new blob type.md b/.gitlab/issue_templates/Geo Replicate a new blob type.md
index 00a71fa406e..7c927e79e93 100644
--- a/.gitlab/issue_templates/Geo Replicate a new blob type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new blob type.md
@@ -37,6 +37,7 @@ It is also a good idea to first open a proof-of-concept merge request. It can be
You can look into the following examples of MRs for implementing replication/verification for a new blob type:
- [Add db changes](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60935) and [add verification for MR diffs using SSF](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63309)
- [Verify Terraform state versions](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58800)
+- [Verify LFS objects](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63981)
### Modify database schemas to prepare to add Geo support for Cool Widgets
@@ -114,113 +115,9 @@ Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org
### Add verification state fields on the Geo primary site
-The Geo primary site needs to checksum every replicable in order for secondaries to verify their own checksums. To do this, Geo requires fields on the Model. There are two ways to add the necessary verification state fields. If the table is large and wide, then it may be a good idea to add verification state fields to a separate table (Option 2). Consult a database expert if needed.
+The Geo primary site needs to checksum every replicable so secondaries can verify their own checksums. To do this, Geo requires fields on the Model. Add verification state fields to a separate table. Consult a database expert if needed.
-#### Add verification state fields to the model table (Option 1)
-
-- [ ] Create the migration file in `db/migrate`:
-
- ```shell
- bin/rails generate migration AddVerificationStateToCoolWidgets
- ```
-
-- [ ] Replace the contents of the migration file with:
-
- ```ruby
- # frozen_string_literal: true
-
- class AddVerificationStateToCoolWidgets < ActiveRecord::Migration[6.0]
- def change
- change_table(:cool_widgets) do |t|
- t.integer :verification_state, default: 0, limit: 2, null: false
- t.column :verification_started_at, :datetime_with_timezone
- t.integer :verification_retry_count, limit: 2, null: false
- t.column :verification_retry_at, :datetime_with_timezone
- t.column :verified_at, :datetime_with_timezone
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
-
- t.text :verification_failure # rubocop:disable Migration/AddLimitToTextColumns
- end
- end
- end
- ```
-
-- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
-- [ ] If `cool_widgets` is a high-traffic table, follow [the database documentation to use `with_lock_retries`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/migration_style_guide.md#when-to-use-the-helper-method)
-- [ ] Adding a `text` column also [requires](../database/strings_and_the_text_data_type.md#add-a-text-column-to-an-existing-table) setting a limit. Create the migration file in `db/migrate`:
-
- ```shell
- bin/rails generate migration AddVerificationFailureLimitToCoolWidgets
- ```
-
-- [ ] Replace the contents of the migration file with:
-
- ```ruby
- # frozen_string_literal: true
-
- class AddVerificationFailureLimitToCoolWidgets < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'cool_widget_verification_failure_text_limit'
-
- def up
- add_text_limit :cool_widget, :verification_failure, 255, constraint_name: CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint(:cool_widget, CONSTRAINT_NAME)
- end
- end
- ```
-
-- [ ] Add indexes on verification fields to ensure verification can be performed efficiently. Some or all of these indexes can be omitted if the table is guaranteed to be small. Ask a database expert if you are considering omitting indexes. Create the migration file in `db/migrate`:
-
- ```shell
- bin/rails generate migration AddVerificationIndexesToCoolWidgets
- ```
-
-- [ ] Replace the contents of the migration file with:
-
- ```ruby
- # frozen_string_literal: true
-
- class AddVerificationIndexesToCoolWidgets < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- VERIFICATION_STATE_INDEX_NAME = "index_cool_widgets_on_verification_state"
- PENDING_VERIFICATION_INDEX_NAME = "index_cool_widgets_pending_verification"
- FAILED_VERIFICATION_INDEX_NAME = "index_cool_widgets_failed_verification"
- NEEDS_VERIFICATION_INDEX_NAME = "index_cool_widgets_needs_verification"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :cool_widgets, :verification_state, name: VERIFICATION_STATE_INDEX_NAME
- add_concurrent_index :cool_widgets, :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
- add_concurrent_index :cool_widgets, :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
- add_concurrent_index :cool_widgets, :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :cool_widgets, VERIFICATION_STATE_INDEX_NAME
- remove_concurrent_index_by_name :cool_widgets, PENDING_VERIFICATION_INDEX_NAME
- remove_concurrent_index_by_name :cool_widgets, FAILED_VERIFICATION_INDEX_NAME
- remove_concurrent_index_by_name :cool_widgets, NEEDS_VERIFICATION_INDEX_NAME
- end
- end
- ```
-
-- [ ] Run database migrations:
-
- ```shell
- bin/rake db:migrate
- ```
-
-- [ ] Be sure to commit the relevant changes in `db/structure.sql`
-
-#### Add verification state fields to a separate table (Option 2)
+#### Add verification state fields to a new table
- [ ] Create the migration file in `db/migrate`:
@@ -274,12 +171,15 @@ The Geo primary site needs to checksum every replicable in order for secondaries
```
- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
+
- [ ] Run database migrations:
```shell
bin/rake db:migrate
```
+- [ ] If `cool_widgets` is a high-traffic table, follow [the database documentation to use `with_lock_retries`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/migration_style_guide.md#when-to-use-the-helper-method)
+
- [ ] Be sure to commit the relevant changes in `db/structure.sql`
That's all of the required database changes.
@@ -288,14 +188,22 @@ That's all of the required database changes.
#### Step 1. Implement replication and verification
-- [ ] Include `Gitlab::Geo::ReplicableModel` in the `CoolWidget` class, and specify the Replicator class `with_replicator Geo::CoolWidgetReplicator`.
+- [ ] Add the following lines to the `cool_widget` model to accomplish some important tasks:
+ - Include `Gitlab::Geo::ReplicableModel` in the `CoolWidget` class, and specify the Replicator class `with_replicator Geo::CoolWidgetReplicator`.
+ - Include the `::Gitlab::Geo::VerificationState` concern.
+ - Delegate verification related methods to the `cool_widget_state` model.
+ - For verification, override some scopes to use the `cool_widget_states` table instead of the model table.
+ - Implement the `verification_state_object` method to return the object that holds
+ the verification details
+ - Override some methods to use the `cool_widget_states` table in verification-related queries.
At this point the `CoolWidget` class should look like this:
```ruby
# frozen_string_literal: true
-
+
class CoolWidget < ApplicationRecord
+ ...
include ::Gitlab::Geo::ReplicableModel
include ::Gitlab::Geo::VerificationState
@@ -303,38 +211,84 @@ That's all of the required database changes.
mount_uploader :file, CoolWidgetUploader
+ has_one :cool_widget_state, autosave: false, inverse_of: :cool_widget, class_name: 'Geo::CoolWidgetState'
+
+ delegate :verification_retry_at, :verification_retry_at=,
+ :verified_at, :verified_at=,
+ :verification_checksum, :verification_checksum=,
+ :verification_failure, :verification_failure=,
+ :verification_retry_count, :verification_retry_count=,
+ :verification_state=, :verification_state,
+ :verification_started_at=, :verification_started_at,
+ to: :cool_widget_state
+ ...
+
+ scope :with_verification_state, ->(state) { joins(:cool_widget_state).where(cool_widget_states: { verification_state: verification_state_value(state) }) }
+ scope :checksummed, -> { joins(:cool_widget_state).where.not(cool_widget_states: { verification_checksum: nil } ) }
+ scope :not_checksummed, -> { joins(:cool_widget_state).where(cool_widget_states: { verification_checksum: nil } ) }
+
# Override the `all` default if not all records can be replicated. For an
# example of an existing Model that needs to do this, see
# `EE::MergeRequestDiff`.
# scope :available_replicables, -> { all }
- # @param primary_key_in [Range, CoolWidget] arg to pass to primary_key_in scope
- # @return [ActiveRecord::Relation<CoolWidget>] everything that should be synced to this node, restricted by primary key
- def self.replicables_for_current_secondary(primary_key_in)
- # This issue template does not help you write this method.
- #
- # This method is called only on Geo secondary sites. It is called when
- # we want to know which records to replicate. This is not easy to automate
- # because for example:
- #
- # * The "selective sync" feature allows admins to choose which namespaces # to replicate, per secondary site. Most Models are scoped to a
- # namespace, but the nature of the relationship to a namespace varies
- # between Models.
- # * The "selective sync" feature allows admins to choose which shards to
- # replicate, per secondary site. Repositories are associated with
- # shards. Most blob types are not, but Project Uploads are.
- # * Remote stored replicables are not replicated, by default. But the
- # setting `sync_object_storage` enables replication of remote stored
- # replicables.
- #
- # Search the codebase for examples, and consult a Geo expert if needed.
+ def verification_state_object
+ cool_widget_state
end
...
+
+ class_methods do
+ extend ::Gitlab::Utils::Override
+ ...
+
+ # @param primary_key_in [Range, CoolWidget] arg to pass to primary_key_in scope
+ # @return [ActiveRecord::Relation<CoolWidget>] everything that should be synced to this node, restricted by primary key
+ def self.replicables_for_current_secondary(primary_key_in)
+ # This issue template does not help you write this method.
+ #
+ # This method is called only on Geo secondary sites. It is called when
+ # we want to know which records to replicate. This is not easy to automate
+ # because for example:
+ #
+ # * The "selective sync" feature allows admins to choose which namespaces # to replicate, per secondary site. Most Models are scoped to a
+ # namespace, but the nature of the relationship to a namespace varies
+ # between Models.
+ # * The "selective sync" feature allows admins to choose which shards to
+ # replicate, per secondary site. Repositories are associated with
+ # shards. Most blob types are not, but Project Uploads are.
+ # * Remote stored replicables are not replicated, by default. But the
+ # setting `sync_object_storage` enables replication of remote stored
+ # replicables.
+ #
+ # Search the codebase for examples, and consult a Geo expert if needed.
+ end
+
+ override :verification_state_table_class
+ def verification_state_table_class
+ CoolWidgetState
+ end
+ end
+ ...
+
+ def cool_widget_state
+ super || build_cool_widget_state
+ end
+
+ ...
end
```
- [ ] Implement `CoolWidget.replicables_for_current_secondary` above.
- [ ] Ensure `CoolWidget.replicables_for_current_secondary` is well-tested. Search the codebase for `replicables_for_current_secondary` to find examples of parameterized table specs. You may need to add more `FactoryBot` traits.
+- [ ] Add the following shared examples to `ee/spec/models/ee/cool_widget_spec.rb`:
+
+ ```ruby
+ include_examples 'a replicable model with a separate table for verification state' do
+ let(:verifiable_model_record) { build(:cool_widget) } # add extra params if needed to make sure the record is included in `available_verifiables`
+ let(:unverifiable_model_record) { build(:cool_widget) } # add extra params if needed to make sure the record is NOT included in `available_verifiables`
+ end
+ ```
+
- [ ] Create `ee/app/replicators/geo/cool_widget_replicator.rb`. Implement the `#carrierwave_uploader` method which should return a `CarrierWave::Uploader`, and implement the class method `.model` to return the `CoolWidget` class:
```ruby
@@ -498,13 +452,7 @@ That's all of the required database changes.
- [ ] Make sure the factory also allows setting a `project` attribute. If the model does not have a direct relation to a project, you can use a `transient` attribute. Check out `spec/factories/merge_request_diffs.rb` for an example.
-##### If you added verification state fields to a separate table (option 2 above), then you need to make additional model and factory changes
-
-If you did not add verification state fields to a separate table, `cool_widget_states`, then skip to [Step 2. Implement metrics gathering](#step-2-implement-metrics-gathering).
-
-Otherwise, you can follow [the example of Merge Request Diffs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63309).
-
-- [ ] Add a `Geo::CoolWidgetState` model in `ee/app/models/ee/geo/cool_widget_state.rb`:
+- [ ] Following [the example of Merge Request Diffs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63309) add a `Geo::CoolWidgetState` model in `ee/app/models/ee/geo/cool_widget_state.rb`:
``` ruby
module Geo
@@ -536,63 +484,6 @@ Otherwise, you can follow [the example of Merge Request Diffs](https://gitlab.co
end
```
-- [ ] Add the following lines to the `cool_widget` model to accomplish some important tasks:
- - Include the `::Gitlab::Geo::VerificationState` concern.
- - Delegate verification related methods to the `cool_widget_state` model.
- - Override some scopes to use the `cool_widget_states` table instead of the model table, for verification.
- - Override some methods to use the `cool_widget_states` table in verification related queries.
-
- ```ruby
- class CoolWidget < ApplicationRecord
- ...
- include ::Gitlab::Geo::VerificationState
-
- has_one :cool_widget_state, autosave: true, inverse_of: :cool_widget, class_name: 'Geo::CoolWidgetState'
-
- delegate :verification_retry_at, :verification_retry_at=,
- :verified_at, :verified_at=,
- :verification_checksum, :verification_checksum=,
- :verification_failure, :verification_failure=,
- :verification_retry_count, :verification_retry_count=,
- :verification_state=, :verification_state,
- :verification_started_at=, :verification_started_at,
- to: :cool_widget_state
- ...
-
- scope :with_verification_state, ->(state) { joins(:cool_widget_state).where(cool_widget_states: { verification_state: verification_state_value(state) }) }
- scope :checksummed, -> { joins(:cool_widget_state).where.not(cool_widget_states: { verification_checksum: nil } ) }
- scope :not_checksummed, -> { joins(:cool_widget_state).where(cool_widget_states: { verification_checksum: nil } ) }
-
- ...
-
- class_methods do
- extend ::Gitlab::Utils::Override
- ...
- override :verification_state_table_name
- def verification_state_table_name
- 'cool_widget_states'
- end
-
- override :verification_state_model_key
- def verification_state_model_key
- 'cool_widget_id'
- end
-
- override :verification_arel_table
- def verification_arel_table
- CoolWidgetState.arel_table
- end
- end
- ...
-
- def cool_widget_state
- super || build_cool_widget_state
- end
-
- ...
- end
- ```
-
#### Step 2. Implement metrics gathering
Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in `GeoNodeStatus` for display in the UI, and sent to Prometheus:
diff --git a/.gitlab/issue_templates/InfraDev.md b/.gitlab/issue_templates/InfraDev.md
index bc0e65c3c22..d337e75289c 100644
--- a/.gitlab/issue_templates/InfraDev.md
+++ b/.gitlab/issue_templates/InfraDev.md
@@ -53,4 +53,4 @@ See also:
-->
/label ~"infradev"
-/label ~"bug"
+/label ~"type::bug"
diff --git a/.gitlab/issue_templates/Problem Validation.md b/.gitlab/issue_templates/Problem Validation.md
index 5d417c5a26d..3f92510b6af 100644
--- a/.gitlab/issue_templates/Problem Validation.md
+++ b/.gitlab/issue_templates/Problem Validation.md
@@ -1,3 +1,7 @@
+<!-- This template is used as a starting point for understing and articulating a customer problem.
+Learn more about it in the handbook: https://about.gitlab.com/handbook/product-development-flow/#validation-phase-2-problem-validation
+-->
+
## Problem Statement
<!-- What is the problem we hope to validate? Reference how to write a real customer problem statement at https://productcoalition.com/how-to-write-a-good-customer-problem-statement-a815f80189ba for guidance. -->
@@ -45,4 +49,8 @@ For example, if the solution will take a product manager, designer, and engineer
- [ ] The problem is well described and detailed with necessary requirements for product design to understand the problem
- [ ] The problem is well described and detailed with necessary requirements for engineering to understand the problem
+## Research Issue
+
+<!-- Link to the Problem Validation Research issue that will be executed by the UX Researcher. https://gitlab.com/gitlab-org/ux-research/ -->
+
/label ~"workflow::validation backlog" ~devops:: ~category: ~group::
diff --git a/.gitlab/issue_templates/Productivity Improvement.md b/.gitlab/issue_templates/Productivity Improvement.md
index 06692d3ede8..040d8ea2f89 100644
--- a/.gitlab/issue_templates/Productivity Improvement.md
+++ b/.gitlab/issue_templates/Productivity Improvement.md
@@ -2,7 +2,7 @@
<!--
Please describe the engineering productivity problem that needs to be solved backed by charts from
-https://about.gitlab.com/handbook/engineering/quality/engineering-productivity-team/#engineering-productivity-team-metrics.
+https://about.gitlab.com/handbook/engineering/quality/engineering-productivity/#engineering-productivity-metrics.
-->
### Problem identification checklist
diff --git a/.gitlab/issue_templates/Refactoring.md b/.gitlab/issue_templates/Refactoring.md
index d9466185ff7..df18dcf7656 100644
--- a/.gitlab/issue_templates/Refactoring.md
+++ b/.gitlab/issue_templates/Refactoring.md
@@ -41,9 +41,9 @@ please list them here.
<!--
Please select the appropriate label from the following:
~"feature::addition"
- ~"feature::maintenance"
+ ~"type::maintenance"
~"tooling::pipelines"
~"tooling::workflow"
-->
-/label ~"feature::maintenance"
+/label ~"type::maintenance"
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md
index 7f2c54f4f49..6bf9e6971d7 100644
--- a/.gitlab/issue_templates/Security developer workflow.md
+++ b/.gitlab/issue_templates/Security developer workflow.md
@@ -12,7 +12,7 @@ Set the title to: `Description of the original issue`
- [ ] Make sure the issue really needs to follow the security release workflow.
- Verify if the issue you're working on `gitlab-org/gitlab` is confidential, if it's public fix should be placed on GitLab canonical and no backports are required.
- If the issue you're fixing doesn't appear to be something that can be exploited by a malicious person and is instead simply a security enhancement do not hesitate to ping `@gitlab-com/gl-security/appsec` to discuss if the issue can be fixed in the canonical repository.
-- [ ] **IMPORTANT**: Mark this [issue as linked] to the Security Release Tracking Issue. You can find it on the topic of the `#releases` Slack channel. This issue
+- [ ] **IMPORTANT**: Mark this [issue as linked] to the Security Release Tracking Issue. You can find it [here](https://gitlab.com/gitlab-org/gitlab/-/issues?sort=created_date&state=opened&label_name[]=upcoming+security+release). This issue
MUST be linked for the release bot to know that the associated merge requests should be merged for this security release.
- Fill out the [Links section](#links):
- [ ] Next to **Issue on GitLab**, add a link to the `gitlab-org/gitlab` issue that describes the security vulnerability.
diff --git a/.gitlab/issue_templates/Technical Evaluation.md b/.gitlab/issue_templates/Technical Evaluation.md
index cf939725a78..680ecb7d9a6 100644
--- a/.gitlab/issue_templates/Technical Evaluation.md
+++ b/.gitlab/issue_templates/Technical Evaluation.md
@@ -29,5 +29,5 @@
### Team
-- [ ] Add ~"workflow::planning breakdown" ~feature and the corresponding `~devops::<stage>` and `~group::<group>` labels.
+- [ ] Add ~"workflow::planning breakdown" ~"type::feature" and the corresponding `~devops::<stage>` and `~group::<group>` labels.
- [ ] Ping the PM and EM.
diff --git a/.gitlab/merge_request_templates/Deprecations.md b/.gitlab/merge_request_templates/Deprecations.md
index 8431e9ca393..1449246b9bc 100644
--- a/.gitlab/merge_request_templates/Deprecations.md
+++ b/.gitlab/merge_request_templates/Deprecations.md
@@ -6,16 +6,19 @@
**Be sure to link this MR to the relevant deprecation issue(s).**
+Deprecation announcements can and should be created and merged into Docs at any time, to optimize user awareness and planning. We encourage confirmed deprecations to be merged as soon as the required reviews are complete, even if weeks ahead of the target milestone's release post. For the announcement to be included in a specific release post and that release's documentation packages, this MR must be reviewed/merged per the due dates below:
+
**By the 10th**: Assign this MR to these team members as Reviewer and for Approval (optional unless noted as required):
- Product Marketing: `@PMM`
- Product Designer(s): `@ProductDesigners`
- Group Manager or Director: `@manager`
- Engineering Manager: `@EM` - Required
+- Technical writer: `@TW` - Required
-**By 8:00 AM PDT 15th**: PM will assign this MR to the TW reviewer: `@PM`
+**By 11:59 AM PDT 15th**: PM assigns this MR to the TW reviewer for final review and merge: `@PM`
-**By 11:59 PM PDT 15th**: TW Reviewer will perform final review and merge this MR to Master: `@TW`
+**By 11:59 PM PDT 17th**: TW Reviewer updates Docs by merging this MR to `master`: `@TW`
---
@@ -31,8 +34,9 @@ They are frequently updated, and everyone should make sure they are aware of the
## PM release post item checklist
- [ ] Set yourself as the Assignee.
+- [ ] If the deprecation is a [breaking change](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-change), add label `breaking change`.
- [ ] Follow the process to [create a deprecation YAML file](https://about.gitlab.com/handbook/marketing/blog/release-posts/#creating-a-deprecation-entry).
-- [ ] Add reviewers by the 10th
+- [ ] Add reviewers by the 10th.
- [ ] When ready to be merged and not later than the 15th, add the ~ready label and @ message the TW for final review and merge.
## Reviewers
@@ -78,5 +82,18 @@ yourself as a reviewer if it's not ready for merge yet.
</details>
-When the PM indicates it is ready for merge, all issues have been addressed merge this MR.
- - You must merge this MR by the 15th so the Release Post TW lead can run the [deprecations in Docs rake task](https://about.gitlab.com/handbook/marketing/blog/release-posts/#update-the-deprecations-doc) on the 16th
+When the PM indicates it is ready for merge and all issues have been addressed, start the merge process.
+
+#### Technical writer merge process
+
+The [deprecations doc's `.md` file](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/update/deprecations.md)
+must be updated before this MR is merged:
+
+1. Check out the MR's branch (in the [`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab) project).
+1. From the command line (in the branch), run `bin/rake gitlab:docs:compile_deprecations`.
+ If you want to double check that it worked, you can run `bin/rake gitlab:docs:check_deprecations`
+ to verify that the doc is up to date.
+1. Commit the updated file and push the changes.
+1. Set the MR to merge when the pipeline succeeds (or merge if the pipeline is already complete).
+
+If you have trouble running the rake task, check the [troubleshooting steps](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecation-rake-task-troubleshooting).
diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md
index 66c1eff412b..893ae7b93b5 100644
--- a/.gitlab/merge_request_templates/Documentation.md
+++ b/.gitlab/merge_request_templates/Documentation.md
@@ -20,10 +20,10 @@
If you are only adding documentation, do not add any of the following labels:
-- `~"feature"`
+- `~"type::feature"`
- `~"frontend"`
- `~"backend"`
-- `~"bug"`
+- `~"type::bug"`
- `~"database"`
These labels cause the MR to be added to code verification QA issues.
diff --git a/.gitlab/merge_request_templates/New End To End Test.md b/.gitlab/merge_request_templates/New End To End Test.md
index f9664c6315f..9ecf8999f66 100644
--- a/.gitlab/merge_request_templates/New End To End Test.md
+++ b/.gitlab/merge_request_templates/New End To End Test.md
@@ -24,5 +24,5 @@ Please link to the respective test case in the testcases project
/label ~"Quality:test-gap" ~"Quality:EE test gaps"
-<!-- Select the appropriate feature label, ~"feature::addition" for tests added for new features, ~"feature::maintenance" for tests added for existing features -->
-/label ~"feature::addition" ~"feature::maintenance"
+<!-- Select the appropriate feature label, ~"feature::addition" for tests added for new features, ~"type::maintenance" for tests added for existing features -->
+/label ~"feature::addition" ~"type::maintenance"
diff --git a/.gitlab/merge_request_templates/Pipeline Configuration.md b/.gitlab/merge_request_templates/Pipeline Configuration.md
index 920abf086cb..62210028c18 100644
--- a/.gitlab/merge_request_templates/Pipeline Configuration.md
+++ b/.gitlab/merge_request_templates/Pipeline Configuration.md
@@ -33,6 +33,6 @@ This will help keep track of expected cost increases to the [GitLab project aver
### Post-merge
-- [ ] Consider communicating these changes to the broader team following the [communication guideline for pipeline changes](https://about.gitlab.com/handbook/engineering/quality/engineering-productivity-team/#pipeline-changes)
+- [ ] Consider communicating these changes to the broader team following the [communication guideline for pipeline changes](https://about.gitlab.com/handbook/engineering/quality/engineering-productivity/#pipeline-changes)
-/label ~tooling ~"tooling::pipelines" ~"Engineering Productivity"
+/label ~"type::tooling" ~"tooling::pipelines" ~"Engineering Productivity"
diff --git a/.gitlab/merge_request_templates/Quarantine End to End Test.md b/.gitlab/merge_request_templates/Quarantine End to End Test.md
index 4edfd2a8c8e..4caebb7f1bb 100644
--- a/.gitlab/merge_request_templates/Quarantine End to End Test.md
+++ b/.gitlab/merge_request_templates/Quarantine End to End Test.md
@@ -30,7 +30,7 @@ the noise (due to constantly failing tests, flaky tests, and so on) so that new
- [ ] To ensure a faster turnaround, ask in the `#quality` Slack channel for someone to review and merge the merge request, rather than assigning it directly.
<!-- Base labels. -->
-/label ~"Quality" ~"QA" ~"feature" ~"feature::maintenance"
+/label ~"Quality" ~"QA" ~"type::maintenance"
<!--
Choose the stage that appears in the test path, e.g. ~"devops::create" for
diff --git a/.gitpod.yml b/.gitpod.yml
index d546cc7f64a..762adb72cce 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -19,6 +19,8 @@ tasks:
# ensure gdk.yml has correct instance settings
gdk config set gitlab.rails.port 443
gdk config set gitlab.rails.https.enabled true
+ # make documentation builds available
+ gdk config set gitlab_docs.enabled true
# reconfigure GDK
echo "$(date) – Reconfiguring GDK" | tee -a /workspace/startup.log
gdk reconfigure
@@ -69,15 +71,13 @@ tasks:
printf "Waiting for GitLab at $(gp url 3000) ..."
# Check /-/readiness which returns JSON, but we're only interested in the exit code
#
- # We use http://localhost:3000 instead of the public hostname because
+ # We use http://localhost:3000 instead of the public hostname because
# it's no longer possible to access as specific cookies are required
until curl --silent --no-buffer --fail http://localhost:3000/-/readiness > /dev/null 2>&1; do printf '.'; sleep 5; done && echo ""
# Give Gitpod a few more seconds to set up everything ...
sleep 5
printf "$(date) – GitLab is up (took ~%.1f minutes)\n" "$((10*$SECONDS/60))e-1" | tee -a /workspace/startup.log
gp preview $(gp url 3000) || true
- # Speed up backend tests
- export GITLAB_TEST_EAGER_LOAD=false
)
ports:
@@ -85,6 +85,8 @@ ports:
onOpen: ignore
- port: 3000 # rails-web
onOpen: notify
+ - port: 3005 # gitlab-docs
+ onOpen: notify
- port: 3010 # gitlab-pages
onOpen: ignore
- port: 3808 # webpack
@@ -104,3 +106,4 @@ vscode:
- octref.vetur@0.34.1
- dbaeumer.vscode-eslint@2.1.8
- gitlab.gitlab-workflow@3.24.0
+ - DavidAnson.vscode-markdownlint@0.44.4
diff --git a/.haml-lint.yml b/.haml-lint.yml
index 1d1c0fa1de2..8d084a0c356 100644
--- a/.haml-lint.yml
+++ b/.haml-lint.yml
@@ -6,6 +6,7 @@ skip_frontmatter: false
exclude:
- 'vendor/**/*'
- 'spec/**/*'
+ - 'ee/spec/**/*'
require:
- './haml_lint/linter/no_plain_nodes.rb'
- './haml_lint/linter/documentation_links.rb'
diff --git a/.nvmrc b/.nvmrc
index c91434ab584..18711d290ea 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-14.15.4
+14.17.5
diff --git a/.rubocop.yml b/.rubocop.yml
index 4bf2392867d..5b7a58e1f2d 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -106,25 +106,31 @@ RSpec/MultipleMemoizedHelpers:
Naming/FileName:
ExpectMatchingDefinition: true
+ CheckDefinitionPathHierarchy: false
Exclude:
+ - '**/*/*.builder'
+ - 'ee/bin/*'
+ - 'config.ru'
+ - 'config/**/*'
+ - 'ee/config/**/*'
+ - 'jh/config/**/*'
- 'db/**/*'
- 'ee/db/**/*'
+ - 'ee/elastic/migrate/*'
+ - 'lib/tasks/**/*.rake'
+ - 'ee/lib/tasks/**/*.rake'
+ - 'lib/generators/**/*'
+ - 'ee/lib/generators/**/*'
+ - 'scripts/**/*'
- 'spec/**/*'
- - 'features/**/*'
+ - 'tooling/bin/**/*'
- 'ee/spec/**/*'
+ - 'jh/spec/**/*'
+ - 'qa/bin/*'
- 'qa/spec/**/*'
- 'qa/qa/specs/**/*'
- - 'qa/bin/*'
- - 'ee/bin/*'
- - 'config/**/*'
- - 'ee/config/**/*'
- - 'lib/generators/**/*'
- - 'locale/unfound_translations.rb'
- - 'ee/locale/unfound_translations.rb'
- - 'ee/lib/generators/**/*'
- - 'qa/qa/scenario/test/integration/ldap_no_tls.rb'
- - 'qa/qa/scenario/test/integration/ldap_tls.rb'
- - 'qa/tasks/*'
+ - 'qa/tasks/**/*.rake'
+ - '**/*.ru'
IgnoreExecutableScripts: true
AllowedAcronyms:
@@ -146,6 +152,26 @@ Naming/FileName:
- CI
- CD
- OAuth
+ - CSP
+ - CSV
+ - SCA
+ - SAN
+ - CIDR
+ - SPDX
+ - MR
+ - SSE
+ - JWT
+ - HLL
+ - GPG
+ - OTP
+ - GID
+ - AR
+ - RSpec
+ - ECDSA
+ - ED25519
+ - GitLab
+ - JavaScript
+ - VSCode
# default ones:
- CLI
- DSL
@@ -682,10 +708,6 @@ Cop/UserAdmin:
- 'spec/**/*.rb'
- 'ee/spec/**/*.rb'
-Performance/OpenStruct:
- Exclude:
- - 'ee/spec/**/*.rb'
-
# See https://gitlab.com/gitlab-org/gitlab/-/issues/327495
Style/RegexpLiteral:
Enabled: false
@@ -712,6 +734,10 @@ QA/SelectorUsage:
Exclude:
- 'spec/rubocop/**/*_spec.rb'
+QA/DuplicateTestcaseLink:
+ # this cop is executed in static-analysis.gitlab-ci.yml since it cannot be run in parallel
+ Enabled: false
+
Performance/ActiveRecordSubtransactions:
Exclude:
- 'spec/**/*.rb'
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index a646f6ec950..7b961e7ee6b 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -32,7 +32,6 @@ Rails/SaveBang:
- 'ee/spec/models/approval_project_rule_spec.rb'
- 'ee/spec/models/burndown_spec.rb'
- 'ee/spec/models/elasticsearch_indexed_namespace_spec.rb'
- - 'ee/spec/models/epic_spec.rb'
- 'ee/spec/models/gitlab_subscription_spec.rb'
- 'ee/spec/models/issue_spec.rb'
- 'ee/spec/models/label_note_spec.rb'
@@ -40,7 +39,6 @@ Rails/SaveBang:
- 'ee/spec/models/license_spec.rb'
- 'ee/spec/models/merge_request_spec.rb'
- 'ee/spec/models/merge_train_spec.rb'
- - 'spec/models/packages/package_spec.rb'
- 'ee/spec/models/project_ci_cd_setting_spec.rb'
- 'ee/spec/models/project_spec.rb'
- 'ee/spec/models/protected_environment_spec.rb'
@@ -136,32 +134,6 @@ Rails/SaveBang:
- 'spec/lib/gitlab/middleware/go_spec.rb'
- 'spec/lib/gitlab/shard_health_cache_spec.rb'
- 'spec/mailers/notify_spec.rb'
- - 'spec/models/clusters/applications/helm_spec.rb'
- - 'spec/models/design_management/version_spec.rb'
- - 'spec/models/environment_spec.rb'
- - 'spec/models/event_spec.rb'
- - 'spec/models/fork_network_spec.rb'
- - 'spec/models/generic_commit_status_spec.rb'
- - 'spec/models/grafana_integration_spec.rb'
- - 'spec/models/group_spec.rb'
- - 'spec/models/identity_spec.rb'
- - 'spec/models/jira_import_state_spec.rb'
- - 'spec/models/namespace_spec.rb'
- - 'spec/models/note_spec.rb'
- - 'spec/models/notification_setting_spec.rb'
- - 'spec/models/operations/feature_flag_scope_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/protectable_dropdown_spec.rb'
- - 'spec/models/redirect_route_spec.rb'
- - 'spec/models/release_spec.rb'
- - 'spec/models/remote_mirror_spec.rb'
- - 'spec/models/resource_milestone_event_spec.rb'
- - 'spec/models/route_spec.rb'
- - 'spec/models/sentry_issue_spec.rb'
- - 'spec/models/snippet_spec.rb'
- - 'spec/models/upload_spec.rb'
Rails/TimeZone:
Enabled: true
@@ -204,7 +176,6 @@ Rails/TimeZone:
- 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_renamed_event_spec.rb'
- 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb'
- 'ee/spec/lib/gitlab/geo/log_cursor/events/reset_checksum_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/upload_deleted_event_spec.rb'
- 'ee/spec/lib/gitlab/geo/log_cursor/logger_spec.rb'
- 'ee/spec/lib/gitlab/git_access_spec.rb'
- 'ee/spec/lib/gitlab/prometheus/queries/additional_metrics_deployment_query_spec.rb'
@@ -1165,6 +1136,7 @@ Gitlab/NamespacedClass:
- 'app/models/members/group_member.rb'
- 'app/models/members/last_group_owner_assigner.rb'
- 'app/models/members/project_member.rb'
+ - 'app/models/members/member_task.rb'
- 'app/models/members_preloader.rb'
- 'app/models/merge_request.rb'
- 'app/models/merge_request_assignee.rb'
@@ -2199,21 +2171,6 @@ Cop/UserAdmin:
- 'lib/gitlab/visibility_level.rb'
- 'qa/qa/runtime/api/client.rb'
-# WIP https://gitlab.com/gitlab-org/gitlab/-/issues/325744
-Performance/OpenStruct:
- Exclude:
- - 'Guardfile'
- - 'app/finders/snippets_finder.rb'
- - 'app/helpers/application_settings_helper.rb'
- - 'ee/lib/gitlab/graphql/aggregations/epics/epic_node.rb'
- - 'ee/lib/gitlab/graphql/aggregations/epics/epic_node.rb'
- - 'lib/api/wikis.rb'
- - 'lib/gitlab/ci/ansi2html.rb'
- - 'lib/gitlab/git/diff_collection.rb'
- - 'lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb'
- - 'lib/gitlab/testing/request_inspector_middleware.rb'
- - 'lib/mattermost/session.rb'
-
# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/324629
Gitlab/DelegatePredicateMethods:
Exclude:
@@ -2443,28 +2400,14 @@ Database/MultipleDatabases:
- 'lib/gitlab/database/load_balancing/sticking.rb'
- 'lib/gitlab/database/migrations/observers/migration_observer.rb'
- 'lib/gitlab/database/migrations/observers/query_log.rb'
- - 'lib/gitlab/database/multi_threaded_migration.rb'
- 'lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb'
- - 'lib/gitlab/database/partitioning/monthly_strategy.rb'
- - 'lib/gitlab/database/partitioning/partition_manager.rb'
- - 'lib/gitlab/database/partitioning/partition_creator.rb'
- - 'lib/gitlab/database/partitioning/replace_table.rb'
- - 'lib/gitlab/database/partitioning/time_partition.rb'
- - 'lib/gitlab/database/postgres_hll/batch_distinct_counter.rb'
- - 'lib/gitlab/database/postgresql_adapter/dump_schema_versions_mixin.rb'
- - 'lib/gitlab/database/postgresql_database_tasks/load_schema_versions_mixin.rb'
- 'lib/gitlab/database.rb'
- - 'lib/gitlab/database/reindexing/concurrent_reindex.rb'
- - 'lib/gitlab/database/reindexing/reindex_concurrently.rb'
- 'lib/gitlab/database/schema_cache_with_renamed_table.rb'
- - 'lib/gitlab/database/schema_migrations/context.rb'
- - 'lib/gitlab/database/schema_version_files.rb'
- - 'lib/gitlab/database/unidirectional_copy_trigger.rb'
- 'lib/gitlab/database/with_lock_retries.rb'
- 'lib/gitlab/gitlab_import/importer.rb'
- 'lib/gitlab/health_checks/db_check.rb'
- 'lib/gitlab/import_export/base/relation_factory.rb'
- - 'lib/gitlab/import_export/relation_tree_restorer.rb'
+ - 'lib/gitlab/import_export/group/relation_tree_restorer.rb'
- 'lib/gitlab/legacy_github_import/importer.rb'
- 'lib/gitlab/metrics/samplers/database_sampler.rb'
- 'lib/gitlab/seeder.rb'
@@ -2604,3 +2547,72 @@ Rails/IncludeUrlHelper:
- 'spec/lib/banzai/filter/issuable_state_filter_spec.rb'
- 'spec/lib/banzai/filter/reference_redactor_filter_spec.rb'
- 'spec/lib/banzai/reference_redactor_spec.rb'
+
+# TODO issue: https://gitlab.com/gitlab-org/gitlab/-/issues/344279
+Style/OpenStructUse:
+ Exclude:
+ - 'app/helpers/application_settings_helper.rb'
+ - 'ee/spec/db/production/license_spec.rb'
+ - 'ee/spec/features/projects/new_project_spec.rb'
+ - 'ee/spec/finders/template_finder_spec.rb'
+ - 'ee/spec/graphql/ee/resolvers/board_lists_resolver_spec.rb'
+ - 'ee/spec/graphql/resolvers/board_groupings/epics_resolvers_spec.rb'
+ - 'ee/spec/helpers/ee/blob_helper_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/group_saml/failure_handler_spec.rb'
+ - 'ee/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb'
+ - 'ee/spec/requests/api/ldap_spec.rb'
+ - 'lib/api/wikis.rb'
+ - 'lib/gitlab/git/diff_collection.rb'
+ - 'lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb'
+ - 'lib/gitlab/testing/request_inspector_middleware.rb'
+ - 'lib/mattermost/session.rb'
+ - 'spec/bin/feature_flag_spec.rb'
+ - 'spec/controllers/admin/clusters_controller_spec.rb'
+ - 'spec/controllers/groups/clusters_controller_spec.rb'
+ - 'spec/controllers/import/fogbugz_controller_spec.rb'
+ - 'spec/controllers/import/gitlab_controller_spec.rb'
+ - 'spec/controllers/projects/clusters_controller_spec.rb'
+ - 'spec/dependencies/omniauth_saml_spec.rb'
+ - 'spec/factories/go_module_versions.rb'
+ - 'spec/factories/wiki_pages.rb'
+ - 'spec/features/projects/clusters/gcp_spec.rb'
+ - 'spec/features/projects/clusters_spec.rb'
+ - 'spec/finders/template_finder_spec.rb'
+ - 'spec/graphql/mutations/branches/create_spec.rb'
+ - 'spec/graphql/mutations/clusters/agent_tokens/create_spec.rb'
+ - 'spec/graphql/mutations/clusters/agents/create_spec.rb'
+ - 'spec/graphql/mutations/clusters/agents/delete_spec.rb'
+ - 'spec/graphql/mutations/commits/create_spec.rb'
+ - 'spec/graphql/mutations/merge_requests/accept_spec.rb'
+ - 'spec/graphql/mutations/merge_requests/create_spec.rb'
+ - 'spec/graphql/types/range_input_type_spec.rb'
+ - 'spec/helpers/application_settings_helper_spec.rb'
+ - 'spec/helpers/profiles_helper_spec.rb'
+ - 'spec/initializers/doorkeeper_spec.rb'
+ - 'spec/lib/gitlab/auth/o_auth/provider_spec.rb'
+ - 'spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb'
+ - 'spec/lib/gitlab/database/migrations/runner_spec.rb'
+ - 'spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb'
+ - 'spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb'
+ - 'spec/lib/gitlab/grape_logging/loggers/exception_logger_spec.rb'
+ - 'spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb'
+ - 'spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb'
+ - 'spec/lib/gitlab/legacy_github_import/project_creator_spec.rb'
+ - 'spec/lib/gitlab/quick_actions/command_definition_spec.rb'
+ - 'spec/lib/gitlab/quick_actions/dsl_spec.rb'
+ - 'spec/lib/gitlab/relative_positioning/range_spec.rb'
+ - 'spec/models/design_management/design_action_spec.rb'
+ - 'spec/models/design_management/design_at_version_spec.rb'
+ - 'spec/models/user_spec.rb'
+ - 'spec/presenters/packages/nuget/search_results_presenter_spec.rb'
+ - 'spec/requests/api/import_github_spec.rb'
+ - 'spec/services/packages/nuget/metadata_extraction_service_spec.rb'
+ - 'spec/services/projects/import_service_spec.rb'
+ - 'spec/services/system_note_service_spec.rb'
+ - 'spec/support/helpers/import_spec_helper.rb'
+ - 'spec/support/helpers/login_helpers.rb'
+ - 'spec/support/helpers/repo_helpers.rb'
+ - 'spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb'
+ - 'spec/tooling/rspec_flaky/flaky_example_spec.rb'
+ - 'tooling/rspec_flaky/flaky_example.rb'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index b329c9df0f9..f29cb429169 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -208,12 +208,6 @@ Metrics/CyclomaticComplexity:
Metrics/PerceivedComplexity:
Max: 25
-# Offense count: 196
-# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, Regex, IgnoreExecutableScripts, AllowedAcronyms.
-# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
-Naming/FileName:
- Enabled: false
-
# Offense count: 11
# Configuration parameters: EnforcedStyle.
# SupportedStyles: lowercase, uppercase
diff --git a/.stylelintrc b/.stylelintrc
index 488e34dd7d4..6e3999fec3b 100644
--- a/.stylelintrc
+++ b/.stylelintrc
@@ -13,27 +13,6 @@
"./scripts/frontend/stylelint/stylelint-utility-classes.js",
],
"rules":{
- "at-rule-disallowed-list": ["extend"],
- "max-nesting-depth": [
- 3,
- {
- "ignoreAtRules":[
- "each",
- "media",
- "supports",
- "include"
- ],
- "severity":"warning"
- }
- ],
- "selector-max-compound-selectors":[3, { "severity": "warning" }],
"stylelint-gitlab/utility-classes":[true,{ "severity": "warning" }],
- "declaration-block-no-duplicate-properties": [
- true,
- {
- "ignore": ["consecutive-duplicates"]
- }
- ],
- "no-eol-whitespace": true,
}
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dad5599a28c..b50b144f571 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -425,6 +425,24 @@ entry.
- [Cleanup bigint conversion for ci_builds](gitlab-org/gitlab@176992aa2b2e76b22637a07d5bafbd6541324a7d) ([merge request](gitlab-org/gitlab!70351))
- [Drop support for data-track-event](gitlab-org/gitlab@ac6027fbef6adf41643412a84945fda6f15c9666) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70234))
+## 14.3.4 (2021-10-28)
+
+### Security (13 changes)
+
+- [Highlight usage of unicode bidi characters](gitlab-org/security/gitlab@0b9bcafa73bc12ad873f75584b993f7b94f1f2e7) ([merge request](gitlab-org/security/gitlab!1938))
+- [Fix dompurify.js to prevent path traversal attacks](gitlab-org/security/gitlab@6599afd4d7357ab356fcb773af19f8388978b3ed) ([merge request](gitlab-org/security/gitlab!1930))
+- [Refresh authorizations on transfer of groups having project shares](gitlab-org/security/gitlab@faad71f44a1b1048b73897d450c923a18ec18c0b) ([merge request](gitlab-org/security/gitlab!1917))
+- [Do not allow Applications API to create apps with blank scopes](gitlab-org/security/gitlab@293931500c84ef7ea9a2117d3ddf094f8ac15dcf) ([merge request](gitlab-org/security/gitlab!1923))
+- [Don't allow author to resolve discussions when MR is locked via GraphQL](gitlab-org/security/gitlab@5027cb2b0303645a921b95d324d3d55dcf7632e4) ([merge request](gitlab-org/security/gitlab!1920))
+- [Workhorse: Allow uploading only a single file](gitlab-org/security/gitlab@c18c2ddfa34a4c3e476136ab3eba9be7f265ad59) ([merge request](gitlab-org/security/gitlab!1914))
+- [Group owners should see SCIM token only once](gitlab-org/security/gitlab@3d6664461da720fb256d8e139961b383e33a3b90) ([merge request](gitlab-org/security/gitlab!1907)) **GitLab Enterprise Edition**
+- [Respect visibility level settings when updating project via API](gitlab-org/security/gitlab@124ca62c02bfa8ef6f7de7b328f80756fd01c052) ([merge request](gitlab-org/security/gitlab!1904))
+- [Avoid decoding the whole tiff image on isTIFF check](gitlab-org/security/gitlab@8e6ffd52f50170a5cf2761e50a3d6efaca5fe64f) ([merge request](gitlab-org/security/gitlab!1900))
+- [Adding a '[redacted]' to mask private email addresses](gitlab-org/security/gitlab@6f2a2b2240eb7590bbc773f35d3927d4854a31b5) ([merge request](gitlab-org/security/gitlab!1894))
+- [Do not display the root password by default](gitlab-org/security/gitlab@87893548183fc4a111e12c0bdb3e409175a41668) ([merge request](gitlab-org/security/gitlab!1803))
+- [Set PipelineSchedules to inactive](gitlab-org/security/gitlab@0e77e1cd938f876f3e9c049a84486c8c90cd0f3f) ([merge request](gitlab-org/security/gitlab!1879))
+- [Remove external_webhook_token from exported project](gitlab-org/security/gitlab@1362f7481aad5e4295da11f0db53e31600c7c7b5) ([merge request](gitlab-org/security/gitlab!1866))
+
## 14.3.3 (2021-10-12)
### Fixed (3 changes)
@@ -973,6 +991,24 @@ entry.
- [Remove the FF ci_reset_bridge_with_subsequent_jobs](gitlab-org/gitlab@a4a75095b9b0250d0b1bdadea90c8a4cd24449b2) ([merge request](gitlab-org/gitlab!68295))
- [Removes ci_same_stage_job_needs ff](gitlab-org/gitlab@5e509cf7aa90041a541b19dda563120a359f0bf9) ([merge request](gitlab-org/gitlab!68041))
+## 14.2.6 (2021-10-28)
+
+### Security (13 changes)
+
+- [Highlight usage of unicode bidi characters](gitlab-org/security/gitlab@18a768bb3cd19b6dc780bb85d91a93605ec8aa4f) ([merge request](gitlab-org/security/gitlab!1939))
+- [Fix dompurify.js to prevent path traversal attacks](gitlab-org/security/gitlab@cfd7c715162c22060b9b80268ef501a9e604421a) ([merge request](gitlab-org/security/gitlab!1931))
+- [Refresh authorizations on transfer of groups having project shares](gitlab-org/security/gitlab@3fc08eb869156a090b015e78da79c8ced16a7162) ([merge request](gitlab-org/security/gitlab!1918))
+- [Do not allow Applications API to create apps with blank scopes](gitlab-org/security/gitlab@c4ffc8c0ee5356bcb9b76dbfa92517589b4225a8) ([merge request](gitlab-org/security/gitlab!1924))
+- [Don't allow author to resolve discussions when MR is locked via GraphQL](gitlab-org/security/gitlab@fe2d0b6f250b60619da97f162c93c9e645daf4af) ([merge request](gitlab-org/security/gitlab!1921))
+- [Workhorse: Allow uploading only a single file](gitlab-org/security/gitlab@89b04599592b7dfc0e4883cfde5d3ecd9ea855b2) ([merge request](gitlab-org/security/gitlab!1915))
+- [Group owners should see SCIM token only once](gitlab-org/security/gitlab@d52c1e41f38039db075a7a3418b8eb9ed8474c2a) ([merge request](gitlab-org/security/gitlab!1908)) **GitLab Enterprise Edition**
+- [Respect visibility level settings when updating project via API](gitlab-org/security/gitlab@3051d6a00d1a56133a77ecd24313bafb4565d576) ([merge request](gitlab-org/security/gitlab!1905))
+- [Avoid decoding the whole tiff image on isTIFF check](gitlab-org/security/gitlab@bab7f45def8fc81fe4b0961a21b4c90a60358ff9) ([merge request](gitlab-org/security/gitlab!1901))
+- [Adding a '[redacted]' to mask private email addresses](gitlab-org/security/gitlab@8eb9749f40b87b9b49b034bceb263219a4d3b114) ([merge request](gitlab-org/security/gitlab!1895))
+- [Do not display the root password by default](gitlab-org/security/gitlab@4ccf08b6645b9f616657edd266d9d31e3602d170) ([merge request](gitlab-org/security/gitlab!1802))
+- [Set PipelineSchedules to inactive](gitlab-org/security/gitlab@ebee16945325d22ceb5c07b7ba48df6fd0b2f067) ([merge request](gitlab-org/security/gitlab!1878))
+- [Remove external_webhook_token from exported project](gitlab-org/security/gitlab@f3ef12185902f3ed5c9d62ffce07418fd704a753) ([merge request](gitlab-org/security/gitlab!1865))
+
## 14.2.5 (2021-09-30)
### Security (28 changes)
@@ -1597,6 +1633,19 @@ entry.
- [Add helpful text to URL group validation and limit text](gitlab-org/gitlab@59a5a6266cb0d5434596170ffa36e4e74b8d2c2c) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65369)) **GitLab Enterprise Edition**
- [Refactor external storage admin area configuration UI and docs](gitlab-org/gitlab@497ba4fc8f4ec1d234c9f5f1ec5c69712b8c7cb3) ([merge request](gitlab-org/gitlab!66219))
+## 14.1.8 (2021-11-15)
+
+### Fixed (1 change)
+
+- [Prevent Git operations from checking replication lag on non-Geo-secondary sites](gitlab-org/gitlab@5abc66f89524b63873b0ce96b0f78c0acc2687f6) ([merge request](gitlab-org/gitlab!73980)) **GitLab Enterprise Edition**
+
+### Changed (4 changes)
+
+- [Geo: Alternate redownload and normal design sync attempts](gitlab-org/gitlab@c23c94e9d791770fd169723845b12097b8512a9e) ([merge request](gitlab-org/gitlab!73980)) **GitLab Enterprise Edition**
+- [Geo: Alternate redownload and normal SSF sync attempts](gitlab-org/gitlab@5aba12770829d43041ef4307049ed500c02b1d77) ([merge request](gitlab-org/gitlab!73980)) **GitLab Enterprise Edition**
+- [Geo: Alternate redownload and normal project syncs](gitlab-org/gitlab@4d3a5798e1f136a027c0b7aab6a35afb3c207ce7) ([merge request](gitlab-org/gitlab!73980)) **GitLab Enterprise Edition**
+- [Geo: Reduce frequency of redownload attempts](gitlab-org/gitlab@795271787c70b7c92a85daa253d2d61561603443) ([merge request](gitlab-org/gitlab!73980)) **GitLab Enterprise Edition**
+
## 14.1.7 (2021-09-30)
### Security (28 changes)
@@ -2273,6 +2322,15 @@ entry.
- [Remove diffs gradual load feature flag](gitlab-org/gitlab@027d7c4327b5b6205a84281239027273517bf81b) ([merge request](gitlab-org/gitlab!55478))
- [Remove partial index for Hashed Storage migration](gitlab-org/gitlab@3ed017a1023d7b0941a7606b69e6caee8d22f15c) ([merge request](gitlab-org/gitlab!62920))
+## 14.0.12 (2021-11-05)
+
+### Changed (4 changes)
+
+- [Geo: Alternate redownload and normal design sync attempts](gitlab-org/gitlab@ed34172e5c7425316480efb732a9429e93e81017) ([merge request](gitlab-org/gitlab!73722)) **GitLab Enterprise Edition**
+- [Geo: Alternate redownload and normal SSF sync attempts](gitlab-org/gitlab@c0f2f40b98c4b9fc72c21c474a2224e045263ea2) ([merge request](gitlab-org/gitlab!73722)) **GitLab Enterprise Edition**
+- [Geo: Alternate redownload and normal project syncs](gitlab-org/gitlab@6370a7258719d5eb0ad83c54383ecb7f4fd54fc2) ([merge request](gitlab-org/gitlab!73722)) **GitLab Enterprise Edition**
+- [Geo: Reduce frequency of redownload attempts](gitlab-org/gitlab@1bcd41f28733b01286a42689857f6530c0805186) ([merge request](gitlab-org/gitlab!73722)) **GitLab Enterprise Edition**
+
## 14.0.11 (2021-09-23)
### Fixed (1 change)
@@ -3044,6 +3102,21 @@ No changes.
- [Add missing metrics information](gitlab-org/gitlab@89cd7fe3b95323e635b2d73e08549b2e6153dc4d) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61772/edit))
- [Track usage of the resolve UI](gitlab-org/gitlab@35c8e30fce288cecefcf2f7c0077d4608e696519) ([merge request](gitlab-org/gitlab!61654))
+## 13.12.15 (2021-11-03)
+
+### Fixed (2 changes)
+
+- [Allow nil for remaining ci cd settings](gitlab-org/gitlab@896fd7ecf23714fa9f710efa4af245a26c677dce) ([merge request](gitlab-org/gitlab!73522))
+- [Allow nil on delegated CI/CD settings](gitlab-org/gitlab@d57a9ea79080fc473eb54c0ee696a50fd270e8a4) ([merge request](gitlab-org/gitlab!73522))
+
+## 13.12.14 (2021-11-03)
+
+This version has been skipped due to QA problems.
+
+## 13.12.13 (2021-10-29)
+
+This version has been skipped due to QA problems.
+
## 13.12.12 (2021-09-21)
No changes.
diff --git a/Dangerfile b/Dangerfile
index 37a45674e16..212097f6a68 100644
--- a/Dangerfile
+++ b/Dangerfile
@@ -17,6 +17,21 @@ end
anything_to_post = status_report.values.any? { |data| data.any? }
-if helper.ci? && anything_to_post
+return unless helper.ci?
+
+def post_labels
+ gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
+ gitlab.mr_json['iid'],
+ add_labels: project_helper.labels_to_add.join(','))
+rescue Gitlab::Error::Forbidden
+ labels = project_helper.labels_to_add.map { |label| %Q(~"#{label}") }
+ warn("This Merge Request needs to be labelled with #{labels.join(' ')}. Please request a reviewer or maintainer to add them.")
+end
+
+if project_helper.labels_to_add.any?
+ post_labels
+end
+
+if anything_to_post
markdown("**If needed, you can retry the [`danger-review` job](#{ENV['CI_JOB_URL']}) that generated this comment.**")
end
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index afc1b70fc5c..397a7ea2e1d 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-14.4.2 \ No newline at end of file
+d69b465fdff3c04f8e3f395aed34aaa59f23fe76
diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION
index 72f51351fcd..d18453764c3 100644
--- a/GITLAB_KAS_VERSION
+++ b/GITLAB_KAS_VERSION
@@ -1 +1 @@
-14.4.0
+14.5.0
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 0a3db35b241..9db5ea12f52 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.46.0
+1.48.0
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index 12e42d263a9..70ca8545134 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-13.21.1
+13.22.0
diff --git a/Gemfile b/Gemfile
index 1e6648df48b..87a0cff84c1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -4,7 +4,7 @@ source 'https://rubygems.org'
gem 'rails', '~> 6.1.4.1'
-gem 'bootsnap', '~> 1.4.6'
+gem 'bootsnap', '~> 1.9.1', require: false
# Responders respond_to and respond_with
gem 'responders', '~> 3.0'
@@ -17,14 +17,14 @@ gem 'default_value_for', '~> 3.4.0'
# Supported DBs
gem 'pg', '~> 1.1'
-gem 'rugged', '~> 1.1'
+gem 'rugged', '~> 1.2'
gem 'grape-path-helpers', '~> 1.7.0'
gem 'faraday', '~> 1.0'
gem 'marginalia', '~> 1.10.0'
# Authorization
-gem 'declarative_policy', '~> 1.0.0'
+gem 'declarative_policy', '~> 1.1.0'
# Authentication libraries
gem 'devise', '~> 4.7.2'
@@ -38,6 +38,7 @@ gem 'omniauth-auth0', '~> 2.0.0'
gem 'omniauth-azure-activedirectory-v2', '~> 1.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9' # Deprecated v1 version
gem 'omniauth-cas3', '~> 1.1.4'
+gem 'omniauth-dingtalk-oauth2', '~> 1.0'
gem 'omniauth-facebook', '~> 4.0.0'
gem 'omniauth-github', '~> 1.4'
gem 'omniauth-gitlab', '~> 1.0.2'
@@ -129,7 +130,7 @@ gem 'fog-local', '~> 0.6'
gem 'fog-openstack', '~> 1.0'
gem 'fog-rackspace', '~> 0.1.1'
gem 'fog-aliyun', '~> 0.3'
-gem 'gitlab-fog-azure-rm', '~> 1.2.0', require: false
+gem 'gitlab-fog-azure-rm', '~> 1.2.0', require: 'fog/azurerm'
# for Google storage
gem 'google-api-client', '~> 0.33'
@@ -186,6 +187,7 @@ gem 'rack-timeout', '~> 0.5.1', require: 'rack/timeout/base'
group :puma do
gem 'puma', '~> 5.3.1', require: false
gem 'puma_worker_killer', '~> 0.3.1', require: false
+ gem 'sd_notify', '~> 0.1.0', require: false
end
# State machine
@@ -290,7 +292,7 @@ gem 'autoprefixer-rails', '10.2.5.1'
gem 'terser', '1.0.2'
gem 'addressable', '~> 2.8'
-gem 'gemojione', '~> 3.3'
+gem 'tanuki_emoji', '~> 0.5'
gem 'gon', '~> 6.4.0'
gem 'request_store', '~> 1.5'
gem 'base32', '~> 0.3.0'
@@ -341,13 +343,15 @@ group :development do
gem 'lefthook', '~> 0.7.0', require: false
gem 'solargraph', '~> 0.43', require: false
- gem 'letter_opener_web', '~> 1.4.1'
+ gem 'letter_opener_web', '~> 2.0.0'
# Better errors handler
gem 'better_errors', '~> 2.9.0'
# thin instead webrick
gem 'thin', '~> 1.8.0'
+
+ gem 'sprite-factory', '~> 1.7'
end
group :development, :test do
@@ -372,7 +376,7 @@ group :development, :test do
gem 'spring', '~> 2.1.0'
gem 'spring-commands-rspec', '~> 1.0.4'
- gem 'gitlab-styles', '~> 6.3.0', require: false
+ gem 'gitlab-styles', '~> 6.4.0', require: false
gem 'haml_lint', '~> 0.36.0', require: false
gem 'bundler-audit', '~> 0.7.0.1', require: false
@@ -396,7 +400,7 @@ group :development, :test do
end
group :development, :test, :danger do
- gem 'gitlab-dangerfiles', '~> 2.3.0', require: false
+ gem 'gitlab-dangerfiles', '~> 2.5.0', require: false
end
group :development, :test, :coverage do
@@ -474,7 +478,7 @@ end
gem 'spamcheck', '~> 0.1.0'
# Gitaly GRPC protocol definitions
-gem 'gitaly', '~> 14.3.0.pre.rc2'
+gem 'gitaly', '~> 14.4.0.pre.rc43'
# KAS GRPC protocol definitions
gem 'kas-grpc', '~> 0.0.2'
@@ -534,3 +538,5 @@ gem 'webauthn', '~> 2.3'
gem 'ipaddress', '~> 0.8.3'
gem 'parslet', '~> 1.8'
+
+gem 'ipynbdiff', '0.3.7'
diff --git a/Gemfile.lock b/Gemfile.lock
index a6b7f598ec6..270ea4532f9 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -148,7 +148,7 @@ GEM
rack (>= 0.9.0)
bindata (2.4.10)
binding_ninja (0.2.3)
- bootsnap (1.4.6)
+ bootsnap (1.9.1)
msgpack (~> 1.0)
bootstrap_form (4.2.0)
actionpack (>= 5.0)
@@ -222,7 +222,7 @@ GEM
css_parser (1.7.0)
addressable
daemons (1.3.1)
- danger (8.3.1)
+ danger (8.4.1)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
colored2 (~> 3.1)
@@ -244,7 +244,7 @@ GEM
html-pipeline
declarative (0.0.20)
declarative-option (0.1.0)
- declarative_policy (1.0.0)
+ declarative_policy (1.1.0)
default_value_for (3.4.0)
activerecord (>= 3.2.0, < 7.0)
deprecation_toolkit (1.5.1)
@@ -436,8 +436,6 @@ GEM
ruby-progressbar (~> 1.4)
fuzzyurl (0.9.0)
gemoji (3.0.1)
- gemojione (3.3.0)
- json
get_process_mem (0.2.5)
ffi (~> 1.0)
gettext (3.3.6)
@@ -452,7 +450,7 @@ GEM
rails (>= 3.2.0)
git (1.7.0)
rchardet (~> 1.8)
- gitaly (14.3.0.pre.rc2)
+ gitaly (14.4.0.pre.rc43)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab (4.16.1)
@@ -460,7 +458,7 @@ GEM
terminal-table (~> 1.5, >= 1.5.1)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
- gitlab-dangerfiles (2.3.0)
+ gitlab-dangerfiles (2.5.0)
danger (>= 8.3.1)
danger-gitlab (>= 8.0.0)
gitlab-experiment (0.6.4)
@@ -492,7 +490,7 @@ GEM
openid_connect (~> 1.2)
gitlab-sidekiq-fetcher (0.8.0)
sidekiq (~> 6.1)
- gitlab-styles (6.3.0)
+ gitlab-styles (6.4.0)
rubocop (~> 0.91, >= 0.91.1)
rubocop-gitlab-security (~> 0.1.1)
rubocop-performance (~> 1.9.2)
@@ -642,6 +640,9 @@ GEM
invisible_captcha (1.1.0)
rails (>= 4.2)
ipaddress (0.8.3)
+ ipynbdiff (0.3.7)
+ diffy (= 3.3.0)
+ json (= 2.5.1)
jaeger-client (1.1.0)
opentracing (~> 0.3)
thrift
@@ -699,10 +700,11 @@ GEM
lefthook (0.7.5)
letter_opener (1.7.0)
launchy (~> 2.2)
- letter_opener_web (1.4.1)
- actionmailer (>= 3.2)
- letter_opener (~> 1.0)
- railties (>= 3.2)
+ letter_opener_web (2.0.0)
+ actionmailer (>= 5.2)
+ letter_opener (~> 1.7)
+ railties (>= 5.2)
+ rexml
libyajl2 (1.2.0)
license_finder (6.0.0)
bundler
@@ -839,6 +841,8 @@ GEM
addressable (~> 2.3)
nokogiri (~> 1.7, >= 1.7.1)
omniauth (~> 1.2)
+ omniauth-dingtalk-oauth2 (1.0.0)
+ omniauth-oauth2 (~> 1.7.1)
omniauth-facebook (4.0.0)
omniauth-oauth2 (~> 1.2)
omniauth-github (1.4.0)
@@ -859,7 +863,7 @@ GEM
omniauth-oauth (1.1.0)
oauth
omniauth (~> 1.0)
- omniauth-oauth2 (1.7.1)
+ omniauth-oauth2 (1.7.2)
oauth2 (~> 1.4)
omniauth (>= 1.9, < 3)
omniauth-oauth2-generic (0.2.2)
@@ -1129,7 +1133,7 @@ GEM
rubyntlm (0.6.2)
rubypants (0.2.0)
rubyzip (2.0.0)
- rugged (1.1.0)
+ rugged (1.2.0)
safe_yaml (1.0.4)
safety_net_attestation (0.4.0)
jwt (~> 2.0)
@@ -1155,6 +1159,7 @@ GEM
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
scientist (1.6.0)
+ sd_notify (0.1.0)
securecompare (1.0.0)
seed-fu (2.3.7)
activerecord (>= 3.1)
@@ -1216,6 +1221,7 @@ GEM
spring (2.1.1)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
+ sprite-factory (1.7.1)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
@@ -1246,6 +1252,7 @@ GEM
sys-filesystem (1.1.9)
ffi
sysexits (1.2.0)
+ tanuki_emoji (0.5.0)
temple (0.8.2)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
@@ -1399,7 +1406,7 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0)
benchmark-memory (~> 0.1)
better_errors (~> 2.9.0)
- bootsnap (~> 1.4.6)
+ bootsnap (~> 1.9.1)
bootstrap_form (~> 4.2.0)
browser (~> 4.2)
bullet (~> 6.1.3)
@@ -1416,7 +1423,7 @@ DEPENDENCIES
crystalball (~> 0.7.0)
database_cleaner (~> 1.7.0)
deckar01-task_list (= 2.3.1)
- declarative_policy (~> 1.0.0)
+ declarative_policy (~> 1.1.0)
default_value_for (~> 3.4.0)
deprecation_toolkit (~> 1.5.1)
derailed_benchmarks
@@ -1454,14 +1461,13 @@ DEPENDENCIES
fog-rackspace (~> 0.1.1)
fugit (~> 1.2.1)
fuubar (~> 2.2.0)
- gemojione (~> 3.3)
gettext (~> 3.3)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly (~> 14.3.0.pre.rc2)
+ gitaly (~> 14.4.0.pre.rc43)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
- gitlab-dangerfiles (~> 2.3.0)
+ gitlab-dangerfiles (~> 2.5.0)
gitlab-experiment (~> 0.6.4)
gitlab-fog-azure-rm (~> 1.2.0)
gitlab-labkit (~> 0.21.1)
@@ -1471,7 +1477,7 @@ DEPENDENCIES
gitlab-net-dns (~> 0.9.1)
gitlab-omniauth-openid-connect (~> 0.8.0)
gitlab-sidekiq-fetcher (= 0.8.0)
- gitlab-styles (~> 6.3.0)
+ gitlab-styles (~> 6.4.0)
gitlab_chronic_duration (~> 0.10.6.2)
gitlab_omniauth-ldap (~> 2.1.1)
gon (~> 6.4.0)
@@ -1501,6 +1507,7 @@ DEPENDENCIES
icalendar
invisible_captcha (~> 1.1.0)
ipaddress (~> 0.8.3)
+ ipynbdiff (= 0.3.7)
jira-ruby (~> 2.1.4)
js_regex (~> 3.7)
json (~> 2.5.1)
@@ -1512,7 +1519,7 @@ DEPENDENCIES
kramdown (~> 2.3.1)
kubeclient (~> 4.9.2)
lefthook (~> 0.7.0)
- letter_opener_web (~> 1.4.1)
+ letter_opener_web (~> 2.0.0)
license_finder (~> 6.0)
licensee (~> 9.14.1)
lockbox (~> 0.6.2)
@@ -1542,6 +1549,7 @@ DEPENDENCIES
omniauth-azure-activedirectory-v2 (~> 1.0)
omniauth-azure-oauth2 (~> 0.0.9)
omniauth-cas3 (~> 1.1.4)
+ omniauth-dingtalk-oauth2 (~> 1.0)
omniauth-facebook (~> 4.0.0)
omniauth-github (~> 1.4)
omniauth-gitlab (~> 1.0.2)
@@ -1603,9 +1611,10 @@ DEPENDENCIES
ruby-saml (~> 1.13.0)
ruby_parser (~> 3.15)
rubyzip (~> 2.0.0)
- rugged (~> 1.1)
+ rugged (~> 1.2)
sanitize (~> 5.2.1)
sassc-rails (~> 2.1.0)
+ sd_notify (~> 0.1.0)
seed-fu (~> 2.3.7)
selenium-webdriver (~> 3.142)
sentry-raven (~> 3.1)
@@ -1622,11 +1631,13 @@ DEPENDENCIES
spamcheck (~> 0.1.0)
spring (~> 2.1.0)
spring-commands-rspec (~> 1.0.4)
+ sprite-factory (~> 1.7)
sprockets (~> 3.7.0)
sshkey (~> 2.0)
stackprof (~> 0.2.15)
state_machines-activerecord (~> 0.8.0)
sys-filesystem (~> 1.1.6)
+ tanuki_emoji (~> 0.5)
terser (= 1.0.2)
test-prof (~> 1.0.7)
test_file_finder (~> 0.1.3)
diff --git a/Guardfile b/Guardfile
index 1d9ec406c1d..66a689ed978 100644
--- a/Guardfile
+++ b/Guardfile
@@ -9,7 +9,7 @@ cmd = ENV['GUARD_CMD'] || (ENV['SPRING'] ? 'spring rspec' : 'bundle exec rspec')
directories %w(app ee lib rubocop tooling spec)
rspec_context_for = proc do |context_path|
- OpenStruct.new(to_s: "spec").tap do |rspec|
+ OpenStruct.new(to_s: "spec").tap do |rspec| # rubocop:disable Style/OpenStructUse
rspec.spec_dir = "#{context_path}spec"
rspec.spec = ->(m) { Guard::RSpec::Dsl.detect_spec_file_for(rspec, m) }
rspec.spec_helper = "#{rspec.spec_dir}/spec_helper.rb"
@@ -19,7 +19,7 @@ rspec_context_for = proc do |context_path|
end
rails_context_for = proc do |context_path, exts|
- OpenStruct.new.tap do |rails|
+ OpenStruct.new.tap do |rails| # rubocop:disable Style/OpenStructUse
rails.app_files = %r{^#{context_path}app/(.+)\.rb$}
rails.views = %r{^#{context_path}app/(views/.+/[^/]*\.(?:#{exts}))$}
diff --git a/README.md b/README.md
index f5ec329cd9e..64f19939ec2 100644
--- a/README.md
+++ b/README.md
@@ -71,7 +71,7 @@ To work on GitLab itself, we recommend setting up your development environment w
If you do not use the GitLab Development Kit you need to install and configure 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 Puma configuration file:
- cp config/puma.rb.example.development config/puma.rb
+ cp config/puma.example.development.rb config/puma.rb
Instructions on how to start GitLab and how to run the tests can be found in the [getting started section of the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit#getting-started).
diff --git a/app/assets/images/auth_buttons/dingtalk_64.png b/app/assets/images/auth_buttons/dingtalk_64.png
new file mode 100644
index 00000000000..77b3fa752bc
--- /dev/null
+++ b/app/assets/images/auth_buttons/dingtalk_64.png
Binary files differ
diff --git a/app/assets/images/emoji.png b/app/assets/images/emoji.png
index 723c2c3f4c8..bc5041a165b 100644
--- a/app/assets/images/emoji.png
+++ b/app/assets/images/emoji.png
Binary files differ
diff --git a/app/assets/images/emoji/100.png b/app/assets/images/emoji/100.png
deleted file mode 100644
index 6903ff0304a..00000000000
--- a/app/assets/images/emoji/100.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/1234.png b/app/assets/images/emoji/1234.png
deleted file mode 100644
index 248dc7e55b6..00000000000
--- a/app/assets/images/emoji/1234.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/8ball.png b/app/assets/images/emoji/8ball.png
deleted file mode 100644
index 38ca662eded..00000000000
--- a/app/assets/images/emoji/8ball.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/a.png b/app/assets/images/emoji/a.png
deleted file mode 100644
index 8603ff05a17..00000000000
--- a/app/assets/images/emoji/a.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ab.png b/app/assets/images/emoji/ab.png
deleted file mode 100644
index d9f2d17dea0..00000000000
--- a/app/assets/images/emoji/ab.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/abc.png b/app/assets/images/emoji/abc.png
deleted file mode 100644
index 7688de692a9..00000000000
--- a/app/assets/images/emoji/abc.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/abcd.png b/app/assets/images/emoji/abcd.png
deleted file mode 100644
index 0996a870570..00000000000
--- a/app/assets/images/emoji/abcd.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/accept.png b/app/assets/images/emoji/accept.png
deleted file mode 100644
index 8afd7ce99cf..00000000000
--- a/app/assets/images/emoji/accept.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/aerial_tramway.png b/app/assets/images/emoji/aerial_tramway.png
deleted file mode 100644
index 3eb4b61bf1d..00000000000
--- a/app/assets/images/emoji/aerial_tramway.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/airplane.png b/app/assets/images/emoji/airplane.png
deleted file mode 100644
index 268d2ac3c8e..00000000000
--- a/app/assets/images/emoji/airplane.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/airplane_arriving.png b/app/assets/images/emoji/airplane_arriving.png
deleted file mode 100644
index d66841962f2..00000000000
--- a/app/assets/images/emoji/airplane_arriving.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/airplane_departure.png b/app/assets/images/emoji/airplane_departure.png
deleted file mode 100644
index a5766f9f4ae..00000000000
--- a/app/assets/images/emoji/airplane_departure.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/airplane_small.png b/app/assets/images/emoji/airplane_small.png
deleted file mode 100644
index b731b15e3a8..00000000000
--- a/app/assets/images/emoji/airplane_small.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/alarm_clock.png b/app/assets/images/emoji/alarm_clock.png
deleted file mode 100644
index cdbc2fbb950..00000000000
--- a/app/assets/images/emoji/alarm_clock.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/alembic.png b/app/assets/images/emoji/alembic.png
deleted file mode 100644
index 307a7324249..00000000000
--- a/app/assets/images/emoji/alembic.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/alien.png b/app/assets/images/emoji/alien.png
deleted file mode 100644
index 3b90e97433b..00000000000
--- a/app/assets/images/emoji/alien.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ambulance.png b/app/assets/images/emoji/ambulance.png
deleted file mode 100644
index 6fb8076d766..00000000000
--- a/app/assets/images/emoji/ambulance.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/amphora.png b/app/assets/images/emoji/amphora.png
deleted file mode 100644
index 96de5056059..00000000000
--- a/app/assets/images/emoji/amphora.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/anchor.png b/app/assets/images/emoji/anchor.png
deleted file mode 100644
index b036f70a00b..00000000000
--- a/app/assets/images/emoji/anchor.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/angel.png b/app/assets/images/emoji/angel.png
deleted file mode 100644
index 66ea97a3b99..00000000000
--- a/app/assets/images/emoji/angel.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/angel_tone1.png b/app/assets/images/emoji/angel_tone1.png
deleted file mode 100644
index 391694dc07e..00000000000
--- a/app/assets/images/emoji/angel_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/angel_tone2.png b/app/assets/images/emoji/angel_tone2.png
deleted file mode 100644
index 700cbe6ed2c..00000000000
--- a/app/assets/images/emoji/angel_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/angel_tone3.png b/app/assets/images/emoji/angel_tone3.png
deleted file mode 100644
index be597437d25..00000000000
--- a/app/assets/images/emoji/angel_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/angel_tone4.png b/app/assets/images/emoji/angel_tone4.png
deleted file mode 100644
index b06d3c853ef..00000000000
--- a/app/assets/images/emoji/angel_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/angel_tone5.png b/app/assets/images/emoji/angel_tone5.png
deleted file mode 100644
index 17bd677e334..00000000000
--- a/app/assets/images/emoji/angel_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/anger.png b/app/assets/images/emoji/anger.png
deleted file mode 100644
index d63c2e000e4..00000000000
--- a/app/assets/images/emoji/anger.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/anger_right.png b/app/assets/images/emoji/anger_right.png
deleted file mode 100644
index f5c97c4d297..00000000000
--- a/app/assets/images/emoji/anger_right.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/angry.png b/app/assets/images/emoji/angry.png
deleted file mode 100644
index cfc4a6ecde5..00000000000
--- a/app/assets/images/emoji/angry.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ant.png b/app/assets/images/emoji/ant.png
deleted file mode 100644
index 994127ed6b3..00000000000
--- a/app/assets/images/emoji/ant.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/apple.png b/app/assets/images/emoji/apple.png
deleted file mode 100644
index da650c60f62..00000000000
--- a/app/assets/images/emoji/apple.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/aquarius.png b/app/assets/images/emoji/aquarius.png
deleted file mode 100644
index 641a4f68889..00000000000
--- a/app/assets/images/emoji/aquarius.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/aries.png b/app/assets/images/emoji/aries.png
deleted file mode 100644
index 21a189d0ede..00000000000
--- a/app/assets/images/emoji/aries.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_backward.png b/app/assets/images/emoji/arrow_backward.png
deleted file mode 100644
index ee38e3b038e..00000000000
--- a/app/assets/images/emoji/arrow_backward.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_double_down.png b/app/assets/images/emoji/arrow_double_down.png
deleted file mode 100644
index 90193bfcb40..00000000000
--- a/app/assets/images/emoji/arrow_double_down.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_double_up.png b/app/assets/images/emoji/arrow_double_up.png
deleted file mode 100644
index 13543d5eef2..00000000000
--- a/app/assets/images/emoji/arrow_double_up.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_down.png b/app/assets/images/emoji/arrow_down.png
deleted file mode 100644
index b8eefd0b19f..00000000000
--- a/app/assets/images/emoji/arrow_down.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_down_small.png b/app/assets/images/emoji/arrow_down_small.png
deleted file mode 100644
index 5870b9a2241..00000000000
--- a/app/assets/images/emoji/arrow_down_small.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_forward.png b/app/assets/images/emoji/arrow_forward.png
deleted file mode 100644
index 4e2b682857c..00000000000
--- a/app/assets/images/emoji/arrow_forward.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_heading_down.png b/app/assets/images/emoji/arrow_heading_down.png
deleted file mode 100644
index 2d9d24bca80..00000000000
--- a/app/assets/images/emoji/arrow_heading_down.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_heading_up.png b/app/assets/images/emoji/arrow_heading_up.png
deleted file mode 100644
index f29bfcfc0de..00000000000
--- a/app/assets/images/emoji/arrow_heading_up.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_left.png b/app/assets/images/emoji/arrow_left.png
deleted file mode 100644
index 8c685e0a81b..00000000000
--- a/app/assets/images/emoji/arrow_left.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_lower_left.png b/app/assets/images/emoji/arrow_lower_left.png
deleted file mode 100644
index 88b37716078..00000000000
--- a/app/assets/images/emoji/arrow_lower_left.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_lower_right.png b/app/assets/images/emoji/arrow_lower_right.png
deleted file mode 100644
index 7e807da7392..00000000000
--- a/app/assets/images/emoji/arrow_lower_right.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_right.png b/app/assets/images/emoji/arrow_right.png
deleted file mode 100644
index 4755670b5cc..00000000000
--- a/app/assets/images/emoji/arrow_right.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_right_hook.png b/app/assets/images/emoji/arrow_right_hook.png
deleted file mode 100644
index e7258ad3268..00000000000
--- a/app/assets/images/emoji/arrow_right_hook.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_up.png b/app/assets/images/emoji/arrow_up.png
deleted file mode 100644
index af8218a87f7..00000000000
--- a/app/assets/images/emoji/arrow_up.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_up_down.png b/app/assets/images/emoji/arrow_up_down.png
deleted file mode 100644
index dfa32b97186..00000000000
--- a/app/assets/images/emoji/arrow_up_down.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_up_small.png b/app/assets/images/emoji/arrow_up_small.png
deleted file mode 100644
index 20a13dcd5cd..00000000000
--- a/app/assets/images/emoji/arrow_up_small.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_upper_left.png b/app/assets/images/emoji/arrow_upper_left.png
deleted file mode 100644
index f38718fbe34..00000000000
--- a/app/assets/images/emoji/arrow_upper_left.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrow_upper_right.png b/app/assets/images/emoji/arrow_upper_right.png
deleted file mode 100644
index c43e12d0f64..00000000000
--- a/app/assets/images/emoji/arrow_upper_right.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrows_clockwise.png b/app/assets/images/emoji/arrows_clockwise.png
deleted file mode 100644
index 26e49c38388..00000000000
--- a/app/assets/images/emoji/arrows_clockwise.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/arrows_counterclockwise.png b/app/assets/images/emoji/arrows_counterclockwise.png
deleted file mode 100644
index 8d06d8e0912..00000000000
--- a/app/assets/images/emoji/arrows_counterclockwise.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/art.png b/app/assets/images/emoji/art.png
deleted file mode 100644
index bd6afe9ff06..00000000000
--- a/app/assets/images/emoji/art.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/articulated_lorry.png b/app/assets/images/emoji/articulated_lorry.png
deleted file mode 100644
index c8217317132..00000000000
--- a/app/assets/images/emoji/articulated_lorry.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/asterisk.png b/app/assets/images/emoji/asterisk.png
deleted file mode 100644
index 2f8e5113803..00000000000
--- a/app/assets/images/emoji/asterisk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/astonished.png b/app/assets/images/emoji/astonished.png
deleted file mode 100644
index bd0ac55ec8e..00000000000
--- a/app/assets/images/emoji/astonished.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/athletic_shoe.png b/app/assets/images/emoji/athletic_shoe.png
deleted file mode 100644
index 423fa07dd5d..00000000000
--- a/app/assets/images/emoji/athletic_shoe.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/atm.png b/app/assets/images/emoji/atm.png
deleted file mode 100644
index 4d935307b94..00000000000
--- a/app/assets/images/emoji/atm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/atom.png b/app/assets/images/emoji/atom.png
deleted file mode 100644
index 5f4567aa093..00000000000
--- a/app/assets/images/emoji/atom.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/avocado.png b/app/assets/images/emoji/avocado.png
deleted file mode 100644
index 06f0d124aed..00000000000
--- a/app/assets/images/emoji/avocado.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/b.png b/app/assets/images/emoji/b.png
deleted file mode 100644
index 25875bc6a14..00000000000
--- a/app/assets/images/emoji/b.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/baby.png b/app/assets/images/emoji/baby.png
deleted file mode 100644
index a4af92c63c7..00000000000
--- a/app/assets/images/emoji/baby.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/baby_bottle.png b/app/assets/images/emoji/baby_bottle.png
deleted file mode 100644
index 2bd10524180..00000000000
--- a/app/assets/images/emoji/baby_bottle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/baby_chick.png b/app/assets/images/emoji/baby_chick.png
deleted file mode 100644
index dccd96576ea..00000000000
--- a/app/assets/images/emoji/baby_chick.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/baby_symbol.png b/app/assets/images/emoji/baby_symbol.png
deleted file mode 100644
index 64a10b71710..00000000000
--- a/app/assets/images/emoji/baby_symbol.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/baby_tone1.png b/app/assets/images/emoji/baby_tone1.png
deleted file mode 100644
index d20911d40db..00000000000
--- a/app/assets/images/emoji/baby_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/baby_tone2.png b/app/assets/images/emoji/baby_tone2.png
deleted file mode 100644
index b0a9b30ed17..00000000000
--- a/app/assets/images/emoji/baby_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/baby_tone3.png b/app/assets/images/emoji/baby_tone3.png
deleted file mode 100644
index 7de5286fac1..00000000000
--- a/app/assets/images/emoji/baby_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/baby_tone4.png b/app/assets/images/emoji/baby_tone4.png
deleted file mode 100644
index 9b7a86ac615..00000000000
--- a/app/assets/images/emoji/baby_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/baby_tone5.png b/app/assets/images/emoji/baby_tone5.png
deleted file mode 100644
index fe1be34cb88..00000000000
--- a/app/assets/images/emoji/baby_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/back.png b/app/assets/images/emoji/back.png
deleted file mode 100644
index d32c5d4f17f..00000000000
--- a/app/assets/images/emoji/back.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bacon.png b/app/assets/images/emoji/bacon.png
deleted file mode 100644
index f38a485fbe4..00000000000
--- a/app/assets/images/emoji/bacon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/badminton.png b/app/assets/images/emoji/badminton.png
deleted file mode 100644
index 7ba15708990..00000000000
--- a/app/assets/images/emoji/badminton.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/baggage_claim.png b/app/assets/images/emoji/baggage_claim.png
deleted file mode 100644
index 409b593e78a..00000000000
--- a/app/assets/images/emoji/baggage_claim.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/balloon.png b/app/assets/images/emoji/balloon.png
deleted file mode 100644
index 07916fe6df1..00000000000
--- a/app/assets/images/emoji/balloon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ballot_box.png b/app/assets/images/emoji/ballot_box.png
deleted file mode 100644
index 9b6767aea9e..00000000000
--- a/app/assets/images/emoji/ballot_box.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ballot_box_with_check.png b/app/assets/images/emoji/ballot_box_with_check.png
deleted file mode 100644
index 284d9573847..00000000000
--- a/app/assets/images/emoji/ballot_box_with_check.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bamboo.png b/app/assets/images/emoji/bamboo.png
deleted file mode 100644
index 5d5e0e728a0..00000000000
--- a/app/assets/images/emoji/bamboo.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/banana.png b/app/assets/images/emoji/banana.png
deleted file mode 100644
index f4987279580..00000000000
--- a/app/assets/images/emoji/banana.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bangbang.png b/app/assets/images/emoji/bangbang.png
deleted file mode 100644
index 58a9c528fca..00000000000
--- a/app/assets/images/emoji/bangbang.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bank.png b/app/assets/images/emoji/bank.png
deleted file mode 100644
index dffdcef36a1..00000000000
--- a/app/assets/images/emoji/bank.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bar_chart.png b/app/assets/images/emoji/bar_chart.png
deleted file mode 100644
index 53c89455008..00000000000
--- a/app/assets/images/emoji/bar_chart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/barber.png b/app/assets/images/emoji/barber.png
deleted file mode 100644
index 896f4d716cf..00000000000
--- a/app/assets/images/emoji/barber.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/baseball.png b/app/assets/images/emoji/baseball.png
deleted file mode 100644
index f8463f1538b..00000000000
--- a/app/assets/images/emoji/baseball.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/basketball.png b/app/assets/images/emoji/basketball.png
deleted file mode 100644
index 64c76b79c6d..00000000000
--- a/app/assets/images/emoji/basketball.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/basketball_player.png b/app/assets/images/emoji/basketball_player.png
deleted file mode 100644
index 8ce90c5cad6..00000000000
--- a/app/assets/images/emoji/basketball_player.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/basketball_player_tone1.png b/app/assets/images/emoji/basketball_player_tone1.png
deleted file mode 100644
index cd12c7ab9bf..00000000000
--- a/app/assets/images/emoji/basketball_player_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/basketball_player_tone2.png b/app/assets/images/emoji/basketball_player_tone2.png
deleted file mode 100644
index f892fd596da..00000000000
--- a/app/assets/images/emoji/basketball_player_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/basketball_player_tone3.png b/app/assets/images/emoji/basketball_player_tone3.png
deleted file mode 100644
index e109997a91a..00000000000
--- a/app/assets/images/emoji/basketball_player_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/basketball_player_tone4.png b/app/assets/images/emoji/basketball_player_tone4.png
deleted file mode 100644
index 3b90b946af4..00000000000
--- a/app/assets/images/emoji/basketball_player_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/basketball_player_tone5.png b/app/assets/images/emoji/basketball_player_tone5.png
deleted file mode 100644
index bafed7828a7..00000000000
--- a/app/assets/images/emoji/basketball_player_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bat.png b/app/assets/images/emoji/bat.png
deleted file mode 100644
index 3152c047e00..00000000000
--- a/app/assets/images/emoji/bat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bath.png b/app/assets/images/emoji/bath.png
deleted file mode 100644
index 43fba5c8a28..00000000000
--- a/app/assets/images/emoji/bath.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bath_tone1.png b/app/assets/images/emoji/bath_tone1.png
deleted file mode 100644
index 2152eabf2f5..00000000000
--- a/app/assets/images/emoji/bath_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bath_tone2.png b/app/assets/images/emoji/bath_tone2.png
deleted file mode 100644
index 2102e6133e3..00000000000
--- a/app/assets/images/emoji/bath_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bath_tone3.png b/app/assets/images/emoji/bath_tone3.png
deleted file mode 100644
index fae66181e9f..00000000000
--- a/app/assets/images/emoji/bath_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bath_tone4.png b/app/assets/images/emoji/bath_tone4.png
deleted file mode 100644
index 1f8959d0d99..00000000000
--- a/app/assets/images/emoji/bath_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bath_tone5.png b/app/assets/images/emoji/bath_tone5.png
deleted file mode 100644
index c8a08e84f25..00000000000
--- a/app/assets/images/emoji/bath_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bathtub.png b/app/assets/images/emoji/bathtub.png
deleted file mode 100644
index 9a5f09361eb..00000000000
--- a/app/assets/images/emoji/bathtub.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/battery.png b/app/assets/images/emoji/battery.png
deleted file mode 100644
index f593e2bdb65..00000000000
--- a/app/assets/images/emoji/battery.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/beach.png b/app/assets/images/emoji/beach.png
deleted file mode 100644
index 69108c8ea10..00000000000
--- a/app/assets/images/emoji/beach.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/beach_umbrella.png b/app/assets/images/emoji/beach_umbrella.png
deleted file mode 100644
index 220a74f8132..00000000000
--- a/app/assets/images/emoji/beach_umbrella.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bear.png b/app/assets/images/emoji/bear.png
deleted file mode 100644
index 272d56bbbcc..00000000000
--- a/app/assets/images/emoji/bear.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bed.png b/app/assets/images/emoji/bed.png
deleted file mode 100644
index 86f964e245d..00000000000
--- a/app/assets/images/emoji/bed.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bee.png b/app/assets/images/emoji/bee.png
deleted file mode 100644
index 46156060096..00000000000
--- a/app/assets/images/emoji/bee.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/beer.png b/app/assets/images/emoji/beer.png
deleted file mode 100644
index b6d73dc0b7a..00000000000
--- a/app/assets/images/emoji/beer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/beers.png b/app/assets/images/emoji/beers.png
deleted file mode 100644
index b55deb66b41..00000000000
--- a/app/assets/images/emoji/beers.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/beetle.png b/app/assets/images/emoji/beetle.png
deleted file mode 100644
index 3d93174d7fc..00000000000
--- a/app/assets/images/emoji/beetle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/beginner.png b/app/assets/images/emoji/beginner.png
deleted file mode 100644
index bc434fb7cb5..00000000000
--- a/app/assets/images/emoji/beginner.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bell.png b/app/assets/images/emoji/bell.png
deleted file mode 100644
index 5b3b0461999..00000000000
--- a/app/assets/images/emoji/bell.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bellhop.png b/app/assets/images/emoji/bellhop.png
deleted file mode 100644
index 6b3297ceaf7..00000000000
--- a/app/assets/images/emoji/bellhop.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bento.png b/app/assets/images/emoji/bento.png
deleted file mode 100644
index 83d41ca7eb9..00000000000
--- a/app/assets/images/emoji/bento.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bicyclist.png b/app/assets/images/emoji/bicyclist.png
deleted file mode 100644
index 9274da11048..00000000000
--- a/app/assets/images/emoji/bicyclist.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bicyclist_tone1.png b/app/assets/images/emoji/bicyclist_tone1.png
deleted file mode 100644
index decc2f728fe..00000000000
--- a/app/assets/images/emoji/bicyclist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bicyclist_tone2.png b/app/assets/images/emoji/bicyclist_tone2.png
deleted file mode 100644
index 0067717b80a..00000000000
--- a/app/assets/images/emoji/bicyclist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bicyclist_tone3.png b/app/assets/images/emoji/bicyclist_tone3.png
deleted file mode 100644
index a4f7b5e2776..00000000000
--- a/app/assets/images/emoji/bicyclist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bicyclist_tone4.png b/app/assets/images/emoji/bicyclist_tone4.png
deleted file mode 100644
index a3c8a797db4..00000000000
--- a/app/assets/images/emoji/bicyclist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bicyclist_tone5.png b/app/assets/images/emoji/bicyclist_tone5.png
deleted file mode 100644
index 1606a874051..00000000000
--- a/app/assets/images/emoji/bicyclist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bike.png b/app/assets/images/emoji/bike.png
deleted file mode 100644
index 556ed70f1a7..00000000000
--- a/app/assets/images/emoji/bike.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bikini.png b/app/assets/images/emoji/bikini.png
deleted file mode 100644
index 77a8a0aae5b..00000000000
--- a/app/assets/images/emoji/bikini.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/biohazard.png b/app/assets/images/emoji/biohazard.png
deleted file mode 100644
index 007b4fc2d85..00000000000
--- a/app/assets/images/emoji/biohazard.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bird.png b/app/assets/images/emoji/bird.png
deleted file mode 100644
index e201c22be33..00000000000
--- a/app/assets/images/emoji/bird.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/birthday.png b/app/assets/images/emoji/birthday.png
deleted file mode 100644
index 317e9a41949..00000000000
--- a/app/assets/images/emoji/birthday.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/black_circle.png b/app/assets/images/emoji/black_circle.png
deleted file mode 100644
index b62b87170e8..00000000000
--- a/app/assets/images/emoji/black_circle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/black_heart.png b/app/assets/images/emoji/black_heart.png
deleted file mode 100644
index b4068c3e6e8..00000000000
--- a/app/assets/images/emoji/black_heart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/black_joker.png b/app/assets/images/emoji/black_joker.png
deleted file mode 100644
index 3d0924b68aa..00000000000
--- a/app/assets/images/emoji/black_joker.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/black_large_square.png b/app/assets/images/emoji/black_large_square.png
deleted file mode 100644
index 162f2bb4290..00000000000
--- a/app/assets/images/emoji/black_large_square.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/black_medium_small_square.png b/app/assets/images/emoji/black_medium_small_square.png
deleted file mode 100644
index 39765bba610..00000000000
--- a/app/assets/images/emoji/black_medium_small_square.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/black_medium_square.png b/app/assets/images/emoji/black_medium_square.png
deleted file mode 100644
index 05a30a6aa2d..00000000000
--- a/app/assets/images/emoji/black_medium_square.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/black_nib.png b/app/assets/images/emoji/black_nib.png
deleted file mode 100644
index 872d0ae1598..00000000000
--- a/app/assets/images/emoji/black_nib.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/black_small_square.png b/app/assets/images/emoji/black_small_square.png
deleted file mode 100644
index 48595d3e1a9..00000000000
--- a/app/assets/images/emoji/black_small_square.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/black_square_button.png b/app/assets/images/emoji/black_square_button.png
deleted file mode 100644
index a78fc2f6b63..00000000000
--- a/app/assets/images/emoji/black_square_button.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/blossom.png b/app/assets/images/emoji/blossom.png
deleted file mode 100644
index 4083026c157..00000000000
--- a/app/assets/images/emoji/blossom.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/blowfish.png b/app/assets/images/emoji/blowfish.png
deleted file mode 100644
index a10f4f84e35..00000000000
--- a/app/assets/images/emoji/blowfish.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/blue_book.png b/app/assets/images/emoji/blue_book.png
deleted file mode 100644
index e1e455401cc..00000000000
--- a/app/assets/images/emoji/blue_book.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/blue_car.png b/app/assets/images/emoji/blue_car.png
deleted file mode 100644
index e8ba817d393..00000000000
--- a/app/assets/images/emoji/blue_car.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/blue_heart.png b/app/assets/images/emoji/blue_heart.png
deleted file mode 100644
index bdf1287e55e..00000000000
--- a/app/assets/images/emoji/blue_heart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/blush.png b/app/assets/images/emoji/blush.png
deleted file mode 100644
index aac1a424ad4..00000000000
--- a/app/assets/images/emoji/blush.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/boar.png b/app/assets/images/emoji/boar.png
deleted file mode 100644
index fead972633c..00000000000
--- a/app/assets/images/emoji/boar.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bomb.png b/app/assets/images/emoji/bomb.png
deleted file mode 100644
index c7f8f81c939..00000000000
--- a/app/assets/images/emoji/bomb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/book.png b/app/assets/images/emoji/book.png
deleted file mode 100644
index 0f4447ed396..00000000000
--- a/app/assets/images/emoji/book.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bookmark.png b/app/assets/images/emoji/bookmark.png
deleted file mode 100644
index bbb444611f0..00000000000
--- a/app/assets/images/emoji/bookmark.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bookmark_tabs.png b/app/assets/images/emoji/bookmark_tabs.png
deleted file mode 100644
index f8d9e01b428..00000000000
--- a/app/assets/images/emoji/bookmark_tabs.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/books.png b/app/assets/images/emoji/books.png
deleted file mode 100644
index 59a8bafeb0d..00000000000
--- a/app/assets/images/emoji/books.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/boom.png b/app/assets/images/emoji/boom.png
deleted file mode 100644
index 9b0f027b1a8..00000000000
--- a/app/assets/images/emoji/boom.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/boot.png b/app/assets/images/emoji/boot.png
deleted file mode 100644
index 11f1065ed07..00000000000
--- a/app/assets/images/emoji/boot.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bouquet.png b/app/assets/images/emoji/bouquet.png
deleted file mode 100644
index 11455af6df4..00000000000
--- a/app/assets/images/emoji/bouquet.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bow.png b/app/assets/images/emoji/bow.png
deleted file mode 100644
index d8f793088dc..00000000000
--- a/app/assets/images/emoji/bow.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bow_and_arrow.png b/app/assets/images/emoji/bow_and_arrow.png
deleted file mode 100644
index 6a538bf475f..00000000000
--- a/app/assets/images/emoji/bow_and_arrow.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bow_tone1.png b/app/assets/images/emoji/bow_tone1.png
deleted file mode 100644
index 87afb7b54cf..00000000000
--- a/app/assets/images/emoji/bow_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bow_tone2.png b/app/assets/images/emoji/bow_tone2.png
deleted file mode 100644
index 3ccf7dc0850..00000000000
--- a/app/assets/images/emoji/bow_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bow_tone3.png b/app/assets/images/emoji/bow_tone3.png
deleted file mode 100644
index 8b9eb64f926..00000000000
--- a/app/assets/images/emoji/bow_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bow_tone4.png b/app/assets/images/emoji/bow_tone4.png
deleted file mode 100644
index 683795ff40d..00000000000
--- a/app/assets/images/emoji/bow_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bow_tone5.png b/app/assets/images/emoji/bow_tone5.png
deleted file mode 100644
index 7969d971752..00000000000
--- a/app/assets/images/emoji/bow_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bowling.png b/app/assets/images/emoji/bowling.png
deleted file mode 100644
index 63add89e53b..00000000000
--- a/app/assets/images/emoji/bowling.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/boxing_glove.png b/app/assets/images/emoji/boxing_glove.png
deleted file mode 100644
index 9838f24e51a..00000000000
--- a/app/assets/images/emoji/boxing_glove.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/boy.png b/app/assets/images/emoji/boy.png
deleted file mode 100644
index 8ecfb0a4e92..00000000000
--- a/app/assets/images/emoji/boy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/boy_tone1.png b/app/assets/images/emoji/boy_tone1.png
deleted file mode 100644
index 2fc436ea512..00000000000
--- a/app/assets/images/emoji/boy_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/boy_tone2.png b/app/assets/images/emoji/boy_tone2.png
deleted file mode 100644
index 09a5f18d360..00000000000
--- a/app/assets/images/emoji/boy_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/boy_tone3.png b/app/assets/images/emoji/boy_tone3.png
deleted file mode 100644
index 3cfe675dd3a..00000000000
--- a/app/assets/images/emoji/boy_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/boy_tone4.png b/app/assets/images/emoji/boy_tone4.png
deleted file mode 100644
index 780be0ace36..00000000000
--- a/app/assets/images/emoji/boy_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/boy_tone5.png b/app/assets/images/emoji/boy_tone5.png
deleted file mode 100644
index f32fe22e35c..00000000000
--- a/app/assets/images/emoji/boy_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bread.png b/app/assets/images/emoji/bread.png
deleted file mode 100644
index 6676510aaa5..00000000000
--- a/app/assets/images/emoji/bread.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bride_with_veil.png b/app/assets/images/emoji/bride_with_veil.png
deleted file mode 100644
index eaf4bd97890..00000000000
--- a/app/assets/images/emoji/bride_with_veil.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bride_with_veil_tone1.png b/app/assets/images/emoji/bride_with_veil_tone1.png
deleted file mode 100644
index c4fb141ae8f..00000000000
--- a/app/assets/images/emoji/bride_with_veil_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bride_with_veil_tone2.png b/app/assets/images/emoji/bride_with_veil_tone2.png
deleted file mode 100644
index c248769fc06..00000000000
--- a/app/assets/images/emoji/bride_with_veil_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bride_with_veil_tone3.png b/app/assets/images/emoji/bride_with_veil_tone3.png
deleted file mode 100644
index 962c0a6eedb..00000000000
--- a/app/assets/images/emoji/bride_with_veil_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bride_with_veil_tone4.png b/app/assets/images/emoji/bride_with_veil_tone4.png
deleted file mode 100644
index 740ca208cd4..00000000000
--- a/app/assets/images/emoji/bride_with_veil_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bride_with_veil_tone5.png b/app/assets/images/emoji/bride_with_veil_tone5.png
deleted file mode 100644
index 5cc5598587d..00000000000
--- a/app/assets/images/emoji/bride_with_veil_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bridge_at_night.png b/app/assets/images/emoji/bridge_at_night.png
deleted file mode 100644
index 1d444e0be65..00000000000
--- a/app/assets/images/emoji/bridge_at_night.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/briefcase.png b/app/assets/images/emoji/briefcase.png
deleted file mode 100644
index b9912ba2148..00000000000
--- a/app/assets/images/emoji/briefcase.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/broken_heart.png b/app/assets/images/emoji/broken_heart.png
deleted file mode 100644
index 718e26ee122..00000000000
--- a/app/assets/images/emoji/broken_heart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bug.png b/app/assets/images/emoji/bug.png
deleted file mode 100644
index e64e72f259a..00000000000
--- a/app/assets/images/emoji/bug.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bulb.png b/app/assets/images/emoji/bulb.png
deleted file mode 100644
index 38e32e02d9f..00000000000
--- a/app/assets/images/emoji/bulb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bullettrain_front.png b/app/assets/images/emoji/bullettrain_front.png
deleted file mode 100644
index 4f698e056fa..00000000000
--- a/app/assets/images/emoji/bullettrain_front.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bullettrain_side.png b/app/assets/images/emoji/bullettrain_side.png
deleted file mode 100644
index ed61c67bf07..00000000000
--- a/app/assets/images/emoji/bullettrain_side.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/burrito.png b/app/assets/images/emoji/burrito.png
deleted file mode 100644
index 02bd5601df7..00000000000
--- a/app/assets/images/emoji/burrito.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bus.png b/app/assets/images/emoji/bus.png
deleted file mode 100644
index 641ddc56ca7..00000000000
--- a/app/assets/images/emoji/bus.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/busstop.png b/app/assets/images/emoji/busstop.png
deleted file mode 100644
index b2b62208bfd..00000000000
--- a/app/assets/images/emoji/busstop.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/bust_in_silhouette.png b/app/assets/images/emoji/bust_in_silhouette.png
deleted file mode 100644
index 123b2cbe1fb..00000000000
--- a/app/assets/images/emoji/bust_in_silhouette.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/busts_in_silhouette.png b/app/assets/images/emoji/busts_in_silhouette.png
deleted file mode 100644
index d7656860a1c..00000000000
--- a/app/assets/images/emoji/busts_in_silhouette.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/butterfly.png b/app/assets/images/emoji/butterfly.png
deleted file mode 100644
index 5631fe99226..00000000000
--- a/app/assets/images/emoji/butterfly.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cactus.png b/app/assets/images/emoji/cactus.png
deleted file mode 100644
index 9b48ccf3d0c..00000000000
--- a/app/assets/images/emoji/cactus.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cake.png b/app/assets/images/emoji/cake.png
deleted file mode 100644
index 4368177be9a..00000000000
--- a/app/assets/images/emoji/cake.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/calendar.png b/app/assets/images/emoji/calendar.png
deleted file mode 100644
index 47353b74447..00000000000
--- a/app/assets/images/emoji/calendar.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/calendar_spiral.png b/app/assets/images/emoji/calendar_spiral.png
deleted file mode 100644
index dec8d49bfa8..00000000000
--- a/app/assets/images/emoji/calendar_spiral.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/call_me.png b/app/assets/images/emoji/call_me.png
deleted file mode 100644
index a10c59ba711..00000000000
--- a/app/assets/images/emoji/call_me.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/call_me_tone1.png b/app/assets/images/emoji/call_me_tone1.png
deleted file mode 100644
index 2c93201181a..00000000000
--- a/app/assets/images/emoji/call_me_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/call_me_tone2.png b/app/assets/images/emoji/call_me_tone2.png
deleted file mode 100644
index c39f45a41ed..00000000000
--- a/app/assets/images/emoji/call_me_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/call_me_tone3.png b/app/assets/images/emoji/call_me_tone3.png
deleted file mode 100644
index 83a57f63c29..00000000000
--- a/app/assets/images/emoji/call_me_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/call_me_tone4.png b/app/assets/images/emoji/call_me_tone4.png
deleted file mode 100644
index 65b3468fe44..00000000000
--- a/app/assets/images/emoji/call_me_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/call_me_tone5.png b/app/assets/images/emoji/call_me_tone5.png
deleted file mode 100644
index 94ef68ff3b3..00000000000
--- a/app/assets/images/emoji/call_me_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/calling.png b/app/assets/images/emoji/calling.png
deleted file mode 100644
index e2f308f8e46..00000000000
--- a/app/assets/images/emoji/calling.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/camel.png b/app/assets/images/emoji/camel.png
deleted file mode 100644
index b421d07a805..00000000000
--- a/app/assets/images/emoji/camel.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/camera.png b/app/assets/images/emoji/camera.png
deleted file mode 100644
index 0a3429f72ef..00000000000
--- a/app/assets/images/emoji/camera.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/camera_with_flash.png b/app/assets/images/emoji/camera_with_flash.png
deleted file mode 100644
index 27471da2029..00000000000
--- a/app/assets/images/emoji/camera_with_flash.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/camping.png b/app/assets/images/emoji/camping.png
deleted file mode 100644
index d589cc1f44b..00000000000
--- a/app/assets/images/emoji/camping.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cancer.png b/app/assets/images/emoji/cancer.png
deleted file mode 100644
index a64af07cb5f..00000000000
--- a/app/assets/images/emoji/cancer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/candle.png b/app/assets/images/emoji/candle.png
deleted file mode 100644
index 0b56444e355..00000000000
--- a/app/assets/images/emoji/candle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/candy.png b/app/assets/images/emoji/candy.png
deleted file mode 100644
index 8c67ace3a35..00000000000
--- a/app/assets/images/emoji/candy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/canoe.png b/app/assets/images/emoji/canoe.png
deleted file mode 100644
index e26cdb9da69..00000000000
--- a/app/assets/images/emoji/canoe.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/capital_abcd.png b/app/assets/images/emoji/capital_abcd.png
deleted file mode 100644
index fe9482d2d8a..00000000000
--- a/app/assets/images/emoji/capital_abcd.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/capricorn.png b/app/assets/images/emoji/capricorn.png
deleted file mode 100644
index 6293d31d4b1..00000000000
--- a/app/assets/images/emoji/capricorn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/card_box.png b/app/assets/images/emoji/card_box.png
deleted file mode 100644
index f2e764ce59d..00000000000
--- a/app/assets/images/emoji/card_box.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/card_index.png b/app/assets/images/emoji/card_index.png
deleted file mode 100644
index 151e11cb3b4..00000000000
--- a/app/assets/images/emoji/card_index.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/carousel_horse.png b/app/assets/images/emoji/carousel_horse.png
deleted file mode 100644
index a17074edf05..00000000000
--- a/app/assets/images/emoji/carousel_horse.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/carrot.png b/app/assets/images/emoji/carrot.png
deleted file mode 100644
index c68829b58e7..00000000000
--- a/app/assets/images/emoji/carrot.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cartwheel.png b/app/assets/images/emoji/cartwheel.png
deleted file mode 100644
index cbcaa578253..00000000000
--- a/app/assets/images/emoji/cartwheel.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cartwheel_tone1.png b/app/assets/images/emoji/cartwheel_tone1.png
deleted file mode 100644
index db6d65895fb..00000000000
--- a/app/assets/images/emoji/cartwheel_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cartwheel_tone2.png b/app/assets/images/emoji/cartwheel_tone2.png
deleted file mode 100644
index e00ffbc27a8..00000000000
--- a/app/assets/images/emoji/cartwheel_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cartwheel_tone3.png b/app/assets/images/emoji/cartwheel_tone3.png
deleted file mode 100644
index 49321be391f..00000000000
--- a/app/assets/images/emoji/cartwheel_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cartwheel_tone4.png b/app/assets/images/emoji/cartwheel_tone4.png
deleted file mode 100644
index d4562b5e3dd..00000000000
--- a/app/assets/images/emoji/cartwheel_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cartwheel_tone5.png b/app/assets/images/emoji/cartwheel_tone5.png
deleted file mode 100644
index 6e09a870767..00000000000
--- a/app/assets/images/emoji/cartwheel_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cat.png b/app/assets/images/emoji/cat.png
deleted file mode 100644
index efd82c2abf3..00000000000
--- a/app/assets/images/emoji/cat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cat2.png b/app/assets/images/emoji/cat2.png
deleted file mode 100644
index 46abe8cbc14..00000000000
--- a/app/assets/images/emoji/cat2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cd.png b/app/assets/images/emoji/cd.png
deleted file mode 100644
index e6b01449cd9..00000000000
--- a/app/assets/images/emoji/cd.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/chains.png b/app/assets/images/emoji/chains.png
deleted file mode 100644
index 57f46139a06..00000000000
--- a/app/assets/images/emoji/chains.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/champagne.png b/app/assets/images/emoji/champagne.png
deleted file mode 100644
index 285a79a93d0..00000000000
--- a/app/assets/images/emoji/champagne.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/champagne_glass.png b/app/assets/images/emoji/champagne_glass.png
deleted file mode 100644
index 31937ae9392..00000000000
--- a/app/assets/images/emoji/champagne_glass.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/chart.png b/app/assets/images/emoji/chart.png
deleted file mode 100644
index 9773f03be22..00000000000
--- a/app/assets/images/emoji/chart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/chart_with_downwards_trend.png b/app/assets/images/emoji/chart_with_downwards_trend.png
deleted file mode 100644
index 5222ec72d85..00000000000
--- a/app/assets/images/emoji/chart_with_downwards_trend.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/chart_with_upwards_trend.png b/app/assets/images/emoji/chart_with_upwards_trend.png
deleted file mode 100644
index f13cfcf9956..00000000000
--- a/app/assets/images/emoji/chart_with_upwards_trend.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/checkered_flag.png b/app/assets/images/emoji/checkered_flag.png
deleted file mode 100644
index 5a71eecb89b..00000000000
--- a/app/assets/images/emoji/checkered_flag.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cheese.png b/app/assets/images/emoji/cheese.png
deleted file mode 100644
index 00e99762286..00000000000
--- a/app/assets/images/emoji/cheese.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cherries.png b/app/assets/images/emoji/cherries.png
deleted file mode 100644
index 9b10cbaac5e..00000000000
--- a/app/assets/images/emoji/cherries.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cherry_blossom.png b/app/assets/images/emoji/cherry_blossom.png
deleted file mode 100644
index 282f3e7bc81..00000000000
--- a/app/assets/images/emoji/cherry_blossom.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/chestnut.png b/app/assets/images/emoji/chestnut.png
deleted file mode 100644
index e9fb40468ed..00000000000
--- a/app/assets/images/emoji/chestnut.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/chicken.png b/app/assets/images/emoji/chicken.png
deleted file mode 100644
index 9a6992e55ba..00000000000
--- a/app/assets/images/emoji/chicken.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/children_crossing.png b/app/assets/images/emoji/children_crossing.png
deleted file mode 100644
index fa4c091c7c3..00000000000
--- a/app/assets/images/emoji/children_crossing.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/chipmunk.png b/app/assets/images/emoji/chipmunk.png
deleted file mode 100644
index 2aac560cb22..00000000000
--- a/app/assets/images/emoji/chipmunk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/chocolate_bar.png b/app/assets/images/emoji/chocolate_bar.png
deleted file mode 100644
index 318bbd40ef9..00000000000
--- a/app/assets/images/emoji/chocolate_bar.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/christmas_tree.png b/app/assets/images/emoji/christmas_tree.png
deleted file mode 100644
index 4197d37a52b..00000000000
--- a/app/assets/images/emoji/christmas_tree.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/church.png b/app/assets/images/emoji/church.png
deleted file mode 100644
index 8242fd272b3..00000000000
--- a/app/assets/images/emoji/church.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cinema.png b/app/assets/images/emoji/cinema.png
deleted file mode 100644
index 65f27b386f2..00000000000
--- a/app/assets/images/emoji/cinema.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/circus_tent.png b/app/assets/images/emoji/circus_tent.png
deleted file mode 100644
index b0379775b12..00000000000
--- a/app/assets/images/emoji/circus_tent.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/city_dusk.png b/app/assets/images/emoji/city_dusk.png
deleted file mode 100644
index 80cdff7cf5d..00000000000
--- a/app/assets/images/emoji/city_dusk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/city_sunset.png b/app/assets/images/emoji/city_sunset.png
deleted file mode 100644
index 7cded0ba55b..00000000000
--- a/app/assets/images/emoji/city_sunset.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cityscape.png b/app/assets/images/emoji/cityscape.png
deleted file mode 100644
index d7b9844a0b4..00000000000
--- a/app/assets/images/emoji/cityscape.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cl.png b/app/assets/images/emoji/cl.png
deleted file mode 100644
index 8b01b4343e2..00000000000
--- a/app/assets/images/emoji/cl.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clap.png b/app/assets/images/emoji/clap.png
deleted file mode 100644
index b0ffe928920..00000000000
--- a/app/assets/images/emoji/clap.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clap_tone1.png b/app/assets/images/emoji/clap_tone1.png
deleted file mode 100644
index de4bc837b96..00000000000
--- a/app/assets/images/emoji/clap_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clap_tone2.png b/app/assets/images/emoji/clap_tone2.png
deleted file mode 100644
index 1323de775ba..00000000000
--- a/app/assets/images/emoji/clap_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clap_tone3.png b/app/assets/images/emoji/clap_tone3.png
deleted file mode 100644
index d448ca19dde..00000000000
--- a/app/assets/images/emoji/clap_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clap_tone4.png b/app/assets/images/emoji/clap_tone4.png
deleted file mode 100644
index c49f44ee91d..00000000000
--- a/app/assets/images/emoji/clap_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clap_tone5.png b/app/assets/images/emoji/clap_tone5.png
deleted file mode 100644
index 29ee9bdf37c..00000000000
--- a/app/assets/images/emoji/clap_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clapper.png b/app/assets/images/emoji/clapper.png
deleted file mode 100644
index 81390883111..00000000000
--- a/app/assets/images/emoji/clapper.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/classical_building.png b/app/assets/images/emoji/classical_building.png
deleted file mode 100644
index de7b559daaf..00000000000
--- a/app/assets/images/emoji/classical_building.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clipboard.png b/app/assets/images/emoji/clipboard.png
deleted file mode 100644
index 7edcfc52509..00000000000
--- a/app/assets/images/emoji/clipboard.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock.png b/app/assets/images/emoji/clock.png
deleted file mode 100644
index ffdb451e3a8..00000000000
--- a/app/assets/images/emoji/clock.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock1.png b/app/assets/images/emoji/clock1.png
deleted file mode 100644
index d6e34941f23..00000000000
--- a/app/assets/images/emoji/clock1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock10.png b/app/assets/images/emoji/clock10.png
deleted file mode 100644
index e62b245cdbe..00000000000
--- a/app/assets/images/emoji/clock10.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock1030.png b/app/assets/images/emoji/clock1030.png
deleted file mode 100644
index 0802b3c65b9..00000000000
--- a/app/assets/images/emoji/clock1030.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock11.png b/app/assets/images/emoji/clock11.png
deleted file mode 100644
index 0983345273b..00000000000
--- a/app/assets/images/emoji/clock11.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock1130.png b/app/assets/images/emoji/clock1130.png
deleted file mode 100644
index d970d03b809..00000000000
--- a/app/assets/images/emoji/clock1130.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock12.png b/app/assets/images/emoji/clock12.png
deleted file mode 100644
index e61caa4b3e2..00000000000
--- a/app/assets/images/emoji/clock12.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock1230.png b/app/assets/images/emoji/clock1230.png
deleted file mode 100644
index f2b1d261721..00000000000
--- a/app/assets/images/emoji/clock1230.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock130.png b/app/assets/images/emoji/clock130.png
deleted file mode 100644
index 86b7689b84e..00000000000
--- a/app/assets/images/emoji/clock130.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock2.png b/app/assets/images/emoji/clock2.png
deleted file mode 100644
index a54253d7d57..00000000000
--- a/app/assets/images/emoji/clock2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock230.png b/app/assets/images/emoji/clock230.png
deleted file mode 100644
index 7a787e018e6..00000000000
--- a/app/assets/images/emoji/clock230.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock3.png b/app/assets/images/emoji/clock3.png
deleted file mode 100644
index 27ec4b1f514..00000000000
--- a/app/assets/images/emoji/clock3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock330.png b/app/assets/images/emoji/clock330.png
deleted file mode 100644
index c6860395cec..00000000000
--- a/app/assets/images/emoji/clock330.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock4.png b/app/assets/images/emoji/clock4.png
deleted file mode 100644
index 60a1ef4cc13..00000000000
--- a/app/assets/images/emoji/clock4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock430.png b/app/assets/images/emoji/clock430.png
deleted file mode 100644
index 3c05b362122..00000000000
--- a/app/assets/images/emoji/clock430.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock5.png b/app/assets/images/emoji/clock5.png
deleted file mode 100644
index c9382d1e094..00000000000
--- a/app/assets/images/emoji/clock5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock530.png b/app/assets/images/emoji/clock530.png
deleted file mode 100644
index c21fa926db2..00000000000
--- a/app/assets/images/emoji/clock530.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock6.png b/app/assets/images/emoji/clock6.png
deleted file mode 100644
index 8fd5d3f5bd7..00000000000
--- a/app/assets/images/emoji/clock6.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock630.png b/app/assets/images/emoji/clock630.png
deleted file mode 100644
index 2aec87fefcf..00000000000
--- a/app/assets/images/emoji/clock630.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock7.png b/app/assets/images/emoji/clock7.png
deleted file mode 100644
index 8c7084036f2..00000000000
--- a/app/assets/images/emoji/clock7.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock730.png b/app/assets/images/emoji/clock730.png
deleted file mode 100644
index f7a1135e03f..00000000000
--- a/app/assets/images/emoji/clock730.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock8.png b/app/assets/images/emoji/clock8.png
deleted file mode 100644
index fcddf722e95..00000000000
--- a/app/assets/images/emoji/clock8.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock830.png b/app/assets/images/emoji/clock830.png
deleted file mode 100644
index 799b4aebc08..00000000000
--- a/app/assets/images/emoji/clock830.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock9.png b/app/assets/images/emoji/clock9.png
deleted file mode 100644
index dfbe0117981..00000000000
--- a/app/assets/images/emoji/clock9.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clock930.png b/app/assets/images/emoji/clock930.png
deleted file mode 100644
index 4a2092ee6f0..00000000000
--- a/app/assets/images/emoji/clock930.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/closed_book.png b/app/assets/images/emoji/closed_book.png
deleted file mode 100644
index 6395cf2151e..00000000000
--- a/app/assets/images/emoji/closed_book.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/closed_lock_with_key.png b/app/assets/images/emoji/closed_lock_with_key.png
deleted file mode 100644
index 1c1cd5d0741..00000000000
--- a/app/assets/images/emoji/closed_lock_with_key.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/closed_umbrella.png b/app/assets/images/emoji/closed_umbrella.png
deleted file mode 100644
index ecefba9e446..00000000000
--- a/app/assets/images/emoji/closed_umbrella.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cloud.png b/app/assets/images/emoji/cloud.png
deleted file mode 100644
index 5b4f57f77ba..00000000000
--- a/app/assets/images/emoji/cloud.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cloud_lightning.png b/app/assets/images/emoji/cloud_lightning.png
deleted file mode 100644
index 0831e88aa31..00000000000
--- a/app/assets/images/emoji/cloud_lightning.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cloud_rain.png b/app/assets/images/emoji/cloud_rain.png
deleted file mode 100644
index 385685e0512..00000000000
--- a/app/assets/images/emoji/cloud_rain.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cloud_snow.png b/app/assets/images/emoji/cloud_snow.png
deleted file mode 100644
index 9720384eb99..00000000000
--- a/app/assets/images/emoji/cloud_snow.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cloud_tornado.png b/app/assets/images/emoji/cloud_tornado.png
deleted file mode 100644
index 4821c89da1e..00000000000
--- a/app/assets/images/emoji/cloud_tornado.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clown.png b/app/assets/images/emoji/clown.png
deleted file mode 100644
index 02b7ff70049..00000000000
--- a/app/assets/images/emoji/clown.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/clubs.png b/app/assets/images/emoji/clubs.png
deleted file mode 100644
index 4f2abf791ca..00000000000
--- a/app/assets/images/emoji/clubs.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cocktail.png b/app/assets/images/emoji/cocktail.png
deleted file mode 100644
index 2e50c57e98d..00000000000
--- a/app/assets/images/emoji/cocktail.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/coffee.png b/app/assets/images/emoji/coffee.png
deleted file mode 100644
index 553061471b1..00000000000
--- a/app/assets/images/emoji/coffee.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/coffin.png b/app/assets/images/emoji/coffin.png
deleted file mode 100644
index fb2932aa5f6..00000000000
--- a/app/assets/images/emoji/coffin.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cold_sweat.png b/app/assets/images/emoji/cold_sweat.png
deleted file mode 100644
index 85b2231bbf6..00000000000
--- a/app/assets/images/emoji/cold_sweat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/comet.png b/app/assets/images/emoji/comet.png
deleted file mode 100644
index a99751f79be..00000000000
--- a/app/assets/images/emoji/comet.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/compression.png b/app/assets/images/emoji/compression.png
deleted file mode 100644
index d7eda7f362a..00000000000
--- a/app/assets/images/emoji/compression.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/computer.png b/app/assets/images/emoji/computer.png
deleted file mode 100644
index c1fee27e3a9..00000000000
--- a/app/assets/images/emoji/computer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/confetti_ball.png b/app/assets/images/emoji/confetti_ball.png
deleted file mode 100644
index ba4fd9b12be..00000000000
--- a/app/assets/images/emoji/confetti_ball.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/confounded.png b/app/assets/images/emoji/confounded.png
deleted file mode 100644
index aa4b29e9375..00000000000
--- a/app/assets/images/emoji/confounded.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/confused.png b/app/assets/images/emoji/confused.png
deleted file mode 100644
index 502b6bf0e0b..00000000000
--- a/app/assets/images/emoji/confused.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/congratulations.png b/app/assets/images/emoji/congratulations.png
deleted file mode 100644
index ba8c89d95ee..00000000000
--- a/app/assets/images/emoji/congratulations.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/construction.png b/app/assets/images/emoji/construction.png
deleted file mode 100644
index ef8db5f471c..00000000000
--- a/app/assets/images/emoji/construction.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/construction_site.png b/app/assets/images/emoji/construction_site.png
deleted file mode 100644
index 8206a20f63f..00000000000
--- a/app/assets/images/emoji/construction_site.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/construction_worker.png b/app/assets/images/emoji/construction_worker.png
deleted file mode 100644
index a9970a89005..00000000000
--- a/app/assets/images/emoji/construction_worker.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/construction_worker_tone1.png b/app/assets/images/emoji/construction_worker_tone1.png
deleted file mode 100644
index 2f24a2bab24..00000000000
--- a/app/assets/images/emoji/construction_worker_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/construction_worker_tone2.png b/app/assets/images/emoji/construction_worker_tone2.png
deleted file mode 100644
index 93c8fec5a75..00000000000
--- a/app/assets/images/emoji/construction_worker_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/construction_worker_tone3.png b/app/assets/images/emoji/construction_worker_tone3.png
deleted file mode 100644
index abc1f2af2e0..00000000000
--- a/app/assets/images/emoji/construction_worker_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/construction_worker_tone4.png b/app/assets/images/emoji/construction_worker_tone4.png
deleted file mode 100644
index eed83289aeb..00000000000
--- a/app/assets/images/emoji/construction_worker_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/construction_worker_tone5.png b/app/assets/images/emoji/construction_worker_tone5.png
deleted file mode 100644
index acbb220b8bb..00000000000
--- a/app/assets/images/emoji/construction_worker_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/control_knobs.png b/app/assets/images/emoji/control_knobs.png
deleted file mode 100644
index 6635ac93b50..00000000000
--- a/app/assets/images/emoji/control_knobs.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/convenience_store.png b/app/assets/images/emoji/convenience_store.png
deleted file mode 100644
index 26b53b5669e..00000000000
--- a/app/assets/images/emoji/convenience_store.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cookie.png b/app/assets/images/emoji/cookie.png
deleted file mode 100644
index 1b6bcb1554f..00000000000
--- a/app/assets/images/emoji/cookie.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cooking.png b/app/assets/images/emoji/cooking.png
deleted file mode 100644
index 918c980577a..00000000000
--- a/app/assets/images/emoji/cooking.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cool.png b/app/assets/images/emoji/cool.png
deleted file mode 100644
index 74674978d00..00000000000
--- a/app/assets/images/emoji/cool.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cop.png b/app/assets/images/emoji/cop.png
deleted file mode 100644
index 0b16d7c17b7..00000000000
--- a/app/assets/images/emoji/cop.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cop_tone1.png b/app/assets/images/emoji/cop_tone1.png
deleted file mode 100644
index 6ccba3879dc..00000000000
--- a/app/assets/images/emoji/cop_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cop_tone2.png b/app/assets/images/emoji/cop_tone2.png
deleted file mode 100644
index 7814ea9f52d..00000000000
--- a/app/assets/images/emoji/cop_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cop_tone3.png b/app/assets/images/emoji/cop_tone3.png
deleted file mode 100644
index d78e88ec872..00000000000
--- a/app/assets/images/emoji/cop_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cop_tone4.png b/app/assets/images/emoji/cop_tone4.png
deleted file mode 100644
index 2e13c508315..00000000000
--- a/app/assets/images/emoji/cop_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cop_tone5.png b/app/assets/images/emoji/cop_tone5.png
deleted file mode 100644
index 2980d61cc2e..00000000000
--- a/app/assets/images/emoji/cop_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/copyright.png b/app/assets/images/emoji/copyright.png
deleted file mode 100644
index 6b9a6adbfd2..00000000000
--- a/app/assets/images/emoji/copyright.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/corn.png b/app/assets/images/emoji/corn.png
deleted file mode 100644
index 36e20127931..00000000000
--- a/app/assets/images/emoji/corn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/couch.png b/app/assets/images/emoji/couch.png
deleted file mode 100644
index 27b19b13bb0..00000000000
--- a/app/assets/images/emoji/couch.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/couple.png b/app/assets/images/emoji/couple.png
deleted file mode 100644
index 960323f3c16..00000000000
--- a/app/assets/images/emoji/couple.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/couple_mm.png b/app/assets/images/emoji/couple_mm.png
deleted file mode 100644
index 8759fa5db87..00000000000
--- a/app/assets/images/emoji/couple_mm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/couple_with_heart.png b/app/assets/images/emoji/couple_with_heart.png
deleted file mode 100644
index 62111601b36..00000000000
--- a/app/assets/images/emoji/couple_with_heart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/couple_ww.png b/app/assets/images/emoji/couple_ww.png
deleted file mode 100644
index 08fdabcdc5c..00000000000
--- a/app/assets/images/emoji/couple_ww.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/couplekiss.png b/app/assets/images/emoji/couplekiss.png
deleted file mode 100644
index 9aa519da9e8..00000000000
--- a/app/assets/images/emoji/couplekiss.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cow.png b/app/assets/images/emoji/cow.png
deleted file mode 100644
index 718a3986d64..00000000000
--- a/app/assets/images/emoji/cow.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cow2.png b/app/assets/images/emoji/cow2.png
deleted file mode 100644
index 4d0ca534ff1..00000000000
--- a/app/assets/images/emoji/cow2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cowboy.png b/app/assets/images/emoji/cowboy.png
deleted file mode 100644
index 70dd5d0d9d1..00000000000
--- a/app/assets/images/emoji/cowboy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/crab.png b/app/assets/images/emoji/crab.png
deleted file mode 100644
index 19f3047ab61..00000000000
--- a/app/assets/images/emoji/crab.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/crayon.png b/app/assets/images/emoji/crayon.png
deleted file mode 100644
index 8d7b427aaa3..00000000000
--- a/app/assets/images/emoji/crayon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/credit_card.png b/app/assets/images/emoji/credit_card.png
deleted file mode 100644
index 372777d5c61..00000000000
--- a/app/assets/images/emoji/credit_card.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/crescent_moon.png b/app/assets/images/emoji/crescent_moon.png
deleted file mode 100644
index 765420ecec7..00000000000
--- a/app/assets/images/emoji/crescent_moon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cricket.png b/app/assets/images/emoji/cricket.png
deleted file mode 100644
index d602294a2cd..00000000000
--- a/app/assets/images/emoji/cricket.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/crocodile.png b/app/assets/images/emoji/crocodile.png
deleted file mode 100644
index 3005c46f176..00000000000
--- a/app/assets/images/emoji/crocodile.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/croissant.png b/app/assets/images/emoji/croissant.png
deleted file mode 100644
index fb33feb1a38..00000000000
--- a/app/assets/images/emoji/croissant.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cross.png b/app/assets/images/emoji/cross.png
deleted file mode 100644
index 42b10e82257..00000000000
--- a/app/assets/images/emoji/cross.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/crossed_flags.png b/app/assets/images/emoji/crossed_flags.png
deleted file mode 100644
index 273bd0f0fe5..00000000000
--- a/app/assets/images/emoji/crossed_flags.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/crossed_swords.png b/app/assets/images/emoji/crossed_swords.png
deleted file mode 100644
index 907e9607134..00000000000
--- a/app/assets/images/emoji/crossed_swords.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/crown.png b/app/assets/images/emoji/crown.png
deleted file mode 100644
index 93b82d92f04..00000000000
--- a/app/assets/images/emoji/crown.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cruise_ship.png b/app/assets/images/emoji/cruise_ship.png
deleted file mode 100644
index 19d4acbe40c..00000000000
--- a/app/assets/images/emoji/cruise_ship.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cry.png b/app/assets/images/emoji/cry.png
deleted file mode 100644
index b7877f8a173..00000000000
--- a/app/assets/images/emoji/cry.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/crying_cat_face.png b/app/assets/images/emoji/crying_cat_face.png
deleted file mode 100644
index b4f49715e00..00000000000
--- a/app/assets/images/emoji/crying_cat_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/crystal_ball.png b/app/assets/images/emoji/crystal_ball.png
deleted file mode 100644
index 485d5c888f1..00000000000
--- a/app/assets/images/emoji/crystal_ball.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cucumber.png b/app/assets/images/emoji/cucumber.png
deleted file mode 100644
index 500807059d2..00000000000
--- a/app/assets/images/emoji/cucumber.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cupid.png b/app/assets/images/emoji/cupid.png
deleted file mode 100644
index 2df0078ddd1..00000000000
--- a/app/assets/images/emoji/cupid.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/curly_loop.png b/app/assets/images/emoji/curly_loop.png
deleted file mode 100644
index 440aa56d50e..00000000000
--- a/app/assets/images/emoji/curly_loop.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/currency_exchange.png b/app/assets/images/emoji/currency_exchange.png
deleted file mode 100644
index 4d46c6050e7..00000000000
--- a/app/assets/images/emoji/currency_exchange.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/curry.png b/app/assets/images/emoji/curry.png
deleted file mode 100644
index 69657ca8103..00000000000
--- a/app/assets/images/emoji/curry.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/custard.png b/app/assets/images/emoji/custard.png
deleted file mode 100644
index fa3df67b8f6..00000000000
--- a/app/assets/images/emoji/custard.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/customs.png b/app/assets/images/emoji/customs.png
deleted file mode 100644
index 21b7ce2c69e..00000000000
--- a/app/assets/images/emoji/customs.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/cyclone.png b/app/assets/images/emoji/cyclone.png
deleted file mode 100644
index ff00b1afe70..00000000000
--- a/app/assets/images/emoji/cyclone.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dagger.png b/app/assets/images/emoji/dagger.png
deleted file mode 100644
index 66e97b0aa25..00000000000
--- a/app/assets/images/emoji/dagger.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dancer.png b/app/assets/images/emoji/dancer.png
deleted file mode 100644
index 04b166991cb..00000000000
--- a/app/assets/images/emoji/dancer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dancer_tone1.png b/app/assets/images/emoji/dancer_tone1.png
deleted file mode 100644
index 2c7b11c3a6e..00000000000
--- a/app/assets/images/emoji/dancer_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dancer_tone2.png b/app/assets/images/emoji/dancer_tone2.png
deleted file mode 100644
index cb04b1f907e..00000000000
--- a/app/assets/images/emoji/dancer_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dancer_tone3.png b/app/assets/images/emoji/dancer_tone3.png
deleted file mode 100644
index 98c5bca7b64..00000000000
--- a/app/assets/images/emoji/dancer_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dancer_tone4.png b/app/assets/images/emoji/dancer_tone4.png
deleted file mode 100644
index fdb1e00cbba..00000000000
--- a/app/assets/images/emoji/dancer_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dancer_tone5.png b/app/assets/images/emoji/dancer_tone5.png
deleted file mode 100644
index 0e34e0e23f0..00000000000
--- a/app/assets/images/emoji/dancer_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dancers.png b/app/assets/images/emoji/dancers.png
deleted file mode 100644
index 67e6ffacb76..00000000000
--- a/app/assets/images/emoji/dancers.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dango.png b/app/assets/images/emoji/dango.png
deleted file mode 100644
index f73f37b01c7..00000000000
--- a/app/assets/images/emoji/dango.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dark_sunglasses.png b/app/assets/images/emoji/dark_sunglasses.png
deleted file mode 100644
index b1b6db0acff..00000000000
--- a/app/assets/images/emoji/dark_sunglasses.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dart.png b/app/assets/images/emoji/dart.png
deleted file mode 100644
index f6704aeb8ba..00000000000
--- a/app/assets/images/emoji/dart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dash.png b/app/assets/images/emoji/dash.png
deleted file mode 100644
index 064b8525c12..00000000000
--- a/app/assets/images/emoji/dash.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/date.png b/app/assets/images/emoji/date.png
deleted file mode 100644
index f05b3da97b8..00000000000
--- a/app/assets/images/emoji/date.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/deciduous_tree.png b/app/assets/images/emoji/deciduous_tree.png
deleted file mode 100644
index 785fc1c30ea..00000000000
--- a/app/assets/images/emoji/deciduous_tree.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/deer.png b/app/assets/images/emoji/deer.png
deleted file mode 100644
index d8698195ff0..00000000000
--- a/app/assets/images/emoji/deer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/department_store.png b/app/assets/images/emoji/department_store.png
deleted file mode 100644
index 58867c7a6e1..00000000000
--- a/app/assets/images/emoji/department_store.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/desert.png b/app/assets/images/emoji/desert.png
deleted file mode 100644
index e9966ff8c65..00000000000
--- a/app/assets/images/emoji/desert.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/desktop.png b/app/assets/images/emoji/desktop.png
deleted file mode 100644
index 909bd42b5e1..00000000000
--- a/app/assets/images/emoji/desktop.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/diamond_shape_with_a_dot_inside.png b/app/assets/images/emoji/diamond_shape_with_a_dot_inside.png
deleted file mode 100644
index 2a22a26d1e2..00000000000
--- a/app/assets/images/emoji/diamond_shape_with_a_dot_inside.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/diamonds.png b/app/assets/images/emoji/diamonds.png
deleted file mode 100644
index 1f25f51f97a..00000000000
--- a/app/assets/images/emoji/diamonds.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/disappointed.png b/app/assets/images/emoji/disappointed.png
deleted file mode 100644
index efe4e67e23c..00000000000
--- a/app/assets/images/emoji/disappointed.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/disappointed_relieved.png b/app/assets/images/emoji/disappointed_relieved.png
deleted file mode 100644
index aef864d2b3d..00000000000
--- a/app/assets/images/emoji/disappointed_relieved.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dividers.png b/app/assets/images/emoji/dividers.png
deleted file mode 100644
index 46a7e403f9d..00000000000
--- a/app/assets/images/emoji/dividers.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dizzy.png b/app/assets/images/emoji/dizzy.png
deleted file mode 100644
index 85f52efad24..00000000000
--- a/app/assets/images/emoji/dizzy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dizzy_face.png b/app/assets/images/emoji/dizzy_face.png
deleted file mode 100644
index 3120316ab5e..00000000000
--- a/app/assets/images/emoji/dizzy_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/do_not_litter.png b/app/assets/images/emoji/do_not_litter.png
deleted file mode 100644
index 341d2575f4f..00000000000
--- a/app/assets/images/emoji/do_not_litter.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dog.png b/app/assets/images/emoji/dog.png
deleted file mode 100644
index 281b81d58bd..00000000000
--- a/app/assets/images/emoji/dog.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dog2.png b/app/assets/images/emoji/dog2.png
deleted file mode 100644
index 976143dbdbe..00000000000
--- a/app/assets/images/emoji/dog2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dollar.png b/app/assets/images/emoji/dollar.png
deleted file mode 100644
index a9904c28293..00000000000
--- a/app/assets/images/emoji/dollar.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dolls.png b/app/assets/images/emoji/dolls.png
deleted file mode 100644
index 10955615110..00000000000
--- a/app/assets/images/emoji/dolls.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dolphin.png b/app/assets/images/emoji/dolphin.png
deleted file mode 100644
index 81434809003..00000000000
--- a/app/assets/images/emoji/dolphin.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/door.png b/app/assets/images/emoji/door.png
deleted file mode 100644
index 36ae3e27494..00000000000
--- a/app/assets/images/emoji/door.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/doughnut.png b/app/assets/images/emoji/doughnut.png
deleted file mode 100644
index 0ca4cd0bde8..00000000000
--- a/app/assets/images/emoji/doughnut.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dove.png b/app/assets/images/emoji/dove.png
deleted file mode 100644
index 9580c4917d7..00000000000
--- a/app/assets/images/emoji/dove.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dragon.png b/app/assets/images/emoji/dragon.png
deleted file mode 100644
index d6311cf5429..00000000000
--- a/app/assets/images/emoji/dragon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dragon_face.png b/app/assets/images/emoji/dragon_face.png
deleted file mode 100644
index 3c2720446c6..00000000000
--- a/app/assets/images/emoji/dragon_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dress.png b/app/assets/images/emoji/dress.png
deleted file mode 100644
index a697ca5c57d..00000000000
--- a/app/assets/images/emoji/dress.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dromedary_camel.png b/app/assets/images/emoji/dromedary_camel.png
deleted file mode 100644
index 5271637c7c4..00000000000
--- a/app/assets/images/emoji/dromedary_camel.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/drooling_face.png b/app/assets/images/emoji/drooling_face.png
deleted file mode 100644
index a5460532597..00000000000
--- a/app/assets/images/emoji/drooling_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/droplet.png b/app/assets/images/emoji/droplet.png
deleted file mode 100644
index 71241ec3061..00000000000
--- a/app/assets/images/emoji/droplet.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/drum.png b/app/assets/images/emoji/drum.png
deleted file mode 100644
index b038727cc99..00000000000
--- a/app/assets/images/emoji/drum.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/duck.png b/app/assets/images/emoji/duck.png
deleted file mode 100644
index 74330b77ca3..00000000000
--- a/app/assets/images/emoji/duck.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/dvd.png b/app/assets/images/emoji/dvd.png
deleted file mode 100644
index 045a6f7a08d..00000000000
--- a/app/assets/images/emoji/dvd.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/e-mail.png b/app/assets/images/emoji/e-mail.png
deleted file mode 100644
index d22e654a20b..00000000000
--- a/app/assets/images/emoji/e-mail.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/eagle.png b/app/assets/images/emoji/eagle.png
deleted file mode 100644
index 4f277debeef..00000000000
--- a/app/assets/images/emoji/eagle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ear.png b/app/assets/images/emoji/ear.png
deleted file mode 100644
index f84f9ff154a..00000000000
--- a/app/assets/images/emoji/ear.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ear_of_rice.png b/app/assets/images/emoji/ear_of_rice.png
deleted file mode 100644
index 3564d9d643a..00000000000
--- a/app/assets/images/emoji/ear_of_rice.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ear_tone1.png b/app/assets/images/emoji/ear_tone1.png
deleted file mode 100644
index d09e1e41996..00000000000
--- a/app/assets/images/emoji/ear_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ear_tone2.png b/app/assets/images/emoji/ear_tone2.png
deleted file mode 100644
index 300d60a9948..00000000000
--- a/app/assets/images/emoji/ear_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ear_tone3.png b/app/assets/images/emoji/ear_tone3.png
deleted file mode 100644
index 2a56eebe445..00000000000
--- a/app/assets/images/emoji/ear_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ear_tone4.png b/app/assets/images/emoji/ear_tone4.png
deleted file mode 100644
index bd270f7763e..00000000000
--- a/app/assets/images/emoji/ear_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ear_tone5.png b/app/assets/images/emoji/ear_tone5.png
deleted file mode 100644
index b96bb441dff..00000000000
--- a/app/assets/images/emoji/ear_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/earth_africa.png b/app/assets/images/emoji/earth_africa.png
deleted file mode 100644
index 66c3348c23a..00000000000
--- a/app/assets/images/emoji/earth_africa.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/earth_americas.png b/app/assets/images/emoji/earth_americas.png
deleted file mode 100644
index 538c3cddd68..00000000000
--- a/app/assets/images/emoji/earth_americas.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/earth_asia.png b/app/assets/images/emoji/earth_asia.png
deleted file mode 100644
index d8df97fec3c..00000000000
--- a/app/assets/images/emoji/earth_asia.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/egg.png b/app/assets/images/emoji/egg.png
deleted file mode 100644
index c171974d993..00000000000
--- a/app/assets/images/emoji/egg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/eggplant.png b/app/assets/images/emoji/eggplant.png
deleted file mode 100644
index fafd7c1a14c..00000000000
--- a/app/assets/images/emoji/eggplant.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/eight.png b/app/assets/images/emoji/eight.png
deleted file mode 100644
index 8c95874d4c5..00000000000
--- a/app/assets/images/emoji/eight.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/eight_pointed_black_star.png b/app/assets/images/emoji/eight_pointed_black_star.png
deleted file mode 100644
index 820179bda50..00000000000
--- a/app/assets/images/emoji/eight_pointed_black_star.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/eight_spoked_asterisk.png b/app/assets/images/emoji/eight_spoked_asterisk.png
deleted file mode 100644
index 3307ffa62ee..00000000000
--- a/app/assets/images/emoji/eight_spoked_asterisk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/eject.png b/app/assets/images/emoji/eject.png
deleted file mode 100644
index ec5cfc48973..00000000000
--- a/app/assets/images/emoji/eject.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/electric_plug.png b/app/assets/images/emoji/electric_plug.png
deleted file mode 100644
index 31d1eb215b4..00000000000
--- a/app/assets/images/emoji/electric_plug.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/elephant.png b/app/assets/images/emoji/elephant.png
deleted file mode 100644
index b8a6d140595..00000000000
--- a/app/assets/images/emoji/elephant.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/end.png b/app/assets/images/emoji/end.png
deleted file mode 100644
index ef3ccd5f367..00000000000
--- a/app/assets/images/emoji/end.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/envelope.png b/app/assets/images/emoji/envelope.png
deleted file mode 100644
index ec77ac375a4..00000000000
--- a/app/assets/images/emoji/envelope.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/envelope_with_arrow.png b/app/assets/images/emoji/envelope_with_arrow.png
deleted file mode 100644
index 7448a6b7673..00000000000
--- a/app/assets/images/emoji/envelope_with_arrow.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/euro.png b/app/assets/images/emoji/euro.png
deleted file mode 100644
index a49020820e1..00000000000
--- a/app/assets/images/emoji/euro.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/european_castle.png b/app/assets/images/emoji/european_castle.png
deleted file mode 100644
index 888d11332ce..00000000000
--- a/app/assets/images/emoji/european_castle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/european_post_office.png b/app/assets/images/emoji/european_post_office.png
deleted file mode 100644
index 3745aff8dd2..00000000000
--- a/app/assets/images/emoji/european_post_office.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/evergreen_tree.png b/app/assets/images/emoji/evergreen_tree.png
deleted file mode 100644
index f679d8dd772..00000000000
--- a/app/assets/images/emoji/evergreen_tree.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/exclamation.png b/app/assets/images/emoji/exclamation.png
deleted file mode 100644
index 2c14406422f..00000000000
--- a/app/assets/images/emoji/exclamation.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/expressionless.png b/app/assets/images/emoji/expressionless.png
deleted file mode 100644
index 2954017f6c2..00000000000
--- a/app/assets/images/emoji/expressionless.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/eye.png b/app/assets/images/emoji/eye.png
deleted file mode 100644
index 9d989cdd375..00000000000
--- a/app/assets/images/emoji/eye.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/eye_in_speech_bubble.png b/app/assets/images/emoji/eye_in_speech_bubble.png
deleted file mode 100644
index 21bd22bbcce..00000000000
--- a/app/assets/images/emoji/eye_in_speech_bubble.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/eyeglasses.png b/app/assets/images/emoji/eyeglasses.png
deleted file mode 100644
index 865d8274acf..00000000000
--- a/app/assets/images/emoji/eyeglasses.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/eyes.png b/app/assets/images/emoji/eyes.png
deleted file mode 100644
index 2102ada7e09..00000000000
--- a/app/assets/images/emoji/eyes.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/face_palm.png b/app/assets/images/emoji/face_palm.png
deleted file mode 100644
index defc796cf16..00000000000
--- a/app/assets/images/emoji/face_palm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/face_palm_tone1.png b/app/assets/images/emoji/face_palm_tone1.png
deleted file mode 100644
index 2f4b010bb40..00000000000
--- a/app/assets/images/emoji/face_palm_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/face_palm_tone2.png b/app/assets/images/emoji/face_palm_tone2.png
deleted file mode 100644
index 97fb6831687..00000000000
--- a/app/assets/images/emoji/face_palm_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/face_palm_tone3.png b/app/assets/images/emoji/face_palm_tone3.png
deleted file mode 100644
index b5b5c1e5306..00000000000
--- a/app/assets/images/emoji/face_palm_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/face_palm_tone4.png b/app/assets/images/emoji/face_palm_tone4.png
deleted file mode 100644
index 2840b113483..00000000000
--- a/app/assets/images/emoji/face_palm_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/face_palm_tone5.png b/app/assets/images/emoji/face_palm_tone5.png
deleted file mode 100644
index 6f070db98be..00000000000
--- a/app/assets/images/emoji/face_palm_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/factory.png b/app/assets/images/emoji/factory.png
deleted file mode 100644
index e1d2ddf4a27..00000000000
--- a/app/assets/images/emoji/factory.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fallen_leaf.png b/app/assets/images/emoji/fallen_leaf.png
deleted file mode 100644
index 0d60e7bdf2d..00000000000
--- a/app/assets/images/emoji/fallen_leaf.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family.png b/app/assets/images/emoji/family.png
deleted file mode 100644
index 26421965791..00000000000
--- a/app/assets/images/emoji/family.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_mmb.png b/app/assets/images/emoji/family_mmb.png
deleted file mode 100644
index 7a2e4e2c491..00000000000
--- a/app/assets/images/emoji/family_mmb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_mmbb.png b/app/assets/images/emoji/family_mmbb.png
deleted file mode 100644
index 81e6c0fc0ee..00000000000
--- a/app/assets/images/emoji/family_mmbb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_mmg.png b/app/assets/images/emoji/family_mmg.png
deleted file mode 100644
index 932a85e1fe5..00000000000
--- a/app/assets/images/emoji/family_mmg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_mmgb.png b/app/assets/images/emoji/family_mmgb.png
deleted file mode 100644
index 41e35166670..00000000000
--- a/app/assets/images/emoji/family_mmgb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_mmgg.png b/app/assets/images/emoji/family_mmgg.png
deleted file mode 100644
index 8e8ccfe6c7f..00000000000
--- a/app/assets/images/emoji/family_mmgg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_mwbb.png b/app/assets/images/emoji/family_mwbb.png
deleted file mode 100644
index b544fbe573f..00000000000
--- a/app/assets/images/emoji/family_mwbb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_mwg.png b/app/assets/images/emoji/family_mwg.png
deleted file mode 100644
index 71d2681c32a..00000000000
--- a/app/assets/images/emoji/family_mwg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_mwgb.png b/app/assets/images/emoji/family_mwgb.png
deleted file mode 100644
index 40dbf1f7a18..00000000000
--- a/app/assets/images/emoji/family_mwgb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_mwgg.png b/app/assets/images/emoji/family_mwgg.png
deleted file mode 100644
index bfefa4879cb..00000000000
--- a/app/assets/images/emoji/family_mwgg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_wwb.png b/app/assets/images/emoji/family_wwb.png
deleted file mode 100644
index 836feae7c78..00000000000
--- a/app/assets/images/emoji/family_wwb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_wwbb.png b/app/assets/images/emoji/family_wwbb.png
deleted file mode 100644
index 6c6ba45e7bb..00000000000
--- a/app/assets/images/emoji/family_wwbb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_wwg.png b/app/assets/images/emoji/family_wwg.png
deleted file mode 100644
index 41225c6fa5a..00000000000
--- a/app/assets/images/emoji/family_wwg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_wwgb.png b/app/assets/images/emoji/family_wwgb.png
deleted file mode 100644
index 284d29ab5da..00000000000
--- a/app/assets/images/emoji/family_wwgb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/family_wwgg.png b/app/assets/images/emoji/family_wwgg.png
deleted file mode 100644
index d8d3f49b85f..00000000000
--- a/app/assets/images/emoji/family_wwgg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fast_forward.png b/app/assets/images/emoji/fast_forward.png
deleted file mode 100644
index c406fedfdb1..00000000000
--- a/app/assets/images/emoji/fast_forward.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fax.png b/app/assets/images/emoji/fax.png
deleted file mode 100644
index 6f929e294c2..00000000000
--- a/app/assets/images/emoji/fax.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fearful.png b/app/assets/images/emoji/fearful.png
deleted file mode 100644
index eb8b347cef9..00000000000
--- a/app/assets/images/emoji/fearful.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/feet.png b/app/assets/images/emoji/feet.png
deleted file mode 100644
index 5fe568cee93..00000000000
--- a/app/assets/images/emoji/feet.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fencer.png b/app/assets/images/emoji/fencer.png
deleted file mode 100644
index 5288c920eb9..00000000000
--- a/app/assets/images/emoji/fencer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ferris_wheel.png b/app/assets/images/emoji/ferris_wheel.png
deleted file mode 100644
index 55c8ff0475b..00000000000
--- a/app/assets/images/emoji/ferris_wheel.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ferry.png b/app/assets/images/emoji/ferry.png
deleted file mode 100644
index 41816b3ae34..00000000000
--- a/app/assets/images/emoji/ferry.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/field_hockey.png b/app/assets/images/emoji/field_hockey.png
deleted file mode 100644
index 839637716ee..00000000000
--- a/app/assets/images/emoji/field_hockey.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/file_cabinet.png b/app/assets/images/emoji/file_cabinet.png
deleted file mode 100644
index fddc65dde96..00000000000
--- a/app/assets/images/emoji/file_cabinet.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/file_folder.png b/app/assets/images/emoji/file_folder.png
deleted file mode 100644
index addedaf0870..00000000000
--- a/app/assets/images/emoji/file_folder.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/film_frames.png b/app/assets/images/emoji/film_frames.png
deleted file mode 100644
index 30143aedbe6..00000000000
--- a/app/assets/images/emoji/film_frames.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fingers_crossed.png b/app/assets/images/emoji/fingers_crossed.png
deleted file mode 100644
index 4cd18514ea3..00000000000
--- a/app/assets/images/emoji/fingers_crossed.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fingers_crossed_tone1.png b/app/assets/images/emoji/fingers_crossed_tone1.png
deleted file mode 100644
index dd2384a6cd5..00000000000
--- a/app/assets/images/emoji/fingers_crossed_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fingers_crossed_tone2.png b/app/assets/images/emoji/fingers_crossed_tone2.png
deleted file mode 100644
index 6228401befe..00000000000
--- a/app/assets/images/emoji/fingers_crossed_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fingers_crossed_tone3.png b/app/assets/images/emoji/fingers_crossed_tone3.png
deleted file mode 100644
index b1074da15f5..00000000000
--- a/app/assets/images/emoji/fingers_crossed_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fingers_crossed_tone4.png b/app/assets/images/emoji/fingers_crossed_tone4.png
deleted file mode 100644
index 75e05e4d332..00000000000
--- a/app/assets/images/emoji/fingers_crossed_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fingers_crossed_tone5.png b/app/assets/images/emoji/fingers_crossed_tone5.png
deleted file mode 100644
index 761aebdc30f..00000000000
--- a/app/assets/images/emoji/fingers_crossed_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fire.png b/app/assets/images/emoji/fire.png
deleted file mode 100644
index bd3775a460b..00000000000
--- a/app/assets/images/emoji/fire.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fire_engine.png b/app/assets/images/emoji/fire_engine.png
deleted file mode 100644
index 2cd45b7cf7e..00000000000
--- a/app/assets/images/emoji/fire_engine.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fireworks.png b/app/assets/images/emoji/fireworks.png
deleted file mode 100644
index 176c8b58265..00000000000
--- a/app/assets/images/emoji/fireworks.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/first_place.png b/app/assets/images/emoji/first_place.png
deleted file mode 100644
index 15612b66492..00000000000
--- a/app/assets/images/emoji/first_place.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/first_quarter_moon.png b/app/assets/images/emoji/first_quarter_moon.png
deleted file mode 100644
index 5dccaf72a4f..00000000000
--- a/app/assets/images/emoji/first_quarter_moon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/first_quarter_moon_with_face.png b/app/assets/images/emoji/first_quarter_moon_with_face.png
deleted file mode 100644
index cd8a3d7acd8..00000000000
--- a/app/assets/images/emoji/first_quarter_moon_with_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fish.png b/app/assets/images/emoji/fish.png
deleted file mode 100644
index c2d2faaacd4..00000000000
--- a/app/assets/images/emoji/fish.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fish_cake.png b/app/assets/images/emoji/fish_cake.png
deleted file mode 100644
index 157bded65db..00000000000
--- a/app/assets/images/emoji/fish_cake.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fishing_pole_and_fish.png b/app/assets/images/emoji/fishing_pole_and_fish.png
deleted file mode 100644
index dfcdf07eb50..00000000000
--- a/app/assets/images/emoji/fishing_pole_and_fish.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fist.png b/app/assets/images/emoji/fist.png
deleted file mode 100644
index de33592bf98..00000000000
--- a/app/assets/images/emoji/fist.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fist_tone1.png b/app/assets/images/emoji/fist_tone1.png
deleted file mode 100644
index 02809e2dd68..00000000000
--- a/app/assets/images/emoji/fist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fist_tone2.png b/app/assets/images/emoji/fist_tone2.png
deleted file mode 100644
index 5de34810383..00000000000
--- a/app/assets/images/emoji/fist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fist_tone3.png b/app/assets/images/emoji/fist_tone3.png
deleted file mode 100644
index 0d5240129b1..00000000000
--- a/app/assets/images/emoji/fist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fist_tone4.png b/app/assets/images/emoji/fist_tone4.png
deleted file mode 100644
index a95c0dd634b..00000000000
--- a/app/assets/images/emoji/fist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fist_tone5.png b/app/assets/images/emoji/fist_tone5.png
deleted file mode 100644
index a2f092fd8c7..00000000000
--- a/app/assets/images/emoji/fist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/five.png b/app/assets/images/emoji/five.png
deleted file mode 100644
index d14371f3f27..00000000000
--- a/app/assets/images/emoji/five.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ac.png b/app/assets/images/emoji/flag_ac.png
deleted file mode 100644
index 286239920c7..00000000000
--- a/app/assets/images/emoji/flag_ac.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ad.png b/app/assets/images/emoji/flag_ad.png
deleted file mode 100644
index 20f4b14e8ad..00000000000
--- a/app/assets/images/emoji/flag_ad.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ae.png b/app/assets/images/emoji/flag_ae.png
deleted file mode 100644
index d16ffe4b862..00000000000
--- a/app/assets/images/emoji/flag_ae.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_af.png b/app/assets/images/emoji/flag_af.png
deleted file mode 100644
index a51533b554d..00000000000
--- a/app/assets/images/emoji/flag_af.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ag.png b/app/assets/images/emoji/flag_ag.png
deleted file mode 100644
index 07f2ce397d0..00000000000
--- a/app/assets/images/emoji/flag_ag.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ai.png b/app/assets/images/emoji/flag_ai.png
deleted file mode 100644
index 500b5ab09fb..00000000000
--- a/app/assets/images/emoji/flag_ai.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_al.png b/app/assets/images/emoji/flag_al.png
deleted file mode 100644
index 03a20132cc6..00000000000
--- a/app/assets/images/emoji/flag_al.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_am.png b/app/assets/images/emoji/flag_am.png
deleted file mode 100644
index 2ad60a273ec..00000000000
--- a/app/assets/images/emoji/flag_am.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ao.png b/app/assets/images/emoji/flag_ao.png
deleted file mode 100644
index cb46c31f862..00000000000
--- a/app/assets/images/emoji/flag_ao.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_aq.png b/app/assets/images/emoji/flag_aq.png
deleted file mode 100644
index b272021d375..00000000000
--- a/app/assets/images/emoji/flag_aq.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ar.png b/app/assets/images/emoji/flag_ar.png
deleted file mode 100644
index 73136caf3b7..00000000000
--- a/app/assets/images/emoji/flag_ar.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_as.png b/app/assets/images/emoji/flag_as.png
deleted file mode 100644
index 3db45a0d9f3..00000000000
--- a/app/assets/images/emoji/flag_as.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_at.png b/app/assets/images/emoji/flag_at.png
deleted file mode 100644
index c43769dcb19..00000000000
--- a/app/assets/images/emoji/flag_at.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_au.png b/app/assets/images/emoji/flag_au.png
deleted file mode 100644
index 7794309c78c..00000000000
--- a/app/assets/images/emoji/flag_au.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_aw.png b/app/assets/images/emoji/flag_aw.png
deleted file mode 100644
index 02c840d12c9..00000000000
--- a/app/assets/images/emoji/flag_aw.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ax.png b/app/assets/images/emoji/flag_ax.png
deleted file mode 100644
index fc5466174bb..00000000000
--- a/app/assets/images/emoji/flag_ax.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_az.png b/app/assets/images/emoji/flag_az.png
deleted file mode 100644
index 89d3d15fd9f..00000000000
--- a/app/assets/images/emoji/flag_az.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ba.png b/app/assets/images/emoji/flag_ba.png
deleted file mode 100644
index 25fe407e13c..00000000000
--- a/app/assets/images/emoji/flag_ba.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bb.png b/app/assets/images/emoji/flag_bb.png
deleted file mode 100644
index bccd8c5c9b0..00000000000
--- a/app/assets/images/emoji/flag_bb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bd.png b/app/assets/images/emoji/flag_bd.png
deleted file mode 100644
index b0597a3149b..00000000000
--- a/app/assets/images/emoji/flag_bd.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_be.png b/app/assets/images/emoji/flag_be.png
deleted file mode 100644
index 551f086e3c4..00000000000
--- a/app/assets/images/emoji/flag_be.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bf.png b/app/assets/images/emoji/flag_bf.png
deleted file mode 100644
index 444d4829f94..00000000000
--- a/app/assets/images/emoji/flag_bf.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bg.png b/app/assets/images/emoji/flag_bg.png
deleted file mode 100644
index 821eee5e170..00000000000
--- a/app/assets/images/emoji/flag_bg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bh.png b/app/assets/images/emoji/flag_bh.png
deleted file mode 100644
index f33724249f0..00000000000
--- a/app/assets/images/emoji/flag_bh.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bi.png b/app/assets/images/emoji/flag_bi.png
deleted file mode 100644
index ea20ac93211..00000000000
--- a/app/assets/images/emoji/flag_bi.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bj.png b/app/assets/images/emoji/flag_bj.png
deleted file mode 100644
index 7cca4f80457..00000000000
--- a/app/assets/images/emoji/flag_bj.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bl.png b/app/assets/images/emoji/flag_bl.png
deleted file mode 100644
index 1082e78999f..00000000000
--- a/app/assets/images/emoji/flag_bl.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_black.png b/app/assets/images/emoji/flag_black.png
deleted file mode 100644
index 0e28d05d5ac..00000000000
--- a/app/assets/images/emoji/flag_black.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bm.png b/app/assets/images/emoji/flag_bm.png
deleted file mode 100644
index ab8cafdac63..00000000000
--- a/app/assets/images/emoji/flag_bm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bn.png b/app/assets/images/emoji/flag_bn.png
deleted file mode 100644
index caa9329a896..00000000000
--- a/app/assets/images/emoji/flag_bn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bo.png b/app/assets/images/emoji/flag_bo.png
deleted file mode 100644
index 98af62b3da7..00000000000
--- a/app/assets/images/emoji/flag_bo.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bq.png b/app/assets/images/emoji/flag_bq.png
deleted file mode 100644
index cb978ef9de9..00000000000
--- a/app/assets/images/emoji/flag_bq.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_br.png b/app/assets/images/emoji/flag_br.png
deleted file mode 100644
index b139366a42b..00000000000
--- a/app/assets/images/emoji/flag_br.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bs.png b/app/assets/images/emoji/flag_bs.png
deleted file mode 100644
index d36bcd2fb52..00000000000
--- a/app/assets/images/emoji/flag_bs.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bt.png b/app/assets/images/emoji/flag_bt.png
deleted file mode 100644
index ed57aa0360e..00000000000
--- a/app/assets/images/emoji/flag_bt.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bv.png b/app/assets/images/emoji/flag_bv.png
deleted file mode 100644
index 5884e648228..00000000000
--- a/app/assets/images/emoji/flag_bv.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bw.png b/app/assets/images/emoji/flag_bw.png
deleted file mode 100644
index cb12f34739d..00000000000
--- a/app/assets/images/emoji/flag_bw.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_by.png b/app/assets/images/emoji/flag_by.png
deleted file mode 100644
index 859c05beb13..00000000000
--- a/app/assets/images/emoji/flag_by.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_bz.png b/app/assets/images/emoji/flag_bz.png
deleted file mode 100644
index 34761cd03d8..00000000000
--- a/app/assets/images/emoji/flag_bz.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ca.png b/app/assets/images/emoji/flag_ca.png
deleted file mode 100644
index 7c5b390e85b..00000000000
--- a/app/assets/images/emoji/flag_ca.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cc.png b/app/assets/images/emoji/flag_cc.png
deleted file mode 100644
index b6555a23d83..00000000000
--- a/app/assets/images/emoji/flag_cc.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cd.png b/app/assets/images/emoji/flag_cd.png
deleted file mode 100644
index fa92009771d..00000000000
--- a/app/assets/images/emoji/flag_cd.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cf.png b/app/assets/images/emoji/flag_cf.png
deleted file mode 100644
index b969ae29ea9..00000000000
--- a/app/assets/images/emoji/flag_cf.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cg.png b/app/assets/images/emoji/flag_cg.png
deleted file mode 100644
index 3a38a40a95e..00000000000
--- a/app/assets/images/emoji/flag_cg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ch.png b/app/assets/images/emoji/flag_ch.png
deleted file mode 100644
index 5ff86b8a3b7..00000000000
--- a/app/assets/images/emoji/flag_ch.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ci.png b/app/assets/images/emoji/flag_ci.png
deleted file mode 100644
index e3b4d15c7f1..00000000000
--- a/app/assets/images/emoji/flag_ci.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ck.png b/app/assets/images/emoji/flag_ck.png
deleted file mode 100644
index b6b53dbc1c4..00000000000
--- a/app/assets/images/emoji/flag_ck.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cl.png b/app/assets/images/emoji/flag_cl.png
deleted file mode 100644
index c9390da5499..00000000000
--- a/app/assets/images/emoji/flag_cl.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cm.png b/app/assets/images/emoji/flag_cm.png
deleted file mode 100644
index 2d3f6ec4518..00000000000
--- a/app/assets/images/emoji/flag_cm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cn.png b/app/assets/images/emoji/flag_cn.png
deleted file mode 100644
index 0a7f350a6d2..00000000000
--- a/app/assets/images/emoji/flag_cn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_co.png b/app/assets/images/emoji/flag_co.png
deleted file mode 100644
index 7e0f5e0dc3c..00000000000
--- a/app/assets/images/emoji/flag_co.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cp.png b/app/assets/images/emoji/flag_cp.png
deleted file mode 100644
index 70c761036bd..00000000000
--- a/app/assets/images/emoji/flag_cp.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cr.png b/app/assets/images/emoji/flag_cr.png
deleted file mode 100644
index a5fce126515..00000000000
--- a/app/assets/images/emoji/flag_cr.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cu.png b/app/assets/images/emoji/flag_cu.png
deleted file mode 100644
index 447328f7dfd..00000000000
--- a/app/assets/images/emoji/flag_cu.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cv.png b/app/assets/images/emoji/flag_cv.png
deleted file mode 100644
index 43faf4d64d5..00000000000
--- a/app/assets/images/emoji/flag_cv.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cw.png b/app/assets/images/emoji/flag_cw.png
deleted file mode 100644
index eb39e8d0078..00000000000
--- a/app/assets/images/emoji/flag_cw.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cx.png b/app/assets/images/emoji/flag_cx.png
deleted file mode 100644
index 09d21359f3a..00000000000
--- a/app/assets/images/emoji/flag_cx.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cy.png b/app/assets/images/emoji/flag_cy.png
deleted file mode 100644
index 154a7aa3176..00000000000
--- a/app/assets/images/emoji/flag_cy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_cz.png b/app/assets/images/emoji/flag_cz.png
deleted file mode 100644
index 9737ca223c7..00000000000
--- a/app/assets/images/emoji/flag_cz.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_de.png b/app/assets/images/emoji/flag_de.png
deleted file mode 100644
index 98ed76b3bab..00000000000
--- a/app/assets/images/emoji/flag_de.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_dg.png b/app/assets/images/emoji/flag_dg.png
deleted file mode 100644
index aae927d14b8..00000000000
--- a/app/assets/images/emoji/flag_dg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_dj.png b/app/assets/images/emoji/flag_dj.png
deleted file mode 100644
index 73c2a2acbd9..00000000000
--- a/app/assets/images/emoji/flag_dj.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_dk.png b/app/assets/images/emoji/flag_dk.png
deleted file mode 100644
index e5a60b06256..00000000000
--- a/app/assets/images/emoji/flag_dk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_dm.png b/app/assets/images/emoji/flag_dm.png
deleted file mode 100644
index 50f8a53981d..00000000000
--- a/app/assets/images/emoji/flag_dm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_do.png b/app/assets/images/emoji/flag_do.png
deleted file mode 100644
index 037a45d7c26..00000000000
--- a/app/assets/images/emoji/flag_do.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_dz.png b/app/assets/images/emoji/flag_dz.png
deleted file mode 100644
index 24945b10f2d..00000000000
--- a/app/assets/images/emoji/flag_dz.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ea.png b/app/assets/images/emoji/flag_ea.png
deleted file mode 100644
index 356ff347838..00000000000
--- a/app/assets/images/emoji/flag_ea.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ec.png b/app/assets/images/emoji/flag_ec.png
deleted file mode 100644
index 13814594619..00000000000
--- a/app/assets/images/emoji/flag_ec.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ee.png b/app/assets/images/emoji/flag_ee.png
deleted file mode 100644
index 84f317e7747..00000000000
--- a/app/assets/images/emoji/flag_ee.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_eg.png b/app/assets/images/emoji/flag_eg.png
deleted file mode 100644
index 57786064a95..00000000000
--- a/app/assets/images/emoji/flag_eg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_eh.png b/app/assets/images/emoji/flag_eh.png
deleted file mode 100644
index 4d7a76687f6..00000000000
--- a/app/assets/images/emoji/flag_eh.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_er.png b/app/assets/images/emoji/flag_er.png
deleted file mode 100644
index 0c3c724c1fb..00000000000
--- a/app/assets/images/emoji/flag_er.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_es.png b/app/assets/images/emoji/flag_es.png
deleted file mode 100644
index 3e73597a225..00000000000
--- a/app/assets/images/emoji/flag_es.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_et.png b/app/assets/images/emoji/flag_et.png
deleted file mode 100644
index 9560a134c97..00000000000
--- a/app/assets/images/emoji/flag_et.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_eu.png b/app/assets/images/emoji/flag_eu.png
deleted file mode 100644
index 0b456cf3330..00000000000
--- a/app/assets/images/emoji/flag_eu.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_fi.png b/app/assets/images/emoji/flag_fi.png
deleted file mode 100644
index ebcf58abfc5..00000000000
--- a/app/assets/images/emoji/flag_fi.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_fj.png b/app/assets/images/emoji/flag_fj.png
deleted file mode 100644
index 9cc8c37fe37..00000000000
--- a/app/assets/images/emoji/flag_fj.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_fk.png b/app/assets/images/emoji/flag_fk.png
deleted file mode 100644
index 61372fd2549..00000000000
--- a/app/assets/images/emoji/flag_fk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_fm.png b/app/assets/images/emoji/flag_fm.png
deleted file mode 100644
index 0889825c8e1..00000000000
--- a/app/assets/images/emoji/flag_fm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_fo.png b/app/assets/images/emoji/flag_fo.png
deleted file mode 100644
index 9a4431b0831..00000000000
--- a/app/assets/images/emoji/flag_fo.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_fr.png b/app/assets/images/emoji/flag_fr.png
deleted file mode 100644
index 62ca19c3fcf..00000000000
--- a/app/assets/images/emoji/flag_fr.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ga.png b/app/assets/images/emoji/flag_ga.png
deleted file mode 100644
index 2e68e527a3e..00000000000
--- a/app/assets/images/emoji/flag_ga.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gb.png b/app/assets/images/emoji/flag_gb.png
deleted file mode 100644
index 3ed10f62347..00000000000
--- a/app/assets/images/emoji/flag_gb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gd.png b/app/assets/images/emoji/flag_gd.png
deleted file mode 100644
index 527aad33807..00000000000
--- a/app/assets/images/emoji/flag_gd.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ge.png b/app/assets/images/emoji/flag_ge.png
deleted file mode 100644
index a75d142480d..00000000000
--- a/app/assets/images/emoji/flag_ge.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gf.png b/app/assets/images/emoji/flag_gf.png
deleted file mode 100644
index 0cf96f327c0..00000000000
--- a/app/assets/images/emoji/flag_gf.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gg.png b/app/assets/images/emoji/flag_gg.png
deleted file mode 100644
index 970002c7f76..00000000000
--- a/app/assets/images/emoji/flag_gg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gh.png b/app/assets/images/emoji/flag_gh.png
deleted file mode 100644
index f31b5eb7b45..00000000000
--- a/app/assets/images/emoji/flag_gh.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gi.png b/app/assets/images/emoji/flag_gi.png
deleted file mode 100644
index e554a2a1d0c..00000000000
--- a/app/assets/images/emoji/flag_gi.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gl.png b/app/assets/images/emoji/flag_gl.png
deleted file mode 100644
index 2e795dd4e33..00000000000
--- a/app/assets/images/emoji/flag_gl.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gm.png b/app/assets/images/emoji/flag_gm.png
deleted file mode 100644
index bb69c0975a3..00000000000
--- a/app/assets/images/emoji/flag_gm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gn.png b/app/assets/images/emoji/flag_gn.png
deleted file mode 100644
index 1981f61dbf5..00000000000
--- a/app/assets/images/emoji/flag_gn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gp.png b/app/assets/images/emoji/flag_gp.png
deleted file mode 100644
index 10e42e672bd..00000000000
--- a/app/assets/images/emoji/flag_gp.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gq.png b/app/assets/images/emoji/flag_gq.png
deleted file mode 100644
index 11475e61eeb..00000000000
--- a/app/assets/images/emoji/flag_gq.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gr.png b/app/assets/images/emoji/flag_gr.png
deleted file mode 100644
index 0f6bb1b6b94..00000000000
--- a/app/assets/images/emoji/flag_gr.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gs.png b/app/assets/images/emoji/flag_gs.png
deleted file mode 100644
index 6fc92780453..00000000000
--- a/app/assets/images/emoji/flag_gs.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gt.png b/app/assets/images/emoji/flag_gt.png
deleted file mode 100644
index 7213d4139ed..00000000000
--- a/app/assets/images/emoji/flag_gt.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gu.png b/app/assets/images/emoji/flag_gu.png
deleted file mode 100644
index 4027549ca3c..00000000000
--- a/app/assets/images/emoji/flag_gu.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gw.png b/app/assets/images/emoji/flag_gw.png
deleted file mode 100644
index 6357f6225f4..00000000000
--- a/app/assets/images/emoji/flag_gw.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_gy.png b/app/assets/images/emoji/flag_gy.png
deleted file mode 100644
index 746e2fb7e44..00000000000
--- a/app/assets/images/emoji/flag_gy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_hk.png b/app/assets/images/emoji/flag_hk.png
deleted file mode 100644
index cf0c7151b56..00000000000
--- a/app/assets/images/emoji/flag_hk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_hm.png b/app/assets/images/emoji/flag_hm.png
deleted file mode 100644
index b613509e466..00000000000
--- a/app/assets/images/emoji/flag_hm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_hn.png b/app/assets/images/emoji/flag_hn.png
deleted file mode 100644
index 402cdcefdf8..00000000000
--- a/app/assets/images/emoji/flag_hn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_hr.png b/app/assets/images/emoji/flag_hr.png
deleted file mode 100644
index 46f4f06b4f2..00000000000
--- a/app/assets/images/emoji/flag_hr.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ht.png b/app/assets/images/emoji/flag_ht.png
deleted file mode 100644
index d8d0c888498..00000000000
--- a/app/assets/images/emoji/flag_ht.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_hu.png b/app/assets/images/emoji/flag_hu.png
deleted file mode 100644
index a898de636a5..00000000000
--- a/app/assets/images/emoji/flag_hu.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ic.png b/app/assets/images/emoji/flag_ic.png
deleted file mode 100644
index 69fd990aa95..00000000000
--- a/app/assets/images/emoji/flag_ic.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_id.png b/app/assets/images/emoji/flag_id.png
deleted file mode 100644
index 85b4c063a45..00000000000
--- a/app/assets/images/emoji/flag_id.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ie.png b/app/assets/images/emoji/flag_ie.png
deleted file mode 100644
index a28295838cc..00000000000
--- a/app/assets/images/emoji/flag_ie.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_il.png b/app/assets/images/emoji/flag_il.png
deleted file mode 100644
index 85c410d45fb..00000000000
--- a/app/assets/images/emoji/flag_il.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_im.png b/app/assets/images/emoji/flag_im.png
deleted file mode 100644
index 60a2458e38e..00000000000
--- a/app/assets/images/emoji/flag_im.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_in.png b/app/assets/images/emoji/flag_in.png
deleted file mode 100644
index feccc8952ce..00000000000
--- a/app/assets/images/emoji/flag_in.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_io.png b/app/assets/images/emoji/flag_io.png
deleted file mode 100644
index aae927d14b8..00000000000
--- a/app/assets/images/emoji/flag_io.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_iq.png b/app/assets/images/emoji/flag_iq.png
deleted file mode 100644
index 41fd1db6f86..00000000000
--- a/app/assets/images/emoji/flag_iq.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ir.png b/app/assets/images/emoji/flag_ir.png
deleted file mode 100644
index ff7aaf62ba6..00000000000
--- a/app/assets/images/emoji/flag_ir.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_is.png b/app/assets/images/emoji/flag_is.png
deleted file mode 100644
index ad8d4131dd2..00000000000
--- a/app/assets/images/emoji/flag_is.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_it.png b/app/assets/images/emoji/flag_it.png
deleted file mode 100644
index f21563ec533..00000000000
--- a/app/assets/images/emoji/flag_it.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_je.png b/app/assets/images/emoji/flag_je.png
deleted file mode 100644
index 198a918f6a4..00000000000
--- a/app/assets/images/emoji/flag_je.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_jm.png b/app/assets/images/emoji/flag_jm.png
deleted file mode 100644
index f84e4f9e8db..00000000000
--- a/app/assets/images/emoji/flag_jm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_jo.png b/app/assets/images/emoji/flag_jo.png
deleted file mode 100644
index 20bfa147e3e..00000000000
--- a/app/assets/images/emoji/flag_jo.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_jp.png b/app/assets/images/emoji/flag_jp.png
deleted file mode 100644
index 8d8838e4708..00000000000
--- a/app/assets/images/emoji/flag_jp.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ke.png b/app/assets/images/emoji/flag_ke.png
deleted file mode 100644
index 9e417ab3009..00000000000
--- a/app/assets/images/emoji/flag_ke.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_kg.png b/app/assets/images/emoji/flag_kg.png
deleted file mode 100644
index 2f2d848fe58..00000000000
--- a/app/assets/images/emoji/flag_kg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_kh.png b/app/assets/images/emoji/flag_kh.png
deleted file mode 100644
index 9a2877dd620..00000000000
--- a/app/assets/images/emoji/flag_kh.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ki.png b/app/assets/images/emoji/flag_ki.png
deleted file mode 100644
index 10e507e3245..00000000000
--- a/app/assets/images/emoji/flag_ki.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_km.png b/app/assets/images/emoji/flag_km.png
deleted file mode 100644
index bd5a0588e03..00000000000
--- a/app/assets/images/emoji/flag_km.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_kn.png b/app/assets/images/emoji/flag_kn.png
deleted file mode 100644
index 776207c9605..00000000000
--- a/app/assets/images/emoji/flag_kn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_kp.png b/app/assets/images/emoji/flag_kp.png
deleted file mode 100644
index 6b3fd89eaaa..00000000000
--- a/app/assets/images/emoji/flag_kp.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_kr.png b/app/assets/images/emoji/flag_kr.png
deleted file mode 100644
index 833a88116e1..00000000000
--- a/app/assets/images/emoji/flag_kr.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_kw.png b/app/assets/images/emoji/flag_kw.png
deleted file mode 100644
index 4d19bfa6ca7..00000000000
--- a/app/assets/images/emoji/flag_kw.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ky.png b/app/assets/images/emoji/flag_ky.png
deleted file mode 100644
index 40daa4da597..00000000000
--- a/app/assets/images/emoji/flag_ky.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_kz.png b/app/assets/images/emoji/flag_kz.png
deleted file mode 100644
index 2f97a8fd3c6..00000000000
--- a/app/assets/images/emoji/flag_kz.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_la.png b/app/assets/images/emoji/flag_la.png
deleted file mode 100644
index 4d4179f34f6..00000000000
--- a/app/assets/images/emoji/flag_la.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_lb.png b/app/assets/images/emoji/flag_lb.png
deleted file mode 100644
index 3d594467011..00000000000
--- a/app/assets/images/emoji/flag_lb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_lc.png b/app/assets/images/emoji/flag_lc.png
deleted file mode 100644
index 45547b1e439..00000000000
--- a/app/assets/images/emoji/flag_lc.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_li.png b/app/assets/images/emoji/flag_li.png
deleted file mode 100644
index 0eafa6a2215..00000000000
--- a/app/assets/images/emoji/flag_li.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_lk.png b/app/assets/images/emoji/flag_lk.png
deleted file mode 100644
index ab4fe10c40c..00000000000
--- a/app/assets/images/emoji/flag_lk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_lr.png b/app/assets/images/emoji/flag_lr.png
deleted file mode 100644
index f66f267fea2..00000000000
--- a/app/assets/images/emoji/flag_lr.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ls.png b/app/assets/images/emoji/flag_ls.png
deleted file mode 100644
index 24745631e3c..00000000000
--- a/app/assets/images/emoji/flag_ls.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_lt.png b/app/assets/images/emoji/flag_lt.png
deleted file mode 100644
index d644b56d62a..00000000000
--- a/app/assets/images/emoji/flag_lt.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_lu.png b/app/assets/images/emoji/flag_lu.png
deleted file mode 100644
index a2df9c92994..00000000000
--- a/app/assets/images/emoji/flag_lu.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_lv.png b/app/assets/images/emoji/flag_lv.png
deleted file mode 100644
index ae680d5f0e3..00000000000
--- a/app/assets/images/emoji/flag_lv.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ly.png b/app/assets/images/emoji/flag_ly.png
deleted file mode 100644
index f6e77b0f3ba..00000000000
--- a/app/assets/images/emoji/flag_ly.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ma.png b/app/assets/images/emoji/flag_ma.png
deleted file mode 100644
index c4a056722cd..00000000000
--- a/app/assets/images/emoji/flag_ma.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mc.png b/app/assets/images/emoji/flag_mc.png
deleted file mode 100644
index d479eab98cb..00000000000
--- a/app/assets/images/emoji/flag_mc.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_md.png b/app/assets/images/emoji/flag_md.png
deleted file mode 100644
index a7a72539872..00000000000
--- a/app/assets/images/emoji/flag_md.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_me.png b/app/assets/images/emoji/flag_me.png
deleted file mode 100644
index 7c771e7e120..00000000000
--- a/app/assets/images/emoji/flag_me.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mf.png b/app/assets/images/emoji/flag_mf.png
deleted file mode 100644
index 70c761036bd..00000000000
--- a/app/assets/images/emoji/flag_mf.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mg.png b/app/assets/images/emoji/flag_mg.png
deleted file mode 100644
index 2f3ccdda76f..00000000000
--- a/app/assets/images/emoji/flag_mg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mh.png b/app/assets/images/emoji/flag_mh.png
deleted file mode 100644
index 598016481c1..00000000000
--- a/app/assets/images/emoji/flag_mh.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mk.png b/app/assets/images/emoji/flag_mk.png
deleted file mode 100644
index 7ba775ee75c..00000000000
--- a/app/assets/images/emoji/flag_mk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ml.png b/app/assets/images/emoji/flag_ml.png
deleted file mode 100644
index 68343785468..00000000000
--- a/app/assets/images/emoji/flag_ml.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mm.png b/app/assets/images/emoji/flag_mm.png
deleted file mode 100644
index 37dc7d71591..00000000000
--- a/app/assets/images/emoji/flag_mm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mn.png b/app/assets/images/emoji/flag_mn.png
deleted file mode 100644
index 1f146bbcd1a..00000000000
--- a/app/assets/images/emoji/flag_mn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mo.png b/app/assets/images/emoji/flag_mo.png
deleted file mode 100644
index 7edde31f64b..00000000000
--- a/app/assets/images/emoji/flag_mo.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mp.png b/app/assets/images/emoji/flag_mp.png
deleted file mode 100644
index 17ec1c441ed..00000000000
--- a/app/assets/images/emoji/flag_mp.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mq.png b/app/assets/images/emoji/flag_mq.png
deleted file mode 100644
index 1e672dc9087..00000000000
--- a/app/assets/images/emoji/flag_mq.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mr.png b/app/assets/images/emoji/flag_mr.png
deleted file mode 100644
index f87de46effe..00000000000
--- a/app/assets/images/emoji/flag_mr.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ms.png b/app/assets/images/emoji/flag_ms.png
deleted file mode 100644
index 480b0d4ebda..00000000000
--- a/app/assets/images/emoji/flag_ms.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mt.png b/app/assets/images/emoji/flag_mt.png
deleted file mode 100644
index c9e1dbdce82..00000000000
--- a/app/assets/images/emoji/flag_mt.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mu.png b/app/assets/images/emoji/flag_mu.png
deleted file mode 100644
index 55b33cb7c33..00000000000
--- a/app/assets/images/emoji/flag_mu.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mv.png b/app/assets/images/emoji/flag_mv.png
deleted file mode 100644
index ce5867126ae..00000000000
--- a/app/assets/images/emoji/flag_mv.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mw.png b/app/assets/images/emoji/flag_mw.png
deleted file mode 100644
index 003d8548401..00000000000
--- a/app/assets/images/emoji/flag_mw.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mx.png b/app/assets/images/emoji/flag_mx.png
deleted file mode 100644
index 42572bcd0ba..00000000000
--- a/app/assets/images/emoji/flag_mx.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_my.png b/app/assets/images/emoji/flag_my.png
deleted file mode 100644
index 17526c26742..00000000000
--- a/app/assets/images/emoji/flag_my.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_mz.png b/app/assets/images/emoji/flag_mz.png
deleted file mode 100644
index 2352a78e786..00000000000
--- a/app/assets/images/emoji/flag_mz.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_na.png b/app/assets/images/emoji/flag_na.png
deleted file mode 100644
index ed31c3df04d..00000000000
--- a/app/assets/images/emoji/flag_na.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_nc.png b/app/assets/images/emoji/flag_nc.png
deleted file mode 100644
index 90b3afebfa3..00000000000
--- a/app/assets/images/emoji/flag_nc.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ne.png b/app/assets/images/emoji/flag_ne.png
deleted file mode 100644
index f98a1173c2a..00000000000
--- a/app/assets/images/emoji/flag_ne.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_nf.png b/app/assets/images/emoji/flag_nf.png
deleted file mode 100644
index 9099e767420..00000000000
--- a/app/assets/images/emoji/flag_nf.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ng.png b/app/assets/images/emoji/flag_ng.png
deleted file mode 100644
index ea0abeff1a1..00000000000
--- a/app/assets/images/emoji/flag_ng.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ni.png b/app/assets/images/emoji/flag_ni.png
deleted file mode 100644
index 772920dfa10..00000000000
--- a/app/assets/images/emoji/flag_ni.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_nl.png b/app/assets/images/emoji/flag_nl.png
deleted file mode 100644
index 83a0e817e41..00000000000
--- a/app/assets/images/emoji/flag_nl.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_no.png b/app/assets/images/emoji/flag_no.png
deleted file mode 100644
index 99d3142eb7b..00000000000
--- a/app/assets/images/emoji/flag_no.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_np.png b/app/assets/images/emoji/flag_np.png
deleted file mode 100644
index 87425a8dfef..00000000000
--- a/app/assets/images/emoji/flag_np.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_nr.png b/app/assets/images/emoji/flag_nr.png
deleted file mode 100644
index b3e3a5d5621..00000000000
--- a/app/assets/images/emoji/flag_nr.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_nu.png b/app/assets/images/emoji/flag_nu.png
deleted file mode 100644
index f03614443ee..00000000000
--- a/app/assets/images/emoji/flag_nu.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_nz.png b/app/assets/images/emoji/flag_nz.png
deleted file mode 100644
index a4eeeab9cd9..00000000000
--- a/app/assets/images/emoji/flag_nz.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_om.png b/app/assets/images/emoji/flag_om.png
deleted file mode 100644
index ea824ba31e7..00000000000
--- a/app/assets/images/emoji/flag_om.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_pa.png b/app/assets/images/emoji/flag_pa.png
deleted file mode 100644
index c3091d89889..00000000000
--- a/app/assets/images/emoji/flag_pa.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_pe.png b/app/assets/images/emoji/flag_pe.png
deleted file mode 100644
index 39223aa9dbb..00000000000
--- a/app/assets/images/emoji/flag_pe.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_pf.png b/app/assets/images/emoji/flag_pf.png
deleted file mode 100644
index 113445f8f6e..00000000000
--- a/app/assets/images/emoji/flag_pf.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_pg.png b/app/assets/images/emoji/flag_pg.png
deleted file mode 100644
index 825e9dcb762..00000000000
--- a/app/assets/images/emoji/flag_pg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ph.png b/app/assets/images/emoji/flag_ph.png
deleted file mode 100644
index 8260e15bd2c..00000000000
--- a/app/assets/images/emoji/flag_ph.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_pk.png b/app/assets/images/emoji/flag_pk.png
deleted file mode 100644
index a7b6a1c5074..00000000000
--- a/app/assets/images/emoji/flag_pk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_pl.png b/app/assets/images/emoji/flag_pl.png
deleted file mode 100644
index 19de2edec11..00000000000
--- a/app/assets/images/emoji/flag_pl.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_pm.png b/app/assets/images/emoji/flag_pm.png
deleted file mode 100644
index 2ca60554193..00000000000
--- a/app/assets/images/emoji/flag_pm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_pn.png b/app/assets/images/emoji/flag_pn.png
deleted file mode 100644
index f2263b154bc..00000000000
--- a/app/assets/images/emoji/flag_pn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_pr.png b/app/assets/images/emoji/flag_pr.png
deleted file mode 100644
index d0209cddb79..00000000000
--- a/app/assets/images/emoji/flag_pr.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ps.png b/app/assets/images/emoji/flag_ps.png
deleted file mode 100644
index 7ccab09778b..00000000000
--- a/app/assets/images/emoji/flag_ps.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_pt.png b/app/assets/images/emoji/flag_pt.png
deleted file mode 100644
index cc93f27c64b..00000000000
--- a/app/assets/images/emoji/flag_pt.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_pw.png b/app/assets/images/emoji/flag_pw.png
deleted file mode 100644
index 154b2f12d3c..00000000000
--- a/app/assets/images/emoji/flag_pw.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_py.png b/app/assets/images/emoji/flag_py.png
deleted file mode 100644
index 662ad2f6ff1..00000000000
--- a/app/assets/images/emoji/flag_py.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_qa.png b/app/assets/images/emoji/flag_qa.png
deleted file mode 100644
index a01d8b05cc7..00000000000
--- a/app/assets/images/emoji/flag_qa.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_re.png b/app/assets/images/emoji/flag_re.png
deleted file mode 100644
index 57f2bbe9df8..00000000000
--- a/app/assets/images/emoji/flag_re.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ro.png b/app/assets/images/emoji/flag_ro.png
deleted file mode 100644
index 3e48c447706..00000000000
--- a/app/assets/images/emoji/flag_ro.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_rs.png b/app/assets/images/emoji/flag_rs.png
deleted file mode 100644
index 9df6c9a5235..00000000000
--- a/app/assets/images/emoji/flag_rs.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ru.png b/app/assets/images/emoji/flag_ru.png
deleted file mode 100644
index e50c9db90e7..00000000000
--- a/app/assets/images/emoji/flag_ru.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_rw.png b/app/assets/images/emoji/flag_rw.png
deleted file mode 100644
index c238c874e1d..00000000000
--- a/app/assets/images/emoji/flag_rw.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sa.png b/app/assets/images/emoji/flag_sa.png
deleted file mode 100644
index 4941be7d198..00000000000
--- a/app/assets/images/emoji/flag_sa.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sb.png b/app/assets/images/emoji/flag_sb.png
deleted file mode 100644
index 7d8f1ac6130..00000000000
--- a/app/assets/images/emoji/flag_sb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sc.png b/app/assets/images/emoji/flag_sc.png
deleted file mode 100644
index 6ae4d90765e..00000000000
--- a/app/assets/images/emoji/flag_sc.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sd.png b/app/assets/images/emoji/flag_sd.png
deleted file mode 100644
index 963be1b36fb..00000000000
--- a/app/assets/images/emoji/flag_sd.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_se.png b/app/assets/images/emoji/flag_se.png
deleted file mode 100644
index fc0d0e0ce89..00000000000
--- a/app/assets/images/emoji/flag_se.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sg.png b/app/assets/images/emoji/flag_sg.png
deleted file mode 100644
index de3c7737c42..00000000000
--- a/app/assets/images/emoji/flag_sg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sh.png b/app/assets/images/emoji/flag_sh.png
deleted file mode 100644
index 40cd9e44e96..00000000000
--- a/app/assets/images/emoji/flag_sh.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_si.png b/app/assets/images/emoji/flag_si.png
deleted file mode 100644
index e308999dba2..00000000000
--- a/app/assets/images/emoji/flag_si.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sj.png b/app/assets/images/emoji/flag_sj.png
deleted file mode 100644
index 5884e648228..00000000000
--- a/app/assets/images/emoji/flag_sj.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sk.png b/app/assets/images/emoji/flag_sk.png
deleted file mode 100644
index 4259d0e1418..00000000000
--- a/app/assets/images/emoji/flag_sk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sl.png b/app/assets/images/emoji/flag_sl.png
deleted file mode 100644
index d2cc68830ab..00000000000
--- a/app/assets/images/emoji/flag_sl.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sm.png b/app/assets/images/emoji/flag_sm.png
deleted file mode 100644
index 03b8708754e..00000000000
--- a/app/assets/images/emoji/flag_sm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sn.png b/app/assets/images/emoji/flag_sn.png
deleted file mode 100644
index 5368bbe93df..00000000000
--- a/app/assets/images/emoji/flag_sn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_so.png b/app/assets/images/emoji/flag_so.png
deleted file mode 100644
index 68a0597365a..00000000000
--- a/app/assets/images/emoji/flag_so.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sr.png b/app/assets/images/emoji/flag_sr.png
deleted file mode 100644
index d3251327035..00000000000
--- a/app/assets/images/emoji/flag_sr.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ss.png b/app/assets/images/emoji/flag_ss.png
deleted file mode 100644
index 122977e798f..00000000000
--- a/app/assets/images/emoji/flag_ss.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_st.png b/app/assets/images/emoji/flag_st.png
deleted file mode 100644
index f83a863d612..00000000000
--- a/app/assets/images/emoji/flag_st.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sv.png b/app/assets/images/emoji/flag_sv.png
deleted file mode 100644
index efb83e2f253..00000000000
--- a/app/assets/images/emoji/flag_sv.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sx.png b/app/assets/images/emoji/flag_sx.png
deleted file mode 100644
index 94b760fbedf..00000000000
--- a/app/assets/images/emoji/flag_sx.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sy.png b/app/assets/images/emoji/flag_sy.png
deleted file mode 100644
index 09a8ee8f78c..00000000000
--- a/app/assets/images/emoji/flag_sy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_sz.png b/app/assets/images/emoji/flag_sz.png
deleted file mode 100644
index f74e82ea1fd..00000000000
--- a/app/assets/images/emoji/flag_sz.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ta.png b/app/assets/images/emoji/flag_ta.png
deleted file mode 100644
index b44283e90e2..00000000000
--- a/app/assets/images/emoji/flag_ta.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tc.png b/app/assets/images/emoji/flag_tc.png
deleted file mode 100644
index 156b33d1ba6..00000000000
--- a/app/assets/images/emoji/flag_tc.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_td.png b/app/assets/images/emoji/flag_td.png
deleted file mode 100644
index ebe7f592828..00000000000
--- a/app/assets/images/emoji/flag_td.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tf.png b/app/assets/images/emoji/flag_tf.png
deleted file mode 100644
index a1a3ad68ee2..00000000000
--- a/app/assets/images/emoji/flag_tf.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tg.png b/app/assets/images/emoji/flag_tg.png
deleted file mode 100644
index 826b73c9ac5..00000000000
--- a/app/assets/images/emoji/flag_tg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_th.png b/app/assets/images/emoji/flag_th.png
deleted file mode 100644
index 93ff542c5a6..00000000000
--- a/app/assets/images/emoji/flag_th.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tj.png b/app/assets/images/emoji/flag_tj.png
deleted file mode 100644
index 7a8a0b6190a..00000000000
--- a/app/assets/images/emoji/flag_tj.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tk.png b/app/assets/images/emoji/flag_tk.png
deleted file mode 100644
index 2fa5a21b1bb..00000000000
--- a/app/assets/images/emoji/flag_tk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tl.png b/app/assets/images/emoji/flag_tl.png
deleted file mode 100644
index 5b120eccc6f..00000000000
--- a/app/assets/images/emoji/flag_tl.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tm.png b/app/assets/images/emoji/flag_tm.png
deleted file mode 100644
index c3c4f532302..00000000000
--- a/app/assets/images/emoji/flag_tm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tn.png b/app/assets/images/emoji/flag_tn.png
deleted file mode 100644
index 58ef161229f..00000000000
--- a/app/assets/images/emoji/flag_tn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_to.png b/app/assets/images/emoji/flag_to.png
deleted file mode 100644
index 1ffa7bb9d19..00000000000
--- a/app/assets/images/emoji/flag_to.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tr.png b/app/assets/images/emoji/flag_tr.png
deleted file mode 100644
index 325251fae88..00000000000
--- a/app/assets/images/emoji/flag_tr.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tt.png b/app/assets/images/emoji/flag_tt.png
deleted file mode 100644
index ed3bb39a300..00000000000
--- a/app/assets/images/emoji/flag_tt.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tv.png b/app/assets/images/emoji/flag_tv.png
deleted file mode 100644
index e82c65c7bb9..00000000000
--- a/app/assets/images/emoji/flag_tv.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tw.png b/app/assets/images/emoji/flag_tw.png
deleted file mode 100644
index 3a8f00b5928..00000000000
--- a/app/assets/images/emoji/flag_tw.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_tz.png b/app/assets/images/emoji/flag_tz.png
deleted file mode 100644
index 2a020853d4e..00000000000
--- a/app/assets/images/emoji/flag_tz.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ua.png b/app/assets/images/emoji/flag_ua.png
deleted file mode 100644
index cd84d1bbd36..00000000000
--- a/app/assets/images/emoji/flag_ua.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ug.png b/app/assets/images/emoji/flag_ug.png
deleted file mode 100644
index dc97690eb55..00000000000
--- a/app/assets/images/emoji/flag_ug.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_um.png b/app/assets/images/emoji/flag_um.png
deleted file mode 100644
index 4a7ee3cdf13..00000000000
--- a/app/assets/images/emoji/flag_um.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_us.png b/app/assets/images/emoji/flag_us.png
deleted file mode 100644
index 9f730305860..00000000000
--- a/app/assets/images/emoji/flag_us.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_uy.png b/app/assets/images/emoji/flag_uy.png
deleted file mode 100644
index b8002a697a6..00000000000
--- a/app/assets/images/emoji/flag_uy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_uz.png b/app/assets/images/emoji/flag_uz.png
deleted file mode 100644
index d56ca9bc424..00000000000
--- a/app/assets/images/emoji/flag_uz.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_va.png b/app/assets/images/emoji/flag_va.png
deleted file mode 100644
index ddaf5e3141b..00000000000
--- a/app/assets/images/emoji/flag_va.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_vc.png b/app/assets/images/emoji/flag_vc.png
deleted file mode 100644
index 43703c62a71..00000000000
--- a/app/assets/images/emoji/flag_vc.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ve.png b/app/assets/images/emoji/flag_ve.png
deleted file mode 100644
index 1b62796824e..00000000000
--- a/app/assets/images/emoji/flag_ve.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_vg.png b/app/assets/images/emoji/flag_vg.png
deleted file mode 100644
index 536f780f1c0..00000000000
--- a/app/assets/images/emoji/flag_vg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_vi.png b/app/assets/images/emoji/flag_vi.png
deleted file mode 100644
index 64102012cfe..00000000000
--- a/app/assets/images/emoji/flag_vi.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_vn.png b/app/assets/images/emoji/flag_vn.png
deleted file mode 100644
index 427036046b6..00000000000
--- a/app/assets/images/emoji/flag_vn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_vu.png b/app/assets/images/emoji/flag_vu.png
deleted file mode 100644
index 706eba44070..00000000000
--- a/app/assets/images/emoji/flag_vu.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_wf.png b/app/assets/images/emoji/flag_wf.png
deleted file mode 100644
index 70c761036bd..00000000000
--- a/app/assets/images/emoji/flag_wf.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_white.png b/app/assets/images/emoji/flag_white.png
deleted file mode 100644
index 86d6e96d5e9..00000000000
--- a/app/assets/images/emoji/flag_white.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ws.png b/app/assets/images/emoji/flag_ws.png
deleted file mode 100644
index a1ea0703141..00000000000
--- a/app/assets/images/emoji/flag_ws.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_xk.png b/app/assets/images/emoji/flag_xk.png
deleted file mode 100644
index e587a446632..00000000000
--- a/app/assets/images/emoji/flag_xk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_ye.png b/app/assets/images/emoji/flag_ye.png
deleted file mode 100644
index eadfebd5f67..00000000000
--- a/app/assets/images/emoji/flag_ye.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_yt.png b/app/assets/images/emoji/flag_yt.png
deleted file mode 100644
index c81fa6d886e..00000000000
--- a/app/assets/images/emoji/flag_yt.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_za.png b/app/assets/images/emoji/flag_za.png
deleted file mode 100644
index f397ef5072f..00000000000
--- a/app/assets/images/emoji/flag_za.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_zm.png b/app/assets/images/emoji/flag_zm.png
deleted file mode 100644
index 2494a31f662..00000000000
--- a/app/assets/images/emoji/flag_zm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flag_zw.png b/app/assets/images/emoji/flag_zw.png
deleted file mode 100644
index e09b9652be6..00000000000
--- a/app/assets/images/emoji/flag_zw.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flags.png b/app/assets/images/emoji/flags.png
deleted file mode 100644
index 3b451035a3a..00000000000
--- a/app/assets/images/emoji/flags.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flashlight.png b/app/assets/images/emoji/flashlight.png
deleted file mode 100644
index eee36c25067..00000000000
--- a/app/assets/images/emoji/flashlight.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fleur-de-lis.png b/app/assets/images/emoji/fleur-de-lis.png
deleted file mode 100644
index c9250d27fa7..00000000000
--- a/app/assets/images/emoji/fleur-de-lis.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/floppy_disk.png b/app/assets/images/emoji/floppy_disk.png
deleted file mode 100644
index 072a76d3c13..00000000000
--- a/app/assets/images/emoji/floppy_disk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flower_playing_cards.png b/app/assets/images/emoji/flower_playing_cards.png
deleted file mode 100644
index 6766b044d95..00000000000
--- a/app/assets/images/emoji/flower_playing_cards.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/flushed.png b/app/assets/images/emoji/flushed.png
deleted file mode 100644
index 829220bc470..00000000000
--- a/app/assets/images/emoji/flushed.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fog.png b/app/assets/images/emoji/fog.png
deleted file mode 100644
index 4e73c2de272..00000000000
--- a/app/assets/images/emoji/fog.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/foggy.png b/app/assets/images/emoji/foggy.png
deleted file mode 100644
index 57702d8d3ac..00000000000
--- a/app/assets/images/emoji/foggy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/football.png b/app/assets/images/emoji/football.png
deleted file mode 100644
index 10366f41fce..00000000000
--- a/app/assets/images/emoji/football.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/footprints.png b/app/assets/images/emoji/footprints.png
deleted file mode 100644
index b2673c5a1a8..00000000000
--- a/app/assets/images/emoji/footprints.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fork_and_knife.png b/app/assets/images/emoji/fork_and_knife.png
deleted file mode 100644
index 09f1feaea1c..00000000000
--- a/app/assets/images/emoji/fork_and_knife.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fork_knife_plate.png b/app/assets/images/emoji/fork_knife_plate.png
deleted file mode 100644
index 7411755f708..00000000000
--- a/app/assets/images/emoji/fork_knife_plate.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fountain.png b/app/assets/images/emoji/fountain.png
deleted file mode 100644
index 293f5d91c0f..00000000000
--- a/app/assets/images/emoji/fountain.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/four.png b/app/assets/images/emoji/four.png
deleted file mode 100644
index b0e914aac45..00000000000
--- a/app/assets/images/emoji/four.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/four_leaf_clover.png b/app/assets/images/emoji/four_leaf_clover.png
deleted file mode 100644
index fdedfcc2b4e..00000000000
--- a/app/assets/images/emoji/four_leaf_clover.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fox.png b/app/assets/images/emoji/fox.png
deleted file mode 100644
index 1ab339bf054..00000000000
--- a/app/assets/images/emoji/fox.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/frame_photo.png b/app/assets/images/emoji/frame_photo.png
deleted file mode 100644
index 9fe84607bfd..00000000000
--- a/app/assets/images/emoji/frame_photo.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/free.png b/app/assets/images/emoji/free.png
deleted file mode 100644
index b71956eb48a..00000000000
--- a/app/assets/images/emoji/free.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/french_bread.png b/app/assets/images/emoji/french_bread.png
deleted file mode 100644
index 4c2c5639822..00000000000
--- a/app/assets/images/emoji/french_bread.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fried_shrimp.png b/app/assets/images/emoji/fried_shrimp.png
deleted file mode 100644
index 752ba7f1398..00000000000
--- a/app/assets/images/emoji/fried_shrimp.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fries.png b/app/assets/images/emoji/fries.png
deleted file mode 100644
index 4e2a4caacef..00000000000
--- a/app/assets/images/emoji/fries.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/frog.png b/app/assets/images/emoji/frog.png
deleted file mode 100644
index 8825d1ad577..00000000000
--- a/app/assets/images/emoji/frog.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/frowning.png b/app/assets/images/emoji/frowning.png
deleted file mode 100644
index 43ab6b0a1c1..00000000000
--- a/app/assets/images/emoji/frowning.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/frowning2.png b/app/assets/images/emoji/frowning2.png
deleted file mode 100644
index 6ae71f233b9..00000000000
--- a/app/assets/images/emoji/frowning2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/fuelpump.png b/app/assets/images/emoji/fuelpump.png
deleted file mode 100644
index 05b18794474..00000000000
--- a/app/assets/images/emoji/fuelpump.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/full_moon.png b/app/assets/images/emoji/full_moon.png
deleted file mode 100644
index c9a2d6aa7c9..00000000000
--- a/app/assets/images/emoji/full_moon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/full_moon_with_face.png b/app/assets/images/emoji/full_moon_with_face.png
deleted file mode 100644
index a5c25bbaf64..00000000000
--- a/app/assets/images/emoji/full_moon_with_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/game_die.png b/app/assets/images/emoji/game_die.png
deleted file mode 100644
index ad3626fe5e5..00000000000
--- a/app/assets/images/emoji/game_die.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/gay_pride_flag.png b/app/assets/images/emoji/gay_pride_flag.png
deleted file mode 100644
index 1bec5f2ffd7..00000000000
--- a/app/assets/images/emoji/gay_pride_flag.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/gear.png b/app/assets/images/emoji/gear.png
deleted file mode 100644
index 2a1cc2c0ff4..00000000000
--- a/app/assets/images/emoji/gear.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/gem.png b/app/assets/images/emoji/gem.png
deleted file mode 100644
index db122d26a19..00000000000
--- a/app/assets/images/emoji/gem.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/gemini.png b/app/assets/images/emoji/gemini.png
deleted file mode 100644
index 1a09698cf00..00000000000
--- a/app/assets/images/emoji/gemini.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ghost.png b/app/assets/images/emoji/ghost.png
deleted file mode 100644
index 5650bc0ed18..00000000000
--- a/app/assets/images/emoji/ghost.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/gift.png b/app/assets/images/emoji/gift.png
deleted file mode 100644
index 844e2164560..00000000000
--- a/app/assets/images/emoji/gift.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/gift_heart.png b/app/assets/images/emoji/gift_heart.png
deleted file mode 100644
index 902ceafe4d1..00000000000
--- a/app/assets/images/emoji/gift_heart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/girl.png b/app/assets/images/emoji/girl.png
deleted file mode 100644
index dc1d4d08b39..00000000000
--- a/app/assets/images/emoji/girl.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/girl_tone1.png b/app/assets/images/emoji/girl_tone1.png
deleted file mode 100644
index bb667e88651..00000000000
--- a/app/assets/images/emoji/girl_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/girl_tone2.png b/app/assets/images/emoji/girl_tone2.png
deleted file mode 100644
index a59ed4a3f0d..00000000000
--- a/app/assets/images/emoji/girl_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/girl_tone3.png b/app/assets/images/emoji/girl_tone3.png
deleted file mode 100644
index 517e7f2a7b0..00000000000
--- a/app/assets/images/emoji/girl_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/girl_tone4.png b/app/assets/images/emoji/girl_tone4.png
deleted file mode 100644
index 542d96c8487..00000000000
--- a/app/assets/images/emoji/girl_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/girl_tone5.png b/app/assets/images/emoji/girl_tone5.png
deleted file mode 100644
index 66b7c28c2df..00000000000
--- a/app/assets/images/emoji/girl_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/globe_with_meridians.png b/app/assets/images/emoji/globe_with_meridians.png
deleted file mode 100644
index 82450c1a4ba..00000000000
--- a/app/assets/images/emoji/globe_with_meridians.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/goal.png b/app/assets/images/emoji/goal.png
deleted file mode 100644
index df3a53da0fb..00000000000
--- a/app/assets/images/emoji/goal.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/goat.png b/app/assets/images/emoji/goat.png
deleted file mode 100644
index f9d9e38a128..00000000000
--- a/app/assets/images/emoji/goat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/golf.png b/app/assets/images/emoji/golf.png
deleted file mode 100644
index f65a21d8a46..00000000000
--- a/app/assets/images/emoji/golf.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/golfer.png b/app/assets/images/emoji/golfer.png
deleted file mode 100644
index 39c552de86d..00000000000
--- a/app/assets/images/emoji/golfer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/gorilla.png b/app/assets/images/emoji/gorilla.png
deleted file mode 100644
index acc51e13622..00000000000
--- a/app/assets/images/emoji/gorilla.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/grapes.png b/app/assets/images/emoji/grapes.png
deleted file mode 100644
index 30d22218896..00000000000
--- a/app/assets/images/emoji/grapes.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/green_apple.png b/app/assets/images/emoji/green_apple.png
deleted file mode 100644
index 5fd51bd3915..00000000000
--- a/app/assets/images/emoji/green_apple.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/green_book.png b/app/assets/images/emoji/green_book.png
deleted file mode 100644
index e5e411cf3b5..00000000000
--- a/app/assets/images/emoji/green_book.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/green_heart.png b/app/assets/images/emoji/green_heart.png
deleted file mode 100644
index c52d60a58be..00000000000
--- a/app/assets/images/emoji/green_heart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/grey_exclamation.png b/app/assets/images/emoji/grey_exclamation.png
deleted file mode 100644
index 9b64da8bf7f..00000000000
--- a/app/assets/images/emoji/grey_exclamation.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/grey_question.png b/app/assets/images/emoji/grey_question.png
deleted file mode 100644
index 6e7824c75f6..00000000000
--- a/app/assets/images/emoji/grey_question.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/grimacing.png b/app/assets/images/emoji/grimacing.png
deleted file mode 100644
index 871b2f071c9..00000000000
--- a/app/assets/images/emoji/grimacing.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/grin.png b/app/assets/images/emoji/grin.png
deleted file mode 100644
index 418d94c811b..00000000000
--- a/app/assets/images/emoji/grin.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/grinning.png b/app/assets/images/emoji/grinning.png
deleted file mode 100644
index 3e8e0dab78c..00000000000
--- a/app/assets/images/emoji/grinning.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/guardsman.png b/app/assets/images/emoji/guardsman.png
deleted file mode 100644
index 8d7ab3c473c..00000000000
--- a/app/assets/images/emoji/guardsman.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/guardsman_tone1.png b/app/assets/images/emoji/guardsman_tone1.png
deleted file mode 100644
index cea9ba27468..00000000000
--- a/app/assets/images/emoji/guardsman_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/guardsman_tone2.png b/app/assets/images/emoji/guardsman_tone2.png
deleted file mode 100644
index 037464e4028..00000000000
--- a/app/assets/images/emoji/guardsman_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/guardsman_tone3.png b/app/assets/images/emoji/guardsman_tone3.png
deleted file mode 100644
index 0f6726fbe87..00000000000
--- a/app/assets/images/emoji/guardsman_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/guardsman_tone4.png b/app/assets/images/emoji/guardsman_tone4.png
deleted file mode 100644
index 85fcf9a3b97..00000000000
--- a/app/assets/images/emoji/guardsman_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/guardsman_tone5.png b/app/assets/images/emoji/guardsman_tone5.png
deleted file mode 100644
index e5f9ca7d5a2..00000000000
--- a/app/assets/images/emoji/guardsman_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/guitar.png b/app/assets/images/emoji/guitar.png
deleted file mode 100644
index 43d752f1e3d..00000000000
--- a/app/assets/images/emoji/guitar.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/gun.png b/app/assets/images/emoji/gun.png
deleted file mode 100644
index 89c5c244c7b..00000000000
--- a/app/assets/images/emoji/gun.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/haircut.png b/app/assets/images/emoji/haircut.png
deleted file mode 100644
index 91266b12930..00000000000
--- a/app/assets/images/emoji/haircut.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/haircut_tone1.png b/app/assets/images/emoji/haircut_tone1.png
deleted file mode 100644
index c743b74abeb..00000000000
--- a/app/assets/images/emoji/haircut_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/haircut_tone2.png b/app/assets/images/emoji/haircut_tone2.png
deleted file mode 100644
index f144f8e55ce..00000000000
--- a/app/assets/images/emoji/haircut_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/haircut_tone3.png b/app/assets/images/emoji/haircut_tone3.png
deleted file mode 100644
index d5ad19563ac..00000000000
--- a/app/assets/images/emoji/haircut_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/haircut_tone4.png b/app/assets/images/emoji/haircut_tone4.png
deleted file mode 100644
index 244fd3af008..00000000000
--- a/app/assets/images/emoji/haircut_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/haircut_tone5.png b/app/assets/images/emoji/haircut_tone5.png
deleted file mode 100644
index 20a94a88623..00000000000
--- a/app/assets/images/emoji/haircut_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hamburger.png b/app/assets/images/emoji/hamburger.png
deleted file mode 100644
index 3573b28a1fd..00000000000
--- a/app/assets/images/emoji/hamburger.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hammer.png b/app/assets/images/emoji/hammer.png
deleted file mode 100644
index 00736cce47d..00000000000
--- a/app/assets/images/emoji/hammer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hammer_pick.png b/app/assets/images/emoji/hammer_pick.png
deleted file mode 100644
index 3bee30ec588..00000000000
--- a/app/assets/images/emoji/hammer_pick.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hamster.png b/app/assets/images/emoji/hamster.png
deleted file mode 100644
index 9a04388e4e7..00000000000
--- a/app/assets/images/emoji/hamster.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hand_splayed.png b/app/assets/images/emoji/hand_splayed.png
deleted file mode 100644
index fb5ae8ebb5a..00000000000
--- a/app/assets/images/emoji/hand_splayed.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hand_splayed_tone1.png b/app/assets/images/emoji/hand_splayed_tone1.png
deleted file mode 100644
index a7888e6bd23..00000000000
--- a/app/assets/images/emoji/hand_splayed_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hand_splayed_tone2.png b/app/assets/images/emoji/hand_splayed_tone2.png
deleted file mode 100644
index cc10fbc272d..00000000000
--- a/app/assets/images/emoji/hand_splayed_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hand_splayed_tone3.png b/app/assets/images/emoji/hand_splayed_tone3.png
deleted file mode 100644
index 707236ae8a4..00000000000
--- a/app/assets/images/emoji/hand_splayed_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hand_splayed_tone4.png b/app/assets/images/emoji/hand_splayed_tone4.png
deleted file mode 100644
index 1430df9c61f..00000000000
--- a/app/assets/images/emoji/hand_splayed_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hand_splayed_tone5.png b/app/assets/images/emoji/hand_splayed_tone5.png
deleted file mode 100644
index 80bec971b6b..00000000000
--- a/app/assets/images/emoji/hand_splayed_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handbag.png b/app/assets/images/emoji/handbag.png
deleted file mode 100644
index cbf75c5d25e..00000000000
--- a/app/assets/images/emoji/handbag.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handball.png b/app/assets/images/emoji/handball.png
deleted file mode 100644
index 1152f1344c7..00000000000
--- a/app/assets/images/emoji/handball.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handball_tone1.png b/app/assets/images/emoji/handball_tone1.png
deleted file mode 100644
index c26cac2df98..00000000000
--- a/app/assets/images/emoji/handball_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handball_tone2.png b/app/assets/images/emoji/handball_tone2.png
deleted file mode 100644
index 7baaf95a9a2..00000000000
--- a/app/assets/images/emoji/handball_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handball_tone3.png b/app/assets/images/emoji/handball_tone3.png
deleted file mode 100644
index 0e3a37c3d40..00000000000
--- a/app/assets/images/emoji/handball_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handball_tone4.png b/app/assets/images/emoji/handball_tone4.png
deleted file mode 100644
index e1233f38266..00000000000
--- a/app/assets/images/emoji/handball_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handball_tone5.png b/app/assets/images/emoji/handball_tone5.png
deleted file mode 100644
index 6b1eb9b64b0..00000000000
--- a/app/assets/images/emoji/handball_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handshake.png b/app/assets/images/emoji/handshake.png
deleted file mode 100644
index c5d35fd8138..00000000000
--- a/app/assets/images/emoji/handshake.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handshake_tone1.png b/app/assets/images/emoji/handshake_tone1.png
deleted file mode 100644
index 8f8fbb9bdca..00000000000
--- a/app/assets/images/emoji/handshake_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handshake_tone2.png b/app/assets/images/emoji/handshake_tone2.png
deleted file mode 100644
index 336a77a6d78..00000000000
--- a/app/assets/images/emoji/handshake_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handshake_tone3.png b/app/assets/images/emoji/handshake_tone3.png
deleted file mode 100644
index 95f62d4fecd..00000000000
--- a/app/assets/images/emoji/handshake_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handshake_tone4.png b/app/assets/images/emoji/handshake_tone4.png
deleted file mode 100644
index 2b0a6433886..00000000000
--- a/app/assets/images/emoji/handshake_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/handshake_tone5.png b/app/assets/images/emoji/handshake_tone5.png
deleted file mode 100644
index 40189ee68e4..00000000000
--- a/app/assets/images/emoji/handshake_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hash.png b/app/assets/images/emoji/hash.png
deleted file mode 100644
index 6e26f0070b0..00000000000
--- a/app/assets/images/emoji/hash.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hatched_chick.png b/app/assets/images/emoji/hatched_chick.png
deleted file mode 100644
index 31dfb511e0e..00000000000
--- a/app/assets/images/emoji/hatched_chick.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hatching_chick.png b/app/assets/images/emoji/hatching_chick.png
deleted file mode 100644
index c5b0e8f3bcc..00000000000
--- a/app/assets/images/emoji/hatching_chick.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/head_bandage.png b/app/assets/images/emoji/head_bandage.png
deleted file mode 100644
index 0be723085e0..00000000000
--- a/app/assets/images/emoji/head_bandage.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/headphones.png b/app/assets/images/emoji/headphones.png
deleted file mode 100644
index e9fd34041d8..00000000000
--- a/app/assets/images/emoji/headphones.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hear_no_evil.png b/app/assets/images/emoji/hear_no_evil.png
deleted file mode 100644
index 74b6be0c6c5..00000000000
--- a/app/assets/images/emoji/hear_no_evil.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heart.png b/app/assets/images/emoji/heart.png
deleted file mode 100644
index 638cb72dc4e..00000000000
--- a/app/assets/images/emoji/heart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heart_decoration.png b/app/assets/images/emoji/heart_decoration.png
deleted file mode 100644
index 5443f60bc63..00000000000
--- a/app/assets/images/emoji/heart_decoration.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heart_exclamation.png b/app/assets/images/emoji/heart_exclamation.png
deleted file mode 100644
index 91b520be40b..00000000000
--- a/app/assets/images/emoji/heart_exclamation.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heart_eyes.png b/app/assets/images/emoji/heart_eyes.png
deleted file mode 100644
index 73fbee29d4e..00000000000
--- a/app/assets/images/emoji/heart_eyes.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heart_eyes_cat.png b/app/assets/images/emoji/heart_eyes_cat.png
deleted file mode 100644
index bc5a833f9a1..00000000000
--- a/app/assets/images/emoji/heart_eyes_cat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heartbeat.png b/app/assets/images/emoji/heartbeat.png
deleted file mode 100644
index 0bcf2d1d567..00000000000
--- a/app/assets/images/emoji/heartbeat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heartpulse.png b/app/assets/images/emoji/heartpulse.png
deleted file mode 100644
index d6e694e972f..00000000000
--- a/app/assets/images/emoji/heartpulse.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hearts.png b/app/assets/images/emoji/hearts.png
deleted file mode 100644
index 393c3ed5267..00000000000
--- a/app/assets/images/emoji/hearts.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heavy_check_mark.png b/app/assets/images/emoji/heavy_check_mark.png
deleted file mode 100644
index 03bd695377e..00000000000
--- a/app/assets/images/emoji/heavy_check_mark.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heavy_division_sign.png b/app/assets/images/emoji/heavy_division_sign.png
deleted file mode 100644
index df32ab21bea..00000000000
--- a/app/assets/images/emoji/heavy_division_sign.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heavy_dollar_sign.png b/app/assets/images/emoji/heavy_dollar_sign.png
deleted file mode 100644
index ef2c2e20590..00000000000
--- a/app/assets/images/emoji/heavy_dollar_sign.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heavy_minus_sign.png b/app/assets/images/emoji/heavy_minus_sign.png
deleted file mode 100644
index 054211caf12..00000000000
--- a/app/assets/images/emoji/heavy_minus_sign.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heavy_multiplication_x.png b/app/assets/images/emoji/heavy_multiplication_x.png
deleted file mode 100644
index e47cc1b685d..00000000000
--- a/app/assets/images/emoji/heavy_multiplication_x.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/heavy_plus_sign.png b/app/assets/images/emoji/heavy_plus_sign.png
deleted file mode 100644
index 40799798aaf..00000000000
--- a/app/assets/images/emoji/heavy_plus_sign.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/helicopter.png b/app/assets/images/emoji/helicopter.png
deleted file mode 100644
index 7ec5f39a51a..00000000000
--- a/app/assets/images/emoji/helicopter.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/helmet_with_cross.png b/app/assets/images/emoji/helmet_with_cross.png
deleted file mode 100644
index 7140a676038..00000000000
--- a/app/assets/images/emoji/helmet_with_cross.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/herb.png b/app/assets/images/emoji/herb.png
deleted file mode 100644
index d984d1562bb..00000000000
--- a/app/assets/images/emoji/herb.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hibiscus.png b/app/assets/images/emoji/hibiscus.png
deleted file mode 100644
index 39dd3524233..00000000000
--- a/app/assets/images/emoji/hibiscus.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/high_brightness.png b/app/assets/images/emoji/high_brightness.png
deleted file mode 100644
index c41f2d5fd50..00000000000
--- a/app/assets/images/emoji/high_brightness.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/high_heel.png b/app/assets/images/emoji/high_heel.png
deleted file mode 100644
index b331cbccc9d..00000000000
--- a/app/assets/images/emoji/high_heel.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hockey.png b/app/assets/images/emoji/hockey.png
deleted file mode 100644
index be94e9cbf73..00000000000
--- a/app/assets/images/emoji/hockey.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hole.png b/app/assets/images/emoji/hole.png
deleted file mode 100644
index 517d2ae0deb..00000000000
--- a/app/assets/images/emoji/hole.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/homes.png b/app/assets/images/emoji/homes.png
deleted file mode 100644
index 6ab4a2a2651..00000000000
--- a/app/assets/images/emoji/homes.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/honey_pot.png b/app/assets/images/emoji/honey_pot.png
deleted file mode 100644
index 9d8f592955e..00000000000
--- a/app/assets/images/emoji/honey_pot.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/horse.png b/app/assets/images/emoji/horse.png
deleted file mode 100644
index 7cb1172f4e4..00000000000
--- a/app/assets/images/emoji/horse.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/horse_racing.png b/app/assets/images/emoji/horse_racing.png
deleted file mode 100644
index addf9edac56..00000000000
--- a/app/assets/images/emoji/horse_racing.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/horse_racing_tone1.png b/app/assets/images/emoji/horse_racing_tone1.png
deleted file mode 100644
index e9bf4092e98..00000000000
--- a/app/assets/images/emoji/horse_racing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/horse_racing_tone2.png b/app/assets/images/emoji/horse_racing_tone2.png
deleted file mode 100644
index 031bbc3d867..00000000000
--- a/app/assets/images/emoji/horse_racing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/horse_racing_tone3.png b/app/assets/images/emoji/horse_racing_tone3.png
deleted file mode 100644
index b40ef891f9b..00000000000
--- a/app/assets/images/emoji/horse_racing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/horse_racing_tone4.png b/app/assets/images/emoji/horse_racing_tone4.png
deleted file mode 100644
index e286cb85065..00000000000
--- a/app/assets/images/emoji/horse_racing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/horse_racing_tone5.png b/app/assets/images/emoji/horse_racing_tone5.png
deleted file mode 100644
index 453c51c6007..00000000000
--- a/app/assets/images/emoji/horse_racing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hospital.png b/app/assets/images/emoji/hospital.png
deleted file mode 100644
index 1cbce4ae767..00000000000
--- a/app/assets/images/emoji/hospital.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hot_pepper.png b/app/assets/images/emoji/hot_pepper.png
deleted file mode 100644
index 266675bd577..00000000000
--- a/app/assets/images/emoji/hot_pepper.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hotdog.png b/app/assets/images/emoji/hotdog.png
deleted file mode 100644
index 3c3354d94cb..00000000000
--- a/app/assets/images/emoji/hotdog.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hotel.png b/app/assets/images/emoji/hotel.png
deleted file mode 100644
index ea8f4c4979a..00000000000
--- a/app/assets/images/emoji/hotel.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hotsprings.png b/app/assets/images/emoji/hotsprings.png
deleted file mode 100644
index 3d9df2d9475..00000000000
--- a/app/assets/images/emoji/hotsprings.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hourglass.png b/app/assets/images/emoji/hourglass.png
deleted file mode 100644
index a5db2d1d3f4..00000000000
--- a/app/assets/images/emoji/hourglass.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hourglass_flowing_sand.png b/app/assets/images/emoji/hourglass_flowing_sand.png
deleted file mode 100644
index b93b15ed6d8..00000000000
--- a/app/assets/images/emoji/hourglass_flowing_sand.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/house.png b/app/assets/images/emoji/house.png
deleted file mode 100644
index 01c98a0ba92..00000000000
--- a/app/assets/images/emoji/house.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/house_abandoned.png b/app/assets/images/emoji/house_abandoned.png
deleted file mode 100644
index c55e81de990..00000000000
--- a/app/assets/images/emoji/house_abandoned.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/house_with_garden.png b/app/assets/images/emoji/house_with_garden.png
deleted file mode 100644
index 0aae41598ef..00000000000
--- a/app/assets/images/emoji/house_with_garden.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hugging.png b/app/assets/images/emoji/hugging.png
deleted file mode 100644
index 5bba6dc6d51..00000000000
--- a/app/assets/images/emoji/hugging.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/hushed.png b/app/assets/images/emoji/hushed.png
deleted file mode 100644
index cad0e23132e..00000000000
--- a/app/assets/images/emoji/hushed.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ice_cream.png b/app/assets/images/emoji/ice_cream.png
deleted file mode 100644
index 94267b9c434..00000000000
--- a/app/assets/images/emoji/ice_cream.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ice_skate.png b/app/assets/images/emoji/ice_skate.png
deleted file mode 100644
index 8c449b0c039..00000000000
--- a/app/assets/images/emoji/ice_skate.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/icecream.png b/app/assets/images/emoji/icecream.png
deleted file mode 100644
index 8f6546e31a5..00000000000
--- a/app/assets/images/emoji/icecream.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/id.png b/app/assets/images/emoji/id.png
deleted file mode 100644
index 5bf69bf7ba8..00000000000
--- a/app/assets/images/emoji/id.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ideograph_advantage.png b/app/assets/images/emoji/ideograph_advantage.png
deleted file mode 100644
index 0c0d589caf0..00000000000
--- a/app/assets/images/emoji/ideograph_advantage.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/imp.png b/app/assets/images/emoji/imp.png
deleted file mode 100644
index 9f9a9605539..00000000000
--- a/app/assets/images/emoji/imp.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/inbox_tray.png b/app/assets/images/emoji/inbox_tray.png
deleted file mode 100644
index 41a6be2b0ee..00000000000
--- a/app/assets/images/emoji/inbox_tray.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/incoming_envelope.png b/app/assets/images/emoji/incoming_envelope.png
deleted file mode 100644
index fd22e88182e..00000000000
--- a/app/assets/images/emoji/incoming_envelope.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/information_desk_person.png b/app/assets/images/emoji/information_desk_person.png
deleted file mode 100644
index 55fc6294d25..00000000000
--- a/app/assets/images/emoji/information_desk_person.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/information_desk_person_tone1.png b/app/assets/images/emoji/information_desk_person_tone1.png
deleted file mode 100644
index 3d9e2247940..00000000000
--- a/app/assets/images/emoji/information_desk_person_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/information_desk_person_tone2.png b/app/assets/images/emoji/information_desk_person_tone2.png
deleted file mode 100644
index 879e8b7966d..00000000000
--- a/app/assets/images/emoji/information_desk_person_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/information_desk_person_tone3.png b/app/assets/images/emoji/information_desk_person_tone3.png
deleted file mode 100644
index 307514eab67..00000000000
--- a/app/assets/images/emoji/information_desk_person_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/information_desk_person_tone4.png b/app/assets/images/emoji/information_desk_person_tone4.png
deleted file mode 100644
index 297395dcb3f..00000000000
--- a/app/assets/images/emoji/information_desk_person_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/information_desk_person_tone5.png b/app/assets/images/emoji/information_desk_person_tone5.png
deleted file mode 100644
index 26f8f22b28b..00000000000
--- a/app/assets/images/emoji/information_desk_person_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/information_source.png b/app/assets/images/emoji/information_source.png
deleted file mode 100644
index 871f2db9314..00000000000
--- a/app/assets/images/emoji/information_source.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/innocent.png b/app/assets/images/emoji/innocent.png
deleted file mode 100644
index 57f5151124f..00000000000
--- a/app/assets/images/emoji/innocent.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/interrobang.png b/app/assets/images/emoji/interrobang.png
deleted file mode 100644
index 509813e9bb2..00000000000
--- a/app/assets/images/emoji/interrobang.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/iphone.png b/app/assets/images/emoji/iphone.png
deleted file mode 100644
index fd377acf872..00000000000
--- a/app/assets/images/emoji/iphone.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/island.png b/app/assets/images/emoji/island.png
deleted file mode 100644
index 7fd834389b7..00000000000
--- a/app/assets/images/emoji/island.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/izakaya_lantern.png b/app/assets/images/emoji/izakaya_lantern.png
deleted file mode 100644
index dfd933f6f36..00000000000
--- a/app/assets/images/emoji/izakaya_lantern.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/jack_o_lantern.png b/app/assets/images/emoji/jack_o_lantern.png
deleted file mode 100644
index 44c3fc0aec9..00000000000
--- a/app/assets/images/emoji/jack_o_lantern.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/japan.png b/app/assets/images/emoji/japan.png
deleted file mode 100644
index d86d0a59e12..00000000000
--- a/app/assets/images/emoji/japan.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/japanese_castle.png b/app/assets/images/emoji/japanese_castle.png
deleted file mode 100644
index 64b4e33a1ae..00000000000
--- a/app/assets/images/emoji/japanese_castle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/japanese_goblin.png b/app/assets/images/emoji/japanese_goblin.png
deleted file mode 100644
index 515c6a2250e..00000000000
--- a/app/assets/images/emoji/japanese_goblin.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/japanese_ogre.png b/app/assets/images/emoji/japanese_ogre.png
deleted file mode 100644
index fe8670fdaf1..00000000000
--- a/app/assets/images/emoji/japanese_ogre.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/jeans.png b/app/assets/images/emoji/jeans.png
deleted file mode 100644
index 2a6869d674c..00000000000
--- a/app/assets/images/emoji/jeans.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/joy.png b/app/assets/images/emoji/joy.png
deleted file mode 100644
index 0ba3b1859d8..00000000000
--- a/app/assets/images/emoji/joy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/joy_cat.png b/app/assets/images/emoji/joy_cat.png
deleted file mode 100644
index aac353179aa..00000000000
--- a/app/assets/images/emoji/joy_cat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/joystick.png b/app/assets/images/emoji/joystick.png
deleted file mode 100644
index 1ee1905434e..00000000000
--- a/app/assets/images/emoji/joystick.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/juggling.png b/app/assets/images/emoji/juggling.png
deleted file mode 100644
index a37f6224a42..00000000000
--- a/app/assets/images/emoji/juggling.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/juggling_tone1.png b/app/assets/images/emoji/juggling_tone1.png
deleted file mode 100644
index c18eda40031..00000000000
--- a/app/assets/images/emoji/juggling_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/juggling_tone2.png b/app/assets/images/emoji/juggling_tone2.png
deleted file mode 100644
index de3b7a555b6..00000000000
--- a/app/assets/images/emoji/juggling_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/juggling_tone3.png b/app/assets/images/emoji/juggling_tone3.png
deleted file mode 100644
index 74ab6d85458..00000000000
--- a/app/assets/images/emoji/juggling_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/juggling_tone4.png b/app/assets/images/emoji/juggling_tone4.png
deleted file mode 100644
index 1c57823203f..00000000000
--- a/app/assets/images/emoji/juggling_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/juggling_tone5.png b/app/assets/images/emoji/juggling_tone5.png
deleted file mode 100644
index c343d6ee98a..00000000000
--- a/app/assets/images/emoji/juggling_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/kaaba.png b/app/assets/images/emoji/kaaba.png
deleted file mode 100644
index 1778c1138e4..00000000000
--- a/app/assets/images/emoji/kaaba.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/key.png b/app/assets/images/emoji/key.png
deleted file mode 100644
index 319cd1b884c..00000000000
--- a/app/assets/images/emoji/key.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/key2.png b/app/assets/images/emoji/key2.png
deleted file mode 100644
index e11d706c6c8..00000000000
--- a/app/assets/images/emoji/key2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/keyboard.png b/app/assets/images/emoji/keyboard.png
deleted file mode 100644
index 75027cb9af7..00000000000
--- a/app/assets/images/emoji/keyboard.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/kimono.png b/app/assets/images/emoji/kimono.png
deleted file mode 100644
index abe851115d1..00000000000
--- a/app/assets/images/emoji/kimono.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/kiss.png b/app/assets/images/emoji/kiss.png
deleted file mode 100644
index 85e6dcfc4e8..00000000000
--- a/app/assets/images/emoji/kiss.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/kiss_mm.png b/app/assets/images/emoji/kiss_mm.png
deleted file mode 100644
index a9a0edae17c..00000000000
--- a/app/assets/images/emoji/kiss_mm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/kiss_ww.png b/app/assets/images/emoji/kiss_ww.png
deleted file mode 100644
index fdac73cbb1d..00000000000
--- a/app/assets/images/emoji/kiss_ww.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/kissing.png b/app/assets/images/emoji/kissing.png
deleted file mode 100644
index 39d325fd8e3..00000000000
--- a/app/assets/images/emoji/kissing.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/kissing_cat.png b/app/assets/images/emoji/kissing_cat.png
deleted file mode 100644
index 6e0bcc77540..00000000000
--- a/app/assets/images/emoji/kissing_cat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/kissing_closed_eyes.png b/app/assets/images/emoji/kissing_closed_eyes.png
deleted file mode 100644
index b684d7d4d6c..00000000000
--- a/app/assets/images/emoji/kissing_closed_eyes.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/kissing_heart.png b/app/assets/images/emoji/kissing_heart.png
deleted file mode 100644
index 0ff808fd614..00000000000
--- a/app/assets/images/emoji/kissing_heart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/kissing_smiling_eyes.png b/app/assets/images/emoji/kissing_smiling_eyes.png
deleted file mode 100644
index e181f17099d..00000000000
--- a/app/assets/images/emoji/kissing_smiling_eyes.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/kiwi.png b/app/assets/images/emoji/kiwi.png
deleted file mode 100644
index dfbd8258074..00000000000
--- a/app/assets/images/emoji/kiwi.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/knife.png b/app/assets/images/emoji/knife.png
deleted file mode 100644
index 1acb9f3077b..00000000000
--- a/app/assets/images/emoji/knife.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/koala.png b/app/assets/images/emoji/koala.png
deleted file mode 100644
index a0aa437a98c..00000000000
--- a/app/assets/images/emoji/koala.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/koko.png b/app/assets/images/emoji/koko.png
deleted file mode 100644
index 6450eb44d90..00000000000
--- a/app/assets/images/emoji/koko.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/label.png b/app/assets/images/emoji/label.png
deleted file mode 100644
index d41c9b4f1e1..00000000000
--- a/app/assets/images/emoji/label.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/large_blue_circle.png b/app/assets/images/emoji/large_blue_circle.png
deleted file mode 100644
index 84078ef3127..00000000000
--- a/app/assets/images/emoji/large_blue_circle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/large_blue_diamond.png b/app/assets/images/emoji/large_blue_diamond.png
deleted file mode 100644
index 416a58bd5a8..00000000000
--- a/app/assets/images/emoji/large_blue_diamond.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/large_orange_diamond.png b/app/assets/images/emoji/large_orange_diamond.png
deleted file mode 100644
index 73ff0ac36c8..00000000000
--- a/app/assets/images/emoji/large_orange_diamond.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/last_quarter_moon.png b/app/assets/images/emoji/last_quarter_moon.png
deleted file mode 100644
index 0842a0dd408..00000000000
--- a/app/assets/images/emoji/last_quarter_moon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/last_quarter_moon_with_face.png b/app/assets/images/emoji/last_quarter_moon_with_face.png
deleted file mode 100644
index 94099343c5d..00000000000
--- a/app/assets/images/emoji/last_quarter_moon_with_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/laughing.png b/app/assets/images/emoji/laughing.png
deleted file mode 100644
index d94e9505ba1..00000000000
--- a/app/assets/images/emoji/laughing.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/leaves.png b/app/assets/images/emoji/leaves.png
deleted file mode 100644
index 1e43e1af820..00000000000
--- a/app/assets/images/emoji/leaves.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ledger.png b/app/assets/images/emoji/ledger.png
deleted file mode 100644
index 13e7561a4bd..00000000000
--- a/app/assets/images/emoji/ledger.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/left_facing_fist.png b/app/assets/images/emoji/left_facing_fist.png
deleted file mode 100644
index a9d9fd8d59c..00000000000
--- a/app/assets/images/emoji/left_facing_fist.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/left_facing_fist_tone1.png b/app/assets/images/emoji/left_facing_fist_tone1.png
deleted file mode 100644
index 1262a6b4b69..00000000000
--- a/app/assets/images/emoji/left_facing_fist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/left_facing_fist_tone2.png b/app/assets/images/emoji/left_facing_fist_tone2.png
deleted file mode 100644
index 40bf70b82b2..00000000000
--- a/app/assets/images/emoji/left_facing_fist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/left_facing_fist_tone3.png b/app/assets/images/emoji/left_facing_fist_tone3.png
deleted file mode 100644
index 93f58145111..00000000000
--- a/app/assets/images/emoji/left_facing_fist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/left_facing_fist_tone4.png b/app/assets/images/emoji/left_facing_fist_tone4.png
deleted file mode 100644
index d82b5ec91f0..00000000000
--- a/app/assets/images/emoji/left_facing_fist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/left_facing_fist_tone5.png b/app/assets/images/emoji/left_facing_fist_tone5.png
deleted file mode 100644
index 09ae4cd492b..00000000000
--- a/app/assets/images/emoji/left_facing_fist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/left_luggage.png b/app/assets/images/emoji/left_luggage.png
deleted file mode 100644
index 887b23f3f25..00000000000
--- a/app/assets/images/emoji/left_luggage.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/left_right_arrow.png b/app/assets/images/emoji/left_right_arrow.png
deleted file mode 100644
index 7937f24f2ac..00000000000
--- a/app/assets/images/emoji/left_right_arrow.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/leftwards_arrow_with_hook.png b/app/assets/images/emoji/leftwards_arrow_with_hook.png
deleted file mode 100644
index ba45c2ad9e9..00000000000
--- a/app/assets/images/emoji/leftwards_arrow_with_hook.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lemon.png b/app/assets/images/emoji/lemon.png
deleted file mode 100644
index 9a7d95ca220..00000000000
--- a/app/assets/images/emoji/lemon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/leo.png b/app/assets/images/emoji/leo.png
deleted file mode 100644
index 30158d34de9..00000000000
--- a/app/assets/images/emoji/leo.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/leopard.png b/app/assets/images/emoji/leopard.png
deleted file mode 100644
index 8aac3d49448..00000000000
--- a/app/assets/images/emoji/leopard.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/level_slider.png b/app/assets/images/emoji/level_slider.png
deleted file mode 100644
index 720a3b34119..00000000000
--- a/app/assets/images/emoji/level_slider.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/levitate.png b/app/assets/images/emoji/levitate.png
deleted file mode 100644
index 3dc315a3d91..00000000000
--- a/app/assets/images/emoji/levitate.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/libra.png b/app/assets/images/emoji/libra.png
deleted file mode 100644
index 8fd133a357c..00000000000
--- a/app/assets/images/emoji/libra.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lifter.png b/app/assets/images/emoji/lifter.png
deleted file mode 100644
index afdeaa476af..00000000000
--- a/app/assets/images/emoji/lifter.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lifter_tone1.png b/app/assets/images/emoji/lifter_tone1.png
deleted file mode 100644
index febaad123ec..00000000000
--- a/app/assets/images/emoji/lifter_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lifter_tone2.png b/app/assets/images/emoji/lifter_tone2.png
deleted file mode 100644
index 27ae794a18e..00000000000
--- a/app/assets/images/emoji/lifter_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lifter_tone3.png b/app/assets/images/emoji/lifter_tone3.png
deleted file mode 100644
index 45c4c22c709..00000000000
--- a/app/assets/images/emoji/lifter_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lifter_tone4.png b/app/assets/images/emoji/lifter_tone4.png
deleted file mode 100644
index 67dd21d2464..00000000000
--- a/app/assets/images/emoji/lifter_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lifter_tone5.png b/app/assets/images/emoji/lifter_tone5.png
deleted file mode 100644
index fa0152038b6..00000000000
--- a/app/assets/images/emoji/lifter_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/light_rail.png b/app/assets/images/emoji/light_rail.png
deleted file mode 100644
index a64829f5078..00000000000
--- a/app/assets/images/emoji/light_rail.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/link.png b/app/assets/images/emoji/link.png
deleted file mode 100644
index ae20f0f8eec..00000000000
--- a/app/assets/images/emoji/link.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lion_face.png b/app/assets/images/emoji/lion_face.png
deleted file mode 100644
index 5062ab47ecf..00000000000
--- a/app/assets/images/emoji/lion_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lips.png b/app/assets/images/emoji/lips.png
deleted file mode 100644
index 35f3cc2006f..00000000000
--- a/app/assets/images/emoji/lips.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lipstick.png b/app/assets/images/emoji/lipstick.png
deleted file mode 100644
index 61a0c084c99..00000000000
--- a/app/assets/images/emoji/lipstick.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lizard.png b/app/assets/images/emoji/lizard.png
deleted file mode 100644
index 8363876050e..00000000000
--- a/app/assets/images/emoji/lizard.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lock.png b/app/assets/images/emoji/lock.png
deleted file mode 100644
index 5a739c46644..00000000000
--- a/app/assets/images/emoji/lock.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lock_with_ink_pen.png b/app/assets/images/emoji/lock_with_ink_pen.png
deleted file mode 100644
index 19a07d162fb..00000000000
--- a/app/assets/images/emoji/lock_with_ink_pen.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lollipop.png b/app/assets/images/emoji/lollipop.png
deleted file mode 100644
index ad76d7bf916..00000000000
--- a/app/assets/images/emoji/lollipop.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/loop.png b/app/assets/images/emoji/loop.png
deleted file mode 100644
index 0b82c8fe315..00000000000
--- a/app/assets/images/emoji/loop.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/loud_sound.png b/app/assets/images/emoji/loud_sound.png
deleted file mode 100644
index 8370033a539..00000000000
--- a/app/assets/images/emoji/loud_sound.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/loudspeaker.png b/app/assets/images/emoji/loudspeaker.png
deleted file mode 100644
index 5fd76a95b82..00000000000
--- a/app/assets/images/emoji/loudspeaker.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/love_hotel.png b/app/assets/images/emoji/love_hotel.png
deleted file mode 100644
index 5e136be6f8b..00000000000
--- a/app/assets/images/emoji/love_hotel.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/love_letter.png b/app/assets/images/emoji/love_letter.png
deleted file mode 100644
index 3c3c767e784..00000000000
--- a/app/assets/images/emoji/love_letter.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/low_brightness.png b/app/assets/images/emoji/low_brightness.png
deleted file mode 100644
index 543011d3961..00000000000
--- a/app/assets/images/emoji/low_brightness.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/lying_face.png b/app/assets/images/emoji/lying_face.png
deleted file mode 100644
index 02827e2628b..00000000000
--- a/app/assets/images/emoji/lying_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/m.png b/app/assets/images/emoji/m.png
deleted file mode 100644
index 8a3506fc1d7..00000000000
--- a/app/assets/images/emoji/m.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mag.png b/app/assets/images/emoji/mag.png
deleted file mode 100644
index 55487156ac6..00000000000
--- a/app/assets/images/emoji/mag.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mag_right.png b/app/assets/images/emoji/mag_right.png
deleted file mode 100644
index 0f4b1bca876..00000000000
--- a/app/assets/images/emoji/mag_right.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mahjong.png b/app/assets/images/emoji/mahjong.png
deleted file mode 100644
index 66fd32025b2..00000000000
--- a/app/assets/images/emoji/mahjong.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mailbox.png b/app/assets/images/emoji/mailbox.png
deleted file mode 100644
index ef5174e40dd..00000000000
--- a/app/assets/images/emoji/mailbox.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mailbox_closed.png b/app/assets/images/emoji/mailbox_closed.png
deleted file mode 100644
index ddc705db0d8..00000000000
--- a/app/assets/images/emoji/mailbox_closed.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mailbox_with_mail.png b/app/assets/images/emoji/mailbox_with_mail.png
deleted file mode 100644
index 5460616a5b1..00000000000
--- a/app/assets/images/emoji/mailbox_with_mail.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mailbox_with_no_mail.png b/app/assets/images/emoji/mailbox_with_no_mail.png
deleted file mode 100644
index f9aeee6b15a..00000000000
--- a/app/assets/images/emoji/mailbox_with_no_mail.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man.png b/app/assets/images/emoji/man.png
deleted file mode 100644
index 857a02e5146..00000000000
--- a/app/assets/images/emoji/man.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_dancing.png b/app/assets/images/emoji/man_dancing.png
deleted file mode 100644
index ccff3bede5a..00000000000
--- a/app/assets/images/emoji/man_dancing.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_dancing_tone1.png b/app/assets/images/emoji/man_dancing_tone1.png
deleted file mode 100644
index e0b9f82d905..00000000000
--- a/app/assets/images/emoji/man_dancing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_dancing_tone2.png b/app/assets/images/emoji/man_dancing_tone2.png
deleted file mode 100644
index a5beed56e2e..00000000000
--- a/app/assets/images/emoji/man_dancing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_dancing_tone3.png b/app/assets/images/emoji/man_dancing_tone3.png
deleted file mode 100644
index 2fa20180a6e..00000000000
--- a/app/assets/images/emoji/man_dancing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_dancing_tone4.png b/app/assets/images/emoji/man_dancing_tone4.png
deleted file mode 100644
index bd3528c83ba..00000000000
--- a/app/assets/images/emoji/man_dancing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_dancing_tone5.png b/app/assets/images/emoji/man_dancing_tone5.png
deleted file mode 100644
index 41fd4f880c9..00000000000
--- a/app/assets/images/emoji/man_dancing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_in_tuxedo.png b/app/assets/images/emoji/man_in_tuxedo.png
deleted file mode 100644
index 5f7e9303f89..00000000000
--- a/app/assets/images/emoji/man_in_tuxedo.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_in_tuxedo_tone1.png b/app/assets/images/emoji/man_in_tuxedo_tone1.png
deleted file mode 100644
index 7b6b3acd99b..00000000000
--- a/app/assets/images/emoji/man_in_tuxedo_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_in_tuxedo_tone2.png b/app/assets/images/emoji/man_in_tuxedo_tone2.png
deleted file mode 100644
index 7975191b360..00000000000
--- a/app/assets/images/emoji/man_in_tuxedo_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_in_tuxedo_tone3.png b/app/assets/images/emoji/man_in_tuxedo_tone3.png
deleted file mode 100644
index a2816f600ae..00000000000
--- a/app/assets/images/emoji/man_in_tuxedo_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_in_tuxedo_tone4.png b/app/assets/images/emoji/man_in_tuxedo_tone4.png
deleted file mode 100644
index ea8291760f9..00000000000
--- a/app/assets/images/emoji/man_in_tuxedo_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_in_tuxedo_tone5.png b/app/assets/images/emoji/man_in_tuxedo_tone5.png
deleted file mode 100644
index c743e05fc5e..00000000000
--- a/app/assets/images/emoji/man_in_tuxedo_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_tone1.png b/app/assets/images/emoji/man_tone1.png
deleted file mode 100644
index bb86e963a80..00000000000
--- a/app/assets/images/emoji/man_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_tone2.png b/app/assets/images/emoji/man_tone2.png
deleted file mode 100644
index fdeeaff46f5..00000000000
--- a/app/assets/images/emoji/man_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_tone3.png b/app/assets/images/emoji/man_tone3.png
deleted file mode 100644
index 7ae0b5df9cf..00000000000
--- a/app/assets/images/emoji/man_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_tone4.png b/app/assets/images/emoji/man_tone4.png
deleted file mode 100644
index db14cde99b8..00000000000
--- a/app/assets/images/emoji/man_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_tone5.png b/app/assets/images/emoji/man_tone5.png
deleted file mode 100644
index 7c67a70529c..00000000000
--- a/app/assets/images/emoji/man_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao.png b/app/assets/images/emoji/man_with_gua_pi_mao.png
deleted file mode 100644
index 7841e13608d..00000000000
--- a/app/assets/images/emoji/man_with_gua_pi_mao.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao_tone1.png b/app/assets/images/emoji/man_with_gua_pi_mao_tone1.png
deleted file mode 100644
index 5b7b3def19c..00000000000
--- a/app/assets/images/emoji/man_with_gua_pi_mao_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao_tone2.png b/app/assets/images/emoji/man_with_gua_pi_mao_tone2.png
deleted file mode 100644
index c8b9cf87f4b..00000000000
--- a/app/assets/images/emoji/man_with_gua_pi_mao_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao_tone3.png b/app/assets/images/emoji/man_with_gua_pi_mao_tone3.png
deleted file mode 100644
index effdd0c4c84..00000000000
--- a/app/assets/images/emoji/man_with_gua_pi_mao_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao_tone4.png b/app/assets/images/emoji/man_with_gua_pi_mao_tone4.png
deleted file mode 100644
index f885ff46fa1..00000000000
--- a/app/assets/images/emoji/man_with_gua_pi_mao_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_with_gua_pi_mao_tone5.png b/app/assets/images/emoji/man_with_gua_pi_mao_tone5.png
deleted file mode 100644
index a6d55ca1380..00000000000
--- a/app/assets/images/emoji/man_with_gua_pi_mao_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_with_turban.png b/app/assets/images/emoji/man_with_turban.png
deleted file mode 100644
index 51cf047f966..00000000000
--- a/app/assets/images/emoji/man_with_turban.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_with_turban_tone1.png b/app/assets/images/emoji/man_with_turban_tone1.png
deleted file mode 100644
index 1e12ee4b231..00000000000
--- a/app/assets/images/emoji/man_with_turban_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_with_turban_tone2.png b/app/assets/images/emoji/man_with_turban_tone2.png
deleted file mode 100644
index 37de4cceb23..00000000000
--- a/app/assets/images/emoji/man_with_turban_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_with_turban_tone3.png b/app/assets/images/emoji/man_with_turban_tone3.png
deleted file mode 100644
index f607afd3450..00000000000
--- a/app/assets/images/emoji/man_with_turban_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_with_turban_tone4.png b/app/assets/images/emoji/man_with_turban_tone4.png
deleted file mode 100644
index c05695888af..00000000000
--- a/app/assets/images/emoji/man_with_turban_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/man_with_turban_tone5.png b/app/assets/images/emoji/man_with_turban_tone5.png
deleted file mode 100644
index 4b4ff64720b..00000000000
--- a/app/assets/images/emoji/man_with_turban_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mans_shoe.png b/app/assets/images/emoji/mans_shoe.png
deleted file mode 100644
index 4bf7541032c..00000000000
--- a/app/assets/images/emoji/mans_shoe.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/map.png b/app/assets/images/emoji/map.png
deleted file mode 100644
index 15efe32c798..00000000000
--- a/app/assets/images/emoji/map.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/maple_leaf.png b/app/assets/images/emoji/maple_leaf.png
deleted file mode 100644
index c49acea67f7..00000000000
--- a/app/assets/images/emoji/maple_leaf.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/martial_arts_uniform.png b/app/assets/images/emoji/martial_arts_uniform.png
deleted file mode 100644
index 8d6114761f6..00000000000
--- a/app/assets/images/emoji/martial_arts_uniform.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mask.png b/app/assets/images/emoji/mask.png
deleted file mode 100644
index 1e800acd1c0..00000000000
--- a/app/assets/images/emoji/mask.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/massage.png b/app/assets/images/emoji/massage.png
deleted file mode 100644
index b91d845e374..00000000000
--- a/app/assets/images/emoji/massage.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/massage_tone1.png b/app/assets/images/emoji/massage_tone1.png
deleted file mode 100644
index e0f415d3186..00000000000
--- a/app/assets/images/emoji/massage_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/massage_tone2.png b/app/assets/images/emoji/massage_tone2.png
deleted file mode 100644
index 0bb244a270b..00000000000
--- a/app/assets/images/emoji/massage_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/massage_tone3.png b/app/assets/images/emoji/massage_tone3.png
deleted file mode 100644
index a117ee81a22..00000000000
--- a/app/assets/images/emoji/massage_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/massage_tone4.png b/app/assets/images/emoji/massage_tone4.png
deleted file mode 100644
index 6f42ab017f4..00000000000
--- a/app/assets/images/emoji/massage_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/massage_tone5.png b/app/assets/images/emoji/massage_tone5.png
deleted file mode 100644
index 6a388c0d0b5..00000000000
--- a/app/assets/images/emoji/massage_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/meat_on_bone.png b/app/assets/images/emoji/meat_on_bone.png
deleted file mode 100644
index b20a59d1690..00000000000
--- a/app/assets/images/emoji/meat_on_bone.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/medal.png b/app/assets/images/emoji/medal.png
deleted file mode 100644
index b85896b14da..00000000000
--- a/app/assets/images/emoji/medal.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mega.png b/app/assets/images/emoji/mega.png
deleted file mode 100644
index 4e6735188e3..00000000000
--- a/app/assets/images/emoji/mega.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/melon.png b/app/assets/images/emoji/melon.png
deleted file mode 100644
index c01232d419d..00000000000
--- a/app/assets/images/emoji/melon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/menorah.png b/app/assets/images/emoji/menorah.png
deleted file mode 100644
index b4297362869..00000000000
--- a/app/assets/images/emoji/menorah.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mens.png b/app/assets/images/emoji/mens.png
deleted file mode 100644
index f5a1e1ba0cd..00000000000
--- a/app/assets/images/emoji/mens.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/metal.png b/app/assets/images/emoji/metal.png
deleted file mode 100644
index 4aa6e7e0a44..00000000000
--- a/app/assets/images/emoji/metal.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/metal_tone1.png b/app/assets/images/emoji/metal_tone1.png
deleted file mode 100644
index c080d2addbd..00000000000
--- a/app/assets/images/emoji/metal_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/metal_tone2.png b/app/assets/images/emoji/metal_tone2.png
deleted file mode 100644
index 12313529bcf..00000000000
--- a/app/assets/images/emoji/metal_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/metal_tone3.png b/app/assets/images/emoji/metal_tone3.png
deleted file mode 100644
index ca9be6ae67b..00000000000
--- a/app/assets/images/emoji/metal_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/metal_tone4.png b/app/assets/images/emoji/metal_tone4.png
deleted file mode 100644
index abe28cbf890..00000000000
--- a/app/assets/images/emoji/metal_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/metal_tone5.png b/app/assets/images/emoji/metal_tone5.png
deleted file mode 100644
index 0c6b5dd34ed..00000000000
--- a/app/assets/images/emoji/metal_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/metro.png b/app/assets/images/emoji/metro.png
deleted file mode 100644
index 1de8f0551f3..00000000000
--- a/app/assets/images/emoji/metro.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/microphone.png b/app/assets/images/emoji/microphone.png
deleted file mode 100644
index d4e6b0def25..00000000000
--- a/app/assets/images/emoji/microphone.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/microphone2.png b/app/assets/images/emoji/microphone2.png
deleted file mode 100644
index cd9167654ff..00000000000
--- a/app/assets/images/emoji/microphone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/microscope.png b/app/assets/images/emoji/microscope.png
deleted file mode 100644
index 90f5acf6a78..00000000000
--- a/app/assets/images/emoji/microscope.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/middle_finger.png b/app/assets/images/emoji/middle_finger.png
deleted file mode 100644
index 697f7a25eb2..00000000000
--- a/app/assets/images/emoji/middle_finger.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/middle_finger_tone1.png b/app/assets/images/emoji/middle_finger_tone1.png
deleted file mode 100644
index 61ef12a1548..00000000000
--- a/app/assets/images/emoji/middle_finger_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/middle_finger_tone2.png b/app/assets/images/emoji/middle_finger_tone2.png
deleted file mode 100644
index c31a69be9af..00000000000
--- a/app/assets/images/emoji/middle_finger_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/middle_finger_tone3.png b/app/assets/images/emoji/middle_finger_tone3.png
deleted file mode 100644
index 73ac216ce63..00000000000
--- a/app/assets/images/emoji/middle_finger_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/middle_finger_tone4.png b/app/assets/images/emoji/middle_finger_tone4.png
deleted file mode 100644
index 80b8ab7706d..00000000000
--- a/app/assets/images/emoji/middle_finger_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/middle_finger_tone5.png b/app/assets/images/emoji/middle_finger_tone5.png
deleted file mode 100644
index a8826b196e8..00000000000
--- a/app/assets/images/emoji/middle_finger_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/military_medal.png b/app/assets/images/emoji/military_medal.png
deleted file mode 100644
index ecd3fb03584..00000000000
--- a/app/assets/images/emoji/military_medal.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/milk.png b/app/assets/images/emoji/milk.png
deleted file mode 100644
index e4fcf2e64f3..00000000000
--- a/app/assets/images/emoji/milk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/milky_way.png b/app/assets/images/emoji/milky_way.png
deleted file mode 100644
index b2b8ac59c5e..00000000000
--- a/app/assets/images/emoji/milky_way.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/minibus.png b/app/assets/images/emoji/minibus.png
deleted file mode 100644
index c60dd8f47ab..00000000000
--- a/app/assets/images/emoji/minibus.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/minidisc.png b/app/assets/images/emoji/minidisc.png
deleted file mode 100644
index 9fa94cfbe74..00000000000
--- a/app/assets/images/emoji/minidisc.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mobile_phone_off.png b/app/assets/images/emoji/mobile_phone_off.png
deleted file mode 100644
index 8b661ec1c94..00000000000
--- a/app/assets/images/emoji/mobile_phone_off.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/money_mouth.png b/app/assets/images/emoji/money_mouth.png
deleted file mode 100644
index 75fd1e90cb0..00000000000
--- a/app/assets/images/emoji/money_mouth.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/money_with_wings.png b/app/assets/images/emoji/money_with_wings.png
deleted file mode 100644
index f022b04b3c2..00000000000
--- a/app/assets/images/emoji/money_with_wings.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/moneybag.png b/app/assets/images/emoji/moneybag.png
deleted file mode 100644
index b9296be0902..00000000000
--- a/app/assets/images/emoji/moneybag.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/monkey.png b/app/assets/images/emoji/monkey.png
deleted file mode 100644
index 9fae29448e3..00000000000
--- a/app/assets/images/emoji/monkey.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/monkey_face.png b/app/assets/images/emoji/monkey_face.png
deleted file mode 100644
index 7cab9b91a82..00000000000
--- a/app/assets/images/emoji/monkey_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/monorail.png b/app/assets/images/emoji/monorail.png
deleted file mode 100644
index 11eb1f574bf..00000000000
--- a/app/assets/images/emoji/monorail.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mortar_board.png b/app/assets/images/emoji/mortar_board.png
deleted file mode 100644
index 8b17ddd9d00..00000000000
--- a/app/assets/images/emoji/mortar_board.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mosque.png b/app/assets/images/emoji/mosque.png
deleted file mode 100644
index ef770b26d96..00000000000
--- a/app/assets/images/emoji/mosque.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/motor_scooter.png b/app/assets/images/emoji/motor_scooter.png
deleted file mode 100644
index c5afa72d807..00000000000
--- a/app/assets/images/emoji/motor_scooter.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/motorboat.png b/app/assets/images/emoji/motorboat.png
deleted file mode 100644
index 0506db1a40f..00000000000
--- a/app/assets/images/emoji/motorboat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/motorcycle.png b/app/assets/images/emoji/motorcycle.png
deleted file mode 100644
index 3d1d567e8ec..00000000000
--- a/app/assets/images/emoji/motorcycle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/motorway.png b/app/assets/images/emoji/motorway.png
deleted file mode 100644
index 8c3d3d03e3f..00000000000
--- a/app/assets/images/emoji/motorway.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mount_fuji.png b/app/assets/images/emoji/mount_fuji.png
deleted file mode 100644
index 88a54752458..00000000000
--- a/app/assets/images/emoji/mount_fuji.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mountain.png b/app/assets/images/emoji/mountain.png
deleted file mode 100644
index 6722ebdd294..00000000000
--- a/app/assets/images/emoji/mountain.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mountain_bicyclist.png b/app/assets/images/emoji/mountain_bicyclist.png
deleted file mode 100644
index 41d3dc3ac6f..00000000000
--- a/app/assets/images/emoji/mountain_bicyclist.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mountain_bicyclist_tone1.png b/app/assets/images/emoji/mountain_bicyclist_tone1.png
deleted file mode 100644
index e9f1daf5e40..00000000000
--- a/app/assets/images/emoji/mountain_bicyclist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mountain_bicyclist_tone2.png b/app/assets/images/emoji/mountain_bicyclist_tone2.png
deleted file mode 100644
index 555b9e29d4d..00000000000
--- a/app/assets/images/emoji/mountain_bicyclist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mountain_bicyclist_tone3.png b/app/assets/images/emoji/mountain_bicyclist_tone3.png
deleted file mode 100644
index 7df5508ec8c..00000000000
--- a/app/assets/images/emoji/mountain_bicyclist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mountain_bicyclist_tone4.png b/app/assets/images/emoji/mountain_bicyclist_tone4.png
deleted file mode 100644
index f94b3450697..00000000000
--- a/app/assets/images/emoji/mountain_bicyclist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mountain_bicyclist_tone5.png b/app/assets/images/emoji/mountain_bicyclist_tone5.png
deleted file mode 100644
index 16a45861e1f..00000000000
--- a/app/assets/images/emoji/mountain_bicyclist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mountain_cableway.png b/app/assets/images/emoji/mountain_cableway.png
deleted file mode 100644
index 1dea73ca53b..00000000000
--- a/app/assets/images/emoji/mountain_cableway.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mountain_railway.png b/app/assets/images/emoji/mountain_railway.png
deleted file mode 100644
index ade2218e469..00000000000
--- a/app/assets/images/emoji/mountain_railway.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mountain_snow.png b/app/assets/images/emoji/mountain_snow.png
deleted file mode 100644
index 76e1cfd8313..00000000000
--- a/app/assets/images/emoji/mountain_snow.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mouse.png b/app/assets/images/emoji/mouse.png
deleted file mode 100644
index 50afcd3262e..00000000000
--- a/app/assets/images/emoji/mouse.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mouse2.png b/app/assets/images/emoji/mouse2.png
deleted file mode 100644
index 20fb041f09f..00000000000
--- a/app/assets/images/emoji/mouse2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mouse_three_button.png b/app/assets/images/emoji/mouse_three_button.png
deleted file mode 100644
index e84e96ff6e8..00000000000
--- a/app/assets/images/emoji/mouse_three_button.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/movie_camera.png b/app/assets/images/emoji/movie_camera.png
deleted file mode 100644
index 4e73b130155..00000000000
--- a/app/assets/images/emoji/movie_camera.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/moyai.png b/app/assets/images/emoji/moyai.png
deleted file mode 100644
index e6a7779c45b..00000000000
--- a/app/assets/images/emoji/moyai.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mrs_claus.png b/app/assets/images/emoji/mrs_claus.png
deleted file mode 100644
index 9cf2458df1a..00000000000
--- a/app/assets/images/emoji/mrs_claus.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mrs_claus_tone1.png b/app/assets/images/emoji/mrs_claus_tone1.png
deleted file mode 100644
index d8a695d7035..00000000000
--- a/app/assets/images/emoji/mrs_claus_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mrs_claus_tone2.png b/app/assets/images/emoji/mrs_claus_tone2.png
deleted file mode 100644
index 0e17e8c51f3..00000000000
--- a/app/assets/images/emoji/mrs_claus_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mrs_claus_tone3.png b/app/assets/images/emoji/mrs_claus_tone3.png
deleted file mode 100644
index c3ee4d1dfae..00000000000
--- a/app/assets/images/emoji/mrs_claus_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mrs_claus_tone4.png b/app/assets/images/emoji/mrs_claus_tone4.png
deleted file mode 100644
index 68a556da2fe..00000000000
--- a/app/assets/images/emoji/mrs_claus_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mrs_claus_tone5.png b/app/assets/images/emoji/mrs_claus_tone5.png
deleted file mode 100644
index ccab3c40ff2..00000000000
--- a/app/assets/images/emoji/mrs_claus_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/muscle.png b/app/assets/images/emoji/muscle.png
deleted file mode 100644
index 7e67c1880f7..00000000000
--- a/app/assets/images/emoji/muscle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/muscle_tone1.png b/app/assets/images/emoji/muscle_tone1.png
deleted file mode 100644
index 1522942ce51..00000000000
--- a/app/assets/images/emoji/muscle_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/muscle_tone2.png b/app/assets/images/emoji/muscle_tone2.png
deleted file mode 100644
index 569c6e832ca..00000000000
--- a/app/assets/images/emoji/muscle_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/muscle_tone3.png b/app/assets/images/emoji/muscle_tone3.png
deleted file mode 100644
index 0a76b00fa89..00000000000
--- a/app/assets/images/emoji/muscle_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/muscle_tone4.png b/app/assets/images/emoji/muscle_tone4.png
deleted file mode 100644
index f0cf31328e0..00000000000
--- a/app/assets/images/emoji/muscle_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/muscle_tone5.png b/app/assets/images/emoji/muscle_tone5.png
deleted file mode 100644
index 4fda92460e8..00000000000
--- a/app/assets/images/emoji/muscle_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mushroom.png b/app/assets/images/emoji/mushroom.png
deleted file mode 100644
index dd85742ba2c..00000000000
--- a/app/assets/images/emoji/mushroom.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/musical_keyboard.png b/app/assets/images/emoji/musical_keyboard.png
deleted file mode 100644
index 442b7456842..00000000000
--- a/app/assets/images/emoji/musical_keyboard.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/musical_note.png b/app/assets/images/emoji/musical_note.png
deleted file mode 100644
index 06691ef61bb..00000000000
--- a/app/assets/images/emoji/musical_note.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/musical_score.png b/app/assets/images/emoji/musical_score.png
deleted file mode 100644
index 47dc05a8ef5..00000000000
--- a/app/assets/images/emoji/musical_score.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/mute.png b/app/assets/images/emoji/mute.png
deleted file mode 100644
index 7c1788e5075..00000000000
--- a/app/assets/images/emoji/mute.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nail_care.png b/app/assets/images/emoji/nail_care.png
deleted file mode 100644
index aa52af7050d..00000000000
--- a/app/assets/images/emoji/nail_care.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nail_care_tone1.png b/app/assets/images/emoji/nail_care_tone1.png
deleted file mode 100644
index 26e883dd244..00000000000
--- a/app/assets/images/emoji/nail_care_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nail_care_tone2.png b/app/assets/images/emoji/nail_care_tone2.png
deleted file mode 100644
index 61257b47ea3..00000000000
--- a/app/assets/images/emoji/nail_care_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nail_care_tone3.png b/app/assets/images/emoji/nail_care_tone3.png
deleted file mode 100644
index 29871b05f62..00000000000
--- a/app/assets/images/emoji/nail_care_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nail_care_tone4.png b/app/assets/images/emoji/nail_care_tone4.png
deleted file mode 100644
index 2881de0b17d..00000000000
--- a/app/assets/images/emoji/nail_care_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nail_care_tone5.png b/app/assets/images/emoji/nail_care_tone5.png
deleted file mode 100644
index a0b7c0a45a6..00000000000
--- a/app/assets/images/emoji/nail_care_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/name_badge.png b/app/assets/images/emoji/name_badge.png
deleted file mode 100644
index ec5ee213e20..00000000000
--- a/app/assets/images/emoji/name_badge.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nauseated_face.png b/app/assets/images/emoji/nauseated_face.png
deleted file mode 100644
index a566c109c28..00000000000
--- a/app/assets/images/emoji/nauseated_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/necktie.png b/app/assets/images/emoji/necktie.png
deleted file mode 100644
index 1804e7f3ff3..00000000000
--- a/app/assets/images/emoji/necktie.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/negative_squared_cross_mark.png b/app/assets/images/emoji/negative_squared_cross_mark.png
deleted file mode 100644
index dae487f1f98..00000000000
--- a/app/assets/images/emoji/negative_squared_cross_mark.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nerd.png b/app/assets/images/emoji/nerd.png
deleted file mode 100644
index 7820bd581dc..00000000000
--- a/app/assets/images/emoji/nerd.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/neutral_face.png b/app/assets/images/emoji/neutral_face.png
deleted file mode 100644
index 065d193afe4..00000000000
--- a/app/assets/images/emoji/neutral_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/new.png b/app/assets/images/emoji/new.png
deleted file mode 100644
index b4f85488d1a..00000000000
--- a/app/assets/images/emoji/new.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/new_moon.png b/app/assets/images/emoji/new_moon.png
deleted file mode 100644
index ecff72caa42..00000000000
--- a/app/assets/images/emoji/new_moon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/new_moon_with_face.png b/app/assets/images/emoji/new_moon_with_face.png
deleted file mode 100644
index 150dd12400c..00000000000
--- a/app/assets/images/emoji/new_moon_with_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/newspaper.png b/app/assets/images/emoji/newspaper.png
deleted file mode 100644
index 2aa8f060bde..00000000000
--- a/app/assets/images/emoji/newspaper.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/newspaper2.png b/app/assets/images/emoji/newspaper2.png
deleted file mode 100644
index f64748df2b2..00000000000
--- a/app/assets/images/emoji/newspaper2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ng.png b/app/assets/images/emoji/ng.png
deleted file mode 100644
index ee8d20f5ebc..00000000000
--- a/app/assets/images/emoji/ng.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/night_with_stars.png b/app/assets/images/emoji/night_with_stars.png
deleted file mode 100644
index ca2018f456d..00000000000
--- a/app/assets/images/emoji/night_with_stars.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nine.png b/app/assets/images/emoji/nine.png
deleted file mode 100644
index 9fce3d1eca9..00000000000
--- a/app/assets/images/emoji/nine.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_bell.png b/app/assets/images/emoji/no_bell.png
deleted file mode 100644
index 15cb38dd1e7..00000000000
--- a/app/assets/images/emoji/no_bell.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_bicycles.png b/app/assets/images/emoji/no_bicycles.png
deleted file mode 100644
index 19c85421ce9..00000000000
--- a/app/assets/images/emoji/no_bicycles.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_entry.png b/app/assets/images/emoji/no_entry.png
deleted file mode 100644
index 476800fc5c6..00000000000
--- a/app/assets/images/emoji/no_entry.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_entry_sign.png b/app/assets/images/emoji/no_entry_sign.png
deleted file mode 100644
index d2efd65e74b..00000000000
--- a/app/assets/images/emoji/no_entry_sign.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_good.png b/app/assets/images/emoji/no_good.png
deleted file mode 100644
index ed577100322..00000000000
--- a/app/assets/images/emoji/no_good.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_good_tone1.png b/app/assets/images/emoji/no_good_tone1.png
deleted file mode 100644
index 5c1a3cbb884..00000000000
--- a/app/assets/images/emoji/no_good_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_good_tone2.png b/app/assets/images/emoji/no_good_tone2.png
deleted file mode 100644
index 80d8021f8fe..00000000000
--- a/app/assets/images/emoji/no_good_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_good_tone3.png b/app/assets/images/emoji/no_good_tone3.png
deleted file mode 100644
index 635e6a00815..00000000000
--- a/app/assets/images/emoji/no_good_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_good_tone4.png b/app/assets/images/emoji/no_good_tone4.png
deleted file mode 100644
index b96e412a374..00000000000
--- a/app/assets/images/emoji/no_good_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_good_tone5.png b/app/assets/images/emoji/no_good_tone5.png
deleted file mode 100644
index 9a7084afa0a..00000000000
--- a/app/assets/images/emoji/no_good_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_mobile_phones.png b/app/assets/images/emoji/no_mobile_phones.png
deleted file mode 100644
index 7b1ae6ea579..00000000000
--- a/app/assets/images/emoji/no_mobile_phones.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_mouth.png b/app/assets/images/emoji/no_mouth.png
deleted file mode 100644
index b642f6c1172..00000000000
--- a/app/assets/images/emoji/no_mouth.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_pedestrians.png b/app/assets/images/emoji/no_pedestrians.png
deleted file mode 100644
index 286aa577a23..00000000000
--- a/app/assets/images/emoji/no_pedestrians.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/no_smoking.png b/app/assets/images/emoji/no_smoking.png
deleted file mode 100644
index 586b8d29d05..00000000000
--- a/app/assets/images/emoji/no_smoking.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/non-potable_water.png b/app/assets/images/emoji/non-potable_water.png
deleted file mode 100644
index 827d4193f4e..00000000000
--- a/app/assets/images/emoji/non-potable_water.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nose.png b/app/assets/images/emoji/nose.png
deleted file mode 100644
index 2f04ac5f98f..00000000000
--- a/app/assets/images/emoji/nose.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nose_tone1.png b/app/assets/images/emoji/nose_tone1.png
deleted file mode 100644
index 8008d17506e..00000000000
--- a/app/assets/images/emoji/nose_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nose_tone2.png b/app/assets/images/emoji/nose_tone2.png
deleted file mode 100644
index ac17f26e827..00000000000
--- a/app/assets/images/emoji/nose_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nose_tone3.png b/app/assets/images/emoji/nose_tone3.png
deleted file mode 100644
index d8b6cbe0f8e..00000000000
--- a/app/assets/images/emoji/nose_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nose_tone4.png b/app/assets/images/emoji/nose_tone4.png
deleted file mode 100644
index 004b2631e2e..00000000000
--- a/app/assets/images/emoji/nose_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nose_tone5.png b/app/assets/images/emoji/nose_tone5.png
deleted file mode 100644
index 7b33821f6c9..00000000000
--- a/app/assets/images/emoji/nose_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/notebook.png b/app/assets/images/emoji/notebook.png
deleted file mode 100644
index f6c28b4915d..00000000000
--- a/app/assets/images/emoji/notebook.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/notebook_with_decorative_cover.png b/app/assets/images/emoji/notebook_with_decorative_cover.png
deleted file mode 100644
index 03f566b6d2c..00000000000
--- a/app/assets/images/emoji/notebook_with_decorative_cover.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/notepad_spiral.png b/app/assets/images/emoji/notepad_spiral.png
deleted file mode 100644
index 85faa10d8ea..00000000000
--- a/app/assets/images/emoji/notepad_spiral.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/notes.png b/app/assets/images/emoji/notes.png
deleted file mode 100644
index 57d499aa181..00000000000
--- a/app/assets/images/emoji/notes.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/nut_and_bolt.png b/app/assets/images/emoji/nut_and_bolt.png
deleted file mode 100644
index 4b9ae155319..00000000000
--- a/app/assets/images/emoji/nut_and_bolt.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/o.png b/app/assets/images/emoji/o.png
deleted file mode 100644
index 3fe75ce4675..00000000000
--- a/app/assets/images/emoji/o.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/o2.png b/app/assets/images/emoji/o2.png
deleted file mode 100644
index 73278ba194a..00000000000
--- a/app/assets/images/emoji/o2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ocean.png b/app/assets/images/emoji/ocean.png
deleted file mode 100644
index 45ff1e87703..00000000000
--- a/app/assets/images/emoji/ocean.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/octagonal_sign.png b/app/assets/images/emoji/octagonal_sign.png
deleted file mode 100644
index 5ed61004045..00000000000
--- a/app/assets/images/emoji/octagonal_sign.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/octopus.png b/app/assets/images/emoji/octopus.png
deleted file mode 100644
index 72c84074aac..00000000000
--- a/app/assets/images/emoji/octopus.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/oden.png b/app/assets/images/emoji/oden.png
deleted file mode 100644
index d38a849fece..00000000000
--- a/app/assets/images/emoji/oden.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/office.png b/app/assets/images/emoji/office.png
deleted file mode 100644
index 7eee927d1b0..00000000000
--- a/app/assets/images/emoji/office.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/oil.png b/app/assets/images/emoji/oil.png
deleted file mode 100644
index c4c4d42da8b..00000000000
--- a/app/assets/images/emoji/oil.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok.png b/app/assets/images/emoji/ok.png
deleted file mode 100644
index d0d775532ff..00000000000
--- a/app/assets/images/emoji/ok.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok_hand.png b/app/assets/images/emoji/ok_hand.png
deleted file mode 100644
index 028d69b0de3..00000000000
--- a/app/assets/images/emoji/ok_hand.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok_hand_tone1.png b/app/assets/images/emoji/ok_hand_tone1.png
deleted file mode 100644
index cecf7b2ab5a..00000000000
--- a/app/assets/images/emoji/ok_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok_hand_tone2.png b/app/assets/images/emoji/ok_hand_tone2.png
deleted file mode 100644
index c19239bcd3d..00000000000
--- a/app/assets/images/emoji/ok_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok_hand_tone3.png b/app/assets/images/emoji/ok_hand_tone3.png
deleted file mode 100644
index 94b65b03ecd..00000000000
--- a/app/assets/images/emoji/ok_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok_hand_tone4.png b/app/assets/images/emoji/ok_hand_tone4.png
deleted file mode 100644
index 03d26f08e6a..00000000000
--- a/app/assets/images/emoji/ok_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok_hand_tone5.png b/app/assets/images/emoji/ok_hand_tone5.png
deleted file mode 100644
index d4b24086364..00000000000
--- a/app/assets/images/emoji/ok_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok_woman.png b/app/assets/images/emoji/ok_woman.png
deleted file mode 100644
index 90a2c7469c4..00000000000
--- a/app/assets/images/emoji/ok_woman.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok_woman_tone1.png b/app/assets/images/emoji/ok_woman_tone1.png
deleted file mode 100644
index c99543e785b..00000000000
--- a/app/assets/images/emoji/ok_woman_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok_woman_tone2.png b/app/assets/images/emoji/ok_woman_tone2.png
deleted file mode 100644
index ad5fae813db..00000000000
--- a/app/assets/images/emoji/ok_woman_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok_woman_tone3.png b/app/assets/images/emoji/ok_woman_tone3.png
deleted file mode 100644
index 51bf4fab406..00000000000
--- a/app/assets/images/emoji/ok_woman_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok_woman_tone4.png b/app/assets/images/emoji/ok_woman_tone4.png
deleted file mode 100644
index ee3f9dc640a..00000000000
--- a/app/assets/images/emoji/ok_woman_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ok_woman_tone5.png b/app/assets/images/emoji/ok_woman_tone5.png
deleted file mode 100644
index 62a9d9237f7..00000000000
--- a/app/assets/images/emoji/ok_woman_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/older_man.png b/app/assets/images/emoji/older_man.png
deleted file mode 100644
index 4ace4e6f308..00000000000
--- a/app/assets/images/emoji/older_man.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/older_man_tone1.png b/app/assets/images/emoji/older_man_tone1.png
deleted file mode 100644
index ab459baace8..00000000000
--- a/app/assets/images/emoji/older_man_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/older_man_tone2.png b/app/assets/images/emoji/older_man_tone2.png
deleted file mode 100644
index f4dfc7694ea..00000000000
--- a/app/assets/images/emoji/older_man_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/older_man_tone3.png b/app/assets/images/emoji/older_man_tone3.png
deleted file mode 100644
index 5ffd11792f4..00000000000
--- a/app/assets/images/emoji/older_man_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/older_man_tone4.png b/app/assets/images/emoji/older_man_tone4.png
deleted file mode 100644
index b350a764bfd..00000000000
--- a/app/assets/images/emoji/older_man_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/older_man_tone5.png b/app/assets/images/emoji/older_man_tone5.png
deleted file mode 100644
index 05fe24a1708..00000000000
--- a/app/assets/images/emoji/older_man_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/older_woman.png b/app/assets/images/emoji/older_woman.png
deleted file mode 100644
index 52dc4987143..00000000000
--- a/app/assets/images/emoji/older_woman.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/older_woman_tone1.png b/app/assets/images/emoji/older_woman_tone1.png
deleted file mode 100644
index b49e821402c..00000000000
--- a/app/assets/images/emoji/older_woman_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/older_woman_tone2.png b/app/assets/images/emoji/older_woman_tone2.png
deleted file mode 100644
index e86bf5ab3b7..00000000000
--- a/app/assets/images/emoji/older_woman_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/older_woman_tone3.png b/app/assets/images/emoji/older_woman_tone3.png
deleted file mode 100644
index 83fc14b0874..00000000000
--- a/app/assets/images/emoji/older_woman_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/older_woman_tone4.png b/app/assets/images/emoji/older_woman_tone4.png
deleted file mode 100644
index e4aa8a424d4..00000000000
--- a/app/assets/images/emoji/older_woman_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/older_woman_tone5.png b/app/assets/images/emoji/older_woman_tone5.png
deleted file mode 100644
index 4009012bb0a..00000000000
--- a/app/assets/images/emoji/older_woman_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/om_symbol.png b/app/assets/images/emoji/om_symbol.png
deleted file mode 100644
index a35c63c459c..00000000000
--- a/app/assets/images/emoji/om_symbol.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/on.png b/app/assets/images/emoji/on.png
deleted file mode 100644
index a0c371ae21e..00000000000
--- a/app/assets/images/emoji/on.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/oncoming_automobile.png b/app/assets/images/emoji/oncoming_automobile.png
deleted file mode 100644
index 3c7e1d52e63..00000000000
--- a/app/assets/images/emoji/oncoming_automobile.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/oncoming_bus.png b/app/assets/images/emoji/oncoming_bus.png
deleted file mode 100644
index ad91e256c7f..00000000000
--- a/app/assets/images/emoji/oncoming_bus.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/oncoming_police_car.png b/app/assets/images/emoji/oncoming_police_car.png
deleted file mode 100644
index c9109c85b5d..00000000000
--- a/app/assets/images/emoji/oncoming_police_car.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/oncoming_taxi.png b/app/assets/images/emoji/oncoming_taxi.png
deleted file mode 100644
index fea14e45846..00000000000
--- a/app/assets/images/emoji/oncoming_taxi.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/one.png b/app/assets/images/emoji/one.png
deleted file mode 100644
index e6d84b80128..00000000000
--- a/app/assets/images/emoji/one.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/open_file_folder.png b/app/assets/images/emoji/open_file_folder.png
deleted file mode 100644
index 3993b09222f..00000000000
--- a/app/assets/images/emoji/open_file_folder.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/open_hands.png b/app/assets/images/emoji/open_hands.png
deleted file mode 100644
index 1cf75c9101e..00000000000
--- a/app/assets/images/emoji/open_hands.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/open_hands_tone1.png b/app/assets/images/emoji/open_hands_tone1.png
deleted file mode 100644
index 352d2614f11..00000000000
--- a/app/assets/images/emoji/open_hands_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/open_hands_tone2.png b/app/assets/images/emoji/open_hands_tone2.png
deleted file mode 100644
index 70824a50c73..00000000000
--- a/app/assets/images/emoji/open_hands_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/open_hands_tone3.png b/app/assets/images/emoji/open_hands_tone3.png
deleted file mode 100644
index d7d136bd3db..00000000000
--- a/app/assets/images/emoji/open_hands_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/open_hands_tone4.png b/app/assets/images/emoji/open_hands_tone4.png
deleted file mode 100644
index df4eaa711e7..00000000000
--- a/app/assets/images/emoji/open_hands_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/open_hands_tone5.png b/app/assets/images/emoji/open_hands_tone5.png
deleted file mode 100644
index 7dc04eaebd8..00000000000
--- a/app/assets/images/emoji/open_hands_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/open_mouth.png b/app/assets/images/emoji/open_mouth.png
deleted file mode 100644
index a62cd27e148..00000000000
--- a/app/assets/images/emoji/open_mouth.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ophiuchus.png b/app/assets/images/emoji/ophiuchus.png
deleted file mode 100644
index 0a780a700da..00000000000
--- a/app/assets/images/emoji/ophiuchus.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/orange_book.png b/app/assets/images/emoji/orange_book.png
deleted file mode 100644
index ab40e6ae6a2..00000000000
--- a/app/assets/images/emoji/orange_book.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/orthodox_cross.png b/app/assets/images/emoji/orthodox_cross.png
deleted file mode 100644
index 0530e33a4d4..00000000000
--- a/app/assets/images/emoji/orthodox_cross.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/outbox_tray.png b/app/assets/images/emoji/outbox_tray.png
deleted file mode 100644
index 46493ed5b2c..00000000000
--- a/app/assets/images/emoji/outbox_tray.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/owl.png b/app/assets/images/emoji/owl.png
deleted file mode 100644
index fa6815480c3..00000000000
--- a/app/assets/images/emoji/owl.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ox.png b/app/assets/images/emoji/ox.png
deleted file mode 100644
index badf5708f2f..00000000000
--- a/app/assets/images/emoji/ox.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/package.png b/app/assets/images/emoji/package.png
deleted file mode 100644
index 85431756ad8..00000000000
--- a/app/assets/images/emoji/package.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/page_facing_up.png b/app/assets/images/emoji/page_facing_up.png
deleted file mode 100644
index ba4ed757e01..00000000000
--- a/app/assets/images/emoji/page_facing_up.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/page_with_curl.png b/app/assets/images/emoji/page_with_curl.png
deleted file mode 100644
index 06355319c74..00000000000
--- a/app/assets/images/emoji/page_with_curl.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pager.png b/app/assets/images/emoji/pager.png
deleted file mode 100644
index b24b99306a2..00000000000
--- a/app/assets/images/emoji/pager.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/paintbrush.png b/app/assets/images/emoji/paintbrush.png
deleted file mode 100644
index 28bffbaa3c9..00000000000
--- a/app/assets/images/emoji/paintbrush.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/palm_tree.png b/app/assets/images/emoji/palm_tree.png
deleted file mode 100644
index 4bbb10f4f19..00000000000
--- a/app/assets/images/emoji/palm_tree.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pancakes.png b/app/assets/images/emoji/pancakes.png
deleted file mode 100644
index 6223d1a28e9..00000000000
--- a/app/assets/images/emoji/pancakes.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/panda_face.png b/app/assets/images/emoji/panda_face.png
deleted file mode 100644
index 978382775ce..00000000000
--- a/app/assets/images/emoji/panda_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/paperclip.png b/app/assets/images/emoji/paperclip.png
deleted file mode 100644
index 8cd8d4f8750..00000000000
--- a/app/assets/images/emoji/paperclip.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/paperclips.png b/app/assets/images/emoji/paperclips.png
deleted file mode 100644
index 76021e8c705..00000000000
--- a/app/assets/images/emoji/paperclips.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/park.png b/app/assets/images/emoji/park.png
deleted file mode 100644
index 63ec7016301..00000000000
--- a/app/assets/images/emoji/park.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/parking.png b/app/assets/images/emoji/parking.png
deleted file mode 100644
index 7be7dac27e8..00000000000
--- a/app/assets/images/emoji/parking.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/part_alternation_mark.png b/app/assets/images/emoji/part_alternation_mark.png
deleted file mode 100644
index 70453d41528..00000000000
--- a/app/assets/images/emoji/part_alternation_mark.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/partly_sunny.png b/app/assets/images/emoji/partly_sunny.png
deleted file mode 100644
index a55e59c344c..00000000000
--- a/app/assets/images/emoji/partly_sunny.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/passport_control.png b/app/assets/images/emoji/passport_control.png
deleted file mode 100644
index 079e34ee4d4..00000000000
--- a/app/assets/images/emoji/passport_control.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pause_button.png b/app/assets/images/emoji/pause_button.png
deleted file mode 100644
index 4f07e7ebfd7..00000000000
--- a/app/assets/images/emoji/pause_button.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/peace.png b/app/assets/images/emoji/peace.png
deleted file mode 100644
index 86033faf477..00000000000
--- a/app/assets/images/emoji/peace.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/peach.png b/app/assets/images/emoji/peach.png
deleted file mode 100644
index 9ab57cbb758..00000000000
--- a/app/assets/images/emoji/peach.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/peanuts.png b/app/assets/images/emoji/peanuts.png
deleted file mode 100644
index b64fadad010..00000000000
--- a/app/assets/images/emoji/peanuts.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pear.png b/app/assets/images/emoji/pear.png
deleted file mode 100644
index 3869f718bcf..00000000000
--- a/app/assets/images/emoji/pear.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pen_ballpoint.png b/app/assets/images/emoji/pen_ballpoint.png
deleted file mode 100644
index 6ef7a342433..00000000000
--- a/app/assets/images/emoji/pen_ballpoint.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pen_fountain.png b/app/assets/images/emoji/pen_fountain.png
deleted file mode 100644
index 3ca4bd2c231..00000000000
--- a/app/assets/images/emoji/pen_fountain.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pencil.png b/app/assets/images/emoji/pencil.png
deleted file mode 100644
index edc6155e168..00000000000
--- a/app/assets/images/emoji/pencil.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pencil2.png b/app/assets/images/emoji/pencil2.png
deleted file mode 100644
index 3833d590fa2..00000000000
--- a/app/assets/images/emoji/pencil2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/penguin.png b/app/assets/images/emoji/penguin.png
deleted file mode 100644
index c0064fb9734..00000000000
--- a/app/assets/images/emoji/penguin.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pensive.png b/app/assets/images/emoji/pensive.png
deleted file mode 100644
index 490fb566954..00000000000
--- a/app/assets/images/emoji/pensive.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/performing_arts.png b/app/assets/images/emoji/performing_arts.png
deleted file mode 100644
index 685441fdaa1..00000000000
--- a/app/assets/images/emoji/performing_arts.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/persevere.png b/app/assets/images/emoji/persevere.png
deleted file mode 100644
index 646a05fe908..00000000000
--- a/app/assets/images/emoji/persevere.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_frowning.png b/app/assets/images/emoji/person_frowning.png
deleted file mode 100644
index 579324959a1..00000000000
--- a/app/assets/images/emoji/person_frowning.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_frowning_tone1.png b/app/assets/images/emoji/person_frowning_tone1.png
deleted file mode 100644
index 21d3bb43923..00000000000
--- a/app/assets/images/emoji/person_frowning_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_frowning_tone2.png b/app/assets/images/emoji/person_frowning_tone2.png
deleted file mode 100644
index 973f5fc8382..00000000000
--- a/app/assets/images/emoji/person_frowning_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_frowning_tone3.png b/app/assets/images/emoji/person_frowning_tone3.png
deleted file mode 100644
index 41fbcc78816..00000000000
--- a/app/assets/images/emoji/person_frowning_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_frowning_tone4.png b/app/assets/images/emoji/person_frowning_tone4.png
deleted file mode 100644
index 5a37c741030..00000000000
--- a/app/assets/images/emoji/person_frowning_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_frowning_tone5.png b/app/assets/images/emoji/person_frowning_tone5.png
deleted file mode 100644
index e08141f3efe..00000000000
--- a/app/assets/images/emoji/person_frowning_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_with_blond_hair.png b/app/assets/images/emoji/person_with_blond_hair.png
deleted file mode 100644
index ad6f01a7dda..00000000000
--- a/app/assets/images/emoji/person_with_blond_hair.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_with_blond_hair_tone1.png b/app/assets/images/emoji/person_with_blond_hair_tone1.png
deleted file mode 100644
index 7d18ef24445..00000000000
--- a/app/assets/images/emoji/person_with_blond_hair_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_with_blond_hair_tone2.png b/app/assets/images/emoji/person_with_blond_hair_tone2.png
deleted file mode 100644
index dae1307315c..00000000000
--- a/app/assets/images/emoji/person_with_blond_hair_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_with_blond_hair_tone3.png b/app/assets/images/emoji/person_with_blond_hair_tone3.png
deleted file mode 100644
index 684677e8e5a..00000000000
--- a/app/assets/images/emoji/person_with_blond_hair_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_with_blond_hair_tone4.png b/app/assets/images/emoji/person_with_blond_hair_tone4.png
deleted file mode 100644
index 012be0b51f8..00000000000
--- a/app/assets/images/emoji/person_with_blond_hair_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_with_blond_hair_tone5.png b/app/assets/images/emoji/person_with_blond_hair_tone5.png
deleted file mode 100644
index d4ecc4cf44b..00000000000
--- a/app/assets/images/emoji/person_with_blond_hair_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_with_pouting_face.png b/app/assets/images/emoji/person_with_pouting_face.png
deleted file mode 100644
index 10eb0571078..00000000000
--- a/app/assets/images/emoji/person_with_pouting_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_with_pouting_face_tone1.png b/app/assets/images/emoji/person_with_pouting_face_tone1.png
deleted file mode 100644
index 57e826b75a4..00000000000
--- a/app/assets/images/emoji/person_with_pouting_face_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_with_pouting_face_tone2.png b/app/assets/images/emoji/person_with_pouting_face_tone2.png
deleted file mode 100644
index 3f317c0c25f..00000000000
--- a/app/assets/images/emoji/person_with_pouting_face_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_with_pouting_face_tone3.png b/app/assets/images/emoji/person_with_pouting_face_tone3.png
deleted file mode 100644
index d2fbb6c20bf..00000000000
--- a/app/assets/images/emoji/person_with_pouting_face_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_with_pouting_face_tone4.png b/app/assets/images/emoji/person_with_pouting_face_tone4.png
deleted file mode 100644
index 643ceb4a5c5..00000000000
--- a/app/assets/images/emoji/person_with_pouting_face_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/person_with_pouting_face_tone5.png b/app/assets/images/emoji/person_with_pouting_face_tone5.png
deleted file mode 100644
index b2eb6859c32..00000000000
--- a/app/assets/images/emoji/person_with_pouting_face_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pick.png b/app/assets/images/emoji/pick.png
deleted file mode 100644
index 6370fe6d791..00000000000
--- a/app/assets/images/emoji/pick.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pig.png b/app/assets/images/emoji/pig.png
deleted file mode 100644
index afe05ca1676..00000000000
--- a/app/assets/images/emoji/pig.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pig2.png b/app/assets/images/emoji/pig2.png
deleted file mode 100644
index 5f31c1a2d75..00000000000
--- a/app/assets/images/emoji/pig2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pig_nose.png b/app/assets/images/emoji/pig_nose.png
deleted file mode 100644
index 3610ae4a910..00000000000
--- a/app/assets/images/emoji/pig_nose.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pill.png b/app/assets/images/emoji/pill.png
deleted file mode 100644
index 1d4530e77a3..00000000000
--- a/app/assets/images/emoji/pill.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pineapple.png b/app/assets/images/emoji/pineapple.png
deleted file mode 100644
index c89a1606462..00000000000
--- a/app/assets/images/emoji/pineapple.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ping_pong.png b/app/assets/images/emoji/ping_pong.png
deleted file mode 100644
index ff3c51727d1..00000000000
--- a/app/assets/images/emoji/ping_pong.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pisces.png b/app/assets/images/emoji/pisces.png
deleted file mode 100644
index 7f6f646a95c..00000000000
--- a/app/assets/images/emoji/pisces.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pizza.png b/app/assets/images/emoji/pizza.png
deleted file mode 100644
index e07365cb398..00000000000
--- a/app/assets/images/emoji/pizza.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/place_of_worship.png b/app/assets/images/emoji/place_of_worship.png
deleted file mode 100644
index 207d59cce85..00000000000
--- a/app/assets/images/emoji/place_of_worship.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/play_pause.png b/app/assets/images/emoji/play_pause.png
deleted file mode 100644
index a9f857139ac..00000000000
--- a/app/assets/images/emoji/play_pause.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_down.png b/app/assets/images/emoji/point_down.png
deleted file mode 100644
index 00d3d13ab5c..00000000000
--- a/app/assets/images/emoji/point_down.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_down_tone1.png b/app/assets/images/emoji/point_down_tone1.png
deleted file mode 100644
index 140f157d8c7..00000000000
--- a/app/assets/images/emoji/point_down_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_down_tone2.png b/app/assets/images/emoji/point_down_tone2.png
deleted file mode 100644
index d518544f7fa..00000000000
--- a/app/assets/images/emoji/point_down_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_down_tone3.png b/app/assets/images/emoji/point_down_tone3.png
deleted file mode 100644
index 018b688b8b7..00000000000
--- a/app/assets/images/emoji/point_down_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_down_tone4.png b/app/assets/images/emoji/point_down_tone4.png
deleted file mode 100644
index 98845bf6f72..00000000000
--- a/app/assets/images/emoji/point_down_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_down_tone5.png b/app/assets/images/emoji/point_down_tone5.png
deleted file mode 100644
index 9a9b039a9fc..00000000000
--- a/app/assets/images/emoji/point_down_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_left.png b/app/assets/images/emoji/point_left.png
deleted file mode 100644
index 599fa2e3cf1..00000000000
--- a/app/assets/images/emoji/point_left.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_left_tone1.png b/app/assets/images/emoji/point_left_tone1.png
deleted file mode 100644
index 88e2c306076..00000000000
--- a/app/assets/images/emoji/point_left_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_left_tone2.png b/app/assets/images/emoji/point_left_tone2.png
deleted file mode 100644
index d3c89d87c5f..00000000000
--- a/app/assets/images/emoji/point_left_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_left_tone3.png b/app/assets/images/emoji/point_left_tone3.png
deleted file mode 100644
index b23b9167358..00000000000
--- a/app/assets/images/emoji/point_left_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_left_tone4.png b/app/assets/images/emoji/point_left_tone4.png
deleted file mode 100644
index 3093f325c27..00000000000
--- a/app/assets/images/emoji/point_left_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_left_tone5.png b/app/assets/images/emoji/point_left_tone5.png
deleted file mode 100644
index 2b4cbfa120c..00000000000
--- a/app/assets/images/emoji/point_left_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_right.png b/app/assets/images/emoji/point_right.png
deleted file mode 100644
index 93a3cd34aa5..00000000000
--- a/app/assets/images/emoji/point_right.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_right_tone1.png b/app/assets/images/emoji/point_right_tone1.png
deleted file mode 100644
index 4a28c6bbc89..00000000000
--- a/app/assets/images/emoji/point_right_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_right_tone2.png b/app/assets/images/emoji/point_right_tone2.png
deleted file mode 100644
index 7cb13231733..00000000000
--- a/app/assets/images/emoji/point_right_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_right_tone3.png b/app/assets/images/emoji/point_right_tone3.png
deleted file mode 100644
index 5514807d71a..00000000000
--- a/app/assets/images/emoji/point_right_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_right_tone4.png b/app/assets/images/emoji/point_right_tone4.png
deleted file mode 100644
index b8541d6440d..00000000000
--- a/app/assets/images/emoji/point_right_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_right_tone5.png b/app/assets/images/emoji/point_right_tone5.png
deleted file mode 100644
index 1b7aab07bb1..00000000000
--- a/app/assets/images/emoji/point_right_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_up.png b/app/assets/images/emoji/point_up.png
deleted file mode 100644
index f4978ff0f00..00000000000
--- a/app/assets/images/emoji/point_up.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_up_2.png b/app/assets/images/emoji/point_up_2.png
deleted file mode 100644
index bc496dfeae4..00000000000
--- a/app/assets/images/emoji/point_up_2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_up_2_tone1.png b/app/assets/images/emoji/point_up_2_tone1.png
deleted file mode 100644
index a12a7e78430..00000000000
--- a/app/assets/images/emoji/point_up_2_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_up_2_tone2.png b/app/assets/images/emoji/point_up_2_tone2.png
deleted file mode 100644
index cdff40ceab0..00000000000
--- a/app/assets/images/emoji/point_up_2_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_up_2_tone3.png b/app/assets/images/emoji/point_up_2_tone3.png
deleted file mode 100644
index a07ce9e5ae8..00000000000
--- a/app/assets/images/emoji/point_up_2_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_up_2_tone4.png b/app/assets/images/emoji/point_up_2_tone4.png
deleted file mode 100644
index 4f86c88ba42..00000000000
--- a/app/assets/images/emoji/point_up_2_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_up_2_tone5.png b/app/assets/images/emoji/point_up_2_tone5.png
deleted file mode 100644
index ed1b26c35d3..00000000000
--- a/app/assets/images/emoji/point_up_2_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_up_tone1.png b/app/assets/images/emoji/point_up_tone1.png
deleted file mode 100644
index 6a9db21d64c..00000000000
--- a/app/assets/images/emoji/point_up_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_up_tone2.png b/app/assets/images/emoji/point_up_tone2.png
deleted file mode 100644
index 15aa9ea0e05..00000000000
--- a/app/assets/images/emoji/point_up_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_up_tone3.png b/app/assets/images/emoji/point_up_tone3.png
deleted file mode 100644
index 652b73a9c5d..00000000000
--- a/app/assets/images/emoji/point_up_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_up_tone4.png b/app/assets/images/emoji/point_up_tone4.png
deleted file mode 100644
index 692bad926e9..00000000000
--- a/app/assets/images/emoji/point_up_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/point_up_tone5.png b/app/assets/images/emoji/point_up_tone5.png
deleted file mode 100644
index 1e1b10fb71c..00000000000
--- a/app/assets/images/emoji/point_up_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/police_car.png b/app/assets/images/emoji/police_car.png
deleted file mode 100644
index 3da4253de7e..00000000000
--- a/app/assets/images/emoji/police_car.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/poodle.png b/app/assets/images/emoji/poodle.png
deleted file mode 100644
index 8ec39e396af..00000000000
--- a/app/assets/images/emoji/poodle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/poop.png b/app/assets/images/emoji/poop.png
deleted file mode 100644
index 10b15e72d56..00000000000
--- a/app/assets/images/emoji/poop.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/popcorn.png b/app/assets/images/emoji/popcorn.png
deleted file mode 100644
index 36853e381d4..00000000000
--- a/app/assets/images/emoji/popcorn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/post_office.png b/app/assets/images/emoji/post_office.png
deleted file mode 100644
index a23848f9aa0..00000000000
--- a/app/assets/images/emoji/post_office.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/postal_horn.png b/app/assets/images/emoji/postal_horn.png
deleted file mode 100644
index c173b8dbd67..00000000000
--- a/app/assets/images/emoji/postal_horn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/postbox.png b/app/assets/images/emoji/postbox.png
deleted file mode 100644
index 07c9c4ab3d6..00000000000
--- a/app/assets/images/emoji/postbox.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/potable_water.png b/app/assets/images/emoji/potable_water.png
deleted file mode 100644
index 2c610049459..00000000000
--- a/app/assets/images/emoji/potable_water.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/potato.png b/app/assets/images/emoji/potato.png
deleted file mode 100644
index 70350ca2c0a..00000000000
--- a/app/assets/images/emoji/potato.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pouch.png b/app/assets/images/emoji/pouch.png
deleted file mode 100644
index 8795c6c66ff..00000000000
--- a/app/assets/images/emoji/pouch.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/poultry_leg.png b/app/assets/images/emoji/poultry_leg.png
deleted file mode 100644
index eea4a53a2f9..00000000000
--- a/app/assets/images/emoji/poultry_leg.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pound.png b/app/assets/images/emoji/pound.png
deleted file mode 100644
index a0d4c4099e9..00000000000
--- a/app/assets/images/emoji/pound.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pouting_cat.png b/app/assets/images/emoji/pouting_cat.png
deleted file mode 100644
index 41ddfeab42b..00000000000
--- a/app/assets/images/emoji/pouting_cat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pray.png b/app/assets/images/emoji/pray.png
deleted file mode 100644
index 8347f2435be..00000000000
--- a/app/assets/images/emoji/pray.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pray_tone1.png b/app/assets/images/emoji/pray_tone1.png
deleted file mode 100644
index 060ef257172..00000000000
--- a/app/assets/images/emoji/pray_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pray_tone2.png b/app/assets/images/emoji/pray_tone2.png
deleted file mode 100644
index 56dc607c07a..00000000000
--- a/app/assets/images/emoji/pray_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pray_tone3.png b/app/assets/images/emoji/pray_tone3.png
deleted file mode 100644
index 0f33b862008..00000000000
--- a/app/assets/images/emoji/pray_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pray_tone4.png b/app/assets/images/emoji/pray_tone4.png
deleted file mode 100644
index 2ea8dc11657..00000000000
--- a/app/assets/images/emoji/pray_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pray_tone5.png b/app/assets/images/emoji/pray_tone5.png
deleted file mode 100644
index 2128a6c4703..00000000000
--- a/app/assets/images/emoji/pray_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/prayer_beads.png b/app/assets/images/emoji/prayer_beads.png
deleted file mode 100644
index a4b6dfcc62e..00000000000
--- a/app/assets/images/emoji/prayer_beads.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pregnant_woman.png b/app/assets/images/emoji/pregnant_woman.png
deleted file mode 100644
index 084e83a414a..00000000000
--- a/app/assets/images/emoji/pregnant_woman.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pregnant_woman_tone1.png b/app/assets/images/emoji/pregnant_woman_tone1.png
deleted file mode 100644
index a78703b33aa..00000000000
--- a/app/assets/images/emoji/pregnant_woman_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pregnant_woman_tone2.png b/app/assets/images/emoji/pregnant_woman_tone2.png
deleted file mode 100644
index 0068c6c4a77..00000000000
--- a/app/assets/images/emoji/pregnant_woman_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pregnant_woman_tone3.png b/app/assets/images/emoji/pregnant_woman_tone3.png
deleted file mode 100644
index 3206296b684..00000000000
--- a/app/assets/images/emoji/pregnant_woman_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pregnant_woman_tone4.png b/app/assets/images/emoji/pregnant_woman_tone4.png
deleted file mode 100644
index 120fda5cd8c..00000000000
--- a/app/assets/images/emoji/pregnant_woman_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pregnant_woman_tone5.png b/app/assets/images/emoji/pregnant_woman_tone5.png
deleted file mode 100644
index 569bfdf05ce..00000000000
--- a/app/assets/images/emoji/pregnant_woman_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/prince.png b/app/assets/images/emoji/prince.png
deleted file mode 100644
index 38d69344c84..00000000000
--- a/app/assets/images/emoji/prince.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/prince_tone1.png b/app/assets/images/emoji/prince_tone1.png
deleted file mode 100644
index 849930c8887..00000000000
--- a/app/assets/images/emoji/prince_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/prince_tone2.png b/app/assets/images/emoji/prince_tone2.png
deleted file mode 100644
index 23d8b3b1285..00000000000
--- a/app/assets/images/emoji/prince_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/prince_tone3.png b/app/assets/images/emoji/prince_tone3.png
deleted file mode 100644
index db6dfff0647..00000000000
--- a/app/assets/images/emoji/prince_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/prince_tone4.png b/app/assets/images/emoji/prince_tone4.png
deleted file mode 100644
index 8e10f8be6a8..00000000000
--- a/app/assets/images/emoji/prince_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/prince_tone5.png b/app/assets/images/emoji/prince_tone5.png
deleted file mode 100644
index 138d4ea7048..00000000000
--- a/app/assets/images/emoji/prince_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/princess.png b/app/assets/images/emoji/princess.png
deleted file mode 100644
index 879e9fa8c5d..00000000000
--- a/app/assets/images/emoji/princess.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/princess_tone1.png b/app/assets/images/emoji/princess_tone1.png
deleted file mode 100644
index c28078cdc36..00000000000
--- a/app/assets/images/emoji/princess_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/princess_tone2.png b/app/assets/images/emoji/princess_tone2.png
deleted file mode 100644
index dcd20e6ecd4..00000000000
--- a/app/assets/images/emoji/princess_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/princess_tone3.png b/app/assets/images/emoji/princess_tone3.png
deleted file mode 100644
index cde6f315c56..00000000000
--- a/app/assets/images/emoji/princess_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/princess_tone4.png b/app/assets/images/emoji/princess_tone4.png
deleted file mode 100644
index c71e69caaef..00000000000
--- a/app/assets/images/emoji/princess_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/princess_tone5.png b/app/assets/images/emoji/princess_tone5.png
deleted file mode 100644
index 063e2645910..00000000000
--- a/app/assets/images/emoji/princess_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/printer.png b/app/assets/images/emoji/printer.png
deleted file mode 100644
index 027c830f0fe..00000000000
--- a/app/assets/images/emoji/printer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/projector.png b/app/assets/images/emoji/projector.png
deleted file mode 100644
index ce9ab0daa28..00000000000
--- a/app/assets/images/emoji/projector.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/punch.png b/app/assets/images/emoji/punch.png
deleted file mode 100644
index b14ca5f5211..00000000000
--- a/app/assets/images/emoji/punch.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/punch_tone1.png b/app/assets/images/emoji/punch_tone1.png
deleted file mode 100644
index 93c7d17fb47..00000000000
--- a/app/assets/images/emoji/punch_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/punch_tone2.png b/app/assets/images/emoji/punch_tone2.png
deleted file mode 100644
index c0a1af6e10a..00000000000
--- a/app/assets/images/emoji/punch_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/punch_tone3.png b/app/assets/images/emoji/punch_tone3.png
deleted file mode 100644
index 1458b021201..00000000000
--- a/app/assets/images/emoji/punch_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/punch_tone4.png b/app/assets/images/emoji/punch_tone4.png
deleted file mode 100644
index c1466bfcdef..00000000000
--- a/app/assets/images/emoji/punch_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/punch_tone5.png b/app/assets/images/emoji/punch_tone5.png
deleted file mode 100644
index 00b4ddb8953..00000000000
--- a/app/assets/images/emoji/punch_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/purple_heart.png b/app/assets/images/emoji/purple_heart.png
deleted file mode 100644
index 95c53a9ade6..00000000000
--- a/app/assets/images/emoji/purple_heart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/purse.png b/app/assets/images/emoji/purse.png
deleted file mode 100644
index 981346193c5..00000000000
--- a/app/assets/images/emoji/purse.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/pushpin.png b/app/assets/images/emoji/pushpin.png
deleted file mode 100644
index 57e07d7f4cc..00000000000
--- a/app/assets/images/emoji/pushpin.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/put_litter_in_its_place.png b/app/assets/images/emoji/put_litter_in_its_place.png
deleted file mode 100644
index 82a84f9a375..00000000000
--- a/app/assets/images/emoji/put_litter_in_its_place.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/question.png b/app/assets/images/emoji/question.png
deleted file mode 100644
index 5a58f3458aa..00000000000
--- a/app/assets/images/emoji/question.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rabbit.png b/app/assets/images/emoji/rabbit.png
deleted file mode 100644
index ea75ab0426e..00000000000
--- a/app/assets/images/emoji/rabbit.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rabbit2.png b/app/assets/images/emoji/rabbit2.png
deleted file mode 100644
index 2c8a29c642f..00000000000
--- a/app/assets/images/emoji/rabbit2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/race_car.png b/app/assets/images/emoji/race_car.png
deleted file mode 100644
index fe3f045f446..00000000000
--- a/app/assets/images/emoji/race_car.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/racehorse.png b/app/assets/images/emoji/racehorse.png
deleted file mode 100644
index b3e73cc8903..00000000000
--- a/app/assets/images/emoji/racehorse.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/radio.png b/app/assets/images/emoji/radio.png
deleted file mode 100644
index dec381fa242..00000000000
--- a/app/assets/images/emoji/radio.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/radio_button.png b/app/assets/images/emoji/radio_button.png
deleted file mode 100644
index 3a23449d917..00000000000
--- a/app/assets/images/emoji/radio_button.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/radioactive.png b/app/assets/images/emoji/radioactive.png
deleted file mode 100644
index 3b46199fe37..00000000000
--- a/app/assets/images/emoji/radioactive.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rage.png b/app/assets/images/emoji/rage.png
deleted file mode 100644
index 9d739bd40ad..00000000000
--- a/app/assets/images/emoji/rage.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/railway_car.png b/app/assets/images/emoji/railway_car.png
deleted file mode 100644
index a9acbf13008..00000000000
--- a/app/assets/images/emoji/railway_car.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/railway_track.png b/app/assets/images/emoji/railway_track.png
deleted file mode 100644
index e1a7a0d1430..00000000000
--- a/app/assets/images/emoji/railway_track.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rainbow.png b/app/assets/images/emoji/rainbow.png
deleted file mode 100644
index 154735d7147..00000000000
--- a/app/assets/images/emoji/rainbow.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_back_of_hand.png b/app/assets/images/emoji/raised_back_of_hand.png
deleted file mode 100644
index 479234294b4..00000000000
--- a/app/assets/images/emoji/raised_back_of_hand.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_back_of_hand_tone1.png b/app/assets/images/emoji/raised_back_of_hand_tone1.png
deleted file mode 100644
index 813d28499b5..00000000000
--- a/app/assets/images/emoji/raised_back_of_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_back_of_hand_tone2.png b/app/assets/images/emoji/raised_back_of_hand_tone2.png
deleted file mode 100644
index 192ff795e37..00000000000
--- a/app/assets/images/emoji/raised_back_of_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_back_of_hand_tone3.png b/app/assets/images/emoji/raised_back_of_hand_tone3.png
deleted file mode 100644
index 61a727abe6b..00000000000
--- a/app/assets/images/emoji/raised_back_of_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_back_of_hand_tone4.png b/app/assets/images/emoji/raised_back_of_hand_tone4.png
deleted file mode 100644
index 2e83da511f5..00000000000
--- a/app/assets/images/emoji/raised_back_of_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_back_of_hand_tone5.png b/app/assets/images/emoji/raised_back_of_hand_tone5.png
deleted file mode 100644
index d7a5b95a02c..00000000000
--- a/app/assets/images/emoji/raised_back_of_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_hand.png b/app/assets/images/emoji/raised_hand.png
deleted file mode 100644
index 6b2954315d1..00000000000
--- a/app/assets/images/emoji/raised_hand.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_hand_tone1.png b/app/assets/images/emoji/raised_hand_tone1.png
deleted file mode 100644
index 3b752902c07..00000000000
--- a/app/assets/images/emoji/raised_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_hand_tone2.png b/app/assets/images/emoji/raised_hand_tone2.png
deleted file mode 100644
index 44e2a514c60..00000000000
--- a/app/assets/images/emoji/raised_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_hand_tone3.png b/app/assets/images/emoji/raised_hand_tone3.png
deleted file mode 100644
index 5bb62a7528a..00000000000
--- a/app/assets/images/emoji/raised_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_hand_tone4.png b/app/assets/images/emoji/raised_hand_tone4.png
deleted file mode 100644
index c7f8c9ec270..00000000000
--- a/app/assets/images/emoji/raised_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_hand_tone5.png b/app/assets/images/emoji/raised_hand_tone5.png
deleted file mode 100644
index c601b58a73e..00000000000
--- a/app/assets/images/emoji/raised_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_hands.png b/app/assets/images/emoji/raised_hands.png
deleted file mode 100644
index c0155f728e7..00000000000
--- a/app/assets/images/emoji/raised_hands.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_hands_tone1.png b/app/assets/images/emoji/raised_hands_tone1.png
deleted file mode 100644
index 1168b8236b6..00000000000
--- a/app/assets/images/emoji/raised_hands_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_hands_tone2.png b/app/assets/images/emoji/raised_hands_tone2.png
deleted file mode 100644
index 322de622903..00000000000
--- a/app/assets/images/emoji/raised_hands_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_hands_tone3.png b/app/assets/images/emoji/raised_hands_tone3.png
deleted file mode 100644
index 2aa24e05ae1..00000000000
--- a/app/assets/images/emoji/raised_hands_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_hands_tone4.png b/app/assets/images/emoji/raised_hands_tone4.png
deleted file mode 100644
index f31bf0db992..00000000000
--- a/app/assets/images/emoji/raised_hands_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raised_hands_tone5.png b/app/assets/images/emoji/raised_hands_tone5.png
deleted file mode 100644
index 5e95067f98b..00000000000
--- a/app/assets/images/emoji/raised_hands_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raising_hand.png b/app/assets/images/emoji/raising_hand.png
deleted file mode 100644
index 2880708c0cc..00000000000
--- a/app/assets/images/emoji/raising_hand.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raising_hand_tone1.png b/app/assets/images/emoji/raising_hand_tone1.png
deleted file mode 100644
index 1c90e3e2689..00000000000
--- a/app/assets/images/emoji/raising_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raising_hand_tone2.png b/app/assets/images/emoji/raising_hand_tone2.png
deleted file mode 100644
index 82c3ef2bfc5..00000000000
--- a/app/assets/images/emoji/raising_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raising_hand_tone3.png b/app/assets/images/emoji/raising_hand_tone3.png
deleted file mode 100644
index 1b1da2aa0ca..00000000000
--- a/app/assets/images/emoji/raising_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raising_hand_tone4.png b/app/assets/images/emoji/raising_hand_tone4.png
deleted file mode 100644
index e453855c01f..00000000000
--- a/app/assets/images/emoji/raising_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/raising_hand_tone5.png b/app/assets/images/emoji/raising_hand_tone5.png
deleted file mode 100644
index b86200fd844..00000000000
--- a/app/assets/images/emoji/raising_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ram.png b/app/assets/images/emoji/ram.png
deleted file mode 100644
index 52a44464c9b..00000000000
--- a/app/assets/images/emoji/ram.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ramen.png b/app/assets/images/emoji/ramen.png
deleted file mode 100644
index c1cb7cd7384..00000000000
--- a/app/assets/images/emoji/ramen.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rat.png b/app/assets/images/emoji/rat.png
deleted file mode 100644
index 86219144f10..00000000000
--- a/app/assets/images/emoji/rat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/record_button.png b/app/assets/images/emoji/record_button.png
deleted file mode 100644
index ada52830fce..00000000000
--- a/app/assets/images/emoji/record_button.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/recycle.png b/app/assets/images/emoji/recycle.png
deleted file mode 100644
index 9221f095c37..00000000000
--- a/app/assets/images/emoji/recycle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/red_car.png b/app/assets/images/emoji/red_car.png
deleted file mode 100644
index b3e6a774dea..00000000000
--- a/app/assets/images/emoji/red_car.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/red_circle.png b/app/assets/images/emoji/red_circle.png
deleted file mode 100644
index 4bef930d92f..00000000000
--- a/app/assets/images/emoji/red_circle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/registered.png b/app/assets/images/emoji/registered.png
deleted file mode 100644
index 53ef9f2d4e6..00000000000
--- a/app/assets/images/emoji/registered.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/relaxed.png b/app/assets/images/emoji/relaxed.png
deleted file mode 100644
index e9e53c03d45..00000000000
--- a/app/assets/images/emoji/relaxed.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/relieved.png b/app/assets/images/emoji/relieved.png
deleted file mode 100644
index 715ad0bf53f..00000000000
--- a/app/assets/images/emoji/relieved.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/reminder_ribbon.png b/app/assets/images/emoji/reminder_ribbon.png
deleted file mode 100644
index 3988bbd094c..00000000000
--- a/app/assets/images/emoji/reminder_ribbon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/repeat.png b/app/assets/images/emoji/repeat.png
deleted file mode 100644
index 540ce4e0fba..00000000000
--- a/app/assets/images/emoji/repeat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/repeat_one.png b/app/assets/images/emoji/repeat_one.png
deleted file mode 100644
index 9567e83337f..00000000000
--- a/app/assets/images/emoji/repeat_one.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/restroom.png b/app/assets/images/emoji/restroom.png
deleted file mode 100644
index 9588e0f0ef7..00000000000
--- a/app/assets/images/emoji/restroom.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/revolving_hearts.png b/app/assets/images/emoji/revolving_hearts.png
deleted file mode 100644
index 7b9d1948f73..00000000000
--- a/app/assets/images/emoji/revolving_hearts.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rewind.png b/app/assets/images/emoji/rewind.png
deleted file mode 100644
index e22e2bd3da5..00000000000
--- a/app/assets/images/emoji/rewind.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rhino.png b/app/assets/images/emoji/rhino.png
deleted file mode 100644
index 12f4e0d9d9b..00000000000
--- a/app/assets/images/emoji/rhino.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ribbon.png b/app/assets/images/emoji/ribbon.png
deleted file mode 100644
index 0f253c3d8c8..00000000000
--- a/app/assets/images/emoji/ribbon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rice.png b/app/assets/images/emoji/rice.png
deleted file mode 100644
index 6e3ac7956b1..00000000000
--- a/app/assets/images/emoji/rice.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rice_ball.png b/app/assets/images/emoji/rice_ball.png
deleted file mode 100644
index d3d8ee25cb8..00000000000
--- a/app/assets/images/emoji/rice_ball.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rice_cracker.png b/app/assets/images/emoji/rice_cracker.png
deleted file mode 100644
index 7fbd08e4ff9..00000000000
--- a/app/assets/images/emoji/rice_cracker.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rice_scene.png b/app/assets/images/emoji/rice_scene.png
deleted file mode 100644
index 1a28426592a..00000000000
--- a/app/assets/images/emoji/rice_scene.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/right_facing_fist.png b/app/assets/images/emoji/right_facing_fist.png
deleted file mode 100644
index 754ed066d2c..00000000000
--- a/app/assets/images/emoji/right_facing_fist.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/right_facing_fist_tone1.png b/app/assets/images/emoji/right_facing_fist_tone1.png
deleted file mode 100644
index 33ded2f61a6..00000000000
--- a/app/assets/images/emoji/right_facing_fist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/right_facing_fist_tone2.png b/app/assets/images/emoji/right_facing_fist_tone2.png
deleted file mode 100644
index 88054e335c7..00000000000
--- a/app/assets/images/emoji/right_facing_fist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/right_facing_fist_tone3.png b/app/assets/images/emoji/right_facing_fist_tone3.png
deleted file mode 100644
index 84b9f5da7f7..00000000000
--- a/app/assets/images/emoji/right_facing_fist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/right_facing_fist_tone4.png b/app/assets/images/emoji/right_facing_fist_tone4.png
deleted file mode 100644
index e741cfea68b..00000000000
--- a/app/assets/images/emoji/right_facing_fist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/right_facing_fist_tone5.png b/app/assets/images/emoji/right_facing_fist_tone5.png
deleted file mode 100644
index cf66d760c1f..00000000000
--- a/app/assets/images/emoji/right_facing_fist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ring.png b/app/assets/images/emoji/ring.png
deleted file mode 100644
index 87d227adb74..00000000000
--- a/app/assets/images/emoji/ring.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/robot.png b/app/assets/images/emoji/robot.png
deleted file mode 100644
index 7cc62612c6a..00000000000
--- a/app/assets/images/emoji/robot.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rocket.png b/app/assets/images/emoji/rocket.png
deleted file mode 100644
index 0d8da089a37..00000000000
--- a/app/assets/images/emoji/rocket.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rofl.png b/app/assets/images/emoji/rofl.png
deleted file mode 100644
index b1736fedfeb..00000000000
--- a/app/assets/images/emoji/rofl.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/roller_coaster.png b/app/assets/images/emoji/roller_coaster.png
deleted file mode 100644
index 5b849e071e8..00000000000
--- a/app/assets/images/emoji/roller_coaster.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rolling_eyes.png b/app/assets/images/emoji/rolling_eyes.png
deleted file mode 100644
index 2f77b9fc3b9..00000000000
--- a/app/assets/images/emoji/rolling_eyes.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rooster.png b/app/assets/images/emoji/rooster.png
deleted file mode 100644
index bbf2bbff97a..00000000000
--- a/app/assets/images/emoji/rooster.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rose.png b/app/assets/images/emoji/rose.png
deleted file mode 100644
index 52c286d31ce..00000000000
--- a/app/assets/images/emoji/rose.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rosette.png b/app/assets/images/emoji/rosette.png
deleted file mode 100644
index 8030e494bcf..00000000000
--- a/app/assets/images/emoji/rosette.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rotating_light.png b/app/assets/images/emoji/rotating_light.png
deleted file mode 100644
index cad66b0afef..00000000000
--- a/app/assets/images/emoji/rotating_light.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/round_pushpin.png b/app/assets/images/emoji/round_pushpin.png
deleted file mode 100644
index 28b9d72866e..00000000000
--- a/app/assets/images/emoji/round_pushpin.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rowboat.png b/app/assets/images/emoji/rowboat.png
deleted file mode 100644
index dd4dfc095d9..00000000000
--- a/app/assets/images/emoji/rowboat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rowboat_tone1.png b/app/assets/images/emoji/rowboat_tone1.png
deleted file mode 100644
index 5e5d18548cb..00000000000
--- a/app/assets/images/emoji/rowboat_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rowboat_tone2.png b/app/assets/images/emoji/rowboat_tone2.png
deleted file mode 100644
index 9b123ef8871..00000000000
--- a/app/assets/images/emoji/rowboat_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rowboat_tone3.png b/app/assets/images/emoji/rowboat_tone3.png
deleted file mode 100644
index 8ebd89a55f5..00000000000
--- a/app/assets/images/emoji/rowboat_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rowboat_tone4.png b/app/assets/images/emoji/rowboat_tone4.png
deleted file mode 100644
index 2b0d04f8725..00000000000
--- a/app/assets/images/emoji/rowboat_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rowboat_tone5.png b/app/assets/images/emoji/rowboat_tone5.png
deleted file mode 100644
index b346f2dfc84..00000000000
--- a/app/assets/images/emoji/rowboat_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/rugby_football.png b/app/assets/images/emoji/rugby_football.png
deleted file mode 100644
index b1872273436..00000000000
--- a/app/assets/images/emoji/rugby_football.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/runner.png b/app/assets/images/emoji/runner.png
deleted file mode 100644
index e914915976a..00000000000
--- a/app/assets/images/emoji/runner.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/runner_tone1.png b/app/assets/images/emoji/runner_tone1.png
deleted file mode 100644
index 9355239a52d..00000000000
--- a/app/assets/images/emoji/runner_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/runner_tone2.png b/app/assets/images/emoji/runner_tone2.png
deleted file mode 100644
index 6112fd5c376..00000000000
--- a/app/assets/images/emoji/runner_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/runner_tone3.png b/app/assets/images/emoji/runner_tone3.png
deleted file mode 100644
index 625ec708f48..00000000000
--- a/app/assets/images/emoji/runner_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/runner_tone4.png b/app/assets/images/emoji/runner_tone4.png
deleted file mode 100644
index 242f1b56337..00000000000
--- a/app/assets/images/emoji/runner_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/runner_tone5.png b/app/assets/images/emoji/runner_tone5.png
deleted file mode 100644
index 2976c6f019f..00000000000
--- a/app/assets/images/emoji/runner_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/running_shirt_with_sash.png b/app/assets/images/emoji/running_shirt_with_sash.png
deleted file mode 100644
index 6d83c06b803..00000000000
--- a/app/assets/images/emoji/running_shirt_with_sash.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sa.png b/app/assets/images/emoji/sa.png
deleted file mode 100644
index 900f9633247..00000000000
--- a/app/assets/images/emoji/sa.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sagittarius.png b/app/assets/images/emoji/sagittarius.png
deleted file mode 100644
index f8d94ff2923..00000000000
--- a/app/assets/images/emoji/sagittarius.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sailboat.png b/app/assets/images/emoji/sailboat.png
deleted file mode 100644
index 772ef11da5d..00000000000
--- a/app/assets/images/emoji/sailboat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sake.png b/app/assets/images/emoji/sake.png
deleted file mode 100644
index 2933f5672c4..00000000000
--- a/app/assets/images/emoji/sake.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/salad.png b/app/assets/images/emoji/salad.png
deleted file mode 100644
index c89f9341158..00000000000
--- a/app/assets/images/emoji/salad.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sandal.png b/app/assets/images/emoji/sandal.png
deleted file mode 100644
index 9d9f5122b7a..00000000000
--- a/app/assets/images/emoji/sandal.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/santa.png b/app/assets/images/emoji/santa.png
deleted file mode 100644
index bc83ab80d52..00000000000
--- a/app/assets/images/emoji/santa.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/santa_tone1.png b/app/assets/images/emoji/santa_tone1.png
deleted file mode 100644
index 5233ffb7174..00000000000
--- a/app/assets/images/emoji/santa_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/santa_tone2.png b/app/assets/images/emoji/santa_tone2.png
deleted file mode 100644
index 4e845438197..00000000000
--- a/app/assets/images/emoji/santa_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/santa_tone3.png b/app/assets/images/emoji/santa_tone3.png
deleted file mode 100644
index 7fc4f33b60f..00000000000
--- a/app/assets/images/emoji/santa_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/santa_tone4.png b/app/assets/images/emoji/santa_tone4.png
deleted file mode 100644
index d1d5a15132d..00000000000
--- a/app/assets/images/emoji/santa_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/santa_tone5.png b/app/assets/images/emoji/santa_tone5.png
deleted file mode 100644
index 4d697a01f24..00000000000
--- a/app/assets/images/emoji/santa_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/satellite.png b/app/assets/images/emoji/satellite.png
deleted file mode 100644
index db0372795f4..00000000000
--- a/app/assets/images/emoji/satellite.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/satellite_orbital.png b/app/assets/images/emoji/satellite_orbital.png
deleted file mode 100644
index 4ba55d6e297..00000000000
--- a/app/assets/images/emoji/satellite_orbital.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/saxophone.png b/app/assets/images/emoji/saxophone.png
deleted file mode 100644
index a392faec291..00000000000
--- a/app/assets/images/emoji/saxophone.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/scales.png b/app/assets/images/emoji/scales.png
deleted file mode 100644
index 0757eda1684..00000000000
--- a/app/assets/images/emoji/scales.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/school.png b/app/assets/images/emoji/school.png
deleted file mode 100644
index 269759534f0..00000000000
--- a/app/assets/images/emoji/school.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/school_satchel.png b/app/assets/images/emoji/school_satchel.png
deleted file mode 100644
index 9997c86e7dc..00000000000
--- a/app/assets/images/emoji/school_satchel.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/scissors.png b/app/assets/images/emoji/scissors.png
deleted file mode 100644
index 270571c8cdd..00000000000
--- a/app/assets/images/emoji/scissors.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/scooter.png b/app/assets/images/emoji/scooter.png
deleted file mode 100644
index 4ab7ef59cd2..00000000000
--- a/app/assets/images/emoji/scooter.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/scorpion.png b/app/assets/images/emoji/scorpion.png
deleted file mode 100644
index 449a6b281c9..00000000000
--- a/app/assets/images/emoji/scorpion.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/scorpius.png b/app/assets/images/emoji/scorpius.png
deleted file mode 100644
index c31a9920455..00000000000
--- a/app/assets/images/emoji/scorpius.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/scream.png b/app/assets/images/emoji/scream.png
deleted file mode 100644
index c3bea9f2510..00000000000
--- a/app/assets/images/emoji/scream.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/scream_cat.png b/app/assets/images/emoji/scream_cat.png
deleted file mode 100644
index 15803ad8e6e..00000000000
--- a/app/assets/images/emoji/scream_cat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/scroll.png b/app/assets/images/emoji/scroll.png
deleted file mode 100644
index 50ee5dcd4b9..00000000000
--- a/app/assets/images/emoji/scroll.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/seat.png b/app/assets/images/emoji/seat.png
deleted file mode 100644
index a6d72d95adb..00000000000
--- a/app/assets/images/emoji/seat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/second_place.png b/app/assets/images/emoji/second_place.png
deleted file mode 100644
index 17b011268b6..00000000000
--- a/app/assets/images/emoji/second_place.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/secret.png b/app/assets/images/emoji/secret.png
deleted file mode 100644
index 5fd72608e60..00000000000
--- a/app/assets/images/emoji/secret.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/see_no_evil.png b/app/assets/images/emoji/see_no_evil.png
deleted file mode 100644
index 5187e474531..00000000000
--- a/app/assets/images/emoji/see_no_evil.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/seedling.png b/app/assets/images/emoji/seedling.png
deleted file mode 100644
index ae0948bcfd6..00000000000
--- a/app/assets/images/emoji/seedling.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/selfie.png b/app/assets/images/emoji/selfie.png
deleted file mode 100644
index 6a1ba75c7e3..00000000000
--- a/app/assets/images/emoji/selfie.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/selfie_tone1.png b/app/assets/images/emoji/selfie_tone1.png
deleted file mode 100644
index 290e075b56f..00000000000
--- a/app/assets/images/emoji/selfie_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/selfie_tone2.png b/app/assets/images/emoji/selfie_tone2.png
deleted file mode 100644
index fcd9595b643..00000000000
--- a/app/assets/images/emoji/selfie_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/selfie_tone3.png b/app/assets/images/emoji/selfie_tone3.png
deleted file mode 100644
index f3a22fdf435..00000000000
--- a/app/assets/images/emoji/selfie_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/selfie_tone4.png b/app/assets/images/emoji/selfie_tone4.png
deleted file mode 100644
index cdecf6d9f4e..00000000000
--- a/app/assets/images/emoji/selfie_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/selfie_tone5.png b/app/assets/images/emoji/selfie_tone5.png
deleted file mode 100644
index 86acbb6c202..00000000000
--- a/app/assets/images/emoji/selfie_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/seven.png b/app/assets/images/emoji/seven.png
deleted file mode 100644
index 9b3476ae7c7..00000000000
--- a/app/assets/images/emoji/seven.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shallow_pan_of_food.png b/app/assets/images/emoji/shallow_pan_of_food.png
deleted file mode 100644
index 663a1006acd..00000000000
--- a/app/assets/images/emoji/shallow_pan_of_food.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shamrock.png b/app/assets/images/emoji/shamrock.png
deleted file mode 100644
index f202aecfe6f..00000000000
--- a/app/assets/images/emoji/shamrock.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shark.png b/app/assets/images/emoji/shark.png
deleted file mode 100644
index c75076d57d8..00000000000
--- a/app/assets/images/emoji/shark.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shaved_ice.png b/app/assets/images/emoji/shaved_ice.png
deleted file mode 100644
index 36dfb53ca93..00000000000
--- a/app/assets/images/emoji/shaved_ice.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sheep.png b/app/assets/images/emoji/sheep.png
deleted file mode 100644
index 102b8a52b28..00000000000
--- a/app/assets/images/emoji/sheep.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shell.png b/app/assets/images/emoji/shell.png
deleted file mode 100644
index 55721629f62..00000000000
--- a/app/assets/images/emoji/shell.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shield.png b/app/assets/images/emoji/shield.png
deleted file mode 100644
index 610bf033ce0..00000000000
--- a/app/assets/images/emoji/shield.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shinto_shrine.png b/app/assets/images/emoji/shinto_shrine.png
deleted file mode 100644
index 5a344975bf3..00000000000
--- a/app/assets/images/emoji/shinto_shrine.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ship.png b/app/assets/images/emoji/ship.png
deleted file mode 100644
index 62d54f7d6c9..00000000000
--- a/app/assets/images/emoji/ship.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shirt.png b/app/assets/images/emoji/shirt.png
deleted file mode 100644
index af08dec8b59..00000000000
--- a/app/assets/images/emoji/shirt.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shopping_bags.png b/app/assets/images/emoji/shopping_bags.png
deleted file mode 100644
index 99f2a2b13ac..00000000000
--- a/app/assets/images/emoji/shopping_bags.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shopping_cart.png b/app/assets/images/emoji/shopping_cart.png
deleted file mode 100644
index 1086fe6e456..00000000000
--- a/app/assets/images/emoji/shopping_cart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shower.png b/app/assets/images/emoji/shower.png
deleted file mode 100644
index 156776a2e52..00000000000
--- a/app/assets/images/emoji/shower.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shrimp.png b/app/assets/images/emoji/shrimp.png
deleted file mode 100644
index 49eff28a71e..00000000000
--- a/app/assets/images/emoji/shrimp.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shrug.png b/app/assets/images/emoji/shrug.png
deleted file mode 100644
index 76e63bfac77..00000000000
--- a/app/assets/images/emoji/shrug.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shrug_tone1.png b/app/assets/images/emoji/shrug_tone1.png
deleted file mode 100644
index 1c895e64468..00000000000
--- a/app/assets/images/emoji/shrug_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shrug_tone2.png b/app/assets/images/emoji/shrug_tone2.png
deleted file mode 100644
index 4e3ca8f8bac..00000000000
--- a/app/assets/images/emoji/shrug_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shrug_tone3.png b/app/assets/images/emoji/shrug_tone3.png
deleted file mode 100644
index d1b16a19bb5..00000000000
--- a/app/assets/images/emoji/shrug_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shrug_tone4.png b/app/assets/images/emoji/shrug_tone4.png
deleted file mode 100644
index 5fbef3f2255..00000000000
--- a/app/assets/images/emoji/shrug_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/shrug_tone5.png b/app/assets/images/emoji/shrug_tone5.png
deleted file mode 100644
index 4af2e28bc5c..00000000000
--- a/app/assets/images/emoji/shrug_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/signal_strength.png b/app/assets/images/emoji/signal_strength.png
deleted file mode 100644
index ee2b5a4b519..00000000000
--- a/app/assets/images/emoji/signal_strength.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/six.png b/app/assets/images/emoji/six.png
deleted file mode 100644
index 371b3acef2c..00000000000
--- a/app/assets/images/emoji/six.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/six_pointed_star.png b/app/assets/images/emoji/six_pointed_star.png
deleted file mode 100644
index 2eb1707458b..00000000000
--- a/app/assets/images/emoji/six_pointed_star.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ski.png b/app/assets/images/emoji/ski.png
deleted file mode 100644
index 4a2d2c12306..00000000000
--- a/app/assets/images/emoji/ski.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/skier.png b/app/assets/images/emoji/skier.png
deleted file mode 100644
index 2eb3bdce2af..00000000000
--- a/app/assets/images/emoji/skier.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/skull.png b/app/assets/images/emoji/skull.png
deleted file mode 100644
index 26abb17296a..00000000000
--- a/app/assets/images/emoji/skull.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/skull_crossbones.png b/app/assets/images/emoji/skull_crossbones.png
deleted file mode 100644
index b459df9227a..00000000000
--- a/app/assets/images/emoji/skull_crossbones.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sleeping.png b/app/assets/images/emoji/sleeping.png
deleted file mode 100644
index 9ecf600d6d8..00000000000
--- a/app/assets/images/emoji/sleeping.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sleeping_accommodation.png b/app/assets/images/emoji/sleeping_accommodation.png
deleted file mode 100644
index c739e7fb69b..00000000000
--- a/app/assets/images/emoji/sleeping_accommodation.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sleepy.png b/app/assets/images/emoji/sleepy.png
deleted file mode 100644
index 836b4107717..00000000000
--- a/app/assets/images/emoji/sleepy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/slight_frown.png b/app/assets/images/emoji/slight_frown.png
deleted file mode 100644
index b2f1d983d36..00000000000
--- a/app/assets/images/emoji/slight_frown.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/slight_smile.png b/app/assets/images/emoji/slight_smile.png
deleted file mode 100644
index ddd7d65dd3d..00000000000
--- a/app/assets/images/emoji/slight_smile.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/slot_machine.png b/app/assets/images/emoji/slot_machine.png
deleted file mode 100644
index ee71b6c268c..00000000000
--- a/app/assets/images/emoji/slot_machine.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/small_blue_diamond.png b/app/assets/images/emoji/small_blue_diamond.png
deleted file mode 100644
index b86b5bc4db3..00000000000
--- a/app/assets/images/emoji/small_blue_diamond.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/small_orange_diamond.png b/app/assets/images/emoji/small_orange_diamond.png
deleted file mode 100644
index e1c6ed9b2f8..00000000000
--- a/app/assets/images/emoji/small_orange_diamond.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/small_red_triangle.png b/app/assets/images/emoji/small_red_triangle.png
deleted file mode 100644
index 785887c195a..00000000000
--- a/app/assets/images/emoji/small_red_triangle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/small_red_triangle_down.png b/app/assets/images/emoji/small_red_triangle_down.png
deleted file mode 100644
index a83beff1914..00000000000
--- a/app/assets/images/emoji/small_red_triangle_down.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/smile.png b/app/assets/images/emoji/smile.png
deleted file mode 100644
index aa47ffe978c..00000000000
--- a/app/assets/images/emoji/smile.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/smile_cat.png b/app/assets/images/emoji/smile_cat.png
deleted file mode 100644
index 6f25f11dd3a..00000000000
--- a/app/assets/images/emoji/smile_cat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/smiley.png b/app/assets/images/emoji/smiley.png
deleted file mode 100644
index 30957a65968..00000000000
--- a/app/assets/images/emoji/smiley.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/smiley_cat.png b/app/assets/images/emoji/smiley_cat.png
deleted file mode 100644
index 163b57a3427..00000000000
--- a/app/assets/images/emoji/smiley_cat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/smiling_imp.png b/app/assets/images/emoji/smiling_imp.png
deleted file mode 100644
index cc2c5f1ec72..00000000000
--- a/app/assets/images/emoji/smiling_imp.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/smirk.png b/app/assets/images/emoji/smirk.png
deleted file mode 100644
index 87852109988..00000000000
--- a/app/assets/images/emoji/smirk.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/smirk_cat.png b/app/assets/images/emoji/smirk_cat.png
deleted file mode 100644
index 9ac5954c199..00000000000
--- a/app/assets/images/emoji/smirk_cat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/smoking.png b/app/assets/images/emoji/smoking.png
deleted file mode 100644
index 910f648c8f9..00000000000
--- a/app/assets/images/emoji/smoking.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/snail.png b/app/assets/images/emoji/snail.png
deleted file mode 100644
index f4ea071e2d3..00000000000
--- a/app/assets/images/emoji/snail.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/snake.png b/app/assets/images/emoji/snake.png
deleted file mode 100644
index d0278a28d8c..00000000000
--- a/app/assets/images/emoji/snake.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sneezing_face.png b/app/assets/images/emoji/sneezing_face.png
deleted file mode 100644
index ccf07d4b64d..00000000000
--- a/app/assets/images/emoji/sneezing_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/snowboarder.png b/app/assets/images/emoji/snowboarder.png
deleted file mode 100644
index 6361c0f2c9d..00000000000
--- a/app/assets/images/emoji/snowboarder.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/snowflake.png b/app/assets/images/emoji/snowflake.png
deleted file mode 100644
index db319a77ec6..00000000000
--- a/app/assets/images/emoji/snowflake.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/snowman.png b/app/assets/images/emoji/snowman.png
deleted file mode 100644
index 20c177c2aff..00000000000
--- a/app/assets/images/emoji/snowman.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/snowman2.png b/app/assets/images/emoji/snowman2.png
deleted file mode 100644
index 896f28502af..00000000000
--- a/app/assets/images/emoji/snowman2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sob.png b/app/assets/images/emoji/sob.png
deleted file mode 100644
index 52e3517a1ee..00000000000
--- a/app/assets/images/emoji/sob.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/soccer.png b/app/assets/images/emoji/soccer.png
deleted file mode 100644
index 28cfa218d6d..00000000000
--- a/app/assets/images/emoji/soccer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/soon.png b/app/assets/images/emoji/soon.png
deleted file mode 100644
index 8cdfd86690d..00000000000
--- a/app/assets/images/emoji/soon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sos.png b/app/assets/images/emoji/sos.png
deleted file mode 100644
index d7d8c9953e4..00000000000
--- a/app/assets/images/emoji/sos.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sound.png b/app/assets/images/emoji/sound.png
deleted file mode 100644
index e75ddca53ba..00000000000
--- a/app/assets/images/emoji/sound.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/space_invader.png b/app/assets/images/emoji/space_invader.png
deleted file mode 100644
index 2e73f5f32e5..00000000000
--- a/app/assets/images/emoji/space_invader.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/spades.png b/app/assets/images/emoji/spades.png
deleted file mode 100644
index f822f184cb0..00000000000
--- a/app/assets/images/emoji/spades.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/spaghetti.png b/app/assets/images/emoji/spaghetti.png
deleted file mode 100644
index 89c24a321f1..00000000000
--- a/app/assets/images/emoji/spaghetti.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sparkle.png b/app/assets/images/emoji/sparkle.png
deleted file mode 100644
index 6aa7b6ec9cf..00000000000
--- a/app/assets/images/emoji/sparkle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sparkler.png b/app/assets/images/emoji/sparkler.png
deleted file mode 100644
index 30339cd6e09..00000000000
--- a/app/assets/images/emoji/sparkler.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sparkles.png b/app/assets/images/emoji/sparkles.png
deleted file mode 100644
index 169bc10b023..00000000000
--- a/app/assets/images/emoji/sparkles.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sparkling_heart.png b/app/assets/images/emoji/sparkling_heart.png
deleted file mode 100644
index 6709269454e..00000000000
--- a/app/assets/images/emoji/sparkling_heart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/speak_no_evil.png b/app/assets/images/emoji/speak_no_evil.png
deleted file mode 100644
index 9d9e07c974b..00000000000
--- a/app/assets/images/emoji/speak_no_evil.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/speaker.png b/app/assets/images/emoji/speaker.png
deleted file mode 100644
index 7bcffb8fc43..00000000000
--- a/app/assets/images/emoji/speaker.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/speaking_head.png b/app/assets/images/emoji/speaking_head.png
deleted file mode 100644
index 2df93aaae09..00000000000
--- a/app/assets/images/emoji/speaking_head.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/speech_balloon.png b/app/assets/images/emoji/speech_balloon.png
deleted file mode 100644
index a34ef741733..00000000000
--- a/app/assets/images/emoji/speech_balloon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/speech_left.png b/app/assets/images/emoji/speech_left.png
deleted file mode 100644
index 00c05959bcd..00000000000
--- a/app/assets/images/emoji/speech_left.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/speedboat.png b/app/assets/images/emoji/speedboat.png
deleted file mode 100644
index 74059d12de1..00000000000
--- a/app/assets/images/emoji/speedboat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/spider.png b/app/assets/images/emoji/spider.png
deleted file mode 100644
index 3849fa90b94..00000000000
--- a/app/assets/images/emoji/spider.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/spider_web.png b/app/assets/images/emoji/spider_web.png
deleted file mode 100644
index ba448ee7fba..00000000000
--- a/app/assets/images/emoji/spider_web.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/spoon.png b/app/assets/images/emoji/spoon.png
deleted file mode 100644
index 3c4da766aee..00000000000
--- a/app/assets/images/emoji/spoon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/spy.png b/app/assets/images/emoji/spy.png
deleted file mode 100644
index a729e9584d6..00000000000
--- a/app/assets/images/emoji/spy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/spy_tone1.png b/app/assets/images/emoji/spy_tone1.png
deleted file mode 100644
index 2d1c022caee..00000000000
--- a/app/assets/images/emoji/spy_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/spy_tone2.png b/app/assets/images/emoji/spy_tone2.png
deleted file mode 100644
index 548b9c26f5d..00000000000
--- a/app/assets/images/emoji/spy_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/spy_tone3.png b/app/assets/images/emoji/spy_tone3.png
deleted file mode 100644
index b023f4b18e1..00000000000
--- a/app/assets/images/emoji/spy_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/spy_tone4.png b/app/assets/images/emoji/spy_tone4.png
deleted file mode 100644
index d8300af492d..00000000000
--- a/app/assets/images/emoji/spy_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/spy_tone5.png b/app/assets/images/emoji/spy_tone5.png
deleted file mode 100644
index ca1462595fa..00000000000
--- a/app/assets/images/emoji/spy_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/squid.png b/app/assets/images/emoji/squid.png
deleted file mode 100644
index d2af223f0cb..00000000000
--- a/app/assets/images/emoji/squid.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/stadium.png b/app/assets/images/emoji/stadium.png
deleted file mode 100644
index 00cd6db5e29..00000000000
--- a/app/assets/images/emoji/stadium.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/star.png b/app/assets/images/emoji/star.png
deleted file mode 100644
index c930947076e..00000000000
--- a/app/assets/images/emoji/star.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/star2.png b/app/assets/images/emoji/star2.png
deleted file mode 100644
index 2f5cba592db..00000000000
--- a/app/assets/images/emoji/star2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/star_and_crescent.png b/app/assets/images/emoji/star_and_crescent.png
deleted file mode 100644
index e182636457d..00000000000
--- a/app/assets/images/emoji/star_and_crescent.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/star_of_david.png b/app/assets/images/emoji/star_of_david.png
deleted file mode 100644
index fc59d0dde24..00000000000
--- a/app/assets/images/emoji/star_of_david.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/stars.png b/app/assets/images/emoji/stars.png
deleted file mode 100644
index aa45384d1c6..00000000000
--- a/app/assets/images/emoji/stars.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/station.png b/app/assets/images/emoji/station.png
deleted file mode 100644
index 5c26fee529c..00000000000
--- a/app/assets/images/emoji/station.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/statue_of_liberty.png b/app/assets/images/emoji/statue_of_liberty.png
deleted file mode 100644
index 05df8289b59..00000000000
--- a/app/assets/images/emoji/statue_of_liberty.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/steam_locomotive.png b/app/assets/images/emoji/steam_locomotive.png
deleted file mode 100644
index 9ac0d999c4c..00000000000
--- a/app/assets/images/emoji/steam_locomotive.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/stew.png b/app/assets/images/emoji/stew.png
deleted file mode 100644
index 6b3f010c17a..00000000000
--- a/app/assets/images/emoji/stew.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/stop_button.png b/app/assets/images/emoji/stop_button.png
deleted file mode 100644
index cfa99988ac2..00000000000
--- a/app/assets/images/emoji/stop_button.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/stopwatch.png b/app/assets/images/emoji/stopwatch.png
deleted file mode 100644
index 8fae1c9a898..00000000000
--- a/app/assets/images/emoji/stopwatch.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/straight_ruler.png b/app/assets/images/emoji/straight_ruler.png
deleted file mode 100644
index 1017b7433a1..00000000000
--- a/app/assets/images/emoji/straight_ruler.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/strawberry.png b/app/assets/images/emoji/strawberry.png
deleted file mode 100644
index 7bb86f0b29c..00000000000
--- a/app/assets/images/emoji/strawberry.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/stuck_out_tongue.png b/app/assets/images/emoji/stuck_out_tongue.png
deleted file mode 100644
index 25757341f96..00000000000
--- a/app/assets/images/emoji/stuck_out_tongue.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/stuck_out_tongue_closed_eyes.png b/app/assets/images/emoji/stuck_out_tongue_closed_eyes.png
deleted file mode 100644
index 5c0401e9b1d..00000000000
--- a/app/assets/images/emoji/stuck_out_tongue_closed_eyes.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/stuck_out_tongue_winking_eye.png b/app/assets/images/emoji/stuck_out_tongue_winking_eye.png
deleted file mode 100644
index 4817eaa3dc6..00000000000
--- a/app/assets/images/emoji/stuck_out_tongue_winking_eye.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/stuffed_flatbread.png b/app/assets/images/emoji/stuffed_flatbread.png
deleted file mode 100644
index a2e10df40a5..00000000000
--- a/app/assets/images/emoji/stuffed_flatbread.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sun_with_face.png b/app/assets/images/emoji/sun_with_face.png
deleted file mode 100644
index 14a4ea971db..00000000000
--- a/app/assets/images/emoji/sun_with_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sunflower.png b/app/assets/images/emoji/sunflower.png
deleted file mode 100644
index 08cc07761ea..00000000000
--- a/app/assets/images/emoji/sunflower.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sunglasses.png b/app/assets/images/emoji/sunglasses.png
deleted file mode 100644
index 20011735110..00000000000
--- a/app/assets/images/emoji/sunglasses.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sunny.png b/app/assets/images/emoji/sunny.png
deleted file mode 100644
index fd521ae31a7..00000000000
--- a/app/assets/images/emoji/sunny.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sunrise.png b/app/assets/images/emoji/sunrise.png
deleted file mode 100644
index 4ad36003c20..00000000000
--- a/app/assets/images/emoji/sunrise.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sunrise_over_mountains.png b/app/assets/images/emoji/sunrise_over_mountains.png
deleted file mode 100644
index 2b99307344d..00000000000
--- a/app/assets/images/emoji/sunrise_over_mountains.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/surfer.png b/app/assets/images/emoji/surfer.png
deleted file mode 100644
index 3ab017adf4b..00000000000
--- a/app/assets/images/emoji/surfer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/surfer_tone1.png b/app/assets/images/emoji/surfer_tone1.png
deleted file mode 100644
index b5faaa524cc..00000000000
--- a/app/assets/images/emoji/surfer_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/surfer_tone2.png b/app/assets/images/emoji/surfer_tone2.png
deleted file mode 100644
index 6d92e412ff1..00000000000
--- a/app/assets/images/emoji/surfer_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/surfer_tone3.png b/app/assets/images/emoji/surfer_tone3.png
deleted file mode 100644
index f05ef59496e..00000000000
--- a/app/assets/images/emoji/surfer_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/surfer_tone4.png b/app/assets/images/emoji/surfer_tone4.png
deleted file mode 100644
index 35e143d19dc..00000000000
--- a/app/assets/images/emoji/surfer_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/surfer_tone5.png b/app/assets/images/emoji/surfer_tone5.png
deleted file mode 100644
index 38917658eac..00000000000
--- a/app/assets/images/emoji/surfer_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sushi.png b/app/assets/images/emoji/sushi.png
deleted file mode 100644
index f171fd2f7a1..00000000000
--- a/app/assets/images/emoji/sushi.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/suspension_railway.png b/app/assets/images/emoji/suspension_railway.png
deleted file mode 100644
index a59d5f48c24..00000000000
--- a/app/assets/images/emoji/suspension_railway.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sweat.png b/app/assets/images/emoji/sweat.png
deleted file mode 100644
index f0dae7b7893..00000000000
--- a/app/assets/images/emoji/sweat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sweat_drops.png b/app/assets/images/emoji/sweat_drops.png
deleted file mode 100644
index 4106117ebc8..00000000000
--- a/app/assets/images/emoji/sweat_drops.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sweat_smile.png b/app/assets/images/emoji/sweat_smile.png
deleted file mode 100644
index cb18d9c899b..00000000000
--- a/app/assets/images/emoji/sweat_smile.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/sweet_potato.png b/app/assets/images/emoji/sweet_potato.png
deleted file mode 100644
index 92a425f2e20..00000000000
--- a/app/assets/images/emoji/sweet_potato.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/swimmer.png b/app/assets/images/emoji/swimmer.png
deleted file mode 100644
index 55b4d72f9a7..00000000000
--- a/app/assets/images/emoji/swimmer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/swimmer_tone1.png b/app/assets/images/emoji/swimmer_tone1.png
deleted file mode 100644
index 38441c9ca9a..00000000000
--- a/app/assets/images/emoji/swimmer_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/swimmer_tone2.png b/app/assets/images/emoji/swimmer_tone2.png
deleted file mode 100644
index b0d43112444..00000000000
--- a/app/assets/images/emoji/swimmer_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/swimmer_tone3.png b/app/assets/images/emoji/swimmer_tone3.png
deleted file mode 100644
index 211e77e2aa0..00000000000
--- a/app/assets/images/emoji/swimmer_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/swimmer_tone4.png b/app/assets/images/emoji/swimmer_tone4.png
deleted file mode 100644
index f34c34db9d2..00000000000
--- a/app/assets/images/emoji/swimmer_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/swimmer_tone5.png b/app/assets/images/emoji/swimmer_tone5.png
deleted file mode 100644
index 3e9231ff868..00000000000
--- a/app/assets/images/emoji/swimmer_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/symbols.png b/app/assets/images/emoji/symbols.png
deleted file mode 100644
index ac2fc1f358f..00000000000
--- a/app/assets/images/emoji/symbols.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/synagogue.png b/app/assets/images/emoji/synagogue.png
deleted file mode 100644
index ee347904c80..00000000000
--- a/app/assets/images/emoji/synagogue.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/syringe.png b/app/assets/images/emoji/syringe.png
deleted file mode 100644
index 71c1a9528d5..00000000000
--- a/app/assets/images/emoji/syringe.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/taco.png b/app/assets/images/emoji/taco.png
deleted file mode 100644
index 10e847a4619..00000000000
--- a/app/assets/images/emoji/taco.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tada.png b/app/assets/images/emoji/tada.png
deleted file mode 100644
index 0244d60f269..00000000000
--- a/app/assets/images/emoji/tada.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tanabata_tree.png b/app/assets/images/emoji/tanabata_tree.png
deleted file mode 100644
index 46fcb3a1aac..00000000000
--- a/app/assets/images/emoji/tanabata_tree.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tangerine.png b/app/assets/images/emoji/tangerine.png
deleted file mode 100644
index ab14e5378db..00000000000
--- a/app/assets/images/emoji/tangerine.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/taurus.png b/app/assets/images/emoji/taurus.png
deleted file mode 100644
index b2a370df42b..00000000000
--- a/app/assets/images/emoji/taurus.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/taxi.png b/app/assets/images/emoji/taxi.png
deleted file mode 100644
index 55f4cc84797..00000000000
--- a/app/assets/images/emoji/taxi.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tea.png b/app/assets/images/emoji/tea.png
deleted file mode 100644
index b53b98f0c45..00000000000
--- a/app/assets/images/emoji/tea.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/telephone.png b/app/assets/images/emoji/telephone.png
deleted file mode 100644
index a1e69f566bc..00000000000
--- a/app/assets/images/emoji/telephone.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/telephone_receiver.png b/app/assets/images/emoji/telephone_receiver.png
deleted file mode 100644
index 69388316c35..00000000000
--- a/app/assets/images/emoji/telephone_receiver.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/telescope.png b/app/assets/images/emoji/telescope.png
deleted file mode 100644
index d63154614b5..00000000000
--- a/app/assets/images/emoji/telescope.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ten.png b/app/assets/images/emoji/ten.png
deleted file mode 100644
index 782d4004962..00000000000
--- a/app/assets/images/emoji/ten.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tennis.png b/app/assets/images/emoji/tennis.png
deleted file mode 100644
index 7e68ba8f301..00000000000
--- a/app/assets/images/emoji/tennis.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tent.png b/app/assets/images/emoji/tent.png
deleted file mode 100644
index 3fddcfc56eb..00000000000
--- a/app/assets/images/emoji/tent.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thermometer.png b/app/assets/images/emoji/thermometer.png
deleted file mode 100644
index b1147392426..00000000000
--- a/app/assets/images/emoji/thermometer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thermometer_face.png b/app/assets/images/emoji/thermometer_face.png
deleted file mode 100644
index 8fc57387563..00000000000
--- a/app/assets/images/emoji/thermometer_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thinking.png b/app/assets/images/emoji/thinking.png
deleted file mode 100644
index c18f6fd14ad..00000000000
--- a/app/assets/images/emoji/thinking.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/third_place.png b/app/assets/images/emoji/third_place.png
deleted file mode 100644
index 636e04a5950..00000000000
--- a/app/assets/images/emoji/third_place.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thought_balloon.png b/app/assets/images/emoji/thought_balloon.png
deleted file mode 100644
index 72fe8fa7022..00000000000
--- a/app/assets/images/emoji/thought_balloon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/three.png b/app/assets/images/emoji/three.png
deleted file mode 100644
index dbaa6183e72..00000000000
--- a/app/assets/images/emoji/three.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thumbsdown.png b/app/assets/images/emoji/thumbsdown.png
deleted file mode 100644
index b63da2f20a8..00000000000
--- a/app/assets/images/emoji/thumbsdown.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thumbsdown_tone1.png b/app/assets/images/emoji/thumbsdown_tone1.png
deleted file mode 100644
index a1631af8e92..00000000000
--- a/app/assets/images/emoji/thumbsdown_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thumbsdown_tone2.png b/app/assets/images/emoji/thumbsdown_tone2.png
deleted file mode 100644
index 85fff82d595..00000000000
--- a/app/assets/images/emoji/thumbsdown_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thumbsdown_tone3.png b/app/assets/images/emoji/thumbsdown_tone3.png
deleted file mode 100644
index eeba3be80fd..00000000000
--- a/app/assets/images/emoji/thumbsdown_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thumbsdown_tone4.png b/app/assets/images/emoji/thumbsdown_tone4.png
deleted file mode 100644
index 1addafdaed0..00000000000
--- a/app/assets/images/emoji/thumbsdown_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thumbsdown_tone5.png b/app/assets/images/emoji/thumbsdown_tone5.png
deleted file mode 100644
index 37ec07b5721..00000000000
--- a/app/assets/images/emoji/thumbsdown_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thumbsup.png b/app/assets/images/emoji/thumbsup.png
deleted file mode 100644
index f9e6f13a34f..00000000000
--- a/app/assets/images/emoji/thumbsup.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thumbsup_tone1.png b/app/assets/images/emoji/thumbsup_tone1.png
deleted file mode 100644
index 39684cd5cc7..00000000000
--- a/app/assets/images/emoji/thumbsup_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thumbsup_tone2.png b/app/assets/images/emoji/thumbsup_tone2.png
deleted file mode 100644
index a9b59723573..00000000000
--- a/app/assets/images/emoji/thumbsup_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thumbsup_tone3.png b/app/assets/images/emoji/thumbsup_tone3.png
deleted file mode 100644
index c5e29167015..00000000000
--- a/app/assets/images/emoji/thumbsup_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thumbsup_tone4.png b/app/assets/images/emoji/thumbsup_tone4.png
deleted file mode 100644
index 5bf4857a884..00000000000
--- a/app/assets/images/emoji/thumbsup_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thumbsup_tone5.png b/app/assets/images/emoji/thumbsup_tone5.png
deleted file mode 100644
index d829f787c61..00000000000
--- a/app/assets/images/emoji/thumbsup_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/thunder_cloud_rain.png b/app/assets/images/emoji/thunder_cloud_rain.png
deleted file mode 100644
index 31a26a1b6ee..00000000000
--- a/app/assets/images/emoji/thunder_cloud_rain.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/ticket.png b/app/assets/images/emoji/ticket.png
deleted file mode 100644
index 605936bb6b3..00000000000
--- a/app/assets/images/emoji/ticket.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tickets.png b/app/assets/images/emoji/tickets.png
deleted file mode 100644
index e510f4a7a50..00000000000
--- a/app/assets/images/emoji/tickets.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tiger.png b/app/assets/images/emoji/tiger.png
deleted file mode 100644
index a4d3ef086d4..00000000000
--- a/app/assets/images/emoji/tiger.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tiger2.png b/app/assets/images/emoji/tiger2.png
deleted file mode 100644
index 871a8b74d56..00000000000
--- a/app/assets/images/emoji/tiger2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/timer.png b/app/assets/images/emoji/timer.png
deleted file mode 100644
index 8a3be574c24..00000000000
--- a/app/assets/images/emoji/timer.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tired_face.png b/app/assets/images/emoji/tired_face.png
deleted file mode 100644
index 4e01eff5b23..00000000000
--- a/app/assets/images/emoji/tired_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tm.png b/app/assets/images/emoji/tm.png
deleted file mode 100644
index 7a0c44a2c2b..00000000000
--- a/app/assets/images/emoji/tm.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/toilet.png b/app/assets/images/emoji/toilet.png
deleted file mode 100644
index 1392f761835..00000000000
--- a/app/assets/images/emoji/toilet.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tokyo_tower.png b/app/assets/images/emoji/tokyo_tower.png
deleted file mode 100644
index 37df7fc65b1..00000000000
--- a/app/assets/images/emoji/tokyo_tower.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tomato.png b/app/assets/images/emoji/tomato.png
deleted file mode 100644
index 497da8f6b22..00000000000
--- a/app/assets/images/emoji/tomato.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tone1.png b/app/assets/images/emoji/tone1.png
deleted file mode 100644
index c395f3d0d68..00000000000
--- a/app/assets/images/emoji/tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tone2.png b/app/assets/images/emoji/tone2.png
deleted file mode 100644
index 080847431c1..00000000000
--- a/app/assets/images/emoji/tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tone3.png b/app/assets/images/emoji/tone3.png
deleted file mode 100644
index 482dd403475..00000000000
--- a/app/assets/images/emoji/tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tone4.png b/app/assets/images/emoji/tone4.png
deleted file mode 100644
index 5cae8bb20b0..00000000000
--- a/app/assets/images/emoji/tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tone5.png b/app/assets/images/emoji/tone5.png
deleted file mode 100644
index 49d1a8c3a64..00000000000
--- a/app/assets/images/emoji/tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tongue.png b/app/assets/images/emoji/tongue.png
deleted file mode 100644
index 70ce9c1225f..00000000000
--- a/app/assets/images/emoji/tongue.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tools.png b/app/assets/images/emoji/tools.png
deleted file mode 100644
index 3c6049273a9..00000000000
--- a/app/assets/images/emoji/tools.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/top.png b/app/assets/images/emoji/top.png
deleted file mode 100644
index 49dea8c08b5..00000000000
--- a/app/assets/images/emoji/top.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tophat.png b/app/assets/images/emoji/tophat.png
deleted file mode 100644
index 131b657b109..00000000000
--- a/app/assets/images/emoji/tophat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/track_next.png b/app/assets/images/emoji/track_next.png
deleted file mode 100644
index f8880d33bab..00000000000
--- a/app/assets/images/emoji/track_next.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/track_previous.png b/app/assets/images/emoji/track_previous.png
deleted file mode 100644
index 1ffd0566cfc..00000000000
--- a/app/assets/images/emoji/track_previous.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/trackball.png b/app/assets/images/emoji/trackball.png
deleted file mode 100644
index 3bea84ad7ce..00000000000
--- a/app/assets/images/emoji/trackball.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tractor.png b/app/assets/images/emoji/tractor.png
deleted file mode 100644
index c1bf8cae44f..00000000000
--- a/app/assets/images/emoji/tractor.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/traffic_light.png b/app/assets/images/emoji/traffic_light.png
deleted file mode 100644
index 6b312285b00..00000000000
--- a/app/assets/images/emoji/traffic_light.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/train.png b/app/assets/images/emoji/train.png
deleted file mode 100644
index 3c80321f7e8..00000000000
--- a/app/assets/images/emoji/train.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/train2.png b/app/assets/images/emoji/train2.png
deleted file mode 100644
index 367c7bc5d39..00000000000
--- a/app/assets/images/emoji/train2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tram.png b/app/assets/images/emoji/tram.png
deleted file mode 100644
index b6f0e69038f..00000000000
--- a/app/assets/images/emoji/tram.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/triangular_flag_on_post.png b/app/assets/images/emoji/triangular_flag_on_post.png
deleted file mode 100644
index c12d8b06886..00000000000
--- a/app/assets/images/emoji/triangular_flag_on_post.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/triangular_ruler.png b/app/assets/images/emoji/triangular_ruler.png
deleted file mode 100644
index 77dee9ee843..00000000000
--- a/app/assets/images/emoji/triangular_ruler.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/trident.png b/app/assets/images/emoji/trident.png
deleted file mode 100644
index 777a1dad121..00000000000
--- a/app/assets/images/emoji/trident.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/triumph.png b/app/assets/images/emoji/triumph.png
deleted file mode 100644
index 0be7a501969..00000000000
--- a/app/assets/images/emoji/triumph.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/trolleybus.png b/app/assets/images/emoji/trolleybus.png
deleted file mode 100644
index 139a9931b52..00000000000
--- a/app/assets/images/emoji/trolleybus.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/trophy.png b/app/assets/images/emoji/trophy.png
deleted file mode 100644
index ac2895c1896..00000000000
--- a/app/assets/images/emoji/trophy.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tropical_drink.png b/app/assets/images/emoji/tropical_drink.png
deleted file mode 100644
index cd714f81b36..00000000000
--- a/app/assets/images/emoji/tropical_drink.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tropical_fish.png b/app/assets/images/emoji/tropical_fish.png
deleted file mode 100644
index 252105235a6..00000000000
--- a/app/assets/images/emoji/tropical_fish.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/truck.png b/app/assets/images/emoji/truck.png
deleted file mode 100644
index 130de047f8b..00000000000
--- a/app/assets/images/emoji/truck.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/trumpet.png b/app/assets/images/emoji/trumpet.png
deleted file mode 100644
index 864ccbcd04a..00000000000
--- a/app/assets/images/emoji/trumpet.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tulip.png b/app/assets/images/emoji/tulip.png
deleted file mode 100644
index f799d75c182..00000000000
--- a/app/assets/images/emoji/tulip.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tumbler_glass.png b/app/assets/images/emoji/tumbler_glass.png
deleted file mode 100644
index 7bf09229879..00000000000
--- a/app/assets/images/emoji/tumbler_glass.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/turkey.png b/app/assets/images/emoji/turkey.png
deleted file mode 100644
index 344af94c9ec..00000000000
--- a/app/assets/images/emoji/turkey.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/turtle.png b/app/assets/images/emoji/turtle.png
deleted file mode 100644
index c22f7519fe8..00000000000
--- a/app/assets/images/emoji/turtle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/tv.png b/app/assets/images/emoji/tv.png
deleted file mode 100644
index 999f1fb5c6d..00000000000
--- a/app/assets/images/emoji/tv.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/twisted_rightwards_arrows.png b/app/assets/images/emoji/twisted_rightwards_arrows.png
deleted file mode 100644
index 5904badde65..00000000000
--- a/app/assets/images/emoji/twisted_rightwards_arrows.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/two.png b/app/assets/images/emoji/two.png
deleted file mode 100644
index 927339c9bff..00000000000
--- a/app/assets/images/emoji/two.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/two_hearts.png b/app/assets/images/emoji/two_hearts.png
deleted file mode 100644
index 4d8c3386042..00000000000
--- a/app/assets/images/emoji/two_hearts.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/two_men_holding_hands.png b/app/assets/images/emoji/two_men_holding_hands.png
deleted file mode 100644
index a511fda822a..00000000000
--- a/app/assets/images/emoji/two_men_holding_hands.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/two_women_holding_hands.png b/app/assets/images/emoji/two_women_holding_hands.png
deleted file mode 100644
index b077cd3e40f..00000000000
--- a/app/assets/images/emoji/two_women_holding_hands.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/u5272.png b/app/assets/images/emoji/u5272.png
deleted file mode 100644
index c4f837fe684..00000000000
--- a/app/assets/images/emoji/u5272.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/u5408.png b/app/assets/images/emoji/u5408.png
deleted file mode 100644
index 8375ad9d9af..00000000000
--- a/app/assets/images/emoji/u5408.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/u55b6.png b/app/assets/images/emoji/u55b6.png
deleted file mode 100644
index d21cb30eaf3..00000000000
--- a/app/assets/images/emoji/u55b6.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/u6307.png b/app/assets/images/emoji/u6307.png
deleted file mode 100644
index 078e23e4ff3..00000000000
--- a/app/assets/images/emoji/u6307.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/u6708.png b/app/assets/images/emoji/u6708.png
deleted file mode 100644
index c41bd36a26a..00000000000
--- a/app/assets/images/emoji/u6708.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/u6709.png b/app/assets/images/emoji/u6709.png
deleted file mode 100644
index a4510de41c0..00000000000
--- a/app/assets/images/emoji/u6709.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/u6e80.png b/app/assets/images/emoji/u6e80.png
deleted file mode 100644
index f9dea8b8833..00000000000
--- a/app/assets/images/emoji/u6e80.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/u7121.png b/app/assets/images/emoji/u7121.png
deleted file mode 100644
index d3a19b420de..00000000000
--- a/app/assets/images/emoji/u7121.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/u7533.png b/app/assets/images/emoji/u7533.png
deleted file mode 100644
index 6b7af0ee222..00000000000
--- a/app/assets/images/emoji/u7533.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/u7981.png b/app/assets/images/emoji/u7981.png
deleted file mode 100644
index 4c704e03433..00000000000
--- a/app/assets/images/emoji/u7981.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/u7a7a.png b/app/assets/images/emoji/u7a7a.png
deleted file mode 100644
index 47966c1ea93..00000000000
--- a/app/assets/images/emoji/u7a7a.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/umbrella.png b/app/assets/images/emoji/umbrella.png
deleted file mode 100644
index 5b35b7ff6a4..00000000000
--- a/app/assets/images/emoji/umbrella.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/umbrella2.png b/app/assets/images/emoji/umbrella2.png
deleted file mode 100644
index 97fe859e74f..00000000000
--- a/app/assets/images/emoji/umbrella2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/unamused.png b/app/assets/images/emoji/unamused.png
deleted file mode 100644
index 25e3677f2eb..00000000000
--- a/app/assets/images/emoji/unamused.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/underage.png b/app/assets/images/emoji/underage.png
deleted file mode 100644
index 6dfe6da51e2..00000000000
--- a/app/assets/images/emoji/underage.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/unicorn.png b/app/assets/images/emoji/unicorn.png
deleted file mode 100644
index 05a97969f7e..00000000000
--- a/app/assets/images/emoji/unicorn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/unlock.png b/app/assets/images/emoji/unlock.png
deleted file mode 100644
index 4a74a693911..00000000000
--- a/app/assets/images/emoji/unlock.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/up.png b/app/assets/images/emoji/up.png
deleted file mode 100644
index 0d42142ba04..00000000000
--- a/app/assets/images/emoji/up.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/upside_down.png b/app/assets/images/emoji/upside_down.png
deleted file mode 100644
index 128f31c9828..00000000000
--- a/app/assets/images/emoji/upside_down.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/urn.png b/app/assets/images/emoji/urn.png
deleted file mode 100644
index 6b5b3503438..00000000000
--- a/app/assets/images/emoji/urn.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/v.png b/app/assets/images/emoji/v.png
deleted file mode 100644
index 70c5516ffee..00000000000
--- a/app/assets/images/emoji/v.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/v_tone1.png b/app/assets/images/emoji/v_tone1.png
deleted file mode 100644
index 6ac54a745f4..00000000000
--- a/app/assets/images/emoji/v_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/v_tone2.png b/app/assets/images/emoji/v_tone2.png
deleted file mode 100644
index 6dd9669866d..00000000000
--- a/app/assets/images/emoji/v_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/v_tone3.png b/app/assets/images/emoji/v_tone3.png
deleted file mode 100644
index a615e53f02f..00000000000
--- a/app/assets/images/emoji/v_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/v_tone4.png b/app/assets/images/emoji/v_tone4.png
deleted file mode 100644
index 33a34bd5a78..00000000000
--- a/app/assets/images/emoji/v_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/v_tone5.png b/app/assets/images/emoji/v_tone5.png
deleted file mode 100644
index 45ad14b6c9c..00000000000
--- a/app/assets/images/emoji/v_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/vertical_traffic_light.png b/app/assets/images/emoji/vertical_traffic_light.png
deleted file mode 100644
index 8085973eecf..00000000000
--- a/app/assets/images/emoji/vertical_traffic_light.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/vhs.png b/app/assets/images/emoji/vhs.png
deleted file mode 100644
index b9eb78ecd92..00000000000
--- a/app/assets/images/emoji/vhs.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/vibration_mode.png b/app/assets/images/emoji/vibration_mode.png
deleted file mode 100644
index cc46510e48e..00000000000
--- a/app/assets/images/emoji/vibration_mode.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/video_camera.png b/app/assets/images/emoji/video_camera.png
deleted file mode 100644
index 85b300d425c..00000000000
--- a/app/assets/images/emoji/video_camera.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/video_game.png b/app/assets/images/emoji/video_game.png
deleted file mode 100644
index 316a9106a55..00000000000
--- a/app/assets/images/emoji/video_game.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/violin.png b/app/assets/images/emoji/violin.png
deleted file mode 100644
index e1e76cce242..00000000000
--- a/app/assets/images/emoji/violin.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/virgo.png b/app/assets/images/emoji/virgo.png
deleted file mode 100644
index a6b56c2cb5e..00000000000
--- a/app/assets/images/emoji/virgo.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/volcano.png b/app/assets/images/emoji/volcano.png
deleted file mode 100644
index 931d569294c..00000000000
--- a/app/assets/images/emoji/volcano.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/volleyball.png b/app/assets/images/emoji/volleyball.png
deleted file mode 100644
index 7a0e49d4b07..00000000000
--- a/app/assets/images/emoji/volleyball.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/vs.png b/app/assets/images/emoji/vs.png
deleted file mode 100644
index e1180f4a464..00000000000
--- a/app/assets/images/emoji/vs.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/vulcan.png b/app/assets/images/emoji/vulcan.png
deleted file mode 100644
index 54728bcaf5c..00000000000
--- a/app/assets/images/emoji/vulcan.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/vulcan_tone1.png b/app/assets/images/emoji/vulcan_tone1.png
deleted file mode 100644
index 8aff5d8fa16..00000000000
--- a/app/assets/images/emoji/vulcan_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/vulcan_tone2.png b/app/assets/images/emoji/vulcan_tone2.png
deleted file mode 100644
index 82b7ad519b4..00000000000
--- a/app/assets/images/emoji/vulcan_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/vulcan_tone3.png b/app/assets/images/emoji/vulcan_tone3.png
deleted file mode 100644
index d1400e1dd28..00000000000
--- a/app/assets/images/emoji/vulcan_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/vulcan_tone4.png b/app/assets/images/emoji/vulcan_tone4.png
deleted file mode 100644
index 47e2b280148..00000000000
--- a/app/assets/images/emoji/vulcan_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/vulcan_tone5.png b/app/assets/images/emoji/vulcan_tone5.png
deleted file mode 100644
index 60b5c6077be..00000000000
--- a/app/assets/images/emoji/vulcan_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/walking.png b/app/assets/images/emoji/walking.png
deleted file mode 100644
index 06dc169a3fd..00000000000
--- a/app/assets/images/emoji/walking.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/walking_tone1.png b/app/assets/images/emoji/walking_tone1.png
deleted file mode 100644
index 4e391b45a0b..00000000000
--- a/app/assets/images/emoji/walking_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/walking_tone2.png b/app/assets/images/emoji/walking_tone2.png
deleted file mode 100644
index 31f94a1bce1..00000000000
--- a/app/assets/images/emoji/walking_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/walking_tone3.png b/app/assets/images/emoji/walking_tone3.png
deleted file mode 100644
index f7ed8e39c2e..00000000000
--- a/app/assets/images/emoji/walking_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/walking_tone4.png b/app/assets/images/emoji/walking_tone4.png
deleted file mode 100644
index e58dc04c7b2..00000000000
--- a/app/assets/images/emoji/walking_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/walking_tone5.png b/app/assets/images/emoji/walking_tone5.png
deleted file mode 100644
index ba4e1b58fcb..00000000000
--- a/app/assets/images/emoji/walking_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/waning_crescent_moon.png b/app/assets/images/emoji/waning_crescent_moon.png
deleted file mode 100644
index cf68706b871..00000000000
--- a/app/assets/images/emoji/waning_crescent_moon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/waning_gibbous_moon.png b/app/assets/images/emoji/waning_gibbous_moon.png
deleted file mode 100644
index 24e16266119..00000000000
--- a/app/assets/images/emoji/waning_gibbous_moon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/warning.png b/app/assets/images/emoji/warning.png
deleted file mode 100644
index 35691c2ed97..00000000000
--- a/app/assets/images/emoji/warning.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wastebasket.png b/app/assets/images/emoji/wastebasket.png
deleted file mode 100644
index 2b3c484b498..00000000000
--- a/app/assets/images/emoji/wastebasket.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/watch.png b/app/assets/images/emoji/watch.png
deleted file mode 100644
index 64819bc6e21..00000000000
--- a/app/assets/images/emoji/watch.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/water_buffalo.png b/app/assets/images/emoji/water_buffalo.png
deleted file mode 100644
index 80446615caf..00000000000
--- a/app/assets/images/emoji/water_buffalo.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/water_polo.png b/app/assets/images/emoji/water_polo.png
deleted file mode 100644
index cb44576780d..00000000000
--- a/app/assets/images/emoji/water_polo.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/water_polo_tone1.png b/app/assets/images/emoji/water_polo_tone1.png
deleted file mode 100644
index bed1a908d6a..00000000000
--- a/app/assets/images/emoji/water_polo_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/water_polo_tone2.png b/app/assets/images/emoji/water_polo_tone2.png
deleted file mode 100644
index ec5a43b4d4a..00000000000
--- a/app/assets/images/emoji/water_polo_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/water_polo_tone3.png b/app/assets/images/emoji/water_polo_tone3.png
deleted file mode 100644
index b081a4a5a96..00000000000
--- a/app/assets/images/emoji/water_polo_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/water_polo_tone4.png b/app/assets/images/emoji/water_polo_tone4.png
deleted file mode 100644
index 82cfbc3b0c7..00000000000
--- a/app/assets/images/emoji/water_polo_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/water_polo_tone5.png b/app/assets/images/emoji/water_polo_tone5.png
deleted file mode 100644
index bd3366eb06c..00000000000
--- a/app/assets/images/emoji/water_polo_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/watermelon.png b/app/assets/images/emoji/watermelon.png
deleted file mode 100644
index 0761488b4c9..00000000000
--- a/app/assets/images/emoji/watermelon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wave.png b/app/assets/images/emoji/wave.png
deleted file mode 100644
index e0cd79b45f5..00000000000
--- a/app/assets/images/emoji/wave.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wave_tone1.png b/app/assets/images/emoji/wave_tone1.png
deleted file mode 100644
index 6b2b34b106e..00000000000
--- a/app/assets/images/emoji/wave_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wave_tone2.png b/app/assets/images/emoji/wave_tone2.png
deleted file mode 100644
index b857119732e..00000000000
--- a/app/assets/images/emoji/wave_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wave_tone3.png b/app/assets/images/emoji/wave_tone3.png
deleted file mode 100644
index 6283b670f43..00000000000
--- a/app/assets/images/emoji/wave_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wave_tone4.png b/app/assets/images/emoji/wave_tone4.png
deleted file mode 100644
index fe6b2baa747..00000000000
--- a/app/assets/images/emoji/wave_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wave_tone5.png b/app/assets/images/emoji/wave_tone5.png
deleted file mode 100644
index 4bd168ebb78..00000000000
--- a/app/assets/images/emoji/wave_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wavy_dash.png b/app/assets/images/emoji/wavy_dash.png
deleted file mode 100644
index 001c8d6e47d..00000000000
--- a/app/assets/images/emoji/wavy_dash.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/waxing_crescent_moon.png b/app/assets/images/emoji/waxing_crescent_moon.png
deleted file mode 100644
index 687125173d9..00000000000
--- a/app/assets/images/emoji/waxing_crescent_moon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/waxing_gibbous_moon.png b/app/assets/images/emoji/waxing_gibbous_moon.png
deleted file mode 100644
index 3a808156318..00000000000
--- a/app/assets/images/emoji/waxing_gibbous_moon.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wc.png b/app/assets/images/emoji/wc.png
deleted file mode 100644
index aa433e84ba6..00000000000
--- a/app/assets/images/emoji/wc.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/weary.png b/app/assets/images/emoji/weary.png
deleted file mode 100644
index 98bfbd24a16..00000000000
--- a/app/assets/images/emoji/weary.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wedding.png b/app/assets/images/emoji/wedding.png
deleted file mode 100644
index d0d8aa0bfae..00000000000
--- a/app/assets/images/emoji/wedding.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/whale.png b/app/assets/images/emoji/whale.png
deleted file mode 100644
index 9f19b44257c..00000000000
--- a/app/assets/images/emoji/whale.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/whale2.png b/app/assets/images/emoji/whale2.png
deleted file mode 100644
index 0df9d3c73a4..00000000000
--- a/app/assets/images/emoji/whale2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wheel_of_dharma.png b/app/assets/images/emoji/wheel_of_dharma.png
deleted file mode 100644
index 3666db0016b..00000000000
--- a/app/assets/images/emoji/wheel_of_dharma.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wheelchair.png b/app/assets/images/emoji/wheelchair.png
deleted file mode 100644
index 4e5b2698eac..00000000000
--- a/app/assets/images/emoji/wheelchair.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/white_check_mark.png b/app/assets/images/emoji/white_check_mark.png
deleted file mode 100644
index e55f087e544..00000000000
--- a/app/assets/images/emoji/white_check_mark.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/white_circle.png b/app/assets/images/emoji/white_circle.png
deleted file mode 100644
index c19e15684dd..00000000000
--- a/app/assets/images/emoji/white_circle.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/white_flower.png b/app/assets/images/emoji/white_flower.png
deleted file mode 100644
index d6af8b60077..00000000000
--- a/app/assets/images/emoji/white_flower.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/white_large_square.png b/app/assets/images/emoji/white_large_square.png
deleted file mode 100644
index 6f06c1c79de..00000000000
--- a/app/assets/images/emoji/white_large_square.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/white_medium_small_square.png b/app/assets/images/emoji/white_medium_small_square.png
deleted file mode 100644
index ae874126750..00000000000
--- a/app/assets/images/emoji/white_medium_small_square.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/white_medium_square.png b/app/assets/images/emoji/white_medium_square.png
deleted file mode 100644
index 8daacf57059..00000000000
--- a/app/assets/images/emoji/white_medium_square.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/white_small_square.png b/app/assets/images/emoji/white_small_square.png
deleted file mode 100644
index d7ebdb0c0ed..00000000000
--- a/app/assets/images/emoji/white_small_square.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/white_square_button.png b/app/assets/images/emoji/white_square_button.png
deleted file mode 100644
index 934b1cedfd2..00000000000
--- a/app/assets/images/emoji/white_square_button.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/white_sun_cloud.png b/app/assets/images/emoji/white_sun_cloud.png
deleted file mode 100644
index 0a4cc100269..00000000000
--- a/app/assets/images/emoji/white_sun_cloud.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/white_sun_rain_cloud.png b/app/assets/images/emoji/white_sun_rain_cloud.png
deleted file mode 100644
index 491f9ca4839..00000000000
--- a/app/assets/images/emoji/white_sun_rain_cloud.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/white_sun_small_cloud.png b/app/assets/images/emoji/white_sun_small_cloud.png
deleted file mode 100644
index cead0bfa521..00000000000
--- a/app/assets/images/emoji/white_sun_small_cloud.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wilted_rose.png b/app/assets/images/emoji/wilted_rose.png
deleted file mode 100644
index 62412b143ae..00000000000
--- a/app/assets/images/emoji/wilted_rose.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wind_blowing_face.png b/app/assets/images/emoji/wind_blowing_face.png
deleted file mode 100644
index df81b652eb6..00000000000
--- a/app/assets/images/emoji/wind_blowing_face.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wind_chime.png b/app/assets/images/emoji/wind_chime.png
deleted file mode 100644
index 3c9ef3a95f6..00000000000
--- a/app/assets/images/emoji/wind_chime.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wine_glass.png b/app/assets/images/emoji/wine_glass.png
deleted file mode 100644
index 3cc98689192..00000000000
--- a/app/assets/images/emoji/wine_glass.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wink.png b/app/assets/images/emoji/wink.png
deleted file mode 100644
index 7ea7810a37d..00000000000
--- a/app/assets/images/emoji/wink.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wolf.png b/app/assets/images/emoji/wolf.png
deleted file mode 100644
index ba7220f2de9..00000000000
--- a/app/assets/images/emoji/wolf.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/woman.png b/app/assets/images/emoji/woman.png
deleted file mode 100644
index ece440e7a61..00000000000
--- a/app/assets/images/emoji/woman.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/woman_tone1.png b/app/assets/images/emoji/woman_tone1.png
deleted file mode 100644
index ff089b8889b..00000000000
--- a/app/assets/images/emoji/woman_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/woman_tone2.png b/app/assets/images/emoji/woman_tone2.png
deleted file mode 100644
index 0719c378016..00000000000
--- a/app/assets/images/emoji/woman_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/woman_tone3.png b/app/assets/images/emoji/woman_tone3.png
deleted file mode 100644
index 5672e2fd52d..00000000000
--- a/app/assets/images/emoji/woman_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/woman_tone4.png b/app/assets/images/emoji/woman_tone4.png
deleted file mode 100644
index 5754aab558b..00000000000
--- a/app/assets/images/emoji/woman_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/woman_tone5.png b/app/assets/images/emoji/woman_tone5.png
deleted file mode 100644
index fc252af3a39..00000000000
--- a/app/assets/images/emoji/woman_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/womans_clothes.png b/app/assets/images/emoji/womans_clothes.png
deleted file mode 100644
index 01410dc8107..00000000000
--- a/app/assets/images/emoji/womans_clothes.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/womans_hat.png b/app/assets/images/emoji/womans_hat.png
deleted file mode 100644
index b837b6a2e47..00000000000
--- a/app/assets/images/emoji/womans_hat.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/womens.png b/app/assets/images/emoji/womens.png
deleted file mode 100644
index d4ecc22e7b3..00000000000
--- a/app/assets/images/emoji/womens.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/worried.png b/app/assets/images/emoji/worried.png
deleted file mode 100644
index 7074afcf5b7..00000000000
--- a/app/assets/images/emoji/worried.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wrench.png b/app/assets/images/emoji/wrench.png
deleted file mode 100644
index c16b7439697..00000000000
--- a/app/assets/images/emoji/wrench.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wrestlers.png b/app/assets/images/emoji/wrestlers.png
deleted file mode 100644
index 71e67cfad85..00000000000
--- a/app/assets/images/emoji/wrestlers.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wrestlers_tone1.png b/app/assets/images/emoji/wrestlers_tone1.png
deleted file mode 100644
index 379070fd03b..00000000000
--- a/app/assets/images/emoji/wrestlers_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wrestlers_tone2.png b/app/assets/images/emoji/wrestlers_tone2.png
deleted file mode 100644
index 6863ea9209d..00000000000
--- a/app/assets/images/emoji/wrestlers_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wrestlers_tone3.png b/app/assets/images/emoji/wrestlers_tone3.png
deleted file mode 100644
index b7e62910127..00000000000
--- a/app/assets/images/emoji/wrestlers_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wrestlers_tone4.png b/app/assets/images/emoji/wrestlers_tone4.png
deleted file mode 100644
index 750f9589233..00000000000
--- a/app/assets/images/emoji/wrestlers_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/wrestlers_tone5.png b/app/assets/images/emoji/wrestlers_tone5.png
deleted file mode 100644
index 36ab9bb3f42..00000000000
--- a/app/assets/images/emoji/wrestlers_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/writing_hand.png b/app/assets/images/emoji/writing_hand.png
deleted file mode 100644
index 85639f8ac40..00000000000
--- a/app/assets/images/emoji/writing_hand.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/writing_hand_tone1.png b/app/assets/images/emoji/writing_hand_tone1.png
deleted file mode 100644
index 7923d8ebb17..00000000000
--- a/app/assets/images/emoji/writing_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/writing_hand_tone2.png b/app/assets/images/emoji/writing_hand_tone2.png
deleted file mode 100644
index bcb304e15d2..00000000000
--- a/app/assets/images/emoji/writing_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/writing_hand_tone3.png b/app/assets/images/emoji/writing_hand_tone3.png
deleted file mode 100644
index fd885fd2d90..00000000000
--- a/app/assets/images/emoji/writing_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/writing_hand_tone4.png b/app/assets/images/emoji/writing_hand_tone4.png
deleted file mode 100644
index d065b8c64ab..00000000000
--- a/app/assets/images/emoji/writing_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/writing_hand_tone5.png b/app/assets/images/emoji/writing_hand_tone5.png
deleted file mode 100644
index a44b3dd757c..00000000000
--- a/app/assets/images/emoji/writing_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/x.png b/app/assets/images/emoji/x.png
deleted file mode 100644
index 9f9ed0f7ad2..00000000000
--- a/app/assets/images/emoji/x.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/yellow_heart.png b/app/assets/images/emoji/yellow_heart.png
deleted file mode 100644
index 7901a9d0103..00000000000
--- a/app/assets/images/emoji/yellow_heart.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/yen.png b/app/assets/images/emoji/yen.png
deleted file mode 100644
index 63ee4799d66..00000000000
--- a/app/assets/images/emoji/yen.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/yin_yang.png b/app/assets/images/emoji/yin_yang.png
deleted file mode 100644
index f2900f6338f..00000000000
--- a/app/assets/images/emoji/yin_yang.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/yum.png b/app/assets/images/emoji/yum.png
deleted file mode 100644
index 2df15753ca1..00000000000
--- a/app/assets/images/emoji/yum.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/zap.png b/app/assets/images/emoji/zap.png
deleted file mode 100644
index 47e68e48e49..00000000000
--- a/app/assets/images/emoji/zap.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/zero.png b/app/assets/images/emoji/zero.png
deleted file mode 100644
index 13aca83e018..00000000000
--- a/app/assets/images/emoji/zero.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/zipper_mouth.png b/app/assets/images/emoji/zipper_mouth.png
deleted file mode 100644
index f8ced2502a7..00000000000
--- a/app/assets/images/emoji/zipper_mouth.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji/zzz.png b/app/assets/images/emoji/zzz.png
deleted file mode 100644
index 9bc72b4469f..00000000000
--- a/app/assets/images/emoji/zzz.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/emoji@2x.png b/app/assets/images/emoji@2x.png
index 987279c13cc..8fe724329bf 100644
--- a/app/assets/images/emoji@2x.png
+++ b/app/assets/images/emoji@2x.png
Binary files differ
diff --git a/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql b/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql
index 60110437ecd..09278e1776a 100644
--- a/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql
+++ b/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql
@@ -1,6 +1,6 @@
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
-query getProjects(
+query accessTokensGetProjects(
$search: String = ""
$after: String = ""
$first: Int = null
diff --git a/app/assets/javascripts/access_tokens/index.js b/app/assets/javascripts/access_tokens/index.js
index 2cd3a8f12ee..7f5f0403de6 100644
--- a/app/assets/javascripts/access_tokens/index.js
+++ b/app/assets/javascripts/access_tokens/index.js
@@ -49,7 +49,7 @@ export const initProjectsField = () => {
{ default: createDefaultClient },
]) => {
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
Vue.use(VueApollo);
diff --git a/app/assets/javascripts/admin/deploy_keys/components/table.vue b/app/assets/javascripts/admin/deploy_keys/components/table.vue
new file mode 100644
index 00000000000..97a5a2f2f32
--- /dev/null
+++ b/app/assets/javascripts/admin/deploy_keys/components/table.vue
@@ -0,0 +1,54 @@
+<script>
+import { GlTable, GlButton } from '@gitlab/ui';
+
+import { __ } from '~/locale';
+
+export default {
+ name: 'DeployKeysTable',
+ i18n: {
+ pageTitle: __('Public deploy keys'),
+ newDeployKeyButtonText: __('New deploy key'),
+ },
+ fields: [
+ {
+ key: 'title',
+ label: __('Title'),
+ },
+ {
+ key: 'fingerprint',
+ label: __('Fingerprint'),
+ },
+ {
+ key: 'projects',
+ label: __('Projects with write access'),
+ },
+ {
+ key: 'created',
+ label: __('Created'),
+ },
+ {
+ key: 'actions',
+ label: __('Actions'),
+ },
+ ],
+ components: {
+ GlTable,
+ GlButton,
+ },
+ inject: ['editPath', 'deletePath', 'createPath', 'emptyStateSvgPath'],
+};
+</script>
+
+<template>
+ <div>
+ <div class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-py-5">
+ <h4 class="gl-m-0">
+ {{ $options.i18n.pageTitle }}
+ </h4>
+ <gl-button variant="confirm" :href="createPath">{{
+ $options.i18n.newDeployKeyButtonText
+ }}</gl-button>
+ </div>
+ <gl-table :fields="$options.fields" data-testid="deploy-keys-list" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/admin/deploy_keys/index.js b/app/assets/javascripts/admin/deploy_keys/index.js
new file mode 100644
index 00000000000..d86de4229de
--- /dev/null
+++ b/app/assets/javascripts/admin/deploy_keys/index.js
@@ -0,0 +1,23 @@
+import Vue from 'vue';
+import DeployKeysTable from './components/table.vue';
+
+export const initAdminDeployKeysTable = () => {
+ const el = document.getElementById('js-admin-deploy-keys-table');
+
+ if (!el) return false;
+
+ const { editPath, deletePath, createPath, emptyStateSvgPath } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ editPath,
+ deletePath,
+ createPath,
+ emptyStateSvgPath,
+ },
+ render(createElement) {
+ return createElement(DeployKeysTable);
+ },
+ });
+};
diff --git a/app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue b/app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue
index ed90343777d..e949498c55b 100644
--- a/app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue
+++ b/app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue
@@ -138,7 +138,7 @@ export default {
/>
</form>
<template #modal-footer>
- <gl-button @click="onCancel">{{ s__('Cancel') }}</gl-button>
+ <gl-button @click="onCancel">{{ __('Cancel') }}</gl-button>
<gl-button
:disabled="!canSubmit"
category="secondary"
diff --git a/app/assets/javascripts/admin/users/index.js b/app/assets/javascripts/admin/users/index.js
index 852b253d25a..0c485d2a239 100644
--- a/app/assets/javascripts/admin/users/index.js
+++ b/app/assets/javascripts/admin/users/index.js
@@ -15,7 +15,7 @@ import {
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
const initApp = (el, component, userPropKey, props = {}) => {
diff --git a/app/assets/javascripts/alert_management/components/alert_management_table.vue b/app/assets/javascripts/alert_management/components/alert_management_table.vue
index e59d7fc058a..79a6bac3ba7 100644
--- a/app/assets/javascripts/alert_management/components/alert_management_table.vue
+++ b/app/assets/javascripts/alert_management/components/alert_management_table.vue
@@ -17,7 +17,6 @@ import { convertToSnakeCase } from '~/lib/utils/text_utility';
import { joinPaths, visitUrl } from '~/lib/utils/url_utility';
import { s__, __ } from '~/locale';
import AlertStatus from '~/vue_shared/alert_details/components/alert_status.vue';
-import AlertsDeprecationWarning from '~/vue_shared/components/alerts_deprecation_warning.vue';
import {
tdClass,
thClass,
@@ -26,7 +25,6 @@ import {
} from '~/vue_shared/components/paginated_table_with_search_and_tabs/constants';
import PaginatedTableWithSearchAndTabs from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { ALERTS_STATUS_TABS, SEVERITY_LEVELS, trackAlertListViewsOptions } from '../constants';
import getAlertsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
@@ -98,7 +96,6 @@ export default {
severityLabels: SEVERITY_LEVELS,
statusTabs: ALERTS_STATUS_TABS,
components: {
- AlertsDeprecationWarning,
GlAlert,
GlLoadingIcon,
GlTable,
@@ -115,7 +112,6 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
- mixins: [glFeatureFlagMixin()],
inject: ['projectPath', 'textQuery', 'assigneeUsernameQuery', 'populatingAlertsHelpUrl'],
apollo: {
alerts: {
@@ -277,8 +273,6 @@ export default {
</gl-sprintf>
</gl-alert>
- <alerts-deprecation-warning v-if="!glFeatures.managedAlertsDeprecation" />
-
<paginated-table-with-search-and-tabs
:show-error-msg="showErrorMsg"
:i18n="$options.i18n"
diff --git a/app/assets/javascripts/alert_management/list.js b/app/assets/javascripts/alert_management/list.js
index 57d1f135606..b23f8a8eba4 100644
--- a/app/assets/javascripts/alert_management/list.js
+++ b/app/assets/javascripts/alert_management/list.js
@@ -23,7 +23,6 @@ export default () => {
assigneeUsernameQuery,
alertManagementEnabled,
userCanEnableAlertManagement,
- hasManagedPrometheus,
} = domEl.dataset;
const apolloProvider = new VueApollo({
@@ -39,7 +38,6 @@ export default () => {
return defaultDataIdFromObject(object);
},
},
- assumeImmutableResults: true,
},
),
});
@@ -66,7 +64,6 @@ export default () => {
alertManagementEnabled: parseBoolean(alertManagementEnabled),
trackAlertStatusUpdateOptions: PAGE_CONFIG.OPERATIONS.TRACK_ALERT_STATUS_UPDATE_OPTIONS,
userCanEnableAlertManagement: parseBoolean(userCanEnableAlertManagement),
- hasManagedPrometheus: parseBoolean(hasManagedPrometheus),
},
apolloProvider,
render(createElement) {
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
index a5f7b84446f..6b5aac57f1c 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
@@ -16,6 +16,7 @@ import {
import * as Sentry from '@sentry/browser';
import { isEqual, isEmpty, omit } from 'lodash';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import { PROMO_URL } from 'jh_else_ce/lib/utils/url_utility';
import {
integrationTypes,
integrationSteps,
@@ -129,6 +130,7 @@ export default {
name: true,
apiUrl: true,
},
+ pricingLink: `${PROMO_URL}/pricing`,
};
},
computed: {
@@ -436,7 +438,7 @@ export default {
disabled="true"
class="gl-display-inline-block gl-my-4"
:message="$options.i18n.integrationFormSteps.selectType.enterprise"
- link="https://about.gitlab.com/pricing"
+ :link="pricingLink"
data-testid="multi-integrations-not-supported"
/>
</gl-form-group>
diff --git a/app/assets/javascripts/alerts_settings/graphql.js b/app/assets/javascripts/alerts_settings/graphql.js
index 15862f4034a..b64e2e3eefa 100644
--- a/app/assets/javascripts/alerts_settings/graphql.js
+++ b/app/assets/javascripts/alerts_settings/graphql.js
@@ -59,6 +59,5 @@ export default new VueApollo({
cacheConfig: {
fragmentMatcher,
},
- assumeImmutableResults: true,
}),
});
diff --git a/app/assets/javascripts/analytics/devops_report/constants.js b/app/assets/javascripts/analytics/devops_report/constants.js
deleted file mode 100644
index b395d7eb464..00000000000
--- a/app/assets/javascripts/analytics/devops_report/constants.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { __ } from '~/locale';
-
-export const INTRO_COOKIE_KEY = 'dev_ops_report_intro_callout_dismissed';
-
-export const INTRO_BANNER_TITLE = __('Introducing Your DevOps Report');
-
-export const INTRO_BANNER_BODY = __(
- 'Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations.',
-);
-
-export const INTRO_BANNER_ACTION_TEXT = __('Read more');
diff --git a/app/assets/javascripts/analytics/devops_report/components/devops_score.vue b/app/assets/javascripts/analytics/devops_reports/components/devops_score.vue
index 238081cc3c0..238081cc3c0 100644
--- a/app/assets/javascripts/analytics/devops_report/components/devops_score.vue
+++ b/app/assets/javascripts/analytics/devops_reports/components/devops_score.vue
diff --git a/app/assets/javascripts/analytics/devops_report/components/devops_score_callout.vue b/app/assets/javascripts/analytics/devops_reports/components/devops_score_callout.vue
index e594b4e360a..e594b4e360a 100644
--- a/app/assets/javascripts/analytics/devops_report/components/devops_score_callout.vue
+++ b/app/assets/javascripts/analytics/devops_reports/components/devops_score_callout.vue
diff --git a/app/assets/javascripts/analytics/devops_report/components/service_ping_disabled.vue b/app/assets/javascripts/analytics/devops_reports/components/service_ping_disabled.vue
index 400326e41e1..400326e41e1 100644
--- a/app/assets/javascripts/analytics/devops_report/components/service_ping_disabled.vue
+++ b/app/assets/javascripts/analytics/devops_reports/components/service_ping_disabled.vue
diff --git a/app/assets/javascripts/analytics/devops_reports/constants.js b/app/assets/javascripts/analytics/devops_reports/constants.js
new file mode 100644
index 00000000000..6091fcb5724
--- /dev/null
+++ b/app/assets/javascripts/analytics/devops_reports/constants.js
@@ -0,0 +1,11 @@
+import { __ } from '~/locale';
+
+export const INTRO_COOKIE_KEY = 'dev_ops_report_intro_callout_dismissed';
+
+export const INTRO_BANNER_TITLE = __('Introducing Your DevOps Reports');
+
+export const INTRO_BANNER_BODY = __(
+ 'Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other.',
+);
+
+export const INTRO_BANNER_ACTION_TEXT = __('Read more');
diff --git a/app/assets/javascripts/analytics/devops_report/devops_score.js b/app/assets/javascripts/analytics/devops_reports/devops_score.js
index 0bf98b65ed5..0bf98b65ed5 100644
--- a/app/assets/javascripts/analytics/devops_report/devops_score.js
+++ b/app/assets/javascripts/analytics/devops_reports/devops_score.js
diff --git a/app/assets/javascripts/analytics/devops_report/devops_score_disabled_service_ping.js b/app/assets/javascripts/analytics/devops_reports/devops_score_disabled_service_ping.js
index eb2992422a4..eb2992422a4 100644
--- a/app/assets/javascripts/analytics/devops_report/devops_score_disabled_service_ping.js
+++ b/app/assets/javascripts/analytics/devops_reports/devops_score_disabled_service_ping.js
diff --git a/app/assets/javascripts/analytics/shared/graphql/projects.query.graphql b/app/assets/javascripts/analytics/shared/graphql/projects.query.graphql
index 63e95d6804c..b870ed4dcbf 100644
--- a/app/assets/javascripts/analytics/shared/graphql/projects.query.graphql
+++ b/app/assets/javascripts/analytics/shared/graphql/projects.query.graphql
@@ -1,4 +1,4 @@
-query getGroupProjects(
+query analyticsGetGroupProjects(
$groupFullPath: ID!
$search: String!
$first: Int!
diff --git a/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue b/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
index 1eb4832a2a3..63ec40d4ec6 100644
--- a/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
+++ b/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
@@ -3,7 +3,7 @@ import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import { GlSingleStat } from '@gitlab/ui/dist/charts';
import createFlash from '~/flash';
import { number } from '~/lib/utils/unit_format';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import usageTrendsCountQuery from '../graphql/queries/usage_trends_count.query.graphql';
const defaultPrecision = 0;
@@ -52,7 +52,7 @@ export default {
mergeRequests: s__('UsageTrends|Merge requests'),
pipelines: s__('UsageTrends|Pipelines'),
},
- loadCountsError: s__('Could not load usage counts. Please refresh the page to try again.'),
+ loadCountsError: __('Could not load usage counts. Please refresh the page to try again.'),
},
};
</script>
diff --git a/app/assets/javascripts/analytics/usage_trends/index.js b/app/assets/javascripts/analytics/usage_trends/index.js
index 3e85832edcf..d1880b09f15 100644
--- a/app/assets/javascripts/analytics/usage_trends/index.js
+++ b/app/assets/javascripts/analytics/usage_trends/index.js
@@ -6,7 +6,7 @@ import UsageTrendsApp from './components/app.vue';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
export default () => {
diff --git a/app/assets/javascripts/api/namespaces_api.js b/app/assets/javascripts/api/namespaces_api.js
new file mode 100644
index 00000000000..166a95b749a
--- /dev/null
+++ b/app/assets/javascripts/api/namespaces_api.js
@@ -0,0 +1,13 @@
+import { buildApiUrl } from '~/api/api_utils';
+import axios from '~/lib/utils/axios_utils';
+
+const NAMESPACE_EXISTS_PATH = '/api/:version/namespaces/:id/exists';
+
+export function getGroupPathAvailability(groupPath, parentId, axiosOptions = {}) {
+ const url = buildApiUrl(NAMESPACE_EXISTS_PATH).replace(':id', encodeURIComponent(groupPath));
+
+ return axios.get(url, {
+ params: { parent_id: parentId, ...axiosOptions.params },
+ ...axiosOptions,
+ });
+}
diff --git a/app/assets/javascripts/artifacts_settings/index.js b/app/assets/javascripts/artifacts_settings/index.js
index 5c9f1c3129c..531b42bc185 100644
--- a/app/assets/javascripts/artifacts_settings/index.js
+++ b/app/assets/javascripts/artifacts_settings/index.js
@@ -6,7 +6,7 @@ import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
export default (containerId = 'js-artifacts-settings-app') => {
diff --git a/app/assets/javascripts/authentication/two_factor_auth/components/manage_two_factor_form.vue b/app/assets/javascripts/authentication/two_factor_auth/components/manage_two_factor_form.vue
index 0b748f18cb2..484c6524d0e 100644
--- a/app/assets/javascripts/authentication/two_factor_auth/components/manage_two_factor_form.vue
+++ b/app/assets/javascripts/authentication/two_factor_auth/components/manage_two_factor_form.vue
@@ -1,26 +1,46 @@
<script>
-import { GlFormInput, GlFormGroup, GlButton, GlForm } from '@gitlab/ui';
+import { GlFormInput, GlFormGroup, GlButton, GlForm, GlModal } from '@gitlab/ui';
import csrf from '~/lib/utils/csrf';
import { __ } from '~/locale';
export const i18n = {
currentPassword: __('Current password'),
+ confirmTitle: __('Are you sure?'),
confirmWebAuthn: __(
- 'Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices.',
+ 'This will invalidate your registered applications and U2F / WebAuthn devices.',
),
- confirm: __('Are you sure? This will invalidate your registered applications and U2F devices.'),
+ confirm: __('This will invalidate your registered applications and U2F devices.'),
disableTwoFactor: __('Disable two-factor authentication'),
+ disable: __('Disable'),
+ cancel: __('Cancel'),
regenerateRecoveryCodes: __('Regenerate recovery codes'),
+ currentPasswordInvalidFeedback: __('Please enter your current password.'),
};
export default {
name: 'ManageTwoFactorForm',
i18n,
+ modalId: 'manage-two-factor-auth-confirm-modal',
+ modalActions: {
+ primary: {
+ text: i18n.disable,
+ attributes: {
+ variant: 'danger',
+ },
+ },
+ secondary: {
+ text: i18n.cancel,
+ attributes: {
+ variant: 'default',
+ },
+ },
+ },
components: {
GlForm,
GlFormInput,
GlFormGroup,
GlButton,
+ GlModal,
},
inject: [
'webauthnEnabled',
@@ -32,8 +52,11 @@ export default {
],
data() {
return {
- method: '',
- action: '#',
+ method: null,
+ action: null,
+ currentPassword: '',
+ currentPasswordState: null,
+ showConfirmModal: false,
};
},
computed: {
@@ -46,9 +69,34 @@ export default {
},
},
methods: {
- handleFormSubmit(event) {
- this.method = event.submitter.dataset.formMethod;
- this.action = event.submitter.dataset.formAction;
+ submitForm() {
+ this.$refs.form.$el.submit();
+ },
+ async handleSubmitButtonClick({ method, action, confirm = false }) {
+ this.method = method;
+ this.action = action;
+
+ if (this.isCurrentPasswordRequired && this.currentPassword === '') {
+ this.currentPasswordState = false;
+
+ return;
+ }
+
+ this.currentPasswordState = null;
+
+ if (confirm) {
+ this.showConfirmModal = true;
+
+ return;
+ }
+
+ // Wait for form action and method to be updated
+ await this.$nextTick();
+
+ this.submitForm();
+ },
+ handleModalPrimary() {
+ this.submitForm();
},
},
csrf,
@@ -57,10 +105,11 @@ export default {
<template>
<gl-form
- class="gl-display-inline-block"
+ ref="form"
+ class="gl-sm-display-inline-block"
method="post"
:action="action"
- @submit="handleFormSubmit($event)"
+ @submit.prevent
>
<input type="hidden" name="_method" data-testid="test-2fa-method-field" :value="method" />
<input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
@@ -69,35 +118,59 @@ export default {
v-if="isCurrentPasswordRequired"
:label="$options.i18n.currentPassword"
label-for="current-password"
+ :state="currentPasswordState"
+ :invalid-feedback="$options.i18n.currentPasswordInvalidFeedback"
>
<gl-form-input
id="current-password"
+ v-model="currentPassword"
type="password"
name="current_password"
- required
+ :state="currentPasswordState"
data-qa-selector="current_password_field"
/>
</gl-form-group>
- <gl-button
- type="submit"
- class="btn-danger gl-mr-3 gl-display-inline-block"
- data-testid="test-2fa-disable-button"
- variant="danger"
- :data-confirm="confirmText"
- :data-form-action="profileTwoFactorAuthPath"
- :data-form-method="profileTwoFactorAuthMethod"
- >
- {{ $options.i18n.disableTwoFactor }}
- </gl-button>
- <gl-button
- type="submit"
- class="gl-display-inline-block"
- data-testid="test-2fa-regenerate-codes-button"
- :data-form-action="codesProfileTwoFactorAuthPath"
- :data-form-method="codesProfileTwoFactorAuthMethod"
+ <div class="gl-display-flex gl-flex-wrap">
+ <gl-button
+ type="submit"
+ class="gl-sm-mr-3 gl-w-full gl-sm-w-auto"
+ data-testid="test-2fa-disable-button"
+ variant="danger"
+ @click.prevent="
+ handleSubmitButtonClick({
+ method: profileTwoFactorAuthMethod,
+ action: profileTwoFactorAuthPath,
+ confirm: true,
+ })
+ "
+ >
+ {{ $options.i18n.disableTwoFactor }}
+ </gl-button>
+ <gl-button
+ type="submit"
+ class="gl-mt-3 gl-sm-mt-0 gl-w-full gl-sm-w-auto"
+ data-testid="test-2fa-regenerate-codes-button"
+ @click.prevent="
+ handleSubmitButtonClick({
+ method: codesProfileTwoFactorAuthMethod,
+ action: codesProfileTwoFactorAuthPath,
+ })
+ "
+ >
+ {{ $options.i18n.regenerateRecoveryCodes }}
+ </gl-button>
+ </div>
+ <gl-modal
+ v-model="showConfirmModal"
+ :modal-id="$options.modalId"
+ size="sm"
+ :title="$options.i18n.confirmTitle"
+ :action-primary="$options.modalActions.primary"
+ :action-secondary="$options.modalActions.secondary"
+ @primary="handleModalPrimary"
>
- {{ $options.i18n.regenerateRecoveryCodes }}
- </gl-button>
+ {{ confirmText }}
+ </gl-modal>
</gl-form>
</template>
diff --git a/app/assets/javascripts/badges/components/badge_settings.vue b/app/assets/javascripts/badges/components/badge_settings.vue
index 825807e833e..0303930de5d 100644
--- a/app/assets/javascripts/badges/components/badge_settings.vue
+++ b/app/assets/javascripts/badges/components/badge_settings.vue
@@ -2,7 +2,7 @@
import { GlSprintf, GlModal } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import createFlash from '~/flash';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import Badge from './badge.vue';
import BadgeForm from './badge_form.vue';
import BadgeList from './badge_list.vue';
@@ -25,13 +25,13 @@ export default {
...mapState(['badgeInModal', 'isEditing']),
primaryProps() {
return {
- text: s__('Delete badge'),
+ text: __('Delete badge'),
attributes: [{ category: 'primary' }, { variant: 'danger' }],
};
},
cancelProps() {
return {
- text: s__('Cancel'),
+ text: __('Cancel'),
};
},
},
diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue
index f5e3bab6ff0..918519f386b 100644
--- a/app/assets/javascripts/batch_comments/components/draft_note.vue
+++ b/app/assets/javascripts/batch_comments/components/draft_note.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton } from '@gitlab/ui';
+import { GlButton, GlSafeHtmlDirective } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import NoteableNote from '~/notes/components/noteable_note.vue';
import PublishButton from './publish_button.vue';
@@ -10,6 +10,9 @@ export default {
PublishButton,
GlButton,
},
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
props: {
draft: {
type: Object,
@@ -72,6 +75,9 @@ export default {
}
},
},
+ safeHtmlConfig: {
+ ADD_TAGS: ['use', 'gl-emoji'],
+ },
};
</script>
<template>
@@ -104,8 +110,8 @@ export default {
<template v-if="!isEditingDraft">
<div
v-if="draftCommands"
+ v-safe-html:[$options.safeHtmlConfig]="draftCommands"
class="referenced-commands draft-note-commands"
- v-html="draftCommands /* eslint-disable-line vue/no-v-html */"
></div>
<p class="draft-note-actions d-flex">
diff --git a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
index 91b3b6a685c..e90c29e939f 100644
--- a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
@@ -15,14 +15,14 @@ export default {
...mapGetters('batchComments', ['draftsCount', 'sortedDrafts']),
},
methods: {
- ...mapActions('diffs', ['toggleActiveFileByHash']),
+ ...mapActions('diffs', ['setCurrentFileHash']),
...mapActions('batchComments', ['scrollToDraft']),
isLast(index) {
return index === this.sortedDrafts.length - 1;
},
async onClickDraft(draft) {
if (this.viewDiffsFileByFile && draft.file_hash) {
- await this.toggleActiveFileByHash(draft.file_hash);
+ await this.setCurrentFileHash(draft.file_hash);
}
await this.scrollToDraft(draft);
diff --git a/app/assets/javascripts/blob/components/blob_content.vue b/app/assets/javascripts/blob/components/blob_content.vue
index 213e026c41f..e3e43ea3a0e 100644
--- a/app/assets/javascripts/blob/components/blob_content.vue
+++ b/app/assets/javascripts/blob/components/blob_content.vue
@@ -65,7 +65,7 @@ export default {
};
</script>
<template>
- <div class="blob-viewer" :data-type="activeViewer.type">
+ <div class="blob-viewer" :data-type="activeViewer.type" :data-loaded="!loading">
<gl-loading-icon v-if="loading" size="md" color="dark" class="my-4 mx-auto" />
<template v-else>
diff --git a/app/assets/javascripts/blob/components/blob_header.vue b/app/assets/javascripts/blob/components/blob_header.vue
index 4742b4ae4b4..933ad448c77 100644
--- a/app/assets/javascripts/blob/components/blob_header.vue
+++ b/app/assets/javascripts/blob/components/blob_header.vue
@@ -3,12 +3,14 @@ import DefaultActions from './blob_header_default_actions.vue';
import BlobFilepath from './blob_header_filepath.vue';
import ViewerSwitcher from './blob_header_viewer_switcher.vue';
import { SIMPLE_BLOB_VIEWER } from './constants';
+import TableOfContents from './table_contents.vue';
export default {
components: {
ViewerSwitcher,
DefaultActions,
BlobFilepath,
+ TableOfContents,
},
props: {
blob: {
@@ -70,11 +72,14 @@ export default {
</script>
<template>
<div class="js-file-title file-title-flex-parent">
- <blob-filepath :blob="blob">
- <template #filepath-prepend>
- <slot name="prepend"></slot>
- </template>
- </blob-filepath>
+ <div class="gl-display-flex">
+ <table-of-contents class="gl-pr-2" />
+ <blob-filepath :blob="blob">
+ <template #filepath-prepend>
+ <slot name="prepend"></slot>
+ </template>
+ </blob-filepath>
+ </div>
<div class="gl-display-none gl-sm-display-flex">
<viewer-switcher v-if="showViewerSwitcher" v-model="viewer" />
diff --git a/app/assets/javascripts/blob/components/table_contents.vue b/app/assets/javascripts/blob/components/table_contents.vue
index 78ecb82f2cd..07da262ec9a 100644
--- a/app/assets/javascripts/blob/components/table_contents.vue
+++ b/app/assets/javascripts/blob/components/table_contents.vue
@@ -18,11 +18,12 @@ export default {
},
mounted() {
this.blobViewer = document.querySelector('.blob-viewer[data-type="rich"]');
+ const blobViewerAttr = (attr) => this.blobViewer.getAttribute(attr);
this.observer = new MutationObserver(() => {
- if (this.blobViewer.classList.contains('hidden')) {
+ if (this.blobViewer.classList.contains('hidden') || blobViewerAttr('data-type') !== 'rich') {
this.isHidden = true;
- } else if (this.blobViewer.getAttribute('data-loaded') === 'true') {
+ } else if (blobViewerAttr('data-loaded') === 'true') {
this.isHidden = false;
this.generateHeaders();
}
diff --git a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
index a3278f8bde2..e75aa523ed0 100644
--- a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
+++ b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
@@ -1,7 +1,7 @@
<script>
import { GlModal, GlSprintf, GlLink, GlButton } from '@gitlab/ui';
import Cookies from 'js-cookie';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import Tracking from '~/tracking';
const trackingMixin = Tracking.mixin();
@@ -69,7 +69,7 @@ export default {
},
},
i18n: {
- modalTitle: s__("That's it, well done!"),
+ modalTitle: __("That's it, well done!"),
pipelinesButton: s__('MR widget|See your pipeline in action'),
mergeRequestButton: s__('MR widget|Back to the Merge request'),
bodyMessage: s__(
diff --git a/app/assets/javascripts/boards/boards_util.js b/app/assets/javascripts/boards/boards_util.js
index c10241d00d7..e6c91c7ac1f 100644
--- a/app/assets/javascripts/boards/boards_util.js
+++ b/app/assets/javascripts/boards/boards_util.js
@@ -1,4 +1,5 @@
import { sortBy, cloneDeep } from 'lodash';
+import { isGid } from '~/graphql_shared/utils';
import { ListType, MilestoneIDs } from './constants';
export function getMilestone() {
@@ -95,6 +96,9 @@ export function fullMilestoneId(id) {
}
export function fullLabelId(label) {
+ if (isGid(label.id)) {
+ return label.id;
+ }
if (label.project_id && label.project_id !== null) {
return `gid://gitlab/ProjectLabel/${label.id}`;
}
diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue
index 1e780f9ef84..563bed6a6b8 100644
--- a/app/assets/javascripts/boards/components/board_card.vue
+++ b/app/assets/javascripts/boards/components/board_card.vue
@@ -83,7 +83,7 @@ export default {
:data-item-path="item.referencePath"
data-testid="board_card"
class="board-card gl-p-5 gl-rounded-base"
- @mouseup="toggleIssue($event)"
+ @click="toggleIssue($event)"
>
<board-card-inner :list="list" :item="item" :update-filters="true" />
</li>
diff --git a/app/assets/javascripts/boards/components/board_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue
index 9bbb8a1a1b2..54668c9e88e 100644
--- a/app/assets/javascripts/boards/components/board_content_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue
@@ -15,6 +15,7 @@ import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue
import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue';
import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue';
import SidebarLabelsWidget from '~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue';
+import { LabelType } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
@@ -53,6 +54,9 @@ export default {
allowLabelEdit: {
default: false,
},
+ labelsFilterBasePath: {
+ default: '',
+ },
},
inheritAttrs: false,
computed: {
@@ -63,7 +67,7 @@ export default {
'groupPathForActiveIssue',
'projectPathForActiveIssue',
]),
- ...mapState(['sidebarType', 'issuableType', 'isSettingLabels']),
+ ...mapState(['sidebarType', 'issuableType']),
isIssuableSidebar() {
return this.sidebarType === ISSUABLE;
},
@@ -84,7 +88,15 @@ export default {
});
},
attrWorkspacePath() {
- return this.isGroupBoard ? this.groupPathForActiveIssue : undefined;
+ return this.isGroupBoard ? this.groupPathForActiveIssue : this.projectPathForActiveIssue;
+ },
+ labelType() {
+ return this.isGroupBoard ? LabelType.group : LabelType.project;
+ },
+ labelsFilterPath() {
+ return this.isGroupBoard
+ ? this.labelsFilterBasePath.replace(':project_path', this.projectPathForActiveIssue)
+ : this.labelsFilterBasePath;
},
},
methods: {
@@ -98,21 +110,19 @@ export default {
handleClose() {
this.toggleBoardItem({ boardItem: this.activeBoardItem, sidebarType: this.sidebarType });
},
- handleUpdateSelectedLabels(input) {
+ handleUpdateSelectedLabels({ labels, id }) {
this.setActiveBoardItemLabels({
- iid: this.activeBoardItem.iid,
+ id,
projectPath: this.projectPathForActiveIssue,
- addLabelIds: input.map((label) => getIdFromGraphQLId(label.id)),
- removeLabelIds: this.activeBoardItem.labels
- .filter((label) => !input.find((selected) => selected.id === label.id))
- .map((label) => label.id),
+ labelIds: labels.map((label) => getIdFromGraphQLId(label.id)),
+ labels,
});
},
- handleLabelRemove(input) {
+ handleLabelRemove(removeLabelId) {
this.setActiveBoardItemLabels({
iid: this.activeBoardItem.iid,
projectPath: this.projectPathForActiveIssue,
- removeLabelIds: [input],
+ removeLabelIds: [removeLabelId],
});
},
},
@@ -207,14 +217,14 @@ export default {
:full-path="projectPathForActiveIssue"
:allow-label-remove="allowLabelEdit"
:allow-multiselect="true"
- :selected-labels="activeBoardItem.labels"
- :labels-select-in-progress="isSettingLabels"
:footer-create-label-title="createLabelTitle"
:footer-manage-label-title="manageLabelTitle"
:labels-create-title="createLabelTitle"
- :labels-filter-base-path="projectPathForActiveIssue"
+ :labels-filter-base-path="labelsFilterPath"
:attr-workspace-path="attrWorkspacePath"
+ workspace-type="project"
:issuable-type="issuableType"
+ :label-create-type="labelType"
@onLabelRemove="handleLabelRemove"
@updateSelectedLabels="handleUpdateSelectedLabels"
>
diff --git a/app/assets/javascripts/boards/components/board_filtered_search.vue b/app/assets/javascripts/boards/components/board_filtered_search.vue
index 7f242dea644..6e6ada2d109 100644
--- a/app/assets/javascripts/boards/components/board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/board_filtered_search.vue
@@ -1,6 +1,7 @@
<script>
-import { pickBy } from 'lodash';
+import { pickBy, isEmpty } from 'lodash';
import { mapActions } from 'vuex';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
@@ -19,6 +20,11 @@ export default {
type: Array,
required: true,
},
+ eeFilters: {
+ required: false,
+ type: Object,
+ default: () => ({}),
+ },
},
data() {
return {
@@ -26,57 +32,6 @@ export default {
};
},
computed: {
- urlParams() {
- const {
- authorUsername,
- labelName,
- assigneeUsername,
- search,
- milestoneTitle,
- types,
- weight,
- } = this.filterParams;
- let notParams = {};
-
- if (Object.prototype.hasOwnProperty.call(this.filterParams, 'not')) {
- notParams = pickBy(
- {
- 'not[label_name][]': this.filterParams.not.labelName,
- 'not[author_username]': this.filterParams.not.authorUsername,
- 'not[assignee_username]': this.filterParams.not.assigneeUsername,
- 'not[types]': this.filterParams.not.types,
- 'not[milestone_title]': this.filterParams.not.milestoneTitle,
- 'not[weight]': this.filterParams.not.weight,
- },
- undefined,
- );
- }
-
- return {
- ...notParams,
- author_username: authorUsername,
- 'label_name[]': labelName,
- assignee_username: assigneeUsername,
- milestone_title: milestoneTitle,
- search,
- types,
- weight,
- };
- },
- },
- methods: {
- ...mapActions(['performSearch']),
- handleFilter(filters) {
- this.filterParams = this.getFilterParams(filters);
-
- updateHistory({
- url: setUrlParams(this.urlParams, window.location.href, true, false, true),
- title: document.title,
- replace: true,
- });
-
- this.performSearch();
- },
getFilteredSearchValue() {
const {
authorUsername,
@@ -86,6 +41,8 @@ export default {
milestoneTitle,
types,
weight,
+ epicId,
+ myReactionEmoji,
} = this.filterParams;
const filteredSearchValue = [];
@@ -133,6 +90,20 @@ export default {
});
}
+ if (myReactionEmoji) {
+ filteredSearchValue.push({
+ type: 'my_reaction_emoji',
+ value: { data: myReactionEmoji, operator: '=' },
+ });
+ }
+
+ if (epicId) {
+ filteredSearchValue.push({
+ type: 'epic_id',
+ value: { data: epicId, operator: '=' },
+ });
+ }
+
if (this.filterParams['not[authorUsername]']) {
filteredSearchValue.push({
type: 'author_username',
@@ -177,12 +148,89 @@ export default {
});
}
+ if (this.filterParams['not[epicId]']) {
+ filteredSearchValue.push({
+ type: 'epic_id',
+ value: { data: this.filterParams['not[epicId]'], operator: '!=' },
+ });
+ }
+
+ if (this.filterParams['not[myReactionEmoji]']) {
+ filteredSearchValue.push({
+ type: 'my_reaction_emoji',
+ value: { data: this.filterParams['not[myReactionEmoji]'], operator: '!=' },
+ });
+ }
+
if (search) {
filteredSearchValue.push(search);
}
return filteredSearchValue;
},
+ urlParams() {
+ const {
+ authorUsername,
+ labelName,
+ assigneeUsername,
+ search,
+ milestoneTitle,
+ types,
+ weight,
+ epicId,
+ myReactionEmoji,
+ } = this.filterParams;
+
+ let notParams = {};
+
+ if (Object.prototype.hasOwnProperty.call(this.filterParams, 'not')) {
+ notParams = pickBy(
+ {
+ 'not[label_name][]': this.filterParams.not.labelName,
+ 'not[author_username]': this.filterParams.not.authorUsername,
+ 'not[assignee_username]': this.filterParams.not.assigneeUsername,
+ 'not[types]': this.filterParams.not.types,
+ 'not[milestone_title]': this.filterParams.not.milestoneTitle,
+ 'not[weight]': this.filterParams.not.weight,
+ 'not[epic_id]': this.filterParams.not.epicId,
+ 'not[my_reaction_emoji]': this.filterParams.not.myReactionEmoji,
+ },
+ undefined,
+ );
+ }
+
+ return {
+ ...notParams,
+ author_username: authorUsername,
+ 'label_name[]': labelName,
+ assignee_username: assigneeUsername,
+ milestone_title: milestoneTitle,
+ search,
+ types,
+ weight,
+ epic_id: getIdFromGraphQLId(epicId),
+ my_reaction_emoji: myReactionEmoji,
+ };
+ },
+ },
+ created() {
+ if (!isEmpty(this.eeFilters)) {
+ this.filterParams = this.eeFilters;
+ }
+ },
+ methods: {
+ ...mapActions(['performSearch']),
+ handleFilter(filters) {
+ this.filterParams = this.getFilterParams(filters);
+
+ updateHistory({
+ url: setUrlParams(this.urlParams, window.location.href, true, false, true),
+ title: document.title,
+ replace: true,
+ });
+
+ this.performSearch();
+ },
getFilterParams(filters = []) {
const notFilters = filters.filter((item) => item.value.operator === '!=');
const equalsFilters = filters.filter(
@@ -216,6 +264,12 @@ export default {
case 'weight':
filterParams.weight = filter.value.data;
break;
+ case 'epic_id':
+ filterParams.epicId = filter.value.data;
+ break;
+ case 'my_reaction_emoji':
+ filterParams.myReactionEmoji = filter.value.data;
+ break;
case 'filtered-search-term':
if (filter.value.data) plainText.push(filter.value.data);
break;
@@ -243,7 +297,7 @@ export default {
namespace=""
:tokens="tokens"
:search-input-placeholder="$options.i18n.search"
- :initial-filter-value="getFilteredSearchValue()"
+ :initial-filter-value="getFilteredSearchValue"
@onFilter="handleFilter"
/>
</template>
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index e939f0c0ebe..6ad57fd8985 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -2,10 +2,10 @@
import { GlModal, GlAlert } from '@gitlab/ui';
import { mapGetters, mapActions, mapState } from 'vuex';
import { TYPE_USER, TYPE_ITERATION, TYPE_MILESTONE } from '~/graphql_shared/constants';
-import { convertToGraphQLId } from '~/graphql_shared/utils';
+import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
import { getParameterByName, visitUrl } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
-import { fullLabelId, fullBoardId } from '../boards_util';
+import { fullLabelId } from '../boards_util';
import { formType } from '../constants';
import createBoardMutation from '../graphql/board_create.mutation.graphql';
@@ -18,11 +18,11 @@ const boardDefaults = {
name: '',
labels: [],
milestone: {},
- iteration_id: undefined,
+ iteration: {},
assignee: {},
weight: null,
- hide_backlog_list: false,
- hide_closed_list: false,
+ hideBacklogList: false,
+ hideClosedList: false,
};
export default {
@@ -57,39 +57,16 @@ export default {
type: Boolean,
required: true,
},
- labelsPath: {
- type: String,
- required: true,
- },
- labelsWebUrl: {
- type: String,
- required: true,
- },
scopedIssueBoardFeatureEnabled: {
type: Boolean,
required: false,
default: false,
},
- projectId: {
- type: Number,
- required: false,
- default: 0,
- },
- groupId: {
- type: Number,
- required: false,
- default: 0,
- },
weights: {
type: Array,
required: false,
default: () => [],
},
- enableScopedLabels: {
- type: Boolean,
- required: false,
- default: false,
- },
currentBoard: {
type: Object,
required: true,
@@ -167,17 +144,16 @@ export default {
return destroyBoardMutation;
},
baseMutationVariables() {
- const { board } = this;
- const variables = {
- name: board.name,
- hideBacklogList: board.hide_backlog_list,
- hideClosedList: board.hide_closed_list,
- };
+ const {
+ board: { name, hideBacklogList, hideClosedList, id },
+ } = this;
- return board.id
+ const variables = { name, hideBacklogList, hideClosedList };
+
+ return id
? {
...variables,
- id: fullBoardId(board.id),
+ id,
}
: {
...variables,
@@ -191,11 +167,13 @@ export default {
assigneeId: this.board.assignee?.id
? convertToGraphQLId(TYPE_USER, this.board.assignee.id)
: null,
+ // Temporarily converting to milestone ID due to https://gitlab.com/gitlab-org/gitlab/-/issues/344779
milestoneId: this.board.milestone?.id
- ? convertToGraphQLId(TYPE_MILESTONE, this.board.milestone.id)
+ ? convertToGraphQLId(TYPE_MILESTONE, getIdFromGraphQLId(this.board.milestone.id))
: null,
- iterationId: this.board.iteration_id
- ? convertToGraphQLId(TYPE_ITERATION, this.board.iteration_id)
+ // Temporarily converting to iteration ID due to https://gitlab.com/gitlab-org/gitlab/-/issues/344779
+ iterationId: this.board.iteration?.id
+ ? convertToGraphQLId(TYPE_ITERATION, getIdFromGraphQLId(this.board.iteration.id))
: null,
};
},
@@ -249,7 +227,7 @@ export default {
await this.$apollo.mutate({
mutation: this.deleteMutation,
variables: {
- id: fullBoardId(this.board.id),
+ id: this.board.id,
},
});
},
@@ -285,19 +263,12 @@ export default {
}
},
setIteration(iterationId) {
- this.board.iteration_id = iterationId;
+ this.$set(this.board, 'iteration', {
+ id: iterationId,
+ });
},
setBoardLabels(labels) {
- labels.forEach((label) => {
- if (label.set && !this.board.labels.find((l) => l.id === label.id)) {
- this.board.labels.push({
- ...label,
- textColor: label.text_color,
- });
- } else if (!label.set) {
- this.board.labels = this.board.labels.filter((selected) => selected.id !== label.id);
- }
- });
+ this.board.labels = labels;
},
setAssignee(assigneeId) {
this.$set(this.board, 'assignee', {
@@ -361,8 +332,8 @@ export default {
</div>
<board-configuration-options
- :hide-backlog-list.sync="board.hide_backlog_list"
- :hide-closed-list.sync="board.hide_closed_list"
+ :hide-backlog-list.sync="board.hideBacklogList"
+ :hide-closed-list.sync="board.hideClosedList"
:readonly="readonly"
/>
@@ -371,11 +342,6 @@ export default {
:collapse-scope="isNewForm"
:board="board"
:can-admin-board="canAdminBoard"
- :labels-path="labelsPath"
- :labels-web-url="labelsWebUrl"
- :enable-scoped-labels="enableScopedLabels"
- :project-id="projectId"
- :group-id="groupId"
:weights="weights"
@set-iteration="setIteration"
@set-board-labels="setBoardLabels"
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index a8d71ab7a35..e985a368e64 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -15,6 +15,8 @@ import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { n__, s__, __ } from '~/locale';
import sidebarEventHub from '~/sidebar/event_hub';
import Tracking from '~/tracking';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import AccessorUtilities from '../../lib/utils/accessor';
import { inactiveId, LIST, ListType, toggleFormEventPrefix } from '../constants';
import eventHub from '../eventhub';
@@ -40,7 +42,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
- mixins: [Tracking.mixin()],
+ mixins: [Tracking.mixin(), glFeatureFlagMixin()],
inject: {
boardId: {
default: '',
@@ -86,6 +88,13 @@ export default {
listTitle() {
return this.list?.label?.description || this.list?.assignee?.name || this.list.title || '';
},
+ listIterationPeriod() {
+ const iteration = this.list?.iteration;
+ return iteration ? this.getIterationPeriod(iteration) : '';
+ },
+ isIterationList() {
+ return this.listType === ListType.iteration;
+ },
showListHeaderButton() {
return !this.disabled && this.listType !== ListType.closed;
},
@@ -96,7 +105,10 @@ export default {
return this.listType === ListType.assignee && this.showListDetails;
},
showIterationListDetails() {
- return this.listType === ListType.iteration && this.showListDetails;
+ return this.isIterationList && this.showListDetails;
+ },
+ iterationCadencesAvailable() {
+ return this.isIterationList && this.glFeatures.iterationCadences;
},
showListDetails() {
return !this.list.collapsed || !this.isSwimlanesHeader;
@@ -208,6 +220,16 @@ export default {
updateListFunction() {
this.updateList({ listId: this.list.id, collapsed: this.list.collapsed });
},
+ /**
+ * TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/344619
+ * This method also exists as a utility function in ee/../iterations/utils.js
+ * Remove the duplication when the EE code is separated from this compoment.
+ */
+ getIterationPeriod({ startDate, dueDate }) {
+ const start = formatDate(startDate, 'mmm d, yyyy', true);
+ const due = formatDate(dueDate, 'mmm d, yyyy', true);
+ return `${start} - ${due}`;
+ },
},
};
</script>
@@ -307,6 +329,13 @@ export default {
class="board-title-main-text gl-text-truncate"
>
{{ listTitle }}
+ <span
+ v-if="iterationCadencesAvailable"
+ class="gl-display-inline-block gl-text-gray-400"
+ data-testid="board-list-iteration-period"
+ >
+ {{ listIterationPeriod }}</span
+ >
</span>
<span
v-if="listType === 'assignee'"
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index 98027917221..71facba1378 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -9,17 +9,20 @@ import {
GlModalDirective,
} from '@gitlab/ui';
import { throttle } from 'lodash';
-import { mapGetters, mapState } from 'vuex';
+import { mapActions, mapGetters, mapState } from 'vuex';
import BoardForm from 'ee_else_ce/boards/components/board_form.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
+import { s__ } from '~/locale';
import eventHub from '../eventhub';
-import groupQuery from '../graphql/group_boards.query.graphql';
-import projectQuery from '../graphql/project_boards.query.graphql';
+import groupBoardsQuery from '../graphql/group_boards.query.graphql';
+import projectBoardsQuery from '../graphql/project_boards.query.graphql';
+import groupBoardQuery from '../graphql/group_board.query.graphql';
+import projectBoardQuery from '../graphql/project_board.query.graphql';
const MIN_BOARDS_TO_VIEW_RECENT = 10;
@@ -39,10 +42,6 @@ export default {
},
inject: ['fullPath', 'recentBoardsEndpoint'],
props: {
- currentBoard: {
- type: Object,
- required: true,
- },
throttleDuration: {
type: Number,
default: 200,
@@ -64,22 +63,6 @@ export default {
type: Boolean,
required: true,
},
- labelsPath: {
- type: String,
- required: true,
- },
- labelsWebUrl: {
- type: String,
- required: true,
- },
- projectId: {
- type: Number,
- required: true,
- },
- groupId: {
- type: Number,
- required: true,
- },
scopedIssueBoardFeatureEnabled: {
type: Boolean,
required: true,
@@ -88,11 +71,6 @@ export default {
type: Array,
required: true,
},
- enabledScopedLabels: {
- type: Boolean,
- required: false,
- default: false,
- },
},
data() {
return {
@@ -107,14 +85,47 @@ export default {
maxPosition: 0,
filterTerm: '',
currentPage: '',
+ board: {},
};
},
+ apollo: {
+ board: {
+ query() {
+ return this.currentBoardQuery;
+ },
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ boardId: this.fullBoardId,
+ };
+ },
+ update(data) {
+ const board = data.workspace?.board;
+ return {
+ ...board,
+ labels: board?.labels?.nodes,
+ };
+ },
+ error() {
+ this.setError({ message: this.$options.i18n.errorFetchingBoard });
+ },
+ },
+ },
computed: {
- ...mapState(['boardType']),
- ...mapGetters(['isGroupBoard']),
+ ...mapState(['boardType', 'fullBoardId']),
+ ...mapGetters(['isGroupBoard', 'isProjectBoard']),
parentType() {
return this.boardType;
},
+ currentBoardQueryCE() {
+ return this.isGroupBoard ? groupBoardQuery : projectBoardQuery;
+ },
+ currentBoardQuery() {
+ return this.currentBoardQueryCE;
+ },
+ isBoardLoading() {
+ return this.$apollo.queries.board.loading;
+ },
loading() {
return this.loadingRecentBoards || Boolean(this.loadingBoards);
},
@@ -123,9 +134,6 @@ export default {
board.name.toLowerCase().includes(this.filterTerm.toLowerCase()),
);
},
- board() {
- return this.currentBoard;
- },
showCreate() {
return this.multipleIssueBoardsAvailable;
},
@@ -158,6 +166,7 @@ export default {
eventHub.$off('showBoardModal', this.showPage);
},
methods: {
+ ...mapActions(['setError']),
showPage(page) {
this.currentPage = page;
},
@@ -174,7 +183,7 @@ export default {
}));
},
boardQuery() {
- return this.isGroupBoard ? groupQuery : projectQuery;
+ return this.isGroupBoard ? groupBoardsQuery : projectBoardsQuery;
},
loadBoards(toggleDropdown = true) {
if (toggleDropdown && this.boards.length > 0) {
@@ -250,6 +259,9 @@ export default {
this.hasScrollFade = this.isScrolledUp();
},
},
+ i18n: {
+ errorFetchingBoard: s__('Board|An error occurred while fetching the board, please try again.'),
+ },
};
</script>
@@ -260,6 +272,7 @@ export default {
data-qa-selector="boards_dropdown"
toggle-class="dropdown-menu-toggle js-dropdown-toggle"
menu-class="flex-column dropdown-extended-height"
+ :loading="isBoardLoading"
:text="board.name"
@show="loadBoards"
>
@@ -354,15 +367,10 @@ export default {
<board-form
v-if="currentPage"
- :labels-path="labelsPath"
- :labels-web-url="labelsWebUrl"
- :project-id="projectId"
- :group-id="groupId"
:can-admin-board="canAdminBoard"
:scoped-issue-board-feature-enabled="scopedIssueBoardFeatureEnabled"
:weights="weights"
- :enable-scoped-labels="enabledScopedLabels"
- :current-board="currentBoard"
+ :current-board="board"
:current-page="currentPage"
@cancel="cancel"
/>
diff --git a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
index b6c5ef955c6..bdb9c2be836 100644
--- a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
@@ -1,13 +1,20 @@
<script>
import { GlFilteredSearchToken } from '@gitlab/ui';
+import fuzzaldrinPlus from 'fuzzaldrin-plus';
import { mapActions } from 'vuex';
-import BoardFilteredSearch from '~/boards/components/board_filtered_search.vue';
+import BoardFilteredSearch from 'ee_else_ce/boards/components/board_filtered_search.vue';
+import { BoardType } from '~/boards/constants';
+import axios from '~/lib/utils/axios_utils';
import issueBoardFilters from '~/boards/issue_board_filters';
import { TYPE_USER } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale';
-import { DEFAULT_MILESTONES_GRAPHQL } from '~/vue_shared/components/filtered_search_bar/constants';
+import {
+ DEFAULT_MILESTONES_GRAPHQL,
+ TOKEN_TITLE_MY_REACTION,
+} from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
+import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue';
@@ -19,6 +26,7 @@ export default {
},
i18n: {
search: __('Search'),
+ epic: __('Epic'),
label: __('Label'),
author: __('Author'),
assignee: __('Assignee'),
@@ -31,6 +39,7 @@ export default {
isNot: __('is not'),
},
components: { BoardFilteredSearch },
+ inject: ['isSignedIn'],
props: {
fullPath: {
type: String,
@@ -42,7 +51,15 @@ export default {
},
},
computed: {
- tokens() {
+ isGroupBoard() {
+ return this.boardType === BoardType.group;
+ },
+ epicsGroupPath() {
+ return this.isGroupBoard
+ ? this.fullPath
+ : this.fullPath.slice(0, this.fullPath.lastIndexOf('/'));
+ },
+ tokensCE() {
const {
label,
is,
@@ -103,6 +120,32 @@ export default {
symbol: '~',
fetchLabels,
},
+ ...(this.isSignedIn
+ ? [
+ {
+ type: 'my_reaction_emoji',
+ title: TOKEN_TITLE_MY_REACTION,
+ icon: 'thumb-up',
+ token: EmojiToken,
+ unique: true,
+ fetchEmojis: (search = '') => {
+ // TODO: Switch to GraphQL query when backend is ready: https://gitlab.com/gitlab-org/gitlab/-/issues/339694
+ return axios
+ .get(`${gon.relative_url_root || ''}/-/autocomplete/award_emojis`)
+ .then(({ data }) => {
+ if (search) {
+ return {
+ data: fuzzaldrinPlus.filter(data, search, {
+ key: ['name'],
+ }),
+ };
+ }
+ return { data };
+ });
+ },
+ },
+ ]
+ : []),
{
type: 'milestone_title',
title: milestone,
@@ -117,7 +160,6 @@ export default {
icon: 'issues',
title: type,
type: 'types',
- operators: [{ value: '=', description: is }],
token: GlFilteredSearchToken,
unique: true,
options: [
@@ -134,6 +176,9 @@ export default {
},
];
},
+ tokens() {
+ return this.tokensCE;
+ },
},
methods: {
...mapActions(['fetchMilestones']),
diff --git a/app/assets/javascripts/boards/components/new_board_button.vue b/app/assets/javascripts/boards/components/new_board_button.vue
new file mode 100644
index 00000000000..f7914c636cc
--- /dev/null
+++ b/app/assets/javascripts/boards/components/new_board_button.vue
@@ -0,0 +1,47 @@
+<script>
+import { GlButton, GlModalDirective } from '@gitlab/ui';
+import { formType } from '~/boards/constants';
+import eventHub from '~/boards/eventhub';
+import { s__ } from '~/locale';
+import Tracking from '~/tracking';
+import GitlabExperiment from '~/experimentation/components/gitlab_experiment.vue';
+
+export default {
+ components: {
+ GlButton,
+ GitlabExperiment,
+ },
+ directives: {
+ GlModalDirective,
+ },
+ mixins: [Tracking.mixin()],
+ inject: ['multipleIssueBoardsAvailable', 'canAdminBoard'],
+ computed: {
+ canShowCreateButton() {
+ return this.canAdminBoard && this.multipleIssueBoardsAvailable;
+ },
+ createButtonText() {
+ return s__('Boards|New board');
+ },
+ },
+ methods: {
+ showDialog() {
+ this.track('click_button', { label: 'create_board' });
+ eventHub.$emit('showBoardModal', formType.new);
+ },
+ },
+};
+</script>
+
+<template>
+ <gitlab-experiment name="prominent_create_board_btn">
+ <template #control> </template>
+ <template #candidate>
+ <div v-if="canShowCreateButton" class="gl-ml-1 gl-mr-3 gl-display-flex gl-align-items-center">
+ <gl-button data-qa-selector="new_board_button" @click.prevent="showDialog">
+ {{ createButtonText }}
+ </gl-button>
+ </div>
+ </template>
+ </gitlab-experiment>
+</template>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
index e74463825c5..ec53947fd5f 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
@@ -91,9 +91,7 @@ export default {
try {
const addLabelIds = payload.filter((label) => label.set).map((label) => label.id);
- const removeLabelIds = this.selectedLabels
- .filter((label) => !payload.find((selected) => selected.id === label.id))
- .map((label) => label.id);
+ const removeLabelIds = payload.filter((label) => !label.set).map((label) => label.id);
const input = {
addLabelIds,
@@ -164,7 +162,7 @@ export default {
:labels-list-title="__('Select label')"
:dropdown-button-text="__('Choose labels')"
:is-editing="edit"
- variant="embedded"
+ variant="sidebar"
class="gl-display-block labels gl-w-full"
@updateSelectedLabels="setLabels"
>
diff --git a/app/assets/javascripts/boards/graphql.js b/app/assets/javascripts/boards/graphql.js
index d8d16184936..64938cb42ed 100644
--- a/app/assets/javascripts/boards/graphql.js
+++ b/app/assets/javascripts/boards/graphql.js
@@ -17,6 +17,5 @@ export const gqlClient = createDefaultClient(
fragmentMatcher,
},
- assumeImmutableResults: true,
},
);
diff --git a/app/assets/javascripts/boards/graphql/board_list_create.mutation.graphql b/app/assets/javascripts/boards/graphql/board_list_create.mutation.graphql
index 3eb23f62940..0e1d11727cf 100644
--- a/app/assets/javascripts/boards/graphql/board_list_create.mutation.graphql
+++ b/app/assets/javascripts/boards/graphql/board_list_create.mutation.graphql
@@ -1,6 +1,6 @@
#import "./board_list.fragment.graphql"
-mutation CreateBoardList($boardId: BoardID!, $backlog: Boolean, $labelId: LabelID) {
+mutation createBoardList($boardId: BoardID!, $backlog: Boolean, $labelId: LabelID) {
boardListCreate(input: { boardId: $boardId, backlog: $backlog, labelId: $labelId }) {
list {
...BoardListFragment
diff --git a/app/assets/javascripts/boards/graphql/board_lists.query.graphql b/app/assets/javascripts/boards/graphql/board_lists.query.graphql
index 734867c77e9..47e87907d76 100644
--- a/app/assets/javascripts/boards/graphql/board_lists.query.graphql
+++ b/app/assets/javascripts/boards/graphql/board_lists.query.graphql
@@ -1,6 +1,6 @@
#import "ee_else_ce/boards/graphql/board_list.fragment.graphql"
-query ListIssues(
+query BoardLists(
$fullPath: ID!
$boardId: ID!
$filters: BoardIssueInput
diff --git a/app/assets/javascripts/boards/graphql/board_scope.fragment.graphql b/app/assets/javascripts/boards/graphql/board_scope.fragment.graphql
new file mode 100644
index 00000000000..57f51822d91
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/board_scope.fragment.graphql
@@ -0,0 +1,6 @@
+fragment BoardScopeFragment on Board {
+ id
+ name
+ hideBacklogList
+ hideClosedList
+}
diff --git a/app/assets/javascripts/boards/graphql/group_board.query.graphql b/app/assets/javascripts/boards/graphql/group_board.query.graphql
new file mode 100644
index 00000000000..77c8e0378f0
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/group_board.query.graphql
@@ -0,0 +1,9 @@
+#import "ee_else_ce/boards/graphql/board_scope.fragment.graphql"
+
+query GroupBoard($fullPath: ID!, $boardId: ID!) {
+ workspace: group(fullPath: $fullPath) {
+ board(id: $boardId) {
+ ...BoardScopeFragment
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/graphql/group_board_iterations.query.graphql b/app/assets/javascripts/boards/graphql/group_board_iterations.query.graphql
deleted file mode 100644
index 1c382c4747b..00000000000
--- a/app/assets/javascripts/boards/graphql/group_board_iterations.query.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-query GroupBoardIterations($fullPath: ID!, $title: String) {
- group(fullPath: $fullPath) {
- iterations(includeAncestors: true, title: $title) {
- nodes {
- id
- title
- }
- }
- }
-}
diff --git a/app/assets/javascripts/boards/graphql/group_projects.query.graphql b/app/assets/javascripts/boards/graphql/group_projects.query.graphql
index 3218c06357c..c5732bbaff3 100644
--- a/app/assets/javascripts/boards/graphql/group_projects.query.graphql
+++ b/app/assets/javascripts/boards/graphql/group_projects.query.graphql
@@ -1,6 +1,6 @@
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
-query getGroupProjects($fullPath: ID!, $search: String, $after: String) {
+query boardsGetGroupProjects($fullPath: ID!, $search: String, $after: String) {
group(fullPath: $fullPath) {
projects(search: $search, after: $after, first: 100, includeSubgroups: true) {
nodes {
diff --git a/app/assets/javascripts/boards/graphql/issue_move_list.mutation.graphql b/app/assets/javascripts/boards/graphql/issue_move_list.mutation.graphql
index 3c574fd8c87..570731ecac6 100644
--- a/app/assets/javascripts/boards/graphql/issue_move_list.mutation.graphql
+++ b/app/assets/javascripts/boards/graphql/issue_move_list.mutation.graphql
@@ -1,6 +1,6 @@
#import "ee_else_ce/boards/graphql/issue.fragment.graphql"
-mutation IssueMoveList(
+mutation issueMoveList(
$projectPath: ID!
$iid: String!
$boardId: ID!
diff --git a/app/assets/javascripts/boards/graphql/lists_issues.query.graphql b/app/assets/javascripts/boards/graphql/lists_issues.query.graphql
index 787dd77b901..9f93bc6d5bf 100644
--- a/app/assets/javascripts/boards/graphql/lists_issues.query.graphql
+++ b/app/assets/javascripts/boards/graphql/lists_issues.query.graphql
@@ -1,6 +1,6 @@
#import "ee_else_ce/boards/graphql/issue.fragment.graphql"
-query ListIssues(
+query BoardListEE(
$fullPath: ID!
$boardId: ID!
$id: ID
diff --git a/app/assets/javascripts/boards/graphql/project_board.query.graphql b/app/assets/javascripts/boards/graphql/project_board.query.graphql
new file mode 100644
index 00000000000..6e4cd6bed57
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/project_board.query.graphql
@@ -0,0 +1,9 @@
+#import "ee_else_ce/boards/graphql/board_scope.fragment.graphql"
+
+query ProjectBoard($fullPath: ID!, $boardId: ID!) {
+ workspace: project(fullPath: $fullPath) {
+ board(id: $boardId) {
+ ...BoardScopeFragment
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/graphql/project_board_iterations.query.graphql b/app/assets/javascripts/boards/graphql/project_board_iterations.query.graphql
deleted file mode 100644
index 078151a275a..00000000000
--- a/app/assets/javascripts/boards/graphql/project_board_iterations.query.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-query ProjectBoardIterations($fullPath: ID!, $title: String) {
- project(fullPath: $fullPath) {
- iterations(includeAncestors: true, title: $title) {
- nodes {
- id
- title
- }
- }
- }
-}
diff --git a/app/assets/javascripts/boards/graphql/project_milestones.query.graphql b/app/assets/javascripts/boards/graphql/project_milestones.query.graphql
index 724b7f5a34c..61c9ddded9b 100644
--- a/app/assets/javascripts/boards/graphql/project_milestones.query.graphql
+++ b/app/assets/javascripts/boards/graphql/project_milestones.query.graphql
@@ -1,4 +1,4 @@
-query projectMilestones(
+query boardProjectMilestones(
$fullPath: ID!
$state: MilestoneStateEnum
$includeAncestors: Boolean
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index b6b1094fb3a..6fa8dd63245 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -13,9 +13,10 @@ import FilteredSearchBoards from '~/boards/filtered_search_boards';
import initBoardsFilteredSearch from '~/boards/mount_filtered_search_issue_boards';
import store from '~/boards/stores';
import toggleFocusMode from '~/boards/toggle_focus';
-import { NavigationType, parseBoolean } from '~/lib/utils/common_utils';
+import { NavigationType, isLoggedIn, parseBoolean } from '~/lib/utils/common_utils';
import { fullBoardId } from './boards_util';
import boardConfigToggle from './config_toggle';
+import initNewBoard from './new_board';
import { gqlClient } from './graphql';
import mountMultipleBoardsSwitcher from './mount_multiple_boards_switcher';
@@ -109,7 +110,7 @@ export default () => {
});
if (gon?.features?.issueBoardsFilteredSearch) {
- initBoardsFilteredSearch(apolloProvider);
+ initBoardsFilteredSearch(apolloProvider, isLoggedIn());
}
mountBoardApp($boardApp);
@@ -130,6 +131,7 @@ export default () => {
}
boardConfigToggle();
+ initNewBoard();
toggleFocusMode();
toggleLabels();
@@ -142,5 +144,7 @@ export default () => {
fullPath: $boardApp.dataset.fullPath,
rootPath: $boardApp.dataset.boardsEndpoint,
recentBoardsEndpoint: $boardApp.dataset.recentBoardsEndpoint,
+ allowScopedLabels: $boardApp.dataset.scopedLabels,
+ labelsManagePath: $boardApp.dataset.labelsManagePath,
});
};
diff --git a/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js b/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js
index 7732091ef34..1ea74d5685c 100644
--- a/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js
+++ b/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js
@@ -1,10 +1,10 @@
import Vue from 'vue';
-import IssueBoardFilteredSearch from '~/boards/components/issue_board_filtered_search.vue';
+import IssueBoardFilteredSearch from 'ee_else_ce/boards/components/issue_board_filtered_search.vue';
import store from '~/boards/stores';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { queryToObject } from '~/lib/utils/url_utility';
-export default (apolloProvider) => {
+export default (apolloProvider, isSignedIn) => {
const el = document.getElementById('js-issue-board-filtered-search');
const rawFilterParams = queryToObject(window.location.search, { gatherArrays: true });
@@ -20,6 +20,7 @@ export default (apolloProvider) => {
el,
provide: {
initialFilterParams,
+ isSignedIn,
},
store, // TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/324094
apolloProvider,
diff --git a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
index a3a8ad06c43..ed32579a9c3 100644
--- a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
+++ b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
@@ -1,23 +1,32 @@
+import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import BoardsSelector from 'ee_else_ce/boards/components/boards_selector.vue';
import store from '~/boards/stores';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
+import introspectionQueryResultData from '~/sidebar/fragmentTypes.json';
Vue.use(VueApollo);
+const fragmentMatcher = new IntrospectionFragmentMatcher({
+ introspectionQueryResultData,
+});
+
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(
{},
{
- assumeImmutableResults: true,
+ cacheConfig: {
+ fragmentMatcher,
+ },
},
),
});
export default (params = {}) => {
const boardsSwitcherElement = document.getElementById('js-multiple-boards-switcher');
+ const { dataset } = boardsSwitcherElement;
return new Vue({
el: boardsSwitcherElement,
components: {
@@ -29,18 +38,16 @@ export default (params = {}) => {
fullPath: params.fullPath,
rootPath: params.rootPath,
recentBoardsEndpoint: params.recentBoardsEndpoint,
+ allowScopedLabels: params.allowScopedLabels,
+ labelsManagePath: params.labelsManagePath,
+ allowLabelCreate: parseBoolean(dataset.canAdminBoard),
},
data() {
- const { dataset } = boardsSwitcherElement;
-
const boardsSelectorProps = {
...dataset,
- currentBoard: JSON.parse(dataset.currentBoard),
hasMissingBoards: parseBoolean(dataset.hasMissingBoards),
canAdminBoard: parseBoolean(dataset.canAdminBoard),
multipleIssueBoardsAvailable: parseBoolean(dataset.multipleIssueBoardsAvailable),
- projectId: dataset.projectId ? Number(dataset.projectId) : 0,
- groupId: Number(dataset.groupId),
scopedIssueBoardFeatureEnabled: parseBoolean(dataset.scopedIssueBoardFeatureEnabled),
weights: JSON.parse(dataset.weights),
};
diff --git a/app/assets/javascripts/boards/new_board.js b/app/assets/javascripts/boards/new_board.js
new file mode 100644
index 00000000000..34f2fea79a9
--- /dev/null
+++ b/app/assets/javascripts/boards/new_board.js
@@ -0,0 +1,29 @@
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import { getExperimentVariant } from '~/experimentation/utils';
+import { CANDIDATE_VARIANT } from '~/experimentation/constants';
+import NewBoardButton from './components/new_board_button.vue';
+
+export default () => {
+ if (getExperimentVariant('prominent_create_board_btn') !== CANDIDATE_VARIANT) {
+ return;
+ }
+
+ const el = document.querySelector('.js-new-board');
+
+ if (!el) {
+ return;
+ }
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ provide: {
+ multipleIssueBoardsAvailable: parseBoolean(el.dataset.multipleIssueBoardsAvailable),
+ canAdminBoard: parseBoolean(el.dataset.canAdminBoard),
+ },
+ render(h) {
+ return h(NewBoardButton);
+ },
+ });
+};
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index ca993e75cf9..3a96e535cf7 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -36,13 +36,11 @@ import {
} from '../boards_util';
import { gqlClient } from '../graphql';
import boardLabelsQuery from '../graphql/board_labels.query.graphql';
-import groupBoardIterationsQuery from '../graphql/group_board_iterations.query.graphql';
import groupBoardMilestonesQuery from '../graphql/group_board_milestones.query.graphql';
import groupProjectsQuery from '../graphql/group_projects.query.graphql';
import issueCreateMutation from '../graphql/issue_create.mutation.graphql';
import issueSetLabelsMutation from '../graphql/issue_set_labels.mutation.graphql';
import listsIssuesQuery from '../graphql/lists_issues.query.graphql';
-import projectBoardIterationsQuery from '../graphql/project_board_iterations.query.graphql';
import projectBoardMilestonesQuery from '../graphql/project_board_milestones.query.graphql';
import * as types from './mutation_types';
@@ -203,52 +201,6 @@ export default {
});
},
- fetchIterations({ state, commit }, title) {
- commit(types.RECEIVE_ITERATIONS_REQUEST);
-
- const { fullPath, boardType } = state;
-
- const variables = {
- fullPath,
- title,
- };
-
- let query;
- if (boardType === BoardType.project) {
- query = projectBoardIterationsQuery;
- }
- if (boardType === BoardType.group) {
- query = groupBoardIterationsQuery;
- }
-
- if (!query) {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- throw new Error('Unknown board type');
- }
-
- return gqlClient
- .query({
- query,
- variables,
- })
- .then(({ data }) => {
- const errors = data[boardType]?.errors;
- const iterations = data[boardType]?.iterations.nodes;
-
- if (errors?.[0]) {
- throw new Error(errors[0]);
- }
-
- commit(types.RECEIVE_ITERATIONS_SUCCESS, iterations);
-
- return iterations;
- })
- .catch((e) => {
- commit(types.RECEIVE_ITERATIONS_FAILURE);
- throw e;
- });
- },
-
fetchMilestones({ state, commit }, searchTerm) {
commit(types.RECEIVE_MILESTONES_REQUEST);
@@ -656,30 +608,45 @@ export default {
},
setActiveIssueLabels: async ({ commit, getters }, input) => {
- commit(types.SET_LABELS_LOADING, true);
const { activeBoardItem } = getters;
- const { data } = await gqlClient.mutate({
- mutation: issueSetLabelsMutation,
- variables: {
- input: {
- iid: input.iid || String(activeBoardItem.iid),
- addLabelIds: input.addLabelIds ?? [],
- removeLabelIds: input.removeLabelIds ?? [],
- projectPath: input.projectPath,
+
+ if (!gon.features?.labelsWidget) {
+ const { data } = await gqlClient.mutate({
+ mutation: issueSetLabelsMutation,
+ variables: {
+ input: {
+ iid: input.iid || String(activeBoardItem.iid),
+ labelIds: input.labelsId ?? undefined,
+ addLabelIds: input.addLabelIds ?? [],
+ removeLabelIds: input.removeLabelIds ?? [],
+ projectPath: input.projectPath,
+ },
},
- },
- });
+ });
- commit(types.SET_LABELS_LOADING, false);
+ if (data.updateIssue?.errors?.length > 0) {
+ throw new Error(data.updateIssue.errors);
+ }
+
+ commit(types.UPDATE_BOARD_ITEM_BY_ID, {
+ itemId: data.updateIssue?.issue?.id || activeBoardItem.id,
+ prop: 'labels',
+ value: data.updateIssue?.issue?.labels.nodes,
+ });
- if (data.updateIssue?.errors?.length > 0) {
- throw new Error(data.updateIssue.errors);
+ return;
}
+ let labels = input?.labels || [];
+ if (input.removeLabelIds) {
+ labels = activeBoardItem.labels.filter(
+ (label) => input.removeLabelIds[0] !== getIdFromGraphQLId(label.id),
+ );
+ }
commit(types.UPDATE_BOARD_ITEM_BY_ID, {
- itemId: data.updateIssue?.issue?.id || activeBoardItem.id,
+ itemId: input.id || activeBoardItem.id,
prop: 'labels',
- value: data.updateIssue.issue.labels.nodes,
+ value: labels,
});
},
diff --git a/app/assets/javascripts/boards/stores/mutation_types.js b/app/assets/javascripts/boards/stores/mutation_types.js
index 26b785932bb..31b78014525 100644
--- a/app/assets/javascripts/boards/stores/mutation_types.js
+++ b/app/assets/javascripts/boards/stores/mutation_types.js
@@ -28,7 +28,6 @@ export const ADD_BOARD_ITEM_TO_LIST = 'ADD_BOARD_ITEM_TO_LIST';
export const REMOVE_BOARD_ITEM_FROM_LIST = 'REMOVE_BOARD_ITEM_FROM_LIST';
export const SET_ACTIVE_ID = 'SET_ACTIVE_ID';
export const UPDATE_BOARD_ITEM_BY_ID = 'UPDATE_BOARD_ITEM_BY_ID';
-export const SET_LABELS_LOADING = 'SET_LABELS_LOADING';
export const SET_ASSIGNEE_LOADING = 'SET_ASSIGNEE_LOADING';
export const RESET_ISSUES = 'RESET_ISSUES';
export const REQUEST_GROUP_PROJECTS = 'REQUEST_GROUP_PROJECTS';
@@ -42,7 +41,3 @@ export const ADD_LIST_TO_HIGHLIGHTED_LISTS = 'ADD_LIST_TO_HIGHLIGHTED_LISTS';
export const REMOVE_LIST_FROM_HIGHLIGHTED_LISTS = 'REMOVE_LIST_FROM_HIGHLIGHTED_LISTS';
export const RESET_BOARD_ITEM_SELECTION = 'RESET_BOARD_ITEM_SELECTION';
export const SET_ERROR = 'SET_ERROR';
-
-export const RECEIVE_ITERATIONS_REQUEST = 'RECEIVE_ITERATIONS_REQUEST';
-export const RECEIVE_ITERATIONS_SUCCESS = 'RECEIVE_ITERATIONS_SUCCESS';
-export const RECEIVE_ITERATIONS_FAILURE = 'RECEIVE_ITERATIONS_FAILURE';
diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js
index d381c076c19..2a2ce7652e6 100644
--- a/app/assets/javascripts/boards/stores/mutations.js
+++ b/app/assets/javascripts/boards/stores/mutations.js
@@ -64,20 +64,6 @@ export default {
);
},
- [mutationTypes.RECEIVE_ITERATIONS_REQUEST](state) {
- state.iterationsLoading = true;
- },
-
- [mutationTypes.RECEIVE_ITERATIONS_SUCCESS](state, iterations) {
- state.iterations = iterations;
- state.iterationsLoading = false;
- },
-
- [mutationTypes.RECEIVE_ITERATIONS_FAILURE](state) {
- state.iterationsLoading = false;
- state.error = __('Failed to load iterations.');
- },
-
[mutationTypes.SET_ACTIVE_ID](state, { id, sidebarType }) {
state.activeId = id;
state.sidebarType = sidebarType;
@@ -195,10 +181,6 @@ export default {
Vue.set(state.boardItems[itemId], prop, value);
},
- [mutationTypes.SET_LABELS_LOADING](state, isLoading) {
- state.isSettingLabels = isLoading;
- },
-
[mutationTypes.SET_ASSIGNEE_LOADING](state, isLoading) {
state.isSettingAssignees = isLoading;
},
diff --git a/app/assets/javascripts/boards/stores/state.js b/app/assets/javascripts/boards/stores/state.js
index 2a6605e687b..80c51c966d2 100644
--- a/app/assets/javascripts/boards/stores/state.js
+++ b/app/assets/javascripts/boards/stores/state.js
@@ -12,7 +12,6 @@ export default () => ({
listsFlags: {},
boardItemsByListId: {},
backupItemsList: [],
- isSettingLabels: false,
isSettingAssignees: false,
pageInfoByListId: {},
boardItems: {},
diff --git a/app/assets/javascripts/breadcrumb.js b/app/assets/javascripts/breadcrumb.js
index b8b8a0b2867..b9d3742974c 100644
--- a/app/assets/javascripts/breadcrumb.js
+++ b/app/assets/javascripts/breadcrumb.js
@@ -1,5 +1,4 @@
import $ from 'jquery';
-import { hide } from '~/tooltips';
export const addTooltipToEl = (el) => {
const textEl = el.querySelector('.js-breadcrumb-item-text');
@@ -19,16 +18,23 @@ export default () => {
.filter((el) => !el.classList.contains('dropdown'))
.map((el) => el.querySelector('a'))
.filter((el) => el);
- const $expander = $('.js-breadcrumbs-collapsed-expander');
+ const $expanderBtn = $('.js-breadcrumbs-collapsed-expander');
topLevelLinks.forEach((el) => addTooltipToEl(el));
- $expander.closest('.dropdown').on('show.bs.dropdown hide.bs.dropdown', (e) => {
- const $el = $('.js-breadcrumbs-collapsed-expander', e.currentTarget);
+ $expanderBtn.on('click', () => {
+ const detailItems = $('.breadcrumbs-detail-item');
+ const hiddenClass = 'gl-display-none!';
- $el.toggleClass('open');
+ $.each(detailItems, (_key, item) => {
+ $(item).toggleClass(hiddenClass);
+ });
- hide($el);
+ // remove the ellipsis
+ $('li.expander').remove();
+
+ // set focus on first breadcrumb item
+ $('.breadcrumb-item-text').first().focus();
});
}
};
diff --git a/app/assets/javascripts/chronic_duration.js b/app/assets/javascripts/chronic_duration.js
new file mode 100644
index 00000000000..1073d736b06
--- /dev/null
+++ b/app/assets/javascripts/chronic_duration.js
@@ -0,0 +1,417 @@
+/*
+ * NOTE:
+ * Changes to this file should be kept in sync with
+ * https://gitlab.com/gitlab-org/gitlab-chronic-duration/-/blob/master/lib/gitlab_chronic_duration.rb.
+ */
+
+/*
+ * This code is based on code from
+ * https://gitlab.com/gitlab-org/gitlab-chronic-duration and is
+ * distributed under the following license:
+ *
+ * MIT License
+ *
+ * Copyright (c) Henry Poydar
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+export class DurationParseError extends Error {}
+
+// On average, there's a little over 4 weeks in month.
+const FULL_WEEKS_PER_MONTH = 4;
+
+const HOURS_PER_DAY = 24;
+const DAYS_PER_MONTH = 30;
+
+const FLOAT_MATCHER = /[0-9]*\.?[0-9]+/g;
+const DURATION_UNITS_LIST = ['seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'years'];
+
+const MAPPINGS = {
+ seconds: 'seconds',
+ second: 'seconds',
+ secs: 'seconds',
+ sec: 'seconds',
+ s: 'seconds',
+ minutes: 'minutes',
+ minute: 'minutes',
+ mins: 'minutes',
+ min: 'minutes',
+ m: 'minutes',
+ hours: 'hours',
+ hour: 'hours',
+ hrs: 'hours',
+ hr: 'hours',
+ h: 'hours',
+ days: 'days',
+ day: 'days',
+ dy: 'days',
+ d: 'days',
+ weeks: 'weeks',
+ week: 'weeks',
+ wks: 'weeks',
+ wk: 'weeks',
+ w: 'weeks',
+ months: 'months',
+ mo: 'months',
+ mos: 'months',
+ month: 'months',
+ years: 'years',
+ year: 'years',
+ yrs: 'years',
+ yr: 'years',
+ y: 'years',
+};
+
+const JOIN_WORDS = ['and', 'with', 'plus'];
+
+function convertToNumber(string) {
+ const f = parseFloat(string);
+ return f % 1 > 0 ? f : parseInt(string, 10);
+}
+
+function durationUnitsSecondsMultiplier(unit, opts) {
+ if (!DURATION_UNITS_LIST.includes(unit)) {
+ return 0;
+ }
+
+ const hoursPerDay = opts.hoursPerDay || HOURS_PER_DAY;
+ const daysPerMonth = opts.daysPerMonth || DAYS_PER_MONTH;
+ const daysPerWeek = Math.trunc(daysPerMonth / FULL_WEEKS_PER_MONTH);
+
+ switch (unit) {
+ case 'years':
+ return 31557600;
+ case 'months':
+ return 3600 * hoursPerDay * daysPerMonth;
+ case 'weeks':
+ return 3600 * hoursPerDay * daysPerWeek;
+ case 'days':
+ return 3600 * hoursPerDay;
+ case 'hours':
+ return 3600;
+ case 'minutes':
+ return 60;
+ case 'seconds':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+function calculateFromWords(string, opts) {
+ let val = 0;
+ const words = string.split(' ');
+ words.forEach((v, k) => {
+ if (v === '') {
+ return;
+ }
+ if (v.search(FLOAT_MATCHER) >= 0) {
+ val +=
+ convertToNumber(v) *
+ durationUnitsSecondsMultiplier(
+ words[parseInt(k, 10) + 1] || opts.defaultUnit || 'seconds',
+ opts,
+ );
+ }
+ });
+ return val;
+}
+
+// Parse 3:41:59 and return 3 hours 41 minutes 59 seconds
+function filterByType(string) {
+ const chronoUnitsList = DURATION_UNITS_LIST.filter((v) => v !== 'weeks');
+ if (
+ string
+ .replace(/ +/g, '')
+ .search(RegExp(`${FLOAT_MATCHER.source}(:${FLOAT_MATCHER.source})+`, 'g')) >= 0
+ ) {
+ const res = [];
+ string
+ .replace(/ +/g, '')
+ .split(':')
+ .reverse()
+ .forEach((v, k) => {
+ if (!chronoUnitsList[k]) {
+ return;
+ }
+ res.push(`${v} ${chronoUnitsList[k]}`);
+ });
+ return res.reverse().join(' ');
+ }
+ return string;
+}
+
+// Get rid of unknown words and map found
+// words to defined time units
+function filterThroughWhiteList(string, opts) {
+ const res = [];
+ string.split(' ').forEach((word) => {
+ if (word === '') {
+ return;
+ }
+ if (word.search(FLOAT_MATCHER) >= 0) {
+ res.push(word.trim());
+ return;
+ }
+ const strippedWord = word.trim().replace(/^,/g, '').replace(/,$/g, '');
+ if (MAPPINGS[strippedWord] !== undefined) {
+ res.push(MAPPINGS[strippedWord]);
+ } else if (!JOIN_WORDS.includes(strippedWord) && opts.raiseExceptions) {
+ throw new DurationParseError(
+ `An invalid word ${JSON.stringify(word)} was used in the string to be parsed.`,
+ );
+ }
+ });
+ // add '1' at front if string starts with something recognizable but not with a number, like 'day' or 'minute 30sec'
+ if (res.length > 0 && MAPPINGS[res[0]]) {
+ res.splice(0, 0, 1);
+ }
+ return res.join(' ');
+}
+
+function cleanup(string, opts) {
+ let res = string.toLowerCase();
+ /*
+ * TODO The Ruby implementation of this algorithm uses the Numerizer module,
+ * which converts strings like "forty two" to "42", but there is no
+ * JavaScript equivalent of Numerizer. Skip it for now until Numerizer is
+ * ported to JavaScript.
+ */
+ res = filterByType(res);
+ res = res
+ .replace(FLOAT_MATCHER, (n) => ` ${n} `)
+ .replace(/ +/g, ' ')
+ .trim();
+ return filterThroughWhiteList(res, opts);
+}
+
+function humanizeTimeUnit(number, unit, pluralize, keepZero) {
+ if (number === '0' && !keepZero) {
+ return null;
+ }
+ let res = number + unit;
+ // A poor man's pluralizer
+ if (number !== '1' && pluralize) {
+ res += 's';
+ }
+ return res;
+}
+
+// Given a string representation of elapsed time,
+// return an integer (or float, if fractions of a
+// second are input)
+export function parseChronicDuration(string, opts = {}) {
+ const result = calculateFromWords(cleanup(string, opts), opts);
+ return !opts.keepZero && result === 0 ? null : result;
+}
+
+// Given an integer and an optional format,
+// returns a formatted string representing elapsed time
+export function outputChronicDuration(seconds, opts = {}) {
+ const units = {
+ years: 0,
+ months: 0,
+ weeks: 0,
+ days: 0,
+ hours: 0,
+ minutes: 0,
+ seconds,
+ };
+
+ const hoursPerDay = opts.hoursPerDay || HOURS_PER_DAY;
+ const daysPerMonth = opts.daysPerMonth || DAYS_PER_MONTH;
+ const daysPerWeek = Math.trunc(daysPerMonth / FULL_WEEKS_PER_MONTH);
+
+ const decimalPlaces =
+ seconds % 1 !== 0 ? seconds.toString().split('.').reverse()[0].length : null;
+
+ const minute = 60;
+ const hour = 60 * minute;
+ const day = hoursPerDay * hour;
+ const month = daysPerMonth * day;
+ const year = 31557600;
+
+ if (units.seconds >= 31557600 && units.seconds % year < units.seconds % month) {
+ units.years = Math.trunc(units.seconds / year);
+ units.months = Math.trunc((units.seconds % year) / month);
+ units.days = Math.trunc(((units.seconds % year) % month) / day);
+ units.hours = Math.trunc((((units.seconds % year) % month) % day) / hour);
+ units.minutes = Math.trunc(((((units.seconds % year) % month) % day) % hour) / minute);
+ units.seconds = Math.trunc(((((units.seconds % year) % month) % day) % hour) % minute);
+ } else if (seconds >= 60) {
+ units.minutes = Math.trunc(seconds / 60);
+ units.seconds %= 60;
+ if (units.minutes >= 60) {
+ units.hours = Math.trunc(units.minutes / 60);
+ units.minutes = Math.trunc(units.minutes % 60);
+ if (!opts.limitToHours) {
+ if (units.hours >= hoursPerDay) {
+ units.days = Math.trunc(units.hours / hoursPerDay);
+ units.hours = Math.trunc(units.hours % hoursPerDay);
+ if (opts.weeks) {
+ if (units.days >= daysPerWeek) {
+ units.weeks = Math.trunc(units.days / daysPerWeek);
+ units.days = Math.trunc(units.days % daysPerWeek);
+ if (units.weeks >= FULL_WEEKS_PER_MONTH) {
+ units.months = Math.trunc(units.weeks / FULL_WEEKS_PER_MONTH);
+ units.weeks = Math.trunc(units.weeks % FULL_WEEKS_PER_MONTH);
+ }
+ }
+ } else if (units.days >= daysPerMonth) {
+ units.months = Math.trunc(units.days / daysPerMonth);
+ units.days = Math.trunc(units.days % daysPerMonth);
+ }
+ }
+ }
+ }
+ }
+
+ let joiner = opts.joiner || ' ';
+ let process = null;
+
+ let dividers;
+ switch (opts.format) {
+ case 'micro':
+ dividers = {
+ years: 'y',
+ months: 'mo',
+ weeks: 'w',
+ days: 'd',
+ hours: 'h',
+ minutes: 'm',
+ seconds: 's',
+ };
+ joiner = '';
+ break;
+ case 'short':
+ dividers = {
+ years: 'y',
+ months: 'mo',
+ weeks: 'w',
+ days: 'd',
+ hours: 'h',
+ minutes: 'm',
+ seconds: 's',
+ };
+ break;
+ case 'long':
+ dividers = {
+ /* eslint-disable @gitlab/require-i18n-strings */
+ years: ' year',
+ months: ' month',
+ weeks: ' week',
+ days: ' day',
+ hours: ' hour',
+ minutes: ' minute',
+ seconds: ' second',
+ /* eslint-enable @gitlab/require-i18n-strings */
+ pluralize: true,
+ };
+ break;
+ case 'chrono':
+ dividers = {
+ years: ':',
+ months: ':',
+ weeks: ':',
+ days: ':',
+ hours: ':',
+ minutes: ':',
+ seconds: ':',
+ keepZero: true,
+ };
+ process = (str) => {
+ // Pad zeros
+ // Get rid of lead off times if they are zero
+ // Get rid of lead off zero
+ // Get rid of trailing:
+ const divider = ':';
+ const processed = [];
+ str.split(divider).forEach((n) => {
+ if (n === '') {
+ return;
+ }
+ // add zeros only if n is an integer
+ if (n.search('\\.') >= 0) {
+ processed.push(
+ parseFloat(n)
+ .toFixed(decimalPlaces)
+ .padStart(3 + decimalPlaces, '0'),
+ );
+ } else {
+ processed.push(n.padStart(2, '0'));
+ }
+ });
+ return processed
+ .join(divider)
+ .replace(/^(00:)+/g, '')
+ .replace(/^0/g, '')
+ .replace(/:$/g, '');
+ };
+ joiner = '';
+ break;
+ default:
+ dividers = {
+ /* eslint-disable @gitlab/require-i18n-strings */
+ years: ' yr',
+ months: ' mo',
+ weeks: ' wk',
+ days: ' day',
+ hours: ' hr',
+ minutes: ' min',
+ seconds: ' sec',
+ /* eslint-enable @gitlab/require-i18n-strings */
+ pluralize: true,
+ };
+ break;
+ }
+
+ let result = [];
+ ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds'].forEach((t) => {
+ if (t === 'weeks' && !opts.weeks) {
+ return;
+ }
+ let num = units[t];
+ if (t === 'seconds' && num % 0 !== 0) {
+ num = num.toFixed(decimalPlaces);
+ } else {
+ num = num.toString();
+ }
+ const keepZero = !dividers.keepZero && t === 'seconds' ? opts.keepZero : dividers.keepZero;
+ const humanized = humanizeTimeUnit(num, dividers[t], dividers.pluralize, keepZero);
+ if (humanized !== null) {
+ result.push(humanized);
+ }
+ });
+
+ if (opts.units) {
+ result = result.slice(0, opts.units);
+ }
+
+ result = result.join(joiner);
+
+ if (process) {
+ result = process(result);
+ }
+
+ return result.length === 0 ? null : result;
+}
diff --git a/app/assets/javascripts/ci_lint/index.js b/app/assets/javascripts/ci_lint/index.js
index f97590ec5db..274aab45deb 100644
--- a/app/assets/javascripts/ci_lint/index.js
+++ b/app/assets/javascripts/ci_lint/index.js
@@ -8,9 +8,7 @@ import CiLint from './components/ci_lint.vue';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(resolvers, {
- assumeImmutableResults: true,
- }),
+ defaultClient: createDefaultClient(resolvers),
});
export default (containerId = '#js-ci-lint') => {
diff --git a/app/assets/javascripts/clusters/agents/components/show.vue b/app/assets/javascripts/clusters/agents/components/show.vue
index 5c672d288c5..afbba9d1f7c 100644
--- a/app/assets/javascripts/clusters/agents/components/show.vue
+++ b/app/assets/javascripts/clusters/agents/components/show.vue
@@ -128,6 +128,7 @@ export default {
</p>
<gl-tabs>
+ <slot name="ee-security-tab"></slot>
<gl-tab>
<template #title>
<span data-testid="cluster-agent-token-count">
diff --git a/app/assets/javascripts/clusters/agents/index.js b/app/assets/javascripts/clusters/agents/index.js
index bcb5b271203..426d8d83847 100644
--- a/app/assets/javascripts/clusters/agents/index.js
+++ b/app/assets/javascripts/clusters/agents/index.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
-import AgentShowPage from './components/show.vue';
+import AgentShowPage from 'ee_else_ce/clusters/agents/components/show.vue';
Vue.use(VueApollo);
diff --git a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
index 0da7be4040f..98db620e3ab 100644
--- a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
+++ b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
@@ -1,8 +1,7 @@
<script>
-import { GlModal, GlButton, GlFormInput } from '@gitlab/ui';
-import { escape } from 'lodash';
+import { GlModal, GlButton, GlFormInput, GlSprintf } from '@gitlab/ui';
import csrf from '~/lib/utils/csrf';
-import { s__, sprintf } from '~/locale';
+import { s__ } from '~/locale';
import SplitButton from '~/vue_shared/components/split_button.vue';
const splitButtonActionItems = [
@@ -29,6 +28,7 @@ export default {
GlModal,
GlButton,
GlFormInput,
+ GlSprintf,
},
props: {
clusterPath: {
@@ -67,17 +67,11 @@ export default {
: s__('ClusterIntegration|You are about to remove your cluster integration.');
},
confirmationTextLabel() {
- return sprintf(
- this.confirmCleanup
- ? s__(
- 'ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:',
- )
- : s__('ClusterIntegration|To remove your integration, type %{clusterName} to confirm:'),
- {
- clusterName: `<code>${escape(this.clusterName)}</code>`,
- },
- false,
- );
+ return this.confirmCleanup
+ ? s__(
+ 'ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:',
+ )
+ : s__('ClusterIntegration|To remove your integration, type %{clusterName} to confirm:');
},
canSubmit() {
return this.enteredClusterName === this.clusterName;
@@ -140,7 +134,13 @@ export default {
<!-- eslint-enable @gitlab/vue-require-i18n-strings -->
</ul>
</div>
- <strong v-html="confirmationTextLabel /* eslint-disable-line vue/no-v-html */"></strong>
+ <strong>
+ <gl-sprintf :message="confirmationTextLabel">
+ <template #clusterName>
+ <code>{{ clusterName }}</code>
+ </template>
+ </gl-sprintf>
+ </strong>
<form ref="form" :action="clusterPath" method="post" class="gl-mb-5">
<input ref="method" type="hidden" name="_method" value="delete" />
<input :value="csrfToken" type="hidden" name="authenticity_token" />
@@ -159,7 +159,7 @@ export default {
)
}}</span>
<template #modal-footer>
- <gl-button variant="secondary" @click="handleCancel">{{ s__('Cancel') }}</gl-button>
+ <gl-button variant="secondary" @click="handleCancel">{{ __('Cancel') }}</gl-button>
<template v-if="confirmCleanup">
<gl-button
:disabled="!canSubmit"
diff --git a/app/assets/javascripts/clusters_list/clusters_util.js b/app/assets/javascripts/clusters_list/clusters_util.js
index 9b870134512..c78c93fe1ba 100644
--- a/app/assets/javascripts/clusters_list/clusters_util.js
+++ b/app/assets/javascripts/clusters_list/clusters_util.js
@@ -6,3 +6,7 @@ export function generateAgentRegistrationCommand(agentToken, kasAddress) {
--agent-version stable \\
--namespace gitlab-kubernetes-agent | kubectl apply -f -`;
}
+
+export function getAgentConfigPath(clusterAgentName) {
+ return `.gitlab/agents/${clusterAgentName}`;
+}
diff --git a/app/assets/javascripts/clusters_list/components/agent_empty_state.vue b/app/assets/javascripts/clusters_list/components/agent_empty_state.vue
index 405339b3d36..af44a23b4b3 100644
--- a/app/assets/javascripts/clusters_list/components/agent_empty_state.vue
+++ b/app/assets/javascripts/clusters_list/components/agent_empty_state.vue
@@ -1,9 +1,16 @@
<script>
import { GlButton, GlEmptyState, GlLink, GlSprintf, GlAlert, GlModalDirective } from '@gitlab/ui';
-import { INSTALL_AGENT_MODAL_ID } from '../constants';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import { INSTALL_AGENT_MODAL_ID, I18N_AGENTS_EMPTY_STATE } from '../constants';
export default {
+ i18n: I18N_AGENTS_EMPTY_STATE,
modalId: INSTALL_AGENT_MODAL_ID,
+ multipleClustersDocsUrl: helpPagePath('user/project/clusters/multiple_kubernetes_clusters'),
+ installDocsUrl: helpPagePath('administration/clusters/kas'),
+ getStartedDocsUrl: helpPagePath('user/clusters/agent/index', {
+ anchor: 'define-a-configuration-repository',
+ }),
components: {
GlButton,
GlEmptyState,
@@ -14,19 +21,17 @@ export default {
directives: {
GlModalDirective,
},
- inject: [
- 'emptyStateImage',
- 'projectPath',
- 'agentDocsUrl',
- 'installDocsUrl',
- 'getStartedDocsUrl',
- 'integrationDocsUrl',
- ],
+ inject: ['emptyStateImage', 'projectPath'],
props: {
hasConfigurations: {
type: Boolean,
required: true,
},
+ isChildComponent: {
+ default: false,
+ required: false,
+ type: Boolean,
+ },
},
computed: {
repositoryPath() {
@@ -37,22 +42,19 @@ export default {
</script>
<template>
- <gl-empty-state
- :svg-path="emptyStateImage"
- :title="s__('ClusterAgents|Integrate Kubernetes with a GitLab Agent')"
- class="empty-state--agent"
- >
+ <gl-empty-state :svg-path="emptyStateImage" title="" class="agents-empty-state">
<template #description>
- <p class="mw-460 gl-mx-auto">
- <gl-sprintf
- :message="
- s__(
- 'ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}',
- )
- "
- >
+ <p class="mw-460 gl-mx-auto gl-text-left">
+ {{ $options.i18n.introText }}
+ </p>
+ <p class="mw-460 gl-mx-auto gl-text-left">
+ <gl-sprintf :message="$options.i18n.multipleClustersText">
<template #link="{ content }">
- <gl-link :href="agentDocsUrl" target="_blank" data-testid="agent-docs-link">
+ <gl-link
+ :href="$options.multipleClustersDocsUrl"
+ target="_blank"
+ data-testid="multiple-clusters-docs-link"
+ >
{{ content }}
</gl-link>
</template>
@@ -60,19 +62,9 @@ export default {
</p>
<p class="mw-460 gl-mx-auto">
- <gl-sprintf
- :message="
- s__(
- 'ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}',
- )
- "
- >
- <template #link="{ content }">
- <gl-link :href="installDocsUrl" target="_blank" data-testid="install-docs-link">
- {{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
+ <gl-link :href="$options.installDocsUrl" target="_blank" data-testid="install-docs-link">
+ {{ $options.i18n.learnMoreText }}
+ </gl-link>
</p>
<gl-alert
@@ -81,24 +73,20 @@ export default {
class="gl-mb-5 text-left"
:dismissible="false"
>
- {{
- s__(
- 'ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process.',
- )
- }}
+ {{ $options.i18n.warningText }}
<template #actions>
<gl-button
category="primary"
variant="info"
- :href="getStartedDocsUrl"
+ :href="$options.getStartedDocsUrl"
target="_blank"
class="gl-ml-0!"
>
- {{ s__('ClusterAgents|Read more about getting started') }}
+ {{ $options.i18n.readMoreText }}
</gl-button>
<gl-button category="secondary" variant="info" :href="repositoryPath">
- {{ s__('ClusterAgents|Go to the repository') }}
+ {{ $options.i18n.repositoryButtonText }}
</gl-button>
</template>
</gl-alert>
@@ -106,13 +94,14 @@ export default {
<template #actions>
<gl-button
+ v-if="!isChildComponent"
v-gl-modal-directive="$options.modalId"
:disabled="!hasConfigurations"
data-testid="integration-primary-button"
category="primary"
- variant="success"
+ variant="confirm"
>
- {{ s__('ClusterAgents|Integrate with the GitLab Agent') }}
+ {{ $options.i18n.primaryButtonText }}
</gl-button>
</template>
</gl-empty-state>
diff --git a/app/assets/javascripts/clusters_list/components/agent_table.vue b/app/assets/javascripts/clusters_list/components/agent_table.vue
index 487e512c06d..000730ac1ba 100644
--- a/app/assets/javascripts/clusters_list/components/agent_table.vue
+++ b/app/assets/javascripts/clusters_list/components/agent_table.vue
@@ -1,6 +1,5 @@
<script>
import {
- GlButton,
GlLink,
GlModalDirective,
GlTable,
@@ -12,11 +11,12 @@ import {
import { s__ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
-import { INSTALL_AGENT_MODAL_ID, AGENT_STATUSES, TROUBLESHOOTING_LINK } from '../constants';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import { INSTALL_AGENT_MODAL_ID, AGENT_STATUSES } from '../constants';
+import { getAgentConfigPath } from '../clusters_util';
export default {
components: {
- GlButton,
GlLink,
GlTable,
GlIcon,
@@ -29,10 +29,12 @@ export default {
GlModalDirective,
},
mixins: [timeagoMixin],
- inject: ['integrationDocsUrl'],
INSTALL_AGENT_MODAL_ID,
AGENT_STATUSES,
- TROUBLESHOOTING_LINK,
+
+ troubleshooting_link: helpPagePath('user/clusters/agent/index', {
+ anchor: 'troubleshooting',
+ }),
props: {
agents: {
required: true,
@@ -41,112 +43,102 @@ export default {
},
computed: {
fields() {
+ const tdClass = 'gl-py-5!';
return [
{
key: 'name',
label: s__('ClusterAgents|Name'),
+ tdClass,
},
{
key: 'status',
label: s__('ClusterAgents|Connection status'),
+ tdClass,
},
{
key: 'lastContact',
label: s__('ClusterAgents|Last contact'),
+ tdClass,
},
{
key: 'configuration',
label: s__('ClusterAgents|Configuration'),
+ tdClass,
},
];
},
},
+ methods: {
+ getCellId(item) {
+ return `connection-status-${item.name}`;
+ },
+ getAgentConfigPath,
+ },
};
</script>
<template>
- <div>
- <div class="gl-display-block gl-text-right gl-my-3">
- <gl-button
- v-gl-modal-directive="$options.INSTALL_AGENT_MODAL_ID"
- variant="confirm"
- category="primary"
- >{{ s__('ClusterAgents|Install a new GitLab Agent') }}
- </gl-button>
- </div>
+ <gl-table
+ :items="agents"
+ :fields="fields"
+ stacked="md"
+ head-variant="white"
+ thead-class="gl-border-b-solid gl-border-b-2 gl-border-b-gray-100"
+ class="gl-mb-4!"
+ data-testid="cluster-agent-list-table"
+ >
+ <template #cell(name)="{ item }">
+ <gl-link :href="item.webPath" data-testid="cluster-agent-name-link">
+ {{ item.name }}
+ </gl-link>
+ </template>
- <gl-table
- :items="agents"
- :fields="fields"
- stacked="md"
- head-variant="white"
- thead-class="gl-border-b-solid gl-border-b-1 gl-border-b-gray-100"
- data-testid="cluster-agent-list-table"
- >
- <template #cell(name)="{ item }">
- <gl-link :href="item.webPath" data-testid="cluster-agent-name-link">
- {{ item.name }}
- </gl-link>
- </template>
-
- <template #cell(status)="{ item }">
- <span
- :id="`connection-status-${item.name}`"
- class="gl-pr-5"
- data-testid="cluster-agent-connection-status"
- >
- <span :class="$options.AGENT_STATUSES[item.status].class" class="gl-mr-3">
- <gl-icon :name="$options.AGENT_STATUSES[item.status].icon" :size="12" /></span
- >{{ $options.AGENT_STATUSES[item.status].name }}
- </span>
- <gl-tooltip
- v-if="item.status === 'active'"
- :target="`connection-status-${item.name}`"
- placement="right"
- >
- <gl-sprintf :message="$options.AGENT_STATUSES[item.status].tooltip.title"
- ><template #timeAgo>{{ timeFormatted(item.lastContact) }}</template>
- </gl-sprintf>
- </gl-tooltip>
- <gl-popover
- v-else
- :target="`connection-status-${item.name}`"
- :title="$options.AGENT_STATUSES[item.status].tooltip.title"
- placement="right"
- container="viewport"
- >
- <p>
- <gl-sprintf :message="$options.AGENT_STATUSES[item.status].tooltip.body"
- ><template #timeAgo>{{ timeFormatted(item.lastContact) }}</template></gl-sprintf
- >
- </p>
- <p class="gl-mb-0">
- {{ s__('ClusterAgents|For more troubleshooting information go to') }}
- <gl-link :href="$options.TROUBLESHOOTING_LINK" target="_blank" class="gl-font-sm">
- {{ $options.TROUBLESHOOTING_LINK }}</gl-link
- >
- </p>
- </gl-popover>
- </template>
+ <template #cell(status)="{ item }">
+ <span :id="getCellId(item)" class="gl-md-pr-5" data-testid="cluster-agent-connection-status">
+ <span :class="$options.AGENT_STATUSES[item.status].class" class="gl-mr-3">
+ <gl-icon :name="$options.AGENT_STATUSES[item.status].icon" :size="12" /></span
+ >{{ $options.AGENT_STATUSES[item.status].name }}
+ </span>
+ <gl-tooltip v-if="item.status === 'active'" :target="getCellId(item)" placement="right">
+ <gl-sprintf :message="$options.AGENT_STATUSES[item.status].tooltip.title"
+ ><template #timeAgo>{{ timeFormatted(item.lastContact) }}</template>
+ </gl-sprintf>
+ </gl-tooltip>
+ <gl-popover
+ v-else
+ :target="getCellId(item)"
+ :title="$options.AGENT_STATUSES[item.status].tooltip.title"
+ placement="right"
+ container="viewport"
+ >
+ <p>
+ <gl-sprintf :message="$options.AGENT_STATUSES[item.status].tooltip.body"
+ ><template #timeAgo>{{ timeFormatted(item.lastContact) }}</template></gl-sprintf
+ >
+ </p>
+ <p class="gl-mb-0">
+ <gl-link :href="$options.troubleshooting_link" target="_blank" class="gl-font-sm">
+ {{ s__('ClusterAgents|Learn how to troubleshoot') }}</gl-link
+ >
+ </p>
+ </gl-popover>
+ </template>
- <template #cell(lastContact)="{ item }">
- <span data-testid="cluster-agent-last-contact">
- <time-ago-tooltip v-if="item.lastContact" :time="item.lastContact" />
- <span v-else>{{ s__('ClusterAgents|Never') }}</span>
- </span>
- </template>
+ <template #cell(lastContact)="{ item }">
+ <span data-testid="cluster-agent-last-contact">
+ <time-ago-tooltip v-if="item.lastContact" :time="item.lastContact" />
+ <span v-else>{{ s__('ClusterAgents|Never') }}</span>
+ </span>
+ </template>
- <template #cell(configuration)="{ item }">
- <span data-testid="cluster-agent-configuration-link">
- <!-- eslint-disable @gitlab/vue-require-i18n-strings -->
- <gl-link v-if="item.configFolder" :href="item.configFolder.webPath">
- .gitlab/agents/{{ item.name }}
- </gl-link>
+ <template #cell(configuration)="{ item }">
+ <span data-testid="cluster-agent-configuration-link">
+ <gl-link v-if="item.configFolder" :href="item.configFolder.webPath">
+ {{ getAgentConfigPath(item.name) }}
+ </gl-link>
- <span v-else>.gitlab/agents/{{ item.name }}</span>
- <!-- eslint-enable @gitlab/vue-require-i18n-strings -->
- </span>
- </template>
- </gl-table>
- </div>
+ <span v-else>{{ getAgentConfigPath(item.name) }}</span>
+ </span>
+ </template>
+ </gl-table>
</template>
diff --git a/app/assets/javascripts/clusters_list/components/agents.vue b/app/assets/javascripts/clusters_list/components/agents.vue
index ed44c1f5fa7..fb5cf7d1206 100644
--- a/app/assets/javascripts/clusters_list/components/agents.vue
+++ b/app/assets/javascripts/clusters_list/components/agents.vue
@@ -4,7 +4,6 @@ import { MAX_LIST_COUNT, ACTIVE_CONNECTION_TIME } from '../constants';
import getAgentsQuery from '../graphql/queries/get_agents.query.graphql';
import AgentEmptyState from './agent_empty_state.vue';
import AgentTable from './agent_table.vue';
-import InstallAgentModal from './install_agent_modal.vue';
export default {
apollo: {
@@ -21,12 +20,14 @@ export default {
this.updateTreeList(data);
return data;
},
+ result() {
+ this.emitAgentsLoaded();
+ },
},
},
components: {
AgentEmptyState,
AgentTable,
- InstallAgentModal,
GlAlert,
GlKeysetPagination,
GlLoadingIcon,
@@ -38,11 +39,21 @@ export default {
required: false,
type: String,
},
+ isChildComponent: {
+ default: false,
+ required: false,
+ type: Boolean,
+ },
+ limit: {
+ default: null,
+ required: false,
+ type: Number,
+ },
},
data() {
return {
cursor: {
- first: MAX_LIST_COUNT,
+ first: this.limit ? this.limit : MAX_LIST_COUNT,
last: null,
},
folderList: {},
@@ -70,7 +81,7 @@ export default {
return this.$apollo.queries.agents.loading;
},
showPagination() {
- return this.agentPageInfo.hasPreviousPage || this.agentPageInfo.hasNextPage;
+ return !this.limit && (this.agentPageInfo.hasPreviousPage || this.agentPageInfo.hasNextPage);
},
treePageInfo() {
return this.agents?.project?.repository?.tree?.trees?.pageInfo || {};
@@ -130,24 +141,31 @@ export default {
}
return 'unused';
},
+ emitAgentsLoaded() {
+ const count = this.agents?.project?.clusterAgents?.count;
+ this.$emit('onAgentsLoad', count);
+ },
},
};
</script>
<template>
- <gl-loading-icon v-if="isLoading" size="md" class="gl-mt-3" />
+ <gl-loading-icon v-if="isLoading" size="md" />
- <section v-else-if="agentList" class="gl-mt-3">
+ <section v-else-if="agentList">
<div v-if="agentList.length">
- <AgentTable :agents="agentList" />
+ <agent-table :agents="agentList" />
<div v-if="showPagination" class="gl-display-flex gl-justify-content-center gl-mt-5">
<gl-keyset-pagination v-bind="agentPageInfo" @prev="prevPage" @next="nextPage" />
</div>
</div>
- <AgentEmptyState v-else :has-configurations="hasConfigurations" />
- <InstallAgentModal @agentRegistered="reloadAgents" />
+ <agent-empty-state
+ v-else
+ :has-configurations="hasConfigurations"
+ :is-child-component="isChildComponent"
+ />
</section>
<gl-alert v-else variant="danger" :dismissible="false">
diff --git a/app/assets/javascripts/clusters_list/components/clusters.vue b/app/assets/javascripts/clusters_list/components/clusters.vue
index 0d1534d20e0..9c330045596 100644
--- a/app/assets/javascripts/clusters_list/components/clusters.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters.vue
@@ -14,6 +14,7 @@ import { __, sprintf } from '~/locale';
import { CLUSTER_TYPES, STATUSES } from '../constants';
import AncestorNotice from './ancestor_notice.vue';
import NodeErrorHelpText from './node_error_help_text.vue';
+import ClustersEmptyState from './clusters_empty_state.vue';
export default {
nodeMemoryText: __('%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} free)'),
@@ -28,10 +29,23 @@ export default {
GlSprintf,
GlTable,
NodeErrorHelpText,
+ ClustersEmptyState,
},
directives: {
GlTooltip: GlTooltipDirective,
},
+ props: {
+ isChildComponent: {
+ default: false,
+ required: false,
+ type: Boolean,
+ },
+ limit: {
+ default: null,
+ required: false,
+ type: Number,
+ },
+ },
computed: {
...mapState([
'clusters',
@@ -40,7 +54,7 @@ export default {
'loadingNodes',
'page',
'providers',
- 'totalCulsters',
+ 'totalClusters',
]),
contentAlignClasses() {
return 'gl-display-flex gl-align-items-center gl-justify-content-end gl-justify-content-md-start';
@@ -55,43 +69,57 @@ export default {
},
},
fields() {
+ const tdClass = 'gl-py-5!';
return [
{
key: 'name',
label: __('Kubernetes cluster'),
+ tdClass,
},
{
key: 'environment_scope',
label: __('Environment scope'),
+ tdClass,
},
{
key: 'node_size',
label: __('Nodes'),
+ tdClass,
},
{
key: 'total_cpu',
label: __('Total cores (CPUs)'),
+ tdClass,
},
{
key: 'total_memory',
label: __('Total memory (GB)'),
+ tdClass,
},
{
key: 'cluster_type',
label: __('Cluster level'),
+ tdClass,
formatter: (value) => CLUSTER_TYPES[value],
},
];
},
- hasClusters() {
+ hasClustersPerPage() {
return this.clustersPerPage > 0;
},
+ hasClusters() {
+ return this.totalClusters > 0;
+ },
},
mounted() {
+ if (this.limit) {
+ this.setClustersPerPage(this.limit);
+ }
+
this.fetchClusters();
},
methods: {
- ...mapActions(['fetchClusters', 'reportSentryError', 'setPage']),
+ ...mapActions(['fetchClusters', 'reportSentryError', 'setPage', 'setClustersPerPage']),
k8sQuantityToGb(quantity) {
if (!quantity) {
return 0;
@@ -196,18 +224,20 @@ export default {
</script>
<template>
- <gl-loading-icon v-if="loadingClusters" size="md" class="gl-mt-3" />
+ <gl-loading-icon v-if="loadingClusters" size="md" />
<section v-else>
<ancestor-notice />
<gl-table
+ v-if="hasClusters"
:items="clusters"
:fields="fields"
+ fixed
stacked="md"
head-variant="white"
- thead-class="gl-border-b-solid gl-border-b-1 gl-border-b-gray-100"
- class="qa-clusters-table"
+ thead-class="gl-border-b-solid gl-border-b-2 gl-border-b-gray-100"
+ class="qa-clusters-table gl-mb-4!"
data-testid="cluster_list_table"
>
<template #cell(name)="{ item }">
@@ -241,7 +271,7 @@ export default {
<gl-skeleton-loading v-else-if="loadingNodes" :lines="1" :class="contentAlignClasses" />
- <NodeErrorHelpText
+ <node-error-help-text
v-else-if="item.kubernetes_errors"
:class="contentAlignClasses"
:error-type="item.kubernetes_errors.connection_error"
@@ -262,7 +292,7 @@ export default {
<gl-skeleton-loading v-else-if="loadingNodes" :lines="1" :class="contentAlignClasses" />
- <NodeErrorHelpText
+ <node-error-help-text
v-else-if="item.kubernetes_errors"
:class="contentAlignClasses"
:error-type="item.kubernetes_errors.node_connection_error"
@@ -283,7 +313,7 @@ export default {
<gl-skeleton-loading v-else-if="loadingNodes" :lines="1" :class="contentAlignClasses" />
- <NodeErrorHelpText
+ <node-error-help-text
v-else-if="item.kubernetes_errors"
:class="contentAlignClasses"
:error-type="item.kubernetes_errors.metrics_connection_error"
@@ -298,11 +328,13 @@ export default {
</template>
</gl-table>
+ <clusters-empty-state v-else :is-child-component="isChildComponent" />
+
<gl-pagination
- v-if="hasClusters"
+ v-if="hasClustersPerPage && !limit"
v-model="currentPage"
:per-page="clustersPerPage"
- :total-items="totalCulsters"
+ :total-items="totalClusters"
:prev-text="__('Prev')"
:next-text="__('Next')"
align="center"
diff --git a/app/assets/javascripts/clusters_list/components/clusters_actions.vue b/app/assets/javascripts/clusters_list/components/clusters_actions.vue
new file mode 100644
index 00000000000..25f67462223
--- /dev/null
+++ b/app/assets/javascripts/clusters_list/components/clusters_actions.vue
@@ -0,0 +1,44 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlModalDirective } from '@gitlab/ui';
+import { INSTALL_AGENT_MODAL_ID, CLUSTERS_ACTIONS } from '../constants';
+
+export default {
+ i18n: CLUSTERS_ACTIONS,
+ INSTALL_AGENT_MODAL_ID,
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ },
+ directives: {
+ GlModalDirective,
+ },
+ inject: ['newClusterPath', 'addClusterPath'],
+};
+</script>
+
+<template>
+ <div class="nav-controls gl-ml-auto">
+ <gl-dropdown
+ ref="dropdown"
+ v-gl-modal-directive="$options.INSTALL_AGENT_MODAL_ID"
+ category="primary"
+ variant="confirm"
+ :text="$options.i18n.actionsButton"
+ split
+ right
+ >
+ <gl-dropdown-item :href="newClusterPath" data-testid="new-cluster-link" @click.stop>
+ {{ $options.i18n.createNewCluster }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-gl-modal-directive="$options.INSTALL_AGENT_MODAL_ID"
+ data-testid="connect-new-agent-link"
+ >
+ {{ $options.i18n.connectWithAgent }}
+ </gl-dropdown-item>
+ <gl-dropdown-item :href="addClusterPath" data-testid="connect-cluster-link" @click.stop>
+ {{ $options.i18n.connectExistingCluster }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+</template>
diff --git a/app/assets/javascripts/clusters_list/components/clusters_empty_state.vue b/app/assets/javascripts/clusters_list/components/clusters_empty_state.vue
new file mode 100644
index 00000000000..3879af6e9cb
--- /dev/null
+++ b/app/assets/javascripts/clusters_list/components/clusters_empty_state.vue
@@ -0,0 +1,76 @@
+<script>
+import { GlEmptyState, GlButton, GlLink, GlSprintf } from '@gitlab/ui';
+import { mapState } from 'vuex';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import { I18N_CLUSTERS_EMPTY_STATE } from '../constants';
+
+export default {
+ i18n: I18N_CLUSTERS_EMPTY_STATE,
+ components: {
+ GlEmptyState,
+ GlButton,
+ GlLink,
+ GlSprintf,
+ },
+ inject: ['emptyStateHelpText', 'clustersEmptyStateImage', 'newClusterPath'],
+ props: {
+ isChildComponent: {
+ default: false,
+ required: false,
+ type: Boolean,
+ },
+ },
+ learnMoreHelpUrl: helpPagePath('user/project/clusters/index'),
+ multipleClustersHelpUrl: helpPagePath('user/project/clusters/multiple_kubernetes_clusters'),
+ computed: {
+ ...mapState(['canAddCluster']),
+ },
+};
+</script>
+
+<template>
+ <gl-empty-state :svg-path="clustersEmptyStateImage" title="">
+ <template #description>
+ <p class="gl-text-left">
+ {{ $options.i18n.description }}
+ </p>
+ <p class="gl-text-left">
+ <gl-sprintf :message="$options.i18n.multipleClustersText">
+ <template #link="{ content }">
+ <gl-link
+ :href="$options.multipleClustersHelpUrl"
+ target="_blank"
+ data-testid="multiple-clusters-docs-link"
+ >
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+
+ <p v-if="emptyStateHelpText" data-testid="clusters-empty-state-text">
+ {{ emptyStateHelpText }}
+ </p>
+
+ <p>
+ <gl-link :href="$options.learnMoreHelpUrl" target="_blank" data-testid="clusters-docs-link">
+ {{ $options.i18n.learnMoreLinkText }}
+ </gl-link>
+ </p>
+ </template>
+
+ <template #actions>
+ <gl-button
+ v-if="!isChildComponent"
+ data-testid="integration-primary-button"
+ data-qa-selector="add_kubernetes_cluster_link"
+ category="primary"
+ variant="confirm"
+ :disabled="!canAddCluster"
+ :href="newClusterPath"
+ >
+ {{ $options.i18n.buttonText }}
+ </gl-button>
+ </template>
+ </gl-empty-state>
+</template>
diff --git a/app/assets/javascripts/clusters_list/components/clusters_main_view.vue b/app/assets/javascripts/clusters_list/components/clusters_main_view.vue
new file mode 100644
index 00000000000..9e03093aa67
--- /dev/null
+++ b/app/assets/javascripts/clusters_list/components/clusters_main_view.vue
@@ -0,0 +1,73 @@
+<script>
+import { GlTabs, GlTab } from '@gitlab/ui';
+import { CLUSTERS_TABS, MAX_CLUSTERS_LIST, MAX_LIST_COUNT, AGENT } from '../constants';
+import Agents from './agents.vue';
+import InstallAgentModal from './install_agent_modal.vue';
+import ClustersActions from './clusters_actions.vue';
+import Clusters from './clusters.vue';
+import ClustersViewAll from './clusters_view_all.vue';
+
+export default {
+ components: {
+ GlTabs,
+ GlTab,
+ ClustersActions,
+ ClustersViewAll,
+ Clusters,
+ Agents,
+ InstallAgentModal,
+ },
+ CLUSTERS_TABS,
+ props: {
+ defaultBranchName: {
+ default: '.noBranch',
+ required: false,
+ type: String,
+ },
+ },
+ data() {
+ return {
+ selectedTabIndex: 0,
+ maxAgents: MAX_CLUSTERS_LIST,
+ };
+ },
+ methods: {
+ onTabChange(tabName) {
+ this.selectedTabIndex = CLUSTERS_TABS.findIndex((tab) => tab.queryParamValue === tabName);
+
+ this.maxAgents = tabName === AGENT ? MAX_LIST_COUNT : MAX_CLUSTERS_LIST;
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-tabs
+ v-model="selectedTabIndex"
+ sync-active-tab-with-query-params
+ nav-class="gl-flex-grow-1 gl-align-items-center"
+ lazy
+ >
+ <gl-tab
+ v-for="(tab, idx) in $options.CLUSTERS_TABS"
+ :key="idx"
+ :title="tab.title"
+ :query-param-value="tab.queryParamValue"
+ class="gl-line-height-20 gl-mt-5"
+ >
+ <component
+ :is="tab.component"
+ :default-branch-name="defaultBranchName"
+ data-testid="clusters-tab-component"
+ @changeTab="onTabChange"
+ />
+ </gl-tab>
+
+ <template #tabs-end>
+ <clusters-actions />
+ </template>
+ </gl-tabs>
+
+ <install-agent-modal :default-branch-name="defaultBranchName" :max-agents="maxAgents" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/clusters_list/components/clusters_view_all.vue b/app/assets/javascripts/clusters_list/components/clusters_view_all.vue
new file mode 100644
index 00000000000..285876e57d8
--- /dev/null
+++ b/app/assets/javascripts/clusters_list/components/clusters_view_all.vue
@@ -0,0 +1,218 @@
+<script>
+import {
+ GlCard,
+ GlSprintf,
+ GlPopover,
+ GlLink,
+ GlButton,
+ GlBadge,
+ GlLoadingIcon,
+ GlModalDirective,
+} from '@gitlab/ui';
+import { mapState } from 'vuex';
+import {
+ AGENT_CARD_INFO,
+ CERTIFICATE_BASED_CARD_INFO,
+ MAX_CLUSTERS_LIST,
+ INSTALL_AGENT_MODAL_ID,
+} from '../constants';
+import Clusters from './clusters.vue';
+import Agents from './agents.vue';
+
+export default {
+ components: {
+ GlCard,
+ GlSprintf,
+ GlPopover,
+ GlLink,
+ GlButton,
+ GlBadge,
+ GlLoadingIcon,
+ Clusters,
+ Agents,
+ },
+ directives: {
+ GlModalDirective,
+ },
+ AGENT_CARD_INFO,
+ CERTIFICATE_BASED_CARD_INFO,
+ MAX_CLUSTERS_LIST,
+ INSTALL_AGENT_MODAL_ID,
+ inject: ['addClusterPath'],
+ props: {
+ defaultBranchName: {
+ default: '.noBranch',
+ required: false,
+ type: String,
+ },
+ },
+ data() {
+ return {
+ loadingAgents: true,
+ totalAgents: null,
+ };
+ },
+ computed: {
+ ...mapState(['loadingClusters', 'totalClusters']),
+ isLoading() {
+ return this.loadingAgents || this.loadingClusters;
+ },
+ agentsCardTitle() {
+ let cardTitle;
+ if (this.totalAgents > 0) {
+ cardTitle = {
+ message: AGENT_CARD_INFO.title,
+ number: this.totalAgents < MAX_CLUSTERS_LIST ? this.totalAgents : MAX_CLUSTERS_LIST,
+ total: this.totalAgents,
+ };
+ } else {
+ cardTitle = {
+ message: AGENT_CARD_INFO.emptyTitle,
+ };
+ }
+
+ return cardTitle;
+ },
+ clustersCardTitle() {
+ let cardTitle;
+ if (this.totalClusters > 0) {
+ cardTitle = {
+ message: CERTIFICATE_BASED_CARD_INFO.title,
+ number: this.totalClusters < MAX_CLUSTERS_LIST ? this.totalClusters : MAX_CLUSTERS_LIST,
+ total: this.totalClusters,
+ };
+ } else {
+ cardTitle = {
+ message: CERTIFICATE_BASED_CARD_INFO.emptyTitle,
+ };
+ }
+
+ return cardTitle;
+ },
+ },
+ methods: {
+ cardFooterNumber(number) {
+ return number > MAX_CLUSTERS_LIST ? number : '';
+ },
+ onAgentsLoad(number) {
+ this.totalAgents = number;
+ this.loadingAgents = false;
+ },
+ changeTab($event, tab) {
+ $event.preventDefault();
+ this.$emit('changeTab', tab);
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-loading-icon v-if="isLoading" size="md" />
+ <div v-show="!isLoading" data-testid="clusters-cards-container">
+ <gl-card
+ header-class="gl-bg-white gl-display-flex gl-align-items-center gl-justify-content-space-between gl-py-4"
+ body-class="gl-pb-0"
+ footer-class="gl-text-right"
+ >
+ <template #header>
+ <h3 data-testid="agent-card-title" class="gl-my-0 gl-font-weight-normal gl-font-size-h2">
+ <gl-sprintf :message="agentsCardTitle.message"
+ ><template #number>{{ agentsCardTitle.number }}</template>
+ <template #total>{{ agentsCardTitle.total }}</template>
+ </gl-sprintf>
+ </h3>
+
+ <gl-badge id="clusters-recommended-badge" size="md" variant="info">{{
+ $options.AGENT_CARD_INFO.tooltip.label
+ }}</gl-badge>
+
+ <gl-popover
+ target="clusters-recommended-badge"
+ container="viewport"
+ placement="bottom"
+ :title="$options.AGENT_CARD_INFO.tooltip.title"
+ >
+ <p class="gl-mb-0">
+ <gl-sprintf :message="$options.AGENT_CARD_INFO.tooltip.text">
+ <template #link="{ content }">
+ <gl-link
+ :href="$options.AGENT_CARD_INFO.tooltip.link"
+ target="_blank"
+ class="gl-font-sm"
+ >
+ {{ content }}</gl-link
+ >
+ </template>
+ </gl-sprintf>
+ </p>
+ </gl-popover>
+ </template>
+
+ <agents
+ :limit="$options.MAX_CLUSTERS_LIST"
+ :default-branch-name="defaultBranchName"
+ :is-child-component="true"
+ @onAgentsLoad="onAgentsLoad"
+ />
+
+ <template #footer>
+ <gl-link
+ v-if="totalAgents"
+ data-testid="agents-tab-footer-link"
+ :href="`?tab=${$options.AGENT_CARD_INFO.tabName}`"
+ @click="changeTab($event, $options.AGENT_CARD_INFO.tabName)"
+ ><gl-sprintf :message="$options.AGENT_CARD_INFO.footerText"
+ ><template #number>{{ cardFooterNumber(totalAgents) }}</template></gl-sprintf
+ ></gl-link
+ ><gl-button
+ v-gl-modal-directive="$options.INSTALL_AGENT_MODAL_ID"
+ class="gl-ml-4"
+ category="secondary"
+ variant="confirm"
+ >{{ $options.AGENT_CARD_INFO.actionText }}</gl-button
+ >
+ </template>
+ </gl-card>
+
+ <gl-card
+ class="gl-mt-6"
+ header-class="gl-bg-white gl-display-flex gl-align-items-center gl-justify-content-space-between"
+ body-class="gl-pb-0"
+ footer-class="gl-text-right"
+ >
+ <template #header>
+ <h3
+ class="gl-my-1 gl-font-weight-normal gl-font-size-h2"
+ data-testid="clusters-card-title"
+ >
+ <gl-sprintf :message="clustersCardTitle.message"
+ ><template #number>{{ clustersCardTitle.number }}</template>
+ <template #total>{{ clustersCardTitle.total }}</template>
+ </gl-sprintf>
+ </h3>
+ </template>
+
+ <clusters :limit="$options.MAX_CLUSTERS_LIST" :is-child-component="true" />
+
+ <template #footer>
+ <gl-link
+ v-if="totalClusters"
+ data-testid="clusters-tab-footer-link"
+ :href="`?tab=${$options.CERTIFICATE_BASED_CARD_INFO.tabName}`"
+ @click="changeTab($event, $options.CERTIFICATE_BASED_CARD_INFO.tabName)"
+ ><gl-sprintf :message="$options.CERTIFICATE_BASED_CARD_INFO.footerText"
+ ><template #number>{{ cardFooterNumber(totalClusters) }}</template></gl-sprintf
+ ></gl-link
+ ><gl-button
+ category="secondary"
+ data-qa-selector="connect_existing_cluster_button"
+ variant="confirm"
+ class="gl-ml-4"
+ :href="addClusterPath"
+ >{{ $options.CERTIFICATE_BASED_CARD_INFO.actionText }}</gl-button
+ >
+ </template>
+ </gl-card>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/clusters_list/components/install_agent_modal.vue b/app/assets/javascripts/clusters_list/components/install_agent_modal.vue
index 5f192fe4d5a..6eb2e85ecea 100644
--- a/app/assets/javascripts/clusters_list/components/install_agent_modal.vue
+++ b/app/assets/javascripts/clusters_list/components/install_agent_modal.vue
@@ -13,8 +13,10 @@ import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import CodeBlock from '~/vue_shared/components/code_block.vue';
import { generateAgentRegistrationCommand } from '../clusters_util';
import { INSTALL_AGENT_MODAL_ID, I18N_INSTALL_AGENT_MODAL } from '../constants';
+import { addAgentToStore } from '../graphql/cache_update';
import createAgent from '../graphql/mutations/create_agent.mutation.graphql';
import createAgentToken from '../graphql/mutations/create_agent_token.mutation.graphql';
+import getAgentsQuery from '../graphql/queries/get_agents.query.graphql';
import AvailableAgentsDropdown from './available_agents_dropdown.vue';
export default {
@@ -33,12 +35,24 @@ export default {
GlSprintf,
},
inject: ['projectPath', 'kasAddress'],
+ props: {
+ defaultBranchName: {
+ default: '.noBranch',
+ required: false,
+ type: String,
+ },
+ maxAgents: {
+ required: true,
+ type: Number,
+ },
+ },
data() {
return {
registering: false,
agentName: null,
agentToken: null,
error: null,
+ clusterAgent: null,
};
},
computed: {
@@ -55,27 +69,31 @@ export default {
return generateAgentRegistrationCommand(this.agentToken, this.kasAddress);
},
basicInstallPath() {
- return helpPagePath('user/clusters/agent/index', {
+ return helpPagePath('user/clusters/agent/install/index', {
anchor: 'install-the-agent-into-the-cluster',
});
},
advancedInstallPath() {
- return helpPagePath('user/clusters/agent/index', { anchor: 'advanced-installation' });
+ return helpPagePath('user/clusters/agent/install/index', { anchor: 'advanced-installation' });
+ },
+ getAgentsQueryVariables() {
+ return {
+ defaultBranchName: this.defaultBranchName,
+ first: this.maxAgents,
+ last: null,
+ projectPath: this.projectPath,
+ };
},
},
methods: {
setAgentName(name) {
this.agentName = name;
},
- cancelClicked() {
- this.$refs.modal.hide();
- },
- doneClicked() {
- this.$emit('agentRegistered');
+ closeModal() {
this.$refs.modal.hide();
},
resetModal() {
- this.registering = null;
+ this.registering = false;
this.agentName = null;
this.agentToken = null;
this.error = null;
@@ -90,6 +108,14 @@ export default {
projectPath: this.projectPath,
},
},
+ update: (store, { data: { createClusterAgent } }) => {
+ addAgentToStore(
+ store,
+ createClusterAgent,
+ getAgentsQuery,
+ this.getAgentsQueryVariables,
+ );
+ },
})
.then(({ data: { createClusterAgent } }) => createClusterAgent);
},
@@ -117,6 +143,8 @@ export default {
throw new Error(agentErrors[0]);
}
+ this.clusterAgent = clusterAgent;
+
const { errors: tokenErrors, secret } = await this.createAgentTokenMutation(
clusterAgent.id,
);
@@ -240,10 +268,10 @@ export default {
</template>
<template #modal-footer>
- <gl-button v-if="canCancel" @click="cancelClicked">{{ $options.i18n.cancel }} </gl-button>
+ <gl-button v-if="canCancel" @click="closeModal">{{ $options.i18n.cancel }} </gl-button>
- <gl-button v-if="registered" variant="confirm" category="primary" @click="doneClicked"
- >{{ $options.i18n.done }}
+ <gl-button v-if="registered" variant="confirm" category="primary" @click="closeModal"
+ >{{ $options.i18n.close }}
</gl-button>
<gl-button
@@ -252,7 +280,7 @@ export default {
variant="confirm"
category="primary"
@click="registerAgent"
- >{{ $options.i18n.next }}
+ >{{ $options.i18n.registerAgentButton }}
</gl-button>
</template>
</gl-modal>
diff --git a/app/assets/javascripts/clusters_list/constants.js b/app/assets/javascripts/clusters_list/constants.js
index 0bade1fc281..9fefdf450c4 100644
--- a/app/assets/javascripts/clusters_list/constants.js
+++ b/app/assets/javascripts/clusters_list/constants.js
@@ -1,10 +1,9 @@
import { __, s__, sprintf } from '~/locale';
+import { helpPagePath } from '~/helpers/help_page_helper';
export const MAX_LIST_COUNT = 25;
export const INSTALL_AGENT_MODAL_ID = 'install-agent';
export const ACTIVE_CONNECTION_TIME = 480000;
-export const TROUBLESHOOTING_LINK =
- 'https://docs.gitlab.com/ee/user/clusters/agent/#troubleshooting';
export const CLUSTER_ERRORS = {
default: {
@@ -66,8 +65,8 @@ export const STATUSES = {
};
export const I18N_INSTALL_AGENT_MODAL = {
- next: __('Next'),
- done: __('Done'),
+ registerAgentButton: s__('ClusterAgents|Register Agent'),
+ close: __('Close'),
cancel: __('Cancel'),
modalTitle: s__('ClusterAgents|Install new Agent'),
@@ -91,7 +90,7 @@ export const I18N_INSTALL_AGENT_MODAL = {
),
basicInstallTitle: s__('ClusterAgents|Recommended installation method'),
- basicInstallBody: s__(
+ basicInstallBody: __(
`Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command.`,
),
@@ -100,7 +99,7 @@ export const I18N_INSTALL_AGENT_MODAL = {
'ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}.',
),
- registrationErrorTitle: s__('Failed to register Agent'),
+ registrationErrorTitle: __('Failed to register Agent'),
unknownError: s__('ClusterAgents|An unknown error occurred. Please try again.'),
};
@@ -141,3 +140,86 @@ export const AGENT_STATUSES = {
},
},
};
+
+export const I18N_AGENTS_EMPTY_STATE = {
+ introText: s__(
+ 'ClusterAgents|Use GitLab Agents to more securely integrate with your clusters to deploy your applications, run your pipelines, use review apps and much more.',
+ ),
+ multipleClustersText: s__(
+ 'ClusterAgents|If you are setting up multiple clusters and are using Auto DevOps, %{linkStart}read about using multiple Kubernetes clusters first.%{linkEnd}',
+ ),
+ learnMoreText: s__('ClusterAgents|Learn more about the GitLab Kubernetes Agent.'),
+ warningText: s__(
+ 'ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process.',
+ ),
+ readMoreText: s__('ClusterAgents|Read more about getting started'),
+ repositoryButtonText: s__('ClusterAgents|Go to the repository'),
+ primaryButtonText: s__('ClusterAgents|Connect with a GitLab Agent'),
+};
+
+export const I18N_CLUSTERS_EMPTY_STATE = {
+ description: s__(
+ 'ClusterIntegration|Use certificates to integrate with your clusters to deploy your applications, run your pipelines, use review apps and much more in an easy way.',
+ ),
+ multipleClustersText: s__(
+ 'ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{linkStart}read about using multiple Kubernetes clusters first.%{linkEnd}',
+ ),
+ learnMoreLinkText: s__('ClusterIntegration|Learn more about the GitLab managed clusters'),
+ buttonText: s__('ClusterIntegration|Connect with a certificate'),
+};
+
+export const AGENT_CARD_INFO = {
+ tabName: 'agent',
+ title: sprintf(s__('ClusterAgents|%{number} of %{total} Agent based integrations')),
+ emptyTitle: s__('ClusterAgents|No Agent based integrations'),
+ tooltip: {
+ label: s__('ClusterAgents|Recommended'),
+ title: s__('ClusterAgents|GitLab Agents'),
+ text: sprintf(
+ s__(
+ 'ClusterAgents|GitLab Agents provide an increased level of security when integrating with clusters. %{linkStart}Learn more about the GitLab Kubernetes Agent.%{linkEnd}',
+ ),
+ ),
+ link: helpPagePath('user/clusters/agent/index'),
+ },
+ actionText: s__('ClusterAgents|Install new Agent'),
+ footerText: sprintf(s__('ClusterAgents|View all %{number} Agent based integrations')),
+};
+
+export const CERTIFICATE_BASED_CARD_INFO = {
+ tabName: 'certificate_based',
+ title: sprintf(s__('ClusterAgents|%{number} of %{total} Certificate based integrations')),
+ emptyTitle: s__('ClusterAgents|No Certificate based integrations'),
+ actionText: s__('ClusterAgents|Connect existing cluster'),
+ footerText: sprintf(s__('ClusterAgents|View all %{number} Certificate based integrations')),
+};
+
+export const MAX_CLUSTERS_LIST = 6;
+
+export const CLUSTERS_TABS = [
+ {
+ title: s__('ClusterAgents|All'),
+ component: 'ClustersViewAll',
+ queryParamValue: 'all',
+ },
+ {
+ title: s__('ClusterAgents|Agent'),
+ component: 'agents',
+ queryParamValue: 'agent',
+ },
+ {
+ title: s__('ClusterAgents|Certificate based'),
+ component: 'clusters',
+ queryParamValue: 'certificate_based',
+ },
+];
+
+export const CLUSTERS_ACTIONS = {
+ actionsButton: s__('ClusterAgents|Actions'),
+ createNewCluster: s__('ClusterAgents|Create new cluster'),
+ connectWithAgent: s__('ClusterAgents|Connect with Agent'),
+ connectExistingCluster: s__('ClusterAgents|Connect with certificate'),
+};
+
+export const AGENT = 'agent';
+export const CERTIFICATE_BASED = 'certificate_based';
diff --git a/app/assets/javascripts/clusters_list/graphql/cache_update.js b/app/assets/javascripts/clusters_list/graphql/cache_update.js
new file mode 100644
index 00000000000..dd633820952
--- /dev/null
+++ b/app/assets/javascripts/clusters_list/graphql/cache_update.js
@@ -0,0 +1,29 @@
+import produce from 'immer';
+import { getAgentConfigPath } from '../clusters_util';
+
+export function addAgentToStore(store, createClusterAgent, query, variables) {
+ const { clusterAgent } = createClusterAgent;
+ const sourceData = store.readQuery({
+ query,
+ variables,
+ });
+
+ const data = produce(sourceData, (draftData) => {
+ const configuration = {
+ name: clusterAgent.name,
+ path: getAgentConfigPath(clusterAgent.name),
+ webPath: clusterAgent.webPath,
+ __typename: 'TreeEntry',
+ };
+
+ draftData.project.clusterAgents.nodes.push(clusterAgent);
+ draftData.project.clusterAgents.count += 1;
+ draftData.project.repository.tree.trees.nodes.push(configuration);
+ });
+
+ store.writeQuery({
+ query,
+ variables,
+ data,
+ });
+}
diff --git a/app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql b/app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql
new file mode 100644
index 00000000000..9b40260471c
--- /dev/null
+++ b/app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql
@@ -0,0 +1,10 @@
+fragment ClusterAgentFragment on ClusterAgent {
+ id
+ name
+ webPath
+ tokens {
+ nodes {
+ lastUsedAt
+ }
+ }
+}
diff --git a/app/assets/javascripts/clusters_list/graphql/mutations/create_agent.mutation.graphql b/app/assets/javascripts/clusters_list/graphql/mutations/create_agent.mutation.graphql
index c29756159f5..996b388089b 100644
--- a/app/assets/javascripts/clusters_list/graphql/mutations/create_agent.mutation.graphql
+++ b/app/assets/javascripts/clusters_list/graphql/mutations/create_agent.mutation.graphql
@@ -1,7 +1,9 @@
+#import "../fragments/cluster_agent.fragment.graphql"
+
mutation createClusterAgent($input: CreateClusterAgentInput!) {
createClusterAgent(input: $input) {
clusterAgent {
- id
+ ...ClusterAgentFragment
}
errors
}
diff --git a/app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql b/app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql
index 61989e00d9e..47b25988877 100644
--- a/app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql
+++ b/app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql
@@ -1,4 +1,5 @@
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
+#import "../fragments/cluster_agent.fragment.graphql"
query getAgents(
$defaultBranchName: String!
@@ -13,19 +14,14 @@ query getAgents(
project(fullPath: $projectPath) {
clusterAgents(first: $first, last: $last, before: $beforeAgent, after: $afterAgent) {
nodes {
- id
- name
- webPath
- tokens {
- nodes {
- lastUsedAt
- }
- }
+ ...ClusterAgentFragment
}
pageInfo {
...PageInfo
}
+
+ count
}
repository {
diff --git a/app/assets/javascripts/clusters_list/index.js b/app/assets/javascripts/clusters_list/index.js
index de18965abbd..7f1ef37814b 100644
--- a/app/assets/javascripts/clusters_list/index.js
+++ b/app/assets/javascripts/clusters_list/index.js
@@ -1,11 +1,11 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import loadClusters from './load_clusters';
-import loadAgents from './load_agents';
+import loadMainView from './load_main_view';
Vue.use(VueApollo);
export default () => {
loadClusters(Vue);
- loadAgents(Vue, VueApollo);
+ loadMainView(Vue, VueApollo);
};
diff --git a/app/assets/javascripts/clusters_list/load_agents.js b/app/assets/javascripts/clusters_list/load_agents.js
deleted file mode 100644
index b77d386df20..00000000000
--- a/app/assets/javascripts/clusters_list/load_agents.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import createDefaultClient from '~/lib/graphql';
-import Agents from './components/agents.vue';
-
-export default (Vue, VueApollo) => {
- const el = document.querySelector('#js-cluster-agents-list');
-
- if (!el) {
- return null;
- }
-
- const defaultClient = createDefaultClient({}, { assumeImmutableResults: true });
-
- const {
- emptyStateImage,
- defaultBranchName,
- projectPath,
- agentDocsUrl,
- installDocsUrl,
- getStartedDocsUrl,
- integrationDocsUrl,
- kasAddress,
- } = el.dataset;
-
- return new Vue({
- el,
- apolloProvider: new VueApollo({ defaultClient }),
- provide: {
- emptyStateImage,
- projectPath,
- agentDocsUrl,
- installDocsUrl,
- getStartedDocsUrl,
- integrationDocsUrl,
- kasAddress,
- },
- render(createElement) {
- return createElement(Agents, {
- props: {
- defaultBranchName,
- },
- });
- },
- });
-};
diff --git a/app/assets/javascripts/clusters_list/load_clusters.js b/app/assets/javascripts/clusters_list/load_clusters.js
index 01430230879..1bb3ea546b2 100644
--- a/app/assets/javascripts/clusters_list/load_clusters.js
+++ b/app/assets/javascripts/clusters_list/load_clusters.js
@@ -8,8 +8,15 @@ export default (Vue) => {
return null;
}
+ const { emptyStateHelpText, newClusterPath, clustersEmptyStateImage } = el.dataset;
+
return new Vue({
el,
+ provide: {
+ emptyStateHelpText,
+ newClusterPath,
+ clustersEmptyStateImage,
+ },
store: createStore(el.dataset),
render(createElement) {
return createElement(Clusters);
diff --git a/app/assets/javascripts/clusters_list/load_main_view.js b/app/assets/javascripts/clusters_list/load_main_view.js
new file mode 100644
index 00000000000..08c99b46e16
--- /dev/null
+++ b/app/assets/javascripts/clusters_list/load_main_view.js
@@ -0,0 +1,50 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import ClustersMainView from './components/clusters_main_view.vue';
+import { createStore } from './store';
+
+Vue.use(VueApollo);
+
+export default () => {
+ const el = document.querySelector('.js-clusters-main-view');
+
+ if (!el) {
+ return null;
+ }
+
+ const defaultClient = createDefaultClient();
+
+ const {
+ emptyStateImage,
+ defaultBranchName,
+ projectPath,
+ kasAddress,
+ newClusterPath,
+ addClusterPath,
+ emptyStateHelpText,
+ clustersEmptyStateImage,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ apolloProvider: new VueApollo({ defaultClient }),
+ provide: {
+ emptyStateImage,
+ projectPath,
+ kasAddress,
+ newClusterPath,
+ addClusterPath,
+ emptyStateHelpText,
+ clustersEmptyStateImage,
+ },
+ store: createStore(el.dataset),
+ render(createElement) {
+ return createElement(ClustersMainView, {
+ props: {
+ defaultBranchName,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/clusters_list/store/actions.js b/app/assets/javascripts/clusters_list/store/actions.js
index 5f35a0b26f3..d70b36e63bc 100644
--- a/app/assets/javascripts/clusters_list/store/actions.js
+++ b/app/assets/javascripts/clusters_list/store/actions.js
@@ -3,7 +3,7 @@ import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import Poll from '~/lib/utils/poll';
-import { __ } from '~/locale';
+import { s__ } from '~/locale';
import { MAX_REQUESTS } from '../constants';
import * as types from './mutation_types';
@@ -30,7 +30,13 @@ export const fetchClusters = ({ state, commit, dispatch }) => {
const poll = new Poll({
resource: {
- fetchClusters: (paginatedEndPoint) => axios.get(paginatedEndPoint),
+ fetchClusters: (paginatedEndPoint) =>
+ axios.get(paginatedEndPoint, {
+ params: {
+ page: state.page,
+ per_page: state.clustersPerPage,
+ },
+ }),
},
data: `${state.endpoint}?page=${state.page}`,
method: 'fetchClusters',
@@ -65,7 +71,7 @@ export const fetchClusters = ({ state, commit, dispatch }) => {
commit(types.SET_LOADING_CLUSTERS, false);
commit(types.SET_LOADING_NODES, false);
createFlash({
- message: __('Clusters|An error occurred while loading clusters'),
+ message: s__('Clusters|An error occurred while loading clusters'),
});
dispatch('reportSentryError', { error: response, tag: 'fetchClustersErrorCallback' });
@@ -78,3 +84,7 @@ export const fetchClusters = ({ state, commit, dispatch }) => {
export const setPage = ({ commit }, page) => {
commit(types.SET_PAGE, page);
};
+
+export const setClustersPerPage = ({ commit }, limit) => {
+ commit(types.SET_CLUSTERS_PER_PAGE, limit);
+};
diff --git a/app/assets/javascripts/clusters_list/store/mutation_types.js b/app/assets/javascripts/clusters_list/store/mutation_types.js
index beb4388c93e..e88d4c74761 100644
--- a/app/assets/javascripts/clusters_list/store/mutation_types.js
+++ b/app/assets/javascripts/clusters_list/store/mutation_types.js
@@ -2,3 +2,4 @@ export const SET_CLUSTERS_DATA = 'SET_CLUSTERS_DATA';
export const SET_LOADING_CLUSTERS = 'SET_LOADING_CLUSTERS';
export const SET_LOADING_NODES = 'SET_LOADING_NODES';
export const SET_PAGE = 'SET_PAGE';
+export const SET_CLUSTERS_PER_PAGE = 'SET_CLUSTERS_PER_PAGE';
diff --git a/app/assets/javascripts/clusters_list/store/mutations.js b/app/assets/javascripts/clusters_list/store/mutations.js
index 5b462928518..93156c9200f 100644
--- a/app/assets/javascripts/clusters_list/store/mutations.js
+++ b/app/assets/javascripts/clusters_list/store/mutations.js
@@ -12,10 +12,13 @@ export default {
clusters: data.clusters,
clustersPerPage: paginationInformation.perPage,
hasAncestorClusters: data.has_ancestor_clusters,
- totalCulsters: paginationInformation.total,
+ totalClusters: paginationInformation.total,
});
},
[types.SET_PAGE](state, value) {
state.page = Number(value) || 1;
},
+ [types.SET_CLUSTERS_PER_PAGE](state, value) {
+ state.clustersPerPage = Number(value) || 1;
+ },
};
diff --git a/app/assets/javascripts/clusters_list/store/state.js b/app/assets/javascripts/clusters_list/store/state.js
index 51fafd49479..763d7389d0f 100644
--- a/app/assets/javascripts/clusters_list/store/state.js
+++ b/app/assets/javascripts/clusters_list/store/state.js
@@ -1,9 +1,11 @@
+import { parseBoolean } from '~/lib/utils/common_utils';
+
export default (initialState = {}) => ({
ancestorHelperPath: initialState.ancestorHelpPath,
endpoint: initialState.endpoint,
hasAncestorClusters: false,
clusters: [],
- clustersPerPage: 0,
+ clustersPerPage: 20,
loadingClusters: true,
loadingNodes: true,
page: 1,
@@ -12,5 +14,6 @@ export default (initialState = {}) => ({
default: { path: initialState.imgTagsDefaultPath, text: initialState.imgTagsDefaultText },
gcp: { path: initialState.imgTagsGcpPath, text: initialState.imgTagsGcpText },
},
- totalCulsters: 0,
+ totalClusters: 0,
+ canAddCluster: parseBoolean(initialState.canAddCluster),
});
diff --git a/app/assets/javascripts/confirm_danger_modal.js b/app/assets/javascripts/confirm_danger_modal.js
index 5b9e70e3c09..ad70d9be16f 100644
--- a/app/assets/javascripts/confirm_danger_modal.js
+++ b/app/assets/javascripts/confirm_danger_modal.js
@@ -3,14 +3,14 @@ import { Rails } from '~/lib/utils/rails_ujs';
import { rstrip } from './lib/utils/common_utils';
function openConfirmDangerModal($form, $modal, text) {
- const $input = $('.js-confirm-danger-input', $modal);
+ const $input = $('.js-legacy-confirm-danger-input', $modal);
$input.val('');
$('.js-confirm-text', $modal).text(text || '');
$modal.modal('show');
- const confirmTextMatch = $('.js-confirm-danger-match', $modal).text();
- const $submit = $('.js-confirm-danger-submit', $modal);
+ const confirmTextMatch = $('.js-legacy-confirm-danger-match', $modal).text();
+ const $submit = $('.js-legacy-confirm-danger-submit', $modal);
$submit.disable();
$input.focus();
@@ -25,7 +25,7 @@ function openConfirmDangerModal($form, $modal, text) {
});
// eslint-disable-next-line @gitlab/no-global-event-off
- $('.js-confirm-danger-submit', $modal)
+ $('.js-legacy-confirm-danger-submit', $modal)
.off('click')
.on('click', () => {
if ($form.data('remote')) {
@@ -47,7 +47,7 @@ function getModal($btn) {
}
export default function initConfirmDangerModal() {
- $(document).on('click', '.js-confirm-danger', (e) => {
+ $(document).on('click', '.js-legacy-confirm-danger', (e) => {
const $btn = $(e.target);
const checkFieldName = $btn.data('checkFieldName');
const checkFieldCompareValue = $btn.data('checkCompareValue');
diff --git a/app/assets/javascripts/content_editor/components/content_editor.vue b/app/assets/javascripts/content_editor/components/content_editor.vue
index 02ab34447ca..a8405fe37c7 100644
--- a/app/assets/javascripts/content_editor/components/content_editor.vue
+++ b/app/assets/javascripts/content_editor/components/content_editor.vue
@@ -3,7 +3,7 @@ import { GlLoadingIcon } from '@gitlab/ui';
import { EditorContent as TiptapEditorContent } from '@tiptap/vue-2';
import { LOADING_CONTENT_EVENT, LOADING_SUCCESS_EVENT, LOADING_ERROR_EVENT } from '../constants';
import { createContentEditor } from '../services/create_content_editor';
-import ContentEditorError from './content_editor_error.vue';
+import ContentEditorAlert from './content_editor_alert.vue';
import ContentEditorProvider from './content_editor_provider.vue';
import EditorStateObserver from './editor_state_observer.vue';
import FormattingBubbleMenu from './formatting_bubble_menu.vue';
@@ -12,7 +12,7 @@ import TopToolbar from './top_toolbar.vue';
export default {
components: {
GlLoadingIcon,
- ContentEditorError,
+ ContentEditorAlert,
ContentEditorProvider,
TiptapEditorContent,
TopToolbar,
@@ -92,7 +92,7 @@ export default {
<content-editor-provider :content-editor="contentEditor">
<div>
<editor-state-observer @docUpdate="notifyChange" @focus="focus" @blur="blur" />
- <content-editor-error />
+ <content-editor-alert />
<div
data-testid="content-editor"
data-qa-selector="content_editor_container"
diff --git a/app/assets/javascripts/content_editor/components/content_editor_alert.vue b/app/assets/javascripts/content_editor/components/content_editor_alert.vue
new file mode 100644
index 00000000000..c6737da1d77
--- /dev/null
+++ b/app/assets/javascripts/content_editor/components/content_editor_alert.vue
@@ -0,0 +1,33 @@
+<script>
+import { GlAlert } from '@gitlab/ui';
+import EditorStateObserver from './editor_state_observer.vue';
+
+export default {
+ components: {
+ GlAlert,
+ EditorStateObserver,
+ },
+ data() {
+ return {
+ message: null,
+ variant: 'danger',
+ };
+ },
+ methods: {
+ displayAlert({ message, variant }) {
+ this.message = message;
+ this.variant = variant;
+ },
+ dismissAlert() {
+ this.message = null;
+ },
+ },
+};
+</script>
+<template>
+ <editor-state-observer @alert="displayAlert">
+ <gl-alert v-if="message" class="gl-mb-6" :variant="variant" @dismiss="dismissAlert">
+ {{ message }}
+ </gl-alert>
+ </editor-state-observer>
+</template>
diff --git a/app/assets/javascripts/content_editor/components/content_editor_error.vue b/app/assets/javascripts/content_editor/components/content_editor_error.vue
deleted file mode 100644
index 031ea92a7e9..00000000000
--- a/app/assets/javascripts/content_editor/components/content_editor_error.vue
+++ /dev/null
@@ -1,31 +0,0 @@
-<script>
-import { GlAlert } from '@gitlab/ui';
-import EditorStateObserver from './editor_state_observer.vue';
-
-export default {
- components: {
- GlAlert,
- EditorStateObserver,
- },
- data() {
- return {
- error: null,
- };
- },
- methods: {
- displayError({ error }) {
- this.error = error;
- },
- dismissError() {
- this.error = null;
- },
- },
-};
-</script>
-<template>
- <editor-state-observer @error="displayError">
- <gl-alert v-if="error" class="gl-mb-6" variant="danger" @dismiss="dismissError">
- {{ error }}
- </gl-alert>
- </editor-state-observer>
-</template>
diff --git a/app/assets/javascripts/content_editor/components/editor_state_observer.vue b/app/assets/javascripts/content_editor/components/editor_state_observer.vue
index 2eeb0719096..0604047a953 100644
--- a/app/assets/javascripts/content_editor/components/editor_state_observer.vue
+++ b/app/assets/javascripts/content_editor/components/editor_state_observer.vue
@@ -7,7 +7,7 @@ export const tiptapToComponentMap = {
transaction: 'transaction',
focus: 'focus',
blur: 'blur',
- error: 'error',
+ alert: 'alert',
};
const getComponentEventName = (tiptapEventName) => tiptapToComponentMap[tiptapEventName];
diff --git a/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue b/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue
index c44e8145982..41c083111c5 100644
--- a/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue
+++ b/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue
@@ -26,8 +26,8 @@ export default {
type: Object,
required: true,
},
- getPos: {
- type: Function,
+ node: {
+ type: Object,
required: true,
},
},
@@ -61,7 +61,17 @@ export default {
const { state } = this.editor;
const { $cursor } = state.selection;
- this.displayActionsDropdown = $cursor?.pos - $cursor?.parentOffset - 1 === this.getPos();
+ if (!$cursor) return;
+
+ this.displayActionsDropdown = false;
+
+ for (let level = 0; level < $cursor.depth; level += 1) {
+ if ($cursor.node(level) === this.node) {
+ this.displayActionsDropdown = true;
+ break;
+ }
+ }
+
if (this.displayActionsDropdown) {
this.selectedRect = getSelectedRect(state);
}
@@ -99,7 +109,11 @@ export default {
:as="cellType"
@click="hideDropdown"
>
- <span v-if="displayActionsDropdown" class="gl-absolute gl-right-0 gl-top-0">
+ <span
+ v-if="displayActionsDropdown"
+ contenteditable="false"
+ class="gl-absolute gl-right-0 gl-top-0"
+ >
<gl-dropdown
ref="dropdown"
dropup
diff --git a/app/assets/javascripts/content_editor/components/wrappers/table_cell_body.vue b/app/assets/javascripts/content_editor/components/wrappers/table_cell_body.vue
index 6b4343dd5b8..47cd837d060 100644
--- a/app/assets/javascripts/content_editor/components/wrappers/table_cell_body.vue
+++ b/app/assets/javascripts/content_editor/components/wrappers/table_cell_body.vue
@@ -11,8 +11,8 @@ export default {
type: Object,
required: true,
},
- getPos: {
- type: Function,
+ node: {
+ type: Object,
required: true,
},
},
diff --git a/app/assets/javascripts/content_editor/components/wrappers/table_cell_header.vue b/app/assets/javascripts/content_editor/components/wrappers/table_cell_header.vue
index 5f9889374f6..150f78bc84f 100644
--- a/app/assets/javascripts/content_editor/components/wrappers/table_cell_header.vue
+++ b/app/assets/javascripts/content_editor/components/wrappers/table_cell_header.vue
@@ -11,8 +11,8 @@ export default {
type: Object,
required: true,
},
- getPos: {
- type: Function,
+ node: {
+ type: Object,
required: true,
},
},
diff --git a/app/assets/javascripts/content_editor/extensions/blockquote.js b/app/assets/javascripts/content_editor/extensions/blockquote.js
index 4512ead44bc..5632bc28592 100644
--- a/app/assets/javascripts/content_editor/extensions/blockquote.js
+++ b/app/assets/javascripts/content_editor/extensions/blockquote.js
@@ -1,10 +1,8 @@
import { Blockquote } from '@tiptap/extension-blockquote';
-import { wrappingInputRule } from 'prosemirror-inputrules';
+import { wrappingInputRule } from '@tiptap/core';
import { getParents } from '~/lib/utils/dom_utils';
import { getMarkdownSource } from '../services/markdown_sourcemap';
-export const multilineInputRegex = /^\s*>>>\s$/gm;
-
export default Blockquote.extend({
addAttributes() {
return {
@@ -25,9 +23,15 @@ export default Blockquote.extend({
},
addInputRules() {
+ const multilineInputRegex = /^\s*>>>\s$/gm;
+
return [
...this.parent?.(),
- wrappingInputRule(multilineInputRegex, this.type, () => ({ multiline: true })),
+ wrappingInputRule({
+ find: multilineInputRegex,
+ type: this.type,
+ getAttributes: () => ({ multiline: true }),
+ }),
];
},
});
diff --git a/app/assets/javascripts/content_editor/extensions/description_list.js b/app/assets/javascripts/content_editor/extensions/description_list.js
index a516dfad2b8..8f5b145cfa3 100644
--- a/app/assets/javascripts/content_editor/extensions/description_list.js
+++ b/app/assets/javascripts/content_editor/extensions/description_list.js
@@ -1,7 +1,4 @@
-import { Node, mergeAttributes } from '@tiptap/core';
-import { wrappingInputRule } from 'prosemirror-inputrules';
-
-export const inputRegex = /^\s*(<dl>)$/;
+import { Node, mergeAttributes, wrappingInputRule } from '@tiptap/core';
export default Node.create({
name: 'descriptionList',
@@ -18,6 +15,8 @@ export default Node.create({
},
addInputRules() {
- return [wrappingInputRule(inputRegex, this.type)];
+ const inputRegex = /^\s*(<dl>)$/;
+
+ return [wrappingInputRule({ find: inputRegex, type: this.type })];
},
});
diff --git a/app/assets/javascripts/content_editor/extensions/details.js b/app/assets/javascripts/content_editor/extensions/details.js
index e3d54ed01fd..46c906d45b1 100644
--- a/app/assets/javascripts/content_editor/extensions/details.js
+++ b/app/assets/javascripts/content_editor/extensions/details.js
@@ -1,10 +1,7 @@
-import { Node } from '@tiptap/core';
+import { Node, wrappingInputRule } from '@tiptap/core';
import { VueNodeViewRenderer } from '@tiptap/vue-2';
-import { wrappingInputRule } from 'prosemirror-inputrules';
import DetailsWrapper from '../components/wrappers/details.vue';
-export const inputRegex = /^\s*(<details>)$/;
-
export default Node.create({
name: 'details',
content: 'detailsContent+',
@@ -24,7 +21,9 @@ export default Node.create({
},
addInputRules() {
- return [wrappingInputRule(inputRegex, this.type)];
+ const inputRegex = /^\s*(<details>)$/;
+
+ return [wrappingInputRule({ find: inputRegex, type: this.type })];
},
addCommands() {
diff --git a/app/assets/javascripts/content_editor/extensions/emoji.js b/app/assets/javascripts/content_editor/extensions/emoji.js
index de608c3aaa2..7f8b5da5f46 100644
--- a/app/assets/javascripts/content_editor/extensions/emoji.js
+++ b/app/assets/javascripts/content_editor/extensions/emoji.js
@@ -1,9 +1,6 @@
-import { Node } from '@tiptap/core';
-import { InputRule } from 'prosemirror-inputrules';
+import { Node, InputRule } from '@tiptap/core';
import { initEmojiMap, getAllEmoji } from '~/emoji';
-export const emojiInputRegex = /(?:^|\s)((?::)((?:\w+))(?::))$/;
-
export default Node.create({
name: 'emoji',
@@ -54,23 +51,28 @@ export default Node.create({
},
addInputRules() {
+ const emojiInputRegex = /(?:^|\s)(:(\w+):)$/;
+
return [
- new InputRule(emojiInputRegex, (state, match, start, end) => {
- const [, , name] = match;
- const emojis = getAllEmoji();
- const emoji = emojis[name];
- const { tr } = state;
+ new InputRule({
+ find: emojiInputRegex,
+ handler: ({ state, range: { from, to }, match }) => {
+ const [, , name] = match;
+ const emojis = getAllEmoji();
+ const emoji = emojis[name];
+ const { tr } = state;
- if (emoji) {
- tr.replaceWith(start, end, [
- state.schema.text(' '),
- this.type.create({ name, moji: emoji.e, unicodeVersion: emoji.u, title: emoji.d }),
- ]);
+ if (emoji) {
+ tr.replaceWith(from, to, [
+ state.schema.text(' '),
+ this.type.create({ name, moji: emoji.e, unicodeVersion: emoji.u, title: emoji.d }),
+ ]);
- return tr;
- }
+ return tr;
+ }
- return null;
+ return null;
+ },
}),
];
},
diff --git a/app/assets/javascripts/content_editor/extensions/frontmatter.js b/app/assets/javascripts/content_editor/extensions/frontmatter.js
index 64c84fe046b..c09c10bc524 100644
--- a/app/assets/javascripts/content_editor/extensions/frontmatter.js
+++ b/app/assets/javascripts/content_editor/extensions/frontmatter.js
@@ -17,4 +17,7 @@ export default CodeBlockHighlight.extend({
addNodeView() {
return new VueNodeViewRenderer(FrontmatterWrapper);
},
+ addInputRules() {
+ return [];
+ },
});
diff --git a/app/assets/javascripts/content_editor/extensions/horizontal_rule.js b/app/assets/javascripts/content_editor/extensions/horizontal_rule.js
index c8ec45d835c..c4f31e5f981 100644
--- a/app/assets/javascripts/content_editor/extensions/horizontal_rule.js
+++ b/app/assets/javascripts/content_editor/extensions/horizontal_rule.js
@@ -1,10 +1,10 @@
import { nodeInputRule } from '@tiptap/core';
import { HorizontalRule } from '@tiptap/extension-horizontal-rule';
-export const hrInputRuleRegExp = /^---$/;
-
export default HorizontalRule.extend({
addInputRules() {
- return [nodeInputRule(hrInputRuleRegExp, this.type)];
+ const hrInputRuleRegExp = /^---$/;
+
+ return [nodeInputRule({ find: hrInputRuleRegExp, type: this.type })];
},
});
diff --git a/app/assets/javascripts/content_editor/extensions/html_marks.js b/app/assets/javascripts/content_editor/extensions/html_marks.js
index 54adb9efa0c..3abf0e3eee2 100644
--- a/app/assets/javascripts/content_editor/extensions/html_marks.js
+++ b/app/assets/javascripts/content_editor/extensions/html_marks.js
@@ -60,7 +60,13 @@ export default marks.map((name) =>
},
addInputRules() {
- return [markInputRule(markInputRegex(name), this.type, extractMarkAttributesFromMatch)];
+ return [
+ markInputRule({
+ find: markInputRegex(name),
+ type: this.type,
+ getAttributes: extractMarkAttributesFromMatch,
+ }),
+ ];
},
}),
);
diff --git a/app/assets/javascripts/content_editor/extensions/inline_diff.js b/app/assets/javascripts/content_editor/extensions/inline_diff.js
index 3bd328958df..22bb1ac072e 100644
--- a/app/assets/javascripts/content_editor/extensions/inline_diff.js
+++ b/app/assets/javascripts/content_editor/extensions/inline_diff.js
@@ -1,8 +1,5 @@
import { Mark, markInputRule, mergeAttributes } from '@tiptap/core';
-export const inputRegexAddition = /(\{\+(.+?)\+\})$/gm;
-export const inputRegexDeletion = /(\{-(.+?)-\})$/gm;
-
export default Mark.create({
name: 'inlineDiff',
@@ -38,9 +35,20 @@ export default Mark.create({
},
addInputRules() {
+ const inputRegexAddition = /(\{\+(.+?)\+\})$/gm;
+ const inputRegexDeletion = /(\{-(.+?)-\})$/gm;
+
return [
- markInputRule(inputRegexAddition, this.type, () => ({ type: 'addition' })),
- markInputRule(inputRegexDeletion, this.type, () => ({ type: 'deletion' })),
+ markInputRule({
+ find: inputRegexAddition,
+ type: this.type,
+ getAttributes: () => ({ type: 'addition' }),
+ }),
+ markInputRule({
+ find: inputRegexDeletion,
+ type: this.type,
+ getAttributes: () => ({ type: 'deletion' }),
+ }),
];
},
});
diff --git a/app/assets/javascripts/content_editor/extensions/link.js b/app/assets/javascripts/content_editor/extensions/link.js
index fc0f38e6935..27bc05dce6f 100644
--- a/app/assets/javascripts/content_editor/extensions/link.js
+++ b/app/assets/javascripts/content_editor/extensions/link.js
@@ -1,9 +1,6 @@
import { markInputRule } from '@tiptap/core';
import { Link } from '@tiptap/extension-link';
-export const markdownLinkSyntaxInputRuleRegExp = /(?:^|\s)\[([\w|\s|-]+)\]\((?<href>.+?)\)$/gm;
-export const urlSyntaxRegExp = /(?:^|\s)(?<href>(?:https?:\/\/|www\.)[\S]+)(?:\s|\n)$/gim;
-
const extractHrefFromMatch = (match) => {
return { href: match.groups.href };
};
@@ -26,9 +23,20 @@ export default Link.extend({
openOnClick: false,
},
addInputRules() {
+ const markdownLinkSyntaxInputRuleRegExp = /(?:^|\s)\[([\w|\s|-]+)\]\((?<href>.+?)\)$/gm;
+ const urlSyntaxRegExp = /(?:^|\s)(?<href>(?:https?:\/\/|www\.)[\S]+)(?:\s|\n)$/gim;
+
return [
- markInputRule(markdownLinkSyntaxInputRuleRegExp, this.type, extractHrefFromMarkdownLink),
- markInputRule(urlSyntaxRegExp, this.type, extractHrefFromMatch),
+ markInputRule({
+ find: markdownLinkSyntaxInputRuleRegExp,
+ type: this.type,
+ getAttributes: extractHrefFromMarkdownLink,
+ }),
+ markInputRule({
+ find: urlSyntaxRegExp,
+ type: this.type,
+ getAttributes: extractHrefFromMatch,
+ }),
];
},
addAttributes() {
diff --git a/app/assets/javascripts/content_editor/extensions/math_inline.js b/app/assets/javascripts/content_editor/extensions/math_inline.js
index 60f5288dcf6..4844f6feb29 100644
--- a/app/assets/javascripts/content_editor/extensions/math_inline.js
+++ b/app/assets/javascripts/content_editor/extensions/math_inline.js
@@ -2,8 +2,6 @@ import { Mark, markInputRule } from '@tiptap/core';
import { __ } from '~/locale';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
-export const inputRegex = /(?:^|\s)\$`([^`]+)`\$$/gm;
-
export default Mark.create({
name: 'mathInline',
@@ -30,6 +28,8 @@ export default Mark.create({
},
addInputRules() {
- return [markInputRule(inputRegex, this.type)];
+ const inputRegex = /(?:^|\s)\$`([^`]+)`\$$/gm;
+
+ return [markInputRule({ find: inputRegex, type: this.type })];
},
});
diff --git a/app/assets/javascripts/content_editor/extensions/subscript.js b/app/assets/javascripts/content_editor/extensions/subscript.js
index d0766f42308..a8c087e8bf0 100644
--- a/app/assets/javascripts/content_editor/extensions/subscript.js
+++ b/app/assets/javascripts/content_editor/extensions/subscript.js
@@ -4,6 +4,12 @@ import { markInputRegex, extractMarkAttributesFromMatch } from '../services/mark
export default Subscript.extend({
addInputRules() {
- return [markInputRule(markInputRegex('sub'), this.type, extractMarkAttributesFromMatch)];
+ return [
+ markInputRule({
+ find: markInputRegex('sub'),
+ type: this.type,
+ getAttributes: extractMarkAttributesFromMatch,
+ }),
+ ];
},
});
diff --git a/app/assets/javascripts/content_editor/extensions/superscript.js b/app/assets/javascripts/content_editor/extensions/superscript.js
index 6cd814977ea..b86906f01f2 100644
--- a/app/assets/javascripts/content_editor/extensions/superscript.js
+++ b/app/assets/javascripts/content_editor/extensions/superscript.js
@@ -4,6 +4,12 @@ import { markInputRegex, extractMarkAttributesFromMatch } from '../services/mark
export default Superscript.extend({
addInputRules() {
- return [markInputRule(markInputRegex('sup'), this.type, extractMarkAttributesFromMatch)];
+ return [
+ markInputRule({
+ find: markInputRegex('sup'),
+ type: this.type,
+ getAttributes: extractMarkAttributesFromMatch,
+ }),
+ ];
},
});
diff --git a/app/assets/javascripts/content_editor/extensions/table.js b/app/assets/javascripts/content_editor/extensions/table.js
index 0f0477cba2e..004bb8b815c 100644
--- a/app/assets/javascripts/content_editor/extensions/table.js
+++ b/app/assets/javascripts/content_editor/extensions/table.js
@@ -1 +1,42 @@
-export { Table as default } from '@tiptap/extension-table';
+import { Table } from '@tiptap/extension-table';
+import { debounce } from 'lodash';
+import { __ } from '~/locale';
+import { getMarkdownSource } from '../services/markdown_sourcemap';
+import { shouldRenderHTMLTable } from '../services/serialization_helpers';
+
+let alertShown = false;
+const onUpdate = debounce((editor) => {
+ if (alertShown) return;
+
+ editor.state.doc.descendants((node) => {
+ if (node.type.name === 'table' && node.attrs.isMarkdown && shouldRenderHTMLTable(node)) {
+ editor.emit('alert', {
+ message: __(
+ 'The content editor may change the markdown formatting style of the document, which may not match your original markdown style.',
+ ),
+ variant: 'warning',
+ });
+
+ alertShown = true;
+
+ return false;
+ }
+
+ return true;
+ });
+}, 1000);
+
+export default Table.extend({
+ addAttributes() {
+ return {
+ isMarkdown: {
+ default: null,
+ parseHTML: (element) => Boolean(getMarkdownSource(element)),
+ },
+ };
+ },
+
+ onUpdate({ editor }) {
+ onUpdate(editor);
+ },
+});
diff --git a/app/assets/javascripts/content_editor/extensions/table_cell.js b/app/assets/javascripts/content_editor/extensions/table_cell.js
index befc33e669f..9f437ce066c 100644
--- a/app/assets/javascripts/content_editor/extensions/table_cell.js
+++ b/app/assets/javascripts/content_editor/extensions/table_cell.js
@@ -1,10 +1,9 @@
import { TableCell } from '@tiptap/extension-table-cell';
import { VueNodeViewRenderer } from '@tiptap/vue-2';
import TableCellBodyWrapper from '../components/wrappers/table_cell_body.vue';
-import { isBlockTablesFeatureEnabled } from '../services/feature_flags';
export default TableCell.extend({
- content: isBlockTablesFeatureEnabled() ? 'block+' : 'inline*',
+ content: 'block+',
addNodeView() {
return VueNodeViewRenderer(TableCellBodyWrapper);
diff --git a/app/assets/javascripts/content_editor/extensions/table_header.js b/app/assets/javascripts/content_editor/extensions/table_header.js
index 829b06fc14b..045fd03199b 100644
--- a/app/assets/javascripts/content_editor/extensions/table_header.js
+++ b/app/assets/javascripts/content_editor/extensions/table_header.js
@@ -1,10 +1,9 @@
import { TableHeader } from '@tiptap/extension-table-header';
import { VueNodeViewRenderer } from '@tiptap/vue-2';
import TableCellHeaderWrapper from '../components/wrappers/table_cell_header.vue';
-import { isBlockTablesFeatureEnabled } from '../services/feature_flags';
export default TableHeader.extend({
- content: isBlockTablesFeatureEnabled() ? 'block+' : 'inline*',
+ content: 'block+',
addNodeView() {
return VueNodeViewRenderer(TableCellHeaderWrapper);
},
diff --git a/app/assets/javascripts/content_editor/extensions/table_of_contents.js b/app/assets/javascripts/content_editor/extensions/table_of_contents.js
index 9e31158837e..a8882f9ede4 100644
--- a/app/assets/javascripts/content_editor/extensions/table_of_contents.js
+++ b/app/assets/javascripts/content_editor/extensions/table_of_contents.js
@@ -1,10 +1,7 @@
-import { Node } from '@tiptap/core';
-import { InputRule } from 'prosemirror-inputrules';
+import { Node, InputRule } from '@tiptap/core';
import { s__ } from '~/locale';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
-export const inputRuleRegExps = [/^\[\[_TOC_\]\]$/, /^\[TOC\]$/];
-
export default Node.create({
name: 'tableOfContents',
@@ -34,17 +31,21 @@ export default Node.create({
addInputRules() {
const { type } = this;
+ const inputRuleRegExps = [/^\[\[_TOC_\]\]$/, /^\[TOC\]$/];
return inputRuleRegExps.map(
(regex) =>
- new InputRule(regex, (state, match, start, end) => {
- const { tr } = state;
+ new InputRule({
+ find: regex,
+ handler: ({ state, range: { from, to }, match }) => {
+ const { tr } = state;
- if (match) {
- tr.replaceWith(start - 1, end, type.create());
- }
+ if (match) {
+ tr.replaceWith(from - 1, to, type.create());
+ }
- return tr;
+ return tr;
+ },
}),
);
},
diff --git a/app/assets/javascripts/content_editor/extensions/word_break.js b/app/assets/javascripts/content_editor/extensions/word_break.js
index 93b42466850..fa7e02f8cc8 100644
--- a/app/assets/javascripts/content_editor/extensions/word_break.js
+++ b/app/assets/javascripts/content_editor/extensions/word_break.js
@@ -1,7 +1,5 @@
import { Node, mergeAttributes, nodeInputRule } from '@tiptap/core';
-export const inputRegex = /^<wbr>$/;
-
export default Node.create({
name: 'wordBreak',
inline: true,
@@ -24,6 +22,8 @@ export default Node.create({
},
addInputRules() {
- return [nodeInputRule(inputRegex, this.type)];
+ const inputRegex = /^<wbr>$/;
+
+ return [nodeInputRule({ find: inputRegex, type: this.type })];
},
});
diff --git a/app/assets/javascripts/content_editor/services/feature_flags.js b/app/assets/javascripts/content_editor/services/feature_flags.js
deleted file mode 100644
index 5f7a4595938..00000000000
--- a/app/assets/javascripts/content_editor/services/feature_flags.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export function isBlockTablesFeatureEnabled() {
- return gon.features?.contentEditorBlockTables;
-}
diff --git a/app/assets/javascripts/content_editor/services/serialization_helpers.js b/app/assets/javascripts/content_editor/services/serialization_helpers.js
index b2327555b45..ed5910fca18 100644
--- a/app/assets/javascripts/content_editor/services/serialization_helpers.js
+++ b/app/assets/javascripts/content_editor/services/serialization_helpers.js
@@ -1,5 +1,4 @@
import { uniq } from 'lodash';
-import { isBlockTablesFeatureEnabled } from './feature_flags';
const defaultAttrs = {
td: { colspan: 1, rowspan: 1, colwidth: null },
@@ -75,7 +74,7 @@ function getChildren(node) {
return children;
}
-function shouldRenderHTMLTable(table) {
+export function shouldRenderHTMLTable(table) {
const { rows, cells } = getRowsAndCells(table);
const cellChildCount = Math.max(...cells.map((cell) => cell.childCount));
@@ -282,11 +281,6 @@ export function renderOrderedList(state, node) {
}
export function renderTableCell(state, node) {
- if (!isBlockTablesFeatureEnabled()) {
- state.renderInline(node);
- return;
- }
-
if (!isInBlockTable(node) || containsParagraphWithOnlyText(node)) {
state.renderInline(node.child(0));
} else {
@@ -303,9 +297,7 @@ export function renderTableRow(state, node) {
}
export function renderTable(state, node) {
- if (isBlockTablesFeatureEnabled()) {
- setIsInBlockTable(node, shouldRenderHTMLTable(node));
- }
+ setIsInBlockTable(node, shouldRenderHTMLTable(node));
if (isInBlockTable(node)) renderTagOpen(state, 'table');
@@ -317,9 +309,7 @@ export function renderTable(state, node) {
state.closeBlock(node);
state.flushClose();
- if (isBlockTablesFeatureEnabled()) {
- unsetIsInBlockTable(node);
- }
+ unsetIsInBlockTable(node);
}
export function renderHardBreak(state, node, parent, index) {
diff --git a/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js b/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js
index d26f32a7e7a..9b1cb76f845 100644
--- a/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js
+++ b/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js
@@ -1,5 +1,5 @@
import { mapValues } from 'lodash';
-import { InputRule } from 'prosemirror-inputrules';
+import { InputRule } from '@tiptap/core';
import { ENTER_KEY, BACKSPACE_KEY } from '~/lib/utils/keys';
import Tracking from '~/tracking';
import {
@@ -17,17 +17,20 @@ const trackKeyboardShortcut = (contentType, commandFn, shortcut) => () => {
};
const trackInputRule = (contentType, inputRule) => {
- return new InputRule(inputRule.match, (...args) => {
- const result = inputRule.handler(...args);
+ return new InputRule({
+ find: inputRule.find,
+ handler: (...args) => {
+ const result = inputRule.handler(...args);
- if (result) {
- Tracking.event(undefined, INPUT_RULE_TRACKING_ACTION, {
- label: CONTENT_EDITOR_TRACKING_LABEL,
- property: contentType,
- });
- }
+ if (result !== null) {
+ Tracking.event(undefined, INPUT_RULE_TRACKING_ACTION, {
+ label: CONTENT_EDITOR_TRACKING_LABEL,
+ property: contentType,
+ });
+ }
- return result;
+ return result;
+ },
});
};
diff --git a/app/assets/javascripts/content_editor/services/upload_helpers.js b/app/assets/javascripts/content_editor/services/upload_helpers.js
index 8ac3f719309..f5bf2742748 100644
--- a/app/assets/javascripts/content_editor/services/upload_helpers.js
+++ b/app/assets/javascripts/content_editor/services/upload_helpers.js
@@ -72,8 +72,9 @@ const uploadImage = async ({ editor, file, uploadsPath, renderMarkdown }) => {
);
} catch (e) {
editor.commands.deleteRange({ from: position, to: position + 1 });
- editor.emit('error', {
- error: __('An error occurred while uploading the image. Please try again.'),
+ editor.emit('alert', {
+ message: __('An error occurred while uploading the image. Please try again.'),
+ variant: 'danger',
});
}
};
@@ -102,8 +103,9 @@ const uploadAttachment = async ({ editor, file, uploadsPath, renderMarkdown }) =
);
} catch (e) {
editor.commands.deleteRange({ from, to: from + 1 });
- editor.emit('error', {
- error: __('An error occurred while uploading the file. Please try again.'),
+ editor.emit('alert', {
+ message: __('An error occurred while uploading the file. Please try again.'),
+ variant: 'danger',
});
}
};
diff --git a/app/assets/javascripts/contextual_sidebar.js b/app/assets/javascripts/contextual_sidebar.js
index 08cf0197993..08942374120 100644
--- a/app/assets/javascripts/contextual_sidebar.js
+++ b/app/assets/javascripts/contextual_sidebar.js
@@ -2,6 +2,8 @@ import { GlBreakpointInstance as bp, breakpoints } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
import Cookies from 'js-cookie';
import { debounce } from 'lodash';
+import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
+import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import { parseBoolean } from '~/lib/utils/common_utils';
export const SIDEBAR_COLLAPSED_CLASS = 'js-sidebar-collapsed';
@@ -112,5 +114,8 @@ export default class ContextualSidebar {
const collapse = parseBoolean(Cookies.get('sidebar_collapsed'));
this.toggleCollapsedSidebar(collapse, true);
}
+
+ initInviteMembersModal();
+ initInviteMembersTrigger();
}
}
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
index 9d4eddc510a..73458a463f2 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
@@ -84,7 +84,7 @@ export default {
),
subnetDropdownHelpPath: 'https://console.aws.amazon.com/vpc/home?#subnets',
securityGroupDropdownHelpText: s__(
- 'ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets.',
+ 'ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets.',
),
securityGroupDropdownHelpPath: 'https://console.aws.amazon.com/vpc/home?#securityGroups',
instanceTypesDropdownHelpText: s__(
diff --git a/app/assets/javascripts/create_merge_request_dropdown.js b/app/assets/javascripts/create_merge_request_dropdown.js
index f4a27dc7d1f..ae6e6bf02e4 100644
--- a/app/assets/javascripts/create_merge_request_dropdown.js
+++ b/app/assets/javascripts/create_merge_request_dropdown.js
@@ -54,6 +54,7 @@ export default class CreateMergeRequestDropdown {
this.isCreatingBranch = false;
this.isCreatingMergeRequest = false;
this.isGettingRef = false;
+ this.refCancelToken = null;
this.mergeRequestCreated = false;
this.refDebounce = debounce((value, target) => this.getRef(value, target), 500);
this.refIsValid = true;
@@ -101,9 +102,18 @@ export default class CreateMergeRequestDropdown {
'click',
this.onClickCreateMergeRequestButton.bind(this),
);
+ this.branchInput.addEventListener('input', this.onChangeInput.bind(this));
this.branchInput.addEventListener('keyup', this.onChangeInput.bind(this));
this.dropdownToggle.addEventListener('click', this.onClickSetFocusOnBranchNameInput.bind(this));
+ // Detect for example when user pastes ref using the mouse
+ this.refInput.addEventListener('input', this.onChangeInput.bind(this));
+ // Detect for example when user presses right arrow to apply the suggested ref
this.refInput.addEventListener('keyup', this.onChangeInput.bind(this));
+ // Detect when user clicks inside the input to apply the suggested ref
+ this.refInput.addEventListener('click', this.onChangeInput.bind(this));
+ // Detect when user clicks outside the input to apply the suggested ref
+ this.refInput.addEventListener('blur', this.onChangeInput.bind(this));
+ // Detect when user presses tab to apply the suggested ref
this.refInput.addEventListener('keydown', CreateMergeRequestDropdown.processTab.bind(this));
}
@@ -247,8 +257,12 @@ export default class CreateMergeRequestDropdown {
getRef(ref, target = 'all') {
if (!ref) return false;
+ this.refCancelToken = axios.CancelToken.source();
+
return axios
- .get(`${createEndpoint(this.projectPath, this.refsPath)}${encodeURIComponent(ref)}`)
+ .get(`${createEndpoint(this.projectPath, this.refsPath)}${encodeURIComponent(ref)}`, {
+ cancelToken: this.refCancelToken.token,
+ })
.then(({ data }) => {
const branches = data[Object.keys(data)[0]];
const tags = data[Object.keys(data)[1]];
@@ -267,7 +281,10 @@ export default class CreateMergeRequestDropdown {
return this.updateInputState(target, ref, result);
})
- .catch(() => {
+ .catch((thrown) => {
+ if (axios.isCancel(thrown)) {
+ return false;
+ }
this.unavailable();
this.disable();
createFlash({
@@ -325,14 +342,23 @@ export default class CreateMergeRequestDropdown {
let target;
let value;
+ // User changed input, cancel to prevent previous request from interfering
+ if (this.refCancelToken !== null) {
+ this.refCancelToken.cancel();
+ }
+
if (event.target === this.branchInput) {
target = 'branch';
({ value } = this.branchInput);
} else if (event.target === this.refInput) {
target = 'ref';
- value =
- event.target.value.slice(0, event.target.selectionStart) +
- event.target.value.slice(event.target.selectionEnd);
+ if (event.target === document.activeElement) {
+ value =
+ event.target.value.slice(0, event.target.selectionStart) +
+ event.target.value.slice(event.target.selectionEnd);
+ } else {
+ value = event.target.value;
+ }
} else {
return false;
}
@@ -358,6 +384,7 @@ export default class CreateMergeRequestDropdown {
this.enable();
this.showAvailableMessage(target);
+ this.refDebounce(value, target);
return true;
}
@@ -414,7 +441,8 @@ export default class CreateMergeRequestDropdown {
if (!selectedText || this.refInput.dataset.value === this.suggestedRef) return;
event.preventDefault();
- window.getSelection().removeAllRanges();
+ const caretPositionEnd = this.refInput.value.length;
+ this.refInput.setSelectionRange(caretPositionEnd, caretPositionEnd);
}
removeMessage(target) {
diff --git a/app/assets/javascripts/crm/components/contacts_root.vue b/app/assets/javascripts/crm/components/contacts_root.vue
new file mode 100644
index 00000000000..83c02f7d5fe
--- /dev/null
+++ b/app/assets/javascripts/crm/components/contacts_root.vue
@@ -0,0 +1,80 @@
+<script>
+import { GlLoadingIcon, GlTable } from '@gitlab/ui';
+import createFlash from '~/flash';
+import { s__, __ } from '~/locale';
+import getGroupContactsQuery from './queries/get_group_contacts.query.graphql';
+
+export default {
+ components: {
+ GlLoadingIcon,
+ GlTable,
+ },
+ inject: ['groupFullPath'],
+ data() {
+ return { contacts: [] };
+ },
+ apollo: {
+ contacts: {
+ query() {
+ return getGroupContactsQuery;
+ },
+ variables() {
+ return {
+ groupFullPath: this.groupFullPath,
+ };
+ },
+ update(data) {
+ return this.extractContacts(data);
+ },
+ error(error) {
+ createFlash({
+ message: __('Something went wrong. Please try again.'),
+ error,
+ captureError: true,
+ });
+ },
+ },
+ },
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.contacts.loading;
+ },
+ },
+ methods: {
+ extractContacts(data) {
+ const contacts = data?.group?.contacts?.nodes || [];
+ return contacts.slice().sort((a, b) => a.firstName.localeCompare(b.firstName));
+ },
+ },
+ fields: [
+ { key: 'firstName', sortable: true },
+ { key: 'lastName', sortable: true },
+ { key: 'email', sortable: true },
+ { key: 'phone', sortable: true },
+ { key: 'description', sortable: true },
+ {
+ key: 'organization',
+ formatter: (organization) => {
+ return organization?.name;
+ },
+ sortable: true,
+ },
+ ],
+ i18n: {
+ emptyText: s__('Crm|No contacts found'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-loading-icon v-if="isLoading" class="gl-mt-5" size="lg" />
+ <gl-table
+ v-else
+ :items="contacts"
+ :fields="$options.fields"
+ :empty-text="$options.i18n.emptyText"
+ show-empty
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/crm/components/organizations_root.vue b/app/assets/javascripts/crm/components/organizations_root.vue
new file mode 100644
index 00000000000..98b45d0a042
--- /dev/null
+++ b/app/assets/javascripts/crm/components/organizations_root.vue
@@ -0,0 +1,71 @@
+<script>
+import { GlLoadingIcon, GlTable } from '@gitlab/ui';
+import createFlash from '~/flash';
+import { s__, __ } from '~/locale';
+import getGroupOrganizationsQuery from './queries/get_group_organizations.query.graphql';
+
+export default {
+ components: {
+ GlLoadingIcon,
+ GlTable,
+ },
+ inject: ['groupFullPath'],
+ data() {
+ return { organizations: [] };
+ },
+ apollo: {
+ organizations: {
+ query() {
+ return getGroupOrganizationsQuery;
+ },
+ variables() {
+ return {
+ groupFullPath: this.groupFullPath,
+ };
+ },
+ update(data) {
+ return this.extractOrganizations(data);
+ },
+ error(error) {
+ createFlash({
+ message: __('Something went wrong. Please try again.'),
+ error,
+ captureError: true,
+ });
+ },
+ },
+ },
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.organizations.loading;
+ },
+ },
+ methods: {
+ extractOrganizations(data) {
+ const organizations = data?.group?.organizations?.nodes || [];
+ return organizations.slice().sort((a, b) => a.name.localeCompare(b.name));
+ },
+ },
+ fields: [
+ { key: 'name', sortable: true },
+ { key: 'defaultRate', sortable: true },
+ { key: 'description', sortable: true },
+ ],
+ i18n: {
+ emptyText: s__('Crm|No organizations found'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-loading-icon v-if="isLoading" class="gl-mt-5" size="lg" />
+ <gl-table
+ v-else
+ :items="organizations"
+ :fields="$options.fields"
+ :empty-text="$options.i18n.emptyText"
+ show-empty
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/crm/components/queries/get_group_contacts.query.graphql b/app/assets/javascripts/crm/components/queries/get_group_contacts.query.graphql
new file mode 100644
index 00000000000..f6acd258585
--- /dev/null
+++ b/app/assets/javascripts/crm/components/queries/get_group_contacts.query.graphql
@@ -0,0 +1,22 @@
+query contacts($groupFullPath: ID!) {
+ group(fullPath: $groupFullPath) {
+ __typename
+ id
+ contacts {
+ nodes {
+ __typename
+ id
+ firstName
+ lastName
+ email
+ phone
+ description
+ organization {
+ __typename
+ id
+ name
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/crm/components/queries/get_group_organizations.query.graphql b/app/assets/javascripts/crm/components/queries/get_group_organizations.query.graphql
new file mode 100644
index 00000000000..7c4ec6ec585
--- /dev/null
+++ b/app/assets/javascripts/crm/components/queries/get_group_organizations.query.graphql
@@ -0,0 +1,15 @@
+query organizations($groupFullPath: ID!) {
+ group(fullPath: $groupFullPath) {
+ __typename
+ id
+ organizations {
+ nodes {
+ __typename
+ id
+ name
+ defaultRate
+ description
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/crm/contacts_bundle.js b/app/assets/javascripts/crm/contacts_bundle.js
new file mode 100644
index 00000000000..6438953596e
--- /dev/null
+++ b/app/assets/javascripts/crm/contacts_bundle.js
@@ -0,0 +1,27 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import CrmContactsRoot from './components/contacts_root.vue';
+
+Vue.use(VueApollo);
+
+export default () => {
+ const el = document.getElementById('js-crm-contacts-app');
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ if (!el) {
+ return false;
+ }
+
+ return new Vue({
+ el,
+ apolloProvider,
+ provide: { groupFullPath: el.dataset.groupFullPath },
+ render(createElement) {
+ return createElement(CrmContactsRoot);
+ },
+ });
+};
diff --git a/app/assets/javascripts/crm/organizations_bundle.js b/app/assets/javascripts/crm/organizations_bundle.js
new file mode 100644
index 00000000000..ac9990b9fb4
--- /dev/null
+++ b/app/assets/javascripts/crm/organizations_bundle.js
@@ -0,0 +1,27 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import CrmOrganizationsRoot from './components/organizations_root.vue';
+
+Vue.use(VueApollo);
+
+export default () => {
+ const el = document.getElementById('js-crm-organizations-app');
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ if (!el) {
+ return false;
+ }
+
+ return new Vue({
+ el,
+ apolloProvider,
+ provide: { groupFullPath: el.dataset.groupFullPath },
+ render(createElement) {
+ return createElement(CrmOrganizationsRoot);
+ },
+ });
+};
diff --git a/app/assets/javascripts/cycle_analytics/components/base.vue b/app/assets/javascripts/cycle_analytics/components/base.vue
index 1d98a42ce58..36430e51dd2 100644
--- a/app/assets/javascripts/cycle_analytics/components/base.vue
+++ b/app/assets/javascripts/cycle_analytics/components/base.vue
@@ -2,10 +2,12 @@
import { GlLoadingIcon } from '@gitlab/ui';
import Cookies from 'js-cookie';
import { mapActions, mapState, mapGetters } from 'vuex';
+import { toYmd } from '~/analytics/shared/utils';
import PathNavigation from '~/cycle_analytics/components/path_navigation.vue';
import StageTable from '~/cycle_analytics/components/stage_table.vue';
import ValueStreamFilters from '~/cycle_analytics/components/value_stream_filters.vue';
import ValueStreamMetrics from '~/cycle_analytics/components/value_stream_metrics.vue';
+import UrlSync from '~/vue_shared/components/url_sync.vue';
import { __ } from '~/locale';
import { SUMMARY_METRICS_REQUEST, METRICS_REQUESTS } from '../constants';
@@ -19,6 +21,7 @@ export default {
StageTable,
ValueStreamFilters,
ValueStreamMetrics,
+ UrlSync,
},
props: {
noDataSvgPath: {
@@ -54,6 +57,9 @@ export default {
'pagination',
]),
...mapGetters(['pathNavigationData', 'filterParams']),
+ isLoaded() {
+ return !this.isLoading && !this.isLoadingStage;
+ },
displayStageEvents() {
const { selectedStageEvents, isLoadingStage, isEmptyStage } = this;
return selectedStageEvents.length && !isLoadingStage && !isEmptyStage;
@@ -98,6 +104,16 @@ export default {
metricsRequests() {
return this.features?.cycleAnalyticsForGroups ? METRICS_REQUESTS : SUMMARY_METRICS_REQUEST;
},
+ query() {
+ return {
+ created_after: toYmd(this.createdAfter),
+ created_before: toYmd(this.createdBefore),
+ stage_id: this.selectedStage?.id || null,
+ sort: this.pagination?.sort || null,
+ direction: this.pagination?.direction || null,
+ page: this.pagination?.page || null,
+ };
+ },
},
methods: {
...mapActions([
@@ -176,5 +192,6 @@ export default {
:pagination="pagination"
@handleUpdatePagination="onHandleUpdatePagination"
/>
+ <url-sync v-if="isLoaded" :query="query" />
</div>
</template>
diff --git a/app/assets/javascripts/cycle_analytics/components/metric_popover.vue b/app/assets/javascripts/cycle_analytics/components/metric_popover.vue
new file mode 100644
index 00000000000..8d90e7b2392
--- /dev/null
+++ b/app/assets/javascripts/cycle_analytics/components/metric_popover.vue
@@ -0,0 +1,61 @@
+<script>
+import { GlPopover, GlLink, GlIcon } from '@gitlab/ui';
+
+export default {
+ name: 'MetricPopover',
+ components: {
+ GlPopover,
+ GlLink,
+ GlIcon,
+ },
+ props: {
+ metric: {
+ type: Object,
+ required: true,
+ },
+ target: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ metricLinks() {
+ return this.metric.links?.filter((link) => !link.docs_link) || [];
+ },
+ docsLink() {
+ return this.metric.links?.find((link) => link.docs_link);
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-popover :target="target" placement="bottom">
+ <template #title>
+ <span class="gl-display-block gl-text-left" data-testid="metric-label">{{
+ metric.label
+ }}</span>
+ </template>
+ <div
+ v-for="(link, idx) in metricLinks"
+ :key="`link-${idx}`"
+ class="gl-display-flex gl-justify-content-space-between gl-text-right gl-py-1"
+ data-testid="metric-link"
+ >
+ <span>{{ link.label }}</span>
+ <gl-link :href="link.url" class="gl-font-sm">
+ {{ link.name }}
+ </gl-link>
+ </div>
+ <span v-if="metric.description" data-testid="metric-description">{{ metric.description }}</span>
+ <gl-link
+ v-if="docsLink"
+ :href="docsLink.url"
+ class="gl-font-sm"
+ target="_blank"
+ data-testid="metric-docs-link"
+ >{{ docsLink.label }}
+ <gl-icon name="external-link" class="gl-vertical-align-middle" />
+ </gl-link>
+ </gl-popover>
+</template>
diff --git a/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue b/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue
index 7371ffd2c7c..9671742e564 100644
--- a/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue
+++ b/app/assets/javascripts/cycle_analytics/components/value_stream_metrics.vue
@@ -1,11 +1,13 @@
<script>
-import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlPopover } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import { GlSingleStat } from '@gitlab/ui/dist/charts';
import { flatten } from 'lodash';
import createFlash from '~/flash';
import { sprintf, s__ } from '~/locale';
+import { redirectTo } from '~/lib/utils/url_utility';
import { METRICS_POPOVER_CONTENT } from '../constants';
import { removeFlash, prepareTimeMetricsData } from '../utils';
+import MetricPopover from './metric_popover.vue';
const requestData = ({ request, endpoint, path, params, name }) => {
return request({ endpoint, params, requestPath: path })
@@ -31,9 +33,9 @@ const fetchMetricsData = (reqs = [], path, params) => {
export default {
name: 'ValueStreamMetrics',
components: {
- GlPopover,
GlSingleStat,
GlSkeletonLoading,
+ MetricPopover,
},
props: {
requestPath: {
@@ -76,32 +78,33 @@ export default {
this.isLoading = false;
});
},
+ hasLinks(links) {
+ return links?.length && links[0].url;
+ },
+ clickHandler({ links }) {
+ if (this.hasLinks(links)) {
+ redirectTo(links[0].url);
+ }
+ },
},
};
</script>
<template>
<div class="gl-display-flex gl-flex-wrap" data-testid="vsa-time-metrics">
- <div v-if="isLoading" class="gl-h-auto gl-py-3 gl-pr-9 gl-my-6">
- <gl-skeleton-loading />
+ <gl-skeleton-loading v-if="isLoading" class="gl-h-auto gl-py-3 gl-pr-9 gl-my-6" />
+ <div v-for="metric in metrics" v-show="!isLoading" :key="metric.key" class="gl-my-6 gl-pr-9">
+ <gl-single-stat
+ :id="metric.key"
+ :value="`${metric.value}`"
+ :title="metric.label"
+ :unit="metric.unit || ''"
+ :should-animate="true"
+ :animation-decimal-places="1"
+ :class="{ 'gl-hover-cursor-pointer': hasLinks(metric.links) }"
+ tabindex="0"
+ @click="clickHandler(metric)"
+ />
+ <metric-popover :metric="metric" :target="metric.key" />
</div>
- <template v-else>
- <div v-for="metric in metrics" :key="metric.key" class="gl-my-6 gl-pr-9">
- <gl-single-stat
- :id="metric.key"
- :value="`${metric.value}`"
- :title="metric.label"
- :unit="metric.unit || ''"
- :should-animate="true"
- :animation-decimal-places="1"
- tabindex="0"
- />
- <gl-popover :target="metric.key" placement="bottom">
- <template #title>
- <span class="gl-display-block gl-text-left">{{ metric.label }}</span>
- </template>
- <span v-if="metric.description">{{ metric.description }}</span>
- </gl-popover>
- </div>
- </template>
</div>
</template>
diff --git a/app/assets/javascripts/cycle_analytics/constants.js b/app/assets/javascripts/cycle_analytics/constants.js
index c205aa1e831..7d5822b0824 100644
--- a/app/assets/javascripts/cycle_analytics/constants.js
+++ b/app/assets/javascripts/cycle_analytics/constants.js
@@ -5,8 +5,6 @@ import {
} from '~/api/analytics_api';
import { __, s__ } from '~/locale';
-export const DEFAULT_DAYS_IN_PAST = 30;
-export const DEFAULT_DAYS_TO_DISPLAY = 30;
export const OVERVIEW_STAGE_ID = 'overview';
export const DEFAULT_VALUE_STREAM = {
@@ -47,6 +45,11 @@ export const METRICS_POPOVER_CONTENT = {
"ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed.",
),
},
+ 'lead-time-for-changes': {
+ description: s__(
+ 'ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period.',
+ ),
+ },
'new-issue': { description: s__('ValueStreamAnalytics|Number of new issues created.') },
'new-issues': { description: s__('ValueStreamAnalytics|Number of new issues created.') },
deploys: { description: s__('ValueStreamAnalytics|Total number of deploys to production.') },
diff --git a/app/assets/javascripts/cycle_analytics/index.js b/app/assets/javascripts/cycle_analytics/index.js
index 34ef03409b8..3da8696edeb 100644
--- a/app/assets/javascripts/cycle_analytics/index.js
+++ b/app/assets/javascripts/cycle_analytics/index.js
@@ -1,44 +1,36 @@
import Vue from 'vue';
+import {
+ extractFilterQueryParameters,
+ extractPaginationQueryParameters,
+} from '~/analytics/shared/utils';
import Translate from '../vue_shared/translate';
import CycleAnalytics from './components/base.vue';
-import { DEFAULT_DAYS_TO_DISPLAY } from './constants';
import createStore from './store';
-import { calculateFormattedDayInPast } from './utils';
+import { buildCycleAnalyticsInitialData } from './utils';
Vue.use(Translate);
export default () => {
const store = createStore();
const el = document.querySelector('#js-cycle-analytics');
- const {
- noAccessSvgPath,
- noDataSvgPath,
- requestPath,
- fullPath,
- projectId,
- groupId,
- groupPath,
- labelsPath,
- milestonesPath,
- } = el.dataset;
+ const { noAccessSvgPath, noDataSvgPath } = el.dataset;
+ const initialData = buildCycleAnalyticsInitialData({ ...el.dataset, gon });
- const { now, past } = calculateFormattedDayInPast(DEFAULT_DAYS_TO_DISPLAY);
+ const pagination = extractPaginationQueryParameters(window.location.search);
+ const {
+ selectedAuthor,
+ selectedMilestone,
+ selectedAssigneeList,
+ selectedLabelList,
+ } = extractFilterQueryParameters(window.location.search);
store.dispatch('initializeVsa', {
- projectId: parseInt(projectId, 10),
- endpoints: {
- requestPath,
- fullPath,
- labelsPath,
- milestonesPath,
- groupId: parseInt(groupId, 10),
- groupPath,
- },
- features: {
- cycleAnalyticsForGroups: Boolean(gon?.licensed_features?.cycleAnalyticsForGroups),
- },
- createdBefore: new Date(now),
- createdAfter: new Date(past),
+ ...initialData,
+ selectedAuthor,
+ selectedMilestone,
+ selectedAssigneeList,
+ selectedLabelList,
+ pagination,
});
// eslint-disable-next-line no-new
@@ -52,7 +44,6 @@ export default () => {
props: {
noDataSvgPath,
noAccessSvgPath,
- fullPath,
},
}),
});
diff --git a/app/assets/javascripts/cycle_analytics/store/actions.js b/app/assets/javascripts/cycle_analytics/store/actions.js
index 24b62849db7..e0156b24f9d 100644
--- a/app/assets/javascripts/cycle_analytics/store/actions.js
+++ b/app/assets/javascripts/cycle_analytics/store/actions.js
@@ -14,7 +14,7 @@ import * as types from './mutation_types';
export const setSelectedValueStream = ({ commit, dispatch }, valueStream) => {
commit(types.SET_SELECTED_VALUE_STREAM, valueStream);
- return Promise.all([dispatch('fetchValueStreamStages'), dispatch('fetchCycleAnalyticsData')]);
+ return dispatch('fetchValueStreamStages');
};
export const fetchValueStreamStages = ({ commit, state }) => {
@@ -46,10 +46,8 @@ export const fetchValueStreams = ({ commit, dispatch, state }) => {
} = state;
commit(types.REQUEST_VALUE_STREAMS);
- const stageRequests = ['setSelectedStage', 'fetchStageMedians', 'fetchStageCountValues'];
return getProjectValueStreams(fullPath)
.then(({ data }) => dispatch('receiveValueStreamsSuccess', data))
- .then(() => Promise.all(stageRequests.map((r) => dispatch(r))))
.catch(({ response: { status } }) => {
commit(types.RECEIVE_VALUE_STREAMS_ERROR, status);
});
@@ -153,33 +151,36 @@ export const fetchStageCountValues = ({
});
};
-export const setSelectedStage = ({ dispatch, commit, state: { stages } }, selectedStage = null) => {
- const stage = selectedStage || stages[0];
- commit(types.SET_SELECTED_STAGE, stage);
- return dispatch('fetchStageData');
+export const fetchValueStreamStageData = ({ dispatch }) =>
+ Promise.all([
+ dispatch('fetchCycleAnalyticsData'),
+ dispatch('fetchStageData'),
+ dispatch('fetchStageMedians'),
+ dispatch('fetchStageCountValues'),
+ ]);
+
+export const refetchStageData = async ({ dispatch, commit }) => {
+ commit(types.SET_LOADING, true);
+ await dispatch('fetchValueStreamStageData');
+ commit(types.SET_LOADING, false);
};
-export const setLoading = ({ commit }, value) => commit(types.SET_LOADING, value);
-
-const refetchStageData = (dispatch) => {
- return Promise.resolve()
- .then(() => dispatch('setLoading', true))
- .then(() =>
- Promise.all([
- dispatch('fetchCycleAnalyticsData'),
- dispatch('fetchStageData'),
- dispatch('fetchStageMedians'),
- dispatch('fetchStageCountValues'),
- ]),
- )
- .finally(() => dispatch('setLoading', false));
+export const setSelectedStage = ({ dispatch, commit }, selectedStage = null) => {
+ commit(types.SET_SELECTED_STAGE, selectedStage);
+ return dispatch('refetchStageData');
};
-export const setFilters = ({ dispatch }) => refetchStageData(dispatch);
+export const setFilters = ({ dispatch }) => dispatch('refetchStageData');
export const setDateRange = ({ dispatch, commit }, { createdAfter, createdBefore }) => {
commit(types.SET_DATE_RANGE, { createdAfter, createdBefore });
- return refetchStageData(dispatch);
+ return dispatch('refetchStageData');
+};
+
+export const setInitialStage = ({ dispatch, commit, state: { stages } }, stage) => {
+ const selectedStage = stage || stages[0];
+ commit(types.SET_SELECTED_STAGE, selectedStage);
+ return dispatch('fetchValueStreamStageData');
};
export const updateStageTablePagination = (
@@ -190,12 +191,18 @@ export const updateStageTablePagination = (
return dispatch('fetchStageData', selectedStage.id);
};
-export const initializeVsa = ({ commit, dispatch }, initialData = {}) => {
+export const initializeVsa = async ({ commit, dispatch }, initialData = {}) => {
commit(types.INITIALIZE_VSA, initialData);
const {
endpoints: { fullPath, groupPath, milestonesPath = '', labelsPath = '' },
+ selectedAuthor,
+ selectedMilestone,
+ selectedAssigneeList,
+ selectedLabelList,
+ selectedStage = null,
} = initialData;
+
dispatch('filters/setEndpoints', {
labelsEndpoint: labelsPath,
milestonesEndpoint: milestonesPath,
@@ -203,7 +210,15 @@ export const initializeVsa = ({ commit, dispatch }, initialData = {}) => {
projectEndpoint: fullPath,
});
- return dispatch('setLoading', true)
- .then(() => dispatch('fetchValueStreams'))
- .finally(() => dispatch('setLoading', false));
+ dispatch('filters/initialize', {
+ selectedAuthor,
+ selectedMilestone,
+ selectedAssigneeList,
+ selectedLabelList,
+ });
+
+ commit(types.SET_LOADING, true);
+ await dispatch('fetchValueStreams');
+ await dispatch('setInitialStage', selectedStage);
+ commit(types.SET_LOADING, false);
};
diff --git a/app/assets/javascripts/cycle_analytics/utils.js b/app/assets/javascripts/cycle_analytics/utils.js
index 3c6267bac06..9af63f5f9cc 100644
--- a/app/assets/javascripts/cycle_analytics/utils.js
+++ b/app/assets/javascripts/cycle_analytics/utils.js
@@ -1,7 +1,4 @@
-import dateFormat from 'dateformat';
-import { dateFormats } from '~/analytics/shared/constants';
import { hideFlash } from '~/flash';
-import { getDateInPast } from '~/lib/utils/datetime/date_calculation_utility';
import { parseSeconds } from '~/lib/utils/datetime_utility';
import { formatTimeAsSummary } from '~/lib/utils/datetime/date_format_utility';
import { slugify } from '~/lib/utils/text_utility';
@@ -74,23 +71,6 @@ export const formatMedianValues = (medians = []) =>
export const filterStagesByHiddenStatus = (stages = [], isHidden = true) =>
stages.filter(({ hidden = false }) => hidden === isHidden);
-const toIsoFormat = (d) => dateFormat(d, dateFormats.isoDate);
-
-/**
- * Takes an integer specifying the number of days to subtract
- * from the date specified will return the 2 dates, formatted as ISO dates
- *
- * @param {Number} daysInPast - Number of days in the past to subtract
- * @param {Date} [today=new Date] - Date to subtract days from, defaults to today
- * @returns {Object} Returns 'now' and the 'past' date formatted as ISO dates
- */
-export const calculateFormattedDayInPast = (daysInPast, today = new Date()) => {
- return {
- now: toIsoFormat(today),
- past: toIsoFormat(getDateInPast(today, daysInPast)),
- };
-};
-
/**
* @typedef {Object} MetricData
* @property {String} title - Title of the metric measured
@@ -123,3 +103,43 @@ export const prepareTimeMetricsData = (data = [], popoverContent = {}) =>
description: popoverContent[key]?.description || '',
};
});
+
+const extractFeatures = (gon) => ({
+ cycleAnalyticsForGroups: Boolean(gon?.licensed_features?.cycleAnalyticsForGroups),
+});
+
+/**
+ * Builds the initial data object for Value Stream Analytics with data loaded from the backend
+ *
+ * @param {Object} dataset - dataset object paseed to the frontend via data-* properties
+ * @returns {Object} - The initial data to load the app with
+ */
+export const buildCycleAnalyticsInitialData = ({
+ fullPath,
+ requestPath,
+ projectId,
+ groupId,
+ groupPath,
+ labelsPath,
+ milestonesPath,
+ stage,
+ createdAfter,
+ createdBefore,
+ gon,
+} = {}) => {
+ return {
+ projectId: parseInt(projectId, 10),
+ endpoints: {
+ requestPath,
+ fullPath,
+ labelsPath,
+ milestonesPath,
+ groupId: parseInt(groupId, 10),
+ groupPath,
+ },
+ createdAfter: new Date(createdAfter),
+ createdBefore: new Date(createdBefore),
+ selectedStage: stage ? JSON.parse(stage) : null,
+ features: extractFeatures(gon),
+ };
+};
diff --git a/app/assets/javascripts/deploy_tokens/components/revoke_button.vue b/app/assets/javascripts/deploy_tokens/components/revoke_button.vue
index e026391ae22..fdf8b7796bf 100644
--- a/app/assets/javascripts/deploy_tokens/components/revoke_button.vue
+++ b/app/assets/javascripts/deploy_tokens/components/revoke_button.vue
@@ -62,7 +62,7 @@ export default {
</gl-sprintf>
{{ s__('DeployTokens|This action cannot be undone.') }}
<template #modal-footer>
- <gl-button category="secondary" @click="cancelHandler">{{ s__('Cancel') }}</gl-button>
+ <gl-button category="secondary" @click="cancelHandler">{{ __('Cancel') }}</gl-button>
<gl-button
category="primary"
variant="danger"
diff --git a/app/assets/javascripts/design_management/graphql.js b/app/assets/javascripts/design_management/graphql.js
index fa57537f74e..5cf32cb7fe3 100644
--- a/app/assets/javascripts/design_management/graphql.js
+++ b/app/assets/javascripts/design_management/graphql.js
@@ -88,7 +88,6 @@ const defaultClient = createDefaultClient(
fragmentMatcher,
},
typeDefs,
- assumeImmutableResults: true,
},
);
diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue
index 5092c30aa60..42d5d8fb359 100644
--- a/app/assets/javascripts/design_management/pages/index.vue
+++ b/app/assets/javascripts/design_management/pages/index.vue
@@ -4,7 +4,7 @@ import VueDraggable from 'vuedraggable';
import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql';
import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
import createFlash, { FLASH_TYPES } from '~/flash';
-import { getFilename } from '~/lib/utils/file_upload';
+import { getFilename, validateImageName } from '~/lib/utils/file_upload';
import { __, s__, sprintf } from '~/locale';
import DesignDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
import DeleteButton from '../components/delete_button.vue';
@@ -284,12 +284,16 @@ export default {
return;
}
event.preventDefault();
- let filename = getFilename(event);
- if (!filename || filename === 'image.png') {
- filename = `design_${Date.now()}.png`;
- }
- const newFile = new File([files[0]], filename);
- this.onUploadDesign([newFile]);
+ const fileList = [...files];
+ fileList.forEach((file) => {
+ let filename = getFilename(file);
+ filename = validateImageName(file);
+ if (!filename || filename === 'image.png') {
+ filename = `design_${Date.now()}.png`;
+ }
+ const newFile = new File([file], filename);
+ this.onUploadDesign([newFile]);
+ });
}
},
toggleOnPasteListener() {
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 465f9836140..f405b82b05b 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -44,6 +44,7 @@ import {
TRACKING_MULTIPLE_FILES_MODE,
} from '../constants';
+import { discussionIntersectionObserverHandlerFactory } from '../utils/discussions';
import diffsEventHub from '../event_hub';
import { reviewStatuses } from '../utils/file_reviews';
import { diffsApp } from '../utils/performance';
@@ -86,6 +87,9 @@ export default {
ALERT_MERGE_CONFLICT,
ALERT_COLLAPSED_FILES,
},
+ provide: {
+ discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
+ },
props: {
endpoint: {
type: String,
@@ -392,8 +396,6 @@ export default {
diffsApp.instrument();
},
created() {
- this.mergeRequestContainers = document.querySelectorAll('.merge-request-container');
-
this.adjustView();
this.subscribeToEvents();
@@ -521,13 +523,6 @@ export default {
} else {
this.removeEventListeners();
}
-
- if (!this.isFluidLayout && this.glFeatures.mrChangesFluidLayout) {
- this.mergeRequestContainers.forEach((el) => {
- el.classList.toggle('limit-container-width', !this.shouldShow);
- el.classList.toggle('container-limited', !this.shouldShow);
- });
- }
},
setEventListeners() {
Mousetrap.bind(keysFor(MR_PREVIOUS_FILE_IN_DIFF), () => this.jumpToFile(-1));
@@ -579,7 +574,7 @@ export default {
jumpToFile(step) {
const targetIndex = this.currentDiffIndex + step;
if (targetIndex >= 0 && targetIndex < this.diffFiles.length) {
- this.scrollToFile(this.diffFiles[targetIndex].file_path);
+ this.scrollToFile({ path: this.diffFiles[targetIndex].file_path });
}
},
setTreeDisplay() {
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index 4435a533591..e54fde72847 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButtonGroup, GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { GlButtonGroup, GlButton, GlTooltipDirective, GlSafeHtmlDirective } from '@gitlab/ui';
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
@@ -34,6 +34,7 @@ export default {
},
directives: {
GlTooltip: GlTooltipDirective,
+ SafeHtml: GlSafeHtmlDirective,
},
mixins: [glFeatureFlagsMixin()],
props: {
@@ -88,6 +89,9 @@ export default {
initUserPopovers(this.$el.querySelectorAll('.js-user-link'));
});
},
+ safeHtmlConfig: {
+ ADD_TAGS: ['gl-emoji'],
+ },
};
</script>
@@ -101,7 +105,7 @@ export default {
>
<div
v-if="commit.signature_html"
- v-html="commit.signature_html /* eslint-disable-line vue/no-v-html */"
+ v-safe-html:[$options.safeHtmlConfig]="commit.signature_html"
></div>
<commit-pipeline-status
v-if="commit.pipeline_status_path"
@@ -142,9 +146,9 @@ export default {
<div class="commit-detail flex-list">
<div class="commit-content" data-qa-selector="commit_content">
<a
+ v-safe-html:[$options.safeHtmlConfig]="commit.title_html"
:href="commit.commit_url"
class="commit-row-message item-title"
- v-html="commit.title_html /* eslint-disable-line vue/no-v-html */"
></a>
<span class="commit-row-message d-block d-sm-none">&middot; {{ commit.short_id }}</span>
@@ -174,9 +178,9 @@ export default {
<div>
<pre
v-if="commit.description_html"
+ v-safe-html:[$options.safeHtmlConfig]="commitDescription"
:class="{ 'js-toggle-content': collapsible, 'd-block': !collapsible }"
class="commit-row-description gl-mb-3 gl-text-body"
- v-html="commitDescription /* eslint-disable-line vue/no-v-html */"
></pre>
</div>
</li>
diff --git a/app/assets/javascripts/diffs/components/diff_comment_cell.vue b/app/assets/javascripts/diffs/components/diff_comment_cell.vue
index 4af4b46f94c..a4fae652d02 100644
--- a/app/assets/javascripts/diffs/components/diff_comment_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_comment_cell.vue
@@ -29,6 +29,11 @@ export default {
required: false,
default: false,
},
+ lineRange: {
+ type: Object,
+ required: false,
+ default: null,
+ },
linePosition: {
type: String,
required: false,
@@ -59,6 +64,7 @@ export default {
<diff-line-note-form
:diff-file-hash="diffFileHash"
:line="line"
+ :range="lineRange"
:note-target-line="line"
:help-page-path="helpPagePath"
:line-position="linePosition"
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 4bcb99424db..238f07ac22c 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -14,7 +14,6 @@ import {
import { escape } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
import { IdState } from 'vendor/vue-virtual-scroller';
-import { diffViewerModes } from '~/ide/constants';
import { scrollToElement } from '~/lib/utils/common_utils';
import { truncateSha } from '~/lib/utils/text_utility';
import { __, s__, sprintf } from '~/locale';
@@ -50,7 +49,7 @@ export default {
mixins: [glFeatureFlagsMixin(), IdState({ idProp: (vm) => vm.diffFile.file_hash })],
i18n: {
...DIFF_FILE_HEADER,
- compareButtonLabel: s__('Compare submodule commit revisions'),
+ compareButtonLabel: __('Compare submodule commit revisions'),
},
props: {
discussionPath: {
@@ -130,7 +129,7 @@ export default {
const truncatedOldSha = escape(truncateSha(this.diffFile.submodule_compare.old_sha));
const truncatedNewSha = escape(truncateSha(this.diffFile.submodule_compare.new_sha));
return sprintf(
- s__('Compare %{oldCommitId}...%{newCommitId}'),
+ __('Compare %{oldCommitId}...%{newCommitId}'),
{
oldCommitId: `<span class="commit-sha">${truncatedOldSha}</span>`,
newCommitId: `<span class="commit-sha">${truncatedNewSha}</span>`,
@@ -181,7 +180,7 @@ export default {
return this.diffFile.renamed_file;
},
isModeChanged() {
- return this.diffFile.viewer.name === diffViewerModes.mode_changed;
+ return this.diffFile.mode_changed;
},
expandDiffToFullFileTitle() {
if (this.diffFile.isShowingFullFile) {
@@ -221,7 +220,7 @@ export default {
'toggleFileDiscussions',
'toggleFileDiscussionWrappers',
'toggleFullDiff',
- 'toggleActiveFileByHash',
+ 'setCurrentFileHash',
'reviewFile',
'setFileCollapsedByUser',
]),
@@ -244,7 +243,7 @@ export default {
scrollToElement(document.querySelector(selector));
window.location.hash = selector;
if (!this.viewDiffsFileByFile) {
- this.toggleActiveFileByHash(this.diffFile.file_hash);
+ this.setCurrentFileHash(this.diffFile.file_hash);
}
}
},
diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
index c445989f143..9d355c96af1 100644
--- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
@@ -2,6 +2,7 @@
import { mapState, mapGetters, mapActions } from 'vuex';
import { s__ } from '~/locale';
import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
+import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import MultilineCommentForm from '../../notes/components/multiline_comment_form.vue';
import {
@@ -32,6 +33,11 @@ export default {
type: Object,
required: true,
},
+ range: {
+ type: Object,
+ required: false,
+ default: null,
+ },
linePosition: {
type: String,
required: false,
@@ -49,6 +55,7 @@ export default {
},
data() {
return {
+ lines: null,
commentLineStart: {
line_code: this.line.line_code,
type: this.line.type,
@@ -116,10 +123,8 @@ export default {
return commentLineOptions(lines, this.line, this.line.line_code, side);
},
commentLines() {
- if (!this.selectedCommentPosition) return [];
-
const lines = [];
- const { start, end } = this.selectedCommentPosition;
+ const { start, end } = this.lines;
const diffLines = this.diffFile[INLINE_DIFF_LINES_KEY];
let isAdding = false;
@@ -144,6 +149,13 @@ export default {
return lines;
},
},
+ created() {
+ if (this.range) {
+ this.lines = { ...this.range };
+ } else if (this.line) {
+ this.lines = { start: this.line, end: this.line };
+ }
+ },
mounted() {
if (this.isLoggedIn) {
const keys = [
@@ -166,16 +178,16 @@ export default {
'saveDiffDiscussion',
'setSuggestPopoverDismissed',
]),
- handleCancelCommentForm(shouldConfirm, isDirty) {
+ async handleCancelCommentForm(shouldConfirm, isDirty) {
if (shouldConfirm && isDirty) {
const msg = s__('Notes|Are you sure you want to cancel creating this comment?');
- // eslint-disable-next-line no-alert
- if (!window.confirm(msg)) {
+ const confirmed = await confirmAction(msg);
+
+ if (!confirmed) {
return;
}
}
-
this.cancelCommentForm({
lineCode: this.line.line_code,
fileHash: this.diffFileHash,
@@ -189,6 +201,9 @@ export default {
this.handleCancelCommentForm(),
);
},
+ updateStartLine(line) {
+ this.lines.start = line;
+ },
},
};
</script>
@@ -199,7 +214,9 @@ export default {
<multiline-comment-form
v-model="commentLineStart"
:line="line"
+ :line-range="lines"
:comment-line-options="commentLineOptions"
+ @input="updateStartLine"
/>
</div>
<note-form
diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue
index 64ded1ca8ca..55c796182ee 100644
--- a/app/assets/javascripts/diffs/components/diff_view.vue
+++ b/app/assets/javascripts/diffs/components/diff_view.vue
@@ -6,6 +6,7 @@ import draftCommentsMixin from '~/diffs/mixins/draft_comments';
import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
import { hide } from '~/tooltips';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { pickDirection } from '../utils/diff_line';
import DiffCommentCell from './diff_comment_cell.vue';
import DiffExpansionCell from './diff_expansion_cell.vue';
import DiffRow from './diff_row.vue';
@@ -106,6 +107,16 @@ export default {
});
this.idState.dragStart = null;
},
+ singleLineComment(code, line) {
+ const lineDir = pickDirection({ line, code });
+
+ this.idState.updatedLineRange = {
+ start: lineDir,
+ end: lineDir,
+ };
+
+ this.showCommentForm({ lineCode: lineDir.line_code, fileHash: this.diffFile.file_hash });
+ },
isHighlighted(line) {
return isHighlighted(
this.highlightedRow,
@@ -169,7 +180,7 @@ export default {
:index="index"
:is-highlighted="isHighlighted(line)"
:file-line-coverage="fileLineCoverage"
- @showCommentForm="(lineCode) => showCommentForm({ lineCode, fileHash: diffFile.file_hash })"
+ @showCommentForm="(code) => singleLineComment(code, line)"
@setHighlightedRow="setHighlightedRow"
@toggleLineDiscussions="
({ lineCode, expanded }) =>
@@ -193,6 +204,7 @@ export default {
<diff-comment-cell
v-if="line.left && (line.left.renderDiscussion || line.left.hasCommentForm)"
:line="line.left"
+ :line-range="idState.updatedLineRange"
:diff-file-hash="diffFile.file_hash"
:help-page-path="helpPagePath"
line-position="left"
@@ -206,6 +218,7 @@ export default {
<diff-comment-cell
v-if="line.right && (line.right.renderDiscussion || line.right.hasCommentForm)"
:line="line.right"
+ :line-range="idState.updatedLineRange"
:diff-file-hash="diffFile.file_hash"
:line-index="index"
:help-page-path="helpPagePath"
diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue
index 41d885d3dc1..85e4199d1c1 100644
--- a/app/assets/javascripts/diffs/components/tree_list.vue
+++ b/app/assets/javascripts/diffs/components/tree_list.vue
@@ -98,7 +98,7 @@ export default {
:file-row-component="$options.DiffFileRow"
:current-diff-file-id="currentDiffFileId"
@toggleTreeOpen="toggleTreeOpen"
- @clickFile="scrollToFile"
+ @clickFile="(path) => scrollToFile({ path })"
/>
</template>
<p v-else class="prepend-top-20 append-bottom-20 text-center">
diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js
index 1b1ab59b2b4..260ebdf2141 100644
--- a/app/assets/javascripts/diffs/index.js
+++ b/app/assets/javascripts/diffs/index.js
@@ -138,7 +138,7 @@ export default function initDiffsApp(store) {
...mapActions('diffs', ['toggleFileFinder', 'scrollToFile']),
openFile(file) {
window.mrTabs.tabShown('diffs');
- this.scrollToFile(file.path);
+ this.scrollToFile({ path: file.path });
},
},
render(createElement) {
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index 5c94c6b803b..692cb913a57 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -85,6 +85,12 @@ export const setBaseConfig = ({ commit }, options) => {
viewDiffsFileByFile,
mrReviews,
});
+
+ Array.from(new Set(Object.values(mrReviews).flat())).forEach((id) => {
+ const viewedId = id.replace(/^hash:/, '');
+
+ commit(types.SET_DIFF_FILE_VIEWED, { id: viewedId, seen: true });
+ });
};
export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
@@ -127,7 +133,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
}
if (!isNoteLink && !state.currentDiffFileId) {
- commit(types.VIEW_DIFF_FILE, diff_files[0]?.file_hash);
+ commit(types.SET_CURRENT_DIFF_FILE, diff_files[0]?.file_hash);
}
if (isNoteLink) {
@@ -143,7 +149,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
!state.diffFiles.some((f) => f.file_hash === state.currentDiffFileId) &&
!isNoteLink
) {
- commit(types.VIEW_DIFF_FILE, state.diffFiles[0].file_hash);
+ commit(types.SET_CURRENT_DIFF_FILE, state.diffFiles[0].file_hash);
}
if (state.diffFiles?.length) {
@@ -248,7 +254,7 @@ export const fetchCoverageFiles = ({ commit, state }) => {
export const setHighlightedRow = ({ commit }, lineCode) => {
const fileHash = lineCode.split('_')[0];
commit(types.SET_HIGHLIGHTED_ROW, lineCode);
- commit(types.VIEW_DIFF_FILE, fileHash);
+ commit(types.SET_CURRENT_DIFF_FILE, fileHash);
handleLocationHash();
};
@@ -514,23 +520,25 @@ export const toggleTreeOpen = ({ commit }, path) => {
commit(types.TOGGLE_FOLDER_OPEN, path);
};
-export const toggleActiveFileByHash = ({ commit }, hash) => {
- commit(types.VIEW_DIFF_FILE, hash);
+export const setCurrentFileHash = ({ commit }, hash) => {
+ commit(types.SET_CURRENT_DIFF_FILE, hash);
};
-export const scrollToFile = ({ state, commit, getters }, path) => {
+export const scrollToFile = ({ state, commit, getters }, { path, setHash = true }) => {
if (!state.treeEntries[path]) return;
const { fileHash } = state.treeEntries[path];
- commit(types.VIEW_DIFF_FILE, fileHash);
+ commit(types.SET_CURRENT_DIFF_FILE, fileHash);
if (getters.isVirtualScrollingEnabled) {
eventHub.$emit('scrollToFileHash', fileHash);
- setTimeout(() => {
- window.history.replaceState(null, null, `#${fileHash}`);
- });
+ if (setHash) {
+ setTimeout(() => {
+ window.history.replaceState(null, null, `#${fileHash}`);
+ });
+ }
} else {
document.location.hash = fileHash;
@@ -804,7 +812,7 @@ export const setCurrentDiffFileIdFromNote = ({ commit, state, rootGetters }, not
const fileHash = rootGetters.getDiscussion(note.discussion_id).diff_file?.file_hash;
if (fileHash && state.diffFiles.some((f) => f.file_hash === fileHash)) {
- commit(types.VIEW_DIFF_FILE, fileHash);
+ commit(types.SET_CURRENT_DIFF_FILE, fileHash);
}
};
@@ -812,7 +820,7 @@ export const navigateToDiffFileIndex = ({ commit, state }, index) => {
const fileHash = state.diffFiles[index].file_hash;
document.location.hash = fileHash;
- commit(types.VIEW_DIFF_FILE, fileHash);
+ commit(types.SET_CURRENT_DIFF_FILE, fileHash);
};
export const setFileByFile = ({ state, commit }, { fileByFile }) => {
@@ -848,6 +856,8 @@ export function reviewFile({ commit, state }, { file, reviewed = true }) {
const reviews = markFileReview(state.mrReviews, file, reviewed);
setReviewsForMergeRequest(mrPath, reviews);
+
+ commit(types.SET_DIFF_FILE_VIEWED, { id: file.file_hash, seen: reviewed });
commit(types.SET_MR_FILE_REVIEWS, reviews);
}
diff --git a/app/assets/javascripts/diffs/store/mutation_types.js b/app/assets/javascripts/diffs/store/mutation_types.js
index 60836f747f5..51c21c1bfc4 100644
--- a/app/assets/javascripts/diffs/store/mutation_types.js
+++ b/app/assets/javascripts/diffs/store/mutation_types.js
@@ -20,7 +20,8 @@ export const SET_LINE_DISCUSSIONS_FOR_FILE = 'SET_LINE_DISCUSSIONS_FOR_FILE';
export const REMOVE_LINE_DISCUSSIONS_FOR_FILE = 'REMOVE_LINE_DISCUSSIONS_FOR_FILE';
export const TOGGLE_FOLDER_OPEN = 'TOGGLE_FOLDER_OPEN';
export const SET_SHOW_TREE_LIST = 'SET_SHOW_TREE_LIST';
-export const VIEW_DIFF_FILE = 'VIEW_DIFF_FILE';
+export const SET_CURRENT_DIFF_FILE = 'SET_CURRENT_DIFF_FILE';
+export const SET_DIFF_FILE_VIEWED = 'SET_DIFF_FILE_VIEWED';
export const OPEN_DIFF_FILE_COMMENT_FORM = 'OPEN_DIFF_FILE_COMMENT_FORM';
export const UPDATE_DIFF_FILE_COMMENT_FORM = 'UPDATE_DIFF_FILE_COMMENT_FORM';
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index 6bc927b9d1f..4a9df0eafcc 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -254,9 +254,11 @@ export default {
[types.SET_SHOW_TREE_LIST](state, showTreeList) {
state.showTreeList = showTreeList;
},
- [types.VIEW_DIFF_FILE](state, fileId) {
+ [types.SET_CURRENT_DIFF_FILE](state, fileId) {
state.currentDiffFileId = fileId;
- Vue.set(state.viewedDiffFileIds, fileId, true);
+ },
+ [types.SET_DIFF_FILE_VIEWED](state, { id, seen }) {
+ Vue.set(state.viewedDiffFileIds, id, seen);
},
[types.OPEN_DIFF_FILE_COMMENT_FORM](state, formData) {
state.commentForms.push({
diff --git a/app/assets/javascripts/diffs/utils/diff_line.js b/app/assets/javascripts/diffs/utils/diff_line.js
new file mode 100644
index 00000000000..a248cc6318b
--- /dev/null
+++ b/app/assets/javascripts/diffs/utils/diff_line.js
@@ -0,0 +1,10 @@
+export function pickDirection({ line, code } = {}) {
+ const { left, right } = line;
+ let direction = left || right;
+
+ if (right?.line_code === code) {
+ direction = right;
+ }
+
+ return direction;
+}
diff --git a/app/assets/javascripts/diffs/utils/discussions.js b/app/assets/javascripts/diffs/utils/discussions.js
new file mode 100644
index 00000000000..c404705d209
--- /dev/null
+++ b/app/assets/javascripts/diffs/utils/discussions.js
@@ -0,0 +1,76 @@
+function normalize(processable) {
+ const { entry } = processable;
+ const offset = entry.rootBounds.bottom - entry.boundingClientRect.top;
+ const direction =
+ offset < 0 ? 'Up' : 'Down'; /* eslint-disable-line @gitlab/require-i18n-strings */
+
+ return {
+ ...processable,
+ entry: {
+ time: entry.time,
+ type: entry.isIntersecting ? 'intersection' : `scroll${direction}`,
+ },
+ };
+}
+
+function sort({ entry: alpha }, { entry: beta }) {
+ const diff = alpha.time - beta.time;
+ let order = 0;
+
+ if (diff < 0) {
+ order = -1;
+ } else if (diff > 0) {
+ order = 1;
+ } else if (alpha.type === 'intersection' && beta.type === 'scrollUp') {
+ order = 2;
+ } else if (alpha.type === 'scrollUp' && beta.type === 'intersection') {
+ order = -2;
+ }
+
+ return order;
+}
+
+function filter(entry) {
+ return entry.type !== 'scrollDown';
+}
+
+export function discussionIntersectionObserverHandlerFactory() {
+ let unprocessed = [];
+ let timer = null;
+
+ return (processable) => {
+ unprocessed.push(processable);
+
+ if (timer) {
+ clearTimeout(timer);
+ }
+
+ timer = setTimeout(() => {
+ unprocessed
+ .map(normalize)
+ .filter(filter)
+ .sort(sort)
+ .forEach((discussionObservationContainer) => {
+ const {
+ entry: { type },
+ currentDiscussion,
+ isFirstUnresolved,
+ isDiffsPage,
+ functions: { setCurrentDiscussionId, getPreviousUnresolvedDiscussionId },
+ } = discussionObservationContainer;
+
+ if (type === 'intersection') {
+ setCurrentDiscussionId(currentDiscussion.id);
+ } else if (type === 'scrollUp') {
+ setCurrentDiscussionId(
+ isFirstUnresolved
+ ? null
+ : getPreviousUnresolvedDiscussionId(currentDiscussion.id, isDiffsPage),
+ );
+ }
+ });
+
+ unprocessed = [];
+ }, 0);
+ };
+}
diff --git a/app/assets/javascripts/diffs/utils/file_reviews.js b/app/assets/javascripts/diffs/utils/file_reviews.js
index 7a4b1aa6b17..227be4e4a6c 100644
--- a/app/assets/javascripts/diffs/utils/file_reviews.js
+++ b/app/assets/javascripts/diffs/utils/file_reviews.js
@@ -52,8 +52,10 @@ export function markFileReview(reviews, file, reviewed = true) {
if (reviewed) {
fileReviews.add(file.id);
+ fileReviews.add(`hash:${file.file_hash}`);
} else {
fileReviews.delete(file.id);
+ fileReviews.delete(`hash:${file.file_hash}`);
}
updatedReviews[file.file_identifier_hash] = Array.from(fileReviews);
diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js
index f98f63529fc..f404fa4e0e8 100644
--- a/app/assets/javascripts/dropzone_input.js
+++ b/app/assets/javascripts/dropzone_input.js
@@ -43,7 +43,6 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
let pasteText;
let addFileToForm;
let updateAttachingMessage;
- let isImage;
let uploadFile;
formTextarea.wrap('<div class="div-dropzone"></div>');
@@ -173,7 +172,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
return dropzoneInstance.addFile(file);
});
});
- // eslint-disable-next-line consistent-return
+
handlePaste = (event) => {
const pasteEvent = event.originalEvent;
const { clipboardData } = pasteEvent;
@@ -186,32 +185,22 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
const text = converter.convertToTableMarkdown();
pasteText(text);
} else {
- const image = isImage(pasteEvent);
-
- if (image) {
- event.preventDefault();
- const MAX_FILE_NAME_LENGTH = 246;
- const filename = getFilename(pasteEvent) || 'image.png';
- const truncateFilename = truncate(filename, MAX_FILE_NAME_LENGTH);
- const text = `{{${truncateFilename}}}`;
- pasteText(text);
-
- return uploadFile(image.getAsFile(), truncateFilename);
- }
- }
- }
- };
-
- isImage = (data) => {
- let i = 0;
- while (i < data.clipboardData.items.length) {
- const item = data.clipboardData.items[i];
- if (item.type.indexOf('image') !== -1) {
- return item;
+ const fileList = [...clipboardData.files];
+ fileList.forEach((file) => {
+ if (file.type.indexOf('image') !== -1) {
+ event.preventDefault();
+ const MAX_FILE_NAME_LENGTH = 246;
+
+ const filename = getFilename(file) || 'image.png';
+ const truncateFilename = truncate(filename, MAX_FILE_NAME_LENGTH);
+ const text = `{{${truncateFilename}}}`;
+ pasteText(text);
+
+ uploadFile(file, truncateFilename);
+ }
+ });
}
- i += 1;
}
- return false;
};
pasteText = (text, shouldPad) => {
diff --git a/app/assets/javascripts/editor/constants.js b/app/assets/javascripts/editor/constants.js
index d40d19000fb..e855e304d27 100644
--- a/app/assets/javascripts/editor/constants.js
+++ b/app/assets/javascripts/editor/constants.js
@@ -1,17 +1,9 @@
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
-import { __ } from '~/locale';
-
-export const SOURCE_EDITOR_INSTANCE_ERROR_NO_EL = __(
- '"el" parameter is required for createInstance()',
-);
+import { s__ } from '~/locale';
export const URI_PREFIX = 'gitlab';
export const CONTENT_UPDATE_DEBOUNCE = DEFAULT_DEBOUNCE_AND_THROTTLE_MS;
-export const ERROR_INSTANCE_REQUIRED_FOR_EXTENSION = __(
- 'Source Editor instance is required to set up an extension.',
-);
-
export const EDITOR_READY_EVENT = 'editor-ready';
export const EDITOR_TYPE_CODE = 'vs.editor.ICodeEditor';
@@ -20,6 +12,32 @@ export const EDITOR_TYPE_DIFF = 'vs.editor.IDiffEditor';
export const EDITOR_CODE_INSTANCE_FN = 'createInstance';
export const EDITOR_DIFF_INSTANCE_FN = 'createDiffInstance';
+export const SOURCE_EDITOR_INSTANCE_ERROR_NO_EL = s__(
+ 'SourceEditor|"el" parameter is required for createInstance()',
+);
+export const ERROR_INSTANCE_REQUIRED_FOR_EXTENSION = s__(
+ 'SourceEditor|Source Editor instance is required to set up an extension.',
+);
+export const EDITOR_EXTENSION_DEFINITION_ERROR = s__(
+ 'SourceEditor|Extension definition should be either a class or a function',
+);
+export const EDITOR_EXTENSION_NO_DEFINITION_ERROR = s__(
+ 'SourceEditor|`definition` property is expected on the extension.',
+);
+export const EDITOR_EXTENSION_DEFINITION_TYPE_ERROR = s__(
+ 'SourceEditor|Extension definition should be either class, function, or an Array of definitions.',
+);
+export const EDITOR_EXTENSION_NOT_SPECIFIED_FOR_UNUSE_ERROR = s__(
+ 'SourceEditor|No extension for unuse has been specified.',
+);
+export const EDITOR_EXTENSION_NOT_REGISTERED_ERROR = s__('SourceEditor|%{name} is not registered.');
+export const EDITOR_EXTENSION_NAMING_CONFLICT_ERROR = s__(
+ 'SourceEditor|Name conflict for "%{prop}()" method.',
+);
+export const EDITOR_EXTENSION_STORE_IS_MISSING_ERROR = s__(
+ 'SourceEditor|Extensions Store is required to check for an extension.',
+);
+
//
// EXTENSIONS' CONSTANTS
//
diff --git a/app/assets/javascripts/editor/extensions/example_source_editor_extension.js b/app/assets/javascripts/editor/extensions/example_source_editor_extension.js
new file mode 100644
index 00000000000..119a2aea9eb
--- /dev/null
+++ b/app/assets/javascripts/editor/extensions/example_source_editor_extension.js
@@ -0,0 +1,116 @@
+// THIS IS AN EXAMPLE
+//
+// This file contains a basic documented example of the Source Editor extensions'
+// API for your convenience. You can copy/paste it into your own file
+// and adjust as you see fit
+//
+
+export class MyFancyExtension {
+ /**
+ * THE LIFE-CYCLE CALLBACKS
+ */
+
+ /**
+ * Is called before the extension gets used by an instance,
+ * Use `onSetup` to setup Monaco directly:
+ * actions, keystrokes, update options, etc.
+ * Is called only once before the extension gets registered
+ *
+ * @param { Object } [setupOptions] The setupOptions object
+ * @param { Object } [instance] The Source Editor instance
+ */
+ // eslint-disable-next-line class-methods-use-this,no-unused-vars
+ onSetup(setupOptions, instance) {}
+
+ /**
+ * The first thing called after the extension is
+ * registered and used by an instance.
+ * Is called every time the extension is applied
+ *
+ * @param { Object } [instance] The Source Editor instance
+ */
+ // eslint-disable-next-line class-methods-use-this,no-unused-vars
+ onUse(instance) {}
+
+ /**
+ * Is called before un-using an extension. Can be used for time-critical
+ * actions like cleanup, reverting visual changes, and other user-facing
+ * updates.
+ *
+ * @param { Object } [instance] The Source Editor instance
+ */
+ // eslint-disable-next-line class-methods-use-this,no-unused-vars
+ onBeforeUnuse(instance) {}
+
+ /**
+ * Is called right after an extension is removed from an instance (un-used)
+ * Can be used for non time-critical tasks like cleanup on the Monaco level
+ * (removing actions, keystrokes, etc.).
+ * onUnuse() will be executed during the browser's idle period
+ * (https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback)
+ *
+ * @param { Object } [instance] The Source Editor instance
+ */
+ // eslint-disable-next-line class-methods-use-this,no-unused-vars
+ onUnuse(instance) {}
+
+ /**
+ * The public API of the extension: these are the methods that will be exposed
+ * to the end user
+ * @returns {Object}
+ */
+ provides() {
+ return {
+ basic: () => {
+ // The most basic method not depending on anything
+ // Use: instance.basic();
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return 'Foo Bar';
+ },
+ basicWithProp: () => {
+ // The methods with access to the props of the extension.
+ // The props can be either hardcoded (for example in `onSetup`), or
+ // can be dynamically passed as part of `setupOptions` object when
+ // using the extension.
+ // Use: instance.use({ definition: MyFancyExtension, setupOptions: { foo: 'bar' }});
+ return this.foo;
+ },
+ basicWithPropsAsList: (prop1, prop2) => {
+ // Just a simple method with local props
+ // The props are passed as usually.
+ // Use: instance.basicWithPropsAsList(prop1, prop2);
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `The prop1 is ${prop1}; the prop2 is ${prop2}`;
+ },
+ basicWithInstance: (instance) => {
+ // The method accessing the instance methods: either own or provided
+ // by previously-registered extensions
+ // `instance` is always supplied to all methods in provides() as THE LAST
+ // argument.
+ // You don't need to explicitly pass instance to this method:
+ // Use: instance.basicWithInstance();
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `We have access to the whole Instance! ${instance.alpha()}`;
+ },
+ advancedWithInstanceAndProps: ({ author, book } = {}, firstname, lastname, instance) => {
+ // Advanced method where
+ // { author, book } — are the props passed as an object
+ // prop1, prop2 — are the props passed as simple list
+ // instance — is automatically supplied, no need to pass it to
+ // the method explicitly
+ // Use: instance.advancedWithInstanceAndProps(
+ // {
+ // author: 'Franz Kafka',
+ // book: 'The Transformation'
+ // },
+ // 'Franz',
+ // 'Kafka'
+ // );
+ return `
+The author is ${author}; the book is ${book}
+The author's name is ${firstname}; the last name is ${lastname}
+We have access to the whole Instance! For example, 'instance.alpha()': ${instance.alpha()}`;
+ },
+ };
+ }
+}
diff --git a/app/assets/javascripts/editor/extensions/source_editor_extension_base.js b/app/assets/javascripts/editor/extensions/source_editor_extension_base.js
index 5fa01f03f7e..03c68fed3b1 100644
--- a/app/assets/javascripts/editor/extensions/source_editor_extension_base.js
+++ b/app/assets/javascripts/editor/extensions/source_editor_extension_base.js
@@ -36,12 +36,24 @@ export class SourceEditorExtension {
});
}
- static highlightLines(instance) {
- const { hash } = window.location;
- if (!hash) {
- return;
- }
- const [start, end] = hash.replace(hashRegexp, '').split('-');
+ static removeHighlights(instance) {
+ Object.assign(instance, {
+ lineDecorations: instance.deltaDecorations(instance.lineDecorations || [], []),
+ });
+ }
+
+ /**
+ * Returns a function that can only be invoked once between
+ * each browser screen repaint.
+ * @param {Object} instance - The Source Editor instance
+ * @param {Array} bounds - The [start, end] array with start
+ * and end coordinates for highlighting
+ */
+ static highlightLines(instance, bounds = null) {
+ const [start, end] =
+ bounds && Array.isArray(bounds)
+ ? bounds
+ : window.location.hash?.replace(hashRegexp, '').split('-');
let startLine = start ? parseInt(start, 10) : null;
let endLine = end ? parseInt(end, 10) : startLine;
if (endLine < startLine) {
@@ -51,15 +63,12 @@ export class SourceEditorExtension {
window.requestAnimationFrame(() => {
instance.revealLineInCenter(startLine);
Object.assign(instance, {
- lineDecorations: instance.deltaDecorations(
- [],
- [
- {
- range: new Range(startLine, 1, endLine, 1),
- options: { isWholeLine: true, className: 'active-line-text' },
- },
- ],
- ),
+ lineDecorations: instance.deltaDecorations(instance.lineDecorations || [], [
+ {
+ range: new Range(startLine, 1, endLine, 1),
+ options: { isWholeLine: true, className: 'active-line-text' },
+ },
+ ]),
});
});
}
diff --git a/app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js b/app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js
new file mode 100644
index 00000000000..212e09c8724
--- /dev/null
+++ b/app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js
@@ -0,0 +1,293 @@
+import { toPath } from 'lodash';
+import { parseDocument, Document, visit, isScalar, isCollection, isMap } from 'yaml';
+import { findPair } from 'yaml/util';
+import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
+
+export class YamlEditorExtension extends SourceEditorExtension {
+ /**
+ * Extends the source editor with capabilities for yaml files.
+ *
+ * @param { Instance } instance Source Editor Instance
+ * @param { boolean } enableComments Convert model nodes with the comment
+ * pattern to comments?
+ * @param { string } highlightPath Add a line highlight to the
+ * node specified by this e.g. `"foo.bar[0]"`
+ * @param { * } model Any JS Object that will be stringified and used as the
+ * editor's value. Equivalent to using `setDataModel()`
+ * @param options SourceEditorExtension Options
+ */
+ constructor({
+ instance,
+ enableComments = false,
+ highlightPath = null,
+ model = null,
+ ...options
+ } = {}) {
+ super({
+ instance,
+ options: {
+ ...options,
+ enableComments,
+ highlightPath,
+ },
+ });
+
+ if (model) {
+ YamlEditorExtension.initFromModel(instance, model);
+ }
+
+ instance.onDidChangeModelContent(() => instance.onUpdate());
+ }
+
+ /**
+ * @private
+ */
+ static initFromModel(instance, model) {
+ const doc = new Document(model);
+ if (instance.options.enableComments) {
+ YamlEditorExtension.transformComments(doc);
+ }
+ instance.setValue(doc.toString());
+ }
+
+ /**
+ * @private
+ * This wraps long comments to a maximum line length of 80 chars.
+ *
+ * The `yaml` package does not currently wrap comments. This function
+ * is a local workaround and should be deprecated if
+ * https://github.com/eemeli/yaml/issues/322
+ * is resolved.
+ */
+ static wrapCommentString(string, level = 0) {
+ if (!string) {
+ return null;
+ }
+ if (level < 0 || Number.isNaN(parseInt(level, 10))) {
+ throw Error(`Invalid value "${level}" for variable \`level\``);
+ }
+ const maxLineWidth = 80;
+ const indentWidth = 2;
+ const commentMarkerWidth = '# '.length;
+ const maxLength = maxLineWidth - commentMarkerWidth - level * indentWidth;
+ const lines = [[]];
+ string.split(' ').forEach((word) => {
+ const currentLine = lines.length - 1;
+ if ([...lines[currentLine], word].join(' ').length <= maxLength) {
+ lines[currentLine].push(word);
+ } else {
+ lines.push([word]);
+ }
+ });
+ return lines.map((line) => ` ${line.join(' ')}`).join('\n');
+ }
+
+ /**
+ * @private
+ *
+ * This utilizes `yaml`'s `visit` function to transform nodes with a
+ * comment key pattern to actual comments.
+ *
+ * In Objects, a key of '#' will be converted to a comment at the top of a
+ * property. Any key following the pattern `#|<some key>` will be placed
+ * right before `<some key>`.
+ *
+ * In Arrays, any string that starts with # (including the space), will
+ * be converted to a comment at the position it was in.
+ *
+ * @param { Document } doc
+ * @returns { Document }
+ */
+ static transformComments(doc) {
+ const getLevel = (path) => {
+ const { length } = path.filter((x) => isCollection(x));
+ return length ? length - 1 : 0;
+ };
+
+ visit(doc, {
+ Pair(_, pair, path) {
+ const key = pair.key.value;
+ // If the key is = '#', we add the value as a comment to the parent
+ // We can then remove the node.
+ if (key === '#') {
+ Object.assign(path[path.length - 1], {
+ commentBefore: YamlEditorExtension.wrapCommentString(pair.value.value, getLevel(path)),
+ });
+ return visit.REMOVE;
+ }
+ // If the key starts with `#|`, we want to add a comment to the
+ // corresponding property. We can then remove the node.
+ if (key.startsWith('#|')) {
+ const targetProperty = key.split('|')[1];
+ const target = findPair(path[path.length - 1].items, targetProperty);
+ if (target) {
+ target.key.commentBefore = YamlEditorExtension.wrapCommentString(
+ pair.value.value,
+ getLevel(path),
+ );
+ }
+ return visit.REMOVE;
+ }
+ return undefined; // If the node is not a comment, do nothing with it
+ },
+ // Sequence is basically an array
+ Seq(_, node, path) {
+ let comment = null;
+ const items = node.items.flatMap((child) => {
+ if (comment) {
+ Object.assign(child, { commentBefore: comment });
+ comment = null;
+ }
+ if (
+ isScalar(child) &&
+ child.value &&
+ child.value.startsWith &&
+ child.value.startsWith('#')
+ ) {
+ const commentValue = child.value.replace(/^#\s?/, '');
+ comment = YamlEditorExtension.wrapCommentString(commentValue, getLevel(path));
+ return [];
+ }
+ return child;
+ });
+ Object.assign(node, { items });
+ // Adding a comment in case the last one is a comment
+ if (comment) {
+ Object.assign(node, { comment });
+ }
+ },
+ });
+ return doc;
+ }
+
+ /**
+ * Get the editor's value parsed as a `Document` as defined by the `yaml`
+ * package
+ * @returns {Document}
+ */
+ getDoc() {
+ return parseDocument(this.getValue());
+ }
+
+ /**
+ * Accepts a `Document` as defined by the `yaml` package and
+ * sets the Editor's value to a stringified version of it.
+ * @param { Document } doc
+ */
+ setDoc(doc) {
+ if (this.options.enableComments) {
+ YamlEditorExtension.transformComments(doc);
+ }
+
+ if (!this.getValue()) {
+ this.setValue(doc.toString());
+ } else {
+ this.updateValue(doc.toString());
+ }
+ }
+
+ /**
+ * Returns the parsed value of the Editor's content as JS.
+ * @returns {*}
+ */
+ getDataModel() {
+ return this.getDoc().toJS();
+ }
+
+ /**
+ * Accepts any JS Object and sets the Editor's value to a stringified version
+ * of that value.
+ *
+ * @param value
+ */
+ setDataModel(value) {
+ this.setDoc(new Document(value));
+ }
+
+ /**
+ * Method to be executed when the Editor's <TextModel> was updated
+ */
+ onUpdate() {
+ if (this.options.highlightPath) {
+ this.highlight(this.options.highlightPath);
+ }
+ }
+
+ /**
+ * Set the editors content to the input without recreating the content model.
+ *
+ * @param blob
+ */
+ updateValue(blob) {
+ // Using applyEdits() instead of setValue() ensures that tokens such as
+ // highlighted lines aren't deleted/recreated which causes a flicker.
+ const model = this.getModel();
+ model.applyEdits([
+ {
+ // A nice improvement would be to replace getFullModelRange() with
+ // a range of the actual diff, avoiding re-formatting the document,
+ // but that's something for a later iteration.
+ range: model.getFullModelRange(),
+ text: blob,
+ },
+ ]);
+ }
+
+ /**
+ * Add a line highlight style to the node specified by the path.
+ *
+ * @param {string|null|false} path A path to a node of the Editor's value,
+ * e.g. `"foo.bar[0]"`. If the value is falsy, this will remove all
+ * highlights.
+ */
+ highlight(path) {
+ if (this.options.highlightPath === path) return;
+ if (!path) {
+ SourceEditorExtension.removeHighlights(this);
+ } else {
+ const res = this.locate(path);
+ SourceEditorExtension.highlightLines(this, res);
+ }
+ this.options.highlightPath = path || null;
+ }
+
+ /**
+ * Return the line numbers of a certain node identified by `path` within
+ * the yaml.
+ *
+ * @param {string} path A path to a node, eg. `foo.bar[0]`
+ * @returns {number[]} Array following the schema `[firstLine, lastLine]`
+ * (both inclusive)
+ *
+ * @throws {Error} Will throw if the path is not found inside the document
+ */
+ locate(path) {
+ if (!path) throw Error(`No path provided.`);
+ const blob = this.getValue();
+ const doc = parseDocument(blob);
+ const pathArray = toPath(path);
+
+ if (!doc.getIn(pathArray)) {
+ throw Error(`The node ${path} could not be found inside the document.`);
+ }
+
+ const parentNode = doc.getIn(pathArray.slice(0, pathArray.length - 1));
+ let startChar;
+ let endChar;
+ if (isMap(parentNode)) {
+ const node = parentNode.items.find(
+ (item) => item.key.value === pathArray[pathArray.length - 1],
+ );
+ [startChar] = node.key.range;
+ [, , endChar] = node.value.range;
+ } else {
+ const node = doc.getIn(pathArray);
+ [startChar, , endChar] = node.range;
+ }
+ const startSlice = blob.slice(0, startChar);
+ const endSlice = blob.slice(0, endChar);
+ const startLine = (startSlice.match(/\n/g) || []).length + 1;
+ const endLine = (endSlice.match(/\n/g) || []).length;
+ return [startLine, endLine];
+ }
+}
diff --git a/app/assets/javascripts/editor/schema/ci.json b/app/assets/javascripts/editor/schema/ci.json
index 0052bc00406..f0db3e5594b 100644
--- a/app/assets/javascripts/editor/schema/ci.json
+++ b/app/assets/javascripts/editor/schema/ci.json
@@ -63,9 +63,9 @@
"items": {
"type": "object",
"properties": {
- "if": {
- "type": "string"
- },
+ "if": { "$ref": "#/definitions/if" },
+ "changes": { "$ref": "#/definitions/changes" },
+ "exists": { "$ref": "#/definitions/exists" },
"variables": { "$ref": "#/definitions/variables" },
"when": {
"type": "string",
@@ -497,24 +497,9 @@
"type": "object",
"additionalProperties": false,
"properties": {
- "if": {
- "type": "string",
- "description": "Expression to evaluate whether additional attributes should be provided to the job"
- },
- "changes": {
- "type": "array",
- "description": "Additional attributes will be provided to job if any of the provided paths matches a modified file",
- "items": {
- "type": "string"
- }
- },
- "exists": {
- "type": "array",
- "description": "Additional attributes will be provided to job if any of the provided paths matches an existing file in the repository",
- "items": {
- "type": "string"
- }
- },
+ "if": { "$ref": "#/definitions/if" },
+ "changes": { "$ref": "#/definitions/changes" },
+ "exists": { "$ref": "#/definitions/exists" },
"variables": { "$ref": "#/definitions/variables" },
"when": { "$ref": "#/definitions/when" },
"start_in": { "$ref": "#/definitions/start_in" },
@@ -541,6 +526,24 @@
]
}
},
+ "if": {
+ "type": "string",
+ "description": "Expression to evaluate whether additional attributes should be provided to the job"
+ },
+ "changes": {
+ "type": "array",
+ "description": "Additional attributes will be provided to job if any of the provided paths matches a modified file",
+ "items": {
+ "type": "string"
+ }
+ },
+ "exists": {
+ "type": "array",
+ "description": "Additional attributes will be provided to job if any of the provided paths matches an existing file in the repository",
+ "items": {
+ "type": "string"
+ }
+ },
"variables": {
"type": "object",
"description": "Defines environment variables for specific jobs. Job level property overrides global variables. If a job sets `variables: {}`, all global variables are turned off.",
@@ -555,7 +558,7 @@
},
"start_in": {
"type": "string",
- "description": "Used in conjunction with 'when: delayed' to set how long to delay before starting a job.",
+ "description": "Used in conjunction with 'when: delayed' to set how long to delay before starting a job. e.g. '5', 5 seconds, 30 minutes, 1 week, etc. Read more: https://docs.gitlab.com/ee/ci/jobs/job_control.html#run-a-job-after-a-delay",
"minLength": 1
},
"allow_failure": {
@@ -939,7 +942,7 @@
"stage": {
"type": "string",
"description": "Define what stage the job will run in.",
- "default": "test"
+ "minLength": 1
},
"only": {
"$ref": "#/definitions/filter",
diff --git a/app/assets/javascripts/editor/source_editor_extension.js b/app/assets/javascripts/editor/source_editor_extension.js
new file mode 100644
index 00000000000..f6bc62a1c09
--- /dev/null
+++ b/app/assets/javascripts/editor/source_editor_extension.js
@@ -0,0 +1,17 @@
+import { EDITOR_EXTENSION_DEFINITION_ERROR } from './constants';
+
+export default class EditorExtension {
+ constructor({ definition, setupOptions } = {}) {
+ if (typeof definition !== 'function') {
+ throw new Error(EDITOR_EXTENSION_DEFINITION_ERROR);
+ }
+ this.name = definition.name; // both class- and fn-based extensions have a name
+ this.setupOptions = setupOptions;
+ // eslint-disable-next-line new-cap
+ this.obj = new definition();
+ }
+
+ get api() {
+ return this.obj.provides?.();
+ }
+}
diff --git a/app/assets/javascripts/editor/source_editor_instance.js b/app/assets/javascripts/editor/source_editor_instance.js
new file mode 100644
index 00000000000..e0ca4ea518b
--- /dev/null
+++ b/app/assets/javascripts/editor/source_editor_instance.js
@@ -0,0 +1,271 @@
+/**
+ * @module source_editor_instance
+ */
+
+/**
+ * A Source Editor Extension definition
+ * @typedef {Object} SourceEditorExtensionDefinition
+ * @property {Object} definition
+ * @property {Object} setupOptions
+ */
+
+/**
+ * A Source Editor Extension
+ * @typedef {Object} SourceEditorExtension
+ * @property {Object} obj
+ * @property {string} name
+ * @property {Object} api
+ */
+
+import { isEqual } from 'lodash';
+import { editor as monacoEditor } from 'monaco-editor';
+import { getBlobLanguage } from '~/editor/utils';
+import { logError } from '~/lib/logger';
+import { sprintf } from '~/locale';
+import EditorExtension from './source_editor_extension';
+import {
+ EDITOR_EXTENSION_DEFINITION_TYPE_ERROR,
+ EDITOR_EXTENSION_NAMING_CONFLICT_ERROR,
+ EDITOR_EXTENSION_NO_DEFINITION_ERROR,
+ EDITOR_EXTENSION_NOT_REGISTERED_ERROR,
+ EDITOR_EXTENSION_NOT_SPECIFIED_FOR_UNUSE_ERROR,
+ EDITOR_EXTENSION_STORE_IS_MISSING_ERROR,
+} from './constants';
+
+const utils = {
+ removeExtFromMethod: (method, extensionName, container) => {
+ if (!container) {
+ return;
+ }
+ if (Object.prototype.hasOwnProperty.call(container, method)) {
+ // eslint-disable-next-line no-param-reassign
+ delete container[method];
+ }
+ },
+
+ getStoredExtension: (extensionsStore, name) => {
+ if (!extensionsStore) {
+ logError(EDITOR_EXTENSION_STORE_IS_MISSING_ERROR);
+ return undefined;
+ }
+ return extensionsStore.get(name);
+ },
+};
+
+/** Class representing a Source Editor Instance */
+export default class EditorInstance {
+ /**
+ * Create a Source Editor Instance
+ * @param {Object} rootInstance - Monaco instance to build on top of
+ * @param {Map} extensionsStore - The global registry for the extension instances
+ * @returns {Object} - A Proxy returning props/methods from either registered extensions, or Source Editor instance, or underlying Monaco instance
+ */
+ constructor(rootInstance = {}, extensionsStore = new Map()) {
+ /** The methods provided by extensions. */
+ this.methods = {};
+
+ const seInstance = this;
+ const getHandler = {
+ get(target, prop, receiver) {
+ const methodExtension =
+ Object.prototype.hasOwnProperty.call(seInstance.methods, prop) &&
+ seInstance.methods[prop];
+ if (methodExtension) {
+ const extension = extensionsStore.get(methodExtension);
+
+ return (...args) => {
+ return extension.api[prop].call(seInstance, ...args, receiver);
+ };
+ }
+ return Reflect.get(seInstance[prop] ? seInstance : target, prop, receiver);
+ },
+ set(target, prop, value) {
+ Object.assign(seInstance, {
+ [prop]: value,
+ });
+ return true;
+ },
+ };
+ const instProxy = new Proxy(rootInstance, getHandler);
+
+ /**
+ * Main entry point to apply an extension to the instance
+ * @param {SourceEditorExtensionDefinition}
+ */
+ this.use = EditorInstance.useUnuse.bind(instProxy, extensionsStore, this.useExtension);
+
+ /**
+ * Main entry point to un-use an extension and remove it from the instance
+ * @param {SourceEditorExtension}
+ */
+ this.unuse = EditorInstance.useUnuse.bind(instProxy, extensionsStore, this.unuseExtension);
+
+ return instProxy;
+ }
+
+ /**
+ * A private dispatcher function for both `use` and `unuse`
+ * @param {Map} extensionsStore - The global registry for the extension instances
+ * @param {Function} fn - A function to route to. Either `this.useExtension` or `this.unuseExtension`
+ * @param {SourceEditorExtensionDefinition[]} extensions - The extensions to use/unuse.
+ * @returns {Function}
+ */
+ static useUnuse(extensionsStore, fn, extensions) {
+ if (Array.isArray(extensions)) {
+ /**
+ * We cut short if the Array is empty and let the destination function to throw
+ * Otherwise, we run the destination function on every entry of the Array
+ */
+ return extensions.length
+ ? extensions.map(fn.bind(this, extensionsStore))
+ : fn.call(this, extensionsStore);
+ }
+ return fn.call(this, extensionsStore, extensions);
+ }
+
+ //
+ // REGISTERING NEW EXTENSION
+ //
+
+ /**
+ * Run all registrations when using an extension
+ * @param {Map} extensionsStore - The global registry for the extension instances
+ * @param {SourceEditorExtensionDefinition} extension - The extension definition to use.
+ * @returns {EditorExtension|*}
+ */
+ useExtension(extensionsStore, extension = {}) {
+ const { definition } = extension;
+ if (!definition) {
+ throw new Error(EDITOR_EXTENSION_NO_DEFINITION_ERROR);
+ }
+ if (typeof definition !== 'function') {
+ throw new Error(EDITOR_EXTENSION_DEFINITION_TYPE_ERROR);
+ }
+
+ // Existing Extension Path
+ const existingExt = utils.getStoredExtension(extensionsStore, definition.name);
+ if (existingExt) {
+ if (isEqual(extension.setupOptions, existingExt.setupOptions)) {
+ return existingExt;
+ }
+ this.unuseExtension(extensionsStore, existingExt);
+ }
+
+ // New Extension Path
+ const extensionInstance = new EditorExtension(extension);
+ const { setupOptions, obj: extensionObj } = extensionInstance;
+ if (extensionObj.onSetup) {
+ extensionObj.onSetup(setupOptions, this);
+ }
+ if (extensionsStore) {
+ this.registerExtension(extensionInstance, extensionsStore);
+ }
+ this.registerExtensionMethods(extensionInstance);
+ return extensionInstance;
+ }
+
+ /**
+ * Register extension in the global extensions store
+ * @param {SourceEditorExtension} extension - Instance of Source Editor extension
+ * @param {Map} extensionsStore - The global registry for the extension instances
+ */
+ registerExtension(extension, extensionsStore) {
+ const { name } = extension;
+ const hasExtensionRegistered =
+ extensionsStore.has(name) &&
+ isEqual(extension.setupOptions, extensionsStore.get(name).setupOptions);
+ if (hasExtensionRegistered) {
+ return;
+ }
+ extensionsStore.set(name, extension);
+ const { obj: extensionObj } = extension;
+ if (extensionObj.onUse) {
+ extensionObj.onUse(this);
+ }
+ }
+
+ /**
+ * Register extension methods in the registry on the instance
+ * @param {SourceEditorExtension} extension - Instance of Source Editor extension
+ */
+ registerExtensionMethods(extension) {
+ const { api, name } = extension;
+
+ if (!api) {
+ return;
+ }
+
+ Object.keys(api).forEach((prop) => {
+ if (this[prop]) {
+ logError(sprintf(EDITOR_EXTENSION_NAMING_CONFLICT_ERROR, { prop }));
+ } else {
+ this.methods[prop] = name;
+ }
+ }, this);
+ }
+
+ //
+ // UNREGISTERING AN EXTENSION
+ //
+
+ /**
+ * Unregister extension with the cleanup
+ * @param {Map} extensionsStore - The global registry for the extension instances
+ * @param {SourceEditorExtension} extension - Instance of Source Editor extension to un-use
+ */
+ unuseExtension(extensionsStore, extension) {
+ if (!extension) {
+ throw new Error(EDITOR_EXTENSION_NOT_SPECIFIED_FOR_UNUSE_ERROR);
+ }
+ const { name } = extension;
+ const existingExt = utils.getStoredExtension(extensionsStore, name);
+ if (!existingExt) {
+ throw new Error(sprintf(EDITOR_EXTENSION_NOT_REGISTERED_ERROR, { name }));
+ }
+ const { obj: extensionObj } = existingExt;
+ if (extensionObj.onBeforeUnuse) {
+ extensionObj.onBeforeUnuse(this);
+ }
+ this.unregisterExtensionMethods(existingExt);
+ if (extensionObj.onUnuse) {
+ extensionObj.onUnuse(this);
+ }
+ }
+
+ /**
+ * Remove all methods associated with this extension from the registry on the instance
+ * @param {SourceEditorExtension} extension - Instance of Source Editor extension to un-use
+ */
+ unregisterExtensionMethods(extension) {
+ const { api, name } = extension;
+ if (!api) {
+ return;
+ }
+ Object.keys(api).forEach((method) => {
+ utils.removeExtFromMethod(method, name, this.methods);
+ });
+ }
+
+ /**
+ * PUBLIC API OF AN INSTANCE
+ */
+
+ /**
+ * Updates model language based on the path
+ * @param {String} path - blob path
+ */
+ updateModelLanguage(path) {
+ const lang = getBlobLanguage(path);
+ const model = this.getModel();
+ // return monacoEditor.setModelLanguage(model, lang);
+ monacoEditor.setModelLanguage(model, lang);
+ }
+
+ /**
+ * Get the methods returned by extensions.
+ * @returns {Array}
+ */
+ get extensionsAPI() {
+ return Object.keys(this.methods);
+ }
+}
diff --git a/app/assets/javascripts/emoji/index.js b/app/assets/javascripts/emoji/index.js
index 7672151af2a..478e3f6aed9 100644
--- a/app/assets/javascripts/emoji/index.js
+++ b/app/assets/javascripts/emoji/index.js
@@ -9,6 +9,7 @@ let emojiMap = null;
let validEmojiNames = null;
export const FALLBACK_EMOJI_KEY = 'grey_question';
+// Keep the version in sync with `lib/gitlab/emoji.rb`
export const EMOJI_VERSION = '1';
const isLocalStorageAvailable = AccessorUtilities.canUseLocalStorage();
diff --git a/app/assets/javascripts/environments/components/delete_environment_modal.vue b/app/assets/javascripts/environments/components/delete_environment_modal.vue
index 2eb2be351b3..26ec882472b 100644
--- a/app/assets/javascripts/environments/components/delete_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/delete_environment_modal.vue
@@ -1,6 +1,6 @@
<script>
import { GlTooltipDirective, GlModal } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
import eventHub from '../event_hub';
export default {
@@ -27,7 +27,7 @@ export default {
},
cancelProps() {
return {
- text: s__('Cancel'),
+ text: __('Cancel'),
};
},
confirmDeleteMessage() {
diff --git a/app/assets/javascripts/environments/components/new_environment_folder.vue b/app/assets/javascripts/environments/components/new_environment_folder.vue
new file mode 100644
index 00000000000..0615bdef537
--- /dev/null
+++ b/app/assets/javascripts/environments/components/new_environment_folder.vue
@@ -0,0 +1,69 @@
+<script>
+import { GlCollapse, GlIcon, GlBadge, GlLink } from '@gitlab/ui';
+import folderQuery from '../graphql/queries/folder.query.graphql';
+
+export default {
+ components: {
+ GlCollapse,
+ GlIcon,
+ GlBadge,
+ GlLink,
+ },
+ props: {
+ nestedEnvironment: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return { visible: false };
+ },
+ apollo: {
+ folder: {
+ query: folderQuery,
+ variables() {
+ return { environment: this.nestedEnvironment.latest };
+ },
+ },
+ },
+ computed: {
+ icons() {
+ return this.visible
+ ? { caret: 'angle-down', folder: 'folder-open' }
+ : { caret: 'angle-right', folder: 'folder-o' };
+ },
+ count() {
+ return this.folder?.availableCount ?? 0;
+ },
+ folderClass() {
+ return { 'gl-font-weight-bold': this.visible };
+ },
+ folderPath() {
+ return this.nestedEnvironment.latest.folderPath;
+ },
+ },
+ methods: {
+ toggleCollapse() {
+ this.visible = !this.visible;
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-border-b-solid gl-border-gray-100 gl-border-1 gl-px-3 gl-pt-3 gl-pb-5">
+ <div class="gl-w-full gl-display-flex gl-align-items-center" @click="toggleCollapse">
+ <gl-icon
+ class="gl-mr-2 gl-fill-current-color gl-text-gray-500"
+ :name="icons.caret"
+ :size="12"
+ />
+ <gl-icon class="gl-mr-2 gl-fill-current-color gl-text-gray-500" :name="icons.folder" />
+ <div class="gl-mr-2 gl-text-gray-500" :class="folderClass">
+ {{ nestedEnvironment.name }}
+ </div>
+ <gl-badge size="sm" class="gl-mr-auto">{{ count }}</gl-badge>
+ <gl-link v-if="visible" :href="folderPath">{{ s__('Environments|Show all') }}</gl-link>
+ </div>
+ <gl-collapse :visible="visible" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/environments/components/new_environments_app.vue b/app/assets/javascripts/environments/components/new_environments_app.vue
new file mode 100644
index 00000000000..a5526f9cd71
--- /dev/null
+++ b/app/assets/javascripts/environments/components/new_environments_app.vue
@@ -0,0 +1,47 @@
+<script>
+import { GlBadge, GlTab, GlTabs } from '@gitlab/ui';
+import environmentAppQuery from '../graphql/queries/environmentApp.query.graphql';
+import EnvironmentFolder from './new_environment_folder.vue';
+
+export default {
+ components: {
+ EnvironmentFolder,
+ GlBadge,
+ GlTab,
+ GlTabs,
+ },
+ apollo: {
+ environmentApp: {
+ query: environmentAppQuery,
+ },
+ },
+ computed: {
+ folders() {
+ return this.environmentApp?.environments.filter((e) => e.size > 1) ?? [];
+ },
+ availableCount() {
+ return this.environmentApp?.availableCount;
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-tabs>
+ <gl-tab>
+ <template #title>
+ <span>{{ __('Available') }}</span>
+ <gl-badge size="sm" class="gl-tab-counter-badge">
+ {{ availableCount }}
+ </gl-badge>
+ </template>
+ <environment-folder
+ v-for="folder in folders"
+ :key="folder.name"
+ class="gl-mb-3"
+ :nested-environment="folder"
+ />
+ </gl-tab>
+ </gl-tabs>
+ </div>
+</template>
diff --git a/app/assets/javascripts/environments/components/rollback_modal_manager.vue b/app/assets/javascripts/environments/components/rollback_modal_manager.vue
index 6aa7d96fdfd..3a8b9ebcb84 100644
--- a/app/assets/javascripts/environments/components/rollback_modal_manager.vue
+++ b/app/assets/javascripts/environments/components/rollback_modal_manager.vue
@@ -15,7 +15,6 @@ export default {
data() {
return {
environment: null,
- retryPath: '',
visible: false,
};
},
@@ -35,9 +34,9 @@ export default {
name: environmentName,
commitShortSha,
commitUrl,
+ retryUrl: retryPath,
isLastDeployment: parseBoolean(isLastDeployment),
};
- this.retryPath = retryPath;
this.visible = true;
});
});
@@ -51,7 +50,5 @@ export default {
v-model="visible"
:environment="environment"
:has-multiple-commits="false"
- :retry-url="retryPath"
/>
- <div v-else></div>
</template>
diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
index f248e9ec079..206381e0b7e 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js
+++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
@@ -8,7 +8,7 @@ Vue.use(Translate);
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
export default () => {
diff --git a/app/assets/javascripts/environments/graphql/client.js b/app/assets/javascripts/environments/graphql/client.js
new file mode 100644
index 00000000000..c734c2fba0c
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/client.js
@@ -0,0 +1,25 @@
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import environmentApp from './queries/environmentApp.query.graphql';
+import { resolvers } from './resolvers';
+import typeDefs from './typedefs.graphql';
+
+export const apolloProvider = (endpoint) => {
+ const defaultClient = createDefaultClient(resolvers(endpoint), {
+ typeDefs,
+ });
+ const { cache } = defaultClient;
+
+ cache.writeQuery({
+ query: environmentApp,
+ data: {
+ availableCount: 0,
+ environments: [],
+ reviewApp: {},
+ stoppedCount: 0,
+ },
+ });
+ return new VueApollo({
+ defaultClient,
+ });
+};
diff --git a/app/assets/javascripts/environments/graphql/mutations/cancel_auto_stop.mutation.graphql b/app/assets/javascripts/environments/graphql/mutations/cancel_auto_stop.mutation.graphql
new file mode 100644
index 00000000000..22dfb8a7a89
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/mutations/cancel_auto_stop.mutation.graphql
@@ -0,0 +1,5 @@
+mutation cancelAutoStop($environment: LocalEnvironment) {
+ cancelAutoStop(environment: $environment) @client {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/environments/graphql/mutations/delete_environment.mutation.graphql b/app/assets/javascripts/environments/graphql/mutations/delete_environment.mutation.graphql
new file mode 100644
index 00000000000..9bb68857923
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/mutations/delete_environment.mutation.graphql
@@ -0,0 +1,5 @@
+mutation deleteEnvironment($environment: LocalEnvironment) {
+ deleteEnvironment(environment: $environment) @client {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/environments/graphql/mutations/rollback_environment.mutation.graphql b/app/assets/javascripts/environments/graphql/mutations/rollback_environment.mutation.graphql
new file mode 100644
index 00000000000..3db4dc2b9a5
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/mutations/rollback_environment.mutation.graphql
@@ -0,0 +1,5 @@
+mutation rollbackEnvironment($environment: LocalEnvironment) {
+ rollbackEnvironment(environment: $environment) @client {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/environments/graphql/mutations/stop_environment.mutation.graphql b/app/assets/javascripts/environments/graphql/mutations/stop_environment.mutation.graphql
new file mode 100644
index 00000000000..7eae0ef4ce4
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/mutations/stop_environment.mutation.graphql
@@ -0,0 +1,5 @@
+mutation stopEnvironment($environment: LocalEnvironment) {
+ stopEnvironment(environment: $environment) @client {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/environments/graphql/mutations/update_canary_ingress.mutation.graphql b/app/assets/javascripts/environments/graphql/mutations/update_canary_ingress.mutation.graphql
index 04ea5cbcaef..936bf49a1ac 100644
--- a/app/assets/javascripts/environments/graphql/mutations/update_canary_ingress.mutation.graphql
+++ b/app/assets/javascripts/environments/graphql/mutations/update_canary_ingress.mutation.graphql
@@ -1,4 +1,4 @@
-mutation($input: EnvironmentsCanaryIngressUpdateInput!) {
+mutation updateCanaryIngress($input: EnvironmentsCanaryIngressUpdateInput!) {
environmentsCanaryIngressUpdate(input: $input) {
errors
}
diff --git a/app/assets/javascripts/environments/graphql/queries/environmentApp.query.graphql b/app/assets/javascripts/environments/graphql/queries/environmentApp.query.graphql
new file mode 100644
index 00000000000..faa76c0a42c
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/queries/environmentApp.query.graphql
@@ -0,0 +1,8 @@
+query getEnvironmentApp {
+ environmentApp @client {
+ availableCount
+ environments
+ reviewApp
+ stoppedCount
+ }
+}
diff --git a/app/assets/javascripts/environments/graphql/queries/folder.query.graphql b/app/assets/javascripts/environments/graphql/queries/folder.query.graphql
new file mode 100644
index 00000000000..3292c916b2e
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/queries/folder.query.graphql
@@ -0,0 +1,7 @@
+query getEnvironmentFolder($environment: NestedLocalEnvironment) {
+ folder(environment: $environment) @client {
+ availableCount
+ environments
+ stoppedCount
+ }
+}
diff --git a/app/assets/javascripts/environments/graphql/resolvers.js b/app/assets/javascripts/environments/graphql/resolvers.js
new file mode 100644
index 00000000000..8322b806370
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/resolvers.js
@@ -0,0 +1,50 @@
+import axios from '~/lib/utils/axios_utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+
+const mapNestedEnvironment = (env) => ({
+ ...convertObjectPropsToCamelCase(env, { deep: true }),
+ __typename: 'NestedLocalEnvironment',
+});
+const mapEnvironment = (env) => ({
+ ...convertObjectPropsToCamelCase(env),
+ __typename: 'LocalEnvironment',
+});
+
+export const resolvers = (endpoint) => ({
+ Query: {
+ environmentApp() {
+ return axios.get(endpoint, { params: { nested: true } }).then((res) => ({
+ availableCount: res.data.available_count,
+ environments: res.data.environments.map(mapNestedEnvironment),
+ reviewApp: {
+ ...convertObjectPropsToCamelCase(res.data.review_app),
+ __typename: 'ReviewApp',
+ },
+ stoppedCount: res.data.stopped_count,
+ __typename: 'LocalEnvironmentApp',
+ }));
+ },
+ folder(_, { environment: { folderPath } }) {
+ return axios.get(folderPath, { params: { per_page: 3 } }).then((res) => ({
+ availableCount: res.data.available_count,
+ environments: res.data.environments.map(mapEnvironment),
+ stoppedCount: res.data.stopped_count,
+ __typename: 'LocalEnvironmentFolder',
+ }));
+ },
+ },
+ Mutations: {
+ stopEnvironment(_, { environment: { stopPath } }) {
+ return axios.post(stopPath);
+ },
+ deleteEnvironment(_, { environment: { deletePath } }) {
+ return axios.delete(deletePath);
+ },
+ rollbackEnvironment(_, { environment: { retryUrl } }) {
+ return axios.post(retryUrl);
+ },
+ cancelAutoStop(_, { environment: { autoStopPath } }) {
+ return axios.post(autoStopPath);
+ },
+ },
+});
diff --git a/app/assets/javascripts/environments/graphql/typedefs.graphql b/app/assets/javascripts/environments/graphql/typedefs.graphql
new file mode 100644
index 00000000000..49ea719449e
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/typedefs.graphql
@@ -0,0 +1,35 @@
+type LocalEnvironment {
+ id: Int!
+ globalId: ID!
+ name: String!
+ folderPath: String
+ stopPath: String
+ deletePath: String
+ retryUrl: String
+ autoStopPath: String
+}
+
+type NestedLocalEnvironment {
+ name: String!
+ size: Int!
+ latest: LocalEnvironment!
+}
+
+type LocalEnvironmentFolder {
+ environments: [LocalEnvironment!]!
+ availableCount: Int!
+ stoppedCount: Int!
+}
+
+type ReviewApp {
+ canSetupReviewApp: Boolean!
+ allClustersEmpty: Boolean!
+ reviewSnippet: String
+}
+
+type LocalEnvironmentApp {
+ stoppedCount: Int!
+ availableCount: Int!
+ environments: [NestedLocalEnvironment!]!
+ reviewApp: ReviewApp!
+}
diff --git a/app/assets/javascripts/environments/index.js b/app/assets/javascripts/environments/index.js
index 5e33923d518..3b1d35c1f22 100644
--- a/app/assets/javascripts/environments/index.js
+++ b/app/assets/javascripts/environments/index.js
@@ -9,40 +9,43 @@ Vue.use(Translate);
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
-export default () => {
- const el = document.getElementById('environments-list-view');
- return new Vue({
- el,
- components: {
- environmentsComponent,
- },
- apolloProvider,
- provide: {
- projectPath: el.dataset.projectPath,
- defaultBranchName: el.dataset.defaultBranchName,
- },
- data() {
- const environmentsData = el.dataset;
+export default (el) => {
+ if (el) {
+ return new Vue({
+ el,
+ components: {
+ environmentsComponent,
+ },
+ apolloProvider,
+ provide: {
+ projectPath: el.dataset.projectPath,
+ defaultBranchName: el.dataset.defaultBranchName,
+ },
+ data() {
+ const environmentsData = el.dataset;
- return {
- endpoint: environmentsData.environmentsDataEndpoint,
- newEnvironmentPath: environmentsData.newEnvironmentPath,
- helpPagePath: environmentsData.helpPagePath,
- canCreateEnvironment: parseBoolean(environmentsData.canCreateEnvironment),
- };
- },
- render(createElement) {
- return createElement('environments-component', {
- props: {
- endpoint: this.endpoint,
- newEnvironmentPath: this.newEnvironmentPath,
- helpPagePath: this.helpPagePath,
- canCreateEnvironment: this.canCreateEnvironment,
- },
- });
- },
- });
+ return {
+ endpoint: environmentsData.environmentsDataEndpoint,
+ newEnvironmentPath: environmentsData.newEnvironmentPath,
+ helpPagePath: environmentsData.helpPagePath,
+ canCreateEnvironment: parseBoolean(environmentsData.canCreateEnvironment),
+ };
+ },
+ render(createElement) {
+ return createElement('environments-component', {
+ props: {
+ endpoint: this.endpoint,
+ newEnvironmentPath: this.newEnvironmentPath,
+ helpPagePath: this.helpPagePath,
+ canCreateEnvironment: this.canCreateEnvironment,
+ },
+ });
+ },
+ });
+ }
+
+ return null;
};
diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js
index 85cff73cc3e..0f9741784d6 100644
--- a/app/assets/javascripts/environments/mixins/environments_mixin.js
+++ b/app/assets/javascripts/environments/mixins/environments_mixin.js
@@ -6,7 +6,7 @@ import Visibility from 'visibilityjs';
import createFlash from '~/flash';
import Poll from '../../lib/utils/poll';
import { getParameterByName } from '../../lib/utils/url_utility';
-import { s__ } from '../../locale';
+import { s__, __ } from '../../locale';
import tabs from '../../vue_shared/components/navigation_tabs.vue';
import tablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import container from '../components/container.vue';
@@ -207,13 +207,13 @@ export default {
tabs() {
return [
{
- name: s__('Available'),
+ name: __('Available'),
scope: 'available',
count: this.state.availableCounter,
isActive: this.scope === 'available',
},
{
- name: s__('Stopped'),
+ name: __('Stopped'),
scope: 'stopped',
count: this.state.stoppedCounter,
isActive: this.scope === 'stopped',
diff --git a/app/assets/javascripts/environments/new_index.js b/app/assets/javascripts/environments/new_index.js
new file mode 100644
index 00000000000..dd5c709c75a
--- /dev/null
+++ b/app/assets/javascripts/environments/new_index.js
@@ -0,0 +1,38 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { parseBoolean } from '../lib/utils/common_utils';
+import { apolloProvider } from './graphql/client';
+import EnvironmentsApp from './components/new_environments_app.vue';
+
+Vue.use(VueApollo);
+
+export default (el) => {
+ if (el) {
+ const {
+ canCreateEnvironment,
+ endpoint,
+ newEnvironmentPath,
+ helpPagePath,
+ projectPath,
+ defaultBranchName,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ apolloProvider: apolloProvider(endpoint),
+ provide: {
+ projectPath,
+ defaultBranchName,
+ endpoint,
+ newEnvironmentPath,
+ helpPagePath,
+ canCreateEnvironment: parseBoolean(canCreateEnvironment),
+ },
+ render(h) {
+ return h(EnvironmentsApp);
+ },
+ });
+ }
+
+ return null;
+};
diff --git a/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue b/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
index 2b8a31da50f..34d01f21da2 100644
--- a/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
+++ b/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltip, GlSprintf, GlIcon } from '@gitlab/ui';
+import { GlTooltip, GlSprintf, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
@@ -12,6 +12,7 @@ export default {
},
directives: {
GlTooltip,
+ SafeHtml,
},
props: {
lines: {
@@ -129,9 +130,9 @@ export default {
{{ lineNum(line) }}
</td>
<td
+ v-safe-html="lineCode(line)"
class="line_content"
:class="{ old: isHighlighted(lineNum(line)) }"
- v-html="lineCode(line) /* eslint-disable-line vue/no-v-html */"
></td>
</tr>
</template>
diff --git a/app/assets/javascripts/experimentation/utils.js b/app/assets/javascripts/experimentation/utils.js
index 624a04fd7c2..dcb6a8e20a3 100644
--- a/app/assets/javascripts/experimentation/utils.js
+++ b/app/assets/javascripts/experimentation/utils.js
@@ -3,11 +3,24 @@ import { get } from 'lodash';
import { DEFAULT_VARIANT, CANDIDATE_VARIANT, TRACKING_CONTEXT_SCHEMA } from './constants';
function getExperimentsData() {
- return get(window, ['gon', 'experiment'], {});
+ // Pull from deprecated window.gon.experiment
+ const experimentsFromGon = get(window, ['gon', 'experiment'], {});
+ // Pull from preferred window.gl.experiments
+ const experimentsFromGl = get(window, ['gl', 'experiments'], {});
+
+ return { ...experimentsFromGon, ...experimentsFromGl };
}
function convertExperimentDataToExperimentContext(experimentData) {
- return { schema: TRACKING_CONTEXT_SCHEMA, data: experimentData };
+ // Bandaid to allow-list only the properties which the current gitlab_experiment context schema suppports.
+ // See TRACKING_CONTEXT_SCHEMA for current version (1-0-0)
+ // https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/1-0-0
+ const { experiment: experimentName, key, variant, migration_keys } = experimentData;
+
+ return {
+ schema: TRACKING_CONTEXT_SCHEMA,
+ data: { experiment: experimentName, key, variant, migration_keys },
+ };
}
export function getExperimentData(experimentName) {
@@ -26,14 +39,14 @@ export function getExperimentVariant(experimentName) {
return getExperimentData(experimentName)?.variant || DEFAULT_VARIANT;
}
-export function experiment(experimentName, variants) {
+export function experiment(experimentName, { use, control, candidate, ...variants }) {
const variant = getExperimentVariant(experimentName);
switch (variant) {
case DEFAULT_VARIANT:
- return variants.use.call();
+ return (use || control).call();
case CANDIDATE_VARIANT:
- return variants.try.call();
+ return (variants.try || candidate).call();
default:
return variants[variant].call();
}
diff --git a/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue b/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue
index d86e13ce722..366ee6bb05b 100644
--- a/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue
+++ b/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue
@@ -213,6 +213,7 @@ export default {
<div
v-if="hasRotateError"
class="gl-text-red-500 gl-display-flex gl-align-items-center gl-font-weight-normal gl-mb-3"
+ data-testid="rotate-error"
>
<gl-icon name="warning" class="gl-mr-2" />
<span>{{ $options.translations.instanceIdRegenerateError }}</span>
diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js
index 741171b185a..1287a7ed746 100644
--- a/app/assets/javascripts/flash.js
+++ b/app/assets/javascripts/flash.js
@@ -9,6 +9,8 @@ const FLASH_TYPES = {
WARNING: 'warning',
};
+const FLASH_CLOSED_EVENT = 'flashClosed';
+
const getCloseEl = (flashEl) => {
return flashEl.querySelector('.js-close-icon');
};
@@ -26,6 +28,7 @@ const hideFlash = (flashEl, fadeTransition = true) => {
() => {
flashEl.remove();
window.dispatchEvent(new Event('resize'));
+ flashEl.dispatchEvent(new Event(FLASH_CLOSED_EVENT));
if (document.body.classList.contains('flash-shown'))
document.body.classList.remove('flash-shown');
},
@@ -132,4 +135,5 @@ export {
hideFlash,
removeFlashClickListener,
FLASH_TYPES,
+ FLASH_CLOSED_EVENT,
};
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
index 5dac315d345..1700437aa84 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
@@ -1,5 +1,4 @@
<script>
-/* eslint-disable vue/require-default-prop */
import { GlButton, GlSafeHtmlDirective } from '@gitlab/ui';
import highlight from '~/lib/utils/highlight';
import { truncateNamespace } from '~/lib/utils/text_utility';
@@ -23,6 +22,7 @@ export default {
matcher: {
type: String,
required: false,
+ default: '',
},
itemId: {
type: Number,
@@ -35,6 +35,7 @@ export default {
namespace: {
type: String,
required: false,
+ default: '',
},
webUrl: {
type: String,
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index cb63c86a4fa..69331ff1a06 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import '~/lib/utils/jquery_at_who';
-import { escape as lodashEscape, sortBy, template } from 'lodash';
+import { escape as lodashEscape, sortBy, template, escapeRegExp } from 'lodash';
import * as Emoji from '~/emoji';
import axios from '~/lib/utils/axios_utils';
import { s__, __, sprintf } from '~/locale';
@@ -65,6 +65,17 @@ export function membersBeforeSave(members) {
});
}
+export const highlighter = (li, query) => {
+ // override default behaviour to escape dot character
+ // see https://github.com/ichord/At.js/pull/576
+ if (!query) {
+ return li;
+ }
+ const escapedQuery = escapeRegExp(query);
+ const regexp = new RegExp(`>\\s*([^<]*?)(${escapedQuery})([^<]*)\\s*<`, 'ig');
+ return li.replace(regexp, (str, $1, $2, $3) => `> ${$1}<strong>${$2}</strong>${$3} <`);
+};
+
export const defaultAutocompleteConfig = {
emojis: true,
members: true,
@@ -664,16 +675,7 @@ class GfmAutoComplete {
}
return null;
},
- highlighter(li, query) {
- // override default behaviour to escape dot character
- // see https://github.com/ichord/At.js/pull/576
- if (!query) {
- return li;
- }
- const escapedQuery = query.replace(/[.+]/, '\\$&');
- const regexp = new RegExp(`>\\s*([^<]*?)(${escapedQuery})([^<]*)\\s*<`, 'ig');
- return li.replace(regexp, (str, $1, $2, $3) => `> ${$1}<strong>${$2}</strong>${$3} <`);
- },
+ highlighter,
};
}
diff --git a/app/assets/javascripts/google_cloud/components/app.vue b/app/assets/javascripts/google_cloud/components/app.vue
new file mode 100644
index 00000000000..1e5be9df019
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/components/app.vue
@@ -0,0 +1,50 @@
+<script>
+import { GlTab, GlTabs } from '@gitlab/ui';
+import IncubationBanner from './incubation_banner.vue';
+import ServiceAccounts from './service_accounts.vue';
+
+export default {
+ components: { GlTab, GlTabs, IncubationBanner, ServiceAccounts },
+ props: {
+ serviceAccounts: {
+ type: Array,
+ required: true,
+ },
+ createServiceAccountUrl: {
+ type: String,
+ required: true,
+ },
+ emptyIllustrationUrl: {
+ type: String,
+ required: true,
+ },
+ },
+ methods: {
+ feedbackUrl(template) {
+ return `https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/meta/-/issues/new?issuable_template=${template}`;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <incubation-banner
+ :share-feedback-url="feedbackUrl('general_feedback')"
+ :report-bug-url="feedbackUrl('report_bug')"
+ :feature-request-url="feedbackUrl('feature_request')"
+ />
+ <gl-tabs>
+ <gl-tab :title="__('Configuration')">
+ <service-accounts
+ class="gl-mx-3"
+ :list="serviceAccounts"
+ :create-url="createServiceAccountUrl"
+ :empty-illustration-url="emptyIllustrationUrl"
+ />
+ </gl-tab>
+ <gl-tab :title="__('Deployments')" disabled />
+ <gl-tab :title="__('Services')" disabled />
+ </gl-tabs>
+ </div>
+</template>
diff --git a/app/assets/javascripts/google_cloud/components/incubation_banner.vue b/app/assets/javascripts/google_cloud/components/incubation_banner.vue
new file mode 100644
index 00000000000..652b8c1aecb
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/components/incubation_banner.vue
@@ -0,0 +1,44 @@
+<script>
+import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
+
+export default {
+ components: { GlAlert, GlLink, GlSprintf },
+ props: {
+ shareFeedbackUrl: {
+ required: true,
+ type: String,
+ },
+ reportBugUrl: {
+ required: true,
+ type: String,
+ },
+ featureRequestUrl: {
+ required: true,
+ type: String,
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-alert :dismissible="false" variant="info">
+ {{ __('This is an experimental feature developed by GitLab Incubation Engineering.') }}
+ <gl-sprintf
+ :message="
+ __(
+ 'We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}',
+ )
+ "
+ >
+ <template #featureLink="{ content }">
+ <gl-link :href="featureRequestUrl">{{ content }}</gl-link>
+ </template>
+ <template #bugLink="{ content }">
+ <gl-link :href="reportBugUrl">{{ content }}</gl-link>
+ </template>
+ <template #feedbackLink="{ content }">
+ <gl-link :href="shareFeedbackUrl">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+</template>
diff --git a/app/assets/javascripts/google_cloud/components/service_accounts.vue b/app/assets/javascripts/google_cloud/components/service_accounts.vue
new file mode 100644
index 00000000000..b70b25a5dc3
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/components/service_accounts.vue
@@ -0,0 +1,65 @@
+<script>
+import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ components: { GlButton, GlEmptyState, GlTable },
+ props: {
+ list: {
+ type: Array,
+ required: true,
+ },
+ createUrl: {
+ type: String,
+ required: true,
+ },
+ emptyIllustrationUrl: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ tableFields: [
+ { key: 'environment', label: __('Environment'), sortable: true },
+ { key: 'gcp_project', label: __('Google Cloud Project'), sortable: true },
+ { key: 'service_account_exists', label: __('Service Account'), sortable: true },
+ { key: 'service_account_key_exists', label: __('Service Account Key'), sortable: true },
+ ],
+ };
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-empty-state
+ v-if="list.length === 0"
+ :title="__('No service accounts')"
+ :description="
+ __('Service Accounts keys authorize GitLab to deploy your Google Cloud project')
+ "
+ :primary-button-link="createUrl"
+ :primary-button-text="__('Create service account')"
+ :svg-path="emptyIllustrationUrl"
+ />
+
+ <div v-else>
+ <h2 class="gl-font-size-h2">{{ __('Service Accounts') }}</h2>
+ <p>{{ __('Service Accounts keys authorize GitLab to deploy your Google Cloud project') }}</p>
+
+ <gl-table :items="list" :fields="tableFields">
+ <template #cell(service_account_exists)="{ value }">
+ {{ value ? '✔' : __('Not found') }}
+ </template>
+ <template #cell(service_account_key_exists)="{ value }">
+ {{ value ? '✔' : __('Not found') }}
+ </template>
+ </gl-table>
+
+ <gl-button :href="createUrl" category="primary" variant="info">
+ {{ __('Create service account') }}
+ </gl-button>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/google_cloud/index.js b/app/assets/javascripts/google_cloud/index.js
new file mode 100644
index 00000000000..a156a632e9a
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/index.js
@@ -0,0 +1,11 @@
+import Vue from 'vue';
+import App from './components/app.vue';
+
+const elementRenderer = (element, props = {}) => (createElement) =>
+ createElement(element, { props });
+
+export default () => {
+ const root = document.querySelector('#js-google-cloud');
+ const props = JSON.parse(root.getAttribute('data'));
+ return new Vue({ el: root, render: elementRenderer(App, props) });
+};
diff --git a/app/assets/javascripts/graphql_shared/fragments/iteration.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/iteration.fragment.graphql
new file mode 100644
index 00000000000..78a368089a8
--- /dev/null
+++ b/app/assets/javascripts/graphql_shared/fragments/iteration.fragment.graphql
@@ -0,0 +1,4 @@
+fragment Iteration on Iteration {
+ id
+ title
+}
diff --git a/app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql b/app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql
index e345fe97281..c5f99a1657e 100644
--- a/app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql
@@ -1,9 +1,10 @@
#import "../fragments/user.fragment.graphql"
#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
-query usersSearch($search: String!, $fullPath: ID!) {
+query groupUsersSearch($search: String!, $fullPath: ID!) {
workspace: group(fullPath: $fullPath) {
- users: groupMembers(search: $search, relations: [DIRECT, INHERITED]) {
+ id
+ users: groupMembers(search: $search, relations: [DIRECT, DESCENDANTS, INHERITED]) {
nodes {
user {
...User
diff --git a/app/assets/javascripts/graphql_shared/queries/project_user_members_search.query.graphql b/app/assets/javascripts/graphql_shared/queries/project_user_members_search.query.graphql
index 1d9497d65ce..62ce27815c7 100644
--- a/app/assets/javascripts/graphql_shared/queries/project_user_members_search.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/project_user_members_search.query.graphql
@@ -1,5 +1,6 @@
query searchProjectMembers($fullPath: ID!, $search: String) {
project(fullPath: $fullPath) {
+ id
projectMembers(search: $search) {
nodes {
user {
diff --git a/app/assets/javascripts/graphql_shared/queries/users_search.query.graphql b/app/assets/javascripts/graphql_shared/queries/users_search.query.graphql
index e18eea33041..d04a49f8b3a 100644
--- a/app/assets/javascripts/graphql_shared/queries/users_search.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/users_search.query.graphql
@@ -1,7 +1,7 @@
#import "../fragments/user.fragment.graphql"
#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
-query usersSearch($search: String!, $fullPath: ID!) {
+query projectUsersSearch($search: String!, $fullPath: ID!) {
workspace: project(fullPath: $fullPath) {
users: projectMembers(search: $search, relations: [DIRECT, INHERITED, INVITED_GROUPS]) {
nodes {
diff --git a/app/assets/javascripts/graphql_shared/utils.js b/app/assets/javascripts/graphql_shared/utils.js
index 828ddd95ffc..8fb70eb59bd 100644
--- a/app/assets/javascripts/graphql_shared/utils.js
+++ b/app/assets/javascripts/graphql_shared/utils.js
@@ -15,6 +15,8 @@ export const isGid = (id) => {
return false;
};
+const parseGid = (gid) => parseInt(`${gid}`.replace(/gid:\/\/gitlab\/.*\//g, ''), 10);
+
/**
* Ids generated by GraphQL endpoints are usually in the format
* gid://gitlab/Environments/123. This method extracts Id number
@@ -23,8 +25,10 @@ export const isGid = (id) => {
* @param {String} gid GraphQL global ID
* @returns {Number}
*/
-export const getIdFromGraphQLId = (gid = '') =>
- parseInt(`${gid}`.replace(/gid:\/\/gitlab\/.*\//g, ''), 10) || null;
+export const getIdFromGraphQLId = (gid = '') => {
+ const parsedGid = parseGid(gid);
+ return Number.isInteger(parsedGid) ? parsedGid : null;
+};
export const MutationOperationMode = {
Append: 'APPEND',
diff --git a/app/assets/javascripts/group.js b/app/assets/javascripts/group.js
index b6a1f41afb5..f255f8a084c 100644
--- a/app/assets/javascripts/group.js
+++ b/app/assets/javascripts/group.js
@@ -1,6 +1,6 @@
import createFlash from '~/flash';
import { __ } from '~/locale';
-import fetchGroupPathAvailability from '~/pages/groups/new/fetch_group_path_availability';
+import { getGroupPathAvailability } from '~/rest_api';
import { slugify } from './lib/utils/text_utility';
export default class Group {
@@ -51,7 +51,7 @@ export default class Group {
const slug = this.groupPaths[0]?.value || slugify(value);
if (!slug) return;
- fetchGroupPathAvailability(slug, this.parentId?.value)
+ getGroupPathAvailability(slug, this.parentId?.value)
.then(({ data }) => data)
.then(({ exists, suggests }) => {
if (exists && suggests.length) {
diff --git a/app/assets/javascripts/group_settings/components/shared_runners_form.vue b/app/assets/javascripts/group_settings/components/shared_runners_form.vue
index f61d96b3dfd..dcac337c6ef 100644
--- a/app/assets/javascripts/group_settings/components/shared_runners_form.vue
+++ b/app/assets/javascripts/group_settings/components/shared_runners_form.vue
@@ -3,13 +3,7 @@ import { GlToggle, GlLoadingIcon, GlTooltip, GlAlert } from '@gitlab/ui';
import { debounce } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
-import {
- DEBOUNCE_TOGGLE_DELAY,
- ERROR_MESSAGE,
- ENABLED,
- DISABLED,
- ALLOW_OVERRIDE,
-} from '../constants';
+import { DEBOUNCE_TOGGLE_DELAY, ERROR_MESSAGE } from '../constants';
export default {
components: {
@@ -18,21 +12,14 @@ export default {
GlTooltip,
GlAlert,
},
- props: {
- updatePath: {
- type: String,
- required: true,
- },
- sharedRunnersAvailability: {
- type: String,
- required: true,
- },
- parentSharedRunnersAvailability: {
- type: String,
- required: false,
- default: '',
- },
- },
+ inject: [
+ 'updatePath',
+ 'sharedRunnersAvailability',
+ 'parentSharedRunnersAvailability',
+ 'runnerEnabled',
+ 'runnerDisabled',
+ 'runnerAllowOverride',
+ ],
data() {
return {
isLoading: false,
@@ -43,21 +30,21 @@ export default {
},
computed: {
toggleDisabled() {
- return this.parentSharedRunnersAvailability === DISABLED || this.isLoading;
+ return this.parentSharedRunnersAvailability === this.runnerDisabled || this.isLoading;
},
enabledOrDisabledSetting() {
- return this.enabled ? ENABLED : DISABLED;
+ return this.enabled ? this.runnerEnabled : this.runnerDisabled;
},
disabledWithOverrideSetting() {
- return this.allowOverride ? ALLOW_OVERRIDE : DISABLED;
+ return this.allowOverride ? this.runnerAllowOverride : this.runnerDisabled;
},
},
created() {
- if (this.sharedRunnersAvailability !== ENABLED) {
+ if (this.sharedRunnersAvailability !== this.runnerEnabled) {
this.enabled = false;
}
- if (this.sharedRunnersAvailability === ALLOW_OVERRIDE) {
+ if (this.sharedRunnersAvailability === this.runnerAllowOverride) {
this.allowOverride = true;
}
},
diff --git a/app/assets/javascripts/group_settings/constants.js b/app/assets/javascripts/group_settings/constants.js
index c7bb851c06b..4067b6b52a3 100644
--- a/app/assets/javascripts/group_settings/constants.js
+++ b/app/assets/javascripts/group_settings/constants.js
@@ -4,8 +4,3 @@ import { __ } from '~/locale';
export const DEBOUNCE_TOGGLE_DELAY = 1000;
export const ERROR_MESSAGE = __('Refresh the page and try again.');
-
-// runner setting options
-export const ENABLED = 'enabled';
-export const DISABLED = 'disabled_and_unoverridable';
-export const ALLOW_OVERRIDE = 'disabled_with_override';
diff --git a/app/assets/javascripts/group_settings/mount_shared_runners.js b/app/assets/javascripts/group_settings/mount_shared_runners.js
index 44284204c41..21a2373e2b1 100644
--- a/app/assets/javascripts/group_settings/mount_shared_runners.js
+++ b/app/assets/javascripts/group_settings/mount_shared_runners.js
@@ -4,12 +4,27 @@ import UpdateSharedRunnersForm from './components/shared_runners_form.vue';
export default (containerId = 'update-shared-runners-form') => {
const containerEl = document.getElementById(containerId);
+ const {
+ updatePath,
+ sharedRunnersAvailability,
+ parentSharedRunnersAvailability,
+ runnerEnabled,
+ runnerDisabled,
+ runnerAllowOverride,
+ } = containerEl.dataset;
+
return new Vue({
el: containerEl,
+ provide: {
+ updatePath,
+ sharedRunnersAvailability,
+ parentSharedRunnersAvailability,
+ runnerEnabled,
+ runnerDisabled,
+ runnerAllowOverride,
+ },
render(createElement) {
- return createElement(UpdateSharedRunnersForm, {
- props: containerEl.dataset,
- });
+ return createElement(UpdateSharedRunnersForm);
},
});
};
diff --git a/app/assets/javascripts/groups/components/item_caret.vue b/app/assets/javascripts/groups/components/item_caret.vue
index 9c379d7bf9b..a51edd385dd 100644
--- a/app/assets/javascripts/groups/components/item_caret.vue
+++ b/app/assets/javascripts/groups/components/item_caret.vue
@@ -22,6 +22,6 @@ export default {
<template>
<span class="folder-caret gl-mr-2">
- <gl-icon :size="10" :name="iconClass" use-deprecated-sizes />
+ <gl-icon :size="12" :name="iconClass" />
</span>
</template>
diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue
index 96cb4f3d495..55ae5501cdb 100644
--- a/app/assets/javascripts/ide/components/jobs/detail.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective, GlButton, GlIcon } from '@gitlab/ui';
+import { GlTooltipDirective, GlButton, GlIcon, GlSafeHtmlDirective } from '@gitlab/ui';
import { throttle } from 'lodash';
import { mapActions, mapState } from 'vuex';
import { __ } from '../../../locale';
@@ -14,6 +14,7 @@ const scrollPositions = {
export default {
directives: {
GlTooltip: GlTooltipDirective,
+ SafeHtml: GlSafeHtmlDirective,
},
components: {
GlButton,
@@ -100,8 +101,8 @@ export default {
<pre ref="buildJobLog" class="build-log mb-0 h-100 mr-3" @scroll="scrollBuildLog">
<code
v-show="!detailJob.isLoading"
+ v-safe-html="jobOutput"
class="bash"
- v-html="jobOutput /* eslint-disable-line vue/no-v-html */"
>
</code>
<div
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index e8541d3a4c3..1c5a00568eb 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -2,7 +2,7 @@
import { GlModal, GlButton } from '@gitlab/ui';
import { mapActions, mapState, mapGetters } from 'vuex';
import createFlash from '~/flash';
-import { __, sprintf, s__ } from '~/locale';
+import { __, sprintf } from '~/locale';
import { modalTypes } from '../../constants';
import { trimPathComponents, getPathParent } from '../../utils';
@@ -58,7 +58,7 @@ export default {
if (this.modalType === modalTypes.rename) {
if (this.entries[this.entryName] && !this.entries[this.entryName].deleted) {
createFlash({
- message: sprintf(s__('The name "%{name}" is already taken in this directory.'), {
+ message: sprintf(__('The name "%{name}" is already taken in this directory.'), {
name: this.entryName,
}),
fadeTransition: false,
diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue
index 907ac496982..e1caf1ba44a 100644
--- a/app/assets/javascripts/ide/components/pipelines/list.vue
+++ b/app/assets/javascripts/ide/components/pipelines/list.vue
@@ -87,7 +87,7 @@ export default {
v-if="!latestPipeline"
:empty-state-svg-path="pipelinesEmptyStateSvgPath"
:can-set-ci="true"
- class="mb-auto mt-auto"
+ class="gl-p-5"
/>
<gl-alert
v-else-if="latestPipeline.yamlError"
diff --git a/app/assets/javascripts/ide/components/shared/commit_message_field.vue b/app/assets/javascripts/ide/components/shared/commit_message_field.vue
new file mode 100644
index 00000000000..7fca7429ad7
--- /dev/null
+++ b/app/assets/javascripts/ide/components/shared/commit_message_field.vue
@@ -0,0 +1,137 @@
+<script>
+import { GlIcon, GlPopover } from '@gitlab/ui';
+import { __, sprintf } from '~/locale';
+import { MAX_TITLE_LENGTH, MAX_BODY_LENGTH } from '../../constants';
+
+export default {
+ components: {
+ GlIcon,
+ GlPopover,
+ },
+ props: {
+ text: {
+ type: String,
+ required: true,
+ },
+ placeholder: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ scrollTop: 0,
+ isFocused: false,
+ };
+ },
+ computed: {
+ allLines() {
+ return this.text.split('\n').map((line, i) => ({
+ text: line.substr(0, this.getLineLength(i)) || ' ',
+ highlightedText: line.substr(this.getLineLength(i)),
+ }));
+ },
+ },
+ methods: {
+ handleScroll() {
+ if (this.$refs.textarea) {
+ this.$nextTick(() => {
+ this.scrollTop = this.$refs.textarea.scrollTop;
+ });
+ }
+ },
+ getLineLength(i) {
+ return i === 0 ? MAX_TITLE_LENGTH : MAX_BODY_LENGTH;
+ },
+ onInput(e) {
+ this.$emit('input', e.target.value);
+ },
+ onCtrlEnter() {
+ if (!this.isFocused) return;
+ this.$emit('submit');
+ },
+ updateIsFocused(isFocused) {
+ this.isFocused = isFocused;
+ },
+ },
+ popoverOptions: {
+ triggers: 'hover',
+ placement: 'top',
+ content: sprintf(
+ __(`
+ The character highlighter helps you keep the subject line to %{titleLength} characters
+ and wrap the body at %{bodyLength} so they are readable in git.
+ `),
+ { titleLength: MAX_TITLE_LENGTH, bodyLength: MAX_BODY_LENGTH },
+ ),
+ },
+};
+</script>
+
+<template>
+ <fieldset
+ class="gl-rounded-base gl-inset-border-1-gray-400 gl-py-4 gl-px-5"
+ :class="{
+ 'gl-outline-none! gl-focus-ring-border-1-gray-900!': isFocused,
+ }"
+ >
+ <div
+ v-once
+ class="gl-display-flex gl-align-items-center gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-pb-3 gl-mb-3"
+ >
+ <div>{{ __('Commit Message') }}</div>
+ <div id="commit-message-popover-container">
+ <span id="commit-message-question" class="gl-gray-700 gl-ml-3">
+ <gl-icon name="question" />
+ </span>
+ <gl-popover
+ target="commit-message-question"
+ container="commit-message-popover-container"
+ v-bind="$options.popoverOptions"
+ />
+ </div>
+ </div>
+ <div class="gl-relative gl-w-full gl-h-13 gl-overflow-hidden">
+ <div class="gl-absolute gl-z-index-1 gl-font-monospace gl-text-transparent">
+ <div
+ data-testid="highlights"
+ :style="{
+ transform: `translate3d(0, ${-scrollTop}px, 0)`,
+ }"
+ >
+ <div v-for="(line, index) in allLines" :key="index">
+ <span
+ data-testid="highlights-text"
+ class="gl-white-space-pre-wrap gl-word-break-word"
+ v-text="line.text"
+ >
+ </span
+ ><mark
+ v-show="line.highlightedText"
+ data-testid="highlights-mark"
+ class="gl-px-1 gl-py-0 gl-bg-orange-100 gl-text-transparent gl-white-space-pre-wrap gl-word-break-word"
+ v-text="line.highlightedText"
+ >
+ </mark>
+ </div>
+ </div>
+ </div>
+ <textarea
+ ref="textarea"
+ :placeholder="placeholder"
+ :value="text"
+ class="gl-absolute gl-w-full gl-h-full gl-z-index-2 gl-font-monospace p-0 gl-outline-0 gl-bg-transparent gl-border-0"
+ data-qa-selector="ide_commit_message_field"
+ dir="auto"
+ name="commit-message"
+ @scroll="handleScroll"
+ @input="onInput"
+ @focus="updateIsFocused(true)"
+ @blur="updateIsFocused(false)"
+ @keydown.ctrl.enter="onCtrlEnter"
+ @keydown.meta.enter="onCtrlEnter"
+ >
+ </textarea>
+ </div>
+ </fieldset>
+</template>
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index 4845b667b40..706d98fdb90 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -5,7 +5,7 @@ export const MAX_TITLE_LENGTH = 50;
export const MAX_BODY_LENGTH = 72;
export const SIDEBAR_INIT_WIDTH = 340;
-export const SIDEBAR_MIN_WIDTH = 340;
+export const SIDEBAR_MIN_WIDTH = 260;
export const SIDEBAR_NAV_WIDTH = 60;
// File view modes
diff --git a/app/assets/javascripts/import_entities/components/group_dropdown.vue b/app/assets/javascripts/import_entities/components/group_dropdown.vue
index 5ba910746ca..25d4037bbe5 100644
--- a/app/assets/javascripts/import_entities/components/group_dropdown.vue
+++ b/app/assets/javascripts/import_entities/components/group_dropdown.vue
@@ -19,7 +19,7 @@ export default {
computed: {
filteredNamespaces() {
return this.namespaces.filter((ns) =>
- ns.toLowerCase().includes(this.searchTerm.toLowerCase()),
+ ns.fullPath.toLowerCase().includes(this.searchTerm.toLowerCase()),
);
},
},
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue b/app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue
index 104c84173fc..e004bc35087 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue
@@ -1,7 +1,5 @@
<script>
import { GlButton, GlIcon, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
-import { joinPaths } from '~/lib/utils/url_utility';
-import { isFinished, isInvalid, isAvailableForImport } from '../utils';
export default {
components: {
@@ -12,32 +10,17 @@ export default {
GlTooltip,
},
props: {
- group: {
- type: Object,
+ isFinished: {
+ type: Boolean,
required: true,
},
- groupPathRegex: {
- type: RegExp,
+ isAvailableForImport: {
+ type: Boolean,
required: true,
},
- },
- computed: {
- fullLastImportPath() {
- return this.group.last_import_target
- ? `${this.group.last_import_target.target_namespace}/${this.group.last_import_target.new_name}`
- : null;
- },
- absoluteLastImportPath() {
- return joinPaths(gon.relative_url_root || '/', this.fullLastImportPath);
- },
- isAvailableForImport() {
- return isAvailableForImport(this.group);
- },
- isFinished() {
- return isFinished(this.group);
- },
- isInvalid() {
- return isInvalid(this.group, this.groupPathRegex);
+ isInvalid: {
+ type: Boolean,
+ required: true,
},
},
};
@@ -56,7 +39,7 @@ export default {
{{ isFinished ? __('Re-import') : __('Import') }}
</gl-button>
<gl-icon
- v-if="isFinished"
+ v-if="isAvailableForImport && isFinished"
v-gl-tooltip
:size="16"
name="information-o"
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_source_cell.vue b/app/assets/javascripts/import_entities/import_groups/components/import_source_cell.vue
index 2de9bd4f868..cad1b983d61 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_source_cell.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_source_cell.vue
@@ -1,7 +1,6 @@
<script>
import { GlLink, GlSprintf, GlIcon } from '@gitlab/ui';
import { joinPaths } from '~/lib/utils/url_utility';
-import { isFinished } from '../utils';
export default {
components: {
@@ -17,16 +16,13 @@ export default {
},
computed: {
fullLastImportPath() {
- return this.group.last_import_target
- ? `${this.group.last_import_target.target_namespace}/${this.group.last_import_target.new_name}`
+ return this.group.lastImportTarget
+ ? `${this.group.lastImportTarget.targetNamespace}/${this.group.lastImportTarget.newName}`
: null;
},
absoluteLastImportPath() {
return joinPaths(gon.relative_url_root || '/', this.fullLastImportPath);
},
- isFinished() {
- return isFinished(this.group);
- },
},
};
</script>
@@ -34,13 +30,13 @@ export default {
<template>
<div>
<gl-link
- :href="group.web_url"
+ :href="group.webUrl"
target="_blank"
class="gl-display-inline-flex gl-align-items-center gl-h-7"
>
- {{ group.full_path }} <gl-icon name="external-link" />
+ {{ group.fullPath }} <gl-icon name="external-link" />
</gl-link>
- <div v-if="isFinished && fullLastImportPath" class="gl-font-sm">
+ <div v-if="group.flags.isFinished && fullLastImportPath" class="gl-font-sm">
<gl-sprintf :message="s__('BulkImport|Last imported to %{link}')">
<template #link>
<gl-link :href="absoluteLastImportPath" class="gl-font-sm" target="_blank">{{
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_table.vue b/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
index 04b037ecc2b..ec6025c84bb 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
@@ -12,18 +12,28 @@ import {
GlTable,
GlFormCheckbox,
} from '@gitlab/ui';
+import { debounce } from 'lodash';
+import createFlash from '~/flash';
import { s__, __, n__ } from '~/locale';
import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
+import { getGroupPathAvailability } from '~/rest_api';
+import axios from '~/lib/utils/axios_utils';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
+
+import { STATUSES } from '../../constants';
import ImportStatusCell from '../../components/import_status.vue';
import importGroupsMutation from '../graphql/mutations/import_groups.mutation.graphql';
-import setImportTargetMutation from '../graphql/mutations/set_import_target.mutation.graphql';
+import updateImportStatusMutation from '../graphql/mutations/update_import_status.mutation.graphql';
import availableNamespacesQuery from '../graphql/queries/available_namespaces.query.graphql';
import bulkImportSourceGroupsQuery from '../graphql/queries/bulk_import_source_groups.query.graphql';
-import { isInvalid, isFinished, isAvailableForImport } from '../utils';
+import { NEW_NAME_FIELD, i18n } from '../constants';
+import { StatusPoller } from '../services/status_poller';
+import { isFinished, isAvailableForImport, isNameValid, isSameTarget } from '../utils';
import ImportActionsCell from './import_actions_cell.vue';
import ImportSourceCell from './import_source_cell.vue';
import ImportTargetCell from './import_target_cell.vue';
+const VALIDATION_DEBOUNCE_TIME = DEFAULT_DEBOUNCE_AND_THROTTLE_MS;
const PAGE_SIZES = [20, 50, 100];
const DEFAULT_PAGE_SIZE = PAGE_SIZES[0];
const DEFAULT_TH_CLASSES =
@@ -59,7 +69,7 @@ export default {
type: RegExp,
required: true,
},
- groupUrlErrorMessage: {
+ jobsPath: {
type: String,
required: true,
},
@@ -70,7 +80,9 @@ export default {
filter: '',
page: 1,
perPage: DEFAULT_PAGE_SIZE,
- selectedGroups: [],
+ selectedGroupsIds: [],
+ pendingGroupsIds: [],
+ importTargets: {},
};
},
@@ -94,14 +106,14 @@ export default {
tdClass: `${DEFAULT_TD_CLASSES} gl-pr-3!`,
},
{
- key: 'web_url',
+ key: 'webUrl',
label: s__('BulkImport|From source group'),
thClass: `${DEFAULT_TH_CLASSES} gl-pl-0! import-jobs-from-col`,
// eslint-disable-next-line @gitlab/require-i18n-strings
tdClass: `${DEFAULT_TD_CLASSES} gl-pl-0!`,
},
{
- key: 'import_target',
+ key: 'importTarget',
label: s__('BulkImport|To new group'),
thClass: `${DEFAULT_TH_CLASSES} import-jobs-to-col`,
tdClass: DEFAULT_TD_CLASSES,
@@ -126,16 +138,39 @@ export default {
return this.bulkImportSourceGroups?.nodes ?? [];
},
+ groupsTableData() {
+ return this.groups.map((group) => {
+ const importTarget = this.getImportTarget(group);
+ const status = this.getStatus(group);
+
+ const flags = {
+ isInvalid: importTarget.validationErrors?.length > 0,
+ isAvailableForImport: isAvailableForImport(group) && status !== STATUSES.SCHEDULING,
+ isFinished: isFinished(group),
+ };
+
+ return {
+ ...group,
+ visibleStatus: status,
+ importTarget,
+ flags: {
+ ...flags,
+ isUnselectable: !flags.isAvailableForImport || flags.isInvalid,
+ },
+ };
+ });
+ },
+
hasSelectedGroups() {
- return this.selectedGroups.length > 0;
+ return this.selectedGroupsIds.length > 0;
},
hasAllAvailableGroupsSelected() {
- return this.selectedGroups.length === this.availableGroupsForImport.length;
+ return this.selectedGroupsIds.length === this.availableGroupsForImport.length;
},
availableGroupsForImport() {
- return this.groups.filter((g) => isAvailableForImport(g) && !this.isInvalid(g));
+ return this.groupsTableData.filter((g) => g.flags.isAvailableForImport && g.flags.isInvalid);
},
humanizedTotal() {
@@ -175,25 +210,43 @@ export default {
filter() {
this.page = 1;
},
- groups() {
+
+ groupsTableData() {
const table = this.getTableRef();
- this.groups.forEach((g, idx) => {
- if (this.selectedGroups.includes(g)) {
+ const matches = new Set();
+ this.groupsTableData.forEach((g, idx) => {
+ if (this.selectedGroupsIds.includes(g.id)) {
+ matches.add(g.id);
this.$nextTick(() => {
table.selectRow(idx);
});
}
});
- this.selectedGroups = [];
+
+ this.selectedGroupsIds = this.selectedGroupsIds.filter((id) => matches.has(id));
},
},
- methods: {
- isUnselectable(group) {
- return !this.isAvailableForImport(group) || this.isInvalid(group);
- },
+ mounted() {
+ this.statusPoller = new StatusPoller({
+ pollPath: this.jobsPath,
+ updateImportStatus: (update) => {
+ this.$apollo.mutate({
+ mutation: updateImportStatusMutation,
+ variables: { id: update.id, status: update.status_name },
+ });
+ },
+ });
- rowClasses(group) {
+ this.statusPoller.startPolling();
+ },
+
+ beforeDestroy() {
+ this.statusPoller.stopPolling();
+ },
+
+ methods: {
+ rowClasses(groupTableItem) {
const DEFAULT_CLASSES = [
'gl-border-gray-200',
'gl-border-0',
@@ -201,7 +254,7 @@ export default {
'gl-border-solid',
];
const result = [...DEFAULT_CLASSES];
- if (this.isUnselectable(group)) {
+ if (groupTableItem.flags.isUnselectable) {
result.push('gl-cursor-default!');
}
return result;
@@ -211,19 +264,13 @@ export default {
if (type === 'row') {
return {
'data-qa-selector': 'import_item',
- 'data-qa-source-group': group.full_path,
+ 'data-qa-source-group': group.fullPath,
};
}
return {};
},
- isAvailableForImport,
- isFinished,
- isInvalid(group) {
- return isInvalid(group, this.groupPathRegex);
- },
-
groupsCount(count) {
return n__('%d group', '%d groups', count);
},
@@ -232,22 +279,64 @@ export default {
this.page = page;
},
- updateImportTarget(sourceGroupId, targetNamespace, newName) {
- this.$apollo.mutate({
- mutation: setImportTargetMutation,
- variables: { sourceGroupId, targetNamespace, newName },
- });
+ getStatus(group) {
+ if (this.pendingGroupsIds.includes(group.id)) {
+ return STATUSES.SCHEDULING;
+ }
+
+ return group.progress?.status || STATUSES.NONE;
},
- importGroups(sourceGroupIds) {
- this.$apollo.mutate({
- mutation: importGroupsMutation,
- variables: { sourceGroupIds },
+ updateImportTarget(group, changes) {
+ const newImportTarget = {
+ ...group.importTarget,
+ ...changes,
+ };
+ this.$set(this.importTargets, group.id, newImportTarget);
+ this.validateImportTarget(newImportTarget);
+ },
+
+ async importGroups(importRequests) {
+ const newPendingGroupsIds = importRequests.map((request) => request.sourceGroupId);
+ newPendingGroupsIds.forEach((id) => {
+ this.importTargets[id].validationErrors = [
+ { field: NEW_NAME_FIELD, message: i18n.ERROR_IMPORT_COMPLETED },
+ ];
+
+ if (!this.pendingGroupsIds.includes(id)) {
+ this.pendingGroupsIds.push(id);
+ }
});
+
+ try {
+ await this.$apollo.mutate({
+ mutation: importGroupsMutation,
+ variables: { importRequests },
+ });
+ } catch (error) {
+ const message = error?.networkError?.response?.data?.error ?? i18n.ERROR_IMPORT;
+ createFlash({
+ message,
+ captureError: true,
+ error,
+ });
+ } finally {
+ this.pendingGroupsIds = this.pendingGroupsIds.filter(
+ (id) => !newPendingGroupsIds.includes(id),
+ );
+ }
},
importSelectedGroups() {
- this.importGroups(this.selectedGroups.map((g) => g.id));
+ const importRequests = this.groupsTableData
+ .filter((group) => this.selectedGroupsIds.includes(group.id))
+ .map((group) => ({
+ sourceGroupId: group.id,
+ targetNamespace: group.importTarget.targetNamespace.fullPath,
+ newName: group.importTarget.newName,
+ }));
+
+ this.importGroups(importRequests);
},
setPageSize(size) {
@@ -263,16 +352,115 @@ export default {
preventSelectingAlreadyImportedGroups(updatedSelection) {
if (updatedSelection) {
- this.selectedGroups = updatedSelection;
+ this.selectedGroupsIds = updatedSelection.map((g) => g.id);
}
const table = this.getTableRef();
- this.groups.forEach((group, idx) => {
- if (table.isRowSelected(idx) && this.isUnselectable(group)) {
+ this.groupsTableData.forEach((group, idx) => {
+ if (table.isRowSelected(idx) && group.flags.isUnselectable) {
table.unselectRow(idx);
}
});
},
+
+ validateImportTarget: debounce(async function validate(importTarget) {
+ const newValidationErrors = [];
+ importTarget.cancellationToken?.cancel();
+ if (importTarget.newName === '') {
+ newValidationErrors.push({ field: NEW_NAME_FIELD, message: i18n.ERROR_REQUIRED });
+ } else if (!isNameValid(importTarget, this.groupPathRegex)) {
+ newValidationErrors.push({ field: NEW_NAME_FIELD, message: i18n.ERROR_INVALID_FORMAT });
+ } else if (Object.values(this.importTargets).find(isSameTarget(importTarget))) {
+ newValidationErrors.push({
+ field: NEW_NAME_FIELD,
+ message: i18n.ERROR_NAME_ALREADY_USED_IN_SUGGESTION,
+ });
+ } else {
+ try {
+ // eslint-disable-next-line no-param-reassign
+ importTarget.cancellationToken = axios.CancelToken.source();
+ const {
+ data: { exists },
+ } = await getGroupPathAvailability(
+ importTarget.newName,
+ importTarget.targetNamespace.id,
+ {
+ cancelToken: importTarget.cancellationToken?.token,
+ },
+ );
+
+ if (exists) {
+ newValidationErrors.push({
+ field: NEW_NAME_FIELD,
+ message: i18n.ERROR_NAME_ALREADY_EXISTS,
+ });
+ }
+ } catch (e) {
+ if (!axios.isCancel(e)) {
+ throw e;
+ }
+ }
+ }
+
+ // eslint-disable-next-line no-param-reassign
+ importTarget.validationErrors = newValidationErrors;
+ }, VALIDATION_DEBOUNCE_TIME),
+
+ getImportTarget(group) {
+ if (this.importTargets[group.id]) {
+ return this.importTargets[group.id];
+ }
+
+ const defaultTargetNamespace = this.availableNamespaces[0] ?? { fullPath: '', id: null };
+ let importTarget;
+ if (group.lastImportTarget) {
+ const targetNamespace = this.availableNamespaces.find(
+ (ns) => ns.fullPath === group.lastImportTarget.targetNamespace,
+ );
+
+ importTarget = {
+ targetNamespace: targetNamespace ?? defaultTargetNamespace,
+ newName: group.lastImportTarget.newName,
+ };
+ } else {
+ importTarget = {
+ targetNamespace: defaultTargetNamespace,
+ newName: group.fullPath,
+ };
+ }
+
+ const cancellationToken = axios.CancelToken.source();
+ this.$set(this.importTargets, group.id, {
+ ...importTarget,
+ cancellationToken,
+ validationErrors: [],
+ });
+
+ getGroupPathAvailability(importTarget.newName, importTarget.targetNamespace.id, {
+ cancelToken: cancellationToken.token,
+ })
+ .then(({ data: { exists, suggests: suggestions } }) => {
+ if (!exists) return;
+
+ let currentSuggestion = suggestions[0] ?? importTarget.newName;
+ const existingTargets = Object.values(this.importTargets)
+ .filter((t) => t.targetNamespace.id === importTarget.targetNamespace.id)
+ .map((t) => t.newName.toLowerCase());
+
+ while (existingTargets.includes(currentSuggestion.toLowerCase())) {
+ currentSuggestion = `${currentSuggestion}-1`;
+ }
+
+ Object.assign(this.importTargets[group.id], {
+ targetNamespace: importTarget.targetNamespace,
+ newName: currentSuggestion,
+ });
+ })
+ .catch(() => {
+ // empty catch intended
+ });
+ return this.importTargets[group.id];
+ },
},
gitlabLogo: window.gon.gitlab_logo,
@@ -329,7 +517,7 @@ export default {
<gl-empty-state
v-else-if="!hasGroups"
:title="s__('BulkImport|You have no groups to import')"
- :description="s__('Check your source instance permissions.')"
+ :description="__('Check your source instance permissions.')"
/>
<template v-else>
<div
@@ -337,7 +525,7 @@ export default {
>
<gl-sprintf :message="__('%{count} selected')">
<template #count>
- {{ selectedGroups.length }}
+ {{ selectedGroupsIds.length }}
</template>
</gl-sprintf>
<gl-button
@@ -355,7 +543,7 @@ export default {
data-qa-selector="import_table"
:tbody-tr-class="rowClasses"
:tbody-tr-attr="qaRowAttributes"
- :items="groups"
+ :items="groupsTableData"
:fields="$options.fields"
selectable
select-mode="multi"
@@ -364,7 +552,7 @@ export default {
>
<template #head(selected)="{ selectAllRows, clearSelected }">
<gl-form-checkbox
- :key="`checkbox-${selectedGroups.length}`"
+ :key="`checkbox-${selectedGroupsIds.length}`"
class="gl-h-7 gl-pt-3"
:checked="hasSelectedGroups"
:indeterminate="hasSelectedGroups && !hasAllAvailableGroupsSelected"
@@ -375,35 +563,39 @@ export default {
<gl-form-checkbox
class="gl-h-7 gl-pt-3"
:checked="rowSelected"
- :disabled="!isAvailableForImport(group) || isInvalid(group)"
+ :disabled="group.flags.isUnselectable"
@change="rowSelected ? unselectRow() : selectRow()"
/>
</template>
- <template #cell(web_url)="{ item: group }">
+ <template #cell(webUrl)="{ item: group }">
<import-source-cell :group="group" />
</template>
- <template #cell(import_target)="{ item: group }">
+ <template #cell(importTarget)="{ item: group }">
<import-target-cell
:group="group"
:available-namespaces="availableNamespaces"
:group-path-regex="groupPathRegex"
- :group-url-error-message="groupUrlErrorMessage"
- @update-target-namespace="
- updateImportTarget(group.id, $event, group.import_target.new_name)
- "
- @update-new-name="
- updateImportTarget(group.id, group.import_target.target_namespace, $event)
- "
+ @update-target-namespace="updateImportTarget(group, { targetNamespace: $event })"
+ @update-new-name="updateImportTarget(group, { newName: $event })"
/>
</template>
- <template #cell(progress)="{ value: { status } }">
- <import-status-cell :status="status" class="gl-line-height-32" />
+ <template #cell(progress)="{ item: group }">
+ <import-status-cell :status="group.visibleStatus" class="gl-line-height-32" />
</template>
<template #cell(actions)="{ item: group }">
<import-actions-cell
- :group="group"
- :group-path-regex="groupPathRegex"
- @import-group="importGroups([group.id])"
+ :is-finished="group.flags.isFinished"
+ :is-available-for-import="group.flags.isAvailableForImport"
+ :is-invalid="group.flags.isInvalid"
+ @import-group="
+ importGroups([
+ {
+ sourceGroupId: group.id,
+ targetNamespace: group.importTarget.targetNamespace.fullPath,
+ newName: group.importTarget.newName,
+ },
+ ])
+ "
/>
</template>
</gl-table>
@@ -413,7 +605,7 @@ export default {
:page-info="bulkImportSourceGroups.pageInfo"
class="gl-m-0"
/>
- <gl-dropdown category="tertiary" class="gl-ml-auto">
+ <gl-dropdown category="tertiary" :aria-label="__('Page size')" class="gl-ml-auto">
<template #button-content>
<span class="font-weight-bold">
<gl-sprintf :message="__('%{count} items per page')">
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue b/app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue
index daced740c94..ca9ae9447d0 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue
@@ -7,12 +7,7 @@ import {
} from '@gitlab/ui';
import { s__ } from '~/locale';
import ImportGroupDropdown from '../../components/group_dropdown.vue';
-import {
- isInvalid,
- getInvalidNameValidationMessage,
- isNameValid,
- isAvailableForImport,
-} from '../utils';
+import { getInvalidNameValidationMessage } from '../utils';
export default {
components: {
@@ -31,44 +26,15 @@ export default {
type: Array,
required: true,
},
- groupPathRegex: {
- type: RegExp,
- required: true,
- },
- groupUrlErrorMessage: {
- type: String,
- required: true,
- },
},
computed: {
- availableNamespaceNames() {
- return this.availableNamespaces.map((ns) => ns.full_path);
- },
-
- importTarget() {
- return this.group.import_target;
+ fullPath() {
+ return this.group.importTarget.targetNamespace.fullPath || s__('BulkImport|No parent');
},
-
invalidNameValidationMessage() {
- return getInvalidNameValidationMessage(this.group);
+ return getInvalidNameValidationMessage(this.group.importTarget);
},
-
- isInvalid() {
- return isInvalid(this.group, this.groupPathRegex);
- },
-
- isNameValid() {
- return isNameValid(this.group, this.groupPathRegex);
- },
-
- isAvailableForImport() {
- return isAvailableForImport(this.group);
- },
- },
-
- i18n: {
- NAME_ALREADY_EXISTS: s__('BulkImport|Name already exists.'),
},
};
</script>
@@ -77,14 +43,14 @@ export default {
<div class="gl-display-flex gl-align-items-stretch">
<import-group-dropdown
#default="{ namespaces }"
- :text="importTarget.target_namespace"
- :disabled="!isAvailableForImport"
- :namespaces="availableNamespaceNames"
+ :text="fullPath"
+ :disabled="!group.flags.isAvailableForImport"
+ :namespaces="availableNamespaces"
toggle-class="gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
class="gl-h-7 gl-flex-grow-1"
data-qa-selector="target_namespace_selector_dropdown"
>
- <gl-dropdown-item @click="$emit('update-target-namespace', '')">{{
+ <gl-dropdown-item @click="$emit('update-target-namespace', { fullPath: '', id: null })">{{
s__('BulkImport|No parent')
}}</gl-dropdown-item>
<template v-if="namespaces.length">
@@ -94,20 +60,20 @@ export default {
</gl-dropdown-section-header>
<gl-dropdown-item
v-for="ns in namespaces"
- :key="ns"
+ :key="ns.fullPath"
data-qa-selector="target_group_dropdown_item"
- :data-qa-group-name="ns"
+ :data-qa-group-name="ns.fullPath"
@click="$emit('update-target-namespace', ns)"
>
- {{ ns }}
+ {{ ns.fullPath }}
</gl-dropdown-item>
</template>
</import-group-dropdown>
<div
class="gl-h-7 gl-px-3 gl-display-flex gl-align-items-center gl-border-solid gl-border-0 gl-border-t-1 gl-border-b-1 gl-bg-gray-10"
:class="{
- 'gl-text-gray-400 gl-border-gray-100': !isAvailableForImport,
- 'gl-border-gray-200': isAvailableForImport,
+ 'gl-text-gray-400 gl-border-gray-100': !group.flags.isAvailableForImport,
+ 'gl-border-gray-200': group.flags.isAvailableForImport,
}"
>
/
@@ -116,21 +82,21 @@ export default {
<gl-form-input
class="gl-rounded-top-left-none gl-rounded-bottom-left-none"
:class="{
- 'gl-inset-border-1-gray-200!': isAvailableForImport,
- 'gl-inset-border-1-gray-100!': !isAvailableForImport,
- 'is-invalid': isInvalid && isAvailableForImport,
+ 'gl-inset-border-1-gray-200!': group.flags.isAvailableForImport,
+ 'gl-inset-border-1-gray-100!': !group.flags.isAvailableForImport,
+ 'is-invalid': group.flags.isInvalid && group.flags.isAvailableForImport,
}"
- :disabled="!isAvailableForImport"
- :value="importTarget.new_name"
+ debounce="500"
+ :disabled="!group.flags.isAvailableForImport"
+ :value="group.importTarget.newName"
+ :aria-label="__('New name')"
@input="$emit('update-new-name', $event)"
/>
- <p v-if="isInvalid" class="gl-text-red-500 gl-m-0 gl-mt-2">
- <template v-if="!isNameValid">
- {{ groupUrlErrorMessage }}
- </template>
- <template v-else-if="invalidNameValidationMessage">
- {{ invalidNameValidationMessage }}
- </template>
+ <p
+ v-if="group.flags.isAvailableForImport && group.flags.isInvalid"
+ class="gl-text-red-500 gl-m-0 gl-mt-2"
+ >
+ {{ invalidNameValidationMessage }}
</p>
</div>
</div>
diff --git a/app/assets/javascripts/import_entities/import_groups/constants.js b/app/assets/javascripts/import_entities/import_groups/constants.js
index b2c3d85e280..aa9cf3897e6 100644
--- a/app/assets/javascripts/import_entities/import_groups/constants.js
+++ b/app/assets/javascripts/import_entities/import_groups/constants.js
@@ -1,7 +1,16 @@
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
export const i18n = {
- NAME_ALREADY_EXISTS: s__('BulkImport|Name already exists.'),
+ ERROR_INVALID_FORMAT: s__(
+ 'GroupSettings|Please choose a group URL with no special characters or spaces.',
+ ),
+ ERROR_NAME_ALREADY_EXISTS: s__('BulkImport|Name already exists.'),
+ ERROR_REQUIRED: __('This field is required.'),
+ ERROR_NAME_ALREADY_USED_IN_SUGGESTION: s__(
+ 'BulkImport|Name already used as a target for another group.',
+ ),
+ ERROR_IMPORT: s__('BulkImport|Importing the group failed.'),
+ ERROR_IMPORT_COMPLETED: s__('BulkImport|Import is finished. Pick another name for re-import'),
};
-export const NEW_NAME_FIELD = 'new_name';
+export const NEW_NAME_FIELD = 'newName';
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js b/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js
index c08cf909a00..bce6e7bcb1f 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js
@@ -1,23 +1,10 @@
-import createFlash from '~/flash';
import createDefaultClient from '~/lib/graphql';
import axios from '~/lib/utils/axios_utils';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
-import { s__ } from '~/locale';
import { STATUSES } from '../../constants';
-import { i18n, NEW_NAME_FIELD } from '../constants';
-import { isAvailableForImport } from '../utils';
import bulkImportSourceGroupItemFragment from './fragments/bulk_import_source_group_item.fragment.graphql';
import bulkImportSourceGroupProgressFragment from './fragments/bulk_import_source_group_progress.fragment.graphql';
-import addValidationErrorMutation from './mutations/add_validation_error.mutation.graphql';
-import removeValidationErrorMutation from './mutations/remove_validation_error.mutation.graphql';
-import setImportProgressMutation from './mutations/set_import_progress.mutation.graphql';
-import setImportTargetMutation from './mutations/set_import_target.mutation.graphql';
-import updateImportStatusMutation from './mutations/update_import_status.mutation.graphql';
-import availableNamespacesQuery from './queries/available_namespaces.query.graphql';
-import bulkImportSourceGroupQuery from './queries/bulk_import_source_group.query.graphql';
-import groupAndProjectQuery from './queries/group_and_project.query.graphql';
-import { SourceGroupsManager } from './services/source_groups_manager';
-import { StatusPoller } from './services/status_poller';
+import { LocalStorageCache } from './services/local_storage_cache';
import typeDefs from './typedefs.graphql';
export const clientTypenames = {
@@ -27,221 +14,99 @@ export const clientTypenames = {
BulkImportPageInfo: 'ClientBulkImportPageInfo',
BulkImportTarget: 'ClientBulkImportTarget',
BulkImportProgress: 'ClientBulkImportProgress',
- BulkImportValidationError: 'ClientBulkImportValidationError',
};
-function makeGroup(data) {
- const result = {
- __typename: clientTypenames.BulkImportSourceGroup,
+function makeLastImportTarget(data) {
+ return {
+ __typename: clientTypenames.BulkImportTarget,
...data,
};
- const NESTED_OBJECT_FIELDS = {
- import_target: clientTypenames.BulkImportTarget,
- last_import_target: clientTypenames.BulkImportTarget,
- progress: clientTypenames.BulkImportProgress,
- };
-
- Object.entries(NESTED_OBJECT_FIELDS).forEach(([field, type]) => {
- if (!data[field]) {
- return;
- }
- result[field] = {
- __typename: type,
- ...data[field],
- };
- });
-
- return result;
}
-async function checkImportTargetIsValid({ client, newName, targetNamespace, sourceGroupId }) {
- const {
- data: { existingGroup, existingProject },
- } = await client.query({
- query: groupAndProjectQuery,
- fetchPolicy: 'no-cache',
- variables: {
- fullPath: `${targetNamespace}/${newName}`,
- },
- });
-
- const variables = {
- field: NEW_NAME_FIELD,
- sourceGroupId,
+function makeProgress(data) {
+ return {
+ __typename: clientTypenames.BulkImportProgress,
+ ...data,
};
-
- if (!existingGroup && !existingProject) {
- client.mutate({
- mutation: removeValidationErrorMutation,
- variables,
- });
- } else {
- client.mutate({
- mutation: addValidationErrorMutation,
- variables: {
- ...variables,
- message: i18n.NAME_ALREADY_EXISTS,
- },
- });
- }
}
-const localProgressId = (id) => `not-started-${id}`;
-const nextName = (name) => `${name}-1`;
+function makeGroup(data) {
+ return {
+ __typename: clientTypenames.BulkImportSourceGroup,
+ ...data,
+ progress: data.progress
+ ? makeProgress({
+ id: `LOCAL-PROGRESS-${data.id}`,
+ ...data.progress,
+ })
+ : null,
+ lastImportTarget: data.lastImportTarget
+ ? makeLastImportTarget({
+ id: data.id,
+ ...data.lastImportTarget,
+ })
+ : null,
+ };
+}
-export function createResolvers({ endpoints, sourceUrl, GroupsManager = SourceGroupsManager }) {
- const groupsManager = new GroupsManager({
- sourceUrl,
+function getGroupFromCache({ client, id, getCacheKey }) {
+ return client.readFragment({
+ fragment: bulkImportSourceGroupItemFragment,
+ fragmentName: 'BulkImportSourceGroupItem',
+ id: getCacheKey({
+ __typename: clientTypenames.BulkImportSourceGroup,
+ id,
+ }),
});
+}
- let statusPoller;
+export function createResolvers({ endpoints }) {
+ const localStorageCache = new LocalStorageCache();
return {
Query: {
- async bulkImportSourceGroup(_, { id }, { client, getCacheKey }) {
- return client.readFragment({
- fragment: bulkImportSourceGroupItemFragment,
- fragmentName: 'BulkImportSourceGroupItem',
- id: getCacheKey({
- __typename: clientTypenames.BulkImportSourceGroup,
- id,
- }),
+ async bulkImportSourceGroups(_, vars) {
+ const { headers, data } = await axios.get(endpoints.status, {
+ params: {
+ page: vars.page,
+ per_page: vars.perPage,
+ filter: vars.filter,
+ },
});
- },
- async bulkImportSourceGroups(_, vars, { client }) {
- if (!statusPoller) {
- statusPoller = new StatusPoller({
- updateImportStatus: ({ id, status_name: status }) =>
- client.mutate({
- mutation: updateImportStatusMutation,
- variables: { id, status },
- }),
- pollPath: endpoints.jobs,
- });
- statusPoller.startPolling();
- }
-
- return Promise.all([
- axios.get(endpoints.status, {
- params: {
- page: vars.page,
- per_page: vars.perPage,
- filter: vars.filter,
- },
- }),
- client.query({ query: availableNamespacesQuery }),
- ]).then(
- ([
- { headers, data },
- {
- data: { availableNamespaces },
- },
- ]) => {
- const pagination = parseIntPagination(normalizeHeaders(headers));
-
- const response = {
- __typename: clientTypenames.BulkImportSourceGroupConnection,
- nodes: data.importable_data.map((group) => {
- const { jobId, importState: cachedImportState } =
- groupsManager.getImportStateFromStorageByGroupId(group.id) ?? {};
-
- const status = cachedImportState?.status ?? STATUSES.NONE;
-
- const importTarget =
- status === STATUSES.FINISHED && cachedImportState.importTarget
- ? {
- target_namespace: cachedImportState.importTarget.target_namespace,
- new_name: nextName(cachedImportState.importTarget.new_name),
- }
- : cachedImportState?.importTarget ?? {
- new_name: group.full_path,
- target_namespace: availableNamespaces[0]?.full_path ?? '',
- };
-
- return makeGroup({
- ...group,
- validation_errors: [],
- progress: {
- id: jobId ?? localProgressId(group.id),
- status,
- },
- import_target: importTarget,
- last_import_target: cachedImportState?.importTarget ?? null,
- });
- }),
- pageInfo: {
- __typename: clientTypenames.BulkImportPageInfo,
- ...pagination,
- },
- };
-
- setTimeout(() => {
- response.nodes.forEach((group) => {
- if (isAvailableForImport(group)) {
- checkImportTargetIsValid({
- client,
- newName: group.import_target.new_name,
- targetNamespace: group.import_target.target_namespace,
- sourceGroupId: group.id,
- });
- }
- });
+ const pagination = parseIntPagination(normalizeHeaders(headers));
+
+ const response = {
+ __typename: clientTypenames.BulkImportSourceGroupConnection,
+ nodes: data.importable_data.map((group) => {
+ return makeGroup({
+ id: group.id,
+ webUrl: group.web_url,
+ fullPath: group.full_path,
+ fullName: group.full_name,
+ ...group,
+ ...localStorageCache.get(group.web_url),
});
-
- return response;
+ }),
+ pageInfo: {
+ __typename: clientTypenames.BulkImportPageInfo,
+ ...pagination,
},
- );
+ };
+ return response;
},
availableNamespaces: () =>
axios.get(endpoints.availableNamespaces).then(({ data }) =>
data.map((namespace) => ({
__typename: clientTypenames.AvailableNamespace,
- ...namespace,
+ id: namespace.id,
+ fullPath: namespace.full_path,
})),
),
},
Mutation: {
- setImportTarget(_, { targetNamespace, newName, sourceGroupId }, { client }) {
- checkImportTargetIsValid({
- client,
- sourceGroupId,
- targetNamespace,
- newName,
- });
-
- return makeGroup({
- id: sourceGroupId,
- import_target: {
- target_namespace: targetNamespace,
- new_name: newName,
- id: sourceGroupId,
- },
- });
- },
-
- async setImportProgress(_, { sourceGroupId, status, jobId, importTarget }) {
- if (jobId) {
- groupsManager.updateImportProgress(jobId, status);
- }
-
- return makeGroup({
- id: sourceGroupId,
- progress: {
- id: jobId ?? localProgressId(sourceGroupId),
- status,
- },
- last_import_target: {
- __typename: clientTypenames.BulkImportTarget,
- ...importTarget,
- },
- });
- },
-
async updateImportStatus(_, { id, status: newStatus }, { client, getCacheKey }) {
- groupsManager.updateImportProgress(id, newStatus);
-
const progressItem = client.readFragment({
fragment: bulkImportSourceGroupProgressFragment,
fragmentName: 'BulkImportSourceGroupProgress',
@@ -251,133 +116,62 @@ export function createResolvers({ endpoints, sourceUrl, GroupsManager = SourceGr
}),
});
- const isInProgress = Boolean(progressItem);
- const { status: currentStatus } = progressItem ?? {};
- if (newStatus === STATUSES.FINISHED && isInProgress && currentStatus !== newStatus) {
- const groups = groupsManager.getImportedGroupsByJobId(id);
+ if (!progressItem) return null;
- groups.forEach(async ({ id: groupId, importTarget }) => {
- client.mutate({
- mutation: setImportTargetMutation,
- variables: {
- sourceGroupId: groupId,
- targetNamespace: importTarget.target_namespace,
- newName: nextName(importTarget.new_name),
- },
- });
- });
- }
+ localStorageCache.updateStatusByJobId(id, newStatus);
return {
__typename: clientTypenames.BulkImportProgress,
+ ...progressItem,
id,
status: newStatus,
};
},
- async addValidationError(_, { sourceGroupId, field, message }, { client }) {
- const {
- data: {
- bulkImportSourceGroup: { validation_errors: validationErrors, ...group },
- },
- } = await client.query({
- query: bulkImportSourceGroupQuery,
- variables: { id: sourceGroupId },
- });
+ async importGroups(_, { importRequests }, { client, getCacheKey }) {
+ const importOperations = importRequests.map((importRequest) => {
+ const group = getGroupFromCache({
+ client,
+ getCacheKey,
+ id: importRequest.sourceGroupId,
+ });
- return {
- ...group,
- validation_errors: [
- ...validationErrors.filter(({ field: f }) => f !== field),
- {
- __typename: clientTypenames.BulkImportValidationError,
- field,
- message,
- },
- ],
- };
- },
+ return {
+ group,
+ ...importRequest,
+ };
+ });
- async removeValidationError(_, { sourceGroupId, field }, { client }) {
const {
- data: {
- bulkImportSourceGroup: { validation_errors: validationErrors, ...group },
- },
- } = await client.query({
- query: bulkImportSourceGroupQuery,
- variables: { id: sourceGroupId },
+ data: { id: jobId },
+ } = await axios.post(endpoints.createBulkImport, {
+ bulk_import: importOperations.map((op) => ({
+ source_type: 'group_entity',
+ source_full_path: op.group.fullPath,
+ destination_namespace: op.targetNamespace,
+ destination_name: op.newName,
+ })),
});
- return {
- ...group,
- validation_errors: validationErrors.filter(({ field: f }) => f !== field),
- };
- },
-
- async importGroups(_, { sourceGroupIds }, { client }) {
- const groups = await Promise.all(
- sourceGroupIds.map((id) =>
- client
- .query({
- query: bulkImportSourceGroupQuery,
- variables: { id },
- })
- .then(({ data }) => data.bulkImportSourceGroup),
- ),
- );
+ return importOperations.map((op) => {
+ const lastImportTarget = {
+ targetNamespace: op.targetNamespace,
+ newName: op.newName,
+ };
- const GROUPS_BEING_SCHEDULED = sourceGroupIds.map((sourceGroupId) =>
- makeGroup({
- id: sourceGroupId,
- progress: {
- id: localProgressId(sourceGroupId),
- status: STATUSES.SCHEDULING,
- },
- }),
- );
-
- const defaultErrorMessage = s__('BulkImport|Importing the group failed');
- axios
- .post(endpoints.createBulkImport, {
- bulk_import: groups.map((group) => ({
- source_type: 'group_entity',
- source_full_path: group.full_path,
- destination_namespace: group.import_target.target_namespace,
- destination_name: group.import_target.new_name,
- })),
- })
- .then(({ data: { id: jobId } }) => {
- groupsManager.createImportState(jobId, {
- status: STATUSES.CREATED,
- groups,
- });
+ const progress = {
+ id: jobId,
+ status: STATUSES.CREATED,
+ };
- return { status: STATUSES.CREATED, jobId };
- })
- .catch((e) => {
- const message = e?.response?.data?.error ?? defaultErrorMessage;
- createFlash({ message });
- return { status: STATUSES.NONE };
- })
- .then((newStatus) =>
- sourceGroupIds.forEach((sourceGroupId, idx) =>
- client.mutate({
- mutation: setImportProgressMutation,
- variables: { sourceGroupId, ...newStatus, importTarget: groups[idx].import_target },
- }),
- ),
- )
- .catch(() => createFlash({ message: defaultErrorMessage }));
+ localStorageCache.set(op.group.webUrl, { progress, lastImportTarget });
- return GROUPS_BEING_SCHEDULED;
+ return makeGroup({ ...op.group, progress, lastImportTarget });
+ });
},
},
};
}
export const createApolloClient = ({ sourceUrl, endpoints }) =>
- createDefaultClient(
- createResolvers({ sourceUrl, endpoints }),
- { assumeImmutableResults: true },
- typeDefs,
- );
+ createDefaultClient(createResolvers({ sourceUrl, endpoints }), { typeDefs });
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_item.fragment.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_item.fragment.graphql
index 089340b3c48..0d83be7c0e8 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_item.fragment.graphql
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_item.fragment.graphql
@@ -2,22 +2,15 @@
fragment BulkImportSourceGroupItem on ClientBulkImportSourceGroup {
id
- web_url
- full_path
- full_name
+ webUrl
+ fullPath
+ fullName
+ lastImportTarget {
+ id
+ targetNamespace
+ newName
+ }
progress {
...BulkImportSourceGroupProgress
}
- import_target {
- target_namespace
- new_name
- }
- last_import_target {
- target_namespace
- new_name
- }
- validation_errors {
- field
- message
- }
}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/add_validation_error.mutation.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/mutations/add_validation_error.mutation.graphql
deleted file mode 100644
index d95c460c046..00000000000
--- a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/add_validation_error.mutation.graphql
+++ /dev/null
@@ -1,9 +0,0 @@
-mutation addValidationError($sourceGroupId: String!, $field: String!, $message: String!) {
- addValidationError(sourceGroupId: $sourceGroupId, field: $field, message: $message) @client {
- id
- validation_errors {
- field
- message
- }
- }
-}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql
index d8e46329e38..75215471d0f 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql
@@ -1,6 +1,11 @@
-mutation importGroups($sourceGroupIds: [String!]!) {
- importGroups(sourceGroupIds: $sourceGroupIds) @client {
+mutation importGroups($importRequests: [ImportGroupInput!]!) {
+ importGroups(importRequests: $importRequests) @client {
id
+ lastImportTarget {
+ id
+ targetNamespace
+ newName
+ }
progress {
id
status
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/remove_validation_error.mutation.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/mutations/remove_validation_error.mutation.graphql
deleted file mode 100644
index 940bf4dfaac..00000000000
--- a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/remove_validation_error.mutation.graphql
+++ /dev/null
@@ -1,9 +0,0 @@
-mutation removeValidationError($sourceGroupId: String!, $field: String!) {
- removeValidationError(sourceGroupId: $sourceGroupId, field: $field) @client {
- id
- validation_errors {
- field
- message
- }
- }
-}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/set_import_progress.mutation.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/mutations/set_import_progress.mutation.graphql
deleted file mode 100644
index 43301554de3..00000000000
--- a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/set_import_progress.mutation.graphql
+++ /dev/null
@@ -1,23 +0,0 @@
-mutation setImportProgress(
- $status: String!
- $sourceGroupId: String!
- $jobId: String
- $importTarget: ImportTargetInput!
-) {
- setImportProgress(
- status: $status
- sourceGroupId: $sourceGroupId
- jobId: $jobId
- importTarget: $importTarget
- ) @client {
- id
- progress {
- id
- status
- }
- last_import_target {
- target_namespace
- new_name
- }
- }
-}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/set_import_target.mutation.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/mutations/set_import_target.mutation.graphql
deleted file mode 100644
index 793b60ee378..00000000000
--- a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/set_import_target.mutation.graphql
+++ /dev/null
@@ -1,13 +0,0 @@
-mutation setImportTarget($newName: String!, $targetNamespace: String!, $sourceGroupId: String!) {
- setImportTarget(
- newName: $newName
- targetNamespace: $targetNamespace
- sourceGroupId: $sourceGroupId
- ) @client {
- id
- import_target {
- new_name
- target_namespace
- }
- }
-}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/queries/available_namespaces.query.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/queries/available_namespaces.query.graphql
index 5ab9796b50a..b0741dfbe5c 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/queries/available_namespaces.query.graphql
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/queries/available_namespaces.query.graphql
@@ -1,6 +1,6 @@
query availableNamespaces {
availableNamespaces @client {
id
- full_path
+ fullPath
}
}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_group.query.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_group.query.graphql
deleted file mode 100644
index 0aff23af96d..00000000000
--- a/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_group.query.graphql
+++ /dev/null
@@ -1,7 +0,0 @@
-#import "../fragments/bulk_import_source_group_item.fragment.graphql"
-
-query bulkImportSourceGroup($id: ID!) {
- bulkImportSourceGroup(id: $id) @client {
- ...BulkImportSourceGroupItem
- }
-}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/queries/group_and_project.query.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/queries/group_and_project.query.graphql
deleted file mode 100644
index d6124f84025..00000000000
--- a/app/assets/javascripts/import_entities/import_groups/graphql/queries/group_and_project.query.graphql
+++ /dev/null
@@ -1,9 +0,0 @@
-query groupAndProject($fullPath: ID!) {
- existingGroup: group(fullPath: $fullPath) {
- id
- }
-
- existingProject: project(fullPath: $fullPath) {
- id
- }
-}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js b/app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js
new file mode 100644
index 00000000000..09bc7b33692
--- /dev/null
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js
@@ -0,0 +1,74 @@
+import { debounce, merge } from 'lodash';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
+
+const OLD_KEY = 'gl-bulk-imports-import-state';
+export const KEY = 'gl-bulk-imports-import-state-v2';
+export const DEBOUNCE_INTERVAL = DEFAULT_DEBOUNCE_AND_THROTTLE_MS;
+
+export class LocalStorageCache {
+ constructor({ storage = window.localStorage } = {}) {
+ this.storage = storage;
+ this.cache = this.loadCacheFromStorage();
+ try {
+ // remove old storage data
+ this.storage.removeItem(OLD_KEY);
+ } catch {
+ // empty catch intended
+ }
+
+ // cache for searching data by jobid
+ this.jobsLookupCache = {};
+ }
+
+ loadCacheFromStorage() {
+ try {
+ return JSON.parse(this.storage.getItem(KEY)) ?? {};
+ } catch {
+ return {};
+ }
+ }
+
+ set(webUrl, data) {
+ this.cache[webUrl] = data;
+ this.saveCacheToStorage();
+ // There are changes to jobIds, drop cache
+ this.jobsLookupCache = {};
+ }
+
+ get(webUrl) {
+ return this.cache[webUrl];
+ }
+
+ getCacheKeysByJobId(jobId) {
+ // this is invoked by polling, so we would like to cache results
+ if (!this.jobsLookupCache[jobId]) {
+ this.jobsLookupCache[jobId] = Object.keys(this.cache).filter(
+ (url) => this.cache[url]?.progress.id === jobId,
+ );
+ }
+
+ return this.jobsLookupCache[jobId];
+ }
+
+ updateStatusByJobId(jobId, status) {
+ this.getCacheKeysByJobId(jobId).forEach((webUrl) =>
+ this.set(webUrl, {
+ ...(this.get(webUrl) ?? {}),
+ progress: {
+ id: jobId,
+ status,
+ },
+ }),
+ );
+ this.saveCacheToStorage();
+ }
+
+ saveCacheToStorage = debounce(() => {
+ try {
+ // storage might be changed in other tab so fetch first
+ this.storage.setItem(KEY, JSON.stringify(merge({}, this.loadCacheFromStorage(), this.cache)));
+ } catch {
+ // empty catch intentional: storage might be unavailable or full
+ }
+ }, DEBOUNCE_INTERVAL);
+}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js b/app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js
deleted file mode 100644
index 7caa37d9ad4..00000000000
--- a/app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import { debounce, merge } from 'lodash';
-
-export const KEY = 'gl-bulk-imports-import-state';
-export const DEBOUNCE_INTERVAL = 200;
-
-export class SourceGroupsManager {
- constructor({ sourceUrl, storage = window.localStorage }) {
- this.sourceUrl = sourceUrl;
-
- this.storage = storage;
- this.importStates = this.loadImportStatesFromStorage();
- }
-
- loadImportStatesFromStorage() {
- try {
- return Object.fromEntries(
- Object.entries(JSON.parse(this.storage.getItem(KEY)) ?? {}).map(([jobId, config]) => {
- // new format of storage
- if (config.groups) {
- return [jobId, config];
- }
-
- return [
- jobId,
- {
- status: config.status,
- groups: [{ id: config.id, importTarget: config.importTarget }],
- },
- ];
- }),
- );
- } catch {
- return {};
- }
- }
-
- createImportState(importId, jobConfig) {
- this.importStates[importId] = {
- status: jobConfig.status,
- groups: jobConfig.groups.map((g) => ({
- importTarget: { ...g.import_target },
- id: g.id,
- })),
- };
- this.saveImportStatesToStorage();
- }
-
- updateImportProgress(importId, status) {
- const currentState = this.importStates[importId];
- if (!currentState) {
- return;
- }
-
- currentState.status = status;
- this.saveImportStatesToStorage();
- }
-
- getImportedGroupsByJobId(jobId) {
- return this.importStates[jobId]?.groups ?? [];
- }
-
- getImportStateFromStorageByGroupId(groupId) {
- const [jobId, importState] =
- Object.entries(this.importStates)
- .reverse()
- .find(([, state]) => state.groups.some((g) => g.id === groupId)) ?? [];
-
- if (!jobId) {
- return null;
- }
-
- const group = importState.groups.find((g) => g.id === groupId);
- return { jobId, importState: { ...group, status: importState.status } };
- }
-
- saveImportStatesToStorage = debounce(() => {
- try {
- // storage might be changed in other tab so fetch first
- this.storage.setItem(
- KEY,
- JSON.stringify(merge({}, this.loadImportStatesFromStorage(), this.importStates)),
- );
- } catch {
- // empty catch intentional: storage might be unavailable or full
- }
- }, DEBOUNCE_INTERVAL);
-}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js b/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js
deleted file mode 100644
index 0297b3d3428..00000000000
--- a/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import Visibility from 'visibilityjs';
-import createFlash from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-import Poll from '~/lib/utils/poll';
-import { s__ } from '~/locale';
-
-export class StatusPoller {
- constructor({ updateImportStatus, pollPath }) {
- this.eTagPoll = new Poll({
- resource: {
- fetchJobs: () => axios.get(pollPath),
- },
- method: 'fetchJobs',
- successCallback: ({ data: statuses }) => {
- statuses.forEach((status) => updateImportStatus(status));
- },
- errorCallback: () =>
- createFlash({
- message: s__('BulkImport|Update of import statuses with realtime changes failed'),
- }),
- });
-
- Visibility.change(() => {
- if (!Visibility.hidden()) {
- this.eTagPoll.restart();
- } else {
- this.eTagPoll.stop();
- }
- });
- }
-
- startPolling() {
- this.eTagPoll.makeRequest();
- }
-}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql
index 6ef4bbafec0..b8dd79a5000 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql
@@ -1,11 +1,11 @@
type ClientBulkImportAvailableNamespace {
id: ID!
- full_path: String!
+ fullPath: String!
}
type ClientBulkImportTarget {
- target_namespace: String!
- new_name: String!
+ targetNamespace: String!
+ newName: String!
}
type ClientBulkImportSourceGroupConnection {
@@ -14,7 +14,7 @@ type ClientBulkImportSourceGroupConnection {
}
type ClientBulkImportProgress {
- id: ID
+ id: ID!
status: String!
}
@@ -25,13 +25,11 @@ type ClientBulkImportValidationError {
type ClientBulkImportSourceGroup {
id: ID!
- web_url: String!
- full_path: String!
- full_name: String!
- progress: ClientBulkImportProgress!
- import_target: ClientBulkImportTarget!
- last_import_target: ClientBulkImportTarget
- validation_errors: [ClientBulkImportValidationError!]!
+ webUrl: String!
+ fullPath: String!
+ fullName: String!
+ lastImportTarget: ClientBulkImportTarget
+ progress: ClientBulkImportProgress
}
type ClientBulkImportPageInfo {
@@ -41,8 +39,13 @@ type ClientBulkImportPageInfo {
totalPages: Int!
}
+type ClientBulkImportNamespaceSuggestion {
+ id: ID!
+ exists: Boolean!
+ suggestions: [String!]!
+}
+
extend type Query {
- bulkImportSourceGroup(id: ID!): ClientBulkImportSourceGroup
bulkImportSourceGroups(
page: Int!
perPage: Int!
@@ -51,26 +54,13 @@ extend type Query {
availableNamespaces: [ClientBulkImportAvailableNamespace!]!
}
-input InputTargetInput {
- target_namespace: String!
- new_name: String!
+input ImportRequestInput {
+ sourceGroupId: ID!
+ targetNamespace: String!
+ newName: String!
}
extend type Mutation {
- setNewName(newName: String, sourceGroupId: ID!): ClientBulkImportSourceGroup!
- setTargetNamespace(targetNamespace: String, sourceGroupId: ID!): ClientBulkImportSourceGroup!
- importGroups(sourceGroupIds: [ID!]!): [ClientBulkImportSourceGroup!]!
- setImportProgress(
- id: ID
- status: String!
- jobId: String
- importTarget: ImportTargetInput!
- ): ClientBulkImportSourceGroup!
- updateImportProgress(id: ID, status: String!): ClientBulkImportProgress
- addValidationError(
- sourceGroupId: ID!
- field: String!
- message: String!
- ): ClientBulkImportSourceGroup!
- removeValidationError(sourceGroupId: ID!, field: String!): ClientBulkImportSourceGroup!
+ importGroups(importRequests: [ImportRequestInput!]!): [ClientBulkImportSourceGroup!]!
+ updateImportStatus(id: ID, status: String!): ClientBulkImportProgress
}
diff --git a/app/assets/javascripts/import_entities/import_groups/index.js b/app/assets/javascripts/import_entities/import_groups/index.js
index 07b839c5c82..67a7258d504 100644
--- a/app/assets/javascripts/import_entities/import_groups/index.js
+++ b/app/assets/javascripts/import_entities/import_groups/index.js
@@ -17,7 +17,6 @@ export function mountImportGroupsApp(mountElement) {
jobsPath,
sourceUrl,
groupPathRegex,
- groupUrlErrorMessage,
} = mountElement.dataset;
const apolloProvider = new VueApollo({
defaultClient: createApolloClient({
@@ -26,7 +25,6 @@ export function mountImportGroupsApp(mountElement) {
status: statusPath,
availableNamespaces: availableNamespacesPath,
createBulkImport: createBulkImportPath,
- jobs: jobsPath,
},
}),
});
@@ -38,8 +36,8 @@ export function mountImportGroupsApp(mountElement) {
return createElement(ImportTable, {
props: {
sourceUrl,
+ jobsPath,
groupPathRegex: new RegExp(`^(${groupPathRegex})$`),
- groupUrlErrorMessage,
},
});
},
diff --git a/app/assets/javascripts/import_entities/import_groups/services/status_poller.js b/app/assets/javascripts/import_entities/import_groups/services/status_poller.js
new file mode 100644
index 00000000000..ba0f2bb947a
--- /dev/null
+++ b/app/assets/javascripts/import_entities/import_groups/services/status_poller.js
@@ -0,0 +1,39 @@
+import Visibility from 'visibilityjs';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import Poll from '~/lib/utils/poll';
+import { s__ } from '~/locale';
+
+export class StatusPoller {
+ constructor({ updateImportStatus, pollPath }) {
+ this.eTagPoll = new Poll({
+ resource: {
+ fetchJobs: () => axios.get(pollPath),
+ },
+ method: 'fetchJobs',
+ successCallback: ({ data: statuses }) => {
+ statuses.forEach((status) => updateImportStatus(status));
+ },
+ errorCallback: () =>
+ createFlash({
+ message: s__('BulkImport|Update of import statuses with realtime changes failed'),
+ }),
+ });
+
+ Visibility.change(() => {
+ if (!Visibility.hidden()) {
+ this.eTagPoll.restart();
+ } else {
+ this.eTagPoll.stop();
+ }
+ });
+ }
+
+ startPolling() {
+ this.eTagPoll.makeRequest();
+ }
+
+ stopPolling() {
+ this.eTagPoll.stop();
+ }
+}
diff --git a/app/assets/javascripts/import_entities/import_groups/utils.js b/app/assets/javascripts/import_entities/import_groups/utils.js
index a1baeaf39dd..1d0ab75e1cb 100644
--- a/app/assets/javascripts/import_entities/import_groups/utils.js
+++ b/app/assets/javascripts/import_entities/import_groups/utils.js
@@ -1,22 +1,25 @@
import { STATUSES } from '../constants';
import { NEW_NAME_FIELD } from './constants';
-export function isNameValid(group, validationRegex) {
- return validationRegex.test(group.import_target[NEW_NAME_FIELD]);
+export function isNameValid(importTarget, validationRegex) {
+ return validationRegex.test(importTarget[NEW_NAME_FIELD]);
}
-export function getInvalidNameValidationMessage(group) {
- return group.validation_errors.find(({ field }) => field === NEW_NAME_FIELD)?.message;
-}
-
-export function isInvalid(group, validationRegex) {
- return Boolean(!isNameValid(group, validationRegex) || getInvalidNameValidationMessage(group));
+export function getInvalidNameValidationMessage(importTarget) {
+ return importTarget.validationErrors?.find(({ field }) => field === NEW_NAME_FIELD)?.message;
}
export function isFinished(group) {
- return group.progress.status === STATUSES.FINISHED;
+ return [STATUSES.FINISHED, STATUSES.FAILED].includes(group.progress?.status);
}
export function isAvailableForImport(group) {
- return [STATUSES.NONE, STATUSES.FINISHED].some((status) => group.progress.status === status);
+ return !group.progress || isFinished(group);
+}
+
+export function isSameTarget(importTarget) {
+ return (target) =>
+ target !== importTarget &&
+ target.newName.toLowerCase() === importTarget.newName.toLowerCase() &&
+ target.targetNamespace.id === importTarget.targetNamespace.id;
}
diff --git a/app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue b/app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue
index 0cd3519bcec..b9f0b5012ac 100644
--- a/app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue
+++ b/app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue
@@ -46,10 +46,6 @@ export default {
return `${this.filter}-${this.repositories.length}-${this.pageInfo.page}`;
},
- availableNamespaces() {
- return this.namespaces.map(({ fullPath }) => fullPath);
- },
-
importAllButtonText() {
if (this.isImportingAnyRepo) {
return n__('Importing %d repository', 'Importing %d repositories', this.importingRepoCount);
@@ -167,7 +163,7 @@ export default {
<provider-repo-table-row
:key="repo.importSource.providerLink"
:repo="repo"
- :available-namespaces="availableNamespaces"
+ :available-namespaces="namespaces"
:user-namespace="defaultTargetNamespace"
/>
</template>
diff --git a/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue b/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue
index a97af5367fb..c3d0ca4ed8c 100644
--- a/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue
+++ b/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue
@@ -128,17 +128,17 @@ export default {
<gl-dropdown-section-header>{{ __('Groups') }}</gl-dropdown-section-header>
<gl-dropdown-item
v-for="ns in namespaces"
- :key="ns"
+ :key="ns.fullPath"
data-qa-selector="target_group_dropdown_item"
- :data-qa-group-name="ns"
- @click="updateImportTarget({ targetNamespace: ns })"
+ :data-qa-group-name="ns.fullPath"
+ @click="updateImportTarget({ targetNamespace: ns.fullPath })"
>
- {{ ns }}
+ {{ ns.fullPath }}
</gl-dropdown-item>
<gl-dropdown-divider />
</template>
<gl-dropdown-section-header>{{ __('Users') }}</gl-dropdown-section-header>
- <gl-dropdown-item @click="updateImportTarget({ targetNamespace: ns })">{{
+ <gl-dropdown-item @click="updateImportTarget({ targetNamespace: userNamespace })">{{
userNamespace
}}</gl-dropdown-item>
</import-group-dropdown>
diff --git a/app/assets/javascripts/incidents/components/incidents_list.vue b/app/assets/javascripts/incidents/components/incidents_list.vue
index 4d34daa43ba..37597da3c8e 100644
--- a/app/assets/javascripts/incidents/components/incidents_list.vue
+++ b/app/assets/javascripts/incidents/components/incidents_list.vue
@@ -125,6 +125,7 @@ export default {
'authorUsernameQuery',
'assigneeUsernameQuery',
'slaFeatureAvailable',
+ 'canCreateIncident',
],
apollo: {
incidents: {
@@ -230,13 +231,16 @@ export default {
},
emptyStateData() {
const {
- emptyState: { title, emptyClosedTabTitle, description },
+ emptyState: { title, emptyClosedTabTitle, description, cannotCreateIncidentDescription },
createIncidentBtnLabel,
} = this.$options.i18n;
if (this.activeClosedTabHasNoIncidents) {
return { title: emptyClosedTabTitle };
}
+ if (!this.canCreateIncident) {
+ return { title, description: cannotCreateIncidentDescription };
+ }
return {
title,
description,
@@ -244,6 +248,9 @@ export default {
btnText: createIncidentBtnLabel,
};
},
+ isHeaderButtonVisible() {
+ return this.canCreateIncident && (!this.isEmpty || this.activeClosedTabHasNoIncidents);
+ },
},
methods: {
hasAssignees(assignees) {
@@ -311,7 +318,7 @@ export default {
>
<template #header-actions>
<gl-button
- v-if="!isEmpty || activeClosedTabHasNoIncidents"
+ v-if="isHeaderButtonVisible"
class="gl-my-3 gl-mr-5 create-incident-button"
data-testid="createIncidentBtn"
data-qa-selector="create_incident_button"
diff --git a/app/assets/javascripts/incidents/constants.js b/app/assets/javascripts/incidents/constants.js
index b82980b5628..23909ae3b6c 100644
--- a/app/assets/javascripts/incidents/constants.js
+++ b/app/assets/javascripts/incidents/constants.js
@@ -11,7 +11,10 @@ export const I18N = {
title: s__('IncidentManagement|Display your incidents in a dedicated view'),
emptyClosedTabTitle: s__('IncidentManagement|There are no closed incidents'),
description: s__(
- 'IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below.',
+ 'IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below.',
+ ),
+ cannotCreateIncidentDescription: s__(
+ 'IncidentManagement|All alerts promoted to incidents are automatically displayed within the list.',
),
},
};
diff --git a/app/assets/javascripts/incidents/list.js b/app/assets/javascripts/incidents/list.js
index 6e6461cd7a9..1d40f1093a4 100644
--- a/app/assets/javascripts/incidents/list.js
+++ b/app/assets/javascripts/incidents/list.js
@@ -21,10 +21,11 @@ export default () => {
authorUsernameQuery,
assigneeUsernameQuery,
slaFeatureAvailable,
+ canCreateIncident,
} = domEl.dataset;
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
return new Vue({
@@ -44,6 +45,7 @@ export default () => {
authorUsernameQuery,
assigneeUsernameQuery,
slaFeatureAvailable: parseBoolean(slaFeatureAvailable),
+ canCreateIncident: parseBoolean(canCreateIncident),
},
apolloProvider,
render(createElement) {
diff --git a/app/assets/javascripts/init_confirm_danger.js b/app/assets/javascripts/init_confirm_danger.js
new file mode 100644
index 00000000000..d3d32c8be54
--- /dev/null
+++ b/app/assets/javascripts/init_confirm_danger.js
@@ -0,0 +1,38 @@
+import Vue from 'vue';
+import { parseBoolean } from './lib/utils/common_utils';
+import ConfirmDanger from './vue_shared/components/confirm_danger/confirm_danger.vue';
+
+export default () => {
+ const el = document.querySelector('.js-confirm-danger');
+ if (!el) return null;
+
+ const {
+ removeFormId = null,
+ phrase,
+ buttonText,
+ buttonTestid = null,
+ confirmDangerMessage,
+ disabled = false,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ confirmDangerMessage,
+ },
+ render: (createElement) =>
+ createElement(ConfirmDanger, {
+ props: {
+ phrase,
+ buttonText,
+ buttonTestid,
+ disabled: parseBoolean(disabled),
+ },
+ on: {
+ confirm: () => {
+ if (removeFormId) document.getElementById(removeFormId)?.submit();
+ },
+ },
+ }),
+ });
+};
diff --git a/app/assets/javascripts/integrations/constants.js b/app/assets/javascripts/integrations/constants.js
index 8a8d38b295c..d214ee4ded6 100644
--- a/app/assets/javascripts/integrations/constants.js
+++ b/app/assets/javascripts/integrations/constants.js
@@ -1,4 +1,4 @@
-import { s__ } from '~/locale';
+import { s__, __ } from '~/locale';
export const TEST_INTEGRATION_EVENT = 'testIntegration';
export const SAVE_INTEGRATION_EVENT = 'saveIntegration';
@@ -21,3 +21,9 @@ export const overrideDropdownDescriptions = {
'Integrations|Default settings are inherited from the instance level.',
),
};
+
+export const I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE = s__(
+ 'Integrations|Connection failed. Please check your settings.',
+);
+export const I18N_DEFAULT_ERROR_MESSAGE = __('Something went wrong on our end.');
+export const I18N_SUCCESSFUL_CONNECTION_MESSAGE = s__('Integrations|Connection successful.');
diff --git a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
index f30298676df..258cd1bf365 100644
--- a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
+++ b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
@@ -62,6 +62,14 @@ export default {
required: false,
default: null,
},
+ /**
+ * The label that is displayed inline with the checkbox.
+ */
+ checkboxLabel: {
+ type: String,
+ required: false,
+ default: null,
+ },
},
data() {
return {
@@ -152,7 +160,7 @@ export default {
<template v-if="isCheckbox">
<input :name="fieldName" type="hidden" :value="model || false" />
<gl-form-checkbox :id="fieldId" v-model="model" :disabled="isInheriting">
- {{ humanizedTitle }}
+ {{ checkboxLabel || humanizedTitle }}
</gl-form-checkbox>
</template>
<template v-else-if="isSelect">
diff --git a/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue b/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
index 0521e1eeea5..7cbfb35aeaa 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
@@ -5,6 +5,7 @@ import {
VALIDATE_INTEGRATION_FORM_EVENT,
GET_JIRA_ISSUE_TYPES_EVENT,
} from '~/integrations/constants';
+import { s__, __ } from '~/locale';
import eventHub from '../event_hub';
import JiraUpgradeCta from './jira_upgrade_cta.vue';
@@ -94,33 +95,38 @@ export default {
eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT);
},
},
+ i18n: {
+ sectionTitle: s__('JiraService|View Jira issues in GitLab'),
+ sectionDescription: s__(
+ 'JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only.',
+ ),
+ enableCheckboxLabel: s__('JiraService|Enable Jira issues'),
+ enableCheckboxHelp: s__(
+ 'JiraService|Warning: All GitLab users that have access to this GitLab project are able to view all issues from the Jira project specified below.',
+ ),
+ projectKeyLabel: s__('JiraService|Jira project key'),
+ projectKeyPlaceholder: s__('JiraService|For example, AB'),
+ requiredFieldFeedback: __('This field is required.'),
+ issueTrackerConflictWarning: s__(
+ 'JiraService|Displaying Jira issues while leaving the GitLab issue functionality enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used.',
+ ),
+ },
};
</script>
<template>
<div>
- <gl-form-group
- :label="s__('JiraService|View Jira issues in GitLab')"
- label-for="jira-issue-settings"
- >
+ <gl-form-group :label="$options.i18n.sectionTitle" label-for="jira-issue-settings">
<div id="jira-issue-settings">
<p>
- {{
- s__(
- 'JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only.',
- )
- }}
+ {{ $options.i18n.sectionDescription }}
</p>
<template v-if="showJiraIssuesIntegration">
<input name="service[issues_enabled]" type="hidden" :value="enableJiraIssues || false" />
<gl-form-checkbox v-model="enableJiraIssues" :disabled="isInheriting">
- {{ s__('JiraService|Enable Jira issues') }}
+ {{ $options.i18n.enableCheckboxLabel }}
<template #help>
- {{
- s__(
- 'JiraService|Warning: All GitLab users that have access to this GitLab project are able to view all issues from the Jira project specified below.',
- )
- }}
+ {{ $options.i18n.enableCheckboxHelp }}
</template>
</gl-form-checkbox>
<template v-if="enableJiraIssues">
@@ -152,30 +158,25 @@ export default {
</gl-form-group>
<template v-if="showJiraIssuesIntegration">
<gl-form-group
- :label="s__('JiraService|Jira project key')"
+ :label="$options.i18n.projectKeyLabel"
label-for="service_project_key"
- :invalid-feedback="__('This field is required.')"
+ :invalid-feedback="$options.i18n.requiredFieldFeedback"
:state="validProjectKey"
+ data-testid="project-key-form-group"
>
<gl-form-input
id="service_project_key"
v-model="projectKey"
name="service[project_key]"
- :placeholder="s__('JiraService|For example, AB')"
+ :placeholder="$options.i18n.projectKeyPlaceholder"
:required="enableJiraIssues"
:state="validProjectKey"
:disabled="!enableJiraIssues"
:readonly="isInheriting"
/>
</gl-form-group>
- <p v-if="gitlabIssuesEnabled">
- <gl-sprintf
- :message="
- s__(
- 'JiraService|Displaying Jira issues while leaving the GitLab issue functionality enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used.',
- )
- "
- >
+ <p v-if="gitlabIssuesEnabled" data-testid="conflict-warning-text">
+ <gl-sprintf :message="$options.i18n.issueTrackerConflictWarning">
<template #link="{ content }">
<gl-link :href="editProjectPath" target="_blank">{{ content }}</gl-link>
</template>
diff --git a/app/assets/javascripts/integrations/integration_settings_form.js b/app/assets/javascripts/integrations/integration_settings_form.js
index f33364d5545..f519fc87c46 100644
--- a/app/assets/javascripts/integrations/integration_settings_form.js
+++ b/app/assets/javascripts/integrations/integration_settings_form.js
@@ -1,5 +1,4 @@
import { delay } from 'lodash';
-import { __, s__ } from '~/locale';
import toast from '~/vue_shared/plugins/global_toast';
import axios from '../lib/utils/axios_utils';
import initForm from './edit';
@@ -10,6 +9,9 @@ import {
GET_JIRA_ISSUE_TYPES_EVENT,
TOGGLE_INTEGRATION_EVENT,
VALIDATE_INTEGRATION_FORM_EVENT,
+ I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
+ I18N_DEFAULT_ERROR_MESSAGE,
+ I18N_SUCCESSFUL_CONNECTION_MESSAGE,
} from './constants';
export default class IntegrationSettingsForm {
@@ -104,11 +106,7 @@ export default class IntegrationSettingsForm {
return this.fetchTestSettings(formData)
.then(
({
- data: {
- issuetypes,
- error,
- message = s__('Integrations|Connection failed. Please check your settings.'),
- },
+ data: { issuetypes, error, message = I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE },
}) => {
if (error || !issuetypes?.length) {
eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
@@ -118,7 +116,7 @@ export default class IntegrationSettingsForm {
dispatch('receiveJiraIssueTypesSuccess', issuetypes);
},
)
- .catch(({ message = __('Something went wrong on our end.') }) => {
+ .catch(({ message = I18N_DEFAULT_ERROR_MESSAGE }) => {
dispatch('receiveJiraIssueTypesError', message);
});
}
@@ -140,11 +138,11 @@ export default class IntegrationSettingsForm {
toast(`${data.message} ${data.service_response}`);
} else {
this.vue.$store.dispatch('receiveJiraIssueTypesSuccess', data.issuetypes);
- toast(s__('Integrations|Connection successful.'));
+ toast(I18N_SUCCESSFUL_CONNECTION_MESSAGE);
}
})
.catch(() => {
- toast(__('Something went wrong on our end.'));
+ toast(I18N_DEFAULT_ERROR_MESSAGE);
})
.finally(() => {
this.vue.$store.dispatch('setIsTesting', false);
diff --git a/app/assets/javascripts/invite_members/components/confetti.vue b/app/assets/javascripts/invite_members/components/confetti.vue
new file mode 100644
index 00000000000..2e5744afcd4
--- /dev/null
+++ b/app/assets/javascripts/invite_members/components/confetti.vue
@@ -0,0 +1,33 @@
+<script>
+import confetti from 'canvas-confetti';
+
+export default {
+ mounted() {
+ confetti.create(this.$refs.canvas, {
+ resize: true,
+ useWorker: true,
+ disableForReducedMotion: true,
+ });
+
+ this.basicCannon();
+ },
+ methods: {
+ basicCannon() {
+ confetti({
+ particleCount: 100,
+ spread: 70,
+ origin: { y: 0.2 },
+ scalar: 2,
+ shapes: ['square'],
+ colors: ['#FC6D26', '#6B4FBB', '#FDB997'],
+ zIndex: 1045,
+ gravity: 1.5,
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <canvas ref="canvas" width="0" height="0"></canvas>
+</template>
diff --git a/app/assets/javascripts/invite_members/components/invite_members_modal.vue b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
index cd0b413265b..cf4f434a7a8 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -1,5 +1,6 @@
<script>
import {
+ GlAlert,
GlFormGroup,
GlModal,
GlDropdown,
@@ -11,29 +12,34 @@ import {
GlFormInput,
GlFormCheckboxGroup,
} from '@gitlab/ui';
-import { partition, isString, unescape } from 'lodash';
+import { partition, isString, unescape, uniqueId } from 'lodash';
import Api from '~/api';
import ExperimentTracking from '~/experimentation/experiment_tracking';
import { sanitize } from '~/lib/dompurify';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
-import { s__, sprintf } from '~/locale';
+import { getParameterValues } from '~/lib/utils/url_utility';
+import { sprintf } from '~/locale';
import {
INVITE_MEMBERS_IN_COMMENT,
GROUP_FILTERS,
USERS_FILTER_ALL,
MEMBER_AREAS_OF_FOCUS,
+ INVITE_MEMBERS_FOR_TASK,
+ MODAL_LABELS,
} from '../constants';
import eventHub from '../event_hub';
import {
responseMessageFromError,
responseMessageFromSuccess,
} from '../utils/response_message_parser';
+import ModalConfetti from './confetti.vue';
import GroupSelect from './group_select.vue';
import MembersTokenSelect from './members_token_select.vue';
export default {
name: 'InviteMembersModal',
components: {
+ GlAlert,
GlFormGroup,
GlDatepicker,
GlLink,
@@ -46,7 +52,9 @@ export default {
GlFormCheckboxGroup,
MembersTokenSelect,
GroupSelect,
+ ModalConfetti,
},
+ inject: ['newProjectPath'],
props: {
id: {
type: String,
@@ -100,36 +108,54 @@ export default {
type: Array,
required: true,
},
+ tasksToBeDoneOptions: {
+ type: Array,
+ required: true,
+ },
+ projects: {
+ type: Array,
+ required: true,
+ },
},
data() {
return {
visible: true,
- modalId: 'invite-members-modal',
+ modalId: uniqueId('invite-members-modal-'),
selectedAccessLevel: this.defaultAccessLevel,
inviteeType: 'members',
newUsersToInvite: [],
selectedDate: undefined,
selectedAreasOfFocus: [],
+ selectedTasksToBeDone: [],
+ selectedTaskProject: this.projects[0],
groupToBeSharedWith: {},
source: 'unknown',
invalidFeedbackMessage: '',
isLoading: false,
+ mode: 'default',
};
},
computed: {
+ isCelebration() {
+ return this.mode === 'celebrate';
+ },
validationState() {
return this.invalidFeedbackMessage === '' ? null : false;
},
isInviteGroup() {
return this.inviteeType === 'group';
},
+ modalTitle() {
+ return this.$options.labels[this.inviteeType].modal[this.mode].title;
+ },
introText() {
- const inviteTo = this.isProject ? 'toProject' : 'toGroup';
-
- return sprintf(this.$options.labels[this.inviteeType][inviteTo].introText, {
+ return sprintf(this.$options.labels[this.inviteeType][this.inviteTo][this.mode].introText, {
name: this.name,
});
},
+ inviteTo() {
+ return this.isProject ? 'toProject' : 'toGroup';
+ },
toastOptions() {
return {
onComplete: () => {
@@ -156,7 +182,7 @@ export default {
);
},
areasOfFocusEnabled() {
- return this.areasOfFocusOptions.length !== 0;
+ return !this.tasksToBeDoneEnabled && this.areasOfFocusOptions.length !== 0;
},
areasOfFocusForPost() {
if (this.selectedAreasOfFocus.length === 0 && this.areasOfFocusEnabled) {
@@ -172,12 +198,40 @@ export default {
return this.$options.labels[this.inviteeType].placeHolder;
},
+ tasksToBeDoneEnabled() {
+ return (
+ getParameterValues('open_modal')[0] === 'invite_members_for_task' &&
+ this.tasksToBeDoneOptions.length
+ );
+ },
+ showTasksToBeDone() {
+ return (
+ this.tasksToBeDoneEnabled &&
+ this.selectedAccessLevel >= INVITE_MEMBERS_FOR_TASK.minimum_access_level
+ );
+ },
+ showTaskProjects() {
+ return !this.isProject && this.selectedTasksToBeDone.length;
+ },
+ tasksToBeDoneForPost() {
+ return this.showTasksToBeDone ? this.selectedTasksToBeDone : [];
+ },
+ tasksProjectForPost() {
+ return this.showTasksToBeDone && this.selectedTasksToBeDone.length
+ ? this.selectedTaskProject.id
+ : '';
+ },
},
mounted() {
eventHub.$on('openModal', (options) => {
this.openModal(options);
this.trackEvent(MEMBER_AREAS_OF_FOCUS.name, MEMBER_AREAS_OF_FOCUS.view);
});
+
+ if (this.tasksToBeDoneEnabled) {
+ this.openModal({ inviteeType: 'members', source: 'in_product_marketing_email' });
+ this.trackEvent(INVITE_MEMBERS_FOR_TASK.name, INVITE_MEMBERS_FOR_TASK.view);
+ }
},
methods: {
partitionNewUsersToInvite() {
@@ -191,7 +245,8 @@ export default {
usersToAddById.map((user) => user.id).join(','),
];
},
- openModal({ inviteeType, source }) {
+ openModal({ mode = 'default', inviteeType, source }) {
+ this.mode = mode;
this.inviteeType = inviteeType;
this.source = source;
@@ -219,6 +274,12 @@ export default {
this.trackEvent(MEMBER_AREAS_OF_FOCUS.name, MEMBER_AREAS_OF_FOCUS.submit);
},
+ trackinviteMembersForTask() {
+ const label = 'selected_tasks_to_be_done';
+ const property = this.selectedTasksToBeDone.join(',');
+ const tracking = new ExperimentTracking(INVITE_MEMBERS_FOR_TASK.name, { label, property });
+ tracking.event(INVITE_MEMBERS_FOR_TASK.submit);
+ },
resetFields() {
this.isLoading = false;
this.selectedAccessLevel = this.defaultAccessLevel;
@@ -227,10 +288,15 @@ export default {
this.groupToBeSharedWith = {};
this.invalidFeedbackMessage = '';
this.selectedAreasOfFocus = [];
+ this.selectedTasksToBeDone = [];
+ [this.selectedTaskProject] = this.projects;
},
changeSelectedItem(item) {
this.selectedAccessLevel = item;
},
+ changeSelectedTaskProject(project) {
+ this.selectedTaskProject = project;
+ },
submitShareWithGroup() {
const apiShareWithGroup = this.isProject
? Api.projectShareWithGroup.bind(Api)
@@ -263,6 +329,7 @@ export default {
promises.push(apiAddByUserId(this.id, this.addByUserIdPostData(usersToAddById)));
}
this.trackInvite();
+ this.trackinviteMembersForTask();
Promise.all(promises)
.then(this.conditionallyShowToastSuccess)
@@ -275,6 +342,8 @@ export default {
access_level: this.selectedAccessLevel,
invite_source: this.source,
areas_of_focus: this.areasOfFocusForPost,
+ tasks_to_be_done: this.tasksToBeDoneForPost,
+ tasks_project_id: this.tasksProjectForPost,
};
},
addByUserIdPostData(usersToAddById) {
@@ -284,6 +353,8 @@ export default {
access_level: this.selectedAccessLevel,
invite_source: this.source,
areas_of_focus: this.areasOfFocusForPost,
+ tasks_to_be_done: this.tasksToBeDoneForPost,
+ tasks_project_id: this.tasksProjectForPost,
};
},
shareWithGroupPostData(groupToBeSharedWith) {
@@ -322,49 +393,7 @@ export default {
return unescape(sanitize(message, { ALLOWED_TAGS: [] }));
},
},
- labels: {
- members: {
- modalTitle: s__('InviteMembersModal|Invite members'),
- searchField: s__('InviteMembersModal|GitLab member or email address'),
- placeHolder: s__('InviteMembersModal|Select members or type email addresses'),
- toGroup: {
- introText: s__(
- "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group.",
- ),
- },
- toProject: {
- introText: s__(
- "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project.",
- ),
- },
- },
- group: {
- modalTitle: s__('InviteMembersModal|Invite a group'),
- searchField: s__('InviteMembersModal|Select a group to invite'),
- placeHolder: s__('InviteMembersModal|Search for a group to invite'),
- toGroup: {
- introText: s__(
- "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group.",
- ),
- },
- toProject: {
- introText: s__(
- "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project.",
- ),
- },
- },
- accessLevel: s__('InviteMembersModal|Select a role'),
- accessExpireDate: s__('InviteMembersModal|Access expiration date (optional)'),
- toastMessageSuccessful: s__('InviteMembersModal|Members were successfully added'),
- invalidFeedbackMessageDefault: s__('InviteMembersModal|Something went wrong'),
- readMoreText: s__(`InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions`),
- inviteButtonText: s__('InviteMembersModal|Invite'),
- cancelButtonText: s__('InviteMembersModal|Cancel'),
- headerCloseLabel: s__('InviteMembersModal|Close invite team members'),
- areasOfFocusLabel: s__(
- 'InviteMembersModal|What would you like new member(s) to focus on? (optional)',
- ),
- },
+ labels: MODAL_LABELS,
membersTokenSelectLabelId: 'invite-members-input',
};
</script>
@@ -374,20 +403,29 @@ export default {
:modal-id="modalId"
size="sm"
data-qa-selector="invite_members_modal_content"
- :title="$options.labels[inviteeType].modalTitle"
+ data-testid="invite-members-modal"
+ :title="modalTitle"
:header-close-label="$options.labels.headerCloseLabel"
@hidden="resetFields"
@close="resetFields"
@hide="resetFields"
>
<div>
- <p ref="introText">
- <gl-sprintf :message="introText">
- <template #strong="{ content }">
- <strong>{{ content }}</strong>
- </template>
- </gl-sprintf>
- </p>
+ <div class="gl-display-flex">
+ <div v-if="isCelebration" class="gl-p-4 gl-font-size-h1"><gl-emoji data-name="tada" /></div>
+ <div>
+ <p ref="introText">
+ <gl-sprintf :message="introText">
+ <template #strong="{ content }">
+ <strong>{{ content }}</strong>
+ </template>
+ </gl-sprintf>
+ <br />
+ <span v-if="isCelebration">{{ $options.labels.members.modal.celebrate.intro }} </span>
+ <modal-confetti v-if="isCelebration" />
+ </p>
+ </div>
+ </div>
<gl-form-group
:invalid-feedback="invalidFeedbackMessage"
@@ -476,24 +514,70 @@ export default {
data-testid="area-of-focus-checks"
/>
</div>
+ <div v-if="showTasksToBeDone" data-testid="invite-members-modal-tasks-to-be-done">
+ <label class="gl-mt-5">
+ {{ $options.labels.members.tasksToBeDone.title }}
+ </label>
+ <template v-if="projects.length">
+ <gl-form-checkbox-group
+ v-model="selectedTasksToBeDone"
+ :options="tasksToBeDoneOptions"
+ data-testid="invite-members-modal-tasks"
+ />
+ <template v-if="showTaskProjects">
+ <label class="gl-mt-5 gl-display-block">
+ {{ $options.labels.members.tasksProject.title }}
+ </label>
+ <gl-dropdown
+ class="gl-w-half gl-xs-w-full"
+ :text="selectedTaskProject.title"
+ data-testid="invite-members-modal-project-select"
+ >
+ <template v-for="project in projects">
+ <gl-dropdown-item
+ :key="project.id"
+ active-class="is-active"
+ is-check-item
+ :is-checked="project.id === selectedTaskProject.id"
+ @click="changeSelectedTaskProject(project)"
+ >
+ {{ project.title }}
+ </gl-dropdown-item>
+ </template>
+ </gl-dropdown>
+ </template>
+ </template>
+ <gl-alert
+ v-else-if="tasksToBeDoneEnabled"
+ variant="tip"
+ :dismissible="false"
+ data-testid="invite-members-modal-no-projects-alert"
+ >
+ <gl-sprintf :message="$options.labels.members.tasksToBeDone.noProjects">
+ <template #link="{ content }">
+ <gl-link :href="newProjectPath" target="_blank" class="gl-label-link">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+ </div>
</div>
<template #modal-footer>
- <div class="gl-display-flex gl-flex-direction-row gl-justify-content-end gl-flex-wrap gl-m-0">
- <gl-button data-testid="cancel-button" @click="closeModal">
- {{ $options.labels.cancelButtonText }}
- </gl-button>
- <div class="gl-mr-3"></div>
- <gl-button
- :disabled="inviteDisabled"
- :loading="isLoading"
- variant="success"
- data-qa-selector="invite_button"
- data-testid="invite-button"
- @click="sendInvite"
- >{{ $options.labels.inviteButtonText }}</gl-button
- >
- </div>
+ <gl-button data-testid="cancel-button" @click="closeModal">
+ {{ $options.labels.cancelButtonText }}
+ </gl-button>
+ <gl-button
+ :disabled="inviteDisabled"
+ :loading="isLoading"
+ variant="success"
+ data-qa-selector="invite_button"
+ data-testid="invite-button"
+ @click="sendInvite"
+ >
+ {{ $options.labels.inviteButtonText }}
+ </gl-button>
</template>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
index 05be427742c..bf3250f63a5 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
@@ -1,11 +1,12 @@
<script>
-import { GlButton, GlLink } from '@gitlab/ui';
+import { GlButton, GlLink, GlIcon } from '@gitlab/ui';
import ExperimentTracking from '~/experimentation/experiment_tracking';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
+import { TRIGGER_ELEMENT_BUTTON, TRIGGER_ELEMENT_SIDE_NAV } from '../constants';
export default {
- components: { GlButton, GlLink },
+ components: { GlButton, GlLink, GlIcon },
props: {
displayText: {
type: String,
@@ -53,13 +54,11 @@ export default {
},
},
computed: {
- isButton() {
- return this.triggerElement === 'button';
- },
componentAttributes() {
const baseAttributes = {
class: this.classes,
'data-qa-selector': 'invite_members_button',
+ 'data-test-id': 'invite-members-button',
};
if (this.event && this.label) {
@@ -77,6 +76,9 @@ export default {
this.trackExperimentOnShow();
},
methods: {
+ checkTrigger(targetTriggerElement) {
+ return this.triggerElement === targetTriggerElement;
+ },
openModal() {
eventHub.$emit('openModal', { inviteeType: 'members', source: this.triggerSource });
},
@@ -87,12 +89,14 @@ export default {
}
},
},
+ TRIGGER_ELEMENT_BUTTON,
+ TRIGGER_ELEMENT_SIDE_NAV,
};
</script>
<template>
<gl-button
- v-if="isButton"
+ v-if="checkTrigger($options.TRIGGER_ELEMENT_BUTTON)"
v-bind="componentAttributes"
:variant="variant"
:icon="icon"
@@ -100,6 +104,17 @@ export default {
>
{{ displayText }}
</gl-button>
+ <gl-link
+ v-else-if="checkTrigger($options.TRIGGER_ELEMENT_SIDE_NAV)"
+ v-bind="componentAttributes"
+ data-is-link="true"
+ @click="openModal"
+ >
+ <span class="nav-icon-container">
+ <gl-icon :name="icon" />
+ </span>
+ <span class="nav-item-name"> {{ displayText }} </span>
+ </gl-link>
<gl-link v-else v-bind="componentAttributes" data-is-link="true" @click="openModal">
{{ displayText }}
</gl-link>
diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js
index d7daf83e26b..59d4c2f3077 100644
--- a/app/assets/javascripts/invite_members/constants.js
+++ b/app/assets/javascripts/invite_members/constants.js
@@ -1,4 +1,4 @@
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
export const SEARCH_DELAY = 200;
@@ -8,6 +8,12 @@ export const MEMBER_AREAS_OF_FOCUS = {
view: 'view',
submit: 'submit',
};
+export const INVITE_MEMBERS_FOR_TASK = {
+ minimum_access_level: 30,
+ name: 'invite_members_for_task',
+ view: 'modal_opened_from_email',
+ submit: 'submit',
+};
export const GROUP_FILTERS = {
ALL: 'all',
@@ -19,3 +25,122 @@ export const API_MESSAGES = {
};
export const USERS_FILTER_ALL = 'all';
export const USERS_FILTER_SAML_PROVIDER_ID = 'saml_provider_id';
+export const TRIGGER_ELEMENT_BUTTON = 'button';
+export const TRIGGER_ELEMENT_SIDE_NAV = 'side-nav';
+export const MEMBERS_MODAL_DEFAULT_TITLE = s__('InviteMembersModal|Invite members');
+export const MEMBERS_MODAL_CELEBRATE_TITLE = s__(
+ 'InviteMembersModal|GitLab is better with colleagues!',
+);
+export const MEMBERS_MODAL_CELEBRATE_INTRO = s__(
+ 'InviteMembersModal|How about inviting a colleague or two to join you?',
+);
+export const MEMBERS_TO_GROUP_DEFAULT_INTRO_TEXT = s__(
+ "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group.",
+);
+
+export const MEMBERS_TO_PROJECT_DEFAULT_INTRO_TEXT = s__(
+ "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project.",
+);
+export const MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT = s__(
+ "InviteMembersModal|Congratulations on creating your project, you're almost there!",
+);
+export const MEMBERS_SEARCH_FIELD = s__('InviteMembersModal|GitLab member or email address');
+export const MEMBERS_PLACEHOLDER = s__('InviteMembersModal|Select members or type email addresses');
+export const MEMBERS_TASKS_TO_BE_DONE_TITLE = s__(
+ 'InviteMembersModal|Create issues for your new team member to work on (optional)',
+);
+export const MEMBERS_TASKS_TO_BE_DONE_NO_PROJECTS = s__(
+ 'InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}',
+);
+export const MEMBERS_TASKS_PROJECTS_TITLE = s__(
+ 'InviteMembersModal|Choose a project for the issues',
+);
+
+export const GROUP_MODAL_DEFAULT_TITLE = s__('InviteMembersModal|Invite a group');
+export const GROUP_MODAL_TO_GROUP_DEFAULT_INTRO_TEXT = s__(
+ "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group.",
+);
+export const GROUP_MODAL_TO_PROJECT_DEFAULT_INTRO_TEXT = s__(
+ "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project.",
+);
+
+export const GROUP_SEARCH_FIELD = s__('InviteMembersModal|Select a group to invite');
+export const GROUP_PLACEHOLDER = s__('InviteMembersModal|Search for a group to invite');
+
+export const ACCESS_LEVEL = s__('InviteMembersModal|Select a role');
+export const ACCESS_EXPIRE_DATE = s__('InviteMembersModal|Access expiration date (optional)');
+export const TOAST_MESSAGE_SUCCESSFUL = s__('InviteMembersModal|Members were successfully added');
+export const INVALID_FEEDBACK_MESSAGE_DEFAULT = s__('InviteMembersModal|Something went wrong');
+export const READ_MORE_TEXT = s__(
+ `InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions`,
+);
+export const INVITE_BUTTON_TEXT = s__('InviteMembersModal|Invite');
+export const CANCEL_BUTTON_TEXT = s__('InviteMembersModal|Cancel');
+export const HEADER_CLOSE_LABEL = s__('InviteMembersModal|Close invite team members');
+export const AREAS_OF_FOCUS_LABEL = s__(
+ 'InviteMembersModal|What would you like new member(s) to focus on? (optional)',
+);
+
+export const MODAL_LABELS = {
+ members: {
+ modal: {
+ default: {
+ title: MEMBERS_MODAL_DEFAULT_TITLE,
+ },
+ celebrate: {
+ title: MEMBERS_MODAL_CELEBRATE_TITLE,
+ intro: MEMBERS_MODAL_CELEBRATE_INTRO,
+ },
+ },
+ toGroup: {
+ default: {
+ introText: MEMBERS_TO_GROUP_DEFAULT_INTRO_TEXT,
+ },
+ },
+ toProject: {
+ default: {
+ introText: MEMBERS_TO_PROJECT_DEFAULT_INTRO_TEXT,
+ },
+ celebrate: {
+ introText: MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT,
+ },
+ },
+ searchField: MEMBERS_SEARCH_FIELD,
+ placeHolder: MEMBERS_PLACEHOLDER,
+ tasksToBeDone: {
+ title: MEMBERS_TASKS_TO_BE_DONE_TITLE,
+ noProjects: MEMBERS_TASKS_TO_BE_DONE_NO_PROJECTS,
+ },
+ tasksProject: {
+ title: MEMBERS_TASKS_PROJECTS_TITLE,
+ },
+ },
+ group: {
+ modal: {
+ default: {
+ title: GROUP_MODAL_DEFAULT_TITLE,
+ },
+ },
+ toGroup: {
+ default: {
+ introText: GROUP_MODAL_TO_GROUP_DEFAULT_INTRO_TEXT,
+ },
+ },
+ toProject: {
+ default: {
+ introText: GROUP_MODAL_TO_PROJECT_DEFAULT_INTRO_TEXT,
+ },
+ },
+ searchField: GROUP_SEARCH_FIELD,
+ placeHolder: GROUP_PLACEHOLDER,
+ },
+ accessLevel: ACCESS_LEVEL,
+ accessExpireDate: ACCESS_EXPIRE_DATE,
+ toastMessageSuccessful: TOAST_MESSAGE_SUCCESSFUL,
+ invalidFeedbackMessageDefault: INVALID_FEEDBACK_MESSAGE_DEFAULT,
+ readMoreText: READ_MORE_TEXT,
+ inviteButtonText: INVITE_BUTTON_TEXT,
+ cancelButtonText: CANCEL_BUTTON_TEXT,
+ headerCloseLabel: HEADER_CLOSE_LABEL,
+ areasOfFocusLabel: AREAS_OF_FOCUS_LABEL,
+};
diff --git a/app/assets/javascripts/invite_members/init_invite_members_modal.js b/app/assets/javascripts/invite_members/init_invite_members_modal.js
index c1dfaa25dc7..fc657a064dd 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_modal.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_modal.js
@@ -5,15 +5,32 @@ import { parseBoolean } from '~/lib/utils/common_utils';
Vue.use(GlToast);
+let initedInviteMembersModal;
+
export default function initInviteMembersModal() {
+ if (initedInviteMembersModal) {
+ // if we already loaded this in another part of the dom, we don't want to do it again
+ // else we will stack the modals
+ return false;
+ }
+
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/344955
+ // bug lying in wait here for someone to put group and project invite in same screen
+ // once that happens we'll need to mount these differently, perhaps split
+ // group/project to each mount one, with many ways to open it.
const el = document.querySelector('.js-invite-members-modal');
if (!el) {
return false;
}
+ initedInviteMembersModal = true;
+
return new Vue({
el,
+ provide: {
+ newProjectPath: el.dataset.newProjectPath,
+ },
render: (createElement) =>
createElement(InviteMembersModal, {
props: {
@@ -24,6 +41,8 @@ export default function initInviteMembersModal() {
groupSelectFilter: el.dataset.groupsFilter,
groupSelectParentId: parseInt(el.dataset.parentId, 10),
areasOfFocusOptions: JSON.parse(el.dataset.areasOfFocusOptions),
+ tasksToBeDoneOptions: JSON.parse(el.dataset.tasksToBeDoneOptions || '[]'),
+ projects: JSON.parse(el.dataset.projects || '[]'),
noSelectionAreasOfFocus: JSON.parse(el.dataset.noSelectionAreasOfFocus),
usersFilter: el.dataset.usersFilter,
filterId: parseInt(el.dataset.filterId, 10),
diff --git a/app/assets/javascripts/issuable/components/issuable_by_email.vue b/app/assets/javascripts/issuable/components/issuable_by_email.vue
index 6e300831e00..799d2bdc9e2 100644
--- a/app/assets/javascripts/issuable/components/issuable_by_email.vue
+++ b/app/assets/javascripts/issuable/components/issuable_by_email.vue
@@ -166,7 +166,7 @@ export default {
</gl-sprintf>
</p>
<template #modal-footer>
- <gl-button category="secondary" @click="cancelHandler">{{ s__('Cancel') }}</gl-button>
+ <gl-button category="secondary" @click="cancelHandler">{{ __('Cancel') }}</gl-button>
</template>
</gl-modal>
</div>
diff --git a/app/assets/javascripts/issuable_suggestions/index.js b/app/assets/javascripts/issuable_suggestions/index.js
index 22a99a17741..8f7f317d6b4 100644
--- a/app/assets/javascripts/issuable_suggestions/index.js
+++ b/app/assets/javascripts/issuable_suggestions/index.js
@@ -10,12 +10,7 @@ export default function initIssuableSuggestions() {
const issueTitle = document.getElementById('issue_title');
const { projectPath } = el.dataset;
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- ),
+ defaultClient: createDefaultClient(),
});
return new Vue({
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index 2c9a512acdb..d3b58ed3012 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -4,7 +4,7 @@ import Visibility from 'visibilityjs';
import createFlash from '~/flash';
import Poll from '~/lib/utils/poll';
import { visitUrl } from '~/lib/utils/url_utility';
-import { __, s__, sprintf } from '~/locale';
+import { __, sprintf } from '~/locale';
import {
IssuableStatus,
IssuableStatusText,
@@ -12,6 +12,7 @@ import {
IssueTypePath,
IncidentTypePath,
IncidentType,
+ POLLING_DELAY,
} from '../constants';
import eventHub from '../event_hub';
import getIssueStateQuery from '../queries/get_issue_state.query.graphql';
@@ -249,7 +250,7 @@ export default {
return false;
},
defaultErrorMessage() {
- return sprintf(s__('Error updating %{issuableType}'), { issuableType: this.issuableType });
+ return sprintf(__('Error updating %{issuableType}'), { issuableType: this.issuableType });
},
isClosed() {
return this.issuableStatus === IssuableStatus.Closed;
@@ -282,7 +283,7 @@ export default {
});
if (!Visibility.hidden()) {
- this.poll.makeDelayedRequest(2000);
+ this.poll.makeDelayedRequest(POLLING_DELAY);
}
Visibility.change(() => {
@@ -436,7 +437,7 @@ export default {
})
.catch(() => {
createFlash({
- message: sprintf(s__('Error deleting %{issuableType}'), {
+ message: sprintf(__('Error deleting %{issuableType}'), {
issuableType: this.issuableType,
}),
});
@@ -457,6 +458,22 @@ export default {
this.flashContainer = null;
}
},
+
+ taskListUpdateStarted() {
+ this.poll.stop();
+ },
+
+ taskListUpdateSucceeded() {
+ this.poll.enable();
+ this.poll.makeDelayedRequest(POLLING_DELAY);
+ },
+
+ taskListUpdateFailed() {
+ this.poll.enable();
+ this.poll.makeDelayedRequest(POLLING_DELAY);
+
+ this.updateStoreState();
+ },
},
};
</script>
@@ -552,7 +569,9 @@ export default {
:issuable-type="issuableType"
:update-url="updateEndpoint"
:lock-version="state.lock_version"
- @taskListUpdateFailed="updateStoreState"
+ @taskListUpdateStarted="taskListUpdateStarted"
+ @taskListUpdateSucceeded="taskListUpdateSucceeded"
+ @taskListUpdateFailed="taskListUpdateFailed"
/>
<edited-component
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index 4c6a1478e95..9dc122d426c 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -2,7 +2,7 @@
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import $ from 'jquery';
import createFlash from '~/flash';
-import { s__, sprintf } from '~/locale';
+import { __, sprintf } from '~/locale';
import TaskList from '../../task_list';
import animateMixin from '../mixins/animate';
@@ -86,15 +86,25 @@ export default {
fieldName: 'description',
lockVersion: this.lockVersion,
selector: '.detail-page-description',
+ onUpdate: this.taskListUpdateStarted.bind(this),
+ onSuccess: this.taskListUpdateSuccess.bind(this),
onError: this.taskListUpdateError.bind(this),
});
}
},
+ taskListUpdateStarted() {
+ this.$emit('taskListUpdateStarted');
+ },
+
+ taskListUpdateSuccess() {
+ this.$emit('taskListUpdateSucceeded');
+ },
+
taskListUpdateError() {
createFlash({
message: sprintf(
- s__(
+ __(
'Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again.',
),
{
diff --git a/app/assets/javascripts/issue_show/components/fields/type.vue b/app/assets/javascripts/issue_show/components/fields/type.vue
index 3eac448c637..9110a6924b4 100644
--- a/app/assets/javascripts/issue_show/components/fields/type.vue
+++ b/app/assets/javascripts/issue_show/components/fields/type.vue
@@ -2,7 +2,7 @@
import { GlFormGroup, GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui';
import { capitalize } from 'lodash';
import { __ } from '~/locale';
-import { IssuableTypes } from '../../constants';
+import { IssuableTypes, IncidentType } from '../../constants';
import getIssueStateQuery from '../../queries/get_issue_state.query.graphql';
import updateIssueStateMutation from '../../queries/update_issue_state.mutation.graphql';
@@ -19,6 +19,14 @@ export default {
GlDropdown,
GlDropdownItem,
},
+ inject: {
+ canCreateIncident: {
+ default: false,
+ },
+ issueType: {
+ default: 'issue',
+ },
+ },
data() {
return {
issueState: {},
@@ -36,6 +44,9 @@ export default {
} = this;
return capitalize(issueType);
},
+ shouldShowIncident() {
+ return this.issueType === IncidentType || this.canCreateIncident;
+ },
},
methods: {
updateIssueType(issueType) {
@@ -47,6 +58,9 @@ export default {
},
});
},
+ isShown(type) {
+ return type.value !== IncidentType || this.shouldShowIncident;
+ },
},
};
</script>
@@ -68,6 +82,7 @@ export default {
>
<gl-dropdown-item
v-for="type in $options.IssuableTypes"
+ v-show="isShown(type)"
:key="type.value"
:is-checked="issueState.issueType === type.value"
is-check-item
diff --git a/app/assets/javascripts/issue_show/components/header_actions.vue b/app/assets/javascripts/issue_show/components/header_actions.vue
index 2bddbe4faa0..2c314ce1c3f 100644
--- a/app/assets/javascripts/issue_show/components/header_actions.vue
+++ b/app/assets/javascripts/issue_show/components/header_actions.vue
@@ -192,9 +192,14 @@ export default {
class="gl-sm-display-none! w-100"
block
:text="dropdownText"
+ data-qa-selector="issue_actions_dropdown"
:loading="isToggleStateButtonLoading"
>
- <gl-dropdown-item v-if="showToggleIssueStateButton" @click="toggleIssueState">
+ <gl-dropdown-item
+ v-if="showToggleIssueStateButton"
+ :data-qa-selector="`mobile_${qaSelector}`"
+ @click="toggleIssueState"
+ >
{{ buttonText }}
</gl-dropdown-item>
<gl-dropdown-item v-if="canCreateIssue" :href="newIssuePath">
diff --git a/app/assets/javascripts/issue_show/constants.js b/app/assets/javascripts/issue_show/constants.js
index 64d39a79821..ef9699deb42 100644
--- a/app/assets/javascripts/issue_show/constants.js
+++ b/app/assets/javascripts/issue_show/constants.js
@@ -37,3 +37,10 @@ export const IncidentTypePath = 'issues/incident';
export const IncidentType = 'incident';
export const issueState = { issueType: undefined, isDirty: false };
+
+export const POLLING_DELAY = 2000;
+
+export const WorkspaceType = {
+ project: 'project',
+ group: 'group',
+};
diff --git a/app/assets/javascripts/issue_show/incident.js b/app/assets/javascripts/issue_show/incident.js
index df986195656..3aff2d9c54a 100644
--- a/app/assets/javascripts/issue_show/incident.js
+++ b/app/assets/javascripts/issue_show/incident.js
@@ -2,25 +2,31 @@ import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import issuableApp from './components/app.vue';
import incidentTabs from './components/incidents/incident_tabs.vue';
-import { issueState } from './constants';
+import { issueState, IncidentType } from './constants';
import apolloProvider from './graphql';
import getIssueStateQuery from './queries/get_issue_state.query.graphql';
+import HeaderActions from './components/header_actions.vue';
-export default function initIssuableApp(issuableData = {}) {
+const bootstrapApollo = (state = {}) => {
+ return apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: getIssueStateQuery,
+ data: {
+ issueState: state,
+ },
+ });
+};
+
+export function initIncidentApp(issuableData = {}) {
const el = document.getElementById('js-issuable-app');
if (!el) {
return undefined;
}
- apolloProvider.clients.defaultClient.cache.writeQuery({
- query: getIssueStateQuery,
- data: {
- issueState: { ...issueState, issueType: el.dataset.issueType },
- },
- });
+ bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
const {
+ canCreateIncident,
canUpdate,
iid,
projectNamespace,
@@ -39,6 +45,8 @@ export default function initIssuableApp(issuableData = {}) {
issuableApp,
},
provide: {
+ issueType: IncidentType,
+ canCreateIncident,
canUpdate,
fullPath,
iid,
@@ -57,3 +65,35 @@ export default function initIssuableApp(issuableData = {}) {
},
});
}
+
+export function initIncidentHeaderActions(store) {
+ const el = document.querySelector('.js-issue-header-actions');
+
+ if (!el) {
+ return undefined;
+ }
+
+ bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
+
+ return new Vue({
+ el,
+ apolloProvider,
+ store,
+ provide: {
+ canCreateIssue: parseBoolean(el.dataset.canCreateIncident),
+ canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic),
+ canReopenIssue: parseBoolean(el.dataset.canReopenIssue),
+ canReportSpam: parseBoolean(el.dataset.canReportSpam),
+ canUpdateIssue: parseBoolean(el.dataset.canUpdateIssue),
+ iid: el.dataset.iid,
+ isIssueAuthor: parseBoolean(el.dataset.isIssueAuthor),
+ issueType: el.dataset.issueType,
+ newIssuePath: el.dataset.newIssuePath,
+ projectPath: el.dataset.projectPath,
+ projectId: el.dataset.projectId,
+ reportAbusePath: el.dataset.reportAbusePath,
+ submitAsSpamPath: el.dataset.submitAsSpamPath,
+ },
+ render: (createElement) => createElement(HeaderActions),
+ });
+}
diff --git a/app/assets/javascripts/issue_show/issue.js b/app/assets/javascripts/issue_show/issue.js
index 4374dba6eb7..25cc51478ff 100644
--- a/app/assets/javascripts/issue_show/issue.js
+++ b/app/assets/javascripts/issue_show/issue.js
@@ -25,17 +25,22 @@ export function initIssuableApp(issuableData, store) {
bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
+ const { canCreateIncident, ...issuableProps } = issuableData;
+
return new Vue({
el,
apolloProvider,
store,
+ provide: {
+ canCreateIncident,
+ },
computed: {
...mapGetters(['getNoteableData']),
},
render(createElement) {
return createElement(IssuableApp, {
props: {
- ...issuableData,
+ ...issuableProps,
isConfidential: this.getNoteableData?.confidential,
isLocked: this.getNoteableData?.discussion_locked,
issuableStatus: this.getNoteableData?.state,
diff --git a/app/assets/javascripts/issues_list/components/issues_list_app.vue b/app/assets/javascripts/issues_list/components/issues_list_app.vue
index 7b51f6ee46a..7f2082e5b90 100644
--- a/app/assets/javascripts/issues_list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues_list/components/issues_list_app.vue
@@ -36,6 +36,7 @@ import {
TOKEN_TYPE_LABEL,
TOKEN_TYPE_MILESTONE,
TOKEN_TYPE_MY_REACTION,
+ TOKEN_TYPE_RELEASE,
TOKEN_TYPE_TYPE,
TOKEN_TYPE_WEIGHT,
UPDATED_DESC,
@@ -65,6 +66,7 @@ import {
TOKEN_TITLE_LABEL,
TOKEN_TITLE_MILESTONE,
TOKEN_TITLE_MY_REACTION,
+ TOKEN_TITLE_RELEASE,
TOKEN_TITLE_TYPE,
TOKEN_TITLE_WEIGHT,
} from '~/vue_shared/components/filtered_search_bar/constants';
@@ -88,6 +90,8 @@ const LabelToken = () =>
import('~/vue_shared/components/filtered_search_bar/tokens/label_token.vue');
const MilestoneToken = () =>
import('~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue');
+const ReleaseToken = () =>
+ import('~/vue_shared/components/filtered_search_bar/tokens/release_token.vue');
const WeightToken = () =>
import('~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue');
@@ -165,6 +169,9 @@ export default {
newIssuePath: {
default: '',
},
+ releasesPath: {
+ default: '',
+ },
rssPath: {
default: '',
},
@@ -288,6 +295,7 @@ export default {
avatar_url: gon.current_user_avatar_url,
});
}
+
const tokens = [
{
type: TOKEN_TYPE_AUTHOR,
@@ -297,7 +305,6 @@ export default {
dataType: 'user',
unique: true,
defaultAuthors: [],
- operators: OPERATOR_IS_ONLY,
fetchAuthors: this.fetchUsers,
preloadedAuthors,
},
@@ -317,7 +324,6 @@ export default {
title: TOKEN_TITLE_MILESTONE,
icon: 'clock',
token: MilestoneToken,
- unique: true,
fetchMilestones: this.fetchMilestones,
},
{
@@ -333,7 +339,6 @@ export default {
title: TOKEN_TITLE_TYPE,
icon: 'issues',
token: GlFilteredSearchToken,
- operators: OPERATOR_IS_ONLY,
options: [
{ icon: 'issue-type-issue', title: 'issue', value: 'issue' },
{ icon: 'issue-type-incident', title: 'incident', value: 'incident' },
@@ -342,6 +347,16 @@ export default {
},
];
+ if (this.isProject) {
+ tokens.push({
+ type: TOKEN_TYPE_RELEASE,
+ title: TOKEN_TITLE_RELEASE,
+ icon: 'rocket',
+ token: ReleaseToken,
+ fetchReleases: this.fetchReleases,
+ });
+ }
+
if (this.isSignedIn) {
tokens.push({
type: TOKEN_TYPE_MY_REACTION,
@@ -349,7 +364,6 @@ export default {
icon: 'thumb-up',
token: EmojiToken,
unique: true,
- operators: OPERATOR_IS_ONLY,
fetchEmojis: this.fetchEmojis,
});
@@ -373,7 +387,6 @@ export default {
title: TOKEN_TITLE_ITERATION,
icon: 'iteration',
token: IterationToken,
- unique: true,
fetchIterations: this.fetchIterations,
});
}
@@ -459,6 +472,9 @@ export default {
fetchEmojis(search) {
return this.fetchWithCache(this.autocompleteAwardEmojisPath, 'emojis', 'name', search);
},
+ fetchReleases(search) {
+ return this.fetchWithCache(this.releasesPath, 'releases', 'tag', search);
+ },
fetchLabels(search) {
return this.$apollo
.query({
diff --git a/app/assets/javascripts/issues_list/components/new_issue_dropdown.vue b/app/assets/javascripts/issues_list/components/new_issue_dropdown.vue
index 037fd9be542..e749579af80 100644
--- a/app/assets/javascripts/issues_list/components/new_issue_dropdown.vue
+++ b/app/assets/javascripts/issues_list/components/new_issue_dropdown.vue
@@ -71,8 +71,11 @@ export default {
hasSelectedProject() {
return this.selectedProject.id;
},
+ projectsWithIssuesEnabled() {
+ return this.projects.filter((project) => project.issuesEnabled);
+ },
showNoSearchResultsText() {
- return !this.projects.length && this.search;
+ return !this.projectsWithIssuesEnabled.length && this.search;
},
},
methods: {
@@ -110,7 +113,7 @@ export default {
<gl-loading-icon v-if="$apollo.queries.projects.loading" />
<template v-else>
<gl-dropdown-item
- v-for="project of projects"
+ v-for="project of projectsWithIssuesEnabled"
:key="project.id"
@click="selectProject(project)"
>
diff --git a/app/assets/javascripts/issues_list/constants.js b/app/assets/javascripts/issues_list/constants.js
index 5bdc1bd9f90..da9b96d0e22 100644
--- a/app/assets/javascripts/issues_list/constants.js
+++ b/app/assets/javascripts/issues_list/constants.js
@@ -166,6 +166,7 @@ const LABEL_PRIORITY_ASC_SORT = 'label_priority_asc';
const POPULARITY_ASC_SORT = 'popularity_asc';
const WEIGHT_DESC_SORT = 'weight_desc';
const BLOCKING_ISSUES_DESC_SORT = 'blocking_issues_desc';
+const TITLE_ASC_SORT = 'title_asc';
const TITLE_DESC_SORT = 'title_desc';
export const urlSortParams = {
@@ -187,7 +188,7 @@ export const urlSortParams = {
[WEIGHT_ASC]: WEIGHT,
[WEIGHT_DESC]: WEIGHT_DESC_SORT,
[BLOCKING_ISSUES_DESC]: BLOCKING_ISSUES_DESC_SORT,
- [TITLE_ASC]: TITLE,
+ [TITLE_ASC]: TITLE_ASC_SORT,
[TITLE_DESC]: TITLE_DESC_SORT,
};
@@ -211,6 +212,7 @@ export const TOKEN_TYPE_ASSIGNEE = 'assignee_username';
export const TOKEN_TYPE_MILESTONE = 'milestone';
export const TOKEN_TYPE_LABEL = 'labels';
export const TOKEN_TYPE_TYPE = 'type';
+export const TOKEN_TYPE_RELEASE = 'release';
export const TOKEN_TYPE_MY_REACTION = 'my_reaction_emoji';
export const TOKEN_TYPE_CONFIDENTIAL = 'confidential';
export const TOKEN_TYPE_ITERATION = 'iteration';
@@ -271,6 +273,7 @@ export const filters = {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'label_name[]',
[SPECIAL_FILTER]: 'label_name[]',
+ [ALTERNATIVE_FILTER]: 'label_name',
},
[OPERATOR_IS_NOT]: {
[NORMAL_FILTER]: 'not[label_name][]',
@@ -280,12 +283,28 @@ export const filters = {
[TOKEN_TYPE_TYPE]: {
[API_PARAM]: {
[NORMAL_FILTER]: 'types',
- [SPECIAL_FILTER]: 'types',
},
[URL_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'type[]',
- [SPECIAL_FILTER]: 'type[]',
+ },
+ [OPERATOR_IS_NOT]: {
+ [NORMAL_FILTER]: 'not[type][]',
+ },
+ },
+ },
+ [TOKEN_TYPE_RELEASE]: {
+ [API_PARAM]: {
+ [NORMAL_FILTER]: 'releaseTag',
+ [SPECIAL_FILTER]: 'releaseTagWildcardId',
+ },
+ [URL_PARAM]: {
+ [OPERATOR_IS]: {
+ [NORMAL_FILTER]: 'release_tag',
+ [SPECIAL_FILTER]: 'release_tag',
+ },
+ [OPERATOR_IS_NOT]: {
+ [NORMAL_FILTER]: 'not[release_tag]',
},
},
},
@@ -299,6 +318,9 @@ export const filters = {
[NORMAL_FILTER]: 'my_reaction_emoji',
[SPECIAL_FILTER]: 'my_reaction_emoji',
},
+ [OPERATOR_IS_NOT]: {
+ [NORMAL_FILTER]: 'not[my_reaction_emoji]',
+ },
},
},
[TOKEN_TYPE_CONFIDENTIAL]: {
diff --git a/app/assets/javascripts/issues_list/index.js b/app/assets/javascripts/issues_list/index.js
index 47af20f5271..59034964afb 100644
--- a/app/assets/javascripts/issues_list/index.js
+++ b/app/assets/javascripts/issues_list/index.js
@@ -24,7 +24,7 @@ export function mountJiraIssuesListApp() {
}
Vue.use(VueApollo);
- const defaultClient = createDefaultClient({}, { assumeImmutableResults: true });
+ const defaultClient = createDefaultClient();
const apolloProvider = new VueApollo({
defaultClient,
});
@@ -103,7 +103,7 @@ export function mountIssuesListApp() {
},
};
- const defaultClient = createDefaultClient(resolvers, { assumeImmutableResults: true });
+ const defaultClient = createDefaultClient(resolvers);
const apolloProvider = new VueApollo({
defaultClient,
});
@@ -137,6 +137,7 @@ export function mountIssuesListApp() {
newIssuePath,
projectImportJiraPath,
quickActionsHelpPath,
+ releasesPath,
resetPath,
rssPath,
showNewIssueLink,
@@ -164,6 +165,7 @@ export function mountIssuesListApp() {
isSignedIn: parseBoolean(isSignedIn),
jiraIntegrationPath,
newIssuePath,
+ releasesPath,
rssPath,
showNewIssueLink: parseBoolean(showNewIssueLink),
signInPath,
diff --git a/app/assets/javascripts/issues_list/queries/get_issues.query.graphql b/app/assets/javascripts/issues_list/queries/get_issues.query.graphql
index 6df72cf6596..9866efbcecc 100644
--- a/app/assets/javascripts/issues_list/queries/get_issues.query.graphql
+++ b/app/assets/javascripts/issues_list/queries/get_issues.query.graphql
@@ -11,9 +11,13 @@ query getIssues(
$assigneeId: String
$assigneeUsernames: [String!]
$authorUsername: String
+ $confidential: Boolean
$labelName: [String]
$milestoneTitle: [String]
$milestoneWildcardId: MilestoneWildcardId
+ $myReactionEmoji: String
+ $releaseTag: [String!]
+ $releaseTagWildcardId: ReleaseTagWildcardId
$types: [IssueType!]
$not: NegatedIssueFilterInput
$beforeCursor: String
@@ -30,9 +34,11 @@ query getIssues(
assigneeId: $assigneeId
assigneeUsernames: $assigneeUsernames
authorUsername: $authorUsername
+ confidential: $confidential
labelName: $labelName
milestoneTitle: $milestoneTitle
milestoneWildcardId: $milestoneWildcardId
+ myReactionEmoji: $myReactionEmoji
types: $types
not: $not
before: $beforeCursor
@@ -57,9 +63,13 @@ query getIssues(
assigneeId: $assigneeId
assigneeUsernames: $assigneeUsernames
authorUsername: $authorUsername
+ confidential: $confidential
labelName: $labelName
milestoneTitle: $milestoneTitle
milestoneWildcardId: $milestoneWildcardId
+ myReactionEmoji: $myReactionEmoji
+ releaseTag: $releaseTag
+ releaseTagWildcardId: $releaseTagWildcardId
types: $types
not: $not
before: $beforeCursor
diff --git a/app/assets/javascripts/issues_list/queries/get_issues_counts.query.graphql b/app/assets/javascripts/issues_list/queries/get_issues_counts.query.graphql
index 7bcdbbb28fc..5e755ec5870 100644
--- a/app/assets/javascripts/issues_list/queries/get_issues_counts.query.graphql
+++ b/app/assets/javascripts/issues_list/queries/get_issues_counts.query.graphql
@@ -5,9 +5,13 @@ query getIssuesCount(
$assigneeId: String
$assigneeUsernames: [String!]
$authorUsername: String
+ $confidential: Boolean
$labelName: [String]
$milestoneTitle: [String]
$milestoneWildcardId: MilestoneWildcardId
+ $myReactionEmoji: String
+ $releaseTag: [String!]
+ $releaseTagWildcardId: ReleaseTagWildcardId
$types: [IssueType!]
$not: NegatedIssueFilterInput
) {
@@ -19,9 +23,11 @@ query getIssuesCount(
assigneeId: $assigneeId
assigneeUsernames: $assigneeUsernames
authorUsername: $authorUsername
+ confidential: $confidential
labelName: $labelName
milestoneTitle: $milestoneTitle
milestoneWildcardId: $milestoneWildcardId
+ myReactionEmoji: $myReactionEmoji
types: $types
not: $not
) {
@@ -34,9 +40,11 @@ query getIssuesCount(
assigneeId: $assigneeId
assigneeUsernames: $assigneeUsernames
authorUsername: $authorUsername
+ confidential: $confidential
labelName: $labelName
milestoneTitle: $milestoneTitle
milestoneWildcardId: $milestoneWildcardId
+ myReactionEmoji: $myReactionEmoji
types: $types
not: $not
) {
@@ -49,9 +57,11 @@ query getIssuesCount(
assigneeId: $assigneeId
assigneeUsernames: $assigneeUsernames
authorUsername: $authorUsername
+ confidential: $confidential
labelName: $labelName
milestoneTitle: $milestoneTitle
milestoneWildcardId: $milestoneWildcardId
+ myReactionEmoji: $myReactionEmoji
types: $types
not: $not
) {
@@ -65,9 +75,13 @@ query getIssuesCount(
assigneeId: $assigneeId
assigneeUsernames: $assigneeUsernames
authorUsername: $authorUsername
+ confidential: $confidential
labelName: $labelName
milestoneTitle: $milestoneTitle
milestoneWildcardId: $milestoneWildcardId
+ myReactionEmoji: $myReactionEmoji
+ releaseTag: $releaseTag
+ releaseTagWildcardId: $releaseTagWildcardId
types: $types
not: $not
) {
@@ -79,9 +93,13 @@ query getIssuesCount(
assigneeId: $assigneeId
assigneeUsernames: $assigneeUsernames
authorUsername: $authorUsername
+ confidential: $confidential
labelName: $labelName
milestoneTitle: $milestoneTitle
milestoneWildcardId: $milestoneWildcardId
+ myReactionEmoji: $myReactionEmoji
+ releaseTag: $releaseTag
+ releaseTagWildcardId: $releaseTagWildcardId
types: $types
not: $not
) {
@@ -93,9 +111,13 @@ query getIssuesCount(
assigneeId: $assigneeId
assigneeUsernames: $assigneeUsernames
authorUsername: $authorUsername
+ confidential: $confidential
labelName: $labelName
milestoneTitle: $milestoneTitle
milestoneWildcardId: $milestoneWildcardId
+ myReactionEmoji: $myReactionEmoji
+ releaseTag: $releaseTag
+ releaseTagWildcardId: $releaseTagWildcardId
types: $types
not: $not
) {
diff --git a/app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql b/app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql
index 8f9b888d19b..8c95e6114d3 100644
--- a/app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql
+++ b/app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql
@@ -1,4 +1,4 @@
-query($fullPath: ID!) {
+query getIssuesListDetails($fullPath: ID!) {
project(fullPath: $fullPath) {
issues {
nodes {
diff --git a/app/assets/javascripts/issues_list/queries/iteration.fragment.graphql b/app/assets/javascripts/issues_list/queries/iteration.fragment.graphql
index 78a368089a8..4f7217be7f7 100644
--- a/app/assets/javascripts/issues_list/queries/iteration.fragment.graphql
+++ b/app/assets/javascripts/issues_list/queries/iteration.fragment.graphql
@@ -1,4 +1,10 @@
fragment Iteration on Iteration {
id
title
+ startDate
+ dueDate
+ iterationCadence {
+ id
+ title
+ }
}
diff --git a/app/assets/javascripts/issues_list/queries/search_projects.query.graphql b/app/assets/javascripts/issues_list/queries/search_projects.query.graphql
index df1f330139a..75463f643a2 100644
--- a/app/assets/javascripts/issues_list/queries/search_projects.query.graphql
+++ b/app/assets/javascripts/issues_list/queries/search_projects.query.graphql
@@ -3,6 +3,7 @@ query searchProjects($fullPath: ID!, $search: String) {
projects(search: $search, includeSubgroups: true) {
nodes {
id
+ issuesEnabled
name
nameWithNamespace
webUrl
diff --git a/app/assets/javascripts/issues_list/service_desk_helper.js b/app/assets/javascripts/issues_list/service_desk_helper.js
index f96567ef53b..815f338f1a0 100644
--- a/app/assets/javascripts/issues_list/service_desk_helper.js
+++ b/app/assets/javascripts/issues_list/service_desk_helper.js
@@ -1,4 +1,4 @@
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
/**
* Generates empty state messages for Service Desk issues list.
@@ -20,12 +20,12 @@ export function generateMessages(emptyStateMeta) {
);
const serviceDeskSupportedMessage = s__(
- 'ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation.',
+ 'ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation.',
);
const commonDescription = `
<span>${serviceDeskSupportedMessage}</span>
- <a href="${serviceDeskHelpPage}">${s__('Learn more.')}</a>`;
+ <a href="${serviceDeskHelpPage}">${__('Learn more.')}</a>`;
return {
serviceDeskEnabledAndCanEditProjectSettings: {
@@ -60,7 +60,7 @@ export function generateMessages(emptyStateMeta) {
'ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email.',
),
primaryLink: incomingEmailHelpPage,
- primaryText: s__('Learn more.'),
+ primaryText: __('Learn more.'),
},
serviceDeskIsNotEnabled: {
title: s__('ServiceDesk|Service Desk is not enabled'),
diff --git a/app/assets/javascripts/issues_list/utils.js b/app/assets/javascripts/issues_list/utils.js
index 1d3d07475af..0e57e2bff83 100644
--- a/app/assets/javascripts/issues_list/utils.js
+++ b/app/assets/javascripts/issues_list/utils.js
@@ -21,9 +21,13 @@ import {
RELATIVE_POSITION_ASC,
SPECIAL_FILTER,
SPECIAL_FILTER_VALUES,
+ TITLE_ASC,
+ TITLE_DESC,
TOKEN_TYPE_ASSIGNEE,
+ TOKEN_TYPE_CONFIDENTIAL,
TOKEN_TYPE_ITERATION,
TOKEN_TYPE_MILESTONE,
+ TOKEN_TYPE_RELEASE,
TOKEN_TYPE_TYPE,
UPDATED_ASC,
UPDATED_DESC,
@@ -113,11 +117,19 @@ export const getSortOptions = (hasIssueWeightsFeature, hasBlockedIssuesFeature)
descending: RELATIVE_POSITION_ASC,
},
},
+ {
+ id: 9,
+ title: __('Title'),
+ sortDirection: {
+ ascending: TITLE_ASC,
+ descending: TITLE_DESC,
+ },
+ },
];
if (hasIssueWeightsFeature) {
sortOptions.push({
- id: 9,
+ id: sortOptions.length + 1,
title: __('Weight'),
sortDirection: {
ascending: WEIGHT_ASC,
@@ -128,7 +140,7 @@ export const getSortOptions = (hasIssueWeightsFeature, hasBlockedIssuesFeature)
if (hasBlockedIssuesFeature) {
sortOptions.push({
- id: 10,
+ id: sortOptions.length + 1,
title: __('Blocking'),
sortDirection: {
ascending: BLOCKING_ISSUES_DESC,
@@ -193,17 +205,23 @@ const getFilterType = (data, tokenType = '') =>
? SPECIAL_FILTER
: NORMAL_FILTER;
+const wildcardTokens = [TOKEN_TYPE_ITERATION, TOKEN_TYPE_MILESTONE, TOKEN_TYPE_RELEASE];
+
const isWildcardValue = (tokenType, value) =>
- (tokenType === TOKEN_TYPE_ITERATION || tokenType === TOKEN_TYPE_MILESTONE) &&
- SPECIAL_FILTER_VALUES.includes(value);
+ wildcardTokens.includes(tokenType) && SPECIAL_FILTER_VALUES.includes(value);
const requiresUpperCaseValue = (tokenType, value) =>
tokenType === TOKEN_TYPE_TYPE || isWildcardValue(tokenType, value);
-const formatData = (token) =>
- requiresUpperCaseValue(token.type, token.value.data)
- ? token.value.data.toUpperCase()
- : token.value.data;
+const formatData = (token) => {
+ if (requiresUpperCaseValue(token.type, token.value.data)) {
+ return token.value.data.toUpperCase();
+ }
+ if (token.type === TOKEN_TYPE_CONFIDENTIAL) {
+ return token.value.data === 'yes';
+ }
+ return token.value.data;
+};
export const convertToApiParams = (filterTokens) => {
const params = {};
diff --git a/app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql b/app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql
index e768154e210..32fbc1113bc 100644
--- a/app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql
+++ b/app/assets/javascripts/jira_connect/branches/graphql/queries/get_projects.query.graphql
@@ -1,6 +1,6 @@
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
-query getProjects(
+query jiraGetProjects(
$search: String!
$after: String = ""
$first: Int!
diff --git a/app/assets/javascripts/jira_connect/branches/index.js b/app/assets/javascripts/jira_connect/branches/index.js
index 95bd4f5c675..04510fcff4b 100644
--- a/app/assets/javascripts/jira_connect/branches/index.js
+++ b/app/assets/javascripts/jira_connect/branches/index.js
@@ -14,12 +14,7 @@ export default async function initJiraConnectBranches() {
const { initialBranchName, successStateSvgPath } = el.dataset;
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- ),
+ defaultClient: createDefaultClient(),
});
return new Vue({
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_button.vue b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_button.vue
new file mode 100644
index 00000000000..0b286bc903f
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_button.vue
@@ -0,0 +1,24 @@
+<script>
+import { GlButton, GlModalDirective } from '@gitlab/ui';
+import { ADD_NAMESPACE_MODAL_ID } from '../constants';
+import AddNamespaceModal from './add_namespace_modal/add_namespace_modal.vue';
+
+export default {
+ components: {
+ GlButton,
+ AddNamespaceModal,
+ },
+ directives: {
+ GlModal: GlModalDirective,
+ },
+ ADD_NAMESPACE_MODAL_ID,
+};
+</script>
+<template>
+ <div>
+ <gl-button v-gl-modal="$options.ADD_NAMESPACE_MODAL_ID" category="primary" variant="info">
+ {{ s__('Integrations|Add namespace') }}
+ </gl-button>
+ <add-namespace-modal />
+ </div>
+</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal.vue b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal.vue
new file mode 100644
index 00000000000..0e209a09b16
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal.vue
@@ -0,0 +1,26 @@
+<script>
+import { GlModal } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+import { ADD_NAMESPACE_MODAL_ID } from '../../constants';
+import GroupsList from './groups_list.vue';
+
+export default {
+ components: { GlModal, GroupsList },
+ modal: {
+ id: ADD_NAMESPACE_MODAL_ID,
+ title: s__('Integrations|Link namespaces'),
+ cancelProps: {
+ text: __('Cancel'),
+ },
+ },
+};
+</script>
+<template>
+ <gl-modal
+ :modal-id="$options.modal.id"
+ :title="$options.modal.title"
+ :action-cancel="$options.modal.cancelProps"
+ >
+ <groups-list />
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/groups_list.vue b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue
index 5a49d7c1a90..5a49d7c1a90 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/components/groups_list.vue
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue
new file mode 100644
index 00000000000..005c3bcd0e3
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue
@@ -0,0 +1,85 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import { addSubscription } from '~/jira_connect/subscriptions/api';
+import { persistAlert, reloadPage } from '~/jira_connect/subscriptions/utils';
+import { s__ } from '~/locale';
+import GroupItemName from '../group_item_name.vue';
+
+export default {
+ components: {
+ GlButton,
+ GroupItemName,
+ },
+ inject: {
+ subscriptionsPath: {
+ default: '',
+ },
+ },
+ props: {
+ group: {
+ type: Object,
+ required: true,
+ },
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ isLoading: false,
+ };
+ },
+ methods: {
+ onClick() {
+ this.isLoading = true;
+
+ addSubscription(this.subscriptionsPath, this.group.full_path)
+ .then(() => {
+ persistAlert({
+ title: s__('Integrations|Namespace successfully linked'),
+ message: s__(
+ 'Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}',
+ ),
+ linkUrl: helpPagePath('integration/jira_development_panel.html', { anchor: 'usage' }),
+ variant: 'success',
+ });
+
+ reloadPage();
+ })
+ .catch((error) => {
+ this.$emit(
+ 'error',
+ error?.response?.data?.error ||
+ s__('Integrations|Failed to link namespace. Please try again.'),
+ );
+ this.isLoading = false;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <li class="gl-border-b-1 gl-border-b-solid gl-border-b-gray-100">
+ <div class="gl-display-flex gl-align-items-center gl-py-3">
+ <div class="gl-min-w-0 gl-display-flex gl-flex-grow-1 gl-flex-shrink-1 gl-align-items-center">
+ <div class="gl-min-w-0 gl-flex-grow-1 flex-shrink-1">
+ <group-item-name :group="group" />
+ </div>
+
+ <gl-button
+ category="secondary"
+ variant="confirm"
+ :loading="isLoading"
+ :disabled="disabled"
+ @click.prevent="onClick"
+ >
+ {{ __('Link') }}
+ </gl-button>
+ </div>
+ </div>
+ </li>
+</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/app.vue b/app/assets/javascripts/jira_connect/subscriptions/components/app.vue
index 413424be28d..c0504cbb645 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/components/app.vue
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/app.vue
@@ -1,65 +1,51 @@
<script>
-import { GlAlert, GlButton, GlLink, GlModal, GlModalDirective, GlSprintf } from '@gitlab/ui';
+import { GlAlert, GlLink, GlSprintf, GlEmptyState } from '@gitlab/ui';
+import { isEmpty } from 'lodash';
import { mapState, mapMutations } from 'vuex';
-import { retrieveAlert, getLocation } from '~/jira_connect/subscriptions/utils';
-import { __ } from '~/locale';
+import { retrieveAlert } from '~/jira_connect/subscriptions/utils';
import { SET_ALERT } from '../store/mutation_types';
-import GroupsList from './groups_list.vue';
import SubscriptionsList from './subscriptions_list.vue';
+import AddNamespaceButton from './add_namespace_button.vue';
+import SignInButton from './sign_in_button.vue';
export default {
name: 'JiraConnectApp',
components: {
GlAlert,
- GlButton,
GlLink,
- GlModal,
GlSprintf,
- GroupsList,
+ GlEmptyState,
SubscriptionsList,
- },
- directives: {
- GlModalDirective,
+ AddNamespaceButton,
+ SignInButton,
},
inject: {
usersPath: {
default: '',
},
- },
- data() {
- return {
- location: '',
- };
+ subscriptions: {
+ default: [],
+ },
},
computed: {
...mapState(['alert']),
- usersPathWithReturnTo() {
- if (this.location) {
- return `${this.usersPath}?return_to=${this.location}`;
- }
-
- return this.usersPath;
- },
shouldShowAlert() {
return Boolean(this.alert?.message);
},
- },
- modal: {
- cancelProps: {
- text: __('Cancel'),
+ hasSubscriptions() {
+ return !isEmpty(this.subscriptions);
+ },
+ userSignedIn() {
+ return Boolean(!this.usersPath);
},
},
created() {
this.setInitialAlert();
- this.setLocation();
},
methods: {
...mapMutations({
setAlert: SET_ALERT,
}),
- async setLocation() {
- this.location = await getLocation();
- },
setInitialAlert() {
const { linkUrl, title, message, variant } = retrieveAlert() || {};
this.setAlert({ linkUrl, title, message, variant });
@@ -88,38 +74,44 @@ export default {
</template>
</gl-alert>
- <h2 class="gl-text-center">{{ s__('JiraService|GitLab for Jira Configuration') }}</h2>
+ <h2 class="gl-text-center gl-mb-7">{{ s__('JiraService|GitLab for Jira Configuration') }}</h2>
+ <div class="jira-connect-app-body gl-mx-auto gl-px-5 gl-mb-7">
+ <template v-if="hasSubscriptions">
+ <div class="gl-display-flex gl-justify-content-end">
+ <sign-in-button v-if="!userSignedIn" :users-path="usersPath" />
+ <add-namespace-button v-else />
+ </div>
- <div class="jira-connect-app-body gl-my-7 gl-px-5 gl-pb-4">
- <div class="gl-display-flex gl-justify-content-end">
- <gl-button
- v-if="usersPath"
- category="primary"
- variant="info"
- class="gl-align-self-center"
- :href="usersPathWithReturnTo"
- target="_blank"
- >{{ s__('Integrations|Sign in to add namespaces') }}</gl-button
+ <subscriptions-list />
+ </template>
+ <template v-else>
+ <div v-if="!userSignedIn" class="gl-text-center">
+ <p class="gl-mb-7">{{ s__('JiraService|Sign in to GitLab.com to get started.') }}</p>
+ <sign-in-button class="gl-mb-7" :users-path="usersPath">
+ {{ __('Sign in to GitLab') }}
+ </sign-in-button>
+ <p>
+ {{
+ s__(
+ 'Integrations|Note: this integration only works with accounts on GitLab.com (SaaS).',
+ )
+ }}
+ </p>
+ </div>
+ <gl-empty-state
+ v-else
+ :title="s__('Integrations|No linked namespaces')"
+ :description="
+ s__(
+ 'Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance.',
+ )
+ "
>
- <template v-else>
- <gl-button
- v-gl-modal-directive="'add-namespace-modal'"
- category="primary"
- variant="info"
- class="gl-align-self-center"
- >{{ s__('Integrations|Add namespace') }}</gl-button
- >
- <gl-modal
- modal-id="add-namespace-modal"
- :title="s__('Integrations|Link namespaces')"
- :action-cancel="$options.modal.cancelProps"
- >
- <groups-list />
- </gl-modal>
- </template>
- </div>
-
- <subscriptions-list />
+ <template #actions>
+ <add-namespace-button />
+ </template>
+ </gl-empty-state>
+ </template>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/groups_list_item.vue b/app/assets/javascripts/jira_connect/subscriptions/components/groups_list_item.vue
deleted file mode 100644
index ed7585e8a88..00000000000
--- a/app/assets/javascripts/jira_connect/subscriptions/components/groups_list_item.vue
+++ /dev/null
@@ -1,85 +0,0 @@
-<script>
-import { GlButton } from '@gitlab/ui';
-import { helpPagePath } from '~/helpers/help_page_helper';
-import { addSubscription } from '~/jira_connect/subscriptions/api';
-import { persistAlert, reloadPage } from '~/jira_connect/subscriptions/utils';
-import { s__ } from '~/locale';
-import GroupItemName from './group_item_name.vue';
-
-export default {
- components: {
- GlButton,
- GroupItemName,
- },
- inject: {
- subscriptionsPath: {
- default: '',
- },
- },
- props: {
- group: {
- type: Object,
- required: true,
- },
- disabled: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- data() {
- return {
- isLoading: false,
- };
- },
- methods: {
- onClick() {
- this.isLoading = true;
-
- addSubscription(this.subscriptionsPath, this.group.full_path)
- .then(() => {
- persistAlert({
- title: s__('Integrations|Namespace successfully linked'),
- message: s__(
- 'Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}',
- ),
- linkUrl: helpPagePath('integration/jira_development_panel.html', { anchor: 'usage' }),
- variant: 'success',
- });
-
- reloadPage();
- })
- .catch((error) => {
- this.$emit(
- 'error',
- error?.response?.data?.error ||
- s__('Integrations|Failed to link namespace. Please try again.'),
- );
- this.isLoading = false;
- });
- },
- },
-};
-</script>
-
-<template>
- <li class="gl-border-b-1 gl-border-b-solid gl-border-b-gray-100">
- <div class="gl-display-flex gl-align-items-center gl-py-3">
- <div class="gl-min-w-0 gl-display-flex gl-flex-grow-1 gl-flex-shrink-1 gl-align-items-center">
- <div class="gl-min-w-0 gl-flex-grow-1 flex-shrink-1">
- <group-item-name :group="group" />
- </div>
-
- <gl-button
- category="secondary"
- variant="confirm"
- :loading="isLoading"
- :disabled="disabled"
- @click.prevent="onClick"
- >
- {{ __('Link') }}
- </gl-button>
- </div>
- </div>
- </li>
-</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue b/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue
new file mode 100644
index 00000000000..dc0a77e99c2
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue
@@ -0,0 +1,36 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils';
+
+export default {
+ components: {
+ GlButton,
+ },
+ props: {
+ usersPath: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ signInURL: '',
+ };
+ },
+ created() {
+ this.setSignInURL();
+ },
+ methods: {
+ async setSignInURL() {
+ this.signInURL = await getGitlabSignInURL(this.usersPath);
+ },
+ },
+};
+</script>
+<template>
+ <gl-button category="primary" variant="info" :href="signInURL" target="_blank">
+ <slot>
+ {{ s__('Integrations|Sign in to add namespaces') }}
+ </slot>
+ </gl-button>
+</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/subscriptions_list.vue b/app/assets/javascripts/jira_connect/subscriptions/components/subscriptions_list.vue
index 7062fb370ed..33126040c16 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/components/subscriptions_list.vue
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/subscriptions_list.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
+import { GlButton, GlTable } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { mapMutations } from 'vuex';
import { removeSubscription } from '~/jira_connect/subscriptions/api';
@@ -12,7 +12,6 @@ import GroupItemName from './group_item_name.vue';
export default {
components: {
GlButton,
- GlEmptyState,
GlTable,
GroupItemName,
TimeagoTooltip,
@@ -44,17 +43,15 @@ export default {
},
],
i18n: {
- emptyTitle: s__('Integrations|No linked namespaces'),
- emptyDescription: s__(
- 'Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance.',
- ),
unlinkError: s__('Integrations|Failed to unlink namespace. Please try again.'),
},
methods: {
...mapMutations({
setAlert: SET_ALERT,
}),
- isEmpty,
+ isUnlinkButtonDisabled(item) {
+ return !isEmpty(item);
+ },
isLoadingItem(item) {
return this.loadingItem === item;
},
@@ -81,29 +78,22 @@ export default {
</script>
<template>
- <div>
- <gl-empty-state
- v-if="isEmpty(subscriptions)"
- :title="$options.i18n.emptyTitle"
- :description="$options.i18n.emptyDescription"
- />
- <gl-table v-else :items="subscriptions" :fields="$options.fields">
- <template #cell(name)="{ item }">
- <group-item-name :group="item.group" />
- </template>
- <template #cell(created_at)="{ item }">
- <timeago-tooltip :time="item.created_at" />
- </template>
- <template #cell(actions)="{ item }">
- <gl-button
- :class="unlinkBtnClass(item)"
- category="secondary"
- :loading="isLoadingItem(item)"
- :disabled="!isEmpty(loadingItem)"
- @click.prevent="onClick(item)"
- >{{ __('Unlink') }}</gl-button
- >
- </template>
- </gl-table>
- </div>
+ <gl-table :items="subscriptions" :fields="$options.fields">
+ <template #cell(name)="{ item }">
+ <group-item-name :group="item.group" />
+ </template>
+ <template #cell(created_at)="{ item }">
+ <timeago-tooltip :time="item.created_at" />
+ </template>
+ <template #cell(actions)="{ item }">
+ <gl-button
+ :class="unlinkBtnClass(item)"
+ category="secondary"
+ :loading="isLoadingItem(item)"
+ :disabled="isUnlinkButtonDisabled(loadingItem)"
+ @click.prevent="onClick(item)"
+ >{{ __('Unlink') }}</gl-button
+ >
+ </template>
+ </gl-table>
</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/constants.js b/app/assets/javascripts/jira_connect/subscriptions/constants.js
index 8dff83eabb5..2a65b7bc1fa 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/constants.js
+++ b/app/assets/javascripts/jira_connect/subscriptions/constants.js
@@ -1,3 +1,5 @@
export const DEFAULT_GROUPS_PER_PAGE = 10;
export const ALERT_LOCALSTORAGE_KEY = 'gitlab_alert';
export const MINIMUM_SEARCH_TERM_LENGTH = 3;
+
+export const ADD_NAMESPACE_MODAL_ID = 'add-namespace-modal';
diff --git a/app/assets/javascripts/jira_connect/subscriptions/index.js b/app/assets/javascripts/jira_connect/subscriptions/index.js
index f1262be0174..8a7a80d885d 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/index.js
+++ b/app/assets/javascripts/jira_connect/subscriptions/index.js
@@ -7,16 +7,20 @@ import Translate from '~/vue_shared/translate';
import JiraConnectApp from './components/app.vue';
import createStore from './store';
-import { getLocation, sizeToParent } from './utils';
+import { getGitlabSignInURL, sizeToParent } from './utils';
const store = createStore();
+/**
+ * Add `return_to` query param to all HAML-defined GitLab sign in links.
+ */
const updateSignInLinks = async () => {
- const location = await getLocation();
- Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => {
- const updatedLink = `${el.getAttribute('href')}?return_to=${location}`;
- el.setAttribute('href', updatedLink);
- });
+ await Promise.all(
+ Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).map(async (el) => {
+ const updatedLink = await getGitlabSignInURL(el.getAttribute('href'));
+ el.setAttribute('href', updatedLink);
+ }),
+ );
};
export async function initJiraConnect() {
diff --git a/app/assets/javascripts/jira_connect/subscriptions/utils.js b/app/assets/javascripts/jira_connect/subscriptions/utils.js
index ed7a9484a81..b2d03a1fbba 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/utils.js
+++ b/app/assets/javascripts/jira_connect/subscriptions/utils.js
@@ -1,4 +1,5 @@
import AccessorUtilities from '~/lib/utils/accessor';
+import { objectToQuery } from '~/lib/utils/url_utility';
import { ALERT_LOCALSTORAGE_KEY } from './constants';
const isFunction = (fn) => typeof fn === 'function';
@@ -71,3 +72,17 @@ export const sizeToParent = () => {
AP.sizeToParent();
}
};
+
+export const getGitlabSignInURL = async (signInURL) => {
+ const location = await getLocation();
+
+ if (location) {
+ const queryParams = {
+ return_to: location,
+ };
+
+ return `${signInURL}?${objectToQuery(queryParams)}`;
+ }
+
+ return signInURL;
+};
diff --git a/app/assets/javascripts/jira_import/index.js b/app/assets/javascripts/jira_import/index.js
index 003f3c7107e..695a237bf50 100644
--- a/app/assets/javascripts/jira_import/index.js
+++ b/app/assets/javascripts/jira_import/index.js
@@ -6,7 +6,7 @@ import App from './components/jira_import_app.vue';
Vue.use(VueApollo);
-const defaultClient = createDefaultClient({}, { assumeImmutableResults: true });
+const defaultClient = createDefaultClient();
const apolloProvider = new VueApollo({
defaultClient,
diff --git a/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql b/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql
index 2aacc5cf668..6fec07cc6f8 100644
--- a/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql
+++ b/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql
@@ -1,6 +1,6 @@
#import "./jira_import.fragment.graphql"
-query($fullPath: ID!) {
+query getJiraImportDetails($fullPath: ID!) {
project(fullPath: $fullPath) {
jiraImportStatus
jiraImports {
diff --git a/app/assets/javascripts/jira_import/queries/get_jira_user_mapping.mutation.graphql b/app/assets/javascripts/jira_import/queries/get_jira_user_mapping.mutation.graphql
index cca33af342c..7af30ffb869 100644
--- a/app/assets/javascripts/jira_import/queries/get_jira_user_mapping.mutation.graphql
+++ b/app/assets/javascripts/jira_import/queries/get_jira_user_mapping.mutation.graphql
@@ -1,4 +1,4 @@
-mutation($input: JiraImportUsersInput!) {
+mutation getJiraUserMapping($input: JiraImportUsersInput!) {
jiraImportUsers(input: $input) {
jiraUsers {
jiraAccountId
diff --git a/app/assets/javascripts/jira_import/queries/initiate_jira_import.mutation.graphql b/app/assets/javascripts/jira_import/queries/initiate_jira_import.mutation.graphql
index 807374bf06c..29f8428fbcf 100644
--- a/app/assets/javascripts/jira_import/queries/initiate_jira_import.mutation.graphql
+++ b/app/assets/javascripts/jira_import/queries/initiate_jira_import.mutation.graphql
@@ -1,6 +1,6 @@
#import "./jira_import.fragment.graphql"
-mutation($input: JiraImportStartInput!) {
+mutation initiateJiraImport($input: JiraImportStartInput!) {
jiraImportStart(input: $input) {
jiraImport {
...JiraImport
diff --git a/app/assets/javascripts/jira_import/queries/search_project_members.query.graphql b/app/assets/javascripts/jira_import/queries/search_project_members.query.graphql
index 06f119e75ed..6ea8963e6a6 100644
--- a/app/assets/javascripts/jira_import/queries/search_project_members.query.graphql
+++ b/app/assets/javascripts/jira_import/queries/search_project_members.query.graphql
@@ -1,4 +1,4 @@
-query searchProjectMembers($fullPath: ID!, $search: String) {
+query jiraSearchProjectMembers($fullPath: ID!, $search: String) {
project(fullPath: $fullPath) {
projectMembers(search: $search) {
nodes {
diff --git a/app/assets/javascripts/jobs/components/manual_variables_form.vue b/app/assets/javascripts/jobs/components/manual_variables_form.vue
index 269551ff9aa..7a52a1b0d6b 100644
--- a/app/assets/javascripts/jobs/components/manual_variables_form.vue
+++ b/app/assets/javascripts/jobs/components/manual_variables_form.vue
@@ -1,5 +1,12 @@
<script>
-import { GlButton, GlLink, GlSprintf } from '@gitlab/ui';
+import {
+ GlFormInputGroup,
+ GlInputGroupText,
+ GlFormInput,
+ GlButton,
+ GlLink,
+ GlSprintf,
+} from '@gitlab/ui';
import { uniqueId } from 'lodash';
import { mapActions } from 'vuex';
import { helpPagePath } from '~/helpers/help_page_helper';
@@ -8,6 +15,9 @@ import { s__ } from '~/locale';
export default {
name: 'ManualVariablesForm',
components: {
+ GlFormInputGroup,
+ GlInputGroupText,
+ GlFormInput,
GlButton,
GlLink,
GlSprintf,
@@ -32,6 +42,9 @@ export default {
value: 'value',
},
i18n: {
+ header: s__('CiVariables|Variables'),
+ keyLabel: s__('CiVariables|Key'),
+ valueLabel: s__('CiVariables|Value'),
keyPlaceholder: s__('CiVariables|Input variable key'),
valuePlaceholder: s__('CiVariables|Input variable value'),
formHelpText: s__(
@@ -40,9 +53,13 @@ export default {
},
data() {
return {
- variables: [],
- key: '',
- secretValue: '',
+ variables: [
+ {
+ key: '',
+ secretValue: '',
+ id: uniqueId(),
+ },
+ ],
triggerBtnDisabled: false,
};
},
@@ -50,40 +67,32 @@ export default {
variableSettings() {
return helpPagePath('ci/variables/index', { anchor: 'add-a-cicd-variable-to-a-project' });
},
- },
- watch: {
- key(newVal) {
- this.handleValueChange(newVal, this.$options.inputTypes.key);
- },
- secretValue(newVal) {
- this.handleValueChange(newVal, this.$options.inputTypes.value);
+ preparedVariables() {
+ // we need to ensure no empty variables are passed to the API
+ // and secretValue should be snake_case when passed to the API
+ return this.variables
+ .filter((variable) => variable.key !== '')
+ .map(({ key, secretValue }) => ({ key, secret_value: secretValue }));
},
},
methods: {
...mapActions(['triggerManualJob']),
- handleValueChange(newValue, type) {
- if (newValue !== '') {
- this.createNewVariable(type);
- this.resetForm();
- }
+ canRemove(index) {
+ return index < this.variables.length - 1;
},
- createNewVariable(type) {
- const newVariable = {
- key: this.key,
- secret_value: this.secretValue,
- id: uniqueId(),
- };
+ addEmptyVariable() {
+ const lastVar = this.variables[this.variables.length - 1];
- this.variables.push(newVariable);
+ if (lastVar.key === '') {
+ return;
+ }
- return this.$nextTick().then(() => {
- this.$refs[`${this.$options.inputTypes[type]}-${newVariable.id}`][0].focus();
+ this.variables.push({
+ key: '',
+ secret_value: '',
+ id: uniqueId(),
});
},
- resetForm() {
- this.key = '';
- this.secretValue = '';
- },
deleteVariable(id) {
this.variables.splice(
this.variables.findIndex((el) => el.id === id),
@@ -93,112 +102,92 @@ export default {
trigger() {
this.triggerBtnDisabled = true;
- this.triggerManualJob(this.variables);
+ this.triggerManualJob(this.preparedVariables);
},
},
};
</script>
<template>
- <div class="col-12" data-testid="manual-vars-form">
- <label>{{ s__('CiVariables|Variables') }}</label>
-
- <div class="ci-table">
- <div class="gl-responsive-table-row table-row-header pb-0 pt-0 border-0" role="row">
- <div class="table-section section-50" role="rowheader">{{ s__('CiVariables|Key') }}</div>
- <div class="table-section section-50" role="rowheader">{{ s__('CiVariables|Value') }}</div>
- </div>
+ <div class="row gl-justify-content-center">
+ <div class="col-10" data-testid="manual-vars-form">
+ <label>{{ $options.i18n.header }}</label>
<div
- v-for="variable in variables"
+ v-for="(variable, index) in variables"
:key="variable.id"
- class="gl-responsive-table-row"
+ class="gl-display-flex gl-align-items-center gl-mb-4"
data-testid="ci-variable-row"
>
- <div class="table-section section-50">
- <div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Key') }}</div>
- <div class="table-mobile-content gl-mr-3">
- <input
- :ref="`${$options.inputTypes.key}-${variable.id}`"
- v-model="variable.key"
- :placeholder="$options.i18n.keyPlaceholder"
- class="ci-variable-body-item form-control"
- data-testid="ci-variable-key"
- />
- </div>
- </div>
+ <gl-form-input-group class="gl-mr-4 gl-flex-grow-1">
+ <template #prepend>
+ <gl-input-group-text>
+ {{ $options.i18n.keyLabel }}
+ </gl-input-group-text>
+ </template>
+ <gl-form-input
+ :ref="`${$options.inputTypes.key}-${variable.id}`"
+ v-model="variable.key"
+ :placeholder="$options.i18n.keyPlaceholder"
+ data-testid="ci-variable-key"
+ @change="addEmptyVariable"
+ />
+ </gl-form-input-group>
- <div class="table-section section-50">
- <div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Value') }}</div>
- <div class="table-mobile-content gl-mr-3">
- <input
- :ref="`${$options.inputTypes.value}-${variable.id}`"
- v-model="variable.secret_value"
- :placeholder="$options.i18n.valuePlaceholder"
- class="ci-variable-body-item form-control"
- data-testid="ci-variable-value"
- />
- </div>
- </div>
+ <gl-form-input-group class="gl-flex-grow-2">
+ <template #prepend>
+ <gl-input-group-text>
+ {{ $options.i18n.valueLabel }}
+ </gl-input-group-text>
+ </template>
+ <gl-form-input
+ :ref="`${$options.inputTypes.value}-${variable.id}`"
+ v-model="variable.secretValue"
+ :placeholder="$options.i18n.valuePlaceholder"
+ data-testid="ci-variable-value"
+ />
+ </gl-form-input-group>
- <div class="table-section section-10">
- <div class="table-mobile-header" role="rowheader"></div>
- <div class="table-mobile-content justify-content-end">
- <gl-button
- category="tertiary"
- icon="clear"
- :aria-label="__('Delete variable')"
- data-testid="delete-variable-btn"
- @click="deleteVariable(variable.id)"
- />
- </div>
- </div>
+ <!-- delete variable button placeholder to not break flex layout -->
+ <div
+ v-if="!canRemove(index)"
+ class="gl-w-7 gl-mr-3"
+ data-testid="delete-variable-btn-placeholder"
+ ></div>
+
+ <gl-button
+ v-if="canRemove(index)"
+ class="gl-flex-grow-0 gl-flex-basis-0"
+ category="tertiary"
+ variant="danger"
+ icon="clear"
+ :aria-label="__('Delete variable')"
+ data-testid="delete-variable-btn"
+ @click="deleteVariable(variable.id)"
+ />
</div>
- <div class="gl-responsive-table-row">
- <div class="table-section section-50">
- <div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Key') }}</div>
- <div class="table-mobile-content gl-mr-3">
- <input
- ref="inputKey"
- v-model="key"
- class="js-input-key form-control"
- :placeholder="$options.i18n.keyPlaceholder"
- />
- </div>
- </div>
- <div class="table-section section-50">
- <div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Value') }}</div>
- <div class="table-mobile-content gl-mr-3">
- <input
- ref="inputSecretValue"
- v-model="secretValue"
- class="ci-variable-body-item form-control"
- :placeholder="$options.i18n.valuePlaceholder"
- />
- </div>
- </div>
+ <div class="gl-text-center gl-mt-5">
+ <gl-sprintf :message="$options.i18n.formHelpText">
+ <template #link="{ content }">
+ <gl-link :href="variableSettings" target="_blank">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </div>
+ <div class="gl-display-flex gl-justify-content-center gl-mt-5">
+ <gl-button
+ class="gl-mt-5"
+ variant="info"
+ category="primary"
+ :aria-label="__('Trigger manual job')"
+ :disabled="triggerBtnDisabled"
+ data-testid="trigger-manual-job-btn"
+ @click="trigger"
+ >
+ {{ action.button_title }}
+ </gl-button>
</div>
- </div>
- <div class="gl-text-center gl-mt-3">
- <gl-sprintf :message="$options.i18n.formHelpText">
- <template #link="{ content }">
- <gl-link :href="variableSettings" target="_blank">
- {{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
- </div>
- <div class="d-flex justify-content-center">
- <gl-button
- variant="info"
- category="primary"
- :aria-label="__('Trigger manual job')"
- :disabled="triggerBtnDisabled"
- data-testid="trigger-manual-job-btn"
- @click="trigger"
- >
- {{ action.button_title }}
- </gl-button>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/trigger_block.vue b/app/assets/javascripts/jobs/components/trigger_block.vue
index fef5b37015c..b1ddede8fe8 100644
--- a/app/assets/javascripts/jobs/components/trigger_block.vue
+++ b/app/assets/javascripts/jobs/components/trigger_block.vue
@@ -84,9 +84,13 @@ export default {
>
</p>
- <gl-table :items="trigger.variables" :fields="$options.fields" small bordered>
+ <gl-table :items="trigger.variables" :fields="$options.fields" small bordered fixed>
+ <template #cell(key)="{ item }">
+ <span class="gl-overflow-break-word">{{ item.key }}</span>
+ </template>
+
<template #cell(value)="data">
- {{ getDisplayValue(data.value) }}
+ <span class="gl-overflow-break-word">{{ getDisplayValue(data.value) }}</span>
</template>
</gl-table>
</template>
diff --git a/app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js b/app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js
index ad92bd4de42..9b7901685b6 100644
--- a/app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js
+++ b/app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js
@@ -9,10 +9,6 @@ import { isNavigatingAway } from '~/lib/utils/is_navigating_away';
* @returns {ApolloLink|null}
*/
export const getSuppressNetworkErrorsDuringNavigationLink = () => {
- if (!gon.features?.suppressApolloErrorsDuringNavigation) {
- return null;
- }
-
return onError(({ networkError }) => {
if (networkError && isNavigatingAway()) {
// Return an observable that will never notify any subscribers with any
diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js
index 39bf804b54e..df2e85afe24 100644
--- a/app/assets/javascripts/lib/graphql.js
+++ b/app/assets/javascripts/lib/graphql.js
@@ -48,7 +48,6 @@ export const stripWhitespaceFromQuery = (url, path) => {
export default (resolvers = {}, config = {}) => {
const {
- assumeImmutableResults,
baseUrl,
batchMax = 10,
cacheConfig,
@@ -161,10 +160,10 @@ export default (resolvers = {}, config = {}) => {
link: appLink,
cache: new InMemoryCache({
...cacheConfig,
- freezeResults: assumeImmutableResults,
+ freezeResults: true,
}),
resolvers,
- assumeImmutableResults,
+ assumeImmutableResults: true,
defaultOptions: {
query: {
fetchPolicy,
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 813fd3dbb1e..a82dad7e2c9 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -220,16 +220,16 @@ export const scrollToElement = (element, options = {}) => {
// In the previous implementation, jQuery naturally deferred this scrolling.
// Unfortunately, we're quite coupled to this implementation detail now.
defer(() => {
- const { duration = 200, offset = 0 } = options;
+ const { duration = 200, offset = 0, behavior = duration ? 'smooth' : 'auto' } = options;
const y = el.getBoundingClientRect().top + window.pageYOffset + offset - contentTop();
- window.scrollTo({ top: y, behavior: duration ? 'smooth' : 'auto' });
+ window.scrollTo({ top: y, behavior });
});
}
};
-export const scrollToElementWithContext = (element) => {
+export const scrollToElementWithContext = (element, options) => {
const offsetMultiplier = -0.1;
- return scrollToElement(element, { offset: window.innerHeight * offsetMultiplier });
+ return scrollToElement(element, { ...options, offset: window.innerHeight * offsetMultiplier });
};
/**
@@ -688,17 +688,20 @@ export const searchBy = (query = '', searchSpace = {}) => {
*/
export const isScopedLabel = ({ title = '' } = {}) => title.includes(SCOPED_LABEL_DELIMITER);
+const scopedLabelRegex = new RegExp(`(.*)${SCOPED_LABEL_DELIMITER}.*`);
+
/**
- * Returns the base value of the scoped label
- *
- * Expected Label to be an Object with `title` as a key:
- * { title: 'LabelTitle', ...otherProperties };
+ * Returns the key of a scoped label.
+ * For example:
+ * - returns `scoped` if the label is `scoped::value`.
+ * - returns `scoped::label` if the label is `scoped::label::value`.
*
- * @param {Object} label
- * @returns String
+ * @param {Object} label object containing `title` property
+ * @returns String scoped label key, or full label if it is not a scoped label
*/
-export const scopedLabelKey = ({ title = '' }) =>
- isScopedLabel({ title }) && title.split(SCOPED_LABEL_DELIMITER)[0];
+export const scopedLabelKey = ({ title = '' }) => {
+ return title.replace(scopedLabelRegex, '$1');
+};
// Methods to set and get Cookie
export const setCookie = (name, value) => Cookies.set(name, value, { expires: 365 });
diff --git a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue
new file mode 100644
index 00000000000..733d0f69f5d
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue
@@ -0,0 +1,47 @@
+<script>
+import { GlModal } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ cancelAction: { text: __('Cancel') },
+ components: {
+ GlModal,
+ },
+ props: {
+ primaryText: {
+ type: String,
+ required: false,
+ default: __('OK'),
+ },
+ primaryVariant: {
+ type: String,
+ required: false,
+ default: 'confirm',
+ },
+ },
+ computed: {
+ primaryAction() {
+ return { text: this.primaryText, attributes: { variant: this.primaryVariant } };
+ },
+ },
+ mounted() {
+ this.$refs.modal.show();
+ },
+};
+</script>
+
+<template>
+ <gl-modal
+ ref="modal"
+ size="sm"
+ modal-id="confirmationModal"
+ body-class="gl-display-flex"
+ :action-primary="primaryAction"
+ :action-cancel="$options.cancelAction"
+ hide-header
+ @primary="$emit('confirmed')"
+ @hidden="$emit('closed')"
+ >
+ <div class="gl-align-self-center"><slot></slot></div>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js
new file mode 100644
index 00000000000..fdd0e045d07
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js
@@ -0,0 +1,55 @@
+import Vue from 'vue';
+
+export function confirmAction(message, { primaryBtnVariant, primaryBtnText } = {}) {
+ return new Promise((resolve) => {
+ let confirmed = false;
+
+ const component = new Vue({
+ components: {
+ ConfirmModal: () => import('./confirm_modal.vue'),
+ },
+ render(h) {
+ return h(
+ 'confirm-modal',
+ {
+ props: {
+ primaryVariant: primaryBtnVariant,
+ primaryText: primaryBtnText,
+ },
+ on: {
+ confirmed() {
+ confirmed = true;
+ },
+ closed() {
+ component.$destroy();
+ resolve(confirmed);
+ },
+ },
+ },
+ [message],
+ );
+ },
+ }).$mount();
+ });
+}
+
+export function confirmViaGlModal(message, element) {
+ const primaryBtnConfig = {};
+
+ const confirmBtnVariant = element.getAttribute('data-confirm-btn-variant');
+
+ if (confirmBtnVariant) {
+ primaryBtnConfig.primaryBtnVariant = confirmBtnVariant;
+ }
+
+ const screenReaderText =
+ element.querySelector('.gl-sr-only')?.textContent ||
+ element.querySelector('.sr-only')?.textContent ||
+ element.getAttribute('aria-label');
+
+ if (screenReaderText) {
+ primaryBtnConfig.primaryBtnText = screenReaderText;
+ }
+
+ return confirmAction(message, primaryBtnConfig);
+}
diff --git a/app/assets/javascripts/lib/utils/constants.js b/app/assets/javascripts/lib/utils/constants.js
index 0e5a23a5cbb..36c6545164e 100644
--- a/app/assets/javascripts/lib/utils/constants.js
+++ b/app/assets/javascripts/lib/utils/constants.js
@@ -24,3 +24,5 @@ export const DEFAULT_TH_CLASSES =
// We set the drawer's z-index to 252 to clear flash messages that might
// be displayed in the page and that have a z-index of 251.
export const DRAWER_Z_INDEX = 252;
+
+export const MIN_USERNAME_LENGTH = 2;
diff --git a/app/assets/javascripts/lib/utils/datetime/date_format_utility.js b/app/assets/javascripts/lib/utils/datetime/date_format_utility.js
index 3c446c21865..7bff2bf3e47 100644
--- a/app/assets/javascripts/lib/utils/datetime/date_format_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime/date_format_utility.js
@@ -14,33 +14,33 @@ import { s__, n__, __, sprintf } from '../../../locale';
export const getMonthNames = (abbreviated) => {
if (abbreviated) {
return [
- s__('Jan'),
- s__('Feb'),
- s__('Mar'),
- s__('Apr'),
- s__('May'),
- s__('Jun'),
- s__('Jul'),
- s__('Aug'),
- s__('Sep'),
- s__('Oct'),
- s__('Nov'),
- s__('Dec'),
+ __('Jan'),
+ __('Feb'),
+ __('Mar'),
+ __('Apr'),
+ __('May'),
+ __('Jun'),
+ __('Jul'),
+ __('Aug'),
+ __('Sep'),
+ __('Oct'),
+ __('Nov'),
+ __('Dec'),
];
}
return [
- s__('January'),
- s__('February'),
- s__('March'),
- s__('April'),
- s__('May'),
- s__('June'),
- s__('July'),
- s__('August'),
- s__('September'),
- s__('October'),
- s__('November'),
- s__('December'),
+ __('January'),
+ __('February'),
+ __('March'),
+ __('April'),
+ __('May'),
+ __('June'),
+ __('July'),
+ __('August'),
+ __('September'),
+ __('October'),
+ __('November'),
+ __('December'),
];
};
diff --git a/app/assets/javascripts/lib/utils/file_upload.js b/app/assets/javascripts/lib/utils/file_upload.js
index b8b63bf58d4..f99a4927338 100644
--- a/app/assets/javascripts/lib/utils/file_upload.js
+++ b/app/assets/javascripts/lib/utils/file_upload.js
@@ -15,13 +15,17 @@ export default (buttonSelector, fileSelector) => {
});
};
-export const getFilename = ({ clipboardData }) => {
- let value;
- if (window.clipboardData && window.clipboardData.getData) {
- value = window.clipboardData.getData('Text');
- } else if (clipboardData && clipboardData.getData) {
- value = clipboardData.getData('text/plain');
+export const getFilename = (file) => {
+ let fileName;
+ if (file) {
+ fileName = file.name;
}
- value = value.split('\r');
- return value[0];
+
+ return fileName;
+};
+
+export const validateImageName = (file) => {
+ const fileName = file.name ? file.name : 'image.png';
+ const legalImageRegex = /^[\w.\-+]+\.(png|jpg|jpeg|gif|bmp|tiff|ico|webp)$/;
+ return legalImageRegex.test(fileName) ? fileName : 'image.png';
};
diff --git a/app/assets/javascripts/lib/utils/rails_ujs.js b/app/assets/javascripts/lib/utils/rails_ujs.js
index 8b40cc7bd11..6b1985a23ba 100644
--- a/app/assets/javascripts/lib/utils/rails_ujs.js
+++ b/app/assets/javascripts/lib/utils/rails_ujs.js
@@ -1,4 +1,42 @@
import Rails from '@rails/ujs';
+import { confirmViaGlModal } from './confirm_via_gl_modal/confirm_via_gl_modal';
+
+function monkeyPatchConfirmModal() {
+ /**
+ * This function is used to replace the `Rails.confirm` which uses `window.confirm`
+ *
+ * This function opens a confirmation modal which will resolve in a promise.
+ * Because the `Rails.confirm` API is synchronous, we go with a little hack here:
+ *
+ * 1. User clicks on something with `data-confirm`
+ * 2. We open the modal and return `false`, ending the "Rails" event chain
+ * 3. If the modal is closed and the user "confirmed" the action
+ * 1. replace the `Rails.confirm` with a function that always returns `true`
+ * 2. click the same element programmatically
+ *
+ * @param message {String} Message to be shown in the modal
+ * @param element {HTMLElement} Element that was clicked on
+ * @returns {boolean}
+ */
+ function confirmViaModal(message, element) {
+ confirmViaGlModal(message, element)
+ .then((confirmed) => {
+ if (confirmed) {
+ Rails.confirm = () => true;
+ element.click();
+ Rails.confirm = confirmViaModal;
+ }
+ })
+ .catch(() => {});
+ return false;
+ }
+
+ Rails.confirm = confirmViaModal;
+}
+
+if (gon?.features?.bootstrapConfirmationModals) {
+ monkeyPatchConfirmModal();
+}
export const initRails = () => {
// eslint-disable-next-line no-underscore-dangle
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 0804d792631..40dd29bea76 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -233,7 +233,7 @@ export function insertMarkdownText({
}
} else if (tag.indexOf(textPlaceholder) > -1) {
textToInsert = tag.replace(textPlaceholder, () =>
- selected.replace(/\\n/g, '\n').replace('%br', '\\n'),
+ selected.replace(/\\n/g, '\n').replace(/%br/g, '\\n'),
);
} else {
textToInsert = String(startChar) + tag + selected + (wrap ? tag : '');
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index c70d23d06ec..e53a39cde06 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -5,6 +5,12 @@ const PATH_SEPARATOR_LEADING_REGEX = new RegExp(`^${PATH_SEPARATOR}+`);
const PATH_SEPARATOR_ENDING_REGEX = new RegExp(`${PATH_SEPARATOR}+$`);
const SHA_REGEX = /[\da-f]{40}/gi;
+// About GitLab default host (overwrite in jh)
+export const PROMO_HOST = 'about.gitlab.com';
+
+// About Gitlab default url (overwrite in jh)
+export const PROMO_URL = `https://${PROMO_HOST}`;
+
// Reset the cursor in a Regex so that multiple uses before a recompile don't fail
function resetRegExp(regex) {
regex.lastIndex = 0; /* eslint-disable-line no-param-reassign */
diff --git a/app/assets/javascripts/logs/components/environment_logs.vue b/app/assets/javascripts/logs/components/environment_logs.vue
index 2a60825a427..c9e7b034950 100644
--- a/app/assets/javascripts/logs/components/environment_logs.vue
+++ b/app/assets/javascripts/logs/components/environment_logs.vue
@@ -130,7 +130,7 @@ export default {
}}
<a :href="clusterApplicationsDocumentationPath">
<strong>
- {{ s__('View Documentation') }}
+ {{ __('View Documentation') }}
</strong>
</a>
</gl-alert>
diff --git a/app/assets/javascripts/members/components/app.vue b/app/assets/javascripts/members/components/app.vue
index 0ec39f58930..c5083bc4826 100644
--- a/app/assets/javascripts/members/components/app.vue
+++ b/app/assets/javascripts/members/components/app.vue
@@ -11,7 +11,10 @@ export default {
components: { MembersTable, FilterSortContainer, GlAlert },
provide() {
return {
- namespace: this.namespace,
+ // We can't use this.namespace due to bug in vue-apollo when
+ // provide is called in beforeCreate
+ // See https://github.com/vuejs/vue-apollo/pull/1153 for details
+ namespace: this.$options.propsData.namespace,
};
},
props: {
diff --git a/app/assets/javascripts/monitoring/components/alert_widget.vue b/app/assets/javascripts/monitoring/components/alert_widget.vue
deleted file mode 100644
index e5d7e2ea2eb..00000000000
--- a/app/assets/javascripts/monitoring/components/alert_widget.vue
+++ /dev/null
@@ -1,285 +0,0 @@
-<script>
-import { GlBadge, GlLoadingIcon, GlModalDirective, GlIcon, GlTooltip, GlSprintf } from '@gitlab/ui';
-import { values, get } from 'lodash';
-import createFlash from '~/flash';
-import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
-import { s__ } from '~/locale';
-import { OPERATORS } from '../constants';
-import AlertsService from '../services/alerts_service';
-import { alertsValidator, queriesValidator } from '../validators';
-import AlertWidgetForm from './alert_widget_form.vue';
-
-export default {
- components: {
- AlertWidgetForm,
- GlBadge,
- GlLoadingIcon,
- GlIcon,
- GlTooltip,
- GlSprintf,
- },
- directives: {
- GlModal: GlModalDirective,
- },
- props: {
- alertsEndpoint: {
- type: String,
- required: true,
- },
- showLoadingState: {
- type: Boolean,
- required: false,
- default: true,
- },
- // { [alertPath]: { alert_attributes } }. Populated from subsequent API calls.
- // Includes only the metrics/alerts to be managed by this widget.
- alertsToManage: {
- type: Object,
- required: false,
- default: () => ({}),
- validator: alertsValidator,
- },
- // [{ metric+query_attributes }]. Represents queries (and alerts) we know about
- // on intial fetch. Essentially used for reference.
- relevantQueries: {
- type: Array,
- required: true,
- validator: queriesValidator,
- },
- modalId: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- service: null,
- errorMessage: null,
- isLoading: false,
- apiAction: 'create',
- };
- },
- i18n: {
- alertsCountMsg: s__('PrometheusAlerts|%{count} alerts applied'),
- singleFiringMsg: s__('PrometheusAlerts|Firing: %{alert}'),
- multipleFiringMsg: s__('PrometheusAlerts|%{firingCount} firing'),
- firingAlertsTooltip: s__('PrometheusAlerts|Firing: %{alerts}'),
- },
- computed: {
- singleAlertSummary() {
- return {
- message: this.isFiring ? this.$options.i18n.singleFiringMsg : this.thresholds[0],
- alert: this.thresholds[0],
- };
- },
- multipleAlertsSummary() {
- return {
- message: this.isFiring
- ? `${this.$options.i18n.alertsCountMsg}, ${this.$options.i18n.multipleFiringMsg}`
- : this.$options.i18n.alertsCountMsg,
- count: this.thresholds.length,
- firingCount: this.firingAlerts.length,
- };
- },
- shouldShowLoadingIcon() {
- return this.showLoadingState && this.isLoading;
- },
- thresholds() {
- const alertsToManage = Object.keys(this.alertsToManage);
- return alertsToManage.map(this.formatAlertSummary);
- },
- hasAlerts() {
- return Boolean(Object.keys(this.alertsToManage).length);
- },
- hasMultipleAlerts() {
- return this.thresholds.length > 1;
- },
- isFiring() {
- return Boolean(this.firingAlerts.length);
- },
- firingAlerts() {
- return values(this.alertsToManage).filter((alert) =>
- this.passedAlertThreshold(this.getQueryData(alert), alert),
- );
- },
- formattedFiringAlerts() {
- return this.firingAlerts.map((alert) => this.formatAlertSummary(alert.alert_path));
- },
- configuredAlert() {
- return this.hasAlerts ? values(this.alertsToManage)[0].metricId : '';
- },
- },
- created() {
- this.service = new AlertsService({ alertsEndpoint: this.alertsEndpoint });
- this.fetchAlertData();
- },
- methods: {
- fetchAlertData() {
- this.isLoading = true;
-
- const queriesWithAlerts = this.relevantQueries.filter((query) => query.alert_path);
-
- return Promise.all(
- queriesWithAlerts.map((query) =>
- this.service
- .readAlert(query.alert_path)
- .then((alertAttributes) => this.setAlert(alertAttributes, query.metricId)),
- ),
- )
- .then(() => {
- this.isLoading = false;
- })
- .catch(() => {
- createFlash({
- message: s__('PrometheusAlerts|Error fetching alert'),
- });
- this.isLoading = false;
- });
- },
- setAlert(alertAttributes, metricId) {
- this.$emit('setAlerts', alertAttributes.alert_path, { ...alertAttributes, metricId });
- },
- removeAlert(alertPath) {
- this.$emit('setAlerts', alertPath, null);
- },
- formatAlertSummary(alertPath) {
- const alert = this.alertsToManage[alertPath];
- const alertQuery = this.relevantQueries.find((query) => query.metricId === alert.metricId);
-
- return `${alertQuery.label} ${alert.operator} ${alert.threshold}`;
- },
- passedAlertThreshold(data, alert) {
- const { threshold, operator } = alert;
-
- switch (operator) {
- case OPERATORS.greaterThan:
- return data.some((value) => value > threshold);
- case OPERATORS.lessThan:
- return data.some((value) => value < threshold);
- case OPERATORS.equalTo:
- return data.some((value) => value === threshold);
- default:
- return false;
- }
- },
- getQueryData(alert) {
- const alertQuery = this.relevantQueries.find((query) => query.metricId === alert.metricId);
-
- return get(alertQuery, 'result[0].values', []).map((value) => get(value, '[1]', null));
- },
- showModal() {
- this.$root.$emit(BV_SHOW_MODAL, this.modalId);
- },
- hideModal() {
- this.errorMessage = null;
- this.$root.$emit(BV_HIDE_MODAL, this.modalId);
- },
- handleSetApiAction(apiAction) {
- this.apiAction = apiAction;
- },
- handleCreate({ operator, threshold, prometheus_metric_id, runbookUrl }) {
- const newAlert = { operator, threshold, prometheus_metric_id, runbookUrl };
- this.isLoading = true;
- this.service
- .createAlert(newAlert)
- .then((alertAttributes) => {
- this.setAlert(alertAttributes, prometheus_metric_id);
- this.isLoading = false;
- this.hideModal();
- })
- .catch(() => {
- this.errorMessage = s__('PrometheusAlerts|Error creating alert');
- this.isLoading = false;
- });
- },
- handleUpdate({ alert, operator, threshold, runbookUrl }) {
- const updatedAlert = { operator, threshold, runbookUrl };
- this.isLoading = true;
- this.service
- .updateAlert(alert, updatedAlert)
- .then((alertAttributes) => {
- this.setAlert(alertAttributes, this.alertsToManage[alert].metricId);
- this.isLoading = false;
- this.hideModal();
- })
- .catch(() => {
- this.errorMessage = s__('PrometheusAlerts|Error saving alert');
- this.isLoading = false;
- });
- },
- handleDelete({ alert }) {
- this.isLoading = true;
- this.service
- .deleteAlert(alert)
- .then(() => {
- this.removeAlert(alert);
- this.isLoading = false;
- this.hideModal();
- })
- .catch(() => {
- this.errorMessage = s__('PrometheusAlerts|Error deleting alert');
- this.isLoading = false;
- });
- },
- },
-};
-</script>
-
-<template>
- <div class="prometheus-alert-widget dropdown flex-grow-2 overflow-hidden">
- <gl-loading-icon v-if="shouldShowLoadingIcon" :inline="true" size="sm" />
- <span v-else-if="errorMessage" ref="alertErrorMessage" class="alert-error-message">{{
- errorMessage
- }}</span>
- <span
- v-else-if="hasAlerts"
- ref="alertCurrentSetting"
- class="alert-current-setting cursor-pointer d-flex"
- @click="showModal"
- >
- <gl-badge :variant="isFiring ? 'danger' : 'neutral'" class="d-flex-center text-truncate">
- <gl-icon name="warning" :size="16" class="flex-shrink-0" />
- <span class="text-truncate gl-pl-2">
- <gl-sprintf
- :message="
- hasMultipleAlerts ? multipleAlertsSummary.message : singleAlertSummary.message
- "
- >
- <template #alert>
- {{ singleAlertSummary.alert }}
- </template>
- <template #count>
- {{ multipleAlertsSummary.count }}
- </template>
- <template #firingCount>
- {{ multipleAlertsSummary.firingCount }}
- </template>
- </gl-sprintf>
- </span>
- </gl-badge>
- <gl-tooltip v-if="hasMultipleAlerts && isFiring" :target="() => $refs.alertCurrentSetting">
- <gl-sprintf :message="$options.i18n.firingAlertsTooltip">
- <template #alerts>
- <div v-for="alert in formattedFiringAlerts" :key="alert.alert_path">
- {{ alert }}
- </div>
- </template>
- </gl-sprintf>
- </gl-tooltip>
- </span>
- <alert-widget-form
- ref="widgetForm"
- :disabled="isLoading"
- :alerts-to-manage="alertsToManage"
- :relevant-queries="relevantQueries"
- :error-message="errorMessage"
- :configured-alert="configuredAlert"
- :modal-id="modalId"
- @create="handleCreate"
- @update="handleUpdate"
- @delete="handleDelete"
- @cancel="hideModal"
- @setAction="handleSetApiAction"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/monitoring/components/alert_widget_form.vue b/app/assets/javascripts/monitoring/components/alert_widget_form.vue
deleted file mode 100644
index 68fd3e256ec..00000000000
--- a/app/assets/javascripts/monitoring/components/alert_widget_form.vue
+++ /dev/null
@@ -1,324 +0,0 @@
-<script>
-import {
- GlLink,
- GlButton,
- GlButtonGroup,
- GlFormGroup,
- GlFormInput,
- GlDropdown,
- GlDropdownItem,
- GlModal,
- GlTooltipDirective,
- GlIcon,
-} from '@gitlab/ui';
-import { isEmpty, findKey } from 'lodash';
-import Vue from 'vue';
-import { __, s__ } from '~/locale';
-import TrackEventDirective from '~/vue_shared/directives/track_event';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import Translate from '~/vue_shared/translate';
-import { OPERATORS } from '../constants';
-import { alertsValidator, queriesValidator } from '../validators';
-
-Vue.use(Translate);
-
-const SUBMIT_ACTION_TEXT = {
- create: __('Add'),
- update: __('Save'),
- delete: __('Delete'),
-};
-
-const SUBMIT_BUTTON_CLASS = {
- create: 'btn-success',
- update: 'btn-success',
- delete: 'btn-danger',
-};
-
-export default {
- components: {
- GlButton,
- GlButtonGroup,
- GlFormGroup,
- GlFormInput,
- GlDropdown,
- GlDropdownItem,
- GlModal,
- GlLink,
- GlIcon,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- TrackEvent: TrackEventDirective,
- },
- mixins: [glFeatureFlagsMixin()],
- props: {
- disabled: {
- type: Boolean,
- required: true,
- },
- errorMessage: {
- type: String,
- required: false,
- default: '',
- },
- configuredAlert: {
- type: String,
- required: false,
- default: '',
- },
- alertsToManage: {
- type: Object,
- required: false,
- default: () => ({}),
- validator: alertsValidator,
- },
- relevantQueries: {
- type: Array,
- required: true,
- validator: queriesValidator,
- },
- modalId: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- operators: OPERATORS,
- operator: null,
- threshold: null,
- prometheusMetricId: null,
- runbookUrl: null,
- selectedAlert: {},
- alertQuery: '',
- };
- },
- computed: {
- isValidQuery() {
- // TODO: Add query validation check (most likely via http request)
- return this.alertQuery.length ? true : null;
- },
- currentQuery() {
- return this.relevantQueries.find((query) => query.metricId === this.prometheusMetricId) || {};
- },
- formDisabled() {
- // We need a prometheusMetricId to determine whether we're
- // creating/updating/deleting
- return this.disabled || !(this.prometheusMetricId || this.isValidQuery);
- },
- supportsComputedAlerts() {
- return this.glFeatures.prometheusComputedAlerts;
- },
- queryDropdownLabel() {
- return this.currentQuery.label || s__('PrometheusAlerts|Select query');
- },
- haveValuesChanged() {
- return (
- this.operator &&
- this.threshold === Number(this.threshold) &&
- (this.operator !== this.selectedAlert.operator ||
- this.threshold !== this.selectedAlert.threshold ||
- this.runbookUrl !== this.selectedAlert.runbookUrl)
- );
- },
- submitAction() {
- if (isEmpty(this.selectedAlert)) return 'create';
- if (this.haveValuesChanged) return 'update';
- return 'delete';
- },
- submitActionText() {
- return SUBMIT_ACTION_TEXT[this.submitAction];
- },
- submitButtonClass() {
- return SUBMIT_BUTTON_CLASS[this.submitAction];
- },
- isSubmitDisabled() {
- return this.disabled || (this.submitAction === 'create' && !this.haveValuesChanged);
- },
- dropdownTitle() {
- return this.submitAction === 'create'
- ? s__('PrometheusAlerts|Add alert')
- : s__('PrometheusAlerts|Edit alert');
- },
- },
- watch: {
- alertsToManage() {
- this.resetAlertData();
- },
- submitAction() {
- this.$emit('setAction', this.submitAction);
- },
- },
- methods: {
- selectQuery(queryId) {
- const existingAlertPath = findKey(this.alertsToManage, (alert) => alert.metricId === queryId);
- const existingAlert = this.alertsToManage[existingAlertPath];
-
- if (existingAlert) {
- const { operator, threshold, runbookUrl } = existingAlert;
-
- this.selectedAlert = existingAlert;
- this.operator = operator;
- this.threshold = threshold;
- this.runbookUrl = runbookUrl;
- } else {
- this.selectedAlert = {};
- this.operator = this.operators.greaterThan;
- this.threshold = null;
- this.runbookUrl = null;
- }
-
- this.prometheusMetricId = queryId;
- },
- handleHidden() {
- this.resetAlertData();
- this.$emit('cancel');
- },
- handleSubmit() {
- this.$emit(this.submitAction, {
- alert: this.selectedAlert.alert_path,
- operator: this.operator,
- threshold: this.threshold,
- prometheus_metric_id: this.prometheusMetricId,
- runbookUrl: this.runbookUrl,
- });
- },
- handleShown() {
- if (this.configuredAlert) {
- this.selectQuery(this.configuredAlert);
- } else if (this.relevantQueries.length === 1) {
- this.selectQuery(this.relevantQueries[0].metricId);
- }
- },
- resetAlertData() {
- this.operator = null;
- this.threshold = null;
- this.prometheusMetricId = null;
- this.selectedAlert = {};
- this.runbookUrl = null;
- },
- getAlertFormActionTrackingOption() {
- const label = `${this.submitAction}_alert`;
- return {
- category: document.body.dataset.page,
- action: 'click_button',
- label,
- };
- },
- },
- alertQueryText: {
- label: __('Query'),
- validFeedback: __('Query is valid'),
- invalidFeedback: __('Invalid query'),
- descriptionTooltip: __(
- 'Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula.',
- ),
- },
-};
-</script>
-
-<template>
- <gl-modal
- ref="alertModal"
- :title="dropdownTitle"
- :modal-id="modalId"
- :ok-variant="submitAction === 'delete' ? 'danger' : 'success'"
- :ok-disabled="formDisabled"
- @ok.prevent="handleSubmit"
- @hidden="handleHidden"
- @shown="handleShown"
- >
- <div v-if="errorMessage" class="alert-modal-message danger_message">{{ errorMessage }}</div>
- <div class="alert-form">
- <gl-form-group
- v-if="supportsComputedAlerts"
- :label="$options.alertQueryText.label"
- label-for="alert-query-input"
- :valid-feedback="$options.alertQueryText.validFeedback"
- :invalid-feedback="$options.alertQueryText.invalidFeedback"
- :state="isValidQuery"
- >
- <gl-form-input id="alert-query-input" v-model.trim="alertQuery" :state="isValidQuery" />
- <template #description>
- <div class="d-flex align-items-center">
- {{ __('Single or combined queries') }}
- <gl-icon
- v-gl-tooltip="$options.alertQueryText.descriptionTooltip"
- name="question"
- class="gl-ml-2"
- />
- </div>
- </template>
- </gl-form-group>
- <gl-form-group v-else label-for="alert-query-dropdown" :label="$options.alertQueryText.label">
- <gl-dropdown
- id="alert-query-dropdown"
- :text="queryDropdownLabel"
- toggle-class="dropdown-menu-toggle gl-border-1! qa-alert-query-dropdown"
- >
- <gl-dropdown-item
- v-for="query in relevantQueries"
- :key="query.metricId"
- data-qa-selector="alert_query_option"
- @click="selectQuery(query.metricId)"
- >
- {{ query.label }}
- </gl-dropdown-item>
- </gl-dropdown>
- </gl-form-group>
- <gl-button-group class="mb-3" :label="s__('PrometheusAlerts|Operator')">
- <gl-button
- :class="{ active: operator === operators.greaterThan }"
- :disabled="formDisabled"
- @click="operator = operators.greaterThan"
- >
- {{ operators.greaterThan }}
- </gl-button>
- <gl-button
- :class="{ active: operator === operators.equalTo }"
- :disabled="formDisabled"
- @click="operator = operators.equalTo"
- >
- {{ operators.equalTo }}
- </gl-button>
- <gl-button
- :class="{ active: operator === operators.lessThan }"
- :disabled="formDisabled"
- @click="operator = operators.lessThan"
- >
- {{ operators.lessThan }}
- </gl-button>
- </gl-button-group>
- <gl-form-group :label="s__('PrometheusAlerts|Threshold')" label-for="alerts-threshold">
- <gl-form-input
- id="alerts-threshold"
- v-model.number="threshold"
- :disabled="formDisabled"
- type="number"
- data-qa-selector="alert_threshold_field"
- />
- </gl-form-group>
- <gl-form-group
- :label="s__('PrometheusAlerts|Runbook URL (optional)')"
- label-for="alert-runbook"
- >
- <gl-form-input
- id="alert-runbook"
- v-model="runbookUrl"
- :disabled="formDisabled"
- data-testid="alertRunbookField"
- type="text"
- :placeholder="s__('PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks')"
- />
- </gl-form-group>
- </div>
- <template #modal-ok>
- <gl-link
- v-track-event="getAlertFormActionTrackingOption()"
- class="text-reset text-decoration-none"
- >
- {{ submitActionText }}
- </gl-link>
- </template>
- </gl-modal>
-</template>
diff --git a/app/assets/javascripts/monitoring/components/charts/empty_chart.vue b/app/assets/javascripts/monitoring/components/charts/empty_chart.vue
index 4b54cffe231..ae079da0b0b 100644
--- a/app/assets/javascripts/monitoring/components/charts/empty_chart.vue
+++ b/app/assets/javascripts/monitoring/components/charts/empty_chart.vue
@@ -1,8 +1,12 @@
<script>
import chartEmptyStateIllustration from '@gitlab/svgs/dist/illustrations/chart-empty-state.svg';
+import { GlSafeHtmlDirective } from '@gitlab/ui';
import { chartHeight } from '../../constants';
export default {
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
data() {
return {
height: chartHeight,
@@ -18,14 +22,15 @@ export default {
created() {
this.chartEmptyStateIllustration = chartEmptyStateIllustration;
},
+ safeHtmlConfig: { ADD_TAGS: ['use'] },
};
</script>
<template>
<div class="d-flex flex-column justify-content-center">
<div
+ v-safe-html:[$options.safeHtmlConfig]="chartEmptyStateIllustration"
class="gl-mt-3 svg-w-100 d-flex align-items-center"
:style="svgContainerStyle"
- v-html="chartEmptyStateIllustration /* eslint-disable-line vue/no-v-html */"
></div>
<h5 class="text-center gl-mt-3">{{ __('No data to display') }}</h5>
</div>
diff --git a/app/assets/javascripts/monitoring/components/charts/time_series.vue b/app/assets/javascripts/monitoring/components/charts/time_series.vue
index 12f5e7efc96..5529a94874b 100644
--- a/app/assets/javascripts/monitoring/components/charts/time_series.vue
+++ b/app/assets/javascripts/monitoring/components/charts/time_series.vue
@@ -73,11 +73,6 @@ export default {
required: false,
default: chartHeight,
},
- thresholds: {
- type: Array,
- required: false,
- default: () => [],
- },
legendLayout: {
type: String,
required: false,
@@ -391,7 +386,6 @@ export default {
:option="chartOptions"
:format-tooltip-text="formatTooltipText"
:format-annotations-tooltip-text="formatAnnotationsTooltipText"
- :thresholds="thresholds"
:width="width"
:height="height"
:legend-layout="legendLayout"
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index be9f104b81e..c9767330b73 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -8,10 +8,8 @@ import invalidUrl from '~/lib/utils/invalid_url';
import { ESC_KEY } from '~/lib/utils/keys';
import { mergeUrlParams, updateHistory } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
-import AlertsDeprecationWarning from '~/vue_shared/components/alerts_deprecation_warning.vue';
import { defaultTimeRange } from '~/vue_shared/constants';
import TrackEventDirective from '~/vue_shared/directives/track_event';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { metricStates, keyboardShortcutKeys } from '../constants';
import {
timeRangeFromUrl,
@@ -30,7 +28,6 @@ import VariablesSection from './variables_section.vue';
export default {
components: {
- AlertsDeprecationWarning,
VueDraggable,
DashboardHeader,
DashboardPanel,
@@ -47,7 +44,6 @@ export default {
GlTooltip: GlTooltipDirective,
TrackEvent: TrackEventDirective,
},
- mixins: [glFeatureFlagMixin()],
props: {
hasMetrics: {
type: Boolean,
@@ -399,8 +395,6 @@ export default {
<template>
<div class="prometheus-graphs" data-qa-selector="prometheus_graphs">
- <alerts-deprecation-warning v-if="!glFeatures.managedAlertsDeprecation" />
-
<dashboard-header
v-if="showHeader"
ref="prometheusGraphsHeader"
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
index 446c6b52602..78e3b15913a 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
@@ -13,20 +13,16 @@ import {
GlTooltip,
GlTooltipDirective,
} from '@gitlab/ui';
-import { mapValues, pickBy } from 'lodash';
import { mapState } from 'vuex';
-import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
import invalidUrl from '~/lib/utils/invalid_url';
import { relativePathToAbsolute, getBaseURL, visitUrl, isSafeURL } from '~/lib/utils/url_utility';
import { __, n__ } from '~/locale';
import TrackEventDirective from '~/vue_shared/directives/track_event';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { panelTypes } from '../constants';
import { graphDataToCsv } from '../csv_export';
import { timeRangeToUrl, downloadCSVOptions, generateLinkToChartOptions } from '../utils';
-import AlertWidget from './alert_widget.vue';
import MonitorAnomalyChart from './charts/anomaly.vue';
import MonitorBarChart from './charts/bar.vue';
import MonitorColumnChart from './charts/column.vue';
@@ -45,7 +41,6 @@ const events = {
export default {
components: {
MonitorEmptyChart,
- AlertWidget,
GlIcon,
GlLink,
GlLoadingIcon,
@@ -62,7 +57,6 @@ export default {
GlTooltip: GlTooltipDirective,
TrackEvent: TrackEventDirective,
},
- mixins: [glFeatureFlagMixin()],
props: {
clipboardText: {
type: String,
@@ -84,16 +78,6 @@ export default {
required: false,
default: 'monitoringDashboard',
},
- alertsEndpoint: {
- type: String,
- required: false,
- default: null,
- },
- prometheusAlertsAvailable: {
- type: Boolean,
- required: false,
- default: false,
- },
settingsPath: {
type: String,
required: false,
@@ -104,7 +88,6 @@ export default {
return {
showTitleTooltip: false,
zoomedTimeRange: null,
- allAlerts: {},
expandBtnAvailable: Boolean(this.$listeners[events.expand]),
};
},
@@ -211,7 +194,7 @@ export default {
/**
* In monitoring, Time Series charts typically support
* a larger feature set like "annotations", "deployment
- * data", alert "thresholds" and "datazoom".
+ * data" and "datazoom".
*
* This is intentional as Time Series are more frequently
* used.
@@ -252,34 +235,11 @@ export default {
const { metrics = [] } = this.graphData;
return metrics.some(({ metricId }) => this.metricsSavedToDb.includes(metricId));
},
- alertWidgetAvailable() {
- const supportsAlerts =
- this.isPanelType(panelTypes.AREA_CHART) || this.isPanelType(panelTypes.LINE_CHART);
- return (
- supportsAlerts &&
- this.prometheusAlertsAvailable &&
- this.alertsEndpoint &&
- this.graphData &&
- this.hasMetricsInDb &&
- !this.glFeatures.managedAlertsDeprecation
- );
- },
- alertModalId() {
- return `alert-modal-${this.graphData.id}`;
- },
},
mounted() {
this.refreshTitleTooltip();
},
methods: {
- getGraphAlerts(queries) {
- if (!this.allAlerts) return {};
- const metricIdsForChart = queries.map((q) => q.metricId);
- return pickBy(this.allAlerts, (alert) => metricIdsForChart.includes(alert.metricId));
- },
- getGraphAlertValues(queries) {
- return Object.values(this.getGraphAlerts(queries));
- },
isPanelType(type) {
return this.graphData?.type === type;
},
@@ -310,24 +270,9 @@ export default {
this.onExpand();
}
},
- setAlerts(alertPath, alertAttributes) {
- if (alertAttributes) {
- this.$set(this.allAlerts, alertPath, alertAttributes);
- } else {
- this.$delete(this.allAlerts, alertPath);
- }
- },
safeUrl(url) {
return isSafeURL(url) ? url : '#';
},
- showAlertModal() {
- this.$root.$emit(BV_SHOW_MODAL, this.alertModalId);
- },
- showAlertModalFromKeyboardShortcut() {
- if (this.isContextualMenuShown) {
- this.showAlertModal();
- }
- },
visitLogsPage() {
if (this.logsPathWithTimeRange) {
visitUrl(relativePathToAbsolute(this.logsPathWithTimeRange, getBaseURL()));
@@ -348,19 +293,6 @@ export default {
this.$refs.copyChartLink.$el.firstChild.click();
}
},
- getAlertRunbooks(queries) {
- const hasRunbook = (alert) => Boolean(alert.runbookUrl);
- const graphAlertsWithRunbooks = pickBy(this.getGraphAlerts(queries), hasRunbook);
- const alertToRunbookTransform = (alert) => {
- const alertQuery = queries.find((query) => query.metricId === alert.metricId);
- return {
- key: alert.metricId,
- href: alert.runbookUrl,
- label: alertQuery.label,
- };
- };
- return mapValues(graphAlertsWithRunbooks, alertToRunbookTransform);
- },
},
panelTypes,
};
@@ -378,15 +310,6 @@ export default {
<gl-tooltip :target="() => $refs.graphTitle" :disabled="!showTitleTooltip">
{{ title }}
</gl-tooltip>
- <alert-widget
- v-if="isContextualMenuShown && alertWidgetAvailable"
- class="mx-1"
- :modal-id="alertModalId"
- :alerts-endpoint="alertsEndpoint"
- :relevant-queries="graphData.metrics"
- :alerts-to-manage="getGraphAlerts(graphData.metrics)"
- @setAlerts="setAlerts"
- />
<div class="flex-grow-1"></div>
<div v-if="graphDataIsLoading" class="mx-1 mt-1">
<gl-loading-icon size="sm" />
@@ -450,32 +373,6 @@ export default {
>
{{ __('Copy link to chart') }}
</gl-dropdown-item>
- <gl-dropdown-item
- v-if="alertWidgetAvailable"
- v-gl-modal="alertModalId"
- data-qa-selector="alert_widget_menu_item"
- >
- {{ __('Alerts') }}
- </gl-dropdown-item>
- <gl-dropdown-item
- v-for="runbook in getAlertRunbooks(graphData.metrics)"
- :key="runbook.key"
- :href="safeUrl(runbook.href)"
- data-testid="runbookLink"
- target="_blank"
- rel="noopener noreferrer"
- >
- <span class="gl-display-flex gl-justify-content-space-between gl-align-items-center">
- <span>
- <gl-sprintf :message="s__('Metrics|View runbook - %{label}')">
- <template #label>
- {{ runbook.label }}
- </template>
- </gl-sprintf>
- </span>
- <gl-icon name="external-link" />
- </span>
- </gl-dropdown-item>
<template v-if="graphData.links && graphData.links.length">
<gl-dropdown-divider />
@@ -515,7 +412,6 @@ export default {
:deployment-data="deploymentData"
:annotations="annotations"
:project-path="projectPath"
- :thresholds="getGraphAlertValues(graphData.metrics)"
:group-id="groupId"
:timezone="dashboardTimezone"
:time-range="fixedCurrentTimeRange"
diff --git a/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue b/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue
index 1765a2f3d5d..a63008aa382 100644
--- a/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue
+++ b/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue
@@ -63,7 +63,7 @@ export default {
return !(this.form.fileName && !this.form.fileName.endsWith('.yml'));
},
fileNameFeedback() {
- return !this.fileNameState ? s__('The file name should have a .yml extension') : '';
+ return !this.fileNameState ? __('The file name should have a .yml extension') : '';
},
},
mounted() {
diff --git a/app/assets/javascripts/monitoring/monitoring_app.js b/app/assets/javascripts/monitoring/monitoring_app.js
index cf79e71b9e0..ee67e5dd827 100644
--- a/app/assets/javascripts/monitoring/monitoring_app.js
+++ b/app/assets/javascripts/monitoring/monitoring_app.js
@@ -12,10 +12,7 @@ export default (props = {}) => {
if (el && el.dataset) {
const { metricsDashboardBasePath, ...dataset } = el.dataset;
- const {
- initState,
- dataProps: { hasManagedPrometheus, ...dataProps },
- } = stateAndPropsFromDataset(dataset);
+ const { initState, dataProps } = stateAndPropsFromDataset(dataset);
const store = createStore(initState);
const router = createRouter(metricsDashboardBasePath);
@@ -24,7 +21,6 @@ export default (props = {}) => {
el,
store,
router,
- provide: { hasManagedPrometheus },
data() {
return {
dashboardProps: { ...dataProps, ...props },
diff --git a/app/assets/javascripts/monitoring/utils.js b/app/assets/javascripts/monitoring/utils.js
index 74b777d7b44..336b613b620 100644
--- a/app/assets/javascripts/monitoring/utils.js
+++ b/app/assets/javascripts/monitoring/utils.js
@@ -41,7 +41,6 @@ export const stateAndPropsFromDataset = (dataset = {}) => {
dataProps.hasMetrics = parseBoolean(dataProps.hasMetrics);
dataProps.customMetricsAvailable = parseBoolean(dataProps.customMetricsAvailable);
dataProps.prometheusAlertsAvailable = parseBoolean(dataProps.prometheusAlertsAvailable);
- dataProps.hasManagedPrometheus = parseBoolean(dataProps.hasManagedPrometheus);
return {
initState: {
diff --git a/app/assets/javascripts/mr_notes/index.js b/app/assets/javascripts/mr_notes/index.js
index ea3e4e5604c..a1377415efe 100644
--- a/app/assets/javascripts/mr_notes/index.js
+++ b/app/assets/javascripts/mr_notes/index.js
@@ -23,8 +23,8 @@ export default function initMrNotes() {
initNotesApp();
document.addEventListener('merged:UpdateActions', () => {
- initRevertCommitModal();
- initCherryPickCommitModal();
+ initRevertCommitModal('i_code_review_post_merge_submit_revert_modal');
+ initCherryPickCommitModal('i_code_review_post_merge_submit_cherry_pick_modal');
});
requestIdleCallback(() => {
diff --git a/app/assets/javascripts/mr_popover/index.js b/app/assets/javascripts/mr_popover/index.js
index 6e46c5d3c1f..714cf67e0bd 100644
--- a/app/assets/javascripts/mr_popover/index.js
+++ b/app/assets/javascripts/mr_popover/index.js
@@ -48,12 +48,7 @@ export default (elements) => {
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- ),
+ defaultClient: createDefaultClient(),
});
const listenerAddedAttr = 'data-mr-listener-added';
diff --git a/app/assets/javascripts/nav/components/responsive_home.vue b/app/assets/javascripts/nav/components/responsive_home.vue
index c8f2f0bfb10..a80fda96363 100644
--- a/app/assets/javascripts/nav/components/responsive_home.vue
+++ b/app/assets/javascripts/nav/components/responsive_home.vue
@@ -55,6 +55,7 @@ export default {
v-gl-tooltip="{ title: newDropdownViewModel.title }"
:view-model="newDropdownViewModel"
class="gl-ml-3"
+ data-qa-selector="mobile_new_dropdown"
/>
</header>
<top-nav-menu-sections class="gl-h-full" :sections="menuSections" v-on="$listeners" />
diff --git a/app/assets/javascripts/nav/components/top_nav_new_dropdown.vue b/app/assets/javascripts/nav/components/top_nav_new_dropdown.vue
index 154bed81854..bfcdcfc7292 100644
--- a/app/assets/javascripts/nav/components/top_nav_new_dropdown.vue
+++ b/app/assets/javascripts/nav/components/top_nav_new_dropdown.vue
@@ -46,6 +46,7 @@ export default {
link-class="top-nav-menu-item"
:href="menuItem.href"
data-testid="item"
+ :data-qa-selector="`${menuItem.title.toLowerCase().replace(' ', '_')}_mobile_button`"
>
{{ menuItem.title }}
</gl-dropdown-item>
diff --git a/app/assets/javascripts/network/branch_graph.js b/app/assets/javascripts/network/branch_graph.js
index 6ee5d85a09f..54fe9d19002 100644
--- a/app/assets/javascripts/network/branch_graph.js
+++ b/app/assets/javascripts/network/branch_graph.js
@@ -272,6 +272,8 @@ export default class BranchGraph {
return r
.text(this.offsetX + this.unitSpace * this.mspace + 35, y, commit.message.split('\n')[0])
.attr({
+ fill: 'currentColor',
+ class: 'gl-text-body',
'text-anchor': 'start',
font: '14px Monaco, monospace',
});
diff --git a/app/assets/javascripts/notebook/cells/output/latex.vue b/app/assets/javascripts/notebook/cells/output/latex.vue
index db9e61dce82..d0ed963b55d 100644
--- a/app/assets/javascripts/notebook/cells/output/latex.vue
+++ b/app/assets/javascripts/notebook/cells/output/latex.vue
@@ -1,4 +1,5 @@
<script>
+import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import 'mathjax/es5/tex-svg';
import Prompt from '../prompt.vue';
@@ -7,6 +8,9 @@ export default {
components: {
Prompt,
},
+ directives: {
+ SafeHtml,
+ },
props: {
count: {
type: Number,
@@ -33,13 +37,16 @@ export default {
return svg.outerHTML;
},
},
+ safeHtmlConfig: {
+ // to support SVGs and custom tags for mathjax
+ ADD_TAGS: ['use', 'mjx-container', 'mjx-tool', 'mjx-status', 'mjx-tip'],
+ },
};
</script>
<template>
<div class="output">
<prompt type="Out" :count="count" :show-output="index === 0" />
- <!-- eslint-disable -->
- <div ref="maths" v-html="code"></div>
+ <div ref="maths" v-safe-html:[$options.safeHtmlConfig]="code"></div>
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue
index 831e6dd8f92..33819c78c0f 100644
--- a/app/assets/javascripts/notes/components/discussion_counter.vue
+++ b/app/assets/javascripts/notes/components/discussion_counter.vue
@@ -78,8 +78,8 @@ export default {
v-if="resolveAllDiscussionsIssuePath && !allResolved"
v-gl-tooltip
:href="resolveAllDiscussionsIssuePath"
- :title="s__('Create issue to resolve all threads')"
- :aria-label="s__('Create issue to resolve all threads')"
+ :title="__('Create issue to resolve all threads')"
+ :aria-label="__('Create issue to resolve all threads')"
class="new-issue-for-discussion discussion-create-issue-btn"
icon="issue-new"
/>
diff --git a/app/assets/javascripts/notes/components/discussion_notes.vue b/app/assets/javascripts/notes/components/discussion_notes.vue
index 6fcfa66ea49..d1df4eb848b 100644
--- a/app/assets/javascripts/notes/components/discussion_notes.vue
+++ b/app/assets/javascripts/notes/components/discussion_notes.vue
@@ -1,5 +1,6 @@
<script>
import { mapGetters, mapActions } from 'vuex';
+import { GlIntersectionObserver } from '@gitlab/ui';
import { __ } from '~/locale';
import PlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue';
@@ -16,7 +17,9 @@ export default {
ToggleRepliesWidget,
NoteEditedText,
DiscussionNotesRepliesWrapper,
+ GlIntersectionObserver,
},
+ inject: ['discussionObserverHandler'],
props: {
discussion: {
type: Object,
@@ -54,7 +57,11 @@ export default {
},
},
computed: {
- ...mapGetters(['userCanReply']),
+ ...mapGetters([
+ 'userCanReply',
+ 'previousUnresolvedDiscussionId',
+ 'firstUnresolvedDiscussionId',
+ ]),
hasReplies() {
return Boolean(this.replies.length);
},
@@ -77,9 +84,20 @@ export default {
url: this.discussion.discussion_path,
};
},
+ isFirstUnresolved() {
+ return this.firstUnresolvedDiscussionId === this.discussion.id;
+ },
+ },
+ observerOptions: {
+ threshold: 0,
+ rootMargin: '0px 0px -50% 0px',
},
methods: {
- ...mapActions(['toggleDiscussion', 'setSelectedCommentPositionHover']),
+ ...mapActions([
+ 'toggleDiscussion',
+ 'setSelectedCommentPositionHover',
+ 'setCurrentDiscussionId',
+ ]),
componentName(note) {
if (note.isPlaceholderNote) {
if (note.placeholderType === SYSTEM_NOTE) {
@@ -110,6 +128,18 @@ export default {
this.setSelectedCommentPositionHover();
}
},
+ observerTriggered(entry) {
+ this.discussionObserverHandler({
+ entry,
+ isFirstUnresolved: this.isFirstUnresolved,
+ currentDiscussion: { ...this.discussion },
+ isDiffsPage: !this.isOverviewTab,
+ functions: {
+ setCurrentDiscussionId: this.setCurrentDiscussionId,
+ getPreviousUnresolvedDiscussionId: this.previousUnresolvedDiscussionId,
+ },
+ });
+ },
},
};
</script>
@@ -122,33 +152,35 @@ export default {
@mouseleave="handleMouseLeave(discussion)"
>
<template v-if="shouldGroupReplies">
- <component
- :is="componentName(firstNote)"
- :note="componentData(firstNote)"
- :line="line || diffLine"
- :discussion-file="discussion.diff_file"
- :commit="commit"
- :help-page-path="helpPagePath"
- :show-reply-button="userCanReply"
- :discussion-root="true"
- :discussion-resolve-path="discussion.resolve_path"
- :is-overview-tab="isOverviewTab"
- @handleDeleteNote="$emit('deleteNote')"
- @startReplying="$emit('startReplying')"
- >
- <template #discussion-resolved-text>
- <note-edited-text
- v-if="discussion.resolved"
- :edited-at="discussion.resolved_at"
- :edited-by="discussion.resolved_by"
- :action-text="resolvedText"
- class-name="discussion-headline-light js-discussion-headline discussion-resolved-text"
- />
- </template>
- <template #avatar-badge>
- <slot name="avatar-badge"></slot>
- </template>
- </component>
+ <gl-intersection-observer :options="$options.observerOptions" @update="observerTriggered">
+ <component
+ :is="componentName(firstNote)"
+ :note="componentData(firstNote)"
+ :line="line || diffLine"
+ :discussion-file="discussion.diff_file"
+ :commit="commit"
+ :help-page-path="helpPagePath"
+ :show-reply-button="userCanReply"
+ :discussion-root="true"
+ :discussion-resolve-path="discussion.resolve_path"
+ :is-overview-tab="isOverviewTab"
+ @handleDeleteNote="$emit('deleteNote')"
+ @startReplying="$emit('startReplying')"
+ >
+ <template #discussion-resolved-text>
+ <note-edited-text
+ v-if="discussion.resolved"
+ :edited-at="discussion.resolved_at"
+ :edited-by="discussion.resolved_by"
+ :action-text="resolvedText"
+ class-name="discussion-headline-light js-discussion-headline discussion-resolved-text"
+ />
+ </template>
+ <template #avatar-badge>
+ <slot name="avatar-badge"></slot>
+ </template>
+ </component>
+ </gl-intersection-observer>
<discussion-notes-replies-wrapper :is-diff-discussion="discussion.diff_discussion">
<toggle-replies-widget
v-if="hasReplies"
diff --git a/app/assets/javascripts/notes/components/multiline_comment_form.vue b/app/assets/javascripts/notes/components/multiline_comment_form.vue
index 6ad565567be..1633b79c3be 100644
--- a/app/assets/javascripts/notes/components/multiline_comment_form.vue
+++ b/app/assets/javascripts/notes/components/multiline_comment_form.vue
@@ -1,6 +1,6 @@
<script>
import { GlFormSelect, GlSprintf } from '@gitlab/ui';
-import { mapActions, mapState } from 'vuex';
+import { mapActions } from 'vuex';
import { getSymbol, getLineClasses } from './multiline_comment_utils';
export default {
@@ -27,13 +27,12 @@ export default {
};
},
computed: {
- ...mapState({ selectedCommentPosition: ({ notes }) => notes.selectedCommentPosition }),
lineNumber() {
return this.commentLineOptions[this.commentLineOptions.length - 1].text;
},
},
created() {
- const line = this.selectedCommentPosition?.start || this.lineRange?.start || this.line;
+ const line = this.lineRange?.start || this.line;
this.commentLineStart = {
line_code: line.line_code,
@@ -42,7 +41,6 @@ export default {
new_line: line.new_line,
};
- if (this.selectedCommentPosition) return;
this.highlightSelection();
},
destroyed() {
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index 1ce1696e332..c09582d6287 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -1,5 +1,6 @@
<script>
import $ from 'jquery';
+import { GlSafeHtmlDirective } from '@gitlab/ui';
import { escape } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
@@ -19,6 +20,9 @@ export default {
noteForm,
Suggestions,
},
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
mixins: [autosave],
props: {
note: {
@@ -144,6 +148,9 @@ export default {
this.removeSuggestionInfoFromBatch(suggestionId);
},
},
+ safeHtmlConfig: {
+ ADD_TAGS: ['use', 'gl-emoji'],
+ },
};
</script>
@@ -163,11 +170,7 @@ export default {
@addToBatch="addSuggestionToBatch"
@removeFromBatch="removeSuggestionFromBatch"
/>
- <div
- v-else
- class="note-text md"
- v-html="note.note_html /* eslint-disable-line vue/no-v-html */"
- ></div>
+ <div v-else v-safe-html:[$options.safeHtmlConfig]="note.note_html" class="note-text md"></div>
<note-form
v-if="isEditing"
ref="noteForm"
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index b05643e5e13..d6b65ed0e8b 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -1,9 +1,9 @@
<script>
-import { GlButton } from '@gitlab/ui';
+import { GlButton, GlSprintf, GlLink } from '@gitlab/ui';
import { mapGetters, mapActions, mapState } from 'vuex';
import { getDraft, updateDraft } from '~/lib/utils/autosave';
import { mergeUrlParams } from '~/lib/utils/url_utility';
-import { __, sprintf } from '~/locale';
+import { __ } from '~/locale';
import markdownField from '~/vue_shared/components/markdown/field.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../event_hub';
@@ -17,6 +17,8 @@ export default {
markdownField,
CommentFieldLayout,
GlButton,
+ GlSprintf,
+ GlLink,
},
mixins: [glFeatureFlagsMixin(), issuableStateMixin, resolvable],
props: {
@@ -203,16 +205,12 @@ export default {
);
},
changedCommentText() {
- return sprintf(
- __(
+ return {
+ text: __(
'This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost.',
),
- {
- startTag: `<a href="${this.noteHash}" target="_blank" rel="noopener noreferrer">`,
- endTag: '</a>',
- },
- false,
- );
+ placeholder: { link: ['startTag', 'endTag'] },
+ };
},
},
watch: {
@@ -318,11 +316,13 @@ export default {
<template>
<div ref="editNoteForm" class="note-edit-form current-note-edit-form js-discussion-note-form">
- <div
- v-if="conflictWhileEditing"
- class="js-conflict-edit-warning alert alert-danger"
- v-html="changedCommentText /* eslint-disable-line vue/no-v-html */"
- ></div>
+ <div v-if="conflictWhileEditing" class="js-conflict-edit-warning alert alert-danger">
+ <gl-sprintf :message="changedCommentText.text" :placeholders="changedCommentText.placeholder">
+ <template #link="{ content }">
+ <gl-link :href="noteHash" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </div>
<div class="flash-container timeline-content"></div>
<form :data-line-code="lineCode" class="edit-note common-note-form js-quick-submit gfm-form">
<comment-field-layout
@@ -334,13 +334,13 @@ export default {
:markdown-docs-path="markdownDocsPath"
:quick-actions-docs-path="quickActionsDocsPath"
:line="line"
+ :lines="lines"
:note="discussionNote"
:can-suggest="canSuggest"
:add-spacing-classes="false"
:help-page-path="helpPagePath"
:show-suggest-popover="showSuggestPopover"
:textarea-value="updatedNoteBody"
- :lines="lines"
@handleSuggestDismissed="() => $emit('handleSuggestDismissed')"
>
<template #textarea>
diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue
index 58570e76795..3ab3e7a20d4 100644
--- a/app/assets/javascripts/notes/components/notes_app.vue
+++ b/app/assets/javascripts/notes/components/notes_app.vue
@@ -8,6 +8,7 @@ import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item
import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import draftNote from '../../batch_comments/components/draft_note.vue';
+import { discussionIntersectionObserverHandlerFactory } from '../../diffs/utils/discussions';
import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility';
import placeholderNote from '../../vue_shared/components/notes/placeholder_note.vue';
import placeholderSystemNote from '../../vue_shared/components/notes/placeholder_system_note.vue';
@@ -38,6 +39,9 @@ export default {
TimelineEntryItem,
},
mixins: [glFeatureFlagsMixin()],
+ provide: {
+ discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
+ },
props: {
noteableData: {
type: Object,
@@ -94,15 +98,17 @@ export default {
return this.noteableData.noteableType;
},
allDiscussions() {
+ let skeletonNotes = [];
+
if (this.renderSkeleton || this.isLoading) {
const prerenderedNotesCount = parseInt(this.notesData.prerenderedNotesCount, 10) || 0;
- return new Array(prerenderedNotesCount).fill({
+ skeletonNotes = new Array(prerenderedNotesCount).fill({
isSkeletonNote: true,
});
}
- return this.discussions;
+ return this.discussions.concat(skeletonNotes);
},
canReply() {
return this.userCanReply && !this.commentsDisabled && !this.timelineEnabled;
@@ -258,7 +264,13 @@ export default {
getFetchDiscussionsConfig() {
const defaultConfig = { path: this.getNotesDataByProp('discussionsPath') };
- if (doesHashExistInUrl(constants.NOTE_UNDERSCORE)) {
+ const currentFilter =
+ this.getNotesDataByProp('notesFilter') || constants.DISCUSSION_FILTERS_DEFAULT_VALUE;
+
+ if (
+ doesHashExistInUrl(constants.NOTE_UNDERSCORE) &&
+ currentFilter !== constants.DISCUSSION_FILTERS_DEFAULT_VALUE
+ ) {
return {
...defaultConfig,
filter: constants.DISCUSSION_FILTERS_DEFAULT_VALUE,
diff --git a/app/assets/javascripts/notes/mixins/discussion_navigation.js b/app/assets/javascripts/notes/mixins/discussion_navigation.js
index 96974c4fa2d..ad529eb99b6 100644
--- a/app/assets/javascripts/notes/mixins/discussion_navigation.js
+++ b/app/assets/javascripts/notes/mixins/discussion_navigation.js
@@ -1,7 +1,10 @@
import { mapGetters, mapActions, mapState } from 'vuex';
import { scrollToElementWithContext, scrollToElement } from '~/lib/utils/common_utils';
+import { updateHistory } from '../../lib/utils/url_utility';
import eventHub from '../event_hub';
+const isDiffsVirtualScrollingEnabled = () => window.gon?.features?.diffsVirtualScrolling;
+
/**
* @param {string} selector
* @returns {boolean}
@@ -11,20 +14,52 @@ function scrollTo(selector, { withoutContext = false } = {}) {
const scrollFunction = withoutContext ? scrollToElement : scrollToElementWithContext;
if (el) {
- scrollFunction(el);
+ scrollFunction(el, {
+ behavior: isDiffsVirtualScrollingEnabled() ? 'auto' : 'smooth',
+ });
return true;
}
return false;
}
+function updateUrlWithNoteId(noteId) {
+ const newHistoryEntry = {
+ state: null,
+ title: window.title,
+ url: `#note_${noteId}`,
+ replace: true,
+ };
+
+ if (noteId && isDiffsVirtualScrollingEnabled()) {
+ // Temporarily mask the ID to avoid the browser default
+ // scrolling taking over which is broken with virtual
+ // scrolling enabled.
+ const note = document.querySelector(`#note_${noteId}`);
+ note?.setAttribute('id', `masked::${note.id}`);
+
+ // Update the hash now that the ID "doesn't exist" in the page
+ updateHistory(newHistoryEntry);
+
+ // Unmask the note's ID
+ note?.setAttribute('id', `note_${noteId}`);
+ } else if (noteId) {
+ updateHistory(newHistoryEntry);
+ }
+}
+
/**
* @param {object} self Component instance with mixin applied
* @param {string} id Discussion id we are jumping to
*/
-function diffsJump({ expandDiscussion }, id) {
+function diffsJump({ expandDiscussion }, id, firstNoteId) {
const selector = `ul.notes[data-discussion-id="${id}"]`;
- eventHub.$once('scrollToDiscussion', () => scrollTo(selector));
+
+ eventHub.$once('scrollToDiscussion', () => {
+ scrollTo(selector);
+ // Wait for the discussion scroll before updating to the more specific ID
+ setTimeout(() => updateUrlWithNoteId(firstNoteId), 0);
+ });
expandDiscussion({ discussionId: id });
}
@@ -56,12 +91,13 @@ function switchToDiscussionsTabAndJumpTo(self, id) {
* @param {object} discussion Discussion we are jumping to
*/
function jumpToDiscussion(self, discussion) {
- const { id, diff_discussion: isDiffDiscussion } = discussion;
+ const { id, diff_discussion: isDiffDiscussion, notes } = discussion;
+ const firstNoteId = notes?.[0]?.id;
if (id) {
const activeTab = window.mrTabs.currentAction;
if (activeTab === 'diffs' && isDiffDiscussion) {
- diffsJump(self, id);
+ diffsJump(self, id, firstNoteId);
} else if (activeTab === 'show') {
discussionJump(self, id);
} else {
@@ -79,10 +115,18 @@ function handleDiscussionJump(self, fn, discussionId = self.currentDiscussionId)
const isDiffView = window.mrTabs.currentAction === 'diffs';
const targetId = fn(discussionId, isDiffView);
const discussion = self.getDiscussion(targetId);
+ const setHash = !isDiffView && !isDiffsVirtualScrollingEnabled();
const discussionFilePath = discussion?.diff_file?.file_path;
+ if (isDiffsVirtualScrollingEnabled()) {
+ window.location.hash = '';
+ }
+
if (discussionFilePath) {
- self.scrollToFile(discussionFilePath);
+ self.scrollToFile({
+ path: discussionFilePath,
+ setHash,
+ });
}
self.$nextTick(() => {
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index 7eb10f647a0..c862a29ad9c 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -1,4 +1,3 @@
-/* eslint-disable @gitlab/require-string-literal-i18n-helpers */
import $ from 'jquery';
import Visibility from 'visibilityjs';
import Vue from 'vue';
@@ -71,7 +70,7 @@ export const setUserData = ({ commit }, data) => commit(types.SET_USER_DATA, dat
export const setLastFetchedAt = ({ commit }, data) => commit(types.SET_LAST_FETCHED_AT, data);
export const setInitialNotes = ({ commit }, discussions) =>
- commit(types.SET_INITIAL_DISCUSSIONS, discussions);
+ commit(types.ADD_OR_UPDATE_DISCUSSIONS, discussions);
export const setTargetNoteHash = ({ commit }, data) => commit(types.SET_TARGET_NOTE_HASH, data);
@@ -90,14 +89,51 @@ export const fetchDiscussions = ({ commit, dispatch }, { path, filter, persistFi
? { params: { notes_filter: filter, persist_filter: persistFilter } }
: null;
+ if (window.gon?.features?.paginatedIssueDiscussions) {
+ return dispatch('fetchDiscussionsBatch', { path, config, perPage: 20 });
+ }
+
return axios.get(path, config).then(({ data }) => {
- commit(types.SET_INITIAL_DISCUSSIONS, data);
+ commit(types.ADD_OR_UPDATE_DISCUSSIONS, data);
commit(types.SET_FETCHING_DISCUSSIONS, false);
dispatch('updateResolvableDiscussionsCounts');
});
};
+export const fetchDiscussionsBatch = ({ commit, dispatch }, { path, config, cursor, perPage }) => {
+ const params = { ...config?.params, per_page: perPage };
+
+ if (cursor) {
+ params.cursor = cursor;
+ }
+
+ return axios.get(path, { params }).then(({ data, headers }) => {
+ commit(types.ADD_OR_UPDATE_DISCUSSIONS, data);
+
+ if (headers['x-next-page-cursor']) {
+ const nextConfig = { ...config };
+
+ if (config?.params?.persist_filter) {
+ delete nextConfig.params.notes_filter;
+ delete nextConfig.params.persist_filter;
+ }
+
+ return dispatch('fetchDiscussionsBatch', {
+ path,
+ config: nextConfig,
+ cursor: headers['x-next-page-cursor'],
+ perPage: Math.min(Math.round(perPage * 1.5), 100),
+ });
+ }
+
+ commit(types.SET_FETCHING_DISCUSSIONS, false);
+ dispatch('updateResolvableDiscussionsCounts');
+
+ return undefined;
+ });
+};
+
export const updateDiscussion = ({ commit, state }, discussion) => {
commit(types.UPDATE_DISCUSSION, discussion);
@@ -621,7 +657,7 @@ export const submitSuggestion = (
const flashMessage = errorMessage || defaultMessage;
createFlash({
- message: __(flashMessage),
+ message: flashMessage,
parent: flashContainer,
});
})
@@ -657,7 +693,7 @@ export const submitSuggestionBatch = ({ commit, dispatch, state }, { message, fl
const flashMessage = errorMessage || defaultMessage;
createFlash({
- message: __(flashMessage),
+ message: flashMessage,
parent: flashContainer,
});
})
diff --git a/app/assets/javascripts/notes/stores/mutation_types.js b/app/assets/javascripts/notes/stores/mutation_types.js
index 2e8b728e013..fcd2846ff0d 100644
--- a/app/assets/javascripts/notes/stores/mutation_types.js
+++ b/app/assets/javascripts/notes/stores/mutation_types.js
@@ -1,11 +1,11 @@
export const ADD_NEW_NOTE = 'ADD_NEW_NOTE';
export const ADD_NEW_REPLY_TO_DISCUSSION = 'ADD_NEW_REPLY_TO_DISCUSSION';
+export const ADD_OR_UPDATE_DISCUSSIONS = 'ADD_OR_UPDATE_DISCUSSIONS';
export const DELETE_NOTE = 'DELETE_NOTE';
export const REMOVE_PLACEHOLDER_NOTES = 'REMOVE_PLACEHOLDER_NOTES';
export const SET_NOTES_DATA = 'SET_NOTES_DATA';
export const SET_NOTEABLE_DATA = 'SET_NOTEABLE_DATA';
export const SET_USER_DATA = 'SET_USER_DATA';
-export const SET_INITIAL_DISCUSSIONS = 'SET_INITIAL_DISCUSSIONS';
export const SET_LAST_FETCHED_AT = 'SET_LAST_FETCHED_AT';
export const SET_TARGET_NOTE_HASH = 'SET_TARGET_NOTE_HASH';
export const SHOW_PLACEHOLDER_NOTE = 'SHOW_PLACEHOLDER_NOTE';
diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js
index c5fa34dfedd..1a99750ddb3 100644
--- a/app/assets/javascripts/notes/stores/mutations.js
+++ b/app/assets/javascripts/notes/stores/mutations.js
@@ -129,8 +129,8 @@ export default {
Object.assign(state, { userData: data });
},
- [types.SET_INITIAL_DISCUSSIONS](state, discussionsData) {
- const discussions = discussionsData.reduce((acc, d) => {
+ [types.ADD_OR_UPDATE_DISCUSSIONS](state, discussionsData) {
+ discussionsData.forEach((d) => {
const discussion = { ...d };
const diffData = {};
@@ -145,27 +145,38 @@ export default {
// To support legacy notes, should be very rare case.
if (discussion.individual_note && discussion.notes.length > 1) {
discussion.notes.forEach((n) => {
- acc.push({
+ const newDiscussion = {
...discussion,
...diffData,
notes: [n], // override notes array to only have one item to mimick individual_note
- });
+ };
+ const oldDiscussion = state.discussions.find(
+ (existingDiscussion) =>
+ existingDiscussion.id === discussion.id && existingDiscussion.notes[0].id === n.id,
+ );
+
+ if (oldDiscussion) {
+ state.discussions.splice(state.discussions.indexOf(oldDiscussion), 1, newDiscussion);
+ } else {
+ state.discussions.push(newDiscussion);
+ }
});
} else {
- const oldNote = utils.findNoteObjectById(state.discussions, discussion.id);
+ const oldDiscussion = utils.findNoteObjectById(state.discussions, discussion.id);
- acc.push({
- ...discussion,
- ...diffData,
- expanded: oldNote ? oldNote.expanded : discussion.expanded,
- });
+ if (oldDiscussion) {
+ state.discussions.splice(state.discussions.indexOf(oldDiscussion), 1, {
+ ...discussion,
+ ...diffData,
+ expanded: oldDiscussion.expanded,
+ });
+ } else {
+ state.discussions.push({ ...discussion, ...diffData });
+ }
}
-
- return acc;
- }, []);
-
- Object.assign(state, { discussions });
+ });
},
+
[types.SET_LAST_FETCHED_AT](state, fetchedAt) {
Object.assign(state, { lastFetchedAt: fetchedAt });
},
diff --git a/app/assets/javascripts/packages/list/components/package_search.vue b/app/assets/javascripts/packages/list/components/package_search.vue
deleted file mode 100644
index 869a2c2f641..00000000000
--- a/app/assets/javascripts/packages/list/components/package_search.vue
+++ /dev/null
@@ -1,57 +0,0 @@
-<script>
-import { mapState, mapActions } from 'vuex';
-import { s__ } from '~/locale';
-import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
-import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
-import UrlSync from '~/vue_shared/components/url_sync.vue';
-import { sortableFields } from '../utils';
-import PackageTypeToken from './tokens/package_type_token.vue';
-
-export default {
- tokens: [
- {
- type: 'type',
- icon: 'package',
- title: s__('PackageRegistry|Type'),
- unique: true,
- token: PackageTypeToken,
- operators: OPERATOR_IS_ONLY,
- },
- ],
- components: { RegistrySearch, UrlSync },
- computed: {
- ...mapState({
- isGroupPage: (state) => state.config.isGroupPage,
- sorting: (state) => state.sorting,
- filter: (state) => state.filter,
- }),
- sortableFields() {
- return sortableFields(this.isGroupPage);
- },
- },
- methods: {
- ...mapActions(['setSorting', 'setFilter']),
- updateSorting(newValue) {
- this.setSorting(newValue);
- this.$emit('update');
- },
- },
-};
-</script>
-
-<template>
- <url-sync>
- <template #default="{ updateQuery }">
- <registry-search
- :filter="filter"
- :sorting="sorting"
- :tokens="$options.tokens"
- :sortable-fields="sortableFields"
- @sorting:changed="updateSorting"
- @filter:changed="setFilter"
- @filter:submit="$emit('update')"
- @query:changed="updateQuery"
- />
- </template>
- </url-sync>
-</template>
diff --git a/app/assets/javascripts/packages/list/components/package_title.vue b/app/assets/javascripts/packages/list/components/package_title.vue
deleted file mode 100644
index 426ad150ea9..00000000000
--- a/app/assets/javascripts/packages/list/components/package_title.vue
+++ /dev/null
@@ -1,47 +0,0 @@
-<script>
-import { n__ } from '~/locale';
-import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
-import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '../constants';
-
-export default {
- name: 'PackageTitle',
- components: {
- TitleArea,
- MetadataItem,
- },
- props: {
- count: {
- type: Number,
- required: false,
- default: null,
- },
- helpUrl: {
- type: String,
- required: true,
- },
- },
- computed: {
- showPackageCount() {
- return Number.isInteger(this.count);
- },
- packageAmountText() {
- return n__(`%d Package`, `%d Packages`, this.count);
- },
- infoMessages() {
- return [{ text: LIST_INTRO_TEXT, link: this.helpUrl }];
- },
- },
- i18n: {
- LIST_TITLE_TEXT,
- },
-};
-</script>
-
-<template>
- <title-area :title="$options.i18n.LIST_TITLE_TEXT" :info-messages="infoMessages">
- <template #metadata-amount>
- <metadata-item v-if="showPackageCount" icon="package" :text="packageAmountText" />
- </template>
- </title-area>
-</template>
diff --git a/app/assets/javascripts/packages/list/components/packages_list_app.vue b/app/assets/javascripts/packages/list/components/packages_list_app.vue
index 4c5fb0ee7c9..31d90fa4dee 100644
--- a/app/assets/javascripts/packages/list/components/packages_list_app.vue
+++ b/app/assets/javascripts/packages/list/components/packages_list_app.vue
@@ -7,6 +7,8 @@ import { s__ } from '~/locale';
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import { getQueryParams, extractFilterAndSorting } from '~/packages_and_registries/shared/utils';
+import InfrastructureTitle from '~/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue';
+import InfrastructureSearch from '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue';
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '../constants';
import PackageList from './packages_list.vue';
@@ -16,28 +18,10 @@ export default {
GlLink,
GlSprintf,
PackageList,
- PackageTitle: () =>
- import(/* webpackChunkName: 'package_registry_components' */ './package_title.vue'),
- PackageSearch: () =>
- import(/* webpackChunkName: 'package_registry_components' */ './package_search.vue'),
- InfrastructureTitle: () =>
- import(
- /* webpackChunkName: 'infrastructure_registry_components' */ '~/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue'
- ),
- InfrastructureSearch: () =>
- import(
- /* webpackChunkName: 'infrastructure_registry_components' */ '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue'
- ),
+ InfrastructureTitle,
+ InfrastructureSearch,
},
inject: {
- titleComponent: {
- from: 'titleComponent',
- default: 'PackageTitle',
- },
- searchComponent: {
- from: 'searchComponent',
- default: 'PackageSearch',
- },
emptyPageTitle: {
from: 'emptyPageTitle',
default: s__('PackageRegistry|There are no packages yet'),
@@ -111,8 +95,8 @@ export default {
<template>
<div>
- <component :is="titleComponent" :help-url="packageHelpUrl" :count="packagesCount" />
- <component :is="searchComponent" @update="requestPackagesList" />
+ <infrastructure-title :help-url="packageHelpUrl" :count="packagesCount" />
+ <infrastructure-search @update="requestPackagesList" />
<package-list @page:changed="onPageChanged" @package:delete="onPackageDeleteRequest">
<template #empty-state>
diff --git a/app/assets/javascripts/packages/list/components/tokens/package_type_token.vue b/app/assets/javascripts/packages/list/components/tokens/package_type_token.vue
deleted file mode 100644
index 74b6774712e..00000000000
--- a/app/assets/javascripts/packages/list/components/tokens/package_type_token.vue
+++ /dev/null
@@ -1,26 +0,0 @@
-<script>
-import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
-import { PACKAGE_TYPES } from '../../constants';
-
-export default {
- components: {
- GlFilteredSearchToken,
- GlFilteredSearchSuggestion,
- },
- PACKAGE_TYPES,
-};
-</script>
-
-<template>
- <gl-filtered-search-token v-bind="{ ...$attrs }" v-on="$listeners">
- <template #suggestions>
- <gl-filtered-search-suggestion
- v-for="(type, index) in $options.PACKAGE_TYPES"
- :key="index"
- :value="type.type"
- >
- {{ type.title }}
- </gl-filtered-search-suggestion>
- </template>
- </gl-filtered-search-token>
-</template>
diff --git a/app/assets/javascripts/packages/list/constants.js b/app/assets/javascripts/packages/list/constants.js
index 2c6fd94024e..4f5071e784b 100644
--- a/app/assets/javascripts/packages/list/constants.js
+++ b/app/assets/javascripts/packages/list/constants.js
@@ -96,10 +96,4 @@ export const PACKAGE_TYPES = [
},
];
-export const LIST_TITLE_TEXT = s__('PackageRegistry|Package Registry');
-
-export const LIST_INTRO_TEXT = s__(
- 'PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}',
-);
-
export const TERRAFORM_SEARCH_TYPE = Object.freeze({ value: { data: 'terraform_module' } });
diff --git a/app/assets/javascripts/registry/explorer/components/delete_button.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/delete_button.vue
index e4a1a1a8266..e4a1a1a8266 100644
--- a/app/assets/javascripts/registry/explorer/components/delete_button.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/delete_button.vue
diff --git a/app/assets/javascripts/registry/explorer/components/delete_image.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/delete_image.vue
index a313854f5e4..a313854f5e4 100644
--- a/app/assets/javascripts/registry/explorer/components/delete_image.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/delete_image.vue
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/delete_alert.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/delete_alert.vue
index 56d2ff86fb7..56d2ff86fb7 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/delete_alert.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/delete_alert.vue
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/delete_modal.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/delete_modal.vue
index f857c96c9d1..f857c96c9d1 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/delete_modal.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/delete_modal.vue
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/details_header.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue
index e9e36151fe6..e9e36151fe6 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/details_header.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/empty_state.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/empty_state.vue
index a16d95a6b30..a16d95a6b30 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/empty_state.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/empty_state.vue
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/partial_cleanup_alert.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert.vue
index 12095655126..12095655126 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/partial_cleanup_alert.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert.vue
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/status_alert.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/status_alert.vue
index fc1504f6c31..fc1504f6c31 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/status_alert.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/status_alert.vue
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
index 3e19a646f53..3e19a646f53 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue
index 0556fd298aa..0556fd298aa 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/tags_loader.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue
index b7afa5fba33..b7afa5fba33 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/tags_loader.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/cleanup_status.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue
index 1f52e319ad0..1f52e319ad0 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/cleanup_status.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/cli_commands.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cli_commands.vue
index 07ee3c6083b..07ee3c6083b 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/cli_commands.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cli_commands.vue
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/group_empty_state.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state.vue
index a68c4de5aa6..a68c4de5aa6 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/group_empty_state.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state.vue
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/image_list.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list.vue
index 5bd13322ebb..5bd13322ebb 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/image_list.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list.vue
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue
index c1ec523574a..c1ec523574a 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/project_empty_state.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state.vue
index 5aa04419ca0..5aa04419ca0 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/project_empty_state.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state.vue
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue
index 6d2ff9ea7b6..6d2ff9ea7b6 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue
diff --git a/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/registry_breadcrumb.vue
index e77eda31596..e77eda31596 100644
--- a/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/registry_breadcrumb.vue
diff --git a/app/assets/javascripts/registry/explorer/constants/common.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/common.js
index f7beec2c935..f7beec2c935 100644
--- a/app/assets/javascripts/registry/explorer/constants/common.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/common.js
diff --git a/app/assets/javascripts/registry/explorer/constants/details.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/details.js
index 19e1a75fb2f..19e1a75fb2f 100644
--- a/app/assets/javascripts/registry/explorer/constants/details.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/details.js
diff --git a/app/assets/javascripts/registry/explorer/constants/expiration_policies.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/expiration_policies.js
index 40f9b09a982..40f9b09a982 100644
--- a/app/assets/javascripts/registry/explorer/constants/expiration_policies.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/expiration_policies.js
diff --git a/app/assets/javascripts/registry/explorer/constants/index.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/index.js
index 6886356d8e2..6886356d8e2 100644
--- a/app/assets/javascripts/registry/explorer/constants/index.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/index.js
diff --git a/app/assets/javascripts/registry/explorer/constants/list.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/list.js
index d21a154d1b8..d21a154d1b8 100644
--- a/app/assets/javascripts/registry/explorer/constants/list.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/list.js
diff --git a/app/assets/javascripts/registry/explorer/constants/quick_start.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/quick_start.js
index 6a39c07eba2..6a39c07eba2 100644
--- a/app/assets/javascripts/registry/explorer/constants/quick_start.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/constants/quick_start.js
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/index.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/index.js
new file mode 100644
index 00000000000..9694bfd4e77
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/index.js
@@ -0,0 +1,14 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+
+Vue.use(VueApollo);
+
+export const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(
+ {},
+ {
+ batchMax: 1,
+ },
+ ),
+});
diff --git a/app/assets/javascripts/registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql
index 4c88b726ee5..4c88b726ee5 100644
--- a/app/assets/javascripts/registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql
diff --git a/app/assets/javascripts/registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql
index a31f2829e13..a31f2829e13 100644
--- a/app/assets/javascripts/registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql
diff --git a/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repositories_details.query.graphql
index 01cb7fa1cab..01cb7fa1cab 100644
--- a/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repositories_details.query.graphql
diff --git a/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_details.query.graphql b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql
index b5a99fd9ac1..b5a99fd9ac1 100644
--- a/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_details.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql
diff --git a/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_tags.query.graphql b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql
index a703c2dd0ac..a703c2dd0ac 100644
--- a/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_tags.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql
diff --git a/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_tags_count.query.graphql b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags_count.query.graphql
index 9092a71edb0..9092a71edb0 100644
--- a/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_tags_count.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags_count.query.graphql
diff --git a/app/assets/javascripts/registry/explorer/index.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js
index 246a6768593..246a6768593 100644
--- a/app/assets/javascripts/registry/explorer/index.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js
diff --git a/app/assets/javascripts/registry/explorer/pages/details.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
index feabc4f770b..feabc4f770b 100644
--- a/app/assets/javascripts/registry/explorer/pages/details.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
diff --git a/app/assets/javascripts/registry/explorer/pages/index.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/index.vue
index dca63e1a569..dca63e1a569 100644
--- a/app/assets/javascripts/registry/explorer/pages/index.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/index.vue
diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue
index 73b957f42f2..73b957f42f2 100644
--- a/app/assets/javascripts/registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue
diff --git a/app/assets/javascripts/registry/explorer/router.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/router.js
index a0c4417d549..a0c4417d549 100644
--- a/app/assets/javascripts/registry/explorer/router.js
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/router.js
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
index 73fb3656af1..71e8cf4f634 100644
--- a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
@@ -1,32 +1,49 @@
<script>
-import { GlAlert, GlFormGroup, GlFormInputGroup, GlSkeletonLoader, GlSprintf } from '@gitlab/ui';
-import { __ } from '~/locale';
+import {
+ GlAlert,
+ GlFormGroup,
+ GlFormInputGroup,
+ GlSkeletonLoader,
+ GlSprintf,
+ GlEmptyState,
+} from '@gitlab/ui';
+import { s__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+import ManifestsList from '~/packages_and_registries/dependency_proxy/components/manifests_list.vue';
import {
DEPENDENCY_PROXY_SETTINGS_DESCRIPTION,
DEPENDENCY_PROXY_DOCS_PATH,
} from '~/packages_and_registries/settings/group/constants';
+import { GRAPHQL_PAGE_SIZE } from '~/packages_and_registries/dependency_proxy/constants';
import getDependencyProxyDetailsQuery from '~/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql';
export default {
components: {
- GlFormGroup,
GlAlert,
+ GlEmptyState,
+ GlFormGroup,
GlFormInputGroup,
+ GlSkeletonLoader,
GlSprintf,
ClipboardButton,
TitleArea,
- GlSkeletonLoader,
+ ManifestsList,
},
- inject: ['groupPath', 'dependencyProxyAvailable'],
+ inject: ['groupPath', 'dependencyProxyAvailable', 'noManifestsIllustration'],
i18n: {
- proxyNotAvailableText: __('Dependency Proxy feature is limited to public groups for now.'),
- proxyDisabledText: __('Dependency Proxy disabled. To enable it, contact the group owner.'),
- proxyImagePrefix: __('Dependency Proxy image prefix'),
- copyImagePrefixText: __('Copy prefix'),
- blobCountAndSize: __('Contains %{count} blobs of images (%{size})'),
+ proxyNotAvailableText: s__(
+ 'DependencyProxy|Dependency Proxy feature is limited to public groups for now.',
+ ),
+ proxyDisabledText: s__(
+ 'DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner.',
+ ),
+ proxyImagePrefix: s__('DependencyProxy|Dependency Proxy image prefix'),
+ copyImagePrefixText: s__('DependencyProxy|Copy prefix'),
+ blobCountAndSize: s__('DependencyProxy|Contains %{count} blobs of images (%{size})'),
+ pageTitle: s__('DependencyProxy|Dependency Proxy'),
+ noManifestTitle: s__('DependencyProxy|There are no images in the cache'),
},
data() {
return {
@@ -40,7 +57,7 @@ export default {
return !this.dependencyProxyAvailable;
},
variables() {
- return { fullPath: this.groupPath };
+ return this.queryVariables;
},
},
},
@@ -56,13 +73,45 @@ export default {
dependencyProxyEnabled() {
return this.group?.dependencyProxySetting?.enabled;
},
+ queryVariables() {
+ return { fullPath: this.groupPath, first: GRAPHQL_PAGE_SIZE };
+ },
+ pageInfo() {
+ return this.group.dependencyProxyManifests.pageInfo;
+ },
+ manifests() {
+ return this.group.dependencyProxyManifests.nodes;
+ },
+ },
+ methods: {
+ fetchNextPage() {
+ this.fetchMore({
+ first: GRAPHQL_PAGE_SIZE,
+ after: this.pageInfo?.endCursor,
+ });
+ },
+ fetchPreviousPage() {
+ this.fetchMore({
+ first: null,
+ last: GRAPHQL_PAGE_SIZE,
+ before: this.pageInfo?.startCursor,
+ });
+ },
+ fetchMore(variables) {
+ this.$apollo.queries.group.fetchMore({
+ variables: { ...this.queryVariables, ...variables },
+ updateQuery(_, { fetchMoreResult }) {
+ return fetchMoreResult;
+ },
+ });
+ },
},
};
</script>
<template>
<div>
- <title-area :title="__('Dependency Proxy')" :info-messages="infoMessages" />
+ <title-area :title="$options.i18n.pageTitle" :info-messages="infoMessages" />
<gl-alert
v-if="!dependencyProxyAvailable"
:dismissible="false"
@@ -97,6 +146,20 @@ export default {
</span>
</template>
</gl-form-group>
+
+ <manifests-list
+ v-if="manifests && manifests.length"
+ :manifests="manifests"
+ :pagination="pageInfo"
+ @prev-page="fetchPreviousPage"
+ @next-page="fetchNextPage"
+ />
+
+ <gl-empty-state
+ v-else
+ :svg-path="noManifestsIllustration"
+ :title="$options.i18n.noManifestTitle"
+ />
</div>
<gl-alert v-else :dismissible="false" data-testid="proxy-disabled">
{{ $options.i18n.proxyDisabledText }}
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifest_row.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifest_row.vue
new file mode 100644
index 00000000000..78880b6e3f4
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifest_row.vue
@@ -0,0 +1,49 @@
+<script>
+import { GlSprintf } from '@gitlab/ui';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
+import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import { s__ } from '~/locale';
+
+export default {
+ name: 'ManifestRow',
+ components: {
+ GlSprintf,
+ ListItem,
+ TimeagoTooltip,
+ },
+ props: {
+ manifest: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ name() {
+ return this.manifest?.imageName.split(':')[0];
+ },
+ version() {
+ return this.manifest?.imageName.split(':')[1];
+ },
+ },
+ i18n: {
+ cachedAgoMessage: s__('DependencyProxy|Cached %{time}'),
+ },
+};
+</script>
+
+<template>
+ <list-item>
+ <template #left-primary> {{ name }} </template>
+ <template #left-secondary> {{ version }} </template>
+ <template #right-primary> &nbsp; </template>
+ <template #right-secondary>
+ <timeago-tooltip :time="manifest.createdAt" data-testid="cached-message">
+ <template #default="{ timeAgo }">
+ <gl-sprintf :message="$options.i18n.cachedAgoMessage">
+ <template #time>{{ timeAgo }}</template>
+ </gl-sprintf>
+ </template>
+ </timeago-tooltip>
+ </template>
+ </list-item>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue
new file mode 100644
index 00000000000..005c8feea3a
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue
@@ -0,0 +1,52 @@
+<script>
+import { GlKeysetPagination } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import ManifestRow from '~/packages_and_registries/dependency_proxy/components/manifest_row.vue';
+
+export default {
+ name: 'ManifestsLists',
+ components: {
+ ManifestRow,
+ GlKeysetPagination,
+ },
+ props: {
+ manifests: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ pagination: {
+ type: Object,
+ required: true,
+ },
+ },
+ i18n: {
+ listTitle: s__('DependencyProxy|Image list'),
+ },
+ computed: {
+ showPagination() {
+ return this.pagination.hasNextPage || this.pagination.hasPreviousPage;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-mt-6">
+ <h3 class="gl-font-base">{{ $options.i18n.listTitle }}</h3>
+ <div
+ class="gl-border-t-1 gl-border-gray-100 gl-border-t-solid gl-display-flex gl-flex-direction-column"
+ >
+ <manifest-row v-for="(manifest, index) in manifests" :key="index" :manifest="manifest" />
+ </div>
+ <div class="gl-display-flex gl-justify-content-center">
+ <gl-keyset-pagination
+ v-if="showPagination"
+ v-bind="pagination"
+ class="gl-mt-3"
+ @prev="$emit('prev-page')"
+ @next="$emit('next-page')"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/constants.js b/app/assets/javascripts/packages_and_registries/dependency_proxy/constants.js
new file mode 100644
index 00000000000..3c6ede6fdce
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/constants.js
@@ -0,0 +1 @@
+export const GRAPHQL_PAGE_SIZE = 20;
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/index.js b/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/index.js
index 16152eb81f6..56f95fa2c1f 100644
--- a/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/index.js
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/index.js
@@ -5,10 +5,5 @@ import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
export const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- ),
+ defaultClient: createDefaultClient(),
});
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql b/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql
index 9058d349bf3..63d5469c955 100644
--- a/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql
@@ -1,4 +1,12 @@
-query getDependencyProxyDetails($fullPath: ID!) {
+#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
+
+query getDependencyProxyDetails(
+ $fullPath: ID!
+ $first: Int
+ $last: Int
+ $after: String
+ $before: String
+) {
group(fullPath: $fullPath) {
dependencyProxyBlobCount
dependencyProxyTotalSize
@@ -6,5 +14,14 @@ query getDependencyProxyDetails($fullPath: ID!) {
dependencyProxySetting {
enabled
}
+ dependencyProxyManifests(after: $after, before: $before, first: $first, last: $last) {
+ nodes {
+ createdAt
+ imageName
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
}
}
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue
index 3d3fa62fd43..bcbeec72961 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue
@@ -23,6 +23,7 @@ import PackageFiles from '~/packages_and_registries/package_registry/components/
import PackageHistory from '~/packages_and_registries/package_registry/components/details/package_history.vue';
import PackageTitle from '~/packages_and_registries/package_registry/components/details/package_title.vue';
import VersionRow from '~/packages_and_registries/package_registry/components/details/version_row.vue';
+import DeletePackage from '~/packages_and_registries/package_registry/components/functional/delete_package.vue';
import {
PACKAGE_TYPE_NUGET,
PACKAGE_TYPE_COMPOSER,
@@ -35,12 +36,10 @@ import {
CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
SHOW_DELETE_SUCCESS_ALERT,
FETCH_PACKAGE_DETAILS_ERROR_MESSAGE,
- DELETE_PACKAGE_ERROR_MESSAGE,
DELETE_PACKAGE_FILE_ERROR_MESSAGE,
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
} from '~/packages_and_registries/package_registry/constants';
-import destroyPackageMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package.mutation.graphql';
import destroyPackageFileMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_file.mutation.graphql';
import getPackageDetails from '~/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql';
import Tracking from '~/tracking';
@@ -62,6 +61,7 @@ export default {
AdditionalMetadata,
InstallationCommands,
PackageFiles,
+ DeletePackage,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -148,40 +148,15 @@ export default {
formatSize(size) {
return numberToHumanSize(size);
},
- async deletePackage() {
- const { data } = await this.$apollo.mutate({
- mutation: destroyPackageMutation,
- variables: {
- id: this.packageEntity.id,
- },
- });
+ navigateToListWithSuccessModal() {
+ const returnTo =
+ !this.groupListUrl || document.referrer.includes(this.projectName)
+ ? this.projectListUrl
+ : this.groupListUrl; // to avoid security issue url are supplied from backend
- if (data?.destroyPackage?.errors[0]) {
- throw data.destroyPackage.errors[0];
- }
- },
- async confirmPackageDeletion() {
- this.track(DELETE_PACKAGE_TRACKING_ACTION);
-
- try {
- await this.deletePackage();
-
- const returnTo =
- !this.groupListUrl || document.referrer.includes(this.projectName)
- ? this.projectListUrl
- : this.groupListUrl; // to avoid security issue url are supplied from backend
-
- const modalQuery = objectToQuery({ [SHOW_DELETE_SUCCESS_ALERT]: true });
+ const modalQuery = objectToQuery({ [SHOW_DELETE_SUCCESS_ALERT]: true });
- window.location.replace(`${returnTo}?${modalQuery}`);
- } catch (error) {
- createFlash({
- message: DELETE_PACKAGE_ERROR_MESSAGE,
- type: 'warning',
- captureError: true,
- error,
- });
- }
+ window.location.replace(`${returnTo}?${modalQuery}`);
},
async deletePackageFile(id) {
try {
@@ -322,26 +297,33 @@ export default {
</gl-tab>
</gl-tabs>
- <gl-modal
- ref="deleteModal"
- modal-id="delete-modal"
- data-testid="delete-modal"
- :action-primary="$options.modal.packageDeletePrimaryAction"
- :action-cancel="$options.modal.cancelAction"
- @primary="confirmPackageDeletion"
- @canceled="track($options.trackingActions.CANCEL_DELETE_PACKAGE)"
+ <delete-package
+ @start="track($options.trackingActions.DELETE_PACKAGE_TRACKING_ACTION)"
+ @end="navigateToListWithSuccessModal"
>
- <template #modal-title>{{ $options.i18n.deleteModalTitle }}</template>
- <gl-sprintf :message="$options.i18n.deleteModalContent">
- <template #version>
- <strong>{{ packageEntity.version }}</strong>
- </template>
+ <template #default="{ deletePackage }">
+ <gl-modal
+ ref="deleteModal"
+ modal-id="delete-modal"
+ data-testid="delete-modal"
+ :action-primary="$options.modal.packageDeletePrimaryAction"
+ :action-cancel="$options.modal.cancelAction"
+ @primary="deletePackage(packageEntity)"
+ @canceled="track($options.trackingActions.CANCEL_DELETE_PACKAGE)"
+ >
+ <template #modal-title>{{ $options.i18n.deleteModalTitle }}</template>
+ <gl-sprintf :message="$options.i18n.deleteModalContent">
+ <template #version>
+ <strong>{{ packageEntity.version }}</strong>
+ </template>
- <template #name>
- <strong>{{ packageEntity.name }}</strong>
- </template>
- </gl-sprintf>
- </gl-modal>
+ <template #name>
+ <strong>{{ packageEntity.name }}</strong>
+ </template>
+ </gl-sprintf>
+ </gl-modal>
+ </template>
+ </delete-package>
<gl-modal
ref="deleteFileModal"
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/functional/delete_package.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/functional/delete_package.vue
new file mode 100644
index 00000000000..7a85fd3052e
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/functional/delete_package.vue
@@ -0,0 +1,62 @@
+<script>
+import destroyPackageMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package.mutation.graphql';
+import createFlash from '~/flash';
+import { s__ } from '~/locale';
+
+import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages_and_registries/package_registry/constants';
+
+export default {
+ props: {
+ refetchQueries: {
+ type: Array,
+ required: false,
+ default: null,
+ },
+ showSuccessAlert: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ i18n: {
+ errorMessage: s__('PackageRegistry|Something went wrong while deleting the package.'),
+ successMessage: DELETE_PACKAGE_SUCCESS_MESSAGE,
+ },
+ methods: {
+ async deletePackage(packageEntity) {
+ try {
+ this.$emit('start');
+ const { data } = await this.$apollo.mutate({
+ mutation: destroyPackageMutation,
+ variables: {
+ id: packageEntity.id,
+ },
+ awaitRefetchQueries: Boolean(this.refetchQueries),
+ refetchQueries: this.refetchQueries,
+ });
+
+ if (data?.destroyPackage?.errors[0]) {
+ throw data.destroyPackage.errors[0];
+ }
+ if (this.showSuccessAlert) {
+ createFlash({
+ message: this.$options.i18n.successMessage,
+ type: 'success',
+ });
+ }
+ } catch (error) {
+ createFlash({
+ message: this.$options.i18n.errorMessage,
+ type: 'warning',
+ captureError: true,
+ error,
+ });
+ }
+ this.$emit('end');
+ },
+ },
+ render() {
+ return this.$scopedSlots.default({ deletePackage: this.deletePackage });
+ },
+};
+</script>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/app.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/app.vue
index 08481ac5655..11eeaf933ff 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/app.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/app.vue
@@ -1,33 +1,31 @@
<script>
-/*
- * The following component has several commented lines, this is because we are refactoring them piece by piece on several mrs
- * For a complete overview of the plan please check: https://gitlab.com/gitlab-org/gitlab/-/issues/330846
- * This work is behind feature flag: https://gitlab.com/gitlab-org/gitlab/-/issues/341136
- */
-// import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
+import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
import createFlash from '~/flash';
import { historyReplaceState } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
-import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages/list/constants';
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
-import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';
import {
PROJECT_RESOURCE_TYPE,
GROUP_RESOURCE_TYPE,
- LIST_QUERY_DEBOUNCE_TIME,
+ GRAPHQL_PAGE_SIZE,
+ DELETE_PACKAGE_SUCCESS_MESSAGE,
} from '~/packages_and_registries/package_registry/constants';
+import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';
+
+import DeletePackage from '~/packages_and_registries/package_registry/components/functional/delete_package.vue';
import PackageTitle from './package_title.vue';
import PackageSearch from './package_search.vue';
-// import PackageList from './packages_list.vue';
+import PackageList from './packages_list.vue';
export default {
components: {
- // GlEmptyState,
- // GlLink,
- // GlSprintf,
- // PackageList,
+ GlEmptyState,
+ GlLink,
+ GlSprintf,
+ PackageList,
PackageTitle,
PackageSearch,
+ DeletePackage,
},
inject: [
'packageHelpUrl',
@@ -41,6 +39,7 @@ export default {
packages: {},
sort: '',
filters: {},
+ mutationLoading: false,
};
},
apollo: {
@@ -52,7 +51,9 @@ export default {
update(data) {
return data[this.graphqlResource].packages;
},
- debounce: LIST_QUERY_DEBOUNCE_TIME,
+ skip() {
+ return !this.sort;
+ },
},
},
computed: {
@@ -64,22 +65,40 @@ export default {
groupSort: this.isGroupPage ? this.sort : undefined,
packageName: this.filters?.packageName,
packageType: this.filters?.packageType,
+ first: GRAPHQL_PAGE_SIZE,
};
},
graphqlResource() {
return this.isGroupPage ? GROUP_RESOURCE_TYPE : PROJECT_RESOURCE_TYPE;
},
+ pageInfo() {
+ return this.packages?.pageInfo ?? {};
+ },
packagesCount() {
return this.packages?.count;
},
hasFilters() {
return this.filters.packageName && this.filters.packageType;
},
+ emptySearch() {
+ return !this.filters.packageName && !this.filters.packageType;
+ },
emptyStateTitle() {
return this.emptySearch
? this.$options.i18n.emptyPageTitle
: this.$options.i18n.noResultsTitle;
},
+ isLoading() {
+ return this.$apollo.queries.packages.loading || this.mutationLoading;
+ },
+ refetchQueriesData() {
+ return [
+ {
+ query: getPackagesQuery,
+ variables: this.queryVariables,
+ },
+ ];
+ },
},
mounted() {
this.checkDeleteAlert();
@@ -99,6 +118,35 @@ export default {
this.sort = sort;
this.filters = { ...filters };
},
+ updateQuery(_, { fetchMoreResult }) {
+ return fetchMoreResult;
+ },
+ fetchNextPage() {
+ const variables = {
+ ...this.queryVariables,
+ first: GRAPHQL_PAGE_SIZE,
+ last: null,
+ after: this.pageInfo?.endCursor,
+ };
+
+ this.$apollo.queries.packages.fetchMore({
+ variables,
+ updateQuery: this.updateQuery,
+ });
+ },
+ fetchPreviousPage() {
+ const variables = {
+ ...this.queryVariables,
+ first: null,
+ last: GRAPHQL_PAGE_SIZE,
+ before: this.pageInfo?.startCursor,
+ };
+
+ this.$apollo.queries.packages.fetchMore({
+ variables,
+ updateQuery: this.updateQuery,
+ });
+ },
},
i18n: {
widenFilters: s__('PackageRegistry|To widen your search, change or remove the filters above.'),
@@ -116,19 +164,35 @@ export default {
<package-title :help-url="packageHelpUrl" :count="packagesCount" />
<package-search @update="handleSearchUpdate" />
- <!-- <package-list @page:changed="onPageChanged" @package:delete="onPackageDeleteRequest">
- <template #empty-state>
- <gl-empty-state :title="emptyStateTitle" :svg-path="emptyListIllustration">
- <template #description>
- <gl-sprintf v-if="hasFilters" :message="$options.i18n.widenFilters" />
- <gl-sprintf v-else :message="$options.i18n.noResultsText">
- <template #noPackagesLink="{ content }">
- <gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link>
+ <delete-package
+ :refetch-queries="refetchQueriesData"
+ show-success-alert
+ @start="mutationLoading = true"
+ @end="mutationLoading = false"
+ >
+ <template #default="{ deletePackage }">
+ <package-list
+ :list="packages.nodes"
+ :is-loading="isLoading"
+ :page-info="pageInfo"
+ @prev-page="fetchPreviousPage"
+ @next-page="fetchNextPage"
+ @package:delete="deletePackage"
+ >
+ <template #empty-state>
+ <gl-empty-state :title="emptyStateTitle" :svg-path="emptyListIllustration">
+ <template #description>
+ <gl-sprintf v-if="hasFilters" :message="$options.i18n.widenFilters" />
+ <gl-sprintf v-else :message="$options.i18n.noResultsText">
+ <template #noPackagesLink="{ content }">
+ <gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
</template>
- </gl-sprintf>
+ </gl-empty-state>
</template>
- </gl-empty-state>
+ </package-list>
</template>
- </package-list> -->
+ </delete-package>
</div>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue
index 836df59ca58..3483d23e251 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue
@@ -1,6 +1,6 @@
<script>
import { s__ } from '~/locale';
-import { sortableFields } from '~/packages/list/utils';
+import { sortableFields } from '~/packages_and_registries/package_registry/utils';
import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_title.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_title.vue
index 6e00a48586e..bf41c36e09b 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_title.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_title.vue
@@ -1,6 +1,5 @@
<script>
-import { n__ } from '~/locale';
-import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '~/packages/list/constants';
+import { n__, s__ } from '~/locale';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
@@ -29,11 +28,14 @@ export default {
return n__(`%d Package`, `%d Packages`, this.count);
},
infoMessages() {
- return [{ text: LIST_INTRO_TEXT, link: this.helpUrl }];
+ return [{ text: this.$options.i18n.LIST_INTRO_TEXT, link: this.helpUrl }];
},
},
i18n: {
- LIST_TITLE_TEXT,
+ LIST_TITLE_TEXT: s__('PackageRegistry|Package Registry'),
+ LIST_INTRO_TEXT: s__(
+ 'PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}',
+ ),
},
};
</script>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue
index 25bac687dbf..2a946544c2f 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue
@@ -1,82 +1,94 @@
<script>
-import { GlPagination, GlModal, GlSprintf } from '@gitlab/ui';
-import { mapState, mapGetters } from 'vuex';
+import { GlModal, GlSprintf, GlKeysetPagination } from '@gitlab/ui';
import { s__ } from '~/locale';
-import PackagesListRow from '~/packages/shared/components/package_list_row.vue';
+import PackagesListRow from '~/packages_and_registries/package_registry/components/list/package_list_row.vue';
import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
-import { TrackingActions } from '~/packages/shared/constants';
-import { packageTypeToTrackCategory } from '~/packages/shared/utils';
+import {
+ DELETE_PACKAGE_TRACKING_ACTION,
+ REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
+ CANCEL_DELETE_PACKAGE_TRACKING_ACTION,
+} from '~/packages_and_registries/package_registry/constants';
+import { packageTypeToTrackCategory } from '~/packages_and_registries/package_registry/utils';
import Tracking from '~/tracking';
export default {
components: {
- GlPagination,
+ GlKeysetPagination,
GlModal,
GlSprintf,
PackagesListLoader,
PackagesListRow,
},
mixins: [Tracking.mixin()],
+ props: {
+ list: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ pageInfo: {
+ type: Object,
+ required: true,
+ },
+ },
+
data() {
return {
itemToBeDeleted: null,
};
},
computed: {
- ...mapState({
- perPage: (state) => state.pagination.perPage,
- totalItems: (state) => state.pagination.total,
- page: (state) => state.pagination.page,
- isGroupPage: (state) => state.config.isGroupPage,
- isLoading: 'isLoading',
- }),
- ...mapGetters({ list: 'getList' }),
- currentPage: {
- get() {
- return this.page;
- },
- set(value) {
- this.$emit('page:changed', value);
- },
- },
isListEmpty() {
return !this.list || this.list.length === 0;
},
- modalAction() {
- return s__('PackageRegistry|Delete package');
- },
deletePackageName() {
return this.itemToBeDeleted?.name ?? '';
},
tracking() {
const category = this.itemToBeDeleted
- ? packageTypeToTrackCategory(this.itemToBeDeleted.package_type)
+ ? packageTypeToTrackCategory(this.itemToBeDeleted.packageType)
: undefined;
return {
category,
};
},
+ showPagination() {
+ return this.pageInfo.hasPreviousPage || this.pageInfo.hasNextPage;
+ },
+ showDeleteModal: {
+ get() {
+ return Boolean(this.itemToBeDeleted);
+ },
+ set(value) {
+ if (!value) {
+ this.itemToBeDeleted = null;
+ }
+ },
+ },
},
methods: {
setItemToBeDeleted(item) {
this.itemToBeDeleted = { ...item };
- this.track(TrackingActions.REQUEST_DELETE_PACKAGE);
- this.$refs.packageListDeleteModal.show();
+ this.track(REQUEST_DELETE_PACKAGE_TRACKING_ACTION);
},
deleteItemConfirmation() {
this.$emit('package:delete', this.itemToBeDeleted);
- this.track(TrackingActions.DELETE_PACKAGE);
- this.itemToBeDeleted = null;
+ this.track(DELETE_PACKAGE_TRACKING_ACTION);
},
deleteItemCanceled() {
- this.track(TrackingActions.CANCEL_DELETE_PACKAGE);
- this.itemToBeDeleted = null;
+ this.track(CANCEL_DELETE_PACKAGE_TRACKING_ACTION);
},
},
i18n: {
deleteModalContent: s__(
'PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?',
),
+ modalAction: s__('PackageRegistry|Delete package'),
},
};
</script>
@@ -95,29 +107,29 @@ export default {
v-for="packageEntity in list"
:key="packageEntity.id"
:package-entity="packageEntity"
- :package-link="packageEntity._links.web_path"
- :is-group="isGroupPage"
@packageToDelete="setItemToBeDeleted"
/>
</div>
- <gl-pagination
- v-model="currentPage"
- :per-page="perPage"
- :total-items="totalItems"
- align="center"
- class="gl-w-full gl-mt-3"
- />
+ <div class="gl-display-flex gl-justify-content-center">
+ <gl-keyset-pagination
+ v-if="showPagination"
+ v-bind="pageInfo"
+ class="gl-mt-3"
+ @prev="$emit('prev-page')"
+ @next="$emit('next-page')"
+ />
+ </div>
<gl-modal
- ref="packageListDeleteModal"
+ v-model="showDeleteModal"
modal-id="confirm-delete-pacakge"
ok-variant="danger"
@ok="deleteItemConfirmation"
@cancel="deleteItemCanceled"
>
- <template #modal-title>{{ modalAction }}</template>
- <template #modal-ok>{{ modalAction }}</template>
+ <template #modal-title>{{ $options.i18n.modalAction }}</template>
+ <template #modal-ok>{{ $options.i18n.modalAction }}</template>
<gl-sprintf :message="$options.i18n.deleteModalContent">
<template #name>
<strong>{{ deletePackageName }}</strong>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/tokens/package_type_token.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/tokens/package_type_token.vue
index 529a7893dfc..59354e77ee9 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/tokens/package_type_token.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/tokens/package_type_token.vue
@@ -1,6 +1,6 @@
<script>
import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
-import { PACKAGE_TYPES } from '~/packages/list/constants';
+import { PACKAGE_TYPES } from '~/packages_and_registries/package_registry/constants';
export default {
components: {
@@ -17,9 +17,9 @@ export default {
<gl-filtered-search-suggestion
v-for="(type, index) in $options.PACKAGE_TYPES"
:key="index"
- :value="type.type"
+ :value="type"
>
- {{ type.title }}
+ {{ type }}
</gl-filtered-search-suggestion>
</template>
</gl-filtered-search-token>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/constants.js b/app/assets/javascripts/packages_and_registries/package_registry/constants.js
index 6a88880fa90..9fd8880861c 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/constants.js
+++ b/app/assets/javascripts/packages_and_registries/package_registry/constants.js
@@ -1,4 +1,4 @@
-import { s__ } from '~/locale';
+import { s__, __ } from '~/locale';
export const PACKAGE_TYPE_CONAN = 'CONAN';
export const PACKAGE_TYPE_MAVEN = 'MAVEN';
@@ -59,16 +59,7 @@ export const TRACKING_ACTION_COPY_COMPOSER_REGISTRY_INCLUDE_COMMAND =
export const TRACKING_ACTION_COPY_COMPOSER_PACKAGE_INCLUDE_COMMAND =
'copy_composer_package_include_command';
-export const TrackingCategories = {
- [PACKAGE_TYPE_MAVEN]: 'MavenPackages',
- [PACKAGE_TYPE_NPM]: 'NpmPackages',
- [PACKAGE_TYPE_CONAN]: 'ConanPackages',
-};
-
export const SHOW_DELETE_SUCCESS_ALERT = 'showSuccessDeleteAlert';
-export const DELETE_PACKAGE_ERROR_MESSAGE = s__(
- 'PackageRegistry|Something went wrong while deleting the package.',
-);
export const DELETE_PACKAGE_FILE_ERROR_MESSAGE = s__(
'PackageRegistry|Something went wrong while deleting the package file.',
);
@@ -79,6 +70,8 @@ export const FETCH_PACKAGE_DETAILS_ERROR_MESSAGE = s__(
'PackageRegistry|Failed to load the package data',
);
+export const DELETE_PACKAGE_SUCCESS_MESSAGE = s__('PackageRegistry|Package deleted successfully');
+
export const PACKAGE_ERROR_STATUS = 'ERROR';
export const PACKAGE_DEFAULT_STATUS = 'DEFAULT';
export const PACKAGE_HIDDEN_STATUS = 'HIDDEN';
@@ -92,4 +85,52 @@ export const INSTANCE_PACKAGE_ENDPOINT_TYPE = 'instance';
export const PROJECT_RESOURCE_TYPE = 'project';
export const GROUP_RESOURCE_TYPE = 'group';
-export const LIST_QUERY_DEBOUNCE_TIME = 50;
+export const GRAPHQL_PAGE_SIZE = 20;
+
+export const LIST_KEY_NAME = 'name';
+export const LIST_KEY_PROJECT = 'project_path';
+export const LIST_KEY_VERSION = 'version';
+export const LIST_KEY_PACKAGE_TYPE = 'type';
+export const LIST_KEY_CREATED_AT = 'created_at';
+
+export const LIST_LABEL_NAME = __('Name');
+export const LIST_LABEL_PROJECT = __('Project');
+export const LIST_LABEL_VERSION = __('Version');
+export const LIST_LABEL_PACKAGE_TYPE = __('Type');
+export const LIST_LABEL_CREATED_AT = __('Published');
+
+export const SORT_FIELDS = [
+ {
+ orderBy: LIST_KEY_NAME,
+ label: LIST_LABEL_NAME,
+ },
+ {
+ orderBy: LIST_KEY_PROJECT,
+ label: LIST_LABEL_PROJECT,
+ },
+ {
+ orderBy: LIST_KEY_VERSION,
+ label: LIST_LABEL_VERSION,
+ },
+ {
+ orderBy: LIST_KEY_PACKAGE_TYPE,
+ label: LIST_LABEL_PACKAGE_TYPE,
+ },
+ {
+ orderBy: LIST_KEY_CREATED_AT,
+ label: LIST_LABEL_CREATED_AT,
+ },
+];
+
+export const PACKAGE_TYPES = [
+ s__('PackageRegistry|Composer'),
+ s__('PackageRegistry|Conan'),
+ s__('PackageRegistry|Generic'),
+ s__('PackageRegistry|Maven'),
+ s__('PackageRegistry|npm'),
+ s__('PackageRegistry|NuGet'),
+ s__('PackageRegistry|PyPI'),
+ s__('PackageRegistry|RubyGems'),
+ s__('PackageRegistry|Debian'),
+ s__('PackageRegistry|Helm'),
+];
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js b/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js
index f8cb5c516e2..21d6fbc9e1f 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js
+++ b/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js
@@ -17,7 +17,6 @@ export const apolloProvider = new VueApollo({
cacheConfig: {
fragmentMatcher,
},
- assumeImmutableResults: true,
},
),
});
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql b/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql
index 74e6de87866..e3115365f8b 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql
@@ -1,4 +1,5 @@
#import "~/packages_and_registries/package_registry/graphql/fragments/package_data.fragment.graphql"
+#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
query getPackages(
$fullPath: ID!
@@ -7,21 +8,47 @@ query getPackages(
$groupSort: PackageGroupSort
$packageName: String
$packageType: PackageTypeEnum
+ $first: Int
+ $last: Int
+ $after: String
+ $before: String
) {
project(fullPath: $fullPath) @skip(if: $isGroupPage) {
- packages(sort: $sort, packageName: $packageName, packageType: $packageType) {
+ packages(
+ sort: $sort
+ packageName: $packageName
+ packageType: $packageType
+ after: $after
+ before: $before
+ first: $first
+ last: $last
+ ) {
count
nodes {
...PackageData
}
+ pageInfo {
+ ...PageInfo
+ }
}
}
group(fullPath: $fullPath) @include(if: $isGroupPage) {
- packages(sort: $groupSort, packageName: $packageName, packageType: $packageType) {
+ packages(
+ sort: $groupSort
+ packageName: $packageName
+ packageType: $packageType
+ after: $after
+ before: $before
+ first: $first
+ last: $last
+ ) {
count
nodes {
...PackageData
}
+ pageInfo {
+ ...PageInfo
+ }
}
}
}
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/utils.js b/app/assets/javascripts/packages_and_registries/package_registry/utils.js
index ae886952c3e..4ff8edb8f66 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/utils.js
+++ b/app/assets/javascripts/packages_and_registries/package_registry/utils.js
@@ -1,3 +1,4 @@
+import { capitalize } from 'lodash';
import { s__ } from '~/locale';
import {
PACKAGE_TYPE_CONAN,
@@ -10,6 +11,8 @@ import {
PACKAGE_TYPE_GENERIC,
PACKAGE_TYPE_DEBIAN,
PACKAGE_TYPE_HELM,
+ LIST_KEY_PROJECT,
+ SORT_FIELDS,
} from './constants';
export const getPackageTypeLabel = (packageType) => {
@@ -38,3 +41,8 @@ export const getPackageTypeLabel = (packageType) => {
return null;
}
};
+
+export const packageTypeToTrackCategory = (type) => `UI::${capitalize(type)}Packages`;
+
+export const sortableFields = (isGroupPage) =>
+ SORT_FIELDS.filter((f) => f.orderBy !== LIST_KEY_PROJECT || isGroupPage);
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue
index 2dbe36def0e..5815c6393a7 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue
@@ -103,6 +103,7 @@ export default {
:disabled="isLoading"
:label="$options.i18n.label"
data-qa-selector="dependency_proxy_setting_toggle"
+ data-testid="dependency-proxy-setting-toggle"
/>
</div>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js b/app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js
index 16152eb81f6..56f95fa2c1f 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js
+++ b/app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js
@@ -5,10 +5,5 @@ import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
export const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- ),
+ defaultClient: createDefaultClient(),
});
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/graphql/index.js b/app/assets/javascripts/packages_and_registries/settings/project/graphql/index.js
index 16152eb81f6..56f95fa2c1f 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/graphql/index.js
+++ b/app/assets/javascripts/packages_and_registries/settings/project/graphql/index.js
@@ -5,10 +5,5 @@ import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
export const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- ),
+ defaultClient: createDefaultClient(),
});
diff --git a/app/assets/javascripts/pages/admin/deploy_keys/index/index.js b/app/assets/javascripts/pages/admin/deploy_keys/index/index.js
new file mode 100644
index 00000000000..1e52aa3efd8
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/deploy_keys/index/index.js
@@ -0,0 +1,3 @@
+import { initAdminDeployKeysTable } from '~/admin/deploy_keys';
+
+initAdminDeployKeysTable();
diff --git a/app/assets/javascripts/pages/admin/dev_ops_report/index.js b/app/assets/javascripts/pages/admin/dev_ops_report/index.js
index a94a60af7ff..4cad87492cf 100644
--- a/app/assets/javascripts/pages/admin/dev_ops_report/index.js
+++ b/app/assets/javascripts/pages/admin/dev_ops_report/index.js
@@ -1,5 +1,5 @@
-import initDevOpsScore from '~/analytics/devops_report/devops_score';
-import initDevOpsScoreDisabledServicePing from '~/analytics/devops_report/devops_score_disabled_service_ping';
+import initDevOpsScore from '~/analytics/devops_reports/devops_score';
+import initDevOpsScoreDisabledServicePing from '~/analytics/devops_reports/devops_score_disabled_service_ping';
initDevOpsScoreDisabledServicePing();
initDevOpsScore();
diff --git a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
index 055d6f40c14..b06c804f3ca 100644
--- a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
+++ b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
@@ -46,7 +46,7 @@ export default {
return sprintf(
s__(`AdminProjects|
You’re about to permanently delete the project %{projectName}, its repository,
- and all related resources, including issues and merge requests. Once you confirm and press
+ and all related resources, including issues and merge requests. After you confirm and press
%{strong_start}Delete project%{strong_end}, it cannot be undone or recovered.`),
{
projectName: `<strong>${escape(this.projectName)}</strong>`,
@@ -70,7 +70,7 @@ export default {
},
primaryProps() {
return {
- text: s__('Delete project'),
+ text: __('Delete project'),
attributes: [{ variant: 'danger' }, { category: 'primary' }, { disabled: !this.canSubmit }],
};
},
diff --git a/app/assets/javascripts/pages/dashboard/todos/index/todos.js b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
index 946076cfb29..a1e7eb5d3de 100644
--- a/app/assets/javascripts/pages/dashboard/todos/index/todos.js
+++ b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
@@ -1,4 +1,4 @@
-/* eslint-disable class-methods-use-this, no-unneeded-ternary */
+/* eslint-disable class-methods-use-this */
import $ from 'jquery';
import { getGroups } from '~/api/groups_api';
@@ -78,7 +78,7 @@ export default class Todos {
initDeprecatedJQueryDropdown($dropdown, {
fieldName,
selectable: true,
- filterable: searchFields ? true : false,
+ filterable: Boolean(searchFields),
search: { fields: searchFields },
data: $dropdown.data('data'),
clicked: () => {
@@ -172,8 +172,8 @@ export default class Todos {
updateBadges(data) {
$(document).trigger('todo:toggle', data.count);
- document.querySelector('.todos-pending .badge').innerHTML = addDelimiter(data.count);
- document.querySelector('.todos-done .badge').innerHTML = addDelimiter(data.done_count);
+ document.querySelector('.js-todos-pending .badge').innerHTML = addDelimiter(data.count);
+ document.querySelector('.js-todos-done .badge').innerHTML = addDelimiter(data.done_count);
}
goToTodoUrl(e) {
diff --git a/app/assets/javascripts/pages/groups/crm/contacts/index.js b/app/assets/javascripts/pages/groups/crm/contacts/index.js
new file mode 100644
index 00000000000..a595246957f
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/crm/contacts/index.js
@@ -0,0 +1,3 @@
+import initCrmContactsApp from '~/crm/contacts_bundle';
+
+initCrmContactsApp();
diff --git a/app/assets/javascripts/pages/groups/crm/organizations/index.js b/app/assets/javascripts/pages/groups/crm/organizations/index.js
new file mode 100644
index 00000000000..16479b43d52
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/crm/organizations/index.js
@@ -0,0 +1,3 @@
+import initCrmOrganizationsApp from '~/crm/organizations_bundle';
+
+initCrmOrganizationsApp();
diff --git a/app/assets/javascripts/pages/groups/edit/index.js b/app/assets/javascripts/pages/groups/edit/index.js
index 49b9822795c..604da77f60c 100644
--- a/app/assets/javascripts/pages/groups/edit/index.js
+++ b/app/assets/javascripts/pages/groups/edit/index.js
@@ -10,10 +10,12 @@ import projectSelect from '~/project_select';
import initSearchSettings from '~/search_settings';
import initSettingsPanels from '~/settings_panels';
import setupTransferEdit from '~/transfer_edit';
+import initConfirmDanger from '~/init_confirm_danger';
document.addEventListener('DOMContentLoaded', () => {
initFilePickers();
initConfirmDangerModal();
+ initConfirmDanger();
initSettingsPanels();
dirtySubmitFactory(
document.querySelectorAll('.js-general-settings-form, .js-general-permissions-form'),
diff --git a/app/assets/javascripts/pages/groups/new/components/app.vue b/app/assets/javascripts/pages/groups/new/components/app.vue
index 9aac364d20e..c3ac074cd7a 100644
--- a/app/assets/javascripts/pages/groups/new/components/app.vue
+++ b/app/assets/javascripts/pages/groups/new/components/app.vue
@@ -47,7 +47,7 @@ export default {
<template>
<new-namespace-page
:jump-to-last-persisted-panel="hasErrors"
- :initial-breadcrumb="s__('New group')"
+ :initial-breadcrumb="__('New group')"
:panels="$options.PANELS"
:title="s__('GroupsNew|Create new group')"
persistence-key="new_group_last_active_tab"
diff --git a/app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue b/app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue
index ea08a0821a8..35193171fb8 100644
--- a/app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue
+++ b/app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue
@@ -20,7 +20,7 @@ export default {
<gl-sprintf
:message="
s__(
- 'GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups.',
+ 'GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects.',
)
"
>
diff --git a/app/assets/javascripts/pages/groups/new/fetch_group_path_availability.js b/app/assets/javascripts/pages/groups/new/fetch_group_path_availability.js
deleted file mode 100644
index 301e0b4f7a2..00000000000
--- a/app/assets/javascripts/pages/groups/new/fetch_group_path_availability.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { buildApiUrl } from '~/api/api_utils';
-import axios from '~/lib/utils/axios_utils';
-
-const NAMESPACE_EXISTS_PATH = '/api/:version/namespaces/:id/exists';
-
-export default function fetchGroupPathAvailability(groupPath, parentId) {
- const url = buildApiUrl(NAMESPACE_EXISTS_PATH).replace(':id', encodeURIComponent(groupPath));
-
- return axios.get(url, {
- params: { parent_id: parentId },
- });
-}
diff --git a/app/assets/javascripts/pages/groups/new/group_path_validator.js b/app/assets/javascripts/pages/groups/new/group_path_validator.js
index c58be202043..8ce73be6e74 100644
--- a/app/assets/javascripts/pages/groups/new/group_path_validator.js
+++ b/app/assets/javascripts/pages/groups/new/group_path_validator.js
@@ -3,7 +3,7 @@ import { debounce } from 'lodash';
import createFlash from '~/flash';
import { __ } from '~/locale';
import InputValidator from '~/validators/input_validator';
-import fetchGroupPathAvailability from './fetch_group_path_availability';
+import { getGroupPathAvailability } from '~/rest_api';
const debounceTimeoutDuration = 1000;
const invalidInputClass = 'gl-field-error-outline';
@@ -45,7 +45,7 @@ export default class GroupPathValidator extends InputValidator {
if (inputDomElement.checkValidity() && groupPath.length > 1) {
GroupPathValidator.setMessageVisibility(inputDomElement, pendingMessageSelector);
- fetchGroupPathAvailability(groupPath, parentId)
+ getGroupPathAvailability(groupPath, parentId)
.then(({ data }) => data)
.then((data) => {
GroupPathValidator.setInputState(inputDomElement, !data.exists);
diff --git a/app/assets/javascripts/pages/groups/packages/index/index.js b/app/assets/javascripts/pages/groups/packages/index/index.js
index 95522573b53..f9eecff4ac4 100644
--- a/app/assets/javascripts/pages/groups/packages/index/index.js
+++ b/app/assets/javascripts/pages/groups/packages/index/index.js
@@ -1,10 +1,3 @@
-(async function packageApp() {
- if (window.gon.features.packageListApollo) {
- const newPackageList = await import('~/packages_and_registries/package_registry/pages/list');
+import packageList from '~/packages_and_registries/package_registry/pages/list';
- newPackageList.default();
- } else {
- const packageList = await import('~/packages/list/packages_list_app_bundle');
- packageList.default();
- }
-})();
+packageList();
diff --git a/app/assets/javascripts/pages/groups/registry/repositories/index.js b/app/assets/javascripts/pages/groups/registry/repositories/index.js
index 6fd32321568..44579ee1217 100644
--- a/app/assets/javascripts/pages/groups/registry/repositories/index.js
+++ b/app/assets/javascripts/pages/groups/registry/repositories/index.js
@@ -1,4 +1,4 @@
-import registryExplorer from '~/registry/explorer/index';
+import registryExplorer from '~/packages_and_registries/container_registry/explorer/index';
const explorer = registryExplorer();
diff --git a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue b/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
index e42e89ce021..b41611001ab 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
+++ b/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
@@ -3,7 +3,7 @@ import { GlModal } from '@gitlab/ui';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
export default {
components: {
@@ -83,7 +83,7 @@ export default {
attributes: [{ variant: 'warning' }],
},
cancelAction: {
- text: s__('Cancel'),
+ text: __('Cancel'),
attributes: [],
},
};
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js
index 80bcbefab46..b365e039191 100644
--- a/app/assets/javascripts/pages/projects/blob/show/index.js
+++ b/app/assets/javascripts/pages/projects/blob/show/index.js
@@ -14,7 +14,7 @@ import '~/sourcegraph/load';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
const viewBlobEl = document.querySelector('#js-view-blob-app');
diff --git a/app/assets/javascripts/pages/projects/edit/index.js b/app/assets/javascripts/pages/projects/edit/index.js
index 335d8d481fc..f4beefea90c 100644
--- a/app/assets/javascripts/pages/projects/edit/index.js
+++ b/app/assets/javascripts/pages/projects/edit/index.js
@@ -1,5 +1,5 @@
import { PROJECT_BADGE } from '~/badges/constants';
-import initConfirmDangerModal from '~/confirm_danger_modal';
+import initLegacyConfirmDangerModal from '~/confirm_danger_modal';
import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
import initFilePickers from '~/file_pickers';
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
@@ -9,11 +9,12 @@ import initSearchSettings from '~/search_settings';
import initSettingsPanels from '~/settings_panels';
import setupTransferEdit from '~/transfer_edit';
import UserCallout from '~/user_callout';
+import initTopicsTokenSelector from '~/projects/settings/topics';
import initProjectPermissionsSettings from '../shared/permissions';
import initProjectLoadingSpinner from '../shared/save_project_loader';
initFilePickers();
-initConfirmDangerModal();
+initLegacyConfirmDangerModal();
initSettingsPanels();
initProjectDeleteButton();
mountBadgeSettings(PROJECT_BADGE);
@@ -28,3 +29,4 @@ setupTransferEdit('.js-project-transfer-form', 'select.select2');
dirtySubmitFactory(document.querySelectorAll('.js-general-settings-form, .js-mr-settings-form'));
initSearchSettings();
+initTopicsTokenSelector();
diff --git a/app/assets/javascripts/pages/projects/environments/index/index.js b/app/assets/javascripts/pages/projects/environments/index/index.js
index 554ed4f9786..f0554d64ddc 100644
--- a/app/assets/javascripts/pages/projects/environments/index/index.js
+++ b/app/assets/javascripts/pages/projects/environments/index/index.js
@@ -1,3 +1,11 @@
import initEnvironments from '~/environments/';
+import initNewEnvironments from '~/environments/new_index';
-initEnvironments();
+let el = document.getElementById('environments-list-view');
+
+if (el) {
+ initEnvironments(el);
+} else {
+ el = document.getElementById('environments-table');
+ initNewEnvironments(el);
+}
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
index 795ae713c08..25b62e6c971 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
@@ -382,7 +382,11 @@ export default {
:data-testid="`radio-${value}`"
>
<div>
- <gl-icon :name="icon" />
+ <gl-icon
+ data-qa-selector="fork_privacy_button"
+ :name="icon"
+ :data-qa-privacy-level="`${value}`"
+ />
<span>{{ text }}</span>
</div>
<template #help>{{ help }}</template>
diff --git a/app/assets/javascripts/pages/projects/google_cloud/index.js b/app/assets/javascripts/pages/projects/google_cloud/index.js
new file mode 100644
index 00000000000..4506ea8efd1
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/google_cloud/index.js
@@ -0,0 +1,3 @@
+import initGoogleCloud from '~/google_cloud/index';
+
+initGoogleCloud();
diff --git a/app/assets/javascripts/pages/projects/issues/show.js b/app/assets/javascripts/pages/projects/issues/show.js
index 62aa5df888f..24aa2f0da13 100644
--- a/app/assets/javascripts/pages/projects/issues/show.js
+++ b/app/assets/javascripts/pages/projects/issues/show.js
@@ -3,7 +3,7 @@ import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import initIssuableSidebar from '~/init_issuable_sidebar';
import { IssuableType } from '~/issuable_show/constants';
import Issue from '~/issue';
-import initIncidentApp from '~/issue_show/incident';
+import { initIncidentApp, initIncidentHeaderActions } from '~/issue_show/incident';
import { initIssuableApp, initIssueHeaderActions } from '~/issue_show/issue';
import { parseIssuableData } from '~/issue_show/utils/parse_data';
import initNotesApp from '~/notes';
@@ -22,16 +22,18 @@ export default function initShowIssue() {
switch (issueType) {
case IssuableType.Incident:
initIncidentApp(issuableData);
+ initIncidentHeaderActions(store);
break;
case IssuableType.Issue:
initIssuableApp(issuableData, store);
+ initIssueHeaderActions(store);
break;
default:
+ initIssueHeaderActions(store);
break;
}
initIssuableHeaderWarning(store);
- initIssueHeaderActions(store);
initSentryErrorStackTraceApp();
initRelatedMergeRequestsApp();
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue
index 51980b2d971..95afcb6bda8 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue
@@ -1,5 +1,6 @@
<script>
import { GlProgressBar, GlSprintf } from '@gitlab/ui';
+import eventHub from '~/invite_members/event_hub';
import { s__ } from '~/locale';
import { ACTION_LABELS, ACTION_SECTIONS } from '../constants';
import LearnGitlabSectionCard from './learn_gitlab_section_card.vue';
@@ -22,6 +23,11 @@ export default {
required: true,
type: Object,
},
+ inviteMembersOpen: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
maxValue: Object.keys(ACTION_LABELS).length,
actionSections: Object.keys(ACTION_SECTIONS),
@@ -33,7 +39,15 @@ export default {
return Math.round((this.progressValue / this.$options.maxValue) * 100);
},
},
+ mounted() {
+ if (this.inviteMembersOpen) {
+ this.openInviteMembersModal('celebrate');
+ }
+ },
methods: {
+ openInviteMembersModal(mode) {
+ eventHub.$emit('openModal', { mode, inviteeType: 'members', source: 'learn-gitlab' });
+ },
actionsFor(section) {
const actions = Object.fromEntries(
Object.entries(this.actions).filter(
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue
index 69fb5878f5c..0995947f3e7 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue
@@ -40,6 +40,7 @@ export default {
data-track-action="click_link"
:data-track-label="$options.i18n.ACTION_LABELS[action].title"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
+ data-track-experiment="change_continuous_onboarding_link_urls"
>
{{ $options.i18n.ACTION_LABELS[action].title }}
</gl-link>
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
index 6da0a8fd212..ea9eec2595f 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import LearnGitlab from '../components/learn_gitlab.vue';
@@ -11,15 +12,17 @@ function initLearnGitlab() {
const actions = convertObjectPropsToCamelCase(JSON.parse(el.dataset.actions));
const sections = convertObjectPropsToCamelCase(JSON.parse(el.dataset.sections));
+ const { inviteMembersOpen } = el.dataset;
return new Vue({
el,
render(createElement) {
return createElement(LearnGitlab, {
- props: { actions, sections },
+ props: { actions, sections, inviteMembersOpen },
});
},
});
}
+initInviteMembersModal();
initLearnGitlab();
diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
index dadf0988582..99094617b0a 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
@@ -28,7 +28,6 @@ export default function initMergeRequestShow() {
const el = document.querySelector('.js-mr-status-box');
const apolloProvider = new VueApollo({
- assumeImmutableResults: true,
defaultClient: createDefaultClient(),
});
// eslint-disable-next-line no-new
diff --git a/app/assets/javascripts/pages/projects/packages/packages/index/index.js b/app/assets/javascripts/pages/projects/packages/packages/index/index.js
index 95522573b53..f9eecff4ac4 100644
--- a/app/assets/javascripts/pages/projects/packages/packages/index/index.js
+++ b/app/assets/javascripts/pages/projects/packages/packages/index/index.js
@@ -1,10 +1,3 @@
-(async function packageApp() {
- if (window.gon.features.packageListApollo) {
- const newPackageList = await import('~/packages_and_registries/package_registry/pages/list');
+import packageList from '~/packages_and_registries/package_registry/pages/list';
- newPackageList.default();
- } else {
- const packageList = await import('~/packages/list/packages_list_app_bundle');
- packageList.default();
- }
-})();
+packageList();
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
index 0e646e8c505..85443843684 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
@@ -72,18 +72,18 @@ export default {
return [
{
value: KEY_EVERY_DAY,
- text: sprintf(s__(`Every day (at %{time})`), { time: this.formattedTime }),
+ text: sprintf(__(`Every day (at %{time})`), { time: this.formattedTime }),
},
{
value: KEY_EVERY_WEEK,
- text: sprintf(s__('Every week (%{weekday} at %{time})'), {
+ text: sprintf(__('Every week (%{weekday} at %{time})'), {
weekday: this.weekday,
time: this.formattedTime,
}),
},
{
value: KEY_EVERY_MONTH,
- text: sprintf(s__('Every month (Day %{day} at %{time})'), {
+ text: sprintf(__('Every month (Day %{day} at %{time})'), {
day: this.randomDay,
time: this.formattedTime,
}),
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index 9e93f709937..a26aeeb6db4 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -23,14 +23,14 @@ export default class Project {
});
}
- $('.hide-no-ssh-message').on('click', function (e) {
+ $('.js-hide-no-ssh-message').on('click', function (e) {
Cookies.set('hide_no_ssh_message', 'false');
- $(this).parents('.no-ssh-key-message').remove();
+ $(this).parents('.js-no-ssh-key-message').remove();
return e.preventDefault();
});
- $('.hide-no-password-message').on('click', function (e) {
+ $('.js-hide-no-password-message').on('click', function (e) {
Cookies.set('hide_no_password_message', 'false');
- $(this).parents('.no-password-message').remove();
+ $(this).parents('.js-no-password-message').remove();
return e.preventDefault();
});
$('.hide-auto-devops-implicitly-enabled-banner').on('click', function (e) {
diff --git a/app/assets/javascripts/pages/projects/registry/repositories/index.js b/app/assets/javascripts/pages/projects/registry/repositories/index.js
index 6fd32321568..44579ee1217 100644
--- a/app/assets/javascripts/pages/projects/registry/repositories/index.js
+++ b/app/assets/javascripts/pages/projects/registry/repositories/index.js
@@ -1,4 +1,4 @@
-import registryExplorer from '~/registry/explorer/index';
+import registryExplorer from '~/packages_and_registries/container_registry/explorer/index';
const explorer = registryExplorer();
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
index b7546a6bed7..cc92a8cd476 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
@@ -1,10 +1,5 @@
<script>
-import { GlIcon } from '@gitlab/ui';
-
export default {
- components: {
- GlIcon,
- },
props: {
label: {
type: String,
@@ -29,10 +24,14 @@ export default {
<div class="project-feature-row">
<label v-if="label" class="label-bold">
{{ label }}
- <a v-if="helpPath" :href="helpPath" target="_blank">
- <gl-icon name="question-o" />
- </a>
</label>
- <span v-if="helpText" class="form-text text-muted"> {{ helpText }} </span> <slot></slot>
+ <div>
+ <span v-if="helpText" class="text-muted"> {{ helpText }} </span>
+ <span v-if="helpPath"
+ ><a :href="helpPath" target="_blank">{{ __('Learn more') }}</a
+ >.</span
+ >
+ </div>
+ <slot></slot>
</div>
</template>
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
index c53d367ed71..384ee1f5034 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
@@ -2,7 +2,7 @@
import { GlIcon, GlSprintf, GlLink, GlFormCheckbox, GlToggle } from '@gitlab/ui';
import settingsMixin from 'ee_else_ce/pages/projects/shared/permissions/mixins/settings_pannel_mixin';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import {
visibilityOptions,
visibilityLevelDescriptions,
@@ -31,7 +31,7 @@ export default {
operationsLabel: s__('ProjectSettings|Operations'),
packagesLabel: s__('ProjectSettings|Packages'),
pagesLabel: s__('ProjectSettings|Pages'),
- ciCdLabel: s__('CI/CD'),
+ ciCdLabel: __('CI/CD'),
repositoryLabel: s__('ProjectSettings|Repository'),
requirementsLabel: s__('ProjectSettings|Requirements'),
securityAndComplianceLabel: s__('ProjectSettings|Security & Compliance'),
@@ -400,6 +400,9 @@ export default {
ref="project-visibility-settings"
:help-path="visibilityHelpPath"
:label="s__('ProjectSettings|Project visibility')"
+ :help-text="
+ s__('ProjectSettings|Manage who can see the project in the public access directory.')
+ "
>
<div class="project-feature-controls gl-display-flex gl-align-items-center gl-my-3 gl-mx-0">
<div class="select-wrapper gl-flex-grow-1">
diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js
index 78b3f2f1b30..31d69a731fe 100644
--- a/app/assets/javascripts/pages/projects/show/index.js
+++ b/app/assets/javascripts/pages/projects/show/index.js
@@ -7,7 +7,7 @@ import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import leaveByUrl from '~/namespaces/leave_by_url';
import initVueNotificationsDropdown from '~/notifications';
-import { initUploadFileTrigger } from '~/projects/upload_file_experiment';
+import { initUploadFileTrigger } from '~/projects/upload_file';
import initReadMore from '~/read_more';
import UserCallout from '~/user_callout';
import Star from '../../../star';
diff --git a/app/assets/javascripts/pages/projects/work_items/index/index.js b/app/assets/javascripts/pages/projects/work_items/index.js
index 11c257611f0..11c257611f0 100644
--- a/app/assets/javascripts/pages/projects/work_items/index/index.js
+++ b/app/assets/javascripts/pages/projects/work_items/index.js
diff --git a/app/assets/javascripts/pages/shared/mount_runner_instructions.js b/app/assets/javascripts/pages/shared/mount_runner_instructions.js
index 1cb7259be64..e83c73edfde 100644
--- a/app/assets/javascripts/pages/shared/mount_runner_instructions.js
+++ b/app/assets/javascripts/pages/shared/mount_runner_instructions.js
@@ -9,12 +9,7 @@ export function initInstallRunner(componentId = 'js-install-runner') {
const installRunnerEl = document.getElementById(componentId);
if (installRunnerEl) {
- const defaultClient = createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- );
+ const defaultClient = createDefaultClient();
const apolloProvider = new VueApollo({
defaultClient,
diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
index a8ec731e105..6f19a9f4379 100644
--- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
+++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
@@ -12,13 +12,15 @@ import {
import axios from '~/lib/utils/axios_utils';
import csrf from '~/lib/utils/csrf';
import { setUrlFragment } from '~/lib/utils/url_utility';
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
import Tracking from '~/tracking';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import {
- WIKI_CONTENT_EDITOR_TRACKING_LABEL,
CONTENT_EDITOR_LOADED_ACTION,
SAVED_USING_CONTENT_EDITOR_ACTION,
+ WIKI_CONTENT_EDITOR_TRACKING_LABEL,
+ WIKI_FORMAT_LABEL,
+ WIKI_FORMAT_UPDATED_ACTION,
} from '../constants';
const trackingMixin = Tracking.mixin({
@@ -83,7 +85,7 @@ export default {
),
},
},
- feedbackTip: s__(
+ feedbackTip: __(
'Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}.',
),
},
@@ -219,6 +221,8 @@ export default {
this.trackFormSubmit();
}
+ this.trackWikiFormat();
+
// Wait until form field values are refreshed
await this.$nextTick();
@@ -304,6 +308,14 @@ export default {
}
},
+ trackWikiFormat() {
+ this.track(WIKI_FORMAT_UPDATED_ACTION, {
+ label: WIKI_FORMAT_LABEL,
+ value: this.format,
+ extra: { project_path: this.pageInfo.path, old_format: this.pageInfo.format },
+ });
+ },
+
dismissContentEditorAlert() {
this.isContentEditorAlertDismissed = true;
},
diff --git a/app/assets/javascripts/pages/shared/wikis/constants.js b/app/assets/javascripts/pages/shared/wikis/constants.js
index b358ac9cf52..94d086158f1 100644
--- a/app/assets/javascripts/pages/shared/wikis/constants.js
+++ b/app/assets/javascripts/pages/shared/wikis/constants.js
@@ -1,4 +1,5 @@
-export const WIKI_CONTENT_EDITOR_TRACKING_LABEL = 'wiki_content_editor';
-
export const CONTENT_EDITOR_LOADED_ACTION = 'content_editor_loaded';
export const SAVED_USING_CONTENT_EDITOR_ACTION = 'saved_using_content_editor';
+export const WIKI_CONTENT_EDITOR_TRACKING_LABEL = 'wiki_content_editor';
+export const WIKI_FORMAT_LABEL = 'wiki_format';
+export const WIKI_FORMAT_UPDATED_ACTION = 'wiki_format_updated';
diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js
index 0fab4678bc3..7f4e79976bc 100644
--- a/app/assets/javascripts/pages/users/activity_calendar.js
+++ b/app/assets/javascripts/pages/users/activity_calendar.js
@@ -5,6 +5,7 @@ import { last } from 'lodash';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { getDayName, getDayDifference } from '~/lib/utils/datetime_utility';
+import { formatDate } from '~/lib/utils/datetime/date_format_utility';
import { n__, s__, __ } from '~/locale';
const d3 = { select };
@@ -294,7 +295,15 @@ export default class ActivityCalendar {
},
responseType: 'text',
})
- .then(({ data }) => $(this.activitiesContainer).html(data))
+ .then(({ data }) => {
+ $(this.activitiesContainer).html(data);
+ document
+ .querySelector(this.activitiesContainer)
+ .querySelectorAll('.js-localtime')
+ .forEach((el) => {
+ el.setAttribute('title', formatDate(el.getAttribute('data-datetime')));
+ });
+ })
.catch(() =>
createFlash({
message: __('An error occurred while retrieving calendar activity'),
diff --git a/app/assets/javascripts/pages/users/terms/index/index.js b/app/assets/javascripts/pages/users/terms/index/index.js
new file mode 100644
index 00000000000..29ddde6da94
--- /dev/null
+++ b/app/assets/javascripts/pages/users/terms/index/index.js
@@ -0,0 +1,4 @@
+import { initTermsApp } from '~/terms';
+import { waitForCSSLoaded } from '~/helpers/startup_css_helper';
+
+waitForCSSLoaded(initTermsApp);
diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
index f163a7c3a8e..1bb82e1d8e6 100644
--- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
@@ -1,7 +1,7 @@
<script>
import { GlButton, GlModal, GlModalDirective, GlSegmentedControl } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import { sortOrders, sortOrderOptions } from '../constants';
import RequestWarning from './request_warning.vue';
@@ -55,7 +55,7 @@ export default {
const summary = {};
if (!this.metricDetails.summaryOptions?.hideTotal) {
- summary[s__('Total')] = this.metricDetails.calls;
+ summary[__('Total')] = this.metricDetails.calls;
}
if (!this.metricDetails.summaryOptions?.hideDuration) {
diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue
index f1fe8cf10fd..905a5f2d271 100644
--- a/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue
+++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue
@@ -36,6 +36,11 @@ export default {
required: false,
default: false,
},
+ scrollToCommitForm: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -52,6 +57,13 @@ export default {
return !(this.message && this.targetBranch);
},
},
+ watch: {
+ scrollToCommitForm(flag) {
+ if (flag) {
+ this.scrollIntoView();
+ }
+ },
+ },
methods: {
onSubmit() {
this.$emit('submit', {
@@ -63,6 +75,10 @@ export default {
onReset() {
this.$emit('cancel');
},
+ scrollIntoView() {
+ this.$el.scrollIntoView({ behavior: 'smooth' });
+ this.$emit('scrolled-to-commit-form');
+ },
},
i18n: {
commitMessage: __('Commit message'),
diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
index 0308cd9c565..14c11099756 100644
--- a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
+++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
@@ -10,9 +10,8 @@ import {
import commitCIFile from '../../graphql/mutations/commit_ci_file.mutation.graphql';
import updateCurrentBranchMutation from '../../graphql/mutations/update_current_branch.mutation.graphql';
import updateLastCommitBranchMutation from '../../graphql/mutations/update_last_commit_branch.mutation.graphql';
+import updatePipelineEtag from '../../graphql/mutations/update_pipeline_etag.mutation.graphql';
import getCurrentBranch from '../../graphql/queries/client/current_branch.graphql';
-import getIsNewCiConfigFile from '../../graphql/queries/client/is_new_ci_config_file.graphql';
-import getPipelineEtag from '../../graphql/queries/client/pipeline_etag.graphql';
import CommitForm from './commit_form.vue';
@@ -41,18 +40,24 @@ export default {
required: false,
default: '',
},
+ isNewCiConfigFile: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ scrollToCommitForm: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
commit: {},
- isNewCiConfigFile: false,
isSaving: false,
};
},
apollo: {
- isNewCiConfigFile: {
- query: getIsNewCiConfigFile,
- },
currentBranch: {
query: getCurrentBranch,
},
@@ -96,10 +101,10 @@ export default {
content: this.ciFileContent,
lastCommitId: this.commitSha,
},
- update(store, { data }) {
+ update(_, { data }) {
const pipelineEtag = data?.commitCreate?.commit?.commitPipelinePath;
if (pipelineEtag) {
- store.writeQuery({ query: getPipelineEtag, data: { pipelineEtag } });
+ this.$apollo.mutate({ mutation: updatePipelineEtag, variables: pipelineEtag });
}
},
});
@@ -146,6 +151,8 @@ export default {
:current-branch="currentBranch"
:default-message="defaultCommitMessage"
:is-saving="isSaving"
+ :scroll-to-commit-form="scrollToCommitForm"
+ v-on="$listeners"
@cancel="onCommitCancel"
@submit="onCommitSubmit"
/>
diff --git a/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue b/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue
index ff1e0b6388f..d7594fb318a 100644
--- a/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue
+++ b/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue
@@ -2,6 +2,7 @@
import { GlButton, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+import { experiment } from '~/experimentation/utils';
import { DRAWER_EXPANDED_KEY } from '../../constants';
import FirstPipelineCard from './cards/first_pipeline_card.vue';
import GettingStartedCard from './cards/getting_started_card.vue';
@@ -53,12 +54,23 @@ export default {
},
methods: {
setInitialExpandState() {
+ let isExpanded;
+
+ experiment('pipeline_editor_walkthrough', {
+ control: () => {
+ isExpanded = true;
+ },
+ candidate: () => {
+ isExpanded = false;
+ },
+ });
+
// We check in the local storage and if no value is defined, we want the default
// to be true. We want to explicitly set it to true here so that the drawer
// animates to open on load.
const localValue = localStorage.getItem(this.$options.localDrawerKey);
if (localValue === null) {
- this.isExpanded = true;
+ this.isExpanded = isExpanded;
}
},
setTopPosition() {
diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
index 68065cc3c73..baf1d17b233 100644
--- a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
+++ b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
@@ -12,7 +12,7 @@ import { produce } from 'immer';
import { fetchPolicies } from '~/lib/graphql';
import { historyPushState } from '~/lib/utils/common_utils';
import { setUrlParams } from '~/lib/utils/url_utility';
-import { s__ } from '~/locale';
+import { __ } from '~/locale';
import {
BRANCH_PAGINATION_LIMIT,
BRANCH_SEARCH_DEBOUNCE,
@@ -25,9 +25,9 @@ import getLastCommitBranchQuery from '~/pipeline_editor/graphql/queries/client/l
export default {
i18n: {
- dropdownHeader: s__('Switch branch'),
- title: s__('Branches'),
- fetchError: s__('Unable to fetch branch list for this project.'),
+ dropdownHeader: __('Switch branch'),
+ title: __('Branches'),
+ fetchError: __('Unable to fetch branch list for this project.'),
},
inputDebounce: BRANCH_SEARCH_DEBOUNCE,
components: {
@@ -43,14 +43,25 @@ export default {
},
inject: ['projectFullPath', 'totalBranches'],
props: {
+ hasUnsavedChanges: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
paginationLimit: {
type: Number,
required: false,
default: BRANCH_PAGINATION_LIMIT,
},
+ shouldLoadNewBranch: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
+ branchSelected: null,
availableBranches: [],
filteredBranches: [],
isSearchingBranches: false,
@@ -101,10 +112,17 @@ export default {
isBranchesLoading() {
return this.$apollo.queries.availableBranches.loading || this.isSearchingBranches;
},
- showBranchSwitcher() {
+ enableBranchSwitcher() {
return this.branches.length > 0 || this.searchTerm.length > 0;
},
},
+ watch: {
+ shouldLoadNewBranch(flag) {
+ if (flag) {
+ this.changeBranch(this.branchSelected);
+ }
+ },
+ },
methods: {
availableBranchesQueryVars(varsOverride = {}) {
if (this.searchTerm.length > 0) {
@@ -149,11 +167,7 @@ export default {
})
.catch(this.showFetchError);
},
- async selectBranch(newBranch) {
- if (newBranch === this.currentBranch) {
- return;
- }
-
+ async changeBranch(newBranch) {
this.updateCurrentBranch(newBranch);
const updatedPath = setUrlParams({ branch_name: newBranch });
historyPushState(updatedPath);
@@ -164,6 +178,19 @@ export default {
await this.$nextTick();
this.$emit('refetchContent');
},
+ selectBranch(newBranch) {
+ if (newBranch !== this.currentBranch) {
+ // If there are unsaved changes, we want to show the user
+ // a modal to confirm what to do with these before changing
+ // branches.
+ if (this.hasUnsavedChanges) {
+ this.branchSelected = newBranch;
+ this.$emit('select-branch', newBranch);
+ } else {
+ this.changeBranch(newBranch);
+ }
+ }
+ },
async setSearchTerm(newSearchTerm) {
this.pageCounter = 0;
this.searchTerm = newSearchTerm.trim();
@@ -203,11 +230,11 @@ export default {
<template>
<gl-dropdown
- v-if="showBranchSwitcher"
v-gl-tooltip.hover
:title="$options.i18n.dropdownHeader"
:header-text="$options.i18n.dropdownHeader"
:text="currentBranch"
+ :disabled="!enableBranchSwitcher"
icon="branch"
data-qa-selector="branch_selector_button"
data-testid="branch-selector"
diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
index 551a0430fbf..83b074dd55c 100644
--- a/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
+++ b/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
@@ -5,10 +5,26 @@ export default {
components: {
BranchSwitcher,
},
+ props: {
+ hasUnsavedChanges: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ shouldLoadNewBranch: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
};
</script>
<template>
<div class="gl-mb-4">
- <branch-switcher v-on="$listeners" />
+ <branch-switcher
+ :has-unsaved-changes="hasUnsavedChanges"
+ :should-load-new-branch="shouldLoadNewBranch"
+ v-on="$listeners"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue b/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue
index fcc31f087ff..ec6ee52b6b2 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue
@@ -63,6 +63,7 @@ export default {
v-if="showPipelineStatus"
:commit-sha="commitSha"
:class="$options.pipelineStatusClasses"
+ v-on="$listeners"
/>
<validation-segment :class="validationStyling" :ci-config="ciConfigData" />
</div>
diff --git a/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_mini_graph.vue b/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_mini_graph.vue
index 75b1398a3c2..25a78aab933 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_mini_graph.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_mini_graph.vue
@@ -1,17 +1,52 @@
<script>
+import { __ } from '~/locale';
import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue';
+import getLinkedPipelinesQuery from '~/projects/commit_box/info/graphql/queries/get_linked_pipelines.query.graphql';
+import { PIPELINE_FAILURE } from '../../constants';
export default {
+ i18n: {
+ linkedPipelinesFetchError: __('Unable to fetch upstream and downstream pipelines.'),
+ },
components: {
PipelineMiniGraph,
+ LinkedPipelinesMiniList: () =>
+ import('ee_component/vue_shared/components/linked_pipelines_mini_list.vue'),
},
+ inject: ['projectFullPath'],
props: {
pipeline: {
type: Object,
required: true,
},
},
+ apollo: {
+ linkedPipelines: {
+ query: getLinkedPipelinesQuery,
+ variables() {
+ return {
+ fullPath: this.projectFullPath,
+ iid: this.pipeline.iid,
+ };
+ },
+ skip() {
+ return !this.pipeline.iid;
+ },
+ update({ project }) {
+ return project?.pipeline;
+ },
+ error() {
+ this.$emit('showError', {
+ type: PIPELINE_FAILURE,
+ reasons: [this.$options.i18n.linkedPipelinesFetchError],
+ });
+ },
+ },
+ },
computed: {
+ downstreamPipelines() {
+ return this.linkedPipelines?.downstream?.nodes || [];
+ },
pipelinePath() {
return this.pipeline.detailedStatus?.detailsPath || '';
},
@@ -38,12 +73,29 @@ export default {
};
});
},
+ showDownstreamPipelines() {
+ return this.downstreamPipelines.length > 0;
+ },
+ upstreamPipeline() {
+ return this.linkedPipelines?.upstream;
+ },
},
};
</script>
<template>
<div v-if="pipelineStages.length > 0" class="stage-cell gl-mr-5">
+ <linked-pipelines-mini-list
+ v-if="upstreamPipeline"
+ :triggered-by="[upstreamPipeline]"
+ data-testid="pipeline-editor-mini-graph-upstream"
+ />
<pipeline-mini-graph class="gl-display-inline" :stages="pipelineStages" />
+ <linked-pipelines-mini-list
+ v-if="showDownstreamPipelines"
+ :triggered="downstreamPipelines"
+ :pipeline-path="pipelinePath"
+ data-testid="pipeline-editor-mini-graph-downstream"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
index a1fa2147994..6fe1459c80c 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlIcon, GlLink, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
+import { GlButton, GlIcon, GlLink, GlLoadingIcon, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { truncateSha } from '~/lib/utils/text_utility';
import { s__ } from '~/locale';
@@ -10,7 +10,6 @@ import {
toggleQueryPollingByVisibility,
} from '~/pipelines/components/graph/utils';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import PipelineEditorMiniGraph from './pipeline_editor_mini_graph.vue';
const POLL_INTERVAL = 10000;
@@ -21,6 +20,10 @@ export const i18n = {
`Pipeline|Pipeline %{idStart}#%{idEnd} %{statusStart}%{statusEnd} for %{commitStart}%{commitEnd}`,
),
viewBtn: s__('Pipeline|View pipeline'),
+ viewCommit: s__('Pipeline|View commit'),
+ pipelineNotTriggeredMsg: s__(
+ 'Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration.',
+ ),
};
export default {
@@ -34,7 +37,9 @@ export default {
GlSprintf,
PipelineEditorMiniGraph,
},
- mixins: [glFeatureFlagMixin()],
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
inject: ['projectFullPath'],
props: {
commitSha: {
@@ -59,12 +64,13 @@ export default {
};
},
update(data) {
- const { id, commitPath = '', detailedStatus = {}, stages, status } =
+ const { id, iid, commit = {}, detailedStatus = {}, stages, status } =
data.project?.pipeline || {};
return {
id,
- commitPath,
+ iid,
+ commit,
detailedStatus,
stages,
status,
@@ -73,20 +79,36 @@ export default {
result(res) {
if (res.data?.project?.pipeline) {
this.hasError = false;
+ } else {
+ this.hasError = true;
+ this.pipelineNotTriggered = true;
}
},
error() {
this.hasError = true;
+ this.networkError = true;
},
pollInterval: POLL_INTERVAL,
},
},
data() {
return {
+ networkError: false,
+ pipelineNotTriggered: false,
hasError: false,
};
},
computed: {
+ commitText() {
+ const shortSha = truncateSha(this.commitSha);
+ const commitTitle = this.pipeline.commit.title || '';
+
+ if (commitTitle.length > 0) {
+ return `${shortSha}: ${commitTitle}`;
+ }
+
+ return shortSha;
+ },
hasPipelineData() {
return Boolean(this.pipeline?.id);
},
@@ -126,13 +148,19 @@ export default {
</div>
</template>
<template v-else-if="hasError">
- <div>
+ <div v-if="networkError">
<gl-icon class="gl-mr-auto" name="warning-solid" />
<span data-testid="pipeline-error-msg">{{ $options.i18n.fetchError }}</span>
</div>
+ <div v-else>
+ <gl-icon class="gl-mr-auto" name="information-o" />
+ <span data-testid="pipeline-not-triggered-error-msg">
+ {{ $options.i18n.pipelineNotTriggeredMsg }}
+ </span>
+ </div>
</template>
<template v-else>
- <div>
+ <div class="gl-text-truncate gl-md-max-w-50p gl-mr-1">
<a :href="status.detailsPath" class="gl-mr-auto">
<ci-icon :status="status" :size="16" data-testid="pipeline-status-icon" />
</a>
@@ -144,25 +172,21 @@ export default {
<template #status>{{ status.text }}</template>
<template #commit>
<gl-link
- :href="pipeline.commitPath"
- class="commit-sha gl-font-weight-normal"
- target="_blank"
+ v-gl-tooltip.hover
+ :href="pipeline.commit.webPath"
+ :title="$options.i18n.viewCommit"
data-testid="pipeline-commit"
>
- {{ shortSha }}
+ {{ commitText }}
</gl-link>
</template>
</gl-sprintf>
</span>
</div>
<div class="gl-display-flex gl-flex-wrap">
- <pipeline-editor-mini-graph
- v-if="glFeatures.pipelineEditorMiniGraph"
- :pipeline="pipeline"
- />
+ <pipeline-editor-mini-graph :pipeline="pipeline" v-on="$listeners" />
<gl-button
class="gl-mt-2 gl-md-mt-0"
- target="_blank"
category="secondary"
variant="confirm"
:href="status.detailsPath"
diff --git a/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue b/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
index 8bffd893473..611b78b3c5e 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
@@ -75,7 +75,7 @@ export default {
return this.$options.i18n.valid;
default:
// Only display first error as a reason
- return this.ciConfig?.errors.length > 0
+ return this.ciConfig?.errors?.length > 0
? sprintf(this.$options.i18n.invalidWithReason, { reason }, false)
: this.$options.i18n.invalid;
}
diff --git a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
index f7c9f10ea46..0cd0d17d944 100644
--- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
+++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
@@ -3,15 +3,18 @@ import { GlAlert, GlLoadingIcon, GlTabs } from '@gitlab/ui';
import { s__ } from '~/locale';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { getParameterValues, setUrlParams, updateHistory } from '~/lib/utils/url_utility';
+import GitlabExperiment from '~/experimentation/components/gitlab_experiment.vue';
import {
CREATE_TAB,
EDITOR_APP_STATUS_EMPTY,
- EDITOR_APP_STATUS_ERROR,
EDITOR_APP_STATUS_INVALID,
EDITOR_APP_STATUS_LOADING,
EDITOR_APP_STATUS_VALID,
LINT_TAB,
MERGED_TAB,
+ TAB_QUERY_PARAM,
+ TABS_INDEX,
VISUALIZE_TAB,
} from '../constants';
import getAppStatus from '../graphql/queries/client/app_status.graphql';
@@ -20,6 +23,7 @@ import CiEditorHeader from './editor/ci_editor_header.vue';
import TextEditor from './editor/text_editor.vue';
import CiLint from './lint/ci_lint.vue';
import EditorTab from './ui/editor_tab.vue';
+import WalkthroughPopover from './walkthrough_popover.vue';
export default {
i18n: {
@@ -42,6 +46,9 @@ export default {
errorTexts: {
loadMergedYaml: s__('Pipelines|Could not load merged YAML content'),
},
+ query: {
+ TAB_QUERY_PARAM,
+ },
tabConstants: {
CREATE_TAB,
LINT_TAB,
@@ -58,6 +65,8 @@ export default {
GlTabs,
PipelineGraph,
TextEditor,
+ GitlabExperiment,
+ WalkthroughPopover,
},
mixins: [glFeatureFlagsMixin()],
props: {
@@ -74,6 +83,10 @@ export default {
required: false,
default: '',
},
+ isNewCiConfigFile: {
+ type: Boolean,
+ required: true,
+ },
},
apollo: {
appStatus: {
@@ -81,9 +94,8 @@ export default {
},
},
computed: {
- hasAppError() {
- // Not an invalid config and with `mergedYaml` data missing
- return this.appStatus === EDITOR_APP_STATUS_ERROR;
+ isMergedYamlAvailable() {
+ return this.ciConfigData?.mergedYaml;
},
isEmpty() {
return this.appStatus === EDITOR_APP_STATUS_EMPTY;
@@ -98,22 +110,51 @@ export default {
return this.appStatus === EDITOR_APP_STATUS_LOADING;
},
},
+ created() {
+ const [tabQueryParam] = getParameterValues(TAB_QUERY_PARAM);
+
+ if (tabQueryParam && TABS_INDEX[tabQueryParam]) {
+ this.setDefaultTab(tabQueryParam);
+ }
+ },
methods: {
setCurrentTab(tabName) {
this.$emit('set-current-tab', tabName);
},
+ setDefaultTab(tabName) {
+ // We associate tab name with the index so that we can use tab name
+ // in other part of the app and load the corresponding tab closer to the
+ // actual component using a hash that binds the name to the indexes.
+ // This also means that if we ever changed tab order, we would justs need to
+ // update `TABS_INDEX` hash instead of all the instances in the app
+ // where we used the individual indexes
+ const newUrl = setUrlParams({ [TAB_QUERY_PARAM]: TABS_INDEX[tabName] });
+
+ this.setCurrentTab(tabName);
+ updateHistory({ url: newUrl, title: document.title, replace: true });
+ },
},
};
</script>
<template>
- <gl-tabs class="file-editor gl-mb-3">
+ <gl-tabs
+ class="file-editor gl-mb-3"
+ :query-param-name="$options.query.TAB_QUERY_PARAM"
+ sync-active-tab-with-query-params
+ >
<editor-tab
class="gl-mb-3"
+ title-link-class="js-walkthrough-popover-target"
:title="$options.i18n.tabEdit"
lazy
data-testid="editor-tab"
@click="setCurrentTab($options.tabConstants.CREATE_TAB)"
>
+ <gitlab-experiment name="pipeline_editor_walkthrough">
+ <template #candidate>
+ <walkthrough-popover v-if="isNewCiConfigFile" v-on="$listeners" />
+ </template>
+ </gitlab-experiment>
<ci-editor-header />
<text-editor :commit-sha="commitSha" :value="ciFileContent" v-on="$listeners" />
</editor-tab>
@@ -154,7 +195,7 @@ export default {
@click="setCurrentTab($options.tabConstants.MERGED_TAB)"
>
<gl-loading-icon v-if="isLoading" size="lg" class="gl-m-3" />
- <gl-alert v-else-if="hasAppError" variant="danger" :dismissible="false">
+ <gl-alert v-else-if="!isMergedYamlAvailable" variant="danger" :dismissible="false">
{{ $options.errorTexts.loadMergedYaml }}
</gl-alert>
<ci-config-merged-preview v-else :ci-config-data="ciConfigData" v-on="$listeners" />
diff --git a/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_messages.vue b/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_messages.vue
index 091b202e10b..7206f19d060 100644
--- a/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_messages.vue
+++ b/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_messages.vue
@@ -8,6 +8,7 @@ import {
DEFAULT_FAILURE,
DEFAULT_SUCCESS,
LOAD_FAILURE_UNKNOWN,
+ PIPELINE_FAILURE,
} from '../../constants';
import CodeSnippetAlert from '../code_snippet_alert/code_snippet_alert.vue';
import {
@@ -24,6 +25,7 @@ export default {
[COMMIT_FAILURE]: s__('Pipelines|The GitLab CI configuration could not be updated.'),
[DEFAULT_FAILURE]: __('Something went wrong on our end.'),
[LOAD_FAILURE_UNKNOWN]: s__('Pipelines|The CI configuration was not loaded, please try again.'),
+ [PIPELINE_FAILURE]: s__('Pipelines|There was a problem with loading the pipeline data.'),
},
successTexts: {
[COMMIT_SUCCESS]: __('Your changes have been successfully committed.'),
@@ -74,6 +76,11 @@ export default {
text: this.$options.errorTexts[COMMIT_FAILURE],
variant: 'danger',
};
+ case PIPELINE_FAILURE:
+ return {
+ text: this.$options.errorTexts[PIPELINE_FAILURE],
+ variant: 'danger',
+ };
default:
return {
text: this.$options.errorTexts[DEFAULT_FAILURE],
diff --git a/app/assets/javascripts/pipeline_editor/components/walkthrough_popover.vue b/app/assets/javascripts/pipeline_editor/components/walkthrough_popover.vue
new file mode 100644
index 00000000000..5742b11b841
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/walkthrough_popover.vue
@@ -0,0 +1,83 @@
+<script>
+import { GlButton, GlPopover, GlSprintf, GlOutsideDirective as Outside } from '@gitlab/ui';
+import { s__ } from '~/locale';
+
+export default {
+ directives: { Outside },
+ i18n: {
+ title: s__('pipelineEditorWalkthrough|See how GitLab pipelines work'),
+ description: s__(
+ 'pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline.',
+ ),
+ instruction: s__(
+ 'pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline.',
+ ),
+ ctaText: s__("pipelineEditorWalkthrough|Let's do this!"),
+ },
+ components: {
+ GlButton,
+ GlPopover,
+ GlSprintf,
+ },
+ data() {
+ return {
+ show: true,
+ };
+ },
+ computed: {
+ targetElement() {
+ return document.querySelector('.js-walkthrough-popover-target');
+ },
+ },
+ methods: {
+ close() {
+ this.show = false;
+ },
+ handleClickCta() {
+ this.close();
+ this.$emit('walkthrough-popover-cta-clicked');
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-popover
+ :show.sync="show"
+ :title="$options.i18n.title"
+ :target="targetElement"
+ placement="right"
+ triggers="focus"
+ >
+ <div v-outside="close" class="gl-display-flex gl-flex-direction-column">
+ <p>
+ <gl-sprintf :message="$options.i18n.description">
+ <template #code="{ content }">
+ <code>{{ content }}</code>
+ </template>
+ </gl-sprintf>
+ </p>
+
+ <p>
+ <gl-sprintf :message="$options.i18n.instruction">
+ <template #bold="{ content }">
+ <strong>
+ {{ content }}
+ </strong>
+ </template>
+ </gl-sprintf>
+ </p>
+
+ <gl-button
+ class="gl-align-self-end"
+ category="tertiary"
+ data-testid="ctaBtn"
+ variant="confirm"
+ @click="handleClickCta"
+ >
+ <gl-emoji data-name="rocket" />
+ {{ this.$options.i18n.ctaText }}
+ </gl-button>
+ </div>
+ </gl-popover>
+</template>
diff --git a/app/assets/javascripts/pipeline_editor/constants.js b/app/assets/javascripts/pipeline_editor/constants.js
index bb03fa126a5..a2eaeeef286 100644
--- a/app/assets/javascripts/pipeline_editor/constants.js
+++ b/app/assets/javascripts/pipeline_editor/constants.js
@@ -5,24 +5,37 @@ export const CI_CONFIG_STATUS_VALID = 'VALID';
// Values for EDITOR_APP_STATUS_* are frontend specifics and
// represent the global state of the pipeline editor app.
export const EDITOR_APP_STATUS_EMPTY = 'EMPTY';
-export const EDITOR_APP_STATUS_ERROR = 'ERROR';
export const EDITOR_APP_STATUS_INVALID = CI_CONFIG_STATUS_INVALID;
export const EDITOR_APP_STATUS_LOADING = 'LOADING';
export const EDITOR_APP_STATUS_VALID = CI_CONFIG_STATUS_VALID;
+export const EDITOR_APP_VALID_STATUSES = [
+ EDITOR_APP_STATUS_EMPTY,
+ EDITOR_APP_STATUS_INVALID,
+ EDITOR_APP_STATUS_LOADING,
+ EDITOR_APP_STATUS_VALID,
+];
+
export const COMMIT_FAILURE = 'COMMIT_FAILURE';
export const COMMIT_SUCCESS = 'COMMIT_SUCCESS';
export const DEFAULT_FAILURE = 'DEFAULT_FAILURE';
export const DEFAULT_SUCCESS = 'DEFAULT_SUCCESS';
export const LOAD_FAILURE_UNKNOWN = 'LOAD_FAILURE_UNKNOWN';
+export const PIPELINE_FAILURE = 'PIPELINE_FAILURE';
export const CREATE_TAB = 'CREATE_TAB';
export const LINT_TAB = 'LINT_TAB';
export const MERGED_TAB = 'MERGED_TAB';
export const VISUALIZE_TAB = 'VISUALIZE_TAB';
-export const TABS_WITH_COMMIT_FORM = [CREATE_TAB, LINT_TAB, VISUALIZE_TAB];
+export const TABS_INDEX = {
+ [CREATE_TAB]: '0',
+ [VISUALIZE_TAB]: '1',
+ [LINT_TAB]: '2',
+ [MERGED_TAB]: '3',
+};
+export const TAB_QUERY_PARAM = 'tab';
export const COMMIT_ACTION_CREATE = 'CREATE';
export const COMMIT_ACTION_UPDATE = 'UPDATE';
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_app_status.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_app_status.mutation.graphql
new file mode 100644
index 00000000000..7487e328668
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_app_status.mutation.graphql
@@ -0,0 +1,3 @@
+mutation updateAppStatus($appStatus: String) {
+ updateAppStatus(appStatus: $appStatus) @client
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_pipeline_etag.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_pipeline_etag.mutation.graphql
new file mode 100644
index 00000000000..9025f00b343
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_pipeline_etag.mutation.graphql
@@ -0,0 +1,3 @@
+mutation updatePipelineEtag($pipelineEtag: String) {
+ updatePipelineEtag(pipelineEtag: $pipelineEtag) @client
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/is_new_ci_config_file.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/is_new_ci_config_file.graphql
deleted file mode 100644
index 8c2ca276f50..00000000000
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/client/is_new_ci_config_file.graphql
+++ /dev/null
@@ -1,3 +0,0 @@
-query getIsNewCiConfigFile {
- isNewCiConfigFile @client
-}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql
index 0c3653a2880..34e98ae3eb3 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql
@@ -1,10 +1,13 @@
query getPipeline($fullPath: ID!, $sha: String!) {
project(fullPath: $fullPath) {
pipeline(sha: $sha) {
- commitPath
id
iid
status
+ commit {
+ title
+ webPath
+ }
detailedStatus {
detailsPath
icon
diff --git a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
index a34652b1495..e4965e00af3 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
+++ b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
@@ -1,7 +1,8 @@
-import produce from 'immer';
import axios from '~/lib/utils/axios_utils';
+import getAppStatus from './queries/client/app_status.graphql';
import getCurrentBranchQuery from './queries/client/current_branch.graphql';
import getLastCommitBranchQuery from './queries/client/last_commit_branch.query.graphql';
+import getPipelineEtag from './queries/client/pipeline_etag.graphql';
export const resolvers = {
Mutation: {
@@ -31,20 +32,28 @@ export const resolvers = {
__typename: 'CiLintContent',
}));
},
+ updateAppStatus: (_, { appStatus }, { cache }) => {
+ cache.writeQuery({
+ query: getAppStatus,
+ data: { appStatus },
+ });
+ },
updateCurrentBranch: (_, { currentBranch }, { cache }) => {
cache.writeQuery({
query: getCurrentBranchQuery,
- data: produce(cache.readQuery({ query: getCurrentBranchQuery }), (draftData) => {
- draftData.currentBranch = currentBranch;
- }),
+ data: { currentBranch },
});
},
updateLastCommitBranch: (_, { lastCommitBranch }, { cache }) => {
cache.writeQuery({
query: getLastCommitBranchQuery,
- data: produce(cache.readQuery({ query: getLastCommitBranchQuery }), (draftData) => {
- draftData.lastCommitBranch = lastCommitBranch;
- }),
+ data: { lastCommitBranch },
+ });
+ },
+ updatePipelineEtag: (_, { pipelineEtag }, { cache }) => {
+ cache.writeQuery({
+ query: getPipelineEtag,
+ data: { pipelineEtag },
});
},
},
diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js
index 89b9091e6f9..4f7f2743aca 100644
--- a/app/assets/javascripts/pipeline_editor/index.js
+++ b/app/assets/javascripts/pipeline_editor/index.js
@@ -3,8 +3,10 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
+import { EDITOR_APP_STATUS_LOADING } from './constants';
import { CODE_SNIPPET_SOURCE_SETTINGS } from './components/code_snippet_alert/constants';
import getCurrentBranch from './graphql/queries/client/current_branch.graphql';
+import getAppStatus from './graphql/queries/client/app_status.graphql';
import getLastCommitBranchQuery from './graphql/queries/client/last_commit_branch.query.graphql';
import getPipelineEtag from './graphql/queries/client/pipeline_etag.graphql';
import { resolvers } from './graphql/resolvers';
@@ -59,12 +61,18 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
defaultClient: createDefaultClient(resolvers, {
typeDefs,
useGet: true,
- assumeImmutableResults: true,
}),
});
const { cache } = apolloProvider.clients.defaultClient;
cache.writeQuery({
+ query: getAppStatus,
+ data: {
+ appStatus: EDITOR_APP_STATUS_LOADING,
+ },
+ });
+
+ cache.writeQuery({
query: getCurrentBranch,
data: {
currentBranch: initialBranchName || defaultBranch,
@@ -93,6 +101,7 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
ciExamplesHelpPagePath,
ciHelpPagePath,
configurationPaths,
+ dataMethod: 'graphql',
defaultBranch,
emptyStateIllustrationPath,
helpPaths,
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index e70417145ab..68db5d8078f 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -12,16 +12,16 @@ import PipelineEditorMessages from './components/ui/pipeline_editor_messages.vue
import {
COMMIT_SHA_POLL_INTERVAL,
EDITOR_APP_STATUS_EMPTY,
- EDITOR_APP_STATUS_ERROR,
+ EDITOR_APP_VALID_STATUSES,
EDITOR_APP_STATUS_LOADING,
LOAD_FAILURE_UNKNOWN,
STARTER_TEMPLATE_NAME,
} from './constants';
+import updateAppStatus from './graphql/mutations/update_app_status.mutation.graphql';
import getBlobContent from './graphql/queries/blob_content.graphql';
import getCiConfigData from './graphql/queries/ci_config.graphql';
import getAppStatus from './graphql/queries/client/app_status.graphql';
import getCurrentBranch from './graphql/queries/client/current_branch.graphql';
-import getIsNewCiConfigFile from './graphql/queries/client/is_new_ci_config_file.graphql';
import getTemplate from './graphql/queries/get_starter_template.query.graphql';
import getLatestCommitShaQuery from './graphql/queries/latest_commit_sha.query.graphql';
import PipelineEditorHome from './pipeline_editor_home.vue';
@@ -44,23 +44,23 @@ export default {
},
data() {
return {
- starterTemplateName: STARTER_TEMPLATE_NAME,
ciConfigData: {},
+ currentCiFileContent: '',
failureType: null,
failureReasons: [],
initialCiFileContent: '',
isFetchingCommitSha: false,
isNewCiConfigFile: false,
lastCommittedContent: '',
- currentCiFileContent: '',
- successType: null,
+ shouldSkipStartScreen: false,
+ showFailure: false,
showStartScreen: false,
showSuccess: false,
- showFailure: false,
starterTemplate: '',
+ starterTemplateName: STARTER_TEMPLATE_NAME,
+ successType: null,
};
},
-
apollo: {
initialCiFileContent: {
fetchPolicy: fetchPolicies.NETWORK_ONLY,
@@ -103,7 +103,11 @@ export default {
}
if (!hasCIFile) {
- this.showStartScreen = true;
+ if (this.shouldSkipStartScreen) {
+ this.setNewEmptyCiConfigFile();
+ } else {
+ this.showStartScreen = true;
+ }
} else if (fileContent.length) {
// If the file content is > 0, then we make sure to reset the
// start screen flag during a refetch
@@ -141,10 +145,10 @@ export default {
return { ...ciConfig, stages };
},
result({ data }) {
- this.setAppStatus(data?.ciConfig?.status || EDITOR_APP_STATUS_ERROR);
+ this.setAppStatus(data?.ciConfig?.status);
},
- error() {
- this.reportFailure(LOAD_FAILURE_UNKNOWN);
+ error(err) {
+ this.reportFailure(LOAD_FAILURE_UNKNOWN, [String(err)]);
},
watchLoading(isLoading) {
if (isLoading) {
@@ -179,9 +183,6 @@ export default {
currentBranch: {
query: getCurrentBranch,
},
- isNewCiConfigFile: {
- query: getIsNewCiConfigFile,
- },
starterTemplate: {
query: getTemplate,
variables() {
@@ -232,6 +233,7 @@ export default {
},
mounted() {
this.loadTemplateFromURL();
+ this.checkShouldSkipStartScreen();
},
methods: {
hideFailure() {
@@ -245,8 +247,6 @@ export default {
await this.$apollo.queries.initialCiFileContent.refetch();
},
reportFailure(type, reasons = []) {
- this.setAppStatus(EDITOR_APP_STATUS_ERROR);
-
window.scrollTo({ top: 0, behavior: 'smooth' });
this.showFailure = true;
this.failureType = type;
@@ -261,12 +261,12 @@ export default {
this.currentCiFileContent = this.lastCommittedContent;
},
setAppStatus(appStatus) {
- this.$apollo.getClient().writeQuery({ query: getAppStatus, data: { appStatus } });
+ if (EDITOR_APP_VALID_STATUSES.includes(appStatus)) {
+ this.$apollo.mutate({ mutation: updateAppStatus, variables: { appStatus } });
+ }
},
setNewEmptyCiConfigFile() {
- this.$apollo
- .getClient()
- .writeQuery({ query: getIsNewCiConfigFile, data: { isNewCiConfigFile: true } });
+ this.isNewCiConfigFile = true;
this.showStartScreen = false;
},
showErrorAlert({ type, reasons = [] }) {
@@ -283,9 +283,7 @@ export default {
this.reportSuccess(type);
if (this.isNewCiConfigFile) {
- this.$apollo
- .getClient()
- .writeQuery({ query: getIsNewCiConfigFile, data: { isNewCiConfigFile: false } });
+ this.isNewCiConfigFile = false;
}
// Keep track of the latest committed content to know
@@ -300,6 +298,10 @@ export default {
this.setNewEmptyCiConfigFile();
}
},
+ checkShouldSkipStartScreen() {
+ const params = queryToObject(window.location.search);
+ this.shouldSkipStartScreen = Boolean(params?.add_new_config_file);
+ },
},
};
</script>
@@ -325,8 +327,9 @@ export default {
<pipeline-editor-home
:ci-config-data="ciConfigData"
:ci-file-content="currentCiFileContent"
- :is-new-ci-config-file="isNewCiConfigFile"
:commit-sha="commitSha"
+ :has-unsaved-changes="hasUnsavedChanges"
+ :is-new-ci-config-file="isNewCiConfigFile"
@commit="updateOnCommit"
@resetContent="resetContent"
@showError="showErrorAlert"
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
index ba567023946..8e8f31a4acc 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
@@ -1,14 +1,31 @@
<script>
+import { GlModal } from '@gitlab/ui';
+import { __ } from '~/locale';
import CommitSection from './components/commit/commit_section.vue';
import PipelineEditorDrawer from './components/drawer/pipeline_editor_drawer.vue';
import PipelineEditorFileNav from './components/file_nav/pipeline_editor_file_nav.vue';
import PipelineEditorHeader from './components/header/pipeline_editor_header.vue';
import PipelineEditorTabs from './components/pipeline_editor_tabs.vue';
-import { TABS_WITH_COMMIT_FORM, CREATE_TAB } from './constants';
+import { CREATE_TAB } from './constants';
export default {
+ commitSectionRef: 'commitSectionRef',
+ modal: {
+ switchBranch: {
+ title: __('You have unsaved changes'),
+ body: __('Uncommitted changes will be lost if you change branches. Do you want to continue?'),
+ actionPrimary: {
+ text: __('Switch Branches'),
+ },
+ actionSecondary: {
+ text: __('Cancel'),
+ attributes: { variant: 'default' },
+ },
+ },
+ },
components: {
CommitSection,
+ GlModal,
PipelineEditorDrawer,
PipelineEditorFileNav,
PipelineEditorHeader,
@@ -28,6 +45,11 @@ export default {
required: false,
default: '',
},
+ hasUnsavedChanges: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
isNewCiConfigFile: {
type: Boolean,
required: true,
@@ -36,40 +58,82 @@ export default {
data() {
return {
currentTab: CREATE_TAB,
+ scrollToCommitForm: false,
+ shouldLoadNewBranch: false,
+ showSwitchBranchModal: false,
};
},
computed: {
showCommitForm() {
- return TABS_WITH_COMMIT_FORM.includes(this.currentTab);
+ return this.currentTab === CREATE_TAB;
},
},
methods: {
+ closeBranchModal() {
+ this.showSwitchBranchModal = false;
+ },
+ handleConfirmSwitchBranch() {
+ this.showSwitchBranchModal = true;
+ },
+ switchBranch() {
+ this.showSwitchBranchModal = false;
+ this.shouldLoadNewBranch = true;
+ },
setCurrentTab(tabName) {
this.currentTab = tabName;
},
+ setScrollToCommitForm(newValue = true) {
+ this.scrollToCommitForm = newValue;
+ },
},
};
</script>
<template>
<div class="gl-pr-9 gl-transition-medium gl-w-full">
- <pipeline-editor-file-nav v-on="$listeners" />
+ <gl-modal
+ v-if="showSwitchBranchModal"
+ visible
+ modal-id="switchBranchModal"
+ :title="$options.modal.switchBranch.title"
+ :action-primary="$options.modal.switchBranch.actionPrimary"
+ :action-secondary="$options.modal.switchBranch.actionSecondary"
+ @primary="switchBranch"
+ @secondary="closeBranchModal"
+ @cancel="closeBranchModal"
+ @hide="closeBranchModal"
+ >
+ {{ $options.modal.switchBranch.body }}
+ </gl-modal>
+ <pipeline-editor-file-nav
+ :has-unsaved-changes="hasUnsavedChanges"
+ :should-load-new-branch="shouldLoadNewBranch"
+ @select-branch="handleConfirmSwitchBranch"
+ v-on="$listeners"
+ />
<pipeline-editor-header
:ci-config-data="ciConfigData"
:commit-sha="commitSha"
:is-new-ci-config-file="isNewCiConfigFile"
+ v-on="$listeners"
/>
<pipeline-editor-tabs
:ci-config-data="ciConfigData"
:ci-file-content="ciFileContent"
:commit-sha="commitSha"
+ :is-new-ci-config-file="isNewCiConfigFile"
v-on="$listeners"
@set-current-tab="setCurrentTab"
+ @walkthrough-popover-cta-clicked="setScrollToCommitForm"
/>
<commit-section
v-if="showCommitForm"
+ :ref="$options.commitSectionRef"
:ci-file-content="ciFileContent"
:commit-sha="commitSha"
+ :is-new-ci-config-file="isNewCiConfigFile"
+ :scroll-to-commit-form="scrollToCommitForm"
+ @scrolled-to-commit-form="setScrollToCommitForm(false)"
v-on="$listeners"
/>
<pipeline-editor-drawer />
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
index b778fe28e59..9725e882d5e 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
@@ -95,9 +95,9 @@ export default {
{{ $options.i18n.artifactsFetchErrorMessage }}
</gl-alert>
- <gl-loading-icon v-if="isLoading" size="sm" />
+ <gl-loading-icon v-else-if="isLoading" size="sm" />
- <gl-dropdown-item v-if="!artifacts.length && !isLoading" data-testid="artifacts-empty-message">
+ <gl-dropdown-item v-else-if="!artifacts.length" data-testid="artifacts-empty-message">
{{ $options.i18n.emptyArtifactsMessage }}
</gl-dropdown-item>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
index 1c7c4d7c704..7d0cea67099 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
@@ -1,20 +1,15 @@
<script>
import {
- GlAlert,
GlDropdown,
GlDropdownItem,
GlDropdownSectionHeader,
- GlLoadingIcon,
GlTooltipDirective,
} from '@gitlab/ui';
-import axios from '~/lib/utils/axios_utils';
-import { __, s__ } from '~/locale';
+import { __ } from '~/locale';
export const i18n = {
artifacts: __('Artifacts'),
artifactSectionHeader: __('Download artifacts'),
- artifactsFetchErrorMessage: s__('Pipelines|Could not load artifacts.'),
- noArtifacts: s__('Pipelines|No artifacts available'),
};
export default {
@@ -23,11 +18,9 @@ export default {
GlTooltip: GlTooltipDirective,
},
components: {
- GlAlert,
GlDropdown,
GlDropdownItem,
GlDropdownSectionHeader,
- GlLoadingIcon,
},
inject: {
artifactsEndpoint: {
@@ -42,44 +35,22 @@ export default {
type: Number,
required: true,
},
- },
- data() {
- return {
- artifacts: [],
- hasError: false,
- isLoading: false,
- };
- },
- computed: {
- hasArtifacts() {
- return Boolean(this.artifacts.length);
+ artifacts: {
+ type: Array,
+ required: false,
+ default: () => [],
},
},
- methods: {
- fetchArtifacts() {
- this.isLoading = true;
- // Replace the placeholder with the ID of the pipeline we are viewing
- const endpoint = this.artifactsEndpoint.replace(
- this.artifactsEndpointPlaceholder,
- this.pipelineId,
- );
- return axios
- .get(endpoint)
- .then(({ data }) => {
- this.artifacts = data.artifacts;
- })
- .catch(() => {
- this.hasError = true;
- })
- .finally(() => {
- this.isLoading = false;
- });
+ computed: {
+ shouldShowDropdown() {
+ return this.artifacts?.length;
},
},
};
</script>
<template>
<gl-dropdown
+ v-if="shouldShowDropdown"
v-gl-tooltip
class="build-artifacts js-pipeline-dropdown-download"
:title="$options.i18n.artifacts"
@@ -89,22 +60,11 @@ export default {
right
lazy
text-sr-only
- @show.once="fetchArtifacts"
>
<gl-dropdown-section-header>{{
$options.i18n.artifactSectionHeader
}}</gl-dropdown-section-header>
- <gl-alert v-if="hasError" variant="danger" :dismissible="false">
- {{ $options.i18n.artifactsFetchErrorMessage }}
- </gl-alert>
-
- <gl-loading-icon v-if="isLoading" size="sm" />
-
- <gl-alert v-else-if="!hasArtifacts" variant="info" :dismissible="false">
- {{ $options.i18n.noArtifacts }}
- </gl-alert>
-
<gl-dropdown-item
v-for="(artifact, i) in artifacts"
:key="i"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue
index c6c81d5253b..83f6356f31a 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue
@@ -76,7 +76,7 @@ export default {
</p>
<div class="row gl-mb-8">
- <div class="col-lg-3">
+ <div class="col-12">
<gl-card>
<div class="gl-flex-direction-row">
<div class="gl-py-5"><gl-emoji class="gl-font-size-h2-xl" data-name="wave" /></div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
index 12ee82f0390..d64decc81ec 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTable, GlTooltipDirective } from '@gitlab/ui';
+import { GlTableLite, GlTooltipDirective } from '@gitlab/ui';
import { s__ } from '~/locale';
import eventHub from '../../event_hub';
import PipelineMiniGraph from './pipeline_mini_graph.vue';
@@ -18,7 +18,7 @@ const DEFAULT_TH_CLASSES =
export default {
components: {
- GlTable,
+ GlTableLite,
LinkedPipelinesMiniList: () =>
import('ee_component/vue_shared/components/linked_pipelines_mini_list.vue'),
PipelinesCommit,
@@ -156,7 +156,7 @@ export default {
</script>
<template>
<div class="ci-table">
- <gl-table
+ <gl-table-lite
:fields="tableFields"
:items="pipelines"
tbody-tr-class="commit"
@@ -225,7 +225,7 @@ export default {
<template #cell(actions)="{ item }">
<pipeline-operations :pipeline="item" :canceling-pipeline="cancelingPipeline" />
</template>
- </gl-table>
+ </gl-table-lite>
<pipeline-stop-modal :pipeline="pipeline" @submit="onSubmit" />
</div>
diff --git a/app/assets/javascripts/pipelines/constants.js b/app/assets/javascripts/pipelines/constants.js
index 5678b613ec6..d123f7a203c 100644
--- a/app/assets/javascripts/pipelines/constants.js
+++ b/app/assets/javascripts/pipelines/constants.js
@@ -49,3 +49,5 @@ export const PipelineKeyOptions = [
key: 'iid',
},
];
+
+export const TOAST_MESSAGE = s__('Pipeline|Creating pipeline.');
diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql
index de8de651eea..8fcae9dbad8 100644
--- a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql
+++ b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql
@@ -18,8 +18,11 @@ query getPipelineHeaderData($fullPath: ID!, $iid: ID!) {
}
createdAt
user {
+ id
name
+ username
webPath
+ webUrl
email
avatarUrl
status {
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
index 082d67c938c..3201f88a9e3 100644
--- a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
+++ b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
@@ -4,7 +4,7 @@ import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/commo
import Poll from '~/lib/utils/poll';
import { __ } from '~/locale';
import { validateParams } from '~/pipelines/utils';
-import { CANCEL_REQUEST } from '../constants';
+import { CANCEL_REQUEST, TOAST_MESSAGE } from '../constants';
import eventHub from '../event_hub';
export default {
@@ -191,7 +191,10 @@ export default {
this.service
.runMRPipeline(options)
- .then(() => this.updateTable())
+ .then(() => {
+ this.$toast.show(TOAST_MESSAGE);
+ this.updateTable();
+ })
.catch(() => {
createFlash({
message: __(
diff --git a/app/assets/javascripts/pipelines/pipeline_shared_client.js b/app/assets/javascripts/pipelines/pipeline_shared_client.js
index 7a922acd0b3..c3be487caae 100644
--- a/app/assets/javascripts/pipelines/pipeline_shared_client.js
+++ b/app/assets/javascripts/pipelines/pipeline_shared_client.js
@@ -5,7 +5,6 @@ export const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(
{},
{
- assumeImmutableResults: true,
useGet: true,
},
),
diff --git a/app/assets/javascripts/profile/account/components/delete_account_modal.vue b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
index 17cbcabeedb..3cb2dce87d3 100644
--- a/app/assets/javascripts/profile/account/components/delete_account_modal.vue
+++ b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
@@ -37,7 +37,7 @@ export default {
},
primaryProps() {
return {
- text: s__('Delete account'),
+ text: __('Delete account'),
attributes: [
{ variant: 'danger', 'data-qa-selector': 'confirm_delete_account_button' },
{ category: 'primary' },
@@ -47,7 +47,7 @@ export default {
},
cancelProps() {
return {
- text: s__('Cancel'),
+ text: __('Cancel'),
};
},
canSubmit() {
diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue
index 7917a9a75e0..45a6130826d 100644
--- a/app/assets/javascripts/profile/account/components/update_username.vue
+++ b/app/assets/javascripts/profile/account/components/update_username.vue
@@ -3,7 +3,7 @@ import { GlSafeHtmlDirective as SafeHtml, GlButton, GlModal, GlModalDirective }
import { escape } from 'lodash';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
export default {
components: {
@@ -58,7 +58,7 @@ Please update your Git repository remotes as soon as possible.`),
},
primaryProps() {
return {
- text: s__('Update username'),
+ text: __('Update username'),
attributes: [
{ variant: 'warning' },
{ category: 'primary' },
@@ -68,7 +68,7 @@ Please update your Git repository remotes as soon as possible.`),
},
cancelProps() {
return {
- text: s__('Cancel'),
+ text: __('Cancel'),
};
},
},
diff --git a/app/assets/javascripts/project_visibility.js b/app/assets/javascripts/project_visibility.js
index e3868e2925d..1b57a69d464 100644
--- a/app/assets/javascripts/project_visibility.js
+++ b/app/assets/javascripts/project_visibility.js
@@ -1,42 +1,58 @@
import $ from 'jquery';
+import eventHub from '~/projects/new/event_hub';
-function setVisibilityOptions(namespaceSelector) {
- if (!namespaceSelector || !('selectedIndex' in namespaceSelector)) {
- return;
- }
- const selectedNamespace = namespaceSelector.options[namespaceSelector.selectedIndex];
- const { name, visibility, visibilityLevel, showPath, editPath } = selectedNamespace.dataset;
+// Values are from lib/gitlab/visibility_level.rb
+const visibilityLevel = {
+ private: 0,
+ internal: 10,
+ public: 20,
+};
+function setVisibilityOptions({ name, visibility, showPath, editPath }) {
document.querySelectorAll('.visibility-level-setting .form-check').forEach((option) => {
+ // Don't change anything if the option is restricted by admin
+ if (option.classList.contains('restricted')) {
+ return;
+ }
+
const optionInput = option.querySelector('input[type=radio]');
- const optionValue = optionInput ? optionInput.value : 0;
- const optionTitle = option.querySelector('.option-title');
- const optionName = optionTitle ? optionTitle.innerText.toLowerCase() : '';
+ const optionValue = optionInput ? parseInt(optionInput.value, 10) : 0;
- // don't change anything if the option is restricted by admin
- if (!option.classList.contains('restricted')) {
- if (visibilityLevel < optionValue) {
- option.classList.add('disabled');
- optionInput.disabled = true;
- const reason = option.querySelector('.option-disabled-reason');
- if (reason) {
- reason.innerHTML = `This project cannot be ${optionName} because the visibility of
+ if (visibilityLevel[visibility] < optionValue) {
+ option.classList.add('disabled');
+ optionInput.disabled = true;
+ const reason = option.querySelector('.option-disabled-reason');
+ if (reason) {
+ const optionTitle = option.querySelector('.option-title');
+ const optionName = optionTitle ? optionTitle.innerText.toLowerCase() : '';
+ reason.innerHTML = `This project cannot be ${optionName} because the visibility of
<a href="${showPath}">${name}</a> is ${visibility}. To make this project
${optionName}, you must first <a href="${editPath}">change the visibility</a>
of the parent group.`;
- }
- } else {
- option.classList.remove('disabled');
- optionInput.disabled = false;
}
+ } else {
+ option.classList.remove('disabled');
+ optionInput.disabled = false;
}
});
}
+function handleSelect2DropdownChange(namespaceSelector) {
+ if (!namespaceSelector || !('selectedIndex' in namespaceSelector)) {
+ return;
+ }
+ const selectedNamespace = namespaceSelector.options[namespaceSelector.selectedIndex];
+ setVisibilityOptions(selectedNamespace.dataset);
+}
+
export default function initProjectVisibilitySelector() {
+ eventHub.$on('update-visibility', setVisibilityOptions);
+
const namespaceSelector = document.querySelector('select.js-select-namespace');
if (namespaceSelector) {
- $('.select2.js-select-namespace').on('change', () => setVisibilityOptions(namespaceSelector));
- setVisibilityOptions(namespaceSelector);
+ $('.select2.js-select-namespace').on('change', () =>
+ handleSelect2DropdownChange(namespaceSelector),
+ );
+ handleSelect2DropdownChange(namespaceSelector);
}
}
diff --git a/app/assets/javascripts/projects/commit/components/form_modal.vue b/app/assets/javascripts/projects/commit/components/form_modal.vue
index ec7d37644a8..f9dd72119d1 100644
--- a/app/assets/javascripts/projects/commit/components/form_modal.vue
+++ b/app/assets/javascripts/projects/commit/components/form_modal.vue
@@ -1,6 +1,7 @@
<script>
import { GlModal, GlForm, GlFormCheckbox, GlSprintf, GlFormGroup } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
+import api from '~/api';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import csrf from '~/lib/utils/csrf';
import eventHub from '../event_hub';
@@ -40,6 +41,11 @@ export default {
required: false,
default: false,
},
+ primaryActionEventName: {
+ type: String,
+ required: false,
+ default: null,
+ },
},
data() {
return {
@@ -83,6 +89,10 @@ export default {
this.$root.$emit(BV_SHOW_MODAL, this.modalId);
},
handlePrimary() {
+ if (this.primaryActionEventName) {
+ api.trackRedisHllUserEvent(this.primaryActionEventName);
+ }
+
this.$refs.form.$el.submit();
},
resetModalHandler() {
diff --git a/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js b/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js
index 47ee8237fea..b21fd1a74de 100644
--- a/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js
+++ b/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js
@@ -9,7 +9,7 @@ import {
} from './constants';
import createStore from './store';
-export default function initInviteMembersModal() {
+export default function initInviteMembersModal(primaryActionEventName) {
const el = document.querySelector('.js-cherry-pick-commit-modal');
if (!el) {
return false;
@@ -52,6 +52,7 @@ export default function initInviteMembersModal() {
openModal: OPEN_CHERRY_PICK_MODAL,
modalId: CHERRY_PICK_MODAL_ID,
isCherryPick: true,
+ primaryActionEventName,
},
}),
});
diff --git a/app/assets/javascripts/projects/commit/init_revert_commit_modal.js b/app/assets/javascripts/projects/commit/init_revert_commit_modal.js
index df26aa3c830..849b2f4858c 100644
--- a/app/assets/javascripts/projects/commit/init_revert_commit_modal.js
+++ b/app/assets/javascripts/projects/commit/init_revert_commit_modal.js
@@ -10,7 +10,7 @@ import {
} from './constants';
import createStore from './store';
-export default function initInviteMembersModal() {
+export default function initInviteMembersModal(primaryActionEventName) {
const el = document.querySelector('.js-revert-commit-modal');
if (!el) {
return false;
@@ -49,6 +49,7 @@ export default function initInviteMembersModal() {
i18n: { ...I18N_REVERT_MODAL, ...I18N_MODAL },
openModal: OPEN_REVERT_MODAL,
modalId: REVERT_MODAL_ID,
+ primaryActionEventName,
},
}),
});
diff --git a/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js b/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js
index 2505c47147f..1d4ec4c110b 100644
--- a/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js
+++ b/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js
@@ -5,12 +5,7 @@ import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- ),
+ defaultClient: createDefaultClient(),
});
export const initCommitPipelineMiniGraph = async (selector = '.js-commit-pipeline-mini-graph') => {
diff --git a/app/assets/javascripts/projects/components/project_delete_button.vue b/app/assets/javascripts/projects/components/project_delete_button.vue
index 06711e4025a..eaf93e2da4f 100644
--- a/app/assets/javascripts/projects/components/project_delete_button.vue
+++ b/app/assets/javascripts/projects/components/project_delete_button.vue
@@ -18,12 +18,36 @@ export default {
type: String,
required: true,
},
+ isFork: {
+ type: Boolean,
+ required: true,
+ },
+ issuesCount: {
+ type: Number,
+ required: true,
+ },
+ mergeRequestsCount: {
+ type: Number,
+ required: true,
+ },
+ forksCount: {
+ type: Number,
+ required: true,
+ },
+ starsCount: {
+ type: Number,
+ required: true,
+ },
},
strings: {
alertTitle: __('You are about to permanently delete this project'),
alertBody: __(
- 'Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc.',
+ 'After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc.',
+ ),
+ isNotForkMessage: __(
+ 'This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:',
),
+ isForkMessage: __('This forked project has the following:'),
},
};
</script>
@@ -37,6 +61,38 @@ export default {
:title="$options.strings.alertTitle"
:dismissible="false"
>
+ <p>
+ <gl-sprintf v-if="isFork" :message="$options.strings.isForkMessage" />
+ <gl-sprintf v-else :message="$options.strings.isNotForkMessage">
+ <template #strong="{ content }">
+ <strong>{{ content }}</strong>
+ </template>
+ </gl-sprintf>
+ </p>
+ <ul>
+ <li>
+ <gl-sprintf :message="n__('%d issue', '%d issues', issuesCount)">
+ <template #issuesCount>{{ issuesCount }}</template>
+ </gl-sprintf>
+ </li>
+ <li>
+ <gl-sprintf
+ :message="n__('%d merge requests', '%d merge requests', mergeRequestsCount)"
+ >
+ <template #mergeRequestsCount>{{ mergeRequestsCount }}</template>
+ </gl-sprintf>
+ </li>
+ <li>
+ <gl-sprintf :message="n__('%d fork', '%d forks', forksCount)">
+ <template #forksCount>{{ forksCount }}</template>
+ </gl-sprintf>
+ </li>
+ <li>
+ <gl-sprintf :message="n__('%d star', '%d stars', starsCount)">
+ <template #starsCount>{{ starsCount }}</template>
+ </gl-sprintf>
+ </li>
+ </ul>
<gl-sprintf :message="$options.strings.alertBody">
<template #strong="{ content }">
<strong>{{ content }}</strong>
diff --git a/app/assets/javascripts/projects/default_project_templates.js b/app/assets/javascripts/projects/default_project_templates.js
index 2da9449d24e..0393d82ca36 100644
--- a/app/assets/javascripts/projects/default_project_templates.js
+++ b/app/assets/javascripts/projects/default_project_templates.js
@@ -93,6 +93,10 @@ export default {
text: s__('ProjectTemplates|Serverless Framework/JS'),
icon: '.template-option .icon-serverless_framework',
},
+ tencent_serverless_framework: {
+ text: s__('ProjectTemplates|Tencent Serverless Framework/NextjsSSR'),
+ icon: '.template-option .icon-tencent_serverless_framework',
+ },
cluster_management: {
text: s__('ProjectTemplates|GitLab Cluster Management'),
icon: '.template-option .icon-cluster_management',
diff --git a/app/assets/javascripts/projects/details/upload_button.vue b/app/assets/javascripts/projects/details/upload_button.vue
index 5b19f15c233..e1c8c66a214 100644
--- a/app/assets/javascripts/projects/details/upload_button.vue
+++ b/app/assets/javascripts/projects/details/upload_button.vue
@@ -1,7 +1,6 @@
<script>
import { GlButton, GlModalDirective } from '@gitlab/ui';
import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
-import { trackFileUploadEvent } from '../upload_file_experiment_tracking';
const UPLOAD_BLOB_MODAL_ID = 'details-modal-upload-blob';
@@ -30,11 +29,6 @@ export default {
default: '',
},
},
- methods: {
- trackOpenModal() {
- trackFileUploadEvent('click_upload_modal_trigger');
- },
- },
uploadBlobModalId: UPLOAD_BLOB_MODAL_ID,
};
</script>
@@ -44,7 +38,6 @@ export default {
v-gl-modal="$options.uploadBlobModalId"
icon="upload"
data-testid="upload-file-button"
- @click="trackOpenModal"
>{{ __('Upload File') }}</gl-button
>
<upload-blob-modal
diff --git a/app/assets/javascripts/projects/new/components/app.vue b/app/assets/javascripts/projects/new/components/app.vue
index 6e9efc50be8..476d6466cbb 100644
--- a/app/assets/javascripts/projects/new/components/app.vue
+++ b/app/assets/javascripts/projects/new/components/app.vue
@@ -95,7 +95,7 @@ export default {
<template>
<new-namespace-page
- :initial-breadcrumb="s__('New project')"
+ :initial-breadcrumb="__('New project')"
:panels="availablePanels"
:jump-to-last-persisted-panel="hasErrors"
:title="s__('ProjectsNew|Create new project')"
diff --git a/app/assets/javascripts/projects/new/components/new_project_url_select.vue b/app/assets/javascripts/projects/new/components/new_project_url_select.vue
index bf44ff70562..e0ba60074af 100644
--- a/app/assets/javascripts/projects/new/components/new_project_url_select.vue
+++ b/app/assets/javascripts/projects/new/components/new_project_url_select.vue
@@ -6,9 +6,9 @@ import {
GlDropdownItem,
GlDropdownText,
GlDropdownSectionHeader,
- GlLoadingIcon,
GlSearchBoxByType,
} from '@gitlab/ui';
+import { joinPaths } from '~/lib/utils/url_utility';
import { MINIMUM_SEARCH_LENGTH } from '~/graphql_shared/constants';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import Tracking from '~/tracking';
@@ -24,7 +24,6 @@ export default {
GlDropdownItem,
GlDropdownText,
GlDropdownSectionHeader,
- GlLoadingIcon,
GlSearchBoxByType,
},
mixins: [Tracking.mixin()],
@@ -103,6 +102,15 @@ export default {
focusInput() {
this.$refs.search.focusInput();
},
+ handleDropdownItemClick(namespace) {
+ eventHub.$emit('update-visibility', {
+ name: namespace.name,
+ visibility: namespace.visibility,
+ showPath: namespace.webUrl,
+ editPath: joinPaths(namespace.webUrl, '-', 'edit'),
+ });
+ this.setNamespace(namespace);
+ },
handleSelectTemplate(groupId) {
this.groupToFilterBy = this.userGroups.find(
(group) => getIdFromGraphQLId(group.id) === groupId,
@@ -134,23 +142,23 @@ export default {
<gl-search-box-by-type
ref="search"
v-model.trim="search"
+ :is-loading="$apollo.queries.currentUser.loading"
data-qa-selector="select_namespace_dropdown_search_field"
/>
- <gl-loading-icon v-if="$apollo.queries.currentUser.loading" />
- <template v-else>
+ <template v-if="!$apollo.queries.currentUser.loading">
<template v-if="hasGroupMatches">
<gl-dropdown-section-header>{{ __('Groups') }}</gl-dropdown-section-header>
<gl-dropdown-item
v-for="group of filteredGroups"
:key="group.id"
- @click="setNamespace(group)"
+ @click="handleDropdownItemClick(group)"
>
{{ group.fullPath }}
</gl-dropdown-item>
</template>
<template v-if="hasNamespaceMatches">
<gl-dropdown-section-header>{{ __('Users') }}</gl-dropdown-section-header>
- <gl-dropdown-item @click="setNamespace(userNamespace)">
+ <gl-dropdown-item @click="handleDropdownItemClick(userNamespace)">
{{ userNamespace.fullPath }}
</gl-dropdown-item>
</template>
@@ -158,6 +166,11 @@ export default {
</template>
</gl-dropdown>
- <input type="hidden" name="project[namespace_id]" :value="selectedNamespace.id" />
+ <input
+ id="project_namespace_id"
+ type="hidden"
+ name="project[namespace_id]"
+ :value="selectedNamespace.id"
+ />
</gl-button-group>
</template>
diff --git a/app/assets/javascripts/projects/new/index.js b/app/assets/javascripts/projects/new/index.js
index 572d3276e4f..010c6a29ae3 100644
--- a/app/assets/javascripts/projects/new/index.js
+++ b/app/assets/javascripts/projects/new/index.js
@@ -50,7 +50,7 @@ export function initNewProjectUrlSelect() {
new Vue({
el,
apolloProvider: new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
}),
provide: {
namespaceFullPath: el.dataset.namespaceFullPath,
diff --git a/app/assets/javascripts/projects/new/queries/search_namespaces_where_user_can_create_projects.query.graphql b/app/assets/javascripts/projects/new/queries/search_namespaces_where_user_can_create_projects.query.graphql
index e16fe5dde49..74febec5a51 100644
--- a/app/assets/javascripts/projects/new/queries/search_namespaces_where_user_can_create_projects.query.graphql
+++ b/app/assets/javascripts/projects/new/queries/search_namespaces_where_user_can_create_projects.query.graphql
@@ -4,6 +4,9 @@ query searchNamespacesWhereUserCanCreateProjects($search: String) {
nodes {
id
fullPath
+ name
+ visibility
+ webUrl
}
}
namespace {
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/app.vue b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
index 25bacc1cc4a..7379d5caed7 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/app.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
@@ -11,12 +11,17 @@ export default {
DeploymentFrequencyCharts: () =>
import('ee_component/dora/components/deployment_frequency_charts.vue'),
LeadTimeCharts: () => import('ee_component/dora/components/lead_time_charts.vue'),
+ ProjectQualitySummary: () => import('ee_component/project_quality_summary/app.vue'),
},
inject: {
shouldRenderDoraCharts: {
type: Boolean,
default: false,
},
+ shouldRenderQualitySummary: {
+ type: Boolean,
+ default: false,
+ },
},
data() {
return {
@@ -31,6 +36,10 @@ export default {
chartsToShow.push('deployment-frequency', 'lead-time');
}
+ if (this.shouldRenderQualitySummary) {
+ chartsToShow.push('project-quality');
+ }
+
return chartsToShow;
},
},
@@ -68,6 +77,9 @@ export default {
<lead-time-charts />
</gl-tab>
</template>
+ <gl-tab v-if="shouldRenderQualitySummary" :title="s__('QualitySummary|Project quality')">
+ <project-quality-summary />
+ </gl-tab>
</gl-tabs>
<pipeline-charts v-else />
</div>
diff --git a/app/assets/javascripts/projects/pipelines/charts/index.js b/app/assets/javascripts/projects/pipelines/charts/index.js
index f7ea89068a0..003b61d94b1 100644
--- a/app/assets/javascripts/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/projects/pipelines/charts/index.js
@@ -7,13 +7,14 @@ import ProjectPipelinesCharts from './components/app.vue';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
const mountPipelineChartsApp = (el) => {
const { projectPath } = el.dataset;
const shouldRenderDoraCharts = parseBoolean(el.dataset.shouldRenderDoraCharts);
+ const shouldRenderQualitySummary = parseBoolean(el.dataset.shouldRenderQualitySummary);
return new Vue({
el,
@@ -25,6 +26,7 @@ const mountPipelineChartsApp = (el) => {
provide: {
projectPath,
shouldRenderDoraCharts,
+ shouldRenderQualitySummary,
},
render: (createElement) => createElement(ProjectPipelinesCharts, {}),
});
diff --git a/app/assets/javascripts/projects/project_delete_button.js b/app/assets/javascripts/projects/project_delete_button.js
index aa7fc31d307..b4d388eda3a 100644
--- a/app/assets/javascripts/projects/project_delete_button.js
+++ b/app/assets/javascripts/projects/project_delete_button.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
import ProjectDeleteButton from './components/project_delete_button.vue';
export default (selector = '#js-project-delete-button') => {
@@ -6,7 +7,15 @@ export default (selector = '#js-project-delete-button') => {
if (!el) return;
- const { confirmPhrase, formPath } = el.dataset;
+ const {
+ confirmPhrase,
+ formPath,
+ isFork,
+ issuesCount,
+ mergeRequestsCount,
+ forksCount,
+ starsCount,
+ } = el.dataset;
// eslint-disable-next-line no-new
new Vue({
@@ -16,6 +25,11 @@ export default (selector = '#js-project-delete-button') => {
props: {
confirmPhrase,
formPath,
+ isFork: parseBoolean(isFork),
+ issuesCount: parseInt(issuesCount, 10),
+ mergeRequestsCount: parseInt(mergeRequestsCount, 10),
+ forksCount: parseInt(forksCount, 10),
+ starsCount: parseInt(starsCount, 10),
},
});
},
diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js
index b350db0c838..8d71a3dab68 100644
--- a/app/assets/javascripts/projects/project_new.js
+++ b/app/assets/javascripts/projects/project_new.js
@@ -43,6 +43,8 @@ const onProjectPathChange = ($projectNameInput, $projectPathInput, hasExistingPr
};
const setProjectNamePathHandlers = ($projectNameInput, $projectPathInput) => {
+ const specialRepo = document.querySelector('.js-user-readme-repo');
+
// eslint-disable-next-line @gitlab/no-global-event-off
$projectNameInput.off('keyup change').on('keyup change', () => {
onProjectNameChange($projectNameInput, $projectPathInput);
@@ -54,6 +56,11 @@ const setProjectNamePathHandlers = ($projectNameInput, $projectPathInput) => {
$projectPathInput.off('keyup change').on('keyup change', () => {
onProjectPathChange($projectNameInput, $projectPathInput, hasUserDefinedProjectName);
hasUserDefinedProjectPath = $projectPathInput.val().trim().length > 0;
+
+ specialRepo.classList.toggle(
+ 'gl-display-none',
+ $projectPathInput.val() !== $projectPathInput.data('username'),
+ );
});
};
diff --git a/app/assets/javascripts/projects/settings/topics/components/topics_token_selector.vue b/app/assets/javascripts/projects/settings/topics/components/topics_token_selector.vue
new file mode 100644
index 00000000000..e8b0e95b142
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/topics/components/topics_token_selector.vue
@@ -0,0 +1,92 @@
+<script>
+import { GlTokenSelector, GlAvatarLabeled } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import searchProjectTopics from '../queries/project_topics_search.query.graphql';
+
+export default {
+ components: {
+ GlTokenSelector,
+ GlAvatarLabeled,
+ },
+ i18n: {
+ placeholder: s__('ProjectSettings|Search for topic'),
+ },
+ props: {
+ selected: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
+ apollo: {
+ topics: {
+ query: searchProjectTopics,
+ variables() {
+ return {
+ search: this.search,
+ };
+ },
+ update(data) {
+ return (
+ data.topics?.nodes.filter(
+ (topic) => !this.selectedTokens.some((token) => token.name === topic.name),
+ ) || []
+ );
+ },
+ debounce: 250,
+ },
+ },
+ data() {
+ return {
+ topics: [],
+ selectedTokens: this.selected,
+ search: '',
+ };
+ },
+ computed: {
+ loading() {
+ return this.$apollo.queries.topics.loading;
+ },
+ placeholderText() {
+ return this.selectedTokens.length ? '' : this.$options.i18n.placeholder;
+ },
+ },
+ methods: {
+ handleEnter(event) {
+ // Prevent form from submitting when adding a token
+ if (event.target.value !== '') {
+ event.preventDefault();
+ }
+ },
+ filterTopics(searchTerm) {
+ this.search = searchTerm;
+ },
+ onTokensUpdate(tokens) {
+ this.$emit('update', tokens);
+ },
+ },
+};
+</script>
+<template>
+ <gl-token-selector
+ ref="tokenSelector"
+ v-model="selectedTokens"
+ :dropdown-items="topics"
+ :loading="loading"
+ allow-user-defined-tokens
+ :placeholder="placeholderText"
+ @keydown.enter="handleEnter"
+ @text-input="filterTopics"
+ @input="onTokensUpdate"
+ >
+ <template #dropdown-item-content="{ dropdownItem }">
+ <gl-avatar-labeled
+ :src="dropdownItem.avatarUrl"
+ :entity-name="dropdownItem.name"
+ :label="dropdownItem.name"
+ :size="32"
+ shape="rect"
+ />
+ </template>
+ </gl-token-selector>
+</template>
diff --git a/app/assets/javascripts/projects/settings/topics/index.js b/app/assets/javascripts/projects/settings/topics/index.js
new file mode 100644
index 00000000000..3fbd1a61abe
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/topics/index.js
@@ -0,0 +1,51 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import TopicsTokenSelector from './components/topics_token_selector.vue';
+
+Vue.use(VueApollo);
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+});
+
+export default () => {
+ const el = document.querySelector('.js-topics-selector');
+
+ if (!el) return null;
+
+ const { hiddenInputId } = el.dataset;
+ const hiddenInput = document.getElementById(hiddenInputId);
+
+ const selected = hiddenInput.value
+ ? hiddenInput.value.split(/,\s*/).map((token, index) => ({
+ id: index,
+ name: token,
+ }))
+ : [];
+
+ return new Vue({
+ el,
+ apolloProvider,
+ render(createElement) {
+ return createElement(TopicsTokenSelector, {
+ props: {
+ selected,
+ },
+ on: {
+ update(tokens) {
+ const value = tokens.map(({ name }) => name).join(', ');
+ hiddenInput.value = value;
+ // Dispatch `input` event so form submit button becomes active
+ hiddenInput.dispatchEvent(
+ new Event('input', {
+ bubbles: true,
+ cancelable: true,
+ }),
+ );
+ },
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/projects/settings/topics/queries/project_topics_search.query.graphql b/app/assets/javascripts/projects/settings/topics/queries/project_topics_search.query.graphql
new file mode 100644
index 00000000000..b193165062a
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/topics/queries/project_topics_search.query.graphql
@@ -0,0 +1,9 @@
+query searchProjectTopics($search: String) {
+ topics(search: $search) {
+ nodes {
+ id
+ name
+ avatarUrl
+ }
+ }
+}
diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue
index 4c083ed5496..14c8c53dd19 100644
--- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue
+++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue
@@ -31,6 +31,9 @@ export default {
selectedTemplate: {
default: '',
},
+ selectedFileTemplateProjectId: {
+ default: null,
+ },
outgoingName: {
default: '',
},
@@ -80,7 +83,7 @@ export default {
});
},
- onSaveTemplate({ selectedTemplate, outgoingName, projectKey }) {
+ onSaveTemplate({ selectedTemplate, fileTemplateProjectId, outgoingName, projectKey }) {
this.isTemplateSaving = true;
const body = {
@@ -88,6 +91,7 @@ export default {
outgoing_name: outgoingName,
project_key: projectKey,
service_desk_enabled: this.isEnabled,
+ file_template_project_id: fileTemplateProjectId,
};
return axios
@@ -132,6 +136,7 @@ export default {
:custom-email="updatedCustomEmail"
:custom-email-enabled="customEmailEnabled"
:initial-selected-template="selectedTemplate"
+ :initial-selected-file-template-project-id="selectedFileTemplateProjectId"
:initial-outgoing-name="outgoingName"
:initial-project-key="projectKey"
:templates="templates"
diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
index fe2d376f1da..b8053bf9ab5 100644
--- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
+++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
@@ -1,15 +1,8 @@
<script>
-import {
- GlButton,
- GlFormSelect,
- GlToggle,
- GlLoadingIcon,
- GlSprintf,
- GlFormInput,
- GlLink,
-} from '@gitlab/ui';
+import { GlButton, GlToggle, GlLoadingIcon, GlSprintf, GlFormInput, GlLink } from '@gitlab/ui';
import { __ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import ServiceDeskTemplateDropdown from './service_desk_template_dropdown.vue';
export default {
i18n: {
@@ -18,12 +11,12 @@ export default {
components: {
ClipboardButton,
GlButton,
- GlFormSelect,
GlToggle,
GlLoadingIcon,
GlSprintf,
GlFormInput,
GlLink,
+ ServiceDeskTemplateDropdown,
},
props: {
isEnabled: {
@@ -49,6 +42,11 @@ export default {
required: false,
default: '',
},
+ initialSelectedFileTemplateProjectId: {
+ type: Number,
+ required: false,
+ default: null,
+ },
initialOutgoingName: {
type: String,
required: false,
@@ -73,14 +71,14 @@ export default {
data() {
return {
selectedTemplate: this.initialSelectedTemplate,
+ selectedFileTemplateProjectId: this.initialSelectedFileTemplateProjectId,
outgoingName: this.initialOutgoingName || __('GitLab Support Bot'),
projectKey: this.initialProjectKey,
+ searchTerm: '',
+ projectKeyError: null,
};
},
computed: {
- templateOptions() {
- return [''].concat(this.templates);
- },
hasProjectKeySupport() {
return Boolean(this.customEmailEnabled);
},
@@ -100,8 +98,21 @@ export default {
selectedTemplate: this.selectedTemplate,
outgoingName: this.outgoingName,
projectKey: this.projectKey,
+ fileTemplateProjectId: this.selectedFileTemplateProjectId,
});
},
+ templateChange({ selectedFileTemplateProjectId, selectedTemplate }) {
+ this.selectedFileTemplateProjectId = selectedFileTemplateProjectId;
+ this.selectedTemplate = selectedTemplate;
+ },
+ validateProjectKey() {
+ if (this.projectKey && !new RegExp(/^[a-z0-9_]+$/).test(this.projectKey)) {
+ this.projectKeyError = __('Only use lowercase letters, numbers, and underscores.');
+ return;
+ }
+
+ this.projectKeyError = null;
+ },
},
};
</script>
@@ -167,8 +178,17 @@ export default {
v-model.trim="projectKey"
data-testid="project-suffix"
class="form-control"
+ :state="!projectKeyError"
+ @blur="validateProjectKey"
/>
- <span v-if="hasProjectKeySupport" class="form-text text-muted">
+ <span v-if="hasProjectKeySupport && projectKeyError" class="form-text text-danger">
+ {{ projectKeyError }}
+ </span>
+ <span
+ v-if="hasProjectKeySupport"
+ class="form-text text-muted"
+ :class="{ 'gl-mt-2!': hasProjectKeySupport && projectKeyError }"
+ >
{{ __('A string appended to the project path to form the Service Desk email address.') }}
</span>
<span v-else class="form-text text-muted">
@@ -193,12 +213,13 @@ export default {
<label for="service-desk-template-select" class="mt-3">
{{ __('Template to append to all Service Desk issues') }}
</label>
- <gl-form-select
- id="service-desk-template-select"
- v-model="selectedTemplate"
- data-qa-selector="service_desk_template_dropdown"
- :options="templateOptions"
+ <service-desk-template-dropdown
+ :selected-template="selectedTemplate"
+ :selected-file-template-project-id="selectedFileTemplateProjectId"
+ :templates="templates"
+ @change="templateChange"
/>
+
<label for="service-desk-email-from-name" class="mt-3">
{{ __('Email display name') }}
</label>
@@ -210,6 +231,7 @@ export default {
<gl-button
variant="success"
class="gl-mt-5"
+ data-testid="save_service_desk_settings_button"
data-qa-selector="save_service_desk_settings_button"
:disabled="isTemplateSaving"
@click="onSaveTemplate"
diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_template_dropdown.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_template_dropdown.vue
new file mode 100644
index 00000000000..bdd9f940d79
--- /dev/null
+++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_template_dropdown.vue
@@ -0,0 +1,115 @@
+<script>
+import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import { GlDropdown, GlDropdownSectionHeader, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownSectionHeader,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ },
+ props: {
+ selectedTemplate: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ templates: {
+ type: Array,
+ required: true,
+ },
+ selectedFileTemplateProjectId: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ searchTerm: '',
+ };
+ },
+ computed: {
+ templateOptions() {
+ if (this.searchTerm) {
+ const filteredTemplates = [];
+ for (let i = 0; i < this.templates.length; i += 2) {
+ const sectionName = this.templates[i];
+ const availableTemplates = this.templates[i + 1];
+
+ const matchedTemplates = fuzzaldrinPlus.filter(availableTemplates, this.searchTerm, {
+ key: 'name',
+ });
+
+ if (matchedTemplates.length > 0) {
+ filteredTemplates.push(sectionName, matchedTemplates);
+ }
+ }
+
+ return filteredTemplates;
+ }
+
+ return this.templates;
+ },
+ },
+ methods: {
+ templateClick(template) {
+ // Clicking on the same template should unselect it
+ if (
+ template.name === this.selectedTemplate &&
+ template.project_id === this.selectedFileTemplateProjectId
+ ) {
+ this.$emit('change', {
+ selectedFileTemplateProjectId: null,
+ selectedTemplate: null,
+ });
+ return;
+ }
+
+ this.$emit('change', {
+ selectedFileTemplateProjectId: template.project_id,
+ selectedTemplate: template.key,
+ });
+ },
+ },
+ i18n: {
+ defaultDropdownText: __('Choose a template'),
+ },
+};
+</script>
+<template>
+ <gl-dropdown
+ id="service-desk-template-select"
+ :text="selectedTemplate || $options.i18n.defaultDropdownText"
+ :header-text="$options.i18n.defaultDropdownText"
+ data-qa-selector="service_desk_template_dropdown"
+ :block="true"
+ class="service-desk-template-select"
+ toggle-class="gl-m-0"
+ >
+ <template #header>
+ <gl-search-box-by-type v-model.trim="searchTerm" />
+ </template>
+ <template v-for="item in templateOptions">
+ <gl-dropdown-section-header v-if="!Array.isArray(item)" :key="item">
+ {{ item }}
+ </gl-dropdown-section-header>
+ <template v-else>
+ <gl-dropdown-item
+ v-for="template in item"
+ :key="template.key"
+ :is-check-item="true"
+ :is-checked="
+ template.project_id === selectedFileTemplateProjectId &&
+ template.name === selectedTemplate
+ "
+ @click="() => templateClick(template)"
+ >
+ {{ template.name }}
+ </gl-dropdown-item>
+ </template>
+ </template>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/projects/settings_service_desk/index.js b/app/assets/javascripts/projects/settings_service_desk/index.js
index f842ffaaa2b..e14cdee17ce 100644
--- a/app/assets/javascripts/projects/settings_service_desk/index.js
+++ b/app/assets/javascripts/projects/settings_service_desk/index.js
@@ -18,6 +18,7 @@ export default () => {
outgoingName,
projectKey,
selectedTemplate,
+ selectedFileTemplateProjectId,
templates,
} = el.dataset;
@@ -32,6 +33,7 @@ export default () => {
outgoingName,
projectKey,
selectedTemplate,
+ selectedFileTemplateProjectId: parseInt(selectedFileTemplateProjectId, 10) || null,
templates: JSON.parse(templates),
},
render: (createElement) => createElement(ServiceDeskRoot),
diff --git a/app/assets/javascripts/projects/storage_counter/components/storage_table.vue b/app/assets/javascripts/projects/storage_counter/components/storage_table.vue
index 7047fd925fb..a42a9711572 100644
--- a/app/assets/javascripts/projects/storage_counter/components/storage_table.vue
+++ b/app/assets/javascripts/projects/storage_counter/components/storage_table.vue
@@ -1,9 +1,10 @@
<script>
-import { GlLink, GlIcon, GlTable, GlSprintf } from '@gitlab/ui';
+import { GlLink, GlIcon, GlTableLite as GlTable, GlSprintf } from '@gitlab/ui';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { thWidthClass } from '~/lib/utils/table_utility';
import { sprintf } from '~/locale';
import { PROJECT_TABLE_LABELS, HELP_LINK_ARIA_LABEL } from '../constants';
+import StorageTypeIcon from './storage_type_icon.vue';
export default {
name: 'StorageTable',
@@ -12,6 +13,7 @@ export default {
GlIcon,
GlTable,
GlSprintf,
+ StorageTypeIcon,
},
props: {
storageTypes: {
@@ -48,31 +50,39 @@ export default {
<template>
<gl-table :items="storageTypes" :fields="$options.projectTableFields">
<template #cell(storageType)="{ item }">
- <p class="gl-font-weight-bold gl-mb-0" :data-testid="`${item.storageType.id}-name`">
- {{ item.storageType.name }}
- <gl-link
- v-if="item.storageType.helpPath"
- :href="item.storageType.helpPath"
- target="_blank"
- :aria-label="helpLinkAriaLabel(item.storageType.name)"
- :data-testid="`${item.storageType.id}-help-link`"
- >
- <gl-icon name="question" :size="12" />
- </gl-link>
- </p>
- <p class="gl-mb-0" :data-testid="`${item.storageType.id}-description`">
- {{ item.storageType.description }}
- </p>
- <p v-if="item.storageType.warningMessage" class="gl-mb-0 gl-font-sm">
- <gl-icon name="warning" :size="12" />
- <gl-sprintf :message="item.storageType.warningMessage">
- <template #warningLink="{ content }">
- <gl-link :href="item.storageType.warningLink" target="_blank" class="gl-font-sm">{{
- content
- }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
+ <div class="gl-display-flex gl-flex-direction-row">
+ <storage-type-icon
+ :name="item.storageType.id"
+ :data-testid="`${item.storageType.id}-icon`"
+ />
+ <div>
+ <p class="gl-font-weight-bold gl-mb-0" :data-testid="`${item.storageType.id}-name`">
+ {{ item.storageType.name }}
+ <gl-link
+ v-if="item.storageType.helpPath"
+ :href="item.storageType.helpPath"
+ target="_blank"
+ :aria-label="helpLinkAriaLabel(item.storageType.name)"
+ :data-testid="`${item.storageType.id}-help-link`"
+ >
+ <gl-icon name="question" :size="12" />
+ </gl-link>
+ </p>
+ <p class="gl-mb-0" :data-testid="`${item.storageType.id}-description`">
+ {{ item.storageType.description }}
+ </p>
+ <p v-if="item.storageType.warningMessage" class="gl-mb-0 gl-font-sm">
+ <gl-icon name="warning" :size="12" />
+ <gl-sprintf :message="item.storageType.warningMessage">
+ <template #warningLink="{ content }">
+ <gl-link :href="item.storageType.warningLink" target="_blank" class="gl-font-sm">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </div>
+ </div>
</template>
</gl-table>
</template>
diff --git a/app/assets/javascripts/projects/storage_counter/components/storage_type_icon.vue b/app/assets/javascripts/projects/storage_counter/components/storage_type_icon.vue
new file mode 100644
index 00000000000..bc7cd42df1e
--- /dev/null
+++ b/app/assets/javascripts/projects/storage_counter/components/storage_type_icon.vue
@@ -0,0 +1,35 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+
+export default {
+ components: { GlIcon },
+ props: {
+ name: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ methods: {
+ iconName(storageTypeName) {
+ const defaultStorageTypeIcon = 'disk';
+ const storageTypeIconMap = {
+ lfsObjectsSize: 'doc-image',
+ snippetsSize: 'snippet',
+ uploadsSize: 'upload',
+ repositorySize: 'infrastructure-registry',
+ packagesSize: 'package',
+ };
+
+ return storageTypeIconMap[`${storageTypeName}`] ?? defaultStorageTypeIcon;
+ },
+ },
+};
+</script>
+<template>
+ <span
+ class="gl-display-inline-flex gl-align-items-flex-start gl-justify-content-center gl-min-w-8 gl-pr-2 gl-pt-1"
+ >
+ <gl-icon :name="iconName(name)" :size="16" class="gl-mt-1" />
+ </span>
+</template>
diff --git a/app/assets/javascripts/projects/storage_counter/constants.js b/app/assets/javascripts/projects/storage_counter/constants.js
index d9b28abfbe7..df4b1800dff 100644
--- a/app/assets/javascripts/projects/storage_counter/constants.js
+++ b/app/assets/javascripts/projects/storage_counter/constants.js
@@ -6,13 +6,13 @@ export const PROJECT_STORAGE_TYPES = [
name: s__('UsageQuota|Artifacts'),
description: s__('UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD.'),
warningMessage: s__(
- 'UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}.',
+ 'UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}.',
),
warningLink: 'https://gitlab.com/groups/gitlab-org/-/epics/5380',
},
{
id: 'lfsObjectsSize',
- name: s__('UsageQuota|LFS Storage'),
+ name: s__('UsageQuota|LFS storage'),
description: s__('UsageQuota|Audio samples, videos, datasets, and graphics.'),
},
{
@@ -23,7 +23,7 @@ export const PROJECT_STORAGE_TYPES = [
{
id: 'repositorySize',
name: s__('UsageQuota|Repository'),
- description: s__('UsageQuota|Git repository, managed by the Gitaly service.'),
+ description: s__('UsageQuota|Git repository.'),
},
{
id: 'snippetsSize',
@@ -51,11 +51,11 @@ export const ERROR_MESSAGE = s__(
'UsageQuota|Something went wrong while fetching project storage statistics',
);
-export const LEARN_MORE_LABEL = s__('Learn more.');
+export const LEARN_MORE_LABEL = __('Learn more.');
export const USAGE_QUOTAS_LABEL = s__('UsageQuota|Usage Quotas');
export const HELP_LINK_ARIA_LABEL = s__('UsageQuota|%{linkTitle} help link');
export const TOTAL_USAGE_DEFAULT_TEXT = __('N/A');
-export const TOTAL_USAGE_TITLE = s__('UsageQuota|Usage Breakdown');
+export const TOTAL_USAGE_TITLE = s__('UsageQuota|Usage breakdown');
export const TOTAL_USAGE_SUBTITLE = s__(
- 'UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items.',
+ 'UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items.',
);
diff --git a/app/assets/javascripts/projects/storage_counter/index.js b/app/assets/javascripts/projects/storage_counter/index.js
index 10668f08402..15796bc1870 100644
--- a/app/assets/javascripts/projects/storage_counter/index.js
+++ b/app/assets/javascripts/projects/storage_counter/index.js
@@ -25,7 +25,7 @@ export default (containerId = 'js-project-storage-count-app') => {
} = el.dataset;
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
return new Vue({
diff --git a/app/assets/javascripts/projects/storage_counter/utils.js b/app/assets/javascripts/projects/storage_counter/utils.js
index cb26603fff5..9fca9d88f46 100644
--- a/app/assets/javascripts/projects/storage_counter/utils.js
+++ b/app/assets/javascripts/projects/storage_counter/utils.js
@@ -14,10 +14,6 @@ export const parseGetProjectStorageResults = (data, helpLinks) => {
}
const { storageSize, ...storageStatistics } = projectStatistics;
const storageTypes = PROJECT_STORAGE_TYPES.reduce((types, currentType) => {
- if (!storageStatistics[currentType.id]) {
- return types;
- }
-
const helpPathKey = currentType.id.replace(`Size`, `HelpPagePath`);
const helpPath = helpLinks[helpPathKey];
diff --git a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
index f6f409873c8..a79da00de43 100644
--- a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
+++ b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
@@ -58,7 +58,7 @@ export default {
};
this.isLoading = false;
createFlash({
- message: s__('Something went wrong on our end'),
+ message: __('Something went wrong on our end'),
});
},
initPolling() {
diff --git a/app/assets/javascripts/projects/upload_file.js b/app/assets/javascripts/projects/upload_file.js
new file mode 100644
index 00000000000..597965eabfc
--- /dev/null
+++ b/app/assets/javascripts/projects/upload_file.js
@@ -0,0 +1,33 @@
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import createRouter from '~/repository/router';
+import UploadButton from './details/upload_button.vue';
+
+export const initUploadFileTrigger = () => {
+ const uploadFileTriggerEl = document.querySelector('.js-upload-file-trigger');
+
+ if (!uploadFileTriggerEl) return false;
+
+ const {
+ targetBranch,
+ originalBranch,
+ canPushCode,
+ path,
+ projectPath,
+ } = uploadFileTriggerEl.dataset;
+
+ return new Vue({
+ el: uploadFileTriggerEl,
+ router: createRouter(projectPath, originalBranch),
+ provide: {
+ targetBranch,
+ originalBranch,
+ canPushCode: parseBoolean(canPushCode),
+ path,
+ projectPath,
+ },
+ render(h) {
+ return h(UploadButton);
+ },
+ });
+};
diff --git a/app/assets/javascripts/projects/upload_file_experiment.js b/app/assets/javascripts/projects/upload_file_experiment.js
deleted file mode 100644
index a7519f2bce8..00000000000
--- a/app/assets/javascripts/projects/upload_file_experiment.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import createRouter from '~/repository/router';
-import UploadButton from './details/upload_button.vue';
-
-export const initUploadFileTrigger = () => {
- const uploadFileTriggerEl = document.querySelector('.js-upload-file-experiment-trigger');
-
- if (!uploadFileTriggerEl) return false;
-
- const {
- targetBranch,
- originalBranch,
- canPushCode,
- path,
- projectPath,
- } = uploadFileTriggerEl.dataset;
-
- return new Vue({
- el: uploadFileTriggerEl,
- router: createRouter(projectPath, originalBranch),
- provide: {
- targetBranch,
- originalBranch,
- canPushCode: parseBoolean(canPushCode),
- path,
- projectPath,
- },
- render(h) {
- return h(UploadButton);
- },
- });
-};
diff --git a/app/assets/javascripts/projects/upload_file_experiment_tracking.js b/app/assets/javascripts/projects/upload_file_experiment_tracking.js
deleted file mode 100644
index c5e93f19b32..00000000000
--- a/app/assets/javascripts/projects/upload_file_experiment_tracking.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import ExperimentTracking from '~/experimentation/experiment_tracking';
-
-export const trackFileUploadEvent = (eventName) => {
- const isEmpty = Boolean(document.querySelector('.project-home-panel.empty-project'));
- const property = isEmpty ? 'empty' : 'nonempty';
- const label = 'blob-upload-modal';
- const FileUploadTracking = new ExperimentTracking('empty_repo_upload', { label, property });
- FileUploadTracking.event(eventName);
-};
diff --git a/app/assets/javascripts/ref/constants.js b/app/assets/javascripts/ref/constants.js
index 1cef986a83d..397e3ed2ac8 100644
--- a/app/assets/javascripts/ref/constants.js
+++ b/app/assets/javascripts/ref/constants.js
@@ -15,9 +15,9 @@ export const DEFAULT_I18N = Object.freeze({
searchPlaceholder: __('Search by Git revision'),
noResultsWithQuery: __('No matching results for "%{query}"'),
noResults: __('No matching results'),
- branchesErrorMessage: __('An error occurred while fetching branches. Retry the search.'),
+ branchesErrorMessage: __('An error occurred while fetching branches. Retry the search.'),
tagsErrorMessage: __('An error occurred while fetching tags. Retry the search.'),
- commitsErrorMessage: __('An error occurred while fetching commits. Retry the search.'),
+ commitsErrorMessage: __('An error occurred while fetching commits. Retry the search.'),
branches: __('Branches'),
tags: __('Tags'),
commits: __('Commits'),
diff --git a/app/assets/javascripts/registry/explorer/graphql/index.js b/app/assets/javascripts/registry/explorer/graphql/index.js
deleted file mode 100644
index d934bcc7419..00000000000
--- a/app/assets/javascripts/registry/explorer/graphql/index.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
-
-Vue.use(VueApollo);
-
-export const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- batchMax: 1,
- assumeImmutableResults: true,
- },
- ),
-});
diff --git a/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue b/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
index 05858c7469d..50835142d28 100644
--- a/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
+++ b/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
@@ -1,7 +1,7 @@
<script>
import { GlLink, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
-import { sprintf, n__, s__ } from '~/locale';
+import { sprintf, __, n__ } from '~/locale';
import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
import { parseIssuableData } from '../../issue_show/utils/parse_data';
@@ -40,7 +40,7 @@ export default {
this.totalCount,
);
- return sprintf(s__('%{mrText}, this issue will be closed automatically.'), { mrText });
+ return sprintf(__('%{mrText}, this issue will be closed automatically.'), { mrText });
},
},
mounted() {
@@ -64,58 +64,51 @@ export default {
</script>
<template>
- <div
- v-if="isFetchingMergeRequests || (!isFetchingMergeRequests && totalCount)"
- id="related-merge-requests"
- >
- <div id="merge-requests" class="card card-slim mt-3">
+ <div v-if="isFetchingMergeRequests || (!isFetchingMergeRequests && totalCount)">
+ <div class="card card-slim gl-mt-5">
<div class="card-header">
- <div class="card-title mt-0 mb-0 h5 merge-requests-title position-relative">
+ <div
+ class="card-title gl-relative gl-display-flex gl-align-items-center gl-line-height-20 gl-font-weight-bold gl-m-0"
+ >
<gl-link
- id="user-content-related-merge-requests"
- class="anchor position-absolute text-decoration-none"
+ class="anchor gl-absolute gl-text-decoration-none"
href="#related-merge-requests"
- aria-hidden="true"
+ aria-labelledby="related-merge-requests"
/>
- <span class="mr-1">
+ <h3 id="related-merge-requests" class="gl-font-base gl-m-0">
{{ __('Related merge requests') }}
- </span>
- <div v-if="totalCount" class="d-inline-flex lh-100 align-middle">
- <div
- class="mr-count-badge gl-display-inline-flex gl-align-items-center gl-py-2 gl-px-3"
- >
- <svg class="s16 mr-1 text-secondary">
- <gl-icon name="merge-request" class="mr-1 text-secondary" />
- </svg>
- <span class="js-items-count">{{ totalCount }}</span>
- </div>
- </div>
+ </h3>
+ <template v-if="totalCount">
+ <gl-icon name="merge-request" class="gl-ml-5 gl-mr-2 gl-text-gray-500" />
+ <span data-testid="count">{{ totalCount }}</span>
+ </template>
</div>
</div>
- <div>
- <div v-if="isFetchingMergeRequests" class="qa-related-merge-requests-loading-icon">
- <gl-loading-icon size="sm" label="Fetching related merge requests" class="py-2" />
- </div>
- <ul v-else class="content-list related-items-list">
- <li v-for="mr in mergeRequests" :key="mr.id" class="list-item pt-0 pb-0">
- <related-issuable-item
- :id-key="mr.id"
- :display-reference="mr.reference"
- :title="mr.title"
- :milestone="mr.milestone"
- :assignees="getAssignees(mr)"
- :created-at="mr.created_at"
- :closed-at="mr.closed_at"
- :merged-at="mr.merged_at"
- :path="mr.web_url"
- :state="mr.state"
- :is-merge-request="true"
- :pipeline-status="mr.head_pipeline && mr.head_pipeline.detailed_status"
- path-id-separator="!"
- />
- </li>
- </ul>
- </div>
+ <gl-loading-icon
+ v-if="isFetchingMergeRequests"
+ size="sm"
+ label="Fetching related merge requests"
+ class="gl-py-3"
+ />
+ <ul v-else class="content-list related-items-list">
+ <li v-for="mr in mergeRequests" :key="mr.id" class="list-item gl-m-0! gl-p-0!">
+ <related-issuable-item
+ :id-key="mr.id"
+ :display-reference="mr.reference"
+ :title="mr.title"
+ :milestone="mr.milestone"
+ :assignees="getAssignees(mr)"
+ :created-at="mr.created_at"
+ :closed-at="mr.closed_at"
+ :merged-at="mr.merged_at"
+ :path="mr.web_url"
+ :state="mr.state"
+ :is-merge-request="true"
+ :pipeline-status="mr.head_pipeline && mr.head_pipeline.detailed_status"
+ path-id-separator="!"
+ />
+ </li>
+ </ul>
</div>
<div
v-if="hasClosingMergeRequest && !isFetchingMergeRequests"
diff --git a/app/assets/javascripts/related_merge_requests/store/actions.js b/app/assets/javascripts/related_merge_requests/store/actions.js
index 652d03a0fd0..94abb50de89 100644
--- a/app/assets/javascripts/related_merge_requests/store/actions.js
+++ b/app/assets/javascripts/related_merge_requests/store/actions.js
@@ -1,7 +1,7 @@
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { normalizeHeaders } from '~/lib/utils/common_utils';
-import { s__ } from '~/locale';
+import { __ } from '~/locale';
import * as types from './mutation_types';
const REQUEST_PAGE_COUNT = 100;
@@ -30,7 +30,7 @@ export const fetchMergeRequests = ({ state, dispatch }) => {
.catch(() => {
dispatch('receiveDataError');
createFlash({
- message: s__('Something went wrong while fetching related merge requests.'),
+ message: __('Something went wrong while fetching related merge requests.'),
});
});
};
diff --git a/app/assets/javascripts/releases/components/tag_field_new.vue b/app/assets/javascripts/releases/components/tag_field_new.vue
index 80f59485426..9e05d00a98d 100644
--- a/app/assets/javascripts/releases/components/tag_field_new.vue
+++ b/app/assets/javascripts/releases/components/tag_field_new.vue
@@ -95,6 +95,8 @@ export default {
noRefSelected: __('No tag selected'),
dropdownHeader: __('Tag name'),
searchPlaceholder: __('Search or create tag'),
+ label: __('Tag name'),
+ labelDescription: __('*Required'),
},
createFrom: {
noRefSelected: __('No source selected'),
@@ -108,11 +110,12 @@ export default {
<template>
<div>
<gl-form-group
- :label="__('Tag name')"
- :label-for="tagNameInputId"
data-testid="tag-name-field"
:state="!showTagNameValidationError"
:invalid-feedback="__('Tag name is required')"
+ :label="$options.translations.tagName.label"
+ :label-for="tagNameInputId"
+ :label-description="$options.translations.tagName.labelDescription"
>
<form-field-container>
<ref-selector
diff --git a/app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql b/app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql
index f2d89dbe682..c69481150e0 100644
--- a/app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql
+++ b/app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql
@@ -6,7 +6,7 @@
# When the `releases_index_apollo_client` feature flag is
# removed, this query should be removed entirely.
-query allReleases(
+query allReleasesDeprecated(
$fullPath: ID!
$first: Int
$last: Int
diff --git a/app/assets/javascripts/releases/mount_index.js b/app/assets/javascripts/releases/mount_index.js
index 59f6ebfc928..86fa72d1496 100644
--- a/app/assets/javascripts/releases/mount_index.js
+++ b/app/assets/javascripts/releases/mount_index.js
@@ -24,7 +24,6 @@ export default () => {
// the purpose of making separate requests. So we explicitly
// disable batching on this page.
batchMax: 1,
- assumeImmutableResults: true,
},
),
});
diff --git a/app/assets/javascripts/releases/mount_show.js b/app/assets/javascripts/releases/mount_show.js
index 686f9e294b7..7272880197a 100644
--- a/app/assets/javascripts/releases/mount_show.js
+++ b/app/assets/javascripts/releases/mount_show.js
@@ -6,12 +6,7 @@ import ReleaseShowApp from './components/app_show.vue';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- ),
+ defaultClient: createDefaultClient(),
});
export default () => {
diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue
index 7ad9fb56972..2cc5a8a79d2 100644
--- a/app/assets/javascripts/repository/components/blob_content_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlButton } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import BlobContent from '~/blob/components/blob_content.vue';
import BlobHeader from '~/blob/components/blob_header.vue';
@@ -17,12 +17,16 @@ import ForkSuggestion from './fork_suggestion.vue';
import { loadViewer, viewerProps } from './blob_viewers';
export default {
+ i18n: {
+ pipelineEditor: __('Pipeline Editor'),
+ },
components: {
BlobHeader,
BlobEdit,
BlobButtonGroup,
BlobContent,
GlLoadingIcon,
+ GlButton,
ForkSuggestion,
},
mixins: [getRefMixin],
@@ -105,6 +109,7 @@ export default {
rawPath: '',
externalStorageUrl: '',
replacePath: '',
+ pipelineEditorPath: '',
deletePath: '',
simpleViewer: {},
richViewer: null,
@@ -242,6 +247,18 @@ export default {
:needs-to-fork="showForkSuggestion"
@edit="editBlob"
/>
+
+ <gl-button
+ v-if="blobInfo.pipelineEditorPath"
+ class="gl-mr-3"
+ category="secondary"
+ variant="confirm"
+ data-testid="pipeline-editor"
+ :href="blobInfo.pipelineEditorPath"
+ >
+ {{ $options.i18n.pipelineEditor }}
+ </gl-button>
+
<blob-button-group
v-if="isLoggedIn"
:path="path"
diff --git a/app/assets/javascripts/repository/components/delete_blob_modal.vue b/app/assets/javascripts/repository/components/delete_blob_modal.vue
index a307b7c0b8a..4a8cedb60b4 100644
--- a/app/assets/javascripts/repository/components/delete_blob_modal.vue
+++ b/app/assets/javascripts/repository/components/delete_blob_modal.vue
@@ -116,15 +116,14 @@ export default {
],
};
},
- /* eslint-disable dot-notation */
showCreateNewMrToggle() {
- return this.canPushCode && this.form.fields['branch_name'].value !== this.originalBranch;
+ return this.canPushCode && this.form.fields.branch_name.value !== this.originalBranch;
},
formCompleted() {
- return this.form.fields['commit_message'].value && this.form.fields['branch_name'].value;
+ return this.form.fields.commit_message.value && this.form.fields.branch_name.value;
},
showHint() {
- const splitCommitMessageByLineBreak = this.form.fields['commit_message'].value
+ const splitCommitMessageByLineBreak = this.form.fields.commit_message.value
.trim()
.split('\n');
const [firstLine, ...otherLines] = splitCommitMessageByLineBreak;
@@ -136,7 +135,7 @@ export default {
otherLines.some((text) => text.length > COMMIT_MESSAGE_BODY_MAX_LENGTH);
return (
- !this.form.fields['commit_message'].feedback &&
+ !this.form.fields.commit_message.feedback &&
(hasFirstLineExceedMaxLength || hasOtherLineExceedMaxLength)
);
},
@@ -173,9 +172,7 @@ export default {
<input type="hidden" name="_method" value="delete" />
<input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
<template v-if="emptyRepo">
- <!-- Once "empty_repo_upload_experiment" is made available, will need to add class 'js-branch-name'
- Follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/335721 -->
- <input type="hidden" name="branch_name" :value="originalBranch" />
+ <input type="hidden" name="branch_name" :value="originalBranch" class="js-branch-name" />
</template>
<template v-else>
<input type="hidden" name="original_branch" :value="originalBranch" />
diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue
index 5c713796bd6..62066973ee6 100644
--- a/app/assets/javascripts/repository/components/last_commit.vue
+++ b/app/assets/javascripts/repository/components/last_commit.vue
@@ -1,5 +1,12 @@
<script>
-import { GlTooltipDirective, GlLink, GlButton, GlButtonGroup, GlLoadingIcon } from '@gitlab/ui';
+import {
+ GlTooltipDirective,
+ GlLink,
+ GlButton,
+ GlButtonGroup,
+ GlLoadingIcon,
+ GlSafeHtmlDirective,
+} from '@gitlab/ui';
import defaultAvatarUrl from 'images/no_avatar.png';
import pathLastCommitQuery from 'shared_queries/repository/path_last_commit.query.graphql';
import { sprintf, s__ } from '~/locale';
@@ -23,6 +30,7 @@ export default {
},
directives: {
GlTooltip: GlTooltipDirective,
+ SafeHtml: GlSafeHtmlDirective,
},
mixins: [getRefMixin],
apollo: {
@@ -96,6 +104,9 @@ export default {
},
},
defaultAvatarUrl,
+ safeHtmlConfig: {
+ ADD_TAGS: ['gl-emoji'],
+ },
};
</script>
@@ -121,10 +132,10 @@ export default {
<div class="commit-detail flex-list">
<div class="commit-content qa-commit-content">
<gl-link
+ v-safe-html:[$options.safeHtmlConfig]="commit.titleHtml"
:href="commit.webPath"
:class="{ 'font-italic': !commit.message }"
class="commit-row-message item-title"
- v-html="commit.titleHtml /* eslint-disable-line vue/no-v-html */"
/>
<gl-button
v-if="commit.descriptionHtml"
@@ -150,15 +161,15 @@ export default {
</div>
<pre
v-if="commitDescription"
+ v-safe-html:[$options.safeHtmlConfig]="commitDescription"
:class="{ 'd-block': showDescription }"
class="commit-row-description gl-mb-3"
- v-html="commitDescription /* eslint-disable-line vue/no-v-html */"
></pre>
</div>
<div class="commit-actions flex-row">
<div
v-if="commit.signatureHtml"
- v-html="commit.signatureHtml /* eslint-disable-line vue/no-v-html */"
+ v-safe-html:[$options.safeHtmlConfig]="commit.signatureHtml"
></div>
<div v-if="commit.pipeline" class="ci-status-link">
<gl-link
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index 5010d60f374..bd06c064ab7 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -11,7 +11,6 @@ import {
GlIntersectionObserver,
} from '@gitlab/ui';
import { escapeRegExp } from 'lodash';
-import filesQuery from 'shared_queries/repository/files.query.graphql';
import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
import { escapeFileUrl } from '~/lib/utils/url_utility';
import { TREE_PAGE_SIZE } from '~/repository/constants';
@@ -178,8 +177,7 @@ export default {
return this.isFolder ? this.loadFolder() : this.loadBlob();
},
loadFolder() {
- const query = this.glFeatures.paginatedTreeGraphqlQuery ? paginatedTreeQuery : filesQuery;
- this.apolloQuery(query, {
+ this.apolloQuery(paginatedTreeQuery, {
projectPath: this.projectPath,
ref: this.ref,
path: this.path,
diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue
index 16dfe3cfb14..ffe8d5531f8 100644
--- a/app/assets/javascripts/repository/components/tree_content.vue
+++ b/app/assets/javascripts/repository/components/tree_content.vue
@@ -1,5 +1,4 @@
<script>
-import filesQuery from 'shared_queries/repository/files.query.graphql';
import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
import createFlash from '~/flash';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -72,9 +71,6 @@ export default {
hasShowMore() {
return !this.clickedShowMore && this.pageLimitReached;
},
- paginatedTreeEnabled() {
- return this.glFeatures.paginatedTreeGraphqlQuery;
- },
},
watch: {
@@ -101,7 +97,7 @@ export default {
return this.$apollo
.query({
- query: this.paginatedTreeEnabled ? paginatedTreeQuery : filesQuery,
+ query: paginatedTreeQuery,
variables: {
projectPath: this.projectPath,
ref: this.ref,
@@ -114,20 +110,19 @@ export default {
if (data.errors) throw data.errors;
if (!data?.project?.repository || originalPath !== (this.path || '/')) return;
- const pageInfo = this.paginatedTreeEnabled
- ? data.project.repository.paginatedTree.pageInfo
- : this.hasNextPage(data.project.repository.tree);
+ const {
+ project: {
+ repository: {
+ paginatedTree: { pageInfo },
+ },
+ },
+ } = data;
this.isLoadingFiles = false;
this.entries = Object.keys(this.entries).reduce(
(acc, key) => ({
...acc,
- [key]: this.normalizeData(
- key,
- this.paginatedTreeEnabled
- ? data.project.repository.paginatedTree.nodes[0][key]
- : data.project.repository.tree[key].edges,
- ),
+ [key]: this.normalizeData(key, data.project.repository.paginatedTree.nodes[0][key]),
}),
{},
);
@@ -149,9 +144,7 @@ export default {
});
},
normalizeData(key, data) {
- return this.entries[key].concat(
- this.paginatedTreeEnabled ? data.nodes : data.map(({ node }) => node),
- );
+ return this.entries[key].concat(data.nodes);
},
hasNextPage(data) {
return []
diff --git a/app/assets/javascripts/repository/components/upload_blob_modal.vue b/app/assets/javascripts/repository/components/upload_blob_modal.vue
index 0199b893453..11e5b5608cb 100644
--- a/app/assets/javascripts/repository/components/upload_blob_modal.vue
+++ b/app/assets/javascripts/repository/components/upload_blob_modal.vue
@@ -15,7 +15,6 @@ import { ContentTypeMultipartFormData } from '~/lib/utils/headers';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { visitUrl, joinPaths } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
-import { trackFileUploadEvent } from '~/projects/upload_file_experiment_tracking';
import UploadDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
import {
SECONDARY_OPTIONS_TEXT,
@@ -165,9 +164,6 @@ export default {
},
})
.then((response) => {
- if (!this.replacePath) {
- trackFileUploadEvent('click_upload_modal_form_submit');
- }
visitUrl(response.data.filePath);
})
.catch(() => {
diff --git a/app/assets/javascripts/repository/graphql.js b/app/assets/javascripts/repository/graphql.js
index 4892e54ebef..96d712ce9b4 100644
--- a/app/assets/javascripts/repository/graphql.js
+++ b/app/assets/javascripts/repository/graphql.js
@@ -64,7 +64,6 @@ const defaultClient = createDefaultClient(
/* eslint-enable @gitlab/require-i18n-strings */
},
},
- assumeImmutableResults: true,
},
);
diff --git a/app/assets/javascripts/repository/mixins/preload.js b/app/assets/javascripts/repository/mixins/preload.js
index a2ddcbf0e4c..30c36dee48f 100644
--- a/app/assets/javascripts/repository/mixins/preload.js
+++ b/app/assets/javascripts/repository/mixins/preload.js
@@ -1,4 +1,3 @@
-import filesQuery from 'shared_queries/repository/files.query.graphql';
import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
import projectPathQuery from '../queries/project_path.query.graphql';
import getRefMixin from './get_ref';
@@ -22,7 +21,7 @@ export default {
return this.$apollo
.query({
- query: gon.features.paginatedTreeGraphqlQuery ? paginatedTreeQuery : filesQuery,
+ query: paginatedTreeQuery,
variables: {
projectPath: this.projectPath,
ref: this.ref,
diff --git a/app/assets/javascripts/repository/queries/blob_info.query.graphql b/app/assets/javascripts/repository/queries/blob_info.query.graphql
index 8e0b5e21ca3..cf3892802fd 100644
--- a/app/assets/javascripts/repository/queries/blob_info.query.graphql
+++ b/app/assets/javascripts/repository/queries/blob_info.query.graphql
@@ -31,6 +31,7 @@ query getBlobInfo($projectPath: ID!, $filePath: String!, $ref: String!) {
storedExternally
rawPath
replacePath
+ pipelineEditorPath
simpleViewer {
fileType
tooLarge
diff --git a/app/assets/javascripts/rest_api.js b/app/assets/javascripts/rest_api.js
index 29642b6633f..48a15954035 100644
--- a/app/assets/javascripts/rest_api.js
+++ b/app/assets/javascripts/rest_api.js
@@ -3,6 +3,7 @@ export * from './api/projects_api';
export * from './api/user_api';
export * from './api/markdown_api';
export * from './api/bulk_imports_api';
+export * from './api/namespaces_api';
// Note: It's not possible to spy on methods imported from this file in
// Jest tests.
diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js
index 381421cdc23..3c8533dd06d 100644
--- a/app/assets/javascripts/right_sidebar.js
+++ b/app/assets/javascripts/right_sidebar.js
@@ -3,6 +3,7 @@
import $ from 'jquery';
import Cookies from 'js-cookie';
import { hide, fixTitle } from '~/tooltips';
+import { DEBOUNCE_DROPDOWN_DELAY } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
import createFlash from './flash';
import axios from './lib/utils/axios_utils';
import { sprintf, s__, __ } from './locale';
@@ -130,8 +131,10 @@ Sidebar.prototype.openDropdown = function (blockOrName) {
// Wait for the sidebar to trigger('click') open
// so it doesn't cause our dropdown to close preemptively
setTimeout(() => {
- $block.find('.js-sidebar-dropdown-toggle').trigger('click');
- });
+ if (!gon.features?.labelsWidget && !$block.hasClass('labels-select-wrapper')) {
+ $block.find('.js-sidebar-dropdown-toggle').trigger('click');
+ }
+ }, DEBOUNCE_DROPDOWN_DELAY);
};
Sidebar.prototype.setCollapseAfterUpdate = function ($block) {
diff --git a/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue b/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
index c8513a0b803..3edb658eaf5 100644
--- a/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
+++ b/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
@@ -1,18 +1,26 @@
<script>
-import { GlLink } from '@gitlab/ui';
+import { GlBadge, GlLink } from '@gitlab/ui';
import createFlash from '~/flash';
import { fetchPolicies } from '~/lib/graphql';
import { updateHistory } from '~/lib/utils/url_utility';
-import { formatNumber, sprintf, __ } from '~/locale';
+import { sprintf, __ } from '~/locale';
+
+import RegistrationDropdown from '../components/registration/registration_dropdown.vue';
import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue';
import RunnerList from '../components/runner_list.vue';
-import RunnerManualSetupHelp from '../components/runner_manual_setup_help.vue';
import RunnerName from '../components/runner_name.vue';
import RunnerPagination from '../components/runner_pagination.vue';
+import RunnerTypeTabs from '../components/runner_type_tabs.vue';
+
import { statusTokenConfig } from '../components/search_tokens/status_token_config';
import { tagTokenConfig } from '../components/search_tokens/tag_token_config';
-import { typeTokenConfig } from '../components/search_tokens/type_token_config';
-import { ADMIN_FILTERED_SEARCH_NAMESPACE, INSTANCE_TYPE, I18N_FETCH_ERROR } from '../constants';
+import {
+ ADMIN_FILTERED_SEARCH_NAMESPACE,
+ INSTANCE_TYPE,
+ GROUP_TYPE,
+ PROJECT_TYPE,
+ I18N_FETCH_ERROR,
+} from '../constants';
import getRunnersQuery from '../graphql/get_runners.query.graphql';
import {
fromUrlQueryToSearch,
@@ -24,19 +32,37 @@ import { captureException } from '../sentry_utils';
export default {
name: 'AdminRunnersApp',
components: {
+ GlBadge,
GlLink,
+ RegistrationDropdown,
RunnerFilteredSearchBar,
RunnerList,
- RunnerManualSetupHelp,
RunnerName,
RunnerPagination,
+ RunnerTypeTabs,
},
props: {
+ registrationToken: {
+ type: String,
+ required: true,
+ },
activeRunnersCount: {
- type: Number,
+ type: String,
required: true,
},
- registrationToken: {
+ allRunnersCount: {
+ type: String,
+ required: true,
+ },
+ instanceRunnersCount: {
+ type: String,
+ required: true,
+ },
+ groupRunnersCount: {
+ type: String,
+ required: true,
+ },
+ projectRunnersCount: {
type: String,
required: true,
},
@@ -86,13 +112,12 @@ export default {
},
activeRunnersMessage() {
return sprintf(__('Runners currently online: %{active_runners_count}'), {
- active_runners_count: formatNumber(this.activeRunnersCount),
+ active_runners_count: this.activeRunnersCount,
});
},
searchTokens() {
return [
statusTokenConfig,
- typeTokenConfig,
{
...tagTokenConfig,
recentTokenValuesStorageKey: `${this.$options.filteredSearchNamespace}-recent-tags`,
@@ -116,6 +141,20 @@ export default {
this.reportToSentry(error);
},
methods: {
+ tabCount({ runnerType }) {
+ switch (runnerType) {
+ case null:
+ return this.allRunnersCount;
+ case INSTANCE_TYPE:
+ return this.instanceRunnersCount;
+ case GROUP_TYPE:
+ return this.groupRunnersCount;
+ case PROJECT_TYPE:
+ return this.projectRunnersCount;
+ default:
+ return null;
+ }
+ },
reportToSentry(error) {
captureException({ error, component: this.$options.name });
},
@@ -126,10 +165,30 @@ export default {
</script>
<template>
<div>
- <runner-manual-setup-help
- :registration-token="registrationToken"
- :type="$options.INSTANCE_TYPE"
- />
+ <div
+ class="gl-display-flex gl-align-items-center gl-flex-direction-column-reverse gl-md-flex-direction-row gl-mt-3 gl-md-mt-0"
+ >
+ <runner-type-tabs
+ v-model="search"
+ class="gl-w-full"
+ content-class="gl-display-none"
+ nav-class="gl-border-none!"
+ >
+ <template #title="{ tab }">
+ {{ tab.title }}
+ <gl-badge v-if="tabCount(tab)" class="gl-ml-1" size="sm">
+ {{ tabCount(tab) }}
+ </gl-badge>
+ </template>
+ </runner-type-tabs>
+
+ <registration-dropdown
+ class="gl-w-full gl-sm-w-auto gl-mr-auto"
+ :registration-token="registrationToken"
+ :type="$options.INSTANCE_TYPE"
+ right
+ />
+ </div>
<runner-filtered-search-bar
v-model="search"
diff --git a/app/assets/javascripts/runner/admin_runners/index.js b/app/assets/javascripts/runner/admin_runners/index.js
index 1eec1019b73..62da6cbfa2b 100644
--- a/app/assets/javascripts/runner/admin_runners/index.js
+++ b/app/assets/javascripts/runner/admin_runners/index.js
@@ -1,8 +1,10 @@
+import { GlToast } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import AdminRunnersApp from './admin_runners_app.vue';
+Vue.use(GlToast);
Vue.use(VueApollo);
export const initAdminRunners = (selector = '#js-admin-runners') => {
@@ -14,15 +16,19 @@ export const initAdminRunners = (selector = '#js-admin-runners') => {
// TODO `activeRunnersCount` should be implemented using a GraphQL API
// https://gitlab.com/gitlab-org/gitlab/-/issues/333806
- const { activeRunnersCount, registrationToken, runnerInstallHelpPage } = el.dataset;
+ const {
+ runnerInstallHelpPage,
+ registrationToken,
+
+ activeRunnersCount,
+ allRunnersCount,
+ instanceRunnersCount,
+ groupRunnersCount,
+ projectRunnersCount,
+ } = el.dataset;
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- ),
+ defaultClient: createDefaultClient(),
});
return new Vue({
@@ -34,8 +40,15 @@ export const initAdminRunners = (selector = '#js-admin-runners') => {
render(h) {
return h(AdminRunnersApp, {
props: {
- activeRunnersCount: parseInt(activeRunnersCount, 10),
registrationToken,
+
+ // All runner counts are returned as formatted
+ // strings, we do not use `parseInt`.
+ activeRunnersCount,
+ allRunnersCount,
+ instanceRunnersCount,
+ groupRunnersCount,
+ projectRunnersCount,
},
});
},
diff --git a/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue b/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
index e26bdbf1aea..c4bddb7b398 100644
--- a/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
+++ b/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
@@ -3,7 +3,7 @@ import { GlButton, GlButtonGroup, GlTooltipDirective } from '@gitlab/ui';
import createFlash from '~/flash';
import { __, s__ } from '~/locale';
import runnerDeleteMutation from '~/runner/graphql/runner_delete.mutation.graphql';
-import runnerUpdateMutation from '~/runner/graphql/runner_update.mutation.graphql';
+import runnerActionsUpdateMutation from '~/runner/graphql/runner_actions_update.mutation.graphql';
import { captureException } from '~/runner/sentry_utils';
const i18n = {
@@ -71,7 +71,7 @@ export default {
runnerUpdate: { errors },
},
} = await this.$apollo.mutate({
- mutation: runnerUpdateMutation,
+ mutation: runnerActionsUpdateMutation,
variables: {
input: {
id: this.runner.id,
diff --git a/app/assets/javascripts/runner/components/cells/runner_status_cell.vue b/app/assets/javascripts/runner/components/cells/runner_status_cell.vue
new file mode 100644
index 00000000000..9ba1192bc8c
--- /dev/null
+++ b/app/assets/javascripts/runner/components/cells/runner_status_cell.vue
@@ -0,0 +1,40 @@
+<script>
+import { GlTooltipDirective } from '@gitlab/ui';
+
+import RunnerContactedStateBadge from '../runner_contacted_state_badge.vue';
+import RunnerPausedBadge from '../runner_paused_badge.vue';
+
+import { I18N_LOCKED_RUNNER_DESCRIPTION, I18N_PAUSED_RUNNER_DESCRIPTION } from '../../constants';
+
+export default {
+ components: {
+ RunnerContactedStateBadge,
+ RunnerPausedBadge,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ runner: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ paused() {
+ return !this.runner.active;
+ },
+ },
+ i18n: {
+ I18N_LOCKED_RUNNER_DESCRIPTION,
+ I18N_PAUSED_RUNNER_DESCRIPTION,
+ },
+};
+</script>
+
+<template>
+ <div>
+ <runner-contacted-state-badge :runner="runner" size="sm" />
+ <runner-paused-badge v-if="paused" size="sm" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/components/cells/runner_summary_cell.vue b/app/assets/javascripts/runner/components/cells/runner_summary_cell.vue
index 886b5cb29fc..3b476997915 100644
--- a/app/assets/javascripts/runner/components/cells/runner_summary_cell.vue
+++ b/app/assets/javascripts/runner/components/cells/runner_summary_cell.vue
@@ -1,11 +1,21 @@
<script>
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import RunnerName from '../runner_name.vue';
+import RunnerTypeBadge from '../runner_type_badge.vue';
+
+import { I18N_LOCKED_RUNNER_DESCRIPTION } from '../../constants';
export default {
components: {
+ GlIcon,
TooltipOnTruncate,
RunnerName,
+ RunnerTypeBadge,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
},
props: {
runner: {
@@ -14,10 +24,19 @@ export default {
},
},
computed: {
+ runnerType() {
+ return this.runner.runnerType;
+ },
+ locked() {
+ return this.runner.locked;
+ },
description() {
return this.runner.description;
},
},
+ i18n: {
+ I18N_LOCKED_RUNNER_DESCRIPTION,
+ },
};
</script>
@@ -26,6 +45,14 @@ export default {
<slot :runner="runner" name="runner-name">
<runner-name :runner="runner" />
</slot>
+
+ <runner-type-badge :type="runnerType" size="sm" />
+ <gl-icon
+ v-if="locked"
+ v-gl-tooltip
+ :title="$options.i18n.I18N_LOCKED_RUNNER_DESCRIPTION"
+ name="lock"
+ />
<tooltip-on-truncate class="gl-display-block" :title="description" truncate-target="child">
<div class="gl-text-truncate">
{{ description }}
diff --git a/app/assets/javascripts/runner/components/cells/runner_type_cell.vue b/app/assets/javascripts/runner/components/cells/runner_type_cell.vue
deleted file mode 100644
index c8cb0bf6088..00000000000
--- a/app/assets/javascripts/runner/components/cells/runner_type_cell.vue
+++ /dev/null
@@ -1,47 +0,0 @@
-<script>
-import { GlTooltipDirective } from '@gitlab/ui';
-import RunnerTypeBadge from '../runner_type_badge.vue';
-import RunnerStateLockedBadge from '../runner_state_locked_badge.vue';
-import RunnerStatePausedBadge from '../runner_state_paused_badge.vue';
-import { I18N_LOCKED_RUNNER_DESCRIPTION, I18N_PAUSED_RUNNER_DESCRIPTION } from '../../constants';
-
-export default {
- components: {
- RunnerTypeBadge,
- RunnerStateLockedBadge,
- RunnerStatePausedBadge,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- runner: {
- type: Object,
- required: true,
- },
- },
- computed: {
- runnerType() {
- return this.runner.runnerType;
- },
- locked() {
- return this.runner.locked;
- },
- paused() {
- return !this.runner.active;
- },
- },
- i18n: {
- I18N_LOCKED_RUNNER_DESCRIPTION,
- I18N_PAUSED_RUNNER_DESCRIPTION,
- },
-};
-</script>
-
-<template>
- <div>
- <runner-type-badge :type="runnerType" size="sm" />
- <runner-state-locked-badge v-if="locked" size="sm" />
- <runner-state-paused-badge v-if="paused" size="sm" />
- </div>
-</template>
diff --git a/app/assets/javascripts/runner/components/helpers/masked_value.vue b/app/assets/javascripts/runner/components/helpers/masked_value.vue
deleted file mode 100644
index feccb37de81..00000000000
--- a/app/assets/javascripts/runner/components/helpers/masked_value.vue
+++ /dev/null
@@ -1,60 +0,0 @@
-<script>
-import { GlButton } from '@gitlab/ui';
-import { __ } from '~/locale';
-
-export default {
- components: {
- GlButton,
- },
- props: {
- value: {
- type: String,
- required: false,
- default: '',
- },
- },
- data() {
- return {
- isMasked: true,
- };
- },
- computed: {
- label() {
- if (this.isMasked) {
- return __('Click to reveal');
- }
- return __('Click to hide');
- },
- icon() {
- if (this.isMasked) {
- return 'eye';
- }
- return 'eye-slash';
- },
- displayedValue() {
- if (this.isMasked && this.value?.length) {
- return '*'.repeat(this.value.length);
- }
- return this.value;
- },
- },
- methods: {
- toggleMasked() {
- this.isMasked = !this.isMasked;
- },
- },
-};
-</script>
-<template>
- <span
- >{{ displayedValue }}
- <gl-button
- :aria-label="label"
- :icon="icon"
- class="gl-text-body!"
- data-testid="toggle-masked"
- variant="link"
- @click="toggleMasked"
- />
- </span>
-</template>
diff --git a/app/assets/javascripts/runner/components/registration/registration_dropdown.vue b/app/assets/javascripts/runner/components/registration/registration_dropdown.vue
new file mode 100644
index 00000000000..3fbe3c1be74
--- /dev/null
+++ b/app/assets/javascripts/runner/components/registration/registration_dropdown.vue
@@ -0,0 +1,112 @@
+<script>
+import {
+ GlFormGroup,
+ GlDropdown,
+ GlDropdownForm,
+ GlDropdownItem,
+ GlDropdownDivider,
+} from '@gitlab/ui';
+import { s__ } from '~/locale';
+import RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue';
+import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../../constants';
+import RegistrationToken from './registration_token.vue';
+import RegistrationTokenResetDropdownItem from './registration_token_reset_dropdown_item.vue';
+
+export default {
+ i18n: {
+ showInstallationInstructions: s__(
+ 'Runners|Show runner installation and registration instructions',
+ ),
+ registrationToken: s__('Runners|Registration token'),
+ },
+ components: {
+ GlFormGroup,
+ GlDropdown,
+ GlDropdownForm,
+ GlDropdownItem,
+ GlDropdownDivider,
+ RegistrationToken,
+ RunnerInstructionsModal,
+ RegistrationTokenResetDropdownItem,
+ },
+ props: {
+ registrationToken: {
+ type: String,
+ required: true,
+ },
+ type: {
+ type: String,
+ required: true,
+ validator(type) {
+ return [INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE].includes(type);
+ },
+ },
+ },
+ data() {
+ return {
+ currentRegistrationToken: this.registrationToken,
+ instructionsModalOpened: false,
+ };
+ },
+ computed: {
+ dropdownText() {
+ switch (this.type) {
+ case INSTANCE_TYPE:
+ return s__('Runners|Register an instance runner');
+ case GROUP_TYPE:
+ return s__('Runners|Register a group runner');
+ case PROJECT_TYPE:
+ return s__('Runners|Register a project runner');
+ default:
+ return s__('Runners|Register a runner');
+ }
+ },
+ },
+ methods: {
+ onShowInstructionsClick() {
+ // Rendering the modal on demand, to avoid
+ // loading instructions prematurely from API.
+ this.instructionsModalOpened = true;
+
+ this.$nextTick(() => {
+ // $refs.runnerInstructionsModal is defined in
+ // the tick after the modal is rendered
+ this.$refs.runnerInstructionsModal.show();
+ });
+ },
+ onTokenReset(token) {
+ this.currentRegistrationToken = token;
+
+ this.$refs.runnerRegistrationDropdown.hide(true);
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown
+ ref="runnerRegistrationDropdown"
+ menu-class="gl-w-auto!"
+ :text="dropdownText"
+ variant="confirm"
+ v-bind="$attrs"
+ >
+ <gl-dropdown-item @click.capture.native.stop="onShowInstructionsClick">
+ {{ $options.i18n.showInstallationInstructions }}
+ <runner-instructions-modal
+ v-if="instructionsModalOpened"
+ ref="runnerInstructionsModal"
+ :registration-token="registrationToken"
+ data-testid="runner-instructions-modal"
+ />
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ <gl-dropdown-form class="gl-p-4!">
+ <gl-form-group class="gl-mb-0" :label="$options.i18n.registrationToken">
+ <registration-token :value="currentRegistrationToken" />
+ </gl-form-group>
+ </gl-dropdown-form>
+ <gl-dropdown-divider />
+ <registration-token-reset-dropdown-item :type="type" @tokenReset="onTokenReset" />
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/runner/components/registration/registration_token.vue b/app/assets/javascripts/runner/components/registration/registration_token.vue
new file mode 100644
index 00000000000..d54a66ff0e4
--- /dev/null
+++ b/app/assets/javascripts/runner/components/registration/registration_token.vue
@@ -0,0 +1,83 @@
+<script>
+import { GlButtonGroup, GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { s__, __ } from '~/locale';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
+
+export default {
+ components: {
+ GlButtonGroup,
+ GlButton,
+ ModalCopyButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ value: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ isMasked: true,
+ };
+ },
+ computed: {
+ maskLabel() {
+ if (this.isMasked) {
+ return __('Click to reveal');
+ }
+ return __('Click to hide');
+ },
+ maskIcon() {
+ if (this.isMasked) {
+ return 'eye';
+ }
+ return 'eye-slash';
+ },
+ displayedValue() {
+ if (this.isMasked && this.value?.length) {
+ return '*'.repeat(this.value.length);
+ }
+ return this.value;
+ },
+ },
+ methods: {
+ onToggleMasked() {
+ this.isMasked = !this.isMasked;
+ },
+ onCopied() {
+ // value already in the clipboard, simply notify the user
+ this.$toast?.show(s__('Runners|Registration token copied!'));
+ },
+ },
+ i18n: {
+ copyLabel: s__('Runners|Copy registration token'),
+ },
+};
+</script>
+<template>
+ <gl-button-group>
+ <gl-button class="gl-font-monospace" data-testid="token-value" label>
+ {{ displayedValue }}
+ </gl-button>
+ <gl-button
+ v-gl-tooltip
+ :aria-label="maskLabel"
+ :title="maskLabel"
+ :icon="maskIcon"
+ class="gl-w-auto! gl-flex-shrink-0!"
+ data-testid="toggle-masked"
+ @click.stop="onToggleMasked"
+ />
+ <modal-copy-button
+ class="gl-w-auto! gl-flex-shrink-0!"
+ :aria-label="$options.i18n.copyLabel"
+ :title="$options.i18n.copyLabel"
+ :text="value"
+ @success="onCopied"
+ />
+ </gl-button-group>
+</template>
diff --git a/app/assets/javascripts/runner/components/registration/registration_token_reset_dropdown_item.vue b/app/assets/javascripts/runner/components/registration/registration_token_reset_dropdown_item.vue
new file mode 100644
index 00000000000..3bb15bff8d8
--- /dev/null
+++ b/app/assets/javascripts/runner/components/registration/registration_token_reset_dropdown_item.vue
@@ -0,0 +1,113 @@
+<script>
+import { GlDropdownItem, GlLoadingIcon } from '@gitlab/ui';
+import createFlash from '~/flash';
+import { TYPE_GROUP, TYPE_PROJECT } from '~/graphql_shared/constants';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import { __, s__ } from '~/locale';
+import runnersRegistrationTokenResetMutation from '~/runner/graphql/runners_registration_token_reset.mutation.graphql';
+import { captureException } from '~/runner/sentry_utils';
+import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../../constants';
+
+export default {
+ name: 'RunnerRegistrationTokenReset',
+ components: {
+ GlDropdownItem,
+ GlLoadingIcon,
+ },
+ inject: {
+ groupId: {
+ default: null,
+ },
+ projectId: {
+ default: null,
+ },
+ },
+ props: {
+ type: {
+ type: String,
+ required: true,
+ validator(type) {
+ return [INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE].includes(type);
+ },
+ },
+ },
+ data() {
+ return {
+ loading: false,
+ };
+ },
+ computed: {
+ resetTokenInput() {
+ switch (this.type) {
+ case INSTANCE_TYPE:
+ return {
+ type: this.type,
+ };
+ case GROUP_TYPE:
+ return {
+ id: convertToGraphQLId(TYPE_GROUP, this.groupId),
+ type: this.type,
+ };
+ case PROJECT_TYPE:
+ return {
+ id: convertToGraphQLId(TYPE_PROJECT, this.projectId),
+ type: this.type,
+ };
+ default:
+ return null;
+ }
+ },
+ },
+ methods: {
+ async resetToken() {
+ // TODO Replace confirmation with gl-modal
+ // See: https://gitlab.com/gitlab-org/gitlab/-/issues/333810
+ // eslint-disable-next-line no-alert
+ if (!window.confirm(__('Are you sure you want to reset the registration token?'))) {
+ return;
+ }
+
+ this.loading = true;
+ try {
+ const {
+ data: {
+ runnersRegistrationTokenReset: { token, errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation: runnersRegistrationTokenResetMutation,
+ variables: {
+ input: this.resetTokenInput,
+ },
+ });
+ if (errors && errors.length) {
+ throw new Error(errors.join(' '));
+ }
+ this.onSuccess(token);
+ } catch (e) {
+ this.onError(e);
+ } finally {
+ this.loading = false;
+ }
+ },
+ onError(error) {
+ const { message } = error;
+ createFlash({ message });
+
+ this.reportToSentry(error);
+ },
+ onSuccess(token) {
+ this.$toast?.show(s__('Runners|New registration token generated!'));
+ this.$emit('tokenReset', token);
+ },
+ reportToSentry(error) {
+ captureException({ error, component: this.$options.name });
+ },
+ },
+};
+</script>
+<template>
+ <gl-dropdown-item @click.capture.native.stop="resetToken">
+ {{ __('Reset registration token') }}
+ <gl-loading-icon v-if="loading" inline />
+ </gl-dropdown-item>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_contacted_state_badge.vue b/app/assets/javascripts/runner/components/runner_contacted_state_badge.vue
new file mode 100644
index 00000000000..b4727f832f8
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_contacted_state_badge.vue
@@ -0,0 +1,69 @@
+<script>
+import { GlBadge, GlTooltipDirective } from '@gitlab/ui';
+import { s__, sprintf } from '~/locale';
+import { getTimeago } from '~/lib/utils/datetime_utility';
+import {
+ I18N_ONLINE_RUNNER_DESCRIPTION,
+ I18N_OFFLINE_RUNNER_DESCRIPTION,
+ I18N_NOT_CONNECTED_RUNNER_DESCRIPTION,
+ STATUS_ONLINE,
+ STATUS_OFFLINE,
+ STATUS_NOT_CONNECTED,
+} from '../constants';
+
+export default {
+ components: {
+ GlBadge,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ runner: {
+ required: true,
+ type: Object,
+ },
+ },
+ computed: {
+ contactedAtTimeAgo() {
+ if (this.runner.contactedAt) {
+ return getTimeago().format(this.runner.contactedAt);
+ }
+ return null;
+ },
+ badge() {
+ switch (this.runner.status) {
+ case STATUS_ONLINE:
+ return {
+ variant: 'success',
+ label: s__('Runners|online'),
+ tooltip: sprintf(I18N_ONLINE_RUNNER_DESCRIPTION, {
+ timeAgo: this.contactedAtTimeAgo,
+ }),
+ };
+ case STATUS_OFFLINE:
+ return {
+ variant: 'muted',
+ label: s__('Runners|offline'),
+ tooltip: sprintf(I18N_OFFLINE_RUNNER_DESCRIPTION, {
+ timeAgo: this.contactedAtTimeAgo,
+ }),
+ };
+ case STATUS_NOT_CONNECTED:
+ return {
+ variant: 'muted',
+ label: s__('Runners|not connected'),
+ tooltip: I18N_NOT_CONNECTED_RUNNER_DESCRIPTION,
+ };
+ default:
+ return null;
+ }
+ },
+ },
+};
+</script>
+<template>
+ <gl-badge v-if="badge" v-gl-tooltip="badge.tooltip" :variant="badge.variant" v-bind="$attrs">
+ {{ badge.label }}
+ </gl-badge>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue b/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
index e04ca8ddca0..a9dfec35479 100644
--- a/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
+++ b/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
@@ -2,6 +2,7 @@
import { cloneDeep } from 'lodash';
import { __ } from '~/locale';
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+import { searchValidator } from '~/runner/runner_search_utils';
import { CREATED_DESC, CREATED_ASC, CONTACTED_DESC, CONTACTED_ASC } from '../constants';
const sortOptions = [
@@ -31,9 +32,12 @@ export default {
value: {
type: Object,
required: true,
- validator(val) {
- return Array.isArray(val?.filters) && typeof val?.sort === 'string';
- },
+ validator: searchValidator,
+ },
+ tokens: {
+ type: Array,
+ required: false,
+ default: () => [],
},
namespace: {
type: String,
@@ -43,7 +47,7 @@ export default {
data() {
// filtered_search_bar_root.vue may mutate the inital
// filters. Use `cloneDeep` to prevent those mutations
- // from affecting this component
+ // from affecting this component
const { filters, sort } = cloneDeep(this.value);
return {
initialFilterValue: filters,
@@ -52,19 +56,17 @@ export default {
},
methods: {
onFilter(filters) {
- const { sort } = this.value;
-
+ // Apply new filters, from page 1
this.$emit('input', {
+ ...this.value,
filters,
- sort,
pagination: { page: 1 },
});
},
onSort(sort) {
- const { filters } = this.value;
-
+ // Apply new sort, from page 1
this.$emit('input', {
- filters,
+ ...this.value,
sort,
pagination: { page: 1 },
});
@@ -74,13 +76,16 @@ export default {
};
</script>
<template>
- <div>
+ <div
+ class="gl-bg-gray-10 gl-p-5 gl-border-solid gl-border-gray-100 gl-border-0 gl-border-t-1 gl-border-b-1"
+ >
<filtered-search
v-bind="$attrs"
:namespace="namespace"
recent-searches-storage-key="runners-search"
:sort-options="$options.sortOptions"
:initial-filter-value="initialFilterValue"
+ :tokens="tokens"
:initial-sort-by="initialSortBy"
:search-input-placeholder="__('Search or filter results...')"
data-testid="runners-filtered-search"
diff --git a/app/assets/javascripts/runner/components/runner_list.vue b/app/assets/javascripts/runner/components/runner_list.vue
index 3f6ea389288..f8dbc469c22 100644
--- a/app/assets/javascripts/runner/components/runner_list.vue
+++ b/app/assets/javascripts/runner/components/runner_list.vue
@@ -1,12 +1,11 @@
<script>
import { GlTable, GlTooltipDirective, GlSkeletonLoader } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { formatNumber, __, s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
-import { RUNNER_JOB_COUNT_LIMIT } from '../constants';
import RunnerActionsCell from './cells/runner_actions_cell.vue';
import RunnerSummaryCell from './cells/runner_summary_cell.vue';
-import RunnerTypeCell from './cells/runner_type_cell.vue';
+import RunnerStatusCell from './cells/runner_status_cell.vue';
import RunnerTags from './runner_tags.vue';
const tableField = ({ key, label = '', width = 10 }) => {
@@ -37,7 +36,7 @@ export default {
RunnerActionsCell,
RunnerSummaryCell,
RunnerTags,
- RunnerTypeCell,
+ RunnerStatusCell,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -54,18 +53,6 @@ export default {
},
},
methods: {
- formatProjectCount(projectCount) {
- if (projectCount === null) {
- return __('n/a');
- }
- return formatNumber(projectCount);
- },
- formatJobCount(jobCount) {
- if (jobCount > RUNNER_JOB_COUNT_LIMIT) {
- return `${formatNumber(RUNNER_JOB_COUNT_LIMIT)}+`;
- }
- return formatNumber(jobCount);
- },
runnerTrAttr(runner) {
if (runner) {
return {
@@ -76,13 +63,11 @@ export default {
},
},
fields: [
- tableField({ key: 'type', label: __('Type/State') }),
- tableField({ key: 'summary', label: s__('Runners|Runner'), width: 30 }),
+ tableField({ key: 'status', label: s__('Runners|Status') }),
+ tableField({ key: 'summary', label: s__('Runners|Runner ID'), width: 30 }),
tableField({ key: 'version', label: __('Version') }),
tableField({ key: 'ipAddress', label: __('IP Address') }),
- tableField({ key: 'projectCount', label: __('Projects'), width: 5 }),
- tableField({ key: 'jobCount', label: __('Jobs'), width: 5 }),
- tableField({ key: 'tagList', label: __('Tags') }),
+ tableField({ key: 'tagList', label: __('Tags'), width: 20 }),
tableField({ key: 'contactedAt', label: __('Last contact') }),
tableField({ key: 'actions', label: '' }),
],
@@ -103,8 +88,8 @@ export default {
<gl-skeleton-loader v-for="i in 4" :key="i" />
</template>
- <template #cell(type)="{ item }">
- <runner-type-cell :runner="item" />
+ <template #cell(status)="{ item }">
+ <runner-status-cell :runner="item" />
</template>
<template #cell(summary)="{ item, index }">
@@ -123,14 +108,6 @@ export default {
{{ ipAddress }}
</template>
- <template #cell(projectCount)="{ item: { projectCount } }">
- {{ formatProjectCount(projectCount) }}
- </template>
-
- <template #cell(jobCount)="{ item: { jobCount } }">
- {{ formatJobCount(jobCount) }}
- </template>
-
<template #cell(tagList)="{ item: { tagList } }">
<runner-tags :tag-list="tagList" size="sm" />
</template>
diff --git a/app/assets/javascripts/runner/components/runner_manual_setup_help.vue b/app/assets/javascripts/runner/components/runner_manual_setup_help.vue
deleted file mode 100644
index 475d362bb52..00000000000
--- a/app/assets/javascripts/runner/components/runner_manual_setup_help.vue
+++ /dev/null
@@ -1,108 +0,0 @@
-<script>
-import { GlLink, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
-import { s__ } from '~/locale';
-import MaskedValue from '~/runner/components/helpers/masked_value.vue';
-import RunnerRegistrationTokenReset from '~/runner/components/runner_registration_token_reset.vue';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import RunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue';
-import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../constants';
-
-export default {
- components: {
- GlLink,
- GlSprintf,
- ClipboardButton,
- MaskedValue,
- RunnerInstructions,
- RunnerRegistrationTokenReset,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- inject: {
- runnerInstallHelpPage: {
- default: null,
- },
- },
- props: {
- registrationToken: {
- type: String,
- required: true,
- },
- type: {
- type: String,
- required: true,
- validator(type) {
- return [INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE].includes(type);
- },
- },
- },
- data() {
- return {
- currentRegistrationToken: this.registrationToken,
- };
- },
- computed: {
- rootUrl() {
- return gon.gitlab_url || '';
- },
- typeName() {
- switch (this.type) {
- case INSTANCE_TYPE:
- return s__('Runners|shared');
- case GROUP_TYPE:
- return s__('Runners|group');
- case PROJECT_TYPE:
- return s__('Runners|specific');
- default:
- return '';
- }
- },
- },
- methods: {
- onTokenReset(token) {
- this.currentRegistrationToken = token;
- },
- },
-};
-</script>
-
-<template>
- <div class="bs-callout">
- <h5 data-testid="runner-help-title">
- <gl-sprintf :message="__('Set up a %{type} runner manually')">
- <template #type>
- {{ typeName }}
- </template>
- </gl-sprintf>
- </h5>
-
- <ol>
- <li>
- <gl-link :href="runnerInstallHelpPage" data-testid="runner-help-link" target="_blank">
- {{ __("Install GitLab Runner and ensure it's running.") }}
- </gl-link>
- </li>
- <li>
- {{ __('Register the runner with this URL:') }}
- <br />
-
- <code data-testid="coordinator-url">{{ rootUrl }}</code>
- <clipboard-button :title="__('Copy URL')" :text="rootUrl" />
- </li>
- <li>
- {{ __('And this registration token:') }}
- <br />
-
- <code data-testid="registration-token"
- ><masked-value :value="currentRegistrationToken"
- /></code>
- <clipboard-button :title="__('Copy token')" :text="currentRegistrationToken" />
- </li>
- </ol>
-
- <runner-registration-token-reset :type="type" @tokenReset="onTokenReset" />
-
- <runner-instructions />
- </div>
-</template>
diff --git a/app/assets/javascripts/runner/components/runner_state_paused_badge.vue b/app/assets/javascripts/runner/components/runner_paused_badge.vue
index d1e6fa05e4d..d1e6fa05e4d 100644
--- a/app/assets/javascripts/runner/components/runner_state_paused_badge.vue
+++ b/app/assets/javascripts/runner/components/runner_paused_badge.vue
diff --git a/app/assets/javascripts/runner/components/runner_registration_token_reset.vue b/app/assets/javascripts/runner/components/runner_registration_token_reset.vue
deleted file mode 100644
index cdf14abd4f9..00000000000
--- a/app/assets/javascripts/runner/components/runner_registration_token_reset.vue
+++ /dev/null
@@ -1,114 +0,0 @@
-<script>
-import { GlButton } from '@gitlab/ui';
-import createFlash, { FLASH_TYPES } from '~/flash';
-import { TYPE_GROUP, TYPE_PROJECT } from '~/graphql_shared/constants';
-import { convertToGraphQLId } from '~/graphql_shared/utils';
-import { __, s__ } from '~/locale';
-import runnersRegistrationTokenResetMutation from '~/runner/graphql/runners_registration_token_reset.mutation.graphql';
-import { captureException } from '~/runner/sentry_utils';
-import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../constants';
-
-export default {
- name: 'RunnerRegistrationTokenReset',
- components: {
- GlButton,
- },
- inject: {
- groupId: {
- default: null,
- },
- projectId: {
- default: null,
- },
- },
- props: {
- type: {
- type: String,
- required: true,
- validator(type) {
- return [INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE].includes(type);
- },
- },
- },
- data() {
- return {
- loading: false,
- };
- },
- computed: {
- resetTokenInput() {
- switch (this.type) {
- case INSTANCE_TYPE:
- return {
- type: this.type,
- };
- case GROUP_TYPE:
- return {
- id: convertToGraphQLId(TYPE_GROUP, this.groupId),
- type: this.type,
- };
- case PROJECT_TYPE:
- return {
- id: convertToGraphQLId(TYPE_PROJECT, this.projectId),
- type: this.type,
- };
- default:
- return null;
- }
- },
- },
- methods: {
- async resetToken() {
- // TODO Replace confirmation with gl-modal
- // See: https://gitlab.com/gitlab-org/gitlab/-/issues/333810
- // eslint-disable-next-line no-alert
- if (!window.confirm(__('Are you sure you want to reset the registration token?'))) {
- return;
- }
-
- this.loading = true;
- try {
- const {
- data: {
- runnersRegistrationTokenReset: { token, errors },
- },
- } = await this.$apollo.mutate({
- mutation: runnersRegistrationTokenResetMutation,
- variables: {
- input: this.resetTokenInput,
- },
- });
- if (errors && errors.length) {
- throw new Error(errors.join(' '));
- }
- this.onSuccess(token);
- } catch (e) {
- this.onError(e);
- } finally {
- this.loading = false;
- }
- },
- onError(error) {
- const { message } = error;
- createFlash({ message });
-
- this.reportToSentry(error);
- },
- onSuccess(token) {
- createFlash({
- message: s__('Runners|New registration token generated!'),
- type: FLASH_TYPES.SUCCESS,
- });
- this.$emit('tokenReset', token);
- },
- reportToSentry(error) {
- captureException({ error, component: this.$options.name });
- },
- },
-};
-</script>
-<template>
- <gl-button :loading="loading" @click="resetToken">
- {{ __('Reset registration token') }}
- </gl-button>
-</template>
diff --git a/app/assets/javascripts/runner/components/runner_state_locked_badge.vue b/app/assets/javascripts/runner/components/runner_state_locked_badge.vue
deleted file mode 100644
index 458526010bc..00000000000
--- a/app/assets/javascripts/runner/components/runner_state_locked_badge.vue
+++ /dev/null
@@ -1,25 +0,0 @@
-<script>
-import { GlBadge, GlTooltipDirective } from '@gitlab/ui';
-import { I18N_LOCKED_RUNNER_DESCRIPTION } from '../constants';
-
-export default {
- components: {
- GlBadge,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- i18n: {
- I18N_LOCKED_RUNNER_DESCRIPTION,
- },
-};
-</script>
-<template>
- <gl-badge
- v-gl-tooltip="$options.i18n.I18N_LOCKED_RUNNER_DESCRIPTION"
- variant="warning"
- v-bind="$attrs"
- >
- {{ s__('Runners|locked') }}
- </gl-badge>
-</template>
diff --git a/app/assets/javascripts/runner/components/runner_tag.vue b/app/assets/javascripts/runner/components/runner_tag.vue
index 06562e618a8..6ad2023a866 100644
--- a/app/assets/javascripts/runner/components/runner_tag.vue
+++ b/app/assets/javascripts/runner/components/runner_tag.vue
@@ -1,11 +1,15 @@
<script>
-import { GlBadge } from '@gitlab/ui';
+import { GlBadge, GlTooltipDirective, GlResizeObserverDirective } from '@gitlab/ui';
import { RUNNER_TAG_BADGE_VARIANT } from '../constants';
export default {
components: {
GlBadge,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ GlResizeObserver: GlResizeObserverDirective,
+ },
props: {
tag: {
type: String,
@@ -14,14 +18,39 @@ export default {
size: {
type: String,
required: false,
- default: 'md',
+ default: 'sm',
+ },
+ },
+ data() {
+ return {
+ overflowing: false,
+ };
+ },
+ computed: {
+ tooltip() {
+ if (this.overflowing) {
+ return this.tag;
+ }
+ return '';
+ },
+ },
+ methods: {
+ onResize() {
+ const { scrollWidth, offsetWidth } = this.$el;
+ this.overflowing = scrollWidth > offsetWidth;
},
},
RUNNER_TAG_BADGE_VARIANT,
};
</script>
<template>
- <gl-badge :size="size" :variant="$options.RUNNER_TAG_BADGE_VARIANT">
+ <gl-badge
+ v-gl-tooltip="tooltip"
+ v-gl-resize-observer="onResize"
+ class="gl-display-inline-block gl-max-w-full gl-text-truncate"
+ :size="size"
+ :variant="$options.RUNNER_TAG_BADGE_VARIANT"
+ >
{{ tag }}
</gl-badge>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_tags.vue b/app/assets/javascripts/runner/components/runner_tags.vue
index aec0d8e2c66..8da5e33076f 100644
--- a/app/assets/javascripts/runner/components/runner_tags.vue
+++ b/app/assets/javascripts/runner/components/runner_tags.vue
@@ -14,13 +14,19 @@ export default {
size: {
type: String,
required: false,
- default: 'md',
+ default: 'sm',
},
},
};
</script>
<template>
<div>
- <runner-tag v-for="tag in tagList" :key="tag" :tag="tag" :size="size" />
+ <runner-tag
+ v-for="tag in tagList"
+ :key="tag"
+ class="gl-display-inline gl-mr-1"
+ :tag="tag"
+ :size="size"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_type_alert.vue b/app/assets/javascripts/runner/components/runner_type_alert.vue
index aa435aaa823..1400875a1d6 100644
--- a/app/assets/javascripts/runner/components/runner_type_alert.vue
+++ b/app/assets/javascripts/runner/components/runner_type_alert.vue
@@ -9,17 +9,14 @@ const ALERT_DATA = {
message: s__(
'Runners|This runner is available to all groups and projects in your GitLab instance.',
),
- variant: 'success',
anchor: 'shared-runners',
},
[GROUP_TYPE]: {
message: s__('Runners|This runner is available to all projects and subgroups in a group.'),
- variant: 'success',
anchor: 'group-runners',
},
[PROJECT_TYPE]: {
message: s__('Runners|This runner is associated with one or more projects.'),
- variant: 'info',
anchor: 'specific-runners',
},
};
@@ -50,7 +47,7 @@ export default {
};
</script>
<template>
- <gl-alert v-if="alert" :variant="alert.variant" :dismissible="false">
+ <gl-alert v-if="alert" variant="info" :dismissible="false">
{{ alert.message }}
<gl-link :href="helpHref">{{ __('Learn more.') }}</gl-link>
</gl-alert>
diff --git a/app/assets/javascripts/runner/components/runner_type_badge.vue b/app/assets/javascripts/runner/components/runner_type_badge.vue
index 1a61b80184b..b885dcefdcb 100644
--- a/app/assets/javascripts/runner/components/runner_type_badge.vue
+++ b/app/assets/javascripts/runner/components/runner_type_badge.vue
@@ -12,17 +12,14 @@ import {
const BADGE_DATA = {
[INSTANCE_TYPE]: {
- variant: 'success',
text: s__('Runners|shared'),
tooltip: I18N_INSTANCE_RUNNER_DESCRIPTION,
},
[GROUP_TYPE]: {
- variant: 'success',
text: s__('Runners|group'),
tooltip: I18N_GROUP_RUNNER_DESCRIPTION,
},
[PROJECT_TYPE]: {
- variant: 'info',
text: s__('Runners|specific'),
tooltip: I18N_PROJECT_RUNNER_DESCRIPTION,
},
@@ -53,7 +50,7 @@ export default {
};
</script>
<template>
- <gl-badge v-if="badge" v-gl-tooltip="badge.tooltip" :variant="badge.variant" v-bind="$attrs">
+ <gl-badge v-if="badge" v-gl-tooltip="badge.tooltip" variant="info" v-bind="$attrs">
{{ badge.text }}
</gl-badge>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_type_tabs.vue b/app/assets/javascripts/runner/components/runner_type_tabs.vue
new file mode 100644
index 00000000000..b767dafaccf
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_type_tabs.vue
@@ -0,0 +1,66 @@
+<script>
+import { GlTabs, GlTab } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { searchValidator } from '~/runner/runner_search_utils';
+import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../constants';
+
+const tabs = [
+ {
+ title: s__('Runners|All'),
+ runnerType: null,
+ },
+ {
+ title: s__('Runners|Instance'),
+ runnerType: INSTANCE_TYPE,
+ },
+ {
+ title: s__('Runners|Group'),
+ runnerType: GROUP_TYPE,
+ },
+ {
+ title: s__('Runners|Project'),
+ runnerType: PROJECT_TYPE,
+ },
+];
+
+export default {
+ components: {
+ GlTabs,
+ GlTab,
+ },
+ props: {
+ value: {
+ type: Object,
+ required: true,
+ validator: searchValidator,
+ },
+ },
+ methods: {
+ onTabSelected({ runnerType }) {
+ this.$emit('input', {
+ ...this.value,
+ runnerType,
+ pagination: { page: 1 },
+ });
+ },
+ isTabActive({ runnerType }) {
+ return runnerType === this.value.runnerType;
+ },
+ },
+ tabs,
+};
+</script>
+<template>
+ <gl-tabs v-bind="$attrs" data-testid="runner-type-tabs">
+ <gl-tab
+ v-for="tab in $options.tabs"
+ :key="`${tab.runnerType}`"
+ :active="isTabActive(tab)"
+ @click="onTabSelected(tab)"
+ >
+ <template #title>
+ <slot name="title" :tab="tab">{{ tab.title }}</slot>
+ </template>
+ </gl-tab>
+ </gl-tabs>
+</template>
diff --git a/app/assets/javascripts/runner/components/search_tokens/status_token_config.js b/app/assets/javascripts/runner/components/search_tokens/status_token_config.js
index 03dff5e61a5..9963048ae1d 100644
--- a/app/assets/javascripts/runner/components/search_tokens/status_token_config.js
+++ b/app/assets/javascripts/runner/components/search_tokens/status_token_config.js
@@ -10,23 +10,29 @@ import {
PARAM_KEY_STATUS,
} from '../../constants';
+const options = [
+ { value: STATUS_ACTIVE, title: s__('Runners|Active') },
+ { value: STATUS_PAUSED, title: s__('Runners|Paused') },
+ { value: STATUS_ONLINE, title: s__('Runners|Online') },
+ { value: STATUS_OFFLINE, title: s__('Runners|Offline') },
+ { value: STATUS_NOT_CONNECTED, title: s__('Runners|Not connected') },
+];
+
export const statusTokenConfig = {
icon: 'status',
title: __('Status'),
type: PARAM_KEY_STATUS,
token: BaseToken,
unique: true,
- options: [
- { value: STATUS_ACTIVE, title: s__('Runners|Active') },
- { value: STATUS_PAUSED, title: s__('Runners|Paused') },
- { value: STATUS_ONLINE, title: s__('Runners|Online') },
- { value: STATUS_OFFLINE, title: s__('Runners|Offline') },
-
- // Added extra quotes in this title to avoid splitting this value:
+ options: options.map(({ value, title }) => ({
+ value,
+ // Replace whitespace with a special character to avoid
+ // splitting this value.
+ // Replacing in each option, as translations may also
+ // contain spaces!
+ // see: https://gitlab.com/gitlab-org/gitlab/-/issues/344142
// see: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1438
- { value: STATUS_NOT_CONNECTED, title: `"${s__('Runners|Not connected')}"` },
- ],
- // TODO In principle we could support more complex search rules,
- // this can be added to a separate issue.
+ title: title.replace(' ', '\u00a0'),
+ })),
operators: OPERATOR_IS_ONLY,
};
diff --git a/app/assets/javascripts/runner/components/search_tokens/type_token_config.js b/app/assets/javascripts/runner/components/search_tokens/type_token_config.js
deleted file mode 100644
index 1da61c53386..00000000000
--- a/app/assets/javascripts/runner/components/search_tokens/type_token_config.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { __, s__ } from '~/locale';
-import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
-import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
-import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE, PARAM_KEY_RUNNER_TYPE } from '../../constants';
-
-export const typeTokenConfig = {
- icon: 'file-tree',
- title: __('Type'),
- type: PARAM_KEY_RUNNER_TYPE,
- token: BaseToken,
- unique: true,
- options: [
- { value: INSTANCE_TYPE, title: s__('Runners|instance') },
- { value: GROUP_TYPE, title: s__('Runners|group') },
- { value: PROJECT_TYPE, title: s__('Runners|project') },
- ],
- // TODO We should support more complex search rules,
- // search for multiple states (OR) or have NOT operators
- operators: OPERATOR_IS_ONLY,
-};
diff --git a/app/assets/javascripts/runner/constants.js b/app/assets/javascripts/runner/constants.js
index a2fb9d9efd8..3952e2398e0 100644
--- a/app/assets/javascripts/runner/constants.js
+++ b/app/assets/javascripts/runner/constants.js
@@ -1,21 +1,33 @@
import { s__ } from '~/locale';
export const RUNNER_PAGE_SIZE = 20;
-export const RUNNER_JOB_COUNT_LIMIT = 1000;
export const GROUP_RUNNER_COUNT_LIMIT = 1000;
export const I18N_FETCH_ERROR = s__('Runners|Something went wrong while fetching runner data.');
export const I18N_DETAILS_TITLE = s__('Runners|Runner #%{runner_id}');
+// Type
export const I18N_INSTANCE_RUNNER_DESCRIPTION = s__('Runners|Available to all projects');
export const I18N_GROUP_RUNNER_DESCRIPTION = s__(
'Runners|Available to all projects and subgroups in the group',
);
export const I18N_PROJECT_RUNNER_DESCRIPTION = s__('Runners|Associated with one or more projects');
+
+// Status
+export const I18N_ONLINE_RUNNER_DESCRIPTION = s__(
+ 'Runners|Runner is online; last contact was %{timeAgo}',
+);
+export const I18N_OFFLINE_RUNNER_DESCRIPTION = s__(
+ 'Runners|No recent contact from this runner; last contact was %{timeAgo}',
+);
+export const I18N_NOT_CONNECTED_RUNNER_DESCRIPTION = s__(
+ 'Runners|This runner has never connected to this instance',
+);
+
export const I18N_LOCKED_RUNNER_DESCRIPTION = s__('Runners|You cannot assign to other projects');
export const I18N_PAUSED_RUNNER_DESCRIPTION = s__('Runners|Not available to run jobs');
-export const RUNNER_TAG_BADGE_VARIANT = 'info';
+export const RUNNER_TAG_BADGE_VARIANT = 'neutral';
export const RUNNER_TAG_BG_CLASS = 'gl-bg-blue-100';
// Filtered search parameter names
diff --git a/app/assets/javascripts/runner/graphql/runner_actions_update.mutation.graphql b/app/assets/javascripts/runner/graphql/runner_actions_update.mutation.graphql
new file mode 100644
index 00000000000..547cc43907c
--- /dev/null
+++ b/app/assets/javascripts/runner/graphql/runner_actions_update.mutation.graphql
@@ -0,0 +1,14 @@
+#import "~/runner/graphql/runner_node.fragment.graphql"
+
+# Mutation for updates within the runners list via action
+# buttons (play, pause, ...), loads attributes shown in the
+# runner list.
+
+mutation runnerActionsUpdate($input: RunnerUpdateInput!) {
+ runnerUpdate(input: $input) {
+ runner {
+ ...RunnerNode
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql b/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql
index 68d6f02f799..98f2dab26ca 100644
--- a/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql
+++ b/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql
@@ -10,6 +10,5 @@ fragment RunnerNode on CiRunner {
locked
tagList
contactedAt
- jobCount
- projectCount
+ status
}
diff --git a/app/assets/javascripts/runner/graphql/runner_update.mutation.graphql b/app/assets/javascripts/runner/graphql/runner_update.mutation.graphql
index dcc7fdf24f1..ea622fd4958 100644
--- a/app/assets/javascripts/runner/graphql/runner_update.mutation.graphql
+++ b/app/assets/javascripts/runner/graphql/runner_update.mutation.graphql
@@ -1,5 +1,8 @@
#import "ee_else_ce/runner/graphql/runner_details.fragment.graphql"
+# Mutation for updates from the runner form, loads
+# attributes shown in the runner details.
+
mutation runnerUpdate($input: RunnerUpdateInput!) {
runnerUpdate(input: $input) {
runner {
diff --git a/app/assets/javascripts/runner/group_runners/group_runners_app.vue b/app/assets/javascripts/runner/group_runners/group_runners_app.vue
index 4bb28796dfa..c3dfa885f27 100644
--- a/app/assets/javascripts/runner/group_runners/group_runners_app.vue
+++ b/app/assets/javascripts/runner/group_runners/group_runners_app.vue
@@ -5,14 +5,14 @@ import { fetchPolicies } from '~/lib/graphql';
import { updateHistory } from '~/lib/utils/url_utility';
import { formatNumber, sprintf, s__ } from '~/locale';
+import RegistrationDropdown from '../components/registration/registration_dropdown.vue';
import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue';
import RunnerList from '../components/runner_list.vue';
-import RunnerManualSetupHelp from '../components/runner_manual_setup_help.vue';
import RunnerName from '../components/runner_name.vue';
import RunnerPagination from '../components/runner_pagination.vue';
+import RunnerTypeTabs from '../components/runner_type_tabs.vue';
import { statusTokenConfig } from '../components/search_tokens/status_token_config';
-import { typeTokenConfig } from '../components/search_tokens/type_token_config';
import {
I18N_FETCH_ERROR,
GROUP_FILTERED_SEARCH_NAMESPACE,
@@ -31,11 +31,12 @@ export default {
name: 'GroupRunnersApp',
components: {
GlLink,
+ RegistrationDropdown,
RunnerFilteredSearchBar,
RunnerList,
- RunnerManualSetupHelp,
RunnerName,
RunnerPagination,
+ RunnerTypeTabs,
},
props: {
registrationToken: {
@@ -112,7 +113,7 @@ export default {
});
},
searchTokens() {
- return [statusTokenConfig, typeTokenConfig];
+ return [statusTokenConfig];
},
filteredSearchNamespace() {
return `${GROUP_FILTERED_SEARCH_NAMESPACE}/${this.groupFullPath}`;
@@ -144,7 +145,20 @@ export default {
<template>
<div>
- <runner-manual-setup-help :registration-token="registrationToken" :type="$options.GROUP_TYPE" />
+ <div class="gl-display-flex gl-align-items-center">
+ <runner-type-tabs
+ v-model="search"
+ content-class="gl-display-none"
+ nav-class="gl-border-none!"
+ />
+
+ <registration-dropdown
+ class="gl-ml-auto"
+ :registration-token="registrationToken"
+ :type="$options.GROUP_TYPE"
+ right
+ />
+ </div>
<runner-filtered-search-bar
v-model="search"
diff --git a/app/assets/javascripts/runner/group_runners/index.js b/app/assets/javascripts/runner/group_runners/index.js
index 9545764c68d..60b7a7ab541 100644
--- a/app/assets/javascripts/runner/group_runners/index.js
+++ b/app/assets/javascripts/runner/group_runners/index.js
@@ -1,8 +1,10 @@
+import { GlToast } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import GroupRunnersApp from './group_runners_app.vue';
+Vue.use(GlToast);
Vue.use(VueApollo);
export const initGroupRunners = (selector = '#js-group-runners') => {
@@ -21,12 +23,7 @@ export const initGroupRunners = (selector = '#js-group-runners') => {
} = el.dataset;
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- ),
+ defaultClient: createDefaultClient(),
});
return new Vue({
diff --git a/app/assets/javascripts/runner/runner_details/index.js b/app/assets/javascripts/runner/runner_details/index.js
index 05e6f86869d..db8f239a3c3 100644
--- a/app/assets/javascripts/runner/runner_details/index.js
+++ b/app/assets/javascripts/runner/runner_details/index.js
@@ -15,12 +15,7 @@ export const initRunnerDetail = (selector = '#js-runner-details') => {
const { runnerId } = el.dataset;
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- ),
+ defaultClient: createDefaultClient(),
});
return new Vue({
diff --git a/app/assets/javascripts/runner/runner_search_utils.js b/app/assets/javascripts/runner/runner_search_utils.js
index 0a817ea0acf..b88023720e8 100644
--- a/app/assets/javascripts/runner/runner_search_utils.js
+++ b/app/assets/javascripts/runner/runner_search_utils.js
@@ -18,6 +18,50 @@ import {
RUNNER_PAGE_SIZE,
} from './constants';
+/**
+ * The filters and sorting of the runners are built around
+ * an object called "search" that contains the current state
+ * of search in the UI. For example:
+ *
+ * ```
+ * const search = {
+ * // The current tab
+ * runnerType: 'INSTANCE_TYPE',
+ *
+ * // Filters in the search bar
+ * filters: [
+ * { type: 'status', value: { data: 'ACTIVE', operator: '=' } },
+ * { type: 'filtered-search-term', value: { data: '' } },
+ * ],
+ *
+ * // Current sorting value
+ * sort: 'CREATED_DESC',
+ *
+ * // Pagination information
+ * pagination: { page: 1 },
+ * };
+ * ```
+ *
+ * An object in this format can be used to generate URLs
+ * with the search parameters or by runner components
+ * a input using a v-model.
+ *
+ * @module runner_search_utils
+ */
+
+/**
+ * Validates a search value
+ * @param {Object} search
+ * @returns {boolean} True if the value follows the search format.
+ */
+export const searchValidator = ({ runnerType, filters, sort }) => {
+ return (
+ (runnerType === null || typeof runnerType === 'string') &&
+ Array.isArray(filters) &&
+ typeof sort === 'string'
+ );
+};
+
const getPaginationFromParams = (params) => {
const page = parseInt(params[PARAM_KEY_PAGE], 10);
const after = params[PARAM_KEY_AFTER];
@@ -35,13 +79,20 @@ const getPaginationFromParams = (params) => {
};
};
+/**
+ * Takes a URL query and transforms it into a "search" object
+ * @param {String?} query
+ * @returns {Object} A search object
+ */
export const fromUrlQueryToSearch = (query = window.location.search) => {
const params = queryToObject(query, { gatherArrays: true });
+ const runnerType = params[PARAM_KEY_RUNNER_TYPE]?.[0] || null;
return {
+ runnerType,
filters: prepareTokens(
urlQueryToFilter(query, {
- filterNamesAllowList: [PARAM_KEY_STATUS, PARAM_KEY_RUNNER_TYPE, PARAM_KEY_TAG],
+ filterNamesAllowList: [PARAM_KEY_STATUS, PARAM_KEY_TAG],
filteredSearchTermKey: PARAM_KEY_SEARCH,
}),
),
@@ -50,8 +101,15 @@ export const fromUrlQueryToSearch = (query = window.location.search) => {
};
};
+/**
+ * Takes a "search" object and transforms it into a URL.
+ *
+ * @param {Object} search
+ * @param {String} url
+ * @returns {String} New URL for the page
+ */
export const fromSearchToUrl = (
- { filters = [], sort = null, pagination = {} },
+ { runnerType = null, filters = [], sort = null, pagination = {} },
url = window.location.href,
) => {
const filterParams = {
@@ -65,6 +123,10 @@ export const fromSearchToUrl = (
}),
};
+ if (runnerType) {
+ filterParams[PARAM_KEY_RUNNER_TYPE] = [runnerType];
+ }
+
if (!filterParams[PARAM_KEY_SEARCH]) {
filterParams[PARAM_KEY_SEARCH] = null;
}
@@ -82,21 +144,31 @@ export const fromSearchToUrl = (
return setUrlParams({ ...filterParams, ...otherParams }, url, false, true, true);
};
-export const fromSearchToVariables = ({ filters = [], sort = null, pagination = {} } = {}) => {
+/**
+ * Takes a "search" object and transforms it into variables for runner a GraphQL query.
+ *
+ * @param {Object} search
+ * @returns {Object} Hash of filter values
+ */
+export const fromSearchToVariables = ({
+ runnerType = null,
+ filters = [],
+ sort = null,
+ pagination = {},
+} = {}) => {
const variables = {};
const queryObj = filterToQueryObject(processFilters(filters), {
filteredSearchTermKey: PARAM_KEY_SEARCH,
});
- variables.search = queryObj[PARAM_KEY_SEARCH];
-
- // TODO Get more than one value when GraphQL API supports OR for "status" or "runner_type"
[variables.status] = queryObj[PARAM_KEY_STATUS] || [];
- [variables.type] = queryObj[PARAM_KEY_RUNNER_TYPE] || [];
-
+ variables.search = queryObj[PARAM_KEY_SEARCH];
variables.tagList = queryObj[PARAM_KEY_TAG];
+ if (runnerType) {
+ variables.type = runnerType;
+ }
if (sort) {
variables.sort = sort;
}
diff --git a/app/assets/javascripts/search/sidebar/components/app.vue b/app/assets/javascripts/search/sidebar/components/app.vue
index 99cf16c8350..5c7cbeac5b2 100644
--- a/app/assets/javascripts/search/sidebar/components/app.vue
+++ b/app/assets/javascripts/search/sidebar/components/app.vue
@@ -13,9 +13,9 @@ export default {
ConfidentialityFilter,
},
computed: {
- ...mapState(['query']),
+ ...mapState(['urlQuery', 'sidebarDirty']),
showReset() {
- return this.query.state || this.query.confidential;
+ return this.urlQuery.state || this.urlQuery.confidential;
},
},
methods: {
@@ -32,7 +32,7 @@ export default {
<status-filter />
<confidentiality-filter />
<div class="gl-display-flex gl-align-items-center gl-mt-3">
- <gl-button category="primary" variant="confirm" size="small" type="submit">
+ <gl-button category="primary" variant="confirm" type="submit" :disabled="!sidebarDirty">
{{ __('Apply') }}
</gl-button>
<gl-link v-if="showReset" class="gl-ml-auto" @click="resetQuery">{{
diff --git a/app/assets/javascripts/search/sidebar/components/radio_filter.vue b/app/assets/javascripts/search/sidebar/components/radio_filter.vue
index 73911b9d319..aa7c26b8044 100644
--- a/app/assets/javascripts/search/sidebar/components/radio_filter.vue
+++ b/app/assets/javascripts/search/sidebar/components/radio_filter.vue
@@ -1,7 +1,7 @@
<script>
import { GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
-import { sprintf, s__ } from '~/locale';
+import { sprintf, __ } from '~/locale';
export default {
name: 'RadioFilter',
@@ -49,7 +49,7 @@ export default {
...mapActions(['setQuery']),
radioLabel(filter) {
return filter.value === this.ANY.value
- ? sprintf(s__('Any %{header}'), { header: this.filterData.header.toLowerCase() })
+ ? sprintf(__('Any %{header}'), { header: this.filterData.header.toLowerCase() })
: filter.label;
},
},
diff --git a/app/assets/javascripts/search/sidebar/constants/state_filter_data.js b/app/assets/javascripts/search/sidebar/constants/state_filter_data.js
index 7c9a029ffe4..2f9f8a7cb46 100644
--- a/app/assets/javascripts/search/sidebar/constants/state_filter_data.js
+++ b/app/assets/javascripts/search/sidebar/constants/state_filter_data.js
@@ -5,7 +5,7 @@ const header = __('Status');
const filters = {
ANY: {
label: __('Any'),
- value: 'all',
+ value: null,
},
OPEN: {
label: __('Open'),
diff --git a/app/assets/javascripts/search/store/actions.js b/app/assets/javascripts/search/store/actions.js
index be64a9278e3..a6af5644681 100644
--- a/app/assets/javascripts/search/store/actions.js
+++ b/app/assets/javascripts/search/store/actions.js
@@ -2,9 +2,9 @@ import Api from '~/api';
import createFlash from '~/flash';
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
-import { GROUPS_LOCAL_STORAGE_KEY, PROJECTS_LOCAL_STORAGE_KEY } from './constants';
+import { GROUPS_LOCAL_STORAGE_KEY, PROJECTS_LOCAL_STORAGE_KEY, SIDEBAR_PARAMS } from './constants';
import * as types from './mutation_types';
-import { loadDataFromLS, setFrequentItemToLS, mergeById } from './utils';
+import { loadDataFromLS, setFrequentItemToLS, mergeById, isSidebarDirty } from './utils';
export const fetchGroups = ({ commit }, search) => {
commit(types.REQUEST_GROUPS);
@@ -86,8 +86,12 @@ export const setFrequentProject = ({ state, commit }, item) => {
commit(types.LOAD_FREQUENT_ITEMS, { key: PROJECTS_LOCAL_STORAGE_KEY, data: frequentItems });
};
-export const setQuery = ({ commit }, { key, value }) => {
+export const setQuery = ({ state, commit }, { key, value }) => {
commit(types.SET_QUERY, { key, value });
+
+ if (SIDEBAR_PARAMS.includes(key)) {
+ commit(types.SET_SIDEBAR_DIRTY, isSidebarDirty(state.query, state.urlQuery));
+ }
};
export const applyQuery = ({ state }) => {
diff --git a/app/assets/javascripts/search/store/constants.js b/app/assets/javascripts/search/store/constants.js
index 3abf7cac6ba..678bd82c7a6 100644
--- a/app/assets/javascripts/search/store/constants.js
+++ b/app/assets/javascripts/search/store/constants.js
@@ -1,3 +1,6 @@
+import { stateFilterData } from '~/search/sidebar/constants/state_filter_data';
+import { confidentialFilterData } from '~/search/sidebar/constants/confidential_filter_data';
+
export const MAX_FREQUENT_ITEMS = 5;
export const MAX_FREQUENCY = 5;
@@ -5,3 +8,5 @@ export const MAX_FREQUENCY = 5;
export const GROUPS_LOCAL_STORAGE_KEY = 'global-search-frequent-groups';
export const PROJECTS_LOCAL_STORAGE_KEY = 'global-search-frequent-projects';
+
+export const SIDEBAR_PARAMS = [stateFilterData.filterParam, confidentialFilterData.filterParam];
diff --git a/app/assets/javascripts/search/store/mutation_types.js b/app/assets/javascripts/search/store/mutation_types.js
index 5c1c29dc738..bf1e3e79cba 100644
--- a/app/assets/javascripts/search/store/mutation_types.js
+++ b/app/assets/javascripts/search/store/mutation_types.js
@@ -7,5 +7,6 @@ export const RECEIVE_PROJECTS_SUCCESS = 'RECEIVE_PROJECTS_SUCCESS';
export const RECEIVE_PROJECTS_ERROR = 'RECEIVE_PROJECTS_ERROR';
export const SET_QUERY = 'SET_QUERY';
+export const SET_SIDEBAR_DIRTY = 'SET_SIDEBAR_DIRTY';
export const LOAD_FREQUENT_ITEMS = 'LOAD_FREQUENT_ITEMS';
diff --git a/app/assets/javascripts/search/store/mutations.js b/app/assets/javascripts/search/store/mutations.js
index 63156a89738..5d154fe3aa0 100644
--- a/app/assets/javascripts/search/store/mutations.js
+++ b/app/assets/javascripts/search/store/mutations.js
@@ -26,6 +26,9 @@ export default {
[types.SET_QUERY](state, { key, value }) {
state.query[key] = value;
},
+ [types.SET_SIDEBAR_DIRTY](state, value) {
+ state.sidebarDirty = value;
+ },
[types.LOAD_FREQUENT_ITEMS](state, { key, data }) {
state.frequentItems[key] = data;
},
diff --git a/app/assets/javascripts/search/store/state.js b/app/assets/javascripts/search/store/state.js
index 5b1429ccc97..d4005697f35 100644
--- a/app/assets/javascripts/search/store/state.js
+++ b/app/assets/javascripts/search/store/state.js
@@ -1,6 +1,8 @@
+import { cloneDeep } from 'lodash';
import { GROUPS_LOCAL_STORAGE_KEY, PROJECTS_LOCAL_STORAGE_KEY } from './constants';
const createState = ({ query }) => ({
+ urlQuery: cloneDeep(query),
query,
groups: [],
fetchingGroups: false,
@@ -10,5 +12,6 @@ const createState = ({ query }) => ({
[GROUPS_LOCAL_STORAGE_KEY]: [],
[PROJECTS_LOCAL_STORAGE_KEY]: [],
},
+ sidebarDirty: false,
});
export default createState;
diff --git a/app/assets/javascripts/search/store/utils.js b/app/assets/javascripts/search/store/utils.js
index b00b9bb0f2e..6b56ff0b5e5 100644
--- a/app/assets/javascripts/search/store/utils.js
+++ b/app/assets/javascripts/search/store/utils.js
@@ -1,5 +1,5 @@
import AccessorUtilities from '../../lib/utils/accessor';
-import { MAX_FREQUENT_ITEMS, MAX_FREQUENCY } from './constants';
+import { MAX_FREQUENT_ITEMS, MAX_FREQUENCY, SIDEBAR_PARAMS } from './constants';
function extractKeys(object, keyList) {
return Object.fromEntries(keyList.map((key) => [key, object[key]]));
@@ -80,3 +80,13 @@ export const mergeById = (inflatedData, storedData) => {
return { ...stored, ...data };
});
};
+
+export const isSidebarDirty = (currentQuery, urlQuery) => {
+ return SIDEBAR_PARAMS.some((param) => {
+ // userAddParam ensures we don't get a false dirty from null !== undefined
+ const userAddedParam = !urlQuery[param] && currentQuery[param];
+ const userChangedExistingParam = urlQuery[param] && urlQuery[param] !== currentQuery[param];
+
+ return userAddedParam || userChangedExistingParam;
+ });
+};
diff --git a/app/assets/javascripts/security_configuration/components/app.vue b/app/assets/javascripts/security_configuration/components/app.vue
index 6c70a8c33db..bc13150c99c 100644
--- a/app/assets/javascripts/security_configuration/components/app.vue
+++ b/app/assets/javascripts/security_configuration/components/app.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTab, GlTabs, GlSprintf, GlLink } from '@gitlab/ui';
+import { GlTab, GlTabs, GlSprintf, GlLink, GlAlert } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
@@ -31,6 +31,7 @@ export default {
AutoDevOpsAlert,
AutoDevOpsEnabledAlert,
FeatureCard,
+ GlAlert,
GlLink,
GlSprintf,
GlTab,
@@ -79,6 +80,7 @@ export default {
data() {
return {
autoDevopsEnabledAlertDismissedProjects: [],
+ errorMessage: '',
};
},
computed: {
@@ -106,6 +108,12 @@ export default {
dismissedProjects.add(this.projectPath);
this.autoDevopsEnabledAlertDismissedProjects = Array.from(dismissedProjects);
},
+ onError(message) {
+ this.errorMessage = message;
+ },
+ dismissAlert() {
+ this.errorMessage = '';
+ },
},
autoDevopsEnabledAlertStorageKey: AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY,
};
@@ -113,6 +121,16 @@ export default {
<template>
<article>
+ <gl-alert
+ v-if="errorMessage"
+ sticky
+ class="gl-top-8 gl-z-index-1"
+ data-testid="manage-via-mr-error-alert"
+ variant="danger"
+ @dismiss="dismissAlert"
+ >
+ {{ errorMessage }}
+ </gl-alert>
<local-storage-sync
v-model="autoDevopsEnabledAlertDismissedProjects"
:storage-key="$options.autoDevopsEnabledAlertStorageKey"
@@ -174,6 +192,7 @@ export default {
data-testid="security-testing-card"
:feature="feature"
class="gl-mb-6"
+ @error="onError"
/>
</template>
</section-layout>
@@ -207,6 +226,7 @@ export default {
:key="feature.type"
:feature="feature"
class="gl-mb-6"
+ @error="onError"
/>
</template>
</section-layout>
diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js
index 6a282df99bf..9c80506549e 100644
--- a/app/assets/javascripts/security_configuration/components/constants.js
+++ b/app/assets/javascripts/security_configuration/components/constants.js
@@ -3,6 +3,7 @@ import { __, s__ } from '~/locale';
import {
REPORT_TYPE_SAST,
+ REPORT_TYPE_SAST_IAC,
REPORT_TYPE_DAST,
REPORT_TYPE_DAST_PROFILES,
REPORT_TYPE_SECRET_DETECTION,
@@ -16,6 +17,7 @@ import {
} from '~/vue_shared/security_reports/constants';
import configureSastMutation from '../graphql/configure_sast.mutation.graphql';
+import configureSastIacMutation from '../graphql/configure_iac.mutation.graphql';
import configureSecretDetectionMutation from '../graphql/configure_secret_detection.mutation.graphql';
/**
@@ -30,6 +32,19 @@ export const SAST_CONFIG_HELP_PATH = helpPagePath('user/application_security/sas
anchor: 'configuration',
});
+export const SAST_IAC_NAME = __('Infrastructure as Code (IaC) Scanning');
+export const SAST_IAC_SHORT_NAME = s__('ciReport|IaC Scanning');
+export const SAST_IAC_DESCRIPTION = __(
+ 'Analyze your infrastructure as code configuration files for known vulnerabilities.',
+);
+export const SAST_IAC_HELP_PATH = helpPagePath('user/application_security/iac_scanning/index');
+export const SAST_IAC_CONFIG_HELP_PATH = helpPagePath(
+ 'user/application_security/iac_scanning/index',
+ {
+ anchor: 'configuration',
+ },
+);
+
export const DAST_NAME = __('Dynamic Application Security Testing (DAST)');
export const DAST_SHORT_NAME = s__('ciReport|DAST');
export const DAST_DESCRIPTION = __('Analyze a review version of your web application.');
@@ -141,6 +156,27 @@ export const securityFeatures = [
// https://gitlab.com/gitlab-org/gitlab/-/issues/331621
canEnableByMergeRequest: true,
},
+ ...(gon?.features?.configureIacScanningViaMr
+ ? [
+ {
+ name: SAST_IAC_NAME,
+ shortName: SAST_IAC_SHORT_NAME,
+ description: SAST_IAC_DESCRIPTION,
+ helpPath: SAST_IAC_HELP_PATH,
+ configurationHelpPath: SAST_IAC_CONFIG_HELP_PATH,
+ type: REPORT_TYPE_SAST_IAC,
+
+ // This field is currently hardcoded because SAST IaC is always available.
+ // It will eventually come from the Backend, the progress is tracked in
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/331622
+ available: true,
+
+ // This field will eventually come from the backend, the progress is
+ // tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/331621
+ canEnableByMergeRequest: true,
+ },
+ ]
+ : []),
{
name: DAST_NAME,
shortName: DAST_SHORT_NAME,
@@ -242,6 +278,21 @@ export const featureToMutationMap = {
},
}),
},
+ ...(gon?.features?.configureIacScanningViaMr
+ ? {
+ [REPORT_TYPE_SAST_IAC]: {
+ mutationId: 'configureSastIac',
+ getMutationPayload: (projectPath) => ({
+ mutation: configureSastIacMutation,
+ variables: {
+ input: {
+ projectPath,
+ },
+ },
+ }),
+ },
+ }
+ : {}),
[REPORT_TYPE_SECRET_DETECTION]: {
mutationId: 'configureSecretDetection',
getMutationPayload: (projectPath) => ({
diff --git a/app/assets/javascripts/security_configuration/components/feature_card.vue b/app/assets/javascripts/security_configuration/components/feature_card.vue
index 86afdbfeb8c..33d72b54f86 100644
--- a/app/assets/javascripts/security_configuration/components/feature_card.vue
+++ b/app/assets/javascripts/security_configuration/components/feature_card.vue
@@ -66,6 +66,11 @@ export default {
return Boolean(name && description && configurationText);
},
},
+ methods: {
+ onError(message) {
+ this.$emit('error', message);
+ },
+ },
i18n: {
enabled: s__('SecurityConfiguration|Enabled'),
notEnabled: s__('SecurityConfiguration|Not enabled'),
@@ -129,6 +134,7 @@ export default {
category="primary"
class="gl-mt-5"
:data-qa-selector="`${feature.type}_mr_button`"
+ @error="onError"
/>
<gl-button
diff --git a/app/assets/javascripts/security_configuration/graphql/configure_iac.mutation.graphql b/app/assets/javascripts/security_configuration/graphql/configure_iac.mutation.graphql
new file mode 100644
index 00000000000..26b826ef722
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/graphql/configure_iac.mutation.graphql
@@ -0,0 +1,6 @@
+mutation configureSastIac($input: ConfigureSastIacInput!) {
+ configureSastIac(input: $input) {
+ successPath
+ errors
+ }
+}
diff --git a/app/assets/javascripts/security_configuration/index.js b/app/assets/javascripts/security_configuration/index.js
index 60d2c0d4e5a..a8623b468f2 100644
--- a/app/assets/javascripts/security_configuration/index.js
+++ b/app/assets/javascripts/security_configuration/index.js
@@ -14,7 +14,7 @@ export const initSecurityConfiguration = (el) => {
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
const {
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
index b1c8f6ef22e..0021fe909e5 100644
--- a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
@@ -339,7 +339,7 @@ export default {
</div>
<div class="gl-display-flex">
<span class="gl-text-gray-600 gl-ml-5">
- {{ s__('SetStatusModal|A busy indicator is shown next to your name and avatar.') }}
+ {{ s__('SetStatusModal|An indicator appears next to your name and avatar') }}
</span>
</div>
</div>
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees.vue b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
index e41bb41dc05..bdd014163a0 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
@@ -39,6 +39,9 @@ export default {
assignSelf() {
this.$emit('assign-self');
},
+ toggleAttentionRequested(data) {
+ this.$emit('toggle-attention-requested', data);
+ },
},
};
</script>
@@ -58,7 +61,12 @@ export default {
</template>
</span>
- <uncollapsed-assignee-list v-else :users="sortedAssigness" :issuable-type="issuableType" />
+ <uncollapsed-assignee-list
+ v-else
+ :users="sortedAssigness"
+ :issuable-type="issuableType"
+ @toggle-attention-requested="toggleAttentionRequested"
+ />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
index 80caebad39d..a3379784bc1 100644
--- a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
@@ -32,6 +32,11 @@ export default {
return this.users.length === 0;
},
},
+ methods: {
+ toggleAttentionRequested(data) {
+ this.$emit('toggle-attention-requested', data);
+ },
+ },
};
</script>
@@ -61,6 +66,7 @@ export default {
:users="users"
:issuable-type="issuableType"
class="gl-text-gray-800 gl-mt-2 hide-collapsed"
+ @toggle-attention-requested="toggleAttentionRequested"
/>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
index c6877226b7d..453dd1b0580 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
@@ -125,6 +125,9 @@ export default {
availability: this.assigneeAvailabilityStatus[username] || '',
}));
},
+ toggleAttentionRequested(data) {
+ this.mediator.toggleAttentionRequested('assignee', data);
+ },
},
};
</script>
@@ -152,6 +155,7 @@ export default {
:editable="store.editable"
:issuable-type="issuableType"
@assign-self="assignSelf"
+ @toggle-attention-requested="toggleAttentionRequested"
/>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
index c2ca87af9ce..8d5c3b2def3 100644
--- a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
@@ -1,6 +1,8 @@
<script>
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { IssuableType } from '~/issue_show/constants';
import { __, sprintf } from '~/locale';
+import AttentionRequestedToggle from '../attention_requested_toggle.vue';
import AssigneeAvatarLink from './assignee_avatar_link.vue';
import UserNameWithStatus from './user_name_with_status.vue';
@@ -8,9 +10,11 @@ const DEFAULT_RENDER_COUNT = 5;
export default {
components: {
+ AttentionRequestedToggle,
AssigneeAvatarLink,
UserNameWithStatus,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
users: {
type: Array,
@@ -32,6 +36,10 @@ export default {
return this.users[0];
},
hasOneUser() {
+ if (this.showVerticalList) {
+ return false;
+ }
+
return this.users.length === 1;
},
hiddenAssigneesLabel() {
@@ -45,6 +53,10 @@ export default {
return this.users.length - DEFAULT_RENDER_COUNT;
},
uncollapsedUsers() {
+ if (this.showVerticalList) {
+ return this.users;
+ }
+
const uncollapsedLength = this.showLess
? Math.min(this.users.length, DEFAULT_RENDER_COUNT)
: this.users.length;
@@ -53,6 +65,12 @@ export default {
username() {
return `@${this.firstUser.username}`;
},
+ showVerticalList() {
+ return this.glFeatures.mrAttentionRequests && this.isMergeRequest;
+ },
+ isMergeRequest() {
+ return this.issuableType === IssuableType.MergeRequest;
+ },
},
methods: {
toggleShowLess() {
@@ -64,6 +82,9 @@ export default {
}
return u?.status?.availability || '';
},
+ toggleAttentionRequested(data) {
+ this.$emit('toggle-attention-requested', data);
+ },
},
};
</script>
@@ -84,11 +105,34 @@ export default {
<div v-else>
<div class="gl-display-flex gl-flex-wrap">
<div
- v-for="user in uncollapsedUsers"
+ v-for="(user, index) in uncollapsedUsers"
:key="user.id"
- class="user-item gl-display-inline-block"
+ :class="{
+ 'user-item': !showVerticalList,
+ 'gl-mb-3': index !== users.length - 1 && showVerticalList,
+ }"
+ class="gl-display-inline-block"
>
- <assignee-avatar-link :user="user" :issuable-type="issuableType" />
+ <attention-requested-toggle
+ v-if="showVerticalList && user.can_update_merge_request"
+ :user="user"
+ type="assignee"
+ @toggle-attention-requested="toggleAttentionRequested"
+ />
+ <assignee-avatar-link
+ :user="user"
+ :issuable-type="issuableType"
+ :tooltip-has-name="!showVerticalList"
+ >
+ <div
+ v-if="showVerticalList"
+ class="gl-ml-3 gl-line-height-normal gl-display-grid"
+ data-testid="username"
+ >
+ <user-name-with-status :name="user.name" :availability="userAvailability(user)" />
+ <span>@{{ user.username }}</span>
+ </div>
+ </assignee-avatar-link>
</div>
</div>
<div v-if="renderShowMoreSection" class="user-list-more gl-hover-text-blue-800">
diff --git a/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue b/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue
new file mode 100644
index 00000000000..38ba468d197
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue
@@ -0,0 +1,74 @@
+<script>
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { __ } from '~/locale';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
+
+export default {
+ i18n: {
+ attentionRequestedReviewer: __('Request attention to review'),
+ attentionRequestedAssignee: __('Request attention'),
+ removeAttentionRequested: __('Remove attention request'),
+ },
+ components: {
+ GlButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ type: {
+ type: String,
+ required: true,
+ },
+ user: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ loading: false,
+ };
+ },
+ computed: {
+ tooltipTitle() {
+ if (this.user.attention_requested) {
+ return this.$options.i18n.removeAttentionRequested;
+ }
+
+ return this.type === 'reviewer'
+ ? this.$options.i18n.attentionRequestedReviewer
+ : this.$options.i18n.attentionRequestedAssignee;
+ },
+ },
+ methods: {
+ toggleAttentionRequired() {
+ if (this.loading) return;
+
+ this.$root.$emit(BV_HIDE_TOOLTIP);
+ this.loading = true;
+ this.$emit('toggle-attention-requested', {
+ user: this.user,
+ callback: this.toggleAttentionRequiredComplete,
+ });
+ },
+ toggleAttentionRequiredComplete() {
+ this.loading = false;
+ },
+ },
+};
+</script>
+
+<template>
+ <span v-gl-tooltip.left.viewport="tooltipTitle">
+ <gl-button
+ :loading="loading"
+ :variant="user.attention_requested ? 'warning' : 'default'"
+ :icon="user.attention_requested ? 'star' : 'star-o'"
+ :aria-label="tooltipTitle"
+ size="small"
+ category="tertiary"
+ @click="toggleAttentionRequired"
+ />
+ </span>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
index d5647619ea3..5cd4a1a5192 100644
--- a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
+++ b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
@@ -11,6 +11,7 @@ import { toLabelGid } from '~/sidebar/utils';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
import LabelsSelectWidget from '~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue';
+import { LabelType } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
const mutationMap = {
@@ -48,6 +49,7 @@ export default {
return {
isLabelsSelectInProgress: false,
selectedLabels: this.initiallySelectedLabels,
+ LabelType,
};
},
methods: {
@@ -154,13 +156,12 @@ export default {
:footer-manage-label-title="__('Manage project labels')"
:labels-create-title="__('Create project label')"
:labels-filter-base-path="projectIssuesPath"
- :labels-select-in-progress="isLabelsSelectInProgress"
- :selected-labels="selectedLabels"
:variant="$options.variant"
:issuable-type="issuableType"
+ workspace-type="project"
+ :attr-workspace-path="fullPath"
+ :label-create-type="LabelType.project"
data-qa-selector="labels_block"
- @onLabelRemove="handleLabelRemove"
- @updateSelectedLabels="handleUpdateSelectedLabels"
>
{{ __('None') }}
</labels-select-widget>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
index 5729b958b5d..b07fd944ff9 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
@@ -49,6 +49,9 @@ export default {
requestReview(data) {
this.$emit('request-review', data);
},
+ toggleAttentionRequested(data) {
+ this.$emit('toggle-attention-requested', data);
+ },
},
};
</script>
@@ -70,6 +73,7 @@ export default {
:root-path="rootPath"
:issuable-type="issuableType"
@request-review="requestReview"
+ @toggle-attention-requested="toggleAttentionRequested"
/>
</div>
</div>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
index e414aaf719b..2ea63219e92 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
@@ -88,6 +88,9 @@ export default {
requestReview(data) {
this.mediator.requestReview(data);
},
+ toggleAttentionRequested(data) {
+ this.mediator.toggleAttentionRequested('reviewer', data);
+ },
},
};
</script>
@@ -106,6 +109,7 @@ export default {
:editable="store.editable"
:issuable-type="issuableType"
@request-review="requestReview"
+ @toggle-attention-requested="toggleAttentionRequested"
/>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
index 2922008cfb2..adaf1b65f3f 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
@@ -1,6 +1,8 @@
<script>
import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { __, sprintf, s__ } from '~/locale';
+import AttentionRequestedToggle from '../attention_requested_toggle.vue';
import ReviewerAvatarLink from './reviewer_avatar_link.vue';
const LOADING_STATE = 'loading';
@@ -14,10 +16,12 @@ export default {
GlButton,
GlIcon,
ReviewerAvatarLink,
+ AttentionRequestedToggle,
},
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
users: {
type: Array,
@@ -76,6 +80,9 @@ export default {
this.loadingStates[userId] = null;
}
},
+ toggleAttentionRequested(data) {
+ this.$emit('toggle-attention-requested', data);
+ },
},
LOADING_STATE,
SUCCESS_STATE,
@@ -90,6 +97,12 @@ export default {
:class="{ 'gl-mb-3': index !== users.length - 1 }"
data-testid="reviewer"
>
+ <attention-requested-toggle
+ v-if="glFeatures.mrAttentionRequests && user.can_update_merge_request"
+ :user="user"
+ type="reviewer"
+ @toggle-attention-requested="toggleAttentionRequested"
+ />
<reviewer-avatar-link :user="user" :root-path="rootPath" :issuable-type="issuableType">
<div class="gl-ml-3 gl-line-height-normal gl-display-grid">
<span>{{ user.name }}</span>
@@ -113,7 +126,9 @@ export default {
data-testid="re-request-success"
/>
<gl-button
- v-else-if="user.can_update_merge_request && user.reviewed"
+ v-else-if="
+ user.can_update_merge_request && user.reviewed && !glFeatures.mrAttentionRequests
+ "
v-gl-tooltip.left
:title="$options.i18n.reRequestReview"
:aria-label="$options.i18n.reRequestReview"
diff --git a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
index 8f4d5406da8..0ba8c4f8907 100644
--- a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
+++ b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
@@ -370,6 +370,7 @@ export default {
:loading="loading"
class="gl-w-full"
toggle-class="gl-max-w-100"
+ block
@shown="setFocus"
>
<gl-search-box-by-type ref="search" v-model="searchTerm" />
diff --git a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
index 22adbd79ef6..056b3e98a1c 100644
--- a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
+++ b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
@@ -134,7 +134,7 @@ export default {
v-if="canUpdate && !initialLoading && canEdit"
category="tertiary"
size="small"
- class="gl-text-gray-900! gl-ml-auto hide-collapsed gl-mr-n2"
+ class="gl-text-gray-900! gl-ml-auto hide-collapsed gl-mr-n2 shortcut-sidebar-dropdown-toggle"
data-testid="edit-button"
:data-track-action="tracking.event"
:data-track-label="tracking.label"
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/report.vue b/app/assets/javascripts/sidebar/components/time_tracking/report.vue
index d4a8abb81a8..5d4031ac68b 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/report.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/report.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon, GlTable } from '@gitlab/ui';
+import { GlLoadingIcon, GlTableLite } from '@gitlab/ui';
import createFlash from '~/flash';
import { TYPE_ISSUE, TYPE_MERGE_REQUEST } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
@@ -12,7 +12,7 @@ const TIME_DATE_FORMAT = 'mmmm d, yyyy, HH:MM ("UTC:" o)';
export default {
components: {
GlLoadingIcon,
- GlTable,
+ GlTableLite,
},
inject: ['issuableType'],
props: {
@@ -89,7 +89,7 @@ export default {
<template>
<div>
<div v-if="isLoading"><gl-loading-icon size="md" /></div>
- <gl-table v-else :items="report" :fields="$options.fields" foot-clone>
+ <gl-table-lite v-else :items="report" :fields="$options.fields" foot-clone>
<template #cell(spentAt)="{ item: { spentAt } }">
<div>{{ formatDate(spentAt) }}</div>
</template>
@@ -111,6 +111,6 @@ export default {
<div>{{ getSummary(summary, note) }}</div>
</template>
<template #foot(note)>&nbsp;</template>
- </gl-table>
+ </gl-table-lite>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/constants.js b/app/assets/javascripts/sidebar/constants.js
index e593973da82..ac34a75ac5c 100644
--- a/app/assets/javascripts/sidebar/constants.js
+++ b/app/assets/javascripts/sidebar/constants.js
@@ -1,4 +1,5 @@
-import { IssuableType } from '~/issue_show/constants';
+import updateIssueLabelsMutation from '~/boards/graphql/issue_set_labels.mutation.graphql';
+import { IssuableType, WorkspaceType } from '~/issue_show/constants';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import epicConfidentialQuery from '~/sidebar/queries/epic_confidential.query.graphql';
import epicDueDateQuery from '~/sidebar/queries/epic_due_date.query.graphql';
@@ -29,11 +30,14 @@ import updateIssueConfidentialMutation from '~/sidebar/queries/update_issue_conf
import updateIssueDueDateMutation from '~/sidebar/queries/update_issue_due_date.mutation.graphql';
import updateIssueSubscriptionMutation from '~/sidebar/queries/update_issue_subscription.mutation.graphql';
import mergeRequestMilestoneMutation from '~/sidebar/queries/update_merge_request_milestone.mutation.graphql';
+import updateMergeRequestLabelsMutation from '~/sidebar/queries/update_merge_request_labels.mutation.graphql';
import updateMergeRequestSubscriptionMutation from '~/sidebar/queries/update_merge_request_subscription.mutation.graphql';
import updateAlertAssigneesMutation from '~/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql';
import epicLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql';
+import updateEpicLabelsMutation from '~/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql';
import groupLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/group_labels.query.graphql';
import issueLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql';
+import mergeRequestLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql';
import projectLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql';
import getAlertAssignees from '~/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql';
import getIssueAssignees from '~/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql';
@@ -109,14 +113,30 @@ export const referenceQueries = {
},
};
-export const labelsQueries = {
+export const workspaceLabelsQueries = {
+ [WorkspaceType.project]: {
+ query: projectLabelsQuery,
+ },
+ [WorkspaceType.group]: {
+ query: groupLabelsQuery,
+ },
+};
+
+export const issuableLabelsQueries = {
[IssuableType.Issue]: {
issuableQuery: issueLabelsQuery,
- workspaceQuery: projectLabelsQuery,
+ mutation: updateIssueLabelsMutation,
+ mutationName: 'updateIssue',
+ },
+ [IssuableType.MergeRequest]: {
+ issuableQuery: mergeRequestLabelsQuery,
+ mutation: updateMergeRequestLabelsMutation,
+ mutationName: 'mergeRequestSetLabels',
},
[IssuableType.Epic]: {
issuableQuery: epicLabelsQuery,
- workspaceQuery: groupLabelsQuery,
+ mutation: updateEpicLabelsMutation,
+ mutationName: 'updateEpic',
},
};
diff --git a/app/assets/javascripts/sidebar/graphql.js b/app/assets/javascripts/sidebar/graphql.js
index 1a806a051b7..6a670db2d38 100644
--- a/app/assets/javascripts/sidebar/graphql.js
+++ b/app/assets/javascripts/sidebar/graphql.js
@@ -25,7 +25,6 @@ export const defaultClient = createDefaultClient(resolvers, {
cacheConfig: {
fragmentMatcher,
},
- assumeImmutableResults: true,
});
export const apolloProvider = new VueApollo({
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 9f5a2f4ebb0..898be4a97ce 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -260,6 +260,10 @@ export function mountSidebarLabels() {
variant: DropdownVariant.Sidebar,
canUpdate: parseBoolean(el.dataset.canEdit),
isClassicSidebar: true,
+ issuableType:
+ isInIssuePage() || isInIncidentPage() || isInDesignPage()
+ ? IssuableType.Issue
+ : IssuableType.MergeRequest,
},
render: (createElement) => createElement(SidebarLabels),
});
diff --git a/app/assets/javascripts/sidebar/queries/sidebarDetails.query.graphql b/app/assets/javascripts/sidebar/queries/sidebarDetails.query.graphql
index 2aff7da4605..dd85eb1631b 100644
--- a/app/assets/javascripts/sidebar/queries/sidebarDetails.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/sidebarDetails.query.graphql
@@ -1,4 +1,4 @@
-query($fullPath: ID!, $iid: String!) {
+query sidebarDetails($fullPath: ID!, $iid: String!) {
project(fullPath: $fullPath) {
issue(iid: $iid) {
iid
diff --git a/app/assets/javascripts/sidebar/queries/toggle_attention_requested.mutation.graphql b/app/assets/javascripts/sidebar/queries/toggle_attention_requested.mutation.graphql
new file mode 100644
index 00000000000..a9f4af6e1b9
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/toggle_attention_requested.mutation.graphql
@@ -0,0 +1,7 @@
+mutation mergeRequestToggleAttentionRequested($projectPath: ID!, $iid: String!, $userId: ID!) {
+ mergeRequestToggleAttentionRequested(
+ input: { projectPath: $projectPath, iid: $iid, userId: $userId }
+ ) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/sidebar/queries/updateStatus.mutation.graphql b/app/assets/javascripts/sidebar/queries/updateStatus.mutation.graphql
index 28a47735143..2c6f379744e 100644
--- a/app/assets/javascripts/sidebar/queries/updateStatus.mutation.graphql
+++ b/app/assets/javascripts/sidebar/queries/updateStatus.mutation.graphql
@@ -1,4 +1,4 @@
-mutation($projectPath: ID!, $iid: String!, $healthStatus: HealthStatus) {
+mutation updateIssueHealthStatus($projectPath: ID!, $iid: String!, $healthStatus: HealthStatus) {
updateIssue(input: { projectPath: $projectPath, iid: $iid, healthStatus: $healthStatus }) {
issuable: issue {
id
diff --git a/app/assets/javascripts/sidebar/queries/update_epic_confidential.mutation.graphql b/app/assets/javascripts/sidebar/queries/update_epic_confidential.mutation.graphql
index 69927ddd205..2d58843140f 100644
--- a/app/assets/javascripts/sidebar/queries/update_epic_confidential.mutation.graphql
+++ b/app/assets/javascripts/sidebar/queries/update_epic_confidential.mutation.graphql
@@ -1,4 +1,4 @@
-mutation updateEpic($input: UpdateEpicInput!) {
+mutation updateIssuableConfidential($input: UpdateEpicInput!) {
issuableSetConfidential: updateEpic(input: $input) {
issuable: epic {
id
diff --git a/app/assets/javascripts/sidebar/queries/update_epic_subscription.mutation.graphql b/app/assets/javascripts/sidebar/queries/update_epic_subscription.mutation.graphql
index af43766aed5..4a3090f3836 100644
--- a/app/assets/javascripts/sidebar/queries/update_epic_subscription.mutation.graphql
+++ b/app/assets/javascripts/sidebar/queries/update_epic_subscription.mutation.graphql
@@ -1,4 +1,4 @@
-mutation epicSetSubscription($fullPath: ID!, $iid: ID!, $subscribedState: Boolean!) {
+mutation boardEpicSetSubscription($fullPath: ID!, $iid: ID!, $subscribedState: Boolean!) {
updateIssuableSubscription: epicSetSubscription(
input: { groupPath: $fullPath, iid: $iid, subscribedState: $subscribedState }
) {
diff --git a/app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql b/app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql
index 317b48c142d..2e6bc8c36ba 100644
--- a/app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql
+++ b/app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql
@@ -1,4 +1,4 @@
-mutation updateEpic($input: UpdateEpicInput!) {
+mutation updateEpicTitle($input: UpdateEpicInput!) {
updateIssuableTitle: updateEpic(input: $input) {
epic {
title
diff --git a/app/assets/javascripts/sidebar/queries/update_issue_subscription.mutation.graphql b/app/assets/javascripts/sidebar/queries/update_issue_subscription.mutation.graphql
index 81891fb601f..e1a3927e7e1 100644
--- a/app/assets/javascripts/sidebar/queries/update_issue_subscription.mutation.graphql
+++ b/app/assets/javascripts/sidebar/queries/update_issue_subscription.mutation.graphql
@@ -1,4 +1,4 @@
-mutation issueSetSubscription($fullPath: ID!, $iid: String!, $subscribedState: Boolean!) {
+mutation projectIssueSetSubscription($fullPath: ID!, $iid: String!, $subscribedState: Boolean!) {
updateIssuableSubscription: issueSetSubscription(
input: { projectPath: $fullPath, iid: $iid, subscribedState: $subscribedState }
) {
diff --git a/app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql b/app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql
index 3c09daad793..016c31ea096 100644
--- a/app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql
+++ b/app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql
@@ -2,6 +2,7 @@ mutation mergeRequestSetLabels($input: MergeRequestSetLabelsInput!) {
mergeRequestSetLabels(input: $input) {
errors
mergeRequest {
+ id
labels {
nodes {
color
diff --git a/app/assets/javascripts/sidebar/services/sidebar_service.js b/app/assets/javascripts/sidebar/services/sidebar_service.js
index cea26acd101..d8ab8f1c65b 100644
--- a/app/assets/javascripts/sidebar/services/sidebar_service.js
+++ b/app/assets/javascripts/sidebar/services/sidebar_service.js
@@ -5,6 +5,7 @@ import createGqClient, { fetchPolicies } from '~/lib/graphql';
import axios from '~/lib/utils/axios_utils';
import reviewerRereviewMutation from '../queries/reviewer_rereview.mutation.graphql';
import sidebarDetailsMRQuery from '../queries/sidebarDetailsMR.query.graphql';
+import toggleAttentionRequestedMutation from '../queries/toggle_attention_requested.mutation.graphql';
const queries = {
merge_request: sidebarDetailsMRQuery,
@@ -90,4 +91,15 @@ export default class SidebarService {
},
});
}
+
+ toggleAttentionRequested(userId) {
+ return gqClient.mutate({
+ mutation: toggleAttentionRequestedMutation,
+ variables: {
+ userId: convertToGraphQLId(TYPE_USER, `${userId}`),
+ projectPath: this.fullPath,
+ iid: this.iid.toString(),
+ },
+ });
+ }
}
diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js
index 9144e3b08db..86580744ccc 100644
--- a/app/assets/javascripts/sidebar/sidebar_mediator.js
+++ b/app/assets/javascripts/sidebar/sidebar_mediator.js
@@ -1,6 +1,6 @@
import Store from 'ee_else_ce/sidebar/stores/sidebar_store';
import createFlash from '~/flash';
-import { __ } from '~/locale';
+import { __, sprintf } from '~/locale';
import toast from '~/vue_shared/plugins/global_toast';
import { visitUrl } from '../lib/utils/url_utility';
import Service from './services/sidebar_service';
@@ -56,13 +56,52 @@ export default class SidebarMediator {
return this.service
.requestReview(userId)
.then(() => {
- this.store.updateReviewer(userId);
+ this.store.updateReviewer(userId, 'reviewed');
toast(__('Requested review'));
callback(userId, true);
})
.catch(() => callback(userId, false));
}
+ async toggleAttentionRequested(type, { user, callback }) {
+ try {
+ const isReviewer = type === 'reviewer';
+ const reviewerOrAssignee = isReviewer
+ ? this.store.findReviewer(user)
+ : this.store.findAssignee(user);
+
+ await this.service.toggleAttentionRequested(user.id);
+
+ if (reviewerOrAssignee.attention_requested) {
+ toast(
+ sprintf(__('Removed attention request from @%{username}'), {
+ username: user.username,
+ }),
+ );
+ } else {
+ toast(sprintf(__('Requested attention from @%{username}'), { username: user.username }));
+ }
+
+ this.store.updateReviewer(user.id, 'attention_requested');
+ this.store.updateAssignee(user.id, 'attention_requested');
+
+ callback();
+ } catch (error) {
+ callback();
+ createFlash({
+ message: sprintf(__('Updating the attention request for %{username} failed.'), {
+ username: user.username,
+ }),
+ error,
+ captureError: true,
+ actionConfig: {
+ title: __('Try again'),
+ clickHandler: () => this.toggleAttentionRequired(type, { user, callback }),
+ },
+ });
+ }
+ }
+
setMoveToProjectId(projectId) {
this.store.setMoveToProjectId(projectId);
}
diff --git a/app/assets/javascripts/sidebar/stores/sidebar_store.js b/app/assets/javascripts/sidebar/stores/sidebar_store.js
index 94c54fc0980..5376791469e 100644
--- a/app/assets/javascripts/sidebar/stores/sidebar_store.js
+++ b/app/assets/javascripts/sidebar/stores/sidebar_store.js
@@ -82,11 +82,19 @@ export default class SidebarStore {
}
}
- updateReviewer(id) {
+ updateAssignee(id, stateKey) {
+ const assignee = this.findAssignee({ id });
+
+ if (assignee) {
+ assignee[stateKey] = !assignee[stateKey];
+ }
+ }
+
+ updateReviewer(id, stateKey) {
const reviewer = this.findReviewer({ id });
if (reviewer) {
- reviewer.reviewed = false;
+ reviewer[stateKey] = !reviewer[stateKey];
}
}
diff --git a/app/assets/javascripts/snippets/index.js b/app/assets/javascripts/snippets/index.js
index 8e7368ef804..21f38c4d8c9 100644
--- a/app/assets/javascripts/snippets/index.js
+++ b/app/assets/javascripts/snippets/index.js
@@ -18,7 +18,6 @@ export default function appFactory(el, Component) {
{},
{
batchMax: 1,
- assumeImmutableResults: true,
},
),
});
diff --git a/app/assets/javascripts/static_site_editor/graphql/index.js b/app/assets/javascripts/static_site_editor/graphql/index.js
index 2ae2baddbcc..53572e680e5 100644
--- a/app/assets/javascripts/static_site_editor/graphql/index.js
+++ b/app/assets/javascripts/static_site_editor/graphql/index.js
@@ -22,7 +22,6 @@ const createApolloProvider = (appData) => {
},
{
typeDefs,
- assumeImmutableResults: true,
},
);
diff --git a/app/assets/javascripts/static_site_editor/pages/success.vue b/app/assets/javascripts/static_site_editor/pages/success.vue
index 70e692a0c86..eb03aa3cca3 100644
--- a/app/assets/javascripts/static_site_editor/pages/success.vue
+++ b/app/assets/javascripts/static_site_editor/pages/success.vue
@@ -30,7 +30,7 @@ export default {
updatedFileDescription() {
const { sourcePath } = this.appData;
- return sprintf(s__('Update %{sourcePath} file'), { sourcePath });
+ return sprintf(__('Update %{sourcePath} file'), { sourcePath });
},
},
created() {
diff --git a/app/assets/javascripts/task_list.js b/app/assets/javascripts/task_list.js
index 93353b400e5..79a30340856 100644
--- a/app/assets/javascripts/task_list.js
+++ b/app/assets/javascripts/task_list.js
@@ -12,6 +12,7 @@ export default class TaskList {
this.lockVersion = options.lockVersion;
this.taskListContainerSelector = `${this.selector} .js-task-list-container`;
this.updateHandler = this.update.bind(this);
+ this.onUpdate = options.onUpdate || (() => {});
this.onSuccess = options.onSuccess || (() => {});
this.onError =
options.onError ||
@@ -96,6 +97,7 @@ export default class TaskList {
},
};
+ this.onUpdate();
this.disableTaskListItems(e);
return axios
diff --git a/app/assets/javascripts/terms/components/app.vue b/app/assets/javascripts/terms/components/app.vue
new file mode 100644
index 00000000000..aedf5b6acfe
--- /dev/null
+++ b/app/assets/javascripts/terms/components/app.vue
@@ -0,0 +1,117 @@
+<script>
+import $ from 'jquery';
+import { GlButton, GlIntersectionObserver, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+
+import { FLASH_TYPES, FLASH_CLOSED_EVENT } from '~/flash';
+import { isLoggedIn } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
+import csrf from '~/lib/utils/csrf';
+import '~/behaviors/markdown/render_gfm';
+
+export default {
+ name: 'TermsApp',
+ i18n: {
+ accept: __('Accept terms'),
+ continue: __('Continue'),
+ decline: __('Decline and sign out'),
+ },
+ flashElements: [],
+ csrf,
+ directives: {
+ SafeHtml,
+ },
+ components: { GlButton, GlIntersectionObserver },
+ inject: ['terms', 'permissions', 'paths'],
+ data() {
+ return {
+ acceptDisabled: true,
+ };
+ },
+ computed: {
+ isLoggedIn,
+ },
+ mounted() {
+ this.renderGFM();
+ this.setScrollableViewportHeight();
+
+ this.$options.flashElements = [
+ ...document.querySelectorAll(
+ Object.values(FLASH_TYPES)
+ .map((flashType) => `.flash-${flashType}`)
+ .join(','),
+ ),
+ ];
+
+ this.$options.flashElements.forEach((flashElement) => {
+ flashElement.addEventListener(FLASH_CLOSED_EVENT, this.handleFlashClose);
+ });
+ },
+ beforeDestroy() {
+ this.$options.flashElements.forEach((flashElement) => {
+ flashElement.removeEventListener(FLASH_CLOSED_EVENT, this.handleFlashClose);
+ });
+ },
+ methods: {
+ renderGFM() {
+ $(this.$refs.gfmContainer).renderGFM();
+ },
+ handleBottomReached() {
+ this.acceptDisabled = false;
+ },
+ setScrollableViewportHeight() {
+ // Reset `max-height` inline style
+ this.$refs.scrollableViewport.style.maxHeight = '';
+
+ const { scrollHeight, clientHeight } = document.documentElement;
+
+ // Set `max-height` to 100vh minus all elements that are NOT the scrollable viewport (header, footer, alerts, etc)
+ this.$refs.scrollableViewport.style.maxHeight = `calc(100vh - ${
+ scrollHeight - clientHeight
+ }px)`;
+ },
+ handleFlashClose(event) {
+ this.setScrollableViewportHeight();
+ event.target.removeEventListener(FLASH_CLOSED_EVENT, this.handleFlashClose);
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div class="gl-card-body gl-relative gl-pb-0 gl-px-0" data-qa-selector="terms_content">
+ <div
+ class="terms-fade gl-absolute gl-left-5 gl-right-5 gl-bottom-0 gl-h-11 gl-pointer-events-none"
+ ></div>
+ <div
+ ref="scrollableViewport"
+ data-testid="scrollable-viewport"
+ class="gl-h-100vh gl-overflow-y-auto gl-pb-11 gl-px-5"
+ >
+ <div ref="gfmContainer" v-safe-html="terms"></div>
+ <gl-intersection-observer @appear="handleBottomReached">
+ <div></div>
+ </gl-intersection-observer>
+ </div>
+ </div>
+ <div v-if="isLoggedIn" class="gl-card-footer gl-display-flex gl-justify-content-end">
+ <form v-if="permissions.canDecline" method="post" :action="paths.decline">
+ <gl-button type="submit">{{ $options.i18n.decline }}</gl-button>
+ <input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
+ </form>
+ <form v-if="permissions.canAccept" class="gl-ml-3" method="post" :action="paths.accept">
+ <gl-button
+ type="submit"
+ variant="confirm"
+ :disabled="acceptDisabled"
+ data-qa-selector="accept_terms_button"
+ >{{ $options.i18n.accept }}</gl-button
+ >
+ <input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
+ </form>
+ <gl-button v-else class="gl-ml-3" :href="paths.root" variant="confirm">{{
+ $options.i18n.continue
+ }}</gl-button>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/terms/index.js b/app/assets/javascripts/terms/index.js
new file mode 100644
index 00000000000..9d60fdfb50a
--- /dev/null
+++ b/app/assets/javascripts/terms/index.js
@@ -0,0 +1,23 @@
+import Vue from 'vue';
+
+import TermsApp from 'jh_else_ce/terms/components/app.vue';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+
+export const initTermsApp = () => {
+ const el = document.getElementById('js-terms-of-service');
+
+ if (!el) return false;
+
+ const { terms, permissions, paths } = convertObjectPropsToCamelCase(
+ JSON.parse(el.dataset.termsData),
+ { deep: true },
+ );
+
+ return new Vue({
+ el,
+ provide: { terms, permissions, paths },
+ render(createElement) {
+ return createElement(TermsApp);
+ },
+ });
+};
diff --git a/app/assets/javascripts/token_access/index.js b/app/assets/javascripts/token_access/index.js
index 8d29a65d705..6a29883290a 100644
--- a/app/assets/javascripts/token_access/index.js
+++ b/app/assets/javascripts/token_access/index.js
@@ -6,7 +6,7 @@ import TokenAccess from './components/token_access.vue';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
export const initTokenAccess = (containerId = 'js-ci-token-access-app') => {
diff --git a/app/assets/javascripts/user_lists/components/user_lists_table.vue b/app/assets/javascripts/user_lists/components/user_lists_table.vue
index 765f59228a6..ccc2bfabb56 100644
--- a/app/assets/javascripts/user_lists/components/user_lists_table.vue
+++ b/app/assets/javascripts/user_lists/components/user_lists_table.vue
@@ -23,7 +23,7 @@ export default {
translations: {
createdTimeagoLabel: s__('UserList|created %{timeago}'),
deleteListTitle: s__('UserList|Delete %{name}?'),
- deleteListMessage: s__('User list %{name} will be removed. Are you sure?'),
+ deleteListMessage: __('User list %{name} will be removed. Are you sure?'),
editUserListLabel: s__('FeatureFlags|Edit User List'),
},
modal: {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue b/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue
new file mode 100644
index 00000000000..492e68b636f
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue
@@ -0,0 +1,77 @@
+<script>
+import { GlSprintf } from '@gitlab/ui';
+import { escape } from 'lodash';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { n__, s__ } from '~/locale';
+
+const mergeCommitCount = s__('mrWidgetCommitsAdded|1 merge commit');
+
+export default {
+ components: {
+ GlSprintf,
+ },
+ mixins: [glFeatureFlagMixin()],
+ props: {
+ isSquashEnabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isFastForwardEnabled: {
+ type: Boolean,
+ required: true,
+ },
+ commitsCount: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ targetBranch: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ targetBranchEscaped() {
+ return escape(this.targetBranch);
+ },
+ commitsCountMessage() {
+ return n__('%d commit', '%d commits', this.isSquashEnabled ? 1 : this.commitsCount);
+ },
+ message() {
+ return this.isFastForwardEnabled
+ ? s__('mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}.')
+ : s__(
+ 'mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}.',
+ );
+ },
+ textDecorativeComponent() {
+ return this.glFeatures.restructuredMrWidget ? 'span' : 'strong';
+ },
+ },
+ mergeCommitCount,
+};
+</script>
+
+<template>
+ <span>
+ <gl-sprintf :message="message">
+ <template #commitCount>
+ <component :is="textDecorativeComponent" class="commits-count-message">{{
+ commitsCountMessage
+ }}</component>
+ </template>
+ <template #mergeCommitCount>
+ <component :is="textDecorativeComponent">{{ $options.mergeCommitCount }}</component>
+ </template>
+ <template #targetBranch>
+ <span class="label-branch">{{ targetBranchEscaped }}</span>
+ </template>
+ <template #squashedCommits>
+ <template v-if="glFeatures.restructuredMrWidget && isSquashEnabled">
+ {{ n__('(squashes %d commit)', '(squashes %d commits)', commitsCount) }}</template
+ ></template
+ >
+ </gl-sprintf>
+ </span>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue
index 0c4a5ee35d9..25dbb614c1d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue
@@ -1,7 +1,11 @@
<script>
import { toNounSeriesText } from '~/lib/utils/grammar';
import { n__, sprintf } from '~/locale';
-import { APPROVED_MESSAGE } from '~/vue_merge_request_widget/components/approvals/messages';
+import {
+ APPROVED_BY_YOU_AND_OTHERS,
+ APPROVED_BY_YOU,
+ APPROVED_BY_OTHERS,
+} from '~/vue_merge_request_widget/components/approvals/messages';
import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
export default {
@@ -29,12 +33,23 @@ export default {
},
},
computed: {
- message() {
- if (this.approved) {
- return APPROVED_MESSAGE;
+ approvalLeftMessage() {
+ if (this.rulesLeft.length) {
+ return sprintf(
+ n__(
+ 'Requires %{count} approval from %{names}.',
+ 'Requires %{count} approvals from %{names}.',
+ this.approvalsLeft,
+ ),
+ {
+ names: toNounSeriesText(this.rulesLeft),
+ count: this.approvalsLeft,
+ },
+ false,
+ );
}
- if (!this.rulesLeft.length) {
+ if (!this.approved) {
return n__(
'Requires %d approval from eligible users.',
'Requires %d approvals from eligible users.',
@@ -42,32 +57,51 @@ export default {
);
}
- return sprintf(
- n__(
- 'Requires %{count} approval from %{names}.',
- 'Requires %{count} approvals from %{names}.',
- this.approvalsLeft,
- ),
- {
- names: toNounSeriesText(this.rulesLeft),
- count: this.approvalsLeft,
- },
- false,
- );
+ return '';
+ },
+ message() {
+ if (this.approvedByMe && this.approvedByOthers) {
+ return APPROVED_BY_YOU_AND_OTHERS;
+ }
+
+ if (this.approvedByMe) {
+ return APPROVED_BY_YOU;
+ }
+
+ if (this.approved) {
+ return APPROVED_BY_OTHERS;
+ }
+
+ return '';
},
hasApprovers() {
return Boolean(this.approvers.length);
},
+ approvedByMe() {
+ if (!this.currentUserId) {
+ return false;
+ }
+ return this.approvers.some((approver) => approver.id === this.currentUserId);
+ },
+ approvedByOthers() {
+ if (!this.currentUserId) {
+ return false;
+ }
+ return this.approvers.some((approver) => approver.id !== this.currentUserId);
+ },
+ currentUserId() {
+ return gon.current_user_id;
+ },
},
- APPROVED_MESSAGE,
};
</script>
<template>
<div data-qa-selector="approvals_summary_content">
- <strong>{{ message }}</strong>
+ <strong>{{ approvalLeftMessage }}</strong>
<template v-if="hasApprovers">
- <span>{{ s__('mrWidget|Approved by') }}</span>
+ <span v-if="approvalLeftMessage">{{ message }}</span>
+ <strong v-else>{{ message }}</strong>
<user-avatar-list class="d-inline-block align-middle" :items="approvers" />
</template>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/messages.js b/app/assets/javascripts/vue_merge_request_widget/components/approvals/messages.js
index 0538c38307b..fbdefa95630 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/messages.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/messages.js
@@ -6,4 +6,6 @@ export const FETCH_ERROR = s__(
);
export const APPROVE_ERROR = s__('mrWidget|An error occurred while submitting your approval.');
export const UNAPPROVE_ERROR = s__('mrWidget|An error occurred while removing your approval.');
-export const APPROVED_MESSAGE = s__('mrWidget|Merge request approved.');
+export const APPROVED_BY_YOU_AND_OTHERS = s__('mrWidget|Approved by you and others');
+export const APPROVED_BY_YOU = s__('mrWidget|Approved by you');
+export const APPROVED_BY_OTHERS = s__('mrWidget|Approved by');
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue
index cbace1ad57c..f4f611dfd1b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue
@@ -12,13 +12,12 @@ import {
CANCELED,
SKIPPED,
} from './constants';
-import MemoryUsage from './memory_usage.vue';
export default {
name: 'DeploymentInfo',
components: {
GlLink,
- MemoryUsage,
+ MemoryUsage: () => import('./memory_usage.vue'),
TooltipOnTruncate,
},
directives: {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_list.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_list.vue
index d3384903cce..655acf28253 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_list.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_list.vue
@@ -2,10 +2,11 @@
import { GlSprintf } from '@gitlab/ui';
import { n__ } from '~/locale';
import MrCollapsibleExtension from '../mr_collapsible_extension.vue';
+import Deployment from './deployment.vue';
export default {
components: {
- Deployment: () => import('./deployment.vue'),
+ Deployment,
GlSprintf,
MrCollapsibleExtension,
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue
index 023367a794e..33a83aef057 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue
@@ -24,13 +24,20 @@ export default {
return sprintf(__('%{widget} options'), { widget: this.widget });
},
},
+ methods: {
+ onClickAction(action) {
+ if (action.onClick) {
+ action.onClick();
+ }
+ },
+ },
};
</script>
<template>
<div>
<gl-dropdown
- v-if="tertiaryButtons"
+ v-if="tertiaryButtons.length"
:text="dropdownLabel"
icon="ellipsis_v"
no-caret
@@ -47,6 +54,7 @@ export default {
:key="index"
:href="btn.href"
:target="btn.target"
+ @click="onClickAction(btn)"
>
{{ btn.text }}
</gl-dropdown-item>
@@ -57,11 +65,12 @@ export default {
:key="index"
:href="btn.href"
:target="btn.target"
- :class="{ 'gl-mr-3': index > 1 }"
+ :class="{ 'gl-mr-3': index !== tertiaryButtons.length - 1 }"
category="tertiary"
variant="confirm"
size="small"
- class="gl-display-none gl-md-display-block"
+ class="gl-display-none gl-md-display-block gl-float-left"
+ @click="onClickAction(btn)"
>
{{ btn.text }}
</gl-button>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
index 298f7c7ad8c..6f10f788952 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
@@ -8,6 +8,8 @@ import {
GlTooltipDirective,
GlIntersectionObserver,
} from '@gitlab/ui';
+import { once } from 'lodash';
+import api from '~/api';
import { sprintf, s__, __ } from '~/locale';
import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
import { EXTENSION_ICON_CLASS } from '../../constants';
@@ -102,8 +104,15 @@ export default {
});
},
methods: {
+ triggerRedisTracking: once(function triggerRedisTracking() {
+ if (this.$options.expandEvent) {
+ api.trackRedisHllUserEvent(this.$options.expandEvent);
+ }
+ }),
toggleCollapsed() {
this.isCollapsed = !this.isCollapsed;
+
+ this.triggerRedisTracking();
},
loadAllData() {
if (this.fullData) return;
@@ -143,7 +152,10 @@ export default {
:is-loading="isLoadingSummary"
:icon-name="statusIconName"
/>
- <div class="media-body gl-display-flex gl-flex-direction-row!">
+ <div
+ class="media-body gl-display-flex gl-flex-direction-row!"
+ data-testid="widget-extension-top-level"
+ >
<div class="gl-flex-grow-1">
<template v-if="isLoadingSummary">{{ widgetLoadingText }}</template>
<div v-else v-safe-html="summary(collapsedData)"></div>
@@ -194,20 +206,28 @@ export default {
class="gl-display-flex gl-align-items-center gl-py-3 gl-pl-7"
data-testid="extension-list-item"
>
- <status-icon v-if="data.icon" :icon-name="data.icon.name" :size="12" />
+ <status-icon v-if="data.icon" :icon-name="data.icon.name" :size="12" class="gl-pl-0" />
<gl-intersection-observer
:options="{ rootMargin: '100px', thresholds: 0.1 }"
- class="gl-flex-wrap gl-align-self-center gl-display-flex"
+ class="gl-flex-wrap gl-display-flex gl-w-full"
@appear="appear(index)"
@disappear="disappear(index)"
>
- <div v-safe-html="data.text" class="gl-mr-4"></div>
+ <div
+ v-safe-html="data.text"
+ class="gl-mr-4 gl-display-flex gl-align-items-center"
+ ></div>
<div v-if="data.link">
<gl-link :href="data.link.href">{{ data.link.text }}</gl-link>
</div>
<gl-badge v-if="data.badge" :variant="data.badge.variant || 'info'">
{{ data.badge.text }}
</gl-badge>
+ <actions
+ :widget="$options.label || $options.name"
+ :tertiary-buttons="data.actions"
+ class="gl-ml-auto"
+ />
</gl-intersection-observer>
</li>
</smart-virtual-list>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js b/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js
index 4ca0b660696..ec6e6ed2620 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js
@@ -12,6 +12,7 @@ export const registerExtension = (extension) => {
name: extension.name,
props: extension.props,
i18n: extension.i18n,
+ expandEvent: extension.expandEvent,
computed: {
...Object.keys(extension.computed).reduce(
(acc, computedKey) => ({
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
index 5c67b9c7ab5..9070cb1fe65 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
@@ -151,7 +151,7 @@ export default {
right
data-qa-selector="download_dropdown"
>
- <gl-dropdown-section-header>{{ s__('Download as') }}</gl-dropdown-section-header>
+ <gl-dropdown-section-header>{{ __('Download as') }}</gl-dropdown-section-header>
<gl-dropdown-item
:href="mr.emailPatchesPath"
class="js-download-email-patches"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
index 9bb955c534f..f7c952f9ef6 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
@@ -101,6 +101,9 @@ export default {
? this.pipeline.details.status
: {};
},
+ artifacts() {
+ return this.pipeline?.details?.artifacts;
+ },
hasStages() {
return this.pipeline?.details?.stages?.length > 0;
},
@@ -285,7 +288,7 @@ export default {
/>
</span>
<linked-pipelines-mini-list v-if="triggered.length" :triggered="triggered" />
- <pipeline-artifacts :pipeline-id="pipeline.id" class="gl-ml-3" />
+ <pipeline-artifacts :pipeline-id="pipeline.id" :artifacts="artifacts" class="gl-ml-3" />
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
index 306026072a3..c314261d3f5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
@@ -1,8 +1,10 @@
<script>
import { s__, n__ } from '~/locale';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'MRWidgetRelatedLinks',
+ mixins: [glFeatureFlagMixin()],
props: {
relatedLinks: {
type: Object,
@@ -14,6 +16,11 @@ export default {
required: false,
default: '',
},
+ showAssignToMe: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
computed: {
closesText() {
@@ -30,16 +37,25 @@ export default {
};
</script>
<template>
- <section class="mr-info-list gl-ml-7 gl-pb-5">
- <p v-if="relatedLinks.closing">
+ <section>
+ <p
+ v-if="relatedLinks.closing"
+ :class="{ 'gl-display-line gl-m-0': glFeatures.restructuredMrWidget }"
+ >
{{ closesText }}
<span v-html="relatedLinks.closing /* eslint-disable-line vue/no-v-html */"></span>
</p>
- <p v-if="relatedLinks.mentioned">
+ <p
+ v-if="relatedLinks.mentioned"
+ :class="{ 'gl-display-line gl-m-0': glFeatures.restructuredMrWidget }"
+ >
{{ n__('mrWidget|Mentions issue', 'mrWidget|Mentions issues', relatedLinks.mentionedCount) }}
<span v-html="relatedLinks.mentioned /* eslint-disable-line vue/no-v-html */"></span>
</p>
- <p v-if="relatedLinks.assignToMe">
+ <p
+ v-if="relatedLinks.assignToMe && showAssignToMe"
+ :class="{ 'gl-display-line gl-m-0': glFeatures.restructuredMrWidget }"
+ >
<span v-html="relatedLinks.assignToMe /* eslint-disable-line vue/no-v-html */"></span>
</p>
</section>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue
index f3673005c45..cd5b7c3110d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue
@@ -4,9 +4,7 @@ import Tracking from '~/tracking';
import DismissibleContainer from '~/vue_shared/components/dismissible_container.vue';
import {
SP_TRACK_LABEL,
- SP_LINK_TRACK_EVENT,
SP_SHOW_TRACK_EVENT,
- SP_LINK_TRACK_VALUE,
SP_SHOW_TRACK_VALUE,
SP_HELP_CONTENT,
SP_HELP_URL,
@@ -20,9 +18,7 @@ export default {
name: 'MRWidgetSuggestPipeline',
SP_ICON_NAME,
SP_TRACK_LABEL,
- SP_LINK_TRACK_EVENT,
SP_SHOW_TRACK_EVENT,
- SP_LINK_TRACK_VALUE,
SP_SHOW_TRACK_VALUE,
SP_HELP_CONTENT,
SP_HELP_URL,
@@ -81,29 +77,14 @@ export default {
<div>
<gl-sprintf
:message="
- s__(`mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd}
- %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd}
- to create one.`)
+ s__(`mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}`)
"
>
- <template #prefixToLink="{ content }">
+ <template #boldHeader="{ content }">
<strong>
{{ content }}
</strong>
</template>
- <template #addPipelineLink="{ content }">
- <gl-link
- :href="pipelinePath"
- class="gl-ml-1"
- data-testid="add-pipeline-link"
- :data-track-property="humanAccess"
- :data-track-value="$options.SP_LINK_TRACK_VALUE"
- :data-track-action="$options.SP_LINK_TRACK_EVENT"
- :data-track-label="$options.SP_TRACK_LABEL"
- >
- {{ content }}
- </gl-link>
- </template>
</gl-sprintf>
</div>
</template>
@@ -115,9 +96,6 @@ export default {
</div>
<div class="col-md-7 order-md-first col-12">
<div class="ml-6 gl-pt-5">
- <strong>
- {{ s__('mrWidget|Are you adding technical debt or code vulnerabilities?') }}
- </strong>
<p class="gl-mt-2">
<gl-sprintf :message="$options.SP_HELP_CONTENT">
<template #link="{ content }">
@@ -142,7 +120,7 @@ export default {
:data-track-action="$options.SP_SHOW_TRACK_EVENT"
:data-track-label="$options.SP_TRACK_LABEL"
>
- {{ __('Show me how to add a pipeline') }}
+ {{ __('Try out GitLab Pipelines') }}
</gl-button>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
index 9268e426954..caafd6b995e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
@@ -4,7 +4,7 @@ import { __ } from '../../locale';
export default {
i18n: {
- removesBranchText: __('The source branch will be deleted'),
+ removesBranchText: __('Deletes the source branch'),
tooltipTitle: __('A user with write access to the source branch selected this option'),
},
components: {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
index 44bdc4a3be8..3eda2828e97 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
@@ -1,5 +1,8 @@
<script>
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+
export default {
+ mixins: [glFeatureFlagMixin()],
props: {
value: {
type: String,
@@ -20,7 +23,10 @@ export default {
<template>
<li>
<div class="commit-message-editor">
- <div class="d-flex flex-wrap align-items-center justify-content-between">
+ <div
+ :class="{ 'gl-mb-3': glFeatures.restructuredMrWidget }"
+ class="d-flex flex-wrap align-items-center justify-content-between"
+ >
<label class="col-form-label" :for="inputId">
<strong>{{ label }}</strong>
</label>
@@ -35,7 +41,7 @@ export default {
rows="7"
@input="$emit('input', $event.target.value)"
></textarea>
- <slot name="checkbox"></slot>
+ <slot name="text-muted"></slot>
</div>
</li>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
index 3ca193514f1..5c4a526bcc3 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue
@@ -1,15 +1,12 @@
<script>
-import { GlButton, GlSprintf } from '@gitlab/ui';
-import { escape } from 'lodash';
-import { __, n__, s__ } from '~/locale';
-
-const mergeCommitCount = s__('mrWidgetCommitsAdded|1 merge commit');
+import { GlButton } from '@gitlab/ui';
+import { __ } from '~/locale';
+import AddedCommitMessage from '../added_commit_message.vue';
export default {
- mergeCommitCount,
components: {
GlButton,
- GlSprintf,
+ AddedCommitMessage,
},
props: {
isSquashEnabled: {
@@ -39,9 +36,6 @@ export default {
collapseIcon() {
return this.expanded ? 'chevron-down' : 'chevron-right';
},
- commitsCountMessage() {
- return n__('%d commit', '%d commits', this.isSquashEnabled ? 1 : this.commitsCount);
- },
modifyLinkMessage() {
if (this.isFastForwardEnabled) return __('Modify commit message');
else if (this.isSquashEnabled) return __('Modify commit messages');
@@ -50,16 +44,6 @@ export default {
ariaLabel() {
return this.expanded ? __('Collapse') : __('Expand');
},
- targetBranchEscaped() {
- return escape(this.targetBranch);
- },
- message() {
- return this.isFastForwardEnabled
- ? s__('mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}.')
- : s__(
- 'mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}.',
- );
- },
},
methods: {
toggle() {
@@ -86,17 +70,12 @@ export default {
<span v-if="expanded">{{ __('Collapse') }}</span>
<span v-else>
<span class="vertical-align-middle">
- <gl-sprintf :message="message">
- <template #commitCount>
- <strong class="commits-count-message">{{ commitsCountMessage }}</strong>
- </template>
- <template #mergeCommitCount>
- <strong>{{ $options.mergeCommitCount }}</strong>
- </template>
- <template #targetBranch>
- <span class="label-branch">{{ targetBranchEscaped }}</span>
- </template>
- </gl-sprintf>
+ <added-commit-message
+ :is-squash-enabled="isSquashEnabled"
+ :is-fast-forward-enabled="isFastForwardEnabled"
+ :commits-count="commitsCount"
+ :target-branch="targetBranch"
+ />
</span>
<gl-button variant="link" class="modify-message-button">
{{ modifyLinkMessage }}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
index 0eb173edbcb..a44caf886a4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
@@ -177,10 +177,10 @@ export default {
</h4>
<section class="mr-info-list">
<p v-if="shouldRemoveSourceBranch">
- {{ s__('mrWidget|The source branch will be deleted') }}
+ {{ s__('mrWidget|Deletes the source branch') }}
</p>
<p v-else class="gl-display-flex">
- <span class="gl-mr-3">{{ s__('mrWidget|The source branch will not be deleted') }}</span>
+ <span class="gl-mr-3">{{ s__('mrWidget|Does not delete the source branch') }}</span>
<gl-button
v-if="canRemoveSourceBranch"
:loading="isRemovingSourceBranch"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue
index e02be6dc2f7..10b93d7849f 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue
@@ -1,4 +1,5 @@
<script>
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import statusIcon from '../mr_widget_status_icon.vue';
export default {
@@ -6,11 +7,12 @@ export default {
components: {
statusIcon,
},
+ mixins: [glFeatureFlagMixin()],
};
</script>
<template>
<div class="mr-widget-body media">
- <status-icon :show-disabled-button="true" status="loading" />
+ <status-icon :show-disabled-button="!glFeatures.restructuredMrWidget" status="loading" />
<div class="media-body space-children">
<span class="bold"> {{ s__('mrWidget|Checking if merge request can be merged…') }} </span>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
index a1759b1a815..84dac95ce74 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
@@ -1,6 +1,7 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
import { GlLoadingIcon, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import api from '~/api';
import createFlash from '~/flash';
import { s__, __ } from '~/locale';
import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '~/projects/commit/constants';
@@ -83,6 +84,8 @@ export default {
removeSourceBranch() {
this.isMakingRequest = true;
+ api.trackRedisHllUserEvent('i_code_review_post_merge_delete_branch');
+
this.service
.removeSourceBranch()
.then((res) => res.data)
@@ -103,9 +106,13 @@ export default {
});
},
openRevertModal() {
+ api.trackRedisHllUserEvent('i_code_review_post_merge_click_revert');
+
modalEventHub.$emit(OPEN_REVERT_MODAL);
},
openCherryPickModal() {
+ api.trackRedisHllUserEvent('i_code_review_post_merge_click_cherry_pick');
+
modalEventHub.$emit(OPEN_CHERRY_PICK_MODAL);
},
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
index 1c245b584ea..247877a8235 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
@@ -32,7 +32,7 @@ export default {
</h4>
<section class="mr-info-list">
<p>
- {{ s__('mrWidget|The changes will be merged into') }}
+ {{ s__('mrWidget|Merges changes into') }}
<span class="label-branch">
<a :href="mr.targetBranchPath">{{ mr.targetBranch }}</a>
</span>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
index 1976d3639a6..9f2870d8d69 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
@@ -1,8 +1,7 @@
<script>
import { GlButton, GlSkeletonLoader } from '@gitlab/ui';
-import { escape } from 'lodash';
import createFlash from '~/flash';
-import { __, sprintf } from '~/locale';
+import { __ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import simplePoll from '../../../lib/utils/simple_poll';
import eventHub from '../../event_hub';
@@ -85,13 +84,7 @@ export default {
return ['failed', 'loading'].includes(this.status);
},
fastForwardMergeText() {
- return sprintf(
- __('Merge blocked: the source branch must be rebased onto the target branch.'),
- {
- targetBranch: `<span class="label-branch">${escape(this.targetBranch)}</span>`,
- },
- false,
- );
+ return __('Merge blocked: the source branch must be rebased onto the target branch.');
},
},
methods: {
@@ -170,8 +163,8 @@ export default {
v-if="!rebaseInProgress && !canPushToSourceBranch"
class="gl-font-weight-bold gl-ml-0!"
data-testid="rebase-message"
- v-html="fastForwardMergeText /* eslint-disable-line vue/no-v-html */"
- ></span>
+ >{{ fastForwardMergeText }}</span
+ >
<div
v-if="!rebaseInProgress && canPushToSourceBranch && !isMakingRequest"
class="accept-merge-holder clearfix js-toggle-container accept-action media space-children"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/new_ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/new_ready_to_merge.vue
index 9a7743348ff..0b6aa104181 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/new_ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/new_ready_to_merge.vue
@@ -37,7 +37,7 @@ export default {
<template>
<div class="mr-widget-body media">
<status-icon status="success" />
- <p class="media-body gl-m-0! gl-font-weight-bold">
+ <p class="media-body gl-m-0! gl-font-weight-bold gl-text-gray-900!">
<template v-if="canMerge">
{{ __('Ready to merge!') }}
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
index 7827c79cd31..2d704d3b07a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
@@ -1,6 +1,7 @@
<script>
import { GlButton, GlSprintf, GlLink, GlSafeHtmlDirective } from '@gitlab/ui';
import emptyStateSVG from 'icons/_mr_widget_empty_state.svg';
+import api from '~/api';
import { helpPagePath } from '~/helpers/help_page_helper';
export default {
@@ -22,6 +23,11 @@ export default {
data() {
return { emptyStateSVG };
},
+ methods: {
+ onClickNewFile() {
+ api.trackRedisHllUserEvent('i_code_review_widget_nothing_merge_click_new_file');
+ },
+ },
ciHelpPage: helpPagePath('/ci/quick_start/index.html'),
safeHtmlConfig: { ADD_TAGS: ['use'] },
};
@@ -59,6 +65,7 @@ export default {
category="secondary"
variant="success"
data-testid="createFileButton"
+ @click="onClickNewFile"
>
{{ __('Create file') }}
</gl-button>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
index 7d4bd4cf1bf..d2cc99302a9 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
@@ -18,9 +18,10 @@ import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests
import createFlash from '~/flash';
import { secondsToMilliseconds } from '~/lib/utils/datetime_utility';
import simplePoll from '~/lib/utils/simple_poll';
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
import SmartInterval from '~/smart_interval';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { helpPagePath } from '~/helpers/help_page_helper';
import MergeRequest from '../../../merge_request';
import {
AUTO_MERGE_STRATEGIES,
@@ -35,6 +36,8 @@ import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import MergeRequestStore from '../../stores/mr_widget_store';
import statusIcon from '../mr_widget_status_icon.vue';
+import AddedCommitMessage from '../added_commit_message.vue';
+import RelatedLinks from '../mr_widget_related_links.vue';
import CommitEdit from './commit_edit.vue';
import CommitMessageDropdown from './commit_message_dropdown.vue';
import CommitsHeader from './commits_header.vue';
@@ -113,6 +116,8 @@ export default {
import(
'ee_component/vue_merge_request_widget/components/merge_train_failed_pipeline_confirmation_dialog.vue'
),
+ AddedCommitMessage,
+ RelatedLinks,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -134,6 +139,7 @@ export default {
isSquashReadOnly: this.mr.squashIsReadonly,
squashCommitMessage: this.mr.squashCommitMessage,
isPipelineFailedModalVisible: false,
+ editCommitMessage: false,
};
},
computed: {
@@ -162,7 +168,7 @@ export default {
},
isMergeAllowed() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
- return this.state.mergeable || false;
+ return this.state.mergeable;
}
return this.mr.isMergeAllowed;
@@ -174,6 +180,11 @@ export default {
return this.mr.canRemoveSourceBranch;
},
+ commitTemplateHelpPage() {
+ return helpPagePath('user/project/merge_requests/commit_templates.md', {
+ anchor: 'merge-commit-message-template',
+ });
+ },
commits() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.state.commitsWithoutMergeCommits.nodes;
@@ -279,6 +290,10 @@ export default {
return enableSquashBeforeMerge && this.commitsCount > 1;
},
shouldShowMergeControls() {
+ if (this.glFeatures.restructuredMrWidget) {
+ return this.restructuredWidgetShowMergeButtons;
+ }
+
return this.isMergeAllowed || this.isAutoMergeAvailable;
},
shouldShowSquashEdit() {
@@ -297,15 +312,26 @@ export default {
showDangerMessageForMergeTrain() {
return this.preferredAutoMergeStrategy === MT_MERGE_STRATEGY && this.isPipelineFailed;
},
+ restructuredWidgetShowMergeButtons() {
+ if (this.glFeatures.restructuredMrWidget) {
+ return this.isMergeAllowed && this.state.userPermissions.canMerge;
+ }
+
+ return true;
+ },
},
mounted() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
eventHub.$on('ApprovalUpdated', this.updateGraphqlState);
+ eventHub.$on('MRWidgetUpdateRequested', this.updateGraphqlState);
+ eventHub.$on('mr.discussion.updated', this.updateGraphqlState);
}
},
beforeDestroy() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
eventHub.$off('ApprovalUpdated', this.updateGraphqlState);
+ eventHub.$off('MRWidgetUpdateRequested', this.updateGraphqlState);
+ eventHub.$off('mr.discussion.updated', this.updateGraphqlState);
}
if (this.pollingInterval) {
@@ -327,15 +353,6 @@ export default {
updateGraphqlState() {
return this.$apollo.queries.state.refetch();
},
- updateMergeCommitMessage(includeDescription) {
- const commitMessage = this.glFeatures.mergeRequestWidgetGraphql
- ? this.state.defaultMergeCommitMessage
- : this.mr.commitMessage;
- const commitMessageWithDescription = this.glFeatures.mergeRequestWidgetGraphql
- ? this.state.defaultMergeCommitMessageWithDescription
- : this.mr.commitMessageWithDescription;
- this.commitMessage = includeDescription ? commitMessageWithDescription : commitMessage;
- },
handleMergeButtonClick(useAutoMerge, mergeImmediately = false, confirmationClicked = false) {
if (this.showFailedPipelineModal && !confirmationClicked) {
this.isPipelineFailedModalVisible = true;
@@ -488,11 +505,21 @@ export default {
});
},
},
+ i18n: {
+ mergeCommitTemplateHintText: s__(
+ 'mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}',
+ ),
+ },
};
</script>
<template>
- <div>
+ <div
+ :class="{
+ 'gl-border-t-1 gl-border-t-solid gl-border-gray-100 gl-bg-gray-10 gl-pl-7':
+ glFeatures.restructuredMrWidget,
+ }"
+ >
<div v-if="loading" class="mr-widget-body">
<div class="gl-w-full mr-ready-to-merge-loader">
<gl-skeleton-loader :width="418" :height="30">
@@ -504,11 +531,16 @@ export default {
</div>
</div>
<template v-else>
- <div class="mr-widget-body media">
- <status-icon :status="iconClass" />
+ <div
+ class="mr-widget-body media"
+ :class="{
+ 'mr-widget-body-line-height-1': glFeatures.restructuredMrWidget,
+ }"
+ >
+ <status-icon v-if="!glFeatures.restructuredMrWidget" :status="iconClass" />
<div class="media-body">
- <div class="mr-widget-body-controls gl-display-flex gl-align-items-center">
- <gl-button-group class="gl-align-self-start">
+ <div class="mr-widget-body-controls gl-display-flex gl-align-items-center gl-flex-wrap">
+ <gl-button-group v-if="restructuredWidgetShowMergeButtons" class="gl-align-self-start">
<gl-button
size="medium"
category="primary"
@@ -555,14 +587,27 @@ export default {
</gl-button-group>
<div
v-if="shouldShowMergeControls"
+ :class="{ 'gl-w-full gl-order-n1 gl-mb-5': glFeatures.restructuredMrWidget }"
class="gl-display-flex gl-align-items-center gl-flex-wrap"
>
+ <merge-train-helper-icon
+ v-if="shouldRenderMergeTrainHelperIcon"
+ :merge-train-when-pipeline-succeeds-docs-path="
+ mr.mergeTrainWhenPipelineSucceedsDocsPath
+ "
+ class="gl-mx-3"
+ />
+
<gl-form-checkbox
v-if="canRemoveSourceBranch"
id="remove-source-branch-input"
v-model="removeSourceBranch"
:disabled="isRemoveSourceBranchButtonDisabled"
- class="js-remove-source-branch-checkbox gl-mx-3 gl-display-flex gl-align-items-center"
+ :class="{
+ 'gl-mx-3': !glFeatures.restructuredMrWidget,
+ 'gl-mr-5': glFeatures.restructuredMrWidget,
+ }"
+ class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center"
>
{{ __('Delete source branch') }}
</gl-form-checkbox>
@@ -573,38 +618,146 @@ export default {
v-model="squashBeforeMerge"
:help-path="mr.squashBeforeMergeHelpPath"
:is-disabled="isSquashReadOnly"
- class="gl-mx-3"
+ :class="{
+ 'gl-mx-3': !glFeatures.restructuredMrWidget,
+ 'gl-mr-5': glFeatures.restructuredMrWidget,
+ }"
/>
- <merge-train-helper-icon
- v-if="shouldRenderMergeTrainHelperIcon"
- :merge-train-when-pipeline-succeeds-docs-path="
- mr.mergeTrainWhenPipelineSucceedsDocsPath
+ <gl-form-checkbox
+ v-if="
+ glFeatures.restructuredMrWidget && (shouldShowSquashEdit || shouldShowMergeEdit)
"
- />
+ v-model="editCommitMessage"
+ class="gl-display-flex gl-align-items-center"
+ >
+ {{ __('Edit commit message') }}
+ </gl-form-checkbox>
+ </div>
+ <div
+ v-else-if="!glFeatures.restructuredMrWidget"
+ class="bold js-resolve-mr-widget-items-message gl-ml-3"
+ >
+ <div
+ v-if="hasPipelineMustSucceedConflict"
+ class="gl-display-flex gl-align-items-center"
+ data-testid="pipeline-succeed-conflict"
+ >
+ <gl-sprintf :message="pipelineMustSucceedConflictText" />
+ <gl-link
+ :href="mr.pipelineMustSucceedDocsPath"
+ target="_blank"
+ class="gl-display-flex gl-ml-2"
+ >
+ <gl-icon name="question" />
+ </gl-link>
+ </div>
+ <gl-sprintf v-else :message="mergeDisabledText" />
</div>
- <template v-else>
- <div class="bold js-resolve-mr-widget-items-message gl-ml-3">
- <div
- v-if="hasPipelineMustSucceedConflict"
- class="gl-display-flex gl-align-items-center"
- data-testid="pipeline-succeed-conflict"
+ <template v-if="glFeatures.restructuredMrWidget">
+ <div v-show="editCommitMessage" class="gl-w-full gl-order-n1">
+ <ul
+ :class="{
+ 'content-list': !glFeatures.restructuredMrWidget,
+ 'gl-list-style-none gl-p-0 gl-pt-4': glFeatures.restructuredMrWidget,
+ }"
+ class="border-top commits-list flex-list"
>
- <gl-sprintf :message="pipelineMustSucceedConflictText" />
- <gl-link
- :href="mr.pipelineMustSucceedDocsPath"
- target="_blank"
- class="gl-display-flex gl-ml-2"
+ <commit-edit
+ v-if="shouldShowSquashEdit"
+ v-model="squashCommitMessage"
+ :label="__('Squash commit message')"
+ input-id="squash-message-edit"
+ class="gl-m-0! gl-p-0!"
+ >
+ <template #header>
+ <commit-message-dropdown v-model="squashCommitMessage" :commits="commits" />
+ </template>
+ </commit-edit>
+ <commit-edit
+ v-if="shouldShowMergeEdit"
+ v-model="commitMessage"
+ :label="__('Merge commit message')"
+ input-id="merge-message-edit"
+ class="gl-m-0! gl-p-0!"
>
- <gl-icon name="question" />
- </gl-link>
- </div>
- <gl-sprintf v-else :message="mergeDisabledText" />
+ <template #text-muted>
+ <p class="form-text text-muted">
+ <gl-sprintf :message="$options.i18n.mergeCommitTemplateHintText">
+ <template #link="{ content }">
+ <gl-link
+ :href="commitTemplateHelpPage"
+ class="inline-link"
+ target="_blank"
+ >
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </template>
+ </commit-edit>
+ </ul>
+ </div>
+ <div
+ v-if="!restructuredWidgetShowMergeButtons"
+ class="gl-w-full gl-order-n1 gl-text-gray-500"
+ >
+ <strong>
+ {{ __('Merge details') }}
+ </strong>
+ <ul class="gl-pl-4 gl-m-0">
+ <li class="gl-line-height-normal">
+ <added-commit-message
+ :is-squash-enabled="squashBeforeMerge"
+ :is-fast-forward-enabled="!shouldShowMergeEdit"
+ :commits-count="commitsCount"
+ :target-branch="stateData.targetBranch"
+ />
+ </li>
+ <li class="gl-line-height-normal">
+ <template v-if="removeSourceBranch">
+ {{ __('Deletes the source branch.') }}
+ </template>
+ <template v-else>
+ {{ __('Does not delete the source branch.') }}
+ </template>
+ </li>
+ <li v-if="mr.relatedLinks" class="gl-line-height-normal">
+ <related-links
+ :state="mr.state"
+ :related-links="mr.relatedLinks"
+ :show-assign-to-me="false"
+ class="mr-ready-merge-related-links gl-display-inline"
+ />
+ </li>
+ </ul>
+ </div>
+ <div
+ v-else
+ :class="{ 'gl-mb-5': restructuredWidgetShowMergeButtons }"
+ class="gl-w-full gl-order-n1 gl-text-gray-500"
+ >
+ <added-commit-message
+ :is-squash-enabled="squashBeforeMerge"
+ :is-fast-forward-enabled="!shouldShowMergeEdit"
+ :commits-count="commitsCount"
+ :target-branch="stateData.targetBranch"
+ />
+ <template v-if="mr.relatedLinks">
+ &middot;
+ <related-links
+ :state="mr.state"
+ :related-links="mr.relatedLinks"
+ :show-assign-to-me="false"
+ class="mr-ready-merge-related-links gl-display-inline"
+ />
+ </template>
</div>
</template>
</div>
<div
- v-if="showDangerMessageForMergeTrain"
+ v-if="showDangerMessageForMergeTrain && !glFeatures.restructuredMrWidget"
class="gl-mt-5 gl-text-gray-500"
data-testid="failed-pipeline-merge-train-text"
>
@@ -612,7 +765,7 @@ export default {
</div>
</div>
</div>
- <template v-if="shouldShowMergeControls">
+ <template v-if="shouldShowMergeControls && !glFeatures.restructuredMrWidget">
<div
v-if="!shouldShowMergeEdit"
class="mr-fast-forward-message"
@@ -621,7 +774,7 @@ export default {
{{ __('Fast-forward merge without a merge commit') }}
</div>
<commits-header
- v-if="shouldShowSquashEdit || shouldShowMergeEdit"
+ v-if="!glFeatures.restructuredMrWidget && (shouldShowSquashEdit || shouldShowMergeEdit)"
:is-squash-enabled="squashBeforeMerge"
:commits-count="commitsCount"
:target-branch="stateData.targetBranch"
@@ -646,15 +799,16 @@ export default {
:label="__('Merge commit message')"
input-id="merge-message-edit"
>
- <template #checkbox>
- <label>
- <input
- id="include-description"
- type="checkbox"
- @change="updateMergeCommitMessage($event.target.checked)"
- />
- {{ __('Include merge request description') }}
- </label>
+ <template #text-muted>
+ <p class="form-text text-muted">
+ <gl-sprintf :message="$options.i18n.mergeCommitTemplateHintText">
+ <template #link="{ content }">
+ <gl-link :href="commitTemplateHelpPage" class="inline-link" target="_blank">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
</template>
</commit-edit>
</ul>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
index 41b5983ae0c..c6227c4394d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
@@ -1,15 +1,18 @@
<script>
-import { GlIcon, GlTooltipDirective, GlFormCheckbox } from '@gitlab/ui';
+import { GlIcon, GlTooltipDirective, GlFormCheckbox, GlLink } from '@gitlab/ui';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { SQUASH_BEFORE_MERGE } from '../../i18n';
export default {
components: {
GlIcon,
GlFormCheckbox,
+ GlLink,
},
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [glFeatureFlagsMixin()],
i18n: {
...SQUASH_BEFORE_MERGE,
},
@@ -33,6 +36,9 @@ export default {
tooltipTitle() {
return this.isDisabled ? this.$options.i18n.tooltipTitle : null;
},
+ helpIconName() {
+ return this.glFeatures.restructuredMrWidget ? 'question-o' : 'question';
+ },
},
};
</script>
@@ -51,18 +57,18 @@ export default {
>
{{ $options.i18n.checkboxLabel }}
</gl-form-checkbox>
- <a
+ <gl-link
v-if="helpPath"
v-gl-tooltip
:href="helpPath"
:title="$options.i18n.helpLabel"
+ :class="{ 'gl-text-blue-600': glFeatures.restructuredMrWidget }"
target="_blank"
- rel="noopener noreferrer nofollow"
>
- <gl-icon name="question" />
+ <gl-icon :name="helpIconName" />
<span class="sr-only">
{{ $options.i18n.helpLabel }}
</span>
- </a>
+ </gl-link>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
index 790870ee4c6..fa4f8b76cb9 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
@@ -10,8 +10,8 @@ import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import getStateQuery from '../../queries/get_state.query.graphql';
-import workInProgressQuery from '../../queries/states/work_in_progress.query.graphql';
-import removeWipMutation from '../../queries/toggle_wip.mutation.graphql';
+import draftQuery from '../../queries/states/draft.query.graphql';
+import removeDraftMutation from '../../queries/toggle_draft.mutation.graphql';
import StatusIcon from '../mr_widget_status_icon.vue';
export default {
@@ -23,7 +23,7 @@ export default {
mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
apollo: {
userPermissions: {
- query: workInProgressQuery,
+ query: draftQuery,
skip() {
return !this.glFeatures.mergeRequestWidgetGraphql;
},
@@ -53,25 +53,25 @@ export default {
},
},
methods: {
- removeWipMutation() {
+ removeDraftMutation() {
const { mergeRequestQueryVariables } = this;
this.isMakingRequest = true;
this.$apollo
.mutate({
- mutation: removeWipMutation,
+ mutation: removeDraftMutation,
variables: {
...mergeRequestQueryVariables,
- wip: false,
+ draft: false,
},
update(
store,
{
data: {
- mergeRequestSetWip: {
+ mergeRequestSetDraft: {
errors,
- mergeRequest: { mergeableDiscussionsState, workInProgress, title },
+ mergeRequest: { mergeableDiscussionsState, draft, title },
},
},
},
@@ -91,7 +91,7 @@ export default {
const data = produce(sourceData, (draftState) => {
draftState.project.mergeRequest.mergeableDiscussionsState = mergeableDiscussionsState;
- draftState.project.mergeRequest.workInProgress = workInProgress;
+ draftState.project.mergeRequest.draft = draft;
draftState.project.mergeRequest.title = title;
});
@@ -104,14 +104,14 @@ export default {
optimisticResponse: {
// eslint-disable-next-line @gitlab/require-i18n-strings
__typename: 'Mutation',
- mergeRequestSetWip: {
+ mergeRequestSetDraft: {
__typename: 'MergeRequestSetWipPayload',
errors: [],
mergeRequest: {
__typename: 'MergeRequest',
mergeableDiscussionsState: true,
title: this.mr.title,
- workInProgress: false,
+ draft: false,
},
},
},
@@ -119,7 +119,7 @@ export default {
.then(
({
data: {
- mergeRequestSetWip: {
+ mergeRequestSetDraft: {
mergeRequest: { title },
},
},
@@ -137,9 +137,9 @@ export default {
this.isMakingRequest = false;
});
},
- handleRemoveWIP() {
+ handleRemoveDraft() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
- this.removeWipMutation();
+ this.removeDraftMutation();
} else {
this.isMakingRequest = true;
this.service
@@ -178,8 +178,8 @@ export default {
size="small"
:disabled="isMakingRequest"
:loading="isMakingRequest"
- class="js-remove-wip gl-ml-3"
- @click="handleRemoveWIP"
+ class="js-remove-draft gl-ml-3"
+ @click="handleRemoveDraft"
>
{{ s__('mrWidget|Mark as ready') }}
</gl-button>
diff --git a/app/assets/javascripts/vue_merge_request_widget/constants.js b/app/assets/javascripts/vue_merge_request_widget/constants.js
index b88e83ccb0f..d0c6cf12e25 100644
--- a/app/assets/javascripts/vue_merge_request_widget/constants.js
+++ b/app/assets/javascripts/vue_merge_request_widget/constants.js
@@ -17,14 +17,12 @@ export const AUTO_MERGE_STRATEGIES = [MWPS_MERGE_STRATEGY, MTWPS_MERGE_STRATEGY,
// SP - "Suggest Pipelines"
export const SP_TRACK_LABEL = 'no_pipeline_noticed';
-export const SP_LINK_TRACK_EVENT = 'click_link';
export const SP_SHOW_TRACK_EVENT = 'click_button';
-export const SP_LINK_TRACK_VALUE = 30;
export const SP_SHOW_TRACK_VALUE = 10;
export const SP_HELP_CONTENT = s__(
- `mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust.`,
+ `mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file.`,
);
-export const SP_HELP_URL = 'https://about.gitlab.com/blog/2019/07/12/guide-to-ci-cd-pipelines/';
+export const SP_HELP_URL = 'https://docs.gitlab.com/ee/ci/quick_start/';
export const SP_ICON_NAME = 'status_notfound';
export const MERGE_ACTIVE_STATUS_PHRASES = [
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
index 349e9d29355..9cbc0b0e5d1 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
@@ -11,6 +11,7 @@ export default {
label: 'Issues',
loading: 'Loading issues...',
},
+ expandEvent: 'i_testing_load_performance_widget_total',
// Add an array of props
// These then get mapped to values stored in the MR Widget store
props: ['targetProjectFullPath', 'conflictsDocsPath'],
@@ -29,7 +30,15 @@ export default {
// Tertiary action buttons that will take the user elsewhere
// in the GitLab app
tertiaryButtons() {
- return [{ text: 'Full report', href: this.conflictsDocsPath, target: '_blank' }];
+ return [
+ {
+ text: 'Click me',
+ onClick() {
+ console.log('Hello world');
+ },
+ },
+ { text: 'Full report', href: this.conflictsDocsPath, target: '_blank' },
+ ];
},
},
methods: {
@@ -66,6 +75,7 @@ export default {
// href: 'https://google.com', // Required: href for the link
// text: 'Link text', // Required: Text to be used inside the link
// },
+ actions: [{ text: 'Full report', href: 'https://gitlab.com', target: '_blank' }],
}));
});
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql b/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql
index 389a81e0a61..da1cace4598 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql
@@ -1,4 +1,4 @@
-query getIssues($projectPath: ID!) {
+query getProjectIssues($projectPath: ID!) {
project(fullPath: $projectPath) {
issues {
count
diff --git a/app/assets/javascripts/vue_merge_request_widget/index.js b/app/assets/javascripts/vue_merge_request_widget/index.js
index f5dbcec7dbe..8d596465970 100644
--- a/app/assets/javascripts/vue_merge_request_widget/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/index.js
@@ -13,12 +13,7 @@ Vue.use(Translate);
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- assumeImmutableResults: true,
- },
- ),
+ defaultClient: createDefaultClient(),
});
export default () => {
diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
index cf6472f2c8c..83789f10285 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
@@ -1,9 +1,13 @@
import { __ } from '~/locale';
export const MERGE_DISABLED_TEXT = __('You can only merge once the items above are resolved.');
+export const MERGE_DISABLED_SKIPPED_PIPELINE_TEXT = __(
+ "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue.",
+);
export const PIPELINE_MUST_SUCCEED_CONFLICT_TEXT = __(
'A CI/CD pipeline must run and be successful before merge.',
);
+export const PIPELINE_SKIPPED_STATUS = 'SKIPPED';
export default {
computed: {
@@ -17,6 +21,10 @@ export default {
);
},
mergeDisabledText() {
+ if (this.pipeline?.status === PIPELINE_SKIPPED_STATUS) {
+ return MERGE_DISABLED_SKIPPED_PIPELINE_TEXT;
+ }
+
return MERGE_DISABLED_TEXT;
},
pipelineMustSucceedConflictText() {
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index 3ac1e881658..c98dc426224 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -91,6 +91,7 @@ export default {
MrWidgetApprovals,
SecurityReportsApp: () => import('~/vue_shared/security_reports/security_reports_app.vue'),
MergeChecksFailed: () => import('./components/states/merge_checks_failed.vue'),
+ ReadyToMerge: ReadyToMergeState,
},
apollo: {
state: {
@@ -213,6 +214,9 @@ export default {
window.gon?.features?.refactorMrWidgetsExtensionsUser
);
},
+ isRestructuredMrWidgetEnabled() {
+ return window.gon?.features?.restructuredMrWidget;
+ },
},
watch: {
'mr.machineValue': {
@@ -547,12 +551,17 @@ export default {
<div class="mr-widget-section">
<component :is="componentName" :mr="mr" :service="service" />
-
- <div class="mr-widget-info">
+ <ready-to-merge
+ v-if="isRestructuredMrWidgetEnabled && mr.commitsCount"
+ :mr="mr"
+ :service="service"
+ />
+ <div v-else class="mr-widget-info">
<mr-widget-related-links
v-if="shouldRenderRelatedLinks"
:state="mr.state"
:related-links="mr.relatedLinks"
+ class="mr-info-list gl-ml-7 gl-pb-5"
/>
<source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
index 871aa880b36..bfb1517be81 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
@@ -23,7 +23,7 @@ query getState($projectPath: ID!, $iid: String!) {
userPermissions {
canMerge
}
- workInProgress
+ draft
}
}
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql
index daf21e75b3b..e0215fbd969 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql
@@ -1,6 +1,6 @@
#import "./auto_merge_enabled.fragment.graphql"
-query autoMergeEnabledQuery($projectPath: ID!, $iid: String!) {
+query autoMergeEnabled($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
mergeRequest(iid: $iid) {
...autoMergeEnabled
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql
index 186c0e64561..e66ac01ab12 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql
@@ -1,4 +1,4 @@
-query workInProgressQuery($projectPath: ID!, $iid: String!) {
+query workInProgress($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
mergeRequest(iid: $iid) {
shouldBeRebased
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql
new file mode 100644
index 00000000000..0983c28448e
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql
@@ -0,0 +1,9 @@
+query mrUserPermission($projectPath: ID!, $iid: String!) {
+ project(fullPath: $projectPath) {
+ mergeRequest(iid: $iid) {
+ userPermissions {
+ updateMergeRequest
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql
index 3b34be73c15..21c3ffd8321 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql
@@ -1,4 +1,4 @@
-query readyToMergeQuery($projectPath: ID!, $iid: String!) {
+query getReadyToMergeStatus($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
mergeRequest(iid: $iid) {
userPermissions {
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
index 367b9ad1cdf..b2a1be5c5a9 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
@@ -18,7 +18,9 @@ fragment ReadyToMerge on Project {
commitCount
diffHeadSha
userPermissions {
+ canMerge
removeSourceBranch
+ updateMergeRequest
}
targetBranch
mergeError
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql
index 78259e1f553..f713739f65a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql
@@ -1,6 +1,6 @@
#import "./ready_to_merge.fragment.graphql"
-query readyToMergeQuery($projectPath: ID!, $iid: String!) {
+query readyToMerge($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
...ReadyToMerge
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/work_in_progress.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/work_in_progress.query.graphql
deleted file mode 100644
index 73e205ebf2b..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/work_in_progress.query.graphql
+++ /dev/null
@@ -1,9 +0,0 @@
-query workInProgressQuery($projectPath: ID!, $iid: String!) {
- project(fullPath: $projectPath) {
- mergeRequest(iid: $iid) {
- userPermissions {
- updateMergeRequest
- }
- }
- }
-}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql
new file mode 100644
index 00000000000..200fb1b7ca5
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql
@@ -0,0 +1,10 @@
+mutation toggleDraftStatus($projectPath: ID!, $iid: String!, $draft: Boolean!) {
+ mergeRequestSetDraft(input: { projectPath: $projectPath, iid: $iid, draft: $draft }) {
+ mergeRequest {
+ mergeableDiscussionsState
+ title
+ draft
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/toggle_wip.mutation.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/toggle_wip.mutation.graphql
deleted file mode 100644
index cfaa198d516..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/queries/toggle_wip.mutation.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-mutation toggleWIPStatus($projectPath: ID!, $iid: String!, $wip: Boolean!) {
- mergeRequestSetWip(input: { projectPath: $projectPath, iid: $iid, wip: $wip }) {
- mergeRequest {
- mergeableDiscussionsState
- title
- workInProgress
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
index 65d78fc283c..2ae4f4da2f3 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
@@ -1,14 +1,14 @@
import { stateKey } from './state_maps';
export default function deviseState() {
- if (this.hasMergeChecksFailed) {
+ if (!this.commitsCount) {
+ return stateKey.nothingToMerge;
+ } else if (this.hasMergeChecksFailed && !this.autoMergeEnabled) {
return stateKey.mergeChecksFailed;
} else if (this.projectArchived) {
return stateKey.archived;
} else if (this.branchMissing) {
return stateKey.missingBranch;
- } else if (!this.commitsCount) {
- return stateKey.nothingToMerge;
} else if (this.mergeStatus === 'unchecked' || this.mergeStatus === 'checking') {
return stateKey.checking;
} else if (this.hasConflicts) {
@@ -17,8 +17,8 @@ export default function deviseState() {
return stateKey.rebase;
} else if (this.onlyAllowMergeIfPipelineSucceeds && this.isPipelineFailed) {
return stateKey.pipelineFailed;
- } else if (this.workInProgress) {
- return stateKey.workInProgress;
+ } else if (this.draft) {
+ return stateKey.draft;
} else if (this.hasMergeableDiscussionsState && !this.autoMergeEnabled) {
return stateKey.unresolvedDiscussions;
} else if (this.isPipelineBlocked) {
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
index 6628225cd46..10a2907c81a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
@@ -164,7 +164,7 @@ export default class MergeRequestStore {
this.projectArchived = data.project_archived;
this.isSHAMismatch = this.sha !== data.diff_head_sha;
this.shouldBeRebased = Boolean(data.should_be_rebased);
- this.workInProgress = data.work_in_progress;
+ this.draft = data.draft;
}
const currentUser = data.current_user;
@@ -207,7 +207,7 @@ export default class MergeRequestStore {
this.isPipelineFailed = this.ciStatus === 'failed' || this.ciStatus === 'canceled';
this.isSHAMismatch = this.sha !== mergeRequest.diffHeadSha;
this.shouldBeRebased = mergeRequest.shouldBeRebased;
- this.workInProgress = mergeRequest.workInProgress;
+ this.draft = mergeRequest.draft;
this.mergeRequestState = mergeRequest.state;
this.setState();
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js b/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js
index 4cb23407a74..9dfeaee905c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js
@@ -4,7 +4,7 @@ export const stateToComponentMap = {
merging: 'mr-widget-merging',
conflicts: 'mr-widget-conflicts',
missingBranch: 'mr-widget-missing-branch',
- workInProgress: 'mr-widget-wip',
+ draft: 'mr-widget-wip',
readyToMerge: 'mr-widget-ready-to-merge',
nothingToMerge: 'mr-widget-nothing-to-merge',
notAllowedToMerge: 'mr-widget-not-allowed',
@@ -24,7 +24,7 @@ export const stateToComponentMap = {
export const statesToShowHelpWidget = [
'merging',
'conflicts',
- 'workInProgress',
+ 'draft',
'readyToMerge',
'checking',
'unresolvedDiscussions',
@@ -40,7 +40,7 @@ export const stateKey = {
nothingToMerge: 'nothingToMerge',
checking: 'checking',
conflicts: 'conflicts',
- workInProgress: 'workInProgress',
+ draft: 'draft',
pipelineFailed: 'pipelineFailed',
unresolvedDiscussions: 'unresolvedDiscussions',
pipelineBlocked: 'pipelineBlocked',
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue b/app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue
index f8f1613879f..6b774b2a734 100644
--- a/app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue
@@ -1,5 +1,5 @@
<script>
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlSafeHtmlDirective } from '@gitlab/ui';
import NoteHeader from '~/notes/components/note_header.vue';
export default {
@@ -7,6 +7,9 @@ export default {
NoteHeader,
GlIcon,
},
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
props: {
note: {
type: Object,
@@ -39,7 +42,7 @@ export default {
<div class="note-header">
<note-header :author="noteAuthor" :created-at="note.createdAt" :note-id="note.id">
- <span v-html="note.bodyHtml /* eslint-disable-line vue/no-v-html */"></span>
+ <span v-safe-html="note.bodyHtml"></span>
</note-header>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql
index da5f1a00e11..0c26fcc0ab2 100644
--- a/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql
@@ -1,7 +1,7 @@
#import "~/graphql_shared/fragments/alert_detail_item.fragment.graphql"
#import "~/graphql_shared/fragments/user.fragment.graphql"
-query alertDetails($fullPath: ID!, $alertId: String) {
+query alertDetailsAssignees($fullPath: ID!, $alertId: String) {
project(fullPath: $fullPath) {
alertManagementAlerts(iid: $alertId) {
nodes {
diff --git a/app/assets/javascripts/vue_shared/alert_details/index.js b/app/assets/javascripts/vue_shared/alert_details/index.js
index fda405c0fa5..9f1da9ae173 100644
--- a/app/assets/javascripts/vue_shared/alert_details/index.js
+++ b/app/assets/javascripts/vue_shared/alert_details/index.js
@@ -38,7 +38,6 @@ export default (selector) => {
return defaultDataIdFromObject(object);
},
},
- assumeImmutableResults: true,
}),
});
diff --git a/app/assets/javascripts/vue_shared/components/alerts_deprecation_warning.vue b/app/assets/javascripts/vue_shared/components/alerts_deprecation_warning.vue
deleted file mode 100644
index 16ca2df02c0..00000000000
--- a/app/assets/javascripts/vue_shared/components/alerts_deprecation_warning.vue
+++ /dev/null
@@ -1,46 +0,0 @@
-<script>
-import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
-import { helpPagePath } from '~/helpers/help_page_helper';
-import { s__ } from '~/locale';
-
-export default {
- components: {
- GlAlert,
- GlLink,
- GlSprintf,
- },
- inject: ['hasManagedPrometheus'],
- i18n: {
- alertsDeprecationText: s__(
- 'Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard.',
- ),
- },
- methods: {
- helpPagePath,
- },
-};
-</script>
-
-<template>
- <gl-alert
- v-if="hasManagedPrometheus"
- variant="warning"
- class="my-2"
- data-testid="alerts-deprecation-warning"
- >
- <gl-sprintf :message="$options.i18n.alertsDeprecationText">
- <template #link="{ content }">
- <gl-link
- :href="
- helpPagePath('operations/metrics/alerts.html', {
- anchor: 'managed-prometheus-instances',
- })
- "
- target="_blank"
- >
- <span>{{ content }}</span>
- </gl-link>
- </template>
- </gl-sprintf>
- </gl-alert>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue b/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
index 40044e518c3..2c74d56f617 100644
--- a/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
@@ -1,5 +1,5 @@
<script>
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlSafeHtmlDirective } from '@gitlab/ui';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { HIGHLIGHT_CLASS_NAME } from './constants';
import ViewerMixin from './mixins';
@@ -9,6 +9,9 @@ export default {
components: {
GlIcon,
},
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
mixins: [ViewerMixin, glFeatureFlagsMixin()],
inject: ['blobHash'],
data() {
@@ -65,7 +68,7 @@ export default {
<div class="blob-content">
<pre
class="code highlight"
- ><code :data-blob-hash="blobHash" v-html="content /* eslint-disable-line vue/no-v-html */"></code></pre>
+ ><code v-safe-html="content" :data-blob-hash="blobHash"></code></pre>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
index f388a468fd2..5de71c35be9 100644
--- a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
@@ -21,6 +21,7 @@ import CiIcon from './ci_icon.vue';
* - Job show view - header
* - MR widget
* - Terraform table
+ * - On-demand scans list
*/
export default {
diff --git a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue
new file mode 100644
index 00000000000..4c07cf44fed
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue
@@ -0,0 +1,54 @@
+<script>
+import { GlButton, GlModalDirective } from '@gitlab/ui';
+import { CONFIRM_DANGER_MODAL_ID } from './constants';
+import ConfirmDangerModal from './confirm_danger_modal.vue';
+
+export default {
+ name: 'ConfirmDanger',
+ components: {
+ GlButton,
+ ConfirmDangerModal,
+ },
+ directives: {
+ GlModal: GlModalDirective,
+ },
+ props: {
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ phrase: {
+ type: String,
+ required: true,
+ },
+ buttonText: {
+ type: String,
+ required: true,
+ },
+ buttonTestid: {
+ type: String,
+ required: false,
+ default: 'confirm-danger-button',
+ },
+ },
+ modalId: CONFIRM_DANGER_MODAL_ID,
+};
+</script>
+<template>
+ <div>
+ <gl-button
+ v-gl-modal="$options.modalId"
+ class="gl-button"
+ variant="danger"
+ :disabled="disabled"
+ :data-testid="buttonTestid"
+ >{{ buttonText }}</gl-button
+ >
+ <confirm-danger-modal
+ :modal-id="$options.modalId"
+ :phrase="phrase"
+ @confirm="$emit('confirm')"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.stories.js b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.stories.js
new file mode 100644
index 00000000000..18fa297da87
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.stories.js
@@ -0,0 +1,28 @@
+/* eslint-disable @gitlab/require-i18n-strings */
+import ConfirmDanger from './confirm_danger.vue';
+
+export default {
+ component: ConfirmDanger,
+ title: 'vue_shared/components/modals/confirm_danger_modal',
+};
+
+const Template = (args, { argTypes }) => ({
+ components: { ConfirmDanger },
+ props: Object.keys(argTypes),
+ template: '<confirm-danger v-bind="$props" />',
+ provide: {
+ confirmDangerMessage: 'You require more Vespene Gas',
+ },
+});
+
+export const Default = Template.bind({});
+Default.args = {
+ phrase: 'You must construct additional pylons',
+ buttonText: 'Confirm button text',
+};
+
+export const Disabled = Template.bind({});
+Disabled.args = {
+ ...Default.args,
+ disabled: true,
+};
diff --git a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue
new file mode 100644
index 00000000000..30c96daf7e3
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue
@@ -0,0 +1,104 @@
+<script>
+import { GlAlert, GlModal, GlFormGroup, GlFormInput, GlSprintf } from '@gitlab/ui';
+import {
+ CONFIRM_DANGER_MODAL_BUTTON,
+ CONFIRM_DANGER_MODAL_TITLE,
+ CONFIRM_DANGER_PHRASE_TEXT,
+ CONFIRM_DANGER_WARNING,
+ CONFIRM_DANGER_MODAL_ERROR,
+} from './constants';
+
+export default {
+ name: 'ConfirmDangerModal',
+ components: {
+ GlAlert,
+ GlModal,
+ GlFormGroup,
+ GlFormInput,
+ GlSprintf,
+ },
+ inject: {
+ confirmDangerMessage: {
+ default: '',
+ },
+ confirmButtonText: {
+ default: CONFIRM_DANGER_MODAL_BUTTON,
+ },
+ },
+ props: {
+ modalId: {
+ type: String,
+ required: true,
+ },
+ phrase: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return { confirmationPhrase: '' };
+ },
+ computed: {
+ isValid() {
+ return Boolean(
+ this.confirmationPhrase.length && this.equalString(this.confirmationPhrase, this.phrase),
+ );
+ },
+ actionPrimary() {
+ return {
+ text: this.confirmButtonText,
+ attributes: [{ variant: 'danger', disabled: !this.isValid }],
+ };
+ },
+ },
+ methods: {
+ equalString(a, b) {
+ return a.trim().toLowerCase() === b.trim().toLowerCase();
+ },
+ },
+ i18n: {
+ CONFIRM_DANGER_MODAL_BUTTON,
+ CONFIRM_DANGER_MODAL_TITLE,
+ CONFIRM_DANGER_WARNING,
+ CONFIRM_DANGER_PHRASE_TEXT,
+ CONFIRM_DANGER_MODAL_ERROR,
+ },
+};
+</script>
+<template>
+ <gl-modal
+ ref="modal"
+ :modal-id="modalId"
+ :data-testid="modalId"
+ :title="$options.i18n.CONFIRM_DANGER_MODAL_TITLE"
+ :action-primary="actionPrimary"
+ @primary="$emit('confirm')"
+ >
+ <gl-alert
+ v-if="confirmDangerMessage"
+ variant="danger"
+ data-testid="confirm-danger-message"
+ :dismissible="false"
+ class="gl-mb-4"
+ >
+ {{ confirmDangerMessage }}
+ </gl-alert>
+ <p data-testid="confirm-danger-warning">{{ $options.i18n.CONFIRM_DANGER_WARNING }}</p>
+ <p data-testid="confirm-danger-phrase">
+ <gl-sprintf :message="$options.i18n.CONFIRM_DANGER_PHRASE_TEXT">
+ <template #phrase_code>
+ <code>{{ phrase }}</code>
+ </template>
+ </gl-sprintf>
+ </p>
+ <gl-form-group :state="isValid" :invalid-feedback="$options.i18n.CONFIRM_DANGER_MODAL_ERROR">
+ <gl-form-input
+ id="confirm_name_input"
+ v-model="confirmationPhrase"
+ class="form-control"
+ data-testid="confirm-danger-input"
+ type="text"
+ />
+ </gl-form-group>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/confirm_danger/constants.js b/app/assets/javascripts/vue_shared/components/confirm_danger/constants.js
new file mode 100644
index 00000000000..fa44a9be411
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/confirm_danger/constants.js
@@ -0,0 +1,12 @@
+import { __ } from '~/locale';
+
+export const CONFIRM_DANGER_MODAL_ID = 'confirm-danger-modal';
+export const CONFIRM_DANGER_MODAL_TITLE = __('Confirmation required');
+export const CONFIRM_DANGER_MODAL_ERROR = __('Confirmation required');
+export const CONFIRM_DANGER_MODAL_BUTTON = __('Confirm');
+export const CONFIRM_DANGER_WARNING = __(
+ 'This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention.',
+);
+export const CONFIRM_DANGER_PHRASE_TEXT = __(
+ 'Please type %{phrase_code} to proceed or close this modal to cancel.',
+);
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
index ea507017caa..9cf8638f3cb 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
@@ -1,5 +1,8 @@
<script>
-import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
+import {
+ GlDeprecatedSkeletonLoading as GlSkeletonLoading,
+ GlSafeHtmlDirective as SafeHtml,
+} from '@gitlab/ui';
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
import { forEach, escape } from 'lodash';
@@ -13,6 +16,9 @@ export default {
components: {
GlSkeletonLoading,
},
+ directives: {
+ SafeHtml,
+ },
props: {
content: {
type: String,
@@ -103,6 +109,7 @@ export default {
}
},
},
+ safeHtmlConfig: { ADD_TAGS: ['gl-emoji', 'use'] },
};
</script>
@@ -111,8 +118,8 @@ export default {
<gl-skeleton-loading v-if="isLoading" />
<div
v-else
+ v-safe-html:[$options.safeHtmlConfig]="previewContent"
class="md gl-ml-auto gl-mr-auto"
- v-html="previewContent /* eslint-disable-line vue/no-v-html */"
></div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue
index 7859ef85dd8..153b0981813 100644
--- a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue
+++ b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue
@@ -45,7 +45,7 @@ export default {
default: false,
},
selected: {
- type: Object,
+ type: [Object, Array],
required: false,
default: () => {},
},
@@ -54,6 +54,11 @@ export default {
required: false,
default: '',
},
+ allowMultiselect: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
isSearchEmpty() {
@@ -66,8 +71,14 @@ export default {
methods: {
selectOption(option) {
this.$emit('set-option', option || null);
+ if (!this.allowMultiselect) {
+ this.$refs.dropdown.hide();
+ }
},
isSelected(option) {
+ if (Array.isArray(this.selected)) {
+ return this.selected.some((label) => label.title === option.title);
+ }
return (
this.selected &&
((option.name && this.selected.name === option.name) ||
@@ -78,7 +89,7 @@ export default {
this.$refs.dropdown.show();
},
setFocus() {
- this.$refs.search.focusInput();
+ this.$refs.search?.focusInput();
},
setSearchTerm(search) {
this.$emit('set-search', search);
@@ -108,56 +119,60 @@ export default {
@shown="setFocus"
>
<template #header>
- <gl-search-box-by-type
- ref="search"
- :value="searchTerm"
- :placeholder="searchText"
- class="js-dropdown-input-field"
- @input="setSearchTerm"
- />
+ <slot name="header">
+ <gl-search-box-by-type
+ ref="search"
+ :value="searchTerm"
+ :placeholder="searchText"
+ class="js-dropdown-input-field"
+ @input="setSearchTerm"
+ />
+ </slot>
</template>
- <gl-dropdown-form class="gl-relative gl-min-h-7">
- <gl-loading-icon
- v-if="isLoading"
- size="md"
- class="gl-absolute gl-left-0 gl-top-0 gl-right-0"
- />
- <template v-else>
- <template v-if="isSearchEmpty && presetOptions.length > 0">
+ <slot name="default">
+ <gl-dropdown-form class="gl-relative gl-min-h-7" data-qa-selector="labels_dropdown_content">
+ <gl-loading-icon
+ v-if="isLoading"
+ size="md"
+ class="gl-absolute gl-left-0 gl-top-0 gl-right-0"
+ />
+ <template v-else>
+ <template v-if="isSearchEmpty && presetOptions.length > 0">
+ <gl-dropdown-item
+ v-for="option in presetOptions"
+ :key="option.id"
+ :is-checked="isSelected(option)"
+ :is-check-centered="true"
+ :is-check-item="true"
+ @click.native.capture.stop="selectOption(option)"
+ >
+ <slot name="preset-item" :item="option">
+ {{ option.title }}
+ </slot>
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ </template>
<gl-dropdown-item
- v-for="option in presetOptions"
+ v-for="option in options"
:key="option.id"
:is-checked="isSelected(option)"
:is-check-centered="true"
:is-check-item="true"
- @click="selectOption(option)"
+ :avatar-url="avatarUrl(option)"
+ :secondary-text="secondaryText(option)"
+ data-testid="unselected-option"
+ @click.native.capture.stop="selectOption(option)"
>
- <slot name="preset-item" :item="option">
+ <slot name="item" :item="option">
{{ option.title }}
</slot>
</gl-dropdown-item>
- <gl-dropdown-divider />
+ <gl-dropdown-item v-if="noOptionsFound" class="gl-pl-6!">
+ {{ $options.i18n.noMatchingResults }}
+ </gl-dropdown-item>
</template>
- <gl-dropdown-item
- v-for="option in options"
- :key="option.id"
- :is-checked="isSelected(option)"
- :is-check-centered="true"
- :is-check-item="true"
- :avatar-url="avatarUrl(option)"
- :secondary-text="secondaryText(option)"
- data-testid="unselected-option"
- @click="selectOption(option)"
- >
- <slot name="item" :item="option">
- {{ option.title }}
- </slot>
- </gl-dropdown-item>
- <gl-dropdown-item v-if="noOptionsFound" class="gl-pl-6!">
- {{ $options.i18n.noMatchingResults }}
- </gl-dropdown-item>
- </template>
- </gl-dropdown-form>
+ </gl-dropdown-form>
+ </slot>
<template #footer>
<slot name="footer"></slot>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/file_icon.vue b/app/assets/javascripts/vue_shared/components/file_icon.vue
index 276fb35b51f..adf34f822ed 100644
--- a/app/assets/javascripts/vue_shared/components/file_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/file_icon.vue
@@ -86,7 +86,7 @@ export default {
<template>
<span>
<gl-loading-icon v-if="loading" size="sm" :inline="true" />
- <gl-icon v-else-if="isSymlink" name="symlink" :size="size" use-deprecated-sizes />
+ <gl-icon v-else-if="isSymlink" name="symlink" :size="size" />
<svg v-else-if="!folder" :key="spriteHref" :class="[iconSizeClass, cssClasses]">
<use v-bind="{ 'xlink:href': spriteHref }" />
</svg>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
index 1df65d0a666..d9290e86bca 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
@@ -53,6 +53,7 @@ export const TOKEN_TITLE_ASSIGNEE = __('Assignee');
export const TOKEN_TITLE_MILESTONE = __('Milestone');
export const TOKEN_TITLE_LABEL = __('Label');
export const TOKEN_TITLE_TYPE = __('Type');
+export const TOKEN_TITLE_RELEASE = __('Release');
export const TOKEN_TITLE_MY_REACTION = __('My-Reaction');
export const TOKEN_TITLE_CONFIDENTIAL = __('Confidential');
export const TOKEN_TITLE_ITERATION = __('Iteration');
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
index 9dc5c5db276..7c1828f2294 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
@@ -171,15 +171,17 @@ export default {
* This watcher listens for updates to `filterValue` on
* such instances. :(
*/
- filterValue(value) {
- const [firstVal] = value;
+ filterValue(newValue, oldValue) {
+ const [firstVal] = newValue;
if (
!this.initialRender &&
- value.length === 1 &&
+ newValue.length === 1 &&
firstVal.type === 'filtered-search-term' &&
!firstVal.value.data
) {
- this.$emit('onFilter', []);
+ const filtersCleared =
+ oldValue[0].type !== 'filtered-search-term' || oldValue[0].value.data !== '';
+ this.$emit('onFilter', [], filtersCleared);
}
// Set initial render flag to false
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
index ae5d3965de1..b3b3d5c88c6 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
@@ -1,6 +1,6 @@
<script>
import { GlAvatar, GlFilteredSearchSuggestion } from '@gitlab/ui';
-
+import { compact } from 'lodash';
import createFlash from '~/flash';
import { __ } from '~/locale';
@@ -59,8 +59,10 @@ export default {
.then((res) => {
// We'd want to avoid doing this check but
// users.json and /groups/:id/members & /projects/:id/users
- // return response differently.
- this.authors = Array.isArray(res) ? res : res.data;
+ // return response differently
+
+ // TODO: rm when completed https://gitlab.com/gitlab-org/gitlab/-/issues/345756
+ this.authors = Array.isArray(res) ? compact(res) : compact(res.data);
})
.catch(() =>
createFlash({
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue
index c1d1bc7da91..aff93ebc9c0 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue
@@ -1,16 +1,21 @@
<script>
-import { GlFilteredSearchSuggestion } from '@gitlab/ui';
+import { GlDropdownDivider, GlDropdownSectionHeader, GlFilteredSearchSuggestion } from '@gitlab/ui';
import createFlash from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { DEFAULT_ITERATIONS } from '../constants';
export default {
components: {
BaseToken,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
GlFilteredSearchSuggestion,
},
+ mixins: [glFeatureFlagMixin()],
props: {
active: {
type: Boolean,
@@ -40,6 +45,27 @@ export default {
getActiveIteration(iterations, data) {
return iterations.find((iteration) => this.getValue(iteration) === data);
},
+ groupIterationsByCadence(iterations) {
+ const cadences = [];
+ iterations.forEach((iteration) => {
+ if (!iteration.iterationCadence) {
+ return;
+ }
+ const { title } = iteration.iterationCadence;
+ const cadenceIteration = {
+ id: iteration.id,
+ title: iteration.title,
+ period: this.getIterationPeriod(iteration),
+ };
+ const cadence = cadences.find((cad) => cad.title === title);
+ if (cadence) {
+ cadence.iterations.push(cadenceIteration);
+ } else {
+ cadences.push({ title, iterations: [cadenceIteration] });
+ }
+ });
+ return cadences;
+ },
fetchIterations(searchTerm) {
this.loading = true;
this.config
@@ -57,6 +83,16 @@ export default {
getValue(iteration) {
return String(getIdFromGraphQLId(iteration.id));
},
+ /**
+ * TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/344619
+ * This method also exists as a utility function in ee/../iterations/utils.js
+ * Remove the duplication when iteration token is moved to EE.
+ */
+ getIterationPeriod({ startDate, dueDate }) {
+ const start = formatDate(startDate, 'mmm d, yyyy', true);
+ const due = formatDate(dueDate, 'mmm d, yyyy', true);
+ return `${start} - ${due}`;
+ },
},
};
</script>
@@ -77,13 +113,26 @@ export default {
{{ activeTokenValue ? activeTokenValue.title : inputValue }}
</template>
<template #suggestions-list="{ suggestions }">
- <gl-filtered-search-suggestion
- v-for="iteration in suggestions"
- :key="iteration.id"
- :value="getValue(iteration)"
- >
- {{ iteration.title }}
- </gl-filtered-search-suggestion>
+ <template v-for="(cadence, index) in groupIterationsByCadence(suggestions)">
+ <gl-dropdown-divider v-if="index !== 0" :key="index" />
+ <gl-dropdown-section-header
+ :key="cadence.title"
+ class="gl-overflow-hidden"
+ :title="cadence.title"
+ >
+ {{ cadence.title }}
+ </gl-dropdown-section-header>
+ <gl-filtered-search-suggestion
+ v-for="iteration in cadence.iterations"
+ :key="iteration.id"
+ :value="getValue(iteration)"
+ >
+ {{ iteration.title }}
+ <div v-if="glFeatures.iterationCadences" class="gl-text-gray-400">
+ {{ iteration.period }}
+ </div>
+ </gl-filtered-search-suggestion>
+ </template>
</template>
</base-token>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue
new file mode 100644
index 00000000000..f353cc3a765
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue
@@ -0,0 +1,85 @@
+<script>
+import { GlFilteredSearchSuggestion } from '@gitlab/ui';
+import createFlash from '~/flash';
+import { __ } from '~/locale';
+import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
+import { DEFAULT_NONE_ANY } from '../constants';
+
+export default {
+ components: {
+ BaseToken,
+ GlFilteredSearchSuggestion,
+ },
+ props: {
+ active: {
+ type: Boolean,
+ required: true,
+ },
+ config: {
+ type: Object,
+ required: true,
+ },
+ value: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ releases: this.config.initialReleases || [],
+ loading: false,
+ };
+ },
+ computed: {
+ defaultReleases() {
+ return this.config.defaultReleases || DEFAULT_NONE_ANY;
+ },
+ },
+ methods: {
+ getActiveRelease(releases, data) {
+ return releases.find((release) => release.tag.toLowerCase() === data.toLowerCase());
+ },
+ fetchReleases(searchTerm) {
+ this.loading = true;
+ this.config
+ .fetchReleases(searchTerm)
+ .then((response) => {
+ this.releases = response;
+ })
+ .catch(() => {
+ createFlash({ message: __('There was a problem fetching releases.') });
+ })
+ .finally(() => {
+ this.loading = false;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <base-token
+ :active="active"
+ :config="config"
+ :value="value"
+ :default-suggestions="defaultReleases"
+ :suggestions="releases"
+ :suggestions-loading="loading"
+ :get-active-token-value="getActiveRelease"
+ @fetch-suggestions="fetchReleases"
+ v-on="$listeners"
+ >
+ <template #view="{ viewTokenProps: { inputValue, activeTokenValue } }">
+ {{ activeTokenValue ? activeTokenValue.tag : inputValue }}
+ </template>
+ <template #suggestions-list="{ suggestions }">
+ <gl-filtered-search-suggestion
+ v-for="release in suggestions"
+ :key="release.id"
+ :value="release.tag"
+ >
+ {{ release.tag }}
+ </gl-filtered-search-suggestion>
+ </template>
+ </base-token>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index 41613bb3307..6ace0bd88f8 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -1,10 +1,16 @@
<script>
-import { GlTooltipDirective, GlLink, GlButton, GlTooltip, GlSafeHtmlDirective } from '@gitlab/ui';
+import {
+ GlTooltipDirective,
+ GlButton,
+ GlSafeHtmlDirective,
+ GlAvatarLink,
+ GlAvatarLabeled,
+} from '@gitlab/ui';
+import { isGid, getIdFromGraphQLId } from '~/graphql_shared/utils';
import { glEmojiTag } from '../../emoji';
import { __, sprintf } from '../../locale';
import CiIconBadge from './ci_badge_link.vue';
import TimeagoTooltip from './time_ago_tooltip.vue';
-import UserAvatarImage from './user_avatar/user_avatar_image.vue';
/**
* Renders header component for job and pipeline page based on UI mockups
@@ -17,10 +23,9 @@ export default {
components: {
CiIconBadge,
TimeagoTooltip,
- UserAvatarImage,
- GlLink,
GlButton,
- GlTooltip,
+ GlAvatarLink,
+ GlAvatarLabeled,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -94,6 +99,9 @@ export default {
return this.itemName;
},
+ userId() {
+ return isGid(this.user?.id) ? getIdFromGraphQLId(this.user?.id) : this.user?.id;
+ },
},
methods: {
@@ -124,24 +132,32 @@ export default {
{{ __('by') }}
<template v-if="user">
- <gl-link
- v-gl-tooltip
- :href="userPath"
- :title="user.email"
- class="js-user-link commit-committer-link"
+ <gl-avatar-link
+ :data-user-id="userId"
+ :data-username="user.username"
+ :data-name="user.name"
+ :href="user.webUrl"
+ target="_blank"
+ class="js-user-link gl-vertical-align-middle gl-mx-2 gl-align-items-center"
>
- <user-avatar-image :img-src="avatarUrl" :img-alt="userAvatarAltText" :size="24" />
- {{ user.name }}
- </gl-link>
- <gl-tooltip v-if="message" :target="() => $refs[$options.EMOJI_REF]">
- {{ message }}
- </gl-tooltip>
- <span
- v-if="statusTooltipHTML"
- :ref="$options.EMOJI_REF"
- v-safe-html:[$options.safeHtmlConfig]="statusTooltipHTML"
- :data-testid="message"
- ></span>
+ <gl-avatar-labeled
+ :size="24"
+ :src="avatarUrl"
+ :label="user.name"
+ class="gl-display-none gl-sm-display-inline-flex gl-mx-1"
+ />
+ <strong class="author gl-display-inline gl-sm-display-none!">@{{ user.username }}</strong>
+ <gl-tooltip v-if="message" :target="() => $refs[$options.EMOJI_REF]">
+ {{ message }}
+ </gl-tooltip>
+ <span
+ v-if="statusTooltipHTML"
+ :ref="$options.EMOJI_REF"
+ v-safe-html:[$options.safeHtmlConfig]="statusTooltipHTML"
+ class="gl-ml-2"
+ :data-testid="message"
+ ></span>
+ </gl-avatar-link>
</template>
</section>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
index f9ae59567b2..648e9c9462f 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
@@ -1,11 +1,11 @@
<script>
-import { GlButton, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { GlBadge, GlButton, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { isLoggedIn } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import ApplySuggestion from './apply_suggestion.vue';
export default {
- components: { GlIcon, GlButton, GlLoadingIcon, ApplySuggestion },
+ components: { GlBadge, GlIcon, GlButton, GlLoadingIcon, ApplySuggestion },
directives: { 'gl-tooltip': GlTooltipDirective },
props: {
batchSuggestionsCount: {
@@ -134,8 +134,14 @@ export default {
<gl-icon name="question-o" css-classes="link-highlight" />
</a>
</div>
- <div v-if="isApplied" class="badge badge-success">{{ __('Applied') }}</div>
- <div v-else-if="isApplying" class="d-flex align-items-center text-secondary">
+ <gl-badge v-if="isApplied" variant="success" data-qa-selector="applied_badge">
+ {{ __('Applied') }}
+ </gl-badge>
+ <div
+ v-else-if="isApplying"
+ class="d-flex align-items-center text-secondary"
+ data-qa-selector="applying_badge"
+ >
<gl-loading-icon size="sm" class="d-flex-center mr-2" />
<span>{{ applyingSuggestionsMessage }}</span>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
index 755e6f1f224..8877cfa39fb 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -26,6 +26,7 @@ import {
import $ from 'jquery';
import { mapGetters, mapActions, mapState } from 'vuex';
import descriptionVersionHistoryMixin from 'ee_else_ce/notes/mixins/description_version_history';
+import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import initMRPopovers from '~/mr_popover/';
import noteHeader from '~/notes/components/note_header.vue';
@@ -61,6 +62,9 @@ export default {
data() {
return {
expanded: false,
+ lines: [],
+ showLines: false,
+ loadingDiff: false,
};
},
computed: {
@@ -94,10 +98,25 @@ export default {
},
methods: {
...mapActions(['fetchDescriptionVersion', 'softDeleteDescriptionVersion']),
+ async toggleDiff() {
+ this.showLines = !this.showLines;
+
+ if (!this.lines.length) {
+ this.loadingDiff = true;
+ const { data } = await axios.get(this.note.outdated_line_change_path);
+
+ this.lines = data.map((l) => ({
+ ...l,
+ rich_text: l.rich_text.replace(/^[+ -]/, ''),
+ }));
+ this.loadingDiff = false;
+ }
+ },
},
safeHtmlConfig: {
ADD_TAGS: ['use'], // to support icon SVGs
},
+ userColorSchemeClass: window.gon.user_color_scheme,
};
</script>
@@ -112,15 +131,28 @@ export default {
<div class="note-header">
<note-header :author="note.author" :created-at="note.created_at" :note-id="note.id">
<span v-safe-html="actionTextHtml"></span>
- <template v-if="canSeeDescriptionVersion" #extra-controls>
+ <template
+ v-if="canSeeDescriptionVersion || note.outdated_line_change_path"
+ #extra-controls
+ >
&middot;
<gl-button
+ v-if="canSeeDescriptionVersion"
variant="link"
:icon="descriptionVersionToggleIcon"
data-testid="compare-btn"
@click="toggleDescriptionVersion"
>{{ __('Compare with previous version') }}</gl-button
>
+ <gl-button
+ v-if="note.outdated_line_change_path"
+ :icon="showLines ? 'chevron-up' : 'chevron-down'"
+ variant="link"
+ data-testid="outdated-lines-change-btn"
+ @click="toggleDiff"
+ >
+ {{ __('Compare changes') }}
+ </gl-button>
</template>
</note-header>
</div>
@@ -154,6 +186,37 @@ export default {
@click="deleteDescriptionVersion"
/>
</div>
+ <div
+ v-if="lines.length && showLines"
+ class="diff-content gl-border-solid gl-border-1 gl-border-gray-200 gl-mt-4 gl-rounded-small gl-overflow-hidden"
+ >
+ <table
+ :class="$options.userColorSchemeClass"
+ class="code js-syntax-highlight"
+ data-testid="outdated-lines"
+ >
+ <tr v-for="line in lines" v-once :key="line.line_code" class="line_holder">
+ <td
+ :class="line.type"
+ class="diff-line-num old_line gl-border-bottom-0! gl-border-top-0!"
+ >
+ {{ line.old_line }}
+ </td>
+ <td
+ :class="line.type"
+ class="diff-line-num new_line gl-border-bottom-0! gl-border-top-0!"
+ >
+ {{ line.new_line }}
+ </td>
+ <td
+ :class="line.type"
+ class="line_content gl-display-table-cell!"
+ v-html="line.rich_text /* eslint-disable-line vue/no-v-html */"
+ ></td>
+ </tr>
+ </table>
+ </div>
+ <gl-skeleton-loading v-else-if="showLines" class="gl-mt-4" />
</div>
</div>
</timeline-entry-item>
diff --git a/app/assets/javascripts/vue_shared/components/registry/title_area.vue b/app/assets/javascripts/vue_shared/components/registry/title_area.vue
index 4b21ec0330a..d108d8d689d 100644
--- a/app/assets/javascripts/vue_shared/components/registry/title_area.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/title_area.vue
@@ -69,20 +69,23 @@ export default {
/>
<div class="gl-display-flex gl-flex-direction-column">
- <h1 class="gl-font-size-h1 gl-mt-3 gl-mb-2" data-testid="title">
+ <h2 class="gl-font-size-h1 gl-mt-3 gl-mb-0" data-testid="title">
<slot name="title">{{ title }}</slot>
- </h1>
+ </h2>
<div
v-if="$slots['sub-header']"
- class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-1"
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-3"
>
<slot name="sub-header"></slot>
</div>
</div>
</div>
- <div class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mt-3">
+ <div
+ v-if="metadataSlots.length > 0"
+ class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mt-3"
+ >
<template v-if="!metadataLoading">
<div
v-for="(row, metadataIndex) in metadataSlots"
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/constants.js b/app/assets/javascripts/vue_shared/components/runner_instructions/constants.js
index facace0d809..34845e3d9e4 100644
--- a/app/assets/javascripts/vue_shared/components/runner_instructions/constants.js
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/constants.js
@@ -2,6 +2,8 @@ import { s__ } from '~/locale';
export const PLATFORMS_WITHOUT_ARCHITECTURES = ['docker', 'kubernetes'];
+export const REGISTRATION_TOKEN_PLACEHOLDER = '$REGISTRATION_TOKEN';
+
export const INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES = {
docker: {
instructions: s__(
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue
index d55c93fd146..d5493aa5a66 100644
--- a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue
@@ -16,8 +16,9 @@ import { isEmpty } from 'lodash';
import { __, s__ } from '~/locale';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import {
- PLATFORMS_WITHOUT_ARCHITECTURES,
INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES,
+ PLATFORMS_WITHOUT_ARCHITECTURES,
+ REGISTRATION_TOKEN_PLACEHOLDER,
} from './constants';
import getRunnerPlatformsQuery from './graphql/queries/get_runner_platforms.query.graphql';
import getRunnerSetupInstructionsQuery from './graphql/queries/get_runner_setup.query.graphql';
@@ -41,7 +42,13 @@ export default {
props: {
modalId: {
type: String,
- required: true,
+ required: false,
+ default: 'runner-instructions-modal',
+ },
+ registrationToken: {
+ type: String,
+ required: false,
+ default: null,
},
},
apollo: {
@@ -117,8 +124,20 @@ export default {
runnerInstallationLink() {
return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatformName]?.link;
},
+ registerInstructionsWithToken() {
+ const { registerInstructions } = this.instructions || {};
+
+ if (this.registrationToken) {
+ return registerInstructions.replace(REGISTRATION_TOKEN_PLACEHOLDER, this.registrationToken);
+ }
+
+ return registerInstructions;
+ },
},
methods: {
+ show() {
+ this.$refs.modal.show();
+ },
selectPlatform(platform) {
this.selectedPlatform = platform;
@@ -158,9 +177,11 @@ export default {
</script>
<template>
<gl-modal
+ ref="modal"
:modal-id="modalId"
:title="$options.i18n.installARunner"
:action-secondary="$options.closeButton"
+ v-bind="$attrs"
>
<gl-alert v-if="showAlert" variant="danger" @dismiss="toggleAlert(false)">
{{ $options.i18n.fetchError }}
@@ -243,11 +264,11 @@ export default {
<pre
class="gl-bg-gray gl-flex-grow-1 gl-white-space-pre-line"
data-testid="register-command"
- >{{ instructions.registerInstructions }}</pre
+ >{{ registerInstructionsWithToken }}</pre
>
<modal-copy-button
:title="$options.i18n.copyInstructions"
- :text="instructions.registerInstructions"
+ :text="registerInstructionsWithToken"
:modal-id="$options.modalId"
css-classes="gl-align-self-start gl-ml-2 gl-mt-2"
category="tertiary"
diff --git a/app/assets/javascripts/vue_shared/components/settings/settings_block.vue b/app/assets/javascripts/vue_shared/components/settings/settings_block.vue
index e75fedbb1d7..e68f0f31c13 100644
--- a/app/assets/javascripts/vue_shared/components/settings/settings_block.vue
+++ b/app/assets/javascripts/vue_shared/components/settings/settings_block.vue
@@ -24,10 +24,13 @@ export default {
},
},
data() {
+ const forceOpen = !this.collapsible || this.defaultExpanded;
return {
// Non-collapsible sections should always be expanded.
// For collapsible sections, fall back to defaultExpanded.
- sectionExpanded: !this.collapsible || this.defaultExpanded,
+ sectionExpanded: forceOpen,
+ initialised: forceOpen,
+ animating: false,
};
},
computed: {
@@ -53,7 +56,12 @@ export default {
toggleSectionExpanded() {
this.sectionExpanded = !this.sectionExpanded;
+ if (!this.initialised) {
+ this.initialised = true;
+ }
+
if (this.sectionExpanded) {
+ this.animating = true;
this.$refs.settingsContent.focus();
}
},
@@ -68,7 +76,10 @@ export default {
</script>
<template>
- <section class="settings" :class="{ 'no-animate': !slideAnimated, expanded: sectionExpanded }">
+ <section
+ class="settings"
+ :class="{ 'no-animate': !slideAnimated, expanded: sectionExpanded, animating }"
+ >
<div class="settings-header">
<h4>
<span
@@ -103,12 +114,14 @@ export default {
</p>
</div>
<div
+ v-show="initialised"
:id="settingsContentId"
ref="settingsContent"
:aria-labelledby="settingsLabelId"
tabindex="-1"
role="region"
class="settings-content"
+ @animationend="animating = false"
>
<slot></slot>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
index 6511c8d8c31..460a10e08ed 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
@@ -40,7 +40,7 @@ export default {
</script>
<template>
- <div v-gl-tooltip.left.viewport :class="containerClass" :title="tooltipText" @click="click">
+ <div v-gl-tooltip.left.viewport="tooltipText" :class="containerClass" @click="click">
<gl-icon v-if="showIcon" name="calendar" />
<slot>
<span> {{ text }} </span>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
index d80b66fd9be..399db978b60 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
@@ -36,6 +36,7 @@ export default {
<template>
<div
class="labels-select-dropdown-contents gl-w-full gl-my-2 gl-py-3 gl-rounded-base gl-absolute"
+ data-testid="labels-select-dropdown-contents"
data-qa-selector="labels_dropdown_content"
:style="directionStyle"
>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue
index 122250d1ce7..8a26c4a6618 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue
@@ -43,12 +43,7 @@ export default {
</script>
<template>
- <div
- v-gl-tooltip.left.viewport
- :title="labelsList"
- class="sidebar-collapsed-icon"
- @click="handleClick"
- >
+ <div v-gl-tooltip.left.viewport="labelsList" class="sidebar-collapsed-icon" @click="handleClick">
<gl-icon name="labels" />
<span>{{ labels.length }}</span>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
index 0ea22eb7aea..9e64f03fe84 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
@@ -1,5 +1,4 @@
import { isScopedLabel, scopedLabelKey } from '~/lib/utils/common_utils';
-import { SCOPED_LABEL_DELIMITER } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
import { DropdownVariant } from '../constants';
import * as types from './mutation_types';
@@ -67,9 +66,11 @@ export default {
}
if (isScopedLabel(candidateLabel)) {
- const scopedKeyWithDelimiter = `${scopedLabelKey(candidateLabel)}${SCOPED_LABEL_DELIMITER}`;
const currentActiveScopedLabel = state.labels.find(
- ({ title }) => title.startsWith(scopedKeyWithDelimiter) && title !== candidateLabel.title,
+ ({ set, title }) =>
+ set &&
+ title !== candidateLabel.title &&
+ scopedLabelKey({ title }) === scopedLabelKey(candidateLabel),
);
if (currentActiveScopedLabel) {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/constants.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/constants.js
index 389eb174c0e..cd671b4d8f5 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/constants.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/constants.js
@@ -1,7 +1,13 @@
export const SCOPED_LABEL_DELIMITER = '::';
+export const DEBOUNCE_DROPDOWN_DELAY = 200;
export const DropdownVariant = {
Sidebar: 'sidebar',
Standalone: 'standalone',
Embedded: 'embedded',
};
+
+export const LabelType = {
+ group: 'group',
+ project: 'project',
+};
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
index 3ee0baf8812..f7485de0342 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
@@ -1,20 +1,25 @@
<script>
import { GlButton, GlDropdown, GlDropdownItem, GlLink } from '@gitlab/ui';
+import { debounce } from 'lodash';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { __, s__, sprintf } from '~/locale';
import DropdownContentsCreateView from './dropdown_contents_create_view.vue';
import DropdownContentsLabelsView from './dropdown_contents_labels_view.vue';
+import DropdownFooter from './dropdown_footer.vue';
+import DropdownHeader from './dropdown_header.vue';
import { isDropdownVariantStandalone, isDropdownVariantSidebar } from './utils';
export default {
components: {
DropdownContentsLabelsView,
DropdownContentsCreateView,
+ DropdownHeader,
+ DropdownFooter,
GlButton,
GlDropdown,
GlDropdownItem,
GlLink,
},
- inject: ['allowLabelCreate', 'labelsManagePath'],
props: {
labelsCreateTitle: {
type: String,
@@ -48,10 +53,6 @@ export default {
type: String,
required: true,
},
- issuableType: {
- type: String,
- required: true,
- },
isVisible: {
type: Boolean,
required: false,
@@ -61,10 +62,17 @@ export default {
type: String,
required: true,
},
+ workspaceType: {
+ type: String,
+ required: true,
+ },
attrWorkspacePath: {
type: String,
- required: false,
- default: undefined,
+ required: true,
+ },
+ labelCreateType: {
+ type: String,
+ required: true,
},
},
data() {
@@ -72,6 +80,7 @@ export default {
showDropdownContentsCreateView: false,
localSelectedLabels: [...this.selectedLabels],
isDirty: false,
+ searchKey: '',
};
},
computed: {
@@ -113,15 +122,24 @@ export default {
if (newVal) {
this.$refs.dropdown.show();
this.isDirty = false;
+ this.localSelectedLabels = this.selectedLabels;
} else {
this.$refs.dropdown.hide();
this.setLabels();
}
},
selectedLabels(newVal) {
- this.localSelectedLabels = newVal;
+ if (!this.isDirty) {
+ this.localSelectedLabels = newVal;
+ }
},
},
+ created() {
+ this.debouncedSearchKeyUpdate = debounce(this.setSearchKey, DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
+ },
+ beforeDestroy() {
+ this.debouncedSearchKeyUpdate.cancel();
+ },
methods: {
toggleDropdownContentsCreateView() {
this.showDropdownContentsCreateView = !this.showDropdownContentsCreateView;
@@ -140,10 +158,20 @@ export default {
this.$emit('setLabels', this.localSelectedLabels);
},
handleDropdownHide() {
+ this.$emit('closeDropdown');
if (!isDropdownVariantSidebar(this.variant)) {
this.setLabels();
}
},
+ setSearchKey(value) {
+ this.searchKey = value;
+ },
+ setFocus() {
+ this.$refs.header.focusInput();
+ },
+ showDropdown() {
+ this.$refs.dropdown.show();
+ },
},
};
</script>
@@ -153,62 +181,44 @@ export default {
ref="dropdown"
:text="buttonText"
class="gl-w-full gl-mt-2"
+ data-testid="labels-select-dropdown-contents"
data-qa-selector="labels_dropdown_content"
@hide="handleDropdownHide"
+ @shown="setFocus"
>
<template #header>
- <div
+ <dropdown-header
v-if="!isStandalone"
- class="dropdown-title gl-display-flex gl-align-items-center gl-pt-0 gl-pb-3!"
- data-testid="dropdown-header"
- >
- <gl-button
- v-if="showDropdownContentsCreateView"
- :aria-label="__('Go back')"
- variant="link"
- size="small"
- class="js-btn-back dropdown-header-button gl-p-0"
- icon="arrow-left"
- data-testid="go-back-button"
- @click.stop="toggleDropdownContent"
- />
- <span class="gl-flex-grow-1">{{ dropdownTitle }}</span>
- <gl-button
- :aria-label="__('Close')"
- variant="link"
- size="small"
- class="dropdown-header-button gl-p-0!"
- icon="close"
- data-testid="close-button"
- @click="$emit('closeDropdown')"
- />
- </div>
+ ref="header"
+ v-model="searchKey"
+ :labels-create-title="labelsCreateTitle"
+ :labels-list-title="labelsListTitle"
+ :show-dropdown-contents-create-view="showDropdownContentsCreateView"
+ @toggleDropdownContentsCreateView="toggleDropdownContent"
+ @closeDropdown="$emit('closeDropdown')"
+ @input="debouncedSearchKeyUpdate"
+ />
</template>
<template #default>
<component
:is="dropdownContentsView"
v-model="localSelectedLabels"
- :selected-labels="selectedLabels"
+ :search-key="searchKey"
:allow-multiselect="allowMultiselect"
- :issuable-type="issuableType"
:full-path="fullPath"
+ :workspace-type="workspaceType"
:attr-workspace-path="attrWorkspacePath"
- @hideCreateView="toggleDropdownContentsCreateView"
+ :label-create-type="labelCreateType"
+ @hideCreateView="toggleDropdownContent"
/>
</template>
<template #footer>
- <div v-if="showDropdownFooter" data-testid="dropdown-footer">
- <gl-dropdown-item
- v-if="allowLabelCreate"
- data-testid="create-label-button"
- @click.capture.native.stop="toggleDropdownContent"
- >
- {{ footerCreateLabelTitle }}
- </gl-dropdown-item>
- <gl-dropdown-item :href="labelsManagePath" @click.capture.native.stop>
- {{ footerManageLabelTitle }}
- </gl-dropdown-item>
- </div>
+ <dropdown-footer
+ v-if="showDropdownFooter"
+ :footer-create-label-title="footerCreateLabelTitle"
+ :footer-manage-label-title="footerManageLabelTitle"
+ @toggleDropdownContentsCreateView="toggleDropdownContent"
+ />
</template>
</gl-dropdown>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
index a2ed08e6b28..da626a21b14 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
@@ -2,10 +2,10 @@
import { GlTooltipDirective, GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui';
import produce from 'immer';
import createFlash from '~/flash';
-import { IssuableType } from '~/issue_show/constants';
import { __ } from '~/locale';
-import { labelsQueries } from '~/sidebar/constants';
+import { workspaceLabelsQueries } from '~/sidebar/constants';
import createLabelMutation from './graphql/create_label.mutation.graphql';
+import { LabelType } from './constants';
const errorMessage = __('Error creating label.');
@@ -20,18 +20,21 @@ export default {
GlTooltip: GlTooltipDirective,
},
props: {
- issuableType: {
+ fullPath: {
type: String,
required: true,
},
- fullPath: {
+ attrWorkspacePath: {
type: String,
required: true,
},
- attrWorkspacePath: {
+ labelCreateType: {
+ type: String,
+ required: true,
+ },
+ workspaceType: {
type: String,
- required: false,
- default: undefined,
+ required: true,
},
},
data() {
@@ -50,25 +53,13 @@ export default {
return Object.keys(colorsMap).map((color) => ({ [color]: colorsMap[color] }));
},
mutationVariables() {
- if (this.issuableType === IssuableType.Epic) {
- return {
- title: this.labelTitle,
- color: this.selectedColor,
- groupPath: this.fullPath,
- };
- }
+ const attributePath = this.labelCreateType === LabelType.group ? 'groupPath' : 'projectPath';
- return this.attrWorkspacePath !== undefined
- ? {
- title: this.labelTitle,
- color: this.selectedColor,
- groupPath: this.attrWorkspacePath,
- }
- : {
- title: this.labelTitle,
- color: this.selectedColor,
- projectPath: this.fullPath,
- };
+ return {
+ title: this.labelTitle,
+ color: this.selectedColor,
+ [attributePath]: this.attrWorkspacePath,
+ };
},
},
methods: {
@@ -82,8 +73,10 @@ export default {
this.selectedColor = this.getColorCode(color);
},
updateLabelsInCache(store, label) {
+ const { query } = workspaceLabelsQueries[this.workspaceType];
+
const sourceData = store.readQuery({
- query: labelsQueries[this.issuableType].workspaceQuery,
+ query,
variables: { fullPath: this.fullPath, searchTerm: '' },
});
@@ -95,7 +88,7 @@ export default {
});
store.writeQuery({
- query: labelsQueries[this.issuableType].workspaceQuery,
+ query,
variables: { fullPath: this.fullPath, searchTerm: '' },
data,
});
@@ -180,7 +173,7 @@ export default {
<gl-button
class="js-btn-cancel-create"
data-testid="cancel-button"
- @click="$emit('hideCreateView')"
+ @click.stop="$emit('hideCreateView')"
>
{{ __('Cancel') }}
</gl-button>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
index e6a25362ff0..e9a2d7747e2 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
@@ -1,18 +1,10 @@
<script>
-import {
- GlDropdownForm,
- GlDropdownItem,
- GlLoadingIcon,
- GlSearchBoxByType,
- GlIntersectionObserver,
-} from '@gitlab/ui';
+import { GlDropdownForm, GlDropdownItem, GlLoadingIcon, GlIntersectionObserver } from '@gitlab/ui';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
-import { debounce } from 'lodash';
import createFlash from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { __ } from '~/locale';
-import { labelsQueries } from '~/sidebar/constants';
+import { workspaceLabelsQueries } from '~/sidebar/constants';
import LabelItem from './label_item.vue';
export default {
@@ -20,7 +12,6 @@ export default {
GlDropdownForm,
GlDropdownItem,
GlLoadingIcon,
- GlSearchBoxByType,
GlIntersectionObserver,
LabelItem,
},
@@ -28,18 +19,10 @@ export default {
prop: 'localSelectedLabels',
},
props: {
- selectedLabels: {
- type: Array,
- required: true,
- },
allowMultiselect: {
type: Boolean,
required: true,
},
- issuableType: {
- type: String,
- required: true,
- },
localSelectedLabels: {
type: Array,
required: true,
@@ -48,10 +31,17 @@ export default {
type: String,
required: true,
},
+ searchKey: {
+ type: String,
+ required: true,
+ },
+ workspaceType: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
- searchKey: '',
labels: [],
isVisible: false,
};
@@ -59,7 +49,7 @@ export default {
apollo: {
labels: {
query() {
- return labelsQueries[this.issuableType].workspaceQuery;
+ return workspaceLabelsQueries[this.workspaceType].query;
},
variables() {
return {
@@ -71,12 +61,6 @@ export default {
return this.searchKey.length === 1 || !this.isVisible;
},
update: (data) => data.workspace?.labels?.nodes || [],
- async result() {
- if (this.$refs.searchInput) {
- await this.$nextTick;
- this.$refs.searchInput.focusInput();
- }
- },
error() {
createFlash({ message: __('Error fetching labels.') });
},
@@ -101,12 +85,6 @@ export default {
return Boolean(this.searchKey) && this.visibleLabels.length === 0;
},
},
- created() {
- this.debouncedSearchKeyUpdate = debounce(this.setSearchKey, DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
- },
- beforeDestroy() {
- this.debouncedSearchKeyUpdate.cancel();
- },
methods: {
isLabelSelected(label) {
return this.localSelectedLabelsIds.includes(getIdFromGraphQLId(label.id));
@@ -137,13 +115,7 @@ export default {
({ id }) => id !== getIdFromGraphQLId(label.id) && id !== label.id,
);
} else {
- labels = [
- ...this.localSelectedLabels,
- {
- ...label,
- id: getIdFromGraphQLId(label.id),
- },
- ];
+ labels = [...this.localSelectedLabels, label];
}
this.$emit('input', labels);
},
@@ -153,12 +125,8 @@ export default {
this.$emit('closeDropdown', this.localSelectedLabels);
}
},
- setSearchKey(value) {
- this.searchKey = value;
- },
onDropdownAppear() {
this.isVisible = true;
- this.$refs.searchInput.focusInput();
},
},
};
@@ -167,14 +135,6 @@ export default {
<template>
<gl-intersection-observer @appear="onDropdownAppear">
<gl-dropdown-form class="labels-select-contents-list js-labels-list">
- <gl-search-box-by-type
- ref="searchInput"
- :value="searchKey"
- :disabled="labelsFetchInProgress"
- data-qa-selector="dropdown_input_field"
- data-testid="dropdown-input-field"
- @input="debouncedSearchKeyUpdate"
- />
<div ref="labelsListContainer" data-testid="dropdown-content">
<gl-loading-icon
v-if="labelsFetchInProgress"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_footer.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_footer.vue
new file mode 100644
index 00000000000..e67e704ffb8
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_footer.vue
@@ -0,0 +1,35 @@
+<script>
+import { GlDropdownItem } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlDropdownItem,
+ },
+ inject: ['allowLabelCreate', 'labelsManagePath'],
+ props: {
+ footerCreateLabelTitle: {
+ type: String,
+ required: true,
+ },
+ footerManageLabelTitle: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div data-testid="dropdown-footer">
+ <gl-dropdown-item
+ v-if="allowLabelCreate"
+ data-testid="create-label-button"
+ @click.capture.native.stop="$emit('toggleDropdownContentsCreateView')"
+ >
+ {{ footerCreateLabelTitle }}
+ </gl-dropdown-item>
+ <gl-dropdown-item :href="labelsManagePath" @click.capture.native.stop>
+ {{ footerManageLabelTitle }}
+ </gl-dropdown-item>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue
new file mode 100644
index 00000000000..10064b01648
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue
@@ -0,0 +1,82 @@
+<script>
+import { GlButton, GlSearchBoxByType } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlButton,
+ GlSearchBoxByType,
+ },
+ model: {
+ prop: 'searchKey',
+ },
+ props: {
+ labelsCreateTitle: {
+ type: String,
+ required: true,
+ },
+ labelsListTitle: {
+ type: String,
+ required: true,
+ },
+ showDropdownContentsCreateView: {
+ type: Boolean,
+ required: true,
+ },
+ labelsFetchInProgress: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ searchKey: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ dropdownTitle() {
+ return this.showDropdownContentsCreateView ? this.labelsCreateTitle : this.labelsListTitle;
+ },
+ },
+ methods: {
+ focusInput() {
+ this.$refs.searchInput?.focusInput();
+ },
+ },
+};
+</script>
+
+<template>
+ <div data-testid="dropdown-header">
+ <div class="dropdown-title gl-display-flex gl-align-items-center gl-pt-0 gl-pb-3!">
+ <gl-button
+ v-if="showDropdownContentsCreateView"
+ :aria-label="__('Go back')"
+ variant="link"
+ size="small"
+ class="js-btn-back dropdown-header-button gl-p-0"
+ icon="arrow-left"
+ data-testid="go-back-button"
+ @click.stop="$emit('toggleDropdownContentsCreateView')"
+ />
+ <span class="gl-flex-grow-1">{{ dropdownTitle }}</span>
+ <gl-button
+ :aria-label="__('Close')"
+ variant="link"
+ size="small"
+ class="dropdown-header-button gl-p-0!"
+ icon="close"
+ data-testid="close-button"
+ @click="$emit('closeDropdown')"
+ />
+ </div>
+ <gl-search-box-by-type
+ v-if="!showDropdownContentsCreateView"
+ ref="searchInput"
+ :value="searchKey"
+ :disabled="labelsFetchInProgress"
+ data-qa-selector="dropdown_input_field"
+ data-testid="dropdown-input-field"
+ @input="$emit('input', $event)"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
index 71d3d87cce5..aed5bc303ee 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
@@ -1,7 +1,6 @@
<script>
import { GlLabel } from '@gitlab/ui';
import { sortBy } from 'lodash';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { isScopedLabel } from '~/lib/utils/common_utils';
export default {
@@ -47,7 +46,7 @@ export default {
return this.allowScopedLabels && isScopedLabel(label);
},
removeLabel(labelId) {
- this.$emit('onLabelRemove', getIdFromGraphQLId(labelId));
+ this.$emit('onLabelRemove', labelId);
},
},
};
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql
index eb478645a03..a9c791091fc 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql
@@ -1,12 +1,11 @@
+#import "~/graphql_shared/fragments/label.fragment.graphql"
+
mutation createLabel($title: String!, $color: String, $projectPath: ID, $groupPath: ID) {
labelCreate(
input: { title: $title, color: $color, projectPath: $projectPath, groupPath: $groupPath }
) {
label {
- id
- color
- description
- title
+ ...Label
}
errors
}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql
index a2e8579486f..c130cc426dc 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql
@@ -1,13 +1,12 @@
+#import "~/graphql_shared/fragments/label.fragment.graphql"
+
query epicLabels($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
issuable: epic(iid: $iid) {
id
labels {
nodes {
- id
- title
- color
- description
+ ...Label
}
}
}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql
new file mode 100644
index 00000000000..45fcb50732e
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql
@@ -0,0 +1,15 @@
+#import "~/graphql_shared/fragments/label.fragment.graphql"
+
+mutation updateEpicLabels($input: UpdateEpicInput!) {
+ updateEpic(input: $input) {
+ epic {
+ id
+ labels {
+ nodes {
+ ...Label
+ }
+ }
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/group_labels.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/group_labels.query.graphql
index acc9bcd2015..ce1a69f84c0 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/group_labels.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/group_labels.query.graphql
@@ -1,11 +1,11 @@
+#import "~/graphql_shared/fragments/label.fragment.graphql"
+
query groupLabels($fullPath: ID!, $searchTerm: String) {
workspace: group(fullPath: $fullPath) {
- labels(searchTerm: $searchTerm, onlyGroupLabels: true) {
+ id
+ labels(searchTerm: $searchTerm, onlyGroupLabels: true, includeAncestorGroups: true) {
nodes {
- id
- title
- color
- description
+ ...Label
}
}
}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql
index 1c2fd3bb7c0..e471d279b24 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql
@@ -1,13 +1,12 @@
+#import "~/graphql_shared/fragments/label.fragment.graphql"
+
query issueLabels($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
issuable: issue(iid: $iid) {
id
labels {
nodes {
- id
- title
- color
- description
+ ...Label
}
}
}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql
new file mode 100644
index 00000000000..dd80e89c8a7
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql
@@ -0,0 +1,14 @@
+#import "~/graphql_shared/fragments/label.fragment.graphql"
+
+query mergeRequestLabels($fullPath: ID!, $iid: String!) {
+ workspace: project(fullPath: $fullPath) {
+ issuable: mergeRequest(iid: $iid) {
+ id
+ labels {
+ nodes {
+ ...Label
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql
index dc39220487d..a7c24620aad 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql
@@ -1,11 +1,11 @@
+#import "~/graphql_shared/fragments/label.fragment.graphql"
+
query projectLabels($fullPath: ID!, $searchTerm: String) {
workspace: project(fullPath: $fullPath) {
+ id
labels(searchTerm: $searchTerm, includeAncestorGroups: true) {
nodes {
- id
- title
- color
- description
+ ...Label
}
}
}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
index 6bd43da2203..97a65c13933 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
@@ -1,9 +1,12 @@
<script>
+import { debounce } from 'lodash';
+import { MutationOperationMode, getIdFromGraphQLId } from '~/graphql_shared/utils';
import createFlash from '~/flash';
+import { IssuableType } from '~/issue_show/constants';
import { __ } from '~/locale';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
-import { labelsQueries } from '~/sidebar/constants';
-import { DropdownVariant } from './constants';
+import { issuableLabelsQueries } from '~/sidebar/constants';
+import { DEBOUNCE_DROPDOWN_DELAY, DropdownVariant } from './constants';
import DropdownContents from './dropdown_contents.vue';
import DropdownValue from './dropdown_value.vue';
import DropdownValueCollapsed from './dropdown_value_collapsed.vue';
@@ -50,16 +53,6 @@ export default {
required: false,
default: DropdownVariant.Sidebar,
},
- selectedLabels: {
- type: Array,
- required: false,
- default: () => [],
- },
- labelsSelectInProgress: {
- type: Boolean,
- required: false,
- default: false,
- },
labelsFilterBasePath: {
type: String,
required: false,
@@ -95,36 +88,44 @@ export default {
required: false,
default: __('Manage group labels'),
},
- isEditing: {
- type: Boolean,
- required: false,
- default: false,
- },
issuableType: {
type: String,
required: true,
},
+ workspaceType: {
+ type: String,
+ required: true,
+ },
attrWorkspacePath: {
type: String,
- required: false,
- default: undefined,
+ required: true,
+ },
+ labelCreateType: {
+ type: String,
+ required: true,
},
},
data() {
return {
contentIsOnViewport: true,
issuableLabels: [],
+ labelsSelectInProgress: false,
+ oldIid: null,
+ sidebarExpandedOnClick: false,
};
},
computed: {
isLoading() {
return this.labelsSelectInProgress || this.$apollo.queries.issuableLabels.loading;
},
+ issuableLabelIds() {
+ return this.issuableLabels.map((label) => label.id);
+ },
},
apollo: {
issuableLabels: {
query() {
- return labelsQueries[this.issuableType].issuableQuery;
+ return issuableLabelsQueries[this.issuableType].issuableQuery;
},
skip() {
return !isDropdownVariantSidebar(this.variant);
@@ -143,16 +144,140 @@ export default {
},
},
},
+ watch: {
+ iid(_, oldVal) {
+ this.oldIid = oldVal;
+ },
+ },
+ mounted() {
+ document.addEventListener('toggleSidebarRevealLabelsDropdown', this.handleCollapsedValueClick);
+ },
+ beforeDestroy() {
+ document.removeEventListener(
+ 'toggleSidebarRevealLabelsDropdown',
+ this.handleCollapsedValueClick,
+ );
+ },
methods: {
handleDropdownClose(labels) {
- this.$emit('updateSelectedLabels', labels);
+ if (this.iid !== '') {
+ this.updateSelectedLabels(this.getUpdateVariables(labels));
+ } else {
+ this.$emit('updateSelectedLabels', { labels });
+ }
+
this.collapseEditableItem();
},
collapseEditableItem() {
this.$refs.editable?.collapse();
+ if (this.sidebarExpandedOnClick) {
+ this.sidebarExpandedOnClick = false;
+ this.$emit('toggleCollapse');
+ }
},
handleCollapsedValueClick() {
+ this.sidebarExpandedOnClick = true;
this.$emit('toggleCollapse');
+ debounce(() => {
+ this.$refs.editable.toggle();
+ this.$refs.dropdownContents.showDropdown();
+ }, DEBOUNCE_DROPDOWN_DELAY)();
+ },
+ getUpdateVariables(labels) {
+ let labelIds = [];
+
+ labelIds = labels.map(({ id }) => id);
+ const currentIid = this.oldIid || this.iid;
+
+ const updateVariables = {
+ iid: currentIid,
+ projectPath: this.fullPath,
+ labelIds,
+ };
+
+ switch (this.issuableType) {
+ case IssuableType.Issue:
+ return updateVariables;
+ case IssuableType.MergeRequest:
+ return {
+ ...updateVariables,
+ operationMode: MutationOperationMode.Replace,
+ };
+ case IssuableType.Epic:
+ return {
+ iid: currentIid,
+ groupPath: this.fullPath,
+ addLabelIds: labelIds.map((id) => getIdFromGraphQLId(id)),
+ removeLabelIds: this.issuableLabelIds
+ .filter((id) => !labelIds.includes(id))
+ .map((id) => getIdFromGraphQLId(id)),
+ };
+ default:
+ return {};
+ }
+ },
+ updateSelectedLabels(inputVariables) {
+ this.labelsSelectInProgress = true;
+
+ this.$apollo
+ .mutate({
+ mutation: issuableLabelsQueries[this.issuableType].mutation,
+ variables: { input: inputVariables },
+ })
+ .then(({ data }) => {
+ const { mutationName } = issuableLabelsQueries[this.issuableType];
+
+ if (data[mutationName]?.errors?.length) {
+ throw new Error();
+ }
+
+ this.$emit('updateSelectedLabels', {
+ id: data[mutationName]?.[this.issuableType]?.id,
+ labels: data[mutationName]?.[this.issuableType]?.labels?.nodes,
+ });
+ })
+ .catch((error) =>
+ createFlash({
+ message: __('An error occurred while updating labels.'),
+ captureError: true,
+ error,
+ }),
+ )
+ .finally(() => {
+ this.labelsSelectInProgress = false;
+ });
+ },
+ getRemoveVariables(labelId) {
+ const removeVariables = {
+ iid: this.iid,
+ projectPath: this.fullPath,
+ };
+
+ switch (this.issuableType) {
+ case IssuableType.Issue:
+ return {
+ ...removeVariables,
+ removeLabelIds: [labelId],
+ };
+ case IssuableType.MergeRequest:
+ return {
+ ...removeVariables,
+ labelIds: [labelId],
+ operationMode: MutationOperationMode.Remove,
+ };
+ case IssuableType.Epic:
+ return {
+ iid: this.iid,
+ removeLabelIds: [getIdFromGraphQLId(labelId)],
+ groupPath: this.fullPath,
+ };
+ default:
+ return {};
+ }
+ },
+ handleLabelRemove(labelId) {
+ this.updateSelectedLabels(this.getRemoveVariables(labelId));
+ this.$emit('onLabelRemove', labelId);
},
isDropdownVariantSidebar,
isDropdownVariantStandalone,
@@ -180,6 +305,7 @@ export default {
:title="__('Labels')"
:loading="isLoading"
:can-edit="allowLabelEdit"
+ @open="oldIid = null"
>
<template #collapsed>
<dropdown-value
@@ -188,7 +314,7 @@ export default {
:allow-label-remove="allowLabelRemove"
:labels-filter-base-path="labelsFilterBasePath"
:labels-filter-param="labelsFilterParam"
- @onLabelRemove="$emit('onLabelRemove', $event)"
+ @onLabelRemove="handleLabelRemove"
>
<slot></slot>
</dropdown-value>
@@ -201,23 +327,25 @@ export default {
:labels-filter-base-path="labelsFilterBasePath"
:labels-filter-param="labelsFilterParam"
class="gl-mb-2"
- @onLabelRemove="$emit('onLabelRemove', $event)"
+ @onLabelRemove="handleLabelRemove"
>
<slot></slot>
</dropdown-value>
<dropdown-contents
+ ref="dropdownContents"
:dropdown-button-text="dropdownButtonText"
:allow-multiselect="allowMultiselect"
:labels-list-title="labelsListTitle"
:footer-create-label-title="footerCreateLabelTitle"
:footer-manage-label-title="footerManageLabelTitle"
:labels-create-title="labelsCreateTitle"
- :selected-labels="selectedLabels"
+ :selected-labels="issuableLabels"
:variant="variant"
- :issuable-type="issuableType"
:is-visible="edit"
:full-path="fullPath"
+ :workspace-type="workspaceType"
:attr-workspace-path="attrWorkspacePath"
+ :label-create-type="labelCreateType"
@setLabels="handleDropdownClose"
@closeDropdown="collapseEditableItem"
/>
@@ -233,10 +361,12 @@ export default {
:footer-create-label-title="footerCreateLabelTitle"
:footer-manage-label-title="footerManageLabelTitle"
:labels-create-title="labelsCreateTitle"
- :selected-labels="selectedLabels"
+ :selected-labels="issuableLabels"
:variant="variant"
- :issuable-type="issuableType"
:full-path="fullPath"
+ :workspace-type="workspaceType"
+ :attr-workspace-path="attrWorkspacePath"
+ :label-create-type="labelCreateType"
@setLabels="handleDropdownClose"
/>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_timelogs.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_timelogs.query.graphql
index a2990d7171b..dffcc053fac 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_timelogs.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_timelogs.query.graphql
@@ -1,6 +1,6 @@
#import "~/graphql_shared/fragments/issuable_timelogs.fragment.graphql"
-query timeTrackingReport($id: IssueID!) {
+query issueTimeTrackingReport($id: IssueID!) {
issuable: issue(id: $id) {
__typename
id
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_timelogs.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_timelogs.query.graphql
index 753f1b345e3..ede9b75d765 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_timelogs.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_timelogs.query.graphql
@@ -1,6 +1,6 @@
#import "~/graphql_shared/fragments/issuable_timelogs.fragment.graphql"
-query timeTrackingReport($id: MergeRequestID!) {
+query mrTimeTrackingReport($id: MergeRequestID!) {
issuable: mergeRequest(id: $id) {
__typename
id
diff --git a/app/assets/javascripts/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.vue b/app/assets/javascripts/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.vue
index 1eea660d527..a16dcb6d893 100644
--- a/app/assets/javascripts/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.vue
+++ b/app/assets/javascripts/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.vue
@@ -5,10 +5,10 @@ import { OBSTACLE_TYPES } from './constants';
const OBSTACLE_TEXT = {
[OBSTACLE_TYPES.oncallSchedules]: s__(
- 'OnCallSchedules|On-call schedule %{obstacle} in Project %{project}',
+ 'OnCallSchedules|On-call schedule %{obstacle} in project %{project}',
),
[OBSTACLE_TYPES.escalationPolicies]: s__(
- 'EscalationPolicies|Escalation policy %{obstacle} in Project %{project}',
+ 'EscalationPolicies|Escalation policy %{obstacle} in project %{project}',
),
};
diff --git a/app/assets/javascripts/vue_shared/constants.js b/app/assets/javascripts/vue_shared/constants.js
index 33fac5ebdbb..9cb66f6e65f 100644
--- a/app/assets/javascripts/vue_shared/constants.js
+++ b/app/assets/javascripts/vue_shared/constants.js
@@ -63,3 +63,6 @@ export const timeRanges = [
export const defaultTimeRange = timeRanges.find((tr) => tr.default);
export const getTimeWindow = (timeWindowName) =>
timeRanges.find((tr) => tr.name === timeWindowName);
+
+export const AVATAR_SHAPE_OPTION_CIRCLE = 'circle';
+export const AVATAR_SHAPE_OPTION_RECT = 'rect';
diff --git a/app/assets/javascripts/vue_shared/directives/validation.js b/app/assets/javascripts/vue_shared/directives/validation.js
index 779b04dc2bd..fc0ff78e7b4 100644
--- a/app/assets/javascripts/vue_shared/directives/validation.js
+++ b/app/assets/javascripts/vue_shared/directives/validation.js
@@ -1,4 +1,4 @@
-import { s__ } from '~/locale';
+import { __ } from '~/locale';
/**
* Validation messages will take priority based on the property order.
@@ -12,11 +12,11 @@ import { s__ } from '~/locale';
const defaultFeedbackMap = {
valueMissing: {
isInvalid: (el) => el.validity?.valueMissing,
- message: s__('Please fill out this field.'),
+ message: __('Please fill out this field.'),
},
urlTypeMismatch: {
isInvalid: (el) => el.type === 'url' && el.validity?.typeMismatch,
- message: s__('Please enter a valid URL format, ex: http://www.example.com/home'),
+ message: __('Please enter a valid URL format, ex: http://www.example.com/home'),
},
};
diff --git a/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue b/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue
index c1e8376d656..114f60c96ee 100644
--- a/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue
+++ b/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue
@@ -82,7 +82,7 @@ export default {
});
this.$root.$on('clicked::link', (e) => {
- window.location = e.target.href;
+ window.location = e.currentTarget.href;
});
},
diff --git a/app/assets/javascripts/vue_shared/security_configuration/provider.js b/app/assets/javascripts/vue_shared/security_configuration/provider.js
index fa23669b615..ef96b443da8 100644
--- a/app/assets/javascripts/vue_shared/security_configuration/provider.js
+++ b/app/assets/javascripts/vue_shared/security_configuration/provider.js
@@ -5,5 +5,5 @@ import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
export default new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ defaultClient: createDefaultClient(),
});
diff --git a/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue b/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue
index 3a4453bc7ae..e0669b3ed27 100644
--- a/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue
+++ b/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue
@@ -26,6 +26,11 @@ export default {
type: Number,
required: true,
},
+ injectedArtifacts: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
},
data() {
return {
@@ -56,6 +61,9 @@ export default {
isLoadingReportArtifacts() {
return this.$apollo.queries.reportArtifacts.loading;
},
+ mergedReportArtifacts() {
+ return [...this.reportArtifacts, ...this.injectedArtifacts];
+ },
},
methods: {
showError(error) {
@@ -77,7 +85,7 @@ export default {
<template>
<security-report-download-dropdown
:title="s__('SecurityReports|Download results')"
- :artifacts="reportArtifacts"
+ :artifacts="mergedReportArtifacts"
:loading="isLoadingReportArtifacts"
/>
</template>
diff --git a/app/assets/javascripts/vue_shared/security_reports/constants.js b/app/assets/javascripts/vue_shared/security_reports/constants.js
index b024e92bd0e..fafbd02634f 100644
--- a/app/assets/javascripts/vue_shared/security_reports/constants.js
+++ b/app/assets/javascripts/vue_shared/security_reports/constants.js
@@ -17,6 +17,7 @@ export const REPORT_FILE_TYPES = {
* Security scan report types, as provided by the backend.
*/
export const REPORT_TYPE_SAST = 'sast';
+export const REPORT_TYPE_SAST_IAC = 'sast_iac';
export const REPORT_TYPE_DAST = 'dast';
export const REPORT_TYPE_DAST_PROFILES = 'dast_profiles';
export const REPORT_TYPE_SECRET_DETECTION = 'secret_detection';
diff --git a/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql b/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql
index b5858ab012b..e1f3c55a886 100644
--- a/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql
+++ b/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql
@@ -1,6 +1,6 @@
#import "../fragments/job_artifacts.fragment.graphql"
-query getCorpuses($projectPath: ID!, $iid: ID, $reportTypes: [SecurityReportTypeEnum!]) {
+query getPipelineCorpuses($projectPath: ID!, $iid: ID, $reportTypes: [SecurityReportTypeEnum!]) {
project(fullPath: $projectPath) {
pipeline(iid: $iid) {
id
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js
index 62a51abe038..8aefc13a5fa 100644
--- a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js
@@ -18,6 +18,7 @@ export const fetchDiff = ({ state, rootState, dispatch }) => {
return fetchDiffData(rootState, state.paths.diffEndpoint, REPORT_TYPE_SAST)
.then((data) => {
dispatch('receiveDiffSuccess', data);
+ return data;
})
.catch(() => {
dispatch('receiveDiffError');
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js
index 722dcce3075..13ca154bfa7 100644
--- a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/actions.js
@@ -18,6 +18,7 @@ export const fetchDiff = ({ state, rootState, dispatch }) => {
return fetchDiffData(rootState, state.paths.diffEndpoint, REPORT_TYPE_SECRET_DETECTION)
.then((data) => {
dispatch('receiveDiffSuccess', data);
+ return data;
})
.catch(() => {
dispatch('receiveDiffError');
diff --git a/app/assets/javascripts/work_items/components/app.vue b/app/assets/javascripts/work_items/components/app.vue
index 93de17d1e43..a14d0c32cbe 100644
--- a/app/assets/javascripts/work_items/components/app.vue
+++ b/app/assets/javascripts/work_items/components/app.vue
@@ -1,9 +1,5 @@
-<script>
-export default {
- name: 'WorkItemRoot',
-};
-</script>
-
<template>
- <div></div>
+ <div>
+ <router-view />
+ </div>
</template>
diff --git a/app/assets/javascripts/work_items/constants.js b/app/assets/javascripts/work_items/constants.js
new file mode 100644
index 00000000000..b39f68abf74
--- /dev/null
+++ b/app/assets/javascripts/work_items/constants.js
@@ -0,0 +1,3 @@
+export const widgetTypes = {
+ title: 'TITLE',
+};
diff --git a/app/assets/javascripts/work_items/graphql/fragmentTypes.json b/app/assets/javascripts/work_items/graphql/fragmentTypes.json
new file mode 100644
index 00000000000..c048ac34ac0
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/fragmentTypes.json
@@ -0,0 +1 @@
+{"__schema":{"types":[{"kind":"INTERFACE","name":"WorkItemWidget","possibleTypes":[{"name":"TitleWidget"}]}]}}
diff --git a/app/assets/javascripts/work_items/graphql/provider.js b/app/assets/javascripts/work_items/graphql/provider.js
new file mode 100644
index 00000000000..083735336ce
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/provider.js
@@ -0,0 +1,55 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
+import createDefaultClient from '~/lib/graphql';
+import workItemQuery from './work_item.query.graphql';
+import introspectionQueryResultData from './fragmentTypes.json';
+import typeDefs from './typedefs.graphql';
+
+const fragmentMatcher = new IntrospectionFragmentMatcher({
+ introspectionQueryResultData,
+});
+
+export function createApolloProvider() {
+ Vue.use(VueApollo);
+
+ const defaultClient = createDefaultClient(
+ {},
+ {
+ cacheConfig: {
+ fragmentMatcher,
+ },
+ typeDefs,
+ },
+ );
+
+ defaultClient.cache.writeQuery({
+ query: workItemQuery,
+ variables: {
+ id: '1',
+ },
+ data: {
+ workItem: {
+ __typename: 'WorkItem',
+ id: '1',
+ type: 'FEATURE',
+ widgets: {
+ __typename: 'WorkItemWidgetConnection',
+ nodes: [
+ {
+ __typename: 'TitleWidget',
+ type: 'TITLE',
+ enabled: true,
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ contentText: 'Test Work Item Title',
+ },
+ ],
+ },
+ },
+ },
+ });
+
+ return new VueApollo({
+ defaultClient,
+ });
+}
diff --git a/app/assets/javascripts/work_items/graphql/resolvers.js b/app/assets/javascripts/work_items/graphql/resolvers.js
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/resolvers.js
diff --git a/app/assets/javascripts/work_items/graphql/typedefs.graphql b/app/assets/javascripts/work_items/graphql/typedefs.graphql
index e69de29bb2d..4a6e4aeed60 100644
--- a/app/assets/javascripts/work_items/graphql/typedefs.graphql
+++ b/app/assets/javascripts/work_items/graphql/typedefs.graphql
@@ -0,0 +1,38 @@
+enum WorkItemType {
+ FEATURE
+}
+
+enum WidgetType {
+ TITLE
+}
+
+interface WorkItemWidget {
+ type: WidgetType!
+}
+
+# Replicating Relay connection type for client schema
+type WorkItemWidgetEdge {
+ cursor: String!
+ node: WorkItemWidget
+}
+
+type WorkItemWidgetConnection {
+ edges: [WorkItemWidgetEdge]
+ nodes: [WorkItemWidget]
+ pageInfo: PageInfo!
+}
+
+type TitleWidget implements WorkItemWidget {
+ type: WidgetType!
+ contentText: String!
+}
+
+type WorkItem {
+ id: ID!
+ type: WorkItemType!
+ widgets: [WorkItemWidgetConnection]
+}
+
+extend type Query {
+ workItem(id: ID!): WorkItem!
+}
diff --git a/app/assets/javascripts/work_items/graphql/widget.fragment.graphql b/app/assets/javascripts/work_items/graphql/widget.fragment.graphql
new file mode 100644
index 00000000000..d7608c26052
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/widget.fragment.graphql
@@ -0,0 +1,3 @@
+fragment WidgetBase on WorkItemWidget {
+ type
+}
diff --git a/app/assets/javascripts/work_items/graphql/work_item.query.graphql b/app/assets/javascripts/work_items/graphql/work_item.query.graphql
new file mode 100644
index 00000000000..549e4f8c65a
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/work_item.query.graphql
@@ -0,0 +1,16 @@
+#import './widget.fragment.graphql'
+
+query WorkItem($id: ID!) {
+ workItem(id: $id) @client {
+ id
+ type
+ widgets {
+ nodes {
+ ...WidgetBase
+ ... on TitleWidget {
+ contentText
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/work_items/index.js b/app/assets/javascripts/work_items/index.js
index a635d43776d..7cc8a23b7b1 100644
--- a/app/assets/javascripts/work_items/index.js
+++ b/app/assets/javascripts/work_items/index.js
@@ -1,11 +1,15 @@
import Vue from 'vue';
import App from './components/app.vue';
+import { createRouter } from './router';
+import { createApolloProvider } from './graphql/provider';
export const initWorkItemsRoot = () => {
const el = document.querySelector('#js-work-items');
return new Vue({
el,
+ router: createRouter(el.dataset.fullPath),
+ apolloProvider: createApolloProvider(),
render(createElement) {
return createElement(App);
},
diff --git a/app/assets/javascripts/work_items/pages/work_item_root.vue b/app/assets/javascripts/work_items/pages/work_item_root.vue
new file mode 100644
index 00000000000..493ee0aba01
--- /dev/null
+++ b/app/assets/javascripts/work_items/pages/work_item_root.vue
@@ -0,0 +1,48 @@
+<script>
+import workItemQuery from '../graphql/work_item.query.graphql';
+import { widgetTypes } from '../constants';
+
+export default {
+ props: {
+ id: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ workItem: null,
+ };
+ },
+ apollo: {
+ workItem: {
+ query: workItemQuery,
+ variables() {
+ return {
+ id: this.id,
+ };
+ },
+ },
+ },
+ computed: {
+ titleWidgetData() {
+ return this.workItem?.widgets?.nodes?.find((widget) => widget.type === widgetTypes.title);
+ },
+ },
+};
+</script>
+
+<template>
+ <section>
+ <!-- Title widget placeholder -->
+ <div>
+ <h2
+ v-if="titleWidgetData"
+ class="gl-font-weight-normal gl-sm-font-weight-bold gl-my-5"
+ data-testid="title"
+ >
+ {{ titleWidgetData.contentText }}
+ </h2>
+ </div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/work_items/router/index.js b/app/assets/javascripts/work_items/router/index.js
new file mode 100644
index 00000000000..142fab8cfa6
--- /dev/null
+++ b/app/assets/javascripts/work_items/router/index.js
@@ -0,0 +1,14 @@
+import Vue from 'vue';
+import VueRouter from 'vue-router';
+import { joinPaths } from '~/lib/utils/url_utility';
+import { routes } from './routes';
+
+Vue.use(VueRouter);
+
+export function createRouter(fullPath) {
+ return new VueRouter({
+ routes,
+ mode: 'history',
+ base: joinPaths(fullPath, '-', 'work_items'),
+ });
+}
diff --git a/app/assets/javascripts/work_items/router/routes.js b/app/assets/javascripts/work_items/router/routes.js
new file mode 100644
index 00000000000..a3cf44ad4ca
--- /dev/null
+++ b/app/assets/javascripts/work_items/router/routes.js
@@ -0,0 +1,8 @@
+export const routes = [
+ {
+ path: '/:id',
+ name: 'work_item',
+ component: () => import('../pages/work_item_root.vue'),
+ props: true,
+ },
+];
diff --git a/app/assets/stylesheets/emoji_sprites.scss b/app/assets/stylesheets/emoji_sprites.scss
index 01d13b30d2b..5a5f39a4b77 100644
--- a/app/assets/stylesheets/emoji_sprites.scss
+++ b/app/assets/stylesheets/emoji_sprites.scss
@@ -7,111 +7,111 @@
background-position: -20px 0;
}
-.emoji-1F627 {
+.emoji-8ball {
background-position: 0 -20px;
}
-.emoji-8ball {
+.emoji-a {
background-position: -20px -20px;
}
-.emoji-a {
+.emoji-ab {
background-position: -40px 0;
}
-.emoji-ab {
+.emoji-abc {
background-position: -40px -20px;
}
-.emoji-abc {
+.emoji-abcd {
background-position: 0 -40px;
}
-.emoji-abcd {
+.emoji-accept {
background-position: -20px -40px;
}
-.emoji-accept {
+.emoji-aerial_tramway {
background-position: -40px -40px;
}
-.emoji-aerial_tramway {
+.emoji-airplane {
background-position: -60px 0;
}
-.emoji-airplane {
+.emoji-airplane_arriving {
background-position: -60px -20px;
}
-.emoji-airplane_arriving {
+.emoji-airplane_departure {
background-position: -60px -40px;
}
-.emoji-airplane_departure {
+.emoji-airplane_small {
background-position: 0 -60px;
}
-.emoji-airplane_small {
+.emoji-alarm_clock {
background-position: -20px -60px;
}
-.emoji-alarm_clock {
+.emoji-alembic {
background-position: -40px -60px;
}
-.emoji-alembic {
+.emoji-alien {
background-position: -60px -60px;
}
-.emoji-alien {
+.emoji-ambulance {
background-position: -80px 0;
}
-.emoji-ambulance {
+.emoji-amphora {
background-position: -80px -20px;
}
-.emoji-amphora {
+.emoji-anchor {
background-position: -80px -40px;
}
-.emoji-anchor {
+.emoji-angel {
background-position: -80px -60px;
}
-.emoji-angel {
+.emoji-angel_tone1 {
background-position: 0 -80px;
}
-.emoji-angel_tone1 {
+.emoji-angel_tone2 {
background-position: -20px -80px;
}
-.emoji-angel_tone2 {
+.emoji-angel_tone3 {
background-position: -40px -80px;
}
-.emoji-angel_tone3 {
+.emoji-angel_tone4 {
background-position: -60px -80px;
}
-.emoji-angel_tone4 {
+.emoji-angel_tone5 {
background-position: -80px -80px;
}
-.emoji-angel_tone5 {
+.emoji-anger {
background-position: -100px 0;
}
-.emoji-anger {
+.emoji-anger_right {
background-position: -100px -20px;
}
-.emoji-anger_right {
+.emoji-angry {
background-position: -100px -40px;
}
-.emoji-angry {
+.emoji-anguished {
background-position: -100px -60px;
}
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index 06a8694eb3d..c1c8bfffff7 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -62,7 +62,6 @@
@import 'framework/sortable';
@import 'framework/ci_variable_list';
@import 'framework/feature_highlight';
-@import 'framework/terms';
@import 'framework/read_more';
@import 'framework/flex_grid';
@import 'framework/system_messages';
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index df78543f96d..8f65f349cf9 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -146,13 +146,6 @@
* Blame file
*/
&.blame {
- //
- // IMPORTANT PERFORMANCE OPTIMIZATION
- //
- // When viewinng a blame with many commits a lot of content is rendered on the page.
- // The line below ensures that we only render what is visible to the user, thus reducing TBT in the browser.
- content-visibility: auto;
-
table {
border: 0;
margin: 0;
@@ -167,12 +160,6 @@
}
td {
- //
- // IMPORTANT PERFORMANCE OPTIMIZATION
- //
- // When viewinng a blame with many commits a lot of content is rendered on the page.
- // The line below ensures that we only render what is visible to the user, thus reducing TBT in the browser.
- content-visibility: auto;
border-top: 0;
border-bottom: 0;
@@ -235,6 +222,25 @@
color: $gray-900;
}
}
+
+ //
+ // IMPORTANT PERFORMANCE OPTIMIZATION
+ //
+ // When viewinng a blame with many commits a lot of content is rendered on the page.
+ // content-visibility rules below ensure that we only render what is visible to the user, thus reducing TBT in the browser.
+ .commit {
+ content-visibility: auto;
+ contain-intrinsic-size: 1px 3em;
+ }
+
+ code .line {
+ content-visibility: auto;
+ contain-intrinsic-size: 1px 1.1875rem;
+ }
+
+ .line-numbers {
+ content-visibility: auto;
+ }
}
&.logs {
diff --git a/app/assets/stylesheets/framework/kbd.scss b/app/assets/stylesheets/framework/kbd.scss
index 05991bc16fd..7dd0ae47834 100644
--- a/app/assets/stylesheets/framework/kbd.scss
+++ b/app/assets/stylesheets/framework/kbd.scss
@@ -12,4 +12,20 @@ kbd {
border-image: none;
border-radius: 3px;
box-shadow: 0 -1px 0 var(--gray-200, $gray-200) inset;
+
+ &.flat {
+ color: $code-color;
+ background-color: $gray-100;
+ border-color: var(--gray-10, $gray-10) var(--gray-10, $gray-10) var(--gray-50, $gray-50);
+ box-shadow: none;
+ border-radius: $border-radius-default;
+ font-family: $monospace-font;
+ font-size: $gl-font-size-small;
+ line-height: 1;
+ white-space: pre-wrap;
+ // Safari
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ word-break: keep-all;
+ }
}
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index ef294635641..9b04b9a2612 100644
--- a/app/assets/stylesheets/framework/markdown_area.scss
+++ b/app/assets/stylesheets/framework/markdown_area.scss
@@ -82,11 +82,11 @@
.nav-links {
li.md-header-toolbar {
margin-left: auto;
- display: none;
+ visibility: hidden;
padding-bottom: $gl-padding-8;
&.active {
- display: block;
+ visibility: visible;
@include media-breakpoint-down(xs) {
flex: none;
@@ -116,7 +116,7 @@
}
.md-preview-holder {
- min-height: 167px;
+ min-height: 172px;
padding: 10px 0;
overflow-x: auto;
}
diff --git a/app/assets/stylesheets/framework/terms.scss b/app/assets/stylesheets/framework/terms.scss
deleted file mode 100644
index b07d6023127..00000000000
--- a/app/assets/stylesheets/framework/terms.scss
+++ /dev/null
@@ -1,60 +0,0 @@
-.terms {
- .with-performance-bar & {
- margin-top: 0;
- }
-
- .alert-wrapper {
- min-height: $header-height + $gl-padding;
- }
-
- .content {
- padding-top: $gl-padding;
- }
-
- .card {
- .card-header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- line-height: $line-height-base;
-
- .logo-text {
- width: 55px;
- height: 24px;
- display: flex;
- flex-direction: column;
- justify-content: center;
- }
-
- .navbar-collapse {
- padding-right: 0;
- flex-grow: 0;
- flex-basis: auto;
-
- .navbar-nav {
- margin: 0;
- }
- }
-
- .nav li {
- float: none;
- }
- }
-
- .panel-content {
- padding: $gl-padding;
-
- *:first-child {
- margin-top: 0;
- }
-
- *:last-child {
- margin-bottom: 0;
- }
- }
-
- .footer-block {
- margin: 0;
- }
- }
-}
diff --git a/app/assets/stylesheets/highlight/common.scss b/app/assets/stylesheets/highlight/common.scss
index 8270db9966e..fb4266a2f41 100644
--- a/app/assets/stylesheets/highlight/common.scss
+++ b/app/assets/stylesheets/highlight/common.scss
@@ -96,9 +96,10 @@
}
@mixin line-number-link($color) {
+ min-width: $gl-spacing-scale-9;
+
&::before {
- @include gl-visibility-hidden;
- @include gl-display-inline-block;
+ @include gl-display-none;
@include gl-align-self-center;
@include gl-mt-2;
@include gl-mr-2;
@@ -114,10 +115,10 @@
}
&:hover::before {
- @include gl-visibility-visible;
+ @include gl-display-inline-block;
}
&:focus::before {
- @include gl-visibility-visible;
+ @include gl-display-inline-block;
}
}
diff --git a/app/assets/stylesheets/mailer.scss b/app/assets/stylesheets/mailer.scss
index 3220510775c..5f50489555b 100644
--- a/app/assets/stylesheets/mailer.scss
+++ b/app/assets/stylesheets/mailer.scss
@@ -143,6 +143,10 @@ table.content {
line-height: 1.4;
padding: 15px 5px;
text-align: center;
+
+ ul.list-style-position-inside {
+ list-style-position: inside;
+ }
}
td.mailer-align-left {
diff --git a/app/assets/stylesheets/page_bundles/boards.scss b/app/assets/stylesheets/page_bundles/boards.scss
index a3ec2167b13..d4c59a6ab0c 100644
--- a/app/assets/stylesheets/page_bundles/boards.scss
+++ b/app/assets/stylesheets/page_bundles/boards.scss
@@ -470,6 +470,10 @@
.labels-select-wrapper.is-embedded .labels-select-wrapper.is-embedded {
width: auto;
}
+
+ .show.dropdown .dropdown-menu {
+ @include gl-w-full;
+ }
}
.board-header-collapsed-info-icon:hover {
diff --git a/app/assets/stylesheets/page_bundles/jira_connect.scss b/app/assets/stylesheets/page_bundles/jira_connect.scss
index 4beb5edbe7b..9fe0490571e 100644
--- a/app/assets/stylesheets/page_bundles/jira_connect.scss
+++ b/app/assets/stylesheets/page_bundles/jira_connect.scss
@@ -42,8 +42,6 @@ $header-height: 40px;
.jira-connect-app-body {
max-width: 768px;
- margin-left: auto;
- margin-right: auto;
}
// needed for external_link
diff --git a/app/assets/stylesheets/page_bundles/terms.scss b/app/assets/stylesheets/page_bundles/terms.scss
new file mode 100644
index 00000000000..8eb66e58aed
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/terms.scss
@@ -0,0 +1,64 @@
+@import 'mixins_and_variables_and_functions';
+
+.terms {
+ .with-system-header &,
+ .with-system-header.with-performance-bar &,
+ .with-performance-bar & {
+ margin-top: 0;
+ }
+
+ .terms-fade {
+ background: linear-gradient(0deg, $white 0%, rgba($white, 0.5) 100%);
+ }
+
+ .content {
+ padding-top: $gl-padding;
+ }
+
+ .gl-card {
+ .gl-card-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ line-height: $line-height-base;
+
+ .logo-text {
+ width: 55px;
+ height: 24px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ }
+
+ .navbar-collapse {
+ padding-right: 0;
+ flex-grow: 0;
+ flex-basis: auto;
+
+ .navbar-nav {
+ margin: 0;
+ }
+ }
+
+ .nav li {
+ float: none;
+ }
+ }
+
+ .panel-content {
+ padding: $gl-padding;
+
+ *:first-child {
+ margin-top: 0;
+ }
+
+ *:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ .footer-block {
+ margin: 0;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/pages/clusters.scss b/app/assets/stylesheets/pages/clusters.scss
index de27ca2e5e8..b450bca4f41 100644
--- a/app/assets/stylesheets/pages/clusters.scss
+++ b/app/assets/stylesheets/pages/clusters.scss
@@ -1,9 +1,13 @@
.clusters-container {
- .empty-state .svg-content img {
- width: 145px;
+ .empty-state .svg-content {
+ @include gl-pb-0;
+
+ img {
+ width: 100px;
+ }
}
- .empty-state--agent {
+ .agents-empty-state {
.text-content {
@include gl-max-w-full;
@include media-breakpoint-up(lg) {
@@ -16,4 +20,23 @@
@include gl-flex-wrap;
}
}
+
+ .gl-card-body {
+ @include media-breakpoint-up(sm) {
+ @include gl-pt-2;
+ min-height: 372px;
+ }
+ }
+
+ @include media-breakpoint-down(xs) {
+ .nav-controls {
+ @include gl-w-full;
+ order: -1;
+
+ .gl-new-dropdown,
+ .split-content-button {
+ @include gl-w-full;
+ }
+ }
+ }
}
diff --git a/app/assets/stylesheets/pages/deploy_keys.scss b/app/assets/stylesheets/pages/deploy_keys.scss
index 2fafe052106..997e42a8fd5 100644
--- a/app/assets/stylesheets/pages/deploy_keys.scss
+++ b/app/assets/stylesheets/pages/deploy_keys.scss
@@ -1,12 +1,3 @@
-.deploy-keys-list {
- width: 100%;
- overflow: auto;
-
- table {
- border: 1px solid $table-border-color;
- }
-}
-
.deploy-keys-title {
padding-bottom: 2px;
line-height: 2;
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index c597d2dd8da..cf5e93e94a2 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -179,6 +179,7 @@
}
.block,
+ .sidebar-contained-width,
.issuable-sidebar-header {
@include clearfix;
padding: $gl-padding 0;
@@ -317,6 +318,7 @@
padding: 0;
.block,
+ .sidebar-contained-width,
.issuable-sidebar-header {
width: $gutter-collapsed-width - 2px;
padding: 0;
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index cec8d8a29cc..3b86750c6ca 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -269,7 +269,9 @@ $tabs-holder-z-index: 250;
}
.mr-widget-body {
- line-height: 28px;
+ &:not(.mr-widget-body-line-height-1) {
+ line-height: 28px;
+ }
@include clearfix;
diff --git a/app/assets/stylesheets/startup/_cloaking.scss b/app/assets/stylesheets/startup/_cloaking.scss
index 3c25feb0c5c..f60d72a51fb 100644
--- a/app/assets/stylesheets/startup/_cloaking.scss
+++ b/app/assets/stylesheets/startup/_cloaking.scss
@@ -2,6 +2,8 @@
Prevent flashing of content when using startup.css
*/
@mixin cloak-startup-scss($display) {
+ // General selector for cloaking until ready
+ .cloak-startup,
// Breadcrumbs and alerts on the top of the page
.content-wrapper > .alert-wrapper,
// Content on pages
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
index d436c328921..efa4b04ee62 100644
--- a/app/assets/stylesheets/startup/startup-dark.scss
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -5,6 +5,7 @@
body.gl-dark {
--gray-50: #303030;
--gray-100: #404040;
+ --gray-600: #bfbfbf;
--gray-900: #fafafa;
--gray-950: #fff;
--green-100: #0d532a;
@@ -12,6 +13,7 @@ body.gl-dark {
--green-700: #91d4a8;
--blue-400: #1f75cb;
--orange-400: #ab6100;
+ --indigo-900-alpha-008: rgba(235, 235, 250, 0.08);
--gl-text-color: #fafafa;
--border-color: #4f4f4f;
--black: #fff;
@@ -1693,9 +1695,15 @@ body.gl-dark {
--black: #fff;
--svg-status-bg: #333;
}
+.nav-sidebar li a {
+ color: var(--gray-600);
+}
.nav-sidebar li.active {
box-shadow: none;
}
+.nav-sidebar li.active:not(.fly-out-top-item) > a:not(.has-sub-items) {
+ background-color: var(--indigo-900-alpha-008);
+}
body.gl-dark .navbar-gitlab {
background-color: #fafafa;
}
@@ -1780,7 +1788,7 @@ body.gl-dark .search .search-input-wrap .clear-icon {
fill: rgba(250, 250, 250, 0.8);
}
body.gl-dark .nav-sidebar li.active > a {
- color: #f0f0f0;
+ color: #fafafa;
}
body.gl-dark .nav-sidebar .fly-out-top-item a,
body.gl-dark .nav-sidebar .fly-out-top-item.active a,
@@ -1935,7 +1943,7 @@ body.gl-dark {
.gl-display-none {
display: none;
}
-@media (min-width: 36rem) {
+@media (min-width: 576px) {
.gl-sm-display-block {
display: block;
}
diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss
index 40026c95a15..977f994dc78 100644
--- a/app/assets/stylesheets/startup/startup-general.scss
+++ b/app/assets/stylesheets/startup/startup-general.scss
@@ -1621,7 +1621,7 @@ svg.s16 {
.gl-display-none {
display: none;
}
-@media (min-width: 36rem) {
+@media (min-width: 576px) {
.gl-sm-display-block {
display: block;
}
diff --git a/app/assets/stylesheets/startup/startup-signin.scss b/app/assets/stylesheets/startup/startup-signin.scss
index 8d7531d6c9c..3daeeb30082 100644
--- a/app/assets/stylesheets/startup/startup-signin.scss
+++ b/app/assets/stylesheets/startup/startup-signin.scss
@@ -776,7 +776,7 @@ svg {
.gl-mb-5 {
margin-bottom: 1rem;
}
-@media (min-width: 36rem) {
+@media (min-width: 576px) {
.gl-sm-mt-0 {
margin-top: 0;
}
diff --git a/app/assets/stylesheets/themes/dark_mode_overrides.scss b/app/assets/stylesheets/themes/dark_mode_overrides.scss
index b77048174c9..2b5751cab36 100644
--- a/app/assets/stylesheets/themes/dark_mode_overrides.scss
+++ b/app/assets/stylesheets/themes/dark_mode_overrides.scss
@@ -42,8 +42,24 @@
}
.nav-sidebar {
- li.active {
- box-shadow: none;
+ li {
+ a {
+ color: var(--gray-600);
+ }
+
+ > a:hover {
+ background-color: var(--indigo-900-alpha-008);
+ }
+
+ &.active {
+ box-shadow: none;
+
+ &:not(.fly-out-top-item) {
+ > a:not(.has-sub-items) {
+ background-color: var(--indigo-900-alpha-008);
+ }
+ }
+ }
}
.sidebar-sub-level-items.fly-out-list {
@@ -53,7 +69,7 @@
}
body.gl-dark {
- @include gitlab-theme($gray-900, $gray-400, $gray-500, $gray-800, $gray-900, $white);
+ @include gitlab-theme($gray-900, $gray-400, $gray-500, $gray-900, $gray-900, $white);
.logo-text svg {
fill: var(--gl-text-color);
diff --git a/app/assets/stylesheets/themes/theme_blue.scss b/app/assets/stylesheets/themes/theme_blue.scss
index 9f9802f77f4..817557f37cd 100644
--- a/app/assets/stylesheets/themes/theme_blue.scss
+++ b/app/assets/stylesheets/themes/theme_blue.scss
@@ -6,7 +6,7 @@ body {
$theme-blue-200,
$theme-blue-500,
$theme-blue-700,
- $theme-blue-800,
+ $gray-900,
$theme-blue-900,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_dark.scss b/app/assets/stylesheets/themes/theme_dark.scss
index e6db6cd2a5e..4c52cdc30df 100644
--- a/app/assets/stylesheets/themes/theme_dark.scss
+++ b/app/assets/stylesheets/themes/theme_dark.scss
@@ -6,7 +6,7 @@ body {
$gray-200,
$gray-300,
$gray-500,
- $gray-700,
+ $gray-900,
$gray-900,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_green.scss b/app/assets/stylesheets/themes/theme_green.scss
index 6dcad6e1301..7e387e97452 100644
--- a/app/assets/stylesheets/themes/theme_green.scss
+++ b/app/assets/stylesheets/themes/theme_green.scss
@@ -6,7 +6,7 @@ body {
$theme-green-200,
$theme-green-500,
$theme-green-700,
- $theme-green-800,
+ $gray-900,
$theme-green-900,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_indigo.scss b/app/assets/stylesheets/themes/theme_indigo.scss
index 9566c9c6004..3bf6cfea650 100644
--- a/app/assets/stylesheets/themes/theme_indigo.scss
+++ b/app/assets/stylesheets/themes/theme_indigo.scss
@@ -6,7 +6,7 @@ body {
$indigo-200,
$indigo-500,
$indigo-700,
- $purple-900,
+ $gray-900,
$indigo-900,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_light.scss b/app/assets/stylesheets/themes/theme_light.scss
index 4c3bc1b2298..f2fdd499781 100644
--- a/app/assets/stylesheets/themes/theme_light.scss
+++ b/app/assets/stylesheets/themes/theme_light.scss
@@ -6,7 +6,7 @@ body {
$gray-500,
$gray-700,
$gray-500,
- $gray-500,
+ $gray-900,
$gray-50,
$gray-500
);
diff --git a/app/assets/stylesheets/themes/theme_light_blue.scss b/app/assets/stylesheets/themes/theme_light_blue.scss
index 07d1c60a4c6..771a84911b3 100644
--- a/app/assets/stylesheets/themes/theme_light_blue.scss
+++ b/app/assets/stylesheets/themes/theme_light_blue.scss
@@ -6,7 +6,7 @@ body {
$theme-light-blue-200,
$theme-light-blue-500,
$theme-light-blue-500,
- $theme-light-blue-700,
+ $gray-900,
$theme-light-blue-700,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_light_green.scss b/app/assets/stylesheets/themes/theme_light_green.scss
index e122501b93c..8c991a7bfb3 100644
--- a/app/assets/stylesheets/themes/theme_light_green.scss
+++ b/app/assets/stylesheets/themes/theme_light_green.scss
@@ -6,7 +6,7 @@ body {
$theme-green-200,
$theme-green-500,
$theme-green-500,
- $theme-light-green-700,
+ $gray-900,
$theme-light-green-700,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_light_indigo.scss b/app/assets/stylesheets/themes/theme_light_indigo.scss
index 5b607238ed9..6c220e0459a 100644
--- a/app/assets/stylesheets/themes/theme_light_indigo.scss
+++ b/app/assets/stylesheets/themes/theme_light_indigo.scss
@@ -6,7 +6,7 @@ body {
$indigo-200,
$indigo-500,
$indigo-500,
- $indigo-700,
+ $gray-900,
$indigo-700,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_light_red.scss b/app/assets/stylesheets/themes/theme_light_red.scss
index fd3980183f3..e1a715293b4 100644
--- a/app/assets/stylesheets/themes/theme_light_red.scss
+++ b/app/assets/stylesheets/themes/theme_light_red.scss
@@ -6,7 +6,7 @@ body {
$theme-light-red-200,
$theme-light-red-500,
$theme-light-red-500,
- $theme-light-red-700,
+ $gray-900,
$theme-light-red-700,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_red.scss b/app/assets/stylesheets/themes/theme_red.scss
index fa5ecc09f50..19fd150727d 100644
--- a/app/assets/stylesheets/themes/theme_red.scss
+++ b/app/assets/stylesheets/themes/theme_red.scss
@@ -6,7 +6,7 @@ body {
$theme-red-200,
$theme-red-500,
$theme-red-700,
- $theme-red-800,
+ $gray-900,
$theme-red-900,
$white
);
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index ec70926b418..7e46f16e1d0 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -281,3 +281,19 @@ $gl-line-height-42: px-to-rem(42px);
display: none;
}
}
+
+// Will both be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1465
+.gl-text-transparent {
+ color: transparent;
+}
+
+.gl-focus-ring-border-1-gray-900\! {
+ @include gl-focus($gl-border-size-1, $gray-900, true);
+}
+
+// Will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2476
+.gl-md-max-w-50p {
+ @include gl-media-breakpoint-up(md) {
+ max-width: 50%;
+ }
+}
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 8039fac02ec..8644d95b96c 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -98,7 +98,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
# Specs are in spec/requests/self_monitoring_project_spec.rb
def create_self_monitoring_project
- job_id = SelfMonitoringProjectCreateWorker.perform_async # rubocop:disable CodeReuse/Worker
+ job_id = SelfMonitoringProjectCreateWorker.with_status.perform_async # rubocop:disable CodeReuse/Worker
render status: :accepted, json: {
job_id: job_id,
@@ -137,7 +137,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
# Specs are in spec/requests/self_monitoring_project_spec.rb
def delete_self_monitoring_project
- job_id = SelfMonitoringProjectDeleteWorker.perform_async # rubocop:disable CodeReuse/Worker
+ job_id = SelfMonitoringProjectDeleteWorker.with_status.perform_async # rubocop:disable CodeReuse/Worker
render status: :accepted, json: {
job_id: job_id,
diff --git a/app/controllers/admin/applications_controller.rb b/app/controllers/admin/applications_controller.rb
index ce7d64336c8..83413afb6b7 100644
--- a/app/controllers/admin/applications_controller.rb
+++ b/app/controllers/admin/applications_controller.rb
@@ -15,6 +15,7 @@ class Admin::ApplicationsController < Admin::ApplicationController
end
def show
+ @created = get_created_session
end
def new
@@ -33,6 +34,8 @@ class Admin::ApplicationsController < Admin::ApplicationController
if @application.persisted?
flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
+ set_created_session
+
redirect_to admin_application_url(@application)
else
render :new
diff --git a/app/controllers/admin/hook_logs_controller.rb b/app/controllers/admin/hook_logs_controller.rb
index 444ad17f86d..aa13673095d 100644
--- a/app/controllers/admin/hook_logs_controller.rb
+++ b/app/controllers/admin/hook_logs_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Admin::HookLogsController < Admin::ApplicationController
- include HooksExecution
+ include ::Integrations::HooksExecution
before_action :hook, only: [:show, :retry]
before_action :hook_log, only: [:show, :retry]
@@ -9,6 +9,7 @@ class Admin::HookLogsController < Admin::ApplicationController
respond_to :html
feature_category :integrations
+ urgency :low, [:retry]
def show
end
diff --git a/app/controllers/admin/hooks_controller.rb b/app/controllers/admin/hooks_controller.rb
index ca24f671b9d..6f5475a4a78 100644
--- a/app/controllers/admin/hooks_controller.rb
+++ b/app/controllers/admin/hooks_controller.rb
@@ -1,14 +1,15 @@
# frozen_string_literal: true
class Admin::HooksController < Admin::ApplicationController
- include HooksExecution
+ include ::Integrations::HooksExecution
before_action :hook_logs, only: :edit
feature_category :integrations
+ urgency :low, [:test]
def index
- @hooks = SystemHook.all
+ @hooks = SystemHook.all.load
@hook = SystemHook.new
end
diff --git a/app/controllers/admin/integrations_controller.rb b/app/controllers/admin/integrations_controller.rb
index a3eb24b9b6f..ad0ee0b2cef 100644
--- a/app/controllers/admin/integrations_controller.rb
+++ b/app/controllers/admin/integrations_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Admin::IntegrationsController < Admin::ApplicationController
- include IntegrationsActions
+ include ::Integrations::Actions
before_action :not_found, unless: -> { instance_level_integrations? }
diff --git a/app/controllers/admin/labels_controller.rb b/app/controllers/admin/labels_controller.rb
index 6cc11b40de0..822b7a93c9c 100644
--- a/app/controllers/admin/labels_controller.rb
+++ b/app/controllers/admin/labels_controller.rb
@@ -3,7 +3,7 @@
class Admin::LabelsController < Admin::ApplicationController
before_action :set_label, only: [:show, :edit, :update, :destroy]
- feature_category :issue_tracking
+ feature_category :team_planning
def index
@labels = Label.templates.page(params[:page])
diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb
index 8c74352a179..9312651b8bf 100644
--- a/app/controllers/admin/runners_controller.rb
+++ b/app/controllers/admin/runners_controller.rb
@@ -8,7 +8,6 @@ class Admin::RunnersController < Admin::ApplicationController
feature_category :runner
def index
- @active_runners_count = Ci::Runner.online.count
end
def show
@@ -86,9 +85,12 @@ class Admin::RunnersController < Admin::ApplicationController
Project.all
end
- @projects = @projects.where.not(id: runner.projects.select(:id)) if runner.projects.any?
- @projects = @projects.inc_routes
- @projects = @projects.page(params[:page]).per(30).without_count
+ ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659') do
+ @projects = @projects.where.not(id: runner.projects.select(:id)) if runner.projects.any?
+ @projects = @projects.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
+ @projects = @projects.inc_routes
+ @projects = @projects.page(params[:page]).per(30).without_count
+ end
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index b22167a3952..3af1afab06e 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -163,7 +163,8 @@ class ApplicationController < ActionController::Base
payload[Labkit::Correlation::CorrelationId::LOG_KEY] = Labkit::Correlation::CorrelationId.current_id
payload[:metadata] = @current_context
-
+ payload[:request_urgency] = urgency&.name
+ payload[:target_duration_s] = urgency&.duration
logged_user = auth_user
if logged_user.present?
payload[:user_id] = logged_user.try(:id)
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 1c07245da08..5cb5690d72d 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -5,7 +5,7 @@ class AutocompleteController < ApplicationController
feature_category :users, [:users, :user]
feature_category :projects, [:projects]
- feature_category :issue_tracking, [:award_emojis]
+ feature_category :team_planning, [:award_emojis]
feature_category :code_review, [:merge_request_target_branches]
feature_category :continuous_delivery, [:deploy_keys_with_owners]
diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb
index 7dea6191fa4..e7ae941886d 100644
--- a/app/controllers/boards/issues_controller.rb
+++ b/app/controllers/boards/issues_controller.rb
@@ -21,7 +21,7 @@ module Boards
before_action :validate_id_list, only: [:bulk_move]
before_action :can_move_issues?, only: [:bulk_move]
- feature_category :boards
+ feature_category :team_planning
def index
list_service = Boards::Issues::ListService.new(board_parent, current_user, filter_params)
diff --git a/app/controllers/boards/lists_controller.rb b/app/controllers/boards/lists_controller.rb
index 8ab8337a3ad..696b251301f 100644
--- a/app/controllers/boards/lists_controller.rb
+++ b/app/controllers/boards/lists_controller.rb
@@ -8,7 +8,7 @@ module Boards
before_action :authorize_read_list, only: [:index]
skip_before_action :authenticate_user!, only: [:index]
- feature_category :boards
+ feature_category :team_planning
def index
lists = Boards::Lists::ListService.new(board.resource_parent, current_user).execute(board)
diff --git a/app/controllers/concerns/gitlab_recaptcha.rb b/app/controllers/concerns/gitlab_recaptcha.rb
new file mode 100644
index 00000000000..15e856463ea
--- /dev/null
+++ b/app/controllers/concerns/gitlab_recaptcha.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module GitlabRecaptcha
+ extend ActiveSupport::Concern
+ include Recaptcha::Verify
+ include RecaptchaHelper
+
+ def load_recaptcha
+ recaptcha_enabled? && Gitlab::Recaptcha.load_configurations!
+ end
+
+ def check_recaptcha
+ return unless load_recaptcha
+ return if verify_recaptcha
+
+ flash[:alert] = _('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.')
+ flash.delete :recaptcha_error
+
+ self.resource = resource_class.new
+ render action: 'new'
+ end
+end
diff --git a/app/controllers/concerns/group_tree.rb b/app/controllers/concerns/group_tree.rb
index 35c1f358a77..e02a766d2b9 100644
--- a/app/controllers/concerns/group_tree.rb
+++ b/app/controllers/concerns/group_tree.rb
@@ -38,13 +38,7 @@ module GroupTree
#
# Pagination needs to be applied before loading the ancestors to
# make sure ancestors are not cut off by pagination.
- filtered_groups_relation = Group.where(id: filtered_groups.select(:id))
-
- if Feature.enabled?(:linear_group_tree_ancestor_scopes, current_user, default_enabled: :yaml)
- filtered_groups_relation.self_and_ancestors
- else
- Gitlab::ObjectHierarchy.new(filtered_groups_relation).base_and_ancestors
- end
+ Group.where(id: filtered_groups.select(:id)).self_and_ancestors
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/controllers/concerns/hooks_execution.rb b/app/controllers/concerns/hooks_execution.rb
deleted file mode 100644
index 87d215f50e7..00000000000
--- a/app/controllers/concerns/hooks_execution.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-module HooksExecution
- extend ActiveSupport::Concern
-
- private
-
- def destroy_hook(hook)
- result = WebHooks::DestroyService.new(current_user).execute(hook)
-
- if result[:status] == :success
- flash[:notice] =
- if result[:async]
- _("%{hook_type} was scheduled for deletion") % { hook_type: hook.model_name.human }
- else
- _("%{hook_type} was deleted") % { hook_type: hook.model_name.human }
- end
- else
- flash[:alert] = result[:message]
- end
- end
-
- def set_hook_execution_notice(result)
- http_status = result[:http_status]
- message = result[:message]
-
- if http_status && http_status >= 200 && http_status < 400
- flash[:notice] = "Hook executed successfully: HTTP #{http_status}"
- elsif http_status
- flash[:alert] = "Hook executed successfully but returned HTTP #{http_status} #{message}"
- else
- flash[:alert] = "Hook execution failed: #{message}"
- end
- end
-
- def create_rate_limit(key, scope)
- if rate_limiter.throttled?(key, scope: [scope, current_user])
- rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user)
-
- render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests
- end
- end
-
- def rate_limiter
- ::Gitlab::ApplicationRateLimiter
- end
-end
diff --git a/app/controllers/concerns/integrations/actions.rb b/app/controllers/concerns/integrations/actions.rb
new file mode 100644
index 00000000000..6490742c0f8
--- /dev/null
+++ b/app/controllers/concerns/integrations/actions.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+module Integrations::Actions
+ extend ActiveSupport::Concern
+
+ included do
+ include Integrations::Params
+ include IntegrationsHelper
+
+ before_action :integration, only: [:edit, :update, :overrides, :test]
+
+ urgency :low, [:test]
+ end
+
+ def edit
+ render 'shared/integrations/edit'
+ end
+
+ def update
+ saved = integration.update(integration_params[:integration])
+
+ respond_to do |format|
+ format.html do
+ if saved
+ PropagateIntegrationWorker.perform_async(integration.id)
+ redirect_to scoped_edit_integration_path(integration), notice: success_message
+ else
+ render 'shared/integrations/edit'
+ end
+ end
+
+ format.json do
+ status = saved ? :ok : :unprocessable_entity
+
+ render json: serialize_as_json, status: status
+ end
+ end
+ end
+
+ def test
+ render json: {}, status: :ok
+ end
+
+ def reset
+ integration.destroy!
+
+ flash[:notice] = s_('Integrations|This integration, and inheriting projects were reset.')
+
+ render json: {}, status: :ok
+ end
+
+ private
+
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ def integration
+ @integration ||= find_or_initialize_non_project_specific_integration(params[:id])
+ end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
+
+ def success_message
+ if integration.active?
+ s_('Integrations|%{integration} settings saved and active.') % { integration: integration.title }
+ else
+ s_('Integrations|%{integration} settings saved, but not active.') % { integration: integration.title }
+ end
+ end
+
+ def serialize_as_json
+ integration
+ .as_json(only: integration.json_fields)
+ .merge(errors: integration.errors.as_json)
+ end
+end
diff --git a/app/controllers/concerns/integrations/hooks_execution.rb b/app/controllers/concerns/integrations/hooks_execution.rb
new file mode 100644
index 00000000000..af039057a9c
--- /dev/null
+++ b/app/controllers/concerns/integrations/hooks_execution.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Integrations::HooksExecution
+ extend ActiveSupport::Concern
+
+ private
+
+ def destroy_hook(hook)
+ result = WebHooks::DestroyService.new(current_user).execute(hook)
+
+ if result[:status] == :success
+ flash[:notice] =
+ if result[:async]
+ _("%{hook_type} was scheduled for deletion") % { hook_type: hook.model_name.human }
+ else
+ _("%{hook_type} was deleted") % { hook_type: hook.model_name.human }
+ end
+ else
+ flash[:alert] = result[:message]
+ end
+ end
+
+ def set_hook_execution_notice(result)
+ http_status = result[:http_status]
+ message = result[:message]
+
+ if http_status && http_status >= 200 && http_status < 400
+ flash[:notice] = "Hook executed successfully: HTTP #{http_status}"
+ elsif http_status
+ flash[:alert] = "Hook executed successfully but returned HTTP #{http_status} #{message}"
+ else
+ flash[:alert] = "Hook execution failed: #{message}"
+ end
+ end
+
+ def create_rate_limit(key, scope)
+ if rate_limiter.throttled?(key, scope: [scope, current_user])
+ rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user)
+
+ render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests
+ end
+ end
+
+ def rate_limiter
+ ::Gitlab::ApplicationRateLimiter
+ end
+end
diff --git a/app/controllers/concerns/integrations/params.rb b/app/controllers/concerns/integrations/params.rb
index 62585ab95af..201fb1dc83f 100644
--- a/app/controllers/concerns/integrations/params.rb
+++ b/app/controllers/concerns/integrations/params.rb
@@ -9,6 +9,7 @@ module Integrations
:add_pusher,
:alert_events,
:api_key,
+ :api_token,
:api_url,
:bamboo_url,
:branches_to_be_notified,
@@ -74,7 +75,8 @@ module Integrations
:url,
:user_key,
:username,
- :webhook
+ :webhook,
+ :zentao_product_xid
].freeze
def integration_params
diff --git a/app/controllers/concerns/integrations_actions.rb b/app/controllers/concerns/integrations_actions.rb
deleted file mode 100644
index dd066cc1b02..00000000000
--- a/app/controllers/concerns/integrations_actions.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-module IntegrationsActions
- extend ActiveSupport::Concern
-
- included do
- include Integrations::Params
- include IntegrationsHelper
-
- before_action :integration, only: [:edit, :update, :overrides, :test]
- end
-
- def edit
- render 'shared/integrations/edit'
- end
-
- def update
- saved = integration.update(integration_params[:integration])
-
- respond_to do |format|
- format.html do
- if saved
- PropagateIntegrationWorker.perform_async(integration.id)
- redirect_to scoped_edit_integration_path(integration), notice: success_message
- else
- render 'shared/integrations/edit'
- end
- end
-
- format.json do
- status = saved ? :ok : :unprocessable_entity
-
- render json: serialize_as_json, status: status
- end
- end
- end
-
- def test
- render json: {}, status: :ok
- end
-
- def reset
- integration.destroy!
-
- flash[:notice] = s_('Integrations|This integration, and inheriting projects were reset.')
-
- render json: {}, status: :ok
- end
-
- private
-
- # rubocop:disable Gitlab/ModuleWithInstanceVariables
- def integration
- @integration ||= find_or_initialize_non_project_specific_integration(params[:id])
- end
- # rubocop:enable Gitlab/ModuleWithInstanceVariables
-
- def success_message
- if integration.active?
- s_('Integrations|%{integration} settings saved and active.') % { integration: integration.title }
- else
- s_('Integrations|%{integration} settings saved, but not active.') % { integration: integration.title }
- end
- end
-
- def serialize_as_json
- integration
- .as_json(only: integration.json_fields)
- .merge(errors: integration.errors.as_json)
- end
-end
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index e1e662a1968..2d7fbb78209 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -149,8 +149,20 @@ module IssuableActions
.includes(:noteable)
.fresh
+ if paginated_discussions
+ paginated_discussions_by_type = paginated_discussions.records.group_by(&:table_name)
+
+ notes = if paginated_discussions_by_type['notes'].present?
+ notes.with_discussion_ids(paginated_discussions_by_type['notes'].map(&:discussion_id))
+ else
+ notes.none
+ end
+
+ response.headers['X-Next-Page-Cursor'] = paginated_discussions.cursor_for_next_page if paginated_discussions.has_next_page?
+ end
+
if notes_filter != UserPreference::NOTES_FILTERS[:only_comments]
- notes = ResourceEvents::MergeIntoNotesService.new(issuable, current_user).execute(notes)
+ notes = ResourceEvents::MergeIntoNotesService.new(issuable, current_user, paginated_notes: paginated_discussions_by_type).execute(notes)
end
notes = prepare_notes_for_rendering(notes)
@@ -159,9 +171,9 @@ module IssuableActions
discussions = Discussion.build_collection(notes, issuable)
if issuable.is_a?(MergeRequest)
- cache_context = [current_user&.cache_key, project.team.human_max_access(current_user&.id)].join(':')
-
- render_cached(discussions, with: discussion_serializer, cache_context: -> (_) { cache_context }, context: self)
+ render_cached(discussions, with: discussion_serializer, cache_context: -> (_) { discussion_cache_context }, context: self)
+ elsif issuable.is_a?(Issue)
+ render json: discussion_serializer.represent(discussions, context: self) if stale?(etag: [discussion_cache_context, discussions])
else
render json: discussion_serializer.represent(discussions, context: self)
end
@@ -170,6 +182,17 @@ module IssuableActions
private
+ def paginated_discussions
+ return if params[:per_page].blank?
+ return unless issuable.instance_of?(Issue) && Feature.enabled?(:paginated_issue_discussions, project, default_enabled: :yaml)
+
+ strong_memoize(:paginated_discussions) do
+ issuable
+ .discussion_root_note_ids(notes_filter: notes_filter)
+ .keyset_paginate(cursor: params[:cursor], per_page: params[:per_page].to_i)
+ end
+ end
+
def notes_filter
strong_memoize(:notes_filter) do
notes_filter_param = params[:notes_filter]&.to_i
@@ -197,6 +220,10 @@ module IssuableActions
current_user&.user_preference&.previous_changes&.any?
end
+ def discussion_cache_context
+ [current_user&.cache_key, project.team.human_max_access(current_user&.id)].join(':')
+ end
+
def discussion_serializer
DiscussionSerializer.new(project: project, noteable: issuable, current_user: current_user, note_entity: ProjectNoteEntity)
end
diff --git a/app/controllers/concerns/oauth_applications.rb b/app/controllers/concerns/oauth_applications.rb
index d2c746db12d..794307ebb0c 100644
--- a/app/controllers/concerns/oauth_applications.rb
+++ b/app/controllers/concerns/oauth_applications.rb
@@ -3,6 +3,8 @@
module OauthApplications
extend ActiveSupport::Concern
+ CREATED_SESSION_KEY = :oauth_applications_created
+
included do
before_action :prepare_scopes, only: [:create, :update]
end
@@ -15,6 +17,14 @@ module OauthApplications
end
end
+ def set_created_session
+ session[CREATED_SESSION_KEY] = true
+ end
+
+ def get_created_session
+ session.delete(CREATED_SESSION_KEY) || false
+ end
+
def load_scopes
@scopes ||= Doorkeeper.configuration.scopes
end
diff --git a/app/controllers/concerns/one_trust_csp.rb b/app/controllers/concerns/one_trust_csp.rb
index 4e98ec586ca..fbd44f52590 100644
--- a/app/controllers/concerns/one_trust_csp.rb
+++ b/app/controllers/concerns/one_trust_csp.rb
@@ -5,7 +5,7 @@ module OneTrustCSP
included do
content_security_policy do |policy|
- next if policy.directives.blank?
+ next unless helpers.one_trust_enabled? || policy.directives.present?
default_script_src = policy.directives['script-src'] || policy.directives['default-src']
script_src_values = Array.wrap(default_script_src) | ["'unsafe-eval'", 'https://cdn.cookielaw.org https://*.onetrust.com']
diff --git a/app/controllers/concerns/workhorse_authorization.rb b/app/controllers/concerns/workhorse_authorization.rb
index a290ba256b6..f9b85944307 100644
--- a/app/controllers/concerns/workhorse_authorization.rb
+++ b/app/controllers/concerns/workhorse_authorization.rb
@@ -26,7 +26,7 @@ module WorkhorseAuthorization
def file_is_valid?(file)
return false unless file.is_a?(::UploadedFile)
- file_extension_whitelist.include?(File.extname(file.original_filename).downcase.delete('.'))
+ file_extension_allowlist.include?(File.extname(file.original_filename).downcase.delete('.'))
end
def uploader_class
@@ -37,7 +37,7 @@ module WorkhorseAuthorization
raise NotImplementedError
end
- def file_extension_whitelist
- ImportExportUploader::EXTENSION_WHITELIST
+ def file_extension_allowlist
+ ImportExportUploader::EXTENSION_ALLOWLIST
end
end
diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb
index 0b833e149a4..6725e19df25 100644
--- a/app/controllers/confirmations_controller.rb
+++ b/app/controllers/confirmations_controller.rb
@@ -2,6 +2,10 @@
class ConfirmationsController < Devise::ConfirmationsController
include AcceptsPendingInvitations
+ include GitlabRecaptcha
+
+ prepend_before_action :check_recaptcha, only: :create
+ before_action :load_recaptcha, only: :new
feature_category :users
@@ -31,6 +35,12 @@ class ConfirmationsController < Devise::ConfirmationsController
end
end
+ def check_recaptcha
+ return unless resource_params[:email].present?
+
+ super
+ end
+
def after_sign_in(resource)
after_sign_in_path_for(resource)
end
diff --git a/app/controllers/dashboard/labels_controller.rb b/app/controllers/dashboard/labels_controller.rb
index b661efa12c0..d2f31258ecd 100644
--- a/app/controllers/dashboard/labels_controller.rb
+++ b/app/controllers/dashboard/labels_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Dashboard::LabelsController < Dashboard::ApplicationController
- feature_category :issue_tracking
+ feature_category :team_planning
def index
respond_to do |format|
diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb
index 1369e82a69b..34d9739d91c 100644
--- a/app/controllers/dashboard/milestones_controller.rb
+++ b/app/controllers/dashboard/milestones_controller.rb
@@ -4,7 +4,7 @@ class Dashboard::MilestonesController < Dashboard::ApplicationController
before_action :projects
before_action :groups, only: :index
- feature_category :issue_tracking
+ feature_category :team_planning
def index
respond_to do |format|
diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb
index 21bbb4d0c98..2c5e6817427 100644
--- a/app/controllers/dashboard/todos_controller.rb
+++ b/app/controllers/dashboard/todos_controller.rb
@@ -8,7 +8,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
before_action :authorize_read_group!, only: :index
before_action :find_todos, only: [:index, :destroy_all]
- feature_category :issue_tracking
+ feature_category :team_planning
def index
@sort = params[:sort]
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 227dd0591d4..8d7686a95fb 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -15,7 +15,7 @@ class DashboardController < Dashboard::ApplicationController
respond_to :html
feature_category :users, [:activity]
- feature_category :issue_tracking, [:issues, :issues_calendar]
+ feature_category :team_planning, [:issues, :issues_calendar]
feature_category :code_review, [:merge_requests]
def activity
diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb
index 3dc6a16cbc1..14dd2ae5691 100644
--- a/app/controllers/explore/projects_controller.rb
+++ b/app/controllers/explore/projects_controller.rb
@@ -68,6 +68,20 @@ class Explore::ProjectsController < Explore::ApplicationController
end
# rubocop: enable CodeReuse/ActiveRecord
+ def topics
+ load_project_counts
+ load_topics
+ end
+
+ def topic
+ load_topic
+
+ return render_404 unless @topic
+
+ params[:topic] = @topic.name
+ @projects = load_projects
+ end
+
private
def load_project_counts
@@ -86,6 +100,14 @@ class Explore::ProjectsController < Explore::ApplicationController
prepare_projects_for_rendering(projects)
end
+ def load_topics
+ @topics = Projects::TopicsFinder.new(params: params.permit(:search)).execute.page(params[:page]).without_count
+ end
+
+ def load_topic
+ @topic = Projects::Topic.find_by_name(params[:topic_name])
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def preload_associations(projects)
projects.includes(:route, :creator, :group, :project_feature, :topics, namespace: [:route, :owner])
diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb
index 0722a712b5c..fde0f133e53 100644
--- a/app/controllers/graphql_controller.rb
+++ b/app/controllers/graphql_controller.rb
@@ -188,6 +188,5 @@ class GraphqlController < ApplicationController
def logs
RequestStore.store[:graphql_logs].to_a
- .map { |log| log.except(:duration_s, :query_string) }
end
end
diff --git a/app/controllers/groups/autocomplete_sources_controller.rb b/app/controllers/groups/autocomplete_sources_controller.rb
index 5270a718952..82f8854bd2b 100644
--- a/app/controllers/groups/autocomplete_sources_controller.rb
+++ b/app/controllers/groups/autocomplete_sources_controller.rb
@@ -2,7 +2,7 @@
class Groups::AutocompleteSourcesController < Groups::ApplicationController
feature_category :subgroups, [:members]
- feature_category :issue_tracking, [:issues, :labels, :milestones, :commands]
+ feature_category :team_planning, [:issues, :labels, :milestones, :commands]
feature_category :code_review, [:merge_requests]
def members
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index e8e6a7e5c1a..3152c4d733f 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -12,9 +12,13 @@ class Groups::BoardsController < Groups::ApplicationController
push_frontend_feature_flag(:swimlanes_buffered_rendering, group, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, group, default_enabled: :yaml)
push_frontend_feature_flag(:labels_widget, group, default_enabled: :yaml)
+ experiment(:prominent_create_board_btn, subject: current_user) do |e|
+ e.use { }
+ e.try { }
+ end.run
end
- feature_category :boards
+ feature_category :team_planning
private
diff --git a/app/controllers/groups/crm_controller.rb b/app/controllers/groups/crm_controller.rb
new file mode 100644
index 00000000000..40661b09be6
--- /dev/null
+++ b/app/controllers/groups/crm_controller.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class Groups::CrmController < Groups::ApplicationController
+ feature_category :team_planning
+
+ before_action :authorize_read_crm_contact!, only: [:contacts]
+ before_action :authorize_read_crm_organization!, only: [:organizations]
+
+ def contacts
+ respond_to do |format|
+ format.html
+ end
+ end
+
+ def organizations
+ respond_to do |format|
+ format.html
+ end
+ end
+
+ private
+
+ def authorize_read_crm_contact!
+ render_404 unless can?(current_user, :read_crm_contact, group)
+ end
+
+ def authorize_read_crm_organization!
+ render_404 unless can?(current_user, :read_crm_organization, group)
+ end
+end
diff --git a/app/controllers/groups/dependency_proxy_for_containers_controller.rb b/app/controllers/groups/dependency_proxy_for_containers_controller.rb
index e19b8ae35f8..fc930ffebbd 100644
--- a/app/controllers/groups/dependency_proxy_for_containers_controller.rb
+++ b/app/controllers/groups/dependency_proxy_for_containers_controller.rb
@@ -11,8 +11,8 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy
before_action :ensure_token_granted!, only: [:blob, :manifest]
before_action :ensure_feature_enabled!
- before_action :verify_workhorse_api!, only: [:authorize_upload_blob, :upload_blob]
- skip_before_action :verify_authenticity_token, only: [:authorize_upload_blob, :upload_blob]
+ before_action :verify_workhorse_api!, only: [:authorize_upload_blob, :upload_blob, :authorize_upload_manifest, :upload_manifest]
+ skip_before_action :verify_authenticity_token, only: [:authorize_upload_blob, :upload_blob, :authorize_upload_manifest, :upload_manifest]
attr_reader :token
@@ -22,20 +22,11 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy
result = DependencyProxy::FindOrCreateManifestService.new(group, image, tag, token).execute
if result[:status] == :success
- response.headers['Docker-Content-Digest'] = result[:manifest].digest
- response.headers['Content-Length'] = result[:manifest].size
- response.headers['Docker-Distribution-Api-Version'] = DependencyProxy::DISTRIBUTION_API_VERSION
- response.headers['Etag'] = "\"#{result[:manifest].digest}\""
- content_type = result[:manifest].content_type
-
- event_name = tracking_event_name(object_type: :manifest, from_cache: result[:from_cache])
- track_package_event(event_name, :dependency_proxy, namespace: group, user: auth_user)
- send_upload(
- result[:manifest].file,
- proxy: true,
- redirect_params: { query: { 'response-content-type' => content_type } },
- send_params: { type: content_type }
- )
+ if result[:manifest]
+ send_manifest(result[:manifest], from_cache: result[:from_cache])
+ else
+ send_dependency(manifest_header, DependencyProxy::Registry.manifest_url(image, tag), manifest_file_name)
+ end
else
render status: result[:http_status], json: result[:message]
end
@@ -59,7 +50,7 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy
def authorize_upload_blob
set_workhorse_internal_api_content_type
- render json: DependencyProxy::FileUploader.workhorse_authorize(has_length: false)
+ render json: DependencyProxy::FileUploader.workhorse_authorize(has_length: false, maximum_size: DependencyProxy::Blob::MAX_FILE_SIZE)
end
def upload_blob
@@ -75,6 +66,37 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy
head :ok
end
+ def authorize_upload_manifest
+ set_workhorse_internal_api_content_type
+
+ render json: DependencyProxy::FileUploader.workhorse_authorize(has_length: false, maximum_size: DependencyProxy::Manifest::MAX_FILE_SIZE)
+ end
+
+ def upload_manifest
+ attrs = {
+ file_name: manifest_file_name,
+ content_type: request.headers[Gitlab::Workhorse::SEND_DEPENDENCY_CONTENT_TYPE_HEADER],
+ digest: request.headers[DependencyProxy::Manifest::DIGEST_HEADER],
+ file: params[:file],
+ size: params[:file].size
+ }
+
+ manifest = @group.dependency_proxy_manifests
+ .active
+ .find_by_file_name(manifest_file_name)
+
+ if manifest
+ manifest.update!(attrs)
+ else
+ @group.dependency_proxy_manifests.create!(attrs)
+ end
+
+ event_name = tracking_event_name(object_type: :manifest, from_cache: false)
+ track_package_event(event_name, :dependency_proxy, namespace: group, user: auth_user)
+
+ head :ok
+ end
+
private
def blob_via_workhorse
@@ -86,14 +108,36 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy
send_upload(blob.file)
else
- send_dependency(token, DependencyProxy::Registry.blob_url(image, params[:sha]), blob_file_name)
+ send_dependency(token_header, DependencyProxy::Registry.blob_url(image, params[:sha]), blob_file_name)
end
end
+ def send_manifest(manifest, from_cache:)
+ response.headers[DependencyProxy::Manifest::DIGEST_HEADER] = manifest.digest
+ response.headers['Content-Length'] = manifest.size
+ response.headers['Docker-Distribution-Api-Version'] = DependencyProxy::DISTRIBUTION_API_VERSION
+ response.headers['Etag'] = "\"#{manifest.digest}\""
+ content_type = manifest.content_type
+
+ event_name = tracking_event_name(object_type: :manifest, from_cache: from_cache)
+ track_package_event(event_name, :dependency_proxy, namespace: group, user: auth_user)
+
+ send_upload(
+ manifest.file,
+ proxy: true,
+ redirect_params: { query: { 'response-content-type' => content_type } },
+ send_params: { type: content_type }
+ )
+ end
+
def blob_file_name
@blob_file_name ||= params[:sha].sub('sha256:', '') + '.gz'
end
+ def manifest_file_name
+ @manifest_file_name ||= "#{image}:#{tag}.json"
+ end
+
def group
strong_memoize(:group) do
Group.find_by_full_path(params[:group_id], follow_redirects: true)
@@ -137,4 +181,12 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy
render status: result[:http_status], json: result[:message]
end
end
+
+ def token_header
+ { Authorization: ["Bearer #{token}"] }
+ end
+
+ def manifest_header
+ token_header.merge(Accept: ::ContainerRegistry::Client::ACCEPTED_TYPES)
+ end
end
diff --git a/app/controllers/groups/email_campaigns_controller.rb b/app/controllers/groups/email_campaigns_controller.rb
index 70c8a23d918..520ad768939 100644
--- a/app/controllers/groups/email_campaigns_controller.rb
+++ b/app/controllers/groups/email_campaigns_controller.rb
@@ -40,7 +40,7 @@ class Groups::EmailCampaignsController < Groups::ApplicationController
project_pipelines_url(group.projects.first)
when :trial, :trial_short
'https://about.gitlab.com/free-trial/'
- when :team, :team_short
+ when :team, :team_short, :invite_team
group_group_members_url(group)
when :admin_verify
project_settings_ci_cd_path(group.projects.first, ci_runner_templates: true, anchor: 'js-runners-settings')
@@ -59,6 +59,11 @@ class Groups::EmailCampaignsController < Groups::ApplicationController
@track = params[:track]&.to_sym
@series = params[:series]&.to_i
+ # There is only one email that will be sent for invite team track so series
+ # should only have the value 0. Return early if track is invite team and
+ # condition for series value is met
+ return if @track == Namespaces::InviteTeamEmailService::TRACK && @series == 0
+
track_valid = @track.in?(Namespaces::InProductMarketingEmailsService::TRACKS.keys)
return render_404 unless track_valid
diff --git a/app/controllers/groups/labels_controller.rb b/app/controllers/groups/labels_controller.rb
index 86dde454cbc..7bcc8182bd6 100644
--- a/app/controllers/groups/labels_controller.rb
+++ b/app/controllers/groups/labels_controller.rb
@@ -9,7 +9,7 @@ class Groups::LabelsController < Groups::ApplicationController
respond_to :html
- feature_category :issue_tracking
+ feature_category :team_planning
def index
respond_to do |format|
diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb
index 63eff750d1b..75877cdef9c 100644
--- a/app/controllers/groups/milestones_controller.rb
+++ b/app/controllers/groups/milestones_controller.rb
@@ -6,7 +6,7 @@ class Groups::MilestonesController < Groups::ApplicationController
before_action :milestone, only: [:edit, :show, :update, :issues, :merge_requests, :participants, :labels, :destroy]
before_action :authorize_admin_milestones!, only: [:edit, :new, :create, :update, :destroy]
- feature_category :issue_tracking
+ feature_category :team_planning
def index
respond_to do |format|
diff --git a/app/controllers/groups/packages_controller.rb b/app/controllers/groups/packages_controller.rb
index d02a8262948..47f1816cc4c 100644
--- a/app/controllers/groups/packages_controller.rb
+++ b/app/controllers/groups/packages_controller.rb
@@ -6,10 +6,6 @@ module Groups
feature_category :package_registry
- before_action do
- push_frontend_feature_flag(:package_list_apollo, default_enabled: :yaml)
- end
-
private
def verify_packages_enabled!
diff --git a/app/controllers/groups/settings/applications_controller.rb b/app/controllers/groups/settings/applications_controller.rb
index f05a96d7810..6388277e4dc 100644
--- a/app/controllers/groups/settings/applications_controller.rb
+++ b/app/controllers/groups/settings/applications_controller.rb
@@ -16,6 +16,7 @@ module Groups
end
def show
+ @created = get_created_session
end
def edit
@@ -27,6 +28,8 @@ module Groups
if @application.persisted?
flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
+ set_created_session
+
redirect_to group_settings_application_url(@group, @application)
else
set_index_vars
diff --git a/app/controllers/groups/settings/integrations_controller.rb b/app/controllers/groups/settings/integrations_controller.rb
index a7a1de03224..0a63c3d304b 100644
--- a/app/controllers/groups/settings/integrations_controller.rb
+++ b/app/controllers/groups/settings/integrations_controller.rb
@@ -3,7 +3,7 @@
module Groups
module Settings
class IntegrationsController < Groups::ApplicationController
- include IntegrationsActions
+ include ::Integrations::Actions
before_action :authorize_admin_group!
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index a419171039e..6ae711a6e14 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -54,7 +54,7 @@ class GroupsController < Groups::ApplicationController
:destroy, :details, :transfer, :activity
]
- feature_category :issue_tracking, [:issues, :issues_calendar, :preview_markdown]
+ feature_category :team_planning, [:issues, :issues_calendar, :preview_markdown]
feature_category :code_review, [:merge_requests, :unfoldered_environment_names]
feature_category :projects, [:projects]
feature_category :importers, [:export, :download_export]
@@ -92,6 +92,7 @@ class GroupsController < Groups::ApplicationController
if @group.import_state&.in_progress?
redirect_to group_import_path(@group)
else
+ publish_invite_members_for_task_experiment
render_show_html
end
end
@@ -379,6 +380,13 @@ class GroupsController < Groups::ApplicationController
def captcha_required?
captcha_enabled? && !params[:parent_id]
end
+
+ def publish_invite_members_for_task_experiment
+ return unless params[:open_modal] == 'invite_members_for_task'
+ return unless current_user&.can?(:admin_group_member, @group)
+
+ experiment(:invite_members_for_task, namespace: @group).publish_to_client
+ end
end
GroupsController.prepend_mod_with('GroupsController')
diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb
index 0ad7478584f..e0020c22145 100644
--- a/app/controllers/help_controller.rb
+++ b/app/controllers/help_controller.rb
@@ -122,3 +122,5 @@ class HelpController < ApplicationController
end
end
end
+
+::HelpController.prepend_mod
diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb
index d32755dbd94..cfd86429df0 100644
--- a/app/controllers/import/bitbucket_controller.rb
+++ b/app/controllers/import/bitbucket_controller.rb
@@ -116,7 +116,9 @@ class Import::BitbucketController < Import::BaseController
redirect_to oauth_client.auth_code.authorize_url(redirect_uri: users_import_bitbucket_callback_url)
end
- def bitbucket_unauthorized
+ def bitbucket_unauthorized(exception)
+ log_exception(exception)
+
go_to_bitbucket_for_permissions
end
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index 4242f918ea0..d4b1306cc5e 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -52,7 +52,7 @@ class InvitesController < ApplicationController
end
def current_user_matches_invite?
- current_user.verified_emails.include?(@member.invite_email)
+ current_user.verified_email?(@member.invite_email)
end
def member?
diff --git a/app/controllers/jira_connect/app_descriptor_controller.rb b/app/controllers/jira_connect/app_descriptor_controller.rb
index e96242c7052..16bd73f5ab6 100644
--- a/app/controllers/jira_connect/app_descriptor_controller.rb
+++ b/app/controllers/jira_connect/app_descriptor_controller.rb
@@ -32,7 +32,7 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
apiVersion: 1,
apiMigrations: {
'context-qsh': true,
- 'signed-install': signed_install_active?,
+ 'signed-install': true,
gdpr: true
}
}
diff --git a/app/controllers/jira_connect/application_controller.rb b/app/controllers/jira_connect/application_controller.rb
index ecb23c326fe..352e78d6255 100644
--- a/app/controllers/jira_connect/application_controller.rb
+++ b/app/controllers/jira_connect/application_controller.rb
@@ -74,8 +74,4 @@ class JiraConnect::ApplicationController < ApplicationController
params[:jwt] || request.headers['Authorization']&.split(' ', 2)&.last
end
end
-
- def signed_install_active?
- Feature.enabled?(:jira_connect_asymmetric_jwt)
- end
end
diff --git a/app/controllers/jira_connect/events_controller.rb b/app/controllers/jira_connect/events_controller.rb
index 76ac15f7631..1ea0a92662b 100644
--- a/app/controllers/jira_connect/events_controller.rb
+++ b/app/controllers/jira_connect/events_controller.rb
@@ -4,14 +4,9 @@ class JiraConnect::EventsController < JiraConnect::ApplicationController
# See https://developer.atlassian.com/cloud/jira/software/app-descriptor/#lifecycle
skip_before_action :verify_atlassian_jwt!
- before_action :verify_asymmetric_atlassian_jwt!, if: :signed_install_active?
-
- before_action :verify_atlassian_jwt!, only: :uninstalled, unless: :signed_install_active?
- before_action :verify_qsh_claim!, only: :uninstalled, unless: :signed_install_active?
+ before_action :verify_asymmetric_atlassian_jwt!
def installed
- return head :ok if !signed_install_active? && atlassian_jwt_valid?
-
return head :ok if current_jira_installation
installation = JiraConnectInstallation.new(event_params)
diff --git a/app/controllers/jira_connect/subscriptions_controller.rb b/app/controllers/jira_connect/subscriptions_controller.rb
index 903ad395e44..fcd95c7942c 100644
--- a/app/controllers/jira_connect/subscriptions_controller.rb
+++ b/app/controllers/jira_connect/subscriptions_controller.rb
@@ -7,8 +7,8 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController
next if p.directives.blank?
# rubocop: disable Lint/PercentStringArray
- script_src_values = Array.wrap(p.directives['script-src']) | %w('self' https://connect-cdn.atl-paas.net https://unpkg.com/jquery@3.3.1/)
- style_src_values = Array.wrap(p.directives['style-src']) | %w('self' 'unsafe-inline' https://unpkg.com/@atlaskit/)
+ script_src_values = Array.wrap(p.directives['script-src']) | %w('self' https://connect-cdn.atl-paas.net)
+ style_src_values = Array.wrap(p.directives['style-src']) | %w('self' 'unsafe-inline')
# rubocop: enable Lint/PercentStringArray
p.frame_ancestors :self, 'https://*.atlassian.net'
diff --git a/app/controllers/jwks_controller.rb b/app/controllers/jwks_controller.rb
index e7b839f5590..3b0e6ca2eb1 100644
--- a/app/controllers/jwks_controller.rb
+++ b/app/controllers/jwks_controller.rb
@@ -1,13 +1,17 @@
# frozen_string_literal: true
-class JwksController < ActionController::Base # rubocop:disable Rails/ApplicationController
+class JwksController < Doorkeeper::OpenidConnect::DiscoveryController
def index
- render json: { keys: keys }
+ render json: { keys: payload }
+ end
+
+ def keys
+ index
end
private
- def keys
+ def payload
[
# We keep openid_connect_signing_key so that we can seamlessly
# replace it with ci_jwt_signing_key and remove it on the next release.
diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb
index 81f188256ba..81084ffe38b 100644
--- a/app/controllers/oauth/applications_controller.rb
+++ b/app/controllers/oauth/applications_controller.rb
@@ -24,12 +24,18 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
set_index_vars
end
+ def show
+ @created = get_created_session
+ end
+
def create
@application = Applications::CreateService.new(current_user, application_params).execute(request)
if @application.persisted?
flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
+ set_created_session
+
redirect_to oauth_application_url(@application)
else
set_index_vars
diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb
index c764f2d0459..ead5d7c9026 100644
--- a/app/controllers/passwords_controller.rb
+++ b/app/controllers/passwords_controller.rb
@@ -1,8 +1,12 @@
# frozen_string_literal: true
class PasswordsController < Devise::PasswordsController
+ include GitlabRecaptcha
+
skip_before_action :require_no_authentication, only: [:edit, :update]
+ prepend_before_action :check_recaptcha, only: :create
+ before_action :load_recaptcha, only: :new
before_action :resource_from_email, only: [:create]
before_action :check_password_authentication_available, only: [:create]
before_action :throttle_reset, only: [:create]
@@ -59,6 +63,12 @@ class PasswordsController < Devise::PasswordsController
alert: _("Password authentication is unavailable.")
end
+ def check_recaptcha
+ return unless resource_params[:email].present?
+
+ super
+ end
+
def throttle_reset
return unless resource && resource.recently_sent_password_reset?
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index e0b5d6be155..e607346b40e 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -66,7 +66,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
render 'create'
else
- @error = _('Invalid pin code')
+ @error = { message: _('Invalid pin code.') }
@qr_code = build_qr_code
if Feature.enabled?(:webauthn)
@@ -147,7 +147,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
end
def current_password_required?
- !current_user.password_automatically_set?
+ !current_user.password_automatically_set? && current_user.allow_password_authentication_for_web?
end
def build_qr_code
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index 69257081cc9..6330a6aa107 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -63,7 +63,7 @@ class ProfilesController < Profiles::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def audit_log
- @events = AuditEvent.where(entity_type: "User", entity_id: current_user.id)
+ @events = AuthenticationEvent.where(user: current_user)
.order("created_at DESC")
.page(params[:page])
diff --git a/app/controllers/projects/alert_management_controller.rb b/app/controllers/projects/alert_management_controller.rb
index 34f9f361e43..ebe867d915d 100644
--- a/app/controllers/projects/alert_management_controller.rb
+++ b/app/controllers/projects/alert_management_controller.rb
@@ -3,10 +3,6 @@
class Projects::AlertManagementController < Projects::ApplicationController
before_action :authorize_read_alert_management_alert!
- before_action(only: [:index]) do
- push_frontend_feature_flag(:managed_alerts_deprecation, @project, default_enabled: :yaml)
- end
-
feature_category :incident_management
def index
diff --git a/app/controllers/projects/alerting/notifications_controller.rb b/app/controllers/projects/alerting/notifications_controller.rb
index 95b403faf55..ae8498ce65f 100644
--- a/app/controllers/projects/alerting/notifications_controller.rb
+++ b/app/controllers/projects/alerting/notifications_controller.rb
@@ -18,7 +18,11 @@ module Projects
token = extract_alert_manager_token(request)
result = notify_service.execute(token, integration)
- head result.http_status
+ if result.success?
+ render json: AlertManagement::AlertSerializer.new.represent(result.payload[:alerts]), code: result.http_status
+ else
+ head result.http_status
+ end
end
private
diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb
index 7c419cac1cc..0d5f64c739c 100644
--- a/app/controllers/projects/autocomplete_sources_controller.rb
+++ b/app/controllers/projects/autocomplete_sources_controller.rb
@@ -3,7 +3,7 @@
class Projects::AutocompleteSourcesController < Projects::ApplicationController
before_action :authorize_read_milestone!, only: :milestones
- feature_category :issue_tracking, [:issues, :labels, :milestones, :commands]
+ feature_category :team_planning, [:issues, :labels, :milestones, :commands]
feature_category :code_review, [:merge_requests]
feature_category :users, [:members]
feature_category :snippets, [:snippets]
diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb
index 0cd59c136e5..8023e51b552 100644
--- a/app/controllers/projects/badges_controller.rb
+++ b/app/controllers/projects/badges_controller.rb
@@ -6,7 +6,8 @@ class Projects::BadgesController < Projects::ApplicationController
before_action :no_cache_headers, only: [:pipeline, :coverage]
before_action :authorize_read_build!, only: [:pipeline, :coverage]
- feature_category :continuous_integration
+ feature_category :continuous_integration, [:index, :pipeline]
+ feature_category :code_testing, [:coverage]
def pipeline
pipeline_status = Gitlab::Ci::Badge::Pipeline::Status
diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb
index 1df7b9ed165..0f87690bba5 100644
--- a/app/controllers/projects/blame_controller.rb
+++ b/app/controllers/projects/blame_controller.rb
@@ -10,6 +10,7 @@ class Projects::BlameController < Projects::ApplicationController
before_action :authorize_download_code!
feature_category :source_code_management
+ urgency :low, [:show]
def show
@blob = @repository.blob_at(@commit.id, @path)
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 17fd28ee06a..cd50c8cf5b1 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -40,6 +40,7 @@ class Projects::BlobController < Projects::ApplicationController
track_redis_hll_event :create, :update, name: 'g_edit_by_sfe'
feature_category :source_code_management
+ urgency :low, [:create, :show, :edit, :update, :diff]
before_action do
push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index 834e4baa7dd..7354c2c71ac 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -12,9 +12,13 @@ class Projects::BoardsController < Projects::ApplicationController
push_frontend_feature_flag(:board_multi_select, project, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml)
push_frontend_feature_flag(:labels_widget, project, default_enabled: :yaml)
+ experiment(:prominent_create_board_btn, subject: current_user) do |e|
+ e.use { }
+ e.try { }
+ end.run
end
- feature_category :boards
+ feature_category :team_planning
private
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index b75effc52d1..63ac5f97420 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -14,6 +14,7 @@ class Projects::BranchesController < Projects::ApplicationController
before_action :limit_diverging_commit_counts!, only: [:diverging_commit_counts]
feature_category :source_code_management
+ urgency :low, [:index, :diverging_commit_counts, :create, :destroy]
def index
respond_to do |format|
@@ -105,8 +106,7 @@ class Projects::BranchesController < Projects::ApplicationController
# rubocop: enable CodeReuse/ActiveRecord
def destroy
- @branch_name = Addressable::URI.unescape(params[:id])
- result = ::Branches::DeleteService.new(project, current_user).execute(@branch_name)
+ result = ::Branches::DeleteService.new(project, current_user).execute(params[:id])
respond_to do |format|
format.html do
diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb
index 22cd247644d..600516f95a2 100644
--- a/app/controllers/projects/ci/pipeline_editor_controller.rb
+++ b/app/controllers/projects/ci/pipeline_editor_controller.rb
@@ -2,8 +2,8 @@
class Projects::Ci::PipelineEditorController < Projects::ApplicationController
before_action :check_can_collaborate!
+ before_action :setup_walkthrough_experiment, only: :show
before_action do
- push_frontend_feature_flag(:pipeline_editor_mini_graph, @project, default_enabled: :yaml)
push_frontend_feature_flag(:schema_linting, @project, default_enabled: :yaml)
end
@@ -17,4 +17,11 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController
def check_can_collaborate!
render_404 unless can_collaborate_with_project?(@project)
end
+
+ def setup_walkthrough_experiment
+ experiment(:pipeline_editor_walkthrough, namespace: @project.namespace, sticky_to: current_user) do |e|
+ e.candidate {}
+ e.record!
+ end
+ end
end
diff --git a/app/controllers/projects/cluster_agents_controller.rb b/app/controllers/projects/cluster_agents_controller.rb
index e7fbe93131d..404d3907128 100644
--- a/app/controllers/projects/cluster_agents_controller.rb
+++ b/app/controllers/projects/cluster_agents_controller.rb
@@ -3,6 +3,10 @@
class Projects::ClusterAgentsController < Projects::ApplicationController
before_action :authorize_can_read_cluster_agent!
+ before_action do
+ push_frontend_feature_flag(:cluster_vulnerabilities, project, default_enabled: :yaml)
+ end
+
feature_category :kubernetes_management
def show
@@ -17,3 +21,5 @@ class Projects::ClusterAgentsController < Projects::ApplicationController
access_denied!
end
end
+
+Projects::ClusterAgentsController.prepend_mod_with('Projects::ClusterAgentsController')
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 6748be06ded..62935e133c5 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -24,6 +24,7 @@ class Projects::CommitController < Projects::ApplicationController
COMMIT_DIFFS_PER_PAGE = 20
feature_category :source_code_management
+ urgency :low, [:pipelines, :merge_requests, :show]
def show
apply_diff_view_cookie!
diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb
index 9ca917841e9..1ca35903703 100644
--- a/app/controllers/projects/commits_controller.rb
+++ b/app/controllers/projects/commits_controller.rb
@@ -6,6 +6,8 @@ class Projects::CommitsController < Projects::ApplicationController
include ExtractsPath
include RendersCommits
+ COMMITS_DEFAULT_LIMIT = 40
+
prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) }
around_action :allow_gitaly_ref_name_caching
before_action :require_non_empty_project
@@ -15,6 +17,7 @@ class Projects::CommitsController < Projects::ApplicationController
before_action :set_commits, except: :commits_root
feature_category :source_code_management
+ urgency :low, [:signatures, :show]
def commits_root
redirect_to project_commits_path(@project, @project.default_branch)
@@ -63,7 +66,9 @@ class Projects::CommitsController < Projects::ApplicationController
def set_commits
render_404 unless @path.empty? || request.format == :atom || @repository.blob_at(@commit.id, @path) || @repository.tree(@commit.id, @path).entries.present?
- @limit = (params[:limit] || 40).to_i
+
+ limit = params[:limit].to_i
+ @limit = limit > 0 ? limit : COMMITS_DEFAULT_LIMIT # limit can only ever be a positive number
@offset = (params[:offset] || 0).to_i
search = params[:search]
author = params[:author]
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index 99f62c18593..07f7c1cf7de 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -21,6 +21,7 @@ class Projects::CompareController < Projects::ApplicationController
before_action :validate_refs!
feature_category :source_code_management
+ urgency :low, [:show, :create, :signatures]
# Diffs may be pretty chunky, the less is better in this endpoint.
# Pagination design guides: https://design.gitlab.com/components/pagination/#behavior
diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb
index db5ba51ee01..dc6a9a73d9e 100644
--- a/app/controllers/projects/cycle_analytics_controller.rb
+++ b/app/controllers/projects/cycle_analytics_controller.rb
@@ -6,8 +6,10 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
include CycleAnalyticsParams
include GracefulTimeoutHandling
include RedisTracking
+ extend ::Gitlab::Utils::Override
before_action :authorize_read_cycle_analytics!
+ before_action :load_value_stream, only: :show
track_redis_hll_event :show, name: 'p_analytics_valuestream'
@@ -19,6 +21,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
def show
@cycle_analytics = Analytics::CycleAnalytics::ProjectLevel.new(project: @project, options: options(cycle_analytics_project_params))
+ @request_params ||= ::Gitlab::Analytics::CycleAnalytics::RequestParams.new(all_cycle_analytics_params)
respond_to do |format|
format.html do
@@ -34,6 +37,15 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
private
+ override :all_cycle_analytics_params
+ def all_cycle_analytics_params
+ super.merge({ project: @project, value_stream: @value_stream })
+ end
+
+ def load_value_stream
+ @value_stream = Analytics::CycleAnalytics::ProjectValueStream.build_default_value_stream(@project)
+ end
+
def cycle_analytics_json
{
summary: @cycle_analytics.summary,
diff --git a/app/controllers/projects/discussions_controller.rb b/app/controllers/projects/discussions_controller.rb
index 708b7a6c7ba..9f7d47b95f3 100644
--- a/app/controllers/projects/discussions_controller.rb
+++ b/app/controllers/projects/discussions_controller.rb
@@ -9,7 +9,7 @@ class Projects::DiscussionsController < Projects::ApplicationController
before_action :discussion, only: [:resolve, :unresolve]
before_action :authorize_resolve_discussion!, only: [:resolve, :unresolve]
- feature_category :issue_tracking
+ feature_category :team_planning
def resolve
Discussions::ResolveService.new(project, current_user, one_or_more_discussions: discussion).execute
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index 23dabd885c8..84ebdcd9364 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -70,11 +70,9 @@ class Projects::EnvironmentsController < Projects::ApplicationController
end
# rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def show
- @deployments = environment.deployments.order(id: :desc).page(params[:page])
+ @deployments = environment.deployments.ordered.page(params[:page])
end
- # rubocop: enable CodeReuse/ActiveRecord
def new
@environment = project.environments.new
diff --git a/app/controllers/projects/find_file_controller.rb b/app/controllers/projects/find_file_controller.rb
index 89e72d98a33..c6bc115e737 100644
--- a/app/controllers/projects/find_file_controller.rb
+++ b/app/controllers/projects/find_file_controller.rb
@@ -11,6 +11,7 @@ class Projects::FindFileController < Projects::ApplicationController
before_action :authorize_download_code!
feature_category :source_code_management
+ urgency :low, [:show, :list]
def show
return render_404 unless @repository.commit(@ref)
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index 7135c0d959e..5154f145b46 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -15,6 +15,7 @@ class Projects::ForksController < Projects::ApplicationController
before_action :authorize_fork_namespace!, only: [:create]
feature_category :source_code_management
+ urgency :low, [:index]
before_action do
push_frontend_feature_flag(:fork_project_form, @project, default_enabled: :yaml)
diff --git a/app/controllers/projects/google_cloud_controller.rb b/app/controllers/projects/google_cloud_controller.rb
index d185457aeb3..7257ed1ef6f 100644
--- a/app/controllers/projects/google_cloud_controller.rb
+++ b/app/controllers/projects/google_cloud_controller.rb
@@ -1,16 +1,34 @@
# frozen_string_literal: true
class Projects::GoogleCloudController < Projects::ApplicationController
- before_action :authorize_can_manage_google_cloud_deployments!
+ feature_category :google_cloud
- feature_category :release_orchestration
+ before_action :admin_project_google_cloud?
+ before_action :google_oauth2_enabled?
+ before_action :feature_flag_enabled?
def index
+ @js_data = {
+ serviceAccounts: GoogleCloud::ServiceAccountsService.new(project).find_for_project,
+ createServiceAccountUrl: '#mocked-url-create-service',
+ emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/pipelines_empty.svg')
+ }.to_json
end
private
- def authorize_can_manage_google_cloud_deployments!
- access_denied! unless can?(current_user, :manage_project_google_cloud, project)
+ def admin_project_google_cloud?
+ access_denied! unless can?(current_user, :admin_project_google_cloud, project)
+ end
+
+ def google_oauth2_enabled?
+ config = Gitlab::Auth::OAuth::Provider.config_for('google_oauth2')
+ if config.app_id.blank? || config.app_secret.blank?
+ access_denied! 'This GitLab instance not configured for Google Oauth2.'
+ end
+ end
+
+ def feature_flag_enabled?
+ access_denied! unless Feature.enabled?(:incubation_5mp_google_cloud)
end
end
diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb
index 7a7961c28bb..d3a05736a47 100644
--- a/app/controllers/projects/graphs_controller.rb
+++ b/app/controllers/projects/graphs_controller.rb
@@ -11,7 +11,10 @@ class Projects::GraphsController < Projects::ApplicationController
track_redis_hll_event :charts, name: 'p_analytics_repo'
- feature_category :source_code_management
+ feature_category :source_code_management, [:show, :commits, :languages, :charts]
+ urgency :low, [:show]
+
+ feature_category :continuous_integration, [:ci]
def show
respond_to do |format|
diff --git a/app/controllers/projects/hook_logs_controller.rb b/app/controllers/projects/hook_logs_controller.rb
index 99ebe3335c0..0ca3d71f728 100644
--- a/app/controllers/projects/hook_logs_controller.rb
+++ b/app/controllers/projects/hook_logs_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Projects::HookLogsController < Projects::ApplicationController
- include HooksExecution
+ include ::Integrations::HooksExecution
before_action :authorize_admin_project!
@@ -13,6 +13,7 @@ class Projects::HookLogsController < Projects::ApplicationController
layout 'project_settings'
feature_category :integrations
+ urgency :low, [:retry]
def show
end
diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb
index b87bfc58f8b..c79e5a8cc85 100644
--- a/app/controllers/projects/hooks_controller.rb
+++ b/app/controllers/projects/hooks_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Projects::HooksController < Projects::ApplicationController
- include HooksExecution
+ include ::Integrations::HooksExecution
# Authorize
before_action :authorize_admin_project!
@@ -13,9 +13,10 @@ class Projects::HooksController < Projects::ApplicationController
layout "project_settings"
feature_category :integrations
+ urgency :low, [:test]
def index
- @hooks = @project.hooks
+ @hooks = @project.hooks.load
@hook = ProjectHook.new
end
diff --git a/app/controllers/projects/issue_links_controller.rb b/app/controllers/projects/issue_links_controller.rb
index 35f3e00fae7..e8c3110574f 100644
--- a/app/controllers/projects/issue_links_controller.rb
+++ b/app/controllers/projects/issue_links_controller.rb
@@ -7,7 +7,7 @@ module Projects
before_action :authorize_admin_issue_link!, only: [:create, :destroy]
before_action :authorize_issue_link_association!, only: :destroy
- feature_category :issue_tracking
+ feature_category :team_planning
private
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index fd508d5f127..853e9c7ccdd 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -48,12 +48,11 @@ class Projects::IssuesController < Projects::ApplicationController
end
before_action only: :show do
- real_time_enabled = Gitlab::ActionCable::Config.in_app? || Feature.enabled?(:real_time_issue_sidebar, @project)
-
- push_to_gon_attributes(:features, :real_time_issue_sidebar, real_time_enabled)
+ push_frontend_feature_flag(:real_time_issue_sidebar, @project, default_enabled: :yaml)
push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml)
push_frontend_feature_flag(:issue_assignees_widget, @project, default_enabled: :yaml)
push_frontend_feature_flag(:labels_widget, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:paginated_issue_discussions, @project, default_enabled: :yaml)
experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance|
experiment_instance.exclude! unless helpers.can_admin_project_member?(@project)
@@ -71,7 +70,7 @@ class Projects::IssuesController < Projects::ApplicationController
alias_method :designs, :show
- feature_category :issue_tracking, [
+ feature_category :team_planning, [
:index, :calendar, :show, :new, :create, :edit, :update,
:destroy, :move, :reorder, :designs, :toggle_subscription,
:discussions, :bulk_update, :realtime_changes,
diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb
index 994be5c2b5c..81b8da9cba3 100644
--- a/app/controllers/projects/jobs_controller.rb
+++ b/app/controllers/projects/jobs_controller.rb
@@ -133,9 +133,9 @@ class Projects::JobsController < Projects::ApplicationController
end
def raw
- if trace_artifact_file
+ if @build.trace.archived_trace_exist?
workhorse_set_content_type!
- send_upload(trace_artifact_file,
+ send_upload(@build.job_artifacts_trace.file,
send_params: raw_send_params,
redirect_params: raw_redirect_params)
else
@@ -219,10 +219,6 @@ class Projects::JobsController < Projects::ApplicationController
params.permit(job_variables_attributes: %i[key secret_value])
end
- def trace_artifact_file
- @trace_artifact_file ||= @build.job_artifacts_trace&.file
- end
-
def find_job_as_build
@build = project.builds.find(params[:id])
end
diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb
index 6bf3885fb7a..814081194d6 100644
--- a/app/controllers/projects/labels_controller.rb
+++ b/app/controllers/projects/labels_controller.rb
@@ -14,7 +14,7 @@ class Projects::LabelsController < Projects::ApplicationController
respond_to :js, :html
- feature_category :issue_tracking
+ feature_category :team_planning
def index
respond_to do |format|
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 46df514abcb..6c5a8aa0610 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -41,6 +41,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:diffs_virtual_scrolling, project, default_enabled: :yaml)
push_frontend_feature_flag(:restructured_mr_widget, project, default_enabled: :yaml)
push_frontend_feature_flag(:mr_changes_fluid_layout, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:mr_attention_requests, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:labels_widget, project, default_enabled: :yaml)
# Usage data feature flags
push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml)
@@ -140,8 +142,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
cache_context = [
params[:serializer],
current_user&.cache_key,
- @merge_request.assignees.map(&:cache_key),
- @merge_request.reviewers.map(&:cache_key)
+ @merge_request.merge_request_assignees.map(&:cache_key),
+ @merge_request.merge_request_reviewers.map(&:cache_key)
]
render_cached(@merge_request,
diff --git a/app/controllers/projects/metrics_dashboard_controller.rb b/app/controllers/projects/metrics_dashboard_controller.rb
index 89c99a5fd5a..3f10749602e 100644
--- a/app/controllers/projects/metrics_dashboard_controller.rb
+++ b/app/controllers/projects/metrics_dashboard_controller.rb
@@ -12,7 +12,6 @@ module Projects
before_action do
push_frontend_feature_flag(:prometheus_computed_alerts)
push_frontend_feature_flag(:disable_metric_dashboard_refresh_rate)
- push_frontend_feature_flag(:managed_alerts_deprecation, @project, default_enabled: :yaml)
end
feature_category :metrics
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index 630e7ccd43f..5dc9718d7a4 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -18,7 +18,7 @@ class Projects::MilestonesController < Projects::ApplicationController
respond_to :html
- feature_category :issue_tracking
+ feature_category :team_planning
def index
@sort = params[:sort] || 'due_date_asc'
diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb
index f3a7bc7913e..84ac9fb01fd 100644
--- a/app/controllers/projects/network_controller.rb
+++ b/app/controllers/projects/network_controller.rb
@@ -11,6 +11,7 @@ class Projects::NetworkController < Projects::ApplicationController
before_action :assign_commit
feature_category :source_code_management
+ urgency :low, [:show]
def show
@url = project_network_path(@project, @ref, @options.merge(format: :json))
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index e7e6aed8ec8..e8057308386 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -11,7 +11,7 @@ class Projects::NotesController < Projects::ApplicationController
before_action :authorize_create_note!, only: [:create]
before_action :authorize_resolve_note!, only: [:resolve, :unresolve]
- feature_category :issue_tracking
+ feature_category :team_planning
def delete_attachment
note.remove_attachment!
@@ -55,6 +55,14 @@ class Projects::NotesController < Projects::ApplicationController
end
end
+ def outdated_line_change
+ diff_lines = Rails.cache.fetch(['note', note.id, 'oudated_line_change'], expires_in: 7.days) do
+ ::MergeRequests::OutdatedDiscussionDiffLinesService.new(project: @project, note: note).execute.to_json
+ end
+
+ render json: diff_lines
+ end
+
private
def render_json_with_notes_serializer
diff --git a/app/controllers/projects/packages/packages_controller.rb b/app/controllers/projects/packages/packages_controller.rb
index dd7c2ad3cbd..5de71466c10 100644
--- a/app/controllers/projects/packages/packages_controller.rb
+++ b/app/controllers/projects/packages/packages_controller.rb
@@ -7,10 +7,6 @@ module Projects
feature_category :package_registry
- before_action do
- push_frontend_feature_flag(:package_list_apollo, default_enabled: :yaml)
- end
-
def show
@package = project.packages.find(params[:id])
end
diff --git a/app/controllers/projects/prometheus/alerts_controller.rb b/app/controllers/projects/prometheus/alerts_controller.rb
index 19c908026cf..312919831d4 100644
--- a/app/controllers/projects/prometheus/alerts_controller.rb
+++ b/app/controllers/projects/prometheus/alerts_controller.rb
@@ -30,7 +30,11 @@ module Projects
token = extract_alert_manager_token(request)
result = notify_service.execute(token)
- head result.http_status
+ if result.success?
+ render json: AlertManagement::AlertSerializer.new.represent(result.payload[:alerts]), code: result.http_status
+ else
+ head result.http_status
+ end
end
def create
diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb
index 4d23c853334..73eb6bb2bf2 100644
--- a/app/controllers/projects/refs_controller.rb
+++ b/app/controllers/projects/refs_controller.rb
@@ -12,6 +12,7 @@ class Projects::RefsController < Projects::ApplicationController
before_action :authorize_download_code!
feature_category :source_code_management
+ urgency :low, [:switch, :logs_tree]
def switch
respond_to do |format|
diff --git a/app/controllers/projects/releases/evidences_controller.rb b/app/controllers/projects/releases/evidences_controller.rb
index 1e2dbf8047c..41e2ce81eb8 100644
--- a/app/controllers/projects/releases/evidences_controller.rb
+++ b/app/controllers/projects/releases/evidences_controller.rb
@@ -20,7 +20,6 @@ module Projects
private
def authorize_read_release_evidence!
- access_denied! unless Feature.enabled?(:release_evidence, project, default_enabled: true)
access_denied! unless can?(current_user, :read_release_evidence, evidence)
end
diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb
index be2abc5cddf..7fba6cc5bf4 100644
--- a/app/controllers/projects/releases_controller.rb
+++ b/app/controllers/projects/releases_controller.rb
@@ -5,9 +5,6 @@ class Projects::ReleasesController < Projects::ApplicationController
before_action :require_non_empty_project, except: [:index]
before_action :release, only: %i[edit show update downloads]
before_action :authorize_read_release!
- # We have to check `download_code` permission because detail URL path
- # contains git-tag name.
- before_action :authorize_download_code!, except: [:index]
before_action :authorize_update_release!, only: %i[edit update]
before_action :authorize_create_release!, only: :new
before_action only: :index do
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index c42d382c4bb..9464826701d 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -18,6 +18,7 @@ class Projects::ServicesController < Projects::ApplicationController
layout "project_settings"
feature_category :integrations
+ urgency :low, [:test]
def edit
end
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index 3033dac8246..4fe37352995 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -104,8 +104,7 @@ module Projects
CreatePipelineWorker.perform_async(project.id, current_user.id, project.default_branch, :web, ignore_skip_ci: true, save_on_errors: false)
# rubocop:enable CodeReuse/Worker
- pipelines_link_start = '<a href="%{url}">'.html_safe % { url: project_pipelines_path(@project) }
- flash[:toast] = _("A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details") % { pipelines_link_start: pipelines_link_start, pipelines_link_end: "</a>".html_safe }
+ flash[:toast] = _("A new Auto DevOps pipeline has been created, go to the Pipelines page for details")
end
def define_variables
diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb
index 728231dbdbd..cc419bab687 100644
--- a/app/controllers/projects/settings/repository_controller.rb
+++ b/app/controllers/projects/settings/repository_controller.rb
@@ -12,6 +12,7 @@ module Projects
feature_category :source_code_management, [:show, :cleanup]
feature_category :continuous_delivery, [:create_deploy_token]
+ urgency :low, [:show]
def show
render_show
diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb
index 02d36c3353d..de0faaca9c0 100644
--- a/app/controllers/projects/tags_controller.rb
+++ b/app/controllers/projects/tags_controller.rb
@@ -10,23 +10,29 @@ class Projects::TagsController < Projects::ApplicationController
before_action :authorize_download_code!
before_action :authorize_admin_tag!, only: [:new, :create, :destroy]
- feature_category :source_code_management, [:index, :show, :new, :destroy]
- feature_category :release_evidence, [:create]
+ feature_category :source_code_management
+ urgency :low, [:new, :show, :index]
# rubocop: disable CodeReuse/ActiveRecord
def index
- params[:sort] = params[:sort].presence || sort_value_recently_updated
+ begin
+ params[:sort] = params[:sort].presence || sort_value_recently_updated
- @sort = params[:sort]
+ @sort = params[:sort]
- @tags, @tags_loading_error = TagsFinder.new(@repository, params).execute
+ @tags = TagsFinder.new(@repository, params).execute
- @tags = Kaminari.paginate_array(@tags).page(params[:page])
- tag_names = @tags.map(&:name)
- @tags_pipelines = @project.ci_pipelines.latest_successful_for_refs(tag_names)
+ @tags = Kaminari.paginate_array(@tags).page(params[:page])
+ tag_names = @tags.map(&:name)
+ @tags_pipelines = @project.ci_pipelines.latest_successful_for_refs(tag_names)
- @releases = project.releases.where(tag: tag_names)
- @tag_pipeline_statuses = Ci::CommitStatusesFinder.new(@project, @repository, current_user, @tags).execute
+ @releases = project.releases.where(tag: tag_names)
+ @tag_pipeline_statuses = Ci::CommitStatusesFinder.new(@project, @repository, current_user, @tags).execute
+
+ rescue Gitlab::Git::CommandError => e
+ @tags = []
+ @tags_loading_error = e
+ end
respond_to do |format|
status = @tags_loading_error ? :service_unavailable : :ok
diff --git a/app/controllers/projects/templates_controller.rb b/app/controllers/projects/templates_controller.rb
index 4bad6dc1b3d..6d06b05c1e9 100644
--- a/app/controllers/projects/templates_controller.rb
+++ b/app/controllers/projects/templates_controller.rb
@@ -6,6 +6,7 @@ class Projects::TemplatesController < Projects::ApplicationController
before_action :get_template_class
feature_category :source_code_management
+ urgency :low, [:names]
def index
templates = @template_type.template_subsets(project)
diff --git a/app/controllers/projects/todos_controller.rb b/app/controllers/projects/todos_controller.rb
index 6ba89ab34f8..dafdeb4c9ef 100644
--- a/app/controllers/projects/todos_controller.rb
+++ b/app/controllers/projects/todos_controller.rb
@@ -6,7 +6,7 @@ class Projects::TodosController < Projects::ApplicationController
before_action :authenticate_user!, only: [:create]
- feature_category :issue_tracking
+ feature_category :team_planning
private
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index a76d45411dd..f8f2c1f0836 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -17,11 +17,12 @@ class Projects::TreeController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:lazy_load_commits, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:paginated_tree_graphql_query, @project, default_enabled: :yaml)
push_frontend_feature_flag(:new_dir_modal, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
end
feature_category :source_code_management
+ urgency :low, [:show]
def show
return render_404 unless @commit
diff --git a/app/controllers/projects/usage_quotas_controller.rb b/app/controllers/projects/usage_quotas_controller.rb
index 103e1cc596a..b319e427eaa 100644
--- a/app/controllers/projects/usage_quotas_controller.rb
+++ b/app/controllers/projects/usage_quotas_controller.rb
@@ -2,7 +2,6 @@
class Projects::UsageQuotasController < Projects::ApplicationController
before_action :authorize_admin_project!
- before_action :verify_usage_quotas_enabled!
layout "project_settings"
@@ -20,10 +19,4 @@ class Projects::UsageQuotasController < Projects::ApplicationController
wiki_help_page_path: help_page_path('administration/wikis/index.md', anchor: 'reduce-wiki-repository-size')
}
end
-
- private
-
- def verify_usage_quotas_enabled!
- render_404 unless Feature.enabled?(:project_storage_ui, project&.group, default_enabled: :yaml)
- end
end
diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb
index 9ee8847004e..02dfaf4c193 100644
--- a/app/controllers/projects/wikis_controller.rb
+++ b/app/controllers/projects/wikis_controller.rb
@@ -3,11 +3,9 @@
class Projects::WikisController < Projects::ApplicationController
include WikiActions
- alias_method :container, :project
+ urgency :low
- before_action do
- push_frontend_feature_flag(:content_editor_block_tables, @project, default_enabled: :yaml)
- end
+ alias_method :container, :project
feature_category :wiki
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 0760f97d7c1..5b17b75a963 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -37,7 +37,6 @@ class ProjectsController < Projects::ApplicationController
push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
push_frontend_feature_flag(:refactor_text_viewer, @project, default_enabled: :yaml)
push_frontend_feature_flag(:increase_page_size_exponentially, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:paginated_tree_graphql_query, @project, default_enabled: :yaml)
push_frontend_feature_flag(:new_dir_modal, @project, default_enabled: :yaml)
end
@@ -49,9 +48,10 @@ class ProjectsController < Projects::ApplicationController
]
feature_category :source_code_management, [:remove_fork, :housekeeping, :refs]
- feature_category :issue_tracking, [:preview_markdown, :new_issuable_address]
+ feature_category :team_planning, [:preview_markdown, :new_issuable_address]
feature_category :importers, [:export, :remove_export, :generate_new_export, :download_export]
feature_category :code_review, [:unfoldered_environment_names]
+ urgency :low, [:refs]
def index
redirect_to(current_user ? root_path : explore_root_path)
@@ -293,7 +293,11 @@ class ProjectsController < Projects::ApplicationController
end
if find_tags && @repository.tag_count.nonzero?
- tags, _ = TagsFinder.new(@repository, params).execute
+ tags = begin
+ TagsFinder.new(@repository, params).execute
+ rescue Gitlab::Git::CommandError
+ []
+ end
options['Tags'] = tags.take(100).map(&:name)
end
@@ -336,11 +340,6 @@ class ProjectsController < Projects::ApplicationController
if can?(current_user, :download_code, @project)
return render 'projects/no_repo' unless @project.repository_exists?
- if @project.can_current_user_push_to_default_branch?
- property = @project.empty_repo? ? 'empty' : 'nonempty'
- experiment(:empty_repo_upload, project: @project).track(:view_project_show, property: property)
- end
-
render 'projects/empty' if @project.empty_repo?
else
if can?(current_user, :read_wiki, @project)
@@ -452,6 +451,7 @@ class ProjectsController < Projects::ApplicationController
:suggestion_commit_message,
:packages_enabled,
:service_desk_enabled,
+ :merge_commit_template,
project_setting_attributes: project_setting_attributes
] + [project_feature_attributes: project_feature_attributes]
end
diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb
index 416bbf43464..39d3125a4a3 100644
--- a/app/controllers/registrations/welcome_controller.rb
+++ b/app/controllers/registrations/welcome_controller.rb
@@ -16,7 +16,9 @@ module Registrations
result = ::Users::SignupService.new(current_user, update_params).execute
if result[:status] == :success
- return redirect_to experiment(:combined_registration, user: current_user).redirect_path(trial_params) if show_signup_onboarding?
+ return redirect_to issues_dashboard_path(assignee_username: current_user.username) if show_tasks_to_be_done?
+
+ return redirect_to update_success_path if show_signup_onboarding?
members = current_user.members
@@ -64,12 +66,23 @@ module Registrations
members.last.source.activity_path
end
+ # overridden in EE
def show_signup_onboarding?
false
end
+ def show_tasks_to_be_done?
+ return unless experiment(:invite_members_for_task).enabled?
+
+ MemberTask.for_members(current_user.members).exists?
+ end
+
+ # overridden in EE
def trial_params
- nil
+ end
+
+ # overridden in EE
+ def update_success_path
end
end
end
diff --git a/app/controllers/repositories/lfs_api_controller.rb b/app/controllers/repositories/lfs_api_controller.rb
index a7719516cb6..30cafb6747e 100644
--- a/app/controllers/repositories/lfs_api_controller.rb
+++ b/app/controllers/repositories/lfs_api_controller.rb
@@ -13,6 +13,7 @@ module Repositories
# added here as a part of the refactor, will be removed
# https://gitlab.com/gitlab-org/gitlab/-/issues/328692
delegate :deploy_token, :user, to: :authentication_result, allow_nil: true
+ urgency :medium, [:batch]
def batch
unless objects.present?
diff --git a/app/controllers/repositories/lfs_storage_controller.rb b/app/controllers/repositories/lfs_storage_controller.rb
index 6ec63a0f939..252b604dcb0 100644
--- a/app/controllers/repositories/lfs_storage_controller.rb
+++ b/app/controllers/repositories/lfs_storage_controller.rb
@@ -11,6 +11,8 @@ module Repositories
# added here as a part of the refactor, will be removed
# https://gitlab.com/gitlab-org/gitlab/-/issues/328692
delegate :deploy_token, :user, to: :authentication_result, allow_nil: true
+ urgency :medium, [:download, :upload_authorize]
+ urgency :low, [:upload_finalize]
def download
lfs_object = LfsObject.find_by_oid(oid)
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 0a18559fc81..0e285dae089 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -46,6 +46,7 @@ class SearchController < ApplicationController
@search_results = @search_service.search_results
@search_objects = @search_service.search_objects
@search_highlight = @search_service.search_highlight
+ @aggregations = @search_service.search_aggregations
increment_search_counters
end
@@ -151,7 +152,7 @@ class SearchController < ApplicationController
def block_anonymous_global_searches
return if params[:project_id].present? || params[:group_id].present?
return if current_user
- return unless ::Feature.enabled?(:block_anonymous_global_searches)
+ return unless ::Feature.enabled?(:block_anonymous_global_searches, type: :ops)
store_location_for(:user, request.fullpath)
diff --git a/app/experiments/change_continuous_onboarding_link_urls_experiment.rb b/app/experiments/change_continuous_onboarding_link_urls_experiment.rb
new file mode 100644
index 00000000000..680cb8eadd8
--- /dev/null
+++ b/app/experiments/change_continuous_onboarding_link_urls_experiment.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class ChangeContinuousOnboardingLinkUrlsExperiment < ApplicationExperiment # rubocop:disable Gitlab/NamespacedClass
+ attr_writer :namespace
+
+ def track(action, **event_args)
+ super(action, **event_args.merge(namespace: @namespace))
+ end
+end
diff --git a/app/experiments/templates/new_project_readme_content/readme_advanced.md.tt b/app/experiments/templates/new_project_readme_content/readme_advanced.md.tt
index bbe8271386f..7592c7c6ab7 100644
--- a/app/experiments/templates/new_project_readme_content/readme_advanced.md.tt
+++ b/app/experiments/templates/new_project_readme_content/readme_advanced.md.tt
@@ -23,13 +23,14 @@ git push -uf origin <%= @project.default_branch_or_main %>
## Integrate with your tools
-- [ ] [Set up project integrations](<%= redirect("https://docs.gitlab.com/ee/user/project/integrations/") %>)
+- [ ] [Set up project integrations](<%= redirect(project_settings_integrations_url(@project)) %>)
## Collaborate with your team
- [ ] [Invite team members and collaborators](<%= redirect("https://docs.gitlab.com/ee/user/project/members/") %>)
- [ ] [Create a new merge request](<%= redirect("https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html") %>)
- [ ] [Automatically close issues from merge requests](<%= redirect("https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically") %>)
+- [ ] [Enable merge request approvals](<%= redirect("https://docs.gitlab.com/ee/user/project/merge_requests/approvals/") %>)
- [ ] [Automatically merge when pipeline succeeds](<%= redirect("https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html") %>)
## Test and Deploy
@@ -40,6 +41,7 @@ Use the built-in continuous integration in GitLab.
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](<%= redirect("https://docs.gitlab.com/ee/user/application_security/sast/") %>)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](<%= redirect("https://docs.gitlab.com/ee/topics/autodevops/requirements.html") %>)
- [ ] [Use pull-based deployments for improved Kubernetes management](<%= redirect("https://docs.gitlab.com/ee/user/clusters/agent/") %>)
+- [ ] [Set up protected environments](<%= redirect("https://docs.gitlab.com/ee/ci/environments/protected_environments.html") %>)
***
diff --git a/app/finders/autocomplete/routes_finder.rb b/app/finders/autocomplete/routes_finder.rb
index b3f2693b273..858a4b69376 100644
--- a/app/finders/autocomplete/routes_finder.rb
+++ b/app/finders/autocomplete/routes_finder.rb
@@ -30,7 +30,7 @@ module Autocomplete
class NamespacesOnly < self
def routables
- return Namespace.all if current_user.admin?
+ return Namespace.without_project_namespaces if current_user.admin?
current_user.namespaces
end
diff --git a/app/finders/award_emojis_finder.rb b/app/finders/award_emojis_finder.rb
index 9ff64637128..709d3f3e593 100644
--- a/app/finders/award_emojis_finder.rb
+++ b/app/finders/award_emojis_finder.rb
@@ -40,7 +40,7 @@ class AwardEmojisFinder
def validate_name_param
return unless params[:name]
- raise ArgumentError, 'Invalid name param' unless params[:name].to_s.in?(Gitlab::Emoji.emojis_names)
+ raise ArgumentError, 'Invalid name param' unless TanukiEmoji.find_by_alpha_code(params[:name].to_s)
end
def validate_awarded_by_param
diff --git a/app/finders/ci/pipelines_finder.rb b/app/finders/ci/pipelines_finder.rb
index 39355853d88..712d5f8c6fb 100644
--- a/app/finders/ci/pipelines_finder.rb
+++ b/app/finders/ci/pipelines_finder.rb
@@ -5,6 +5,13 @@ module Ci
attr_reader :project, :pipelines, :params, :current_user
ALLOWED_INDEXED_COLUMNS = %w[id status ref updated_at user_id].freeze
+ ALLOWED_SCOPES = {
+ RUNNING: 'running',
+ PENDING: 'pending',
+ FINISHED: 'finished',
+ BRANCHES: 'branches',
+ TAGS: 'tags'
+ }.freeze
def initialize(project, current_user, params = {})
@project = project
@@ -65,15 +72,15 @@ module Ci
def by_scope(items)
case params[:scope]
- when 'running'
+ when ALLOWED_SCOPES[:RUNNING]
items.running
- when 'pending'
+ when ALLOWED_SCOPES[:PENDING]
items.pending
- when 'finished'
+ when ALLOWED_SCOPES[:FINISHED]
items.finished
- when 'branches'
+ when ALLOWED_SCOPES[:BRANCHES]
from_ids(ids_for_ref(branches))
- when 'tags'
+ when ALLOWED_SCOPES[:TAGS]
from_ids(ids_for_ref(tags))
else
items
diff --git a/app/finders/ci/pipelines_for_merge_request_finder.rb b/app/finders/ci/pipelines_for_merge_request_finder.rb
index 9476c30f525..b623a94541b 100644
--- a/app/finders/ci/pipelines_for_merge_request_finder.rb
+++ b/app/finders/ci/pipelines_for_merge_request_finder.rb
@@ -31,65 +31,27 @@ module Ci
# Fetch all pipelines without permission check.
def all
- ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336891') do
- strong_memoize(:all_pipelines) do
- next Ci::Pipeline.none unless source_project
-
- pipelines =
- if merge_request.persisted?
- all_pipelines_for_merge_request
- else
- triggered_for_branch.for_sha(commit_shas)
- end
-
- sort(pipelines)
- end
- end
- end
-
- private
+ strong_memoize(:all_pipelines) do
+ next Ci::Pipeline.none unless source_project
- # rubocop: disable CodeReuse/ActiveRecord
- def pipelines_using_cte
- sha_relation = merge_request.all_commits.select(:sha).distinct
-
- cte = Gitlab::SQL::CTE.new(:shas, sha_relation)
-
- pipelines_for_merge_requests = triggered_by_merge_request
- pipelines_for_branch = filter_by_sha(triggered_for_branch, cte)
-
- Ci::Pipeline.with(cte.to_arel) # rubocop: disable CodeReuse/ActiveRecord
- .from_union([pipelines_for_merge_requests, pipelines_for_branch])
- end
- # rubocop: enable CodeReuse/ActiveRecord
+ pipelines =
+ if merge_request.persisted?
+ all_pipelines_for_merge_request
+ else
+ triggered_for_branch.for_sha(commit_shas)
+ end
- def filter_by_sha(pipelines, cte)
- hex = Arel::Nodes::SqlLiteral.new("'hex'")
- string_sha = Arel::Nodes::NamedFunction.new('encode', [cte.table[:sha], hex])
- join_condition = string_sha.eq(Ci::Pipeline.arel_table[:sha])
-
- filter_by(pipelines, cte, join_condition)
+ sort(pipelines)
+ end
end
- def filter_by(pipelines, cte, join_condition)
- shas_table =
- Ci::Pipeline.arel_table
- .join(cte.table, Arel::Nodes::InnerJoin)
- .on(join_condition)
- .join_sources
-
- pipelines.joins(shas_table) # rubocop: disable CodeReuse/ActiveRecord
- end
+ private
def all_pipelines_for_merge_request
- if Feature.enabled?(:decomposed_ci_query_in_pipelines_for_merge_request_finder, target_project, default_enabled: :yaml)
- pipelines_for_merge_request = triggered_by_merge_request
- pipelines_for_branch = triggered_for_branch.for_sha(recent_diff_head_shas(COMMITS_LIMIT))
+ pipelines_for_merge_request = triggered_by_merge_request
+ pipelines_for_branch = triggered_for_branch.for_sha(recent_diff_head_shas(COMMITS_LIMIT))
- Ci::Pipeline.from_union([pipelines_for_merge_request, pipelines_for_branch])
- else
- pipelines_using_cte
- end
+ Ci::Pipeline.from_union([pipelines_for_merge_request, pipelines_for_branch])
end
# NOTE: this method returns only parent merge request pipelines.
diff --git a/app/finders/clusters/agent_authorizations_finder.rb b/app/finders/clusters/agent_authorizations_finder.rb
new file mode 100644
index 00000000000..373cf7fe8b9
--- /dev/null
+++ b/app/finders/clusters/agent_authorizations_finder.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module Clusters
+ class AgentAuthorizationsFinder
+ def initialize(project)
+ @project = project
+ end
+
+ def execute
+ # closest, most-specific authorization for a given agent wins
+ (project_authorizations + implicit_authorizations + group_authorizations)
+ .uniq(&:agent_id)
+ end
+
+ private
+
+ attr_reader :project
+
+ def implicit_authorizations
+ project.cluster_agents.map do |agent|
+ Clusters::Agents::ImplicitAuthorization.new(agent: agent)
+ end
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def project_authorizations
+ ancestor_ids = project.group ? project.ancestors.select(:id) : project.namespace_id
+
+ Clusters::Agents::ProjectAuthorization
+ .where(project_id: project.id)
+ .joins(agent: :project)
+ .preload(agent: :project)
+ .where(cluster_agents: { projects: { namespace_id: ancestor_ids } })
+ .with_available_ci_access_fields(project)
+ .to_a
+ end
+
+ def group_authorizations
+ return [] unless project.group
+
+ authorizations = Clusters::Agents::GroupAuthorization.arel_table
+
+ ordered_ancestors_cte = Gitlab::SQL::CTE.new(
+ :ordered_ancestors,
+ project.group.self_and_ancestors(hierarchy_order: :asc).reselect(:id)
+ )
+
+ cte_join_sources = authorizations.join(ordered_ancestors_cte.table).on(
+ authorizations[:group_id].eq(ordered_ancestors_cte.table[:id])
+ ).join_sources
+
+ Clusters::Agents::GroupAuthorization
+ .with(ordered_ancestors_cte.to_arel)
+ .joins(cte_join_sources)
+ .joins(agent: :project)
+ .where('projects.namespace_id IN (SELECT id FROM ordered_ancestors)')
+ .with_available_ci_access_fields(project)
+ .order(Arel.sql('agent_id, array_position(ARRAY(SELECT id FROM ordered_ancestors)::bigint[], agent_group_authorizations.group_id)'))
+ .select('DISTINCT ON (agent_id) agent_group_authorizations.*')
+ .preload(agent: :project)
+ .to_a
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/finders/environments/environments_by_deployments_finder.rb b/app/finders/environments/environments_by_deployments_finder.rb
index e0ecc98b1c0..a41cfcb37e4 100644
--- a/app/finders/environments/environments_by_deployments_finder.rb
+++ b/app/finders/environments/environments_by_deployments_finder.rb
@@ -23,12 +23,18 @@ module Environments
deployments.none
end
- environment_ids = deployments
- .group(:environment_id)
- .select(:environment_id)
+ environments =
+ if Feature.enabled?(:environments_by_deployments_finder_exists_optimization, default_enabled: :yaml)
+ project.environments.available
+ .where('EXISTS (?)', deployments.where('environment_id = environments.id'))
+ else
+ environment_ids = deployments
+ .group(:environment_id)
+ .select(:environment_id)
- environments = project.environments.available
- .where(id: environment_ids)
+ project.environments.available
+ .where(id: environment_ids)
+ end
if params[:find_latest]
find_one(environments.order_by_last_deployed_at_desc)
diff --git a/app/finders/events_finder.rb b/app/finders/events_finder.rb
index 4c619f3d7ea..4ed447a90ce 100644
--- a/app/finders/events_finder.rb
+++ b/app/finders/events_finder.rb
@@ -44,7 +44,6 @@ class EventsFinder
events = by_created_at_after(events)
events = sort(events)
- events = events.with_associations if params[:with_associations]
paginated_filtered_by_user_visibility(events)
end
@@ -113,10 +112,12 @@ class EventsFinder
end
def paginated_filtered_by_user_visibility(events)
+ events_count = events.count
+ events = events.with_associations if params[:with_associations]
limited_events = events.page(page).per(per_page)
visible_events = limited_events.select { |event| event.visible_to_user?(current_user) }
- Kaminari.paginate_array(visible_events, total_count: events.count)
+ Kaminari.paginate_array(visible_events, total_count: events_count)
end
def per_page
diff --git a/app/finders/issuables/label_filter.rb b/app/finders/issuables/label_filter.rb
index f4712fa6879..9a6ca107b19 100644
--- a/app/finders/issuables/label_filter.rb
+++ b/app/finders/issuables/label_filter.rb
@@ -82,6 +82,8 @@ module Issuables
if root_namespace
label_ids = find_label_ids(label_names).flatten(1)
+ return issuables if label_ids.empty?
+
issuables.where(label_link_query(target_model, label_ids: label_ids).arel.exists.not)
else
issuables.where(label_link_query(target_model, label_names: label_names).arel.exists.not)
@@ -133,11 +135,7 @@ module Issuables
# rubocop: disable CodeReuse/ActiveRecord
def label_link_query(target_model, label_ids: nil, label_names: nil)
- relation = LabelLink
- .where(target_type: target_model.name)
- .where(LabelLink.arel_table['target_id'].eq(target_model.arel_table['id']))
-
- relation = relation.where(label_id: label_ids) if label_ids
+ relation = LabelLink.by_target_for_exists_query(target_model.name, target_model.arel_table['id'], label_ids)
relation = relation.joins(:label).where(labels: { name: label_names }) if label_names
relation
diff --git a/app/finders/members_finder.rb b/app/finders/members_finder.rb
index 0faafa6df9c..e68a0c8fca9 100644
--- a/app/finders/members_finder.rb
+++ b/app/finders/members_finder.rb
@@ -70,16 +70,11 @@ class MembersFinder
end
def project_invited_groups
- invited_groups_and_ancestors = if ::Feature.enabled?(:linear_members_finder_ancestor_scopes, current_user, default_enabled: :yaml)
- project.invited_groups
- .self_and_ancestors
- else
- Gitlab::ObjectHierarchy
- .new(project.invited_groups)
- .base_and_ancestors
- end
-
- invited_groups_ids_including_ancestors = invited_groups_and_ancestors.public_or_visible_to_user(current_user).select(:id)
+ invited_groups_ids_including_ancestors = project
+ .invited_groups
+ .self_and_ancestors
+ .public_or_visible_to_user(current_user)
+ .select(:id)
GroupMember.with_source_id(invited_groups_ids_including_ancestors).non_minimal_access
end
diff --git a/app/finders/packages/group_packages_finder.rb b/app/finders/packages/group_packages_finder.rb
index 3ac5f00d518..2a62dd5c0e5 100644
--- a/app/finders/packages/group_packages_finder.rb
+++ b/app/finders/packages/group_packages_finder.rb
@@ -22,7 +22,7 @@ module Packages
def packages_for_group_projects(installable_only: false)
packages = ::Packages::Package
- .including_build_info
+ .preload_pipelines
.including_project_route
.including_tags
.for_projects(group_projects_visible_to_current_user.select(:id))
diff --git a/app/finders/packages/package_finder.rb b/app/finders/packages/package_finder.rb
index ee96896e350..e482a0503f0 100644
--- a/app/finders/packages/package_finder.rb
+++ b/app/finders/packages/package_finder.rb
@@ -9,7 +9,7 @@ module Packages
def execute
@project
.packages
- .including_build_info
+ .preload_pipelines
.including_project_route
.including_tags
.displayable
diff --git a/app/finders/packages/packages_finder.rb b/app/finders/packages/packages_finder.rb
index 552468ecfd1..3bc348c8dc8 100644
--- a/app/finders/packages/packages_finder.rb
+++ b/app/finders/packages/packages_finder.rb
@@ -14,9 +14,10 @@ module Packages
def execute
packages = project.packages
- .including_build_info
+ .preload_pipelines
.including_project_route
.including_tags
+
packages = filter_with_version(packages)
packages = filter_by_package_type(packages)
packages = filter_by_package_name(packages)
diff --git a/app/finders/security/security_jobs_finder.rb b/app/finders/security/security_jobs_finder.rb
index 008d4e29b13..5754492cfa7 100644
--- a/app/finders/security/security_jobs_finder.rb
+++ b/app/finders/security/security_jobs_finder.rb
@@ -13,7 +13,7 @@
module Security
class SecurityJobsFinder < JobsFinder
def self.allowed_job_types
- [:sast, :dast, :dependency_scanning, :container_scanning, :secret_detection, :coverage_fuzzing, :api_fuzzing, :cluster_image_scanning]
+ [:sast, :sast_iac, :dast, :dependency_scanning, :container_scanning, :secret_detection, :coverage_fuzzing, :api_fuzzing, :cluster_image_scanning]
end
end
end
diff --git a/app/finders/snippets_finder.rb b/app/finders/snippets_finder.rb
index 81643826782..b1e12721712 100644
--- a/app/finders/snippets_finder.rb
+++ b/app/finders/snippets_finder.rb
@@ -42,12 +42,11 @@ class SnippetsFinder < UnionFinder
include FinderMethods
include Gitlab::Utils::StrongMemoize
- attr_accessor :current_user, :params
- delegate :explore, :only_personal, :only_project, :scope, :sort, to: :params
+ attr_reader :current_user, :params
def initialize(current_user = nil, params = {})
@current_user = current_user
- @params = OpenStruct.new(params)
+ @params = params
if project && author
raise(
@@ -77,9 +76,9 @@ class SnippetsFinder < UnionFinder
private
def init_collection
- if explore
+ if explore?
snippets_for_explore
- elsif only_personal
+ elsif only_personal?
personal_snippets
elsif project
snippets_for_a_single_project
@@ -110,7 +109,7 @@ class SnippetsFinder < UnionFinder
# over the resulting SQL query.
def snippets_for_personal_and_multiple_projects
queries = []
- queries << personal_snippets unless only_project
+ queries << personal_snippets unless only_project?
if Ability.allowed?(current_user, :read_cross_project)
queries << snippets_of_visible_projects
@@ -171,7 +170,7 @@ class SnippetsFinder < UnionFinder
end
def visibility_from_scope
- case scope.to_s
+ case params[:scope].to_s
when 'are_private'
Snippet::PRIVATE
when 'are_internal'
@@ -206,7 +205,19 @@ class SnippetsFinder < UnionFinder
end
def sort_param
- sort.presence || 'id_desc'
+ params[:sort].presence || 'id_desc'
+ end
+
+ def explore?
+ params[:explore].present?
+ end
+
+ def only_personal?
+ params[:only_personal].present?
+ end
+
+ def only_project?
+ params[:only_project].present?
end
def prepared_union(queries)
diff --git a/app/finders/tags_finder.rb b/app/finders/tags_finder.rb
index 0ccbbdc1b87..6bc5419e704 100644
--- a/app/finders/tags_finder.rb
+++ b/app/finders/tags_finder.rb
@@ -5,11 +5,36 @@ class TagsFinder < GitRefsFinder
super(repository, params)
end
- def execute
- tags = repository.tags_sorted_by(sort)
+ def execute(gitaly_pagination: false)
+ tags = if gitaly_pagination
+ repository.tags_sorted_by(sort, pagination_params)
+ else
+ repository.tags_sorted_by(sort)
+ end
- [by_search(tags), nil]
- rescue Gitlab::Git::CommandError => e
- [[], e]
+ by_search(tags)
+
+ rescue ArgumentError => e
+ raise Gitlab::Git::InvalidPageToken, "Invalid page token: #{page_token}" if e.message.include?('page token')
+
+ raise
+ end
+
+ def total
+ repository.tag_count
+ end
+
+ private
+
+ def per_page
+ params[:per_page].presence
+ end
+
+ def page_token
+ "#{Gitlab::Git::TAG_REF_PREFIX}#{@params[:page_token]}" if params[:page_token]
+ end
+
+ def pagination_params
+ { limit: per_page, page_token: page_token }
end
end
diff --git a/app/graphql/gitlab_schema.rb b/app/graphql/gitlab_schema.rb
index 38ba1611c48..e15a185a743 100644
--- a/app/graphql/gitlab_schema.rb
+++ b/app/graphql/gitlab_schema.rb
@@ -10,11 +10,17 @@ class GitlabSchema < GraphQL::Schema
DEFAULT_MAX_DEPTH = 15
AUTHENTICATED_MAX_DEPTH = 20
+ # Tracers (order is important)
+ use Gitlab::Graphql::Tracers::ApplicationContextTracer
+ use Gitlab::Graphql::Tracers::MetricsTracer
+ use Gitlab::Graphql::Tracers::LoggerTracer
+ use Gitlab::Graphql::GenericTracing # Old tracer which will be removed eventually
+ use Gitlab::Graphql::Tracers::TimerTracer
+
use GraphQL::Subscriptions::ActionCableSubscriptions
use GraphQL::Pagination::Connections
use BatchLoader::GraphQL
use Gitlab::Graphql::Pagination::Connections
- use Gitlab::Graphql::GenericTracing
use Gitlab::Graphql::Timeout, max_seconds: Gitlab.config.gitlab.graphql_timeout
query_analyzer Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer.new
diff --git a/app/graphql/mutations/customer_relations/contacts/create.rb b/app/graphql/mutations/customer_relations/contacts/create.rb
index 77b4864468b..3495f30f227 100644
--- a/app/graphql/mutations/customer_relations/contacts/create.rb
+++ b/app/graphql/mutations/customer_relations/contacts/create.rb
@@ -42,13 +42,11 @@ module Mutations
required: false,
description: 'Description of or notes for the contact.'
- authorize :admin_contact
+ authorize :admin_crm_contact
def resolve(args)
group = authorized_find!(id: args[:group_id])
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless Feature.enabled?(:customer_relations, group, default_enabled: :yaml)
-
set_organization!(args)
result = ::CustomerRelations::Contacts::CreateService.new(group: group, current_user: current_user, params: args).execute
{ contact: result.payload, errors: result.errors }
diff --git a/app/graphql/mutations/customer_relations/contacts/update.rb b/app/graphql/mutations/customer_relations/contacts/update.rb
index e9e7c9b6abd..e2f671058f0 100644
--- a/app/graphql/mutations/customer_relations/contacts/update.rb
+++ b/app/graphql/mutations/customer_relations/contacts/update.rb
@@ -8,7 +8,7 @@ module Mutations
graphql_name 'CustomerRelationsContactUpdate'
- authorize :admin_contact
+ authorize :admin_crm_contact
field :contact,
Types::CustomerRelations::ContactType,
@@ -48,8 +48,6 @@ module Mutations
raise_resource_not_available_error! unless contact
group = contact.group
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless Feature.enabled?(:customer_relations, group, default_enabled: :yaml)
-
authorize!(group)
result = ::CustomerRelations::Contacts::UpdateService.new(group: group, current_user: current_user, params: args).execute(contact)
diff --git a/app/graphql/mutations/customer_relations/organizations/create.rb b/app/graphql/mutations/customer_relations/organizations/create.rb
index bb02e1f7346..17e0e9ad459 100644
--- a/app/graphql/mutations/customer_relations/organizations/create.rb
+++ b/app/graphql/mutations/customer_relations/organizations/create.rb
@@ -33,13 +33,11 @@ module Mutations
required: false,
description: 'Description of or notes for the organization.'
- authorize :admin_organization
+ authorize :admin_crm_organization
def resolve(args)
group = authorized_find!(id: args[:group_id])
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless Feature.enabled?(:customer_relations, group, default_enabled: :yaml)
-
result = ::CustomerRelations::Organizations::CreateService.new(group: group, current_user: current_user, params: args).execute
{ organization: result.payload, errors: result.errors }
end
diff --git a/app/graphql/mutations/customer_relations/organizations/update.rb b/app/graphql/mutations/customer_relations/organizations/update.rb
index d8eb55d77e9..21fcf565239 100644
--- a/app/graphql/mutations/customer_relations/organizations/update.rb
+++ b/app/graphql/mutations/customer_relations/organizations/update.rb
@@ -8,7 +8,7 @@ module Mutations
graphql_name 'CustomerRelationsOrganizationUpdate'
- authorize :admin_organization
+ authorize :admin_crm_organization
field :organization,
Types::CustomerRelations::OrganizationType,
@@ -39,8 +39,6 @@ module Mutations
raise_resource_not_available_error! unless organization
group = organization.group
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless Feature.enabled?(:customer_relations, group, default_enabled: :yaml)
-
authorize!(group)
result = ::CustomerRelations::Organizations::UpdateService.new(group: group, current_user: current_user, params: args).execute(organization)
diff --git a/app/graphql/mutations/issues/create.rb b/app/graphql/mutations/issues/create.rb
index 70a8f539ccf..72b03cc27c2 100644
--- a/app/graphql/mutations/issues/create.rb
+++ b/app/graphql/mutations/issues/create.rb
@@ -3,13 +3,14 @@
module Mutations
module Issues
class Create < BaseMutation
+ include Mutations::SpamProtection
include FindsProject
+ include CommonMutationArguments
+
graphql_name 'CreateIssue'
authorize :create_issue
- include CommonMutationArguments
-
argument :project_path, GraphQL::Types::ID,
required: true,
description: 'Project full path the issue is associated with.'
@@ -76,9 +77,7 @@ module Mutations
spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
issue = ::Issues::CreateService.new(project: project, current_user: current_user, params: params, spam_params: spam_params).execute
- if issue.spam?
- issue.errors.add(:base, 'Spam detected.')
- end
+ check_spam_action_response!(issue)
{
issue: issue.valid? ? issue : nil,
diff --git a/app/graphql/mutations/issues/set_crm_contacts.rb b/app/graphql/mutations/issues/set_crm_contacts.rb
new file mode 100644
index 00000000000..7a9e6237eaa
--- /dev/null
+++ b/app/graphql/mutations/issues/set_crm_contacts.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Issues
+ class SetCrmContacts < Base
+ graphql_name 'IssueSetCrmContacts'
+
+ argument :crm_contact_ids,
+ [::Types::GlobalIDType[::CustomerRelations::Contact]],
+ required: true,
+ description: 'Customer relations contact IDs to set. Replaces existing contacts by default.'
+
+ argument :operation_mode,
+ Types::MutationOperationModeEnum,
+ required: false,
+ description: 'Changes the operation mode. Defaults to REPLACE.'
+
+ def resolve(project_path:, iid:, crm_contact_ids:, operation_mode: Types::MutationOperationModeEnum.enum[:replace])
+ issue = authorized_find!(project_path: project_path, iid: iid)
+ project = issue.project
+ raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless Feature.enabled?(:customer_relations, project.group, default_enabled: :yaml)
+
+ crm_contact_ids = crm_contact_ids.compact.map do |crm_contact_id|
+ raise Gitlab::Graphql::Errors::ArgumentError, "Contact #{crm_contact_id} is invalid." unless crm_contact_id.respond_to?(:model_id)
+
+ crm_contact_id.model_id.to_i
+ end
+
+ attribute_name = case operation_mode
+ when Types::MutationOperationModeEnum.enum[:append]
+ :add_crm_contact_ids
+ when Types::MutationOperationModeEnum.enum[:remove]
+ :remove_crm_contact_ids
+ else
+ :crm_contact_ids
+ end
+
+ response = ::Issues::SetCrmContactsService.new(project: project, current_user: current_user, params: { attribute_name => crm_contact_ids })
+ .execute(issue)
+
+ {
+ issue: issue,
+ errors: response.errors
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/merge_requests/set_wip.rb b/app/graphql/mutations/merge_requests/set_wip.rb
deleted file mode 100644
index 9b6b67d4b4f..00000000000
--- a/app/graphql/mutations/merge_requests/set_wip.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module MergeRequests
- class SetWip < Base
- graphql_name 'MergeRequestSetWip'
-
- argument :wip,
- GraphQL::Types::Boolean,
- required: true,
- description: <<~DESC
- Whether or not to set the merge request as a draft.
- DESC
-
- def resolve(project_path:, iid:, wip: nil)
- merge_request = authorized_find!(project_path: project_path, iid: iid)
- project = merge_request.project
-
- ::MergeRequests::UpdateService.new(project: project, current_user: current_user, params: { wip_event: wip_event(merge_request, wip) })
- .execute(merge_request)
-
- {
- merge_request: merge_request,
- errors: errors_on_object(merge_request)
- }
- end
-
- private
-
- def wip_event(merge_request, wip)
- wip ? 'wip' : 'unwip'
- end
- end
- end
-end
diff --git a/app/graphql/mutations/merge_requests/toggle_attention_requested.rb b/app/graphql/mutations/merge_requests/toggle_attention_requested.rb
new file mode 100644
index 00000000000..f316f23fb85
--- /dev/null
+++ b/app/graphql/mutations/merge_requests/toggle_attention_requested.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Mutations
+ module MergeRequests
+ class ToggleAttentionRequested < Base
+ graphql_name 'MergeRequestToggleAttentionRequested'
+
+ argument :user_id, ::Types::GlobalIDType[::User],
+ loads: Types::UserType,
+ required: true,
+ description: <<~DESC
+ User ID for the user to toggle attention requested.
+ DESC
+
+ def resolve(project_path:, iid:, user:)
+ merge_request = authorized_find!(project_path: project_path, iid: iid)
+
+ result = ::MergeRequests::ToggleAttentionRequestedService.new(project: merge_request.project, current_user: current_user, merge_request: merge_request, user: user).execute
+
+ {
+ merge_request: merge_request,
+ errors: Array(result[:message])
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/security/ci_configuration/configure_sast_iac.rb b/app/graphql/mutations/security/ci_configuration/configure_sast_iac.rb
new file mode 100644
index 00000000000..a2073f10b1d
--- /dev/null
+++ b/app/graphql/mutations/security/ci_configuration/configure_sast_iac.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Security
+ module CiConfiguration
+ class ConfigureSastIac < BaseSecurityAnalyzer
+ graphql_name 'ConfigureSastIac'
+ description <<~DESC
+ Enable SAST IaC for a project in a new or
+ modified `.gitlab-ci.yml` file in a new branch. The new
+ branch and a URL to create a merge request are a part of the
+ response.
+ DESC
+
+ def configure_analyzer(project, **_args)
+ ::Security::CiConfiguration::SastIacCreateService.new(project, current_user).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/queries/epic/epic_children.query.graphql b/app/graphql/queries/epic/epic_children.query.graphql
index b0e55811b7d..be82813dddb 100644
--- a/app/graphql/queries/epic/epic_children.query.graphql
+++ b/app/graphql/queries/epic/epic_children.query.graphql
@@ -89,6 +89,7 @@ query childItems(
iid
epicIssueId
title
+ blocked
closedAt
state
createdAt
diff --git a/app/graphql/resolvers/base_issues_resolver.rb b/app/graphql/resolvers/base_issues_resolver.rb
new file mode 100644
index 00000000000..54ebb697cb2
--- /dev/null
+++ b/app/graphql/resolvers/base_issues_resolver.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class BaseIssuesResolver < BaseResolver
+ prepend IssueResolverArguments
+
+ argument :state, Types::IssuableStateEnum,
+ required: false,
+ description: 'Current state of this issue.'
+ argument :sort, Types::IssueSortEnum,
+ description: 'Sort issues by this criteria.',
+ required: false,
+ default_value: :created_desc
+
+ type Types::IssueType.connection_type, null: true
+
+ NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc
+ popularity_asc popularity_desc
+ label_priority_asc label_priority_desc
+ milestone_due_asc milestone_due_desc].freeze
+
+ def continue_issue_resolve(parent, finder, **args)
+ issues = Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all { |q| apply_lookahead(q) }
+
+ if non_stable_cursor_sort?(args[:sort])
+ # Certain complex sorts are not supported by the stable cursor pagination yet.
+ # In these cases, we use offset pagination, so we return the correct connection.
+ offset_pagination(issues)
+ else
+ issues
+ end
+ end
+
+ private
+
+ def unconditional_includes
+ [
+ {
+ project: [:project_feature]
+ },
+ :author
+ ]
+ end
+
+ def preloads
+ {
+ alert_management_alert: [:alert_management_alert],
+ labels: [:labels],
+ assignees: [:assignees],
+ timelogs: [:timelogs],
+ customer_relations_contacts: { customer_relations_contacts: [:group] }
+ }
+ end
+
+ def non_stable_cursor_sort?(sort)
+ NON_STABLE_CURSOR_SORTS.include?(sort)
+ end
+ end
+end
+
+Resolvers::BaseIssuesResolver.prepend_mod_with('Resolvers::BaseIssuesResolver')
diff --git a/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb b/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb
new file mode 100644
index 00000000000..35d30827561
--- /dev/null
+++ b/app/graphql/resolvers/ci/pipeline_job_artifacts_resolver.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Ci
+ class PipelineJobArtifactsResolver < BaseResolver
+ type [Types::Ci::JobArtifactType], null: false
+
+ alias_method :pipeline, :object
+
+ def resolve
+ find_job_artifacts
+ end
+
+ private
+
+ def find_job_artifacts
+ BatchLoader::GraphQL.for(pipeline).batch do |pipelines, loader|
+ ActiveRecord::Associations::Preloader.new.preload(pipelines, :job_artifacts) # rubocop: disable CodeReuse/ActiveRecord
+
+ pipelines.each { |pl| loader.call(pl, pl.job_artifacts) }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
index 855877110e5..38c79ff52ac 100644
--- a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
+++ b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
@@ -55,8 +55,8 @@ module IssueResolverArguments
description: 'Filter issues by the given issue types.',
required: false
argument :milestone_wildcard_id, ::Types::MilestoneWildcardIdEnum,
- required: false,
- description: 'Filter issues by milestone ID wildcard.'
+ required: false,
+ description: 'Filter issues by milestone ID wildcard.'
argument :my_reaction_emoji, GraphQL::Types::String,
required: false,
description: 'Filter by reaction emoji applied by the current user. Wildcard values "NONE" and "ANY" are supported.'
@@ -83,6 +83,7 @@ module IssueResolverArguments
args[:attempt_project_search_optimizations] = true if args[:search].present?
prepare_assignee_username_params(args)
+ prepare_release_tag_params(args)
finder = IssuesFinder.new(current_user, args)
@@ -93,6 +94,7 @@ module IssueResolverArguments
params_not_mutually_exclusive(args, mutually_exclusive_assignee_username_args)
params_not_mutually_exclusive(args, mutually_exclusive_milestone_args)
params_not_mutually_exclusive(args.fetch(:not, {}), mutually_exclusive_milestone_args)
+ params_not_mutually_exclusive(args, mutually_exclusive_release_tag_args)
validate_anonymous_search_access! if args[:search].present?
super
@@ -105,10 +107,30 @@ module IssueResolverArguments
complexity
end
+
+ def accept_release_tag
+ argument :release_tag, [GraphQL::Types::String],
+ required: false,
+ description: "Release tag associated with the issue's milestone."
+ argument :release_tag_wildcard_id, Types::ReleaseTagWildcardIdEnum,
+ required: false,
+ description: 'Filter issues by release tag ID wildcard.'
+ end
end
private
+ def prepare_release_tag_params(args)
+ release_tag_wildcard = args.delete(:release_tag_wildcard_id)
+ return if release_tag_wildcard.blank?
+
+ args[:release_tag] ||= release_tag_wildcard
+ end
+
+ def mutually_exclusive_release_tag_args
+ [:release_tag, :release_tag_wildcard_id]
+ end
+
def prepare_assignee_username_params(args)
args[:assignee_username] = args.delete(:assignee_usernames) if args[:assignee_usernames].present?
args[:not][:assignee_username] = args[:not].delete(:assignee_usernames) if args.dig(:not, :assignee_usernames).present?
diff --git a/app/graphql/resolvers/concerns/resolves_groups.rb b/app/graphql/resolvers/concerns/resolves_groups.rb
new file mode 100644
index 00000000000..c451d4e7936
--- /dev/null
+++ b/app/graphql/resolvers/concerns/resolves_groups.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+# Mixin for all resolver classes for type `Types::GroupType.connection_type`.
+module ResolvesGroups
+ extend ActiveSupport::Concern
+ include LooksAhead
+
+ def resolve_with_lookahead(**args)
+ apply_lookahead(resolve_groups(**args))
+ end
+
+ private
+
+ # The resolver should implement this method.
+ def resolve_groups(**args)
+ raise NotImplementedError
+ end
+
+ def preloads
+ {
+ contacts: [:contacts],
+ container_repositories_count: [:container_repositories],
+ custom_emoji: [:custom_emoji],
+ full_path: [:route],
+ organizations: [:organizations],
+ path: [:route],
+ dependency_proxy_blob_count: [:dependency_proxy_blobs],
+ dependency_proxy_blobs: [:dependency_proxy_blobs],
+ dependency_proxy_image_count: [:dependency_proxy_manifests],
+ dependency_proxy_image_ttl_policy: [:dependency_proxy_image_ttl_policy],
+ dependency_proxy_setting: [:dependency_proxy_setting]
+ }
+ end
+end
diff --git a/app/graphql/resolvers/concerns/resolves_pipelines.rb b/app/graphql/resolvers/concerns/resolves_pipelines.rb
index 7fb0852b11e..1c01e5e0250 100644
--- a/app/graphql/resolvers/concerns/resolves_pipelines.rb
+++ b/app/graphql/resolvers/concerns/resolves_pipelines.rb
@@ -9,6 +9,9 @@ module ResolvesPipelines
Types::Ci::PipelineStatusEnum,
required: false,
description: "Filter pipelines by their status."
+ argument :scope, ::Types::Ci::PipelineScopeEnum,
+ required: false,
+ description: 'Filter pipelines by scope.'
argument :ref,
GraphQL::Types::String,
required: false,
diff --git a/app/graphql/resolvers/group_issues_resolver.rb b/app/graphql/resolvers/group_issues_resolver.rb
index 1db0ab08e31..28f9266974f 100644
--- a/app/graphql/resolvers/group_issues_resolver.rb
+++ b/app/graphql/resolvers/group_issues_resolver.rb
@@ -1,10 +1,18 @@
# frozen_string_literal: true
-# rubocop:disable Graphql/ResolverType (inherited from IssuesResolver)
+# rubocop:disable Graphql/ResolverType (inherited from BaseIssuesResolver)
module Resolvers
- class GroupIssuesResolver < IssuesResolver
+ class GroupIssuesResolver < BaseIssuesResolver
include GroupIssuableResolver
include_subgroups 'issues'
+
+ def ready?(**args)
+ if args.dig(:not, :release_tag).present?
+ raise ::Gitlab::Graphql::Errors::ArgumentError, 'releaseTag filter is not allowed when parent is a group.'
+ end
+
+ super
+ end
end
end
diff --git a/app/graphql/resolvers/groups_resolver.rb b/app/graphql/resolvers/groups_resolver.rb
index b090fdc49d4..abd3bf9e6e0 100644
--- a/app/graphql/resolvers/groups_resolver.rb
+++ b/app/graphql/resolvers/groups_resolver.rb
@@ -2,6 +2,8 @@
module Resolvers
class GroupsResolver < BaseResolver
+ include ResolvesGroups
+
type Types::GroupType, null: true
argument :include_parent_descendants, GraphQL::Types::Boolean,
@@ -19,16 +21,12 @@ module Resolvers
alias_method :parent, :object
- def resolve(**args)
- return [] unless parent.present?
-
- find_groups(args)
- end
-
private
# rubocop: disable CodeReuse/ActiveRecord
- def find_groups(args)
+ def resolve_groups(args)
+ return Group.none unless parent.present?
+
GroupsFinder
.new(context[:current_user], args.merge(parent: parent))
.execute
diff --git a/app/graphql/resolvers/issue_status_counts_resolver.rb b/app/graphql/resolvers/issue_status_counts_resolver.rb
index 58cff559d0d..db5c91daac2 100644
--- a/app/graphql/resolvers/issue_status_counts_resolver.rb
+++ b/app/graphql/resolvers/issue_status_counts_resolver.rb
@@ -5,6 +5,7 @@ module Resolvers
prepend IssueResolverArguments
type Types::IssueStatusCountsType, null: true
+ accept_release_tag
extras [:lookahead]
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
index b556964ae0c..4b52ef61d57 100644
--- a/app/graphql/resolvers/issues_resolver.rb
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -1,61 +1,8 @@
# frozen_string_literal: true
+# rubocop:disable Graphql/ResolverType (inherited from BaseIssuesResolver)
module Resolvers
- class IssuesResolver < BaseResolver
- prepend IssueResolverArguments
-
- argument :state, Types::IssuableStateEnum,
- required: false,
- description: 'Current state of this issue.'
- argument :sort, Types::IssueSortEnum,
- description: 'Sort issues by this criteria.',
- required: false,
- default_value: :created_desc
-
- type Types::IssueType.connection_type, null: true
-
- NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc
- popularity_asc popularity_desc
- label_priority_asc label_priority_desc
- milestone_due_asc milestone_due_desc].freeze
-
- def continue_issue_resolve(parent, finder, **args)
- issues = Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all { |q| apply_lookahead(q) }
-
- if non_stable_cursor_sort?(args[:sort])
- # Certain complex sorts are not supported by the stable cursor pagination yet.
- # In these cases, we use offset pagination, so we return the correct connection.
- offset_pagination(issues)
- else
- issues
- end
- end
-
- private
-
- def unconditional_includes
- [
- {
- project: [:project_feature]
- },
- :author
- ]
- end
-
- def preloads
- {
- alert_management_alert: [:alert_management_alert],
- labels: [:labels],
- assignees: [:assignees],
- timelogs: [:timelogs],
- customer_relations_contacts: { customer_relations_contacts: [:group] }
- }
- end
-
- def non_stable_cursor_sort?(sort)
- NON_STABLE_CURSOR_SORTS.include?(sort)
- end
+ class IssuesResolver < BaseIssuesResolver
+ accept_release_tag
end
end
-
-Resolvers::IssuesResolver.prepend_mod_with('Resolvers::IssuesResolver')
diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb
index c0dd61078c6..bd7f1f0774e 100644
--- a/app/graphql/resolvers/merge_requests_resolver.rb
+++ b/app/graphql/resolvers/merge_requests_resolver.rb
@@ -68,6 +68,12 @@ module Resolvers
description: 'Sort merge requests by this criteria.',
required: false,
default_value: :created_desc
+ argument :created_after, Types::TimeType,
+ required: false,
+ description: 'Merge requests created after this timestamp.'
+ argument :created_before, Types::TimeType,
+ required: false,
+ description: 'Merge requests created before this timestamp.'
negated do
argument :labels, [GraphQL::Types::String],
diff --git a/app/graphql/resolvers/topics_resolver.rb b/app/graphql/resolvers/topics_resolver.rb
new file mode 100644
index 00000000000..d8199f3d89b
--- /dev/null
+++ b/app/graphql/resolvers/topics_resolver.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class TopicsResolver < BaseResolver
+ type Types::Projects::TopicType, null: true
+
+ argument :search, GraphQL::Types::String,
+ required: false,
+ description: 'Search query for topic name.'
+
+ def resolve(**args)
+ if args[:search].present?
+ ::Projects::Topic.search(args[:search]).order_by_total_projects_count
+ else
+ ::Projects::Topic.order_by_total_projects_count
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/users/groups_resolver.rb b/app/graphql/resolvers/users/groups_resolver.rb
index 0899b08e19c..eafb56d8f4c 100644
--- a/app/graphql/resolvers/users/groups_resolver.rb
+++ b/app/graphql/resolvers/users/groups_resolver.rb
@@ -3,8 +3,8 @@
module Resolvers
module Users
class GroupsResolver < BaseResolver
+ include ResolvesGroups
include Gitlab::Graphql::Authorize::AuthorizeResource
- include LooksAhead
type Types::GroupType.connection_type, null: true
@@ -20,22 +20,17 @@ module Resolvers
description: 'Filter by permissions the user has on groups.'
before_connection_authorization do |nodes, current_user|
- Preloaders::UserMaxAccessLevelInGroupsPreloader.new(nodes, current_user).execute
+ Preloaders::GroupPolicyPreloader.new(nodes, current_user).execute
end
- def resolve_with_lookahead(**args)
- return unless Feature.enabled?(:paginatable_namespace_drop_down_for_project_creation, current_user, default_enabled: :yaml)
-
- apply_lookahead(Groups::UserGroupsFinder.new(current_user, object, args).execute)
+ def ready?(**args)
+ Feature.enabled?(:paginatable_namespace_drop_down_for_project_creation, current_user, default_enabled: :yaml)
end
private
- def preloads
- {
- path: [:route],
- full_path: [:route]
- }
+ def resolve_groups(**args)
+ Groups::UserGroupsFinder.new(current_user, object, args).execute
end
end
end
diff --git a/app/graphql/types/ci/job_artifact_type.rb b/app/graphql/types/ci/job_artifact_type.rb
index f80681bcf36..69bb5325dba 100644
--- a/app/graphql/types/ci/job_artifact_type.rb
+++ b/app/graphql/types/ci/job_artifact_type.rb
@@ -12,6 +12,10 @@ module Types
field :file_type, ::Types::Ci::JobArtifactFileTypeEnum, null: true,
description: 'File type of the artifact.'
+ field :name, GraphQL::Types::String, null: true,
+ description: 'File name of the artifact.',
+ method: :filename
+
def download_path
::Gitlab::Routing.url_helpers.download_project_job_artifacts_path(
object.project,
diff --git a/app/graphql/types/ci/pipeline_scope_enum.rb b/app/graphql/types/ci/pipeline_scope_enum.rb
new file mode 100644
index 00000000000..3ce81bc7bf3
--- /dev/null
+++ b/app/graphql/types/ci/pipeline_scope_enum.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class PipelineScopeEnum < BaseEnum
+ SCOPES_DESCRIPTION = {
+ running: 'Pipeline is running.',
+ pending: 'Pipeline has not started running yet.',
+ finished: 'Pipeline has completed.',
+ branches: 'Branches.',
+ tags: 'Tags.'
+ }.freeze
+
+ SCOPES_DESCRIPTION.each do |scope, description|
+ value scope.to_s.upcase,
+ description: description,
+ value: scope.to_s
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci/pipeline_status_enum.rb b/app/graphql/types/ci/pipeline_status_enum.rb
index 2800454a999..c8e031e18ea 100644
--- a/app/graphql/types/ci/pipeline_status_enum.rb
+++ b/app/graphql/types/ci/pipeline_status_enum.rb
@@ -3,10 +3,24 @@
module Types
module Ci
class PipelineStatusEnum < BaseEnum
- ::Ci::Pipeline.all_state_names.each do |state_symbol|
- value state_symbol.to_s.upcase,
- description: "#{::Ci::Pipeline::STATUSES_DESCRIPTION[state_symbol]}.",
- value: state_symbol.to_s
+ STATUSES_DESCRIPTION = {
+ created: 'Pipeline has been created.',
+ waiting_for_resource: 'A resource (for example, a runner) that the pipeline requires to run is unavailable.',
+ preparing: 'Pipeline is preparing to run.',
+ pending: 'Pipeline has not started running yet.',
+ running: 'Pipeline is running.',
+ failed: 'At least one stage of the pipeline failed.',
+ success: 'Pipeline completed successfully.',
+ canceled: 'Pipeline was canceled before completion.',
+ skipped: 'Pipeline was skipped.',
+ manual: 'Pipeline needs to be manually started.',
+ scheduled: 'Pipeline is scheduled to run.'
+ }.freeze
+
+ STATUSES_DESCRIPTION.each do |state, description|
+ value state.to_s.upcase,
+ description: description,
+ value: state.to_s
end
end
end
diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb
index 493ce188d9b..da2f11be9e2 100644
--- a/app/graphql/types/ci/pipeline_type.rb
+++ b/app/graphql/types/ci/pipeline_type.rb
@@ -108,6 +108,11 @@ module Types
description: 'Name of the job.'
end
+ field :job_artifacts,
+ null: true,
+ description: 'Job artifacts of the pipeline.',
+ resolver: ::Resolvers::Ci::PipelineJobArtifactsResolver
+
field :source_job,
type: Types::Ci::JobType,
null: true,
@@ -125,6 +130,10 @@ module Types
field :path, GraphQL::Types::String, null: true,
description: "Relative path to the pipeline's page."
+ field :commit, Types::CommitType, null: true,
+ description: "Git commit of the pipeline.",
+ calls_gitaly: true
+
field :commit_path, GraphQL::Types::String, null: true,
description: 'Path to the commit that triggered the pipeline.'
diff --git a/app/graphql/types/ci/runner_setup_type.rb b/app/graphql/types/ci/runner_setup_type.rb
index 70f33cef8ad..b6b020db40e 100644
--- a/app/graphql/types/ci/runner_setup_type.rb
+++ b/app/graphql/types/ci/runner_setup_type.rb
@@ -9,7 +9,7 @@ module Types
field :install_instructions, GraphQL::Types::String, null: false,
description: 'Instructions for installing the runner on the specified architecture.'
field :register_instructions, GraphQL::Types::String, null: true,
- description: 'Instructions for registering the runner.'
+ description: 'Instructions for registering the runner. The actual registration tokens are not included in the commands. Instead, a placeholder `$REGISTRATION_TOKEN` is shown.'
end
end
end
diff --git a/app/graphql/types/commit_type.rb b/app/graphql/types/commit_type.rb
index dc1bf6a3101..7d141bd6daa 100644
--- a/app/graphql/types/commit_type.rb
+++ b/app/graphql/types/commit_type.rb
@@ -14,12 +14,19 @@ module Types
description: 'SHA1 ID of the commit.'
field :short_id, type: GraphQL::Types::String, null: false,
description: 'Short SHA1 ID of the commit.'
+
field :title, type: GraphQL::Types::String, null: true, calls_gitaly: true,
description: 'Title of the commit message.'
markdown_field :title_html, null: true
+
+ field :full_title, type: GraphQL::Types::String, null: true, calls_gitaly: true,
+ description: 'Full title of the commit message.'
+ markdown_field :full_title_html, null: true
+
field :description, type: GraphQL::Types::String, null: true,
description: 'Description of the commit message.'
markdown_field :description_html, null: true
+
field :message, type: GraphQL::Types::String, null: true,
description: 'Raw commit message.'
field :authored_date, type: Types::TimeType, null: true,
diff --git a/app/graphql/types/customer_relations/contact_type.rb b/app/graphql/types/customer_relations/contact_type.rb
index b5224a3e239..6a3882c66af 100644
--- a/app/graphql/types/customer_relations/contact_type.rb
+++ b/app/graphql/types/customer_relations/contact_type.rb
@@ -5,7 +5,7 @@ module Types
class ContactType < BaseObject
graphql_name 'CustomerRelationsContact'
- authorize :read_contact
+ authorize :read_crm_contact
field :id,
GraphQL::Types::ID,
diff --git a/app/graphql/types/customer_relations/organization_type.rb b/app/graphql/types/customer_relations/organization_type.rb
index 9b22fa35b11..0f97f0a2433 100644
--- a/app/graphql/types/customer_relations/organization_type.rb
+++ b/app/graphql/types/customer_relations/organization_type.rb
@@ -5,7 +5,7 @@ module Types
class OrganizationType < BaseObject
graphql_name 'CustomerRelationsOrganization'
- authorize :read_organization
+ authorize :read_crm_organization
field :id,
GraphQL::Types::ID,
diff --git a/app/graphql/types/dependency_proxy/manifest_type.rb b/app/graphql/types/dependency_proxy/manifest_type.rb
index 9aa62266ef7..ef9f730df43 100644
--- a/app/graphql/types/dependency_proxy/manifest_type.rb
+++ b/app/graphql/types/dependency_proxy/manifest_type.rb
@@ -8,6 +8,7 @@ module Types
authorize :read_dependency_proxy
+ field :id, ::Types::GlobalIDType[::DependencyProxy::Manifest], null: false, description: 'ID of the manifest.'
field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
field :file_name, GraphQL::Types::String, null: false, description: 'Name of the manifest.'
diff --git a/app/graphql/types/evidence_type.rb b/app/graphql/types/evidence_type.rb
index 26fb64d25d8..33f46c712f1 100644
--- a/app/graphql/types/evidence_type.rb
+++ b/app/graphql/types/evidence_type.rb
@@ -5,7 +5,7 @@ module Types
graphql_name 'ReleaseEvidence'
description 'Evidence for a release'
- authorize :download_code
+ authorize :read_release_evidence
present_using Releases::EvidencePresenter
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index b1bbabcdaed..4a20d84f2ab 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -34,6 +34,7 @@ module Types
null: true,
method: :project_creation_level_str,
description: 'Permission level required to create projects in the group.'
+
field :subgroup_creation_level,
type: GraphQL::Types::String,
null: true,
@@ -44,6 +45,7 @@ module Types
type: GraphQL::Types::Boolean,
null: true,
description: 'Indicates if all users in this group are required to set up two-factor authentication.'
+
field :two_factor_grace_period,
type: GraphQL::Types::Int,
null: true,
@@ -220,12 +222,16 @@ module Types
group.container_repositories.size
end
+ def dependency_proxy_manifests
+ group.dependency_proxy_manifests.order_id_desc
+ end
+
def dependency_proxy_image_count
- group.dependency_proxy_manifests.count
+ group.dependency_proxy_manifests.size
end
def dependency_proxy_blob_count
- group.dependency_proxy_blobs.count
+ group.dependency_proxy_blobs.size
end
def dependency_proxy_total_size
diff --git a/app/graphql/types/issues/negated_issue_filter_input_type.rb b/app/graphql/types/issues/negated_issue_filter_input_type.rb
index c8b7cdaa68e..73e090a4802 100644
--- a/app/graphql/types/issues/negated_issue_filter_input_type.rb
+++ b/app/graphql/types/issues/negated_issue_filter_input_type.rb
@@ -14,6 +14,9 @@ module Types
argument :milestone_title, [GraphQL::Types::String],
required: false,
description: 'Milestone not applied to this issue.'
+ argument :release_tag, [GraphQL::Types::String],
+ required: false,
+ description: "Release tag not associated with the issue's milestone. Ignored when parent is a group."
argument :author_username, GraphQL::Types::String,
required: false,
description: "Username of a user who didn't author the issue."
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 004ac364487..a0f00ddc3c6 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -53,9 +53,6 @@ module Types
description: 'Indicates if the source branch is protected.'
field :target_branch, GraphQL::Types::String, null: false,
description: 'Target branch of the merge request.'
- field :work_in_progress, GraphQL::Types::Boolean, method: :work_in_progress?, null: false,
- deprecated: { reason: 'Use `draft`', milestone: '13.12' },
- description: 'Indicates if the merge request is a draft.'
field :draft, GraphQL::Types::Boolean, method: :draft?, null: false,
description: 'Indicates if the merge request is a draft.'
field :merge_when_pipeline_succeeds, GraphQL::Types::Boolean, null: true,
@@ -102,7 +99,8 @@ module Types
field :default_merge_commit_message, GraphQL::Types::String, null: true,
description: 'Default merge commit message of the merge request.'
field :default_merge_commit_message_with_description, GraphQL::Types::String, null: true,
- description: 'Default merge commit message of the merge request with description.'
+ description: 'Default merge commit message of the merge request with description. Will have the same value as `defaultMergeCommitMessage` when project has `mergeCommitTemplate` set.',
+ deprecated: { reason: 'Define merge commit template in project and use `defaultMergeCommitMessage`', milestone: '14.5' }
field :default_squash_commit_message, GraphQL::Types::String, null: true, calls_gitaly: true,
description: 'Default squash commit message of the merge request.'
field :merge_ongoing, GraphQL::Types::Boolean, method: :merge_ongoing?, null: false,
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index cd4c45d2942..e8a952e9c61 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -16,6 +16,7 @@ module Types
mount_mutation Mutations::AlertManagement::HttpIntegration::ResetToken
mount_mutation Mutations::AlertManagement::HttpIntegration::Destroy
mount_mutation Mutations::Security::CiConfiguration::ConfigureSast
+ mount_mutation Mutations::Security::CiConfiguration::ConfigureSastIac
mount_mutation Mutations::Security::CiConfiguration::ConfigureSecretDetection
mount_mutation Mutations::AlertManagement::PrometheusIntegration::Create
mount_mutation Mutations::AlertManagement::PrometheusIntegration::Update
@@ -48,6 +49,7 @@ module Types
mount_mutation Mutations::Environments::CanaryIngress::Update
mount_mutation Mutations::Issues::Create
mount_mutation Mutations::Issues::SetAssignees
+ mount_mutation Mutations::Issues::SetCrmContacts
mount_mutation Mutations::Issues::SetConfidential
mount_mutation Mutations::Issues::SetLocked
mount_mutation Mutations::Issues::SetDueDate
@@ -63,12 +65,10 @@ module Types
mount_mutation Mutations::MergeRequests::SetLocked
mount_mutation Mutations::MergeRequests::SetMilestone
mount_mutation Mutations::MergeRequests::SetSubscription
- mount_mutation Mutations::MergeRequests::SetWip,
- calls_gitaly: true,
- deprecated: { reason: 'Use mergeRequestSetDraft', milestone: '13.12' }
mount_mutation Mutations::MergeRequests::SetDraft, calls_gitaly: true
mount_mutation Mutations::MergeRequests::SetAssignees
mount_mutation Mutations::MergeRequests::ReviewerRereview
+ mount_mutation Mutations::MergeRequests::ToggleAttentionRequested, feature_flag: :mr_attention_requests
mount_mutation Mutations::Metrics::Dashboard::Annotations::Create
mount_mutation Mutations::Metrics::Dashboard::Annotations::Delete
mount_mutation Mutations::Notes::Create::Note, calls_gitaly: true
diff --git a/app/graphql/types/packages/file_metadata_type.rb b/app/graphql/types/packages/file_metadata_type.rb
index 46ccb424218..0731fc897a2 100644
--- a/app/graphql/types/packages/file_metadata_type.rb
+++ b/app/graphql/types/packages/file_metadata_type.rb
@@ -14,6 +14,8 @@ module Types
case object
when ::Packages::Conan::FileMetadatum
::Types::Packages::Conan::FileMetadatumType
+ when ::Packages::Helm::FileMetadatum
+ ::Types::Packages::Helm::FileMetadatumType
else
# NOTE: This method must be kept in sync with `PackageFileType#file_metadata`,
# which must never produce data that this discriminator cannot handle.
@@ -21,7 +23,8 @@ module Types
end
end
- orphan_types Types::Packages::Conan::FileMetadatumType
+ orphan_types Types::Packages::Conan::FileMetadatumType,
+ Types::Packages::Helm::FileMetadatumType
end
end
end
diff --git a/app/graphql/types/packages/helm/dependency_type.rb b/app/graphql/types/packages/helm/dependency_type.rb
new file mode 100644
index 00000000000..35598c2b1d7
--- /dev/null
+++ b/app/graphql/types/packages/helm/dependency_type.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Helm
+ # rubocop: disable Graphql/AuthorizeTypes
+ class DependencyType < BaseObject
+ graphql_name 'PackageHelmDependencyType'
+ description 'Represents a Helm dependency'
+
+ # Need to be synced with app/validators/json_schemas/helm_metadata.json#dependencies
+ field :name, GraphQL::Types::String, null: true, description: 'Name of the dependency.'
+ field :version, GraphQL::Types::String, null: true, description: 'Version of the dependency.'
+ field :repository, GraphQL::Types::String, null: true, description: 'Repository of the dependency.'
+ field :condition, GraphQL::Types::String, null: true, description: 'Condition of the dependency.'
+ field :tags, [GraphQL::Types::String], null: true, description: 'Tags of the dependency.'
+ field :enabled, GraphQL::Types::Boolean, null: true, description: 'Indicates the dependency is enabled.'
+ field :import_values, [GraphQL::Types::JSON], null: true, description: 'Import-values of the dependency.', hash_key: "import-values" # rubocop:disable Graphql/JSONType
+ field :alias, GraphQL::Types::String, null: true, description: 'Alias of the dependency.', resolver_method: :resolve_alias
+
+ # field :alias` conflicts with a built-in method
+ def resolve_alias
+ object['alias']
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/helm/file_metadatum_type.rb b/app/graphql/types/packages/helm/file_metadatum_type.rb
new file mode 100644
index 00000000000..734ed52df40
--- /dev/null
+++ b/app/graphql/types/packages/helm/file_metadatum_type.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Helm
+ class FileMetadatumType < BaseObject
+ graphql_name 'HelmFileMetadata'
+ description 'Helm file metadata'
+
+ implements Types::Packages::FileMetadataType
+
+ authorize :read_package
+
+ field :channel, GraphQL::Types::String, null: false, description: 'Channel of the Helm chart.'
+ field :metadata, Types::Packages::Helm::MetadataType, null: false, description: 'Metadata of the Helm chart.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/helm/maintainer_type.rb b/app/graphql/types/packages/helm/maintainer_type.rb
new file mode 100644
index 00000000000..6d25a26c46b
--- /dev/null
+++ b/app/graphql/types/packages/helm/maintainer_type.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Helm
+ # rubocop: disable Graphql/AuthorizeTypes
+ class MaintainerType < BaseObject
+ graphql_name 'PackageHelmMaintainerType'
+ description 'Represents a Helm maintainer'
+
+ # Need to be synced with app/validators/json_schemas/helm_metadata.json#maintainers
+ field :name, GraphQL::Types::String, null: true, description: 'Name of the maintainer.'
+ field :email, GraphQL::Types::String, null: true, description: 'Email of the maintainer.'
+ field :url, GraphQL::Types::String, null: true, description: 'URL of the maintainer.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/helm/metadata_type.rb b/app/graphql/types/packages/helm/metadata_type.rb
new file mode 100644
index 00000000000..eeb3e8087a8
--- /dev/null
+++ b/app/graphql/types/packages/helm/metadata_type.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Helm
+ # rubocop: disable Graphql/AuthorizeTypes
+ class MetadataType < BaseObject
+ graphql_name 'PackageHelmMetadataType'
+ description 'Represents the contents of a Helm Chart.yml file'
+
+ # Need to be synced with app/validators/json_schemas/helm_metadata.json
+ field :name, GraphQL::Types::String, null: false, description: 'Name of the chart.'
+ field :home, GraphQL::Types::String, null: true, description: 'URL of the home page.'
+ field :sources, [GraphQL::Types::String], null: true, description: 'URLs of the source code for the chart.'
+ field :version, GraphQL::Types::String, null: false, description: 'Version of the chart.'
+ field :description, GraphQL::Types::String, null: true, description: 'Description of the chart.'
+ field :keywords, [GraphQL::Types::String], null: true, description: 'Keywords for the chart.'
+ field :maintainers, [Types::Packages::Helm::MaintainerType], null: true, description: 'Maintainers of the chart.'
+ field :icon, GraphQL::Types::String, null: true, description: 'URL to an SVG or PNG image for the chart.'
+ field :api_version, GraphQL::Types::String, null: false, description: 'API version of the chart.', hash_key: "apiVersion"
+ field :condition, GraphQL::Types::String, null: true, description: 'Condition for the chart.'
+ field :tags, GraphQL::Types::String, null: true, description: 'Tags for the chart.'
+ field :app_version, GraphQL::Types::String, null: true, description: 'App version of the chart.', hash_key: "appVersion"
+ field :deprecated, GraphQL::Types::Boolean, null: true, description: 'Indicates if the chart is deprecated.'
+ field :annotations, GraphQL::Types::JSON, null: true, description: 'Annotations for the chart.' # rubocop:disable Graphql/JSONType
+ field :kube_version, GraphQL::Types::String, null: true, description: 'Kubernetes versions for the chart.', hash_key: "kubeVersion"
+ field :dependencies, [Types::Packages::Helm::DependencyType], null: true, description: 'Dependencies of the chart.'
+ field :type, GraphQL::Types::String, null: true, description: 'Type of the chart.', hash_key: "appVersion"
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/package_file_type.rb b/app/graphql/types/packages/package_file_type.rb
index 8cc0f9b984a..f90a0992bf8 100644
--- a/app/graphql/types/packages/package_file_type.rb
+++ b/app/graphql/types/packages/package_file_type.rb
@@ -27,6 +27,8 @@ module Types
case object.package.package_type
when 'conan'
object.conan_file_metadatum
+ when 'helm'
+ object.helm_file_metadatum
else
nil
end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 791875242df..b6cb9cd3302 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -306,7 +306,7 @@ module Types
null: true,
description: 'A single release of the project.',
resolver: Resolvers::ReleasesResolver.single,
- authorize: :download_code
+ authorize: :read_release
field :container_expiration_policy,
Types::ContainerExpirationPolicyType,
@@ -381,6 +381,11 @@ module Types
description: 'Cluster agents associated with the project.',
resolver: ::Resolvers::Clusters::AgentsResolver
+ field :merge_commit_template,
+ GraphQL::Types::String,
+ null: true,
+ description: 'Template used to create merge commit message in merge requests.'
+
def label(title:)
BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args|
LabelsFinder
diff --git a/app/graphql/types/projects/topic_type.rb b/app/graphql/types/projects/topic_type.rb
new file mode 100644
index 00000000000..79ab69e794b
--- /dev/null
+++ b/app/graphql/types/projects/topic_type.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Types
+ module Projects
+ # rubocop: disable Graphql/AuthorizeTypes
+ class TopicType < BaseObject
+ graphql_name 'Topic'
+
+ field :id, GraphQL::Types::ID, null: false,
+ description: 'ID of the topic.'
+
+ field :name, GraphQL::Types::String, null: false,
+ description: 'Name of the topic.'
+
+ field :description, GraphQL::Types::String, null: true,
+ description: 'Description of the topic.'
+ markdown_field :description_html, null: true
+
+ field :avatar_url, GraphQL::Types::String, null: true,
+ description: 'URL to avatar image file of the topic.'
+
+ def avatar_url
+ object.avatar_url(only_path: false)
+ end
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+ end
+end
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index ed4ddbb982b..4a4d6727c3f 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -140,6 +140,11 @@ module Types
null: true,
resolver: Resolvers::BoardListResolver
+ field :topics, Types::Projects::TopicType.connection_type,
+ null: true,
+ resolver: Resolvers::TopicsResolver,
+ description: "Find project topics."
+
def design_management
DesignManagementObject.new(nil)
end
diff --git a/app/graphql/types/release_links_type.rb b/app/graphql/types/release_links_type.rb
index 7830e29f3cd..37ad52ce6d0 100644
--- a/app/graphql/types/release_links_type.rb
+++ b/app/graphql/types/release_links_type.rb
@@ -4,7 +4,7 @@ module Types
class ReleaseLinksType < BaseObject
graphql_name 'ReleaseLinks'
- authorize :download_code
+ authorize :read_release
alias_method :release, :object
@@ -16,14 +16,19 @@ module Types
description: "HTTP URL of the release's edit page.",
authorize: :update_release
field :opened_merge_requests_url, GraphQL::Types::String, null: true,
- description: 'HTTP URL of the merge request page, filtered by this release and `state=open`.'
+ description: 'HTTP URL of the merge request page, filtered by this release and `state=open`.',
+ authorize: :download_code
field :merged_merge_requests_url, GraphQL::Types::String, null: true,
- description: 'HTTP URL of the merge request page , filtered by this release and `state=merged`.'
+ description: 'HTTP URL of the merge request page , filtered by this release and `state=merged`.',
+ authorize: :download_code
field :closed_merge_requests_url, GraphQL::Types::String, null: true,
- description: 'HTTP URL of the merge request page , filtered by this release and `state=closed`.'
+ description: 'HTTP URL of the merge request page , filtered by this release and `state=closed`.',
+ authorize: :download_code
field :opened_issues_url, GraphQL::Types::String, null: true,
- description: 'HTTP URL of the issues page, filtered by this release and `state=open`.'
+ description: 'HTTP URL of the issues page, filtered by this release and `state=open`.',
+ authorize: :download_code
field :closed_issues_url, GraphQL::Types::String, null: true,
- description: 'HTTP URL of the issues page, filtered by this release and `state=closed`.'
+ description: 'HTTP URL of the issues page, filtered by this release and `state=closed`.',
+ authorize: :download_code
end
end
diff --git a/app/graphql/types/release_tag_wildcard_id_enum.rb b/app/graphql/types/release_tag_wildcard_id_enum.rb
new file mode 100644
index 00000000000..27765864101
--- /dev/null
+++ b/app/graphql/types/release_tag_wildcard_id_enum.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Types
+ class ReleaseTagWildcardIdEnum < BaseEnum
+ graphql_name 'ReleaseTagWildcardId'
+ description 'Release tag ID wildcard values'
+
+ value 'NONE', 'No release tag is assigned.'
+ value 'ANY', 'Release tag is assigned.'
+ end
+end
diff --git a/app/graphql/types/release_type.rb b/app/graphql/types/release_type.rb
index 6dda93c7329..fcc9ec49252 100644
--- a/app/graphql/types/release_type.rb
+++ b/app/graphql/types/release_type.rb
@@ -14,8 +14,7 @@ module Types
present_using ReleasePresenter
field :tag_name, GraphQL::Types::String, null: true, method: :tag,
- description: 'Name of the tag associated with the release.',
- authorize: :download_code
+ description: 'Name of the tag associated with the release.'
field :tag_path, GraphQL::Types::String, null: true,
description: 'Relative web path to the tag associated with the release.',
authorize: :download_code
diff --git a/app/graphql/types/repository/blob_type.rb b/app/graphql/types/repository/blob_type.rb
index ef7f535212f..104171e6772 100644
--- a/app/graphql/types/repository/blob_type.rb
+++ b/app/graphql/types/repository/blob_type.rb
@@ -68,6 +68,9 @@ module Types
field :replace_path, GraphQL::Types::String, null: true,
description: 'Web path to replace the blob content.'
+ field :pipeline_editor_path, GraphQL::Types::String, null: true,
+ description: 'Web path to edit .gitlab-ci.yml file.'
+
field :file_type, GraphQL::Types::String, null: true,
description: 'Expected format of the blob based on the extension.'
diff --git a/app/graphql/types/repository_type.rb b/app/graphql/types/repository_type.rb
index 63d1eef5b59..fc9860900c9 100644
--- a/app/graphql/types/repository_type.rb
+++ b/app/graphql/types/repository_type.rb
@@ -16,8 +16,7 @@ module Types
description: 'Tree of the repository.'
field :paginated_tree, Types::Tree::TreeType.connection_type, null: true, resolver: Resolvers::PaginatedTreeResolver, calls_gitaly: true,
max_page_size: 100,
- description: 'Paginated tree of the repository.',
- feature_flag: :paginated_tree_graphql_query
+ description: 'Paginated tree of the repository.'
field :blobs, Types::Repository::BlobType.connection_type, null: true, resolver: Resolvers::BlobsResolver, calls_gitaly: true,
description: 'Blobs contained within the repository'
field :branch_names, [GraphQL::Types::String], null: true, calls_gitaly: true,
diff --git a/app/helpers/admin/deploy_key_helper.rb b/app/helpers/admin/deploy_key_helper.rb
new file mode 100644
index 00000000000..caf3757a68e
--- /dev/null
+++ b/app/helpers/admin/deploy_key_helper.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Admin
+ module DeployKeyHelper
+ def admin_deploy_keys_data
+ {
+ edit_path: edit_admin_deploy_key_path(':id'),
+ delete_path: admin_deploy_key_path(':id'),
+ create_path: new_admin_deploy_key_path,
+ empty_state_svg_path: image_path('illustrations/empty-state/empty-deploy-keys-lg.svg')
+ }
+ end
+ end
+end
diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb
index 60e37c96f61..5ca360f38da 100644
--- a/app/helpers/appearances_helper.rb
+++ b/app/helpers/appearances_helper.rb
@@ -39,14 +39,14 @@ module AppearancesHelper
if current_appearance&.header_logo?
image_tag current_appearance.header_logo_path, class: 'brand-header-logo'
else
- render 'shared/logo.svg'
+ render partial: 'shared/logo', formats: :svg
end
end
# Skip the 'GitLab' type logo when custom brand logo is set
def brand_header_logo_type
unless current_appearance&.header_logo?
- render 'shared/logo_type.svg'
+ render partial: 'shared/logo_type', formats: :svg
end
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 2103a37180f..b8ee71daeee 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -404,6 +404,10 @@ module ApplicationSettingsHelper
:keep_latest_artifact,
:whats_new_variant,
:user_deactivation_emails_enabled,
+ :sentry_enabled,
+ :sentry_dsn,
+ :sentry_clientside_dsn,
+ :sentry_environment,
:sidekiq_job_limiter_mode,
:sidekiq_job_limiter_compression_threshold_bytes,
:sidekiq_job_limiter_limit_bytes,
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index a0c3a6f2f52..6fe92a5a978 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -8,6 +8,7 @@ module AuthHelper
azure_oauth2
bitbucket
facebook
+ dingtalk
github
gitlab
google_oauth2
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index 33d5bae88f4..c26a73028b9 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -43,7 +43,7 @@ module BoardsHelper
def build_issue_link_base
if board.group_board?
- "#{group_path(@board.group)}/:project_path/issues"
+ "/:project_path/-/issues"
else
project_issues_path(@project)
end
diff --git a/app/helpers/breadcrumbs_helper.rb b/app/helpers/breadcrumbs_helper.rb
index ade7c48b03f..3a622a65685 100644
--- a/app/helpers/breadcrumbs_helper.rb
+++ b/app/helpers/breadcrumbs_helper.rb
@@ -27,10 +27,10 @@ module BreadcrumbsHelper
end
end
- def add_to_breadcrumb_dropdown(link, location: :before)
- @breadcrumb_dropdown_links ||= {}
- @breadcrumb_dropdown_links[location] ||= []
- @breadcrumb_dropdown_links[location] << link
+ def add_to_breadcrumb_collapsed_links(link, location: :before)
+ @breadcrumb_collapsed_links ||= {}
+ @breadcrumb_collapsed_links[location] ||= []
+ @breadcrumb_collapsed_links[location] << link
end
def push_to_schema_breadcrumb(text, link)
diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb
index 6be46b40023..6104a1256d5 100644
--- a/app/helpers/ci/pipelines_helper.rb
+++ b/app/helpers/ci/pipelines_helper.rb
@@ -67,6 +67,17 @@ module Ci
]
end
+ def has_pipeline_badges?(pipeline)
+ pipeline.child? ||
+ pipeline.latest? ||
+ pipeline.merge_train_pipeline? ||
+ pipeline.has_yaml_errors? ||
+ pipeline.failure_reason? ||
+ pipeline.auto_devops_source? ||
+ pipeline.detached_merge_request_pipeline? ||
+ pipeline.stuck?
+ end
+
private
def warning_markdown(pipeline)
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
index ec10610714b..17057505173 100644
--- a/app/helpers/ci/runners_helper.rb
+++ b/app/helpers/ci/runners_helper.rb
@@ -6,27 +6,30 @@ module Ci
def runner_status_icon(runner, size: 16, icon_class: '')
status = runner.status
+ active = runner.active
title = ''
icon = 'warning-solid'
span_class = ''
case status
+ when :online
+ if active
+ title = s_("Runners|Runner is online, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
+ icon = 'status-active'
+ span_class = 'gl-text-green-500'
+ else
+ title = s_("Runners|Runner is paused, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
+ icon = 'status-paused'
+ span_class = 'gl-text-gray-600'
+ end
when :not_connected
title = s_("Runners|New runner, has not connected yet")
icon = 'warning-solid'
- when :online
- title = s_("Runners|Runner is online, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
- icon = 'status-active'
- span_class = 'gl-text-green-500'
when :offline
title = s_("Runners|Runner is offline, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
icon = 'status-failed'
span_class = 'gl-text-red-500'
- when :paused
- title = s_("Runners|Runner is paused, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
- icon = 'status-paused'
- span_class = 'gl-text-gray-600'
end
content_tag(:span, class: span_class, title: title, data: { toggle: 'tooltip', container: 'body', testid: 'runner_status_icon', qa_selector: "runner_status_#{status}_content" }) do
@@ -57,11 +60,30 @@ module Ci
end
end
+ def admin_runners_data_attributes
+ {
+ # Runner install help page is external, located at
+ # https://gitlab.com/gitlab-org/gitlab-runner
+ runner_install_help_page: 'https://docs.gitlab.com/runner/install/',
+ registration_token: Gitlab::CurrentSettings.runners_registration_token,
+
+ # All runner counts are returned as formatted strings
+ active_runners_count: Ci::Runner.online.count.to_s,
+ all_runners_count: limited_counter_with_delimiter(Ci::Runner),
+ instance_runners_count: limited_counter_with_delimiter(Ci::Runner.instance_type),
+ group_runners_count: limited_counter_with_delimiter(Ci::Runner.group_type),
+ project_runners_count: limited_counter_with_delimiter(Ci::Runner.project_type)
+ }
+ end
+
def group_shared_runners_settings_data(group)
{
update_path: api_v4_groups_path(id: group.id),
shared_runners_availability: group.shared_runners_setting,
- parent_shared_runners_availability: group.parent&.shared_runners_setting
+ parent_shared_runners_availability: group.parent&.shared_runners_setting,
+ runner_enabled: Namespace::SR_ENABLED,
+ runner_disabled: Namespace::SR_DISABLED_AND_UNOVERRIDABLE,
+ runner_allow_override: Namespace::SR_DISABLED_WITH_OVERRIDE
}
end
diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb
index c355fa5cc67..93b6b4e8fe2 100644
--- a/app/helpers/clusters_helper.rb
+++ b/app/helpers/clusters_helper.rb
@@ -12,35 +12,36 @@ module ClustersHelper
end
end
- def display_cluster_agents?(_clusterable)
- false
+ def display_cluster_agents?(clusterable)
+ clusterable.is_a?(Project)
end
- def js_cluster_agents_list_data(clusterable_project)
- {
- default_branch_name: clusterable_project.default_branch,
- empty_state_image: image_path('illustrations/clusters_empty.svg'),
- project_path: clusterable_project.full_path,
- agent_docs_url: help_page_path('user/clusters/agent/index'),
- install_docs_url: help_page_path('administration/clusters/kas'),
- get_started_docs_url: help_page_path('user/clusters/agent/index', anchor: 'define-a-configuration-repository'),
- integration_docs_url: help_page_path('user/clusters/agent/index', anchor: 'get-started-with-gitops-and-the-gitlab-agent'),
- kas_address: Gitlab::Kas.external_url
- }
- end
-
- def js_clusters_list_data(path = nil)
+ def js_clusters_list_data(clusterable)
{
ancestor_help_path: help_page_path('user/group/clusters/index', anchor: 'cluster-precedence'),
- endpoint: path,
+ endpoint: clusterable.index_path(format: :json),
img_tags: {
aws: { path: image_path('illustrations/logos/amazon_eks.svg'), text: s_('ClusterIntegration|Amazon EKS') },
default: { path: image_path('illustrations/logos/kubernetes.svg'), text: _('Kubernetes Cluster') },
gcp: { path: image_path('illustrations/logos/google_gke.svg'), text: s_('ClusterIntegration|Google GKE') }
- }
+ },
+ clusters_empty_state_image: image_path('illustrations/empty-state/empty-state-clusters.svg'),
+ empty_state_help_text: clusterable.empty_state_help_text,
+ new_cluster_path: clusterable.new_path(tab: 'create'),
+ can_add_cluster: clusterable.can_add_cluster?.to_s
}
end
+ def js_clusters_data(clusterable)
+ {
+ default_branch_name: clusterable.default_branch,
+ empty_state_image: image_path('illustrations/empty-state/empty-state-agents.svg'),
+ project_path: clusterable.full_path,
+ add_cluster_path: clusterable.new_path(tab: 'add'),
+ kas_address: Gitlab::Kas.external_url
+ }.merge(js_clusters_list_data(clusterable))
+ end
+
def js_cluster_form_data(cluster, can_edit)
{
enabled: cluster.enabled?.to_s,
diff --git a/app/helpers/emoji_helper.rb b/app/helpers/emoji_helper.rb
index 51b7fd7f352..c390924f7e3 100644
--- a/app/helpers/emoji_helper.rb
+++ b/app/helpers/emoji_helper.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module EmojiHelper
- def emoji_icon(*args)
- raw Gitlab::Emoji.gl_emoji_tag(*args)
+ def emoji_icon(emoji_name, *options)
+ emoji = TanukiEmoji.find_by_alpha_code(emoji_name)
+ raw Gitlab::Emoji.gl_emoji_tag(emoji, *options)
end
end
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index b2842664879..cde45e7bc0f 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -69,9 +69,7 @@ module EnvironmentsHelper
'custom_metrics_path' => project_prometheus_metrics_path(project),
'validate_query_path' => validate_query_project_prometheus_metrics_path(project),
'custom_metrics_available' => "#{custom_metrics_available?(project)}",
- 'prometheus_alerts_available' => "#{can?(current_user, :read_prometheus_alerts, project)}",
- 'dashboard_timezone' => project.metrics_setting_dashboard_timezone.to_s.upcase,
- 'has_managed_prometheus' => has_managed_prometheus?(project).to_s
+ 'dashboard_timezone' => project.metrics_setting_dashboard_timezone.to_s.upcase
}
end
@@ -86,10 +84,6 @@ module EnvironmentsHelper
}
end
- def has_managed_prometheus?(project)
- project.prometheus_integration&.prometheus_available? == true
- end
-
def metrics_dashboard_base_path(environment, project)
# This is needed to support our transition from environment scoped metric paths to project scoped.
if project
diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb
index 3a94f7d47c2..45ca820f7b3 100644
--- a/app/helpers/graph_helper.rb
+++ b/app/helpers/graph_helper.rb
@@ -26,6 +26,10 @@ module GraphHelper
def should_render_dora_charts
false
end
+
+ def should_render_quality_summary
+ false
+ end
end
GraphHelper.prepend_mod_with('GraphHelper')
diff --git a/app/helpers/groups/settings_helper.rb b/app/helpers/groups/settings_helper.rb
new file mode 100644
index 00000000000..1b391680996
--- /dev/null
+++ b/app/helpers/groups/settings_helper.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Groups
+ module SettingsHelper
+ include GroupsHelper
+
+ def group_settings_confirm_modal_data(group, remove_form_id = nil)
+ {
+ remove_form_id: remove_form_id,
+ button_text: _('Remove group'),
+ button_testid: 'remove-group-button',
+ disabled: group.paid?.to_s,
+ confirm_danger_message: remove_group_message(group),
+ phrase: group.full_path
+ }
+ end
+ end
+end
+
+Groups::SettingsHelper.prepend_mod_with('Groups::SettingsHelper')
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 30aaa0a5acc..9ba7d004d6c 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -39,7 +39,7 @@ module GroupsHelper
sorted_ancestors(group).with_route.reverse_each.with_index do |parent, index|
if index > 0
- add_to_breadcrumb_dropdown(group_title_link(parent, hidable: false, show_avatar: true, for_dropdown: true), location: :before)
+ add_to_breadcrumb_collapsed_links(group_title_link(parent), location: :before)
else
full_title << breadcrumb_list_item(group_title_link(parent, hidable: false))
end
@@ -47,7 +47,7 @@ module GroupsHelper
push_to_schema_breadcrumb(simple_sanitize(parent.name), group_path(parent))
end
- full_title << render("layouts/nav/breadcrumbs/collapsed_dropdown", location: :before, title: _("Show parent subgroups"))
+ full_title << render("layouts/nav/breadcrumbs/collapsed_inline_list", location: :before, title: _("Show all breadcrumbs"))
full_title << breadcrumb_list_item(group_title_link(group))
push_to_schema_breadcrumb(simple_sanitize(group.name), group_path(group))
diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb
index c38b4a7aedf..32d808c960c 100644
--- a/app/helpers/icons_helper.rb
+++ b/app/helpers/icons_helper.rb
@@ -9,9 +9,7 @@ module IconsHelper
def custom_icon(icon_name, size: DEFAULT_ICON_SIZE)
memoized_icon("#{icon_name}_#{size}") do
- # We can't simply do the below, because there are some .erb SVGs.
- # File.read(Rails.root.join("app/views/shared/icons/_#{icon_name}.svg")).html_safe
- render "shared/icons/#{icon_name}.svg", size: size
+ render partial: "shared/icons/#{icon_name}", formats: :svg, locals: { size: size }
end
end
diff --git a/app/helpers/integrations_helper.rb b/app/helpers/integrations_helper.rb
index 8819aa9e9cc..bb4a7fef6be 100644
--- a/app/helpers/integrations_helper.rb
+++ b/app/helpers/integrations_helper.rb
@@ -132,6 +132,20 @@ module IntegrationsHelper
end
end
+ def zentao_issue_breadcrumb_link(issue)
+ link_to issue[:web_url], { target: '_blank', rel: 'noopener noreferrer', class: 'gl-display-flex gl-align-items-center gl-white-space-nowrap' } do
+ icon = image_tag image_path('logos/zentao.svg'), width: 15, height: 15, class: 'gl-mr-2'
+ [icon, html_escape(issue[:id])].join.html_safe
+ end
+ end
+
+ def zentao_issues_show_data
+ {
+ issues_show_path: project_integrations_zentao_issue_path(@project, params[:id], format: :json),
+ issues_list_path: project_integrations_zentao_issues_path(@project)
+ }
+ end
+
extend self
private
diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb
index d9bd64f4c2e..01ae0ce4f31 100644
--- a/app/helpers/invite_members_helper.rb
+++ b/app/helpers/invite_members_helper.rb
@@ -42,6 +42,14 @@ module InviteMembersHelper
e.candidate { dataset.merge!(areas_of_focus_options: member_areas_of_focus_options.to_json, no_selection_areas_of_focus: ['no_selection']) }
end
+ if show_invite_members_for_task?
+ dataset.merge!(
+ tasks_to_be_done_options: tasks_to_be_done_options.to_json,
+ projects: projects_for_source(source).to_json,
+ new_project_path: source.is_a?(Group) ? new_project_path(namespace_id: source.id) : ''
+ )
+ end
+
dataset
end
@@ -71,4 +79,19 @@ module InviteMembersHelper
def users_filter_data(group)
{}
end
+
+ def show_invite_members_for_task?
+ return unless current_user && experiment(:invite_members_for_task).enabled?
+
+ params[:open_modal] == 'invite_members_for_task'
+ end
+
+ def tasks_to_be_done_options
+ ::MemberTask::TASKS.keys.map { |task| { value: task, text: localized_tasks_to_be_done_choices[task] } }
+ end
+
+ def projects_for_source(source)
+ projects = source.is_a?(Project) ? [source] : source.projects
+ projects.map { |project| { id: project.id, title: project.title } }
+ end
end
diff --git a/app/helpers/issuables_description_templates_helper.rb b/app/helpers/issuables_description_templates_helper.rb
index a5b9a6eee80..6b546d5c6fc 100644
--- a/app/helpers/issuables_description_templates_helper.rb
+++ b/app/helpers/issuables_description_templates_helper.rb
@@ -32,14 +32,17 @@ module IssuablesDescriptionTemplatesHelper
@template_types[project.id][issuable_type] ||= TemplateFinder.all_template_names(project, issuable_type.pluralize)
end
- # Overriden on EE::IssuablesDescriptionTemplatesHelper to include inherited templates names
- def issuable_templates_names(issuable, include_inherited_templates = false)
+ def selected_template(issuable)
all_templates = issuable_templates(ref_project, issuable.to_ability_name)
- all_templates.values.flatten.map { |tpl| tpl[:name] if tpl[:project_id] == ref_project.id }.compact.uniq
+
+ # Only local templates will be listed if licenses for inherited templates are not present
+ all_templates = all_templates.values.flatten.map { |tpl| tpl[:name] }.compact.uniq
+
+ all_templates.find { |tmpl_name| tmpl_name == params[:issuable_template] }
end
- def selected_template(issuable)
- params[:issuable_template] if issuable_templates_names(issuable, true).any? { |tmpl_name| tmpl_name == params[:issuable_template] }
+ def available_service_desk_templates_for(project)
+ issuable_templates(project, 'issue').flatten.to_json
end
def template_names_path(parent, issuable)
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 24c6ef8cd68..07f5adae272 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -257,7 +257,8 @@ module IssuablesHelper
zoomMeetingUrl: ZoomMeeting.canonical_meeting_url(issuable),
sentryIssueIdentifier: SentryIssue.find_by(issue: issuable)&.sentry_issue_identifier, # rubocop:disable CodeReuse/ActiveRecord
iid: issuable.iid.to_s,
- isHidden: issue_hidden?(issuable)
+ isHidden: issue_hidden?(issuable),
+ canCreateIncident: create_issue_type_allowed?(issuable.project, :incident)
}
end
@@ -284,9 +285,7 @@ module IssuablesHelper
end
def issuables_count_for_state(issuable_type, state)
- store_in_cache = parent.is_a?(Group) ? parent.cached_issues_state_count_enabled? : false
-
- Gitlab::IssuablesCountForState.new(finder, store_in_redis_cache: store_in_cache)[state]
+ Gitlab::IssuablesCountForState.new(finder, store_in_redis_cache: true)[state]
end
def close_issuable_path(issuable)
@@ -442,7 +441,7 @@ module IssuablesHelper
end
def format_count(issuable_type, count, threshold)
- if issuable_type == :issues && parent.is_a?(Group) && parent.cached_issues_state_count_enabled?
+ if issuable_type == :issues && parent.is_a?(Group)
format_cached_count(threshold, count)
else
number_with_delimiter(count)
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 49f7d9aeef1..a88ca6f6b11 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
module IssuesHelper
+ include Issues::IssueTypeHelpers
+
def issue_css_classes(issue)
classes = ["issue"]
classes << "closed" if issue.closed?
@@ -190,6 +192,7 @@ module IssuesHelper
{
can_create_issue: show_new_issue_link?(project).to_s,
+ can_create_incident: create_issue_type_allowed?(project, :incident).to_s,
can_reopen_issue: can?(current_user, :reopen_issue, issuable).to_s,
can_report_spam: issuable.submittable_as_spam_by?(current_user).to_s,
can_update_issue: can?(current_user, :update_issue, issuable).to_s,
@@ -233,6 +236,7 @@ module IssuesHelper
new_issue_path: new_project_issue_path(project, issue: { milestone_id: finder.milestones.first.try(:id) }),
project_import_jira_path: project_import_jira_path(project),
quick_actions_help_path: help_page_path('user/project/quick_actions'),
+ releases_path: project_releases_path(project, format: :json),
reset_path: new_issuable_address_project_path(project, issuable_type: 'issue'),
show_new_issue_link: show_new_issue_link?(project).to_s
)
diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb
index 4fb7a05a0e9..08a30c4d53b 100644
--- a/app/helpers/learn_gitlab_helper.rb
+++ b/app/helpers/learn_gitlab_helper.rb
@@ -7,10 +7,32 @@ module LearnGitlabHelper
learn_gitlab_onboarding_available?(project)
end
+ def learn_gitlab_data(project)
+ {
+ actions: onboarding_actions_data(project).to_json,
+ sections: onboarding_sections_data.to_json
+ }
+ end
+
+ def learn_gitlab_onboarding_available?(project)
+ OnboardingProgress.onboarding?(project.namespace) &&
+ LearnGitlab::Project.new(current_user).available?
+ end
+
+ private
+
def onboarding_actions_data(project)
attributes = onboarding_progress(project).attributes.symbolize_keys
- action_urls.to_h do |action, url|
+ urls_to_use = nil
+
+ experiment(:change_continuous_onboarding_link_urls) do |e|
+ e.namespace = project.namespace
+ e.use { urls_to_use = action_urls }
+ e.try { urls_to_use = new_action_urls(project) }
+ end
+
+ urls_to_use.to_h do |action, url|
[
action,
url: url,
@@ -34,18 +56,22 @@ module LearnGitlabHelper
}
end
- def learn_gitlab_onboarding_available?(project)
- OnboardingProgress.onboarding?(project.namespace) &&
- LearnGitlab::Project.new(current_user).available?
- end
-
- private
-
def action_urls
LearnGitlab::Onboarding::ACTION_ISSUE_IDS.transform_values { |id| project_issue_url(learn_gitlab_project, id) }
.merge(LearnGitlab::Onboarding::ACTION_DOC_URLS)
end
+ def new_action_urls(project)
+ action_urls.merge(
+ issue_created: project_issues_path(project),
+ git_write: project_path(project),
+ pipeline_created: project_pipelines_path(project),
+ merge_request_created: project_merge_requests_path(project),
+ user_added: project_members_url(project),
+ security_scan_enabled: project_security_configuration_path(project)
+ )
+ end
+
def learn_gitlab_project
@learn_gitlab_project ||= LearnGitlab::Project.new(current_user).project
end
@@ -54,3 +80,5 @@ module LearnGitlabHelper
OnboardingProgress.find_by(namespace: project.namespace) # rubocop: disable CodeReuse/ActiveRecord
end
end
+
+LearnGitlabHelper.prepend_mod_with('LearnGitlabHelper')
diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb
index d3db5d24207..aac49cfa234 100644
--- a/app/helpers/members_helper.rb
+++ b/app/helpers/members_helper.rb
@@ -56,6 +56,14 @@ module MembersHelper
end
end
+ def localized_tasks_to_be_done_choices
+ {
+ code: s_('TasksToBeDone|Create/import code into a project (repository)'),
+ ci: s_('TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code'),
+ issues: s_('TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work')
+ }.freeze
+ end
+
private
def source_text(member)
diff --git a/app/helpers/nav/top_nav_helper.rb b/app/helpers/nav/top_nav_helper.rb
index 3055ad57b80..ecef2d38e54 100644
--- a/app/helpers/nav/top_nav_helper.rb
+++ b/app/helpers/nav/top_nav_helper.rb
@@ -267,6 +267,7 @@ module Nav
builder.add_primary_menu_item(id: 'your', title: _('Your projects'), href: dashboard_projects_path)
builder.add_primary_menu_item(id: 'starred', title: _('Starred projects'), href: starred_dashboard_projects_path)
builder.add_primary_menu_item(id: 'explore', title: _('Explore projects'), href: explore_root_path)
+ builder.add_primary_menu_item(id: 'topics', title: _('Explore topics'), href: topics_explore_projects_path)
builder.add_secondary_menu_item(id: 'create', title: _('Create new project'), href: new_project_path)
builder.build
end
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index fff7e5d1c7f..2dadaa0be0a 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -167,11 +167,11 @@ module NotesHelper
}
end
- def discussions_path(issuable)
+ def discussions_path(issuable, **params)
if issuable.is_a?(Issue)
- discussions_project_issue_path(@project, issuable, format: :json)
+ discussions_project_issue_path(@project, issuable, params.merge(format: :json))
else
- discussions_project_merge_request_path(@project, issuable, format: :json)
+ discussions_project_merge_request_path(@project, issuable, params.merge(format: :json))
end
end
@@ -188,7 +188,8 @@ module NotesHelper
reopenPath: reopen_issuable_path(issuable),
notesPath: notes_url,
prerenderedNotesCount: issuable.capped_notes_count(MAX_PRERENDERED_NOTES),
- lastFetchedAt: initial_last_fetched_at
+ lastFetchedAt: initial_last_fetched_at,
+ notesFilter: current_user&.notes_filter_for(issuable)
}
if issuable.is_a?(MergeRequest)
diff --git a/app/helpers/one_trust_helper.rb b/app/helpers/one_trust_helper.rb
index 9f92a73a4d4..55364d36a0e 100644
--- a/app/helpers/one_trust_helper.rb
+++ b/app/helpers/one_trust_helper.rb
@@ -4,7 +4,6 @@ module OneTrustHelper
def one_trust_enabled?
Feature.enabled?(:ecomm_instrumentation, type: :ops) &&
Gitlab.config.extra.has_key?('one_trust_id') &&
- Gitlab.config.extra.one_trust_id.present? &&
- !current_user
+ Gitlab.config.extra.one_trust_id.present?
end
end
diff --git a/app/helpers/projects/alert_management_helper.rb b/app/helpers/projects/alert_management_helper.rb
index b50e287a509..e03f2ae78bf 100644
--- a/app/helpers/projects/alert_management_helper.rb
+++ b/app/helpers/projects/alert_management_helper.rb
@@ -10,7 +10,6 @@ module Projects::AlertManagementHelper
'empty-alert-svg-path' => image_path('illustrations/alert-management-empty-state.svg'),
'user-can-enable-alert-management' => can?(current_user, :admin_operations, project).to_s,
'alert-management-enabled' => alert_management_enabled?(project).to_s,
- 'has-managed-prometheus' => has_managed_prometheus?(project).to_s,
'text-query': params[:search],
'assignee-username-query': params[:assignee_username]
}
@@ -28,10 +27,6 @@ module Projects::AlertManagementHelper
private
- def has_managed_prometheus?(project)
- project.prometheus_integration&.prometheus_available? == true
- end
-
def alert_management_enabled?(project)
!!(
project.alert_management_alerts.any? ||
diff --git a/app/helpers/projects/incidents_helper.rb b/app/helpers/projects/incidents_helper.rb
index dde2980817f..4b3ff8a3e83 100644
--- a/app/helpers/projects/incidents_helper.rb
+++ b/app/helpers/projects/incidents_helper.rb
@@ -11,7 +11,8 @@ module Projects::IncidentsHelper
'empty-list-svg-path' => image_path('illustrations/incident-empty-state.svg'),
'text-query': params[:search],
'author-username-query': params[:author_username],
- 'assignee-username-query': params[:assignee_username]
+ 'assignee-username-query': params[:assignee_username],
+ 'can-create-incident': create_issue_type_allowed?(project, :incident).to_s
}
end
end
diff --git a/app/helpers/projects/security/configuration_helper.rb b/app/helpers/projects/security/configuration_helper.rb
index dee106ab3ae..8281b1f8522 100644
--- a/app/helpers/projects/security/configuration_helper.rb
+++ b/app/helpers/projects/security/configuration_helper.rb
@@ -4,7 +4,7 @@ module Projects
module Security
module ConfigurationHelper
def security_upgrade_path
- 'https://about.gitlab.com/pricing/'
+ "https://#{ApplicationHelper.promo_host}/pricing/"
end
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index e3b63d122d2..8366b25d2bc 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -196,12 +196,26 @@ module ProjectsHelper
cookies["hide_auto_devops_implicitly_enabled_banner_#{project.id}".to_sym].blank?
end
- def link_to_set_password
- if current_user.require_password_creation_for_git?
- link_to s_('SetPasswordToCloneLink|set a password'), edit_profile_password_path
- else
- link_to s_('CreateTokenToCloneLink|create a personal access token'), profile_personal_access_tokens_path
- end
+ def no_password_message
+ push_pull_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('gitlab-basics/start-using-git', anchor: 'pull-and-push') }
+ clone_with_https_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('gitlab-basics/start-using-git', anchor: 'clone-with-https') }
+ set_password_link_start = '<a href="%{url}">'.html_safe % { url: edit_profile_password_path }
+ set_up_pat_link_start = '<a href="%{url}">'.html_safe % { url: profile_personal_access_tokens_path }
+
+ message = if current_user.require_password_creation_for_git?
+ _('Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}.')
+ else
+ _('Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}.')
+ end
+
+ html_escape(message) % {
+ push_pull_link_start: push_pull_link_start,
+ protocol: gitlab_config.protocol.upcase,
+ clone_with_https_link_start: clone_with_https_link_start,
+ set_password_link_start: set_password_link_start,
+ set_up_pat_link_start: set_up_pat_link_start,
+ link_end: '</a>'.html_safe
+ }
end
# Returns true if any projects are present.
@@ -382,6 +396,15 @@ module ProjectsHelper
""
end
+ # Returns the confirm phrase the user needs to type in order to delete the project
+ #
+ # Thus the phrase should include the namespace to make it very clear to the
+ # user which project is subject to deletion.
+ # Relevant issue: https://gitlab.com/gitlab-org/gitlab/-/issues/343591
+ def delete_confirm_phrase(project)
+ project.path_with_namespace
+ end
+
private
def tab_ability_map
@@ -590,6 +613,7 @@ module ProjectsHelper
%w[
environments
clusters
+ cluster_agents
functions
error_tracking
alert_management
diff --git a/app/helpers/recaptcha_helper.rb b/app/helpers/recaptcha_helper.rb
index 0df62f7b715..5b17ab4b815 100644
--- a/app/helpers/recaptcha_helper.rb
+++ b/app/helpers/recaptcha_helper.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
module RecaptchaHelper
- def show_recaptcha_sign_up?
+ def recaptcha_enabled?
!!Gitlab::Recaptcha.enabled?
end
+ alias_method :show_recaptcha_sign_up?, :recaptcha_enabled?
end
RecaptchaHelper.prepend_mod
diff --git a/app/helpers/reminder_emails_helper.rb b/app/helpers/reminder_emails_helper.rb
index bffb3cf7751..132fc3b784c 100644
--- a/app/helpers/reminder_emails_helper.rb
+++ b/app/helpers/reminder_emails_helper.rb
@@ -7,7 +7,8 @@ module ReminderEmailsHelper
s_('InviteReminderEmail|Invitation pending')
when 1
if format == :html
- s_('InviteReminderEmail|Hey there %{wave_emoji}').html_safe % { wave_emoji: Gitlab::Emoji.gl_emoji_tag('wave') }
+ wave_emoji_tag = Gitlab::Emoji.gl_emoji_tag(TanukiEmoji.find_by_alpha_code('wave'))
+ s_('InviteReminderEmail|Hey there %{wave_emoji}').html_safe % { wave_emoji: wave_emoji_tag }
else
s_('InviteReminderEmail|Hey there!')
end
diff --git a/app/helpers/routing/pseudonymization_helper.rb b/app/helpers/routing/pseudonymization_helper.rb
index b73e49803ae..ac30669dc83 100644
--- a/app/helpers/routing/pseudonymization_helper.rb
+++ b/app/helpers/routing/pseudonymization_helper.rb
@@ -2,58 +2,86 @@
module Routing
module PseudonymizationHelper
- def masked_page_url
- return unless Feature.enabled?(:mask_page_urls, type: :ops)
+ class MaskHelper
+ QUERY_PARAMS_TO_NOT_MASK = %w[].freeze
- mask_params(Rails.application.routes.recognize_path(request.original_fullpath))
- rescue ActionController::RoutingError, URI::InvalidURIError => e
- Gitlab::ErrorTracking.track_exception(e, url: request.original_fullpath)
- nil
- end
+ def initialize(request_object, group, project)
+ @request = request_object
+ @group = group
+ @project = project
+ end
+
+ def mask_params
+ return default_root_url + @request.original_fullpath unless has_maskable_params?
- private
+ masked_params = @request.path_parameters.to_h do |key, value|
+ case key
+ when :project_id
+ [key, "project#{@project&.id}"]
+ when :namespace_id, :group_id
+ namespace = @group || @project&.namespace
+ [key, "namespace#{namespace&.id}"]
+ when :id
+ [key, mask_id(value)]
+ else
+ [key, value]
+ end
+ end
- def mask_params(request_params)
- return if request_params[:action] == 'new'
+ Gitlab::Routing.url_helpers.url_for(masked_params.merge(params: masked_query_params))
+ end
- namespace_type = request_params[:controller].split('/')[1]
+ private
- namespace_type.present? ? url_with_namespace_type(request_params, namespace_type) : url_without_namespace_type(request_params)
- end
+ def mask_id(value)
+ if @request.path_parameters[:controller] == 'projects/blob'
+ ':repository_path'
+ elsif @request.path_parameters[:controller] == 'projects'
+ "project#{@project&.id}"
+ elsif @request.path_parameters[:controller] == 'groups'
+ "namespace#{@group&.id}"
+ else
+ value
+ end
+ end
- def url_without_namespace_type(request_params)
- masked_url = "#{request.protocol}#{request.host_with_port}"
+ def has_maskable_params?
+ request_params = @request.path_parameters.to_h
+ request_params.key?(:namespace_id) || request_params.key?(:group_id) || request_params.key?(:project_id) || request_params.key?(:id) || @request.query_string.present?
+ end
- masked_url += case request_params[:controller]
- when 'groups'
- "/namespace:#{group.id}"
- when 'projects'
- "/namespace:#{project.namespace_id}/project:#{project.id}"
- when 'root'
- ''
- else
- "#{request.path}"
- end
+ def masked_query_params
+ return {} unless @request.query_string.present?
- masked_url += request.query_string.present? ? "?#{request.query_string}" : ''
+ query_string_hash = Rack::Utils.parse_nested_query(@request.query_string)
- masked_url
- end
+ query_string_hash.keys.each do |key|
+ next if QUERY_PARAMS_TO_NOT_MASK.include?(key)
- def url_with_namespace_type(request_params, namespace_type)
- masked_url = "#{request.protocol}#{request.host_with_port}"
+ query_string_hash[key] = "masked_#{key}"
+ end
- if request_params.has_key?(:project_id)
- masked_url += "/namespace:#{project.namespace_id}/project:#{project.id}/-/#{namespace_type}"
+ query_string_hash
end
- if request_params.has_key?(:id)
- masked_url += namespace_type == 'blob' ? '/:repository_path' : "/#{request_params[:id]}"
+ def default_root_url
+ Gitlab::Routing.url_helpers.root_url(only_path: false)
end
+ end
- masked_url += request.query_string.present? ? "?#{request.query_string}" : ''
+ def masked_page_url
+ return unless Feature.enabled?(:mask_page_urls, type: :ops)
+
+ current_group = group if defined?(group)
+ current_project = project if defined?(project)
+ mask_helper = MaskHelper.new(request, current_group, current_project)
+ mask_helper.mask_params
- masked_url
+ # We rescue all exception for time being till we test this helper extensively.
+ # Check https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72864#note_711515501
+ rescue => e # rubocop:disable Style/RescueStandardError
+ Gitlab::ErrorTracking.track_exception(e, url: request.original_fullpath)
+ nil
end
end
end
diff --git a/app/helpers/storage_helper.rb b/app/helpers/storage_helper.rb
index d6a4d6ac57a..a60143db739 100644
--- a/app/helpers/storage_helper.rb
+++ b/app/helpers/storage_helper.rb
@@ -14,12 +14,13 @@ module StorageHelper
counter_repositories: storage_counter(statistics.repository_size),
counter_wikis: storage_counter(statistics.wiki_size),
counter_build_artifacts: storage_counter(statistics.build_artifacts_size),
+ counter_pipeline_artifacts: storage_counter(statistics.pipeline_artifacts_size),
counter_lfs_objects: storage_counter(statistics.lfs_objects_size),
counter_snippets: storage_counter(statistics.snippets_size),
counter_packages: storage_counter(statistics.packages_size),
counter_uploads: storage_counter(statistics.uploads_size)
}
- _("Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}") % counters
+ _("Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}") % counters
end
end
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index a6bb2f3b246..e53e35baac3 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -33,7 +33,6 @@ module TabHelper
# :item_active - Overrides the default state focing the "active" css classes (optional).
#
def gl_tab_link_to(name = nil, options = {}, html_options = {}, &block)
- tab_class = 'nav-item'
link_classes = %w[nav-link gl-tab-nav-item]
active_link_classes = %w[active gl-tab-nav-item-active gl-tab-nav-item-active-indigo]
@@ -52,6 +51,8 @@ module TabHelper
end
html_options = html_options.except(:item_active)
+ extra_tab_classes = html_options.delete(:tab_class)
+ tab_class = %w[nav-item].push(*extra_tab_classes)
content_tag(:li, class: tab_class, role: 'presentation') do
if block_given?
@@ -210,3 +211,12 @@ module TabHelper
current_page?(options)
end
end
+
+def gl_tab_counter_badge(count, html_options = {})
+ badge_classes = %w[badge badge-muted badge-pill gl-badge sm gl-tab-counter-badge]
+ content_tag(:span,
+ count,
+ class: [*html_options[:class], badge_classes].join(' '),
+ data: html_options[:data]
+ )
+end
diff --git a/app/helpers/terms_helper.rb b/app/helpers/terms_helper.rb
new file mode 100644
index 00000000000..5f321551413
--- /dev/null
+++ b/app/helpers/terms_helper.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module TermsHelper
+ def terms_data(terms, redirect)
+ redirect_params = { redirect: redirect } if redirect
+
+ {
+ terms: markdown_field(terms, :terms),
+ permissions: {
+ can_accept: can?(current_user, :accept_terms, terms),
+ can_decline: can?(current_user, :decline_terms, terms)
+ },
+ paths: {
+ accept: accept_term_path(terms, redirect_params),
+ decline: decline_term_path(terms, redirect_params),
+ root: root_path
+ }
+ }.to_json
+ end
+end
diff --git a/app/helpers/time_zone_helper.rb b/app/helpers/time_zone_helper.rb
index a0d9c8403e8..db355f5ff65 100644
--- a/app/helpers/time_zone_helper.rb
+++ b/app/helpers/time_zone_helper.rb
@@ -32,10 +32,16 @@ module TimeZoneHelper
end
end
+ def local_time_instance(timezone)
+ return Time.zone if timezone.blank?
+
+ ActiveSupport::TimeZone.new(timezone) || Time.zone
+ end
+
def local_time(timezone)
return if timezone.blank?
- time_zone_instance = ActiveSupport::TimeZone.new(timezone) || Time.zone
+ time_zone_instance = local_time_instance(timezone)
time_zone_instance.now.strftime("%-l:%M %p")
end
end
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index e9dc271dbdd..79767ca76b7 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -24,6 +24,7 @@ module TodosHelper
when Todo::UNMERGEABLE then 'Could not merge'
when Todo::DIRECTLY_ADDRESSED then "directly addressed #{todo_action_subject(todo)} on"
when Todo::MERGE_TRAIN_REMOVED then "Removed from Merge Train:"
+ when Todo::ATTENTION_REQUESTED then 'requested your attention on'
end
end
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
index 1c67ca983fa..d8e69145c40 100644
--- a/app/helpers/user_callouts_helper.rb
+++ b/app/helpers/user_callouts_helper.rb
@@ -81,32 +81,11 @@ module UserCalloutsHelper
def user_dismissed_for_group(feature_name, group, ignore_dismissal_earlier_than = nil)
return false unless current_user
- set_dismissed_from_cookie(group)
-
current_user.dismissed_callout_for_group?(feature_name: feature_name,
group: group,
ignore_dismissal_earlier_than: ignore_dismissal_earlier_than)
end
- def set_dismissed_from_cookie(group)
- # bridge function for one milestone to try and not annoy users who might have already dismissed this alert
- # remove in 14.4 or 14.5? https://gitlab.com/gitlab-org/gitlab/-/issues/340322
- dismissed_key = "invite_#{group.id}_#{current_user.id}"
-
- if cookies[dismissed_key].present?
- params = {
- feature_name: INVITE_MEMBERS_BANNER,
- group_id: group.id
- }
-
- Users::DismissGroupCalloutService.new(
- container: nil, current_user: current_user, params: params
- ).execute
-
- cookies.delete dismissed_key
- end
- end
-
def just_created?
flash[:notice]&.include?('successfully created')
end
diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb
index 1b0d1254dc8..ba876f6cb65 100644
--- a/app/helpers/wiki_helper.rb
+++ b/app/helpers/wiki_helper.rb
@@ -9,7 +9,7 @@ module WikiHelper
if page.persisted?
titles << page.human_title
breadcrumb_title(page.human_title)
- wiki_breadcrumb_dropdown_links(page.slug)
+ wiki_breadcrumb_collapsed_links(page.slug)
end
titles << action if action
@@ -39,14 +39,14 @@ module WikiHelper
.join(' / ')
end
- def wiki_breadcrumb_dropdown_links(page_slug)
+ def wiki_breadcrumb_collapsed_links(page_slug)
page_slug_split = page_slug.split('/')
page_slug_split.pop(1)
current_slug = ""
page_slug_split
.map do |dir_or_page|
current_slug = "#{current_slug}#{dir_or_page}/"
- add_to_breadcrumb_dropdown link_to(WikiPage.unhyphenize(dir_or_page).capitalize, wiki_page_path(@wiki, current_slug)), location: :after
+ add_to_breadcrumb_collapsed_links link_to(WikiPage.unhyphenize(dir_or_page).capitalize, wiki_page_path(@wiki, current_slug)), location: :after
end
end
diff --git a/app/helpers/workhorse_helper.rb b/app/helpers/workhorse_helper.rb
index 4862282bc73..2460c956bb6 100644
--- a/app/helpers/workhorse_helper.rb
+++ b/app/helpers/workhorse_helper.rb
@@ -41,8 +41,8 @@ module WorkhorseHelper
head :ok
end
- def send_dependency(token, url, filename)
- headers.store(*Gitlab::Workhorse.send_dependency(token, url))
+ def send_dependency(dependency_headers, url, filename)
+ headers.store(*Gitlab::Workhorse.send_dependency(dependency_headers, url))
headers['Content-Disposition'] =
ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: filename)
headers['Content-Type'] = 'application/gzip'
diff --git a/app/mailers/emails/members.rb b/app/mailers/emails/members.rb
index 6954fd46850..8a9ed557cc6 100644
--- a/app/mailers/emails/members.rb
+++ b/app/mailers/emails/members.rb
@@ -43,9 +43,13 @@ module Emails
user = User.find(user_id)
+ @source_hidden = !member_source.readable_by?(user)
+
+ human_name = @source_hidden ? 'Hidden' : member_source.human_name
+
member_email_with_layout(
to: user.notification_email_for(notification_group),
- subject: subject("Access to the #{member_source.human_name} #{member_source.model_name.singular} was denied"))
+ subject: subject("Access to the #{human_name} #{member_source.model_name.singular} was denied"))
end
def member_invited_email(member_source_type, member_id, token)
diff --git a/app/mailers/emails/pipelines.rb b/app/mailers/emails/pipelines.rb
index 1b27d062391..5363ad63771 100644
--- a/app/mailers/emails/pipelines.rb
+++ b/app/mailers/emails/pipelines.rb
@@ -2,21 +2,23 @@
module Emails
module Pipelines
- def pipeline_success_email(pipeline, recipients)
- pipeline_mail(pipeline, recipients, 'Successful')
+ def pipeline_success_email(pipeline, recipient)
+ pipeline_mail(pipeline, recipient, 'Successful')
end
- def pipeline_failed_email(pipeline, recipients)
- pipeline_mail(pipeline, recipients, 'Failed')
+ def pipeline_failed_email(pipeline, recipient)
+ pipeline_mail(pipeline, recipient, 'Failed')
end
- def pipeline_fixed_email(pipeline, recipients)
- pipeline_mail(pipeline, recipients, 'Fixed')
+ def pipeline_fixed_email(pipeline, recipient)
+ pipeline_mail(pipeline, recipient, 'Fixed')
end
private
- def pipeline_mail(pipeline, recipients, status)
+ def pipeline_mail(pipeline, recipient, status)
+ raise ArgumentError if recipient.is_a?(Array)
+
@project = pipeline.project
@pipeline = pipeline
@@ -28,10 +30,7 @@ module Emails
add_headers
- # We use bcc here because we don't want to generate these emails for a
- # thousand times. This could be potentially expensive in a loop, and
- # recipients would contain all project watchers so it could be a lot.
- mail(bcc: recipients,
+ mail(to: recipient,
subject: subject(pipeline_subject(status))) do |format|
format.html { render layout: 'mailer' }
format.text { render layout: 'mailer' }
diff --git a/app/models/analytics/cycle_analytics/issue_stage_event.rb b/app/models/analytics/cycle_analytics/issue_stage_event.rb
index 3e6ed86d534..837eb35c839 100644
--- a/app/models/analytics/cycle_analytics/issue_stage_event.rb
+++ b/app/models/analytics/cycle_analytics/issue_stage_event.rb
@@ -8,9 +8,22 @@ module Analytics
validates(*%i[stage_event_hash_id issue_id group_id project_id start_event_timestamp], presence: true)
+ alias_attribute :state, :state_id
+ enum state: Issue.available_states, _suffix: true
+
+ scope :assigned_to, ->(user) do
+ assignees_class = IssueAssignee
+ condition = assignees_class.where(user_id: user).where(arel_table[:issue_id].eq(assignees_class.arel_table[:issue_id]))
+ where(condition.arel.exists)
+ end
+
def self.issuable_id_column
:issue_id
end
+
+ def self.issuable_model
+ ::Issue
+ end
end
end
end
diff --git a/app/models/analytics/cycle_analytics/merge_request_stage_event.rb b/app/models/analytics/cycle_analytics/merge_request_stage_event.rb
index d0ec3c4e8b9..0dfa322b2c3 100644
--- a/app/models/analytics/cycle_analytics/merge_request_stage_event.rb
+++ b/app/models/analytics/cycle_analytics/merge_request_stage_event.rb
@@ -8,9 +8,22 @@ module Analytics
validates(*%i[stage_event_hash_id merge_request_id group_id project_id start_event_timestamp], presence: true)
+ alias_attribute :state, :state_id
+ enum state: MergeRequest.available_states, _suffix: true
+
+ scope :assigned_to, ->(user) do
+ assignees_class = MergeRequestAssignee
+ condition = assignees_class.where(user_id: user).where(arel_table[:merge_request_id].eq(assignees_class.arel_table[:merge_request_id]))
+ where(condition.arel.exists)
+ end
+
def self.issuable_id_column
:merge_request_id
end
+
+ def self.issuable_model
+ ::MergeRequest
+ end
end
end
end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index d2757d8c17d..bcd8bdd6638 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -1,7 +1,10 @@
# frozen_string_literal: true
class ApplicationRecord < ActiveRecord::Base
- self.gitlab_schema = :gitlab_main
+ include DatabaseReflection
+ include Transactions
+ include LegacyBulkInsert
+
self.abstract_class = true
alias_method :reset, :reload
@@ -92,8 +95,7 @@ class ApplicationRecord < ActiveRecord::Base
end
def self.declarative_enum(enum_mod)
- values = enum_mod.definition.transform_values { |v| v[:value] }
- enum(enum_mod.key => values)
+ enum(enum_mod.key => enum_mod.values)
end
def self.cached_column_list
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 5a8cbd8d71c..af5796d682f 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -536,6 +536,18 @@ class ApplicationSetting < ApplicationRecord
validates :sidekiq_job_limiter_limit_bytes,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+ validates :sentry_enabled,
+ inclusion: { in: [true, false], message: _('must be a boolean value') }
+ validates :sentry_dsn,
+ addressable_url: true, presence: true, length: { maximum: 255 },
+ if: :sentry_enabled?
+ validates :sentry_clientside_dsn,
+ addressable_url: true, allow_blank: true, length: { maximum: 255 },
+ if: :sentry_enabled?
+ validates :sentry_environment,
+ presence: true, length: { maximum: 255 },
+ if: :sentry_enabled?
+
attr_encrypted :asset_proxy_secret_key,
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_truncated,
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index 7bdea36bb8a..54ec8b2c3e4 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -146,6 +146,9 @@ module ApplicationSettingImplementation
session_expire_delay: Settings.gitlab['session_expire_delay'],
shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'],
shared_runners_text: nil,
+ sidekiq_job_limiter_mode: Gitlab::SidekiqMiddleware::SizeLimiter::Validator::COMPRESS_MODE,
+ sidekiq_job_limiter_compression_threshold_bytes: Gitlab::SidekiqMiddleware::SizeLimiter::Validator::DEFAULT_COMPRESSION_THRESHOLD_BYTES,
+ sidekiq_job_limiter_limit_bytes: Gitlab::SidekiqMiddleware::SizeLimiter::Validator::DEFAULT_SIZE_LIMIT,
sign_in_text: nil,
signup_enabled: Settings.gitlab['signup_enabled'],
snippet_size_limit: 50.megabytes,
@@ -241,11 +244,11 @@ module ApplicationSettingImplementation
end
def home_page_url_column_exists?
- ::Gitlab::Database.main.cached_column_exists?(:application_settings, :home_page_url)
+ ApplicationSetting.database.cached_column_exists?(:home_page_url)
end
def help_page_support_url_column_exists?
- ::Gitlab::Database.main.cached_column_exists?(:application_settings, :help_page_support_url)
+ ApplicationSetting.database.cached_column_exists?(:help_page_support_url)
end
def disabled_oauth_sign_in_sources=(sources)
diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb
index a1c6793607f..1a8bd05c42c 100644
--- a/app/models/audit_event.rb
+++ b/app/models/audit_event.rb
@@ -30,6 +30,8 @@ class AuditEvent < ApplicationRecord
scope :by_entity_type, -> (entity_type) { where(entity_type: entity_type) }
scope :by_entity_id, -> (entity_id) { where(entity_id: entity_id) }
scope :by_author_id, -> (author_id) { where(author_id: author_id) }
+ scope :by_entity_username, -> (username) { where(entity_id: find_user_id(username)) }
+ scope :by_author_username, -> (username) { where(author_id: find_user_id(username)) }
after_initialize :initialize_details
@@ -106,6 +108,10 @@ class AuditEvent < ApplicationRecord
self[name] = self.details[name] = original
end
end
+
+ def self.find_user_id(username)
+ User.find_by_username(username)&.id
+ end
end
AuditEvent.prepend_mod_with('AuditEvent')
diff --git a/app/models/award_emoji.rb b/app/models/award_emoji.rb
index c8f6b9aaedb..b665f3d5d8c 100644
--- a/app/models/award_emoji.rb
+++ b/app/models/award_emoji.rb
@@ -14,7 +14,7 @@ class AwardEmoji < ApplicationRecord
validates :user, presence: true
validates :awardable, presence: true, unless: :importing?
- validates :name, presence: true, inclusion: { in: Gitlab::Emoji.emojis_names }
+ validates :name, presence: true, 'gitlab/emoji_name': true
validates :name, uniqueness: { scope: [:user, :awardable_type, :awardable_id] }, unless: -> { ghost_user? || importing? }
participant :user
diff --git a/app/models/blob_viewer/package_json.rb b/app/models/blob_viewer/package_json.rb
index 7cae60a74d6..1d10cc82a85 100644
--- a/app/models/blob_viewer/package_json.rb
+++ b/app/models/blob_viewer/package_json.rb
@@ -7,11 +7,15 @@ module BlobViewer
self.file_types = %i(package_json)
def manager_name
- 'npm'
+ yarn? ? 'yarn' : 'npm'
+ end
+
+ def yarn?
+ json_data['engines'].present? && json_data['engines']['yarn'].present?
end
def manager_url
- 'https://www.npmjs.com/'
+ yarn? ? 'https://yarnpkg.com/' : 'https://www.npmjs.com/'
end
def package_name
@@ -38,7 +42,11 @@ module BlobViewer
end
def npm_url
- "https://www.npmjs.com/package/#{package_name}"
+ if yarn?
+ "https://yarnpkg.com/package/#{package_name}"
+ else
+ "https://www.npmjs.com/package/#{package_name}"
+ end
end
end
end
diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb
index ecac4ab95f4..2368be6196c 100644
--- a/app/models/bulk_imports/entity.rb
+++ b/app/models/bulk_imports/entity.rb
@@ -112,6 +112,10 @@ class BulkImports::Entity < ApplicationRecord
@export_relations_url_path ||= EXPORT_RELATIONS_URL % { resource: pluralized_name, full_path: encoded_source_full_path }
end
+ def relation_download_url_path(relation)
+ "#{export_relations_url_path}/download?relation=#{relation}"
+ end
+
private
def validate_parent_is_a_group
diff --git a/app/models/chat_name.rb b/app/models/chat_name.rb
index ff3f2663b73..da7312df18b 100644
--- a/app/models/chat_name.rb
+++ b/app/models/chat_name.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class ChatName < ApplicationRecord
+ include LooseForeignKey
+
LAST_USED_AT_INTERVAL = 1.hour
belongs_to :integration, foreign_key: :service_id
@@ -14,6 +16,8 @@ class ChatName < ApplicationRecord
validates :user_id, uniqueness: { scope: [:service_id] }
validates :chat_id, uniqueness: { scope: [:service_id, :team_id] }
+ loose_foreign_key :ci_pipeline_chat_data, :chat_name_id, on_delete: :async_delete
+
# Updates the "last_used_timestamp" but only if it wasn't already updated
# recently.
#
diff --git a/app/models/ci/application_record.rb b/app/models/ci/application_record.rb
index 913e7a62c66..ea7b1104e36 100644
--- a/app/models/ci/application_record.rb
+++ b/app/models/ci/application_record.rb
@@ -2,9 +2,12 @@
module Ci
class ApplicationRecord < ::ApplicationRecord
- self.gitlab_schema = :gitlab_ci
self.abstract_class = true
+ if Gitlab::Database.has_config?(:ci)
+ connects_to database: { writing: :ci, reading: :ci }
+ end
+
def self.table_name_prefix
'ci_'
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 990ef71a457..3fdc44bccf3 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -10,7 +10,6 @@ module Ci
include Presentable
include Importable
include Ci::HasRef
- include IgnorableColumns
BuildArchivedError = Class.new(StandardError)
@@ -70,9 +69,6 @@ module Ci
delegate :gitlab_deploy_token, to: :project
delegate :trigger_short_token, to: :trigger_request, allow_nil: true
- ignore_columns :id_convert_to_bigint, remove_with: '14.5', remove_after: '2021-10-22'
- ignore_columns :stage_id_convert_to_bigint, remove_with: '14.5', remove_after: '2021-10-22'
-
##
# Since Gitlab 11.5, deployments records started being created right after
# `ci_builds` creation. We can look up a relevant `environment` through
@@ -175,6 +171,7 @@ module Ci
scope :with_live_trace, -> { where('EXISTS (?)', Ci::BuildTraceChunk.where('ci_builds.id = ci_build_trace_chunks.build_id').select(1)) }
scope :with_stale_live_trace, -> { with_live_trace.finished_before(12.hours.ago) }
scope :finished_before, -> (date) { finished.where('finished_at < ?', date) }
+ scope :license_management_jobs, -> { where(name: %i(license_management license_scanning)) } # handle license rename https://gitlab.com/gitlab-org/gitlab/issues/8911
scope :with_secure_reports_from_config_options, -> (job_types) do
joins(:metadata).where("ci_builds_metadata.config_options -> 'artifacts' -> 'reports' ?| array[:job_types]", job_types: job_types)
@@ -313,12 +310,6 @@ module Ci
end
after_transition pending: :running do |build|
- unless build.update_deployment_after_transaction_commit?
- Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do
- build.deployment&.run
- end
- end
-
build.run_after_commit do
build.pipeline.persistent_ref.create
@@ -339,12 +330,6 @@ module Ci
end
after_transition any => [:success] do |build|
- unless build.update_deployment_after_transaction_commit?
- Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do
- build.deployment&.succeed
- end
- end
-
build.run_after_commit do
BuildSuccessWorker.perform_async(id)
PagesWorker.perform_async(:deploy, id) if build.pages_generator?
@@ -353,23 +338,6 @@ module Ci
after_transition any => [:failed] do |build|
next unless build.project
- next unless build.deployment
-
- unless build.update_deployment_after_transaction_commit?
- begin
- Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do
- build.deployment.drop!
- end
- rescue StandardError => e
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, build_id: build.id)
- end
- end
-
- true
- end
-
- after_transition any => [:failed] do |build|
- next unless build.project
if build.auto_retry_allowed?
begin
@@ -380,25 +348,12 @@ module Ci
end
end
- after_transition any => [:skipped, :canceled] do |build, transition|
- unless build.update_deployment_after_transaction_commit?
- Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338867') do
- if transition.to_name == :skipped
- build.deployment&.skip
- else
- build.deployment&.cancel
- end
- end
- end
- end
-
# Synchronize Deployment Status
# Please note that the data integirty is not assured because we can't use
# a database transaction due to DB decomposition.
after_transition do |build, transition|
next if transition.loopback?
next unless build.project
- next unless build.update_deployment_after_transaction_commit?
build.run_after_commit do
build.deployment&.sync_status_with(build)
@@ -585,7 +540,6 @@ module Ci
.concat(persisted_variables)
.concat(dependency_proxy_variables)
.concat(job_jwt_variables)
- .concat(kubernetes_variables)
.concat(scoped_variables)
.concat(job_variables)
.concat(persisted_environment_variables)
@@ -1120,12 +1074,6 @@ module Ci
runner&.instance_type?
end
- def update_deployment_after_transaction_commit?
- strong_memoize(:update_deployment_after_transaction_commit) do
- Feature.enabled?(:update_deployment_after_transaction_commit, project, default_enabled: :yaml)
- end
- end
-
protected
def run_status_commit_hooks!
@@ -1213,10 +1161,6 @@ module Ci
end
end
- def kubernetes_variables
- [] # Overridden in EE
- end
-
def conditionally_allow_failure!(exit_code)
return unless exit_code
diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb
index 0d6d6f7a6a5..ca68989002c 100644
--- a/app/models/ci/build_metadata.rb
+++ b/app/models/ci/build_metadata.rb
@@ -23,6 +23,7 @@ module Ci
serialize :config_options, Serializers::SymbolizedJson # rubocop:disable Cop/ActiveRecordSerialize
serialize :config_variables, Serializers::SymbolizedJson # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :runtime_runner_features, Serializers::SymbolizedJson # rubocop:disable Cop/ActiveRecordSerialize
chronic_duration_attr_reader :timeout_human_readable, :timeout
@@ -37,8 +38,7 @@ module Ci
job_timeout_source: 4
}
- ignore_column :build_id_convert_to_bigint, remove_with: '14.5', remove_after: '2021-10-22'
- ignore_columns :id_convert_to_bigint, remove_with: '14.5', remove_after: '2021-10-22'
+ ignore_columns :runner_features, remove_with: '14.7', remove_after: '2021-11-22'
def update_timeout_state
timeout = timeout_with_highest_precedence
@@ -48,6 +48,14 @@ module Ci
update(timeout: timeout.value, timeout_source: timeout.source)
end
+ def set_cancel_gracefully
+ runtime_runner_features.merge!( { cancel_gracefully: true } )
+ end
+
+ def cancel_gracefully?
+ runtime_runner_features[:cancel_gracefully] == true
+ end
+
private
def set_build_project
diff --git a/app/models/ci/build_need.rb b/app/models/ci/build_need.rb
index bf1470ca20f..d4cbbfac4ab 100644
--- a/app/models/ci/build_need.rb
+++ b/app/models/ci/build_need.rb
@@ -3,7 +3,6 @@
module Ci
class BuildNeed < Ci::ApplicationRecord
include BulkInsertSafe
- include IgnorableColumns
belongs_to :build, class_name: "Ci::Processable", foreign_key: :build_id, inverse_of: :needs
@@ -13,12 +12,5 @@ module Ci
scope :scoped_build, -> { where('ci_builds.id=ci_build_needs.build_id') }
scope :artifacts, -> { where(artifacts: true) }
-
- # TODO: Remove once build_id_convert_to_bigint is not an "ignored" column anymore (see .ignore_columns above)
- # There is a database-side trigger to populate this column. This is unexpected in the context
- # of cloning an instance, e.g. when retrying the job. Hence we exclude the ignored column explicitly here.
- def attributes
- super.except('build_id_convert_to_bigint')
- end
end
end
diff --git a/app/models/ci/build_runner_session.rb b/app/models/ci/build_runner_session.rb
index e12c0f82c99..c6dbb5d0a43 100644
--- a/app/models/ci/build_runner_session.rb
+++ b/app/models/ci/build_runner_session.rb
@@ -4,8 +4,6 @@ module Ci
# The purpose of this class is to store Build related runner session.
# Data will be removed after transitioning from running to any state.
class BuildRunnerSession < Ci::ApplicationRecord
- include IgnorableColumns
-
TERMINAL_SUBPROTOCOL = 'terminal.gitlab.com'
DEFAULT_SERVICE_NAME = 'build'
DEFAULT_PORT_NAME = 'default_port'
diff --git a/app/models/ci/build_trace_chunk.rb b/app/models/ci/build_trace_chunk.rb
index 6edb5ef4579..221a2284106 100644
--- a/app/models/ci/build_trace_chunk.rb
+++ b/app/models/ci/build_trace_chunk.rb
@@ -7,7 +7,6 @@ module Ci
include ::Checksummable
include ::Gitlab::ExclusiveLeaseHelpers
include ::Gitlab::OptimisticLocking
- include IgnorableColumns
belongs_to :build, class_name: "Ci::Build", foreign_key: :build_id
diff --git a/app/models/ci/ci_database_record.rb b/app/models/ci/ci_database_record.rb
deleted file mode 100644
index e2b832a28e7..00000000000
--- a/app/models/ci/ci_database_record.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- # TODO: https://gitlab.com/groups/gitlab-org/-/epics/6168
- #
- # Do not use this yet outside of `ci_instance_variables`.
- # This class is part of a migration to move all CI classes to a new separate database.
- # Initially we are only going to be moving the `Ci::InstanceVariable` model and it will be duplicated in the main and CI tables
- # Do not extend this class in any other models.
- class CiDatabaseRecord < Ci::ApplicationRecord
- self.abstract_class = true
-
- if Gitlab::Database.has_config?(:ci)
- connects_to database: { writing: :ci, reading: :ci }
- end
- end
-end
diff --git a/app/models/ci/instance_variable.rb b/app/models/ci/instance_variable.rb
index f4aa935b983..da9d4dea537 100644
--- a/app/models/ci/instance_variable.rb
+++ b/app/models/ci/instance_variable.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class InstanceVariable < Ci::CiDatabaseRecord
+ class InstanceVariable < Ci::ApplicationRecord
extend Gitlab::ProcessMemoryCache::Helper
include Ci::NewHasVariable
include Ci::Maskable
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index ad3e867f9d5..ec1137920ef 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -10,9 +10,7 @@ module Ci
include Artifactable
include FileStoreMounter
include EachBatch
- include IgnorableColumns
-
- ignore_columns %i[id_convert_to_bigint job_id_convert_to_bigint], remove_with: '14.5', remove_after: '2021-11-22'
+ include Gitlab::Utils::StrongMemoize
TEST_REPORT_FILE_TYPES = %w[junit].freeze
COVERAGE_REPORT_FILE_TYPES = %w[cobertura].freeze
@@ -124,6 +122,9 @@ module Ci
mount_file_store_uploader JobArtifactUploader
+ skip_callback :save, :after, :store_file!, if: :store_after_commit?
+ after_commit :store_file_after_commit!, on: [:create, :update], if: :store_after_commit?
+
validates :file_format, presence: true, unless: :trace?, on: :create
validate :validate_file_format!, unless: :trace?, on: :create
before_save :set_size, if: :file_changed?
@@ -338,8 +339,23 @@ module Ci
}
end
+ def store_after_commit?
+ strong_memoize(:store_after_commit) do
+ trace? &&
+ JobArtifactUploader.direct_upload_enabled? &&
+ Feature.enabled?(:ci_store_trace_outside_transaction, project, default_enabled: :yaml)
+ end
+ end
+
private
+ def store_file_after_commit!
+ return unless previous_changes.key?(:file)
+
+ store_file!
+ update_file_store
+ end
+
def set_size
self.size = file.size
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 0041ec5135c..a29aa756e38 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -71,7 +71,7 @@ module Ci
has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id # rubocop:disable Cop/ActiveRecordDependent
has_many :variables, class_name: 'Ci::PipelineVariable'
has_many :deployments, through: :builds
- has_many :environments, -> { distinct }, through: :deployments
+ has_many :environments, -> { distinct.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338658') }, through: :deployments
has_many :latest_builds, -> { latest.with_project_and_metadata }, foreign_key: :commit_id, inverse_of: :pipeline, class_name: 'Ci::Build'
has_many :downloadable_artifacts, -> do
not_expired.or(where_exists(::Ci::Pipeline.artifacts_locked.where('ci_pipelines.id = ci_builds.commit_id'))).downloadable.with_job
@@ -652,8 +652,15 @@ module Ci
end
def batch_lookup_report_artifact_for_file_type(file_type)
+ batch_lookup_report_artifact_for_file_types([file_type])
+ end
+
+ def batch_lookup_report_artifact_for_file_types(file_types)
+ file_types_to_search = []
+ file_types.each { |file_type| file_types_to_search.append(*::Ci::JobArtifact.associated_file_types_for(file_type.to_s)) }
+
latest_report_artifacts
- .values_at(*::Ci::JobArtifact.associated_file_types_for(file_type.to_s))
+ .values_at(*file_types_to_search.uniq)
.flatten
.compact
.last
@@ -684,7 +691,9 @@ module Ci
end
def freeze_period?
- Ci::FreezePeriodStatus.new(project: project).execute
+ strong_memoize(:freeze_period) do
+ Ci::FreezePeriodStatus.new(project: project).execute
+ end
end
def has_warnings?
@@ -780,6 +789,10 @@ module Ci
strong_memoize(:legacy_trigger) { trigger_requests.first }
end
+ def variables_builder
+ @variables_builder ||= ::Gitlab::Ci::Variables::Builder.new(self)
+ end
+
def persisted_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
break variables unless persisted?
@@ -796,20 +809,7 @@ module Ci
variables.append(key: 'CI_PIPELINE_CREATED_AT', value: created_at&.iso8601)
variables.concat(predefined_commit_variables)
-
- if merge_request?
- variables.append(key: 'CI_MERGE_REQUEST_EVENT_TYPE', value: merge_request_event_type.to_s)
- variables.append(key: 'CI_MERGE_REQUEST_SOURCE_BRANCH_SHA', value: source_sha.to_s)
- variables.append(key: 'CI_MERGE_REQUEST_TARGET_BRANCH_SHA', value: target_sha.to_s)
-
- diff = self.merge_request_diff
- if diff.present?
- variables.append(key: 'CI_MERGE_REQUEST_DIFF_ID', value: diff.id.to_s)
- variables.append(key: 'CI_MERGE_REQUEST_DIFF_BASE_SHA', value: diff.base_commit_sha)
- end
-
- variables.concat(merge_request.predefined_variables)
- end
+ variables.concat(predefined_merge_request_variables)
if open_merge_requests_refs.any?
variables.append(key: 'CI_OPEN_MERGE_REQUESTS', value: open_merge_requests_refs.join(','))
@@ -825,27 +825,49 @@ module Ci
end
def predefined_commit_variables
- Gitlab::Ci::Variables::Collection.new.tap do |variables|
- variables.append(key: 'CI_COMMIT_SHA', value: sha)
- variables.append(key: 'CI_COMMIT_SHORT_SHA', value: short_sha)
- variables.append(key: 'CI_COMMIT_BEFORE_SHA', value: before_sha)
- variables.append(key: 'CI_COMMIT_REF_NAME', value: source_ref)
- variables.append(key: 'CI_COMMIT_REF_SLUG', value: source_ref_slug)
- variables.append(key: 'CI_COMMIT_BRANCH', value: ref) if branch?
- variables.append(key: 'CI_COMMIT_TAG', value: ref) if tag?
- variables.append(key: 'CI_COMMIT_MESSAGE', value: git_commit_message.to_s)
- variables.append(key: 'CI_COMMIT_TITLE', value: git_commit_full_title.to_s)
- variables.append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description.to_s)
- variables.append(key: 'CI_COMMIT_REF_PROTECTED', value: (!!protected_ref?).to_s)
- variables.append(key: 'CI_COMMIT_TIMESTAMP', value: git_commit_timestamp.to_s)
- variables.append(key: 'CI_COMMIT_AUTHOR', value: git_author_full_text.to_s)
-
- # legacy variables
- variables.append(key: 'CI_BUILD_REF', value: sha)
- variables.append(key: 'CI_BUILD_BEFORE_SHA', value: before_sha)
- variables.append(key: 'CI_BUILD_REF_NAME', value: source_ref)
- variables.append(key: 'CI_BUILD_REF_SLUG', value: source_ref_slug)
- variables.append(key: 'CI_BUILD_TAG', value: ref) if tag?
+ strong_memoize(:predefined_commit_variables) do
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ variables.append(key: 'CI_COMMIT_SHA', value: sha)
+ variables.append(key: 'CI_COMMIT_SHORT_SHA', value: short_sha)
+ variables.append(key: 'CI_COMMIT_BEFORE_SHA', value: before_sha)
+ variables.append(key: 'CI_COMMIT_REF_NAME', value: source_ref)
+ variables.append(key: 'CI_COMMIT_REF_SLUG', value: source_ref_slug)
+ variables.append(key: 'CI_COMMIT_BRANCH', value: ref) if branch?
+ variables.append(key: 'CI_COMMIT_TAG', value: ref) if tag?
+ variables.append(key: 'CI_COMMIT_MESSAGE', value: git_commit_message.to_s)
+ variables.append(key: 'CI_COMMIT_TITLE', value: git_commit_full_title.to_s)
+ variables.append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description.to_s)
+ variables.append(key: 'CI_COMMIT_REF_PROTECTED', value: (!!protected_ref?).to_s)
+ variables.append(key: 'CI_COMMIT_TIMESTAMP', value: git_commit_timestamp.to_s)
+ variables.append(key: 'CI_COMMIT_AUTHOR', value: git_author_full_text.to_s)
+
+ # legacy variables
+ variables.append(key: 'CI_BUILD_REF', value: sha)
+ variables.append(key: 'CI_BUILD_BEFORE_SHA', value: before_sha)
+ variables.append(key: 'CI_BUILD_REF_NAME', value: source_ref)
+ variables.append(key: 'CI_BUILD_REF_SLUG', value: source_ref_slug)
+ variables.append(key: 'CI_BUILD_TAG', value: ref) if tag?
+ end
+ end
+ end
+
+ def predefined_merge_request_variables
+ strong_memoize(:predefined_merge_request_variables) do
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ next variables unless merge_request?
+
+ variables.append(key: 'CI_MERGE_REQUEST_EVENT_TYPE', value: merge_request_event_type.to_s)
+ variables.append(key: 'CI_MERGE_REQUEST_SOURCE_BRANCH_SHA', value: source_sha.to_s)
+ variables.append(key: 'CI_MERGE_REQUEST_TARGET_BRANCH_SHA', value: target_sha.to_s)
+
+ diff = self.merge_request_diff
+ if diff.present?
+ variables.append(key: 'CI_MERGE_REQUEST_DIFF_ID', value: diff.id.to_s)
+ variables.append(key: 'CI_MERGE_REQUEST_DIFF_BASE_SHA', value: diff.base_commit_sha)
+ end
+
+ variables.concat(merge_request.predefined_variables)
+ end
end
end
@@ -1254,6 +1276,18 @@ module Ci
self.builds.latest.build_matchers(project)
end
+ def predefined_vars_in_builder_enabled?
+ strong_memoize(:predefined_vars_in_builder_enabled) do
+ Feature.enabled?(:ci_predefined_vars_in_builder, project, default_enabled: :yaml)
+ end
+ end
+
+ def authorized_cluster_agents
+ strong_memoize(:authorized_cluster_agents) do
+ ::Clusters::AgentAuthorizationsFinder.new(project).execute.map(&:agent)
+ end
+ end
+
private
def add_message(severity, content)
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 2f718ad7582..8a3025e5608 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -12,6 +12,7 @@ module Ci
include Gitlab::Utils::StrongMemoize
include TaggableQueries
include Presentable
+ include LooseForeignKey
add_authentication_token_field :token, encrypted: :optional
@@ -82,7 +83,9 @@ module Ci
groups = Gitlab::ObjectHierarchy.new(groups).base_and_ancestors
end
- joins(:runner_namespaces).where(ci_runner_namespaces: { namespace_id: groups })
+ joins(:runner_namespaces)
+ .where(ci_runner_namespaces: { namespace_id: groups })
+ .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433')
}
scope :belonging_to_group_or_project, -> (group_id, project_id) {
@@ -94,13 +97,16 @@ module Ci
union_sql = ::Gitlab::SQL::Union.new([group_runners, project_runners]).to_sql
from("(#{union_sql}) #{table_name}")
+ .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433')
}
scope :belonging_to_parent_group_of_project, -> (project_id) {
project_groups = ::Group.joins(:projects).where(projects: { id: project_id })
hierarchy_groups = Gitlab::ObjectHierarchy.new(project_groups).base_and_ancestors
- joins(:groups).where(namespaces: { id: hierarchy_groups })
+ joins(:groups)
+ .where(namespaces: { id: hierarchy_groups })
+ .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433')
}
scope :owned_or_instance_wide, -> (project_id) do
@@ -111,7 +117,7 @@ module Ci
instance_type
],
remove_duplicates: false
- )
+ ).allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433')
end
scope :assignable_for, ->(project) do
@@ -162,6 +168,8 @@ module Ci
validates :config, json_schema: { filename: 'ci_runner_config' }
+ loose_foreign_key :clusters_applications_runners, :runner_id, on_delete: :async_nullify
+
# Searches for runners matching the given query.
#
# This method uses ILIKE on PostgreSQL for the description field and performs a full match on tokens.
@@ -266,6 +274,14 @@ module Ci
end
def status
+ return :not_connected unless contacted_at
+
+ online? ? :online : :offline
+ end
+
+ # DEPRECATED
+ # TODO Remove in %15.0 in favor of `status` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/344648
+ def deprecated_rest_status
if contacted_at.nil?
:not_connected
elsif active?
@@ -436,10 +452,8 @@ module Ci
end
def no_groups
- ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659') do
- if groups.any?
- errors.add(:runner, 'cannot have groups assigned')
- end
+ if runner_namespaces.any?
+ errors.add(:runner, 'cannot have groups assigned')
end
end
@@ -450,10 +464,8 @@ module Ci
end
def exactly_one_group
- ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659') do
- unless groups.one?
- errors.add(:runner, 'needs to be assigned to exactly one group')
- end
+ unless runner_namespaces.one?
+ errors.add(:runner, 'needs to be assigned to exactly one group')
end
end
diff --git a/app/models/ci/sources/pipeline.rb b/app/models/ci/sources/pipeline.rb
index 95842d944f9..f78caf710a6 100644
--- a/app/models/ci/sources/pipeline.rb
+++ b/app/models/ci/sources/pipeline.rb
@@ -4,9 +4,6 @@ module Ci
module Sources
class Pipeline < Ci::ApplicationRecord
include Ci::NamespacedModelName
- include IgnorableColumns
-
- ignore_columns 'source_job_id_convert_to_bigint', remove_with: '14.5', remove_after: '2021-11-22'
self.table_name = "ci_sources_pipelines"
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index 131e18adf62..e2b15497638 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -6,7 +6,6 @@ module Ci
include Ci::HasStatus
include Gitlab::OptimisticLocking
include Presentable
- include IgnorableColumns
enum status: Ci::HasStatus::STATUSES_ENUM
diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb
index 595315f14ab..5bf5ae51ec8 100644
--- a/app/models/ci/trigger.rb
+++ b/app/models/ci/trigger.rb
@@ -3,6 +3,10 @@
module Ci
class Trigger < Ci::ApplicationRecord
include Presentable
+ include Limitable
+
+ self.limit_name = 'pipeline_triggers'
+ self.limit_scope = :project
belongs_to :project
belongs_to :owner, class_name: "User"
diff --git a/app/models/clusters/agents/group_authorization.rb b/app/models/clusters/agents/group_authorization.rb
index 28a711aaf17..58ba874ab53 100644
--- a/app/models/clusters/agents/group_authorization.rb
+++ b/app/models/clusters/agents/group_authorization.rb
@@ -3,6 +3,8 @@
module Clusters
module Agents
class GroupAuthorization < ApplicationRecord
+ include ::Clusters::Agents::AuthorizationConfigScopes
+
self.table_name = 'agent_group_authorizations'
belongs_to :agent, class_name: 'Clusters::Agent', optional: false
diff --git a/app/models/clusters/agents/project_authorization.rb b/app/models/clusters/agents/project_authorization.rb
index f6d19086751..b9b44741936 100644
--- a/app/models/clusters/agents/project_authorization.rb
+++ b/app/models/clusters/agents/project_authorization.rb
@@ -3,6 +3,8 @@
module Clusters
module Agents
class ProjectAuthorization < ApplicationRecord
+ include ::Clusters::Agents::AuthorizationConfigScopes
+
self.table_name = 'agent_project_authorizations'
belongs_to :agent, class_name: 'Clusters::Agent', optional: false
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index 7cef92ce81a..59a9251d6b7 100644
--- a/app/models/clusters/applications/runner.rb
+++ b/app/models/clusters/applications/runner.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Runner < ApplicationRecord
- VERSION = '0.31.0'
+ VERSION = '0.34.0'
self.table_name = 'clusters_applications_runners'
@@ -70,7 +70,7 @@ module Clusters
}
if cluster.group_type?
- attributes[:groups] = [group]
+ attributes[:runner_namespaces] = [::Ci::RunnerNamespace.new(namespace: group)]
elsif cluster.project_type?
attributes[:runner_projects] = [::Ci::RunnerProject.new(project: project)]
end
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index feac7bbc363..87afa9f9491 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -139,8 +139,6 @@ module Clusters
scope :with_available_elasticstack, -> { joins(:application_elastic_stack).merge(::Clusters::Applications::ElasticStack.available) }
scope :with_available_cilium, -> { joins(:application_cilium).merge(::Clusters::Applications::Cilium.available) }
scope :distinct_with_deployed_environments, -> { joins(:environments).merge(::Deployment.success).distinct }
- scope :preload_elasticstack, -> { preload(:integration_elastic_stack) }
- scope :preload_environments, -> { preload(:environments) }
scope :managed, -> { where(managed: true) }
scope :with_persisted_applications, -> { eager_load(*APPLICATIONS_ASSOCIATIONS) }
@@ -150,9 +148,7 @@ module Clusters
scope :for_project_namespace, -> (namespace_id) { joins(:projects).where(projects: { namespace_id: namespace_id }) }
scope :with_name, -> (name) { where(name: name) }
- # with_application_prometheus scope is deprecated, and scheduled for removal
- # in %14.0. See https://gitlab.com/groups/gitlab-org/-/epics/4280
- scope :with_application_prometheus, -> { includes(:application_prometheus).joins(:application_prometheus) }
+ scope :with_integration_prometheus, -> { includes(:integration_prometheus).joins(:integration_prometheus) }
scope :with_project_http_integrations, -> (project_ids) do
conditions = { projects: :alert_management_http_integrations }
includes(conditions).joins(conditions).where(projects: { id: project_ids })
@@ -311,7 +307,7 @@ module Clusters
end
def kubeclient
- platform_kubernetes.kubeclient if kubernetes?
+ platform_kubernetes&.kubeclient if kubernetes?
end
def elastic_stack_adapter
diff --git a/app/models/clusters/integrations/prometheus.rb b/app/models/clusters/integrations/prometheus.rb
index d745a49afc1..8b21fa351a3 100644
--- a/app/models/clusters/integrations/prometheus.rb
+++ b/app/models/clusters/integrations/prometheus.rb
@@ -14,6 +14,13 @@ module Clusters
validates :cluster, presence: true
validates :enabled, inclusion: { in: [true, false] }
+ # Periodically checked and kept up to date for Monitor demo projects
+ enum health_status: {
+ unknown: 0,
+ healthy: 1,
+ unhealthy: 2
+ }
+
attr_encrypted :alert_manager_token,
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_32,
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 43427e2ebc7..d75f7984e2c 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -48,7 +48,7 @@ class CommitStatus < Ci::ApplicationRecord
scope :ordered, -> { order(:name) }
scope :ordered_by_stage, -> { order(stage_idx: :asc) }
scope :latest_ordered, -> { latest.ordered.includes(project: :namespace) }
- scope :retried_ordered, -> { retried.ordered.includes(project: :namespace) }
+ scope :retried_ordered, -> { retried.order(name: :asc, id: :desc).includes(project: :namespace) }
scope :ordered_by_pipeline, -> { order(pipeline_id: :asc) }
scope :before_stage, -> (index) { where('stage_idx < ?', index) }
scope :for_stage, -> (index) { where(stage_idx: index) }
diff --git a/app/models/concerns/alert_event_lifecycle.rb b/app/models/concerns/alert_event_lifecycle.rb
index 4d2b717ead2..72fe7757b44 100644
--- a/app/models/concerns/alert_event_lifecycle.rb
+++ b/app/models/concerns/alert_event_lifecycle.rb
@@ -41,8 +41,6 @@ module AlertEventLifecycle
scope :firing, -> { where(status: status_value_for(:firing)) }
scope :resolved, -> { where(status: status_value_for(:resolved)) }
- scope :count_by_project_id, -> { group(:project_id).count }
-
def self.status_value_for(name)
state_machines[:status].states[name].value
end
diff --git a/app/models/concerns/analytics/cycle_analytics/stage_event_model.rb b/app/models/concerns/analytics/cycle_analytics/stage_event_model.rb
index 7462e1e828b..324e0fb57cb 100644
--- a/app/models/concerns/analytics/cycle_analytics/stage_event_model.rb
+++ b/app/models/concerns/analytics/cycle_analytics/stage_event_model.rb
@@ -5,6 +5,23 @@ module Analytics
module StageEventModel
extend ActiveSupport::Concern
+ included do
+ scope :by_stage_event_hash_id, ->(id) { where(stage_event_hash_id: id) }
+ scope :by_project_id, ->(id) { where(project_id: id) }
+ scope :by_group_id, ->(id) { where(group_id: id) }
+ scope :end_event_timestamp_after, -> (date) { where(arel_table[:end_event_timestamp].gteq(date)) }
+ scope :end_event_timestamp_before, -> (date) { where(arel_table[:end_event_timestamp].lteq(date)) }
+ scope :start_event_timestamp_after, -> (date) { where(arel_table[:start_event_timestamp].gteq(date)) }
+ scope :start_event_timestamp_before, -> (date) { where(arel_table[:start_event_timestamp].lteq(date)) }
+ scope :authored, ->(user) { where(author_id: user) }
+ scope :with_milestone_id, ->(milestone_id) { where(milestone_id: milestone_id) }
+ scope :end_event_is_not_happened_yet, -> { where(end_event_timestamp: nil) }
+ end
+
+ def issuable_id
+ attributes[self.class.issuable_id_column.to_s]
+ end
+
class_methods do
def upsert_data(data)
upsert_values = data.map do |row|
@@ -13,8 +30,9 @@ module Analytics
:issuable_id,
:group_id,
:project_id,
- :author_id,
:milestone_id,
+ :author_id,
+ :state_id,
:start_event_timestamp,
:end_event_timestamp
)
@@ -31,6 +49,7 @@ module Analytics
project_id,
milestone_id,
author_id,
+ state_id,
start_event_timestamp,
end_event_timestamp
)
@@ -39,10 +58,11 @@ module Analytics
DO UPDATE SET
group_id = excluded.group_id,
project_id = excluded.project_id,
- start_event_timestamp = excluded.start_event_timestamp,
- end_event_timestamp = excluded.end_event_timestamp,
milestone_id = excluded.milestone_id,
- author_id = excluded.author_id
+ author_id = excluded.author_id,
+ state_id = excluded.state_id,
+ start_event_timestamp = excluded.start_event_timestamp,
+ end_event_timestamp = excluded.end_event_timestamp
SQL
result = connection.execute(query)
diff --git a/app/models/concerns/cascading_namespace_setting_attribute.rb b/app/models/concerns/cascading_namespace_setting_attribute.rb
index e58e5ddc966..731729a1ed5 100644
--- a/app/models/concerns/cascading_namespace_setting_attribute.rb
+++ b/app/models/concerns/cascading_namespace_setting_attribute.rb
@@ -127,7 +127,7 @@ module CascadingNamespaceSettingAttribute
end
def alias_boolean(attribute)
- return unless Gitlab::Database.main.exists? && type_for_attribute(attribute).type == :boolean
+ return unless database.exists? && type_for_attribute(attribute).type == :boolean
alias_method :"#{attribute}?", attribute
end
@@ -176,10 +176,10 @@ module CascadingNamespaceSettingAttribute
private
def locked_value(attribute)
+ return application_setting_value(attribute) if locked_by_application_setting?(attribute)
+
ancestor = locked_ancestor(attribute)
return ancestor.read_attribute(attribute) if ancestor
-
- Gitlab::CurrentSettings.public_send(attribute) # rubocop:disable GitlabSecurity/PublicSend
end
def locked_ancestor(attribute)
diff --git a/app/models/concerns/ci/contextable.rb b/app/models/concerns/ci/contextable.rb
index 27a704c1de0..a9589cea5e9 100644
--- a/app/models/concerns/ci/contextable.rb
+++ b/app/models/concerns/ci/contextable.rb
@@ -10,11 +10,14 @@ module Ci
# Variables in the environment name scope.
#
def scoped_variables(environment: expanded_environment_name, dependencies: true)
- Gitlab::Ci::Variables::Collection.new.tap do |variables|
- variables.concat(predefined_variables)
+ track_duration do
+ variables = pipeline.variables_builder.scoped_variables(self, environment: environment, dependencies: dependencies)
+
+ variables.concat(predefined_variables) unless pipeline.predefined_vars_in_builder_enabled?
variables.concat(project.predefined_variables)
variables.concat(pipeline.predefined_variables)
variables.concat(runner.predefined_variables) if runnable? && runner
+ variables.concat(kubernetes_variables)
variables.concat(deployment_variables(environment: environment))
variables.concat(yaml_variables)
variables.concat(user_variables)
@@ -25,9 +28,23 @@ module Ci
variables.concat(trigger_request.user_variables) if trigger_request
variables.concat(pipeline.variables)
variables.concat(pipeline.pipeline_schedule.job_variables) if pipeline.pipeline_schedule
+
+ variables
end
end
+ def track_duration
+ start_time = ::Gitlab::Metrics::System.monotonic_time
+ result = yield
+ duration = ::Gitlab::Metrics::System.monotonic_time - start_time
+
+ ::Gitlab::Ci::Pipeline::Metrics
+ .pipeline_builder_scoped_variables_histogram
+ .observe({}, duration.seconds)
+
+ result
+ end
+
##
# Variables that do not depend on the environment name.
#
@@ -72,6 +89,18 @@ module Ci
end
end
+ def kubernetes_variables
+ ::Gitlab::Ci::Variables::Collection.new.tap do |collection|
+ # Should get merged with the cluster kubeconfig in deployment_variables, see
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/335089
+ template = ::Ci::GenerateKubeconfigService.new(self).execute
+
+ if template.valid?
+ collection.append(key: 'KUBECONFIG', value: template.to_yaml, public: false, file: true)
+ end
+ end
+ end
+
def deployment_variables(environment:)
return [] unless environment
diff --git a/app/models/concerns/ci/has_status.rb b/app/models/concerns/ci/has_status.rb
index 8d715279da8..ccaccec3b6b 100644
--- a/app/models/concerns/ci/has_status.rb
+++ b/app/models/concerns/ci/has_status.rb
@@ -14,21 +14,8 @@ module Ci
PASSED_WITH_WARNINGS_STATUSES = %w[failed canceled].to_set.freeze
EXCLUDE_IGNORED_STATUSES = %w[manual failed canceled].to_set.freeze
STATUSES_ENUM = { created: 0, pending: 1, running: 2, success: 3,
- failed: 4, canceled: 5, skipped: 6, manual: 7,
- scheduled: 8, preparing: 9, waiting_for_resource: 10 }.freeze
- STATUSES_DESCRIPTION = {
- created: 'Pipeline has been created',
- waiting_for_resource: 'A resource (for example, a runner) that the pipeline requires to run is unavailable',
- preparing: 'Pipeline is preparing to run',
- pending: 'Pipeline has not started running yet',
- running: 'Pipeline is running',
- failed: 'At least one stage of the pipeline failed',
- success: 'Pipeline completed successfully',
- canceled: 'Pipeline was canceled before completion',
- skipped: 'Pipeline was skipped',
- manual: 'Pipeline needs to be manually started',
- scheduled: 'Pipeline is scheduled to run'
- }.freeze
+ failed: 4, canceled: 5, skipped: 6, manual: 7,
+ scheduled: 8, preparing: 9, waiting_for_resource: 10 }.freeze
UnknownStatusError = Class.new(StandardError)
diff --git a/app/models/concerns/ci/metadatable.rb b/app/models/concerns/ci/metadatable.rb
index 344f5aa4cd5..611b27c722b 100644
--- a/app/models/concerns/ci/metadatable.rb
+++ b/app/models/concerns/ci/metadatable.rb
@@ -20,7 +20,8 @@ module Ci
delegate :interruptible, to: :metadata, prefix: false, allow_nil: true
delegate :has_exposed_artifacts?, to: :metadata, prefix: false, allow_nil: true
delegate :environment_auto_stop_in, to: :metadata, prefix: false, allow_nil: true
- delegate :runner_features, to: :metadata, prefix: false, allow_nil: false
+ delegate :set_cancel_gracefully, to: :metadata, prefix: false, allow_nil: false
+ delegate :cancel_gracefully?, to: :metadata, prefix: false, allow_nil: false
before_create :ensure_metadata
end
diff --git a/app/models/concerns/clusters/agents/authorization_config_scopes.rb b/app/models/concerns/clusters/agents/authorization_config_scopes.rb
new file mode 100644
index 00000000000..0a0406c3389
--- /dev/null
+++ b/app/models/concerns/clusters/agents/authorization_config_scopes.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Agents
+ module AuthorizationConfigScopes
+ extend ActiveSupport::Concern
+
+ included do
+ scope :with_available_ci_access_fields, ->(project) {
+ where("config->'access_as' IS NULL")
+ .or(where("config->'access_as' = '{}'"))
+ .or(where("config->'access_as' ?| array[:fields]", fields: available_ci_access_fields(project)))
+ }
+ end
+
+ class_methods do
+ def available_ci_access_fields(_project)
+ %w(agent)
+ end
+ end
+ end
+ end
+end
+
+Clusters::Agents::AuthorizationConfigScopes.prepend_mod
diff --git a/app/models/concerns/database_reflection.rb b/app/models/concerns/database_reflection.rb
new file mode 100644
index 00000000000..1842f5bf4ec
--- /dev/null
+++ b/app/models/concerns/database_reflection.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# A module that makes it easier/less verbose to reflect upon a database
+# connection.
+#
+# Using this module you can write this:
+#
+# User.database.database_name
+#
+# Instead of this:
+#
+# Gitlab::Database::Reflection.new(User).database_name
+module DatabaseReflection
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def database
+ @database_reflection ||= ::Gitlab::Database::Reflection.new(self)
+ end
+ end
+end
diff --git a/app/models/concerns/enums/vulnerability.rb b/app/models/concerns/enums/vulnerability.rb
index 749d1ad65cd..4b325de61bc 100644
--- a/app/models/concerns/enums/vulnerability.rb
+++ b/app/models/concerns/enums/vulnerability.rb
@@ -37,6 +37,15 @@ module Enums
security_audit: 4
}.with_indifferent_access.freeze
+ # keep the order of the values in the state enum, it is used in state_order method to properly order vulnerabilities based on state
+ # remember to recreate index_vulnerabilities_on_state_case_id index when you update or extend this enum
+ VULNERABILITY_STATES = {
+ detected: 1,
+ confirmed: 4,
+ resolved: 3,
+ dismissed: 2
+ }.with_indifferent_access.freeze
+
def self.confidence_levels
CONFIDENCE_LEVELS
end
@@ -52,6 +61,10 @@ module Enums
def self.detection_methods
DETECTION_METHODS
end
+
+ def self.vulnerability_states
+ VULNERABILITY_STATES
+ end
end
end
diff --git a/app/models/concerns/file_store_mounter.rb b/app/models/concerns/file_store_mounter.rb
index 9d4463e5297..bfcf8a1e7b9 100644
--- a/app/models/concerns/file_store_mounter.rb
+++ b/app/models/concerns/file_store_mounter.rb
@@ -7,15 +7,13 @@ module FileStoreMounter
def mount_file_store_uploader(uploader)
mount_uploader(:file, uploader)
+ # This hook is a no-op when the file is uploaded after_commit
after_save :update_file_store, if: :saved_change_to_file?
end
end
- private
-
def update_file_store
- # The file.object_store is set during `uploader.store!`
- # which happens after object is inserted/updated
- self.update_column(:file_store, file.object_store)
+ # The file.object_store is set during `uploader.store!` and `uploader.migrate!`
+ update_column(:file_store, file.object_store)
end
end
diff --git a/app/models/concerns/has_integrations.rb b/app/models/concerns/has_integrations.rb
deleted file mode 100644
index 76e03d68600..00000000000
--- a/app/models/concerns/has_integrations.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-module HasIntegrations
- extend ActiveSupport::Concern
-
- class_methods do
- def without_integration(integration)
- integrations = Integration
- .select('1')
- .where("#{Integration.table_name}.project_id = projects.id")
- .where(type: integration.type)
-
- Project
- .where('NOT EXISTS (?)', integrations)
- .where(pending_delete: false)
- .where(archived: false)
- end
- end
-end
diff --git a/app/models/concerns/has_user_type.rb b/app/models/concerns/has_user_type.rb
index 4b4f9c0df84..28ee54afaa9 100644
--- a/app/models/concerns/has_user_type.rb
+++ b/app/models/concerns/has_user_type.rb
@@ -28,6 +28,7 @@ module HasUserType
scope :non_internal, -> { humans.or(where(user_type: NON_INTERNAL_USER_TYPES)) }
scope :without_ghosts, -> { humans.or(where.not(user_type: :ghost)) }
scope :without_project_bot, -> { humans.or(where.not(user_type: :project_bot)) }
+ scope :human_or_service_user, -> { humans.or(where(user_type: :service_user)) }
enum user_type: USER_TYPES
diff --git a/app/models/concerns/integrations/push_data_validations.rb b/app/models/concerns/integrations/push_data_validations.rb
new file mode 100644
index 00000000000..966fc94e289
--- /dev/null
+++ b/app/models/concerns/integrations/push_data_validations.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+# This concern is used by registered integrations such as Integrations::TeamCity and
+# Integrations::DroneCi and adds methods to perform validations on the received
+# data.
+module Integrations
+ module PushDataValidations
+ extend ActiveSupport::Concern
+
+ def merge_request_valid?(data)
+ data.dig(:object_attributes, :state) == 'opened' && merge_request_unchecked?(data)
+ end
+
+ def push_valid?(data)
+ data[:total_commits_count] > 0 &&
+ !branch_removed?(data) &&
+ # prefer merge request trigger over push to avoid double builds
+ !opened_merge_requests?(data)
+ end
+
+ def tag_push_valid?(data)
+ data[:total_commits_count] > 0 && !branch_removed?(data)
+ end
+
+ private
+
+ def branch_removed?(data)
+ Gitlab::Git.blank_ref?(data[:after])
+ end
+
+ def opened_merge_requests?(data)
+ project.merge_requests
+ .opened
+ .from_project(project)
+ .from_source_branches(Gitlab::Git.ref_name(data[:ref]))
+ .exists?
+ end
+
+ def merge_request_unchecked?(data)
+ MergeRequest.state_machines[:merge_status]
+ .check_state?(data.dig(:object_attributes, :merge_status))
+ end
+ end
+end
diff --git a/app/models/concerns/integrations/reactively_cached.rb b/app/models/concerns/integrations/reactively_cached.rb
new file mode 100644
index 00000000000..62eff06c8e2
--- /dev/null
+++ b/app/models/concerns/integrations/reactively_cached.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Integrations
+ module ReactivelyCached
+ extend ActiveSupport::Concern
+
+ included do
+ include ::ReactiveCaching
+
+ # Default cache key: class name + project_id
+ self.reactive_cache_key = ->(integration) { [integration.class.model_name.singular, integration.project_id] }
+ self.reactive_cache_work_type = :external_dependency
+ end
+ end
+end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 5c307158a9a..4273eb331a1 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -92,7 +92,6 @@ module Issuable
scope :recent, -> { reorder(id: :desc) }
scope :of_projects, ->(ids) { where(project_id: ids) }
scope :opened, -> { with_state(:opened) }
- scope :only_opened, -> { with_state(:opened) }
scope :closed, -> { with_state(:closed) }
# rubocop:disable GitlabSecurity/SqlInjection
diff --git a/app/models/concerns/legacy_bulk_insert.rb b/app/models/concerns/legacy_bulk_insert.rb
new file mode 100644
index 00000000000..1249dfb70cd
--- /dev/null
+++ b/app/models/concerns/legacy_bulk_insert.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module LegacyBulkInsert
+ extend ActiveSupport::Concern
+
+ class_methods do
+ # Bulk inserts a number of rows into a table, optionally returning their
+ # IDs.
+ #
+ # This method is deprecated, and you should use the BulkInsertSafe module
+ # instead.
+ #
+ # table - The name of the table to insert the rows into.
+ # rows - An Array of Hash instances, each mapping the columns to their
+ # values.
+ # return_ids - When set to true the return value will be an Array of IDs of
+ # the inserted rows
+ # disable_quote - A key or an Array of keys to exclude from quoting (You
+ # become responsible for protection from SQL injection for
+ # these keys!)
+ # on_conflict - Defines an upsert. Values can be: :disabled (default) or
+ # :do_nothing
+ def legacy_bulk_insert(table, rows, return_ids: false, disable_quote: [], on_conflict: nil)
+ return if rows.empty?
+
+ keys = rows.first.keys
+ columns = keys.map { |key| connection.quote_column_name(key) }
+
+ disable_quote = Array(disable_quote).to_set
+ tuples = rows.map do |row|
+ keys.map do |k|
+ disable_quote.include?(k) ? row[k] : connection.quote(row[k])
+ end
+ end
+
+ sql = <<-EOF
+ INSERT INTO #{table} (#{columns.join(', ')})
+ VALUES #{tuples.map { |tuple| "(#{tuple.join(', ')})" }.join(', ')}
+ EOF
+
+ sql = "#{sql} ON CONFLICT DO NOTHING" if on_conflict == :do_nothing
+
+ sql = "#{sql} RETURNING id" if return_ids
+
+ result = connection.execute(sql)
+
+ if return_ids
+ result.values.map { |tuple| tuple[0].to_i }
+ else
+ []
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/loaded_in_group_list.rb b/app/models/concerns/loaded_in_group_list.rb
index 848ef63f1c2..98f6ad58434 100644
--- a/app/models/concerns/loaded_in_group_list.rb
+++ b/app/models/concerns/loaded_in_group_list.rb
@@ -41,9 +41,11 @@ module LoadedInGroupList
namespaces = Namespace.arel_table
children = namespaces.alias('children')
+ # TODO 6473: remove the filtering of the Namespaces::ProjectNamespace see https://gitlab.com/groups/gitlab-org/-/epics/6473
namespaces.project(Arel.star.count.as('preloaded_subgroup_count'))
.from(children)
.where(children[:parent_id].eq(namespaces[:id]))
+ .where(children[:type].is_distinct_from(Namespaces::ProjectNamespace.sti_name))
end
def member_count_sql
diff --git a/app/models/concerns/loose_foreign_key.rb b/app/models/concerns/loose_foreign_key.rb
index 4e822a04869..102292672b3 100644
--- a/app/models/concerns/loose_foreign_key.rb
+++ b/app/models/concerns/loose_foreign_key.rb
@@ -7,20 +7,18 @@ module LooseForeignKey
# Loose foreign keys allow delayed processing of associated database records
# with similar guarantees than a database foreign key.
#
- # TODO: finalize this later once the async job is in place
- #
# Prerequisites:
#
# To start using the concern, you'll need to install a database trigger to the parent
# table in a standard DB migration (not post-migration).
#
- # > add_loose_foreign_key_support(:projects, :gitlab_main)
+ # > track_record_deletions(:projects)
#
# Usage:
#
# > class Ci::Build < ApplicationRecord
# >
- # > loose_foreign_key :security_scans, :build_id, on_delete: :async_delete, gitlab_schema: :gitlab_main
+ # > loose_foreign_key :security_scans, :build_id, on_delete: :async_delete
# >
# > # associations can be still defined, the dependent options is no longer necessary:
# > has_many :security_scans, class_name: 'Security::Scan'
@@ -32,14 +30,6 @@ module LooseForeignKey
# - :async_delete - deletes the children rows via an asynchronous process.
# - :async_nullify - sets the foreign key column to null via an asynchronous process.
#
- # Options for gitlab_schema:
- #
- # - :gitlab_ci
- # - :gitlab_main
- #
- # The value can be determined by calling `Model.gitlab_schema` where the Model represents
- # the model for the child table.
- #
# How it works:
#
# When adding loose foreign key support to the table, a DELETE trigger is installed
@@ -69,23 +59,17 @@ module LooseForeignKey
end
on_delete_options = %i[async_delete async_nullify]
- gitlab_schema_options = [ApplicationRecord.gitlab_schema, Ci::ApplicationRecord.gitlab_schema]
unless on_delete_options.include?(symbolized_options[:on_delete]&.to_sym)
raise "Invalid on_delete option given: #{symbolized_options[:on_delete]}. Valid options: #{on_delete_options.join(', ')}"
end
- unless gitlab_schema_options.include?(symbolized_options[:gitlab_schema]&.to_sym)
- raise "Invalid gitlab_schema option given: #{symbolized_options[:gitlab_schema]}. Valid options: #{gitlab_schema_options.join(', ')}"
- end
-
definition = ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
table_name.to_s,
to_table.to_s,
{
column: column.to_s,
- on_delete: symbolized_options[:on_delete].to_sym,
- gitlab_schema: symbolized_options[:gitlab_schema].to_sym
+ on_delete: symbolized_options[:on_delete].to_sym
}
)
diff --git a/app/models/concerns/merge_request_reviewer_state.rb b/app/models/concerns/merge_request_reviewer_state.rb
new file mode 100644
index 00000000000..216a3a0bd64
--- /dev/null
+++ b/app/models/concerns/merge_request_reviewer_state.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module MergeRequestReviewerState
+ extend ActiveSupport::Concern
+
+ included do
+ enum state: {
+ unreviewed: 0,
+ reviewed: 1,
+ attention_requested: 2
+ }
+
+ validates :state,
+ presence: true,
+ inclusion: { in: self.states.keys }
+
+ after_initialize :set_state, unless: :persisted?
+
+ def set_state
+ if Feature.enabled?(:mr_attention_requests, self.merge_request&.project, default_enabled: :yaml)
+ self.state = :attention_requested
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/milestoneable.rb b/app/models/concerns/milestoneable.rb
index c4f810ab9b1..12041b103f6 100644
--- a/app/models/concerns/milestoneable.rb
+++ b/app/models/concerns/milestoneable.rb
@@ -14,13 +14,12 @@ module Milestoneable
validate :milestone_is_valid
- scope :of_milestones, ->(ids) { where(milestone_id: ids) }
scope :any_milestone, -> { where.not(milestone_id: nil) }
scope :with_milestone, ->(title) { left_joins_milestones.where(milestones: { title: title }) }
scope :without_particular_milestone, ->(title) { left_outer_joins(:milestone).where("milestones.title != ? OR milestone_id IS NULL", title) }
scope :any_release, -> { joins_milestone_releases }
scope :with_release, -> (tag, project_id) { joins_milestone_releases.where( milestones: { releases: { tag: tag, project_id: project_id } } ) }
- scope :without_particular_release, -> (tag, project_id) { joins_milestone_releases.where.not( milestones: { releases: { tag: tag, project_id: project_id } } ) }
+ scope :without_particular_release, -> (tag, project_id) { joins_milestone_releases.where.not(milestones: { releases: { tag: tag, project_id: project_id } }) }
scope :left_joins_milestones, -> { joins("LEFT OUTER JOIN milestones ON #{table_name}.milestone_id = milestones.id") }
scope :order_milestone_due_desc, -> { left_joins_milestones.reorder(Arel.sql('milestones.due_date IS NULL, milestones.id IS NULL, milestones.due_date DESC')) }
diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb
index f6d4e5bd27b..ea4fe5b27dc 100644
--- a/app/models/concerns/noteable.rb
+++ b/app/models/concerns/noteable.rb
@@ -98,6 +98,27 @@ module Noteable
.order('MIN(created_at), MIN(id)')
end
+ # This does not consider OutOfContextDiscussions in MRs
+ # where notes from commits are overriden so that they have
+ # the same discussion_id
+ def discussion_root_note_ids(notes_filter:)
+ relations = []
+
+ relations << discussion_notes.select(
+ "'notes' AS table_name",
+ 'discussion_id',
+ 'MIN(id) AS id',
+ 'MIN(created_at) AS created_at'
+ ).with_notes_filter(notes_filter)
+ .group(:discussion_id)
+
+ if notes_filter != UserPreference::NOTES_FILTERS[:only_comments]
+ relations += synthetic_note_ids_relations
+ end
+
+ Note.from_union(relations, remove_duplicates: false).fresh
+ end
+
def capped_notes_count(max)
notes.limit(max).count
end
@@ -179,6 +200,18 @@ module Noteable
project_email.sub('@', "-#{iid}@")
end
+
+ private
+
+ # Synthetic system notes don't have discussion IDs because these are generated dynamically
+ # in Ruby. These are always root notes anyway so we don't need to group by discussion ID.
+ def synthetic_note_ids_relations
+ [
+ resource_label_events.select("'resource_label_events'", "'NULL'", :id, :created_at),
+ resource_milestone_events.select("'resource_milestone_events'", "'NULL'", :id, :created_at),
+ resource_state_events.select("'resource_state_events'", "'NULL'", :id, :created_at)
+ ]
+ end
end
Noteable.extend(Noteable::ClassMethods)
diff --git a/app/models/concerns/reactive_service.rb b/app/models/concerns/reactive_service.rb
deleted file mode 100644
index c444f238944..00000000000
--- a/app/models/concerns/reactive_service.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module ReactiveService
- extend ActiveSupport::Concern
-
- included do
- include ReactiveCaching
-
- # Default cache key: class name + project_id
- self.reactive_cache_key = ->(service) { [service.class.model_name.singular, service.project_id] }
- self.reactive_cache_work_type = :external_dependency
- end
-end
diff --git a/app/models/concerns/security/latest_pipeline_information.rb b/app/models/concerns/security/latest_pipeline_information.rb
new file mode 100644
index 00000000000..87eae3cac68
--- /dev/null
+++ b/app/models/concerns/security/latest_pipeline_information.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Security
+ module LatestPipelineInformation
+ private
+
+ def scanner_enabled?(scan_type)
+ latest_builds_reports.include?(scan_type)
+ end
+
+ def latest_builds_reports(only_successful_builds: false)
+ strong_memoize("latest_builds_reports_#{only_successful_builds}") do
+ builds = latest_security_builds
+ builds = builds.select { |build| build.status == 'success' } if only_successful_builds
+ builds.flat_map do |build|
+ build.options[:artifacts][:reports].keys
+ end
+ end
+ end
+
+ def latest_security_builds
+ return [] unless latest_default_branch_pipeline
+
+ ::Security::SecurityJobsFinder.new(pipeline: latest_default_branch_pipeline).execute +
+ ::Security::LicenseComplianceJobsFinder.new(pipeline: latest_default_branch_pipeline).execute
+ end
+
+ def latest_default_branch_pipeline
+ strong_memoize(:pipeline) { latest_pipeline }
+ end
+
+ def auto_devops_source?
+ latest_default_branch_pipeline&.auto_devops_source?
+ end
+ end
+end
diff --git a/app/models/concerns/service_push_data_validations.rb b/app/models/concerns/service_push_data_validations.rb
deleted file mode 100644
index 451804a2c56..00000000000
--- a/app/models/concerns/service_push_data_validations.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-# This concern is used by registered integrations such as Integrations::TeamCity and
-# Integrations::DroneCi and adds methods to perform validations on the received
-# data.
-
-module ServicePushDataValidations
- extend ActiveSupport::Concern
-
- def merge_request_valid?(data)
- data.dig(:object_attributes, :state) == 'opened' && merge_request_unchecked?(data)
- end
-
- def push_valid?(data)
- data[:total_commits_count] > 0 &&
- !branch_removed?(data) &&
- # prefer merge request trigger over push to avoid double builds
- !opened_merge_requests?(data)
- end
-
- def tag_push_valid?(data)
- data[:total_commits_count] > 0 && !branch_removed?(data)
- end
-
- private
-
- def branch_removed?(data)
- Gitlab::Git.blank_ref?(data[:after])
- end
-
- def opened_merge_requests?(data)
- project.merge_requests
- .opened
- .from_project(project)
- .from_source_branches(Gitlab::Git.ref_name(data[:ref]))
- .exists?
- end
-
- def merge_request_unchecked?(data)
- MergeRequest.state_machines[:merge_status]
- .check_state?(data.dig(:object_attributes, :merge_status))
- end
-end
diff --git a/app/models/concerns/sha256_attribute.rb b/app/models/concerns/sha256_attribute.rb
index 17fda6c806c..3c906642b1a 100644
--- a/app/models/concerns/sha256_attribute.rb
+++ b/app/models/concerns/sha256_attribute.rb
@@ -39,7 +39,7 @@ module Sha256Attribute
end
def database_exists?
- Gitlab::Database.main.exists?
+ database.exists?
end
end
end
diff --git a/app/models/concerns/sha_attribute.rb b/app/models/concerns/sha_attribute.rb
index 27277bc5296..ba7c6c0cd8b 100644
--- a/app/models/concerns/sha_attribute.rb
+++ b/app/models/concerns/sha_attribute.rb
@@ -32,7 +32,7 @@ module ShaAttribute
end
def database_exists?
- Gitlab::Database.main.exists?
+ database.exists?
end
end
end
diff --git a/app/models/concerns/strip_attribute.rb b/app/models/concerns/strip_attribute.rb
index 1c433a3275e..817a4465f91 100644
--- a/app/models/concerns/strip_attribute.rb
+++ b/app/models/concerns/strip_attribute.rb
@@ -2,7 +2,8 @@
# == Strip Attribute module
#
-# Contains functionality to clean attributes before validation
+# Contains functionality to remove leading and trailing
+# whitespace from the attribute before validation
#
# Usage:
#
diff --git a/app/models/concerns/timebox.rb b/app/models/concerns/timebox.rb
index 79cbe225e5a..3fe9d7f4d71 100644
--- a/app/models/concerns/timebox.rb
+++ b/app/models/concerns/timebox.rb
@@ -11,9 +11,7 @@ module Timebox
include StripAttribute
include FromUnion
- TimeboxStruct = Struct.new(:title, :name, :id) do
- include GlobalID::Identification
-
+ TimeboxStruct = Struct.new(:title, :name, :id, :class_name) do
# Ensure these models match the interface required for exporting
def serializable_hash(_opts = {})
{ title: title, name: name, id: id }
@@ -22,6 +20,10 @@ module Timebox
def self.declarative_policy_class
"TimeboxPolicy"
end
+
+ def to_global_id
+ ::Gitlab::GlobalId.build(self, model_name: class_name, id: id)
+ end
end
# Represents a "No Timebox" state used for filtering Issues and Merge
@@ -33,10 +35,10 @@ module Timebox
included do
# Defines the same constants above, but inside the including class.
- const_set :None, TimeboxStruct.new("No #{self.name}", "No #{self.name}", 0)
- const_set :Any, TimeboxStruct.new("Any #{self.name}", '', -1)
- const_set :Upcoming, TimeboxStruct.new('Upcoming', '#upcoming', -2)
- const_set :Started, TimeboxStruct.new('Started', '#started', -3)
+ const_set :None, TimeboxStruct.new("No #{self.name}", "No #{self.name}", 0, self.name)
+ const_set :Any, TimeboxStruct.new("Any #{self.name}", '', -1, self.name)
+ const_set :Upcoming, TimeboxStruct.new('Upcoming', '#upcoming', -2, self.name)
+ const_set :Started, TimeboxStruct.new('Started', '#started', -3, self.name)
alias_method :timebox_id, :id
diff --git a/app/models/concerns/transactions.rb b/app/models/concerns/transactions.rb
new file mode 100644
index 00000000000..a186ebc8475
--- /dev/null
+++ b/app/models/concerns/transactions.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Transactions
+ extend ActiveSupport::Concern
+
+ class_methods do
+ # inside_transaction? will return true if the caller is running within a
+ # transaction. Handles special cases when running inside a test environment,
+ # where tests may be wrapped in transactions
+ def inside_transaction?
+ base = Rails.env.test? ? @open_transactions_baseline.to_i : 0
+
+ connection.open_transactions > base
+ end
+
+ # These methods that access @open_transactions_baseline are not thread-safe.
+ # These are fine though because we only call these in RSpec's main thread.
+ # If we decide to run specs multi-threaded, we would need to use something
+ # like ThreadGroup to keep track of this value
+ def set_open_transactions_baseline
+ @open_transactions_baseline = connection.open_transactions
+ end
+
+ def reset_open_transactions_baseline
+ @open_transactions_baseline = 0
+ end
+ end
+end
diff --git a/app/models/concerns/ttl_expirable.rb b/app/models/concerns/ttl_expirable.rb
index 00abe0a06e6..6d89521255c 100644
--- a/app/models/concerns/ttl_expirable.rb
+++ b/app/models/concerns/ttl_expirable.rb
@@ -5,10 +5,11 @@ module TtlExpirable
included do
validates :status, presence: true
+ default_value_for :read_at, Time.zone.now
enum status: { default: 0, expired: 1, processing: 2, error: 3 }
- scope :updated_before, ->(number_of_days) { where("updated_at <= ?", Time.zone.now - number_of_days.days) }
+ scope :read_before, ->(number_of_days) { where("read_at <= ?", Time.zone.now - number_of_days.days) }
scope :active, -> { where(status: :default) }
scope :lock_next_by, ->(sort) do
@@ -17,4 +18,8 @@ module TtlExpirable
.lock('FOR UPDATE SKIP LOCKED')
end
end
+
+ def read!
+ self.update(read_at: Time.zone.now)
+ end
end
diff --git a/app/models/concerns/update_highest_role.rb b/app/models/concerns/update_highest_role.rb
index 6432cc794a5..2b0ec5c7e21 100644
--- a/app/models/concerns/update_highest_role.rb
+++ b/app/models/concerns/update_highest_role.rb
@@ -15,7 +15,7 @@ module UpdateHighestRole
# Schedule a Sidekiq job to update the highest role for a User
#
# The job will be called outside of a transaction in order to ensure the changes
- # to be commited before attempting to update the highest role.
+ # to be committed before attempting to update the highest role.
# The exlusive lease will not be released after completion to prevent multiple jobs
# being executed during the defined timeout.
def update_highest_role
diff --git a/app/models/concerns/x509_serial_number_attribute.rb b/app/models/concerns/x509_serial_number_attribute.rb
index dfb1e151b41..e51ed95bf70 100644
--- a/app/models/concerns/x509_serial_number_attribute.rb
+++ b/app/models/concerns/x509_serial_number_attribute.rb
@@ -39,7 +39,7 @@ module X509SerialNumberAttribute
end
def database_exists?
- Gitlab::Database.main.exists?
+ database.exists?
end
end
end
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index ecdac64b31b..173b38b2c63 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -31,7 +31,7 @@ class CustomEmoji < ApplicationRecord
private
def valid_emoji_name
- if Gitlab::Emoji.emoji_exists?(name)
+ if TanukiEmoji.find_by_alpha_code(name)
errors.add(:name, _('%{name} is already being used for another emoji') % { name: self.name })
end
end
diff --git a/app/models/customer_relations/contact.rb b/app/models/customer_relations/contact.rb
index c632f8e2efa..5898bc3412f 100644
--- a/app/models/customer_relations/contact.rb
+++ b/app/models/customer_relations/contact.rb
@@ -7,7 +7,8 @@ class CustomerRelations::Contact < ApplicationRecord
belongs_to :group, -> { where(type: Group.sti_name) }, foreign_key: 'group_id'
belongs_to :organization, optional: true
- has_and_belongs_to_many :issues, join_table: :issue_customer_relations_contacts # rubocop: disable Rails/HasAndBelongsToMany
+ has_many :issue_contacts, inverse_of: :contact
+ has_many :issues, through: :issue_contacts, inverse_of: :customer_relations_contacts
strip_attributes! :phone, :first_name, :last_name
diff --git a/app/models/customer_relations/issue_contact.rb b/app/models/customer_relations/issue_contact.rb
new file mode 100644
index 00000000000..98faf8d6644
--- /dev/null
+++ b/app/models/customer_relations/issue_contact.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class CustomerRelations::IssueContact < ApplicationRecord
+ self.table_name = "issue_customer_relations_contacts"
+
+ belongs_to :issue, optional: false, inverse_of: :customer_relations_contacts
+ belongs_to :contact, optional: false, inverse_of: :issue_contacts
+
+ validate :contact_belongs_to_issue_group
+
+ private
+
+ def contact_belongs_to_issue_group
+ return unless contact&.group_id
+ return unless issue&.project&.namespace_id
+ return if contact.group_id == issue.project.namespace_id
+
+ errors.add(:base, _('The contact does not belong to the same group as the issue'))
+ end
+end
diff --git a/app/models/data_list.rb b/app/models/data_list.rb
index adad8e3013e..e99364b2709 100644
--- a/app/models/data_list.rb
+++ b/app/models/data_list.rb
@@ -1,22 +1,26 @@
# frozen_string_literal: true
class DataList
- def initialize(batch, data_fields_hash, klass)
+ def initialize(batch, data_fields_hash, data_fields_klass)
@batch = batch
@data_fields_hash = data_fields_hash
- @klass = klass
+ @data_fields_klass = data_fields_klass
end
def to_array
- [klass, columns, values]
+ [data_fields_klass, columns, values]
end
private
- attr_reader :batch, :data_fields_hash, :klass
+ attr_reader :batch, :data_fields_hash, :data_fields_klass
def columns
- data_fields_hash.keys << 'service_id'
+ data_fields_hash.keys << data_fields_foreign_key
+ end
+
+ def data_fields_foreign_key
+ data_fields_klass.reflections['integration'].foreign_key
end
def values
diff --git a/app/models/dependency_proxy/blob.rb b/app/models/dependency_proxy/blob.rb
index 7ca15652586..bd5c022e692 100644
--- a/app/models/dependency_proxy/blob.rb
+++ b/app/models/dependency_proxy/blob.rb
@@ -7,6 +7,8 @@ class DependencyProxy::Blob < ApplicationRecord
belongs_to :group
+ MAX_FILE_SIZE = 5.gigabytes.freeze
+
validates :group, presence: true
validates :file, presence: true
validates :file_name, presence: true
diff --git a/app/models/dependency_proxy/manifest.rb b/app/models/dependency_proxy/manifest.rb
index b83047efe54..64f484942ef 100644
--- a/app/models/dependency_proxy/manifest.rb
+++ b/app/models/dependency_proxy/manifest.rb
@@ -7,17 +7,19 @@ class DependencyProxy::Manifest < ApplicationRecord
belongs_to :group
+ MAX_FILE_SIZE = 10.megabytes.freeze
+ DIGEST_HEADER = 'Docker-Content-Digest'
+
validates :group, presence: true
validates :file, presence: true
validates :file_name, presence: true
validates :digest, presence: true
- mount_file_store_uploader DependencyProxy::FileUploader
+ scope :order_id_desc, -> { reorder(id: :desc) }
- def self.find_or_initialize_by_file_name_or_digest(file_name:, digest:)
- result = find_by(file_name: file_name) || find_by(digest: digest)
- return result if result
+ mount_file_store_uploader DependencyProxy::FileUploader
- new(file_name: file_name, digest: digest)
+ def self.find_by_file_name_or_digest(file_name:, digest:)
+ find_by(file_name: file_name) || find_by(digest: digest)
end
end
diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb
index 8f5a713af3f..4ed38f578ee 100644
--- a/app/models/deploy_key.rb
+++ b/app/models/deploy_key.rb
@@ -7,12 +7,16 @@ class DeployKey < Key
has_many :deploy_keys_projects, inverse_of: :deploy_key, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :projects, through: :deploy_keys_projects
+
+ has_many :deploy_keys_projects_with_write_access, -> { with_write_access }, class_name: "DeployKeysProject"
+ has_many :projects_with_write_access, -> { includes(:route) }, class_name: 'Project', through: :deploy_keys_projects_with_write_access, source: :project
has_many :protected_branch_push_access_levels, class_name: '::ProtectedBranch::PushAccessLevel'
scope :in_projects, ->(projects) { joins(:deploy_keys_projects).where(deploy_keys_projects: { project_id: projects }) }
scope :with_write_access, -> { joins(:deploy_keys_projects).merge(DeployKeysProject.with_write_access) }
scope :are_public, -> { where(public: true) }
scope :with_projects, -> { includes(deploy_keys_projects: { project: [:route, namespace: :route] }) }
+ scope :including_projects_with_write_access, -> { includes(:projects_with_write_access) }
accepts_nested_attributes_for :deploy_keys_projects
@@ -52,10 +56,6 @@ class DeployKey < Key
end
end
- def projects_with_write_access
- Project.with_route.where(id: deploy_keys_projects.with_write_access.select(:project_id))
- end
-
def self.with_write_access_for_project(project, deploy_key: nil)
query = in_projects(project).with_write_access
query = query.where(id: deploy_key) if deploy_key
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index f91700f764b..ade19ce02a8 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -8,11 +8,12 @@ class Deployment < ApplicationRecord
include Importable
include Gitlab::Utils::StrongMemoize
include FastDestroyAll
- include IgnorableColumns
StatusUpdateError = Class.new(StandardError)
StatusSyncError = Class.new(StandardError)
+ ARCHIVABLE_OFFSET = 50_000
+
belongs_to :project, required: true
belongs_to :environment, required: true
belongs_to :cluster, class_name: 'Clusters::Cluster', optional: true
@@ -54,6 +55,8 @@ class Deployment < ApplicationRecord
scope :finished_after, ->(date) { where('finished_at >= ?', date) }
scope :finished_before, ->(date) { where('finished_at < ?', date) }
+ scope :ordered, -> { order(finished_at: :desc) }
+
FINISHED_STATUSES = %i[success failed canceled].freeze
state_machine :status, initial: :created do
@@ -99,6 +102,10 @@ class Deployment < ApplicationRecord
deployment.run_after_commit do
Deployments::UpdateEnvironmentWorker.perform_async(id)
Deployments::LinkMergeRequestWorker.perform_async(id)
+
+ if ::Feature.enabled?(:deployments_archive, deployment.project, default_enabled: :yaml)
+ Deployments::ArchiveInProjectWorker.perform_async(deployment.project_id)
+ end
end
end
@@ -132,6 +139,14 @@ class Deployment < ApplicationRecord
skipped: 5
}
+ def self.archivables_in(project, limit:)
+ start_iid = project.deployments.order(iid: :desc).limit(1)
+ .select("(iid - #{ARCHIVABLE_OFFSET}) AS start_iid")
+
+ project.deployments.preload(:environment).where('iid <= (?)', start_iid)
+ .where(archived: false).limit(limit)
+ end
+
def self.last_for_environment(environment)
ids = self
.for_environment(environment)
@@ -299,7 +314,7 @@ class Deployment < ApplicationRecord
"#{id} as deployment_id",
"#{environment_id} as environment_id").to_sql
- # We don't use `Gitlab::Database.main.bulk_insert` here so that we don't need to
+ # We don't use `ApplicationRecord.legacy_bulk_insert` here so that we don't need to
# first pluck lots of IDs into memory.
#
# We also ignore any duplicates so this method can be called multiple times
@@ -325,6 +340,7 @@ class Deployment < ApplicationRecord
def sync_status_with(build)
return false unless ::Deployment.statuses.include?(build.status)
+ return false if build.created? || build.status == self.status
update_status!(build.status)
rescue StandardError => e
diff --git a/app/models/design_management/version.rb b/app/models/design_management/version.rb
index 6cda03557d1..5819404efb9 100644
--- a/app/models/design_management/version.rb
+++ b/app/models/design_management/version.rb
@@ -88,7 +88,7 @@ module DesignManagement
rows = design_actions.map { |action| action.row_attrs(version) }
- Gitlab::Database.main.bulk_insert(::DesignManagement::Action.table_name, rows) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(::DesignManagement::Action.table_name, rows) # rubocop:disable Gitlab/BulkInsert
version.designs.reset
version.validate!
design_actions.each(&:performed)
diff --git a/app/models/email.rb b/app/models/email.rb
index 0140f784842..676e79406e9 100644
--- a/app/models/email.rb
+++ b/app/models/email.rb
@@ -29,7 +29,7 @@ class Email < ApplicationRecord
end
def unique_email
- self.errors.add(:email, 'has already been taken') if User.exists?(email: self.email)
+ self.errors.add(:email, 'has already been taken') if primary_email_of_another_user?
end
def validate_email_format
@@ -40,4 +40,14 @@ class Email < ApplicationRecord
def update_invalid_gpg_signatures
user.update_invalid_gpg_signatures if confirmed?
end
+
+ def user_primary_email?
+ email.casecmp?(user.email)
+ end
+
+ private
+
+ def primary_email_of_another_user?
+ User.where(email: email).where.not(id: user_id).exists?
+ end
end
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 31ab426728b..2618991c9e5 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -425,6 +425,14 @@ class Environment < ApplicationRecord
clear_reactive_cache!
end
+ def should_link_to_merge_requests?
+ unfoldered? || production? || staging?
+ end
+
+ def unfoldered?
+ environment_type.nil?
+ end
+
private
def rollout_status_available?
diff --git a/app/models/error_tracking/error.rb b/app/models/error_tracking/error.rb
index 2d6a4694def..efbb6adff70 100644
--- a/app/models/error_tracking/error.rb
+++ b/app/models/error_tracking/error.rb
@@ -18,9 +18,10 @@ class ErrorTracking::Error < ApplicationRecord
scope :for_status, -> (status) { where(status: status) }
validates :project, presence: true
- validates :name, presence: true
- validates :description, presence: true
- validates :actor, presence: true
+ validates :name, presence: true, length: { maximum: 255 }
+ validates :description, presence: true, length: { maximum: 1024 }
+ validates :actor, presence: true, length: { maximum: 255 }
+ validates :platform, length: { maximum: 255 }
validates :status, presence: true
enum status: {
diff --git a/app/models/error_tracking/error_event.rb b/app/models/error_tracking/error_event.rb
index 686518a39fb..0b638f65768 100644
--- a/app/models/error_tracking/error_event.rb
+++ b/app/models/error_tracking/error_event.rb
@@ -6,7 +6,9 @@ class ErrorTracking::ErrorEvent < ApplicationRecord
validates :payload, json_schema: { filename: 'error_tracking_event_payload' }
validates :error, presence: true
- validates :description, presence: true
+ validates :description, presence: true, length: { maximum: 1024 }
+ validates :level, length: { maximum: 255 }
+ validates :environment, length: { maximum: 255 }
validates :occurred_at, presence: true
def stacktrace
@@ -61,9 +63,9 @@ class ErrorTracking::ErrorEvent < ApplicationRecord
pre_context = entry['pre_context']
post_context = entry['post_context']
- context += lines_with_position(pre_context, error_line_no - pre_context.size)
+ context += lines_with_position(pre_context, error_line_no - pre_context.size) if pre_context
context += lines_with_position([error_line], error_line_no)
- context += lines_with_position(post_context, error_line_no + 1)
+ context += lines_with_position(post_context, error_line_no + 1) if post_context
context.reject(&:blank?)
end
diff --git a/app/models/event.rb b/app/models/event.rb
index d6588699d27..f6174589a84 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -9,9 +9,6 @@ class Event < ApplicationRecord
include Gitlab::Utils::StrongMemoize
include UsageStatistics
include ShaAttribute
- include IgnorableColumns
-
- ignore_columns :id_convert_to_bigint, remove_with: '14.5', remove_after: '2021-10-22'
default_scope { reorder(nil) } # rubocop:disable Cop/DefaultScope
diff --git a/app/models/gpg_signature.rb b/app/models/gpg_signature.rb
index 0c36e51120f..2775b520b2f 100644
--- a/app/models/gpg_signature.rb
+++ b/app/models/gpg_signature.rb
@@ -12,7 +12,8 @@ class GpgSignature < ApplicationRecord
same_user_different_email: 2,
other_user: 3,
unverified_key: 4,
- unknown_key: 5
+ unknown_key: 5,
+ multiple_signatures: 6
}
belongs_to :project
diff --git a/app/models/group.rb b/app/models/group.rb
index c5e119451e3..2dd20300ad2 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -56,6 +56,9 @@ class Group < Namespace
has_many :boards
has_many :badges, class_name: 'GroupBadge'
+ has_many :organizations, class_name: 'CustomerRelations::Organization', inverse_of: :group
+ has_many :contacts, class_name: 'CustomerRelations::Contact', inverse_of: :group
+
has_many :cluster_groups, class_name: 'Clusters::Group'
has_many :clusters, through: :cluster_groups, class_name: 'Clusters::Cluster'
@@ -194,13 +197,8 @@ class Group < Namespace
def ids_with_disabled_email(groups)
inner_groups = Group.where('id = namespaces_with_emails_disabled.id')
- inner_ancestors = if Feature.enabled?(:linear_group_ancestor_scopes, default_enabled: :yaml)
- inner_groups.self_and_ancestors
- else
- Gitlab::ObjectHierarchy.new(inner_groups).base_and_ancestors
- end
-
- inner_query = inner_ancestors
+ inner_query = inner_groups
+ .self_and_ancestors
.where(emails_disabled: true)
.select('1')
.limit(1)
@@ -317,13 +315,15 @@ class Group < Namespace
owners.include?(user)
end
- def add_users(users, access_level, current_user: nil, expires_at: nil)
+ def add_users(users, access_level, current_user: nil, expires_at: nil, tasks_to_be_done: [], tasks_project_id: nil)
Members::Groups::BulkCreatorService.add_users( # rubocop:disable CodeReuse/ServiceClass
self,
users,
access_level,
current_user: current_user,
- expires_at: expires_at
+ expires_at: expires_at,
+ tasks_to_be_done: tasks_to_be_done,
+ tasks_project_id: tasks_project_id
)
end
@@ -760,18 +760,6 @@ class Group < Namespace
Timelog.in_group(self)
end
- def cached_issues_state_count_enabled?
- Feature.enabled?(:cached_issues_state_count, self, default_enabled: :yaml)
- end
-
- def organizations
- ::CustomerRelations::Organization.where(group_id: self.id)
- end
-
- def contacts
- ::CustomerRelations::Contact.where(group_id: self.id)
- end
-
def dependency_proxy_image_ttl_policy
super || build_dependency_proxy_image_ttl_policy
end
diff --git a/app/models/integration.rb b/app/models/integration.rb
index 158764bb783..d3059fa6d4a 100644
--- a/app/models/integration.rb
+++ b/app/models/integration.rb
@@ -14,7 +14,7 @@ class Integration < ApplicationRecord
asana assembla bamboo bugzilla buildkite campfire confluence custom_issue_tracker datadog discord
drone_ci emails_on_push ewm external_wiki flowdock hangouts_chat irker jira
mattermost mattermost_slash_commands microsoft_teams packagist pipelines_email
- pivotaltracker prometheus pushover redmine slack slack_slash_commands teamcity unify_circuit webex_teams youtrack
+ pivotaltracker prometheus pushover redmine shimo slack slack_slash_commands teamcity unify_circuit webex_teams youtrack zentao
].freeze
PROJECT_SPECIFIC_INTEGRATION_NAMES = %w[
@@ -373,7 +373,7 @@ class Integration < ApplicationRecord
end
def to_data_fields_hash
- data_fields.as_json(only: data_fields.class.column_names).except('id', 'service_id')
+ data_fields.as_json(only: data_fields.class.column_names).except('id', 'service_id', 'integration_id')
end
def event_channel_names
diff --git a/app/models/integrations/bamboo.rb b/app/models/integrations/bamboo.rb
index 1a7cbaa34c7..0774b84b69f 100644
--- a/app/models/integrations/bamboo.rb
+++ b/app/models/integrations/bamboo.rb
@@ -3,7 +3,7 @@
module Integrations
class Bamboo < BaseCi
include ActionView::Helpers::UrlHelper
- include ReactiveService
+ include ReactivelyCached
prop_accessor :bamboo_url, :build_key, :username, :password
diff --git a/app/models/integrations/base_chat_notification.rb b/app/models/integrations/base_chat_notification.rb
index c6335782b5e..ca72de47d30 100644
--- a/app/models/integrations/base_chat_notification.rb
+++ b/app/models/integrations/base_chat_notification.rb
@@ -73,7 +73,12 @@ module Integrations
{ type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}", required: true }.freeze,
{ type: 'text', name: 'username', placeholder: 'GitLab-integration' }.freeze,
{ type: 'checkbox', name: 'notify_only_broken_pipelines', help: 'Do not send notifications for successful pipelines.' }.freeze,
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }.freeze,
+ {
+ type: 'select',
+ name: 'branches_to_be_notified',
+ title: s_('Integrations|Branches for which notifications are to be sent'),
+ choices: branch_choices
+ }.freeze,
{
type: 'text',
name: 'labels_to_be_notified',
diff --git a/app/models/integrations/buildkite.rb b/app/models/integrations/buildkite.rb
index 94a37f0c4f2..9fad3a42647 100644
--- a/app/models/integrations/buildkite.rb
+++ b/app/models/integrations/buildkite.rb
@@ -5,7 +5,7 @@ require "addressable/uri"
module Integrations
class Buildkite < BaseCi
include HasWebHook
- include ReactiveService
+ include ReactivelyCached
extend Gitlab::Utils::Override
ENDPOINT = "https://buildkite.com"
diff --git a/app/models/integrations/discord.rb b/app/models/integrations/discord.rb
index 76160a61bc3..21993dd3c43 100644
--- a/app/models/integrations/discord.rb
+++ b/app/models/integrations/discord.rb
@@ -41,7 +41,12 @@ module Integrations
[
{ type: "text", name: "webhook", placeholder: "https://discordapp.com/api/webhooks/…", help: "URL to the webhook for the Discord channel." },
{ type: "checkbox", name: "notify_only_broken_pipelines" },
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
+ {
+ type: 'select',
+ name: 'branches_to_be_notified',
+ title: s_('Integrations|Branches for which notifications are to be sent'),
+ choices: branch_choices
+ }
]
end
diff --git a/app/models/integrations/drone_ci.rb b/app/models/integrations/drone_ci.rb
index c93ae432fe9..856d14c022d 100644
--- a/app/models/integrations/drone_ci.rb
+++ b/app/models/integrations/drone_ci.rb
@@ -3,8 +3,8 @@
module Integrations
class DroneCi < BaseCi
include HasWebHook
- include ReactiveService
- include ServicePushDataValidations
+ include PushDataValidations
+ include ReactivelyCached
extend Gitlab::Utils::Override
prop_accessor :drone_url, :token
diff --git a/app/models/integrations/emails_on_push.rb b/app/models/integrations/emails_on_push.rb
index e277633664f..a9cd67550dc 100644
--- a/app/models/integrations/emails_on_push.rb
+++ b/app/models/integrations/emails_on_push.rb
@@ -76,7 +76,12 @@ module Integrations
help: s_("EmailsOnPushService|Send notifications from the committer's email address if the domain matches the domain used by your GitLab instance (such as %{domains}).") % { domains: domains } },
{ type: 'checkbox', name: 'disable_diffs', title: s_("EmailsOnPushService|Disable code diffs"),
help: s_("EmailsOnPushService|Don't include possibly sensitive code diffs in notification body.") },
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices },
+ {
+ type: 'select',
+ name: 'branches_to_be_notified',
+ title: s_('Integrations|Branches for which notifications are to be sent'),
+ choices: branch_choices
+ },
{
type: 'textarea',
name: 'recipients',
@@ -92,7 +97,7 @@ module Integrations
return if recipients.blank?
if self.class.valid_recipients(recipients).size > RECIPIENTS_LIMIT
- errors.add(:recipients, s_("EmailsOnPushService|can't exceed %{recipients_limit}") % { recipients_limit: RECIPIENTS_LIMIT })
+ errors.add(:recipients, s_("Integrations|can't exceed %{recipients_limit}") % { recipients_limit: RECIPIENTS_LIMIT })
end
end
end
diff --git a/app/models/integrations/hangouts_chat.rb b/app/models/integrations/hangouts_chat.rb
index d02cfe4ec56..0d6b9fb1019 100644
--- a/app/models/integrations/hangouts_chat.rb
+++ b/app/models/integrations/hangouts_chat.rb
@@ -40,7 +40,12 @@ module Integrations
[
{ type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}" },
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
+ {
+ type: 'select',
+ name: 'branches_to_be_notified',
+ title: s_('Integrations|Branches for which notifications are to be sent'),
+ choices: branch_choices
+ }
]
end
diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb
index ec6adc87bf4..42c291abf55 100644
--- a/app/models/integrations/jira.rb
+++ b/app/models/integrations/jira.rb
@@ -89,7 +89,6 @@ module Integrations
site: URI.join(url, '/').to_s.delete_suffix('/'), # Intended to find the root
context_path: (url.path.presence || '/').delete_suffix('/'),
auth_type: :basic,
- read_timeout: 120,
use_cookies: true,
additional_cookies: ['OBBasicAuth=fromDialog'],
use_ssl: url.scheme == 'https'
@@ -303,6 +302,14 @@ module Integrations
private
+ def branch_name(noteable)
+ if Feature.enabled?(:jira_use_first_ref_by_oid, project, default_enabled: :yaml)
+ noteable.first_ref_by_oid(project.repository)
+ else
+ noteable.ref_names(project.repository).first
+ end
+ end
+
def server_info
strong_memoize(:server_info) do
client_url.present? ? jira_request { client.ServerInfo.all.attrs } : nil
@@ -496,7 +503,7 @@ module Integrations
{
id: noteable.short_id,
description: noteable.safe_message,
- branch: noteable.ref_names(project.repository).first
+ branch: branch_name(noteable)
}
elsif noteable.is_a?(MergeRequest)
{
@@ -521,7 +528,9 @@ module Integrations
yield
rescue StandardError => error
@error = error
- log_error("Error sending message", client_url: client_url, error: @error.message)
+ payload = { client_url: client_url }
+ Gitlab::ExceptionLogFormatter.format!(error, payload)
+ log_error("Error sending message", payload)
nil
end
diff --git a/app/models/integrations/microsoft_teams.rb b/app/models/integrations/microsoft_teams.rb
index 5aad25e8ddc..71cd4ddaf82 100644
--- a/app/models/integrations/microsoft_teams.rb
+++ b/app/models/integrations/microsoft_teams.rb
@@ -37,7 +37,12 @@ module Integrations
[
{ type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}" },
{ type: 'checkbox', name: 'notify_only_broken_pipelines', help: 'If selected, successful pipelines do not trigger a notification event.' },
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
+ {
+ type: 'select',
+ name: 'branches_to_be_notified',
+ title: s_('Integrations|Branches for which notifications are to be sent'),
+ choices: branch_choices
+ }
]
end
diff --git a/app/models/integrations/pipelines_email.rb b/app/models/integrations/pipelines_email.rb
index efba35cc2a8..6dc41958daa 100644
--- a/app/models/integrations/pipelines_email.rb
+++ b/app/models/integrations/pipelines_email.rb
@@ -4,9 +4,12 @@ module Integrations
class PipelinesEmail < Integration
include NotificationBranchSelection
+ RECIPIENTS_LIMIT = 30
+
prop_accessor :recipients, :branches_to_be_notified
boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch
validates :recipients, presence: true, if: :validate_recipients?
+ validate :number_of_recipients_within_limit, if: :validate_recipients?
def initialize_properties
if properties.nil?
@@ -49,7 +52,7 @@ module Integrations
return unless supported_events.include?(data[:object_kind])
return unless force || should_pipeline_be_notified?(data)
- all_recipients = retrieve_recipients(data)
+ all_recipients = retrieve_recipients
return unless all_recipients.any?
@@ -71,6 +74,7 @@ module Integrations
name: 'notify_only_broken_pipelines' },
{ type: 'select',
name: 'branches_to_be_notified',
+ title: s_('Integrations|Branches for which notifications are to be sent'),
choices: branch_choices }
]
end
@@ -98,8 +102,18 @@ module Integrations
end
end
- def retrieve_recipients(data)
+ def retrieve_recipients
recipients.to_s.split(/[,\r\n ]+/).reject(&:empty?)
end
+
+ private
+
+ def number_of_recipients_within_limit
+ return if recipients.blank?
+
+ if retrieve_recipients.size > RECIPIENTS_LIMIT
+ errors.add(:recipients, s_("Integrations|can't exceed %{recipients_limit}") % { recipients_limit: RECIPIENTS_LIMIT })
+ end
+ end
end
end
diff --git a/app/models/integrations/shimo.rb b/app/models/integrations/shimo.rb
new file mode 100644
index 00000000000..4f42fda2577
--- /dev/null
+++ b/app/models/integrations/shimo.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Shimo < Integration
+ prop_accessor :external_wiki_url
+ validates :external_wiki_url, presence: true, public_url: true, if: :activated?
+
+ def render?
+ valid? && activated?
+ end
+
+ def title
+ s_('Shimo|Shimo')
+ end
+
+ def description
+ s_('Shimo|Link to a Shimo Workspace from the sidebar.')
+ end
+
+ def self.to_param
+ 'shimo'
+ end
+
+ # support for `test` method
+ def execute(_data)
+ response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true, use_read_total_timeout: true)
+ response.body if response.code == 200
+ rescue StandardError
+ nil
+ end
+
+ def self.supported_events
+ %w()
+ end
+
+ def fields
+ [
+ {
+ type: 'text',
+ name: 'external_wiki_url',
+ title: s_('Shimo|Shimo Workspace URL'),
+ required: true
+ }
+ ]
+ end
+ end
+end
diff --git a/app/models/integrations/teamcity.rb b/app/models/integrations/teamcity.rb
index 3f868b57597..008b591c304 100644
--- a/app/models/integrations/teamcity.rb
+++ b/app/models/integrations/teamcity.rb
@@ -2,8 +2,8 @@
module Integrations
class Teamcity < BaseCi
- include ReactiveService
- include ServicePushDataValidations
+ include PushDataValidations
+ include ReactivelyCached
prop_accessor :teamcity_url, :build_type, :username, :password
diff --git a/app/models/integrations/unify_circuit.rb b/app/models/integrations/unify_circuit.rb
index e3e180ae959..f085423d229 100644
--- a/app/models/integrations/unify_circuit.rb
+++ b/app/models/integrations/unify_circuit.rb
@@ -34,7 +34,12 @@ module Integrations
[
{ type: 'text', name: 'webhook', placeholder: "https://yourcircuit.com/rest/v2/webhooks/incoming/…", required: true },
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
+ {
+ type: 'select',
+ name: 'branches_to_be_notified',
+ title: s_('Integrations|Branches for which notifications are to be sent'),
+ choices: branch_choices
+ }
]
end
diff --git a/app/models/integrations/webex_teams.rb b/app/models/integrations/webex_teams.rb
index 6fd82a32035..7660eda6f83 100644
--- a/app/models/integrations/webex_teams.rb
+++ b/app/models/integrations/webex_teams.rb
@@ -36,7 +36,12 @@ module Integrations
[
{ type: 'text', name: 'webhook', placeholder: "https://api.ciscospark.com/v1/webhooks/incoming/...", required: true },
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
+ {
+ type: 'select',
+ name: 'branches_to_be_notified',
+ title: s_('Integrations|Branches for which notifications are to be sent'),
+ choices: branch_choices
+ }
]
end
diff --git a/app/models/integrations/zentao.rb b/app/models/integrations/zentao.rb
index 68c02f54c61..493d42cc40b 100644
--- a/app/models/integrations/zentao.rb
+++ b/app/models/integrations/zentao.rb
@@ -2,6 +2,8 @@
module Integrations
class Zentao < Integration
+ include Gitlab::Routing
+
data_field :url, :api_url, :api_token, :zentao_product_xid
validates :url, public_url: true, presence: true, if: :activated?
@@ -9,16 +11,29 @@ module Integrations
validates :api_token, presence: true, if: :activated?
validates :zentao_product_xid, presence: true, if: :activated?
+ # License Level: EEP_FEATURES
+ def self.issues_license_available?(project)
+ project&.licensed_feature_available?(:zentao_issues_integration)
+ end
+
def data_fields
zentao_tracker_data || self.build_zentao_tracker_data
end
def title
- self.class.name.demodulize
+ 'ZenTao'
end
def description
- s_("ZentaoIntegration|Use Zentao as this project's issue tracker.")
+ s_("ZentaoIntegration|Use ZenTao as this project's issue tracker.")
+ end
+
+ def help
+ s_("ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}.") % {
+ link_start: '<a href="%{url}" target="_blank" rel="noopener noreferrer">'
+ .html_safe % { url: help_page_url('user/project/integrations/zentao') },
+ link_end: '</a>'.html_safe
+ }
end
def self.to_param
@@ -42,28 +57,29 @@ module Integrations
{
type: 'text',
name: 'url',
- title: s_('ZentaoIntegration|Zentao Web URL'),
+ title: s_('ZentaoIntegration|ZenTao Web URL'),
placeholder: 'https://www.zentao.net',
- help: s_('ZentaoIntegration|Base URL of the Zentao instance.'),
+ help: s_('ZentaoIntegration|Base URL of the ZenTao instance.'),
required: true
},
{
type: 'text',
name: 'api_url',
- title: s_('ZentaoIntegration|Zentao API URL (optional)'),
+ title: s_('ZentaoIntegration|ZenTao API URL (optional)'),
help: s_('ZentaoIntegration|If different from Web URL.')
},
{
type: 'password',
name: 'api_token',
- title: s_('ZentaoIntegration|Zentao API token'),
- non_empty_password_title: s_('ZentaoIntegration|Enter API token'),
+ title: s_('ZentaoIntegration|ZenTao API token'),
+ non_empty_password_title: s_('ZentaoIntegration|Enter new ZenTao API token'),
+ non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'),
required: true
},
{
type: 'text',
name: 'zentao_product_xid',
- title: s_('ZentaoIntegration|Zentao Product ID'),
+ title: s_('ZentaoIntegration|ZenTao Product ID'),
required: true
}
]
@@ -76,3 +92,5 @@ module Integrations
end
end
end
+
+::Integrations::Zentao.prepend_mod
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 9c568414ec2..47dc084d69c 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -81,7 +81,8 @@ class Issue < ApplicationRecord
has_and_belongs_to_many :self_managed_prometheus_alert_events, join_table: :issues_self_managed_prometheus_alert_events # rubocop: disable Rails/HasAndBelongsToMany
has_and_belongs_to_many :prometheus_alert_events, join_table: :issues_prometheus_alert_events # rubocop: disable Rails/HasAndBelongsToMany
has_many :prometheus_alerts, through: :prometheus_alert_events
- has_and_belongs_to_many :customer_relations_contacts, join_table: :issue_customer_relations_contacts, class_name: 'CustomerRelations::Contact' # rubocop: disable Rails/HasAndBelongsToMany
+ has_many :issue_customer_relations_contacts, class_name: 'CustomerRelations::IssueContact', inverse_of: :issue
+ has_many :customer_relations_contacts, through: :issue_customer_relations_contacts, source: :contact, class_name: 'CustomerRelations::Contact', inverse_of: :issues
accepts_nested_attributes_for :issuable_severity, update_only: true
accepts_nested_attributes_for :sentry_issue
@@ -203,6 +204,8 @@ class Issue < ApplicationRecord
before_transition closed: :opened do |issue|
issue.closed_at = nil
issue.closed_by = nil
+
+ issue.clear_closure_reason_references
end
end
@@ -378,6 +381,11 @@ class Issue < ApplicationRecord
!duplicated_to_id.nil?
end
+ def clear_closure_reason_references
+ self.moved_to_id = nil
+ self.duplicated_to_id = nil
+ end
+
def can_move?(user, to_project = nil)
if to_project
return false unless user.can?(:admin_issue, to_project)
diff --git a/app/models/key.rb b/app/models/key.rb
index 64385953865..a478434538c 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -46,7 +46,7 @@ class Key < ApplicationRecord
scope :order_last_used_at_desc, -> { reorder(::Gitlab::Database.nulls_last_order('last_used_at', 'DESC')) }
# Date is set specifically in this scope to improve query time.
- scope :expired_and_not_notified, -> { where(["date(expires_at AT TIME ZONE 'UTC') BETWEEN '2000-01-01' AND CURRENT_DATE AND expiry_notification_delivered_at IS NULL"]) }
+ scope :expired_today_and_not_notified, -> { where(["date(expires_at AT TIME ZONE 'UTC') = CURRENT_DATE AND expiry_notification_delivered_at IS NULL"]) }
scope :expiring_soon_and_not_notified, -> { where(["date(expires_at AT TIME ZONE 'UTC') > CURRENT_DATE AND date(expires_at AT TIME ZONE 'UTC') < ? AND before_expiry_notification_delivered_at IS NULL", DAYS_TO_EXPIRE.days.from_now.to_date]) }
def self.regular_keys
diff --git a/app/models/label_link.rb b/app/models/label_link.rb
index 4fb5fd8c58a..d326b07ad31 100644
--- a/app/models/label_link.rb
+++ b/app/models/label_link.rb
@@ -11,4 +11,16 @@ class LabelLink < ApplicationRecord
validates :label, presence: true, unless: :importing?
scope :for_target, -> (target_id, target_type) { where(target_id: target_id, target_type: target_type) }
+
+ # Example: Issues has at least one label within a project
+ # > Issue.where(project_id: 100) # or any scope on issues
+ # > .where(LabelLink.by_target_for_exists_query('Issue', Issue.arel_table[:id]).arel.exists)
+ scope :by_target_for_exists_query, -> (target_type, arel_join_column, label_ids = nil) do
+ relation = LabelLink
+ .where(target_type: target_type)
+ .where(arel_table['target_id'].eq(arel_join_column))
+
+ relation = relation.where(label_id: label_ids) if label_ids
+ relation
+ end
end
diff --git a/app/models/loose_foreign_keys/deleted_record.rb b/app/models/loose_foreign_keys/deleted_record.rb
index ca5a2800a03..c3b3e76f67b 100644
--- a/app/models/loose_foreign_keys/deleted_record.rb
+++ b/app/models/loose_foreign_keys/deleted_record.rb
@@ -1,5 +1,32 @@
# frozen_string_literal: true
class LooseForeignKeys::DeletedRecord < ApplicationRecord
- extend SuppressCompositePrimaryKeyWarning
+ self.primary_key = :id
+
+ scope :for_table, -> (table) { where(fully_qualified_table_name: table) }
+ scope :consume_order, -> { order(:partition, :consume_after, :id) }
+
+ enum status: { pending: 1, processed: 2 }, _prefix: :status
+
+ def self.load_batch_for_table(table, batch_size)
+ for_table(table)
+ .status_pending
+ .consume_order
+ .limit(batch_size)
+ .to_a
+ end
+
+ def self.mark_records_processed(all_records)
+ # Run a query for each partition to optimize the row lookup by primary key (partition, id)
+ update_count = 0
+
+ all_records.group_by(&:partition).each do |partition, records_within_partition|
+ update_count += status_pending
+ .where(partition: partition)
+ .where(id: records_within_partition.pluck(:id))
+ .update_all(status: :processed)
+ end
+
+ update_count
+ end
end
diff --git a/app/models/loose_foreign_keys/modification_tracker.rb b/app/models/loose_foreign_keys/modification_tracker.rb
new file mode 100644
index 00000000000..6eb04608cd9
--- /dev/null
+++ b/app/models/loose_foreign_keys/modification_tracker.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module LooseForeignKeys
+ class ModificationTracker
+ MAX_DELETES = 100_000
+ MAX_UPDATES = 50_000
+ MAX_RUNTIME = 3.minutes
+
+ delegate :monotonic_time, to: :'Gitlab::Metrics::System'
+
+ def initialize
+ @delete_count_by_table = Hash.new { |h, k| h[k] = 0 }
+ @update_count_by_table = Hash.new { |h, k| h[k] = 0 }
+ @start_time = monotonic_time
+ @deletes_counter = Gitlab::Metrics.counter(
+ :loose_foreign_key_deletions,
+ 'The number of loose foreign key deletions'
+ )
+ @updates_counter = Gitlab::Metrics.counter(
+ :loose_foreign_key_updates,
+ 'The number of loose foreign key updates'
+ )
+ end
+
+ def add_deletions(table, count)
+ @delete_count_by_table[table] += count
+ @deletes_counter.increment({ table: table }, count)
+ end
+
+ def add_updates(table, count)
+ @update_count_by_table[table] += count
+ @updates_counter.increment({ table: table }, count)
+ end
+
+ def over_limit?
+ @delete_count_by_table.values.sum >= MAX_DELETES ||
+ @update_count_by_table.values.sum >= MAX_UPDATES ||
+ monotonic_time - @start_time >= MAX_RUNTIME
+ end
+
+ def stats
+ {
+ over_limit: over_limit?,
+ delete_count_by_table: @delete_count_by_table,
+ update_count_by_table: @update_count_by_table,
+ delete_count: @delete_count_by_table.values.sum,
+ update_count: @update_count_by_table.values.sum
+ }
+ end
+ end
+end
diff --git a/app/models/member.rb b/app/models/member.rb
index 21fd4aebd7b..11f67a77ee2 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -13,6 +13,7 @@ class Member < ApplicationRecord
include FromUnion
include UpdateHighestRole
include RestrictedSignup
+ include Gitlab::Experiment::Dsl
AVATAR_SIZE = 40
ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10
@@ -22,8 +23,10 @@ class Member < ApplicationRecord
belongs_to :created_by, class_name: "User"
belongs_to :user
belongs_to :source, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
+ has_one :member_task
delegate :name, :username, :email, to: :user, prefix: true
+ delegate :tasks_to_be_done, to: :member_task, allow_nil: true
validates :expires_at, allow_blank: true, future_date: true
validates :user, presence: true, unless: :invite?
@@ -413,6 +416,14 @@ class Member < ApplicationRecord
def after_accept_invite
post_create_hook
+
+ if experiment(:invite_members_for_task).enabled?
+ run_after_commit_or_now do
+ if member_task
+ TasksToBeDone::CreateWorker.perform_async(member_task.id, created_by_id, [user_id.to_i])
+ end
+ end
+ end
end
def after_decline_invite
diff --git a/app/models/members/member_task.rb b/app/models/members/member_task.rb
new file mode 100644
index 00000000000..f093619ff36
--- /dev/null
+++ b/app/models/members/member_task.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+class MemberTask < ApplicationRecord
+ TASKS = {
+ code: 0,
+ ci: 1,
+ issues: 2
+ }.freeze
+
+ belongs_to :member
+ belongs_to :project
+
+ validates :member, :project, presence: true
+ validates :tasks, inclusion: { in: TASKS.values }
+ validate :tasks_uniqueness
+ validate :project_in_member_source
+
+ scope :for_members, -> (members) { joins(:member).where(member: members) }
+
+ def tasks_to_be_done
+ Array(self[:tasks]).map { |task| TASKS.key(task) }
+ end
+
+ def tasks_to_be_done=(tasks)
+ self[:tasks] = Array(tasks).map do |task|
+ TASKS[task.to_sym]
+ end.uniq
+ end
+
+ private
+
+ def tasks_uniqueness
+ errors.add(:tasks, 'are not unique') unless Array(tasks).length == Array(tasks).uniq.length
+ end
+
+ def project_in_member_source
+ if member.is_a?(GroupMember)
+ errors.add(:project, _('is not in the member group')) unless project.namespace == member.source
+ elsif member.is_a?(ProjectMember)
+ errors.add(:project, _('is not the member project')) unless project == member.source
+ end
+ end
+end
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index eec46b3493e..89b72508e84 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -94,7 +94,6 @@ class ProjectMember < Member
override :refresh_member_authorized_projects
def refresh_member_authorized_projects(blocking:)
- return super unless Feature.enabled?(:specialized_service_for_project_member_auth_refresh)
return unless user
# rubocop:disable CodeReuse/ServiceClass
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 15862fb2bfa..0cd8f12088c 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -268,7 +268,6 @@ class MergeRequest < ApplicationRecord
from_fork.where('source_project_id = ? OR target_project_id = ?', project.id, project.id)
end
scope :merged, -> { with_state(:merged) }
- scope :closed_and_merged, -> { with_states(:closed, :merged) }
scope :open_and_closed, -> { with_states(:opened, :closed) }
scope :drafts, -> { where(draft: true) }
scope :from_source_branches, ->(branches) { where(source_branch: branches) }
@@ -663,7 +662,7 @@ class MergeRequest < ApplicationRecord
# updates `merge_jid` with the MergeWorker#jid.
# This helps tracking enqueued and ongoing merge jobs.
def merge_async(user_id, params)
- jid = MergeWorker.perform_async(id, user_id, params.to_h)
+ jid = MergeWorker.with_status.perform_async(id, user_id, params.to_h)
update_column(:merge_jid, jid)
# merge_ongoing? depends on merge_jid
@@ -682,7 +681,7 @@ class MergeRequest < ApplicationRecord
# attribute is set *and* that the sidekiq job is still running. So a JID
# for a completed RebaseWorker is equivalent to a nil JID.
jid = Sidekiq::Worker.skipping_transaction_check do
- RebaseWorker.perform_async(id, user_id, skip_ci)
+ RebaseWorker.with_status.perform_async(id, user_id, skip_ci)
end
update_column(:rebase_jid, jid)
@@ -1317,6 +1316,10 @@ class MergeRequest < ApplicationRecord
end
def default_merge_commit_message(include_description: false)
+ if self.target_project.merge_commit_template.present? && !include_description
+ return ::Gitlab::MergeRequests::MergeCommitMessage.new(merge_request: self).message
+ end
+
closes_issues_references = visible_closing_issues_for.map do |issue|
issue.to_reference(target_project)
end
@@ -1409,7 +1412,15 @@ class MergeRequest < ApplicationRecord
def environments
return Environment.none unless actual_head_pipeline&.merge_request?
- actual_head_pipeline.environments
+ build_for_actual_head_pipeline = Ci::Build.latest.where(pipeline: actual_head_pipeline)
+
+ environments = build_for_actual_head_pipeline.joins(:metadata)
+ .where.not('ci_builds_metadata.expanded_environment_name' => nil)
+ .distinct('ci_builds_metadata.expanded_environment_name')
+ .limit(100)
+ .pluck(:expanded_environment_name)
+
+ Environment.where(project: project, name: environments)
end
def fetch_ref!
@@ -1907,6 +1918,10 @@ class MergeRequest < ApplicationRecord
true
end
+ def find_assignee(user)
+ merge_request_assignees.find_by(user_id: user.id)
+ end
+
def find_reviewer(user)
merge_request_reviewers.find_by(user_id: user.id)
end
@@ -1930,6 +1945,10 @@ class MergeRequest < ApplicationRecord
end
end
+ def attention_requested_enabled?
+ Feature.enabled?(:mr_attention_requests, project, default_enabled: :yaml)
+ end
+
private
def set_draft_status
diff --git a/app/models/merge_request_assignee.rb b/app/models/merge_request_assignee.rb
index 86bf950ae19..fd8e5860040 100644
--- a/app/models/merge_request_assignee.rb
+++ b/app/models/merge_request_assignee.rb
@@ -1,10 +1,16 @@
# frozen_string_literal: true
class MergeRequestAssignee < ApplicationRecord
+ include MergeRequestReviewerState
+
belongs_to :merge_request, touch: true
belongs_to :assignee, class_name: "User", foreign_key: :user_id, inverse_of: :merge_request_assignees
validates :assignee, uniqueness: { scope: :merge_request_id }
scope :in_projects, ->(project_ids) { joins(:merge_request).where(merge_requests: { target_project_id: project_ids }) }
+
+ def cache_key
+ [model_name.cache_key, id, state, assignee.cache_key]
+ end
end
diff --git a/app/models/merge_request_context_commit.rb b/app/models/merge_request_context_commit.rb
index 09824ed4468..ebbdecf8aa7 100644
--- a/app/models/merge_request_context_commit.rb
+++ b/app/models/merge_request_context_commit.rb
@@ -26,7 +26,7 @@ class MergeRequestContextCommit < ApplicationRecord
# create MergeRequestContextCommit by given commit sha and it's diff file record
def self.bulk_insert(rows, **args)
- Gitlab::Database.main.bulk_insert('merge_request_context_commits', rows, **args) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert('merge_request_context_commits', rows, **args) # rubocop:disable Gitlab/BulkInsert
end
def to_commit
diff --git a/app/models/merge_request_context_commit_diff_file.rb b/app/models/merge_request_context_commit_diff_file.rb
index b9efebe3af2..fdf57068928 100644
--- a/app/models/merge_request_context_commit_diff_file.rb
+++ b/app/models/merge_request_context_commit_diff_file.rb
@@ -14,7 +14,7 @@ class MergeRequestContextCommitDiffFile < ApplicationRecord
# create MergeRequestContextCommitDiffFile by given diff file record(s)
def self.bulk_insert(*args)
- Gitlab::Database.main.bulk_insert('merge_request_context_commit_diff_files', *args) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert('merge_request_context_commit_diff_files', *args) # rubocop:disable Gitlab/BulkInsert
end
def path
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index bd94c0ad30e..2516ff05bda 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -515,7 +515,7 @@ class MergeRequestDiff < ApplicationRecord
transaction do
MergeRequestDiffFile.where(merge_request_diff_id: id).delete_all
- Gitlab::Database.main.bulk_insert('merge_request_diff_files', rows) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert('merge_request_diff_files', rows) # rubocop:disable Gitlab/BulkInsert
save!
end
@@ -535,7 +535,7 @@ class MergeRequestDiff < ApplicationRecord
transaction do
MergeRequestDiffFile.where(merge_request_diff_id: id).delete_all
- Gitlab::Database.main.bulk_insert('merge_request_diff_files', rows) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert('merge_request_diff_files', rows) # rubocop:disable Gitlab/BulkInsert
update!(stored_externally: false)
end
@@ -595,7 +595,7 @@ class MergeRequestDiff < ApplicationRecord
rows = build_external_merge_request_diff_files(rows) if use_external_diff?
# Faster inserts
- Gitlab::Database.main.bulk_insert('merge_request_diff_files', rows) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert('merge_request_diff_files', rows) # rubocop:disable Gitlab/BulkInsert
end
def build_external_diff_tempfile(rows)
@@ -710,7 +710,7 @@ class MergeRequestDiff < ApplicationRecord
end
CommitCollection
- .new(merge_request.source_project, commits, merge_request.source_branch)
+ .new(merge_request.target_project, commits, merge_request.target_branch)
end
def save_diffs
diff --git a/app/models/merge_request_diff_commit.rb b/app/models/merge_request_diff_commit.rb
index d9a1784cdda..66f1e45fd49 100644
--- a/app/models/merge_request_diff_commit.rb
+++ b/app/models/merge_request_diff_commit.rb
@@ -6,6 +6,12 @@ class MergeRequestDiffCommit < ApplicationRecord
include BulkInsertSafe
include ShaAttribute
include CachedCommit
+ include IgnorableColumns
+ include FromUnion
+
+ ignore_column %i[author_name author_email committer_name committer_email],
+ remove_with: '14.6',
+ remove_after: '2021-11-22'
belongs_to :merge_request_diff
@@ -51,9 +57,14 @@ class MergeRequestDiffCommit < ApplicationRecord
committer =
users[[commit_hash[:committer_name], commit_hash[:committer_email]]]
+ # These fields are only used to determine the author/committer IDs, we
+ # don't store them in the DB.
+ commit_hash = commit_hash
+ .except(:author_name, :author_email, :committer_name, :committer_email)
+
commit_hash.merge(
- commit_author_id: author&.id,
- committer_id: committer&.id,
+ commit_author_id: author.id,
+ committer_id: committer.id,
merge_request_diff_id: merge_request_diff_id,
relative_order: index,
sha: Gitlab::Database::ShaAttribute.serialize(sha), # rubocop:disable Cop/ActiveRecordSerialize
@@ -63,7 +74,7 @@ class MergeRequestDiffCommit < ApplicationRecord
)
end
- Gitlab::Database.main.bulk_insert(self.table_name, rows) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(self.table_name, rows) # rubocop:disable Gitlab/BulkInsert
end
def self.prepare_commits_for_bulk_insert(commits)
@@ -104,18 +115,18 @@ class MergeRequestDiffCommit < ApplicationRecord
end
def author_name
- commit_author_id ? commit_author.name : super
+ commit_author&.name
end
def author_email
- commit_author_id ? commit_author.email : super
+ commit_author&.email
end
def committer_name
- committer_id ? committer.name : super
+ committer&.name
end
def committer_email
- committer_id ? committer.email : super
+ committer&.email
end
end
diff --git a/app/models/merge_request_reviewer.rb b/app/models/merge_request_reviewer.rb
index 4a1f31a7f39..4abf0fa09f0 100644
--- a/app/models/merge_request_reviewer.rb
+++ b/app/models/merge_request_reviewer.rb
@@ -1,15 +1,12 @@
# frozen_string_literal: true
class MergeRequestReviewer < ApplicationRecord
- enum state: {
- unreviewed: 0,
- reviewed: 1
- }
-
- validates :state,
- presence: true,
- inclusion: { in: MergeRequestReviewer.states.keys }
+ include MergeRequestReviewerState
belongs_to :merge_request
belongs_to :reviewer, class_name: 'User', foreign_key: :user_id, inverse_of: :merge_request_reviewers
+
+ def cache_key
+ [model_name.cache_key, id, state, reviewer.cache_key]
+ end
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 07f9bb99952..353a896b3fe 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -16,9 +16,11 @@ class Namespace < ApplicationRecord
include Namespaces::Traversal::Linear
include EachBatch
- ignore_column :delayed_project_removal, remove_with: '14.1', remove_after: '2021-05-22'
+ # Temporary column used for back-filling project namespaces.
+ # Remove it once the back-filling of all project namespaces is done.
+ ignore_column :tmp_project_id, remove_with: '14.7', remove_after: '2022-01-22'
- # Tells ActiveRecord not to store the full class name, in order to space some space
+ # Tells ActiveRecord not to store the full class name, in order to save some space
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69794
self.store_full_sti_class = false
self.store_full_class_name = false
@@ -54,7 +56,7 @@ class Namespace < ApplicationRecord
belongs_to :owner, class_name: "User"
belongs_to :parent, class_name: "Namespace"
- has_many :children, class_name: "Namespace", foreign_key: :parent_id
+ has_many :children, -> { where(type: Group.sti_name) }, class_name: "Namespace", foreign_key: :parent_id
has_many :custom_emoji, inverse_of: :namespace
has_one :chat_team, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :root_storage_statistics, class_name: 'Namespace::RootStorageStatistics'
@@ -95,9 +97,11 @@ class Namespace < ApplicationRecord
validates :max_artifacts_size, numericality: { only_integer: true, greater_than: 0, allow_nil: true }
validate :validate_parent_type, if: -> { Feature.enabled?(:validate_namespace_parent_type, default_enabled: :yaml) }
- validate :nesting_level_allowed
- validate :changing_shared_runners_enabled_is_allowed
- validate :changing_allow_descendants_override_disabled_shared_runners_is_allowed
+
+ # ProjectNamespaces excluded as they are not meant to appear in the group hierarchy at the moment.
+ validate :nesting_level_allowed, unless: -> { project_namespace? }
+ validate :changing_shared_runners_enabled_is_allowed, unless: -> { project_namespace? }
+ validate :changing_allow_descendants_override_disabled_shared_runners_is_allowed, unless: -> { project_namespace? }
delegate :name, to: :owner, allow_nil: true, prefix: true
delegate :avatar_url, to: :owner, allow_nil: true
@@ -123,7 +127,7 @@ class Namespace < ApplicationRecord
scope :user_namespaces, -> { where(type: [nil, Namespaces::UserNamespace.sti_name]) }
# TODO: this can be simplified with `type != 'Project'` when working on issue
# https://gitlab.com/gitlab-org/gitlab/-/issues/341070
- scope :without_project_namespaces, -> { where("type IS DISTINCT FROM ?", Namespaces::ProjectNamespace.sti_name) }
+ scope :without_project_namespaces, -> { where(Namespace.arel_table[:type].is_distinct_from(Namespaces::ProjectNamespace.sti_name)) }
scope :sort_by_type, -> { order(Gitlab::Database.nulls_first_order(:type)) }
scope :include_route, -> { includes(:route) }
scope :by_parent, -> (parent) { where(parent_id: parent) }
@@ -140,6 +144,7 @@ class Namespace < ApplicationRecord
'COALESCE(SUM(ps.snippets_size), 0) AS snippets_size',
'COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size',
'COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size',
+ 'COALESCE(SUM(ps.pipeline_artifacts_size), 0) AS pipeline_artifacts_size',
'COALESCE(SUM(ps.packages_size), 0) AS packages_size',
'COALESCE(SUM(ps.uploads_size), 0) AS uploads_size'
)
@@ -189,9 +194,9 @@ class Namespace < ApplicationRecord
# Returns an ActiveRecord::Relation.
def search(query, include_parents: false)
if include_parents
- where(id: Route.for_routable_type(Namespace.name).fuzzy_search(query, [Route.arel_table[:path], Route.arel_table[:name]]).select(:source_id))
+ without_project_namespaces.where(id: Route.for_routable_type(Namespace.name).fuzzy_search(query, [Route.arel_table[:path], Route.arel_table[:name]]).select(:source_id))
else
- fuzzy_search(query, [:path, :name])
+ without_project_namespaces.fuzzy_search(query, [:path, :name])
end
end
@@ -494,6 +499,10 @@ class Namespace < ApplicationRecord
Feature.enabled?(:block_issue_repositioning, self, type: :ops, default_enabled: :yaml)
end
+ def project_namespace_creation_enabled?
+ Feature.enabled?(:create_project_namespace_on_project_create, self, default_enabled: :yaml)
+ end
+
private
def expire_child_caches
@@ -535,21 +544,23 @@ class Namespace < ApplicationRecord
# Until we compare the inconsistency rates of the new specialized worker and
# the old approach, we still run AuthorizedProjectsWorker
# but with some delay and lower urgency as a safety net.
- Group
- .joins(project_group_links: :project)
- .where(projects: { namespace_id: id })
- .distinct
- .find_each do |group|
- group.refresh_members_authorized_projects(
- blocking: false,
- priority: UserProjectAccessChangedService::LOW_PRIORITY
- )
- end
+ enqueue_jobs_for_groups_requiring_authorizations_refresh(priority: UserProjectAccessChangedService::LOW_PRIORITY)
else
- Group
- .joins(project_group_links: :project)
- .where(projects: { namespace_id: id })
- .find_each(&:refresh_members_authorized_projects)
+ enqueue_jobs_for_groups_requiring_authorizations_refresh(priority: UserProjectAccessChangedService::HIGH_PRIORITY)
+ end
+ end
+
+ def enqueue_jobs_for_groups_requiring_authorizations_refresh(priority:)
+ groups_requiring_authorizations_refresh = Group
+ .joins(project_group_links: :project)
+ .where(projects: { namespace_id: id })
+ .distinct
+
+ groups_requiring_authorizations_refresh.find_each do |group|
+ group.refresh_members_authorized_projects(
+ blocking: false,
+ priority: priority
+ )
end
end
@@ -573,7 +584,7 @@ class Namespace < ApplicationRecord
end
if user_namespace?
- errors.add(:parent_id, _('cannot not be used for user namespace'))
+ errors.add(:parent_id, _('cannot be used for user namespace'))
elsif group_namespace?
errors.add(:parent_id, _('user namespace cannot be the parent of another namespace')) if parent.user_namespace?
end
diff --git a/app/models/namespaces/project_namespace.rb b/app/models/namespaces/project_namespace.rb
index d1806c1c088..22ec550dee2 100644
--- a/app/models/namespaces/project_namespace.rb
+++ b/app/models/namespaces/project_namespace.rb
@@ -4,8 +4,6 @@ module Namespaces
class ProjectNamespace < Namespace
has_one :project, foreign_key: :project_namespace_id, inverse_of: :project_namespace
- validates :project, presence: true
-
def self.sti_name
'Project'
end
diff --git a/app/models/namespaces/traversal/linear.rb b/app/models/namespaces/traversal/linear.rb
index d7130322ed1..1736fe82ca5 100644
--- a/app/models/namespaces/traversal/linear.rb
+++ b/app/models/namespaces/traversal/linear.rb
@@ -161,7 +161,7 @@ module Namespaces
def lineage(top: nil, bottom: nil, hierarchy_order: nil)
raise UnboundedSearch, 'Must bound search by either top or bottom' unless top || bottom
- skope = self.class.without_sti_condition
+ skope = self.class
if top
skope = skope.where("traversal_ids @> ('{?}')", top.id)
@@ -181,7 +181,6 @@ module Namespaces
# standard SELECT to avoid mismatched attribute errors when trying to
# chain future ActiveRelation commands, and retain the ordering.
skope = self.class
- .without_sti_condition
.from(skope, self.class.table_name)
.select(skope.arel_table[Arel.star])
.order(depth: hierarchy_order)
diff --git a/app/models/namespaces/traversal/linear_scopes.rb b/app/models/namespaces/traversal/linear_scopes.rb
index 2da0e48c2da..f5c44171c42 100644
--- a/app/models/namespaces/traversal/linear_scopes.rb
+++ b/app/models/namespaces/traversal/linear_scopes.rb
@@ -15,12 +15,18 @@ module Namespaces
select('namespaces.traversal_ids[array_length(namespaces.traversal_ids, 1)] AS id')
end
+ def roots
+ return super unless use_traversal_ids_roots?
+
+ root_ids = all.select("#{quoted_table_name}.traversal_ids[1]").distinct
+ unscoped.where(id: root_ids)
+ end
+
def self_and_ancestors(include_self: true, hierarchy_order: nil)
return super unless use_traversal_ids_for_ancestor_scopes?
records = unscoped
- .without_sti_condition
- .where(id: without_sti_condition.select('unnest(traversal_ids)'))
+ .where(id: select('unnest(traversal_ids)'))
.order_by_depth(hierarchy_order)
.normal_select
@@ -40,24 +46,24 @@ module Namespaces
def self_and_descendants(include_self: true)
return super unless use_traversal_ids?
- records = self_and_descendants_with_duplicates(include_self: include_self)
-
- distinct = records.select('DISTINCT on(namespaces.id) namespaces.*')
-
- distinct.normal_select
+ if Feature.enabled?(:traversal_ids_btree, default_enabled: :yaml)
+ self_and_descendants_with_comparison_operators(include_self: include_self)
+ else
+ records = self_and_descendants_with_duplicates_with_array_operator(include_self: include_self)
+ distinct = records.select('DISTINCT on(namespaces.id) namespaces.*')
+ distinct.normal_select
+ end
end
def self_and_descendant_ids(include_self: true)
return super unless use_traversal_ids?
- self_and_descendants_with_duplicates(include_self: include_self)
- .select('DISTINCT namespaces.id')
- end
-
- # Make sure we drop the STI `type = 'Group'` condition for better performance.
- # Logically equivalent so long as hierarchies remain homogeneous.
- def without_sti_condition
- unscope(where: :type)
+ if Feature.enabled?(:traversal_ids_btree, default_enabled: :yaml)
+ self_and_descendants_with_comparison_operators(include_self: include_self).as_ids
+ else
+ self_and_descendants_with_duplicates_with_array_operator(include_self: include_self)
+ .select('DISTINCT namespaces.id')
+ end
end
def order_by_depth(hierarchy_order)
@@ -75,7 +81,7 @@ module Namespaces
# When we have queries that break this SELECT * format we can run in to errors.
# For example `SELECT DISTINCT on(...)` will fail when we chain a `.count` c
def normal_select
- unscoped.without_sti_condition.from(all, :namespaces)
+ unscoped.from(all, :namespaces)
end
private
@@ -84,16 +90,52 @@ module Namespaces
Feature.enabled?(:use_traversal_ids, default_enabled: :yaml)
end
+ def use_traversal_ids_roots?
+ Feature.enabled?(:use_traversal_ids_roots, default_enabled: :yaml) &&
+ use_traversal_ids?
+ end
+
def use_traversal_ids_for_ancestor_scopes?
Feature.enabled?(:use_traversal_ids_for_ancestor_scopes, default_enabled: :yaml) &&
use_traversal_ids?
end
- def self_and_descendants_with_duplicates(include_self: true)
+ def self_and_descendants_with_comparison_operators(include_self: true)
+ base = all.select(
+ :traversal_ids,
+ 'LEAD (namespaces.traversal_ids, 1) OVER (ORDER BY namespaces.traversal_ids ASC) next_traversal_ids'
+ )
+ cte = Gitlab::SQL::CTE.new(:base_cte, base)
+
+ namespaces = Arel::Table.new(:namespaces)
+ records = unscoped
+ .with(cte.to_arel)
+ .from([cte.table, namespaces])
+
+ # Bound the search space to ourselves (optional) and descendants.
+ #
+ # WHERE (base_cte.next_traversal_ids IS NULL OR base_cte.next_traversal_ids > namespaces.traversal_ids)
+ # AND next_traversal_ids_sibling(base_cte.traversal_ids) > namespaces.traversal_ids
+ records = records
+ .where(cte.table[:next_traversal_ids].eq(nil).or(cte.table[:next_traversal_ids].gt(namespaces[:traversal_ids])))
+ .where(next_sibling_func(cte.table[:traversal_ids]).gt(namespaces[:traversal_ids]))
+
+ # AND base_cte.traversal_ids <= namespaces.traversal_ids
+ if include_self
+ records.where(cte.table[:traversal_ids].lteq(namespaces[:traversal_ids]))
+ else
+ records.where(cte.table[:traversal_ids].lt(namespaces[:traversal_ids]))
+ end
+ end
+
+ def next_sibling_func(*args)
+ Arel::Nodes::NamedFunction.new('next_traversal_ids_sibling', args)
+ end
+
+ def self_and_descendants_with_duplicates_with_array_operator(include_self: true)
base_ids = select(:id)
records = unscoped
- .without_sti_condition
.from("namespaces, (#{base_ids.to_sql}) base")
.where('namespaces.traversal_ids @> ARRAY[base.id]')
diff --git a/app/models/namespaces/traversal/recursive_scopes.rb b/app/models/namespaces/traversal/recursive_scopes.rb
index 6659cefe095..925d9b8bb0c 100644
--- a/app/models/namespaces/traversal/recursive_scopes.rb
+++ b/app/models/namespaces/traversal/recursive_scopes.rb
@@ -10,6 +10,13 @@ module Namespaces
select('id')
end
+ def roots
+ Gitlab::ObjectHierarchy
+ .new(all)
+ .base_and_ancestors
+ .where(namespaces: { parent_id: nil })
+ end
+
def self_and_ancestors(include_self: true, hierarchy_order: nil)
records = Gitlab::ObjectHierarchy.new(all).base_and_ancestors(hierarchy_order: hierarchy_order)
diff --git a/app/models/namespaces/user_namespace.rb b/app/models/namespaces/user_namespace.rb
index 22b7a0a3b2b..d4d7d352e71 100644
--- a/app/models/namespaces/user_namespace.rb
+++ b/app/models/namespaces/user_namespace.rb
@@ -3,6 +3,26 @@
# TODO: currently not created/mapped in the database, will be done in another issue
# https://gitlab.com/gitlab-org/gitlab/-/issues/341070
module Namespaces
+ ####################################################################
+ # PLEASE DO NOT OVERRIDE METHODS IN THIS CLASS!
+ #
+ # This class is a placeholder for STI. But we also want to ensure
+ # tests using `:namespace` factory are still testing the same functionality.
+ #
+ # Many legacy tests use `:namespace` which has a slight semantic
+ # mismatch as it always has been a User (personal) namespace.
+ #
+ # If you need to make a change here, please ping the
+ # Manage/Workspaces group so we can ensure that the
+ # changes do not break existing functionality.
+ #
+ # As Namespaces evolve we may be able to relax this restriction
+ # but for now, please check in with us <3
+ #
+ # For details, see the discussion in
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74152
+ ####################################################################
+
class UserNamespace < Namespace
def self.sti_name
'User'
diff --git a/app/models/note.rb b/app/models/note.rb
index 37473518892..cb285028203 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -114,6 +114,7 @@ class Note < ApplicationRecord
scope :fresh, -> { order_created_asc.with_order_id_asc }
scope :updated_after, ->(time) { where('updated_at > ?', time) }
scope :with_updated_at, ->(time) { where(updated_at: time) }
+ scope :with_discussion_ids, ->(discussion_ids) { where(discussion_id: discussion_ids) }
scope :with_suggestions, -> { joins(:suggestions) }
scope :inc_author, -> { includes(:author) }
scope :with_api_entity_associations, -> { preload(:note_diff_file, :author) }
diff --git a/app/models/packages/npm.rb b/app/models/packages/npm.rb
index e49199d911c..9221187d92a 100644
--- a/app/models/packages/npm.rb
+++ b/app/models/packages/npm.rb
@@ -9,5 +9,9 @@ module Packages
package_name.match(Gitlab::Regex.npm_package_name_regex)&.captures&.first
end
+
+ def self.table_name_prefix
+ 'packages_npm_'
+ end
end
end
diff --git a/app/models/packages/npm/metadatum.rb b/app/models/packages/npm/metadatum.rb
new file mode 100644
index 00000000000..7388c4bdbd2
--- /dev/null
+++ b/app/models/packages/npm/metadatum.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class Packages::Npm::Metadatum < ApplicationRecord
+ belongs_to :package, -> { where(package_type: :npm) }, inverse_of: :npm_metadatum
+
+ validates :package, presence: true
+ # From https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#abbreviated-version-object
+ validates :package_json, json_schema: { filename: "npm_package_json" }
+ validate :ensure_npm_package_type
+ validate :ensure_package_json_size
+
+ private
+
+ def ensure_npm_package_type
+ return if package&.npm?
+
+ errors.add(:base, _('Package type must be NPM'))
+ end
+
+ def ensure_package_json_size
+ return if package_json.to_s.size < 20000
+
+ errors.add(:package_json, _('structure is too large'))
+ end
+end
diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb
index 34eae6ab5dc..962a1057a22 100644
--- a/app/models/packages/package.rb
+++ b/app/models/packages/package.rb
@@ -39,8 +39,9 @@ class Packages::Package < ApplicationRecord
has_one :nuget_metadatum, inverse_of: :package, class_name: 'Packages::Nuget::Metadatum'
has_one :composer_metadatum, inverse_of: :package, class_name: 'Packages::Composer::Metadatum'
has_one :rubygems_metadatum, inverse_of: :package, class_name: 'Packages::Rubygems::Metadatum'
+ has_one :npm_metadatum, inverse_of: :package, class_name: 'Packages::Npm::Metadatum'
has_many :build_infos, inverse_of: :package
- has_many :pipelines, through: :build_infos
+ has_many :pipelines, through: :build_infos, disable_joins: true
has_one :debian_publication, inverse_of: :package, class_name: 'Packages::Debian::Publication'
has_one :debian_distribution, through: :debian_publication, source: :distribution, inverse_of: :packages, class_name: 'Packages::Debian::ProjectDistribution'
@@ -102,7 +103,6 @@ class Packages::Package < ApplicationRecord
scope :with_status, ->(status) { where(status: status) }
scope :displayable, -> { with_status(DISPLAYABLE_STATUSES) }
scope :installable, -> { with_status(INSTALLABLE_STATUSES) }
- scope :including_build_info, -> { includes(pipelines: :user) }
scope :including_project_route, -> { includes(project: { namespace: :route }) }
scope :including_tags, -> { includes(:tags) }
scope :including_dependency_links, -> { includes(dependency_links: :dependency) }
@@ -126,11 +126,13 @@ class Packages::Package < ApplicationRecord
.where(Packages::Composer::Metadatum.table_name => { target_sha: target })
end
scope :preload_composer, -> { preload(:composer_metadatum) }
+ scope :preload_npm_metadatum, -> { preload(:npm_metadatum) }
scope :without_nuget_temporary_name, -> { where.not(name: Packages::Nuget::TEMPORARY_PACKAGE_NAME) }
scope :has_version, -> { where.not(version: nil) }
scope :preload_files, -> { preload(:package_files) }
+ scope :preload_pipelines, -> { preload(pipelines: :user) }
scope :last_of_each_version, -> { where(id: all.select('MAX(id) AS id').group(:version)) }
scope :limit_recent, ->(limit) { order_created_desc.limit(limit) }
scope :select_distinct_name, -> { select(:name).distinct }
@@ -245,7 +247,7 @@ class Packages::Package < ApplicationRecord
def versions
project.packages
- .including_build_info
+ .preload_pipelines
.including_tags
.with_name(name)
.where.not(version: version)
diff --git a/app/models/packages/package_file.rb b/app/models/packages/package_file.rb
index 14701b8a800..87c9f56cc41 100644
--- a/app/models/packages/package_file.rb
+++ b/app/models/packages/package_file.rb
@@ -15,7 +15,7 @@ class Packages::PackageFile < ApplicationRecord
has_one :conan_file_metadatum, inverse_of: :package_file, class_name: 'Packages::Conan::FileMetadatum'
has_many :package_file_build_infos, inverse_of: :package_file, class_name: 'Packages::PackageFileBuildInfo'
- has_many :pipelines, through: :package_file_build_infos
+ has_many :pipelines, through: :package_file_build_infos, disable_joins: true
has_one :debian_file_metadatum, inverse_of: :package_file, class_name: 'Packages::Debian::FileMetadatum'
has_one :helm_file_metadatum, inverse_of: :package_file, class_name: 'Packages::Helm::FileMetadatum'
@@ -38,6 +38,7 @@ class Packages::PackageFile < ApplicationRecord
scope :with_format, ->(format) { where(::Packages::PackageFile.arel_table[:file_name].matches("%.#{format}")) }
scope :preload_package, -> { preload(:package) }
+ scope :preload_pipelines, -> { preload(pipelines: :user) }
scope :preload_conan_file_metadata, -> { preload(:conan_file_metadatum) }
scope :preload_debian_file_metadata, -> { preload(:debian_file_metadatum) }
scope :preload_helm_file_metadata, -> { preload(:helm_file_metadatum) }
diff --git a/app/models/preloaders/group_policy_preloader.rb b/app/models/preloaders/group_policy_preloader.rb
new file mode 100644
index 00000000000..95d6e0b5c1f
--- /dev/null
+++ b/app/models/preloaders/group_policy_preloader.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Preloaders
+ class GroupPolicyPreloader
+ def initialize(groups, current_user)
+ @groups = groups
+ @current_user = current_user
+ end
+
+ def execute
+ Preloaders::UserMaxAccessLevelInGroupsPreloader.new(@groups, @current_user).execute
+ Preloaders::GroupRootAncestorPreloader.new(@groups, root_ancestor_preloads).execute
+ end
+
+ private
+
+ def root_ancestor_preloads
+ []
+ end
+ end
+end
+
+Preloaders::GroupPolicyPreloader.prepend_mod_with('Preloaders::GroupPolicyPreloader')
diff --git a/app/models/preloaders/group_root_ancestor_preloader.rb b/app/models/preloaders/group_root_ancestor_preloader.rb
new file mode 100644
index 00000000000..3ca713d9635
--- /dev/null
+++ b/app/models/preloaders/group_root_ancestor_preloader.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Preloaders
+ class GroupRootAncestorPreloader
+ def initialize(groups, root_ancestor_preloads = [])
+ @groups = groups
+ @root_ancestor_preloads = root_ancestor_preloads
+ end
+
+ def execute
+ return unless ::Feature.enabled?(:use_traversal_ids, default_enabled: :yaml)
+
+ # type == 'Group' condition located on subquery to prevent a filter in the query
+ root_query = Namespace.joins("INNER JOIN (#{join_sql}) as root_query ON root_query.root_id = namespaces.id")
+ .select('namespaces.*, root_query.id as source_id')
+
+ root_query = root_query.preload(*@root_ancestor_preloads) if @root_ancestor_preloads.any?
+
+ root_ancestors_by_id = root_query.group_by(&:source_id)
+
+ @groups.each do |group|
+ group.root_ancestor = root_ancestors_by_id[group.id].first
+ end
+ end
+
+ private
+
+ def join_sql
+ Group.select('id, traversal_ids[1] as root_id').where(id: @groups.map(&:id)).to_sql
+ end
+ end
+end
diff --git a/app/models/preloaders/user_max_access_level_in_groups_preloader.rb b/app/models/preloaders/user_max_access_level_in_groups_preloader.rb
index 14f1d271572..bdd76d39ec1 100644
--- a/app/models/preloaders/user_max_access_level_in_groups_preloader.rb
+++ b/app/models/preloaders/user_max_access_level_in_groups_preloader.rb
@@ -3,7 +3,6 @@
module Preloaders
# This class preloads the max access level (role) for the user within the given groups and
# stores the values in requests store.
- # Will only be able to preload max access level for groups where the user is a direct member
class UserMaxAccessLevelInGroupsPreloader
include BulkMemberAccessLoad
@@ -13,8 +12,17 @@ module Preloaders
end
def execute
+ if ::Feature.enabled?(:use_traversal_ids, default_enabled: :yaml)
+ preload_with_traversal_ids
+ else
+ preload_direct_memberships
+ end
+ end
+
+ private
+
+ def preload_direct_memberships
group_memberships = GroupMember.active_without_invites_and_requests
- .non_minimal_access
.where(user: @user, source_id: @groups)
.group(:source_id)
.maximum(:access_level)
@@ -23,5 +31,22 @@ module Preloaders
merge_value_to_request_store(User, @user.id, group_id, max_access_level)
end
end
+
+ def preload_with_traversal_ids
+ max_access_levels = GroupMember.active_without_invites_and_requests
+ .where(user: @user)
+ .joins("INNER JOIN (#{traversal_join_sql}) as hierarchy ON members.source_id = hierarchy.traversal_id")
+ .group('hierarchy.id')
+ .maximum(:access_level)
+
+ @groups.each do |group|
+ max_access_level = max_access_levels[group.id] || Gitlab::Access::NO_ACCESS
+ merge_value_to_request_store(User, @user.id, group.id, max_access_level)
+ end
+ end
+
+ def traversal_join_sql
+ Namespace.select('id, unnest(traversal_ids) as traversal_id').where(id: @groups.map(&:id)).to_sql
+ end
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 2ceba10e86e..2288850553c 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -19,7 +19,6 @@ class Project < ApplicationRecord
include Presentable
include HasRepository
include HasWiki
- include HasIntegrations
include CanMoveRepositoryStorage
include Routable
include GroupDescendant
@@ -98,7 +97,7 @@ class Project < ApplicationRecord
before_validation :mark_remote_mirrors_for_removal, if: -> { RemoteMirror.table_exists? }
before_save :ensure_runners_token
- before_save :ensure_project_namespace_in_sync
+ before_validation :ensure_project_namespace_in_sync
after_save :update_project_statistics, if: :saved_change_to_namespace_id?
@@ -147,7 +146,7 @@ class Project < ApplicationRecord
belongs_to :namespace
# Sync deletion via DB Trigger to ensure we do not have
# a project without a project_namespace (or vice-versa)
- belongs_to :project_namespace, autosave: true, class_name: 'Namespaces::ProjectNamespace', foreign_key: 'project_namespace_id', inverse_of: :project
+ belongs_to :project_namespace, autosave: true, class_name: 'Namespaces::ProjectNamespace', foreign_key: 'project_namespace_id'
alias_method :parent, :namespace
alias_attribute :parent_id, :namespace_id
@@ -189,6 +188,7 @@ class Project < ApplicationRecord
has_one :prometheus_integration, class_name: 'Integrations::Prometheus', inverse_of: :project
has_one :pushover_integration, class_name: 'Integrations::Pushover'
has_one :redmine_integration, class_name: 'Integrations::Redmine'
+ has_one :shimo_integration, class_name: 'Integrations::Shimo'
has_one :slack_integration, class_name: 'Integrations::Slack'
has_one :slack_slash_commands_integration, class_name: 'Integrations::SlackSlashCommands'
has_one :teamcity_integration, class_name: 'Integrations::Teamcity'
@@ -451,6 +451,7 @@ class Project < ApplicationRecord
:allow_merge_on_skipped_pipeline=, :has_confluence?,
to: :project_setting
delegate :active?, to: :prometheus_integration, allow_nil: true, prefix: true
+ delegate :merge_commit_template, :merge_commit_template=, to: :project_setting, allow_nil: true
delegate :log_jira_dvcs_integration_usage, :jira_dvcs_server_last_sync_at, :jira_dvcs_cloud_last_sync_at, to: :feature_usage
@@ -475,6 +476,7 @@ class Project < ApplicationRecord
validates :project_feature, presence: true
validates :namespace, presence: true
+ validates :project_namespace, presence: true, if: -> { self.namespace && self.root_namespace.project_namespace_creation_enabled? }
validates :name, uniqueness: { scope: :namespace_id }
validates :import_url, public_url: { schemes: ->(project) { project.persisted? ? VALID_MIRROR_PROTOCOLS : VALID_IMPORT_PROTOCOLS },
ports: ->(project) { project.persisted? ? VALID_MIRROR_PORTS : VALID_IMPORT_PORTS },
@@ -492,6 +494,7 @@ class Project < ApplicationRecord
validates :variables, nested_attributes_duplicates: { scope: :environment_scope }
validates :bfg_object_map, file_size: { maximum: :max_attachment_size }
validates :max_artifacts_size, numericality: { only_integer: true, greater_than: 0, allow_nil: true }
+ validates :suggestion_commit_message, length: { maximum: 255 }
# Scopes
scope :pending_delete, -> { where(pending_delete: true) }
@@ -857,6 +860,18 @@ class Project < ApplicationRecord
rescue ActionController::RoutingError, URI::InvalidURIError
nil
end
+
+ def without_integration(integration)
+ integrations = Integration
+ .select('1')
+ .where("#{Integration.table_name}.project_id = projects.id")
+ .where(type: integration.type)
+
+ Project
+ .where('NOT EXISTS (?)', integrations)
+ .where(pending_delete: false)
+ .where(archived: false)
+ end
end
def initialize(attributes = nil)
@@ -1453,7 +1468,7 @@ class Project < ApplicationRecord
end
def disabled_integrations
- [:zentao]
+ [:shimo]
end
def find_or_initialize_integration(name)
@@ -1777,10 +1792,12 @@ class Project < ApplicationRecord
def all_runners
Ci::Runner.from_union([runners, group_runners, shared_runners])
+ .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/339937')
end
def all_available_runners
Ci::Runner.from_union([runners, group_runners, available_shared_runners])
+ .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/339937')
end
# Once issue 339937 is fixed, please search for all mentioned of
@@ -2051,14 +2068,16 @@ class Project < ApplicationRecord
end
def predefined_variables
- Gitlab::Ci::Variables::Collection.new
- .concat(predefined_ci_server_variables)
- .concat(predefined_project_variables)
- .concat(pages_variables)
- .concat(container_registry_variables)
- .concat(dependency_proxy_variables)
- .concat(auto_devops_variables)
- .concat(api_variables)
+ strong_memoize(:predefined_variables) do
+ Gitlab::Ci::Variables::Collection.new
+ .concat(predefined_ci_server_variables)
+ .concat(predefined_project_variables)
+ .concat(pages_variables)
+ .concat(container_registry_variables)
+ .concat(dependency_proxy_variables)
+ .concat(auto_devops_variables)
+ .concat(api_variables)
+ end
end
def predefined_project_variables
@@ -2579,18 +2598,21 @@ class Project < ApplicationRecord
config = Gitlab.config.incoming_email
wildcard = Gitlab::IncomingEmail::WILDCARD_PLACEHOLDER
- config.address&.gsub(wildcard, "#{full_path_slug}-#{id}-issue-")
+ config.address&.gsub(wildcard, "#{full_path_slug}-#{default_service_desk_suffix}")
end
def service_desk_custom_address
return unless Gitlab::ServiceDeskEmail.enabled?
- key = service_desk_setting&.project_key
- return unless key.present?
+ key = service_desk_setting&.project_key || default_service_desk_suffix
Gitlab::ServiceDeskEmail.address_for_key("#{full_path_slug}-#{key}")
end
+ def default_service_desk_suffix
+ "#{id}-issue-"
+ end
+
def root_namespace
if namespace.has_parent?
namespace.root_ancestor
@@ -2911,12 +2933,28 @@ class Project < ApplicationRecord
end
def ensure_project_namespace_in_sync
- if changes.keys & [:name, :path, :namespace_id, :visibility_level] && project_namespace.present?
- project_namespace.name = name
- project_namespace.path = path
- project_namespace.parent = namespace
- project_namespace.visibility_level = visibility_level
- end
+ # create project_namespace when project is created if create_project_namespace_on_project_create FF is enabled
+ build_project_namespace if project_namespace_creation_enabled?
+
+ # regardless of create_project_namespace_on_project_create FF we need
+ # to keep project and project namespace in sync if there is one
+ sync_attributes(project_namespace) if sync_project_namespace?
+ end
+
+ def project_namespace_creation_enabled?
+ new_record? && !project_namespace && self.namespace && self.root_namespace.project_namespace_creation_enabled?
+ end
+
+ def sync_project_namespace?
+ (changes.keys & %w(name path namespace_id namespace visibility_level shared_runners_enabled)).any? && project_namespace.present?
+ end
+
+ def sync_attributes(project_namespace)
+ project_namespace.name = name
+ project_namespace.path = path
+ project_namespace.parent = namespace
+ project_namespace.shared_runners_enabled = shared_runners_enabled
+ project_namespace.visibility_level = visibility_level
end
end
diff --git a/app/models/project_authorization.rb b/app/models/project_authorization.rb
index 64e768007ee..fed19a37a16 100644
--- a/app/models/project_authorization.rb
+++ b/app/models/project_authorization.rb
@@ -24,8 +24,9 @@ class ProjectAuthorization < ApplicationRecord
end
connection.execute <<-EOF.strip_heredoc
- INSERT INTO project_authorizations (user_id, project_id, access_level)
- VALUES #{tuples.map { |tuple| "(#{tuple.join(', ')})" }.join(', ')}
+ INSERT INTO project_authorizations (user_id, project_id, access_level)
+ VALUES #{tuples.map { |tuple| "(#{tuple.join(', ')})" }.join(', ')}
+ ON CONFLICT DO NOTHING
EOF
end
end
diff --git a/app/models/project_setting.rb b/app/models/project_setting.rb
index 24d892290a6..6c8d2226bc9 100644
--- a/app/models/project_setting.rb
+++ b/app/models/project_setting.rb
@@ -12,6 +12,8 @@ class ProjectSetting < ApplicationRecord
self.primary_key = :project_id
+ validates :merge_commit_template, length: { maximum: 500 }
+
def squash_enabled_by_default?
%w[always default_on].include?(squash_option)
end
diff --git a/app/models/project_team.rb b/app/models/project_team.rb
index 774d81156b7..94904e9792f 100644
--- a/app/models/project_team.rb
+++ b/app/models/project_team.rb
@@ -41,13 +41,15 @@ class ProjectTeam
member
end
- def add_users(users, access_level, current_user: nil, expires_at: nil)
+ def add_users(users, access_level, current_user: nil, expires_at: nil, tasks_to_be_done: [], tasks_project_id: nil)
Members::Projects::BulkCreatorService.add_users( # rubocop:disable CodeReuse/ServiceClass
project,
users,
access_level,
current_user: current_user,
- expires_at: expires_at
+ expires_at: expires_at,
+ tasks_to_be_done: tasks_to_be_done,
+ tasks_project_id: tasks_project_id
)
end
diff --git a/app/models/projects/topic.rb b/app/models/projects/topic.rb
index f3352ecc5ee..8d6f8c3a9ca 100644
--- a/app/models/projects/topic.rb
+++ b/app/models/projects/topic.rb
@@ -28,3 +28,5 @@ module Projects
end
end
end
+
+::Projects::Topic.prepend_mod_with('Projects::Topic')
diff --git a/app/models/push_event_payload.rb b/app/models/push_event_payload.rb
index 441b94e1855..8358be35470 100644
--- a/app/models/push_event_payload.rb
+++ b/app/models/push_event_payload.rb
@@ -2,9 +2,6 @@
class PushEventPayload < ApplicationRecord
extend SuppressCompositePrimaryKeyWarning
- include IgnorableColumns
-
- ignore_columns :event_id_convert_to_bigint, remove_with: '14.4', remove_after: '2021-10-22'
include ShaAttribute
diff --git a/app/models/release.rb b/app/models/release.rb
index eac6346cc60..0fda6940249 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -34,6 +34,7 @@ class Release < ApplicationRecord
project: [:project_feature, :route, { namespace: :route }])
}
scope :with_milestones, -> { joins(:milestone_releases) }
+ scope :with_group_milestones, -> { joins(:milestones).where.not(milestones: { group_id: nil }) }
scope :recent, -> { sorted.limit(MAX_NUMBER_TO_DISPLAY) }
scope :without_evidence, -> { left_joins(:evidences).where(::Releases::Evidence.arel_table[:id].eq(nil)) }
scope :released_within_2hrs, -> { where(released_at: Time.zone.now - 1.hour..Time.zone.now + 1.hour) }
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 119d874a6e1..47482f04bca 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -731,10 +731,8 @@ class Repository
raw_repository.local_branches(sort_by: sort_by, pagination_params: pagination_params)
end
- def tags_sorted_by(value)
- return raw_repository.tags(sort_by: value) if Feature.enabled?(:tags_finder_gitaly, project, default_enabled: :yaml)
-
- tags_ruby_sort(value)
+ def tags_sorted_by(value, pagination_params = nil)
+ raw_repository.tags(sort_by: value, pagination_params: pagination_params)
end
# Params:
@@ -1091,6 +1089,13 @@ class Repository
after_create
true
+ rescue Gitlab::Git::Repository::RepositoryExists
+ # We do not want to call `#after_create` given that we didn't create the
+ # repo, but we obviously have a mismatch between what's in our exists cache
+ # and actual on-disk state as seen by Gitaly. Let's thus expire our caches.
+ expire_status_cache
+
+ nil
end
def create_from_bundle(bundle_path)
@@ -1163,34 +1168,6 @@ class Repository
@request_store_cache ||= Gitlab::RepositoryCache.new(self, backend: Gitlab::SafeRequestStore)
end
- # Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/339741
- def tags_ruby_sort(value)
- case value
- when 'name_asc'
- VersionSorter.sort(tags) { |tag| tag.name }
- when 'name_desc'
- VersionSorter.rsort(tags) { |tag| tag.name }
- when 'updated_desc'
- tags_sorted_by_committed_date.reverse
- when 'updated_asc'
- tags_sorted_by_committed_date
- else
- tags
- end
- end
-
- # Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/339741
- def tags_sorted_by_committed_date
- # Annotated tags can point to any object (e.g. a blob), but generally
- # tags point to a commit. If we don't have a commit, then just default
- # to putting the tag at the end of the list.
- default = Time.current
-
- tags.sort_by do |tag|
- tag.dereferenced_target&.committed_date || default
- end
- end
-
def repository_event(event, tags = {})
Gitlab::Metrics.add_event(event, tags)
end
diff --git a/app/models/suggestion.rb b/app/models/suggestion.rb
index ff564d87449..f1ca5c23997 100644
--- a/app/models/suggestion.rb
+++ b/app/models/suggestion.rb
@@ -50,6 +50,7 @@ class Suggestion < ApplicationRecord
next _("Can't apply as the source branch was deleted.") unless noteable.source_branch_exists?
next outdated_reason if outdated?(cached: cached) || !note.active?
next _("This suggestion already matches its content.") unless different_content?
+ next _("This file was modified for readability, and can't accept suggestions. Edit it directly.") if file_path.end_with? "ipynb"
end
end
diff --git a/app/models/todo.rb b/app/models/todo.rb
index 94a99603848..742b8fd2a9d 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -18,6 +18,7 @@ class Todo < ApplicationRecord
DIRECTLY_ADDRESSED = 7
MERGE_TRAIN_REMOVED = 8 # This is an EE-only feature
REVIEW_REQUESTED = 9
+ ATTENTION_REQUESTED = 10
ACTION_NAMES = {
ASSIGNED => :assigned,
@@ -28,7 +29,8 @@ class Todo < ApplicationRecord
APPROVAL_REQUIRED => :approval_required,
UNMERGEABLE => :unmergeable,
DIRECTLY_ADDRESSED => :directly_addressed,
- MERGE_TRAIN_REMOVED => :merge_train_removed
+ MERGE_TRAIN_REMOVED => :merge_train_removed,
+ ATTENTION_REQUESTED => :attention_requested
}.freeze
belongs_to :author, class_name: "User"
@@ -189,6 +191,10 @@ class Todo < ApplicationRecord
action == REVIEW_REQUESTED
end
+ def attention_requested?
+ action == ATTENTION_REQUESTED
+ end
+
def merge_train_removed?
action == MERGE_TRAIN_REMOVED
end
diff --git a/app/models/upload.rb b/app/models/upload.rb
index c1a3df82457..ac7ebb31abc 100644
--- a/app/models/upload.rb
+++ b/app/models/upload.rb
@@ -2,6 +2,7 @@
class Upload < ApplicationRecord
include Checksummable
+
# Upper limit for foreground checksum processing
CHECKSUM_THRESHOLD = 100.megabytes
@@ -51,9 +52,9 @@ class Upload < ApplicationRecord
##
# FastDestroyAll concerns
- def finalize_fast_destroy(keys)
- keys.each do |store_class, paths|
- store_class.new.delete_keys_async(paths)
+ def finalize_fast_destroy(items_to_remove)
+ items_to_remove.each do |store_class, keys|
+ store_class.new.delete_keys_async(keys)
end
end
end
@@ -65,6 +66,10 @@ class Upload < ApplicationRecord
uploader_class.absolute_path(self)
end
+ def relative_path
+ uploader_class.relative_path(self)
+ end
+
def calculate_checksum!
self.checksum = nil
return unless needs_checksum?
diff --git a/app/models/uploads/fog.rb b/app/models/uploads/fog.rb
index b44e273e9ab..5d57b644dbe 100644
--- a/app/models/uploads/fog.rb
+++ b/app/models/uploads/fog.rb
@@ -15,13 +15,21 @@ module Uploads
end
def delete_keys(keys)
- keys.each do |key|
- connection.delete_object(bucket_name, key)
- end
+ keys.each { |key| delete_object(key) }
end
private
+ def delete_object(key)
+ connection.delete_object(bucket_name, key)
+
+ # So far, only GoogleCloudStorage raises an exception when the file is not found.
+ # Other providers support idempotent requests and does not raise an error
+ # when the file is missing.
+ rescue ::Google::Apis::ClientError => e
+ Gitlab::ErrorTracking.log_exception(e)
+ end
+
def object_store
Gitlab.config.uploads.object_store
end
diff --git a/app/models/uploads/local.rb b/app/models/uploads/local.rb
index bd295a66838..9df69998991 100644
--- a/app/models/uploads/local.rb
+++ b/app/models/uploads/local.rb
@@ -55,3 +55,5 @@ module Uploads
end
end
end
+
+Uploads::Local.prepend_mod
diff --git a/app/models/user.rb b/app/models/user.rb
index 0e19e6e4a79..3ab5b7ee364 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -123,7 +123,7 @@ class User < ApplicationRecord
# Profile
has_many :keys, -> { regular_keys }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
- has_many :expired_and_unnotified_keys, -> { expired_and_not_notified }, class_name: 'Key'
+ has_many :expired_today_and_unnotified_keys, -> { expired_today_and_not_notified }, class_name: 'Key'
has_many :expiring_soon_and_unnotified_keys, -> { expiring_soon_and_not_notified }, class_name: 'Key'
has_many :deploy_keys, -> { where(type: 'DeployKey') }, dependent: :nullify # rubocop:disable Cop/ActiveRecordDependent
has_many :group_deploy_keys
@@ -274,14 +274,21 @@ class User < ApplicationRecord
after_update :username_changed_hook, if: :saved_change_to_username?
after_destroy :post_destroy_hook
after_destroy :remove_key_cache
+ after_create :add_primary_email_to_emails!, if: :confirmed?
after_commit(on: :update) do
if previous_changes.key?('email')
- # Grab previous_email here since previous_changes changes after
- # #update_emails_with_primary_email and #update_notification_email are called
+ # Add the old primary email to Emails if not added already - this should be removed
+ # after the background migration for MR https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70872/ has completed,
+ # as the primary email is now added to Emails upon confirmation
+ # Issue to remove that: https://gitlab.com/gitlab-org/gitlab/-/issues/344134
previous_confirmed_at = previous_changes.key?('confirmed_at') ? previous_changes['confirmed_at'][0] : confirmed_at
previous_email = previous_changes[:email][0]
+ if previous_confirmed_at && !emails.exists?(email: previous_email)
+ # rubocop: disable CodeReuse/ServiceClass
+ Emails::CreateService.new(self, user: self, email: previous_email).execute(confirmed_at: previous_confirmed_at)
+ # rubocop: enable CodeReuse/ServiceClass
+ end
- update_emails_with_primary_email(previous_confirmed_at, previous_email)
update_invalid_gpg_signatures
end
end
@@ -454,8 +461,8 @@ class User < ApplicationRecord
scope :order_recent_last_activity, -> { reorder(Gitlab::Database.nulls_last_order('last_activity_on', 'DESC')) }
scope :order_oldest_last_activity, -> { reorder(Gitlab::Database.nulls_first_order('last_activity_on', 'ASC')) }
scope :by_id_and_login, ->(id, login) { where(id: id).where('username = LOWER(:login) OR email = LOWER(:login)', login: login) }
- scope :dormant, -> { active.where('last_activity_on <= ?', MINIMUM_INACTIVE_DAYS.day.ago.to_date) }
- scope :with_no_activity, -> { active.where(last_activity_on: nil) }
+ scope :dormant, -> { with_state(:active).human_or_service_user.where('last_activity_on <= ?', MINIMUM_INACTIVE_DAYS.day.ago.to_date) }
+ scope :with_no_activity, -> { with_state(:active).human_or_service_user.where(last_activity_on: nil) }
scope :by_provider_and_extern_uid, ->(provider, extern_uid) { joins(:identities).merge(Identity.with_extern_uid(provider, extern_uid)) }
scope :get_ids_by_username, -> (username) { where(username: username).pluck(:id) }
@@ -466,7 +473,11 @@ class User < ApplicationRecord
end
def active_for_authentication?
- super && can?(:log_in)
+ return false unless super
+
+ check_ldap_if_ldap_blocked!
+
+ can?(:log_in)
end
# The messages for these keys are defined in `devise.en.yml`
@@ -935,6 +946,8 @@ class User < ApplicationRecord
end
def unique_email
+ return if errors.added?(:email, _('has already been taken'))
+
if !emails.exists?(email: email) && Email.exists?(email: email)
errors.add(:email, _('has already been taken'))
end
@@ -963,24 +976,6 @@ class User < ApplicationRecord
skip_reconfirmation! if emails.confirmed.where(email: self.email).any?
end
- # Note: the use of the Emails services will cause `saves` on the user object, running
- # through the callbacks again and can have side effects, such as the `previous_changes`
- # hash and `_was` variables getting munged.
- # By using an `after_commit` instead of `after_update`, we avoid the recursive callback
- # scenario, though it then requires us to use the `previous_changes` hash
- # rubocop: disable CodeReuse/ServiceClass
- def update_emails_with_primary_email(previous_confirmed_at, previous_email)
- primary_email_record = emails.find_by(email: email)
- Emails::DestroyService.new(self, user: self).execute(primary_email_record) if primary_email_record
-
- # the original primary email was confirmed, and we want that to carry over. We don't
- # have access to the original confirmation values at this point, so just set confirmed_at
- Emails::CreateService.new(self, user: self, email: previous_email).execute(confirmed_at: previous_confirmed_at)
-
- update_columns(confirmed_at: primary_email_record.confirmed_at) if primary_email_record&.confirmed_at
- end
- # rubocop: enable CodeReuse/ServiceClass
-
def update_invalid_gpg_signatures
gpg_keys.each(&:update_invalid_gpg_signatures)
end
@@ -1025,8 +1020,10 @@ class User < ApplicationRecord
end
# rubocop: enable CodeReuse/ServiceClass
- def remove_project_authorizations(project_ids)
- project_authorizations.where(project_id: project_ids).delete_all
+ def remove_project_authorizations(project_ids, per_batch = 1000)
+ project_ids.each_slice(per_batch) do |project_ids_batch|
+ project_authorizations.where(project_id: project_ids_batch).delete_all
+ end
end
def authorized_projects(min_access_level = nil)
@@ -1389,7 +1386,7 @@ class User < ApplicationRecord
all_emails << email unless temp_oauth_email?
all_emails << private_commit_email if include_private_email
all_emails.concat(emails.map(&:email))
- all_emails
+ all_emails.uniq
end
def verified_emails(include_private_email: true)
@@ -1397,7 +1394,7 @@ class User < ApplicationRecord
verified_emails << email if primary_email_verified?
verified_emails << private_commit_email if include_private_email
verified_emails.concat(emails.confirmed.pluck(:email))
- verified_emails
+ verified_emails.uniq
end
def public_verified_emails
@@ -1610,8 +1607,6 @@ class User < ApplicationRecord
true
end
- # TODO Please check all callers and remove allow_cross_joins_across_databases,
- # when https://gitlab.com/gitlab-org/gitlab/-/issues/336436 is done.
def ci_owned_runners
@ci_owned_runners ||= begin
project_runners = Ci::RunnerProject
@@ -1624,7 +1619,7 @@ class User < ApplicationRecord
.joins(:runner)
.select('ci_runners.*')
- Ci::Runner.from_union([project_runners, group_runners])
+ Ci::Runner.from_union([project_runners, group_runners]).allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336436')
end
end
@@ -1980,6 +1975,37 @@ class User < ApplicationRecord
ci_job_token_scope.present?
end
+ # override from Devise::Confirmable
+ #
+ # Add the primary email to user.emails (or confirm it if it was already
+ # present) when the primary email is confirmed.
+ def confirm(*args)
+ saved = super(*args)
+ return false unless saved
+
+ email_to_confirm = self.emails.find_by(email: self.email)
+
+ if email_to_confirm.present?
+ email_to_confirm.confirm(*args)
+ else
+ add_primary_email_to_emails!
+ end
+
+ saved
+ end
+
+ def user_project
+ strong_memoize(:user_project) do
+ personal_projects.find_by(path: username, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ end
+ end
+
+ def user_readme
+ strong_memoize(:user_readme) do
+ user_project&.repository&.readme
+ end
+ end
+
protected
# override, from Devise::Validatable
@@ -2020,6 +2046,12 @@ class User < ApplicationRecord
'en'
end
+ # rubocop: disable CodeReuse/ServiceClass
+ def add_primary_email_to_emails!
+ Emails::CreateService.new(self, user: self, email: self.email).execute(confirmed_at: self.confirmed_at)
+ end
+ # rubocop: enable CodeReuse/ServiceClass
+
def notification_email_verified
return if notification_email.blank? || temp_oauth_email?
@@ -2153,6 +2185,13 @@ class User < ApplicationRecord
def ci_job_token_scope_cache_key
"users:#{id}:ci:job_token_scope"
end
+
+ # An `ldap_blocked` user will be unblocked if LDAP indicates they are allowed.
+ def check_ldap_if_ldap_blocked!
+ return unless ::Gitlab::Auth::Ldap::Config.enabled? && ldap_blocked?
+
+ ::Gitlab::Auth::Ldap::Access.allowed?(self)
+ end
end
User.prepend_mod_with('User')
diff --git a/app/models/user_status.rb b/app/models/user_status.rb
index 1c8634e47c3..7a803e8f1f6 100644
--- a/app/models/user_status.rb
+++ b/app/models/user_status.rb
@@ -22,7 +22,7 @@ class UserStatus < ApplicationRecord
enum availability: { not_set: 0, busy: 1 }
validates :user, presence: true
- validates :emoji, inclusion: { in: Gitlab::Emoji.emojis_names }
+ validates :emoji, 'gitlab/emoji_name': true
validates :message, length: { maximum: 100 }, allow_blank: true
scope :scheduled_for_cleanup, -> { where(arel_table[:clear_status_at].lteq(Time.current)) }
@@ -33,3 +33,5 @@ class UserStatus < ApplicationRecord
self.clear_status_at = CLEAR_STATUS_QUICK_OPTIONS[value]&.from_now
end
end
+
+UserStatus.prepend_mod_with('UserStatus')
diff --git a/app/models/users/credit_card_validation.rb b/app/models/users/credit_card_validation.rb
index a4cc43d1f13..556ee03605d 100644
--- a/app/models/users/credit_card_validation.rb
+++ b/app/models/users/credit_card_validation.rb
@@ -9,6 +9,7 @@ module Users
belongs_to :user
validates :holder_name, length: { maximum: 26 }
+ validates :network, length: { maximum: 32 }
validates :last_digits, allow_nil: true, numericality: {
greater_than_or_equal_to: 0, less_than_or_equal_to: 9999
}
@@ -17,7 +18,7 @@ module Users
self.class.where(
expiration_date: expiration_date,
last_digits: last_digits,
- holder_name: holder_name
+ network: network
).order(credit_card_validated_at: :desc).includes(:user)
end
end
diff --git a/app/models/users/in_product_marketing_email.rb b/app/models/users/in_product_marketing_email.rb
index 8fe52ac7ecc..1f1eaacfe5c 100644
--- a/app/models/users/in_product_marketing_email.rb
+++ b/app/models/users/in_product_marketing_email.rb
@@ -22,7 +22,8 @@ module Users
experience: 4,
team_short: 5,
trial_short: 6,
- admin_verify: 7
+ admin_verify: 7,
+ invite_team: 8
}, _suffix: true
scope :without_track_and_series, -> (track, series) do
diff --git a/app/models/users_statistics.rb b/app/models/users_statistics.rb
index a903541f69a..a314ae8920b 100644
--- a/app/models/users_statistics.rb
+++ b/app/models/users_statistics.rb
@@ -3,12 +3,6 @@
class UsersStatistics < ApplicationRecord
scope :order_created_at_desc, -> { order(created_at: :desc) }
- class << self
- def latest
- order_created_at_desc.first
- end
- end
-
def active
[
without_groups_and_projects,
@@ -26,30 +20,26 @@ class UsersStatistics < ApplicationRecord
end
class << self
- def create_current_stats!
- stats_by_role = highest_role_stats
+ def latest
+ order_created_at_desc.first
+ end
- create!(
- without_groups_and_projects: without_groups_and_projects_stats,
- with_highest_role_guest: stats_by_role[:guest],
- with_highest_role_reporter: stats_by_role[:reporter],
- with_highest_role_developer: stats_by_role[:developer],
- with_highest_role_maintainer: stats_by_role[:maintainer],
- with_highest_role_owner: stats_by_role[:owner],
- bots: bot_stats,
- blocked: blocked_stats
- )
+ def create_current_stats!
+ create!(highest_role_stats)
end
private
def highest_role_stats
{
- owner: batch_count_for_access_level(Gitlab::Access::OWNER),
- maintainer: batch_count_for_access_level(Gitlab::Access::MAINTAINER),
- developer: batch_count_for_access_level(Gitlab::Access::DEVELOPER),
- reporter: batch_count_for_access_level(Gitlab::Access::REPORTER),
- guest: batch_count_for_access_level(Gitlab::Access::GUEST)
+ without_groups_and_projects: without_groups_and_projects_stats,
+ with_highest_role_guest: batch_count_for_access_level(Gitlab::Access::GUEST),
+ with_highest_role_reporter: batch_count_for_access_level(Gitlab::Access::REPORTER),
+ with_highest_role_developer: batch_count_for_access_level(Gitlab::Access::DEVELOPER),
+ with_highest_role_maintainer: batch_count_for_access_level(Gitlab::Access::MAINTAINER),
+ with_highest_role_owner: batch_count_for_access_level(Gitlab::Access::OWNER),
+ bots: bot_stats,
+ blocked: blocked_stats
}
end
diff --git a/app/models/webauthn_registration.rb b/app/models/webauthn_registration.rb
index 76f8faa11c7..71b50192e29 100644
--- a/app/models/webauthn_registration.rb
+++ b/app/models/webauthn_registration.rb
@@ -5,7 +5,8 @@
class WebauthnRegistration < ApplicationRecord
belongs_to :user
- validates :credential_xid, :public_key, :name, :counter, presence: true
+ validates :credential_xid, :public_key, :counter, presence: true
+ validates :name, length: { minimum: 0, allow_nil: false }
validates :counter,
numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 2**32 - 1 }
end
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 64395f69c42..833d5b9bd34 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -75,6 +75,8 @@ class GroupPolicy < BasePolicy
with_scope :subject
condition(:has_project_with_service_desk_enabled) { @subject.has_project_with_service_desk_enabled? }
+ condition(:crm_enabled, score: 0, scope: :subject) { Feature.enabled?(:customer_relations, @subject) }
+
rule { can?(:read_group) & design_management_enabled }.policy do
enable :read_design_activity
end
@@ -113,8 +115,8 @@ class GroupPolicy < BasePolicy
enable :read_group_member
enable :read_custom_emoji
enable :read_counts
- enable :read_organization
- enable :read_contact
+ enable :read_crm_organization
+ enable :read_crm_contact
end
rule { ~public_group & ~has_access }.prevent :read_counts
@@ -134,8 +136,8 @@ class GroupPolicy < BasePolicy
enable :create_package
enable :create_package_settings
enable :developer_access
- enable :admin_organization
- enable :admin_contact
+ enable :admin_crm_organization
+ enable :admin_crm_contact
end
rule { reporter }.policy do
@@ -252,6 +254,13 @@ class GroupPolicy < BasePolicy
enable :read_label
end
+ rule { ~crm_enabled }.policy do
+ prevent :read_crm_contact
+ prevent :read_crm_organization
+ prevent :admin_crm_contact
+ prevent :admin_crm_organization
+ end
+
def access_level(for_any_session: false)
return GroupMember::NO_ACCESS if @user.nil?
return GroupMember::NO_ACCESS unless user_is_user?
diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb
index 575e532c615..c9c13b29643 100644
--- a/app/policies/issue_policy.rb
+++ b/app/policies/issue_policy.rb
@@ -12,6 +12,9 @@ class IssuePolicy < IssuablePolicy
@user && IssueCollection.new([@subject]).visible_to(@user).any?
end
+ desc "User can read contacts belonging to the issue group"
+ condition(:can_read_crm_contacts, scope: :subject) { @user.can?(:read_crm_contact, @subject.project.group) }
+
desc "Issue is confidential"
condition(:confidential, scope: :subject) { @subject.confidential? }
@@ -77,6 +80,10 @@ class IssuePolicy < IssuablePolicy
rule { ~persisted & can?(:create_issue) }.policy do
enable :set_confidentiality
end
+
+ rule { can?(:set_issue_metadata) & can_read_crm_contacts }.policy do
+ enable :set_issue_crm_contacts
+ end
end
IssuePolicy.prepend_mod_with('IssuePolicy')
diff --git a/app/policies/packages/helm/file_metadatum_policy.rb b/app/policies/packages/helm/file_metadatum_policy.rb
new file mode 100644
index 00000000000..4e0cb9046bf
--- /dev/null
+++ b/app/policies/packages/helm/file_metadatum_policy.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+module Packages
+ module Helm
+ class FileMetadatumPolicy < BasePolicy
+ delegate { @subject.package_file.package }
+ end
+ end
+end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 87573c9ad13..d81db357162 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -47,6 +47,9 @@ class ProjectPolicy < BasePolicy
desc "Project is archived"
condition(:archived, scope: :subject, score: 0) { project.archived? }
+ desc "Project is in the process of being deleted"
+ condition(:pending_delete) { project.pending_delete? }
+
condition(:default_issues_tracker, scope: :subject) { project.default_issues_tracker? }
desc "Container registry is disabled"
@@ -248,7 +251,7 @@ class ProjectPolicy < BasePolicy
enable :read_insights
end
- rule { can?(:guest_access) & can?(:create_issue) }.enable :create_incident
+ rule { can?(:reporter_access) & can?(:create_issue) }.enable :create_incident
# These abilities are not allowed to admins that are not members of the project,
# that's why they are defined separately.
@@ -439,7 +442,7 @@ class ProjectPolicy < BasePolicy
enable :destroy_freeze_period
enable :admin_feature_flags_client
enable :update_runners_registration_token
- enable :manage_project_google_cloud
+ enable :admin_project_google_cloud
end
rule { public_project & metrics_dashboard_allowed }.policy do
@@ -457,7 +460,13 @@ class ProjectPolicy < BasePolicy
prevent(*readonly_abilities)
readonly_features.each do |feature|
- prevent(*create_update_admin_destroy(feature))
+ prevent(*create_update_admin(feature))
+ end
+ end
+
+ rule { archived & ~pending_delete }.policy do
+ readonly_features.each do |feature|
+ prevent(:"destroy_#{feature}")
end
end
diff --git a/app/presenters/award_emoji_presenter.rb b/app/presenters/award_emoji_presenter.rb
index 8a7b58e0aba..9a1c8d6934d 100644
--- a/app/presenters/award_emoji_presenter.rb
+++ b/app/presenters/award_emoji_presenter.rb
@@ -4,24 +4,24 @@ class AwardEmojiPresenter < Gitlab::View::Presenter::Delegated
presents ::AwardEmoji, as: :award_emoji
def description
- as_emoji['description']
+ as_emoji&.description
end
def unicode
- as_emoji['unicode']
+ as_emoji&.hex
end
def emoji
- as_emoji['moji']
+ as_emoji&.codepoints
end
def unicode_version
- Gitlab::Emoji.emoji_unicode_version(award_emoji.name)
+ as_emoji&.unicode_version
end
private
def as_emoji
- @emoji ||= Gitlab::Emoji.emojis[award_emoji.name] || {}
+ @emoji ||= TanukiEmoji.find_by_alpha_code(award_emoji.name)
end
end
diff --git a/app/presenters/blob_presenter.rb b/app/presenters/blob_presenter.rb
index c198859aa4c..5835a77d0b9 100644
--- a/app/presenters/blob_presenter.rb
+++ b/app/presenters/blob_presenter.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+require 'ipynbdiff'
class BlobPresenter < Gitlab::View::Presenter::Delegated
include ApplicationHelper
@@ -20,6 +21,17 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
)
end
+ def highlight_transformed(plain: nil)
+ load_all_blob_data
+
+ Gitlab::Highlight.highlight(
+ blob.path,
+ transformed_blob_data,
+ language: transformed_blob_language,
+ plain: plain
+ )
+ end
+
def plain_data
return if blob.binary?
@@ -50,6 +62,10 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
url_helpers.project_create_blob_path(project, ref_qualified_path)
end
+ def pipeline_editor_path
+ project_ci_pipeline_editor_path(project, branch_name: blob.commit_id) if can_collaborate_with_project?(project) && blob.path == project.ci_config_path_or_default
+ end
+
def fork_and_edit_path
fork_path_for_current_user(project, edit_blob_path)
end
@@ -107,4 +123,21 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
def language
blob.language_from_gitattributes
end
+
+ def transformed_blob_language
+ @transformed_blob_language ||= blob.path.ends_with?('.ipynb') ? 'md' : language
+ end
+
+ def transformed_blob_data
+ @transformed_blob ||= if blob.path.ends_with?('.ipynb') && blob.transformed_for_diff
+ IpynbDiff.transform(blob.data,
+ raise_errors: true,
+ options: { include_metadata: false, cell_decorator: :percent })
+ end
+
+ @transformed_blob ||= blob.data
+ rescue IpynbDiff::InvalidNotebookError => e
+ Gitlab::ErrorTracking.log_exception(e)
+ blob.data
+ end
end
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index b0066e2d7f0..8e1b675d051 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -33,11 +33,7 @@ module Ci
end
def runner_variables
- if Feature.enabled?(:variable_inside_variable, project, default_enabled: :yaml)
- variables.sort_and_expand_all(project, keep_undefined: true).to_runner_variables
- else
- variables.to_runner_variables
- end
+ variables.sort_and_expand_all(keep_undefined: true).to_runner_variables
end
def refspecs
diff --git a/app/presenters/packages/npm/package_presenter.rb b/app/presenters/packages/npm/package_presenter.rb
index b9595eb6647..9e3308c2573 100644
--- a/app/presenters/packages/npm/package_presenter.rb
+++ b/app/presenters/packages/npm/package_presenter.rb
@@ -5,26 +5,37 @@ module Packages
class PackagePresenter
include API::Helpers::RelatedResourcesHelpers
+ # Allowed fields are those defined in the abbreviated form
+ # defined here: https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#abbreviated-version-object
+ # except: name, version, dist, dependencies and xDependencies. Those are generated by this presenter.
+ PACKAGE_JSON_ALLOWED_FIELDS = %w[deprecated bin directories dist engines _hasShrinkwrap].freeze
+
attr_reader :name, :packages
- def initialize(name, packages)
+ def initialize(name, packages, include_metadata: false)
@name = name
@packages = packages
+ @include_metadata = include_metadata
end
def versions
package_versions = {}
packages.each_batch do |relation|
- relation.including_dependency_links
- .preload_files
- .each do |package|
- package_file = package.package_files.last
+ batched_packages = relation.including_dependency_links
+ .preload_files
+
+ if @include_metadata
+ batched_packages = batched_packages.preload_npm_metadatum
+ end
+
+ batched_packages.each do |package|
+ package_file = package.package_files.last
- next unless package_file
+ next unless package_file
- package_versions[package.version] = build_package_version(package, package_file)
- end
+ package_versions[package.version] = build_package_version(package, package_file)
+ end
end
package_versions
@@ -41,14 +52,14 @@ module Packages
end
def build_package_version(package, package_file)
- {
+ abbreviated_package_json(package).merge(
name: package.name,
version: package.version,
dist: {
shasum: package_file.file_sha1,
tarball: tarball_url(package, package_file)
}
- }.tap do |package_version|
+ ).tap do |package_version|
package_version.merge!(build_package_dependencies(package))
end
end
@@ -79,6 +90,13 @@ module Packages
Packages::Tag.for_packages(packages)
.preload_package
end
+
+ def abbreviated_package_json(package)
+ return {} unless @include_metadata
+
+ json = package.npm_metadatum&.package_json || {}
+ json.slice(*PACKAGE_JSON_ALLOWED_FIELDS)
+ end
end
end
end
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index bbd8c715f5c..ec66f9bdd4f 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -249,33 +249,23 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
strong_memoize(:upload_anchor_data) do
next unless can_current_user_push_to_default_branch?
- experiment(:empty_repo_upload, project: project) do |e|
- e.use {}
- e.try do
- AnchorData.new(false,
- statistic_icon('upload') + _('Upload file'),
- '#modal-upload-blob',
- 'js-upload-file-experiment-trigger',
- nil,
- nil,
- {
- 'target_branch' => default_branch_or_main,
- 'original_branch' => default_branch_or_main,
- 'can_push_code' => 'true',
- 'path' => project_create_blob_path(project, default_branch_or_main),
- 'project_path' => project.full_path
- }
- )
- end
- e.run
- end
+ AnchorData.new(false,
+ statistic_icon('upload') + _('Upload file'),
+ '#modal-upload-blob',
+ 'js-upload-file-trigger',
+ nil,
+ nil,
+ {
+ 'target_branch' => default_branch_or_main,
+ 'original_branch' => default_branch_or_main,
+ 'can_push_code' => 'true',
+ 'path' => project_create_blob_path(project, default_branch_or_main),
+ 'project_path' => project.full_path
+ }
+ )
end
end
- def empty_repo_upload_experiment?
- upload_anchor_data.present?
- end
-
def new_file_anchor_data
if can_current_user_push_to_default_branch?
new_file_path = empty_repo? ? ide_edit_path(project, default_branch_or_main) : project_new_blob_path(project, default_branch_or_main)
diff --git a/app/presenters/release_presenter.rb b/app/presenters/release_presenter.rb
index c919c7f4c60..dac42af38bf 100644
--- a/app/presenters/release_presenter.rb
+++ b/app/presenters/release_presenter.rb
@@ -22,8 +22,6 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated
end
def self_url
- return unless can_download_code?
-
project_release_url(project, release)
end
@@ -64,7 +62,7 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated
delegator_override :name
def name
- can_download_code? ? release.name : "Release-#{release.id}"
+ release.name
end
def download_url(filepath)
diff --git a/app/serializers/alert_management/alert_entity.rb b/app/serializers/alert_management/alert_entity.rb
new file mode 100644
index 00000000000..6871da44887
--- /dev/null
+++ b/app/serializers/alert_management/alert_entity.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module AlertManagement
+ class AlertEntity < Grape::Entity
+ expose :iid
+ expose :title
+ end
+end
diff --git a/app/serializers/alert_management/alert_serializer.rb b/app/serializers/alert_management/alert_serializer.rb
new file mode 100644
index 00000000000..89815bf6510
--- /dev/null
+++ b/app/serializers/alert_management/alert_serializer.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module AlertManagement
+ class AlertSerializer < BaseSerializer
+ entity AlertManagement::AlertEntity
+ end
+end
diff --git a/app/serializers/analytics_summary_entity.rb b/app/serializers/analytics_summary_entity.rb
index 62828fc1428..dc42d7f52ad 100644
--- a/app/serializers/analytics_summary_entity.rb
+++ b/app/serializers/analytics_summary_entity.rb
@@ -4,6 +4,7 @@ class AnalyticsSummaryEntity < Grape::Entity
expose :value, safe: true
expose :title
expose :unit, if: { with_unit: true }
+ expose :links
private
diff --git a/app/serializers/merge_request_sidebar_extras_entity.rb b/app/serializers/merge_request_sidebar_extras_entity.rb
index 1a0111fe5d0..c211f9c1608 100644
--- a/app/serializers/merge_request_sidebar_extras_entity.rb
+++ b/app/serializers/merge_request_sidebar_extras_entity.rb
@@ -2,10 +2,10 @@
class MergeRequestSidebarExtrasEntity < IssuableSidebarExtrasEntity
expose :assignees do |merge_request, options|
- MergeRequestUserEntity.represent(merge_request.assignees, options.merge(merge_request: merge_request))
+ MergeRequestUserEntity.represent(merge_request.assignees, options.merge(merge_request: merge_request, type: :assignees))
end
expose :reviewers do |merge_request, options|
- MergeRequestUserEntity.represent(merge_request.reviewers, options.merge(merge_request: merge_request))
+ MergeRequestUserEntity.represent(merge_request.reviewers, options.merge(merge_request: merge_request, type: :reviewers))
end
end
diff --git a/app/serializers/merge_request_user_entity.rb b/app/serializers/merge_request_user_entity.rb
index 66672494bd9..97912656bbb 100644
--- a/app/serializers/merge_request_user_entity.rb
+++ b/app/serializers/merge_request_user_entity.rb
@@ -16,10 +16,12 @@ class MergeRequestUserEntity < ::API::Entities::UserBasic
request.current_user&.can?(:update_merge_request, options[:merge_request])
end
- expose :reviewed, if: satisfies(:present?, :allows_reviewers?) do |reviewer, options|
- reviewer = options[:merge_request].find_reviewer(reviewer)
+ expose :reviewed, if: satisfies(:present?, :allows_reviewers?) do |user, options|
+ find_reviewer_or_assignee(user, options)&.reviewed?
+ end
- reviewer&.reviewed?
+ expose :attention_requested, if: satisfies(:present?, :allows_reviewers?, :attention_requested_enabled?) do |user, options|
+ find_reviewer_or_assignee(user, options)&.attention_requested?
end
expose :approved, if: satisfies(:present?) do |user, options|
@@ -27,6 +29,16 @@ class MergeRequestUserEntity < ::API::Entities::UserBasic
# makes one query per merge request, whereas #approved_by? makes one per user
options[:merge_request].approvals.any? { |app| app.user_id == user.id }
end
+
+ private
+
+ def find_reviewer_or_assignee(user, options)
+ if options[:type] == :reviewers
+ options[:merge_request].find_reviewer(user)
+ else
+ options[:merge_request].find_assignee(user)
+ end
+ end
end
MergeRequestUserEntity.prepend_mod_with('MergeRequestUserEntity')
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index 1e4289ce774..bd60d60c8db 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -48,7 +48,7 @@ class MergeRequestWidgetEntity < Grape::Entity
end
expose :conflicts_docs_path do |merge_request|
- help_page_path('user/project/merge_requests/resolve_conflicts.md')
+ help_page_path('user/project/merge_requests/conflicts.md')
end
expose :reviewing_and_managing_merge_requests_docs_path do |merge_request|
@@ -64,14 +64,12 @@ class MergeRequestWidgetEntity < Grape::Entity
end
expose :merge_request_add_ci_config_path, if: ->(mr, _) { can_add_ci_config_path?(mr) } do |merge_request|
- project_new_blob_path(
- merge_request.source_project,
- merge_request.source_branch,
- file_name: '.gitlab-ci.yml',
- commit_message: s_("CommitMessage|Add %{file_name}") % { file_name: Gitlab::FileDetector::PATTERNS[:gitlab_ci] },
- mr_path: merge_request_path(merge_request),
- suggest_gitlab_ci_yml: true
- )
+ project = merge_request.source_project
+ params = {
+ branch_name: merge_request.source_branch,
+ add_new_config_file: true
+ }
+ project_ci_pipeline_editor_path(project, params)
end
expose :user_callouts_path do |_merge_request|
@@ -177,7 +175,6 @@ class MergeRequestWidgetEntity < Grape::Entity
def can_add_ci_config_path?(merge_request)
merge_request.open? &&
merge_request.source_branch_exists? &&
- merge_request.source_project&.uses_default_ci_config? &&
!merge_request.source_project.has_ci? &&
merge_request.commits_count > 0 &&
can?(current_user, :read_build, merge_request.source_project) &&
diff --git a/app/serializers/note_entity.rb b/app/serializers/note_entity.rb
index 8308e954c06..8f189f14dea 100644
--- a/app/serializers/note_entity.rb
+++ b/app/serializers/note_entity.rb
@@ -51,6 +51,10 @@ class NoteEntity < API::Entities::Note
SystemNoteHelper.system_note_icon_name(note)
end
+ expose :outdated_line_change_path, if: -> (note, _) { note.system? && note.change_position&.line_range && Feature.enabled?(:display_outdated_line_diff, note.project, default_enabled: :yaml) } do |note|
+ outdated_line_change_namespace_project_note_path(namespace_id: note.project.namespace, project_id: note.project, id: note)
+ end
+
expose :is_noteable_author do |note|
note.noteable_author?(request.noteable)
end
diff --git a/app/serializers/service_field_entity.rb b/app/serializers/service_field_entity.rb
index 960e216906e..aad9db5ffea 100644
--- a/app/serializers/service_field_entity.rb
+++ b/app/serializers/service_field_entity.rb
@@ -4,7 +4,7 @@ class ServiceFieldEntity < Grape::Entity
include RequestAwareEntity
include Gitlab::Utils::StrongMemoize
- expose :type, :name, :placeholder, :required, :choices
+ expose :type, :name, :placeholder, :required, :choices, :checkbox_label
expose :title do |field|
non_empty_password?(field) ? field[:non_empty_password_title] : field[:title]
diff --git a/app/services/alert_management/process_prometheus_alert_service.rb b/app/services/alert_management/process_prometheus_alert_service.rb
index 605ab7a1869..1b377a3d367 100644
--- a/app/services/alert_management/process_prometheus_alert_service.rb
+++ b/app/services/alert_management/process_prometheus_alert_service.rb
@@ -4,6 +4,7 @@ module AlertManagement
class ProcessPrometheusAlertService
extend ::Gitlab::Utils::Override
include ::AlertManagement::AlertProcessing
+ include ::AlertManagement::Responses
def initialize(project, payload)
@project = project
@@ -18,7 +19,7 @@ module AlertManagement
complete_post_processing_tasks
- ServiceResponse.success
+ success(alert)
end
private
@@ -40,9 +41,5 @@ module AlertManagement
def resolving_alert?
incoming_payload.resolved?
end
-
- def bad_request
- ServiceResponse.error(message: 'Bad Request', http_status: :bad_request)
- end
end
end
diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb
index 558798c830d..563d4a924fc 100644
--- a/app/services/audit_event_service.rb
+++ b/app/services/audit_event_service.rb
@@ -119,6 +119,10 @@ class AuditEventService
event
end
+ def stream_event_to_external_destinations(_event)
+ # Defined in EE
+ end
+
def log_authentication_event_to_database
return unless Gitlab::Database.read_write? && authentication_event?
@@ -130,6 +134,7 @@ class AuditEventService
def save_or_track(event)
event.save!
+ stream_event_to_external_destinations(event)
rescue StandardError => e
Gitlab::ErrorTracking.track_exception(e, audit_event_type: event.class.to_s)
end
diff --git a/app/services/authorized_project_update/project_access_changed_service.rb b/app/services/authorized_project_update/project_access_changed_service.rb
new file mode 100644
index 00000000000..62bf4ced1ae
--- /dev/null
+++ b/app/services/authorized_project_update/project_access_changed_service.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module AuthorizedProjectUpdate
+ class ProjectAccessChangedService
+ def initialize(project_ids)
+ @project_ids = Array.wrap(project_ids)
+ end
+
+ def execute(blocking: true)
+ bulk_args = @project_ids.map { |id| [id] }
+
+ if blocking
+ AuthorizedProjectUpdate::ProjectRecalculateWorker.bulk_perform_and_wait(bulk_args)
+ else
+ AuthorizedProjectUpdate::ProjectRecalculateWorker.bulk_perform_async(bulk_args) # rubocop:disable Scalability/BulkPerformWithContext
+ end
+ end
+ end
+end
diff --git a/app/services/award_emojis/base_service.rb b/app/services/award_emojis/base_service.rb
index a677d03a221..626e26d63b5 100644
--- a/app/services/award_emojis/base_service.rb
+++ b/app/services/award_emojis/base_service.rb
@@ -14,7 +14,7 @@ module AwardEmojis
private
def normalize_name(name)
- Gitlab::Emoji.normalize_emoji_name(name)
+ TanukiEmoji.find_by_alpha_code(name)&.name || name
end
# Provide more error state data than what BaseService allows.
diff --git a/app/services/base_service.rb b/app/services/base_service.rb
index 275ebcc7bcd..c7380768e32 100644
--- a/app/services/base_service.rb
+++ b/app/services/base_service.rb
@@ -6,13 +6,7 @@
# and existing service will use these one by one.
# After all are migrated, we can remove this class.
#
-# New services should consider inheriting from:
-#
-# - BaseContainerService for services scoped by container (project or group)
-# - BaseProjectService for services scoped to projects
-# - BaseGroupService for services scoped to groups
-#
-# or, create a new base class and update this comment.
+# For new services, please see https://docs.gitlab.com/ee/development/reusing_abstractions.html#service-classes
class BaseService
include BaseServiceUtility
include Gitlab::Experiment::Dsl
diff --git a/app/services/bulk_imports/file_download_service.rb b/app/services/bulk_imports/file_download_service.rb
index 9a301c260a9..d08dc72e30b 100644
--- a/app/services/bulk_imports/file_download_service.rb
+++ b/app/services/bulk_imports/file_download_service.rb
@@ -7,8 +7,16 @@ module BulkImports
REMOTE_FILENAME_PATTERN = %r{filename="(?<filename>[^"]+)"}.freeze
FILENAME_SIZE_LIMIT = 255 # chars before the extension
-
- def initialize(configuration:, relative_url:, dir:, file_size_limit:, allowed_content_types:, filename: nil)
+ DEFAULT_FILE_SIZE_LIMIT = 5.gigabytes
+ DEFAULT_ALLOWED_CONTENT_TYPES = %w(application/gzip application/octet-stream).freeze
+
+ def initialize(
+ configuration:,
+ relative_url:,
+ dir:,
+ file_size_limit: DEFAULT_FILE_SIZE_LIMIT,
+ allowed_content_types: DEFAULT_ALLOWED_CONTENT_TYPES,
+ filename: nil)
@configuration = configuration
@relative_url = relative_url
@filename = filename
diff --git a/app/services/bulk_update_integration_service.rb b/app/services/bulk_update_integration_service.rb
index 45465ba3946..29c4d0cc220 100644
--- a/app/services/bulk_update_integration_service.rb
+++ b/app/services/bulk_update_integration_service.rb
@@ -12,7 +12,7 @@ class BulkUpdateIntegrationService
Integration.where(id: batch_ids).update_all(integration_hash)
if integration.data_fields_present?
- integration.data_fields.class.where(service_id: batch_ids).update_all(data_fields_hash)
+ integration.data_fields.class.where(data_fields_foreign_key => batch_ids).update_all(data_fields_hash)
end
end
end
@@ -22,6 +22,11 @@ class BulkUpdateIntegrationService
attr_reader :integration, :batch
+ # service_id or integration_id
+ def data_fields_foreign_key
+ integration.data_fields.class.reflections['integration'].foreign_key
+ end
+
def integration_hash
integration.to_integration_hash.tap { |json| json['inherit_from_id'] = integration.inherit_from_id || integration.id }
end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index ba9665555cc..540e8f7b970 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -25,6 +25,7 @@ module Ci
Gitlab::Ci::Pipeline::Chain::Populate,
Gitlab::Ci::Pipeline::Chain::StopDryRun,
Gitlab::Ci::Pipeline::Chain::Create,
+ Gitlab::Ci::Pipeline::Chain::CreateCrossDatabaseAssociations,
Gitlab::Ci::Pipeline::Chain::Limit::Activity,
Gitlab::Ci::Pipeline::Chain::Limit::JobActivity,
Gitlab::Ci::Pipeline::Chain::CancelPendingPipelines,
diff --git a/app/services/ci/destroy_pipeline_service.rb b/app/services/ci/destroy_pipeline_service.rb
index 476c7523d60..6fbde5d291c 100644
--- a/app/services/ci/destroy_pipeline_service.rb
+++ b/app/services/ci/destroy_pipeline_service.rb
@@ -12,7 +12,9 @@ module Ci
# Ci::Pipeline#destroy triggers `use_fast_destroy :job_artifacts` and
# ci_builds has ON DELETE CASCADE to ci_pipelines. The pipeline, the builds,
# job and pipeline artifacts all get destroyed here.
- pipeline.reset.destroy!
+ ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/345664') do
+ pipeline.reset.destroy!
+ end
ServiceResponse.success(message: 'Pipeline not found')
rescue ActiveRecord::RecordNotFound
diff --git a/app/services/ci/external_pull_requests/create_pipeline_service.rb b/app/services/ci/external_pull_requests/create_pipeline_service.rb
index dd93ca4708e..66127c94d35 100644
--- a/app/services/ci/external_pull_requests/create_pipeline_service.rb
+++ b/app/services/ci/external_pull_requests/create_pipeline_service.rb
@@ -16,14 +16,9 @@ module Ci
private
def create_pipeline_for(pull_request)
- if ::Feature.enabled?(:ci_create_external_pr_pipeline_async, project, default_enabled: :yaml)
- Ci::ExternalPullRequests::CreatePipelineWorker.perform_async(
- project.id, current_user.id, pull_request.id
- )
- else
- Ci::CreatePipelineService.new(project, current_user, create_params(pull_request))
- .execute(:external_pull_request_event, external_pull_request: pull_request)
- end
+ Ci::ExternalPullRequests::CreatePipelineWorker.perform_async(
+ project.id, current_user.id, pull_request.id
+ )
end
def create_params(pull_request)
diff --git a/app/services/ci/generate_kubeconfig_service.rb b/app/services/ci/generate_kubeconfig_service.rb
new file mode 100644
index 00000000000..18f68c0ff09
--- /dev/null
+++ b/app/services/ci/generate_kubeconfig_service.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Ci
+ class GenerateKubeconfigService
+ def initialize(build)
+ @build = build
+ @template = Gitlab::Kubernetes::Kubeconfig::Template.new
+ end
+
+ def execute
+ template.add_cluster(
+ name: cluster_name,
+ url: Gitlab::Kas.tunnel_url
+ )
+
+ agents.each do |agent|
+ user = user_name(agent)
+
+ template.add_user(
+ name: user,
+ token: agent_token(agent)
+ )
+
+ template.add_context(
+ name: context_name(agent),
+ cluster: cluster_name,
+ user: user
+ )
+ end
+
+ template
+ end
+
+ private
+
+ attr_reader :build, :template
+
+ def agents
+ build.pipeline.authorized_cluster_agents
+ end
+
+ def cluster_name
+ 'gitlab'
+ end
+
+ def user_name(agent)
+ ['agent', agent.id].join(delimiter)
+ end
+
+ def context_name(agent)
+ [agent.project.full_path, agent.name].join(delimiter)
+ end
+
+ def agent_token(agent)
+ ['ci', agent.id, build.token].join(delimiter)
+ end
+
+ def delimiter
+ ':'
+ end
+ end
+end
diff --git a/app/services/ci/job_artifacts/create_service.rb b/app/services/ci/job_artifacts/create_service.rb
index 9fc7c3b4d40..7c67a2e175d 100644
--- a/app/services/ci/job_artifacts/create_service.rb
+++ b/app/services/ci/job_artifacts/create_service.rb
@@ -19,6 +19,7 @@ module Ci
def initialize(job)
@job = job
@project = job.project
+ @pipeline = job.pipeline if ::Feature.enabled?(:ci_update_unlocked_job_artifacts, @project)
end
def authorize(artifact_type:, filesize: nil)
@@ -53,7 +54,7 @@ module Ci
private
- attr_reader :job, :project
+ attr_reader :job, :project, :pipeline
def validate_requirements(artifact_type:, filesize:)
return too_large_error if too_large?(artifact_type, filesize)
@@ -85,34 +86,38 @@ module Ci
expire_in = params['expire_in'] ||
Gitlab::CurrentSettings.current_application_settings.default_artifacts_expire_in
- artifact = Ci::JobArtifact.new(
+ artifact_attributes = {
job_id: job.id,
project: project,
- file: artifacts_file,
- file_type: params[:artifact_type],
- file_format: params[:artifact_format],
- file_sha256: artifacts_file.sha256,
- expire_in: expire_in)
+ expire_in: expire_in
+ }
+
+ artifact_attributes[:locked] = pipeline.locked if ::Feature.enabled?(:ci_update_unlocked_job_artifacts, project)
+
+ artifact = Ci::JobArtifact.new(
+ artifact_attributes.merge(
+ file: artifacts_file,
+ file_type: params[:artifact_type],
+ file_format: params[:artifact_format],
+ file_sha256: artifacts_file.sha256
+ )
+ )
artifact_metadata = if metadata_file
Ci::JobArtifact.new(
- job_id: job.id,
- project: project,
- file: metadata_file,
- file_type: :metadata,
- file_format: :gzip,
- file_sha256: metadata_file.sha256,
- expire_in: expire_in)
+ artifact_attributes.merge(
+ file: metadata_file,
+ file_type: :metadata,
+ file_format: :gzip,
+ file_sha256: metadata_file.sha256
+ )
+ )
end
[artifact, artifact_metadata]
end
def parse_artifact(artifact)
- unless Feature.enabled?(:ci_synchronous_artifact_parsing, project, default_enabled: true)
- return success
- end
-
case artifact.file_type
when 'dotenv' then parse_dotenv_artifact(artifact)
else success
diff --git a/app/services/ci/job_artifacts/destroy_all_expired_service.rb b/app/services/ci/job_artifacts/destroy_all_expired_service.rb
index 3e9cc95d135..e4f65736a58 100644
--- a/app/services/ci/job_artifacts/destroy_all_expired_service.rb
+++ b/app/services/ci/job_artifacts/destroy_all_expired_service.rb
@@ -24,7 +24,11 @@ module Ci
# which is scheduled every 7 minutes.
def execute
in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
- destroy_job_artifacts_with_slow_iteration(Time.current)
+ if ::Feature.enabled?(:ci_destroy_unlocked_job_artifacts)
+ destroy_unlocked_job_artifacts(Time.current)
+ else
+ destroy_job_artifacts_with_slow_iteration(Time.current)
+ end
end
@removed_artifacts_count
@@ -32,13 +36,21 @@ module Ci
private
+ def destroy_unlocked_job_artifacts(start_at)
+ loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
+ artifacts = Ci::JobArtifact.expired_before(start_at).artifact_unlocked.limit(BATCH_SIZE)
+ service_response = destroy_batch(artifacts)
+ @removed_artifacts_count += service_response[:destroyed_artifacts_count]
+ end
+ end
+
def destroy_job_artifacts_with_slow_iteration(start_at)
Ci::JobArtifact.expired_before(start_at).each_batch(of: BATCH_SIZE, column: :expire_at, order: :desc) do |relation, index|
# For performance reasons, join with ci_pipelines after the batch is queried.
# See: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47496
artifacts = relation.unlocked
- service_response = destroy_batch_async(artifacts)
+ service_response = destroy_batch(artifacts)
@removed_artifacts_count += service_response[:destroyed_artifacts_count]
break if loop_timeout?(start_at)
@@ -46,7 +58,7 @@ module Ci
end
end
- def destroy_batch_async(artifacts)
+ def destroy_batch(artifacts)
Ci::JobArtifacts::DestroyBatchService.new(artifacts).execute
end
diff --git a/app/services/ci/job_artifacts/destroy_batch_service.rb b/app/services/ci/job_artifacts/destroy_batch_service.rb
index 8536b88ccc0..866b40c32d8 100644
--- a/app/services/ci/job_artifacts/destroy_batch_service.rb
+++ b/app/services/ci/job_artifacts/destroy_batch_service.rb
@@ -26,15 +26,18 @@ module Ci
def execute(update_stats: true)
return success(destroyed_artifacts_count: 0, statistics_updates: {}) if @job_artifacts.empty?
+ destroy_related_records(@job_artifacts)
+
Ci::DeletedObject.transaction do
Ci::DeletedObject.bulk_import(@job_artifacts, @pick_up_at)
Ci::JobArtifact.id_in(@job_artifacts.map(&:id)).delete_all
- destroy_related_records(@job_artifacts)
end
+ after_batch_destroy_hook(@job_artifacts)
+
# This is executed outside of the transaction because it depends on Redis
update_project_statistics! if update_stats
- increment_monitoring_statistics(artifacts_count)
+ increment_monitoring_statistics(artifacts_count, artifacts_bytes)
success(destroyed_artifacts_count: artifacts_count,
statistics_updates: affected_project_statistics)
@@ -43,9 +46,12 @@ module Ci
private
- # This method is implemented in EE and it must do only database work
+ # Overriden in EE
def destroy_related_records(artifacts); end
+ # Overriden in EE
+ def after_batch_destroy_hook(artifacts); end
+
# using ! here since this can't be called inside a transaction
def update_project_statistics!
affected_project_statistics.each do |project, delta|
@@ -63,8 +69,9 @@ module Ci
end
end
- def increment_monitoring_statistics(size)
- metrics.increment_destroyed_artifacts(size)
+ def increment_monitoring_statistics(size, bytes)
+ metrics.increment_destroyed_artifacts_count(size)
+ metrics.increment_destroyed_artifacts_bytes(bytes)
end
def metrics
@@ -76,6 +83,12 @@ module Ci
@job_artifacts.count
end
end
+
+ def artifacts_bytes
+ strong_memoize(:artifacts_bytes) do
+ @job_artifacts.sum { |artifact| artifact.try(:size) || 0 }
+ end
+ end
end
end
end
diff --git a/app/services/ci/parse_dotenv_artifact_service.rb b/app/services/ci/parse_dotenv_artifact_service.rb
index 2ee9be476bb..725ecbcce5d 100644
--- a/app/services/ci/parse_dotenv_artifact_service.rb
+++ b/app/services/ci/parse_dotenv_artifact_service.rb
@@ -2,8 +2,7 @@
module Ci
class ParseDotenvArtifactService < ::BaseService
- MAX_ACCEPTABLE_DOTENV_SIZE = 5.kilobytes
- MAX_ACCEPTABLE_VARIABLES_COUNT = 20
+ include ::Gitlab::Utils::StrongMemoize
SizeLimitError = Class.new(StandardError)
ParserError = Class.new(StandardError)
@@ -27,9 +26,9 @@ module Ci
raise ArgumentError, 'Artifact is not dotenv file type'
end
- unless artifact.file.size < MAX_ACCEPTABLE_DOTENV_SIZE
+ unless artifact.file.size < dotenv_size_limit
raise SizeLimitError,
- "Dotenv Artifact Too Big. Maximum Allowable Size: #{MAX_ACCEPTABLE_DOTENV_SIZE}"
+ "Dotenv Artifact Too Big. Maximum Allowable Size: #{dotenv_size_limit}"
end
end
@@ -45,9 +44,9 @@ module Ci
end
end
- if variables.size > MAX_ACCEPTABLE_VARIABLES_COUNT
+ if variables.size > dotenv_variable_limit
raise SizeLimitError,
- "Dotenv files cannot have more than #{MAX_ACCEPTABLE_VARIABLES_COUNT} variables"
+ "Dotenv files cannot have more than #{dotenv_variable_limit} variables"
end
variables
@@ -60,5 +59,13 @@ module Ci
result.each(&:strip!)
end
+
+ def dotenv_variable_limit
+ strong_memoize(:dotenv_variable_limit) { project.actual_limits.dotenv_variables }
+ end
+
+ def dotenv_size_limit
+ strong_memoize(:dotenv_size_limit) { project.actual_limits.dotenv_size }
+ end
end
end
diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb
index 07cfbb9ce3c..ebb07de9d29 100644
--- a/app/services/ci/retry_build_service.rb
+++ b/app/services/ci/retry_build_service.rb
@@ -63,7 +63,7 @@ module Ci
def clone_build(build)
project.builds.new(build_attributes(build)).tap do |new_build|
- new_build.assign_attributes(::Gitlab::Ci::Pipeline::Seed::Build.environment_attributes_for(new_build))
+ new_build.assign_attributes(deployment_attributes_for(new_build, build))
end
end
@@ -75,6 +75,11 @@ module Ci
attributes[:user] = current_user
attributes
end
+
+ def deployment_attributes_for(new_build, old_build)
+ ::Gitlab::Ci::Pipeline::Seed::Build
+ .deployment_attributes_for(new_build, old_build.persisted_environment)
+ end
end
end
diff --git a/app/services/ci/unlock_artifacts_service.rb b/app/services/ci/unlock_artifacts_service.rb
index 7c169cb8395..30da31ba8ec 100644
--- a/app/services/ci/unlock_artifacts_service.rb
+++ b/app/services/ci/unlock_artifacts_service.rb
@@ -5,22 +5,84 @@ module Ci
BATCH_SIZE = 100
def execute(ci_ref, before_pipeline = nil)
- query = <<~SQL.squish
- UPDATE "ci_pipelines"
- SET "locked" = #{::Ci::Pipeline.lockeds[:unlocked]}
- WHERE "ci_pipelines"."id" in (
- #{collect_pipelines(ci_ref, before_pipeline).select(:id).to_sql}
- LIMIT #{BATCH_SIZE}
- FOR UPDATE SKIP LOCKED
- )
- RETURNING "ci_pipelines"."id";
- SQL
-
- loop do
- break if Ci::Pipeline.connection.exec_query(query).empty?
+ results = {
+ unlocked_pipelines: 0,
+ unlocked_job_artifacts: 0
+ }
+
+ if ::Feature.enabled?(:ci_update_unlocked_job_artifacts, ci_ref.project)
+ loop do
+ unlocked_pipelines = []
+ unlocked_job_artifacts = []
+
+ ::Ci::Pipeline.transaction do
+ unlocked_pipelines = unlock_pipelines(ci_ref, before_pipeline)
+ unlocked_job_artifacts = unlock_job_artifacts(unlocked_pipelines)
+ end
+
+ break if unlocked_pipelines.empty?
+
+ results[:unlocked_pipelines] += unlocked_pipelines.length
+ results[:unlocked_job_artifacts] += unlocked_job_artifacts.length
+ end
+ else
+ query = <<~SQL.squish
+ UPDATE "ci_pipelines"
+ SET "locked" = #{::Ci::Pipeline.lockeds[:unlocked]}
+ WHERE "ci_pipelines"."id" in (
+ #{collect_pipelines(ci_ref, before_pipeline).select(:id).to_sql}
+ LIMIT #{BATCH_SIZE}
+ FOR UPDATE SKIP LOCKED
+ )
+ RETURNING "ci_pipelines"."id";
+ SQL
+
+ loop do
+ unlocked_pipelines = Ci::Pipeline.connection.exec_query(query)
+
+ break if unlocked_pipelines.empty?
+
+ results[:unlocked_pipelines] += unlocked_pipelines.length
+ end
end
+
+ results
end
+ # rubocop:disable CodeReuse/ActiveRecord
+ def unlock_job_artifacts_query(pipeline_ids)
+ ci_job_artifacts = ::Ci::JobArtifact.arel_table
+
+ build_ids = ::Ci::Build.select(:id).where(commit_id: pipeline_ids)
+
+ returning = Arel::Nodes::Grouping.new(ci_job_artifacts[:id])
+
+ Arel::UpdateManager.new
+ .table(ci_job_artifacts)
+ .where(ci_job_artifacts[:job_id].in(Arel.sql(build_ids.to_sql)))
+ .set([[ci_job_artifacts[:locked], ::Ci::JobArtifact.lockeds[:unlocked]]])
+ .to_sql + " RETURNING #{returning.to_sql}"
+ end
+ # rubocop:enable CodeReuse/ActiveRecord
+
+ # rubocop:disable CodeReuse/ActiveRecord
+ def unlock_pipelines_query(ci_ref, before_pipeline)
+ ci_pipelines = ::Ci::Pipeline.arel_table
+
+ pipelines_scope = ci_ref.pipelines.artifacts_locked
+ pipelines_scope = pipelines_scope.before_pipeline(before_pipeline) if before_pipeline
+ pipelines_scope = pipelines_scope.select(:id).limit(BATCH_SIZE).lock('FOR UPDATE SKIP LOCKED')
+
+ returning = Arel::Nodes::Grouping.new(ci_pipelines[:id])
+
+ Arel::UpdateManager.new
+ .table(ci_pipelines)
+ .where(ci_pipelines[:id].in(Arel.sql(pipelines_scope.to_sql)))
+ .set([[ci_pipelines[:locked], ::Ci::Pipeline.lockeds[:unlocked]]])
+ .to_sql + " RETURNING #{returning.to_sql}"
+ end
+ # rubocop:enable CodeReuse/ActiveRecord
+
private
def collect_pipelines(ci_ref, before_pipeline)
@@ -29,5 +91,17 @@ module Ci
pipeline_scope.artifacts_locked
end
+
+ def unlock_job_artifacts(pipelines)
+ return if pipelines.empty?
+
+ ::Ci::JobArtifact.connection.exec_query(
+ unlock_job_artifacts_query(pipelines.rows.flatten)
+ )
+ end
+
+ def unlock_pipelines(ci_ref, before_pipeline)
+ ::Ci::Pipeline.connection.exec_query(unlock_pipelines_query(ci_ref, before_pipeline))
+ end
end
end
diff --git a/app/services/ci/update_build_state_service.rb b/app/services/ci/update_build_state_service.rb
index 3b403f92486..826d9a2eda3 100644
--- a/app/services/ci/update_build_state_service.rb
+++ b/app/services/ci/update_build_state_service.rb
@@ -73,11 +73,11 @@ module Ci
::Gitlab::Ci::Trace::Checksum.new(build).then do |checksum|
unless checksum.valid?
metrics.increment_trace_operation(operation: :invalid)
- metrics.increment_error_counter(type: :chunks_invalid_checksum)
+ metrics.increment_error_counter(error_reason: :chunks_invalid_checksum)
if checksum.corrupted?
metrics.increment_trace_operation(operation: :corrupted)
- metrics.increment_error_counter(type: :chunks_invalid_size)
+ metrics.increment_error_counter(error_reason: :chunks_invalid_size)
end
next unless log_invalid_chunks?
diff --git a/app/services/clusters/agents/refresh_authorization_service.rb b/app/services/clusters/agents/refresh_authorization_service.rb
index 7f401eef720..54b90a7304c 100644
--- a/app/services/clusters/agents/refresh_authorization_service.rb
+++ b/app/services/clusters/agents/refresh_authorization_service.rb
@@ -86,7 +86,7 @@ module Clusters
if group_root_ancestor?
root_ancestor.all_projects
else
- ::Project.none
+ ::Project.id_in(project.id)
end
end
diff --git a/app/services/clusters/applications/prometheus_health_check_service.rb b/app/services/clusters/applications/prometheus_health_check_service.rb
deleted file mode 100644
index eda47f56e72..00000000000
--- a/app/services/clusters/applications/prometheus_health_check_service.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-# frozen_string_literal: true
-
-module Clusters
- module Applications
- class PrometheusHealthCheckService
- include Gitlab::Utils::StrongMemoize
- include Gitlab::Routing
-
- def initialize(cluster)
- @cluster = cluster
- @logger = Gitlab::AppJsonLogger.build
- end
-
- def execute
- raise 'Invalid cluster type. Only project types are allowed.' unless @cluster.project_type?
-
- return unless prometheus_application.installed?
-
- project = @cluster.clusterable
-
- @logger.info(
- message: 'Prometheus health check',
- cluster_id: @cluster.id,
- newly_unhealthy: became_unhealthy?,
- currently_healthy: currently_healthy?,
- was_healthy: was_healthy?
- )
-
- send_notification(project) if became_unhealthy?
-
- prometheus_application.update_columns(healthy: currently_healthy?) if health_changed?
- end
-
- private
-
- def prometheus_application
- strong_memoize(:prometheus_application) do
- @cluster.application_prometheus
- end
- end
-
- def currently_healthy?
- strong_memoize(:currently_healthy) do
- prometheus_application.prometheus_client.healthy?
- end
- end
-
- def became_unhealthy?
- strong_memoize(:became_unhealthy) do
- (was_healthy? || was_healthy?.nil?) && !currently_healthy?
- end
- end
-
- def was_healthy?
- strong_memoize(:was_healthy) do
- prometheus_application.healthy
- end
- end
-
- def health_changed?
- was_healthy? != currently_healthy?
- end
-
- def send_notification(project)
- notification_payload = build_notification_payload(project)
- integration = project.alert_management_http_integrations.active.first
-
- Projects::Alerting::NotifyService.new(project, notification_payload).execute(integration&.token, integration)
-
- @logger.info(message: 'Successfully notified of Prometheus newly unhealthy', cluster_id: @cluster.id, project_id: project.id)
- end
-
- def build_notification_payload(project)
- cluster_path = namespace_project_cluster_path(
- project_id: project.path,
- namespace_id: project.namespace.path,
- id: @cluster.id
- )
-
- {
- title: "Prometheus is Unhealthy. Cluster Name: #{@cluster.name}",
- description: "Prometheus is unhealthy for the cluster: [#{@cluster.name}](#{cluster_path}) attached to project #{project.name}."
- }
- end
- end
- end
-end
diff --git a/app/services/clusters/cleanup/project_namespace_service.rb b/app/services/clusters/cleanup/project_namespace_service.rb
index 16254041306..0173f93f625 100644
--- a/app/services/clusters/cleanup/project_namespace_service.rb
+++ b/app/services/clusters/cleanup/project_namespace_service.rb
@@ -35,9 +35,11 @@ module Clusters
end
def kubeclient_delete_namespace(kubernetes_namespace)
- cluster.kubeclient.delete_namespace(kubernetes_namespace.namespace)
+ cluster.kubeclient&.delete_namespace(kubernetes_namespace.namespace)
rescue Kubeclient::ResourceNotFoundError
- # no-op: nothing to delete
+ # The resources have already been deleted, possibly on a previous attempt that timed out
+ rescue Gitlab::UrlBlocker::BlockedUrlError
+ # User gave an invalid cluster from the start, or deleted the endpoint before this job ran
end
end
end
diff --git a/app/services/clusters/cleanup/service_account_service.rb b/app/services/clusters/cleanup/service_account_service.rb
index baac9e4a9e7..53f968cd409 100644
--- a/app/services/clusters/cleanup/service_account_service.rb
+++ b/app/services/clusters/cleanup/service_account_service.rb
@@ -16,11 +16,14 @@ module Clusters
def delete_gitlab_service_account
log_event(:deleting_gitlab_service_account)
- cluster.kubeclient.delete_service_account(
+ cluster.kubeclient&.delete_service_account(
::Clusters::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAME,
::Clusters::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAMESPACE
)
rescue Kubeclient::ResourceNotFoundError
+ # The resources have already been deleted, possibly on a previous attempt that timed out
+ rescue Gitlab::UrlBlocker::BlockedUrlError
+ # User gave an invalid cluster from the start, or deleted the endpoint before this job ran
end
end
end
diff --git a/app/services/clusters/integrations/prometheus_health_check_service.rb b/app/services/clusters/integrations/prometheus_health_check_service.rb
new file mode 100644
index 00000000000..cd06e59449c
--- /dev/null
+++ b/app/services/clusters/integrations/prometheus_health_check_service.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Integrations
+ class PrometheusHealthCheckService
+ include Gitlab::Utils::StrongMemoize
+ include Gitlab::Routing
+
+ def initialize(cluster)
+ @cluster = cluster
+ @logger = Gitlab::AppJsonLogger.build
+ end
+
+ def execute
+ raise 'Invalid cluster type. Only project types are allowed.' unless @cluster.project_type?
+
+ return unless prometheus_integration.enabled
+
+ project = @cluster.clusterable
+
+ @logger.info(
+ message: 'Prometheus health check',
+ cluster_id: @cluster.id,
+ newly_unhealthy: became_unhealthy?,
+ currently_healthy: currently_healthy?,
+ was_healthy: was_healthy?
+ )
+
+ send_notification(project) if became_unhealthy?
+
+ prometheus_integration.update_columns(health_status: current_health_status) if health_changed?
+ end
+
+ private
+
+ def prometheus_integration
+ strong_memoize(:prometheus_integration) do
+ @cluster.integration_prometheus
+ end
+ end
+
+ def current_health_status
+ if currently_healthy?
+ :healthy
+ else
+ :unhealthy
+ end
+ end
+
+ def currently_healthy?
+ strong_memoize(:currently_healthy) do
+ prometheus_integration.prometheus_client.healthy?
+ end
+ end
+
+ def became_unhealthy?
+ strong_memoize(:became_unhealthy) do
+ (was_healthy? || was_unknown?) && !currently_healthy?
+ end
+ end
+
+ def was_healthy?
+ strong_memoize(:was_healthy) do
+ prometheus_integration.healthy?
+ end
+ end
+
+ def was_unknown?
+ strong_memoize(:was_unknown) do
+ prometheus_integration.unknown?
+ end
+ end
+
+ def health_changed?
+ was_healthy? != currently_healthy?
+ end
+
+ def send_notification(project)
+ notification_payload = build_notification_payload(project)
+ integration = project.alert_management_http_integrations.active.first
+
+ Projects::Alerting::NotifyService.new(project, notification_payload).execute(integration&.token, integration)
+
+ @logger.info(message: 'Successfully notified of Prometheus newly unhealthy', cluster_id: @cluster.id, project_id: project.id)
+ end
+
+ def build_notification_payload(project)
+ cluster_path = namespace_project_cluster_path(
+ project_id: project.path,
+ namespace_id: project.namespace.path,
+ id: @cluster.id
+ )
+
+ {
+ title: "Prometheus is Unhealthy. Cluster Name: #{@cluster.name}",
+ description: "Prometheus is unhealthy for the cluster: [#{@cluster.name}](#{cluster_path}) attached to project #{project.name}."
+ }
+ end
+ end
+ end
+end
diff --git a/app/services/concerns/alert_management/responses.rb b/app/services/concerns/alert_management/responses.rb
new file mode 100644
index 00000000000..183a831a00a
--- /dev/null
+++ b/app/services/concerns/alert_management/responses.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module AlertManagement
+ # Module to hold common response logic for AlertManagement services.
+ module Responses
+ def success(alerts)
+ ServiceResponse.success(payload: { alerts: Array(alerts) })
+ end
+
+ def bad_request
+ ServiceResponse.error(message: 'Bad Request', http_status: :bad_request)
+ end
+
+ def unauthorized
+ ServiceResponse.error(message: 'Unauthorized', http_status: :unauthorized)
+ end
+
+ def unprocessable_entity
+ ServiceResponse.error(message: 'Unprocessable Entity', http_status: :unprocessable_entity)
+ end
+
+ def forbidden
+ ServiceResponse.error(message: 'Forbidden', http_status: :forbidden)
+ end
+ end
+end
diff --git a/app/services/concerns/issues/issue_type_helpers.rb b/app/services/concerns/issues/issue_type_helpers.rb
new file mode 100644
index 00000000000..44c20d20ff1
--- /dev/null
+++ b/app/services/concerns/issues/issue_type_helpers.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Issues
+ module IssueTypeHelpers
+ # @param object [Issue, Project]
+ # @param issue_type [String, Symbol]
+ def create_issue_type_allowed?(object, issue_type)
+ WorkItem::Type.base_types.key?(issue_type.to_s) &&
+ can?(current_user, :"create_#{issue_type}", object)
+ end
+ end
+end
diff --git a/app/services/concerns/members/bulk_create_users.rb b/app/services/concerns/members/bulk_create_users.rb
index 4498f40c396..b98917f1396 100644
--- a/app/services/concerns/members/bulk_create_users.rb
+++ b/app/services/concerns/members/bulk_create_users.rb
@@ -6,7 +6,7 @@ module Members
included do
class << self
- def add_users(source, users, access_level, current_user: nil, expires_at: nil)
+ def add_users(source, users, access_level, current_user: nil, expires_at: nil, tasks_to_be_done: [], tasks_project_id: nil)
return [] unless users.present?
emails, users, existing_members = parse_users_list(source, users)
@@ -18,7 +18,9 @@ module Members
access_level,
existing_members: existing_members,
current_user: current_user,
- expires_at: expires_at)
+ expires_at: expires_at,
+ tasks_to_be_done: tasks_to_be_done,
+ tasks_project_id: tasks_project_id)
.execute
end
end
diff --git a/app/services/customer_relations/contacts/base_service.rb b/app/services/customer_relations/contacts/base_service.rb
index 89f6f2c3f1f..1797e5021a1 100644
--- a/app/services/customer_relations/contacts/base_service.rb
+++ b/app/services/customer_relations/contacts/base_service.rb
@@ -6,7 +6,7 @@ module CustomerRelations
private
def allowed?
- current_user&.can?(:admin_contact, group)
+ current_user&.can?(:admin_crm_contact, group)
end
def error(message)
diff --git a/app/services/customer_relations/organizations/base_service.rb b/app/services/customer_relations/organizations/base_service.rb
index 8f8480d697c..9b4ccafcea6 100644
--- a/app/services/customer_relations/organizations/base_service.rb
+++ b/app/services/customer_relations/organizations/base_service.rb
@@ -6,7 +6,7 @@ module CustomerRelations
private
def allowed?
- current_user&.can?(:admin_organization, group)
+ current_user&.can?(:admin_crm_organization, group)
end
def error(message)
diff --git a/app/services/dependency_proxy/find_or_create_blob_service.rb b/app/services/dependency_proxy/find_or_create_blob_service.rb
index 0a6db6e3d34..1b43263a3ba 100644
--- a/app/services/dependency_proxy/find_or_create_blob_service.rb
+++ b/app/services/dependency_proxy/find_or_create_blob_service.rb
@@ -30,8 +30,7 @@ module DependencyProxy
blob.save!
end
- # Technical debt: change to read_at https://gitlab.com/gitlab-org/gitlab/-/issues/341536
- blob.touch if from_cache
+ blob.read! if from_cache
success(blob: blob, from_cache: from_cache)
end
diff --git a/app/services/dependency_proxy/find_or_create_manifest_service.rb b/app/services/dependency_proxy/find_or_create_manifest_service.rb
index 1976d4d47f4..aeb62be9f3a 100644
--- a/app/services/dependency_proxy/find_or_create_manifest_service.rb
+++ b/app/services/dependency_proxy/find_or_create_manifest_service.rb
@@ -14,18 +14,18 @@ module DependencyProxy
def execute
@manifest = @group.dependency_proxy_manifests
.active
- .find_or_initialize_by_file_name_or_digest(file_name: @file_name, digest: @tag)
+ .find_by_file_name_or_digest(file_name: @file_name, digest: @tag)
head_result = DependencyProxy::HeadManifestService.new(@image, @tag, @token).execute
- if cached_manifest_matches?(head_result)
- @manifest.touch
+ return respond if cached_manifest_matches?(head_result)
- return success(manifest: @manifest, from_cache: true)
+ if Feature.enabled?(:dependency_proxy_manifest_workhorse, @group, default_enabled: :yaml)
+ success(manifest: nil, from_cache: false)
+ else
+ pull_new_manifest
+ respond(from_cache: false)
end
-
- pull_new_manifest
- respond(from_cache: false)
rescue Timeout::Error, *Gitlab::HTTP::HTTP_ERRORS
respond
end
@@ -34,12 +34,19 @@ module DependencyProxy
def pull_new_manifest
DependencyProxy::PullManifestService.new(@image, @tag, @token).execute_with_manifest do |new_manifest|
- @manifest.update!(
+ params = {
+ file_name: @file_name,
content_type: new_manifest[:content_type],
digest: new_manifest[:digest],
file: new_manifest[:file],
size: new_manifest[:file].size
- )
+ }
+
+ if @manifest
+ @manifest.update!(params)
+ else
+ @manifest = @group.dependency_proxy_manifests.create!(params)
+ end
end
end
@@ -50,9 +57,8 @@ module DependencyProxy
end
def respond(from_cache: true)
- if @manifest.persisted?
- # Technical debt: change to read_at https://gitlab.com/gitlab-org/gitlab/-/issues/341536
- @manifest.touch if from_cache
+ if @manifest
+ @manifest.read!
success(manifest: @manifest, from_cache: from_cache)
else
diff --git a/app/services/dependency_proxy/head_manifest_service.rb b/app/services/dependency_proxy/head_manifest_service.rb
index ecc3eb77399..cd575b83a98 100644
--- a/app/services/dependency_proxy/head_manifest_service.rb
+++ b/app/services/dependency_proxy/head_manifest_service.rb
@@ -14,7 +14,10 @@ module DependencyProxy
response = Gitlab::HTTP.head(manifest_url, headers: auth_headers.merge(Accept: ACCEPT_HEADERS))
if response.success?
- success(digest: response.headers['docker-content-digest'], content_type: response.headers['content-type'])
+ success(
+ digest: response.headers[DependencyProxy::Manifest::DIGEST_HEADER],
+ content_type: response.headers['content-type']
+ )
else
error(response.body, response.code)
end
diff --git a/app/services/dependency_proxy/pull_manifest_service.rb b/app/services/dependency_proxy/pull_manifest_service.rb
index 31494773cc0..e8f0ad6374a 100644
--- a/app/services/dependency_proxy/pull_manifest_service.rb
+++ b/app/services/dependency_proxy/pull_manifest_service.rb
@@ -20,7 +20,13 @@ module DependencyProxy
file.write(response.body)
file.flush
- yield(success(file: file, digest: response.headers['docker-content-digest'], content_type: response.headers['content-type']))
+ yield(
+ success(
+ file: file,
+ digest: response.headers[DependencyProxy::Manifest::DIGEST_HEADER],
+ content_type: response.headers['content-type']
+ )
+ )
ensure
file.close
file.unlink
diff --git a/app/services/deployments/archive_in_project_service.rb b/app/services/deployments/archive_in_project_service.rb
new file mode 100644
index 00000000000..a593721f390
--- /dev/null
+++ b/app/services/deployments/archive_in_project_service.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Deployments
+ # This service archives old deploymets and deletes deployment refs for
+ # keeping the project repository performant.
+ class ArchiveInProjectService < ::BaseService
+ BATCH_SIZE = 100
+
+ def execute
+ unless ::Feature.enabled?(:deployments_archive, project, default_enabled: :yaml)
+ return error('Feature flag is not enabled')
+ end
+
+ deployments = Deployment.archivables_in(project, limit: BATCH_SIZE)
+
+ return success(result: :empty) if deployments.empty?
+
+ ids = deployments.map(&:id)
+ ref_paths = deployments.map(&:ref_path)
+
+ project.repository.delete_refs(*ref_paths)
+ project.deployments.id_in(ids).update_all(archived: true)
+
+ success(result: :archived, count: ids.count)
+ end
+ end
+end
diff --git a/app/services/deployments/link_merge_requests_service.rb b/app/services/deployments/link_merge_requests_service.rb
index 39fbef5dee2..40385418e48 100644
--- a/app/services/deployments/link_merge_requests_service.rb
+++ b/app/services/deployments/link_merge_requests_service.rb
@@ -16,7 +16,7 @@ module Deployments
# Review apps have the environment type set (e.g. to `review`, though the
# exact value may differ). We don't want to link merge requests to review
# app deployments, as this is not useful.
- return if deployment.environment.environment_type
+ return unless deployment.environment.should_link_to_merge_requests?
# This service is triggered by a Sidekiq worker, which only runs when a
# deployment is successful. We add an extra check here in case we ever
diff --git a/app/services/design_management/copy_design_collection/copy_service.rb b/app/services/design_management/copy_design_collection/copy_service.rb
index c43696442d2..5e557e9ea53 100644
--- a/app/services/design_management/copy_design_collection/copy_service.rb
+++ b/app/services/design_management/copy_design_collection/copy_service.rb
@@ -181,12 +181,12 @@ module DesignManagement
)
end
- # TODO Replace `Gitlab::Database.main.bulk_insert` with `BulkInsertSafe`
+ # TODO Replace `ApplicationRecord.legacy_bulk_insert` with `BulkInsertSafe`
# once https://gitlab.com/gitlab-org/gitlab/-/issues/247718 is fixed.
# When this is fixed, we can remove the call to
# `with_project_iid_supply` above, since the objects will be instantiated
# and callbacks (including `ensure_project_iid!`) will fire.
- ::Gitlab::Database.main.bulk_insert( # rubocop:disable Gitlab/BulkInsert
+ ::ApplicationRecord.legacy_bulk_insert( # rubocop:disable Gitlab/BulkInsert
DesignManagement::Design.table_name,
new_rows,
return_ids: true
@@ -207,9 +207,9 @@ module DesignManagement
)
end
- # TODO Replace `Gitlab::Database.main.bulk_insert` with `BulkInsertSafe`
+ # TODO Replace `ApplicationRecord.legacy_bulk_insert` with `BulkInsertSafe`
# once https://gitlab.com/gitlab-org/gitlab/-/issues/247718 is fixed.
- ::Gitlab::Database.main.bulk_insert( # rubocop:disable Gitlab/BulkInsert
+ ::ApplicationRecord.legacy_bulk_insert( # rubocop:disable Gitlab/BulkInsert
DesignManagement::Version.table_name,
new_rows,
return_ids: true
@@ -239,7 +239,7 @@ module DesignManagement
end
# We cannot use `BulkInsertSafe` because of the uploader mounted in `Action`.
- ::Gitlab::Database.main.bulk_insert( # rubocop:disable Gitlab/BulkInsert
+ ::ApplicationRecord.legacy_bulk_insert( # rubocop:disable Gitlab/BulkInsert
DesignManagement::Action.table_name,
new_rows
)
@@ -278,7 +278,7 @@ module DesignManagement
# We cannot use `BulkInsertSafe` due to the LfsObjectsProject#update_project_statistics
# callback that fires after_commit.
- ::Gitlab::Database.main.bulk_insert( # rubocop:disable Gitlab/BulkInsert
+ ::ApplicationRecord.legacy_bulk_insert( # rubocop:disable Gitlab/BulkInsert
LfsObjectsProject.table_name,
new_rows,
on_conflict: :do_nothing # Upsert
diff --git a/app/services/emails/destroy_service.rb b/app/services/emails/destroy_service.rb
index d10833e66cb..d211c3470b2 100644
--- a/app/services/emails/destroy_service.rb
+++ b/app/services/emails/destroy_service.rb
@@ -3,6 +3,8 @@
module Emails
class DestroyService < ::Emails::BaseService
def execute(email)
+ raise StandardError, 'Cannot delete primary email' if email.user_primary_email?
+
email.destroy && update_secondary_emails!(email.email)
end
diff --git a/app/services/error_tracking/collect_error_service.rb b/app/services/error_tracking/collect_error_service.rb
index 477453a693e..304e3898ee5 100644
--- a/app/services/error_tracking/collect_error_service.rb
+++ b/app/services/error_tracking/collect_error_service.rb
@@ -15,7 +15,7 @@ module ErrorTracking
)
# The payload field contains all the data on error including stacktrace in jsonb.
- # Together with occured_at these are 2 main attributes that we need to save here.
+ # Together with occurred_at these are 2 main attributes that we need to save here.
error.events.create!(
environment: event['environment'],
description: exception['value'],
@@ -28,7 +28,18 @@ module ErrorTracking
private
def event
- params[:event]
+ @event ||= format_event(params[:event])
+ end
+
+ def format_event(event)
+ # Some SDK send exception payload as Array. For exmple Go lang SDK.
+ # We need to convert it to hash format we expect.
+ if event['exception'].is_a?(Array)
+ exception = event['exception']
+ event['exception'] = { 'values' => exception }
+ end
+
+ event
end
def exception
diff --git a/app/services/google_cloud/service_accounts_service.rb b/app/services/google_cloud/service_accounts_service.rb
new file mode 100644
index 00000000000..29ed69693b0
--- /dev/null
+++ b/app/services/google_cloud/service_accounts_service.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module GoogleCloud
+ ##
+ # GCP keys used to store Google Cloud Service Accounts
+ GCP_KEYS = %w[GCP_PROJECT_ID GCP_SERVICE_ACCOUNT GCP_SERVICE_ACCOUNT_KEY].freeze
+
+ ##
+ # This service deals with GCP Service Accounts in GitLab
+
+ class ServiceAccountsService < ::BaseService
+ ##
+ # Find GCP Service Accounts in a GitLab project
+ #
+ # This method looks up GitLab project's CI vars
+ # and returns Google Cloud Service Accounts combinations
+ # aligning GitLab project and environment to GCP projects
+
+ def find_for_project
+ group_vars_by_environment.map do |environment_scope, value|
+ {
+ environment: environment_scope,
+ gcp_project: value['GCP_PROJECT_ID'],
+ service_account_exists: value['GCP_SERVICE_ACCOUNT'].present?,
+ service_account_key_exists: value['GCP_SERVICE_ACCOUNT_KEY'].present?
+ }
+ end
+ end
+
+ private
+
+ def group_vars_by_environment
+ filtered_vars = @project.variables.filter { |variable| GCP_KEYS.include? variable.key }
+ filtered_vars.each_with_object({}) do |variable, grouped|
+ grouped[variable.environment_scope] ||= {}
+ grouped[variable.environment_scope][variable.key] = variable.value
+ end
+ end
+ end
+end
diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb
index f900927793a..da3cebc2e6d 100644
--- a/app/services/groups/create_service.rb
+++ b/app/services/groups/create_service.rb
@@ -6,6 +6,7 @@ module Groups
@current_user = user
@params = params.dup
@chat_team = @params.delete(:create_chat_team)
+ @create_event = @params.delete(:create_event)
end
def execute
@@ -42,15 +43,26 @@ module Groups
end
end
+ after_create_hook
+
@group
end
private
+ attr_reader :create_event
+
def after_build_hook(group, params)
# overridden in EE
end
+ def after_create_hook
+ if group.persisted? && group.root?
+ delay = Namespaces::InviteTeamEmailService::DELIVERY_DELAY_IN_MINUTES
+ Namespaces::InviteTeamEmailWorker.perform_in(delay, group.id, current_user.id)
+ end
+ end
+
def remove_unallowed_params
params.delete(:default_branch_protection) unless can?(current_user, :create_group_with_default_branch_protection)
params.delete(:allow_mfa_for_subgroups)
diff --git a/app/services/groups/import_export/import_service.rb b/app/services/groups/import_export/import_service.rb
index f9db552f743..c8c2124078d 100644
--- a/app/services/groups/import_export/import_service.rb
+++ b/app/services/groups/import_export/import_service.rb
@@ -14,7 +14,7 @@ module Groups
def async_execute
group_import_state = GroupImportState.safe_find_or_create_by!(group: group, user: current_user)
- jid = GroupImportWorker.perform_async(current_user.id, group.id)
+ jid = GroupImportWorker.with_status.perform_async(current_user.id, group.id)
if jid.present?
group_import_state.update!(jid: jid)
diff --git a/app/services/groups/transfer_service.rb b/app/services/groups/transfer_service.rb
index 334083a859f..cd89eb799dc 100644
--- a/app/services/groups/transfer_service.rb
+++ b/app/services/groups/transfer_service.rb
@@ -175,21 +175,18 @@ module Groups
end
def refresh_project_authorizations
- ProjectAuthorization.where(project_id: @group.all_projects.select(:id)).delete_all # rubocop: disable CodeReuse/ActiveRecord
+ projects_to_update = Set.new
- # refresh authorized projects for current_user immediately
- current_user.refresh_authorized_projects
-
- # schedule refreshing projects for all the members of the group
- @group.refresh_members_authorized_projects
+ # All projects in this hierarchy need to have their project authorizations recalculated
+ @group.all_projects.each_batch { |prjs| projects_to_update.merge(prjs.ids) } # rubocop: disable CodeReuse/ActiveRecord
# When a group is transferred, it also affects who gets access to the projects shared to
# the subgroups within its hierarchy, so we also schedule jobs that refresh authorizations for all such shared projects.
- project_group_shares_within_the_hierarchy = ProjectGroupLink.in_group(group.self_and_descendants.select(:id))
-
- project_group_shares_within_the_hierarchy.find_each do |project_group_link|
- AuthorizedProjectUpdate::ProjectRecalculateWorker.perform_async(project_group_link.project_id)
+ ProjectGroupLink.in_group(@group.self_and_descendants.select(:id)).each_batch do |project_group_links|
+ projects_to_update.merge(project_group_links.pluck(:project_id)) # rubocop: disable CodeReuse/ActiveRecord
end
+
+ AuthorizedProjectUpdate::ProjectAccessChangedService.new(projects_to_update.to_a).execute unless projects_to_update.empty?
end
def raise_transfer_error(message)
@@ -199,7 +196,7 @@ module Groups
def localized_error_messages
{
database_not_supported: s_('TransferGroup|Database is not supported.'),
- namespace_with_same_path: s_('TransferGroup|The parent group already has a subgroup with the same path.'),
+ namespace_with_same_path: s_('TransferGroup|The parent group already has a subgroup or a project with the same path.'),
group_is_already_root: s_('TransferGroup|Group is already a root group.'),
same_parent_as_current: s_('TransferGroup|Group is already associated to the parent group.'),
invalid_policies: s_("TransferGroup|You don't have enough permissions."),
diff --git a/app/services/import/github/notes/create_service.rb b/app/services/import/github/notes/create_service.rb
new file mode 100644
index 00000000000..79145f42313
--- /dev/null
+++ b/app/services/import/github/notes/create_service.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Import
+ module Github
+ module Notes
+ class CreateService < ::Notes::CreateService
+ # Github does not have support to quick actions in notes (like /assign)
+ # Therefore, when importing notes we skip the quick actions processing
+ def quick_actions_supported?(_note)
+ false
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/issuable/clone/attributes_rewriter.rb b/app/services/issuable/clone/attributes_rewriter.rb
index d8b639bb422..279d3051848 100644
--- a/app/services/issuable/clone/attributes_rewriter.rb
+++ b/app/services/issuable/clone/attributes_rewriter.rb
@@ -99,7 +99,7 @@ module Issuable
yield(event)
end.compact
- Gitlab::Database.main.bulk_insert(table_name, events) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(table_name, events) # rubocop:disable Gitlab/BulkInsert
end
end
diff --git a/app/services/issuable_links/list_service.rb b/app/services/issuable_links/list_service.rb
index fe9678dcc32..cc41a65379a 100644
--- a/app/services/issuable_links/list_service.rb
+++ b/app/services/issuable_links/list_service.rb
@@ -12,11 +12,16 @@ module IssuableLinks
end
def execute
- serializer.new(current_user: current_user, issuable: issuable).represent(child_issuables)
+ serializer.new(current_user: current_user, issuable: issuable)
+ .represent(child_issuables, serializer_options)
end
private
+ def serializer_options
+ {}
+ end
+
def serializer
raise NotImplementedError
end
diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb
index 6dce9fd6e73..efb5de5b17c 100644
--- a/app/services/issues/base_service.rb
+++ b/app/services/issues/base_service.rb
@@ -3,6 +3,7 @@
module Issues
class BaseService < ::IssuableBaseService
include IncidentManagement::UsageData
+ include IssueTypeHelpers
def hook_data(issue, action, old_associations: {})
hook_data = issue.to_hook_data(current_user, old_associations: old_associations)
@@ -44,7 +45,7 @@ module Issues
def filter_params(issue)
super
- params.delete(:issue_type) unless issue_type_allowed?(issue)
+ params.delete(:issue_type) unless create_issue_type_allowed?(issue, params[:issue_type])
filter_incident_label(issue) if params[:issue_type]
moved_issue = params.delete(:moved_issue)
@@ -89,12 +90,6 @@ module Issues
Milestones::IssuesCountService.new(milestone).delete_cache
end
- # @param object [Issue, Project]
- def issue_type_allowed?(object)
- WorkItem::Type.base_types.key?(params[:issue_type]) &&
- can?(current_user, :"create_#{params[:issue_type]}", object)
- end
-
# @param issue [Issue]
def filter_incident_label(issue)
return unless add_incident_label?(issue) || remove_incident_label?(issue)
diff --git a/app/services/issues/build_service.rb b/app/services/issues/build_service.rb
index 7fdc8daf15c..8fd844c4886 100644
--- a/app/services/issues/build_service.rb
+++ b/app/services/issues/build_service.rb
@@ -80,7 +80,7 @@ module Issues
]
allowed_params << :milestone_id if can?(current_user, :admin_issue, project)
- allowed_params << :issue_type if issue_type_allowed?(project)
+ allowed_params << :issue_type if create_issue_type_allowed?(project, params[:issue_type])
params.slice(*allowed_params)
end
diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb
index ac846c769a3..65f143d0b21 100644
--- a/app/services/issues/close_service.rb
+++ b/app/services/issues/close_service.rb
@@ -62,6 +62,7 @@ module Issues
def perform_incident_management_actions(issue)
resolve_alert(issue)
+ resolve_incident(issue)
end
def close_external_issue(issue, closed_via)
@@ -91,6 +92,14 @@ module Issues
end
end
+ def resolve_incident(issue)
+ return unless issue.incident?
+
+ status = issue.incident_management_issuable_escalation_status || issue.build_incident_management_issuable_escalation_status
+
+ SystemNoteService.resolve_incident_status(issue, current_user) if status.resolve
+ end
+
def store_first_mentioned_in_commit_at(issue, merge_request, max_commit_lookup: 100)
metrics = issue.metrics
return if metrics.nil? || metrics.first_mentioned_in_commit_at
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index fcedd1c1c8d..fa8d380404b 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -6,7 +6,7 @@ module Issues
prepend RateLimitedService
rate_limit key: :issues_create,
- opts: { scope: [:project, :current_user], users_allowlist: -> { [User.support_bot.username] } }
+ opts: { scope: [:project, :current_user, :external_author] }
# NOTE: For Issues::CreateService, we require the spam_params and do not default it to nil, because
# spam_checking is likely to be necessary. However, if there is not a request available in scope
@@ -25,6 +25,10 @@ module Issues
create(@issue, skip_system_notes: skip_system_notes)
end
+ def external_author
+ params[:external_author] # present when creating an issue using service desk (email: from)
+ end
+
def before_create(issue)
Spam::SpamActionService.new(
spammable: issue,
diff --git a/app/services/issues/set_crm_contacts_service.rb b/app/services/issues/set_crm_contacts_service.rb
new file mode 100644
index 00000000000..13fe30b5ac8
--- /dev/null
+++ b/app/services/issues/set_crm_contacts_service.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+module Issues
+ class SetCrmContactsService < ::BaseProjectService
+ attr_accessor :issue, :errors
+
+ MAX_ADDITIONAL_CONTACTS = 6
+
+ def execute(issue)
+ @issue = issue
+ @errors = []
+
+ return error_no_permissions unless allowed?
+ return error_invalid_params unless valid_params?
+
+ determine_changes if params[:crm_contact_ids]
+
+ return error_too_many if too_many?
+
+ add_contacts if params[:add_crm_contact_ids]
+ remove_contacts if params[:remove_crm_contact_ids]
+
+ if issue.valid?
+ ServiceResponse.success(payload: issue)
+ else
+ # The default error isn't very helpful: "Issue customer relations contacts is invalid"
+ issue.errors.delete(:issue_customer_relations_contacts)
+ issue.errors.add(:issue_customer_relations_contacts, errors.to_sentence)
+ ServiceResponse.error(payload: issue, message: issue.errors.full_messages)
+ end
+ end
+
+ private
+
+ def determine_changes
+ existing_contact_ids = issue.issue_customer_relations_contacts.map(&:contact_id)
+ params[:add_crm_contact_ids] = params[:crm_contact_ids] - existing_contact_ids
+ params[:remove_crm_contact_ids] = existing_contact_ids - params[:crm_contact_ids]
+ end
+
+ def add_contacts
+ params[:add_crm_contact_ids].uniq.each do |contact_id|
+ issue_contact = issue.issue_customer_relations_contacts.create(contact_id: contact_id)
+
+ unless issue_contact.persisted?
+ # The validation ensures that the id exists and the user has permission
+ errors << "#{contact_id}: The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ end
+ end
+ end
+
+ def remove_contacts
+ issue.issue_customer_relations_contacts
+ .where(contact_id: params[:remove_crm_contact_ids]) # rubocop: disable CodeReuse/ActiveRecord
+ .delete_all
+ end
+
+ def allowed?
+ current_user&.can?(:set_issue_crm_contacts, issue)
+ end
+
+ def valid_params?
+ set_present? ^ add_or_remove_present?
+ end
+
+ def set_present?
+ params[:crm_contact_ids].present?
+ end
+
+ def add_or_remove_present?
+ params[:add_crm_contact_ids].present? || params[:remove_crm_contact_ids].present?
+ end
+
+ def too_many?
+ params[:add_crm_contact_ids] && params[:add_crm_contact_ids].length > MAX_ADDITIONAL_CONTACTS
+ end
+
+ def error_no_permissions
+ ServiceResponse.error(message: ['You have insufficient permissions to set customer relations contacts for this issue'])
+ end
+
+ def error_invalid_params
+ ServiceResponse.error(message: ['You cannot combine crm_contact_ids with add_crm_contact_ids or remove_crm_contact_ids'])
+ end
+
+ def error_too_many
+ ServiceResponse.error(payload: issue, message: ["You can only add up to #{MAX_ADDITIONAL_CONTACTS} contacts at one time"])
+ end
+ end
+end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index d120b007af2..824a609dfb9 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -80,7 +80,7 @@ module Issues
todo_service.reassigned_assignable(issue, current_user, old_assignees)
track_incident_action(current_user, issue, :incident_assigned)
- if Gitlab::ActionCable::Config.in_app? || Feature.enabled?(:broadcast_issue_updates, issue.project)
+ if Feature.enabled?(:broadcast_issue_updates, issue.project, default_enabled: :yaml)
GraphqlTriggers.issuable_assignees_updated(issue)
end
end
diff --git a/app/services/jira/requests/base.rb b/app/services/jira/requests/base.rb
index 56484075d08..a16f8bbd367 100644
--- a/app/services/jira/requests/base.rb
+++ b/app/services/jira/requests/base.rb
@@ -67,9 +67,19 @@ module Jira
ServiceResponse.error(message: error_message(e))
end
+ def auth_docs_link_start
+ auth_docs_link_url = Rails.application.routes.url_helpers.help_page_path('integration/jira', anchor: 'authentication-in-jira')
+ '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: auth_docs_link_url }
+ end
+
+ def config_docs_link_start
+ config_docs_link_url = Rails.application.routes.url_helpers.help_page_path('integration/jira/configure')
+ '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: config_docs_link_url }
+ end
+
def error_message(error)
reportable_error_message(error) ||
- s_('JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again.')
+ s_('JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again.').html_safe % { docs_link_start: config_docs_link_start, docs_link_end: '</a>'.html_safe }
end
# Returns a user-facing error message if possible, otherwise `nil`.
@@ -93,11 +103,11 @@ module Jira
def reportable_jira_ruby_error_message(error)
case error.message
when 'Unauthorized'
- s_('JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again.')
+ s_('JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again.').html_safe % { docs_link_start: auth_docs_link_start, docs_link_end: '</a>'.html_safe }
when 'Forbidden'
- s_('JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again.')
+ s_('JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again.').html_safe % { docs_link_start: auth_docs_link_start, docs_link_end: '</a>'.html_safe }
when 'Bad Request'
- s_('JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again.')
+ s_('JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again.').html_safe % { docs_link_start: config_docs_link_start, docs_link_end: '</a>'.html_safe }
when /errorMessages/
jira_ruby_json_error_message(error.message)
end
@@ -111,7 +121,7 @@ module Jira
messages = Rails::Html::FullSanitizer.new.sanitize(messages).presence
return unless messages
- s_('JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again.') % { messages: messages }
+ s_('JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again.').html_safe % { messages: messages, docs_link_start: config_docs_link_start, docs_link_end: '</a>'.html_safe }
rescue JSON::ParserError
end
end
diff --git a/app/services/labels/transfer_service.rb b/app/services/labels/transfer_service.rb
index a05090d6bfb..19d419609a5 100644
--- a/app/services/labels/transfer_service.rb
+++ b/app/services/labels/transfer_service.rb
@@ -50,21 +50,32 @@ module Labels
# rubocop: disable CodeReuse/ActiveRecord
def group_labels_applied_to_issues
- @group_labels_applied_to_issues ||= Label.joins(:issues)
- .where(
- issues: { project_id: project.id },
- labels: { group_id: old_group.self_and_ancestors }
- )
+ @labels_applied_to_issues ||= if use_optimized_group_labels_query?
+ Label.joins(:issues)
+ .joins("INNER JOIN namespaces on namespaces.id = labels.group_id AND namespaces.type = 'Group'" )
+ .where(issues: { project_id: project.id }).reorder(nil)
+ else
+ Label.joins(:issues).where(
+ issues: { project_id: project.id },
+ labels: { group_id: old_group.self_and_ancestors }
+ )
+ end
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def group_labels_applied_to_merge_requests
- @group_labels_applied_to_merge_requests ||= Label.joins(:merge_requests)
- .where(
- merge_requests: { target_project_id: project.id },
- labels: { group_id: old_group.self_and_ancestors }
- )
+ @labels_applied_to_mrs ||= if use_optimized_group_labels_query?
+ Label.joins(:merge_requests)
+ .joins("INNER JOIN namespaces on namespaces.id = labels.group_id AND namespaces.type = 'Group'" )
+ .where(merge_requests: { target_project_id: project.id }).reorder(nil)
+ else
+ Label.joins(:merge_requests)
+ .where(
+ merge_requests: { target_project_id: project.id },
+ labels: { group_id: old_group.self_and_ancestors }
+ )
+ end
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -88,5 +99,9 @@ module Labels
.update_all(label_id: new_label_id)
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def use_optimized_group_labels_query?
+ Feature.enabled?(:use_optimized_group_labels_query, project.root_namespace, default_enabled: :yaml)
+ end
end
end
diff --git a/app/services/loose_foreign_keys/batch_cleaner_service.rb b/app/services/loose_foreign_keys/batch_cleaner_service.rb
new file mode 100644
index 00000000000..06c05e8ff54
--- /dev/null
+++ b/app/services/loose_foreign_keys/batch_cleaner_service.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module LooseForeignKeys
+ class BatchCleanerService
+ def initialize(parent_klass:, deleted_parent_records:, modification_tracker: LooseForeignKeys::ModificationTracker.new, models_by_table_name:)
+ @parent_klass = parent_klass
+ @deleted_parent_records = deleted_parent_records
+ @modification_tracker = modification_tracker
+ @models_by_table_name = models_by_table_name
+ @deleted_records_counter = Gitlab::Metrics.counter(
+ :loose_foreign_key_processed_deleted_records,
+ 'The number of processed loose foreign key deleted records'
+ )
+ end
+
+ def execute
+ parent_klass.loose_foreign_key_definitions.each do |foreign_key_definition|
+ run_cleaner_service(foreign_key_definition, with_skip_locked: true)
+ break if modification_tracker.over_limit?
+
+ run_cleaner_service(foreign_key_definition, with_skip_locked: false)
+ break if modification_tracker.over_limit?
+ end
+
+ return if modification_tracker.over_limit?
+
+ # At this point, all associations are cleaned up, we can update the status of the parent records
+ update_count = LooseForeignKeys::DeletedRecord.mark_records_processed(deleted_parent_records)
+
+ deleted_records_counter.increment({ table: parent_klass.table_name, db_config_name: LooseForeignKeys::DeletedRecord.connection.pool.db_config.name }, update_count)
+ end
+
+ private
+
+ attr_reader :parent_klass, :deleted_parent_records, :modification_tracker, :models_by_table_name, :deleted_records_counter
+
+ def record_result(cleaner, result)
+ if cleaner.async_delete?
+ modification_tracker.add_deletions(result[:table], result[:affected_rows])
+ elsif cleaner.async_nullify?
+ modification_tracker.add_updates(result[:table], result[:affected_rows])
+ end
+ end
+
+ def run_cleaner_service(foreign_key_definition, with_skip_locked:)
+ cleaner = CleanerService.new(
+ model: models_by_table_name.fetch(foreign_key_definition.to_table),
+ foreign_key_definition: foreign_key_definition,
+ deleted_parent_records: deleted_parent_records,
+ with_skip_locked: with_skip_locked
+ )
+
+ loop do
+ result = cleaner.execute
+ record_result(cleaner, result)
+
+ break if modification_tracker.over_limit? || result[:affected_rows] == 0
+ end
+ end
+ end
+end
diff --git a/app/services/loose_foreign_keys/cleaner_service.rb b/app/services/loose_foreign_keys/cleaner_service.rb
new file mode 100644
index 00000000000..8fe053e2edf
--- /dev/null
+++ b/app/services/loose_foreign_keys/cleaner_service.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+module LooseForeignKeys
+ # rubocop: disable CodeReuse/ActiveRecord
+ class CleanerService
+ DELETE_LIMIT = 1000
+ UPDATE_LIMIT = 500
+
+ delegate :connection, to: :model
+
+ def initialize(model:, foreign_key_definition:, deleted_parent_records:, with_skip_locked: false)
+ @model = model
+ @foreign_key_definition = foreign_key_definition
+ @deleted_parent_records = deleted_parent_records
+ @with_skip_locked = with_skip_locked
+ end
+
+ def execute
+ result = connection.execute(build_query)
+
+ { affected_rows: result.cmd_tuples, table: foreign_key_definition.to_table }
+ end
+
+ def async_delete?
+ foreign_key_definition.on_delete == :async_delete
+ end
+
+ def async_nullify?
+ foreign_key_definition.on_delete == :async_nullify
+ end
+
+ private
+
+ attr_reader :model, :foreign_key_definition, :deleted_parent_records, :with_skip_locked
+
+ def build_query
+ query = if async_delete?
+ delete_query
+ elsif async_nullify?
+ update_query
+ else
+ raise "Invalid on_delete argument: #{foreign_key_definition.on_delete}"
+ end
+
+ unless query.include?(%{"#{foreign_key_definition.column}" IN (})
+ raise("FATAL: foreign key condition is missing from the generated query: #{query}")
+ end
+
+ query
+ end
+
+ def arel_table
+ @arel_table ||= model.arel_table
+ end
+
+ def primary_keys
+ @primary_keys ||= connection.primary_keys(model.table_name).map { |key| arel_table[key] }
+ end
+
+ def quoted_table_name
+ @quoted_table_name ||= Arel.sql(connection.quote_table_name(model.table_name))
+ end
+
+ def delete_query
+ query = Arel::DeleteManager.new
+ query.from(quoted_table_name)
+
+ add_in_query_with_limit(query, DELETE_LIMIT)
+ end
+
+ def update_query
+ query = Arel::UpdateManager.new
+ query.table(quoted_table_name)
+ query.set([[arel_table[foreign_key_definition.column], nil]])
+
+ add_in_query_with_limit(query, UPDATE_LIMIT)
+ end
+
+ # IN query with one or composite primary key
+ # WHERE (primary_key1, primary_key2) IN (subselect)
+ def add_in_query_with_limit(query, limit)
+ columns = Arel::Nodes::Grouping.new(primary_keys)
+ query.where(columns.in(in_query_with_limit(limit))).to_sql
+ end
+
+ # Builds the following sub-query
+ # SELECT primary_keys FROM table WHERE foreign_key IN (1, 2, 3) LIMIT N
+ def in_query_with_limit(limit)
+ in_query = Arel::SelectManager.new
+ in_query.from(quoted_table_name)
+ in_query.where(arel_table[foreign_key_definition.column].in(deleted_parent_records.map(&:primary_key_value)))
+ in_query.projections = primary_keys
+ in_query.take(limit)
+ in_query.lock(Arel.sql('FOR UPDATE SKIP LOCKED')) if with_skip_locked
+ in_query
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+end
diff --git a/app/services/loose_foreign_keys/process_deleted_records_service.rb b/app/services/loose_foreign_keys/process_deleted_records_service.rb
new file mode 100644
index 00000000000..735fc8a2415
--- /dev/null
+++ b/app/services/loose_foreign_keys/process_deleted_records_service.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+module LooseForeignKeys
+ class ProcessDeletedRecordsService
+ BATCH_SIZE = 1000
+
+ def initialize(connection:)
+ @connection = connection
+ end
+
+ def execute
+ modification_tracker = ModificationTracker.new
+
+ tracked_tables.cycle do |table|
+ records = load_batch_for_table(table)
+
+ if records.empty?
+ tracked_tables.delete(table)
+ next
+ end
+
+ break if modification_tracker.over_limit?
+
+ model = find_parent_model!(table)
+
+ LooseForeignKeys::BatchCleanerService
+ .new(parent_klass: model,
+ deleted_parent_records: records,
+ modification_tracker: modification_tracker,
+ models_by_table_name: models_by_table_name)
+ .execute
+
+ break if modification_tracker.over_limit?
+ end
+
+ modification_tracker.stats
+ end
+
+ private
+
+ attr_reader :connection
+
+ def load_batch_for_table(table)
+ fully_qualified_table_name = "#{current_schema}.#{table}"
+ LooseForeignKeys::DeletedRecord.load_batch_for_table(fully_qualified_table_name, BATCH_SIZE)
+ end
+
+ def find_parent_model!(table)
+ models_by_table_name.fetch(table)
+ end
+
+ def current_schema
+ @current_schema = connection.current_schema
+ end
+
+ def tracked_tables
+ @tracked_tables ||= models_by_table_name
+ .select { |table_name, model| model.respond_to?(:loose_foreign_key_definitions) }
+ .keys
+ end
+
+ def models_by_table_name
+ @models_by_table_name ||= begin
+ all_models
+ .select(&:base_class?)
+ .index_by(&:table_name)
+ end
+ end
+
+ def all_models
+ ApplicationRecord.descendants
+ end
+ end
+end
diff --git a/app/services/members/create_service.rb b/app/services/members/create_service.rb
index 0cc62e661a3..cb905e01613 100644
--- a/app/services/members/create_service.rb
+++ b/app/services/members/create_service.rb
@@ -63,10 +63,14 @@ module Members
invites,
params[:access_level],
expires_at: params[:expires_at],
- current_user: current_user
+ current_user: current_user,
+ tasks_to_be_done: params[:tasks_to_be_done],
+ tasks_project_id: params[:tasks_project_id]
)
members.each { |member| process_result(member) }
+
+ create_tasks_to_be_done
end
def process_result(member)
@@ -112,6 +116,19 @@ module Members
end
end
+ def create_tasks_to_be_done
+ return unless experiment(:invite_members_for_task).enabled?
+ return if params[:tasks_to_be_done].blank? || params[:tasks_project_id].blank?
+
+ valid_members = members.select { |member| member.valid? && member.member_task.valid? }
+ return unless valid_members.present?
+
+ # We can take the first `member_task` here, since all tasks will have the same attributes needed
+ # for the `TasksToBeDone::CreateWorker`, ie. `project` and `tasks_to_be_done`.
+ member_task = valid_members[0].member_task
+ TasksToBeDone::CreateWorker.perform_async(member_task.id, current_user.id, valid_members.map(&:user_id))
+ end
+
def areas_of_focus
params[:areas_of_focus] || []
end
diff --git a/app/services/members/creator_service.rb b/app/services/members/creator_service.rb
index 7b0bebff760..f2c8a6f20a1 100644
--- a/app/services/members/creator_service.rb
+++ b/app/services/members/creator_service.rb
@@ -4,6 +4,8 @@ module Members
# This class serves as more of an app-wide way we add/create members
# All roads to add members should take this path.
class CreatorService
+ include Gitlab::Experiment::Dsl
+
class << self
def parsed_access_level(access_level)
access_levels.fetch(access_level) { access_level.to_i }
@@ -24,6 +26,7 @@ module Members
def execute
find_or_build_member
update_member
+ create_member_task
member
end
@@ -61,6 +64,21 @@ module Members
}
end
+ def create_member_task
+ return unless experiment(:invite_members_for_task).enabled?
+ return unless member.persisted?
+ return if member_task_attributes.value?(nil)
+
+ member.create_member_task(member_task_attributes)
+ end
+
+ def member_task_attributes
+ {
+ tasks_to_be_done: args[:tasks_to_be_done],
+ project_id: args[:tasks_project_id]
+ }
+ end
+
def approve_request
::Members::ApproveAccessRequestService.new(current_user,
access_level: access_level)
diff --git a/app/services/members/invite_service.rb b/app/services/members/invite_service.rb
index 257a986b8dd..85acb720f0f 100644
--- a/app/services/members/invite_service.rb
+++ b/app/services/members/invite_service.rb
@@ -39,6 +39,11 @@ module Members
errors[invite_email(member)] = member.errors.full_messages.to_sentence
end
+ override :create_tasks_to_be_done
+ def create_tasks_to_be_done
+ # Only create task issues for existing users. Tasks for new users are created when they signup.
+ end
+
def invite_email(member)
member.invite_email || member.user.email
end
diff --git a/app/services/merge_requests/outdated_discussion_diff_lines_service.rb b/app/services/merge_requests/outdated_discussion_diff_lines_service.rb
new file mode 100644
index 00000000000..a2de5a32963
--- /dev/null
+++ b/app/services/merge_requests/outdated_discussion_diff_lines_service.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class OutdatedDiscussionDiffLinesService
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :project, :note
+
+ OVERFLOW_LINES_COUNT = 2
+
+ def initialize(project:, note:)
+ @project = project
+ @note = note
+ end
+
+ def execute
+ end_position = position.line_range["end"]
+ diff_line_index = diff_lines.find_index do |l|
+ if end_position["new_line"]
+ l.new_line == end_position["new_line"]
+ elsif end_position["old_line"]
+ l.old_line == end_position["old_line"]
+ end
+ end
+ initial_line_index = [diff_line_index - OVERFLOW_LINES_COUNT, 0].max
+ last_line_index = [diff_line_index + OVERFLOW_LINES_COUNT, diff_lines.length].min
+
+ prev_lines = []
+
+ diff_lines[initial_line_index..last_line_index].each do |line|
+ if line.meta?
+ prev_lines.clear
+ else
+ prev_lines << line
+ end
+ end
+
+ prev_lines
+ end
+
+ private
+
+ def position
+ note.change_position
+ end
+
+ def repository
+ project.repository
+ end
+
+ def diff_file
+ position.diff_file(repository)
+ end
+
+ def diff_lines
+ strong_memoize(:diff_lines) do
+ diff_file.highlighted_diff_lines
+ end
+ end
+ end
+end
diff --git a/app/services/merge_requests/retarget_chain_service.rb b/app/services/merge_requests/retarget_chain_service.rb
index dab6e198979..33aae4184ae 100644
--- a/app/services/merge_requests/retarget_chain_service.rb
+++ b/app/services/merge_requests/retarget_chain_service.rb
@@ -5,8 +5,6 @@ module MergeRequests
MAX_RETARGET_MERGE_REQUESTS = 4
def execute(merge_request)
- return unless Feature.enabled?(:retarget_merge_requests, merge_request.target_project, default_enabled: :yaml)
-
# we can only retarget MRs that are targeting the same project
return unless merge_request.for_same_project? && merge_request.merged?
diff --git a/app/services/merge_requests/toggle_attention_requested_service.rb b/app/services/merge_requests/toggle_attention_requested_service.rb
new file mode 100644
index 00000000000..66c5d6fce5d
--- /dev/null
+++ b/app/services/merge_requests/toggle_attention_requested_service.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class ToggleAttentionRequestedService < MergeRequests::BaseService
+ attr_accessor :merge_request, :user
+
+ def initialize(project:, current_user:, merge_request:, user:)
+ super(project: project, current_user: current_user)
+
+ @merge_request = merge_request
+ @user = user
+ end
+
+ def execute
+ return error("Invalid permissions") unless can?(current_user, :update_merge_request, merge_request)
+
+ if reviewer || assignee
+ update_state(reviewer)
+ update_state(assignee)
+
+ if reviewer&.attention_requested? || assignee&.attention_requested?
+ notity_user
+ end
+
+ success
+ else
+ error("User is not a reviewer or assignee of the merge request")
+ end
+ end
+
+ private
+
+ def notity_user
+ todo_service.create_attention_requested_todo(merge_request, current_user, user)
+ end
+
+ def assignee
+ merge_request.find_assignee(user)
+ end
+
+ def reviewer
+ merge_request.find_reviewer(user)
+ end
+
+ def update_state(reviewer_or_assignee)
+ reviewer_or_assignee&.update(state: reviewer_or_assignee&.attention_requested? ? :reviewed : :attention_requested)
+ end
+ end
+end
diff --git a/app/services/namespaces/in_product_marketing_email_records.rb b/app/services/namespaces/in_product_marketing_email_records.rb
new file mode 100644
index 00000000000..1237a05ea13
--- /dev/null
+++ b/app/services/namespaces/in_product_marketing_email_records.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Namespaces
+ class InProductMarketingEmailRecords
+ attr_reader :records
+
+ def initialize
+ @records = []
+ end
+
+ def save!
+ Users::InProductMarketingEmail.bulk_insert!(@records)
+ @records = []
+ end
+
+ def add(user, track, series)
+ @records << Users::InProductMarketingEmail.new(
+ user: user,
+ track: track,
+ series: series,
+ created_at: Time.zone.now,
+ updated_at: Time.zone.now
+ )
+ end
+ end
+end
diff --git a/app/services/namespaces/in_product_marketing_emails_service.rb b/app/services/namespaces/in_product_marketing_emails_service.rb
index 0401653cf3c..90900698e1a 100644
--- a/app/services/namespaces/in_product_marketing_emails_service.rb
+++ b/app/services/namespaces/in_product_marketing_emails_service.rb
@@ -56,7 +56,7 @@ module Namespaces
def initialize(track, interval)
@track = track
@interval = interval
- @in_product_marketing_email_records = []
+ @sent_email_records = InProductMarketingEmailRecords.new
end
def execute
@@ -71,17 +71,21 @@ module Namespaces
private
- attr_reader :track, :interval, :in_product_marketing_email_records
+ attr_reader :track, :interval, :sent_email_records
+
+ def send_email(user, group)
+ NotificationService.new.in_product_marketing(user.id, group.id, track, series)
+ end
def send_email_for_group(group)
users_for_group(group).each do |user|
if can_perform_action?(user, group)
send_email(user, group)
- track_sent_email(user, track, series)
+ sent_email_records.add(user, track, series)
end
end
- save_tracked_emails!
+ sent_email_records.save!
end
def groups_for_track
@@ -126,10 +130,6 @@ module Namespaces
end
end
- def send_email(user, group)
- NotificationService.new.in_product_marketing(user.id, group.id, track, series)
- end
-
def completed_actions
TRACKS[track][:completed_actions]
end
@@ -146,21 +146,6 @@ module Namespaces
def series
TRACKS[track][:interval_days].index(interval)
end
-
- def save_tracked_emails!
- Users::InProductMarketingEmail.bulk_insert!(in_product_marketing_email_records)
- @in_product_marketing_email_records = []
- end
-
- def track_sent_email(user, track, series)
- in_product_marketing_email_records << Users::InProductMarketingEmail.new(
- user: user,
- track: track,
- series: series,
- created_at: Time.zone.now,
- updated_at: Time.zone.now
- )
- end
end
end
diff --git a/app/services/namespaces/invite_team_email_service.rb b/app/services/namespaces/invite_team_email_service.rb
new file mode 100644
index 00000000000..45975d1953a
--- /dev/null
+++ b/app/services/namespaces/invite_team_email_service.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Namespaces
+ class InviteTeamEmailService
+ include Gitlab::Experiment::Dsl
+
+ TRACK = :invite_team
+ DELIVERY_DELAY_IN_MINUTES = 20.minutes
+
+ def self.send_email(user, group)
+ new(user, group).execute
+ end
+
+ def initialize(user, group)
+ @group = group
+ @user = user
+ @sent_email_records = InProductMarketingEmailRecords.new
+ end
+
+ def execute
+ return unless user.email_opted_in?
+ return unless group.root?
+ return unless group.setup_for_company
+
+ # Exclude group if users other than the creator have already been
+ # added/invited
+ return unless group.member_count == 1
+
+ return if email_for_track_sent_to_user?
+
+ experiment(:invite_team_email, group: group) do |e|
+ e.candidate do
+ send_email(user, group)
+ sent_email_records.add(user, track, series)
+ sent_email_records.save!
+ end
+
+ e.record!
+ end
+ end
+
+ private
+
+ attr_reader :user, :group, :sent_email_records
+
+ def send_email(user, group)
+ NotificationService.new.in_product_marketing(user.id, group.id, track, series)
+ end
+
+ def track
+ TRACK
+ end
+
+ def series
+ 0
+ end
+
+ def email_for_track_sent_to_user?
+ Users::InProductMarketingEmail.for_user_with_track_and_series(user, track, series).present?
+ end
+ end
+end
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 194c3d7bf7b..9a0db3bb9aa 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -43,7 +43,7 @@ module Notes
private
def execute_quick_actions(note)
- return yield(false) unless quick_actions_service.supported?(note)
+ return yield(false) unless quick_actions_supported?(note)
content, update_params, message = quick_actions_service.execute(note, quick_action_options)
only_commands = content.empty?
@@ -54,6 +54,10 @@ module Notes
do_commands(note, update_params, message, only_commands)
end
+ def quick_actions_supported?(note)
+ quick_actions_service.supported?(note)
+ end
+
def quick_actions_service
@quick_actions_service ||= QuickActionsService.new(project, current_user)
end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index afc9015e758..6ad3a74b85d 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -598,8 +598,8 @@ class NotificationService
user.notification_email_for(pipeline.project.group)
end
- if recipients.any?
- mailer.public_send(email_template, pipeline, recipients).deliver_later
+ recipients.each do |recipient|
+ mailer.public_send(email_template, pipeline, recipient).deliver_later
end
end
diff --git a/app/services/packages/create_dependency_service.rb b/app/services/packages/create_dependency_service.rb
index 2c80ec66dbc..10a86e44cb0 100644
--- a/app/services/packages/create_dependency_service.rb
+++ b/app/services/packages/create_dependency_service.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
module Packages
+ # rubocop: disable Gitlab/BulkInsert
class CreateDependencyService < BaseService
attr_reader :package, :dependencies
@@ -51,7 +52,7 @@ module Packages
}
end
- ids = database.bulk_insert(Packages::Dependency.table_name, rows, return_ids: true, on_conflict: :do_nothing)
+ ids = ApplicationRecord.legacy_bulk_insert(Packages::Dependency.table_name, rows, return_ids: true, on_conflict: :do_nothing)
return ids if ids.size == names_and_version_patterns.size
Packages::Dependency.uncached do
@@ -72,11 +73,8 @@ module Packages
}
end
- database.bulk_insert(Packages::DependencyLink.table_name, rows)
- end
-
- def database
- ::Gitlab::Database.main
+ ApplicationRecord.legacy_bulk_insert(Packages::DependencyLink.table_name, rows)
end
end
+ # rubocop: enable Gitlab/BulkInsert
end
diff --git a/app/services/packages/npm/create_package_service.rb b/app/services/packages/npm/create_package_service.rb
index 1d5d9c38432..ae9c92a3d3a 100644
--- a/app/services/packages/npm/create_package_service.rb
+++ b/app/services/packages/npm/create_package_service.rb
@@ -4,6 +4,8 @@ module Packages
class CreatePackageService < ::Packages::CreatePackageService
include Gitlab::Utils::StrongMemoize
+ PACKAGE_JSON_NOT_ALLOWED_FIELDS = %w[readme readmeFilename].freeze
+
def execute
return error('Version is empty.', 400) if version.blank?
return error('Package already exists.', 403) if current_package_exists?
@@ -21,6 +23,10 @@ module Packages
::Packages::CreateDependencyService.new(package, package_dependencies).execute
::Packages::Npm::CreateTagService.new(package, dist_tag).execute
+ if Feature.enabled?(:packages_npm_abbreviated_metadata, project, default_enabled: :yaml)
+ package.create_npm_metadatum!(package_json: package_json)
+ end
+
package
end
@@ -46,6 +52,10 @@ module Packages
params[:versions][version]
end
+ def package_json
+ version_data.except(*PACKAGE_JSON_NOT_ALLOWED_FIELDS)
+ end
+
def dist_tag
params['dist-tags'].each_key.first
end
diff --git a/app/services/packages/nuget/create_dependency_service.rb b/app/services/packages/nuget/create_dependency_service.rb
index 3fc42056d43..85f295ac7b7 100644
--- a/app/services/packages/nuget/create_dependency_service.rb
+++ b/app/services/packages/nuget/create_dependency_service.rb
@@ -41,7 +41,7 @@ module Packages
}
end
- ::Gitlab::Database.main.bulk_insert(::Packages::Nuget::DependencyLinkMetadatum.table_name, rows.compact) # rubocop:disable Gitlab/BulkInsert
+ ::ApplicationRecord.legacy_bulk_insert(::Packages::Nuget::DependencyLinkMetadatum.table_name, rows.compact) # rubocop:disable Gitlab/BulkInsert
end
def raw_dependency_for(dependency)
diff --git a/app/services/packages/rubygems/create_dependencies_service.rb b/app/services/packages/rubygems/create_dependencies_service.rb
index dea429148cf..0b2ae56bf45 100644
--- a/app/services/packages/rubygems/create_dependencies_service.rb
+++ b/app/services/packages/rubygems/create_dependencies_service.rb
@@ -3,8 +3,6 @@
module Packages
module Rubygems
class CreateDependenciesService
- include BulkInsertSafe
-
def initialize(package, gemspec)
@package = package
@gemspec = gemspec
diff --git a/app/services/packages/update_tags_service.rb b/app/services/packages/update_tags_service.rb
index 2bdf75a6617..f29c54dacb9 100644
--- a/app/services/packages/update_tags_service.rb
+++ b/app/services/packages/update_tags_service.rb
@@ -15,7 +15,7 @@ module Packages
tags_to_create = @tags - existing_tags
@package.tags.with_name(tags_to_destroy).delete_all if tags_to_destroy.any?
- ::Gitlab::Database.main.bulk_insert(Packages::Tag.table_name, rows(tags_to_create)) if tags_to_create.any? # rubocop:disable Gitlab/BulkInsert
+ ::ApplicationRecord.legacy_bulk_insert(Packages::Tag.table_name, rows(tags_to_create)) if tags_to_create.any? # rubocop:disable Gitlab/BulkInsert
end
private
diff --git a/app/services/projects/alerting/notify_service.rb b/app/services/projects/alerting/notify_service.rb
index a5ee7173bdf..e5d40b60747 100644
--- a/app/services/projects/alerting/notify_service.rb
+++ b/app/services/projects/alerting/notify_service.rb
@@ -5,6 +5,7 @@ module Projects
class NotifyService
extend ::Gitlab::Utils::Override
include ::AlertManagement::AlertProcessing
+ include ::AlertManagement::Responses
def initialize(project, payload)
@project = project
@@ -23,7 +24,7 @@ module Projects
complete_post_processing_tasks
- ServiceResponse.success
+ success(alert)
end
private
@@ -46,18 +47,6 @@ module Projects
def valid_token?(token)
token == integration.token
end
-
- def bad_request
- ServiceResponse.error(message: 'Bad Request', http_status: :bad_request)
- end
-
- def unauthorized
- ServiceResponse.error(message: 'Unauthorized', http_status: :unauthorized)
- end
-
- def forbidden
- ServiceResponse.error(message: 'Forbidden', http_status: :forbidden)
- end
end
end
end
diff --git a/app/services/projects/all_issues_count_service.rb b/app/services/projects/all_issues_count_service.rb
new file mode 100644
index 00000000000..15352b14d3e
--- /dev/null
+++ b/app/services/projects/all_issues_count_service.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Projects
+ # Service class for counting and caching the number of all issues of a
+ # project.
+ class AllIssuesCountService < Projects::CountService
+ def relation_for_count
+ @project.issues
+ end
+
+ def cache_key_name
+ 'all_issues_count'
+ end
+ end
+end
diff --git a/app/services/projects/all_merge_requests_count_service.rb b/app/services/projects/all_merge_requests_count_service.rb
new file mode 100644
index 00000000000..db0bab3f799
--- /dev/null
+++ b/app/services/projects/all_merge_requests_count_service.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Projects
+ # Service class for counting and caching the number of all merge requests of
+ # a project.
+ class AllMergeRequestsCountService < Projects::CountService
+ def relation_for_count
+ @project.merge_requests
+ end
+
+ def cache_key_name
+ 'all_merge_requests_count'
+ end
+ end
+end
diff --git a/app/services/projects/container_repository/cache_tags_created_at_service.rb b/app/services/projects/container_repository/cache_tags_created_at_service.rb
deleted file mode 100644
index 3a5346d7a23..00000000000
--- a/app/services/projects/container_repository/cache_tags_created_at_service.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-# frozen_string_literal: true
-
-module Projects
- module ContainerRepository
- class CacheTagsCreatedAtService
- def initialize(container_repository)
- @container_repository = container_repository
- @cached_tag_names = Set.new
- end
-
- def populate(tags)
- return if tags.empty?
-
- # This will load all tags in one Redis roundtrip
- # the maximum number of tags is configurable and is set to 200 by default.
- # https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/packages/container_registry/index.md#set-cleanup-limits-to-conserve-resources
- keys = tags.map(&method(:cache_key))
- cached_tags_count = 0
-
- ::Gitlab::Redis::Cache.with do |redis|
- tags.zip(redis.mget(keys)).each do |tag, created_at|
- next unless created_at
-
- tag.created_at = DateTime.rfc3339(created_at)
- @cached_tag_names << tag.name
- cached_tags_count += 1
- end
- end
-
- cached_tags_count
- end
-
- def insert(tags, max_ttl_in_seconds)
- return unless max_ttl_in_seconds
- return if tags.empty?
-
- # tags with nil created_at are not cacheable
- # tags already cached don't need to be cached again
- cacheable_tags = tags.select do |tag|
- tag.created_at.present? && !tag.name.in?(@cached_tag_names)
- end
-
- return if cacheable_tags.empty?
-
- now = Time.zone.now
-
- ::Gitlab::Redis::Cache.with do |redis|
- # we use a pipeline instead of a MSET because each tag has
- # a specific ttl
- redis.pipelined do
- cacheable_tags.each do |tag|
- created_at = tag.created_at
- # ttl is the max_ttl_in_seconds reduced by the number
- # of seconds that the tag has already existed
- ttl = max_ttl_in_seconds - (now - created_at).seconds
- ttl = ttl.to_i
- redis.set(cache_key(tag), created_at.rfc3339, ex: ttl) if ttl > 0
- end
- end
- end
- end
-
- private
-
- def cache_key(tag)
- "container_repository:{#{@container_repository.id}}:tag:#{tag.name}:created_at"
- end
- end
- end
-end
diff --git a/app/services/projects/container_repository/cleanup_tags_service.rb b/app/services/projects/container_repository/cleanup_tags_service.rb
index 3a60de0f1ee..1a788abac12 100644
--- a/app/services/projects/container_repository/cleanup_tags_service.rb
+++ b/app/services/projects/container_repository/cleanup_tags_service.rb
@@ -140,14 +140,13 @@ module Projects
def cache
strong_memoize(:cache) do
- ::Projects::ContainerRepository::CacheTagsCreatedAtService.new(@container_repository)
+ ::Gitlab::ContainerRepository::Tags::Cache.new(@container_repository)
end
end
def caching_enabled?
container_expiration_policy &&
- older_than.present? &&
- Feature.enabled?(:container_registry_expiration_policies_caching, @project)
+ older_than.present?
end
def throttling_enabled?
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 1536f0a22b8..1d187b140ef 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -45,7 +45,7 @@ module Projects
if namespace_id
# Find matching namespace and check if it allowed
# for current user if namespace_id passed.
- unless current_user.can?(:create_projects, project_namespace)
+ unless current_user.can?(:create_projects, parent_namespace)
@project.namespace_id = nil
deny_namespace
return @project
@@ -136,7 +136,7 @@ module Projects
access_level: group_access_level)
end
- AuthorizedProjectUpdate::ProjectCreateWorker.perform_async(@project.id)
+ AuthorizedProjectUpdate::ProjectRecalculateWorker.perform_async(@project.id)
# AuthorizedProjectsWorker uses an exclusive lease per user but
# specialized workers might have synchronization issues. Until we
# compare the inconsistency rates of both approaches, we still run
@@ -227,14 +227,14 @@ module Projects
def extra_attributes_for_measurement
{
current_user: current_user&.name,
- project_full_path: "#{project_namespace&.full_path}/#{@params[:path]}"
+ project_full_path: "#{parent_namespace&.full_path}/#{@params[:path]}"
}
end
private
- def project_namespace
- @project_namespace ||= Namespace.find_by_id(@params[:namespace_id]) || current_user.namespace
+ def parent_namespace
+ @parent_namespace ||= Namespace.find_by_id(@params[:namespace_id]) || current_user.namespace
end
def create_from_template?
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index 27f813f4661..b7ed9202b01 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -152,9 +152,12 @@ module Projects
deleted_count = project.commit_statuses.delete_all
- if deleted_count > 0
- Gitlab::AppLogger.info "Projects::DestroyService - Project #{project.id} - #{deleted_count} leftover commit statuses"
- end
+ Gitlab::AppLogger.info(
+ class: 'Projects::DestroyService',
+ project_id: project.id,
+ message: 'leftover commit statuses',
+ orphaned_commit_status_count: deleted_count
+ )
end
# The project can have multiple webhooks with hundreds of thousands of web_hook_logs.
diff --git a/app/services/projects/detect_repository_languages_service.rb b/app/services/projects/detect_repository_languages_service.rb
index 0356a6b0ccd..9db0b71d106 100644
--- a/app/services/projects/detect_repository_languages_service.rb
+++ b/app/services/projects/detect_repository_languages_service.rb
@@ -21,7 +21,7 @@ module Projects
.update_all(share: update[:share])
end
- Gitlab::Database.main.bulk_insert( # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert( # rubocop:disable Gitlab/BulkInsert
RepositoryLanguage.table_name,
detection.insertions(matching_programming_languages)
)
diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb
index 64c0f1ff4ac..b1a2182fbdc 100644
--- a/app/services/projects/import_export/export_service.rb
+++ b/app/services/projects/import_export/export_service.rb
@@ -36,6 +36,7 @@ module Projects
private
attr_accessor :shared
+ attr_reader :logger
def execute_after_export_action(after_export_strategy)
return unless after_export_strategy
@@ -74,7 +75,11 @@ module Projects
end
def project_tree_saver
- tree_saver_class.new(project: project, current_user: current_user, shared: shared, params: params)
+ tree_saver_class.new(project: project,
+ current_user: current_user,
+ shared: shared,
+ params: params,
+ logger: logger)
end
def tree_saver_class
@@ -116,7 +121,7 @@ module Projects
end
def notify_success
- @logger.info(
+ logger.info(
message: 'Project successfully exported',
project_name: project.name,
project_id: project.id
@@ -124,7 +129,7 @@ module Projects
end
def notify_error
- @logger.error(
+ logger.error(
message: 'Project export error',
export_errors: shared.errors.join(', '),
project_name: project.name,
diff --git a/app/services/projects/lfs_pointers/lfs_link_service.rb b/app/services/projects/lfs_pointers/lfs_link_service.rb
index 7c00b9e6105..cf3cc5cd8e0 100644
--- a/app/services/projects/lfs_pointers/lfs_link_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_link_service.rb
@@ -38,7 +38,7 @@ module Projects
rows = existent_lfs_objects
.not_linked_to_project(project)
.map { |existing_lfs_object| { project_id: project.id, lfs_object_id: existing_lfs_object.id } }
- Gitlab::Database.main.bulk_insert(:lfs_objects_projects, rows) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(:lfs_objects_projects, rows) # rubocop:disable Gitlab/BulkInsert
iterations += 1
linked_existing_objects += existent_lfs_objects.map(&:oid)
diff --git a/app/services/projects/participants_service.rb b/app/services/projects/participants_service.rb
index 1616a8a4062..152590fffff 100644
--- a/app/services/projects/participants_service.rb
+++ b/app/services/projects/participants_service.rb
@@ -36,17 +36,9 @@ module Projects
private
def project_members_through_invited_groups
- groups_with_ancestors = if ::Feature.enabled?(:linear_participants_service_ancestor_scopes, current_user, default_enabled: :yaml)
- visible_groups.self_and_ancestors
- else
- Gitlab::ObjectHierarchy
- .new(visible_groups)
- .base_and_ancestors
- end
-
GroupMember
.active_without_invites_and_requests
- .with_source_id(groups_with_ancestors.pluck_primary_key)
+ .with_source_id(visible_groups.self_and_ancestors.pluck_primary_key)
end
def visible_groups
diff --git a/app/services/projects/prometheus/alerts/notify_service.rb b/app/services/projects/prometheus/alerts/notify_service.rb
index c1bf2e68436..56f65718d24 100644
--- a/app/services/projects/prometheus/alerts/notify_service.rb
+++ b/app/services/projects/prometheus/alerts/notify_service.rb
@@ -6,6 +6,7 @@ module Projects
class NotifyService
include Gitlab::Utils::StrongMemoize
include ::IncidentManagement::Settings
+ include ::AlertManagement::Responses
# This set of keys identifies a payload as a valid Prometheus
# payload and thus processable by this service. See also
@@ -27,9 +28,9 @@ module Projects
return unprocessable_entity unless self.class.processable?(payload)
return unauthorized unless valid_alert_manager_token?(token, integration)
- process_prometheus_alerts
+ alert_responses = process_prometheus_alerts
- ServiceResponse.success
+ alert_response(alert_responses)
end
def self.processable?(payload)
@@ -128,23 +129,17 @@ module Projects
end
def process_prometheus_alerts
- alerts.each do |alert|
+ alerts.map do |alert|
AlertManagement::ProcessPrometheusAlertService
.new(project, alert.to_h)
.execute
end
end
- def bad_request
- ServiceResponse.error(message: 'Bad Request', http_status: :bad_request)
- end
-
- def unauthorized
- ServiceResponse.error(message: 'Unauthorized', http_status: :unauthorized)
- end
+ def alert_response(alert_responses)
+ alerts = alert_responses.map { |resp| resp.payload[:alert] }.compact
- def unprocessable_entity
- ServiceResponse.error(message: 'Unprocessable Entity', http_status: :unprocessable_entity)
+ success(alerts)
end
end
end
diff --git a/app/services/resource_events/base_synthetic_notes_builder_service.rb b/app/services/resource_events/base_synthetic_notes_builder_service.rb
index 5939b9d2f9c..192d40129a3 100644
--- a/app/services/resource_events/base_synthetic_notes_builder_service.rb
+++ b/app/services/resource_events/base_synthetic_notes_builder_service.rb
@@ -24,10 +24,18 @@ module ResourceEvents
private
def apply_common_filters(events)
+ events = apply_pagination(events)
events = apply_last_fetched_at(events)
apply_fetch_until(events)
end
+ def apply_pagination(events)
+ return events if params[:paginated_notes].nil?
+ return events.none if params[:paginated_notes][table_name].blank?
+
+ events.id_in(params[:paginated_notes][table_name].map(&:id))
+ end
+
def apply_last_fetched_at(events)
return events unless params[:last_fetched_at].present?
@@ -47,5 +55,9 @@ module ResourceEvents
resource.project || resource.group
end
end
+
+ def table_name
+ raise NotImplementedError
+ end
end
end
diff --git a/app/services/resource_events/change_labels_service.rb b/app/services/resource_events/change_labels_service.rb
index bc2d3a946cc..03ac839c509 100644
--- a/app/services/resource_events/change_labels_service.rb
+++ b/app/services/resource_events/change_labels_service.rb
@@ -23,7 +23,7 @@ module ResourceEvents
label_hash.merge(label_id: label.id, action: ResourceLabelEvent.actions['remove'])
end
- Gitlab::Database.main.bulk_insert(ResourceLabelEvent.table_name, labels) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(ResourceLabelEvent.table_name, labels) # rubocop:disable Gitlab/BulkInsert
resource.expire_note_etag_cache
Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_label_changed_action(author: user) if resource.is_a?(Issue)
diff --git a/app/services/resource_events/synthetic_label_notes_builder_service.rb b/app/services/resource_events/synthetic_label_notes_builder_service.rb
index 5915ea938cf..0e5d945d13c 100644
--- a/app/services/resource_events/synthetic_label_notes_builder_service.rb
+++ b/app/services/resource_events/synthetic_label_notes_builder_service.rb
@@ -23,5 +23,9 @@ module ResourceEvents
events.group_by { |event| event.discussion_id }
end
+
+ def table_name
+ 'resource_label_events'
+ end
end
end
diff --git a/app/services/resource_events/synthetic_milestone_notes_builder_service.rb b/app/services/resource_events/synthetic_milestone_notes_builder_service.rb
index 10acf94e22b..0e2b171e192 100644
--- a/app/services/resource_events/synthetic_milestone_notes_builder_service.rb
+++ b/app/services/resource_events/synthetic_milestone_notes_builder_service.rb
@@ -21,5 +21,9 @@ module ResourceEvents
events = resource.resource_milestone_events.includes(user: :status) # rubocop: disable CodeReuse/ActiveRecord
apply_common_filters(events)
end
+
+ def table_name
+ 'resource_milestone_events'
+ end
end
end
diff --git a/app/services/resource_events/synthetic_state_notes_builder_service.rb b/app/services/resource_events/synthetic_state_notes_builder_service.rb
index 71d40200365..e17882b00de 100644
--- a/app/services/resource_events/synthetic_state_notes_builder_service.rb
+++ b/app/services/resource_events/synthetic_state_notes_builder_service.rb
@@ -16,5 +16,9 @@ module ResourceEvents
events = resource.resource_state_events.includes(user: :status) # rubocop: disable CodeReuse/ActiveRecord
apply_common_filters(events)
end
+
+ def table_name
+ 'resource_state_events'
+ end
end
end
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index cce7821a226..4ba1b3ade86 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -75,6 +75,10 @@ class SearchService
search_results.highlight_map(scope)
end
+ def search_aggregations
+ search_results.aggregations(scope)
+ end
+
private
def page
diff --git a/app/services/security/ci_configuration/sast_iac_create_service.rb b/app/services/security/ci_configuration/sast_iac_create_service.rb
new file mode 100644
index 00000000000..80e9cf963da
--- /dev/null
+++ b/app/services/security/ci_configuration/sast_iac_create_service.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Security
+ module CiConfiguration
+ class SastIacCreateService < ::Security::CiConfiguration::BaseCreateService
+ private
+
+ def action
+ Security::CiConfiguration::SastIacBuildAction.new(project.auto_devops_enabled?, existing_gitlab_ci_content).generate
+ end
+
+ def next_branch
+ 'set-sast-iac-config'
+ end
+
+ def message
+ _('Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist')
+ end
+
+ def description
+ _('Configure SAST IaC in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST IaC settings.')
+ end
+ end
+ end
+end
diff --git a/app/services/snippets/update_service.rb b/app/services/snippets/update_service.rb
index d83b21271c0..76d5063c337 100644
--- a/app/services/snippets/update_service.rb
+++ b/app/services/snippets/update_service.rb
@@ -148,3 +148,5 @@ module Snippets
end
end
end
+
+Snippets::UpdateService.prepend_mod_with('Snippets::UpdateService')
diff --git a/app/services/spam/spam_verdict_service.rb b/app/services/spam/spam_verdict_service.rb
index 8d995631db6..c8bdcf4310b 100644
--- a/app/services/spam/spam_verdict_service.rb
+++ b/app/services/spam/spam_verdict_service.rb
@@ -73,18 +73,12 @@ module Spam
begin
result, attribs, _error = spamcheck_client.issue_spam?(spam_issue: target, user: user, context: context)
- return [nil, attribs] unless result
-
# @TODO log if error is not nil https://gitlab.com/gitlab-org/gitlab/-/issues/329545
- return [result, attribs] if result == NOOP || attribs["monitorMode"] == "true"
+ return [nil, attribs] unless result
+
+ [result, attribs]
- # Duplicate logic with Akismet logic in #akismet_verdict
- if Gitlab::Recaptcha.enabled? && result != ALLOW
- [CONDITIONAL_ALLOW, attribs]
- else
- [result, attribs]
- end
rescue StandardError => e
Gitlab::ErrorTracking.log_exception(e)
diff --git a/app/services/suggestions/create_service.rb b/app/services/suggestions/create_service.rb
index eb98ed57d55..239cd86e0ec 100644
--- a/app/services/suggestions/create_service.rb
+++ b/app/services/suggestions/create_service.rb
@@ -25,7 +25,7 @@ module Suggestions
end
rows.in_groups_of(100, false) do |rows|
- Gitlab::Database.main.bulk_insert('suggestions', rows) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert('suggestions', rows) # rubocop:disable Gitlab/BulkInsert
end
Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter.track_add_suggestion_action(note: @note)
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index e5080718b69..dc5cf0fe554 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -327,6 +327,10 @@ module SystemNoteService
::SystemNotes::IncidentService.new(noteable: incident, project: incident.project, author: author).change_incident_severity
end
+ def resolve_incident_status(incident, author)
+ ::SystemNotes::IncidentService.new(noteable: incident, project: incident.project, author: author).resolve_incident_status
+ end
+
def log_resolving_alert(alert, monitoring_tool)
::SystemNotes::AlertManagementService.new(noteable: alert, project: alert.project).log_resolving_alert(monitoring_tool)
end
diff --git a/app/services/system_notes/incident_service.rb b/app/services/system_notes/incident_service.rb
index 4628662f0e9..785291e0637 100644
--- a/app/services/system_notes/incident_service.rb
+++ b/app/services/system_notes/incident_service.rb
@@ -25,5 +25,11 @@ module SystemNotes
)
end
end
+
+ def resolve_incident_status
+ body = 'changed the status to **Resolved** by closing the incident'
+
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'status'))
+ end
end
end
diff --git a/app/services/system_notes/issuables_service.rb b/app/services/system_notes/issuables_service.rb
index 62aead352aa..94629ae7609 100644
--- a/app/services/system_notes/issuables_service.rb
+++ b/app/services/system_notes/issuables_service.rb
@@ -176,7 +176,13 @@ module SystemNotes
body = cross_reference_note_content(gfm_reference)
if noteable.is_a?(ExternalIssue)
- noteable.project.external_issue_tracker.create_cross_reference_note(noteable, mentioner, author)
+ Integrations::CreateExternalCrossReferenceWorker.perform_async(
+ noteable.project_id,
+ noteable.id,
+ mentioner.class.name,
+ mentioner.id,
+ author.id
+ )
else
track_cross_reference_action
create_note(NoteSummary.new(noteable, noteable.project, author, body, action: 'cross_reference'))
diff --git a/app/services/tasks_to_be_done/base_service.rb b/app/services/tasks_to_be_done/base_service.rb
new file mode 100644
index 00000000000..a5648ad10c4
--- /dev/null
+++ b/app/services/tasks_to_be_done/base_service.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+module TasksToBeDone
+ class BaseService < ::IssuableBaseService
+ LABEL_PREFIX = 'tasks to be done'
+
+ def initialize(project:, current_user:, assignee_ids: [])
+ params = {
+ assignee_ids: assignee_ids,
+ title: title,
+ description: description,
+ add_labels: label_name
+ }
+ super(project: project, current_user: current_user, params: params)
+ end
+
+ def execute
+ if (issue = existing_task_issue)
+ update_service = Issues::UpdateService.new(project: project, current_user: current_user, params: { add_assignee_ids: params[:assignee_ids] })
+ update_service.execute(issue)
+ else
+ build_service = Issues::BuildService.new(project: project, current_user: current_user, params: params)
+ create(build_service.execute)
+ end
+ end
+
+ private
+
+ def existing_task_issue
+ IssuesFinder.new(
+ current_user,
+ project_id: project.id,
+ state: 'opened',
+ non_archived: true,
+ label_name: label_name
+ ).execute.last
+ end
+
+ def title
+ raise NotImplementedError
+ end
+
+ def description
+ raise NotImplementedError
+ end
+
+ def label_suffix
+ raise NotImplementedError
+ end
+
+ def label_name
+ "#{LABEL_PREFIX}:#{label_suffix}"
+ end
+ end
+end
diff --git a/app/services/tasks_to_be_done/create_ci_task_service.rb b/app/services/tasks_to_be_done/create_ci_task_service.rb
new file mode 100644
index 00000000000..025ca2feb8e
--- /dev/null
+++ b/app/services/tasks_to_be_done/create_ci_task_service.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module TasksToBeDone
+ class CreateCiTaskService < BaseService
+ protected
+
+ def title
+ 'Set up CI/CD'
+ end
+
+ def description
+ <<~DESCRIPTION
+ GitLab CI/CD is a tool built into GitLab for software development through the [continuous methodologies](https://docs.gitlab.com/ee/ci/introduction/index.html#introduction-to-cicd-methodologies):
+
+ * Continuous Integration (CI)
+ * Continuous Delivery (CD)
+ * Continuous Deployment (CD)
+
+ Continuous Integration works by pushing small changes to your application’s codebase hosted in a Git repository, and, to every push, run a pipeline of scripts to build, test, and validate the code changes before merging them into the main branch.
+
+ Continuous Delivery and Deployment consist of a step further CI, deploying your application to production at every push to the default branch of the repository.
+
+ These methodologies allow you to catch bugs and errors early in the development cycle, ensuring that all the code deployed to production complies with the code standards you established for your app.
+
+ * :book: [Read the documentation](https://docs.gitlab.com/ee/ci/introduction/index.html)
+ * :clapper: [Watch a Demo](https://www.youtube.com/watch?v=1iXFbchozdY)
+
+ ## Next steps
+
+ * [ ] To start we recommend reviewing the following documentation:
+ * [ ] [How GitLab CI/CD works.](https://docs.gitlab.com/ee/ci/introduction/index.html#how-gitlab-cicd-works)
+ * [ ] [Fundamental pipeline architectures.](https://docs.gitlab.com/ee/ci/pipelines/pipeline_architectures.html)
+ * [ ] [GitLab CI/CD basic workflow.](https://docs.gitlab.com/ee/ci/introduction/index.html#basic-cicd-workflow)
+ * [ ] [Step-by-step guide for writing .gitlab-ci.yml for the first time.](https://docs.gitlab.com/ee/user/project/pages/getting_started_part_four.html)
+ * [ ] When you're ready select **Projects** (in the top navigation bar) > **Your projects** > select the Project you've already created.
+ * [ ] Select **CI / CD** in the left navigation to start setting up CI / CD in your project.
+ DESCRIPTION
+ end
+
+ def label_suffix
+ 'ci'
+ end
+ end
+end
diff --git a/app/services/tasks_to_be_done/create_code_task_service.rb b/app/services/tasks_to_be_done/create_code_task_service.rb
new file mode 100644
index 00000000000..dc3b9366a66
--- /dev/null
+++ b/app/services/tasks_to_be_done/create_code_task_service.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module TasksToBeDone
+ class CreateCodeTaskService < BaseService
+ protected
+
+ def title
+ 'Create or import your code into your Project (Repository)'
+ end
+
+ def description
+ <<~DESCRIPTION
+ You've already created your Group and Project within GitLab; we'll quickly review this hierarchy below. Once you're within your project you can easily create or import repositories.
+
+ **With GitLab Groups, you can:**
+
+ * Create one or multiple Projects for hosting your codebase (repositories).
+ * Assemble related projects together.
+ * Grant members access to several projects at once.
+
+ Groups can also be nested in subgroups.
+
+ Read more about groups in our [documentation](https://docs.gitlab.com/ee/user/group/).
+
+ **Within GitLab Projects, you can**
+
+ * Use it as an issue tracker.
+ * Collaborate on code.
+ * Continuously build, test, and deploy your app with built-in GitLab CI/CD.
+
+ You can also import an existing repository by providing the Git URL.
+
+ * :book: [Read the documentation](https://docs.gitlab.com/ee/user/project/index.html).
+
+ ## Next steps
+
+ Create or import your first repository into the project you created:
+
+ * [ ] Click **Projects** in the top navigation bar, then click **Your projects**.
+ * [ ] Select the Project that you created, then select **Repository**.
+ * [ ] Once on the Repository page you can select the **+** icon to add or import files.
+ * [ ] You can review our full documentation on creating [repositories](https://docs.gitlab.com/ee/user/project/repository/) in GitLab.
+
+ :tada: All done, you can close this issue!
+ DESCRIPTION
+ end
+
+ def label_suffix
+ 'code'
+ end
+ end
+end
diff --git a/app/services/tasks_to_be_done/create_issues_task_service.rb b/app/services/tasks_to_be_done/create_issues_task_service.rb
new file mode 100644
index 00000000000..a2de6852868
--- /dev/null
+++ b/app/services/tasks_to_be_done/create_issues_task_service.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module TasksToBeDone
+ class CreateIssuesTaskService < BaseService
+ protected
+
+ def title
+ 'Create/import issues (tickets) to collaborate on ideas and plan work'
+ end
+
+ def description
+ <<~DESCRIPTION
+ Issues allow you and your team to discuss proposals before, and during, their implementation. They can be used for a variety of other purposes, customized to your needs and workflow.
+
+ Issues are always associated with a specific project. If you have multiple projects in a group, you can view all the issues at the group level. [You can review our full Issue documentation here.](https://docs.gitlab.com/ee/user/project/issues/)
+
+ If you have existing issues or equivalent tickets you can import them as long as they are formatted as a CSV file, [the import process is covered here](https://docs.gitlab.com/ee/user/project/issues/csv_import.html).
+
+ **Common use cases include:**
+
+ * Discussing the implementation of a new idea
+ * Tracking tasks and work status
+ * Accepting feature proposals, questions, support requests, or bug reports
+ * Elaborating on new code implementations
+
+ ## Next steps
+
+ * [ ] Select **Projects** in the top navigation > **Your Projects** > select the Project you've already created.
+ * [ ] Once you've selected that project, you can select **Issues** in the left navigation, then click **New issue**.
+ * [ ] Fill in the title and description in the **New issue** page.
+ * [ ] Click on **Create issue**.
+
+ Pro tip: When you're in a group or project you can always utilize the **+** icon in the top navigation (located to the left of the search bar) to quickly create new issues.
+
+ That's it! You can close this issue.
+ DESCRIPTION
+ end
+
+ def label_suffix
+ 'issues'
+ end
+ end
+end
diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb
index 71bb813f384..091f441831a 100644
--- a/app/services/todo_service.rb
+++ b/app/services/todo_service.rb
@@ -217,6 +217,11 @@ class TodoService
create_todos(reviewers, attributes)
end
+ def create_attention_requested_todo(target, author, users)
+ attributes = attributes_for_todo(target.project, target, author, Todo::ATTENTION_REQUESTED)
+ create_todos(users, attributes)
+ end
+
private
def create_todos(users, attributes)
diff --git a/app/services/users/destroy_service.rb b/app/services/users/destroy_service.rb
index 4ec875098fa..1634cc017ae 100644
--- a/app/services/users/destroy_service.rb
+++ b/app/services/users/destroy_service.rb
@@ -65,7 +65,10 @@ module Users
user.destroy_dependent_associations_in_batches(exclude: [:snippets])
# Destroy the namespace after destroying the user since certain methods may depend on the namespace existing
- user_data = user.destroy
+ user_data = nil
+ ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/340260') do
+ user_data = user.destroy
+ end
namespace.destroy
user_data
diff --git a/app/services/users/refresh_authorized_projects_service.rb b/app/services/users/refresh_authorized_projects_service.rb
index 1850fa9747d..2d9766c3c56 100644
--- a/app/services/users/refresh_authorized_projects_service.rb
+++ b/app/services/users/refresh_authorized_projects_service.rb
@@ -67,10 +67,8 @@ module Users
def update_authorizations(remove = [], add = [])
log_refresh_details(remove, add)
- User.transaction do
- user.remove_project_authorizations(remove) unless remove.empty?
- ProjectAuthorization.insert_authorizations(add) unless add.empty?
- end
+ user.remove_project_authorizations(remove) unless remove.empty?
+ ProjectAuthorization.insert_authorizations(add) unless add.empty?
# Since we batch insert authorization rows, Rails' associations may get
# out of sync. As such we force a reload of the User object.
diff --git a/app/services/users/upsert_credit_card_validation_service.rb b/app/services/users/upsert_credit_card_validation_service.rb
index 86b5b923418..61cf598f178 100644
--- a/app/services/users/upsert_credit_card_validation_service.rb
+++ b/app/services/users/upsert_credit_card_validation_service.rb
@@ -12,6 +12,7 @@ module Users
credit_card_validated_at: params.fetch(:credit_card_validated_at),
expiration_date: get_expiration_date(params),
last_digits: Integer(params.fetch(:credit_card_mask_number), 10),
+ network: params.fetch(:credit_card_type),
holder_name: params.fetch(:credit_card_holder_name)
}
diff --git a/app/uploaders/bulk_imports/export_uploader.rb b/app/uploaders/bulk_imports/export_uploader.rb
index 356e5ce028e..cd6e599054b 100644
--- a/app/uploaders/bulk_imports/export_uploader.rb
+++ b/app/uploaders/bulk_imports/export_uploader.rb
@@ -2,6 +2,6 @@
module BulkImports
class ExportUploader < ImportExportUploader
- EXTENSION_WHITELIST = %w[ndjson.gz].freeze
+ EXTENSION_ALLOWLIST = %w[ndjson.gz].freeze
end
end
diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb
index 20aab58243a..bd959b14648 100644
--- a/app/uploaders/file_uploader.rb
+++ b/app/uploaders/file_uploader.rb
@@ -32,7 +32,14 @@ class FileUploader < GitlabUploader
def self.absolute_path(upload)
File.join(
- absolute_base_dir(upload.model),
+ root,
+ relative_path(upload)
+ )
+ end
+
+ def self.relative_path(upload)
+ File.join(
+ base_dir(upload.model),
upload.path # already contain the dynamic_segment, see #upload_path
)
end
diff --git a/app/uploaders/import_export_uploader.rb b/app/uploaders/import_export_uploader.rb
index 369afba2bae..7b161d72efb 100644
--- a/app/uploaders/import_export_uploader.rb
+++ b/app/uploaders/import_export_uploader.rb
@@ -1,14 +1,14 @@
# frozen_string_literal: true
class ImportExportUploader < AttachmentUploader
- EXTENSION_WHITELIST = %w[tar.gz gz].freeze
+ EXTENSION_ALLOWLIST = %w[tar.gz gz].freeze
def self.workhorse_local_upload_path
File.join(options.storage_path, 'uploads', TMP_UPLOAD_PATH)
end
def extension_whitelist
- EXTENSION_WHITELIST
+ EXTENSION_ALLOWLIST
end
def move_to_cache
diff --git a/app/validators/gitlab/emoji_name_validator.rb b/app/validators/gitlab/emoji_name_validator.rb
new file mode 100644
index 00000000000..a9092d0194f
--- /dev/null
+++ b/app/validators/gitlab/emoji_name_validator.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# Gitlab::EmojiNameValidator
+#
+# Validates that the provided value matches an indexed emoji alpha code
+#
+# @example Usage
+# class AwardEmoji < ApplicationRecord
+# validate :name, 'gitlab/emoji_name': true
+# end
+module Gitlab
+ class EmojiNameValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ unless TanukiEmoji.find_by_alpha_code(value.to_s)
+ record.errors.add(attribute, (options[:message] || 'is not a valid emoji name'))
+ end
+ end
+ end
+end
diff --git a/app/validators/json_schemas/error_tracking_event_payload.json b/app/validators/json_schemas/error_tracking_event_payload.json
index 52efcf6800c..73ff71043ce 100644
--- a/app/validators/json_schemas/error_tracking_event_payload.json
+++ b/app/validators/json_schemas/error_tracking_event_payload.json
@@ -1,7 +1,7 @@
{
"description": "Error tracking event payload",
"type": "object",
- "required": [],
+ "required": ["exception"],
"properties": {
"environment": {
"type": "string"
@@ -14,7 +14,7 @@
},
"exception": {
"type": "object",
- "required": [],
+ "required": ["values"],
"properties": {
"values": {
"type": "array",
@@ -28,12 +28,6 @@
"value": {
"type": "string"
},
- "module": {
- "type": "string"
- },
- "thread_id": {
- "type": "number"
- },
"stacktrace": {
"type": "object",
"required": [],
@@ -44,9 +38,6 @@
"type": "object",
"required": [],
"properties": {
- "project_root": {
- "type": "string"
- },
"abs_path": {
"type": "string"
},
diff --git a/app/validators/json_schemas/helm_metadata.json b/app/validators/json_schemas/helm_metadata.json
index 7ac36e956f3..a5ff6f0b33a 100644
--- a/app/validators/json_schemas/helm_metadata.json
+++ b/app/validators/json_schemas/helm_metadata.json
@@ -103,7 +103,23 @@
"import-values": {
"type": "array",
"items": {
-
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "child": {
+ "type": "string"
+ },
+ "parent": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ }
+ ]
}
},
"alias": {
diff --git a/app/validators/json_schemas/npm_package_json.json b/app/validators/json_schemas/npm_package_json.json
new file mode 100644
index 00000000000..01bd874d214
--- /dev/null
+++ b/app/validators/json_schemas/npm_package_json.json
@@ -0,0 +1,26 @@
+{
+ "description": "NPM package json metadata",
+ "type": "object",
+ "properties": {
+ "name": { "type": "string" },
+ "version": { "type": "string" },
+ "dist": {
+ "type": "object",
+ "properties": {
+ "tarball": { "type": "string" },
+ "shasum": { "type": "string" }
+ },
+ "additionalProperties": true,
+ "required": [
+ "tarball",
+ "shasum"
+ ]
+ }
+ },
+ "additionalProperties": true,
+ "required": [
+ "name",
+ "version",
+ "dist"
+ ]
+}
diff --git a/app/views/admin/application_settings/_performance_bar.html.haml b/app/views/admin/application_settings/_performance_bar.html.haml
index ba7d747fa04..58ea2be8b61 100644
--- a/app/views/admin/application_settings/_performance_bar.html.haml
+++ b/app/views/admin/application_settings/_performance_bar.html.haml
@@ -6,7 +6,7 @@
.form-check
= f.check_box :performance_bar_enabled, class: 'form-check-input', data: { qa_selector: 'enable_performance_bar_checkbox'}
= f.label :performance_bar_enabled, class: 'form-check-label' do
- = _("Allow non-administrators to access to the performance bar")
+ = _("Allow non-administrators access to the performance bar")
.form-group
= f.label :performance_bar_allowed_group_path, _('Allow access to members of the following group'), class: 'label-bold'
= f.text_field :performance_bar_allowed_group_path, class: 'form-control gl-form-input', placeholder: 'my-org/my-group', value: @application_setting.performance_bar_allowed_group&.full_path
diff --git a/app/views/admin/application_settings/_protected_paths.html.haml b/app/views/admin/application_settings/_protected_paths.html.haml
index 04b42f42014..d273c81f51d 100644
--- a/app/views/admin/application_settings/_protected_paths.html.haml
+++ b/app/views/admin/application_settings/_protected_paths.html.haml
@@ -2,30 +2,26 @@
= form_errors(@application_setting)
%fieldset
- - if omnibus_protected_paths_throttle?
- .bs-callout.bs-callout-danger
- - relative_url_link = 'https://docs.gitlab.com/ee/user/admin_area/settings/protected_paths.html#migrate-settings-from-gitlab-123-and-earlier'
- - relative_url_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: relative_url_link }
- = _("Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}.").html_safe % { relative_url_link_start: relative_url_link_start, relative_url_link_end: '</a>'.html_safe }
-
.form-group
.form-check
= f.check_box :throttle_protected_paths_enabled, class: 'form-check-input'
= f.label :throttle_protected_paths_enabled, class: 'form-check-label' do
- = _('Enable protected paths rate limit')
+ = _('Enable rate limiting for POST requests to the specified paths')
%span.form-text.text-muted
- = _('Helps reduce request volume for protected paths')
+ = _('Helps reduce request volume for protected paths.')
.form-group
- = f.label :throttle_protected_paths_requests_per_period, 'Max requests per period per user', class: 'label-bold'
+ = f.label :throttle_protected_paths_requests_per_period, 'Maximum requests per period per user', class: 'label-bold'
= f.number_field :throttle_protected_paths_requests_per_period, class: 'form-control gl-form-input'
.form-group
- = f.label :throttle_protected_paths_period_in_seconds, 'Rate limit period in seconds', class: 'label-bold'
+ = f.label :throttle_protected_paths_period_in_seconds, 'Rate limit period (in seconds)', class: 'label-bold'
= f.number_field :throttle_protected_paths_period_in_seconds, class: 'form-control gl-form-input'
.form-group
= f.label :protected_paths, class: 'label-bold' do
+ = _('Paths to protect with rate limiting')
+ = f.text_area :protected_paths_raw, placeholder: '/users/sign_in,/users/password', class: 'form-control gl-form-input', rows: 10
+ %span.form-text.text-muted
- relative_url_link = 'https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab'
- relative_url_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: relative_url_link }
- = _('All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}.').html_safe % { relative_url_link_start: relative_url_link_start, relative_url_link_end: '</a>'.html_safe }
- = f.text_area :protected_paths_raw, placeholder: '/users/sign_in,/users/password', class: 'form-control gl-form-input', rows: 10
+ = _('All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}.').html_safe % { relative_url_link_start: relative_url_link_start, relative_url_link_end: '</a>'.html_safe }
= f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/admin/application_settings/_sentry.html.haml b/app/views/admin/application_settings/_sentry.html.haml
new file mode 100644
index 00000000000..5fd373d59e9
--- /dev/null
+++ b/app/views/admin/application_settings/_sentry.html.haml
@@ -0,0 +1,22 @@
+= form_for @application_setting, url: metrics_and_profiling_admin_application_settings_path(anchor: 'js-sentry-settings'), html: { class: 'fieldset-form', id: 'sentry-settings' } do |f|
+ = form_errors(@application_setting)
+
+ %span.text-muted
+ = _('Changing any setting here requires an application restart')
+
+ %fieldset
+ .form-group
+ .form-check
+ = f.check_box :sentry_enabled, class: 'form-check-input'
+ = f.label :sentry_enabled, _('Enable Sentry error tracking'), class: 'form-check-label'
+ .form-group
+ = f.label :sentry_dsn, _('DSN'), class: 'label-light'
+ = f.text_field :sentry_dsn, class: 'form-control gl-form-input', placeholder: 'https://public@sentry.example.com/1'
+ .form-group
+ = f.label :sentry_clientside_dsn, _('Clientside DSN'), class: 'label-light'
+ = f.text_field :sentry_clientside_dsn, class: 'form-control gl-form-input', placeholder: 'https://public@sentry.example.com/2'
+ .form-group
+ = f.label :sentry_environment, _('Environment'), class: 'label-light'
+ = f.text_field :sentry_environment, class: 'form-control gl-form-input', placeholder: Rails.env
+
+ = f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/admin/application_settings/_usage.html.haml b/app/views/admin/application_settings/_usage.html.haml
index 5bdad50c161..4fba1aee12d 100644
--- a/app/views/admin/application_settings/_usage.html.haml
+++ b/app/views/admin/application_settings/_usage.html.haml
@@ -15,7 +15,7 @@
.form-group
- can_be_configured = @application_setting.usage_ping_can_be_configured?
.form-check
- = f.check_box :usage_ping_enabled, disabled: !can_be_configured, class: 'form-check-input'
+ = f.check_box :usage_ping_enabled, disabled: !can_be_configured, class: 'form-check-input', data: { qa_selector: 'enable_usage_data_checkbox' }
= f.label :usage_ping_enabled, class: 'form-check-label' do
= _('Enable Service Ping')
.form-text.text-muted
diff --git a/app/views/admin/application_settings/_visibility_and_access.html.haml b/app/views/admin/application_settings/_visibility_and_access.html.haml
index b6266c3ea34..e56c898b236 100644
--- a/app/views/admin/application_settings/_visibility_and_access.html.haml
+++ b/app/views/admin/application_settings/_visibility_and_access.html.haml
@@ -1,13 +1,11 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-visibility-settings'), html: { class: 'fieldset-form', id: 'visibility-settings' } do |f|
+= gitlab_ui_form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-visibility-settings'), html: { class: 'fieldset-form', id: 'visibility-settings' } do |f|
= form_errors(@application_setting)
%fieldset
- = render 'shared/default_branch_protection', f: f, selected_level: @application_setting.default_branch_protection
+ = render 'shared/default_branch_protection', f: f
= render_if_exists 'admin/application_settings/group_owners_can_manage_default_branch_protection_setting', form: f
- .form-group
- = f.label s_('ProjectCreationLevel|Default project creation protection'), class: 'label-bold'
- = f.select :default_project_creation, options_for_select(Gitlab::Access.project_creation_options, @application_setting.default_project_creation), {}, class: 'form-control'
+ = render 'shared/project_creation_levels', f: f, method: :default_project_creation, legend: s_('ProjectCreationLevel|Default project creation protection')
= render_if_exists 'admin/application_settings/default_project_deletion_protection_setting', form: f
= render_if_exists 'admin/application_settings/default_delayed_project_deletion_setting', form: f
= render_if_exists 'admin/application_settings/default_project_deletion_adjourned_period_setting', form: f
diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml
index a72c96bb577..53ba626760b 100644
--- a/app/views/admin/application_settings/general.html.haml
+++ b/app/views/admin/application_settings/general.html.haml
@@ -80,7 +80,7 @@
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Set the maximum session time for a web terminal.')
- = link_to _('How do I use a web terminal?'), help_page_path('ci/environments/index.md', anchor: 'web-terminals'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to _('How do I use a web terminal?'), help_page_path('ci/environments/index.md', anchor: 'web-terminals-deprecated'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'terminal'
diff --git a/app/views/admin/application_settings/metrics_and_profiling.html.haml b/app/views/admin/application_settings/metrics_and_profiling.html.haml
index 6087551d7c7..7cb5760f62a 100644
--- a/app/views/admin/application_settings/metrics_and_profiling.html.haml
+++ b/app/views/admin/application_settings/metrics_and_profiling.html.haml
@@ -42,7 +42,7 @@
.js-self-monitoring-settings{ data: self_monitoring_project_data }
-%section.settings.as-usage.no-animate#js-usage-settings{ class: ('expanded' if expanded_by_default?) }
+%section.settings.as-usage.no-animate#js-usage-settings{ class: ('expanded' if expanded_by_default?), data: { qa_selector: 'usage_statistics_settings_content' } }
.settings-header#usage-statistics
%h4
= _('Usage statistics')
@@ -54,3 +54,15 @@
= render 'usage'
= render_if_exists 'admin/application_settings/pseudonymizer_settings', expanded: expanded_by_default?
+
+- if Feature.enabled?(:configure_sentry_in_application_settings, default_enabled: :yaml)
+ %section.settings.as-sentry.no-animate#js-sentry-settings{ class: ('expanded' if expanded_by_default?), data: { qa_selector: 'sentry_settings_content' } }
+ .settings-header
+ %h4
+ = _('Sentry')
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded_by_default? ? _('Collapse') : _('Expand')
+ %p
+ = _('Configure Sentry integration for error tracking')
+ .settings-content
+ = render 'sentry'
diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml
index 58e3f3f1136..3a053205725 100644
--- a/app/views/admin/application_settings/network.html.haml
+++ b/app/views/admin/application_settings/network.html.haml
@@ -87,14 +87,12 @@
%section.settings.as-protected-paths.no-animate#js-protected-paths-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4
- = _('Protected Paths')
+ = _('Protected paths')
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- = _('Configure paths to be protected by Rack Attack.')
- .help-block
- = _('These paths are protected for POST requests.')
- = link_to _('More information'), help_page_path('security/rack_attack', anchor: 'protected-paths-throttle'), target: '_blank'
+ = _('Rate limit access to specified paths.')
+ = link_to _('Learn more.'), help_page_path('user/admin_area/settings/protected_paths.md'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'protected_paths'
diff --git a/app/views/admin/application_settings/reporting.html.haml b/app/views/admin/application_settings/reporting.html.haml
index d2e118f0624..ae6243c3b50 100644
--- a/app/views/admin/application_settings/reporting.html.haml
+++ b/app/views/admin/application_settings/reporting.html.haml
@@ -13,6 +13,9 @@
.settings-content
= render 'spam'
+-# this partial is from JiHu, see details in https://gitlab.com/gitlab-jh/gitlab/-/merge_requests/135
+= render_if_exists 'admin/application_settings/content_validation_section'
+
%section.settings.as-abuse.no-animate#js-abuse-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4
diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml
index 8dcd5f81c23..d9c683cbcc3 100644
--- a/app/views/admin/applications/show.html.haml
+++ b/app/views/admin/applications/show.html.haml
@@ -6,4 +6,5 @@
= render 'shared/doorkeeper/applications/show',
edit_path: edit_admin_application_path(@application),
delete_path: admin_application_path(@application),
+ index_path: admin_applications_path,
show_trusted_row: true
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 681e7ccb613..4197d5b961f 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -153,9 +153,9 @@
%span.float-right
#{Rails::VERSION::STRING}
%p
- = Gitlab::Database.main.human_adapter_name
+ = ApplicationRecord.database.human_adapter_name
%span.float-right
- = Gitlab::Database.main.version
+ = ApplicationRecord.database.version
%p
= _('Redis')
%span.float-right
diff --git a/app/views/admin/dashboard/stats.html.haml b/app/views/admin/dashboard/stats.html.haml
index b98d11b734b..e0701812ba3 100644
--- a/app/views/admin/dashboard/stats.html.haml
+++ b/app/views/admin/dashboard/stats.html.haml
@@ -1,74 +1,75 @@
- page_title s_('AdminArea|Users statistics')
-%h3.my-4
+%h3.gl-my-6
= s_('AdminArea|Users statistics')
%table.table.gl-text-gray-500
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Users without a Group and Project')
= render_if_exists 'admin/dashboard/included_free_in_license_tooltip'
- %td.p-3.text-right
- = @users_statistics&.without_groups_and_projects.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.without_groups_and_projects
+ = render_if_exists 'admin/dashboard/minimal_access_stats_row', users_statistics: @users_statistics
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Guest')
= render_if_exists 'admin/dashboard/included_free_in_license_tooltip'
- %td.p-3.text-right
- = @users_statistics&.with_highest_role_guest.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.with_highest_role_guest
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Reporter')
- %td.p-3.text-right
- = @users_statistics&.with_highest_role_reporter.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.with_highest_role_reporter
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Developer')
- %td.p-3.text-right
- = @users_statistics&.with_highest_role_developer.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.with_highest_role_developer
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Maintainer')
- %td.p-3.text-right
- = @users_statistics&.with_highest_role_maintainer.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.with_highest_role_maintainer
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Owner')
- %td.p-3.text-right
- = @users_statistics&.with_highest_role_owner.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.with_highest_role_owner
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Bots')
- %td.p-3.text-right
- = @users_statistics&.bots.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.bots
= render_if_exists 'admin/dashboard/billable_users_row'
%tr.bg-gray-light.gl-text-gray-900
- %td.p-3
+ %td.gl-p-5!
%strong
= s_('AdminArea|Active users')
- %td.p-3.text-right
+ %td.gl-text-right{ class: 'gl-p-5!' }
%strong
- = @users_statistics&.active.to_i
+ = @users_statistics&.active
%tr.bg-gray-light.gl-text-gray-900
- %td.p-3
+ %td.gl-p-5!
%strong
= s_('AdminArea|Blocked users')
- %td.p-3.text-right
+ %td.gl-text-right{ class: 'gl-p-5!' }
%strong
- = @users_statistics&.blocked.to_i
+ = @users_statistics&.blocked
%tr.bg-gray-light.gl-text-gray-900
- %td.p-3
+ %td.gl-p-5!
%strong
= s_('AdminArea|Total users')
- %td.p-3.text-right
+ %td.gl-text-right{ class: 'gl-p-5!' }
%strong
- = @users_statistics&.total.to_i
+ = @users_statistics&.total
diff --git a/app/views/admin/deploy_keys/index.html.haml b/app/views/admin/deploy_keys/index.html.haml
index eec8f816f04..ba4abdc02e4 100644
--- a/app/views/admin/deploy_keys/index.html.haml
+++ b/app/views/admin/deploy_keys/index.html.haml
@@ -1,33 +1,44 @@
- page_title _('Deploy Keys')
-- if @deploy_keys.any?
- %h3.page-title.deploy-keys-title
- = _('Public deploy keys (%{deploy_keys_count})') % { deploy_keys_count: @deploy_keys.load.size }
- = link_to _('New deploy key'), new_admin_deploy_key_path, class: 'float-right btn gl-button btn-confirm btn-md gl-button'
- .table-holder.deploy-keys-list
- %table.table
+
+- if Feature.enabled?(:admin_deploy_keys_vue, default_enabled: :yaml)
+ #js-admin-deploy-keys-table{ data: admin_deploy_keys_data }
+- else
+ - if @deploy_keys.any?
+ %h3.page-title.deploy-keys-title
+ = _('Public deploy keys (%{deploy_keys_count})') % { deploy_keys_count: @deploy_keys.load.size }
+ = link_to _('New deploy key'), new_admin_deploy_key_path, class: 'float-right btn gl-button btn-confirm btn-md gl-button'
+ %table.table.b-table.gl-table.b-table-stacked-lg{ data: { testid: 'deploy-keys-list' } }
%thead
%tr
- %th.col-sm-2= _('Title')
- %th.col-sm-4= _('Fingerprint')
- %th.col-sm-2= _('Projects with write access')
- %th.col-sm-2= _('Added at')
- %th.col-sm-2
+ %th= _('Title')
+ %th= _('Fingerprint')
+ %th= _('Projects with write access')
+ %th= _('Created')
+ %th.gl-lg-w-1px.gl-white-space-nowrap
+ %span.gl-sr-only
+ = _('Actions')
%tbody
- @deploy_keys.each do |deploy_key|
%tr
- %td
- %strong= deploy_key.title
- %td
- %code.key-fingerprint= deploy_key.fingerprint
- %td
- - deploy_key.projects_with_write_access.each do |project|
- = link_to project.full_name, admin_project_path(project), class: 'label deploy-project-label'
- %td
- %span.cgray
- = _('added %{created_at_timeago}').html_safe % { created_at_timeago: time_ago_with_tooltip(deploy_key.created_at) }
- %td
- .float-right
- = link_to _('Edit'), edit_admin_deploy_key_path(deploy_key), class: 'btn gl-button btn-sm'
- = link_to _('Remove'), admin_deploy_key_path(deploy_key), data: { confirm: _('Are you sure?') }, method: :delete, class: 'gl-button btn btn-sm btn-danger delete-key'
-- else
- = render 'shared/empty_states/deploy_keys'
+ %td{ data: { label: _('Title') } }
+ %div
+ = deploy_key.title
+ %td{ data: { label: _('Fingerprint') } }
+ %div
+ %code= deploy_key.fingerprint
+ %td{ data: { label: _('Projects with write access') } }
+ %div
+ - deploy_key.projects_with_write_access.each do |project|
+ = link_to project.full_name, admin_project_path(project), class: 'gl-display-block'
+ %td{ data: { label: _('Created') } }
+ %div
+ = time_ago_with_tooltip(deploy_key.created_at)
+ %td.gl-lg-w-1px.gl-white-space-nowrap{ data: { label: _('Actions') } }
+ %div
+ = link_to edit_admin_deploy_key_path(deploy_key), class: 'btn btn-default btn-md gl-button btn-icon gl-mr-3', aria: { label: _('Edit deploy key') } do
+ = sprite_icon('pencil', css_class: 'gl-button-icon')
+ = link_to admin_deploy_key_path(deploy_key), data: { confirm: _('Are you sure?') }, method: :delete, class: 'btn btn-danger btn-md gl-button btn-icon', aria: { label: _('Remove deploy key') } do
+ = sprite_icon('remove', css_class: 'gl-button-icon')
+
+ - else
+ = render 'shared/empty_states/deploy_keys'
diff --git a/app/views/admin/dev_ops_report/_report.html.haml b/app/views/admin/dev_ops_report/_score.html.haml
index 208afefc73b..208afefc73b 100644
--- a/app/views/admin/dev_ops_report/_report.html.haml
+++ b/app/views/admin/dev_ops_report/_score.html.haml
diff --git a/app/views/admin/dev_ops_report/show.html.haml b/app/views/admin/dev_ops_report/show.html.haml
index c16ef7af76d..a2425b93ad3 100644
--- a/app/views/admin/dev_ops_report/show.html.haml
+++ b/app/views/admin/dev_ops_report/show.html.haml
@@ -1,4 +1,4 @@
-- page_title _('DevOps Report')
+- page_title _('DevOps Reports')
- add_page_specific_style 'page_bundles/dev_ops_report'
.container
@@ -6,5 +6,5 @@
- if show_adoption?
= render_if_exists 'admin/dev_ops_report/devops_tabs'
- else
- = render 'report'
+ = render 'score'
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index f298fce7bcf..0539d7f13a2 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -1,4 +1,4 @@
- breadcrumb_title _('Runners')
- page_title _('Runners')
-#js-admin-runners{ data: { registration_token: Gitlab::CurrentSettings.runners_registration_token, runner_install_help_page: 'https://docs.gitlab.com/runner/install/', active_runners_count: @active_runners_count } }
+#js-admin-runners{ data: admin_runners_data_attributes }
diff --git a/app/views/admin/topics/_topic.html.haml b/app/views/admin/topics/_topic.html.haml
index abf3cffa422..959e7ab31fc 100644
--- a/app/views/admin/topics/_topic.html.haml
+++ b/app/views/admin/topics/_topic.html.haml
@@ -6,7 +6,7 @@
.gl-min-w-0.gl-flex-grow-1
.title
- = topic.name
+ = link_to topic.name, topic_explore_projects_path(topic_name: topic.name)
.stats.gl-text-gray-500.gl-flex-shrink-0.gl-display-none.gl-sm-display-flex
%span.gl-ml-5.has-tooltip{ title: n_('%d project', '%d projects', topic.total_projects_count) % topic.total_projects_count }
diff --git a/app/views/admin/users/_tabs.html.haml b/app/views/admin/users/_tabs.html.haml
index 90f06eeaf3f..6c14e1189fe 100644
--- a/app/views/admin/users/_tabs.html.haml
+++ b/app/views/admin/users/_tabs.html.haml
@@ -1,7 +1,3 @@
-%ul.nav-links.nav-tabs.nav.js-users-tabs{ role: 'tablist' }
- %li.nav-item{ role: 'presentation' }
- %a.nav-link{ href: admin_users_path, class: active_when(current_page?(admin_users_path)), role: 'tab' }
- = s_('AdminUsers|Users')
- %li.nav-item{ role: 'presentation' }
- %a.nav-link{ href: admin_cohorts_path, class: active_when(current_page?(admin_cohorts_path)), role: 'tab' }
- = s_('AdminUsers|Cohorts')
+= gl_tabs_nav({ class: 'js-users-tabs' }) do
+ = gl_tab_link_to s_('AdminUsers|Users'), admin_users_path
+ = gl_tab_link_to s_('AdminUsers|Cohorts'), admin_cohorts_path
diff --git a/app/views/admin/users/_users.html.haml b/app/views/admin/users/_users.html.haml
index 1a43d91b800..e62e4cfa192 100644
--- a/app/views/admin/users/_users.html.haml
+++ b/app/views/admin/users/_users.html.haml
@@ -3,48 +3,38 @@
= sprite_icon('chevron-lg-left', size: 12)
.fade-right
= sprite_icon('chevron-lg-right', size: 12)
- %ul.nav-links.nav.nav-tabs.scrolling-tabs
- = nav_link(html_options: { class: active_when(params[:filter].nil?) }) do
- = link_to admin_users_path do
- = s_('AdminUsers|Active')
- %small.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(User.active_without_ghosts)
- = nav_link(html_options: { class: active_when(params[:filter] == 'admins') }) do
- = link_to admin_users_path(filter: "admins") do
- = s_('AdminUsers|Admins')
- %small.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(User.admins)
- = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_enabled')} filter-two-factor-enabled" }) do
- = link_to admin_users_path(filter: 'two_factor_enabled') do
- = s_('AdminUsers|2FA Enabled')
- %small.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(User.with_two_factor)
- = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_disabled')} filter-two-factor-disabled" }) do
- = link_to admin_users_path(filter: 'two_factor_disabled') do
- = s_('AdminUsers|2FA Disabled')
- %small.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(User.without_two_factor)
- = nav_link(html_options: { class: active_when(params[:filter] == 'external') }) do
- = link_to admin_users_path(filter: 'external') do
- = s_('AdminUsers|External')
- %small.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(User.external)
- = nav_link(html_options: { class: active_when(params[:filter] == 'blocked') }) do
- = link_to admin_users_path(filter: "blocked") do
- = s_('AdminUsers|Blocked')
- %small.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(User.blocked)
+ = gl_tabs_nav({ class: 'scrolling-tabs nav-links gl-display-flex gl-flex-grow-1' }) do
+ = gl_tab_link_to admin_users_path, { item_active: active_when(params[:filter].nil?), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Active')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.active_without_ghosts))
+ = gl_tab_link_to admin_users_path(filter: "admins"), { item_active: active_when(params[:filter] == 'admins'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Admins')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.admins))
+ = gl_tab_link_to admin_users_path(filter: 'two_factor_enabled'), { item_active: active_when(params[:filter] == 'two_factor_enabled'), class: 'filter-two-factor-enabled gl-border-0!' } do
+ = s_('AdminUsers|2FA Enabled')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.with_two_factor))
+ = gl_tab_link_to admin_users_path(filter: 'two_factor_disabled'), { item_active: active_when(params[:filter] == 'two_factor_disabled'), class: 'filter-two-factor-disabled gl-border-0!' } do
+ = s_('AdminUsers|2FA Disabled')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.without_two_factor))
+ = gl_tab_link_to admin_users_path(filter: 'external'), { item_active: active_when(params[:filter] == 'external'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|External')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.external))
+ = gl_tab_link_to admin_users_path(filter: "blocked"), { item_active: active_when(params[:filter] == 'blocked'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Blocked')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.blocked))
- if ban_feature_available?
- = nav_link(html_options: { class: active_when(params[:filter] == 'banned') }) do
- = link_to admin_users_path(filter: "banned") do
- = s_('AdminUsers|Banned')
- %small.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(User.banned)
- = nav_link(html_options: { class: "#{active_when(params[:filter] == 'blocked_pending_approval')} filter-blocked-pending-approval" }) do
- = link_to admin_users_path(filter: "blocked_pending_approval"), data: { qa_selector: 'pending_approval_tab' } do
- = s_('AdminUsers|Pending approval')
- %small.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(User.blocked_pending_approval)
- = nav_link(html_options: { class: active_when(params[:filter] == 'deactivated') }) do
- = link_to admin_users_path(filter: "deactivated") do
- = s_('AdminUsers|Deactivated')
- %small.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(User.deactivated)
- = nav_link(html_options: { class: active_when(params[:filter] == 'wop') }) do
- = link_to admin_users_path(filter: "wop") do
- = s_('AdminUsers|Without projects')
- %small.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(User.without_projects)
+ = gl_tab_link_to admin_users_path(filter: "banned"), { item_active: active_when(params[:filter] == 'banned'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Banned')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.banned))
+ = gl_tab_link_to admin_users_path(filter: "blocked_pending_approval"), { item_active: active_when(params[:filter] == 'blocked_pending_approval'), class: 'filter-blocked-pending-approval gl-border-0!', data: { qa_selector: 'pending_approval_tab' } } do
+ = s_('AdminUsers|Pending approval')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.blocked_pending_approval))
+ = gl_tab_link_to admin_users_path(filter: "deactivated"), { item_active: active_when(params[:filter] == 'deactivated'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Deactivated')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.deactivated))
+ = gl_tab_link_to admin_users_path(filter: "wop"), { item_active: active_when(params[:filter] == 'wop'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Without projects')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.without_projects))
.nav-controls
= render_if_exists 'admin/users/admin_email_users'
= render_if_exists 'admin/users/admin_export_user_permissions'
diff --git a/app/views/clusters/clusters/_cluster_list.html.haml b/app/views/clusters/clusters/_cluster_list.html.haml
index 38ed7e334c9..e5e1b68225e 100644
--- a/app/views/clusters/clusters/_cluster_list.html.haml
+++ b/app/views/clusters/clusters/_cluster_list.html.haml
@@ -1,12 +1,10 @@
-- if clusters.empty?
- = render 'empty_state'
-- else
+- if !clusters.empty?
.top-area.adjust
.gl-display-block.gl-text-right.gl-my-4.gl-w-full
- if clusterable.can_add_cluster?
- = link_to s_('ClusterIntegration|Connect cluster with certificate'), clusterable.new_path, class: 'btn gl-button btn-confirm js-add-cluster gl-py-2', qa_selector: :integrate_kubernetes_cluster_button
+ = link_to s_('ClusterIntegration|Connect cluster with certificate'), clusterable.new_path, class: 'btn gl-button btn-confirm js-add-cluster gl-py-2', data: { qa_selector: 'integrate_kubernetes_cluster_button' }
- else
%span.btn.gl-button.btn-confirm.js-add-cluster.disabled.gl-py-2
= s_("ClusterIntegration|Connect cluster with certificate")
- #js-clusters-list-app{ data: js_clusters_list_data(clusterable.index_path(format: :json)) }
+#js-clusters-list-app{ data: js_clusters_list_data(clusterable) }
diff --git a/app/views/clusters/clusters/_empty_state.html.haml b/app/views/clusters/clusters/_empty_state.html.haml
deleted file mode 100644
index feef3e0027f..00000000000
--- a/app/views/clusters/clusters/_empty_state.html.haml
+++ /dev/null
@@ -1,14 +0,0 @@
-.row.empty-state
- .col-12
- .svg-content= image_tag 'illustrations/clusters_empty.svg'
- .col-12
- .text-content
- %h4.gl-text-center= s_('ClusterIntegration|Integrate Kubernetes with a cluster certificate')
- %p.gl-text-center
- = s_('ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way.')
- = clusterable.empty_state_help_text
- = clusterable.learn_more_link
-
- - if clusterable.can_add_cluster?
- .gl-text-center
- = link_to s_('ClusterIntegration|Integrate with a cluster certificate'), clusterable.new_path, class: 'gl-button btn btn-confirm', data: { qa_selector: 'add_kubernetes_cluster_link' }
diff --git a/app/views/clusters/clusters/aws/_new.html.haml b/app/views/clusters/clusters/aws/_new.html.haml
index f6d50410e9a..7142dd83dce 100644
--- a/app/views/clusters/clusters/aws/_new.html.haml
+++ b/app/views/clusters/clusters/aws/_new.html.haml
@@ -11,7 +11,7 @@
'external-id' => @aws_role.role_external_id,
'role-arn' => @aws_role.role_arn,
'instance-types' => @instance_types,
- 'kubernetes-integration-help-path' => help_page_path('user/project/clusters/index'),
+ 'kubernetes-integration-help-path' => help_page_path('user/infrastructure/clusters/index.md'),
'account-and-external-ids-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'how-to-create-a-new-cluster-on-eks-through-cluster-certificates-deprecated'),
'create-role-arn-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'how-to-create-a-new-cluster-on-eks-through-cluster-certificates-deprecated'),
'external-link-icon' => sprite_icon('external-link') } }
diff --git a/app/views/clusters/clusters/gcp/_form.html.haml b/app/views/clusters/clusters/gcp/_form.html.haml
index 5266fad9278..173456926a5 100644
--- a/app/views/clusters/clusters/gcp/_form.html.haml
+++ b/app/views/clusters/clusters/gcp/_form.html.haml
@@ -2,7 +2,7 @@
- zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones'
- machine_type_link_url = 'https://cloud.google.com/compute/docs/machine-types'
- pricing_link_url = 'https://cloud.google.com/compute/pricing#machinetype'
-- kubernetes_integration_url = help_page_path('user/project/clusters/index')
+- kubernetes_integration_url = help_page_path('user/infrastructure/clusters/index.md')
- help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe
- help_link_end = ' %{external_link_icon}</a>'.html_safe % { external_link_icon: external_link_icon }
@@ -74,7 +74,7 @@
label_class: 'label-bold' }
.form-text.text-muted
= s_('ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster.')
- = link_to _('More information'), help_page_path('user/project/clusters/gitlab_managed_clusters.md', anchor: 'gitlab-managed-clusters'), target: '_blank'
+ = link_to _('More information'), help_page_path('user/project/clusters/gitlab_managed_clusters.md'), target: '_blank'
.form-group
= field.check_box :namespace_per_environment, { label: s_('ClusterIntegration|Namespace per environment'), label_class: 'label-bold' }
diff --git a/app/views/clusters/clusters/index.html.haml b/app/views/clusters/clusters/index.html.haml
index 45287a01cc9..457e34b306a 100644
--- a/app/views/clusters/clusters/index.html.haml
+++ b/app/views/clusters/clusters/index.html.haml
@@ -3,24 +3,10 @@
= render_gcp_signup_offer
-.clusters-container.gl-my-2
+.clusters-container
- if display_cluster_agents?(clusterable)
- .js-toggle-container
- %ul.nav-links.nav-tabs.nav{ role: 'tablist' }
- %li.nav-item{ role: 'presentation' }
- %a.nav-link.active{ href: "#certificate-clusters-pane", id: "certificate-clusters-tab", data: { toggle: 'tab' }, role: 'tab' }
- %span= s_('ClusterIntegration|Clusters connected with a certificate')
-
- %li.nav-item{ role: 'presentation' }
- %a.nav-link{ href: "#agent-clusters-pane", id: "agent-clusters-tab", data: { toggle: 'tab' }, role: 'tab' }
- %span= s_('ClusterIntegration|GitLab Agent managed clusters')
-
- .tab-content
- .tab-pane.active{ id: 'certificate-clusters-pane', role: 'tabpanel' }
- = render 'cluster_list', clusters: @clusters
-
- .tab-pane{ id: 'agent-clusters-pane', role: 'tabpanel' }
- #js-cluster-agents-list{ data: js_cluster_agents_list_data(clusterable) }
+ .gl-my-6
+ .js-clusters-main-view{ data: js_clusters_data(clusterable) }
- else
= render 'cluster_list', clusters: @clusters
diff --git a/app/views/clusters/clusters/new.html.haml b/app/views/clusters/clusters/new.html.haml
index 74e336723ba..7af7a812338 100644
--- a/app/views/clusters/clusters/new.html.haml
+++ b/app/views/clusters/clusters/new.html.haml
@@ -1,31 +1,31 @@
- breadcrumb_title _('Kubernetes')
- page_title _('Kubernetes Cluster')
-- active_tab = local_assigns.fetch(:active_tab, 'create')
- provider = params[:provider]
+- active_tab = params[:tab] || local_assigns.fetch(:active_tab, 'create')
+- is_active_tab_create = active_tab === 'create'
+- is_active_tab_add = active_tab === 'add'
= render_gcp_signup_offer
.row.gl-mt-3
.col-md-3
= render 'sidebar'
- .col-md-9.js-toggle-container
- %ul.nav-links.nav-tabs.gitlab-tabs.nav{ role: 'tablist' }
- %li.nav-item{ role: 'presentation' }
- %a.nav-link{ href: '#create-cluster-pane', id: 'create-cluster-tab', class: active_when(active_tab == 'create'), data: { toggle: 'tab' }, role: 'tab' }
- %span
- = create_new_cluster_label(provider: params[:provider])
- %li.nav-item{ role: 'presentation' }
- %a.nav-link{ href: '#add-cluster-pane', id: 'add-cluster-tab', class: active_when(active_tab == 'add'), data: { toggle: 'tab', qa_selector: 'add_existing_cluster_tab' }, role: 'tab' }
- %span= s_('ClusterIntegration|Connect existing cluster')
+ .col-md-9
+ = gl_tabs_nav({ class: 'nav-justified' }) do
+ = gl_tab_link_to clusterable.new_path(tab: 'create'), { item_active: is_active_tab_create } do
+ %span= create_new_cluster_label(provider: params[:provider])
+ = gl_tab_link_to s_('ClusterIntegration|Connect existing cluster'), clusterable.new_path(tab: 'add'), { item_active: is_active_tab_add, qa_selector: 'add_existing_cluster_tab' }
- .tab-content.gitlab-tab-content
- .tab-pane.p-0{ id: 'create-cluster-pane', class: active_when(active_tab == 'create'), role: 'tabpanel' }
- = render 'clusters/clusters/cloud_providers/cloud_provider_selector'
+ .tab-content
+ - if is_active_tab_create
+ .tab-pane.active{ role: 'tabpanel' }
+ = render 'clusters/clusters/cloud_providers/cloud_provider_selector'
- - if ['aws', 'gcp'].include?(provider)
- .p-3.border-top
- = render "clusters/clusters/#{provider}/new"
+ - if ['aws', 'gcp'].include?(provider)
+ .p-3.border-top
+ = render "clusters/clusters/#{provider}/new"
- .tab-pane{ id: 'add-cluster-pane', class: active_when(active_tab == 'add'), role: 'tabpanel' }
- #js-cluster-new{ data: js_cluster_new }
- = render 'clusters/clusters/user/form'
+ - if is_active_tab_add
+ .tab-pane.active.gl-p-5{ role: 'tabpanel' }
+ #js-cluster-new{ data: js_cluster_new }
+ = render 'clusters/clusters/user/form'
diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml
index 2a09d8d8cc0..e4c8f225ed2 100644
--- a/app/views/clusters/clusters/show.html.haml
+++ b/app/views/clusters/clusters/show.html.haml
@@ -13,7 +13,7 @@
cluster_status: @cluster.status_name,
cluster_status_reason: @cluster.status_reason,
provider_type: @cluster.provider_type,
- help_path: help_page_path('user/project/clusters/index.md'),
+ help_path: help_page_path('user/infrastructure/clusters/index.md'),
environments_help_path: help_page_path('ci/environments/index.md', anchor: 'create-a-static-environment'),
clusters_help_path: help_page_path('user/project/clusters/deploy_to_cluster.md'),
deploy_boards_help_path: help_page_path('user/project/deploy_boards.md', anchor: 'enabling-deploy-boards'),
diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml
index fdaf2107686..b94b14bf6bd 100644
--- a/app/views/dashboard/_projects_head.html.haml
+++ b/app/views/dashboard/_projects_head.html.haml
@@ -14,19 +14,7 @@
.top-area.scrolling-tabs-container.inner-page-scroll-tabs
.fade-left= sprite_icon('chevron-lg-left', size: 12)
.fade-right= sprite_icon('chevron-lg-right', size: 12)
- %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs{ class: ('border-0' if feature_project_list_filter_bar) }
- = nav_link(page: [dashboard_projects_path, root_path]) do
- = link_to dashboard_projects_path, class: 'shortcuts-activity', data: {placement: 'right'} do
- = _("Your projects")
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(@total_user_projects_count)
- = nav_link(page: starred_dashboard_projects_path) do
- = link_to starred_dashboard_projects_path, data: {placement: 'right'} do
- = _("Starred projects")
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(@total_starred_projects_count)
- = nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path]) do
- = link_to explore_root_path, data: {placement: 'right'} do
- = _("Explore projects")
- = render_if_exists "dashboard/removed_projects_tab", removed_projects_count: @removed_projects_count
+ = render 'dashboard/projects_nav'
- unless feature_project_list_filter_bar
.nav-controls
= render 'shared/projects/search_form'
diff --git a/app/views/dashboard/_projects_nav.html.haml b/app/views/dashboard/_projects_nav.html.haml
new file mode 100644
index 00000000000..64aa1e01d06
--- /dev/null
+++ b/app/views/dashboard/_projects_nav.html.haml
@@ -0,0 +1,13 @@
+- is_your_projects_path = current_page?(dashboard_projects_path) || current_page?(root_path)
+- is_explore_projects_path = current_page?(explore_root_path) || current_page?(trending_explore_projects_path) || current_page?(starred_explore_projects_path) || current_page?(explore_projects_path)
+
+= gl_tabs_nav({ class: 'scrolling-tabs nav-links gl-display-flex gl-flex-grow-1 gl-flex-nowrap gl-border-0' }) do
+ = gl_tab_link_to dashboard_projects_path, { item_active: is_your_projects_path, class: 'shortcuts-activity', data: { placement: 'right' } } do
+ = _("Your projects")
+ = gl_tab_counter_badge(limited_counter_with_delimiter(@total_user_projects_count))
+ = gl_tab_link_to starred_dashboard_projects_path, { data: { placement: 'right' } } do
+ = _("Starred projects")
+ = gl_tab_counter_badge(limited_counter_with_delimiter(@total_starred_projects_count))
+ = gl_tab_link_to _("Explore projects"), explore_root_path, { item_active: is_explore_projects_path, data: { placement: 'right' } }
+ = gl_tab_link_to _("Explore topics"), topics_explore_projects_path, { data: { placement: 'right' } }
+ = render_if_exists "dashboard/removed_projects_tab", removed_projects_count: @removed_projects_count
diff --git a/app/views/dashboard/_snippets_head.html.haml b/app/views/dashboard/_snippets_head.html.haml
index e96b5695ddc..8c468812e33 100644
--- a/app/views/dashboard/_snippets_head.html.haml
+++ b/app/views/dashboard/_snippets_head.html.haml
@@ -7,10 +7,6 @@
= link_to _("New snippet"), new_snippet_path, class: "gl-button btn btn-confirm", title: _("New snippet")
.top-area
- %ul.nav-links.nav.nav-tabs
- = nav_link(page: dashboard_snippets_path, html_options: {class: 'home'}) do
- = link_to dashboard_snippets_path, title: 'Your snippets', data: {placement: 'right'} do
- Your snippets
- = nav_link(page: explore_snippets_path) do
- = link_to explore_snippets_path, title: 'Explore snippets', data: {placement: 'right'} do
- Explore snippets
+ = gl_tabs_nav({ class: 'gl-border-0' }) do
+ = gl_tab_link_to _('Your snippets'), dashboard_snippets_path, { title: _('Your snippets') }
+ = gl_tab_link_to _('Explore snippets'), explore_snippets_path, { title: _('Explore snippets') }
diff --git a/app/views/dashboard/projects/_nav.html.haml b/app/views/dashboard/projects/_nav.html.haml
index f9b61bf1f3e..3e39872902d 100644
--- a/app/views/dashboard/projects/_nav.html.haml
+++ b/app/views/dashboard/projects/_nav.html.haml
@@ -14,8 +14,6 @@
= link_to s_('DashboardProjects|All'), dashboard_projects_path, class: params[:personal].present? ? inactive_class : active_class
= link_to s_('DashboardProjects|Personal'), filter_projects_path(personal: true), class: params[:personal].present? ? active_class : inactive_class
- else
- %ul.nav-links.mobile-separator.nav.nav-tabs
- = nav_link(html_options: { class: ("active" unless params[:personal].present?) }) do
- = link_to s_('DashboardProjects|All'), dashboard_projects_path
- = nav_link(html_options: { class: ("active" if params[:personal].present?) }) do
- = link_to s_('DashboardProjects|Personal'), filter_projects_path(personal: true)
+ = gl_tabs_nav do
+ = gl_tab_link_to s_('DashboardProjects|All'), dashboard_projects_path, { item_active: params[:personal].blank? }
+ = gl_tab_link_to s_('DashboardProjects|Personal'), filter_projects_path(personal: true), { item_active: params[:personal].present? }
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index 58f817bf63b..aa54a1e589e 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -10,19 +10,13 @@
- if current_user.todos.any?
.top-area
- %ul.nav-links.mobile-separator.nav.nav-tabs
- %li.todos-pending{ class: active_when(params[:state].blank? || params[:state] == 'pending') }>
- = link_to todos_filter_path(state: 'pending') do
- %span
- To Do
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm
- = number_with_delimiter(todos_pending_count)
- %li.todos-done{ class: active_when(params[:state] == 'done') }>
- = link_to todos_filter_path(state: 'done') do
- %span
- Done
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm
- = number_with_delimiter(todos_done_count)
+ = gl_tabs_nav({ class: 'gl-flex-grow-1 gl-border-0' }) do
+ = gl_tab_link_to todos_filter_path(state: 'pending'), item_active: params[:state].blank? || params[:state] == 'pending', class: "js-todos-pending" do
+ = _("To Do")
+ = gl_tab_counter_badge number_with_delimiter(todos_pending_count)
+ = gl_tab_link_to todos_filter_path(state: 'done'), item_active: params[:state] == 'done', class: "js-todos-done" do
+ = _("Done")
+ = gl_tab_counter_badge number_with_delimiter(todos_done_count)
.nav-controls
- if @allowed_todos.any?(&:pending?)
diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml
index 51354618aa4..eee223ff63c 100644
--- a/app/views/devise/confirmations/new.html.haml
+++ b/app/views/devise/confirmations/new.html.haml
@@ -7,7 +7,12 @@
.form-group
= f.label :email
= f.email_field :email, class: "form-control gl-form-input", required: true, title: _('Please provide a valid email address.'), value: nil
- .clearfix
+
+ %div
+ - if recaptcha_enabled?
+ = recaptcha_tags nonce: content_security_policy_nonce
+
+ .gl-mt-5
= f.submit _("Resend"), class: 'gl-button btn btn-confirm'
.clearfix.prepend-top-20
diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml
index 7f6ce712af2..7bbde4a39c7 100644
--- a/app/views/devise/passwords/new.html.haml
+++ b/app/views/devise/passwords/new.html.haml
@@ -8,7 +8,12 @@
= f.email_field :email, class: "form-control gl-form-input", required: true, value: params[:user_email], autofocus: true, title: _('Please provide a valid email address.')
.form-text.text-muted
= _('Requires your primary GitLab email address.')
- .clearfix
+
+ %div
+ - if recaptcha_enabled?
+ = recaptcha_tags nonce: content_security_policy_nonce
+
+ .gl-mt-5
= f.submit _("Reset password"), class: "gl-button btn-confirm btn"
.clearfix.prepend-top-20
diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml
index 75521d42f7e..3a568421ce9 100644
--- a/app/views/doorkeeper/applications/show.html.haml
+++ b/app/views/doorkeeper/applications/show.html.haml
@@ -6,4 +6,7 @@
%h3.page-title
= _("Application: %{name}") % { name: @application.name }
-= render 'shared/doorkeeper/applications/show', edit_path: edit_oauth_application_path(@application), delete_path: oauth_application_path(@application)
+= render 'shared/doorkeeper/applications/show',
+ edit_path: edit_oauth_application_path(@application),
+ delete_path: oauth_application_path(@application),
+ index_path: oauth_applications_path
diff --git a/app/views/errors/omniauth_error.html.haml b/app/views/errors/omniauth_error.html.haml
index 0e9041d07ea..e114e4609f8 100644
--- a/app/views/errors/omniauth_error.html.haml
+++ b/app/views/errors/omniauth_error.html.haml
@@ -1,7 +1,7 @@
- content_for(:title, 'Auth Error')
.container
- = render "shared/errors/graphic_422.svg"
+ = render partial: "shared/errors/graphic_422", formats: :svg
%h3 Sign-in using #{@provider} auth failed
%p.light.subtitle Sign-in failed because #{@error}.
diff --git a/app/views/explore/groups/_nav.html.haml b/app/views/explore/groups/_nav.html.haml
index c337149a2f3..3c9c4e9f76b 100644
--- a/app/views/explore/groups/_nav.html.haml
+++ b/app/views/explore/groups/_nav.html.haml
@@ -1,8 +1,6 @@
.top-area
- %ul.nav-links.nav.nav-tabs
- = nav_link(page: explore_groups_path) do
- = link_to explore_groups_path do
- = _("Explore Groups")
+ = gl_tabs_nav({ class: 'gl-display-flex gl-flex-grow-1 gl-border-none'}) do
+ = gl_tab_link_to _("Explore Groups"), explore_groups_path
.nav-controls
= render 'shared/groups/search_form'
= render 'shared/groups/dropdown'
diff --git a/app/views/explore/projects/_nav.html.haml b/app/views/explore/projects/_nav.html.haml
index 65b7d055843..9d7a6f1ccfb 100644
--- a/app/views/explore/projects/_nav.html.haml
+++ b/app/views/explore/projects/_nav.html.haml
@@ -1,14 +1,8 @@
.top-area
- %ul.nav-links.nav.nav-tabs
- = nav_link(page: [explore_projects_path, explore_root_path]) do
- = link_to explore_projects_path do
- = _('All')
- = nav_link(page: starred_explore_projects_path) do
- = link_to starred_explore_projects_path do
- = _('Most stars')
- = nav_link(page: trending_explore_projects_path) do
- = link_to trending_explore_projects_path do
- = _('Trending')
+ = gl_tabs_nav({ class: 'gl-display-flex gl-flex-grow-1 gl-border-none'}) do
+ = gl_tab_link_to _('All'), explore_projects_path, { item_active: current_page?(explore_projects_path) || current_page?(explore_root_path) }
+ = gl_tab_link_to _('Most stars'), starred_explore_projects_path
+ = gl_tab_link_to _('Trending'), trending_explore_projects_path
.nav-controls
- unless current_user
diff --git a/app/views/explore/projects/topic.html.haml b/app/views/explore/projects/topic.html.haml
new file mode 100644
index 00000000000..aeb040ea61f
--- /dev/null
+++ b/app/views/explore/projects/topic.html.haml
@@ -0,0 +1,31 @@
+- @hide_top_links = false
+- @no_container = true
+- page_title @topic.name, _("Topics")
+- max_topic_name_length = 50
+
+= render_dashboard_ultimate_trial(current_user)
+
+.gl-text-center.gl-bg-gray-10.gl-pb-2.gl-pt-6
+ .gl-pb-5.gl-align-items-center.gl-justify-content-center.gl-display-flex
+ .avatar-container.rect-avatar.s60.gl-flex-shrink-0
+ = topic_icon(@topic, alt: _('Topic avatar'), class: 'avatar topic-avatar s60')
+ - if @topic.name.length > max_topic_name_length
+ %h1.gl-mt-3.str-truncated.has-tooltip{ title: @topic.name }
+ = truncate(@topic.name, length: max_topic_name_length)
+ - else
+ %h1.gl-mt-3
+ = @topic.name
+ - if @topic.description.present?
+ .topic-description.gl-ml-4.gl-mr-4
+ = markdown(@topic.description)
+
+%div{ class: container_class }
+ .gl-py-5.gl-border-gray-100.gl-border-b-solid.gl-border-b-1
+ %h3.gl-m-0= _('Projects with this topic')
+ .top-area.gl-pt-2.gl-pb-2
+ .nav-controls
+ = render 'shared/projects/search_form'
+ = render 'shared/projects/dropdown'
+ = render 'filter'
+
+ = render 'projects', projects: @projects
diff --git a/app/views/explore/projects/topics.html.haml b/app/views/explore/projects/topics.html.haml
new file mode 100644
index 00000000000..228304d25b6
--- /dev/null
+++ b/app/views/explore/projects/topics.html.haml
@@ -0,0 +1,12 @@
+- @hide_top_links = true
+- page_title _("Topics")
+- header_title _("Topics"), topics_explore_projects_path
+
+= render_dashboard_ultimate_trial(current_user)
+
+- if current_user
+ = render 'explore/topics/head'
+- else
+ = render 'explore/head'
+
+= render partial: 'shared/topics/list'
diff --git a/app/views/explore/topics/_head.html.haml b/app/views/explore/topics/_head.html.haml
new file mode 100644
index 00000000000..f5ee95b16c3
--- /dev/null
+++ b/app/views/explore/topics/_head.html.haml
@@ -0,0 +1,9 @@
+.page-title-holder.d-flex.align-items-center
+ %h1.page-title= _('Projects')
+
+.top-area.scrolling-tabs-container.inner-page-scroll-tabs
+ .fade-left= sprite_icon('chevron-lg-left', size: 12)
+ .fade-right= sprite_icon('chevron-lg-right', size: 12)
+ = render 'dashboard/projects_nav'
+ .nav-controls
+ = render 'shared/topics/search_form'
diff --git a/app/views/groups/_invite_members_side_nav_link.html.haml b/app/views/groups/_invite_members_side_nav_link.html.haml
new file mode 100644
index 00000000000..bccfa9897da
--- /dev/null
+++ b/app/views/groups/_invite_members_side_nav_link.html.haml
@@ -0,0 +1,8 @@
+.js-invite-members-trigger{ data: { trigger_source: 'group-side-nav',
+ classes: 'gl-text-decoration-none! gl-shadow-none! gl-text-body!',
+ icon: 'users',
+ display_text: title,
+ trigger_element: 'side-nav'} }
+
+= render partial: 'shared/nav/sidebar_submenu', locals: { sidebar_menu: sidebar_menu }
+= render 'groups/invite_members_modal', group: group
diff --git a/app/views/groups/boards/show.html.haml b/app/views/groups/boards/show.html.haml
index dbbf78eed00..92838fa4b11 100644
--- a/app/views/groups/boards/show.html.haml
+++ b/app/views/groups/boards/show.html.haml
@@ -1,3 +1 @@
-= render 'shared/alerts/positioning_disabled'
-
= render "shared/boards/show", board: @board, group: true
diff --git a/app/views/groups/crm/contacts.html.haml b/app/views/groups/crm/contacts.html.haml
new file mode 100644
index 00000000000..c452a969d17
--- /dev/null
+++ b/app/views/groups/crm/contacts.html.haml
@@ -0,0 +1,4 @@
+- breadcrumb_title _('Customer Relations Contacts')
+- page_title _('Customer Relations Contacts')
+
+#js-crm-contacts-app{ data: { group_full_path: @group.full_path } }
diff --git a/app/views/groups/crm/organizations.html.haml b/app/views/groups/crm/organizations.html.haml
new file mode 100644
index 00000000000..e83dab9fda6
--- /dev/null
+++ b/app/views/groups/crm/organizations.html.haml
@@ -0,0 +1,4 @@
+- breadcrumb_title _('Customer Relations Organizations')
+- page_title _('Customer Relations Organizations')
+
+#js-crm-organizations-app{ data: { group_full_path: @group.full_path } }
diff --git a/app/views/groups/dependency_proxies/show.html.haml b/app/views/groups/dependency_proxies/show.html.haml
index 8936c4dcbb4..47caec717af 100644
--- a/app/views/groups/dependency_proxies/show.html.haml
+++ b/app/views/groups/dependency_proxies/show.html.haml
@@ -1,5 +1,7 @@
- page_title _("Dependency Proxy")
+- @content_class = "limit-container-width" unless fluid_layout
- dependency_proxy_available = Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true) || @group.public?
#js-dependency-proxy{ data: { group_path: @group.full_path,
- dependency_proxy_available: dependency_proxy_available.to_s } }
+ dependency_proxy_available: dependency_proxy_available.to_s,
+ no_manifests_illustration: image_path('illustrations/docker-empty-state.svg') } }
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index 0f11ca5fb8f..e55af71022e 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -10,7 +10,7 @@
.row{ 'v-cloak': true }
#create-group-pane.tab-pane
- = form_for @group, html: { class: 'group-form gl-show-field-errors' } do |f|
+ = form_for @group, html: { class: 'group-form gl-show-field-errors gl-mt-3' } do |f|
= render 'new_group_fields', f: f, group_name_id: 'create-group-name'
#import-group-pane.tab-pane
diff --git a/app/views/groups/settings/_advanced.html.haml b/app/views/groups/settings/_advanced.html.haml
index cdff533e3c7..a82f7803b44 100644
--- a/app/views/groups/settings/_advanced.html.haml
+++ b/app/views/groups/settings/_advanced.html.haml
@@ -1,3 +1,4 @@
+- remove_form_id = 'js-remove-group-form'
= render 'groups/settings/export', group: @group
.sub-section
@@ -26,6 +27,6 @@
= f.submit s_('GroupSettings|Change group URL'), class: 'btn gl-button btn-warning'
= render 'groups/settings/transfer', group: @group
-= render 'groups/settings/remove', group: @group
+= render 'groups/settings/remove', group: @group, remove_form_id: remove_form_id
= render_if_exists 'groups/settings/restore', group: @group
-= render_if_exists 'groups/settings/immediately_remove', group: @group
+= render_if_exists 'groups/settings/immediately_remove', group: @group, remove_form_id: remove_form_id
diff --git a/app/views/groups/settings/_membership.html.haml b/app/views/groups/settings/_membership.html.haml
index b05a294e864..c1566dddc00 100644
--- a/app/views/groups/settings/_membership.html.haml
+++ b/app/views/groups/settings/_membership.html.haml
@@ -4,3 +4,4 @@
= render 'shared/allow_request_access', form: f
= render_if_exists 'groups/member_lock_setting', f: f, group: @group
+= render_if_exists 'groups/user_caps_setting', f: f, group: @group
diff --git a/app/views/groups/settings/_permanent_deletion.html.haml b/app/views/groups/settings/_permanent_deletion.html.haml
index 125a20060ed..152cdfc1411 100644
--- a/app/views/groups/settings/_permanent_deletion.html.haml
+++ b/app/views/groups/settings/_permanent_deletion.html.haml
@@ -1,9 +1,11 @@
+- remove_form_id = local_assigns.fetch(:remove_form_id, nil)
+
.sub-section
%h4.danger-title= _('Remove group')
- = form_tag(group, method: :delete) do
+ = form_tag(group, method: :delete, id: remove_form_id) do
%p
= _('Removing this group also removes all child projects, including archived projects, and their resources.')
%br
%strong= _('Removed group can not be restored!')
- = render 'groups/settings/remove_button', group: group
+ = render 'groups/settings/remove_button', group: group, remove_form_id: remove_form_id
diff --git a/app/views/groups/settings/_remove.html.haml b/app/views/groups/settings/_remove.html.haml
index a617467019a..8571b93364b 100644
--- a/app/views/groups/settings/_remove.html.haml
+++ b/app/views/groups/settings/_remove.html.haml
@@ -1,5 +1,6 @@
+- remove_form_id = local_assigns.fetch(:remove_form_id, nil)
+
- if group.adjourned_deletion?
- = render_if_exists 'groups/settings/adjourned_deletion', group: group
+ = render_if_exists 'groups/settings/adjourned_deletion', group: group, remove_form_id: remove_form_id
- else
- = render 'groups/settings/permanent_deletion', group: group
-
+ = render 'groups/settings/permanent_deletion', group: group, remove_form_id: remove_form_id
diff --git a/app/views/groups/settings/_remove_button.html.haml b/app/views/groups/settings/_remove_button.html.haml
index a04dba68b92..1d5b7160049 100644
--- a/app/views/groups/settings/_remove_button.html.haml
+++ b/app/views/groups/settings/_remove_button.html.haml
@@ -1,7 +1,9 @@
+- remove_form_id = local_assigns.fetch(:remove_form_id, nil)
+
- if group.paid?
.gl-alert.gl-alert-info.gl-mb-5{ data: { testid: 'group-has-linked-subscription-alert' } }
= sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
= html_escape(_("This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group.")) % { linkStart: "<a href=\"#{help_page_path('subscriptions/index', anchor: 'change-the-linked-namespace')}\">".html_safe, linkEnd: '</a>'.html_safe }
-= button_to _('Remove group'), '#', class: ['btn gl-button btn-danger js-confirm-danger', ('disabled' if group.paid?)], data: { 'confirm-danger-message' => remove_group_message(group), 'testid' => 'remove-group-button' }
+.js-confirm-danger{ data: group_settings_confirm_modal_data(group, remove_form_id) }
diff --git a/app/views/groups/settings/_transfer.html.haml b/app/views/groups/settings/_transfer.html.haml
index 1472ae42152..b2379d77314 100644
--- a/app/views/groups/settings/_transfer.html.haml
+++ b/app/views/groups/settings/_transfer.html.haml
@@ -14,7 +14,7 @@
%li= s_("GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.")
- if group.paid?
- .gl-alert.gl-alert-info.gl-mb-5{ data: { testid: 'group-to-transfer-has-linked-subscription-alert' } }
+ .gl-alert.gl-alert-info.gl-mb-5
= sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
= html_escape(_("This group can't be transfered because it is linked to a subscription. To transfer this group, %{linkStart}link the subscription%{linkEnd} with a different group.")) % { linkStart: "<a href=\"#{help_page_path('subscriptions/index', anchor: 'change-the-linked-namespace')}\">".html_safe, linkEnd: '</a>'.html_safe }
diff --git a/app/views/groups/settings/applications/show.html.haml b/app/views/groups/settings/applications/show.html.haml
index fce3602349b..6e7f6ce4df0 100644
--- a/app/views/groups/settings/applications/show.html.haml
+++ b/app/views/groups/settings/applications/show.html.haml
@@ -6,4 +6,7 @@
%h3.page-title
= _("Group application: %{name}") % { name: @application.name }
-= render 'shared/doorkeeper/applications/show', edit_path: edit_group_settings_application_path(@group, @application), delete_path: group_settings_application_path(@group, @application)
+= render 'shared/doorkeeper/applications/show',
+ edit_path: edit_group_settings_application_path(@group, @application),
+ delete_path: group_settings_application_path(@group, @application),
+ index_path: group_settings_applications_path
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 2e74d983397..ed3f2b0c6db 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -32,8 +32,6 @@
= render_if_exists 'groups/group_activity_analytics', group: @group
-= render 'groups/invite_members_modal', group: @group
-
.groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
.top-area.group-nav-container.justify-content-between
.scrolling-tabs-container.inner-page-scroll-tabs
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index 95888963947..f81afd0a82e 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -46,5 +46,5 @@
%button.btn-blank.btn-link.js-trigger-shortcut{ type: 'button' }
= _('Use shortcuts')
- unless Gitlab::CurrentSettings.help_page_hide_commercial_content?
- %li= link_to _('Get a support subscription'), 'https://about.gitlab.com/pricing/'
- %li= link_to _('Compare GitLab editions'), 'https://about.gitlab.com/features/#compare'
+ %li= link_to _('Get a support subscription'), "https://#{ApplicationHelper.promo_host}/pricing/"
+ %li= link_to _('Compare GitLab editions'), "https://#{ApplicationHelper.promo_host}/features/#compare"
diff --git a/app/views/import/github/new.html.haml b/app/views/import/github/new.html.haml
index 3f7f929f766..ef6479f8be2 100644
--- a/app/views/import/github/new.html.haml
+++ b/app/views/import/github/new.html.haml
@@ -23,7 +23,7 @@
= form_tag personal_access_token_import_github_path, method: :post do
.form-group
%label.label-bold= _('Personal Access Token')
- = text_field_tag :personal_access_token, '', class: 'form-control', placeholder: _('e.g. %{token}') % { token: '8d3f016698e...' }, data: { qa_selector: 'personal_access_token_field' }
+ = text_field_tag :personal_access_token, '', class: 'form-control gl-form-input', placeholder: _('e.g. %{token}') % { token: '8d3f016698e...' }, data: { qa_selector: 'personal_access_token_field' }
%span.form-text.text-muted
= import_github_personal_access_token_message
diff --git a/app/views/issues/_issues_calendar.ics.ruby b/app/views/issues/_issues_calendar.ics.ruby
index c21c4dac9f0..4b0be661aa5 100644
--- a/app/views/issues/_issues_calendar.ics.ruby
+++ b/app/views/issues/_issues_calendar.ics.ruby
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
# frozen_string_literal: true
cal = Icalendar::Calendar.new
@@ -17,3 +18,5 @@ end
# rubocop: enable CodeReuse/ActiveRecord
cal.to_ical
+
+# rubocop:enable Naming/FileName
diff --git a/app/views/jira_connect/branches/new.html.haml b/app/views/jira_connect/branches/new.html.haml
index f0e34c30018..74d547e6bb8 100644
--- a/app/views/jira_connect/branches/new.html.haml
+++ b/app/views/jira_connect/branches/new.html.haml
@@ -1,5 +1,6 @@
- @hide_breadcrumbs = true
- @hide_top_links = true
+- @content_class = 'limit-container-width'
- page_title _('New branch')
.js-jira-connect-create-branch{ data: @new_branch_data }
diff --git a/app/views/jira_connect/subscriptions/index.html.haml b/app/views/jira_connect/subscriptions/index.html.haml
index cbe9a860210..be2be7288f8 100644
--- a/app/views/jira_connect/subscriptions/index.html.haml
+++ b/app/views/jira_connect/subscriptions/index.html.haml
@@ -9,20 +9,9 @@
= link_to _('Sign in to GitLab'), jira_connect_users_path, target: '_blank', rel: 'noopener noreferrer', class: 'js-jira-connect-sign-in'
%main.jira-connect-app.gl-px-5.gl-pt-7.gl-mx-auto
- - if current_user.blank? && @subscriptions.empty?
- .jira-connect-app-body.gl-px-5.gl-text-center
- %h2= s_('JiraService|GitLab for Jira Configuration')
- %p= s_('JiraService|Sign in to GitLab.com to get started.')
+ .js-jira-connect-app{ data: jira_connect_app_data(@subscriptions) }
- .gl-mt-7
- = external_link _('Sign in to GitLab'), jira_connect_users_path, class: "btn gl-button btn-confirm js-jira-connect-sign-in"
-
- .gl-mt-7
- %p= s_('Integrations|Note: this integration only works with accounts on GitLab.com (SaaS).')
- - else
- .js-jira-connect-app{ data: jira_connect_app_data(@subscriptions) }
-
- %p.jira-connect-app-body.gl-px-5.gl-mt-7.gl-font-base.gl-text-center
+ %p.jira-connect-app-body.gl-px-5.gl-font-base.gl-text-center.gl-mx-auto
%strong= s_('Integrations|Browser limitations')
- browser_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'
- firefox_link_start = browser_link_start.html_safe % { url: 'https://www.mozilla.org/en-US/firefox/' }
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index a89c621a55c..5ca4a2f9888 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -92,3 +92,5 @@
= render 'layouts/google_analytics' if extra_config.has_key?('google_analytics_id')
= render 'layouts/matomo' if extra_config.has_key?('matomo_url') && extra_config.has_key?('matomo_site_id')
= render 'layouts/snowplow'
+ -# This is needed by [GitLab JH](https://gitlab.com/gitlab-jh/gitlab/-/issues/184)
+ = render_if_exists "layouts/frontend_monitor"
diff --git a/app/views/layouts/_loading_hints.html.haml b/app/views/layouts/_loading_hints.html.haml
index e2189009045..9b2815ea9bc 100644
--- a/app/views/layouts/_loading_hints.html.haml
+++ b/app/views/layouts/_loading_hints.html.haml
@@ -1,4 +1,4 @@
-= cache_if(Feature.enabled?(:cached_loading_hints, current_user), [ActionController::Base.asset_host, user_application_theme, user_color_scheme], expires_in: 1.minute) do
+= cache([ActionController::Base.asset_host, user_application_theme, user_color_scheme], expires_in: 1.minute) do
- css_crossorigin = ActionController::Base.asset_host ? 'anonymous' : nil
- if ActionController::Base.asset_host
@@ -11,5 +11,5 @@
= preload_link_tag(path_to_stylesheet('application_utilities'), crossorigin: css_crossorigin)
= preload_link_tag(path_to_stylesheet('application'), crossorigin: css_crossorigin)
= preload_link_tag(path_to_stylesheet("highlight/themes/#{user_color_scheme}"), crossorigin: css_crossorigin)
- - if Gitlab::Tracking.enabled? && Gitlab::CurrentSettings.snowplow_collector_hostname
- %link{ rel: 'preconnect', href: Gitlab::CurrentSettings.snowplow_collector_hostname, crossorigin: '' }
+ - if Gitlab::Tracking.enabled? && Gitlab::Tracking.collector_hostname
+ %link{ rel: 'preconnect', href: Gitlab::Tracking.collector_hostname, crossorigin: '' }
diff --git a/app/views/layouts/_published_experiments.html.haml b/app/views/layouts/_published_experiments.html.haml
new file mode 100644
index 00000000000..717e1e633d2
--- /dev/null
+++ b/app/views/layouts/_published_experiments.html.haml
@@ -0,0 +1,4 @@
+= javascript_tag(nonce: content_security_policy_nonce) do
+ :plain
+ gl = window.gl || {};
+ gl.experiments = #{raw ApplicationExperiment.published_experiments.reject { |name, data| data[:excluded] }.to_json};
diff --git a/app/views/layouts/_snowplow.html.haml b/app/views/layouts/_snowplow.html.haml
index fc3b12acc46..7e242fb4a8e 100644
--- a/app/views/layouts/_snowplow.html.haml
+++ b/app/views/layouts/_snowplow.html.haml
@@ -10,5 +10,6 @@
window.snowplowOptions = #{Gitlab::Tracking.options(@group).to_json}
gl = window.gl || {};
- gl.snowplowStandardContext = #{Gitlab::Tracking::StandardContext.new.to_context.to_json.to_json}
+ gl.snowplowStandardContext = #{Gitlab::Tracking::StandardContext.new(namespace: @group || @project&.namespace,
+ project: @project, user: current_user).to_context.to_json.to_json}
gl.snowplowPseudonymizedPageUrl = #{masked_page_url.to_json};
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 899bf65de48..26e3d9b3b92 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -16,4 +16,5 @@
= render 'layouts/img_loader'
+ = render 'layouts/published_experiments'
= yield :scripts_body
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 8d28823bfa4..83e8ff79aec 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -120,7 +120,7 @@
- sign_in_text = allow_signup? ? _('Sign in / Register') : _('Sign in')
= link_to sign_in_text, new_session_path(:user, redirect_to_referer: 'yes'), class: 'gl-button btn btn-default btn-sign-in'
- %button.navbar-toggler.d-block.d-sm-none{ type: 'button', class: 'gl-border-none!', data: { testid: 'top-nav-responsive-toggle' } }
+ %button.navbar-toggler.d-block.d-sm-none{ type: 'button', class: 'gl-border-none!', data: { testid: 'top-nav-responsive-toggle', qa_selector: 'mobile_navbar_button' } }
%span.sr-only= _('Toggle navigation')
%span.more-icon.gl-px-3.gl-font-sm.gl-font-weight-bold
%span.gl-pr-2= _('Menu')
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
index 01e59b8e2ef..a03cd4cd68f 100644
--- a/app/views/layouts/header/_help_dropdown.html.haml
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -10,7 +10,7 @@
%li
%button.js-shortcuts-modal-trigger{ type: "button" }
= _("Keyboard shortcuts")
- %span.text-secondary.float-right{ "aria-hidden": "true" }= '?'.html_safe
+ %kbd.flat.float-right{ "aria-hidden": "true" }= '?'.html_safe
%li.divider
%li
= link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback"
diff --git a/app/views/layouts/header/_logo_with_title.html.haml b/app/views/layouts/header/_logo_with_title.html.haml
index 9b5a47306d2..0b9d4e2eea4 100644
--- a/app/views/layouts/header/_logo_with_title.html.haml
+++ b/app/views/layouts/header/_logo_with_title.html.haml
@@ -1,4 +1,4 @@
%header.navbar.fixed-top.navbar-gitlab.justify-content-center
- = render 'shared/logo.svg'
+ = render partial: 'shared/logo', formats: :svg
%span.logo-text.d-none.d-lg-block.gl-ml-3.pt-1
- = render 'shared/logo_type.svg'
+ = render partial: 'shared/logo_type', formats: :svg
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
index 02a37dac158..3c52c430868 100644
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ b/app/views/layouts/nav/_breadcrumbs.html.haml
@@ -6,7 +6,7 @@
%nav.breadcrumbs{ class: [container, @content_class], 'aria-label': _('Breadcrumbs') }
.breadcrumbs-container{ class: ("border-bottom-0" if @no_breadcrumb_border) }
- if defined?(@left_sidebar)
- = button_tag class: 'toggle-mobile-nav', type: 'button' do
+ = button_tag class: 'toggle-mobile-nav', data: { qa_selector: 'toggle_mobile_nav_button' }, type: 'button' do
%span.sr-only= _("Open sidebar")
= sprite_icon('hamburger', size: 18)
.breadcrumbs-links{ data: { testid: 'breadcrumb-links', qa_selector: 'breadcrumb_links_content' } }
@@ -16,7 +16,7 @@
- if @breadcrumbs_extra_links
- @breadcrumbs_extra_links.each do |extra|
= breadcrumb_list_item link_to(extra[:text], extra[:link])
- = render "layouts/nav/breadcrumbs/collapsed_dropdown", location: :after
+ = render "layouts/nav/breadcrumbs/collapsed_inline_list", location: :after
- unless @skip_current_level_breadcrumb
%li
%h2.breadcrumbs-sub-title{ data: { qa_selector: 'breadcrumb_sub_title_content' } }
diff --git a/app/views/layouts/nav/_top_nav_responsive.html.haml b/app/views/layouts/nav/_top_nav_responsive.html.haml
index 86fd8b6d80c..22a260b5c0c 100644
--- a/app/views/layouts/nav/_top_nav_responsive.html.haml
+++ b/app/views/layouts/nav/_top_nav_responsive.html.haml
@@ -2,4 +2,5 @@
- view_model = top_nav_responsive_view_model(project: @project, group: @group)
.top-nav-responsive{ class: top_class }
- #js-top-nav-responsive{ data: { view_model: view_model.to_json } }
+ .cloak-startup
+ #js-top-nav-responsive{ data: { view_model: view_model.to_json } }
diff --git a/app/views/layouts/nav/breadcrumbs/_collapsed_dropdown.html.haml b/app/views/layouts/nav/breadcrumbs/_collapsed_dropdown.html.haml
deleted file mode 100644
index 8ea75087fed..00000000000
--- a/app/views/layouts/nav/breadcrumbs/_collapsed_dropdown.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-- dropdown_location = local_assigns.fetch(:location, nil)
-- button_tooltip = local_assigns.fetch(:title, _("Show parent pages"))
-- if defined?(@breadcrumb_dropdown_links) && @breadcrumb_dropdown_links.key?(dropdown_location)
- %li.dropdown
- %button.text-expander.has-tooltip.js-breadcrumbs-collapsed-expander{ type: "button", data: { toggle: "dropdown", container: "body" }, "aria-label": button_tooltip, title: button_tooltip }
- = sprite_icon("ellipsis_h", size: 12)
- = sprite_icon("angle-right", size: 8, css_class: "breadcrumbs-list-angle")
- .dropdown-menu
- %ul
- - @breadcrumb_dropdown_links[dropdown_location].each_with_index do |link, index|
- %li{ style: "text-indent: #{[index * 16, 60].min}px;" }= link
diff --git a/app/views/layouts/nav/breadcrumbs/_collapsed_inline_list.html.haml b/app/views/layouts/nav/breadcrumbs/_collapsed_inline_list.html.haml
new file mode 100644
index 00000000000..ccb660c050e
--- /dev/null
+++ b/app/views/layouts/nav/breadcrumbs/_collapsed_inline_list.html.haml
@@ -0,0 +1,11 @@
+- dropdown_location = local_assigns.fetch(:location, nil)
+- button_tooltip = local_assigns.fetch(:title, _("Show all breadcrumbs"))
+- if defined?(@breadcrumb_collapsed_links) && @breadcrumb_collapsed_links.key?(dropdown_location)
+ %li.expander
+ %button.text-expander.has-tooltip.js-breadcrumbs-collapsed-expander{ type: "button", data: { container: "body" }, "aria-label": button_tooltip, title: button_tooltip }
+ = sprite_icon("ellipsis_h", size: 12)
+ = sprite_icon("angle-right", size: 8, css_class: "breadcrumbs-list-angle")
+ - @breadcrumb_collapsed_links[dropdown_location].each_with_index do |link, index|
+ %li{ :class => "gl-display-none! breadcrumbs-detail-item" }
+ = link
+ = sprite_icon("angle-right", size: 8, css_class: "breadcrumbs-list-angle")
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 842fb23d24a..f820f911d61 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -66,9 +66,9 @@
= _('Analytics')
%li.divider.fly-out-top-item
= nav_link(controller: :dev_ops_report) do
- = link_to admin_dev_ops_report_path, title: _('DevOps Report') do
+ = link_to admin_dev_ops_report_path, title: _('DevOps Reports') do
%span
- = _('DevOps Report')
+ = _('DevOps Reports')
= nav_link(controller: :usage_trends) do
= link_to admin_usage_trends_path, title: _('Usage Trends') do
%span
diff --git a/app/views/layouts/terms.html.haml b/app/views/layouts/terms.html.haml
index 4d5c354388f..caa46b7bc56 100644
--- a/app/views/layouts/terms.html.haml
+++ b/app/views/layouts/terms.html.haml
@@ -1,21 +1,22 @@
!!! 5
+- add_page_specific_style 'page_bundles/terms'
- @hide_breadcrumbs = true
%html{ lang: I18n.locale, class: page_class }
= render "layouts/head"
%body{ data: { page: body_data_page } }
.layout-page.terms{ class: page_class }
- .content-wrapper
+ .content-wrapper.gl-pb-5
.mobile-overlay
.alert-wrapper
= render "layouts/broadcast"
= render 'layouts/header/read_only_banner'
- = render "layouts/flash", extra_flash_class: 'limit-container-width'
+ = render "layouts/flash"
%div{ class: "#{container_class} limit-container-width" }
.content{ id: "content-body" }
- .card
- .card-header
+ .gl-card
+ .gl-card-header
= brand_header_logo
- logo_text = brand_header_logo_type
- if logo_text.present?
diff --git a/app/views/notify/in_product_marketing_email.html.haml b/app/views/notify/in_product_marketing_email.html.haml
index 6382718480f..a85fa7c519f 100644
--- a/app/views/notify/in_product_marketing_email.html.haml
+++ b/app/views/notify/in_product_marketing_email.html.haml
@@ -166,10 +166,11 @@
= about_link('mailers/in_product_marketing/gitlab-logo-gray-rgb.png', 200)
%tr
%td{ "aria-hidden" => "true", height: "30", style: "font-size: 0; line-height: 0;" }
- %tr{ style: "background-color: #ffffff;" }
- %td{ style: "color: #424242; padding: 10px 30px; text-align: center; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;font-size: 16px; line-height: 22px; border: 1px solid #dddddd" }
- %p
- = @message.progress.html_safe
+ - if @message.series?
+ %tr{ style: "background-color: #ffffff;" }
+ %td{ style: "color: #424242; padding: 10px 30px; text-align: center; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;font-size: 16px; line-height: 22px; border: 1px solid #dddddd" }
+ %p
+ = @message.progress.html_safe
%tr
%td{ bgcolor: "#ffffff", height: "auto", style: "max-width: 600px; width: 100%; text-align: center; height: 200px; padding: 25px 15px; mso-line-height-rule: exactly; min-height: 40px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;", valign: "middle", width: "100%" }
= inline_image_link(@message.logo_path, { width: '150', style: 'width: 150px;' })
@@ -210,6 +211,12 @@
%td{ style: "padding: 10px 20px 30px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 18px; line-height: 24px;" }
%p{ style: "margin: 0 0 50px 0;" }
= @message.feedback_thanks
+ - if @message.invite_members?
+ %tr
+ %td{ align: "center", style: "padding: 0 20px 80px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
+ = @message.invite_text
+ %br
+ = @message.invite_link
%tr{ style: "background-color: #ffffff;" }
%td{ align: "center", style: "padding:75px 20px 25px;" }
= about_link('gitlab_logo.png', 80)
diff --git a/app/views/notify/in_product_marketing_email.text.erb b/app/views/notify/in_product_marketing_email.text.erb
index 6f0a2efa410..79a366eb1cc 100644
--- a/app/views/notify/in_product_marketing_email.text.erb
+++ b/app/views/notify/in_product_marketing_email.text.erb
@@ -21,6 +21,10 @@
<%= @message.feedback_thanks %>
<% end %>
+<% if @message.invite_members? %>
+<%= @message.invite_text %>
+<%= @message.invite_link %>
+<% end %>
diff --git a/app/views/notify/member_access_denied_email.html.haml b/app/views/notify/member_access_denied_email.html.haml
index 11661a423dd..eeef66d353d 100644
--- a/app/views/notify/member_access_denied_email.html.haml
+++ b/app/views/notify/member_access_denied_email.html.haml
@@ -2,6 +2,11 @@
%td.text-content
%p
Your request to join the
- #{link_to member_source.human_name, member_source.web_url, class: :highlight} #{member_source.model_name.singular}
- has been #{content_tag :span, 'denied', class: :highlight}.
+
+ - if @source_hidden
+ #{content_tag :span, 'Hidden', class: :highlight}
+ - else
+ #{link_to member_source.human_name, member_source.web_url, class: :highlight}
+
+ #{member_source.model_name.singular} has been #{content_tag :span, 'denied', class: :highlight}.
diff --git a/app/views/notify/member_access_granted_email.html.haml b/app/views/notify/member_access_granted_email.html.haml
index e28a10a243f..cce36f7b8a6 100644
--- a/app/views/notify/member_access_granted_email.html.haml
+++ b/app/views/notify/member_access_granted_email.html.haml
@@ -8,7 +8,11 @@
%td.text-content
%p
= _('You have been granted %{access_level} access to the %{source_link} %{source_type}.').html_safe % { access_level: access_level, source_link: source_link, source_type: source_type }
+ - if member.tasks_to_be_done.present?
+ = s_("InviteEmail|You were assigned the following tasks:")
+ %ul.list-style-position-inside
+ - member.tasks_to_be_done.each do |task|
+ %li= localized_tasks_to_be_done_choices[task]
%p
- leave_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: leave_link }
= _('If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}.').html_safe % { source_type: source_type, leave_link_start: leave_link_start, link_end: link_end }
-
diff --git a/app/views/notify/member_invited_email.html.haml b/app/views/notify/member_invited_email.html.haml
index 5489a2ac6a1..1d1f696e1b2 100644
--- a/app/views/notify/member_invited_email.html.haml
+++ b/app/views/notify/member_invited_email.html.haml
@@ -24,6 +24,11 @@
%p
- if member.created_by
= html_escape(s_("InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders.merge({ inviter: (link_to inviter_name, user_url(member.created_by)).html_safe })
+ - if member.tasks_to_be_done.present?
+ = s_("InviteEmail|and has assigned you the following tasks:")
+ %ul.list-style-position-inside
+ - member.tasks_to_be_done.each do |task|
+ %li= localized_tasks_to_be_done_choices[task]
- else
= html_escape(s_("InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders
%p.invite-actions
diff --git a/app/views/profiles/_event_table.html.haml b/app/views/profiles/_event_table.html.haml
index f74902a3c3b..67c649a9fce 100644
--- a/app/views/profiles/_event_table.html.haml
+++ b/app/views/profiles/_event_table.html.haml
@@ -3,10 +3,11 @@
%ul.content-list
- events.each do |event|
- %li
- %span.description
- = audit_icon(event.details[:with], css_class: 'gl-mr-2')
- = _('Signed in with %{authentication} authentication') % { authentication: event.details[:with]}
- %span.float-right= time_ago_with_tooltip(event.created_at)
+ - if event.success?
+ %li
+ %span.description
+ = audit_icon('key', css_class: 'gl-mr-2')
+ = _('Signed in with %{authentication} authentication') % { authentication: event.provider }
+ %span.float-right= time_ago_with_tooltip(event.created_at)
= paginate events, theme: "gitlab"
diff --git a/app/views/profiles/audit_log.html.haml b/app/views/profiles/audit_log.html.haml
index aec855c790e..4bbb4a21b39 100644
--- a/app/views/profiles/audit_log.html.haml
+++ b/app/views/profiles/audit_log.html.haml
@@ -6,6 +6,6 @@
%h4.gl-mt-0
= page_title
%p
- = _('This is a security log of important events involving your account.')
+ = _('This is a security log of authentication events involving your account.')
.col-lg-8
= render 'event_table', events: @events
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
index 35bdfbb1c29..0cfe65994da 100644
--- a/app/views/profiles/emails/index.html.haml
+++ b/app/views/profiles/emails/index.html.haml
@@ -44,7 +44,7 @@
%span.badge.badge-muted.badge-pill.gl-badge.badge-info= s_('Profiles|Public email')
- if @primary_email === current_user.notification_email_or_default
%span.badge.badge-muted.badge-pill.gl-badge.badge-info= s_('Profiles|Default notification email')
- - @emails.each do |email|
+ - @emails.reject(&:user_primary_email?).each do |email|
%li{ data: { qa_selector: 'email_row_content' } }
= render partial: 'shared/email_with_badge', locals: { email: email.email, verified: email.confirmed? }
%span.float-right
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 3e41f107e04..b1470520eea 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -71,7 +71,7 @@
placeholder: s_("Profiles|What's your status?")
.checkbox-icon-inline-wrapper
= status_form.check_box :availability, { data: { testid: "user-availability-checkbox" }, label: s_("Profiles|Busy"), wrapper_class: 'gl-mr-0 gl-font-weight-bold' }, availability["busy"], availability["not_set"]
- .gl-text-gray-600.gl-ml-5= s_('Profiles|"Busy" will be shown next to your name')
+ .gl-text-gray-600.gl-ml-5= s_('Profiles|An indicator appears next to your name and avatar')
.col-lg-12
%hr
.row.user-time-preferences.js-search-settings-section
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 00df8608957..0eae3c95bf6 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -43,7 +43,9 @@
.gl-alert.gl-alert-danger.gl-mb-5
.gl-alert-container
.gl-alert-content
- = @error
+ %p.gl-alert-body.gl-md-0
+ = @error[:message]
+ = link_to _('Try the troubleshooting steps here.'), help_page_path('user/profile/account/two_factor_authentication.md', anchor: 'troubleshooting'), target: '_blank', rel: 'noopener noreferrer'
.form-group
= label_tag :pin_code, _('Pin code'), class: "label-bold"
= text_field_tag :pin_code, nil, class: "form-control gl-form-input", required: true, data: { qa_selector: 'pin_code_field' }
diff --git a/app/views/projects/_invite_members_side_nav_link.html.haml b/app/views/projects/_invite_members_side_nav_link.html.haml
new file mode 100644
index 00000000000..ea6174d19f0
--- /dev/null
+++ b/app/views/projects/_invite_members_side_nav_link.html.haml
@@ -0,0 +1,8 @@
+.js-invite-members-trigger{ data: { trigger_source: 'project-side-nav',
+ classes: 'gl-text-decoration-none! gl-shadow-none! gl-text-body!',
+ icon: 'users',
+ display_text: title,
+ trigger_element: 'side-nav'} }
+
+= render partial: 'shared/nav/sidebar_submenu', locals: { sidebar_menu: sidebar_menu }
+= render 'projects/invite_members_modal', project: project
diff --git a/app/views/projects/_merge_request_merge_commit_template.html.haml b/app/views/projects/_merge_request_merge_commit_template.html.haml
new file mode 100644
index 00000000000..185b730e0bb
--- /dev/null
+++ b/app/views/projects/_merge_request_merge_commit_template.html.haml
@@ -0,0 +1,17 @@
+- form = local_assigns.fetch(:form)
+
+.form-group
+ %b= s_('ProjectSettings|Merge commit message template')
+ %p.text-secondary
+ - configure_the_merge_commit_message_help_link_url = help_page_path('user/project/merge_requests/commit_templates.md', anchor: 'merge-commit-message-template')
+ - configure_the_merge_commit_message_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configure_the_merge_commit_message_help_link_url }
+ = s_('ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}').html_safe % { link_start: configure_the_merge_commit_message_help_link_start, link_end: '</a>'.html_safe }
+ .mb-2
+ - default_merge_commit_template = "Merge branch '%{source_branch}' into '%{target_branch}'\n\n%{title}\n\n%{issues}\n\nSee merge request %{reference}"
+ = form.text_area :merge_commit_template, class: 'form-control gl-form-input', rows: 8, maxlength: 500, placeholder: default_merge_commit_template
+ %p.form-text.text-muted
+ = s_('ProjectSettings|Maximum 500 characters.')
+ = s_('ProjectSettings|Supported variables:')
+ - Gitlab::MergeRequests::MergeCommitMessage::PLACEHOLDERS.keys.each do |placeholder|
+ %code
+ = "%{#{placeholder}}".html_safe
diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml
index f595b4f709b..c5a25bec6eb 100644
--- a/app/views/projects/_merge_request_settings.html.haml
+++ b/app/views/projects/_merge_request_settings.html.haml
@@ -10,5 +10,7 @@
= render 'projects/merge_request_merge_suggestions_settings', project: @project, form: form
+= render 'projects/merge_request_merge_commit_template', project: @project, form: form
+
- if @project.forked?
= render 'projects/merge_request_target_project_settings', project: @project, form: form
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index 256c3ebad0a..c21240b340c 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -40,12 +40,17 @@
.form-group.project-path.col-sm-6
= f.label :path, class: 'label-bold' do
%span= _("Project slug")
- = f.text_field :path, placeholder: "my-awesome-project", class: "form-control gl-form-input", required: true, aria: { required: true }
+ = f.text_field :path, placeholder: "my-awesome-project", class: "form-control gl-form-input", required: true, aria: { required: true }, data: { username: current_user.username }
- if current_user.can_create_group?
.form-text.text-muted
- link_start_group_path = '<a href="%{path}">' % { path: new_group_path }
- project_tip = s_('ProjectsNew|Want to house several dependent projects under the same namespace? %{link_start}Create a group.%{link_end}') % { link_start: link_start_group_path, link_end: '</a>' }
= project_tip.html_safe
+.gl-alert.gl-alert-success.gl-mb-4.gl-display-none.js-user-readme-repo
+ = sprite_icon('check-circle', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-body
+ - help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/profile/index', anchor: 'user-profile-readme') }
+ = html_escape(_('%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}')) % { project_path: "<strong>#{current_user.username} / #{current_user.username}</strong>".html_safe, help_link_start: help_link_start, help_link_end: '</a>'.html_safe }
.form-group
= f.label :description, class: 'label-bold' do
@@ -72,7 +77,7 @@
- e.try do
.form-group
.form-check.gl-mb-3
- = check_box_tag 'project[initialize_with_sast]', '1', true, class: 'form-check-input', data: { track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
+ = check_box_tag 'project[initialize_with_sast]', '1', true, class: 'form-check-input', data: { qa_selector: 'initialize_with_sast_checkbox', track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
= label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
= s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
.form-text.text-muted
@@ -81,7 +86,7 @@
- e.try(:free_indicator) do
.form-group
.form-check.gl-mb-3
- = check_box_tag 'project[initialize_with_sast]', '1', true, class: 'form-check-input', data: { track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
+ = check_box_tag 'project[initialize_with_sast]', '1', true, class: 'form-check-input', data: { qa_selector: 'initialize_with_sast_checkbox', track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
= label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
= s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
%span.badge.badge-info.badge-pill.gl-badge.sm= _('Free')
diff --git a/app/views/projects/_remove.html.haml b/app/views/projects/_remove.html.haml
index cb0ec9f19c8..815e76ebcb9 100644
--- a/app/views/projects/_remove.html.haml
+++ b/app/views/projects/_remove.html.haml
@@ -1,4 +1,6 @@
- return unless can?(current_user, :remove_project, project)
+- merge_requests_count = Projects::AllMergeRequestsCountService.new(project).count
+- issues_count = Projects::AllIssuesCountService.new(project).count
.sub-section
%h4.danger-title= _('Delete project')
@@ -7,4 +9,4 @@
= link_to _('Learn more.'), help_page_path('user/project/settings/index', anchor: 'removing-a-fork-relationship'), target: '_blank', rel: 'noopener noreferrer'
%p
%strong= _('Deleted projects cannot be restored!')
- #js-project-delete-button{ data: { form_path: project_path(project), confirm_phrase: project.path } }
+ #js-project-delete-button{ data: { form_path: project_path(project), confirm_phrase: delete_confirm_phrase(project), is_fork: project.forked?.to_s, issues_count: number_with_delimiter(issues_count), merge_requests_count: number_with_delimiter(merge_requests_count), forks_count: number_with_delimiter(project.forks_count), stars_count: number_with_delimiter(project.star_count) } }
diff --git a/app/views/projects/_remove_fork.html.haml b/app/views/projects/_remove_fork.html.haml
index 8fa21966683..92eb29dc407 100644
--- a/app/views/projects/_remove_fork.html.haml
+++ b/app/views/projects/_remove_fork.html.haml
@@ -8,4 +8,4 @@
%p
%strong= _('Once removed, the fork relationship cannot be restored. This project will no longer be able to receive or send merge requests to the source project or other forks.')
= link_to _('Learn more.'), help_page_path('user/project/settings/index', anchor: 'removing-a-fork-relationship'), target: '_blank', rel: 'noopener noreferrer'
- = button_to _('Remove fork relationship'), '#', class: "gl-button btn btn-danger js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_warning_message(@project) }
+ = button_to _('Remove fork relationship'), '#', class: "gl-button btn btn-danger js-legacy-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_warning_message(@project) }
diff --git a/app/views/projects/_service_desk_settings.html.haml b/app/views/projects/_service_desk_settings.html.haml
index 7b345941cf7..63cf4dfe0ab 100644
--- a/app/views/projects/_service_desk_settings.html.haml
+++ b/app/views/projects/_service_desk_settings.html.haml
@@ -14,8 +14,9 @@
custom_email: (@project.service_desk_custom_address if @project.service_desk_enabled),
custom_email_enabled: "#{Gitlab::ServiceDeskEmail.enabled?}",
selected_template: "#{@project.service_desk_setting&.issue_template_key}",
+ selected_file_template_project_id: "#{@project.service_desk_setting&.file_template_project_id}",
outgoing_name: "#{@project.service_desk_setting&.outgoing_name}",
project_key: "#{@project.service_desk_setting&.project_key}",
- templates: issuable_templates_names(Issue.new) } }
+ templates: available_service_desk_templates_for(@project) } }
- elsif show_callout?('promote_service_desk_dismissed')
= render 'shared/promotions/promote_servicedesk'
diff --git a/app/views/projects/_transfer.html.haml b/app/views/projects/_transfer.html.haml
index ee717c2deca..e48008e1cc6 100644
--- a/app/views/projects/_transfer.html.haml
+++ b/app/views/projects/_transfer.html.haml
@@ -14,4 +14,4 @@
= label_tag :new_namespace_id, _('Select a new namespace'), class: 'gl-font-weight-bold'
.form-group
= select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2'
- = f.submit 'Transfer project', class: "gl-button btn btn-danger js-confirm-danger qa-transfer-button", data: { "confirm-danger-message" => transfer_project_message(@project) }
+ = f.submit 'Transfer project', class: "gl-button btn btn-danger js-legacy-confirm-danger qa-transfer-button", data: { "confirm-danger-message" => transfer_project_message(@project) }
diff --git a/app/views/projects/_visibility_modal.html.haml b/app/views/projects/_visibility_modal.html.haml
index f75216a71b6..db98b978f04 100644
--- a/app/views/projects/_visibility_modal.html.haml
+++ b/app/views/projects/_visibility_modal.html.haml
@@ -20,10 +20,10 @@
%li
= _("Current forks will keep their visibility level.").html_safe
%label{ for: "confirm_path_input" }
- = _("To confirm, type %{phrase_code}").html_safe % { phrase_code: '<code class="js-confirm-danger-match">%{phrase_name}</code>'.html_safe % { phrase_name: @project.full_path } }
+ = _("To confirm, type %{phrase_code}").html_safe % { phrase_code: '<code class="js-legacy-confirm-danger-match">%{phrase_name}</code>'.html_safe % { phrase_name: @project.full_path } }
.form-group
- = text_field_tag 'confirm_path_input', '', class: 'form-control js-confirm-danger-input qa-confirm-input'
+ = text_field_tag 'confirm_path_input', '', class: 'form-control js-legacy-confirm-danger-input qa-confirm-input'
.form-actions
%button.btn.gl-button.btn-default.gl-mr-4{ type: "button", "data-dismiss": "modal" }
= _('Cancel')
- = submit_tag _('Reduce project visibility'), class: "btn gl-button btn-danger js-confirm-danger-submit qa-confirm-button", disabled: true
+ = submit_tag _('Reduce project visibility'), class: "btn gl-button btn-danger js-legacy-confirm-danger-submit qa-confirm-button", disabled: true
diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml
index 30c052e054f..704576619a7 100644
--- a/app/views/projects/blame/show.html.haml
+++ b/app/views/projects/blame/show.html.haml
@@ -20,7 +20,7 @@
%span.legend-box.legend-box-9
%span.right-label Older
- .table-responsive.file-content.blame.code.js-syntax-highlight
+ .table-responsive.file-content.blame.code{ class: user_color_scheme }
%table
- current_line = 1
- @blame.groups.each do |blame_group|
diff --git a/app/views/projects/blob/_header.html.haml b/app/views/projects/blob/_header.html.haml
index d7668dd1c91..dad4ea205b4 100644
--- a/app/views/projects/blob/_header.html.haml
+++ b/app/views/projects/blob/_header.html.haml
@@ -10,7 +10,7 @@
= edit_blob_button(@project, @ref, @path, blob: blob)
= ide_edit_button(@project, @ref, @path, blob: blob)
- if can_view_pipeline_editor?(@project) && @path == @project.ci_config_path_or_default
- = link_to "Pipeline Editor", project_ci_pipeline_editor_path(@project), class: "btn gl-button btn-confirm-secondary gl-ml-3"
+ = link_to "Pipeline Editor", project_ci_pipeline_editor_path(@project, branch_name: @ref), class: "btn gl-button btn-confirm-secondary gl-ml-3"
.btn-group{ role: "group", class: ("gl-ml-3" if current_user) }>
= render_if_exists 'projects/blob/header_file_locks_link'
- if current_user
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index ecbef9a11a7..8378ce2c7e5 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -16,14 +16,10 @@
%h3.page-title.blob-edit-page-title
Edit file
.file-editor
- %ul.nav-links.no-bottom.js-edit-mode.nav.nav-tabs
- %li.active
- = link_to '#editor' do
- Write
+ = gl_tabs_nav({ class: 'js-edit-mode nav-links gl-border-0'}) do
+ = gl_tab_link_to _('Write'), '#editor', { tab_class: 'active' }
- %li
- = link_to '#preview', 'data-preview-url' => project_preview_blob_path(@project, @id) do
- = editing_preview_title(@blob.name)
+ = gl_tab_link_to editing_preview_title(@blob.name), '#preview', { data: { 'preview-url': project_preview_blob_path(@project, @id) } }
= form_tag(project_update_blob_path(@project, @id), method: :put, class: 'js-quick-submit js-requires-input js-edit-blob-form', data: blob_editor_paths(@project)) do
= render 'projects/blob/editor', ref: @ref, path: @path, blob_data: @blob.data
diff --git a/app/views/projects/blob/viewers/_changelog.html.haml b/app/views/projects/blob/viewers/_changelog.html.haml
index cac858c1444..5f3b9285ea9 100644
--- a/app/views/projects/blob/viewers/_changelog.html.haml
+++ b/app/views/projects/blob/viewers/_changelog.html.haml
@@ -1,3 +1,3 @@
= sprite_icon('history', css_class: 'gl-mr-1 gl-vertical-align-text-bottom')
= succeed '.' do
- = _("To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}.").html_safe % { link_start: "<a href='#{project_tags_path(viewer.project)}'>".html_safe, link_end: "</a>".html_safe }
+ = _("To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}").html_safe % { link_start: "<a href='#{project_tags_path(viewer.project)}'>".html_safe, link_end: "</a>".html_safe }
diff --git a/app/views/projects/blob/viewers/_readme.html.haml b/app/views/projects/blob/viewers/_readme.html.haml
index e06ff4edf71..c07428f0337 100644
--- a/app/views/projects/blob/viewers/_readme.html.haml
+++ b/app/views/projects/blob/viewers/_readme.html.haml
@@ -1,4 +1,4 @@
= sprite_icon('information-o', css_class: 'gl-vertical-align-middle! gl-mr-2')
= succeed '.' do
- link_to_wiki = link_to(_("the wiki"), wiki_path(viewer.project.wiki))
- = _("To learn more about this project, read %{link_to_wiki}.").html_safe % { link_to_wiki: link_to_wiki }
+ = _("To learn more about this project, read %{link_to_wiki}").html_safe % { link_to_wiki: link_to_wiki }
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 99a9535b8e8..be6efa310b9 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -23,7 +23,7 @@
- if commit
= render 'projects/branches/commit', commit: commit, project: @project
- else
- = s_('Branches|Cant find HEAD commit for this branch')
+ = s_('Branches|Can’t find HEAD commit for this branch')
- if branch.name != @repository.root_ref
.js-branch-divergence-graph
diff --git a/app/views/projects/commit/_ci_menu.html.haml b/app/views/projects/commit/_ci_menu.html.haml
index 41f5fb3dcbd..60a79456c36 100644
--- a/app/views/projects/commit/_ci_menu.html.haml
+++ b/app/views/projects/commit/_ci_menu.html.haml
@@ -1,12 +1,10 @@
- any_pipelines = @commit.present(current_user: current_user).any_pipelines?
-%ul.nav-links.no-top.no-bottom.commit-ci-menu.nav.nav-tabs
- = nav_link(path: 'commit#show') do
- = link_to project_commit_path(@project, @commit.id) do
- = _('Changes')
- %span.badge.badge-pill= @diffs.size
+= gl_tabs_nav({ class: 'commit-ci-menu gl-display-flex gl-flex-grow-1'}) do
+ = gl_tab_link_to project_commit_path(@project, @commit.id) do
+ = _('Changes')
+ = gl_tab_counter_badge(@diffs.size)
- if any_pipelines
- = nav_link(path: 'commit#pipelines') do
- = link_to pipelines_project_commit_path(@project, @commit.id) do
- = _('Pipelines')
- %span.badge.badge-pill.js-pipelines-mr-count= @commit.pipelines.size
+ = gl_tab_link_to pipelines_project_commit_path(@project, @commit.id) do
+ = _('Pipelines')
+ = gl_tab_counter_badge(@commit.pipelines.size, { class: 'js-pipelines-mr-count' })
diff --git a/app/views/projects/commit/_multiple_signatures_signature_badge.html.haml b/app/views/projects/commit/_multiple_signatures_signature_badge.html.haml
new file mode 100644
index 00000000000..74515438af2
--- /dev/null
+++ b/app/views/projects/commit/_multiple_signatures_signature_badge.html.haml
@@ -0,0 +1,6 @@
+- title = capture do
+ = html_escape(_('This commit was signed with %{strong_open}multiple%{strong_close} signatures.')) % { strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
+
+- locals = { signature: signature, title: title, label: _('Unverified'), css_class: 'invalid', icon: 'status_notfound_borderless' }
+
+= render partial: 'projects/commit/signature_badge', locals: locals
diff --git a/app/views/projects/confluences/show.html.haml b/app/views/projects/confluences/show.html.haml
index cf4e39f9659..413de90b67b 100644
--- a/app/views/projects/confluences/show.html.haml
+++ b/app/views/projects/confluences/show.html.haml
@@ -6,9 +6,8 @@
= s_('WikiEmpty|Confluence is enabled')
%p
- wiki_confluence_epic_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/3629'
- - wiki_confluence_epic_link_start = format('<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe, url: wiki_confluence_epic_link_url)
- = format(s_("WikiEmpty|You've enabled the Confluence Workspace integration. Your wiki will be viewable directly within Confluence. We are hard at work integrating Confluence more seamlessly into GitLab. If you'd like to stay up to date, follow our %{wiki_confluence_epic_link_start}Confluence epic%{wiki_confluence_epic_link_end}.").html_safe, wiki_confluence_epic_link_start: wiki_confluence_epic_link_start, wiki_confluence_epic_link_end: '</a>'.html_safe)
+ - wiki_confluence_epic_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: wiki_confluence_epic_link_url }
+ = html_escape(s_("WikiEmpty|You've enabled the Confluence Workspace integration. Your wiki will be viewable directly within Confluence. We are hard at work integrating Confluence more seamlessly into GitLab. If you'd like to stay up to date, follow our %{wiki_confluence_epic_link_start}Confluence epic%{wiki_confluence_epic_link_end}.")) % { wiki_confluence_epic_link_start: wiki_confluence_epic_link_start, wiki_confluence_epic_link_end: '</a>'.html_safe }
= link_to @project.confluence_integration.confluence_url, target: '_blank', rel: 'noopener noreferrer', class: 'gl-button btn btn-success external-url', title: s_('WikiEmpty|Go to Confluence') do
- = sprite_icon('external-link')
= s_('WikiEmpty|Go to Confluence')
-
+ = sprite_icon('external-link')
diff --git a/app/views/projects/cycle_analytics/show.html.haml b/app/views/projects/cycle_analytics/show.html.haml
index f398ac6ede7..ba79f0ee3cb 100644
--- a/app/views/projects/cycle_analytics/show.html.haml
+++ b/app/views/projects/cycle_analytics/show.html.haml
@@ -1,4 +1,6 @@
- page_title _("Value Stream Analytics")
+- data_attributes = @request_params.valid? ? @request_params.to_data_attributes : {}
+- data_attributes.merge!(cycle_analytics_initial_data(@project, @group))
- add_page_specific_style 'page_bundles/cycle_analytics'
-#js-cycle-analytics{ data: cycle_analytics_initial_data(@project, @group) }
+#js-cycle-analytics{ data: data_attributes }
diff --git a/app/views/projects/deployments/_deployment.html.haml b/app/views/projects/deployments/_deployment.html.haml
index 57dfcb8cf4a..f18574c3ad5 100644
--- a/app/views/projects/deployments/_deployment.html.haml
+++ b/app/views/projects/deployments/_deployment.html.haml
@@ -6,7 +6,7 @@
.table-section.section-10{ role: 'gridcell' }
.table-mobile-header{ role: 'rowheader' }= _("ID")
- %strong.table-mobile-content ##{deployment.iid}
+ %strong.table-mobile-content{ data: { testid: 'deployment-id' } } ##{deployment.iid}
.table-section.section-10{ role: 'gridcell' }
.table-mobile-header{ role: 'rowheader' }= _("Triggerer")
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 926a0610577..6421aef14cf 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -23,7 +23,7 @@
.js-project-permissions-form
- if show_visibility_confirm_modal?(@project)
= render "visibility_modal"
- = f.submit _('Save changes'), class: "btn gl-button btn-confirm #{('js-confirm-danger' if show_visibility_confirm_modal?(@project))}", data: { qa_selector: 'visibility_features_permissions_save_button', check_field_name: ("project[visibility_level]" if show_visibility_confirm_modal?(@project)), check_compare_value: @project.visibility_level }
+ = f.submit _('Save changes'), class: "btn gl-button btn-confirm #{('js-legacy-confirm-danger' if show_visibility_confirm_modal?(@project))}", data: { qa_selector: 'visibility_features_permissions_save_button', check_field_name: ("project[visibility_level]" if show_visibility_confirm_modal?(@project)), check_compare_value: @project.visibility_level }
%section.rspec-merge-request-settings.settings.merge-requests-feature.no-animate#js-merge-request-settings{ class: [('expanded' if expanded), ('hidden' if @project.project_feature.send(:merge_requests_access_level) == 0)], data: { qa_selector: 'merge_request_settings_content' } }
.settings-header
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 905794c0730..c3fbf774faa 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -77,5 +77,5 @@
git push -u origin --all
git push -u origin --tags
-- if @project.empty_repo_upload_experiment?
+- if @project.upload_anchor_data.present?
= render 'projects/blob/upload', title: _('Upload New File'), placeholder: _('Upload New File'), button_title: _('Upload file'), form_path: project_create_blob_path(@project, default_branch_name), ref: default_branch_name, method: :post
diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml
index 0136184f80d..72ccc8d830c 100644
--- a/app/views/projects/environments/index.html.haml
+++ b/app/views/projects/environments/index.html.haml
@@ -1,10 +1,19 @@
- page_title _("Environments")
-- add_page_specific_style 'page_bundles/environments'
-#environments-list-view{ data: { environments_data: environments_list_data,
- "can-read-environment" => can?(current_user, :read_environment, @project).to_s,
- "can-create-environment" => can?(current_user, :create_environment, @project).to_s,
- "new-environment-path" => new_project_environment_path(@project),
- "help-page-path" => help_page_path("ci/environments/index.md"),
- "project-path" => @project.full_path,
- "default-branch-name" => @project.default_branch_or_main } }
+- if Feature.enabled?(:new_environments_table)
+ #environments-table{ data: { endpoint: project_environments_path(@project, format: :json),
+ "can-read-environment" => can?(current_user, :read_environment, @project).to_s,
+ "can-create-environment" => can?(current_user, :create_environment, @project).to_s,
+ "new-environment-path" => new_project_environment_path(@project),
+ "help-page-path" => help_page_path("ci/environments/index.md"),
+ "project-path" => @project.full_path,
+ "default-branch-name" => @project.default_branch_or_main } }
+- else
+ - add_page_specific_style 'page_bundles/environments'
+ #environments-list-view{ data: { environments_data: environments_list_data,
+ "can-read-environment" => can?(current_user, :read_environment, @project).to_s,
+ "can-create-environment" => can?(current_user, :create_environment, @project).to_s,
+ "new-environment-path" => new_project_environment_path(@project),
+ "help-page-path" => help_page_path("ci/environments/index.md"),
+ "project-path" => @project.full_path,
+ "default-branch-name" => @project.default_branch_or_main } }
diff --git a/app/views/projects/google_cloud/index.html.haml b/app/views/projects/google_cloud/index.html.haml
index 4fc66e17810..69e481501d5 100644
--- a/app/views/projects/google_cloud/index.html.haml
+++ b/app/views/projects/google_cloud/index.html.haml
@@ -3,81 +3,4 @@
- @content_class = "limit-container-width" unless fluid_layout
-#js-google-cloud
-
- %h1.gl-font-size-h1 Google Cloud
-
- %section#js-section-google-cloud-service-accounts
-
- %h2.gl-font-size-h2 Service Accounts
-
- %p= _('Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project.')
-
- %table.table.b-table.gl-table
-
- %thead
- %tr
- %th Environment
- %th GCP Project ID
- %th Service Account Key
-
- %tbody
-
- %tr
- %td *
- %td serving-salutes-453
- %td .....
-
- %tr
- %td production
- %td crimson-corey-234
- %td .....
-
- %tr
- %td review/*
- %td roving-river-379
- %td .....
-
- %a.gl-button.btn.btn-primary= _('Add new service account')
-
- %br
-
- %section#js-section-google-cloud-deployments
-
- .row.row-fluid
-
- .col-lg-4
- %h2.gl-font-size-h2 Deployments
- %p= _('Google Cloud offers several deployment targets. Select the one most suitable for your project.')
- %p
- = _('Deployments to Google Kubernetes Engine can be ')
- %a{ href: '#' }= _('managed')
- = _('in Infrastructure :: Kubernetes clusters')
-
- .col-lg-8
-
- %br
-
- .gl-card.gl-mb-6
- .gl-card-body
- .gl-display-flex.gl-align-items-baseline
- %strong.gl-font-lg App Engine
- .gl-ml-auto.gl-text-gray-500 Disabled
- %p= _('App Engine description and apps that are suitable for this deployment target')
- %button.gl-button.btn.btn-default= _('Configure via Merge Request')
-
- .gl-card.gl-mb-6
- .gl-card-body
- .gl-display-flex.gl-align-items-baseline
- %strong.gl-font-lg Cloud Functions
- .gl-ml-auto.gl-text-gray-500 Disabled
- %p= _('Cloud Functions description and apps that are suitable for this deployment target')
- %button.gl-button.btn.btn-default= _('Configure via Merge Request')
-
- .gl-card.gl-mb-6
- .gl-card-body
- .gl-display-flex.gl-align-items-baseline
- %strong.gl-font-lg Cloud Run
- .gl-ml-auto.gl-text-gray-500 Disabled
- %p= _('Cloud Run description and apps that are suitable for this deployment target')
- %button.gl-button.btn.btn-default= _('Configure via Merge Request')
+#js-google-cloud{ data: @js_data }
diff --git a/app/views/projects/hook_logs/show.html.haml b/app/views/projects/hook_logs/show.html.haml
index 86dfa1929d6..f6861e4119e 100644
--- a/app/views/projects/hook_logs/show.html.haml
+++ b/app/views/projects/hook_logs/show.html.haml
@@ -2,11 +2,11 @@
- add_to_breadcrumbs _('Webhook Settings'), namespace_project_hooks_path
- page_title _('Webhook Logs')
-.row.gl-mt-3.gl-mb-3
- .col-lg-3
- %h4.gl-mt-0
- = _("Request details")
- .col-lg-9
- = link_to _('Resend Request'), @hook_log.present.retry_path, method: :post, class: "btn gl-button btn-default float-right gl-ml-3"
-
- = render partial: 'shared/hook_logs/content', locals: { hook_log: @hook_log }
+%h3.page-title
+ = _("Request details")
+
+%hr
+
+= link_to _("Resend Request"), @hook_log.present.retry_path, method: :post, class: "btn gl-button btn-default float-right gl-ml-3"
+
+= render partial: 'shared/hook_logs/content', locals: { hook_log: @hook_log }
diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml
index 2fbaa5812c0..f1c19756474 100644
--- a/app/views/projects/issues/_discussion.html.haml
+++ b/app/views/projects/issues/_discussion.html.haml
@@ -1,5 +1,4 @@
-- add_page_startup_api_call discussions_path(@issue)
-- add_page_startup_api_call notes_url
+- add_page_startup_api_call Feature.enabled?(:paginated_issue_discussions, @project, default_enabled: :yaml) ? discussions_path(@issue, per_page: 20) : discussions_path(@issue)
- @gfm_form = true
diff --git a/app/views/projects/issues/_issues.html.haml b/app/views/projects/issues/_issues.html.haml
index e4d072a9472..1ab51df6d24 100644
--- a/app/views/projects/issues/_issues.html.haml
+++ b/app/views/projects/issues/_issues.html.haml
@@ -1,5 +1,5 @@
- is_project_overview = local_assigns.fetch(:is_project_overview, false)
-= render 'shared/alerts/positioning_disabled'
+= render 'shared/alerts/positioning_disabled' if @sort == 'relative_position'
- if Feature.enabled?(:vue_issuables_list, @project) && !is_project_overview
- data_endpoint = local_assigns.fetch(:data_endpoint, expose_path(api_v4_projects_issues_path(id: @project.id)))
diff --git a/app/views/projects/issues/_service_desk_empty_state.html.haml b/app/views/projects/issues/_service_desk_empty_state.html.haml
index a4251c8e5dc..afeb2a23ea2 100644
--- a/app/views/projects/issues/_service_desk_empty_state.html.haml
+++ b/app/views/projects/issues/_service_desk_empty_state.html.haml
@@ -16,7 +16,7 @@
= s_("ServiceDesk|Your users can send emails to this address:")
%code= @project.service_desk_address
- %span= s_("ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation.")
+ %span= s_("ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation.")
= link_to _('Learn more.'), help_page_path('user/project/service_desk')
- if can_edit_project_settings && !service_desk_enabled
diff --git a/app/views/projects/issues/_service_desk_info_content.html.haml b/app/views/projects/issues/_service_desk_info_content.html.haml
index 448a341eba6..f0ec68ba54b 100644
--- a/app/views/projects/issues/_service_desk_info_content.html.haml
+++ b/app/views/projects/issues/_service_desk_info_content.html.haml
@@ -1,16 +1,17 @@
- service_desk_enabled = @project.service_desk_enabled?
- can_edit_project_settings = can?(current_user, :admin_project, @project)
+- can_admin_issues = can?(current_user, :admin_issue, @project)
- title_text = s_("ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab")
.non-empty-state.media
.svg-content
- = render 'shared/empty_states/icons/service_desk_callout.svg'
+ = render partial: 'shared/empty_states/icons/service_desk_callout', formats: :svg
.gl-mt-3.gl-ml-3
%h5= title_text
- - if can_edit_project_settings && service_desk_enabled
+ - if can_admin_issues && service_desk_enabled
%p
= s_("ServiceDesk|Your users can send emails to this address:")
%code= @project.service_desk_address
diff --git a/app/views/projects/learn_gitlab/index.html.haml b/app/views/projects/learn_gitlab/index.html.haml
index 4935b72d3fa..9b17be99da0 100644
--- a/app/views/projects/learn_gitlab/index.html.haml
+++ b/app/views/projects/learn_gitlab/index.html.haml
@@ -1,5 +1,12 @@
- breadcrumb_title _("Learn GitLab")
- page_title _("Learn GitLab")
- add_page_specific_style 'page_bundles/learn_gitlab'
+- data = learn_gitlab_data(@project)
+- invite_members_open = session.delete(:confetti_post_signup)
-#js-learn-gitlab-app{ data: { actions: onboarding_actions_data(@project).to_json, sections: onboarding_sections_data.to_json } }
+- experiment(:confetti_post_signup, actor: current_user) do |e|
+ - e.control do
+ #js-learn-gitlab-app{ data: data }
+ - e.candidate do
+ = render 'projects/invite_members_modal', project: @project
+ #js-learn-gitlab-app{ data: data.merge(invite_members_open: invite_members_open) }
diff --git a/app/views/projects/merge_requests/_widget.html.haml b/app/views/projects/merge_requests/_widget.html.haml
index 459742c3b81..0c8af873095 100644
--- a/app/views/projects/merge_requests/_widget.html.haml
+++ b/app/views/projects/merge_requests/_widget.html.haml
@@ -14,8 +14,8 @@
window.gl.mrWidgetData.pipeline_must_succeed_docs_path = '#{help_page_path('user/project/merge_requests/merge_when_pipeline_succeeds.md', anchor: 'only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds')}';
window.gl.mrWidgetData.security_approvals_help_page_path = '#{help_page_path('user/application_security/index.md', anchor: 'security-approvals-in-merge-requests')}';
window.gl.mrWidgetData.license_compliance_docs_path = '#{help_page_path('user/compliance/license_compliance/index.md', anchor: 'policies')}';
- window.gl.mrWidgetData.eligible_approvers_docs_path = '#{help_page_path('user/project/merge_requests/merge_request_approvals', anchor: 'eligible-approvers')}';
- window.gl.mrWidgetData.approvals_help_path = '#{help_page_path("user/project/merge_requests/merge_request_approvals")}';
+ window.gl.mrWidgetData.eligible_approvers_docs_path = '#{help_page_path('user/project/merge_requests/approvals/rules.md', anchor: 'eligible-approvers')}';
+ window.gl.mrWidgetData.approvals_help_path = '#{help_page_path("user/project/merge_requests/approvals/index.md")}';
window.gl.mrWidgetData.pipelines_empty_svg_path = '#{image_path('illustrations/pipelines_empty.svg')}';
window.gl.mrWidgetData.codequality_help_path = '#{help_page_path("user/project/merge_requests/code_quality", anchor: "code-quality-reports")}';
window.gl.mrWidgetData.false_positive_doc_url = '#{help_page_path('user/application_security/vulnerabilities/index')}';
diff --git a/app/views/projects/mirrors/_instructions.html.haml b/app/views/projects/mirrors/_instructions.html.haml
index a91751da0aa..2bd2c7cac44 100644
--- a/app/views/projects/mirrors/_instructions.html.haml
+++ b/app/views/projects/mirrors/_instructions.html.haml
@@ -3,7 +3,7 @@
%li
= html_escape(_('The repository must be accessible over %{code_open}http://%{code_close},
%{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} or %{code_open}git://%{code_close}.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- %li= html_escape(_('When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
+ %li= html_escape(_('When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
%li= html_escape(_('Include the username in the URL if required: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
%li
- minutes = Gitlab.config.gitlab_shell.git_timeout / 60
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index c62853145b6..4e4738ebd25 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -12,7 +12,7 @@
.row{ 'v-cloak': true }
#blank-project-pane.tab-pane.active
- = form_for @project, html: { class: 'new_project' } do |f|
+ = form_for @project, html: { class: 'new_project gl-mt-3' } do |f|
= render 'new_project_fields', f: f, project_name_id: "blank-project-name"
#create-from-template-pane.tab-pane
diff --git a/app/views/projects/pages/_no_domains.html.haml b/app/views/projects/pages/_no_domains.html.haml
index 8d6e403b93a..a537bd80d30 100644
--- a/app/views/projects/pages/_no_domains.html.haml
+++ b/app/views/projects/pages/_no_domains.html.haml
@@ -3,4 +3,4 @@
.card-header
= s_('GitLabPages|Domains')
.nothing-here-block
- = s_("GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it.")
+ = s_("GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it.")
diff --git a/app/views/projects/pipeline_schedules/_tabs.html.haml b/app/views/projects/pipeline_schedules/_tabs.html.haml
index f69041e1eb1..f825ef35902 100644
--- a/app/views/projects/pipeline_schedules/_tabs.html.haml
+++ b/app/views/projects/pipeline_schedules/_tabs.html.haml
@@ -1,18 +1,12 @@
-%ul.nav-links.mobile-separator.nav.nav-tabs
- %li{ class: active_when(scope.nil?) }>
- = link_to schedule_path_proc.call(nil) do
- = s_("PipelineSchedules|All")
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm.js-totalbuilds-count
- = number_with_delimiter(all_schedules.count(:id))
+= gl_tabs_nav({ class: 'gl-display-flex gl-flex-grow-1 gl-border-0' }) do
+ = gl_tab_link_to schedule_path_proc.call(nil), { item_active: active_when(scope.nil?) } do
+ = s_("PipelineSchedules|All")
+ = gl_tab_counter_badge(number_with_delimiter(all_schedules.count(:id)), { class: 'js-totalbuilds-count' })
- %li{ class: active_when(scope == 'active') }>
- = link_to schedule_path_proc.call('active') do
- = s_("PipelineSchedules|Active")
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm
- = number_with_delimiter(all_schedules.active.count(:id))
+ = gl_tab_link_to schedule_path_proc.call('active'), { item_active: active_when(scope == 'active') } do
+ = s_("PipelineSchedules|Active")
+ = gl_tab_counter_badge(number_with_delimiter(all_schedules.active.count(:id)))
- %li{ class: active_when(scope == 'inactive') }>
- = link_to schedule_path_proc.call('inactive') do
- = s_("PipelineSchedules|Inactive")
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm
- = number_with_delimiter(all_schedules.inactive.count(:id))
+ = gl_tab_link_to schedule_path_proc.call('inactive'), { item_active: active_when(scope == 'inactive') } do
+ = s_("PipelineSchedules|Inactive")
+ = gl_tab_counter_badge(number_with_delimiter(all_schedules.inactive.count(:id)))
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index 4a10f6aee1c..0bfdee088b4 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -17,45 +17,46 @@
- if @pipeline.queued_duration
= "(queued for #{time_interval_in_words(@pipeline.queued_duration)})"
- .well-segment.qa-pipeline-badges
- .icon-container
- = sprite_icon('flag')
- - if @pipeline.child?
- %span.js-pipeline-child.badge.badge-pill.gl-badge.sm.badge-primary.has-tooltip{ title: s_("Pipelines|This is a child pipeline within the parent pipeline") }
- = s_('Pipelines|Child pipeline')
- = surround '(', ')' do
- = link_to s_('Pipelines|parent'), pipeline_path(@pipeline.triggered_by_pipeline), class: 'text-white text-underline'
- - if @pipeline.latest?
- %span.js-pipeline-url-latest.badge.badge-pill.gl-badge.sm.badge-success.has-tooltip{ title: _("Latest pipeline for the most recent commit on this branch") }
- latest
- - if @pipeline.merge_train_pipeline?
- %span.js-pipeline-url-train.badge.badge-pill.gl-badge.sm.badge-info.has-tooltip{ title: _("This is a merge train pipeline") }
- train
- - if @pipeline.has_yaml_errors?
- %span.js-pipeline-url-yaml.badge.badge-pill.gl-badge.sm.badge-danger.has-tooltip{ title: @pipeline.yaml_errors }
- yaml invalid
- - if @pipeline.failure_reason?
- %span.js-pipeline-url-failure.badge.badge-pill.gl-badge.sm.badge-danger.has-tooltip{ title: @pipeline.failure_reason }
- error
- - if @pipeline.auto_devops_source?
- - popover_title_text = html_escape(_('This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}')) % { b_open: '<b>'.html_safe, b_close: '</b>'.html_safe }
- - popover_content_url = help_page_path('topics/autodevops/index.md')
- - popover_content_text = _('Learn more about Auto DevOps')
- %a.js-pipeline-url-autodevops.badge.badge-pill.gl-badge.sm.badge-info.autodevops-badge{ href: "#", tabindex: "0", role: "button", data: { container: "body",
- toggle: "popover",
- placement: "top",
- html: "true",
- triggers: "focus",
- title: "<div class='gl-font-weight-normal gl-line-height-normal'>#{popover_title_text}</div>",
- content: "<a href='#{popover_content_url}' target='_blank' rel='noopener noreferrer nofollow'>#{popover_content_text}</a>",
- } }
- Auto DevOps
- - if @pipeline.detached_merge_request_pipeline?
- %span.js-pipeline-url-mergerequest.badge.badge-pill.gl-badge.sm.badge-info.has-tooltip{ title: _('Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results.') }
- detached
- - if @pipeline.stuck?
- %span.js-pipeline-url-stuck.badge.badge-pill.gl-badge.sm.badge-warning
- stuck
+ - if has_pipeline_badges?(@pipeline)
+ .well-segment.qa-pipeline-badges
+ .icon-container
+ = sprite_icon('flag')
+ - if @pipeline.child?
+ %span.js-pipeline-child.badge.badge-pill.gl-badge.sm.badge-primary.has-tooltip{ title: s_("Pipelines|This is a child pipeline within the parent pipeline") }
+ = s_('Pipelines|Child pipeline')
+ = surround '(', ')' do
+ = link_to s_('Pipelines|parent'), pipeline_path(@pipeline.triggered_by_pipeline), class: 'text-white text-underline'
+ - if @pipeline.latest?
+ %span.js-pipeline-url-latest.badge.badge-pill.gl-badge.sm.badge-success.has-tooltip{ title: _("Latest pipeline for the most recent commit on this branch") }
+ latest
+ - if @pipeline.merge_train_pipeline?
+ %span.js-pipeline-url-train.badge.badge-pill.gl-badge.sm.badge-info.has-tooltip{ title: _("This is a merge train pipeline") }
+ train
+ - if @pipeline.has_yaml_errors?
+ %span.js-pipeline-url-yaml.badge.badge-pill.gl-badge.sm.badge-danger.has-tooltip{ title: @pipeline.yaml_errors }
+ yaml invalid
+ - if @pipeline.failure_reason?
+ %span.js-pipeline-url-failure.badge.badge-pill.gl-badge.sm.badge-danger.has-tooltip{ title: @pipeline.failure_reason }
+ error
+ - if @pipeline.auto_devops_source?
+ - popover_title_text = html_escape(_('This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}')) % { b_open: '<b>'.html_safe, b_close: '</b>'.html_safe }
+ - popover_content_url = help_page_path('topics/autodevops/index.md')
+ - popover_content_text = _('Learn more about Auto DevOps')
+ %a.js-pipeline-url-autodevops.badge.badge-pill.gl-badge.sm.badge-info.autodevops-badge{ href: "#", tabindex: "0", role: "button", data: { container: "body",
+ toggle: "popover",
+ placement: "top",
+ html: "true",
+ triggers: "focus",
+ title: "<div class='gl-font-weight-normal gl-line-height-normal'>#{popover_title_text}</div>",
+ content: "<a href='#{popover_content_url}' target='_blank' rel='noopener noreferrer nofollow'>#{popover_content_text}</a>",
+ } }
+ Auto DevOps
+ - if @pipeline.detached_merge_request_pipeline?
+ %span.js-pipeline-url-mergerequest.badge.badge-pill.gl-badge.sm.badge-info.has-tooltip{ title: _('Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results.') }
+ detached
+ - if @pipeline.stuck?
+ %span.js-pipeline-url-stuck.badge.badge-pill.gl-badge.sm.badge-warning
+ stuck
.well-segment.branch-info
.icon-container.commit-icon
diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml
index 992407adf71..21e871246d7 100644
--- a/app/views/projects/pipelines/charts.html.haml
+++ b/app/views/projects/pipelines/charts.html.haml
@@ -1,4 +1,5 @@
- page_title _('CI/CD Analytics')
#js-project-pipelines-charts-app{ data: { project_path: @project.full_path,
- should_render_dora_charts: should_render_dora_charts.to_s } }
+ should_render_dora_charts: should_render_dora_charts.to_s,
+ should_render_quality_summary: should_render_quality_summary.to_s } }
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
index 8fd8d3cf540..c911fc8a203 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -22,8 +22,8 @@
%ul
- @pipeline.yaml_errors.split(",").each do |error|
%li= error
- - lint_link_url = project_ci_lint_path(@project)
- - lint_link_start = '<a href="%{url}">'.html_safe % { url: lint_link_url }
+ - lint_link_url = project_ci_pipeline_editor_path(@project, tab: "LINT_TAB")
+ - lint_link_start = '<a href="%{url}" class="gl-text-blue-500!">'.html_safe % { url: lint_link_url }
= s_('You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}').html_safe % { gitlab_ci_yml: '.gitlab-ci.yml', lint_link_start: lint_link_start, lint_link_end: '</a>'.html_safe }
= render "projects/pipelines/with_tabs", pipeline: @pipeline, stages: @stages, pipeline_has_errors: pipeline_has_errors
diff --git a/app/views/projects/product_analytics/_links.html.haml b/app/views/projects/product_analytics/_links.html.haml
index 0797c5baf91..6e5667e2644 100644
--- a/app/views/projects/product_analytics/_links.html.haml
+++ b/app/views/projects/product_analytics/_links.html.haml
@@ -1,10 +1,5 @@
-.mb-3
- %ul.nav-links
- = nav_link(path: 'product_analytics#index') do
- = link_to _('Events'), project_product_analytics_path(@project)
- = nav_link(path: 'product_analytics#graphs') do
- = link_to 'Graphs', graphs_project_product_analytics_path(@project)
- = nav_link(path: 'product_analytics#test') do
- = link_to _('Test'), test_project_product_analytics_path(@project)
- = nav_link(path: 'product_analytics#setup') do
- = link_to _('Setup'), setup_project_product_analytics_path(@project)
+= gl_tabs_nav({ class: 'mb-3'}) do
+ = gl_tab_link_to _('Events'), project_product_analytics_path(@project)
+ = gl_tab_link_to _('Graphs'), graphs_project_product_analytics_path(@project)
+ = gl_tab_link_to _('Test'), test_project_product_analytics_path(@project)
+ = gl_tab_link_to _('Setup'), setup_project_product_analytics_path(@project)
diff --git a/app/views/projects/settings/_general.html.haml b/app/views/projects/settings/_general.html.haml
index b185f45d129..0f4d5869cea 100644
--- a/app/views/projects/settings/_general.html.haml
+++ b/app/views/projects/settings/_general.html.haml
@@ -1,3 +1,4 @@
+- hidden_topics_field_id = 'project_topic_list_field'
= form_for [@project], html: { multipart: true, class: "edit-project js-general-settings-form" }, authenticity_token: true do |f|
%input{ name: 'update_section', type: 'hidden', value: 'js-general-settings' }
@@ -15,9 +16,9 @@
.row
.form-group.col-md-9
- = f.label :topics, _('Topics (optional)'), class: 'label-bold'
- = f.text_field :topics, value: @project.topic_list.join(', '), maxlength: 2000, class: "form-control gl-form-input"
- %p.form-text.text-muted= _('Separate topics with commas.')
+ = f.label :topics, _('Topics'), class: 'label-bold'
+ .js-topics-selector{ data: { hidden_input_id: hidden_topics_field_id } }
+ = f.hidden_field :topics, value: @project.topic_list.join(', '), id: hidden_topics_field_id
.row
.form-group.col-md-9
diff --git a/app/views/projects/work_items/index.html.haml b/app/views/projects/work_items/index.html.haml
index 052db598571..0efd7a740d3 100644
--- a/app/views/projects/work_items/index.html.haml
+++ b/app/views/projects/work_items/index.html.haml
@@ -1,3 +1,3 @@
- page_title s_('WorkItem|Work Items')
-#js-work-items
+#js-work-items{ data: { full_path: @project.full_path } }
diff --git a/app/views/registrations/welcome/show.html.haml b/app/views/registrations/welcome/show.html.haml
index 9356b6ad49c..65a1ffa3e46 100644
--- a/app/views/registrations/welcome/show.html.haml
+++ b/app/views/registrations/welcome/show.html.haml
@@ -24,9 +24,10 @@
.form-group.col-sm-12.js-other-role-group.hidden
= f.label :other_role, _('What is your job title? (optional)'), class: 'form-check-label gl-mb-3'
= f.text_field :other_role, class: 'form-control'
+ = render_if_exists "registrations/welcome/jobs_to_be_done", f: f
= render_if_exists "registrations/welcome/setup_for_company", f: f
+ = render_if_exists "registrations/welcome/joining_project"
= render 'devise/shared/email_opted_in', f: f
- = render_if_exists "registrations/welcome/jobs_to_be_done", f: f
.row
.form-group.col-sm-12.gl-mb-0
- if partial_exists? "registrations/welcome/button"
diff --git a/app/views/search/_category.html.haml b/app/views/search/_category.html.haml
index ca6f2369bd8..54aa9aad8a5 100644
--- a/app/views/search/_category.html.haml
+++ b/app/views/search/_category.html.haml
@@ -5,7 +5,7 @@
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left= sprite_icon('chevron-lg-left', size: 12)
.fade-right= sprite_icon('chevron-lg-right', size: 12)
- %ul.nav-links.search-filter.scrolling-tabs.nav.nav-tabs
+ = gl_tabs_nav({ class: 'search-filter scrolling-tabs nav-links'}) do
- if @project
- if project_search_tabs?(:blobs)
= search_filter_link 'blobs', _("Code"), data: { qa_selector: 'code_tab' }
diff --git a/app/views/shared/_confirm_modal.html.haml b/app/views/shared/_confirm_modal.html.haml
index 8b13bb948ee..4cb3f6d1739 100644
--- a/app/views/shared/_confirm_modal.html.haml
+++ b/app/views/shared/_confirm_modal.html.haml
@@ -12,10 +12,10 @@
%p
%span.js-warning-text= _('This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention.')
%br
- - phrase_code = '<code class="js-confirm-danger-match">%{phrase_name}</code>'.html_safe % { phrase_name: phrase }
+ - phrase_code = '<code class="js-legacy-confirm-danger-match">%{phrase_name}</code>'.html_safe % { phrase_name: phrase }
= _('Please type %{phrase_code} to proceed or close this modal to cancel.').html_safe % { phrase_code: phrase_code }
.form-group
- = text_field_tag 'confirm_name_input', '', class: 'form-control js-confirm-danger-input qa-confirm-input'
+ = text_field_tag 'confirm_name_input', '', class: 'form-control js-legacy-confirm-danger-input qa-confirm-input'
.form-actions
- = submit_tag _('Confirm'), class: "gl-button btn btn-danger js-confirm-danger-submit qa-confirm-button"
+ = submit_tag _('Confirm'), class: "gl-button btn btn-danger js-legacy-confirm-danger-submit qa-confirm-button"
diff --git a/app/views/shared/_default_branch_protection.html.haml b/app/views/shared/_default_branch_protection.html.haml
index d7ae21debd8..7a6152f6d96 100644
--- a/app/views/shared/_default_branch_protection.html.haml
+++ b/app/views/shared/_default_branch_protection.html.haml
@@ -1,3 +1,4 @@
-.form-group
- = f.label :default_branch_protection, class: 'label-bold'
- = f.select :default_branch_protection, options_for_select(Gitlab::Access.protection_options, selected_level), {}, class: 'form-control'
+%fieldset.form-group
+ %legend.h5.gl-border-none.gl-mt-0.gl-mb-3= _('Default branch protection')
+ - Gitlab::Access.protection_options.each do |option|
+ = f.gitlab_ui_radio_component :default_branch_protection, option[:value], option[:label], help_text: option[:help_text]
diff --git a/app/views/shared/_issues.html.haml b/app/views/shared/_issues.html.haml
index 6eb736b0710..4e3b1e02f16 100644
--- a/app/views/shared/_issues.html.haml
+++ b/app/views/shared/_issues.html.haml
@@ -1,4 +1,4 @@
-= render 'shared/alerts/positioning_disabled'
+= render 'shared/alerts/positioning_disabled' if @sort == 'relative_position'
- if @issues.to_a.any?
%ul.content-list.issues-list.issuable-list{ class: issue_manual_ordering_class, data: { group_full_path: @group&.full_path } }
diff --git a/app/views/shared/_md_preview.html.haml b/app/views/shared/_md_preview.html.haml
index 0976defea1b..a49a0667d84 100644
--- a/app/views/shared/_md_preview.html.haml
+++ b/app/views/shared/_md_preview.html.haml
@@ -9,7 +9,7 @@
.md-area.position-relative
.md-header
- %ul.nav.nav-tabs.nav-links.clearfix
+ = gl_tabs_nav({ class: 'clearfix nav-links'}) do
%li.md-header-tab.active
%button.js-md-write-button
= _("Write")
diff --git a/app/views/shared/_new_commit_form.html.haml b/app/views/shared/_new_commit_form.html.haml
index 5641c67e462..14ea96f9669 100644
--- a/app/views/shared/_new_commit_form.html.haml
+++ b/app/views/shared/_new_commit_form.html.haml
@@ -5,9 +5,7 @@
- if project.empty_repo?
- ref = local_assigns[:ref] || @ref
- - branch_name_class = project.empty_repo_upload_experiment? ? 'js-branch-name' : nil
-
- = hidden_field_tag 'branch_name', ref, class: branch_name_class
+ = hidden_field_tag 'branch_name', ref, class: 'js-branch-name'
- else
- if can?(current_user, :push_code, @project)
.form-group.row.branch
diff --git a/app/views/shared/_no_password.html.haml b/app/views/shared/_no_password.html.haml
index 9c1e5a49b44..d1e1a8a819d 100644
--- a/app/views/shared/_no_password.html.haml
+++ b/app/views/shared/_no_password.html.haml
@@ -1,12 +1,10 @@
- if show_no_password_message?
- .no-password-message.gl-alert.gl-alert-warning
- = sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label': _('Dismiss') }
- = sprite_icon('close', size: 16, css_class: 'gl-icon')
+ = render 'shared/global_alert',
+ variant: :warning,
+ alert_class: 'js-no-password-message',
+ close_button_class: 'js-hide-no-password-message' do
.gl-alert-body
- - translation_params = { protocol: gitlab_config.protocol.upcase, set_password_link: link_to_set_password }
- - set_password_message = _("You won't be able to pull or push repositories via %{protocol} until you %{set_password_link} on your account") % translation_params
- = set_password_message.html_safe
+ = no_password_message
.gl-alert-actions
- = link_to _('Remind later'), '#', class: 'hide-no-password-message btn gl-alert-action btn-info btn-md gl-button'
- = link_to _("Don't show again"), profile_path(user: {hide_no_password: true}), method: :put, role: 'button', class: 'btn gl-alert-action btn-md btn-default gl-button btn-default-secondary'
+ = link_to _('Remind later'), '#', class: 'js-hide-no-password-message gl-alert-action btn btn-confirm btn-md gl-button'
+ = link_to _("Don't show again"), profile_path(user: { hide_no_password: true }), method: :put, role: 'button', class: 'gl-alert-action btn btn-default btn-md gl-button'
diff --git a/app/views/shared/_no_ssh.html.haml b/app/views/shared/_no_ssh.html.haml
index 2c6ceb58654..20dc1b41970 100644
--- a/app/views/shared/_no_ssh.html.haml
+++ b/app/views/shared/_no_ssh.html.haml
@@ -1,10 +1,10 @@
- if show_no_ssh_key_message?
- %div{ class: 'no-ssh-key-message gl-alert gl-alert-warning', role: 'alert' }
- = sprite_icon('warning', css_class: 'gl-icon s16 gl-alert-icon gl-alert-icon-no-title')
- %button{ class: 'gl-alert-dismiss hide-no-ssh-message', type: 'button', 'aria-label': _('Dismiss') }
- = sprite_icon('close', css_class: 'gl-icon s16')
+ = render 'shared/global_alert',
+ variant: :warning,
+ alert_class: 'js-no-ssh-message',
+ close_button_class: 'js-hide-no-ssh-message' do
.gl-alert-body
- = s_("MissingSSHKeyWarningLink|You won't be able to pull or push repositories via SSH until you add an SSH key to your profile")
+ = s_("MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile.")
.gl-alert-actions
- = link_to s_('MissingSSHKeyWarningLink|Add SSH key'), profile_keys_path, class: "btn gl-alert-action btn-warning btn-md gl-button"
- = link_to s_("MissingSSHKeyWarningLink|Don't show again"), profile_path(user: {hide_no_ssh_key: true}), method: :put, role: 'button', class: 'btn gl-alert-action btn-md btn-warning gl-button btn-warning-secondary'
+ = link_to s_('MissingSSHKeyWarningLink|Add SSH key'), profile_keys_path, class: "gl-alert-action btn btn-confirm btn-md gl-button"
+ = link_to s_("MissingSSHKeyWarningLink|Don't show again"), profile_path(user: { hide_no_ssh_key: true }), method: :put, role: 'button', class: 'gl-alert-action btn btn-default btn-md gl-button'
diff --git a/app/views/shared/_project_creation_levels.html.haml b/app/views/shared/_project_creation_levels.html.haml
new file mode 100644
index 00000000000..00f495a26dc
--- /dev/null
+++ b/app/views/shared/_project_creation_levels.html.haml
@@ -0,0 +1,7 @@
+- method = local_assigns.fetch(:method, nil)
+- legend = local_assigns.fetch(:legend, nil)
+
+%fieldset.form-group
+ %legend.h5.gl-border-none.gl-mt-0.gl-mb-3= legend
+ - Gitlab::Access.project_creation_options.each do |label, value|
+ = f.gitlab_ui_radio_component method, value, label
diff --git a/app/views/shared/_visibility_radios.html.haml b/app/views/shared/_visibility_radios.html.haml
index f48bfcd0e72..760fe18ddec 100644
--- a/app/views/shared/_visibility_radios.html.haml
+++ b/app/views/shared/_visibility_radios.html.haml
@@ -10,6 +10,7 @@
= visibility_level_label(level)
.option-description
= visibility_level_description(level, form_model)
+ .option-disabled-reason
.text-muted
- if all_visibility_levels_restricted?
diff --git a/app/views/shared/alerts/_positioning_disabled.html.haml b/app/views/shared/alerts/_positioning_disabled.html.haml
index 91c1d3463d8..59f2fcef24c 100644
--- a/app/views/shared/alerts/_positioning_disabled.html.haml
+++ b/app/views/shared/alerts/_positioning_disabled.html.haml
@@ -1,2 +1,2 @@
- if issue_repositioning_disabled?
- = render 'shared/alert_info', body: _('Issues manual ordering is temporarily disabled for technical reasons.')
+ = render 'shared/alert_info', body: _('Issues are being rebalanced at the moment, so manual reordering is disabled.')
diff --git a/app/views/shared/boards/_switcher.html.haml b/app/views/shared/boards/_switcher.html.haml
index 18e0ca20cf7..c667b3a4626 100644
--- a/app/views/shared/boards/_switcher.html.haml
+++ b/app/views/shared/boards/_switcher.html.haml
@@ -3,15 +3,10 @@
- milestone_filter_opts = milestone_filter_opts.merge(only_group_milestones: true) if board.group_board?
- weights = Gitlab.ee? ? ([Issue::WEIGHT_ANY] + Issue.weight_options) : []
-#js-multiple-boards-switcher.inline.boards-switcher{ data: { current_board: current_board_json.to_json,
- milestone_path: milestones_filter_path(milestone_filter_opts),
+#js-multiple-boards-switcher.inline.boards-switcher{ data: { milestone_path: milestones_filter_path(milestone_filter_opts),
board_base_url: board_base_url,
has_missing_boards: (!multiple_boards_available? && current_board_parent.boards.size > 1).to_s,
can_admin_board: can?(current_user, :admin_issue_board, parent).to_s,
multiple_issue_boards_available: parent.multiple_issue_boards_available?.to_s,
- labels_path: labels_filter_path_with_defaults(only_group_labels: true, include_descendant_groups: true),
- labels_web_url: parent.is_a?(Project) ? project_labels_path(@project) : group_labels_path(@group),
- project_id: @project&.id,
- group_id: @group&.id,
scoped_issue_board_feature_enabled: Gitlab.ee? && parent.feature_available?(:scoped_issue_board) ? 'true' : 'false',
weights: weights.to_json } }
diff --git a/app/views/shared/deploy_tokens/_form.html.haml b/app/views/shared/deploy_tokens/_form.html.haml
index e049afbc40b..902a0cad483 100644
--- a/app/views/shared/deploy_tokens/_form.html.haml
+++ b/app/views/shared/deploy_tokens/_form.html.haml
@@ -36,7 +36,7 @@
.text-secondary= s_('DeployTokens|Allows read-only access to registry images.')
%fieldset.form-group.form-check
- = f.check_box :write_registry, class: 'form-check-input'
+ = f.check_box :write_registry, class: 'form-check-input', data: { qa_selector: 'deploy_token_write_registry_checkbox' }
= f.label :write_registry, 'write_registry', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows read and write access to registry images.')
diff --git a/app/views/shared/doorkeeper/applications/_show.html.haml b/app/views/shared/doorkeeper/applications/_show.html.haml
index 8d6b9604c1c..f533b5b5a4d 100644
--- a/app/views/shared/doorkeeper/applications/_show.html.haml
+++ b/app/views/shared/doorkeeper/applications/_show.html.haml
@@ -39,6 +39,9 @@
= render "shared/tokens/scopes_list", token: @application
-.form-actions
- = link_to _('Edit'), edit_path, class: 'gl-button btn btn-confirm wide float-left'
- = render 'shared/doorkeeper/applications/delete_form', path: delete_path, submit_btn_css: 'gl-button btn btn-danger gl-ml-3'
+.form-actions.gl-display-flex.gl-justify-content-space-between
+ %div
+ - if @created
+ = link_to _('Continue'), index_path, class: 'btn btn-confirm btn-md gl-button gl-mr-3'
+ = link_to _('Edit'), edit_path, class: 'btn btn-default btn-md gl-button'
+ = render 'shared/doorkeeper/applications/delete_form', path: delete_path, submit_btn_css: 'btn btn-danger btn-md gl-button btn-danger-secondary'
diff --git a/app/views/shared/hook_logs/_content.html.haml b/app/views/shared/hook_logs/_content.html.haml
index 51f44afe55e..ab6875a09f7 100644
--- a/app/views/shared/hook_logs/_content.html.haml
+++ b/app/views/shared/hook_logs/_content.html.haml
@@ -1,44 +1,47 @@
-%p
- %strong Request URL:
- POST
- = hook_log.url
- = render partial: 'shared/hook_logs/status_label', locals: { hook_log: hook_log }
+%span.gl-display-flex.gl-align-items-center
+ %h4
+ POST
+ = hook_log.url
+ %span.badge.gl-badge.badge-pill.badge-muted.sm.gl-ml-3
+ = hook_log.trigger.singularize.titleize
%p
- %strong Trigger:
- %td.d-none.d-sm-block
- %span.badge.badge-gray.deploy-project-label
- = hook_log.trigger.singularize.titleize
-%p
- %strong Elapsed time:
- #{number_with_precision(hook_log.execution_duration, precision: 2)} sec
-%p
- %strong Request time:
- = time_ago_with_tooltip(hook_log.created_at)
+ = _('Completed in %{duration_seconds} seconds (%{relative_time})').html_safe % { duration_seconds: number_with_precision(hook_log.execution_duration, precision: 2), relative_time: time_ago_with_tooltip(hook_log.created_at) }
%hr
- if hook_log.internal_error_message.present?
- .bs-callout.bs-callout-danger
- = hook_log.internal_error_message
+ .gl-alert-container
+ .gl-alert.gl-alert-danger
+ .gl-alert-container
+ = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ %h4.gl-alert-title= _('Internal error occured while delivering this webhook.')
+ .gl-alert-body
+ = _('Error: %{error}') % { error: hook_log.internal_error_message }
+
+%h4= _('Response')
+= render partial: 'shared/hook_logs/status_label', locals: { hook_log: hook_log }
+%pre.gl-mt-3
+ :escaped
+ #{hook_log.response_body}
-%h5 Request headers:
+%h5= _('Headers')
%pre
- - hook_log.request_headers.each do |k, v|
- <strong>#{k}:</strong> #{v}
+ - hook_log.response_headers.each do |k, v|
+ <span class="gl-font-weight-bold">#{k}:</span> #{v}
%br
-%h5 Request body:
+%h4.gl-mt-6= _('Request')
%pre
:escaped
#{Gitlab::Json.pretty_generate(hook_log.request_data)}
-%h5 Response headers:
+
+%h5= _('Headers')
%pre
- - hook_log.response_headers.each do |k, v|
- <strong>#{k}:</strong> #{v}
+ - hook_log.request_headers.each do |k, v|
+ <span class="gl-font-weight-bold">#{k}:</span> #{v}
%br
-%h5 Response body:
-%pre
- :escaped
- #{hook_log.response_body}
+
+
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 81a7581d392..e097852216c 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -15,6 +15,7 @@
.d-flex.flex-column.flex-md-row.flex-grow-1.mb-lg-0.mb-md-2.mb-sm-0.w-100
- if type == :boards
= render "shared/boards/switcher", board: board
+ .js-new-board{ data: { multiple_issue_boards_available: parent.multiple_issue_boards_available?.to_s, can_admin_board: can?(current_user, :admin_issue_board, parent).to_s, } }
= form_tag page_filter_path, method: :get, class: 'filter-form js-filter-form w-100' do
- if params[:search].present?
= hidden_field_tag :search, params[:search]
diff --git a/app/views/shared/issuable/form/_branch_chooser.html.haml b/app/views/shared/issuable/form/_branch_chooser.html.haml
index 1f391e8a321..46df9b4ef9a 100644
--- a/app/views/shared/issuable/form/_branch_chooser.html.haml
+++ b/app/views/shared/issuable/form/_branch_chooser.html.haml
@@ -23,7 +23,7 @@
= html_escape(_('From %{code_open}%{source_title}%{code_close} into')) % { source_title: source_title, code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- if issuable.new_record?
- %code#js-target-branch-title= target_title
+ %code#js-target-branch-title{ data: { branch_name: @merge_request.target_branch } }= target_title
&nbsp;
= link_to _('Change branches'), mr_change_branches_path(issuable)
- elsif issuable.for_fork?
diff --git a/app/views/shared/issuable/form/_type_selector.html.haml b/app/views/shared/issuable/form/_type_selector.html.haml
index f5f6f32d5ba..ae0fe54de4f 100644
--- a/app/views/shared/issuable/form/_type_selector.html.haml
+++ b/app/views/shared/issuable/form/_type_selector.html.haml
@@ -18,17 +18,19 @@
= sprite_icon('close', size: 16, css_class: 'dropdown-menu-close-icon')
.dropdown-content{ data: { testid: 'issue-type-select-dropdown' } }
%ul
- %li.js-filter-issuable-type
- = link_to new_project_issue_path(@project), class: ("is-active" if issuable.issue?) do
- #{sprite_icon(work_item_type_icon(:issue), css_class: 'gl-icon')} #{_("Issue")}
- %li.js-filter-issuable-type{ data: { track: { action: "select_issue_type_incident", label: "select_issue_type_incident_dropdown_option" } } }
- = link_to new_project_issue_path(@project, { issuable_template: 'incident', issue: { issue_type: 'incident' } }), class: ("is-active" if issuable.incident?) do
- #{sprite_icon(work_item_type_icon(:incident), css_class: 'gl-icon')} #{_("Incident")}
+ - if create_issue_type_allowed?(@project, :issue)
+ %li.js-filter-issuable-type
+ = link_to new_project_issue_path(@project), class: ("is-active" if issuable.issue?) do
+ #{sprite_icon(work_item_type_icon(:issue), css_class: 'gl-icon')} #{_('Issue')}
+ - if create_issue_type_allowed?(@project, :incident)
+ %li.js-filter-issuable-type{ data: { track: { action: "select_issue_type_incident", label: "select_issue_type_incident_dropdown_option" } } }
+ = link_to new_project_issue_path(@project, { issuable_template: 'incident', issue: { issue_type: 'incident' } }), class: ("is-active" if issuable.incident?) do
+ #{sprite_icon(work_item_type_icon(:incident), css_class: 'gl-icon')} #{_('Incident')}
#js-type-popover
- if issuable.incident?
%p.form-text.text-muted
- incident_docs_url = help_page_path('operations/incident_management/incidents.md')
- - incident_docs_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: incident_docs_url }
- = _('A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents.').html_safe % { incident_docs_start: incident_docs_start, incident_docs_end: '</a>'.html_safe }
+ - incident_docs_start = format('<a href="%{url}" target="_blank" rel="noopener noreferrer">', url: incident_docs_url)
+ = format(_('A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents.'), incident_docs_start: incident_docs_start, incident_docs_end: '</a>').html_safe
diff --git a/app/views/shared/labels/_nav.html.haml b/app/views/shared/labels/_nav.html.haml
index a0225e35c90..47e9d9b0e4a 100644
--- a/app/views/shared/labels/_nav.html.haml
+++ b/app/views/shared/labels/_nav.html.haml
@@ -1,14 +1,10 @@
- subscribed = params[:subscribed]
.top-area.adjust
- %ul.nav-links.nav.nav-tabs
- %li{ class: active_when(subscribed != 'true') }>
- = link_to labels_filter_path do
- = _('All')
+ = gl_tabs_nav({ class: 'gl-flex-grow-1 gl-border-0' }) do
+ = gl_tab_link_to _('All'), labels_filter_path, { item_active: subscribed != 'true' }
- if current_user
- %li{ class: active_when(subscribed == 'true') }>
- = link_to labels_filter_path(subscribed: 'true') do
- = _('Subscribed')
+ = gl_tab_link_to _('Subscribed'), labels_filter_path(subscribed: 'true'), { item_active: subscribed == 'true' }
.nav-controls
= form_tag labels_filter_path, method: :get do
= hidden_field_tag :subscribed, params[:subscribed]
diff --git a/app/views/shared/nav/_sidebar_menu.html.haml b/app/views/shared/nav/_sidebar_menu.html.haml
index 903d2d077ba..3f71368aff3 100644
--- a/app/views/shared/nav/_sidebar_menu.html.haml
+++ b/app/views/shared/nav/_sidebar_menu.html.haml
@@ -16,15 +16,4 @@
%span.badge.badge-pill.count{ **sidebar_menu.pill_html_options }
= number_with_delimiter(sidebar_menu.pill_count)
- %ul.sidebar-sub-level-items{ class: ('is-fly-out-only' unless sidebar_menu.has_renderable_items?) }
- = nav_link(**sidebar_menu.all_active_routes, html_options: { class: 'fly-out-top-item' } ) do
- %span.fly-out-top-item-container
- %strong.fly-out-top-item-name
- = sidebar_menu.title
- - if sidebar_menu.has_pill?
- %span.badge.badge-pill.count.fly-out-badge{ **sidebar_menu.pill_html_options }
- = number_with_delimiter(sidebar_menu.pill_count)
-
- - if sidebar_menu.has_renderable_items?
- %li.divider.fly-out-top-item
- = render partial: 'shared/nav/sidebar_menu_item', collection: sidebar_menu.renderable_items
+ = render partial: 'shared/nav/sidebar_submenu', locals: { sidebar_menu: sidebar_menu }
diff --git a/app/views/shared/nav/_sidebar_submenu.html.haml b/app/views/shared/nav/_sidebar_submenu.html.haml
new file mode 100644
index 00000000000..750e6c9ee57
--- /dev/null
+++ b/app/views/shared/nav/_sidebar_submenu.html.haml
@@ -0,0 +1,12 @@
+%ul.sidebar-sub-level-items{ class: ('is-fly-out-only' unless sidebar_menu.has_renderable_items?) }
+ = nav_link(**sidebar_menu.all_active_routes, html_options: { class: 'fly-out-top-item' } ) do
+ %span.fly-out-top-item-container
+ %strong.fly-out-top-item-name
+ = sidebar_menu.title
+ - if sidebar_menu.has_pill?
+ %span.badge.badge-pill.count.fly-out-badge{ **sidebar_menu.pill_html_options }
+ = number_with_delimiter(sidebar_menu.pill_count)
+
+ - if sidebar_menu.has_renderable_items?
+ %li.divider.fly-out-top-item
+ = render partial: 'shared/nav/sidebar_menu_item', collection: sidebar_menu.renderable_items
diff --git a/app/views/shared/projects/_topics.html.haml b/app/views/shared/projects/_topics.html.haml
index a7429483da1..e303f05c5df 100644
--- a/app/views/shared/projects/_topics.html.haml
+++ b/app/views/shared/projects/_topics.html.haml
@@ -8,7 +8,7 @@
= sprite_icon('tag', css_class: 'icon gl-relative gl-mr-2')
- project.topics_to_show.each do |topic|
- - explore_project_topic_path = explore_projects_path(topic: topic)
+ - explore_project_topic_path = topic_explore_projects_path(topic_name: topic)
- if topic.length > max_project_topic_length
%a{ class: "#{ project_topics_classes } str-truncated-30 has-tooltip", data: { container: "body" }, title: topic, href: explore_project_topic_path, itemprop: 'keywords' }
= truncate(topic, length: max_project_topic_length)
@@ -21,7 +21,7 @@
- content = capture do
%span.gl-display-inline-flex.gl-flex-wrap
- project.topics_not_shown.each do |topic|
- - explore_project_topic_path = explore_projects_path(topic: topic)
+ - explore_project_topic_path = topic_explore_projects_path(topic_name: topic)
- if topic.length > max_project_topic_length
%a{ class: "#{ project_topics_classes } gl-mb-3 str-truncated has-tooltip", data: { container: "body" }, title: topic, href: explore_project_topic_path, itemprop: 'keywords' }
= truncate(topic, length: max_project_topic_length)
diff --git a/app/views/shared/runners/_shared_runners_description.html.haml b/app/views/shared/runners/_shared_runners_description.html.haml
index a276f725576..e2b57a7fd73 100644
--- a/app/views/shared/runners/_shared_runners_description.html.haml
+++ b/app/views/shared/runners/_shared_runners_description.html.haml
@@ -1,4 +1,5 @@
-- link = link_to _('MaxBuilds'), 'https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnersmachine-section', target: '_blank'
+-# "MaxBuilds" is a runner configuration keyword so it must not be translated.
+- link = link_to 'MaxBuilds', 'https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnersmachine-section', target: '_blank'
%h4
= _('Shared runners')
diff --git a/app/views/shared/topics/_list.html.haml b/app/views/shared/topics/_list.html.haml
new file mode 100644
index 00000000000..ddf47261d42
--- /dev/null
+++ b/app/views/shared/topics/_list.html.haml
@@ -0,0 +1,9 @@
+- remote = local_assigns.fetch(:remote, false)
+
+- if @topics.empty?
+ = render 'shared/empty_states/topics'
+- else
+ .row.gl-mt-3
+ = render partial: 'shared/topics/topic', collection: @topics
+
+ = paginate_collection @topics, remote: remote
diff --git a/app/views/shared/topics/_topic.html.haml b/app/views/shared/topics/_topic.html.haml
new file mode 100644
index 00000000000..a47d4495777
--- /dev/null
+++ b/app/views/shared/topics/_topic.html.haml
@@ -0,0 +1,16 @@
+- max_topic_name_length = 30
+- detail_page_link = topic_explore_projects_path(topic_name: topic.name)
+
+.col-lg-3.col-md-4.col-sm-12
+ .gl-card.gl-mb-5
+ .gl-card-body.gl-display-flex.gl-align-items-center
+ .avatar-container.rect-avatar.s40.gl-flex-shrink-0
+ = link_to detail_page_link do
+ = topic_icon(topic, class: "avatar s40")
+ = link_to detail_page_link do
+ - if topic.name.length > max_topic_name_length
+ %h5.str-truncated.has-tooltip{ title: topic.name }
+ = truncate(topic.name, length: max_topic_name_length)
+ - else
+ %h5
+ = topic.name
diff --git a/app/views/shared/web_hooks/_index.html.haml b/app/views/shared/web_hooks/_index.html.haml
index 794418b8336..f1eef5d7f0f 100644
--- a/app/views/shared/web_hooks/_index.html.haml
+++ b/app/views/shared/web_hooks/_index.html.haml
@@ -3,7 +3,7 @@
.card-header
%h5
= hook_class.underscore.humanize.titleize.pluralize
- (#{hooks.load.size})
+ (#{hooks.size})
- if hooks.any?
%ul.content-list
diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml
index 2e6d335a98d..0d904de9372 100644
--- a/app/views/users/_overview.html.haml
+++ b/app/views/users/_overview.html.haml
@@ -2,13 +2,28 @@
.row.d-none.d-sm-flex
.col-12.calendar-block.gl-my-3
- .user-calendar.light{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
+ .user-calendar.light{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: local_time_instance(@user.timezone).now.utc_offset } }
.gl-spinner.gl-spinner-md.gl-my-8
.user-calendar-error.invisible
= _('There was an error loading users activity calendar.')
%a.js-retry-load{ href: '#' }
= s_('UserProfile|Retry')
.user-calendar-activities
+- if @user.user_readme
+ .row.justify-content-center
+ .col-12.col-md-10.col-lg-8.gl-my-6
+ .gl-display-flex
+ %ol.breadcrumb.gl-breadcrumb-list.gl-mb-4
+ %li.breadcrumb-item.gl-breadcrumb-item
+ = link_to @user.username, project_path(@user.user_project)
+ %span.gl-breadcrumb-separator
+ = sprite_icon("chevron-right", size: 16)
+ %li.breadcrumb-item.gl-breadcrumb-item
+ = link_to @user.user_readme.path, @user.user_project.readme_url
+ - if current_user == @user
+ .gl-ml-auto
+ = link_to _('Edit'), edit_blob_path(@user.user_project, @user.user_project.default_branch, @user.user_readme.path)
+ = render 'projects/blob/viewer', viewer: @user.user_readme.rich_viewer, load_async: false
.row
%div{ class: activity_pane_class }
- if can?(current_user, :read_cross_project)
diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml
index 2f44a57c388..cffeb55597f 100644
--- a/app/views/users/calendar_activities.html.haml
+++ b/app/views/users/calendar_activities.html.haml
@@ -5,9 +5,9 @@
%ul.bordered-list
- @events.sort_by(&:created_at).each do |event|
%li
- %span.light
+ %span.light.js-localtime{ :data => { :datetime => event.created_at.utc.strftime('%Y-%m-%dT%H:%M:%SZ'), :toggle => 'tooltip', :placement => 'top' } }
= sprite_icon('clock', css_class: 'gl-vertical-align-text-bottom')
- = event.created_at.to_time.in_time_zone.strftime('%-I:%M%P')
+ = event.created_at.to_time.in_time_zone(@user.timezone).strftime('%-I:%M%P')
- if event.visible_to_user?(current_user)
- if event.push_action?
#{event.action_name} #{event.ref_type}
diff --git a/app/views/users/terms/index.html.haml b/app/views/users/terms/index.html.haml
index 771ee693120..92095e78f69 100644
--- a/app/views/users/terms/index.html.haml
+++ b/app/views/users/terms/index.html.haml
@@ -1,20 +1,23 @@
- redirect_params = { redirect: @redirect } if @redirect
- accept_term_link = accept_term_path(@term, redirect_params)
-.card-body.rendered-terms{ data: { qa_selector: 'terms_content' } }
- = markdown_field(@term, :terms)
-- if current_user
- = render_if_exists 'devise/shared/form_phone_verification', accept_term_link: accept_term_link, inline: true
- .card-footer.footer-block.clearfix
- - if can?(current_user, :accept_terms, @term)
- .float-right
- = button_to accept_term_link, class: 'gl-button btn btn-confirm gl-ml-3', data: { qa_selector: 'accept_terms_button' } do
- = _('Accept terms')
- - else
- .float-right
- = link_to root_path, class: 'gl-button btn btn-confirm gl-ml-3' do
- = _('Continue')
- - if can?(current_user, :decline_terms, @term)
- .float-right
- = button_to decline_term_path(@term, redirect_params), class: 'gl-button btn btn-default gl-ml-3' do
- = _('Decline and sign out')
+- if Feature.enabled?(:terms_of_service_vue, current_user, default_enabled: :yaml)
+ #js-terms-of-service{ data: { terms_data: terms_data(@term, @redirect) } }
+- else
+ .card-body.rendered-terms{ data: { qa_selector: 'terms_content' } }
+ = markdown_field(@term, :terms)
+ - if current_user
+ = render_if_exists 'devise/shared/form_phone_verification', accept_term_link: accept_term_link, inline: true
+ .card-footer.footer-block.clearfix
+ - if can?(current_user, :accept_terms, @term)
+ .float-right
+ = button_to accept_term_link, class: 'gl-button btn btn-confirm gl-ml-3', data: { qa_selector: 'accept_terms_button' } do
+ = _('Accept terms')
+ - else
+ .float-right
+ = link_to root_path, class: 'gl-button btn btn-confirm gl-ml-3' do
+ = _('Continue')
+ - if can?(current_user, :decline_terms, @term)
+ .float-right
+ = button_to decline_term_path(@term, redirect_params), class: 'gl-button btn btn-default gl-ml-3' do
+ = _('Decline and sign out')
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index c7ce2eb8d00..699744b355c 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -246,6 +246,15 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: cronjob:clusters_integrations_check_prometheus_health
+ :worker_name: Clusters::Integrations::CheckPrometheusHealthWorker
+ :feature_category: :incident_management
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: cronjob:container_expiration_policy
:worker_name: ContainerExpirationPolicyWorker
:feature_category: :container_registry
@@ -347,13 +356,22 @@
:tags: []
- :name: cronjob:issue_due_scheduler
:worker_name: IssueDueSchedulerWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent:
:tags: []
+- :name: cronjob:issues_reschedule_stuck_issue_rebalances
+ :worker_name: Issues::RescheduleStuckIssueRebalancesWorker
+ :feature_category: :team_planning
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: cronjob:jira_import_stuck_jira_import_jobs
:worker_name: Gitlab::JiraImport::StuckJiraImportJobsWorker
:feature_category: :importers
@@ -363,6 +381,15 @@
:weight: 1
:idempotent:
:tags: []
+- :name: cronjob:loose_foreign_keys_cleanup
+ :worker_name: LooseForeignKeys::CleanupWorker
+ :feature_category: :sharding
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: cronjob:member_invitation_reminder_emails
:worker_name: MemberInvitationReminderEmailsWorker
:feature_category: :subgroups
@@ -696,6 +723,15 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: deployment:deployments_archive_in_project
+ :worker_name: Deployments::ArchiveInProjectWorker
+ :feature_category: :continuous_delivery
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 3
+ :idempotent: true
+ :tags: []
- :name: deployment:deployments_drop_older_deployments
:worker_name: Deployments::DropOlderDeploymentsWorker
:feature_category: :continuous_delivery
@@ -1069,15 +1105,6 @@
:idempotent:
:tags:
- :needs_own_queue
-- :name: incident_management:clusters_applications_check_prometheus_health
- :worker_name: Clusters::Applications::CheckPrometheusHealthWorker
- :feature_category: :incident_management
- :has_external_dependencies: true
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 2
- :idempotent: true
- :tags: []
- :name: incident_management:incident_management_add_severity_system_note
:worker_name: IncidentManagement::AddSeveritySystemNoteWorker
:feature_category: :incident_management
@@ -1251,7 +1278,7 @@
:tags: []
- :name: mail_scheduler:mail_scheduler_issue_due
:worker_name: MailScheduler::IssueDueWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -1260,7 +1287,7 @@
:tags: []
- :name: mail_scheduler:mail_scheduler_notification_service
:worker_name: MailScheduler::NotificationServiceWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :cpu
@@ -1737,7 +1764,7 @@
:tags: []
- :name: todos_destroyer:todos_destroyer_confidential_issue
:worker_name: TodosDestroyer::ConfidentialIssueWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -1746,7 +1773,7 @@
:tags: []
- :name: todos_destroyer:todos_destroyer_destroyed_designs
:worker_name: TodosDestroyer::DestroyedDesignsWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -1755,7 +1782,7 @@
:tags: []
- :name: todos_destroyer:todos_destroyer_destroyed_issuable
:worker_name: TodosDestroyer::DestroyedIssuableWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -1764,7 +1791,7 @@
:tags: []
- :name: todos_destroyer:todos_destroyer_entity_leave
:worker_name: TodosDestroyer::EntityLeaveWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -1773,7 +1800,7 @@
:tags: []
- :name: todos_destroyer:todos_destroyer_group_private
:worker_name: TodosDestroyer::GroupPrivateWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -1782,7 +1809,7 @@
:tags: []
- :name: todos_destroyer:todos_destroyer_private_features
:worker_name: TodosDestroyer::PrivateFeaturesWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -1791,7 +1818,7 @@
:tags: []
- :name: todos_destroyer:todos_destroyer_project_private
:worker_name: TodosDestroyer::ProjectPrivateWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -2052,7 +2079,7 @@
:tags: []
- :name: email_receiver
:worker_name: EmailReceiverWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :high
:resource_boundary: :unknown
@@ -2116,7 +2143,7 @@
:tags: []
- :name: export_csv
:worker_name: ExportCsvWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :cpu
@@ -2206,13 +2233,22 @@
:tags: []
- :name: import_issues_csv
:worker_name: ImportIssuesCsvWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :cpu
:weight: 2
:idempotent: true
:tags: []
+- :name: integrations_create_external_cross_reference
+ :worker_name: Integrations::CreateExternalCrossReferenceWorker
+ :feature_category: :integrations
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: invalid_gpg_signature_update
:worker_name: InvalidGpgSignatureUpdateWorker
:feature_category: :source_code_management
@@ -2233,7 +2269,7 @@
:tags: []
- :name: issuable_export_csv
:worker_name: IssuableExportCsvWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :cpu
@@ -2242,7 +2278,7 @@
:tags: []
- :name: issuable_label_links_destroy
:worker_name: Issuable::LabelLinksDestroyWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -2251,7 +2287,7 @@
:tags: []
- :name: issuables_clear_groups_issue_counter
:worker_name: Issuables::ClearGroupsIssueCounterWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -2260,7 +2296,7 @@
:tags: []
- :name: issue_placement
:worker_name: IssuePlacementWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :high
:resource_boundary: :cpu
@@ -2269,7 +2305,25 @@
:tags: []
- :name: issue_rebalancing
:worker_name: IssueRebalancingWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: issues_placement
+ :worker_name: Issues::PlacementWorker
+ :feature_category: :team_planning
+ :has_external_dependencies:
+ :urgency: :high
+ :resource_boundary: :cpu
+ :weight: 2
+ :idempotent: true
+ :tags: []
+- :name: issues_rebalancing
+ :worker_name: Issues::RebalancingWorker
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -2375,6 +2429,15 @@
:weight: 1
:idempotent:
:tags: []
+- :name: namespaces_invite_team_email
+ :worker_name: Namespaces::InviteTeamEmailWorker
+ :feature_category: :experimentation_activation
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent:
+ :tags: []
- :name: namespaces_onboarding_issue_created
:worker_name: Namespaces::OnboardingIssueCreatedWorker
:feature_category: :onboarding
@@ -2413,7 +2476,7 @@
:tags: []
- :name: new_issue
:worker_name: NewIssueWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :high
:resource_boundary: :cpu
@@ -2431,7 +2494,7 @@
:tags: []
- :name: new_note
:worker_name: NewNoteWorker
- :feature_category: :issue_tracking
+ :feature_category: :team_planning
:has_external_dependencies:
:urgency: :high
:resource_boundary: :cpu
@@ -2799,6 +2862,15 @@
:weight: 1
:idempotent:
:tags: []
+- :name: tasks_to_be_done_create
+ :worker_name: TasksToBeDone::CreateWorker
+ :feature_category: :onboarding
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :cpu
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: update_external_pull_requests
:worker_name: UpdateExternalPullRequestsWorker
:feature_category: :source_code_management
diff --git a/app/workers/authorized_project_update/project_recalculate_worker.rb b/app/workers/authorized_project_update/project_recalculate_worker.rb
index 3d073f18622..1b5faee0b6f 100644
--- a/app/workers/authorized_project_update/project_recalculate_worker.rb
+++ b/app/workers/authorized_project_update/project_recalculate_worker.rb
@@ -7,6 +7,8 @@ module AuthorizedProjectUpdate
data_consistency :always
include Gitlab::ExclusiveLeaseHelpers
+ prepend WaitableWorker
+
feature_category :authentication_and_authorization
urgency :high
queue_namespace :authorized_project_update
diff --git a/app/workers/authorized_projects_worker.rb b/app/workers/authorized_projects_worker.rb
index 46fe6c7f7ce..afe14369d43 100644
--- a/app/workers/authorized_projects_worker.rb
+++ b/app/workers/authorized_projects_worker.rb
@@ -25,11 +25,9 @@ class AuthorizedProjectsWorker
end
end
- # rubocop: disable CodeReuse/ActiveRecord
def perform(user_id)
- user = User.find_by(id: user_id)
+ user = User.find_by_id(user_id)
user&.refresh_authorized_projects(source: self.class.name)
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/build_hooks_worker.rb b/app/workers/build_hooks_worker.rb
index a0d1d9dca45..78244e0941e 100644
--- a/app/workers/build_hooks_worker.rb
+++ b/app/workers/build_hooks_worker.rb
@@ -14,7 +14,7 @@ class BuildHooksWorker # rubocop:disable Scalability/IdempotentWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(build_id)
Ci::Build.includes({ runner: :tags })
- .find_by(id: build_id)
+ .find_by_id(build_id)
.try(:execute_hooks)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/workers/build_queue_worker.rb b/app/workers/build_queue_worker.rb
index 4ab08bbd7fe..af1136de94c 100644
--- a/app/workers/build_queue_worker.rb
+++ b/app/workers/build_queue_worker.rb
@@ -12,11 +12,9 @@ class BuildQueueWorker # rubocop:disable Scalability/IdempotentWorker
worker_resource_boundary :cpu
data_consistency :sticky
- # rubocop: disable CodeReuse/ActiveRecord
def perform(build_id)
- Ci::Build.find_by(id: build_id).try do |build|
+ Ci::Build.find_by_id(build_id).try do |build|
Ci::UpdateBuildQueueService.new.tick(build)
end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/build_success_worker.rb b/app/workers/build_success_worker.rb
index ce39ac946a9..114bced0b22 100644
--- a/app/workers/build_success_worker.rb
+++ b/app/workers/build_success_worker.rb
@@ -11,13 +11,11 @@ class BuildSuccessWorker # rubocop:disable Scalability/IdempotentWorker
queue_namespace :pipeline_processing
urgency :high
- # rubocop: disable CodeReuse/ActiveRecord
def perform(build_id)
- Ci::Build.find_by(id: build_id).try do |build|
+ Ci::Build.find_by_id(build_id).try do |build|
stop_environment(build) if build.stops_environment?
end
end
- # rubocop: enable CodeReuse/ActiveRecord
private
diff --git a/app/workers/chat_notification_worker.rb b/app/workers/chat_notification_worker.rb
index 2a2e94cc6f1..23d8a1ec29d 100644
--- a/app/workers/chat_notification_worker.rb
+++ b/app/workers/chat_notification_worker.rb
@@ -16,9 +16,8 @@ class ChatNotificationWorker # rubocop:disable Scalability/IdempotentWorker
RESCHEDULE_INTERVAL = 2.seconds
RESCHEDULE_TIMEOUT = 5.minutes
- # rubocop: disable CodeReuse/ActiveRecord
def perform(build_id, reschedule_count = 0)
- Ci::Build.find_by(id: build_id).try do |build|
+ Ci::Build.find_by_id(build_id).try do |build|
send_response(build)
end
rescue Gitlab::Chat::Output::MissingBuildSectionError
@@ -30,7 +29,6 @@ class ChatNotificationWorker # rubocop:disable Scalability/IdempotentWorker
# the job instead of producing an error.
self.class.perform_in(RESCHEDULE_INTERVAL, build_id, reschedule_count + 1)
end
- # rubocop: enable CodeReuse/ActiveRecord
def send_response(build)
Gitlab::Chat::Responder.responder_for(build).try do |responder|
diff --git a/app/workers/ci/archive_trace_worker.rb b/app/workers/ci/archive_trace_worker.rb
index 503cfc07c25..5a22a5c74ee 100644
--- a/app/workers/ci/archive_trace_worker.rb
+++ b/app/workers/ci/archive_trace_worker.rb
@@ -9,12 +9,10 @@ module Ci
sidekiq_options retry: 3
include PipelineBackgroundQueue
- # rubocop: disable CodeReuse/ActiveRecord
def perform(job_id)
- Ci::Build.without_archived_trace.find_by(id: job_id).try do |job|
+ Ci::Build.without_archived_trace.find_by_id(job_id).try do |job|
Ci::ArchiveTraceService.new.execute(job, worker_name: self.class.name)
end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
diff --git a/app/workers/ci/build_finished_worker.rb b/app/workers/ci/build_finished_worker.rb
index f047ba8fde5..aa12bdb009e 100644
--- a/app/workers/ci/build_finished_worker.rb
+++ b/app/workers/ci/build_finished_worker.rb
@@ -16,7 +16,7 @@ module Ci
ARCHIVE_TRACES_IN = 2.minutes.freeze
def perform(build_id)
- return unless build = Ci::Build.find_by(id: build_id) # rubocop: disable CodeReuse/ActiveRecord
+ return unless build = Ci::Build.find_by_id(build_id)
return unless build.project
return if build.project.pending_delete?
diff --git a/app/workers/ci/build_trace_chunk_flush_worker.rb b/app/workers/ci/build_trace_chunk_flush_worker.rb
index 79881ec84fd..62fc3efd4f0 100644
--- a/app/workers/ci/build_trace_chunk_flush_worker.rb
+++ b/app/workers/ci/build_trace_chunk_flush_worker.rb
@@ -13,12 +13,10 @@ module Ci
idempotent!
- # rubocop: disable CodeReuse/ActiveRecord
def perform(id)
- ::Ci::BuildTraceChunk.find_by(id: id).try do |chunk|
+ ::Ci::BuildTraceChunk.find_by_id(id).try do |chunk|
chunk.persist_data!
end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
diff --git a/app/workers/ci/pipeline_success_unlock_artifacts_worker.rb b/app/workers/ci/pipeline_success_unlock_artifacts_worker.rb
index 160947fb38e..590514424bb 100644
--- a/app/workers/ci/pipeline_success_unlock_artifacts_worker.rb
+++ b/app/workers/ci/pipeline_success_unlock_artifacts_worker.rb
@@ -15,9 +15,12 @@ module Ci
::Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
break unless pipeline.has_archive_artifacts?
- ::Ci::UnlockArtifactsService
+ results = ::Ci::UnlockArtifactsService
.new(pipeline.project, pipeline.user)
.execute(pipeline.ci_ref, pipeline)
+
+ log_extra_metadata_on_done(:unlocked_pipelines, results[:unlocked_pipelines])
+ log_extra_metadata_on_done(:unlocked_job_artifacts, results[:unlocked_job_artifacts])
end
end
end
diff --git a/app/workers/ci/ref_delete_unlock_artifacts_worker.rb b/app/workers/ci/ref_delete_unlock_artifacts_worker.rb
index 0c217644cc4..aeadf111bfb 100644
--- a/app/workers/ci/ref_delete_unlock_artifacts_worker.rb
+++ b/app/workers/ci/ref_delete_unlock_artifacts_worker.rb
@@ -15,9 +15,12 @@ module Ci
::Project.find_by_id(project_id).try do |project|
::User.find_by_id(user_id).try do |user|
project.ci_refs.find_by_ref_path(ref_path).try do |ci_ref|
- ::Ci::UnlockArtifactsService
+ results = ::Ci::UnlockArtifactsService
.new(project, user)
.execute(ci_ref)
+
+ log_extra_metadata_on_done(:unlocked_pipelines, results[:unlocked_pipelines])
+ log_extra_metadata_on_done(:unlocked_job_artifacts, results[:unlocked_job_artifacts])
end
end
end
diff --git a/app/workers/ci/resource_groups/assign_resource_from_resource_group_worker.rb b/app/workers/ci/resource_groups/assign_resource_from_resource_group_worker.rb
index 98b4f4ad73a..533cb7c425f 100644
--- a/app/workers/ci/resource_groups/assign_resource_from_resource_group_worker.rb
+++ b/app/workers/ci/resource_groups/assign_resource_from_resource_group_worker.rb
@@ -21,7 +21,7 @@ module Ci
# Therefore, we can deduplicate the sidekiq jobs until the on-going
# assignment process has been finished.
idempotent!
- deduplicate :until_executed
+ deduplicate :until_executed, if_deduplicated: :reschedule_once
def perform(resource_group_id)
::Ci::ResourceGroup.find_by_id(resource_group_id).try do |resource_group|
diff --git a/app/workers/cluster_update_app_worker.rb b/app/workers/cluster_update_app_worker.rb
index cd2b2e38ea4..97fdec02ba4 100644
--- a/app/workers/cluster_update_app_worker.rb
+++ b/app/workers/cluster_update_app_worker.rb
@@ -26,16 +26,14 @@ class ClusterUpdateAppWorker # rubocop:disable Scalability/IdempotentWorker
private
- # rubocop: disable CodeReuse/ActiveRecord
def execute(app_name, app_id, project_id, scheduled_time)
- project = Project.find_by(id: project_id)
+ project = Project.find_by_id(project_id)
return unless project
find_application(app_name, app_id) do |app|
update_prometheus(app, scheduled_time, project)
end
end
- # rubocop: enable CodeReuse/ActiveRecord
def update_prometheus(app, scheduled_time, project)
return unless app.managed_prometheus?
diff --git a/app/workers/clusters/applications/check_prometheus_health_worker.rb b/app/workers/clusters/applications/check_prometheus_health_worker.rb
deleted file mode 100644
index 4f85c5c5b7a..00000000000
--- a/app/workers/clusters/applications/check_prometheus_health_worker.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Clusters
- module Applications
- class CheckPrometheusHealthWorker
- include ApplicationWorker
-
- data_consistency :always
-
- # rubocop:disable Scalability/CronWorkerContext
- # This worker does not perform work scoped to a context
- include CronjobQueue
- # rubocop:enable Scalability/CronWorkerContext
-
- queue_namespace :incident_management
- feature_category :incident_management
- urgency :low
-
- idempotent!
- worker_has_external_dependencies!
-
- def perform
- demo_project_ids = Gitlab::Monitor::DemoProjects.primary_keys
-
- clusters = Clusters::Cluster.with_application_prometheus
- .with_project_http_integrations(demo_project_ids)
-
- # Move to a seperate worker with scoped context if expanded to do work on customer projects
- clusters.each { |cluster| Clusters::Applications::PrometheusHealthCheckService.new(cluster).execute }
- end
- end
- end
-end
diff --git a/app/workers/clusters/integrations/check_prometheus_health_worker.rb b/app/workers/clusters/integrations/check_prometheus_health_worker.rb
new file mode 100644
index 00000000000..0c0d86e975c
--- /dev/null
+++ b/app/workers/clusters/integrations/check_prometheus_health_worker.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Integrations
+ class CheckPrometheusHealthWorker
+ include ApplicationWorker
+
+ data_consistency :always
+
+ # rubocop:disable Scalability/CronWorkerContext
+ # This worker does not perform work scoped to a context
+ include CronjobQueue
+ # rubocop:enable Scalability/CronWorkerContext
+
+ feature_category :incident_management
+ urgency :low
+
+ idempotent!
+ worker_has_external_dependencies!
+
+ def perform
+ demo_project_ids = Gitlab::Monitor::DemoProjects.primary_keys
+
+ clusters = Clusters::Cluster.with_integration_prometheus
+ .with_project_http_integrations(demo_project_ids)
+
+ # Move to a seperate worker with scoped context if expanded to do work on customer projects
+ clusters.each { |cluster| Clusters::Integrations::PrometheusHealthCheckService.new(cluster).execute }
+ end
+ end
+ end
+end
diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb
index 3399a4f9b57..03a0b5fae00 100644
--- a/app/workers/concerns/application_worker.rb
+++ b/app/workers/concerns/application_worker.rb
@@ -14,6 +14,7 @@ module ApplicationWorker
LOGGING_EXTRA_KEY = 'extra'
DEFAULT_DELAY_INTERVAL = 1
+ SAFE_PUSH_BULK_LIMIT = 1000
included do
set_queue
@@ -54,6 +55,12 @@ module ApplicationWorker
subclass.after_set_class_attribute { subclass.set_queue }
end
+ def with_status
+ status_from_class = self.sidekiq_options_hash['status_expiration']
+
+ set(status_expiration: status_from_class || Gitlab::SidekiqStatus::DEFAULT_EXPIRATION)
+ end
+
def generated_queue_name
Gitlab::SidekiqConfig::WorkerRouter.queue_name_from_worker_name(self)
end
@@ -130,29 +137,62 @@ module ApplicationWorker
end
end
+ def log_bulk_perform_async?
+ @log_bulk_perform_async
+ end
+
+ def log_bulk_perform_async!
+ @log_bulk_perform_async = true
+ end
+
def queue_size
Sidekiq::Queue.new(queue).size
end
def bulk_perform_async(args_list)
- Sidekiq::Client.push_bulk('class' => self, 'args' => args_list)
+ if log_bulk_perform_async?
+ Sidekiq.logger.info('class' => self.name, 'args_list' => args_list, 'args_list_count' => args_list.length, 'message' => 'Inserting multiple jobs')
+ end
+
+ do_push_bulk(args_list).tap do |job_ids|
+ if log_bulk_perform_async?
+ Sidekiq.logger.info('class' => self.name, 'jid_list' => job_ids, 'jid_list_count' => job_ids.length, 'message' => 'Completed JID insertion')
+ end
+ end
end
def bulk_perform_in(delay, args_list, batch_size: nil, batch_delay: nil)
now = Time.now.to_i
- schedule = now + delay.to_i
+ base_schedule_at = now + delay.to_i
- if schedule <= now
- raise ArgumentError, _('The schedule time must be in the future!')
+ if base_schedule_at <= now
+ raise ArgumentError, 'The schedule time must be in the future!'
end
+ schedule_at = base_schedule_at
+
if batch_size && batch_delay
- args_list.each_slice(batch_size.to_i).with_index do |args_batch, idx|
- batch_schedule = schedule + idx * batch_delay.to_i
- Sidekiq::Client.push_bulk('class' => self, 'args' => args_batch, 'at' => batch_schedule)
+ batch_size = batch_size.to_i
+ batch_delay = batch_delay.to_i
+
+ raise ArgumentError, 'batch_size should be greater than 0' unless batch_size > 0
+ raise ArgumentError, 'batch_delay should be greater than 0' unless batch_delay > 0
+
+ # build an array of schedules corresponding to each item in `args_list`
+ bulk_schedule_at = Array.new(args_list.size) do |index|
+ batch_number = index / batch_size
+ base_schedule_at + (batch_number * batch_delay)
+ end
+
+ schedule_at = bulk_schedule_at
+ end
+
+ if Feature.enabled?(:sidekiq_push_bulk_in_batches)
+ in_safe_limit_batches(args_list, schedule_at) do |args_batch, schedule_at_for_batch|
+ Sidekiq::Client.push_bulk('class' => self, 'args' => args_batch, 'at' => schedule_at_for_batch)
end
else
- Sidekiq::Client.push_bulk('class' => self, 'args' => args_list, 'at' => schedule)
+ Sidekiq::Client.push_bulk('class' => self, 'args' => args_list, 'at' => schedule_at)
end
end
@@ -161,5 +201,44 @@ module ApplicationWorker
def delay_interval
DEFAULT_DELAY_INTERVAL.seconds
end
+
+ private
+
+ def do_push_bulk(args_list)
+ if Feature.enabled?(:sidekiq_push_bulk_in_batches)
+ in_safe_limit_batches(args_list) do |args_batch, _|
+ Sidekiq::Client.push_bulk('class' => self, 'args' => args_batch)
+ end
+ else
+ Sidekiq::Client.push_bulk('class' => self, 'args' => args_list)
+ end
+ end
+
+ def in_safe_limit_batches(args_list, schedule_at = nil, safe_limit = SAFE_PUSH_BULK_LIMIT)
+ # `schedule_at` could be one of
+ # - nil.
+ # - a single Numeric that represents time, like `30.minutes.from_now.to_i`.
+ # - an array, where each element is a Numeric that reprsents time.
+ # - Each element in this array would correspond to the time at which
+ # - the job in `args_list` at the corresponding index needs to be scheduled.
+
+ # In the case where `schedule_at` is an array of Numeric, it needs to be sliced
+ # in the same manner as the `args_list`, with each slice containing `safe_limit`
+ # number of elements.
+ schedule_at = schedule_at.each_slice(safe_limit).to_a if schedule_at.is_a?(Array)
+
+ args_list.each_slice(safe_limit).with_index.flat_map do |args_batch, index|
+ schedule_at_for_batch = process_schedule_at_for_batch(schedule_at, index)
+
+ yield(args_batch, schedule_at_for_batch)
+ end
+ end
+
+ def process_schedule_at_for_batch(schedule_at, index)
+ return unless schedule_at
+ return schedule_at[index] if schedule_at.is_a?(Array) && schedule_at.all?(Array)
+
+ schedule_at
+ end
end
end
diff --git a/app/workers/concerns/gitlab/github_import/rescheduling_methods.rb b/app/workers/concerns/gitlab/github_import/rescheduling_methods.rb
index eb1af0869bd..0a43a0fc4d2 100644
--- a/app/workers/concerns/gitlab/github_import/rescheduling_methods.rb
+++ b/app/workers/concerns/gitlab/github_import/rescheduling_methods.rb
@@ -8,9 +8,8 @@ module Gitlab
# project_id - The ID of the GitLab project to import the note into.
# hash - A Hash containing the details of the GitHub object to import.
# notify_key - The Redis key to notify upon completion, if any.
- # rubocop: disable CodeReuse/ActiveRecord
def perform(project_id, hash, notify_key = nil)
- project = Project.find_by(id: project_id)
+ project = Project.find_by_id(project_id)
return notify_waiter(notify_key) unless project
@@ -25,7 +24,6 @@ module Gitlab
.perform_in(client.rate_limit_resets_in, project.id, hash, notify_key)
end
end
- # rubocop: enable CodeReuse/ActiveRecord
def try_import(*args)
import(*args)
diff --git a/app/workers/concerns/gitlab/github_import/stage_methods.rb b/app/workers/concerns/gitlab/github_import/stage_methods.rb
index d7b4578af63..225716f6bf3 100644
--- a/app/workers/concerns/gitlab/github_import/stage_methods.rb
+++ b/app/workers/concerns/gitlab/github_import/stage_methods.rb
@@ -33,13 +33,13 @@ module Gitlab
self.class.perform_in(client.rate_limit_resets_in, project.id)
end
- # rubocop: disable CodeReuse/ActiveRecord
def find_project(id)
# If the project has been marked as failed we want to bail out
# automatically.
- Project.joins_import_state.where(import_state: { status: :started }).find_by(id: id)
+ # rubocop: disable CodeReuse/ActiveRecord
+ Project.joins_import_state.where(import_state: { status: :started }).find_by_id(id)
+ # rubocop: enable CodeReuse/ActiveRecord
end
- # rubocop: enable CodeReuse/ActiveRecord
def abort_on_failure
false
diff --git a/app/workers/concerns/gitlab/jira_import/import_worker.rb b/app/workers/concerns/gitlab/jira_import/import_worker.rb
index 107b6e2e9be..d18b9ff023b 100644
--- a/app/workers/concerns/gitlab/jira_import/import_worker.rb
+++ b/app/workers/concerns/gitlab/jira_import/import_worker.rb
@@ -14,7 +14,7 @@ module Gitlab
end
def perform(project_id)
- project = Project.find_by(id: project_id) # rubocop: disable CodeReuse/ActiveRecord
+ project = Project.find_by_id(project_id)
return unless can_import?(project)
diff --git a/app/workers/concerns/limited_capacity/worker.rb b/app/workers/concerns/limited_capacity/worker.rb
index b4cdfda680f..bcedb4efcc0 100644
--- a/app/workers/concerns/limited_capacity/worker.rb
+++ b/app/workers/concerns/limited_capacity/worker.rb
@@ -47,7 +47,7 @@ module LimitedCapacity
# would be occupied by a job that will be performed in the distant future.
# We let the cron worker enqueue new jobs, this could be seen as our retry and
# back off mechanism because the job might fail again if executed immediately.
- sidekiq_options retry: 0
+ sidekiq_options retry: 0, status_expiration: Gitlab::SidekiqStatus::DEFAULT_EXPIRATION
deduplicate :none
end
diff --git a/app/workers/concerns/new_issuable.rb b/app/workers/concerns/new_issuable.rb
index 482a74f49f7..d761f023cad 100644
--- a/app/workers/concerns/new_issuable.rb
+++ b/app/workers/concerns/new_issuable.rb
@@ -10,21 +10,17 @@ module NewIssuable
user && issuable
end
- # rubocop: disable CodeReuse/ActiveRecord
def set_user(user_id)
- @user = User.find_by(id: user_id) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ @user = User.find_by_id(user_id) # rubocop:disable Gitlab/ModuleWithInstanceVariables
log_error(User, user_id) unless @user # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def set_issuable(issuable_id)
- @issuable = issuable_class.find_by(id: issuable_id) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ @issuable = issuable_class.find_by_id(issuable_id) # rubocop:disable Gitlab/ModuleWithInstanceVariables
log_error(issuable_class, issuable_id) unless @issuable # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
- # rubocop: enable CodeReuse/ActiveRecord
def log_error(record_class, record_id)
Gitlab::AppLogger.error("#{self.class}: couldn't find #{record_class} with ID=#{record_id}, skipping job")
diff --git a/app/workers/concerns/todos_destroyer_queue.rb b/app/workers/concerns/todos_destroyer_queue.rb
index 1bbccbfb1f9..1c31b64ad97 100644
--- a/app/workers/concerns/todos_destroyer_queue.rb
+++ b/app/workers/concerns/todos_destroyer_queue.rb
@@ -8,6 +8,6 @@ module TodosDestroyerQueue
included do
queue_namespace :todos_destroyer
- feature_category :issue_tracking
+ feature_category :team_planning
end
end
diff --git a/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb b/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
index 69f5906f54c..7f7a77d0524 100644
--- a/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
+++ b/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
@@ -159,7 +159,10 @@ module ContainerExpirationPolicies
return unless tags_count && cached_tags_count && tags_count != 0
- log_extra_metadata_on_done(:cleanup_tags_service_cache_hit_ratio, cached_tags_count / tags_count.to_f)
+ ratio = cached_tags_count / tags_count.to_f
+ ratio_as_percentage = (ratio * 100).round(2)
+
+ log_extra_metadata_on_done(:cleanup_tags_service_cache_hit_ratio, ratio_as_percentage)
end
def log_truncate(result)
diff --git a/app/workers/create_commit_signature_worker.rb b/app/workers/create_commit_signature_worker.rb
index 01a2e109967..c35d2d3b33b 100644
--- a/app/workers/create_commit_signature_worker.rb
+++ b/app/workers/create_commit_signature_worker.rb
@@ -12,7 +12,6 @@ class CreateCommitSignatureWorker
idempotent!
loggable_arguments 0
- # rubocop: disable CodeReuse/ActiveRecord
def perform(commit_shas, project_id)
# Older versions of Git::BranchPushService may push a single commit ID on
# the stack. We need this to be backwards compatible.
@@ -20,7 +19,7 @@ class CreateCommitSignatureWorker
return if commit_shas.empty?
- project = Project.find_by(id: project_id)
+ project = Project.find_by_id(project_id)
return unless project
commits = project.commits_by(oids: commit_shas)
@@ -44,5 +43,4 @@ class CreateCommitSignatureWorker
Gitlab::AppLogger.error("Failed to create signature for commit #{commit.id}. Error: #{e.message}")
end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/database/drop_detached_partitions_worker.rb b/app/workers/database/drop_detached_partitions_worker.rb
index 1e4dc20a0d2..126c46a338b 100644
--- a/app/workers/database/drop_detached_partitions_worker.rb
+++ b/app/workers/database/drop_detached_partitions_worker.rb
@@ -12,7 +12,7 @@ module Database
def perform
Gitlab::Database::Partitioning.drop_detached_partitions
ensure
- Gitlab::Database::Partitioning::PartitionMonitoring.new.report_metrics
+ Gitlab::Database::Partitioning.report_metrics
end
end
end
diff --git a/app/workers/database/partition_management_worker.rb b/app/workers/database/partition_management_worker.rb
index 5a1f139dc29..ba1ad7a0e81 100644
--- a/app/workers/database/partition_management_worker.rb
+++ b/app/workers/database/partition_management_worker.rb
@@ -14,7 +14,7 @@ module Database
def perform
Gitlab::Database::Partitioning.sync_partitions
ensure
- Gitlab::Database::Partitioning::PartitionMonitoring.new.report_metrics
+ Gitlab::Database::Partitioning.report_metrics
end
end
end
diff --git a/app/workers/delete_container_repository_worker.rb b/app/workers/delete_container_repository_worker.rb
index beeca559060..a4d6adc2195 100644
--- a/app/workers/delete_container_repository_worker.rb
+++ b/app/workers/delete_container_repository_worker.rb
@@ -15,10 +15,9 @@ class DeleteContainerRepositoryWorker # rubocop:disable Scalability/IdempotentWo
attr_reader :container_repository
- # rubocop: disable CodeReuse/ActiveRecord
def perform(current_user_id, container_repository_id)
- current_user = User.find_by(id: current_user_id)
- @container_repository = ContainerRepository.find_by(id: container_repository_id)
+ current_user = User.find_by_id(current_user_id)
+ @container_repository = ContainerRepository.find_by_id(container_repository_id)
project = container_repository&.project
return unless current_user && container_repository && project
@@ -29,7 +28,6 @@ class DeleteContainerRepositoryWorker # rubocop:disable Scalability/IdempotentWo
Projects::ContainerRepository::DestroyService.new(project, current_user).execute(container_repository)
end
end
- # rubocop: enable CodeReuse/ActiveRecord
# For ExclusiveLeaseGuard concern
def lease_key
diff --git a/app/workers/dependency_proxy/image_ttl_group_policy_worker.rb b/app/workers/dependency_proxy/image_ttl_group_policy_worker.rb
index fed469e6dc8..6a1de00ce80 100644
--- a/app/workers/dependency_proxy/image_ttl_group_policy_worker.rb
+++ b/app/workers/dependency_proxy/image_ttl_group_policy_worker.rb
@@ -13,9 +13,8 @@ module DependencyProxy
def perform
DependencyProxy::ImageTtlGroupPolicy.enabled.each do |policy|
- # Technical Debt: change to read_before https://gitlab.com/gitlab-org/gitlab/-/issues/341536
- qualified_blobs = policy.group.dependency_proxy_blobs.active.updated_before(policy.ttl)
- qualified_manifests = policy.group.dependency_proxy_manifests.active.updated_before(policy.ttl)
+ qualified_blobs = policy.group.dependency_proxy_blobs.active.read_before(policy.ttl)
+ qualified_manifests = policy.group.dependency_proxy_manifests.active.read_before(policy.ttl)
enqueue_blob_cleanup_job if expire_artifacts(qualified_blobs, DependencyProxy::Blob)
enqueue_manifest_cleanup_job if expire_artifacts(qualified_manifests, DependencyProxy::Manifest)
diff --git a/app/workers/deployments/archive_in_project_worker.rb b/app/workers/deployments/archive_in_project_worker.rb
new file mode 100644
index 00000000000..2de4cacbbd6
--- /dev/null
+++ b/app/workers/deployments/archive_in_project_worker.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Deployments
+ class ArchiveInProjectWorker
+ include ApplicationWorker
+
+ queue_namespace :deployment
+ feature_category :continuous_delivery
+ idempotent!
+ deduplicate :until_executed, including_scheduled: true
+ data_consistency :delayed
+
+ def perform(project_id)
+ Project.find_by_id(project_id).try do |project|
+ Deployments::ArchiveInProjectService.new(project, nil).execute
+ end
+ end
+ end
+end
diff --git a/app/workers/detect_repository_languages_worker.rb b/app/workers/detect_repository_languages_worker.rb
index 8c7ef6c9e32..702b83a3185 100644
--- a/app/workers/detect_repository_languages_worker.rb
+++ b/app/workers/detect_repository_languages_worker.rb
@@ -14,16 +14,14 @@ class DetectRepositoryLanguagesWorker # rubocop:disable Scalability/IdempotentWo
attr_reader :project
- # rubocop: disable CodeReuse/ActiveRecord
def perform(project_id, user_id = nil)
- @project = Project.find_by(id: project_id)
+ @project = Project.find_by_id(project_id)
return unless project
try_obtain_lease do
::Projects::DetectRepositoryLanguagesService.new(project).execute
end
end
- # rubocop: enable CodeReuse/ActiveRecord
private
diff --git a/app/workers/email_receiver_worker.rb b/app/workers/email_receiver_worker.rb
index 51211834e06..321d492f0f3 100644
--- a/app/workers/email_receiver_worker.rb
+++ b/app/workers/email_receiver_worker.rb
@@ -7,7 +7,7 @@ class EmailReceiverWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: 3
- feature_category :issue_tracking
+ feature_category :team_planning
urgency :high
weight 2
@@ -118,7 +118,9 @@ class EmailReceiverWorker # rubocop:disable Scalability/IdempotentWorker
end
if reason
- EmailRejectionMailer.rejection(reason, raw, can_retry).deliver_later
+ receiver.mail.body = nil
+
+ EmailRejectionMailer.rejection(reason, receiver.mail.encoded, can_retry).deliver_later
end
end
end
diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb
index 0230a226567..d7bd8207f06 100644
--- a/app/workers/emails_on_push_worker.rb
+++ b/app/workers/emails_on_push_worker.rb
@@ -87,13 +87,14 @@ class EmailsOnPushWorker # rubocop:disable Scalability/IdempotentWorker
private
def send_email(recipient, project_id, options)
- # Generating the body of this email can be expensive, so only do it once
- @skip_premailer ||= email.present?
- @email ||= Notify.repository_push_email(project_id, options)
-
- email.to = recipient
- email.add_message_id
- email.header[:skip_premailer] = true if skip_premailer
- email.deliver_now
+ @email ||= Notify.repository_push_email(project_id, options).tap do |mail|
+ Premailer::Rails::Hook.perform(mail)
+ end
+
+ current_email = email.dup
+ current_email.to = recipient
+ current_email.add_message_id
+ current_email.header[:skip_premailer] = true
+ current_email.deliver_now
end
end
diff --git a/app/workers/expire_build_instance_artifacts_worker.rb b/app/workers/expire_build_instance_artifacts_worker.rb
index 77b8f59e365..948e1a59b07 100644
--- a/app/workers/expire_build_instance_artifacts_worker.rb
+++ b/app/workers/expire_build_instance_artifacts_worker.rb
@@ -9,17 +9,17 @@ class ExpireBuildInstanceArtifactsWorker # rubocop:disable Scalability/Idempoten
feature_category :build_artifacts
- # rubocop: disable CodeReuse/ActiveRecord
def perform(build_id)
+ # rubocop: disable CodeReuse/ActiveRecord
build = Ci::Build
.with_expired_artifacts
.reorder(nil)
- .find_by(id: build_id)
+ .find_by_id(build_id)
+ # rubocop: enable CodeReuse/ActiveRecord
return unless build&.project && !build.project.pending_delete
Gitlab::AppLogger.info("Removing artifacts for build #{build.id}...")
build.erase_erasable_artifacts!
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/expire_job_cache_worker.rb b/app/workers/expire_job_cache_worker.rb
index 7374f650546..3c5a7717d70 100644
--- a/app/workers/expire_job_cache_worker.rb
+++ b/app/workers/expire_job_cache_worker.rb
@@ -14,9 +14,8 @@ class ExpireJobCacheWorker # rubocop:disable Scalability/IdempotentWorker
deduplicate :until_executing, including_scheduled: true
idempotent!
- # rubocop: disable CodeReuse/ActiveRecord
def perform(job_id)
- job = CommitStatus.preload(:pipeline, :project).find_by(id: job_id)
+ job = CommitStatus.preload(:pipeline, :project).find_by_id(job_id) # rubocop: disable CodeReuse/ActiveRecord
return unless job
pipeline = job.pipeline
@@ -25,7 +24,6 @@ class ExpireJobCacheWorker # rubocop:disable Scalability/IdempotentWorker
Gitlab::EtagCaching::Store.new.touch(project_job_path(project, job))
ExpirePipelineCacheWorker.perform_async(pipeline.id)
end
- # rubocop: enable CodeReuse/ActiveRecord
private
diff --git a/app/workers/expire_pipeline_cache_worker.rb b/app/workers/expire_pipeline_cache_worker.rb
index 07e6939d1c7..9a0c617da57 100644
--- a/app/workers/expire_pipeline_cache_worker.rb
+++ b/app/workers/expire_pipeline_cache_worker.rb
@@ -17,13 +17,11 @@ class ExpirePipelineCacheWorker
# Uncomment once https://gitlab.com/gitlab-org/gitlab/-/issues/325291 is resolved
# idempotent!
- # rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id)
- pipeline = Ci::Pipeline.find_by(id: pipeline_id)
+ pipeline = Ci::Pipeline.find_by_id(pipeline_id)
return unless pipeline
Ci::ExpirePipelineCacheService.new.execute(pipeline)
end
- # rubocop: enable CodeReuse/ActiveRecord
end
# rubocop:enable Scalability/IdempotentWorker
diff --git a/app/workers/export_csv_worker.rb b/app/workers/export_csv_worker.rb
index 68feaa61cdd..c5feb02b2bd 100644
--- a/app/workers/export_csv_worker.rb
+++ b/app/workers/export_csv_worker.rb
@@ -7,7 +7,7 @@ class ExportCsvWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: 3
- feature_category :issue_tracking
+ feature_category :team_planning
worker_resource_boundary :cpu
loggable_arguments 2
diff --git a/app/workers/gitlab/jira_import/import_issue_worker.rb b/app/workers/gitlab/jira_import/import_issue_worker.rb
index eabe7328b92..3824cc1f3ef 100644
--- a/app/workers/gitlab/jira_import/import_issue_worker.rb
+++ b/app/workers/gitlab/jira_import/import_issue_worker.rb
@@ -54,7 +54,7 @@ module Gitlab
label_link_attrs << build_label_attrs(issue_id, import_label_id.to_i)
- Gitlab::Database.main.bulk_insert(LabelLink.table_name, label_link_attrs) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(LabelLink.table_name, label_link_attrs) # rubocop:disable Gitlab/BulkInsert
end
def assign_issue(project_id, issue_id, assignee_ids)
@@ -62,7 +62,7 @@ module Gitlab
assignee_attrs = assignee_ids.map { |user_id| { issue_id: issue_id, user_id: user_id } }
- Gitlab::Database.main.bulk_insert(IssueAssignee.table_name, assignee_attrs) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(IssueAssignee.table_name, assignee_attrs) # rubocop:disable Gitlab/BulkInsert
end
def build_label_attrs(issue_id, label_id)
diff --git a/app/workers/gitlab/jira_import/stage/start_import_worker.rb b/app/workers/gitlab/jira_import/stage/start_import_worker.rb
index e0de3ee169e..3f6ad66e278 100644
--- a/app/workers/gitlab/jira_import/stage/start_import_worker.rb
+++ b/app/workers/gitlab/jira_import/stage/start_import_worker.rb
@@ -16,7 +16,7 @@ module Gitlab
attr_reader :project
def perform(project_id)
- @project = Project.find_by(id: project_id) # rubocop: disable CodeReuse/ActiveRecord
+ @project = Project.find_by_id(project_id)
return unless start_import
diff --git a/app/workers/hashed_storage/project_migrate_worker.rb b/app/workers/hashed_storage/project_migrate_worker.rb
index bcc80cc2a70..460aac3f2f2 100644
--- a/app/workers/hashed_storage/project_migrate_worker.rb
+++ b/app/workers/hashed_storage/project_migrate_worker.rb
@@ -16,12 +16,11 @@ module HashedStorage
attr_reader :project_id
- # rubocop: disable CodeReuse/ActiveRecord
def perform(project_id, old_disk_path = nil)
@project_id = project_id # we need to set this in order to create the lease_key
try_obtain_lease do
- project = Project.without_deleted.find_by(id: project_id)
+ project = Project.without_deleted.find_by_id(project_id)
break unless project && project.storage_upgradable?
old_disk_path ||= Storage::LegacyProject.new(project).disk_path
@@ -29,6 +28,5 @@ module HashedStorage
::Projects::HashedStorage::MigrationService.new(project, old_disk_path, logger: logger).execute
end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
diff --git a/app/workers/hashed_storage/project_rollback_worker.rb b/app/workers/hashed_storage/project_rollback_worker.rb
index 07a7ab63718..91ea3dd9189 100644
--- a/app/workers/hashed_storage/project_rollback_worker.rb
+++ b/app/workers/hashed_storage/project_rollback_worker.rb
@@ -16,12 +16,11 @@ module HashedStorage
attr_reader :project_id
- # rubocop: disable CodeReuse/ActiveRecord
def perform(project_id, old_disk_path = nil)
@project_id = project_id # we need to set this in order to create the lease_key
try_obtain_lease do
- project = Project.without_deleted.find_by(id: project_id)
+ project = Project.without_deleted.find_by_id(project_id)
break unless project
old_disk_path ||= project.disk_path
@@ -29,6 +28,5 @@ module HashedStorage
::Projects::HashedStorage::RollbackService.new(project, old_disk_path, logger: logger).execute
end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
diff --git a/app/workers/import_issues_csv_worker.rb b/app/workers/import_issues_csv_worker.rb
index 58e411c7b19..fe5b1c13d56 100644
--- a/app/workers/import_issues_csv_worker.rb
+++ b/app/workers/import_issues_csv_worker.rb
@@ -8,7 +8,7 @@ class ImportIssuesCsvWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: 3
idempotent!
- feature_category :issue_tracking
+ feature_category :team_planning
worker_resource_boundary :cpu
weight 2
diff --git a/app/workers/integrations/create_external_cross_reference_worker.rb b/app/workers/integrations/create_external_cross_reference_worker.rb
new file mode 100644
index 00000000000..02c1315249e
--- /dev/null
+++ b/app/workers/integrations/create_external_cross_reference_worker.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Integrations
+ class CreateExternalCrossReferenceWorker
+ include ApplicationWorker
+
+ data_consistency :delayed
+
+ feature_category :integrations
+ urgency :low
+ idempotent!
+ deduplicate :until_executed, including_scheduled: true
+ loggable_arguments 2
+
+ def perform(project_id, external_issue_id, mentionable_type, mentionable_id, author_id)
+ project = Project.find_by_id(project_id) || return
+ author = User.find_by_id(author_id) || return
+ mentionable = find_mentionable(mentionable_type, mentionable_id, project) || return
+ external_issue = ExternalIssue.new(external_issue_id, project)
+
+ project.external_issue_tracker.create_cross_reference_note(
+ external_issue,
+ mentionable,
+ author
+ )
+ end
+
+ private
+
+ def find_mentionable(mentionable_type, mentionable_id, project)
+ mentionable_class = mentionable_type.safe_constantize
+
+ # Passing an invalid mentionable_class is a developer error, so we don't want to retry the job
+ # but still track the exception on production, and raise it in development.
+ unless mentionable_class && mentionable_class < Mentionable
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(ArgumentError.new("Unexpected class '#{mentionable_type}' is not a Mentionable"))
+ return
+ end
+
+ if mentionable_type == 'Commit'
+ project.commit(mentionable_id)
+ else
+ mentionable_class.find_by_id(mentionable_id)
+ end
+ end
+ end
+end
diff --git a/app/workers/invalid_gpg_signature_update_worker.rb b/app/workers/invalid_gpg_signature_update_worker.rb
index c9567e102d3..7dc1e395597 100644
--- a/app/workers/invalid_gpg_signature_update_worker.rb
+++ b/app/workers/invalid_gpg_signature_update_worker.rb
@@ -10,13 +10,11 @@ class InvalidGpgSignatureUpdateWorker # rubocop:disable Scalability/IdempotentWo
feature_category :source_code_management
weight 2
- # rubocop: disable CodeReuse/ActiveRecord
def perform(gpg_key_id)
- gpg_key = GpgKey.find_by(id: gpg_key_id)
+ gpg_key = GpgKey.find_by_id(gpg_key_id)
return unless gpg_key
Gitlab::Gpg::InvalidGpgSignatureUpdater.new(gpg_key).run
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/issuable/label_links_destroy_worker.rb b/app/workers/issuable/label_links_destroy_worker.rb
index f88c061bafb..da785550a43 100644
--- a/app/workers/issuable/label_links_destroy_worker.rb
+++ b/app/workers/issuable/label_links_destroy_worker.rb
@@ -7,7 +7,7 @@ module Issuable
data_consistency :always
idempotent!
- feature_category :issue_tracking
+ feature_category :team_planning
def perform(target_id, target_type)
::Issuable::DestroyLabelLinksService.new(target_id, target_type).execute
diff --git a/app/workers/issuable_export_csv_worker.rb b/app/workers/issuable_export_csv_worker.rb
index 7e2c3407772..9d543a21dc3 100644
--- a/app/workers/issuable_export_csv_worker.rb
+++ b/app/workers/issuable_export_csv_worker.rb
@@ -7,7 +7,7 @@ class IssuableExportCsvWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: 3
- feature_category :issue_tracking
+ feature_category :team_planning
worker_resource_boundary :cpu
loggable_arguments 2
diff --git a/app/workers/issuables/clear_groups_issue_counter_worker.rb b/app/workers/issuables/clear_groups_issue_counter_worker.rb
index 9e62224b83d..82026bc21c7 100644
--- a/app/workers/issuables/clear_groups_issue_counter_worker.rb
+++ b/app/workers/issuables/clear_groups_issue_counter_worker.rb
@@ -8,7 +8,7 @@ module Issuables
idempotent!
urgency :low
- feature_category :issue_tracking
+ feature_category :team_planning
def perform(group_ids = [])
return if group_ids.empty?
diff --git a/app/workers/issue_due_scheduler_worker.rb b/app/workers/issue_due_scheduler_worker.rb
index ad3470ae64b..ab586dce717 100644
--- a/app/workers/issue_due_scheduler_worker.rb
+++ b/app/workers/issue_due_scheduler_worker.rb
@@ -7,7 +7,7 @@ class IssueDueSchedulerWorker # rubocop:disable Scalability/IdempotentWorker
include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
- feature_category :issue_tracking
+ feature_category :team_planning
# rubocop: disable CodeReuse/ActiveRecord
def perform
diff --git a/app/workers/issue_placement_worker.rb b/app/workers/issue_placement_worker.rb
index 22e2a8e95f4..cfd72b90a42 100644
--- a/app/workers/issue_placement_worker.rb
+++ b/app/workers/issue_placement_worker.rb
@@ -1,5 +1,8 @@
# frozen_string_literal: true
+# todo: remove this worker and it's queue definition from all_queues after Issues::PlacementWorker is deployed
+# We want to keep it for one release in case some jobs are already scheduled in the old queue so we need the worker
+# to be available to finish those. All new jobs will be queued into the new queue.
class IssuePlacementWorker
include ApplicationWorker
@@ -9,7 +12,7 @@ class IssuePlacementWorker
idempotent!
deduplicate :until_executed, including_scheduled: true
- feature_category :issue_tracking
+ feature_category :team_planning
urgency :high
worker_resource_boundary :cpu
weight 2
diff --git a/app/workers/issue_rebalancing_worker.rb b/app/workers/issue_rebalancing_worker.rb
index 01984197aae..a43e76feae4 100644
--- a/app/workers/issue_rebalancing_worker.rb
+++ b/app/workers/issue_rebalancing_worker.rb
@@ -1,5 +1,8 @@
# frozen_string_literal: true
+# todo: remove this worker and it's queue definition from all_queues after Issue::RebalancingWorker is released.
+# We want to keep it for one release in case some jobs are already scheduled in the old queue so we need the worker
+# to be available to finish those. All new jobs will be queued into the new queue.
class IssueRebalancingWorker
include ApplicationWorker
@@ -9,13 +12,14 @@ class IssueRebalancingWorker
idempotent!
urgency :low
- feature_category :issue_tracking
+ feature_category :team_planning
deduplicate :until_executed, including_scheduled: true
def perform(ignore = nil, project_id = nil, root_namespace_id = nil)
# we need to have exactly one of the project_id and root_namespace_id params be non-nil
raise ArgumentError, "Expected only one of the params project_id: #{project_id} and root_namespace_id: #{root_namespace_id}" if project_id && root_namespace_id
return if project_id.nil? && root_namespace_id.nil?
+ return if ::Gitlab::Issues::Rebalancing::State.rebalance_recently_finished?(project_id, root_namespace_id)
# pull the projects collection to be rebalanced either the project if namespace is not a group(i.e. user namesapce)
# or the root namespace, this also makes the worker backward compatible with previous version where a project_id was
diff --git a/app/workers/issues/placement_worker.rb b/app/workers/issues/placement_worker.rb
new file mode 100644
index 00000000000..ec29a754128
--- /dev/null
+++ b/app/workers/issues/placement_worker.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Issues
+ class PlacementWorker
+ include ApplicationWorker
+
+ data_consistency :always
+
+ sidekiq_options retry: 3
+
+ idempotent!
+ deduplicate :until_executed, including_scheduled: true
+ feature_category :team_planning
+ urgency :high
+ worker_resource_boundary :cpu
+ weight 2
+
+ # Move at most the most recent 100 issues
+ QUERY_LIMIT = 100
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def perform(issue_id, project_id = nil)
+ issue = find_issue(issue_id, project_id)
+ return unless issue
+
+ # Temporary disable moving null elements because of performance problems
+ # For more information check https://gitlab.com/gitlab-com/gl-infra/production/-/issues/4321
+ return if issue.blocked_for_repositioning?
+
+ # Move the oldest 100 unpositioned items to the end.
+ # This is to deal with out-of-order execution of the worker,
+ # while preserving creation order.
+ to_place = Issue
+ .relative_positioning_query_base(issue)
+ .with_null_relative_position
+ .order({ created_at: :asc }, { id: :asc })
+ .limit(QUERY_LIMIT + 1)
+ .to_a
+
+ leftover = to_place.pop if to_place.count > QUERY_LIMIT
+
+ Issue.move_nulls_to_end(to_place)
+ Issues::BaseService.new(project: nil).rebalance_if_needed(to_place.max_by(&:relative_position))
+ Issues::PlacementWorker.perform_async(nil, leftover.project_id) if leftover.present?
+ rescue RelativePositioning::NoSpaceLeft => e
+ Gitlab::ErrorTracking.log_exception(e, issue_id: issue_id, project_id: project_id)
+ Issues::RebalancingWorker.perform_async(nil, *root_namespace_id_to_rebalance(issue, project_id))
+ end
+
+ def find_issue(issue_id, project_id)
+ return Issue.id_in(issue_id).take if issue_id
+
+ project = Project.id_in(project_id).take
+ return unless project
+
+ project.issues.take
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ private
+
+ def root_namespace_id_to_rebalance(issue, project_id)
+ project_id = project_id.presence || issue.project_id
+ Project.find(project_id)&.self_or_root_group_ids
+ end
+ end
+end
diff --git a/app/workers/issues/rebalancing_worker.rb b/app/workers/issues/rebalancing_worker.rb
new file mode 100644
index 00000000000..466617d9fa1
--- /dev/null
+++ b/app/workers/issues/rebalancing_worker.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Issues
+ class RebalancingWorker
+ include ApplicationWorker
+
+ data_consistency :always
+
+ sidekiq_options retry: 3
+
+ idempotent!
+ urgency :low
+ feature_category :team_planning
+ deduplicate :until_executed, including_scheduled: true
+
+ def perform(ignore = nil, project_id = nil, root_namespace_id = nil)
+ # we need to have exactly one of the project_id and root_namespace_id params be non-nil
+ raise ArgumentError, "Expected only one of the params project_id: #{project_id} and root_namespace_id: #{root_namespace_id}" if project_id && root_namespace_id
+ return if project_id.nil? && root_namespace_id.nil?
+
+ # pull the projects collection to be rebalanced either the project if namespace is not a group(i.e. user namesapce)
+ # or the root namespace, this also makes the worker backward compatible with previous version where a project_id was
+ # passed as the param
+ projects_to_rebalance = projects_collection(project_id, root_namespace_id)
+
+ # something might have happened with the namespace between scheduling the worker and actually running it,
+ # maybe it was removed.
+ if projects_to_rebalance.blank?
+ Gitlab::ErrorTracking.log_exception(
+ ArgumentError.new("Projects to be rebalanced not found for arguments: project_id #{project_id}, root_namespace_id: #{root_namespace_id}"),
+ { project_id: project_id, root_namespace_id: root_namespace_id })
+
+ return
+ end
+
+ Issues::RelativePositionRebalancingService.new(projects_to_rebalance).execute
+ rescue Issues::RelativePositionRebalancingService::TooManyConcurrentRebalances => e
+ Gitlab::ErrorTracking.log_exception(e, root_namespace_id: root_namespace_id, project_id: project_id)
+ end
+
+ private
+
+ def projects_collection(project_id, root_namespace_id)
+ # we can have either project_id(older version) or project_id if project is part of a user namespace and not a group
+ # or root_namespace_id(newer version) never both.
+ return Project.id_in([project_id]) if project_id
+
+ Namespace.find_by_id(root_namespace_id)&.all_projects
+ end
+ end
+end
diff --git a/app/workers/issues/reschedule_stuck_issue_rebalances_worker.rb b/app/workers/issues/reschedule_stuck_issue_rebalances_worker.rb
new file mode 100644
index 00000000000..d1759589cc0
--- /dev/null
+++ b/app/workers/issues/reschedule_stuck_issue_rebalances_worker.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Issues
+ class RescheduleStuckIssueRebalancesWorker
+ include ApplicationWorker
+ include CronjobQueue
+
+ data_consistency :sticky
+
+ idempotent!
+ urgency :low
+ feature_category :team_planning
+ deduplicate :until_executed, including_scheduled: true
+
+ def perform
+ namespace_ids, project_ids = ::Gitlab::Issues::Rebalancing::State.fetch_rebalancing_groups_and_projects
+
+ return if namespace_ids.blank? && project_ids.blank?
+
+ namespaces = Namespace.id_in(namespace_ids)
+ projects = Project.id_in(project_ids)
+
+ IssueRebalancingWorker.bulk_perform_async_with_contexts(
+ namespaces,
+ arguments_proc: -> (namespace) { [nil, nil, namespace.id] },
+ context_proc: -> (namespace) { { namespace: namespace } }
+ )
+
+ IssueRebalancingWorker.bulk_perform_async_with_contexts(
+ projects,
+ arguments_proc: -> (project) { [nil, project.id, nil] },
+ context_proc: -> (project) { { project: project } }
+ )
+ end
+ end
+end
diff --git a/app/workers/loose_foreign_keys/cleanup_worker.rb b/app/workers/loose_foreign_keys/cleanup_worker.rb
new file mode 100644
index 00000000000..b4565dbf624
--- /dev/null
+++ b/app/workers/loose_foreign_keys/cleanup_worker.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module LooseForeignKeys
+ class CleanupWorker
+ include ApplicationWorker
+ include Gitlab::ExclusiveLeaseHelpers
+ include CronjobQueue # rubocop: disable Scalability/CronWorkerContext
+
+ feature_category :sharding
+ data_consistency :always
+ idempotent!
+
+ def perform
+ return if Feature.disabled?(:loose_foreign_key_cleanup, default_enabled: :yaml)
+
+ ttl = ModificationTracker::MAX_RUNTIME + 1.minute
+ in_lock(self.class.name.underscore, ttl: ttl, retries: 0) do
+ # TODO: Iterate over the connections
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/341513
+ stats = ProcessDeletedRecordsService.new(connection: ApplicationRecord.connection).execute
+ log_extra_metadata_on_done(:stats, stats)
+ end
+ end
+ end
+end
diff --git a/app/workers/mail_scheduler/issue_due_worker.rb b/app/workers/mail_scheduler/issue_due_worker.rb
index 4c17f8df722..585fa43916e 100644
--- a/app/workers/mail_scheduler/issue_due_worker.rb
+++ b/app/workers/mail_scheduler/issue_due_worker.rb
@@ -9,7 +9,7 @@ module MailScheduler
sidekiq_options retry: 3
include MailSchedulerQueue
- feature_category :issue_tracking
+ feature_category :team_planning
# rubocop: disable CodeReuse/ActiveRecord
def perform(project_id)
diff --git a/app/workers/mail_scheduler/notification_service_worker.rb b/app/workers/mail_scheduler/notification_service_worker.rb
index 0e6494a45d6..25c9ac5547b 100644
--- a/app/workers/mail_scheduler/notification_service_worker.rb
+++ b/app/workers/mail_scheduler/notification_service_worker.rb
@@ -11,7 +11,7 @@ module MailScheduler
sidekiq_options retry: 3
include MailSchedulerQueue
- feature_category :issue_tracking
+ feature_category :team_planning
worker_resource_boundary :cpu
loggable_arguments 0
diff --git a/app/workers/namespaces/invite_team_email_worker.rb b/app/workers/namespaces/invite_team_email_worker.rb
new file mode 100644
index 00000000000..eabf33a7fba
--- /dev/null
+++ b/app/workers/namespaces/invite_team_email_worker.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Namespaces
+ class InviteTeamEmailWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+
+ data_consistency :always
+
+ feature_category :experimentation_activation
+ urgency :low
+
+ def perform(group_id, user_id)
+ # rubocop: disable CodeReuse/ActiveRecord
+ user = User.find_by(id: user_id)
+ group = Group.find_by(id: group_id)
+ # rubocop: enable CodeReuse/ActiveRecord
+ return unless user && group
+
+ Namespaces::InviteTeamEmailService.send_email(user, group)
+ end
+ end
+end
diff --git a/app/workers/new_issue_worker.rb b/app/workers/new_issue_worker.rb
index 899545fc02c..13936fac1e4 100644
--- a/app/workers/new_issue_worker.rb
+++ b/app/workers/new_issue_worker.rb
@@ -8,7 +8,7 @@ class NewIssueWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: 3
include NewIssuable
- feature_category :issue_tracking
+ feature_category :team_planning
urgency :high
worker_resource_boundary :cpu
weight 2
diff --git a/app/workers/new_note_worker.rb b/app/workers/new_note_worker.rb
index e54d84e382e..ecc78236161 100644
--- a/app/workers/new_note_worker.rb
+++ b/app/workers/new_note_worker.rb
@@ -7,21 +7,19 @@ class NewNoteWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_options retry: 3
- feature_category :issue_tracking
+ feature_category :team_planning
urgency :high
worker_resource_boundary :cpu
weight 2
# Keep extra parameter to preserve backwards compatibility with
# old `NewNoteWorker` jobs (can remove later)
- # rubocop: disable CodeReuse/ActiveRecord
def perform(note_id, _params = {})
- if note = Note.find_by(id: note_id)
+ if note = Note.find_by_id(note_id)
NotificationService.new.new_note(note) unless note.skip_notification?
Notes::PostProcessService.new(note).execute
else
Gitlab::AppLogger.error("NewNoteWorker: couldn't find note with ID=#{note_id}, skipping job")
end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/pages_domain_verification_worker.rb b/app/workers/pages_domain_verification_worker.rb
index 59de00d40d5..1696abd7b70 100644
--- a/app/workers/pages_domain_verification_worker.rb
+++ b/app/workers/pages_domain_verification_worker.rb
@@ -9,15 +9,13 @@ class PagesDomainVerificationWorker # rubocop:disable Scalability/IdempotentWork
feature_category :pages
- # rubocop: disable CodeReuse/ActiveRecord
def perform(domain_id)
return if Gitlab::Database.read_only?
- domain = PagesDomain.find_by(id: domain_id)
+ domain = PagesDomain.find_by_id(domain_id)
return unless domain
VerifyPagesDomainService.new(domain).execute
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/pages_worker.rb b/app/workers/pages_worker.rb
index 5e951ab2c3a..cceafbc7d2d 100644
--- a/app/workers/pages_worker.rb
+++ b/app/workers/pages_worker.rb
@@ -14,15 +14,13 @@ class PagesWorker # rubocop:disable Scalability/IdempotentWorker
send(action, *arg) # rubocop:disable GitlabSecurity/PublicSend
end
- # rubocop: disable CodeReuse/ActiveRecord
def deploy(build_id)
- build = Ci::Build.find_by(id: build_id)
+ build = Ci::Build.find_by_id(build_id)
update_contents = Projects::UpdatePagesService.new(build.project, build).execute
if update_contents[:status] == :success
Projects::UpdatePagesConfigurationService.new(build.project).execute
end
end
- # rubocop: enable CodeReuse/ActiveRecord
def remove(namespace_path, project_path)
full_path = File.join(Settings.pages.path, namespace_path, project_path)
diff --git a/app/workers/pipeline_hooks_worker.rb b/app/workers/pipeline_hooks_worker.rb
index c67f3860a50..eb5d0086592 100644
--- a/app/workers/pipeline_hooks_worker.rb
+++ b/app/workers/pipeline_hooks_worker.rb
@@ -10,12 +10,10 @@ class PipelineHooksWorker # rubocop:disable Scalability/IdempotentWorker
worker_resource_boundary :cpu
data_consistency :delayed
- # rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id)
- pipeline = Ci::Pipeline.find_by(id: pipeline_id)
+ pipeline = Ci::Pipeline.find_by_id(pipeline_id)
return unless pipeline
Ci::Pipelines::HookService.new(pipeline).execute
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/pipeline_metrics_worker.rb b/app/workers/pipeline_metrics_worker.rb
index c2580c3d48b..4e98c7268ac 100644
--- a/app/workers/pipeline_metrics_worker.rb
+++ b/app/workers/pipeline_metrics_worker.rb
@@ -10,14 +10,12 @@ class PipelineMetricsWorker # rubocop:disable Scalability/IdempotentWorker
urgency :high
- # rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id)
- Ci::Pipeline.find_by(id: pipeline_id).try do |pipeline|
+ Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
update_metrics_for_active_pipeline(pipeline) if pipeline.active?
update_metrics_for_succeeded_pipeline(pipeline) if pipeline.success?
end
end
- # rubocop: enable CodeReuse/ActiveRecord
private
@@ -29,11 +27,9 @@ class PipelineMetricsWorker # rubocop:disable Scalability/IdempotentWorker
metrics(pipeline).update_all(latest_build_started_at: pipeline.started_at, latest_build_finished_at: pipeline.finished_at, pipeline_id: pipeline.id)
end
- # rubocop: disable CodeReuse/ActiveRecord
def metrics(pipeline)
- MergeRequest::Metrics.where(merge_request_id: merge_requests(pipeline))
+ MergeRequest::Metrics.where(merge_request_id: merge_requests(pipeline)) # rubocop: disable CodeReuse/ActiveRecord
end
- # rubocop: enable CodeReuse/ActiveRecord
def merge_requests(pipeline)
pipeline.merge_requests_as_head_pipeline.map(&:id)
diff --git a/app/workers/pipeline_process_worker.rb b/app/workers/pipeline_process_worker.rb
index 9370b361068..b4712aaeafb 100644
--- a/app/workers/pipeline_process_worker.rb
+++ b/app/workers/pipeline_process_worker.rb
@@ -16,13 +16,11 @@ class PipelineProcessWorker
idempotent!
deduplicate :until_executing
- # rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id)
- Ci::Pipeline.find_by(id: pipeline_id).try do |pipeline|
+ Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
Ci::ProcessPipelineService
.new(pipeline)
.execute
end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 7d0322361b8..45af15216fc 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -128,7 +128,6 @@ class PostReceive
end
def after_project_changes_hooks(project, user, refs, changes)
- experiment(:empty_repo_upload, project: project).track_initial_write
repository_update_hook_data = Gitlab::DataBuilder::Repository.update(project, user, changes, refs)
SystemHooksService.new.execute_hooks(repository_update_hook_data, :repository_update_hooks)
Gitlab::UsageDataCounters::SourceCodeCounter.count(:pushes)
diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb
index 328fdc4717c..0e90b41e28d 100644
--- a/app/workers/project_cache_worker.rb
+++ b/app/workers/project_cache_worker.rb
@@ -23,9 +23,8 @@ class ProjectCacheWorker
# refresh, if empty all columns will be refreshed
# refresh_statistics - A boolean that determines whether project statistics should
# be updated.
- # rubocop: disable CodeReuse/ActiveRecord
def perform(project_id, files = [], statistics = [], refresh_statistics = true)
- project = Project.find_by(id: project_id)
+ project = Project.find_by_id(project_id)
return unless project
@@ -37,7 +36,6 @@ class ProjectCacheWorker
project.cleanup
end
- # rubocop: enable CodeReuse/ActiveRecord
# NOTE: triggering both an immediate update and one in 15 minutes if we
# successfully obtain the lease. That way, we only need to wait for the
diff --git a/app/workers/propagate_service_template_worker.rb b/app/workers/propagate_service_template_worker.rb
index 6b8382ae433..908f867279f 100644
--- a/app/workers/propagate_service_template_worker.rb
+++ b/app/workers/propagate_service_template_worker.rb
@@ -13,13 +13,11 @@ class PropagateServiceTemplateWorker # rubocop:disable Scalability/IdempotentWor
LEASE_TIMEOUT = 4.hours.to_i
- # rubocop: disable CodeReuse/ActiveRecord
def perform(template_id)
return unless try_obtain_lease_for(template_id)
- Admin::PropagateServiceTemplate.propagate(Integration.find_by(id: template_id))
+ Admin::PropagateServiceTemplate.propagate(Integration.find_by_id(template_id))
end
- # rubocop: enable CodeReuse/ActiveRecord
private
diff --git a/app/workers/run_pipeline_schedule_worker.rb b/app/workers/run_pipeline_schedule_worker.rb
index 12042ebc4f0..f08d8231e43 100644
--- a/app/workers/run_pipeline_schedule_worker.rb
+++ b/app/workers/run_pipeline_schedule_worker.rb
@@ -11,16 +11,14 @@ class RunPipelineScheduleWorker # rubocop:disable Scalability/IdempotentWorker
queue_namespace :pipeline_creation
feature_category :continuous_integration
- # rubocop: disable CodeReuse/ActiveRecord
def perform(schedule_id, user_id)
- schedule = Ci::PipelineSchedule.find_by(id: schedule_id)
- user = User.find_by(id: user_id)
+ schedule = Ci::PipelineSchedule.find_by_id(schedule_id)
+ user = User.find_by_id(user_id)
return unless schedule && user
run_pipeline_schedule(schedule, user)
end
- # rubocop: enable CodeReuse/ActiveRecord
def run_pipeline_schedule(schedule, user)
Ci::CreatePipelineService.new(schedule.project,
diff --git a/app/workers/ssh_keys/expired_notification_worker.rb b/app/workers/ssh_keys/expired_notification_worker.rb
index d8553b5a9a2..dc1efce51ce 100644
--- a/app/workers/ssh_keys/expired_notification_worker.rb
+++ b/app/workers/ssh_keys/expired_notification_worker.rb
@@ -29,7 +29,7 @@ module SshKeys
)
])
- scope = Key.expired_and_not_notified.order(order)
+ scope = Key.expired_today_and_not_notified.order(order)
iterator = Gitlab::Pagination::Keyset::Iterator.new(scope: scope, use_union_optimization: true)
iterator.each_batch(of: BATCH_SIZE) do |relation|
@@ -37,7 +37,7 @@ module SshKeys
users.each do |user|
with_context(user: user) do
- Keys::ExpiryNotificationService.new(user, { keys: user.expired_and_unnotified_keys, expiring_soon: false }).execute
+ Keys::ExpiryNotificationService.new(user, { keys: user.expired_today_and_unnotified_keys, expiring_soon: false }).execute
end
end
end
diff --git a/app/workers/tasks_to_be_done/create_worker.rb b/app/workers/tasks_to_be_done/create_worker.rb
new file mode 100644
index 00000000000..0953f190fd0
--- /dev/null
+++ b/app/workers/tasks_to_be_done/create_worker.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module TasksToBeDone
+ class CreateWorker
+ include ApplicationWorker
+
+ data_consistency :always
+ idempotent!
+ feature_category :onboarding
+ urgency :low
+ worker_resource_boundary :cpu
+
+ def perform(member_task_id, current_user_id, assignee_ids = [])
+ member_task = MemberTask.find(member_task_id)
+ current_user = User.find(current_user_id)
+ project = member_task.project
+
+ member_task.tasks_to_be_done.each do |task|
+ service_class(task)
+ .new(project: project, current_user: current_user, assignee_ids: assignee_ids)
+ .execute
+ end
+ end
+
+ private
+
+ def service_class(task)
+ "TasksToBeDone::Create#{task.to_s.camelize}TaskService".constantize
+ end
+ end
+end
diff --git a/app/workers/update_highest_role_worker.rb b/app/workers/update_highest_role_worker.rb
index d5df46c172b..064b8203d4d 100644
--- a/app/workers/update_highest_role_worker.rb
+++ b/app/workers/update_highest_role_worker.rb
@@ -13,17 +13,15 @@ class UpdateHighestRoleWorker
idempotent!
- # rubocop: disable CodeReuse/ActiveRecord
def perform(user_id)
- user = User.find_by(id: user_id)
+ user = User.find_by_id(user_id)
return unless user.present?
if user.active? && user.human? && !user.internal?
Users::UpdateHighestMemberRoleService.new(user).execute
else
- UserHighestRole.where(user_id: user_id).delete_all
+ UserHighestRole.where(user_id: user_id).delete_all # rubocop: disable CodeReuse/ActiveRecord
end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/update_merge_requests_worker.rb b/app/workers/update_merge_requests_worker.rb
index 421a6e47425..5c96257cb63 100644
--- a/app/workers/update_merge_requests_worker.rb
+++ b/app/workers/update_merge_requests_worker.rb
@@ -13,15 +13,13 @@ class UpdateMergeRequestsWorker # rubocop:disable Scalability/IdempotentWorker
weight 3
loggable_arguments 2, 3, 4
- # rubocop: disable CodeReuse/ActiveRecord
def perform(project_id, user_id, oldrev, newrev, ref)
- project = Project.find_by(id: project_id)
+ project = Project.find_by_id(project_id)
return unless project
- user = User.find_by(id: user_id)
+ user = User.find_by_id(user_id)
return unless user
MergeRequests::RefreshService.new(project: project, current_user: user).execute(oldrev, newrev, ref)
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/update_project_statistics_worker.rb b/app/workers/update_project_statistics_worker.rb
index 4a32753ac70..45a6cc8f476 100644
--- a/app/workers/update_project_statistics_worker.rb
+++ b/app/workers/update_project_statistics_worker.rb
@@ -13,11 +13,9 @@ class UpdateProjectStatisticsWorker # rubocop:disable Scalability/IdempotentWork
# project_id - The ID of the project for which to flush the cache.
# statistics - An Array containing columns from ProjectStatistics to
# refresh, if empty all columns will be refreshed
- # rubocop: disable CodeReuse/ActiveRecord
def perform(project_id, statistics = [])
- project = Project.find_by(id: project_id)
+ project = Project.find_by_id(project_id)
Projects::UpdateStatisticsService.new(project, nil, statistics: statistics).execute
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/bin/background_jobs b/bin/background_jobs
index f9b42b97e06..d8929881f12 100755
--- a/bin/background_jobs
+++ b/bin/background_jobs
@@ -8,6 +8,8 @@ sidekiq_pidfile="$app_root/tmp/pids/sidekiq-cluster.pid"
sidekiq_logfile="$app_root/log/sidekiq.log"
gitlab_user=$(ls -l config.ru | awk '{print $3}')
+trap cleanup EXIT
+
warn()
{
echo "$@" 1>&2
@@ -59,6 +61,11 @@ start_sidekiq()
${cmd} bin/sidekiq-cluster "${processes_args[@]}" -P $sidekiq_pidfile -e $RAILS_ENV "$@" 2>&1 | tee -a $sidekiq_logfile
}
+cleanup()
+{
+ stop
+}
+
action="$1"
shift
diff --git a/bin/pngquant b/bin/pngquant
index 8434e9d3ec9..a614814a8a3 100755
--- a/bin/pngquant
+++ b/bin/pngquant
@@ -5,7 +5,7 @@ require 'rails'
require 'png_quantizator'
require 'parallel'
require 'rainbow/ext/string'
-require_relative '../tooling/lib/tooling/images'
+require_relative '../tooling/lib/tooling/image'
return if Rails.env.production?
diff --git a/bin/sidekiq-cluster b/bin/sidekiq-cluster
index 47f8e82d228..db7833acdc9 100755
--- a/bin/sidekiq-cluster
+++ b/bin/sidekiq-cluster
@@ -1,13 +1,7 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
-require 'optparse'
-require_relative '../lib/gitlab'
-require_relative '../lib/gitlab/utils'
-require_relative '../lib/gitlab/sidekiq_config/cli_methods'
-require_relative '../lib/gitlab/sidekiq_config/worker_matcher'
-require_relative '../lib/gitlab/sidekiq_cluster'
-require_relative '../lib/gitlab/sidekiq_cluster/cli'
+require_relative '../sidekiq_cluster/cli'
Thread.abort_on_exception = true
diff --git a/config/application.rb b/config/application.rb
index dba9550a3dc..dde1eae30e7 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -16,6 +16,38 @@ Bundler.require(*Rails.groups)
module Gitlab
class Application < Rails::Application
+ config.load_defaults 6.1
+
+ # This section contains configuration from Rails upgrades to override the new defaults so that we
+ # keep existing behavior.
+ #
+ # For boolean values, the new default is the opposite of the value being set in this section.
+ # For other types, the new default is noted in the comments. These are also documented in
+ # https://guides.rubyonrails.org/configuring.html#results-of-config-load-defaults
+ #
+ # To switch a setting to the new default value, we just need to delete the specific line here.
+
+ # Rails 6.1
+ config.action_dispatch.cookies_same_site_protection = nil # New default is :lax
+ ActiveSupport.utc_to_local_returns_utc_offset_times = false
+ config.action_controller.urlsafe_csrf_tokens = false
+ config.action_view.preload_links_header = false
+
+ # Rails 5.2
+ config.action_dispatch.use_authenticated_cookie_encryption = false
+ config.active_support.use_authenticated_message_encryption = false
+ config.active_support.hash_digest_class = ::Digest::MD5 # New default is ::Digest::SHA1
+ config.action_controller.default_protect_from_forgery = false
+ config.action_view.form_with_generates_ids = false
+
+ # Rails 5.1
+ config.assets.unknown_asset_fallback = true
+
+ # Rails 5.0
+ config.action_controller.per_form_csrf_tokens = false
+ config.action_controller.forgery_protection_origin_check = false
+ ActiveSupport.to_time_preserves_timezone = false
+
require_dependency Rails.root.join('lib/gitlab')
require_dependency Rails.root.join('lib/gitlab/utils')
require_dependency Rails.root.join('lib/gitlab/action_cable/config')
@@ -28,6 +60,7 @@ module Gitlab
require_dependency Rails.root.join('lib/gitlab/redis/sessions')
require_dependency Rails.root.join('lib/gitlab/current_settings')
require_dependency Rails.root.join('lib/gitlab/middleware/read_only')
+ require_dependency Rails.root.join('lib/gitlab/middleware/compressed_json')
require_dependency Rails.root.join('lib/gitlab/middleware/basic_health_check')
require_dependency Rails.root.join('lib/gitlab/middleware/same_site_cookies')
require_dependency Rails.root.join('lib/gitlab/middleware/handle_ip_spoof_attack_error')
@@ -36,8 +69,6 @@ module Gitlab
require_dependency Rails.root.join('lib/gitlab/runtime')
require_dependency Rails.root.join('lib/gitlab/patch/legacy_database_config')
- config.autoloader = :zeitwerk
-
# To be removed in 15.0
# This preload is needed to convert legacy `database.yml`
# from `production: adapter: postgresql`
@@ -189,17 +220,18 @@ module Gitlab
# regardless if schema_search_path is set, or not.
config.active_record.dump_schemas = :all
- # Use new connection handling so that we can use Rails 6.1+ multiple
- # database support.
- config.active_record.legacy_connection_handling = false
-
- config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob"
+ # Override default Active Record settings
+ # We cannot do this in an initializer because some models are already loaded by then
+ config.active_record.cache_versioning = false
+ config.active_record.collection_cache_versioning = false
+ config.active_record.has_many_inversing = false
+ config.active_record.belongs_to_required_by_default = false
# Enable the asset pipeline
config.assets.enabled = true
# Support legacy unicode file named img emojis, `1F939.png`
- config.assets.paths << Gemojione.images_path
+ config.assets.paths << TanukiEmoji.images_path
config.assets.paths << "#{config.root}/vendor/assets/fonts"
config.assets.precompile << "application_utilities.css"
@@ -222,7 +254,7 @@ module Gitlab
config.assets.precompile << "page_bundles/build.css"
config.assets.precompile << "page_bundles/ci_status.css"
config.assets.precompile << "page_bundles/cycle_analytics.css"
- config.assets.precompile << "page_bundles/dev_ops_report.css"
+ config.assets.precompile << "page_bundles/dev_ops_reports.css"
config.assets.precompile << "page_bundles/environments.css"
config.assets.precompile << "page_bundles/epics.css"
config.assets.precompile << "page_bundles/error_tracking_details.css"
@@ -255,6 +287,7 @@ module Gitlab
config.assets.precompile << "page_bundles/security_discover.css"
config.assets.precompile << "page_bundles/signup.css"
config.assets.precompile << "page_bundles/terminal.css"
+ config.assets.precompile << "page_bundles/terms.css"
config.assets.precompile << "page_bundles/todos.css"
config.assets.precompile << "page_bundles/wiki.css"
config.assets.precompile << "page_bundles/xterm.css"
@@ -318,6 +351,8 @@ module Gitlab
config.middleware.insert_after Rack::Sendfile, ::Gitlab::Middleware::RackMultipartTempfileFactory
+ config.middleware.insert_before Rack::Runtime, ::Gitlab::Middleware::CompressedJson
+
# Allow access to GitLab API from other domains
config.middleware.insert_before Warden::Manager, Rack::Cors do
headers_to_expose = %w[Link X-Total X-Total-Pages X-Per-Page X-Page X-Next-Page X-Prev-Page X-Gitlab-Blob-Id X-Gitlab-Commit-Id X-Gitlab-Content-Sha256 X-Gitlab-Encoding X-Gitlab-File-Name X-Gitlab-File-Path X-Gitlab-Last-Commit-Id X-Gitlab-Ref X-Gitlab-Size]
@@ -376,6 +411,7 @@ module Gitlab
config.cache_store = :redis_cache_store, Gitlab::Redis::Cache.active_support_config
config.active_job.queue_adapter = :sidekiq
+ config.action_mailer.deliver_later_queue_name = :mailers
# This is needed for gitlab-shell
ENV['GITLAB_PATH_OUTSIDE_HOOK'] = ENV['PATH']
diff --git a/config/boot.rb b/config/boot.rb
index afa3c04c3c7..ec9470bc506 100644
--- a/config/boot.rb
+++ b/config/boot.rb
@@ -1,4 +1,6 @@
# frozen_string_literal: true
require_relative 'bundler_setup'
-require 'bootsnap/setup' if ENV['RAILS_ENV'] != 'production' || %w(1 yes true).include?(ENV['ENABLE_BOOTSNAP'])
+
+enable_bootsnap_default_value = ENV['RAILS_ENV'] != 'production' ? '1' : '0'
+require 'bootsnap/setup' if %w(1 yes true).include?(ENV.fetch('ENABLE_BOOTSNAP', enable_bootsnap_default_value))
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index 573286a4c11..894e60b61f2 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -37,12 +37,6 @@
:versions: []
:when: 2016-05-02 05:31:54.498490000 Z
- - :permit
- - LGPL
- - :who: Connor Shea
- :why: http://www.gnu.org/licenses/license-list.html#LGPLv2.1
- :versions: []
- :when: 2016-05-02 05:32:48.645841000 Z
-- - :permit
- ISC
- :who: Connor Shea
:why: http://www.gnu.org/licenses/license-list.html#ISC
@@ -55,24 +49,12 @@
:versions: []
:when: 2016-05-02 05:44:38.246021000 Z
- - :permit
- - LGPL-2.1+
- - :who: Connor Shea
- :why: Equivalent to LGPL.
- :versions: []
- :when: 2016-05-02 05:52:56.303239000 Z
-- - :permit
- BSD
- :who: Connor Shea
:why: https://opensource.org/licenses/BSD-2-Clause
:versions: []
:when: 2016-05-02 05:55:09.796363000 Z
- - :permit
- - LGPLv2+
- - :who: Stan Hu
- :why: Equivalent to LGPLv2
- :versions: []
- :when: 2016-06-07 17:14:10.907682000 Z
-- - :permit
- Artistic 2.0
- :who: Josh Frye
:why: Disk/mount information display on Admin pages
@@ -211,14 +193,19 @@
:why: https://github.com/pieroxy/lz-string/blob/master/LICENSE.txt
:versions: []
:when: 2018-08-03 08:22:44.973457000 Z
-- - :license
+- - :add_package
- smooshpack
- - LGPL
- - :who: Phil Hughes
- :why: https://github.com/CompuIves/codesandbox-client/blob/master/packages/sandpack/LICENSE.md
+ - 0.0.62
+ - &1
+ :who: Phil Hughes
+ :why: https://github.com/codesandbox/codesandbox-client/blob/006adee03295b5d42bb311a526774747758fd1a0/standalone-packages/sandpack/LICENSE.md
:versions: []
:when: 2018-08-03 08:24:29.578991000 Z
- - :license
+ - smooshpack
+ - LGPL
+ - *1
+- - :license
- codesandbox-import-util-types
- LGPL
- :who: Phil Hughes
@@ -317,3 +304,61 @@
:why: https://github.com/xijo/reverse_markdown/blob/master/LICENSE
:versions: []
:when: 2021-02-03 08:47:28.792907000 Z
+- - :approve
+ - sidekiq
+ - :who: Sean McGivern
+ :why: https://gitlab.com/gitlab-com/legal-and-compliance/-/issues/672
+ :versions: []
+ :when: 2021-11-08 13:53:54.127540759 Z
+- - :approve
+ - gitlab-sidekiq-fetcher
+ - :who: Sean McGivern
+ :why: https://gitlab.com/gitlab-com/legal-and-compliance/-/issues/672
+ :versions: []
+ :when: 2021-11-08 13:54:27.222104249 Z
+- - :approve
+ - device_detector
+ - :who: Sean McGivern
+ :why: https://gitlab.com/gitlab-com/legal-and-compliance/-/issues/672
+ :versions: []
+ :when: 2021-11-08 13:54:52.533334287 Z
+- - :approve
+ - gpgme
+ - :who: Sean McGivern
+ :why: https://gitlab.com/gitlab-com/legal-and-compliance/-/issues/672
+ :versions: []
+ :when: 2021-11-08 13:54:43.878212822 Z
+- - :approve
+ - rchardet
+ - :who: Sean McGivern
+ :why: https://gitlab.com/gitlab-com/legal-and-compliance/-/issues/672
+ :versions: []
+ :when: 2021-11-08 13:54:35.324449740 Z
+- - :approve
+ - timfel-krb5-auth
+ - :who: Sean McGivern
+ :why: https://gitlab.com/gitlab-com/legal-and-compliance/-/issues/672
+ :versions: []
+ :when: 2021-11-08 13:55:10.859429290 Z
+- - :approve
+ - codesandbox-import-util-types
+ - :who: Sean McGivern
+ :why: https://gitlab.com/gitlab-com/legal-and-compliance/-/issues/672
+ :versions: []
+ :when: 2021-11-08 14:03:20.304435279 Z
+- - :approve
+ - codesandbox-import-utils
+ - :who: Sean McGivern
+ :why: https://gitlab.com/gitlab-com/legal-and-compliance/-/issues/672
+ :versions: []
+ :when: 2021-11-08 14:03:25.577163700 Z
+- - :approve
+ - smooshpack
+ - &2
+ :who: Sean McGivern
+ :why: https://gitlab.com/gitlab-com/legal-and-compliance/-/issues/672
+ :versions: []
+ :when: 2021-11-10 10:09:31.584355110 Z
+- - :approve
+ - 0.0.62
+ - *2
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 92de88394c6..076957f3057 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -42,8 +42,6 @@ Rails.application.configure do
# Raises helpful error messages.
config.assets.raise_runtime_errors = true
- # For having correct urls in mails
- config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
# Open sent mails in browser
config.action_mailer.delivery_method = :letter_opener_web
# Log mail delivery errors
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 9fa8a1b762c..2935e0c7636 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -49,7 +49,7 @@ Rails.application.configure do
# Print deprecation notices to the stderr
config.active_support.deprecation = :stderr
- config.eager_load = Gitlab::Utils.to_boolean(ENV['GITLAB_TEST_EAGER_LOAD'], default: true)
+ config.eager_load = Gitlab::Utils.to_boolean(ENV['GITLAB_TEST_EAGER_LOAD'], default: ENV['CI'].present?)
config.cache_store = :null_store
@@ -59,8 +59,4 @@ Rails.application.configure do
config.logger = ActiveSupport::TaggedLogging.new(Logger.new(nil))
config.log_level = :fatal
end
-
- # Mount the ActionCable Engine in-app so that we don't have to spawn another Puma
- # process for feature specs
- ENV['ACTION_CABLE_IN_APP'] = 'true'
end
diff --git a/config/feature_categories.yml b/config/feature_categories.yml
index e61048a6427..04804e373ab 100644
--- a/config/feature_categories.yml
+++ b/config/feature_categories.yml
@@ -15,7 +15,6 @@
- authentication_and_authorization
- auto_devops
- backup_restore
-- boards
- build_artifacts
- chatops
- cloud_native_installation
@@ -44,7 +43,6 @@
- dynamic_application_security_testing
- editor_extension
- environment_management
-- epics
- error_tracking
- experimentation_activation
- experimentation_adoption
@@ -59,6 +57,7 @@
- gitaly
- gitlab_docs
- global_search
+- google_cloud
- helm_chart_registry
- horse
- importers
@@ -69,7 +68,6 @@
- intel_code_security
- interactive_application_security_testing
- internationalization
-- issue_tracking
- jenkins_importer
- kubernetes_management
- license
@@ -91,16 +89,17 @@
- pipeline_abuse_prevention
- pipeline_authoring
- planning_analytics
+- portfolio_management
- privacy_control_center
- product_analytics
- projects
- purchase
- quality_management
+- redis
- release_evidence
- release_orchestration
- requirements_management
- review_apps
-- roadmaps
- runbooks
- runner
- scalability
@@ -118,7 +117,7 @@
- static_site_editor
- subgroups
- synthetic_monitoring
-- time_tracking
+- team_planning
- tracing
- usability_testing
- usage_ping
diff --git a/config/feature_flags/development/add_actor_based_user_to_snowplow_tracking.yml b/config/feature_flags/development/add_actor_based_user_to_snowplow_tracking.yml
deleted file mode 100644
index 9dc20148d56..00000000000
--- a/config/feature_flags/development/add_actor_based_user_to_snowplow_tracking.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: add_actor_based_user_to_snowplow_tracking
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71353
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338150
-milestone: '14.4'
-type: development
-group: group::product intelligence
-default_enabled: false
diff --git a/config/feature_flags/development/add_namespace_and_project_to_snowplow_tracking.yml b/config/feature_flags/development/add_namespace_and_project_to_snowplow_tracking.yml
deleted file mode 100644
index ebffae2a446..00000000000
--- a/config/feature_flags/development/add_namespace_and_project_to_snowplow_tracking.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: add_namespace_and_project_to_snowplow_tracking
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68277
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338670
-milestone: '14.3'
-type: development
-group: group::product intelligence
-default_enabled: false
diff --git a/config/feature_flags/development/additional_snowplow_tracking.yml b/config/feature_flags/development/additional_snowplow_tracking.yml
deleted file mode 100644
index 0d021a2f8b0..00000000000
--- a/config/feature_flags/development/additional_snowplow_tracking.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: additional_snowplow_tracking
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/12088
-rollout_issue_url:
-milestone: '11.11'
-type: development
-group: group::product intelligence
-default_enabled: false
diff --git a/config/feature_flags/development/admin_deploy_keys_vue.yml b/config/feature_flags/development/admin_deploy_keys_vue.yml
new file mode 100644
index 00000000000..c57ed728ffb
--- /dev/null
+++ b/config/feature_flags/development/admin_deploy_keys_vue.yml
@@ -0,0 +1,8 @@
+---
+name: admin_deploy_keys_vue
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73580
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344855
+milestone: '14.5'
+type: development
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/development/api_v3_commits_skip_diff_files.yml b/config/feature_flags/development/api_v3_commits_skip_diff_files.yml
new file mode 100644
index 00000000000..a3a953e983c
--- /dev/null
+++ b/config/feature_flags/development/api_v3_commits_skip_diff_files.yml
@@ -0,0 +1,8 @@
+---
+name: api_v3_commits_skip_diff_files
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67647
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344617
+milestone: '14.5'
+type: development
+group: group::integrations
+default_enabled: true
diff --git a/config/feature_flags/development/atomic_sidekiq_scheduler.yml b/config/feature_flags/development/atomic_sidekiq_scheduler.yml
new file mode 100644
index 00000000000..ab516f61144
--- /dev/null
+++ b/config/feature_flags/development/atomic_sidekiq_scheduler.yml
@@ -0,0 +1,8 @@
+---
+name: atomic_sidekiq_scheduler
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72380
+rollout_issue_url:
+milestone: '14.5'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/between_commits_via_list_commits.yml b/config/feature_flags/development/between_commits_via_list_commits.yml
new file mode 100644
index 00000000000..f048fd4e1b6
--- /dev/null
+++ b/config/feature_flags/development/between_commits_via_list_commits.yml
@@ -0,0 +1,8 @@
+---
+name: between_commits_via_list_commits
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74273
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345458
+milestone: '14.5'
+type: development
+group: group::gitaly
+default_enabled: false
diff --git a/config/feature_flags/development/block_anonymous_global_searches.yml b/config/feature_flags/development/block_anonymous_global_searches.yml
deleted file mode 100644
index ee72f1ac60a..00000000000
--- a/config/feature_flags/development/block_anonymous_global_searches.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: block_anonymous_global_searches
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41041
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/244276
-milestone: '13.4'
-type: development
-group: group::global search
-default_enabled: false
diff --git a/config/feature_flags/development/bootstrap_confirmation_modals.yml b/config/feature_flags/development/bootstrap_confirmation_modals.yml
new file mode 100644
index 00000000000..e67fd03fea6
--- /dev/null
+++ b/config/feature_flags/development/bootstrap_confirmation_modals.yml
@@ -0,0 +1,8 @@
+---
+name: bootstrap_confirmation_modals
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73167
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344658
+milestone: '14.5'
+type: development
+group: group::foundations
+default_enabled: false
diff --git a/config/feature_flags/development/broadcast_issue_updates.yml b/config/feature_flags/development/broadcast_issue_updates.yml
index b7c6ccf2353..c38263528a9 100644
--- a/config/feature_flags/development/broadcast_issue_updates.yml
+++ b/config/feature_flags/development/broadcast_issue_updates.yml
@@ -1,8 +1,8 @@
---
name: broadcast_issue_updates
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30732
-rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/1210
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/3413
milestone: '13.0'
type: development
group: group::project management
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/cached_issues_state_count.yml b/config/feature_flags/development/cached_issues_state_count.yml
deleted file mode 100644
index 34d96b601d9..00000000000
--- a/config/feature_flags/development/cached_issues_state_count.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: cached_issues_state_count
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67418
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/333089
-milestone: '14.3'
-type: development
-group: group::product planning
-default_enabled: false
diff --git a/config/feature_flags/development/cached_loading_hints.yml b/config/feature_flags/development/cached_loading_hints.yml
deleted file mode 100644
index ba4eaece55a..00000000000
--- a/config/feature_flags/development/cached_loading_hints.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: cached_loading_hints
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61609
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330802
-milestone: '13.12'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/ci_create_external_pr_pipeline_async.yml b/config/feature_flags/development/ci_create_external_pr_pipeline_async.yml
deleted file mode 100644
index 48c7dbcf740..00000000000
--- a/config/feature_flags/development/ci_create_external_pr_pipeline_async.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_create_external_pr_pipeline_async
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68567
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338908
-milestone: '14.3'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml b/config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml
new file mode 100644
index 00000000000..b064e6bf09f
--- /dev/null
+++ b/config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml
@@ -0,0 +1,8 @@
+---
+name: ci_destroy_unlocked_job_artifacts
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72406
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338165
+milestone: '14.5'
+type: development
+group: group::testing
+default_enabled: false
diff --git a/config/feature_flags/development/ci_new_artifact_file_reader.yml b/config/feature_flags/development/ci_new_artifact_file_reader.yml
deleted file mode 100644
index d475f3f370d..00000000000
--- a/config/feature_flags/development/ci_new_artifact_file_reader.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_new_artifact_file_reader
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46552
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/273755
-milestone: '13.6'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/ci_predefined_vars_in_builder.yml b/config/feature_flags/development/ci_predefined_vars_in_builder.yml
new file mode 100644
index 00000000000..5aacf6ee681
--- /dev/null
+++ b/config/feature_flags/development/ci_predefined_vars_in_builder.yml
@@ -0,0 +1,8 @@
+---
+name: ci_predefined_vars_in_builder
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72348
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/231300
+milestone: '14.4'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/ci_store_trace_outside_transaction.yml b/config/feature_flags/development/ci_store_trace_outside_transaction.yml
new file mode 100644
index 00000000000..89b135850fe
--- /dev/null
+++ b/config/feature_flags/development/ci_store_trace_outside_transaction.yml
@@ -0,0 +1,8 @@
+---
+name: ci_store_trace_outside_transaction
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66203
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/336280
+milestone: '15.4'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/ci_synchronous_artifact_parsing.yml b/config/feature_flags/development/ci_synchronous_artifact_parsing.yml
deleted file mode 100644
index ab3a35e409b..00000000000
--- a/config/feature_flags/development/ci_synchronous_artifact_parsing.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_synchronous_artifact_parsing
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26247
-rollout_issue_url:
-milestone: '12.9'
-type: development
-group: group::release
-default_enabled: true
diff --git a/config/feature_flags/development/ci_update_unlocked_job_artifacts.yml b/config/feature_flags/development/ci_update_unlocked_job_artifacts.yml
new file mode 100644
index 00000000000..9157928f352
--- /dev/null
+++ b/config/feature_flags/development/ci_update_unlocked_job_artifacts.yml
@@ -0,0 +1,8 @@
+---
+name: ci_update_unlocked_job_artifacts
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70235
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343465
+milestone: '14.5'
+type: development
+group: group::testing
+default_enabled: false
diff --git a/config/feature_flags/development/ci_validate_job_length.yml b/config/feature_flags/development/ci_validate_job_length.yml
new file mode 100644
index 00000000000..5e29d3c1435
--- /dev/null
+++ b/config/feature_flags/development/ci_validate_job_length.yml
@@ -0,0 +1,8 @@
+---
+name: ci_validate_job_length
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73599
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344665
+milestone: '14.5'
+type: development
+group: group::pipeline authoring
+default_enabled: true
diff --git a/config/feature_flags/development/cluster_vulnerabilities.yml b/config/feature_flags/development/cluster_vulnerabilities.yml
new file mode 100644
index 00000000000..919cdc1d009
--- /dev/null
+++ b/config/feature_flags/development/cluster_vulnerabilities.yml
@@ -0,0 +1,8 @@
+---
+name: cluster_vulnerabilities
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73321
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343917
+milestone: '14.5'
+type: development
+group: group::container security
+default_enabled: false
diff --git a/config/feature_flags/development/configure_iac_scanning_via_mr.yml b/config/feature_flags/development/configure_iac_scanning_via_mr.yml
new file mode 100644
index 00000000000..cef22644b8f
--- /dev/null
+++ b/config/feature_flags/development/configure_iac_scanning_via_mr.yml
@@ -0,0 +1,8 @@
+---
+name: configure_iac_scanning_via_mr
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73155
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343966
+milestone: '14.5'
+type: development
+group: group::static analysis
+default_enabled: true
diff --git a/config/feature_flags/development/configure_sentry_in_application_settings.yml b/config/feature_flags/development/configure_sentry_in_application_settings.yml
new file mode 100644
index 00000000000..82b2261994b
--- /dev/null
+++ b/config/feature_flags/development/configure_sentry_in_application_settings.yml
@@ -0,0 +1,8 @@
+---
+name: configure_sentry_in_application_settings
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73381
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344832
+milestone: '14.5'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/container_registry_expiration_policies_caching.yml b/config/feature_flags/development/container_registry_expiration_policies_caching.yml
deleted file mode 100644
index 6e8b0efe94d..00000000000
--- a/config/feature_flags/development/container_registry_expiration_policies_caching.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: container_registry_expiration_policies_caching
-introduced_by_url:
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340606
-milestone: '14.3'
-type: development
-group: group::package
-default_enabled: false
diff --git a/config/feature_flags/development/content_editor_block_tables.yml b/config/feature_flags/development/content_editor_block_tables.yml
deleted file mode 100644
index 176422bbc92..00000000000
--- a/config/feature_flags/development/content_editor_block_tables.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: content_editor_block_tables
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66187
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338937
-milestone: '14.3'
-type: development
-group: group::editor
-default_enabled: false
diff --git a/config/feature_flags/development/create_project_namespace_on_project_create.yml b/config/feature_flags/development/create_project_namespace_on_project_create.yml
new file mode 100644
index 00000000000..3fbf929ca2e
--- /dev/null
+++ b/config/feature_flags/development/create_project_namespace_on_project_create.yml
@@ -0,0 +1,8 @@
+---
+name: create_project_namespace_on_project_create
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70972
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344954
+milestone: '14.5'
+type: development
+group: group::workspace
+default_enabled: false
diff --git a/config/feature_flags/development/dast_view_scans.yml b/config/feature_flags/development/dast_view_scans.yml
index 39c14097b60..736fcb01091 100644
--- a/config/feature_flags/development/dast_view_scans.yml
+++ b/config/feature_flags/development/dast_view_scans.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340388
milestone: '14.3'
type: development
group: group::dynamic analysis
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/decomposed_ci_query_in_pipelines_for_merge_request_finder.yml b/config/feature_flags/development/decomposed_ci_query_in_pipelines_for_merge_request_finder.yml
deleted file mode 100644
index 235b37dfb1d..00000000000
--- a/config/feature_flags/development/decomposed_ci_query_in_pipelines_for_merge_request_finder.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: decomposed_ci_query_in_pipelines_for_merge_request_finder
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68549
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341341
-milestone: '14.4'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/dependency_proxy_manifest_workhorse.yml b/config/feature_flags/development/dependency_proxy_manifest_workhorse.yml
new file mode 100644
index 00000000000..f1e3be78da8
--- /dev/null
+++ b/config/feature_flags/development/dependency_proxy_manifest_workhorse.yml
@@ -0,0 +1,8 @@
+---
+name: dependency_proxy_manifest_workhorse
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73033
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344216
+milestone: '14.4'
+type: development
+group: group::package
+default_enabled: true
diff --git a/config/feature_flags/development/dependency_proxy_workhorse.yml b/config/feature_flags/development/dependency_proxy_workhorse.yml
index a3545d32cd5..a14f38fa001 100644
--- a/config/feature_flags/development/dependency_proxy_workhorse.yml
+++ b/config/feature_flags/development/dependency_proxy_workhorse.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339639
milestone: '14.3'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/deployments_archive.yml b/config/feature_flags/development/deployments_archive.yml
new file mode 100644
index 00000000000..ad6b5fb47d9
--- /dev/null
+++ b/config/feature_flags/development/deployments_archive.yml
@@ -0,0 +1,8 @@
+---
+name: deployments_archive
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73628
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345027
+milestone: '14.5'
+type: development
+group: group::release
+default_enabled: false
diff --git a/config/feature_flags/development/detect_cross_database_modification.yml b/config/feature_flags/development/detect_cross_database_modification.yml
new file mode 100644
index 00000000000..7f74e136291
--- /dev/null
+++ b/config/feature_flags/development/detect_cross_database_modification.yml
@@ -0,0 +1,8 @@
+---
+name: detect_cross_database_modification
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73316
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344620
+milestone: '14.5'
+type: development
+group: group::sharding
+default_enabled: false
diff --git a/config/feature_flags/development/display_outdated_line_diff.yml b/config/feature_flags/development/display_outdated_line_diff.yml
new file mode 100644
index 00000000000..6baa258c52b
--- /dev/null
+++ b/config/feature_flags/development/display_outdated_line_diff.yml
@@ -0,0 +1,8 @@
+---
+name: display_outdated_line_diff
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72597
+rollout_issue_url:
+milestone: '14.5'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/environments_by_deployments_finder_exists_optimization.yml b/config/feature_flags/development/environments_by_deployments_finder_exists_optimization.yml
new file mode 100644
index 00000000000..a265d9528f7
--- /dev/null
+++ b/config/feature_flags/development/environments_by_deployments_finder_exists_optimization.yml
@@ -0,0 +1,8 @@
+---
+name: environments_by_deployments_finder_exists_optimization
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72781/
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343544
+milestone: '14.5'
+type: development
+group: group::release
+default_enabled: false
diff --git a/config/feature_flags/development/finding_ci_pipeline_disable_joins.yml b/config/feature_flags/development/finding_ci_pipeline_disable_joins.yml
deleted file mode 100644
index 8987b729cac..00000000000
--- a/config/feature_flags/development/finding_ci_pipeline_disable_joins.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: finding_ci_pipeline_disable_joins
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70216
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338665
-milestone: '14.3'
-type: development
-group: group::threat insights
-default_enabled: true
diff --git a/config/feature_flags/development/github_importer_use_diff_note_with_suggestions.yml b/config/feature_flags/development/github_importer_use_diff_note_with_suggestions.yml
new file mode 100644
index 00000000000..c106d5131ff
--- /dev/null
+++ b/config/feature_flags/development/github_importer_use_diff_note_with_suggestions.yml
@@ -0,0 +1,8 @@
+---
+name: github_importer_use_diff_note_with_suggestions
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71765
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344309
+milestone: '14.5'
+type: development
+group: group::import
+default_enabled: false
diff --git a/config/feature_flags/development/group_authorized_agents.yml b/config/feature_flags/development/group_authorized_agents.yml
deleted file mode 100644
index e1c4620994d..00000000000
--- a/config/feature_flags/development/group_authorized_agents.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: group_authorized_agents
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69047
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340166
-milestone: '14.3'
-type: development
-group: group::configure
-default_enabled: false
diff --git a/config/feature_flags/development/jira_connect_asymmetric_jwt.yml b/config/feature_flags/development/jira_connect_asymmetric_jwt.yml
deleted file mode 100644
index e204a7d6fac..00000000000
--- a/config/feature_flags/development/jira_connect_asymmetric_jwt.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: jira_connect_asymmetric_jwt
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71080
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342808
-milestone: '14.4'
-type: development
-group: group::integrations
-default_enabled: false
diff --git a/config/feature_flags/development/jira_issue_details_edit_labels.yml b/config/feature_flags/development/jira_issue_details_edit_labels.yml
deleted file mode 100644
index c43d01bf969..00000000000
--- a/config/feature_flags/development/jira_issue_details_edit_labels.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: jira_issue_details_edit_labels
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65298
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/335069
-milestone: '14.1'
-type: development
-group: group::integrations
-default_enabled: false
diff --git a/config/feature_flags/development/jira_issue_details_edit_status.yml b/config/feature_flags/development/jira_issue_details_edit_status.yml
deleted file mode 100644
index 311e243c570..00000000000
--- a/config/feature_flags/development/jira_issue_details_edit_status.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: jira_issue_details_edit_status
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60092
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330628
-milestone: '14.1'
-type: development
-group: group::integrations
-default_enabled: false
diff --git a/config/feature_flags/development/jira_use_first_ref_by_oid.yml b/config/feature_flags/development/jira_use_first_ref_by_oid.yml
new file mode 100644
index 00000000000..10e2ad1b8ad
--- /dev/null
+++ b/config/feature_flags/development/jira_use_first_ref_by_oid.yml
@@ -0,0 +1,8 @@
+---
+name: jira_use_first_ref_by_oid
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72739
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343585
+milestone: '14.5'
+type: development
+group: group::integrations
+default_enabled: false
diff --git a/config/feature_flags/development/jupyter_clean_diffs.yml b/config/feature_flags/development/jupyter_clean_diffs.yml
new file mode 100644
index 00000000000..0f3f6fe3057
--- /dev/null
+++ b/config/feature_flags/development/jupyter_clean_diffs.yml
@@ -0,0 +1,8 @@
+---
+name: jupyter_clean_diffs
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71477
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343433
+milestone: '14.5'
+type: development
+group: group::incubation
+default_enabled: true
diff --git a/config/feature_flags/development/linear_application_setting_ancestor_scopes.yml b/config/feature_flags/development/linear_application_setting_ancestor_scopes.yml
deleted file mode 100644
index 18c64df78d7..00000000000
--- a/config/feature_flags/development/linear_application_setting_ancestor_scopes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_application_setting_ancestor_scopes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70579
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341346
-milestone: '14.4'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/linear_ee_group_ancestor_scopes.yml b/config/feature_flags/development/linear_ee_group_ancestor_scopes.yml
deleted file mode 100644
index 46294b0aef0..00000000000
--- a/config/feature_flags/development/linear_ee_group_ancestor_scopes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_ee_group_ancestor_scopes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70708
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341350
-milestone: '14.4'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/linear_group_ancestor_scopes.yml b/config/feature_flags/development/linear_group_ancestor_scopes.yml
deleted file mode 100644
index f23399c1e6f..00000000000
--- a/config/feature_flags/development/linear_group_ancestor_scopes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_group_ancestor_scopes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70495
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341115
-milestone: '14.4'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/linear_group_plans_preloaded_ancestor_scopes.yml b/config/feature_flags/development/linear_group_plans_preloaded_ancestor_scopes.yml
deleted file mode 100644
index d45b8d71a20..00000000000
--- a/config/feature_flags/development/linear_group_plans_preloaded_ancestor_scopes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_group_plans_preloaded_ancestor_scopes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70685
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341349
-milestone: '14.4'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/linear_group_tree_ancestor_scopes.yml b/config/feature_flags/development/linear_group_tree_ancestor_scopes.yml
deleted file mode 100644
index 3a195242fa1..00000000000
--- a/config/feature_flags/development/linear_group_tree_ancestor_scopes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_group_tree_ancestor_scopes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70503
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341117
-milestone: '14.4'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/linear_members_finder_ancestor_scopes.yml b/config/feature_flags/development/linear_members_finder_ancestor_scopes.yml
deleted file mode 100644
index 6bd5e164324..00000000000
--- a/config/feature_flags/development/linear_members_finder_ancestor_scopes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_members_finder_ancestor_scopes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70583
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341347
-milestone: '14.4'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/linear_participants_service_ancestor_scopes.yml b/config/feature_flags/development/linear_participants_service_ancestor_scopes.yml
deleted file mode 100644
index 41b6f3b32d9..00000000000
--- a/config/feature_flags/development/linear_participants_service_ancestor_scopes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_participants_service_ancestor_scopes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70684
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341348
-milestone: '14.4'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/loose_foreign_key_cleanup.yml b/config/feature_flags/development/loose_foreign_key_cleanup.yml
new file mode 100644
index 00000000000..915ed662333
--- /dev/null
+++ b/config/feature_flags/development/loose_foreign_key_cleanup.yml
@@ -0,0 +1,8 @@
+---
+name: loose_foreign_key_cleanup
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69165
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343545
+milestone: '14.4'
+type: development
+group: group::sharding
+default_enabled: true
diff --git a/config/feature_flags/development/managed_alerts_deprecation.yml b/config/feature_flags/development/managed_alerts_deprecation.yml
deleted file mode 100644
index f849aa33141..00000000000
--- a/config/feature_flags/development/managed_alerts_deprecation.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: managed_alerts_deprecation
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62528
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331863
-milestone: '14.0'
-type: development
-group: group::monitor
-default_enabled: true
diff --git a/config/feature_flags/development/mr_attention_requests.yml b/config/feature_flags/development/mr_attention_requests.yml
new file mode 100644
index 00000000000..b80300d1acf
--- /dev/null
+++ b/config/feature_flags/development/mr_attention_requests.yml
@@ -0,0 +1,8 @@
+---
+name: mr_attention_requests
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72773
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343528
+milestone: '14.4'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/mr_changes_fluid_layout.yml b/config/feature_flags/development/mr_changes_fluid_layout.yml
index 87f0c0c6569..dcb9dee2ece 100644
--- a/config/feature_flags/development/mr_changes_fluid_layout.yml
+++ b/config/feature_flags/development/mr_changes_fluid_layout.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341809
milestone: '14.4'
type: development
group: group::code review
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/multiple_gpg_signatures.yml b/config/feature_flags/development/multiple_gpg_signatures.yml
new file mode 100644
index 00000000000..3b9b8d0a465
--- /dev/null
+++ b/config/feature_flags/development/multiple_gpg_signatures.yml
@@ -0,0 +1,8 @@
+---
+name: multiple_gpg_signatures
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74095
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345261
+milestone: '14.5'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/new_customersdot_staging_url.yml b/config/feature_flags/development/new_customersdot_staging_url.yml
deleted file mode 100644
index 288d7f66f01..00000000000
--- a/config/feature_flags/development/new_customersdot_staging_url.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: new_customersdot_staging_url
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71827
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342513
-milestone: '14.4'
-type: development
-group: group::fulfillment
-default_enabled: false
diff --git a/config/feature_flags/development/new_environments_table.yml b/config/feature_flags/development/new_environments_table.yml
new file mode 100644
index 00000000000..b97a4d49cd8
--- /dev/null
+++ b/config/feature_flags/development/new_environments_table.yml
@@ -0,0 +1,8 @@
+---
+name: new_environments_table
+introduced_by_url:
+rollout_issue_url:
+milestone: '14.4'
+type: development
+group: group::release
+default_enabled: false
diff --git a/config/feature_flags/development/new_graphql_keyset_pagination.yml b/config/feature_flags/development/new_graphql_keyset_pagination.yml
index f4afcba68cf..7f1c73756b3 100644
--- a/config/feature_flags/development/new_graphql_keyset_pagination.yml
+++ b/config/feature_flags/development/new_graphql_keyset_pagination.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323730
milestone: '13.10'
type: development
group: group::optimize
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/package_list_apollo.yml b/config/feature_flags/development/package_list_apollo.yml
deleted file mode 100644
index 522b08594e2..00000000000
--- a/config/feature_flags/development/package_list_apollo.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: package_list_apollo
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70598
-rollout_issue_url:
-milestone: '14.3'
-type: development
-group: group::package
-default_enabled: false
diff --git a/config/feature_flags/development/packages_npm_abbreviated_metadata.yml b/config/feature_flags/development/packages_npm_abbreviated_metadata.yml
new file mode 100644
index 00000000000..ad191adfa20
--- /dev/null
+++ b/config/feature_flags/development/packages_npm_abbreviated_metadata.yml
@@ -0,0 +1,8 @@
+---
+name: packages_npm_abbreviated_metadata
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73639
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344827
+milestone: '14.5'
+type: development
+group: group::package
+default_enabled: true
diff --git a/config/feature_flags/development/paginated_issue_discussions.yml b/config/feature_flags/development/paginated_issue_discussions.yml
new file mode 100644
index 00000000000..f4e765bd7f2
--- /dev/null
+++ b/config/feature_flags/development/paginated_issue_discussions.yml
@@ -0,0 +1,8 @@
+---
+name: paginated_issue_discussions
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69933
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345351
+milestone: '14.5'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/paginated_tree_graphql_query.yml b/config/feature_flags/development/paginated_tree_graphql_query.yml
deleted file mode 100644
index d56d8fc336c..00000000000
--- a/config/feature_flags/development/paginated_tree_graphql_query.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: paginated_tree_graphql_query
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66751
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337214
-milestone: '14.2'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/pipeline_editor_mini_graph.yml b/config/feature_flags/development/pipeline_editor_mini_graph.yml
deleted file mode 100644
index 6f31cb18d82..00000000000
--- a/config/feature_flags/development/pipeline_editor_mini_graph.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: pipeline_editor_mini_graph
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71622
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342217
-milestone: '14.4'
-type: development
-group: group::pipeline authoring
-default_enabled: false
diff --git a/config/feature_flags/development/project_storage_ui.yml b/config/feature_flags/development/project_storage_ui.yml
deleted file mode 100644
index 23a5b5c3d29..00000000000
--- a/config/feature_flags/development/project_storage_ui.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: project_storage_ui
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68289
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334889
-milestone: '14.2'
-type: development
-group: group::utilization
-default_enabled: false
diff --git a/config/feature_flags/development/query_analyzer_gitlab_schema_metrics.yml b/config/feature_flags/development/query_analyzer_gitlab_schema_metrics.yml
new file mode 100644
index 00000000000..b784105368c
--- /dev/null
+++ b/config/feature_flags/development/query_analyzer_gitlab_schema_metrics.yml
@@ -0,0 +1,8 @@
+---
+name: query_analyzer_gitlab_schema_metrics
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73839
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345034
+milestone: '14.5'
+type: development
+group: group::sharding
+default_enabled: false
diff --git a/config/feature_flags/development/query_project_ci_feature_usages_for_coverage.yml b/config/feature_flags/development/query_project_ci_feature_usages_for_coverage.yml
deleted file mode 100644
index 1b720d6276b..00000000000
--- a/config/feature_flags/development/query_project_ci_feature_usages_for_coverage.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: query_project_ci_feature_usages_for_coverage
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69890
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339974
-milestone: '14.3'
-type: development
-group: group::testing
-default_enabled: false
diff --git a/config/feature_flags/development/real_time_issue_sidebar.yml b/config/feature_flags/development/real_time_issue_sidebar.yml
index 4fe8e19213a..12d3da86cad 100644
--- a/config/feature_flags/development/real_time_issue_sidebar.yml
+++ b/config/feature_flags/development/real_time_issue_sidebar.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/1210
milestone: '13.0'
type: development
group: group::project management
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/release_evidence.yml b/config/feature_flags/development/release_evidence.yml
deleted file mode 100644
index 3ba5ed86c71..00000000000
--- a/config/feature_flags/development/release_evidence.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: release_evidence
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26509
-rollout_issue_url:
-milestone: '12.10'
-type: development
-group: group::release
-default_enabled: true
diff --git a/config/feature_flags/development/report_on_long_redis_durations.yml b/config/feature_flags/development/report_on_long_redis_durations.yml
deleted file mode 100644
index 0f93c591d63..00000000000
--- a/config/feature_flags/development/report_on_long_redis_durations.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: report_on_long_redis_durations
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67512
-rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1183
-milestone: '14.2'
-type: development
-group: team::Scalability
-default_enabled: false
diff --git a/config/feature_flags/development/request_apdex_counters.yml b/config/feature_flags/development/request_apdex_counters.yml
deleted file mode 100644
index 07d6cb7ac5e..00000000000
--- a/config/feature_flags/development/request_apdex_counters.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: request_apdex_counters
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69154
-rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1099
-milestone: '14.3'
-type: development
-group: team::Scalability
-default_enabled: false
diff --git a/config/feature_flags/development/retarget_merge_requests.yml b/config/feature_flags/development/retarget_merge_requests.yml
deleted file mode 100644
index cbad472a56e..00000000000
--- a/config/feature_flags/development/retarget_merge_requests.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: retarget_merge_requests
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53710
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320895
-milestone: '13.9'
-type: development
-group: group::memory
-default_enabled: true
diff --git a/config/feature_flags/development/security_finding_build_disable_joins.yml b/config/feature_flags/development/security_finding_build_disable_joins.yml
new file mode 100644
index 00000000000..7432882eca8
--- /dev/null
+++ b/config/feature_flags/development/security_finding_build_disable_joins.yml
@@ -0,0 +1,8 @@
+---
+name: security_finding_build_disable_joins
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72738
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342380
+milestone: '14.4'
+type: development
+group: group::threat insights
+default_enabled: true
diff --git a/config/feature_flags/development/show_relevant_approval_rule_approvers.yml b/config/feature_flags/development/show_relevant_approval_rule_approvers.yml
index 2fef085381d..233f6916896 100644
--- a/config/feature_flags/development/show_relevant_approval_rule_approvers.yml
+++ b/config/feature_flags/development/show_relevant_approval_rule_approvers.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329153
milestone: '13.12'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/sidekiq_push_bulk_in_batches.yml b/config/feature_flags/development/sidekiq_push_bulk_in_batches.yml
new file mode 100644
index 00000000000..ea4c5253856
--- /dev/null
+++ b/config/feature_flags/development/sidekiq_push_bulk_in_batches.yml
@@ -0,0 +1,8 @@
+---
+name: sidekiq_push_bulk_in_batches
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72263
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343740
+milestone: '14.5'
+type: development
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/development/specialized_service_for_project_member_auth_refresh.yml b/config/feature_flags/development/specialized_service_for_project_member_auth_refresh.yml
deleted file mode 100644
index 2d0c4cf14c3..00000000000
--- a/config/feature_flags/development/specialized_service_for_project_member_auth_refresh.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: specialized_service_for_project_member_auth_refresh
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67477
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337730
-milestone: '14.2'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/suppress_apollo_errors_during_navigation.yml b/config/feature_flags/development/suppress_apollo_errors_during_navigation.yml
deleted file mode 100644
index 21548fa4dbb..00000000000
--- a/config/feature_flags/development/suppress_apollo_errors_during_navigation.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: suppress_apollo_errors_during_navigation
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72031
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342745
-milestone: '14.4'
-type: development
-group: group::foundations
-default_enabled: false
diff --git a/config/feature_flags/development/surface_environment_creation_failure.yml b/config/feature_flags/development/surface_environment_creation_failure.yml
index 2c312d432ef..acb8600b0bb 100644
--- a/config/feature_flags/development/surface_environment_creation_failure.yml
+++ b/config/feature_flags/development/surface_environment_creation_failure.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340169
milestone: '14.4'
type: development
group: group::release
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/tag_list_keyset_pagination.yml b/config/feature_flags/development/tag_list_keyset_pagination.yml
new file mode 100644
index 00000000000..54bd96d82cf
--- /dev/null
+++ b/config/feature_flags/development/tag_list_keyset_pagination.yml
@@ -0,0 +1,8 @@
+---
+name: tag_list_keyset_pagination
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74239
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345595
+milestone: '14.5'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/tags_finder_gitaly.yml b/config/feature_flags/development/tags_finder_gitaly.yml
deleted file mode 100644
index 065a253a69f..00000000000
--- a/config/feature_flags/development/tags_finder_gitaly.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: tags_finder_gitaly
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69101
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339741
-milestone: '14.3'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/terms_of_service_vue.yml b/config/feature_flags/development/terms_of_service_vue.yml
new file mode 100644
index 00000000000..01bf3613127
--- /dev/null
+++ b/config/feature_flags/development/terms_of_service_vue.yml
@@ -0,0 +1,8 @@
+---
+name: terms_of_service_vue
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343046
+milestone: '14.5'
+type: development
+group: group::access
+default_enabled: true
diff --git a/config/feature_flags/development/traversal_ids_btree.yml b/config/feature_flags/development/traversal_ids_btree.yml
new file mode 100644
index 00000000000..aaecafe04ae
--- /dev/null
+++ b/config/feature_flags/development/traversal_ids_btree.yml
@@ -0,0 +1,8 @@
+---
+name: traversal_ids_btree
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69535
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342871
+milestone: '14.5'
+type: development
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/development/update_deployment_after_transaction_commit.yml b/config/feature_flags/development/update_deployment_after_transaction_commit.yml
deleted file mode 100644
index c07622fc9b4..00000000000
--- a/config/feature_flags/development/update_deployment_after_transaction_commit.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: update_deployment_after_transaction_commit
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71450
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342021
-milestone: '14.4'
-type: development
-group: group::release
-default_enabled: false
diff --git a/config/feature_flags/development/usage_data_instrumentation.yml b/config/feature_flags/development/usage_data_instrumentation.yml
new file mode 100644
index 00000000000..e2610cbd39c
--- /dev/null
+++ b/config/feature_flags/development/usage_data_instrumentation.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_instrumentation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68808
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345252
+milestone: '14.5'
+type: development
+group: group::product intelligence
+default_enabled: false
diff --git a/config/feature_flags/development/use_cmark_renderer.yml b/config/feature_flags/development/use_cmark_renderer.yml
new file mode 100644
index 00000000000..b47031a6924
--- /dev/null
+++ b/config/feature_flags/development/use_cmark_renderer.yml
@@ -0,0 +1,8 @@
+---
+name: use_cmark_renderer
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61792
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345744
+milestone: '14.6'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/use_model_load_balancing.yml b/config/feature_flags/development/use_model_load_balancing.yml
new file mode 100644
index 00000000000..630e34acff3
--- /dev/null
+++ b/config/feature_flags/development/use_model_load_balancing.yml
@@ -0,0 +1,8 @@
+---
+name: use_model_load_balancing
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73631
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344797
+milestone: '14.5'
+type: development
+group: group::sharding
+default_enabled: false
diff --git a/config/feature_flags/development/use_multi_store.yml b/config/feature_flags/development/use_multi_store.yml
new file mode 100644
index 00000000000..48db4a092b5
--- /dev/null
+++ b/config/feature_flags/development/use_multi_store.yml
@@ -0,0 +1,8 @@
+---
+name: use_multi_store
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73660
+rollout_issue_url:
+milestone: '14.5'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/development/use_optimized_group_labels_query.yml b/config/feature_flags/development/use_optimized_group_labels_query.yml
new file mode 100644
index 00000000000..37e2525d03e
--- /dev/null
+++ b/config/feature_flags/development/use_optimized_group_labels_query.yml
@@ -0,0 +1,8 @@
+---
+name: use_optimized_group_labels_query
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73501
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344957
+milestone: '14.5'
+type: development
+group: group::workspace
+default_enabled: false
diff --git a/config/feature_flags/development/use_traversal_ids_roots.yml b/config/feature_flags/development/use_traversal_ids_roots.yml
new file mode 100644
index 00000000000..3c0685dc872
--- /dev/null
+++ b/config/feature_flags/development/use_traversal_ids_roots.yml
@@ -0,0 +1,8 @@
+---
+name: use_traversal_ids_roots
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74148
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345438
+milestone: '14.5'
+type: development
+group: group::workspace
+default_enabled: false
diff --git a/config/feature_flags/development/use_vsa_aggregated_tables.yml b/config/feature_flags/development/use_vsa_aggregated_tables.yml
new file mode 100644
index 00000000000..d2adec3633b
--- /dev/null
+++ b/config/feature_flags/development/use_vsa_aggregated_tables.yml
@@ -0,0 +1,8 @@
+---
+name: use_vsa_aggregated_tables
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72978
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343429
+milestone: '14.5'
+type: development
+group: group::optimize
+default_enabled: false
diff --git a/config/feature_flags/development/variable_inside_variable.yml b/config/feature_flags/development/variable_inside_variable.yml
deleted file mode 100644
index fee4897b3f0..00000000000
--- a/config/feature_flags/development/variable_inside_variable.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: variable_inside_variable
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50156
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297382
-milestone: '13.11'
-type: development
-group: group::runner
-default_enabled: true
diff --git a/config/feature_flags/development/workhorse_use_sidechannel.yml b/config/feature_flags/development/workhorse_use_sidechannel.yml
index f39d313bf1a..1ba32be28c1 100644
--- a/config/feature_flags/development/workhorse_use_sidechannel.yml
+++ b/config/feature_flags/development/workhorse_use_sidechannel.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1
milestone: '14.4'
type: development
group: 'group::scalability'
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/experiment/bypass_registration.yml b/config/feature_flags/experiment/bypass_registration.yml
new file mode 100644
index 00000000000..b3a0d634248
--- /dev/null
+++ b/config/feature_flags/experiment/bypass_registration.yml
@@ -0,0 +1,8 @@
+---
+name: bypass_registration
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72827
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340560
+milestone: '14.5'
+type: experiment
+group: group::adoption
+default_enabled: false
diff --git a/config/feature_flags/experiment/change_continuous_onboarding_link_urls.yml b/config/feature_flags/experiment/change_continuous_onboarding_link_urls.yml
new file mode 100644
index 00000000000..e65d7cd8d94
--- /dev/null
+++ b/config/feature_flags/experiment/change_continuous_onboarding_link_urls.yml
@@ -0,0 +1,8 @@
+---
+name: change_continuous_onboarding_link_urls
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71408
+rollout_issue_url:
+milestone: '14.5'
+type: experiment
+group: group::conversion
+default_enabled: false
diff --git a/config/feature_flags/experiment/confetti_post_signup.yml b/config/feature_flags/experiment/confetti_post_signup.yml
new file mode 100644
index 00000000000..9f677bf252a
--- /dev/null
+++ b/config/feature_flags/experiment/confetti_post_signup.yml
@@ -0,0 +1,8 @@
+---
+name: confetti_post_signup
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70011
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339890
+milestone: '14.5'
+type: experiment
+group: group::expansion
+default_enabled: false
diff --git a/config/feature_flags/experiment/empty_repo_upload.yml b/config/feature_flags/experiment/empty_repo_upload.yml
deleted file mode 100644
index 9655a4d3cb4..00000000000
--- a/config/feature_flags/experiment/empty_repo_upload.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: empty_repo_upload
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52755
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285296
-milestone: '13.9'
-type: experiment
-group: group::adoption
-default_enabled: false
diff --git a/config/feature_flags/experiment/invite_members_for_task.yml b/config/feature_flags/experiment/invite_members_for_task.yml
new file mode 100644
index 00000000000..30743811f26
--- /dev/null
+++ b/config/feature_flags/experiment/invite_members_for_task.yml
@@ -0,0 +1,8 @@
+---
+name: invite_members_for_task
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339747
+milestone: '14.5'
+type: experiment
+group: group::activation
+default_enabled: false
diff --git a/config/feature_flags/experiment/invite_members_in_side_nav.yml b/config/feature_flags/experiment/invite_members_in_side_nav.yml
new file mode 100644
index 00000000000..7968a885374
--- /dev/null
+++ b/config/feature_flags/experiment/invite_members_in_side_nav.yml
@@ -0,0 +1,8 @@
+---
+name: invite_members_in_side_nav
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70451
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342951
+milestone: '14.5'
+type: experiment
+group: group::expansion
+default_enabled: false
diff --git a/config/feature_flags/experiment/invite_team_email.yml b/config/feature_flags/experiment/invite_team_email.yml
new file mode 100644
index 00000000000..f430b6ff88b
--- /dev/null
+++ b/config/feature_flags/experiment/invite_team_email.yml
@@ -0,0 +1,8 @@
+---
+name: invite_team_email
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72470
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345553
+milestone: '14.5'
+type: experiment
+group: group::activation
+default_enabled: false
diff --git a/config/feature_flags/experiment/pipeline_editor_walkthrough.yml b/config/feature_flags/experiment/pipeline_editor_walkthrough.yml
new file mode 100644
index 00000000000..6d8895cbab7
--- /dev/null
+++ b/config/feature_flags/experiment/pipeline_editor_walkthrough.yml
@@ -0,0 +1,8 @@
+---
+name: pipeline_editor_walkthrough
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73050
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345558
+milestone: '14.5'
+type: experiment
+group: group::activation
+default_enabled: false
diff --git a/config/feature_flags/experiment/prominent_create_board_btn.yml b/config/feature_flags/experiment/prominent_create_board_btn.yml
new file mode 100644
index 00000000000..b54dd25be15
--- /dev/null
+++ b/config/feature_flags/experiment/prominent_create_board_btn.yml
@@ -0,0 +1,8 @@
+---
+name: prominent_create_board_btn
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72683"
+rollout_issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/343415"
+milestone: "14.5"
+type: experiment
+group: group::product planning
+default_enabled: false
diff --git a/config/feature_flags/ops/additional_snowplow_tracking.yml b/config/feature_flags/ops/additional_snowplow_tracking.yml
new file mode 100644
index 00000000000..4dbf91bbff5
--- /dev/null
+++ b/config/feature_flags/ops/additional_snowplow_tracking.yml
@@ -0,0 +1,8 @@
+---
+name: additional_snowplow_tracking
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/12088
+rollout_issue_url:
+milestone: '11.11'
+group: group::product intelligence
+default_enabled: false
+type: ops
diff --git a/config/feature_flags/ops/block_anonymous_global_searches.yml b/config/feature_flags/ops/block_anonymous_global_searches.yml
new file mode 100644
index 00000000000..ecdf7243ed7
--- /dev/null
+++ b/config/feature_flags/ops/block_anonymous_global_searches.yml
@@ -0,0 +1,8 @@
+---
+name: block_anonymous_global_searches
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41041
+rollout_issue_url:
+milestone: '13.4'
+type: ops
+group: group::global search
+default_enabled: false
diff --git a/config/feature_flags/ops/product_analytics_tracking.yml b/config/feature_flags/ops/product_analytics_tracking.yml
deleted file mode 100644
index 5d392c4e4a7..00000000000
--- a/config/feature_flags/ops/product_analytics_tracking.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: product_analytics_tracking
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46482
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285519
-milestone: '13.7'
-type: ops
-group: group::product intelligence
-default_enabled: false
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index bb69c215f8d..4e5e15d261b 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -1024,6 +1024,9 @@ production: &base
# - { name: 'bitbucket',
# app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET' }
+ # - { name: 'dingtalk',
+ # app_id: 'YOUR_APP_ID',
+ # app_secret: 'YOUR_APP_SECRET' }
# - { name: 'gitlab',
# app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET',
@@ -1515,6 +1518,9 @@ test:
- { name: 'bitbucket',
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET' }
+ - { name: 'dingtalk',
+ app_id: 'YOUR_APP_ID',
+ app_secret: 'YOUR_APP_SECRET' }
- { name: 'gitlab',
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
diff --git a/config/initializers/00_active_record_gitlab_schema.rb b/config/initializers/00_active_record_gitlab_schema.rb
deleted file mode 100644
index f1ddd4d4eb1..00000000000
--- a/config/initializers/00_active_record_gitlab_schema.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-# This parameter describes a virtual context to indicate
-# table affinity to other tables.
-#
-# Table affinity limits cross-joins, cross-modifications,
-# foreign keys and validates relationship between tables
-#
-# By default it is undefined
-ActiveRecord::Base.class_attribute :gitlab_schema, default: nil
diff --git a/config/initializers/0_acts_as_taggable.rb b/config/initializers/0_acts_as_taggable.rb
deleted file mode 100644
index 8dee3c52a53..00000000000
--- a/config/initializers/0_acts_as_taggable.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-ActsAsTaggableOn.strict_case_match = true
-
-# tags_counter enables caching count of tags which results in an update whenever a tag is added or removed
-# since the count is not used anywhere its better performance wise to disable this cache
-ActsAsTaggableOn.tags_counter = false
-
-# validate that counter cache is disabled
-raise "Counter cache is not disabled" if
- ActsAsTaggableOn::Tagging.reflections["tag"].options[:counter_cache]
-
-ActsAsTaggableOn::Tagging.include IgnorableColumns
-ActsAsTaggableOn::Tagging.ignore_column :id_convert_to_bigint, remove_with: '14.5', remove_after: '2021-10-22'
-ActsAsTaggableOn::Tagging.ignore_column :taggable_id_convert_to_bigint, remove_with: '14.5', remove_after: '2021-10-22'
-
-# The tags and taggings are supposed to be part of `gitlab_ci`
-ActsAsTaggableOn::Tag.gitlab_schema = :gitlab_ci
-ActsAsTaggableOn::Tagging.gitlab_schema = :gitlab_ci
diff --git a/config/initializers/0_marginalia.rb b/config/initializers/0_marginalia.rb
index f7a1f5f0469..805a9e33347 100644
--- a/config/initializers/0_marginalia.rb
+++ b/config/initializers/0_marginalia.rb
@@ -19,7 +19,10 @@ Marginalia::Comment.components = [:application, :correlation_id, :jid, :endpoint
# adding :line has some overhead because a regexp on the backtrace has
# to be run on every SQL query. Only enable this in development because
# we've seen it slow things down.
-Marginalia::Comment.components << :line if Rails.env.development?
+if Rails.env.development?
+ Marginalia::Comment.components << :line
+ Marginalia::Comment.lines_to_ignore = Regexp.union(Gitlab::BacktraceCleaner::IGNORE_BACKTRACES + %w(lib/ruby/gems/ lib/gem_extensions/ lib/ruby/))
+end
Gitlab::Marginalia.set_application_name
diff --git a/config/initializers/0_postgresql_types.rb b/config/initializers/0_postgresql_types.rb
new file mode 100644
index 00000000000..79e7510ee55
--- /dev/null
+++ b/config/initializers/0_postgresql_types.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+# As discussed in https://github.com/rails/rails/issues/40687, this
+# patch registers a few types to silence warnings when Rails comes
+# across some PostgreSQL types it does not recognize.
+module PostgreSQLAdapterCustomTypes
+ def initialize_type_map(m = type_map) # rubocop:disable Naming/MethodParameterName
+ m.register_type('xid', ActiveRecord::Type::Integer.new(limit: 8))
+ m.register_type('pg_node_tree', ActiveRecord::Type::String.new)
+ m.register_type('_aclitem', ActiveRecord::Type::String.new)
+ m.register_type('pg_lsn', ActiveRecord::Type::String.new)
+
+ super
+ end
+end
+
+ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(PostgreSQLAdapterCustomTypes)
diff --git a/config/initializers/1_acts_as_taggable.rb b/config/initializers/1_acts_as_taggable.rb
new file mode 100644
index 00000000000..59412aef755
--- /dev/null
+++ b/config/initializers/1_acts_as_taggable.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+ActsAsTaggableOn.strict_case_match = true
+
+# tags_counter enables caching count of tags which results in an update whenever a tag is added or removed
+# since the count is not used anywhere its better performance wise to disable this cache
+ActsAsTaggableOn.tags_counter = false
+
+# validate that counter cache is disabled
+raise "Counter cache is not disabled" if
+ ActsAsTaggableOn::Tagging.reflections["tag"].options[:counter_cache]
+
+# Redirects retrieve_connection to use Ci::ApplicationRecord's connection
+[::ActsAsTaggableOn::Tag, ::ActsAsTaggableOn::Tagging].each do |model|
+ model.connection_specification_name = Ci::ApplicationRecord.connection_specification_name
+ model.singleton_class.delegate :connection, :sticking, to: '::Ci::ApplicationRecord'
+end
diff --git a/config/initializers/1_postgresql_only.rb b/config/initializers/1_postgresql_only.rb
index 7bb851daa08..3be55255ddd 100644
--- a/config/initializers/1_postgresql_only.rb
+++ b/config/initializers/1_postgresql_only.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
raise "PostgreSQL is the only supported database from GitLab 12.1" unless
- Gitlab::Database.main.postgresql?
+ ApplicationRecord.database.postgresql?
Gitlab::Database.check_postgres_version_and_print_warning
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index d6957491b16..8fb2161b14e 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -571,7 +571,7 @@ Settings.cron_jobs['user_status_cleanup_batch_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['user_status_cleanup_batch_worker']['cron'] ||= '* * * * *'
Settings.cron_jobs['user_status_cleanup_batch_worker']['job_class'] = 'UserStatusCleanup::BatchWorker'
Settings.cron_jobs['ssh_keys_expired_notification_worker'] ||= Settingslogic.new({})
-Settings.cron_jobs['ssh_keys_expired_notification_worker']['cron'] ||= '0 2 * * *'
+Settings.cron_jobs['ssh_keys_expired_notification_worker']['cron'] ||= '0 2,14 * * *'
Settings.cron_jobs['ssh_keys_expired_notification_worker']['job_class'] = 'SshKeys::ExpiredNotificationWorker'
Settings.cron_jobs['namespaces_in_product_marketing_emails_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['namespaces_in_product_marketing_emails_worker']['cron'] ||= '0 16 * * *'
@@ -588,6 +588,12 @@ Settings.cron_jobs['ci_delete_unit_tests_worker']['job_class'] = 'Ci::DeleteUnit
Settings.cron_jobs['batched_background_migrations_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['batched_background_migrations_worker']['cron'] ||= '* * * * *'
Settings.cron_jobs['batched_background_migrations_worker']['job_class'] = 'Database::BatchedBackgroundMigrationWorker'
+Settings.cron_jobs['issues_reschedule_stuck_issue_rebalances'] ||= Settingslogic.new({})
+Settings.cron_jobs['issues_reschedule_stuck_issue_rebalances']['cron'] ||= '*/15 * * * *'
+Settings.cron_jobs['issues_reschedule_stuck_issue_rebalances']['job_class'] = 'Issues::RescheduleStuckIssueRebalancesWorker'
+Settings.cron_jobs['clusters_integrations_check_prometheus_health_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['clusters_integrations_check_prometheus_health_worker']['cron'] ||= '0 * * * *'
+Settings.cron_jobs['clusters_integrations_check_prometheus_health_worker']['job_class'] = 'Clusters::Integrations::CheckPrometheusHealthWorker'
Gitlab.ee do
Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker'] ||= Settingslogic.new({})
@@ -713,6 +719,9 @@ Gitlab.ee do
Settings.cron_jobs['app_sec_dast_profile_schedule_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['app_sec_dast_profile_schedule_worker']['cron'] ||= '7-59/15 * * * *'
Settings.cron_jobs['app_sec_dast_profile_schedule_worker']['job_class'] = 'AppSec::Dast::ProfileScheduleWorker'
+ Settings.cron_jobs['loose_foreign_keys_cleanup_worker'] ||= Settingslogic.new({})
+ Settings.cron_jobs['loose_foreign_keys_cleanup_worker']['cron'] ||= '*/5 * * * *'
+ Settings.cron_jobs['loose_foreign_keys_cleanup_worker']['job_class'] = 'LooseForeignKeys::CleanupWorker'
end
#
diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb
index 587d393fd77..28f3da9b3df 100644
--- a/config/initializers/7_prometheus_metrics.rb
+++ b/config/initializers/7_prometheus_metrics.rb
@@ -65,7 +65,7 @@ if !Rails.env.test? && Gitlab::Metrics.prometheus_metrics_enabled?
Gitlab::Metrics::Samplers::DatabaseSampler.initialize_instance.start
Gitlab::Metrics::Samplers::ThreadsSampler.initialize_instance.start
- if Gitlab::Runtime.action_cable?
+ if Gitlab::Runtime.web_server?
Gitlab::Metrics::Samplers::ActionCableSampler.instance.start
end
diff --git a/config/initializers/action_cable.rb b/config/initializers/action_cable.rb
index a7ef5cc332c..fc40d0b69c5 100644
--- a/config/initializers/action_cable.rb
+++ b/config/initializers/action_cable.rb
@@ -3,8 +3,7 @@
require 'action_cable/subscription_adapter/redis'
Rails.application.configure do
- # Mount the ActionCable engine when in-app mode is enabled
- config.action_cable.mount_path = Gitlab::ActionCable::Config.in_app? ? '/-/cable' : nil
+ config.action_cable.mount_path = '/-/cable'
config.action_cable.url = Gitlab::Utils.append_path(Gitlab.config.gitlab.relative_url_root, '/-/cable')
config.action_cable.worker_pool_size = Gitlab::ActionCable::Config.worker_pool_size
diff --git a/config/initializers/action_view.rb b/config/initializers/action_view.rb
deleted file mode 100644
index 76171733483..00000000000
--- a/config/initializers/action_view.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-# This file was introduced during upgrading Rails from 5.2 to 6.0.
-# This file can be removed when `config.load_defaults 6.0` is introduced.
-
-# Don't force requests from old versions of IE to be UTF-8 encoded.
-Rails.application.config.action_view.default_enforce_utf8 = false
diff --git a/config/initializers/active_record_lifecycle.rb b/config/initializers/active_record_lifecycle.rb
index 75991c9da35..8d4b6d61abe 100644
--- a/config/initializers/active_record_lifecycle.rb
+++ b/config/initializers/active_record_lifecycle.rb
@@ -14,7 +14,7 @@ end
if defined?(ActiveRecord::Base)
Gitlab::Cluster::LifecycleEvents.on_before_fork do
- raise 'ActiveRecord connection not established. Unable to start.' unless Gitlab::Database.main.exists?
+ raise 'ActiveRecord connection not established. Unable to start.' unless ApplicationRecord.database.exists?
# the following is highly recommended for Rails + "preload_app true"
# as there's no need for the master process to hold a connection
diff --git a/config/initializers/console_message.rb b/config/initializers/console_message.rb
index 5e9e7a7a9af..3f98568c500 100644
--- a/config/initializers/console_message.rb
+++ b/config/initializers/console_message.rb
@@ -10,8 +10,8 @@ if Gitlab::Runtime.console?
puts " GitLab:".ljust(justify) + "#{Gitlab::VERSION} (#{Gitlab.revision}) #{Gitlab.ee? ? 'EE' : 'FOSS'}"
puts " GitLab Shell:".ljust(justify) + "#{Gitlab::VersionInfo.parse(Gitlab::Shell.version)}"
- if Gitlab::Database.main.exists?
- puts " #{Gitlab::Database.main.human_adapter_name}:".ljust(justify) + Gitlab::Database.main.version
+ if ApplicationRecord.database.exists?
+ puts " #{ApplicationRecord.database.human_adapter_name}:".ljust(justify) + ApplicationRecord.database.version
Gitlab.ee do
if Gitlab::Geo.connected? && Gitlab::Geo.enabled?
diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb
index 375a23fdfd6..27451001679 100644
--- a/config/initializers/cookies_serializer.rb
+++ b/config/initializers/cookies_serializer.rb
@@ -2,6 +2,5 @@
# Be sure to restart your server when you modify this file.
-Rails.application.config.action_dispatch.use_cookies_with_metadata = true
Rails.application.config.action_dispatch.cookies_serializer =
Gitlab::Utils.to_boolean(ENV['USE_UNSAFE_HYBRID_COOKIES']) ? :hybrid : :json
diff --git a/config/initializers/database_config.rb b/config/initializers/database_config.rb
index 7aedf9013ae..1eb9d12812a 100644
--- a/config/initializers/database_config.rb
+++ b/config/initializers/database_config.rb
@@ -10,8 +10,6 @@ Gitlab.ee do
end
end
-ActiveRecord::Base.establish_connection(Gitlab::Database.main.db_config_with_default_pool_size)
-
Gitlab.ee do
if Gitlab::Runtime.sidekiq? && Gitlab::Geo.geo_database_configured?
Rails.configuration.geo_database['pool'] = Gitlab::Database.default_pool_size
diff --git a/config/initializers/database_query_analyzers.rb b/config/initializers/database_query_analyzers.rb
new file mode 100644
index 00000000000..8a2fe1d8388
--- /dev/null
+++ b/config/initializers/database_query_analyzers.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+# Currently we register validator only for `dev` or `test` environment
+if Gitlab.dev_or_test_env? || Gitlab::Utils.to_boolean(ENV['GITLAB_ENABLE_QUERY_ANALYZERS'], default: false)
+ Gitlab::Database::QueryAnalyzer.instance.hook!
+ Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(::Gitlab::Database::QueryAnalyzers::GitlabSchemasMetrics)
+
+ if Rails.env.test? || Gitlab::Utils.to_boolean(ENV['ENABLE_CROSS_DATABASE_MODIFICATION_DETECTION'], default: false)
+ Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification)
+ end
+
+ Gitlab::Application.configure do |config|
+ config.middleware.use(Gitlab::Middleware::QueryAnalyzer)
+ end
+end
diff --git a/config/initializers/direct_upload_support.rb b/config/initializers/direct_upload_support.rb
index 880aea7d114..f57f0d7980d 100644
--- a/config/initializers/direct_upload_support.rb
+++ b/config/initializers/direct_upload_support.rb
@@ -17,7 +17,7 @@ class DirectUploadsValidator
raise ValidationError, "No provider configured for '#{uploader_type}'. #{supported_provider_text}" if provider.blank?
- return if provider_loaded?(provider)
+ return if provider_supported?(provider)
raise ValidationError, "Object storage provider '#{provider}' is not supported " \
"when 'direct_upload' is used for '#{uploader_type}'. #{supported_provider_text}"
@@ -25,12 +25,8 @@ class DirectUploadsValidator
private
- def provider_loaded?(provider)
- return false unless SUPPORTED_DIRECT_UPLOAD_PROVIDERS.include?(provider)
-
- require 'fog/azurerm' if provider == ObjectStorage::Config::AZURE_PROVIDER
-
- true
+ def provider_supported?(provider)
+ SUPPORTED_DIRECT_UPLOAD_PROVIDERS.include?(provider)
end
def supported_provider_text
diff --git a/config/initializers/elastic_client_setup.rb b/config/initializers/elastic_client_setup.rb
index 5b8d81265ad..67b5032a2ee 100644
--- a/config/initializers/elastic_client_setup.rb
+++ b/config/initializers/elastic_client_setup.rb
@@ -45,6 +45,23 @@ Gitlab.ee do
end
end
+ ### Modified from elasticsearch-model/lib/elasticsearch/model/searching.rb
+
+ module Elasticsearch
+ module Model
+ module Searching
+ class SearchRequest
+ def execute!
+ response = klass.client.search(@definition)
+ raise Elastic::TimeoutError if response['timed_out']
+
+ response
+ end
+ end
+ end
+ end
+ end
+
### Modified from elasticsearch-model/lib/elasticsearch/model.rb
[
diff --git a/config/initializers/forbid_sidekiq_in_transactions.rb b/config/initializers/forbid_sidekiq_in_transactions.rb
index ba5c1340b10..e5e17672c4e 100644
--- a/config/initializers/forbid_sidekiq_in_transactions.rb
+++ b/config/initializers/forbid_sidekiq_in_transactions.rb
@@ -20,7 +20,7 @@ module Sidekiq
module NoEnqueueingFromTransactions
%i(perform_async perform_at perform_in).each do |name|
define_method(name) do |*args|
- if !Sidekiq::Worker.skip_transaction_check && Gitlab::Database.main.inside_transaction?
+ if !Sidekiq::Worker.skip_transaction_check && ApplicationRecord.inside_transaction?
begin
raise Sidekiq::Worker::EnqueueFromTransactionError, <<~MSG
`#{self}.#{name}` cannot be called inside a transaction as this can lead to
diff --git a/config/initializers/load_balancing.rb b/config/initializers/load_balancing.rb
index a31b11bb2be..df75178740b 100644
--- a/config/initializers/load_balancing.rb
+++ b/config/initializers/load_balancing.rb
@@ -20,7 +20,7 @@ Gitlab::Database::LoadBalancing.base_models.each do |model|
Gitlab::Cluster::LifecycleEvents.on_before_fork do
# When forking, we don't want to wait until the connections aren't in use
# any more, as this could delay the boot cycle.
- model.connection.load_balancer.disconnect!(timeout: 0)
+ model.load_balancer.disconnect!(timeout: 0)
end
# Service discovery only needs to run in the worker processes, as the main one
diff --git a/config/initializers/new_framework_defaults.rb b/config/initializers/new_framework_defaults.rb
deleted file mode 100644
index 3d3ee5299e2..00000000000
--- a/config/initializers/new_framework_defaults.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-# Remove this `if` condition when upgraded to rails 5.0.
-# The body must be kept.
-# Be sure to restart your server when you modify this file.
-#
-# This file contains migration options to ease your Rails 5.0 upgrade.
-#
-# Once upgraded flip defaults one by one to migrate to the new default.
-#
-# Read the Guide for Upgrading Ruby on Rails for more info on each option.
-
-# Enable per-form CSRF tokens. Previous versions had false.
-Rails.application.config.action_controller.per_form_csrf_tokens = false
-
-# Enable origin-checking CSRF mitigation. Previous versions had false.
-Rails.application.config.action_controller.forgery_protection_origin_check = false
-
-# Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`.
-# Previous versions had false.
-ActiveSupport.to_time_preserves_timezone = false
-
-# Require `belongs_to` associations by default. Previous versions had false.
-Rails.application.config.active_record.belongs_to_required_by_default = false
diff --git a/config/initializers/postgres_partitioning.rb b/config/initializers/postgres_partitioning.rb
index 49f382547d6..5af8cf52656 100644
--- a/config/initializers/postgres_partitioning.rb
+++ b/config/initializers/postgres_partitioning.rb
@@ -10,10 +10,29 @@ if Gitlab.ee?
IncidentManagement::PendingEscalations::Alert,
IncidentManagement::PendingEscalations::Issue
])
+else
+ Gitlab::Database::Partitioning.register_tables([
+ {
+ table_name: 'incident_management_pending_alert_escalations',
+ partitioned_column: :process_at, strategy: :monthly
+ },
+ {
+ table_name: 'incident_management_pending_issue_escalations',
+ partitioned_column: :process_at, strategy: :monthly
+ }
+ ])
end
-begin
- Gitlab::Database::Partitioning.sync_partitions unless ENV['DISABLE_POSTGRES_PARTITION_CREATION_ON_STARTUP']
-rescue ActiveRecord::ActiveRecordError, PG::Error
- # ignore - happens when Rake tasks yet have to create a database, e.g. for testing
+# The following tables are already defined as models
+unless Gitlab.jh?
+ Gitlab::Database::Partitioning.register_tables([
+ # This should be synchronized with the following model:
+ # https://gitlab.com/gitlab-jh/gitlab/-/blob/main-jh/jh/app/models/phone/verification_code.rb
+ {
+ table_name: 'verification_codes',
+ partitioned_column: :created_at, strategy: :monthly
+ }
+ ])
end
+
+Gitlab::Database::Partitioning.sync_partitions_ignore_db_error
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
index 02fc4912f94..75328dcd891 100644
--- a/config/initializers/session_store.rb
+++ b/config/initializers/session_store.rb
@@ -19,15 +19,31 @@ cookie_key = if Rails.env.development?
"_gitlab_session"
end
-sessions_config = Gitlab::Redis::SharedState.params
-sessions_config[:namespace] = Gitlab::Redis::SharedState::SESSION_NAMESPACE
+if Gitlab::Utils.to_boolean(ENV['GITLAB_REDIS_STORE_WITH_SESSION_STORE'], default: true)
+ store = Gitlab::Redis::SharedState.store(
+ namespace: Gitlab::Redis::SharedState::SESSION_NAMESPACE
+ )
-Gitlab::Application.config.session_store(
- :redis_store, # Using the cookie_store would enable session replay attacks.
- servers: sessions_config,
- key: cookie_key,
- secure: Gitlab.config.gitlab.https,
- httponly: true,
- expires_in: Settings.gitlab['session_expire_delay'] * 60,
- path: Rails.application.config.relative_url_root.presence || '/'
-)
+ Gitlab::Application.config.session_store(
+ :redis_store, # Using the cookie_store would enable session replay attacks.
+ redis_store: store,
+ key: cookie_key,
+ secure: Gitlab.config.gitlab.https,
+ httponly: true,
+ expires_in: Settings.gitlab['session_expire_delay'] * 60,
+ path: Rails.application.config.relative_url_root.presence || '/'
+ )
+else
+ sessions_config = Gitlab::Redis::SharedState.params
+ sessions_config[:namespace] = Gitlab::Redis::SharedState::SESSION_NAMESPACE
+
+ Gitlab::Application.config.session_store(
+ :redis_store, # Using the cookie_store would enable session replay attacks.
+ servers: sessions_config,
+ key: cookie_key,
+ secure: Gitlab.config.gitlab.https,
+ httponly: true,
+ expires_in: Settings.gitlab['session_expire_delay'] * 60,
+ path: Rails.application.config.relative_url_root.presence || '/'
+ )
+end
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index d33550b82d1..23052e7ac57 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -114,3 +114,6 @@ Sidekiq.configure_client do |config|
config.client_middleware(&Gitlab::SidekiqMiddleware.client_configurator)
end
+
+Sidekiq::Client.prepend Gitlab::Patch::SidekiqClient
+Sidekiq::Cron::Poller.prepend Gitlab::Patch::SidekiqCronPoller
diff --git a/config/initializers/zz_metrics.rb b/config/initializers/zz_metrics.rb
index 8e69e1634f1..7fa71225aae 100644
--- a/config/initializers/zz_metrics.rb
+++ b/config/initializers/zz_metrics.rb
@@ -42,7 +42,7 @@ if Gitlab::Metrics.enabled? && !Rails.env.test? && !(Rails.env.development? && d
def connect(*args)
val = super
- if current_transaction = ::Gitlab::Metrics::Transaction.current
+ if current_transaction = (::Gitlab::Metrics::WebTransaction.current || ::Gitlab::Metrics::BackgroundTransaction.current)
current_transaction.increment(:gitlab_transaction_new_redis_connections_total, 1)
end
diff --git a/config/initializers_before_autoloader/000_inflections.rb b/config/initializers_before_autoloader/000_inflections.rb
index b7e4e143765..876ae5da230 100644
--- a/config/initializers_before_autoloader/000_inflections.rb
+++ b/config/initializers_before_autoloader/000_inflections.rb
@@ -39,4 +39,5 @@ ActiveSupport::Inflector.inflections do |inflect|
inflect.acronym 'EE'
inflect.acronym 'JH'
inflect.acronym 'CSP'
+ inflect.acronym 'VSCode'
end
diff --git a/config/initializers_before_autoloader/100_patch_omniauth_oauth2.rb b/config/initializers_before_autoloader/100_patch_omniauth_oauth2.rb
index 1ede92609a9..c6baae56d3d 100644
--- a/config/initializers_before_autoloader/100_patch_omniauth_oauth2.rb
+++ b/config/initializers_before_autoloader/100_patch_omniauth_oauth2.rb
@@ -10,31 +10,11 @@
module OmniAuth
module Strategies
class OAuth2
+ alias_method :original_callback_phase, :callback_phase
+
def callback_phase
- error = request.params["error_reason"].presence || request.params["error"].presence
- # Monkey patch #1:
- #
- # Swap the order of these conditions around so the `state` param is verified *first*,
- # before using the error params returned by the provider.
- #
- # This avoids content spoofing attacks by crafting a URL with malicious messages,
- # because the `state` param is only present in the session after a valid OAuth2 authentication flow.
- if !options.provider_ignores_state && (request.params["state"].to_s.empty? || request.params["state"] != session.delete("omniauth.state"))
- fail!(:csrf_detected, CallbackError.new(:csrf_detected, "CSRF detected"))
- elsif error
- fail!(error, CallbackError.new(request.params["error"], request.params["error_description"].presence || request.params["error_reason"].presence, request.params["error_uri"]))
- else
- self.access_token = build_access_token
- self.access_token = access_token.refresh! if access_token.expired?
- super
- end
- rescue ::OAuth2::Error, CallbackError => e
- fail!(:invalid_credentials, e)
- rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e
- fail!(:timeout, e)
- rescue ::SocketError => e
- fail!(:failed_to_connect, e)
- # Monkey patch #2:
+ original_callback_phase
+ # Monkey patch #1:
#
# Also catch errors from Faraday.
# See https://github.com/omniauth/omniauth-oauth2/pull/129
diff --git a/config/known_invalid_graphql_queries.yml b/config/known_invalid_graphql_queries.yml
index 3dc4b10a6a8..84c6039793d 100644
--- a/config/known_invalid_graphql_queries.yml
+++ b/config/known_invalid_graphql_queries.yml
@@ -1,5 +1,3 @@
---
filenames:
- - ee/app/assets/javascripts/oncall_schedules/graphql/mutations/update_oncall_schedule_rotation.mutation.graphql
- - ee/app/assets/javascripts/security_configuration/api_fuzzing/graphql/api_fuzzing_ci_configuration.query.graphql
- - ee/app/assets/javascripts/security_configuration/api_fuzzing/graphql/create_api_fuzzing_configuration.mutation.graphql
+ - ee/app/assets/javascripts/oncall_schedules/graphql/mutations/update_oncall_schedule_rotation.mutation.graphql \ No newline at end of file
diff --git a/config/metrics/aggregates/code_review.yml b/config/metrics/aggregates/code_review.yml
index 54ebe5da192..04a0b5e34e9 100644
--- a/config/metrics/aggregates/code_review.yml
+++ b/config/metrics/aggregates/code_review.yml
@@ -67,6 +67,12 @@
- 'i_code_review_user_resolve_conflict'
- 'i_code_review_user_searches_diff'
- 'i_code_review_user_resolve_thread_in_issue'
+ - 'i_code_review_widget_nothing_merge_click_new_file'
+ - 'i_code_review_post_merge_delete_branch'
+ - 'i_code_review_post_merge_click_revert'
+ - 'i_code_review_post_merge_click_cherry_pick'
+ - 'i_code_review_post_merge_submit_revert_modal'
+ - 'i_code_review_post_merge_submit_cherry_pick_modal'
- name: code_review_category_monthly_active_users
operator: OR
source: redis
@@ -126,6 +132,12 @@
- 'i_code_review_user_resolve_conflict'
- 'i_code_review_user_searches_diff'
- 'i_code_review_user_resolve_thread_in_issue'
+ - 'i_code_review_widget_nothing_merge_click_new_file'
+ - 'i_code_review_post_merge_delete_branch'
+ - 'i_code_review_post_merge_click_revert'
+ - 'i_code_review_post_merge_click_cherry_pick'
+ - 'i_code_review_post_merge_submit_revert_modal'
+ - 'i_code_review_post_merge_submit_cherry_pick_modal'
- name: code_review_extension_category_monthly_active_users
operator: OR
source: redis
diff --git a/config/metrics/counts_28d/20210216183203_product_analytics_test_metrics_union.yml b/config/metrics/counts_28d/20210216183203_product_analytics_test_metrics_union.yml
index 924a19cae74..8ea92369e0b 100644
--- a/config/metrics/counts_28d/20210216183203_product_analytics_test_metrics_union.yml
+++ b/config/metrics/counts_28d/20210216183203_product_analytics_test_metrics_union.yml
@@ -11,7 +11,7 @@ status: removed
milestone_removed: '13.11'
milestone: '13.7'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49886
-time_frame: 7d
+time_frame: 28d
data_source: redis_hll
distribution:
- ce
diff --git a/config/metrics/counts_28d/20210216183648_github.yml b/config/metrics/counts_28d/20210216183648_github.yml
index efa4cca301f..c33cc1809af 100644
--- a/config/metrics/counts_28d/20210216183648_github.yml
+++ b/config/metrics/counts_28d/20210216183648_github.yml
@@ -8,7 +8,7 @@ product_group: group::import
product_category: importers
value_type: number
status: active
-time_frame: all
+time_frame: 28d
data_source: database
distribution:
- ce
diff --git a/config/metrics/counts_28d/20210216183650_bitbucket.yml b/config/metrics/counts_28d/20210216183650_bitbucket.yml
index 5731b6b3cae..557a38cad1c 100644
--- a/config/metrics/counts_28d/20210216183650_bitbucket.yml
+++ b/config/metrics/counts_28d/20210216183650_bitbucket.yml
@@ -8,7 +8,7 @@ product_group: group::import
product_category: importers
value_type: number
status: active
-time_frame: all
+time_frame: 28d
data_source: database
distribution:
- ce
diff --git a/config/metrics/counts_28d/20210216183652_bitbucket_server.yml b/config/metrics/counts_28d/20210216183652_bitbucket_server.yml
index be4e45b8975..d9f255a0b2d 100644
--- a/config/metrics/counts_28d/20210216183652_bitbucket_server.yml
+++ b/config/metrics/counts_28d/20210216183652_bitbucket_server.yml
@@ -8,7 +8,7 @@ product_group: group::import
product_category: importers
value_type: number
status: active
-time_frame: all
+time_frame: 28d
data_source: database
distribution:
- ce
diff --git a/config/metrics/counts_28d/20210216184312_i_code_review_user_toggled_task_item_status_monthly.yml b/config/metrics/counts_28d/20210216184312_i_code_review_user_toggled_task_item_status_monthly.yml
index 72617203f6a..495c7740e3f 100644
--- a/config/metrics/counts_28d/20210216184312_i_code_review_user_toggled_task_item_status_monthly.yml
+++ b/config/metrics/counts_28d/20210216184312_i_code_review_user_toggled_task_item_status_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who toggled a task item in a merge
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184322_i_code_review_user_approve_mr_monthly.yml b/config/metrics/counts_28d/20210216184322_i_code_review_user_approve_mr_monthly.yml
index f3c4a921afa..87d78d83450 100644
--- a/config/metrics/counts_28d/20210216184322_i_code_review_user_approve_mr_monthly.yml
+++ b/config/metrics/counts_28d/20210216184322_i_code_review_user_approve_mr_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who approve a merge request
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184326_i_code_review_user_unapprove_mr_monthly.yml b/config/metrics/counts_28d/20210216184326_i_code_review_user_unapprove_mr_monthly.yml
index ab4d4c1bfc7..94ac6d7b6b7 100644
--- a/config/metrics/counts_28d/20210216184326_i_code_review_user_unapprove_mr_monthly.yml
+++ b/config/metrics/counts_28d/20210216184326_i_code_review_user_unapprove_mr_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who unapprove a merge request
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184330_i_code_review_user_resolve_thread_monthly.yml b/config/metrics/counts_28d/20210216184330_i_code_review_user_resolve_thread_monthly.yml
index 9f2ab332a08..5cd9131d663 100644
--- a/config/metrics/counts_28d/20210216184330_i_code_review_user_resolve_thread_monthly.yml
+++ b/config/metrics/counts_28d/20210216184330_i_code_review_user_resolve_thread_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who resolve a thread in a merge req
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184334_i_code_review_user_unresolve_thread_monthly.yml b/config/metrics/counts_28d/20210216184334_i_code_review_user_unresolve_thread_monthly.yml
index 83644eff397..01ab33527cc 100644
--- a/config/metrics/counts_28d/20210216184334_i_code_review_user_unresolve_thread_monthly.yml
+++ b/config/metrics/counts_28d/20210216184334_i_code_review_user_unresolve_thread_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who unresolve a thread in a merge r
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184338_i_code_review_edit_mr_title_monthly.yml b/config/metrics/counts_28d/20210216184338_i_code_review_edit_mr_title_monthly.yml
index df7acea15f8..e09ac66953f 100644
--- a/config/metrics/counts_28d/20210216184338_i_code_review_edit_mr_title_monthly.yml
+++ b/config/metrics/counts_28d/20210216184338_i_code_review_edit_mr_title_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who edit the title of a merge reque
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184342_i_code_review_edit_mr_desc_monthly.yml b/config/metrics/counts_28d/20210216184342_i_code_review_edit_mr_desc_monthly.yml
index 02980ed84f8..99bddd4591b 100644
--- a/config/metrics/counts_28d/20210216184342_i_code_review_edit_mr_desc_monthly.yml
+++ b/config/metrics/counts_28d/20210216184342_i_code_review_edit_mr_desc_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who edit the description of a merge
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184353_i_code_review_user_create_review_note_monthly.yml b/config/metrics/counts_28d/20210216184353_i_code_review_user_create_review_note_monthly.yml
index cb0ba9c4785..9626907c904 100644
--- a/config/metrics/counts_28d/20210216184353_i_code_review_user_create_review_note_monthly.yml
+++ b/config/metrics/counts_28d/20210216184353_i_code_review_user_create_review_note_monthly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per month who create a note as part of a merg
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184357_i_code_review_user_publish_review_monthly.yml b/config/metrics/counts_28d/20210216184357_i_code_review_user_publish_review_monthly.yml
index 78228a1da48..1153c89126e 100644
--- a/config/metrics/counts_28d/20210216184357_i_code_review_user_publish_review_monthly.yml
+++ b/config/metrics/counts_28d/20210216184357_i_code_review_user_publish_review_monthly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per month who publish their review as part of
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184401_i_code_review_user_create_multiline_mr_comment_monthly.yml b/config/metrics/counts_28d/20210216184401_i_code_review_user_create_multiline_mr_comment_monthly.yml
index 4a4853a7520..805914598d6 100644
--- a/config/metrics/counts_28d/20210216184401_i_code_review_user_create_multiline_mr_comment_monthly.yml
+++ b/config/metrics/counts_28d/20210216184401_i_code_review_user_create_multiline_mr_comment_monthly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per month who create a multiline comment in a
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184405_i_code_review_user_edit_multiline_mr_comment_monthly.yml b/config/metrics/counts_28d/20210216184405_i_code_review_user_edit_multiline_mr_comment_monthly.yml
index 36b2de72379..84fa938126f 100644
--- a/config/metrics/counts_28d/20210216184405_i_code_review_user_edit_multiline_mr_comment_monthly.yml
+++ b/config/metrics/counts_28d/20210216184405_i_code_review_user_edit_multiline_mr_comment_monthly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per week who edit a multiline comment in a me
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184409_i_code_review_user_remove_multiline_mr_comment_monthly.yml b/config/metrics/counts_28d/20210216184409_i_code_review_user_remove_multiline_mr_comment_monthly.yml
index 7cc2b9b2cc2..db2155a71fe 100644
--- a/config/metrics/counts_28d/20210216184409_i_code_review_user_remove_multiline_mr_comment_monthly.yml
+++ b/config/metrics/counts_28d/20210216184409_i_code_review_user_remove_multiline_mr_comment_monthly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per month who remove a multiline comment in a
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184418_i_code_review_user_assigned_monthly.yml b/config/metrics/counts_28d/20210216184418_i_code_review_user_assigned_monthly.yml
index 7e8db2be0b7..da36f141a43 100644
--- a/config/metrics/counts_28d/20210216184418_i_code_review_user_assigned_monthly.yml
+++ b/config/metrics/counts_28d/20210216184418_i_code_review_user_assigned_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who are assigned to a merge request
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184422_i_code_review_user_marked_as_draft_monthly.yml b/config/metrics/counts_28d/20210216184422_i_code_review_user_marked_as_draft_monthly.yml
index f755351eb1e..4afb00c81dd 100644
--- a/config/metrics/counts_28d/20210216184422_i_code_review_user_marked_as_draft_monthly.yml
+++ b/config/metrics/counts_28d/20210216184422_i_code_review_user_marked_as_draft_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who mark a merge request as a draft
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184426_i_code_review_user_unmarked_as_draft_monthly.yml b/config/metrics/counts_28d/20210216184426_i_code_review_user_unmarked_as_draft_monthly.yml
index a5685f7634a..c104c010002 100644
--- a/config/metrics/counts_28d/20210216184426_i_code_review_user_unmarked_as_draft_monthly.yml
+++ b/config/metrics/counts_28d/20210216184426_i_code_review_user_unmarked_as_draft_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who unmark a merge request as a dra
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184430_i_code_review_user_review_requested_monthly.yml b/config/metrics/counts_28d/20210216184430_i_code_review_user_review_requested_monthly.yml
index 9e6f61a755b..d65c8380bc9 100644
--- a/config/metrics/counts_28d/20210216184430_i_code_review_user_review_requested_monthly.yml
+++ b/config/metrics/counts_28d/20210216184430_i_code_review_user_review_requested_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who request a review of a merge req
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184434_i_code_review_user_approval_rule_added_monthly.yml b/config/metrics/counts_28d/20210216184434_i_code_review_user_approval_rule_added_monthly.yml
index 35562e095c8..0da9ce57fea 100644
--- a/config/metrics/counts_28d/20210216184434_i_code_review_user_approval_rule_added_monthly.yml
+++ b/config/metrics/counts_28d/20210216184434_i_code_review_user_approval_rule_added_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who add an approval rule to a merge
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184438_i_code_review_user_approval_rule_deleted_monthly.yml b/config/metrics/counts_28d/20210216184438_i_code_review_user_approval_rule_deleted_monthly.yml
index 023f241596e..d2be31f7e89 100644
--- a/config/metrics/counts_28d/20210216184438_i_code_review_user_approval_rule_deleted_monthly.yml
+++ b/config/metrics/counts_28d/20210216184438_i_code_review_user_approval_rule_deleted_monthly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per month who delete an approval rule to a me
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184442_i_code_review_user_approval_rule_edited_monthly.yml b/config/metrics/counts_28d/20210216184442_i_code_review_user_approval_rule_edited_monthly.yml
index eae629b21f3..2c1fc6664ff 100644
--- a/config/metrics/counts_28d/20210216184442_i_code_review_user_approval_rule_edited_monthly.yml
+++ b/config/metrics/counts_28d/20210216184442_i_code_review_user_approval_rule_edited_monthly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per month who delete an approval rule to a me
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184446_i_code_review_user_vs_code_api_request_monthly.yml b/config/metrics/counts_28d/20210216184446_i_code_review_user_vs_code_api_request_monthly.yml
index f833466e32c..fec6640220f 100644
--- a/config/metrics/counts_28d/20210216184446_i_code_review_user_vs_code_api_request_monthly.yml
+++ b/config/metrics/counts_28d/20210216184446_i_code_review_user_vs_code_api_request_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who use GitLab Workflow for VS Code
product_stage: create
product_group: group::code review
product_category: editor_extension
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184450_i_code_review_user_create_mr_from_issue_monthly.yml b/config/metrics/counts_28d/20210216184450_i_code_review_user_create_mr_from_issue_monthly.yml
index 25a1a2948db..27c161cf13c 100644
--- a/config/metrics/counts_28d/20210216184450_i_code_review_user_create_mr_from_issue_monthly.yml
+++ b/config/metrics/counts_28d/20210216184450_i_code_review_user_create_mr_from_issue_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who create a merge request from an
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml
index c4c390d16e6..f41722f99cc 100644
--- a/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per month who interact with a merge request
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
index 66b8e714723..c80a7dada11 100644
--- a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
@@ -159,6 +159,7 @@ options:
- p_ci_templates_implicit_security_api_fuzzing
- p_ci_templates_implicit_security_dast
- p_ci_templates_implicit_security_cluster_image_scanning
+ - p_ci_templates_kaniko
distribution:
- ce
- ee
diff --git a/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml
index 84da476edb5..a09e973206d 100644
--- a/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml
+++ b/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml
@@ -8,8 +8,7 @@ product_stage: package
product_group: group::package
product_category: package registry
value_type: number
-status: broken
-repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331455
+status: active
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml b/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml
index f028719bfe1..93f551178c3 100644
--- a/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml
+++ b/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml
@@ -8,8 +8,7 @@ product_stage: package
product_group: group::package
product_category: package registry
value_type: number
-status: broken
-repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331455
+status: active
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml b/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml
index 8ce25e2d976..29ec7855453 100644
--- a/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml
+++ b/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml
@@ -7,6 +7,7 @@ product_section:
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
milestone: "13.12"
diff --git a/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml b/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml
index b287346496b..dceee0cc3ff 100644
--- a/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml
+++ b/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml
@@ -7,6 +7,7 @@ product_section:
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
milestone: "13.12"
diff --git a/config/metrics/counts_28d/20210929102434_p_ci_templates_implicit_jobs_build_monthly.yml b/config/metrics/counts_28d/20210929102434_p_ci_templates_implicit_jobs_build_monthly.yml
index 4fa6d3d8843..a923fd255b7 100644
--- a/config/metrics/counts_28d/20210929102434_p_ci_templates_implicit_jobs_build_monthly.yml
+++ b/config/metrics/counts_28d/20210929102434_p_ci_templates_implicit_jobs_build_monthly.yml
@@ -9,7 +9,7 @@ value_type: number
status: active
milestone: "14.4"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71157
-time_frame: 7d
+time_frame: 28d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20210929102736_p_ci_templates_implicit_jobs_deploy_latest_monthly.yml b/config/metrics/counts_28d/20210929102736_p_ci_templates_implicit_jobs_deploy_latest_monthly.yml
index 9d19a6ffa72..28ed156f483 100644
--- a/config/metrics/counts_28d/20210929102736_p_ci_templates_implicit_jobs_deploy_latest_monthly.yml
+++ b/config/metrics/counts_28d/20210929102736_p_ci_templates_implicit_jobs_deploy_latest_monthly.yml
@@ -9,7 +9,7 @@ value_type: number
status: active
milestone: "14.4"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71157
-time_frame: 7d
+time_frame: 28d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20210929103010_p_ci_templates_implicit_jobs_deploy_monthly.yml b/config/metrics/counts_28d/20210929103010_p_ci_templates_implicit_jobs_deploy_monthly.yml
index 5b7b7924c4a..13f3bb050db 100644
--- a/config/metrics/counts_28d/20210929103010_p_ci_templates_implicit_jobs_deploy_monthly.yml
+++ b/config/metrics/counts_28d/20210929103010_p_ci_templates_implicit_jobs_deploy_monthly.yml
@@ -9,7 +9,7 @@ value_type: number
status: active
milestone: "14.4"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71157
-time_frame: 7d
+time_frame: 28d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20211015154445_p_ci_templates_kaniko_monthly.yml b/config/metrics/counts_28d/20211015154445_p_ci_templates_kaniko_monthly.yml
new file mode 100644
index 00000000000..1278c880072
--- /dev/null
+++ b/config/metrics/counts_28d/20211015154445_p_ci_templates_kaniko_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_kaniko_monthly
+description: ''
+product_section: ops
+product_stage: verify
+product_group: group::pipeline authoring
+product_category: pipeline_authoring
+value_type: number
+status: active
+milestone: '14.3'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72400
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
+options:
+ events:
+ - p_ci_templates_kaniko
diff --git a/config/metrics/counts_28d/20211102141250_i_quickactions_promote_to_incident_monthly.yml b/config/metrics/counts_28d/20211102141250_i_quickactions_promote_to_incident_monthly.yml
new file mode 100644
index 00000000000..76f24633869
--- /dev/null
+++ b/config/metrics/counts_28d/20211102141250_i_quickactions_promote_to_incident_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_promote_to_incident_monthly
+description: Count of MAU using the `/promote_to_incident` quick action
+product_section: ops
+product_stage: monitor
+product_group: group::monitor
+product_category: incident_management
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73992
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_promote_to_incident
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20211102205024_p_ci_templates_security_sast_iac_latest_monthly.yml b/config/metrics/counts_28d/20211102205024_p_ci_templates_security_sast_iac_latest_monthly.yml
new file mode 100644
index 00000000000..c9589f3ff29
--- /dev/null
+++ b/config/metrics/counts_28d/20211102205024_p_ci_templates_security_sast_iac_latest_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_security_sast_iac_latest_monthly
+description: Count of pipelines using the latest SAST IaC template
+product_section: sec
+product_stage: secure
+product_group: "group::static analysis"
+product_category: SAST
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73076
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_security_sast_iac_latest
diff --git a/config/metrics/counts_28d/20211102205223_p_ci_templates_implicit_security_sast_iac_latest_monthly.yml b/config/metrics/counts_28d/20211102205223_p_ci_templates_implicit_security_sast_iac_latest_monthly.yml
new file mode 100644
index 00000000000..9e5724b1e40
--- /dev/null
+++ b/config/metrics/counts_28d/20211102205223_p_ci_templates_implicit_security_sast_iac_latest_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_sast_iac_latest_monthly
+description: Count of pipelines with implicit runs using the latest SAST IaC template
+product_section: sec
+product_stage: secure
+product_group: "group::static analysis"
+product_category: SAST
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73076
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_implicit_security_sast_iac_latest
diff --git a/config/metrics/counts_28d/20211102213704_p_ci_templates_jobs_sast_iac_latest_monthly.yml b/config/metrics/counts_28d/20211102213704_p_ci_templates_jobs_sast_iac_latest_monthly.yml
new file mode 100644
index 00000000000..40aa9cdbab1
--- /dev/null
+++ b/config/metrics/counts_28d/20211102213704_p_ci_templates_jobs_sast_iac_latest_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_sast_iac_latest_monthly
+description: Count of pipelines using the latest SAST IaC template
+product_section: sec
+product_stage: secure
+product_group: "group::static analysis"
+product_category: SAST
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73074
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_jobs_sast_iac_latest
diff --git a/config/metrics/counts_28d/20211102213921_p_ci_templates_implicit_jobs_sast_iac_latest_monthly.yml b/config/metrics/counts_28d/20211102213921_p_ci_templates_implicit_jobs_sast_iac_latest_monthly.yml
new file mode 100644
index 00000000000..3fa3c751366
--- /dev/null
+++ b/config/metrics/counts_28d/20211102213921_p_ci_templates_implicit_jobs_sast_iac_latest_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_sast_iac_latest_monthly
+description: Count of pipelines with implicit runs using the latest SAST IaC template
+product_section: sec
+product_stage: secure
+product_group: "group::static analysis"
+product_category: SAST
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73074
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_implicit_jobs_sast_iac_latest
diff --git a/config/metrics/counts_28d/20211104154357_i_code_review_widget_nothing_merge_click_new_file_monthly.yml b/config/metrics/counts_28d/20211104154357_i_code_review_widget_nothing_merge_click_new_file_monthly.yml
new file mode 100644
index 00000000000..1aa0edf60e6
--- /dev/null
+++ b/config/metrics/counts_28d/20211104154357_i_code_review_widget_nothing_merge_click_new_file_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_widget_nothing_merge_click_new_file_monthly
+description: Count of users who click the create file button in the nothing to merge widget state
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url:
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_widget_nothing_merge_click_new_file
+data_category: optional
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20211111162103_i_code_review_post_merge_delete_branch_monthly.yml b/config/metrics/counts_28d/20211111162103_i_code_review_post_merge_delete_branch_monthly.yml
new file mode 100644
index 00000000000..8bdad9d6837
--- /dev/null
+++ b/config/metrics/counts_28d/20211111162103_i_code_review_post_merge_delete_branch_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_post_merge_delete_branch_monthly
+description: Count of users who click the delete source branch button after merge
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url:
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_post_merge_delete_branch
+data_category: optional
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20211111162422_i_code_review_post_merge_click_revert_monthly.yml b/config/metrics/counts_28d/20211111162422_i_code_review_post_merge_click_revert_monthly.yml
new file mode 100644
index 00000000000..aac7e359887
--- /dev/null
+++ b/config/metrics/counts_28d/20211111162422_i_code_review_post_merge_click_revert_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_post_merge_click_revert_monthly
+description: Count of users who click the revert button in the merge requet widget
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url:
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_post_merge_click_revert
+data_category: optional
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20211112102446_i_code_review_post_merge_click_cherry_pick_monthly.yml b/config/metrics/counts_28d/20211112102446_i_code_review_post_merge_click_cherry_pick_monthly.yml
new file mode 100644
index 00000000000..cb0eb0e9b34
--- /dev/null
+++ b/config/metrics/counts_28d/20211112102446_i_code_review_post_merge_click_cherry_pick_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_post_merge_click_cherry_pick_monthly
+description: Count of users who click the cherry pick button in the merge requet widget
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url:
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_post_merge_click_cherry_pick
+data_category: optional
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20211112114333_i_code_review_post_merge_submit_revert_modal_monthly.yml b/config/metrics/counts_28d/20211112114333_i_code_review_post_merge_submit_revert_modal_monthly.yml
new file mode 100644
index 00000000000..8e20f87ee29
--- /dev/null
+++ b/config/metrics/counts_28d/20211112114333_i_code_review_post_merge_submit_revert_modal_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_post_merge_submit_revert_modal_monthly
+description: Count of users who submit the post merge revert modal
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url:
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_post_merge_submit_revert_modal
+data_category: optional
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20211112115144_i_code_review_post_merge_submit_cherry_pick_modal_monthly.yml b/config/metrics/counts_28d/20211112115144_i_code_review_post_merge_submit_cherry_pick_modal_monthly.yml
new file mode 100644
index 00000000000..e1492156507
--- /dev/null
+++ b/config/metrics/counts_28d/20211112115144_i_code_review_post_merge_submit_cherry_pick_modal_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_post_merge_submit_cherry_pick_modal_monthly
+description: Count of users who submit the post merge revert modal
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url:
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_post_merge_submit_cherry_pick_modal
+data_category: optional
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml b/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml
index 2a1a174f5a5..36097c13951 100644
--- a/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml
+++ b/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml
@@ -5,6 +5,7 @@ description: Count of WAU editing an issue title
product_stage: plan
product_group: group::project management
product_category: issue_tracking
+product_section: 'TBD'
value_type: number
status: active
milestone: "13.6"
diff --git a/config/metrics/counts_7d/20210216181347_g_project_management_issue_cross_referenced_weekly.yml b/config/metrics/counts_7d/20210216181347_g_project_management_issue_cross_referenced_weekly.yml
index 13094d1f7fd..d74794c08c7 100644
--- a/config/metrics/counts_7d/20210216181347_g_project_management_issue_cross_referenced_weekly.yml
+++ b/config/metrics/counts_7d/20210216181347_g_project_management_issue_cross_referenced_weekly.yml
@@ -8,7 +8,7 @@ product_group: group::project management
product_category: issue_tracking
value_type: number
status: active
-time_frame: 28d
+time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
options:
diff --git a/config/metrics/counts_7d/20210216184310_i_code_review_user_toggled_task_item_status_weekly.yml b/config/metrics/counts_7d/20210216184310_i_code_review_user_toggled_task_item_status_weekly.yml
index 892bafaadd6..78d489712bb 100644
--- a/config/metrics/counts_7d/20210216184310_i_code_review_user_toggled_task_item_status_weekly.yml
+++ b/config/metrics/counts_7d/20210216184310_i_code_review_user_toggled_task_item_status_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who toggled a task item in a merge r
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184320_i_code_review_user_approve_mr_weekly.yml b/config/metrics/counts_7d/20210216184320_i_code_review_user_approve_mr_weekly.yml
index 6f4de7ac49e..50a616d3156 100644
--- a/config/metrics/counts_7d/20210216184320_i_code_review_user_approve_mr_weekly.yml
+++ b/config/metrics/counts_7d/20210216184320_i_code_review_user_approve_mr_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who approve a merge request
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184324_i_code_review_user_unapprove_mr_weekly.yml b/config/metrics/counts_7d/20210216184324_i_code_review_user_unapprove_mr_weekly.yml
index 756bbea7657..341178587c9 100644
--- a/config/metrics/counts_7d/20210216184324_i_code_review_user_unapprove_mr_weekly.yml
+++ b/config/metrics/counts_7d/20210216184324_i_code_review_user_unapprove_mr_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who unapprove a merge request
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184328_i_code_review_user_resolve_thread_weekly.yml b/config/metrics/counts_7d/20210216184328_i_code_review_user_resolve_thread_weekly.yml
index 7cff71aa29c..bb80932f86b 100644
--- a/config/metrics/counts_7d/20210216184328_i_code_review_user_resolve_thread_weekly.yml
+++ b/config/metrics/counts_7d/20210216184328_i_code_review_user_resolve_thread_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who resolve a thread in a merge requ
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184332_i_code_review_user_unresolve_thread_weekly.yml b/config/metrics/counts_7d/20210216184332_i_code_review_user_unresolve_thread_weekly.yml
index 20171f95fd3..1d91fa77e0c 100644
--- a/config/metrics/counts_7d/20210216184332_i_code_review_user_unresolve_thread_weekly.yml
+++ b/config/metrics/counts_7d/20210216184332_i_code_review_user_unresolve_thread_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who unresolve a thread in a merge re
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184336_i_code_review_edit_mr_title_weekly.yml b/config/metrics/counts_7d/20210216184336_i_code_review_edit_mr_title_weekly.yml
index 5e56eaaa837..bb2ebfc942b 100644
--- a/config/metrics/counts_7d/20210216184336_i_code_review_edit_mr_title_weekly.yml
+++ b/config/metrics/counts_7d/20210216184336_i_code_review_edit_mr_title_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who edit the title of a merge reques
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184340_i_code_review_edit_mr_desc_weekly.yml b/config/metrics/counts_7d/20210216184340_i_code_review_edit_mr_desc_weekly.yml
index 3c7a7f7d82a..64de1c4ef82 100644
--- a/config/metrics/counts_7d/20210216184340_i_code_review_edit_mr_desc_weekly.yml
+++ b/config/metrics/counts_7d/20210216184340_i_code_review_edit_mr_desc_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who edit the description of a merge
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184351_i_code_review_user_create_review_note_weekly.yml b/config/metrics/counts_7d/20210216184351_i_code_review_user_create_review_note_weekly.yml
index 6b91ab4102f..731c07d4fad 100644
--- a/config/metrics/counts_7d/20210216184351_i_code_review_user_create_review_note_weekly.yml
+++ b/config/metrics/counts_7d/20210216184351_i_code_review_user_create_review_note_weekly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per week who create a note as part of a merge
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184355_i_code_review_user_publish_review_weekly.yml b/config/metrics/counts_7d/20210216184355_i_code_review_user_publish_review_weekly.yml
index 20c4c9cef5e..d036350ef9d 100644
--- a/config/metrics/counts_7d/20210216184355_i_code_review_user_publish_review_weekly.yml
+++ b/config/metrics/counts_7d/20210216184355_i_code_review_user_publish_review_weekly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per week who publish their review as part of
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184359_i_code_review_user_create_multiline_mr_comment_weekly.yml b/config/metrics/counts_7d/20210216184359_i_code_review_user_create_multiline_mr_comment_weekly.yml
index 26300d52dce..b90e46a5cd8 100644
--- a/config/metrics/counts_7d/20210216184359_i_code_review_user_create_multiline_mr_comment_weekly.yml
+++ b/config/metrics/counts_7d/20210216184359_i_code_review_user_create_multiline_mr_comment_weekly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per week who create a multiline comment in a
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184403_i_code_review_user_edit_multiline_mr_comment_weekly.yml b/config/metrics/counts_7d/20210216184403_i_code_review_user_edit_multiline_mr_comment_weekly.yml
index 2cbae1dff37..5efcda783ff 100644
--- a/config/metrics/counts_7d/20210216184403_i_code_review_user_edit_multiline_mr_comment_weekly.yml
+++ b/config/metrics/counts_7d/20210216184403_i_code_review_user_edit_multiline_mr_comment_weekly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per week who edit a multiline comment in a me
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184407_i_code_review_user_remove_multiline_mr_comment_weekly.yml b/config/metrics/counts_7d/20210216184407_i_code_review_user_remove_multiline_mr_comment_weekly.yml
index 1d80969f63a..71f051f10ee 100644
--- a/config/metrics/counts_7d/20210216184407_i_code_review_user_remove_multiline_mr_comment_weekly.yml
+++ b/config/metrics/counts_7d/20210216184407_i_code_review_user_remove_multiline_mr_comment_weekly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per week who remove a multiline comment in a
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184416_i_code_review_user_assigned_weekly.yml b/config/metrics/counts_7d/20210216184416_i_code_review_user_assigned_weekly.yml
index 741f8ff83fc..2bef437e3d0 100644
--- a/config/metrics/counts_7d/20210216184416_i_code_review_user_assigned_weekly.yml
+++ b/config/metrics/counts_7d/20210216184416_i_code_review_user_assigned_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who are assigned to a merge request
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184420_i_code_review_user_marked_as_draft_weekly.yml b/config/metrics/counts_7d/20210216184420_i_code_review_user_marked_as_draft_weekly.yml
index 960a9b18987..28bfd16ef6f 100644
--- a/config/metrics/counts_7d/20210216184420_i_code_review_user_marked_as_draft_weekly.yml
+++ b/config/metrics/counts_7d/20210216184420_i_code_review_user_marked_as_draft_weekly.yml
@@ -4,6 +4,7 @@ key_path: redis_hll_counters.code_review.i_code_review_user_marked_as_draft_week
description: Count of unique users per week who mark a merge request as a draft
product_stage: create
product_group: group::code review
+product_section: 'TBD'
product_category: code_review
value_type: number
status: active
diff --git a/config/metrics/counts_7d/20210216184424_i_code_review_user_unmarked_as_draft_weekly.yml b/config/metrics/counts_7d/20210216184424_i_code_review_user_unmarked_as_draft_weekly.yml
index 76a7a4a97ab..4c2944cf0c1 100644
--- a/config/metrics/counts_7d/20210216184424_i_code_review_user_unmarked_as_draft_weekly.yml
+++ b/config/metrics/counts_7d/20210216184424_i_code_review_user_unmarked_as_draft_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who unmark a merge request as a draf
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184428_i_code_review_user_review_requested_weekly.yml b/config/metrics/counts_7d/20210216184428_i_code_review_user_review_requested_weekly.yml
index 70b88e97e20..57381e15a19 100644
--- a/config/metrics/counts_7d/20210216184428_i_code_review_user_review_requested_weekly.yml
+++ b/config/metrics/counts_7d/20210216184428_i_code_review_user_review_requested_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who request a review of a merge requ
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184432_i_code_review_user_approval_rule_added_weekly.yml b/config/metrics/counts_7d/20210216184432_i_code_review_user_approval_rule_added_weekly.yml
index 038f53b62a9..b38faa983c7 100644
--- a/config/metrics/counts_7d/20210216184432_i_code_review_user_approval_rule_added_weekly.yml
+++ b/config/metrics/counts_7d/20210216184432_i_code_review_user_approval_rule_added_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who add an approval rule to a merge
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184436_i_code_review_user_approval_rule_deleted_weekly.yml b/config/metrics/counts_7d/20210216184436_i_code_review_user_approval_rule_deleted_weekly.yml
index 8a7b2c31194..02fe4cc5993 100644
--- a/config/metrics/counts_7d/20210216184436_i_code_review_user_approval_rule_deleted_weekly.yml
+++ b/config/metrics/counts_7d/20210216184436_i_code_review_user_approval_rule_deleted_weekly.yml
@@ -6,6 +6,7 @@ description: Count of unique users per week who delete an approval rule to a mer
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184440_i_code_review_user_approval_rule_edited_weekly.yml b/config/metrics/counts_7d/20210216184440_i_code_review_user_approval_rule_edited_weekly.yml
index b5831569160..58b569521bb 100644
--- a/config/metrics/counts_7d/20210216184440_i_code_review_user_approval_rule_edited_weekly.yml
+++ b/config/metrics/counts_7d/20210216184440_i_code_review_user_approval_rule_edited_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who edit an approval rule to a merge
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184444_i_code_review_user_vs_code_api_request_weekly.yml b/config/metrics/counts_7d/20210216184444_i_code_review_user_vs_code_api_request_weekly.yml
index cab4aa62b43..3e3668df67d 100644
--- a/config/metrics/counts_7d/20210216184444_i_code_review_user_vs_code_api_request_weekly.yml
+++ b/config/metrics/counts_7d/20210216184444_i_code_review_user_vs_code_api_request_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who use GitLab Workflow for VS Code
product_stage: create
product_group: group::code review
product_category: editor_extension
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184448_i_code_review_user_create_mr_from_issue_weekly.yml b/config/metrics/counts_7d/20210216184448_i_code_review_user_create_mr_from_issue_weekly.yml
index 53a18b79605..7cf0936e79f 100644
--- a/config/metrics/counts_7d/20210216184448_i_code_review_user_create_mr_from_issue_weekly.yml
+++ b/config/metrics/counts_7d/20210216184448_i_code_review_user_create_mr_from_issue_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who create a merge request from an i
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml
index 24f82a6a442..eb62bf37a70 100644
--- a/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml
@@ -5,6 +5,7 @@ description: Count of unique users per week who interact with a merge request
product_stage: create
product_group: group::code review
product_category: code_review
+product_section: 'TBD'
value_type: number
status: active
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
index cf0e69c6da2..31813735ea4 100644
--- a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
@@ -159,6 +159,7 @@ options:
- p_ci_templates_implicit_security_api_fuzzing
- p_ci_templates_implicit_security_dast
- p_ci_templates_implicit_security_cluster_image_scanning
+ - p_ci_templates_kaniko
distribution:
- ce
- ee
diff --git a/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml b/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml
index 63278bcfbd8..d529d1c2f38 100644
--- a/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml
+++ b/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml
@@ -8,8 +8,7 @@ product_stage: package
product_group: group::package
product_category: package registry
value_type: number
-status: broken
-repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331455
+status: active
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml b/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml
index 1402f3fd574..a8449bad161 100644
--- a/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml
+++ b/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: redis_hll_counters.code_review.i_code_review_user_load_conflict_ui_weekly
name: load_conflict_ui
description: Count of unique users per week who load the conflict resolution page
-product_section:
+product_section: 'TBD'
product_stage: create
product_group: group::code review
product_category: code_review
diff --git a/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml b/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml
index a60f6a23a76..b25ed55bae1 100644
--- a/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml
+++ b/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml
@@ -3,14 +3,14 @@ data_category: optional
key_path: redis_hll_counters.code_review.i_code_review_user_resolve_conflict_weekly
name: resolve_conflict
description: Count of unique users per week who attempt to resolve a conflict through the ui
-product_section:
+product_section: 'TBD'
product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
status: active
milestone: "13.12"
-time_frame: 28d
+time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
options:
diff --git a/config/metrics/counts_7d/20211015154445_p_ci_templates_kaniko_weekly.yml b/config/metrics/counts_7d/20211015154445_p_ci_templates_kaniko_weekly.yml
new file mode 100644
index 00000000000..f101eefc933
--- /dev/null
+++ b/config/metrics/counts_7d/20211015154445_p_ci_templates_kaniko_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_kaniko_weekly
+description: ''
+product_section: ops
+product_stage: release
+product_group: group::release
+product_category: continuous_delivery
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72400
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
+options:
+ events:
+ - p_ci_templates_kaniko
diff --git a/config/metrics/counts_7d/20211102141244_i_quickactions_promote_to_incident_weekly.yml b/config/metrics/counts_7d/20211102141244_i_quickactions_promote_to_incident_weekly.yml
new file mode 100644
index 00000000000..a3ca5d70089
--- /dev/null
+++ b/config/metrics/counts_7d/20211102141244_i_quickactions_promote_to_incident_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_promote_to_incident_weekly
+description: Count of WAU using the `/severity` quick action
+product_section: ops
+product_stage: monitor
+product_group: group::monitor
+product_category: incident_management
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73992
+time_frame: 7d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_promote_to_incident
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20211102202454_p_ci_templates_security_sast_iac_latest_weekly.yml b/config/metrics/counts_7d/20211102202454_p_ci_templates_security_sast_iac_latest_weekly.yml
new file mode 100644
index 00000000000..e7e2c096902
--- /dev/null
+++ b/config/metrics/counts_7d/20211102202454_p_ci_templates_security_sast_iac_latest_weekly.yml
@@ -0,0 +1,27 @@
+---
+data_category: optional
+key_path: redis_hll_counters.ci_templates.p_ci_templates_security_sast_iac_latest_weekly
+description: Count of pipelines using the latest SAST IaC template
+product_section: sec
+product_stage: secure
+product_group: "group::static analysis"
+product_category: SAST
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73076
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_security_sast_iac_latest
diff --git a/config/metrics/counts_7d/20211102204352_p_ci_templates_implicit_security_sast_iac_latest_weekly.yml b/config/metrics/counts_7d/20211102204352_p_ci_templates_implicit_security_sast_iac_latest_weekly.yml
new file mode 100644
index 00000000000..09070adb2c1
--- /dev/null
+++ b/config/metrics/counts_7d/20211102204352_p_ci_templates_implicit_security_sast_iac_latest_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_sast_iac_latest_weekly
+description: Count of pipelines with implicit runs using the latest SAST IaC template
+product_section: sec
+product_stage: secure
+product_group: "group::static analysis"
+product_category: SAST
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73076
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_implicit_security_sast_iac_latest
diff --git a/config/metrics/counts_7d/20211102213112_p_ci_templates_jobs_sast_iac_latest_weekly.yml b/config/metrics/counts_7d/20211102213112_p_ci_templates_jobs_sast_iac_latest_weekly.yml
new file mode 100644
index 00000000000..3fdd37bffa5
--- /dev/null
+++ b/config/metrics/counts_7d/20211102213112_p_ci_templates_jobs_sast_iac_latest_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_sast_iac_latest_weekly
+description: Count of pipelines using the latest SAST IaC template
+product_section: sec
+product_stage: secure
+product_group: "group::static analysis"
+product_category: SAST
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73074
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_jobs_sast_iac_latest
diff --git a/config/metrics/counts_7d/20211102213417_p_ci_templates_implicit_jobs_sast_iac_latest_weekly.yml b/config/metrics/counts_7d/20211102213417_p_ci_templates_implicit_jobs_sast_iac_latest_weekly.yml
new file mode 100644
index 00000000000..3a58cd033f2
--- /dev/null
+++ b/config/metrics/counts_7d/20211102213417_p_ci_templates_implicit_jobs_sast_iac_latest_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_sast_iac_latest_weekly
+description: Count of pipelines with implicit runs using the latest SAST IaC template
+product_section: sec
+product_stage: secure
+product_group: "group::static analysis"
+product_category: SAST
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73074
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_implicit_jobs_sast_iac_latest
diff --git a/config/metrics/counts_7d/20211104154352_i_code_review_widget_nothing_merge_click_new_file_weekly.yml b/config/metrics/counts_7d/20211104154352_i_code_review_widget_nothing_merge_click_new_file_weekly.yml
new file mode 100644
index 00000000000..9f8ae151a80
--- /dev/null
+++ b/config/metrics/counts_7d/20211104154352_i_code_review_widget_nothing_merge_click_new_file_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_widget_nothing_merge_click_new_file_weekly
+description: Count of users who click the create file button in the nothing to merge widget state
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url:
+time_frame: 7d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_widget_nothing_merge_click_new_file
+data_category: optional
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20211111162058_i_code_review_post_merge_delete_branch_weekly.yml b/config/metrics/counts_7d/20211111162058_i_code_review_post_merge_delete_branch_weekly.yml
new file mode 100644
index 00000000000..f6cd1f6a86b
--- /dev/null
+++ b/config/metrics/counts_7d/20211111162058_i_code_review_post_merge_delete_branch_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_post_merge_delete_branch_weekly
+description: Count of users who click the delete source branch button after merge
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url:
+time_frame: 7d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_post_merge_delete_branch
+data_category: optional
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20211111162417_i_code_review_post_merge_click_revert_weekly.yml b/config/metrics/counts_7d/20211111162417_i_code_review_post_merge_click_revert_weekly.yml
new file mode 100644
index 00000000000..70f968fcc0e
--- /dev/null
+++ b/config/metrics/counts_7d/20211111162417_i_code_review_post_merge_click_revert_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_post_merge_click_revert_weekly
+description: Count of users who click the revert button in the merge requet widget
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url:
+time_frame: 7d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_post_merge_click_revert
+data_category: optional
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20211112102440_i_code_review_post_merge_click_cherry_pick_weekly.yml b/config/metrics/counts_7d/20211112102440_i_code_review_post_merge_click_cherry_pick_weekly.yml
new file mode 100644
index 00000000000..90428f31a7a
--- /dev/null
+++ b/config/metrics/counts_7d/20211112102440_i_code_review_post_merge_click_cherry_pick_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_post_merge_click_cherry_pick_weekly
+description: Count of users who click the cherry pick button in the merge requet widget
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url:
+time_frame: 7d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_post_merge_click_cherry_pick
+data_category: optional
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20211112114327_i_code_review_post_merge_submit_revert_modal_weekly.yml b/config/metrics/counts_7d/20211112114327_i_code_review_post_merge_submit_revert_modal_weekly.yml
new file mode 100644
index 00000000000..ea7238e9913
--- /dev/null
+++ b/config/metrics/counts_7d/20211112114327_i_code_review_post_merge_submit_revert_modal_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_post_merge_submit_revert_modal_weekly
+description: Count of users who submit the post merge revert modal
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url:
+time_frame: 7d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_post_merge_submit_revert_modal
+data_category: optional
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20211112115138_i_code_review_post_merge_submit_cherry_pick_modal_weekly.yml b/config/metrics/counts_7d/20211112115138_i_code_review_post_merge_submit_cherry_pick_modal_weekly.yml
new file mode 100644
index 00000000000..ac8649eef80
--- /dev/null
+++ b/config/metrics/counts_7d/20211112115138_i_code_review_post_merge_submit_cherry_pick_modal_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_post_merge_submit_cherry_pick_modal_weekly
+description: Count of users who submit the post merge revert modal
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url:
+time_frame: 7d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_post_merge_submit_cherry_pick_modal
+data_category: optional
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_all/20210216174902_g_analytics_merge_request.yml b/config/metrics/counts_all/20210216174902_g_analytics_merge_request.yml
index c15990a9309..af9338f028a 100644
--- a/config/metrics/counts_all/20210216174902_g_analytics_merge_request.yml
+++ b/config/metrics/counts_all/20210216174902_g_analytics_merge_request.yml
@@ -8,7 +8,7 @@ product_group: group::optimize
product_category:
value_type: number
status: removed
-time_frame: 7d
+time_frame: all
data_source: redis_hll
distribution:
- ce
diff --git a/config/metrics/counts_all/20210216175316_kubernetes_agents.yml b/config/metrics/counts_all/20210216175316_kubernetes_agents.yml
new file mode 100644
index 00000000000..f126415a78f
--- /dev/null
+++ b/config/metrics/counts_all/20210216175316_kubernetes_agents.yml
@@ -0,0 +1,21 @@
+---
+data_category: optional
+key_path: counts.kubernetes_agents
+description: Count of Kubernetes registered agents
+product_section: ops
+product_stage: configure
+product_group: group::configure
+product_category: kubernetes_management
+value_type: number
+status: active
+time_frame: all
+data_source: database
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+performance_indicator_type: []
+milestone: "<13.9"
diff --git a/config/metrics/counts_all/20210216175318_kubernetes_agents_with_token.yml b/config/metrics/counts_all/20210216175318_kubernetes_agents_with_token.yml
new file mode 100644
index 00000000000..6cbdb1679a5
--- /dev/null
+++ b/config/metrics/counts_all/20210216175318_kubernetes_agents_with_token.yml
@@ -0,0 +1,21 @@
+---
+data_category: optional
+key_path: counts.kubernetes_agents_with_token
+description: Count of Kubernetes agents with at least one token
+product_section: ops
+product_stage: configure
+product_group: group::configure
+product_category: kubernetes_management
+value_type: number
+status: active
+time_frame: all
+data_source: database
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+performance_indicator_type: []
+milestone: "<13.9"
diff --git a/config/metrics/counts_all/20210216180754_events.yml b/config/metrics/counts_all/20210216180754_events.yml
index 1dfeadbbdfe..dce6352d266 100644
--- a/config/metrics/counts_all/20210216180754_events.yml
+++ b/config/metrics/counts_all/20210216180754_events.yml
@@ -7,7 +7,8 @@ product_stage: manage
product_group: group::manage
product_category:
value_type: number
-status: active
+status: broken
+repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344100
time_frame: all
data_source: database
distribution:
diff --git a/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml b/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml
new file mode 100644
index 00000000000..e558763e2a0
--- /dev/null
+++ b/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml
@@ -0,0 +1,22 @@
+---
+data_category: optional
+key_path: counts.kubernetes_agent_k8s_api_proxy_request
+description: Count of Kubernetes API proxy requests
+product_section: ops
+product_stage: configure
+product_group: group::configure
+product_category: kubernetes_management
+value_type: number
+status: active
+milestone: '13.12'
+introduced_by_url:
+time_frame: all
+data_source: redis
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+performance_indicator_type: []
diff --git a/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml b/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml
index 1f505694535..c201b4c79ee 100644
--- a/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml
+++ b/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_create_0_sent
name: "count_sent_first_email_of_the_create_track_for_in_product_marketing_emails"
description: Total sent emails of the create track's first email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml b/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml
index fb2bd8f59e0..cb5f3185eb0 100644
--- a/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_create_0_cta_clicked
name: "count_clicks_on_the_first_email_of_the_create_track_for_in_product_marketing_emails"
description: Total clicks on the create track's first email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml b/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml
index 13587d77e9a..2b849be1c32 100644
--- a/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml
+++ b/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_create_1_sent
name: "count_sent_second_email_of_the_create_track_for_in_product_marketing_emails"
description: Total sent emails of the create track's second email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml b/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml
index e5635ba3d92..ab50a629468 100644
--- a/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_create_1_cta_clicked
name: "count_clicks_on_the_second_email_of_the_create_track_for_in_product_marketing_emails"
description: Total clicks on the create track's second email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml b/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml
index 10fb21997d3..72a1d56cab2 100644
--- a/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml
+++ b/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_create_2_sent
name: "count_sent_third_email_of_the_create_track_for_in_product_marketing_emails"
description: Total sent emails of the create track's third email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml b/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml
index 21841bfe7ba..17dcf4286ac 100644
--- a/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_create_2_cta_clicked
name: "count_clicks_on_the_third_email_of_the_create_track_for_in_product_marketing_emails"
description: Total clicks on the create track's third email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml b/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml
index 66d894a62a9..c504783a652 100644
--- a/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml
+++ b/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_verify_0_sent
name: "count_sent_first_email_of_the_verify_track_for_in_product_marketing_emails"
description: Total sent emails of the verify track's first email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml b/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml
index 39d02b343e5..cb316eb3164 100644
--- a/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_verify_0_cta_clicked
name: "count_clicks_on_the_first_email_of_the_verify_track_for_in_product_marketing_emails"
description: Total clicks on the verify track's first email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml b/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml
index dcd61e22ab3..e4d1e90bb22 100644
--- a/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml
+++ b/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_verify_1_sent
name: "count_sent_second_email_of_the_verify_track_for_in_product_marketing_emails"
description: Total sent emails of the verify track's second email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml b/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml
index 359eb181926..2b08899e228 100644
--- a/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_verify_1_cta_clicked
name: "count_clicks_on_the_second_email_of_the_verify_track_for_in_product_marketing_emails"
description: Total clicks on the verify track's second email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml b/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml
index b0263ce11ed..33c77609b6f 100644
--- a/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml
+++ b/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_verify_2_sent
name: "count_sent_third_email_of_the_verify_track_for_in_product_marketing_emails"
description: Total sent emails of the verify track's third email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml b/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml
index ba0e6ad9753..0cd780b53ed 100644
--- a/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_verify_2_cta_clicked
name: "count_clicks_on_the_third_email_of_the_verify_track_for_in_product_marketing_emails"
description: Total clicks on the verify track's third email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml b/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml
index 843b1de808f..70c1e3d1250 100644
--- a/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml
+++ b/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_trial_0_sent
name: "count_sent_first_email_of_the_trial_track_for_in_product_marketing_emails"
description: Total sent emails of the trial track's first email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml b/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml
index 82832d991ee..258273438e3 100644
--- a/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_trial_0_cta_clicked
name: "count_clicks_on_the_first_email_of_the_trial_track_for_in_product_marketing_emails"
description: Total clicks on the verify trial's first email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml b/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml
index 2393643bacc..f32440ca1ae 100644
--- a/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml
+++ b/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_trial_1_sent
name: "count_sent_second_email_of_the_trial_track_for_in_product_marketing_emails"
description: Total sent emails of the trial track's second email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml b/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml
index cb72d9bb8f5..67543b98020 100644
--- a/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_trial_1_cta_clicked
name: "count_clicks_on_the_second_email_of_the_trial_track_for_in_product_marketing_emails"
description: Total clicks on the trial track's second email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml b/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml
index b1ae09410d1..185d5bb3aee 100644
--- a/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml
+++ b/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_trial_2_sent
name: "count_sent_third_email_of_the_trial_track_for_in_product_marketing_emails"
description: Total sent emails of the trial track's third email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml b/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml
index a5714e17223..f3a54e2ae31 100644
--- a/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_trial_2_cta_clicked
name: "count_clicks_on_the_third_email_of_the_trial_track_for_in_product_marketing_emails"
description: Total clicks on the trial track's third email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml b/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml
index beb6c6b9ecc..07b61f70b2e 100644
--- a/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml
+++ b/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_team_0_sent
name: "count_sent_first_email_of_the_trial_team_for_in_product_marketing_emails"
description: Total sent emails of the team track's first email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml b/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml
index 331639ca54f..27d47aff9c3 100644
--- a/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_team_0_cta_clicked
name: "count_clicks_on_the_first_email_of_the_team_track_for_in_product_marketing_emails"
description: Total clicks on the team track's first email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml b/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml
index afa2854b0f9..daba149d6c5 100644
--- a/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml
+++ b/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_team_1_sent
name: "count_sent_second_email_of_the_team_track_for_in_product_marketing_emails"
description: Total sent emails of the team track's second email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml b/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml
index 0bac5ef76b7..3d5150f6042 100644
--- a/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_team_1_cta_clicked
name: "count_clicks_on_the_second_email_of_the_team_track_for_in_product_marketing_emails"
description: Total clicks on the team track's second email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml b/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml
index fe0770d900b..aaaecb85e74 100644
--- a/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml
+++ b/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_team_2_sent
name: "count_sent_third_email_of_the_team_track_for_in_product_marketing_emails"
description: Total sent emails of the team track's third email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml b/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml
index 3fe16910ae5..0618ca56e89 100644
--- a/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml
+++ b/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_team_2_cta_clicked
name: "count_clicks_on_the_third_email_of_the_team_track_for_in_product_marketing_emails"
description: Total clicks on the team track's third email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml b/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml
index 17c5b1a48c4..d4b2f57f3a4 100644
--- a/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml
+++ b/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.in_product_marketing_email_experience_0_sent
name: "count_sent_first_email_of_the_experience_track_for_in_product_marketing_emails"
description: Total sent emails of the experience track's first email
-product_section:
+product_section: 'TBD'
product_stage: growth
product_group: group::activation
product_category: onboarding
diff --git a/config/metrics/counts_all/20210715094459_releases_with_milestones.yml b/config/metrics/counts_all/20210715094459_releases_with_milestones.yml
index 5d853604580..0be5497e561 100644
--- a/config/metrics/counts_all/20210715094459_releases_with_milestones.yml
+++ b/config/metrics/counts_all/20210715094459_releases_with_milestones.yml
@@ -10,7 +10,7 @@ value_type: number
status: active
milestone: "14.4"
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71287'
-time_frame: 28d
+time_frame: all
data_source: database
instrumentation_class: 'CountUsersAssociatingMilestonesToReleasesMetric'
data_category: Optional
diff --git a/config/metrics/counts_all/20210730011801_projects_zentao_active.yml b/config/metrics/counts_all/20210730011801_projects_zentao_active.yml
new file mode 100644
index 00000000000..8a9c3f969a0
--- /dev/null
+++ b/config/metrics/counts_all/20210730011801_projects_zentao_active.yml
@@ -0,0 +1,22 @@
+---
+key_path: counts.projects_zentao_active
+name: count_all_projects_zentao_active
+description: Count of projects with active Zentao integrations
+product_section: dev
+product_stage: ecosystem
+product_group: group::integrations
+product_category: integrations
+value_type: number
+status: active
+milestone: "14.4"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338178
+time_frame: all
+data_source: database
+data_category: Operational
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210730011802_groups_zentao_active.yml b/config/metrics/counts_all/20210730011802_groups_zentao_active.yml
new file mode 100644
index 00000000000..c8a1dfbbdd2
--- /dev/null
+++ b/config/metrics/counts_all/20210730011802_groups_zentao_active.yml
@@ -0,0 +1,22 @@
+---
+key_path: counts.groups_zentao_active
+name: count_all_groups_zentao_active
+description: Count of groups with active Zentao integrations
+product_section: dev
+product_stage: ecosystem
+product_group: group::integrations
+product_category: integrations
+value_type: number
+status: active
+milestone: "14.4"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338178
+time_frame: all
+data_source: database
+data_category: Operational
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210730011804_instances_zentao_active.yml b/config/metrics/counts_all/20210730011804_instances_zentao_active.yml
new file mode 100644
index 00000000000..b1c2a9d8b13
--- /dev/null
+++ b/config/metrics/counts_all/20210730011804_instances_zentao_active.yml
@@ -0,0 +1,22 @@
+---
+key_path: counts.instances_zentao_active
+name: count_all_instances_zentao_active
+description: Count of instances with active Zentao integrations
+product_section: dev
+product_stage: ecosystem
+product_group: group::integrations
+product_category: integrations
+value_type: number
+status: active
+milestone: "14.4"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338178
+time_frame: all
+data_source: database
+data_category: Operational
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210730011805_projects_inheriting_zentao_active.yml b/config/metrics/counts_all/20210730011805_projects_inheriting_zentao_active.yml
new file mode 100644
index 00000000000..34c48ada0ee
--- /dev/null
+++ b/config/metrics/counts_all/20210730011805_projects_inheriting_zentao_active.yml
@@ -0,0 +1,22 @@
+---
+key_path: counts.projects_inheriting_zentao_active
+name: count_all_projects_inheriting_zentao_active
+description: Count of projects that inherit active Zentao integrations
+product_section: dev
+product_stage: ecosystem
+product_group: group::integrations
+product_category: integrations
+value_type: number
+status: active
+milestone: "14.4"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338178
+time_frame: all
+data_source: database
+data_category: Operational
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210730011806_groups_inheriting_zentao_active.yml b/config/metrics/counts_all/20210730011806_groups_inheriting_zentao_active.yml
new file mode 100644
index 00000000000..4d374db026e
--- /dev/null
+++ b/config/metrics/counts_all/20210730011806_groups_inheriting_zentao_active.yml
@@ -0,0 +1,22 @@
+---
+key_path: counts.groups_inheriting_zentao_active
+name: count_all_groups_inheriting_zentao_active
+description: Count of groups that inherit active Zentao integrations
+product_section: dev
+product_stage: ecosystem
+product_group: group::integrations
+product_category: integrations
+value_type: number
+status: active
+milestone: "14.4"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338178
+time_frame: all
+data_source: database
+data_category: Operational
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20211028210001_projects_shimo_active.yml b/config/metrics/counts_all/20211028210001_projects_shimo_active.yml
new file mode 100644
index 00000000000..b6b11407c6a
--- /dev/null
+++ b/config/metrics/counts_all/20211028210001_projects_shimo_active.yml
@@ -0,0 +1,22 @@
+---
+key_path: counts.projects_shimo_active
+name: count_all_projects_shimo_active
+description: Count of projects with active Shimo integrations
+product_section: dev
+product_stage: ecosystem
+product_group: group::integrations
+product_category: integrations
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343386
+time_frame: all
+data_source: database
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20211028210002_groups_shimo_active.yml b/config/metrics/counts_all/20211028210002_groups_shimo_active.yml
new file mode 100644
index 00000000000..3f2423f7696
--- /dev/null
+++ b/config/metrics/counts_all/20211028210002_groups_shimo_active.yml
@@ -0,0 +1,22 @@
+---
+key_path: counts.groups_shimo_active
+name: count_all_groups_shimo_active
+description: Count of groups with active Shimo integrations
+product_section: dev
+product_stage: ecosystem
+product_group: group::integrations
+product_category: integrations
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343386
+time_frame: all
+data_source: database
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20211028210003_instances_shimo_active.yml b/config/metrics/counts_all/20211028210003_instances_shimo_active.yml
new file mode 100644
index 00000000000..2b835ef6d6c
--- /dev/null
+++ b/config/metrics/counts_all/20211028210003_instances_shimo_active.yml
@@ -0,0 +1,22 @@
+---
+key_path: counts.instances_shimo_active
+name: count_all_instances_shimo_active
+description: Count of instances with active Shimo integrations
+product_section: dev
+product_stage: ecosystem
+product_group: group::integrations
+product_category: integrations
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343386
+time_frame: all
+data_source: database
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20211028210004_projects_inheriting_shimo_active.yml b/config/metrics/counts_all/20211028210004_projects_inheriting_shimo_active.yml
new file mode 100644
index 00000000000..d7d231206d5
--- /dev/null
+++ b/config/metrics/counts_all/20211028210004_projects_inheriting_shimo_active.yml
@@ -0,0 +1,22 @@
+---
+key_path: counts.projects_inheriting_shimo_active
+name: count_all_projects_inheriting_shimo_active
+description: Count of projects that inherit active Shimo integrations
+product_section: dev
+product_stage: ecosystem
+product_group: group::integrations
+product_category: integrations
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343386
+time_frame: all
+data_source: database
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20211028210005_groups_inheriting_shimo_active.yml b/config/metrics/counts_all/20211028210005_groups_inheriting_shimo_active.yml
new file mode 100644
index 00000000000..d979e672f60
--- /dev/null
+++ b/config/metrics/counts_all/20211028210005_groups_inheriting_shimo_active.yml
@@ -0,0 +1,22 @@
+---
+key_path: counts.groups_inheriting_shimo_active
+name: count_all_groups_inheriting_shimo_active
+description: Count of groups that inherit active Shimo integrations
+product_section: dev
+product_stage: ecosystem
+product_group: group::integrations
+product_category: integrations
+value_type: number
+status: active
+milestone: "14.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343386
+time_frame: all
+data_source: database
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/schema.json b/config/metrics/schema.json
index ede7b9d3f6c..d416c7b6d6e 100644
--- a/config/metrics/schema.json
+++ b/config/metrics/schema.json
@@ -1,6 +1,6 @@
{
"type": "object",
- "required": ["key_path", "description", "value_type", "status", "product_group", "product_stage", "time_frame", "data_source", "distribution", "tier", "data_category", "milestone"],
+ "required": ["key_path", "description", "value_type", "status", "product_group", "product_section", "product_stage", "time_frame", "data_source", "distribution", "tier", "data_category", "milestone"],
"properties": {
"key_path": {
"type": "string"
@@ -13,10 +13,10 @@
"type": "string"
},
"product_section": {
- "type": ["string", "null"]
+ "type": ["string"]
},
"product_stage": {
- "type": ["string", "null"]
+ "type": ["string"]
},
"product_group": {
"type": "string"
diff --git a/config/plugins/graphql_known_operations_plugin.js b/config/plugins/graphql_known_operations_plugin.js
new file mode 100644
index 00000000000..164b34c1dd1
--- /dev/null
+++ b/config/plugins/graphql_known_operations_plugin.js
@@ -0,0 +1,112 @@
+/* eslint-disable no-underscore-dangle */
+const yaml = require('js-yaml');
+
+const PLUGIN_NAME = 'GraphqlKnownOperationsPlugin';
+const GRAPHQL_PATH_REGEX = /(query|mutation)\.graphql$/;
+const OPERATION_NAME_SOURCE_REGEX = /^\s*module\.exports.*oneQuery.*"(\w+)"/gm;
+
+/**
+ * Returns whether a given webpack module is a "graphql" module
+ */
+const isGraphqlModule = (module) => {
+ return GRAPHQL_PATH_REGEX.test(module.resource);
+};
+
+/**
+ * Returns graphql operation names we can parse from the given module
+ *
+ * Since webpack gives us the source **after** the graphql-tag/loader runs,
+ * we can look for specific lines we're guaranteed to have from the
+ * graphql-tag/loader.
+ */
+const getOperationNames = (module) => {
+ const originalSource = module.originalSource();
+
+ if (!originalSource) {
+ return [];
+ }
+
+ const matches = originalSource.source().toString().matchAll(OPERATION_NAME_SOURCE_REGEX);
+
+ return Array.from(matches).map((match) => match[1]);
+};
+
+const createFileContents = (knownOperations) => {
+ const sourceData = Array.from(knownOperations.values()).sort((a, b) => a.localeCompare(b));
+
+ return yaml.dump(sourceData);
+};
+
+/**
+ * Creates a webpack4 compatible "RawSource"
+ *
+ * Inspired from https://sourcegraph.com/github.com/FormidableLabs/webpack-stats-plugin@e050ff8c362d5ddd45c66ade724d4a397ace3e5c/-/blob/lib/stats-writer-plugin.js?L144
+ */
+const createWebpackRawSource = (source) => {
+ const buff = Buffer.from(source, 'utf-8');
+
+ return {
+ source() {
+ return buff;
+ },
+ size() {
+ return buff.length;
+ },
+ };
+};
+
+const onSucceedModule = ({ module, knownOperations }) => {
+ if (!isGraphqlModule(module)) {
+ return;
+ }
+
+ getOperationNames(module).forEach((x) => knownOperations.add(x));
+};
+
+const onCompilerEmit = ({ compilation, knownOperations, filename }) => {
+ const contents = createFileContents(knownOperations);
+ const source = createWebpackRawSource(contents);
+
+ const asset = compilation.getAsset(filename);
+ if (asset) {
+ compilation.updateAsset(filename, source);
+ } else {
+ compilation.emitAsset(filename, source);
+ }
+};
+
+/**
+ * Webpack plugin that outputs a file containing known graphql operations.
+ *
+ * A lot of the mechanices was expired from [this example][1].
+ *
+ * [1]: https://sourcegraph.com/github.com/FormidableLabs/webpack-stats-plugin@e050ff8c362d5ddd45c66ade724d4a397ace3e5c/-/blob/lib/stats-writer-plugin.js?L136
+ */
+class GraphqlKnownOperationsPlugin {
+ constructor({ filename }) {
+ this._filename = filename;
+ }
+
+ apply(compiler) {
+ const knownOperations = new Set();
+
+ compiler.hooks.emit.tap(PLUGIN_NAME, (compilation) => {
+ onCompilerEmit({
+ compilation,
+ knownOperations,
+ filename: this._filename,
+ });
+ });
+
+ compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
+ compilation.hooks.succeedModule.tap(PLUGIN_NAME, (module) => {
+ onSucceedModule({
+ module,
+ knownOperations,
+ });
+ });
+ });
+ }
+}
+
+module.exports = GraphqlKnownOperationsPlugin;
diff --git a/config/routes.rb b/config/routes.rb
index 01e57a01359..94d36961b32 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -43,12 +43,15 @@ Rails.application.routes.draw do
draw :oauth
- use_doorkeeper_openid_connect
+ use_doorkeeper_openid_connect do
+ controllers discovery: 'jwks'
+ end
+
# Add OPTIONS method for CORS preflight requests
match '/oauth/userinfo' => 'doorkeeper/openid_connect/userinfo#show', via: :options
- match '/oauth/discovery/keys' => 'doorkeeper/openid_connect/discovery#keys', via: :options
- match '/.well-known/openid-configuration' => 'doorkeeper/openid_connect/discovery#provider', via: :options
- match '/.well-known/webfinger' => 'doorkeeper/openid_connect/discovery#webfinger', via: :options
+ match '/oauth/discovery/keys' => 'jwks#keys', via: :options
+ match '/.well-known/openid-configuration' => 'jwks#provider', via: :options
+ match '/.well-known/webfinger' => 'jwks#webfinger', via: :options
match '/oauth/token' => 'oauth/tokens#create', via: :options
match '/oauth/revoke' => 'oauth/tokens#revoke', via: :options
diff --git a/config/routes/explore.rb b/config/routes/explore.rb
index c6bf98b6fb3..6ddf4d23138 100644
--- a/config/routes/explore.rb
+++ b/config/routes/explore.rb
@@ -5,6 +5,8 @@ namespace :explore do
collection do
get :trending
get :starred
+ get :topics
+ get 'topics/:topic_name', action: :topic, as: :topic, constraints: { topic_name: /.+/ }
end
end
diff --git a/config/routes/group.rb b/config/routes/group.rb
index 803249f8861..9a50d580747 100644
--- a/config/routes/group.rb
+++ b/config/routes/group.rb
@@ -125,6 +125,13 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
get 'milestones'
end
end
+
+ resources :crm, only: [] do
+ collection do
+ get 'contacts'
+ get 'organizations'
+ end
+ end
end
scope(path: '*id',
@@ -148,5 +155,7 @@ scope format: false do
get 'v2/*group_id/dependency_proxy/containers/*image/blobs/:sha' => 'groups/dependency_proxy_for_containers#blob' # rubocop:todo Cop/PutGroupRoutesUnderScope
post 'v2/*group_id/dependency_proxy/containers/*image/blobs/:sha/upload/authorize' => 'groups/dependency_proxy_for_containers#authorize_upload_blob' # rubocop:todo Cop/PutGroupRoutesUnderScope
post 'v2/*group_id/dependency_proxy/containers/*image/blobs/:sha/upload' => 'groups/dependency_proxy_for_containers#upload_blob' # rubocop:todo Cop/PutGroupRoutesUnderScope
+ post 'v2/*group_id/dependency_proxy/containers/*image/manifests/*tag/upload/authorize' => 'groups/dependency_proxy_for_containers#authorize_upload_manifest' # rubocop:todo Cop/PutGroupRoutesUnderScope
+ post 'v2/*group_id/dependency_proxy/containers/*image/manifests/*tag/upload' => 'groups/dependency_proxy_for_containers#upload_manifest' # rubocop:todo Cop/PutGroupRoutesUnderScope
end
end
diff --git a/config/routes/project.rb b/config/routes/project.rb
index b1be9ad2ada..7f9b2cc4fbf 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -38,7 +38,9 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
namespace :security do
- resource :configuration, only: [:show], controller: :configuration
+ resource :configuration, only: [:show], controller: :configuration do
+ resource :sast, only: [:show], controller: :sast_configuration
+ end
end
resources :artifacts, only: [:index, :destroy]
@@ -358,7 +360,9 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get 'details', on: :member
end
- resources :work_items, only: [:index]
+ get 'alert_management/:id', to: 'alert_management#details', as: 'alert_management_alert'
+
+ get 'work_items/*work_items_path' => 'work_items#index', as: :work_items
resource :tracing, only: [:show]
@@ -536,6 +540,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
delete :delete_attachment # rubocop:todo Cop/PutProjectRoutesUnderScope
post :resolve # rubocop:todo Cop/PutProjectRoutesUnderScope
delete :resolve, action: :unresolve # rubocop:todo Cop/PutProjectRoutesUnderScope
+ get :outdated_line_change # rubocop:todo Cop/PutProjectRoutesUnderScope
end
end
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 56183d167be..f7e3f036c53 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -35,10 +35,14 @@
- 1
- - analytics_usage_trends_counter_job
- 1
+- - app_sec_dast_scans_consistency
+ - 1
- - approval_rules_external_approval_rule_payload
- 1
- - approve_blocked_pending_approval_users
- 1
+- - audit_events_audit_event_streaming
+ - 1
- - authorized_keys
- 2
- - authorized_project_update
@@ -175,6 +179,8 @@
- 1
- - group_wikis_git_garbage_collect
- 1
+- - groups_create_event
+ - 1
- - groups_export_memberships
- 1
- - groups_schedule_bulk_repository_shard_moves
@@ -197,6 +203,8 @@
- 1
- - incident_management_pending_escalations_alert_create
- 1
+- - integrations_create_external_cross_reference
+ - 1
- - invalid_gpg_signature_update
- 2
- - irker
@@ -211,6 +219,10 @@
- 2
- - issue_rebalancing
- 1
+- - issues_placement
+ - 2
+- - issues_rebalancing
+ - 1
- - iterations
- 1
- - jira_connect
@@ -247,6 +259,8 @@
- 1
- - namespaceless_project_destroy
- 1
+- - namespaces_invite_team_email
+ - 1
- - namespaces_onboarding_issue_created
- 1
- - namespaces_onboarding_pipeline_created
@@ -391,6 +405,8 @@
- 1
- - system_hook_push
- 1
+- - tasks_to_be_done_create
+ - 1
- - todos_destroyer
- 1
- - unassign_issuables
diff --git a/config/webpack.config.js b/config/webpack.config.js
index e1a48ee2b41..f334e17bbaf 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -24,6 +24,7 @@ const IS_JH = require('./helpers/is_jh_env');
const vendorDllHash = require('./helpers/vendor_dll_hash');
const MonacoWebpackPlugin = require('./plugins/monaco_webpack');
+const GraphqlKnownOperationsPlugin = require('./plugins/graphql_known_operations_plugin');
const ROOT_PATH = path.resolve(__dirname, '..');
const SUPPORTED_BROWSERS = fs.readFileSync(path.join(ROOT_PATH, '.browserslistrc'), 'utf-8');
@@ -198,6 +199,7 @@ if (!IS_PRODUCTION) {
Object.assign(alias, {
test_fixtures: path.join(ROOT_PATH, `tmp/tests/frontend/${fixtureDir}`),
+ test_fixtures_static: path.join(ROOT_PATH, 'spec/frontend/fixtures/static'),
test_helpers: path.join(ROOT_PATH, 'spec/frontend_integration/test_helpers'),
});
}
@@ -455,6 +457,8 @@ module.exports = {
globalAPI: true,
}),
+ new GraphqlKnownOperationsPlugin({ filename: 'graphql_known_operations.yml' }),
+
// fix legacy jQuery plugins which depend on globals
new webpack.ProvidePlugin({
$: 'jquery',
diff --git a/danger/database/Dangerfile b/danger/database/Dangerfile
index 693c03b9dad..70adbb4c139 100644
--- a/danger/database/Dangerfile
+++ b/danger/database/Dangerfile
@@ -66,8 +66,6 @@ if gitlab.mr_labels.include?('database') || db_paths_to_review.any?
end
unless helper.has_database_scoped_labels?
- gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
- gitlab.mr_json['iid'],
- add_labels: 'database::review pending')
+ project_helper.labels_to_add << 'database::review pending'
end
end
diff --git a/danger/feature_flag/Dangerfile b/danger/feature_flag/Dangerfile
index 9b67590f117..d6c1c53cddc 100644
--- a/danger/feature_flag/Dangerfile
+++ b/danger/feature_flag/Dangerfile
@@ -58,9 +58,7 @@ def message_for_feature_flag_with_group!(feature_flag:, mr_group_label:)
return if feature_flag.group_match_mr_label?(mr_group_label)
if mr_group_label.nil?
- gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
- gitlab.mr_json['iid'],
- add_labels: feature_flag.group)
+ project_helper.labels_to_add << feature_flag.group
else
fail %(`group` is set to ~"#{feature_flag.group}" in #{gitlab.html_link(feature_flag.path)}, which does not match ~"#{mr_group_label}" set on the MR!)
end
diff --git a/danger/metadata/Dangerfile b/danger/metadata/Dangerfile
deleted file mode 100644
index 27dda687f6a..00000000000
--- a/danger/metadata/Dangerfile
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-# rubocop:disable Style/SignalException
-
-DEFAULT_BRANCH = 'master'
-
-THROUGHPUT_LABELS = [
- 'Community contribution',
- 'security',
- 'bug',
- 'feature',
- 'feature::addition',
- 'feature::maintenance',
- 'tooling',
- 'tooling::pipelines',
- 'tooling::workflow',
- 'documentation'
-].freeze
-
-if gitlab.mr_body.size < 5
- fail "Please provide a proper merge request description."
-end
-
-if (THROUGHPUT_LABELS & gitlab.mr_labels).empty?
- warn 'Please add a [merge request type](https://about.gitlab.com/handbook/engineering/metrics/#work-type-classification) to this merge request.'
-end
-
-unless gitlab.mr_json["assignee"]
- warn "This merge request does not have any assignee yet. Setting an assignee clarifies who needs to take action on the merge request at any given time."
-end
-
-has_milestone = !gitlab.mr_json["milestone"].nil?
-
-unless has_milestone || (helper.security_mr? && gitlab.branch_for_base == DEFAULT_BRANCH)
- warn "This merge request does not refer to an existing milestone.", sticky: false
-end
-
-has_pick_into_stable_label = gitlab.mr_labels.find { |label| label.start_with?('Pick into') }
-
-if gitlab.branch_for_base != DEFAULT_BRANCH && !has_pick_into_stable_label && !helper.security_mr?
- warn "Most of the time, merge requests should target `#{DEFAULT_BRANCH}`. Otherwise, please set the relevant `Pick into X.Y` label."
-end
diff --git a/danger/pipeline/Dangerfile b/danger/pipeline/Dangerfile
index 5503094ba50..861d031915e 100644
--- a/danger/pipeline/Dangerfile
+++ b/danger/pipeline/Dangerfile
@@ -14,7 +14,7 @@ Please consider the effect of the changes in this merge request on the following
- personal forks
- Effects on [pipeline performance](https://about.gitlab.com/handbook/engineering/quality/performance-indicators/#average-merge-request-pipeline-duration-for-gitlab)
-Please consider communicating these changes to the broader team following the [communication guideline for pipeline changes](https://about.gitlab.com/handbook/engineering/quality/engineering-productivity-team/#pipeline-changes)
+Please consider communicating these changes to the broader team following the [communication guideline for pipeline changes](https://about.gitlab.com/handbook/engineering/quality/engineering-productivity/#pipeline-changes)
MESSAGE
if helper.has_ci_changes?
diff --git a/danger/product_intelligence/Dangerfile b/danger/product_intelligence/Dangerfile
index fd6ae76b4f1..eedb9b89d22 100644
--- a/danger/product_intelligence/Dangerfile
+++ b/danger/product_intelligence/Dangerfile
@@ -12,13 +12,11 @@ For MR review guidelines, see the [Service Ping review guidelines](https://docs.
MSG
# exit if not matching files or if no product intelligence labels
-matching_changed_files = product_intelligence.matching_changed_files
-labels = product_intelligence.missing_labels
+product_intelligence_paths_to_review = project_helper.changes_by_category[:product_intelligence]
+labels_to_add = product_intelligence.missing_labels
-return if matching_changed_files.empty? || labels.empty?
+return if product_intelligence_paths_to_review.empty? || labels_to_add.empty?
-warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(matching_changed_files))
+warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(product_intelligence_paths_to_review))
-gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
- gitlab.mr_json['iid'],
- add_labels: labels)
+project_helper.labels_to_add.concat(labels_to_add)
diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile
index 54b46807241..4eb1d987d84 100644
--- a/danger/roulette/Dangerfile
+++ b/danger/roulette/Dangerfile
@@ -48,10 +48,18 @@ Please consider creating a merge request to
for them.
MARKDOWN
+def group_not_available_template(slack_channel, gitlab_group)
+ <<~TEMPLATE
+ No engineer is available for automated assignment, please reach out to `#{slack_channel}` slack channel or mention `#{gitlab_group}` for assistance.
+ TEMPLATE
+end
+
OPTIONAL_REVIEW_TEMPLATE = '%{role} review is optional for %{category}'
NOT_AVAILABLE_TEMPLATES = {
default: 'No %{role} available',
- product_intelligence: "No engineer is available for automated assignment, please reach out to `#g_product_intelligence` slack channel or mention `@gitlab-org/growth/product-intelligence/engineers` for assistance."
+ product_intelligence: group_not_available_template('#g_product_intelligence', '@gitlab-org/growth/product-intelligence/engineers'),
+ integrations_be: group_not_available_template('#g_ecosystem_integrations', '@gitlab-org/ecosystem-stage/integrations'),
+ integrations_fe: group_not_available_template('#g_ecosystem_integrations', '@gitlab-org/ecosystem-stage/integrations')
}.freeze
def note_for_spins_role(spins, role, category)
@@ -96,6 +104,9 @@ categories = Set.new(changes.keys - [:unknown])
# Ensure to spin for database reviewer/maintainer when ~database is applied (e.g. to review SQL queries)
categories << :database if helper.mr_labels.include?('database')
+# Ensure to spin for UX reviewer for community contributions when ~UX is applied (e.g. to review changes to the UI)
+categories << :ux if (["UX", "Community contribution"] - helper.mr_labels).empty?
+
# Ensure to spin for Product Intelligence reviewer when ~"product intelligence::review pending" is applied
categories << :product_intelligence if helper.mr_labels.include?("product intelligence::review pending")
diff --git a/danger/specialization_labels/Dangerfile b/danger/specialization_labels/Dangerfile
index e86d66f5fbc..24a759cddc8 100644
--- a/danger/specialization_labels/Dangerfile
+++ b/danger/specialization_labels/Dangerfile
@@ -6,21 +6,24 @@ SPECIALIZATIONS = {
database: 'database',
backend: 'backend',
frontend: 'frontend',
+ ux: 'UX',
docs: 'documentation',
qa: 'QA',
- tooling: 'tooling',
+ tooling: 'type::tooling',
ci_template: 'ci::templates',
feature_flag: 'feature flag'
}.freeze
labels_to_add = project_helper.changes_by_category.each_with_object([]) do |(category, _changes), memo|
label = SPECIALIZATIONS[category]
+ next unless label
+ next if gitlab.mr_labels.include?(label)
- memo << label if label && !gitlab.mr_labels.include?(label)
-end
+ # Don't override already-set scoped labels.
+ label_scope = label.split('::')[0...-1].join('::')
+ next if !label_scope.empty? && gitlab.mr_labels.any? { |mr_label| mr_label.start_with?(label_scope) }
-if labels_to_add.any?
- gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
- gitlab.mr_json['iid'],
- add_labels: labels_to_add.join(','))
+ memo << label
end
+
+project_helper.labels_to_add.concat(labels_to_add) if labels_to_add.any?
diff --git a/danger/specs/Dangerfile b/danger/specs/Dangerfile
index 117eaf61062..067fb62807a 100644
--- a/danger/specs/Dangerfile
+++ b/danger/specs/Dangerfile
@@ -1,7 +1,7 @@
# frozen_string_literal: true
NO_SPECS_LABELS = [
- 'tooling',
+ 'type::tooling',
'tooling::pipelines',
'tooling::workflow',
'documentation',
diff --git a/danger/z_metadata/Dangerfile b/danger/z_metadata/Dangerfile
new file mode 100644
index 00000000000..0a70554486f
--- /dev/null
+++ b/danger/z_metadata/Dangerfile
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+# rubocop:disable Style/SignalException
+
+DEFAULT_BRANCH = 'master'
+
+TYPE_LABELS = [
+ 'type::feature',
+ 'feature::addition',
+ 'type::maintenance',
+ 'type::tooling',
+ 'tooling::pipelines',
+ 'tooling::workflow',
+ 'type::bug'
+].freeze
+
+if gitlab.mr_body.size < 5
+ fail "Please provide a proper merge request description."
+end
+
+if (TYPE_LABELS & (gitlab.mr_labels + project_helper.labels_to_add)).empty?
+ warn 'Please add a [merge request type](https://about.gitlab.com/handbook/engineering/metrics/#work-type-classification) to this merge request.'
+end
+
+unless gitlab.mr_json["assignee"]
+ warn "This merge request does not have any assignee yet. Setting an assignee clarifies who needs to take action on the merge request at any given time."
+end
+
+has_milestone = !gitlab.mr_json["milestone"].nil?
+
+unless has_milestone || (helper.security_mr? && gitlab.branch_for_base == DEFAULT_BRANCH)
+ warn "This merge request does not refer to an existing milestone.", sticky: false
+end
+
+has_pick_into_stable_label = gitlab.mr_labels.find { |label| label.start_with?('Pick into') }
+
+if gitlab.branch_for_base != DEFAULT_BRANCH && !has_pick_into_stable_label && !helper.security_mr?
+ warn "Most of the time, merge requests should target `#{DEFAULT_BRANCH}`. Otherwise, please set the relevant `Pick into X.Y` label."
+end
diff --git a/data/deprecations/ runner-s3-authenticationtype-nonexplicit-config-deprecation.yml b/data/deprecations/ runner-s3-authenticationtype-nonexplicit-config-deprecation.yml
new file mode 100644
index 00000000000..01ca5839281
--- /dev/null
+++ b/data/deprecations/ runner-s3-authenticationtype-nonexplicit-config-deprecation.yml
@@ -0,0 +1,12 @@
+- name: "`AuthenticationType` for `[runners.cache.s3]` must be explicitly assigned"
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22"
+ removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ In GitLab 15.0 and later, to access the AWS S3 cache, you must specify the `AuthenticationType` for [`[runners.cache.s3]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscaches3-section). The `AuthenticationType` must be `IAM` or `credentials`.
+
+ Prior to 14.5, if you did not define the `AuthenticationType`, GitLab Runner chose a type for you.
+ stage: Verify
+ tiers: [Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/28171
+ documentation_url: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscaches3-section
diff --git a/data/deprecations/14-0-nfs-fot-git-repository-storage.yml b/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
index f38742439aa..6884f6e3f69 100644
--- a/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
+++ b/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
@@ -1,7 +1,7 @@
- name: "NFS for Git repository storage deprecated" # The name of the feature to be deprecated
announcement_milestone: "14.0" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-06-22" # The date of the milestone release when this feature was first announced as deprecated
- removal_milestone: "15.2" # The milestone when this feature is planned to be removed
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
With the general availability of Gitaly Cluster ([introduced in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/)), we have deprecated development (bugfixes, performance improvements, etc) for NFS for Git repository storage in GitLab 14.0. We will continue to provide technical support for NFS for Git repositories throughout 14.x, but we will remove all support for NFS in GitLab 15.0. Please see our official [Statement of Support](https://about.gitlab.com/support/statement-of-support.html#gitaly-and-nfs) for further information.
@@ -19,4 +19,4 @@
documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
- removal_date: "2022-06-22" # (optional - may be required in the future) YYYY-MM-DD format - the date of the milestone release when this feature is planned to be removed
+ removal_date: "2022-05-22" # (optional - may be required in the future) YYYY-MM-DD format - the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/14-2-deprecation-task-runner.yml b/data/deprecations/14-2-deprecation-task-runner.yml
index 4d01a1969ad..52fd1f0f288 100644
--- a/data/deprecations/14-2-deprecation-task-runner.yml
+++ b/data/deprecations/14-2-deprecation-task-runner.yml
@@ -1,7 +1,7 @@
- name: "Rename Task Runner pod to Toolbox" # The name of the feature to be deprecated
announcement_milestone: "14.2" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-08-22" # The date of the milestone release when this feature was first announced as deprecated
- removal_milestone: "14.4" # The milestone when this feature is planned to be removed
+ removal_milestone: "14.5" # The milestone when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
The Task Runner pod is used to execute periodic housekeeping tasks within the GitLab application and is often confused with the GitLab Runner. Thus, [Task Runner will be renamed to Toolbox](https://gitlab.com/groups/gitlab-org/charts/-/epics/25).
@@ -13,4 +13,4 @@
documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
- removal_date: "2021-10-22" # (optional - may be required in the future) YYYY-MM-DD format - the date of the milestone release when this feature is planned to be removed
+ removal_date: "2021-11-22" # (optional - may be required in the future) YYYY-MM-DD format - the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/14-3-package-container-registry-api-group-update.yml b/data/deprecations/14-3-package-container-registry-api-group-update.yml
new file mode 100644
index 00000000000..3021e283846
--- /dev/null
+++ b/data/deprecations/14-3-package-container-registry-api-group-update.yml
@@ -0,0 +1,12 @@
+- name: "Update to the Container Registry group-level API"
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ In milestone 15.0, support for the `tags` and `tags_count` parameters will be removed from the Container Registry API that [gets registry repositories from a group](../api/container_registry.md#within-a-group).
+
+ The `GET /groups/:id/registry/repositories` endpoint will remain, but won't return any info about tags. To get the info about tags, you can use the existing `GET /registry/repositories/:id` endpoint, which will continue to support the `tags` and `tag_count` options as it does today. The latter must be called once per image repository.
+ stage: Package
+ tiers: Free
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/336912
+ documentation_url: https://docs.gitlab.com/ee/api/container_registry.html#within-a-group
+ announcement_date: 2021-11-22
diff --git a/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml b/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
new file mode 100644
index 00000000000..86e7718b9e1
--- /dev/null
+++ b/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
@@ -0,0 +1,19 @@
+- name: "Certificate-based integration with Kubernetes"
+ announcement_milestone: "14.5"
+ announcement_date: "2021-11-15"
+ removal_milestone: "15.0"
+ body: |
+ [We are deprecating the certificate-based integration with Kubernetes](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
+ The timeline of removal of the integration from the product is not yet planned and we will communicate
+ more details as they emerge. The certificate-based integration will continue to receive security and
+ critical fixes, and features built on the integration will continue to work with supported Kubernetes
+ versions. We will provide migration plans in a future iteration. See [the list of features affected by this deprecation](https://docs.gitlab.com/ee/user/infrastructure/clusters/#deprecated-features).
+ For updates and details, follow this [epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
+
+ For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend the use of the
+ [Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab.
+ stage: Configure
+ tiers: [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: 'https://gitlab.com/groups/gitlab-org/configure/-/epics/8'
+ documentation_url: 'https://docs.gitlab.com/ee/user/infrastructure/clusters/#certificate-based-kubernetes-integration-deprecated'
+ removal_date: # (optional - may be required in the future) YYYY-MM-DD format. This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml b/data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml
new file mode 100644
index 00000000000..c5f9e244af0
--- /dev/null
+++ b/data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml
@@ -0,0 +1,11 @@
+- name: "Converting an instance (shared) runner to a project (specific) runner is deprecated"
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22"
+ removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ In GitLab 15.0, we will remove the feature that enables you to convert an instance (shared) runner to a project (specific) runner. Users who need to add a runner to only a particular project can register a runner to the project directly.
+
+ stage: Verify
+ tiers: [Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345347
+
diff --git a/data/deprecations/14-5-deprecate-opensuse-15-2.yml b/data/deprecations/14-5-deprecate-opensuse-15-2.yml
new file mode 100644
index 00000000000..b887f92e6a3
--- /dev/null
+++ b/data/deprecations/14-5-deprecate-opensuse-15-2.yml
@@ -0,0 +1,9 @@
+- name: "openSUSE Leap 15.2 packages" # The name of the feature to be deprecated
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "14.8" # The milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ Distribution support and security updates for openSUSE Leap 15.2 are [ending December 2021](https://en.opensuse.org/Lifetime#openSUSE_Leap).
+
+ Starting in 14.5 we are providing packages for openSUSE Leap 15.3, and will stop providing packages for openSUSE Leap 15.2 in the 14.8 milestone.
+ issue_url: https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6427
diff --git a/data/deprecations/14-5-deprecation-vsa-announce-deprecation-of-vsa-filtering-calculation.yml b/data/deprecations/14-5-deprecation-vsa-announce-deprecation-of-vsa-filtering-calculation.yml
new file mode 100644
index 00000000000..2961fab7487
--- /dev/null
+++ b/data/deprecations/14-5-deprecation-vsa-announce-deprecation-of-vsa-filtering-calculation.yml
@@ -0,0 +1,13 @@
+- name: "Value Stream Analytics filtering calculation change" # The name of the feature to be deprecated
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ We are changing how the date filter works in Value Stream Analytics. Instead of filtering by the time that the issue or merge request was created, the date filter will filter by the end event time of the given stage. This will result in completely different figures after this change has rolled out.
+
+ If you monitor Value Stream Analytics metrics and rely on the date filter, to avoid losing data, you must save the data prior to this change.
+ stage: manage # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/343210' # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: "https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html#filter-value-stream-analytics-data" # (optional) This is a link to the current documentation page
+ image_url: "vsa_warning.png" # (optional) This is a link to a thumbnail image depicting the feature
diff --git a/data/deprecations/14-5-geo-deprecate-promote-db.yml b/data/deprecations/14-5-geo-deprecate-promote-db.yml
new file mode 100644
index 00000000000..ba2aa7dc032
--- /dev/null
+++ b/data/deprecations/14-5-geo-deprecate-promote-db.yml
@@ -0,0 +1,25 @@
+# This is a template for a feature deprecation
+# A deprecation typically occurs when a feature or capability is planned to be removed in a future release.
+# Deprecations should be announced at least two releases prior to removal. Any breaking changes should only be done in major releases.
+#
+# Below is an example of what a single entry should look like, it's required attributes,
+# and what types we expect those attribute values to be.
+#
+# For more information please refer to the handbook documentation here:
+# {{LINK TBD}}
+#
+# Please delete this line and above before submitting your merge request.
+
+- name: "Removal of `promote-db` command from `gitlab-ctl`" # The name of the feature to be deprecated
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-db` which is used to promote database nodes in multi-node Geo secondary sites. `gitlab-ctl promote-db` will continue to function as-is and be available until GitLab 15.0. We recommend that Geo customers begin testing the new `gitlab-ctl promote` command in their staging environments and incorporating the new command in their failover procedures.
+ stage: "Enablement"
+ tiers: [Premium, Ultimate]
+ issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/345207"
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
+ removal_date: "2022-05-22"
diff --git a/data/deprecations/14-5-geo-deprecate-promote-to-primary-node.yml b/data/deprecations/14-5-geo-deprecate-promote-to-primary-node.yml
new file mode 100644
index 00000000000..29301ed3c47
--- /dev/null
+++ b/data/deprecations/14-5-geo-deprecate-promote-to-primary-node.yml
@@ -0,0 +1,25 @@
+# This is a template for a feature deprecation
+# A deprecation typically occurs when a feature or capability is planned to be removed in a future release.
+# Deprecations should be announced at least two releases prior to removal. Any breaking changes should only be done in major releases.
+#
+# Below is an example of what a single entry should look like, it's required attributes,
+# and what types we expect those attribute values to be.
+#
+# For more information please refer to the handbook documentation here:
+# {{LINK TBD}}
+#
+# Please delete this line and above before submitting your merge request.
+
+- name: "Removal of `promote-to-primary-node` command from `gitlab-ctl`" # The name of the feature to be deprecated
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-to-primary-node` which was only usable for single-node Geo sites. `gitlab-ctl promote-to-primary-node` will continue to function as-is and be available until GitLab 15.0. We recommend that Geo customers begin testing the new `gitlab-ctl promote` command in their staging environments and incorporating the new command in their failover procedures.
+ stage: "Enablement"
+ tiers: [Premium, Ultimate]
+ issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/345207"
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
+ removal_date: "2022-05-22"
diff --git a/data/deprecations/14-5-runner-api-status-does-contain-paused.yml b/data/deprecations/14-5-runner-api-status-does-contain-paused.yml
new file mode 100644
index 00000000000..8c7cde8a121
--- /dev/null
+++ b/data/deprecations/14-5-runner-api-status-does-contain-paused.yml
@@ -0,0 +1,17 @@
+- name: "REST API Runner will not contain `paused`"
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ Runner REST API will not return `paused` as a status in GitLab 15.0.
+
+ Paused runners' status will only relate to runner contact status, such as:
+ `online`, `offline`, or `not_connected`. Status `paused` will not appear when the runner is
+ not active.
+
+ When checking if a runner is `paused`, API users are advised to check the boolean attribute
+ `active` to be `false` instead.
+ stage: Verify
+ tiers: [Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344648
+ documentation_url: https://docs.gitlab.com/ee/api/runners.html
+ announcement_date: "2021-11-22"
diff --git a/data/deprecations/15-0-deprecate-sles-12sp2.yml b/data/deprecations/15-0-deprecate-sles-12sp2.yml
new file mode 100644
index 00000000000..fd5057bb8d3
--- /dev/null
+++ b/data/deprecations/15-0-deprecate-sles-12sp2.yml
@@ -0,0 +1,6 @@
+- name: "Deprecate support for SLES 12 SP2" # The name of the feature to be deprecated
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22"
+ removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ Long term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 12 SP2 [ended on March 31, 2021](https://www.suse.com/lifecycle/). The CA certificates on SP2 include the expired DST root certificate, and it's not getting new CA certificate package updates. We have implemented some [workarounds](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/191), but we will not be able to continue to keep the build running properly.
diff --git a/data/deprecations/15-0-deprecation-versions-packagetype.yml b/data/deprecations/15-0-deprecation-versions-packagetype.yml
new file mode 100644
index 00000000000..4e1501b48ba
--- /dev/null
+++ b/data/deprecations/15-0-deprecation-versions-packagetype.yml
@@ -0,0 +1,12 @@
+- name: "Deprecate `Versions` on base `PackageType`"
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ As part of the work to create a [Package Registry GraphQL API](https://gitlab.com/groups/gitlab-org/-/epics/6318), the Package group deprecated the `Version` type for the basic `PackageType` type and moved it to [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#packagedetailstype).
+
+ In milestone 15.0, we will completely remove `Version` from `PackageType`.
+ stage: package
+ tiers: Free
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327453
+
diff --git a/data/deprecations/15-0-remove-dependency-proxy-permissions-flag.yml b/data/deprecations/15-0-remove-dependency-proxy-permissions-flag.yml
new file mode 100644
index 00000000000..292dc4a14c0
--- /dev/null
+++ b/data/deprecations/15-0-remove-dependency-proxy-permissions-flag.yml
@@ -0,0 +1,11 @@
+- name: "Remove the `:dependency_proxy_for_private_groups` feature flag" # The name of the feature to be deprecated
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ We added a feature flag because [GitLab-#11582](https://gitlab.com/gitlab-org/gitlab/-/issues/11582) changed how public groups use the Dependency Proxy. Prior to this change, you could use the Dependency Proxy without authentication. The change requires authentication to use the Dependency Proxy.
+
+ In milestone 15.0, we will remove the feature flag entirely. Moving forward, you must authenticate when using the Dependency Proxy.
+ stage: package
+ tiers: Free
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276777
diff --git a/data/deprecations/15-0-remove-package-pipelines-api.yml b/data/deprecations/15-0-remove-package-pipelines-api.yml
new file mode 100644
index 00000000000..ba69ed75e0f
--- /dev/null
+++ b/data/deprecations/15-0-remove-package-pipelines-api.yml
@@ -0,0 +1,11 @@
+- name: "Package pipelines in API payload is paginated" # The name of the feature to be deprecated
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ A request to the API for `/api/v4/projects/:id/packages` returns a paginated result of packages. Each package lists all of its pipelines in this response. This is a performance concern, as it's possible for a package to have hundreds or thousands of associated pipelines.
+
+ In milestone 15.0, we will remove the `pipelines` attribute from the API response.
+ stage: package
+ tiers: Free
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/289956
diff --git a/data/deprecations/15-0-remove-pipelines-from-version-field.yml b/data/deprecations/15-0-remove-pipelines-from-version-field.yml
new file mode 100644
index 00000000000..6f4f8db55cd
--- /dev/null
+++ b/data/deprecations/15-0-remove-pipelines-from-version-field.yml
@@ -0,0 +1,14 @@
+- name: "Remove the `pipelines` field from the `version` field" # The name of the feature to be deprecated
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ In GraphQL, there are two `pipelines` fields that you can use in a [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/#packagedetailstype) to get the pipelines for package versions:
+
+ - The `versions` field's `pipelines` field. This returns all the pipelines associated with all the package's versions, which can pull an unbounded number of objects in memory and create performance concerns.
+ - The `pipelines` field of a specific `version`. This returns only the pipelines associated with that single package version.
+
+ To mitigate possible performance problems, we will remove the `versions` field's `pipelines` field in milestone 15.0. Although you will no longer be able to get all pipelines for all versions of a package, you can still get the pipelines of a single version through the remaining `pipelines` field for that version.
+ stage: package
+ tiers: Free
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342882
diff --git a/data/deprecations/deprecate-defaultMergeCommitMessageWithDescription-graphql.yml b/data/deprecations/deprecate-defaultMergeCommitMessageWithDescription-graphql.yml
new file mode 100644
index 00000000000..eba37d1eb8f
--- /dev/null
+++ b/data/deprecations/deprecate-defaultMergeCommitMessageWithDescription-graphql.yml
@@ -0,0 +1,14 @@
+- name: "defaultMergeCommitMessageWithDescription GraphQL API field will be removed in GitLab 15.0" # The name of the feature to be deprecated
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ The GraphQL API field `defaultMergeCommitMessageWithDescription` has been deprecated and will be removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
+ removal_date: # (optional - may be required in the future) YYYY-MM-DD format. This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/disable_strict_host_key_checking.yml b/data/deprecations/disable_strict_host_key_checking.yml
new file mode 100644
index 00000000000..62011795bb9
--- /dev/null
+++ b/data/deprecations/disable_strict_host_key_checking.yml
@@ -0,0 +1,12 @@
+- name: "Known host required for GitLab Runner SSH executor"
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-11-22"
+ removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ In [GitLab 14.3](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/3074), we added a configuration setting in the GitLab Runner `config.toml` file. This setting, [`[runners.ssh.disable_strict_host_key_checking]`](https://docs.gitlab.com/runner/executors/ssh.html#security), controls whether or not to use strict host key checking with the SSH executor.
+
+ In GitLab 15.0 and later, the default value for this configuration option will change from `true` to `false`. This means that strict host key checking will be enforced when using the GitLab Runner SSH executor.
+ stage: Verify
+ tiers: [Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/28192
+ documentation_url: https://docs.gitlab.com/runner/executors/ssh.html#security
diff --git a/data/deprecations/templates/_deprecation_template.md.erb b/data/deprecations/templates/_deprecation_template.md.erb
index a037151c6ac..80b860b367f 100644
--- a/data/deprecations/templates/_deprecation_template.md.erb
+++ b/data/deprecations/templates/_deprecation_template.md.erb
@@ -17,13 +17,23 @@ sole discretion of GitLab Inc.
<!-- vale off -->
<!--
+DO NOT EDIT THIS PAGE DIRECTLY
+
This page is automatically generated from the YAML files in `/data/deprecations` by the rake task
located at `lib/tasks/gitlab/docs/compile_deprecations.rake`.
-Do not edit this page directly.
+For deprecation authors (usually Product Managers and Engineering Managers):
+
+- To add a deprecation, use the example.yml file in `/data/deprecations/templates` as a template.
+- For more information about authoring deprecations, check the the deprecation item guidance:
+ https://about.gitlab.com/handbook/marketing/blog/release-posts/#creating-a-deprecation-entry
+
+For deprecation reviewers (Technical Writers only):
-To add a deprecation, use the example.yml file in `/data/deprecations/templates` as a template,
-then run `bin/rake gitlab:docs:compile_deprecations`.
+- To update the deprecation doc, run: `bin/rake gitlab:docs:compile_deprecations`
+- To verify the deprecations doc is up to date, run: `bin/rake gitlab:docs:check_deprecations`
+- For more information about updating the deprecation doc, see the deprecation doc update guidance:
+ https://about.gitlab.com/handbook/marketing/blog/release-posts/#update-the-deprecations-doc
-->
<% if milestones.any? -%>
<%- milestones.each do |milestone| %>
diff --git a/data/deprecations/templates/example.yml b/data/deprecations/templates/example.yml
index a11a6800a74..0aaa68e4bd8 100644
--- a/data/deprecations/templates/example.yml
+++ b/data/deprecations/templates/example.yml
@@ -6,7 +6,7 @@
# and what types we expect those attribute values to be.
#
# For more information please refer to the handbook documentation here:
-# {{LINK TBD}}
+# https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations
#
# Please delete this line and above before submitting your merge request.
@@ -19,11 +19,10 @@
This area supports markdown. Delete this entire comment and replace it with your markdown content.
- Make sure to run `bin/rake gitlab:docs:compile_deprecations` locally before committing and pushing your changes.
-
- When ready, assign to your tech writer to review and merge.
+ When ready, assign to your tech writer for review. When ready, they will run `bin/rake gitlab:docs:compile_deprecations` to update the deprecations doc, then merge.
END OF BODY COMMENT -->
+# The following items are not published on the docs page, but may be used in the future.
stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: # (optional) This is a link to the deprecation issue in GitLab
diff --git a/data/deprecations/vsa_warning.png b/data/deprecations/vsa_warning.png
new file mode 100644
index 00000000000..7ee6c1e2343
--- /dev/null
+++ b/data/deprecations/vsa_warning.png
Binary files differ
diff --git a/db/fixtures/development/15_award_emoji.rb b/db/fixtures/development/15_award_emoji.rb
index 2b69a6c26ab..efad7e92bb0 100644
--- a/db/fixtures/development/15_award_emoji.rb
+++ b/db/fixtures/development/15_award_emoji.rb
@@ -1,15 +1,13 @@
require './spec/support/sidekiq_middleware'
Gitlab::Seeder.quiet do
- EMOJI = Gitlab::Emoji.emojis.keys
-
def seed_award_emoji(klass)
klass.order(Gitlab::Database.random).limit(klass.count / 2).each do |awardable|
awardable.project.authorized_users.where('project_authorizations.access_level > ?', Gitlab::Access::GUEST).sample(2).each do |user|
- AwardEmojis::AddService.new(awardable, EMOJI.sample, user).execute
+ AwardEmojis::AddService.new(awardable, TanukiEmoji.index.all.sample.name, user).execute
awardable.notes.user.sample(2).each do |note|
- AwardEmojis::AddService.new(note, EMOJI.sample, user).execute
+ AwardEmojis::AddService.new(note, TanukiEmoji.index.all.sample.name, user).execute
end
print '.'
diff --git a/db/fixtures/development/17_cycle_analytics.rb b/db/fixtures/development/17_cycle_analytics.rb
index 95d956fb402..fa19775a571 100644
--- a/db/fixtures/development/17_cycle_analytics.rb
+++ b/db/fixtures/development/17_cycle_analytics.rb
@@ -157,16 +157,17 @@ class Gitlab::Seeder::CycleAnalytics
end
def create_new_vsm_project
+ namespace = FactoryBot.create(
+ :group,
+ name: "Value Stream Management Group #{suffix}",
+ path: "vsmg-#{suffix}"
+ )
project = FactoryBot.create(
:project,
name: "Value Stream Management Project #{suffix}",
path: "vsmp-#{suffix}",
creator: admin,
- namespace: FactoryBot.create(
- :group,
- name: "Value Stream Management Group #{suffix}",
- path: "vsmg-#{suffix}"
- )
+ namespace: namespace
)
project.create_repository
diff --git a/db/fixtures/development/20_nested_groups.rb b/db/fixtures/development/20_nested_groups.rb
index 8f64dfbd644..d9aea17aa16 100644
--- a/db/fixtures/development/20_nested_groups.rb
+++ b/db/fixtures/development/20_nested_groups.rb
@@ -23,8 +23,9 @@ Sidekiq::Testing.inline! do
full_path = url.sub('https://android.googlesource.com/', '')
full_path = full_path.sub(/\.git\z/, '')
full_path, _, project_path = full_path.rpartition('/')
- group = Group.find_by_full_path(full_path) ||
- Groups::NestedCreateService.new(user, group_path: full_path).execute
+ group = Sidekiq::Worker.skipping_transaction_check do
+ Group.find_by_full_path(full_path) || Groups::NestedCreateService.new(user, group_path: full_path).execute
+ end
params = {
import_url: url,
diff --git a/db/fixtures/development/98_gitlab_instance_administration_project.rb b/db/fixtures/development/98_gitlab_instance_administration_project.rb
index 8be707ffb08..9f50ce6a7e4 100644
--- a/db/fixtures/development/98_gitlab_instance_administration_project.rb
+++ b/db/fixtures/development/98_gitlab_instance_administration_project.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
-response = ::Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService.new.execute
+response = Sidekiq::Worker.skipping_transaction_check do
+ ::Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService.new.execute
+end
if response[:status] == :success
puts "Successfully created self monitoring project."
diff --git a/db/init_structure.sql b/db/init_structure.sql
index e2048e436ed..d3f576a7b89 100644
--- a/db/init_structure.sql
+++ b/db/init_structure.sql
@@ -1,5 +1,8740 @@
+CREATE SCHEMA gitlab_partitions_dynamic;
+
+COMMENT ON SCHEMA gitlab_partitions_dynamic IS 'Schema to hold partitions managed dynamically from the application, e.g. for time space partitioning.';
+
+CREATE SCHEMA gitlab_partitions_static;
+
+COMMENT ON SCHEMA gitlab_partitions_static IS 'Schema to hold static partitions, e.g. for hash partitioning';
+
+CREATE EXTENSION IF NOT EXISTS btree_gist;
+
CREATE EXTENSION IF NOT EXISTS pg_trgm;
+CREATE FUNCTION table_sync_function_2be879775d() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+IF (TG_OP = 'DELETE') THEN
+ DELETE FROM audit_events_archived where id = OLD.id;
+ELSIF (TG_OP = 'UPDATE') THEN
+ UPDATE audit_events_archived
+ SET author_id = NEW.author_id,
+ entity_id = NEW.entity_id,
+ entity_type = NEW.entity_type,
+ details = NEW.details,
+ created_at = NEW.created_at,
+ ip_address = NEW.ip_address,
+ author_name = NEW.author_name,
+ target_details = NEW.target_details,
+ entity_path = NEW.entity_path,
+ target_type = NEW.target_type,
+ target_id = NEW.target_id
+ WHERE audit_events_archived.id = NEW.id;
+ELSIF (TG_OP = 'INSERT') THEN
+ INSERT INTO audit_events_archived (id,
+ author_id,
+ entity_id,
+ entity_type,
+ details,
+ created_at,
+ ip_address,
+ author_name,
+ target_details,
+ entity_path,
+ target_type,
+ target_id)
+ VALUES (NEW.id,
+ NEW.author_id,
+ NEW.entity_id,
+ NEW.entity_type,
+ NEW.details,
+ NEW.created_at,
+ NEW.ip_address,
+ NEW.author_name,
+ NEW.target_details,
+ NEW.entity_path,
+ NEW.target_type,
+ NEW.target_id);
+END IF;
+RETURN NULL;
+
+END
+$$;
+
+COMMENT ON FUNCTION table_sync_function_2be879775d() IS 'Partitioning migration: table sync for audit_events table';
+
+CREATE TABLE audit_events (
+ id bigint NOT NULL,
+ author_id integer NOT NULL,
+ entity_id integer NOT NULL,
+ entity_type character varying NOT NULL,
+ details text,
+ ip_address inet,
+ author_name text,
+ target_details text,
+ entity_path text,
+ created_at timestamp without time zone NOT NULL,
+ target_type text,
+ target_id bigint,
+ CONSTRAINT check_83ff8406e2 CHECK ((char_length(author_name) <= 255)),
+ CONSTRAINT check_97a8c868e7 CHECK ((char_length(target_type) <= 255))
+)
+PARTITION BY RANGE (created_at);
+
+CREATE TABLE product_analytics_events_experimental (
+ id bigint NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+)
+PARTITION BY HASH (project_id);
+
+CREATE SEQUENCE product_analytics_events_experimental_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE product_analytics_events_experimental_id_seq OWNED BY product_analytics_events_experimental.id;
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_00 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_00 FOR VALUES WITH (modulus 64, remainder 0);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_01 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_01 FOR VALUES WITH (modulus 64, remainder 1);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_02 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_02 FOR VALUES WITH (modulus 64, remainder 2);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_03 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_03 FOR VALUES WITH (modulus 64, remainder 3);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_04 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_04 FOR VALUES WITH (modulus 64, remainder 4);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_05 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_05 FOR VALUES WITH (modulus 64, remainder 5);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_06 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_06 FOR VALUES WITH (modulus 64, remainder 6);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_07 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_07 FOR VALUES WITH (modulus 64, remainder 7);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_08 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_08 FOR VALUES WITH (modulus 64, remainder 8);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_09 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_09 FOR VALUES WITH (modulus 64, remainder 9);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_10 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_10 FOR VALUES WITH (modulus 64, remainder 10);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_11 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_11 FOR VALUES WITH (modulus 64, remainder 11);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_12 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_12 FOR VALUES WITH (modulus 64, remainder 12);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_13 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_13 FOR VALUES WITH (modulus 64, remainder 13);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_14 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_14 FOR VALUES WITH (modulus 64, remainder 14);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_15 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_15 FOR VALUES WITH (modulus 64, remainder 15);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_16 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_16 FOR VALUES WITH (modulus 64, remainder 16);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_17 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_17 FOR VALUES WITH (modulus 64, remainder 17);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_18 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_18 FOR VALUES WITH (modulus 64, remainder 18);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_19 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_19 FOR VALUES WITH (modulus 64, remainder 19);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_20 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_20 FOR VALUES WITH (modulus 64, remainder 20);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_21 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_21 FOR VALUES WITH (modulus 64, remainder 21);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_22 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_22 FOR VALUES WITH (modulus 64, remainder 22);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_23 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_23 FOR VALUES WITH (modulus 64, remainder 23);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_24 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_24 FOR VALUES WITH (modulus 64, remainder 24);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_25 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_25 FOR VALUES WITH (modulus 64, remainder 25);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_26 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_26 FOR VALUES WITH (modulus 64, remainder 26);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_27 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_27 FOR VALUES WITH (modulus 64, remainder 27);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_28 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_28 FOR VALUES WITH (modulus 64, remainder 28);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_29 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_29 FOR VALUES WITH (modulus 64, remainder 29);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_30 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_30 FOR VALUES WITH (modulus 64, remainder 30);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_31 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_31 FOR VALUES WITH (modulus 64, remainder 31);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_32 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_32 FOR VALUES WITH (modulus 64, remainder 32);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_33 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_33 FOR VALUES WITH (modulus 64, remainder 33);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_34 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_34 FOR VALUES WITH (modulus 64, remainder 34);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_35 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_35 FOR VALUES WITH (modulus 64, remainder 35);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_36 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_36 FOR VALUES WITH (modulus 64, remainder 36);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_37 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_37 FOR VALUES WITH (modulus 64, remainder 37);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_38 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_38 FOR VALUES WITH (modulus 64, remainder 38);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_39 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_39 FOR VALUES WITH (modulus 64, remainder 39);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_40 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_40 FOR VALUES WITH (modulus 64, remainder 40);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_41 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_41 FOR VALUES WITH (modulus 64, remainder 41);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_42 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_42 FOR VALUES WITH (modulus 64, remainder 42);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_43 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_43 FOR VALUES WITH (modulus 64, remainder 43);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_44 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_44 FOR VALUES WITH (modulus 64, remainder 44);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_45 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_45 FOR VALUES WITH (modulus 64, remainder 45);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_46 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_46 FOR VALUES WITH (modulus 64, remainder 46);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_47 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_47 FOR VALUES WITH (modulus 64, remainder 47);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_48 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_48 FOR VALUES WITH (modulus 64, remainder 48);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_49 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_49 FOR VALUES WITH (modulus 64, remainder 49);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_50 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_50 FOR VALUES WITH (modulus 64, remainder 50);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_51 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_51 FOR VALUES WITH (modulus 64, remainder 51);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_52 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_52 FOR VALUES WITH (modulus 64, remainder 52);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_53 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_53 FOR VALUES WITH (modulus 64, remainder 53);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_54 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_54 FOR VALUES WITH (modulus 64, remainder 54);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_55 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_55 FOR VALUES WITH (modulus 64, remainder 55);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_56 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_56 FOR VALUES WITH (modulus 64, remainder 56);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_57 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_57 FOR VALUES WITH (modulus 64, remainder 57);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_58 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_58 FOR VALUES WITH (modulus 64, remainder 58);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_59 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_59 FOR VALUES WITH (modulus 64, remainder 59);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_60 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_60 FOR VALUES WITH (modulus 64, remainder 60);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_61 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_61 FOR VALUES WITH (modulus 64, remainder 61);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_62 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_62 FOR VALUES WITH (modulus 64, remainder 62);
+
+CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_63 (
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ project_id integer NOT NULL,
+ platform character varying(255),
+ etl_tstamp timestamp with time zone,
+ collector_tstamp timestamp with time zone NOT NULL,
+ dvce_created_tstamp timestamp with time zone,
+ event character varying(128),
+ event_id character(36) NOT NULL,
+ txn_id integer,
+ name_tracker character varying(128),
+ v_tracker character varying(100),
+ v_collector character varying(100) NOT NULL,
+ v_etl character varying(100) NOT NULL,
+ user_id character varying(255),
+ user_ipaddress character varying(45),
+ user_fingerprint character varying(50),
+ domain_userid character varying(36),
+ domain_sessionidx smallint,
+ network_userid character varying(38),
+ geo_country character(2),
+ geo_region character(3),
+ geo_city character varying(75),
+ geo_zipcode character varying(15),
+ geo_latitude double precision,
+ geo_longitude double precision,
+ geo_region_name character varying(100),
+ ip_isp character varying(100),
+ ip_organization character varying(100),
+ ip_domain character varying(100),
+ ip_netspeed character varying(100),
+ page_url text,
+ page_title character varying(2000),
+ page_referrer text,
+ page_urlscheme character varying(16),
+ page_urlhost character varying(255),
+ page_urlport integer,
+ page_urlpath character varying(3000),
+ page_urlquery character varying(6000),
+ page_urlfragment character varying(3000),
+ refr_urlscheme character varying(16),
+ refr_urlhost character varying(255),
+ refr_urlport integer,
+ refr_urlpath character varying(6000),
+ refr_urlquery character varying(6000),
+ refr_urlfragment character varying(3000),
+ refr_medium character varying(25),
+ refr_source character varying(50),
+ refr_term character varying(255),
+ mkt_medium character varying(255),
+ mkt_source character varying(255),
+ mkt_term character varying(255),
+ mkt_content character varying(500),
+ mkt_campaign character varying(255),
+ se_category character varying(1000),
+ se_action character varying(1000),
+ se_label character varying(1000),
+ se_property character varying(1000),
+ se_value double precision,
+ tr_orderid character varying(255),
+ tr_affiliation character varying(255),
+ tr_total numeric(18,2),
+ tr_tax numeric(18,2),
+ tr_shipping numeric(18,2),
+ tr_city character varying(255),
+ tr_state character varying(255),
+ tr_country character varying(255),
+ ti_orderid character varying(255),
+ ti_sku character varying(255),
+ ti_name character varying(255),
+ ti_category character varying(255),
+ ti_price numeric(18,2),
+ ti_quantity integer,
+ pp_xoffset_min integer,
+ pp_xoffset_max integer,
+ pp_yoffset_min integer,
+ pp_yoffset_max integer,
+ useragent character varying(1000),
+ br_name character varying(50),
+ br_family character varying(50),
+ br_version character varying(50),
+ br_type character varying(50),
+ br_renderengine character varying(50),
+ br_lang character varying(255),
+ br_features_pdf boolean,
+ br_features_flash boolean,
+ br_features_java boolean,
+ br_features_director boolean,
+ br_features_quicktime boolean,
+ br_features_realplayer boolean,
+ br_features_windowsmedia boolean,
+ br_features_gears boolean,
+ br_features_silverlight boolean,
+ br_cookies boolean,
+ br_colordepth character varying(12),
+ br_viewwidth integer,
+ br_viewheight integer,
+ os_name character varying(50),
+ os_family character varying(50),
+ os_manufacturer character varying(50),
+ os_timezone character varying(50),
+ dvce_type character varying(50),
+ dvce_ismobile boolean,
+ dvce_screenwidth integer,
+ dvce_screenheight integer,
+ doc_charset character varying(128),
+ doc_width integer,
+ doc_height integer,
+ tr_currency character(3),
+ tr_total_base numeric(18,2),
+ tr_tax_base numeric(18,2),
+ tr_shipping_base numeric(18,2),
+ ti_currency character(3),
+ ti_price_base numeric(18,2),
+ base_currency character(3),
+ geo_timezone character varying(64),
+ mkt_clickid character varying(128),
+ mkt_network character varying(64),
+ etl_tags character varying(500),
+ dvce_sent_tstamp timestamp with time zone,
+ refr_domain_userid character varying(36),
+ refr_dvce_tstamp timestamp with time zone,
+ domain_sessionid character(36),
+ derived_tstamp timestamp with time zone,
+ event_vendor character varying(1000),
+ event_name character varying(1000),
+ event_format character varying(128),
+ event_version character varying(128),
+ event_fingerprint character varying(128),
+ true_tstamp timestamp with time zone
+);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_63 FOR VALUES WITH (modulus 64, remainder 63);
+
CREATE TABLE abuse_reports (
id integer NOT NULL,
reporter_id integer,
@@ -21,6 +8756,101 @@ CREATE SEQUENCE abuse_reports_id_seq
ALTER SEQUENCE abuse_reports_id_seq OWNED BY abuse_reports.id;
+CREATE TABLE alert_management_alert_assignees (
+ id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ alert_id bigint NOT NULL
+);
+
+CREATE SEQUENCE alert_management_alert_assignees_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE alert_management_alert_assignees_id_seq OWNED BY alert_management_alert_assignees.id;
+
+CREATE TABLE alert_management_alert_user_mentions (
+ id bigint NOT NULL,
+ alert_management_alert_id bigint NOT NULL,
+ note_id bigint,
+ mentioned_users_ids integer[],
+ mentioned_projects_ids integer[],
+ mentioned_groups_ids integer[]
+);
+
+CREATE SEQUENCE alert_management_alert_user_mentions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE alert_management_alert_user_mentions_id_seq OWNED BY alert_management_alert_user_mentions.id;
+
+CREATE TABLE alert_management_alerts (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ started_at timestamp with time zone NOT NULL,
+ ended_at timestamp with time zone,
+ events integer DEFAULT 1 NOT NULL,
+ iid integer NOT NULL,
+ severity smallint DEFAULT 0 NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
+ fingerprint bytea,
+ issue_id bigint,
+ project_id bigint NOT NULL,
+ title text NOT NULL,
+ description text,
+ service text,
+ monitoring_tool text,
+ hosts text[] DEFAULT '{}'::text[] NOT NULL,
+ payload jsonb DEFAULT '{}'::jsonb NOT NULL,
+ prometheus_alert_id integer,
+ environment_id integer,
+ domain smallint DEFAULT 0,
+ CONSTRAINT check_2df3e2fdc1 CHECK ((char_length(monitoring_tool) <= 100)),
+ CONSTRAINT check_5e9e57cadb CHECK ((char_length(description) <= 1000)),
+ CONSTRAINT check_bac14dddde CHECK ((char_length(service) <= 100)),
+ CONSTRAINT check_d1d1c2d14c CHECK ((char_length(title) <= 200))
+);
+
+CREATE SEQUENCE alert_management_alerts_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE alert_management_alerts_id_seq OWNED BY alert_management_alerts.id;
+
+CREATE TABLE alert_management_http_integrations (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ active boolean DEFAULT false NOT NULL,
+ encrypted_token text NOT NULL,
+ encrypted_token_iv text NOT NULL,
+ endpoint_identifier text NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_286943b636 CHECK ((char_length(encrypted_token_iv) <= 255)),
+ CONSTRAINT check_392143ccf4 CHECK ((char_length(name) <= 255)),
+ CONSTRAINT check_e270820180 CHECK ((char_length(endpoint_identifier) <= 255)),
+ CONSTRAINT check_f68577c4af CHECK ((char_length(encrypted_token) <= 255))
+);
+
+CREATE SEQUENCE alert_management_http_integrations_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE alert_management_http_integrations_id_seq OWNED BY alert_management_http_integrations.id;
+
CREATE TABLE alerts_service_data (
id bigint NOT NULL,
service_id integer NOT NULL,
@@ -68,7 +8898,8 @@ CREATE TABLE analytics_cycle_analytics_group_stages (
end_event_label_id bigint,
hidden boolean DEFAULT false NOT NULL,
custom boolean DEFAULT true NOT NULL,
- name character varying(255) NOT NULL
+ name character varying(255) NOT NULL,
+ group_value_stream_id bigint NOT NULL
);
CREATE SEQUENCE analytics_cycle_analytics_group_stages_id_seq
@@ -80,6 +8911,24 @@ CREATE SEQUENCE analytics_cycle_analytics_group_stages_id_seq
ALTER SEQUENCE analytics_cycle_analytics_group_stages_id_seq OWNED BY analytics_cycle_analytics_group_stages.id;
+CREATE TABLE analytics_cycle_analytics_group_value_streams (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ group_id bigint NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_bc1ed5f1f7 CHECK ((char_length(name) <= 100))
+);
+
+CREATE SEQUENCE analytics_cycle_analytics_group_value_streams_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE analytics_cycle_analytics_group_value_streams_id_seq OWNED BY analytics_cycle_analytics_group_value_streams.id;
+
CREATE TABLE analytics_cycle_analytics_project_stages (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -104,64 +8953,90 @@ CREATE SEQUENCE analytics_cycle_analytics_project_stages_id_seq
ALTER SEQUENCE analytics_cycle_analytics_project_stages_id_seq OWNED BY analytics_cycle_analytics_project_stages.id;
-CREATE TABLE analytics_language_trend_repository_languages (
- file_count integer DEFAULT 0 NOT NULL,
- programming_language_id bigint NOT NULL,
- project_id bigint NOT NULL,
- loc integer DEFAULT 0 NOT NULL,
- bytes integer DEFAULT 0 NOT NULL,
- percentage smallint DEFAULT 0 NOT NULL,
- snapshot_date date NOT NULL
+CREATE TABLE analytics_devops_adoption_segment_selections (
+ id bigint NOT NULL,
+ segment_id bigint NOT NULL,
+ group_id bigint,
+ project_id bigint,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ CONSTRAINT segment_selection_project_id_or_group_id_required CHECK ((((project_id <> NULL::bigint) AND (group_id IS NULL)) OR ((group_id <> NULL::bigint) AND (project_id IS NULL))))
);
-CREATE TABLE analytics_repository_file_commits (
+CREATE SEQUENCE analytics_devops_adoption_segment_selections_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE analytics_devops_adoption_segment_selections_id_seq OWNED BY analytics_devops_adoption_segment_selections.id;
+
+CREATE TABLE analytics_devops_adoption_segments (
id bigint NOT NULL,
- analytics_repository_file_id bigint NOT NULL,
- project_id bigint NOT NULL,
- committed_date date NOT NULL,
- commit_count smallint NOT NULL
+ name text NOT NULL,
+ last_recorded_at timestamp with time zone,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ CONSTRAINT check_4be7a006fd CHECK ((char_length(name) <= 255))
);
-CREATE SEQUENCE analytics_repository_file_commits_id_seq
+CREATE SEQUENCE analytics_devops_adoption_segments_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE analytics_repository_file_commits_id_seq OWNED BY analytics_repository_file_commits.id;
+ALTER SEQUENCE analytics_devops_adoption_segments_id_seq OWNED BY analytics_devops_adoption_segments.id;
-CREATE TABLE analytics_repository_file_edits (
+CREATE TABLE analytics_devops_adoption_snapshots (
id bigint NOT NULL,
- project_id bigint NOT NULL,
- analytics_repository_file_id bigint NOT NULL,
- committed_date date NOT NULL,
- num_edits integer DEFAULT 0 NOT NULL
+ segment_id bigint NOT NULL,
+ recorded_at timestamp with time zone NOT NULL,
+ issue_opened boolean NOT NULL,
+ merge_request_opened boolean NOT NULL,
+ merge_request_approved boolean NOT NULL,
+ runner_configured boolean NOT NULL,
+ pipeline_succeeded boolean NOT NULL,
+ deploy_succeeded boolean NOT NULL,
+ security_scan_succeeded boolean NOT NULL
);
-CREATE SEQUENCE analytics_repository_file_edits_id_seq
+CREATE SEQUENCE analytics_devops_adoption_snapshots_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE analytics_repository_file_edits_id_seq OWNED BY analytics_repository_file_edits.id;
+ALTER SEQUENCE analytics_devops_adoption_snapshots_id_seq OWNED BY analytics_devops_adoption_snapshots.id;
-CREATE TABLE analytics_repository_files (
+CREATE TABLE analytics_instance_statistics_measurements (
id bigint NOT NULL,
- project_id bigint NOT NULL,
- file_path character varying(4096) NOT NULL
+ count bigint NOT NULL,
+ recorded_at timestamp with time zone NOT NULL,
+ identifier smallint NOT NULL
);
-CREATE SEQUENCE analytics_repository_files_id_seq
+CREATE SEQUENCE analytics_instance_statistics_measurements_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE analytics_repository_files_id_seq OWNED BY analytics_repository_files.id;
+ALTER SEQUENCE analytics_instance_statistics_measurements_id_seq OWNED BY analytics_instance_statistics_measurements.id;
+
+CREATE TABLE analytics_language_trend_repository_languages (
+ file_count integer DEFAULT 0 NOT NULL,
+ programming_language_id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ loc integer DEFAULT 0 NOT NULL,
+ bytes integer DEFAULT 0 NOT NULL,
+ percentage smallint DEFAULT 0 NOT NULL,
+ snapshot_date date NOT NULL
+);
CREATE TABLE appearances (
id integer NOT NULL,
@@ -183,7 +9058,10 @@ CREATE TABLE appearances (
message_background_color text,
message_font_color text,
email_header_and_footer_enabled boolean DEFAULT false NOT NULL,
- updated_by integer
+ updated_by integer,
+ profile_image_guidelines text,
+ profile_image_guidelines_html text,
+ CONSTRAINT appearances_profile_image_guidelines CHECK ((char_length(profile_image_guidelines) <= 4096))
);
CREATE SEQUENCE appearances_id_seq
@@ -228,13 +9106,11 @@ CREATE TABLE application_settings (
max_attachment_size integer DEFAULT 10 NOT NULL,
default_project_visibility integer DEFAULT 0 NOT NULL,
default_snippet_visibility integer DEFAULT 0 NOT NULL,
- domain_whitelist text,
user_oauth_applications boolean DEFAULT true,
after_sign_out_path character varying,
session_expire_delay integer DEFAULT 10080 NOT NULL,
import_sources text,
help_page_text text,
- admin_notification_email character varying,
shared_runners_enabled boolean DEFAULT true NOT NULL,
max_artifacts_size integer DEFAULT 100 NOT NULL,
runners_registration_token character varying,
@@ -263,8 +9139,6 @@ CREATE TABLE application_settings (
user_default_external boolean DEFAULT false NOT NULL,
repository_storages character varying DEFAULT 'default'::character varying,
enabled_git_access_protocol character varying,
- domain_blacklist_enabled boolean DEFAULT false,
- domain_blacklist text,
usage_ping_enabled boolean DEFAULT true NOT NULL,
sign_in_text_html text,
help_page_text_html text,
@@ -328,17 +9202,16 @@ CREATE TABLE application_settings (
enforce_terms boolean DEFAULT false,
mirror_available boolean DEFAULT true NOT NULL,
hide_third_party_offers boolean DEFAULT false NOT NULL,
- instance_statistics_visibility_private boolean DEFAULT false NOT NULL,
receive_max_input_size integer,
web_ide_clientside_preview_enabled boolean DEFAULT false NOT NULL,
user_show_add_ssh_key_message boolean DEFAULT true NOT NULL,
outbound_local_requests_whitelist character varying(255)[] DEFAULT '{}'::character varying[] NOT NULL,
usage_stats_set_by_user_id integer,
- diff_max_patch_bytes integer DEFAULT 102400 NOT NULL,
+ diff_max_patch_bytes integer DEFAULT 204800 NOT NULL,
archive_builds_in_seconds integer,
commit_email_hostname character varying,
first_day_of_week integer DEFAULT 0 NOT NULL,
- protected_ci_variables boolean DEFAULT false NOT NULL,
+ protected_ci_variables boolean DEFAULT true NOT NULL,
runners_registration_token_encrypted character varying,
local_markdown_version integer DEFAULT 0 NOT NULL,
asset_proxy_enabled boolean DEFAULT false NOT NULL,
@@ -358,7 +9231,6 @@ CREATE TABLE application_settings (
elasticsearch_aws_region character varying DEFAULT 'us-east-1'::character varying,
elasticsearch_aws_access_key character varying,
geo_status_timeout integer DEFAULT 10,
- elasticsearch_experimental_indexer boolean,
check_namespace_plan boolean DEFAULT false NOT NULL,
mirror_max_delay integer DEFAULT 300 NOT NULL,
mirror_max_capacity integer DEFAULT 100 NOT NULL,
@@ -395,7 +9267,7 @@ CREATE TABLE application_settings (
throttle_protected_paths_enabled boolean DEFAULT false NOT NULL,
throttle_protected_paths_requests_per_period integer DEFAULT 10 NOT NULL,
throttle_protected_paths_period_in_seconds integer DEFAULT 60 NOT NULL,
- protected_paths character varying(255)[] DEFAULT '{/users/password,/users/sign_in,/api/v3/session.json,/api/v3/session,/api/v4/session.json,/api/v4/session,/users,/users/confirmation,/unsubscribes/,/import/github/personal_access_token,/admin/session}'::character varying[],
+ protected_paths character varying(255)[] DEFAULT '{/users/password,/users/sign_in,/api/v3/session.json,/api/v3/session,/api/v4/session.json,/api/v4/session,/users,/users/confirmation,/unsubscribes/,/import/github/personal_access_token,/admin/session,/oauth/authorize,/oauth/token}'::character varying[],
snowplow_collector_hostname character varying,
sourcegraph_enabled boolean DEFAULT false NOT NULL,
sourcegraph_url character varying(255),
@@ -407,7 +9279,6 @@ CREATE TABLE application_settings (
productivity_analytics_start_date timestamp with time zone,
push_event_activities_limit integer DEFAULT 3 NOT NULL,
custom_http_clone_url_root character varying(511),
- snowplow_iglu_registry_url character varying(255),
deletion_adjourned_period integer DEFAULT 7 NOT NULL,
snowplow_app_id character varying,
eks_integration_enabled boolean DEFAULT false NOT NULL,
@@ -434,7 +9305,91 @@ CREATE TABLE application_settings (
minimum_password_length integer DEFAULT 8 NOT NULL,
updating_name_disabled_for_users boolean DEFAULT false NOT NULL,
force_pages_access_control boolean DEFAULT false NOT NULL,
- CONSTRAINT check_b4f67a6296 CHECK ((allow_local_requests_from_web_hooks_and_services IS NOT NULL))
+ instance_administrators_group_id integer,
+ disable_overriding_approvers_per_merge_request boolean DEFAULT false NOT NULL,
+ prevent_merge_requests_author_approval boolean DEFAULT false NOT NULL,
+ prevent_merge_requests_committers_approval boolean DEFAULT false NOT NULL,
+ elasticsearch_indexed_field_length_limit integer DEFAULT 0 NOT NULL,
+ elasticsearch_max_bulk_size_mb smallint DEFAULT 10 NOT NULL,
+ elasticsearch_max_bulk_concurrency smallint DEFAULT 10 NOT NULL,
+ email_restrictions_enabled boolean DEFAULT false NOT NULL,
+ email_restrictions text,
+ npm_package_requests_forwarding boolean DEFAULT true NOT NULL,
+ push_rule_id bigint,
+ issues_create_limit integer DEFAULT 0 NOT NULL,
+ seat_link_enabled boolean DEFAULT true NOT NULL,
+ container_expiration_policies_enable_historic_entries boolean DEFAULT false NOT NULL,
+ group_owners_can_manage_default_branch_protection boolean DEFAULT true NOT NULL,
+ container_registry_vendor text DEFAULT ''::text NOT NULL,
+ container_registry_version text DEFAULT ''::text NOT NULL,
+ container_registry_features text[] DEFAULT '{}'::text[] NOT NULL,
+ spam_check_endpoint_url text,
+ spam_check_endpoint_enabled boolean DEFAULT false NOT NULL,
+ elasticsearch_pause_indexing boolean DEFAULT false NOT NULL,
+ repository_storages_weighted jsonb DEFAULT '{}'::jsonb NOT NULL,
+ max_import_size integer DEFAULT 50 NOT NULL,
+ enforce_pat_expiration boolean DEFAULT true NOT NULL,
+ compliance_frameworks smallint[] DEFAULT '{}'::smallint[] NOT NULL,
+ notify_on_unknown_sign_in boolean DEFAULT true NOT NULL,
+ default_branch_name text,
+ maintenance_mode boolean DEFAULT false NOT NULL,
+ maintenance_mode_message text,
+ project_import_limit integer DEFAULT 6 NOT NULL,
+ project_export_limit integer DEFAULT 6 NOT NULL,
+ project_download_export_limit integer DEFAULT 1 NOT NULL,
+ group_import_limit integer DEFAULT 6 NOT NULL,
+ group_export_limit integer DEFAULT 6 NOT NULL,
+ group_download_export_limit integer DEFAULT 1 NOT NULL,
+ container_registry_delete_tags_service_timeout integer DEFAULT 250 NOT NULL,
+ wiki_page_max_content_bytes bigint DEFAULT 52428800 NOT NULL,
+ elasticsearch_indexed_file_size_limit_kb integer DEFAULT 1024 NOT NULL,
+ enforce_namespace_storage_limit boolean DEFAULT false NOT NULL,
+ gitpod_enabled boolean DEFAULT false NOT NULL,
+ gitpod_url text DEFAULT 'https://gitpod.io/'::text,
+ elasticsearch_client_request_timeout integer DEFAULT 0 NOT NULL,
+ abuse_notification_email character varying,
+ kroki_url text,
+ kroki_enabled boolean DEFAULT false NOT NULL,
+ help_page_documentation_base_url text,
+ container_registry_expiration_policies_worker_capacity integer DEFAULT 0 NOT NULL,
+ require_admin_approval_after_user_signup boolean DEFAULT true NOT NULL,
+ automatic_purchased_storage_allocation boolean DEFAULT false NOT NULL,
+ encrypted_ci_jwt_signing_key text,
+ encrypted_ci_jwt_signing_key_iv text,
+ elasticsearch_analyzers_smartcn_enabled boolean DEFAULT false NOT NULL,
+ elasticsearch_analyzers_smartcn_search boolean DEFAULT false NOT NULL,
+ elasticsearch_analyzers_kuromoji_enabled boolean DEFAULT false NOT NULL,
+ elasticsearch_analyzers_kuromoji_search boolean DEFAULT false NOT NULL,
+ new_user_signups_cap integer,
+ secret_detection_token_revocation_enabled boolean DEFAULT false NOT NULL,
+ secret_detection_token_revocation_url text,
+ encrypted_secret_detection_token_revocation_token text,
+ encrypted_secret_detection_token_revocation_token_iv text,
+ domain_denylist_enabled boolean DEFAULT false,
+ domain_denylist text,
+ domain_allowlist text,
+ secret_detection_revocation_token_types_url text,
+ encrypted_cloud_license_auth_token text,
+ encrypted_cloud_license_auth_token_iv text,
+ cloud_license_enabled boolean DEFAULT false NOT NULL,
+ personal_access_token_prefix text,
+ kroki_formats jsonb DEFAULT '{}'::jsonb NOT NULL,
+ disable_feed_token boolean DEFAULT false NOT NULL,
+ CONSTRAINT app_settings_registry_exp_policies_worker_capacity_positive CHECK ((container_registry_expiration_policies_worker_capacity >= 0)),
+ CONSTRAINT check_17d9558205 CHECK ((char_length(kroki_url) <= 1024)),
+ CONSTRAINT check_2dba05b802 CHECK ((char_length(gitpod_url) <= 255)),
+ CONSTRAINT check_51700b31b5 CHECK ((char_length(default_branch_name) <= 255)),
+ CONSTRAINT check_57123c9593 CHECK ((char_length(help_page_documentation_base_url) <= 255)),
+ CONSTRAINT check_718b4458ae CHECK ((char_length(personal_access_token_prefix) <= 20)),
+ CONSTRAINT check_85a39b68ff CHECK ((char_length(encrypted_ci_jwt_signing_key_iv) <= 255)),
+ CONSTRAINT check_9a719834eb CHECK ((char_length(secret_detection_token_revocation_url) <= 255)),
+ CONSTRAINT check_9c6c447a13 CHECK ((char_length(maintenance_mode_message) <= 255)),
+ CONSTRAINT check_a5704163cc CHECK ((char_length(secret_detection_revocation_token_types_url) <= 255)),
+ CONSTRAINT check_b4f67a6296 CHECK ((allow_local_requests_from_web_hooks_and_services IS NOT NULL)),
+ CONSTRAINT check_d03919528d CHECK ((char_length(container_registry_vendor) <= 255)),
+ CONSTRAINT check_d820146492 CHECK ((char_length(spam_check_endpoint_url) <= 255)),
+ CONSTRAINT check_e5aba18f02 CHECK ((char_length(container_registry_version) <= 255)),
+ CONSTRAINT check_ef6176834f CHECK ((char_length(encrypted_cloud_license_auth_token_iv) <= 255))
);
CREATE SEQUENCE application_settings_id_seq
@@ -468,10 +9423,12 @@ CREATE TABLE approval_merge_request_rules (
updated_at timestamp with time zone NOT NULL,
merge_request_id integer NOT NULL,
approvals_required smallint DEFAULT 0 NOT NULL,
- code_owner boolean DEFAULT false NOT NULL,
name character varying NOT NULL,
rule_type smallint DEFAULT 1 NOT NULL,
- report_type smallint
+ report_type smallint,
+ section text,
+ modified_from_project_rule boolean DEFAULT false NOT NULL,
+ CONSTRAINT check_6fca5928b2 CHECK ((char_length(section) <= 255))
);
CREATE TABLE approval_merge_request_rules_approved_approvers (
@@ -562,6 +9519,11 @@ CREATE SEQUENCE approval_project_rules_id_seq
ALTER SEQUENCE approval_project_rules_id_seq OWNED BY approval_project_rules.id;
+CREATE TABLE approval_project_rules_protected_branches (
+ approval_project_rule_id bigint NOT NULL,
+ protected_branch_id bigint NOT NULL
+);
+
CREATE TABLE approval_project_rules_users (
id bigint NOT NULL,
approval_project_rule_id bigint NOT NULL,
@@ -633,15 +9595,49 @@ CREATE SEQUENCE approvers_id_seq
ALTER SEQUENCE approvers_id_seq OWNED BY approvers.id;
-CREATE TABLE audit_events (
+CREATE TABLE atlassian_identities (
+ user_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ expires_at timestamp with time zone,
+ extern_uid text NOT NULL,
+ encrypted_token bytea,
+ encrypted_token_iv bytea,
+ encrypted_refresh_token bytea,
+ encrypted_refresh_token_iv bytea,
+ CONSTRAINT atlassian_identities_refresh_token_iv_length_constraint CHECK ((octet_length(encrypted_refresh_token_iv) <= 12)),
+ CONSTRAINT atlassian_identities_refresh_token_length_constraint CHECK ((octet_length(encrypted_refresh_token) <= 512)),
+ CONSTRAINT atlassian_identities_token_iv_length_constraint CHECK ((octet_length(encrypted_token_iv) <= 12)),
+ CONSTRAINT atlassian_identities_token_length_constraint CHECK ((octet_length(encrypted_token) <= 2048)),
+ CONSTRAINT check_32f5779763 CHECK ((char_length(extern_uid) <= 255))
+);
+
+CREATE SEQUENCE atlassian_identities_user_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE atlassian_identities_user_id_seq OWNED BY atlassian_identities.user_id;
+
+CREATE TABLE audit_events_archived (
id integer NOT NULL,
author_id integer NOT NULL,
- type character varying NOT NULL,
entity_id integer NOT NULL,
entity_type character varying NOT NULL,
details text,
created_at timestamp without time zone,
- updated_at timestamp without time zone
+ ip_address inet,
+ author_name text,
+ target_details text,
+ entity_path text,
+ target_type text,
+ target_id bigint,
+ CONSTRAINT check_492aaa021d CHECK ((char_length(entity_path) <= 5500)),
+ CONSTRAINT check_82294106dd CHECK ((char_length(target_type) <= 255)),
+ CONSTRAINT check_83ff8406e2 CHECK ((char_length(author_name) <= 255)),
+ CONSTRAINT check_d493ec90b5 CHECK ((char_length(target_details) <= 5500))
);
CREATE SEQUENCE audit_events_id_seq
@@ -654,6 +9650,27 @@ CREATE SEQUENCE audit_events_id_seq
ALTER SEQUENCE audit_events_id_seq OWNED BY audit_events.id;
+CREATE TABLE authentication_events (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ user_id bigint,
+ result smallint NOT NULL,
+ ip_address inet,
+ provider text NOT NULL,
+ user_name text NOT NULL,
+ CONSTRAINT check_45a6cc4e80 CHECK ((char_length(user_name) <= 255)),
+ CONSTRAINT check_c64f424630 CHECK ((char_length(provider) <= 64))
+);
+
+CREATE SEQUENCE authentication_events_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE authentication_events_id_seq OWNED BY authentication_events.id;
+
CREATE TABLE award_emoji (
id integer NOT NULL,
name character varying,
@@ -678,8 +9695,46 @@ CREATE TABLE aws_roles (
user_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- role_arn character varying(2048) NOT NULL,
- role_external_id character varying(64) NOT NULL
+ role_arn character varying(2048),
+ role_external_id character varying(64) NOT NULL,
+ region text,
+ CONSTRAINT check_57adedab55 CHECK ((char_length(region) <= 255))
+);
+
+CREATE TABLE background_migration_jobs (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
+ class_name text NOT NULL,
+ arguments jsonb NOT NULL,
+ CONSTRAINT check_b0de0a5852 CHECK ((char_length(class_name) <= 200))
+);
+
+CREATE SEQUENCE background_migration_jobs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE background_migration_jobs_id_seq OWNED BY background_migration_jobs.id;
+
+CREATE TABLE backup_labels (
+ id integer NOT NULL,
+ title character varying,
+ color character varying,
+ project_id integer,
+ created_at timestamp without time zone,
+ updated_at timestamp without time zone,
+ template boolean DEFAULT false,
+ description character varying,
+ description_html text,
+ type character varying,
+ group_id integer,
+ cached_markdown_version integer,
+ restore_action integer,
+ new_title character varying
);
CREATE TABLE badges (
@@ -772,6 +9827,24 @@ CREATE SEQUENCE board_project_recent_visits_id_seq
ALTER SEQUENCE board_project_recent_visits_id_seq OWNED BY board_project_recent_visits.id;
+CREATE TABLE board_user_preferences (
+ id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ board_id bigint NOT NULL,
+ hide_labels boolean,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE board_user_preferences_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE board_user_preferences_id_seq OWNED BY board_user_preferences.id;
+
CREATE TABLE boards (
id integer NOT NULL,
project_id integer,
@@ -780,9 +9853,82 @@ CREATE TABLE boards (
group_id integer,
milestone_id integer,
weight integer,
- name character varying DEFAULT 'Development'::character varying NOT NULL
+ name character varying DEFAULT 'Development'::character varying NOT NULL,
+ hide_backlog_list boolean DEFAULT false NOT NULL,
+ hide_closed_list boolean DEFAULT false NOT NULL,
+ iteration_id bigint
+);
+
+CREATE TABLE boards_epic_board_labels (
+ id bigint NOT NULL,
+ epic_board_id bigint NOT NULL,
+ label_id bigint NOT NULL
+);
+
+CREATE SEQUENCE boards_epic_board_labels_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE boards_epic_board_labels_id_seq OWNED BY boards_epic_board_labels.id;
+
+CREATE TABLE boards_epic_board_positions (
+ id bigint NOT NULL,
+ epic_board_id bigint NOT NULL,
+ epic_id bigint NOT NULL,
+ relative_position integer,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE boards_epic_board_positions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE boards_epic_board_positions_id_seq OWNED BY boards_epic_board_positions.id;
+
+CREATE TABLE boards_epic_boards (
+ id bigint NOT NULL,
+ hide_backlog_list boolean DEFAULT false NOT NULL,
+ hide_closed_list boolean DEFAULT false NOT NULL,
+ group_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ name text DEFAULT 'Development'::text NOT NULL,
+ CONSTRAINT check_bcbbffe601 CHECK ((char_length(name) <= 255))
);
+CREATE SEQUENCE boards_epic_boards_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE boards_epic_boards_id_seq OWNED BY boards_epic_boards.id;
+
+CREATE TABLE boards_epic_user_preferences (
+ id bigint NOT NULL,
+ board_id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ epic_id bigint NOT NULL,
+ collapsed boolean DEFAULT false NOT NULL
+);
+
+CREATE SEQUENCE boards_epic_user_preferences_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE boards_epic_user_preferences_id_seq OWNED BY boards_epic_user_preferences.id;
+
CREATE SEQUENCE boards_id_seq
AS integer
START WITH 1
@@ -819,6 +9965,116 @@ CREATE SEQUENCE broadcast_messages_id_seq
ALTER SEQUENCE broadcast_messages_id_seq OWNED BY broadcast_messages.id;
+CREATE TABLE bulk_import_configurations (
+ id bigint NOT NULL,
+ bulk_import_id integer NOT NULL,
+ encrypted_url text,
+ encrypted_url_iv text,
+ encrypted_access_token text,
+ encrypted_access_token_iv text,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE bulk_import_configurations_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE bulk_import_configurations_id_seq OWNED BY bulk_import_configurations.id;
+
+CREATE TABLE bulk_import_entities (
+ id bigint NOT NULL,
+ bulk_import_id bigint NOT NULL,
+ parent_id bigint,
+ namespace_id bigint,
+ project_id bigint,
+ source_type smallint NOT NULL,
+ source_full_path text NOT NULL,
+ destination_name text NOT NULL,
+ destination_namespace text NOT NULL,
+ status smallint NOT NULL,
+ jid text,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ CONSTRAINT check_13f279f7da CHECK ((char_length(source_full_path) <= 255)),
+ CONSTRAINT check_715d725ea2 CHECK ((char_length(destination_name) <= 255)),
+ CONSTRAINT check_796a4d9cc6 CHECK ((char_length(jid) <= 255)),
+ CONSTRAINT check_b834fff4d9 CHECK ((char_length(destination_namespace) <= 255))
+);
+
+CREATE SEQUENCE bulk_import_entities_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE bulk_import_entities_id_seq OWNED BY bulk_import_entities.id;
+
+CREATE TABLE bulk_import_failures (
+ id bigint NOT NULL,
+ bulk_import_entity_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ pipeline_class text NOT NULL,
+ exception_class text NOT NULL,
+ exception_message text NOT NULL,
+ correlation_id_value text,
+ CONSTRAINT check_053d65c7a4 CHECK ((char_length(pipeline_class) <= 255)),
+ CONSTRAINT check_6eca8f972e CHECK ((char_length(exception_message) <= 255)),
+ CONSTRAINT check_c7dba8398e CHECK ((char_length(exception_class) <= 255)),
+ CONSTRAINT check_e787285882 CHECK ((char_length(correlation_id_value) <= 255))
+);
+
+CREATE SEQUENCE bulk_import_failures_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE bulk_import_failures_id_seq OWNED BY bulk_import_failures.id;
+
+CREATE TABLE bulk_import_trackers (
+ id bigint NOT NULL,
+ bulk_import_entity_id bigint NOT NULL,
+ relation text NOT NULL,
+ next_page text,
+ has_next_page boolean DEFAULT false NOT NULL,
+ CONSTRAINT check_2d45cae629 CHECK ((char_length(relation) <= 255)),
+ CONSTRAINT check_40aeaa600b CHECK ((char_length(next_page) <= 255)),
+ CONSTRAINT check_next_page_requirement CHECK (((has_next_page IS FALSE) OR (next_page IS NOT NULL)))
+);
+
+CREATE SEQUENCE bulk_import_trackers_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE bulk_import_trackers_id_seq OWNED BY bulk_import_trackers.id;
+
+CREATE TABLE bulk_imports (
+ id bigint NOT NULL,
+ user_id integer NOT NULL,
+ source_type smallint NOT NULL,
+ status smallint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE bulk_imports_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE bulk_imports_id_seq OWNED BY bulk_imports.id;
+
CREATE TABLE chat_names (
id integer NOT NULL,
user_id integer NOT NULL,
@@ -878,12 +10134,49 @@ CREATE SEQUENCE ci_build_needs_id_seq
ALTER SEQUENCE ci_build_needs_id_seq OWNED BY ci_build_needs.id;
+CREATE TABLE ci_build_pending_states (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ build_id bigint NOT NULL,
+ state smallint,
+ failure_reason smallint,
+ trace_checksum bytea,
+ trace_bytesize bigint
+);
+
+CREATE SEQUENCE ci_build_pending_states_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_build_pending_states_id_seq OWNED BY ci_build_pending_states.id;
+
+CREATE TABLE ci_build_report_results (
+ build_id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ data jsonb DEFAULT '{}'::jsonb NOT NULL
+);
+
+CREATE SEQUENCE ci_build_report_results_build_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_build_report_results_build_id_seq OWNED BY ci_build_report_results.build_id;
+
CREATE TABLE ci_build_trace_chunks (
id bigint NOT NULL,
build_id integer NOT NULL,
chunk_index integer NOT NULL,
data_store integer NOT NULL,
- raw_data bytea
+ raw_data bytea,
+ checksum bytea,
+ lock_version integer DEFAULT 0 NOT NULL
);
CREATE SEQUENCE ci_build_trace_chunks_id_seq
@@ -957,7 +10250,7 @@ CREATE TABLE ci_builds (
yaml_variables text,
queued_at timestamp without time zone,
token character varying,
- lock_version integer,
+ lock_version integer DEFAULT 0,
coverage_regex character varying,
auto_canceled_by_id integer,
retried boolean,
@@ -995,7 +10288,9 @@ CREATE TABLE ci_builds_metadata (
config_variables jsonb,
interruptible boolean,
has_exposed_artifacts boolean,
- environment_auto_stop_in character varying(255)
+ environment_auto_stop_in character varying(255),
+ expanded_environment_name character varying(255),
+ secrets jsonb DEFAULT '{}'::jsonb NOT NULL
);
CREATE SEQUENCE ci_builds_metadata_id_seq
@@ -1025,6 +10320,66 @@ CREATE SEQUENCE ci_builds_runner_session_id_seq
ALTER SEQUENCE ci_builds_runner_session_id_seq OWNED BY ci_builds_runner_session.id;
+CREATE TABLE ci_daily_build_group_report_results (
+ id bigint NOT NULL,
+ date date NOT NULL,
+ project_id bigint NOT NULL,
+ last_pipeline_id bigint NOT NULL,
+ ref_path text NOT NULL,
+ group_name text NOT NULL,
+ data jsonb NOT NULL,
+ default_branch boolean DEFAULT false NOT NULL
+);
+
+CREATE SEQUENCE ci_daily_build_group_report_results_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_daily_build_group_report_results_id_seq OWNED BY ci_daily_build_group_report_results.id;
+
+CREATE TABLE ci_deleted_objects (
+ id bigint NOT NULL,
+ file_store smallint DEFAULT 1 NOT NULL,
+ pick_up_at timestamp with time zone DEFAULT now() NOT NULL,
+ store_dir text NOT NULL,
+ file text NOT NULL,
+ CONSTRAINT check_5e151d6912 CHECK ((char_length(store_dir) <= 1024))
+);
+
+CREATE SEQUENCE ci_deleted_objects_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_deleted_objects_id_seq OWNED BY ci_deleted_objects.id;
+
+CREATE TABLE ci_freeze_periods (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ freeze_start text NOT NULL,
+ freeze_end text NOT NULL,
+ cron_timezone text NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ CONSTRAINT check_4a7939e04e CHECK ((char_length(freeze_end) <= 998)),
+ CONSTRAINT check_a92607bd2b CHECK ((char_length(freeze_start) <= 998)),
+ CONSTRAINT check_b14055adc3 CHECK ((char_length(cron_timezone) <= 255))
+);
+
+CREATE SEQUENCE ci_freeze_periods_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_freeze_periods_id_seq OWNED BY ci_freeze_periods.id;
+
CREATE TABLE ci_group_variables (
id integer NOT NULL,
key character varying NOT NULL,
@@ -1050,6 +10405,28 @@ CREATE SEQUENCE ci_group_variables_id_seq
ALTER SEQUENCE ci_group_variables_id_seq OWNED BY ci_group_variables.id;
+CREATE TABLE ci_instance_variables (
+ id bigint NOT NULL,
+ variable_type smallint DEFAULT 1 NOT NULL,
+ masked boolean DEFAULT false,
+ protected boolean DEFAULT false,
+ key text NOT NULL,
+ encrypted_value text,
+ encrypted_value_iv text,
+ CONSTRAINT check_07a45a5bcb CHECK ((char_length(encrypted_value_iv) <= 255)),
+ CONSTRAINT check_5aede12208 CHECK ((char_length(key) <= 255)),
+ CONSTRAINT check_956afd70f1 CHECK ((char_length(encrypted_value) <= 13579))
+);
+
+CREATE SEQUENCE ci_instance_variables_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_instance_variables_id_seq OWNED BY ci_instance_variables.id;
+
CREATE TABLE ci_job_artifacts (
id integer NOT NULL,
project_id integer NOT NULL,
@@ -1060,10 +10437,11 @@ CREATE TABLE ci_job_artifacts (
updated_at timestamp with time zone NOT NULL,
expire_at timestamp with time zone,
file character varying,
- file_store integer,
+ file_store integer DEFAULT 1,
file_sha256 bytea,
file_format smallint,
- file_location smallint
+ file_location smallint,
+ CONSTRAINT check_27f0f6dbab CHECK ((file_store IS NOT NULL))
);
CREATE SEQUENCE ci_job_artifacts_id_seq
@@ -1082,7 +10460,8 @@ CREATE TABLE ci_job_variables (
encrypted_value text,
encrypted_value_iv character varying,
job_id bigint NOT NULL,
- variable_type smallint DEFAULT 1 NOT NULL
+ variable_type smallint DEFAULT 1 NOT NULL,
+ source smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE ci_job_variables_id_seq
@@ -1094,6 +10473,31 @@ CREATE SEQUENCE ci_job_variables_id_seq
ALTER SEQUENCE ci_job_variables_id_seq OWNED BY ci_job_variables.id;
+CREATE TABLE ci_pipeline_artifacts (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ pipeline_id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ size integer NOT NULL,
+ file_store smallint DEFAULT 1 NOT NULL,
+ file_type smallint NOT NULL,
+ file_format smallint NOT NULL,
+ file text,
+ expire_at timestamp with time zone,
+ CONSTRAINT check_191b5850ec CHECK ((char_length(file) <= 255)),
+ CONSTRAINT check_abeeb71caf CHECK ((file IS NOT NULL))
+);
+
+CREATE SEQUENCE ci_pipeline_artifacts_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_pipeline_artifacts_id_seq OWNED BY ci_pipeline_artifacts.id;
+
CREATE TABLE ci_pipeline_chat_data (
id bigint NOT NULL,
pipeline_id integer NOT NULL,
@@ -1110,6 +10514,23 @@ CREATE SEQUENCE ci_pipeline_chat_data_id_seq
ALTER SEQUENCE ci_pipeline_chat_data_id_seq OWNED BY ci_pipeline_chat_data.id;
+CREATE TABLE ci_pipeline_messages (
+ id bigint NOT NULL,
+ severity smallint DEFAULT 0 NOT NULL,
+ pipeline_id integer NOT NULL,
+ content text NOT NULL,
+ CONSTRAINT check_58ca2981b2 CHECK ((char_length(content) <= 10000))
+);
+
+CREATE SEQUENCE ci_pipeline_messages_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_pipeline_messages_id_seq OWNED BY ci_pipeline_messages.id;
+
CREATE TABLE ci_pipeline_schedule_variables (
id integer NOT NULL,
key character varying NOT NULL,
@@ -1194,7 +10615,7 @@ CREATE TABLE ci_pipelines (
finished_at timestamp without time zone,
duration integer,
user_id integer,
- lock_version integer,
+ lock_version integer DEFAULT 0,
auto_canceled_by_id integer,
pipeline_schedule_id integer,
source integer,
@@ -1205,7 +10626,9 @@ CREATE TABLE ci_pipelines (
merge_request_id integer,
source_sha bytea,
target_sha bytea,
- external_pull_request_id bigint
+ external_pull_request_id bigint,
+ ci_ref_id bigint,
+ locked smallint DEFAULT 1 NOT NULL
);
CREATE TABLE ci_pipelines_config (
@@ -1232,14 +10655,30 @@ CREATE SEQUENCE ci_pipelines_id_seq
ALTER SEQUENCE ci_pipelines_id_seq OWNED BY ci_pipelines.id;
+CREATE TABLE ci_platform_metrics (
+ id bigint NOT NULL,
+ recorded_at timestamp with time zone NOT NULL,
+ platform_target text NOT NULL,
+ count integer NOT NULL,
+ CONSTRAINT check_f922abc32b CHECK ((char_length(platform_target) <= 255)),
+ CONSTRAINT ci_platform_metrics_check_count_positive CHECK ((count > 0))
+);
+
+CREATE SEQUENCE ci_platform_metrics_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_platform_metrics_id_seq OWNED BY ci_platform_metrics.id;
+
CREATE TABLE ci_refs (
id bigint NOT NULL,
- project_id integer NOT NULL,
- lock_version integer DEFAULT 0,
- last_updated_by_pipeline_id integer,
- tag boolean DEFAULT false NOT NULL,
- ref character varying(255) NOT NULL,
- status character varying(255) NOT NULL
+ project_id bigint NOT NULL,
+ lock_version integer DEFAULT 0 NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
+ ref_path text NOT NULL
);
CREATE SEQUENCE ci_refs_id_seq
@@ -1339,7 +10778,9 @@ CREATE TABLE ci_runners (
maximum_timeout integer,
ip_address character varying,
runner_type smallint NOT NULL,
- token_encrypted character varying
+ token_encrypted character varying,
+ public_projects_minutes_cost_factor double precision DEFAULT 0.0 NOT NULL,
+ private_projects_minutes_cost_factor double precision DEFAULT 1.0 NOT NULL
);
CREATE SEQUENCE ci_runners_id_seq
@@ -1371,6 +10812,21 @@ CREATE SEQUENCE ci_sources_pipelines_id_seq
ALTER SEQUENCE ci_sources_pipelines_id_seq OWNED BY ci_sources_pipelines.id;
+CREATE TABLE ci_sources_projects (
+ id bigint NOT NULL,
+ pipeline_id bigint NOT NULL,
+ source_project_id bigint NOT NULL
+);
+
+CREATE SEQUENCE ci_sources_projects_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_sources_projects_id_seq OWNED BY ci_sources_projects.id;
+
CREATE TABLE ci_stages (
id integer NOT NULL,
project_id integer,
@@ -1379,7 +10835,7 @@ CREATE TABLE ci_stages (
updated_at timestamp without time zone,
name character varying,
status integer,
- lock_version integer,
+ lock_version integer DEFAULT 0,
"position" integer
);
@@ -1408,6 +10864,38 @@ CREATE SEQUENCE ci_subscriptions_projects_id_seq
ALTER SEQUENCE ci_subscriptions_projects_id_seq OWNED BY ci_subscriptions_projects.id;
+CREATE TABLE ci_test_case_failures (
+ id bigint NOT NULL,
+ failed_at timestamp with time zone,
+ test_case_id bigint NOT NULL,
+ build_id bigint NOT NULL
+);
+
+CREATE SEQUENCE ci_test_case_failures_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_test_case_failures_id_seq OWNED BY ci_test_case_failures.id;
+
+CREATE TABLE ci_test_cases (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ key_hash text NOT NULL,
+ CONSTRAINT check_dd3c5d1c15 CHECK ((char_length(key_hash) <= 64))
+);
+
+CREATE SEQUENCE ci_test_cases_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_test_cases_id_seq OWNED BY ci_test_cases.id;
+
CREATE TABLE ci_trigger_requests (
id integer NOT NULL,
trigger_id integer NOT NULL,
@@ -1472,6 +10960,42 @@ CREATE SEQUENCE ci_variables_id_seq
ALTER SEQUENCE ci_variables_id_seq OWNED BY ci_variables.id;
+CREATE TABLE cluster_agent_tokens (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ agent_id bigint NOT NULL,
+ token_encrypted text NOT NULL,
+ CONSTRAINT check_c60daed227 CHECK ((char_length(token_encrypted) <= 255))
+);
+
+CREATE SEQUENCE cluster_agent_tokens_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE cluster_agent_tokens_id_seq OWNED BY cluster_agent_tokens.id;
+
+CREATE TABLE cluster_agents (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_3498369510 CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE cluster_agents_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE cluster_agents_id_seq OWNED BY cluster_agents.id;
+
CREATE TABLE cluster_groups (
id integer NOT NULL,
cluster_id integer NOT NULL,
@@ -1535,7 +11059,6 @@ ALTER SEQUENCE cluster_projects_id_seq OWNED BY cluster_projects.id;
CREATE TABLE cluster_providers_aws (
id bigint NOT NULL,
cluster_id bigint NOT NULL,
- created_by_user_id integer,
num_nodes integer NOT NULL,
status integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -1551,7 +11074,9 @@ CREATE TABLE cluster_providers_aws (
encrypted_secret_access_key_iv character varying(255),
encrypted_secret_access_key text,
session_token text,
- status_reason text
+ status_reason text,
+ kubernetes_version text DEFAULT '1.14'::text NOT NULL,
+ CONSTRAINT check_f1f42cd85e CHECK ((char_length(kubernetes_version) <= 30))
);
CREATE SEQUENCE cluster_providers_aws_id_seq
@@ -1608,7 +11133,8 @@ CREATE TABLE clusters (
namespace_per_environment boolean DEFAULT true NOT NULL,
cleanup_status smallint DEFAULT 1 NOT NULL,
cleanup_status_reason text,
- management_project_id integer
+ management_project_id integer,
+ helm_major_version integer DEFAULT 2 NOT NULL
);
CREATE TABLE clusters_applications_cert_managers (
@@ -1632,6 +11158,24 @@ CREATE SEQUENCE clusters_applications_cert_managers_id_seq
ALTER SEQUENCE clusters_applications_cert_managers_id_seq OWNED BY clusters_applications_cert_managers.id;
+CREATE TABLE clusters_applications_cilium (
+ id bigint NOT NULL,
+ cluster_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ status integer NOT NULL,
+ status_reason text
+);
+
+CREATE SEQUENCE clusters_applications_cilium_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE clusters_applications_cilium_id_seq OWNED BY clusters_applications_cilium.id;
+
CREATE TABLE clusters_applications_crossplane (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -1659,7 +11203,6 @@ CREATE TABLE clusters_applications_elastic_stacks (
cluster_id bigint NOT NULL,
status integer NOT NULL,
version character varying(255) NOT NULL,
- kibana_hostname character varying(255),
status_reason text
);
@@ -1672,6 +11215,30 @@ CREATE SEQUENCE clusters_applications_elastic_stacks_id_seq
ALTER SEQUENCE clusters_applications_elastic_stacks_id_seq OWNED BY clusters_applications_elastic_stacks.id;
+CREATE TABLE clusters_applications_fluentd (
+ id bigint NOT NULL,
+ protocol smallint NOT NULL,
+ status integer NOT NULL,
+ port integer NOT NULL,
+ cluster_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ version character varying(255) NOT NULL,
+ host character varying(255) NOT NULL,
+ status_reason text,
+ waf_log_enabled boolean DEFAULT true NOT NULL,
+ cilium_log_enabled boolean DEFAULT true NOT NULL
+);
+
+CREATE SEQUENCE clusters_applications_fluentd_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE clusters_applications_fluentd_id_seq OWNED BY clusters_applications_fluentd.id;
+
CREATE TABLE clusters_applications_helm (
id integer NOT NULL,
cluster_id integer NOT NULL,
@@ -1707,7 +11274,8 @@ CREATE TABLE clusters_applications_ingress (
status_reason text,
external_ip character varying,
external_hostname character varying,
- modsecurity_enabled boolean
+ modsecurity_enabled boolean,
+ modsecurity_mode smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE clusters_applications_ingress_id_seq
@@ -1775,7 +11343,8 @@ CREATE TABLE clusters_applications_prometheus (
updated_at timestamp with time zone NOT NULL,
encrypted_alert_manager_token character varying,
encrypted_alert_manager_token_iv character varying,
- last_update_started_at timestamp with time zone
+ last_update_started_at timestamp with time zone,
+ healthy boolean
);
CREATE SEQUENCE clusters_applications_prometheus_id_seq
@@ -1862,16 +11431,40 @@ CREATE SEQUENCE commit_user_mentions_id_seq
ALTER SEQUENCE commit_user_mentions_id_seq OWNED BY commit_user_mentions.id;
+CREATE TABLE compliance_management_frameworks (
+ id bigint NOT NULL,
+ group_id bigint,
+ name text NOT NULL,
+ description text NOT NULL,
+ color text NOT NULL,
+ namespace_id integer NOT NULL,
+ regulated boolean DEFAULT true NOT NULL,
+ CONSTRAINT check_08cd34b2c2 CHECK ((char_length(color) <= 10)),
+ CONSTRAINT check_1617e0b87e CHECK ((char_length(description) <= 255)),
+ CONSTRAINT check_ab00bc2193 CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE compliance_management_frameworks_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE compliance_management_frameworks_id_seq OWNED BY compliance_management_frameworks.id;
+
CREATE TABLE container_expiration_policies (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
next_run_at timestamp with time zone,
project_id bigint NOT NULL,
- name_regex character varying(255),
- cadence character varying(12) DEFAULT '7d'::character varying NOT NULL,
- older_than character varying(12),
- keep_n integer,
- enabled boolean DEFAULT false NOT NULL
+ name_regex character varying(255) DEFAULT '.*'::character varying,
+ cadence character varying(12) DEFAULT '1d'::character varying NOT NULL,
+ older_than character varying(12) DEFAULT '90d'::character varying,
+ keep_n integer DEFAULT 10,
+ enabled boolean DEFAULT false NOT NULL,
+ name_regex_keep text,
+ CONSTRAINT container_expiration_policies_name_regex_keep CHECK ((char_length(name_regex_keep) <= 255))
);
CREATE TABLE container_repositories (
@@ -1879,7 +11472,10 @@ CREATE TABLE container_repositories (
project_id integer NOT NULL,
name character varying NOT NULL,
created_at timestamp without time zone NOT NULL,
- updated_at timestamp without time zone NOT NULL
+ updated_at timestamp without time zone NOT NULL,
+ status smallint,
+ expiration_policy_started_at timestamp with time zone,
+ expiration_policy_cleanup_status smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE container_repositories_id_seq
@@ -1938,6 +11534,153 @@ CREATE SEQUENCE conversational_development_index_metrics_id_seq
ALTER SEQUENCE conversational_development_index_metrics_id_seq OWNED BY conversational_development_index_metrics.id;
+CREATE TABLE csv_issue_imports (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE csv_issue_imports_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE csv_issue_imports_id_seq OWNED BY csv_issue_imports.id;
+
+CREATE TABLE custom_emoji (
+ id bigint NOT NULL,
+ namespace_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ name text NOT NULL,
+ file text NOT NULL,
+ external boolean DEFAULT true NOT NULL,
+ CONSTRAINT check_8c586dd507 CHECK ((char_length(name) <= 36)),
+ CONSTRAINT check_dd5d60f1fb CHECK ((char_length(file) <= 255))
+);
+
+CREATE SEQUENCE custom_emoji_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE custom_emoji_id_seq OWNED BY custom_emoji.id;
+
+CREATE TABLE dast_scanner_profiles (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id integer NOT NULL,
+ spider_timeout smallint,
+ target_timeout smallint,
+ name text NOT NULL,
+ scan_type smallint DEFAULT 1 NOT NULL,
+ use_ajax_spider boolean DEFAULT false NOT NULL,
+ show_debug_messages boolean DEFAULT false NOT NULL,
+ CONSTRAINT check_568568fabf CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE dast_scanner_profiles_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE dast_scanner_profiles_id_seq OWNED BY dast_scanner_profiles.id;
+
+CREATE TABLE dast_site_profiles (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ dast_site_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_6cfab17b48 CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE dast_site_profiles_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE dast_site_profiles_id_seq OWNED BY dast_site_profiles.id;
+
+CREATE TABLE dast_site_tokens (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ expired_at timestamp with time zone,
+ token text NOT NULL,
+ url text NOT NULL,
+ CONSTRAINT check_02a6bf20a7 CHECK ((char_length(token) <= 255)),
+ CONSTRAINT check_69ab8622a6 CHECK ((char_length(url) <= 255))
+);
+
+CREATE SEQUENCE dast_site_tokens_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE dast_site_tokens_id_seq OWNED BY dast_site_tokens.id;
+
+CREATE TABLE dast_site_validations (
+ id bigint NOT NULL,
+ dast_site_token_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ validation_started_at timestamp with time zone,
+ validation_passed_at timestamp with time zone,
+ validation_failed_at timestamp with time zone,
+ validation_last_retried_at timestamp with time zone,
+ validation_strategy smallint NOT NULL,
+ url_base text NOT NULL,
+ url_path text NOT NULL,
+ state text DEFAULT 'pending'::text NOT NULL,
+ CONSTRAINT check_13b34efe4b CHECK ((char_length(url_path) <= 255)),
+ CONSTRAINT check_283be72e9b CHECK ((char_length(state) <= 255)),
+ CONSTRAINT check_cd3b538210 CHECK ((char_length(url_base) <= 255))
+);
+
+CREATE SEQUENCE dast_site_validations_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE dast_site_validations_id_seq OWNED BY dast_site_validations.id;
+
+CREATE TABLE dast_sites (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ url text NOT NULL,
+ dast_site_validation_id bigint,
+ CONSTRAINT check_46df8b449c CHECK ((char_length(url) <= 255))
+);
+
+CREATE SEQUENCE dast_sites_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE dast_sites_id_seq OWNED BY dast_sites.id;
+
CREATE TABLE dependency_proxy_blobs (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -1977,6 +11720,30 @@ CREATE SEQUENCE dependency_proxy_group_settings_id_seq
ALTER SEQUENCE dependency_proxy_group_settings_id_seq OWNED BY dependency_proxy_group_settings.id;
+CREATE TABLE dependency_proxy_manifests (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ group_id bigint NOT NULL,
+ size bigint,
+ file_store smallint,
+ file_name text NOT NULL,
+ file text NOT NULL,
+ digest text NOT NULL,
+ CONSTRAINT check_079b293a7b CHECK ((char_length(file) <= 255)),
+ CONSTRAINT check_c579e3f586 CHECK ((char_length(file_name) <= 255)),
+ CONSTRAINT check_f5d9996bf1 CHECK ((char_length(digest) <= 255))
+);
+
+CREATE SEQUENCE dependency_proxy_manifests_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE dependency_proxy_manifests_id_seq OWNED BY dependency_proxy_manifests.id;
+
CREATE TABLE deploy_keys_projects (
id integer NOT NULL,
deploy_key_id integer NOT NULL,
@@ -2006,7 +11773,11 @@ CREATE TABLE deploy_tokens (
name character varying NOT NULL,
token character varying,
username character varying,
- token_encrypted character varying(255)
+ token_encrypted character varying(255),
+ deploy_token_type smallint DEFAULT 2 NOT NULL,
+ write_registry boolean DEFAULT false NOT NULL,
+ read_package_registry boolean DEFAULT false NOT NULL,
+ write_package_registry boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE deploy_tokens_id_seq
@@ -2019,9 +11790,16 @@ CREATE SEQUENCE deploy_tokens_id_seq
ALTER SEQUENCE deploy_tokens_id_seq OWNED BY deploy_tokens.id;
+CREATE TABLE deployment_clusters (
+ deployment_id integer NOT NULL,
+ cluster_id integer NOT NULL,
+ kubernetes_namespace character varying(255)
+);
+
CREATE TABLE deployment_merge_requests (
deployment_id integer NOT NULL,
- merge_request_id integer NOT NULL
+ merge_request_id integer NOT NULL,
+ environment_id integer
);
CREATE TABLE deployments (
@@ -2077,7 +11855,11 @@ CREATE TABLE design_management_designs (
id bigint NOT NULL,
project_id integer NOT NULL,
issue_id integer,
- filename character varying NOT NULL
+ filename character varying NOT NULL,
+ relative_position integer,
+ iid integer,
+ CONSTRAINT check_07155e2715 CHECK ((char_length((filename)::text) <= 255)),
+ CONSTRAINT check_cfb92df01a CHECK ((iid IS NOT NULL))
);
CREATE SEQUENCE design_management_designs_id_seq
@@ -2093,9 +11875,19 @@ CREATE TABLE design_management_designs_versions (
design_id bigint NOT NULL,
version_id bigint NOT NULL,
event smallint DEFAULT 0 NOT NULL,
- image_v432x230 character varying(255)
+ image_v432x230 character varying(255),
+ id bigint NOT NULL
);
+CREATE SEQUENCE design_management_designs_versions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE design_management_designs_versions_id_seq OWNED BY design_management_designs_versions.id;
+
CREATE TABLE design_management_versions (
id bigint NOT NULL,
sha bytea NOT NULL,
@@ -2131,6 +11923,30 @@ CREATE SEQUENCE design_user_mentions_id_seq
ALTER SEQUENCE design_user_mentions_id_seq OWNED BY design_user_mentions.id;
+CREATE TABLE diff_note_positions (
+ id bigint NOT NULL,
+ note_id bigint NOT NULL,
+ old_line integer,
+ new_line integer,
+ diff_content_type smallint NOT NULL,
+ diff_type smallint NOT NULL,
+ line_code character varying(255) NOT NULL,
+ base_sha bytea NOT NULL,
+ start_sha bytea NOT NULL,
+ head_sha bytea NOT NULL,
+ old_path text NOT NULL,
+ new_path text NOT NULL
+);
+
+CREATE SEQUENCE diff_note_positions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE diff_note_positions_id_seq OWNED BY diff_note_positions.id;
+
CREATE TABLE draft_notes (
id bigint NOT NULL,
merge_request_id integer NOT NULL,
@@ -2153,16 +11969,44 @@ CREATE SEQUENCE draft_notes_id_seq
ALTER SEQUENCE draft_notes_id_seq OWNED BY draft_notes.id;
+CREATE TABLE elastic_reindexing_tasks (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ documents_count integer,
+ state smallint DEFAULT 0 NOT NULL,
+ in_progress boolean DEFAULT true NOT NULL,
+ index_name_from text,
+ index_name_to text,
+ elastic_task text,
+ error_message text,
+ documents_count_target integer,
+ delete_original_index_at timestamp with time zone,
+ CONSTRAINT check_04151aca42 CHECK ((char_length(index_name_from) <= 255)),
+ CONSTRAINT check_7f64acda8e CHECK ((char_length(error_message) <= 255)),
+ CONSTRAINT check_85ebff7124 CHECK ((char_length(index_name_to) <= 255)),
+ CONSTRAINT check_942e5aae53 CHECK ((char_length(elastic_task) <= 255))
+);
+
+CREATE SEQUENCE elastic_reindexing_tasks_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE elastic_reindexing_tasks_id_seq OWNED BY elastic_reindexing_tasks.id;
+
CREATE TABLE elasticsearch_indexed_namespaces (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- namespace_id integer
+ namespace_id integer NOT NULL
);
CREATE TABLE elasticsearch_indexed_projects (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- project_id integer
+ project_id integer NOT NULL
);
CREATE TABLE emails (
@@ -2270,7 +12114,7 @@ CREATE TABLE epics (
cached_markdown_version integer,
updated_by_id integer,
last_edited_by_id integer,
- lock_version integer,
+ lock_version integer DEFAULT 0,
start_date date,
end_date date,
last_edited_at timestamp without time zone,
@@ -2293,6 +12137,8 @@ CREATE TABLE epics (
start_date_sourcing_epic_id integer,
due_date_sourcing_epic_id integer,
state_id smallint DEFAULT 1,
+ external_key character varying(255),
+ confidential boolean DEFAULT false NOT NULL,
CONSTRAINT check_57ee003890 CHECK ((state_id IS NOT NULL))
);
@@ -2315,7 +12161,9 @@ CREATE TABLE events (
updated_at timestamp with time zone NOT NULL,
action smallint NOT NULL,
target_type character varying,
- group_id bigint
+ group_id bigint,
+ fingerprint bytea,
+ CONSTRAINT check_97e06e05ad CHECK ((octet_length(fingerprint) <= 128))
);
CREATE SEQUENCE events_id_seq
@@ -2346,6 +12194,62 @@ CREATE SEQUENCE evidences_id_seq
ALTER SEQUENCE evidences_id_seq OWNED BY evidences.id;
+CREATE TABLE experiment_subjects (
+ id bigint NOT NULL,
+ experiment_id bigint NOT NULL,
+ user_id bigint,
+ group_id bigint,
+ project_id bigint,
+ variant smallint DEFAULT 0 NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ CONSTRAINT chk_has_one_subject CHECK ((num_nonnulls(user_id, group_id, project_id) = 1))
+);
+
+CREATE SEQUENCE experiment_subjects_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE experiment_subjects_id_seq OWNED BY experiment_subjects.id;
+
+CREATE TABLE experiment_users (
+ id bigint NOT NULL,
+ experiment_id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ group_type smallint DEFAULT 0 NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ converted_at timestamp with time zone,
+ context jsonb DEFAULT '{}'::jsonb NOT NULL
+);
+
+CREATE SEQUENCE experiment_users_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE experiment_users_id_seq OWNED BY experiment_users.id;
+
+CREATE TABLE experiments (
+ id bigint NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_e2dda25ed0 CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE experiments_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE experiments_id_seq OWNED BY experiments.id;
+
CREATE TABLE external_pull_requests (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -2439,24 +12343,6 @@ CREATE SEQUENCE fork_networks_id_seq
ALTER SEQUENCE fork_networks_id_seq OWNED BY fork_networks.id;
-CREATE TABLE forked_project_links (
- id integer NOT NULL,
- forked_to_project_id integer NOT NULL,
- forked_from_project_id integer NOT NULL,
- created_at timestamp without time zone,
- updated_at timestamp without time zone
-);
-
-CREATE SEQUENCE forked_project_links_id_seq
- AS integer
- START WITH 1
- INCREMENT BY 1
- NO MINVALUE
- NO MAXVALUE
- CACHE 1;
-
-ALTER SEQUENCE forked_project_links_id_seq OWNED BY forked_project_links.id;
-
CREATE TABLE geo_cache_invalidation_events (
id bigint NOT NULL,
key character varying NOT NULL
@@ -2500,7 +12386,8 @@ CREATE TABLE geo_event_log (
job_artifact_deleted_event_id bigint,
reset_checksum_event_id bigint,
cache_invalidation_event_id bigint,
- container_repository_updated_event_id bigint
+ container_repository_updated_event_id bigint,
+ geo_event_id integer
);
CREATE SEQUENCE geo_event_log_id_seq
@@ -2512,6 +12399,23 @@ CREATE SEQUENCE geo_event_log_id_seq
ALTER SEQUENCE geo_event_log_id_seq OWNED BY geo_event_log.id;
+CREATE TABLE geo_events (
+ id bigint NOT NULL,
+ replicable_name character varying(255) NOT NULL,
+ event_name character varying(255) NOT NULL,
+ payload jsonb DEFAULT '{}'::jsonb NOT NULL,
+ created_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE geo_events_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE geo_events_id_seq OWNED BY geo_events.id;
+
CREATE TABLE geo_hashed_storage_attachments_events (
id bigint NOT NULL,
project_id integer NOT NULL,
@@ -2654,7 +12558,8 @@ CREATE TABLE geo_node_statuses (
design_repositories_count integer,
design_repositories_synced_count integer,
design_repositories_failed_count integer,
- design_repositories_registry_count integer
+ design_repositories_registry_count integer,
+ status jsonb DEFAULT '{}'::jsonb NOT NULL
);
CREATE SEQUENCE geo_node_statuses_id_seq
@@ -2839,7 +12744,8 @@ CREATE TABLE gitlab_subscription_histories (
change_type smallint,
gitlab_subscription_id bigint NOT NULL,
created_at timestamp with time zone,
- trial_starts_on date
+ trial_starts_on date,
+ auto_renew boolean
);
CREATE SEQUENCE gitlab_subscription_histories_id_seq
@@ -2863,7 +12769,10 @@ CREATE TABLE gitlab_subscriptions (
max_seats_used integer DEFAULT 0,
seats integer DEFAULT 0,
trial boolean DEFAULT false,
- trial_starts_on date
+ trial_starts_on date,
+ auto_renew boolean,
+ seats_in_use integer DEFAULT 0 NOT NULL,
+ seats_owed integer DEFAULT 0 NOT NULL
);
CREATE SEQUENCE gitlab_subscriptions_id_seq
@@ -2981,6 +12890,66 @@ CREATE TABLE group_deletion_schedules (
marked_for_deletion_on date NOT NULL
);
+CREATE TABLE group_deploy_keys (
+ id bigint NOT NULL,
+ user_id bigint,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ last_used_at timestamp with time zone,
+ expires_at timestamp with time zone,
+ key text NOT NULL,
+ title text,
+ fingerprint text NOT NULL,
+ fingerprint_sha256 bytea,
+ CONSTRAINT check_cc0365908d CHECK ((char_length(title) <= 255)),
+ CONSTRAINT check_e4526dcf91 CHECK ((char_length(fingerprint) <= 255)),
+ CONSTRAINT check_f58fa0a0f7 CHECK ((char_length(key) <= 4096))
+);
+
+CREATE TABLE group_deploy_keys_groups (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ group_id bigint NOT NULL,
+ group_deploy_key_id bigint NOT NULL,
+ can_push boolean DEFAULT false NOT NULL
+);
+
+CREATE SEQUENCE group_deploy_keys_groups_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE group_deploy_keys_groups_id_seq OWNED BY group_deploy_keys_groups.id;
+
+CREATE SEQUENCE group_deploy_keys_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE group_deploy_keys_id_seq OWNED BY group_deploy_keys.id;
+
+CREATE TABLE group_deploy_tokens (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ group_id bigint NOT NULL,
+ deploy_token_id bigint NOT NULL
+);
+
+CREATE SEQUENCE group_deploy_tokens_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE group_deploy_tokens_id_seq OWNED BY group_deploy_tokens.id;
+
CREATE TABLE group_group_links (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -3000,12 +12969,42 @@ CREATE SEQUENCE group_group_links_id_seq
ALTER SEQUENCE group_group_links_id_seq OWNED BY group_group_links.id;
+CREATE TABLE group_import_states (
+ group_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
+ jid text,
+ last_error text,
+ user_id bigint,
+ CONSTRAINT check_87b58f6b30 CHECK ((char_length(last_error) <= 255)),
+ CONSTRAINT check_96558fff96 CHECK ((char_length(jid) <= 100))
+);
+
+CREATE SEQUENCE group_import_states_group_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE group_import_states_group_id_seq OWNED BY group_import_states.group_id;
+
+CREATE TABLE group_wiki_repositories (
+ shard_id bigint NOT NULL,
+ group_id bigint NOT NULL,
+ disk_path text NOT NULL,
+ CONSTRAINT check_07f1c81806 CHECK ((char_length(disk_path) <= 80))
+);
+
CREATE TABLE historical_data (
id integer NOT NULL,
- date date NOT NULL,
+ date date,
active_user_count integer,
created_at timestamp without time zone,
- updated_at timestamp without time zone
+ updated_at timestamp without time zone,
+ recorded_at timestamp with time zone,
+ CONSTRAINT check_640e8cf66c CHECK ((recorded_at IS NOT NULL))
);
CREATE SEQUENCE historical_data_id_seq
@@ -3061,12 +13060,15 @@ ALTER SEQUENCE import_export_uploads_id_seq OWNED BY import_export_uploads.id;
CREATE TABLE import_failures (
id bigint NOT NULL,
relation_index integer,
- project_id bigint NOT NULL,
+ project_id bigint,
created_at timestamp with time zone NOT NULL,
relation_key character varying(64),
exception_class character varying(128),
correlation_id_value character varying(128),
- exception_message character varying(255)
+ exception_message character varying(255),
+ retry_count integer,
+ group_id integer,
+ source character varying(128)
);
CREATE SEQUENCE import_failures_id_seq
@@ -3078,6 +13080,84 @@ CREATE SEQUENCE import_failures_id_seq
ALTER SEQUENCE import_failures_id_seq OWNED BY import_failures.id;
+CREATE TABLE incident_management_oncall_participants (
+ id bigint NOT NULL,
+ oncall_rotation_id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ color_palette smallint NOT NULL,
+ color_weight smallint NOT NULL
+);
+
+CREATE SEQUENCE incident_management_oncall_participants_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE incident_management_oncall_participants_id_seq OWNED BY incident_management_oncall_participants.id;
+
+CREATE TABLE incident_management_oncall_rotations (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ oncall_schedule_id bigint NOT NULL,
+ length integer NOT NULL,
+ length_unit smallint NOT NULL,
+ starts_at timestamp with time zone NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_5209fb5d02 CHECK ((char_length(name) <= 200))
+);
+
+CREATE SEQUENCE incident_management_oncall_rotations_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE incident_management_oncall_rotations_id_seq OWNED BY incident_management_oncall_rotations.id;
+
+CREATE TABLE incident_management_oncall_schedules (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ iid integer NOT NULL,
+ name text NOT NULL,
+ description text,
+ timezone text,
+ CONSTRAINT check_7ed1fd5aa7 CHECK ((char_length(description) <= 1000)),
+ CONSTRAINT check_cc77cbb103 CHECK ((char_length(timezone) <= 100)),
+ CONSTRAINT check_e6ef43a664 CHECK ((char_length(name) <= 200))
+);
+
+CREATE SEQUENCE incident_management_oncall_schedules_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE incident_management_oncall_schedules_id_seq OWNED BY incident_management_oncall_schedules.id;
+
+CREATE TABLE incident_management_oncall_shifts (
+ id bigint NOT NULL,
+ rotation_id bigint NOT NULL,
+ participant_id bigint NOT NULL,
+ starts_at timestamp with time zone NOT NULL,
+ ends_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE incident_management_oncall_shifts_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE incident_management_oncall_shifts_id_seq OWNED BY incident_management_oncall_shifts.id;
+
CREATE TABLE index_statuses (
id integer NOT NULL,
project_id integer NOT NULL,
@@ -3148,11 +13228,80 @@ CREATE SEQUENCE ip_restrictions_id_seq
ALTER SEQUENCE ip_restrictions_id_seq OWNED BY ip_restrictions.id;
+CREATE TABLE issuable_metric_images (
+ id bigint NOT NULL,
+ issue_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ file_store smallint,
+ file text NOT NULL,
+ url text,
+ CONSTRAINT check_5b3011e234 CHECK ((char_length(url) <= 255)),
+ CONSTRAINT check_7ed527062f CHECK ((char_length(file) <= 255))
+);
+
+CREATE SEQUENCE issuable_metric_images_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE issuable_metric_images_id_seq OWNED BY issuable_metric_images.id;
+
+CREATE TABLE issuable_severities (
+ id bigint NOT NULL,
+ issue_id bigint NOT NULL,
+ severity smallint DEFAULT 0 NOT NULL
+);
+
+CREATE SEQUENCE issuable_severities_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE issuable_severities_id_seq OWNED BY issuable_severities.id;
+
+CREATE TABLE issuable_slas (
+ id bigint NOT NULL,
+ issue_id bigint NOT NULL,
+ due_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE issuable_slas_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE issuable_slas_id_seq OWNED BY issuable_slas.id;
+
CREATE TABLE issue_assignees (
user_id integer NOT NULL,
issue_id integer NOT NULL
);
+CREATE TABLE issue_email_participants (
+ id bigint NOT NULL,
+ issue_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ email text NOT NULL,
+ CONSTRAINT check_2c321d408d CHECK ((char_length(email) <= 255))
+);
+
+CREATE SEQUENCE issue_email_participants_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE issue_email_participants_id_seq OWNED BY issue_email_participants.id;
+
CREATE TABLE issue_links (
id integer NOT NULL,
source_id integer NOT NULL,
@@ -3192,11 +13341,6 @@ CREATE SEQUENCE issue_metrics_id_seq
ALTER SEQUENCE issue_metrics_id_seq OWNED BY issue_metrics.id;
-CREATE TABLE issue_milestones (
- issue_id bigint NOT NULL,
- milestone_id bigint NOT NULL
-);
-
CREATE TABLE issue_tracker_data (
id bigint NOT NULL,
service_id integer NOT NULL,
@@ -3246,13 +13390,12 @@ CREATE TABLE issues (
updated_at timestamp without time zone,
description text,
milestone_id integer,
- state character varying,
iid integer,
updated_by_id integer,
confidential boolean DEFAULT false NOT NULL,
due_date date,
moved_to_id integer,
- lock_version integer,
+ lock_version integer DEFAULT 0,
title_html text,
description_html text,
time_estimate integer,
@@ -3267,7 +13410,12 @@ CREATE TABLE issues (
service_desk_reply_to character varying,
weight integer,
duplicated_to_id integer,
- promoted_to_epic_id integer
+ promoted_to_epic_id integer,
+ health_status smallint,
+ sprint_id bigint,
+ external_key character varying(255),
+ blocking_issues_count integer DEFAULT 0 NOT NULL,
+ issue_type smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE issues_id_seq
@@ -3328,6 +13476,36 @@ CREATE SEQUENCE jira_connect_subscriptions_id_seq
ALTER SEQUENCE jira_connect_subscriptions_id_seq OWNED BY jira_connect_subscriptions.id;
+CREATE TABLE jira_imports (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ user_id bigint,
+ label_id bigint,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ finished_at timestamp with time zone,
+ jira_project_xid bigint NOT NULL,
+ total_issue_count integer DEFAULT 0 NOT NULL,
+ imported_issues_count integer DEFAULT 0 NOT NULL,
+ failed_to_import_count integer DEFAULT 0 NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
+ jid character varying(255),
+ jira_project_key character varying(255) NOT NULL,
+ jira_project_name character varying(255) NOT NULL,
+ scheduled_at timestamp with time zone,
+ error_message text,
+ CONSTRAINT check_9ed451c5b1 CHECK ((char_length(error_message) <= 1000))
+);
+
+CREATE SEQUENCE jira_imports_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE jira_imports_id_seq OWNED BY jira_imports.id;
+
CREATE TABLE jira_tracker_data (
id bigint NOT NULL,
service_id integer NOT NULL,
@@ -3341,7 +13519,14 @@ CREATE TABLE jira_tracker_data (
encrypted_username_iv character varying,
encrypted_password character varying,
encrypted_password_iv character varying,
- jira_issue_transition_id character varying
+ jira_issue_transition_id character varying,
+ project_key text,
+ issues_enabled boolean DEFAULT false NOT NULL,
+ deployment_type smallint DEFAULT 0 NOT NULL,
+ vulnerabilities_issuetype text,
+ vulnerabilities_enabled boolean DEFAULT false NOT NULL,
+ CONSTRAINT check_0bf84b76e9 CHECK ((char_length(vulnerabilities_issuetype) <= 255)),
+ CONSTRAINT check_214cf6a48b CHECK ((char_length(project_key) <= 255))
);
CREATE SEQUENCE jira_tracker_data_id_seq
@@ -3364,7 +13549,8 @@ CREATE TABLE keys (
fingerprint character varying,
public boolean DEFAULT false NOT NULL,
last_used_at timestamp without time zone,
- fingerprint_sha256 bytea
+ fingerprint_sha256 bytea,
+ expires_at timestamp with time zone
);
CREATE SEQUENCE keys_id_seq
@@ -3486,7 +13672,8 @@ CREATE TABLE lfs_objects (
created_at timestamp without time zone,
updated_at timestamp without time zone,
file character varying,
- file_store integer
+ file_store integer DEFAULT 1,
+ CONSTRAINT check_eecfc5717d CHECK ((file_store IS NOT NULL))
);
CREATE SEQUENCE lfs_objects_id_seq
@@ -3564,7 +13751,9 @@ CREATE TABLE lists (
milestone_id integer,
user_id integer,
max_issue_count integer DEFAULT 0 NOT NULL,
- max_issue_weight integer DEFAULT 0 NOT NULL
+ max_issue_weight integer DEFAULT 0 NOT NULL,
+ limit_metric character varying(20),
+ iteration_id bigint
);
CREATE SEQUENCE lists_id_seq
@@ -3610,7 +13799,8 @@ ALTER SEQUENCE members_id_seq OWNED BY members.id;
CREATE TABLE merge_request_assignees (
id integer NOT NULL,
user_id integer NOT NULL,
- merge_request_id integer NOT NULL
+ merge_request_id integer NOT NULL,
+ created_at timestamp with time zone
);
CREATE SEQUENCE merge_request_assignees_id_seq
@@ -3640,8 +13830,25 @@ CREATE SEQUENCE merge_request_blocks_id_seq
ALTER SEQUENCE merge_request_blocks_id_seq OWNED BY merge_request_blocks.id;
+CREATE TABLE merge_request_cleanup_schedules (
+ merge_request_id bigint NOT NULL,
+ scheduled_at timestamp with time zone NOT NULL,
+ completed_at timestamp with time zone,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE merge_request_cleanup_schedules_merge_request_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE merge_request_cleanup_schedules_merge_request_id_seq OWNED BY merge_request_cleanup_schedules.merge_request_id;
+
CREATE TABLE merge_request_context_commit_diff_files (
- merge_request_context_commit_id bigint,
+ merge_request_context_commit_id bigint NOT NULL,
sha bytea NOT NULL,
relative_order integer NOT NULL,
a_mode character varying(255) NOT NULL,
@@ -3692,6 +13899,25 @@ CREATE TABLE merge_request_diff_commits (
message text
);
+CREATE TABLE merge_request_diff_details (
+ merge_request_diff_id bigint NOT NULL,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ verification_retry_count smallint,
+ verification_checksum bytea,
+ verification_failure text,
+ CONSTRAINT check_81429e3622 CHECK ((char_length(verification_failure) <= 255))
+);
+
+CREATE SEQUENCE merge_request_diff_details_merge_request_diff_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE merge_request_diff_details_merge_request_diff_id_seq OWNED BY merge_request_diff_details.merge_request_diff_id;
+
CREATE TABLE merge_request_diff_files (
merge_request_diff_id integer NOT NULL,
relative_order integer NOT NULL,
@@ -3721,8 +13947,11 @@ CREATE TABLE merge_request_diffs (
start_commit_sha character varying,
commits_count integer,
external_diff character varying,
- external_diff_store integer,
- stored_externally boolean
+ external_diff_store integer DEFAULT 1,
+ stored_externally boolean,
+ files_count smallint,
+ sorted boolean DEFAULT false NOT NULL,
+ CONSTRAINT check_93ee616ac9 CHECK ((external_diff_store IS NOT NULL))
);
CREATE SEQUENCE merge_request_diffs_id_seq
@@ -3753,7 +13982,13 @@ CREATE TABLE merge_request_metrics (
last_commit_at timestamp with time zone,
diff_size integer,
modified_paths_size integer,
- commits_count integer
+ commits_count integer,
+ first_approved_at timestamp with time zone,
+ first_reassigned_at timestamp with time zone,
+ added_lines integer,
+ removed_lines integer,
+ target_project_id integer,
+ CONSTRAINT check_e03d0900bf CHECK ((target_project_id IS NOT NULL))
);
CREATE SEQUENCE merge_request_metrics_id_seq
@@ -3766,11 +14001,22 @@ CREATE SEQUENCE merge_request_metrics_id_seq
ALTER SEQUENCE merge_request_metrics_id_seq OWNED BY merge_request_metrics.id;
-CREATE TABLE merge_request_milestones (
+CREATE TABLE merge_request_reviewers (
+ id bigint NOT NULL,
+ user_id bigint NOT NULL,
merge_request_id bigint NOT NULL,
- milestone_id bigint NOT NULL
+ created_at timestamp with time zone NOT NULL
);
+CREATE SEQUENCE merge_request_reviewers_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE merge_request_reviewers_id_seq OWNED BY merge_request_reviewers.id;
+
CREATE TABLE merge_request_user_mentions (
id bigint NOT NULL,
merge_request_id integer NOT NULL,
@@ -3800,7 +14046,6 @@ CREATE TABLE merge_requests (
created_at timestamp without time zone,
updated_at timestamp without time zone,
milestone_id integer,
- state character varying DEFAULT 'opened'::character varying NOT NULL,
merge_status character varying DEFAULT 'unchecked'::character varying NOT NULL,
target_project_id integer NOT NULL,
iid integer,
@@ -3813,7 +14058,7 @@ CREATE TABLE merge_requests (
merge_commit_sha character varying,
rebase_commit_sha character varying,
in_progress_merge_commit_sha character varying,
- lock_version integer,
+ lock_version integer DEFAULT 0,
title_html text,
description_html text,
time_estimate integer,
@@ -3829,7 +14074,9 @@ CREATE TABLE merge_requests (
state_id smallint DEFAULT 1 NOT NULL,
approvals_before_merge integer,
rebase_jid character varying,
- squash_commit_sha bytea
+ squash_commit_sha bytea,
+ sprint_id bigint,
+ merge_ref_sha bytea
);
CREATE TABLE merge_requests_closing_issues (
@@ -3869,7 +14116,9 @@ CREATE TABLE merge_trains (
updated_at timestamp with time zone NOT NULL,
target_project_id integer NOT NULL,
target_branch text NOT NULL,
- status smallint DEFAULT 0 NOT NULL
+ status smallint DEFAULT 0 NOT NULL,
+ merged_at timestamp with time zone,
+ duration integer
);
CREATE SEQUENCE merge_trains_id_seq
@@ -3881,6 +14130,45 @@ CREATE SEQUENCE merge_trains_id_seq
ALTER SEQUENCE merge_trains_id_seq OWNED BY merge_trains.id;
+CREATE TABLE metrics_dashboard_annotations (
+ id bigint NOT NULL,
+ starting_at timestamp with time zone NOT NULL,
+ ending_at timestamp with time zone,
+ environment_id bigint,
+ cluster_id bigint,
+ dashboard_path character varying(255) NOT NULL,
+ panel_xid character varying(255),
+ description text NOT NULL
+);
+
+CREATE SEQUENCE metrics_dashboard_annotations_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE metrics_dashboard_annotations_id_seq OWNED BY metrics_dashboard_annotations.id;
+
+CREATE TABLE metrics_users_starred_dashboards (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ dashboard_path text NOT NULL,
+ CONSTRAINT check_79a84a0f57 CHECK ((char_length(dashboard_path) <= 255))
+);
+
+CREATE SEQUENCE metrics_users_starred_dashboards_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE metrics_users_starred_dashboards_id_seq OWNED BY metrics_users_starred_dashboards.id;
+
CREATE TABLE milestone_releases (
milestone_id bigint NOT NULL,
release_id bigint NOT NULL
@@ -3927,6 +14215,29 @@ CREATE SEQUENCE namespace_aggregation_schedules_namespace_id_seq
ALTER SEQUENCE namespace_aggregation_schedules_namespace_id_seq OWNED BY namespace_aggregation_schedules.namespace_id;
+CREATE TABLE namespace_limits (
+ additional_purchased_storage_size bigint DEFAULT 0 NOT NULL,
+ additional_purchased_storage_ends_on date,
+ namespace_id integer NOT NULL,
+ temporary_storage_increase_ends_on date
+);
+
+CREATE TABLE namespace_onboarding_actions (
+ id bigint NOT NULL,
+ namespace_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ action smallint NOT NULL
+);
+
+CREATE SEQUENCE namespace_onboarding_actions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE namespace_onboarding_actions_id_seq OWNED BY namespace_onboarding_actions.id;
+
CREATE TABLE namespace_root_storage_statistics (
namespace_id integer NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -3935,7 +14246,10 @@ CREATE TABLE namespace_root_storage_statistics (
wiki_size bigint DEFAULT 0 NOT NULL,
build_artifacts_size bigint DEFAULT 0 NOT NULL,
storage_size bigint DEFAULT 0 NOT NULL,
- packages_size bigint DEFAULT 0 NOT NULL
+ packages_size bigint DEFAULT 0 NOT NULL,
+ snippets_size bigint DEFAULT 0 NOT NULL,
+ pipeline_artifacts_size bigint DEFAULT 0 NOT NULL,
+ uploads_size bigint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE namespace_root_storage_statistics_namespace_id_seq
@@ -3948,6 +14262,16 @@ CREATE SEQUENCE namespace_root_storage_statistics_namespace_id_seq
ALTER SEQUENCE namespace_root_storage_statistics_namespace_id_seq OWNED BY namespace_root_storage_statistics.namespace_id;
+CREATE TABLE namespace_settings (
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ namespace_id integer NOT NULL,
+ prevent_forking_outside_group boolean DEFAULT false NOT NULL,
+ allow_mfa_for_subgroups boolean DEFAULT true NOT NULL,
+ default_branch_name text,
+ CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255))
+);
+
CREATE TABLE namespace_statistics (
id integer NOT NULL,
namespace_id integer NOT NULL,
@@ -3994,11 +14318,9 @@ CREATE TABLE namespaces (
ldap_sync_last_successful_update_at timestamp without time zone,
ldap_sync_last_sync_at timestamp without time zone,
ldap_sync_last_update_at timestamp without time zone,
- plan_id integer,
repository_size_limit bigint,
saml_discovery_token character varying,
shared_runners_minutes_limit integer,
- trial_ends_on timestamp with time zone,
extra_shared_runners_minutes_limit integer,
ldap_sync_status character varying DEFAULT 'ready'::character varying NOT NULL,
membership_lock boolean DEFAULT false,
@@ -4008,7 +14330,15 @@ CREATE TABLE namespaces (
emails_disabled boolean,
max_pages_size integer,
max_artifacts_size integer,
- mentions_disabled boolean
+ mentions_disabled boolean,
+ default_branch_protection smallint,
+ unlock_membership_to_ldap boolean,
+ max_personal_access_token_lifetime integer,
+ push_rule_id bigint,
+ shared_runners_enabled boolean DEFAULT true NOT NULL,
+ allow_descendants_override_disabled_shared_runners boolean DEFAULT false NOT NULL,
+ traversal_ids integer[] DEFAULT '{}'::integer[] NOT NULL,
+ delayed_project_removal boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE namespaces_id_seq
@@ -4069,7 +14399,8 @@ CREATE TABLE notes (
cached_markdown_version integer,
change_position text,
resolved_by_push boolean,
- review_id bigint
+ review_id bigint,
+ confidential boolean
);
CREATE SEQUENCE notes_id_seq
@@ -4107,7 +14438,9 @@ CREATE TABLE notification_settings (
notification_email character varying,
new_epic boolean,
new_release boolean,
- fixed_pipeline boolean
+ fixed_pipeline boolean,
+ moved_project boolean DEFAULT true NOT NULL,
+ change_reviewer_merge_request boolean
);
CREATE SEQUENCE notification_settings_id_seq
@@ -4129,7 +14462,11 @@ CREATE TABLE oauth_access_grants (
redirect_uri text NOT NULL,
created_at timestamp without time zone NOT NULL,
revoked_at timestamp without time zone,
- scopes character varying
+ scopes character varying,
+ code_challenge text,
+ code_challenge_method text,
+ CONSTRAINT oauth_access_grants_code_challenge CHECK ((char_length(code_challenge) <= 128)),
+ CONSTRAINT oauth_access_grants_code_challenge_method CHECK ((char_length(code_challenge_method) <= 5))
);
CREATE SEQUENCE oauth_access_grants_id_seq
@@ -4205,6 +14542,30 @@ CREATE SEQUENCE oauth_openid_requests_id_seq
ALTER SEQUENCE oauth_openid_requests_id_seq OWNED BY oauth_openid_requests.id;
+CREATE TABLE open_project_tracker_data (
+ id bigint NOT NULL,
+ service_id integer NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ encrypted_url character varying(255),
+ encrypted_url_iv character varying(255),
+ encrypted_api_url character varying(255),
+ encrypted_api_url_iv character varying(255),
+ encrypted_token character varying(255),
+ encrypted_token_iv character varying(255),
+ closed_status_id character varying(5),
+ project_identifier_code character varying(100)
+);
+
+CREATE SEQUENCE open_project_tracker_data_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE open_project_tracker_data_id_seq OWNED BY open_project_tracker_data.id;
+
CREATE TABLE operations_feature_flag_scopes (
id bigint NOT NULL,
feature_flag_id bigint NOT NULL,
@@ -4231,7 +14592,9 @@ CREATE TABLE operations_feature_flags (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
name character varying NOT NULL,
- description text
+ description text,
+ iid integer NOT NULL,
+ version smallint DEFAULT 1 NOT NULL
);
CREATE TABLE operations_feature_flags_clients (
@@ -4258,6 +14621,86 @@ CREATE SEQUENCE operations_feature_flags_id_seq
ALTER SEQUENCE operations_feature_flags_id_seq OWNED BY operations_feature_flags.id;
+CREATE TABLE operations_feature_flags_issues (
+ id bigint NOT NULL,
+ feature_flag_id bigint NOT NULL,
+ issue_id bigint NOT NULL
+);
+
+CREATE SEQUENCE operations_feature_flags_issues_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE operations_feature_flags_issues_id_seq OWNED BY operations_feature_flags_issues.id;
+
+CREATE TABLE operations_scopes (
+ id bigint NOT NULL,
+ strategy_id bigint NOT NULL,
+ environment_scope character varying(255) NOT NULL
+);
+
+CREATE SEQUENCE operations_scopes_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE operations_scopes_id_seq OWNED BY operations_scopes.id;
+
+CREATE TABLE operations_strategies (
+ id bigint NOT NULL,
+ feature_flag_id bigint NOT NULL,
+ name character varying(255) NOT NULL,
+ parameters jsonb DEFAULT '{}'::jsonb NOT NULL
+);
+
+CREATE SEQUENCE operations_strategies_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE operations_strategies_id_seq OWNED BY operations_strategies.id;
+
+CREATE TABLE operations_strategies_user_lists (
+ id bigint NOT NULL,
+ strategy_id bigint NOT NULL,
+ user_list_id bigint NOT NULL
+);
+
+CREATE SEQUENCE operations_strategies_user_lists_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE operations_strategies_user_lists_id_seq OWNED BY operations_strategies_user_lists.id;
+
+CREATE TABLE operations_user_lists (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ iid integer NOT NULL,
+ name character varying(255) NOT NULL,
+ user_xids text DEFAULT ''::text NOT NULL
+);
+
+CREATE SEQUENCE operations_user_lists_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE operations_user_lists_id_seq OWNED BY operations_user_lists.id;
+
CREATE TABLE packages_build_infos (
id bigint NOT NULL,
package_id integer NOT NULL,
@@ -4273,6 +14716,13 @@ CREATE SEQUENCE packages_build_infos_id_seq
ALTER SEQUENCE packages_build_infos_id_seq OWNED BY packages_build_infos.id;
+CREATE TABLE packages_composer_metadata (
+ package_id bigint NOT NULL,
+ target_sha bytea NOT NULL,
+ composer_json jsonb DEFAULT '{}'::jsonb NOT NULL,
+ version_cache_sha bytea
+);
+
CREATE TABLE packages_conan_file_metadata (
id bigint NOT NULL,
package_file_id bigint NOT NULL,
@@ -4311,6 +14761,237 @@ CREATE SEQUENCE packages_conan_metadata_id_seq
ALTER SEQUENCE packages_conan_metadata_id_seq OWNED BY packages_conan_metadata.id;
+CREATE TABLE packages_debian_file_metadata (
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ package_file_id bigint NOT NULL,
+ file_type smallint NOT NULL,
+ component text,
+ architecture text,
+ fields jsonb,
+ CONSTRAINT check_2ebedda4b6 CHECK ((char_length(component) <= 255)),
+ CONSTRAINT check_e6e1fffcca CHECK ((char_length(architecture) <= 255))
+);
+
+CREATE TABLE packages_debian_group_architectures (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ distribution_id bigint NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_ddb220164a CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_group_architectures_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_group_architectures_id_seq OWNED BY packages_debian_group_architectures.id;
+
+CREATE TABLE packages_debian_group_component_files (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ component_id bigint NOT NULL,
+ architecture_id bigint,
+ size integer NOT NULL,
+ file_type smallint NOT NULL,
+ compression_type smallint,
+ file_store smallint DEFAULT 1 NOT NULL,
+ file text NOT NULL,
+ file_md5 bytea NOT NULL,
+ file_sha256 bytea NOT NULL,
+ CONSTRAINT check_839e1685bc CHECK ((char_length(file) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_group_component_files_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_group_component_files_id_seq OWNED BY packages_debian_group_component_files.id;
+
+CREATE TABLE packages_debian_group_components (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ distribution_id bigint NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_a9bc7d85be CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_group_components_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_group_components_id_seq OWNED BY packages_debian_group_components.id;
+
+CREATE TABLE packages_debian_group_distributions (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ group_id bigint NOT NULL,
+ creator_id bigint,
+ valid_time_duration_seconds integer,
+ file_store smallint DEFAULT 1 NOT NULL,
+ automatic boolean DEFAULT true NOT NULL,
+ automatic_upgrades boolean DEFAULT false NOT NULL,
+ codename text NOT NULL,
+ suite text,
+ origin text,
+ label text,
+ version text,
+ description text,
+ encrypted_signing_keys text,
+ encrypted_signing_keys_iv text,
+ file text,
+ file_signature text,
+ CONSTRAINT check_310ac457b8 CHECK ((char_length(description) <= 255)),
+ CONSTRAINT check_3d6f87fc31 CHECK ((char_length(file_signature) <= 4096)),
+ CONSTRAINT check_3fdadf4a0c CHECK ((char_length(version) <= 255)),
+ CONSTRAINT check_590e18405a CHECK ((char_length(codename) <= 255)),
+ CONSTRAINT check_9b90bc0f07 CHECK ((char_length(encrypted_signing_keys_iv) <= 255)),
+ CONSTRAINT check_b057cd840a CHECK ((char_length(origin) <= 255)),
+ CONSTRAINT check_b811ec1218 CHECK ((char_length(encrypted_signing_keys) <= 2048)),
+ CONSTRAINT check_be5ed8d307 CHECK ((char_length(file) <= 255)),
+ CONSTRAINT check_d3244bfc0b CHECK ((char_length(label) <= 255)),
+ CONSTRAINT check_e7c928a24b CHECK ((char_length(suite) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_group_distributions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_group_distributions_id_seq OWNED BY packages_debian_group_distributions.id;
+
+CREATE TABLE packages_debian_project_architectures (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ distribution_id bigint NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_9c2e1c99d8 CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_project_architectures_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_project_architectures_id_seq OWNED BY packages_debian_project_architectures.id;
+
+CREATE TABLE packages_debian_project_component_files (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ component_id bigint NOT NULL,
+ architecture_id bigint,
+ size integer NOT NULL,
+ file_type smallint NOT NULL,
+ compression_type smallint,
+ file_store smallint DEFAULT 1 NOT NULL,
+ file text NOT NULL,
+ file_md5 bytea NOT NULL,
+ file_sha256 bytea NOT NULL,
+ CONSTRAINT check_e5af03fa2d CHECK ((char_length(file) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_project_component_files_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_project_component_files_id_seq OWNED BY packages_debian_project_component_files.id;
+
+CREATE TABLE packages_debian_project_components (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ distribution_id bigint NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_517559f298 CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_project_components_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_project_components_id_seq OWNED BY packages_debian_project_components.id;
+
+CREATE TABLE packages_debian_project_distributions (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ creator_id bigint,
+ valid_time_duration_seconds integer,
+ file_store smallint DEFAULT 1 NOT NULL,
+ automatic boolean DEFAULT true NOT NULL,
+ automatic_upgrades boolean DEFAULT false NOT NULL,
+ codename text NOT NULL,
+ suite text,
+ origin text,
+ label text,
+ version text,
+ description text,
+ encrypted_signing_keys text,
+ encrypted_signing_keys_iv text,
+ file text,
+ file_signature text,
+ CONSTRAINT check_6177ccd4a6 CHECK ((char_length(origin) <= 255)),
+ CONSTRAINT check_6f6b55a4c4 CHECK ((char_length(label) <= 255)),
+ CONSTRAINT check_834dabadb6 CHECK ((char_length(codename) <= 255)),
+ CONSTRAINT check_96965792c2 CHECK ((char_length(version) <= 255)),
+ CONSTRAINT check_a56ae58a17 CHECK ((char_length(suite) <= 255)),
+ CONSTRAINT check_a5a2ac6af2 CHECK ((char_length(file_signature) <= 4096)),
+ CONSTRAINT check_b93154339f CHECK ((char_length(description) <= 255)),
+ CONSTRAINT check_c25603a25b CHECK ((char_length(encrypted_signing_keys) <= 2048)),
+ CONSTRAINT check_cb4ac9599e CHECK ((char_length(file) <= 255)),
+ CONSTRAINT check_d488f8cce3 CHECK ((char_length(encrypted_signing_keys_iv) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_project_distributions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_project_distributions_id_seq OWNED BY packages_debian_project_distributions.id;
+
+CREATE TABLE packages_debian_publications (
+ id bigint NOT NULL,
+ package_id bigint NOT NULL,
+ distribution_id bigint NOT NULL
+);
+
+CREATE SEQUENCE packages_debian_publications_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_publications_id_seq OWNED BY packages_debian_publications.id;
+
CREATE TABLE packages_dependencies (
id bigint NOT NULL,
name character varying(255) NOT NULL,
@@ -4342,6 +15023,25 @@ CREATE SEQUENCE packages_dependency_links_id_seq
ALTER SEQUENCE packages_dependency_links_id_seq OWNED BY packages_dependency_links.id;
+CREATE TABLE packages_events (
+ id bigint NOT NULL,
+ event_type smallint NOT NULL,
+ event_scope smallint NOT NULL,
+ originator_type smallint NOT NULL,
+ originator bigint,
+ created_at timestamp with time zone NOT NULL,
+ package_id bigint
+);
+
+CREATE SEQUENCE packages_events_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_events_id_seq OWNED BY packages_events.id;
+
CREATE TABLE packages_maven_metadata (
id bigint NOT NULL,
package_id bigint NOT NULL,
@@ -4362,18 +15062,57 @@ CREATE SEQUENCE packages_maven_metadata_id_seq
ALTER SEQUENCE packages_maven_metadata_id_seq OWNED BY packages_maven_metadata.id;
+CREATE TABLE packages_nuget_dependency_link_metadata (
+ dependency_link_id bigint NOT NULL,
+ target_framework text NOT NULL,
+ CONSTRAINT packages_nuget_dependency_link_metadata_target_framework_constr CHECK ((char_length(target_framework) <= 255))
+);
+
+CREATE TABLE packages_nuget_metadata (
+ package_id bigint NOT NULL,
+ license_url text,
+ project_url text,
+ icon_url text,
+ CONSTRAINT packages_nuget_metadata_icon_url_constraint CHECK ((char_length(icon_url) <= 255)),
+ CONSTRAINT packages_nuget_metadata_license_url_constraint CHECK ((char_length(license_url) <= 255)),
+ CONSTRAINT packages_nuget_metadata_project_url_constraint CHECK ((char_length(project_url) <= 255))
+);
+
+CREATE TABLE packages_package_file_build_infos (
+ id bigint NOT NULL,
+ package_file_id bigint NOT NULL,
+ pipeline_id bigint
+);
+
+CREATE SEQUENCE packages_package_file_build_infos_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_package_file_build_infos_id_seq OWNED BY packages_package_file_build_infos.id;
+
CREATE TABLE packages_package_files (
id bigint NOT NULL,
package_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
size bigint,
- file_type integer,
- file_store integer,
+ file_store integer DEFAULT 1,
file_md5 bytea,
file_sha1 bytea,
file_name character varying NOT NULL,
- file text NOT NULL
+ file text NOT NULL,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ verification_failure character varying(255),
+ verification_retry_count integer,
+ file_sha256 bytea,
+ verification_checksum bytea,
+ verification_state smallint DEFAULT 0 NOT NULL,
+ verification_started_at timestamp with time zone,
+ CONSTRAINT check_4c5e6bb0b3 CHECK ((file_store IS NOT NULL))
);
CREATE SEQUENCE packages_package_files_id_seq
@@ -4392,7 +15131,8 @@ CREATE TABLE packages_packages (
updated_at timestamp with time zone NOT NULL,
name character varying NOT NULL,
version character varying,
- package_type smallint NOT NULL
+ package_type smallint NOT NULL,
+ creator_id integer
);
CREATE SEQUENCE packages_packages_id_seq
@@ -4404,10 +15144,19 @@ CREATE SEQUENCE packages_packages_id_seq
ALTER SEQUENCE packages_packages_id_seq OWNED BY packages_packages.id;
+CREATE TABLE packages_pypi_metadata (
+ package_id bigint NOT NULL,
+ required_python text,
+ CONSTRAINT check_0d9aed55b2 CHECK ((required_python IS NOT NULL)),
+ CONSTRAINT check_379019d5da CHECK ((char_length(required_python) <= 255))
+);
+
CREATE TABLE packages_tags (
id bigint NOT NULL,
package_id integer NOT NULL,
- name character varying(255) NOT NULL
+ name character varying(255) NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
);
CREATE SEQUENCE packages_tags_id_seq
@@ -4419,6 +15168,29 @@ CREATE SEQUENCE packages_tags_id_seq
ALTER SEQUENCE packages_tags_id_seq OWNED BY packages_tags.id;
+CREATE TABLE pages_deployments (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ ci_build_id bigint,
+ file_store smallint NOT NULL,
+ size integer NOT NULL,
+ file text NOT NULL,
+ file_count integer NOT NULL,
+ file_sha256 bytea NOT NULL,
+ CONSTRAINT check_f0fe8032dd CHECK ((char_length(file) <= 255))
+);
+
+CREATE SEQUENCE pages_deployments_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE pages_deployments_id_seq OWNED BY pages_deployments.id;
+
CREATE TABLE pages_domain_acme_orders (
id bigint NOT NULL,
pages_domain_id integer NOT NULL,
@@ -4458,7 +15230,10 @@ CREATE TABLE pages_domains (
certificate_valid_not_after timestamp with time zone,
certificate_source smallint DEFAULT 0 NOT NULL,
wildcard boolean DEFAULT false NOT NULL,
- domain_type smallint DEFAULT 2 NOT NULL
+ usage smallint DEFAULT 0 NOT NULL,
+ scope smallint DEFAULT 2,
+ auto_ssl_failed boolean DEFAULT false NOT NULL,
+ CONSTRAINT check_ab7cf26a46 CHECK ((scope IS NOT NULL))
);
CREATE SEQUENCE pages_domains_id_seq
@@ -4471,6 +15246,28 @@ CREATE SEQUENCE pages_domains_id_seq
ALTER SEQUENCE pages_domains_id_seq OWNED BY pages_domains.id;
+CREATE TABLE partitioned_foreign_keys (
+ id bigint NOT NULL,
+ cascade_delete boolean DEFAULT true NOT NULL,
+ from_table text NOT NULL,
+ from_column text NOT NULL,
+ to_table text NOT NULL,
+ to_column text NOT NULL,
+ CONSTRAINT check_2c2e02a62b CHECK ((char_length(from_column) <= 63)),
+ CONSTRAINT check_40738efb57 CHECK ((char_length(to_table) <= 63)),
+ CONSTRAINT check_741676d405 CHECK ((char_length(from_table) <= 63)),
+ CONSTRAINT check_7e98be694f CHECK ((char_length(to_column) <= 63))
+);
+
+CREATE SEQUENCE partitioned_foreign_keys_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE partitioned_foreign_keys_id_seq OWNED BY partitioned_foreign_keys.id;
+
CREATE TABLE path_locks (
id integer NOT NULL,
path character varying NOT NULL,
@@ -4502,7 +15299,9 @@ CREATE TABLE personal_access_tokens (
'::character varying NOT NULL,
impersonation boolean DEFAULT false NOT NULL,
token_digest character varying,
- expire_notification_delivered boolean DEFAULT false NOT NULL
+ expire_notification_delivered boolean DEFAULT false NOT NULL,
+ last_used_at timestamp with time zone,
+ after_expiry_notification_delivered boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE personal_access_tokens_id_seq
@@ -4521,7 +15320,53 @@ CREATE TABLE plan_limits (
ci_pipeline_size integer DEFAULT 0 NOT NULL,
ci_active_jobs integer DEFAULT 0 NOT NULL,
id bigint NOT NULL,
- project_hooks integer DEFAULT 0 NOT NULL
+ project_hooks integer DEFAULT 100 NOT NULL,
+ group_hooks integer DEFAULT 50 NOT NULL,
+ ci_project_subscriptions integer DEFAULT 2 NOT NULL,
+ ci_pipeline_schedules integer DEFAULT 10 NOT NULL,
+ offset_pagination_limit integer DEFAULT 50000 NOT NULL,
+ ci_instance_level_variables integer DEFAULT 25 NOT NULL,
+ ci_max_artifact_size_lsif integer DEFAULT 100 NOT NULL,
+ ci_max_artifact_size_archive integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_metadata integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_trace integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_junit integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_sast integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_dependency_scanning integer DEFAULT 350 NOT NULL,
+ ci_max_artifact_size_container_scanning integer DEFAULT 150 NOT NULL,
+ ci_max_artifact_size_dast integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_codequality integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_license_management integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_license_scanning integer DEFAULT 100 NOT NULL,
+ ci_max_artifact_size_performance integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_metrics integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_metrics_referee integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_network_referee integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_dotenv integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_cobertura integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_terraform integer DEFAULT 5 NOT NULL,
+ ci_max_artifact_size_accessibility integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_cluster_applications integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_secret_detection integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_requirements integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_coverage_fuzzing integer DEFAULT 0 NOT NULL,
+ storage_size_limit integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_browser_performance integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_load_performance integer DEFAULT 0 NOT NULL,
+ ci_needs_size_limit integer DEFAULT 50 NOT NULL,
+ conan_max_file_size bigint DEFAULT '3221225472'::bigint NOT NULL,
+ maven_max_file_size bigint DEFAULT '3221225472'::bigint NOT NULL,
+ npm_max_file_size bigint DEFAULT 524288000 NOT NULL,
+ nuget_max_file_size bigint DEFAULT 524288000 NOT NULL,
+ pypi_max_file_size bigint DEFAULT '3221225472'::bigint NOT NULL,
+ generic_packages_max_file_size bigint DEFAULT '5368709120'::bigint NOT NULL,
+ project_feature_flags integer DEFAULT 200 NOT NULL,
+ golang_max_file_size bigint DEFAULT 104857600 NOT NULL,
+ debian_max_file_size bigint DEFAULT '3221225472'::bigint NOT NULL,
+ ci_max_artifact_size_api_fuzzing integer DEFAULT 0 NOT NULL,
+ daily_invites integer DEFAULT 0 NOT NULL,
+ ci_pipeline_deployments integer DEFAULT 500 NOT NULL,
+ pull_mirror_interval_seconds integer DEFAULT 300 NOT NULL
);
CREATE SEQUENCE plan_limits_id_seq
@@ -4568,6 +15413,200 @@ CREATE SEQUENCE pool_repositories_id_seq
ALTER SEQUENCE pool_repositories_id_seq OWNED BY pool_repositories.id;
+CREATE VIEW postgres_index_bloat_estimates AS
+ SELECT (((relation_stats.nspname)::text || '.'::text) || (relation_stats.idxname)::text) AS identifier,
+ (
+ CASE
+ WHEN ((relation_stats.relpages)::double precision > relation_stats.est_pages_ff) THEN ((relation_stats.bs)::double precision * ((relation_stats.relpages)::double precision - relation_stats.est_pages_ff))
+ ELSE (0)::double precision
+ END)::bigint AS bloat_size_bytes
+ FROM ( SELECT COALESCE(((1)::double precision + ceil((rows_hdr_pdg_stats.reltuples / floor((((((rows_hdr_pdg_stats.bs - (rows_hdr_pdg_stats.pageopqdata)::numeric) - (rows_hdr_pdg_stats.pagehdr)::numeric) * (rows_hdr_pdg_stats.fillfactor)::numeric))::double precision / ((100)::double precision * (((4)::numeric + rows_hdr_pdg_stats.nulldatahdrwidth))::double precision)))))), (0)::double precision) AS est_pages_ff,
+ rows_hdr_pdg_stats.bs,
+ rows_hdr_pdg_stats.nspname,
+ rows_hdr_pdg_stats.tblname,
+ rows_hdr_pdg_stats.idxname,
+ rows_hdr_pdg_stats.relpages,
+ rows_hdr_pdg_stats.is_na
+ FROM ( SELECT rows_data_stats.maxalign,
+ rows_data_stats.bs,
+ rows_data_stats.nspname,
+ rows_data_stats.tblname,
+ rows_data_stats.idxname,
+ rows_data_stats.reltuples,
+ rows_data_stats.relpages,
+ rows_data_stats.idxoid,
+ rows_data_stats.fillfactor,
+ (((((((rows_data_stats.index_tuple_hdr_bm + rows_data_stats.maxalign) -
+ CASE
+ WHEN ((rows_data_stats.index_tuple_hdr_bm % rows_data_stats.maxalign) = 0) THEN rows_data_stats.maxalign
+ ELSE (rows_data_stats.index_tuple_hdr_bm % rows_data_stats.maxalign)
+ END))::double precision + rows_data_stats.nulldatawidth) + (rows_data_stats.maxalign)::double precision) - (
+ CASE
+ WHEN (rows_data_stats.nulldatawidth = (0)::double precision) THEN 0
+ WHEN (((rows_data_stats.nulldatawidth)::integer % rows_data_stats.maxalign) = 0) THEN rows_data_stats.maxalign
+ ELSE ((rows_data_stats.nulldatawidth)::integer % rows_data_stats.maxalign)
+ END)::double precision))::numeric AS nulldatahdrwidth,
+ rows_data_stats.pagehdr,
+ rows_data_stats.pageopqdata,
+ rows_data_stats.is_na
+ FROM ( SELECT n.nspname,
+ i.tblname,
+ i.idxname,
+ i.reltuples,
+ i.relpages,
+ i.idxoid,
+ i.fillfactor,
+ (current_setting('block_size'::text))::numeric AS bs,
+ CASE
+ WHEN ((version() ~ 'mingw32'::text) OR (version() ~ '64-bit|x86_64|ppc64|ia64|amd64'::text)) THEN 8
+ ELSE 4
+ END AS maxalign,
+ 24 AS pagehdr,
+ 16 AS pageopqdata,
+ CASE
+ WHEN (max(COALESCE(s.null_frac, (0)::real)) = (0)::double precision) THEN 2
+ ELSE (2 + (((32 + 8) - 1) / 8))
+ END AS index_tuple_hdr_bm,
+ sum((((1)::double precision - COALESCE(s.null_frac, (0)::real)) * (COALESCE(s.avg_width, 1024))::double precision)) AS nulldatawidth,
+ (max(
+ CASE
+ WHEN (i.atttypid = ('name'::regtype)::oid) THEN 1
+ ELSE 0
+ END) > 0) AS is_na
+ FROM ((( SELECT ct.relname AS tblname,
+ ct.relnamespace,
+ ic.idxname,
+ ic.attpos,
+ ic.indkey,
+ ic.indkey[ic.attpos] AS indkey,
+ ic.reltuples,
+ ic.relpages,
+ ic.tbloid,
+ ic.idxoid,
+ ic.fillfactor,
+ COALESCE(a1.attnum, a2.attnum) AS attnum,
+ COALESCE(a1.attname, a2.attname) AS attname,
+ COALESCE(a1.atttypid, a2.atttypid) AS atttypid,
+CASE
+ WHEN (a1.attnum IS NULL) THEN ic.idxname
+ ELSE ct.relname
+END AS attrelname
+ FROM (((( SELECT idx_data.idxname,
+ idx_data.reltuples,
+ idx_data.relpages,
+ idx_data.tbloid,
+ idx_data.idxoid,
+ idx_data.fillfactor,
+ idx_data.indkey,
+ generate_series(1, (idx_data.indnatts)::integer) AS attpos
+ FROM ( SELECT ci.relname AS idxname,
+ ci.reltuples,
+ ci.relpages,
+ i_1.indrelid AS tbloid,
+ i_1.indexrelid AS idxoid,
+ COALESCE((("substring"(array_to_string(ci.reloptions, ' '::text), 'fillfactor=([0-9]+)'::text))::smallint)::integer, 90) AS fillfactor,
+ i_1.indnatts,
+ (string_to_array(textin(int2vectorout(i_1.indkey)), ' '::text))::integer[] AS indkey
+ FROM (pg_index i_1
+ JOIN pg_class ci ON ((ci.oid = i_1.indexrelid)))
+ WHERE ((ci.relam = ( SELECT pg_am.oid
+ FROM pg_am
+ WHERE (pg_am.amname = 'btree'::name))) AND (ci.relpages > 0))) idx_data) ic
+ JOIN pg_class ct ON ((ct.oid = ic.tbloid)))
+ LEFT JOIN pg_attribute a1 ON (((ic.indkey[ic.attpos] <> 0) AND (a1.attrelid = ic.tbloid) AND (a1.attnum = ic.indkey[ic.attpos]))))
+ LEFT JOIN pg_attribute a2 ON (((ic.indkey[ic.attpos] = 0) AND (a2.attrelid = ic.idxoid) AND (a2.attnum = ic.attpos))))) i(tblname, relnamespace, idxname, attpos, indkey, indkey_1, reltuples, relpages, tbloid, idxoid, fillfactor, attnum, attname, atttypid, attrelname)
+ JOIN pg_namespace n ON ((n.oid = i.relnamespace)))
+ JOIN pg_stats s ON (((s.schemaname = n.nspname) AND (s.tablename = i.attrelname) AND (s.attname = i.attname))))
+ GROUP BY n.nspname, i.tblname, i.idxname, i.reltuples, i.relpages, i.idxoid, i.fillfactor, (current_setting('block_size'::text))::numeric,
+ CASE
+ WHEN ((version() ~ 'mingw32'::text) OR (version() ~ '64-bit|x86_64|ppc64|ia64|amd64'::text)) THEN 8
+ ELSE 4
+ END, 24::integer, 16::integer) rows_data_stats) rows_hdr_pdg_stats) relation_stats
+ WHERE ((relation_stats.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name])) AND (NOT relation_stats.is_na))
+ ORDER BY relation_stats.nspname, relation_stats.tblname, relation_stats.idxname;
+
+CREATE VIEW postgres_indexes AS
+ SELECT (((pg_namespace.nspname)::text || '.'::text) || (pg_class.relname)::text) AS identifier,
+ pg_index.indexrelid,
+ pg_namespace.nspname AS schema,
+ pg_class.relname AS name,
+ pg_indexes.tablename,
+ pg_index.indisunique AS "unique",
+ pg_index.indisvalid AS valid_index,
+ pg_class.relispartition AS partitioned,
+ pg_index.indisexclusion AS exclusion,
+ (pg_index.indexprs IS NOT NULL) AS expression,
+ (pg_index.indpred IS NOT NULL) AS partial,
+ pg_indexes.indexdef AS definition,
+ pg_relation_size((pg_class.oid)::regclass) AS ondisk_size_bytes
+ FROM (((pg_index
+ JOIN pg_class ON ((pg_class.oid = pg_index.indexrelid)))
+ JOIN pg_namespace ON ((pg_class.relnamespace = pg_namespace.oid)))
+ JOIN pg_indexes ON ((pg_class.relname = pg_indexes.indexname)))
+ WHERE ((pg_namespace.nspname <> 'pg_catalog'::name) AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name])));
+
+CREATE VIEW postgres_partitioned_tables AS
+ SELECT (((pg_namespace.nspname)::text || '.'::text) || (pg_class.relname)::text) AS identifier,
+ pg_class.oid,
+ pg_namespace.nspname AS schema,
+ pg_class.relname AS name,
+ CASE partitioned_tables.partstrat
+ WHEN 'l'::"char" THEN 'list'::text
+ WHEN 'r'::"char" THEN 'range'::text
+ WHEN 'h'::"char" THEN 'hash'::text
+ ELSE NULL::text
+ END AS strategy,
+ array_agg(pg_attribute.attname) AS key_columns
+ FROM (((( SELECT pg_partitioned_table.partrelid,
+ pg_partitioned_table.partstrat,
+ unnest(pg_partitioned_table.partattrs) AS column_position
+ FROM pg_partitioned_table) partitioned_tables
+ JOIN pg_class ON ((partitioned_tables.partrelid = pg_class.oid)))
+ JOIN pg_namespace ON ((pg_class.relnamespace = pg_namespace.oid)))
+ JOIN pg_attribute ON (((pg_attribute.attrelid = pg_class.oid) AND (pg_attribute.attnum = partitioned_tables.column_position))))
+ WHERE (pg_namespace.nspname = "current_schema"())
+ GROUP BY (((pg_namespace.nspname)::text || '.'::text) || (pg_class.relname)::text), pg_class.oid, pg_namespace.nspname, pg_class.relname,
+ CASE partitioned_tables.partstrat
+ WHEN 'l'::"char" THEN 'list'::text
+ WHEN 'r'::"char" THEN 'range'::text
+ WHEN 'h'::"char" THEN 'hash'::text
+ ELSE NULL::text
+ END;
+
+CREATE VIEW postgres_partitions AS
+ SELECT (((pg_namespace.nspname)::text || '.'::text) || (pg_class.relname)::text) AS identifier,
+ pg_class.oid,
+ pg_namespace.nspname AS schema,
+ pg_class.relname AS name,
+ (((parent_namespace.nspname)::text || '.'::text) || (parent_class.relname)::text) AS parent_identifier,
+ pg_get_expr(pg_class.relpartbound, pg_inherits.inhrelid) AS condition
+ FROM ((((pg_class
+ JOIN pg_namespace ON ((pg_namespace.oid = pg_class.relnamespace)))
+ JOIN pg_inherits ON ((pg_class.oid = pg_inherits.inhrelid)))
+ JOIN pg_class parent_class ON ((pg_inherits.inhparent = parent_class.oid)))
+ JOIN pg_namespace parent_namespace ON ((parent_class.relnamespace = parent_namespace.oid)))
+ WHERE (pg_class.relispartition AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name])));
+
+CREATE TABLE postgres_reindex_actions (
+ id bigint NOT NULL,
+ action_start timestamp with time zone NOT NULL,
+ action_end timestamp with time zone,
+ ondisk_size_bytes_start bigint NOT NULL,
+ ondisk_size_bytes_end bigint,
+ state smallint DEFAULT 0 NOT NULL,
+ index_identifier text NOT NULL,
+ CONSTRAINT check_f12527622c CHECK ((char_length(index_identifier) <= 255))
+);
+
+CREATE SEQUENCE postgres_reindex_actions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE postgres_reindex_actions_id_seq OWNED BY postgres_reindex_actions.id;
+
CREATE TABLE programming_languages (
id integer NOT NULL,
name character varying NOT NULL,
@@ -4585,6 +15624,11 @@ CREATE SEQUENCE programming_languages_id_seq
ALTER SEQUENCE programming_languages_id_seq OWNED BY programming_languages.id;
+CREATE TABLE project_access_tokens (
+ personal_access_token_id bigint NOT NULL,
+ project_id bigint NOT NULL
+);
+
CREATE TABLE project_alerting_settings (
project_id integer NOT NULL,
encrypted_token character varying NOT NULL,
@@ -4638,7 +15682,11 @@ CREATE TABLE project_ci_cd_settings (
project_id integer NOT NULL,
group_runners_enabled boolean DEFAULT true NOT NULL,
merge_pipelines_enabled boolean,
- default_git_depth integer
+ default_git_depth integer,
+ forward_deployment_enabled boolean,
+ merge_trains_enabled boolean DEFAULT false,
+ auto_rollback_enabled boolean DEFAULT false NOT NULL,
+ keep_latest_artifact boolean DEFAULT true NOT NULL
);
CREATE SEQUENCE project_ci_cd_settings_id_seq
@@ -4651,6 +15699,22 @@ CREATE SEQUENCE project_ci_cd_settings_id_seq
ALTER SEQUENCE project_ci_cd_settings_id_seq OWNED BY project_ci_cd_settings.id;
+CREATE TABLE project_compliance_framework_settings (
+ project_id bigint NOT NULL,
+ framework smallint,
+ framework_id bigint,
+ CONSTRAINT check_d348de9e2d CHECK ((framework_id IS NOT NULL))
+);
+
+CREATE SEQUENCE project_compliance_framework_settings_project_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE project_compliance_framework_settings_project_id_seq OWNED BY project_compliance_framework_settings.project_id;
+
CREATE TABLE project_custom_attributes (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -4713,6 +15777,24 @@ CREATE TABLE project_error_tracking_settings (
organization_name character varying
);
+CREATE TABLE project_export_jobs (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ status smallint DEFAULT 0 NOT NULL,
+ jid character varying(100) NOT NULL
+);
+
+CREATE SEQUENCE project_export_jobs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE project_export_jobs_id_seq OWNED BY project_export_jobs.id;
+
CREATE TABLE project_feature_usages (
project_id integer NOT NULL,
jira_dvcs_cloud_last_sync_at timestamp without time zone,
@@ -4730,7 +15812,12 @@ CREATE TABLE project_features (
created_at timestamp without time zone,
updated_at timestamp without time zone,
repository_access_level integer DEFAULT 20 NOT NULL,
- pages_access_level integer NOT NULL
+ pages_access_level integer NOT NULL,
+ forking_access_level integer,
+ metrics_dashboard_access_level integer,
+ analytics_access_level integer DEFAULT 20 NOT NULL,
+ requirements_access_level integer DEFAULT 20 NOT NULL,
+ operations_access_level integer DEFAULT 20 NOT NULL
);
CREATE SEQUENCE project_features_id_seq
@@ -4784,14 +15871,23 @@ ALTER SEQUENCE project_import_data_id_seq OWNED BY project_import_data.id;
CREATE TABLE project_incident_management_settings (
project_id integer NOT NULL,
- create_issue boolean DEFAULT true NOT NULL,
+ create_issue boolean DEFAULT false NOT NULL,
send_email boolean DEFAULT false NOT NULL,
- issue_template_key text
+ issue_template_key text,
+ pagerduty_active boolean DEFAULT false NOT NULL,
+ encrypted_pagerduty_token bytea,
+ encrypted_pagerduty_token_iv bytea,
+ auto_close_incident boolean DEFAULT true NOT NULL,
+ sla_timer boolean DEFAULT false,
+ sla_timer_minutes integer,
+ CONSTRAINT pagerduty_token_iv_length_constraint CHECK ((octet_length(encrypted_pagerduty_token_iv) <= 12)),
+ CONSTRAINT pagerduty_token_length_constraint CHECK ((octet_length(encrypted_pagerduty_token) <= 255))
);
CREATE TABLE project_metrics_settings (
project_id integer NOT NULL,
- external_dashboard_url character varying NOT NULL
+ external_dashboard_url character varying,
+ dashboard_timezone smallint DEFAULT 0 NOT NULL
);
CREATE TABLE project_mirror_data (
@@ -4805,7 +15901,8 @@ CREATE TABLE project_mirror_data (
last_update_scheduled_at timestamp without time zone,
last_update_started_at timestamp without time zone,
next_execution_timestamp timestamp without time zone,
- retry_count integer DEFAULT 0 NOT NULL
+ retry_count integer DEFAULT 0 NOT NULL,
+ correlation_id_value character varying(128)
);
CREATE SEQUENCE project_mirror_data_id_seq
@@ -4820,7 +15917,9 @@ ALTER SEQUENCE project_mirror_data_id_seq OWNED BY project_mirror_data.id;
CREATE TABLE project_pages_metadata (
project_id bigint NOT NULL,
- deployed boolean DEFAULT false NOT NULL
+ deployed boolean DEFAULT false NOT NULL,
+ artifacts_archive_id bigint,
+ pages_deployment_id bigint
);
CREATE TABLE project_repositories (
@@ -4864,10 +15963,57 @@ CREATE SEQUENCE project_repository_states_id_seq
ALTER SEQUENCE project_repository_states_id_seq OWNED BY project_repository_states.id;
+CREATE TABLE project_repository_storage_moves (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ state smallint DEFAULT 1 NOT NULL,
+ source_storage_name text NOT NULL,
+ destination_storage_name text NOT NULL,
+ CONSTRAINT project_repository_storage_moves_destination_storage_name CHECK ((char_length(destination_storage_name) <= 255)),
+ CONSTRAINT project_repository_storage_moves_source_storage_name CHECK ((char_length(source_storage_name) <= 255))
+);
+
+CREATE SEQUENCE project_repository_storage_moves_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE project_repository_storage_moves_id_seq OWNED BY project_repository_storage_moves.id;
+
+CREATE TABLE project_security_settings (
+ project_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ auto_fix_container_scanning boolean DEFAULT true NOT NULL,
+ auto_fix_dast boolean DEFAULT true NOT NULL,
+ auto_fix_dependency_scanning boolean DEFAULT true NOT NULL,
+ auto_fix_sast boolean DEFAULT true NOT NULL
+);
+
+CREATE SEQUENCE project_security_settings_project_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE project_security_settings_project_id_seq OWNED BY project_security_settings.project_id;
+
CREATE TABLE project_settings (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- project_id integer NOT NULL
+ project_id integer NOT NULL,
+ show_default_award_emojis boolean DEFAULT true NOT NULL,
+ allow_merge_on_skipped_pipeline boolean,
+ push_rule_id bigint,
+ squash_option smallint DEFAULT 3,
+ has_confluence boolean DEFAULT false NOT NULL,
+ cve_id_request_enabled boolean DEFAULT true NOT NULL,
+ has_vulnerabilities boolean DEFAULT false NOT NULL
);
CREATE TABLE project_statistics (
@@ -4882,7 +16028,10 @@ CREATE TABLE project_statistics (
shared_runners_seconds bigint DEFAULT 0 NOT NULL,
shared_runners_seconds_last_reset timestamp without time zone,
packages_size bigint DEFAULT 0 NOT NULL,
- wiki_size bigint
+ wiki_size bigint,
+ snippets_size bigint,
+ pipeline_artifacts_size bigint DEFAULT 0 NOT NULL,
+ uploads_size bigint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE project_statistics_id_seq
@@ -4993,7 +16142,8 @@ CREATE TABLE projects (
marked_for_deletion_at date,
marked_for_deletion_by_user_id integer,
remove_source_branch_after_merge boolean,
- suggestion_commit_message character varying(255)
+ suggestion_commit_message character varying(255),
+ autoclose_referenced_issues boolean
);
CREATE SEQUENCE projects_id_seq
@@ -5033,7 +16183,9 @@ CREATE TABLE prometheus_alerts (
operator integer NOT NULL,
environment_id integer NOT NULL,
project_id integer NOT NULL,
- prometheus_metric_id integer NOT NULL
+ prometheus_metric_id integer NOT NULL,
+ runbook_url text,
+ CONSTRAINT check_cb76d7e629 CHECK ((char_length(runbook_url) <= 255))
);
CREATE SEQUENCE prometheus_alerts_id_seq
@@ -5058,7 +16210,9 @@ CREATE TABLE prometheus_metrics (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
common boolean DEFAULT false NOT NULL,
- identifier character varying
+ identifier character varying,
+ dashboard_path text,
+ CONSTRAINT check_0ad9f01463 CHECK ((char_length(dashboard_path) <= 2048))
);
CREATE SEQUENCE prometheus_metrics_id_seq
@@ -5098,7 +16252,8 @@ CREATE TABLE protected_branch_push_access_levels (
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
group_id integer,
- user_id integer
+ user_id integer,
+ deploy_key_id integer
);
CREATE SEQUENCE protected_branch_push_access_levels_id_seq
@@ -5268,6 +16423,24 @@ CREATE SEQUENCE push_rules_id_seq
ALTER SEQUENCE push_rules_id_seq OWNED BY push_rules.id;
+CREATE TABLE raw_usage_data (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ recorded_at timestamp with time zone NOT NULL,
+ sent_at timestamp with time zone,
+ payload jsonb NOT NULL
+);
+
+CREATE SEQUENCE raw_usage_data_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE raw_usage_data_id_seq OWNED BY raw_usage_data.id;
+
CREATE TABLE redirect_routes (
id integer NOT NULL,
source_id integer NOT NULL,
@@ -5293,7 +16466,9 @@ CREATE TABLE release_links (
url character varying NOT NULL,
name character varying NOT NULL,
created_at timestamp with time zone NOT NULL,
- updated_at timestamp with time zone NOT NULL
+ updated_at timestamp with time zone NOT NULL,
+ filepath character varying(128),
+ link_type smallint DEFAULT 0
);
CREATE SEQUENCE release_links_id_seq
@@ -5347,7 +16522,8 @@ CREATE TABLE remote_mirrors (
encrypted_credentials_salt character varying,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
- error_notification_sent boolean
+ error_notification_sent boolean,
+ keep_divergent_refs boolean
);
CREATE SEQUENCE remote_mirrors_id_seq
@@ -5366,6 +16542,84 @@ CREATE TABLE repository_languages (
share double precision NOT NULL
);
+CREATE TABLE required_code_owners_sections (
+ id bigint NOT NULL,
+ protected_branch_id bigint NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_e58d53741e CHECK ((char_length(name) <= 1024))
+);
+
+CREATE SEQUENCE required_code_owners_sections_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE required_code_owners_sections_id_seq OWNED BY required_code_owners_sections.id;
+
+CREATE TABLE requirements (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id integer NOT NULL,
+ author_id integer,
+ iid integer NOT NULL,
+ cached_markdown_version integer,
+ state smallint DEFAULT 1 NOT NULL,
+ title character varying(255) NOT NULL,
+ title_html text,
+ description text,
+ description_html text,
+ CONSTRAINT check_785ae25b9d CHECK ((char_length(description) <= 10000))
+);
+
+CREATE SEQUENCE requirements_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE requirements_id_seq OWNED BY requirements.id;
+
+CREATE TABLE requirements_management_test_reports (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ requirement_id bigint NOT NULL,
+ author_id bigint,
+ state smallint NOT NULL,
+ build_id bigint
+);
+
+CREATE SEQUENCE requirements_management_test_reports_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE requirements_management_test_reports_id_seq OWNED BY requirements_management_test_reports.id;
+
+CREATE TABLE resource_iteration_events (
+ id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ issue_id bigint,
+ merge_request_id bigint,
+ iteration_id bigint,
+ created_at timestamp with time zone NOT NULL,
+ action smallint NOT NULL
+);
+
+CREATE SEQUENCE resource_iteration_events_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE resource_iteration_events_id_seq OWNED BY resource_iteration_events.id;
+
CREATE TABLE resource_label_events (
id bigint NOT NULL,
action integer NOT NULL,
@@ -5389,9 +16643,54 @@ CREATE SEQUENCE resource_label_events_id_seq
ALTER SEQUENCE resource_label_events_id_seq OWNED BY resource_label_events.id;
+CREATE TABLE resource_milestone_events (
+ id bigint NOT NULL,
+ user_id bigint,
+ issue_id bigint,
+ merge_request_id bigint,
+ milestone_id bigint,
+ action smallint NOT NULL,
+ state smallint NOT NULL,
+ created_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE resource_milestone_events_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE resource_milestone_events_id_seq OWNED BY resource_milestone_events.id;
+
+CREATE TABLE resource_state_events (
+ id bigint NOT NULL,
+ user_id bigint,
+ issue_id bigint,
+ merge_request_id bigint,
+ created_at timestamp with time zone NOT NULL,
+ state smallint NOT NULL,
+ epic_id integer,
+ source_commit text,
+ close_after_error_tracking_resolve boolean DEFAULT false NOT NULL,
+ close_auto_resolve_prometheus_alert boolean DEFAULT false NOT NULL,
+ source_merge_request_id bigint,
+ CONSTRAINT check_f0bcfaa3a2 CHECK ((char_length(source_commit) <= 40)),
+ CONSTRAINT state_events_must_belong_to_issue_or_merge_request_or_epic CHECK ((((issue_id <> NULL::bigint) AND (merge_request_id IS NULL) AND (epic_id IS NULL)) OR ((issue_id IS NULL) AND (merge_request_id <> NULL::bigint) AND (epic_id IS NULL)) OR ((issue_id IS NULL) AND (merge_request_id IS NULL) AND (epic_id <> NULL::integer))))
+);
+
+CREATE SEQUENCE resource_state_events_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE resource_state_events_id_seq OWNED BY resource_state_events.id;
+
CREATE TABLE resource_weight_events (
id bigint NOT NULL,
- user_id bigint NOT NULL,
+ user_id bigint,
issue_id bigint NOT NULL,
weight integer,
created_at timestamp with time zone NOT NULL
@@ -5443,6 +16742,25 @@ CREATE SEQUENCE routes_id_seq
ALTER SEQUENCE routes_id_seq OWNED BY routes.id;
+CREATE TABLE saml_group_links (
+ id bigint NOT NULL,
+ access_level smallint NOT NULL,
+ group_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ saml_group_name text NOT NULL,
+ CONSTRAINT check_1b3fc49d1e CHECK ((char_length(saml_group_name) <= 255))
+);
+
+CREATE SEQUENCE saml_group_links_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE saml_group_links_id_seq OWNED BY saml_group_links.id;
+
CREATE TABLE saml_providers (
id integer NOT NULL,
group_id integer NOT NULL,
@@ -5451,7 +16769,8 @@ CREATE TABLE saml_providers (
sso_url character varying NOT NULL,
enforced_sso boolean DEFAULT false NOT NULL,
enforced_group_managed_accounts boolean DEFAULT false NOT NULL,
- prohibited_outer_forks boolean DEFAULT false
+ prohibited_outer_forks boolean DEFAULT true NOT NULL,
+ default_membership_role smallint DEFAULT 10 NOT NULL
);
CREATE SEQUENCE saml_providers_id_seq
@@ -5464,6 +16783,25 @@ CREATE SEQUENCE saml_providers_id_seq
ALTER SEQUENCE saml_providers_id_seq OWNED BY saml_providers.id;
+CREATE TABLE scim_identities (
+ id bigint NOT NULL,
+ group_id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ active boolean DEFAULT false,
+ extern_uid character varying(255) NOT NULL
+);
+
+CREATE SEQUENCE scim_identities_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE scim_identities_id_seq OWNED BY scim_identities.id;
+
CREATE TABLE scim_oauth_access_tokens (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -5482,6 +16820,45 @@ CREATE SEQUENCE scim_oauth_access_tokens_id_seq
ALTER SEQUENCE scim_oauth_access_tokens_id_seq OWNED BY scim_oauth_access_tokens.id;
+CREATE TABLE security_findings (
+ id bigint NOT NULL,
+ scan_id bigint NOT NULL,
+ scanner_id bigint NOT NULL,
+ severity smallint NOT NULL,
+ confidence smallint NOT NULL,
+ project_fingerprint text NOT NULL,
+ deduplicated boolean DEFAULT false NOT NULL,
+ "position" integer,
+ uuid uuid,
+ CONSTRAINT check_b9508c6df8 CHECK ((char_length(project_fingerprint) <= 40))
+);
+
+CREATE SEQUENCE security_findings_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE security_findings_id_seq OWNED BY security_findings.id;
+
+CREATE TABLE security_scans (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ build_id bigint NOT NULL,
+ scan_type smallint NOT NULL
+);
+
+CREATE SEQUENCE security_scans_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE security_scans_id_seq OWNED BY security_scans.id;
+
CREATE TABLE self_managed_prometheus_alert_events (
id bigint NOT NULL,
project_id bigint NOT NULL,
@@ -5548,19 +16925,22 @@ CREATE TABLE serverless_domain_cluster (
creator_id bigint,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- uuid character varying(14) NOT NULL
+ uuid character varying(14) NOT NULL,
+ encrypted_key text,
+ encrypted_key_iv character varying(255),
+ certificate text
);
CREATE TABLE service_desk_settings (
project_id bigint NOT NULL,
issue_template_key character varying(255),
- outgoing_name character varying(255)
+ outgoing_name character varying(255),
+ project_key character varying(255)
);
CREATE TABLE services (
id integer NOT NULL,
type character varying,
- title character varying,
project_id integer,
created_at timestamp without time zone,
updated_at timestamp without time zone,
@@ -5573,7 +16953,6 @@ CREATE TABLE services (
tag_push_events boolean DEFAULT true,
note_events boolean DEFAULT true NOT NULL,
category character varying DEFAULT 'common'::character varying NOT NULL,
- "default" boolean DEFAULT false,
wiki_page_events boolean DEFAULT true,
pipeline_events boolean DEFAULT false NOT NULL,
confidential_issues_events boolean DEFAULT true NOT NULL,
@@ -5581,8 +16960,12 @@ CREATE TABLE services (
job_events boolean DEFAULT false NOT NULL,
confidential_note_events boolean DEFAULT true,
deployment_events boolean DEFAULT false NOT NULL,
- description character varying(500),
- comment_on_event_enabled boolean DEFAULT true NOT NULL
+ comment_on_event_enabled boolean DEFAULT true NOT NULL,
+ instance boolean DEFAULT false NOT NULL,
+ comment_detail smallint,
+ inherit_from_id bigint,
+ alert_events boolean,
+ group_id bigint
);
CREATE SEQUENCE services_id_seq
@@ -5647,6 +17030,46 @@ CREATE SEQUENCE smartcard_identities_id_seq
ALTER SEQUENCE smartcard_identities_id_seq OWNED BY smartcard_identities.id;
+CREATE TABLE snippet_repositories (
+ shard_id bigint NOT NULL,
+ snippet_id bigint NOT NULL,
+ disk_path character varying(80) NOT NULL,
+ verification_retry_count smallint,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ verification_checksum bytea,
+ verification_failure text,
+ CONSTRAINT snippet_repositories_verification_failure_text_limit CHECK ((char_length(verification_failure) <= 255))
+);
+
+CREATE TABLE snippet_repository_storage_moves (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ snippet_id bigint NOT NULL,
+ state smallint DEFAULT 1 NOT NULL,
+ source_storage_name text NOT NULL,
+ destination_storage_name text NOT NULL,
+ CONSTRAINT snippet_repository_storage_moves_destination_storage_name CHECK ((char_length(destination_storage_name) <= 255)),
+ CONSTRAINT snippet_repository_storage_moves_source_storage_name CHECK ((char_length(source_storage_name) <= 255))
+);
+
+CREATE SEQUENCE snippet_repository_storage_moves_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE snippet_repository_storage_moves_id_seq OWNED BY snippet_repository_storage_moves.id;
+
+CREATE TABLE snippet_statistics (
+ snippet_id bigint NOT NULL,
+ repository_size bigint DEFAULT 0 NOT NULL,
+ file_count bigint DEFAULT 0 NOT NULL,
+ commit_count bigint DEFAULT 0 NOT NULL
+);
+
CREATE TABLE snippet_user_mentions (
id bigint NOT NULL,
snippet_id integer NOT NULL,
@@ -5684,8 +17107,7 @@ CREATE TABLE snippets (
encrypted_secret_token character varying(255),
encrypted_secret_token_iv character varying(255),
secret boolean DEFAULT false NOT NULL,
- repository_storage character varying(255) DEFAULT 'default'::character varying NOT NULL,
- storage_version integer DEFAULT 2 NOT NULL
+ repository_read_only boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE snippets_id_seq
@@ -5703,6 +17125,8 @@ CREATE TABLE software_license_policies (
project_id integer NOT NULL,
software_license_id integer NOT NULL,
classification integer DEFAULT 0,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
CONSTRAINT check_8e8751b568 CHECK ((classification IS NOT NULL))
);
@@ -5757,6 +17181,73 @@ CREATE SEQUENCE spam_logs_id_seq
ALTER SEQUENCE spam_logs_id_seq OWNED BY spam_logs.id;
+CREATE TABLE sprints (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ start_date date,
+ due_date date,
+ project_id bigint,
+ group_id bigint,
+ iid integer NOT NULL,
+ cached_markdown_version integer,
+ title text NOT NULL,
+ title_html text,
+ description text,
+ description_html text,
+ state_enum smallint DEFAULT 1 NOT NULL,
+ CONSTRAINT sprints_must_belong_to_project_or_group CHECK ((((project_id <> NULL::bigint) AND (group_id IS NULL)) OR ((group_id <> NULL::bigint) AND (project_id IS NULL)))),
+ CONSTRAINT sprints_title CHECK ((char_length(title) <= 255))
+);
+
+CREATE SEQUENCE sprints_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE sprints_id_seq OWNED BY sprints.id;
+
+CREATE TABLE status_page_published_incidents (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ issue_id bigint NOT NULL
+);
+
+CREATE SEQUENCE status_page_published_incidents_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE status_page_published_incidents_id_seq OWNED BY status_page_published_incidents.id;
+
+CREATE TABLE status_page_settings (
+ project_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ enabled boolean DEFAULT false NOT NULL,
+ aws_s3_bucket_name character varying(63) NOT NULL,
+ aws_region character varying(255) NOT NULL,
+ aws_access_key character varying(255) NOT NULL,
+ encrypted_aws_secret_key character varying(255) NOT NULL,
+ encrypted_aws_secret_key_iv character varying(255) NOT NULL,
+ status_page_url text,
+ CONSTRAINT check_75a79cd992 CHECK ((char_length(status_page_url) <= 1024))
+);
+
+CREATE SEQUENCE status_page_settings_project_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE status_page_settings_project_id_seq OWNED BY status_page_settings.project_id;
+
CREATE TABLE subscriptions (
id integer NOT NULL,
user_id integer,
@@ -5876,6 +17367,58 @@ CREATE SEQUENCE term_agreements_id_seq
ALTER SEQUENCE term_agreements_id_seq OWNED BY term_agreements.id;
+CREATE TABLE terraform_state_versions (
+ id bigint NOT NULL,
+ terraform_state_id bigint NOT NULL,
+ created_by_user_id bigint,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ version integer NOT NULL,
+ file_store smallint NOT NULL,
+ file text NOT NULL,
+ verification_retry_count smallint,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ verification_checksum bytea,
+ verification_failure text,
+ ci_build_id bigint,
+ CONSTRAINT check_0824bb7bbd CHECK ((char_length(file) <= 255)),
+ CONSTRAINT tf_state_versions_verification_failure_text_limit CHECK ((char_length(verification_failure) <= 255))
+);
+
+CREATE SEQUENCE terraform_state_versions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE terraform_state_versions_id_seq OWNED BY terraform_state_versions.id;
+
+CREATE TABLE terraform_states (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ file_store smallint,
+ file character varying(255),
+ lock_xid character varying(255),
+ locked_at timestamp with time zone,
+ locked_by_user_id bigint,
+ uuid character varying(32) NOT NULL,
+ name character varying(255),
+ versioning_enabled boolean DEFAULT true NOT NULL
+);
+
+CREATE SEQUENCE terraform_states_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE terraform_states_id_seq OWNED BY terraform_states.id;
+
CREATE TABLE timelogs (
id integer NOT NULL,
time_spent integer NOT NULL,
@@ -5884,7 +17427,8 @@ CREATE TABLE timelogs (
updated_at timestamp without time zone NOT NULL,
issue_id integer,
merge_request_id integer,
- spent_at timestamp with time zone
+ spent_at timestamp with time zone,
+ note_id integer
);
CREATE SEQUENCE timelogs_id_seq
@@ -5910,7 +17454,8 @@ CREATE TABLE todos (
updated_at timestamp without time zone,
note_id integer,
commit_id character varying,
- group_id integer
+ group_id integer,
+ resolved_by_action smallint
);
CREATE SEQUENCE todos_id_seq
@@ -5923,6 +17468,22 @@ CREATE SEQUENCE todos_id_seq
ALTER SEQUENCE todos_id_seq OWNED BY todos.id;
+CREATE TABLE token_with_ivs (
+ id bigint NOT NULL,
+ hashed_token bytea NOT NULL,
+ hashed_plaintext_token bytea NOT NULL,
+ iv bytea NOT NULL
+);
+
+CREATE SEQUENCE token_with_ivs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE token_with_ivs_id_seq OWNED BY token_with_ivs.id;
+
CREATE TABLE trending_projects (
id integer NOT NULL,
project_id integer NOT NULL
@@ -5969,9 +17530,10 @@ CREATE TABLE uploads (
model_id integer,
uploader character varying NOT NULL,
created_at timestamp without time zone NOT NULL,
- store integer,
+ store integer DEFAULT 1,
mount_point character varying,
- secret character varying
+ secret character varying,
+ CONSTRAINT check_5e9547379c CHECK ((store IS NOT NULL))
);
CREATE SEQUENCE uploads_id_seq
@@ -6008,7 +17570,8 @@ ALTER SEQUENCE user_agent_details_id_seq OWNED BY user_agent_details.id;
CREATE TABLE user_callouts (
id integer NOT NULL,
feature_name integer NOT NULL,
- user_id integer NOT NULL
+ user_id integer NOT NULL,
+ dismissed_at timestamp with time zone
);
CREATE SEQUENCE user_callouts_id_seq
@@ -6021,6 +17584,23 @@ CREATE SEQUENCE user_callouts_id_seq
ALTER SEQUENCE user_callouts_id_seq OWNED BY user_callouts.id;
+CREATE TABLE user_canonical_emails (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ user_id bigint NOT NULL,
+ canonical_email character varying NOT NULL
+);
+
+CREATE SEQUENCE user_canonical_emails_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE user_canonical_emails_id_seq OWNED BY user_canonical_emails.id;
+
CREATE TABLE user_custom_attributes (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -6040,11 +17620,64 @@ CREATE SEQUENCE user_custom_attributes_id_seq
ALTER SEQUENCE user_custom_attributes_id_seq OWNED BY user_custom_attributes.id;
+CREATE TABLE user_details (
+ user_id bigint NOT NULL,
+ job_title character varying(200) DEFAULT ''::character varying NOT NULL,
+ bio character varying(255) DEFAULT ''::character varying NOT NULL,
+ webauthn_xid text,
+ bio_html text,
+ cached_markdown_version integer,
+ provisioned_by_group_id bigint,
+ other_role text,
+ CONSTRAINT check_245664af82 CHECK ((char_length(webauthn_xid) <= 100)),
+ CONSTRAINT check_b132136b01 CHECK ((char_length(other_role) <= 100))
+);
+
+CREATE SEQUENCE user_details_user_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE user_details_user_id_seq OWNED BY user_details.user_id;
+
+CREATE TABLE user_follow_users (
+ follower_id integer NOT NULL,
+ followee_id integer NOT NULL
+);
+
+CREATE TABLE user_highest_roles (
+ updated_at timestamp with time zone NOT NULL,
+ user_id bigint NOT NULL,
+ highest_access_level integer
+);
+
CREATE TABLE user_interacted_projects (
user_id integer NOT NULL,
project_id integer NOT NULL
);
+CREATE TABLE user_permission_export_uploads (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ user_id bigint NOT NULL,
+ file_store integer,
+ status smallint DEFAULT 0 NOT NULL,
+ file text,
+ CONSTRAINT check_1956806648 CHECK ((char_length(file) <= 255))
+);
+
+CREATE SEQUENCE user_permission_export_uploads_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE user_permission_export_uploads_id_seq OWNED BY user_permission_export_uploads.id;
+
CREATE TABLE user_preferences (
id integer NOT NULL,
user_id integer NOT NULL,
@@ -6067,7 +17700,10 @@ CREATE TABLE user_preferences (
setup_for_company boolean,
sourcegraph_enabled boolean,
render_whitespace_in_code boolean,
- tab_width smallint
+ tab_width smallint,
+ experience_level smallint,
+ view_diffs_file_by_file boolean DEFAULT false NOT NULL,
+ gitpod_enabled boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE user_preferences_id_seq
@@ -6085,7 +17721,8 @@ CREATE TABLE user_statuses (
cached_markdown_version integer,
emoji character varying DEFAULT 'speech_balloon'::character varying NOT NULL,
message character varying(100),
- message_html character varying
+ message_html character varying,
+ availability smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE user_statuses_user_id_seq
@@ -6137,7 +17774,6 @@ CREATE TABLE users (
skype character varying DEFAULT ''::character varying NOT NULL,
linkedin character varying DEFAULT ''::character varying NOT NULL,
twitter character varying DEFAULT ''::character varying NOT NULL,
- bio character varying,
failed_attempts integer DEFAULT 0,
locked_at timestamp without time zone,
username character varying,
@@ -6177,7 +17813,6 @@ CREATE TABLE users (
organization character varying,
require_two_factor_authentication_from_group boolean DEFAULT false NOT NULL,
two_factor_grace_period integer DEFAULT 48 NOT NULL,
- ghost boolean,
last_activity_on date,
notified_of_own_activity boolean,
preferred_language character varying,
@@ -6197,11 +17832,11 @@ CREATE TABLE users (
managing_group_id integer,
note text,
roadmap_layout smallint,
- bot_type smallint,
static_object_token character varying(255),
first_name character varying(255),
last_name character varying(255),
- role smallint
+ role smallint,
+ user_type smallint
);
CREATE SEQUENCE users_id_seq
@@ -6254,6 +17889,29 @@ CREATE SEQUENCE users_star_projects_id_seq
ALTER SEQUENCE users_star_projects_id_seq OWNED BY users_star_projects.id;
+CREATE TABLE users_statistics (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ without_groups_and_projects integer DEFAULT 0 NOT NULL,
+ with_highest_role_guest integer DEFAULT 0 NOT NULL,
+ with_highest_role_reporter integer DEFAULT 0 NOT NULL,
+ with_highest_role_developer integer DEFAULT 0 NOT NULL,
+ with_highest_role_maintainer integer DEFAULT 0 NOT NULL,
+ with_highest_role_owner integer DEFAULT 0 NOT NULL,
+ bots integer DEFAULT 0 NOT NULL,
+ blocked integer DEFAULT 0 NOT NULL
+);
+
+CREATE SEQUENCE users_statistics_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE users_statistics_id_seq OWNED BY users_statistics.id;
+
CREATE TABLE vulnerabilities (
id bigint NOT NULL,
milestone_id bigint,
@@ -6264,11 +17922,9 @@ CREATE TABLE vulnerabilities (
last_edited_by_id bigint,
start_date_sourcing_milestone_id bigint,
due_date_sourcing_milestone_id bigint,
- closed_by_id bigint,
last_edited_at timestamp with time zone,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- closed_at timestamp with time zone,
start_date date,
due_date date,
state smallint DEFAULT 1 NOT NULL,
@@ -6283,7 +17939,12 @@ CREATE TABLE vulnerabilities (
report_type smallint NOT NULL,
cached_markdown_version integer,
resolved_by_id bigint,
- resolved_at timestamp with time zone
+ resolved_at timestamp with time zone,
+ confirmed_by_id bigint,
+ confirmed_at timestamp with time zone,
+ dismissed_at timestamp with time zone,
+ dismissed_by_id bigint,
+ resolved_on_default_branch boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE vulnerabilities_id_seq
@@ -6295,6 +17956,53 @@ CREATE SEQUENCE vulnerabilities_id_seq
ALTER SEQUENCE vulnerabilities_id_seq OWNED BY vulnerabilities.id;
+CREATE TABLE vulnerability_exports (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ started_at timestamp with time zone,
+ finished_at timestamp with time zone,
+ status character varying(255) NOT NULL,
+ file character varying(255),
+ project_id bigint,
+ author_id bigint NOT NULL,
+ file_store integer,
+ format smallint DEFAULT 0 NOT NULL,
+ group_id integer
+);
+
+CREATE SEQUENCE vulnerability_exports_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_exports_id_seq OWNED BY vulnerability_exports.id;
+
+CREATE TABLE vulnerability_external_issue_links (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ author_id bigint NOT NULL,
+ vulnerability_id bigint NOT NULL,
+ link_type smallint DEFAULT 1 NOT NULL,
+ external_type smallint DEFAULT 1 NOT NULL,
+ external_project_key text NOT NULL,
+ external_issue_key text NOT NULL,
+ CONSTRAINT check_3200604f5e CHECK ((char_length(external_issue_key) <= 255)),
+ CONSTRAINT check_68cffd19b0 CHECK ((char_length(external_project_key) <= 255))
+);
+
+CREATE SEQUENCE vulnerability_external_issue_links_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_external_issue_links_id_seq OWNED BY vulnerability_external_issue_links.id;
+
CREATE TABLE vulnerability_feedback (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -6309,7 +18017,8 @@ CREATE TABLE vulnerability_feedback (
merge_request_id integer,
comment_author_id integer,
comment text,
- comment_timestamp timestamp with time zone
+ comment_timestamp timestamp with time zone,
+ finding_uuid uuid
);
CREATE SEQUENCE vulnerability_feedback_id_seq
@@ -6322,6 +18031,86 @@ CREATE SEQUENCE vulnerability_feedback_id_seq
ALTER SEQUENCE vulnerability_feedback_id_seq OWNED BY vulnerability_feedback.id;
+CREATE TABLE vulnerability_finding_fingerprints (
+ id bigint NOT NULL,
+ finding_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ algorithm_type integer NOT NULL,
+ fingerprint_sha256 bytea NOT NULL
+);
+
+CREATE SEQUENCE vulnerability_finding_fingerprints_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_finding_fingerprints_id_seq OWNED BY vulnerability_finding_fingerprints.id;
+
+CREATE TABLE vulnerability_finding_links (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ vulnerability_occurrence_id bigint NOT NULL,
+ name text,
+ url text NOT NULL,
+ CONSTRAINT check_55f0a95439 CHECK ((char_length(name) <= 255)),
+ CONSTRAINT check_b7fe886df6 CHECK ((char_length(url) <= 2048))
+);
+
+CREATE SEQUENCE vulnerability_finding_links_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_finding_links_id_seq OWNED BY vulnerability_finding_links.id;
+
+CREATE TABLE vulnerability_findings_remediations (
+ id bigint NOT NULL,
+ vulnerability_occurrence_id bigint,
+ vulnerability_remediation_id bigint,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE vulnerability_findings_remediations_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_findings_remediations_id_seq OWNED BY vulnerability_findings_remediations.id;
+
+CREATE TABLE vulnerability_historical_statistics (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ total integer DEFAULT 0 NOT NULL,
+ critical integer DEFAULT 0 NOT NULL,
+ high integer DEFAULT 0 NOT NULL,
+ medium integer DEFAULT 0 NOT NULL,
+ low integer DEFAULT 0 NOT NULL,
+ unknown integer DEFAULT 0 NOT NULL,
+ info integer DEFAULT 0 NOT NULL,
+ date date NOT NULL,
+ letter_grade smallint NOT NULL
+);
+
+CREATE SEQUENCE vulnerability_historical_statistics_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_historical_statistics_id_seq OWNED BY vulnerability_historical_statistics.id;
+
CREATE TABLE vulnerability_identifiers (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -6411,7 +18200,8 @@ CREATE TABLE vulnerability_occurrences (
name character varying NOT NULL,
metadata_version character varying NOT NULL,
raw_metadata text NOT NULL,
- vulnerability_id bigint
+ vulnerability_id bigint,
+ details jsonb DEFAULT '{}'::jsonb NOT NULL
);
CREATE SEQUENCE vulnerability_occurrences_id_seq
@@ -6423,13 +18213,38 @@ CREATE SEQUENCE vulnerability_occurrences_id_seq
ALTER SEQUENCE vulnerability_occurrences_id_seq OWNED BY vulnerability_occurrences.id;
+CREATE TABLE vulnerability_remediations (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ file_store smallint,
+ summary text NOT NULL,
+ file text NOT NULL,
+ checksum bytea NOT NULL,
+ project_id bigint NOT NULL,
+ CONSTRAINT check_ac0ccabff3 CHECK ((char_length(summary) <= 200)),
+ CONSTRAINT check_fe3325e3ba CHECK ((char_length(file) <= 255))
+);
+
+COMMENT ON COLUMN vulnerability_remediations.checksum IS 'Stores the SHA256 checksum of the attached diff file';
+
+CREATE SEQUENCE vulnerability_remediations_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_remediations_id_seq OWNED BY vulnerability_remediations.id;
+
CREATE TABLE vulnerability_scanners (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
project_id integer NOT NULL,
external_id character varying NOT NULL,
- name character varying NOT NULL
+ name character varying NOT NULL,
+ vendor text DEFAULT 'GitLab'::text NOT NULL
);
CREATE SEQUENCE vulnerability_scanners_id_seq
@@ -6441,6 +18256,48 @@ CREATE SEQUENCE vulnerability_scanners_id_seq
ALTER SEQUENCE vulnerability_scanners_id_seq OWNED BY vulnerability_scanners.id;
+CREATE TABLE vulnerability_statistics (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ total integer DEFAULT 0 NOT NULL,
+ critical integer DEFAULT 0 NOT NULL,
+ high integer DEFAULT 0 NOT NULL,
+ medium integer DEFAULT 0 NOT NULL,
+ low integer DEFAULT 0 NOT NULL,
+ unknown integer DEFAULT 0 NOT NULL,
+ info integer DEFAULT 0 NOT NULL,
+ letter_grade smallint NOT NULL
+);
+
+CREATE SEQUENCE vulnerability_statistics_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_statistics_id_seq OWNED BY vulnerability_statistics.id;
+
+CREATE TABLE vulnerability_user_mentions (
+ id bigint NOT NULL,
+ vulnerability_id bigint NOT NULL,
+ note_id integer,
+ mentioned_users_ids integer[],
+ mentioned_projects_ids integer[],
+ mentioned_groups_ids integer[]
+);
+
+CREATE SEQUENCE vulnerability_user_mentions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_user_mentions_id_seq OWNED BY vulnerability_user_mentions.id;
+
CREATE TABLE web_hook_logs (
id integer NOT NULL,
web_hook_id integer NOT NULL,
@@ -6491,7 +18348,11 @@ CREATE TABLE web_hooks (
encrypted_token_iv character varying,
encrypted_url character varying,
encrypted_url_iv character varying,
- group_id integer
+ group_id integer,
+ deployment_events boolean DEFAULT false NOT NULL,
+ feature_flag_events boolean DEFAULT false NOT NULL,
+ releases_events boolean DEFAULT false NOT NULL,
+ member_events boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE web_hooks_id_seq
@@ -6512,7 +18373,10 @@ CREATE TABLE webauthn_registrations (
updated_at timestamp with time zone NOT NULL,
credential_xid text NOT NULL,
name text NOT NULL,
- public_key text NOT NULL
+ public_key text NOT NULL,
+ u2f_registration_id integer,
+ CONSTRAINT check_2f02e74321 CHECK ((char_length(name) <= 255)),
+ CONSTRAINT check_e54008d9ce CHECK ((char_length(credential_xid) <= 340))
);
CREATE SEQUENCE webauthn_registrations_id_seq
@@ -6524,6 +18388,43 @@ CREATE SEQUENCE webauthn_registrations_id_seq
ALTER SEQUENCE webauthn_registrations_id_seq OWNED BY webauthn_registrations.id;
+CREATE TABLE wiki_page_meta (
+ id integer NOT NULL,
+ project_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ title character varying(255) NOT NULL
+);
+
+CREATE SEQUENCE wiki_page_meta_id_seq
+ AS integer
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE wiki_page_meta_id_seq OWNED BY wiki_page_meta.id;
+
+CREATE TABLE wiki_page_slugs (
+ id integer NOT NULL,
+ canonical boolean DEFAULT false NOT NULL,
+ wiki_page_meta_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ slug character varying(2048) NOT NULL
+);
+
+CREATE SEQUENCE wiki_page_slugs_id_seq
+ AS integer
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE wiki_page_slugs_id_seq OWNED BY wiki_page_slugs.id;
+
CREATE TABLE x509_certificates (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -6603,19 +18504,31 @@ ALTER SEQUENCE zoom_meetings_id_seq OWNED BY zoom_meetings.id;
ALTER TABLE ONLY abuse_reports ALTER COLUMN id SET DEFAULT nextval('abuse_reports_id_seq'::regclass);
+ALTER TABLE ONLY alert_management_alert_assignees ALTER COLUMN id SET DEFAULT nextval('alert_management_alert_assignees_id_seq'::regclass);
+
+ALTER TABLE ONLY alert_management_alert_user_mentions ALTER COLUMN id SET DEFAULT nextval('alert_management_alert_user_mentions_id_seq'::regclass);
+
+ALTER TABLE ONLY alert_management_alerts ALTER COLUMN id SET DEFAULT nextval('alert_management_alerts_id_seq'::regclass);
+
+ALTER TABLE ONLY alert_management_http_integrations ALTER COLUMN id SET DEFAULT nextval('alert_management_http_integrations_id_seq'::regclass);
+
ALTER TABLE ONLY alerts_service_data ALTER COLUMN id SET DEFAULT nextval('alerts_service_data_id_seq'::regclass);
ALTER TABLE ONLY allowed_email_domains ALTER COLUMN id SET DEFAULT nextval('allowed_email_domains_id_seq'::regclass);
ALTER TABLE ONLY analytics_cycle_analytics_group_stages ALTER COLUMN id SET DEFAULT nextval('analytics_cycle_analytics_group_stages_id_seq'::regclass);
+ALTER TABLE ONLY analytics_cycle_analytics_group_value_streams ALTER COLUMN id SET DEFAULT nextval('analytics_cycle_analytics_group_value_streams_id_seq'::regclass);
+
ALTER TABLE ONLY analytics_cycle_analytics_project_stages ALTER COLUMN id SET DEFAULT nextval('analytics_cycle_analytics_project_stages_id_seq'::regclass);
-ALTER TABLE ONLY analytics_repository_file_commits ALTER COLUMN id SET DEFAULT nextval('analytics_repository_file_commits_id_seq'::regclass);
+ALTER TABLE ONLY analytics_devops_adoption_segment_selections ALTER COLUMN id SET DEFAULT nextval('analytics_devops_adoption_segment_selections_id_seq'::regclass);
-ALTER TABLE ONLY analytics_repository_file_edits ALTER COLUMN id SET DEFAULT nextval('analytics_repository_file_edits_id_seq'::regclass);
+ALTER TABLE ONLY analytics_devops_adoption_segments ALTER COLUMN id SET DEFAULT nextval('analytics_devops_adoption_segments_id_seq'::regclass);
-ALTER TABLE ONLY analytics_repository_files ALTER COLUMN id SET DEFAULT nextval('analytics_repository_files_id_seq'::regclass);
+ALTER TABLE ONLY analytics_devops_adoption_snapshots ALTER COLUMN id SET DEFAULT nextval('analytics_devops_adoption_snapshots_id_seq'::regclass);
+
+ALTER TABLE ONLY analytics_instance_statistics_measurements ALTER COLUMN id SET DEFAULT nextval('analytics_instance_statistics_measurements_id_seq'::regclass);
ALTER TABLE ONLY appearances ALTER COLUMN id SET DEFAULT nextval('appearances_id_seq'::regclass);
@@ -6645,10 +18558,16 @@ ALTER TABLE ONLY approver_groups ALTER COLUMN id SET DEFAULT nextval('approver_g
ALTER TABLE ONLY approvers ALTER COLUMN id SET DEFAULT nextval('approvers_id_seq'::regclass);
+ALTER TABLE ONLY atlassian_identities ALTER COLUMN user_id SET DEFAULT nextval('atlassian_identities_user_id_seq'::regclass);
+
ALTER TABLE ONLY audit_events ALTER COLUMN id SET DEFAULT nextval('audit_events_id_seq'::regclass);
+ALTER TABLE ONLY authentication_events ALTER COLUMN id SET DEFAULT nextval('authentication_events_id_seq'::regclass);
+
ALTER TABLE ONLY award_emoji ALTER COLUMN id SET DEFAULT nextval('award_emoji_id_seq'::regclass);
+ALTER TABLE ONLY background_migration_jobs ALTER COLUMN id SET DEFAULT nextval('background_migration_jobs_id_seq'::regclass);
+
ALTER TABLE ONLY badges ALTER COLUMN id SET DEFAULT nextval('badges_id_seq'::regclass);
ALTER TABLE ONLY board_assignees ALTER COLUMN id SET DEFAULT nextval('board_assignees_id_seq'::regclass);
@@ -6659,16 +18578,40 @@ ALTER TABLE ONLY board_labels ALTER COLUMN id SET DEFAULT nextval('board_labels_
ALTER TABLE ONLY board_project_recent_visits ALTER COLUMN id SET DEFAULT nextval('board_project_recent_visits_id_seq'::regclass);
+ALTER TABLE ONLY board_user_preferences ALTER COLUMN id SET DEFAULT nextval('board_user_preferences_id_seq'::regclass);
+
ALTER TABLE ONLY boards ALTER COLUMN id SET DEFAULT nextval('boards_id_seq'::regclass);
+ALTER TABLE ONLY boards_epic_board_labels ALTER COLUMN id SET DEFAULT nextval('boards_epic_board_labels_id_seq'::regclass);
+
+ALTER TABLE ONLY boards_epic_board_positions ALTER COLUMN id SET DEFAULT nextval('boards_epic_board_positions_id_seq'::regclass);
+
+ALTER TABLE ONLY boards_epic_boards ALTER COLUMN id SET DEFAULT nextval('boards_epic_boards_id_seq'::regclass);
+
+ALTER TABLE ONLY boards_epic_user_preferences ALTER COLUMN id SET DEFAULT nextval('boards_epic_user_preferences_id_seq'::regclass);
+
ALTER TABLE ONLY broadcast_messages ALTER COLUMN id SET DEFAULT nextval('broadcast_messages_id_seq'::regclass);
+ALTER TABLE ONLY bulk_import_configurations ALTER COLUMN id SET DEFAULT nextval('bulk_import_configurations_id_seq'::regclass);
+
+ALTER TABLE ONLY bulk_import_entities ALTER COLUMN id SET DEFAULT nextval('bulk_import_entities_id_seq'::regclass);
+
+ALTER TABLE ONLY bulk_import_failures ALTER COLUMN id SET DEFAULT nextval('bulk_import_failures_id_seq'::regclass);
+
+ALTER TABLE ONLY bulk_import_trackers ALTER COLUMN id SET DEFAULT nextval('bulk_import_trackers_id_seq'::regclass);
+
+ALTER TABLE ONLY bulk_imports ALTER COLUMN id SET DEFAULT nextval('bulk_imports_id_seq'::regclass);
+
ALTER TABLE ONLY chat_names ALTER COLUMN id SET DEFAULT nextval('chat_names_id_seq'::regclass);
ALTER TABLE ONLY chat_teams ALTER COLUMN id SET DEFAULT nextval('chat_teams_id_seq'::regclass);
ALTER TABLE ONLY ci_build_needs ALTER COLUMN id SET DEFAULT nextval('ci_build_needs_id_seq'::regclass);
+ALTER TABLE ONLY ci_build_pending_states ALTER COLUMN id SET DEFAULT nextval('ci_build_pending_states_id_seq'::regclass);
+
+ALTER TABLE ONLY ci_build_report_results ALTER COLUMN build_id SET DEFAULT nextval('ci_build_report_results_build_id_seq'::regclass);
+
ALTER TABLE ONLY ci_build_trace_chunks ALTER COLUMN id SET DEFAULT nextval('ci_build_trace_chunks_id_seq'::regclass);
ALTER TABLE ONLY ci_build_trace_section_names ALTER COLUMN id SET DEFAULT nextval('ci_build_trace_section_names_id_seq'::regclass);
@@ -6679,14 +18622,26 @@ ALTER TABLE ONLY ci_builds_metadata ALTER COLUMN id SET DEFAULT nextval('ci_buil
ALTER TABLE ONLY ci_builds_runner_session ALTER COLUMN id SET DEFAULT nextval('ci_builds_runner_session_id_seq'::regclass);
+ALTER TABLE ONLY ci_daily_build_group_report_results ALTER COLUMN id SET DEFAULT nextval('ci_daily_build_group_report_results_id_seq'::regclass);
+
+ALTER TABLE ONLY ci_deleted_objects ALTER COLUMN id SET DEFAULT nextval('ci_deleted_objects_id_seq'::regclass);
+
+ALTER TABLE ONLY ci_freeze_periods ALTER COLUMN id SET DEFAULT nextval('ci_freeze_periods_id_seq'::regclass);
+
ALTER TABLE ONLY ci_group_variables ALTER COLUMN id SET DEFAULT nextval('ci_group_variables_id_seq'::regclass);
+ALTER TABLE ONLY ci_instance_variables ALTER COLUMN id SET DEFAULT nextval('ci_instance_variables_id_seq'::regclass);
+
ALTER TABLE ONLY ci_job_artifacts ALTER COLUMN id SET DEFAULT nextval('ci_job_artifacts_id_seq'::regclass);
ALTER TABLE ONLY ci_job_variables ALTER COLUMN id SET DEFAULT nextval('ci_job_variables_id_seq'::regclass);
+ALTER TABLE ONLY ci_pipeline_artifacts ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_artifacts_id_seq'::regclass);
+
ALTER TABLE ONLY ci_pipeline_chat_data ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_chat_data_id_seq'::regclass);
+ALTER TABLE ONLY ci_pipeline_messages ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_messages_id_seq'::regclass);
+
ALTER TABLE ONLY ci_pipeline_schedule_variables ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_schedule_variables_id_seq'::regclass);
ALTER TABLE ONLY ci_pipeline_schedules ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_schedules_id_seq'::regclass);
@@ -6697,6 +18652,8 @@ ALTER TABLE ONLY ci_pipelines ALTER COLUMN id SET DEFAULT nextval('ci_pipelines_
ALTER TABLE ONLY ci_pipelines_config ALTER COLUMN pipeline_id SET DEFAULT nextval('ci_pipelines_config_pipeline_id_seq'::regclass);
+ALTER TABLE ONLY ci_platform_metrics ALTER COLUMN id SET DEFAULT nextval('ci_platform_metrics_id_seq'::regclass);
+
ALTER TABLE ONLY ci_refs ALTER COLUMN id SET DEFAULT nextval('ci_refs_id_seq'::regclass);
ALTER TABLE ONLY ci_resource_groups ALTER COLUMN id SET DEFAULT nextval('ci_resource_groups_id_seq'::regclass);
@@ -6711,16 +18668,26 @@ ALTER TABLE ONLY ci_runners ALTER COLUMN id SET DEFAULT nextval('ci_runners_id_s
ALTER TABLE ONLY ci_sources_pipelines ALTER COLUMN id SET DEFAULT nextval('ci_sources_pipelines_id_seq'::regclass);
+ALTER TABLE ONLY ci_sources_projects ALTER COLUMN id SET DEFAULT nextval('ci_sources_projects_id_seq'::regclass);
+
ALTER TABLE ONLY ci_stages ALTER COLUMN id SET DEFAULT nextval('ci_stages_id_seq'::regclass);
ALTER TABLE ONLY ci_subscriptions_projects ALTER COLUMN id SET DEFAULT nextval('ci_subscriptions_projects_id_seq'::regclass);
+ALTER TABLE ONLY ci_test_case_failures ALTER COLUMN id SET DEFAULT nextval('ci_test_case_failures_id_seq'::regclass);
+
+ALTER TABLE ONLY ci_test_cases ALTER COLUMN id SET DEFAULT nextval('ci_test_cases_id_seq'::regclass);
+
ALTER TABLE ONLY ci_trigger_requests ALTER COLUMN id SET DEFAULT nextval('ci_trigger_requests_id_seq'::regclass);
ALTER TABLE ONLY ci_triggers ALTER COLUMN id SET DEFAULT nextval('ci_triggers_id_seq'::regclass);
ALTER TABLE ONLY ci_variables ALTER COLUMN id SET DEFAULT nextval('ci_variables_id_seq'::regclass);
+ALTER TABLE ONLY cluster_agent_tokens ALTER COLUMN id SET DEFAULT nextval('cluster_agent_tokens_id_seq'::regclass);
+
+ALTER TABLE ONLY cluster_agents ALTER COLUMN id SET DEFAULT nextval('cluster_agents_id_seq'::regclass);
+
ALTER TABLE ONLY cluster_groups ALTER COLUMN id SET DEFAULT nextval('cluster_groups_id_seq'::regclass);
ALTER TABLE ONLY cluster_platforms_kubernetes ALTER COLUMN id SET DEFAULT nextval('cluster_platforms_kubernetes_id_seq'::regclass);
@@ -6735,10 +18702,14 @@ ALTER TABLE ONLY clusters ALTER COLUMN id SET DEFAULT nextval('clusters_id_seq':
ALTER TABLE ONLY clusters_applications_cert_managers ALTER COLUMN id SET DEFAULT nextval('clusters_applications_cert_managers_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_cilium ALTER COLUMN id SET DEFAULT nextval('clusters_applications_cilium_id_seq'::regclass);
+
ALTER TABLE ONLY clusters_applications_crossplane ALTER COLUMN id SET DEFAULT nextval('clusters_applications_crossplane_id_seq'::regclass);
ALTER TABLE ONLY clusters_applications_elastic_stacks ALTER COLUMN id SET DEFAULT nextval('clusters_applications_elastic_stacks_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_fluentd ALTER COLUMN id SET DEFAULT nextval('clusters_applications_fluentd_id_seq'::regclass);
+
ALTER TABLE ONLY clusters_applications_helm ALTER COLUMN id SET DEFAULT nextval('clusters_applications_helm_id_seq'::regclass);
ALTER TABLE ONLY clusters_applications_ingress ALTER COLUMN id SET DEFAULT nextval('clusters_applications_ingress_id_seq'::regclass);
@@ -6755,14 +18726,32 @@ ALTER TABLE ONLY clusters_kubernetes_namespaces ALTER COLUMN id SET DEFAULT next
ALTER TABLE ONLY commit_user_mentions ALTER COLUMN id SET DEFAULT nextval('commit_user_mentions_id_seq'::regclass);
+ALTER TABLE ONLY compliance_management_frameworks ALTER COLUMN id SET DEFAULT nextval('compliance_management_frameworks_id_seq'::regclass);
+
ALTER TABLE ONLY container_repositories ALTER COLUMN id SET DEFAULT nextval('container_repositories_id_seq'::regclass);
ALTER TABLE ONLY conversational_development_index_metrics ALTER COLUMN id SET DEFAULT nextval('conversational_development_index_metrics_id_seq'::regclass);
+ALTER TABLE ONLY csv_issue_imports ALTER COLUMN id SET DEFAULT nextval('csv_issue_imports_id_seq'::regclass);
+
+ALTER TABLE ONLY custom_emoji ALTER COLUMN id SET DEFAULT nextval('custom_emoji_id_seq'::regclass);
+
+ALTER TABLE ONLY dast_scanner_profiles ALTER COLUMN id SET DEFAULT nextval('dast_scanner_profiles_id_seq'::regclass);
+
+ALTER TABLE ONLY dast_site_profiles ALTER COLUMN id SET DEFAULT nextval('dast_site_profiles_id_seq'::regclass);
+
+ALTER TABLE ONLY dast_site_tokens ALTER COLUMN id SET DEFAULT nextval('dast_site_tokens_id_seq'::regclass);
+
+ALTER TABLE ONLY dast_site_validations ALTER COLUMN id SET DEFAULT nextval('dast_site_validations_id_seq'::regclass);
+
+ALTER TABLE ONLY dast_sites ALTER COLUMN id SET DEFAULT nextval('dast_sites_id_seq'::regclass);
+
ALTER TABLE ONLY dependency_proxy_blobs ALTER COLUMN id SET DEFAULT nextval('dependency_proxy_blobs_id_seq'::regclass);
ALTER TABLE ONLY dependency_proxy_group_settings ALTER COLUMN id SET DEFAULT nextval('dependency_proxy_group_settings_id_seq'::regclass);
+ALTER TABLE ONLY dependency_proxy_manifests ALTER COLUMN id SET DEFAULT nextval('dependency_proxy_manifests_id_seq'::regclass);
+
ALTER TABLE ONLY deploy_keys_projects ALTER COLUMN id SET DEFAULT nextval('deploy_keys_projects_id_seq'::regclass);
ALTER TABLE ONLY deploy_tokens ALTER COLUMN id SET DEFAULT nextval('deploy_tokens_id_seq'::regclass);
@@ -6773,12 +18762,18 @@ ALTER TABLE ONLY description_versions ALTER COLUMN id SET DEFAULT nextval('descr
ALTER TABLE ONLY design_management_designs ALTER COLUMN id SET DEFAULT nextval('design_management_designs_id_seq'::regclass);
+ALTER TABLE ONLY design_management_designs_versions ALTER COLUMN id SET DEFAULT nextval('design_management_designs_versions_id_seq'::regclass);
+
ALTER TABLE ONLY design_management_versions ALTER COLUMN id SET DEFAULT nextval('design_management_versions_id_seq'::regclass);
ALTER TABLE ONLY design_user_mentions ALTER COLUMN id SET DEFAULT nextval('design_user_mentions_id_seq'::regclass);
+ALTER TABLE ONLY diff_note_positions ALTER COLUMN id SET DEFAULT nextval('diff_note_positions_id_seq'::regclass);
+
ALTER TABLE ONLY draft_notes ALTER COLUMN id SET DEFAULT nextval('draft_notes_id_seq'::regclass);
+ALTER TABLE ONLY elastic_reindexing_tasks ALTER COLUMN id SET DEFAULT nextval('elastic_reindexing_tasks_id_seq'::regclass);
+
ALTER TABLE ONLY emails ALTER COLUMN id SET DEFAULT nextval('emails_id_seq'::regclass);
ALTER TABLE ONLY environments ALTER COLUMN id SET DEFAULT nextval('environments_id_seq'::regclass);
@@ -6795,6 +18790,12 @@ ALTER TABLE ONLY events ALTER COLUMN id SET DEFAULT nextval('events_id_seq'::reg
ALTER TABLE ONLY evidences ALTER COLUMN id SET DEFAULT nextval('evidences_id_seq'::regclass);
+ALTER TABLE ONLY experiment_subjects ALTER COLUMN id SET DEFAULT nextval('experiment_subjects_id_seq'::regclass);
+
+ALTER TABLE ONLY experiment_users ALTER COLUMN id SET DEFAULT nextval('experiment_users_id_seq'::regclass);
+
+ALTER TABLE ONLY experiments ALTER COLUMN id SET DEFAULT nextval('experiments_id_seq'::regclass);
+
ALTER TABLE ONLY external_pull_requests ALTER COLUMN id SET DEFAULT nextval('external_pull_requests_id_seq'::regclass);
ALTER TABLE ONLY feature_gates ALTER COLUMN id SET DEFAULT nextval('feature_gates_id_seq'::regclass);
@@ -6805,14 +18806,14 @@ ALTER TABLE ONLY fork_network_members ALTER COLUMN id SET DEFAULT nextval('fork_
ALTER TABLE ONLY fork_networks ALTER COLUMN id SET DEFAULT nextval('fork_networks_id_seq'::regclass);
-ALTER TABLE ONLY forked_project_links ALTER COLUMN id SET DEFAULT nextval('forked_project_links_id_seq'::regclass);
-
ALTER TABLE ONLY geo_cache_invalidation_events ALTER COLUMN id SET DEFAULT nextval('geo_cache_invalidation_events_id_seq'::regclass);
ALTER TABLE ONLY geo_container_repository_updated_events ALTER COLUMN id SET DEFAULT nextval('geo_container_repository_updated_events_id_seq'::regclass);
ALTER TABLE ONLY geo_event_log ALTER COLUMN id SET DEFAULT nextval('geo_event_log_id_seq'::regclass);
+ALTER TABLE ONLY geo_events ALTER COLUMN id SET DEFAULT nextval('geo_events_id_seq'::regclass);
+
ALTER TABLE ONLY geo_hashed_storage_attachments_events ALTER COLUMN id SET DEFAULT nextval('geo_hashed_storage_attachments_events_id_seq'::regclass);
ALTER TABLE ONLY geo_hashed_storage_migrated_events ALTER COLUMN id SET DEFAULT nextval('geo_hashed_storage_migrated_events_id_seq'::regclass);
@@ -6855,8 +18856,16 @@ ALTER TABLE ONLY grafana_integrations ALTER COLUMN id SET DEFAULT nextval('grafa
ALTER TABLE ONLY group_custom_attributes ALTER COLUMN id SET DEFAULT nextval('group_custom_attributes_id_seq'::regclass);
+ALTER TABLE ONLY group_deploy_keys ALTER COLUMN id SET DEFAULT nextval('group_deploy_keys_id_seq'::regclass);
+
+ALTER TABLE ONLY group_deploy_keys_groups ALTER COLUMN id SET DEFAULT nextval('group_deploy_keys_groups_id_seq'::regclass);
+
+ALTER TABLE ONLY group_deploy_tokens ALTER COLUMN id SET DEFAULT nextval('group_deploy_tokens_id_seq'::regclass);
+
ALTER TABLE ONLY group_group_links ALTER COLUMN id SET DEFAULT nextval('group_group_links_id_seq'::regclass);
+ALTER TABLE ONLY group_import_states ALTER COLUMN group_id SET DEFAULT nextval('group_import_states_group_id_seq'::regclass);
+
ALTER TABLE ONLY historical_data ALTER COLUMN id SET DEFAULT nextval('historical_data_id_seq'::regclass);
ALTER TABLE ONLY identities ALTER COLUMN id SET DEFAULT nextval('identities_id_seq'::regclass);
@@ -6865,6 +18874,14 @@ ALTER TABLE ONLY import_export_uploads ALTER COLUMN id SET DEFAULT nextval('impo
ALTER TABLE ONLY import_failures ALTER COLUMN id SET DEFAULT nextval('import_failures_id_seq'::regclass);
+ALTER TABLE ONLY incident_management_oncall_participants ALTER COLUMN id SET DEFAULT nextval('incident_management_oncall_participants_id_seq'::regclass);
+
+ALTER TABLE ONLY incident_management_oncall_rotations ALTER COLUMN id SET DEFAULT nextval('incident_management_oncall_rotations_id_seq'::regclass);
+
+ALTER TABLE ONLY incident_management_oncall_schedules ALTER COLUMN id SET DEFAULT nextval('incident_management_oncall_schedules_id_seq'::regclass);
+
+ALTER TABLE ONLY incident_management_oncall_shifts ALTER COLUMN id SET DEFAULT nextval('incident_management_oncall_shifts_id_seq'::regclass);
+
ALTER TABLE ONLY index_statuses ALTER COLUMN id SET DEFAULT nextval('index_statuses_id_seq'::regclass);
ALTER TABLE ONLY insights ALTER COLUMN id SET DEFAULT nextval('insights_id_seq'::regclass);
@@ -6873,6 +18890,14 @@ ALTER TABLE ONLY internal_ids ALTER COLUMN id SET DEFAULT nextval('internal_ids_
ALTER TABLE ONLY ip_restrictions ALTER COLUMN id SET DEFAULT nextval('ip_restrictions_id_seq'::regclass);
+ALTER TABLE ONLY issuable_metric_images ALTER COLUMN id SET DEFAULT nextval('issuable_metric_images_id_seq'::regclass);
+
+ALTER TABLE ONLY issuable_severities ALTER COLUMN id SET DEFAULT nextval('issuable_severities_id_seq'::regclass);
+
+ALTER TABLE ONLY issuable_slas ALTER COLUMN id SET DEFAULT nextval('issuable_slas_id_seq'::regclass);
+
+ALTER TABLE ONLY issue_email_participants ALTER COLUMN id SET DEFAULT nextval('issue_email_participants_id_seq'::regclass);
+
ALTER TABLE ONLY issue_links ALTER COLUMN id SET DEFAULT nextval('issue_links_id_seq'::regclass);
ALTER TABLE ONLY issue_metrics ALTER COLUMN id SET DEFAULT nextval('issue_metrics_id_seq'::regclass);
@@ -6887,6 +18912,8 @@ ALTER TABLE ONLY jira_connect_installations ALTER COLUMN id SET DEFAULT nextval(
ALTER TABLE ONLY jira_connect_subscriptions ALTER COLUMN id SET DEFAULT nextval('jira_connect_subscriptions_id_seq'::regclass);
+ALTER TABLE ONLY jira_imports ALTER COLUMN id SET DEFAULT nextval('jira_imports_id_seq'::regclass);
+
ALTER TABLE ONLY jira_tracker_data ALTER COLUMN id SET DEFAULT nextval('jira_tracker_data_id_seq'::regclass);
ALTER TABLE ONLY keys ALTER COLUMN id SET DEFAULT nextval('keys_id_seq'::regclass);
@@ -6917,12 +18944,18 @@ ALTER TABLE ONLY merge_request_assignees ALTER COLUMN id SET DEFAULT nextval('me
ALTER TABLE ONLY merge_request_blocks ALTER COLUMN id SET DEFAULT nextval('merge_request_blocks_id_seq'::regclass);
+ALTER TABLE ONLY merge_request_cleanup_schedules ALTER COLUMN merge_request_id SET DEFAULT nextval('merge_request_cleanup_schedules_merge_request_id_seq'::regclass);
+
ALTER TABLE ONLY merge_request_context_commits ALTER COLUMN id SET DEFAULT nextval('merge_request_context_commits_id_seq'::regclass);
+ALTER TABLE ONLY merge_request_diff_details ALTER COLUMN merge_request_diff_id SET DEFAULT nextval('merge_request_diff_details_merge_request_diff_id_seq'::regclass);
+
ALTER TABLE ONLY merge_request_diffs ALTER COLUMN id SET DEFAULT nextval('merge_request_diffs_id_seq'::regclass);
ALTER TABLE ONLY merge_request_metrics ALTER COLUMN id SET DEFAULT nextval('merge_request_metrics_id_seq'::regclass);
+ALTER TABLE ONLY merge_request_reviewers ALTER COLUMN id SET DEFAULT nextval('merge_request_reviewers_id_seq'::regclass);
+
ALTER TABLE ONLY merge_request_user_mentions ALTER COLUMN id SET DEFAULT nextval('merge_request_user_mentions_id_seq'::regclass);
ALTER TABLE ONLY merge_requests ALTER COLUMN id SET DEFAULT nextval('merge_requests_id_seq'::regclass);
@@ -6931,10 +18964,16 @@ ALTER TABLE ONLY merge_requests_closing_issues ALTER COLUMN id SET DEFAULT nextv
ALTER TABLE ONLY merge_trains ALTER COLUMN id SET DEFAULT nextval('merge_trains_id_seq'::regclass);
+ALTER TABLE ONLY metrics_dashboard_annotations ALTER COLUMN id SET DEFAULT nextval('metrics_dashboard_annotations_id_seq'::regclass);
+
+ALTER TABLE ONLY metrics_users_starred_dashboards ALTER COLUMN id SET DEFAULT nextval('metrics_users_starred_dashboards_id_seq'::regclass);
+
ALTER TABLE ONLY milestones ALTER COLUMN id SET DEFAULT nextval('milestones_id_seq'::regclass);
ALTER TABLE ONLY namespace_aggregation_schedules ALTER COLUMN namespace_id SET DEFAULT nextval('namespace_aggregation_schedules_namespace_id_seq'::regclass);
+ALTER TABLE ONLY namespace_onboarding_actions ALTER COLUMN id SET DEFAULT nextval('namespace_onboarding_actions_id_seq'::regclass);
+
ALTER TABLE ONLY namespace_root_storage_statistics ALTER COLUMN namespace_id SET DEFAULT nextval('namespace_root_storage_statistics_namespace_id_seq'::regclass);
ALTER TABLE ONLY namespace_statistics ALTER COLUMN id SET DEFAULT nextval('namespace_statistics_id_seq'::regclass);
@@ -6955,34 +18994,72 @@ ALTER TABLE ONLY oauth_applications ALTER COLUMN id SET DEFAULT nextval('oauth_a
ALTER TABLE ONLY oauth_openid_requests ALTER COLUMN id SET DEFAULT nextval('oauth_openid_requests_id_seq'::regclass);
+ALTER TABLE ONLY open_project_tracker_data ALTER COLUMN id SET DEFAULT nextval('open_project_tracker_data_id_seq'::regclass);
+
ALTER TABLE ONLY operations_feature_flag_scopes ALTER COLUMN id SET DEFAULT nextval('operations_feature_flag_scopes_id_seq'::regclass);
ALTER TABLE ONLY operations_feature_flags ALTER COLUMN id SET DEFAULT nextval('operations_feature_flags_id_seq'::regclass);
ALTER TABLE ONLY operations_feature_flags_clients ALTER COLUMN id SET DEFAULT nextval('operations_feature_flags_clients_id_seq'::regclass);
+ALTER TABLE ONLY operations_feature_flags_issues ALTER COLUMN id SET DEFAULT nextval('operations_feature_flags_issues_id_seq'::regclass);
+
+ALTER TABLE ONLY operations_scopes ALTER COLUMN id SET DEFAULT nextval('operations_scopes_id_seq'::regclass);
+
+ALTER TABLE ONLY operations_strategies ALTER COLUMN id SET DEFAULT nextval('operations_strategies_id_seq'::regclass);
+
+ALTER TABLE ONLY operations_strategies_user_lists ALTER COLUMN id SET DEFAULT nextval('operations_strategies_user_lists_id_seq'::regclass);
+
+ALTER TABLE ONLY operations_user_lists ALTER COLUMN id SET DEFAULT nextval('operations_user_lists_id_seq'::regclass);
+
ALTER TABLE ONLY packages_build_infos ALTER COLUMN id SET DEFAULT nextval('packages_build_infos_id_seq'::regclass);
ALTER TABLE ONLY packages_conan_file_metadata ALTER COLUMN id SET DEFAULT nextval('packages_conan_file_metadata_id_seq'::regclass);
ALTER TABLE ONLY packages_conan_metadata ALTER COLUMN id SET DEFAULT nextval('packages_conan_metadata_id_seq'::regclass);
+ALTER TABLE ONLY packages_debian_group_architectures ALTER COLUMN id SET DEFAULT nextval('packages_debian_group_architectures_id_seq'::regclass);
+
+ALTER TABLE ONLY packages_debian_group_component_files ALTER COLUMN id SET DEFAULT nextval('packages_debian_group_component_files_id_seq'::regclass);
+
+ALTER TABLE ONLY packages_debian_group_components ALTER COLUMN id SET DEFAULT nextval('packages_debian_group_components_id_seq'::regclass);
+
+ALTER TABLE ONLY packages_debian_group_distributions ALTER COLUMN id SET DEFAULT nextval('packages_debian_group_distributions_id_seq'::regclass);
+
+ALTER TABLE ONLY packages_debian_project_architectures ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_architectures_id_seq'::regclass);
+
+ALTER TABLE ONLY packages_debian_project_component_files ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_component_files_id_seq'::regclass);
+
+ALTER TABLE ONLY packages_debian_project_components ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_components_id_seq'::regclass);
+
+ALTER TABLE ONLY packages_debian_project_distributions ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_distributions_id_seq'::regclass);
+
+ALTER TABLE ONLY packages_debian_publications ALTER COLUMN id SET DEFAULT nextval('packages_debian_publications_id_seq'::regclass);
+
ALTER TABLE ONLY packages_dependencies ALTER COLUMN id SET DEFAULT nextval('packages_dependencies_id_seq'::regclass);
ALTER TABLE ONLY packages_dependency_links ALTER COLUMN id SET DEFAULT nextval('packages_dependency_links_id_seq'::regclass);
+ALTER TABLE ONLY packages_events ALTER COLUMN id SET DEFAULT nextval('packages_events_id_seq'::regclass);
+
ALTER TABLE ONLY packages_maven_metadata ALTER COLUMN id SET DEFAULT nextval('packages_maven_metadata_id_seq'::regclass);
+ALTER TABLE ONLY packages_package_file_build_infos ALTER COLUMN id SET DEFAULT nextval('packages_package_file_build_infos_id_seq'::regclass);
+
ALTER TABLE ONLY packages_package_files ALTER COLUMN id SET DEFAULT nextval('packages_package_files_id_seq'::regclass);
ALTER TABLE ONLY packages_packages ALTER COLUMN id SET DEFAULT nextval('packages_packages_id_seq'::regclass);
ALTER TABLE ONLY packages_tags ALTER COLUMN id SET DEFAULT nextval('packages_tags_id_seq'::regclass);
+ALTER TABLE ONLY pages_deployments ALTER COLUMN id SET DEFAULT nextval('pages_deployments_id_seq'::regclass);
+
ALTER TABLE ONLY pages_domain_acme_orders ALTER COLUMN id SET DEFAULT nextval('pages_domain_acme_orders_id_seq'::regclass);
ALTER TABLE ONLY pages_domains ALTER COLUMN id SET DEFAULT nextval('pages_domains_id_seq'::regclass);
+ALTER TABLE ONLY partitioned_foreign_keys ALTER COLUMN id SET DEFAULT nextval('partitioned_foreign_keys_id_seq'::regclass);
+
ALTER TABLE ONLY path_locks ALTER COLUMN id SET DEFAULT nextval('path_locks_id_seq'::regclass);
ALTER TABLE ONLY personal_access_tokens ALTER COLUMN id SET DEFAULT nextval('personal_access_tokens_id_seq'::regclass);
@@ -6993,6 +19070,10 @@ ALTER TABLE ONLY plans ALTER COLUMN id SET DEFAULT nextval('plans_id_seq'::regcl
ALTER TABLE ONLY pool_repositories ALTER COLUMN id SET DEFAULT nextval('pool_repositories_id_seq'::regclass);
+ALTER TABLE ONLY postgres_reindex_actions ALTER COLUMN id SET DEFAULT nextval('postgres_reindex_actions_id_seq'::regclass);
+
+ALTER TABLE ONLY product_analytics_events_experimental ALTER COLUMN id SET DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass);
+
ALTER TABLE ONLY programming_languages ALTER COLUMN id SET DEFAULT nextval('programming_languages_id_seq'::regclass);
ALTER TABLE ONLY project_aliases ALTER COLUMN id SET DEFAULT nextval('project_aliases_id_seq'::regclass);
@@ -7001,12 +19082,16 @@ ALTER TABLE ONLY project_auto_devops ALTER COLUMN id SET DEFAULT nextval('projec
ALTER TABLE ONLY project_ci_cd_settings ALTER COLUMN id SET DEFAULT nextval('project_ci_cd_settings_id_seq'::regclass);
+ALTER TABLE ONLY project_compliance_framework_settings ALTER COLUMN project_id SET DEFAULT nextval('project_compliance_framework_settings_project_id_seq'::regclass);
+
ALTER TABLE ONLY project_custom_attributes ALTER COLUMN id SET DEFAULT nextval('project_custom_attributes_id_seq'::regclass);
ALTER TABLE ONLY project_daily_statistics ALTER COLUMN id SET DEFAULT nextval('project_daily_statistics_id_seq'::regclass);
ALTER TABLE ONLY project_deploy_tokens ALTER COLUMN id SET DEFAULT nextval('project_deploy_tokens_id_seq'::regclass);
+ALTER TABLE ONLY project_export_jobs ALTER COLUMN id SET DEFAULT nextval('project_export_jobs_id_seq'::regclass);
+
ALTER TABLE ONLY project_features ALTER COLUMN id SET DEFAULT nextval('project_features_id_seq'::regclass);
ALTER TABLE ONLY project_group_links ALTER COLUMN id SET DEFAULT nextval('project_group_links_id_seq'::regclass);
@@ -7019,6 +19104,10 @@ ALTER TABLE ONLY project_repositories ALTER COLUMN id SET DEFAULT nextval('proje
ALTER TABLE ONLY project_repository_states ALTER COLUMN id SET DEFAULT nextval('project_repository_states_id_seq'::regclass);
+ALTER TABLE ONLY project_repository_storage_moves ALTER COLUMN id SET DEFAULT nextval('project_repository_storage_moves_id_seq'::regclass);
+
+ALTER TABLE ONLY project_security_settings ALTER COLUMN project_id SET DEFAULT nextval('project_security_settings_project_id_seq'::regclass);
+
ALTER TABLE ONLY project_statistics ALTER COLUMN id SET DEFAULT nextval('project_statistics_id_seq'::regclass);
ALTER TABLE ONLY project_tracing_settings ALTER COLUMN id SET DEFAULT nextval('project_tracing_settings_id_seq'::regclass);
@@ -7049,6 +19138,8 @@ ALTER TABLE ONLY protected_tags ALTER COLUMN id SET DEFAULT nextval('protected_t
ALTER TABLE ONLY push_rules ALTER COLUMN id SET DEFAULT nextval('push_rules_id_seq'::regclass);
+ALTER TABLE ONLY raw_usage_data ALTER COLUMN id SET DEFAULT nextval('raw_usage_data_id_seq'::regclass);
+
ALTER TABLE ONLY redirect_routes ALTER COLUMN id SET DEFAULT nextval('redirect_routes_id_seq'::regclass);
ALTER TABLE ONLY release_links ALTER COLUMN id SET DEFAULT nextval('release_links_id_seq'::regclass);
@@ -7057,18 +19148,38 @@ ALTER TABLE ONLY releases ALTER COLUMN id SET DEFAULT nextval('releases_id_seq':
ALTER TABLE ONLY remote_mirrors ALTER COLUMN id SET DEFAULT nextval('remote_mirrors_id_seq'::regclass);
+ALTER TABLE ONLY required_code_owners_sections ALTER COLUMN id SET DEFAULT nextval('required_code_owners_sections_id_seq'::regclass);
+
+ALTER TABLE ONLY requirements ALTER COLUMN id SET DEFAULT nextval('requirements_id_seq'::regclass);
+
+ALTER TABLE ONLY requirements_management_test_reports ALTER COLUMN id SET DEFAULT nextval('requirements_management_test_reports_id_seq'::regclass);
+
+ALTER TABLE ONLY resource_iteration_events ALTER COLUMN id SET DEFAULT nextval('resource_iteration_events_id_seq'::regclass);
+
ALTER TABLE ONLY resource_label_events ALTER COLUMN id SET DEFAULT nextval('resource_label_events_id_seq'::regclass);
+ALTER TABLE ONLY resource_milestone_events ALTER COLUMN id SET DEFAULT nextval('resource_milestone_events_id_seq'::regclass);
+
+ALTER TABLE ONLY resource_state_events ALTER COLUMN id SET DEFAULT nextval('resource_state_events_id_seq'::regclass);
+
ALTER TABLE ONLY resource_weight_events ALTER COLUMN id SET DEFAULT nextval('resource_weight_events_id_seq'::regclass);
ALTER TABLE ONLY reviews ALTER COLUMN id SET DEFAULT nextval('reviews_id_seq'::regclass);
ALTER TABLE ONLY routes ALTER COLUMN id SET DEFAULT nextval('routes_id_seq'::regclass);
+ALTER TABLE ONLY saml_group_links ALTER COLUMN id SET DEFAULT nextval('saml_group_links_id_seq'::regclass);
+
ALTER TABLE ONLY saml_providers ALTER COLUMN id SET DEFAULT nextval('saml_providers_id_seq'::regclass);
+ALTER TABLE ONLY scim_identities ALTER COLUMN id SET DEFAULT nextval('scim_identities_id_seq'::regclass);
+
ALTER TABLE ONLY scim_oauth_access_tokens ALTER COLUMN id SET DEFAULT nextval('scim_oauth_access_tokens_id_seq'::regclass);
+ALTER TABLE ONLY security_findings ALTER COLUMN id SET DEFAULT nextval('security_findings_id_seq'::regclass);
+
+ALTER TABLE ONLY security_scans ALTER COLUMN id SET DEFAULT nextval('security_scans_id_seq'::regclass);
+
ALTER TABLE ONLY self_managed_prometheus_alert_events ALTER COLUMN id SET DEFAULT nextval('self_managed_prometheus_alert_events_id_seq'::regclass);
ALTER TABLE ONLY sent_notifications ALTER COLUMN id SET DEFAULT nextval('sent_notifications_id_seq'::regclass);
@@ -7083,6 +19194,8 @@ ALTER TABLE ONLY slack_integrations ALTER COLUMN id SET DEFAULT nextval('slack_i
ALTER TABLE ONLY smartcard_identities ALTER COLUMN id SET DEFAULT nextval('smartcard_identities_id_seq'::regclass);
+ALTER TABLE ONLY snippet_repository_storage_moves ALTER COLUMN id SET DEFAULT nextval('snippet_repository_storage_moves_id_seq'::regclass);
+
ALTER TABLE ONLY snippet_user_mentions ALTER COLUMN id SET DEFAULT nextval('snippet_user_mentions_id_seq'::regclass);
ALTER TABLE ONLY snippets ALTER COLUMN id SET DEFAULT nextval('snippets_id_seq'::regclass);
@@ -7093,6 +19206,12 @@ ALTER TABLE ONLY software_licenses ALTER COLUMN id SET DEFAULT nextval('software
ALTER TABLE ONLY spam_logs ALTER COLUMN id SET DEFAULT nextval('spam_logs_id_seq'::regclass);
+ALTER TABLE ONLY sprints ALTER COLUMN id SET DEFAULT nextval('sprints_id_seq'::regclass);
+
+ALTER TABLE ONLY status_page_published_incidents ALTER COLUMN id SET DEFAULT nextval('status_page_published_incidents_id_seq'::regclass);
+
+ALTER TABLE ONLY status_page_settings ALTER COLUMN project_id SET DEFAULT nextval('status_page_settings_project_id_seq'::regclass);
+
ALTER TABLE ONLY subscriptions ALTER COLUMN id SET DEFAULT nextval('subscriptions_id_seq'::regclass);
ALTER TABLE ONLY suggestions ALTER COLUMN id SET DEFAULT nextval('suggestions_id_seq'::regclass);
@@ -7105,10 +19224,16 @@ ALTER TABLE ONLY tags ALTER COLUMN id SET DEFAULT nextval('tags_id_seq'::regclas
ALTER TABLE ONLY term_agreements ALTER COLUMN id SET DEFAULT nextval('term_agreements_id_seq'::regclass);
+ALTER TABLE ONLY terraform_state_versions ALTER COLUMN id SET DEFAULT nextval('terraform_state_versions_id_seq'::regclass);
+
+ALTER TABLE ONLY terraform_states ALTER COLUMN id SET DEFAULT nextval('terraform_states_id_seq'::regclass);
+
ALTER TABLE ONLY timelogs ALTER COLUMN id SET DEFAULT nextval('timelogs_id_seq'::regclass);
ALTER TABLE ONLY todos ALTER COLUMN id SET DEFAULT nextval('todos_id_seq'::regclass);
+ALTER TABLE ONLY token_with_ivs ALTER COLUMN id SET DEFAULT nextval('token_with_ivs_id_seq'::regclass);
+
ALTER TABLE ONLY trending_projects ALTER COLUMN id SET DEFAULT nextval('trending_projects_id_seq'::regclass);
ALTER TABLE ONLY u2f_registrations ALTER COLUMN id SET DEFAULT nextval('u2f_registrations_id_seq'::regclass);
@@ -7119,8 +19244,14 @@ ALTER TABLE ONLY user_agent_details ALTER COLUMN id SET DEFAULT nextval('user_ag
ALTER TABLE ONLY user_callouts ALTER COLUMN id SET DEFAULT nextval('user_callouts_id_seq'::regclass);
+ALTER TABLE ONLY user_canonical_emails ALTER COLUMN id SET DEFAULT nextval('user_canonical_emails_id_seq'::regclass);
+
ALTER TABLE ONLY user_custom_attributes ALTER COLUMN id SET DEFAULT nextval('user_custom_attributes_id_seq'::regclass);
+ALTER TABLE ONLY user_details ALTER COLUMN user_id SET DEFAULT nextval('user_details_user_id_seq'::regclass);
+
+ALTER TABLE ONLY user_permission_export_uploads ALTER COLUMN id SET DEFAULT nextval('user_permission_export_uploads_id_seq'::regclass);
+
ALTER TABLE ONLY user_preferences ALTER COLUMN id SET DEFAULT nextval('user_preferences_id_seq'::regclass);
ALTER TABLE ONLY user_statuses ALTER COLUMN user_id SET DEFAULT nextval('user_statuses_user_id_seq'::regclass);
@@ -7133,10 +19264,24 @@ ALTER TABLE ONLY users_ops_dashboard_projects ALTER COLUMN id SET DEFAULT nextva
ALTER TABLE ONLY users_star_projects ALTER COLUMN id SET DEFAULT nextval('users_star_projects_id_seq'::regclass);
+ALTER TABLE ONLY users_statistics ALTER COLUMN id SET DEFAULT nextval('users_statistics_id_seq'::regclass);
+
ALTER TABLE ONLY vulnerabilities ALTER COLUMN id SET DEFAULT nextval('vulnerabilities_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_exports ALTER COLUMN id SET DEFAULT nextval('vulnerability_exports_id_seq'::regclass);
+
+ALTER TABLE ONLY vulnerability_external_issue_links ALTER COLUMN id SET DEFAULT nextval('vulnerability_external_issue_links_id_seq'::regclass);
+
ALTER TABLE ONLY vulnerability_feedback ALTER COLUMN id SET DEFAULT nextval('vulnerability_feedback_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_finding_fingerprints ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_fingerprints_id_seq'::regclass);
+
+ALTER TABLE ONLY vulnerability_finding_links ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_links_id_seq'::regclass);
+
+ALTER TABLE ONLY vulnerability_findings_remediations ALTER COLUMN id SET DEFAULT nextval('vulnerability_findings_remediations_id_seq'::regclass);
+
+ALTER TABLE ONLY vulnerability_historical_statistics ALTER COLUMN id SET DEFAULT nextval('vulnerability_historical_statistics_id_seq'::regclass);
+
ALTER TABLE ONLY vulnerability_identifiers ALTER COLUMN id SET DEFAULT nextval('vulnerability_identifiers_id_seq'::regclass);
ALTER TABLE ONLY vulnerability_issue_links ALTER COLUMN id SET DEFAULT nextval('vulnerability_issue_links_id_seq'::regclass);
@@ -7147,14 +19292,24 @@ ALTER TABLE ONLY vulnerability_occurrence_pipelines ALTER COLUMN id SET DEFAULT
ALTER TABLE ONLY vulnerability_occurrences ALTER COLUMN id SET DEFAULT nextval('vulnerability_occurrences_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_remediations ALTER COLUMN id SET DEFAULT nextval('vulnerability_remediations_id_seq'::regclass);
+
ALTER TABLE ONLY vulnerability_scanners ALTER COLUMN id SET DEFAULT nextval('vulnerability_scanners_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_statistics ALTER COLUMN id SET DEFAULT nextval('vulnerability_statistics_id_seq'::regclass);
+
+ALTER TABLE ONLY vulnerability_user_mentions ALTER COLUMN id SET DEFAULT nextval('vulnerability_user_mentions_id_seq'::regclass);
+
ALTER TABLE ONLY web_hook_logs ALTER COLUMN id SET DEFAULT nextval('web_hook_logs_id_seq'::regclass);
ALTER TABLE ONLY web_hooks ALTER COLUMN id SET DEFAULT nextval('web_hooks_id_seq'::regclass);
ALTER TABLE ONLY webauthn_registrations ALTER COLUMN id SET DEFAULT nextval('webauthn_registrations_id_seq'::regclass);
+ALTER TABLE ONLY wiki_page_meta ALTER COLUMN id SET DEFAULT nextval('wiki_page_meta_id_seq'::regclass);
+
+ALTER TABLE ONLY wiki_page_slugs ALTER COLUMN id SET DEFAULT nextval('wiki_page_slugs_id_seq'::regclass);
+
ALTER TABLE ONLY x509_certificates ALTER COLUMN id SET DEFAULT nextval('x509_certificates_id_seq'::regclass);
ALTER TABLE ONLY x509_commit_signatures ALTER COLUMN id SET DEFAULT nextval('x509_commit_signatures_id_seq'::regclass);
@@ -7163,9 +19318,216 @@ ALTER TABLE ONLY x509_issuers ALTER COLUMN id SET DEFAULT nextval('x509_issuers_
ALTER TABLE ONLY zoom_meetings ALTER COLUMN id SET DEFAULT nextval('zoom_meetings_id_seq'::regclass);
+ALTER TABLE ONLY product_analytics_events_experimental
+ ADD CONSTRAINT product_analytics_events_experimental_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_00
+ ADD CONSTRAINT product_analytics_events_experimental_00_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_01
+ ADD CONSTRAINT product_analytics_events_experimental_01_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_02
+ ADD CONSTRAINT product_analytics_events_experimental_02_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_03
+ ADD CONSTRAINT product_analytics_events_experimental_03_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_04
+ ADD CONSTRAINT product_analytics_events_experimental_04_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_05
+ ADD CONSTRAINT product_analytics_events_experimental_05_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_06
+ ADD CONSTRAINT product_analytics_events_experimental_06_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_07
+ ADD CONSTRAINT product_analytics_events_experimental_07_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_08
+ ADD CONSTRAINT product_analytics_events_experimental_08_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_09
+ ADD CONSTRAINT product_analytics_events_experimental_09_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_10
+ ADD CONSTRAINT product_analytics_events_experimental_10_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_11
+ ADD CONSTRAINT product_analytics_events_experimental_11_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_12
+ ADD CONSTRAINT product_analytics_events_experimental_12_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_13
+ ADD CONSTRAINT product_analytics_events_experimental_13_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_14
+ ADD CONSTRAINT product_analytics_events_experimental_14_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_15
+ ADD CONSTRAINT product_analytics_events_experimental_15_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_16
+ ADD CONSTRAINT product_analytics_events_experimental_16_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_17
+ ADD CONSTRAINT product_analytics_events_experimental_17_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_18
+ ADD CONSTRAINT product_analytics_events_experimental_18_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_19
+ ADD CONSTRAINT product_analytics_events_experimental_19_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_20
+ ADD CONSTRAINT product_analytics_events_experimental_20_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_21
+ ADD CONSTRAINT product_analytics_events_experimental_21_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_22
+ ADD CONSTRAINT product_analytics_events_experimental_22_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_23
+ ADD CONSTRAINT product_analytics_events_experimental_23_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_24
+ ADD CONSTRAINT product_analytics_events_experimental_24_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_25
+ ADD CONSTRAINT product_analytics_events_experimental_25_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_26
+ ADD CONSTRAINT product_analytics_events_experimental_26_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_27
+ ADD CONSTRAINT product_analytics_events_experimental_27_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_28
+ ADD CONSTRAINT product_analytics_events_experimental_28_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_29
+ ADD CONSTRAINT product_analytics_events_experimental_29_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_30
+ ADD CONSTRAINT product_analytics_events_experimental_30_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_31
+ ADD CONSTRAINT product_analytics_events_experimental_31_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_32
+ ADD CONSTRAINT product_analytics_events_experimental_32_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_33
+ ADD CONSTRAINT product_analytics_events_experimental_33_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_34
+ ADD CONSTRAINT product_analytics_events_experimental_34_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_35
+ ADD CONSTRAINT product_analytics_events_experimental_35_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_36
+ ADD CONSTRAINT product_analytics_events_experimental_36_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_37
+ ADD CONSTRAINT product_analytics_events_experimental_37_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_38
+ ADD CONSTRAINT product_analytics_events_experimental_38_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_39
+ ADD CONSTRAINT product_analytics_events_experimental_39_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_40
+ ADD CONSTRAINT product_analytics_events_experimental_40_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_41
+ ADD CONSTRAINT product_analytics_events_experimental_41_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_42
+ ADD CONSTRAINT product_analytics_events_experimental_42_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_43
+ ADD CONSTRAINT product_analytics_events_experimental_43_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_44
+ ADD CONSTRAINT product_analytics_events_experimental_44_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_45
+ ADD CONSTRAINT product_analytics_events_experimental_45_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_46
+ ADD CONSTRAINT product_analytics_events_experimental_46_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_47
+ ADD CONSTRAINT product_analytics_events_experimental_47_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_48
+ ADD CONSTRAINT product_analytics_events_experimental_48_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_49
+ ADD CONSTRAINT product_analytics_events_experimental_49_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_50
+ ADD CONSTRAINT product_analytics_events_experimental_50_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_51
+ ADD CONSTRAINT product_analytics_events_experimental_51_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_52
+ ADD CONSTRAINT product_analytics_events_experimental_52_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_53
+ ADD CONSTRAINT product_analytics_events_experimental_53_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_54
+ ADD CONSTRAINT product_analytics_events_experimental_54_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_55
+ ADD CONSTRAINT product_analytics_events_experimental_55_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_56
+ ADD CONSTRAINT product_analytics_events_experimental_56_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_57
+ ADD CONSTRAINT product_analytics_events_experimental_57_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_58
+ ADD CONSTRAINT product_analytics_events_experimental_58_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_59
+ ADD CONSTRAINT product_analytics_events_experimental_59_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_60
+ ADD CONSTRAINT product_analytics_events_experimental_60_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_61
+ ADD CONSTRAINT product_analytics_events_experimental_61_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_62
+ ADD CONSTRAINT product_analytics_events_experimental_62_pkey PRIMARY KEY (id, project_id);
+
+ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_63
+ ADD CONSTRAINT product_analytics_events_experimental_63_pkey PRIMARY KEY (id, project_id);
+
ALTER TABLE ONLY abuse_reports
ADD CONSTRAINT abuse_reports_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY alert_management_alert_assignees
+ ADD CONSTRAINT alert_management_alert_assignees_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY alert_management_alert_user_mentions
+ ADD CONSTRAINT alert_management_alert_user_mentions_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY alert_management_alerts
+ ADD CONSTRAINT alert_management_alerts_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY alert_management_http_integrations
+ ADD CONSTRAINT alert_management_http_integrations_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY alerts_service_data
ADD CONSTRAINT alerts_service_data_pkey PRIMARY KEY (id);
@@ -7175,17 +19537,26 @@ ALTER TABLE ONLY allowed_email_domains
ALTER TABLE ONLY analytics_cycle_analytics_group_stages
ADD CONSTRAINT analytics_cycle_analytics_group_stages_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY analytics_cycle_analytics_group_value_streams
+ ADD CONSTRAINT analytics_cycle_analytics_group_value_streams_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY analytics_cycle_analytics_project_stages
ADD CONSTRAINT analytics_cycle_analytics_project_stages_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY analytics_repository_file_commits
- ADD CONSTRAINT analytics_repository_file_commits_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY analytics_devops_adoption_segment_selections
+ ADD CONSTRAINT analytics_devops_adoption_segment_selections_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY analytics_repository_file_edits
- ADD CONSTRAINT analytics_repository_file_edits_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY analytics_devops_adoption_segments
+ ADD CONSTRAINT analytics_devops_adoption_segments_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY analytics_repository_files
- ADD CONSTRAINT analytics_repository_files_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY analytics_devops_adoption_snapshots
+ ADD CONSTRAINT analytics_devops_adoption_snapshots_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY analytics_instance_statistics_measurements
+ ADD CONSTRAINT analytics_instance_statistics_measurements_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY analytics_language_trend_repository_languages
+ ADD CONSTRAINT analytics_language_trend_repository_languages_pkey PRIMARY KEY (programming_language_id, project_id, snapshot_date);
ALTER TABLE ONLY appearances
ADD CONSTRAINT appearances_pkey PRIMARY KEY (id);
@@ -7217,6 +19588,9 @@ ALTER TABLE ONLY approval_project_rules_groups
ALTER TABLE ONLY approval_project_rules
ADD CONSTRAINT approval_project_rules_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY approval_project_rules_protected_branches
+ ADD CONSTRAINT approval_project_rules_protected_branches_pkey PRIMARY KEY (approval_project_rule_id, protected_branch_id);
+
ALTER TABLE ONLY approval_project_rules_users
ADD CONSTRAINT approval_project_rules_users_pkey PRIMARY KEY (id);
@@ -7229,8 +19603,17 @@ ALTER TABLE ONLY approver_groups
ALTER TABLE ONLY approvers
ADD CONSTRAINT approvers_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY atlassian_identities
+ ADD CONSTRAINT atlassian_identities_pkey PRIMARY KEY (user_id);
+
+ALTER TABLE ONLY audit_events_archived
+ ADD CONSTRAINT audit_events_archived_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY audit_events
- ADD CONSTRAINT audit_events_pkey PRIMARY KEY (id);
+ ADD CONSTRAINT audit_events_pkey PRIMARY KEY (id, created_at);
+
+ALTER TABLE ONLY authentication_events
+ ADD CONSTRAINT authentication_events_pkey PRIMARY KEY (id);
ALTER TABLE ONLY award_emoji
ADD CONSTRAINT award_emoji_pkey PRIMARY KEY (id);
@@ -7238,6 +19621,12 @@ ALTER TABLE ONLY award_emoji
ALTER TABLE ONLY aws_roles
ADD CONSTRAINT aws_roles_pkey PRIMARY KEY (user_id);
+ALTER TABLE ONLY background_migration_jobs
+ ADD CONSTRAINT background_migration_jobs_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY backup_labels
+ ADD CONSTRAINT backup_labels_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY badges
ADD CONSTRAINT badges_pkey PRIMARY KEY (id);
@@ -7253,27 +19642,72 @@ ALTER TABLE ONLY board_labels
ALTER TABLE ONLY board_project_recent_visits
ADD CONSTRAINT board_project_recent_visits_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY board_user_preferences
+ ADD CONSTRAINT board_user_preferences_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY boards_epic_board_labels
+ ADD CONSTRAINT boards_epic_board_labels_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY boards_epic_board_positions
+ ADD CONSTRAINT boards_epic_board_positions_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY boards_epic_boards
+ ADD CONSTRAINT boards_epic_boards_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY boards_epic_user_preferences
+ ADD CONSTRAINT boards_epic_user_preferences_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY boards
ADD CONSTRAINT boards_pkey PRIMARY KEY (id);
ALTER TABLE ONLY broadcast_messages
ADD CONSTRAINT broadcast_messages_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY bulk_import_configurations
+ ADD CONSTRAINT bulk_import_configurations_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY bulk_import_entities
+ ADD CONSTRAINT bulk_import_entities_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY bulk_import_failures
+ ADD CONSTRAINT bulk_import_failures_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY bulk_import_trackers
+ ADD CONSTRAINT bulk_import_trackers_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY bulk_imports
+ ADD CONSTRAINT bulk_imports_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY chat_names
ADD CONSTRAINT chat_names_pkey PRIMARY KEY (id);
ALTER TABLE ONLY chat_teams
ADD CONSTRAINT chat_teams_pkey PRIMARY KEY (id);
+ALTER TABLE vulnerability_scanners
+ ADD CONSTRAINT check_37608c9db5 CHECK ((char_length(vendor) <= 255)) NOT VALID;
+
+ALTER TABLE group_import_states
+ ADD CONSTRAINT check_cda75c7c3f CHECK ((user_id IS NOT NULL)) NOT VALID;
+
ALTER TABLE ONLY ci_build_needs
ADD CONSTRAINT ci_build_needs_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_build_pending_states
+ ADD CONSTRAINT ci_build_pending_states_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY ci_build_report_results
+ ADD CONSTRAINT ci_build_report_results_pkey PRIMARY KEY (build_id);
+
ALTER TABLE ONLY ci_build_trace_chunks
ADD CONSTRAINT ci_build_trace_chunks_pkey PRIMARY KEY (id);
ALTER TABLE ONLY ci_build_trace_section_names
ADD CONSTRAINT ci_build_trace_section_names_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_build_trace_sections
+ ADD CONSTRAINT ci_build_trace_sections_pkey PRIMARY KEY (build_id, section_name_id);
+
ALTER TABLE ONLY ci_builds_metadata
ADD CONSTRAINT ci_builds_metadata_pkey PRIMARY KEY (id);
@@ -7283,18 +19717,36 @@ ALTER TABLE ONLY ci_builds
ALTER TABLE ONLY ci_builds_runner_session
ADD CONSTRAINT ci_builds_runner_session_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_daily_build_group_report_results
+ ADD CONSTRAINT ci_daily_build_group_report_results_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY ci_deleted_objects
+ ADD CONSTRAINT ci_deleted_objects_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY ci_freeze_periods
+ ADD CONSTRAINT ci_freeze_periods_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_group_variables
ADD CONSTRAINT ci_group_variables_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_instance_variables
+ ADD CONSTRAINT ci_instance_variables_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_job_artifacts
ADD CONSTRAINT ci_job_artifacts_pkey PRIMARY KEY (id);
ALTER TABLE ONLY ci_job_variables
ADD CONSTRAINT ci_job_variables_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_pipeline_artifacts
+ ADD CONSTRAINT ci_pipeline_artifacts_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_pipeline_chat_data
ADD CONSTRAINT ci_pipeline_chat_data_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_pipeline_messages
+ ADD CONSTRAINT ci_pipeline_messages_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_pipeline_schedule_variables
ADD CONSTRAINT ci_pipeline_schedule_variables_pkey PRIMARY KEY (id);
@@ -7310,6 +19762,9 @@ ALTER TABLE ONLY ci_pipelines_config
ALTER TABLE ONLY ci_pipelines
ADD CONSTRAINT ci_pipelines_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_platform_metrics
+ ADD CONSTRAINT ci_platform_metrics_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_refs
ADD CONSTRAINT ci_refs_pkey PRIMARY KEY (id);
@@ -7331,12 +19786,21 @@ ALTER TABLE ONLY ci_runners
ALTER TABLE ONLY ci_sources_pipelines
ADD CONSTRAINT ci_sources_pipelines_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_sources_projects
+ ADD CONSTRAINT ci_sources_projects_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_stages
ADD CONSTRAINT ci_stages_pkey PRIMARY KEY (id);
ALTER TABLE ONLY ci_subscriptions_projects
ADD CONSTRAINT ci_subscriptions_projects_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_test_case_failures
+ ADD CONSTRAINT ci_test_case_failures_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY ci_test_cases
+ ADD CONSTRAINT ci_test_cases_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_trigger_requests
ADD CONSTRAINT ci_trigger_requests_pkey PRIMARY KEY (id);
@@ -7346,6 +19810,12 @@ ALTER TABLE ONLY ci_triggers
ALTER TABLE ONLY ci_variables
ADD CONSTRAINT ci_variables_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY cluster_agent_tokens
+ ADD CONSTRAINT cluster_agent_tokens_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY cluster_agents
+ ADD CONSTRAINT cluster_agents_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY cluster_groups
ADD CONSTRAINT cluster_groups_pkey PRIMARY KEY (id);
@@ -7364,12 +19834,18 @@ ALTER TABLE ONLY cluster_providers_gcp
ALTER TABLE ONLY clusters_applications_cert_managers
ADD CONSTRAINT clusters_applications_cert_managers_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY clusters_applications_cilium
+ ADD CONSTRAINT clusters_applications_cilium_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY clusters_applications_crossplane
ADD CONSTRAINT clusters_applications_crossplane_pkey PRIMARY KEY (id);
ALTER TABLE ONLY clusters_applications_elastic_stacks
ADD CONSTRAINT clusters_applications_elastic_stacks_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY clusters_applications_fluentd
+ ADD CONSTRAINT clusters_applications_fluentd_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY clusters_applications_helm
ADD CONSTRAINT clusters_applications_helm_pkey PRIMARY KEY (id);
@@ -7397,6 +19873,9 @@ ALTER TABLE ONLY clusters
ALTER TABLE ONLY commit_user_mentions
ADD CONSTRAINT commit_user_mentions_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY compliance_management_frameworks
+ ADD CONSTRAINT compliance_management_frameworks_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY container_expiration_policies
ADD CONSTRAINT container_expiration_policies_pkey PRIMARY KEY (project_id);
@@ -7406,18 +19885,48 @@ ALTER TABLE ONLY container_repositories
ALTER TABLE ONLY conversational_development_index_metrics
ADD CONSTRAINT conversational_development_index_metrics_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY csv_issue_imports
+ ADD CONSTRAINT csv_issue_imports_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY custom_emoji
+ ADD CONSTRAINT custom_emoji_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY dast_scanner_profiles
+ ADD CONSTRAINT dast_scanner_profiles_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY dast_site_profiles
+ ADD CONSTRAINT dast_site_profiles_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY dast_site_tokens
+ ADD CONSTRAINT dast_site_tokens_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY dast_site_validations
+ ADD CONSTRAINT dast_site_validations_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY dast_sites
+ ADD CONSTRAINT dast_sites_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY dependency_proxy_blobs
ADD CONSTRAINT dependency_proxy_blobs_pkey PRIMARY KEY (id);
ALTER TABLE ONLY dependency_proxy_group_settings
ADD CONSTRAINT dependency_proxy_group_settings_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY dependency_proxy_manifests
+ ADD CONSTRAINT dependency_proxy_manifests_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY deploy_keys_projects
ADD CONSTRAINT deploy_keys_projects_pkey PRIMARY KEY (id);
ALTER TABLE ONLY deploy_tokens
ADD CONSTRAINT deploy_tokens_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY deployment_clusters
+ ADD CONSTRAINT deployment_clusters_pkey PRIMARY KEY (deployment_id);
+
+ALTER TABLE ONLY deployment_merge_requests
+ ADD CONSTRAINT deployment_merge_requests_pkey PRIMARY KEY (deployment_id, merge_request_id);
+
ALTER TABLE ONLY deployments
ADD CONSTRAINT deployments_pkey PRIMARY KEY (id);
@@ -7427,15 +19936,30 @@ ALTER TABLE ONLY description_versions
ALTER TABLE ONLY design_management_designs
ADD CONSTRAINT design_management_designs_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY design_management_designs_versions
+ ADD CONSTRAINT design_management_designs_versions_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY design_management_versions
ADD CONSTRAINT design_management_versions_pkey PRIMARY KEY (id);
ALTER TABLE ONLY design_user_mentions
ADD CONSTRAINT design_user_mentions_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY diff_note_positions
+ ADD CONSTRAINT diff_note_positions_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY draft_notes
ADD CONSTRAINT draft_notes_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY elastic_reindexing_tasks
+ ADD CONSTRAINT elastic_reindexing_tasks_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY elasticsearch_indexed_namespaces
+ ADD CONSTRAINT elasticsearch_indexed_namespaces_pkey PRIMARY KEY (namespace_id);
+
+ALTER TABLE ONLY elasticsearch_indexed_projects
+ ADD CONSTRAINT elasticsearch_indexed_projects_pkey PRIMARY KEY (project_id);
+
ALTER TABLE ONLY emails
ADD CONSTRAINT emails_pkey PRIMARY KEY (id);
@@ -7460,6 +19984,15 @@ ALTER TABLE ONLY events
ALTER TABLE ONLY evidences
ADD CONSTRAINT evidences_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY experiment_subjects
+ ADD CONSTRAINT experiment_subjects_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY experiment_users
+ ADD CONSTRAINT experiment_users_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY experiments
+ ADD CONSTRAINT experiments_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY external_pull_requests
ADD CONSTRAINT external_pull_requests_pkey PRIMARY KEY (id);
@@ -7475,9 +20008,6 @@ ALTER TABLE ONLY fork_network_members
ALTER TABLE ONLY fork_networks
ADD CONSTRAINT fork_networks_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY forked_project_links
- ADD CONSTRAINT forked_project_links_pkey PRIMARY KEY (id);
-
ALTER TABLE ONLY geo_cache_invalidation_events
ADD CONSTRAINT geo_cache_invalidation_events_pkey PRIMARY KEY (id);
@@ -7487,6 +20017,9 @@ ALTER TABLE ONLY geo_container_repository_updated_events
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT geo_event_log_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY geo_events
+ ADD CONSTRAINT geo_events_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY geo_hashed_storage_attachments_events
ADD CONSTRAINT geo_hashed_storage_attachments_events_pkey PRIMARY KEY (id);
@@ -7553,9 +20086,24 @@ ALTER TABLE ONLY group_custom_attributes
ALTER TABLE ONLY group_deletion_schedules
ADD CONSTRAINT group_deletion_schedules_pkey PRIMARY KEY (group_id);
+ALTER TABLE ONLY group_deploy_keys_groups
+ ADD CONSTRAINT group_deploy_keys_groups_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY group_deploy_keys
+ ADD CONSTRAINT group_deploy_keys_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY group_deploy_tokens
+ ADD CONSTRAINT group_deploy_tokens_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY group_group_links
ADD CONSTRAINT group_group_links_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY group_import_states
+ ADD CONSTRAINT group_import_states_pkey PRIMARY KEY (group_id);
+
+ALTER TABLE ONLY group_wiki_repositories
+ ADD CONSTRAINT group_wiki_repositories_pkey PRIMARY KEY (group_id);
+
ALTER TABLE ONLY historical_data
ADD CONSTRAINT historical_data_pkey PRIMARY KEY (id);
@@ -7568,6 +20116,21 @@ ALTER TABLE ONLY import_export_uploads
ALTER TABLE ONLY import_failures
ADD CONSTRAINT import_failures_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY incident_management_oncall_shifts
+ ADD CONSTRAINT inc_mgmnt_no_overlapping_oncall_shifts EXCLUDE USING gist (rotation_id WITH =, tstzrange(starts_at, ends_at, '[)'::text) WITH &&);
+
+ALTER TABLE ONLY incident_management_oncall_participants
+ ADD CONSTRAINT incident_management_oncall_participants_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY incident_management_oncall_rotations
+ ADD CONSTRAINT incident_management_oncall_rotations_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY incident_management_oncall_schedules
+ ADD CONSTRAINT incident_management_oncall_schedules_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY incident_management_oncall_shifts
+ ADD CONSTRAINT incident_management_oncall_shifts_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY index_statuses
ADD CONSTRAINT index_statuses_pkey PRIMARY KEY (id);
@@ -7580,6 +20143,21 @@ ALTER TABLE ONLY internal_ids
ALTER TABLE ONLY ip_restrictions
ADD CONSTRAINT ip_restrictions_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY issuable_metric_images
+ ADD CONSTRAINT issuable_metric_images_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY issuable_severities
+ ADD CONSTRAINT issuable_severities_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY issuable_slas
+ ADD CONSTRAINT issuable_slas_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY issue_assignees
+ ADD CONSTRAINT issue_assignees_pkey PRIMARY KEY (issue_id, user_id);
+
+ALTER TABLE ONLY issue_email_participants
+ ADD CONSTRAINT issue_email_participants_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY issue_links
ADD CONSTRAINT issue_links_pkey PRIMARY KEY (id);
@@ -7595,12 +20173,27 @@ ALTER TABLE ONLY issue_user_mentions
ALTER TABLE ONLY issues
ADD CONSTRAINT issues_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY issues_prometheus_alert_events
+ ADD CONSTRAINT issues_prometheus_alert_events_pkey PRIMARY KEY (issue_id, prometheus_alert_event_id);
+
+ALTER TABLE ONLY issues_self_managed_prometheus_alert_events
+ ADD CONSTRAINT issues_self_managed_prometheus_alert_events_pkey PRIMARY KEY (issue_id, self_managed_prometheus_alert_event_id);
+
+ALTER TABLE ONLY sprints
+ ADD CONSTRAINT iteration_start_and_due_daterange_group_id_constraint EXCLUDE USING gist (group_id WITH =, daterange(start_date, due_date, '[]'::text) WITH &&) WHERE ((group_id IS NOT NULL));
+
+ALTER TABLE ONLY sprints
+ ADD CONSTRAINT iteration_start_and_due_daterange_project_id_constraint EXCLUDE USING gist (project_id WITH =, daterange(start_date, due_date, '[]'::text) WITH &&) WHERE ((project_id IS NOT NULL));
+
ALTER TABLE ONLY jira_connect_installations
ADD CONSTRAINT jira_connect_installations_pkey PRIMARY KEY (id);
ALTER TABLE ONLY jira_connect_subscriptions
ADD CONSTRAINT jira_connect_subscriptions_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY jira_imports
+ ADD CONSTRAINT jira_imports_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY jira_tracker_data
ADD CONSTRAINT jira_tracker_data_pkey PRIMARY KEY (id);
@@ -7646,15 +20239,33 @@ ALTER TABLE ONLY merge_request_assignees
ALTER TABLE ONLY merge_request_blocks
ADD CONSTRAINT merge_request_blocks_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY merge_request_cleanup_schedules
+ ADD CONSTRAINT merge_request_cleanup_schedules_pkey PRIMARY KEY (merge_request_id);
+
+ALTER TABLE ONLY merge_request_context_commit_diff_files
+ ADD CONSTRAINT merge_request_context_commit_diff_files_pkey PRIMARY KEY (merge_request_context_commit_id, relative_order);
+
ALTER TABLE ONLY merge_request_context_commits
ADD CONSTRAINT merge_request_context_commits_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY merge_request_diff_commits
+ ADD CONSTRAINT merge_request_diff_commits_pkey PRIMARY KEY (merge_request_diff_id, relative_order);
+
+ALTER TABLE ONLY merge_request_diff_details
+ ADD CONSTRAINT merge_request_diff_details_pkey PRIMARY KEY (merge_request_diff_id);
+
+ALTER TABLE ONLY merge_request_diff_files
+ ADD CONSTRAINT merge_request_diff_files_pkey PRIMARY KEY (merge_request_diff_id, relative_order);
+
ALTER TABLE ONLY merge_request_diffs
ADD CONSTRAINT merge_request_diffs_pkey PRIMARY KEY (id);
ALTER TABLE ONLY merge_request_metrics
ADD CONSTRAINT merge_request_metrics_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY merge_request_reviewers
+ ADD CONSTRAINT merge_request_reviewers_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY merge_request_user_mentions
ADD CONSTRAINT merge_request_user_mentions_pkey PRIMARY KEY (id);
@@ -7667,15 +20278,33 @@ ALTER TABLE ONLY merge_requests
ALTER TABLE ONLY merge_trains
ADD CONSTRAINT merge_trains_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY metrics_dashboard_annotations
+ ADD CONSTRAINT metrics_dashboard_annotations_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY metrics_users_starred_dashboards
+ ADD CONSTRAINT metrics_users_starred_dashboards_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY milestone_releases
+ ADD CONSTRAINT milestone_releases_pkey PRIMARY KEY (milestone_id, release_id);
+
ALTER TABLE ONLY milestones
ADD CONSTRAINT milestones_pkey PRIMARY KEY (id);
ALTER TABLE ONLY namespace_aggregation_schedules
ADD CONSTRAINT namespace_aggregation_schedules_pkey PRIMARY KEY (namespace_id);
+ALTER TABLE ONLY namespace_limits
+ ADD CONSTRAINT namespace_limits_pkey PRIMARY KEY (namespace_id);
+
+ALTER TABLE ONLY namespace_onboarding_actions
+ ADD CONSTRAINT namespace_onboarding_actions_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY namespace_root_storage_statistics
ADD CONSTRAINT namespace_root_storage_statistics_pkey PRIMARY KEY (namespace_id);
+ALTER TABLE ONLY namespace_settings
+ ADD CONSTRAINT namespace_settings_pkey PRIMARY KEY (namespace_id);
+
ALTER TABLE ONLY namespace_statistics
ADD CONSTRAINT namespace_statistics_pkey PRIMARY KEY (id);
@@ -7703,48 +20332,120 @@ ALTER TABLE ONLY oauth_applications
ALTER TABLE ONLY oauth_openid_requests
ADD CONSTRAINT oauth_openid_requests_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY open_project_tracker_data
+ ADD CONSTRAINT open_project_tracker_data_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY operations_feature_flag_scopes
ADD CONSTRAINT operations_feature_flag_scopes_pkey PRIMARY KEY (id);
ALTER TABLE ONLY operations_feature_flags_clients
ADD CONSTRAINT operations_feature_flags_clients_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY operations_feature_flags_issues
+ ADD CONSTRAINT operations_feature_flags_issues_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY operations_feature_flags
ADD CONSTRAINT operations_feature_flags_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY operations_scopes
+ ADD CONSTRAINT operations_scopes_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY operations_strategies
+ ADD CONSTRAINT operations_strategies_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY operations_strategies_user_lists
+ ADD CONSTRAINT operations_strategies_user_lists_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY operations_user_lists
+ ADD CONSTRAINT operations_user_lists_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_build_infos
ADD CONSTRAINT packages_build_infos_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_composer_metadata
+ ADD CONSTRAINT packages_composer_metadata_pkey PRIMARY KEY (package_id);
+
ALTER TABLE ONLY packages_conan_file_metadata
ADD CONSTRAINT packages_conan_file_metadata_pkey PRIMARY KEY (id);
ALTER TABLE ONLY packages_conan_metadata
ADD CONSTRAINT packages_conan_metadata_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_debian_file_metadata
+ ADD CONSTRAINT packages_debian_file_metadata_pkey PRIMARY KEY (package_file_id);
+
+ALTER TABLE ONLY packages_debian_group_architectures
+ ADD CONSTRAINT packages_debian_group_architectures_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY packages_debian_group_component_files
+ ADD CONSTRAINT packages_debian_group_component_files_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY packages_debian_group_components
+ ADD CONSTRAINT packages_debian_group_components_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY packages_debian_group_distributions
+ ADD CONSTRAINT packages_debian_group_distributions_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY packages_debian_project_architectures
+ ADD CONSTRAINT packages_debian_project_architectures_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY packages_debian_project_component_files
+ ADD CONSTRAINT packages_debian_project_component_files_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY packages_debian_project_components
+ ADD CONSTRAINT packages_debian_project_components_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY packages_debian_project_distributions
+ ADD CONSTRAINT packages_debian_project_distributions_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY packages_debian_publications
+ ADD CONSTRAINT packages_debian_publications_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_dependencies
ADD CONSTRAINT packages_dependencies_pkey PRIMARY KEY (id);
ALTER TABLE ONLY packages_dependency_links
ADD CONSTRAINT packages_dependency_links_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_events
+ ADD CONSTRAINT packages_events_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_maven_metadata
ADD CONSTRAINT packages_maven_metadata_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_nuget_dependency_link_metadata
+ ADD CONSTRAINT packages_nuget_dependency_link_metadata_pkey PRIMARY KEY (dependency_link_id);
+
+ALTER TABLE ONLY packages_nuget_metadata
+ ADD CONSTRAINT packages_nuget_metadata_pkey PRIMARY KEY (package_id);
+
+ALTER TABLE ONLY packages_package_file_build_infos
+ ADD CONSTRAINT packages_package_file_build_infos_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_package_files
ADD CONSTRAINT packages_package_files_pkey PRIMARY KEY (id);
ALTER TABLE ONLY packages_packages
ADD CONSTRAINT packages_packages_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_pypi_metadata
+ ADD CONSTRAINT packages_pypi_metadata_pkey PRIMARY KEY (package_id);
+
ALTER TABLE ONLY packages_tags
ADD CONSTRAINT packages_tags_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY pages_deployments
+ ADD CONSTRAINT pages_deployments_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY pages_domain_acme_orders
ADD CONSTRAINT pages_domain_acme_orders_pkey PRIMARY KEY (id);
ALTER TABLE ONLY pages_domains
ADD CONSTRAINT pages_domains_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY partitioned_foreign_keys
+ ADD CONSTRAINT partitioned_foreign_keys_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY path_locks
ADD CONSTRAINT path_locks_pkey PRIMARY KEY (id);
@@ -7760,21 +20461,33 @@ ALTER TABLE ONLY plans
ALTER TABLE ONLY pool_repositories
ADD CONSTRAINT pool_repositories_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY postgres_reindex_actions
+ ADD CONSTRAINT postgres_reindex_actions_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY programming_languages
ADD CONSTRAINT programming_languages_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY project_access_tokens
+ ADD CONSTRAINT project_access_tokens_pkey PRIMARY KEY (personal_access_token_id, project_id);
+
ALTER TABLE ONLY project_alerting_settings
ADD CONSTRAINT project_alerting_settings_pkey PRIMARY KEY (project_id);
ALTER TABLE ONLY project_aliases
ADD CONSTRAINT project_aliases_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY project_authorizations
+ ADD CONSTRAINT project_authorizations_pkey PRIMARY KEY (user_id, project_id, access_level);
+
ALTER TABLE ONLY project_auto_devops
ADD CONSTRAINT project_auto_devops_pkey PRIMARY KEY (id);
ALTER TABLE ONLY project_ci_cd_settings
ADD CONSTRAINT project_ci_cd_settings_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY project_compliance_framework_settings
+ ADD CONSTRAINT project_compliance_framework_settings_pkey PRIMARY KEY (project_id);
+
ALTER TABLE ONLY project_custom_attributes
ADD CONSTRAINT project_custom_attributes_pkey PRIMARY KEY (id);
@@ -7787,6 +20500,9 @@ ALTER TABLE ONLY project_deploy_tokens
ALTER TABLE ONLY project_error_tracking_settings
ADD CONSTRAINT project_error_tracking_settings_pkey PRIMARY KEY (project_id);
+ALTER TABLE ONLY project_export_jobs
+ ADD CONSTRAINT project_export_jobs_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY project_feature_usages
ADD CONSTRAINT project_feature_usages_pkey PRIMARY KEY (project_id);
@@ -7808,12 +20524,21 @@ ALTER TABLE ONLY project_metrics_settings
ALTER TABLE ONLY project_mirror_data
ADD CONSTRAINT project_mirror_data_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY project_pages_metadata
+ ADD CONSTRAINT project_pages_metadata_pkey PRIMARY KEY (project_id);
+
ALTER TABLE ONLY project_repositories
ADD CONSTRAINT project_repositories_pkey PRIMARY KEY (id);
ALTER TABLE ONLY project_repository_states
ADD CONSTRAINT project_repository_states_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY project_repository_storage_moves
+ ADD CONSTRAINT project_repository_storage_moves_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY project_security_settings
+ ADD CONSTRAINT project_security_settings_pkey PRIMARY KEY (project_id);
+
ALTER TABLE ONLY project_settings
ADD CONSTRAINT project_settings_pkey PRIMARY KEY (project_id);
@@ -7859,9 +20584,15 @@ ALTER TABLE ONLY protected_tag_create_access_levels
ALTER TABLE ONLY protected_tags
ADD CONSTRAINT protected_tags_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY push_event_payloads
+ ADD CONSTRAINT push_event_payloads_pkey PRIMARY KEY (event_id);
+
ALTER TABLE ONLY push_rules
ADD CONSTRAINT push_rules_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY raw_usage_data
+ ADD CONSTRAINT raw_usage_data_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY redirect_routes
ADD CONSTRAINT redirect_routes_pkey PRIMARY KEY (id);
@@ -7874,9 +20605,30 @@ ALTER TABLE ONLY releases
ALTER TABLE ONLY remote_mirrors
ADD CONSTRAINT remote_mirrors_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY repository_languages
+ ADD CONSTRAINT repository_languages_pkey PRIMARY KEY (project_id, programming_language_id);
+
+ALTER TABLE ONLY required_code_owners_sections
+ ADD CONSTRAINT required_code_owners_sections_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY requirements_management_test_reports
+ ADD CONSTRAINT requirements_management_test_reports_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY requirements
+ ADD CONSTRAINT requirements_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY resource_iteration_events
+ ADD CONSTRAINT resource_iteration_events_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY resource_label_events
ADD CONSTRAINT resource_label_events_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY resource_milestone_events
+ ADD CONSTRAINT resource_milestone_events_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY resource_state_events
+ ADD CONSTRAINT resource_state_events_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY resource_weight_events
ADD CONSTRAINT resource_weight_events_pkey PRIMARY KEY (id);
@@ -7886,12 +20638,24 @@ ALTER TABLE ONLY reviews
ALTER TABLE ONLY routes
ADD CONSTRAINT routes_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY saml_group_links
+ ADD CONSTRAINT saml_group_links_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY saml_providers
ADD CONSTRAINT saml_providers_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY scim_identities
+ ADD CONSTRAINT scim_identities_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY scim_oauth_access_tokens
ADD CONSTRAINT scim_oauth_access_tokens_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY security_findings
+ ADD CONSTRAINT security_findings_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY security_scans
+ ADD CONSTRAINT security_scans_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY self_managed_prometheus_alert_events
ADD CONSTRAINT self_managed_prometheus_alert_events_pkey PRIMARY KEY (id);
@@ -7919,6 +20683,15 @@ ALTER TABLE ONLY slack_integrations
ALTER TABLE ONLY smartcard_identities
ADD CONSTRAINT smartcard_identities_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY snippet_repositories
+ ADD CONSTRAINT snippet_repositories_pkey PRIMARY KEY (snippet_id);
+
+ALTER TABLE ONLY snippet_repository_storage_moves
+ ADD CONSTRAINT snippet_repository_storage_moves_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY snippet_statistics
+ ADD CONSTRAINT snippet_statistics_pkey PRIMARY KEY (snippet_id);
+
ALTER TABLE ONLY snippet_user_mentions
ADD CONSTRAINT snippet_user_mentions_pkey PRIMARY KEY (id);
@@ -7934,6 +20707,15 @@ ALTER TABLE ONLY software_licenses
ALTER TABLE ONLY spam_logs
ADD CONSTRAINT spam_logs_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY sprints
+ ADD CONSTRAINT sprints_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY status_page_published_incidents
+ ADD CONSTRAINT status_page_published_incidents_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY status_page_settings
+ ADD CONSTRAINT status_page_settings_pkey PRIMARY KEY (project_id);
+
ALTER TABLE ONLY subscriptions
ADD CONSTRAINT subscriptions_pkey PRIMARY KEY (id);
@@ -7952,12 +20734,21 @@ ALTER TABLE ONLY tags
ALTER TABLE ONLY term_agreements
ADD CONSTRAINT term_agreements_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY terraform_state_versions
+ ADD CONSTRAINT terraform_state_versions_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY terraform_states
+ ADD CONSTRAINT terraform_states_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY timelogs
ADD CONSTRAINT timelogs_pkey PRIMARY KEY (id);
ALTER TABLE ONLY todos
ADD CONSTRAINT todos_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY token_with_ivs
+ ADD CONSTRAINT token_with_ivs_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY trending_projects
ADD CONSTRAINT trending_projects_pkey PRIMARY KEY (id);
@@ -7973,9 +20764,27 @@ ALTER TABLE ONLY user_agent_details
ALTER TABLE ONLY user_callouts
ADD CONSTRAINT user_callouts_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY user_canonical_emails
+ ADD CONSTRAINT user_canonical_emails_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY user_custom_attributes
ADD CONSTRAINT user_custom_attributes_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY user_details
+ ADD CONSTRAINT user_details_pkey PRIMARY KEY (user_id);
+
+ALTER TABLE ONLY user_follow_users
+ ADD CONSTRAINT user_follow_users_pkey PRIMARY KEY (follower_id, followee_id);
+
+ALTER TABLE ONLY user_highest_roles
+ ADD CONSTRAINT user_highest_roles_pkey PRIMARY KEY (user_id);
+
+ALTER TABLE ONLY user_interacted_projects
+ ADD CONSTRAINT user_interacted_projects_pkey PRIMARY KEY (project_id, user_id);
+
+ALTER TABLE ONLY user_permission_export_uploads
+ ADD CONSTRAINT user_permission_export_uploads_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY user_preferences
ADD CONSTRAINT user_preferences_pkey PRIMARY KEY (id);
@@ -7991,15 +20800,39 @@ ALTER TABLE ONLY users_ops_dashboard_projects
ALTER TABLE ONLY users
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY users_security_dashboard_projects
+ ADD CONSTRAINT users_security_dashboard_projects_pkey PRIMARY KEY (project_id, user_id);
+
ALTER TABLE ONLY users_star_projects
ADD CONSTRAINT users_star_projects_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY users_statistics
+ ADD CONSTRAINT users_statistics_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT vulnerabilities_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY vulnerability_exports
+ ADD CONSTRAINT vulnerability_exports_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY vulnerability_external_issue_links
+ ADD CONSTRAINT vulnerability_external_issue_links_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT vulnerability_feedback_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY vulnerability_finding_fingerprints
+ ADD CONSTRAINT vulnerability_finding_fingerprints_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY vulnerability_finding_links
+ ADD CONSTRAINT vulnerability_finding_links_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY vulnerability_findings_remediations
+ ADD CONSTRAINT vulnerability_findings_remediations_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY vulnerability_historical_statistics
+ ADD CONSTRAINT vulnerability_historical_statistics_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY vulnerability_identifiers
ADD CONSTRAINT vulnerability_identifiers_pkey PRIMARY KEY (id);
@@ -8015,9 +20848,18 @@ ALTER TABLE ONLY vulnerability_occurrence_pipelines
ALTER TABLE ONLY vulnerability_occurrences
ADD CONSTRAINT vulnerability_occurrences_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY vulnerability_remediations
+ ADD CONSTRAINT vulnerability_remediations_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY vulnerability_scanners
ADD CONSTRAINT vulnerability_scanners_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY vulnerability_statistics
+ ADD CONSTRAINT vulnerability_statistics_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY vulnerability_user_mentions
+ ADD CONSTRAINT vulnerability_user_mentions_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY web_hook_logs
ADD CONSTRAINT web_hook_logs_pkey PRIMARY KEY (id);
@@ -8027,6 +20869,12 @@ ALTER TABLE ONLY web_hooks
ALTER TABLE ONLY webauthn_registrations
ADD CONSTRAINT webauthn_registrations_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY wiki_page_meta
+ ADD CONSTRAINT wiki_page_meta_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY wiki_page_slugs
+ ADD CONSTRAINT wiki_page_slugs_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY x509_certificates
ADD CONSTRAINT x509_certificates_pkey PRIMARY KEY (id);
@@ -8039,19 +20887,167 @@ ALTER TABLE ONLY x509_issuers
ALTER TABLE ONLY zoom_meetings
ADD CONSTRAINT zoom_meetings_pkey PRIMARY KEY (id);
-CREATE INDEX analytics_index_audit_events_on_created_at_and_author_id ON audit_events USING btree (created_at, author_id);
+CREATE INDEX index_product_analytics_events_experimental_project_and_time ON ONLY product_analytics_events_experimental USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx10 ON gitlab_partitions_static.product_analytics_events_experimental_10 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx11 ON gitlab_partitions_static.product_analytics_events_experimental_11 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx12 ON gitlab_partitions_static.product_analytics_events_experimental_12 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx13 ON gitlab_partitions_static.product_analytics_events_experimental_13 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx14 ON gitlab_partitions_static.product_analytics_events_experimental_14 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx15 ON gitlab_partitions_static.product_analytics_events_experimental_15 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx16 ON gitlab_partitions_static.product_analytics_events_experimental_16 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx17 ON gitlab_partitions_static.product_analytics_events_experimental_17 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx18 ON gitlab_partitions_static.product_analytics_events_experimental_18 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx19 ON gitlab_partitions_static.product_analytics_events_experimental_19 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx20 ON gitlab_partitions_static.product_analytics_events_experimental_20 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx21 ON gitlab_partitions_static.product_analytics_events_experimental_21 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx22 ON gitlab_partitions_static.product_analytics_events_experimental_22 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx23 ON gitlab_partitions_static.product_analytics_events_experimental_23 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx24 ON gitlab_partitions_static.product_analytics_events_experimental_24 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx25 ON gitlab_partitions_static.product_analytics_events_experimental_25 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx26 ON gitlab_partitions_static.product_analytics_events_experimental_26 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx27 ON gitlab_partitions_static.product_analytics_events_experimental_27 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx28 ON gitlab_partitions_static.product_analytics_events_experimental_28 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx29 ON gitlab_partitions_static.product_analytics_events_experimental_29 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx30 ON gitlab_partitions_static.product_analytics_events_experimental_30 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx31 ON gitlab_partitions_static.product_analytics_events_experimental_31 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx32 ON gitlab_partitions_static.product_analytics_events_experimental_32 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx33 ON gitlab_partitions_static.product_analytics_events_experimental_33 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx34 ON gitlab_partitions_static.product_analytics_events_experimental_34 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx35 ON gitlab_partitions_static.product_analytics_events_experimental_35 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx36 ON gitlab_partitions_static.product_analytics_events_experimental_36 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx37 ON gitlab_partitions_static.product_analytics_events_experimental_37 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx38 ON gitlab_partitions_static.product_analytics_events_experimental_38 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx39 ON gitlab_partitions_static.product_analytics_events_experimental_39 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx40 ON gitlab_partitions_static.product_analytics_events_experimental_40 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx41 ON gitlab_partitions_static.product_analytics_events_experimental_41 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx42 ON gitlab_partitions_static.product_analytics_events_experimental_42 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx43 ON gitlab_partitions_static.product_analytics_events_experimental_43 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx44 ON gitlab_partitions_static.product_analytics_events_experimental_44 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx45 ON gitlab_partitions_static.product_analytics_events_experimental_45 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx46 ON gitlab_partitions_static.product_analytics_events_experimental_46 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx47 ON gitlab_partitions_static.product_analytics_events_experimental_47 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx48 ON gitlab_partitions_static.product_analytics_events_experimental_48 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx49 ON gitlab_partitions_static.product_analytics_events_experimental_49 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx50 ON gitlab_partitions_static.product_analytics_events_experimental_50 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx51 ON gitlab_partitions_static.product_analytics_events_experimental_51 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx52 ON gitlab_partitions_static.product_analytics_events_experimental_52 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx53 ON gitlab_partitions_static.product_analytics_events_experimental_53 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx54 ON gitlab_partitions_static.product_analytics_events_experimental_54 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx55 ON gitlab_partitions_static.product_analytics_events_experimental_55 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx56 ON gitlab_partitions_static.product_analytics_events_experimental_56 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx57 ON gitlab_partitions_static.product_analytics_events_experimental_57 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx58 ON gitlab_partitions_static.product_analytics_events_experimental_58 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx59 ON gitlab_partitions_static.product_analytics_events_experimental_59 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx60 ON gitlab_partitions_static.product_analytics_events_experimental_60 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx61 ON gitlab_partitions_static.product_analytics_events_experimental_61 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx62 ON gitlab_partitions_static.product_analytics_events_experimental_62 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx63 ON gitlab_partitions_static.product_analytics_events_experimental_63 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_exper_project_id_collector_tstamp_idx1 ON gitlab_partitions_static.product_analytics_events_experimental_01 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_exper_project_id_collector_tstamp_idx2 ON gitlab_partitions_static.product_analytics_events_experimental_02 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_exper_project_id_collector_tstamp_idx3 ON gitlab_partitions_static.product_analytics_events_experimental_03 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_exper_project_id_collector_tstamp_idx4 ON gitlab_partitions_static.product_analytics_events_experimental_04 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_exper_project_id_collector_tstamp_idx5 ON gitlab_partitions_static.product_analytics_events_experimental_05 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_exper_project_id_collector_tstamp_idx6 ON gitlab_partitions_static.product_analytics_events_experimental_06 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_exper_project_id_collector_tstamp_idx7 ON gitlab_partitions_static.product_analytics_events_experimental_07 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_exper_project_id_collector_tstamp_idx8 ON gitlab_partitions_static.product_analytics_events_experimental_08 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_exper_project_id_collector_tstamp_idx9 ON gitlab_partitions_static.product_analytics_events_experimental_09 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX product_analytics_events_experi_project_id_collector_tstamp_idx ON gitlab_partitions_static.product_analytics_events_experimental_00 USING btree (project_id, collector_tstamp);
+
+CREATE INDEX active_billable_users ON users USING btree (id) WHERE (((state)::text = 'active'::text) AND ((user_type IS NULL) OR (user_type = ANY (ARRAY[NULL::integer, 6, 4]))) AND ((user_type IS NULL) OR (user_type <> ALL ('{2,6,1,3,7,8}'::smallint[]))));
+
+CREATE INDEX analytics_index_audit_events_on_created_at_and_author_id ON audit_events_archived USING btree (created_at, author_id);
+
+CREATE INDEX analytics_index_audit_events_part_on_created_at_and_author_id ON ONLY audit_events USING btree (created_at, author_id);
CREATE INDEX analytics_index_events_on_created_at_and_author_id ON events USING btree (created_at, author_id);
CREATE INDEX analytics_repository_languages_on_project_id ON analytics_language_trend_repository_languages USING btree (project_id);
-CREATE UNIQUE INDEX analytics_repository_languages_unique_index ON analytics_language_trend_repository_languages USING btree (programming_language_id, project_id, snapshot_date);
-
CREATE UNIQUE INDEX any_approver_merge_request_rule_type_unique_index ON approval_merge_request_rules USING btree (merge_request_id, rule_type) WHERE (rule_type = 4);
CREATE UNIQUE INDEX any_approver_project_rule_type_unique_index ON approval_project_rules USING btree (project_id) WHERE (rule_type = 3);
-CREATE UNIQUE INDEX approval_rule_name_index_for_code_owners ON approval_merge_request_rules USING btree (merge_request_id, code_owner, name) WHERE (code_owner = true);
+CREATE INDEX approval_mr_rule_index_merge_request_id ON approval_merge_request_rules USING btree (merge_request_id);
+
+CREATE UNIQUE INDEX backup_labels_group_id_project_id_title_idx ON backup_labels USING btree (group_id, project_id, title);
+
+CREATE INDEX backup_labels_group_id_title_idx ON backup_labels USING btree (group_id, title) WHERE (project_id = NULL::integer);
+
+CREATE INDEX backup_labels_project_id_idx ON backup_labels USING btree (project_id);
+
+CREATE INDEX backup_labels_project_id_title_idx ON backup_labels USING btree (project_id, title) WHERE (group_id = NULL::integer);
+
+CREATE INDEX backup_labels_template_idx ON backup_labels USING btree (template) WHERE template;
+
+CREATE INDEX backup_labels_title_idx ON backup_labels USING btree (title);
+
+CREATE INDEX backup_labels_type_project_id_idx ON backup_labels USING btree (type, project_id);
+
+CREATE UNIQUE INDEX bulk_import_trackers_uniq_relation_by_entity ON bulk_import_trackers USING btree (bulk_import_entity_id, relation);
CREATE INDEX ci_builds_gitlab_monitor_metrics ON ci_builds USING btree (status, created_at, project_id) WHERE ((type)::text = 'Ci::Build'::text);
@@ -8063,22 +21059,36 @@ CREATE UNIQUE INDEX design_management_designs_versions_uniqueness ON design_mana
CREATE INDEX design_user_mentions_on_design_id_and_note_id_index ON design_user_mentions USING btree (design_id, note_id);
-CREATE INDEX epic_mentions_temp_index ON notes USING btree (id) WHERE ((note ~~ '%@%'::text) AND ((noteable_type)::text = 'Epic'::text));
-
CREATE UNIQUE INDEX epic_user_mentions_on_epic_id_and_note_id_index ON epic_user_mentions USING btree (epic_id, note_id);
CREATE UNIQUE INDEX epic_user_mentions_on_epic_id_index ON epic_user_mentions USING btree (epic_id) WHERE (note_id IS NULL);
-CREATE UNIQUE INDEX idx_deployment_merge_requests_unique_index ON deployment_merge_requests USING btree (deployment_id, merge_request_id);
+CREATE INDEX expired_artifacts_temp_index ON ci_job_artifacts USING btree (id, created_at) WHERE ((expire_at IS NULL) AND (created_at < '2020-06-22 02:00:00+02'::timestamp with time zone));
+
+CREATE INDEX finding_links_on_vulnerability_occurrence_id ON vulnerability_finding_links USING btree (vulnerability_occurrence_id);
+
+CREATE INDEX idx_audit_events_on_entity_id_desc_author_id_created_at ON audit_events_archived USING btree (entity_id, entity_type, id DESC, author_id, created_at);
+
+CREATE INDEX idx_audit_events_part_on_entity_id_desc_author_id_created_at ON ONLY audit_events USING btree (entity_id, entity_type, id DESC, author_id, created_at);
+
+CREATE INDEX idx_ci_pipelines_artifacts_locked ON ci_pipelines USING btree (ci_ref_id, id) WHERE (locked = 1);
+
+CREATE INDEX idx_container_exp_policies_on_project_id_next_run_at_enabled ON container_expiration_policies USING btree (project_id, next_run_at, enabled);
+
+CREATE INDEX idx_container_repositories_on_exp_cleanup_status_and_start_date ON container_repositories USING btree (expiration_policy_cleanup_status, expiration_policy_started_at);
+
+CREATE INDEX idx_deployment_clusters_on_cluster_id_and_kubernetes_namespace ON deployment_clusters USING btree (cluster_id, kubernetes_namespace);
+
+CREATE UNIQUE INDEX idx_environment_merge_requests_unique_index ON deployment_merge_requests USING btree (environment_id, merge_request_id);
CREATE INDEX idx_geo_con_rep_updated_events_on_container_repository_id ON geo_container_repository_updated_events USING btree (container_repository_id);
+CREATE INDEX idx_issues_on_health_status_not_null ON issues USING btree (health_status) WHERE (health_status IS NOT NULL);
+
CREATE INDEX idx_issues_on_project_id_and_created_at_and_id_and_state_id ON issues USING btree (project_id, created_at, id, state_id);
CREATE INDEX idx_issues_on_project_id_and_due_date_and_id_and_state_id ON issues USING btree (project_id, due_date, id, state_id) WHERE (due_date IS NOT NULL);
-CREATE INDEX idx_issues_on_project_id_and_due_date_and_id_and_state_partial ON issues USING btree (project_id, due_date, id, state) WHERE (due_date IS NOT NULL);
-
CREATE INDEX idx_issues_on_project_id_and_rel_position_and_state_id_and_id ON issues USING btree (project_id, relative_position, state_id, id DESC);
CREATE INDEX idx_issues_on_project_id_and_updated_at_and_id_and_state_id ON issues USING btree (project_id, updated_at, id, state_id);
@@ -8089,20 +21099,40 @@ CREATE INDEX idx_jira_connect_subscriptions_on_installation_id ON jira_connect_s
CREATE UNIQUE INDEX idx_jira_connect_subscriptions_on_installation_id_namespace_id ON jira_connect_subscriptions USING btree (jira_connect_installation_id, namespace_id);
+CREATE INDEX idx_members_created_at_user_id_invite_token ON members USING btree (created_at) WHERE ((invite_token IS NOT NULL) AND (user_id IS NULL));
+
CREATE INDEX idx_merge_requests_on_id_and_merge_jid ON merge_requests USING btree (id, merge_jid) WHERE ((merge_jid IS NOT NULL) AND (state_id = 4));
+CREATE INDEX idx_merge_requests_on_merged_state ON merge_requests USING btree (id) WHERE (state_id = 3);
+
CREATE INDEX idx_merge_requests_on_source_project_and_branch_state_opened ON merge_requests USING btree (source_project_id, source_branch) WHERE (state_id = 1);
CREATE INDEX idx_merge_requests_on_state_id_and_merge_status ON merge_requests USING btree (state_id, merge_status) WHERE ((state_id = 1) AND ((merge_status)::text = 'can_be_merged'::text));
CREATE INDEX idx_merge_requests_on_target_project_id_and_iid_opened ON merge_requests USING btree (target_project_id, iid) WHERE (state_id = 1);
-CREATE INDEX idx_mr_cc_diff_files_on_mr_cc_id ON merge_request_context_commit_diff_files USING btree (merge_request_context_commit_id);
+CREATE INDEX idx_merge_requests_on_target_project_id_and_locked_state ON merge_requests USING btree (target_project_id) WHERE (state_id = 4);
+
+CREATE UNIQUE INDEX idx_metrics_users_starred_dashboard_on_user_project_dashboard ON metrics_users_starred_dashboards USING btree (user_id, project_id, dashboard_path);
CREATE INDEX idx_mr_cc_diff_files_on_mr_cc_id_and_sha ON merge_request_context_commit_diff_files USING btree (merge_request_context_commit_id, sha);
+CREATE UNIQUE INDEX idx_on_compliance_management_frameworks_namespace_id_name ON compliance_management_frameworks USING btree (namespace_id, name);
+
+CREATE INDEX idx_on_issues_where_service_desk_reply_to_is_not_null ON issues USING btree (id) WHERE (service_desk_reply_to IS NOT NULL);
+
+CREATE INDEX idx_packages_build_infos_on_package_id ON packages_build_infos USING btree (package_id);
+
+CREATE INDEX idx_packages_debian_group_component_files_on_architecture_id ON packages_debian_group_component_files USING btree (architecture_id);
+
+CREATE INDEX idx_packages_debian_project_component_files_on_architecture_id ON packages_debian_project_component_files USING btree (architecture_id);
+
CREATE INDEX idx_packages_packages_on_project_id_name_version_package_type ON packages_packages USING btree (project_id, name, version, package_type);
+CREATE INDEX idx_pkgs_deb_grp_architectures_on_distribution_id ON packages_debian_group_architectures USING btree (distribution_id);
+
+CREATE INDEX idx_pkgs_deb_proj_architectures_on_distribution_id ON packages_debian_project_architectures USING btree (distribution_id);
+
CREATE UNIQUE INDEX idx_pkgs_dep_links_on_pkg_id_dependency_id_dependency_type ON packages_dependency_links USING btree (package_id, dependency_id, dependency_type);
CREATE INDEX idx_proj_feat_usg_on_jira_dvcs_cloud_last_sync_at_and_proj_id ON project_feature_usages USING btree (jira_dvcs_cloud_last_sync_at, project_id) WHERE (jira_dvcs_cloud_last_sync_at IS NOT NULL);
@@ -8113,6 +21143,10 @@ CREATE UNIQUE INDEX idx_project_id_payload_key_self_managed_prometheus_alert_eve
CREATE INDEX idx_project_repository_check_partial ON projects USING btree (repository_storage, created_at) WHERE (last_repository_check_at IS NULL);
+CREATE INDEX idx_projects_id_created_at_disable_overriding_approvers_false ON projects USING btree (id, created_at) WHERE ((disable_overriding_approvers_per_merge_request = false) OR (disable_overriding_approvers_per_merge_request IS NULL));
+
+CREATE INDEX idx_projects_id_created_at_disable_overriding_approvers_true ON projects USING btree (id, created_at) WHERE (disable_overriding_approvers_per_merge_request = true);
+
CREATE INDEX idx_projects_on_repository_storage_last_repository_updated_at ON projects USING btree (id, repository_storage, last_repository_updated_at);
CREATE INDEX idx_repository_states_on_last_repository_verification_ran_at ON project_repository_states USING btree (project_id, last_repository_verification_ran_at) WHERE ((repository_verification_checksum IS NOT NULL) AND (last_repository_verification_failure IS NULL));
@@ -8125,14 +21159,48 @@ CREATE INDEX idx_repository_states_on_wiki_failure_partial ON project_repository
CREATE INDEX idx_repository_states_outdated_checksums ON project_repository_states USING btree (project_id) WHERE (((repository_verification_checksum IS NULL) AND (last_repository_verification_failure IS NULL)) OR ((wiki_verification_checksum IS NULL) AND (last_wiki_verification_failure IS NULL)));
+CREATE UNIQUE INDEX idx_security_scans_on_build_and_scan_type ON security_scans USING btree (build_id, scan_type);
+
+CREATE INDEX idx_security_scans_on_scan_type ON security_scans USING btree (scan_type);
+
CREATE UNIQUE INDEX idx_serverless_domain_cluster_on_clusters_applications_knative ON serverless_domain_cluster USING btree (clusters_applications_knative_id);
+CREATE UNIQUE INDEX idx_vuln_fingerprints_on_occurrences_id_and_fingerprint ON vulnerability_finding_fingerprints USING btree (finding_id, fingerprint_sha256);
+
+CREATE UNIQUE INDEX idx_vuln_fingerprints_uniqueness ON vulnerability_finding_fingerprints USING btree (finding_id, algorithm_type, fingerprint_sha256);
+
+CREATE UNIQUE INDEX idx_vulnerability_ext_issue_links_on_vulne_id_and_ext_issue ON vulnerability_external_issue_links USING btree (vulnerability_id, external_type, external_project_key, external_issue_key);
+
+CREATE UNIQUE INDEX idx_vulnerability_ext_issue_links_on_vulne_id_and_link_type ON vulnerability_external_issue_links USING btree (vulnerability_id, link_type) WHERE (link_type = 1);
+
CREATE UNIQUE INDEX idx_vulnerability_issue_links_on_vulnerability_id_and_issue_id ON vulnerability_issue_links USING btree (vulnerability_id, issue_id);
CREATE UNIQUE INDEX idx_vulnerability_issue_links_on_vulnerability_id_and_link_type ON vulnerability_issue_links USING btree (vulnerability_id, link_type) WHERE (link_type = 2);
CREATE INDEX index_abuse_reports_on_user_id ON abuse_reports USING btree (user_id);
+CREATE INDEX index_alert_assignees_on_alert_id ON alert_management_alert_assignees USING btree (alert_id);
+
+CREATE UNIQUE INDEX index_alert_assignees_on_user_id_and_alert_id ON alert_management_alert_assignees USING btree (user_id, alert_id);
+
+CREATE INDEX index_alert_management_alerts_on_domain ON alert_management_alerts USING btree (domain);
+
+CREATE INDEX index_alert_management_alerts_on_environment_id ON alert_management_alerts USING btree (environment_id) WHERE (environment_id IS NOT NULL);
+
+CREATE INDEX index_alert_management_alerts_on_issue_id ON alert_management_alerts USING btree (issue_id);
+
+CREATE UNIQUE INDEX index_alert_management_alerts_on_project_id_and_iid ON alert_management_alerts USING btree (project_id, iid);
+
+CREATE INDEX index_alert_management_alerts_on_prometheus_alert_id ON alert_management_alerts USING btree (prometheus_alert_id) WHERE (prometheus_alert_id IS NOT NULL);
+
+CREATE INDEX index_alert_management_http_integrations_on_project_id ON alert_management_http_integrations USING btree (project_id);
+
+CREATE UNIQUE INDEX index_alert_user_mentions_on_alert_id ON alert_management_alert_user_mentions USING btree (alert_management_alert_id) WHERE (note_id IS NULL);
+
+CREATE UNIQUE INDEX index_alert_user_mentions_on_alert_id_and_note_id ON alert_management_alert_user_mentions USING btree (alert_management_alert_id, note_id);
+
+CREATE UNIQUE INDEX index_alert_user_mentions_on_note_id ON alert_management_alert_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
+
CREATE INDEX index_alerts_service_data_on_service_id ON alerts_service_data USING btree (service_id);
CREATE INDEX index_allowed_email_domains_on_group_id ON allowed_email_domains USING btree (group_id);
@@ -8141,12 +21209,14 @@ CREATE INDEX index_analytics_ca_group_stages_on_end_event_label_id ON analytics_
CREATE INDEX index_analytics_ca_group_stages_on_group_id ON analytics_cycle_analytics_group_stages USING btree (group_id);
-CREATE UNIQUE INDEX index_analytics_ca_group_stages_on_group_id_and_name ON analytics_cycle_analytics_group_stages USING btree (group_id, name);
-
CREATE INDEX index_analytics_ca_group_stages_on_relative_position ON analytics_cycle_analytics_group_stages USING btree (relative_position);
CREATE INDEX index_analytics_ca_group_stages_on_start_event_label_id ON analytics_cycle_analytics_group_stages USING btree (start_event_label_id);
+CREATE INDEX index_analytics_ca_group_stages_on_value_stream_id ON analytics_cycle_analytics_group_stages USING btree (group_value_stream_id);
+
+CREATE UNIQUE INDEX index_analytics_ca_group_value_streams_on_group_id_and_name ON analytics_cycle_analytics_group_value_streams USING btree (group_id, name);
+
CREATE INDEX index_analytics_ca_project_stages_on_end_event_label_id ON analytics_cycle_analytics_project_stages USING btree (end_event_label_id);
CREATE INDEX index_analytics_ca_project_stages_on_project_id ON analytics_cycle_analytics_project_stages USING btree (project_id);
@@ -8157,16 +21227,18 @@ CREATE INDEX index_analytics_ca_project_stages_on_relative_position ON analytics
CREATE INDEX index_analytics_ca_project_stages_on_start_event_label_id ON analytics_cycle_analytics_project_stages USING btree (start_event_label_id);
-CREATE INDEX index_analytics_repository_file_commits_file_id ON analytics_repository_file_commits USING btree (analytics_repository_file_id);
+CREATE INDEX index_analytics_cycle_analytics_group_stages_custom_only ON analytics_cycle_analytics_group_stages USING btree (id) WHERE (custom = true);
-CREATE INDEX index_analytics_repository_file_edits_on_project_id ON analytics_repository_file_edits USING btree (project_id);
-
-CREATE UNIQUE INDEX index_analytics_repository_files_on_project_id_and_file_path ON analytics_repository_files USING btree (project_id, file_path);
+CREATE UNIQUE INDEX index_analytics_devops_adoption_segments_on_name ON analytics_devops_adoption_segments USING btree (name);
CREATE INDEX index_application_settings_on_custom_project_templates_group_id ON application_settings USING btree (custom_project_templates_group_id);
CREATE INDEX index_application_settings_on_file_template_project_id ON application_settings USING btree (file_template_project_id);
+CREATE INDEX index_application_settings_on_instance_administrators_group_id ON application_settings USING btree (instance_administrators_group_id);
+
+CREATE UNIQUE INDEX index_application_settings_on_push_rule_id ON application_settings USING btree (push_rule_id);
+
CREATE INDEX index_application_settings_on_usage_stats_set_by_user_id ON application_settings USING btree (usage_stats_set_by_user_id);
CREATE INDEX index_applicationsettings_on_instance_administration_project_id ON application_settings USING btree (instance_administration_project_id);
@@ -8175,8 +21247,6 @@ CREATE UNIQUE INDEX index_approval_merge_request_rule_sources_1 ON approval_merg
CREATE INDEX index_approval_merge_request_rule_sources_2 ON approval_merge_request_rule_sources USING btree (approval_project_rule_id);
-CREATE INDEX index_approval_merge_request_rules_1 ON approval_merge_request_rules USING btree (merge_request_id, code_owner);
-
CREATE UNIQUE INDEX index_approval_merge_request_rules_approved_approvers_1 ON approval_merge_request_rules_approved_approvers USING btree (approval_merge_request_rule_id, user_id);
CREATE INDEX index_approval_merge_request_rules_approved_approvers_2 ON approval_merge_request_rules_approved_approvers USING btree (user_id);
@@ -8193,20 +21263,30 @@ CREATE UNIQUE INDEX index_approval_project_rules_groups_1 ON approval_project_ru
CREATE INDEX index_approval_project_rules_groups_2 ON approval_project_rules_groups USING btree (group_id);
+CREATE INDEX index_approval_project_rules_on_id_with_regular_type ON approval_project_rules USING btree (id) WHERE (rule_type = 0);
+
CREATE INDEX index_approval_project_rules_on_project_id ON approval_project_rules USING btree (project_id);
CREATE INDEX index_approval_project_rules_on_rule_type ON approval_project_rules USING btree (rule_type);
+CREATE INDEX index_approval_project_rules_protected_branches_pb_id ON approval_project_rules_protected_branches USING btree (protected_branch_id);
+
CREATE UNIQUE INDEX index_approval_project_rules_users_1 ON approval_project_rules_users USING btree (approval_project_rule_id, user_id);
CREATE INDEX index_approval_project_rules_users_2 ON approval_project_rules_users USING btree (user_id);
-CREATE UNIQUE INDEX index_approval_rule_name_for_code_owners_rule_type ON approval_merge_request_rules USING btree (merge_request_id, rule_type, name) WHERE (rule_type = 2);
+CREATE INDEX index_approval_project_rules_users_on_approval_project_rule_id ON approval_project_rules_users USING btree (approval_project_rule_id);
+
+CREATE UNIQUE INDEX index_approval_rule_name_for_code_owners_rule_type ON approval_merge_request_rules USING btree (merge_request_id, name) WHERE ((rule_type = 2) AND (section IS NULL));
+
+CREATE UNIQUE INDEX index_approval_rule_name_for_sectional_code_owners_rule_type ON approval_merge_request_rules USING btree (merge_request_id, name, section) WHERE (rule_type = 2);
CREATE INDEX index_approval_rules_code_owners_rule_type ON approval_merge_request_rules USING btree (merge_request_id, rule_type) WHERE (rule_type = 2);
CREATE INDEX index_approvals_on_merge_request_id ON approvals USING btree (merge_request_id);
+CREATE INDEX index_approvals_on_merge_request_id_and_created_at ON approvals USING btree (merge_request_id, created_at);
+
CREATE UNIQUE INDEX index_approvals_on_user_id_and_merge_request_id ON approvals USING btree (user_id, merge_request_id);
CREATE INDEX index_approver_groups_on_group_id ON approver_groups USING btree (group_id);
@@ -8217,7 +21297,13 @@ CREATE INDEX index_approvers_on_target_id_and_target_type ON approvers USING btr
CREATE INDEX index_approvers_on_user_id ON approvers USING btree (user_id);
-CREATE INDEX index_audit_events_on_entity_id_and_entity_type ON audit_events USING btree (entity_id, entity_type);
+CREATE UNIQUE INDEX index_atlassian_identities_on_extern_uid ON atlassian_identities USING btree (extern_uid);
+
+CREATE INDEX index_authentication_events_on_provider ON authentication_events USING btree (provider);
+
+CREATE INDEX index_authentication_events_on_provider_user_id_created_at ON authentication_events USING btree (provider, user_id, created_at) WHERE (result = 1);
+
+CREATE INDEX index_authentication_events_on_user_id ON authentication_events USING btree (user_id);
CREATE INDEX index_award_emoji_on_awardable_type_and_awardable_id ON award_emoji USING btree (awardable_type, awardable_id);
@@ -8227,6 +21313,12 @@ CREATE UNIQUE INDEX index_aws_roles_on_role_external_id ON aws_roles USING btree
CREATE UNIQUE INDEX index_aws_roles_on_user_id ON aws_roles USING btree (user_id);
+CREATE INDEX index_background_migration_jobs_for_partitioning_migrations ON background_migration_jobs USING btree (((arguments ->> 2))) WHERE (class_name = 'Gitlab::Database::PartitioningMigrationHelpers::BackfillPartitionedTable'::text);
+
+CREATE INDEX index_background_migration_jobs_on_class_name_and_arguments ON background_migration_jobs USING btree (class_name, arguments);
+
+CREATE INDEX index_background_migration_jobs_on_class_name_and_status_and_id ON background_migration_jobs USING btree (class_name, status, id);
+
CREATE INDEX index_badges_on_group_id ON badges USING btree (group_id);
CREATE INDEX index_badges_on_project_id ON badges USING btree (project_id);
@@ -8255,13 +21347,55 @@ CREATE INDEX index_board_project_recent_visits_on_user_id ON board_project_recen
CREATE UNIQUE INDEX index_board_project_recent_visits_on_user_project_and_board ON board_project_recent_visits USING btree (user_id, project_id, board_id);
+CREATE INDEX index_board_user_preferences_on_board_id ON board_user_preferences USING btree (board_id);
+
+CREATE INDEX index_board_user_preferences_on_user_id ON board_user_preferences USING btree (user_id);
+
+CREATE UNIQUE INDEX index_board_user_preferences_on_user_id_and_board_id ON board_user_preferences USING btree (user_id, board_id);
+
+CREATE INDEX index_boards_epic_board_labels_on_epic_board_id ON boards_epic_board_labels USING btree (epic_board_id);
+
+CREATE INDEX index_boards_epic_board_labels_on_label_id ON boards_epic_board_labels USING btree (label_id);
+
+CREATE UNIQUE INDEX index_boards_epic_board_positions_on_epic_board_id_and_epic_id ON boards_epic_board_positions USING btree (epic_board_id, epic_id);
+
+CREATE INDEX index_boards_epic_board_positions_on_epic_id ON boards_epic_board_positions USING btree (epic_id);
+
+CREATE INDEX index_boards_epic_boards_on_group_id ON boards_epic_boards USING btree (group_id);
+
+CREATE INDEX index_boards_epic_user_preferences_on_board_id ON boards_epic_user_preferences USING btree (board_id);
+
+CREATE UNIQUE INDEX index_boards_epic_user_preferences_on_board_user_epic_unique ON boards_epic_user_preferences USING btree (board_id, user_id, epic_id);
+
+CREATE INDEX index_boards_epic_user_preferences_on_epic_id ON boards_epic_user_preferences USING btree (epic_id);
+
+CREATE INDEX index_boards_epic_user_preferences_on_user_id ON boards_epic_user_preferences USING btree (user_id);
+
CREATE INDEX index_boards_on_group_id ON boards USING btree (group_id);
+CREATE INDEX index_boards_on_iteration_id ON boards USING btree (iteration_id);
+
CREATE INDEX index_boards_on_milestone_id ON boards USING btree (milestone_id);
CREATE INDEX index_boards_on_project_id ON boards USING btree (project_id);
-CREATE INDEX index_broadcast_messages_on_starts_at_and_ends_at_and_id ON broadcast_messages USING btree (starts_at, ends_at, id);
+CREATE INDEX index_broadcast_message_on_ends_at_and_broadcast_type_and_id ON broadcast_messages USING btree (ends_at, broadcast_type, id);
+
+CREATE INDEX index_bulk_import_configurations_on_bulk_import_id ON bulk_import_configurations USING btree (bulk_import_id);
+
+CREATE INDEX index_bulk_import_entities_on_bulk_import_id ON bulk_import_entities USING btree (bulk_import_id);
+
+CREATE INDEX index_bulk_import_entities_on_namespace_id ON bulk_import_entities USING btree (namespace_id);
+
+CREATE INDEX index_bulk_import_entities_on_parent_id ON bulk_import_entities USING btree (parent_id);
+
+CREATE INDEX index_bulk_import_entities_on_project_id ON bulk_import_entities USING btree (project_id);
+
+CREATE INDEX index_bulk_import_failures_on_bulk_import_entity_id ON bulk_import_failures USING btree (bulk_import_entity_id);
+
+CREATE INDEX index_bulk_import_failures_on_correlation_id_value ON bulk_import_failures USING btree (correlation_id_value);
+
+CREATE INDEX index_bulk_imports_on_user_id ON bulk_imports USING btree (user_id);
CREATE UNIQUE INDEX index_chat_names_on_service_id_and_team_id_and_chat_id ON chat_names USING btree (service_id, team_id, chat_id);
@@ -8271,12 +21405,14 @@ CREATE UNIQUE INDEX index_chat_teams_on_namespace_id ON chat_teams USING btree (
CREATE UNIQUE INDEX index_ci_build_needs_on_build_id_and_name ON ci_build_needs USING btree (build_id, name);
+CREATE UNIQUE INDEX index_ci_build_pending_states_on_build_id ON ci_build_pending_states USING btree (build_id);
+
+CREATE INDEX index_ci_build_report_results_on_project_id ON ci_build_report_results USING btree (project_id);
+
CREATE UNIQUE INDEX index_ci_build_trace_chunks_on_build_id_and_chunk_index ON ci_build_trace_chunks USING btree (build_id, chunk_index);
CREATE UNIQUE INDEX index_ci_build_trace_section_names_on_project_id_and_name ON ci_build_trace_section_names USING btree (project_id, name);
-CREATE UNIQUE INDEX index_ci_build_trace_sections_on_build_id_and_section_name_id ON ci_build_trace_sections USING btree (build_id, section_name_id);
-
CREATE INDEX index_ci_build_trace_sections_on_project_id ON ci_build_trace_sections USING btree (project_id);
CREATE INDEX index_ci_build_trace_sections_on_section_name_id ON ci_build_trace_sections USING btree (section_name_id);
@@ -8293,8 +21429,6 @@ CREATE INDEX index_ci_builds_on_artifacts_expire_at ON ci_builds USING btree (ar
CREATE INDEX index_ci_builds_on_auto_canceled_by_id ON ci_builds USING btree (auto_canceled_by_id);
-CREATE INDEX index_ci_builds_on_commit_id_and_artifacts_expireatandidpartial ON ci_builds USING btree (commit_id, artifacts_expire_at, id) WHERE (((type)::text = 'Ci::Build'::text) AND ((retried = false) OR (retried IS NULL)) AND ((name)::text = ANY (ARRAY[('sast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('sast:container'::character varying)::text, ('container_scanning'::character varying)::text, ('dast'::character varying)::text])));
-
CREATE INDEX index_ci_builds_on_commit_id_and_stage_idx_and_created_at ON ci_builds USING btree (commit_id, stage_idx, created_at);
CREATE INDEX index_ci_builds_on_commit_id_and_status_and_type ON ci_builds USING btree (commit_id, status, type);
@@ -8303,7 +21437,7 @@ CREATE INDEX index_ci_builds_on_commit_id_and_type_and_name_and_ref ON ci_builds
CREATE INDEX index_ci_builds_on_commit_id_and_type_and_ref ON ci_builds USING btree (commit_id, type, ref);
-CREATE INDEX index_ci_builds_on_name_for_security_products_values ON ci_builds USING btree (name) WHERE ((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text]));
+CREATE INDEX index_ci_builds_on_commit_id_artifacts_expired_at_and_id ON ci_builds USING btree (commit_id, artifacts_expire_at, id) WHERE (((type)::text = 'Ci::Build'::text) AND ((retried = false) OR (retried IS NULL)) AND ((name)::text = ANY (ARRAY[('sast'::character varying)::text, ('secret_detection'::character varying)::text, ('dependency_scanning'::character varying)::text, ('container_scanning'::character varying)::text, ('dast'::character varying)::text])));
CREATE INDEX index_ci_builds_on_project_id_and_id ON ci_builds USING btree (project_id, id);
@@ -8315,7 +21449,7 @@ CREATE INDEX index_ci_builds_on_protected ON ci_builds USING btree (protected);
CREATE INDEX index_ci_builds_on_queued_at ON ci_builds USING btree (queued_at);
-CREATE INDEX index_ci_builds_on_runner_id ON ci_builds USING btree (runner_id);
+CREATE INDEX index_ci_builds_on_runner_id_and_id_desc ON ci_builds USING btree (runner_id, id DESC);
CREATE INDEX index_ci_builds_on_stage_id ON ci_builds USING btree (stage_id);
@@ -8331,12 +21465,28 @@ CREATE INDEX index_ci_builds_on_upstream_pipeline_id ON ci_builds USING btree (u
CREATE INDEX index_ci_builds_on_user_id ON ci_builds USING btree (user_id);
+CREATE INDEX index_ci_builds_on_user_id_and_created_at_and_type_eq_ci_build ON ci_builds USING btree (user_id, created_at) WHERE ((type)::text = 'Ci::Build'::text);
+
CREATE INDEX index_ci_builds_project_id_and_status_for_live_jobs_partial2 ON ci_builds USING btree (project_id, status) WHERE (((type)::text = 'Ci::Build'::text) AND ((status)::text = ANY (ARRAY[('running'::character varying)::text, ('pending'::character varying)::text, ('created'::character varying)::text])));
CREATE UNIQUE INDEX index_ci_builds_runner_session_on_build_id ON ci_builds_runner_session USING btree (build_id);
+CREATE INDEX index_ci_daily_build_group_report_results_on_last_pipeline_id ON ci_daily_build_group_report_results USING btree (last_pipeline_id);
+
+CREATE INDEX index_ci_daily_build_group_report_results_on_project_and_date ON ci_daily_build_group_report_results USING btree (project_id, date DESC) WHERE ((default_branch = true) AND ((data -> 'coverage'::text) IS NOT NULL));
+
+CREATE INDEX index_ci_deleted_objects_on_pick_up_at ON ci_deleted_objects USING btree (pick_up_at);
+
+CREATE INDEX index_ci_freeze_periods_on_project_id ON ci_freeze_periods USING btree (project_id);
+
CREATE UNIQUE INDEX index_ci_group_variables_on_group_id_and_key ON ci_group_variables USING btree (group_id, key);
+CREATE UNIQUE INDEX index_ci_instance_variables_on_key ON ci_instance_variables USING btree (key);
+
+CREATE INDEX index_ci_job_artifacts_for_terraform_reports ON ci_job_artifacts USING btree (project_id, id) WHERE (file_type = 18);
+
+CREATE INDEX index_ci_job_artifacts_id_for_terraform_reports ON ci_job_artifacts USING btree (id) WHERE (file_type = 18);
+
CREATE INDEX index_ci_job_artifacts_on_expire_at_and_job_id ON ci_job_artifacts USING btree (expire_at, job_id);
CREATE INDEX index_ci_job_artifacts_on_file_store ON ci_job_artifacts USING btree (file_store);
@@ -8351,10 +21501,20 @@ CREATE INDEX index_ci_job_variables_on_job_id ON ci_job_variables USING btree (j
CREATE UNIQUE INDEX index_ci_job_variables_on_key_and_job_id ON ci_job_variables USING btree (key, job_id);
+CREATE INDEX index_ci_pipeline_artifacts_on_expire_at ON ci_pipeline_artifacts USING btree (expire_at);
+
+CREATE INDEX index_ci_pipeline_artifacts_on_pipeline_id ON ci_pipeline_artifacts USING btree (pipeline_id);
+
+CREATE UNIQUE INDEX index_ci_pipeline_artifacts_on_pipeline_id_and_file_type ON ci_pipeline_artifacts USING btree (pipeline_id, file_type);
+
+CREATE INDEX index_ci_pipeline_artifacts_on_project_id ON ci_pipeline_artifacts USING btree (project_id);
+
CREATE INDEX index_ci_pipeline_chat_data_on_chat_name_id ON ci_pipeline_chat_data USING btree (chat_name_id);
CREATE UNIQUE INDEX index_ci_pipeline_chat_data_on_pipeline_id ON ci_pipeline_chat_data USING btree (pipeline_id);
+CREATE INDEX index_ci_pipeline_messages_on_pipeline_id ON ci_pipeline_messages USING btree (pipeline_id);
+
CREATE UNIQUE INDEX index_ci_pipeline_schedule_variables_on_schedule_id_and_key ON ci_pipeline_schedule_variables USING btree (pipeline_schedule_id, key);
CREATE INDEX index_ci_pipeline_schedules_on_next_run_at_and_active ON ci_pipeline_schedules USING btree (next_run_at, active);
@@ -8363,14 +21523,16 @@ CREATE INDEX index_ci_pipeline_schedules_on_owner_id ON ci_pipeline_schedules US
CREATE INDEX index_ci_pipeline_schedules_on_project_id ON ci_pipeline_schedules USING btree (project_id);
-CREATE INDEX index_ci_pipeline_variables_on_pipeline_id ON ci_pipeline_variables USING btree (pipeline_id) WHERE ((key)::text = 'AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE'::text);
-
CREATE UNIQUE INDEX index_ci_pipeline_variables_on_pipeline_id_and_key ON ci_pipeline_variables USING btree (pipeline_id, key);
CREATE INDEX index_ci_pipelines_config_on_pipeline_id ON ci_pipelines_config USING btree (pipeline_id);
+CREATE INDEX index_ci_pipelines_for_ondemand_dast_scans ON ci_pipelines USING btree (id) WHERE (source = 13);
+
CREATE INDEX index_ci_pipelines_on_auto_canceled_by_id ON ci_pipelines USING btree (auto_canceled_by_id);
+CREATE INDEX index_ci_pipelines_on_ci_ref_id_and_more ON ci_pipelines USING btree (ci_ref_id, id DESC, source, status) WHERE (ci_ref_id IS NOT NULL);
+
CREATE INDEX index_ci_pipelines_on_external_pull_request_id ON ci_pipelines USING btree (external_pull_request_id) WHERE (external_pull_request_id IS NOT NULL);
CREATE INDEX index_ci_pipelines_on_merge_request_id ON ci_pipelines USING btree (merge_request_id) WHERE (merge_request_id IS NOT NULL);
@@ -8389,17 +21551,21 @@ CREATE INDEX index_ci_pipelines_on_project_id_and_source ON ci_pipelines USING b
CREATE INDEX index_ci_pipelines_on_project_id_and_status_and_config_source ON ci_pipelines USING btree (project_id, status, config_source);
+CREATE INDEX index_ci_pipelines_on_project_id_and_status_and_created_at ON ci_pipelines USING btree (project_id, status, created_at);
+
CREATE INDEX index_ci_pipelines_on_project_id_and_status_and_updated_at ON ci_pipelines USING btree (project_id, status, updated_at);
+CREATE INDEX index_ci_pipelines_on_project_id_and_user_id_and_status_and_ref ON ci_pipelines USING btree (project_id, user_id, status, ref) WHERE (source <> 12);
+
CREATE INDEX index_ci_pipelines_on_project_idandrefandiddesc ON ci_pipelines USING btree (project_id, ref, id DESC);
-CREATE INDEX index_ci_pipelines_on_status ON ci_pipelines USING btree (status);
+CREATE INDEX index_ci_pipelines_on_status_and_id ON ci_pipelines USING btree (status, id);
-CREATE INDEX index_ci_pipelines_on_user_id ON ci_pipelines USING btree (user_id);
+CREATE INDEX index_ci_pipelines_on_user_id_and_created_at_and_config_source ON ci_pipelines USING btree (user_id, created_at, config_source);
-CREATE INDEX index_ci_refs_on_last_updated_by_pipeline_id ON ci_refs USING btree (last_updated_by_pipeline_id);
+CREATE INDEX index_ci_pipelines_on_user_id_and_created_at_and_source ON ci_pipelines USING btree (user_id, created_at, source);
-CREATE UNIQUE INDEX index_ci_refs_on_project_id_and_ref_and_tag ON ci_refs USING btree (project_id, ref, tag);
+CREATE UNIQUE INDEX index_ci_refs_on_project_id_and_ref_path ON ci_refs USING btree (project_id, ref_path);
CREATE UNIQUE INDEX index_ci_resource_groups_on_project_id_and_key ON ci_resource_groups USING btree (project_id, key);
@@ -8437,6 +21603,10 @@ CREATE INDEX index_ci_sources_pipelines_on_source_pipeline_id ON ci_sources_pipe
CREATE INDEX index_ci_sources_pipelines_on_source_project_id ON ci_sources_pipelines USING btree (source_project_id);
+CREATE INDEX index_ci_sources_projects_on_pipeline_id ON ci_sources_projects USING btree (pipeline_id);
+
+CREATE UNIQUE INDEX index_ci_sources_projects_on_source_project_id_and_pipeline_id ON ci_sources_projects USING btree (source_project_id, pipeline_id);
+
CREATE INDEX index_ci_stages_on_pipeline_id ON ci_stages USING btree (pipeline_id);
CREATE UNIQUE INDEX index_ci_stages_on_pipeline_id_and_name ON ci_stages USING btree (pipeline_id, name);
@@ -8449,6 +21619,10 @@ CREATE INDEX index_ci_subscriptions_projects_on_upstream_project_id ON ci_subscr
CREATE UNIQUE INDEX index_ci_subscriptions_projects_unique_subscription ON ci_subscriptions_projects USING btree (downstream_project_id, upstream_project_id);
+CREATE INDEX index_ci_test_case_failures_on_build_id ON ci_test_case_failures USING btree (build_id);
+
+CREATE UNIQUE INDEX index_ci_test_cases_on_project_id_and_key_hash ON ci_test_cases USING btree (project_id, key_hash);
+
CREATE INDEX index_ci_trigger_requests_on_commit_id ON ci_trigger_requests USING btree (commit_id);
CREATE INDEX index_ci_trigger_requests_on_trigger_id_and_id ON ci_trigger_requests USING btree (trigger_id, id DESC);
@@ -8457,10 +21631,16 @@ CREATE INDEX index_ci_triggers_on_owner_id ON ci_triggers USING btree (owner_id)
CREATE INDEX index_ci_triggers_on_project_id ON ci_triggers USING btree (project_id);
-CREATE INDEX index_ci_variables_on_project_id ON ci_variables USING btree (project_id) WHERE ((key)::text = 'AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE'::text);
+CREATE INDEX index_ci_variables_on_key ON ci_variables USING btree (key);
CREATE UNIQUE INDEX index_ci_variables_on_project_id_and_key_and_environment_scope ON ci_variables USING btree (project_id, key, environment_scope);
+CREATE INDEX index_cluster_agent_tokens_on_agent_id ON cluster_agent_tokens USING btree (agent_id);
+
+CREATE UNIQUE INDEX index_cluster_agent_tokens_on_token_encrypted ON cluster_agent_tokens USING btree (token_encrypted);
+
+CREATE UNIQUE INDEX index_cluster_agents_on_project_id_and_name ON cluster_agents USING btree (project_id, name);
+
CREATE UNIQUE INDEX index_cluster_groups_on_cluster_id_and_group_id ON cluster_groups USING btree (cluster_id, group_id);
CREATE INDEX index_cluster_groups_on_group_id ON cluster_groups USING btree (group_id);
@@ -8475,22 +21655,26 @@ CREATE UNIQUE INDEX index_cluster_providers_aws_on_cluster_id ON cluster_provide
CREATE INDEX index_cluster_providers_aws_on_cluster_id_and_status ON cluster_providers_aws USING btree (cluster_id, status);
-CREATE INDEX index_cluster_providers_aws_on_created_by_user_id ON cluster_providers_aws USING btree (created_by_user_id);
-
CREATE INDEX index_cluster_providers_gcp_on_cloud_run ON cluster_providers_gcp USING btree (cloud_run);
CREATE UNIQUE INDEX index_cluster_providers_gcp_on_cluster_id ON cluster_providers_gcp USING btree (cluster_id);
CREATE UNIQUE INDEX index_clusters_applications_cert_managers_on_cluster_id ON clusters_applications_cert_managers USING btree (cluster_id);
+CREATE UNIQUE INDEX index_clusters_applications_cilium_on_cluster_id ON clusters_applications_cilium USING btree (cluster_id);
+
CREATE UNIQUE INDEX index_clusters_applications_crossplane_on_cluster_id ON clusters_applications_crossplane USING btree (cluster_id);
CREATE UNIQUE INDEX index_clusters_applications_elastic_stacks_on_cluster_id ON clusters_applications_elastic_stacks USING btree (cluster_id);
+CREATE UNIQUE INDEX index_clusters_applications_fluentd_on_cluster_id ON clusters_applications_fluentd USING btree (cluster_id);
+
CREATE UNIQUE INDEX index_clusters_applications_helm_on_cluster_id ON clusters_applications_helm USING btree (cluster_id);
CREATE UNIQUE INDEX index_clusters_applications_ingress_on_cluster_id ON clusters_applications_ingress USING btree (cluster_id);
+CREATE INDEX index_clusters_applications_ingress_on_modsecurity ON clusters_applications_ingress USING btree (modsecurity_enabled, modsecurity_mode, cluster_id);
+
CREATE UNIQUE INDEX index_clusters_applications_jupyter_on_cluster_id ON clusters_applications_jupyter USING btree (cluster_id);
CREATE INDEX index_clusters_applications_jupyter_on_oauth_application_id ON clusters_applications_jupyter USING btree (oauth_application_id);
@@ -8511,7 +21695,9 @@ CREATE INDEX index_clusters_kubernetes_namespaces_on_environment_id ON clusters_
CREATE INDEX index_clusters_kubernetes_namespaces_on_project_id ON clusters_kubernetes_namespaces USING btree (project_id);
-CREATE INDEX index_clusters_on_enabled ON clusters USING btree (enabled);
+CREATE INDEX index_clusters_on_enabled_and_provider_type_and_id ON clusters USING btree (enabled, provider_type, id);
+
+CREATE INDEX index_clusters_on_enabled_cluster_type_id_and_created_at ON clusters USING btree (enabled, cluster_type, id, created_at);
CREATE INDEX index_clusters_on_management_project_id ON clusters USING btree (management_project_id) WHERE (management_project_id IS NOT NULL);
@@ -8523,12 +21709,46 @@ CREATE INDEX index_container_expiration_policies_on_next_run_at_and_enabled ON c
CREATE INDEX index_container_repositories_on_project_id ON container_repositories USING btree (project_id);
+CREATE INDEX index_container_repositories_on_project_id_and_id ON container_repositories USING btree (project_id, id);
+
CREATE UNIQUE INDEX index_container_repositories_on_project_id_and_name ON container_repositories USING btree (project_id, name);
+CREATE INDEX index_container_repository_on_name_trigram ON container_repositories USING gin (name gin_trgm_ops);
+
+CREATE INDEX index_created_at_on_codeowner_approval_merge_request_rules ON approval_merge_request_rules USING btree (created_at) WHERE ((rule_type = 2) AND (section <> 'codeowners'::text));
+
+CREATE INDEX index_csv_issue_imports_on_project_id ON csv_issue_imports USING btree (project_id);
+
+CREATE INDEX index_csv_issue_imports_on_user_id ON csv_issue_imports USING btree (user_id);
+
+CREATE UNIQUE INDEX index_custom_emoji_on_namespace_id_and_name ON custom_emoji USING btree (namespace_id, name);
+
+CREATE UNIQUE INDEX index_daily_build_group_report_results_unique_columns ON ci_daily_build_group_report_results USING btree (project_id, ref_path, date, group_name);
+
+CREATE UNIQUE INDEX index_dast_scanner_profiles_on_project_id_and_name ON dast_scanner_profiles USING btree (project_id, name);
+
+CREATE INDEX index_dast_site_profiles_on_dast_site_id ON dast_site_profiles USING btree (dast_site_id);
+
+CREATE UNIQUE INDEX index_dast_site_profiles_on_project_id_and_name ON dast_site_profiles USING btree (project_id, name);
+
+CREATE INDEX index_dast_site_tokens_on_project_id ON dast_site_tokens USING btree (project_id);
+
+CREATE INDEX index_dast_site_validations_on_dast_site_token_id ON dast_site_validations USING btree (dast_site_token_id);
+
+CREATE INDEX index_dast_site_validations_on_url_base_and_state ON dast_site_validations USING btree (url_base, state);
+
+CREATE INDEX index_dast_sites_on_dast_site_validation_id ON dast_sites USING btree (dast_site_validation_id);
+
+CREATE UNIQUE INDEX index_dast_sites_on_project_id_and_url ON dast_sites USING btree (project_id, url);
+
CREATE INDEX index_dependency_proxy_blobs_on_group_id_and_file_name ON dependency_proxy_blobs USING btree (group_id, file_name);
CREATE INDEX index_dependency_proxy_group_settings_on_group_id ON dependency_proxy_group_settings USING btree (group_id);
+CREATE UNIQUE INDEX index_dependency_proxy_manifests_on_group_id_and_file_name ON dependency_proxy_manifests USING btree (group_id, file_name);
+
+CREATE INDEX index_deploy_key_id_on_protected_branch_push_access_levels ON protected_branch_push_access_levels USING btree (deploy_key_id);
+
CREATE INDEX index_deploy_keys_projects_on_deploy_key_id ON deploy_keys_projects USING btree (deploy_key_id);
CREATE INDEX index_deploy_keys_projects_on_project_id ON deploy_keys_projects USING btree (project_id);
@@ -8539,6 +21759,8 @@ CREATE INDEX index_deploy_tokens_on_token_and_expires_at_and_id ON deploy_tokens
CREATE UNIQUE INDEX index_deploy_tokens_on_token_encrypted ON deploy_tokens USING btree (token_encrypted);
+CREATE UNIQUE INDEX index_deployment_clusters_on_cluster_id_and_deployment_id ON deployment_clusters USING btree (cluster_id, deployment_id);
+
CREATE INDEX index_deployment_merge_requests_on_merge_request_id ON deployment_merge_requests USING btree (merge_request_id);
CREATE INDEX index_deployments_on_cluster_id_and_status ON deployments USING btree (cluster_id, status);
@@ -8551,7 +21773,13 @@ CREATE INDEX index_deployments_on_environment_id_and_id ON deployments USING btr
CREATE INDEX index_deployments_on_environment_id_and_iid_and_project_id ON deployments USING btree (environment_id, iid, project_id);
-CREATE INDEX index_deployments_on_environment_id_and_status ON deployments USING btree (environment_id, status);
+CREATE INDEX index_deployments_on_environment_status_sha ON deployments USING btree (environment_id, status, sha);
+
+CREATE INDEX index_deployments_on_id_and_status_and_created_at ON deployments USING btree (id, status, created_at);
+
+CREATE INDEX index_deployments_on_id_where_cluster_id_present ON deployments USING btree (id) WHERE (cluster_id IS NOT NULL);
+
+CREATE INDEX index_deployments_on_project_and_finished ON deployments USING btree (project_id, finished_at) WHERE (status = 2);
CREATE INDEX index_deployments_on_project_id_and_id ON deployments USING btree (project_id, id DESC);
@@ -8565,12 +21793,20 @@ CREATE INDEX index_deployments_on_project_id_and_status_and_created_at ON deploy
CREATE INDEX index_deployments_on_project_id_and_updated_at_and_id ON deployments USING btree (project_id, updated_at DESC, id DESC);
+CREATE INDEX index_deployments_on_project_id_sha ON deployments USING btree (project_id, sha);
+
+CREATE INDEX index_deployments_on_user_id_and_status_and_created_at ON deployments USING btree (user_id, status, created_at);
+
CREATE INDEX index_description_versions_on_epic_id ON description_versions USING btree (epic_id) WHERE (epic_id IS NOT NULL);
CREATE INDEX index_description_versions_on_issue_id ON description_versions USING btree (issue_id) WHERE (issue_id IS NOT NULL);
CREATE INDEX index_description_versions_on_merge_request_id ON description_versions USING btree (merge_request_id) WHERE (merge_request_id IS NOT NULL);
+CREATE INDEX index_design_management_designs_issue_id_relative_position_id ON design_management_designs USING btree (issue_id, relative_position, id);
+
+CREATE UNIQUE INDEX index_design_management_designs_on_iid_and_project_id ON design_management_designs USING btree (project_id, iid);
+
CREATE UNIQUE INDEX index_design_management_designs_on_issue_id_and_filename ON design_management_designs USING btree (issue_id, filename);
CREATE INDEX index_design_management_designs_on_project_id ON design_management_designs USING btree (project_id);
@@ -8589,17 +21825,19 @@ CREATE UNIQUE INDEX index_design_management_versions_on_sha_and_issue_id ON desi
CREATE UNIQUE INDEX index_design_user_mentions_on_note_id ON design_user_mentions USING btree (note_id);
+CREATE UNIQUE INDEX index_diff_note_positions_on_note_id_and_diff_type ON diff_note_positions USING btree (note_id, diff_type);
+
CREATE INDEX index_draft_notes_on_author_id ON draft_notes USING btree (author_id);
CREATE INDEX index_draft_notes_on_discussion_id ON draft_notes USING btree (discussion_id);
CREATE INDEX index_draft_notes_on_merge_request_id ON draft_notes USING btree (merge_request_id);
-CREATE INDEX index_elasticsearch_indexed_namespaces_on_created_at ON elasticsearch_indexed_namespaces USING btree (created_at);
+CREATE UNIQUE INDEX index_elastic_reindexing_tasks_on_in_progress ON elastic_reindexing_tasks USING btree (in_progress) WHERE in_progress;
-CREATE UNIQUE INDEX index_elasticsearch_indexed_namespaces_on_namespace_id ON elasticsearch_indexed_namespaces USING btree (namespace_id);
+CREATE INDEX index_elastic_reindexing_tasks_on_state ON elastic_reindexing_tasks USING btree (state);
-CREATE UNIQUE INDEX index_elasticsearch_indexed_projects_on_project_id ON elasticsearch_indexed_projects USING btree (project_id);
+CREATE INDEX index_elasticsearch_indexed_namespaces_on_created_at ON elasticsearch_indexed_namespaces USING btree (created_at);
CREATE UNIQUE INDEX index_emails_on_confirmation_token ON emails USING btree (confirmation_token);
@@ -8607,6 +21845,8 @@ CREATE UNIQUE INDEX index_emails_on_email ON emails USING btree (email);
CREATE INDEX index_emails_on_user_id ON emails USING btree (user_id);
+CREATE INDEX index_enabled_clusters_on_id ON clusters USING btree (id) WHERE (enabled = true);
+
CREATE INDEX index_environments_on_name_varchar_pattern_ops ON environments USING btree (name varchar_pattern_ops);
CREATE UNIQUE INDEX index_environments_on_project_id_and_name ON environments USING btree (project_id, name);
@@ -8615,6 +21855,8 @@ CREATE UNIQUE INDEX index_environments_on_project_id_and_slug ON environments US
CREATE INDEX index_environments_on_project_id_state_environment_type ON environments USING btree (project_id, state, environment_type);
+CREATE INDEX index_environments_on_state_and_auto_stop_at ON environments USING btree (state, auto_stop_at) WHERE ((auto_stop_at IS NOT NULL) AND ((state)::text = 'available'::text));
+
CREATE INDEX index_epic_issues_on_epic_id ON epic_issues USING btree (epic_id);
CREATE UNIQUE INDEX index_epic_issues_on_issue_id ON epic_issues USING btree (issue_id);
@@ -8629,6 +21871,8 @@ CREATE INDEX index_epics_on_author_id ON epics USING btree (author_id);
CREATE INDEX index_epics_on_closed_by_id ON epics USING btree (closed_by_id);
+CREATE INDEX index_epics_on_confidential ON epics USING btree (confidential);
+
CREATE INDEX index_epics_on_due_date_sourcing_epic_id ON epics USING btree (due_date_sourcing_epic_id) WHERE (due_date_sourcing_epic_id IS NOT NULL);
CREATE INDEX index_epics_on_due_date_sourcing_milestone_id ON epics USING btree (due_date_sourcing_milestone_id);
@@ -8637,8 +21881,18 @@ CREATE INDEX index_epics_on_end_date ON epics USING btree (end_date);
CREATE INDEX index_epics_on_group_id ON epics USING btree (group_id);
+CREATE UNIQUE INDEX index_epics_on_group_id_and_external_key ON epics USING btree (group_id, external_key) WHERE (external_key IS NOT NULL);
+
+CREATE UNIQUE INDEX index_epics_on_group_id_and_iid ON epics USING btree (group_id, iid);
+
+CREATE INDEX index_epics_on_group_id_and_iid_varchar_pattern ON epics USING btree (group_id, ((iid)::character varying) varchar_pattern_ops);
+
CREATE INDEX index_epics_on_iid ON epics USING btree (iid);
+CREATE INDEX index_epics_on_last_edited_by_id ON epics USING btree (last_edited_by_id);
+
+CREATE INDEX index_epics_on_lock_version ON epics USING btree (lock_version) WHERE (lock_version IS NULL);
+
CREATE INDEX index_epics_on_parent_id ON epics USING btree (parent_id);
CREATE INDEX index_epics_on_start_date ON epics USING btree (start_date);
@@ -8649,6 +21903,10 @@ CREATE INDEX index_epics_on_start_date_sourcing_milestone_id ON epics USING btre
CREATE INDEX index_events_on_action ON events USING btree (action);
+CREATE INDEX index_events_on_author_id_and_created_at ON events USING btree (author_id, created_at);
+
+CREATE INDEX index_events_on_author_id_and_created_at_merge_requests ON events USING btree (author_id, created_at) WHERE ((target_type)::text = 'MergeRequest'::text);
+
CREATE INDEX index_events_on_author_id_and_project_id ON events USING btree (author_id, project_id);
CREATE INDEX index_events_on_group_id_partial ON events USING btree (group_id) WHERE (group_id IS NOT NULL);
@@ -8657,10 +21915,30 @@ CREATE INDEX index_events_on_project_id_and_created_at ON events USING btree (pr
CREATE INDEX index_events_on_project_id_and_id ON events USING btree (project_id, id);
+CREATE INDEX index_events_on_project_id_and_id_desc_on_merged_action ON events USING btree (project_id, id DESC) WHERE (action = 7);
+
CREATE INDEX index_events_on_target_type_and_target_id ON events USING btree (target_type, target_id);
+CREATE UNIQUE INDEX index_events_on_target_type_and_target_id_and_fingerprint ON events USING btree (target_type, target_id, fingerprint);
+
CREATE INDEX index_evidences_on_release_id ON evidences USING btree (release_id);
+CREATE INDEX index_experiment_subjects_on_experiment_id ON experiment_subjects USING btree (experiment_id);
+
+CREATE INDEX index_experiment_subjects_on_group_id ON experiment_subjects USING btree (group_id);
+
+CREATE INDEX index_experiment_subjects_on_project_id ON experiment_subjects USING btree (project_id);
+
+CREATE INDEX index_experiment_subjects_on_user_id ON experiment_subjects USING btree (user_id);
+
+CREATE INDEX index_experiment_users_on_experiment_id ON experiment_users USING btree (experiment_id);
+
+CREATE INDEX index_experiment_users_on_user_id ON experiment_users USING btree (user_id);
+
+CREATE UNIQUE INDEX index_experiments_on_name ON experiments USING btree (name);
+
+CREATE INDEX index_expired_and_not_notified_personal_access_tokens ON personal_access_tokens USING btree (id, expires_at) WHERE ((impersonation = false) AND (revoked = false) AND (expire_notification_delivered = false));
+
CREATE UNIQUE INDEX index_external_pull_requests_on_project_and_branches ON external_pull_requests USING btree (project_id, source_branch, target_branch);
CREATE UNIQUE INDEX index_feature_flag_scopes_on_flag_id_and_environment_scope ON operations_feature_flag_scopes USING btree (feature_flag_id, environment_scope);
@@ -8671,10 +21949,6 @@ CREATE UNIQUE INDEX index_feature_gates_on_feature_key_and_key_and_value ON feat
CREATE UNIQUE INDEX index_features_on_key ON features USING btree (key);
-CREATE UNIQUE INDEX index_file_commits_on_committed_date_file_id_and_project_id ON analytics_repository_file_commits USING btree (project_id, committed_date, analytics_repository_file_id);
-
-CREATE UNIQUE INDEX index_file_edits_on_committed_date_file_id_and_project_id ON analytics_repository_file_edits USING btree (analytics_repository_file_id, committed_date, project_id);
-
CREATE INDEX index_for_resource_group ON ci_builds USING btree (resource_group_id, id) WHERE (resource_group_id IS NOT NULL);
CREATE INDEX index_for_status_per_branch_per_project ON merge_trains USING btree (target_project_id, target_branch, status);
@@ -8687,12 +21961,12 @@ CREATE UNIQUE INDEX index_fork_network_members_on_project_id ON fork_network_mem
CREATE UNIQUE INDEX index_fork_networks_on_root_project_id ON fork_networks USING btree (root_project_id);
-CREATE UNIQUE INDEX index_forked_project_links_on_forked_to_project_id ON forked_project_links USING btree (forked_to_project_id);
-
CREATE INDEX index_geo_event_log_on_cache_invalidation_event_id ON geo_event_log USING btree (cache_invalidation_event_id) WHERE (cache_invalidation_event_id IS NOT NULL);
CREATE INDEX index_geo_event_log_on_container_repository_updated_event_id ON geo_event_log USING btree (container_repository_updated_event_id);
+CREATE INDEX index_geo_event_log_on_geo_event_id ON geo_event_log USING btree (geo_event_id) WHERE (geo_event_id IS NOT NULL);
+
CREATE INDEX index_geo_event_log_on_hashed_storage_attachments_event_id ON geo_event_log USING btree (hashed_storage_attachments_event_id) WHERE (hashed_storage_attachments_event_id IS NOT NULL);
CREATE INDEX index_geo_event_log_on_hashed_storage_migrated_event_id ON geo_event_log USING btree (hashed_storage_migrated_event_id) WHERE (hashed_storage_migrated_event_id IS NOT NULL);
@@ -8755,6 +22029,8 @@ CREATE INDEX index_geo_upload_deleted_events_on_upload_id ON geo_upload_deleted_
CREATE INDEX index_gitlab_subscription_histories_on_gitlab_subscription_id ON gitlab_subscription_histories USING btree (gitlab_subscription_id);
+CREATE INDEX index_gitlab_subscriptions_on_end_date_and_namespace_id ON gitlab_subscriptions USING btree (end_date, namespace_id);
+
CREATE INDEX index_gitlab_subscriptions_on_hosted_plan_id ON gitlab_subscriptions USING btree (hosted_plan_id);
CREATE UNIQUE INDEX index_gitlab_subscriptions_on_namespace_id ON gitlab_subscriptions USING btree (namespace_id);
@@ -8793,14 +22069,42 @@ CREATE INDEX index_group_deletion_schedules_on_marked_for_deletion_on ON group_d
CREATE INDEX index_group_deletion_schedules_on_user_id ON group_deletion_schedules USING btree (user_id);
+CREATE UNIQUE INDEX index_group_deploy_keys_group_on_group_deploy_key_and_group_ids ON group_deploy_keys_groups USING btree (group_id, group_deploy_key_id);
+
+CREATE INDEX index_group_deploy_keys_groups_on_group_deploy_key_id ON group_deploy_keys_groups USING btree (group_deploy_key_id);
+
+CREATE UNIQUE INDEX index_group_deploy_keys_on_fingerprint ON group_deploy_keys USING btree (fingerprint);
+
+CREATE INDEX index_group_deploy_keys_on_fingerprint_sha256 ON group_deploy_keys USING btree (fingerprint_sha256);
+
+CREATE INDEX index_group_deploy_keys_on_user_id ON group_deploy_keys USING btree (user_id);
+
+CREATE INDEX index_group_deploy_tokens_on_deploy_token_id ON group_deploy_tokens USING btree (deploy_token_id);
+
+CREATE UNIQUE INDEX index_group_deploy_tokens_on_group_and_deploy_token_ids ON group_deploy_tokens USING btree (group_id, deploy_token_id);
+
CREATE UNIQUE INDEX index_group_group_links_on_shared_group_and_shared_with_group ON group_group_links USING btree (shared_group_id, shared_with_group_id);
CREATE INDEX index_group_group_links_on_shared_with_group_id ON group_group_links USING btree (shared_with_group_id);
+CREATE INDEX index_group_import_states_on_group_id ON group_import_states USING btree (group_id);
+
+CREATE INDEX index_group_import_states_on_user_id ON group_import_states USING btree (user_id) WHERE (user_id IS NOT NULL);
+
+CREATE UNIQUE INDEX index_group_stages_on_group_id_group_value_stream_id_and_name ON analytics_cycle_analytics_group_stages USING btree (group_id, group_value_stream_id, name);
+
+CREATE UNIQUE INDEX index_group_wiki_repositories_on_disk_path ON group_wiki_repositories USING btree (disk_path);
+
+CREATE INDEX index_group_wiki_repositories_on_shard_id ON group_wiki_repositories USING btree (shard_id);
+
+CREATE UNIQUE INDEX index_http_integrations_on_active_and_project_and_endpoint ON alert_management_http_integrations USING btree (active, project_id, endpoint_identifier) WHERE active;
+
CREATE INDEX index_identities_on_saml_provider_id ON identities USING btree (saml_provider_id) WHERE (saml_provider_id IS NOT NULL);
CREATE INDEX index_identities_on_user_id ON identities USING btree (user_id);
+CREATE UNIQUE INDEX index_im_oncall_schedules_on_project_id_and_iid ON incident_management_oncall_schedules USING btree (project_id, iid);
+
CREATE UNIQUE INDEX index_import_export_uploads_on_group_id ON import_export_uploads USING btree (group_id) WHERE (group_id IS NOT NULL);
CREATE INDEX index_import_export_uploads_on_project_id ON import_export_uploads USING btree (project_id);
@@ -8809,7 +22113,29 @@ CREATE INDEX index_import_export_uploads_on_updated_at ON import_export_uploads
CREATE INDEX index_import_failures_on_correlation_id_value ON import_failures USING btree (correlation_id_value);
-CREATE INDEX index_import_failures_on_project_id ON import_failures USING btree (project_id);
+CREATE INDEX index_import_failures_on_group_id_not_null ON import_failures USING btree (group_id) WHERE (group_id IS NOT NULL);
+
+CREATE INDEX index_import_failures_on_project_id_and_correlation_id_value ON import_failures USING btree (project_id, correlation_id_value) WHERE (retry_count = 0);
+
+CREATE INDEX index_import_failures_on_project_id_not_null ON import_failures USING btree (project_id) WHERE (project_id IS NOT NULL);
+
+CREATE INDEX index_imported_projects_on_import_type_creator_id_created_at ON projects USING btree (import_type, creator_id, created_at) WHERE (import_type IS NOT NULL);
+
+CREATE INDEX index_inc_mgmnt_oncall_participants_on_oncall_rotation_id ON incident_management_oncall_participants USING btree (oncall_rotation_id);
+
+CREATE INDEX index_inc_mgmnt_oncall_participants_on_oncall_user_id ON incident_management_oncall_participants USING btree (user_id);
+
+CREATE UNIQUE INDEX index_inc_mgmnt_oncall_participants_on_user_id_and_rotation_id ON incident_management_oncall_participants USING btree (user_id, oncall_rotation_id);
+
+CREATE UNIQUE INDEX index_inc_mgmnt_oncall_rotations_on_oncall_schedule_id_and_id ON incident_management_oncall_rotations USING btree (oncall_schedule_id, id);
+
+CREATE UNIQUE INDEX index_inc_mgmnt_oncall_rotations_on_oncall_schedule_id_and_name ON incident_management_oncall_rotations USING btree (oncall_schedule_id, name);
+
+CREATE INDEX index_incident_management_oncall_schedules_on_project_id ON incident_management_oncall_schedules USING btree (project_id);
+
+CREATE INDEX index_incident_management_oncall_shifts_on_participant_id ON incident_management_oncall_shifts USING btree (participant_id);
+
+CREATE INDEX index_incident_management_oncall_shifts_on_rotation_id ON incident_management_oncall_shifts USING btree (rotation_id);
CREATE UNIQUE INDEX index_index_statuses_on_project_id ON index_statuses USING btree (project_id);
@@ -8827,10 +22153,16 @@ CREATE UNIQUE INDEX index_internal_ids_on_usage_and_project_id ON internal_ids U
CREATE INDEX index_ip_restrictions_on_group_id ON ip_restrictions USING btree (group_id);
-CREATE UNIQUE INDEX index_issue_assignees_on_issue_id_and_user_id ON issue_assignees USING btree (issue_id, user_id);
+CREATE INDEX index_issuable_metric_images_on_issue_id ON issuable_metric_images USING btree (issue_id);
+
+CREATE UNIQUE INDEX index_issuable_severities_on_issue_id ON issuable_severities USING btree (issue_id);
+
+CREATE UNIQUE INDEX index_issuable_slas_on_issue_id ON issuable_slas USING btree (issue_id);
CREATE INDEX index_issue_assignees_on_user_id ON issue_assignees USING btree (user_id);
+CREATE UNIQUE INDEX index_issue_email_participants_on_issue_id_and_lower_email ON issue_email_participants USING btree (issue_id, lower(email));
+
CREATE INDEX index_issue_links_on_source_id ON issue_links USING btree (source_id);
CREATE UNIQUE INDEX index_issue_links_on_source_id_and_target_id ON issue_links USING btree (source_id, target_id);
@@ -8841,11 +22173,7 @@ CREATE INDEX index_issue_metrics ON issue_metrics USING btree (issue_id);
CREATE INDEX index_issue_metrics_on_issue_id_and_timestamps ON issue_metrics USING btree (issue_id, first_mentioned_in_commit_at, first_associated_with_milestone_at, first_added_to_board_at);
-CREATE UNIQUE INDEX index_issue_milestones_on_issue_id ON issue_milestones USING btree (issue_id);
-
-CREATE UNIQUE INDEX index_issue_milestones_on_issue_id_and_milestone_id ON issue_milestones USING btree (issue_id, milestone_id);
-
-CREATE INDEX index_issue_milestones_on_milestone_id ON issue_milestones USING btree (milestone_id);
+CREATE INDEX index_issue_on_project_id_state_id_and_blocking_issues_count ON issues USING btree (project_id, state_id, blocking_issues_count);
CREATE INDEX index_issue_tracker_data_on_service_id ON issue_tracker_data USING btree (service_id);
@@ -8853,6 +22181,8 @@ CREATE UNIQUE INDEX index_issue_user_mentions_on_note_id ON issue_user_mentions
CREATE INDEX index_issues_on_author_id ON issues USING btree (author_id);
+CREATE INDEX index_issues_on_author_id_and_id_and_created_at ON issues USING btree (author_id, id, created_at);
+
CREATE INDEX index_issues_on_closed_by_id ON issues USING btree (closed_by_id);
CREATE INDEX index_issues_on_confidential ON issues USING btree (confidential);
@@ -8861,23 +22191,27 @@ CREATE INDEX index_issues_on_description_trigram ON issues USING gin (descriptio
CREATE INDEX index_issues_on_duplicated_to_id ON issues USING btree (duplicated_to_id) WHERE (duplicated_to_id IS NOT NULL);
+CREATE INDEX index_issues_on_incident_issue_type ON issues USING btree (issue_type) WHERE (issue_type = 1);
+
+CREATE INDEX index_issues_on_last_edited_by_id ON issues USING btree (last_edited_by_id);
+
+CREATE INDEX index_issues_on_lock_version ON issues USING btree (lock_version) WHERE (lock_version IS NULL);
+
CREATE INDEX index_issues_on_milestone_id ON issues USING btree (milestone_id);
CREATE INDEX index_issues_on_moved_to_id ON issues USING btree (moved_to_id) WHERE (moved_to_id IS NOT NULL);
-CREATE INDEX index_issues_on_project_id_and_created_at_and_id_and_state ON issues USING btree (project_id, created_at, id, state);
+CREATE INDEX index_issues_on_project_id_and_closed_at ON issues USING btree (project_id, closed_at);
-CREATE UNIQUE INDEX index_issues_on_project_id_and_iid ON issues USING btree (project_id, iid);
+CREATE INDEX index_issues_on_project_id_and_created_at_issue_type_incident ON issues USING btree (project_id, created_at) WHERE (issue_type = 1);
-CREATE INDEX index_issues_on_project_id_and_rel_position_and_state_and_id ON issues USING btree (project_id, relative_position, state, id DESC);
+CREATE UNIQUE INDEX index_issues_on_project_id_and_external_key ON issues USING btree (project_id, external_key) WHERE (external_key IS NOT NULL);
-CREATE INDEX index_issues_on_project_id_and_updated_at_and_id_and_state ON issues USING btree (project_id, updated_at, id, state);
+CREATE UNIQUE INDEX index_issues_on_project_id_and_iid ON issues USING btree (project_id, iid);
CREATE INDEX index_issues_on_promoted_to_epic_id ON issues USING btree (promoted_to_epic_id) WHERE (promoted_to_epic_id IS NOT NULL);
-CREATE INDEX index_issues_on_relative_position ON issues USING btree (relative_position);
-
-CREATE INDEX index_issues_on_state ON issues USING btree (state);
+CREATE INDEX index_issues_on_sprint_id ON issues USING btree (sprint_id);
CREATE INDEX index_issues_on_title_trigram ON issues USING gin (title gin_trgm_ops);
@@ -8889,19 +22223,27 @@ CREATE UNIQUE INDEX index_jira_connect_installations_on_client_key ON jira_conne
CREATE INDEX index_jira_connect_subscriptions_on_namespace_id ON jira_connect_subscriptions USING btree (namespace_id);
+CREATE INDEX index_jira_imports_on_label_id ON jira_imports USING btree (label_id);
+
+CREATE INDEX index_jira_imports_on_project_id_and_jira_project_key ON jira_imports USING btree (project_id, jira_project_key);
+
+CREATE INDEX index_jira_imports_on_user_id ON jira_imports USING btree (user_id);
+
CREATE INDEX index_jira_tracker_data_on_service_id ON jira_tracker_data USING btree (service_id);
CREATE UNIQUE INDEX index_keys_on_fingerprint ON keys USING btree (fingerprint);
CREATE INDEX index_keys_on_fingerprint_sha256 ON keys USING btree (fingerprint_sha256);
+CREATE INDEX index_keys_on_id_and_ldap_key_type ON keys USING btree (id) WHERE ((type)::text = 'LDAPKey'::text);
+
CREATE INDEX index_keys_on_last_used_at ON keys USING btree (last_used_at DESC NULLS LAST);
CREATE INDEX index_keys_on_user_id ON keys USING btree (user_id);
CREATE UNIQUE INDEX index_kubernetes_namespaces_on_cluster_project_environment_id ON clusters_kubernetes_namespaces USING btree (cluster_id, project_id, environment_id);
-CREATE INDEX index_label_links_on_label_id ON label_links USING btree (label_id);
+CREATE INDEX index_label_links_on_label_id_and_target_type ON label_links USING btree (label_id, target_type);
CREATE INDEX index_label_links_on_target_id_and_target_type ON label_links USING btree (target_id, target_type);
@@ -8913,11 +22255,13 @@ CREATE UNIQUE INDEX index_label_priorities_on_project_id_and_label_id ON label_p
CREATE UNIQUE INDEX index_labels_on_group_id_and_project_id_and_title ON labels USING btree (group_id, project_id, title);
-CREATE INDEX index_labels_on_group_id_and_title ON labels USING btree (group_id, title) WHERE (project_id = NULL::integer);
+CREATE UNIQUE INDEX index_labels_on_group_id_and_title_unique ON labels USING btree (group_id, title) WHERE (project_id IS NULL);
+
+CREATE INDEX index_labels_on_group_id_and_title_with_null_project_id ON labels USING btree (group_id, title) WHERE (project_id IS NULL);
CREATE INDEX index_labels_on_project_id ON labels USING btree (project_id);
-CREATE INDEX index_labels_on_project_id_and_title ON labels USING btree (project_id, title) WHERE (group_id = NULL::integer);
+CREATE UNIQUE INDEX index_labels_on_project_id_and_title_unique ON labels USING btree (project_id, title) WHERE (group_id IS NULL);
CREATE INDEX index_labels_on_template ON labels USING btree (template) WHERE template;
@@ -8935,7 +22279,7 @@ CREATE UNIQUE INDEX index_lfs_objects_on_oid ON lfs_objects USING btree (oid);
CREATE INDEX index_lfs_objects_projects_on_lfs_object_id ON lfs_objects_projects USING btree (lfs_object_id);
-CREATE INDEX index_lfs_objects_projects_on_project_id ON lfs_objects_projects USING btree (project_id);
+CREATE INDEX index_lfs_objects_projects_on_project_id_and_lfs_object_id ON lfs_objects_projects USING btree (project_id, lfs_object_id);
CREATE INDEX index_list_user_preferences_on_list_id ON list_user_preferences USING btree (list_id);
@@ -8945,6 +22289,8 @@ CREATE UNIQUE INDEX index_list_user_preferences_on_user_id_and_list_id ON list_u
CREATE UNIQUE INDEX index_lists_on_board_id_and_label_id ON lists USING btree (board_id, label_id);
+CREATE INDEX index_lists_on_iteration_id ON lists USING btree (iteration_id);
+
CREATE INDEX index_lists_on_label_id ON lists USING btree (label_id);
CREATE INDEX index_lists_on_list_type ON lists USING btree (list_type);
@@ -8967,6 +22313,8 @@ CREATE INDEX index_members_on_source_id_and_source_type ON members USING btree (
CREATE INDEX index_members_on_user_id ON members USING btree (user_id);
+CREATE INDEX index_members_on_user_id_created_at ON members USING btree (user_id, created_at) WHERE ((ldap = true) AND ((type)::text = 'GroupMember'::text) AND ((source_type)::text = 'Namespace'::text));
+
CREATE INDEX index_merge_request_assignees_on_merge_request_id ON merge_request_assignees USING btree (merge_request_id);
CREATE UNIQUE INDEX index_merge_request_assignees_on_merge_request_id_and_user_id ON merge_request_assignees USING btree (merge_request_id, user_id);
@@ -8975,19 +22323,19 @@ CREATE INDEX index_merge_request_assignees_on_user_id ON merge_request_assignees
CREATE INDEX index_merge_request_blocks_on_blocked_merge_request_id ON merge_request_blocks USING btree (blocked_merge_request_id);
-CREATE INDEX index_merge_request_context_commits_on_merge_request_id ON merge_request_context_commits USING btree (merge_request_id);
+CREATE UNIQUE INDEX index_merge_request_cleanup_schedules_on_merge_request_id ON merge_request_cleanup_schedules USING btree (merge_request_id);
-CREATE UNIQUE INDEX index_merge_request_diff_commits_on_mr_diff_id_and_order ON merge_request_diff_commits USING btree (merge_request_diff_id, relative_order);
+CREATE INDEX index_merge_request_context_commits_on_merge_request_id ON merge_request_context_commits USING btree (merge_request_id);
CREATE INDEX index_merge_request_diff_commits_on_sha ON merge_request_diff_commits USING btree (sha);
-CREATE UNIQUE INDEX index_merge_request_diff_files_on_mr_diff_id_and_order ON merge_request_diff_files USING btree (merge_request_diff_id, relative_order);
+CREATE INDEX index_merge_request_diff_details_on_merge_request_diff_id ON merge_request_diff_details USING btree (merge_request_diff_id);
-CREATE INDEX index_merge_request_diffs_on_merge_request_id_and_id ON merge_request_diffs USING btree (merge_request_id, id);
+CREATE INDEX index_merge_request_diffs_by_id_partial ON merge_request_diffs USING btree (id) WHERE ((files_count > 0) AND ((NOT stored_externally) OR (stored_externally IS NULL)));
-CREATE INDEX index_merge_request_diffs_on_merge_request_id_and_id_partial ON merge_request_diffs USING btree (merge_request_id, id) WHERE ((NOT stored_externally) OR (stored_externally IS NULL));
+CREATE INDEX index_merge_request_diffs_on_external_diff_store ON merge_request_diffs USING btree (external_diff_store);
-CREATE INDEX index_merge_request_metrics ON merge_request_metrics USING btree (merge_request_id);
+CREATE INDEX index_merge_request_diffs_on_merge_request_id_and_id ON merge_request_diffs USING btree (merge_request_id, id);
CREATE INDEX index_merge_request_metrics_on_first_deployed_to_production_at ON merge_request_metrics USING btree (first_deployed_to_production_at);
@@ -9003,9 +22351,11 @@ CREATE INDEX index_merge_request_metrics_on_merged_by_id ON merge_request_metric
CREATE INDEX index_merge_request_metrics_on_pipeline_id ON merge_request_metrics USING btree (pipeline_id);
-CREATE UNIQUE INDEX index_merge_request_milestones_on_merge_request_id ON merge_request_milestones USING btree (merge_request_id);
+CREATE INDEX index_merge_request_metrics_on_target_project_id ON merge_request_metrics USING btree (target_project_id);
-CREATE INDEX index_merge_request_milestones_on_milestone_id ON merge_request_milestones USING btree (milestone_id);
+CREATE UNIQUE INDEX index_merge_request_reviewers_on_merge_request_id_and_user_id ON merge_request_reviewers USING btree (merge_request_id, user_id);
+
+CREATE INDEX index_merge_request_reviewers_on_user_id ON merge_request_reviewers USING btree (user_id);
CREATE UNIQUE INDEX index_merge_request_user_mentions_on_note_id ON merge_request_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
@@ -9023,30 +22373,34 @@ CREATE INDEX index_merge_requests_on_description_trigram ON merge_requests USING
CREATE INDEX index_merge_requests_on_head_pipeline_id ON merge_requests USING btree (head_pipeline_id);
-CREATE INDEX index_merge_requests_on_id_and_merge_jid ON merge_requests USING btree (id, merge_jid) WHERE ((merge_jid IS NOT NULL) AND ((state)::text = 'locked'::text));
-
CREATE INDEX index_merge_requests_on_latest_merge_request_diff_id ON merge_requests USING btree (latest_merge_request_diff_id);
+CREATE INDEX index_merge_requests_on_lock_version ON merge_requests USING btree (lock_version) WHERE (lock_version IS NULL);
+
CREATE INDEX index_merge_requests_on_merge_user_id ON merge_requests USING btree (merge_user_id) WHERE (merge_user_id IS NOT NULL);
CREATE INDEX index_merge_requests_on_milestone_id ON merge_requests USING btree (milestone_id);
CREATE INDEX index_merge_requests_on_source_branch ON merge_requests USING btree (source_branch);
-CREATE INDEX index_merge_requests_on_source_project_and_branch_state_opened ON merge_requests USING btree (source_project_id, source_branch) WHERE ((state)::text = 'opened'::text);
-
CREATE INDEX index_merge_requests_on_source_project_id_and_source_branch ON merge_requests USING btree (source_project_id, source_branch);
-CREATE INDEX index_merge_requests_on_state_and_merge_status ON merge_requests USING btree (state, merge_status) WHERE (((state)::text = 'opened'::text) AND ((merge_status)::text = 'can_be_merged'::text));
+CREATE INDEX index_merge_requests_on_sprint_id ON merge_requests USING btree (sprint_id);
CREATE INDEX index_merge_requests_on_target_branch ON merge_requests USING btree (target_branch);
+CREATE INDEX index_merge_requests_on_target_project_id_and_created_at_and_id ON merge_requests USING btree (target_project_id, created_at, id);
+
CREATE UNIQUE INDEX index_merge_requests_on_target_project_id_and_iid ON merge_requests USING btree (target_project_id, iid);
-CREATE INDEX index_merge_requests_on_target_project_id_and_iid_opened ON merge_requests USING btree (target_project_id, iid) WHERE ((state)::text = 'opened'::text);
+CREATE INDEX index_merge_requests_on_target_project_id_and_iid_and_state_id ON merge_requests USING btree (target_project_id, iid, state_id);
+
+CREATE INDEX index_merge_requests_on_target_project_id_and_iid_jira_title ON merge_requests USING btree (target_project_id, iid) WHERE ((title)::text ~ '[A-Z][A-Z_0-9]+-\d+'::text);
CREATE INDEX index_merge_requests_on_target_project_id_and_target_branch ON merge_requests USING btree (target_project_id, target_branch) WHERE ((state_id = 1) AND (merge_when_pipeline_succeeds = true));
+CREATE INDEX index_merge_requests_on_target_project_id_iid_jira_description ON merge_requests USING btree (target_project_id, iid) WHERE (description ~ '[A-Z][A-Z_0-9]+-\d+'::text);
+
CREATE INDEX index_merge_requests_on_title ON merge_requests USING btree (title);
CREATE INDEX index_merge_requests_on_title_trigram ON merge_requests USING gin (title gin_trgm_ops);
@@ -9055,14 +22409,20 @@ CREATE INDEX index_merge_requests_on_tp_id_and_merge_commit_sha_and_id ON merge_
CREATE INDEX index_merge_requests_on_updated_by_id ON merge_requests USING btree (updated_by_id) WHERE (updated_by_id IS NOT NULL);
-CREATE INDEX index_merge_requests_target_project_id_created_at ON merge_requests USING btree (target_project_id, created_at);
-
CREATE UNIQUE INDEX index_merge_trains_on_merge_request_id ON merge_trains USING btree (merge_request_id);
CREATE INDEX index_merge_trains_on_pipeline_id ON merge_trains USING btree (pipeline_id);
CREATE INDEX index_merge_trains_on_user_id ON merge_trains USING btree (user_id);
+CREATE INDEX index_metrics_dashboard_annotations_on_cluster_id_and_3_columns ON metrics_dashboard_annotations USING btree (cluster_id, dashboard_path, starting_at, ending_at) WHERE (cluster_id IS NOT NULL);
+
+CREATE INDEX index_metrics_dashboard_annotations_on_environment_id_and_3_col ON metrics_dashboard_annotations USING btree (environment_id, dashboard_path, starting_at, ending_at) WHERE (environment_id IS NOT NULL);
+
+CREATE INDEX index_metrics_dashboard_annotations_on_timespan_end ON metrics_dashboard_annotations USING btree (COALESCE(ending_at, starting_at));
+
+CREATE INDEX index_metrics_users_starred_dashboards_on_project_id ON metrics_users_starred_dashboards USING btree (project_id);
+
CREATE INDEX index_milestone_releases_on_release_id ON milestone_releases USING btree (release_id);
CREATE INDEX index_milestones_on_description_trigram ON milestones USING gin (description gin_trgm_ops);
@@ -9077,18 +22437,22 @@ CREATE INDEX index_milestones_on_title ON milestones USING btree (title);
CREATE INDEX index_milestones_on_title_trigram ON milestones USING gin (title gin_trgm_ops);
-CREATE UNIQUE INDEX index_miletone_releases_on_milestone_and_release ON milestone_releases USING btree (milestone_id, release_id);
-
CREATE INDEX index_mirror_data_on_next_execution_and_retry_count ON project_mirror_data USING btree (next_execution_timestamp, retry_count);
CREATE UNIQUE INDEX index_mr_blocks_on_blocking_and_blocked_mr_ids ON merge_request_blocks USING btree (blocking_merge_request_id, blocked_merge_request_id);
+CREATE INDEX index_mr_cleanup_schedules_timestamps ON merge_request_cleanup_schedules USING btree (scheduled_at) WHERE (completed_at IS NULL);
+
CREATE UNIQUE INDEX index_mr_context_commits_on_merge_request_id_and_sha ON merge_request_context_commits USING btree (merge_request_id, sha);
-CREATE UNIQUE INDEX index_mrs_milestones_on_mr_id_and_milestone_id ON merge_request_milestones USING btree (merge_request_id, milestone_id);
+CREATE INDEX index_mr_metrics_on_target_project_id_merged_at_nulls_last ON merge_request_metrics USING btree (target_project_id, merged_at DESC NULLS LAST, id DESC);
+
+CREATE INDEX index_mr_metrics_on_target_project_id_merged_at_time_to_merge ON merge_request_metrics USING btree (target_project_id, merged_at, created_at) WHERE (merged_at > created_at);
CREATE UNIQUE INDEX index_namespace_aggregation_schedules_on_namespace_id ON namespace_aggregation_schedules USING btree (namespace_id);
+CREATE INDEX index_namespace_onboarding_actions_on_namespace_id ON namespace_onboarding_actions USING btree (namespace_id);
+
CREATE UNIQUE INDEX index_namespace_root_storage_statistics_on_namespace_id ON namespace_root_storage_statistics USING btree (namespace_id);
CREATE UNIQUE INDEX index_namespace_statistics_on_namespace_id ON namespace_statistics USING btree (namespace_id);
@@ -9115,7 +22479,7 @@ CREATE INDEX index_namespaces_on_path ON namespaces USING btree (path);
CREATE INDEX index_namespaces_on_path_trigram ON namespaces USING gin (path gin_trgm_ops);
-CREATE INDEX index_namespaces_on_plan_id ON namespaces USING btree (plan_id);
+CREATE UNIQUE INDEX index_namespaces_on_push_rule_id ON namespaces USING btree (push_rule_id);
CREATE INDEX index_namespaces_on_require_two_factor_authentication ON namespaces USING btree (require_two_factor_authentication);
@@ -9125,13 +22489,13 @@ CREATE UNIQUE INDEX index_namespaces_on_runners_token_encrypted ON namespaces US
CREATE INDEX index_namespaces_on_shared_and_extra_runners_minutes_limit ON namespaces USING btree (shared_runners_minutes_limit, extra_shared_runners_minutes_limit);
-CREATE INDEX index_namespaces_on_trial_ends_on ON namespaces USING btree (trial_ends_on) WHERE (trial_ends_on IS NOT NULL);
+CREATE INDEX index_namespaces_on_type_and_id_partial ON namespaces USING btree (type, id) WHERE (type IS NOT NULL);
-CREATE INDEX index_namespaces_on_type_partial ON namespaces USING btree (type) WHERE (type IS NOT NULL);
+CREATE INDEX index_non_requested_project_members_on_source_id_and_type ON members USING btree (source_id, source_type) WHERE ((requested_at IS NULL) AND ((type)::text = 'ProjectMember'::text));
CREATE UNIQUE INDEX index_note_diff_files_on_diff_note_id ON note_diff_files USING btree (diff_note_id);
-CREATE INDEX index_notes_on_author_id ON notes USING btree (author_id);
+CREATE INDEX index_notes_on_author_id_and_created_at_and_id ON notes USING btree (author_id, created_at, id);
CREATE INDEX index_notes_on_commit_id ON notes USING btree (commit_id);
@@ -9143,7 +22507,7 @@ CREATE INDEX index_notes_on_line_code ON notes USING btree (line_code);
CREATE INDEX index_notes_on_note_trigram ON notes USING gin (note gin_trgm_ops);
-CREATE INDEX index_notes_on_noteable_id_and_noteable_type ON notes USING btree (noteable_id, noteable_type);
+CREATE INDEX index_notes_on_noteable_id_and_noteable_type_and_system ON notes USING btree (noteable_id, noteable_type, system);
CREATE INDEX index_notes_on_project_id_and_id_and_system_false ON notes USING btree (project_id, id) WHERE (NOT system);
@@ -9157,6 +22521,8 @@ CREATE INDEX index_notification_settings_on_user_id ON notification_settings USI
CREATE UNIQUE INDEX index_notifications_on_user_id_and_source_id_and_source_type ON notification_settings USING btree (user_id, source_id, source_type);
+CREATE INDEX index_oauth_access_grants_on_resource_owner_id ON oauth_access_grants USING btree (resource_owner_id, application_id, created_at);
+
CREATE UNIQUE INDEX index_oauth_access_grants_on_token ON oauth_access_grants USING btree (token);
CREATE INDEX index_oauth_access_tokens_on_application_id ON oauth_access_tokens USING btree (application_id);
@@ -9175,43 +22541,137 @@ CREATE INDEX index_oauth_openid_requests_on_access_grant_id ON oauth_openid_requ
CREATE UNIQUE INDEX index_on_deploy_keys_id_and_type_and_public ON keys USING btree (id, type) WHERE (public = true);
+CREATE INDEX index_on_id_partial_with_legacy_storage ON projects USING btree (id) WHERE ((storage_version < 2) OR (storage_version IS NULL));
+
CREATE INDEX index_on_identities_lower_extern_uid_and_provider ON identities USING btree (lower((extern_uid)::text), provider);
+CREATE UNIQUE INDEX index_on_instance_statistics_recorded_at_and_identifier ON analytics_instance_statistics_measurements USING btree (identifier, recorded_at);
+
+CREATE INDEX index_on_label_links_all_columns ON label_links USING btree (target_id, label_id, target_type);
+
+CREATE INDEX index_on_namespaces_lower_name ON namespaces USING btree (lower((name)::text));
+
+CREATE INDEX index_on_namespaces_lower_path ON namespaces USING btree (lower((path)::text));
+
+CREATE INDEX index_on_projects_lower_path ON projects USING btree (lower((path)::text));
+
+CREATE INDEX index_on_routes_lower_path ON routes USING btree (lower((path)::text));
+
+CREATE UNIQUE INDEX index_on_segment_selections_group_id_segment_id ON analytics_devops_adoption_segment_selections USING btree (group_id, segment_id);
+
+CREATE UNIQUE INDEX index_on_segment_selections_project_id_segment_id ON analytics_devops_adoption_segment_selections USING btree (project_id, segment_id);
+
+CREATE INDEX index_on_segment_selections_segment_id ON analytics_devops_adoption_segment_selections USING btree (segment_id);
+
+CREATE INDEX index_on_snapshots_segment_id_recorded_at ON analytics_devops_adoption_snapshots USING btree (segment_id, recorded_at);
+
+CREATE INDEX index_on_users_lower_email ON users USING btree (lower((email)::text));
+
+CREATE INDEX index_on_users_lower_username ON users USING btree (lower((username)::text));
+
CREATE INDEX index_on_users_name_lower ON users USING btree (lower((name)::text));
+CREATE INDEX index_open_project_tracker_data_on_service_id ON open_project_tracker_data USING btree (service_id);
+
+CREATE INDEX index_operations_feature_flags_issues_on_issue_id ON operations_feature_flags_issues USING btree (issue_id);
+
+CREATE UNIQUE INDEX index_operations_feature_flags_on_project_id_and_iid ON operations_feature_flags USING btree (project_id, iid);
+
CREATE UNIQUE INDEX index_operations_feature_flags_on_project_id_and_name ON operations_feature_flags USING btree (project_id, name);
-CREATE UNIQUE INDEX index_packages_build_infos_on_package_id ON packages_build_infos USING btree (package_id);
+CREATE UNIQUE INDEX index_operations_scopes_on_strategy_id_and_environment_scope ON operations_scopes USING btree (strategy_id, environment_scope);
+
+CREATE INDEX index_operations_strategies_on_feature_flag_id ON operations_strategies USING btree (feature_flag_id);
+
+CREATE INDEX index_operations_strategies_user_lists_on_user_list_id ON operations_strategies_user_lists USING btree (user_list_id);
+
+CREATE UNIQUE INDEX index_operations_user_lists_on_project_id_and_iid ON operations_user_lists USING btree (project_id, iid);
+
+CREATE UNIQUE INDEX index_operations_user_lists_on_project_id_and_name ON operations_user_lists USING btree (project_id, name);
+
+CREATE UNIQUE INDEX index_ops_feature_flags_issues_on_feature_flag_id_and_issue_id ON operations_feature_flags_issues USING btree (feature_flag_id, issue_id);
+
+CREATE UNIQUE INDEX index_ops_strategies_user_lists_on_strategy_id_and_user_list_id ON operations_strategies_user_lists USING btree (strategy_id, user_list_id);
CREATE INDEX index_packages_build_infos_on_pipeline_id ON packages_build_infos USING btree (pipeline_id);
+CREATE UNIQUE INDEX index_packages_composer_metadata_on_package_id_and_target_sha ON packages_composer_metadata USING btree (package_id, target_sha);
+
CREATE UNIQUE INDEX index_packages_conan_file_metadata_on_package_file_id ON packages_conan_file_metadata USING btree (package_file_id);
-CREATE UNIQUE INDEX index_packages_conan_metadata_on_package_id ON packages_conan_metadata USING btree (package_id);
+CREATE UNIQUE INDEX index_packages_conan_metadata_on_package_id_username_channel ON packages_conan_metadata USING btree (package_id, package_username, package_channel);
+
+CREATE INDEX index_packages_debian_group_component_files_on_component_id ON packages_debian_group_component_files USING btree (component_id);
+
+CREATE INDEX index_packages_debian_group_distributions_on_creator_id ON packages_debian_group_distributions USING btree (creator_id);
+
+CREATE INDEX index_packages_debian_group_distributions_on_group_id ON packages_debian_group_distributions USING btree (group_id);
+
+CREATE INDEX index_packages_debian_project_component_files_on_component_id ON packages_debian_project_component_files USING btree (component_id);
+
+CREATE INDEX index_packages_debian_project_distributions_on_creator_id ON packages_debian_project_distributions USING btree (creator_id);
+
+CREATE INDEX index_packages_debian_project_distributions_on_project_id ON packages_debian_project_distributions USING btree (project_id);
+
+CREATE INDEX index_packages_debian_publications_on_distribution_id ON packages_debian_publications USING btree (distribution_id);
+
+CREATE UNIQUE INDEX index_packages_debian_publications_on_package_id ON packages_debian_publications USING btree (package_id);
CREATE UNIQUE INDEX index_packages_dependencies_on_name_and_version_pattern ON packages_dependencies USING btree (name, version_pattern);
CREATE INDEX index_packages_dependency_links_on_dependency_id ON packages_dependency_links USING btree (dependency_id);
+CREATE INDEX index_packages_events_on_package_id ON packages_events USING btree (package_id);
+
CREATE INDEX index_packages_maven_metadata_on_package_id_and_path ON packages_maven_metadata USING btree (package_id, path);
+CREATE INDEX index_packages_nuget_dl_metadata_on_dependency_link_id ON packages_nuget_dependency_link_metadata USING btree (dependency_link_id);
+
+CREATE UNIQUE INDEX index_packages_on_project_id_name_version_unique_when_generic ON packages_packages USING btree (project_id, name, version) WHERE (package_type = 7);
+
+CREATE INDEX index_packages_package_file_build_infos_on_package_file_id ON packages_package_file_build_infos USING btree (package_file_id);
+
+CREATE INDEX index_packages_package_file_build_infos_on_pipeline_id ON packages_package_file_build_infos USING btree (pipeline_id);
+
+CREATE INDEX index_packages_package_files_on_file_store ON packages_package_files USING btree (file_store);
+
CREATE INDEX index_packages_package_files_on_package_id_and_file_name ON packages_package_files USING btree (package_id, file_name);
+CREATE INDEX index_packages_package_files_on_verification_state ON packages_package_files USING btree (verification_state);
+
+CREATE INDEX index_packages_packages_on_creator_id ON packages_packages USING btree (creator_id);
+
+CREATE INDEX index_packages_packages_on_id_and_created_at ON packages_packages USING btree (id, created_at);
+
CREATE INDEX index_packages_packages_on_name_trigram ON packages_packages USING gin (name gin_trgm_ops);
-CREATE INDEX index_packages_packages_on_project_id ON packages_packages USING btree (project_id);
+CREATE INDEX index_packages_packages_on_project_id_and_created_at ON packages_packages USING btree (project_id, created_at);
+
+CREATE INDEX index_packages_packages_on_project_id_and_package_type ON packages_packages USING btree (project_id, package_type);
+
+CREATE INDEX index_packages_packages_on_project_id_and_version ON packages_packages USING btree (project_id, version);
+
+CREATE INDEX index_packages_project_id_name_partial_for_nuget ON packages_packages USING btree (project_id, name) WHERE (((name)::text <> 'NuGet.Temporary.Package'::text) AND (version IS NOT NULL) AND (package_type = 4));
CREATE INDEX index_packages_tags_on_package_id ON packages_tags USING btree (package_id);
+CREATE INDEX index_packages_tags_on_package_id_and_updated_at ON packages_tags USING btree (package_id, updated_at DESC);
+
+CREATE INDEX index_pages_deployments_on_ci_build_id ON pages_deployments USING btree (ci_build_id);
+
+CREATE INDEX index_pages_deployments_on_project_id ON pages_deployments USING btree (project_id);
+
CREATE INDEX index_pages_domain_acme_orders_on_challenge_token ON pages_domain_acme_orders USING btree (challenge_token);
CREATE INDEX index_pages_domain_acme_orders_on_pages_domain_id ON pages_domain_acme_orders USING btree (pages_domain_id);
-CREATE INDEX index_pages_domains_need_auto_ssl_renewal ON pages_domains USING btree (certificate_source, certificate_valid_not_after) WHERE (auto_ssl_enabled = true);
+CREATE INDEX index_pages_domains_need_auto_ssl_renewal_user_provided ON pages_domains USING btree (id) WHERE ((auto_ssl_enabled = true) AND (auto_ssl_failed = false) AND (certificate_source = 0));
-CREATE UNIQUE INDEX index_pages_domains_on_domain ON pages_domains USING btree (domain);
+CREATE INDEX index_pages_domains_need_auto_ssl_renewal_valid_not_after ON pages_domains USING btree (certificate_valid_not_after) WHERE ((auto_ssl_enabled = true) AND (auto_ssl_failed = false));
-CREATE INDEX index_pages_domains_on_domain_type ON pages_domains USING btree (domain_type);
+CREATE UNIQUE INDEX index_pages_domains_on_domain_and_wildcard ON pages_domains USING btree (domain, wildcard);
+
+CREATE INDEX index_pages_domains_on_domain_lowercase ON pages_domains USING btree (lower((domain)::text));
CREATE INDEX index_pages_domains_on_project_id ON pages_domains USING btree (project_id);
@@ -9219,12 +22679,22 @@ CREATE INDEX index_pages_domains_on_project_id_and_enabled_until ON pages_domain
CREATE INDEX index_pages_domains_on_remove_at ON pages_domains USING btree (remove_at);
+CREATE INDEX index_pages_domains_on_scope ON pages_domains USING btree (scope);
+
+CREATE INDEX index_pages_domains_on_usage ON pages_domains USING btree (usage);
+
CREATE INDEX index_pages_domains_on_verified_at ON pages_domains USING btree (verified_at);
CREATE INDEX index_pages_domains_on_verified_at_and_enabled_until ON pages_domains USING btree (verified_at, enabled_until);
CREATE INDEX index_pages_domains_on_wildcard ON pages_domains USING btree (wildcard);
+CREATE UNIQUE INDEX index_partial_am_alerts_on_project_id_and_fingerprint ON alert_management_alerts USING btree (project_id, fingerprint) WHERE (status <> 2);
+
+CREATE INDEX index_partial_ci_builds_on_user_id_name_parser_features ON ci_builds USING btree (user_id, name) WHERE (((type)::text = 'Ci::Build'::text) AND ((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('license_scanning'::character varying)::text, ('sast'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('secret_detection'::character varying)::text])));
+
+CREATE UNIQUE INDEX index_partitioned_foreign_keys_unique_index ON partitioned_foreign_keys USING btree (to_table, from_table, from_column);
+
CREATE INDEX index_pat_on_user_id_and_expires_at ON personal_access_tokens USING btree (user_id, expires_at);
CREATE INDEX index_path_locks_on_path ON path_locks USING btree (path);
@@ -9239,7 +22709,7 @@ CREATE INDEX index_personal_access_tokens_on_user_id ON personal_access_tokens U
CREATE UNIQUE INDEX index_plan_limits_on_plan_id ON plan_limits USING btree (plan_id);
-CREATE INDEX index_plans_on_name ON plans USING btree (name);
+CREATE UNIQUE INDEX index_plans_on_name ON plans USING btree (name);
CREATE UNIQUE INDEX index_pool_repositories_on_disk_path ON pool_repositories USING btree (disk_path);
@@ -9247,20 +22717,26 @@ CREATE INDEX index_pool_repositories_on_shard_id ON pool_repositories USING btre
CREATE UNIQUE INDEX index_pool_repositories_on_source_project_id_and_shard_id ON pool_repositories USING btree (source_project_id, shard_id);
+CREATE INDEX index_postgres_reindex_actions_on_index_identifier ON postgres_reindex_actions USING btree (index_identifier);
+
CREATE UNIQUE INDEX index_programming_languages_on_name ON programming_languages USING btree (name);
+CREATE INDEX index_project_access_tokens_on_project_id ON project_access_tokens USING btree (project_id);
+
CREATE UNIQUE INDEX index_project_aliases_on_name ON project_aliases USING btree (name);
CREATE INDEX index_project_aliases_on_project_id ON project_aliases USING btree (project_id);
CREATE INDEX index_project_authorizations_on_project_id ON project_authorizations USING btree (project_id);
-CREATE UNIQUE INDEX index_project_authorizations_on_user_id_project_id_access_level ON project_authorizations USING btree (user_id, project_id, access_level);
-
CREATE UNIQUE INDEX index_project_auto_devops_on_project_id ON project_auto_devops USING btree (project_id);
CREATE UNIQUE INDEX index_project_ci_cd_settings_on_project_id ON project_ci_cd_settings USING btree (project_id);
+CREATE INDEX index_project_compliance_framework_settings_on_framework_id ON project_compliance_framework_settings USING btree (framework_id);
+
+CREATE INDEX index_project_compliance_framework_settings_on_project_id ON project_compliance_framework_settings USING btree (project_id);
+
CREATE INDEX index_project_custom_attributes_on_key_and_value ON project_custom_attributes USING btree (key, value);
CREATE UNIQUE INDEX index_project_custom_attributes_on_project_id_and_key ON project_custom_attributes USING btree (project_id, key);
@@ -9271,18 +22747,28 @@ CREATE INDEX index_project_deploy_tokens_on_deploy_token_id ON project_deploy_to
CREATE UNIQUE INDEX index_project_deploy_tokens_on_project_id_and_deploy_token_id ON project_deploy_tokens USING btree (project_id, deploy_token_id);
+CREATE UNIQUE INDEX index_project_export_jobs_on_jid ON project_export_jobs USING btree (jid);
+
+CREATE INDEX index_project_export_jobs_on_project_id_and_jid ON project_export_jobs USING btree (project_id, jid);
+
+CREATE INDEX index_project_export_jobs_on_project_id_and_status ON project_export_jobs USING btree (project_id, status);
+
+CREATE INDEX index_project_export_jobs_on_status ON project_export_jobs USING btree (status);
+
CREATE INDEX index_project_feature_usages_on_project_id ON project_feature_usages USING btree (project_id);
CREATE UNIQUE INDEX index_project_features_on_project_id ON project_features USING btree (project_id);
+CREATE INDEX index_project_features_on_project_id_bal_20 ON project_features USING btree (project_id) WHERE (builds_access_level = 20);
+
+CREATE INDEX index_project_features_on_project_id_ral_20 ON project_features USING btree (project_id) WHERE (repository_access_level = 20);
+
CREATE INDEX index_project_group_links_on_group_id ON project_group_links USING btree (group_id);
CREATE INDEX index_project_group_links_on_project_id ON project_group_links USING btree (project_id);
CREATE INDEX index_project_import_data_on_project_id ON project_import_data USING btree (project_id);
-CREATE INDEX index_project_mirror_data_on_jid ON project_mirror_data USING btree (jid);
-
CREATE INDEX index_project_mirror_data_on_last_successful_update_at ON project_mirror_data USING btree (last_successful_update_at);
CREATE INDEX index_project_mirror_data_on_last_update_at_and_retry_count ON project_mirror_data USING btree (last_update_at, retry_count);
@@ -9291,7 +22777,9 @@ CREATE UNIQUE INDEX index_project_mirror_data_on_project_id ON project_mirror_da
CREATE INDEX index_project_mirror_data_on_status ON project_mirror_data USING btree (status);
-CREATE UNIQUE INDEX index_project_pages_metadata_on_project_id ON project_pages_metadata USING btree (project_id);
+CREATE INDEX index_project_pages_metadata_on_artifacts_archive_id ON project_pages_metadata USING btree (artifacts_archive_id);
+
+CREATE INDEX index_project_pages_metadata_on_pages_deployment_id ON project_pages_metadata USING btree (pages_deployment_id);
CREATE INDEX index_project_pages_metadata_on_project_id_and_deployed_is_true ON project_pages_metadata USING btree (project_id) WHERE (deployed = true);
@@ -9301,23 +22789,75 @@ CREATE UNIQUE INDEX index_project_repositories_on_project_id ON project_reposito
CREATE INDEX index_project_repositories_on_shard_id ON project_repositories USING btree (shard_id);
+CREATE INDEX index_project_repositories_on_shard_id_and_project_id ON project_repositories USING btree (shard_id, project_id);
+
CREATE UNIQUE INDEX index_project_repository_states_on_project_id ON project_repository_states USING btree (project_id);
+CREATE INDEX index_project_repository_storage_moves_on_project_id ON project_repository_storage_moves USING btree (project_id);
+
+CREATE INDEX index_project_settings_on_project_id_partially ON project_settings USING btree (project_id) WHERE (has_vulnerabilities IS TRUE);
+
+CREATE UNIQUE INDEX index_project_settings_on_push_rule_id ON project_settings USING btree (push_rule_id);
+
CREATE INDEX index_project_statistics_on_namespace_id ON project_statistics USING btree (namespace_id);
+CREATE INDEX index_project_statistics_on_packages_size_and_project_id ON project_statistics USING btree (packages_size, project_id);
+
CREATE UNIQUE INDEX index_project_statistics_on_project_id ON project_statistics USING btree (project_id);
+CREATE INDEX index_project_statistics_on_repository_size_and_project_id ON project_statistics USING btree (repository_size, project_id);
+
+CREATE INDEX index_project_statistics_on_storage_size_and_project_id ON project_statistics USING btree (storage_size, project_id);
+
+CREATE INDEX index_project_statistics_on_wiki_size_and_project_id ON project_statistics USING btree (wiki_size, project_id);
+
CREATE UNIQUE INDEX index_project_tracing_settings_on_project_id ON project_tracing_settings USING btree (project_id);
+CREATE INDEX index_projects_aimed_for_deletion ON projects USING btree (marked_for_deletion_at) WHERE ((marked_for_deletion_at IS NOT NULL) AND (pending_delete = false));
+
+CREATE INDEX index_projects_api_created_at_id_desc ON projects USING btree (created_at, id DESC);
+
+CREATE INDEX index_projects_api_created_at_id_for_archived ON projects USING btree (created_at, id) WHERE ((archived = true) AND (pending_delete = false));
+
+CREATE INDEX index_projects_api_created_at_id_for_archived_vis20 ON projects USING btree (created_at, id) WHERE ((archived = true) AND (visibility_level = 20) AND (pending_delete = false));
+
+CREATE INDEX index_projects_api_created_at_id_for_vis10 ON projects USING btree (created_at, id) WHERE ((visibility_level = 10) AND (pending_delete = false));
+
+CREATE INDEX index_projects_api_last_activity_at_id_desc ON projects USING btree (last_activity_at, id DESC);
+
+CREATE INDEX index_projects_api_name_id_desc ON projects USING btree (name, id DESC);
+
+CREATE INDEX index_projects_api_path_id_desc ON projects USING btree (path, id DESC);
+
+CREATE INDEX index_projects_api_updated_at_id_desc ON projects USING btree (updated_at, id DESC);
+
+CREATE INDEX index_projects_api_vis20_created_at ON projects USING btree (created_at, id) WHERE (visibility_level = 20);
+
+CREATE INDEX index_projects_api_vis20_last_activity_at ON projects USING btree (last_activity_at, id) WHERE (visibility_level = 20);
+
+CREATE INDEX index_projects_api_vis20_name ON projects USING btree (name, id) WHERE (visibility_level = 20);
+
+CREATE INDEX index_projects_api_vis20_path ON projects USING btree (path, id) WHERE (visibility_level = 20);
+
+CREATE INDEX index_projects_api_vis20_updated_at ON projects USING btree (updated_at, id) WHERE (visibility_level = 20);
+
CREATE INDEX index_projects_on_created_at_and_id ON projects USING btree (created_at, id);
-CREATE INDEX index_projects_on_creator_id ON projects USING btree (creator_id);
+CREATE INDEX index_projects_on_creator_id_and_created_at_and_id ON projects USING btree (creator_id, created_at, id);
+
+CREATE INDEX index_projects_on_creator_id_and_id ON projects USING btree (creator_id, id);
+
+CREATE INDEX index_projects_on_creator_id_import_type_and_created_at_partial ON projects USING btree (creator_id, import_type, created_at) WHERE (import_type IS NOT NULL);
CREATE INDEX index_projects_on_description_trigram ON projects USING gin (description gin_trgm_ops);
+CREATE INDEX index_projects_on_id_and_archived_and_pending_delete ON projects USING btree (id) WHERE ((archived = false) AND (pending_delete = false));
+
CREATE UNIQUE INDEX index_projects_on_id_partial_for_visibility ON projects USING btree (id) WHERE (visibility_level = ANY (ARRAY[10, 20]));
-CREATE INDEX index_projects_on_last_activity_at ON projects USING btree (last_activity_at);
+CREATE INDEX index_projects_on_id_service_desk_enabled ON projects USING btree (id) WHERE (service_desk_enabled = true);
+
+CREATE INDEX index_projects_on_last_activity_at_and_id ON projects USING btree (last_activity_at, id);
CREATE INDEX index_projects_on_last_repository_check_at ON projects USING btree (last_repository_check_at) WHERE (last_repository_check_at IS NOT NULL);
@@ -9327,21 +22867,23 @@ CREATE INDEX index_projects_on_last_repository_updated_at ON projects USING btre
CREATE INDEX index_projects_on_lower_name ON projects USING btree (lower((name)::text));
-CREATE INDEX index_projects_on_marked_for_deletion_at ON projects USING btree (marked_for_deletion_at) WHERE (marked_for_deletion_at IS NOT NULL);
-
CREATE INDEX index_projects_on_marked_for_deletion_by_user_id ON projects USING btree (marked_for_deletion_by_user_id) WHERE (marked_for_deletion_by_user_id IS NOT NULL);
-CREATE INDEX index_projects_on_mirror_and_mirror_trigger_builds_both_true ON projects USING btree (id) WHERE ((mirror IS TRUE) AND (mirror_trigger_builds IS TRUE));
+CREATE INDEX index_projects_on_mirror_creator_id_created_at ON projects USING btree (creator_id, created_at) WHERE ((mirror = true) AND (mirror_trigger_builds = true));
+
+CREATE INDEX index_projects_on_mirror_id_where_mirror_and_trigger_builds ON projects USING btree (id) WHERE ((mirror = true) AND (mirror_trigger_builds = true));
CREATE INDEX index_projects_on_mirror_last_successful_update_at ON projects USING btree (mirror_last_successful_update_at);
CREATE INDEX index_projects_on_mirror_user_id ON projects USING btree (mirror_user_id);
+CREATE INDEX index_projects_on_name_and_id ON projects USING btree (name, id);
+
CREATE INDEX index_projects_on_name_trigram ON projects USING gin (name gin_trgm_ops);
-CREATE INDEX index_projects_on_namespace_id ON projects USING btree (namespace_id);
+CREATE INDEX index_projects_on_namespace_id_and_id ON projects USING btree (namespace_id, id);
-CREATE INDEX index_projects_on_path ON projects USING btree (path);
+CREATE INDEX index_projects_on_path_and_id ON projects USING btree (path, id);
CREATE INDEX index_projects_on_path_trigram ON projects USING gin (path gin_trgm_ops);
@@ -9357,7 +22899,7 @@ CREATE INDEX index_projects_on_runners_token_encrypted ON projects USING btree (
CREATE INDEX index_projects_on_star_count ON projects USING btree (star_count);
-CREATE INDEX index_projects_on_visibility_level_and_created_at_and_id ON projects USING btree (visibility_level, created_at, id);
+CREATE INDEX index_projects_on_updated_at_and_id ON projects USING btree (updated_at, id);
CREATE UNIQUE INDEX index_prometheus_alert_event_scoped_payload_key ON prometheus_alert_events USING btree (prometheus_alert_id, payload_key);
@@ -9373,7 +22915,9 @@ CREATE INDEX index_prometheus_metrics_on_common ON prometheus_metrics USING btre
CREATE INDEX index_prometheus_metrics_on_group ON prometheus_metrics USING btree ("group");
-CREATE UNIQUE INDEX index_prometheus_metrics_on_identifier ON prometheus_metrics USING btree (identifier);
+CREATE UNIQUE INDEX index_prometheus_metrics_on_identifier_and_null_project ON prometheus_metrics USING btree (identifier) WHERE (project_id IS NULL);
+
+CREATE UNIQUE INDEX index_prometheus_metrics_on_identifier_and_project_id ON prometheus_metrics USING btree (identifier, project_id);
CREATE INDEX index_prometheus_metrics_on_project_id ON prometheus_metrics USING btree (project_id);
@@ -9417,12 +22961,12 @@ CREATE INDEX index_protected_tags_on_project_id ON protected_tags USING btree (p
CREATE UNIQUE INDEX index_protected_tags_on_project_id_and_name ON protected_tags USING btree (project_id, name);
-CREATE UNIQUE INDEX index_push_event_payloads_on_event_id ON push_event_payloads USING btree (event_id);
-
CREATE INDEX index_push_rules_on_is_sample ON push_rules USING btree (is_sample) WHERE is_sample;
CREATE INDEX index_push_rules_on_project_id ON push_rules USING btree (project_id);
+CREATE UNIQUE INDEX index_raw_usage_data_on_recorded_at ON raw_usage_data USING btree (recorded_at);
+
CREATE UNIQUE INDEX index_redirect_routes_on_path ON redirect_routes USING btree (path);
CREATE UNIQUE INDEX index_redirect_routes_on_path_unique_text_pattern_ops ON redirect_routes USING btree (lower((path)::text) varchar_pattern_ops);
@@ -9437,22 +22981,78 @@ CREATE INDEX index_releases_on_author_id ON releases USING btree (author_id);
CREATE INDEX index_releases_on_project_id_and_tag ON releases USING btree (project_id, tag);
+CREATE INDEX index_releases_on_released_at ON releases USING btree (released_at);
+
CREATE INDEX index_remote_mirrors_on_last_successful_update_at ON remote_mirrors USING btree (last_successful_update_at);
CREATE INDEX index_remote_mirrors_on_project_id ON remote_mirrors USING btree (project_id);
-CREATE UNIQUE INDEX index_repository_languages_on_project_and_languages_id ON repository_languages USING btree (project_id, programming_language_id);
+CREATE INDEX index_required_code_owners_sections_on_protected_branch_id ON required_code_owners_sections USING btree (protected_branch_id);
-CREATE INDEX index_resource_label_events_on_epic_id ON resource_label_events USING btree (epic_id);
+CREATE INDEX index_requirements_management_test_reports_on_author_id ON requirements_management_test_reports USING btree (author_id);
+
+CREATE INDEX index_requirements_management_test_reports_on_build_id ON requirements_management_test_reports USING btree (build_id);
+
+CREATE INDEX index_requirements_management_test_reports_on_requirement_id ON requirements_management_test_reports USING btree (requirement_id);
+
+CREATE INDEX index_requirements_on_author_id ON requirements USING btree (author_id);
+
+CREATE INDEX index_requirements_on_created_at ON requirements USING btree (created_at);
-CREATE INDEX index_resource_label_events_on_issue_id ON resource_label_events USING btree (issue_id);
+CREATE INDEX index_requirements_on_project_id ON requirements USING btree (project_id);
+
+CREATE UNIQUE INDEX index_requirements_on_project_id_and_iid ON requirements USING btree (project_id, iid) WHERE (project_id IS NOT NULL);
+
+CREATE INDEX index_requirements_on_state ON requirements USING btree (state);
+
+CREATE INDEX index_requirements_on_title_trigram ON requirements USING gin (title gin_trgm_ops);
+
+CREATE INDEX index_requirements_on_updated_at ON requirements USING btree (updated_at);
+
+CREATE INDEX index_resource_iteration_events_on_issue_id ON resource_iteration_events USING btree (issue_id);
+
+CREATE INDEX index_resource_iteration_events_on_iteration_id ON resource_iteration_events USING btree (iteration_id);
+
+CREATE INDEX index_resource_iteration_events_on_iteration_id_and_add_action ON resource_iteration_events USING btree (iteration_id) WHERE (action = 1);
+
+CREATE INDEX index_resource_iteration_events_on_merge_request_id ON resource_iteration_events USING btree (merge_request_id);
+
+CREATE INDEX index_resource_iteration_events_on_user_id ON resource_iteration_events USING btree (user_id);
+
+CREATE INDEX index_resource_label_events_issue_id_label_id_action ON resource_label_events USING btree (issue_id, label_id, action);
+
+CREATE INDEX index_resource_label_events_on_epic_id ON resource_label_events USING btree (epic_id);
CREATE INDEX index_resource_label_events_on_label_id_and_action ON resource_label_events USING btree (label_id, action);
-CREATE INDEX index_resource_label_events_on_merge_request_id ON resource_label_events USING btree (merge_request_id);
+CREATE INDEX index_resource_label_events_on_merge_request_id_label_id_action ON resource_label_events USING btree (merge_request_id, label_id, action);
CREATE INDEX index_resource_label_events_on_user_id ON resource_label_events USING btree (user_id);
+CREATE INDEX index_resource_milestone_events_created_at ON resource_milestone_events USING btree (created_at);
+
+CREATE INDEX index_resource_milestone_events_on_issue_id ON resource_milestone_events USING btree (issue_id);
+
+CREATE INDEX index_resource_milestone_events_on_merge_request_id ON resource_milestone_events USING btree (merge_request_id);
+
+CREATE INDEX index_resource_milestone_events_on_milestone_id ON resource_milestone_events USING btree (milestone_id);
+
+CREATE INDEX index_resource_milestone_events_on_milestone_id_and_add_action ON resource_milestone_events USING btree (milestone_id) WHERE (action = 1);
+
+CREATE INDEX index_resource_milestone_events_on_user_id ON resource_milestone_events USING btree (user_id);
+
+CREATE INDEX index_resource_state_events_on_epic_id ON resource_state_events USING btree (epic_id);
+
+CREATE INDEX index_resource_state_events_on_issue_id_and_created_at ON resource_state_events USING btree (issue_id, created_at);
+
+CREATE INDEX index_resource_state_events_on_merge_request_id ON resource_state_events USING btree (merge_request_id);
+
+CREATE INDEX index_resource_state_events_on_source_merge_request_id ON resource_state_events USING btree (source_merge_request_id);
+
+CREATE INDEX index_resource_state_events_on_user_id ON resource_state_events USING btree (user_id);
+
+CREATE INDEX index_resource_weight_events_on_issue_id_and_created_at ON resource_weight_events USING btree (issue_id, created_at);
+
CREATE INDEX index_resource_weight_events_on_issue_id_and_weight ON resource_weight_events USING btree (issue_id, weight);
CREATE INDEX index_resource_weight_events_on_user_id ON resource_weight_events USING btree (user_id);
@@ -9463,32 +23063,80 @@ CREATE INDEX index_reviews_on_merge_request_id ON reviews USING btree (merge_req
CREATE INDEX index_reviews_on_project_id ON reviews USING btree (project_id);
+CREATE INDEX index_route_on_name_trigram ON routes USING gin (name gin_trgm_ops);
+
CREATE UNIQUE INDEX index_routes_on_path ON routes USING btree (path);
CREATE INDEX index_routes_on_path_text_pattern_ops ON routes USING btree (path varchar_pattern_ops);
+CREATE INDEX index_routes_on_path_trigram ON routes USING gin (path gin_trgm_ops);
+
CREATE UNIQUE INDEX index_routes_on_source_type_and_source_id ON routes USING btree (source_type, source_id);
+CREATE UNIQUE INDEX index_saml_group_links_on_group_id_and_saml_group_name ON saml_group_links USING btree (group_id, saml_group_name);
+
CREATE INDEX index_saml_providers_on_group_id ON saml_providers USING btree (group_id);
+CREATE INDEX index_scim_identities_on_group_id ON scim_identities USING btree (group_id);
+
+CREATE UNIQUE INDEX index_scim_identities_on_lower_extern_uid_and_group_id ON scim_identities USING btree (lower((extern_uid)::text), group_id);
+
+CREATE UNIQUE INDEX index_scim_identities_on_user_id_and_group_id ON scim_identities USING btree (user_id, group_id);
+
CREATE UNIQUE INDEX index_scim_oauth_access_tokens_on_group_id_and_token_encrypted ON scim_oauth_access_tokens USING btree (group_id, token_encrypted);
+CREATE INDEX index_secure_ci_builds_on_user_id_name_created_at ON ci_builds USING btree (user_id, name, created_at) WHERE (((type)::text = 'Ci::Build'::text) AND ((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('license_scanning'::character varying)::text, ('sast'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('apifuzzer_fuzz'::character varying)::text, ('apifuzzer_fuzz_dnd'::character varying)::text, ('secret_detection'::character varying)::text])));
+
+CREATE INDEX index_security_ci_builds_on_name_and_id_parser_features ON ci_builds USING btree (name, id) WHERE (((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text, ('secret_detection'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text));
+
+CREATE INDEX index_security_findings_on_confidence ON security_findings USING btree (confidence);
+
+CREATE INDEX index_security_findings_on_project_fingerprint ON security_findings USING btree (project_fingerprint);
+
+CREATE INDEX index_security_findings_on_scan_id_and_deduplicated ON security_findings USING btree (scan_id, deduplicated);
+
+CREATE UNIQUE INDEX index_security_findings_on_scan_id_and_position ON security_findings USING btree (scan_id, "position");
+
+CREATE INDEX index_security_findings_on_scanner_id ON security_findings USING btree (scanner_id);
+
+CREATE INDEX index_security_findings_on_severity ON security_findings USING btree (severity);
+
+CREATE UNIQUE INDEX index_security_findings_on_uuid ON security_findings USING btree (uuid);
+
+CREATE INDEX index_security_scans_on_date_created_at_and_id ON security_scans USING btree (date(timezone('UTC'::text, created_at)), id);
+
CREATE INDEX index_self_managed_prometheus_alert_events_on_environment_id ON self_managed_prometheus_alert_events USING btree (environment_id);
+CREATE INDEX index_sent_notifications_on_noteable_type_noteable_id ON sent_notifications USING btree (noteable_id) WHERE ((noteable_type)::text = 'Issue'::text);
+
CREATE UNIQUE INDEX index_sent_notifications_on_reply_key ON sent_notifications USING btree (reply_key);
CREATE UNIQUE INDEX index_sentry_issues_on_issue_id ON sentry_issues USING btree (issue_id);
+CREATE INDEX index_sentry_issues_on_sentry_issue_identifier ON sentry_issues USING btree (sentry_issue_identifier);
+
CREATE INDEX index_serverless_domain_cluster_on_creator_id ON serverless_domain_cluster USING btree (creator_id);
CREATE INDEX index_serverless_domain_cluster_on_pages_domain_id ON serverless_domain_cluster USING btree (pages_domain_id);
-CREATE INDEX index_services_on_project_id ON services USING btree (project_id);
+CREATE INDEX index_service_desk_enabled_projects_on_id_creator_id_created_at ON projects USING btree (id, creator_id, created_at) WHERE (service_desk_enabled = true);
+
+CREATE INDEX index_services_on_inherit_from_id ON services USING btree (inherit_from_id);
+
+CREATE INDEX index_services_on_project_id_and_type ON services USING btree (project_id, type);
CREATE INDEX index_services_on_template ON services USING btree (template);
CREATE INDEX index_services_on_type ON services USING btree (type);
+CREATE UNIQUE INDEX index_services_on_type_and_instance_partial ON services USING btree (type, instance) WHERE (instance = true);
+
+CREATE UNIQUE INDEX index_services_on_type_and_template_partial ON services USING btree (type, template) WHERE (template = true);
+
+CREATE INDEX index_services_on_type_id_when_active_and_project_id_not_null ON services USING btree (type, id) WHERE ((active = true) AND (project_id IS NOT NULL));
+
+CREATE UNIQUE INDEX index_services_on_unique_group_id_and_type ON services USING btree (group_id, type);
+
CREATE UNIQUE INDEX index_shards_on_name ON shards USING btree (name);
CREATE INDEX index_slack_integrations_on_service_id ON slack_integrations USING btree (service_id);
@@ -9499,6 +23147,14 @@ CREATE UNIQUE INDEX index_smartcard_identities_on_subject_and_issuer ON smartcar
CREATE INDEX index_smartcard_identities_on_user_id ON smartcard_identities USING btree (user_id);
+CREATE INDEX index_snippet_on_id_and_project_id ON snippets USING btree (id, project_id);
+
+CREATE UNIQUE INDEX index_snippet_repositories_on_disk_path ON snippet_repositories USING btree (disk_path);
+
+CREATE INDEX index_snippet_repositories_on_shard_id ON snippet_repositories USING btree (shard_id);
+
+CREATE INDEX index_snippet_repository_storage_moves_on_snippet_id ON snippet_repository_storage_moves USING btree (snippet_id);
+
CREATE UNIQUE INDEX index_snippet_user_mentions_on_note_id ON snippet_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
CREATE INDEX index_snippets_on_author_id ON snippets USING btree (author_id);
@@ -9507,8 +23163,14 @@ CREATE INDEX index_snippets_on_content_trigram ON snippets USING gin (content gi
CREATE INDEX index_snippets_on_created_at ON snippets USING btree (created_at);
+CREATE INDEX index_snippets_on_description_trigram ON snippets USING gin (description gin_trgm_ops);
+
CREATE INDEX index_snippets_on_file_name_trigram ON snippets USING gin (file_name gin_trgm_ops);
+CREATE INDEX index_snippets_on_id_and_created_at ON snippets USING btree (id, created_at);
+
+CREATE INDEX index_snippets_on_id_and_type ON snippets USING btree (id, type);
+
CREATE INDEX index_snippets_on_project_id_and_visibility_level ON snippets USING btree (project_id, visibility_level);
CREATE INDEX index_snippets_on_title_trigram ON snippets USING gin (title gin_trgm_ops);
@@ -9525,10 +23187,32 @@ CREATE INDEX index_software_licenses_on_spdx_identifier ON software_licenses USI
CREATE UNIQUE INDEX index_software_licenses_on_unique_name ON software_licenses USING btree (name);
+CREATE INDEX index_sprints_on_description_trigram ON sprints USING gin (description gin_trgm_ops);
+
+CREATE INDEX index_sprints_on_due_date ON sprints USING btree (due_date);
+
+CREATE INDEX index_sprints_on_group_id ON sprints USING btree (group_id);
+
+CREATE UNIQUE INDEX index_sprints_on_group_id_and_title ON sprints USING btree (group_id, title) WHERE (group_id IS NOT NULL);
+
+CREATE UNIQUE INDEX index_sprints_on_project_id_and_iid ON sprints USING btree (project_id, iid);
+
+CREATE UNIQUE INDEX index_sprints_on_project_id_and_title ON sprints USING btree (project_id, title) WHERE (project_id IS NOT NULL);
+
+CREATE INDEX index_sprints_on_title ON sprints USING btree (title);
+
+CREATE INDEX index_sprints_on_title_trigram ON sprints USING gin (title gin_trgm_ops);
+
+CREATE UNIQUE INDEX index_status_page_published_incidents_on_issue_id ON status_page_published_incidents USING btree (issue_id);
+
+CREATE INDEX index_status_page_settings_on_project_id ON status_page_settings USING btree (project_id);
+
CREATE INDEX index_subscriptions_on_project_id ON subscriptions USING btree (project_id);
CREATE UNIQUE INDEX index_subscriptions_on_subscribable_and_user_id_and_project_id ON subscriptions USING btree (subscribable_id, subscribable_type, user_id, project_id);
+CREATE INDEX index_successful_deployments_on_cluster_id_and_environment_id ON deployments USING btree (cluster_id, environment_id) WHERE (status = 2);
+
CREATE INDEX index_suggestions_on_note_id ON suggestions USING btree (note_id);
CREATE UNIQUE INDEX index_suggestions_on_note_id_and_relative_order ON suggestions USING btree (note_id, relative_order);
@@ -9551,16 +23235,36 @@ CREATE INDEX index_term_agreements_on_term_id ON term_agreements USING btree (te
CREATE INDEX index_term_agreements_on_user_id ON term_agreements USING btree (user_id);
+CREATE INDEX index_terraform_state_versions_on_ci_build_id ON terraform_state_versions USING btree (ci_build_id);
+
+CREATE INDEX index_terraform_state_versions_on_created_by_user_id ON terraform_state_versions USING btree (created_by_user_id);
+
+CREATE UNIQUE INDEX index_terraform_state_versions_on_state_id_and_version ON terraform_state_versions USING btree (terraform_state_id, version);
+
+CREATE INDEX index_terraform_states_on_file_store ON terraform_states USING btree (file_store);
+
+CREATE INDEX index_terraform_states_on_locked_by_user_id ON terraform_states USING btree (locked_by_user_id);
+
+CREATE UNIQUE INDEX index_terraform_states_on_project_id_and_name ON terraform_states USING btree (project_id, name);
+
+CREATE UNIQUE INDEX index_terraform_states_on_uuid ON terraform_states USING btree (uuid);
+
+CREATE UNIQUE INDEX index_test_case_failures_unique_columns ON ci_test_case_failures USING btree (test_case_id, failed_at DESC, build_id);
+
CREATE INDEX index_timelogs_on_issue_id ON timelogs USING btree (issue_id);
CREATE INDEX index_timelogs_on_merge_request_id ON timelogs USING btree (merge_request_id);
+CREATE INDEX index_timelogs_on_note_id ON timelogs USING btree (note_id);
+
CREATE INDEX index_timelogs_on_spent_at ON timelogs USING btree (spent_at) WHERE (spent_at IS NOT NULL);
CREATE INDEX index_timelogs_on_user_id ON timelogs USING btree (user_id);
CREATE INDEX index_todos_on_author_id ON todos USING btree (author_id);
+CREATE INDEX index_todos_on_author_id_and_created_at ON todos USING btree (author_id, created_at);
+
CREATE INDEX index_todos_on_commit_id ON todos USING btree (commit_id);
CREATE INDEX index_todos_on_group_id ON todos USING btree (group_id);
@@ -9577,6 +23281,10 @@ CREATE INDEX index_todos_on_user_id_and_id_done ON todos USING btree (user_id, i
CREATE INDEX index_todos_on_user_id_and_id_pending ON todos USING btree (user_id, id) WHERE ((state)::text = 'pending'::text);
+CREATE UNIQUE INDEX index_token_with_ivs_on_hashed_plaintext_token ON token_with_ivs USING btree (hashed_plaintext_token);
+
+CREATE UNIQUE INDEX index_token_with_ivs_on_hashed_token ON token_with_ivs USING btree (hashed_token);
+
CREATE UNIQUE INDEX index_trending_projects_on_project_id ON trending_projects USING btree (project_id);
CREATE INDEX index_u2f_registrations_on_key_handle ON u2f_registrations USING btree (key_handle);
@@ -9597,14 +23305,28 @@ CREATE INDEX index_user_callouts_on_user_id ON user_callouts USING btree (user_i
CREATE UNIQUE INDEX index_user_callouts_on_user_id_and_feature_name ON user_callouts USING btree (user_id, feature_name);
+CREATE INDEX index_user_canonical_emails_on_canonical_email ON user_canonical_emails USING btree (canonical_email);
+
+CREATE UNIQUE INDEX index_user_canonical_emails_on_user_id ON user_canonical_emails USING btree (user_id);
+
+CREATE UNIQUE INDEX index_user_canonical_emails_on_user_id_and_canonical_email ON user_canonical_emails USING btree (user_id, canonical_email);
+
CREATE INDEX index_user_custom_attributes_on_key_and_value ON user_custom_attributes USING btree (key, value);
CREATE UNIQUE INDEX index_user_custom_attributes_on_user_id_and_key ON user_custom_attributes USING btree (user_id, key);
-CREATE UNIQUE INDEX index_user_interacted_projects_on_project_id_and_user_id ON user_interacted_projects USING btree (project_id, user_id);
+CREATE INDEX index_user_details_on_provisioned_by_group_id ON user_details USING btree (provisioned_by_group_id);
+
+CREATE UNIQUE INDEX index_user_details_on_user_id ON user_details USING btree (user_id);
+
+CREATE INDEX index_user_highest_roles_on_user_id_and_highest_access_level ON user_highest_roles USING btree (user_id, highest_access_level);
CREATE INDEX index_user_interacted_projects_on_user_id ON user_interacted_projects USING btree (user_id);
+CREATE INDEX index_user_permission_export_uploads_on_user_id_and_status ON user_permission_export_uploads USING btree (user_id, status);
+
+CREATE INDEX index_user_preferences_on_gitpod_enabled ON user_preferences USING btree (gitpod_enabled);
+
CREATE UNIQUE INDEX index_user_preferences_on_user_id ON user_preferences USING btree (user_id);
CREATE INDEX index_user_statuses_on_user_id ON user_statuses USING btree (user_id);
@@ -9615,8 +23337,6 @@ CREATE INDEX index_users_on_accepted_term_id ON users USING btree (accepted_term
CREATE INDEX index_users_on_admin ON users USING btree (admin);
-CREATE INDEX index_users_on_bot_type ON users USING btree (bot_type);
-
CREATE UNIQUE INDEX index_users_on_confirmation_token ON users USING btree (confirmation_token);
CREATE INDEX index_users_on_created_at ON users USING btree (created_at);
@@ -9627,8 +23347,6 @@ CREATE INDEX index_users_on_email_trigram ON users USING gin (email gin_trgm_ops
CREATE INDEX index_users_on_feed_token ON users USING btree (feed_token);
-CREATE INDEX index_users_on_ghost ON users USING btree (ghost);
-
CREATE INDEX index_users_on_group_view ON users USING btree (group_view);
CREATE INDEX index_users_on_incoming_email_token ON users USING btree (incoming_email_token);
@@ -9641,18 +23359,22 @@ CREATE INDEX index_users_on_name_trigram ON users USING gin (name gin_trgm_ops);
CREATE INDEX index_users_on_public_email ON users USING btree (public_email) WHERE ((public_email)::text <> ''::text);
+CREATE INDEX index_users_on_require_two_factor_authentication_from_group ON users USING btree (require_two_factor_authentication_from_group) WHERE (require_two_factor_authentication_from_group = true);
+
CREATE UNIQUE INDEX index_users_on_reset_password_token ON users USING btree (reset_password_token);
CREATE INDEX index_users_on_state ON users USING btree (state);
-CREATE INDEX index_users_on_state_and_internal ON users USING btree (state) WHERE (ghost IS NOT TRUE);
-
-CREATE INDEX index_users_on_state_and_internal_ee ON users USING btree (state) WHERE ((ghost IS NOT TRUE) AND (bot_type IS NULL));
+CREATE INDEX index_users_on_state_and_user_type ON users USING btree (state, user_type);
CREATE UNIQUE INDEX index_users_on_static_object_token ON users USING btree (static_object_token);
CREATE INDEX index_users_on_unconfirmed_email ON users USING btree (unconfirmed_email) WHERE (unconfirmed_email IS NOT NULL);
+CREATE UNIQUE INDEX index_users_on_unlock_token ON users USING btree (unlock_token);
+
+CREATE INDEX index_users_on_user_type ON users USING btree (user_type);
+
CREATE INDEX index_users_on_username ON users USING btree (username);
CREATE INDEX index_users_on_username_trigram ON users USING gin (username gin_trgm_ops);
@@ -9667,9 +23389,13 @@ CREATE INDEX index_users_star_projects_on_project_id ON users_star_projects USIN
CREATE UNIQUE INDEX index_users_star_projects_on_user_id_and_project_id ON users_star_projects USING btree (user_id, project_id);
+CREATE UNIQUE INDEX index_vuln_historical_statistics_on_project_id_and_date ON vulnerability_historical_statistics USING btree (project_id, date);
+
CREATE INDEX index_vulnerabilities_on_author_id ON vulnerabilities USING btree (author_id);
-CREATE INDEX index_vulnerabilities_on_closed_by_id ON vulnerabilities USING btree (closed_by_id);
+CREATE INDEX index_vulnerabilities_on_confirmed_by_id ON vulnerabilities USING btree (confirmed_by_id);
+
+CREATE INDEX index_vulnerabilities_on_dismissed_by_id ON vulnerabilities USING btree (dismissed_by_id);
CREATE INDEX index_vulnerabilities_on_due_date_sourcing_milestone_id ON vulnerabilities USING btree (due_date_sourcing_milestone_id);
@@ -9679,24 +23405,50 @@ CREATE INDEX index_vulnerabilities_on_last_edited_by_id ON vulnerabilities USING
CREATE INDEX index_vulnerabilities_on_milestone_id ON vulnerabilities USING btree (milestone_id);
-CREATE INDEX index_vulnerabilities_on_project_id ON vulnerabilities USING btree (project_id);
+CREATE INDEX index_vulnerabilities_on_project_id_and_state_and_severity ON vulnerabilities USING btree (project_id, state, severity);
CREATE INDEX index_vulnerabilities_on_resolved_by_id ON vulnerabilities USING btree (resolved_by_id);
CREATE INDEX index_vulnerabilities_on_start_date_sourcing_milestone_id ON vulnerabilities USING btree (start_date_sourcing_milestone_id);
+CREATE INDEX index_vulnerabilities_on_state_case_id ON vulnerabilities USING btree (array_position(ARRAY[(1)::smallint, (4)::smallint, (3)::smallint, (2)::smallint], state), id DESC);
+
+CREATE INDEX index_vulnerabilities_on_state_case_id_desc ON vulnerabilities USING btree (array_position(ARRAY[(1)::smallint, (4)::smallint, (3)::smallint, (2)::smallint], state) DESC, id DESC);
+
CREATE INDEX index_vulnerabilities_on_updated_by_id ON vulnerabilities USING btree (updated_by_id);
+CREATE INDEX index_vulnerability_exports_on_author_id ON vulnerability_exports USING btree (author_id);
+
+CREATE INDEX index_vulnerability_exports_on_file_store ON vulnerability_exports USING btree (file_store);
+
+CREATE INDEX index_vulnerability_exports_on_group_id_not_null ON vulnerability_exports USING btree (group_id) WHERE (group_id IS NOT NULL);
+
+CREATE INDEX index_vulnerability_exports_on_project_id_not_null ON vulnerability_exports USING btree (project_id) WHERE (project_id IS NOT NULL);
+
+CREATE INDEX index_vulnerability_external_issue_links_on_author_id ON vulnerability_external_issue_links USING btree (author_id);
+
+CREATE INDEX index_vulnerability_external_issue_links_on_vulnerability_id ON vulnerability_external_issue_links USING btree (vulnerability_id);
+
CREATE INDEX index_vulnerability_feedback_on_author_id ON vulnerability_feedback USING btree (author_id);
CREATE INDEX index_vulnerability_feedback_on_comment_author_id ON vulnerability_feedback USING btree (comment_author_id);
CREATE INDEX index_vulnerability_feedback_on_issue_id ON vulnerability_feedback USING btree (issue_id);
+CREATE INDEX index_vulnerability_feedback_on_issue_id_not_null ON vulnerability_feedback USING btree (id) WHERE (issue_id IS NOT NULL);
+
CREATE INDEX index_vulnerability_feedback_on_merge_request_id ON vulnerability_feedback USING btree (merge_request_id);
CREATE INDEX index_vulnerability_feedback_on_pipeline_id ON vulnerability_feedback USING btree (pipeline_id);
+CREATE INDEX index_vulnerability_finding_fingerprints_on_finding_id ON vulnerability_finding_fingerprints USING btree (finding_id);
+
+CREATE INDEX index_vulnerability_findings_remediations_on_remediation_id ON vulnerability_findings_remediations USING btree (vulnerability_remediation_id);
+
+CREATE UNIQUE INDEX index_vulnerability_findings_remediations_on_unique_keys ON vulnerability_findings_remediations USING btree (vulnerability_occurrence_id, vulnerability_remediation_id);
+
+CREATE INDEX index_vulnerability_historical_statistics_on_date_and_id ON vulnerability_historical_statistics USING btree (date, id);
+
CREATE UNIQUE INDEX index_vulnerability_identifiers_on_project_id_and_fingerprint ON vulnerability_identifiers USING btree (project_id, fingerprint);
CREATE INDEX index_vulnerability_issue_links_on_issue_id ON vulnerability_issue_links USING btree (issue_id);
@@ -9707,8 +23459,12 @@ CREATE UNIQUE INDEX index_vulnerability_occurrence_identifiers_on_unique_keys ON
CREATE INDEX index_vulnerability_occurrence_pipelines_on_pipeline_id ON vulnerability_occurrence_pipelines USING btree (pipeline_id);
+CREATE INDEX index_vulnerability_occurrences_for_issue_links_migration ON vulnerability_occurrences USING btree (project_id, report_type, encode(project_fingerprint, 'hex'::text));
+
CREATE INDEX index_vulnerability_occurrences_on_primary_identifier_id ON vulnerability_occurrences USING btree (primary_identifier_id);
+CREATE INDEX index_vulnerability_occurrences_on_project_fingerprint ON vulnerability_occurrences USING btree (project_fingerprint);
+
CREATE INDEX index_vulnerability_occurrences_on_scanner_id ON vulnerability_occurrences USING btree (scanner_id);
CREATE UNIQUE INDEX index_vulnerability_occurrences_on_unique_keys ON vulnerability_occurrences USING btree (project_id, primary_identifier_id, location_fingerprint, scanner_id);
@@ -9717,20 +23473,44 @@ CREATE UNIQUE INDEX index_vulnerability_occurrences_on_uuid ON vulnerability_occ
CREATE INDEX index_vulnerability_occurrences_on_vulnerability_id ON vulnerability_occurrences USING btree (vulnerability_id);
+CREATE UNIQUE INDEX index_vulnerability_remediations_on_project_id_and_checksum ON vulnerability_remediations USING btree (project_id, checksum);
+
CREATE UNIQUE INDEX index_vulnerability_scanners_on_project_id_and_external_id ON vulnerability_scanners USING btree (project_id, external_id);
+CREATE INDEX index_vulnerability_statistics_on_letter_grade ON vulnerability_statistics USING btree (letter_grade);
+
+CREATE UNIQUE INDEX index_vulnerability_statistics_on_unique_project_id ON vulnerability_statistics USING btree (project_id);
+
+CREATE UNIQUE INDEX index_vulnerability_user_mentions_on_note_id ON vulnerability_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
+
+CREATE UNIQUE INDEX index_vulns_user_mentions_on_vulnerability_id ON vulnerability_user_mentions USING btree (vulnerability_id) WHERE (note_id IS NULL);
+
+CREATE UNIQUE INDEX index_vulns_user_mentions_on_vulnerability_id_and_note_id ON vulnerability_user_mentions USING btree (vulnerability_id, note_id);
+
CREATE INDEX index_web_hook_logs_on_created_at_and_web_hook_id ON web_hook_logs USING btree (created_at, web_hook_id);
CREATE INDEX index_web_hook_logs_on_web_hook_id ON web_hook_logs USING btree (web_hook_id);
+CREATE INDEX index_web_hooks_on_group_id ON web_hooks USING btree (group_id) WHERE ((type)::text = 'GroupHook'::text);
+
CREATE INDEX index_web_hooks_on_project_id ON web_hooks USING btree (project_id);
+CREATE INDEX index_web_hooks_on_service_id ON web_hooks USING btree (service_id);
+
CREATE INDEX index_web_hooks_on_type ON web_hooks USING btree (type);
CREATE UNIQUE INDEX index_webauthn_registrations_on_credential_xid ON webauthn_registrations USING btree (credential_xid);
+CREATE INDEX index_webauthn_registrations_on_u2f_registration_id ON webauthn_registrations USING btree (u2f_registration_id) WHERE (u2f_registration_id IS NOT NULL);
+
CREATE INDEX index_webauthn_registrations_on_user_id ON webauthn_registrations USING btree (user_id);
+CREATE INDEX index_wiki_page_meta_on_project_id ON wiki_page_meta USING btree (project_id);
+
+CREATE UNIQUE INDEX index_wiki_page_slugs_on_slug_and_wiki_page_meta_id ON wiki_page_slugs USING btree (slug, wiki_page_meta_id);
+
+CREATE INDEX index_wiki_page_slugs_on_wiki_page_meta_id ON wiki_page_slugs USING btree (wiki_page_meta_id);
+
CREATE INDEX index_x509_certificates_on_subject_key_identifier ON x509_certificates USING btree (subject_key_identifier);
CREATE INDEX index_x509_certificates_on_x509_issuer_id ON x509_certificates USING btree (x509_issuer_id);
@@ -9755,20 +23535,32 @@ CREATE INDEX issue_id_issues_prometheus_alert_events_index ON issues_prometheus_
CREATE INDEX issue_id_issues_self_managed_rometheus_alert_events_index ON issues_self_managed_prometheus_alert_events USING btree (self_managed_prometheus_alert_event_id);
-CREATE UNIQUE INDEX issue_id_prometheus_alert_event_id_index ON issues_prometheus_alert_events USING btree (issue_id, prometheus_alert_event_id);
-
-CREATE UNIQUE INDEX issue_id_self_managed_prometheus_alert_event_id_index ON issues_self_managed_prometheus_alert_events USING btree (issue_id, self_managed_prometheus_alert_event_id);
-
CREATE UNIQUE INDEX issue_user_mentions_on_issue_id_and_note_id_index ON issue_user_mentions USING btree (issue_id, note_id);
CREATE UNIQUE INDEX issue_user_mentions_on_issue_id_index ON issue_user_mentions USING btree (issue_id) WHERE (note_id IS NULL);
CREATE UNIQUE INDEX kubernetes_namespaces_cluster_and_namespace ON clusters_kubernetes_namespaces USING btree (cluster_id, namespace);
+CREATE INDEX merge_request_mentions_temp_index ON merge_requests USING btree (id) WHERE ((description ~~ '%@%'::text) OR ((title)::text ~~ '%@%'::text));
+
CREATE UNIQUE INDEX merge_request_user_mentions_on_mr_id_and_note_id_index ON merge_request_user_mentions USING btree (merge_request_id, note_id);
CREATE UNIQUE INDEX merge_request_user_mentions_on_mr_id_index ON merge_request_user_mentions USING btree (merge_request_id) WHERE (note_id IS NULL);
+CREATE INDEX merge_requests_state_id_temp_index ON merge_requests USING btree (id) WHERE (state_id = ANY (ARRAY[2, 3]));
+
+CREATE INDEX note_mentions_temp_index ON notes USING btree (id, noteable_type) WHERE (note ~~ '%@%'::text);
+
+CREATE UNIQUE INDEX one_canonical_wiki_page_slug_per_metadata ON wiki_page_slugs USING btree (wiki_page_meta_id) WHERE (canonical = true);
+
+CREATE INDEX package_name_index ON packages_packages USING btree (name);
+
+CREATE INDEX packages_packages_failed_verification ON packages_package_files USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
+
+CREATE INDEX packages_packages_needs_verification ON packages_package_files USING btree (verification_state) WHERE ((verification_state = 0) OR (verification_state = 3));
+
+CREATE INDEX packages_packages_pending_verification ON packages_package_files USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0);
+
CREATE INDEX partial_index_ci_builds_on_scheduled_at_with_scheduled_jobs ON ci_builds USING btree (scheduled_at) WHERE ((scheduled_at IS NOT NULL) AND ((type)::text = 'Ci::Build'::text) AND ((status)::text = 'scheduled'::text));
CREATE INDEX partial_index_deployments_for_legacy_successful_deployments ON deployments USING btree (id) WHERE ((finished_at IS NULL) AND (status = 2));
@@ -9781,16 +23573,309 @@ CREATE UNIQUE INDEX snippet_user_mentions_on_snippet_id_index ON snippet_user_me
CREATE UNIQUE INDEX taggings_idx ON taggings USING btree (tag_id, taggable_id, taggable_type, context, tagger_id, tagger_type);
+CREATE INDEX temporary_index_vulnerabilities_on_id ON vulnerabilities USING btree (id) WHERE ((state = 2) AND ((dismissed_at IS NULL) OR (dismissed_by_id IS NULL)));
+
CREATE UNIQUE INDEX term_agreements_unique_index ON term_agreements USING btree (user_id, term_id);
CREATE INDEX tmp_build_stage_position_index ON ci_builds USING btree (stage_id, stage_idx) WHERE (stage_idx IS NOT NULL);
-CREATE UNIQUE INDEX users_security_dashboard_projects_unique_index ON users_security_dashboard_projects USING btree (project_id, user_id);
+CREATE INDEX tmp_idx_deduplicate_vulnerability_occurrences ON vulnerability_occurrences USING btree (project_id, report_type, location_fingerprint, primary_identifier_id, id);
+
+CREATE INDEX tmp_index_ci_builds_lock_version ON ci_builds USING btree (id) WHERE (lock_version IS NULL);
+
+CREATE INDEX tmp_index_ci_pipelines_lock_version ON ci_pipelines USING btree (id) WHERE (lock_version IS NULL);
+
+CREATE INDEX tmp_index_ci_stages_lock_version ON ci_stages USING btree (id) WHERE (lock_version IS NULL);
+
+CREATE INDEX tmp_index_for_email_unconfirmation_migration ON emails USING btree (id) WHERE (confirmed_at IS NOT NULL);
+
+CREATE INDEX tmp_index_on_vulnerabilities_non_dismissed ON vulnerabilities USING btree (id) WHERE (state <> 2);
+
+CREATE UNIQUE INDEX uniq_pkgs_deb_grp_architectures_on_distribution_id_and_name ON packages_debian_group_architectures USING btree (distribution_id, name);
+
+CREATE UNIQUE INDEX uniq_pkgs_deb_grp_components_on_distribution_id_and_name ON packages_debian_group_components USING btree (distribution_id, name);
+
+CREATE UNIQUE INDEX uniq_pkgs_deb_proj_architectures_on_distribution_id_and_name ON packages_debian_project_architectures USING btree (distribution_id, name);
+
+CREATE UNIQUE INDEX uniq_pkgs_deb_proj_components_on_distribution_id_and_name ON packages_debian_project_components USING btree (distribution_id, name);
+
+CREATE UNIQUE INDEX uniq_pkgs_debian_group_distributions_group_id_and_codename ON packages_debian_group_distributions USING btree (group_id, codename);
+
+CREATE UNIQUE INDEX uniq_pkgs_debian_group_distributions_group_id_and_suite ON packages_debian_group_distributions USING btree (group_id, suite);
+
+CREATE UNIQUE INDEX uniq_pkgs_debian_project_distributions_project_id_and_codename ON packages_debian_project_distributions USING btree (project_id, codename);
+
+CREATE UNIQUE INDEX uniq_pkgs_debian_project_distributions_project_id_and_suite ON packages_debian_project_distributions USING btree (project_id, suite);
+
+CREATE UNIQUE INDEX unique_merge_request_metrics_by_merge_request_id ON merge_request_metrics USING btree (merge_request_id);
+
+CREATE INDEX user_follow_users_followee_id_idx ON user_follow_users USING btree (followee_id);
CREATE UNIQUE INDEX vulnerability_feedback_unique_idx ON vulnerability_feedback USING btree (project_id, category, feedback_type, project_fingerprint);
CREATE UNIQUE INDEX vulnerability_occurrence_pipelines_on_unique_keys ON vulnerability_occurrence_pipelines USING btree (occurrence_id, pipeline_id);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx10;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx11;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx12;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx13;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx14;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx15;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx16;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx17;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx18;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx19;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx20;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx21;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx22;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx23;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx24;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx25;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx26;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx27;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx28;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx29;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx30;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx31;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx32;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx33;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx34;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx35;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx36;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx37;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx38;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx39;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx40;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx41;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx42;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx43;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx44;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx45;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx46;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx47;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx48;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx49;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx50;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx51;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx52;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx53;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx54;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx55;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx56;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx57;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx58;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx59;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx60;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx61;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx62;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx63;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx1;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx2;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx3;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx4;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx5;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx6;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx7;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx8;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx9;
+
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experi_project_id_collector_tstamp_idx;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_00_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_01_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_02_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_03_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_04_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_05_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_06_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_07_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_08_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_09_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_10_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_11_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_12_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_13_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_14_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_15_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_16_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_17_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_18_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_19_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_20_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_21_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_22_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_23_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_24_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_25_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_26_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_27_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_28_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_29_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_30_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_31_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_32_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_33_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_34_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_35_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_36_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_37_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_38_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_39_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_40_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_41_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_42_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_43_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_44_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_45_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_46_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_47_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_48_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_49_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_50_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_51_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_52_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_53_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_54_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_55_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_56_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_57_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_58_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_59_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_60_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_61_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_62_pkey;
+
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_63_pkey;
+
+CREATE TRIGGER table_sync_trigger_ee39a25f9d AFTER INSERT OR DELETE OR UPDATE ON audit_events FOR EACH ROW EXECUTE FUNCTION table_sync_function_2be879775d();
+
+ALTER TABLE ONLY chat_names
+ ADD CONSTRAINT fk_00797a2bf9 FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_013c9f36ca FOREIGN KEY (due_date_sourcing_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
@@ -9800,6 +23885,12 @@ ALTER TABLE ONLY clusters_applications_runners
ALTER TABLE ONLY design_management_designs_versions
ADD CONSTRAINT fk_03c671965c FOREIGN KEY (design_id) REFERENCES design_management_designs(id) ON DELETE CASCADE;
+ALTER TABLE ONLY terraform_state_versions
+ ADD CONSTRAINT fk_04b91e4a9f FOREIGN KEY (ci_build_id) REFERENCES ci_builds(id) ON DELETE SET NULL;
+
+ALTER TABLE ONLY ci_test_cases
+ ADD CONSTRAINT fk_0526c30ded FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issues
ADD CONSTRAINT fk_05f1e72feb FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -9809,6 +23900,9 @@ ALTER TABLE ONLY merge_requests
ALTER TABLE ONLY projects
ADD CONSTRAINT fk_0a31cca0b8 FOREIGN KEY (marked_for_deletion_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY dast_sites
+ ADD CONSTRAINT fk_0a57f2271b FOREIGN KEY (dast_site_validation_id) REFERENCES dast_site_validations(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY web_hooks
ADD CONSTRAINT fk_0c8ca6d9d1 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -9818,6 +23912,9 @@ ALTER TABLE ONLY notification_settings
ALTER TABLE ONLY lists
ADD CONSTRAINT fk_0d3f677137 FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_pages_metadata
+ ADD CONSTRAINT fk_0fd5b22688 FOREIGN KEY (pages_deployment_id) REFERENCES pages_deployments(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY group_deletion_schedules
ADD CONSTRAINT fk_11e3ebfcdd FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -9827,6 +23924,12 @@ ALTER TABLE ONLY vulnerabilities
ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT fk_131d289c65 FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
+ALTER TABLE ONLY webauthn_registrations
+ ADD CONSTRAINT fk_13e04d719a FOREIGN KEY (u2f_registration_id) REFERENCES u2f_registrations(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY protected_branch_push_access_levels
+ ADD CONSTRAINT fk_15d2a7a4ae FOREIGN KEY (deploy_key_id) REFERENCES keys(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY internal_ids
ADD CONSTRAINT fk_162941d509 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -9839,6 +23942,9 @@ ALTER TABLE ONLY project_features
ALTER TABLE ONLY ci_pipelines
ADD CONSTRAINT fk_190998ef09 FOREIGN KEY (external_pull_request_id) REFERENCES external_pull_requests(id) ON DELETE SET NULL;
+ALTER TABLE ONLY user_details
+ ADD CONSTRAINT fk_190e4fcc88 FOREIGN KEY (provisioned_by_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT fk_1d37cddf91 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE SET NULL;
@@ -9846,7 +23952,7 @@ ALTER TABLE ONLY ci_sources_pipelines
ADD CONSTRAINT fk_1e53c97c0a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY epics
- ADD CONSTRAINT fk_1fbed67632 FOREIGN KEY (start_date_sourcing_milestone_id) REFERENCES milestones(id) ON DELETE SET NULL NOT VALID;
+ ADD CONSTRAINT fk_1fbed67632 FOREIGN KEY (start_date_sourcing_milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
ALTER TABLE ONLY geo_container_repository_updated_events
ADD CONSTRAINT fk_212c89c706 FOREIGN KEY (container_repository_id) REFERENCES container_repositories(id) ON DELETE CASCADE;
@@ -9854,9 +23960,15 @@ ALTER TABLE ONLY geo_container_repository_updated_events
ALTER TABLE ONLY users_star_projects
ADD CONSTRAINT fk_22cd27ddfc FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY alert_management_alerts
+ ADD CONSTRAINT fk_2358b75436 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY ci_stages
ADD CONSTRAINT fk_2360681d1d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY import_failures
+ ADD CONSTRAINT fk_24b824da43 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY project_ci_cd_settings
ADD CONSTRAINT fk_24c15d2f2e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -9881,6 +23993,9 @@ ALTER TABLE ONLY notes
ALTER TABLE ONLY members
ADD CONSTRAINT fk_2e88fb7ce9 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY lists
+ ADD CONSTRAINT fk_30f2a831f4 FOREIGN KEY (iteration_id) REFERENCES sprints(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY approvals
ADD CONSTRAINT fk_310d714958 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
@@ -9893,6 +24008,9 @@ ALTER TABLE ONLY merge_requests
ALTER TABLE ONLY ci_group_variables
ADD CONSTRAINT fk_33ae4d58d8 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespaces
+ ADD CONSTRAINT fk_3448c97865 FOREIGN KEY (push_rule_id) REFERENCES push_rules(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_3654b61b03 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -9902,8 +24020,11 @@ ALTER TABLE ONLY push_event_payloads
ALTER TABLE ONLY ci_builds
ADD CONSTRAINT fk_3a9eaa254d FOREIGN KEY (stage_id) REFERENCES ci_stages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issues
+ ADD CONSTRAINT fk_3b8c72ea56 FOREIGN KEY (sprint_id) REFERENCES sprints(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY epics
- ADD CONSTRAINT fk_3c1fd1cccc FOREIGN KEY (due_date_sourcing_milestone_id) REFERENCES milestones(id) ON DELETE SET NULL NOT VALID;
+ ADD CONSTRAINT fk_3c1fd1cccc FOREIGN KEY (due_date_sourcing_milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
ALTER TABLE ONLY ci_pipelines
ADD CONSTRAINT fk_3d34ab2e06 FOREIGN KEY (pipeline_schedule_id) REFERENCES ci_pipeline_schedules(id) ON DELETE SET NULL;
@@ -9914,9 +24035,6 @@ ALTER TABLE ONLY ci_pipeline_schedule_variables
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_42c3b54bed FOREIGN KEY (cache_invalidation_event_id) REFERENCES geo_cache_invalidation_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY forked_project_links
- ADD CONSTRAINT fk_434510edb0 FOREIGN KEY (forked_to_project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY ci_runner_projects
ADD CONSTRAINT fk_4478a6f1e4 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -9932,9 +24050,15 @@ ALTER TABLE ONLY geo_event_log
ALTER TABLE ONLY ci_build_trace_sections
ADD CONSTRAINT fk_4ebe41f502 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY alert_management_alerts
+ ADD CONSTRAINT fk_51ab4b6089 FOREIGN KEY (prometheus_alert_id) REFERENCES prometheus_alerts(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY path_locks
ADD CONSTRAINT fk_5265c98f24 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_metrics
+ ADD CONSTRAINT fk_56067dcb44 FOREIGN KEY (target_project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT fk_563ff1912e FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE SET NULL;
@@ -9944,6 +24068,12 @@ ALTER TABLE ONLY deploy_keys_projects
ALTER TABLE ONLY issue_assignees
ADD CONSTRAINT fk_5e0c8d9154 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY csv_issue_imports
+ ADD CONSTRAINT fk_5e1572387c FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY project_access_tokens
+ ADD CONSTRAINT fk_5f7e8450e1 FOREIGN KEY (personal_access_token_id) REFERENCES personal_access_tokens(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_6149611a04 FOREIGN KEY (assignee_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -9959,6 +24089,12 @@ ALTER TABLE ONLY merge_requests
ALTER TABLE ONLY ci_builds
ADD CONSTRAINT fk_6661f4f0e8 FOREIGN KEY (resource_group_id) REFERENCES ci_resource_groups(id) ON DELETE SET NULL;
+ALTER TABLE ONLY project_pages_metadata
+ ADD CONSTRAINT fk_69366a119e FOREIGN KEY (artifacts_archive_id) REFERENCES ci_job_artifacts(id) ON DELETE SET NULL;
+
+ALTER TABLE ONLY application_settings
+ ADD CONSTRAINT fk_693b8795e4 FOREIGN KEY (push_rule_id) REFERENCES push_rules(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_6a5165a692 FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
@@ -9968,12 +24104,18 @@ ALTER TABLE ONLY geo_event_log
ALTER TABLE ONLY projects
ADD CONSTRAINT fk_6e5c14658a FOREIGN KEY (pool_repository_id) REFERENCES pool_repositories(id) ON DELETE SET NULL;
+ALTER TABLE ONLY terraform_state_versions
+ ADD CONSTRAINT fk_6e81384d7f FOREIGN KEY (created_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY protected_branch_push_access_levels
ADD CONSTRAINT fk_7111b68cdb FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY services
ADD CONSTRAINT fk_71cce407f9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_725465b774 FOREIGN KEY (dismissed_by_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY index_statuses
ADD CONSTRAINT fk_74b2492545 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10007,9 +24149,21 @@ ALTER TABLE ONLY vulnerabilities
ALTER TABLE ONLY labels
ADD CONSTRAINT fk_7de4989a69 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY backup_labels
+ ADD CONSTRAINT fk_7de4989a69 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY merge_requests
+ ADD CONSTRAINT fk_7e85395a64 FOREIGN KEY (sprint_id) REFERENCES sprints(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_request_metrics
ADD CONSTRAINT fk_7f28d925f3 FOREIGN KEY (merged_by_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY group_import_states
+ ADD CONSTRAINT fk_8053b3ebd6 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY sprints
+ ADD CONSTRAINT fk_80aa8a1f95 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY import_export_uploads
ADD CONSTRAINT fk_83319d9721 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -10031,15 +24185,24 @@ ALTER TABLE ONLY packages_package_files
ALTER TABLE ONLY ci_builds
ADD CONSTRAINT fk_87f4cefcda FOREIGN KEY (upstream_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY experiment_subjects
+ ADD CONSTRAINT fk_88489af1b1 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT fk_88b4d546ef FOREIGN KEY (start_date_sourcing_milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
+ALTER TABLE ONLY bulk_import_entities
+ ADD CONSTRAINT fk_88c725229f FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issues
ADD CONSTRAINT fk_899c8f3231 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY protected_branch_merge_access_levels
ADD CONSTRAINT fk_8a3072ccb3 FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
+ALTER TABLE ONLY timelogs
+ ADD CONSTRAINT fk_8d058cd571 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY releases
ADD CONSTRAINT fk_8e4456f90f FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -10058,6 +24221,9 @@ ALTER TABLE ONLY vulnerability_feedback
ALTER TABLE ONLY milestones
ADD CONSTRAINT fk_95650a40d4 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_959d40ad0a FOREIGN KEY (confirmed_by_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY application_settings
ADD CONSTRAINT fk_964370041d FOREIGN KEY (usage_stats_set_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -10085,12 +24251,18 @@ ALTER TABLE ONLY issues
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_9d480c64b2 FOREIGN KEY (start_date_sourcing_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
+ALTER TABLE ONLY alert_management_alerts
+ ADD CONSTRAINT fk_9e49e5c2b7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_pipeline_schedules
ADD CONSTRAINT fk_9ea99f58d2 FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE SET NULL;
ALTER TABLE ONLY protected_branch_push_access_levels
ADD CONSTRAINT fk_9ffc86a3d9 FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
+ALTER TABLE ONLY deployment_merge_requests
+ ADD CONSTRAINT fk_a064ff4453 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issues
ADD CONSTRAINT fk_a194299be1 FOREIGN KEY (moved_to_id) REFERENCES issues(id) ON DELETE SET NULL;
@@ -10106,6 +24278,9 @@ ALTER TABLE ONLY todos
ALTER TABLE ONLY jira_connect_subscriptions
ADD CONSTRAINT fk_a3c10bcf7d FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY bulk_import_entities
+ ADD CONSTRAINT fk_a44ff95be5 FOREIGN KEY (parent_id) REFERENCES bulk_import_entities(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY users
ADD CONSTRAINT fk_a4b8fefe3e FOREIGN KEY (managing_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
@@ -10115,6 +24290,9 @@ ALTER TABLE ONLY merge_requests
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_aa5798e761 FOREIGN KEY (closed_by_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY alert_management_alerts
+ ADD CONSTRAINT fk_aad61aedca FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY identities
ADD CONSTRAINT fk_aade90f0fc FOREIGN KEY (saml_provider_id) REFERENCES saml_providers(id) ON DELETE CASCADE;
@@ -10130,15 +24308,27 @@ ALTER TABLE ONLY ci_variables
ALTER TABLE ONLY merge_request_metrics
ADD CONSTRAINT fk_ae440388cc FOREIGN KEY (latest_closed_by_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY analytics_cycle_analytics_group_stages
+ ADD CONSTRAINT fk_analytics_cycle_analytics_group_stages_group_value_stream_id FOREIGN KEY (group_value_stream_id) REFERENCES analytics_cycle_analytics_group_value_streams(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY fork_network_members
ADD CONSTRAINT fk_b01280dae4 FOREIGN KEY (forked_from_project_id) REFERENCES projects(id) ON DELETE SET NULL;
ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT fk_b1de915a15 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY project_access_tokens
+ ADD CONSTRAINT fk_b27801bfbf FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY protected_tag_create_access_levels
ADD CONSTRAINT fk_b4eb82fe3c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY bulk_import_entities
+ ADD CONSTRAINT fk_b69fa2b2df FOREIGN KEY (bulk_import_id) REFERENCES bulk_imports(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY compliance_management_frameworks
+ ADD CONSTRAINT fk_b74c45b71f FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issue_assignees
ADD CONSTRAINT fk_b7d881734a FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
@@ -10151,6 +24341,12 @@ ALTER TABLE ONLY deployments
ALTER TABLE ONLY gitlab_subscriptions
ADD CONSTRAINT fk_bd0c4019c3 FOREIGN KEY (hosted_plan_id) REFERENCES plans(id) ON DELETE CASCADE;
+ALTER TABLE ONLY metrics_users_starred_dashboards
+ ADD CONSTRAINT fk_bd6ae32fac FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY project_compliance_framework_settings
+ ADD CONSTRAINT fk_be413374a9 FOREIGN KEY (framework_id) REFERENCES compliance_management_frameworks(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY snippets
ADD CONSTRAINT fk_be41fd4bb7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10166,9 +24362,15 @@ ALTER TABLE ONLY ci_builds
ALTER TABLE ONLY design_management_versions
ADD CONSTRAINT fk_c1440b4896 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY packages_packages
+ ADD CONSTRAINT fk_c188f0dba4 FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_c1f241c70d FOREIGN KEY (upload_deleted_event_id) REFERENCES geo_upload_deleted_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_exports
+ ADD CONSTRAINT fk_c3d3cb5d0f FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_c4b1c1f66e FOREIGN KEY (repository_deleted_event_id) REFERENCES geo_repository_deleted_events(id) ON DELETE CASCADE;
@@ -10178,30 +24380,45 @@ ALTER TABLE ONLY issues
ALTER TABLE ONLY issue_links
ADD CONSTRAINT fk_c900194ff2 FOREIGN KEY (source_id) REFERENCES issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY experiment_subjects
+ ADD CONSTRAINT fk_ccc28f8ceb FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY todos
ADD CONSTRAINT fk_ccf0373936 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY vulnerabilities
- ADD CONSTRAINT fk_cf5c60acbf FOREIGN KEY (closed_by_id) REFERENCES users(id) ON DELETE SET NULL;
-
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_cff7185ad2 FOREIGN KEY (reset_checksum_event_id) REFERENCES geo_reset_checksum_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY bulk_import_entities
+ ADD CONSTRAINT fk_d06d023c30 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY environments
ADD CONSTRAINT fk_d1c8c1da6a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_builds
ADD CONSTRAINT fk_d3130c9a7f FOREIGN KEY (commit_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY web_hooks
+ ADD CONSTRAINT fk_d47999a98a FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE NOT VALID;
+
ALTER TABLE ONLY ci_sources_pipelines
ADD CONSTRAINT fk_d4e29af7d7 FOREIGN KEY (source_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_d5af95fcd9 FOREIGN KEY (lfs_object_deleted_event_id) REFERENCES geo_lfs_object_deleted_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_test_case_failures
+ ADD CONSTRAINT fk_d69404d827 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY lists
ADD CONSTRAINT fk_d6cf4279f7 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY metrics_users_starred_dashboards
+ ADD CONSTRAINT fk_d76a2b9a8c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY ci_pipelines
+ ADD CONSTRAINT fk_d80e161c54 FOREIGN KEY (ci_ref_id) REFERENCES ci_refs(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY system_note_metadata
ADD CONSTRAINT fk_d83a918cb1 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
@@ -10217,9 +24434,15 @@ ALTER TABLE ONLY dependency_proxy_blobs
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_dccd3f98fc FOREIGN KEY (assignee_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY analytics_devops_adoption_segment_selections
+ ADD CONSTRAINT fk_ded7fe0344 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issues
ADD CONSTRAINT fk_df75a7c8b8 FOREIGN KEY (promoted_to_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
+ALTER TABLE ONLY experiment_subjects
+ ADD CONSTRAINT fk_dfc3e211d4 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_resources
ADD CONSTRAINT fk_e169a8e3d5 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE SET NULL;
@@ -10238,15 +24461,27 @@ ALTER TABLE ONLY merge_requests
ALTER TABLE ONLY issue_links
ADD CONSTRAINT fk_e71bb44f1f FOREIGN KEY (target_id) REFERENCES issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY csv_issue_imports
+ ADD CONSTRAINT fk_e71c0ae362 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY namespaces
ADD CONSTRAINT fk_e7a0b20a6b FOREIGN KEY (custom_project_templates_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
ALTER TABLE ONLY fork_networks
ADD CONSTRAINT fk_e7b436b2b5 FOREIGN KEY (root_project_id) REFERENCES projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY sprints
+ ADD CONSTRAINT fk_e8206c9686 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY application_settings
+ ADD CONSTRAINT fk_e8a145f3a7 FOREIGN KEY (instance_administrators_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY ci_triggers
ADD CONSTRAINT fk_e8e10d1964 FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY services
+ ADD CONSTRAINT fk_e8fe908a34 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY pages_domains
ADD CONSTRAINT fk_ea2f6dfc6f FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10259,12 +24494,21 @@ ALTER TABLE ONLY events
ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT fk_efb96ab1e2 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY emails
+ ADD CONSTRAINT fk_emails_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY clusters
ADD CONSTRAINT fk_f05c5e5a42 FOREIGN KEY (management_project_id) REFERENCES projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY vulnerability_external_issue_links
+ ADD CONSTRAINT fk_f07bb8233d FOREIGN KEY (vulnerability_id) REFERENCES vulnerabilities(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_f081aa4489 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY analytics_devops_adoption_segment_selections
+ ADD CONSTRAINT fk_f1472b95f3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY boards
ADD CONSTRAINT fk_f15266b5f9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10286,21 +24530,42 @@ ALTER TABLE ONLY ci_stages
ALTER TABLE ONLY system_note_metadata
ADD CONSTRAINT fk_fbd87415c9 FOREIGN KEY (description_version_id) REFERENCES description_versions(id) ON DELETE SET NULL;
+ALTER TABLE ONLY vulnerability_remediations
+ ADD CONSTRAINT fk_fc61a535a0 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_fd82eae0b9 FOREIGN KEY (head_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-ALTER TABLE ONLY namespaces
- ADD CONSTRAINT fk_fdd12e5b80 FOREIGN KEY (plan_id) REFERENCES plans(id) ON DELETE SET NULL;
-
ALTER TABLE ONLY project_import_data
ADD CONSTRAINT fk_ffb9ee3a10 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY issues
ADD CONSTRAINT fk_ffed080f01 FOREIGN KEY (updated_by_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_geo_event_log_on_geo_event_id FOREIGN KEY (geo_event_id) REFERENCES geo_events(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY path_locks
+ ADD CONSTRAINT fk_path_locks_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY personal_access_tokens
ADD CONSTRAINT fk_personal_access_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_settings
+ ADD CONSTRAINT fk_project_settings_push_rule_id FOREIGN KEY (push_rule_id) REFERENCES push_rules(id) ON DELETE SET NULL;
+
+ALTER TABLE ONLY projects
+ ADD CONSTRAINT fk_projects_namespace_id FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE RESTRICT;
+
+ALTER TABLE ONLY protected_branch_merge_access_levels
+ ADD CONSTRAINT fk_protected_branch_merge_access_levels_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY protected_branch_push_access_levels
+ ADD CONSTRAINT fk_protected_branch_push_access_levels_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY protected_tag_create_access_levels
+ ADD CONSTRAINT fk_protected_tag_create_access_levels_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY approval_merge_request_rules
ADD CONSTRAINT fk_rails_004ce82224 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
@@ -10310,12 +24575,27 @@ ALTER TABLE ONLY namespace_statistics
ALTER TABLE ONLY clusters_applications_elastic_stacks
ADD CONSTRAINT fk_rails_026f219f46 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY incident_management_oncall_participants
+ ADD CONSTRAINT fk_rails_032b12996a FOREIGN KEY (oncall_rotation_id) REFERENCES incident_management_oncall_rotations(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY events
ADD CONSTRAINT fk_rails_0434b48643 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY ip_restrictions
ADD CONSTRAINT fk_rails_04a93778d5 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY terraform_state_versions
+ ADD CONSTRAINT fk_rails_04f176e239 FOREIGN KEY (terraform_state_id) REFERENCES terraform_states(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY analytics_devops_adoption_segment_selections
+ ADD CONSTRAINT fk_rails_053f00a9da FOREIGN KEY (segment_id) REFERENCES analytics_devops_adoption_segments(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY ci_build_report_results
+ ADD CONSTRAINT fk_rails_056d298d48 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY ci_daily_build_group_report_results
+ ADD CONSTRAINT fk_rails_0667f7608c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_subscriptions_projects
ADD CONSTRAINT fk_rails_0818751483 FOREIGN KEY (downstream_project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10328,12 +24608,18 @@ ALTER TABLE ONLY trending_projects
ALTER TABLE ONLY project_deploy_tokens
ADD CONSTRAINT fk_rails_0aca134388 FOREIGN KEY (deploy_token_id) REFERENCES deploy_tokens(id) ON DELETE CASCADE;
-ALTER TABLE ONLY analytics_repository_file_commits
- ADD CONSTRAINT fk_rails_0aefa9ee3e FOREIGN KEY (analytics_repository_file_id) REFERENCES analytics_repository_files(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_group_distributions
+ ADD CONSTRAINT fk_rails_0adf75c347 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE RESTRICT;
ALTER TABLE ONLY packages_conan_file_metadata
ADD CONSTRAINT fk_rails_0afabd9328 FOREIGN KEY (package_file_id) REFERENCES packages_package_files(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_build_pending_states
+ ADD CONSTRAINT fk_rails_0bbbfeaf9d FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY operations_user_lists
+ ADD CONSTRAINT fk_rails_0c716e079b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY geo_node_statuses
ADD CONSTRAINT fk_rails_0ecc699c2a FOREIGN KEY (geo_node_id) REFERENCES geo_nodes(id) ON DELETE CASCADE;
@@ -10346,15 +24632,24 @@ ALTER TABLE ONLY user_synced_attributes_metadata
ALTER TABLE ONLY project_authorizations
ADD CONSTRAINT fk_rails_0f84bb11f3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issue_email_participants
+ ADD CONSTRAINT fk_rails_0fdfd8b811 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_request_context_commits
ADD CONSTRAINT fk_rails_0fe0039f60 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_build_trace_chunks
ADD CONSTRAINT fk_rails_1013b761f2 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_exports
+ ADD CONSTRAINT fk_rails_1019162882 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY prometheus_alert_events
ADD CONSTRAINT fk_rails_106f901176 FOREIGN KEY (prometheus_alert_id) REFERENCES prometheus_alerts(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_sources_projects
+ ADD CONSTRAINT fk_rails_10a1eb379a FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY zoom_meetings
ADD CONSTRAINT fk_rails_1190f0e0fa FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10370,9 +24665,21 @@ ALTER TABLE ONLY description_versions
ALTER TABLE ONLY project_statistics
ADD CONSTRAINT fk_rails_12c471002f FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_details
+ ADD CONSTRAINT fk_rails_12e0b3043d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY bulk_imports
+ ADD CONSTRAINT fk_rails_130a09357d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY diff_note_positions
+ ADD CONSTRAINT fk_rails_13c7212859 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY users_security_dashboard_projects
ADD CONSTRAINT fk_rails_150cd5682c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_build_report_results
+ ADD CONSTRAINT fk_rails_16cb1ff064 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY project_deploy_tokens
ADD CONSTRAINT fk_rails_170e03cbaf FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10391,9 +24698,30 @@ ALTER TABLE ONLY cluster_providers_aws
ALTER TABLE ONLY grafana_integrations
ADD CONSTRAINT fk_rails_18d0e2b564 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY bulk_import_failures
+ ADD CONSTRAINT fk_rails_1964240b8c FOREIGN KEY (bulk_import_entity_id) REFERENCES bulk_import_entities(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY group_wiki_repositories
+ ADD CONSTRAINT fk_rails_19755e374b FOREIGN KEY (shard_id) REFERENCES shards(id) ON DELETE RESTRICT;
+
+ALTER TABLE ONLY open_project_tracker_data
+ ADD CONSTRAINT fk_rails_1987546e48 FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY gpg_signatures
ADD CONSTRAINT fk_rails_19d4f1c6f9 FOREIGN KEY (gpg_key_subkey_id) REFERENCES gpg_key_subkeys(id) ON DELETE SET NULL;
+ALTER TABLE ONLY incident_management_oncall_schedules
+ ADD CONSTRAINT fk_rails_19e83fdd65 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY vulnerability_user_mentions
+ ADD CONSTRAINT fk_rails_1a41c485cd FOREIGN KEY (vulnerability_id) REFERENCES vulnerabilities(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY packages_debian_file_metadata
+ ADD CONSTRAINT fk_rails_1ae85be112 FOREIGN KEY (package_file_id) REFERENCES packages_package_files(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY issuable_slas
+ ADD CONSTRAINT fk_rails_1b8768cd63 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY board_assignees
ADD CONSTRAINT fk_rails_1c0ff59e82 FOREIGN KEY (assignee_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -10403,12 +24731,12 @@ ALTER TABLE ONLY epic_user_mentions
ALTER TABLE ONLY approver_groups
ADD CONSTRAINT fk_rails_1cdcbd7723 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_refs
- ADD CONSTRAINT fk_rails_1da48d19ce FOREIGN KEY (last_updated_by_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-
ALTER TABLE ONLY boards
ADD CONSTRAINT fk_rails_1e9a074a35 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY boards_epic_board_positions
+ ADD CONSTRAINT fk_rails_1ecfd9f2de FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY geo_repository_created_events
ADD CONSTRAINT fk_rails_1f49e46a61 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10418,9 +24746,6 @@ ALTER TABLE ONLY approval_merge_request_rules_groups
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT fk_rails_20976e6fd9 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-ALTER TABLE ONLY merge_request_milestones
- ADD CONSTRAINT fk_rails_212ba37b52 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY user_statuses
ADD CONSTRAINT fk_rails_2178592333 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -10433,18 +24758,42 @@ ALTER TABLE ONLY clusters_applications_runners
ALTER TABLE ONLY service_desk_settings
ADD CONSTRAINT fk_rails_223a296a85 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY protected_tag_create_access_levels
- ADD CONSTRAINT fk_rails_2349b78b91 FOREIGN KEY (user_id) REFERENCES users(id);
+ALTER TABLE ONLY saml_group_links
+ ADD CONSTRAINT fk_rails_22e312c530 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY group_custom_attributes
ADD CONSTRAINT fk_rails_246e0db83a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY incident_management_oncall_rotations
+ ADD CONSTRAINT fk_rails_256e0bc604 FOREIGN KEY (oncall_schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY analytics_devops_adoption_snapshots
+ ADD CONSTRAINT fk_rails_25da9a92c0 FOREIGN KEY (segment_id) REFERENCES analytics_devops_adoption_segments(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY cluster_agents
+ ADD CONSTRAINT fk_rails_25e9fc2d5d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY boards_epic_user_preferences
+ ADD CONSTRAINT fk_rails_268c57d62d FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY group_wiki_repositories
+ ADD CONSTRAINT fk_rails_26f867598c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY lfs_file_locks
ADD CONSTRAINT fk_rails_27a1d98fa8 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE ONLY project_alerting_settings
ADD CONSTRAINT fk_rails_27a84b407d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dast_site_validations
+ ADD CONSTRAINT fk_rails_285c617324 FOREIGN KEY (dast_site_token_id) REFERENCES dast_site_tokens(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY vulnerability_findings_remediations
+ ADD CONSTRAINT fk_rails_28a8d0cf93 FOREIGN KEY (vulnerability_occurrence_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY resource_state_events
+ ADD CONSTRAINT fk_rails_29af06892a FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY reviews
ADD CONSTRAINT fk_rails_29e6f859c4 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -10460,15 +24809,33 @@ ALTER TABLE ONLY group_group_links
ALTER TABLE ONLY geo_repository_updated_events
ADD CONSTRAINT fk_rails_2b70854c08 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_group_component_files
+ ADD CONSTRAINT fk_rails_2b8992dd83 FOREIGN KEY (architecture_id) REFERENCES packages_debian_group_architectures(id) ON DELETE RESTRICT;
+
+ALTER TABLE ONLY boards_epic_board_labels
+ ADD CONSTRAINT fk_rails_2bedeb8799 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY protected_branch_unprotect_access_levels
ADD CONSTRAINT fk_rails_2d2aba21ef FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_freeze_periods
+ ADD CONSTRAINT fk_rails_2e02bbd1a6 FOREIGN KEY (project_id) REFERENCES projects(id);
+
+ALTER TABLE ONLY issuable_severities
+ ADD CONSTRAINT fk_rails_2fbb74ad6d FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY saml_providers
ADD CONSTRAINT fk_rails_306d459be7 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_state_events
+ ADD CONSTRAINT fk_rails_3112bba7dc FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_request_diff_commits
ADD CONSTRAINT fk_rails_316aaceda3 FOREIGN KEY (merge_request_diff_id) REFERENCES merge_request_diffs(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_import_states
+ ADD CONSTRAINT fk_rails_31c3e0503a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY zoom_meetings
ADD CONSTRAINT fk_rails_3263f29616 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
@@ -10484,18 +24851,33 @@ ALTER TABLE ONLY merge_request_metrics
ALTER TABLE ONLY suggestions
ADD CONSTRAINT fk_rails_33b03a535c FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY requirements
+ ADD CONSTRAINT fk_rails_33fed8aa4e FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
+
+ALTER TABLE ONLY metrics_dashboard_annotations
+ ADD CONSTRAINT fk_rails_345ab51043 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY wiki_page_slugs
+ ADD CONSTRAINT fk_rails_358b46be14 FOREIGN KEY (wiki_page_meta_id) REFERENCES wiki_page_meta(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY board_labels
ADD CONSTRAINT fk_rails_362b0600a3 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
ALTER TABLE ONLY merge_request_blocks
ADD CONSTRAINT fk_rails_364d4bea8b FOREIGN KEY (blocked_merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_reviewers
+ ADD CONSTRAINT fk_rails_3704a66140 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY analytics_cycle_analytics_project_stages
ADD CONSTRAINT fk_rails_3829e49b66 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY issue_user_mentions
ADD CONSTRAINT fk_rails_3861d9fefa FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespace_settings
+ ADD CONSTRAINT fk_rails_3896d4fae5 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY self_managed_prometheus_alert_events
ADD CONSTRAINT fk_rails_3936dadc62 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10523,6 +24905,9 @@ ALTER TABLE ONLY snippet_user_mentions
ALTER TABLE ONLY clusters_applications_helm
ADD CONSTRAINT fk_rails_3e2b1c06bc FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_package_file_build_infos
+ ADD CONSTRAINT fk_rails_3e3f630188 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY epic_user_mentions
ADD CONSTRAINT fk_rails_3eaf4d88cc FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
@@ -10550,6 +24935,12 @@ ALTER TABLE ONLY ci_refs
ALTER TABLE ONLY ci_resources
ADD CONSTRAINT fk_rails_430336af2d FOREIGN KEY (resource_group_id) REFERENCES ci_resource_groups(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_applications_fluentd
+ ADD CONSTRAINT fk_rails_4319b1dcd2 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY operations_strategies_user_lists
+ ADD CONSTRAINT fk_rails_43241e8d29 FOREIGN KEY (strategy_id) REFERENCES operations_strategies(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY remote_mirrors
ADD CONSTRAINT fk_rails_43a9aa4ca8 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10562,6 +24953,9 @@ ALTER TABLE ONLY merge_request_assignees
ALTER TABLE ONLY packages_dependency_links
ADD CONSTRAINT fk_rails_4437bf4070 FOREIGN KEY (dependency_id) REFERENCES packages_dependencies(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespace_onboarding_actions
+ ADD CONSTRAINT fk_rails_4504f6875a FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY project_auto_devops
ADD CONSTRAINT fk_rails_45436b12b2 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10583,9 +24977,15 @@ ALTER TABLE ONLY vulnerability_feedback
ALTER TABLE ONLY user_custom_attributes
ADD CONSTRAINT fk_rails_47b91868a8 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pipeline_artifacts
+ ADD CONSTRAINT fk_rails_4a70390ca6 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY group_deletion_schedules
ADD CONSTRAINT fk_rails_4b8c694a6c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY snippet_repository_storage_moves
+ ADD CONSTRAINT fk_rails_4b950f5b94 FOREIGN KEY (snippet_id) REFERENCES snippets(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY design_management_designs
ADD CONSTRAINT fk_rails_4bb1073360 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10598,21 +24998,48 @@ ALTER TABLE ONLY project_metrics_settings
ALTER TABLE ONLY prometheus_metrics
ADD CONSTRAINT fk_rails_4c8957a707 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY scim_identities
+ ADD CONSTRAINT fk_rails_4d2056ebd9 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY snippet_user_mentions
ADD CONSTRAINT fk_rails_4d3f96b2cb FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY deployment_clusters
+ ADD CONSTRAINT fk_rails_4e6243e120 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY geo_repository_renamed_events
ADD CONSTRAINT fk_rails_4e6524febb FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY aws_roles
ADD CONSTRAINT fk_rails_4ed56f4720 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY security_scans
+ ADD CONSTRAINT fk_rails_4ef1e6b4c6 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY packages_debian_publications
+ ADD CONSTRAINT fk_rails_4fc8ebd03e FOREIGN KEY (distribution_id) REFERENCES packages_debian_project_distributions(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_request_diff_files
ADD CONSTRAINT fk_rails_501aa0a391 FOREIGN KEY (merge_request_diff_id) REFERENCES merge_request_diffs(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_iteration_events
+ ADD CONSTRAINT fk_rails_501fa15d69 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
+
+ALTER TABLE ONLY status_page_settings
+ ADD CONSTRAINT fk_rails_506e5ba391 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY project_repository_storage_moves
+ ADD CONSTRAINT fk_rails_5106dbd44a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY bulk_import_configurations
+ ADD CONSTRAINT fk_rails_536b96bff1 FOREIGN KEY (bulk_import_id) REFERENCES bulk_imports(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY x509_commit_signatures
ADD CONSTRAINT fk_rails_53fe41188f FOREIGN KEY (x509_certificate_id) REFERENCES x509_certificates(id) ON DELETE CASCADE;
+ALTER TABLE ONLY analytics_cycle_analytics_group_value_streams
+ ADD CONSTRAINT fk_rails_540627381a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY geo_node_namespace_links
ADD CONSTRAINT fk_rails_546bf08d3e FOREIGN KEY (geo_node_id) REFERENCES geo_nodes(id) ON DELETE CASCADE;
@@ -10622,12 +25049,30 @@ ALTER TABLE ONLY clusters_applications_knative
ALTER TABLE ONLY clusters_applications_prometheus
ADD CONSTRAINT fk_rails_557e773639 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY terraform_states
+ ADD CONSTRAINT fk_rails_558901b030 FOREIGN KEY (locked_by_user_id) REFERENCES users(id);
+
+ALTER TABLE ONLY issuable_metric_images
+ ADD CONSTRAINT fk_rails_56417a5a7f FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY group_deploy_keys
+ ADD CONSTRAINT fk_rails_5682fc07f8 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT;
+
+ALTER TABLE ONLY experiment_users
+ ADD CONSTRAINT fk_rails_56d4708b4a FOREIGN KEY (experiment_id) REFERENCES experiments(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issue_user_mentions
ADD CONSTRAINT fk_rails_57581fda73 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
ALTER TABLE ONLY merge_request_assignees
ADD CONSTRAINT fk_rails_579d375628 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_project_architectures
+ ADD CONSTRAINT fk_rails_5808663adf FOREIGN KEY (distribution_id) REFERENCES packages_debian_project_distributions(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY clusters_applications_cilium
+ ADD CONSTRAINT fk_rails_59dc12eea6 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY analytics_cycle_analytics_group_stages
ADD CONSTRAINT fk_rails_5a22f40223 FOREIGN KEY (start_event_label_id) REFERENCES labels(id) ON DELETE CASCADE;
@@ -10640,6 +25085,9 @@ ALTER TABLE ONLY resource_label_events
ALTER TABLE ONLY approval_merge_request_rules_groups
ADD CONSTRAINT fk_rails_5b2ecf6139 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES approval_merge_request_rules(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespace_limits
+ ADD CONSTRAINT fk_rails_5b3f2bc334 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY protected_environment_deploy_access_levels
ADD CONSTRAINT fk_rails_5b9f6970fe FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -10667,21 +25115,42 @@ ALTER TABLE ONLY resource_weight_events
ALTER TABLE ONLY approval_project_rules
ADD CONSTRAINT fk_rails_5fb4dd100b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY protected_branch_merge_access_levels
- ADD CONSTRAINT fk_rails_5ffb4f3590 FOREIGN KEY (user_id) REFERENCES users(id);
+ALTER TABLE ONLY incident_management_oncall_participants
+ ADD CONSTRAINT fk_rails_5fe86ea341 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY user_highest_roles
+ ADD CONSTRAINT fk_rails_60f6c325a6 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY group_deploy_tokens
+ ADD CONSTRAINT fk_rails_61a572b41a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY status_page_published_incidents
+ ADD CONSTRAINT fk_rails_61e5493940 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY deployment_clusters
+ ADD CONSTRAINT fk_rails_6359a164df FOREIGN KEY (deployment_id) REFERENCES deployments(id) ON DELETE CASCADE;
ALTER TABLE ONLY evidences
ADD CONSTRAINT fk_rails_6388b435a6 FOREIGN KEY (release_id) REFERENCES releases(id) ON DELETE CASCADE;
+ALTER TABLE ONLY jira_imports
+ ADD CONSTRAINT fk_rails_63cbe52ada FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY vulnerability_occurrence_pipelines
ADD CONSTRAINT fk_rails_6421e35d7d FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_deploy_tokens
+ ADD CONSTRAINT fk_rails_6477b01f6b FOREIGN KEY (deploy_token_id) REFERENCES deploy_tokens(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY reviews
ADD CONSTRAINT fk_rails_64798be025 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY operations_feature_flags
ADD CONSTRAINT fk_rails_648e241be7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_sources_projects
+ ADD CONSTRAINT fk_rails_64b6855cbc FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY board_group_recent_visits
ADD CONSTRAINT fk_rails_64bfc19bc5 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -10691,6 +25160,9 @@ ALTER TABLE ONLY approval_merge_request_rule_sources
ALTER TABLE ONLY ci_pipeline_chat_data
ADD CONSTRAINT fk_rails_64ebfab6b3 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_project_rules_protected_branches
+ ADD CONSTRAINT fk_rails_65203aa786 FOREIGN KEY (approval_project_rule_id) REFERENCES approval_project_rules(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY design_management_versions
ADD CONSTRAINT fk_rails_6574200d99 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
@@ -10703,24 +25175,39 @@ ALTER TABLE ONLY operations_feature_flags_clients
ALTER TABLE ONLY web_hook_logs
ADD CONSTRAINT fk_rails_666826e111 FOREIGN KEY (web_hook_id) REFERENCES web_hooks(id) ON DELETE CASCADE;
+ALTER TABLE ONLY jira_imports
+ ADD CONSTRAINT fk_rails_675d38c03b FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE SET NULL;
+
+ALTER TABLE ONLY vulnerability_findings_remediations
+ ADD CONSTRAINT fk_rails_681c85ae0f FOREIGN KEY (vulnerability_remediation_id) REFERENCES vulnerability_remediations(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY resource_iteration_events
+ ADD CONSTRAINT fk_rails_6830c13ac1 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY geo_hashed_storage_migrated_events
ADD CONSTRAINT fk_rails_687ed7d7c5 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY plan_limits
ADD CONSTRAINT fk_rails_69f8b6184f FOREIGN KEY (plan_id) REFERENCES plans(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_feature_flags_issues
+ ADD CONSTRAINT fk_rails_6a8856ca4f FOREIGN KEY (feature_flag_id) REFERENCES operations_feature_flags(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY prometheus_alerts
ADD CONSTRAINT fk_rails_6d9b283465 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
-ALTER TABLE ONLY merge_request_milestones
- ADD CONSTRAINT fk_rails_6da5e88b3c FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY term_agreements
ADD CONSTRAINT fk_rails_6ea6520e4a FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_compliance_framework_settings
+ ADD CONSTRAINT fk_rails_6f5294f16c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY users_security_dashboard_projects
ADD CONSTRAINT fk_rails_6f6cf8e66e FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dast_sites
+ ADD CONSTRAINT fk_rails_6febb6ea9c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_builds_runner_session
ADD CONSTRAINT fk_rails_70707857d3 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
@@ -10733,9 +25220,27 @@ ALTER TABLE ONLY project_custom_attributes
ALTER TABLE ONLY user_interacted_projects
ADD CONSTRAINT fk_rails_722ceba4f7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY security_findings
+ ADD CONSTRAINT fk_rails_729b763a54 FOREIGN KEY (scanner_id) REFERENCES vulnerability_scanners(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY dast_scanner_profiles
+ ADD CONSTRAINT fk_rails_72a8ba7141 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY vulnerability_historical_statistics
+ ADD CONSTRAINT fk_rails_72b73ed023 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY slack_integrations
ADD CONSTRAINT fk_rails_73db19721a FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
+ALTER TABLE ONLY custom_emoji
+ ADD CONSTRAINT fk_rails_745925b412 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY boards_epic_board_labels
+ ADD CONSTRAINT fk_rails_7471128a8e FOREIGN KEY (epic_board_id) REFERENCES boards_epic_boards(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY dast_site_profiles
+ ADD CONSTRAINT fk_rails_747dc64abc FOREIGN KEY (dast_site_id) REFERENCES dast_sites(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_request_context_commit_diff_files
ADD CONSTRAINT fk_rails_74a00a1787 FOREIGN KEY (merge_request_context_commit_id) REFERENCES merge_request_context_commits(id) ON DELETE CASCADE;
@@ -10748,36 +25253,45 @@ ALTER TABLE ONLY release_links
ALTER TABLE ONLY milestone_releases
ADD CONSTRAINT fk_rails_754f27dbfa FOREIGN KEY (release_id) REFERENCES releases(id) ON DELETE CASCADE;
-ALTER TABLE ONLY analytics_repository_files
- ADD CONSTRAINT fk_rails_755b835007 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY geo_repositories_changed_events
ADD CONSTRAINT fk_rails_75ec0fefcc FOREIGN KEY (geo_node_id) REFERENCES geo_nodes(id) ON DELETE CASCADE;
ALTER TABLE ONLY resource_label_events
ADD CONSTRAINT fk_rails_75efb0a653 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
-ALTER TABLE ONLY path_locks
- ADD CONSTRAINT fk_rails_762cdcf942 FOREIGN KEY (user_id) REFERENCES users(id);
-
ALTER TABLE ONLY x509_certificates
ADD CONSTRAINT fk_rails_76479fb5b4 FOREIGN KEY (x509_issuer_id) REFERENCES x509_issuers(id) ON DELETE CASCADE;
ALTER TABLE ONLY pages_domain_acme_orders
ADD CONSTRAINT fk_rails_76581b1c16 FOREIGN KEY (pages_domain_id) REFERENCES pages_domains(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_publications
+ ADD CONSTRAINT fk_rails_7668c1d606 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY boards_epic_user_preferences
+ ADD CONSTRAINT fk_rails_76c4e9732d FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_subscriptions_projects
ADD CONSTRAINT fk_rails_7871f9a97b FOREIGN KEY (upstream_project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY terraform_states
+ ADD CONSTRAINT fk_rails_78f54ca485 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY software_license_policies
ADD CONSTRAINT fk_rails_7a7a2a92de FOREIGN KEY (software_license_id) REFERENCES software_licenses(id) ON DELETE CASCADE;
ALTER TABLE ONLY project_repositories
ADD CONSTRAINT fk_rails_7a810d4121 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_scopes
+ ADD CONSTRAINT fk_rails_7a9358853b FOREIGN KEY (strategy_id) REFERENCES operations_strategies(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY milestone_releases
ADD CONSTRAINT fk_rails_7ae0756a2d FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_state_events
+ ADD CONSTRAINT fk_rails_7ddc5f7457 FOREIGN KEY (source_merge_request_id) REFERENCES merge_requests(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY application_settings
ADD CONSTRAINT fk_rails_7e112a9599 FOREIGN KEY (instance_administration_project_id) REFERENCES projects(id) ON DELETE SET NULL;
@@ -10787,15 +25301,33 @@ ALTER TABLE ONLY clusters_kubernetes_namespaces
ALTER TABLE ONLY approval_merge_request_rules_users
ADD CONSTRAINT fk_rails_80e6801803 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES approval_merge_request_rules(id) ON DELETE CASCADE;
+ALTER TABLE ONLY required_code_owners_sections
+ ADD CONSTRAINT fk_rails_817708cf2d FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY dast_site_profiles
+ ADD CONSTRAINT fk_rails_83e309d69e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY boards_epic_user_preferences
+ ADD CONSTRAINT fk_rails_851fe1510a FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY deployment_merge_requests
ADD CONSTRAINT fk_rails_86a6d8bf12 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
ALTER TABLE ONLY analytics_language_trend_repository_languages
ADD CONSTRAINT fk_rails_86cc9aef5f FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_diff_details
+ ADD CONSTRAINT fk_rails_86f4d24ecd FOREIGN KEY (merge_request_diff_id) REFERENCES merge_request_diffs(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY clusters_applications_crossplane
ADD CONSTRAINT fk_rails_87186702df FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_package_file_build_infos
+ ADD CONSTRAINT fk_rails_871ca3ae21 FOREIGN KEY (package_file_id) REFERENCES packages_package_files(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY boards_epic_boards
+ ADD CONSTRAINT fk_rails_874c573878 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_runner_namespaces
ADD CONSTRAINT fk_rails_8767676b7a FOREIGN KEY (runner_id) REFERENCES ci_runners(id) ON DELETE CASCADE;
@@ -10805,12 +25337,15 @@ ALTER TABLE ONLY software_license_policies
ALTER TABLE ONLY protected_environment_deploy_access_levels
ADD CONSTRAINT fk_rails_898a13b650 FOREIGN KEY (protected_environment_id) REFERENCES protected_environments(id) ON DELETE CASCADE;
-ALTER TABLE ONLY analytics_repository_file_commits
- ADD CONSTRAINT fk_rails_89bc941356 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY snippet_repositories
+ ADD CONSTRAINT fk_rails_8afd7e2f71 FOREIGN KEY (snippet_id) REFERENCES snippets(id) ON DELETE CASCADE;
ALTER TABLE ONLY gpg_key_subkeys
ADD CONSTRAINT fk_rails_8b2c90b046 FOREIGN KEY (gpg_key_id) REFERENCES gpg_keys(id) ON DELETE CASCADE;
+ALTER TABLE ONLY board_user_preferences
+ ADD CONSTRAINT fk_rails_8b3b23ce82 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY allowed_email_domains
ADD CONSTRAINT fk_rails_8b5da859f9 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -10826,18 +25361,21 @@ ALTER TABLE ONLY packages_conan_metadata
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT fk_rails_8c77e5891a FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_pipeline_messages
+ ADD CONSTRAINT fk_rails_8d3b04e3e1 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY approval_merge_request_rules_approved_approvers
ADD CONSTRAINT fk_rails_8dc94cff4d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY protected_branch_push_access_levels
- ADD CONSTRAINT fk_rails_8dcb712d65 FOREIGN KEY (user_id) REFERENCES users(id);
-
ALTER TABLE ONLY design_user_mentions
ADD CONSTRAINT fk_rails_8de8c6d632 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
ALTER TABLE ONLY clusters_kubernetes_namespaces
ADD CONSTRAINT fk_rails_8df789f3ab FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE SET NULL;
+ALTER TABLE ONLY alert_management_alert_user_mentions
+ ADD CONSTRAINT fk_rails_8e48eca0fe FOREIGN KEY (alert_management_alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY project_daily_statistics
ADD CONSTRAINT fk_rails_8e549b272d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -10859,9 +25397,24 @@ ALTER TABLE ONLY project_error_tracking_settings
ALTER TABLE ONLY list_user_preferences
ADD CONSTRAINT fk_rails_916d72cafd FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_cleanup_schedules
+ ADD CONSTRAINT fk_rails_92dd0e705c FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY board_labels
ADD CONSTRAINT fk_rails_9374a16edd FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
+ALTER TABLE ONLY alert_management_alert_assignees
+ ADD CONSTRAINT fk_rails_93c0f6703b FOREIGN KEY (alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY scim_identities
+ ADD CONSTRAINT fk_rails_9421a0bffb FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY packages_debian_project_distributions
+ ADD CONSTRAINT fk_rails_94b95e1f84 FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE SET NULL;
+
+ALTER TABLE ONLY packages_pypi_metadata
+ ADD CONSTRAINT fk_rails_9698717cdd FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY packages_dependency_links
ADD CONSTRAINT fk_rails_96ef1c00d3 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
@@ -10877,12 +25430,21 @@ ALTER TABLE ONLY board_project_recent_visits
ALTER TABLE ONLY clusters_kubernetes_namespaces
ADD CONSTRAINT fk_rails_98fe21e486 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY pages_deployments
+ ADD CONSTRAINT fk_rails_993b88f59a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY vulnerability_exports
+ ADD CONSTRAINT fk_rails_9aff2c3b45 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY users_ops_dashboard_projects
ADD CONSTRAINT fk_rails_9b4ebf005b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY project_incident_management_settings
ADD CONSTRAINT fk_rails_9c2ea1b7dd FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_project_components
+ ADD CONSTRAINT fk_rails_9d072b5073 FOREIGN KEY (distribution_id) REFERENCES packages_debian_project_distributions(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY gpg_keys
ADD CONSTRAINT fk_rails_9d1f5d8719 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -10895,12 +25457,18 @@ ALTER TABLE ONLY badges
ALTER TABLE ONLY clusters_applications_cert_managers
ADD CONSTRAINT fk_rails_9e4f2cb4b2 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_milestone_events
+ ADD CONSTRAINT fk_rails_a006df5590 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY namespace_root_storage_statistics
ADD CONSTRAINT fk_rails_a0702c430b FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY project_aliases
ADD CONSTRAINT fk_rails_a1804f74a7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_user_mentions
+ ADD CONSTRAINT fk_rails_a18600f210 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY jira_tracker_data
ADD CONSTRAINT fk_rails_a299066916 FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
@@ -10928,12 +25496,24 @@ ALTER TABLE ONLY user_preferences
ALTER TABLE ONLY sentry_issues
ADD CONSTRAINT fk_rails_a6a9612965 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_permission_export_uploads
+ ADD CONSTRAINT fk_rails_a7130085e3 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY repository_languages
ADD CONSTRAINT fk_rails_a750ec87a8 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dependency_proxy_manifests
+ ADD CONSTRAINT fk_rails_a758021fb0 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY resource_milestone_events
+ ADD CONSTRAINT fk_rails_a788026e85 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY term_agreements
ADD CONSTRAINT fk_rails_a88721bcdf FOREIGN KEY (term_id) REFERENCES application_setting_terms(id);
+ALTER TABLE ONLY ci_pipeline_artifacts
+ ADD CONSTRAINT fk_rails_a9e811a466 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_request_user_mentions
ADD CONSTRAINT fk_rails_aa1b2961b1 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
@@ -10943,21 +25523,42 @@ ALTER TABLE ONLY x509_commit_signatures
ALTER TABLE ONLY ci_build_trace_sections
ADD CONSTRAINT fk_rails_ab7c104e26 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_iteration_events
+ ADD CONSTRAINT fk_rails_abf5d4affa FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY clusters
ADD CONSTRAINT fk_rails_ac3a663d79 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY packages_composer_metadata
+ ADD CONSTRAINT fk_rails_ad48c2e5bb FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY analytics_cycle_analytics_group_stages
ADD CONSTRAINT fk_rails_ae5da3409b FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY metrics_dashboard_annotations
+ ADD CONSTRAINT fk_rails_aeb11a7643 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY bulk_import_trackers
+ ADD CONSTRAINT fk_rails_aed566d3f3 FOREIGN KEY (bulk_import_entity_id) REFERENCES bulk_import_entities(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY pool_repositories
ADD CONSTRAINT fk_rails_af3f8c5d62 FOREIGN KEY (shard_id) REFERENCES shards(id) ON DELETE RESTRICT;
+ALTER TABLE ONLY vulnerability_statistics
+ ADD CONSTRAINT fk_rails_af61a7df4c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY resource_label_events
ADD CONSTRAINT fk_rails_b126799f57 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE SET NULL;
+ALTER TABLE ONLY webauthn_registrations
+ ADD CONSTRAINT fk_rails_b15c016782 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY packages_build_infos
ADD CONSTRAINT fk_rails_b18868292d FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY authentication_events
+ ADD CONSTRAINT fk_rails_b204656a54 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY merge_trains
ADD CONSTRAINT fk_rails_b29261ce31 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -10970,15 +25571,18 @@ ALTER TABLE ONLY issues_prometheus_alert_events
ALTER TABLE ONLY merge_trains
ADD CONSTRAINT fk_rails_b374b5225d FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY issue_milestones
- ADD CONSTRAINT fk_rails_b3daad894f FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY application_settings
ADD CONSTRAINT fk_rails_b53e481273 FOREIGN KEY (custom_project_templates_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
+ALTER TABLE ONLY packages_debian_project_component_files
+ ADD CONSTRAINT fk_rails_b543a9622b FOREIGN KEY (architecture_id) REFERENCES packages_debian_project_architectures(id) ON DELETE RESTRICT;
+
ALTER TABLE ONLY namespace_aggregation_schedules
ADD CONSTRAINT fk_rails_b565c8d16c FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_project_rules_protected_branches
+ ADD CONSTRAINT fk_rails_b7567b031b FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY alerts_service_data
ADD CONSTRAINT fk_rails_b93215a42c FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
@@ -10991,6 +25595,12 @@ ALTER TABLE ONLY approval_project_rules_users
ALTER TABLE ONLY lists
ADD CONSTRAINT fk_rails_baed5f39b7 FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE CASCADE;
+ALTER TABLE ONLY security_findings
+ ADD CONSTRAINT fk_rails_bb63863cf1 FOREIGN KEY (scan_id) REFERENCES security_scans(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY packages_debian_project_component_files
+ ADD CONSTRAINT fk_rails_bbe9ebfbd9 FOREIGN KEY (component_id) REFERENCES packages_debian_project_components(id) ON DELETE RESTRICT;
+
ALTER TABLE ONLY approval_merge_request_rules_users
ADD CONSTRAINT fk_rails_bc8972fa55 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -11006,6 +25616,9 @@ ALTER TABLE ONLY elasticsearch_indexed_namespaces
ALTER TABLE ONLY vulnerability_occurrence_identifiers
ADD CONSTRAINT fk_rails_be2e49e1d0 FOREIGN KEY (identifier_id) REFERENCES vulnerability_identifiers(id) ON DELETE CASCADE;
+ALTER TABLE ONLY alert_management_http_integrations
+ ADD CONSTRAINT fk_rails_bec49f52cc FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY vulnerability_occurrences
ADD CONSTRAINT fk_rails_bf5b788ca7 FOREIGN KEY (scanner_id) REFERENCES vulnerability_scanners(id) ON DELETE CASCADE;
@@ -11015,8 +25628,8 @@ ALTER TABLE ONLY resource_weight_events
ALTER TABLE ONLY design_management_designs
ADD CONSTRAINT fk_rails_bfe283ec3c FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY u2f_registrations
- ADD CONSTRAINT fk_rails_bfe6a84544 FOREIGN KEY (user_id) REFERENCES users(id);
+ALTER TABLE ONLY atlassian_identities
+ ADD CONSTRAINT fk_rails_c02928bc18 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE ONLY serverless_domain_cluster
ADD CONSTRAINT fk_rails_c09009dee1 FOREIGN KEY (pages_domain_id) REFERENCES pages_domains(id) ON DELETE CASCADE;
@@ -11024,44 +25637,86 @@ ALTER TABLE ONLY serverless_domain_cluster
ALTER TABLE ONLY labels
ADD CONSTRAINT fk_rails_c1ac5161d8 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY backup_labels
+ ADD CONSTRAINT fk_rails_c1ac5161d8 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY project_feature_usages
ADD CONSTRAINT fk_rails_c22a50024b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_canonical_emails
+ ADD CONSTRAINT fk_rails_c2bd828b51 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY project_repositories
ADD CONSTRAINT fk_rails_c3258dc63b FOREIGN KEY (shard_id) REFERENCES shards(id) ON DELETE RESTRICT;
+ALTER TABLE ONLY packages_nuget_dependency_link_metadata
+ ADD CONSTRAINT fk_rails_c3313ee2e4 FOREIGN KEY (dependency_link_id) REFERENCES packages_dependency_links(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY group_deploy_keys_groups
+ ADD CONSTRAINT fk_rails_c3854f19f5 FOREIGN KEY (group_deploy_key_id) REFERENCES group_deploy_keys(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY pages_deployments
+ ADD CONSTRAINT fk_rails_c3a90cf29b FOREIGN KEY (ci_build_id) REFERENCES ci_builds(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY merge_request_user_mentions
ADD CONSTRAINT fk_rails_c440b9ea31 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_job_artifacts
ADD CONSTRAINT fk_rails_c5137cb2c1 FOREIGN KEY (job_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_events
+ ADD CONSTRAINT fk_rails_c6c20d0094 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY project_settings
ADD CONSTRAINT fk_rails_c6df6e6328 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY container_expiration_policies
ADD CONSTRAINT fk_rails_c7360f09ad FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY wiki_page_meta
+ ADD CONSTRAINT fk_rails_c7a0c59cf1 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY scim_oauth_access_tokens
ADD CONSTRAINT fk_rails_c84404fb6c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY vulnerability_occurrences
ADD CONSTRAINT fk_rails_c8661a61eb FOREIGN KEY (primary_identifier_id) REFERENCES vulnerability_identifiers(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_export_jobs
+ ADD CONSTRAINT fk_rails_c88d8db2e1 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY resource_state_events
+ ADD CONSTRAINT fk_rails_c913c64977 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY resource_milestone_events
+ ADD CONSTRAINT fk_rails_c940fb9fc5 FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY gpg_signatures
ADD CONSTRAINT fk_rails_c97176f5f7 FOREIGN KEY (gpg_key_id) REFERENCES gpg_keys(id) ON DELETE SET NULL;
ALTER TABLE ONLY board_group_recent_visits
ADD CONSTRAINT fk_rails_ca04c38720 FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
+ALTER TABLE ONLY boards_epic_board_positions
+ ADD CONSTRAINT fk_rails_cb4563dd6e FOREIGN KEY (epic_board_id) REFERENCES boards_epic_boards(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY vulnerability_finding_links
+ ADD CONSTRAINT fk_rails_cbdfde27ce FOREIGN KEY (vulnerability_occurrence_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issues_self_managed_prometheus_alert_events
ADD CONSTRAINT fk_rails_cc5d88bbb0 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_strategies_user_lists
+ ADD CONSTRAINT fk_rails_ccb7e4bc0b FOREIGN KEY (user_list_id) REFERENCES operations_user_lists(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issue_tracker_data
ADD CONSTRAINT fk_rails_ccc0840427 FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
-ALTER TABLE ONLY analytics_repository_file_edits
- ADD CONSTRAINT fk_rails_ce1d13b872 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_milestone_events
+ ADD CONSTRAINT fk_rails_cedf8cce4d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
+
+ALTER TABLE ONLY resource_iteration_events
+ ADD CONSTRAINT fk_rails_cee126f66c FOREIGN KEY (iteration_id) REFERENCES sprints(id) ON DELETE CASCADE;
ALTER TABLE ONLY epic_metrics
ADD CONSTRAINT fk_rails_d071904753 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
@@ -11069,9 +25724,18 @@ ALTER TABLE ONLY epic_metrics
ALTER TABLE ONLY subscriptions
ADD CONSTRAINT fk_rails_d0c8bda804 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_strategies
+ ADD CONSTRAINT fk_rails_d183b6e6dd FOREIGN KEY (feature_flag_id) REFERENCES operations_feature_flags(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY project_mirror_data
ADD CONSTRAINT fk_rails_d1aad367d7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY cluster_agent_tokens
+ ADD CONSTRAINT fk_rails_d1d26abc25 FOREIGN KEY (agent_id) REFERENCES cluster_agents(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY requirements_management_test_reports
+ ADD CONSTRAINT fk_rails_d1e8b498bf FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY pool_repositories
ADD CONSTRAINT fk_rails_d2711daad4 FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE SET NULL;
@@ -11081,27 +25745,45 @@ ALTER TABLE ONLY group_group_links
ALTER TABLE ONLY vulnerability_issue_links
ADD CONSTRAINT fk_rails_d459c19036 FOREIGN KEY (vulnerability_id) REFERENCES vulnerabilities(id) ON DELETE CASCADE;
+ALTER TABLE ONLY alert_management_alert_assignees
+ ADD CONSTRAINT fk_rails_d47570ac62 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY geo_hashed_storage_attachments_events
ADD CONSTRAINT fk_rails_d496b088e9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY analytics_repository_file_edits
- ADD CONSTRAINT fk_rails_d74fd62274 FOREIGN KEY (analytics_repository_file_id) REFERENCES analytics_repository_files(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_reviewers
+ ADD CONSTRAINT fk_rails_d9fec24b9d FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY jira_imports
+ ADD CONSTRAINT fk_rails_da617096ce FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
ALTER TABLE ONLY issues_prometheus_alert_events
ADD CONSTRAINT fk_rails_db5b756534 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY board_user_preferences
+ ADD CONSTRAINT fk_rails_dbebdaa8fe FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY vulnerability_occurrence_pipelines
ADD CONSTRAINT fk_rails_dc3ae04693 FOREIGN KEY (occurrence_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
ALTER TABLE ONLY deployment_merge_requests
ADD CONSTRAINT fk_rails_dcbce9f4df FOREIGN KEY (deployment_id) REFERENCES deployments(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_group_component_files
+ ADD CONSTRAINT fk_rails_dd262386e9 FOREIGN KEY (component_id) REFERENCES packages_debian_group_components(id) ON DELETE RESTRICT;
+
ALTER TABLE ONLY user_callouts
ADD CONSTRAINT fk_rails_ddfdd80f3d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT fk_rails_debd54e456 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_project_distributions
+ ADD CONSTRAINT fk_rails_df44271a30 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE RESTRICT;
+
+ALTER TABLE ONLY incident_management_oncall_shifts
+ ADD CONSTRAINT fk_rails_df4feb286a FOREIGN KEY (rotation_id) REFERENCES incident_management_oncall_rotations(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY analytics_cycle_analytics_group_stages
ADD CONSTRAINT fk_rails_dfb37c880d FOREIGN KEY (end_event_label_id) REFERENCES labels(id) ON DELETE CASCADE;
@@ -11123,18 +25805,30 @@ ALTER TABLE ONLY vulnerability_occurrence_identifiers
ALTER TABLE ONLY serverless_domain_cluster
ADD CONSTRAINT fk_rails_e59e868733 FOREIGN KEY (clusters_applications_knative_id) REFERENCES clusters_applications_knative(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_external_issue_links
+ ADD CONSTRAINT fk_rails_e5ba7f7b13 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY approval_merge_request_rule_sources
ADD CONSTRAINT fk_rails_e605a04f76 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES approval_merge_request_rules(id) ON DELETE CASCADE;
ALTER TABLE ONLY prometheus_alerts
ADD CONSTRAINT fk_rails_e6351447ec FOREIGN KEY (prometheus_metric_id) REFERENCES prometheus_metrics(id) ON DELETE CASCADE;
+ALTER TABLE ONLY requirements_management_test_reports
+ ADD CONSTRAINT fk_rails_e67d085910 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY merge_request_metrics
ADD CONSTRAINT fk_rails_e6d7c24d1b FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
ALTER TABLE ONLY draft_notes
ADD CONSTRAINT fk_rails_e753681674 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dast_site_tokens
+ ADD CONSTRAINT fk_rails_e84f721a8e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY group_deploy_keys_groups
+ ADD CONSTRAINT fk_rails_e87145115d FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY description_versions
ADD CONSTRAINT fk_rails_e8f4caf9c7 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
@@ -11147,8 +25841,29 @@ ALTER TABLE ONLY merge_request_blocks
ALTER TABLE ONLY protected_branch_unprotect_access_levels
ADD CONSTRAINT fk_rails_e9eb8dc025 FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
-ALTER TABLE ONLY cluster_providers_aws
- ADD CONSTRAINT fk_rails_ed1fdfaeb2 FOREIGN KEY (created_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_test_case_failures
+ ADD CONSTRAINT fk_rails_eab6349715 FOREIGN KEY (test_case_id) REFERENCES ci_test_cases(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY alert_management_alert_user_mentions
+ ADD CONSTRAINT fk_rails_eb2de0cdef FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY snippet_statistics
+ ADD CONSTRAINT fk_rails_ebc283ccf1 FOREIGN KEY (snippet_id) REFERENCES snippets(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY project_security_settings
+ ADD CONSTRAINT fk_rails_ed4abe1338 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY packages_debian_group_distributions
+ ADD CONSTRAINT fk_rails_ede0bb937f FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE SET NULL;
+
+ALTER TABLE ONLY experiment_subjects
+ ADD CONSTRAINT fk_rails_ede5754774 FOREIGN KEY (experiment_id) REFERENCES experiments(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY ci_daily_build_group_report_results
+ ADD CONSTRAINT fk_rails_ee072d13b3 FOREIGN KEY (last_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY packages_debian_group_architectures
+ ADD CONSTRAINT fk_rails_ef667d1b03 FOREIGN KEY (distribution_id) REFERENCES packages_debian_group_distributions(id) ON DELETE CASCADE;
ALTER TABLE ONLY label_priorities
ADD CONSTRAINT fk_rails_ef916d14fa FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -11162,6 +25877,12 @@ ALTER TABLE ONLY prometheus_alerts
ALTER TABLE ONLY import_export_uploads
ADD CONSTRAINT fk_rails_f129140f9e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY requirements
+ ADD CONSTRAINT fk_rails_f212e67e63 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY snippet_repositories
+ ADD CONSTRAINT fk_rails_f21f899728 FOREIGN KEY (shard_id) REFERENCES shards(id) ON DELETE RESTRICT;
+
ALTER TABLE ONLY ci_pipeline_chat_data
ADD CONSTRAINT fk_rails_f300456b63 FOREIGN KEY (chat_name_id) REFERENCES chat_names(id) ON DELETE CASCADE;
@@ -11174,6 +25895,15 @@ ALTER TABLE ONLY insights
ALTER TABLE ONLY board_group_recent_visits
ADD CONSTRAINT fk_rails_f410736518 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_state_events
+ ADD CONSTRAINT fk_rails_f5827a7ccd FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
+
+ALTER TABLE ONLY packages_debian_group_components
+ ADD CONSTRAINT fk_rails_f5f1ef54c6 FOREIGN KEY (distribution_id) REFERENCES packages_debian_group_distributions(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY incident_management_oncall_shifts
+ ADD CONSTRAINT fk_rails_f6eef06841 FOREIGN KEY (participant_id) REFERENCES incident_management_oncall_participants(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY design_user_mentions
ADD CONSTRAINT fk_rails_f7075a53c1 FOREIGN KEY (design_id) REFERENCES design_management_designs(id) ON DELETE CASCADE;
@@ -11195,6 +25925,15 @@ ALTER TABLE ONLY merge_trains
ALTER TABLE ONLY ci_runner_namespaces
ADD CONSTRAINT fk_rails_f9d9ed3308 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_finding_fingerprints
+ ADD CONSTRAINT fk_rails_fa411253b2 FOREIGN KEY (finding_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY requirements_management_test_reports
+ ADD CONSTRAINT fk_rails_fb3308ad55 FOREIGN KEY (requirement_id) REFERENCES requirements(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY operations_feature_flags_issues
+ ADD CONSTRAINT fk_rails_fb4d2a7cb1 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY board_project_recent_visits
ADD CONSTRAINT fk_rails_fb6fc419cb FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -11204,6 +25943,12 @@ ALTER TABLE ONLY serverless_domain_cluster
ALTER TABLE ONLY ci_job_variables
ADD CONSTRAINT fk_rails_fbf3b34792 FOREIGN KEY (job_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_nuget_metadata
+ ADD CONSTRAINT fk_rails_fc0c19f5b4 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY experiment_users
+ ADD CONSTRAINT fk_rails_fd805f771a FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY cluster_groups
ADD CONSTRAINT fk_rails_fdb8648a96 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
@@ -11213,14 +25958,26 @@ ALTER TABLE ONLY project_tracing_settings
ALTER TABLE ONLY resource_label_events
ADD CONSTRAINT fk_rails_fe91ece594 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY issue_milestones
- ADD CONSTRAINT fk_rails_ff90aaa198 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY ci_builds_metadata
ADD CONSTRAINT fk_rails_ffcf702a02 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY services
+ ADD CONSTRAINT fk_services_inherit_from_id FOREIGN KEY (inherit_from_id) REFERENCES services(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY timelogs
ADD CONSTRAINT fk_timelogs_issues_issue_id FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
ALTER TABLE ONLY timelogs
ADD CONSTRAINT fk_timelogs_merge_requests_merge_request_id FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY u2f_registrations
+ ADD CONSTRAINT fk_u2f_registrations_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE product_analytics_events_experimental
+ ADD CONSTRAINT product_analytics_events_experimental_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY user_follow_users
+ ADD CONSTRAINT user_follow_users_followee_id_fkey FOREIGN KEY (followee_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY user_follow_users
+ ADD CONSTRAINT user_follow_users_follower_id_fkey FOREIGN KEY (follower_id) REFERENCES users(id) ON DELETE CASCADE;
diff --git a/db/migrate/20200102140148_add_expanded_environment_name_to_ci_build_metadata.rb b/db/migrate/20200102140148_add_expanded_environment_name_to_ci_build_metadata.rb
deleted file mode 100644
index 21520f86bf8..00000000000
--- a/db/migrate/20200102140148_add_expanded_environment_name_to_ci_build_metadata.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class AddExpandedEnvironmentNameToCiBuildMetadata < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def up
- add_column :ci_builds_metadata, :expanded_environment_name, :string, limit: 255
- end
- # rubocop:enable Migration/PreventStrings
-
- def down
- remove_column :ci_builds_metadata, :expanded_environment_name
- end
-end
diff --git a/db/migrate/20200102170221_add_storage_version_index_to_projects.rb b/db/migrate/20200102170221_add_storage_version_index_to_projects.rb
deleted file mode 100644
index 8965b5eedb9..00000000000
--- a/db/migrate/20200102170221_add_storage_version_index_to_projects.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddStorageVersionIndexToProjects < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, :id, where: 'storage_version < 2 or storage_version IS NULL', name: 'index_on_id_partial_with_legacy_storage'
- end
-
- def down
- remove_concurrent_index :projects, :id, where: 'storage_version < 2 or storage_version IS NULL', name: 'index_on_id_partial_with_legacy_storage'
- end
-end
diff --git a/db/migrate/20200103190741_add_column_for_instance_administrators_group.rb b/db/migrate/20200103190741_add_column_for_instance_administrators_group.rb
deleted file mode 100644
index 5afc7dc6a4d..00000000000
--- a/db/migrate/20200103190741_add_column_for_instance_administrators_group.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddColumnForInstanceAdministratorsGroup < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :instance_administrators_group_id, :integer
- end
-end
diff --git a/db/migrate/20200103192859_add_fk_for_instance_administrators_group.rb b/db/migrate/20200103192859_add_fk_for_instance_administrators_group.rb
deleted file mode 100644
index 0ad37d6bd29..00000000000
--- a/db/migrate/20200103192859_add_fk_for_instance_administrators_group.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddFkForInstanceAdministratorsGroup < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key(
- :application_settings,
- :namespaces,
- column: :instance_administrators_group_id,
- on_delete: :nullify
- )
- end
-
- def down
- remove_foreign_key :application_settings, column: :instance_administrators_group_id
- end
-end
diff --git a/db/migrate/20200103192914_add_index_for_instance_administrators_group.rb b/db/migrate/20200103192914_add_index_for_instance_administrators_group.rb
deleted file mode 100644
index 703dcf5d0e3..00000000000
--- a/db/migrate/20200103192914_add_index_for_instance_administrators_group.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexForInstanceAdministratorsGroup < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :application_settings, :instance_administrators_group_id
- end
-
- def down
- remove_concurrent_index :application_settings, :instance_administrators_group_id
- end
-end
diff --git a/db/migrate/20200103195205_add_autoclose_referenced_issues_to_projects.rb b/db/migrate/20200103195205_add_autoclose_referenced_issues_to_projects.rb
deleted file mode 100644
index db473434205..00000000000
--- a/db/migrate/20200103195205_add_autoclose_referenced_issues_to_projects.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddAutocloseReferencedIssuesToProjects < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- add_column :projects, :autoclose_referenced_issues, :boolean # rubocop:disable Migration/AddColumnsToWideTables
- end
-end
diff --git a/db/migrate/20200104113850_add_forking_access_level_to_project_feature.rb b/db/migrate/20200104113850_add_forking_access_level_to_project_feature.rb
deleted file mode 100644
index 2c5f764ebf3..00000000000
--- a/db/migrate/20200104113850_add_forking_access_level_to_project_feature.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddForkingAccessLevelToProjectFeature < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- add_column :project_features, :forking_access_level, :integer
- end
-end
diff --git a/db/migrate/20200106085831_add_timestamps_to_packages_tags.rb b/db/migrate/20200106085831_add_timestamps_to_packages_tags.rb
deleted file mode 100644
index 2720d9b3297..00000000000
--- a/db/migrate/20200106085831_add_timestamps_to_packages_tags.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class AddTimestampsToPackagesTags < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- # We disable these cops here because adding this column is safe. The table does not
- # have any data in it.
- # rubocop: disable Migration/AddIndex
- def up
- add_timestamps_with_timezone(:packages_tags, null: false)
- add_index(:packages_tags, [:package_id, :updated_at], order: { updated_at: :desc })
- end
-
- # We disable these cops here because adding this column is safe. The table does not
- # have any data in it.
- # rubocop: disable Migration/RemoveIndex
- def down
- remove_index(:packages_tags, [:package_id, :updated_at])
- remove_timestamps(:packages_tags)
- end
-end
diff --git a/db/migrate/20200107172020_add_timestamp_softwarelicensespolicy.rb b/db/migrate/20200107172020_add_timestamp_softwarelicensespolicy.rb
deleted file mode 100644
index 0d62f3051ce..00000000000
--- a/db/migrate/20200107172020_add_timestamp_softwarelicensespolicy.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class AddTimestampSoftwarelicensespolicy < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- add_timestamps_with_timezone(:software_license_policies, null: true)
- end
-
- def down
- remove_timestamps(:software_license_policies)
- end
-end
diff --git a/db/migrate/20200108100603_update_project_hooks_limit.rb b/db/migrate/20200108100603_update_project_hooks_limit.rb
deleted file mode 100644
index 91533b69afa..00000000000
--- a/db/migrate/20200108100603_update_project_hooks_limit.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateProjectHooksLimit < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- return unless Gitlab.com?
-
- create_or_update_plan_limit('project_hooks', 'free', 100)
- create_or_update_plan_limit('project_hooks', 'bronze', 100)
- create_or_update_plan_limit('project_hooks', 'silver', 100)
- end
-
- def down
- return unless Gitlab.com?
-
- create_or_update_plan_limit('project_hooks', 'free', 10)
- create_or_update_plan_limit('project_hooks', 'bronze', 20)
- create_or_update_plan_limit('project_hooks', 'silver', 30)
- end
-end
diff --git a/db/migrate/20200108155731_create_indexes_for_project_api_created_at_order.rb b/db/migrate/20200108155731_create_indexes_for_project_api_created_at_order.rb
deleted file mode 100644
index 2356f08b681..00000000000
--- a/db/migrate/20200108155731_create_indexes_for_project_api_created_at_order.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class CreateIndexesForProjectApiCreatedAtOrder < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, %i(visibility_level created_at id), order: { id: :desc }, name: 'index_projects_on_visibility_level_created_at_id_desc'
- add_concurrent_index :projects, %i(visibility_level created_at id), order: { created_at: :desc, id: :desc }, name: 'index_projects_on_visibility_level_created_at_desc_id_desc'
- remove_concurrent_index_by_name :projects, 'index_projects_on_visibility_level_and_created_at_and_id'
- end
-
- def down
- add_concurrent_index :projects, %i(visibility_level created_at id), name: 'index_projects_on_visibility_level_and_created_at_and_id'
- remove_concurrent_index_by_name :projects, 'index_projects_on_visibility_level_created_at_id_desc'
- remove_concurrent_index_by_name :projects, 'index_projects_on_visibility_level_created_at_desc_id_desc'
- end
-end
diff --git a/db/migrate/20200108233040_remove_index_project_mirror_data_on_jid.rb b/db/migrate/20200108233040_remove_index_project_mirror_data_on_jid.rb
deleted file mode 100644
index 86a69275cb7..00000000000
--- a/db/migrate/20200108233040_remove_index_project_mirror_data_on_jid.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexProjectMirrorDataOnJid < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index :project_mirror_data, :jid
- end
-
- def down
- add_concurrent_index :project_mirror_data, :jid
- end
-end
diff --git a/db/migrate/20200109030418_add_sorting_index_to_packages.rb b/db/migrate/20200109030418_add_sorting_index_to_packages.rb
deleted file mode 100644
index 989f3de3c04..00000000000
--- a/db/migrate/20200109030418_add_sorting_index_to_packages.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddSortingIndexToPackages < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :packages_packages, [:project_id, :created_at]
- add_concurrent_index :packages_packages, [:project_id, :version]
- add_concurrent_index :packages_packages, [:project_id, :package_type]
- end
-
- def down
- remove_concurrent_index :packages_packages, [:project_id, :created_at]
- remove_concurrent_index :packages_packages, [:project_id, :version]
- remove_concurrent_index :packages_packages, [:project_id, :package_type]
- end
-end
diff --git a/db/migrate/20200109085206_create_approval_project_rules_protected_branches.rb b/db/migrate/20200109085206_create_approval_project_rules_protected_branches.rb
deleted file mode 100644
index 4e75f7d41fd..00000000000
--- a/db/migrate/20200109085206_create_approval_project_rules_protected_branches.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class CreateApprovalProjectRulesProtectedBranches < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- create_table :approval_project_rules_protected_branches, id: false do |t|
- t.references :approval_project_rule,
- null: false,
- index: false,
- foreign_key: { on_delete: :cascade }
- t.references :protected_branch,
- null: false,
- index: { name: 'index_approval_project_rules_protected_branches_pb_id' },
- foreign_key: { on_delete: :cascade }
- t.index [:approval_project_rule_id, :protected_branch_id], name: 'index_approval_project_rules_protected_branches_unique', unique: true, using: :btree
- end
- end
-end
diff --git a/db/migrate/20200109233938_remove_project_id_index_from_packages.rb b/db/migrate/20200109233938_remove_project_id_index_from_packages.rb
deleted file mode 100644
index e806c5d5a18..00000000000
--- a/db/migrate/20200109233938_remove_project_id_index_from_packages.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveProjectIdIndexFromPackages < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index :packages_packages, [:project_id]
- end
-
- def down
- add_concurrent_index :packages_packages, [:project_id]
- end
-end
diff --git a/db/migrate/20200110089001_fix_invalid_epic_sourcing_milestone_ids.rb b/db/migrate/20200110089001_fix_invalid_epic_sourcing_milestone_ids.rb
deleted file mode 100644
index 04f65c3a810..00000000000
--- a/db/migrate/20200110089001_fix_invalid_epic_sourcing_milestone_ids.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class FixInvalidEpicSourcingMilestoneIds < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def up
- nullify_invalid_data(:start_date_sourcing_milestone_id)
- nullify_invalid_data(:due_date_sourcing_milestone_id)
- end
-
- def down
- # no-op
- end
-
- private
-
- def nullify_invalid_data(column_name)
- execute(<<-SQL.squish)
- UPDATE epics
- SET #{column_name} = null
- WHERE #{column_name} NOT IN (SELECT id FROM milestones);
- SQL
- end
-end
diff --git a/db/migrate/20200110090153_validate_foreign_key_epic_start_date_sourcing_milestone.rb b/db/migrate/20200110090153_validate_foreign_key_epic_start_date_sourcing_milestone.rb
deleted file mode 100644
index 26ddf44cfeb..00000000000
--- a/db/migrate/20200110090153_validate_foreign_key_epic_start_date_sourcing_milestone.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateForeignKeyEpicStartDateSourcingMilestone < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- validate_foreign_key(:epics, :start_date_sourcing_milestone_id)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200110144316_add_indexes_for_projects_api.rb b/db/migrate/20200110144316_add_indexes_for_projects_api.rb
deleted file mode 100644
index 6b0ca252456..00000000000
--- a/db/migrate/20200110144316_add_indexes_for_projects_api.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexesForProjectsApi < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- COLUMNS = %i(created_at last_activity_at updated_at name path)
-
- def up
- COLUMNS.each do |column|
- add_concurrent_index :projects, [column, :id], where: 'visibility_level = 20', order: { id: :desc }, name: "index_projects_api_vis20_#{column}_id_desc"
- add_concurrent_index :projects, [column, :id], where: 'visibility_level = 20', name: "index_projects_api_vis20_#{column}"
- end
-
- remove_concurrent_index_by_name :projects, 'index_projects_on_visibility_level_created_at_id_desc'
- remove_concurrent_index_by_name :projects, 'index_projects_on_visibility_level_created_at_desc_id_desc'
- end
-
- def down
- add_concurrent_index :projects, %i(visibility_level created_at id), order: { id: :desc }, name: 'index_projects_on_visibility_level_created_at_id_desc'
- add_concurrent_index :projects, %i(visibility_level created_at id), order: { created_at: :desc, id: :desc }, name: 'index_projects_on_visibility_level_created_at_desc_id_desc'
-
- COLUMNS.each do |column|
- remove_concurrent_index_by_name :projects, "index_projects_api_vis20_#{column}_id_desc"
- remove_concurrent_index_by_name :projects, "index_projects_api_vis20_#{column}"
- end
- end
-end
diff --git a/db/migrate/20200110203532_validate_foreign_key_epic_due_date_sourcing_milestone.rb b/db/migrate/20200110203532_validate_foreign_key_epic_due_date_sourcing_milestone.rb
deleted file mode 100644
index 2ff48715068..00000000000
--- a/db/migrate/20200110203532_validate_foreign_key_epic_due_date_sourcing_milestone.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateForeignKeyEpicDueDateSourcingMilestone < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- validate_foreign_key(:epics, :due_date_sourcing_milestone_id)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200113133352_add_indexes_for_projects_api_authenticated.rb b/db/migrate/20200113133352_add_indexes_for_projects_api_authenticated.rb
deleted file mode 100644
index 53d317b3321..00000000000
--- a/db/migrate/20200113133352_add_indexes_for_projects_api_authenticated.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexesForProjectsApiAuthenticated < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- COLUMNS = %i(updated_at name)
-
- def up
- add_concurrent_index :projects, %i(created_at id), order: { id: :desc }, name: 'index_projects_api_created_at_id_desc'
-
- add_concurrent_index :projects, %i(last_activity_at id), name: 'index_projects_on_last_activity_at_and_id'
- remove_concurrent_index :projects, :last_activity_at
- add_concurrent_index :projects, %i(last_activity_at id), order: { id: :desc }, name: 'index_projects_api_last_activity_at_id_desc'
-
- add_concurrent_index :projects, %i(path id), name: 'index_projects_on_path_and_id'
- remove_concurrent_index_by_name :projects, 'index_projects_on_path'
- add_concurrent_index :projects, %i(path id), order: { id: :desc }, name: 'index_projects_api_path_id_desc'
-
- COLUMNS.each do |column|
- add_concurrent_index :projects, [column, :id], name: "index_projects_on_#{column}_and_id"
- add_concurrent_index :projects, [column, :id], order: { id: :desc }, name: "index_projects_api_#{column}_id_desc"
- end
- end
-
- def down
- remove_concurrent_index_by_name :projects, 'index_projects_api_created_at_id_desc'
-
- remove_concurrent_index_by_name :projects, 'index_projects_on_last_activity_at_and_id'
- add_concurrent_index :projects, :last_activity_at, name: 'index_projects_on_last_activity_at'
- remove_concurrent_index_by_name :projects, 'index_projects_api_last_activity_at_id_desc'
-
- remove_concurrent_index_by_name :projects, 'index_projects_on_path_and_id'
- add_concurrent_index :projects, :path, name: 'index_projects_on_path'
- remove_concurrent_index_by_name :projects, 'index_projects_api_path_id_desc'
-
- COLUMNS.each do |column|
- remove_concurrent_index_by_name :projects, "index_projects_on_#{column}_and_id"
- remove_concurrent_index_by_name :projects, "index_projects_api_#{column}_id_desc"
- end
- end
-end
diff --git a/db/migrate/20200114140305_add_fields_to_application_settings_for_merge_requests_approvals.rb b/db/migrate/20200114140305_add_fields_to_application_settings_for_merge_requests_approvals.rb
deleted file mode 100644
index 5e035f91f24..00000000000
--- a/db/migrate/20200114140305_add_fields_to_application_settings_for_merge_requests_approvals.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class AddFieldsToApplicationSettingsForMergeRequestsApprovals < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def up
- add_column(:application_settings,
- :disable_overriding_approvers_per_merge_request,
- :boolean,
- default: false,
- null: false)
- add_column(:application_settings,
- :prevent_merge_requests_author_approval,
- :boolean,
- default: false,
- null: false)
- add_column(:application_settings,
- :prevent_merge_requests_committers_approval,
- :boolean,
- default: false,
- null: false)
- end
-
- def down
- remove_column(:application_settings, :disable_overriding_approvers_per_merge_request)
- remove_column(:application_settings, :prevent_merge_requests_author_approval)
- remove_column(:application_settings, :prevent_merge_requests_committers_approval)
- end
-end
diff --git a/db/migrate/20200114204949_add_index_to_sentry_issues_sentry_issue_identifier.rb b/db/migrate/20200114204949_add_index_to_sentry_issues_sentry_issue_identifier.rb
deleted file mode 100644
index 05b9e6d5958..00000000000
--- a/db/migrate/20200114204949_add_index_to_sentry_issues_sentry_issue_identifier.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToSentryIssuesSentryIssueIdentifier < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :sentry_issues, :sentry_issue_identifier
- end
-
- def down
- remove_concurrent_index :sentry_issues, :sentry_issue_identifier
- end
-end
diff --git a/db/migrate/20200115135132_add_retry_count_and_group_id_to_import_failures.rb b/db/migrate/20200115135132_add_retry_count_and_group_id_to_import_failures.rb
deleted file mode 100644
index 8f62aaba60e..00000000000
--- a/db/migrate/20200115135132_add_retry_count_and_group_id_to_import_failures.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddRetryCountAndGroupIdToImportFailures < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- add_column :import_failures, :retry_count, :integer
- add_column :import_failures, :group_id, :integer
- change_column_null(:import_failures, :project_id, true)
- end
-end
diff --git a/db/migrate/20200115135234_add_group_index_and_fk_to_import_failures.rb b/db/migrate/20200115135234_add_group_index_and_fk_to_import_failures.rb
deleted file mode 100644
index c7f2354440b..00000000000
--- a/db/migrate/20200115135234_add_group_index_and_fk_to_import_failures.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddGroupIndexAndFkToImportFailures < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- GROUP_INDEX = 'index_import_failures_on_group_id_not_null'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:import_failures, :group_id, where: 'group_id IS NOT NULL', name: GROUP_INDEX)
-
- add_concurrent_foreign_key(:import_failures, :namespaces, column: :group_id)
- end
-
- def down
- remove_foreign_key(:import_failures, column: :group_id)
-
- remove_concurrent_index_by_name(:import_failures, GROUP_INDEX)
- end
-end
diff --git a/db/migrate/20200116051619_drop_background_migration_jobs.rb b/db/migrate/20200116051619_drop_background_migration_jobs.rb
deleted file mode 100644
index f492ec0af9d..00000000000
--- a/db/migrate/20200116051619_drop_background_migration_jobs.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class DropBackgroundMigrationJobs < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- DROPPED_JOB_CLASS = 'ActivatePrometheusServicesForSharedClusterApplications'
- QUEUE = 'background_migration'
-
- def up
- Sidekiq::Queue.new(QUEUE).each do |job|
- klass, project_id, *should_be_empty = job.args
- next unless klass == DROPPED_JOB_CLASS && project_id.is_a?(Integer) && should_be_empty.empty?
-
- job.delete
- end
- end
-end
diff --git a/db/migrate/20200116175538_update_timestamp_softwarelicensespolicy.rb b/db/migrate/20200116175538_update_timestamp_softwarelicensespolicy.rb
deleted file mode 100644
index 5ed797e33a3..00000000000
--- a/db/migrate/20200116175538_update_timestamp_softwarelicensespolicy.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class UpdateTimestampSoftwarelicensespolicy < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- time = Time.zone.now
-
- update_column_in_batches(:software_license_policies, :created_at, time) do |table, query|
- query.where(table[:created_at].eq(nil))
- end
-
- update_column_in_batches(:software_license_policies, :updated_at, time) do |table, query|
- query.where(table[:updated_at].eq(nil))
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200117112554_update_project_index_to_import_failures.rb b/db/migrate/20200117112554_update_project_index_to_import_failures.rb
deleted file mode 100644
index 888a9bec778..00000000000
--- a/db/migrate/20200117112554_update_project_index_to_import_failures.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateProjectIndexToImportFailures < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
- PROJECT_INDEX_OLD = 'index_import_failures_on_project_id'
- PROJECT_INDEX_NEW = 'index_import_failures_on_project_id_not_null'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:import_failures, :project_id, where: 'project_id IS NOT NULL', name: PROJECT_INDEX_NEW)
- remove_concurrent_index_by_name(:import_failures, PROJECT_INDEX_OLD)
- end
-
- def down
- add_concurrent_index(:import_failures, :project_id, name: PROJECT_INDEX_OLD)
- remove_concurrent_index_by_name(:import_failures, PROJECT_INDEX_NEW)
- end
-end
diff --git a/db/migrate/20200117194830_add_iid_to_operations_feature_flags.rb b/db/migrate/20200117194830_add_iid_to_operations_feature_flags.rb
deleted file mode 100644
index b18d9788b9f..00000000000
--- a/db/migrate/20200117194830_add_iid_to_operations_feature_flags.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddIidToOperationsFeatureFlags < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def up
- add_column :operations_feature_flags, :iid, :integer
- end
-
- def down
- remove_column :operations_feature_flags, :iid
- end
-end
diff --git a/db/migrate/20200117194840_add_index_on_operations_feature_flags_iid.rb b/db/migrate/20200117194840_add_index_on_operations_feature_flags_iid.rb
deleted file mode 100644
index 67dedb56ec1..00000000000
--- a/db/migrate/20200117194840_add_index_on_operations_feature_flags_iid.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnOperationsFeatureFlagsIid < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :operations_feature_flags, [:project_id, :iid], unique: true
- end
-
- def down
- remove_concurrent_index :operations_feature_flags, [:project_id, :iid]
- end
-end
diff --git a/db/migrate/20200121132641_update_timestamp_softwarelicensespolicy_not_null.rb b/db/migrate/20200121132641_update_timestamp_softwarelicensespolicy_not_null.rb
deleted file mode 100644
index 1da96b470ef..00000000000
--- a/db/migrate/20200121132641_update_timestamp_softwarelicensespolicy_not_null.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class UpdateTimestampSoftwarelicensespolicyNotNull < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- change_column_null(:software_license_policies, :created_at, false)
- change_column_null(:software_license_policies, :updated_at, false)
- end
-end
diff --git a/db/migrate/20200121192942_create_geo_events.rb b/db/migrate/20200121192942_create_geo_events.rb
deleted file mode 100644
index 0c885e8524c..00000000000
--- a/db/migrate/20200121192942_create_geo_events.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class CreateGeoEvents < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :geo_events do |t|
- t.string :replicable_name, limit: 255, null: false
- t.string :event_name, limit: 255, null: false
- t.jsonb :payload, default: {}, null: false
- t.datetime_with_timezone :created_at, null: false
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200121194000_add_geo_event_id_to_geo_event_log.rb b/db/migrate/20200121194000_add_geo_event_id_to_geo_event_log.rb
deleted file mode 100644
index 720995164b2..00000000000
--- a/db/migrate/20200121194000_add_geo_event_id_to_geo_event_log.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddGeoEventIdToGeoEventLog < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- add_column :geo_event_log, :geo_event_id, :integer
- end
-end
diff --git a/db/migrate/20200121194048_add_geo_event_id_index_to_geo_event_log.rb b/db/migrate/20200121194048_add_geo_event_id_index_to_geo_event_log.rb
deleted file mode 100644
index 9b0ec12c959..00000000000
--- a/db/migrate/20200121194048_add_geo_event_id_index_to_geo_event_log.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddGeoEventIdIndexToGeoEventLog < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :geo_event_log, :geo_event_id,
- where: "(geo_event_id IS NOT NULL)",
- using: :btree,
- name: 'index_geo_event_log_on_geo_event_id'
- end
-
- def down
- remove_concurrent_index :geo_event_log, :geo_event_id, name: 'index_geo_event_log_on_geo_event_id'
- end
-end
diff --git a/db/migrate/20200121194154_add_geo_events_foreign_key.rb b/db/migrate/20200121194154_add_geo_events_foreign_key.rb
deleted file mode 100644
index b5e16e22989..00000000000
--- a/db/migrate/20200121194154_add_geo_events_foreign_key.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddGeoEventsForeignKey < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :geo_event_log, :geo_events,
- column: :geo_event_id,
- name: 'fk_geo_event_log_on_geo_event_id',
- on_delete: :cascade
- end
-
- def down
- remove_foreign_key_without_error :geo_event_log, column: :geo_event_id, name: 'fk_geo_event_log_on_geo_event_id'
- end
-end
diff --git a/db/migrate/20200121200203_create_group_deploy_tokens.rb b/db/migrate/20200121200203_create_group_deploy_tokens.rb
deleted file mode 100644
index 55b30745fcf..00000000000
--- a/db/migrate/20200121200203_create_group_deploy_tokens.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class CreateGroupDeployTokens < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- create_table :group_deploy_tokens do |t|
- t.timestamps_with_timezone null: false
-
- t.references :group, index: false, null: false, foreign_key: { to_table: :namespaces, on_delete: :cascade }
- t.references :deploy_token, null: false, foreign_key: { on_delete: :cascade }
-
- t.index [:group_id, :deploy_token_id], unique: true, name: 'index_group_deploy_tokens_on_group_and_deploy_token_ids'
- end
- end
-end
diff --git a/db/migrate/20200122161638_add_deploy_token_type_to_deploy_tokens.rb b/db/migrate/20200122161638_add_deploy_token_type_to_deploy_tokens.rb
deleted file mode 100644
index 99459199709..00000000000
--- a/db/migrate/20200122161638_add_deploy_token_type_to_deploy_tokens.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddDeployTokenTypeToDeployTokens < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
-
- def up
- add_column_with_default :deploy_tokens, :deploy_token_type, :integer, default: 2, limit: 2, allow_null: false # rubocop:disable Migration/AddColumnWithDefault
- end
-
- def down
- remove_column :deploy_tokens, :deploy_token_type
- end
-end
diff --git a/db/migrate/20200123040535_add_multi_column_index_on_lfs_objects_projects.rb b/db/migrate/20200123040535_add_multi_column_index_on_lfs_objects_projects.rb
deleted file mode 100644
index 36ccfa4743e..00000000000
--- a/db/migrate/20200123040535_add_multi_column_index_on_lfs_objects_projects.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddMultiColumnIndexOnLfsObjectsProjects < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :lfs_objects_projects, [:project_id, :lfs_object_id]
- end
-
- def down
- remove_concurrent_index :lfs_objects_projects, [:project_id, :lfs_object_id]
- end
-end
diff --git a/db/migrate/20200123045415_remove_project_id_index_on_lfs_objects_projects.rb b/db/migrate/20200123045415_remove_project_id_index_on_lfs_objects_projects.rb
deleted file mode 100644
index 540383e8808..00000000000
--- a/db/migrate/20200123045415_remove_project_id_index_on_lfs_objects_projects.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveProjectIdIndexOnLfsObjectsProjects < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index :lfs_objects_projects, :project_id
- end
-
- def down
- add_concurrent_index :lfs_objects_projects, :project_id
- end
-end
diff --git a/db/migrate/20200123090839_remove_analytics_repository_table_fks_on_projects.rb b/db/migrate/20200123090839_remove_analytics_repository_table_fks_on_projects.rb
deleted file mode 100644
index 18fd349df2a..00000000000
--- a/db/migrate/20200123090839_remove_analytics_repository_table_fks_on_projects.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveAnalyticsRepositoryTableFksOnProjects < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- # Requires ExclusiveLock on all tables. analytics_* tables are empty
- with_lock_retries do
- remove_foreign_key_if_exists(:analytics_repository_files, :projects)
- end
-
- with_lock_retries do
- remove_foreign_key_if_exists(:analytics_repository_file_edits, :projects) if table_exists?(:analytics_repository_file_edits) # this table might be already dropped on development environment
- end
-
- with_lock_retries do
- remove_foreign_key_if_exists(:analytics_repository_file_commits, :projects)
- end
- end
-
- def down
- add_concurrent_foreign_key(:analytics_repository_files, :projects, column: :project_id, on_delete: :cascade)
- add_concurrent_foreign_key(:analytics_repository_file_edits, :projects, column: :project_id, on_delete: :cascade)
- add_concurrent_foreign_key(:analytics_repository_file_commits, :projects, column: :project_id, on_delete: :cascade)
- end
-end
diff --git a/db/migrate/20200123091422_remove_analytics_repository_files_fk_on_other_analytics_tables.rb b/db/migrate/20200123091422_remove_analytics_repository_files_fk_on_other_analytics_tables.rb
deleted file mode 100644
index a436ad8d529..00000000000
--- a/db/migrate/20200123091422_remove_analytics_repository_files_fk_on_other_analytics_tables.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveAnalyticsRepositoryFilesFkOnOtherAnalyticsTables < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- # Requires ExclusiveLock on all tables. analytics_* tables are empty
- with_lock_retries do
- remove_foreign_key_if_exists(:analytics_repository_file_edits, :analytics_repository_files) if table_exists?(:analytics_repository_file_edits) # this table might be already dropped on development environment
- end
-
- with_lock_retries do
- remove_foreign_key_if_exists(:analytics_repository_file_commits, :analytics_repository_files)
- end
- end
-
- def down
- add_concurrent_foreign_key(:analytics_repository_file_edits, :analytics_repository_files, column: :analytics_repository_file_id, on_delete: :cascade)
- add_concurrent_foreign_key(:analytics_repository_file_commits, :analytics_repository_files, column: :analytics_repository_file_id, on_delete: :cascade)
- end
-end
diff --git a/db/migrate/20200123091622_drop_analytics_repository_files_table.rb b/db/migrate/20200123091622_drop_analytics_repository_files_table.rb
deleted file mode 100644
index ed6746165a8..00000000000
--- a/db/migrate/20200123091622_drop_analytics_repository_files_table.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class DropAnalyticsRepositoryFilesTable < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- # Requires ExclusiveLock on the table. Not in use, no records, no FKs.
- # rubocop:disable Migration/DropTable
- drop_table :analytics_repository_files
- # rubocop:enable Migration/DropTable
- end
-
- def down
- create_table :analytics_repository_files do |t|
- t.bigint :project_id, null: false
- t.string :file_path, limit: 4096, null: false
- end
-
- add_index :analytics_repository_files, [:project_id, :file_path], unique: true
- end
-end
diff --git a/db/migrate/20200123091734_drop_analytics_repository_file_commits_table.rb b/db/migrate/20200123091734_drop_analytics_repository_file_commits_table.rb
deleted file mode 100644
index 2eb10a9056d..00000000000
--- a/db/migrate/20200123091734_drop_analytics_repository_file_commits_table.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class DropAnalyticsRepositoryFileCommitsTable < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- # Requires ExclusiveLock on the table. Not in use, no records, no FKs.
- # rubocop:disable Migration/DropTable
- drop_table :analytics_repository_file_commits
- # rubocop:enable Migration/DropTable
- end
-
- def down
- create_table :analytics_repository_file_commits do |t|
- t.bigint :analytics_repository_file_id, null: false
- t.index :analytics_repository_file_id, name: 'index_analytics_repository_file_commits_file_id'
- t.bigint :project_id, null: false
- t.date :committed_date, null: false
- t.integer :commit_count, limit: 2, null: false
- end
-
- add_index :analytics_repository_file_commits,
- [:project_id, :committed_date, :analytics_repository_file_id],
- name: 'index_file_commits_on_committed_date_file_id_and_project_id',
- unique: true
- end
-end
diff --git a/db/migrate/20200123091854_drop_analytics_repository_file_edits_table.rb b/db/migrate/20200123091854_drop_analytics_repository_file_edits_table.rb
deleted file mode 100644
index e4bdb6f6ec2..00000000000
--- a/db/migrate/20200123091854_drop_analytics_repository_file_edits_table.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class DropAnalyticsRepositoryFileEditsTable < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- # Requires ExclusiveLock on the table. Not in use, no records, no FKs.
- # rubocop:disable Migration/DropTable
- drop_table :analytics_repository_file_edits if table_exists?(:analytics_repository_file_edits) # this table might be already dropped on development environment
- # rubocop:enable Migration/DropTable
- end
-
- def down
- create_table :analytics_repository_file_edits do |t|
- t.bigint :project_id, null: false
- t.index :project_id
- t.bigint :analytics_repository_file_id, null: false
- t.date :committed_date, null: false
- t.integer :num_edits, null: false, default: 0
- end
-
- add_index :analytics_repository_file_edits,
- [:analytics_repository_file_id, :committed_date, :project_id],
- name: 'index_file_edits_on_committed_date_file_id_and_project_id',
- unique: true
- end
-end
diff --git a/db/migrate/20200124053531_add_source_to_import_failures.rb b/db/migrate/20200124053531_add_source_to_import_failures.rb
deleted file mode 100644
index 2ca0bcba09f..00000000000
--- a/db/migrate/20200124053531_add_source_to_import_failures.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddSourceToImportFailures < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- add_column :import_failures, :source, :string, limit: 128
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200124143014_add_restrict_deployment_order_to_project_ci_cd_settings.rb b/db/migrate/20200124143014_add_restrict_deployment_order_to_project_ci_cd_settings.rb
deleted file mode 100644
index 6a222ce8d51..00000000000
--- a/db/migrate/20200124143014_add_restrict_deployment_order_to_project_ci_cd_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddRestrictDeploymentOrderToProjectCiCdSettings < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- add_column :project_ci_cd_settings, :forward_deployment_enabled, :boolean
- end
-end
diff --git a/db/migrate/20200128105731_add_duration_to_merge_trains.rb b/db/migrate/20200128105731_add_duration_to_merge_trains.rb
deleted file mode 100644
index a7aacaba5e1..00000000000
--- a/db/migrate/20200128105731_add_duration_to_merge_trains.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class AddDurationToMergeTrains < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- add_column :merge_trains, :merged_at, :datetime_with_timezone
- add_column :merge_trains, :duration, :integer
- end
-end
diff --git a/db/migrate/20200128141125_add_index_web_hooks_on_group_id.rb b/db/migrate/20200128141125_add_index_web_hooks_on_group_id.rb
deleted file mode 100644
index 8c7f6426587..00000000000
--- a/db/migrate/20200128141125_add_index_web_hooks_on_group_id.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexWebHooksOnGroupId < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :web_hooks, :group_id, where: "type = 'GroupHook'"
- end
-
- def down
- remove_concurrent_index :web_hooks, :group_id, where: "type = 'GroupHook'"
- end
-end
diff --git a/db/migrate/20200128184209_add_usage_to_pages_domains.rb b/db/migrate/20200128184209_add_usage_to_pages_domains.rb
deleted file mode 100644
index 292490078cd..00000000000
--- a/db/migrate/20200128184209_add_usage_to_pages_domains.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddUsageToPagesDomains < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- PAGES_USAGE = 0
-
- disable_ddl_transaction!
-
- def up
- add_column_with_default :pages_domains, :usage, :integer, limit: 2, default: PAGES_USAGE, allow_null: false # rubocop:disable Migration/AddColumnWithDefault
- end
-
- def down
- remove_column :pages_domains, :usage
- end
-end
diff --git a/db/migrate/20200129034515_update_indexes_of_pages_domains_add_usage_domain_wildcard_remove_domain.rb b/db/migrate/20200129034515_update_indexes_of_pages_domains_add_usage_domain_wildcard_remove_domain.rb
deleted file mode 100644
index 2f13567c540..00000000000
--- a/db/migrate/20200129034515_update_indexes_of_pages_domains_add_usage_domain_wildcard_remove_domain.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateIndexesOfPagesDomainsAddUsageDomainWildcardRemoveDomain < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :pages_domains, :usage
- add_concurrent_index :pages_domains, [:domain, :wildcard], unique: true
- remove_concurrent_index :pages_domains, :domain
- end
-
- def down
- remove_concurrent_index :pages_domains, :usage
- remove_concurrent_index :pages_domains, [:domain, :wildcard]
- add_concurrent_index :pages_domains, :domain, unique: true
- end
-end
diff --git a/db/migrate/20200129035446_rename_pages_domains_domain_type_to_scope.rb b/db/migrate/20200129035446_rename_pages_domains_domain_type_to_scope.rb
deleted file mode 100644
index 74d9827e370..00000000000
--- a/db/migrate/20200129035446_rename_pages_domains_domain_type_to_scope.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RenamePagesDomainsDomainTypeToScope < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- rename_column_concurrently :pages_domains, :domain_type, :scope
- end
-
- def down
- undo_rename_column_concurrently :pages_domains, :domain_type, :scope
- end
-end
diff --git a/db/migrate/20200129133716_add_resource_milestone_events_table.rb b/db/migrate/20200129133716_add_resource_milestone_events_table.rb
deleted file mode 100644
index 681190a8744..00000000000
--- a/db/migrate/20200129133716_add_resource_milestone_events_table.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class AddResourceMilestoneEventsTable < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- def change
- create_table :resource_milestone_events, id: :bigserial do |t|
- t.references :user, null: false, foreign_key: { on_delete: :nullify },
- index: { name: 'index_resource_milestone_events_on_user_id' }
- t.references :issue, null: true, foreign_key: { on_delete: :cascade },
- index: { name: 'index_resource_milestone_events_on_issue_id' }
- t.references :merge_request, null: true, foreign_key: { on_delete: :cascade },
- index: { name: 'index_resource_milestone_events_on_merge_request_id' }
- t.references :milestone, foreign_key: { on_delete: :cascade },
- index: { name: 'index_resource_milestone_events_on_milestone_id' }
-
- t.integer :action, limit: 2, null: false
- t.integer :state, limit: 2, null: false
- t.integer :cached_markdown_version
- t.text :reference
- t.text :reference_html
- t.datetime_with_timezone :created_at, null: false
- end
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20200129172428_add_index_on_audit_events_id_desc.rb b/db/migrate/20200129172428_add_index_on_audit_events_id_desc.rb
deleted file mode 100644
index b9182c99ebf..00000000000
--- a/db/migrate/20200129172428_add_index_on_audit_events_id_desc.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnAuditEventsIdDesc < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- OLD_INDEX_NAME = 'index_audit_events_on_entity_id_and_entity_type'
- NEW_INDEX_NAME = 'index_audit_events_on_entity_id_and_entity_type_and_id_desc'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :audit_events, [:entity_id, :entity_type, :id], name: NEW_INDEX_NAME,
- order: { entity_id: :asc, entity_type: :asc, id: :desc }
-
- remove_concurrent_index_by_name :audit_events, OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :audit_events, [:entity_id, :entity_type], name: OLD_INDEX_NAME
-
- remove_concurrent_index_by_name :audit_events, NEW_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200130134335_add_cert_and_key_to_serverless_domain_cluster.rb b/db/migrate/20200130134335_add_cert_and_key_to_serverless_domain_cluster.rb
deleted file mode 100644
index 81764aefe7c..00000000000
--- a/db/migrate/20200130134335_add_cert_and_key_to_serverless_domain_cluster.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddCertAndKeyToServerlessDomainCluster < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- # rubocop:disable Migration/AddLimitToTextColumns
- def change
- add_column :serverless_domain_cluster, :encrypted_key, :text
- add_column :serverless_domain_cluster, :encrypted_key_iv, :string, limit: 255
- add_column :serverless_domain_cluster, :certificate, :text
- end
- # rubocop:enable Migration/AddLimitToTextColumns
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200130161817_drop_unneeded_indexes_for_projects_api_requests.rb b/db/migrate/20200130161817_drop_unneeded_indexes_for_projects_api_requests.rb
deleted file mode 100644
index 50b98ab9dba..00000000000
--- a/db/migrate/20200130161817_drop_unneeded_indexes_for_projects_api_requests.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class DropUnneededIndexesForProjectsApiRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
-
- def up
- indexes = %w(
- index_projects_api_vis20_created_at_id_desc
- index_projects_api_vis20_last_activity_at_id_desc
- index_projects_api_vis20_updated_at_id_desc
- index_projects_api_vis20_name_id_desc
- index_projects_api_vis20_path_id_desc
- )
-
- indexes.each do |index|
- remove_concurrent_index_by_name :projects, index
- end
- end
-
- def down
- columns = %i(created_at last_activity_at updated_at name path)
-
- columns.each do |column|
- add_concurrent_index :projects, [column, :id], where: 'visibility_level = 20', order: { id: :desc }, name: "index_projects_api_vis20_#{column}_id_desc"
- end
- end
-end
diff --git a/db/migrate/20200131140428_create_index_on_auto_stop_in.rb b/db/migrate/20200131140428_create_index_on_auto_stop_in.rb
deleted file mode 100644
index 526e7dcfe30..00000000000
--- a/db/migrate/20200131140428_create_index_on_auto_stop_in.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class CreateIndexOnAutoStopIn < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :environments, %i[state auto_stop_at], where: "auto_stop_at IS NOT NULL AND state = 'available'"
- end
-
- def down
- remove_concurrent_index :environments, %i[state auto_stop_at]
- end
-end
diff --git a/db/migrate/20200131181354_add_health_status_to_epics.rb b/db/migrate/20200131181354_add_health_status_to_epics.rb
deleted file mode 100644
index 4e5f9ab138d..00000000000
--- a/db/migrate/20200131181354_add_health_status_to_epics.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddHealthStatusToEpics < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :epics, :health_status, :integer, limit: 2
- end
-end
diff --git a/db/migrate/20200131191754_add_health_status_to_issues.rb b/db/migrate/20200131191754_add_health_status_to_issues.rb
deleted file mode 100644
index ca4e797f4b7..00000000000
--- a/db/migrate/20200131191754_add_health_status_to_issues.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddHealthStatusToIssues < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :issues, :health_status, :integer, limit: 2
- end
-end
diff --git a/db/migrate/20200202100932_add_service_desk_project_key.rb b/db/migrate/20200202100932_add_service_desk_project_key.rb
deleted file mode 100644
index 5095e628b42..00000000000
--- a/db/migrate/20200202100932_add_service_desk_project_key.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddServiceDeskProjectKey < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- add_column :service_desk_settings, :project_key, :string, limit: 255
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200203015140_add_id_to_design_management_designs_versions.rb b/db/migrate/20200203015140_add_id_to_design_management_designs_versions.rb
deleted file mode 100644
index f809bc84fae..00000000000
--- a/db/migrate/20200203015140_add_id_to_design_management_designs_versions.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddIdToDesignManagementDesignsVersions < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :design_management_designs_versions, :id, :primary_key
- end
-end
diff --git a/db/migrate/20200203025400_default_lock_version_to_zero_for_merge_requests.rb b/db/migrate/20200203025400_default_lock_version_to_zero_for_merge_requests.rb
deleted file mode 100644
index 8e48490af77..00000000000
--- a/db/migrate/20200203025400_default_lock_version_to_zero_for_merge_requests.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class DefaultLockVersionToZeroForMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :merge_requests, :lock_version, from: nil, to: 0
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :merge_requests, :lock_version, from: 0, to: nil
- end
- end
-end
diff --git a/db/migrate/20200203025602_default_lock_version_to_zero_for_issues.rb b/db/migrate/20200203025602_default_lock_version_to_zero_for_issues.rb
deleted file mode 100644
index 1265de70728..00000000000
--- a/db/migrate/20200203025602_default_lock_version_to_zero_for_issues.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class DefaultLockVersionToZeroForIssues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :issues, :lock_version, from: nil, to: 0
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :issues, :lock_version, from: 0, to: nil
- end
- end
-end
diff --git a/db/migrate/20200203025619_default_lock_version_to_zero_for_epics.rb b/db/migrate/20200203025619_default_lock_version_to_zero_for_epics.rb
deleted file mode 100644
index b2af8cbe707..00000000000
--- a/db/migrate/20200203025619_default_lock_version_to_zero_for_epics.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class DefaultLockVersionToZeroForEpics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :epics, :lock_version, from: nil, to: 0
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :epics, :lock_version, from: 0, to: nil
- end
- end
-end
diff --git a/db/migrate/20200203025744_default_lock_version_to_zero_for_ci_builds.rb b/db/migrate/20200203025744_default_lock_version_to_zero_for_ci_builds.rb
deleted file mode 100644
index f40bf7d6309..00000000000
--- a/db/migrate/20200203025744_default_lock_version_to_zero_for_ci_builds.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class DefaultLockVersionToZeroForCiBuilds < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :ci_builds, :lock_version, from: nil, to: 0
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :ci_builds, :lock_version, from: 0, to: nil
- end
- end
-end
diff --git a/db/migrate/20200203025801_default_lock_version_to_zero_for_ci_stages.rb b/db/migrate/20200203025801_default_lock_version_to_zero_for_ci_stages.rb
deleted file mode 100644
index fd3194a742a..00000000000
--- a/db/migrate/20200203025801_default_lock_version_to_zero_for_ci_stages.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class DefaultLockVersionToZeroForCiStages < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :ci_stages, :lock_version, from: nil, to: 0
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :ci_stages, :lock_version, from: 0, to: nil
- end
- end
-end
diff --git a/db/migrate/20200203025821_default_lock_version_to_zero_for_ci_pipelines.rb b/db/migrate/20200203025821_default_lock_version_to_zero_for_ci_pipelines.rb
deleted file mode 100644
index 6b4568cc7e8..00000000000
--- a/db/migrate/20200203025821_default_lock_version_to_zero_for_ci_pipelines.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class DefaultLockVersionToZeroForCiPipelines < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :ci_pipelines, :lock_version, from: nil, to: 0
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :ci_pipelines, :lock_version, from: 0, to: nil
- end
- end
-end
diff --git a/db/migrate/20200203173508_add_confirmed_attributes_to_vulnerabilities.rb b/db/migrate/20200203173508_add_confirmed_attributes_to_vulnerabilities.rb
deleted file mode 100644
index 43a375c011f..00000000000
--- a/db/migrate/20200203173508_add_confirmed_attributes_to_vulnerabilities.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class AddConfirmedAttributesToVulnerabilities < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- add_column :vulnerabilities, :confirmed_by_id, :bigint
- add_column :vulnerabilities, :confirmed_at, :datetime_with_timezone
- end
-end
diff --git a/db/migrate/20200203183508_add_index_for_vulnerability_confirmed_by.rb b/db/migrate/20200203183508_add_index_for_vulnerability_confirmed_by.rb
deleted file mode 100644
index dd50e7be893..00000000000
--- a/db/migrate/20200203183508_add_index_for_vulnerability_confirmed_by.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexForVulnerabilityConfirmedBy < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :vulnerabilities, :confirmed_by_id
- add_concurrent_foreign_key :vulnerabilities, :users, column: :confirmed_by_id, on_delete: :nullify
- end
-
- def down
- remove_foreign_key :vulnerabilities, column: :confirmed_by_id
- remove_concurrent_index :vulnerabilities, :confirmed_by_id
- end
-end
diff --git a/db/migrate/20200203232433_create_security_scan.rb b/db/migrate/20200203232433_create_security_scan.rb
deleted file mode 100644
index a5fe73efbf2..00000000000
--- a/db/migrate/20200203232433_create_security_scan.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class CreateSecurityScan < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- create_table :security_scans, id: :bigserial do |t|
- t.timestamps_with_timezone null: false
-
- t.references :build,
- null: false,
- index: false,
- foreign_key: { to_table: :ci_builds, on_delete: :cascade },
- type: :bigint
-
- t.integer :scan_type,
- null: false,
- index: { name: "idx_security_scans_on_scan_type" },
- limit: 2
-
- t.index [:build_id, :scan_type], name: "idx_security_scans_on_build_and_scan_type", unique: true
- end
- end
-end
diff --git a/db/migrate/20200204070729_add_elasticsearch_indexed_field_length_limit_to_application_settings.rb b/db/migrate/20200204070729_add_elasticsearch_indexed_field_length_limit_to_application_settings.rb
deleted file mode 100644
index 7d478706613..00000000000
--- a/db/migrate/20200204070729_add_elasticsearch_indexed_field_length_limit_to_application_settings.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddElasticsearchIndexedFieldLengthLimitToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column :application_settings, :elasticsearch_indexed_field_length_limit, :integer, null: false, default: 0
-
- if Gitlab.com?
- execute 'UPDATE application_settings SET elasticsearch_indexed_field_length_limit = 20000'
- end
- end
-
- def down
- remove_column :application_settings, :elasticsearch_indexed_field_length_limit
- end
-end
diff --git a/db/migrate/20200204131054_change_broadcast_message_index.rb b/db/migrate/20200204131054_change_broadcast_message_index.rb
deleted file mode 100644
index 9545eacd3a1..00000000000
--- a/db/migrate/20200204131054_change_broadcast_message_index.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeBroadcastMessageIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :broadcast_messages, %i(ends_at broadcast_type id), name: 'index_broadcast_message_on_ends_at_and_broadcast_type_and_id'
- remove_concurrent_index_by_name :broadcast_messages, :index_broadcast_messages_on_starts_at_and_ends_at_and_id
- end
-
- def down
- add_concurrent_index :broadcast_messages, %i(starts_at ends_at id), name: 'index_broadcast_messages_on_starts_at_and_ends_at_and_id'
- remove_concurrent_index_by_name :broadcast_messages, :index_broadcast_message_on_ends_at_and_broadcast_type_and_id
- end
-end
diff --git a/db/migrate/20200204131831_create_daily_report_results.rb b/db/migrate/20200204131831_create_daily_report_results.rb
deleted file mode 100644
index 6992b6317e1..00000000000
--- a/db/migrate/20200204131831_create_daily_report_results.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDailyReportResults < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :ci_daily_report_results do |t|
- t.date :date, null: false
- t.bigint :project_id, null: false
- t.bigint :last_pipeline_id, null: false
- t.float :value, null: false
- t.integer :param_type, limit: 8, null: false
- t.string :ref_path, null: false
- t.string :title, null: false
-
- t.index :last_pipeline_id
- t.index [:project_id, :ref_path, :param_type, :date, :title], name: 'index_daily_report_results_unique_columns', unique: true
- t.foreign_key :projects, on_delete: :cascade
- t.foreign_key :ci_pipelines, column: :last_pipeline_id, on_delete: :cascade
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200205143231_add_dissmised_at_to_user_callouts.rb b/db/migrate/20200205143231_add_dissmised_at_to_user_callouts.rb
deleted file mode 100644
index f9942d442b5..00000000000
--- a/db/migrate/20200205143231_add_dissmised_at_to_user_callouts.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddDissmisedAtToUserCallouts < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- add_column :user_callouts, :dismissed_at, :datetime_with_timezone
- end
-end
diff --git a/db/migrate/20200206112850_create_snippet_repository_table.rb b/db/migrate/20200206112850_create_snippet_repository_table.rb
deleted file mode 100644
index b9120264bb7..00000000000
--- a/db/migrate/20200206112850_create_snippet_repository_table.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class CreateSnippetRepositoryTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :snippet_repositories, id: false, primary_key: :snippet_id do |t|
- t.references :shard, null: false, index: true, foreign_key: { on_delete: :restrict }
- t.references :snippet, primary_key: true, default: nil, index: false, foreign_key: { on_delete: :cascade }
- t.string :disk_path, limit: 80, null: false, index: { unique: true }
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200206141511_change_saml_provider_outer_forks_default.rb b/db/migrate/20200206141511_change_saml_provider_outer_forks_default.rb
deleted file mode 100644
index 971cc4da921..00000000000
--- a/db/migrate/20200206141511_change_saml_provider_outer_forks_default.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeSamlProviderOuterForksDefault < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- change_column_null :saml_providers, :prohibited_outer_forks, false
- change_column_default :saml_providers, :prohibited_outer_forks, true
- end
-
- def down
- change_column_default :saml_providers, :prohibited_outer_forks, false
- change_column_null :saml_providers, :prohibited_outer_forks, true
- end
-end
diff --git a/db/migrate/20200207062728_add_default_branch_protection_to_namespaces.rb b/db/migrate/20200207062728_add_default_branch_protection_to_namespaces.rb
deleted file mode 100644
index 56a30b02290..00000000000
--- a/db/migrate/20200207062728_add_default_branch_protection_to_namespaces.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultBranchProtectionToNamespaces < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :namespaces, :default_branch_protection, :integer, limit: 2 # rubocop:disable Migration/AddColumnsToWideTables
- end
- end
-
- def down
- with_lock_retries do
- remove_column :namespaces, :default_branch_protection
- end
- end
-end
diff --git a/db/migrate/20200207090921_add_nuget_index_to_packages_packages.rb b/db/migrate/20200207090921_add_nuget_index_to_packages_packages.rb
deleted file mode 100644
index 1bd9c4dc0d0..00000000000
--- a/db/migrate/20200207090921_add_nuget_index_to_packages_packages.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddNugetIndexToPackagesPackages < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_packages_project_id_name_partial_for_nuget'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :packages_packages, [:project_id, :name], name: INDEX_NAME, where: "name <> 'NuGet.Temporary.Package' AND version is not null AND package_type = 4"
- end
-
- def down
- remove_concurrent_index_by_name :packages_packages, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200207132752_add_es_bulk_config.rb b/db/migrate/20200207132752_add_es_bulk_config.rb
deleted file mode 100644
index c460971139c..00000000000
--- a/db/migrate/20200207132752_add_es_bulk_config.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddEsBulkConfig < ActiveRecord::Migration[6.0]
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- def change
- add_column :application_settings, :elasticsearch_max_bulk_size_mb, :smallint, null: false, default: 10
- add_column :application_settings, :elasticsearch_max_bulk_concurrency, :smallint, null: false, default: 10
- end
-end
diff --git a/db/migrate/20200207151640_create_deployment_clusters.rb b/db/migrate/20200207151640_create_deployment_clusters.rb
deleted file mode 100644
index dd05d1730d9..00000000000
--- a/db/migrate/20200207151640_create_deployment_clusters.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDeploymentClusters < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :deployment_clusters, id: false, force: :cascade do |t|
- t.references :deployment, foreign_key: { on_delete: :cascade }, primary_key: true, type: :integer, index: false, default: nil
- t.references :cluster, foreign_key: { on_delete: :cascade }, type: :integer, index: false, null: false
- t.string :kubernetes_namespace, limit: 255
-
- t.index [:cluster_id, :kubernetes_namespace], name: 'idx_deployment_clusters_on_cluster_id_and_kubernetes_namespace'
- t.index [:cluster_id, :deployment_id], unique: true
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200207182131_replace_conan_metadata_index.rb b/db/migrate/20200207182131_replace_conan_metadata_index.rb
deleted file mode 100644
index 4f55a2974d8..00000000000
--- a/db/migrate/20200207182131_replace_conan_metadata_index.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class ReplaceConanMetadataIndex < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- OLD_INDEX = 'index_packages_conan_metadata_on_package_id'
- NEW_INDEX = 'index_packages_conan_metadata_on_package_id_username_channel'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :packages_conan_metadata,
- [:package_id, :package_username, :package_channel],
- unique: true, name: NEW_INDEX
-
- remove_concurrent_index_by_name :packages_conan_metadata, OLD_INDEX
- end
-
- def down
- add_concurrent_index :packages_conan_metadata, :package_id, name: OLD_INDEX
-
- remove_concurrent_index_by_name :packages_conan_metadata, NEW_INDEX
- end
-end
diff --git a/db/migrate/20200209131152_add_feature_filter_type_to_user_preferences.rb b/db/migrate/20200209131152_add_feature_filter_type_to_user_preferences.rb
deleted file mode 100644
index c05b624c438..00000000000
--- a/db/migrate/20200209131152_add_feature_filter_type_to_user_preferences.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddFeatureFilterTypeToUserPreferences < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :user_preferences, :feature_filter_type, :bigint
- end
-end
diff --git a/db/migrate/20200210135504_remove_packages_deprecated_dependencies.rb b/db/migrate/20200210135504_remove_packages_deprecated_dependencies.rb
deleted file mode 100644
index 476b3de659a..00000000000
--- a/db/migrate/20200210135504_remove_packages_deprecated_dependencies.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class RemovePackagesDeprecatedDependencies < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute('DELETE FROM packages_dependency_links WHERE dependency_type = 5')
- end
-
- def down
- # There is nothing to do to reverse this migration
- end
-end
diff --git a/db/migrate/20200210184410_create_operations_strategies_table.rb b/db/migrate/20200210184410_create_operations_strategies_table.rb
deleted file mode 100644
index 4d65267c1a7..00000000000
--- a/db/migrate/20200210184410_create_operations_strategies_table.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class CreateOperationsStrategiesTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :operations_strategies do |t|
- t.references :feature_flag, index: true, null: false, foreign_key: { to_table: :operations_feature_flags, on_delete: :cascade }
- t.string :name, null: false, limit: 255
- t.jsonb :parameters, null: false, default: {}
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200210184420_create_operations_scopes_table.rb b/db/migrate/20200210184420_create_operations_scopes_table.rb
deleted file mode 100644
index 7ce21feb865..00000000000
--- a/db/migrate/20200210184420_create_operations_scopes_table.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class CreateOperationsScopesTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :operations_scopes do |t|
- t.references :strategy, null: false, index: false, foreign_key: { to_table: :operations_strategies, on_delete: :cascade }
- t.string :environment_scope, null: false, limit: 255
- end
-
- add_index :operations_scopes, [:strategy_id, :environment_scope], unique: true
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200211174946_add_auto_renew_to_gitlab_subscriptions.rb b/db/migrate/20200211174946_add_auto_renew_to_gitlab_subscriptions.rb
deleted file mode 100644
index 6bce74bb8f8..00000000000
--- a/db/migrate/20200211174946_add_auto_renew_to_gitlab_subscriptions.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class AddAutoRenewToGitlabSubscriptions < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :gitlab_subscription_histories, :auto_renew, :boolean
- add_column :gitlab_subscriptions, :auto_renew, :boolean
- end
-end
diff --git a/db/migrate/20200212014653_rename_security_dashboard_feature_flag_to_instance_security_dashboard.rb b/db/migrate/20200212014653_rename_security_dashboard_feature_flag_to_instance_security_dashboard.rb
deleted file mode 100644
index 8d37f6c1dd4..00000000000
--- a/db/migrate/20200212014653_rename_security_dashboard_feature_flag_to_instance_security_dashboard.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class RenameSecurityDashboardFeatureFlagToInstanceSecurityDashboard < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- class FeatureGate < ApplicationRecord
- self.table_name = 'feature_gates'
- end
-
- def up
- security_dashboard_feature = FeatureGate.find_by(feature_key: :security_dashboard, key: :boolean)
-
- if security_dashboard_feature.present?
- FeatureGate.safe_find_or_create_by!(
- feature_key: :instance_security_dashboard,
- key: :boolean,
- value: security_dashboard_feature.value
- )
- end
- end
-
- def down
- FeatureGate.find_by(feature_key: :instance_security_dashboard, key: :boolean)&.delete
- end
-end
diff --git a/db/migrate/20200212133945_add_group_hooks_to_plan_limits.rb b/db/migrate/20200212133945_add_group_hooks_to_plan_limits.rb
deleted file mode 100644
index 4e279ff903d..00000000000
--- a/db/migrate/20200212133945_add_group_hooks_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddGroupHooksToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column(:plan_limits, :group_hooks, :integer, default: 0, null: false)
- end
-end
diff --git a/db/migrate/20200212134201_insert_group_hooks_plan_limits.rb b/db/migrate/20200212134201_insert_group_hooks_plan_limits.rb
deleted file mode 100644
index a2963cfaf4d..00000000000
--- a/db/migrate/20200212134201_insert_group_hooks_plan_limits.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class InsertGroupHooksPlanLimits < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- return unless Gitlab.com?
-
- create_or_update_plan_limit('group_hooks', 'bronze', 50)
- create_or_update_plan_limit('group_hooks', 'silver', 50)
- create_or_update_plan_limit('group_hooks', 'gold', 50)
- end
-
- def down
- return unless Gitlab.com?
-
- create_or_update_plan_limit('group_hooks', 'bronze', 0)
- create_or_update_plan_limit('group_hooks', 'silver', 0)
- create_or_update_plan_limit('group_hooks', 'gold', 0)
- end
-end
diff --git a/db/migrate/20200213093702_add_email_restrictions_to_application_settings.rb b/db/migrate/20200213093702_add_email_restrictions_to_application_settings.rb
deleted file mode 100644
index 2b8afacb6b3..00000000000
--- a/db/migrate/20200213093702_add_email_restrictions_to_application_settings.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddEmailRestrictionsToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- def up
- add_column(:application_settings, :email_restrictions_enabled, :boolean, default: false, null: false)
- add_column(:application_settings, :email_restrictions, :text, null: true)
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-
- def down
- remove_column(:application_settings, :email_restrictions_enabled)
- remove_column(:application_settings, :email_restrictions)
- end
-end
diff --git a/db/migrate/20200213100530_add_verification_columns_to_packages.rb b/db/migrate/20200213100530_add_verification_columns_to_packages.rb
deleted file mode 100644
index b715f35fcab..00000000000
--- a/db/migrate/20200213100530_add_verification_columns_to_packages.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class AddVerificationColumnsToPackages < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- add_column :packages_package_files, :verification_retry_at, :datetime_with_timezone
- add_column :packages_package_files, :verified_at, :datetime_with_timezone
- add_column :packages_package_files, :verification_checksum, :string, limit: 255
- add_column :packages_package_files, :verification_failure, :string, limit: 255
- add_column :packages_package_files, :verification_retry_count, :integer
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200213155311_add_npm_package_requests_forwarding_to_application_settings.rb b/db/migrate/20200213155311_add_npm_package_requests_forwarding_to_application_settings.rb
deleted file mode 100644
index 3815117a7e8..00000000000
--- a/db/migrate/20200213155311_add_npm_package_requests_forwarding_to_application_settings.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddNpmPackageRequestsForwardingToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column_with_default(:application_settings, :npm_package_requests_forwarding, # rubocop:disable Migration/AddColumnWithDefault
- :boolean,
- default: false,
- allow_null: false)
- end
-
- def down
- remove_column(:application_settings, :npm_package_requests_forwarding)
- end
-end
diff --git a/db/migrate/20200213224220_add_sprints.rb b/db/migrate/20200213224220_add_sprints.rb
deleted file mode 100644
index 8d82d1e261a..00000000000
--- a/db/migrate/20200213224220_add_sprints.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class AddSprints < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :sprints, id: :bigserial do |t|
- t.timestamps_with_timezone null: false
- t.date :start_date
- t.date :due_date
-
- t.references :project, foreign_key: false, index: false
- t.references :group, foreign_key: false, index: true
-
- t.integer :iid, null: false
- t.integer :cached_markdown_version
- t.integer :state, limit: 2
- # rubocop:disable Migration/AddLimitToTextColumns
- t.text :title, null: false
- t.text :title_html
- t.text :description
- t.text :description_html
- # rubocop:enable Migration/AddLimitToTextColumns
-
- t.index :description, name: "index_sprints_on_description_trigram", opclass: :gin_trgm_ops, using: :gin
- t.index :due_date
- t.index %w(project_id iid), unique: true
- t.index :title
- t.index :title, name: "index_sprints_on_title_trigram", opclass: :gin_trgm_ops, using: :gin
-
- t.index %w(project_id title), unique: true, where: 'project_id IS NOT NULL'
- t.index %w(group_id title), unique: true, where: 'group_id IS NOT NULL'
- end
- end
-end
diff --git a/db/migrate/20200214025454_add_canonical_emails.rb b/db/migrate/20200214025454_add_canonical_emails.rb
deleted file mode 100644
index 0732d39169d..00000000000
--- a/db/migrate/20200214025454_add_canonical_emails.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class AddCanonicalEmails < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :user_canonical_emails do |t|
- t.timestamps_with_timezone
- t.references :user, index: false, null: false, foreign_key: { on_delete: :cascade }
- t.string :canonical_email, null: false, index: true # rubocop:disable Migration/PreventStrings
- end
- end
-
- add_index :user_canonical_emails, [:user_id, :canonical_email], unique: true
- add_index :user_canonical_emails, :user_id, unique: true
- end
-
- def down
- with_lock_retries do
- drop_table(:user_canonical_emails)
- end
- end
-end
diff --git a/db/migrate/20200214085940_clean_grafana_url.rb b/db/migrate/20200214085940_clean_grafana_url.rb
deleted file mode 100644
index 7dff6532516..00000000000
--- a/db/migrate/20200214085940_clean_grafana_url.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class CleanGrafanaUrl < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute(
- <<-SQL
- UPDATE
- application_settings
- SET
- grafana_url = default
- WHERE
- position('javascript:' IN btrim(application_settings.grafana_url)) = 1
- SQL
- )
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200215222507_drop_forked_project_links_fk.rb b/db/migrate/20200215222507_drop_forked_project_links_fk.rb
deleted file mode 100644
index 7fe38a6ccdb..00000000000
--- a/db/migrate/20200215222507_drop_forked_project_links_fk.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class DropForkedProjectLinksFk < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- remove_foreign_key_if_exists :forked_project_links, column: :forked_to_project_id
- end
- end
-
- def down
- unless foreign_key_exists?(:forked_project_links, :projects, column: :forked_to_project_id)
- with_lock_retries do
- add_foreign_key :forked_project_links, :projects, column: :forked_to_project_id, on_delete: :cascade, validate: false
- end
- end
-
- fk_name = concurrent_foreign_key_name(:forked_project_links, :forked_to_project_id, prefix: 'fk_rails_')
- validate_foreign_key(:forked_project_links, :forked_to_project_id, name: fk_name)
- end
-end
diff --git a/db/migrate/20200215225103_drop_forked_project_links_table.rb b/db/migrate/20200215225103_drop_forked_project_links_table.rb
deleted file mode 100644
index 6acced2c734..00000000000
--- a/db/migrate/20200215225103_drop_forked_project_links_table.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-# rubocop:disable Migration/Datetime
-
-class DropForkedProjectLinksTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- # rubocop:disable Migration/DropTable
- drop_table "forked_project_links", id: :serial do |t|
- t.integer "forked_to_project_id", null: false
- t.integer "forked_from_project_id", null: false
- t.datetime "created_at"
- t.datetime "updated_at"
- t.index ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true
- end
- # rubocop:enable Migration/DropTable
- end
-end
diff --git a/db/migrate/20200218113721_add_indexes_to_package_file.rb b/db/migrate/20200218113721_add_indexes_to_package_file.rb
deleted file mode 100644
index 7c66da6819e..00000000000
--- a/db/migrate/20200218113721_add_indexes_to_package_file.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexesToPackageFile < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :packages_package_files, :verification_failure, where: "(verification_failure IS NOT NULL)", name: "packages_packages_verification_failure_partial"
- add_concurrent_index :packages_package_files, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: "packages_packages_verification_checksum_partial"
- end
-
- def down
- remove_concurrent_index :packages_package_files, :verification_failure
- remove_concurrent_index :packages_package_files, :verification_checksum
- end
-end
diff --git a/db/migrate/20200219105209_add_filepath_to_release_links.rb b/db/migrate/20200219105209_add_filepath_to_release_links.rb
deleted file mode 100644
index ba69332fb70..00000000000
--- a/db/migrate/20200219105209_add_filepath_to_release_links.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-class AddFilepathToReleaseLinks < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :release_links, :filepath, :string, limit: 128 # rubocop:disable Migration/PreventStrings
- end
-end
diff --git a/db/migrate/20200219133859_add_environment_id_to_deployment_merge_requests.rb b/db/migrate/20200219133859_add_environment_id_to_deployment_merge_requests.rb
deleted file mode 100644
index a57d0b44c52..00000000000
--- a/db/migrate/20200219133859_add_environment_id_to_deployment_merge_requests.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddEnvironmentIdToDeploymentMergeRequests < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :deployment_merge_requests, :environment_id, :integer, null: true
- end
-end
diff --git a/db/migrate/20200219135440_add_limit_metric_type_to_list.rb b/db/migrate/20200219135440_add_limit_metric_type_to_list.rb
deleted file mode 100644
index a2b2fb25ac9..00000000000
--- a/db/migrate/20200219135440_add_limit_metric_type_to_list.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddLimitMetricTypeToList < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :lists, :limit_metric, :string, limit: 20 # rubocop:disable Migration/PreventStrings
- end
-end
diff --git a/db/migrate/20200219141307_add_environment_id_fk_to_deployment_merge_requests.rb b/db/migrate/20200219141307_add_environment_id_fk_to_deployment_merge_requests.rb
deleted file mode 100644
index 76980b21feb..00000000000
--- a/db/migrate/20200219141307_add_environment_id_fk_to_deployment_merge_requests.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddEnvironmentIdFkToDeploymentMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :deployment_merge_requests, :environments, column: :environment_id, on_delete: :cascade
- end
-
- def down
- remove_foreign_key_if_exists :deployment_merge_requests, column: :environment_id
- end
-end
diff --git a/db/migrate/20200219142522_add_environment_id_merge_request_id_uniq_idx_to_deployment_merge_requests.rb b/db/migrate/20200219142522_add_environment_id_merge_request_id_uniq_idx_to_deployment_merge_requests.rb
deleted file mode 100644
index a557f3f88d7..00000000000
--- a/db/migrate/20200219142522_add_environment_id_merge_request_id_uniq_idx_to_deployment_merge_requests.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddEnvironmentIdMergeRequestIdUniqIdxToDeploymentMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :deployment_merge_requests, [:environment_id, :merge_request_id], unique: true, name: 'idx_environment_merge_requests_unique_index'
- end
-
- def down
- remove_concurrent_index_by_name :deployment_merge_requests, 'idx_environment_merge_requests_unique_index'
- end
-end
diff --git a/db/migrate/20200220180944_add_keep_divergent_refs.rb b/db/migrate/20200220180944_add_keep_divergent_refs.rb
deleted file mode 100644
index 0b123bc9d72..00000000000
--- a/db/migrate/20200220180944_add_keep_divergent_refs.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddKeepDivergentRefs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- add_column :remote_mirrors, :keep_divergent_refs, :boolean
- end
-end
diff --git a/db/migrate/20200221023320_add_index_on_pages_domain_on_domain_lowercase.rb b/db/migrate/20200221023320_add_index_on_pages_domain_on_domain_lowercase.rb
deleted file mode 100644
index 53f8f5e7f81..00000000000
--- a/db/migrate/20200221023320_add_index_on_pages_domain_on_domain_lowercase.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnPagesDomainOnDomainLowercase < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = 'index_pages_domains_on_domain_lowercase'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :pages_domains, 'LOWER(domain)', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :pages_domains, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200221074028_add_mr_metrics_first_approved_at.rb b/db/migrate/20200221074028_add_mr_metrics_first_approved_at.rb
deleted file mode 100644
index 993905f66ce..00000000000
--- a/db/migrate/20200221074028_add_mr_metrics_first_approved_at.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddMrMetricsFirstApprovedAt < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column :merge_request_metrics, :first_approved_at, :datetime_with_timezone
- end
-
- def down
- remove_column :merge_request_metrics, :first_approved_at
- end
-end
diff --git a/db/migrate/20200221100514_create_users_statistics.rb b/db/migrate/20200221100514_create_users_statistics.rb
deleted file mode 100644
index c02e635bdd4..00000000000
--- a/db/migrate/20200221100514_create_users_statistics.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class CreateUsersStatistics < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :users_statistics do |t|
- t.timestamps_with_timezone null: false
- t.integer :without_groups_and_projects, null: false, default: 0
- t.integer :with_highest_role_guest, null: false, default: 0
- t.integer :with_highest_role_reporter, null: false, default: 0
- t.integer :with_highest_role_developer, null: false, default: 0
- t.integer :with_highest_role_maintainer, null: false, default: 0
- t.integer :with_highest_role_owner, null: false, default: 0
- t.integer :bots, null: false, default: 0
- t.integer :blocked, null: false, default: 0
- end
- end
-end
diff --git a/db/migrate/20200221105436_update_application_setting_npm_package_requests_forwarding_default.rb b/db/migrate/20200221105436_update_application_setting_npm_package_requests_forwarding_default.rb
deleted file mode 100644
index 2479df2737d..00000000000
--- a/db/migrate/20200221105436_update_application_setting_npm_package_requests_forwarding_default.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateApplicationSettingNpmPackageRequestsForwardingDefault < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- change_column_default :application_settings, :npm_package_requests_forwarding, true
-
- execute('UPDATE application_settings SET npm_package_requests_forwarding = TRUE')
- end
-
- def down
- change_column_default :application_settings, :npm_package_requests_forwarding, false
-
- execute('UPDATE application_settings SET npm_package_requests_forwarding = FALSE')
- end
-end
diff --git a/db/migrate/20200221144534_drop_activate_prometheus_services_background_jobs.rb b/db/migrate/20200221144534_drop_activate_prometheus_services_background_jobs.rb
deleted file mode 100644
index 4ec514f7fca..00000000000
--- a/db/migrate/20200221144534_drop_activate_prometheus_services_background_jobs.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class DropActivatePrometheusServicesBackgroundJobs < ActiveRecord::Migration[6.0]
- DOWNTIME = false
- DROPPED_JOB_CLASS = 'ActivatePrometheusServicesForSharedClusterApplications'
- QUEUE = 'background_migration'
-
- def up
- sidekiq_queues.each do |queue|
- queue.each do |job|
- klass, project_id, *should_be_empty = job.args
- next unless klass == DROPPED_JOB_CLASS && project_id.is_a?(Integer) && should_be_empty.empty?
-
- job.delete
- end
- end
- end
-
- def down
- # no-op
- end
-
- def sidekiq_queues
- [Sidekiq::ScheduledSet.new, Sidekiq::RetrySet.new, Sidekiq::Queue.new(QUEUE)]
- end
-end
diff --git a/db/migrate/20200222055543_add_confidential_to_note.rb b/db/migrate/20200222055543_add_confidential_to_note.rb
deleted file mode 100644
index d7bf64dca44..00000000000
--- a/db/migrate/20200222055543_add_confidential_to_note.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-class AddConfidentialToNote < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :notes, :confidential, :boolean
- end
- end
-
- def down
- with_lock_retries do
- remove_column :notes, :confidential
- end
- end
-end
diff --git a/db/migrate/20200224020219_add_status_page_settings.rb b/db/migrate/20200224020219_add_status_page_settings.rb
deleted file mode 100644
index b45dfc8ec46..00000000000
--- a/db/migrate/20200224020219_add_status_page_settings.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddStatusPageSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :status_page_settings, id: false do |t|
- t.references :project, index: true, primary_key: true, foreign_key: { on_delete: :cascade }, unique: true, null: false
- t.timestamps_with_timezone null: false
- t.boolean :enabled, default: false, null: false
- t.string :aws_s3_bucket_name, limit: 63, null: false
- t.string :aws_region, limit: 255, null: false
- t.string :aws_access_key, limit: 255, null: false
- t.string :encrypted_aws_secret_key, limit: 255, null: false
- t.string :encrypted_aws_secret_key_iv, limit: 255, null: false
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200224163804_add_version_to_feature_flags_table.rb b/db/migrate/20200224163804_add_version_to_feature_flags_table.rb
deleted file mode 100644
index d300f7c83e1..00000000000
--- a/db/migrate/20200224163804_add_version_to_feature_flags_table.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class AddVersionToFeatureFlagsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- FEATURE_FLAG_LEGACY_VERSION = 1
-
- def up
- # The operations_feature_flags table is small enough that we can disable this cop.
- # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25552#note_291202882
- # rubocop:disable Migration/AddColumnWithDefault
- add_column_with_default(:operations_feature_flags, :version, :smallint, default: FEATURE_FLAG_LEGACY_VERSION, allow_null: false)
- # rubocop:enable Migration/AddColumnWithDefault
- end
-
- def down
- remove_column(:operations_feature_flags, :version)
- end
-end
diff --git a/db/migrate/20200224185814_add_project_subscriptions_to_plan_limits.rb b/db/migrate/20200224185814_add_project_subscriptions_to_plan_limits.rb
deleted file mode 100644
index 789f23501fb..00000000000
--- a/db/migrate/20200224185814_add_project_subscriptions_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectSubscriptionsToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column(:plan_limits, :ci_project_subscriptions, :integer, default: 0, null: false)
- end
-end
diff --git a/db/migrate/20200225111018_add_index_for_group_and_iid_search_to_epics.rb b/db/migrate/20200225111018_add_index_for_group_and_iid_search_to_epics.rb
deleted file mode 100644
index 98f35d9f1ae..00000000000
--- a/db/migrate/20200225111018_add_index_for_group_and_iid_search_to_epics.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexForGroupAndIidSearchToEpics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_epics_on_group_id_and_iid_varchar_pattern'
-
- disable_ddl_transaction!
-
- def up
- disable_statement_timeout do
- execute "CREATE INDEX CONCURRENTLY \"#{INDEX_NAME}\" ON epics (group_id, CAST(iid AS VARCHAR) varchar_pattern_ops);"
- end
- end
-
- def down
- disable_statement_timeout do
- remove_concurrent_index_by_name :epics, INDEX_NAME
- end
- end
-end
diff --git a/db/migrate/20200225123228_insert_project_subscriptions_plan_limits.rb b/db/migrate/20200225123228_insert_project_subscriptions_plan_limits.rb
deleted file mode 100644
index f04e0c68cf6..00000000000
--- a/db/migrate/20200225123228_insert_project_subscriptions_plan_limits.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class InsertProjectSubscriptionsPlanLimits < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- return unless Gitlab.com?
-
- create_or_update_plan_limit('ci_project_subscriptions', 'free', 2)
- create_or_update_plan_limit('ci_project_subscriptions', 'bronze', 2)
- create_or_update_plan_limit('ci_project_subscriptions', 'silver', 2)
- create_or_update_plan_limit('ci_project_subscriptions', 'gold', 2)
- end
-
- def down
- return unless Gitlab.com?
-
- create_or_update_plan_limit('ci_project_subscriptions', 'free', 0)
- create_or_update_plan_limit('ci_project_subscriptions', 'bronze', 0)
- create_or_update_plan_limit('ci_project_subscriptions', 'silver', 0)
- create_or_update_plan_limit('ci_project_subscriptions', 'gold', 0)
- end
-end
diff --git a/db/migrate/20200226100614_create_requirements.rb b/db/migrate/20200226100614_create_requirements.rb
deleted file mode 100644
index f374e1e9581..00000000000
--- a/db/migrate/20200226100614_create_requirements.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class CreateRequirements < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :requirements do |t|
- t.timestamps_with_timezone null: false
- t.integer :project_id, null: false
- t.integer :author_id
- t.integer :iid, null: false
- t.integer :cached_markdown_version
- t.integer :state, limit: 2, default: 1, null: false
- t.string :title, limit: 255, null: false
- t.text :title_html # rubocop:disable Migration/AddLimitToTextColumns
-
- t.index :project_id
- t.index :author_id
- t.index :title, name: "index_requirements_on_title_trigram", using: :gin, opclass: :gin_trgm_ops
- t.index :state
- t.index :created_at
- t.index :updated_at
- t.index %w(project_id iid), name: 'index_requirements_on_project_id_and_iid', where: 'project_id IS NOT NULL', unique: true, using: :btree
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200226100624_requirements_add_project_fk.rb b/db/migrate/20200226100624_requirements_add_project_fk.rb
deleted file mode 100644
index b44ce1d34ec..00000000000
--- a/db/migrate/20200226100624_requirements_add_project_fk.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RequirementsAddProjectFk < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key(:requirements, :projects, column: :project_id, on_delete: :cascade)
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key(:requirements, column: :project_id)
- end
- end
-end
diff --git a/db/migrate/20200226100634_requirements_add_author_fk.rb b/db/migrate/20200226100634_requirements_add_author_fk.rb
deleted file mode 100644
index b458657827f..00000000000
--- a/db/migrate/20200226100634_requirements_add_author_fk.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RequirementsAddAuthorFk < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key(:requirements, :users, column: :author_id, on_delete: :nullify)
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key(:requirements, column: :author_id)
- end
- end
-end
diff --git a/db/migrate/20200226162156_rename_closed_at_to_dismissed_at_in_vulnerabilities.rb b/db/migrate/20200226162156_rename_closed_at_to_dismissed_at_in_vulnerabilities.rb
deleted file mode 100644
index ce7170cb335..00000000000
--- a/db/migrate/20200226162156_rename_closed_at_to_dismissed_at_in_vulnerabilities.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RenameClosedAtToDismissedAtInVulnerabilities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- rename_column_concurrently :vulnerabilities, :closed_at, :dismissed_at
- end
-
- def down
- undo_rename_column_concurrently :vulnerabilities, :closed_at, :dismissed_at
- end
-end
diff --git a/db/migrate/20200226162634_rename_closed_by_to_dismissed_by_in_vulnerabilities.rb b/db/migrate/20200226162634_rename_closed_by_to_dismissed_by_in_vulnerabilities.rb
deleted file mode 100644
index 04b1f0d7136..00000000000
--- a/db/migrate/20200226162634_rename_closed_by_to_dismissed_by_in_vulnerabilities.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RenameClosedByToDismissedByInVulnerabilities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- rename_column_concurrently :vulnerabilities, :closed_by_id, :dismissed_by_id
- end
-
- def down
- undo_rename_column_concurrently :vulnerabilities, :closed_by_id, :dismissed_by_id
- end
-end
diff --git a/db/migrate/20200227164113_create_scim_identities.rb b/db/migrate/20200227164113_create_scim_identities.rb
deleted file mode 100644
index 34e119ccfe3..00000000000
--- a/db/migrate/20200227164113_create_scim_identities.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class CreateScimIdentities < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :scim_identities do |t|
- t.references :group, foreign_key: { to_table: :namespaces, on_delete: :cascade }, null: false
- t.references :user, index: false, foreign_key: { on_delete: :cascade }, null: false
- t.timestamps_with_timezone
- t.boolean :active, default: false
- t.string :extern_uid, null: false, limit: 255
-
- t.index 'LOWER(extern_uid),group_id', name: 'index_scim_identities_on_lower_extern_uid_and_group_id', unique: true
- t.index [:user_id, :group_id], unique: true
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200227165129_create_user_details.rb b/db/migrate/20200227165129_create_user_details.rb
deleted file mode 100644
index 89258eadb9f..00000000000
--- a/db/migrate/20200227165129_create_user_details.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class CreateUserDetails < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def up
- with_lock_retries do
- create_table :user_details, id: false do |t|
- t.references :user, index: false, foreign_key: { on_delete: :cascade }, null: false, primary_key: true
- t.string :job_title, limit: 200, default: "", null: false
- end
- end
-
- add_index :user_details, :user_id, unique: true
- end
- # rubocop:enable Migration/PreventStrings
-
- def down
- with_lock_retries do
- drop_table :user_details
- end
- end
-end
diff --git a/db/migrate/20200228160542_create_ci_sources_projects.rb b/db/migrate/20200228160542_create_ci_sources_projects.rb
deleted file mode 100644
index 36f5167a784..00000000000
--- a/db/migrate/20200228160542_create_ci_sources_projects.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCiSourcesProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- create_table :ci_sources_projects do |t|
- t.bigint :pipeline_id, null: false
- t.bigint :source_project_id, null: false
-
- t.index [:source_project_id, :pipeline_id], unique: true
- t.index :pipeline_id
- end
- end
-end
diff --git a/db/migrate/20200229171700_create_custom_emojis.rb b/db/migrate/20200229171700_create_custom_emojis.rb
deleted file mode 100644
index f0574831f33..00000000000
--- a/db/migrate/20200229171700_create_custom_emojis.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCustomEmojis < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:custom_emoji)
- create_table :custom_emoji do |t|
- t.references :namespace, index: false, null: false, foreign_key: { on_delete: :cascade }
- t.datetime_with_timezone :created_at, null: false
- t.datetime_with_timezone :updated_at, null: false
- t.text :name, null: false
- t.text :file, null: false
- end
- end
-
- unless index_exists?(:custom_emoji, [:namespace_id, :name], unique: true)
- add_index :custom_emoji, [:namespace_id, :name], unique: true
- end
-
- add_text_limit(:custom_emoji, :name, 36)
- add_text_limit(:custom_emoji, :file, 255)
- end
-
- def down
- drop_table :custom_emoji
- end
-end
diff --git a/db/migrate/20200302152516_add_wiki_slug.rb b/db/migrate/20200302152516_add_wiki_slug.rb
deleted file mode 100644
index a7891427c10..00000000000
--- a/db/migrate/20200302152516_add_wiki_slug.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class AddWikiSlug < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :wiki_page_meta, id: :serial do |t|
- t.references :project, index: true, foreign_key: { on_delete: :cascade }, null: false
- t.timestamps_with_timezone null: false
- t.string :title, null: false, limit: 255
- end
-
- create_table :wiki_page_slugs, id: :serial do |t|
- t.boolean :canonical, default: false, null: false
- t.references :wiki_page_meta, index: true, foreign_key: { on_delete: :cascade }, null: false
- t.timestamps_with_timezone null: false
- t.string :slug, null: false, limit: 2048
- t.index [:slug, :wiki_page_meta_id], unique: true
- t.index [:wiki_page_meta_id], name: 'one_canonical_wiki_page_slug_per_metadata', unique: true, where: "(canonical = true)"
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200303055348_add_expires_at_to_keys.rb b/db/migrate/20200303055348_add_expires_at_to_keys.rb
deleted file mode 100644
index ef7b813a2ef..00000000000
--- a/db/migrate/20200303055348_add_expires_at_to_keys.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddExpiresAtToKeys < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :keys, :expires_at, :datetime_with_timezone
- end
-end
diff --git a/db/migrate/20200303074328_add_index_on_snippet_description.rb b/db/migrate/20200303074328_add_index_on_snippet_description.rb
deleted file mode 100644
index f23e5f8bf8e..00000000000
--- a/db/migrate/20200303074328_add_index_on_snippet_description.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnSnippetDescription < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_snippets_on_description_trigram'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :snippets, :description, name: INDEX_NAME, using: :gin, opclass: { description: :gin_trgm_ops }
- end
-
- def down
- remove_concurrent_index_by_name :snippets, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200303181648_add_healthy_to_clusters_applications_prometheus.rb b/db/migrate/20200303181648_add_healthy_to_clusters_applications_prometheus.rb
deleted file mode 100644
index 402cdbbdc14..00000000000
--- a/db/migrate/20200303181648_add_healthy_to_clusters_applications_prometheus.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class AddHealthyToClustersApplicationsPrometheus < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- # Default is null to indicate that a health check has not run for a project
- # For now, health checks will only run on monitor demo projects
- add_column :clusters_applications_prometheus, :healthy, :boolean
- end
-
- def down
- remove_column :clusters_applications_prometheus, :healthy
- end
-end
diff --git a/db/migrate/20200304023245_add_sprint_to_issues.rb b/db/migrate/20200304023245_add_sprint_to_issues.rb
deleted file mode 100644
index c8bc5258ffd..00000000000
--- a/db/migrate/20200304023245_add_sprint_to_issues.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddSprintToIssues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- # index will be added in another migration with `add_concurrent_index`
- add_column :issues, :sprint_id, :bigint
- end
- end
-
- def down
- with_lock_retries do
- remove_column :issues, :sprint_id
- end
- end
-end
diff --git a/db/migrate/20200304023851_add_sprint_to_merge_requests.rb b/db/migrate/20200304023851_add_sprint_to_merge_requests.rb
deleted file mode 100644
index e294abe66cd..00000000000
--- a/db/migrate/20200304023851_add_sprint_to_merge_requests.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddSprintToMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- # index will be added in another migration with `add_concurrent_index`
- add_column :merge_requests, :sprint_id, :bigint
- end
- end
-
- def down
- with_lock_retries do
- remove_column :merge_requests, :sprint_id
- end
- end
-end
diff --git a/db/migrate/20200304024025_add_sprint_id_index_to_issues.rb b/db/migrate/20200304024025_add_sprint_id_index_to_issues.rb
deleted file mode 100644
index aaece3445db..00000000000
--- a/db/migrate/20200304024025_add_sprint_id_index_to_issues.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddSprintIdIndexToIssues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :issues, :sprint_id
- add_concurrent_foreign_key :issues, :sprints, column: :sprint_id
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :issues, column: :sprint_id
- end
- remove_concurrent_index :issues, :sprint_id
- end
-end
diff --git a/db/migrate/20200304024042_add_sprint_id_index_to_merge_requests.rb b/db/migrate/20200304024042_add_sprint_id_index_to_merge_requests.rb
deleted file mode 100644
index 219d10ff47c..00000000000
--- a/db/migrate/20200304024042_add_sprint_id_index_to_merge_requests.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddSprintIdIndexToMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :merge_requests, :sprint_id
- add_concurrent_foreign_key :merge_requests, :sprints, column: :sprint_id
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :merge_requests, column: :sprint_id
- end
- remove_concurrent_index :merge_requests, :sprint_id
- end
-end
diff --git a/db/migrate/20200304085423_add_user_type.rb b/db/migrate/20200304085423_add_user_type.rb
deleted file mode 100644
index 3c20f2d26d8..00000000000
--- a/db/migrate/20200304085423_add_user_type.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddUserType < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :users, :user_type, :integer, limit: 2 # rubocop:disable Migration/AddColumnsToWideTables
- end
- end
-
- def down
- with_lock_retries do
- remove_column :users, :user_type
- end
- end
-end
diff --git a/db/migrate/20200304090155_add_user_type_index.rb b/db/migrate/20200304090155_add_user_type_index.rb
deleted file mode 100644
index cd3b87d0a45..00000000000
--- a/db/migrate/20200304090155_add_user_type_index.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddUserTypeIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :users, :user_type
- end
-
- def down
- remove_concurrent_index :users, :user_type
- end
-end
diff --git a/db/migrate/20200304121828_add_ci_sources_project_pipeline_foreign_key.rb b/db/migrate/20200304121828_add_ci_sources_project_pipeline_foreign_key.rb
deleted file mode 100644
index ed244a7d308..00000000000
--- a/db/migrate/20200304121828_add_ci_sources_project_pipeline_foreign_key.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddCiSourcesProjectPipelineForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :ci_sources_projects, :ci_pipelines, column: :pipeline_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :ci_sources_projects, :ci_pipelines, column: :pipeline_id
- end
- end
-end
diff --git a/db/migrate/20200304121844_add_ci_sources_project_source_project_foreign_key.rb b/db/migrate/20200304121844_add_ci_sources_project_source_project_foreign_key.rb
deleted file mode 100644
index 56ae2106644..00000000000
--- a/db/migrate/20200304121844_add_ci_sources_project_source_project_foreign_key.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddCiSourcesProjectSourceProjectForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :ci_sources_projects, :projects, column: :source_project_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :ci_sources_projects, :projects, column: :source_project_id
- end
- end
-end
diff --git a/db/migrate/20200304124406_add_unlock_membership_to_ldap_of_groups.rb b/db/migrate/20200304124406_add_unlock_membership_to_ldap_of_groups.rb
deleted file mode 100644
index 19e6573af9b..00000000000
--- a/db/migrate/20200304124406_add_unlock_membership_to_ldap_of_groups.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddUnlockMembershipToLdapOfGroups < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column(:namespaces, :unlock_membership_to_ldap, :boolean) # rubocop:disable Migration/AddColumnsToWideTables
- end
- end
-
- def down
- with_lock_retries do
- remove_column :namespaces, :unlock_membership_to_ldap
- end
- end
-end
diff --git a/db/migrate/20200304160800_add_index_services_on_template.rb b/db/migrate/20200304160800_add_index_services_on_template.rb
deleted file mode 100644
index 731fa04123c..00000000000
--- a/db/migrate/20200304160800_add_index_services_on_template.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexServicesOnTemplate < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # This migration is a corrective action to add the missing
- # index_services_on_template index on staging.
- def up
- add_concurrent_index(:services, :template) unless index_exists?(:services, :template)
- end
-
- def down
- # No reverse action as this is a corrective migration.
- end
-end
diff --git a/db/migrate/20200304160801_delete_template_services_duplicated_by_type.rb b/db/migrate/20200304160801_delete_template_services_duplicated_by_type.rb
deleted file mode 100644
index a1c5161aea0..00000000000
--- a/db/migrate/20200304160801_delete_template_services_duplicated_by_type.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class DeleteTemplateServicesDuplicatedByType < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- # Delete service templates with duplicated types. Keep the service
- # template with the lowest `id` because that is the service template used:
- # https://gitlab.com/gitlab-org/gitlab/-/blob/v12.8.1-ee/app/controllers/admin/services_controller.rb#L37
- execute <<~SQL
- DELETE
- FROM services
- WHERE TEMPLATE = TRUE
- AND id NOT IN
- (SELECT MIN(id)
- FROM services
- WHERE TEMPLATE = TRUE
- GROUP BY TYPE);
- SQL
- end
-
- def down
- # This migration cannot be reversed.
- end
-end
diff --git a/db/migrate/20200304160823_add_index_to_service_unique_template_per_type.rb b/db/migrate/20200304160823_add_index_to_service_unique_template_per_type.rb
deleted file mode 100644
index b81e5acf67f..00000000000
--- a/db/migrate/20200304160823_add_index_to_service_unique_template_per_type.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToServiceUniqueTemplatePerType < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:services, [:type, :template], unique: true, where: 'template IS TRUE')
- end
-
- def down
- remove_concurrent_index(:services, [:type, :template])
- end
-end
diff --git a/db/migrate/20200305020458_add_label_restore_table.rb b/db/migrate/20200305020458_add_label_restore_table.rb
deleted file mode 100644
index a5809cfe14b..00000000000
--- a/db/migrate/20200305020458_add_label_restore_table.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class AddLabelRestoreTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- # copy table
- execute "CREATE TABLE #{backup_labels_table_name} (LIKE #{labels_table_name} INCLUDING ALL);"
-
- # make the primary key a real functioning one rather than incremental
- execute "ALTER TABLE #{backup_labels_table_name} ALTER COLUMN ID DROP DEFAULT;"
-
- # add some fields that make changes trackable
- execute "ALTER TABLE #{backup_labels_table_name} ADD COLUMN restore_action INTEGER;"
- execute "ALTER TABLE #{backup_labels_table_name} ADD COLUMN new_title VARCHAR;"
- end
-
- def down
- drop_table backup_labels_table_name
- end
-
- private
-
- def labels_table_name
- :labels
- end
-
- def backup_labels_table_name
- :backup_labels
- end
-end
diff --git a/db/migrate/20200305020459_add_label_restore_foreign_keys.rb b/db/migrate/20200305020459_add_label_restore_foreign_keys.rb
deleted file mode 100644
index 4b7c68cb20b..00000000000
--- a/db/migrate/20200305020459_add_label_restore_foreign_keys.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class AddLabelRestoreForeignKeys < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- # create foreign keys
- connection.foreign_keys(labels_table_name).each do |fk|
- fk_options = fk.options
- add_concurrent_foreign_key(backup_labels_table_name, fk.to_table, name: fk.name, column: fk_options[:column])
- end
- end
-
- def down
- connection.foreign_keys(backup_labels_table_name).each do |fk|
- with_lock_retries do
- remove_foreign_key backup_labels_table_name, name: fk.name
- end
- end
- end
-
- private
-
- def labels_table_name
- :labels
- end
-
- def backup_labels_table_name
- :backup_labels
- end
-end
diff --git a/db/migrate/20200305121159_add_merge_request_metrics_first_reassigned_at.rb b/db/migrate/20200305121159_add_merge_request_metrics_first_reassigned_at.rb
deleted file mode 100644
index 714adf925ed..00000000000
--- a/db/migrate/20200305121159_add_merge_request_metrics_first_reassigned_at.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddMergeRequestMetricsFirstReassignedAt < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :merge_request_metrics, :first_reassigned_at, :datetime_with_timezone
- end
- end
-
- def down
- with_lock_retries do
- remove_column :merge_request_metrics, :first_reassigned_at, :datetime_with_timezone
- end
- end
-end
diff --git a/db/migrate/20200305151736_delete_template_project_services.rb b/db/migrate/20200305151736_delete_template_project_services.rb
deleted file mode 100644
index 2ab8d46a94e..00000000000
--- a/db/migrate/20200305151736_delete_template_project_services.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class DeleteTemplateProjectServices < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- # In 12.9 an ActiveRecord validation for services not being a template and
- # attached to a project at the same time is introduced. This migration cleans up invalid data.
- execute <<~SQL
- DELETE
- FROM services
- WHERE TEMPLATE = TRUE AND project_id IS NOT NULL
- SQL
- end
-
- def down
- # This migration cannot be reversed.
- end
-end
diff --git a/db/migrate/20200305200641_create_terraform_states.rb b/db/migrate/20200305200641_create_terraform_states.rb
deleted file mode 100644
index 8429d5cfeb3..00000000000
--- a/db/migrate/20200305200641_create_terraform_states.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class CreateTerraformStates < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :terraform_states do |t|
- t.references :project, index: true, foreign_key: { on_delete: :cascade }, null: false
- t.timestamps_with_timezone null: false
- t.integer :file_store, limit: 2
- t.string :file, limit: 255
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200306095654_add_merge_request_assignee_created_at.rb b/db/migrate/20200306095654_add_merge_request_assignee_created_at.rb
deleted file mode 100644
index 127a20f127b..00000000000
--- a/db/migrate/20200306095654_add_merge_request_assignee_created_at.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddMergeRequestAssigneeCreatedAt < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :merge_request_assignees, :created_at, :datetime_with_timezone
- end
- end
-
- def down
- with_lock_retries do
- remove_column :merge_request_assignees, :created_at
- end
- end
-end
diff --git a/db/migrate/20200306160521_add_index_on_author_id_and_created_at_to_events.rb b/db/migrate/20200306160521_add_index_on_author_id_and_created_at_to_events.rb
deleted file mode 100644
index 2f7c16b3f20..00000000000
--- a/db/migrate/20200306160521_add_index_on_author_id_and_created_at_to_events.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnAuthorIdAndCreatedAtToEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_events_on_author_id_and_created_at'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :events, [:author_id, :created_at], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :events, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200306170211_add_index_on_author_id_and_id_and_created_at_to_issues.rb b/db/migrate/20200306170211_add_index_on_author_id_and_id_and_created_at_to_issues.rb
deleted file mode 100644
index c581ca3874f..00000000000
--- a/db/migrate/20200306170211_add_index_on_author_id_and_id_and_created_at_to_issues.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnAuthorIdAndIdAndCreatedAtToIssues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :issues, [:author_id, :id, :created_at]
- end
-
- def down
- remove_concurrent_index :issues, [:author_id, :id, :created_at]
- end
-end
diff --git a/db/migrate/20200306170321_add_index_on_user_id_and_created_at_to_ci_pipelines.rb b/db/migrate/20200306170321_add_index_on_user_id_and_created_at_to_ci_pipelines.rb
deleted file mode 100644
index b88f938d1c2..00000000000
--- a/db/migrate/20200306170321_add_index_on_user_id_and_created_at_to_ci_pipelines.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnUserIdAndCreatedAtToCiPipelines < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_pipelines, [:user_id, :created_at]
- remove_concurrent_index :ci_pipelines, [:user_id]
- end
-
- def down
- add_concurrent_index :ci_pipelines, [:user_id]
- remove_concurrent_index :ci_pipelines, [:user_id, :created_at]
- end
-end
diff --git a/db/migrate/20200306170531_add_index_on_author_id_and_created_at_to_todos.rb b/db/migrate/20200306170531_add_index_on_author_id_and_created_at_to_todos.rb
deleted file mode 100644
index d0d31ca7c52..00000000000
--- a/db/migrate/20200306170531_add_index_on_author_id_and_created_at_to_todos.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-class AddIndexOnAuthorIdAndCreatedAtToTodos < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :todos, [:author_id, :created_at]
- end
-
- def down
- remove_concurrent_index :todos, [:author_id, :created_at]
- end
-end
diff --git a/db/migrate/20200306192548_add_index_on_project_id_and_type_to_services.rb b/db/migrate/20200306192548_add_index_on_project_id_and_type_to_services.rb
deleted file mode 100644
index 9deb3c2832d..00000000000
--- a/db/migrate/20200306192548_add_index_on_project_id_and_type_to_services.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnProjectIdAndTypeToServices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_services_on_project_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :services, [:project_id, :type]
-
- remove_concurrent_index_by_name :services, INDEX_NAME
- end
-
- def down
- add_concurrent_index :services, :project_id, name: INDEX_NAME
-
- remove_concurrent_index :services, [:project_id, :type]
- end
-end
diff --git a/db/migrate/20200306193236_add_index_on_creator_id_and_created_at_to_projects.rb b/db/migrate/20200306193236_add_index_on_creator_id_and_created_at_to_projects.rb
deleted file mode 100644
index 913383d32f4..00000000000
--- a/db/migrate/20200306193236_add_index_on_creator_id_and_created_at_to_projects.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnCreatorIdAndCreatedAtToProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_projects_on_creator_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, [:creator_id, :created_at]
-
- remove_concurrent_index_by_name :projects, INDEX_NAME
- end
-
- def down
- add_concurrent_index :projects, :creator_id, name: INDEX_NAME
-
- remove_concurrent_index :projects, [:creator_id, :created_at]
- end
-end
diff --git a/db/migrate/20200309140540_add_index_on_project_id_and_repository_access_level_to_project_features.rb b/db/migrate/20200309140540_add_index_on_project_id_and_repository_access_level_to_project_features.rb
deleted file mode 100644
index a2093db0b3b..00000000000
--- a/db/migrate/20200309140540_add_index_on_project_id_and_repository_access_level_to_project_features.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnProjectIdAndRepositoryAccessLevelToProjectFeatures < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_project_features_on_project_id_ral_20'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :project_features, :project_id, where: 'repository_access_level = 20', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :project_features, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200309162244_add_open_project_tracker_data.rb b/db/migrate/20200309162244_add_open_project_tracker_data.rb
deleted file mode 100644
index 5906eb7ebff..00000000000
--- a/db/migrate/20200309162244_add_open_project_tracker_data.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddOpenProjectTrackerData < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :open_project_tracker_data do |t|
- t.references :service, foreign_key: { on_delete: :cascade }, type: :integer, index: true, null: false
- t.timestamps_with_timezone
- t.string :encrypted_url, limit: 255
- t.string :encrypted_url_iv, limit: 255
- t.string :encrypted_api_url, limit: 255
- t.string :encrypted_api_url_iv, limit: 255
- t.string :encrypted_token, limit: 255
- t.string :encrypted_token_iv, limit: 255
- t.string :closed_status_id, limit: 5
- t.string :project_identifier_code, limit: 100
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200309195209_add_index_on_project_id_and_builds_access_level_to_project_features.rb b/db/migrate/20200309195209_add_index_on_project_id_and_builds_access_level_to_project_features.rb
deleted file mode 100644
index 8d6ab60ca48..00000000000
--- a/db/migrate/20200309195209_add_index_on_project_id_and_builds_access_level_to_project_features.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnProjectIdAndBuildsAccessLevelToProjectFeatures < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_project_features_on_project_id_bal_20'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :project_features, :project_id, where: 'builds_access_level = 20', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :project_features, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200309195710_add_index_on_mirror_and_creator_id_and_created_at_to_projects.rb b/db/migrate/20200309195710_add_index_on_mirror_and_creator_id_and_created_at_to_projects.rb
deleted file mode 100644
index e1bdb5d7a0d..00000000000
--- a/db/migrate/20200309195710_add_index_on_mirror_and_creator_id_and_created_at_to_projects.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnMirrorAndCreatorIdAndCreatedAtToProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_projects_on_mirror_creator_id_created_at'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, [:creator_id, :created_at], where: 'mirror = true and mirror_trigger_builds = true', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :projects, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200310123229_add_index_on_enabled_and_provider_type_and_id_to_clusters.rb b/db/migrate/20200310123229_add_index_on_enabled_and_provider_type_and_id_to_clusters.rb
deleted file mode 100644
index edd9343e743..00000000000
--- a/db/migrate/20200310123229_add_index_on_enabled_and_provider_type_and_id_to_clusters.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnEnabledAndProviderTypeAndIdToClusters < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :clusters, [:enabled, :provider_type, :id]
- remove_concurrent_index :clusters, :enabled
- end
-
- def down
- add_concurrent_index :clusters, :enabled
- remove_concurrent_index :clusters, [:enabled, :provider_type, :id]
- end
-end
diff --git a/db/migrate/20200310132654_add_instance_to_services.rb b/db/migrate/20200310132654_add_instance_to_services.rb
deleted file mode 100644
index 5f3c3e8616b..00000000000
--- a/db/migrate/20200310132654_add_instance_to_services.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddInstanceToServices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # rubocop:disable Migration/AddColumnWithDefault
- # rubocop:disable Migration/UpdateLargeTable
- def up
- add_column_with_default(:services, :instance, :boolean, default: false)
- end
- # rubocop:enable Migration/AddColumnWithDefault
- # rubocop:enable Migration/UpdateLargeTable
-
- def down
- remove_column(:services, :instance)
- end
-end
diff --git a/db/migrate/20200310133822_add_index_on_author_id_and_id_and_created_at_to_notes.rb b/db/migrate/20200310133822_add_index_on_author_id_and_id_and_created_at_to_notes.rb
deleted file mode 100644
index 8005da5fbae..00000000000
--- a/db/migrate/20200310133822_add_index_on_author_id_and_id_and_created_at_to_notes.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnAuthorIdAndIdAndCreatedAtToNotes < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :notes, [:author_id, :created_at]
- remove_concurrent_index :notes, [:author_id]
- end
-
- def down
- add_concurrent_index :notes, [:author_id]
- remove_concurrent_index :notes, [:author_id, :created_at]
- end
-end
diff --git a/db/migrate/20200310135823_add_index_to_service_unique_instance_per_type.rb b/db/migrate/20200310135823_add_index_to_service_unique_instance_per_type.rb
deleted file mode 100644
index 1a60c521b71..00000000000
--- a/db/migrate/20200310135823_add_index_to_service_unique_instance_per_type.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToServiceUniqueInstancePerType < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:services, [:type, :instance], unique: true, where: 'instance IS TRUE')
- end
-
- def down
- remove_concurrent_index(:services, [:type, :instance])
- end
-end
diff --git a/db/migrate/20200310145304_add_runtime_created_to_ci_job_variables.rb b/db/migrate/20200310145304_add_runtime_created_to_ci_job_variables.rb
deleted file mode 100644
index e76136a5c1f..00000000000
--- a/db/migrate/20200310145304_add_runtime_created_to_ci_job_variables.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddRuntimeCreatedToCiJobVariables < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- DEFAULT_SOURCE = 0 # Equvalent to Ci::JobVariable.internal_source
-
- def up
- add_column_with_default(:ci_job_variables, :source, :integer, limit: 2, default: DEFAULT_SOURCE, allow_null: false) # rubocop:disable Migration/AddColumnWithDefault
- end
-
- def down
- remove_column(:ci_job_variables, :source)
- end
-end
diff --git a/db/migrate/20200311074438_migrate_bot_type_to_user_type.rb b/db/migrate/20200311074438_migrate_bot_type_to_user_type.rb
deleted file mode 100644
index b13842794d3..00000000000
--- a/db/migrate/20200311074438_migrate_bot_type_to_user_type.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateBotTypeToUserType < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute('UPDATE users SET user_type = bot_type WHERE bot_type IS NOT NULL AND user_type IS NULL')
- end
-
- def down
- execute('UPDATE users SET user_type = NULL WHERE bot_type IS NOT NULL AND bot_type = user_type')
- end
-end
diff --git a/db/migrate/20200311082301_add_user_state_index.rb b/db/migrate/20200311082301_add_user_state_index.rb
deleted file mode 100644
index 953941c2a53..00000000000
--- a/db/migrate/20200311082301_add_user_state_index.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddUserStateIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:users, [:state, :user_type], where: 'ghost IS NOT TRUE', name: 'index_users_on_state_and_user_type_internal')
- remove_concurrent_index_by_name(:users, 'index_users_on_state_and_internal_ee')
- remove_concurrent_index_by_name(:users, 'index_users_on_state_and_internal')
- end
-
- def down
- add_concurrent_index(:users, :state, where: 'ghost IS NOT TRUE AND bot_type IS NULL', name: 'index_users_on_state_and_internal_ee')
- add_concurrent_index(:users, :state, where: 'ghost IS NOT TRUE', name: 'index_users_on_state_and_internal')
- remove_concurrent_index_by_name(:users, 'index_users_on_state_and_internal_ee')
- end
-end
diff --git a/db/migrate/20200311084025_add_index_on_user_id_status_created_at_to_deployments.rb b/db/migrate/20200311084025_add_index_on_user_id_status_created_at_to_deployments.rb
deleted file mode 100644
index 1744b701f0a..00000000000
--- a/db/migrate/20200311084025_add_index_on_user_id_status_created_at_to_deployments.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnUserIdStatusCreatedAtToDeployments < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :deployments, [:user_id, :status, :created_at]
- end
-
- def down
- remove_concurrent_index :deployments, [:user_id, :status, :created_at]
- end
-end
diff --git a/db/migrate/20200311093210_create_user_highest_roles.rb b/db/migrate/20200311093210_create_user_highest_roles.rb
deleted file mode 100644
index 36007f196d1..00000000000
--- a/db/migrate/20200311093210_create_user_highest_roles.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class CreateUserHighestRoles < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :user_highest_roles, id: false do |t|
- t.datetime_with_timezone :updated_at, null: false
- t.references :user, primary_key: true, default: nil, index: false, foreign_key: { on_delete: :cascade }
- t.integer :highest_access_level
-
- t.index [:user_id, :highest_access_level]
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :user_highest_roles
- end
- end
-end
diff --git a/db/migrate/20200311094020_add_index_on_id_and_status_to_deployments.rb b/db/migrate/20200311094020_add_index_on_id_and_status_to_deployments.rb
deleted file mode 100644
index 77c746ed88b..00000000000
--- a/db/migrate/20200311094020_add_index_on_id_and_status_to_deployments.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnIdAndStatusToDeployments < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :deployments, [:id, :status]
- end
-
- def down
- remove_concurrent_index :deployments, [:id, :status]
- end
-end
diff --git a/db/migrate/20200311141053_add_ci_pipeline_schedules_to_plan_limits.rb b/db/migrate/20200311141053_add_ci_pipeline_schedules_to_plan_limits.rb
deleted file mode 100644
index e7fe3e63349..00000000000
--- a/db/migrate/20200311141053_add_ci_pipeline_schedules_to_plan_limits.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddCiPipelineSchedulesToPlanLimits < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
-
- def up
- add_column_with_default(:plan_limits, :ci_pipeline_schedules, :integer, default: 0, allow_null: false) # rubocop:disable Migration/AddColumnWithDefault
- end
-
- def down
- remove_column(:plan_limits, :ci_pipeline_schedules)
- end
-end
diff --git a/db/migrate/20200311141943_insert_ci_pipeline_schedules_plan_limits.rb b/db/migrate/20200311141943_insert_ci_pipeline_schedules_plan_limits.rb
deleted file mode 100644
index 2a04781c65e..00000000000
--- a/db/migrate/20200311141943_insert_ci_pipeline_schedules_plan_limits.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class InsertCiPipelineSchedulesPlanLimits < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- return unless Gitlab.com?
-
- create_or_update_plan_limit('ci_pipeline_schedules', 'free', 10)
- create_or_update_plan_limit('ci_pipeline_schedules', 'bronze', 50)
- create_or_update_plan_limit('ci_pipeline_schedules', 'silver', 50)
- create_or_update_plan_limit('ci_pipeline_schedules', 'gold', 50)
- end
-
- def down
- return unless Gitlab.com?
-
- create_or_update_plan_limit('ci_pipeline_schedules', 'free', 0)
- create_or_update_plan_limit('ci_pipeline_schedules', 'bronze', 0)
- create_or_update_plan_limit('ci_pipeline_schedules', 'silver', 0)
- create_or_update_plan_limit('ci_pipeline_schedules', 'gold', 0)
- end
-end
diff --git a/db/migrate/20200311154110_create_vulnerability_exports.rb b/db/migrate/20200311154110_create_vulnerability_exports.rb
deleted file mode 100644
index 5a3355ab5be..00000000000
--- a/db/migrate/20200311154110_create_vulnerability_exports.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class CreateVulnerabilityExports < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :vulnerability_exports do |t|
- t.timestamps_with_timezone null: false
- t.datetime_with_timezone :started_at
- t.datetime_with_timezone :finished_at
- t.string :status, limit: 255, null: false
- t.string :file, limit: 255
- t.bigint :project_id, null: false
- t.bigint :author_id, null: false
- t.integer :file_store
- t.integer :format, limit: 2, null: false, default: 0
-
- t.index %i[project_id id], unique: true
- t.index %i[author_id]
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200311165635_create_project_export_jobs.rb b/db/migrate/20200311165635_create_project_export_jobs.rb
deleted file mode 100644
index 21ff5f488f7..00000000000
--- a/db/migrate/20200311165635_create_project_export_jobs.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class CreateProjectExportJobs < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :project_export_jobs do |t|
- t.references :project, index: false, null: false, foreign_key: { on_delete: :cascade }
- t.timestamps_with_timezone null: false
- t.integer :status, limit: 2, null: false, default: 0
- t.string :jid, limit: 100, null: false, unique: true
-
- t.index [:project_id, :jid]
- t.index [:jid], unique: true
- t.index [:status]
- t.index [:project_id, :status]
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200311214912_add_modsecurity_mode_to_ingress_application.rb b/db/migrate/20200311214912_add_modsecurity_mode_to_ingress_application.rb
deleted file mode 100644
index 7f3366a4900..00000000000
--- a/db/migrate/20200311214912_add_modsecurity_mode_to_ingress_application.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddModsecurityModeToIngressApplication < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column_with_default(:clusters_applications_ingress, :modsecurity_mode, :smallint, default: 0, allow_null: false) # rubocop:disable Migration/AddColumnWithDefault
- end
-
- def down
- remove_column :clusters_applications_ingress, :modsecurity_mode
- end
-end
diff --git a/db/migrate/20200312053852_populate_canonical_emails.rb b/db/migrate/20200312053852_populate_canonical_emails.rb
deleted file mode 100644
index 10efffab59c..00000000000
--- a/db/migrate/20200312053852_populate_canonical_emails.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class PopulateCanonicalEmails < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- class User < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'users'
-
- scope :with_gmail, -> { select(:id, :email).where("email ILIKE '%gmail.com'") }
- end
-
- # Limited to *@gmail.com addresses only as a first iteration, because we know
- # Gmail ignores `.` appearing in the Agent name, as well as anything after `+`
-
- def up
- # batch size is the default, 1000
- migration = Gitlab::BackgroundMigration::PopulateCanonicalEmails
- migration_name = migration.to_s.demodulize
-
- queue_background_migration_jobs_by_range_at_intervals(
- User.with_gmail,
- migration_name,
- 1.minute)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200312125121_add_index_on_active_and_template_and_type_and_id_to_services.rb b/db/migrate/20200312125121_add_index_on_active_and_template_and_type_and_id_to_services.rb
deleted file mode 100644
index 76e5860c2f3..00000000000
--- a/db/migrate/20200312125121_add_index_on_active_and_template_and_type_and_id_to_services.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnActiveAndTemplateAndTypeAndIdToServices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_services_on_type_and_id_and_template_when_active'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :services, [:type, :id, :template], where: 'active = TRUE', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :services, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200312160532_add_index_on_mirror_and_id_to_projects.rb b/db/migrate/20200312160532_add_index_on_mirror_and_id_to_projects.rb
deleted file mode 100644
index 3a64b915931..00000000000
--- a/db/migrate/20200312160532_add_index_on_mirror_and_id_to_projects.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnMirrorAndIdToProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- OLD_INDEX_NAME = 'index_projects_on_mirror_and_mirror_trigger_builds_both_true'
- NEW_INDEX_NAME = 'index_projects_on_mirror_id_where_mirror_and_trigger_builds'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, :id, where: 'mirror = TRUE AND mirror_trigger_builds = TRUE', name: NEW_INDEX_NAME
- remove_concurrent_index_by_name :projects, OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :projects, :id, where: 'mirror IS TRUE AND mirror_trigger_builds IS TRUE', name: OLD_INDEX_NAME
- remove_concurrent_index_by_name :projects, NEW_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200312163407_add_index_on_id_and_service_desk_enabled_to_projects.rb b/db/migrate/20200312163407_add_index_on_id_and_service_desk_enabled_to_projects.rb
deleted file mode 100644
index 903bd12ddf4..00000000000
--- a/db/migrate/20200312163407_add_index_on_id_and_service_desk_enabled_to_projects.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnIdAndServiceDeskEnabledToProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_projects_on_id_service_desk_enabled'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, :id, where: 'service_desk_enabled = true', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :projects, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200313101649_fill_ghost_user_type.rb b/db/migrate/20200313101649_fill_ghost_user_type.rb
deleted file mode 100644
index fa0c02e5413..00000000000
--- a/db/migrate/20200313101649_fill_ghost_user_type.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class FillGhostUserType < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute('UPDATE users SET user_type = 5 WHERE ghost IS TRUE AND user_type IS NULL')
- end
-
- def down
- execute('UPDATE users SET user_type = NULL WHERE ghost IS TRUE AND user_type IS NOT NULL')
- end
-end
diff --git a/db/migrate/20200313123934_add_index_on_user_id_type_source_type_ldap_and_created_at_to_members.rb b/db/migrate/20200313123934_add_index_on_user_id_type_source_type_ldap_and_created_at_to_members.rb
deleted file mode 100644
index c4dde7086c2..00000000000
--- a/db/migrate/20200313123934_add_index_on_user_id_type_source_type_ldap_and_created_at_to_members.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnUserIdTypeSourceTypeLdapAndCreatedAtToMembers < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_members_on_user_id_created_at'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :members, [:user_id, :created_at], where: "ldap = TRUE AND type = 'GroupMember' AND source_type = 'Namespace'", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :members, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200313202430_add_index_chat_name_service_id.rb b/db/migrate/20200313202430_add_index_chat_name_service_id.rb
deleted file mode 100644
index f4a88973751..00000000000
--- a/db/migrate/20200313202430_add_index_chat_name_service_id.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexChatNameServiceId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :chat_names, :service_id
- end
-
- def down
- remove_concurrent_index :chat_names, :service_id
- end
-end
diff --git a/db/migrate/20200313203525_add_invalid_foreign_key_from_chat_name_to_service.rb b/db/migrate/20200313203525_add_invalid_foreign_key_from_chat_name_to_service.rb
deleted file mode 100644
index c6e340693f8..00000000000
--- a/db/migrate/20200313203525_add_invalid_foreign_key_from_chat_name_to_service.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddInvalidForeignKeyFromChatNameToService < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :chat_names, :services, column: :service_id, on_delete: :cascade, validate: false
- end
-
- def down
- remove_foreign_key_if_exists :chat_names, column: :service_id
- end
-end
diff --git a/db/migrate/20200314060834_add_scanned_resources_count_to_security_scan.rb b/db/migrate/20200314060834_add_scanned_resources_count_to_security_scan.rb
deleted file mode 100644
index e8f7a693e99..00000000000
--- a/db/migrate/20200314060834_add_scanned_resources_count_to_security_scan.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-class AddScannedResourcesCountToSecurityScan < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column :security_scans, :scanned_resources_count, :integer
- end
-
- def down
- remove_column :security_scans, :scanned_resources_count
- end
-end
diff --git a/db/migrate/20200316111759_add_index_on_id_and_ldap_key_to_keys.rb b/db/migrate/20200316111759_add_index_on_id_and_ldap_key_to_keys.rb
deleted file mode 100644
index 23e7b5ba7b9..00000000000
--- a/db/migrate/20200316111759_add_index_on_id_and_ldap_key_to_keys.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnIdAndLdapKeyToKeys < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_keys_on_id_and_ldap_key_type'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :keys, [:id], where: "type = 'LDAPKey'", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :keys, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200316162648_add_index_on_namespace_id_and_id_to_projects.rb b/db/migrate/20200316162648_add_index_on_namespace_id_and_id_to_projects.rb
deleted file mode 100644
index 96fbab1e2ea..00000000000
--- a/db/migrate/20200316162648_add_index_on_namespace_id_and_id_to_projects.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnNamespaceIdAndIdToProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, [:namespace_id, :id]
- remove_concurrent_index :projects, :namespace_id
- end
-
- def down
- add_concurrent_index :projects, :namespace_id
- remove_concurrent_index :projects, [:namespace_id, :id]
- end
-end
diff --git a/db/migrate/20200316173312_add_vulnerability_export_project_foreign_key.rb b/db/migrate/20200316173312_add_vulnerability_export_project_foreign_key.rb
deleted file mode 100644
index 84b96c64658..00000000000
--- a/db/migrate/20200316173312_add_vulnerability_export_project_foreign_key.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddVulnerabilityExportProjectForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :vulnerability_exports, :projects, column: :project_id, on_delete: :cascade, index: false
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :vulnerability_exports, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20200317110602_add_migrating_user_highest_roles_table_index_to_users.rb b/db/migrate/20200317110602_add_migrating_user_highest_roles_table_index_to_users.rb
deleted file mode 100644
index e67dc323c39..00000000000
--- a/db/migrate/20200317110602_add_migrating_user_highest_roles_table_index_to_users.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddMigratingUserHighestRolesTableIndexToUsers < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_for_migrating_user_highest_roles_table'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :users,
- :id,
- where: "state = 'active' AND user_type IS NULL AND bot_type IS NULL AND ghost IS NOT TRUE",
- name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :users, :id, name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20200317142110_add_vulnerability_export_user_foreign_key.rb b/db/migrate/20200317142110_add_vulnerability_export_user_foreign_key.rb
deleted file mode 100644
index c4f685701b9..00000000000
--- a/db/migrate/20200317142110_add_vulnerability_export_user_foreign_key.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddVulnerabilityExportUserForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :vulnerability_exports, :users, column: :author_id, on_delete: :cascade, index: false
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :vulnerability_exports, column: :author_id
- end
- end
-end
diff --git a/db/migrate/20200318140400_create_vulnerability_user_mentions.rb b/db/migrate/20200318140400_create_vulnerability_user_mentions.rb
deleted file mode 100644
index 919bc94cfa6..00000000000
--- a/db/migrate/20200318140400_create_vulnerability_user_mentions.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class CreateVulnerabilityUserMentions < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :vulnerability_user_mentions do |t|
- t.references :vulnerability, type: :bigint, index: false, null: false, foreign_key: { on_delete: :cascade }
- t.references :note, type: :integer,
- index: { where: 'note_id IS NOT NULL', unique: true }, null: true, foreign_key: { on_delete: :cascade }
- t.integer :mentioned_users_ids, array: true
- t.integer :mentioned_projects_ids, array: true
- t.integer :mentioned_groups_ids, array: true
- end
-
- add_index :vulnerability_user_mentions, [:vulnerability_id], where: 'note_id is null', unique: true, name: 'index_vulns_user_mentions_on_vulnerability_id'
- add_index :vulnerability_user_mentions, [:vulnerability_id, :note_id], unique: true, name: 'index_vulns_user_mentions_on_vulnerability_id_and_note_id'
- end
-end
diff --git a/db/migrate/20200318152134_adds_sha256_to_package_files.rb b/db/migrate/20200318152134_adds_sha256_to_package_files.rb
deleted file mode 100644
index 26d2c1b97d4..00000000000
--- a/db/migrate/20200318152134_adds_sha256_to_package_files.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddsSha256ToPackageFiles < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :packages_package_files, :file_sha256, :binary
- end
-end
diff --git a/db/migrate/20200318162148_add_external_key_to_issues_table.rb b/db/migrate/20200318162148_add_external_key_to_issues_table.rb
deleted file mode 100644
index b98937861be..00000000000
--- a/db/migrate/20200318162148_add_external_key_to_issues_table.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddExternalKeyToIssuesTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :issues, :external_key, :string, limit: 255 # rubocop:disable Migration/PreventStrings
- end
- end
-
- def down
- with_lock_retries do
- remove_column :issues, :external_key
- end
- end
-end
diff --git a/db/migrate/20200318163148_add_index_on_external_key_to_issues_table.rb b/db/migrate/20200318163148_add_index_on_external_key_to_issues_table.rb
deleted file mode 100644
index adca6c3b493..00000000000
--- a/db/migrate/20200318163148_add_index_on_external_key_to_issues_table.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnExternalKeyToIssuesTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:issues, [:project_id, :external_key], unique: true, where: 'external_key IS NOT NULL')
- end
-
- def down
- remove_concurrent_index(:issues, [:project_id, :external_key])
- end
-end
diff --git a/db/migrate/20200318164448_add_external_key_to_epics_table.rb b/db/migrate/20200318164448_add_external_key_to_epics_table.rb
deleted file mode 100644
index dee2ca98f36..00000000000
--- a/db/migrate/20200318164448_add_external_key_to_epics_table.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddExternalKeyToEpicsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :epics, :external_key, :string, limit: 255 # rubocop:disable Migration/PreventStrings
- end
- end
-
- def down
- with_lock_retries do
- remove_column :epics, :external_key
- end
- end
-end
diff --git a/db/migrate/20200318165448_add_index_on_external_key_to_epics_table.rb b/db/migrate/20200318165448_add_index_on_external_key_to_epics_table.rb
deleted file mode 100644
index 0f3b2dbe3ee..00000000000
--- a/db/migrate/20200318165448_add_index_on_external_key_to_epics_table.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnExternalKeyToEpicsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:epics, [:group_id, :external_key], unique: true, where: 'external_key IS NOT NULL')
- end
-
- def down
- remove_concurrent_index(:epics, [:group_id, :external_key])
- end
-end
diff --git a/db/migrate/20200318175008_add_index_on_id_and_archived_and_pending_delete_to_projects.rb b/db/migrate/20200318175008_add_index_on_id_and_archived_and_pending_delete_to_projects.rb
deleted file mode 100644
index 9dba8537764..00000000000
--- a/db/migrate/20200318175008_add_index_on_id_and_archived_and_pending_delete_to_projects.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnIdAndArchivedAndPendingDeleteToProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_projects_on_id_and_archived_and_pending_delete'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, :id, where: "archived = FALSE AND pending_delete = FALSE", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :projects, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200318183553_create_pypi_package_metadata.rb b/db/migrate/20200318183553_create_pypi_package_metadata.rb
deleted file mode 100644
index 6ebe70da643..00000000000
--- a/db/migrate/20200318183553_create_pypi_package_metadata.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePypiPackageMetadata < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- create_table :packages_pypi_metadata, id: false do |t|
- t.references :package, primary_key: true, index: false, default: nil, foreign_key: { to_table: :packages_packages, on_delete: :cascade }, type: :bigint
- t.string "required_python", null: false, limit: 50 # rubocop:disable Migration/PreventStrings
- end
- end
-end
diff --git a/db/migrate/20200319123041_update_plan_limits_defaults.rb b/db/migrate/20200319123041_update_plan_limits_defaults.rb
deleted file mode 100644
index 252af26cb7f..00000000000
--- a/db/migrate/20200319123041_update_plan_limits_defaults.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class UpdatePlanLimitsDefaults < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- change_column_default :plan_limits, :project_hooks, 100
- change_column_default :plan_limits, :group_hooks, 50
- change_column_default :plan_limits, :ci_project_subscriptions, 2
- change_column_default :plan_limits, :ci_pipeline_schedules, 10
- end
-
- def down
- change_column_default :plan_limits, :project_hooks, 0
- change_column_default :plan_limits, :group_hooks, 0
- change_column_default :plan_limits, :ci_project_subscriptions, 0
- change_column_default :plan_limits, :ci_pipeline_schedules, 0
- end
-end
diff --git a/db/migrate/20200319124127_create_metrics_dashboard_annotations.rb b/db/migrate/20200319124127_create_metrics_dashboard_annotations.rb
deleted file mode 100644
index 9e10299b4f8..00000000000
--- a/db/migrate/20200319124127_create_metrics_dashboard_annotations.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class CreateMetricsDashboardAnnotations < ActiveRecord::Migration[6.0]
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :metrics_dashboard_annotations do |t|
- t.datetime_with_timezone :starting_at, null: false
- t.datetime_with_timezone :ending_at
- t.references :environment, index: false, foreign_key: { on_delete: :cascade }, null: true
- t.references :cluster, index: false, foreign_key: { on_delete: :cascade }, null: true
- t.string :dashboard_path, null: false, limit: 255
- t.string :panel_xid, limit: 255
- t.text :description, null: false, limit: 255 # rubocop:disable Migration/AddLimitToTextColumns
-
- t.index %i(environment_id dashboard_path starting_at ending_at), where: 'environment_id IS NOT NULL', name: "index_metrics_dashboard_annotations_on_environment_id_and_3_col"
- t.index %i(cluster_id dashboard_path starting_at ending_at), where: 'cluster_id IS NOT NULL', name: "index_metrics_dashboard_annotations_on_cluster_id_and_3_columns"
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200319203901_add_index_on_users_unlock_token.rb b/db/migrate/20200319203901_add_index_on_users_unlock_token.rb
deleted file mode 100644
index 931e685f3fe..00000000000
--- a/db/migrate/20200319203901_add_index_on_users_unlock_token.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnUsersUnlockToken < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_users_on_unlock_token'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :users, :unlock_token, unique: true, name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :users, :unlock_token, unique: true, name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20200320112455_add_cost_factor_fileds_to_ci_runners.rb b/db/migrate/20200320112455_add_cost_factor_fileds_to_ci_runners.rb
deleted file mode 100644
index ca92b395b6f..00000000000
--- a/db/migrate/20200320112455_add_cost_factor_fileds_to_ci_runners.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddCostFactorFiledsToCiRunners < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column_with_default(:ci_runners, :public_projects_minutes_cost_factor, :float, allow_null: false, default: 0.0) # rubocop:disable Migration/AddColumnWithDefault
- add_column_with_default(:ci_runners, :private_projects_minutes_cost_factor, :float, allow_null: false, default: 1.0) # rubocop:disable Migration/AddColumnWithDefault
- end
-
- def down
- remove_column(:ci_runners, :public_projects_minutes_cost_factor)
- remove_column(:ci_runners, :private_projects_minutes_cost_factor)
- end
-end
diff --git a/db/migrate/20200320123839_add_letsencrypt_errors_to_pages_domains.rb b/db/migrate/20200320123839_add_letsencrypt_errors_to_pages_domains.rb
deleted file mode 100644
index 6e7c37918e1..00000000000
--- a/db/migrate/20200320123839_add_letsencrypt_errors_to_pages_domains.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddLetsencryptErrorsToPagesDomains < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column_with_default :pages_domains, :auto_ssl_failed, :boolean, default: false # rubocop:disable Migration/AddColumnWithDefault
- end
-
- def down
- remove_column :pages_domains, :auto_ssl_failed
- end
-end
diff --git a/db/migrate/20200320212400_add_project_show_default_award_emojis.rb b/db/migrate/20200320212400_add_project_show_default_award_emojis.rb
deleted file mode 100644
index c8238f75455..00000000000
--- a/db/migrate/20200320212400_add_project_show_default_award_emojis.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectShowDefaultAwardEmojis < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- add_column :project_settings, :show_default_award_emojis, :boolean, default: true, null: false
- end
-end
diff --git a/db/migrate/20200323071918_add_bio_to_user_details.rb b/db/migrate/20200323071918_add_bio_to_user_details.rb
deleted file mode 100644
index 9ef9d553215..00000000000
--- a/db/migrate/20200323071918_add_bio_to_user_details.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddBioToUserDetails < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # rubocop:disable Migration/PreventStrings
- def up
- # rubocop:disable Migration/AddColumnWithDefault
- add_column_with_default(:user_details, :bio, :string, default: '', allow_null: false, limit: 255)
- # rubocop:enable Migration/AddColumnWithDefault
- end
- # rubocop:enable Migration/PreventStrings
-
- def down
- remove_column(:user_details, :bio)
- end
-end
diff --git a/db/migrate/20200323074147_add_temp_index_on_users_bio.rb b/db/migrate/20200323074147_add_temp_index_on_users_bio.rb
deleted file mode 100644
index 4b26bb971f5..00000000000
--- a/db/migrate/20200323074147_add_temp_index_on_users_bio.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddTempIndexOnUsersBio < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'tmp_idx_on_user_id_where_bio_is_filled'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :users, :id, where: "(COALESCE(bio, '') IS DISTINCT FROM '')", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :users, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb b/db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb
deleted file mode 100644
index 7388d6bbc13..00000000000
--- a/db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddMaxPersonalAccessTokenLifetimeToNamespaces < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :namespaces, :max_personal_access_token_lifetime, :integer # rubocop:disable Migration/AddColumnsToWideTables
- end
- end
-
- def down
- with_lock_retries do
- remove_column :namespaces, :max_personal_access_token_lifetime
- end
- end
-end
diff --git a/db/migrate/20200323122201_add_index_on_user_and_created_at_to_ci_builds.rb b/db/migrate/20200323122201_add_index_on_user_and_created_at_to_ci_builds.rb
deleted file mode 100644
index d0f63034502..00000000000
--- a/db/migrate/20200323122201_add_index_on_user_and_created_at_to_ci_builds.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnUserAndCreatedAtToCiBuilds < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'index_ci_builds_on_user_id_and_created_at_and_type_eq_ci_build'
-
- def up
- add_concurrent_index :ci_builds, [:user_id, :created_at], where: "type = 'Ci::Build'", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :ci_builds, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200323134519_add_api_indexes_for_archived_projects.rb b/db/migrate/20200323134519_add_api_indexes_for_archived_projects.rb
deleted file mode 100644
index cacf427dbe4..00000000000
--- a/db/migrate/20200323134519_add_api_indexes_for_archived_projects.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class AddApiIndexesForArchivedProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- PUBLIC_AND_ARCHIVED_INDEX_NAME = "index_projects_api_created_at_id_for_archived_vis20"
- ARCHIVED_INDEX_NAME = "index_projects_api_created_at_id_for_archived"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, [:created_at, :id],
- where: "archived = true AND visibility_level = 20 AND pending_delete = false",
- name: PUBLIC_AND_ARCHIVED_INDEX_NAME
-
- add_concurrent_index :projects, [:created_at, :id], where: "archived = true AND pending_delete = false",
- name: ARCHIVED_INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :projects, ARCHIVED_INDEX_NAME
-
- remove_concurrent_index_by_name :projects, PUBLIC_AND_ARCHIVED_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200324093258_add_index_on_id_creator_id_and_created_at_to_projects_table.rb b/db/migrate/20200324093258_add_index_on_id_creator_id_and_created_at_to_projects_table.rb
deleted file mode 100644
index 6c4d59af5d6..00000000000
--- a/db/migrate/20200324093258_add_index_on_id_creator_id_and_created_at_to_projects_table.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnIdCreatorIdAndCreatedAtToProjectsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_service_desk_enabled_projects_on_id_creator_id_created_at'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, [:id, :creator_id, :created_at], where: '"projects"."service_desk_enabled" = TRUE', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :projects, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200324115359_add_namespace_storage_size_limit_to_application_settings.rb b/db/migrate/20200324115359_add_namespace_storage_size_limit_to_application_settings.rb
deleted file mode 100644
index 793dc4678c6..00000000000
--- a/db/migrate/20200324115359_add_namespace_storage_size_limit_to_application_settings.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddNamespaceStorageSizeLimitToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- add_column_with_default :application_settings, :namespace_storage_size_limit, :bigint, default: 0 # rubocop:disable Migration/AddColumnWithDefault
- end
-
- def down
- remove_column :application_settings, :namespace_storage_size_limit
- end
-end
diff --git a/db/migrate/20200325094612_add_allow_merge_on_skipped_pipeline_to_project_settings.rb b/db/migrate/20200325094612_add_allow_merge_on_skipped_pipeline_to_project_settings.rb
deleted file mode 100644
index 8575dd2f080..00000000000
--- a/db/migrate/20200325094612_add_allow_merge_on_skipped_pipeline_to_project_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddAllowMergeOnSkippedPipelineToProjectSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :project_settings, :allow_merge_on_skipped_pipeline, :boolean
- end
-end
diff --git a/db/migrate/20200325104755_add_push_rules_id_to_project_settings.rb b/db/migrate/20200325104755_add_push_rules_id_to_project_settings.rb
deleted file mode 100644
index 93de736436b..00000000000
--- a/db/migrate/20200325104755_add_push_rules_id_to_project_settings.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddPushRulesIdToProjectSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :project_settings, :push_rule_id, :bigint
- end
- end
-
- def down
- with_lock_retries do
- remove_column :project_settings, :push_rule_id
- end
- end
-end
diff --git a/db/migrate/20200325104756_add_push_rules_foreign_key_to_project_settings.rb b/db/migrate/20200325104756_add_push_rules_foreign_key_to_project_settings.rb
deleted file mode 100644
index 41ad8d73b4c..00000000000
--- a/db/migrate/20200325104756_add_push_rules_foreign_key_to_project_settings.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddPushRulesForeignKeyToProjectSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :project_settings, :push_rule_id, unique: true
- add_concurrent_foreign_key :project_settings, :push_rules, column: :push_rule_id, on_delete: :cascade
- end
-
- def down
- remove_foreign_key_if_exists :project_settings, column: :push_rule_id
- remove_concurrent_index :project_settings, :push_rule_id
- end
-end
diff --git a/db/migrate/20200325104833_add_push_rules_id_to_application_settings.rb b/db/migrate/20200325104833_add_push_rules_id_to_application_settings.rb
deleted file mode 100644
index 4650f1734c0..00000000000
--- a/db/migrate/20200325104833_add_push_rules_id_to_application_settings.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddPushRulesIdToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :application_settings, :push_rule_id, :bigint
- end
- end
-
- def down
- with_lock_retries do
- remove_column :application_settings, :push_rule_id
- end
- end
-end
diff --git a/db/migrate/20200325104834_add_push_rules_foreign_key_to_application_settings.rb b/db/migrate/20200325104834_add_push_rules_foreign_key_to_application_settings.rb
deleted file mode 100644
index 5263250833d..00000000000
--- a/db/migrate/20200325104834_add_push_rules_foreign_key_to_application_settings.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddPushRulesForeignKeyToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :application_settings, :push_rule_id, unique: true
- add_concurrent_foreign_key :application_settings, :push_rules, column: :push_rule_id, on_delete: :nullify
- end
-
- def down
- remove_concurrent_index :application_settings, :push_rule_id
- remove_foreign_key_if_exists :application_settings, column: :push_rule_id
- end
-end
diff --git a/db/migrate/20200325111432_add_issues_create_limit_to_application_settings.rb b/db/migrate/20200325111432_add_issues_create_limit_to_application_settings.rb
deleted file mode 100644
index 60da96ccf33..00000000000
--- a/db/migrate/20200325111432_add_issues_create_limit_to_application_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddIssuesCreateLimitToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :issues_create_limit, :integer, default: 300, null: false
- end
-end
diff --git a/db/migrate/20200325152327_add_seat_link_enabled_to_application_settings.rb b/db/migrate/20200325152327_add_seat_link_enabled_to_application_settings.rb
deleted file mode 100644
index fbea3ad1227..00000000000
--- a/db/migrate/20200325152327_add_seat_link_enabled_to_application_settings.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddSeatLinkEnabledToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column_with_default(:application_settings, :seat_link_enabled, # rubocop:disable Migration/AddColumnWithDefault
- :boolean,
- default: true,
- allow_null: false)
- end
-
- def down
- remove_column(:application_settings, :seat_link_enabled)
- end
-end
diff --git a/db/migrate/20200325160952_add_index_on_name_type_eq_ci_build_to_ci_builds.rb b/db/migrate/20200325160952_add_index_on_name_type_eq_ci_build_to_ci_builds.rb
deleted file mode 100644
index 7e15c3ad11d..00000000000
--- a/db/migrate/20200325160952_add_index_on_name_type_eq_ci_build_to_ci_builds.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnNameTypeEqCiBuildToCiBuilds < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'index_ci_builds_on_name_and_security_type_eq_ci_build'
-
- def up
- add_concurrent_index :ci_builds, [:name, :id],
- name: INDEX_NAME,
- where: "((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text, ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text)"
- end
-
- def down
- remove_concurrent_index_by_name :ci_builds, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200325183636_add_api_index_for_internal_projects.rb b/db/migrate/20200325183636_add_api_index_for_internal_projects.rb
deleted file mode 100644
index ce47f1f3ded..00000000000
--- a/db/migrate/20200325183636_add_api_index_for_internal_projects.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddApiIndexForInternalProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INTERNAL_PROJECTS_INDEX_NAME = "index_projects_api_created_at_id_for_vis10"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, [:created_at, :id],
- where: "visibility_level = 10 AND pending_delete = false",
- name: INTERNAL_PROJECTS_INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :projects, INTERNAL_PROJECTS_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200326114443_create_jira_imports_table.rb b/db/migrate/20200326114443_create_jira_imports_table.rb
deleted file mode 100644
index d53ccb166b0..00000000000
--- a/db/migrate/20200326114443_create_jira_imports_table.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class CreateJiraImportsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :jira_imports do |t|
- t.integer :project_id, null: false, limit: 8
- t.integer :user_id, limit: 8
- t.integer :label_id, limit: 8
- t.timestamps_with_timezone
- t.datetime_with_timezone :finished_at
- t.integer :jira_project_xid, null: false, limit: 8
- t.integer :total_issue_count, null: false, default: 0, limit: 4
- t.integer :imported_issues_count, null: false, default: 0, limit: 4
- t.integer :failed_to_import_count, null: false, default: 0, limit: 4
- t.integer :status, limit: 2, null: false, default: 0
- t.string :jid, limit: 255
- t.string :jira_project_key, null: false, limit: 255
- t.string :jira_project_name, null: false, limit: 255
- end
-
- add_index :jira_imports, [:project_id, :jira_project_key], name: 'index_jira_imports_on_project_id_and_jira_project_key'
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200326122700_create_diff_note_positions.rb b/db/migrate/20200326122700_create_diff_note_positions.rb
deleted file mode 100644
index d37f7fef078..00000000000
--- a/db/migrate/20200326122700_create_diff_note_positions.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDiffNotePositions < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # rubocop:disable Migration/PreventStrings
- def up
- with_lock_retries do
- create_table :diff_note_positions do |t|
- t.references :note, foreign_key: { on_delete: :cascade }, null: false, index: false
- t.integer :old_line
- t.integer :new_line
- t.integer :diff_content_type, limit: 2, null: false
- t.integer :diff_type, limit: 2, null: false
- t.string :line_code, limit: 255, null: false
- t.binary :base_sha, null: false
- t.binary :start_sha, null: false
- t.binary :head_sha, null: false
- t.text :old_path, null: false
- t.text :new_path, null: false
-
- t.index [:note_id, :diff_type], unique: true
- end
- end
- end
- # rubocop:enable Migration/PreventStrings
- # rubocop:enable Migration/AddLimitToTextColumns
-
- def down
- drop_table :diff_note_positions
- end
-end
diff --git a/db/migrate/20200326124443_add_projects_fk_to_jira_imports_table.rb b/db/migrate/20200326124443_add_projects_fk_to_jira_imports_table.rb
deleted file mode 100644
index 654d35619e3..00000000000
--- a/db/migrate/20200326124443_add_projects_fk_to_jira_imports_table.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectsFkToJiraImportsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :jira_imports, :projects, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :jira_imports, :projects
- end
- end
-end
diff --git a/db/migrate/20200326134443_add_users_fk_to_jira_imports_table.rb b/db/migrate/20200326134443_add_users_fk_to_jira_imports_table.rb
deleted file mode 100644
index 429f72628e2..00000000000
--- a/db/migrate/20200326134443_add_users_fk_to_jira_imports_table.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddUsersFkToJiraImportsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :jira_imports, :users, on_delete: :nullify
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :jira_imports, :users
- end
- end
-end
diff --git a/db/migrate/20200326135443_add_users_fk_index_on_jira_imports_table.rb b/db/migrate/20200326135443_add_users_fk_index_on_jira_imports_table.rb
deleted file mode 100644
index 5a26672f305..00000000000
--- a/db/migrate/20200326135443_add_users_fk_index_on_jira_imports_table.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddUsersFkIndexOnJiraImportsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :jira_imports, :user_id
- end
-
- def down
- remove_concurrent_index :jira_imports, :user_id
- end
-end
diff --git a/db/migrate/20200326144443_add_labels_fk_to_jira_imports_table.rb b/db/migrate/20200326144443_add_labels_fk_to_jira_imports_table.rb
deleted file mode 100644
index 9bcadcb61c1..00000000000
--- a/db/migrate/20200326144443_add_labels_fk_to_jira_imports_table.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddLabelsFkToJiraImportsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :jira_imports, :labels, on_delete: :nullify
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :jira_imports, :labels
- end
- end
-end
diff --git a/db/migrate/20200326145443_add_labels_fk_index_on_jira_imports_table.rb b/db/migrate/20200326145443_add_labels_fk_index_on_jira_imports_table.rb
deleted file mode 100644
index d71c6f07989..00000000000
--- a/db/migrate/20200326145443_add_labels_fk_index_on_jira_imports_table.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddLabelsFkIndexOnJiraImportsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :jira_imports, :label_id
- end
-
- def down
- remove_concurrent_index :jira_imports, :label_id
- end
-end
diff --git a/db/migrate/20200330074719_add_index_for_group_vsm_usage_ping.rb b/db/migrate/20200330074719_add_index_for_group_vsm_usage_ping.rb
deleted file mode 100644
index 55ae2383d71..00000000000
--- a/db/migrate/20200330074719_add_index_for_group_vsm_usage_ping.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexForGroupVsmUsagePing < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_analytics_cycle_analytics_group_stages_custom_only'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :analytics_cycle_analytics_group_stages, :id, where: 'custom = true', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :analytics_cycle_analytics_group_stages, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200330121000_add_confidential_attribute_to_epics.rb b/db/migrate/20200330121000_add_confidential_attribute_to_epics.rb
deleted file mode 100644
index 4db227728c8..00000000000
--- a/db/migrate/20200330121000_add_confidential_attribute_to_epics.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddConfidentialAttributeToEpics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column_with_default(:epics, :confidential, :boolean, default: false) # rubocop:disable Migration/AddColumnWithDefault
- end
-
- def down
- remove_column(:epics, :confidential)
- end
-end
diff --git a/db/migrate/20200330123739_remove_index_ci_builds_on_name_for_security_reports_values.rb b/db/migrate/20200330123739_remove_index_ci_builds_on_name_for_security_reports_values.rb
deleted file mode 100644
index 7ab57183e18..00000000000
--- a/db/migrate/20200330123739_remove_index_ci_builds_on_name_for_security_reports_values.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexCiBuildsOnNameForSecurityReportsValues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'index_ci_builds_on_name_for_security_reports_values'
-
- def up
- remove_concurrent_index_by_name :ci_builds, INDEX_NAME
- end
-
- def down
- add_concurrent_index :ci_builds,
- :name,
- name: INDEX_NAME,
- where: "((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text, ('license_scanning'::character varying)::text]))"
- end
-end
diff --git a/db/migrate/20200330132913_add_index_on_author_id_and_created_at_and_id_to_notes.rb b/db/migrate/20200330132913_add_index_on_author_id_and_created_at_and_id_to_notes.rb
deleted file mode 100644
index 3b0a63ee565..00000000000
--- a/db/migrate/20200330132913_add_index_on_author_id_and_created_at_and_id_to_notes.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnAuthorIdAndCreatedAtAndIdToNotes < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :notes, [:author_id, :created_at, :id]
- remove_concurrent_index :notes, [:author_id, :created_at]
- end
-
- def down
- add_concurrent_index :notes, [:author_id, :created_at]
- remove_concurrent_index :notes, [:author_id, :created_at, :id]
- end
-end
diff --git a/db/migrate/20200330203826_drop_fk_in_ci_ref.rb b/db/migrate/20200330203826_drop_fk_in_ci_ref.rb
deleted file mode 100644
index 08cb4aaddab..00000000000
--- a/db/migrate/20200330203826_drop_fk_in_ci_ref.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class DropFkInCiRef < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- remove_foreign_key_if_exists :ci_refs, column: :project_id
- end
- with_lock_retries do
- remove_foreign_key_if_exists :ci_refs, column: :last_updated_by_pipeline_id
- end
- end
-
- def down
- add_foreign_key_if_not_exists :ci_refs, :projects, column: :project_id, on_delete: :cascade
- add_foreign_key_if_not_exists :ci_refs, :ci_pipelines, column: :last_updated_by_pipeline_id, on_delete: :nullify
- end
-
- private
-
- def add_foreign_key_if_not_exists(source, target, column:, on_delete:)
- return unless table_exists?(source)
- return if foreign_key_exists?(source, target, column: column)
-
- add_concurrent_foreign_key(source, target, column: column, on_delete: on_delete)
- end
-end
diff --git a/db/migrate/20200330203837_recreate_ci_ref.rb b/db/migrate/20200330203837_recreate_ci_ref.rb
deleted file mode 100644
index 734795f594f..00000000000
--- a/db/migrate/20200330203837_recreate_ci_ref.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-class RecreateCiRef < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- UNKNOWN_STATUS = 0
-
- def up
- with_lock_retries do
- # rubocop:disable Migration/DropTable
- drop_table :ci_refs
- # rubocop:enable Migration/DropTable
-
- create_table :ci_refs do |t|
- t.references :project, null: false, index: false, foreign_key: { on_delete: :cascade }, type: :bigint
- t.integer :lock_version, null: false, default: 0
- t.integer :status, null: false, limit: 2, default: UNKNOWN_STATUS
- t.text :ref_path, null: false # rubocop: disable Migration/AddLimitToTextColumns
- t.index [:project_id, :ref_path], unique: true
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :ci_refs
-
- create_table :ci_refs do |t|
- t.references :project, null: false, index: false, foreign_key: { on_delete: :cascade }, type: :integer
- t.integer :lock_version, default: 0
- t.integer :last_updated_by_pipeline_id
- t.boolean :tag, default: false, null: false
- t.string :ref, null: false, limit: 255
- t.string :status, null: false, limit: 255
- t.foreign_key :ci_pipelines, column: :last_updated_by_pipeline_id, on_delete: :nullify
- t.index [:project_id, :ref, :tag], unique: true
- t.index [:last_updated_by_pipeline_id]
- end
- end
- end
-end
diff --git a/db/migrate/20200331103637_add_ci_ref_id_to_ci_pipelines.rb b/db/migrate/20200331103637_add_ci_ref_id_to_ci_pipelines.rb
deleted file mode 100644
index 9f2780670dc..00000000000
--- a/db/migrate/20200331103637_add_ci_ref_id_to_ci_pipelines.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddCiRefIdToCiPipelines < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :ci_pipelines, :ci_ref_id, :bigint
- end
- end
-
- def down
- with_lock_retries do
- remove_column :ci_pipelines, :ci_ref_id, :bigint
- end
- end
-end
diff --git a/db/migrate/20200331113728_add_index_to_ci_ref_id.rb b/db/migrate/20200331113728_add_index_to_ci_ref_id.rb
deleted file mode 100644
index d3495fd4fa1..00000000000
--- a/db/migrate/20200331113728_add_index_to_ci_ref_id.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToCiRefId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_pipelines, [:ci_ref_id], where: 'ci_ref_id IS NOT NULL'
- end
-
- def down
- remove_concurrent_index :ci_pipelines, [:ci_ref_id], where: 'ci_ref_id IS NOT NULL'
- end
-end
diff --git a/db/migrate/20200331113738_add_fk_to_ci_ref_id.rb b/db/migrate/20200331113738_add_fk_to_ci_ref_id.rb
deleted file mode 100644
index 1a7a76904b1..00000000000
--- a/db/migrate/20200331113738_add_fk_to_ci_ref_id.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddFkToCiRefId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :ci_pipelines, :ci_refs, column: :ci_ref_id, on_delete: :nullify
- end
-
- def down
- with_lock_retries do
- remove_foreign_key_if_exists :ci_pipelines, column: :ci_ref_id
- end
- end
-end
diff --git a/db/migrate/20200331132103_add_project_compliance_framework_settings_table.rb b/db/migrate/20200331132103_add_project_compliance_framework_settings_table.rb
deleted file mode 100644
index 6af8c6db939..00000000000
--- a/db/migrate/20200331132103_add_project_compliance_framework_settings_table.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectComplianceFrameworkSettingsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :project_compliance_framework_settings, id: false do |t|
- t.references :project, primary_key: true, null: false, index: true, foreign_key: { on_delete: :cascade }
- t.integer :framework, null: false, limit: 2
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :project_compliance_framework_settings
- end
- end
-end
diff --git a/db/migrate/20200331195952_add_container_expiration_policies_enable_historic_entries_to_application_settings.rb b/db/migrate/20200331195952_add_container_expiration_policies_enable_historic_entries_to_application_settings.rb
deleted file mode 100644
index b4cbb04b93a..00000000000
--- a/db/migrate/20200331195952_add_container_expiration_policies_enable_historic_entries_to_application_settings.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddContainerExpirationPoliciesEnableHistoricEntriesToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column_with_default(:application_settings, # rubocop:disable Migration/AddColumnWithDefault
- :container_expiration_policies_enable_historic_entries,
- :boolean,
- default: false,
- allow_null: false)
- end
-
- def down
- remove_column(:application_settings,
- :container_expiration_policies_enable_historic_entries)
- end
-end
diff --git a/db/migrate/20200331220930_enable_container_expiration_policies_by_default.rb b/db/migrate/20200331220930_enable_container_expiration_policies_by_default.rb
deleted file mode 100644
index 46393416eb7..00000000000
--- a/db/migrate/20200331220930_enable_container_expiration_policies_by_default.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class EnableContainerExpirationPoliciesByDefault < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :container_expiration_policies, :enabled, true
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :container_expiration_policies, :enabled, false
- end
- end
-end
diff --git a/db/migrate/20200401095430_add_jsonb_to_geo_node_status_table.rb b/db/migrate/20200401095430_add_jsonb_to_geo_node_status_table.rb
deleted file mode 100644
index 46eb826341c..00000000000
--- a/db/migrate/20200401095430_add_jsonb_to_geo_node_status_table.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddJsonbToGeoNodeStatusTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_table :geo_node_statuses do |t|
- t.jsonb :status, null: false, default: {}
- end
- end
-end
diff --git a/db/migrate/20200401211005_create_operations_user_lists.rb b/db/migrate/20200401211005_create_operations_user_lists.rb
deleted file mode 100644
index b0b02ca8886..00000000000
--- a/db/migrate/20200401211005_create_operations_user_lists.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class CreateOperationsUserLists < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :operations_user_lists do |t|
- t.references :project, index: false, foreign_key: { on_delete: :cascade }, null: false
- t.timestamps_with_timezone
- t.integer :iid, null: false
- t.string :name, null: false, limit: 255 # rubocop:disable Migration/PreventStrings
- t.text :user_xids, null: false, default: '' # rubocop:disable Migration/AddLimitToTextColumns
-
- t.index [:project_id, :iid], unique: true
- t.index [:project_id, :name], unique: true
- end
- end
-end
diff --git a/db/migrate/20200402001106_add_cluster_type_index_to_clusters.rb b/db/migrate/20200402001106_add_cluster_type_index_to_clusters.rb
deleted file mode 100644
index b328b8681c1..00000000000
--- a/db/migrate/20200402001106_add_cluster_type_index_to_clusters.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddClusterTypeIndexToClusters < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
- INDEX_NAME = 'index_clusters_on_enabled_cluster_type_id_and_created_at'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :clusters, [:enabled, :cluster_type, :id, :created_at], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :clusters, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200402115013_add_index_on_modsecurity_to_ingress.rb b/db/migrate/20200402115013_add_index_on_modsecurity_to_ingress.rb
deleted file mode 100644
index 8bd2d957092..00000000000
--- a/db/migrate/20200402115013_add_index_on_modsecurity_to_ingress.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnModsecurityToIngress < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_clusters_applications_ingress_on_modsecurity'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :clusters_applications_ingress, [:modsecurity_enabled, :modsecurity_mode, :cluster_id], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :clusters_applications_ingress, [:modsecurity_enabled, :modsecurity_mode, :cluster_id], name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20200402115623_add_index_on_successful_deployment_and_environment_id_to_deployments.rb b/db/migrate/20200402115623_add_index_on_successful_deployment_and_environment_id_to_deployments.rb
deleted file mode 100644
index c86f7ad63f0..00000000000
--- a/db/migrate/20200402115623_add_index_on_successful_deployment_and_environment_id_to_deployments.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnSuccessfulDeploymentAndEnvironmentIdToDeployments < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_successful_deployments_on_cluster_id_and_environment_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :deployments, [:cluster_id, :environment_id], where: 'status = 2', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :deployments, [:cluster_id, :environment_id], where: 'status = 2', name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20200402123926_add_line_metrics_to_mr_metrics.rb b/db/migrate/20200402123926_add_line_metrics_to_mr_metrics.rb
deleted file mode 100644
index 1ca106e1614..00000000000
--- a/db/migrate/20200402123926_add_line_metrics_to_mr_metrics.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddLineMetricsToMrMetrics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :merge_request_metrics, :added_lines, :integer
- add_column :merge_request_metrics, :removed_lines, :integer
- end
- end
-
- def down
- with_lock_retries do
- remove_column :merge_request_metrics, :added_lines, :integer
- remove_column :merge_request_metrics, :removed_lines, :integer
- end
- end
-end
diff --git a/db/migrate/20200402124802_add_correlation_id_to_project_import_state.rb b/db/migrate/20200402124802_add_correlation_id_to_project_import_state.rb
deleted file mode 100644
index 97eb01529cc..00000000000
--- a/db/migrate/20200402124802_add_correlation_id_to_project_import_state.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddCorrelationIdToProjectImportState < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def up
- with_lock_retries do
- add_column :project_mirror_data, :correlation_id_value, :string, limit: 128
- end
- end
- # rubocop:enable Migration/PreventStrings
-
- def down
- with_lock_retries do
- remove_column :project_mirror_data, :correlation_id_value
- end
- end
-end
diff --git a/db/migrate/20200402135250_add_delete_status_to_container_repository.rb b/db/migrate/20200402135250_add_delete_status_to_container_repository.rb
deleted file mode 100644
index a0dbb307bfc..00000000000
--- a/db/migrate/20200402135250_add_delete_status_to_container_repository.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddDeleteStatusToContainerRepository < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column(:container_repositories, :status, :integer, limit: 2)
- end
-
- def down
- remove_column(:container_repositories, :status)
- end
-end
diff --git a/db/migrate/20200402185044_create_clusters_applications_fluentd.rb b/db/migrate/20200402185044_create_clusters_applications_fluentd.rb
deleted file mode 100644
index 2116b2ffe01..00000000000
--- a/db/migrate/20200402185044_create_clusters_applications_fluentd.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class CreateClustersApplicationsFluentd < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- create_table :clusters_applications_fluentd do |t|
- t.integer :protocol, null: false, limit: 2
- t.integer :status, null: false
- t.integer :port, null: false
- t.references :cluster, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade }
- t.timestamps_with_timezone null: false
- t.string :version, null: false, limit: 255
- t.string :host, null: false, limit: 255
- t.text :status_reason # rubocop:disable Migration/AddLimitToTextColumns
- end
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200403184110_add_partial_index_on_id_to_ci_job_artifacts.rb b/db/migrate/20200403184110_add_partial_index_on_id_to_ci_job_artifacts.rb
deleted file mode 100644
index f5f9f167df3..00000000000
--- a/db/migrate/20200403184110_add_partial_index_on_id_to_ci_job_artifacts.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddPartialIndexOnIdToCiJobArtifacts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_ci_job_artifacts_file_store_is_null'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_job_artifacts, :id, where: 'file_store IS NULL', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :ci_job_artifacts, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200403185127_add_partial_index_on_id_to_lfs_objects.rb b/db/migrate/20200403185127_add_partial_index_on_id_to_lfs_objects.rb
deleted file mode 100644
index e72bb37eb0e..00000000000
--- a/db/migrate/20200403185127_add_partial_index_on_id_to_lfs_objects.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddPartialIndexOnIdToLfsObjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_lfs_objects_file_store_is_null'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :lfs_objects, :id, where: 'file_store IS NULL', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :lfs_objects, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200403185422_add_partial_index_on_id_to_uploads.rb b/db/migrate/20200403185422_add_partial_index_on_id_to_uploads.rb
deleted file mode 100644
index e5b532bad61..00000000000
--- a/db/migrate/20200403185422_add_partial_index_on_id_to_uploads.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddPartialIndexOnIdToUploads < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_uploads_store_is_null'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :uploads, :id, where: 'store IS NULL', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :uploads, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200406095930_add_needs_ssl_renewal_user_provided_pages_domains_index.rb b/db/migrate/20200406095930_add_needs_ssl_renewal_user_provided_pages_domains_index.rb
deleted file mode 100644
index 73db5e71b94..00000000000
--- a/db/migrate/20200406095930_add_needs_ssl_renewal_user_provided_pages_domains_index.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddNeedsSslRenewalUserProvidedPagesDomainsIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = 'index_pages_domains_need_auto_ssl_renewal_user_provided'
- INDEX_SCOPE = "auto_ssl_enabled = true AND auto_ssl_failed = false AND certificate_source = 0"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:pages_domains, :id, where: INDEX_SCOPE, name: INDEX_NAME)
- end
-
- def down
- remove_concurrent_index(:pages_domains, :id, where: INDEX_SCOPE, name: INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200406100909_add_needs_ssl_renewal_valid_not_after_pages_domains_index.rb b/db/migrate/20200406100909_add_needs_ssl_renewal_valid_not_after_pages_domains_index.rb
deleted file mode 100644
index 3c5db9ec082..00000000000
--- a/db/migrate/20200406100909_add_needs_ssl_renewal_valid_not_after_pages_domains_index.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddNeedsSslRenewalValidNotAfterPagesDomainsIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = 'index_pages_domains_need_auto_ssl_renewal_valid_not_after'
- INDEX_SCOPE = "auto_ssl_enabled = true AND auto_ssl_failed = false"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:pages_domains, :certificate_valid_not_after, where: INDEX_SCOPE, name: INDEX_NAME)
- end
-
- def down
- remove_concurrent_index(:pages_domains, :certificate_valid_not_after, where: INDEX_SCOPE, name: INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200406102111_add_index_to_deployments_where_cluster_id_is_not_null.rb b/db/migrate/20200406102111_add_index_to_deployments_where_cluster_id_is_not_null.rb
deleted file mode 100644
index 67ffba6af5e..00000000000
--- a/db/migrate/20200406102111_add_index_to_deployments_where_cluster_id_is_not_null.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToDeploymentsWhereClusterIdIsNotNull < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :deployments, :id, where: 'cluster_id IS NOT NULL', name: 'index_deployments_on_id_where_cluster_id_present'
- end
-
- def down
- remove_concurrent_index :deployments, :id, where: 'cluster_id IS NOT NULL', name: 'index_deployments_on_id_where_cluster_id_present'
- end
-end
diff --git a/db/migrate/20200406132529_add_resource_state_events_table.rb b/db/migrate/20200406132529_add_resource_state_events_table.rb
deleted file mode 100644
index ce241dff4dd..00000000000
--- a/db/migrate/20200406132529_add_resource_state_events_table.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddResourceStateEventsTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :resource_state_events, id: :bigserial do |t|
- t.bigint :user_id, null: false
- t.bigint :issue_id, null: true
- t.bigint :merge_request_id, null: true
-
- t.datetime_with_timezone :created_at, null: false
- t.integer :state, limit: 2, null: false
-
- t.index [:issue_id, :created_at], name: 'index_resource_state_events_on_issue_id_and_created_at'
- t.index [:user_id], name: 'index_resource_state_events_on_user_id'
- t.index [:merge_request_id], name: 'index_resource_state_events_on_merge_request_id'
- end
- end
-end
diff --git a/db/migrate/20200406135648_add_index_to_created_at_on_resource_milestone_events.rb b/db/migrate/20200406135648_add_index_to_created_at_on_resource_milestone_events.rb
deleted file mode 100644
index 6b8b981990d..00000000000
--- a/db/migrate/20200406135648_add_index_to_created_at_on_resource_milestone_events.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToCreatedAtOnResourceMilestoneEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- INDEX_NAME = 'index_resource_milestone_events_created_at'
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :resource_milestone_events, :created_at, name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :resource_milestone_events, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200406141452_add_index_to_issue_id_and_created_at_on_resource_weight_events.rb b/db/migrate/20200406141452_add_index_to_issue_id_and_created_at_on_resource_weight_events.rb
deleted file mode 100644
index 94a1b589ff9..00000000000
--- a/db/migrate/20200406141452_add_index_to_issue_id_and_created_at_on_resource_weight_events.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToIssueIdAndCreatedAtOnResourceWeightEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- INDEX_NAME = 'index_resource_weight_events_on_issue_id_and_created_at'
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :resource_weight_events, [:issue_id, :created_at], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :resource_weight_events, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200406192059_add_write_registry_to_deploy_tokens.rb b/db/migrate/20200406192059_add_write_registry_to_deploy_tokens.rb
deleted file mode 100644
index 9d1628bc42a..00000000000
--- a/db/migrate/20200406192059_add_write_registry_to_deploy_tokens.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddWriteRegistryToDeployTokens < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column_with_default(:deploy_tokens, :write_registry, :boolean, default: false, allow_null: false) # rubocop:disable Migration/AddColumnWithDefault
- end
-
- def down
- remove_column(:deploy_tokens, :write_registry)
- end
-end
diff --git a/db/migrate/20200407120000_add_push_rule_id_to_groups.rb b/db/migrate/20200407120000_add_push_rule_id_to_groups.rb
deleted file mode 100644
index 738f0a4c605..00000000000
--- a/db/migrate/20200407120000_add_push_rule_id_to_groups.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddPushRuleIdToGroups < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :namespaces, :push_rule_id, :bigint # rubocop:disable Migration/AddColumnsToWideTables
- end
- end
-
- def down
- with_lock_retries do
- remove_column :namespaces, :push_rule_id
- end
- end
-end
diff --git a/db/migrate/20200407121321_add_push_rule_foreign_key_to_groups.rb b/db/migrate/20200407121321_add_push_rule_foreign_key_to_groups.rb
deleted file mode 100644
index acc74b43659..00000000000
--- a/db/migrate/20200407121321_add_push_rule_foreign_key_to_groups.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddPushRuleForeignKeyToGroups < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :namespaces, :push_rule_id, unique: true
- add_concurrent_foreign_key :namespaces, :push_rules, column: :push_rule_id, on_delete: :nullify
- end
-
- def down
- remove_foreign_key_if_exists :namespaces, column: :push_rule_id
- remove_concurrent_index :namespaces, :push_rule_id
- end
-end
diff --git a/db/migrate/20200407171133_add_protected_tag_create_access_levels_user_id_foreign_key.rb b/db/migrate/20200407171133_add_protected_tag_create_access_levels_user_id_foreign_key.rb
deleted file mode 100644
index 79532b8179c..00000000000
--- a/db/migrate/20200407171133_add_protected_tag_create_access_levels_user_id_foreign_key.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class AddProtectedTagCreateAccessLevelsUserIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_protected_tag_create_access_levels_user_id'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- add_foreign_key(:protected_tag_create_access_levels, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME)
- remove_foreign_key_if_exists(:protected_tag_create_access_levels, column: :user_id, on_delete: nil)
- end
- end
-
- def down
- fk_exists = foreign_key_exists?(:protected_tag_create_access_levels, :users, column: :user_id, on_delete: nil)
-
- unless fk_exists
- with_lock_retries do
- add_foreign_key(:protected_tag_create_access_levels, :users, column: :user_id, validate: false)
- end
- end
-
- remove_foreign_key_if_exists(:protected_tag_create_access_levels, column: :user_id, name: CONSTRAINT_NAME)
-
- fk_name = concurrent_foreign_key_name(:protected_tag_create_access_levels, :user_id, prefix: 'fk_rails_')
- validate_foreign_key(:protected_tag_create_access_levels, :user_id, name: fk_name)
- end
-end
diff --git a/db/migrate/20200407171417_validate_protected_tag_create_access_levels_user_id_foreign_key.rb b/db/migrate/20200407171417_validate_protected_tag_create_access_levels_user_id_foreign_key.rb
deleted file mode 100644
index baba65e0b7d..00000000000
--- a/db/migrate/20200407171417_validate_protected_tag_create_access_levels_user_id_foreign_key.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateProtectedTagCreateAccessLevelsUserIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_protected_tag_create_access_levels_user_id'
-
- def up
- validate_foreign_key :protected_tag_create_access_levels, :user_id, name: CONSTRAINT_NAME
- end
-
- def down
- # no op
- end
-end
diff --git a/db/migrate/20200407182205_create_partitioned_foreign_keys.rb b/db/migrate/20200407182205_create_partitioned_foreign_keys.rb
deleted file mode 100644
index aca8116d2dd..00000000000
--- a/db/migrate/20200407182205_create_partitioned_foreign_keys.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePartitionedForeignKeys < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :partitioned_foreign_keys do |t|
- t.boolean :cascade_delete, null: false, default: true
- t.text :from_table, null: false
- t.text :from_column, null: false
- t.text :to_table, null: false
- t.text :to_column, null: false
- end
-
- add_text_limit :partitioned_foreign_keys, :from_table, 63
- add_text_limit :partitioned_foreign_keys, :from_column, 63
- add_text_limit :partitioned_foreign_keys, :to_table, 63
- add_text_limit :partitioned_foreign_keys, :to_column, 63
-
- add_index :partitioned_foreign_keys, [:to_table, :from_table, :from_column], unique: true,
- name: "index_partitioned_foreign_keys_unique_index"
- end
-
- def down
- drop_table :partitioned_foreign_keys
- end
-end
diff --git a/db/migrate/20200407222647_create_project_repository_storage_moves.rb b/db/migrate/20200407222647_create_project_repository_storage_moves.rb
deleted file mode 100644
index 402a1cdd4a6..00000000000
--- a/db/migrate/20200407222647_create_project_repository_storage_moves.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class CreateProjectRepositoryStorageMoves < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :project_repository_storage_moves do |t|
- t.timestamps_with_timezone
- t.integer :project_id, limit: 8, null: false
- t.integer :state, limit: 2, default: 1, null: false
- t.text :source_storage_name, null: false
- t.text :destination_storage_name, null: false
- end
-
- add_index :project_repository_storage_moves, :project_id
-
- add_text_limit(:project_repository_storage_moves, :source_storage_name, 255, constraint_name: 'project_repository_storage_moves_source_storage_name')
- add_text_limit(:project_repository_storage_moves, :destination_storage_name, 255, constraint_name: 'project_repository_storage_moves_destination_storage_name')
- end
-
- def down
- remove_check_constraint(:project_repository_storage_moves, 'project_repository_storage_moves_source_storage_name')
- remove_check_constraint(:project_repository_storage_moves, 'project_repository_storage_moves_destination_storage_name')
-
- drop_table :project_repository_storage_moves
- end
-end
diff --git a/db/migrate/20200408125046_create_ci_freeze_periods.rb b/db/migrate/20200408125046_create_ci_freeze_periods.rb
deleted file mode 100644
index 42a385150b8..00000000000
--- a/db/migrate/20200408125046_create_ci_freeze_periods.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCiFreezePeriods < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:ci_freeze_periods)
- create_table :ci_freeze_periods do |t|
- t.references :project, foreign_key: true, null: false
- t.text :freeze_start, null: false
- t.text :freeze_end, null: false
- t.text :cron_timezone, null: false
-
- t.timestamps_with_timezone null: false
- end
- end
-
- add_text_limit :ci_freeze_periods, :freeze_start, 998
- add_text_limit :ci_freeze_periods, :freeze_end, 998
- add_text_limit :ci_freeze_periods, :cron_timezone, 255
- end
-
- def down
- drop_table :ci_freeze_periods
- end
-end
diff --git a/db/migrate/20200408133211_add_index_on_route_path_trigram.rb b/db/migrate/20200408133211_add_index_on_route_path_trigram.rb
deleted file mode 100644
index 3329252bbd3..00000000000
--- a/db/migrate/20200408133211_add_index_on_route_path_trigram.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnRoutePathTrigram < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_routes_on_path_trigram'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :routes, :path, name: INDEX_NAME, using: :gin, opclass: { path: :gin_trgm_ops }
- end
-
- def down
- remove_concurrent_index_by_name(:routes, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200408153842_add_index_on_creator_id_and_id_on_projects.rb b/db/migrate/20200408153842_add_index_on_creator_id_and_id_on_projects.rb
deleted file mode 100644
index 2cc91efcc36..00000000000
--- a/db/migrate/20200408153842_add_index_on_creator_id_and_id_on_projects.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnCreatorIdAndIdOnProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, [:creator_id, :id]
- end
-
- def down
- remove_concurrent_index :projects, [:creator_id, :id]
- end
-end
diff --git a/db/migrate/20200408154331_add_protected_branch_merge_access_levels_user_id_foreign_key.rb b/db/migrate/20200408154331_add_protected_branch_merge_access_levels_user_id_foreign_key.rb
deleted file mode 100644
index 0c5118c162b..00000000000
--- a/db/migrate/20200408154331_add_protected_branch_merge_access_levels_user_id_foreign_key.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class AddProtectedBranchMergeAccessLevelsUserIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_protected_branch_merge_access_levels_user_id'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- add_foreign_key(:protected_branch_merge_access_levels, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME)
- remove_foreign_key_if_exists(:protected_branch_merge_access_levels, column: :user_id, on_delete: nil)
- end
- end
-
- def down
- fk_exists = foreign_key_exists?(:protected_branch_merge_access_levels, :users, column: :user_id, on_delete: nil)
-
- unless fk_exists
- with_lock_retries do
- add_foreign_key(:protected_branch_merge_access_levels, :users, column: :user_id, validate: false)
- end
- end
-
- remove_foreign_key_if_exists(:protected_branch_merge_access_levels, column: :user_id, name: CONSTRAINT_NAME)
-
- fk_name = concurrent_foreign_key_name(:protected_branch_merge_access_levels, :user_id, prefix: 'fk_rails_')
- validate_foreign_key(:protected_branch_merge_access_levels, :user_id, name: fk_name)
- end
-end
diff --git a/db/migrate/20200408154349_validate_protected_branch_merge_access_levels_user_id_foreign_key.rb b/db/migrate/20200408154349_validate_protected_branch_merge_access_levels_user_id_foreign_key.rb
deleted file mode 100644
index c4ec957d607..00000000000
--- a/db/migrate/20200408154349_validate_protected_branch_merge_access_levels_user_id_foreign_key.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateProtectedBranchMergeAccessLevelsUserIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_protected_branch_merge_access_levels_user_id'
-
- def up
- validate_foreign_key :protected_branch_merge_access_levels, :user_id, name: CONSTRAINT_NAME
- end
-
- def down
- # no op
- end
-end
diff --git a/db/migrate/20200408154411_add_path_locks_user_id_foreign_key.rb b/db/migrate/20200408154411_add_path_locks_user_id_foreign_key.rb
deleted file mode 100644
index aae79c175bc..00000000000
--- a/db/migrate/20200408154411_add_path_locks_user_id_foreign_key.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class AddPathLocksUserIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_path_locks_user_id'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- add_foreign_key(:path_locks, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME)
- remove_foreign_key_if_exists(:path_locks, column: :user_id, on_delete: nil)
- end
- end
-
- def down
- fk_exists = foreign_key_exists?(:path_locks, :users, column: :user_id, on_delete: nil)
-
- unless fk_exists
- with_lock_retries do
- add_foreign_key(:path_locks, :users, column: :user_id, validate: false)
- end
- end
-
- remove_foreign_key_if_exists(:path_locks, column: :user_id, name: CONSTRAINT_NAME)
-
- fk_name = concurrent_foreign_key_name(:path_locks, :user_id, prefix: 'fk_rails_')
- validate_foreign_key(:path_locks, :user_id, name: fk_name)
- end
-end
diff --git a/db/migrate/20200408154428_validate_path_locks_user_id_foreign_key.rb b/db/migrate/20200408154428_validate_path_locks_user_id_foreign_key.rb
deleted file mode 100644
index 500409ee44a..00000000000
--- a/db/migrate/20200408154428_validate_path_locks_user_id_foreign_key.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class ValidatePathLocksUserIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_path_locks_user_id'
-
- def up
- validate_foreign_key :path_locks, :user_id, name: CONSTRAINT_NAME
- end
-
- def down
- # no op
- end
-end
diff --git a/db/migrate/20200408154455_add_protected_branch_push_access_levels_user_id_foreign_key.rb b/db/migrate/20200408154455_add_protected_branch_push_access_levels_user_id_foreign_key.rb
deleted file mode 100644
index 1cfe240df05..00000000000
--- a/db/migrate/20200408154455_add_protected_branch_push_access_levels_user_id_foreign_key.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class AddProtectedBranchPushAccessLevelsUserIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_protected_branch_push_access_levels_user_id'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- add_foreign_key(:protected_branch_push_access_levels, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME)
- remove_foreign_key_if_exists(:protected_branch_push_access_levels, column: :user_id, on_delete: nil)
- end
- end
-
- def down
- fk_exists = foreign_key_exists?(:protected_branch_push_access_levels, :users, column: :user_id, on_delete: nil)
-
- unless fk_exists
- with_lock_retries do
- add_foreign_key(:protected_branch_push_access_levels, :users, column: :user_id, validate: false)
- end
- end
-
- remove_foreign_key_if_exists(:protected_branch_push_access_levels, column: :user_id, name: CONSTRAINT_NAME)
-
- fk_name = concurrent_foreign_key_name(:protected_branch_push_access_levels, :user_id, prefix: 'fk_rails_')
- validate_foreign_key(:protected_branch_push_access_levels, :user_id, name: fk_name)
- end
-end
diff --git a/db/migrate/20200408154533_validate_protected_branch_push_access_levels_user_id_foreign_key.rb b/db/migrate/20200408154533_validate_protected_branch_push_access_levels_user_id_foreign_key.rb
deleted file mode 100644
index d6f9cab6d7e..00000000000
--- a/db/migrate/20200408154533_validate_protected_branch_push_access_levels_user_id_foreign_key.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateProtectedBranchPushAccessLevelsUserIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_protected_branch_push_access_levels_user_id'
-
- def up
- validate_foreign_key :protected_branch_push_access_levels, :user_id, name: CONSTRAINT_NAME
- end
-
- def down
- # no op
- end
-end
diff --git a/db/migrate/20200408154604_add_u2f_registrations_user_id_foreign_key.rb b/db/migrate/20200408154604_add_u2f_registrations_user_id_foreign_key.rb
deleted file mode 100644
index cdb81d73c99..00000000000
--- a/db/migrate/20200408154604_add_u2f_registrations_user_id_foreign_key.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class AddU2fRegistrationsUserIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_u2f_registrations_user_id'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- add_foreign_key(:u2f_registrations, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME)
- remove_foreign_key_if_exists(:u2f_registrations, column: :user_id, on_delete: nil)
- end
- end
-
- def down
- fk_exists = foreign_key_exists?(:u2f_registrations, :users, column: :user_id, on_delete: nil)
-
- unless fk_exists
- with_lock_retries do
- add_foreign_key(:u2f_registrations, :users, column: :user_id, validate: false)
- end
- end
-
- remove_foreign_key_if_exists(:u2f_registrations, column: :user_id, name: CONSTRAINT_NAME)
-
- fk_name = concurrent_foreign_key_name(:u2f_registrations, :user_id, prefix: 'fk_rails_')
- validate_foreign_key(:u2f_registrations, :user_id, name: fk_name)
- end
-end
diff --git a/db/migrate/20200408154624_validate_u2f_registrations_user_id_foreign_key.rb b/db/migrate/20200408154624_validate_u2f_registrations_user_id_foreign_key.rb
deleted file mode 100644
index ff723a4793f..00000000000
--- a/db/migrate/20200408154624_validate_u2f_registrations_user_id_foreign_key.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-#
-class ValidateU2fRegistrationsUserIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_u2f_registrations_user_id'
-
- def up
- validate_foreign_key :u2f_registrations, :user_id, name: CONSTRAINT_NAME
- end
-
- def down
- # no op
- end
-end
diff --git a/db/migrate/20200408175424_add_index_on_creator_id_created_at_id_to_projects_table.rb b/db/migrate/20200408175424_add_index_on_creator_id_created_at_id_to_projects_table.rb
deleted file mode 100644
index 70df38aea17..00000000000
--- a/db/migrate/20200408175424_add_index_on_creator_id_created_at_id_to_projects_table.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnCreatorIdCreatedAtIdToProjectsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, [:creator_id, :created_at, :id]
- end
-
- def down
- remove_concurrent_index :projects, [:creator_id, :created_at, :id]
- end
-end
diff --git a/db/migrate/20200408212219_add_status_page_url_to_status_page_settings.rb b/db/migrate/20200408212219_add_status_page_url_to_status_page_settings.rb
deleted file mode 100644
index 3b3849c109c..00000000000
--- a/db/migrate/20200408212219_add_status_page_url_to_status_page_settings.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddStatusPageUrlToStatusPageSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column :status_page_settings, :status_page_url, :text
- add_text_limit :status_page_settings, :status_page_url, 1024
- end
-
- def down
- remove_column :status_page_settings, :status_page_url
- end
-end
diff --git a/db/migrate/20200409085956_add_partial_index_on_import_failures_retry_count.rb b/db/migrate/20200409085956_add_partial_index_on_import_failures_retry_count.rb
deleted file mode 100644
index 0999f7b4c95..00000000000
--- a/db/migrate/20200409085956_add_partial_index_on_import_failures_retry_count.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddPartialIndexOnImportFailuresRetryCount < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :import_failures, [:project_id, :correlation_id_value], where: 'retry_count = 0'
- end
-
- def down
- remove_concurrent_index :import_failures, [:project_id, :correlation_id_value]
- end
-end
diff --git a/db/migrate/20200409105455_change_verification_checksum_field_type_in_package_file.rb b/db/migrate/20200409105455_change_verification_checksum_field_type_in_package_file.rb
deleted file mode 100644
index 187ab0aa20b..00000000000
--- a/db/migrate/20200409105455_change_verification_checksum_field_type_in_package_file.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeVerificationChecksumFieldTypeInPackageFile < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- # The use of this column is behind a feature flag that never got enabled,
- # so it's safe to remove it in a normal migration
- remove_column :packages_package_files, :verification_checksum, :string # rubocop:disable Migration/RemoveColumn
- add_column :packages_package_files, :verification_checksum, :binary
- end
-
- def down
- remove_column :packages_package_files, :verification_checksum, :binary
- add_column :packages_package_files, :verification_checksum, :string
- end
-end
diff --git a/db/migrate/20200409105456_add_checksum_index_to_package_file.rb b/db/migrate/20200409105456_add_checksum_index_to_package_file.rb
deleted file mode 100644
index 07762109895..00000000000
--- a/db/migrate/20200409105456_add_checksum_index_to_package_file.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddChecksumIndexToPackageFile < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :packages_package_files, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: "packages_packages_verification_checksum_partial"
- end
-
- def down
- remove_concurrent_index :packages_package_files, :verification_checksum
- end
-end
diff --git a/db/migrate/20200410104828_add_comment_detail_to_services.rb b/db/migrate/20200410104828_add_comment_detail_to_services.rb
deleted file mode 100644
index 61d993cce32..00000000000
--- a/db/migrate/20200410104828_add_comment_detail_to_services.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddCommentDetailToServices < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column :services, :comment_detail, :smallint
- end
-
- def down
- remove_column :services, :comment_detail
- end
-end
diff --git a/db/migrate/20200410232012_add_metrics_dashboard_access_level_to_project_feature.rb b/db/migrate/20200410232012_add_metrics_dashboard_access_level_to_project_feature.rb
deleted file mode 100644
index 2953cdf3429..00000000000
--- a/db/migrate/20200410232012_add_metrics_dashboard_access_level_to_project_feature.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddMetricsDashboardAccessLevelToProjectFeature < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :project_features, :metrics_dashboard_access_level, :integer
- end
- end
-
- def down
- with_lock_retries do
- remove_column :project_features, :metrics_dashboard_access_level, :integer
- end
- end
-end
diff --git a/db/migrate/20200411125656_add_package_scopes_to_deploy_tokens.rb b/db/migrate/20200411125656_add_package_scopes_to_deploy_tokens.rb
deleted file mode 100644
index e7e2f91d4d1..00000000000
--- a/db/migrate/20200411125656_add_package_scopes_to_deploy_tokens.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddPackageScopesToDeployTokens < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column_with_default(:deploy_tokens, :read_package_registry, :boolean, default: false, allow_null: false) # rubocop:disable Migration/AddColumnWithDefault
- add_column_with_default(:deploy_tokens, :write_package_registry, :boolean, default: false, allow_null: false) # rubocop:disable Migration/AddColumnWithDefault
- end
-
- def down
- remove_column(:deploy_tokens, :read_package_registry)
- remove_column(:deploy_tokens, :write_package_registry)
- end
-end
diff --git a/db/migrate/20200413072059_add_group_owners_can_manage_default_branch_protection_to_application_settings.rb b/db/migrate/20200413072059_add_group_owners_can_manage_default_branch_protection_to_application_settings.rb
deleted file mode 100644
index 2918aaea93e..00000000000
--- a/db/migrate/20200413072059_add_group_owners_can_manage_default_branch_protection_to_application_settings.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddGroupOwnersCanManageDefaultBranchProtectionToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- add_column_with_default(:application_settings, # rubocop:disable Migration/AddColumnWithDefault
- :group_owners_can_manage_default_branch_protection,
- :boolean,
- default: true)
- end
-
- def down
- remove_column :application_settings, :group_owners_can_manage_default_branch_protection
- end
-end
diff --git a/db/migrate/20200413230056_add_waf_and_cilium_logs_to_applications_fluentd.rb b/db/migrate/20200413230056_add_waf_and_cilium_logs_to_applications_fluentd.rb
deleted file mode 100644
index 99f6aa0e4a8..00000000000
--- a/db/migrate/20200413230056_add_waf_and_cilium_logs_to_applications_fluentd.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class AddWafAndCiliumLogsToApplicationsFluentd < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column_with_default(:clusters_applications_fluentd, # rubocop:disable Migration/AddColumnWithDefault
- :waf_log_enabled,
- :boolean,
- default: true,
- allow_null: false)
- add_column_with_default(:clusters_applications_fluentd, # rubocop:disable Migration/AddColumnWithDefault
- :cilium_log_enabled,
- :boolean,
- default: true,
- allow_null: false)
- end
-
- def down
- remove_column(:clusters_applications_fluentd,
- :waf_log_enabled)
- remove_column(:clusters_applications_fluentd,
- :cilium_log_enabled)
- end
-end
diff --git a/db/migrate/20200414112444_add_group_id_to_vulnerability_exports.rb b/db/migrate/20200414112444_add_group_id_to_vulnerability_exports.rb
deleted file mode 100644
index fad63d53a81..00000000000
--- a/db/migrate/20200414112444_add_group_id_to_vulnerability_exports.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class AddGroupIdToVulnerabilityExports < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :vulnerability_exports, :group_id, :integer
- change_column_null :vulnerability_exports, :project_id, true
- end
-end
diff --git a/db/migrate/20200414114611_add_group_id_index_and_fk_to_vulnerability_exports.rb b/db/migrate/20200414114611_add_group_id_index_and_fk_to_vulnerability_exports.rb
deleted file mode 100644
index a3e60b87857..00000000000
--- a/db/migrate/20200414114611_add_group_id_index_and_fk_to_vulnerability_exports.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddGroupIdIndexAndFkToVulnerabilityExports < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- GROUP_ID_INDEX_NAME = 'index_vulnerability_exports_on_group_id_not_null'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:vulnerability_exports, :group_id, where: 'group_id IS NOT NULL', name: GROUP_ID_INDEX_NAME)
- add_concurrent_foreign_key(:vulnerability_exports, :namespaces, column: :group_id)
- end
-
- def down
- remove_foreign_key(:vulnerability_exports, column: :group_id)
- remove_concurrent_index_by_name(:vulnerability_exports, GROUP_ID_INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200414115801_change_project_index_on_vulnerability_exports.rb b/db/migrate/20200414115801_change_project_index_on_vulnerability_exports.rb
deleted file mode 100644
index e669faa7fca..00000000000
--- a/db/migrate/20200414115801_change_project_index_on_vulnerability_exports.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeProjectIndexOnVulnerabilityExports < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- OLD_INDEX_NAME = 'index_vulnerability_exports_on_project_id_and_id'
- NEW_INDEX_NAME = 'index_vulnerability_exports_on_project_id_not_null'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:vulnerability_exports, :project_id, where: 'project_id IS NOT NULL', name: NEW_INDEX_NAME)
- remove_concurrent_index_by_name(:vulnerability_exports, OLD_INDEX_NAME)
- end
-
- def down
- add_concurrent_index(:vulnerability_exports, [:project_id, :id], unique: true, name: OLD_INDEX_NAME)
- remove_concurrent_index_by_name(:vulnerability_exports, NEW_INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200414144547_remove_index_projects_on_creator_id_and_created_at_from_projects.rb b/db/migrate/20200414144547_remove_index_projects_on_creator_id_and_created_at_from_projects.rb
deleted file mode 100644
index c4409fcc55d..00000000000
--- a/db/migrate/20200414144547_remove_index_projects_on_creator_id_and_created_at_from_projects.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexProjectsOnCreatorIdAndCreatedAtFromProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_projects_on_creator_id_and_created_at'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :projects, INDEX_NAME
- end
-
- def down
- add_concurrent_index :projects, [:creator_id, :created_at], name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20200415153154_add_unique_index_on_plan_name.rb b/db/migrate/20200415153154_add_unique_index_on_plan_name.rb
deleted file mode 100644
index d959d1315b4..00000000000
--- a/db/migrate/20200415153154_add_unique_index_on_plan_name.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddUniqueIndexOnPlanName < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index :plans, :name
- add_concurrent_index :plans, :name, unique: true
- end
-
- def down
- remove_concurrent_index :plans, :name, unique: true
- add_concurrent_index :plans, :name
- end
-end
diff --git a/db/migrate/20200415160722_remove_not_null_lfs_objects_constraint.rb b/db/migrate/20200415160722_remove_not_null_lfs_objects_constraint.rb
deleted file mode 100644
index 58cfa8e8969..00000000000
--- a/db/migrate/20200415160722_remove_not_null_lfs_objects_constraint.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveNotNullLfsObjectsConstraint < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- execute <<~SQL
- ALTER TABLE lfs_objects DROP CONSTRAINT IF EXISTS lfs_objects_file_store_not_null;
- SQL
- end
- end
-
- def down
- # No-op
- end
-end
diff --git a/db/migrate/20200415161021_remove_not_null_ci_job_artifacts_constraint.rb b/db/migrate/20200415161021_remove_not_null_ci_job_artifacts_constraint.rb
deleted file mode 100644
index 65430c180ce..00000000000
--- a/db/migrate/20200415161021_remove_not_null_ci_job_artifacts_constraint.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveNotNullCiJobArtifactsConstraint < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- execute <<~SQL
- ALTER TABLE ci_job_artifacts DROP CONSTRAINT IF EXISTS ci_job_artifacts_file_store_not_null;
- SQL
- end
- end
-
- def down
- # No-op
- end
-end
diff --git a/db/migrate/20200415161206_remove_not_null_uploads_constraint.rb b/db/migrate/20200415161206_remove_not_null_uploads_constraint.rb
deleted file mode 100644
index 23f202bac7e..00000000000
--- a/db/migrate/20200415161206_remove_not_null_uploads_constraint.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveNotNullUploadsConstraint < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- execute <<~SQL
- ALTER TABLE uploads DROP CONSTRAINT IF EXISTS uploads_store_not_null;
- SQL
- end
- end
-
- def down
- # No-op
- end
-end
diff --git a/db/migrate/20200415192656_add_name_regex_keep_to_container_expiration_policies.rb b/db/migrate/20200415192656_add_name_regex_keep_to_container_expiration_policies.rb
deleted file mode 100644
index e223d94caf7..00000000000
--- a/db/migrate/20200415192656_add_name_regex_keep_to_container_expiration_policies.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddNameRegexKeepToContainerExpirationPolicies < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'container_expiration_policies_name_regex_keep'
-
- def up
- add_column(:container_expiration_policies, :name_regex_keep, :text)
- add_text_limit(:container_expiration_policies, :name_regex_keep, 255, constraint_name: CONSTRAINT_NAME)
- end
-
- def down
- remove_check_constraint(:container_expiration_policies, CONSTRAINT_NAME)
- remove_column(:container_expiration_policies, :name_regex_keep)
- end
-end
diff --git a/db/migrate/20200415203024_add_offset_pagination_plan_limit.rb b/db/migrate/20200415203024_add_offset_pagination_plan_limit.rb
deleted file mode 100644
index b4d4be894f6..00000000000
--- a/db/migrate/20200415203024_add_offset_pagination_plan_limit.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddOffsetPaginationPlanLimit < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :plan_limits, :offset_pagination_limit, :integer, default: 50000, null: false
- end
-end
diff --git a/db/migrate/20200416005331_create_status_page_published_incidents.rb b/db/migrate/20200416005331_create_status_page_published_incidents.rb
deleted file mode 100644
index 75889cd5bb6..00000000000
--- a/db/migrate/20200416005331_create_status_page_published_incidents.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class CreateStatusPagePublishedIncidents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :status_page_published_incidents do |t|
- t.timestamps_with_timezone null: false
- t.references :issue, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade }
- end
- end
- end
-
- def down
- drop_table :status_page_published_incidents
- end
-end
diff --git a/db/migrate/20200416120128_add_columns_to_terraform_state.rb b/db/migrate/20200416120128_add_columns_to_terraform_state.rb
deleted file mode 100644
index 65d25d842e5..00000000000
--- a/db/migrate/20200416120128_add_columns_to_terraform_state.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddColumnsToTerraformState < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/PreventStrings
- def change
- add_column :terraform_states, :lock_xid, :string, limit: 255
- add_column :terraform_states, :locked_at, :datetime_with_timezone
- add_column :terraform_states, :locked_by_user_id, :bigint
- add_column :terraform_states, :uuid, :string, limit: 32, null: false # rubocop:disable Rails/NotNullColumn (table not used yet)
- add_column :terraform_states, :name, :string, limit: 255
- add_index :terraform_states, :locked_by_user_id # rubocop:disable Migration/AddIndex (table not used yet)
- add_index :terraform_states, :uuid, unique: true # rubocop:disable Migration/AddIndex (table not used yet)
- add_index :terraform_states, [:project_id, :name], unique: true # rubocop:disable Migration/AddIndex (table not used yet)
- remove_index :terraform_states, :project_id # rubocop:disable Migration/RemoveIndex (table not used yet)
- end
- # rubocop:enable Migration/PreventStrings
-end
diff --git a/db/migrate/20200416120354_add_locked_by_user_id_foreign_key_to_terraform_state.rb b/db/migrate/20200416120354_add_locked_by_user_id_foreign_key_to_terraform_state.rb
deleted file mode 100644
index 144291d94be..00000000000
--- a/db/migrate/20200416120354_add_locked_by_user_id_foreign_key_to_terraform_state.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddLockedByUserIdForeignKeyToTerraformState < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :terraform_states, :users, column: :locked_by_user_id
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :terraform_states, column: :locked_by_user_id
- end
- end
-end
diff --git a/db/migrate/20200417044453_create_alert_management_alerts.rb b/db/migrate/20200417044453_create_alert_management_alerts.rb
deleted file mode 100644
index 6221eeeb24b..00000000000
--- a/db/migrate/20200417044453_create_alert_management_alerts.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-class CreateAlertManagementAlerts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:alert_management_alerts)
- create_table :alert_management_alerts do |t|
- t.timestamps_with_timezone
- t.datetime_with_timezone :started_at, null: false
- t.datetime_with_timezone :ended_at
- t.integer :events, default: 1, null: false
- t.integer :iid, null: false
- t.integer :severity, default: 0, null: false, limit: 2
- t.integer :status, default: 0, null: false, limit: 2
- t.binary :fingerprint
- t.bigint :issue_id, index: true
- t.bigint :project_id, null: false
- t.text :title, null: false
- t.text :description
- t.text :service
- t.text :monitoring_tool
- t.text :hosts, array: true, null: false, default: [] # rubocop:disable Migration/AddLimitToTextColumns
- t.jsonb :payload, null: false, default: {}
-
- t.index %w(project_id iid), name: 'index_alert_management_alerts_on_project_id_and_iid', unique: true, using: :btree
- t.index %w(project_id fingerprint), name: 'index_alert_management_alerts_on_project_id_and_fingerprint', unique: true, using: :btree
- end
- end
-
- add_text_limit :alert_management_alerts, :title, 200
- add_text_limit :alert_management_alerts, :description, 1000
- add_text_limit :alert_management_alerts, :service, 100
- add_text_limit :alert_management_alerts, :monitoring_tool, 100
- end
-
- def down
- drop_table :alert_management_alerts
- end
-end
diff --git a/db/migrate/20200417075843_remove_and_add_foreign_key_to_project_settings.rb b/db/migrate/20200417075843_remove_and_add_foreign_key_to_project_settings.rb
deleted file mode 100644
index 695bd3381c8..00000000000
--- a/db/migrate/20200417075843_remove_and_add_foreign_key_to_project_settings.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveAndAddForeignKeyToProjectSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_project_settings_push_rule_id'
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :project_settings, :push_rules, column: :push_rule_id, name: CONSTRAINT_NAME, on_delete: :nullify
- remove_foreign_key_if_exists :project_settings, column: :push_rule_id, on_delete: :cascade
- end
-
- def down
- add_concurrent_foreign_key :project_settings, :push_rules, column: :push_rule_id, on_delete: :cascade
- remove_foreign_key_if_exists :project_settings, column: :push_rule_id, name: CONSTRAINT_NAME, on_delete: :nullify
- end
-end
diff --git a/db/migrate/20200417145946_add_locked_to_ci_job_artifact.rb b/db/migrate/20200417145946_add_locked_to_ci_job_artifact.rb
deleted file mode 100644
index 3bcc733f3b0..00000000000
--- a/db/migrate/20200417145946_add_locked_to_ci_job_artifact.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddLockedToCiJobArtifact < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :ci_job_artifacts, :locked, :boolean
- end
- end
-
- def down
- with_lock_retries do
- remove_column :ci_job_artifacts, :locked
- end
- end
-end
diff --git a/db/migrate/20200420092011_add_profile_image_guidelines_to_appearances.rb b/db/migrate/20200420092011_add_profile_image_guidelines_to_appearances.rb
deleted file mode 100644
index bab3e21e285..00000000000
--- a/db/migrate/20200420092011_add_profile_image_guidelines_to_appearances.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddProfileImageGuidelinesToAppearances < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column :appearances, :profile_image_guidelines, :text, null: true
- add_column :appearances, :profile_image_guidelines_html, :text, null: true # rubocop:disable Migration/AddLimitToTextColumns
-
- add_text_limit :appearances, :profile_image_guidelines, 4096, constraint_name: 'appearances_profile_image_guidelines'
- end
-
- def down
- remove_column :appearances, :profile_image_guidelines
- remove_column :appearances, :profile_image_guidelines_html
- end
-end
diff --git a/db/migrate/20200420104303_add_group_import_states_table.rb b/db/migrate/20200420104303_add_group_import_states_table.rb
deleted file mode 100644
index a44a2ea75f3..00000000000
--- a/db/migrate/20200420104303_add_group_import_states_table.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class AddGroupImportStatesTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- def up
- with_lock_retries do
- create_table :group_import_states, id: false do |t|
- t.references :group, primary_key: true, foreign_key: { to_table: :namespaces, on_delete: :cascade }
- t.timestamps_with_timezone null: false
- t.integer :status, limit: 2, null: false, default: 0
- t.text :jid, null: false, unique: true
- t.text :last_error
- end
- end
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-
- def down
- drop_table :group_import_states
- end
-end
diff --git a/db/migrate/20200420104323_add_text_limit_to_group_import_states.rb b/db/migrate/20200420104323_add_text_limit_to_group_import_states.rb
deleted file mode 100644
index c21b18d7b0e..00000000000
--- a/db/migrate/20200420104323_add_text_limit_to_group_import_states.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToGroupImportStates < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :group_import_states, :jid, 100
- add_text_limit :group_import_states, :last_error, 255
- end
-
- def down
- remove_text_limit :group_import_states, :jid
- remove_text_limit :group_import_states, :last_error
- end
-end
diff --git a/db/migrate/20200420115948_create_metrics_users_starred_dashboard.rb b/db/migrate/20200420115948_create_metrics_users_starred_dashboard.rb
deleted file mode 100644
index 27130136e9d..00000000000
--- a/db/migrate/20200420115948_create_metrics_users_starred_dashboard.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class CreateMetricsUsersStarredDashboard < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # limit added in following migration db/migrate/20200424101920_add_text_limit_to_metrics_users_starred_dashboards_dashboard_path.rb
- # to allow this migration to be run inside the transaction
- # rubocop: disable Migration/AddLimitToTextColumns
- def up
- create_table :metrics_users_starred_dashboards do |t|
- t.timestamps_with_timezone
- t.bigint :project_id, null: false
- t.bigint :user_id, null: false
- t.text :dashboard_path, null: false
-
- t.index :project_id
- t.index %i(user_id project_id dashboard_path), name: "idx_metrics_users_starred_dashboard_on_user_project_dashboard", unique: true
- end
- end
- # rubocop: enable Migration/AddLimitToTextColumns
-
- def down
- drop_table :metrics_users_starred_dashboards
- end
-end
diff --git a/db/migrate/20200420141733_add_index_on_enabled_clusters.rb b/db/migrate/20200420141733_add_index_on_enabled_clusters.rb
deleted file mode 100644
index 43f4b072c82..00000000000
--- a/db/migrate/20200420141733_add_index_on_enabled_clusters.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnEnabledClusters < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_enabled_clusters_on_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :clusters, [:id], where: 'enabled = true', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :clusters, [:id], where: 'enabled = true', name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20200420172113_add_text_limit_to_sprints_title.rb b/db/migrate/20200420172113_add_text_limit_to_sprints_title.rb
deleted file mode 100644
index 17707cc9dd1..00000000000
--- a/db/migrate/20200420172113_add_text_limit_to_sprints_title.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToSprintsTitle < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'sprints_title'
-
- def up
- add_text_limit :sprints, :title, 255, constraint_name: CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint :sprints, CONSTRAINT_NAME
- end
-end
diff --git a/db/migrate/20200420172752_add_sprints_foreign_key_to_projects.rb b/db/migrate/20200420172752_add_sprints_foreign_key_to_projects.rb
deleted file mode 100644
index 46b5c9c2ac2..00000000000
--- a/db/migrate/20200420172752_add_sprints_foreign_key_to_projects.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddSprintsForeignKeyToProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :sprints, :projects, column: :project_id, on_delete: :cascade
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :sprints, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20200420172927_add_sprints_foreign_key_to_groups.rb b/db/migrate/20200420172927_add_sprints_foreign_key_to_groups.rb
deleted file mode 100644
index cd90fe50cde..00000000000
--- a/db/migrate/20200420172927_add_sprints_foreign_key_to_groups.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddSprintsForeignKeyToGroups < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :sprints, :namespaces, column: :group_id, on_delete: :cascade
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :sprints, column: :group_id
- end
- end
-end
diff --git a/db/migrate/20200420201933_add_check_constraint_to_sprint_must_belong_to_project_or_group.rb b/db/migrate/20200420201933_add_check_constraint_to_sprint_must_belong_to_project_or_group.rb
deleted file mode 100644
index 9962eab95e3..00000000000
--- a/db/migrate/20200420201933_add_check_constraint_to_sprint_must_belong_to_project_or_group.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddCheckConstraintToSprintMustBelongToProjectOrGroup < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'sprints_must_belong_to_project_or_group'
-
- def up
- add_check_constraint :sprints, '(project_id != NULL AND group_id IS NULL) OR (group_id != NULL AND project_id IS NULL)', CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint :sprints, CONSTRAINT_NAME
- end
-end
diff --git a/db/migrate/20200421054930_remove_index_on_pipeline_id_from_ci_pipeline_variables.rb b/db/migrate/20200421054930_remove_index_on_pipeline_id_from_ci_pipeline_variables.rb
deleted file mode 100644
index 1a904188fc6..00000000000
--- a/db/migrate/20200421054930_remove_index_on_pipeline_id_from_ci_pipeline_variables.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexOnPipelineIdFromCiPipelineVariables < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_ci_pipeline_variables_on_pipeline_id'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :ci_pipeline_variables, INDEX_NAME
- end
-
- def down
- add_concurrent_index :ci_pipeline_variables, :pipeline_id, name: INDEX_NAME, where: "key = 'AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE'"
- end
-end
diff --git a/db/migrate/20200421054948_remove_index_on_pipeline_id_from_ci_variables.rb b/db/migrate/20200421054948_remove_index_on_pipeline_id_from_ci_variables.rb
deleted file mode 100644
index f7e6d10e8a3..00000000000
--- a/db/migrate/20200421054948_remove_index_on_pipeline_id_from_ci_variables.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexOnPipelineIdFromCiVariables < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_ci_variables_on_project_id'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :ci_variables, INDEX_NAME
- end
-
- def down
- add_concurrent_index :ci_variables, :project_id, name: INDEX_NAME, where: "key = 'AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE'"
- end
-end
diff --git a/db/migrate/20200421092907_add_index_container_repository_on_name_trigram_to_container_repository.rb b/db/migrate/20200421092907_add_index_container_repository_on_name_trigram_to_container_repository.rb
deleted file mode 100644
index debca8c6008..00000000000
--- a/db/migrate/20200421092907_add_index_container_repository_on_name_trigram_to_container_repository.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexContainerRepositoryOnNameTrigramToContainerRepository < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_container_repository_on_name_trigram'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :container_repositories, :name, name: INDEX_NAME, using: :gin, opclass: { name: :gin_trgm_ops }
- end
-
- def down
- remove_concurrent_index_by_name(:container_repositories, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200421111005_create_daily_build_group_report_results.rb b/db/migrate/20200421111005_create_daily_build_group_report_results.rb
deleted file mode 100644
index 12d1c7531d5..00000000000
--- a/db/migrate/20200421111005_create_daily_build_group_report_results.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDailyBuildGroupReportResults < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :ci_daily_build_group_report_results do |t|
- t.date :date, null: false
- t.bigint :project_id, null: false
- t.bigint :last_pipeline_id, null: false
- t.text :ref_path, null: false # rubocop:disable Migration/AddLimitToTextColumns
- t.text :group_name, null: false # rubocop:disable Migration/AddLimitToTextColumns
- t.jsonb :data, null: false
-
- t.index :last_pipeline_id
- t.index [:project_id, :ref_path, :date, :group_name], name: 'index_daily_build_group_report_results_unique_columns', unique: true
- t.foreign_key :projects, on_delete: :cascade
- t.foreign_key :ci_pipelines, column: :last_pipeline_id, on_delete: :cascade
- end
- end
-end
diff --git a/db/migrate/20200421233150_add_foreign_keys_for_alert_management_alerts.rb b/db/migrate/20200421233150_add_foreign_keys_for_alert_management_alerts.rb
deleted file mode 100644
index b16bdf9830c..00000000000
--- a/db/migrate/20200421233150_add_foreign_keys_for_alert_management_alerts.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeysForAlertManagementAlerts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :alert_management_alerts, :projects, column: :project_id, on_delete: :cascade
- add_concurrent_foreign_key :alert_management_alerts, :issues, column: :issue_id, on_delete: :nullify
- end
-
- def down
- remove_foreign_key_if_exists :alert_management_alerts, column: :project_id
- remove_foreign_key_if_exists :alert_management_alerts, column: :issue_id
- end
-end
diff --git a/db/migrate/20200422091541_create_ci_instance_variables.rb b/db/migrate/20200422091541_create_ci_instance_variables.rb
deleted file mode 100644
index ab2a4722f89..00000000000
--- a/db/migrate/20200422091541_create_ci_instance_variables.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCiInstanceVariables < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:ci_instance_variables)
- create_table :ci_instance_variables do |t|
- t.integer :variable_type, null: false, limit: 2, default: 1
- t.boolean :masked, default: false, allow_null: false
- t.boolean :protected, default: false, allow_null: false
- t.text :key, null: false
- t.text :encrypted_value
- t.text :encrypted_value_iv
-
- t.index [:key], name: 'index_ci_instance_variables_on_key', unique: true, using: :btree
- end
- end
-
- add_text_limit(:ci_instance_variables, :key, 255)
- add_text_limit(:ci_instance_variables, :encrypted_value, 1024)
- add_text_limit(:ci_instance_variables, :encrypted_value_iv, 255)
- end
-
- def down
- drop_table :ci_instance_variables
- end
-end
diff --git a/db/migrate/20200422213749_create_operations_strategies_user_lists.rb b/db/migrate/20200422213749_create_operations_strategies_user_lists.rb
deleted file mode 100644
index 113f2f2f54a..00000000000
--- a/db/migrate/20200422213749_create_operations_strategies_user_lists.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class CreateOperationsStrategiesUserLists < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :operations_strategies_user_lists do |t|
- t.references :strategy, index: false, foreign_key: { on_delete: :cascade, to_table: :operations_strategies }, null: false
- t.references :user_list, index: true, foreign_key: { on_delete: :cascade, to_table: :operations_user_lists }, null: false
-
- t.index [:strategy_id, :user_list_id], unique: true, name: :index_ops_strategies_user_lists_on_strategy_id_and_user_list_id
- end
- end
-end
diff --git a/db/migrate/20200423075720_add_user_id_foreign_key_to_resource_state_events.rb b/db/migrate/20200423075720_add_user_id_foreign_key_to_resource_state_events.rb
deleted file mode 100644
index 91a6dbe4214..00000000000
--- a/db/migrate/20200423075720_add_user_id_foreign_key_to_resource_state_events.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddUserIdForeignKeyToResourceStateEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :resource_state_events, :users, column: :user_id, on_delete: :nullify
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :resource_state_events, column: :user_id
- end
- end
-end
diff --git a/db/migrate/20200423080334_add_issue_id_foreign_key_to_resource_state_events.rb b/db/migrate/20200423080334_add_issue_id_foreign_key_to_resource_state_events.rb
deleted file mode 100644
index b9f0fdeaa16..00000000000
--- a/db/migrate/20200423080334_add_issue_id_foreign_key_to_resource_state_events.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIssueIdForeignKeyToResourceStateEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :resource_state_events, :issues, column: :issue_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :resource_state_events, column: :issue_id
- end
- end
-end
diff --git a/db/migrate/20200423080607_add_merge_request_id_foreign_key_to_resource_state_events.rb b/db/migrate/20200423080607_add_merge_request_id_foreign_key_to_resource_state_events.rb
deleted file mode 100644
index 3c070984f9e..00000000000
--- a/db/migrate/20200423080607_add_merge_request_id_foreign_key_to_resource_state_events.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddMergeRequestIdForeignKeyToResourceStateEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :resource_state_events, :merge_requests, column: :merge_request_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :resource_state_events, column: :merge_request_id
- end
- end
-end
diff --git a/db/migrate/20200423081409_add_constraint_to_resource_state_events_must_belong_to_issue_or_merge_request.rb b/db/migrate/20200423081409_add_constraint_to_resource_state_events_must_belong_to_issue_or_merge_request.rb
deleted file mode 100644
index 57df1045e2c..00000000000
--- a/db/migrate/20200423081409_add_constraint_to_resource_state_events_must_belong_to_issue_or_merge_request.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddConstraintToResourceStateEventsMustBelongToIssueOrMergeRequest < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'resource_state_events_must_belong_to_issue_or_merge_request'
-
- def up
- add_check_constraint :resource_state_events, '(issue_id != NULL AND merge_request_id IS NULL) OR (merge_request_id != NULL AND issue_id IS NULL)', CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint :resource_state_events, CONSTRAINT_NAME
- end
-end
diff --git a/db/migrate/20200423081441_add_foreign_key_from_users_to_metrics_users_starred_dashboars.rb b/db/migrate/20200423081441_add_foreign_key_from_users_to_metrics_users_starred_dashboars.rb
deleted file mode 100644
index c3a7635193c..00000000000
--- a/db/migrate/20200423081441_add_foreign_key_from_users_to_metrics_users_starred_dashboars.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyFromUsersToMetricsUsersStarredDashboars < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :metrics_users_starred_dashboards, :users, column: :user_id, on_delete: :cascade
- end
-
- def down
- with_lock_retries do
- remove_foreign_key_if_exists :metrics_users_starred_dashboards, column: :user_id
- end
- end
-end
diff --git a/db/migrate/20200423081519_add_foreign_key_from_projects_to_metrics_users_starred_dashboars.rb b/db/migrate/20200423081519_add_foreign_key_from_projects_to_metrics_users_starred_dashboars.rb
deleted file mode 100644
index 88565c24eca..00000000000
--- a/db/migrate/20200423081519_add_foreign_key_from_projects_to_metrics_users_starred_dashboars.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyFromProjectsToMetricsUsersStarredDashboars < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :metrics_users_starred_dashboards, :projects, column: :project_id, on_delete: :cascade
- end
-
- def down
- with_lock_retries do
- remove_foreign_key_if_exists :metrics_users_starred_dashboards, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20200423101529_add_scheduled_at_to_jira_imports.rb b/db/migrate/20200423101529_add_scheduled_at_to_jira_imports.rb
deleted file mode 100644
index f0d9393b6f9..00000000000
--- a/db/migrate/20200423101529_add_scheduled_at_to_jira_imports.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddScheduledAtToJiraImports < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :jira_imports, :scheduled_at, :datetime_with_timezone
- end
-end
diff --git a/db/migrate/20200424050250_remove_orphaned_invited_members.rb b/db/migrate/20200424050250_remove_orphaned_invited_members.rb
deleted file mode 100644
index 0fb2f7d9c39..00000000000
--- a/db/migrate/20200424050250_remove_orphaned_invited_members.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveOrphanedInvitedMembers < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- # As of 2020-04-23, there are 19 entries on GitLab.com that match this criteria.
- execute "DELETE FROM members WHERE user_id IS NULL AND invite_token IS NULL AND invite_accepted_at IS NOT NULL"
- end
-
- def down
- end
-end
diff --git a/db/migrate/20200424101920_add_text_limit_to_metrics_users_starred_dashboards_dashboard_path.rb b/db/migrate/20200424101920_add_text_limit_to_metrics_users_starred_dashboards_dashboard_path.rb
deleted file mode 100644
index a5620fd8e29..00000000000
--- a/db/migrate/20200424101920_add_text_limit_to_metrics_users_starred_dashboards_dashboard_path.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToMetricsUsersStarredDashboardsDashboardPath < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- add_text_limit :metrics_users_starred_dashboards, :dashboard_path, 255
- end
-
- def down
- remove_text_limit :metrics_users_starred_dashboards, :dashboard_path
- end
-end
diff --git a/db/migrate/20200424102023_add_shared_runners_enabled_and_override_to_namespaces.rb b/db/migrate/20200424102023_add_shared_runners_enabled_and_override_to_namespaces.rb
deleted file mode 100644
index 1adc421b9af..00000000000
--- a/db/migrate/20200424102023_add_shared_runners_enabled_and_override_to_namespaces.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddSharedRunnersEnabledAndOverrideToNamespaces < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :namespaces, :shared_runners_enabled, :boolean, default: true, null: false # rubocop:disable Migration/AddColumnsToWideTables
- add_column :namespaces, :allow_descendants_override_disabled_shared_runners, :boolean, default: false, null: false # rubocop:disable Migration/AddColumnsToWideTables
- end
- end
-
- def down
- with_lock_retries do
- remove_column :namespaces, :shared_runners_enabled, :boolean
- remove_column :namespaces, :allow_descendants_override_disabled_shared_runners, :boolean
- end
- end
-end
diff --git a/db/migrate/20200424135319_create_nuget_dependency_link_metadata.rb b/db/migrate/20200424135319_create_nuget_dependency_link_metadata.rb
deleted file mode 100644
index 1043616a1c7..00000000000
--- a/db/migrate/20200424135319_create_nuget_dependency_link_metadata.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class CreateNugetDependencyLinkMetadata < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'packages_nuget_dependency_link_metadata_target_framework_constr'
-
- def up
- unless table_exists?(:packages_nuget_dependency_link_metadata)
- create_table :packages_nuget_dependency_link_metadata, id: false do |t|
- t.references :dependency_link, primary_key: true, default: nil, foreign_key: { to_table: :packages_dependency_links, on_delete: :cascade }, index: { name: 'index_packages_nuget_dl_metadata_on_dependency_link_id' }, type: :bigint
- t.text :target_framework, null: false
- end
- end
-
- add_text_limit :packages_nuget_dependency_link_metadata, :target_framework, 255, constraint_name: CONSTRAINT_NAME
- end
-
- def down
- drop_table :packages_nuget_dependency_link_metadata
- end
-end
diff --git a/db/migrate/20200429001827_sprint_rename_state_to_state_enum.rb b/db/migrate/20200429001827_sprint_rename_state_to_state_enum.rb
deleted file mode 100644
index 721b9b7c64f..00000000000
--- a/db/migrate/20200429001827_sprint_rename_state_to_state_enum.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class SprintRenameStateToStateEnum < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- rename_column_concurrently :sprints, :state, :state_enum
- end
-
- def down
- undo_rename_column_concurrently :sprints, :state, :state_enum
- end
-end
diff --git a/db/migrate/20200429015603_add_fk_to_project_repository_storage_moves.rb b/db/migrate/20200429015603_add_fk_to_project_repository_storage_moves.rb
deleted file mode 100644
index 166ce320a23..00000000000
--- a/db/migrate/20200429015603_add_fk_to_project_repository_storage_moves.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddFkToProjectRepositoryStorageMoves < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :project_repository_storage_moves, :projects, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :project_repository_storage_moves, :projects
- end
- end
-end
diff --git a/db/migrate/20200429023324_add_composer_metadata.rb b/db/migrate/20200429023324_add_composer_metadata.rb
deleted file mode 100644
index 738b630bec1..00000000000
--- a/db/migrate/20200429023324_add_composer_metadata.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AddComposerMetadata < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :packages_composer_metadata, id: false do |t|
- t.references :package, primary_key: true, index: false, default: nil, foreign_key: { to_table: :packages_packages, on_delete: :cascade }, type: :bigint
- t.binary :target_sha, null: false
- end
- end
-end
diff --git a/db/migrate/20200429181335_add_default_value_for_file_store_to_lfs_objects.rb b/db/migrate/20200429181335_add_default_value_for_file_store_to_lfs_objects.rb
deleted file mode 100644
index f316a092bfc..00000000000
--- a/db/migrate/20200429181335_add_default_value_for_file_store_to_lfs_objects.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultValueForFileStoreToLfsObjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :lfs_objects, :file_store, 1
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :lfs_objects, :file_store, nil
- end
- end
-end
diff --git a/db/migrate/20200429181955_add_default_value_for_file_store_to_ci_job_artifacts.rb b/db/migrate/20200429181955_add_default_value_for_file_store_to_ci_job_artifacts.rb
deleted file mode 100644
index ac3d5e41e3e..00000000000
--- a/db/migrate/20200429181955_add_default_value_for_file_store_to_ci_job_artifacts.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultValueForFileStoreToCiJobArtifacts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :ci_job_artifacts, :file_store, 1
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :ci_job_artifacts, :file_store, nil
- end
- end
-end
diff --git a/db/migrate/20200429182245_add_default_value_for_store_to_uploads.rb b/db/migrate/20200429182245_add_default_value_for_store_to_uploads.rb
deleted file mode 100644
index f28fcce8f2f..00000000000
--- a/db/migrate/20200429182245_add_default_value_for_store_to_uploads.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultValueForStoreToUploads < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :uploads, :store, 1
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :uploads, :store, nil
- end
- end
-end
diff --git a/db/migrate/20200430103158_create_group_wiki_repositories.rb b/db/migrate/20200430103158_create_group_wiki_repositories.rb
deleted file mode 100644
index b84a8a55def..00000000000
--- a/db/migrate/20200430103158_create_group_wiki_repositories.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class CreateGroupWikiRepositories < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :group_wiki_repositories, id: false do |t|
- t.bigint :shard_id, null: false, index: true
- t.bigint :group_id, null: false, index: false, primary_key: true, default: nil
-
- # The limit is added in db/migrate/20200511120430_add_group_wiki_repositories_disk_path_limit.rb
- t.text :disk_path, null: false, index: { unique: true } # rubocop:disable Migration/AddLimitToTextColumns
- end
- end
-end
diff --git a/db/migrate/20200430123614_create_project_access_tokens.rb b/db/migrate/20200430123614_create_project_access_tokens.rb
deleted file mode 100644
index f07b1875ce0..00000000000
--- a/db/migrate/20200430123614_create_project_access_tokens.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class CreateProjectAccessTokens < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :project_access_tokens, primary_key: [:personal_access_token_id, :project_id] do |t|
- t.column :personal_access_token_id, :bigint, null: false
- t.column :project_id, :bigint, null: false
- end
-
- add_index :project_access_tokens, :project_id
- end
-end
diff --git a/db/migrate/20200430130048_create_packages_nuget_metadata.rb b/db/migrate/20200430130048_create_packages_nuget_metadata.rb
deleted file mode 100644
index 0f0d490c93d..00000000000
--- a/db/migrate/20200430130048_create_packages_nuget_metadata.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackagesNugetMetadata < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- LICENSE_URL_CONSTRAINT_NAME = 'packages_nuget_metadata_license_url_constraint'
- PROJECT_URL_CONSTRAINT_NAME = 'packages_nuget_metadata_project_url_constraint'
- ICON_URL_CONSTRAINT_NAME = 'packages_nuget_metadata_icon_url_constraint'
-
- def up
- unless table_exists?(:packages_nuget_metadata)
- with_lock_retries do
- create_table :packages_nuget_metadata, id: false do |t|
- t.references :package, primary_key: true, default: nil, index: false, foreign_key: { to_table: :packages_packages, on_delete: :cascade }, type: :bigint
- t.text :license_url
- t.text :project_url
- t.text :icon_url
- end
- end
- end
-
- add_text_limit :packages_nuget_metadata, :license_url, 255, constraint_name: LICENSE_URL_CONSTRAINT_NAME
- add_text_limit :packages_nuget_metadata, :project_url, 255, constraint_name: PROJECT_URL_CONSTRAINT_NAME
- add_text_limit :packages_nuget_metadata, :icon_url, 255, constraint_name: ICON_URL_CONSTRAINT_NAME
- end
-
- def down
- drop_table :packages_nuget_metadata
- end
-end
diff --git a/db/migrate/20200430174637_create_group_deploy_keys.rb b/db/migrate/20200430174637_create_group_deploy_keys.rb
deleted file mode 100644
index 9771ae013ea..00000000000
--- a/db/migrate/20200430174637_create_group_deploy_keys.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class CreateGroupDeployKeys < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:group_deploy_keys)
- with_lock_retries do
- create_table :group_deploy_keys do |t|
- t.references :user, foreign_key: { on_delete: :restrict }, index: true
- t.timestamps_with_timezone
- t.datetime_with_timezone :last_used_at
- t.datetime_with_timezone :expires_at
- t.text :key, null: false, unique: true
- t.text :title
- t.text :fingerprint, null: false, unique: true
- t.binary :fingerprint_sha256
-
- t.index :fingerprint, unique: true
- t.index :fingerprint_sha256
- end
- end
- end
-
- add_text_limit(:group_deploy_keys, :key, 4096)
- add_text_limit(:group_deploy_keys, :title, 255)
- add_text_limit(:group_deploy_keys, :fingerprint, 255)
- end
-
- def down
- drop_table :group_deploy_keys
- end
-end
diff --git a/db/migrate/20200504191813_add_fingerprint_to_events.rb b/db/migrate/20200504191813_add_fingerprint_to_events.rb
deleted file mode 100644
index 1171d548f10..00000000000
--- a/db/migrate/20200504191813_add_fingerprint_to_events.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class AddFingerprintToEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:events, :fingerprint)
- with_lock_retries { add_column :events, :fingerprint, :binary }
- end
-
- unless check_constraint_exists?(:events, constraint_name)
- add_check_constraint(
- :events,
- "octet_length(fingerprint) <= 128",
- constraint_name,
- validate: true
- )
- end
- end
-
- def down
- remove_check_constraint(:events, constraint_name)
-
- if column_exists?(:events, :fingerprint)
- with_lock_retries { remove_column :events, :fingerprint }
- end
- end
-
- def constraint_name
- check_constraint_name(:events, :fingerprint, 'max_length')
- end
-end
diff --git a/db/migrate/20200504200709_add_index_on_fingerprint_and_target_type_to_events.rb b/db/migrate/20200504200709_add_index_on_fingerprint_and_target_type_to_events.rb
deleted file mode 100644
index 9b06d593300..00000000000
--- a/db/migrate/20200504200709_add_index_on_fingerprint_and_target_type_to_events.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnFingerprintAndTargetTypeToEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- KEYS = [:target_type, :target_id, :fingerprint]
-
- def up
- add_concurrent_index :events, KEYS, using: :btree, unique: true
- end
-
- def down
- remove_concurrent_index :events, KEYS
- end
-end
diff --git a/db/migrate/20200505164958_add_registry_settings_to_application_settings.rb b/db/migrate/20200505164958_add_registry_settings_to_application_settings.rb
deleted file mode 100644
index 4c307dbe845..00000000000
--- a/db/migrate/20200505164958_add_registry_settings_to_application_settings.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class AddRegistrySettingsToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # rubocop:disable Migration/AddLimitToTextColumns
- def up
- add_column_with_default(:application_settings, # rubocop:disable Migration/AddColumnWithDefault
- :container_registry_vendor,
- :text,
- default: '',
- allow_null: false)
-
- add_column_with_default(:application_settings, # rubocop:disable Migration/AddColumnWithDefault
- :container_registry_version,
- :text,
- default: '',
- allow_null: false)
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-
- def down
- remove_column :application_settings, :container_registry_vendor
- remove_column :application_settings, :container_registry_version
- end
-end
diff --git a/db/migrate/20200505171834_add_text_limit_to_container_registry_vendor.rb b/db/migrate/20200505171834_add_text_limit_to_container_registry_vendor.rb
deleted file mode 100644
index 242dcc9a837..00000000000
--- a/db/migrate/20200505171834_add_text_limit_to_container_registry_vendor.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToContainerRegistryVendor < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :application_settings, :container_registry_vendor, 255
- end
-
- def down
- remove_text_limit :application_settings, :container_registry_vendor
- end
-end
diff --git a/db/migrate/20200505172405_add_text_limit_to_container_registry_version.rb b/db/migrate/20200505172405_add_text_limit_to_container_registry_version.rb
deleted file mode 100644
index 36589c9cc75..00000000000
--- a/db/migrate/20200505172405_add_text_limit_to_container_registry_version.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToContainerRegistryVersion < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :application_settings, :container_registry_version, 255
- end
-
- def down
- remove_text_limit :application_settings, :container_registry_version
- end
-end
diff --git a/db/migrate/20200507221434_add_container_registry_features_to_application_settings.rb b/db/migrate/20200507221434_add_container_registry_features_to_application_settings.rb
deleted file mode 100644
index fbbf2306f81..00000000000
--- a/db/migrate/20200507221434_add_container_registry_features_to_application_settings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddContainerRegistryFeaturesToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column :application_settings, :container_registry_features, :text, array: true, default: [], null: false
- end
-
- def down
- remove_column :application_settings, :container_registry_features
- end
-end
diff --git a/db/migrate/20200508021128_remove_ultraauth_provider_from_identities.rb b/db/migrate/20200508021128_remove_ultraauth_provider_from_identities.rb
deleted file mode 100644
index dd3f1dbcc0e..00000000000
--- a/db/migrate/20200508021128_remove_ultraauth_provider_from_identities.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveUltraauthProviderFromIdentities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :identities, :provider
- execute "DELETE FROM identities WHERE provider = 'ultraauth'"
- remove_concurrent_index :identities, :provider
- end
-
- def down
- end
-end
diff --git a/db/migrate/20200508050301_add_spam_check_endpoint_to_application_settings.rb b/db/migrate/20200508050301_add_spam_check_endpoint_to_application_settings.rb
deleted file mode 100644
index d30b8abbbc3..00000000000
--- a/db/migrate/20200508050301_add_spam_check_endpoint_to_application_settings.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-class AddSpamCheckEndpointToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:application_settings, :spam_check_endpoint_url)
- add_column :application_settings, :spam_check_endpoint_url, :text
- end
-
- add_text_limit :application_settings, :spam_check_endpoint_url, 255
-
- unless column_exists?(:application_settings, :spam_check_endpoint_enabled)
- add_column :application_settings, :spam_check_endpoint_enabled, :boolean, null: false, default: false
- end
- end
-
- def down
- remove_column_if_exists :spam_check_endpoint_url
- remove_column_if_exists :spam_check_endpoint_enabled
- end
-
- private
-
- def remove_column_if_exists(column)
- return unless column_exists?(:application_settings, column)
-
- remove_column :application_settings, column
- end
-end
diff --git a/db/migrate/20200508140959_add_elasticsearch_pause_indexing_to_application_settings.rb b/db/migrate/20200508140959_add_elasticsearch_pause_indexing_to_application_settings.rb
deleted file mode 100644
index 5828db973ed..00000000000
--- a/db/migrate/20200508140959_add_elasticsearch_pause_indexing_to_application_settings.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddElasticsearchPauseIndexingToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- add_column :application_settings, :elasticsearch_pause_indexing, :boolean, default: false, null: false
- end
- end
-
- def down
- remove_column :application_settings, :elasticsearch_pause_indexing
- end
-end
diff --git a/db/migrate/20200508203901_add_repository_storages_weighted_to_application_settings.rb b/db/migrate/20200508203901_add_repository_storages_weighted_to_application_settings.rb
deleted file mode 100644
index fecaed9a7a0..00000000000
--- a/db/migrate/20200508203901_add_repository_storages_weighted_to_application_settings.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-class AddRepositoryStoragesWeightedToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- class ApplicationSetting < ActiveRecord::Base
- serialize :repository_storages
- self.table_name = 'application_settings'
- end
-
- def up
- add_column :application_settings, :repository_storages_weighted, :jsonb, default: {}, null: false
-
- seed_repository_storages_weighted
- end
-
- def down
- remove_column :application_settings, :repository_storages_weighted
- end
-
- private
-
- def seed_repository_storages_weighted
- # We need to flush the cache to ensure the newly-added column is loaded
- ApplicationSetting.reset_column_information
-
- # There should only be one row here due to
- # 20200420162730_remove_additional_application_settings_rows.rb
- ApplicationSetting.all.each do |settings|
- storages = Gitlab.config.repositories.storages.keys.collect do |storage|
- weight = settings.repository_storages.include?(storage) ? 100 : 0
- [storage.to_sym, weight]
- end
-
- settings.repository_storages_weighted = Hash[storages]
- settings.save!
- end
- end
-end
diff --git a/db/migrate/20200509203901_reseed_repository_storages_weighted.rb b/db/migrate/20200509203901_reseed_repository_storages_weighted.rb
deleted file mode 100644
index 7a751b77c1c..00000000000
--- a/db/migrate/20200509203901_reseed_repository_storages_weighted.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class ReseedRepositoryStoragesWeighted < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- class ApplicationSetting < ActiveRecord::Base
- serialize :repository_storages
- self.table_name = 'application_settings'
- end
-
- def up
- reseed_repository_storages_weighted
- end
-
- private
-
- def reseed_repository_storages_weighted
- # We need to flush the cache to ensure the newly-added column is loaded
- ApplicationSetting.reset_column_information
-
- # There should only be one row here due to
- # 20200420162730_remove_additional_application_settings_rows.rb
- ApplicationSetting.all.each do |settings|
- # Admins may have already tweaked these values, so don't do anything
- # if there is data already.
- next if settings.repository_storages_weighted.present?
-
- storages = Gitlab.config.repositories.storages.keys.collect do |storage|
- weight = settings.repository_storages.include?(storage) ? 100 : 0
- [storage.to_sym, weight]
- end
-
- settings.repository_storages_weighted = Hash[storages]
- settings.save!
- end
- end
-end
diff --git a/db/migrate/20200510181937_add_web_authn_xid_to_user_details.rb b/db/migrate/20200510181937_add_web_authn_xid_to_user_details.rb
deleted file mode 100644
index d41e6611c45..00000000000
--- a/db/migrate/20200510181937_add_web_authn_xid_to_user_details.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AddWebAuthnXidToUserDetails < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in subsequent migration
- def change
- add_column :user_details, :webauthn_xid, :text
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20200510182218_add_text_limit_to_user_details_webauthn_xid.rb b/db/migrate/20200510182218_add_text_limit_to_user_details_webauthn_xid.rb
deleted file mode 100644
index 715cfd771f5..00000000000
--- a/db/migrate/20200510182218_add_text_limit_to_user_details_webauthn_xid.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToUserDetailsWebauthnXid < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :user_details, :webauthn_xid, 100
- end
-
- def down
- remove_text_limit :user_details, :webauthn_xid
- end
-end
diff --git a/db/migrate/20200510182556_add_text_limit_to_webauthn_registrations_name.rb b/db/migrate/20200510182556_add_text_limit_to_webauthn_registrations_name.rb
deleted file mode 100644
index 28805505ba6..00000000000
--- a/db/migrate/20200510182556_add_text_limit_to_webauthn_registrations_name.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToWebauthnRegistrationsName < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :webauthn_registrations, :name, 255
- end
-
- def down
- remove_text_limit :webauthn_registrations, :name
- end
-end
diff --git a/db/migrate/20200510182824_add_text_limit_to_webauthn_registrations_credential_xid.rb b/db/migrate/20200510182824_add_text_limit_to_webauthn_registrations_credential_xid.rb
deleted file mode 100644
index 51155f370ef..00000000000
--- a/db/migrate/20200510182824_add_text_limit_to_webauthn_registrations_credential_xid.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToWebauthnRegistrationsCredentialXid < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :webauthn_registrations, :credential_xid, 255
- end
-
- def down
- remove_text_limit :webauthn_registrations, :credential_xid
- end
-end
diff --git a/db/migrate/20200510183128_add_foreign_key_from_webauthn_registrations_to_users.rb b/db/migrate/20200510183128_add_foreign_key_from_webauthn_registrations_to_users.rb
deleted file mode 100644
index 9071e3e17e3..00000000000
--- a/db/migrate/20200510183128_add_foreign_key_from_webauthn_registrations_to_users.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyFromWebauthnRegistrationsToUsers < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- # disable_ddl_transaction!
-
- def up
- with_lock_retries do
- add_foreign_key :webauthn_registrations, :users, column: :user_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :webauthn_registrations, column: :user_id
- end
- end
-end
diff --git a/db/migrate/20200511092246_add_epic_id_to_resource_state_events.rb b/db/migrate/20200511092246_add_epic_id_to_resource_state_events.rb
deleted file mode 100644
index 85d965972aa..00000000000
--- a/db/migrate/20200511092246_add_epic_id_to_resource_state_events.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddEpicIdToResourceStateEvents < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- INDEX_NAME = 'index_resource_state_events_on_epic_id'
-
- def up
- add_column :resource_state_events, :epic_id, :integer
- add_index :resource_state_events, :epic_id, name: INDEX_NAME # rubocop:disable Migration/AddIndex
- end
-
- def down
- remove_index :resource_state_events, name: INDEX_NAME # rubocop:disable Migration/RemoveIndex
- remove_column :resource_state_events, :epic_id, :integer
- end
-end
diff --git a/db/migrate/20200511092505_add_foreign_key_to_epic_id_on_resource_state_events.rb b/db/migrate/20200511092505_add_foreign_key_to_epic_id_on_resource_state_events.rb
deleted file mode 100644
index 1daa620501a..00000000000
--- a/db/migrate/20200511092505_add_foreign_key_to_epic_id_on_resource_state_events.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToEpicIdOnResourceStateEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :resource_state_events, :epics, column: :epic_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :resource_state_events, column: :epic_id
- end
- end
-end
diff --git a/db/migrate/20200511115430_add_inherit_from_to_services.rb b/db/migrate/20200511115430_add_inherit_from_to_services.rb
deleted file mode 100644
index c409b543dbf..00000000000
--- a/db/migrate/20200511115430_add_inherit_from_to_services.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddInheritFromToServices < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :services, :inherit_from_id, :bigint
- end
-end
diff --git a/db/migrate/20200511115431_add_index_inherit_from_id_to_services.rb b/db/migrate/20200511115431_add_index_inherit_from_id_to_services.rb
deleted file mode 100644
index a0a5f361edf..00000000000
--- a/db/migrate/20200511115431_add_index_inherit_from_id_to_services.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexInheritFromIdToServices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :services, :inherit_from_id
-
- add_concurrent_foreign_key :services, :services, column: :inherit_from_id, on_delete: :nullify
- end
-
- def down
- remove_foreign_key_if_exists :services, column: :inherit_from_id
-
- remove_concurrent_index :services, :inherit_from_id
- end
-end
diff --git a/db/migrate/20200511121549_add_group_wiki_repositories_shard_id_foreign_key.rb b/db/migrate/20200511121549_add_group_wiki_repositories_shard_id_foreign_key.rb
deleted file mode 100644
index d1bb3fcc6ea..00000000000
--- a/db/migrate/20200511121549_add_group_wiki_repositories_shard_id_foreign_key.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddGroupWikiRepositoriesShardIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :group_wiki_repositories, :shards, on_delete: :restrict
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :group_wiki_repositories, :shards
- end
- end
-end
diff --git a/db/migrate/20200511121610_add_group_wiki_repositories_group_id_foreign_key.rb b/db/migrate/20200511121610_add_group_wiki_repositories_group_id_foreign_key.rb
deleted file mode 100644
index 40f272cc0e7..00000000000
--- a/db/migrate/20200511121610_add_group_wiki_repositories_group_id_foreign_key.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddGroupWikiRepositoriesGroupIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :group_wiki_repositories, :namespaces, column: :group_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :group_wiki_repositories, :namespaces, column: :group_id
- end
- end
-end
diff --git a/db/migrate/20200511121620_add_group_wiki_repositories_disk_path_limit.rb b/db/migrate/20200511121620_add_group_wiki_repositories_disk_path_limit.rb
deleted file mode 100644
index db4b9d8a6e4..00000000000
--- a/db/migrate/20200511121620_add_group_wiki_repositories_disk_path_limit.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddGroupWikiRepositoriesDiskPathLimit < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :group_wiki_repositories, :disk_path, 80
- end
-
- def down
- remove_text_limit :group_wiki_repositories, :disk_path
- end
-end
diff --git a/db/migrate/20200511130129_remove_deprecated_jenkins_service_records.rb b/db/migrate/20200511130129_remove_deprecated_jenkins_service_records.rb
deleted file mode 100644
index 258142f950e..00000000000
--- a/db/migrate/20200511130129_remove_deprecated_jenkins_service_records.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveDeprecatedJenkinsServiceRecords < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute <<~SQL.strip
- DELETE FROM services WHERE type = 'JenkinsDeprecatedService';
- SQL
- end
-
- def down
- # no-op
-
- # The records were removed by `up`
- end
-end
diff --git a/db/migrate/20200511181027_create_test_reports.rb b/db/migrate/20200511181027_create_test_reports.rb
deleted file mode 100644
index a08e208441d..00000000000
--- a/db/migrate/20200511181027_create_test_reports.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class CreateTestReports < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :requirements_management_test_reports do |t|
- t.datetime_with_timezone :created_at, null: false
- t.references :requirement, null: false, foreign_key: { on_delete: :cascade }
- t.bigint :pipeline_id
- t.bigint :author_id
- t.integer :state, null: false, limit: 2
-
- t.index :pipeline_id
- t.index :author_id
- end
- end
-end
diff --git a/db/migrate/20200511191027_add_author_foreign_key_to_test_reports.rb b/db/migrate/20200511191027_add_author_foreign_key_to_test_reports.rb
deleted file mode 100644
index 532133fe7f9..00000000000
--- a/db/migrate/20200511191027_add_author_foreign_key_to_test_reports.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddAuthorForeignKeyToTestReports < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :requirements_management_test_reports, :users, column: :author_id, on_delete: :nullify
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :requirements_management_test_reports, column: :author_id
- end
- end
-end
diff --git a/db/migrate/20200511208012_add_pipeline_foreign_key_to_test_reports.rb b/db/migrate/20200511208012_add_pipeline_foreign_key_to_test_reports.rb
deleted file mode 100644
index 46657f9af6d..00000000000
--- a/db/migrate/20200511208012_add_pipeline_foreign_key_to_test_reports.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddPipelineForeignKeyToTestReports < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :requirements_management_test_reports, :ci_pipelines, column: :pipeline_id, on_delete: :nullify
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :requirements_management_test_reports, column: :pipeline_id
- end
- end
-end
diff --git a/db/migrate/20200512085150_change_default_value_of_protected_ci_variables_of_application_settings_to_true.rb b/db/migrate/20200512085150_change_default_value_of_protected_ci_variables_of_application_settings_to_true.rb
deleted file mode 100644
index ca623ccf8b4..00000000000
--- a/db/migrate/20200512085150_change_default_value_of_protected_ci_variables_of_application_settings_to_true.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeDefaultValueOfProtectedCiVariablesOfApplicationSettingsToTrue < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_column_default :application_settings, :protected_ci_variables, from: false, to: true
- end
-end
diff --git a/db/migrate/20200512160004_add_index_to_ci_job_artifacts_for_terraform_reports.rb b/db/migrate/20200512160004_add_index_to_ci_job_artifacts_for_terraform_reports.rb
deleted file mode 100644
index 20eaa549ee5..00000000000
--- a/db/migrate/20200512160004_add_index_to_ci_job_artifacts_for_terraform_reports.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToCiJobArtifactsForTerraformReports < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_ci_job_artifacts_for_terraform_reports'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_job_artifacts, [:project_id, :id], where: 'file_type = 18', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :ci_job_artifacts, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200512164334_sprint_make_state_enum_not_null_and_default.rb b/db/migrate/20200512164334_sprint_make_state_enum_not_null_and_default.rb
deleted file mode 100644
index f0db228e249..00000000000
--- a/db/migrate/20200512164334_sprint_make_state_enum_not_null_and_default.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class SprintMakeStateEnumNotNullAndDefault < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- change_column_default :sprints, :state_enum, from: 0, to: 1
- change_column_null :sprints, :state_enum, false, 1
- end
-
- def down
- change_column_null :sprints, :state_enum, true
- change_column_default :sprints, :state_enum, from: 1, to: nil
- end
-end
diff --git a/db/migrate/20200512195442_update_index_on_name_type_eq_ci_build_to_ci_builds.rb b/db/migrate/20200512195442_update_index_on_name_type_eq_ci_build_to_ci_builds.rb
deleted file mode 100644
index f1334afb89d..00000000000
--- a/db/migrate/20200512195442_update_index_on_name_type_eq_ci_build_to_ci_builds.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateIndexOnNameTypeEqCiBuildToCiBuilds < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- OLD_INDEX_NAME = 'index_ci_builds_on_name_and_security_type_eq_ci_build'
- NEW_INDEX_NAME = 'index_security_ci_builds_on_name_and_id'
-
- OLD_CLAUSE = "((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text,
- ('dast'::character varying)::text,
- ('dependency_scanning'::character varying)::text,
- ('license_management'::character varying)::text,
- ('sast'::character varying)::text,
- ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text)"
-
- NEW_CLAUSE = "((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text,
- ('dast'::character varying)::text,
- ('dependency_scanning'::character varying)::text,
- ('license_management'::character varying)::text,
- ('sast'::character varying)::text,
- ('secret_detection'::character varying)::text,
- ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text)"
-
- def up
- add_concurrent_index :ci_builds, [:name, :id], name: NEW_INDEX_NAME, where: NEW_CLAUSE
- remove_concurrent_index_by_name :ci_builds, OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :ci_builds, [:name, :id], name: OLD_INDEX_NAME, where: OLD_CLAUSE
- remove_concurrent_index_by_name :ci_builds, NEW_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200513160930_fix_not_null_check_constraint_inconsistency.rb b/db/migrate/20200513160930_fix_not_null_check_constraint_inconsistency.rb
deleted file mode 100644
index a8bb91cf6cf..00000000000
--- a/db/migrate/20200513160930_fix_not_null_check_constraint_inconsistency.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class FixNotNullCheckConstraintInconsistency < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- table = :application_settings
-
- %i(container_registry_vendor container_registry_version).each do |column|
- change_column_null table, column, false
- remove_not_null_constraint(table, column) if check_not_null_constraint_exists?(table, column)
- end
- end
-
- def down
- # No-op: for regular systems without the inconsistency, #up is a no-op, too
- end
-end
diff --git a/db/migrate/20200513224143_add_section_to_approval_merge_request_rule.rb b/db/migrate/20200513224143_add_section_to_approval_merge_request_rule.rb
deleted file mode 100644
index 98424e9b735..00000000000
--- a/db/migrate/20200513224143_add_section_to_approval_merge_request_rule.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddSectionToApprovalMergeRequestRule < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:approval_merge_request_rules, :section)
- add_column :approval_merge_request_rules, :section, :text
- end
-
- add_text_limit :approval_merge_request_rules, :section, 255
- end
-
- def down
- remove_column :approval_merge_request_rules, :section
- end
-end
diff --git a/db/migrate/20200513234502_fill_file_store_lfs_objects.rb b/db/migrate/20200513234502_fill_file_store_lfs_objects.rb
deleted file mode 100644
index 74066afbd83..00000000000
--- a/db/migrate/20200513234502_fill_file_store_lfs_objects.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class FillFileStoreLfsObjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- update_column_in_batches(:lfs_objects, :file_store, 1) do |table, query|
- query.where(table[:file_store].eq(nil))
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200513235347_fill_store_uploads.rb b/db/migrate/20200513235347_fill_store_uploads.rb
deleted file mode 100644
index 42db5e4cc08..00000000000
--- a/db/migrate/20200513235347_fill_store_uploads.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class FillStoreUploads < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- update_column_in_batches(:uploads, :store, 1) do |table, query|
- query.where(table[:store].eq(nil))
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200513235532_fill_file_store_ci_job_artifacts.rb b/db/migrate/20200513235532_fill_file_store_ci_job_artifacts.rb
deleted file mode 100644
index d4c25167535..00000000000
--- a/db/migrate/20200513235532_fill_file_store_ci_job_artifacts.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class FillFileStoreCiJobArtifacts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- # rubocop:disable Migration/UpdateLargeTable
- update_column_in_batches(:ci_job_artifacts, :file_store, 1) do |table, query|
- query.where(table[:file_store].eq(nil))
- end
- # rubocop:enable Migration/UpdateLargeTable
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200515152649_enable_btree_gist_extension.rb b/db/migrate/20200515152649_enable_btree_gist_extension.rb
deleted file mode 100644
index bd81c921a87..00000000000
--- a/db/migrate/20200515152649_enable_btree_gist_extension.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class EnableBtreeGistExtension < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- create_extension :btree_gist
- end
-
- def down
- drop_extension :btree_gist
- end
-end
diff --git a/db/migrate/20200515153633_iteration_date_range_constraint.rb b/db/migrate/20200515153633_iteration_date_range_constraint.rb
deleted file mode 100644
index ab197ff8ae7..00000000000
--- a/db/migrate/20200515153633_iteration_date_range_constraint.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-class IterationDateRangeConstraint < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute <<~SQL
- ALTER TABLE sprints
- ADD CONSTRAINT iteration_start_and_due_daterange_project_id_constraint
- EXCLUDE USING gist
- ( project_id WITH =,
- daterange(start_date, due_date, '[]') WITH &&
- )
- WHERE (project_id IS NOT NULL)
- SQL
-
- execute <<~SQL
- ALTER TABLE sprints
- ADD CONSTRAINT iteration_start_and_due_daterange_group_id_constraint
- EXCLUDE USING gist
- ( group_id WITH =,
- daterange(start_date, due_date, '[]') WITH &&
- )
- WHERE (group_id IS NOT NULL)
- SQL
- end
-
- def down
- execute <<~SQL
- ALTER TABLE sprints
- DROP CONSTRAINT IF EXISTS iteration_start_and_due_daterange_project_id_constraint
- SQL
-
- execute <<~SQL
- ALTER TABLE sprints
- DROP CONSTRAINT IF EXISTS iteration_start_and_due_daterange_group_id_constraint
- SQL
- end
-end
diff --git a/db/migrate/20200515155620_add_index_non_requested_project_members_on_source_id_source_type.rb b/db/migrate/20200515155620_add_index_non_requested_project_members_on_source_id_source_type.rb
deleted file mode 100644
index 333f4e93e95..00000000000
--- a/db/migrate/20200515155620_add_index_non_requested_project_members_on_source_id_source_type.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexNonRequestedProjectMembersOnSourceIdSourceType < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:members, [:source_id, :source_type], where: "requested_at IS NULL and type = 'ProjectMember'", name: 'index_non_requested_project_members_on_source_id_and_type')
- end
-
- def down
- remove_concurrent_index_by_name(:members, 'index_non_requested_project_members_on_source_id_and_type')
- end
-end
diff --git a/db/migrate/20200518091745_add_index_to_personal_access_token_impersonation.rb b/db/migrate/20200518091745_add_index_to_personal_access_token_impersonation.rb
deleted file mode 100644
index f9681f1a976..00000000000
--- a/db/migrate/20200518091745_add_index_to_personal_access_token_impersonation.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToPersonalAccessTokenImpersonation < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_expired_and_not_notified_personal_access_tokens'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(
- :personal_access_tokens,
- [:id, :expires_at],
- where: "impersonation = FALSE AND revoked = FALSE AND expire_notification_delivered = FALSE",
- name: INDEX_NAME
- )
- end
-
- def down
- remove_concurrent_index_by_name(
- :personal_access_tokens,
- name: INDEX_NAME
- )
- end
-end
diff --git a/db/migrate/20200519074709_update_resource_state_events_constraint_to_support_epic_id.rb b/db/migrate/20200519074709_update_resource_state_events_constraint_to_support_epic_id.rb
deleted file mode 100644
index ff60e3bdac1..00000000000
--- a/db/migrate/20200519074709_update_resource_state_events_constraint_to_support_epic_id.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateResourceStateEventsConstraintToSupportEpicId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- OLD_CONSTRAINT = 'resource_state_events_must_belong_to_issue_or_merge_request'
- CONSTRAINT_NAME = 'resource_state_events_must_belong_to_issue_or_merge_request_or_'
-
- def up
- remove_check_constraint :resource_state_events, OLD_CONSTRAINT
- add_check_constraint :resource_state_events, "(issue_id != NULL AND merge_request_id IS NULL AND epic_id IS NULL) OR " \
- "(issue_id IS NULL AND merge_request_id != NULL AND epic_id IS NULL) OR" \
- "(issue_id IS NULL AND merge_request_id IS NULL AND epic_id != NULL)", CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint :resource_state_events, CONSTRAINT_NAME
- add_check_constraint :resource_state_events, '(issue_id != NULL AND merge_request_id IS NULL) OR (merge_request_id != NULL AND issue_id IS NULL)', OLD_CONSTRAINT
- end
-end
diff --git a/db/migrate/20200519101002_add_error_message_column_to_jira_imports.rb b/db/migrate/20200519101002_add_error_message_column_to_jira_imports.rb
deleted file mode 100644
index 478b5358056..00000000000
--- a/db/migrate/20200519101002_add_error_message_column_to_jira_imports.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddErrorMessageColumnToJiraImports < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:jira_imports, :error_message)
- add_column :jira_imports, :error_message, :text
- end
-
- add_text_limit :jira_imports, :error_message, 1000
- end
-
- def down
- return unless column_exists?(:jira_imports, :error_message)
-
- remove_column :jira_imports, :error_message
- end
-end
diff --git a/db/migrate/20200519115908_add_epics_confidential_index.rb b/db/migrate/20200519115908_add_epics_confidential_index.rb
deleted file mode 100644
index 68a1715acb4..00000000000
--- a/db/migrate/20200519115908_add_epics_confidential_index.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddEpicsConfidentialIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :epics, :confidential
- end
-
- def down
- remove_concurrent_index :epics, :confidential
- end
-end
diff --git a/db/migrate/20200519141534_add_instance_level_variables_column_to_plan_limits.rb b/db/migrate/20200519141534_add_instance_level_variables_column_to_plan_limits.rb
deleted file mode 100644
index bf36e74a746..00000000000
--- a/db/migrate/20200519141534_add_instance_level_variables_column_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddInstanceLevelVariablesColumnToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :plan_limits, :ci_instance_level_variables, :integer, default: 25, null: false
- end
-end
diff --git a/db/migrate/20200519194042_update_container_expiration_policies_defaults.rb b/db/migrate/20200519194042_update_container_expiration_policies_defaults.rb
deleted file mode 100644
index 071f50d16a0..00000000000
--- a/db/migrate/20200519194042_update_container_expiration_policies_defaults.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateContainerExpirationPoliciesDefaults < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :container_expiration_policies, :cadence, '1d'
- change_column_default :container_expiration_policies, :keep_n, 10
- change_column_default :container_expiration_policies, :older_than, '90d'
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :container_expiration_policies, :cadence, '7d'
- change_column_default :container_expiration_policies, :keep_n, nil
- change_column_default :container_expiration_policies, :older_than, nil
- end
- end
-end
diff --git a/db/migrate/20200520103514_add_todo_resolved_by_action.rb b/db/migrate/20200520103514_add_todo_resolved_by_action.rb
deleted file mode 100644
index 0aa91091451..00000000000
--- a/db/migrate/20200520103514_add_todo_resolved_by_action.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddTodoResolvedByAction < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :todos, :resolved_by_action, :integer, limit: 2
- end
- end
-
- def down
- with_lock_retries do
- remove_column :todos, :resolved_by_action
- end
- end
-end
diff --git a/db/migrate/20200521022725_add_experience_level_to_user_preferences.rb b/db/migrate/20200521022725_add_experience_level_to_user_preferences.rb
deleted file mode 100644
index e70a13599c3..00000000000
--- a/db/migrate/20200521022725_add_experience_level_to_user_preferences.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddExperienceLevelToUserPreferences < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :user_preferences, :experience_level, :integer, limit: 2
- end
-end
diff --git a/db/migrate/20200521225327_create_alert_management_alert_assignees.rb b/db/migrate/20200521225327_create_alert_management_alert_assignees.rb
deleted file mode 100644
index 99de2646b3d..00000000000
--- a/db/migrate/20200521225327_create_alert_management_alert_assignees.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class CreateAlertManagementAlertAssignees < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- ALERT_INDEX_NAME = 'index_alert_assignees_on_alert_id'
- UNIQUE_INDEX_NAME = 'index_alert_assignees_on_user_id_and_alert_id'
-
- def up
- create_table :alert_management_alert_assignees do |t|
- t.bigint :user_id, null: false
- t.bigint :alert_id, null: false
-
- t.index :alert_id, name: ALERT_INDEX_NAME
- t.index [:user_id, :alert_id], unique: true, name: UNIQUE_INDEX_NAME
- end
- end
-
- def down
- drop_table :alert_management_alert_assignees
- end
-end
diff --git a/db/migrate/20200521225337_add_foreign_key_to_user_id_on_alert_management_alert_assignees.rb b/db/migrate/20200521225337_add_foreign_key_to_user_id_on_alert_management_alert_assignees.rb
deleted file mode 100644
index 4a6a25a8472..00000000000
--- a/db/migrate/20200521225337_add_foreign_key_to_user_id_on_alert_management_alert_assignees.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToUserIdOnAlertManagementAlertAssignees < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :alert_management_alert_assignees, :users, column: :user_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :alert_management_alert_assignees, column: :user_id
- end
- end
-end
diff --git a/db/migrate/20200521225346_add_foreign_key_to_alert_id_on_alert_mangagement_alert_assignees.rb b/db/migrate/20200521225346_add_foreign_key_to_alert_id_on_alert_mangagement_alert_assignees.rb
deleted file mode 100644
index 77d374f08fa..00000000000
--- a/db/migrate/20200521225346_add_foreign_key_to_alert_id_on_alert_mangagement_alert_assignees.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToAlertIdOnAlertMangagementAlertAssignees < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :alert_management_alert_assignees, :alert_management_alerts, column: :alert_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :alert_management_alert_assignees, column: :alert_id
- end
- end
-end
diff --git a/db/migrate/20200522205606_create_group_deploy_keys_group.rb b/db/migrate/20200522205606_create_group_deploy_keys_group.rb
deleted file mode 100644
index 85dbc14b0f5..00000000000
--- a/db/migrate/20200522205606_create_group_deploy_keys_group.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class CreateGroupDeployKeysGroup < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :group_deploy_keys_groups do |t|
- t.timestamps_with_timezone
-
- t.references :group, index: false, null: false, foreign_key: { to_table: :namespaces, on_delete: :cascade }
- t.references :group_deploy_key, null: false, foreign_key: { on_delete: :cascade }
-
- t.index [:group_id, :group_deploy_key_id], unique: true, name: 'index_group_deploy_keys_group_on_group_deploy_key_and_group_ids'
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :group_deploy_keys_groups
- end
- end
-end
diff --git a/db/migrate/20200522235146_add_index_on_snippet_type_and_id.rb b/db/migrate/20200522235146_add_index_on_snippet_type_and_id.rb
deleted file mode 100644
index 0949e8049d1..00000000000
--- a/db/migrate/20200522235146_add_index_on_snippet_type_and_id.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnSnippetTypeAndId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :snippets, [:id, :type]
- end
-
- def down
- remove_concurrent_index :snippets, [:id, :type]
- end
-end
diff --git a/db/migrate/20200524104346_add_source_to_resource_state_event.rb b/db/migrate/20200524104346_add_source_to_resource_state_event.rb
deleted file mode 100644
index a1d1575bb02..00000000000
--- a/db/migrate/20200524104346_add_source_to_resource_state_event.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddSourceToResourceStateEvent < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:resource_state_events, :source_commit)
- add_column :resource_state_events, :source_commit, :text
- end
-
- add_text_limit :resource_state_events, :source_commit, 40
- end
-
- def down
- remove_column :resource_state_events, :source_commit
- end
-end
diff --git a/db/migrate/20200525114553_rename_user_type_index.rb b/db/migrate/20200525114553_rename_user_type_index.rb
deleted file mode 100644
index 44ce142ffcb..00000000000
--- a/db/migrate/20200525114553_rename_user_type_index.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RenameUserTypeIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :users, [:state, :user_type], name: 'index_users_on_state_and_user_type'
- remove_concurrent_index_by_name :users, 'index_users_on_state_and_user_type_internal'
- end
-
- def down
- add_concurrent_index :users, [:state, :user_type], where: 'ghost IS NOT TRUE', name: 'index_users_on_state_and_user_type_internal'
- remove_concurrent_index_by_name :users, 'index_users_on_state_and_user_type'
- end
-end
diff --git a/db/migrate/20200526013844_add_alert_events_to_services.rb b/db/migrate/20200526013844_add_alert_events_to_services.rb
deleted file mode 100644
index 1dba7fcaad4..00000000000
--- a/db/migrate/20200526013844_add_alert_events_to_services.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddAlertEventsToServices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :services, :alert_events, :boolean
- end
- end
-
- def down
- with_lock_retries do
- remove_column :services, :alert_events
- end
- end
-end
diff --git a/db/migrate/20200526120714_change_partial_indexes_on_services.rb b/db/migrate/20200526120714_change_partial_indexes_on_services.rb
deleted file mode 100644
index a4d58cda105..00000000000
--- a/db/migrate/20200526120714_change_partial_indexes_on_services.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class ChangePartialIndexesOnServices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :services, [:type, :instance], unique: true, where: 'instance = true', name: 'index_services_on_type_and_instance_partial'
- remove_concurrent_index_by_name :services, 'index_services_on_type_and_instance'
-
- add_concurrent_index :services, [:type, :template], unique: true, where: 'template = true', name: 'index_services_on_type_and_template_partial'
- remove_concurrent_index_by_name :services, 'index_services_on_type_and_template'
- end
-
- def down
- add_concurrent_index :services, [:type, :instance], unique: true, where: 'instance IS TRUE', name: 'index_services_on_type_and_instance'
- remove_concurrent_index_by_name :services, 'index_services_on_type_and_instance_partial'
-
- add_concurrent_index :services, [:type, :template], unique: true, where: 'template IS TRUE', name: 'index_services_on_type_and_template'
- remove_concurrent_index_by_name :services, 'index_services_on_type_and_template_partial'
- end
-end
diff --git a/db/migrate/20200526142550_drop_null_constraint_on_group_import_state_jid.rb b/db/migrate/20200526142550_drop_null_constraint_on_group_import_state_jid.rb
deleted file mode 100644
index d0dfa126455..00000000000
--- a/db/migrate/20200526142550_drop_null_constraint_on_group_import_state_jid.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class DropNullConstraintOnGroupImportStateJid < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- change_column_null :group_import_states, :jid, true
- end
-
- def down
- # No-op -- null values could have been added after this this constraint was removed.
- end
-end
diff --git a/db/migrate/20200526153844_add_issues_last_edited_by_id_index.rb b/db/migrate/20200526153844_add_issues_last_edited_by_id_index.rb
deleted file mode 100644
index 85f121a4c02..00000000000
--- a/db/migrate/20200526153844_add_issues_last_edited_by_id_index.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIssuesLastEditedByIdIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :issues, :last_edited_by_id
- add_concurrent_index :epics, :last_edited_by_id
- end
-
- def down
- remove_concurrent_index :issues, :last_edited_by_id
- remove_concurrent_index :epics, :last_edited_by_id
- end
-end
diff --git a/db/migrate/20200526164946_create_operations_feature_flags_issues.rb b/db/migrate/20200526164946_create_operations_feature_flags_issues.rb
deleted file mode 100644
index 24876997cfd..00000000000
--- a/db/migrate/20200526164946_create_operations_feature_flags_issues.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class CreateOperationsFeatureFlagsIssues < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :operations_feature_flags_issues do |t|
- t.references :feature_flag, index: false, foreign_key: { on_delete: :cascade, to_table: :operations_feature_flags }, null: false
- t.bigint :issue_id, null: false
-
- t.index [:feature_flag_id, :issue_id], unique: true, name: :index_ops_feature_flags_issues_on_feature_flag_id_and_issue_id
- t.index :issue_id
- end
- end
-end
diff --git a/db/migrate/20200526164947_add_foreign_key_to_ops_feature_flags_issues.rb b/db/migrate/20200526164947_add_foreign_key_to_ops_feature_flags_issues.rb
deleted file mode 100644
index a11a8094823..00000000000
--- a/db/migrate/20200526164947_add_foreign_key_to_ops_feature_flags_issues.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToOpsFeatureFlagsIssues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :operations_feature_flags_issues, :issues, column: :issue_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :operations_feature_flags_issues, column: :issue_id
- end
- end
-end
diff --git a/db/migrate/20200526193555_add_squash_option_to_project.rb b/db/migrate/20200526193555_add_squash_option_to_project.rb
deleted file mode 100644
index 6dd4e1c7c8e..00000000000
--- a/db/migrate/20200526193555_add_squash_option_to_project.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddSquashOptionToProject < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :project_settings, :squash_option, :integer, default: 3, limit: 2
- end
-end
diff --git a/db/migrate/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type.rb b/db/migrate/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type.rb
deleted file mode 100644
index 2483ff7f8fa..00000000000
--- a/db/migrate/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type.rb
+++ /dev/null
@@ -1,116 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateIndexApprovalRuleNameForCodeOwnersRuleType < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- LEGACY_INDEX_NAME_RULE_TYPE = "index_approval_rule_name_for_code_owners_rule_type"
- LEGACY_INDEX_NAME_CODE_OWNERS = "approval_rule_name_index_for_code_owners"
-
- SECTIONAL_INDEX_NAME = "index_approval_rule_name_for_sectional_code_owners_rule_type"
-
- CODE_OWNER_RULE_TYPE = 2
-
- def up
- unless index_exists_by_name?(:approval_merge_request_rules, SECTIONAL_INDEX_NAME)
- # Ensure only 1 code_owner rule with the same name and section per merge_request
- #
- add_concurrent_index(
- :approval_merge_request_rules,
- [:merge_request_id, :name, :section],
- unique: true,
- where: "rule_type = #{CODE_OWNER_RULE_TYPE}",
- name: SECTIONAL_INDEX_NAME
- )
- end
-
- remove_concurrent_index_by_name :approval_merge_request_rules, LEGACY_INDEX_NAME_RULE_TYPE
- remove_concurrent_index_by_name :approval_merge_request_rules, LEGACY_INDEX_NAME_CODE_OWNERS
-
- add_concurrent_index(
- :approval_merge_request_rules,
- [:merge_request_id, :name],
- unique: true,
- where: "rule_type = #{CODE_OWNER_RULE_TYPE} AND section IS NULL",
- name: LEGACY_INDEX_NAME_RULE_TYPE
- )
-
- add_concurrent_index(
- :approval_merge_request_rules,
- [:merge_request_id, :code_owner, :name],
- unique: true,
- where: "code_owner = true AND section IS NULL",
- name: LEGACY_INDEX_NAME_CODE_OWNERS
- )
- end
-
- def down
- # In a rollback situation, we can't guarantee that there will not be
- # records that were allowed under the more specific SECTIONAL_INDEX_NAME
- # index but would cause uniqueness violations under both the
- # LEGACY_INDEX_NAME_RULE_TYPE and LEGACY_INDEX_NAME_CODE_OWNERS indices.
- # Therefore, we need to first find all the MergeRequests with
- # ApprovalMergeRequestRules that would violate these "new" indices and
- # delete those approval rules, then create the new index, then finally
- # recreate the approval rules for those merge requests.
- #
-
- # First, find all MergeRequests with ApprovalMergeRequestRules that will
- # violate the new index.
- #
- if Gitlab.ee?
- merge_request_ids = ApprovalMergeRequestRule
- .select(:merge_request_id)
- .where(rule_type: CODE_OWNER_RULE_TYPE)
- .group(:merge_request_id, :rule_type, :name)
- .includes(:merge_request)
- .having("count(*) > 1")
- .collect(&:merge_request_id)
-
- # Delete ALL their code_owner approval rules
- #
- merge_request_ids.each_slice(10) do |ids|
- ApprovalMergeRequestRule.where(merge_request_id: ids).code_owner.delete_all
- end
- end
-
- # Remove legacy partial indices that only apply to `section IS NULL` records
- #
- remove_concurrent_index_by_name :approval_merge_request_rules, LEGACY_INDEX_NAME_RULE_TYPE
- remove_concurrent_index_by_name :approval_merge_request_rules, LEGACY_INDEX_NAME_CODE_OWNERS
-
- # Reconstruct original "legacy" indices
- #
- add_concurrent_index(
- :approval_merge_request_rules,
- [:merge_request_id, :name],
- unique: true,
- where: "rule_type = #{CODE_OWNER_RULE_TYPE}",
- name: LEGACY_INDEX_NAME_RULE_TYPE
- )
-
- add_concurrent_index(
- :approval_merge_request_rules,
- [:merge_request_id, :code_owner, :name],
- unique: true,
- where: "code_owner = true",
- name: LEGACY_INDEX_NAME_CODE_OWNERS
- )
-
- # MergeRequest::SyncCodeOwnerApprovalRules recreates the code_owner rules
- # from scratch, adding them to the index. Duplicates will be rejected.
- #
- if Gitlab.ee?
- merge_request_ids.each_slice(10) do |ids|
- MergeRequest.where(id: ids).each do |merge_request|
- MergeRequests::SyncCodeOwnerApprovalRules.new(merge_request).execute
- end
- end
- end
-
- remove_concurrent_index_by_name :approval_merge_request_rules, SECTIONAL_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200527092027_add_link_type_to_release_links.rb b/db/migrate/20200527092027_add_link_type_to_release_links.rb
deleted file mode 100644
index 5088775f665..00000000000
--- a/db/migrate/20200527092027_add_link_type_to_release_links.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddLinkTypeToReleaseLinks < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :release_links, :link_type, :integer, limit: 2, default: 0
- end
- end
-
- def down
- with_lock_retries do
- remove_column :release_links, :link_type
- end
- end
-end
diff --git a/db/migrate/20200527135313_add_requirements_build_reference.rb b/db/migrate/20200527135313_add_requirements_build_reference.rb
deleted file mode 100644
index b492871a19b..00000000000
--- a/db/migrate/20200527135313_add_requirements_build_reference.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class AddRequirementsBuildReference < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_requirements_management_test_reports_on_build_id'
-
- def up
- add_column :requirements_management_test_reports, :build_id, :bigint
- add_index :requirements_management_test_reports, :build_id, name: INDEX_NAME # rubocop:disable Migration/AddIndex
-
- with_lock_retries do
- add_foreign_key :requirements_management_test_reports, :ci_builds, column: :build_id, on_delete: :nullify
- end
- end
-
- def down
- with_lock_retries do
- remove_column :requirements_management_test_reports, :build_id
- end
- end
-end
diff --git a/db/migrate/20200527151413_create_ci_build_report_results_table.rb b/db/migrate/20200527151413_create_ci_build_report_results_table.rb
deleted file mode 100644
index 7f854dd4891..00000000000
--- a/db/migrate/20200527151413_create_ci_build_report_results_table.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCiBuildReportResultsTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :ci_build_report_results, id: false do |t|
- t.bigint :build_id, null: false, index: false, primary_key: true
- t.bigint :project_id, null: false, index: true
- t.jsonb :data, null: false, default: {}
- end
- end
-end
diff --git a/db/migrate/20200527152116_add_foreign_key_to_build_id_on_build_report_results.rb b/db/migrate/20200527152116_add_foreign_key_to_build_id_on_build_report_results.rb
deleted file mode 100644
index 1809fed551a..00000000000
--- a/db/migrate/20200527152116_add_foreign_key_to_build_id_on_build_report_results.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToBuildIdOnBuildReportResults < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :ci_build_report_results, :ci_builds, column: :build_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :ci_build_report_results, column: :build_id
- end
- end
-end
diff --git a/db/migrate/20200527152657_add_foreign_key_to_project_id_on_build_report_results.rb b/db/migrate/20200527152657_add_foreign_key_to_project_id_on_build_report_results.rb
deleted file mode 100644
index 1857cb07b06..00000000000
--- a/db/migrate/20200527152657_add_foreign_key_to_project_id_on_build_report_results.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToProjectIdOnBuildReportResults < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :ci_build_report_results, :projects, column: :project_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :ci_build_report_results, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20200527170649_create_alert_management_alert_user_mentions.rb b/db/migrate/20200527170649_create_alert_management_alert_user_mentions.rb
deleted file mode 100644
index 15e4ab2a357..00000000000
--- a/db/migrate/20200527170649_create_alert_management_alert_user_mentions.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class CreateAlertManagementAlertUserMentions < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :alert_management_alert_user_mentions do |t|
- t.references :alert_management_alert, type: :bigint, index: false, null: false, foreign_key: { on_delete: :cascade }
- t.bigint :note_id, null: true
-
- t.integer :mentioned_users_ids, array: true
- t.integer :mentioned_projects_ids, array: true
- t.integer :mentioned_groups_ids, array: true
- end
-
- add_index :alert_management_alert_user_mentions, [:note_id], where: 'note_id IS NOT NULL', unique: true, name: 'index_alert_user_mentions_on_note_id'
- add_index :alert_management_alert_user_mentions, [:alert_management_alert_id], where: 'note_id IS NULL', unique: true, name: 'index_alert_user_mentions_on_alert_id'
- add_index :alert_management_alert_user_mentions, [:alert_management_alert_id, :note_id], unique: true, name: 'index_alert_user_mentions_on_alert_id_and_note_id'
- end
-end
diff --git a/db/migrate/20200527211000_add_max_import_size.rb b/db/migrate/20200527211000_add_max_import_size.rb
deleted file mode 100644
index 2779997dbb2..00000000000
--- a/db/migrate/20200527211000_add_max_import_size.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class AddMaxImportSize < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- add_column(:application_settings, :max_import_size, :integer, default: 50, null: false)
- end
-
- def down
- remove_column(:application_settings, :max_import_size)
- end
-end
diff --git a/db/migrate/20200527211605_add_locked_to_ci_pipelines.rb b/db/migrate/20200527211605_add_locked_to_ci_pipelines.rb
deleted file mode 100644
index 3587e6c4a08..00000000000
--- a/db/migrate/20200527211605_add_locked_to_ci_pipelines.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddLockedToCiPipelines < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :ci_pipelines, :locked, :integer, limit: 2, null: false, default: 0
- end
- end
-
- def down
- with_lock_retries do
- remove_column :ci_pipelines, :locked
- end
- end
-end
diff --git a/db/migrate/20200528054112_add_index_to_package_name.rb b/db/migrate/20200528054112_add_index_to_package_name.rb
deleted file mode 100644
index fa12088741d..00000000000
--- a/db/migrate/20200528054112_add_index_to_package_name.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToPackageName < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'package_name_index'
-
- def up
- add_concurrent_index(:packages_packages, :name, name: INDEX_NAME)
- end
-
- def down
- remove_concurrent_index(:packages_packages, :name, name: INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200528125905_add_project_id_user_id_status_ref_index_to_ci_pipelines.rb b/db/migrate/20200528125905_add_project_id_user_id_status_ref_index_to_ci_pipelines.rb
deleted file mode 100644
index 7211490e337..00000000000
--- a/db/migrate/20200528125905_add_project_id_user_id_status_ref_index_to_ci_pipelines.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectIdUserIdStatusRefIndexToCiPipelines < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- SOURCE_PARENT_PIPELINE = 12
-
- def up
- add_concurrent_index(
- :ci_pipelines,
- [:project_id, :user_id, :status, :ref],
- where: "source != #{SOURCE_PARENT_PIPELINE}"
- )
- end
-
- def down
- remove_concurrent_index(
- :ci_pipelines,
- [:project_id, :user_id, :status, :ref],
- where: "source != #{SOURCE_PARENT_PIPELINE}"
- )
- end
-end
diff --git a/db/migrate/20200528171933_remove_not_null_from_external_dashboard_url.rb b/db/migrate/20200528171933_remove_not_null_from_external_dashboard_url.rb
deleted file mode 100644
index d146c8b487b..00000000000
--- a/db/migrate/20200528171933_remove_not_null_from_external_dashboard_url.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class RemoveNotNullFromExternalDashboardUrl < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_column_null :project_metrics_settings, :external_dashboard_url, true
- end
-end
diff --git a/db/migrate/20200601210148_add_dashboard_timezone_to_project_metrics_setting.rb b/db/migrate/20200601210148_add_dashboard_timezone_to_project_metrics_setting.rb
deleted file mode 100644
index 3f74ef28621..00000000000
--- a/db/migrate/20200601210148_add_dashboard_timezone_to_project_metrics_setting.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddDashboardTimezoneToProjectMetricsSetting < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :project_metrics_settings, :dashboard_timezone, :integer, limit: 2, null: false, default: 0
- end
-end
diff --git a/db/migrate/20200603073101_change_constraint_name_on_resource_state_events.rb b/db/migrate/20200603073101_change_constraint_name_on_resource_state_events.rb
deleted file mode 100644
index d37027bf2fb..00000000000
--- a/db/migrate/20200603073101_change_constraint_name_on_resource_state_events.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeConstraintNameOnResourceStateEvents < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- NEW_CONSTRAINT_NAME = 'state_events_must_belong_to_issue_or_merge_request_or_epic'
- OLD_CONSTRAINT_NAME = 'resource_state_events_must_belong_to_issue_or_merge_request_or_'
-
- def up
- execute "ALTER TABLE resource_state_events RENAME CONSTRAINT #{OLD_CONSTRAINT_NAME} TO #{NEW_CONSTRAINT_NAME};"
- end
-
- def down
- execute "ALTER TABLE resource_state_events RENAME CONSTRAINT #{NEW_CONSTRAINT_NAME} TO #{OLD_CONSTRAINT_NAME};"
- end
-end
diff --git a/db/migrate/20200603180338_add_enforce_pat_expiration_to_application_settings.rb b/db/migrate/20200603180338_add_enforce_pat_expiration_to_application_settings.rb
deleted file mode 100644
index ca0abc70b64..00000000000
--- a/db/migrate/20200603180338_add_enforce_pat_expiration_to_application_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddEnforcePatExpirationToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :enforce_pat_expiration, :boolean, default: true, null: false
- end
-end
diff --git a/db/migrate/20200604001128_add_secrets_to_ci_builds_metadata.rb b/db/migrate/20200604001128_add_secrets_to_ci_builds_metadata.rb
deleted file mode 100644
index 9a67993cf5c..00000000000
--- a/db/migrate/20200604001128_add_secrets_to_ci_builds_metadata.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddSecretsToCiBuildsMetadata < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :ci_builds_metadata, :secrets, :jsonb, default: {}, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :ci_builds_metadata, :secrets
- end
- end
-end
diff --git a/db/migrate/20200604143628_create_project_security_settings.rb b/db/migrate/20200604143628_create_project_security_settings.rb
deleted file mode 100644
index f972cb509a7..00000000000
--- a/db/migrate/20200604143628_create_project_security_settings.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class CreateProjectSecuritySettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :project_security_settings, id: false do |t|
- t.references :project, primary_key: true, index: false, foreign_key: { on_delete: :cascade }
- t.timestamps_with_timezone
-
- t.boolean :auto_fix_container_scanning, default: true, null: false
- t.boolean :auto_fix_dast, default: true, null: false
- t.boolean :auto_fix_dependency_scanning, default: true, null: false
- t.boolean :auto_fix_sast, default: true, null: false
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :project_security_settings
- end
- end
-end
diff --git a/db/migrate/20200604145731_create_board_user_preferences.rb b/db/migrate/20200604145731_create_board_user_preferences.rb
deleted file mode 100644
index e83f467d690..00000000000
--- a/db/migrate/20200604145731_create_board_user_preferences.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class CreateBoardUserPreferences < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- create_table :board_user_preferences do |t|
- t.bigint :user_id, null: false, index: true
- t.bigint :board_id, null: false, index: true
- t.boolean :hide_labels
- t.timestamps_with_timezone null: false
- end
-
- add_index :board_user_preferences, [:user_id, :board_id], unique: true
- end
-
- def down
- drop_table :board_user_preferences
- end
-end
diff --git a/db/migrate/20200604174544_add_users_foreign_key_to_board_user_preferences.rb b/db/migrate/20200604174544_add_users_foreign_key_to_board_user_preferences.rb
deleted file mode 100644
index cc613e0261e..00000000000
--- a/db/migrate/20200604174544_add_users_foreign_key_to_board_user_preferences.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddUsersForeignKeyToBoardUserPreferences < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :board_user_preferences, :users, column: :user_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :board_user_preferences, column: :user_id
- end
- end
-end
diff --git a/db/migrate/20200604174558_add_boards_foreign_key_to_board_user_preferences.rb b/db/migrate/20200604174558_add_boards_foreign_key_to_board_user_preferences.rb
deleted file mode 100644
index 4ac978d3741..00000000000
--- a/db/migrate/20200604174558_add_boards_foreign_key_to_board_user_preferences.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddBoardsForeignKeyToBoardUserPreferences < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :board_user_preferences, :boards, column: :board_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :board_user_preferences, column: :board_id
- end
- end
-end
diff --git a/db/migrate/20200605003204_add_foreign_key_to_alert_management_alert_user_mentions.rb b/db/migrate/20200605003204_add_foreign_key_to_alert_management_alert_user_mentions.rb
deleted file mode 100644
index 3198544d3a9..00000000000
--- a/db/migrate/20200605003204_add_foreign_key_to_alert_management_alert_user_mentions.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToAlertManagementAlertUserMentions < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :alert_management_alert_user_mentions, :notes, column: :note_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :alert_management_alert_user_mentions, column: :note_id
- end
- end
-end
diff --git a/db/migrate/20200605093113_add_ip_address_to_audit_events.rb b/db/migrate/20200605093113_add_ip_address_to_audit_events.rb
deleted file mode 100644
index 9f5694ddce2..00000000000
--- a/db/migrate/20200605093113_add_ip_address_to_audit_events.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddIpAddressToAuditEvents < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :audit_events, :ip_address, :inet
- end
-end
diff --git a/db/migrate/20200605160806_add_index_on_repository_size_and_project_id_to_project_statistics.rb b/db/migrate/20200605160806_add_index_on_repository_size_and_project_id_to_project_statistics.rb
deleted file mode 100644
index 2e7b75bcd17..00000000000
--- a/db/migrate/20200605160806_add_index_on_repository_size_and_project_id_to_project_statistics.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnRepositorySizeAndProjectIdToProjectStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :project_statistics, [:repository_size, :project_id]
- end
-
- def down
- remove_concurrent_index :project_statistics, [:repository_size, :project_id]
- end
-end
diff --git a/db/migrate/20200605160836_add_index_on_storage_size_and_project_id_to_project_statistics.rb b/db/migrate/20200605160836_add_index_on_storage_size_and_project_id_to_project_statistics.rb
deleted file mode 100644
index 22f9dab634b..00000000000
--- a/db/migrate/20200605160836_add_index_on_storage_size_and_project_id_to_project_statistics.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnStorageSizeAndProjectIdToProjectStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :project_statistics, [:storage_size, :project_id]
- end
-
- def down
- remove_concurrent_index :project_statistics, [:storage_size, :project_id]
- end
-end
diff --git a/db/migrate/20200605160851_add_index_on_wiki_size_and_project_id_to_project_statistics.rb b/db/migrate/20200605160851_add_index_on_wiki_size_and_project_id_to_project_statistics.rb
deleted file mode 100644
index d32994afbfc..00000000000
--- a/db/migrate/20200605160851_add_index_on_wiki_size_and_project_id_to_project_statistics.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnWikiSizeAndProjectIdToProjectStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :project_statistics, [:wiki_size, :project_id]
- end
-
- def down
- remove_concurrent_index :project_statistics, [:wiki_size, :project_id]
- end
-end
diff --git a/db/migrate/20200607223047_create_cluster_agents.rb b/db/migrate/20200607223047_create_cluster_agents.rb
deleted file mode 100644
index 50dd28562e4..00000000000
--- a/db/migrate/20200607223047_create_cluster_agents.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class CreateClusterAgents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:cluster_agents)
- with_lock_retries do
- create_table :cluster_agents do |t|
- t.timestamps_with_timezone null: false
- t.belongs_to(:project, null: false, index: true, foreign_key: { on_delete: :cascade })
- t.text :name, null: false
-
- t.index [:project_id, :name], unique: true
- end
- end
- end
-
- add_text_limit :cluster_agents, :name, 255
- end
-
- def down
- with_lock_retries do
- drop_table :cluster_agents
- end
- end
-end
diff --git a/db/migrate/20200607235435_create_cluster_agent_tokens.rb b/db/migrate/20200607235435_create_cluster_agent_tokens.rb
deleted file mode 100644
index 30c3ad30fa5..00000000000
--- a/db/migrate/20200607235435_create_cluster_agent_tokens.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class CreateClusterAgentTokens < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:cluster_agent_tokens)
- create_table :cluster_agent_tokens do |t|
- t.timestamps_with_timezone null: false
- t.belongs_to :agent, null: false, index: true, foreign_key: { to_table: :cluster_agents, on_delete: :cascade }
- t.text :token_encrypted, null: false
-
- t.index :token_encrypted, unique: true
- end
- end
-
- add_text_limit :cluster_agent_tokens, :token_encrypted, 255
- end
-
- def down
- drop_table :cluster_agent_tokens
- end
-end
diff --git a/db/migrate/20200608214008_change_column_default_project_incident_management_settings.rb b/db/migrate/20200608214008_change_column_default_project_incident_management_settings.rb
deleted file mode 100644
index 1bfafb410c0..00000000000
--- a/db/migrate/20200608214008_change_column_default_project_incident_management_settings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeColumnDefaultProjectIncidentManagementSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- change_column_default(:project_incident_management_settings, :create_issue, from: true, to: false)
- end
-
- def down
- change_column_default(:project_incident_management_settings, :create_issue, from: false, to: true)
- end
-end
diff --git a/db/migrate/20200609012539_add_traversal_ids_to_namespaces.rb b/db/migrate/20200609012539_add_traversal_ids_to_namespaces.rb
deleted file mode 100644
index 3041d7a8e58..00000000000
--- a/db/migrate/20200609012539_add_traversal_ids_to_namespaces.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddTraversalIdsToNamespaces < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :namespaces, :traversal_ids, :integer, array: true, default: [], null: false # rubocop:disable Migration/AddColumnsToWideTables
- end
- end
-
- def down
- with_lock_retries do
- remove_column :namespaces, :traversal_ids
- end
- end
-end
diff --git a/db/migrate/20200609142506_remove_not_null_constraint_from_weight_events_table.rb b/db/migrate/20200609142506_remove_not_null_constraint_from_weight_events_table.rb
deleted file mode 100644
index af4d4dbbf42..00000000000
--- a/db/migrate/20200609142506_remove_not_null_constraint_from_weight_events_table.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveNotNullConstraintFromWeightEventsTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_column_null :resource_weight_events, :user_id, true
- end
-end
diff --git a/db/migrate/20200609142507_remove_not_null_constraint_from_milestone_events_table.rb b/db/migrate/20200609142507_remove_not_null_constraint_from_milestone_events_table.rb
deleted file mode 100644
index 41204afb014..00000000000
--- a/db/migrate/20200609142507_remove_not_null_constraint_from_milestone_events_table.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveNotNullConstraintFromMilestoneEventsTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_column_null :resource_milestone_events, :user_id, true
- end
-end
diff --git a/db/migrate/20200609142508_remove_not_null_constraint_from_state_events_table.rb b/db/migrate/20200609142508_remove_not_null_constraint_from_state_events_table.rb
deleted file mode 100644
index ffa047a78f9..00000000000
--- a/db/migrate/20200609142508_remove_not_null_constraint_from_state_events_table.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveNotNullConstraintFromStateEventsTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_column_null :resource_state_events, :user_id, true
- end
-end
diff --git a/db/migrate/20200609212701_add_incident_settings_to_all_existing_projects.rb b/db/migrate/20200609212701_add_incident_settings_to_all_existing_projects.rb
deleted file mode 100644
index a2931824ef5..00000000000
--- a/db/migrate/20200609212701_add_incident_settings_to_all_existing_projects.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-class AddIncidentSettingsToAllExistingProjects < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- # Add records to projects project_incident_management_settings
- # to preserve behavior for existing projects that
- # are using the create issue functionality with the default setting of true
- query = <<-SQL
- WITH project_ids AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported}(
- SELECT DISTINCT issues.project_id AS id
- FROM issues
- LEFT OUTER JOIN project_incident_management_settings
- ON project_incident_management_settings.project_id = issues.project_id
- INNER JOIN label_links
- ON label_links.target_type = 'Issue'
- AND label_links.target_id = issues.id
- INNER JOIN labels
- ON labels.id = label_links.label_id
- WHERE ( project_incident_management_settings.project_id IS NULL )
- -- Use incident labels even though they could be manually added by users who
- -- are not using alert funtionality.
- AND labels.title = 'incident'
- AND labels.color = '#CC0033'
- AND labels.description = 'Denotes a disruption to IT services and the associated issues require immediate attention'
- )
- INSERT INTO project_incident_management_settings (project_id, create_issue, send_email, issue_template_key)
- SELECT project_ids.id, TRUE, FALSE, NULL
- FROM project_ids
- ON CONFLICT (project_id) DO NOTHING;
- SQL
-
- execute(query)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200610033228_create_terraform_state_versions.rb b/db/migrate/20200610033228_create_terraform_state_versions.rb
deleted file mode 100644
index 10e9faa56ab..00000000000
--- a/db/migrate/20200610033228_create_terraform_state_versions.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class CreateTerraformStateVersions < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :terraform_state_versions, if_not_exists: true do |t|
- t.references :terraform_state, index: false, null: false, foreign_key: { on_delete: :cascade }
- t.references :created_by_user, foreign_key: false
- t.timestamps_with_timezone null: false
- t.integer :version, null: false
- t.integer :file_store, limit: 2, null: false
- t.text :file, null: false
-
- t.index [:terraform_state_id, :version], unique: true, name: 'index_terraform_state_versions_on_state_id_and_version'
- end
-
- add_text_limit :terraform_state_versions, :file, 255
- end
-
- def down
- drop_table :terraform_state_versions
- end
-end
diff --git a/db/migrate/20200610040615_add_versioning_enabled_to_terraform_states.rb b/db/migrate/20200610040615_add_versioning_enabled_to_terraform_states.rb
deleted file mode 100644
index 51a9fd3908b..00000000000
--- a/db/migrate/20200610040615_add_versioning_enabled_to_terraform_states.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddVersioningEnabledToTerraformStates < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :terraform_states, :versioning_enabled, :boolean, null: false, default: false
- end
-end
diff --git a/db/migrate/20200610130002_create_vulnerability_statistics.rb b/db/migrate/20200610130002_create_vulnerability_statistics.rb
deleted file mode 100644
index 77fd116230e..00000000000
--- a/db/migrate/20200610130002_create_vulnerability_statistics.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class CreateVulnerabilityStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :vulnerability_statistics do |t|
- t.timestamps_with_timezone null: false
- t.references :project, null: false, foreign_key: { on_delete: :cascade }
- t.integer :total, default: 0, null: false
- t.integer :critical, default: 0, null: false
- t.integer :high, default: 0, null: false
- t.integer :medium, default: 0, null: false
- t.integer :low, default: 0, null: false
- t.integer :unknown, default: 0, null: false
- t.integer :info, default: 0, null: false
- t.integer :letter_grade, limit: 1, index: true, null: false
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :vulnerability_statistics
- end
- end
-end
diff --git a/db/migrate/20200611013227_add_users_foreign_key_to_terraform_state_versions.rb b/db/migrate/20200611013227_add_users_foreign_key_to_terraform_state_versions.rb
deleted file mode 100644
index b599622c776..00000000000
--- a/db/migrate/20200611013227_add_users_foreign_key_to_terraform_state_versions.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddUsersForeignKeyToTerraformStateVersions < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :terraform_state_versions, :users, column: :created_by_user_id, on_delete: :nullify
- end
-
- def down
- with_lock_retries do
- remove_foreign_key_if_exists :terraform_state_versions, :users, column: :created_by_user_id
- end
- end
-end
diff --git a/db/migrate/20200613104045_add_compliance_frameworks_to_application_settings.rb b/db/migrate/20200613104045_add_compliance_frameworks_to_application_settings.rb
deleted file mode 100644
index be6f14692e7..00000000000
--- a/db/migrate/20200613104045_add_compliance_frameworks_to_application_settings.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddComplianceFrameworksToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :application_settings, :compliance_frameworks, :integer, limit: 2, array: true, default: [], null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :application_settings, :compliance_frameworks
- end
- end
-end
diff --git a/db/migrate/20200615083635_add_composer_json_to_metadata.rb b/db/migrate/20200615083635_add_composer_json_to_metadata.rb
deleted file mode 100644
index 0240d298d34..00000000000
--- a/db/migrate/20200615083635_add_composer_json_to_metadata.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddComposerJsonToMetadata < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :packages_composer_metadata, :composer_json, :jsonb, default: {}, null: false
- end
-end
diff --git a/db/migrate/20200615121217_add_projects_foreign_key_to_project_access_tokens.rb b/db/migrate/20200615121217_add_projects_foreign_key_to_project_access_tokens.rb
deleted file mode 100644
index bc8956ff6df..00000000000
--- a/db/migrate/20200615121217_add_projects_foreign_key_to_project_access_tokens.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectsForeignKeyToProjectAccessTokens < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :project_access_tokens, :projects, column: :project_id
- end
-
- def down
- remove_foreign_key_if_exists :project_access_tokens, column: :project_id
- end
-end
diff --git a/db/migrate/20200615123055_add_personal_access_token_foreign_key_to_project_access_tokens.rb b/db/migrate/20200615123055_add_personal_access_token_foreign_key_to_project_access_tokens.rb
deleted file mode 100644
index efe3fe13bab..00000000000
--- a/db/migrate/20200615123055_add_personal_access_token_foreign_key_to_project_access_tokens.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddPersonalAccessTokenForeignKeyToProjectAccessTokens < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :project_access_tokens, :personal_access_tokens, column: :personal_access_token_id
- end
-
- def down
- remove_foreign_key_if_exists :project_access_tokens, column: :personal_access_token_id
- end
-end
diff --git a/db/migrate/20200615141554_add_closed_by_fields_to_resource_state_events.rb b/db/migrate/20200615141554_add_closed_by_fields_to_resource_state_events.rb
deleted file mode 100644
index ba11e64e667..00000000000
--- a/db/migrate/20200615141554_add_closed_by_fields_to_resource_state_events.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddClosedByFieldsToResourceStateEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- add_column :resource_state_events, :close_after_error_tracking_resolve, :boolean, default: false, null: false
- add_column :resource_state_events, :close_auto_resolve_prometheus_alert, :boolean, default: false, null: false
- end
-
- def down
- remove_column :resource_state_events, :close_auto_resolve_prometheus_alert, :boolean
- remove_column :resource_state_events, :close_after_error_tracking_resolve, :boolean
- end
-end
diff --git a/db/migrate/20200615193524_add_verify_known_sign_in_to_application_settings.rb b/db/migrate/20200615193524_add_verify_known_sign_in_to_application_settings.rb
deleted file mode 100644
index c50a17968a9..00000000000
--- a/db/migrate/20200615193524_add_verify_known_sign_in_to_application_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddVerifyKnownSignInToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :notify_on_unknown_sign_in, :boolean, default: true, null: false
- end
-end
diff --git a/db/migrate/20200615232735_add_index_to_composer_metadata.rb b/db/migrate/20200615232735_add_index_to_composer_metadata.rb
deleted file mode 100644
index 72a490c55d8..00000000000
--- a/db/migrate/20200615232735_add_index_to_composer_metadata.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToComposerMetadata < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:packages_composer_metadata, [:package_id, :target_sha], unique: true)
- end
-
- def down
- remove_concurrent_index(:packages_composer_metadata, [:package_id, :target_sha])
- end
-end
diff --git a/db/migrate/20200615234047_create_clusters_applications_cilium.rb b/db/migrate/20200615234047_create_clusters_applications_cilium.rb
deleted file mode 100644
index 9f77ee71164..00000000000
--- a/db/migrate/20200615234047_create_clusters_applications_cilium.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class CreateClustersApplicationsCilium < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :clusters_applications_cilium do |t|
- t.references :cluster, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade }
- t.timestamps_with_timezone null: false
- t.integer :status, null: false
- t.text :status_reason # rubocop:disable Migration/AddLimitToTextColumns
- end
- end
-end
diff --git a/db/migrate/20200616124338_add_plan_limits_for_max_size_per_artifact_type.rb b/db/migrate/20200616124338_add_plan_limits_for_max_size_per_artifact_type.rb
deleted file mode 100644
index 28fadb495dd..00000000000
--- a/db/migrate/20200616124338_add_plan_limits_for_max_size_per_artifact_type.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-class AddPlanLimitsForMaxSizePerArtifactType < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- # We need to set the 20mb default for lsif for backward compatibility
- # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34767#note_371619075
- add_column :plan_limits, "ci_max_artifact_size_lsif", :integer, default: 20, null: false
-
- artifact_types.each do |type|
- add_column :plan_limits, "ci_max_artifact_size_#{type}", :integer, default: 0, null: false
- end
- end
-
- private
-
- def artifact_types
- # The list of artifact types (except lsif) from Ci::JobArtifact file_type enum as of this writing.
- # Intentionally duplicated so that the migration won't change behavior
- # if ever we remove or add more to the list later on.
- %w[
- archive
- metadata
- trace
- junit
- sast
- dependency_scanning
- container_scanning
- dast
- codequality
- license_management
- license_scanning
- performance
- metrics
- metrics_referee
- network_referee
- dotenv
- cobertura
- terraform
- accessibility
- cluster_applications
- secret_detection
- requirements
- coverage_fuzzing
- ]
- end
-end
diff --git a/db/migrate/20200616145031_add_author_id_index_to_audit_events.rb b/db/migrate/20200616145031_add_author_id_index_to_audit_events.rb
deleted file mode 100644
index cb06fbe2b11..00000000000
--- a/db/migrate/20200616145031_add_author_id_index_to_audit_events.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddAuthorIdIndexToAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'index_audit_events_on_entity_id_entity_type_id_desc_author_id'
- OLD_INDEX_NAME = 'index_audit_events_on_entity_id_and_entity_type_and_id_desc'
-
- def up
- add_concurrent_index(:audit_events, [:entity_id, :entity_type, :id, :author_id], order: { id: :desc }, name: INDEX_NAME)
- remove_concurrent_index_by_name(:audit_events, OLD_INDEX_NAME)
- end
-
- def down
- add_concurrent_index(:audit_events, [:entity_id, :entity_type, :id], order: { id: :desc }, name: OLD_INDEX_NAME)
- remove_concurrent_index_by_name(:audit_events, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200617000757_clean_up_file_store_lfs_objects.rb b/db/migrate/20200617000757_clean_up_file_store_lfs_objects.rb
deleted file mode 100644
index a1a86355d02..00000000000
--- a/db/migrate/20200617000757_clean_up_file_store_lfs_objects.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class CleanUpFileStoreLfsObjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- # rubocop:disable Migration/UpdateColumnInBatches
- update_column_in_batches(:lfs_objects, :file_store, 1) do |table, query|
- query.where(table[:file_store].eq(nil))
- end
- # rubocop:enable Migration/UpdateColumnInBatches
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200617001001_clean_up_store_uploads.rb b/db/migrate/20200617001001_clean_up_store_uploads.rb
deleted file mode 100644
index 970d0485b0d..00000000000
--- a/db/migrate/20200617001001_clean_up_store_uploads.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class CleanUpStoreUploads < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- # rubocop:disable Migration/UpdateColumnInBatches
- update_column_in_batches(:uploads, :store, 1) do |table, query|
- query.where(table[:store].eq(nil))
- end
- # rubocop:enable Migration/UpdateColumnInBatches
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200617001118_clean_up_file_store_ci_job_artifacts.rb b/db/migrate/20200617001118_clean_up_file_store_ci_job_artifacts.rb
deleted file mode 100644
index e30f7e342e5..00000000000
--- a/db/migrate/20200617001118_clean_up_file_store_ci_job_artifacts.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class CleanUpFileStoreCiJobArtifacts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- # rubocop:disable Migration/UpdateColumnInBatches
- # rubocop:disable Migration/UpdateLargeTable
- update_column_in_batches(:ci_job_artifacts, :file_store, 1) do |table, query|
- query.where(table[:file_store].eq(nil))
- end
- # rubocop:enable Migration/UpdateColumnInBatches
- # rubocop:enable Migration/UpdateLargeTable
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200617150041_create_namespace_limits.rb b/db/migrate/20200617150041_create_namespace_limits.rb
deleted file mode 100644
index 59a014ff7ca..00000000000
--- a/db/migrate/20200617150041_create_namespace_limits.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class CreateNamespaceLimits < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :namespace_limits, id: false do |t|
- t.bigint :additional_purchased_storage_size, default: 0, null: false
- t.date :additional_purchased_storage_ends_on, null: true
-
- t.references :namespace, primary_key: true, default: nil, type: :integer, index: false, foreign_key: { on_delete: :cascade }
- end
- end
- end
-
- def down
- drop_table :namespace_limits
- end
-end
diff --git a/db/migrate/20200617205000_add_deploy_key_id_to_push_access_levels.rb b/db/migrate/20200617205000_add_deploy_key_id_to_push_access_levels.rb
deleted file mode 100644
index 11b92c2a321..00000000000
--- a/db/migrate/20200617205000_add_deploy_key_id_to_push_access_levels.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddDeployKeyIdToPushAccessLevels < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:protected_branch_push_access_levels, :deploy_key_id)
- add_column :protected_branch_push_access_levels, :deploy_key_id, :integer
- end
-
- add_concurrent_foreign_key :protected_branch_push_access_levels, :keys, column: :deploy_key_id, on_delete: :cascade
- add_concurrent_index :protected_branch_push_access_levels, :deploy_key_id, name: 'index_deploy_key_id_on_protected_branch_push_access_levels'
- end
-
- def down
- remove_column :protected_branch_push_access_levels, :deploy_key_id
- end
-end
diff --git a/db/migrate/20200618105638_add_index_on_id_and_created_at_to_snippets.rb b/db/migrate/20200618105638_add_index_on_id_and_created_at_to_snippets.rb
deleted file mode 100644
index d9ef3b18e9b..00000000000
--- a/db/migrate/20200618105638_add_index_on_id_and_created_at_to_snippets.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnIdAndCreatedAtToSnippets < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :snippets, [:id, :created_at]
- end
-
- def down
- remove_concurrent_index :snippets, [:id, :created_at]
- end
-end
diff --git a/db/migrate/20200618134223_restore_previous_schema_without_lock_version_null_constraint.rb b/db/migrate/20200618134223_restore_previous_schema_without_lock_version_null_constraint.rb
deleted file mode 100644
index 85e98d05d02..00000000000
--- a/db/migrate/20200618134223_restore_previous_schema_without_lock_version_null_constraint.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class RestorePreviousSchemaWithoutLockVersionNullConstraint < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- TABLES = %i(epics merge_requests issues ci_stages ci_builds ci_pipelines).freeze
-
- disable_ddl_transaction!
-
- def up
- TABLES.each do |table|
- remove_not_null_constraint table, :lock_version
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200618134723_restore_previous_schema_with_lock_version_indices.rb b/db/migrate/20200618134723_restore_previous_schema_with_lock_version_indices.rb
deleted file mode 100644
index 64fdb373387..00000000000
--- a/db/migrate/20200618134723_restore_previous_schema_with_lock_version_indices.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class RestorePreviousSchemaWithLockVersionIndices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :issues, :lock_version, where: "lock_version IS NULL"
- add_concurrent_index :merge_requests, :lock_version, where: "lock_version IS NULL"
- add_concurrent_index :epics, :lock_version, where: "lock_version IS NULL"
- add_concurrent_index :ci_stages, :id, where: "lock_version IS NULL", name: "tmp_index_ci_stages_lock_version"
- add_concurrent_index :ci_builds, :id, where: "lock_version IS NULL", name: "tmp_index_ci_builds_lock_version"
- add_concurrent_index :ci_pipelines, :id, where: "lock_version IS NULL", name: "tmp_index_ci_pipelines_lock_version"
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200619000316_add_has_confluence_to_project_settings.rb b/db/migrate/20200619000316_add_has_confluence_to_project_settings.rb
deleted file mode 100644
index 0f33e0bc47a..00000000000
--- a/db/migrate/20200619000316_add_has_confluence_to_project_settings.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddHasConfluenceToProjectSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :project_settings, :has_confluence, :boolean, default: false, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :project_settings, :has_confluence
- end
- end
-end
diff --git a/db/migrate/20200619154527_add_project_key_to_jira_tracker_data.rb b/db/migrate/20200619154527_add_project_key_to_jira_tracker_data.rb
deleted file mode 100644
index 574eb99a6cc..00000000000
--- a/db/migrate/20200619154527_add_project_key_to_jira_tracker_data.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectKeyToJiraTrackerData < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in 20200619154528_add_text_limit_to_jira_tracker_data_project_key
- def change
- add_column :jira_tracker_data, :project_key, :text
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20200619154528_add_text_limit_to_jira_tracker_data_project_key.rb b/db/migrate/20200619154528_add_text_limit_to_jira_tracker_data_project_key.rb
deleted file mode 100644
index 6cf8a787381..00000000000
--- a/db/migrate/20200619154528_add_text_limit_to_jira_tracker_data_project_key.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToJiraTrackerDataProjectKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :jira_tracker_data, :project_key, 255
- end
-
- def down
- remove_text_limit :jira_tracker_data, :project_key
- end
-end
diff --git a/db/migrate/20200622040750_add_prometheus_alert_id_to_alert_management_alerts.rb b/db/migrate/20200622040750_add_prometheus_alert_id_to_alert_management_alerts.rb
deleted file mode 100644
index e7669db0a28..00000000000
--- a/db/migrate/20200622040750_add_prometheus_alert_id_to_alert_management_alerts.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddPrometheusAlertIdToAlertManagementAlerts < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column :alert_management_alerts, :prometheus_alert_id, :integer
-
- add_column :alert_management_alerts, :environment_id, :integer
- end
-
- def down
- remove_column :alert_management_alerts, :prometheus_alert_id
- remove_column :alert_management_alerts, :environment_id
- end
-end
diff --git a/db/migrate/20200622070606_add_vendor_to_vulnerability_scanners.rb b/db/migrate/20200622070606_add_vendor_to_vulnerability_scanners.rb
deleted file mode 100644
index 2c9c0a9110d..00000000000
--- a/db/migrate/20200622070606_add_vendor_to_vulnerability_scanners.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class AddVendorToVulnerabilityScanners < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- DEFAULT_SCANNER_VENDOR = 'GitLab'
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in 20200622070620_add_limit_to_vulnerability_scanners_vendor
- def up
- with_lock_retries do
- add_column :vulnerability_scanners, :vendor, :text, default: DEFAULT_SCANNER_VENDOR, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :vulnerability_scanners, :vendor
- end
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20200622070620_add_limit_to_vulnerability_scanners_vendor.rb b/db/migrate/20200622070620_add_limit_to_vulnerability_scanners_vendor.rb
deleted file mode 100644
index efcbbde3e29..00000000000
--- a/db/migrate/20200622070620_add_limit_to_vulnerability_scanners_vendor.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddLimitToVulnerabilityScannersVendor < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :vulnerability_scanners, :vendor, 255, validate: false
- end
-
- def down
- remove_text_limit :vulnerability_scanners, :vendor
- end
-end
diff --git a/db/migrate/20200622095419_add_snippets_size_to_project_statistics.rb b/db/migrate/20200622095419_add_snippets_size_to_project_statistics.rb
deleted file mode 100644
index 9fe470478b8..00000000000
--- a/db/migrate/20200622095419_add_snippets_size_to_project_statistics.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddSnippetsSizeToProjectStatistics < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :project_statistics, :snippets_size, :bigint
- end
-end
diff --git a/db/migrate/20200622103836_create_snippet_statistics.rb b/db/migrate/20200622103836_create_snippet_statistics.rb
deleted file mode 100644
index 691a9acdc04..00000000000
--- a/db/migrate/20200622103836_create_snippet_statistics.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class CreateSnippetStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :snippet_statistics, id: false do |t|
- t.references :snippet, primary_key: true, default: nil, index: false, foreign_key: { on_delete: :cascade }
- t.bigint :repository_size, default: 0, null: false
- t.bigint :file_count, default: 0, null: false
- t.bigint :commit_count, default: 0, null: false
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :snippet_statistics
- end
- end
-end
diff --git a/db/migrate/20200622104923_create_ci_pipeline_messages_table.rb b/db/migrate/20200622104923_create_ci_pipeline_messages_table.rb
deleted file mode 100644
index 40d63b1189e..00000000000
--- a/db/migrate/20200622104923_create_ci_pipeline_messages_table.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCiPipelineMessagesTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- ERROR_SEVERITY = 0
- MAX_CONTENT_LENGTH = 10_000
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- create_table :ci_pipeline_messages do |t|
- t.integer :severity, null: false, default: ERROR_SEVERITY, limit: 2
- t.references :pipeline, index: true, null: false, foreign_key: { to_table: :ci_pipelines, on_delete: :cascade }, type: :integer
- t.text :content, null: false
- end
- end
-
- add_text_limit :ci_pipeline_messages, :content, MAX_CONTENT_LENGTH
- end
-
- def down
- drop_table :ci_pipeline_messages
- end
-end
diff --git a/db/migrate/20200622235737_remove_index_ci_job_artifacts_file_store_is_null.rb b/db/migrate/20200622235737_remove_index_ci_job_artifacts_file_store_is_null.rb
deleted file mode 100644
index e293bcfa1ce..00000000000
--- a/db/migrate/20200622235737_remove_index_ci_job_artifacts_file_store_is_null.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexCiJobArtifactsFileStoreIsNull < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_ci_job_artifacts_file_store_is_null'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name(:ci_job_artifacts, INDEX_NAME)
- end
-
- def down
- add_concurrent_index(:ci_job_artifacts, :id, where: "file_store IS NULL", name: INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200623000148_remove_index_lfs_objects_file_store_is_null.rb b/db/migrate/20200623000148_remove_index_lfs_objects_file_store_is_null.rb
deleted file mode 100644
index 76faa5c4cd2..00000000000
--- a/db/migrate/20200623000148_remove_index_lfs_objects_file_store_is_null.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexLfsObjectsFileStoreIsNull < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_lfs_objects_file_store_is_null'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name(:lfs_objects, INDEX_NAME)
- end
-
- def down
- add_concurrent_index(:lfs_objects, :id, where: "file_store IS NULL", name: INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200623000320_remove_index_uploads_store_is_null.rb b/db/migrate/20200623000320_remove_index_uploads_store_is_null.rb
deleted file mode 100644
index ad84cd5a649..00000000000
--- a/db/migrate/20200623000320_remove_index_uploads_store_is_null.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexUploadsStoreIsNull < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_uploads_store_is_null'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name(:uploads, INDEX_NAME)
- end
-
- def down
- add_concurrent_index(:uploads, :id, where: "store IS NULL", name: INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200623073431_add_source_merge_request_id_to_resource_state_events.rb b/db/migrate/20200623073431_add_source_merge_request_id_to_resource_state_events.rb
deleted file mode 100644
index 01d0d8ce1d4..00000000000
--- a/db/migrate/20200623073431_add_source_merge_request_id_to_resource_state_events.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class AddSourceMergeRequestIdToResourceStateEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- INDEX_NAME = 'index_resource_state_events_on_source_merge_request_id'
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:resource_state_events, :source_merge_request_id)
- add_column :resource_state_events, :source_merge_request_id, :bigint
- end
-
- unless index_exists?(:resource_state_events, :source_merge_request_id, name: INDEX_NAME)
- add_index :resource_state_events, :source_merge_request_id, name: INDEX_NAME # rubocop: disable Migration/AddIndex
- end
-
- unless foreign_key_exists?(:resource_state_events, :merge_requests, column: :source_merge_request_id)
- with_lock_retries do
- add_foreign_key :resource_state_events, :merge_requests, column: :source_merge_request_id, on_delete: :nullify
- end
- end
- end
-
- def down
- with_lock_retries do
- remove_column :resource_state_events, :source_merge_request_id
- end
- end
-end
diff --git a/db/migrate/20200623090030_add_author_name_to_audit_event.rb b/db/migrate/20200623090030_add_author_name_to_audit_event.rb
deleted file mode 100644
index 8b45503189a..00000000000
--- a/db/migrate/20200623090030_add_author_name_to_audit_event.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddAuthorNameToAuditEvent < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:audit_events, :author_name)
- with_lock_retries do
- add_column :audit_events, :author_name, :text
- end
- end
-
- add_text_limit :audit_events, :author_name, 255
- end
-
- def down
- remove_column :audit_events, :author_name
- end
-end
diff --git a/db/migrate/20200623121135_create_dynamic_partitions_schema.rb b/db/migrate/20200623121135_create_dynamic_partitions_schema.rb
deleted file mode 100644
index 931a55ebcf4..00000000000
--- a/db/migrate/20200623121135_create_dynamic_partitions_schema.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDynamicPartitionsSchema < ActiveRecord::Migration[6.0]
- include Gitlab::Database::SchemaHelpers
-
- DOWNTIME = false
-
- def up
- execute 'CREATE SCHEMA gitlab_partitions_dynamic'
-
- create_comment(:schema, :gitlab_partitions_dynamic, <<~EOS.strip)
- Schema to hold partitions managed dynamically from the application, e.g. for time space partitioning.
- EOS
- end
-
- def down
- execute 'DROP SCHEMA gitlab_partitions_dynamic'
- end
-end
diff --git a/db/migrate/20200623141217_add_view_diffs_file_by_file_to_user_preferences.rb b/db/migrate/20200623141217_add_view_diffs_file_by_file_to_user_preferences.rb
deleted file mode 100644
index 9ea38bd4ab4..00000000000
--- a/db/migrate/20200623141217_add_view_diffs_file_by_file_to_user_preferences.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddViewDiffsFileByFileToUserPreferences < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- add_column :user_preferences, :view_diffs_file_by_file, :boolean, default: false, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :user_preferences, :view_diffs_file_by_file, :boolean
- end
- end
-end
diff --git a/db/migrate/20200623141544_create_elastic_reindexing_task.rb b/db/migrate/20200623141544_create_elastic_reindexing_task.rb
deleted file mode 100644
index 7089df4f1ea..00000000000
--- a/db/migrate/20200623141544_create_elastic_reindexing_task.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class CreateElasticReindexingTask < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :elastic_reindexing_tasks do |t|
- t.timestamps_with_timezone null: false
- t.integer :documents_count
- t.integer :state, null: false, default: 0, limit: 2, index: true
- t.boolean :in_progress, null: false, default: true
- t.text :index_name_from
- t.text :index_name_to
- t.text :elastic_task
- t.text :error_message
- end
-
- add_text_limit :elastic_reindexing_tasks, :index_name_from, 255
- add_text_limit :elastic_reindexing_tasks, :index_name_to, 255
- add_text_limit :elastic_reindexing_tasks, :elastic_task, 255
- add_text_limit :elastic_reindexing_tasks, :error_message, 255
-
- add_index :elastic_reindexing_tasks, :in_progress, unique: true, where: 'in_progress'
- end
-
- def down
- drop_table :elastic_reindexing_tasks
- end
-end
diff --git a/db/migrate/20200623170000_create_static_partitions_schema.rb b/db/migrate/20200623170000_create_static_partitions_schema.rb
deleted file mode 100644
index d8878d2fe33..00000000000
--- a/db/migrate/20200623170000_create_static_partitions_schema.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class CreateStaticPartitionsSchema < ActiveRecord::Migration[6.0]
- include Gitlab::Database::SchemaHelpers
-
- DOWNTIME = false
-
- def up
- execute 'CREATE SCHEMA gitlab_partitions_static'
-
- create_comment(:schema, :gitlab_partitions_static, <<~EOS.strip)
- Schema to hold static partitions, e.g. for hash partitioning
- EOS
- end
-
- def down
- execute 'DROP SCHEMA gitlab_partitions_static'
- end
-end
diff --git a/db/migrate/20200623185440_add_product_analytics_table.rb b/db/migrate/20200623185440_add_product_analytics_table.rb
deleted file mode 100644
index 0a0d438bfb9..00000000000
--- a/db/migrate/20200623185440_add_product_analytics_table.rb
+++ /dev/null
@@ -1,202 +0,0 @@
-# frozen_string_literal: true
-
-class AddProductAnalyticsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- include Gitlab::Database::PartitioningMigrationHelpers::TableManagementHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- # Table is based on https://github.com/snowplow/snowplow/blob/master/4-storage/postgres-storage/sql/atomic-def.sql 6e07b1c, with the following differences:
- # * app_id varchar -> project_id integer (+ FK)
- # * Add `id bigserial`
- # * Hash partitioning based on `project_id`
- # * Timestamp columns: Change type to timestamp with time zone
- #
- # This table is part of the "product analytics experiment" and as such marked "experimental". The goal here is to
- # explore the product analytics as a MVP feature more. We are explicitly not spending time on relational modeling
- # here.
- #
- # We expect significant changes to the database part of this once the feature has been validated.
- # Therefore, we expect to drop the table when feature validation is complete. All data will be lost.
- def up
- with_lock_retries do
- execute <<~SQL
- CREATE TABLE "product_analytics_events_experimental" (
- id bigserial NOT NULL,
- -- App
- "project_id" integer NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
- "platform" varchar(255),
- -- Date/time
- "etl_tstamp" timestamp with time zone,
- "collector_tstamp" timestamp with time zone NOT NULL,
- "dvce_created_tstamp" timestamp with time zone,
- -- Date/time
- "event" varchar(128),
- "event_id" char(36) NOT NULL,
- "txn_id" integer,
- -- Versioning
- "name_tracker" varchar(128),
- "v_tracker" varchar(100),
- "v_collector" varchar(100) NOT NULL,
- "v_etl" varchar(100) NOT NULL,
- -- User and visit
- "user_id" varchar(255),
- "user_ipaddress" varchar(45),
- "user_fingerprint" varchar(50),
- "domain_userid" varchar(36),
- "domain_sessionidx" smallint,
- "network_userid" varchar(38),
- -- Location
- "geo_country" char(2),
- "geo_region" char(3),
- "geo_city" varchar(75),
- "geo_zipcode" varchar(15),
- "geo_latitude" double precision,
- "geo_longitude" double precision,
- "geo_region_name" varchar(100),
- -- IP lookups
- "ip_isp" varchar(100),
- "ip_organization" varchar(100),
- "ip_domain" varchar(100),
- "ip_netspeed" varchar(100),
- -- Page
- "page_url" text,
- "page_title" varchar(2000),
- "page_referrer" text,
- -- Page URL components
- "page_urlscheme" varchar(16),
- "page_urlhost" varchar(255),
- "page_urlport" integer,
- "page_urlpath" varchar(3000),
- "page_urlquery" varchar(6000),
- "page_urlfragment" varchar(3000),
- -- Referrer URL components
- "refr_urlscheme" varchar(16),
- "refr_urlhost" varchar(255),
- "refr_urlport" integer,
- "refr_urlpath" varchar(6000),
- "refr_urlquery" varchar(6000),
- "refr_urlfragment" varchar(3000),
- -- Referrer details
- "refr_medium" varchar(25),
- "refr_source" varchar(50),
- "refr_term" varchar(255),
- -- Marketing
- "mkt_medium" varchar(255),
- "mkt_source" varchar(255),
- "mkt_term" varchar(255),
- "mkt_content" varchar(500),
- "mkt_campaign" varchar(255),
- -- Custom structured event
- "se_category" varchar(1000),
- "se_action" varchar(1000),
- "se_label" varchar(1000),
- "se_property" varchar(1000),
- "se_value" double precision,
- -- Ecommerce
- "tr_orderid" varchar(255),
- "tr_affiliation" varchar(255),
- "tr_total" decimal(18,2),
- "tr_tax" decimal(18,2),
- "tr_shipping" decimal(18,2),
- "tr_city" varchar(255),
- "tr_state" varchar(255),
- "tr_country" varchar(255),
- "ti_orderid" varchar(255),
- "ti_sku" varchar(255),
- "ti_name" varchar(255),
- "ti_category" varchar(255),
- "ti_price" decimal(18,2),
- "ti_quantity" integer,
- -- Page ping
- "pp_xoffset_min" integer,
- "pp_xoffset_max" integer,
- "pp_yoffset_min" integer,
- "pp_yoffset_max" integer,
- -- User Agent
- "useragent" varchar(1000),
- -- Browser
- "br_name" varchar(50),
- "br_family" varchar(50),
- "br_version" varchar(50),
- "br_type" varchar(50),
- "br_renderengine" varchar(50),
- "br_lang" varchar(255),
- "br_features_pdf" boolean,
- "br_features_flash" boolean,
- "br_features_java" boolean,
- "br_features_director" boolean,
- "br_features_quicktime" boolean,
- "br_features_realplayer" boolean,
- "br_features_windowsmedia" boolean,
- "br_features_gears" boolean,
- "br_features_silverlight" boolean,
- "br_cookies" boolean,
- "br_colordepth" varchar(12),
- "br_viewwidth" integer,
- "br_viewheight" integer,
- -- Operating System
- "os_name" varchar(50),
- "os_family" varchar(50),
- "os_manufacturer" varchar(50),
- "os_timezone" varchar(50),
- -- Device/Hardware
- "dvce_type" varchar(50),
- "dvce_ismobile" boolean,
- "dvce_screenwidth" integer,
- "dvce_screenheight" integer,
- -- Document
- "doc_charset" varchar(128),
- "doc_width" integer,
- "doc_height" integer,
- -- Currency
- "tr_currency" char(3),
- "tr_total_base" decimal(18, 2),
- "tr_tax_base" decimal(18, 2),
- "tr_shipping_base" decimal(18, 2),
- "ti_currency" char(3),
- "ti_price_base" decimal(18, 2),
- "base_currency" char(3),
- -- Geolocation
- "geo_timezone" varchar(64),
- -- Click ID
- "mkt_clickid" varchar(128),
- "mkt_network" varchar(64),
- -- ETL tags
- "etl_tags" varchar(500),
- -- Time event was sent
- "dvce_sent_tstamp" timestamp with time zone,
- -- Referer
- "refr_domain_userid" varchar(36),
- "refr_dvce_tstamp" timestamp with time zone,
- -- Session ID
- "domain_sessionid" char(36),
- -- Derived timestamp
- "derived_tstamp" timestamp with time zone,
- -- Event schema
- "event_vendor" varchar(1000),
- "event_name" varchar(1000),
- "event_format" varchar(128),
- "event_version" varchar(128),
- -- Event fingerprint
- "event_fingerprint" varchar(128),
- -- True timestamp
- "true_tstamp" timestamp with time zone,
- PRIMARY KEY (id, project_id)
- ) PARTITION BY HASH (project_id)
- WITHOUT OIDS;
-
- CREATE INDEX index_product_analytics_events_experimental_project_and_time ON product_analytics_events_experimental (project_id, collector_tstamp);
- SQL
-
- create_hash_partitions :product_analytics_events_experimental, 64
- end
- end
-
- def down
- with_lock_retries do
- execute 'DROP TABLE product_analytics_events_experimental'
- end
- end
-end
diff --git a/db/migrate/20200624075411_add_storage_size_limit_to_plan_limit.rb b/db/migrate/20200624075411_add_storage_size_limit_to_plan_limit.rb
deleted file mode 100644
index 7d1b081be02..00000000000
--- a/db/migrate/20200624075411_add_storage_size_limit_to_plan_limit.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddStorageSizeLimitToPlanLimit < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :plan_limits, :storage_size_limit, :integer, default: 0, null: false
- end
-end
diff --git a/db/migrate/20200624142107_create_analytics_cycle_analytics_group_value_streams.rb b/db/migrate/20200624142107_create_analytics_cycle_analytics_group_value_streams.rb
deleted file mode 100644
index 4b3f5222399..00000000000
--- a/db/migrate/20200624142107_create_analytics_cycle_analytics_group_value_streams.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class CreateAnalyticsCycleAnalyticsGroupValueStreams < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_analytics_ca_group_value_streams_on_group_id_and_name'
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:analytics_cycle_analytics_group_value_streams)
- with_lock_retries do
- create_table :analytics_cycle_analytics_group_value_streams do |t|
- t.timestamps_with_timezone
- t.references(:group,
- null: false,
- index: false,
- foreign_key: { to_table: :namespaces, on_delete: :cascade }
- )
- t.text :name, null: false
- t.index [:group_id, :name], unique: true, name: INDEX_NAME
- end
- end
- end
-
- add_text_limit :analytics_cycle_analytics_group_value_streams, :name, 100
- end
-
- def down
- drop_table :analytics_cycle_analytics_group_value_streams
- end
-end
diff --git a/db/migrate/20200624142207_add_group_value_stream_to_cycle_analytics_group_stages.rb b/db/migrate/20200624142207_add_group_value_stream_to_cycle_analytics_group_stages.rb
deleted file mode 100644
index 3ce912eb440..00000000000
--- a/db/migrate/20200624142207_add_group_value_stream_to_cycle_analytics_group_stages.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddGroupValueStreamToCycleAnalyticsGroupStages < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :analytics_cycle_analytics_group_stages, :group_value_stream_id, :bigint
- end
- end
-
- def down
- with_lock_retries do
- remove_column :analytics_cycle_analytics_group_stages, :group_value_stream_id
- end
- end
-end
diff --git a/db/migrate/20200624222443_add_default_branch_name_to_application_settings.rb b/db/migrate/20200624222443_add_default_branch_name_to_application_settings.rb
deleted file mode 100644
index 5da9006e9a0..00000000000
--- a/db/migrate/20200624222443_add_default_branch_name_to_application_settings.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultBranchNameToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in db/migrate/20200625190458_add_limit_to_default_branch_name_to_application_settings
- def change
- add_column :application_settings, :default_branch_name, :text
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20200625045442_add_idx_and_fk_for_prometheus_and_environment_to_alert_management_alerts.rb b/db/migrate/20200625045442_add_idx_and_fk_for_prometheus_and_environment_to_alert_management_alerts.rb
deleted file mode 100644
index f4869b15735..00000000000
--- a/db/migrate/20200625045442_add_idx_and_fk_for_prometheus_and_environment_to_alert_management_alerts.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class AddIdxAndFkForPrometheusAndEnvironmentToAlertManagementAlerts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :alert_management_alerts, :prometheus_alert_id, where: 'prometheus_alert_id is not null'
- add_concurrent_foreign_key :alert_management_alerts, :prometheus_alerts, column: :prometheus_alert_id, on_delete: :cascade
-
- add_concurrent_index :alert_management_alerts, :environment_id, where: 'environment_id is not null'
- add_concurrent_foreign_key :alert_management_alerts, :environments, column: :environment_id, on_delete: :nullify
- end
-
- def down
- remove_concurrent_index :alert_management_alerts, :prometheus_alert_id
- remove_foreign_key_without_error :alert_management_alerts, column: :prometheus_alert_id
-
- remove_concurrent_index :alert_management_alerts, :environment_id
- remove_foreign_key_without_error :alert_management_alerts, column: :environment_id
- end
-end
diff --git a/db/migrate/20200625082258_add_snippets_size_to_root_storage_statistics.rb b/db/migrate/20200625082258_add_snippets_size_to_root_storage_statistics.rb
deleted file mode 100644
index 7dd0bd94805..00000000000
--- a/db/migrate/20200625082258_add_snippets_size_to_root_storage_statistics.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddSnippetsSizeToRootStorageStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :namespace_root_storage_statistics, :snippets_size, :bigint, default: 0, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :namespace_root_storage_statistics, :snippets_size
- end
- end
-end
diff --git a/db/migrate/20200625113337_add_last_used_to_personal_access_tokens.rb b/db/migrate/20200625113337_add_last_used_to_personal_access_tokens.rb
deleted file mode 100644
index c9d155eb628..00000000000
--- a/db/migrate/20200625113337_add_last_used_to_personal_access_tokens.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddLastUsedToPersonalAccessTokens < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- include Gitlab::Database::MigrationHelpers
-
- def up
- with_lock_retries do
- add_column :personal_access_tokens, :last_used_at, :datetime_with_timezone
- end
- end
-
- def down
- with_lock_retries do
- remove_column :personal_access_tokens, :last_used_at, :datetime_with_timezone
- end
- end
-end
diff --git a/db/migrate/20200625174052_add_partial_index_to_locked_pipelines.rb b/db/migrate/20200625174052_add_partial_index_to_locked_pipelines.rb
deleted file mode 100644
index 85f706f5d31..00000000000
--- a/db/migrate/20200625174052_add_partial_index_to_locked_pipelines.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddPartialIndexToLockedPipelines < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_pipelines, [:ci_ref_id, :id], name: 'idx_ci_pipelines_artifacts_locked', where: 'locked = 1'
- end
-
- def down
- remove_concurrent_index :ci_pipelines, 'idx_ci_pipelines_artifacts_locked'
- end
-end
diff --git a/db/migrate/20200625190458_add_limit_to_default_branch_name_to_application_settings.rb b/db/migrate/20200625190458_add_limit_to_default_branch_name_to_application_settings.rb
deleted file mode 100644
index b11eb514577..00000000000
--- a/db/migrate/20200625190458_add_limit_to_default_branch_name_to_application_settings.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddLimitToDefaultBranchNameToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :application_settings, :default_branch_name, 255
- end
-
- def down
- remove_text_limit :application_settings, :default_branch_name
- end
-end
diff --git a/db/migrate/20200625193358_increase_size_on_instance_level_variable_values.rb b/db/migrate/20200625193358_increase_size_on_instance_level_variable_values.rb
deleted file mode 100644
index ee665287a31..00000000000
--- a/db/migrate/20200625193358_increase_size_on_instance_level_variable_values.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class IncreaseSizeOnInstanceLevelVariableValues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- existing_constraint_name = text_limit_name(:ci_instance_variables, :encrypted_value)
- new_constraint_name = check_constraint_name(:ci_instance_variables, :encrypted_value, :char_length_updated)
-
- add_text_limit(:ci_instance_variables, :encrypted_value, 13_579, constraint_name: new_constraint_name)
- remove_check_constraint(:ci_instance_variables, existing_constraint_name)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200626130220_drop_partitions_dynamic_schema_if_exists.rb b/db/migrate/20200626130220_drop_partitions_dynamic_schema_if_exists.rb
deleted file mode 100644
index fa31bc8ff0e..00000000000
--- a/db/migrate/20200626130220_drop_partitions_dynamic_schema_if_exists.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class DropPartitionsDynamicSchemaIfExists < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- # This targets GitLab.com only - we deployed a migration to create this schema, but reverted the change
- execute 'DROP SCHEMA IF EXISTS partitions_dynamic'
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20200628210938_add_maintenance_mode_application_to_settings.rb b/db/migrate/20200628210938_add_maintenance_mode_application_to_settings.rb
deleted file mode 100644
index 6f1959a128f..00000000000
--- a/db/migrate/20200628210938_add_maintenance_mode_application_to_settings.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class AddMaintenanceModeApplicationToSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:application_settings, :maintenance_mode)
- change_table :application_settings do |t|
- t.boolean :maintenance_mode, default: false, null: false
- t.text :maintenance_mode_message
- end
- end
-
- add_text_limit(:application_settings, :maintenance_mode_message, 255)
- end
-
- def down
- if column_exists?(:application_settings, :maintenance_mode)
- remove_column :application_settings, :maintenance_mode
- end
-
- if column_exists?(:application_settings, :maintenance_mode_message)
- remove_column :application_settings, :maintenance_mode_message
- end
- end
-end
diff --git a/db/migrate/20200629134747_add_extra_index_to_label_links.rb b/db/migrate/20200629134747_add_extra_index_to_label_links.rb
deleted file mode 100644
index e2066a1db42..00000000000
--- a/db/migrate/20200629134747_add_extra_index_to_label_links.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class AddExtraIndexToLabelLinks < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_COVERING_ALL_COLUMNS = 'index_on_label_links_all_columns'
- INDEX_TO_REPLACE = 'index_label_links_on_label_id'
- NEW_INDEX = 'index_label_links_on_label_id_and_target_type'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :label_links, [:target_id, :label_id, :target_type], name: INDEX_COVERING_ALL_COLUMNS
-
- add_concurrent_index :label_links, [:label_id, :target_type], name: NEW_INDEX
- remove_concurrent_index_by_name(:label_links, INDEX_TO_REPLACE)
- end
-
- def down
- remove_concurrent_index_by_name(:label_links, INDEX_COVERING_ALL_COLUMNS)
-
- add_concurrent_index(:label_links, :label_id, name: INDEX_TO_REPLACE)
- remove_concurrent_index_by_name(:label_links, NEW_INDEX)
- end
-end
diff --git a/db/migrate/20200629192638_add_uniq_index_on_metric_identifier_and_project_id.rb b/db/migrate/20200629192638_add_uniq_index_on_metric_identifier_and_project_id.rb
deleted file mode 100644
index 3e77f80b5e8..00000000000
--- a/db/migrate/20200629192638_add_uniq_index_on_metric_identifier_and_project_id.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddUniqIndexOnMetricIdentifierAndProjectId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :prometheus_metrics, [:identifier, :project_id], unique: true
- end
-
- def down
- remove_concurrent_index :prometheus_metrics, [:identifier, :project_id]
- end
-end
diff --git a/db/migrate/20200630091656_add_bio_html_to_user_details.rb b/db/migrate/20200630091656_add_bio_html_to_user_details.rb
deleted file mode 100644
index 6a9df85d6a4..00000000000
--- a/db/migrate/20200630091656_add_bio_html_to_user_details.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class AddBioHtmlToUserDetails < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- # Note: bio_html is calculated from bio, the bio column is already constrained
- add_column :user_details, :bio_html, :text # rubocop:disable Migration/AddLimitToTextColumns
- add_column :user_details, :cached_markdown_version, :integer
- end
- end
-
- def down
- with_lock_retries do
- remove_column :user_details, :bio_html
- remove_column :user_details, :cached_markdown_version
- end
- end
-end
diff --git a/db/migrate/20200630110826_add_documents_count_target_to_elastic_reindexing_tasks.rb b/db/migrate/20200630110826_add_documents_count_target_to_elastic_reindexing_tasks.rb
deleted file mode 100644
index dcb4ccc857d..00000000000
--- a/db/migrate/20200630110826_add_documents_count_target_to_elastic_reindexing_tasks.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddDocumentsCountTargetToElasticReindexingTasks < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :elastic_reindexing_tasks, :documents_count_target, :integer
- end
-end
diff --git a/db/migrate/20200701064756_add_not_valid_foreign_key_to_cycle_analytics_group_stages.rb b/db/migrate/20200701064756_add_not_valid_foreign_key_to_cycle_analytics_group_stages.rb
deleted file mode 100644
index e54cecc5af8..00000000000
--- a/db/migrate/20200701064756_add_not_valid_foreign_key_to_cycle_analytics_group_stages.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddNotValidForeignKeyToCycleAnalyticsGroupStages < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_analytics_cycle_analytics_group_stages_group_value_stream_id'
- INDEX_NAME = 'index_analytics_ca_group_stages_on_value_stream_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :analytics_cycle_analytics_group_stages, :group_value_stream_id, name: INDEX_NAME
- add_foreign_key :analytics_cycle_analytics_group_stages, :analytics_cycle_analytics_group_value_streams,
- column: :group_value_stream_id, name: CONSTRAINT_NAME, on_delete: :cascade, validate: false
- end
-
- def down
- remove_foreign_key_if_exists :analytics_cycle_analytics_group_stages, column: :group_value_stream_id, name: CONSTRAINT_NAME
- remove_concurrent_index :analytics_cycle_analytics_group_stages, :group_value_stream_id
- end
-end
diff --git a/db/migrate/20200701093859_add_import_export_limits_to_application_settings.rb b/db/migrate/20200701093859_add_import_export_limits_to_application_settings.rb
deleted file mode 100644
index 6f40f439385..00000000000
--- a/db/migrate/20200701093859_add_import_export_limits_to_application_settings.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class AddImportExportLimitsToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :project_import_limit, :integer, default: 6, null: false
- add_column :application_settings, :project_export_limit, :integer, default: 6, null: false
- add_column :application_settings, :project_download_export_limit, :integer, default: 1, null: false
-
- add_column :application_settings, :group_import_limit, :integer, default: 6, null: false
- add_column :application_settings, :group_export_limit, :integer, default: 6, null: false
- add_column :application_settings, :group_download_export_limit, :integer, default: 1, null: false
- end
-end
diff --git a/db/migrate/20200701190523_add_delayed_project_removal_to_namespaces.rb b/db/migrate/20200701190523_add_delayed_project_removal_to_namespaces.rb
deleted file mode 100644
index fcc08723520..00000000000
--- a/db/migrate/20200701190523_add_delayed_project_removal_to_namespaces.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddDelayedProjectRemovalToNamespaces < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :namespaces, :delayed_project_removal, :boolean, default: false, null: false # rubocop:disable Migration/AddColumnsToWideTables
- end
- end
-
- def down
- with_lock_retries do
- remove_column :namespaces, :delayed_project_removal
- end
- end
-end
diff --git a/db/migrate/20200701205710_create_background_migration_jobs.rb b/db/migrate/20200701205710_create_background_migration_jobs.rb
deleted file mode 100644
index 706b8bd5abe..00000000000
--- a/db/migrate/20200701205710_create_background_migration_jobs.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class CreateBackgroundMigrationJobs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:background_migration_jobs)
- create_table :background_migration_jobs do |t|
- t.timestamps_with_timezone
- t.integer :status, null: false, limit: 2, default: 0
- t.text :class_name, null: false
- t.jsonb :arguments, null: false
-
- t.index [:class_name, :arguments]
- t.index [:class_name, :status, :id]
- end
- end
-
- add_text_limit :background_migration_jobs, :class_name, 200
- end
-
- def down
- drop_table :background_migration_jobs
- end
-end
diff --git a/db/migrate/20200701221303_change_default_value_of_ci_max_artifact_size_terraform_of_plan_limits_from_0_to_5.rb b/db/migrate/20200701221303_change_default_value_of_ci_max_artifact_size_terraform_of_plan_limits_from_0_to_5.rb
deleted file mode 100644
index e295d2f601a..00000000000
--- a/db/migrate/20200701221303_change_default_value_of_ci_max_artifact_size_terraform_of_plan_limits_from_0_to_5.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeDefaultValueOfCiMaxArtifactSizeTerraformOfPlanLimitsFrom0To5 < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :plan_limits, :ci_max_artifact_size_terraform, 5
- execute('UPDATE plan_limits SET ci_max_artifact_size_terraform = 5 WHERE ci_max_artifact_size_terraform = 0')
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :plan_limits, :ci_max_artifact_size_terraform, 0
- execute('UPDATE plan_limits SET ci_max_artifact_size_terraform = 0 WHERE ci_max_artifact_size_terraform = 5')
- end
- end
-end
diff --git a/db/migrate/20200702123805_change_project_id_index_to_be_unique_on_vulnerability_statistics_table.rb b/db/migrate/20200702123805_change_project_id_index_to_be_unique_on_vulnerability_statistics_table.rb
deleted file mode 100644
index 7562a32a25e..00000000000
--- a/db/migrate/20200702123805_change_project_id_index_to_be_unique_on_vulnerability_statistics_table.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeProjectIdIndexToBeUniqueOnVulnerabilityStatisticsTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- INDEX_NAME = 'index_vulnerability_statistics_on_unique_project_id'
-
- def up
- remove_index :vulnerability_statistics, :project_id # rubocop:disable Migration/RemoveIndex (table is empty)
- add_index :vulnerability_statistics, :project_id, name: INDEX_NAME, unique: true # rubocop:disable Migration/AddIndex (table is empty)
- end
-
- def down
- remove_index :vulnerability_statistics, name: INDEX_NAME # rubocop:disable Migration/RemoveIndex (table is empty)
- add_index :vulnerability_statistics, :project_id # rubocop:disable Migration/AddIndex (table is empty)
- end
-end
diff --git a/db/migrate/20200702201039_change_prometheus_metrics_identifier_index.rb b/db/migrate/20200702201039_change_prometheus_metrics_identifier_index.rb
deleted file mode 100644
index 248195c8c75..00000000000
--- a/db/migrate/20200702201039_change_prometheus_metrics_identifier_index.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class ChangePrometheusMetricsIdentifierIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- NEW_INDEX = :index_prometheus_metrics_on_identifier_and_null_project
- OLD_INDEX = :index_prometheus_metrics_on_identifier
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :prometheus_metrics, :identifier, name: NEW_INDEX, unique: true, where: 'project_id IS NULL'
- remove_concurrent_index_by_name :prometheus_metrics, OLD_INDEX
- end
-
- def down
- add_concurrent_index :prometheus_metrics, :identifier, name: OLD_INDEX, unique: true
- remove_concurrent_index_by_name :prometheus_metrics, NEW_INDEX
- end
-end
diff --git a/db/migrate/20200703035021_add_notes_to_timelogs.rb b/db/migrate/20200703035021_add_notes_to_timelogs.rb
deleted file mode 100644
index d711fd0400d..00000000000
--- a/db/migrate/20200703035021_add_notes_to_timelogs.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class AddNotesToTimelogs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- add_column :timelogs, :note_id, :integer
- end
- add_concurrent_index :timelogs, :note_id
- add_concurrent_foreign_key :timelogs, :notes, column: :note_id
- end
-
- def down
- remove_foreign_key_if_exists :timelogs, column: :note_id
- remove_concurrent_index :timelogs, :note_id
- with_lock_retries do
- remove_column :timelogs, :note_id
- end
- end
-end
diff --git a/db/migrate/20200703121557_remove_f_keys_from_ci_daily_report_results_table.rb b/db/migrate/20200703121557_remove_f_keys_from_ci_daily_report_results_table.rb
deleted file mode 100644
index 43b869b007d..00000000000
--- a/db/migrate/20200703121557_remove_f_keys_from_ci_daily_report_results_table.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveFKeysFromCiDailyReportResultsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- remove_foreign_key_if_exists :ci_daily_report_results, :projects
- remove_foreign_key_if_exists :ci_daily_report_results, :ci_pipelines
- end
- end
-
- def down
- add_concurrent_foreign_key :ci_daily_report_results, :projects, column: :project_id, on_delete: :cascade
- add_concurrent_foreign_key :ci_daily_report_results, :ci_pipelines, column: :last_pipeline_id, on_delete: :cascade
- end
-end
diff --git a/db/migrate/20200703124823_create_namespace_settings.rb b/db/migrate/20200703124823_create_namespace_settings.rb
deleted file mode 100644
index 907b9d2ca8c..00000000000
--- a/db/migrate/20200703124823_create_namespace_settings.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class CreateNamespaceSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- create_table :namespace_settings, id: false do |t|
- t.timestamps_with_timezone null: false
- t.references :namespace, primary_key: true, default: nil, type: :integer, index: false, foreign_key: { on_delete: :cascade }
- end
- end
- end
-
- def down
- drop_table :namespace_settings
- end
-end
diff --git a/db/migrate/20200703154822_add_issues_enabled_to_jira_tracker_data.rb b/db/migrate/20200703154822_add_issues_enabled_to_jira_tracker_data.rb
deleted file mode 100644
index e56f6f6ee11..00000000000
--- a/db/migrate/20200703154822_add_issues_enabled_to_jira_tracker_data.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddIssuesEnabledToJiraTrackerData < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :jira_tracker_data, :issues_enabled, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20200706005325_remove_elastic_batch_project_indexer_worker_queue.rb b/db/migrate/20200706005325_remove_elastic_batch_project_indexer_worker_queue.rb
deleted file mode 100644
index 07854096a8b..00000000000
--- a/db/migrate/20200706005325_remove_elastic_batch_project_indexer_worker_queue.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveElasticBatchProjectIndexerWorkerQueue < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- Sidekiq.redis do |conn|
- conn.del "queue:elastic_batch_project_indexer"
- end
- end
-end
diff --git a/db/migrate/20200706035141_adjust_unique_index_alert_management_alerts.rb b/db/migrate/20200706035141_adjust_unique_index_alert_management_alerts.rb
deleted file mode 100644
index 0a6e614be9a..00000000000
--- a/db/migrate/20200706035141_adjust_unique_index_alert_management_alerts.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class AdjustUniqueIndexAlertManagementAlerts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_alert_management_alerts_on_project_id_and_fingerprint'
- NEW_INDEX_NAME = 'index_partial_am_alerts_on_project_id_and_fingerprint'
- RESOLVED_STATUS = 2
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:alert_management_alerts, %w(project_id fingerprint), where: "status <> #{RESOLVED_STATUS}", name: NEW_INDEX_NAME, unique: true, using: :btree)
- remove_concurrent_index_by_name :alert_management_alerts, INDEX_NAME
- end
-
- def down
- # Nullify duplicate fingerprints, except for the newest of each match (project_id, fingerprint).
- query = <<-SQL
- UPDATE alert_management_alerts am
- SET fingerprint = NULL
- WHERE am.created_at <>
- (SELECT MAX(created_at)
- FROM alert_management_alerts am2
- WHERE am.fingerprint = am2.fingerprint AND am.project_id = am2.project_id)
- AND am.fingerprint IS NOT NULL;
- SQL
-
- execute(query)
-
- remove_concurrent_index_by_name :alert_management_alerts, NEW_INDEX_NAME
- add_concurrent_index(:alert_management_alerts, %w(project_id fingerprint), name: INDEX_NAME, unique: true, using: :btree)
- end
-end
diff --git a/db/migrate/20200706170536_add_temporary_storage_increase_to_namespace_limits.rb b/db/migrate/20200706170536_add_temporary_storage_increase_to_namespace_limits.rb
deleted file mode 100644
index 0b6d57831c7..00000000000
--- a/db/migrate/20200706170536_add_temporary_storage_increase_to_namespace_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddTemporaryStorageIncreaseToNamespaceLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :namespace_limits, :temporary_storage_increase_ends_on, :date, null: true
- end
-end
diff --git a/db/migrate/20200707071941_drop_old_non_unique_index_on_mr_metrics.rb b/db/migrate/20200707071941_drop_old_non_unique_index_on_mr_metrics.rb
deleted file mode 100644
index aa90a0c5915..00000000000
--- a/db/migrate/20200707071941_drop_old_non_unique_index_on_mr_metrics.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class DropOldNonUniqueIndexOnMrMetrics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_merge_request_metrics'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name(:merge_request_metrics, INDEX_NAME)
- end
-
- def down
- add_concurrent_index :merge_request_metrics, :merge_request_id, name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20200707094341_add_browser_performance_to_plan_limits.rb b/db/migrate/20200707094341_add_browser_performance_to_plan_limits.rb
deleted file mode 100644
index ef0bea88ead..00000000000
--- a/db/migrate/20200707094341_add_browser_performance_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddBrowserPerformanceToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :plan_limits, "ci_max_artifact_size_browser_performance", :integer, default: 0, null: false
- end
-end
diff --git a/db/migrate/20200707095849_add_load_performance_to_plan_limits.rb b/db/migrate/20200707095849_add_load_performance_to_plan_limits.rb
deleted file mode 100644
index df95956f089..00000000000
--- a/db/migrate/20200707095849_add_load_performance_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddLoadPerformanceToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :plan_limits, "ci_max_artifact_size_load_performance", :integer, default: 0, null: false
- end
-end
diff --git a/db/migrate/20200708080631_add_pager_duty_integration_columns_to_project_incident_management_settings.rb b/db/migrate/20200708080631_add_pager_duty_integration_columns_to_project_incident_management_settings.rb
deleted file mode 100644
index ab56a863f51..00000000000
--- a/db/migrate/20200708080631_add_pager_duty_integration_columns_to_project_incident_management_settings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddPagerDutyIntegrationColumnsToProjectIncidentManagementSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # limit constraints added in a separate migration:
- # 20200710130234_add_limit_constraints_to_project_incident_management_settings_token.rb
- def change
- add_column :project_incident_management_settings, :pagerduty_active, :boolean, null: false, default: false
- add_column :project_incident_management_settings, :encrypted_pagerduty_token, :binary, null: true
- add_column :project_incident_management_settings, :encrypted_pagerduty_token_iv, :binary, null: true
- end
-end
diff --git a/db/migrate/20200710105332_change_issues_create_limit_default.rb b/db/migrate/20200710105332_change_issues_create_limit_default.rb
deleted file mode 100644
index 9fbd5375395..00000000000
--- a/db/migrate/20200710105332_change_issues_create_limit_default.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeIssuesCreateLimitDefault < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :application_settings, :issues_create_limit, from: 300, to: 0
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :application_settings, :issues_create_limit, from: 0, to: 300
- end
- end
-end
diff --git a/db/migrate/20200710113437_add_container_registry_delete_tags_service_timeout_to_application_settings.rb b/db/migrate/20200710113437_add_container_registry_delete_tags_service_timeout_to_application_settings.rb
deleted file mode 100644
index d3865db2e18..00000000000
--- a/db/migrate/20200710113437_add_container_registry_delete_tags_service_timeout_to_application_settings.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddContainerRegistryDeleteTagsServiceTimeoutToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column(
- :application_settings,
- :container_registry_delete_tags_service_timeout,
- :integer,
- default: 250,
- null: false
- )
- end
-
- def down
- remove_column(:application_settings, :container_registry_delete_tags_service_timeout)
- end
-end
diff --git a/db/migrate/20200710130234_add_limit_constraints_to_project_incident_management_settings_token.rb b/db/migrate/20200710130234_add_limit_constraints_to_project_incident_management_settings_token.rb
deleted file mode 100644
index 8af927d0959..00000000000
--- a/db/migrate/20200710130234_add_limit_constraints_to_project_incident_management_settings_token.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddLimitConstraintsToProjectIncidentManagementSettingsToken < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_check_constraint :project_incident_management_settings, 'octet_length(encrypted_pagerduty_token) <= 255', 'pagerduty_token_length_constraint'
- add_check_constraint :project_incident_management_settings, 'octet_length(encrypted_pagerduty_token_iv) <= 12', 'pagerduty_token_iv_length_constraint'
- end
-
- def down
- remove_check_constraint :project_incident_management_settings, 'pagerduty_token_length_constraint'
- remove_check_constraint :project_incident_management_settings, 'pagerduty_token_iv_length_constraint'
- end
-end
diff --git a/db/migrate/20200710152642_add_verification_state_to_terraform_states.rb b/db/migrate/20200710152642_add_verification_state_to_terraform_states.rb
deleted file mode 100644
index 71c14faab0c..00000000000
--- a/db/migrate/20200710152642_add_verification_state_to_terraform_states.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddVerificationStateToTerraformStates < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_table(:terraform_states) do |t|
- t.column :verification_retry_at, :datetime_with_timezone
- t.column :verified_at, :datetime_with_timezone
- t.integer :verification_retry_count, limit: 2
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in 20200710153009_add_verification_failure_limit_and_index_to_terraform_states
- t.text :verification_failure
- # rubocop:enable Migration/AddLimitToTextColumns
- end
- end
-end
diff --git a/db/migrate/20200710153009_add_verification_failure_limit_and_index_to_terraform_states.rb b/db/migrate/20200710153009_add_verification_failure_limit_and_index_to_terraform_states.rb
deleted file mode 100644
index 9d36a8faf4f..00000000000
--- a/db/migrate/20200710153009_add_verification_failure_limit_and_index_to_terraform_states.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddVerificationFailureLimitAndIndexToTerraformStates < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :terraform_states, :verification_failure, where: "(verification_failure IS NOT NULL)", name: "terraform_states_verification_failure_partial"
- add_concurrent_index :terraform_states, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: "terraform_states_verification_checksum_partial"
- add_text_limit :terraform_states, :verification_failure, 255
- end
-
- def down
- remove_concurrent_index :terraform_states, :verification_failure
- remove_concurrent_index :terraform_states, :verification_checksum
- remove_text_limit :terraform_states, :verification_failure
- end
-end
diff --git a/db/migrate/20200712084655_create_dast_sites.rb b/db/migrate/20200712084655_create_dast_sites.rb
deleted file mode 100644
index fc8d423ffb2..00000000000
--- a/db/migrate/20200712084655_create_dast_sites.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDastSites < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- create_table :dast_sites do |t|
- t.references :project, foreign_key: { on_delete: :cascade }, null: false, index: false
- t.timestamps_with_timezone null: false
-
- t.text :url, null: false
- end
- end
-
- add_concurrent_index :dast_sites, [:project_id, :url], unique: true
- add_text_limit :dast_sites, :url, 255
- end
-
- def down
- drop_table :dast_sites
- end
-end
diff --git a/db/migrate/20200712235622_create_dast_site_profiles.rb b/db/migrate/20200712235622_create_dast_site_profiles.rb
deleted file mode 100644
index 593cccd450a..00000000000
--- a/db/migrate/20200712235622_create_dast_site_profiles.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDastSiteProfiles < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- create_table :dast_site_profiles do |t|
- t.references :project, foreign_key: { on_delete: :cascade }, null: false, index: false
- t.references :dast_site, foreign_key: { on_delete: :cascade }, null: false
- t.timestamps_with_timezone null: false
-
- t.text :name, null: false
- end
- end
-
- add_concurrent_index :dast_site_profiles, [:project_id, :name], unique: true
- add_text_limit :dast_site_profiles, :name, 255
- end
-
- def down
- drop_table :dast_site_profiles
- end
-end
diff --git a/db/migrate/20200713141854_add_wiki_page_max_content_bytes_to_application_settings.rb b/db/migrate/20200713141854_add_wiki_page_max_content_bytes_to_application_settings.rb
deleted file mode 100644
index c0763d9816c..00000000000
--- a/db/migrate/20200713141854_add_wiki_page_max_content_bytes_to_application_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddWikiPageMaxContentBytesToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :wiki_page_max_content_bytes, :bigint, default: 50.megabytes, null: false
- end
-end
diff --git a/db/migrate/20200713152443_add_background_migration_job_index_for_partitioning_migrations.rb b/db/migrate/20200713152443_add_background_migration_job_index_for_partitioning_migrations.rb
deleted file mode 100644
index 5ca9b6536ee..00000000000
--- a/db/migrate/20200713152443_add_background_migration_job_index_for_partitioning_migrations.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddBackgroundMigrationJobIndexForPartitioningMigrations < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- INDEX_NAME = 'index_background_migration_jobs_for_partitioning_migrations'
-
- def up
- # rubocop:disable Migration/AddIndex
- add_index :background_migration_jobs, '((arguments ->> 2))', name: INDEX_NAME,
- where: "class_name = 'Gitlab::Database::PartitioningMigrationHelpers::BackfillPartitionedTable'"
- # rubocop:enable Migration/AddIndex
- end
-
- def down
- remove_index :background_migration_jobs, name: INDEX_NAME # rubocop:disable Migration/RemoveIndex
- end
-end
diff --git a/db/migrate/20200715124210_add_target_details_to_audit_event.rb b/db/migrate/20200715124210_add_target_details_to_audit_event.rb
deleted file mode 100644
index 65efe24a1e8..00000000000
--- a/db/migrate/20200715124210_add_target_details_to_audit_event.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddTargetDetailsToAuditEvent < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- # rubocop:disable Migration/AddLimitToTextColumns
- add_column(:audit_events, :target_details, :text)
- # rubocop:enable Migration/AddLimitToTextColumns
- end
- end
-
- def down
- with_lock_retries do
- remove_column(:audit_events, :target_details)
- end
- end
-end
diff --git a/db/migrate/20200715135130_create_vulnerability_historical_statistics.rb b/db/migrate/20200715135130_create_vulnerability_historical_statistics.rb
deleted file mode 100644
index 6afa123c341..00000000000
--- a/db/migrate/20200715135130_create_vulnerability_historical_statistics.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-class CreateVulnerabilityHistoricalStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- INDEX_NAME = 'index_vuln_historical_statistics_on_project_id_and_date'
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :vulnerability_historical_statistics do |t|
- t.timestamps_with_timezone null: false
- t.references :project, null: false, index: false, foreign_key: { on_delete: :cascade }
- t.integer :total, default: 0, null: false
- t.integer :critical, default: 0, null: false
- t.integer :high, default: 0, null: false
- t.integer :medium, default: 0, null: false
- t.integer :low, default: 0, null: false
- t.integer :unknown, default: 0, null: false
- t.integer :info, default: 0, null: false
- t.date :date, null: false
- t.integer :letter_grade, limit: 1, null: false
- t.index [:project_id, :date], unique: true, name: INDEX_NAME
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :vulnerability_historical_statistics
- end
- end
-end
diff --git a/db/migrate/20200715171155_add_deployment_type_to_tracker.rb b/db/migrate/20200715171155_add_deployment_type_to_tracker.rb
deleted file mode 100644
index 649331ecb54..00000000000
--- a/db/migrate/20200715171155_add_deployment_type_to_tracker.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddDeploymentTypeToTracker < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :jira_tracker_data, :deployment_type, :smallint, default: 0, null: false
- end
-end
diff --git a/db/migrate/20200715202659_add_index_on_package_files_file_store.rb b/db/migrate/20200715202659_add_index_on_package_files_file_store.rb
deleted file mode 100644
index 92e8364d22c..00000000000
--- a/db/migrate/20200715202659_add_index_on_package_files_file_store.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnPackageFilesFileStore < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :packages_package_files, :file_store
- end
-
- def down
- remove_concurrent_index :packages_package_files, :file_store
- end
-end
diff --git a/db/migrate/20200716044023_add_entity_path_to_audit_events.rb b/db/migrate/20200716044023_add_entity_path_to_audit_events.rb
deleted file mode 100644
index d16bfaa0beb..00000000000
--- a/db/migrate/20200716044023_add_entity_path_to_audit_events.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddEntityPathToAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- # rubocop:disable Migration/AddLimitToTextColumns
- add_column(:audit_events, :entity_path, :text)
- # rubocop:enable Migration/AddLimitToTextColumns
- end
- end
-
- def down
- with_lock_retries do
- remove_column(:audit_events, :entity_path)
- end
- end
-end
diff --git a/db/migrate/20200716120000_partition_audit_events.rb b/db/migrate/20200716120000_partition_audit_events.rb
deleted file mode 100644
index aef090339ea..00000000000
--- a/db/migrate/20200716120000_partition_audit_events.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class PartitionAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- include Gitlab::Database::PartitioningMigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- partition_table_by_date :audit_events, :created_at
- end
-
- def down
- drop_partitioned_table_for :audit_events
- end
-end
diff --git a/db/migrate/20200716120419_add_text_limit_on_entity_path_to_audit_events.rb b/db/migrate/20200716120419_add_text_limit_on_entity_path_to_audit_events.rb
deleted file mode 100644
index 0dea811f41c..00000000000
--- a/db/migrate/20200716120419_add_text_limit_on_entity_path_to_audit_events.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitOnEntityPathToAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :audit_events, :entity_path, 5_500
- end
-
- def down
- remove_text_limit :audit_events, :entity_path
- end
-end
diff --git a/db/migrate/20200716145156_add_text_limit_to_audit_event_target_details.rb b/db/migrate/20200716145156_add_text_limit_to_audit_event_target_details.rb
deleted file mode 100644
index 43ee98b69e0..00000000000
--- a/db/migrate/20200716145156_add_text_limit_to_audit_event_target_details.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToAuditEventTargetDetails < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :audit_events, :target_details, 5_500
- end
-
- def down
- remove_text_limit :audit_events, :target_details
- end
-end
diff --git a/db/migrate/20200717040735_change_aws_roles_role_arn_null.rb b/db/migrate/20200717040735_change_aws_roles_role_arn_null.rb
deleted file mode 100644
index 707cfe96a7c..00000000000
--- a/db/migrate/20200717040735_change_aws_roles_role_arn_null.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeAwsRolesRoleArnNull < ActiveRecord::Migration[6.0]
- DOWNTIME = false
- EXAMPLE_ARN = 'arn:aws:iam::000000000000:role/example-role'
-
- def up
- change_column_null :aws_roles, :role_arn, true
- end
-
- def down
- # Records may now exist with nulls, so we must fill them with a dummy value
- change_column_null :aws_roles, :role_arn, false, EXAMPLE_ARN
- end
-end
diff --git a/db/migrate/20200717080257_add_prevent_forking_to_namespace_settings.rb b/db/migrate/20200717080257_add_prevent_forking_to_namespace_settings.rb
deleted file mode 100644
index b46daac6a98..00000000000
--- a/db/migrate/20200717080257_add_prevent_forking_to_namespace_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddPreventForkingToNamespaceSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :namespace_settings, :prevent_forking_outside_group, :boolean, null: false, default: false
- end
-end
diff --git a/db/migrate/20200717163656_add_moved_project_to_notification_settings.rb b/db/migrate/20200717163656_add_moved_project_to_notification_settings.rb
deleted file mode 100644
index 9c60a678c1f..00000000000
--- a/db/migrate/20200717163656_add_moved_project_to_notification_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddMovedProjectToNotificationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :notification_settings, :moved_project, :boolean, default: true, null: false
- end
-end
diff --git a/db/migrate/20200718040100_add_index_on_merge_request_diffs_external_diff_store.rb b/db/migrate/20200718040100_add_index_on_merge_request_diffs_external_diff_store.rb
deleted file mode 100644
index 372a9df82a1..00000000000
--- a/db/migrate/20200718040100_add_index_on_merge_request_diffs_external_diff_store.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnMergeRequestDiffsExternalDiffStore < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :merge_request_diffs, :external_diff_store
- end
-
- def down
- remove_concurrent_index :merge_request_diffs, :external_diff_store
- end
-end
diff --git a/db/migrate/20200718040200_add_index_on_terraform_states_file_store.rb b/db/migrate/20200718040200_add_index_on_terraform_states_file_store.rb
deleted file mode 100644
index 7dddcf1fcea..00000000000
--- a/db/migrate/20200718040200_add_index_on_terraform_states_file_store.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnTerraformStatesFileStore < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :terraform_states, :file_store
- end
-
- def down
- remove_concurrent_index :terraform_states, :file_store
- end
-end
diff --git a/db/migrate/20200718040300_add_index_on_vulnerability_exports_file_store.rb b/db/migrate/20200718040300_add_index_on_vulnerability_exports_file_store.rb
deleted file mode 100644
index c0d546ae112..00000000000
--- a/db/migrate/20200718040300_add_index_on_vulnerability_exports_file_store.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnVulnerabilityExportsFileStore < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :vulnerability_exports, :file_store
- end
-
- def down
- remove_concurrent_index :vulnerability_exports, :file_store
- end
-end
diff --git a/db/migrate/20200720053909_add_elasticsearch_indexed_file_size_limit_kb_to_application_settings.rb b/db/migrate/20200720053909_add_elasticsearch_indexed_file_size_limit_kb_to_application_settings.rb
deleted file mode 100644
index bab5fe827d0..00000000000
--- a/db/migrate/20200720053909_add_elasticsearch_indexed_file_size_limit_kb_to_application_settings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddElasticsearchIndexedFileSizeLimitKbToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings,
- :elasticsearch_indexed_file_size_limit_kb,
- :integer,
- null: false,
- default: 1024 # 1 MiB (units in KiB)
- end
-end
diff --git a/db/migrate/20200720154007_create_vulnerabilities_export_verification_status.rb b/db/migrate/20200720154007_create_vulnerabilities_export_verification_status.rb
deleted file mode 100644
index 5cbb5fdd1e5..00000000000
--- a/db/migrate/20200720154007_create_vulnerabilities_export_verification_status.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-class CreateVulnerabilitiesExportVerificationStatus < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:vulnerability_export_verification_status)
- with_lock_retries do
- create_table :vulnerability_export_verification_status, id: false do |t|
- t.references :vulnerability_export,
- primary_key: true,
- null: false,
- foreign_key: { on_delete: :cascade },
- index:
- { name: 'index_vulnerability_export_verification_status_on_export_id' }
- t.datetime_with_timezone :verification_retry_at
- t.datetime_with_timezone :verified_at
- t.integer :verification_retry_count, limit: 2
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
- t.text :verification_failure
-
- t.index :verification_failure, where: "(verification_failure IS NOT NULL)", name: "vulnerability_exports_verification_failure_partial"
- t.index :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: "vulnerability_exports_verification_checksum_partial"
- end
- end
- end
-
- add_text_limit :vulnerability_export_verification_status, :verification_failure, 255
- end
-
- def down
- return unless table_exists?(:vulnerability_export_verification_status)
-
- with_lock_retries do
- drop_table :vulnerability_export_verification_status
- end
- end
-end
diff --git a/db/migrate/20200720154123_add_external_to_custom_emoji.rb b/db/migrate/20200720154123_add_external_to_custom_emoji.rb
deleted file mode 100644
index 2a97235eec4..00000000000
--- a/db/migrate/20200720154123_add_external_to_custom_emoji.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddExternalToCustomEmoji < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :custom_emoji, :external, :boolean, default: true, null: false
- end
-end
diff --git a/db/migrate/20200720191134_add_blocking_issues_count_to_issues.rb b/db/migrate/20200720191134_add_blocking_issues_count_to_issues.rb
deleted file mode 100644
index dbb43541ad6..00000000000
--- a/db/migrate/20200720191134_add_blocking_issues_count_to_issues.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class AddBlockingIssuesCountToIssues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_issue_on_project_id_state_id_and_blocking_issues_count'
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:issues, :blocking_issues_count)
- with_lock_retries do
- add_column :issues, :blocking_issues_count, :integer, default: 0, null: false
- end
- end
-
- add_concurrent_index :issues, [:project_id, :state_id, :blocking_issues_count], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :issues, INDEX_NAME
-
- with_lock_retries do
- remove_column :issues, :blocking_issues_count
- end
- end
-end
diff --git a/db/migrate/20200721034536_add_issue_type_to_issues.rb b/db/migrate/20200721034536_add_issue_type_to_issues.rb
deleted file mode 100644
index 96ae8c421da..00000000000
--- a/db/migrate/20200721034536_add_issue_type_to_issues.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddIssueTypeToIssues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- # Set default to issue type
- add_column :issues, :issue_type, :integer, limit: 2, default: 0, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :issues, :issue_type
- end
- end
-end
diff --git a/db/migrate/20200721043502_add_issue_type_index_to_issues.rb b/db/migrate/20200721043502_add_issue_type_index_to_issues.rb
deleted file mode 100644
index 2faad98d032..00000000000
--- a/db/migrate/20200721043502_add_issue_type_index_to_issues.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIssueTypeIndexToIssues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- INCIDENT_TYPE = 1
- INDEX_NAME = 'index_issues_on_incident_issue_type'
-
- def up
- add_concurrent_index :issues,
- :issue_type, where: "issue_type = #{INCIDENT_TYPE}",
- name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :issues, :issue_type
- end
-end
diff --git a/db/migrate/20200721052853_create_dast_scanner_profile.rb b/db/migrate/20200721052853_create_dast_scanner_profile.rb
deleted file mode 100644
index 0dc0012d837..00000000000
--- a/db/migrate/20200721052853_create_dast_scanner_profile.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDastScannerProfile < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:dast_scanner_profiles)
- with_lock_retries do
- create_table :dast_scanner_profiles do |t|
- t.timestamps_with_timezone null: false
- t.references :project, null: false, index: false, foreign_key: { on_delete: :cascade }, type: :integer
- t.integer :spider_timeout, limit: 2
- t.integer :target_timeout, limit: 2
- t.text :name, null: false
- t.index [:project_id, :name], unique: true
- end
- end
- end
-
- add_text_limit(:dast_scanner_profiles, :name, 255)
- end
-
- def down
- with_lock_retries do
- drop_table :dast_scanner_profiles
- end
- end
-end
diff --git a/db/migrate/20200721230558_add_index_to_projects_aimed_for_deletion.rb b/db/migrate/20200721230558_add_index_to_projects_aimed_for_deletion.rb
deleted file mode 100644
index 44dfe2ff3e1..00000000000
--- a/db/migrate/20200721230558_add_index_to_projects_aimed_for_deletion.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToProjectsAimedForDeletion < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- PROJECTS_AIMED_FOR_DELETION_INDEX_NAME = "index_projects_aimed_for_deletion"
- MARKED_FOR_DELETION_PROJECTS_INDEX_NAME = "index_projects_on_marked_for_deletion_at"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects,
- :marked_for_deletion_at,
- where: "marked_for_deletion_at IS NOT NULL AND pending_delete = false",
- name: PROJECTS_AIMED_FOR_DELETION_INDEX_NAME
-
- remove_concurrent_index_by_name :projects, MARKED_FOR_DELETION_PROJECTS_INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :projects, PROJECTS_AIMED_FOR_DELETION_INDEX_NAME
-
- add_concurrent_index :projects, :marked_for_deletion_at, where: 'marked_for_deletion_at IS NOT NULL'
- end
-end
diff --git a/db/migrate/20200722075411_add_ci_needs_size_limit_to_plan_limit.rb b/db/migrate/20200722075411_add_ci_needs_size_limit_to_plan_limit.rb
deleted file mode 100644
index b615a09a61b..00000000000
--- a/db/migrate/20200722075411_add_ci_needs_size_limit_to_plan_limit.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddCiNeedsSizeLimitToPlanLimit < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :plan_limits, :ci_needs_size_limit, :integer, default: 50, null: false
- end
-end
diff --git a/db/migrate/20200722084623_add_default_membership_role_to_saml_provider.rb b/db/migrate/20200722084623_add_default_membership_role_to_saml_provider.rb
deleted file mode 100644
index bd82aab1aae..00000000000
--- a/db/migrate/20200722084623_add_default_membership_role_to_saml_provider.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultMembershipRoleToSamlProvider < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- GUEST_USER_ROLE = 10
-
- def change
- add_column :saml_providers, :default_membership_role, :smallint, default: GUEST_USER_ROLE, null: false
- end
-end
diff --git a/db/migrate/20200722091435_add_relative_position_to_design_management_designs.rb b/db/migrate/20200722091435_add_relative_position_to_design_management_designs.rb
deleted file mode 100644
index 42b7a1d3898..00000000000
--- a/db/migrate/20200722091435_add_relative_position_to_design_management_designs.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddRelativePositionToDesignManagementDesigns < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :design_management_designs, :relative_position, :integer
- end
-end
diff --git a/db/migrate/20200722131241_create_resource_iteration_events_table.rb b/db/migrate/20200722131241_create_resource_iteration_events_table.rb
deleted file mode 100644
index 619faeaaadf..00000000000
--- a/db/migrate/20200722131241_create_resource_iteration_events_table.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class CreateResourceIterationEventsTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :resource_iteration_events do |t|
- t.bigint :user_id, null: false, index: { name: 'index_resource_iteration_events_on_user_id' }
- t.bigint :issue_id, null: true, index: { name: 'index_resource_iteration_events_on_issue_id' }
- t.bigint :merge_request_id, null: true, index: { name: 'index_resource_iteration_events_on_merge_request_id' }
- t.bigint :iteration_id, index: { name: 'index_resource_iteration_events_on_iteration_id' }
- t.datetime_with_timezone :created_at, null: false
- t.integer :action, limit: 2, null: false
- end
- end
-end
diff --git a/db/migrate/20200722132040_add_users_fk_to_resource_iteration_events_table.rb b/db/migrate/20200722132040_add_users_fk_to_resource_iteration_events_table.rb
deleted file mode 100644
index c3d95c9dfc2..00000000000
--- a/db/migrate/20200722132040_add_users_fk_to_resource_iteration_events_table.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddUsersFkToResourceIterationEventsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :resource_iteration_events, :users, column: :user_id, on_delete: :nullify
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :resource_iteration_events, column: :user_id
- end
- end
-end
diff --git a/db/migrate/20200722132540_add_issues_fk_to_resource_iteration_events_table.rb b/db/migrate/20200722132540_add_issues_fk_to_resource_iteration_events_table.rb
deleted file mode 100644
index b603f14f62b..00000000000
--- a/db/migrate/20200722132540_add_issues_fk_to_resource_iteration_events_table.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIssuesFkToResourceIterationEventsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :resource_iteration_events, :issues, column: :issue_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :resource_iteration_events, column: :issue_id
- end
- end
-end
diff --git a/db/migrate/20200722133040_add_merge_requests_fk_to_resource_iteration_events_table.rb b/db/migrate/20200722133040_add_merge_requests_fk_to_resource_iteration_events_table.rb
deleted file mode 100644
index e047b157a53..00000000000
--- a/db/migrate/20200722133040_add_merge_requests_fk_to_resource_iteration_events_table.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddMergeRequestsFkToResourceIterationEventsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :resource_iteration_events, :merge_requests, column: :merge_request_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :resource_iteration_events, column: :merge_request_id
- end
- end
-end
diff --git a/db/migrate/20200722133540_add_iterations_fk_to_resource_iteration_events_table.rb b/db/migrate/20200722133540_add_iterations_fk_to_resource_iteration_events_table.rb
deleted file mode 100644
index 1bb3ac7c8bd..00000000000
--- a/db/migrate/20200722133540_add_iterations_fk_to_resource_iteration_events_table.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIterationsFkToResourceIterationEventsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :resource_iteration_events, :sprints, column: :iteration_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :resource_iteration_events, column: :iteration_id
- end
- end
-end
diff --git a/db/migrate/20200723125205_add_target_project_id_to_mr_metrics.rb b/db/migrate/20200723125205_add_target_project_id_to_mr_metrics.rb
deleted file mode 100644
index fb01b3fe046..00000000000
--- a/db/migrate/20200723125205_add_target_project_id_to_mr_metrics.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddTargetProjectIdToMrMetrics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :merge_request_metrics, :target_project_id, :integer
- end
- end
-
- def down
- with_lock_retries do
- remove_column :merge_request_metrics, :target_project_id, :integer
- end
- end
-end
diff --git a/db/migrate/20200723128332_add_fk_to_metrics_target_project_id.rb b/db/migrate/20200723128332_add_fk_to_metrics_target_project_id.rb
deleted file mode 100644
index 6536b20b9c1..00000000000
--- a/db/migrate/20200723128332_add_fk_to_metrics_target_project_id.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddFkToMetricsTargetProjectId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:merge_request_metrics, :target_project_id)
- add_concurrent_foreign_key(:merge_request_metrics, :projects, column: :target_project_id, on_delete: :cascade)
- end
-
- def down
- remove_foreign_key(:merge_request_metrics, column: :target_project_id)
- remove_concurrent_index(:merge_request_metrics, :target_project_id)
- end
-end
diff --git a/db/migrate/20200724100123_add_index_on_vulnerability_historical_statistics_date.rb b/db/migrate/20200724100123_add_index_on_vulnerability_historical_statistics_date.rb
deleted file mode 100644
index 696f98b40f6..00000000000
--- a/db/migrate/20200724100123_add_index_on_vulnerability_historical_statistics_date.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnVulnerabilityHistoricalStatisticsDate < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :vulnerability_historical_statistics, [:date, :id]
- end
-
- def down
- remove_concurrent_index :vulnerability_historical_statistics, [:date, :id]
- end
-end
diff --git a/db/migrate/20200727082309_remove_index_chat_name_service_id.rb b/db/migrate/20200727082309_remove_index_chat_name_service_id.rb
deleted file mode 100644
index 49cda2dd41f..00000000000
--- a/db/migrate/20200727082309_remove_index_chat_name_service_id.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexChatNameServiceId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index :chat_names, :service_id
- end
-
- def down
- add_concurrent_index :chat_names, :service_id
- end
-end
diff --git a/db/migrate/20200727142337_update_defaults_for_sca_artifacts.rb b/db/migrate/20200727142337_update_defaults_for_sca_artifacts.rb
deleted file mode 100644
index d745943a7d3..00000000000
--- a/db/migrate/20200727142337_update_defaults_for_sca_artifacts.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateDefaultsForScaArtifacts < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- DEPENDENCY_SCANNING_LIMIT_MB = 350
- CONTAINER_SCANNING_LIMIT_MB = 150
- LICENSE_SCANNING_LIMIT_MB = 100
-
- def up
- change_column_default :plan_limits, :ci_max_artifact_size_dependency_scanning, DEPENDENCY_SCANNING_LIMIT_MB
- change_column_default :plan_limits, :ci_max_artifact_size_container_scanning, CONTAINER_SCANNING_LIMIT_MB
- change_column_default :plan_limits, :ci_max_artifact_size_license_scanning, LICENSE_SCANNING_LIMIT_MB
- end
-
- def down
- change_column_default :plan_limits, :ci_max_artifact_size_dependency_scanning, 0
- change_column_default :plan_limits, :ci_max_artifact_size_container_scanning, 0
- change_column_default :plan_limits, :ci_max_artifact_size_license_scanning, 0
- end
-end
diff --git a/db/migrate/20200728080250_replace_unique_index_on_cycle_analytics_stages.rb b/db/migrate/20200728080250_replace_unique_index_on_cycle_analytics_stages.rb
deleted file mode 100644
index 0e562ae27e2..00000000000
--- a/db/migrate/20200728080250_replace_unique_index_on_cycle_analytics_stages.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-class ReplaceUniqueIndexOnCycleAnalyticsStages < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- OLD_INDEX_NAME = 'index_analytics_ca_group_stages_on_group_id_and_name'
- NEW_INDEX_NAME = 'index_group_stages_on_group_id_group_value_stream_id_and_name'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:analytics_cycle_analytics_group_stages,
- [:group_id, :group_value_stream_id, :name],
- unique: true,
- name: NEW_INDEX_NAME)
-
- remove_concurrent_index_by_name :analytics_cycle_analytics_group_stages, OLD_INDEX_NAME
- end
-
- def down
- # Removing duplicated records (group_id, name) that would prevent re-creating the old index.
- execute <<-SQL
- DELETE FROM analytics_cycle_analytics_group_stages
- USING (
- SELECT group_id, name, MIN(id) as min_id
- FROM analytics_cycle_analytics_group_stages
- GROUP BY group_id, name
- HAVING COUNT(id) > 1
- ) as analytics_cycle_analytics_group_stages_name_duplicates
- WHERE analytics_cycle_analytics_group_stages_name_duplicates.group_id = analytics_cycle_analytics_group_stages.group_id
- AND analytics_cycle_analytics_group_stages_name_duplicates.name = analytics_cycle_analytics_group_stages.name
- AND analytics_cycle_analytics_group_stages_name_duplicates.min_id <> analytics_cycle_analytics_group_stages.id
- SQL
-
- add_concurrent_index(:analytics_cycle_analytics_group_stages,
- [:group_id, :name],
- unique: true,
- name: OLD_INDEX_NAME)
-
- remove_concurrent_index_by_name :analytics_cycle_analytics_group_stages, NEW_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200728163009_add_deployment_events_to_web_hooks.rb b/db/migrate/20200728163009_add_deployment_events_to_web_hooks.rb
deleted file mode 100644
index b1bf9560bcc..00000000000
--- a/db/migrate/20200728163009_add_deployment_events_to_web_hooks.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddDeploymentEventsToWebHooks < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :web_hooks, :deployment_events, :boolean, null: false, default: false
- end
-end
diff --git a/db/migrate/20200728174137_add_index_on_design_management_designs_issue_id_and_relative_position_and_id.rb b/db/migrate/20200728174137_add_index_on_design_management_designs_issue_id_and_relative_position_and_id.rb
deleted file mode 100644
index 140c344e837..00000000000
--- a/db/migrate/20200728174137_add_index_on_design_management_designs_issue_id_and_relative_position_and_id.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnDesignManagementDesignsIssueIdAndRelativePositionAndId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_design_management_designs_issue_id_relative_position_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :design_management_designs, [:issue_id, :relative_position, :id], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :design_management_designs, [:issue_id, :relative_position, :id], name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20200728175710_add_enforce_namespace_storage_limit_to_application_settings.rb b/db/migrate/20200728175710_add_enforce_namespace_storage_limit_to_application_settings.rb
deleted file mode 100644
index adbc86ec621..00000000000
--- a/db/migrate/20200728175710_add_enforce_namespace_storage_limit_to_application_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddEnforceNamespaceStorageLimitToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :enforce_namespace_storage_limit, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20200728182311_add_o_auth_paths_to_protected_paths.rb b/db/migrate/20200728182311_add_o_auth_paths_to_protected_paths.rb
deleted file mode 100644
index 7a5af0135fa..00000000000
--- a/db/migrate/20200728182311_add_o_auth_paths_to_protected_paths.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-class AddOAuthPathsToProtectedPaths < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- ADD_PROTECTED_PATHS = [
- '/oauth/authorize',
- '/oauth/token'
- ].freeze
-
- EXISTING_DEFAULT_PROTECTED_PATHS = [
- '/users/password',
- '/users/sign_in',
- '/api/v3/session.json',
- '/api/v3/session',
- '/api/v4/session.json',
- '/api/v4/session',
- '/users',
- '/users/confirmation',
- '/unsubscribes/',
- '/import/github/personal_access_token',
- '/admin/session'
- ].freeze
-
- NEW_DEFAULT_PROTECTED_PATHS = (EXISTING_DEFAULT_PROTECTED_PATHS + ADD_PROTECTED_PATHS).freeze
-
- class ApplicationSetting < ActiveRecord::Base
- self.table_name = 'application_settings'
- end
-
- def up
- change_column_default :application_settings, :protected_paths, NEW_DEFAULT_PROTECTED_PATHS
-
- ApplicationSetting.reset_column_information
-
- ApplicationSetting.where.not(protected_paths: nil).each do |application_setting|
- missing_paths = ADD_PROTECTED_PATHS - application_setting.protected_paths
-
- next if missing_paths.empty?
-
- updated_protected_paths = application_setting.protected_paths + missing_paths
- application_setting.update!(protected_paths: updated_protected_paths)
- end
- end
-
- def down
- change_column_default :application_settings, :protected_paths, EXISTING_DEFAULT_PROTECTED_PATHS
-
- ApplicationSetting.reset_column_information
-
- ApplicationSetting.where.not(protected_paths: nil).each do |application_setting|
- paths_to_remove = application_setting.protected_paths - EXISTING_DEFAULT_PROTECTED_PATHS
-
- next if paths_to_remove.empty?
-
- updated_protected_paths = application_setting.protected_paths - paths_to_remove
- application_setting.update!(protected_paths: updated_protected_paths)
- end
- end
-end
diff --git a/db/migrate/20200729151021_add_after_expiry_notification_delivered_to_personal_access_tokens.rb b/db/migrate/20200729151021_add_after_expiry_notification_delivered_to_personal_access_tokens.rb
deleted file mode 100644
index 001436b7285..00000000000
--- a/db/migrate/20200729151021_add_after_expiry_notification_delivered_to_personal_access_tokens.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddAfterExpiryNotificationDeliveredToPersonalAccessTokens < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def change
- add_column :personal_access_tokens, :after_expiry_notification_delivered, :boolean, null: false, default: false
- end
-end
diff --git a/db/migrate/20200729175935_add_dashboard_path_to_prometheus_metrics.rb b/db/migrate/20200729175935_add_dashboard_path_to_prometheus_metrics.rb
deleted file mode 100644
index 0562e8d1c14..00000000000
--- a/db/migrate/20200729175935_add_dashboard_path_to_prometheus_metrics.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class AddDashboardPathToPrometheusMetrics < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- # Text limit is added in 20200730210506_add_text_limit_to_dashboard_path
- add_column :prometheus_metrics, :dashboard_path, :text # rubocop:disable Migration/AddLimitToTextColumns
- end
-
- def down
- remove_column :prometheus_metrics, :dashboard_path
- end
-end
diff --git a/db/migrate/20200729180539_add_can_push_to_group_deploy_keys_groups.rb b/db/migrate/20200729180539_add_can_push_to_group_deploy_keys_groups.rb
deleted file mode 100644
index 3412790c20c..00000000000
--- a/db/migrate/20200729180539_add_can_push_to_group_deploy_keys_groups.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddCanPushToGroupDeployKeysGroups < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :group_deploy_keys_groups, :can_push, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20200729181641_add_index_to_resource_milestone_events_add_events.rb b/db/migrate/20200729181641_add_index_to_resource_milestone_events_add_events.rb
deleted file mode 100644
index 438f9c6bfa3..00000000000
--- a/db/migrate/20200729181641_add_index_to_resource_milestone_events_add_events.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToResourceMilestoneEventsAddEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'index_resource_milestone_events_on_milestone_id_and_add_action'
- ADD_ACTION = '1'
-
- def up
- # Index add milestone events
- add_concurrent_index :resource_milestone_events, :milestone_id, where: "action = #{ADD_ACTION}", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :resource_milestone_events, :milestone_id, name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20200729191227_add_runbook_to_prometheus_alert.rb b/db/migrate/20200729191227_add_runbook_to_prometheus_alert.rb
deleted file mode 100644
index a45b6eab1ee..00000000000
--- a/db/migrate/20200729191227_add_runbook_to_prometheus_alert.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class AddRunbookToPrometheusAlert < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- # limit is added in 20200501000002_add_text_limit_to_sprints_extended_title
- add_column :prometheus_alerts, :runbook_url, :text # rubocop:disable Migration/AddLimitToTextColumns
- end
-
- def down
- remove_column :prometheus_alerts, :runbook_url
- end
-end
diff --git a/db/migrate/20200729200808_add_text_limit_to_runbook_on_prometheus_alerts.rb b/db/migrate/20200729200808_add_text_limit_to_runbook_on_prometheus_alerts.rb
deleted file mode 100644
index 010b53ab35e..00000000000
--- a/db/migrate/20200729200808_add_text_limit_to_runbook_on_prometheus_alerts.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToRunbookOnPrometheusAlerts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :prometheus_alerts, :runbook_url, 255
- end
-
- def down
- remove_text_limit :prometheus_alerts, :runbook_url
- end
-end
diff --git a/db/migrate/20200729202222_add_index_to_ci_pipeline_project_id_created_at.rb b/db/migrate/20200729202222_add_index_to_ci_pipeline_project_id_created_at.rb
deleted file mode 100644
index d1ee9c49d30..00000000000
--- a/db/migrate/20200729202222_add_index_to_ci_pipeline_project_id_created_at.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToCiPipelineProjectIdCreatedAt < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_pipelines, [:project_id, :created_at]
- end
-
- def down
- remove_concurrent_index :ci_pipelines, [:project_id, :created_at]
- end
-end
diff --git a/db/migrate/20200730044810_add_indexes_to_resource_label_events_to_support_vsa.rb b/db/migrate/20200730044810_add_indexes_to_resource_label_events_to_support_vsa.rb
deleted file mode 100644
index ba114e81618..00000000000
--- a/db/migrate/20200730044810_add_indexes_to_resource_label_events_to_support_vsa.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexesToResourceLabelEventsToSupportVsa < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- NEW_INDEX_NAME_ON_ISSUE_ID = 'index_resource_label_events_issue_id_label_id_action'
- OLD_INDEX_NAME_ON_ISSUE_ID = 'index_resource_label_events_on_issue_id'
-
- NEW_INDEX_NAME_ON_MERGE_REQUEST_ID = 'index_resource_label_events_on_merge_request_id_label_id_action'
- OLD_INDEX_NAME_ON_MERGE_REQUEST_ID = 'index_resource_label_events_on_merge_request_id'
-
- def up
- add_concurrent_index :resource_label_events, [:issue_id, :label_id, :action], name: NEW_INDEX_NAME_ON_ISSUE_ID
- remove_concurrent_index_by_name :resource_label_events, OLD_INDEX_NAME_ON_ISSUE_ID
-
- add_concurrent_index :resource_label_events, [:merge_request_id, :label_id, :action], name: NEW_INDEX_NAME_ON_MERGE_REQUEST_ID
- remove_concurrent_index_by_name :resource_label_events, OLD_INDEX_NAME_ON_MERGE_REQUEST_ID
- end
-
- def down
- add_concurrent_index :resource_label_events, :issue_id, name: OLD_INDEX_NAME_ON_ISSUE_ID
- remove_concurrent_index_by_name(:resource_label_events, NEW_INDEX_NAME_ON_ISSUE_ID)
-
- add_concurrent_index :resource_label_events, :merge_request_id, name: OLD_INDEX_NAME_ON_MERGE_REQUEST_ID
- remove_concurrent_index_by_name(:resource_label_events, NEW_INDEX_NAME_ON_MERGE_REQUEST_ID)
- end
-end
diff --git a/db/migrate/20200730083043_replace_index_for_service_usage_data.rb b/db/migrate/20200730083043_replace_index_for_service_usage_data.rb
deleted file mode 100644
index 0d3012c319d..00000000000
--- a/db/migrate/20200730083043_replace_index_for_service_usage_data.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class ReplaceIndexForServiceUsageData < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- OLD_INDEX_NAME = 'index_services_on_type_and_id_and_template_when_active'
- NEW_INDEX_NAME = 'index_services_on_type_id_when_active_not_instance_not_template'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :services, [:type, :id], where: 'active = TRUE AND instance = FALSE AND template = FALSE', name: NEW_INDEX_NAME
-
- remove_concurrent_index_by_name :services, OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :services, [:type, :id, :template], where: 'active = TRUE', name: OLD_INDEX_NAME
-
- remove_concurrent_index :services, NEW_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200730131946_add_hide_lists_to_boards.rb b/db/migrate/20200730131946_add_hide_lists_to_boards.rb
deleted file mode 100644
index e431ea852a7..00000000000
--- a/db/migrate/20200730131946_add_hide_lists_to_boards.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class AddHideListsToBoards < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :boards, :hide_backlog_list, :boolean, default: false, null: false
- add_column :boards, :hide_closed_list, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20200730210506_add_text_limit_to_dashboard_path.rb b/db/migrate/20200730210506_add_text_limit_to_dashboard_path.rb
deleted file mode 100644
index a236cc68988..00000000000
--- a/db/migrate/20200730210506_add_text_limit_to_dashboard_path.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToDashboardPath < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit(:prometheus_metrics, :dashboard_path, 2048)
- end
-
- def down
- remove_text_limit(:prometheus_metrics, :dashboard_path)
- end
-end
diff --git a/db/migrate/20200731085019_create_experiment.rb b/db/migrate/20200731085019_create_experiment.rb
deleted file mode 100644
index cd326e0958f..00000000000
--- a/db/migrate/20200731085019_create_experiment.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class CreateExperiment < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:experiments)
- create_table :experiments do |t|
- t.text :name, null: false
-
- t.index :name, unique: true
- end
- end
-
- add_text_limit :experiments, :name, 255
- end
-
- def down
- drop_table :experiments
- end
-end
diff --git a/db/migrate/20200731090553_create_experiment_user.rb b/db/migrate/20200731090553_create_experiment_user.rb
deleted file mode 100644
index 9080429dfd3..00000000000
--- a/db/migrate/20200731090553_create_experiment_user.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class CreateExperimentUser < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- create_table :experiment_users do |t|
- t.bigint :experiment_id, null: false
- t.bigint :user_id, null: false
- t.integer :group_type, limit: 2, null: false, default: 0
- t.timestamps_with_timezone null: false
- end
-
- add_index :experiment_users, :experiment_id
- add_index :experiment_users, :user_id
- end
-
- def down
- drop_table :experiment_users
- end
-end
diff --git a/db/migrate/20200731201408_add_foreign_key_to_experiment_on_experiment_users.rb b/db/migrate/20200731201408_add_foreign_key_to_experiment_on_experiment_users.rb
deleted file mode 100644
index c1a6dae242b..00000000000
--- a/db/migrate/20200731201408_add_foreign_key_to_experiment_on_experiment_users.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToExperimentOnExperimentUsers < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- # There is no need to use add_concurrent_foreign_key since it's an empty table
- add_foreign_key :experiment_users, :experiments, column: :experiment_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :experiment_users, column: :experiment_id
- end
- end
-end
diff --git a/db/migrate/20200731201834_add_foreign_key_to_user_on_experiment_users.rb b/db/migrate/20200731201834_add_foreign_key_to_user_on_experiment_users.rb
deleted file mode 100644
index 673a0bde0b1..00000000000
--- a/db/migrate/20200731201834_add_foreign_key_to_user_on_experiment_users.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToUserOnExperimentUsers < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- # There is no need to use add_concurrent_foreign_key since it's an empty table
- add_foreign_key :experiment_users, :users, column: :user_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :experiment_users, column: :user_id
- end
- end
-end
diff --git a/db/migrate/20200803111512_add_group_id_to_services.rb b/db/migrate/20200803111512_add_group_id_to_services.rb
deleted file mode 100644
index 7d4a0ef4dd5..00000000000
--- a/db/migrate/20200803111512_add_group_id_to_services.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddGroupIdToServices < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :services, :group_id, :bigint
- end
-end
diff --git a/db/migrate/20200803112806_add_index_group_id_to_services.rb b/db/migrate/20200803112806_add_index_group_id_to_services.rb
deleted file mode 100644
index 145009672ef..00000000000
--- a/db/migrate/20200803112806_add_index_group_id_to_services.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexGroupIdToServices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_services_on_unique_group_id_and_type'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :services, [:group_id, :type], unique: true, name: INDEX_NAME
-
- add_concurrent_foreign_key :services, :namespaces, column: :group_id
- end
-
- def down
- remove_foreign_key_if_exists :services, column: :group_id
-
- remove_concurrent_index_by_name :services, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200803125340_create_raw_usage_data.rb b/db/migrate/20200803125340_create_raw_usage_data.rb
deleted file mode 100644
index f1c23a7b0f5..00000000000
--- a/db/migrate/20200803125340_create_raw_usage_data.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class CreateRawUsageData < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- unless table_exists?(:raw_usage_data)
- create_table :raw_usage_data do |t|
- t.timestamps_with_timezone
- t.datetime_with_timezone :recorded_at, null: false
- t.datetime_with_timezone :sent_at
- t.jsonb :payload, null: false
-
- t.index [:recorded_at], unique: true
- end
- end
- end
-
- def down
- drop_table :raw_usage_data
- end
-end
diff --git a/db/migrate/20200804041018_add_default_value_for_external_diff_store_to_merge_request_diffs.rb b/db/migrate/20200804041018_add_default_value_for_external_diff_store_to_merge_request_diffs.rb
deleted file mode 100644
index 1a565fef125..00000000000
--- a/db/migrate/20200804041018_add_default_value_for_external_diff_store_to_merge_request_diffs.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultValueForExternalDiffStoreToMergeRequestDiffs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :merge_request_diffs, :external_diff_store, 1
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :merge_request_diffs, :external_diff_store, nil
- end
- end
-end
diff --git a/db/migrate/20200804222543_add_resolved_on_default_branch_into_vulnerabilities_table.rb b/db/migrate/20200804222543_add_resolved_on_default_branch_into_vulnerabilities_table.rb
deleted file mode 100644
index afb97871575..00000000000
--- a/db/migrate/20200804222543_add_resolved_on_default_branch_into_vulnerabilities_table.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddResolvedOnDefaultBranchIntoVulnerabilitiesTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_table :vulnerabilities do |t|
- t.boolean :resolved_on_default_branch, default: false, null: false
- end
- end
-end
diff --git a/db/migrate/20200805071842_add_index_on_end_date_and_namespace_id_to_gitlab_subscriptions.rb b/db/migrate/20200805071842_add_index_on_end_date_and_namespace_id_to_gitlab_subscriptions.rb
deleted file mode 100644
index 266b0a50318..00000000000
--- a/db/migrate/20200805071842_add_index_on_end_date_and_namespace_id_to_gitlab_subscriptions.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnEndDateAndNamespaceIdToGitlabSubscriptions < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :gitlab_subscriptions, [:end_date, :namespace_id]
- end
-
- def down
- remove_concurrent_index :gitlab_subscriptions, [:end_date, :namespace_id],
- name: 'index_gitlab_subscriptions_on_end_date_and_namespace_id'
- end
-end
diff --git a/db/migrate/20200805150316_create_ci_pipeline_artifact.rb b/db/migrate/20200805150316_create_ci_pipeline_artifact.rb
deleted file mode 100644
index 01995972011..00000000000
--- a/db/migrate/20200805150316_create_ci_pipeline_artifact.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCiPipelineArtifact < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:ci_pipeline_artifacts)
- create_table :ci_pipeline_artifacts do |t|
- t.timestamps_with_timezone
- t.bigint :pipeline_id, null: false, index: true
- t.bigint :project_id, null: false, index: true
- t.integer :size, null: false
- t.integer :file_store, null: false, limit: 2
- t.integer :file_type, null: false, limit: 2
- t.integer :file_format, null: false, limit: 2
- t.text :file
-
- t.index [:pipeline_id, :file_type], unique: true
- end
- end
-
- add_text_limit :ci_pipeline_artifacts, :file, 255
- end
-
- def down
- drop_table :ci_pipeline_artifacts
- end
-end
diff --git a/db/migrate/20200805151001_add_foreign_key_to_pipeline_id_on_pipeline_artifact.rb b/db/migrate/20200805151001_add_foreign_key_to_pipeline_id_on_pipeline_artifact.rb
deleted file mode 100644
index 5cfe0496b8d..00000000000
--- a/db/migrate/20200805151001_add_foreign_key_to_pipeline_id_on_pipeline_artifact.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToPipelineIdOnPipelineArtifact < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :ci_pipeline_artifacts, :ci_pipelines, column: :pipeline_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :ci_pipeline_artifacts, column: :pipeline_id
- end
- end
-end
diff --git a/db/migrate/20200805151726_add_foreign_key_to_project_id_on_pipeline_artifact.rb b/db/migrate/20200805151726_add_foreign_key_to_project_id_on_pipeline_artifact.rb
deleted file mode 100644
index fe418f4c5af..00000000000
--- a/db/migrate/20200805151726_add_foreign_key_to_project_id_on_pipeline_artifact.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToProjectIdOnPipelineArtifact < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :ci_pipeline_artifacts, :projects, column: :project_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :ci_pipeline_artifacts, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20200806004232_add_default_value_for_file_store_to_package_files.rb b/db/migrate/20200806004232_add_default_value_for_file_store_to_package_files.rb
deleted file mode 100644
index 06f033891fc..00000000000
--- a/db/migrate/20200806004232_add_default_value_for_file_store_to_package_files.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultValueForFileStoreToPackageFiles < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :packages_package_files, :file_store, 1
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :packages_package_files, :file_store, nil
- end
- end
-end
diff --git a/db/migrate/20200807070820_add_index_for_compliance_merged_merge_request_to_events.rb b/db/migrate/20200807070820_add_index_for_compliance_merged_merge_request_to_events.rb
deleted file mode 100644
index 4650437056e..00000000000
--- a/db/migrate/20200807070820_add_index_for_compliance_merged_merge_request_to_events.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexForComplianceMergedMergeRequestToEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_events_on_project_id_and_id_desc_on_merged_action'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :events, [:project_id, :id],
- order: { id: :desc },
- where: "action = 7", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :events, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200807132726_add_delete_original_index_at_to_reindexing_tasks.rb b/db/migrate/20200807132726_add_delete_original_index_at_to_reindexing_tasks.rb
deleted file mode 100644
index 435b2a45e85..00000000000
--- a/db/migrate/20200807132726_add_delete_original_index_at_to_reindexing_tasks.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddDeleteOriginalIndexAtToReindexingTasks < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :elastic_reindexing_tasks, :delete_original_index_at, :datetime_with_timezone
- end
- end
-
- def down
- with_lock_retries do
- remove_column :elastic_reindexing_tasks, :delete_original_index_at
- end
- end
-end
diff --git a/db/migrate/20200807150937_add_file_count_to_merge_request_diffs.rb b/db/migrate/20200807150937_add_file_count_to_merge_request_diffs.rb
deleted file mode 100644
index 3afc246d698..00000000000
--- a/db/migrate/20200807150937_add_file_count_to_merge_request_diffs.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddFileCountToMergeRequestDiffs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- add_column :merge_request_diffs, :files_count, :smallint
- end
- end
-
- def down
- with_lock_retries do
- remove_column :merge_request_diffs, :files_count, :smallint
- end
- end
-end
diff --git a/db/migrate/20200810152043_add_expire_at_to_ci_pipeline_artifact.rb b/db/migrate/20200810152043_add_expire_at_to_ci_pipeline_artifact.rb
deleted file mode 100644
index 1aaa0f36f16..00000000000
--- a/db/migrate/20200810152043_add_expire_at_to_ci_pipeline_artifact.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddExpireAtToCiPipelineArtifact < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :ci_pipeline_artifacts, :expire_at, :datetime_with_timezone
- end
-end
diff --git a/db/migrate/20200811055018_remove_not_null_constraint_on_type_from_audit_events.rb b/db/migrate/20200811055018_remove_not_null_constraint_on_type_from_audit_events.rb
deleted file mode 100644
index 25c3ef71655..00000000000
--- a/db/migrate/20200811055018_remove_not_null_constraint_on_type_from_audit_events.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveNotNullConstraintOnTypeFromAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # To avoid deadlock on audit_event and audit_event_part... since there is a trigger to insert record from audit_events
- # to audit_events_part..., we need to ensure each ALTER TABLE command run in its own transaction.
- def up
- with_lock_retries do
- change_column_null :audit_events_part_5fc467ac26, :type, true
- end
-
- with_lock_retries do
- change_column_null :audit_events, :type, true
- end
- end
-
- def down
- # no-op -- null values might be added after this constraint is removed.
- end
-end
diff --git a/db/migrate/20200811154630_add_gitpod_application_settings.rb b/db/migrate/20200811154630_add_gitpod_application_settings.rb
deleted file mode 100644
index e4211d25d0b..00000000000
--- a/db/migrate/20200811154630_add_gitpod_application_settings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddGitpodApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in 20200727154631_add_gitpod_application_settings_text_limit
- def change
- add_column :application_settings, :gitpod_enabled, :boolean, default: false, null: false
- add_column :application_settings, :gitpod_url, :text, default: 'https://gitpod.io/', null: true
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20200811154631_add_gitpod_application_settings_text_limit.rb b/db/migrate/20200811154631_add_gitpod_application_settings_text_limit.rb
deleted file mode 100644
index 1f43b5d88d5..00000000000
--- a/db/migrate/20200811154631_add_gitpod_application_settings_text_limit.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddGitpodApplicationSettingsTextLimit < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :application_settings, :gitpod_url, 255
- end
-
- def down
- remove_text_limit :application_settings, :gitpod_url
- end
-end
diff --git a/db/migrate/20200811154632_add_gitpod_user_preferences.rb b/db/migrate/20200811154632_add_gitpod_user_preferences.rb
deleted file mode 100644
index 0392c80d39c..00000000000
--- a/db/migrate/20200811154632_add_gitpod_user_preferences.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddGitpodUserPreferences < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :user_preferences, :gitpod_enabled, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20200811194848_add_default_value_for_file_store_to_pipeline_artifact.rb b/db/migrate/20200811194848_add_default_value_for_file_store_to_pipeline_artifact.rb
deleted file mode 100644
index f689a505809..00000000000
--- a/db/migrate/20200811194848_add_default_value_for_file_store_to_pipeline_artifact.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultValueForFileStoreToPipelineArtifact < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- PIPELINE_ARTIFACT_LOCAL_FILE_STORE = 1
-
- def up
- with_lock_retries do
- change_column_default :ci_pipeline_artifacts, :file_store, PIPELINE_ARTIFACT_LOCAL_FILE_STORE
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :ci_pipeline_artifacts, :file_store, nil
- end
- end
-end
diff --git a/db/migrate/20200812112204_add_index_to_mr_metrics_target_project_id.rb b/db/migrate/20200812112204_add_index_to_mr_metrics_target_project_id.rb
deleted file mode 100644
index da483e7222c..00000000000
--- a/db/migrate/20200812112204_add_index_to_mr_metrics_target_project_id.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToMrMetricsTargetProjectId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_merge_request_metrics_on_target_project_id_merged_at'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :merge_request_metrics, [:target_project_id, :merged_at], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name(:merge_request_metrics, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200812150810_add_verification_state_to_snippet_repository.rb b/db/migrate/20200812150810_add_verification_state_to_snippet_repository.rb
deleted file mode 100644
index 3fdf0b4adf4..00000000000
--- a/db/migrate/20200812150810_add_verification_state_to_snippet_repository.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddVerificationStateToSnippetRepository < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_table(:snippet_repositories) do |t|
- t.integer :verification_retry_count, limit: 2
- t.column :verification_retry_at, :datetime_with_timezone
- t.column :verified_at, :datetime_with_timezone
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
-
- # rubocop:disable Migration/AddLimitToTextColumns
- t.text :verification_failure
- # rubocop:enable Migration/AddLimitToTextColumns
- end
- end
-end
diff --git a/db/migrate/20200812150811_add_verification_failure_to_snippet_repository.rb b/db/migrate/20200812150811_add_verification_failure_to_snippet_repository.rb
deleted file mode 100644
index 64cd094acf0..00000000000
--- a/db/migrate/20200812150811_add_verification_failure_to_snippet_repository.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddVerificationFailureToSnippetRepository < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'snippet_repositories_verification_failure_text_limit'
-
- def up
- add_text_limit :snippet_repositories, :verification_failure, 255, constraint_name: CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint(:snippet_repositories, CONSTRAINT_NAME)
- end
-end
diff --git a/db/migrate/20200812150812_add_verification_failure_index_to_snippet_repository.rb b/db/migrate/20200812150812_add_verification_failure_index_to_snippet_repository.rb
deleted file mode 100644
index 3c1d2dc988d..00000000000
--- a/db/migrate/20200812150812_add_verification_failure_index_to_snippet_repository.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddVerificationFailureIndexToSnippetRepository < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :snippet_repositories, :verification_failure, where: "(verification_failure IS NOT NULL)", name: 'snippet_repositories_verification_failure_partial'
- add_concurrent_index :snippet_repositories, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: 'snippet_repositories_verification_checksum_partial'
- end
-
- def down
- remove_concurrent_index_by_name :snippet_repositories, 'snippet_repositories_verification_failure_partial'
- remove_concurrent_index_by_name :snippet_repositories, 'snippet_repositories_verification_checksum_partial'
- end
-end
diff --git a/db/migrate/20200813135558_create_ci_deleted_objects.rb b/db/migrate/20200813135558_create_ci_deleted_objects.rb
deleted file mode 100644
index 5364b7fc0ce..00000000000
--- a/db/migrate/20200813135558_create_ci_deleted_objects.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCiDeletedObjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :ci_deleted_objects, if_not_exists: true do |t|
- t.integer :file_store, limit: 2, default: 1, null: false
- t.datetime_with_timezone :pick_up_at, null: false, default: -> { 'now()' }, index: true
- t.text :store_dir, null: false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # This column depends on the `file` column from `ci_job_artifacts` table
- # which doesn't have a constraint limit on it.
- t.text :file, null: false
- # rubocop:enable Migration/AddLimitToTextColumns
- end
-
- add_text_limit(:ci_deleted_objects, :store_dir, 1024)
- end
-
- def down
- drop_table :ci_deleted_objects
- end
-end
diff --git a/db/migrate/20200813143304_add_new_external_diff_migration_index.rb b/db/migrate/20200813143304_add_new_external_diff_migration_index.rb
deleted file mode 100644
index 64611e4f50a..00000000000
--- a/db/migrate/20200813143304_add_new_external_diff_migration_index.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class AddNewExternalDiffMigrationIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_merge_request_diffs_by_id_partial'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(
- :merge_request_diffs,
- :id,
- name: INDEX_NAME,
- where: 'files_count > 0 AND ((NOT stored_externally) OR (stored_externally IS NULL))'
- )
- end
-
- def down
- remove_concurrent_index_by_name(:merge_request_diffs, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200813143356_remove_old_external_diff_migration_index.rb b/db/migrate/20200813143356_remove_old_external_diff_migration_index.rb
deleted file mode 100644
index a3730247f10..00000000000
--- a/db/migrate/20200813143356_remove_old_external_diff_migration_index.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveOldExternalDiffMigrationIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name(
- :merge_request_diffs,
- 'index_merge_request_diffs_on_merge_request_id_and_id_partial'
- )
- end
-
- def down
- add_concurrent_index(
- :merge_request_diffs,
- [:merge_request_id, :id],
- where: 'NOT stored_externally OR stored_externally IS NULL',
- name: 'index_merge_request_diffs_on_merge_request_id_and_id_partial'
- )
- end
-end
diff --git a/db/migrate/20200816133024_add_cve_id_request_project_setting.rb b/db/migrate/20200816133024_add_cve_id_request_project_setting.rb
deleted file mode 100644
index c4fe86845eb..00000000000
--- a/db/migrate/20200816133024_add_cve_id_request_project_setting.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddCveIdRequestProjectSetting < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column :project_settings, :cve_id_request_enabled, :boolean, default: true, null: false
- end
-
- def down
- remove_column :project_settings, :cve_id_request_enabled
- end
-end
diff --git a/db/migrate/20200817142800_add_pipeline_artifacts_size_to_project_statistics.rb b/db/migrate/20200817142800_add_pipeline_artifacts_size_to_project_statistics.rb
deleted file mode 100644
index a15d94a41b7..00000000000
--- a/db/migrate/20200817142800_add_pipeline_artifacts_size_to_project_statistics.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddPipelineArtifactsSizeToProjectStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :project_statistics, :pipeline_artifacts_size, :bigint, default: 0, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :project_statistics, :pipeline_artifacts_size, :bigint, default: 0, null: false
- end
- end
-end
diff --git a/db/migrate/20200817195628_add_modified_to_approval_merge_request_rule.rb b/db/migrate/20200817195628_add_modified_to_approval_merge_request_rule.rb
deleted file mode 100644
index 71a29ae9bc5..00000000000
--- a/db/migrate/20200817195628_add_modified_to_approval_merge_request_rule.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddModifiedToApprovalMergeRequestRule < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :approval_merge_request_rules, :modified_from_project_rule, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20200818052219_add_kubernetes_version_to_cluster_providers_aws.rb b/db/migrate/20200818052219_add_kubernetes_version_to_cluster_providers_aws.rb
deleted file mode 100644
index fa3d5210e91..00000000000
--- a/db/migrate/20200818052219_add_kubernetes_version_to_cluster_providers_aws.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddKubernetesVersionToClusterProvidersAws < ActiveRecord::Migration[6.0]
- # Uncomment the following include if you require helper functions:
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:cluster_providers_aws, :kubernetes_version)
- add_column :cluster_providers_aws, :kubernetes_version, :text, null: false, default: '1.14'
- end
-
- add_text_limit :cluster_providers_aws, :kubernetes_version, 30
- end
-
- def down
- if column_exists?(:cluster_providers_aws, :kubernetes_version)
- remove_column :cluster_providers_aws, :kubernetes_version
- end
- end
-end
diff --git a/db/migrate/20200818092401_add_checksum_to_build_chunk.rb b/db/migrate/20200818092401_add_checksum_to_build_chunk.rb
deleted file mode 100644
index c1c968571a2..00000000000
--- a/db/migrate/20200818092401_add_checksum_to_build_chunk.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddChecksumToBuildChunk < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :ci_build_trace_chunks, :checksum, :binary
- end
-end
diff --git a/db/migrate/20200818171229_add_package_max_file_size_to_plan_limits.rb b/db/migrate/20200818171229_add_package_max_file_size_to_plan_limits.rb
deleted file mode 100644
index 5343da6ed5e..00000000000
--- a/db/migrate/20200818171229_add_package_max_file_size_to_plan_limits.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddPackageMaxFileSizeToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column(:plan_limits, :conan_max_file_size, :bigint, default: 50.megabytes, null: false)
- add_column(:plan_limits, :maven_max_file_size, :bigint, default: 50.megabytes, null: false)
- add_column(:plan_limits, :npm_max_file_size, :bigint, default: 50.megabytes, null: false)
- add_column(:plan_limits, :nuget_max_file_size, :bigint, default: 50.megabytes, null: false)
- add_column(:plan_limits, :pypi_max_file_size, :bigint, default: 50.megabytes, null: false)
- end
-end
diff --git a/db/migrate/20200819192143_add_emails_user_id_foreign_key.rb b/db/migrate/20200819192143_add_emails_user_id_foreign_key.rb
deleted file mode 100644
index 7f00aa6341b..00000000000
--- a/db/migrate/20200819192143_add_emails_user_id_foreign_key.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddEmailsUserIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_emails_user_id'
-
- def up
- with_lock_retries do
- add_foreign_key :emails, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key_if_exists :emails, column: :user_id, name: CONSTRAINT_NAME
- end
- end
-end
diff --git a/db/migrate/20200820105408_add_index_to_container_scanning_findings.rb b/db/migrate/20200820105408_add_index_to_container_scanning_findings.rb
deleted file mode 100644
index dd474b57602..00000000000
--- a/db/migrate/20200820105408_add_index_to_container_scanning_findings.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToContainerScanningFindings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'idx_container_scanning_findings'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:vulnerability_occurrences, :id,
- where: "report_type = 2",
- name: INDEX_NAME)
- end
-
- def down
- remove_concurrent_index_by_name(:vulnerability_occurrences, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200820130839_add_auto_close_incident_to_project_incident_management_settings.rb b/db/migrate/20200820130839_add_auto_close_incident_to_project_incident_management_settings.rb
deleted file mode 100644
index 01aafa6d988..00000000000
--- a/db/migrate/20200820130839_add_auto_close_incident_to_project_incident_management_settings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddAutoCloseIncidentToProjectIncidentManagementSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column :project_incident_management_settings, :auto_close_incident, :boolean, default: true, null: false
- end
-
- def down
- remove_column :project_incident_management_settings, :auto_close_incident
- end
-end
diff --git a/db/migrate/20200820204041_create_ci_platform_metrics.rb b/db/migrate/20200820204041_create_ci_platform_metrics.rb
deleted file mode 100644
index 27a5a3dc8eb..00000000000
--- a/db/migrate/20200820204041_create_ci_platform_metrics.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCiPlatformMetrics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CI_VARIABLES_KEY_INDEX_NAME = "index_ci_variables_on_key"
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:ci_platform_metrics)
- create_table :ci_platform_metrics do |t|
- t.datetime_with_timezone :recorded_at, null: false
- t.text :platform_target, null: false
- t.integer :count, null: false
- end
- end
-
- add_text_limit :ci_platform_metrics, :platform_target, 255
- add_concurrent_index :ci_variables, :key, name: CI_VARIABLES_KEY_INDEX_NAME
- end
-
- def down
- if table_exists?(:ci_platform_metrics)
- drop_table :ci_platform_metrics
- end
-
- remove_concurrent_index :ci_variables, :key, name: CI_VARIABLES_KEY_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200821034419_add_unique_index_for_generic_packages.rb b/db/migrate/20200821034419_add_unique_index_for_generic_packages.rb
deleted file mode 100644
index f0e4749bbb5..00000000000
--- a/db/migrate/20200821034419_add_unique_index_for_generic_packages.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddUniqueIndexForGenericPackages < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = 'index_packages_on_project_id_name_version_unique_when_generic'
- PACKAGE_TYPE_GENERIC = 7
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :packages_packages, [:project_id, :name, :version], unique: true, where: "package_type = #{PACKAGE_TYPE_GENERIC}", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name(:packages_packages, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200821194920_create_atlassian_identities.rb b/db/migrate/20200821194920_create_atlassian_identities.rb
deleted file mode 100644
index 1aab9ed6381..00000000000
--- a/db/migrate/20200821194920_create_atlassian_identities.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-class CreateAtlassianIdentities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:atlassian_identities)
- with_lock_retries do
- create_table :atlassian_identities, id: false do |t|
- t.references :user, index: false, foreign_key: { on_delete: :cascade }, null: false, primary_key: true
- t.timestamps_with_timezone
- t.datetime_with_timezone :expires_at
- t.text :extern_uid, null: false, index: { unique: true }
- t.binary :encrypted_token
- t.binary :encrypted_token_iv
- t.binary :encrypted_refresh_token
- t.binary :encrypted_refresh_token_iv
- end
- end
- end
-
- add_text_limit :atlassian_identities, :extern_uid, 255
-
- add_check_constraint :atlassian_identities, 'octet_length(encrypted_token) <= 2048', 'atlassian_identities_token_length_constraint'
- add_check_constraint :atlassian_identities, 'octet_length(encrypted_token_iv) <= 12', 'atlassian_identities_token_iv_length_constraint'
- add_check_constraint :atlassian_identities, 'octet_length(encrypted_refresh_token) <= 512', 'atlassian_identities_refresh_token_length_constraint'
- add_check_constraint :atlassian_identities, 'octet_length(encrypted_refresh_token_iv) <= 12', 'atlassian_identities_refresh_token_iv_length_constraint'
- end
-
- def down
- with_lock_retries do
- drop_table :atlassian_identities
- end
- end
-end
diff --git a/db/migrate/20200824045812_add_generic_package_max_file_size_to_plan_limits.rb b/db/migrate/20200824045812_add_generic_package_max_file_size_to_plan_limits.rb
deleted file mode 100644
index eea4f8de7bf..00000000000
--- a/db/migrate/20200824045812_add_generic_package_max_file_size_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddGenericPackageMaxFileSizeToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column(:plan_limits, :generic_packages_max_file_size, :bigint, default: 5.gigabytes, null: false)
- end
-end
diff --git a/db/migrate/20200824124623_create_issuable_severities.rb b/db/migrate/20200824124623_create_issuable_severities.rb
deleted file mode 100644
index 674a54fc16d..00000000000
--- a/db/migrate/20200824124623_create_issuable_severities.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class CreateIssuableSeverities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :issuable_severities do |t|
- t.references :issue, index: { unique: true }, null: false, foreign_key: { on_delete: :cascade }
- t.integer :severity, null: false, default: 0, limit: 2 # 0 - will stand for unknown
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :issuable_severities
- end
- end
-end
diff --git a/db/migrate/20200825071735_create_merge_request_reviewers.rb b/db/migrate/20200825071735_create_merge_request_reviewers.rb
deleted file mode 100644
index 45451476bb0..00000000000
--- a/db/migrate/20200825071735_create_merge_request_reviewers.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class CreateMergeRequestReviewers < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- create_table :merge_request_reviewers do |t|
- t.bigint :user_id, null: false
- t.bigint :merge_request_id, null: false
- t.datetime_with_timezone :created_at, null: false
- end
-
- add_index :merge_request_reviewers, [:merge_request_id, :user_id], unique: true
- add_index :merge_request_reviewers, :user_id
- end
-
- def down
- drop_table :merge_request_reviewers
- end
-end
diff --git a/db/migrate/20200825081025_boards_epic_user_preferences.rb b/db/migrate/20200825081025_boards_epic_user_preferences.rb
deleted file mode 100644
index fc7454a6a9a..00000000000
--- a/db/migrate/20200825081025_boards_epic_user_preferences.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class BoardsEpicUserPreferences < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- create_table :boards_epic_user_preferences do |t|
- t.bigint :board_id, null: false
- t.bigint :user_id, null: false
- t.bigint :epic_id, null: false
- t.boolean :collapsed, default: false, null: false
- end
-
- add_index :boards_epic_user_preferences, :board_id
- add_index :boards_epic_user_preferences, :user_id
- add_index :boards_epic_user_preferences, :epic_id
- add_index :boards_epic_user_preferences, [:board_id, :user_id, :epic_id], unique: true, name: 'index_boards_epic_user_preferences_on_board_user_epic_unique'
- end
-
- def down
- drop_table :boards_epic_user_preferences
- end
-end
diff --git a/db/migrate/20200825081035_boards_epic_user_preferences_fk_board.rb b/db/migrate/20200825081035_boards_epic_user_preferences_fk_board.rb
deleted file mode 100644
index 1c014573fb4..00000000000
--- a/db/migrate/20200825081035_boards_epic_user_preferences_fk_board.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class BoardsEpicUserPreferencesFkBoard < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :boards_epic_user_preferences, :boards, column: :board_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :boards_epic_user_preferences, column: :board_id
- end
- end
-end
diff --git a/db/migrate/20200825081045_boards_epic_user_preferences_fk_user.rb b/db/migrate/20200825081045_boards_epic_user_preferences_fk_user.rb
deleted file mode 100644
index 3edc3bc0ded..00000000000
--- a/db/migrate/20200825081045_boards_epic_user_preferences_fk_user.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class BoardsEpicUserPreferencesFkUser < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :boards_epic_user_preferences, :users, column: :user_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :boards_epic_user_preferences, column: :user_id
- end
- end
-end
diff --git a/db/migrate/20200825081055_boards_epic_user_preferences_fk_epic.rb b/db/migrate/20200825081055_boards_epic_user_preferences_fk_epic.rb
deleted file mode 100644
index 0354060b7c1..00000000000
--- a/db/migrate/20200825081055_boards_epic_user_preferences_fk_epic.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class BoardsEpicUserPreferencesFkEpic < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :boards_epic_user_preferences, :epics, column: :epic_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :boards_epic_user_preferences, column: :epic_id
- end
- end
-end
diff --git a/db/migrate/20200825084819_create_security_findings_table.rb b/db/migrate/20200825084819_create_security_findings_table.rb
deleted file mode 100644
index d44b4671e2f..00000000000
--- a/db/migrate/20200825084819_create_security_findings_table.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class CreateSecurityFindingsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:security_findings)
- create_table :security_findings do |t|
- t.references :scan, null: false
- t.references :scanner, null: false
- t.integer :severity, limit: 2, index: true, null: false
- t.integer :confidence, limit: 2, index: true, null: false
- t.text :project_fingerprint, index: true, null: false
- end
- end
-
- add_text_limit :security_findings, :project_fingerprint, 40
- end
-
- def down
- drop_table :security_findings
- end
-end
diff --git a/db/migrate/20200825154237_update_package_file_size_plan_limits_defaults.rb b/db/migrate/20200825154237_update_package_file_size_plan_limits_defaults.rb
deleted file mode 100644
index b71e2a86f4a..00000000000
--- a/db/migrate/20200825154237_update_package_file_size_plan_limits_defaults.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class UpdatePackageFileSizePlanLimitsDefaults < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_column_default(:plan_limits, :maven_max_file_size, from: 50.megabytes, to: 3.gigabytes)
- change_column_default(:plan_limits, :conan_max_file_size, from: 50.megabytes, to: 3.gigabytes)
- change_column_default(:plan_limits, :nuget_max_file_size, from: 50.megabytes, to: 500.megabytes)
- change_column_default(:plan_limits, :npm_max_file_size, from: 50.megabytes, to: 500.megabytes)
- change_column_default(:plan_limits, :pypi_max_file_size, from: 50.megabytes, to: 3.gigabytes)
- end
-end
diff --git a/db/migrate/20200825180050_add_pipeline_artifacts_size_to_root_storage_statistics.rb b/db/migrate/20200825180050_add_pipeline_artifacts_size_to_root_storage_statistics.rb
deleted file mode 100644
index 069480c6887..00000000000
--- a/db/migrate/20200825180050_add_pipeline_artifacts_size_to_root_storage_statistics.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddPipelineArtifactsSizeToRootStorageStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :namespace_root_storage_statistics, :pipeline_artifacts_size, :bigint, default: 0, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :namespace_root_storage_statistics, :pipeline_artifacts_size, :bigint, default: 0, null: false
- end
- end
-end
diff --git a/db/migrate/20200826073745_add_default_to_ci_pipeline_locked.rb b/db/migrate/20200826073745_add_default_to_ci_pipeline_locked.rb
deleted file mode 100644
index e73963043d5..00000000000
--- a/db/migrate/20200826073745_add_default_to_ci_pipeline_locked.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultToCiPipelineLocked < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- ARTIFACTS_LOCKED = 1
- UNLOCKED = 0
-
- def up
- with_lock_retries do
- change_column_default :ci_pipelines, :locked, ARTIFACTS_LOCKED
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :ci_pipelines, :locked, UNLOCKED
- end
- end
-end
diff --git a/db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb b/db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb
deleted file mode 100644
index 5938d3c8d3a..00000000000
--- a/db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectsIndexOnImportTypeCreatorIdCreatedAt < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_imported_projects_on_import_type_creator_id_created_at'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects,
- [:import_type, :creator_id, :created_at],
- where: 'import_type IS NOT NULL',
- name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :projects, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200826212800_add_index_on_merge_request_id_and_rule_type_to_approval_merge_request_rule.rb b/db/migrate/20200826212800_add_index_on_merge_request_id_and_rule_type_to_approval_merge_request_rule.rb
deleted file mode 100644
index a40e09648ef..00000000000
--- a/db/migrate/20200826212800_add_index_on_merge_request_id_and_rule_type_to_approval_merge_request_rule.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnMergeRequestIdAndRuleTypeToApprovalMergeRequestRule < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = "approval_mr_rule_index_merge_request_id"
-
- def up
- add_concurrent_index(
- :approval_merge_request_rules,
- :merge_request_id,
- name: INDEX_NAME
- )
- end
-
- def down
- remove_concurrent_index_by_name :approval_merge_request_rules, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200827005322_add_creator_id_to_packages.rb b/db/migrate/20200827005322_add_creator_id_to_packages.rb
deleted file mode 100644
index ecd73ff8785..00000000000
--- a/db/migrate/20200827005322_add_creator_id_to_packages.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddCreatorIdToPackages < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column(:packages_packages, :creator_id, :integer)
- end
-end
diff --git a/db/migrate/20200827060911_add_merge_request_foreign_key_to_merge_request_reviewers.rb b/db/migrate/20200827060911_add_merge_request_foreign_key_to_merge_request_reviewers.rb
deleted file mode 100644
index 73d0eea9819..00000000000
--- a/db/migrate/20200827060911_add_merge_request_foreign_key_to_merge_request_reviewers.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddMergeRequestForeignKeyToMergeRequestReviewers < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :merge_request_reviewers, :merge_requests, column: :merge_request_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :merge_request_reviewers, column: :merge_request_id
- end
- end
-end
diff --git a/db/migrate/20200827060932_add_user_foreign_key_to_merge_request_reviewers.rb b/db/migrate/20200827060932_add_user_foreign_key_to_merge_request_reviewers.rb
deleted file mode 100644
index 5463c3d9846..00000000000
--- a/db/migrate/20200827060932_add_user_foreign_key_to_merge_request_reviewers.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddUserForeignKeyToMergeRequestReviewers < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :merge_request_reviewers, :users, column: :user_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :merge_request_reviewers, column: :user_id
- end
- end
-end
diff --git a/db/migrate/20200827085101_add_seats_currently_in_use_in_gitlab_subscriptions.rb b/db/migrate/20200827085101_add_seats_currently_in_use_in_gitlab_subscriptions.rb
deleted file mode 100644
index 83f2d573b6d..00000000000
--- a/db/migrate/20200827085101_add_seats_currently_in_use_in_gitlab_subscriptions.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddSeatsCurrentlyInUseInGitlabSubscriptions < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :gitlab_subscriptions, :seats_in_use, :integer, default: 0, null: false
- add_column :gitlab_subscriptions, :seats_owed, :integer, default: 0, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :gitlab_subscriptions, :seats_in_use
- remove_column :gitlab_subscriptions, :seats_owed
- end
- end
-end
diff --git a/db/migrate/20200827102234_add_ci_job_artifact_id_to_pages_metadata.rb b/db/migrate/20200827102234_add_ci_job_artifact_id_to_pages_metadata.rb
deleted file mode 100644
index 4109c512f14..00000000000
--- a/db/migrate/20200827102234_add_ci_job_artifact_id_to_pages_metadata.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddCiJobArtifactIdToPagesMetadata < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column(:project_pages_metadata, :artifacts_archive_id, :bigint)
- end
-end
diff --git a/db/migrate/20200827104432_add_foreign_key_to_artifacts_archive_id_in_pages_metadata.rb b/db/migrate/20200827104432_add_foreign_key_to_artifacts_archive_id_in_pages_metadata.rb
deleted file mode 100644
index 90451ad597a..00000000000
--- a/db/migrate/20200827104432_add_foreign_key_to_artifacts_archive_id_in_pages_metadata.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToArtifactsArchiveIdInPagesMetadata < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = "index_project_pages_metadata_on_artifacts_archive_id"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:project_pages_metadata, :artifacts_archive_id, name: INDEX_NAME)
- add_concurrent_foreign_key(:project_pages_metadata, :ci_job_artifacts, column: :artifacts_archive_id, on_delete: :nullify)
- end
-
- def down
- remove_foreign_key_if_exists(:project_pages_metadata, :ci_job_artifacts, column: :artifacts_archive_id)
- remove_concurrent_index_by_name(:project_pages_metadata, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200827114902_create_analytics_instance_statistics_measurements.rb b/db/migrate/20200827114902_create_analytics_instance_statistics_measurements.rb
deleted file mode 100644
index f8584d4b9f6..00000000000
--- a/db/migrate/20200827114902_create_analytics_instance_statistics_measurements.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class CreateAnalyticsInstanceStatisticsMeasurements < ActiveRecord::Migration[6.0]
- DOWNTIME = false
- UNIQUE_INDEX_NAME = 'index_on_instance_statistics_recorded_at_and_identifier'
-
- def change
- create_table :analytics_instance_statistics_measurements do |t|
- t.bigint :count, null: false
- t.datetime_with_timezone :recorded_at, null: false
- t.integer :identifier, limit: 2, null: false
- end
-
- add_index :analytics_instance_statistics_measurements, [:identifier, :recorded_at], unique: true, name: UNIQUE_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200827142811_create_merge_request_diff_details.rb b/db/migrate/20200827142811_create_merge_request_diff_details.rb
deleted file mode 100644
index 29b070bc675..00000000000
--- a/db/migrate/20200827142811_create_merge_request_diff_details.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class CreateMergeRequestDiffDetails < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:merge_request_diff_details)
- with_lock_retries do
- create_table :merge_request_diff_details, id: false do |t|
- t.references :merge_request_diff, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
- t.datetime_with_timezone :verification_retry_at
- t.datetime_with_timezone :verified_at
- t.integer :verification_retry_count, limit: 2
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
- t.text :verification_failure
- end
- end
- end
-
- add_text_limit :merge_request_diff_details, :verification_failure, 255
- end
-
- def down
- drop_table :merge_request_diff_details
- end
-end
diff --git a/db/migrate/20200827150057_add_index_expire_at_to_pipeline_artifacts.rb b/db/migrate/20200827150057_add_index_expire_at_to_pipeline_artifacts.rb
deleted file mode 100644
index 0a1943aa58b..00000000000
--- a/db/migrate/20200827150057_add_index_expire_at_to_pipeline_artifacts.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexExpireAtToPipelineArtifacts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_ci_pipeline_artifacts_on_expire_at'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_pipeline_artifacts, :expire_at, name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name(:ci_pipeline_artifacts, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200828155134_add_foreign_key_on_scan_id_to_security_scans.rb b/db/migrate/20200828155134_add_foreign_key_on_scan_id_to_security_scans.rb
deleted file mode 100644
index 9d815cc75dc..00000000000
--- a/db/migrate/20200828155134_add_foreign_key_on_scan_id_to_security_scans.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyOnScanIdToSecurityScans < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :security_findings, :security_scans, column: :scan_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :security_findings, column: :scan_id
- end
- end
-end
diff --git a/db/migrate/20200828155205_add_foreign_key_on_scanner_id_to_vulnerability_scanners.rb b/db/migrate/20200828155205_add_foreign_key_on_scanner_id_to_vulnerability_scanners.rb
deleted file mode 100644
index 015e83b59b1..00000000000
--- a/db/migrate/20200828155205_add_foreign_key_on_scanner_id_to_vulnerability_scanners.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyOnScannerIdToVulnerabilityScanners < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :security_findings, :vulnerability_scanners, column: :scanner_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :security_findings, column: :scanner_id
- end
- end
-end
diff --git a/db/migrate/20200830201204_add_index_to_package_creator.rb b/db/migrate/20200830201204_add_index_to_package_creator.rb
deleted file mode 100644
index fbc8bbade94..00000000000
--- a/db/migrate/20200830201204_add_index_to_package_creator.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToPackageCreator < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'index_packages_packages_on_creator_id'
-
- def up
- add_concurrent_index :packages_packages, :creator_id, name: INDEX_NAME
- add_concurrent_foreign_key(:packages_packages, :users, column: :creator_id, on_delete: :nullify)
- end
-
- def down
- remove_foreign_key_if_exists(:packages_packages, :users, column: :creator_id)
- remove_concurrent_index_by_name(:packages_packages, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200831204646_add_project_feature_flags_to_plan_limits.rb b/db/migrate/20200831204646_add_project_feature_flags_to_plan_limits.rb
deleted file mode 100644
index d4bd2431d9c..00000000000
--- a/db/migrate/20200831204646_add_project_feature_flags_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectFeatureFlagsToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column(:plan_limits, :project_feature_flags, :integer, default: 200, null: false)
- end
-end
diff --git a/db/migrate/20200831222347_insert_project_feature_flags_plan_limits.rb b/db/migrate/20200831222347_insert_project_feature_flags_plan_limits.rb
deleted file mode 100644
index 2c91016d9dd..00000000000
--- a/db/migrate/20200831222347_insert_project_feature_flags_plan_limits.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class InsertProjectFeatureFlagsPlanLimits < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- return unless Gitlab.com?
-
- create_or_update_plan_limit('project_feature_flags', 'free', 50)
- create_or_update_plan_limit('project_feature_flags', 'bronze', 100)
- create_or_update_plan_limit('project_feature_flags', 'silver', 150)
- create_or_update_plan_limit('project_feature_flags', 'gold', 200)
- end
-
- def down
- return unless Gitlab.com?
-
- create_or_update_plan_limit('project_feature_flags', 'free', 0)
- create_or_update_plan_limit('project_feature_flags', 'bronze', 0)
- create_or_update_plan_limit('project_feature_flags', 'silver', 0)
- create_or_update_plan_limit('project_feature_flags', 'gold', 0)
- end
-end
diff --git a/db/migrate/20200901203055_add_id_created_at_index_to_packages.rb b/db/migrate/20200901203055_add_id_created_at_index_to_packages.rb
deleted file mode 100644
index d92309e3fef..00000000000
--- a/db/migrate/20200901203055_add_id_created_at_index_to_packages.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIdCreatedAtIndexToPackages < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'index_packages_packages_on_id_and_created_at'
-
- def up
- add_concurrent_index :packages_packages, [:id, :created_at], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name(:packages_packages, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200901214416_change_pypi_python_version_type.rb b/db/migrate/20200901214416_change_pypi_python_version_type.rb
deleted file mode 100644
index b670b2129c2..00000000000
--- a/db/migrate/20200901214416_change_pypi_python_version_type.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class ChangePypiPythonVersionType < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- change_column_type_concurrently :packages_pypi_metadata, :required_python, :text, batch_column_name: :package_id # rubocop:disable Migration/AddLimitToTextColumns
- end
-
- def down
- cleanup_concurrent_column_type_change(:packages_pypi_metadata, :required_python)
- change_column_null :packages_pypi_metadata, :required_python, false
- end
-end
diff --git a/db/migrate/20200902135542_update_package_max_file_size_plan_limits.rb b/db/migrate/20200902135542_update_package_max_file_size_plan_limits.rb
deleted file mode 100644
index 0ba8f12f89e..00000000000
--- a/db/migrate/20200902135542_update_package_max_file_size_plan_limits.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-class UpdatePackageMaxFileSizePlanLimits < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- # this is intended to be a no-op for GitLab.com
- # 5GB is the value for these columns as of 2020-09-02
- if Gitlab.com?
- update_all_plan_limits('conan_max_file_size', 5.gigabytes)
- update_all_plan_limits('maven_max_file_size', 5.gigabytes)
- update_all_plan_limits('npm_max_file_size', 5.gigabytes)
- update_all_plan_limits('nuget_max_file_size', 5.gigabytes)
- update_all_plan_limits('pypi_max_file_size', 5.gigabytes)
- else
- update_all_plan_limits('conan_max_file_size', 3.gigabytes)
- update_all_plan_limits('maven_max_file_size', 3.gigabytes)
- update_all_plan_limits('npm_max_file_size', 500.megabytes)
- update_all_plan_limits('nuget_max_file_size', 500.megabytes)
- update_all_plan_limits('pypi_max_file_size', 3.gigabytes)
- end
- end
-
- def down
- update_all_plan_limits('conan_max_file_size', 50.megabytes)
- update_all_plan_limits('maven_max_file_size', 50.megabytes)
- update_all_plan_limits('npm_max_file_size', 50.megabytes)
- update_all_plan_limits('nuget_max_file_size', 50.megabytes)
- update_all_plan_limits('pypi_max_file_size', 50.megabytes)
- end
-
- private
-
- def update_all_plan_limits(limit_name, limit_value)
- limit_name_quoted = quote_column_name(limit_name)
- limit_value_quoted = quote(limit_value)
-
- execute <<~SQL
- UPDATE plan_limits
- SET #{limit_name_quoted} = #{limit_value_quoted};
- SQL
- end
-end
diff --git a/db/migrate/20200903054946_add_elasticsearch_client_timeout.rb b/db/migrate/20200903054946_add_elasticsearch_client_timeout.rb
deleted file mode 100644
index 93e70461641..00000000000
--- a/db/migrate/20200903054946_add_elasticsearch_client_timeout.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddElasticsearchClientTimeout < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :elasticsearch_client_request_timeout, :integer, null: false, default: 0
- end
-end
diff --git a/db/migrate/20200903092241_add_index_to_resource_iteration_events_add_events.rb b/db/migrate/20200903092241_add_index_to_resource_iteration_events_add_events.rb
deleted file mode 100644
index be530f1f9b5..00000000000
--- a/db/migrate/20200903092241_add_index_to_resource_iteration_events_add_events.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToResourceIterationEventsAddEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'index_resource_iteration_events_on_iteration_id_and_add_action'
- ADD_ACTION = '1'
-
- def up
- # Index add iteration events
- add_concurrent_index :resource_iteration_events, :iteration_id, where: "action = #{ADD_ACTION}", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :resource_iteration_events, :iteration_id, name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20200904092131_add_merge_ref_sha_to_merge_requests.rb b/db/migrate/20200904092131_add_merge_ref_sha_to_merge_requests.rb
deleted file mode 100644
index a490bc8fe07..00000000000
--- a/db/migrate/20200904092131_add_merge_ref_sha_to_merge_requests.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddMergeRefShaToMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :merge_requests, :merge_ref_sha, :binary
- end
- end
-
- def down
- with_lock_retries do
- remove_column :merge_requests, :merge_ref_sha
- end
- end
-end
diff --git a/db/migrate/20200904131544_create_ci_build_pending_states.rb b/db/migrate/20200904131544_create_ci_build_pending_states.rb
deleted file mode 100644
index 2c21ce3ce32..00000000000
--- a/db/migrate/20200904131544_create_ci_build_pending_states.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCiBuildPendingStates < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :ci_build_pending_states do |t|
- t.timestamps_with_timezone
- t.references :build, index: { unique: true }, null: false, foreign_key: { to_table: :ci_builds, on_delete: :cascade }, type: :bigint
- t.integer :state
- t.integer :failure_reason
- t.binary :trace_checksum
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :ci_build_pending_states
- end
- end
-end
diff --git a/db/migrate/20200905013247_add_golang_package_max_file_size_to_plan_limits.rb b/db/migrate/20200905013247_add_golang_package_max_file_size_to_plan_limits.rb
deleted file mode 100644
index 0a6d0ce7339..00000000000
--- a/db/migrate/20200905013247_add_golang_package_max_file_size_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddGolangPackageMaxFileSizeToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column(:plan_limits, :golang_max_file_size, :bigint, default: 100.megabytes, null: false)
- end
-end
diff --git a/db/migrate/20200907021256_create_dast_site_tokens.rb b/db/migrate/20200907021256_create_dast_site_tokens.rb
deleted file mode 100644
index a8e221aef69..00000000000
--- a/db/migrate/20200907021256_create_dast_site_tokens.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDastSiteTokens < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:dast_site_tokens)
- with_lock_retries do
- create_table :dast_site_tokens do |t|
- t.references :project, foreign_key: { on_delete: :cascade }, null: false, index: true
-
- t.timestamps_with_timezone null: false
- t.datetime_with_timezone :expired_at
-
- t.text :token, null: false, unique: true
- t.text :url, null: false
- end
- end
- end
-
- add_text_limit :dast_site_tokens, :token, 255
- add_text_limit :dast_site_tokens, :url, 255
- end
-
- def down
- with_lock_retries do
- drop_table :dast_site_tokens
- end
- end
-end
diff --git a/db/migrate/20200907062101_create_dast_site_validations.rb b/db/migrate/20200907062101_create_dast_site_validations.rb
deleted file mode 100644
index 5ff2084d693..00000000000
--- a/db/migrate/20200907062101_create_dast_site_validations.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDastSiteValidations < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:dast_site_validations)
- with_lock_retries do
- create_table :dast_site_validations do |t|
- t.references :dast_site_token, foreign_key: { on_delete: :cascade }, null: false, index: true
-
- t.timestamps_with_timezone null: false
- t.datetime_with_timezone :validation_started_at
- t.datetime_with_timezone :validation_passed_at
- t.datetime_with_timezone :validation_failed_at
- t.datetime_with_timezone :validation_last_retried_at
-
- t.integer :validation_strategy, null: false, limit: 2
-
- t.text :url_base, null: false
- t.text :url_path, null: false
- end
- end
- end
-
- add_concurrent_index :dast_site_validations, :url_base
- add_text_limit :dast_site_validations, :url_base, 255
- add_text_limit :dast_site_validations, :url_path, 255
- end
-
- def down
- with_lock_retries do
- drop_table :dast_site_validations
- end
- end
-end
diff --git a/db/migrate/20200907092610_add_user_id_to_group_import_states.rb b/db/migrate/20200907092610_add_user_id_to_group_import_states.rb
deleted file mode 100644
index 231bafeabdb..00000000000
--- a/db/migrate/20200907092610_add_user_id_to_group_import_states.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class AddUserIdToGroupImportStates < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:group_import_states, :user_id)
- with_lock_retries do
- add_column :group_import_states, :user_id, :bigint
- end
- end
-
- add_concurrent_foreign_key :group_import_states, :users, column: :user_id, on_delete: :cascade
- add_concurrent_index :group_import_states, :user_id, where: 'user_id IS NOT NULL', name: 'index_group_import_states_on_user_id'
- end
-
- def down
- with_lock_retries do
- remove_column :group_import_states, :user_id
- end
- end
-end
diff --git a/db/migrate/20200908033805_add_dast_site_validation_id_to_dast_site.rb b/db/migrate/20200908033805_add_dast_site_validation_id_to_dast_site.rb
deleted file mode 100644
index 3ac86fb1d9e..00000000000
--- a/db/migrate/20200908033805_add_dast_site_validation_id_to_dast_site.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class AddDastSiteValidationIdToDastSite < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- TABLE_NAME = :dast_sites
- RELATION_NAME = :dast_site_validations
- FK_NAME = :dast_site_validation_id
- INDEX_NAME = "index_dast_sites_on_#{FK_NAME}"
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(TABLE_NAME, FK_NAME)
- with_lock_retries do
- add_column TABLE_NAME, FK_NAME, :bigint
- end
- end
-
- add_concurrent_index TABLE_NAME, FK_NAME, name: INDEX_NAME
- add_concurrent_foreign_key TABLE_NAME, RELATION_NAME, column: FK_NAME, on_delete: :nullify
- end
-
- def down
- remove_foreign_key_if_exists TABLE_NAME, RELATION_NAME
- remove_concurrent_index_by_name TABLE_NAME, INDEX_NAME
-
- with_lock_retries do
- remove_column TABLE_NAME, FK_NAME
- end
- end
-end
diff --git a/db/migrate/20200908094810_add_new_setting_to_namespace_setting.rb b/db/migrate/20200908094810_add_new_setting_to_namespace_setting.rb
deleted file mode 100644
index 27fc93a2c53..00000000000
--- a/db/migrate/20200908094810_add_new_setting_to_namespace_setting.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddNewSettingToNamespaceSetting < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :namespace_settings, :allow_mfa_for_subgroups, :boolean, default: true, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :namespace_settings, :allow_mfa_for_subgroups
- end
- end
-end
diff --git a/db/migrate/20200908100053_create_authentication_events.rb b/db/migrate/20200908100053_create_authentication_events.rb
deleted file mode 100644
index 2ea9f4e24af..00000000000
--- a/db/migrate/20200908100053_create_authentication_events.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class CreateAuthenticationEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:authentication_events)
- with_lock_retries do
- create_table :authentication_events do |t|
- t.datetime_with_timezone :created_at, null: false
- t.references :user, foreign_key: { on_delete: :nullify }, index: true
- t.integer :result, limit: 2, null: false
- t.inet :ip_address
- t.text :provider, null: false, index: true
- t.text :user_name, null: false
- end
- end
- end
-
- add_text_limit :authentication_events, :provider, 64
- add_text_limit :authentication_events, :user_name, 255
- end
-
- def down
- with_lock_retries do
- drop_table :authentication_events
- end
- end
-end
diff --git a/db/migrate/20200908183231_add_check_positive_constraint_to_ci_platform_metrics.rb b/db/migrate/20200908183231_add_check_positive_constraint_to_ci_platform_metrics.rb
deleted file mode 100644
index 8593e03b5d8..00000000000
--- a/db/migrate/20200908183231_add_check_positive_constraint_to_ci_platform_metrics.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddCheckPositiveConstraintToCiPlatformMetrics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'ci_platform_metrics_check_count_positive'
-
- def up
- add_check_constraint :ci_platform_metrics, 'count > 0', CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint :ci_platform_metrics, CONSTRAINT_NAME
- end
-end
diff --git a/db/migrate/20200908212414_add_feature_flag_events_to_web_hooks.rb b/db/migrate/20200908212414_add_feature_flag_events_to_web_hooks.rb
deleted file mode 100644
index 40e2b37b390..00000000000
--- a/db/migrate/20200908212414_add_feature_flag_events_to_web_hooks.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddFeatureFlagEventsToWebHooks < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :web_hooks, :feature_flag_events, :boolean, null: false, default: false
- end
-end
diff --git a/db/migrate/20200909040555_create_package_events.rb b/db/migrate/20200909040555_create_package_events.rb
deleted file mode 100644
index 000ff051a7c..00000000000
--- a/db/migrate/20200909040555_create_package_events.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackageEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- create_table :packages_events do |t|
- t.integer :event_type, null: false, limit: 2
- t.integer :event_scope, null: false, limit: 2
- t.integer :originator_type, null: false, limit: 2
- t.bigint :originator
- t.datetime_with_timezone :created_at, null: false
-
- t.references :package, primary_key: false, default: nil, index: true, foreign_key: { to_table: :packages_packages, on_delete: :nullify }, type: :bigint
- end
- end
-end
diff --git a/db/migrate/20200909083339_add_change_reviewer_merge_request_to_notification_settings.rb b/db/migrate/20200909083339_add_change_reviewer_merge_request_to_notification_settings.rb
deleted file mode 100644
index 7024cc4a263..00000000000
--- a/db/migrate/20200909083339_add_change_reviewer_merge_request_to_notification_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddChangeReviewerMergeRequestToNotificationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :notification_settings, :change_reviewer_merge_request, :boolean
- end
-end
diff --git a/db/migrate/20200911120132_create_pages_deployments.rb b/db/migrate/20200911120132_create_pages_deployments.rb
deleted file mode 100644
index 25327a76900..00000000000
--- a/db/migrate/20200911120132_create_pages_deployments.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePagesDeployments < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :pages_deployments, if_not_exists: true do |t|
- t.timestamps_with_timezone
-
- t.bigint :project_id, index: true, null: false
- t.bigint :ci_build_id, index: true
-
- t.integer :file_store, null: false, limit: 2
- t.integer :size, null: false
- t.text :file, null: false
- end
-
- add_text_limit :pages_deployments, :file, 255
- end
-
- def down
- drop_table :pages_deployments
- end
-end
diff --git a/db/migrate/20200911121027_add_pages_deployment_project_foreign_key.rb b/db/migrate/20200911121027_add_pages_deployment_project_foreign_key.rb
deleted file mode 100644
index 665b9de9230..00000000000
--- a/db/migrate/20200911121027_add_pages_deployment_project_foreign_key.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddPagesDeploymentProjectForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :pages_deployments, :projects, column: :project_id, on_delete: :cascade
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :pages_deployments, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20200911121048_add_pages_deployment_ci_build_foreign_key.rb b/db/migrate/20200911121048_add_pages_deployment_ci_build_foreign_key.rb
deleted file mode 100644
index 83f38b2fae3..00000000000
--- a/db/migrate/20200911121048_add_pages_deployment_ci_build_foreign_key.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddPagesDeploymentCiBuildForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :pages_deployments, :ci_builds, column: :ci_build_id, on_delete: :nullify
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :pages_deployments, column: :ci_build_id
- end
- end
-end
diff --git a/db/migrate/20200912152943_rename_admin_notification_email_application_setting.rb b/db/migrate/20200912152943_rename_admin_notification_email_application_setting.rb
deleted file mode 100644
index b469099014d..00000000000
--- a/db/migrate/20200912152943_rename_admin_notification_email_application_setting.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RenameAdminNotificationEmailApplicationSetting < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- rename_column_concurrently :application_settings, :admin_notification_email, :abuse_notification_email
- end
-
- def down
- undo_rename_column_concurrently :application_settings, :admin_notification_email, :abuse_notification_email
- end
-end
diff --git a/db/migrate/20200912193210_add_scheduling_issues_temp_indexes.rb b/db/migrate/20200912193210_add_scheduling_issues_temp_indexes.rb
deleted file mode 100644
index bc2b8d4ce97..00000000000
--- a/db/migrate/20200912193210_add_scheduling_issues_temp_indexes.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddSchedulingIssuesTempIndexes < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :issue_links, [:source_id], where: 'link_type = 1', name: 'tmp_idx_blocking_type_links'
- add_concurrent_index :issue_links, [:target_id], where: 'link_type = 2', name: 'tmp_idx_blocked_by_type_links'
- add_concurrent_index :issues, :id, where: '(state_id = 1 AND blocking_issues_count = 0)', name: 'tmp_idx_index_issues_with_outdate_blocking_count'
- end
-
- def down
- remove_concurrent_index_by_name(:issue_links, 'tmp_idx_blocking_type_links')
- remove_concurrent_index_by_name(:issue_links, 'tmp_idx_blocked_by_type_links')
- remove_concurrent_index_by_name(:issues, 'tmp_idx_index_issues_with_outdate_blocking_count')
- end
-end
diff --git a/db/migrate/20200913115700_add_kroki_application_settings.rb b/db/migrate/20200913115700_add_kroki_application_settings.rb
deleted file mode 100644
index 84d490c2980..00000000000
--- a/db/migrate/20200913115700_add_kroki_application_settings.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddKrokiApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in 20201011005400_add_text_limit_to_application_settings_kroki_url.rb
- #
- def change
- add_column :application_settings, :kroki_url, :text
- add_column :application_settings, :kroki_enabled, :boolean, default: false, null: false
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20200914070140_add_expiration_policy_started_at_to_container_repositories.rb b/db/migrate/20200914070140_add_expiration_policy_started_at_to_container_repositories.rb
deleted file mode 100644
index fa787fe98b0..00000000000
--- a/db/migrate/20200914070140_add_expiration_policy_started_at_to_container_repositories.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddExpirationPolicyStartedAtToContainerRepositories < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column(:container_repositories, :expiration_policy_started_at, :datetime_with_timezone)
- end
-
- def down
- remove_column(:container_repositories, :expiration_policy_started_at)
- end
-end
diff --git a/db/migrate/20200914091326_change_build_pending_state_enums.rb b/db/migrate/20200914091326_change_build_pending_state_enums.rb
deleted file mode 100644
index dadb15e8844..00000000000
--- a/db/migrate/20200914091326_change_build_pending_state_enums.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeBuildPendingStateEnums < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- change_column :ci_build_pending_states, :state, :integer, limit: 2
- change_column :ci_build_pending_states, :failure_reason, :integer, limit: 2
- end
-
- def down
- change_column :ci_build_pending_states, :state, :integer
- change_column :ci_build_pending_states, :failure_reason, :integer
- end
-end
diff --git a/db/migrate/20200914104642_modify_merge_request_api_index.rb b/db/migrate/20200914104642_modify_merge_request_api_index.rb
deleted file mode 100644
index c21404a10c2..00000000000
--- a/db/migrate/20200914104642_modify_merge_request_api_index.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class ModifyMergeRequestApiIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :merge_requests, [:target_project_id, :created_at, :id], name: :index_merge_requests_on_target_project_id_and_created_at_and_id
- end
-
- def down
- remove_concurrent_index :merge_requests, [:target_project_id, :created_at, :id], name: :index_merge_requests_on_target_project_id_and_created_at_and_id
- end
-end
diff --git a/db/migrate/20200914105202_remove_old_merge_request_api_index.rb b/db/migrate/20200914105202_remove_old_merge_request_api_index.rb
deleted file mode 100644
index 826833dbfb2..00000000000
--- a/db/migrate/20200914105202_remove_old_merge_request_api_index.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveOldMergeRequestApiIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index :merge_requests, [:target_project_id, :created_at], name: :index_merge_requests_target_project_id_created_at
- end
-
- def down
- add_concurrent_index :merge_requests, [:target_project_id, :created_at], name: :index_merge_requests_target_project_id_created_at
- end
-end
diff --git a/db/migrate/20200914155135_add_deduplicated_flag_into_security_findings_table.rb b/db/migrate/20200914155135_add_deduplicated_flag_into_security_findings_table.rb
deleted file mode 100644
index f403c2d9a07..00000000000
--- a/db/migrate/20200914155135_add_deduplicated_flag_into_security_findings_table.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddDeduplicatedFlagIntoSecurityFindingsTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :security_findings, :deduplicated, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20200914183227_add_index_on_deduplicated_column_of_security_findings.rb b/db/migrate/20200914183227_add_index_on_deduplicated_column_of_security_findings.rb
deleted file mode 100644
index 1d0f656df4d..00000000000
--- a/db/migrate/20200914183227_add_index_on_deduplicated_column_of_security_findings.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnDeduplicatedColumnOfSecurityFindings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_security_findings_on_scan_id_and_deduplicated'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :security_findings, [:scan_id, :deduplicated], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :security_findings, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200914184212_remove_index_on_security_findings_scan_id.rb b/db/migrate/20200914184212_remove_index_on_security_findings_scan_id.rb
deleted file mode 100644
index 342dba537d5..00000000000
--- a/db/migrate/20200914184212_remove_index_on_security_findings_scan_id.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexOnSecurityFindingsScanId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_security_findings_on_scan_id'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :security_findings, INDEX_NAME
- end
-
- def down
- add_concurrent_index :security_findings, :scan_id, name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20200915134004_add_indices_to_approval_project_rules.rb b/db/migrate/20200915134004_add_indices_to_approval_project_rules.rb
deleted file mode 100644
index b7b0e1da2cb..00000000000
--- a/db/migrate/20200915134004_add_indices_to_approval_project_rules.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddIndicesToApprovalProjectRules < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- RULE_TYPE_INDEX_NAME = 'index_approval_project_rules_on_id_with_regular_type'
- RULE_ID_INDEX_NAME = 'index_approval_project_rules_users_on_approval_project_rule_id'
-
- def up
- add_concurrent_index :approval_project_rules, :id, where: 'rule_type = 0', name: RULE_TYPE_INDEX_NAME
- add_concurrent_index :approval_project_rules_users, :approval_project_rule_id, name: RULE_ID_INDEX_NAME
- end
-
- def down
- remove_concurrent_index :approval_project_rules, :id, where: 'rule_type = 0', name: RULE_TYPE_INDEX_NAME
- remove_concurrent_index :approval_project_rules_users, :approval_project_rule_id, name: RULE_ID_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200915152641_add_verification_state_to_terraform_state_version.rb b/db/migrate/20200915152641_add_verification_state_to_terraform_state_version.rb
deleted file mode 100644
index 9cc9a702397..00000000000
--- a/db/migrate/20200915152641_add_verification_state_to_terraform_state_version.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddVerificationStateToTerraformStateVersion < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_table(:terraform_state_versions) do |t|
- t.integer :verification_retry_count, limit: 2
- t.column :verification_retry_at, :datetime_with_timezone
- t.column :verified_at, :datetime_with_timezone
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
-
- # rubocop:disable Migration/AddLimitToTextColumns
- t.text :verification_failure
- # rubocop:enable Migration/AddLimitToTextColumns
- end
- end
-end
diff --git a/db/migrate/20200915164448_add_verification_failure_limit_to_terraform_state_version.rb b/db/migrate/20200915164448_add_verification_failure_limit_to_terraform_state_version.rb
deleted file mode 100644
index 810057a5f54..00000000000
--- a/db/migrate/20200915164448_add_verification_failure_limit_to_terraform_state_version.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddVerificationFailureLimitToTerraformStateVersion < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'tf_state_versions_verification_failure_text_limit'
-
- def up
- add_text_limit :terraform_state_versions, :verification_failure, 255, constraint_name: CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint(:terraform_state_versions, CONSTRAINT_NAME)
- end
-end
diff --git a/db/migrate/20200915164844_add_verification_failure_index_to_terraform_state_version.rb b/db/migrate/20200915164844_add_verification_failure_index_to_terraform_state_version.rb
deleted file mode 100644
index 423484e74bb..00000000000
--- a/db/migrate/20200915164844_add_verification_failure_index_to_terraform_state_version.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class AddVerificationFailureIndexToTerraformStateVersion < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- FAILURE_INDEX_NAME = 'terraform_state_versions_verification_failure_partial'
- CHECKSUM_INDEX_NAME = 'terraform_state_versions_verification_checksum_partial'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :terraform_state_versions, :verification_failure,
- where: "(verification_failure IS NOT NULL)",
- name: FAILURE_INDEX_NAME
- add_concurrent_index :terraform_state_versions, :verification_checksum,
- where: "(verification_checksum IS NOT NULL)",
- name: CHECKSUM_INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :terraform_state_versions, FAILURE_INDEX_NAME
- remove_concurrent_index_by_name :terraform_state_versions, CHECKSUM_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200916120837_add_index_to_members_for_unaccepted_invitations.rb b/db/migrate/20200916120837_add_index_to_members_for_unaccepted_invitations.rb
deleted file mode 100644
index 3b0e4b99eb5..00000000000
--- a/db/migrate/20200916120837_add_index_to_members_for_unaccepted_invitations.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToMembersForUnacceptedInvitations < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = 'idx_members_created_at_user_id_invite_token'
- INDEX_SCOPE = 'invite_token IS NOT NULL AND user_id IS NULL'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:members, :created_at, where: INDEX_SCOPE, name: INDEX_NAME)
- end
-
- def down
- remove_concurrent_index(:members, :created_at, where: INDEX_SCOPE, name: INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200916135044_add_state_id_index_to_merge_requests.rb b/db/migrate/20200916135044_add_state_id_index_to_merge_requests.rb
deleted file mode 100644
index bec162ff888..00000000000
--- a/db/migrate/20200916135044_add_state_id_index_to_merge_requests.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddStateIdIndexToMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :merge_requests, [:target_project_id, :iid, :state_id], name: :index_merge_requests_on_target_project_id_and_iid_and_state_id
- end
-
- def down
- remove_concurrent_index :merge_requests, [:target_project_id, :iid, :state_id], name: :index_merge_requests_on_target_project_id_and_iid_and_state_id
- end
-end
diff --git a/db/migrate/20200916151442_add_result_index_to_authentication_events.rb b/db/migrate/20200916151442_add_result_index_to_authentication_events.rb
deleted file mode 100644
index 13b0521038e..00000000000
--- a/db/migrate/20200916151442_add_result_index_to_authentication_events.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddResultIndexToAuthenticationEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_authentication_events_on_provider_user_id_created_at'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :authentication_events, [:provider, :user_id, :created_at], where: 'result = 1', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :authentication_events, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200916165232_add_debian_max_file_size_to_plan_limits.rb b/db/migrate/20200916165232_add_debian_max_file_size_to_plan_limits.rb
deleted file mode 100644
index 9a91a5d2195..00000000000
--- a/db/migrate/20200916165232_add_debian_max_file_size_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddDebianMaxFileSizeToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :plan_limits, :debian_max_file_size, :bigint, default: 3.gigabytes, null: false
- end
-end
diff --git a/db/migrate/20200917121650_add_help_page_documentation_url_to_application_settings.rb b/db/migrate/20200917121650_add_help_page_documentation_url_to_application_settings.rb
deleted file mode 100644
index 21259b633b1..00000000000
--- a/db/migrate/20200917121650_add_help_page_documentation_url_to_application_settings.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AddHelpPageDocumentationUrlToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in 20200921113722_add_text_limit_to_help_page_documentation_url.rb
- def change
- add_column :application_settings, :help_page_documentation_base_url, :text
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20200919200318_add_default_branch_name_to_namespace_settings.rb b/db/migrate/20200919200318_add_default_branch_name_to_namespace_settings.rb
deleted file mode 100644
index c8c856c7533..00000000000
--- a/db/migrate/20200919200318_add_default_branch_name_to_namespace_settings.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultBranchNameToNamespaceSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
-
- # limit is added in 20200919204155_add_text_limit_to_namespace_settings_default_branch_name
- #
- def change
- add_column :namespace_settings, :default_branch_name, :text
- end
-
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20200919204155_add_text_limit_to_namespace_settings_default_branch_name.rb b/db/migrate/20200919204155_add_text_limit_to_namespace_settings_default_branch_name.rb
deleted file mode 100644
index 174a1a9c556..00000000000
--- a/db/migrate/20200919204155_add_text_limit_to_namespace_settings_default_branch_name.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToNamespaceSettingsDefaultBranchName < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :namespace_settings, :default_branch_name, 255
- end
-
- def down
- # Down is required as `add_text_limit` is not reversible
- #
- remove_text_limit :namespace_settings, :default_branch_name
- end
-end
diff --git a/db/migrate/20200920130356_add_container_expiration_policy_worker_settings_to_application_settings.rb b/db/migrate/20200920130356_add_container_expiration_policy_worker_settings_to_application_settings.rb
deleted file mode 100644
index 7501f150283..00000000000
--- a/db/migrate/20200920130356_add_container_expiration_policy_worker_settings_to_application_settings.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddContainerExpirationPolicyWorkerSettingsToApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- unless column_exists?(:application_settings, :container_registry_expiration_policies_worker_capacity)
- add_column(:application_settings, :container_registry_expiration_policies_worker_capacity, :integer, default: 0, null: false)
- end
- end
-
- def down
- if column_exists?(:application_settings, :container_registry_expiration_policies_worker_capacity)
- remove_column(:application_settings, :container_registry_expiration_policies_worker_capacity)
- end
- end
-end
diff --git a/db/migrate/20200921093826_add_index_to_user_preferences.rb b/db/migrate/20200921093826_add_index_to_user_preferences.rb
deleted file mode 100644
index 78b04eb7a83..00000000000
--- a/db/migrate/20200921093826_add_index_to_user_preferences.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToUserPreferences < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :user_preferences, :gitpod_enabled, name: :index_user_preferences_on_gitpod_enabled
- end
-
- def down
- remove_concurrent_index :user_preferences, :gitpod_enabled, name: :index_user_preferences_on_gitpod_enabled
- end
-end
diff --git a/db/migrate/20200921113722_add_text_limit_to_help_page_documentation_url.rb b/db/migrate/20200921113722_add_text_limit_to_help_page_documentation_url.rb
deleted file mode 100644
index a262ea559a5..00000000000
--- a/db/migrate/20200921113722_add_text_limit_to_help_page_documentation_url.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToHelpPageDocumentationUrl < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :application_settings, :help_page_documentation_base_url, 255
- end
-
- def down
- remove_text_limit :application_settings, :help_page_documentation_base_url
- end
-end
diff --git a/db/migrate/20200921130028_add_pages_deployment_id_to_pages_metadata.rb b/db/migrate/20200921130028_add_pages_deployment_id_to_pages_metadata.rb
deleted file mode 100644
index 395ce43d8ac..00000000000
--- a/db/migrate/20200921130028_add_pages_deployment_id_to_pages_metadata.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddPagesDeploymentIdToPagesMetadata < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :project_pages_metadata, :pages_deployment_id, :bigint
- end
-end
diff --git a/db/migrate/20200921131313_add_foreign_key_to_pages_deployment_id_in_project_pages_metadata.rb b/db/migrate/20200921131313_add_foreign_key_to_pages_deployment_id_in_project_pages_metadata.rb
deleted file mode 100644
index 8611f3ab943..00000000000
--- a/db/migrate/20200921131313_add_foreign_key_to_pages_deployment_id_in_project_pages_metadata.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToPagesDeploymentIdInProjectPagesMetadata < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_project_pages_metadata_on_pages_deployment_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:project_pages_metadata, :pages_deployment_id, name: INDEX_NAME)
- add_concurrent_foreign_key :project_pages_metadata, :pages_deployments, column: :pages_deployment_id, on_delete: :nullify
- end
-
- def down
- remove_foreign_key_if_exists :project_pages_metadata, column: :pages_deployment_id
- remove_concurrent_index_by_name(:project_pages_metadata, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200921203231_remove_duplicate_cluster_agents_index.rb b/db/migrate/20200921203231_remove_duplicate_cluster_agents_index.rb
deleted file mode 100644
index 3f073e32d84..00000000000
--- a/db/migrate/20200921203231_remove_duplicate_cluster_agents_index.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveDuplicateClusterAgentsIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX = 'index_cluster_agents_on_project_id'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :cluster_agents, INDEX
- end
-
- def down
- add_concurrent_index :cluster_agents, :project_id, name: INDEX
- end
-end
diff --git a/db/migrate/20200922052316_create_issue_email_participants.rb b/db/migrate/20200922052316_create_issue_email_participants.rb
deleted file mode 100644
index a8aeb9d9a5a..00000000000
--- a/db/migrate/20200922052316_create_issue_email_participants.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class CreateIssueEmailParticipants < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:issue_email_participants)
- with_lock_retries do
- create_table :issue_email_participants do |t|
- t.references :issue, index: false, null: false, foreign_key: { on_delete: :cascade }
- t.datetime_with_timezone :created_at, null: false
- t.datetime_with_timezone :updated_at, null: false
- t.text :email, null: false
-
- t.index [:issue_id, :email], unique: true
- end
- end
-
- add_text_limit(:issue_email_participants, :email, 255)
- end
- end
-
- def down
- with_lock_retries do
- drop_table :issue_email_participants
- end
- end
-end
diff --git a/db/migrate/20200922075244_add_compliance_framework_model.rb b/db/migrate/20200922075244_add_compliance_framework_model.rb
deleted file mode 100644
index 376482d9005..00000000000
--- a/db/migrate/20200922075244_add_compliance_framework_model.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class AddComplianceFrameworkModel < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:compliance_management_frameworks)
- with_lock_retries do
- create_table :compliance_management_frameworks do |t|
- t.references :group, foreign_key: { to_table: :namespaces, on_delete: :cascade }, null: false, index: false
- t.text :name, null: false
- t.text :description, null: false
- t.text :color, null: false
- t.index [:group_id, :name], unique: true
- end
- end
- end
-
- add_text_limit :compliance_management_frameworks, :name, 255
- add_text_limit :compliance_management_frameworks, :description, 255
- add_text_limit :compliance_management_frameworks, :color, 10
- end
-
- def down
- with_lock_retries do
- drop_table :compliance_management_frameworks
- end
- end
-end
diff --git a/db/migrate/20200922093004_add_postgres_index_view.rb b/db/migrate/20200922093004_add_postgres_index_view.rb
deleted file mode 100644
index c16eae4dd0b..00000000000
--- a/db/migrate/20200922093004_add_postgres_index_view.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class AddPostgresIndexView < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute(<<~SQL)
- CREATE VIEW postgres_indexes AS
- SELECT
- pg_namespace.nspname || '.' || pg_class.relname as identifier,
- pg_index.indexrelid,
- pg_namespace.nspname as schema,
- pg_class.relname as name,
- pg_index.indisunique as unique,
- pg_index.indisvalid as valid_index,
- pg_class.relispartition as partitioned,
- pg_index.indisexclusion as exclusion,
- pg_indexes.indexdef as definition,
- pg_relation_size(pg_class.oid) as ondisk_size_bytes
- FROM pg_index
- INNER JOIN pg_class ON pg_class.oid = pg_index.indexrelid
- INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
- INNER JOIN pg_indexes ON pg_class.relname = pg_indexes.indexname
- WHERE pg_namespace.nspname <> 'pg_catalog'
- SQL
- end
-
- def down
- execute(<<~SQL)
- DROP VIEW postgres_indexes
- SQL
- end
-end
diff --git a/db/migrate/20200922133949_create_bulk_import.rb b/db/migrate/20200922133949_create_bulk_import.rb
deleted file mode 100644
index 29d770d13ff..00000000000
--- a/db/migrate/20200922133949_create_bulk_import.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class CreateBulkImport < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :bulk_imports do |t|
- t.references :user, type: :integer, index: true, null: false, foreign_key: { on_delete: :cascade }
-
- t.integer :source_type, null: false, limit: 2
- t.integer :status, null: false, limit: 2
-
- t.timestamps_with_timezone
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :bulk_imports
- end
- end
-end
diff --git a/db/migrate/20200923071622_add_description_to_requirements.rb b/db/migrate/20200923071622_add_description_to_requirements.rb
deleted file mode 100644
index b4b1250c10a..00000000000
--- a/db/migrate/20200923071622_add_description_to_requirements.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class AddDescriptionToRequirements < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit for description is added in 20200923071644_add_text_limit_to_requirements_description
- # for description_html limit is not set because it's for caching purposes and
- # its value is generated from `description`
- def change
- add_column :requirements, :description, :text
- add_column :requirements, :description_html, :text
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20200923071644_add_text_limit_to_requirements_description.rb b/db/migrate/20200923071644_add_text_limit_to_requirements_description.rb
deleted file mode 100644
index 0172d6bbba3..00000000000
--- a/db/migrate/20200923071644_add_text_limit_to_requirements_description.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToRequirementsDescription < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :requirements, :description, 10_000
- end
-
- def down
- remove_text_limit :requirements, :description
- end
-end
diff --git a/db/migrate/20200923102312_update_programming_language_colors.rb b/db/migrate/20200923102312_update_programming_language_colors.rb
deleted file mode 100644
index 37233bd3148..00000000000
--- a/db/migrate/20200923102312_update_programming_language_colors.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-require 'yaml'
-
-class UpdateProgrammingLanguageColors < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- class ProgrammingLanguage < ActiveRecord::Base; end
-
- def up
- YAML.load_file("vendor/languages.yml").each do |name, metadata|
- color = metadata["color"]
- next unless color.present?
-
- ProgrammingLanguage.where(name: name).update(color: color)
- end
- end
-
- def down
- # noop
- end
-end
diff --git a/db/migrate/20200923130057_remove_tmp_container_scanning_index.rb b/db/migrate/20200923130057_remove_tmp_container_scanning_index.rb
deleted file mode 100644
index e9ab6f9ff15..00000000000
--- a/db/migrate/20200923130057_remove_tmp_container_scanning_index.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveTmpContainerScanningIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'tmp_index_for_fixing_inconsistent_vulnerability_occurrences'
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name(:vulnerability_occurrences, INDEX_NAME)
- end
-
- def down
- # report_type: 2 container scanning
- add_concurrent_index(:vulnerability_occurrences, :id,
- where: "LENGTH(location_fingerprint) = 40 AND report_type = 2",
- name: INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200923140404_add_postgres_reindex_actions_table.rb b/db/migrate/20200923140404_add_postgres_reindex_actions_table.rb
deleted file mode 100644
index ed37e44e201..00000000000
--- a/db/migrate/20200923140404_add_postgres_reindex_actions_table.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class AddPostgresReindexActionsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :postgres_reindex_actions, if_not_exists: true do |t|
- t.datetime_with_timezone :action_start, null: false
- t.datetime_with_timezone :action_end
- t.bigint :ondisk_size_bytes_start, null: false
- t.bigint :ondisk_size_bytes_end
- t.integer :state, limit: 2, null: false, default: 0
- t.text :index_identifier, null: false, index: true
- end
-
- add_text_limit(:postgres_reindex_actions, :index_identifier, 255)
- end
-
- def down
- drop_table :postgres_reindex_actions
- end
-end
diff --git a/db/migrate/20200924035825_add_options_to_dast_scanner_profile.rb b/db/migrate/20200924035825_add_options_to_dast_scanner_profile.rb
deleted file mode 100644
index 588ce8fada7..00000000000
--- a/db/migrate/20200924035825_add_options_to_dast_scanner_profile.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddOptionsToDastScannerProfile < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- PASSIVE_SCAN_ENUM_VALUE = 1
-
- def change
- add_column :dast_scanner_profiles, :scan_type, :integer, limit: 2, default: PASSIVE_SCAN_ENUM_VALUE, null: false
- add_column :dast_scanner_profiles, :use_ajax_spider, :boolean, default: false, null: false
- add_column :dast_scanner_profiles, :show_debug_messages, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20200925112104_create_bulk_import_configurations.rb b/db/migrate/20200925112104_create_bulk_import_configurations.rb
deleted file mode 100644
index b894cdeefbc..00000000000
--- a/db/migrate/20200925112104_create_bulk_import_configurations.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class CreateBulkImportConfigurations < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :bulk_import_configurations, if_not_exists: true do |t|
- t.references :bulk_import, type: :integer, index: true, null: false, foreign_key: { on_delete: :cascade }
-
- t.text :encrypted_url # rubocop: disable Migration/AddLimitToTextColumns
- t.text :encrypted_url_iv # rubocop: disable Migration/AddLimitToTextColumns
-
- t.text :encrypted_access_token # rubocop: disable Migration/AddLimitToTextColumns
- t.text :encrypted_access_token_iv # rubocop: disable Migration/AddLimitToTextColumns
-
- t.timestamps_with_timezone
- end
- end
-
- def down
- drop_table :bulk_import_configurations
- end
-end
diff --git a/db/migrate/20200925114522_create_bulk_import_entities.rb b/db/migrate/20200925114522_create_bulk_import_entities.rb
deleted file mode 100644
index c78c4aee9ae..00000000000
--- a/db/migrate/20200925114522_create_bulk_import_entities.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-class CreateBulkImportEntities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :bulk_import_entities, if_not_exists: true do |t|
- t.bigint :bulk_import_id, index: true, null: false
- t.bigint :parent_id, index: true
- t.bigint :namespace_id, index: true
- t.bigint :project_id, index: true
-
- t.integer :source_type, null: false, limit: 2
- t.text :source_full_path, null: false
-
- t.text :destination_name, null: false
- t.text :destination_namespace, null: false
-
- t.integer :status, null: false, limit: 2
- t.text :jid
-
- t.timestamps_with_timezone
- end
-
- add_text_limit(:bulk_import_entities, :source_full_path, 255)
- add_text_limit(:bulk_import_entities, :destination_name, 255)
- add_text_limit(:bulk_import_entities, :destination_namespace, 255)
- add_text_limit(:bulk_import_entities, :jid, 255)
- end
-
- def down
- drop_table :bulk_import_entities
- end
-end
diff --git a/db/migrate/20200925125321_add_u2f_id_to_webauthn_registration.rb b/db/migrate/20200925125321_add_u2f_id_to_webauthn_registration.rb
deleted file mode 100644
index 8a352fc6e9f..00000000000
--- a/db/migrate/20200925125321_add_u2f_id_to_webauthn_registration.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddU2fIdToWebauthnRegistration < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- add_column :webauthn_registrations, :u2f_registration_id, :integer
- end
-end
diff --git a/db/migrate/20200925153423_add_bulk_import_foreign_key_to_bulk_import_entities.rb b/db/migrate/20200925153423_add_bulk_import_foreign_key_to_bulk_import_entities.rb
deleted file mode 100644
index fca4070d990..00000000000
--- a/db/migrate/20200925153423_add_bulk_import_foreign_key_to_bulk_import_entities.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddBulkImportForeignKeyToBulkImportEntities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :bulk_import_entities, :bulk_imports, column: :bulk_import_id, on_delete: :cascade
- end
-
- def down
- remove_foreign_key :bulk_import_entities, column: :bulk_import_id
- end
-end
diff --git a/db/migrate/20200925193815_add_parent_foreign_key_to_bulk_import_entities.rb b/db/migrate/20200925193815_add_parent_foreign_key_to_bulk_import_entities.rb
deleted file mode 100644
index 37e38c384b8..00000000000
--- a/db/migrate/20200925193815_add_parent_foreign_key_to_bulk_import_entities.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddParentForeignKeyToBulkImportEntities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :bulk_import_entities, :bulk_import_entities, column: :parent_id, on_delete: :cascade
- end
-
- def down
- remove_foreign_key :bulk_import_entities, column: :parent_id
- end
-end
diff --git a/db/migrate/20200925193906_add_namespace_foreign_key_to_bulk_import_entities.rb b/db/migrate/20200925193906_add_namespace_foreign_key_to_bulk_import_entities.rb
deleted file mode 100644
index 13212395488..00000000000
--- a/db/migrate/20200925193906_add_namespace_foreign_key_to_bulk_import_entities.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddNamespaceForeignKeyToBulkImportEntities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :bulk_import_entities, :namespaces, column: :namespace_id
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :bulk_import_entities, column: :namespace_id
- end
- end
-end
diff --git a/db/migrate/20200925194006_add_project_foreign_key_to_bulk_import_entities.rb b/db/migrate/20200925194006_add_project_foreign_key_to_bulk_import_entities.rb
deleted file mode 100644
index 975f2b1ef4a..00000000000
--- a/db/migrate/20200925194006_add_project_foreign_key_to_bulk_import_entities.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectForeignKeyToBulkImportEntities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :bulk_import_entities, :projects, column: :project_id
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :bulk_import_entities, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20200927224750_add_incident_issue_type_index_to_issues.rb b/db/migrate/20200927224750_add_incident_issue_type_index_to_issues.rb
deleted file mode 100644
index ed4dd5b9cc1..00000000000
--- a/db/migrate/20200927224750_add_incident_issue_type_index_to_issues.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddIncidentIssueTypeIndexToIssues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INCIDENT_ISSUE_TYPE = 1
- INDEX_NAME = 'index_issues_project_id_issue_type_incident'
-
- def up
- add_concurrent_index :issues, :project_id, where: "issue_type = #{INCIDENT_ISSUE_TYPE}", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name(:issues, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200928095732_add_state_to_dast_site_validation.rb b/db/migrate/20200928095732_add_state_to_dast_site_validation.rb
deleted file mode 100644
index 7adeef54d71..00000000000
--- a/db/migrate/20200928095732_add_state_to_dast_site_validation.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AddStateToDastSiteValidation < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in 20200928100408_add_text_limit_to_dast_site_validation_state.rb
- def change
- add_column :dast_site_validations, :state, :text, default: :pending, null: false
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20200928100408_add_text_limit_to_dast_site_validation_state.rb b/db/migrate/20200928100408_add_text_limit_to_dast_site_validation_state.rb
deleted file mode 100644
index 18bf7ee4bdc..00000000000
--- a/db/migrate/20200928100408_add_text_limit_to_dast_site_validation_state.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToDastSiteValidationState < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :dast_site_validations, :state, 255
- end
-
- def down
- remove_text_limit :dast_site_validations, :state
- end
-end
diff --git a/db/migrate/20200928123510_add_expiration_policy_cleanup_status_to_container_repositories.rb b/db/migrate/20200928123510_add_expiration_policy_cleanup_status_to_container_repositories.rb
deleted file mode 100644
index 4d611a56e9c..00000000000
--- a/db/migrate/20200928123510_add_expiration_policy_cleanup_status_to_container_repositories.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class AddExpirationPolicyCleanupStatusToContainerRepositories < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'idx_container_repositories_on_exp_cleanup_status_and_start_date'
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:container_repositories, :expiration_policy_cleanup_status)
- add_column(:container_repositories, :expiration_policy_cleanup_status, :integer, limit: 2, default: 0, null: false)
- end
-
- add_concurrent_index(:container_repositories, [:expiration_policy_cleanup_status, :expiration_policy_started_at], name: INDEX_NAME)
- end
-
- def down
- remove_concurrent_index(:container_repositories, [:expiration_policy_cleanup_status, :expiration_policy_started_at], name: INDEX_NAME)
-
- if column_exists?(:container_repositories, :expiration_policy_cleanup_status)
- remove_column(:container_repositories, :expiration_policy_cleanup_status)
- end
- end
-end
diff --git a/db/migrate/20200928125258_add_foreign_key_to_u2f_reg_id_in_webauthn_regs.rb b/db/migrate/20200928125258_add_foreign_key_to_u2f_reg_id_in_webauthn_regs.rb
deleted file mode 100644
index b76b826658e..00000000000
--- a/db/migrate/20200928125258_add_foreign_key_to_u2f_reg_id_in_webauthn_regs.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToU2fRegIdInWebauthnRegs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_webauthn_registrations_on_u2f_registration_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :webauthn_registrations, :u2f_registration_id, where: 'u2f_registration_id IS NOT NULL', name: INDEX_NAME
- add_concurrent_foreign_key :webauthn_registrations, :u2f_registrations, column: :u2f_registration_id, on_delete: :cascade
- end
-
- def down
- remove_foreign_key_if_exists :webauthn_registrations, column: :u2f_registration_id
- remove_concurrent_index_by_name(:webauthn_registrations, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200928131934_create_required_code_owners_sections.rb b/db/migrate/20200928131934_create_required_code_owners_sections.rb
deleted file mode 100644
index f2dfd4007e5..00000000000
--- a/db/migrate/20200928131934_create_required_code_owners_sections.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class CreateRequiredCodeOwnersSections < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- create_table :required_code_owners_sections, if_not_exists: true do |t|
- t.references :protected_branch, null: false, foreign_key: { on_delete: :cascade }
- t.text :name, null: false
- end
- end
-
- add_text_limit :required_code_owners_sections, :name, 1024
- end
-
- def down
- with_lock_retries do
- drop_table :required_code_owners_sections, if_exists: true
- end
- end
-end
diff --git a/db/migrate/20200928164807_add_index_on_vulnerabilities_state_case.rb b/db/migrate/20200928164807_add_index_on_vulnerabilities_state_case.rb
deleted file mode 100644
index 7bfae7377d7..00000000000
--- a/db/migrate/20200928164807_add_index_on_vulnerabilities_state_case.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnVulnerabilitiesStateCase < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_vulnerabilities_on_state_case_id'
- STATE_ORDER_ARRAY_POSITION = 'ARRAY_POSITION(ARRAY[1, 4, 3, 2]::smallint[], state)'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :vulnerabilities, "#{STATE_ORDER_ARRAY_POSITION}, id DESC", name: INDEX_NAME
- add_concurrent_index :vulnerabilities, "#{STATE_ORDER_ARRAY_POSITION} DESC, id DESC", name: "#{INDEX_NAME}_desc"
- end
-
- def down
- remove_concurrent_index_by_name :vulnerabilities, "#{INDEX_NAME}_desc"
- remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
- end
-end
diff --git a/db/migrate/20200928203531_create_alert_management_http_integrations.rb b/db/migrate/20200928203531_create_alert_management_http_integrations.rb
deleted file mode 100644
index fe13fe400e3..00000000000
--- a/db/migrate/20200928203531_create_alert_management_http_integrations.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class CreateAlertManagementHttpIntegrations < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- UNIQUE_INDEX = 'index_http_integrations_on_active_and_project_and_endpoint'
-
- disable_ddl_transaction!
-
- def up
- create_table :alert_management_http_integrations, if_not_exists: true do |t|
- t.timestamps_with_timezone
- t.bigint :project_id, index: true, null: false
- t.boolean :active, null: false, default: false
- t.text :encrypted_token, null: false
- t.text :encrypted_token_iv, null: false
- t.text :endpoint_identifier, null: false
- t.text :name, null: false
- end
-
- add_text_limit :alert_management_http_integrations, :encrypted_token, 255
- add_text_limit :alert_management_http_integrations, :encrypted_token_iv, 255
- add_text_limit :alert_management_http_integrations, :endpoint_identifier, 255
- add_text_limit :alert_management_http_integrations, :name, 255
-
- add_index :alert_management_http_integrations,
- [:active, :project_id, :endpoint_identifier],
- unique: true,
- name: UNIQUE_INDEX,
- where: 'active'
- end
-
- def down
- drop_table :alert_management_http_integrations
- end
-end
diff --git a/db/migrate/20200928210524_add_http_integrations_project_foreign_key.rb b/db/migrate/20200928210524_add_http_integrations_project_foreign_key.rb
deleted file mode 100644
index f59a5a0b5bb..00000000000
--- a/db/migrate/20200928210524_add_http_integrations_project_foreign_key.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddHttpIntegrationsProjectForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_foreign_key :alert_management_http_integrations, :projects, column: :project_id, on_delete: :cascade # rubocop:disable Migration/AddConcurrentForeignKey
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :alert_management_http_integrations, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20200928233632_remove_terraform_state_verification_indexes.rb b/db/migrate/20200928233632_remove_terraform_state_verification_indexes.rb
deleted file mode 100644
index b5a7bb5e39d..00000000000
--- a/db/migrate/20200928233632_remove_terraform_state_verification_indexes.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveTerraformStateVerificationIndexes < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CHECKSUM_INDEX_NAME = "terraform_states_verification_checksum_partial"
- FAILURE_INDEX_NAME = "terraform_states_verification_failure_partial"
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index :terraform_states, :verification_failure, name: FAILURE_INDEX_NAME
- remove_concurrent_index :terraform_states, :verification_checksum, name: CHECKSUM_INDEX_NAME
- end
-
- def down
- add_concurrent_index :terraform_states, :verification_failure, where: "(verification_failure IS NOT NULL)", name: FAILURE_INDEX_NAME
- add_concurrent_index :terraform_states, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: CHECKSUM_INDEX_NAME
- end
-end
diff --git a/db/migrate/20200929032729_add_sla_minutes_to_project_incident_management_settings.rb b/db/migrate/20200929032729_add_sla_minutes_to_project_incident_management_settings.rb
deleted file mode 100644
index 2848cdf8fcd..00000000000
--- a/db/migrate/20200929032729_add_sla_minutes_to_project_incident_management_settings.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class AddSlaMinutesToProjectIncidentManagementSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :project_incident_management_settings, :sla_timer, :boolean, default: false
- add_column :project_incident_management_settings, :sla_timer_minutes, :integer
- end
-end
diff --git a/db/migrate/20200929063159_add_require_admin_approval_after_user_signup_to_application_settings.rb b/db/migrate/20200929063159_add_require_admin_approval_after_user_signup_to_application_settings.rb
deleted file mode 100644
index 92d82757b79..00000000000
--- a/db/migrate/20200929063159_add_require_admin_approval_after_user_signup_to_application_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddRequireAdminApprovalAfterUserSignupToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :require_admin_approval_after_user_signup, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20200930094812_update_postgres_indexes_view.rb b/db/migrate/20200930094812_update_postgres_indexes_view.rb
deleted file mode 100644
index b36ea362e6f..00000000000
--- a/db/migrate/20200930094812_update_postgres_indexes_view.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-class UpdatePostgresIndexesView < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute(<<~SQL)
- CREATE OR REPLACE VIEW postgres_indexes AS
- SELECT
- pg_namespace.nspname || '.' || pg_class.relname as identifier,
- pg_index.indexrelid,
- pg_namespace.nspname as schema,
- pg_class.relname as name,
- pg_index.indisunique as unique,
- pg_index.indisvalid as valid_index,
- pg_class.relispartition as partitioned,
- pg_index.indisexclusion as exclusion,
- pg_indexes.indexdef as definition,
- pg_relation_size(pg_class.oid) as ondisk_size_bytes
- FROM pg_index
- INNER JOIN pg_class ON pg_class.oid = pg_index.indexrelid
- INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
- INNER JOIN pg_indexes ON pg_class.relname = pg_indexes.indexname
- WHERE pg_namespace.nspname <> 'pg_catalog'
- AND pg_namespace.nspname IN (
- current_schema(),
- 'gitlab_partitions_dynamic',
- 'gitlab_partitions_static'
- )
- SQL
- end
-
- def down
- execute(<<~SQL)
- CREATE OR REPLACE VIEW postgres_indexes AS
- SELECT
- pg_namespace.nspname || '.' || pg_class.relname as identifier,
- pg_index.indexrelid,
- pg_namespace.nspname as schema,
- pg_class.relname as name,
- pg_index.indisunique as unique,
- pg_index.indisvalid as valid_index,
- pg_class.relispartition as partitioned,
- pg_index.indisexclusion as exclusion,
- pg_indexes.indexdef as definition,
- pg_relation_size(pg_class.oid) as ondisk_size_bytes
- FROM pg_index
- INNER JOIN pg_class ON pg_class.oid = pg_index.indexrelid
- INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
- INNER JOIN pg_indexes ON pg_class.relname = pg_indexes.indexname
- WHERE pg_namespace.nspname <> 'pg_catalog'
- SQL
- end
-end
diff --git a/db/migrate/20200930131343_add_index_on_project_id_and_sha_to_deployments.rb b/db/migrate/20200930131343_add_index_on_project_id_and_sha_to_deployments.rb
deleted file mode 100644
index 19a536f8f6e..00000000000
--- a/db/migrate/20200930131343_add_index_on_project_id_and_sha_to_deployments.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddIndexOnProjectIdAndShaToDeployments < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
- INDEX_NAME = 'index_deployments_on_project_id_sha'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :deployments, [:project_id, :sha], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name(:deployments, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20200930132319_add_api_fuzzing_to_plan_limits.rb b/db/migrate/20200930132319_add_api_fuzzing_to_plan_limits.rb
deleted file mode 100644
index 9be79974ee4..00000000000
--- a/db/migrate/20200930132319_add_api_fuzzing_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddApiFuzzingToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :plan_limits, "ci_max_artifact_size_api_fuzzing", :integer, default: 0, null: false
- end
-end
diff --git a/db/migrate/20201002012659_add_issuable_sla_table.rb b/db/migrate/20201002012659_add_issuable_sla_table.rb
deleted file mode 100644
index c43187bf93a..00000000000
--- a/db/migrate/20201002012659_add_issuable_sla_table.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AddIssuableSlaTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :issuable_slas do |t|
- t.references :issue, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade }
- t.datetime_with_timezone :due_at, null: false
- end
- end
-end
diff --git a/db/migrate/20201004163918_remove_project_id_and_id_index_from_vulnerabilities_table.rb b/db/migrate/20201004163918_remove_project_id_and_id_index_from_vulnerabilities_table.rb
deleted file mode 100644
index 73028b6b795..00000000000
--- a/db/migrate/20201004163918_remove_project_id_and_id_index_from_vulnerabilities_table.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveProjectIdAndIdIndexFromVulnerabilitiesTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_vulnerabilities_on_project_id_and_id'
-
- disable_ddl_transaction!
-
- def up
- Gitlab::BackgroundMigration.steal('PopulateResolvedOnDefaultBranchColumn')
- remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
- end
-
- def down
- add_concurrent_index :vulnerabilities, [:project_id, :id], name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20201005092703_add_namespace_column_to_frameworks.rb b/db/migrate/20201005092703_add_namespace_column_to_frameworks.rb
deleted file mode 100644
index b7a9866e50b..00000000000
--- a/db/migrate/20201005092703_add_namespace_column_to_frameworks.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class AddNamespaceColumnToFrameworks < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'idx_on_compliance_management_frameworks_namespace_id_name'
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:compliance_management_frameworks, :namespace_id)
- add_column(:compliance_management_frameworks, :namespace_id, :integer)
- end
-
- add_concurrent_foreign_key(:compliance_management_frameworks, :namespaces, column: :namespace_id, on_delete: :cascade)
- add_concurrent_index(:compliance_management_frameworks, [:namespace_id, :name], unique: true, name: INDEX_NAME)
- end
-
- def down
- remove_concurrent_index_by_name(:compliance_management_frameworks, INDEX_NAME)
- remove_foreign_key_if_exists(:compliance_management_frameworks, :namespaces, column: :namespace_id)
-
- remove_column(:compliance_management_frameworks, :namespace_id)
- end
-end
diff --git a/db/migrate/20201005092709_remove_compliance_frameworks_group_id_fk.rb b/db/migrate/20201005092709_remove_compliance_frameworks_group_id_fk.rb
deleted file mode 100644
index dcbe48c03f9..00000000000
--- a/db/migrate/20201005092709_remove_compliance_frameworks_group_id_fk.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveComplianceFrameworksGroupIdFk < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_compliance_management_frameworks_on_group_id_and_name'
-
- class TmpComplianceFramework < ActiveRecord::Base
- self.table_name = 'compliance_management_frameworks'
-
- include EachBatch
- end
-
- disable_ddl_transaction!
-
- def up
- TmpComplianceFramework.each_batch(of: 100) do |query|
- query.update_all('namespace_id = group_id') # Copy data in case we rolled back before...
- end
-
- change_column_null(:compliance_management_frameworks, :group_id, true)
-
- remove_foreign_key_if_exists(:compliance_management_frameworks, :namespaces, column: :group_id)
- remove_concurrent_index_by_name(:compliance_management_frameworks, INDEX_NAME)
- end
-
- def down
- # This is just to make the rollback possible
- TmpComplianceFramework.each_batch(of: 100) do |query|
- query.update_all('group_id = namespace_id') # The group_id column is not in used at all
- end
-
- change_column_null(:compliance_management_frameworks, :group_id, false)
-
- add_concurrent_foreign_key(:compliance_management_frameworks, :namespaces, column: :group_id, on_delete: :cascade)
- add_concurrent_index(:compliance_management_frameworks, [:group_id, :name], unique: true, name: INDEX_NAME)
- end
-end
diff --git a/db/migrate/20201005092753_add_framework_id_to_project_framework_settings.rb b/db/migrate/20201005092753_add_framework_id_to_project_framework_settings.rb
deleted file mode 100644
index f9ac12dcfd2..00000000000
--- a/db/migrate/20201005092753_add_framework_id_to_project_framework_settings.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-class AddFrameworkIdToProjectFrameworkSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:project_compliance_framework_settings, :framework_id)
- with_lock_retries do
- add_column(:project_compliance_framework_settings, :framework_id, :bigint)
- end
- end
-
- add_concurrent_index(:project_compliance_framework_settings, :framework_id)
-
- add_concurrent_foreign_key(
- :project_compliance_framework_settings,
- :compliance_management_frameworks,
- column: :framework_id,
- on_delete: :cascade
- )
- end
-
- def down
- remove_foreign_key_if_exists(:project_compliance_framework_settings, :compliance_management_frameworks, column: :framework_id)
-
- with_lock_retries do
- remove_column(:project_compliance_framework_settings, :framework_id)
- end
- end
-end
diff --git a/db/migrate/20201006014605_add_automatic_purchased_storage_allocation_to_application_settings.rb b/db/migrate/20201006014605_add_automatic_purchased_storage_allocation_to_application_settings.rb
deleted file mode 100644
index f88bd177b98..00000000000
--- a/db/migrate/20201006014605_add_automatic_purchased_storage_allocation_to_application_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddAutomaticPurchasedStorageAllocationToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :automatic_purchased_storage_allocation, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20201007033527_add_daily_invites_to_plan_limits.rb b/db/migrate/20201007033527_add_daily_invites_to_plan_limits.rb
deleted file mode 100644
index 8f0079cd639..00000000000
--- a/db/migrate/20201007033527_add_daily_invites_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddDailyInvitesToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column(:plan_limits, :daily_invites, :integer, default: 0, null: false)
- end
-end
diff --git a/db/migrate/20201007033723_insert_daily_invites_plan_limits.rb b/db/migrate/20201007033723_insert_daily_invites_plan_limits.rb
deleted file mode 100644
index dcdcbbb0964..00000000000
--- a/db/migrate/20201007033723_insert_daily_invites_plan_limits.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class InsertDailyInvitesPlanLimits < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- return unless Gitlab.com?
-
- create_or_update_plan_limit('daily_invites', 'free', 20)
- create_or_update_plan_limit('daily_invites', 'bronze', 0)
- create_or_update_plan_limit('daily_invites', 'silver', 0)
- create_or_update_plan_limit('daily_invites', 'gold', 0)
- end
-
- def down
- return unless Gitlab.com?
-
- create_or_update_plan_limit('daily_invites', 'free', 0)
- create_or_update_plan_limit('daily_invites', 'bronze', 0)
- create_or_update_plan_limit('daily_invites', 'silver', 0)
- create_or_update_plan_limit('daily_invites', 'gold', 0)
- end
-end
diff --git a/db/migrate/20201007115209_add_lock_version_to_ci_build_trace_chunk.rb b/db/migrate/20201007115209_add_lock_version_to_ci_build_trace_chunk.rb
deleted file mode 100644
index fdef5e2f52a..00000000000
--- a/db/migrate/20201007115209_add_lock_version_to_ci_build_trace_chunk.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddLockVersionToCiBuildTraceChunk < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :ci_build_trace_chunks, :lock_version, :integer, default: 0, null: false
- end
-end
diff --git a/db/migrate/20201008011523_add_ci_jwt_signing_key_to_application_settings.rb b/db/migrate/20201008011523_add_ci_jwt_signing_key_to_application_settings.rb
deleted file mode 100644
index c51f7e8b706..00000000000
--- a/db/migrate/20201008011523_add_ci_jwt_signing_key_to_application_settings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddCiJwtSigningKeyToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in 20201001011937_add_text_limit_to_application_settings_encrypted_ci_jwt_signing_key_iv
- def change
- add_column :application_settings, :encrypted_ci_jwt_signing_key, :text
- add_column :application_settings, :encrypted_ci_jwt_signing_key_iv, :text
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20201008011937_add_text_limit_to_application_settings_encrypted_ci_jwt_signing_key_iv.rb b/db/migrate/20201008011937_add_text_limit_to_application_settings_encrypted_ci_jwt_signing_key_iv.rb
deleted file mode 100644
index 39f6eb2106a..00000000000
--- a/db/migrate/20201008011937_add_text_limit_to_application_settings_encrypted_ci_jwt_signing_key_iv.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToApplicationSettingsEncryptedCiJwtSigningKeyIv < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :application_settings, :encrypted_ci_jwt_signing_key_iv, 255
- end
-
- def down
- remove_text_limit :application_settings, :encrypted_ci_jwt_signing_key_iv
- end
-end
diff --git a/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb b/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb
deleted file mode 100644
index 5d7b6349fe6..00000000000
--- a/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class GenerateCiJwtSigningKey < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- class ApplicationSetting < ActiveRecord::Base
- self.table_name = 'application_settings'
-
- attr_encrypted :ci_jwt_signing_key, {
- mode: :per_attribute_iv,
- key: Gitlab::Utils.ensure_utf8_size(Rails.application.secrets.db_key_base, bytes: 32.bytes),
- algorithm: 'aes-256-gcm',
- encode: true
- }
- end
-
- def up
- ApplicationSetting.reset_column_information
-
- ApplicationSetting.find_each do |application_setting|
- application_setting.update(ci_jwt_signing_key: OpenSSL::PKey::RSA.new(2048).to_pem)
- end
- end
-
- def down
- ApplicationSetting.reset_column_information
-
- ApplicationSetting.find_each do |application_setting|
- application_setting.update_columns(encrypted_ci_jwt_signing_key: nil, encrypted_ci_jwt_signing_key_iv: nil)
- end
- end
-end
diff --git a/db/migrate/20201008075620_add_releases_events_to_web_hooks.rb b/db/migrate/20201008075620_add_releases_events_to_web_hooks.rb
deleted file mode 100644
index f6df213f162..00000000000
--- a/db/migrate/20201008075620_add_releases_events_to_web_hooks.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddReleasesEventsToWebHooks < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :web_hooks, :releases_events, :boolean, null: false, default: false
- end
-end
diff --git a/db/migrate/20201008125643_create_csv_issue_imports.rb b/db/migrate/20201008125643_create_csv_issue_imports.rb
deleted file mode 100644
index be3206af6d8..00000000000
--- a/db/migrate/20201008125643_create_csv_issue_imports.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCsvIssueImports < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- create_table :csv_issue_imports do |t|
- t.bigint :project_id, null: false, index: true
- t.bigint :user_id, null: false, index: true
-
- t.timestamps_with_timezone
- end
- end
-
- def down
- drop_table :csv_issue_imports
- end
-end
diff --git a/db/migrate/20201008144854_set_regex_defaults_on_container_expiration_policies.rb b/db/migrate/20201008144854_set_regex_defaults_on_container_expiration_policies.rb
deleted file mode 100644
index 45c411fc238..00000000000
--- a/db/migrate/20201008144854_set_regex_defaults_on_container_expiration_policies.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class SetRegexDefaultsOnContainerExpirationPolicies < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :container_expiration_policies, :name_regex, '.*'
- change_column_default :container_expiration_policies, :enabled, false
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :container_expiration_policies, :name_regex, nil
- change_column_default :container_expiration_policies, :enabled, true
- end
- end
-end
diff --git a/db/migrate/20201008224441_add_position_into_security_findings.rb b/db/migrate/20201008224441_add_position_into_security_findings.rb
deleted file mode 100644
index ee6d5370f83..00000000000
--- a/db/migrate/20201008224441_add_position_into_security_findings.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddPositionIntoSecurityFindings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :security_findings, :position, :integer
- end
- end
-
- def down
- with_lock_retries do
- remove_column :security_findings, :position
- end
- end
-end
diff --git a/db/migrate/20201009090954_add_index_with_project_id_to_container_expiration_policies.rb b/db/migrate/20201009090954_add_index_with_project_id_to_container_expiration_policies.rb
deleted file mode 100644
index ec44d5ddcef..00000000000
--- a/db/migrate/20201009090954_add_index_with_project_id_to_container_expiration_policies.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexWithProjectIdToContainerExpirationPolicies < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = 'idx_container_exp_policies_on_project_id_next_run_at_enabled'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :container_expiration_policies, [:project_id, :next_run_at, :enabled], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :container_expiration_policies, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201011005400_add_text_limit_to_application_settings_kroki_url.rb b/db/migrate/20201011005400_add_text_limit_to_application_settings_kroki_url.rb
deleted file mode 100644
index 96427cc3454..00000000000
--- a/db/migrate/20201011005400_add_text_limit_to_application_settings_kroki_url.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToApplicationSettingsKrokiUrl < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :application_settings, :kroki_url, 1024
- end
-
- def down
- # Down is required as `add_text_limit` is not reversible
- #
- remove_text_limit :application_settings, :kroki_url
- end
-end
diff --git a/db/migrate/20201012073022_remove_not_null_constraint_on_framework.rb b/db/migrate/20201012073022_remove_not_null_constraint_on_framework.rb
deleted file mode 100644
index b8cc8984575..00000000000
--- a/db/migrate/20201012073022_remove_not_null_constraint_on_framework.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveNotNullConstraintOnFramework < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- GDPR_FRAMEWORK_ID = 1
-
- disable_ddl_transaction!
-
- class TmpComplianceProjectFrameworkSetting < ActiveRecord::Base
- self.table_name = 'project_compliance_framework_settings'
- self.primary_key = :project_id
-
- include EachBatch
- end
-
- def up
- change_column_null :project_compliance_framework_settings, :framework, true
- end
-
- def down
- # Custom frameworks cannot be rolled back easily since we don't have enum for them.
- # To make the database consistent, we mark them as GDPR framework.
- # Note: framework customization will be implemented in the next 1-3 releases so data
- # corruption due to the rollback is unlikely.
- TmpComplianceProjectFrameworkSetting.each_batch(of: 100) do |query|
- query.where(framework: nil).update_all(framework: GDPR_FRAMEWORK_ID)
- end
-
- change_column_null :project_compliance_framework_settings, :framework, false
- end
-end
diff --git a/db/migrate/20201012122428_add_container_registry_expiration_policies_worker_capacity_constraint.rb b/db/migrate/20201012122428_add_container_registry_expiration_policies_worker_capacity_constraint.rb
deleted file mode 100644
index e4f7d1309a3..00000000000
--- a/db/migrate/20201012122428_add_container_registry_expiration_policies_worker_capacity_constraint.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddContainerRegistryExpirationPoliciesWorkerCapacityConstraint < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- CONSTRAINT_NAME = 'app_settings_registry_exp_policies_worker_capacity_positive'
-
- disable_ddl_transaction!
-
- def up
- add_check_constraint :application_settings, 'container_registry_expiration_policies_worker_capacity >= 0', CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint :application_settings, CONSTRAINT_NAME
- end
-end
diff --git a/db/migrate/20201012134230_create_ci_test_cases.rb b/db/migrate/20201012134230_create_ci_test_cases.rb
deleted file mode 100644
index fd1bcaf1093..00000000000
--- a/db/migrate/20201012134230_create_ci_test_cases.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCiTestCases < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:ci_test_cases)
- create_table :ci_test_cases do |t|
- t.bigint :project_id, null: false
- t.text :key_hash, null: false
-
- t.index [:project_id, :key_hash], unique: true
- # NOTE: FK for projects will be added on a separate migration as per guidelines
- end
- end
-
- add_text_limit :ci_test_cases, :key_hash, 64
- end
-
- def down
- drop_table :ci_test_cases
- end
-end
diff --git a/db/migrate/20201012135330_create_ci_test_case_failures.rb b/db/migrate/20201012135330_create_ci_test_case_failures.rb
deleted file mode 100644
index 7eaf7b5256d..00000000000
--- a/db/migrate/20201012135330_create_ci_test_case_failures.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class CreateCiTestCaseFailures < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- create_table :ci_test_case_failures do |t|
- t.datetime_with_timezone :failed_at
- t.bigint :test_case_id, null: false
- t.bigint :build_id, null: false
-
- t.index [:test_case_id, :failed_at, :build_id], name: 'index_test_case_failures_unique_columns', unique: true, order: { failed_at: :desc }
- t.index :build_id
- t.foreign_key :ci_test_cases, column: :test_case_id, on_delete: :cascade
- # NOTE: FK for ci_builds will be added on a separate migration as per guidelines
- end
- end
-
- def down
- drop_table :ci_test_case_failures
- end
-end
diff --git a/db/migrate/20201012140110_add_projects_fk_to_ci_test_cases.rb b/db/migrate/20201012140110_add_projects_fk_to_ci_test_cases.rb
deleted file mode 100644
index d30b332e41a..00000000000
--- a/db/migrate/20201012140110_add_projects_fk_to_ci_test_cases.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectsFkToCiTestCases < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :ci_test_cases, :projects, column: :project_id, on_delete: :cascade
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :ci_test_cases, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20201012140452_add_ci_builds_fk_to_ci_test_case_failures.rb b/db/migrate/20201012140452_add_ci_builds_fk_to_ci_test_case_failures.rb
deleted file mode 100644
index 0f2fdf071fa..00000000000
--- a/db/migrate/20201012140452_add_ci_builds_fk_to_ci_test_case_failures.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddCiBuildsFkToCiTestCaseFailures < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :ci_test_case_failures, :ci_builds, column: :build_id, on_delete: :cascade
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :ci_test_case_failures, column: :build_id
- end
- end
-end
diff --git a/db/migrate/20201012194936_create_saml_group_links.rb b/db/migrate/20201012194936_create_saml_group_links.rb
deleted file mode 100644
index d47c383afef..00000000000
--- a/db/migrate/20201012194936_create_saml_group_links.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class CreateSamlGroupLinks < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- create_table :saml_group_links, if_not_exists: true do |t|
- t.integer :access_level, null: false, limit: 2
- t.references :group, index: false, foreign_key: { to_table: :namespaces, on_delete: :cascade }, null: false
- t.timestamps_with_timezone
- t.text :saml_group_name, null: false
-
- t.index [:group_id, :saml_group_name], unique: true
- end
- end
-
- add_text_limit :saml_group_links, :saml_group_name, 255
- end
-
- def down
- with_lock_retries do
- drop_table :saml_group_links
- end
- end
-end
diff --git a/db/migrate/20201014163633_specify_primary_key_where_missing.rb b/db/migrate/20201014163633_specify_primary_key_where_missing.rb
deleted file mode 100644
index bca111dacf2..00000000000
--- a/db/migrate/20201014163633_specify_primary_key_where_missing.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-class SpecifyPrimaryKeyWhereMissing < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- TABLES = {
- project_authorizations: [:index_project_authorizations_on_user_id_project_id_access_level, %i(user_id project_id access_level)],
- analytics_language_trend_repository_languages: [:analytics_repository_languages_unique_index, %i(programming_language_id project_id snapshot_date)],
- approval_project_rules_protected_branches: [:index_approval_project_rules_protected_branches_unique, %i(approval_project_rule_id protected_branch_id)],
- ci_build_trace_sections: [:index_ci_build_trace_sections_on_build_id_and_section_name_id, %i(build_id section_name_id)],
- deployment_merge_requests: [:idx_deployment_merge_requests_unique_index, %i(deployment_id merge_request_id)],
- issue_assignees: [:index_issue_assignees_on_issue_id_and_user_id, %i(issue_id user_id)],
- issues_prometheus_alert_events: [:issue_id_prometheus_alert_event_id_index, %i(issue_id prometheus_alert_event_id)],
- issues_self_managed_prometheus_alert_events: [:issue_id_self_managed_prometheus_alert_event_id_index, %i(issue_id self_managed_prometheus_alert_event_id)],
- merge_request_diff_commits: [:index_merge_request_diff_commits_on_mr_diff_id_and_order, %i(merge_request_diff_id relative_order)],
- merge_request_diff_files: [:index_merge_request_diff_files_on_mr_diff_id_and_order, %i(merge_request_diff_id relative_order)],
- milestone_releases: [:index_miletone_releases_on_milestone_and_release, %i(milestone_id release_id)],
- project_pages_metadata: [:index_project_pages_metadata_on_project_id, %i(project_id)],
- push_event_payloads: [:index_push_event_payloads_on_event_id, %i(event_id)],
- repository_languages: [:index_repository_languages_on_project_and_languages_id, %i(project_id programming_language_id)],
- user_interacted_projects: [:index_user_interacted_projects_on_project_id_and_user_id, %i(project_id user_id)],
- users_security_dashboard_projects: [:users_security_dashboard_projects_unique_index, %i(project_id user_id)]
- }.freeze
-
- def up
- TABLES.each do |table, (unique_index, _)|
- with_lock_retries do
- execute "ALTER TABLE #{table} ADD CONSTRAINT #{table}_pkey PRIMARY KEY USING INDEX #{unique_index}" if index_exists_by_name?(table, unique_index)
- end
- end
- end
-
- def down
- TABLES.each do |table, (unique_index, columns)|
- add_concurrent_index table, columns, name: unique_index, unique: true
-
- with_lock_retries do
- execute "ALTER TABLE #{table} DROP CONSTRAINT #{table}_pkey"
- end
- end
- end
-end
diff --git a/db/migrate/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs.rb b/db/migrate/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs.rb
deleted file mode 100644
index c26636444af..00000000000
--- a/db/migrate/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class DropBackfillJiraTrackerDeploymentTypeJobs < ActiveRecord::Migration[6.0]
- DOWNTIME = false
- DROPPED_JOB_CLASS = 'BackfillJiraTrackerDeploymentType'
- QUEUE = 'background_migration'
-
- def up
- sidekiq_queues.each do |queue|
- queue.each do |job|
- next unless job.args.first == DROPPED_JOB_CLASS
-
- job.delete
- end
- end
- end
-
- def down
- # no-op
- end
-
- def sidekiq_queues
- [Sidekiq::ScheduledSet.new, Sidekiq::RetrySet.new, Sidekiq::Queue.new(QUEUE)]
- end
-end
diff --git a/db/migrate/20201015121805_add_project_foreign_key_to_csv_issue_imports.rb b/db/migrate/20201015121805_add_project_foreign_key_to_csv_issue_imports.rb
deleted file mode 100644
index 9476d2d55bd..00000000000
--- a/db/migrate/20201015121805_add_project_foreign_key_to_csv_issue_imports.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectForeignKeyToCsvIssueImports < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :csv_issue_imports, :projects, column: :project_id
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :csv_issue_imports, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20201015121825_add_user_foreign_key_to_csv_issue_imports.rb b/db/migrate/20201015121825_add_user_foreign_key_to_csv_issue_imports.rb
deleted file mode 100644
index ae91695bff4..00000000000
--- a/db/migrate/20201015121825_add_user_foreign_key_to_csv_issue_imports.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddUserForeignKeyToCsvIssueImports < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :csv_issue_imports, :users, column: :user_id
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :csv_issue_imports, column: :user_id
- end
- end
-end
diff --git a/db/migrate/20201015194852_add_index_on_state_for_dast_site_validations.rb b/db/migrate/20201015194852_add_index_on_state_for_dast_site_validations.rb
deleted file mode 100644
index 785d7c8829c..00000000000
--- a/db/migrate/20201015194852_add_index_on_state_for_dast_site_validations.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnStateForDastSiteValidations < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- OLD_INDEX_NAME = 'index_dast_site_validations_on_url_base'
- NEW_INDEX_NAME = 'index_dast_site_validations_on_url_base_and_state'
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :dast_site_validations, [:url_base, :state], name: NEW_INDEX_NAME
- remove_concurrent_index_by_name :dast_site_validations, OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :dast_site_validations, :url_base, name: OLD_INDEX_NAME
- remove_concurrent_index_by_name :dast_site_validations, NEW_INDEX_NAME
- end
-end
diff --git a/db/migrate/20201015231049_add_ci_build_id_to_terraform_state_versions.rb b/db/migrate/20201015231049_add_ci_build_id_to_terraform_state_versions.rb
deleted file mode 100644
index 539b2af5fc4..00000000000
--- a/db/migrate/20201015231049_add_ci_build_id_to_terraform_state_versions.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class AddCiBuildIdToTerraformStateVersions < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_terraform_state_versions_on_ci_build_id'
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:terraform_state_versions, :ci_build_id)
- add_column :terraform_state_versions, :ci_build_id, :bigint
- end
-
- add_concurrent_index :terraform_state_versions, :ci_build_id, name: INDEX_NAME
- add_concurrent_foreign_key :terraform_state_versions, :ci_builds, column: :ci_build_id, on_delete: :nullify
- end
-
- def down
- with_lock_retries do
- remove_foreign_key_if_exists :terraform_state_versions, :ci_builds, column: :ci_build_id
- end
-
- remove_concurrent_index_by_name :terraform_state_versions, INDEX_NAME
- remove_column :terraform_state_versions, :ci_build_id
- end
-end
diff --git a/db/migrate/20201016074302_add_index_project_id_and_id_to_container_repositories.rb b/db/migrate/20201016074302_add_index_project_id_and_id_to_container_repositories.rb
deleted file mode 100644
index b2e7c62ba0c..00000000000
--- a/db/migrate/20201016074302_add_index_project_id_and_id_to_container_repositories.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexProjectIdAndIdToContainerRepositories < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_container_repositories_on_project_id_and_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:container_repositories, [:project_id, :id], name: INDEX_NAME)
- end
-
- def down
- remove_concurrent_index(:container_repositories, [:project_id, :id], name: INDEX_NAME)
- end
-end
diff --git a/db/migrate/20201019091307_add_unique_index_on_scan_id_and_position_of_security_findings.rb b/db/migrate/20201019091307_add_unique_index_on_scan_id_and_position_of_security_findings.rb
deleted file mode 100644
index 3303e41d8a1..00000000000
--- a/db/migrate/20201019091307_add_unique_index_on_scan_id_and_position_of_security_findings.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddUniqueIndexOnScanIdAndPositionOfSecurityFindings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_security_findings_on_scan_id_and_position'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :security_findings, [:scan_id, :position], unique: true, name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :security_findings, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201019101549_add_es_custom_analyzers_settings.rb b/db/migrate/20201019101549_add_es_custom_analyzers_settings.rb
deleted file mode 100644
index 47fd9ebbb8e..00000000000
--- a/db/migrate/20201019101549_add_es_custom_analyzers_settings.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AddEsCustomAnalyzersSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :elasticsearch_analyzers_smartcn_enabled, :bool, null: false, default: false
- add_column :application_settings, :elasticsearch_analyzers_smartcn_search, :bool, null: false, default: false
- add_column :application_settings, :elasticsearch_analyzers_kuromoji_enabled, :bool, null: false, default: false
- add_column :application_settings, :elasticsearch_analyzers_kuromoji_search, :bool, null: false, default: false
- end
-end
diff --git a/db/migrate/20201019111952_add_sha256_and_filecount_to_pages_deployments.rb b/db/migrate/20201019111952_add_sha256_and_filecount_to_pages_deployments.rb
deleted file mode 100644
index 1921701626d..00000000000
--- a/db/migrate/20201019111952_add_sha256_and_filecount_to_pages_deployments.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddSha256AndFilecountToPagesDeployments < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- # pages_deployments were never enabled on any production/staging
- # environments, so we safely delete them for people who enabled
- # them locally
- execute "DELETE FROM pages_deployments"
-
- # rubocop:disable Rails/NotNullColumn
- add_column :pages_deployments, :file_count, :integer, null: false
- add_column :pages_deployments, :file_sha256, :binary, null: false
- # rubocop:enable Rails/NotNullColumn
- end
-
- def down
- remove_column :pages_deployments, :file_sha256
- remove_column :pages_deployments, :file_count
- end
-end
diff --git a/db/migrate/20201019113009_add_new_user_signups_cap_to_application_settings.rb b/db/migrate/20201019113009_add_new_user_signups_cap_to_application_settings.rb
deleted file mode 100644
index 8754b0d481e..00000000000
--- a/db/migrate/20201019113009_add_new_user_signups_cap_to_application_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddNewUserSignupsCapToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :new_user_signups_cap, :integer
- end
-end
diff --git a/db/migrate/20201019130244_remove_license_compliance_temp_index.rb b/db/migrate/20201019130244_remove_license_compliance_temp_index.rb
deleted file mode 100644
index d0383d999ed..00000000000
--- a/db/migrate/20201019130244_remove_license_compliance_temp_index.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveLicenseComplianceTempIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_ci_job_artifacts_on_license_compliance_file_types'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :ci_job_artifacts, name: INDEX_NAME
- end
-
- def down
- add_concurrent_index :ci_job_artifacts, [:job_id, :file_type], where: 'file_type = 10 OR file_type = 101', name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20201019152046_add_default_branch_to_daily_build_group_report_result.rb b/db/migrate/20201019152046_add_default_branch_to_daily_build_group_report_result.rb
deleted file mode 100644
index 8a0051b8106..00000000000
--- a/db/migrate/20201019152046_add_default_branch_to_daily_build_group_report_result.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultBranchToDailyBuildGroupReportResult < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- add_column :ci_daily_build_group_report_results, :default_branch, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20201019161924_add_partitioned_table_view.rb b/db/migrate/20201019161924_add_partitioned_table_view.rb
deleted file mode 100644
index 45bbfda40ff..00000000000
--- a/db/migrate/20201019161924_add_partitioned_table_view.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-class AddPartitionedTableView < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute(<<~SQL)
- CREATE OR REPLACE VIEW postgres_partitioned_tables AS
- SELECT
- pg_namespace.nspname::text || '.'::text || pg_class.relname::text AS identifier,
- pg_class.oid AS oid,
- pg_namespace.nspname AS schema,
- pg_class.relname AS name,
- CASE partitioned_tables.partstrat
- WHEN 'l' THEN 'list'
- WHEN 'r' THEN 'range'
- WHEN 'h' THEN 'hash'
- END as strategy,
- array_agg(pg_attribute.attname) as key_columns
- FROM (
- SELECT
- partrelid,
- partstrat,
- unnest(partattrs) as column_position
- FROM pg_partitioned_table
- ) partitioned_tables
- INNER JOIN pg_class
- ON partitioned_tables.partrelid = pg_class.oid
- INNER JOIN pg_namespace
- ON pg_class.relnamespace = pg_namespace.oid
- INNER JOIN pg_attribute
- ON pg_attribute.attrelid = pg_class.oid
- AND pg_attribute.attnum = partitioned_tables.column_position
- WHERE pg_namespace.nspname = current_schema()
- GROUP BY identifier, pg_class.oid, schema, name, strategy;
- SQL
- end
-
- def down
- execute(<<~SQL)
- DROP VIEW IF EXISTS postgres_partitioned_tables
- SQL
- end
-end
diff --git a/db/migrate/20201019172704_add_partitions_view.rb b/db/migrate/20201019172704_add_partitions_view.rb
deleted file mode 100644
index 991d137faf3..00000000000
--- a/db/migrate/20201019172704_add_partitions_view.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-class AddPartitionsView < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute(<<~SQL)
- CREATE OR REPLACE VIEW postgres_partitions AS
- SELECT
- pg_namespace.nspname::text || '.'::text || pg_class.relname::text AS identifier,
- pg_class.oid AS oid,
- pg_namespace.nspname AS schema,
- pg_class.relname AS name,
- parent_namespace.nspname::text || '.'::text || parent_class.relname::text AS parent_identifier,
- pg_get_expr(pg_class.relpartbound, pg_inherits.inhrelid) AS condition
- FROM pg_class
- INNER JOIN pg_namespace
- ON pg_namespace.oid = pg_class.relnamespace
- INNER JOIN pg_inherits
- ON pg_class.oid = pg_inherits.inhrelid
- INNER JOIN pg_class parent_class
- ON pg_inherits.inhparent = parent_class.oid
- INNER JOIN pg_namespace parent_namespace
- ON parent_class.relnamespace = parent_namespace.oid
- WHERE pg_class.relispartition
- AND pg_namespace.nspname IN (
- current_schema(),
- 'gitlab_partitions_dynamic',
- 'gitlab_partitions_static'
- )
- SQL
- end
-
- def down
- execute(<<~SQL)
- DROP VIEW IF EXISTS postgres_partitions
- SQL
- end
-end
diff --git a/db/migrate/20201021085007_create_analytics_devops_adoption_segments.rb b/db/migrate/20201021085007_create_analytics_devops_adoption_segments.rb
deleted file mode 100644
index 3e322675ba6..00000000000
--- a/db/migrate/20201021085007_create_analytics_devops_adoption_segments.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class CreateAnalyticsDevopsAdoptionSegments < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :analytics_devops_adoption_segments, if_not_exists: true do |t|
- t.text :name, null: false, index: { unique: true }
- t.datetime_with_timezone :last_recorded_at
-
- t.timestamps_with_timezone
- end
-
- add_text_limit :analytics_devops_adoption_segments, :name, 255
- end
-
- def down
- drop_table :analytics_devops_adoption_segments
- end
-end
diff --git a/db/migrate/20201021101956_add_index_route_on_name_trigram_to_route.rb b/db/migrate/20201021101956_add_index_route_on_name_trigram_to_route.rb
deleted file mode 100644
index cf65c7500c5..00000000000
--- a/db/migrate/20201021101956_add_index_route_on_name_trigram_to_route.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexRouteOnNameTrigramToRoute < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_route_on_name_trigram'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :routes, :name, name: INDEX_NAME, using: :gin, opclass: { name: :gin_trgm_ops }
- end
-
- def down
- remove_concurrent_index_by_name(:routes, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20201021102554_create_analytics_devops_adoption_segment_selections.rb b/db/migrate/20201021102554_create_analytics_devops_adoption_segment_selections.rb
deleted file mode 100644
index c5aac7a82a5..00000000000
--- a/db/migrate/20201021102554_create_analytics_devops_adoption_segment_selections.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class CreateAnalyticsDevopsAdoptionSegmentSelections < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :analytics_devops_adoption_segment_selections do |t|
- t.references :segment, index: { name: 'index_on_segment_selections_segment_id' }, null: false, foreign_key: { to_table: :analytics_devops_adoption_segments, on_delete: :cascade }
- t.bigint :group_id
- t.bigint :project_id
- t.index [:group_id, :segment_id], unique: true, name: 'index_on_segment_selections_group_id_segment_id'
- t.index [:project_id, :segment_id], unique: true, name: 'index_on_segment_selections_project_id_segment_id'
-
- t.timestamps_with_timezone
- end
- end
-end
diff --git a/db/migrate/20201021105347_add_foreign_key_project_id_to_segment_selection.rb b/db/migrate/20201021105347_add_foreign_key_project_id_to_segment_selection.rb
deleted file mode 100644
index 651770e059c..00000000000
--- a/db/migrate/20201021105347_add_foreign_key_project_id_to_segment_selection.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyProjectIdToSegmentSelection < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key(:analytics_devops_adoption_segment_selections, :projects, column: :project_id, on_delete: :cascade)
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :analytics_devops_adoption_segment_selections, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20201021105600_add_foreign_key_group_id_to_segment_selection.rb b/db/migrate/20201021105600_add_foreign_key_group_id_to_segment_selection.rb
deleted file mode 100644
index 3ee73ee3a64..00000000000
--- a/db/migrate/20201021105600_add_foreign_key_group_id_to_segment_selection.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyGroupIdToSegmentSelection < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key(:analytics_devops_adoption_segment_selections, :namespaces, column: :group_id, on_delete: :cascade)
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :analytics_devops_adoption_segment_selections, column: :group_id
- end
- end
-end
diff --git a/db/migrate/20201021105959_add_check_constraint_to_segment_selection.rb b/db/migrate/20201021105959_add_check_constraint_to_segment_selection.rb
deleted file mode 100644
index 68fec36aa8a..00000000000
--- a/db/migrate/20201021105959_add_check_constraint_to_segment_selection.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddCheckConstraintToSegmentSelection < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'segment_selection_project_id_or_group_id_required'
-
- def up
- add_check_constraint :analytics_devops_adoption_segment_selections, '(project_id != NULL AND group_id IS NULL) OR (group_id != NULL AND project_id IS NULL)', CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint :analytics_devops_adoption_segment_selections, CONSTRAINT_NAME
- end
-end
diff --git a/db/migrate/20201021142812_add_index_to_ci_daily_build_group_report_results.rb b/db/migrate/20201021142812_add_index_to_ci_daily_build_group_report_results.rb
deleted file mode 100644
index c811e3deeda..00000000000
--- a/db/migrate/20201021142812_add_index_to_ci_daily_build_group_report_results.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToCiDailyBuildGroupReportResults < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_ci_daily_build_group_report_results_on_project_and_date'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(
- :ci_daily_build_group_report_results,
- [:project_id, :date],
- order: { date: :desc },
- where: "default_branch = TRUE AND (data -> 'coverage') IS NOT NULL",
- name: INDEX_NAME
- )
- end
-
- def down
- remove_concurrent_index_by_name(:ci_daily_build_group_report_results, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20201021152210_add_secret_detection_token_revocation_application_settings.rb b/db/migrate/20201021152210_add_secret_detection_token_revocation_application_settings.rb
deleted file mode 100644
index 6334dcd8c1a..00000000000
--- a/db/migrate/20201021152210_add_secret_detection_token_revocation_application_settings.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddSecretDetectionTokenRevocationApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column :application_settings, :secret_detection_token_revocation_enabled, :boolean, default: false, null: false
- add_column :application_settings, :secret_detection_token_revocation_url, :text, null: true # rubocop:disable Migration/AddLimitToTextColumns
-
- add_column :application_settings, :encrypted_secret_detection_token_revocation_token, :text
- add_column :application_settings, :encrypted_secret_detection_token_revocation_token_iv, :text
- end
-
- def down
- remove_column :application_settings, :secret_detection_token_revocation_enabled
- remove_column :application_settings, :secret_detection_token_revocation_url
-
- remove_column :application_settings, :encrypted_secret_detection_token_revocation_token
- remove_column :application_settings, :encrypted_secret_detection_token_revocation_token_iv
- end
-end
diff --git a/db/migrate/20201021155606_add_analytics_access_level_to_project_features.rb b/db/migrate/20201021155606_add_analytics_access_level_to_project_features.rb
deleted file mode 100644
index faedbced06b..00000000000
--- a/db/migrate/20201021155606_add_analytics_access_level_to_project_features.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddAnalyticsAccessLevelToProjectFeatures < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :project_features, :analytics_access_level, :integer, default: 20, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :project_features, :analytics_access_level, :integer
- end
- end
-end
diff --git a/db/migrate/20201021190539_add_text_limit_to_secret_detection_token_revocation_application_settings.rb b/db/migrate/20201021190539_add_text_limit_to_secret_detection_token_revocation_application_settings.rb
deleted file mode 100644
index ea5e12322d0..00000000000
--- a/db/migrate/20201021190539_add_text_limit_to_secret_detection_token_revocation_application_settings.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToSecretDetectionTokenRevocationApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :application_settings, :secret_detection_token_revocation_url, 255
- end
-
- def down
- remove_text_limit :application_settings, :secret_detection_token_revocation_url
- end
-end
diff --git a/db/migrate/20201021220101_add_merge_trains_enabled.rb b/db/migrate/20201021220101_add_merge_trains_enabled.rb
deleted file mode 100644
index 88a71897435..00000000000
--- a/db/migrate/20201021220101_add_merge_trains_enabled.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddMergeTrainsEnabled < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :project_ci_cd_settings, :merge_trains_enabled, :boolean, default: false, allow_null: false
- end
-end
diff --git a/db/migrate/20201022080802_add_repository_read_only_to_snippets.rb b/db/migrate/20201022080802_add_repository_read_only_to_snippets.rb
deleted file mode 100644
index d0cb329fb02..00000000000
--- a/db/migrate/20201022080802_add_repository_read_only_to_snippets.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddRepositoryReadOnlyToSnippets < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :snippets, :repository_read_only, :boolean, default: false, null: false
- end
-end
diff --git a/db/migrate/20201022094845_add_historical_data_recorded_at.rb b/db/migrate/20201022094845_add_historical_data_recorded_at.rb
deleted file mode 100644
index c90889e2d38..00000000000
--- a/db/migrate/20201022094845_add_historical_data_recorded_at.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddHistoricalDataRecordedAt < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column(:historical_data, :recorded_at, :timestamptz)
- end
-
- def down
- remove_column(:historical_data, :recorded_at)
- end
-end
diff --git a/db/migrate/20201022094846_update_historical_data_recorded_at.rb b/db/migrate/20201022094846_update_historical_data_recorded_at.rb
deleted file mode 100644
index bd1889149bb..00000000000
--- a/db/migrate/20201022094846_update_historical_data_recorded_at.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateHistoricalDataRecordedAt < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- update_value = Arel.sql("COALESCE(created_at, date + '12:00'::time AT TIME ZONE '#{Time.zone&.tzinfo&.name || "Etc/UTC"}')")
-
- update_column_in_batches(:historical_data, :recorded_at, update_value) do |table, query|
- query.where(table[:recorded_at].eq(nil))
- end
-
- add_not_null_constraint :historical_data, :recorded_at
-
- change_column_null :historical_data, :date, true
- end
-
- def down
- change_column_null :historical_data, :date, false
-
- remove_not_null_constraint :historical_data, :recorded_at
-
- update_column_in_batches(:historical_data, :recorded_at, nil) do |table, query|
- query.where(table[:recorded_at].not_eq(nil))
- end
- end
-end
diff --git a/db/migrate/20201022103304_add_availability_to_user_statuses.rb b/db/migrate/20201022103304_add_availability_to_user_statuses.rb
deleted file mode 100644
index 9144c81fcfb..00000000000
--- a/db/migrate/20201022103304_add_availability_to_user_statuses.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddAvailabilityToUserStatuses < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :user_statuses, :availability, :integer, limit: 2, default: 0, null: false
- end
-end
diff --git a/db/migrate/20201022144501_create_snippet_repository_storage_move.rb b/db/migrate/20201022144501_create_snippet_repository_storage_move.rb
deleted file mode 100644
index 7db38191942..00000000000
--- a/db/migrate/20201022144501_create_snippet_repository_storage_move.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class CreateSnippetRepositoryStorageMove < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:snippet_repository_storage_moves)
- with_lock_retries do
- create_table :snippet_repository_storage_moves do |t|
- t.timestamps_with_timezone
- t.references :snippet, index: true, null: false, foreign_key: { on_delete: :cascade }
- t.integer :state, limit: 2, default: 1, null: false
- t.text :source_storage_name, null: false
- t.text :destination_storage_name, null: false
- end
- end
- end
-
- add_text_limit(:snippet_repository_storage_moves, :source_storage_name, 255, constraint_name: 'snippet_repository_storage_moves_source_storage_name')
- add_text_limit(:snippet_repository_storage_moves, :destination_storage_name, 255, constraint_name: 'snippet_repository_storage_moves_destination_storage_name')
- end
-
- def down
- with_lock_retries do
- drop_table :snippet_repository_storage_moves
- end
- end
-end
diff --git a/db/migrate/20201022191817_add_has_vulnerabilities_into_project_settings.rb b/db/migrate/20201022191817_add_has_vulnerabilities_into_project_settings.rb
deleted file mode 100644
index bb2d683c4e2..00000000000
--- a/db/migrate/20201022191817_add_has_vulnerabilities_into_project_settings.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddHasVulnerabilitiesIntoProjectSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :project_settings, :has_vulnerabilities, :boolean, default: false, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :project_settings, :has_vulnerabilities
- end
- end
-end
diff --git a/db/migrate/20201022192254_index_project_settings_on_project_id_partially.rb b/db/migrate/20201022192254_index_project_settings_on_project_id_partially.rb
deleted file mode 100644
index 57247bd0f22..00000000000
--- a/db/migrate/20201022192254_index_project_settings_on_project_id_partially.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class IndexProjectSettingsOnProjectIdPartially < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_project_settings_on_project_id_partially'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :project_settings, :project_id, name: INDEX_NAME, where: 'has_vulnerabilities IS TRUE'
- end
-
- def down
- remove_concurrent_index_by_name :project_settings, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201023114628_create_merge_request_cleanup_schedules.rb b/db/migrate/20201023114628_create_merge_request_cleanup_schedules.rb
deleted file mode 100644
index f63738682b1..00000000000
--- a/db/migrate/20201023114628_create_merge_request_cleanup_schedules.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class CreateMergeRequestCleanupSchedules < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :merge_request_cleanup_schedules, id: false do |t|
- t.references :merge_request, primary_key: true, index: { unique: true }, null: false, foreign_key: { on_delete: :cascade }
- t.datetime_with_timezone :scheduled_at, null: false
- t.datetime_with_timezone :completed_at, null: true
-
- t.timestamps_with_timezone
-
- t.index :scheduled_at, where: 'completed_at IS NULL', name: 'index_mr_cleanup_schedules_timestamps'
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :merge_request_cleanup_schedules
- end
- end
-end
diff --git a/db/migrate/20201026200736_seed_merge_trains_enabled.rb b/db/migrate/20201026200736_seed_merge_trains_enabled.rb
deleted file mode 100644
index c22c2a408bc..00000000000
--- a/db/migrate/20201026200736_seed_merge_trains_enabled.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class SeedMergeTrainsEnabled < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- update_column_in_batches(:project_ci_cd_settings, :merge_trains_enabled, true) do |table, query|
- query.where(table[:merge_pipelines_enabled].eq(true))
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20201027002551_migrate_services_to_http_integrations.rb b/db/migrate/20201027002551_migrate_services_to_http_integrations.rb
deleted file mode 100644
index 5fe05320862..00000000000
--- a/db/migrate/20201027002551_migrate_services_to_http_integrations.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateServicesToHttpIntegrations < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- ALERT_SERVICE_TYPE = 'AlertsService'
- SERVICE_NAMES_IDENTIFIER = {
- name: 'HTTP endpoint',
- identifier: 'legacy'
- }
-
- class HttpIntegration < ActiveRecord::Base
- self.table_name = 'alert_management_http_integrations'
- end
-
- # For each Alerts service,
- # Create the matching HttpIntegration
- def up
- HttpIntegration.reset_column_information
-
- sql = <<~SQL
- SELECT * FROM services
- JOIN alerts_service_data
- ON (services.id = alerts_service_data.service_id)
- WHERE type = '#{ALERT_SERVICE_TYPE}'
- AND active = TRUE
- SQL
-
- current_time = Time.current
-
- values = select_all(sql).map do |alerts_service|
- {
- project_id: alerts_service['project_id'],
- name: SERVICE_NAMES_IDENTIFIER[:name],
- endpoint_identifier: SERVICE_NAMES_IDENTIFIER[:identifier],
- encrypted_token: alerts_service['encrypted_token'],
- encrypted_token_iv: alerts_service['encrypted_token_iv'],
- active: alerts_service['active'],
- updated_at: current_time,
- created_at: current_time
- }
- end
-
- HttpIntegration.insert_all(values) if values.present?
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20201027101010_create_user_follow_users.rb b/db/migrate/20201027101010_create_user_follow_users.rb
deleted file mode 100644
index 7c1f831f3b2..00000000000
--- a/db/migrate/20201027101010_create_user_follow_users.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class CreateUserFollowUsers < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- execute <<~SQL
- CREATE TABLE user_follow_users (
- follower_id integer not null references users (id) on delete cascade,
- followee_id integer not null references users (id) on delete cascade,
- PRIMARY KEY (follower_id, followee_id)
- );
- CREATE INDEX ON user_follow_users (followee_id);
- SQL
- end
- end
-
- def down
- drop_table :user_follow_users
- end
-end
diff --git a/db/migrate/20201027135651_add_auto_rollback_setting.rb b/db/migrate/20201027135651_add_auto_rollback_setting.rb
deleted file mode 100644
index 8e916ac9d36..00000000000
--- a/db/migrate/20201027135651_add_auto_rollback_setting.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddAutoRollbackSetting < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :project_ci_cd_settings, :auto_rollback_enabled, :boolean, default: false, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :project_ci_cd_settings, :auto_rollback_enabled
- end
- end
-end
diff --git a/db/migrate/20201027210127_add_index_to_oauth_access_grants_resource_owner_id.rb b/db/migrate/20201027210127_add_index_to_oauth_access_grants_resource_owner_id.rb
deleted file mode 100644
index 035d2fb4386..00000000000
--- a/db/migrate/20201027210127_add_index_to_oauth_access_grants_resource_owner_id.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToOauthAccessGrantsResourceOwnerId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_oauth_access_grants_on_resource_owner_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :oauth_access_grants, %i[resource_owner_id application_id created_at], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :oauth_access_grants, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201027211138_increase_default_diff_max_patch_bytes.rb b/db/migrate/20201027211138_increase_default_diff_max_patch_bytes.rb
deleted file mode 100644
index 92d9025706f..00000000000
--- a/db/migrate/20201027211138_increase_default_diff_max_patch_bytes.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class IncreaseDefaultDiffMaxPatchBytes < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_column_default(:application_settings, :diff_max_patch_bytes, from: 102400, to: 204800)
- end
-end
diff --git a/db/migrate/20201028160831_add_temporary_index_to_vulnerabilities_table.rb b/db/migrate/20201028160831_add_temporary_index_to_vulnerabilities_table.rb
deleted file mode 100644
index 05bb75be75a..00000000000
--- a/db/migrate/20201028160831_add_temporary_index_to_vulnerabilities_table.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddTemporaryIndexToVulnerabilitiesTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'temporary_index_vulnerabilities_on_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :vulnerabilities, :id, where: "state = 2 AND (dismissed_at IS NULL OR dismissed_by_id IS NULL)", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201028184640_add_helm_major_version_to_clusters.rb b/db/migrate/20201028184640_add_helm_major_version_to_clusters.rb
deleted file mode 100644
index 2169fd41826..00000000000
--- a/db/migrate/20201028184640_add_helm_major_version_to_clusters.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddHelmMajorVersionToClusters < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column(:clusters, :helm_major_version, :integer, default: 2, null: false)
- end
-end
diff --git a/db/migrate/20201028204306_migrate_default_diff_max_patch_bytes_to_minimum_200kb.rb b/db/migrate/20201028204306_migrate_default_diff_max_patch_bytes_to_minimum_200kb.rb
deleted file mode 100644
index 11d47904e67..00000000000
--- a/db/migrate/20201028204306_migrate_default_diff_max_patch_bytes_to_minimum_200kb.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateDefaultDiffMaxPatchBytesToMinimum200kb < ActiveRecord::Migration[6.0]
- DOWNTIME = false
- MAX_SIZE = 200.kilobytes
-
- class ApplicationSetting < ActiveRecord::Base
- self.table_name = 'application_settings'
- end
-
- def up
- table = ApplicationSetting.arel_table
- ApplicationSetting.where(table[:diff_max_patch_bytes].lt(MAX_SIZE)).update_all(diff_max_patch_bytes: MAX_SIZE)
- end
-
- def down
- table = ApplicationSetting.arel_table
- ApplicationSetting.where(table[:diff_max_patch_bytes].eq(MAX_SIZE)).update_all(diff_max_patch_bytes: 100.kilobytes)
- end
-end
diff --git a/db/migrate/20201029143650_rename_application_settings_to_allow_deny_names.rb b/db/migrate/20201029143650_rename_application_settings_to_allow_deny_names.rb
deleted file mode 100644
index 2d96da91069..00000000000
--- a/db/migrate/20201029143650_rename_application_settings_to_allow_deny_names.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class RenameApplicationSettingsToAllowDenyNames < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- rename_column_concurrently :application_settings, :domain_blacklist_enabled, :domain_denylist_enabled
- rename_column_concurrently :application_settings, :domain_blacklist, :domain_denylist
- rename_column_concurrently :application_settings, :domain_whitelist, :domain_allowlist
- end
-
- def down
- undo_rename_column_concurrently :application_settings, :domain_blacklist_enabled, :domain_denylist_enabled
- undo_rename_column_concurrently :application_settings, :domain_blacklist, :domain_denylist
- undo_rename_column_concurrently :application_settings, :domain_whitelist, :domain_allowlist
- end
-end
diff --git a/db/migrate/20201029144444_create_vulnerability_finding_links.rb b/db/migrate/20201029144444_create_vulnerability_finding_links.rb
deleted file mode 100644
index 225a2de6e19..00000000000
--- a/db/migrate/20201029144444_create_vulnerability_finding_links.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class CreateVulnerabilityFindingLinks < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :vulnerability_finding_links, if_not_exists: true do |t|
- t.timestamps_with_timezone null: false
- t.references :vulnerability_occurrence, index: { name: 'finding_links_on_vulnerability_occurrence_id' }, null: false, foreign_key: { on_delete: :cascade }
- t.text :name
- t.text :url, null: false
- end
-
- add_text_limit :vulnerability_finding_links, :name, 255
- add_text_limit :vulnerability_finding_links, :url, 2048
- end
-
- def down
- drop_table :vulnerability_finding_links
- end
-end
diff --git a/db/migrate/20201029144524_add_index_to_releases.rb b/db/migrate/20201029144524_add_index_to_releases.rb
deleted file mode 100644
index fbffa1453af..00000000000
--- a/db/migrate/20201029144524_add_index_to_releases.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToReleases < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_releases_on_released_at'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :releases, :released_at, name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :releases, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201030092151_add_requirements_access_level_to_project_features.rb b/db/migrate/20201030092151_add_requirements_access_level_to_project_features.rb
deleted file mode 100644
index e4ba7b2adb9..00000000000
--- a/db/migrate/20201030092151_add_requirements_access_level_to_project_features.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddRequirementsAccessLevelToProjectFeatures < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- unless column_exists?(:project_features, :requirements_access_level)
- with_lock_retries { add_column :project_features, :requirements_access_level, :integer, default: 20, null: false }
- end
- end
-
- def down
- if column_exists?(:project_features, :requirements_access_level)
- with_lock_retries { remove_column :project_features, :requirements_access_level }
- end
- end
-end
diff --git a/db/migrate/20201030200115_add_iid_to_design_management_design.rb b/db/migrate/20201030200115_add_iid_to_design_management_design.rb
deleted file mode 100644
index c31cd86d5e2..00000000000
--- a/db/migrate/20201030200115_add_iid_to_design_management_design.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddIidToDesignManagementDesign < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :design_management_designs, :iid, :integer
- end
-end
diff --git a/db/migrate/20201030200539_add_index_on_design_management_designs_iid_project_id.rb b/db/migrate/20201030200539_add_index_on_design_management_designs_iid_project_id.rb
deleted file mode 100644
index 3ff50c299cb..00000000000
--- a/db/migrate/20201030200539_add_index_on_design_management_designs_iid_project_id.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnDesignManagementDesignsIidProjectId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'index_design_management_designs_on_iid_and_project_id'
-
- def up
- add_concurrent_index :design_management_designs, [:project_id, :iid],
- name: INDEX_NAME,
- unique: true
- end
-
- def down
- remove_concurrent_index_by_name :design_management_designs, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201030223933_add_ci_pipeline_deployments_to_plan_limits.rb b/db/migrate/20201030223933_add_ci_pipeline_deployments_to_plan_limits.rb
deleted file mode 100644
index 60f0ff9d6ed..00000000000
--- a/db/migrate/20201030223933_add_ci_pipeline_deployments_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddCiPipelineDeploymentsToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :plan_limits, :ci_pipeline_deployments, :integer, default: 500, null: false
- end
-end
diff --git a/db/migrate/20201102184743_add_index_to_incident_issues_on_project_and_created_at.rb b/db/migrate/20201102184743_add_index_to_incident_issues_on_project_and_created_at.rb
deleted file mode 100644
index 1fd900002c3..00000000000
--- a/db/migrate/20201102184743_add_index_to_incident_issues_on_project_and_created_at.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToIncidentIssuesOnProjectAndCreatedAt < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- INCIDENT_TYPE = 1
- OLD_INDEX_NAME = 'index_issues_project_id_issue_type_incident'
- NEW_INDEX_NAME = 'index_issues_on_project_id_and_created_at_issue_type_incident'
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :issues,
- [:project_id, :created_at],
- where: "issue_type = #{INCIDENT_TYPE}",
- name: NEW_INDEX_NAME
-
- remove_concurrent_index_by_name :issues, OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :issues,
- :project_id,
- where: "issue_type = #{INCIDENT_TYPE}",
- name: OLD_INDEX_NAME
-
- remove_concurrent_index_by_name :issues, NEW_INDEX_NAME
- end
-end
diff --git a/db/migrate/20201103045515_add_issuable_metric_images.rb b/db/migrate/20201103045515_add_issuable_metric_images.rb
deleted file mode 100644
index c598bb468a1..00000000000
--- a/db/migrate/20201103045515_add_issuable_metric_images.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class AddIssuableMetricImages < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:issuable_metric_images)
- with_lock_retries do
- create_table :issuable_metric_images do |t|
- t.references :issue, null: false, index: true, foreign_key: { on_delete: :cascade }
- t.timestamps_with_timezone
- t.integer :file_store, limit: 2
- t.text :file, null: false
- t.text :url
- end
- end
- end
-
- add_text_limit(:issuable_metric_images, :url, 255)
- add_text_limit(:issuable_metric_images, :file, 255)
- end
-
- def down
- with_lock_retries do
- drop_table :issuable_metric_images
- end
- end
-end
diff --git a/db/migrate/20201103095752_add_issues_closed_at_index.rb b/db/migrate/20201103095752_add_issues_closed_at_index.rb
deleted file mode 100644
index 7a8ee4e8d67..00000000000
--- a/db/migrate/20201103095752_add_issues_closed_at_index.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIssuesClosedAtIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:issues, [:project_id, :closed_at])
- end
-
- def down
- remove_concurrent_index_by_name(:issues, 'index_issues_on_project_id_and_closed_at')
- end
-end
diff --git a/db/migrate/20201103171537_add_index_active_billable_users_to_user.rb b/db/migrate/20201103171537_add_index_active_billable_users_to_user.rb
deleted file mode 100644
index 3ad7a3f4ca3..00000000000
--- a/db/migrate/20201103171537_add_index_active_billable_users_to_user.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexActiveBillableUsersToUser < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'active_billable_users'
- HUMAN_TYPE = 'NULL'
- HUMAN_SVC_BOT_TYPES = "#{HUMAN_TYPE}, 6, 4"
- BOT_TYPES = '2,6,1,3,7,8'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :users, :id, name: INDEX_NAME, where: "(state = 'active' AND (user_type is #{HUMAN_TYPE} or user_type in (#{HUMAN_SVC_BOT_TYPES}))) and ((users.user_type IS #{HUMAN_TYPE}) OR (users.user_type <> ALL ('{#{BOT_TYPES}}')))"
- end
-
- def down
- remove_concurrent_index_by_name(:users, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20201103184333_create_packages_package_file_build_infos.rb b/db/migrate/20201103184333_create_packages_package_file_build_infos.rb
deleted file mode 100644
index 9cb6869cae4..00000000000
--- a/db/migrate/20201103184333_create_packages_package_file_build_infos.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackagesPackageFileBuildInfos < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- unless table_exists?(:packages_package_file_build_infos)
- with_lock_retries do
- create_table :packages_package_file_build_infos do |t|
- t.references :package_file, index: true,
- null: false,
- foreign_key: { to_table: :packages_package_files, on_delete: :cascade },
- type: :bigint
- t.references :pipeline, index: true,
- null: true,
- foreign_key: { to_table: :ci_pipelines, on_delete: :nullify },
- type: :bigint
- end
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :packages_package_file_build_infos
- end
- end
-end
diff --git a/db/migrate/20201103202213_update_packages_build_infos_index.rb b/db/migrate/20201103202213_update_packages_build_infos_index.rb
deleted file mode 100644
index d737517045b..00000000000
--- a/db/migrate/20201103202213_update_packages_build_infos_index.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class UpdatePackagesBuildInfosIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- NEW_INDEX_NAME = 'idx_packages_build_infos_on_package_id'
- OLD_INDEX_NAME = 'index_packages_build_infos_on_package_id'
-
- def up
- add_concurrent_index :packages_build_infos, :package_id, name: NEW_INDEX_NAME
- remove_concurrent_index_by_name :packages_build_infos, OLD_INDEX_NAME
- end
-
- def down
- # No op. It is possible records would validate the UNIQUE constraint, so it
- # cannot be added back to the index.
- end
-end
diff --git a/db/migrate/20201104142036_add_index_to_merge_request_metrics_target_project_id.rb b/db/migrate/20201104142036_add_index_to_merge_request_metrics_target_project_id.rb
deleted file mode 100644
index 348a3387b6f..00000000000
--- a/db/migrate/20201104142036_add_index_to_merge_request_metrics_target_project_id.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToMergeRequestMetricsTargetProjectId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_mr_metrics_on_target_project_id_merged_at_time_to_merge'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :merge_request_metrics, [:target_project_id, :merged_at, :created_at], where: 'merged_at > created_at', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name(:merge_request_metrics, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20201104204739_create_bulk_import_trackers.rb b/db/migrate/20201104204739_create_bulk_import_trackers.rb
deleted file mode 100644
index 906bd06248d..00000000000
--- a/db/migrate/20201104204739_create_bulk_import_trackers.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-class CreateBulkImportTrackers < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- unless table_exists?(:bulk_import_trackers)
- create_table :bulk_import_trackers do |t|
- t.references :bulk_import_entity,
- null: false,
- index: false,
- foreign_key: { on_delete: :cascade }
-
- t.text :relation, null: false
- t.text :next_page
- t.boolean :has_next_page, default: false, null: false
-
- t.index %w(bulk_import_entity_id relation),
- unique: true,
- name: :bulk_import_trackers_uniq_relation_by_entity
- end
- end
- end
-
- add_check_constraint :bulk_import_trackers,
- '(has_next_page IS FALSE or next_page IS NOT NULL)',
- 'check_next_page_requirement'
- add_text_limit :bulk_import_trackers, :relation, 255
- add_text_limit :bulk_import_trackers, :next_page, 255
- end
-
- def down
- with_lock_retries do
- drop_table :bulk_import_trackers
- end
- end
-end
diff --git a/db/migrate/20201105021637_add_uploads_size_to_project_statistics.rb b/db/migrate/20201105021637_add_uploads_size_to_project_statistics.rb
deleted file mode 100644
index 1d2251f6c37..00000000000
--- a/db/migrate/20201105021637_add_uploads_size_to_project_statistics.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddUploadsSizeToProjectStatistics < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column :project_statistics, :uploads_size, :bigint, default: 0, null: false
- end
-
- def down
- remove_column :project_statistics, :uploads_size
- end
-end
diff --git a/db/migrate/20201105024127_add_uploads_size_to_namespace_root_storage_statistics.rb b/db/migrate/20201105024127_add_uploads_size_to_namespace_root_storage_statistics.rb
deleted file mode 100644
index c3cccc7d5f2..00000000000
--- a/db/migrate/20201105024127_add_uploads_size_to_namespace_root_storage_statistics.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddUploadsSizeToNamespaceRootStorageStatistics < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column :namespace_root_storage_statistics, :uploads_size, :bigint, default: 0, null: false
- end
-
- def down
- remove_column :namespace_root_storage_statistics, :uploads_size
- end
-end
diff --git a/db/migrate/20201105135051_change_default_value_of_ci_max_artifact_size_lsif_of_plan_limits_from20_to100.rb b/db/migrate/20201105135051_change_default_value_of_ci_max_artifact_size_lsif_of_plan_limits_from20_to100.rb
deleted file mode 100644
index d53f81ecabb..00000000000
--- a/db/migrate/20201105135051_change_default_value_of_ci_max_artifact_size_lsif_of_plan_limits_from20_to100.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeDefaultValueOfCiMaxArtifactSizeLsifOfPlanLimitsFrom20To100 < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- change_column_default :plan_limits, :ci_max_artifact_size_lsif, 100
- execute('UPDATE plan_limits SET ci_max_artifact_size_lsif = 100 WHERE ci_max_artifact_size_lsif = 20')
- end
- end
-
- def down
- with_lock_retries do
- change_column_default :plan_limits, :ci_max_artifact_size_lsif, 20
- execute('UPDATE plan_limits SET ci_max_artifact_size_lsif = 20 WHERE ci_max_artifact_size_lsif = 100')
- end
- end
-end
diff --git a/db/migrate/20201105143211_add_vulnerabilities_enabled_and_issuetype_to_jira_tracker_data.rb b/db/migrate/20201105143211_add_vulnerabilities_enabled_and_issuetype_to_jira_tracker_data.rb
deleted file mode 100644
index 27269de611c..00000000000
--- a/db/migrate/20201105143211_add_vulnerabilities_enabled_and_issuetype_to_jira_tracker_data.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddVulnerabilitiesEnabledAndIssuetypeToJiraTrackerData < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in 20201105143312_add_text_limit_to_jira_tracker_data_issuetype.rb
- def change
- add_column :jira_tracker_data, :vulnerabilities_issuetype, :text
- add_column :jira_tracker_data, :vulnerabilities_enabled, :boolean, default: false, null: false
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20201105143312_add_text_limit_to_jira_tracker_data_issuetype.rb b/db/migrate/20201105143312_add_text_limit_to_jira_tracker_data_issuetype.rb
deleted file mode 100644
index 4a81b0ce7af..00000000000
--- a/db/migrate/20201105143312_add_text_limit_to_jira_tracker_data_issuetype.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToJiraTrackerDataIssuetype < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :jira_tracker_data, :vulnerabilities_issuetype, 255
- end
-
- def down
- remove_text_limit :jira_tracker_data, :vulnerabilities_issuetype
- end
-end
diff --git a/db/migrate/20201106134139_add_pipelines_created_index.rb b/db/migrate/20201106134139_add_pipelines_created_index.rb
deleted file mode 100644
index aaf6643cf0b..00000000000
--- a/db/migrate/20201106134139_add_pipelines_created_index.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddPipelinesCreatedIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = :index_ci_pipelines_on_project_id_and_status_and_created_at
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_pipelines, [:project_id, :status, :created_at], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :ci_pipelines, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201106135608_remove_redundant_pipelines_index.rb b/db/migrate/20201106135608_remove_redundant_pipelines_index.rb
deleted file mode 100644
index 03e757c0ec1..00000000000
--- a/db/migrate/20201106135608_remove_redundant_pipelines_index.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveRedundantPipelinesIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :ci_pipelines, :index_ci_pipelines_on_project_id_and_created_at
- end
-
- def down
- add_concurrent_index :ci_pipelines, [:project_id, :created_at]
- end
-end
diff --git a/db/migrate/20201106193452_add_converted_at_to_experiment_users.rb b/db/migrate/20201106193452_add_converted_at_to_experiment_users.rb
deleted file mode 100644
index 5391093516b..00000000000
--- a/db/migrate/20201106193452_add_converted_at_to_experiment_users.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddConvertedAtToExperimentUsers < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :experiment_users, :converted_at, :datetime_with_timezone
- end
-end
diff --git a/db/migrate/20201107032257_add_default_true_require_admin_approval_after_user_signup_to_application_settings.rb b/db/migrate/20201107032257_add_default_true_require_admin_approval_after_user_signup_to_application_settings.rb
deleted file mode 100644
index 196f7bd8359..00000000000
--- a/db/migrate/20201107032257_add_default_true_require_admin_approval_after_user_signup_to_application_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultTrueRequireAdminApprovalAfterUserSignupToApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_column_default :application_settings, :require_admin_approval_after_user_signup, from: false, to: true
- end
-end
diff --git a/db/migrate/20201108134919_add_finding_fingerprint_table.rb b/db/migrate/20201108134919_add_finding_fingerprint_table.rb
deleted file mode 100644
index dd8ffe8e8aa..00000000000
--- a/db/migrate/20201108134919_add_finding_fingerprint_table.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-class AddFindingFingerprintTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- FINGERPRINT_IDX = :idx_vuln_fingerprints_on_occurrences_id_and_fingerprint
- UNIQ_IDX = :idx_vuln_fingerprints_uniqueness
-
- def up
- with_lock_retries do
- create_table :vulnerability_finding_fingerprints do |t|
- t.references :finding,
- index: true,
- null: false,
- foreign_key: { to_table: :vulnerability_occurrences, column: :finding_id, on_delete: :cascade }
-
- t.timestamps_with_timezone null: false
-
- t.integer :algorithm_type, null: false
- t.binary :fingerprint_sha256, null: false
-
- t.index %i[finding_id fingerprint_sha256],
- name: FINGERPRINT_IDX,
- unique: true # only one link should exist between occurrence and the fingerprint
-
- t.index %i[finding_id algorithm_type fingerprint_sha256],
- name: UNIQ_IDX,
- unique: true # these should be unique
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :vulnerability_finding_fingerprints
- end
- end
-end
diff --git a/db/migrate/20201109080645_create_vulnerability_remediations_table.rb b/db/migrate/20201109080645_create_vulnerability_remediations_table.rb
deleted file mode 100644
index b00ce797c7d..00000000000
--- a/db/migrate/20201109080645_create_vulnerability_remediations_table.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class CreateVulnerabilityRemediationsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :vulnerability_remediations, if_not_exists: true do |t|
- t.timestamps_with_timezone
-
- t.integer :file_store, limit: 2
- t.text :summary, null: false
- t.text :file, null: false
- end
-
- add_text_limit :vulnerability_remediations, :summary, 200
- add_text_limit :vulnerability_remediations, :file, 255
- end
-
- def down
- drop_table :vulnerability_remediations
- end
-end
diff --git a/db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb b/db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb
deleted file mode 100644
index e944cee24e4..00000000000
--- a/db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class CreateVulnerabilityFindingsRemediationsJoinTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/CreateTableWithForeignKeys
- def change
- create_table :vulnerability_findings_remediations do |t|
- t.references :vulnerability_occurrence, index: false, foreign_key: { on_delete: :cascade }
- t.references :vulnerability_remediation, index: { name: 'index_vulnerability_findings_remediations_on_remediation_id' }, foreign_key: { on_delete: :cascade }
-
- t.timestamps_with_timezone
-
- t.index [:vulnerability_occurrence_id, :vulnerability_remediation_id], unique: true, name: 'index_vulnerability_findings_remediations_on_unique_keys'
- end
- end
- # rubocop:enable Migration/CreateTableWithForeignKeys
-end
diff --git a/db/migrate/20201109144634_add_region_field_to_aws_role.rb b/db/migrate/20201109144634_add_region_field_to_aws_role.rb
deleted file mode 100644
index ced75f24552..00000000000
--- a/db/migrate/20201109144634_add_region_field_to_aws_role.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddRegionFieldToAwsRole < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:aws_roles, :region)
- add_column :aws_roles, :region, :text
- end
-
- add_text_limit :aws_roles, :region, 255
- end
-
- def down
- remove_column :aws_roles, :region
- end
-end
diff --git a/db/migrate/20201109180311_add_secret_detection_revocation_token_types_application_settings.rb b/db/migrate/20201109180311_add_secret_detection_revocation_token_types_application_settings.rb
deleted file mode 100644
index 0823655f92f..00000000000
--- a/db/migrate/20201109180311_add_secret_detection_revocation_token_types_application_settings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddSecretDetectionRevocationTokenTypesApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- add_column :application_settings, :secret_detection_revocation_token_types_url, :text, null: true # rubocop:disable Migration/AddLimitToTextColumns
- end
-
- def down
- remove_column :application_settings, :secret_detection_revocation_token_types_url
- end
-end
diff --git a/db/migrate/20201109184023_add_text_limit_to_secret_detection_revocation_token_types_application_settings.rb b/db/migrate/20201109184023_add_text_limit_to_secret_detection_revocation_token_types_application_settings.rb
deleted file mode 100644
index 9e0329aafcc..00000000000
--- a/db/migrate/20201109184023_add_text_limit_to_secret_detection_revocation_token_types_application_settings.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToSecretDetectionRevocationTokenTypesApplicationSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :application_settings, :secret_detection_revocation_token_types_url, 255
- end
-
- def down
- remove_text_limit :application_settings, :secret_detection_revocation_token_types_url
- end
-end
diff --git a/db/migrate/20201110035029_created_index_for_vulnerability_occurrences_on_project_fingerprint.rb b/db/migrate/20201110035029_created_index_for_vulnerability_occurrences_on_project_fingerprint.rb
deleted file mode 100644
index fed117d5f08..00000000000
--- a/db/migrate/20201110035029_created_index_for_vulnerability_occurrences_on_project_fingerprint.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class CreatedIndexForVulnerabilityOccurrencesOnProjectFingerprint < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_vulnerability_occurrences_on_project_fingerprint'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :vulnerability_occurrences, :project_fingerprint, name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :vulnerability_occurrences, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201110110454_extend_postgres_indexes_view.rb b/db/migrate/20201110110454_extend_postgres_indexes_view.rb
deleted file mode 100644
index 4e9172024d3..00000000000
--- a/db/migrate/20201110110454_extend_postgres_indexes_view.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-class ExtendPostgresIndexesView < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute(<<~SQL)
- DROP VIEW postgres_indexes;
-
- CREATE VIEW postgres_indexes AS
- SELECT (pg_namespace.nspname::text || '.'::text) || pg_class.relname::text AS identifier,
- pg_index.indexrelid,
- pg_namespace.nspname AS schema,
- pg_class.relname AS name,
- pg_index.indisunique AS "unique",
- pg_index.indisvalid AS valid_index,
- pg_class.relispartition AS partitioned,
- pg_index.indisexclusion AS exclusion,
- pg_index.indexprs IS NOT NULL as expression,
- pg_index.indpred IS NOT NULL as partial,
- pg_indexes.indexdef AS definition,
- pg_relation_size(pg_class.oid::regclass) AS ondisk_size_bytes
- FROM pg_index
- JOIN pg_class ON pg_class.oid = pg_index.indexrelid
- JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
- JOIN pg_indexes ON pg_class.relname = pg_indexes.indexname
- WHERE pg_namespace.nspname <> 'pg_catalog'::name
- AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name]));
- SQL
- end
-
- def down
- execute(<<~SQL)
- DROP VIEW postgres_indexes;
-
- CREATE VIEW postgres_indexes AS
- SELECT (pg_namespace.nspname::text || '.'::text) || pg_class.relname::text AS identifier,
- pg_index.indexrelid,
- pg_namespace.nspname AS schema,
- pg_class.relname AS name,
- pg_index.indisunique AS "unique",
- pg_index.indisvalid AS valid_index,
- pg_class.relispartition AS partitioned,
- pg_index.indisexclusion AS exclusion,
- pg_indexes.indexdef AS definition,
- pg_relation_size(pg_class.oid::regclass) AS ondisk_size_bytes
- FROM pg_index
- JOIN pg_class ON pg_class.oid = pg_index.indexrelid
- JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
- JOIN pg_indexes ON pg_class.relname = pg_indexes.indexname
- WHERE pg_namespace.nspname <> 'pg_catalog'::name
- AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name]));
- SQL
- end
-end
diff --git a/db/migrate/20201110133629_change_index_mr_metrics_target_project_id.rb b/db/migrate/20201110133629_change_index_mr_metrics_target_project_id.rb
deleted file mode 100644
index 5bd810207d8..00000000000
--- a/db/migrate/20201110133629_change_index_mr_metrics_target_project_id.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeIndexMrMetricsTargetProjectId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- disable_ddl_transaction!
-
- DOWNTIME = false
- INDEX_NAME = 'index_merge_request_metrics_on_target_project_id_merged_at'
- NULLS_LAST_INDEX_NAME = 'index_mr_metrics_on_target_project_id_merged_at_nulls_last'
-
- def up
- add_concurrent_index :merge_request_metrics, [:target_project_id, :merged_at, :id], order: { merged_at: 'DESC NULLS LAST', id: 'DESC' }, name: NULLS_LAST_INDEX_NAME
- remove_concurrent_index_by_name(:merge_request_metrics, INDEX_NAME)
- end
-
- def down
- add_concurrent_index :merge_request_metrics, [:target_project_id, :merged_at], name: INDEX_NAME
- remove_concurrent_index_by_name(:merge_request_metrics, NULLS_LAST_INDEX_NAME)
- end
-end
diff --git a/db/migrate/20201110221400_create_experiment_subjects.rb b/db/migrate/20201110221400_create_experiment_subjects.rb
deleted file mode 100644
index 0c04d5b219f..00000000000
--- a/db/migrate/20201110221400_create_experiment_subjects.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class CreateExperimentSubjects < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- create_table :experiment_subjects do |t|
- t.references :experiment, index: true, foreign_key: { on_delete: :cascade }, null: false
- t.bigint :user_id, index: true
- t.bigint :group_id, index: true
- t.bigint :project_id, index: true
- t.integer :variant, limit: 2, null: false, default: 0
- t.timestamps_with_timezone null: false
- end
-
- # Require exactly one of user_id, group_id, or project_id to be NOT NULL
- execute <<-SQL
- ALTER TABLE experiment_subjects ADD CONSTRAINT chk_has_one_subject CHECK (num_nonnulls(user_id, group_id, project_id) = 1);
- SQL
- end
-
- def down
- drop_table :experiment_subjects
- end
-end
diff --git a/db/migrate/20201111051655_add_foreign_key_to_experiment_subjects_on_user.rb b/db/migrate/20201111051655_add_foreign_key_to_experiment_subjects_on_user.rb
deleted file mode 100644
index 231d083dfda..00000000000
--- a/db/migrate/20201111051655_add_foreign_key_to_experiment_subjects_on_user.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToExperimentSubjectsOnUser < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
-
- def up
- add_concurrent_foreign_key :experiment_subjects, :users, column: :user_id, on_delete: :cascade
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :experiment_subjects, column: :user_id
- end
- end
-end
diff --git a/db/migrate/20201111051847_add_foreign_key_to_experiment_subjects_on_group.rb b/db/migrate/20201111051847_add_foreign_key_to_experiment_subjects_on_group.rb
deleted file mode 100644
index ad0d7ae027e..00000000000
--- a/db/migrate/20201111051847_add_foreign_key_to_experiment_subjects_on_group.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToExperimentSubjectsOnGroup < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
-
- def up
- add_concurrent_foreign_key :experiment_subjects, :namespaces, column: :group_id, on_delete: :cascade
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :experiment_subjects, column: :group_id
- end
- end
-end
diff --git a/db/migrate/20201111051904_add_foreign_key_to_experiment_subjects_on_project.rb b/db/migrate/20201111051904_add_foreign_key_to_experiment_subjects_on_project.rb
deleted file mode 100644
index a8a05292cca..00000000000
--- a/db/migrate/20201111051904_add_foreign_key_to_experiment_subjects_on_project.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddForeignKeyToExperimentSubjectsOnProject < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
-
- def up
- add_concurrent_foreign_key :experiment_subjects, :projects, column: :project_id, on_delete: :cascade
- end
-
- def down
- with_lock_retries do
- remove_foreign_key :experiment_subjects, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20201111100136_create_analytics_devops_adoption_snapshots.rb b/db/migrate/20201111100136_create_analytics_devops_adoption_snapshots.rb
deleted file mode 100644
index ee029d17c94..00000000000
--- a/db/migrate/20201111100136_create_analytics_devops_adoption_snapshots.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class CreateAnalyticsDevopsAdoptionSnapshots < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- create_table :analytics_devops_adoption_snapshots do |t|
- t.references :segment, index: false, null: false, foreign_key: { to_table: :analytics_devops_adoption_segments, on_delete: :cascade }
- t.datetime_with_timezone :recorded_at, null: false
- t.boolean :issue_opened, null: false
- t.boolean :merge_request_opened, null: false
- t.boolean :merge_request_approved, null: false
- t.boolean :runner_configured, null: false
- t.boolean :pipeline_succeeded, null: false
- t.boolean :deploy_succeeded, null: false
- t.boolean :security_scan_succeeded, null: false
-
- t.index [:segment_id, :recorded_at], name: 'index_on_snapshots_segment_id_recorded_at'
- end
- end
-end
diff --git a/db/migrate/20201111110318_add_cloud_license_auth_token_to_settings.rb b/db/migrate/20201111110318_add_cloud_license_auth_token_to_settings.rb
deleted file mode 100644
index e2069835597..00000000000
--- a/db/migrate/20201111110318_add_cloud_license_auth_token_to_settings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddCloudLicenseAuthTokenToSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in 20201111110918_add_cloud_license_auth_token_application_settings_text_limit
- def change
- add_column :application_settings, :encrypted_cloud_license_auth_token, :text
- add_column :application_settings, :encrypted_cloud_license_auth_token_iv, :text
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20201111110918_add_cloud_license_auth_token_application_settings_text_limit.rb b/db/migrate/20201111110918_add_cloud_license_auth_token_application_settings_text_limit.rb
deleted file mode 100644
index fd1ee5e07bf..00000000000
--- a/db/migrate/20201111110918_add_cloud_license_auth_token_application_settings_text_limit.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddCloudLicenseAuthTokenApplicationSettingsTextLimit < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :application_settings, :encrypted_cloud_license_auth_token_iv, 255
- end
-
- def down
- remove_text_limit :application_settings, :encrypted_cloud_license_auth_token_iv
- end
-end
diff --git a/db/migrate/20201111115414_create_incident_management_oncall_schedules.rb b/db/migrate/20201111115414_create_incident_management_oncall_schedules.rb
deleted file mode 100644
index dbb7d1c0808..00000000000
--- a/db/migrate/20201111115414_create_incident_management_oncall_schedules.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class CreateIncidentManagementOncallSchedules < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- unless table_exists?(:incident_management_oncall_schedules)
- create_table :incident_management_oncall_schedules do |t|
- t.timestamps_with_timezone
- t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade }
- t.integer :iid, null: false
- t.text :name, null: false
- t.text :description
- t.text :timezone
-
- t.index %w(project_id iid), name: 'index_im_oncall_schedules_on_project_id_and_iid', unique: true, using: :btree
- end
- end
- end
-
- add_text_limit :incident_management_oncall_schedules, :name, 200
- add_text_limit :incident_management_oncall_schedules, :description, 1000
- add_text_limit :incident_management_oncall_schedules, :timezone, 100
- end
-
- def down
- with_lock_retries do
- drop_table :incident_management_oncall_schedules
- end
- end
-end
diff --git a/db/migrate/20201111145317_add_relation_to_indexes_view.rb b/db/migrate/20201111145317_add_relation_to_indexes_view.rb
deleted file mode 100644
index 318b77c1dc6..00000000000
--- a/db/migrate/20201111145317_add_relation_to_indexes_view.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-class AddRelationToIndexesView < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute(<<~SQL)
- DROP VIEW postgres_indexes;
-
- CREATE VIEW postgres_indexes AS
- SELECT (pg_namespace.nspname::text || '.'::text) || pg_class.relname::text AS identifier,
- pg_index.indexrelid,
- pg_namespace.nspname AS schema,
- pg_class.relname AS name,
- pg_indexes.tablename,
- pg_index.indisunique AS "unique",
- pg_index.indisvalid AS valid_index,
- pg_class.relispartition AS partitioned,
- pg_index.indisexclusion AS exclusion,
- pg_index.indexprs IS NOT NULL as expression,
- pg_index.indpred IS NOT NULL as partial,
- pg_indexes.indexdef AS definition,
- pg_relation_size(pg_class.oid::regclass) AS ondisk_size_bytes
- FROM pg_index
- JOIN pg_class ON pg_class.oid = pg_index.indexrelid
- JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
- JOIN pg_indexes ON pg_class.relname = pg_indexes.indexname
- WHERE pg_namespace.nspname <> 'pg_catalog'::name
- AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name]));
- SQL
- end
-
- def down
- execute(<<~SQL)
- DROP VIEW postgres_indexes;
-
- CREATE VIEW postgres_indexes AS
- SELECT (pg_namespace.nspname::text || '.'::text) || pg_class.relname::text AS identifier,
- pg_index.indexrelid,
- pg_namespace.nspname AS schema,
- pg_class.relname AS name,
- pg_index.indisunique AS "unique",
- pg_index.indisvalid AS valid_index,
- pg_class.relispartition AS partitioned,
- pg_index.indisexclusion AS exclusion,
- pg_index.indexprs IS NOT NULL as expression,
- pg_index.indpred IS NOT NULL as partial,
- pg_indexes.indexdef AS definition,
- pg_relation_size(pg_class.oid::regclass) AS ondisk_size_bytes
- FROM pg_index
- JOIN pg_class ON pg_class.oid = pg_index.indexrelid
- JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
- JOIN pg_indexes ON pg_class.relname = pg_indexes.indexname
- WHERE pg_namespace.nspname <> 'pg_catalog'::name
- AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name]));
- SQL
- end
-end
diff --git a/db/migrate/20201111152859_add_missing_expression_indexes.rb b/db/migrate/20201111152859_add_missing_expression_indexes.rb
deleted file mode 100644
index e2742f7f3bc..00000000000
--- a/db/migrate/20201111152859_add_missing_expression_indexes.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-class AddMissingExpressionIndexes < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEXES = [
- [:namespaces, :index_on_namespaces_lower_name, 'LOWER(name)'],
- [:namespaces, :index_on_namespaces_lower_path, 'LOWER(path)'],
- [:projects, :index_on_projects_lower_path, 'LOWER(path)'],
- [:routes, :index_on_routes_lower_path, 'LOWER(path)'],
- [:users, :index_on_users_lower_username, 'LOWER(username)'],
- [:users, :index_on_users_lower_email, 'LOWER(email)']
- ]
-
- def up
- # Those indexes had been introduced before, but they haven't been
- # captured in structure.sql. For installations that already have it,
- # this is a no-op - others will get it retroactively with
- # this migration.
-
- tables = Set.new
-
- INDEXES.each do |(table, name, expression)|
- unless index_name_exists?(table, name)
- add_concurrent_index table, expression, name: name
- tables.add(table)
- end
- end
-
- # Rebuild statistics on affected tables only
- tables.each do |table|
- execute("ANALYZE #{table}")
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20201112132808_create_bulk_import_failures.rb b/db/migrate/20201112132808_create_bulk_import_failures.rb
deleted file mode 100644
index cdc5a4d6ff0..00000000000
--- a/db/migrate/20201112132808_create_bulk_import_failures.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-class CreateBulkImportFailures < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- unless table_exists?(:bulk_import_failures)
- create_table :bulk_import_failures do |t|
- t.references :bulk_import_entity,
- null: false,
- index: true,
- foreign_key: { on_delete: :cascade }
-
- t.datetime_with_timezone :created_at, null: false
- t.text :pipeline_class, null: false
- t.text :exception_class, null: false
- t.text :exception_message, null: false
- t.text :correlation_id_value, index: true
- end
- end
- end
-
- add_text_limit :bulk_import_failures, :pipeline_class, 255
- add_text_limit :bulk_import_failures, :exception_class, 255
- add_text_limit :bulk_import_failures, :exception_message, 255
- add_text_limit :bulk_import_failures, :correlation_id_value, 255
- end
-
- def down
- with_lock_retries do
- drop_table :bulk_import_failures
- end
- end
-end
diff --git a/db/migrate/20201112173532_add_verification_state_to_package_files.rb b/db/migrate/20201112173532_add_verification_state_to_package_files.rb
deleted file mode 100644
index 61f526bd77e..00000000000
--- a/db/migrate/20201112173532_add_verification_state_to_package_files.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class AddVerificationStateToPackageFiles < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :packages_package_files, :verification_state, :integer, default: 0, limit: 2, null: false
- add_column :packages_package_files, :verification_started_at, :datetime_with_timezone
- end
-end
diff --git a/db/migrate/20201112173911_add_index_on_verification_state_on_package_files.rb b/db/migrate/20201112173911_add_index_on_verification_state_on_package_files.rb
deleted file mode 100644
index 17e6b7d01f6..00000000000
--- a/db/migrate/20201112173911_add_index_on_verification_state_on_package_files.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnVerificationStateOnPackageFiles < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_packages_package_files_on_verification_state'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :packages_package_files, :verification_state, name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :packages_package_files, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201112195322_reseed_merge_trains_enabled.rb b/db/migrate/20201112195322_reseed_merge_trains_enabled.rb
deleted file mode 100644
index 777c59d16b1..00000000000
--- a/db/migrate/20201112195322_reseed_merge_trains_enabled.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class ReseedMergeTrainsEnabled < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- update_column_in_batches(:project_ci_cd_settings, :merge_trains_enabled, true) do |table, query|
- query.where(table[:merge_pipelines_enabled].eq(true))
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20201112215028_add_partitioned_audit_event_indexes.rb b/db/migrate/20201112215028_add_partitioned_audit_event_indexes.rb
deleted file mode 100644
index d8b2833474b..00000000000
--- a/db/migrate/20201112215028_add_partitioned_audit_event_indexes.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class AddPartitionedAuditEventIndexes < ActiveRecord::Migration[6.0]
- include Gitlab::Database::PartitioningMigrationHelpers
-
- DOWNTIME = false
-
- CREATED_AT_AUTHOR_ID_INDEX_NAME = 'analytics_index_audit_events_part_on_created_at_and_author_id'
- ENTITY_ID_DESC_INDEX_NAME = 'idx_audit_events_part_on_entity_id_desc_author_id_created_at'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_partitioned_index :audit_events_part_5fc467ac26,
- [:created_at, :author_id],
- name: CREATED_AT_AUTHOR_ID_INDEX_NAME
-
- add_concurrent_partitioned_index :audit_events_part_5fc467ac26,
- [:entity_id, :entity_type, :id, :author_id, :created_at],
- order: { id: :desc },
- name: ENTITY_ID_DESC_INDEX_NAME
- end
-
- def down
- remove_concurrent_partitioned_index_by_name :audit_events_part_5fc467ac26, ENTITY_ID_DESC_INDEX_NAME
-
- remove_concurrent_partitioned_index_by_name :audit_events_part_5fc467ac26, CREATED_AT_AUTHOR_ID_INDEX_NAME
- end
-end
diff --git a/db/migrate/20201112215132_swap_partitioned_audit_events.rb b/db/migrate/20201112215132_swap_partitioned_audit_events.rb
deleted file mode 100644
index 8360dbd4aa5..00000000000
--- a/db/migrate/20201112215132_swap_partitioned_audit_events.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class SwapPartitionedAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::PartitioningMigrationHelpers
-
- DOWNTIME = false
-
- def up
- replace_with_partitioned_table :audit_events
- end
-
- def down
- rollback_replace_with_partitioned_table :audit_events
- end
-end
diff --git a/db/migrate/20201116090328_add_regulated_to_compliance_frameworks.rb b/db/migrate/20201116090328_add_regulated_to_compliance_frameworks.rb
deleted file mode 100644
index f2e0c23ccfc..00000000000
--- a/db/migrate/20201116090328_add_regulated_to_compliance_frameworks.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddRegulatedToComplianceFrameworks < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column(:compliance_management_frameworks, :regulated, :boolean, default: true, null: false)
- end
-end
diff --git a/db/migrate/20201116211829_create_user_permission_export_uploads.rb b/db/migrate/20201116211829_create_user_permission_export_uploads.rb
deleted file mode 100644
index d6207fe0c2c..00000000000
--- a/db/migrate/20201116211829_create_user_permission_export_uploads.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class CreateUserPermissionExportUploads < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- unless table_exists?(:user_permission_export_uploads)
- create_table :user_permission_export_uploads do |t|
- t.timestamps_with_timezone null: false
- t.references :user, foreign_key: { on_delete: :cascade }, index: false, null: false
- t.integer :file_store
- t.integer :status, limit: 2, null: false, default: 0
- t.text :file
-
- t.index [:user_id, :status]
- end
- end
- end
-
- add_text_limit :user_permission_export_uploads, :file, 255
- end
-
- def down
- with_lock_retries do
- drop_table :user_permission_export_uploads
- end
- end
-end
diff --git a/db/migrate/20201117054609_add_cloud_license_enabled_to_settings.rb b/db/migrate/20201117054609_add_cloud_license_enabled_to_settings.rb
deleted file mode 100644
index 4488aa376a1..00000000000
--- a/db/migrate/20201117054609_add_cloud_license_enabled_to_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddCloudLicenseEnabledToSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :cloud_license_enabled, :boolean, null: false, default: false
- end
-end
diff --git a/db/migrate/20201117075742_change_webauthn_xid_length.rb b/db/migrate/20201117075742_change_webauthn_xid_length.rb
deleted file mode 100644
index 2d836662e01..00000000000
--- a/db/migrate/20201117075742_change_webauthn_xid_length.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeWebauthnXidLength < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :webauthn_registrations, :credential_xid, 340, constraint_name: check_constraint_name(:webauthn_registrations, :credential_xid, 'max_length_v2')
- remove_text_limit :webauthn_registrations, :credential_xid, constraint_name: check_constraint_name(:webauthn_registrations, :credential_xid, 'max_length')
- end
-
- def down
- # no-op: Danger of failling if there are records with length(credential_xid) > 255
- end
-end
diff --git a/db/migrate/20201117153333_add_index_on_package_size_and_project_id_to_project_statistics.rb b/db/migrate/20201117153333_add_index_on_package_size_and_project_id_to_project_statistics.rb
deleted file mode 100644
index efb5cf14d3c..00000000000
--- a/db/migrate/20201117153333_add_index_on_package_size_and_project_id_to_project_statistics.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnPackageSizeAndProjectIdToProjectStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_project_statistics_on_packages_size_and_project_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :project_statistics, [:packages_size, :project_id],
- name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :project_statistics, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201117184334_add_index_to_project_repositories_shard_id_project_id.rb b/db/migrate/20201117184334_add_index_to_project_repositories_shard_id_project_id.rb
deleted file mode 100644
index 25d95231ac4..00000000000
--- a/db/migrate/20201117184334_add_index_to_project_repositories_shard_id_project_id.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToProjectRepositoriesShardIdProjectId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :project_repositories, [:shard_id, :project_id]
- end
-
- def down
- remove_concurrent_index :project_repositories, [:shard_id, :project_id], name: 'index_project_repositories_on_shard_id_and_project_id'
- end
-end
diff --git a/db/migrate/20201117203224_add_iteration_id_to_boards_table.rb b/db/migrate/20201117203224_add_iteration_id_to_boards_table.rb
deleted file mode 100644
index 18abe096604..00000000000
--- a/db/migrate/20201117203224_add_iteration_id_to_boards_table.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIterationIdToBoardsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :boards, :iteration_id, :bigint
- end
- end
-
- def down
- with_lock_retries do
- remove_column :boards, :iteration_id
- end
- end
-end
diff --git a/db/migrate/20201117213024_add_iteration_id_index_to_boards_table.rb b/db/migrate/20201117213024_add_iteration_id_index_to_boards_table.rb
deleted file mode 100644
index e038b4eacd9..00000000000
--- a/db/migrate/20201117213024_add_iteration_id_index_to_boards_table.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIterationIdIndexToBoardsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_boards_on_iteration_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :boards, :iteration_id, name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :boards, :iteration_id, name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20201118093135_create_namespace_onboarding_actions.rb b/db/migrate/20201118093135_create_namespace_onboarding_actions.rb
deleted file mode 100644
index 6b38a0dddca..00000000000
--- a/db/migrate/20201118093135_create_namespace_onboarding_actions.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class CreateNamespaceOnboardingActions < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :namespace_onboarding_actions do |t|
- t.references :namespace, index: true, null: false, foreign_key: { on_delete: :cascade }
- t.datetime_with_timezone :created_at, null: false
- t.integer :action, limit: 2, null: false
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :namespace_onboarding_actions
- end
- end
-end
diff --git a/db/migrate/20201119031515_add_iteration_id_to_lists.rb b/db/migrate/20201119031515_add_iteration_id_to_lists.rb
deleted file mode 100644
index 62e13f53e92..00000000000
--- a/db/migrate/20201119031515_add_iteration_id_to_lists.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddIterationIdToLists < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :lists, :iteration_id, :bigint
- end
-end
diff --git a/db/migrate/20201119053603_add_iteration_lists_foreign_key.rb b/db/migrate/20201119053603_add_iteration_lists_foreign_key.rb
deleted file mode 100644
index 8d9ec1f2e59..00000000000
--- a/db/migrate/20201119053603_add_iteration_lists_foreign_key.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIterationListsForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = 'index_lists_on_iteration_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :lists, :iteration_id, name: INDEX_NAME
- add_concurrent_foreign_key :lists, :sprints, column: :iteration_id, on_delete: :cascade
- end
-
- def down
- remove_foreign_key_if_exists :lists, :sprints, column: :iteration_id
- remove_concurrent_index_by_name :lists, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201119125730_add_web_hooks_service_foreign_key.rb b/db/migrate/20201119125730_add_web_hooks_service_foreign_key.rb
deleted file mode 100644
index d350a7de282..00000000000
--- a/db/migrate/20201119125730_add_web_hooks_service_foreign_key.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class AddWebHooksServiceForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_web_hooks_on_service_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :web_hooks, :service_id, name: INDEX_NAME
- add_concurrent_foreign_key :web_hooks, :services, column: :service_id, on_delete: :cascade, validate: false
- end
-
- def down
- with_lock_retries do
- remove_foreign_key_if_exists :web_hooks, column: :service_id
- end
-
- remove_concurrent_index_by_name :web_hooks, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201119133534_add_personal_access_token_prefix_to_application_setting.rb b/db/migrate/20201119133534_add_personal_access_token_prefix_to_application_setting.rb
deleted file mode 100644
index c6bb6b7d514..00000000000
--- a/db/migrate/20201119133534_add_personal_access_token_prefix_to_application_setting.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AddPersonalAccessTokenPrefixToApplicationSetting < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- # rubocop:disable Migration/AddLimitToTextColumns
- # limit is added in 20201119133604_add_text_limit_to_application_setting_personal_access_token_prefix
- def change
- add_column :application_settings, :personal_access_token_prefix, :text
- end
- # rubocop:enable Migration/AddLimitToTextColumns
-end
diff --git a/db/migrate/20201119133604_add_text_limit_to_application_setting_personal_access_token_prefix.rb b/db/migrate/20201119133604_add_text_limit_to_application_setting_personal_access_token_prefix.rb
deleted file mode 100644
index a118da9e3e7..00000000000
--- a/db/migrate/20201119133604_add_text_limit_to_application_setting_personal_access_token_prefix.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToApplicationSettingPersonalAccessTokenPrefix < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :application_settings, :personal_access_token_prefix, 20
- end
-
- def down
- remove_text_limit :application_settings, :personal_access_token_prefix
- end
-end
diff --git a/db/migrate/20201119162801_change_services_inherit_from_id_foreign_key.rb b/db/migrate/20201119162801_change_services_inherit_from_id_foreign_key.rb
deleted file mode 100644
index a7f12fcf726..00000000000
--- a/db/migrate/20201119162801_change_services_inherit_from_id_foreign_key.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeServicesInheritFromIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_foreign_key :services, :services, column: :inherit_from_id, on_delete: :cascade, name: 'fk_services_inherit_from_id'
- remove_foreign_key_if_exists :services, name: 'fk_868a8e7ad6'
- end
-
- def down
- remove_foreign_key_if_exists :services, name: 'fk_services_inherit_from_id'
- add_concurrent_foreign_key :services, :services, column: :inherit_from_id, on_delete: :nullify, name: 'fk_868a8e7ad6'
- end
-end
diff --git a/db/migrate/20201119164605_add_checksum_into_vulnerability_remediations.rb b/db/migrate/20201119164605_add_checksum_into_vulnerability_remediations.rb
deleted file mode 100644
index a9ac1ed0676..00000000000
--- a/db/migrate/20201119164605_add_checksum_into_vulnerability_remediations.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddChecksumIntoVulnerabilityRemediations < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :vulnerability_remediations, :checksum, :binary, null: false, comment: 'Stores the SHA256 checksum of the attached diff file' # rubocop:disable Rails/NotNullColumn
-
- add_index :vulnerability_remediations, :checksum, unique: true # rubocop:disable Migration/AddIndex (Table is empty)
- end
-end
diff --git a/db/migrate/20201119213406_change_terraform_versioning_enabled_default.rb b/db/migrate/20201119213406_change_terraform_versioning_enabled_default.rb
deleted file mode 100644
index 490fe481589..00000000000
--- a/db/migrate/20201119213406_change_terraform_versioning_enabled_default.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeTerraformVersioningEnabledDefault < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_column_default :terraform_states, :versioning_enabled, from: false, to: true
- end
-end
diff --git a/db/migrate/20201120092000_add_kroki_formats_to_application_settings_table.rb b/db/migrate/20201120092000_add_kroki_formats_to_application_settings_table.rb
deleted file mode 100644
index a059099dbc4..00000000000
--- a/db/migrate/20201120092000_add_kroki_formats_to_application_settings_table.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AddKrokiFormatsToApplicationSettingsTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_table :application_settings do |t|
- t.jsonb :kroki_formats, null: false, default: {}
- end
- end
-end
diff --git a/db/migrate/20201120125953_replace_unused_labels_index.rb b/db/migrate/20201120125953_replace_unused_labels_index.rb
deleted file mode 100644
index afddbce618d..00000000000
--- a/db/migrate/20201120125953_replace_unused_labels_index.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class ReplaceUnusedLabelsIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- NEW_INDEX_NAME = 'index_labels_on_group_id_and_title_with_null_project_id'
- OLD_INDEX_NAME = 'index_labels_on_group_id_and_title'
-
- def up
- add_concurrent_index :labels, [:group_id, :title], where: 'project_id IS NULL', name: NEW_INDEX_NAME
- remove_concurrent_index_by_name :labels, OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :labels, [:group_id, :title], where: 'project_id = NULL::integer', name: OLD_INDEX_NAME
- remove_concurrent_index_by_name :labels, NEW_INDEX_NAME
- end
-end
diff --git a/db/migrate/20201120144823_create_tokens_with_iv.rb b/db/migrate/20201120144823_create_tokens_with_iv.rb
deleted file mode 100644
index f8dc75513fb..00000000000
--- a/db/migrate/20201120144823_create_tokens_with_iv.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class CreateTokensWithIv < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- create_table :token_with_ivs do |t|
- t.binary :hashed_token, null: false
- t.binary :hashed_plaintext_token, null: false
- t.binary :iv, null: false
-
- t.index :hashed_token, name: 'index_token_with_ivs_on_hashed_token', unique: true, using: :btree
- t.index :hashed_plaintext_token, name: 'index_token_with_ivs_on_hashed_plaintext_token', unique: true, using: :btree
- end
- end
-end
diff --git a/db/migrate/20201123081307_add_operations_project_feature_to_metrics.rb b/db/migrate/20201123081307_add_operations_project_feature_to_metrics.rb
deleted file mode 100644
index 6801b49fae5..00000000000
--- a/db/migrate/20201123081307_add_operations_project_feature_to_metrics.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddOperationsProjectFeatureToMetrics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :project_features, :operations_access_level, :integer, default: 20, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :project_features, :operations_access_level
- end
- end
-end
diff --git a/db/migrate/20201123161611_add_provisioned_by_group_to_user_details.rb b/db/migrate/20201123161611_add_provisioned_by_group_to_user_details.rb
deleted file mode 100644
index 6e4d0e84509..00000000000
--- a/db/migrate/20201123161611_add_provisioned_by_group_to_user_details.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class AddProvisionedByGroupToUserDetails < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_user_details_on_provisioned_by_group_id'
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:user_details, :provisioned_by_group_id)
- with_lock_retries { add_column(:user_details, :provisioned_by_group_id, :integer, limit: 8) }
- end
-
- add_concurrent_index :user_details, :provisioned_by_group_id, name: INDEX_NAME
- add_concurrent_foreign_key :user_details, :namespaces, column: :provisioned_by_group_id, on_delete: :nullify
- end
-
- def down
- with_lock_retries { remove_foreign_key_without_error :user_details, column: :provisioned_by_group_id }
-
- remove_concurrent_index_by_name :user_details, INDEX_NAME
-
- if column_exists?(:user_details, :provisioned_by_group_id)
- with_lock_retries { remove_column(:user_details, :provisioned_by_group_id) }
- end
- end
-end
diff --git a/db/migrate/20201124030537_create_incident_management_on_call_rotations.rb b/db/migrate/20201124030537_create_incident_management_on_call_rotations.rb
deleted file mode 100644
index 18546d97fd5..00000000000
--- a/db/migrate/20201124030537_create_incident_management_on_call_rotations.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class CreateIncidentManagementOnCallRotations < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:incident_management_oncall_rotations)
- with_lock_retries do
- create_table :incident_management_oncall_rotations do |t|
- t.timestamps_with_timezone
- t.references :oncall_schedule, index: false, null: false, foreign_key: { to_table: :incident_management_oncall_schedules, on_delete: :cascade }
- t.integer :length, null: false
- t.integer :length_unit, limit: 2, null: false
- t.datetime_with_timezone :starts_at, null: false
- t.text :name, null: false
-
- t.index %w(oncall_schedule_id id), name: 'index_inc_mgmnt_oncall_rotations_on_oncall_schedule_id_and_id', unique: true, using: :btree
- t.index %w(oncall_schedule_id name), name: 'index_inc_mgmnt_oncall_rotations_on_oncall_schedule_id_and_name', unique: true, using: :btree
- end
- end
- end
-
- add_text_limit :incident_management_oncall_rotations, :name, 200
- end
-
- def down
- with_lock_retries do
- drop_table :incident_management_oncall_rotations
- end
- end
-end
diff --git a/db/migrate/20201124075951_create_vulnerability_external_links.rb b/db/migrate/20201124075951_create_vulnerability_external_links.rb
deleted file mode 100644
index 8200b15559b..00000000000
--- a/db/migrate/20201124075951_create_vulnerability_external_links.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-class CreateVulnerabilityExternalLinks < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- create_table :vulnerability_external_issue_links, if_not_exists: true do |t|
- t.timestamps_with_timezone null: false
- t.references :author, null: false, index: true, foreign_key: { to_table: :users, on_delete: :nullify }, type: :bigint
- t.references :vulnerability, null: false, index: true, type: :bigint
- t.integer :link_type, limit: 2, null: false, default: 1 # 'created'
- t.integer :external_type, limit: 2, null: false, default: 1 # 'jira'
- t.text :external_project_key, null: false
- t.text :external_issue_key, null: false
-
- t.index %i[vulnerability_id external_type external_project_key external_issue_key],
- name: 'idx_vulnerability_ext_issue_links_on_vulne_id_and_ext_issue',
- unique: true
- t.index %i[vulnerability_id link_type],
- name: 'idx_vulnerability_ext_issue_links_on_vulne_id_and_link_type',
- where: 'link_type = 1',
- unique: true # only one 'created' link per vulnerability is allowed
- end
- end
-
- add_concurrent_foreign_key :vulnerability_external_issue_links, :vulnerabilities, column: :vulnerability_id, on_delete: :cascade
-
- add_text_limit :vulnerability_external_issue_links, :external_project_key, 255
- add_text_limit :vulnerability_external_issue_links, :external_issue_key, 255
- end
-
- def down
- with_lock_retries do
- drop_table :vulnerability_external_issue_links
- end
- end
-end
diff --git a/db/migrate/20201125030847_create_dependency_proxy_manifests.rb b/db/migrate/20201125030847_create_dependency_proxy_manifests.rb
deleted file mode 100644
index 6c1a3f23bf3..00000000000
--- a/db/migrate/20201125030847_create_dependency_proxy_manifests.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDependencyProxyManifests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- create_table :dependency_proxy_manifests, if_not_exists: true do |t|
- t.timestamps_with_timezone
- t.references :group, index: false, null: false, foreign_key: { to_table: :namespaces, on_delete: :cascade }, type: :bigint
- t.bigint :size
- t.integer :file_store, limit: 2
- t.text :file_name, null: false
- t.text :file, null: false
- t.text :digest, null: false
-
- t.index [:group_id, :digest], name: 'index_dependency_proxy_manifests_on_group_id_and_digest'
- end
- end
-
- add_text_limit :dependency_proxy_manifests, :file_name, 255
- add_text_limit :dependency_proxy_manifests, :file, 255
- add_text_limit :dependency_proxy_manifests, :digest, 255
- end
-
- def down
- drop_table :dependency_proxy_manifests
- end
-end
diff --git a/db/migrate/20201125233219_add_incident_management_on_call_participants.rb b/db/migrate/20201125233219_add_incident_management_on_call_participants.rb
deleted file mode 100644
index 2a9b1d8b276..00000000000
--- a/db/migrate/20201125233219_add_incident_management_on_call_participants.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class AddIncidentManagementOnCallParticipants < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- PARTICIPANT_ROTATION_INDEX_NAME = 'index_inc_mgmnt_oncall_participants_on_oncall_rotation_id'
- PARTICIPANT_USER_INDEX_NAME = 'index_inc_mgmnt_oncall_participants_on_oncall_user_id'
- UNIQUE_INDEX_NAME = 'index_inc_mgmnt_oncall_participants_on_user_id_and_rotation_id'
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:incident_management_oncall_participants)
- with_lock_retries do
- create_table :incident_management_oncall_participants do |t|
- t.references :oncall_rotation, index: false, null: false, foreign_key: { to_table: :incident_management_oncall_rotations, on_delete: :cascade }
- t.references :user, index: false, null: false, foreign_key: { on_delete: :cascade }
- t.integer :color_palette, limit: 2, null: false
- t.integer :color_weight, limit: 2, null: false
- t.index :user_id, name: PARTICIPANT_USER_INDEX_NAME
- t.index :oncall_rotation_id, name: PARTICIPANT_ROTATION_INDEX_NAME
- t.index [:user_id, :oncall_rotation_id], unique: true, name: UNIQUE_INDEX_NAME
- end
- end
- end
- end
-
- def down
- drop_table :incident_management_oncall_participants
- end
-end
diff --git a/db/migrate/20201126165919_add_epic_boards.rb b/db/migrate/20201126165919_add_epic_boards.rb
deleted file mode 100644
index 432b839d6ea..00000000000
--- a/db/migrate/20201126165919_add_epic_boards.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class AddEpicBoards < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- create_table :boards_epic_boards do |t|
- t.boolean :hide_backlog_list, default: false, null: false
- t.boolean :hide_closed_list, default: false, null: false
- t.references :group, index: true, foreign_key: { to_table: :namespaces, on_delete: :cascade }, null: false
- t.timestamps_with_timezone
- t.text :name, default: 'Development', null: false
- end
- end
-
- add_text_limit :boards_epic_boards, :name, 255
- end
-
- def down
- with_lock_retries do
- drop_table :boards_epic_boards
- end
- end
-end
diff --git a/db/migrate/20201126172030_add_feed_token_off_to_settings.rb b/db/migrate/20201126172030_add_feed_token_off_to_settings.rb
deleted file mode 100644
index 04e05c9bd43..00000000000
--- a/db/migrate/20201126172030_add_feed_token_off_to_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddFeedTokenOffToSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :application_settings, :disable_feed_token, :boolean, null: false, default: false
- end
-end
diff --git a/db/migrate/20201126190039_add_epic_board_labels.rb b/db/migrate/20201126190039_add_epic_board_labels.rb
deleted file mode 100644
index 519e705ce14..00000000000
--- a/db/migrate/20201126190039_add_epic_board_labels.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class AddEpicBoardLabels < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- create_table :boards_epic_board_labels do |t|
- t.references :epic_board, index: true, foreign_key: { to_table: :boards_epic_boards, on_delete: :cascade }, null: false
- t.references :label, index: true, foreign_key: { on_delete: :cascade }, null: false
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :boards_epic_board_labels
- end
- end
-end
diff --git a/db/migrate/20201127104228_add_index_to_security_scans_on_created_at_and_id.rb b/db/migrate/20201127104228_add_index_to_security_scans_on_created_at_and_id.rb
deleted file mode 100644
index c9bbe8ab77d..00000000000
--- a/db/migrate/20201127104228_add_index_to_security_scans_on_created_at_and_id.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToSecurityScansOnCreatedAtAndId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_security_scans_on_date_created_at_and_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :security_scans, "date(timezone('UTC', created_at)), id", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name(:security_scans, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20201127141433_add_other_role_to_user_details.rb b/db/migrate/20201127141433_add_other_role_to_user_details.rb
deleted file mode 100644
index 586dbb033fd..00000000000
--- a/db/migrate/20201127141433_add_other_role_to_user_details.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class AddOtherRoleToUserDetails < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless column_exists?(:user_details, :other_role)
- with_lock_retries do
- add_column :user_details, :other_role, :text
- end
- end
-
- add_text_limit :user_details, :other_role, 100
- end
-
- def down
- with_lock_retries do
- remove_column :user_details, :other_role
- end
- end
-end
diff --git a/db/migrate/20201127170848_add_index_bloat_estimate_view.rb b/db/migrate/20201127170848_add_index_bloat_estimate_view.rb
deleted file mode 100644
index ab268f8569e..00000000000
--- a/db/migrate/20201127170848_add_index_bloat_estimate_view.rb
+++ /dev/null
@@ -1,109 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexBloatEstimateView < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute(<<~SQL)
- CREATE VIEW postgres_index_bloat_estimates AS
- -- Originally from: https://github.com/ioguix/pgsql-bloat-estimation/blob/master/btree/btree_bloat.sql
- -- WARNING: executed with a non-superuser role, the query inspect only index on tables you are granted to read.
- -- WARNING: rows with is_na = 't' are known to have bad statistics ("name" type is not supported).
- -- This query is compatible with PostgreSQL 8.2 and after
- SELECT nspname || '.' || idxname as identifier,
- CASE WHEN relpages > est_pages_ff
- THEN bs*(relpages-est_pages_ff)
- ELSE 0
- END::bigint AS bloat_size_bytes
- FROM (
- SELECT
- coalesce(1 +
- ceil(reltuples/floor((bs-pageopqdata-pagehdr)*fillfactor/(100*(4+nulldatahdrwidth)::float))), 0
- ) AS est_pages_ff,
- bs, nspname, tblname, idxname, relpages, is_na
- FROM (
- SELECT maxalign, bs, nspname, tblname, idxname, reltuples, relpages, idxoid, fillfactor,
- ( index_tuple_hdr_bm +
- maxalign - CASE -- Add padding to the index tuple header to align on MAXALIGN
- WHEN index_tuple_hdr_bm%maxalign = 0 THEN maxalign
- ELSE index_tuple_hdr_bm%maxalign
- END
- + nulldatawidth + maxalign - CASE -- Add padding to the data to align on MAXALIGN
- WHEN nulldatawidth = 0 THEN 0
- WHEN nulldatawidth::integer%maxalign = 0 THEN maxalign
- ELSE nulldatawidth::integer%maxalign
- END
- )::numeric AS nulldatahdrwidth, pagehdr, pageopqdata, is_na
- FROM (
- SELECT n.nspname, i.tblname, i.idxname, i.reltuples, i.relpages,
- i.idxoid, i.fillfactor, current_setting('block_size')::numeric AS bs,
- CASE -- MAXALIGN: 4 on 32bits, 8 on 64bits (and mingw32 ?)
- WHEN version() ~ 'mingw32' OR version() ~ '64-bit|x86_64|ppc64|ia64|amd64' THEN 8
- ELSE 4
- END AS maxalign,
- /* per page header, fixed size: 20 for 7.X, 24 for others */
- 24 AS pagehdr,
- /* per page btree opaque data */
- 16 AS pageopqdata,
- /* per tuple header: add IndexAttributeBitMapData if some cols are null-able */
- CASE WHEN max(coalesce(s.null_frac,0)) = 0
- THEN 2 -- IndexTupleData size
- ELSE 2 + (( 32 + 8 - 1 ) / 8) -- IndexTupleData size + IndexAttributeBitMapData size ( max num filed per index + 8 - 1 /8)
- END AS index_tuple_hdr_bm,
- /* data len: we remove null values save space using it fractionnal part from stats */
- sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 1024)) AS nulldatawidth,
- max( CASE WHEN i.atttypid = 'pg_catalog.name'::regtype THEN 1 ELSE 0 END ) > 0 AS is_na
- FROM (
- SELECT ct.relname AS tblname, ct.relnamespace, ic.idxname, ic.attpos, ic.indkey, ic.indkey[ic.attpos], ic.reltuples, ic.relpages, ic.tbloid, ic.idxoid, ic.fillfactor,
- coalesce(a1.attnum, a2.attnum) AS attnum, coalesce(a1.attname, a2.attname) AS attname, coalesce(a1.atttypid, a2.atttypid) AS atttypid,
- CASE WHEN a1.attnum IS NULL
- THEN ic.idxname
- ELSE ct.relname
- END AS attrelname
- FROM (
- SELECT idxname, reltuples, relpages, tbloid, idxoid, fillfactor, indkey,
- pg_catalog.generate_series(1,indnatts) AS attpos
- FROM (
- SELECT ci.relname AS idxname, ci.reltuples, ci.relpages, i.indrelid AS tbloid,
- i.indexrelid AS idxoid,
- coalesce(substring(
- array_to_string(ci.reloptions, ' ')
- from 'fillfactor=([0-9]+)')::smallint, 90) AS fillfactor,
- i.indnatts,
- pg_catalog.string_to_array(pg_catalog.textin(
- pg_catalog.int2vectorout(i.indkey)),' ')::int[] AS indkey
- FROM pg_catalog.pg_index i
- JOIN pg_catalog.pg_class ci ON ci.oid = i.indexrelid
- WHERE ci.relam=(SELECT oid FROM pg_am WHERE amname = 'btree')
- AND ci.relpages > 0
- ) AS idx_data
- ) AS ic
- JOIN pg_catalog.pg_class ct ON ct.oid = ic.tbloid
- LEFT JOIN pg_catalog.pg_attribute a1 ON
- ic.indkey[ic.attpos] <> 0
- AND a1.attrelid = ic.tbloid
- AND a1.attnum = ic.indkey[ic.attpos]
- LEFT JOIN pg_catalog.pg_attribute a2 ON
- ic.indkey[ic.attpos] = 0
- AND a2.attrelid = ic.idxoid
- AND a2.attnum = ic.attpos
- ) i
- JOIN pg_catalog.pg_namespace n ON n.oid = i.relnamespace
- JOIN pg_catalog.pg_stats s ON s.schemaname = n.nspname
- AND s.tablename = i.attrelname
- AND s.attname = i.attname
- GROUP BY 1,2,3,4,5,6,7,8,9,10,11
- ) AS rows_data_stats
- ) AS rows_hdr_pdg_stats
- ) AS relation_stats
- WHERE nspname IN ("current_schema"(), 'gitlab_partitions_dynamic', 'gitlab_partitions_static') AND NOT is_na
- ORDER BY nspname, tblname, idxname;
- SQL
- end
-
- def down
- execute(<<~SQL)
- DROP VIEW postgres_index_bloat_estimates
- SQL
- end
-end
diff --git a/db/migrate/20201128210000_add_service_desk_reply_to_is_not_null_index_on_issues_fix.rb b/db/migrate/20201128210000_add_service_desk_reply_to_is_not_null_index_on_issues_fix.rb
deleted file mode 100644
index 52d24de60d5..00000000000
--- a/db/migrate/20201128210000_add_service_desk_reply_to_is_not_null_index_on_issues_fix.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddServiceDeskReplyToIsNotNullIndexOnIssuesFix < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'idx_on_issues_where_service_desk_reply_to_is_not_null'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:issues, [:id], name: INDEX_NAME, where: 'service_desk_reply_to IS NOT NULL')
- end
-
- def down
- remove_concurrent_index_by_name(:issues, INDEX_NAME)
- end
-end
diff --git a/db/migrate/20201201033202_add_verification_indexes_for_package_files.rb b/db/migrate/20201201033202_add_verification_indexes_for_package_files.rb
deleted file mode 100644
index b7f55101682..00000000000
--- a/db/migrate/20201201033202_add_verification_indexes_for_package_files.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class AddVerificationIndexesForPackageFiles < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- PENDING_VERIFICATION_INDEX_NAME = "packages_packages_pending_verification"
- FAILED_VERIFICATION_INDEX_NAME = "packages_packages_failed_verification"
- NEEDS_VERIFICATION_INDEX_NAME = "packages_packages_needs_verification"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :packages_package_files, :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
- add_concurrent_index :packages_package_files, :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
- add_concurrent_index :packages_package_files, :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :packages_package_files, PENDING_VERIFICATION_INDEX_NAME
- remove_concurrent_index_by_name :packages_package_files, FAILED_VERIFICATION_INDEX_NAME
- remove_concurrent_index_by_name :packages_package_files, NEEDS_VERIFICATION_INDEX_NAME
- end
-end
diff --git a/db/migrate/20201201034258_add_index_for_non_system_noteables.rb b/db/migrate/20201201034258_add_index_for_non_system_noteables.rb
deleted file mode 100644
index 5927463e767..00000000000
--- a/db/migrate/20201201034258_add_index_for_non_system_noteables.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexForNonSystemNoteables < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- LEGACY_INDEX_NAME = "index_notes_on_noteable_id_and_noteable_type"
- NEW_INDEX_NAME = "index_notes_on_noteable_id_and_noteable_type_and_system"
-
- def up
- add_concurrent_index :notes, [:noteable_id, :noteable_type, :system], name: NEW_INDEX_NAME
-
- remove_concurrent_index_by_name :notes, LEGACY_INDEX_NAME
- end
-
- def down
- add_concurrent_index :notes, [:noteable_id, :noteable_type], name: LEGACY_INDEX_NAME
-
- remove_concurrent_index_by_name :notes, NEW_INDEX_NAME
- end
-end
diff --git a/db/migrate/20201201161655_add_primary_key_to_elastic_search_indexed_projects.rb b/db/migrate/20201201161655_add_primary_key_to_elastic_search_indexed_projects.rb
deleted file mode 100644
index cf7221693f9..00000000000
--- a/db/migrate/20201201161655_add_primary_key_to_elastic_search_indexed_projects.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class AddPrimaryKeyToElasticSearchIndexedProjects < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- UNIQUE_INDEX_NAME = 'index_elasticsearch_indexed_projects_on_project_id'
- PRIMARY_KEY_NAME = 'elasticsearch_indexed_projects_pkey'
-
- def up
- execute(<<~SQL)
- DELETE FROM elasticsearch_indexed_projects
- WHERE project_id IS NULL
- SQL
-
- execute(<<~SQL)
- ALTER TABLE elasticsearch_indexed_projects
- ALTER COLUMN project_id SET NOT NULL,
- ADD CONSTRAINT #{PRIMARY_KEY_NAME} PRIMARY KEY USING INDEX #{UNIQUE_INDEX_NAME}
- SQL
- end
-
- def down
- add_index :elasticsearch_indexed_projects, :project_id, unique: true, name: UNIQUE_INDEX_NAME # rubocop:disable Migration/AddIndex
-
- execute(<<~SQL)
- ALTER TABLE elasticsearch_indexed_projects
- DROP CONSTRAINT #{PRIMARY_KEY_NAME},
- ALTER COLUMN project_id DROP NOT NULL
- SQL
- end
-end
diff --git a/db/migrate/20201201163227_add_finding_uuid_to_vulnerability_feedback.rb b/db/migrate/20201201163227_add_finding_uuid_to_vulnerability_feedback.rb
deleted file mode 100644
index a2e13806000..00000000000
--- a/db/migrate/20201201163227_add_finding_uuid_to_vulnerability_feedback.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class AddFindingUuidToVulnerabilityFeedback < ActiveRecord::Migration[6.0]
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- def change
- add_column :vulnerability_feedback, :finding_uuid, :uuid
- end
-end
diff --git a/db/migrate/20201201175656_add_index_vulnerabilities_on_project_id_and_state_and_severity.rb b/db/migrate/20201201175656_add_index_vulnerabilities_on_project_id_and_state_and_severity.rb
deleted file mode 100644
index d0e8920d7a5..00000000000
--- a/db/migrate/20201201175656_add_index_vulnerabilities_on_project_id_and_state_and_severity.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexVulnerabilitiesOnProjectIdAndStateAndSeverity < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_vulnerabilities_on_project_id_and_state_and_severity'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :vulnerabilities, [:project_id, :state, :severity], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201201190002_add_other_context_to_experiment_user.rb b/db/migrate/20201201190002_add_other_context_to_experiment_user.rb
deleted file mode 100644
index c901f049e75..00000000000
--- a/db/migrate/20201201190002_add_other_context_to_experiment_user.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddOtherContextToExperimentUser < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :experiment_users, :context, :jsonb, default: {}, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :experiment_users, :context
- end
- end
-end
diff --git a/db/migrate/20201201192112_add_primary_key_to_elastic_search_indexed_namespaces.rb b/db/migrate/20201201192112_add_primary_key_to_elastic_search_indexed_namespaces.rb
deleted file mode 100644
index 610cd2828ca..00000000000
--- a/db/migrate/20201201192112_add_primary_key_to_elastic_search_indexed_namespaces.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-class AddPrimaryKeyToElasticSearchIndexedNamespaces < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- UNIQUE_INDEX_NAME = 'index_elasticsearch_indexed_namespaces_on_namespace_id'
- PRIMARY_KEY_NAME = 'elasticsearch_indexed_namespaces_pkey'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- execute(<<~SQL)
- LOCK TABLE elasticsearch_indexed_namespaces IN ACCESS EXCLUSIVE MODE;
-
- DELETE FROM elasticsearch_indexed_namespaces
- WHERE namespace_id IS NULL;
-
- ALTER TABLE elasticsearch_indexed_namespaces
- ADD CONSTRAINT #{PRIMARY_KEY_NAME} PRIMARY KEY USING INDEX #{UNIQUE_INDEX_NAME};
- SQL
- end
- end
-
- def down
- add_concurrent_index :elasticsearch_indexed_namespaces, :namespace_id, unique: true, name: UNIQUE_INDEX_NAME
-
- with_lock_retries do
- execute(<<~SQL)
- ALTER TABLE elasticsearch_indexed_namespaces
- DROP CONSTRAINT #{PRIMARY_KEY_NAME},
- ALTER COLUMN namespace_id DROP NOT NULL
- SQL
- end
- end
-end
diff --git a/db/migrate/20201202003042_add_epic_board_positions.rb b/db/migrate/20201202003042_add_epic_board_positions.rb
deleted file mode 100644
index 528d5ed3af1..00000000000
--- a/db/migrate/20201202003042_add_epic_board_positions.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class AddEpicBoardPositions < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- create_table :boards_epic_board_positions do |t|
- t.references :epic_board, foreign_key: { to_table: :boards_epic_boards, on_delete: :cascade }, null: false, index: false
- t.references :epic, foreign_key: { on_delete: :cascade }, null: false, index: true
- t.integer :relative_position
-
- t.timestamps_with_timezone null: false
-
- t.index [:epic_board_id, :epic_id], unique: true, name: :index_boards_epic_board_positions_on_epic_board_id_and_epic_id
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :boards_epic_board_positions
- end
- end
-end
diff --git a/db/migrate/20201202025644_add_column_to_security_findings.rb b/db/migrate/20201202025644_add_column_to_security_findings.rb
deleted file mode 100644
index 0b63b79d949..00000000000
--- a/db/migrate/20201202025644_add_column_to_security_findings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-#
-class AddColumnToSecurityFindings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :security_findings, :uuid, :uuid
- end
-end
diff --git a/db/migrate/20201202025937_add_index_to_security_findings_uuid.rb b/db/migrate/20201202025937_add_index_to_security_findings_uuid.rb
deleted file mode 100644
index 4c33809fbfc..00000000000
--- a/db/migrate/20201202025937_add_index_to_security_findings_uuid.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToSecurityFindingsUuid < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_security_findings_on_uuid'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :security_findings, :uuid, name: INDEX_NAME, unique: true
- end
-
- def down
- remove_concurrent_index_by_name :security_findings, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201202133606_add_sorted_to_merge_request_diffs.rb b/db/migrate/20201202133606_add_sorted_to_merge_request_diffs.rb
deleted file mode 100644
index 4c0d28d70a1..00000000000
--- a/db/migrate/20201202133606_add_sorted_to_merge_request_diffs.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddSortedToMergeRequestDiffs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :merge_request_diffs, :sorted, :boolean, null: false, default: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :merge_request_diffs, :sorted
- end
- end
-end
diff --git a/db/migrate/20201202142751_drop_index_vulnerabilities_on_project_id.rb b/db/migrate/20201202142751_drop_index_vulnerabilities_on_project_id.rb
deleted file mode 100644
index c1ca32a1978..00000000000
--- a/db/migrate/20201202142751_drop_index_vulnerabilities_on_project_id.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class DropIndexVulnerabilitiesOnProjectId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_vulnerabilities_on_project_id'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
- end
-
- def down
- add_concurrent_index :vulnerabilities, :project_id, name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20201202150001_add_details_to_vulnerability_findings.rb b/db/migrate/20201202150001_add_details_to_vulnerability_findings.rb
deleted file mode 100644
index b7639bdfaa3..00000000000
--- a/db/migrate/20201202150001_add_details_to_vulnerability_findings.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddDetailsToVulnerabilityFindings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :vulnerability_occurrences, :details, :jsonb, default: {}, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :vulnerability_occurrences, :details
- end
- end
-end
diff --git a/db/migrate/20201202155913_add_primary_key_to_merge_request_context_commit_diff_files.rb b/db/migrate/20201202155913_add_primary_key_to_merge_request_context_commit_diff_files.rb
deleted file mode 100644
index 90c7b2731c8..00000000000
--- a/db/migrate/20201202155913_add_primary_key_to_merge_request_context_commit_diff_files.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class AddPrimaryKeyToMergeRequestContextCommitDiffFiles < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- execute(<<~SQL)
- DELETE FROM merge_request_context_commit_diff_files
- WHERE merge_request_context_commit_id IS NULL;
-
- DELETE FROM merge_request_context_commit_diff_files df1
- USING merge_request_context_commit_diff_files df2
- WHERE df1.ctid < df2.ctid
- AND df1.merge_request_context_commit_id = df2.merge_request_context_commit_id
- AND df1.relative_order = df2.relative_order;
-
- ALTER TABLE merge_request_context_commit_diff_files
- ADD CONSTRAINT merge_request_context_commit_diff_files_pkey PRIMARY KEY (merge_request_context_commit_id, relative_order);
- SQL
- end
-
- def down
- execute(<<~SQL)
- ALTER TABLE merge_request_context_commit_diff_files
- DROP CONSTRAINT merge_request_context_commit_diff_files_pkey,
- ALTER COLUMN merge_request_context_commit_id DROP NOT NULL
- SQL
- end
-end
diff --git a/db/migrate/20201202160105_add_group_file_name_index_to_dependency_proxy_manifests.rb b/db/migrate/20201202160105_add_group_file_name_index_to_dependency_proxy_manifests.rb
deleted file mode 100644
index a0bafeedaec..00000000000
--- a/db/migrate/20201202160105_add_group_file_name_index_to_dependency_proxy_manifests.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddGroupFileNameIndexToDependencyProxyManifests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- NEW_INDEX = 'index_dependency_proxy_manifests_on_group_id_and_file_name'
- OLD_INDEX = 'index_dependency_proxy_manifests_on_group_id_and_digest'
-
- def up
- add_concurrent_index :dependency_proxy_manifests, [:group_id, :file_name], name: NEW_INDEX, unique: true
- remove_concurrent_index_by_name :dependency_proxy_manifests, OLD_INDEX
- end
-
- def down
- add_concurrent_index :dependency_proxy_manifests, [:group_id, :digest], name: OLD_INDEX
- remove_concurrent_index_by_name :dependency_proxy_manifests, NEW_INDEX
- end
-end
diff --git a/db/migrate/20201202161021_remove_redundant_index_on_merge_request_context_commit_diff_files.rb b/db/migrate/20201202161021_remove_redundant_index_on_merge_request_context_commit_diff_files.rb
deleted file mode 100644
index a9c0a079955..00000000000
--- a/db/migrate/20201202161021_remove_redundant_index_on_merge_request_context_commit_diff_files.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveRedundantIndexOnMergeRequestContextCommitDiffFiles < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :merge_request_context_commit_diff_files, 'idx_mr_cc_diff_files_on_mr_cc_id'
- end
-
- def down
- # no-op: this index is not tracked in structure.sql, and is redundant due to idx_mr_cc_diff_files_on_mr_cc_id_and_sha
- end
-end
diff --git a/db/migrate/20201203123524_add_domain_enum_to_alerts.rb b/db/migrate/20201203123524_add_domain_enum_to_alerts.rb
deleted file mode 100644
index f1dec91a346..00000000000
--- a/db/migrate/20201203123524_add_domain_enum_to_alerts.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddDomainEnumToAlerts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :alert_management_alerts, :domain, :integer, limit: 2, default: 0
- end
- end
-
- def down
- with_lock_retries do
- remove_column :alert_management_alerts, :domain, :integer, limit: 2
- end
- end
-end
diff --git a/db/migrate/20201203144655_add_allow_to_edit_commit_to_project_settings.rb b/db/migrate/20201203144655_add_allow_to_edit_commit_to_project_settings.rb
deleted file mode 100644
index fb2f7366955..00000000000
--- a/db/migrate/20201203144655_add_allow_to_edit_commit_to_project_settings.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class AddAllowToEditCommitToProjectSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- # no-op
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20201203171631_add_index_to_domain.rb b/db/migrate/20201203171631_add_index_to_domain.rb
deleted file mode 100644
index dc7b9539e95..00000000000
--- a/db/migrate/20201203171631_add_index_to_domain.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToDomain < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
- INDEX_NAME = 'index_alert_management_alerts_on_domain'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :alert_management_alerts, :domain, name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :alert_management_alerts, :domain, name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20201204085522_add_project_id_into_vulnerability_remediations.rb b/db/migrate/20201204085522_add_project_id_into_vulnerability_remediations.rb
deleted file mode 100644
index 6a136ab0389..00000000000
--- a/db/migrate/20201204085522_add_project_id_into_vulnerability_remediations.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectIdIntoVulnerabilityRemediations < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- connection.execute('DELETE FROM vulnerability_remediations')
-
- add_column :vulnerability_remediations, :project_id, :bigint, null: false # rubocop:disable Rails/NotNullColumn
- end
-
- def down
- with_lock_retries do
- remove_column :vulnerability_remediations, :project_id
- end
- end
-end
diff --git a/db/migrate/20201204090855_add_compound_index_to_vulnerability_remediations_table.rb b/db/migrate/20201204090855_add_compound_index_to_vulnerability_remediations_table.rb
deleted file mode 100644
index 0b4b6e552aa..00000000000
--- a/db/migrate/20201204090855_add_compound_index_to_vulnerability_remediations_table.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class AddCompoundIndexToVulnerabilityRemediationsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- NEW_INDEX_NAME = 'index_vulnerability_remediations_on_project_id_and_checksum'
- OLD_INDEX_NAME = 'index_vulnerability_remediations_on_checksum'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :vulnerability_remediations, [:project_id, :checksum], unique: true, name: NEW_INDEX_NAME
- add_concurrent_foreign_key :vulnerability_remediations, :projects, column: :project_id
-
- remove_concurrent_index_by_name :vulnerability_remediations, OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :vulnerability_remediations, :checksum, unique: true, name: OLD_INDEX_NAME
-
- remove_concurrent_index_by_name :vulnerability_remediations, NEW_INDEX_NAME
-
- with_lock_retries do
- remove_foreign_key_if_exists :vulnerability_remediations, column: :project_id
- end
- end
-end
diff --git a/db/migrate/20201204105300_create_packages_debian_file_metadata.rb b/db/migrate/20201204105300_create_packages_debian_file_metadata.rb
deleted file mode 100644
index 2bba1b6f38e..00000000000
--- a/db/migrate/20201204105300_create_packages_debian_file_metadata.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackagesDebianFileMetadata < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:packages_debian_file_metadata)
- create_table :packages_debian_file_metadata, id: false do |t|
- t.timestamps_with_timezone
- t.references :package_file, primary_key: true, index: false, default: nil, null: false, foreign_key: { to_table: :packages_package_files, on_delete: :cascade }, type: :bigint
- t.integer :file_type, limit: 2, null: false
- t.text :component
- t.text :architecture
- t.jsonb :fields
- end
- end
-
- add_text_limit :packages_debian_file_metadata, :component, 255
- add_text_limit :packages_debian_file_metadata, :architecture, 255
- end
-
- def down
- drop_table :packages_debian_file_metadata
- end
-end
diff --git a/db/migrate/20201204110700_create_packages_debian_project_distributions.rb b/db/migrate/20201204110700_create_packages_debian_project_distributions.rb
deleted file mode 100644
index 5fe45c6236f..00000000000
--- a/db/migrate/20201204110700_create_packages_debian_project_distributions.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackagesDebianProjectDistributions < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- UNIQUE_CODENAME = 'uniq_pkgs_debian_project_distributions_project_id_and_codename'
- UNIQUE_SUITE = 'uniq_pkgs_debian_project_distributions_project_id_and_suite'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- unless table_exists?(:packages_debian_project_distributions)
- create_table :packages_debian_project_distributions do |t|
- t.timestamps_with_timezone
- t.references :project, foreign_key: { to_table: :projects, on_delete: :restrict }, null: false
- t.references :creator, foreign_key: { to_table: :users, on_delete: :nullify }
- t.integer :valid_time_duration_seconds
- t.integer :file_store, limit: 2, default: 1, null: false
- t.boolean :automatic, default: true, null: false
- t.boolean :automatic_upgrades, default: false, null: false
- t.text :codename, null: false
- t.text :suite
- t.text :origin
- t.text :label
- t.text :version
- t.text :description
- t.text :encrypted_signing_keys
- t.text :encrypted_signing_keys_iv
- t.text :file
- t.text :file_signature
-
- t.index %w(project_id codename),
- name: UNIQUE_CODENAME,
- unique: true,
- using: :btree
- t.index %w(project_id suite),
- name: UNIQUE_SUITE,
- unique: true,
- using: :btree
- end
- end
- end
-
- add_text_limit :packages_debian_project_distributions, :codename, 255
- add_text_limit :packages_debian_project_distributions, :suite, 255
- add_text_limit :packages_debian_project_distributions, :origin, 255
- add_text_limit :packages_debian_project_distributions, :label, 255
- add_text_limit :packages_debian_project_distributions, :version, 255
- add_text_limit :packages_debian_project_distributions, :description, 255
- add_text_limit :packages_debian_project_distributions, :encrypted_signing_keys, 2048
- add_text_limit :packages_debian_project_distributions, :encrypted_signing_keys_iv, 255
- add_text_limit :packages_debian_project_distributions, :file, 255
- add_text_limit :packages_debian_project_distributions, :file_signature, 4096
- end
-
- def down
- drop_table :packages_debian_project_distributions
- end
-end
diff --git a/db/migrate/20201204110800_create_packages_debian_group_distributions.rb b/db/migrate/20201204110800_create_packages_debian_group_distributions.rb
deleted file mode 100644
index 9ad9a59b3e9..00000000000
--- a/db/migrate/20201204110800_create_packages_debian_group_distributions.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackagesDebianGroupDistributions < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- UNIQUE_CODENAME = 'uniq_pkgs_debian_group_distributions_group_id_and_codename'
- UNIQUE_SUITE = 'uniq_pkgs_debian_group_distributions_group_id_and_suite'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- unless table_exists?(:packages_debian_group_distributions)
- create_table :packages_debian_group_distributions do |t|
- t.timestamps_with_timezone
- t.references :group, foreign_key: { to_table: :namespaces, on_delete: :restrict }, null: false
- t.references :creator, foreign_key: { to_table: :users, on_delete: :nullify }
- t.integer :valid_time_duration_seconds
- t.integer :file_store, limit: 2, default: 1, null: false
- t.boolean :automatic, default: true, null: false
- t.boolean :automatic_upgrades, default: false, null: false
- t.text :codename, null: false
- t.text :suite
- t.text :origin
- t.text :label
- t.text :version
- t.text :description
- t.text :encrypted_signing_keys
- t.text :encrypted_signing_keys_iv
- t.text :file
- t.text :file_signature
-
- t.index %w(group_id codename),
- name: UNIQUE_CODENAME,
- unique: true,
- using: :btree
- t.index %w(group_id suite),
- name: UNIQUE_SUITE,
- unique: true,
- using: :btree
- end
- end
- end
-
- add_text_limit :packages_debian_group_distributions, :codename, 255
- add_text_limit :packages_debian_group_distributions, :suite, 255
- add_text_limit :packages_debian_group_distributions, :origin, 255
- add_text_limit :packages_debian_group_distributions, :label, 255
- add_text_limit :packages_debian_group_distributions, :version, 255
- add_text_limit :packages_debian_group_distributions, :description, 255
- add_text_limit :packages_debian_group_distributions, :encrypted_signing_keys, 2048
- add_text_limit :packages_debian_group_distributions, :encrypted_signing_keys_iv, 255
- add_text_limit :packages_debian_group_distributions, :file, 255
- add_text_limit :packages_debian_group_distributions, :file_signature, 4096
- end
-
- def down
- drop_table :packages_debian_group_distributions
- end
-end
diff --git a/db/migrate/20201204111000_create_packages_debian_project_architectures.rb b/db/migrate/20201204111000_create_packages_debian_project_architectures.rb
deleted file mode 100644
index f684a413873..00000000000
--- a/db/migrate/20201204111000_create_packages_debian_project_architectures.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackagesDebianProjectArchitectures < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = 'idx_pkgs_deb_proj_architectures_on_distribution_id'
- UNIQUE_NAME = 'uniq_pkgs_deb_proj_architectures_on_distribution_id_and_name'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- unless table_exists?(:packages_debian_project_architectures)
- create_table :packages_debian_project_architectures do |t|
- t.timestamps_with_timezone
- t.references :distribution,
- foreign_key: { to_table: :packages_debian_project_distributions, on_delete: :cascade },
- null: false,
- index: { name: INDEX_NAME }
- t.text :name, null: false
-
- t.index %w(distribution_id name),
- name: UNIQUE_NAME,
- unique: true,
- using: :btree
- end
- end
- end
-
- add_text_limit :packages_debian_project_architectures, :name, 255
- end
-
- def down
- drop_table :packages_debian_project_architectures
- end
-end
diff --git a/db/migrate/20201204111100_create_packages_debian_group_architectures.rb b/db/migrate/20201204111100_create_packages_debian_group_architectures.rb
deleted file mode 100644
index 8a001414c45..00000000000
--- a/db/migrate/20201204111100_create_packages_debian_group_architectures.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackagesDebianGroupArchitectures < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = 'idx_pkgs_deb_grp_architectures_on_distribution_id'
- UNIQUE_NAME = 'uniq_pkgs_deb_grp_architectures_on_distribution_id_and_name'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- unless table_exists?(:packages_debian_group_architectures)
- create_table :packages_debian_group_architectures do |t|
- t.timestamps_with_timezone
- t.references :distribution,
- foreign_key: { to_table: :packages_debian_group_distributions, on_delete: :cascade },
- null: false,
- index: { name: INDEX_NAME }
- t.text :name, null: false
-
- t.index %w(distribution_id name),
- name: UNIQUE_NAME,
- unique: true,
- using: :btree
- end
- end
- end
-
- add_text_limit :packages_debian_group_architectures, :name, 255
- end
-
- def down
- drop_table :packages_debian_group_architectures
- end
-end
diff --git a/db/migrate/20201204111200_create_packages_debian_project_components.rb b/db/migrate/20201204111200_create_packages_debian_project_components.rb
deleted file mode 100644
index 76946967357..00000000000
--- a/db/migrate/20201204111200_create_packages_debian_project_components.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackagesDebianProjectComponents < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- UNIQUE_NAME = 'uniq_pkgs_deb_proj_components_on_distribution_id_and_name'
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:packages_debian_project_components)
- create_table :packages_debian_project_components do |t|
- t.timestamps_with_timezone
- t.references :distribution,
- foreign_key: { to_table: :packages_debian_project_distributions, on_delete: :cascade },
- null: false,
- index: false
- t.text :name, null: false
-
- t.index %w(distribution_id name),
- name: UNIQUE_NAME,
- unique: true,
- using: :btree
- end
- end
-
- add_text_limit :packages_debian_project_components, :name, 255
- end
-
- def down
- drop_table :packages_debian_project_components
- end
-end
diff --git a/db/migrate/20201204111300_create_packages_debian_group_components.rb b/db/migrate/20201204111300_create_packages_debian_group_components.rb
deleted file mode 100644
index c69f8d10c2b..00000000000
--- a/db/migrate/20201204111300_create_packages_debian_group_components.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackagesDebianGroupComponents < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- UNIQUE_NAME = 'uniq_pkgs_deb_grp_components_on_distribution_id_and_name'
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:packages_debian_group_components)
- create_table :packages_debian_group_components do |t|
- t.timestamps_with_timezone
- t.references :distribution,
- foreign_key: { to_table: :packages_debian_group_distributions, on_delete: :cascade },
- null: false,
- index: false
- t.text :name, null: false
-
- t.index %w(distribution_id name),
- name: UNIQUE_NAME,
- unique: true,
- using: :btree
- end
- end
-
- add_text_limit :packages_debian_group_components, :name, 255
- end
-
- def down
- drop_table :packages_debian_group_components
- end
-end
diff --git a/db/migrate/20201204111400_create_packages_debian_project_component_files.rb b/db/migrate/20201204111400_create_packages_debian_project_component_files.rb
deleted file mode 100644
index 74ee1e9c4cf..00000000000
--- a/db/migrate/20201204111400_create_packages_debian_project_component_files.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackagesDebianProjectComponentFiles < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_ARCHITECTURE = 'idx_packages_debian_project_component_files_on_architecture_id'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- unless table_exists?(:packages_debian_project_component_files)
- create_table :packages_debian_project_component_files do |t|
- t.timestamps_with_timezone
- t.references :component,
- foreign_key: { to_table: :packages_debian_project_components, on_delete: :restrict },
- null: false,
- index: true
- t.references :architecture,
- foreign_key: { to_table: :packages_debian_project_architectures, on_delete: :restrict },
- index: { name: INDEX_ARCHITECTURE }
- t.integer :size, null: false
- t.integer :file_type, limit: 2, null: false
- t.integer :compression_type, limit: 2
- t.integer :file_store, limit: 2, default: 1, null: false
- t.text :file, null: false
- t.binary :file_md5, null: false
- t.binary :file_sha256, null: false
- end
- end
- end
-
- add_text_limit :packages_debian_project_component_files, :file, 255
- end
-
- def down
- drop_table :packages_debian_project_component_files
- end
-end
diff --git a/db/migrate/20201204111500_create_packages_debian_group_component_files.rb b/db/migrate/20201204111500_create_packages_debian_group_component_files.rb
deleted file mode 100644
index 2592d5b108a..00000000000
--- a/db/migrate/20201204111500_create_packages_debian_group_component_files.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackagesDebianGroupComponentFiles < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_ARCHITECTURE = 'idx_packages_debian_group_component_files_on_architecture_id'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- unless table_exists?(:packages_debian_group_component_files)
- create_table :packages_debian_group_component_files do |t|
- t.timestamps_with_timezone
- t.references :component,
- foreign_key: { to_table: :packages_debian_group_components, on_delete: :restrict },
- null: false,
- index: true
- t.references :architecture,
- foreign_key: { to_table: :packages_debian_group_architectures, on_delete: :restrict },
- index: { name: INDEX_ARCHITECTURE }
- t.integer :size, null: false
- t.integer :file_type, limit: 2, null: false
- t.integer :compression_type, limit: 2
- t.integer :file_store, limit: 2, default: 1, null: false
- t.text :file, null: false
- t.binary :file_md5, null: false
- t.binary :file_sha256, null: false
- end
- end
- end
-
- add_text_limit :packages_debian_group_component_files, :file, 255
- end
-
- def down
- drop_table :packages_debian_group_component_files
- end
-end
diff --git a/db/migrate/20201204111600_create_packages_debian_publications.rb b/db/migrate/20201204111600_create_packages_debian_publications.rb
deleted file mode 100644
index 2fd26c2c367..00000000000
--- a/db/migrate/20201204111600_create_packages_debian_publications.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackagesDebianPublications < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- create_table :packages_debian_publications do |t|
- t.references :package,
- index: { unique: true },
- null: false,
- foreign_key: { to_table: :packages_packages, on_delete: :cascade }
- t.references :distribution,
- null: false,
- foreign_key: { to_table: :packages_debian_project_distributions, on_delete: :cascade }
- end
- end
-end
diff --git a/db/migrate/20201204141038_add_trace_bytesize_to_ci_build_pending_states.rb b/db/migrate/20201204141038_add_trace_bytesize_to_ci_build_pending_states.rb
deleted file mode 100644
index c866493e8d8..00000000000
--- a/db/migrate/20201204141038_add_trace_bytesize_to_ci_build_pending_states.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddTraceBytesizeToCiBuildPendingStates < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :ci_build_pending_states, :trace_bytesize, :bigint
- end
-end
diff --git a/db/migrate/20201204193952_keep_latest_artifact_project_level.rb b/db/migrate/20201204193952_keep_latest_artifact_project_level.rb
deleted file mode 100644
index 3fc9fad1dc6..00000000000
--- a/db/migrate/20201204193952_keep_latest_artifact_project_level.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class KeepLatestArtifactProjectLevel < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :project_ci_cd_settings, :keep_latest_artifact, :boolean, default: true, null: false
- end
- end
-
- def down
- with_lock_retries do
- remove_column :project_ci_cd_settings, :keep_latest_artifact
- end
- end
-end
diff --git a/db/migrate/20201204205814_add_member_events_to_web_hooks.rb b/db/migrate/20201204205814_add_member_events_to_web_hooks.rb
deleted file mode 100644
index edb374f1bdd..00000000000
--- a/db/migrate/20201204205814_add_member_events_to_web_hooks.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddMemberEventsToWebHooks < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :web_hooks, :member_events, :boolean, null: false, default: false
- end
-end
diff --git a/db/migrate/20201204215353_add_pull_mirror_interval_to_plan_limits.rb b/db/migrate/20201204215353_add_pull_mirror_interval_to_plan_limits.rb
deleted file mode 100644
index 3484e4c8afa..00000000000
--- a/db/migrate/20201204215353_add_pull_mirror_interval_to_plan_limits.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class AddPullMirrorIntervalToPlanLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- add_column :plan_limits, :pull_mirror_interval_seconds, :integer, default: 300, null: false
- end
-end
diff --git a/db/migrate/20201208081429_update_internal_ids_last_value_for_epics_renamed.rb b/db/migrate/20201208081429_update_internal_ids_last_value_for_epics_renamed.rb
deleted file mode 100644
index fadc365d53c..00000000000
--- a/db/migrate/20201208081429_update_internal_ids_last_value_for_epics_renamed.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateInternalIdsLastValueForEpicsRenamed < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- ApplicationRecord.connection.execute(<<-SQL.squish)
- UPDATE internal_ids
- SET last_value = epics_max_iids.maximum_iid
- FROM
- (
- SELECT
- MAX(epics.iid) AS maximum_iid,
- epics.group_id AS epics_group_id
- FROM epics
- GROUP BY epics.group_id
- ) epics_max_iids
- WHERE internal_ids.last_value < epics_max_iids.maximum_iid
- AND namespace_id = epics_max_iids.epics_group_id
- AND internal_ids.usage = 4
- SQL
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/migrate/20201208143911_add_approvals_created_at_index.rb b/db/migrate/20201208143911_add_approvals_created_at_index.rb
deleted file mode 100644
index cfec6b257c2..00000000000
--- a/db/migrate/20201208143911_add_approvals_created_at_index.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddApprovalsCreatedAtIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'index_approvals_on_merge_request_id_and_created_at'
-
- def up
- add_concurrent_index :approvals, [:merge_request_id, :created_at], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :approvals, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201208181411_remove_temporary_blocking_issues_index.rb b/db/migrate/20201208181411_remove_temporary_blocking_issues_index.rb
deleted file mode 100644
index ea63d2d1ed3..00000000000
--- a/db/migrate/20201208181411_remove_temporary_blocking_issues_index.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveTemporaryBlockingIssuesIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name(:issue_links, 'tmp_idx_blocking_type_links')
- remove_concurrent_index_by_name(:issue_links, 'tmp_idx_blocked_by_type_links')
- remove_concurrent_index_by_name(:issues, 'tmp_idx_index_issues_with_outdate_blocking_count')
- end
-
- def down
- add_concurrent_index :issue_links, [:source_id], where: 'link_type = 1', name: 'tmp_idx_blocking_type_links'
- add_concurrent_index :issue_links, [:target_id], where: 'link_type = 2', name: 'tmp_idx_blocked_by_type_links'
- add_concurrent_index :issues, :id, where: '(state_id = 1 AND blocking_issues_count = 0)', name: 'tmp_idx_index_issues_with_outdate_blocking_count'
- end
-end
diff --git a/db/migrate/20201208210209_create_incident_management_oncall_shifts.rb b/db/migrate/20201208210209_create_incident_management_oncall_shifts.rb
deleted file mode 100644
index 49cb32ffee0..00000000000
--- a/db/migrate/20201208210209_create_incident_management_oncall_shifts.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class CreateIncidentManagementOncallShifts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- unless table_exists?(:incident_management_oncall_shifts)
- with_lock_retries do
- create_table :incident_management_oncall_shifts do |t|
- t.references :rotation, null: false, foreign_key: { to_table: :incident_management_oncall_rotations, on_delete: :cascade }
- t.references :participant, null: false, foreign_key: { to_table: :incident_management_oncall_participants, on_delete: :cascade }
- t.datetime_with_timezone :starts_at, null: false
- t.datetime_with_timezone :ends_at, null: false
- end
-
- execute <<~SQL
- ALTER TABLE incident_management_oncall_shifts
- ADD CONSTRAINT inc_mgmnt_no_overlapping_oncall_shifts
- EXCLUDE USING gist
- ( rotation_id WITH =,
- tstzrange(starts_at, ends_at, '[)') WITH &&
- )
- SQL
- end
- end
- end
-
- def down
- with_lock_retries do
- drop_table :incident_management_oncall_shifts
- end
- end
-end
diff --git a/db/migrate/20201209154746_expand_ci_pipelines_index_on_ci_ref_id.rb b/db/migrate/20201209154746_expand_ci_pipelines_index_on_ci_ref_id.rb
deleted file mode 100644
index b88763a30f9..00000000000
--- a/db/migrate/20201209154746_expand_ci_pipelines_index_on_ci_ref_id.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class ExpandCiPipelinesIndexOnCiRefId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- NEW_NAME = 'index_ci_pipelines_on_ci_ref_id_and_more'
- OLD_NAME = 'index_ci_pipelines_on_ci_ref_id'
-
- def up
- add_concurrent_index :ci_pipelines, %i[ci_ref_id id source status], order: { id: :desc }, where: 'ci_ref_id IS NOT NULL', name: NEW_NAME
-
- remove_concurrent_index_by_name :ci_pipelines, OLD_NAME
- end
-
- def down
- add_concurrent_index :ci_pipelines, :ci_ref_id, where: 'ci_ref_id IS NOT NULL', name: OLD_NAME
-
- remove_concurrent_index_by_name :ci_pipelines, NEW_NAME
- end
-end
diff --git a/db/migrate/20201209163113_recreate_index_issue_email_participants_on_issue_id_and_email.rb b/db/migrate/20201209163113_recreate_index_issue_email_participants_on_issue_id_and_email.rb
deleted file mode 100644
index 9cbf68fd63a..00000000000
--- a/db/migrate/20201209163113_recreate_index_issue_email_participants_on_issue_id_and_email.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class RecreateIndexIssueEmailParticipantsOnIssueIdAndEmail < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- OLD_INDEX_NAME = 'index_issue_email_participants_on_issue_id_and_email'
- NEW_INDEX_NAME = 'index_issue_email_participants_on_issue_id_and_lower_email'
-
- def up
- # This table is currently empty, so no need to worry about unique index violations
- add_concurrent_index :issue_email_participants, 'issue_id, lower(email)', unique: true, name: NEW_INDEX_NAME
- remove_concurrent_index_by_name :issue_email_participants, OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :issue_email_participants, [:issue_id, :email], unique: true, name: OLD_INDEX_NAME
- remove_concurrent_index_by_name :issue_email_participants, NEW_INDEX_NAME
- end
-end
diff --git a/db/migrate/20201209163958_add_code_challenge_to_oauth_access_grants.rb b/db/migrate/20201209163958_add_code_challenge_to_oauth_access_grants.rb
deleted file mode 100644
index 48292cce55b..00000000000
--- a/db/migrate/20201209163958_add_code_challenge_to_oauth_access_grants.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class AddCodeChallengeToOauthAccessGrants < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_column(:oauth_access_grants, :code_challenge, :text, null: true) unless column_exists?(:oauth_access_grants, :code_challenge)
- # If `code_challenge_method` is 'plain' the length is at most 128 characters as per the spec
- # https://tools.ietf.org/html/rfc7636#section-4.1
- # Otherwise the max length of base64(SHA256(code_verifier)) is 44 characters
- add_text_limit(:oauth_access_grants, :code_challenge, 128, constraint_name: 'oauth_access_grants_code_challenge')
-
- add_column(:oauth_access_grants, :code_challenge_method, :text, null: true) unless column_exists?(:oauth_access_grants, :code_challenge_method)
- # Values are either 'plain' or 'S256'
- add_text_limit(:oauth_access_grants, :code_challenge_method, 5, constraint_name: 'oauth_access_grants_code_challenge_method')
- end
-
- def down
- remove_column(:oauth_access_grants, :code_challenge)
- remove_column(:oauth_access_grants, :code_challenge_method)
- end
-end
diff --git a/db/migrate/20201209193551_add_version_sha_cache_to_composer_metadata.rb b/db/migrate/20201209193551_add_version_sha_cache_to_composer_metadata.rb
deleted file mode 100644
index 62d0cdae8bc..00000000000
--- a/db/migrate/20201209193551_add_version_sha_cache_to_composer_metadata.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddVersionShaCacheToComposerMetadata < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- add_column :packages_composer_metadata, :version_cache_sha, :binary, null: true
- end
- end
-
- def down
- with_lock_retries do
- remove_column :packages_composer_metadata, :version_cache_sha, :binary
- end
- end
-end
diff --git a/db/migrate/20201210101250_add_index_projects_on_import_type_and_creator_id.rb b/db/migrate/20201210101250_add_index_projects_on_import_type_and_creator_id.rb
deleted file mode 100644
index 5eb8f1d658e..00000000000
--- a/db/migrate/20201210101250_add_index_projects_on_import_type_and_creator_id.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexProjectsOnImportTypeAndCreatorId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, [:creator_id, :import_type, :created_at],
- where: 'import_type IS NOT NULL',
- name: 'index_projects_on_creator_id_import_type_and_created_at_partial'
- end
-
- def down
- remove_concurrent_index_by_name :projects, 'index_projects_on_creator_id_import_type_and_created_at_partial'
- end
-end
diff --git a/db/migrate/20201210175044_add_index_to_snippet_on_project_id.rb b/db/migrate/20201210175044_add_index_to_snippet_on_project_id.rb
deleted file mode 100644
index 6de4a840409..00000000000
--- a/db/migrate/20201210175044_add_index_to_snippet_on_project_id.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToSnippetOnProjectId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- INDEX_NAME = "index_snippet_on_id_and_project_id"
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :snippets, [:id, :project_id], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :snippets, INDEX_NAME
- end
-end
diff --git a/db/migrate/20201211042306_add_deployments_finder_by_finished_at_index.rb b/db/migrate/20201211042306_add_deployments_finder_by_finished_at_index.rb
deleted file mode 100644
index f937ff7a436..00000000000
--- a/db/migrate/20201211042306_add_deployments_finder_by_finished_at_index.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class AddDeploymentsFinderByFinishedAtIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = "index_deployments_on_project_and_finished"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :deployments,
- [:project_id, :finished_at],
- where: 'status = 2',
- name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :deployments,
- [:project_id, :finished_at],
- where: 'status = 2',
- name: INDEX_NAME
- end
-end
diff --git a/db/migrate/20210629031900_associate_existing_dast_builds_with_variables.rb b/db/migrate/20210629031900_associate_existing_dast_builds_with_variables.rb
index 3d81db87143..5db39334550 100644
--- a/db/migrate/20210629031900_associate_existing_dast_builds_with_variables.rb
+++ b/db/migrate/20210629031900_associate_existing_dast_builds_with_variables.rb
@@ -20,7 +20,6 @@ class AssociateExistingDastBuildsWithVariables < ActiveRecord::Migration[6.1]
class Build < ApplicationRecord
self.table_name = 'ci_builds'
self.inheritance_column = :_type_disabled
- self.gitlab_schema = :gitlab_ci
default_scope { where(name: :dast, stage: :dast) } # rubocop:disable Cop/DefaultScope
end
diff --git a/db/migrate/20211004122540_create_member_tasks.rb b/db/migrate/20211004122540_create_member_tasks.rb
new file mode 100644
index 00000000000..e1141873bcb
--- /dev/null
+++ b/db/migrate/20211004122540_create_member_tasks.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class CreateMemberTasks < Gitlab::Database::Migration[1.0]
+ def change
+ create_table :member_tasks do |t|
+ t.references :member, index: true, null: false
+ t.references :project, index: true, null: false
+ t.timestamps_with_timezone null: false
+ t.integer :tasks, limit: 2, array: true, null: false, default: []
+ t.index [:member_id, :project_id], unique: true
+ end
+ end
+end
diff --git a/db/migrate/20211005112404_add_member_id_foreign_key_to_member_tasks.rb b/db/migrate/20211005112404_add_member_id_foreign_key_to_member_tasks.rb
new file mode 100644
index 00000000000..f3447918ad3
--- /dev/null
+++ b/db/migrate/20211005112404_add_member_id_foreign_key_to_member_tasks.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddMemberIdForeignKeyToMemberTasks < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :member_tasks, :members, column: :member_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :member_tasks, column: :member_id
+ end
+ end
+end
diff --git a/db/migrate/20211005112645_add_project_id_foreign_key_to_member_tasks.rb b/db/migrate/20211005112645_add_project_id_foreign_key_to_member_tasks.rb
new file mode 100644
index 00000000000..ead6bb88e60
--- /dev/null
+++ b/db/migrate/20211005112645_add_project_id_foreign_key_to_member_tasks.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddProjectIdForeignKeyToMemberTasks < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :member_tasks, :projects, column: :project_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :member_tasks, column: :project_id
+ end
+ end
+end
diff --git a/db/migrate/20211008193137_add_health_status_column_on_clusters_integration_prometheus.rb b/db/migrate/20211008193137_add_health_status_column_on_clusters_integration_prometheus.rb
new file mode 100644
index 00000000000..a69d12d4e52
--- /dev/null
+++ b/db/migrate/20211008193137_add_health_status_column_on_clusters_integration_prometheus.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+class AddHealthStatusColumnOnClustersIntegrationPrometheus < Gitlab::Database::Migration[1.0]
+ def change
+ # For now, health checks will only run on monitor demo projects
+ add_column :clusters_integration_prometheus, :health_status, :smallint, limit: 2, default: 0, null: false
+ end
+end
diff --git a/db/migrate/20211011004242_create_content_blocked_states.rb b/db/migrate/20211011004242_create_content_blocked_states.rb
new file mode 100644
index 00000000000..d70717f9786
--- /dev/null
+++ b/db/migrate/20211011004242_create_content_blocked_states.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class CreateContentBlockedStates < Gitlab::Database::Migration[1.0]
+ def change
+ create_table :content_blocked_states, comment: 'JiHu-specific table' do |t|
+ t.timestamps_with_timezone null: false
+ t.binary :commit_sha, null: false
+ t.binary :blob_sha, null: false
+ t.text :path, null: false, limit: 2048
+ t.text :container_identifier, null: false, limit: 255
+
+ t.index [:container_identifier, :commit_sha, :path], name: 'index_content_blocked_states_on_container_id_commit_sha_path', unique: true
+ end
+ end
+end
diff --git a/db/migrate/20211012015903_next_traversal_ids_sibling_function.rb b/db/migrate/20211012015903_next_traversal_ids_sibling_function.rb
new file mode 100644
index 00000000000..f32b8fc5a65
--- /dev/null
+++ b/db/migrate/20211012015903_next_traversal_ids_sibling_function.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class NextTraversalIdsSiblingFunction < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::SchemaHelpers
+
+ FUNCTION_NAME = 'next_traversal_ids_sibling'
+
+ def up
+ # Given array [1,2,3,4,5], concatenate the first part of the array [1,2,3,4]
+ # with the last element in the array (5) after being incremented ([6]).
+ #
+ # [1,2,3,4,5] => [1,2,3,4,6]
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION #{FUNCTION_NAME}(traversal_ids INT[]) RETURNS INT[]
+ AS $$
+ BEGIN
+ return traversal_ids[1:array_length(traversal_ids, 1)-1] ||
+ ARRAY[traversal_ids[array_length(traversal_ids, 1)]+1];
+ END;
+ $$
+ LANGUAGE plpgsql
+ IMMUTABLE
+ RETURNS NULL ON NULL INPUT;
+ SQL
+ end
+
+ def down
+ execute("DROP FUNCTION #{FUNCTION_NAME}(traversal_ids INT[])")
+ end
+end
diff --git a/db/migrate/20211012134316_clean_up_migrate_merge_request_diff_commit_users.rb b/db/migrate/20211012134316_clean_up_migrate_merge_request_diff_commit_users.rb
new file mode 100644
index 00000000000..443dbe37c0b
--- /dev/null
+++ b/db/migrate/20211012134316_clean_up_migrate_merge_request_diff_commit_users.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class CleanUpMigrateMergeRequestDiffCommitUsers < Gitlab::Database::Migration[1.0]
+ def up
+ jobs = Gitlab::Database::BackgroundMigrationJob
+ .for_migration_class('MigrateMergeRequestDiffCommitUsers')
+ .pending
+ .to_a
+
+ return if jobs.empty?
+
+ say("#{jobs.length} MigrateMergeRequestDiffCommitUsers are still pending")
+
+ # Normally we don't process background migrations in a regular migration, as
+ # this could take a while to complete and thus block a deployment.
+ #
+ # In this case the jobs have all been processed for GitLab.com at the time
+ # of writing. In addition, it's been a few releases since this migration was
+ # introduced. As a result, self-hosted instances should have their
+ # migrations finished a long time ago.
+ #
+ # For these reasons we clean up any pending jobs (just in case) before
+ # deploying the code. This also allows us to immediately start using the new
+ # setup only, instead of having to support both the old and new approach for
+ # at least one more release.
+ jobs.each do |job|
+ Gitlab::BackgroundMigration::MigrateMergeRequestDiffCommitUsers
+ .new
+ .perform(*job.arguments)
+ end
+ end
+
+ def down
+ end
+end
diff --git a/db/migrate/20211013014228_add_content_validation_endpoint_to_application_settings.rb b/db/migrate/20211013014228_add_content_validation_endpoint_to_application_settings.rb
new file mode 100644
index 00000000000..9a79fdca192
--- /dev/null
+++ b/db/migrate/20211013014228_add_content_validation_endpoint_to_application_settings.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddContentValidationEndpointToApplicationSettings < Gitlab::Database::Migration[1.0]
+ def up
+ # rubocop:disable Migration/AddLimitToTextColumns
+ add_column :application_settings, :content_validation_endpoint_url, :text, comment: 'JiHu-specific column'
+ # rubocop:disable Migration/AddLimitToTextColumns
+
+ add_column :application_settings, :encrypted_content_validation_api_key, :binary, comment: 'JiHu-specific column'
+ add_column :application_settings, :encrypted_content_validation_api_key_iv, :binary, comment: 'JiHu-specific column'
+ add_column :application_settings, :content_validation_endpoint_enabled, :boolean, null: false, default: false, comment: 'JiHu-specific column'
+ end
+
+ def down
+ remove_column :application_settings, :content_validation_endpoint_url
+ remove_column :application_settings, :encrypted_content_validation_api_key
+ remove_column :application_settings, :encrypted_content_validation_api_key_iv
+ remove_column :application_settings, :content_validation_endpoint_enabled
+ end
+end
diff --git a/db/migrate/20211013080714_add_network_to_user_credit_card_validations.rb b/db/migrate/20211013080714_add_network_to_user_credit_card_validations.rb
new file mode 100644
index 00000000000..eee4cbad796
--- /dev/null
+++ b/db/migrate/20211013080714_add_network_to_user_credit_card_validations.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddNetworkToUserCreditCardValidations < Gitlab::Database::Migration[1.0]
+ # rubocop:disable Migration/AddLimitToTextColumns
+ def change
+ add_column :user_credit_card_validations, :network, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20211013080715_limit_network_on_user_credit_card_validations.rb b/db/migrate/20211013080715_limit_network_on_user_credit_card_validations.rb
new file mode 100644
index 00000000000..38a019e718d
--- /dev/null
+++ b/db/migrate/20211013080715_limit_network_on_user_credit_card_validations.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class LimitNetworkOnUserCreditCardValidations < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :user_credit_card_validations, :network, 32
+ end
+
+ def down
+ remove_text_limit :user_credit_card_validations, :network
+ end
+end
diff --git a/db/migrate/20211013080716_index_include_network_on_user_credit_card_validations.rb b/db/migrate/20211013080716_index_include_network_on_user_credit_card_validations.rb
new file mode 100644
index 00000000000..849dbab77db
--- /dev/null
+++ b/db/migrate/20211013080716_index_include_network_on_user_credit_card_validations.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class IndexIncludeNetworkOnUserCreditCardValidations < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_user_credit_card_validations_meta_data_partial_match'
+
+ def up
+ add_concurrent_index :user_credit_card_validations,
+ [:expiration_date, :last_digits, :network, :credit_card_validated_at],
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :user_credit_card_validations, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211013192749_add_states_into_approval_project_rules.rb b/db/migrate/20211013192749_add_states_into_approval_project_rules.rb
new file mode 100644
index 00000000000..98fefbab12c
--- /dev/null
+++ b/db/migrate/20211013192749_add_states_into_approval_project_rules.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddStatesIntoApprovalProjectRules < Gitlab::Database::Migration[1.0]
+ def up
+ add_column :approval_project_rules, :vulnerability_states, :text, array: true, null: false, default: ['newly_detected']
+ end
+
+ def down
+ remove_column :approval_project_rules, :vulnerability_states
+ end
+end
diff --git a/db/migrate/20211015021114_add_merge_commit_template_to_project_settings.rb b/db/migrate/20211015021114_add_merge_commit_template_to_project_settings.rb
new file mode 100644
index 00000000000..adf2fdb2da7
--- /dev/null
+++ b/db/migrate/20211015021114_add_merge_commit_template_to_project_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddMergeCommitTemplateToProjectSettings < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ add_column :project_settings, :merge_commit_template, :text # rubocop:disable Migration/AddLimitToTextColumns
+ end
+end
diff --git a/db/migrate/20211015024135_add_merge_commit_template_limit_to_project_settings.rb b/db/migrate/20211015024135_add_merge_commit_template_limit_to_project_settings.rb
new file mode 100644
index 00000000000..972872b8d2a
--- /dev/null
+++ b/db/migrate/20211015024135_add_merge_commit_template_limit_to_project_settings.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddMergeCommitTemplateLimitToProjectSettings < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :project_settings, :merge_commit_template, 500
+ end
+
+ def down
+ remove_text_limit :project_settings, :merge_commit_template
+ end
+end
diff --git a/db/migrate/20211018101034_add_tmp_project_id_column_to_namespaces.rb b/db/migrate/20211018101034_add_tmp_project_id_column_to_namespaces.rb
new file mode 100644
index 00000000000..cc73cb5047b
--- /dev/null
+++ b/db/migrate/20211018101034_add_tmp_project_id_column_to_namespaces.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddTmpProjectIdColumnToNamespaces < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ # this is a temporary column to be able to batch insert records into namespaces table and then be able to link these
+ # to projects table.
+ add_column :namespaces, :tmp_project_id, :integer # rubocop: disable Migration/AddColumnsToWideTables
+ end
+end
diff --git a/db/migrate/20211018161447_fix_double_entries_in_postgres_index_view.rb b/db/migrate/20211018161447_fix_double_entries_in_postgres_index_view.rb
new file mode 100644
index 00000000000..574f54bc60e
--- /dev/null
+++ b/db/migrate/20211018161447_fix_double_entries_in_postgres_index_view.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+class FixDoubleEntriesInPostgresIndexView < Gitlab::Database::Migration[1.0]
+ def up
+ execute(<<~SQL)
+ DROP VIEW IF EXISTS postgres_indexes;
+
+ CREATE VIEW postgres_indexes AS
+ SELECT (pg_namespace.nspname::text || '.'::text) || i.relname::text AS identifier,
+ pg_index.indexrelid,
+ pg_namespace.nspname AS schema,
+ i.relname AS name,
+ pg_indexes.tablename,
+ a.amname AS type,
+ pg_index.indisunique AS "unique",
+ pg_index.indisvalid AS valid_index,
+ i.relispartition AS partitioned,
+ pg_index.indisexclusion AS exclusion,
+ pg_index.indexprs IS NOT NULL AS expression,
+ pg_index.indpred IS NOT NULL AS partial,
+ pg_indexes.indexdef AS definition,
+ pg_relation_size(i.oid::regclass) AS ondisk_size_bytes
+ FROM pg_index
+ JOIN pg_class i ON i.oid = pg_index.indexrelid
+ JOIN pg_namespace ON i.relnamespace = pg_namespace.oid
+ JOIN pg_indexes ON i.relname = pg_indexes.indexname AND pg_namespace.nspname = pg_indexes.schemaname
+ JOIN pg_am a ON i.relam = a.oid
+ WHERE pg_namespace.nspname <> 'pg_catalog'::name AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name]));
+ SQL
+ end
+
+ def down
+ execute(<<~SQL)
+ DROP VIEW IF EXISTS postgres_indexes;
+
+ CREATE VIEW postgres_indexes AS
+ SELECT (pg_namespace.nspname::text || '.'::text) || i.relname::text AS identifier,
+ pg_index.indexrelid,
+ pg_namespace.nspname AS schema,
+ i.relname AS name,
+ pg_indexes.tablename,
+ a.amname AS type,
+ pg_index.indisunique AS "unique",
+ pg_index.indisvalid AS valid_index,
+ i.relispartition AS partitioned,
+ pg_index.indisexclusion AS exclusion,
+ pg_index.indexprs IS NOT NULL AS expression,
+ pg_index.indpred IS NOT NULL AS partial,
+ pg_indexes.indexdef AS definition,
+ pg_relation_size(i.oid::regclass) AS ondisk_size_bytes
+ FROM pg_index
+ JOIN pg_class i ON i.oid = pg_index.indexrelid
+ JOIN pg_namespace ON i.relnamespace = pg_namespace.oid
+ JOIN pg_indexes ON i.relname = pg_indexes.indexname
+ JOIN pg_am a ON i.relam = a.oid
+ WHERE pg_namespace.nspname <> 'pg_catalog'::name AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name]));
+ SQL
+ end
+end
diff --git a/db/migrate/20211019153615_add_state_to_merge_request_assignees.rb b/db/migrate/20211019153615_add_state_to_merge_request_assignees.rb
new file mode 100644
index 00000000000..0eb8d0989a5
--- /dev/null
+++ b/db/migrate/20211019153615_add_state_to_merge_request_assignees.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+class AddStateToMergeRequestAssignees < Gitlab::Database::Migration[1.0]
+ REVIEW_DEFAULT_STATE = 0
+
+ def change
+ add_column :merge_request_assignees, :state, :smallint, default: REVIEW_DEFAULT_STATE, null: false
+ end
+end
diff --git a/db/migrate/20211020030948_add_runtime_runner_features_to_ci_builds_metadata.rb b/db/migrate/20211020030948_add_runtime_runner_features_to_ci_builds_metadata.rb
new file mode 100644
index 00000000000..970c018df46
--- /dev/null
+++ b/db/migrate/20211020030948_add_runtime_runner_features_to_ci_builds_metadata.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddRuntimeRunnerFeaturesToCiBuildsMetadata < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ add_column :ci_builds_metadata, :runtime_runner_features, :jsonb, default: {}, null: false
+ end
+end
diff --git a/db/migrate/20211020095357_add_group_traversal_id_index.rb b/db/migrate/20211020095357_add_group_traversal_id_index.rb
new file mode 100644
index 00000000000..e4739ff217e
--- /dev/null
+++ b/db/migrate/20211020095357_add_group_traversal_id_index.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddGroupTraversalIdIndex < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_namespaces_on_traversal_ids_for_groups'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :namespaces, :traversal_ids, using: :gin, where: "type='Group'", name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :namespaces, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211021125908_add_sentry_settings_to_application_settings.rb b/db/migrate/20211021125908_add_sentry_settings_to_application_settings.rb
new file mode 100644
index 00000000000..d8b40893b47
--- /dev/null
+++ b/db/migrate/20211021125908_add_sentry_settings_to_application_settings.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class AddSentrySettingsToApplicationSettings < Gitlab::Database::Migration[1.0]
+ # rubocop:disable Migration/AddLimitToTextColumns
+ def change
+ add_column :application_settings, :sentry_enabled, :boolean, default: false, null: false
+ add_column :application_settings, :sentry_dsn, :text
+ add_column :application_settings, :sentry_clientside_dsn, :text
+ add_column :application_settings, :sentry_environment, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20211021134458_add_limits_to_sentry_settings_on_application_settings.rb b/db/migrate/20211021134458_add_limits_to_sentry_settings_on_application_settings.rb
new file mode 100644
index 00000000000..34d18741788
--- /dev/null
+++ b/db/migrate/20211021134458_add_limits_to_sentry_settings_on_application_settings.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddLimitsToSentrySettingsOnApplicationSettings < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :application_settings, :sentry_dsn, 255
+ add_text_limit :application_settings, :sentry_clientside_dsn, 255
+ add_text_limit :application_settings, :sentry_environment, 255
+ end
+
+ def down
+ remove_text_limit :application_settings, :sentry_dsn
+ remove_text_limit :application_settings, :sentry_clientside_dsn
+ remove_text_limit :application_settings, :sentry_environment
+ end
+end
diff --git a/db/migrate/20211025103744_add_state_id_to_vsa_issue_stage_events.rb b/db/migrate/20211025103744_add_state_id_to_vsa_issue_stage_events.rb
new file mode 100644
index 00000000000..345cd1785ea
--- /dev/null
+++ b/db/migrate/20211025103744_add_state_id_to_vsa_issue_stage_events.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddStateIdToVsaIssueStageEvents < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :analytics_cycle_analytics_issue_stage_events, :state_id, :smallint, default: 1, null: false
+ end
+end
diff --git a/db/migrate/20211025103758_add_state_id_to_vsa_merge_request_stage_events.rb b/db/migrate/20211025103758_add_state_id_to_vsa_merge_request_stage_events.rb
new file mode 100644
index 00000000000..be28d56e19d
--- /dev/null
+++ b/db/migrate/20211025103758_add_state_id_to_vsa_merge_request_stage_events.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddStateIdToVsaMergeRequestStageEvents < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :analytics_cycle_analytics_merge_request_stage_events, :state_id, :smallint, default: 1, null: false
+ end
+end
diff --git a/db/migrate/20211026143238_remove_index_releases_on_author_id.rb b/db/migrate/20211026143238_remove_index_releases_on_author_id.rb
new file mode 100644
index 00000000000..7cd086dbf7d
--- /dev/null
+++ b/db/migrate/20211026143238_remove_index_releases_on_author_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoveIndexReleasesOnAuthorId < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_releases_on_author_id'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :releases, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :releases, [:author_id], name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211027203950_add_updated_index_for_dormant_users.rb b/db/migrate/20211027203950_add_updated_index_for_dormant_users.rb
new file mode 100644
index 00000000000..8b004af06c0
--- /dev/null
+++ b/db/migrate/20211027203950_add_updated_index_for_dormant_users.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddUpdatedIndexForDormantUsers < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_users_on_id_and_last_activity_on_for_active_human_service'
+
+ disable_ddl_transaction!
+
+ def up
+ index_condition = "state = 'active' AND (users.user_type IS NULL OR users.user_type = 4)"
+
+ add_concurrent_index :users, [:id, :last_activity_on], where: index_condition, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :users, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211028132247_create_packages_npm_metadata.rb b/db/migrate/20211028132247_create_packages_npm_metadata.rb
new file mode 100644
index 00000000000..cbe5429fca1
--- /dev/null
+++ b/db/migrate/20211028132247_create_packages_npm_metadata.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class CreatePackagesNpmMetadata < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ create_table :packages_npm_metadata, id: false do |t|
+ t.references :package, primary_key: true, default: nil, index: false, foreign_key: { to_table: :packages_packages, on_delete: :cascade }, type: :bigint
+ t.jsonb :package_json, default: {}, null: false
+
+ t.check_constraint 'char_length(package_json::text) < 20000'
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :packages_npm_metadata
+ end
+ end
+end
diff --git a/db/migrate/20211028212259_add_default_to_personal_access_tokens_prefix.rb b/db/migrate/20211028212259_add_default_to_personal_access_tokens_prefix.rb
new file mode 100644
index 00000000000..d9949863a92
--- /dev/null
+++ b/db/migrate/20211028212259_add_default_to_personal_access_tokens_prefix.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddDefaultToPersonalAccessTokensPrefix < Gitlab::Database::Migration[1.0]
+ def change
+ change_column_default(:application_settings, :personal_access_token_prefix, from: nil, to: 'glpat-')
+ end
+end
diff --git a/db/migrate/20211101132310_add_reindexing_queue.rb b/db/migrate/20211101132310_add_reindexing_queue.rb
new file mode 100644
index 00000000000..d9d1f9dce89
--- /dev/null
+++ b/db/migrate/20211101132310_add_reindexing_queue.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddReindexingQueue < Gitlab::Database::Migration[1.0]
+ def change
+ create_table :postgres_reindex_queued_actions do |t|
+ t.text :index_identifier, null: false, limit: 255
+ t.integer :state, limit: 2, null: false, default: 0
+ t.timestamps_with_timezone null: false
+
+ t.index :state
+ end
+
+ change_column_default :postgres_reindex_queued_actions, :created_at, from: nil, to: -> { 'NOW()' }
+ change_column_default :postgres_reindex_queued_actions, :updated_at, from: nil, to: -> { 'NOW()' }
+ end
+end
diff --git a/db/migrate/20211103062728_add_with_highest_role_minimal_access_to_users_statistics.rb b/db/migrate/20211103062728_add_with_highest_role_minimal_access_to_users_statistics.rb
new file mode 100644
index 00000000000..43cd7afbf06
--- /dev/null
+++ b/db/migrate/20211103062728_add_with_highest_role_minimal_access_to_users_statistics.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddWithHighestRoleMinimalAccessToUsersStatistics < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :users_statistics, :with_highest_role_minimal_access, :integer, null: false, default: 0
+ end
+end
diff --git a/db/migrate/20211104012209_add_text_limit_to_application_settings_content_validation_endpoint_url.rb b/db/migrate/20211104012209_add_text_limit_to_application_settings_content_validation_endpoint_url.rb
new file mode 100644
index 00000000000..4062fd1be01
--- /dev/null
+++ b/db/migrate/20211104012209_add_text_limit_to_application_settings_content_validation_endpoint_url.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddTextLimitToApplicationSettingsContentValidationEndpointUrl < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :application_settings, :content_validation_endpoint_url, 255
+ end
+
+ def down
+ remove_text_limit :application_settings, :content_validation_endpoint_url
+ end
+end
diff --git a/db/migrate/20211105010101_add_archived_column_to_deployments.rb b/db/migrate/20211105010101_add_archived_column_to_deployments.rb
new file mode 100644
index 00000000000..f9ac81915b4
--- /dev/null
+++ b/db/migrate/20211105010101_add_archived_column_to_deployments.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddArchivedColumnToDeployments < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ add_column :deployments, :archived, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20211105125756_add_read_at_to_dependency_proxy_manifests.rb b/db/migrate/20211105125756_add_read_at_to_dependency_proxy_manifests.rb
new file mode 100644
index 00000000000..a594674f470
--- /dev/null
+++ b/db/migrate/20211105125756_add_read_at_to_dependency_proxy_manifests.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddReadAtToDependencyProxyManifests < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :dependency_proxy_manifests, :read_at, :datetime_with_timezone, null: false, default: -> { 'NOW()' }
+ end
+end
diff --git a/db/migrate/20211105125813_add_read_at_to_dependency_proxy_blobs.rb b/db/migrate/20211105125813_add_read_at_to_dependency_proxy_blobs.rb
new file mode 100644
index 00000000000..1808a541498
--- /dev/null
+++ b/db/migrate/20211105125813_add_read_at_to_dependency_proxy_blobs.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddReadAtToDependencyProxyBlobs < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :dependency_proxy_blobs, :read_at, :datetime_with_timezone, null: false, default: -> { 'NOW()' }
+ end
+end
diff --git a/db/migrate/20211105160316_create_dotenv_application_limits.rb b/db/migrate/20211105160316_create_dotenv_application_limits.rb
new file mode 100644
index 00000000000..3ea94fd60fc
--- /dev/null
+++ b/db/migrate/20211105160316_create_dotenv_application_limits.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+class CreateDotenvApplicationLimits < Gitlab::Database::Migration[1.0]
+ def change
+ add_column(:plan_limits, :dotenv_variables, :integer, default: 20, null: false)
+ add_column(:plan_limits, :dotenv_size, :integer, default: 5.kilobytes, null: false)
+ end
+end
diff --git a/db/migrate/20211105161404_insert_dotenv_application_limits.rb b/db/migrate/20211105161404_insert_dotenv_application_limits.rb
new file mode 100644
index 00000000000..2749cf4a019
--- /dev/null
+++ b/db/migrate/20211105161404_insert_dotenv_application_limits.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class InsertDotenvApplicationLimits < Gitlab::Database::Migration[1.0]
+ def up
+ create_or_update_plan_limit('dotenv_variables', 'default', 150)
+ create_or_update_plan_limit('dotenv_variables', 'free', 50)
+ create_or_update_plan_limit('dotenv_variables', 'opensource', 150)
+ create_or_update_plan_limit('dotenv_variables', 'premium', 100)
+ create_or_update_plan_limit('dotenv_variables', 'premium_trial', 100)
+ create_or_update_plan_limit('dotenv_variables', 'ultimate', 150)
+ create_or_update_plan_limit('dotenv_variables', 'ultimate_trial', 150)
+
+ create_or_update_plan_limit('dotenv_size', 'default', 5.kilobytes)
+ end
+
+ def down
+ create_or_update_plan_limit('dotenv_variables', 'default', 20)
+ create_or_update_plan_limit('dotenv_variables', 'free', 20)
+ create_or_update_plan_limit('dotenv_variables', 'opensource', 20)
+ create_or_update_plan_limit('dotenv_variables', 'premium', 20)
+ create_or_update_plan_limit('dotenv_variables', 'premium_trial', 20)
+ create_or_update_plan_limit('dotenv_variables', 'ultimate', 20)
+ create_or_update_plan_limit('dotenv_variables', 'ultimate_trial', 20)
+
+ create_or_update_plan_limit('dotenv_size', 'default', 5.kilobytes)
+ end
+end
diff --git a/db/migrate/20211108154510_create_pipeline_triggers_application_limits.rb b/db/migrate/20211108154510_create_pipeline_triggers_application_limits.rb
new file mode 100644
index 00000000000..38671c75e0c
--- /dev/null
+++ b/db/migrate/20211108154510_create_pipeline_triggers_application_limits.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class CreatePipelineTriggersApplicationLimits < Gitlab::Database::Migration[1.0]
+ def change
+ add_column(:plan_limits, :pipeline_triggers, :integer, default: 25_000, null: false)
+ end
+end
diff --git a/db/migrate/20211108154841_insert_pipeline_triggers_application_limits.rb b/db/migrate/20211108154841_insert_pipeline_triggers_application_limits.rb
new file mode 100644
index 00000000000..c1341fad729
--- /dev/null
+++ b/db/migrate/20211108154841_insert_pipeline_triggers_application_limits.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class InsertPipelineTriggersApplicationLimits < Gitlab::Database::Migration[1.0]
+ def up
+ create_or_update_plan_limit('pipeline_triggers', 'default', 0)
+ create_or_update_plan_limit('pipeline_triggers', 'free', 25_000)
+ create_or_update_plan_limit('pipeline_triggers', 'opensource', 0)
+ create_or_update_plan_limit('pipeline_triggers', 'premium', 0)
+ create_or_update_plan_limit('pipeline_triggers', 'premium_trial', 0)
+ create_or_update_plan_limit('pipeline_triggers', 'ultimate', 0)
+ create_or_update_plan_limit('pipeline_triggers', 'ultimate_trial', 0)
+ end
+
+ def down
+ create_or_update_plan_limit('pipeline_triggers', 'default', 0)
+ create_or_update_plan_limit('pipeline_triggers', 'free', 0)
+ create_or_update_plan_limit('pipeline_triggers', 'opensource', 0)
+ create_or_update_plan_limit('pipeline_triggers', 'premium', 0)
+ create_or_update_plan_limit('pipeline_triggers', 'premium_trial', 0)
+ create_or_update_plan_limit('pipeline_triggers', 'ultimate', 0)
+ create_or_update_plan_limit('pipeline_triggers', 'ultimate_trial', 0)
+ end
+end
diff --git a/db/migrate/20211108203248_update_dependency_proxy_indexes_with_read_at.rb b/db/migrate/20211108203248_update_dependency_proxy_indexes_with_read_at.rb
new file mode 100644
index 00000000000..ac0f0ddca17
--- /dev/null
+++ b/db/migrate/20211108203248_update_dependency_proxy_indexes_with_read_at.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class UpdateDependencyProxyIndexesWithReadAt < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ NEW_BLOB_INDEX = 'index_dependency_proxy_blobs_on_group_id_status_read_at_id'
+ OLD_BLOB_INDEX = 'index_dependency_proxy_blobs_on_group_id_status_and_id'
+
+ NEW_MANIFEST_INDEX = 'index_dependency_proxy_manifests_on_group_id_status_read_at_id'
+ OLD_MANIFEST_INDEX = 'index_dependency_proxy_manifests_on_group_id_status_and_id'
+
+ def up
+ add_concurrent_index :dependency_proxy_blobs, [:group_id, :status, :read_at, :id], name: NEW_BLOB_INDEX
+ add_concurrent_index :dependency_proxy_manifests, [:group_id, :status, :read_at, :id], name: NEW_MANIFEST_INDEX
+
+ remove_concurrent_index_by_name :dependency_proxy_blobs, OLD_BLOB_INDEX
+ remove_concurrent_index_by_name :dependency_proxy_manifests, OLD_MANIFEST_INDEX
+ end
+
+ def down
+ add_concurrent_index :dependency_proxy_blobs, [:group_id, :status, :id], name: OLD_BLOB_INDEX
+ add_concurrent_index :dependency_proxy_manifests, [:group_id, :status, :id], name: OLD_MANIFEST_INDEX
+
+ remove_concurrent_index_by_name :dependency_proxy_blobs, NEW_BLOB_INDEX
+ remove_concurrent_index_by_name :dependency_proxy_manifests, NEW_MANIFEST_INDEX
+ end
+end
diff --git a/db/migrate/20211108211434_remove_index_for_resource_group.rb b/db/migrate/20211108211434_remove_index_for_resource_group.rb
new file mode 100644
index 00000000000..8b03f12d08b
--- /dev/null
+++ b/db/migrate/20211108211434_remove_index_for_resource_group.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveIndexForResourceGroup < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_for_resource_group'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :ci_builds, INDEX_NAME
+ end
+
+ def down
+ # rubocop:disable Migration/PreventIndexCreation
+ add_concurrent_index :ci_builds, [:resource_group_id, :id], where: 'resource_group_id IS NOT NULL', name: INDEX_NAME
+ # rubocop:enable Migration/PreventIndexCreation
+ end
+end
diff --git a/db/migrate/20211109100050_add_consume_after_to_loose_fk_deleted_records.rb b/db/migrate/20211109100050_add_consume_after_to_loose_fk_deleted_records.rb
new file mode 100644
index 00000000000..6b8e8c0d4f3
--- /dev/null
+++ b/db/migrate/20211109100050_add_consume_after_to_loose_fk_deleted_records.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddConsumeAfterToLooseFkDeletedRecords < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def up
+ add_column :loose_foreign_keys_deleted_records, :consume_after, :datetime_with_timezone, default: -> { 'NOW()' }
+ end
+
+ def down
+ remove_column :loose_foreign_keys_deleted_records, :consume_after
+ end
+end
diff --git a/db/migrate/20211109101010_support_partition_query_in_loose_fk_table.rb b/db/migrate/20211109101010_support_partition_query_in_loose_fk_table.rb
new file mode 100644
index 00000000000..fccb1fc5cac
--- /dev/null
+++ b/db/migrate/20211109101010_support_partition_query_in_loose_fk_table.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class SupportPartitionQueryInLooseFkTable < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_loose_foreign_keys_deleted_records_for_partitioned_query'
+
+ def up
+ add_concurrent_partitioned_index :loose_foreign_keys_deleted_records,
+ %I[partition fully_qualified_table_name consume_after id],
+ where: 'status = 1',
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_partitioned_index_by_name :loose_foreign_keys_deleted_records, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211110010101_add_index_on_unarchived_deployments.rb b/db/migrate/20211110010101_add_index_on_unarchived_deployments.rb
new file mode 100644
index 00000000000..0bfafb94d0b
--- /dev/null
+++ b/db/migrate/20211110010101_add_index_on_unarchived_deployments.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexOnUnarchivedDeployments < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_deployments_on_archived_project_id_iid'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :deployments, %i[archived project_id iid], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :deployments, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211110100050_add_has_shimo_to_project_settings.rb b/db/migrate/20211110100050_add_has_shimo_to_project_settings.rb
new file mode 100644
index 00000000000..01507908e0f
--- /dev/null
+++ b/db/migrate/20211110100050_add_has_shimo_to_project_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddHasShimoToProjectSettings < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ add_column :project_settings, :has_shimo, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20211112155416_populate_default_value_for_personal_access_tokens_prefix.rb b/db/migrate/20211112155416_populate_default_value_for_personal_access_tokens_prefix.rb
new file mode 100644
index 00000000000..8dd23e1a72e
--- /dev/null
+++ b/db/migrate/20211112155416_populate_default_value_for_personal_access_tokens_prefix.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class PopulateDefaultValueForPersonalAccessTokensPrefix < Gitlab::Database::Migration[1.0]
+ def up
+ execute(
+ <<-SQL
+ UPDATE
+ application_settings
+ SET
+ personal_access_token_prefix = default
+ WHERE
+ personal_access_token_prefix IS NULL
+ SQL
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20200106071113_update_fingerprint_sha256_within_keys.rb b/db/post_migrate/20200106071113_update_fingerprint_sha256_within_keys.rb
deleted file mode 100644
index 06f5c881006..00000000000
--- a/db/post_migrate/20200106071113_update_fingerprint_sha256_within_keys.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateFingerprintSha256WithinKeys < ActiveRecord::Migration[5.0]
- include Gitlab::Database::MigrationHelpers
-
- class Key < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'keys'
- self.inheritance_column = :_type_disabled
- end
-
- disable_ddl_transaction!
-
- def up
- queue_background_migration_jobs_by_range_at_intervals(Key, 'MigrateFingerprintSha256WithinKeys', 5.minutes)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200110121314_schedule_update_existing_subgroup_to_match_visibility_level_of_parent.rb b/db/post_migrate/20200110121314_schedule_update_existing_subgroup_to_match_visibility_level_of_parent.rb
deleted file mode 100644
index 813cd600ddc..00000000000
--- a/db/post_migrate/20200110121314_schedule_update_existing_subgroup_to_match_visibility_level_of_parent.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class ScheduleUpdateExistingSubgroupToMatchVisibilityLevelOfParent < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- MIGRATION = 'UpdateExistingSubgroupToMatchVisibilityLevelOfParent'
- DELAY_INTERVAL = 5.minutes.to_i
- BATCH_SIZE = 1000
- VISIBILITY_LEVELS = {
- internal: 10,
- private: 0
- }
-
- disable_ddl_transaction!
-
- def up
- offset = update_groups(VISIBILITY_LEVELS[:internal])
- update_groups(VISIBILITY_LEVELS[:private], offset: offset)
- end
-
- def down
- # no-op
- end
-
- private
-
- def update_groups(level, offset: 0)
- groups = exec_query <<~SQL
- SELECT id
- FROM namespaces
- WHERE visibility_level = #{level}
- AND type = 'Group'
- AND EXISTS (SELECT 1
- FROM namespaces AS children
- WHERE children.parent_id = namespaces.id)
- SQL
-
- ids = groups.rows.flatten
-
- iterator = 1
-
- ids.in_groups_of(BATCH_SIZE, false) do |batch_of_ids|
- delay = DELAY_INTERVAL * (iterator + offset)
- BackgroundMigrationWorker.perform_in(delay, MIGRATION, [batch_of_ids, level])
- iterator += 1
- end
-
- say("Background jobs for visibility level #{level} scheduled in #{iterator} iterations")
-
- offset + iterator
- end
-end
diff --git a/db/post_migrate/20200113151354_remove_creations_in_gitlab_subscription_histories.rb b/db/post_migrate/20200113151354_remove_creations_in_gitlab_subscription_histories.rb
deleted file mode 100644
index 39ca5124b32..00000000000
--- a/db/post_migrate/20200113151354_remove_creations_in_gitlab_subscription_histories.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveCreationsInGitlabSubscriptionHistories < ActiveRecord::Migration[5.2]
- DOWNTIME = false
- GITLAB_SUBSCRIPTION_CREATED = 0
-
- def up
- return unless Gitlab.com?
-
- delete_sql = "DELETE FROM gitlab_subscription_histories WHERE change_type=#{GITLAB_SUBSCRIPTION_CREATED} RETURNING *"
-
- records = execute(delete_sql)
-
- logger = Gitlab::BackgroundMigration::Logger.build
- records.to_a.each do |record|
- logger.info record.as_json.merge(message: "gitlab_subscription_histories with change_type=0 was deleted")
- end
- end
-
- def down
- # There's no way to restore, and the data is useless
- # all the data to be deleted in case needed https://gitlab.com/gitlab-org/gitlab/uploads/7409379b0ed658624f5d33202b5668a1/gitlab_subscription_histories_change_type_0.sql.txt
- end
-end
diff --git a/db/post_migrate/20200114112932_add_temporary_partial_index_on_project_id_to_services.rb b/db/post_migrate/20200114112932_add_temporary_partial_index_on_project_id_to_services.rb
deleted file mode 100644
index 55494f1e4ac..00000000000
--- a/db/post_migrate/20200114112932_add_temporary_partial_index_on_project_id_to_services.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddTemporaryPartialIndexOnProjectIdToServices < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'tmp_index_on_project_id_partial_with_prometheus_services'
- PARTIAL_FILTER = "type = 'PrometheusService'"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :services, :project_id, where: PARTIAL_FILTER, name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :services, :project_id, where: PARTIAL_FILTER, name: INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200114113341_patch_prometheus_services_for_shared_cluster_applications.rb b/db/post_migrate/20200114113341_patch_prometheus_services_for_shared_cluster_applications.rb
deleted file mode 100644
index d49bd10887c..00000000000
--- a/db/post_migrate/20200114113341_patch_prometheus_services_for_shared_cluster_applications.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class PatchPrometheusServicesForSharedClusterApplications < ActiveRecord::Migration[5.2]
- def up
- # no-op
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200117194850_backfill_operations_feature_flags_iid.rb b/db/post_migrate/20200117194850_backfill_operations_feature_flags_iid.rb
deleted file mode 100644
index bc97bd6062d..00000000000
--- a/db/post_migrate/20200117194850_backfill_operations_feature_flags_iid.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillOperationsFeatureFlagsIid < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- ###
- # This should update about 700 rows on gitlab.com
- # Execution time is predicted to take less than a second based on #database-lab results
- # https://gitlab.com/gitlab-org/gitlab/merge_requests/22175#migration-performance
- ###
- def up
- execute('LOCK operations_feature_flags IN ACCESS EXCLUSIVE MODE')
-
- backfill_iids('operations_feature_flags')
-
- change_column_null :operations_feature_flags, :iid, false
- end
-
- def down
- change_column_null :operations_feature_flags, :iid, true
- end
-end
diff --git a/db/post_migrate/20200117194900_delete_internal_ids_where_feature_flags_usage.rb b/db/post_migrate/20200117194900_delete_internal_ids_where_feature_flags_usage.rb
deleted file mode 100644
index 0cf1ab03622..00000000000
--- a/db/post_migrate/20200117194900_delete_internal_ids_where_feature_flags_usage.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class DeleteInternalIdsWhereFeatureFlagsUsage < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- sql = <<~SQL
- DELETE FROM internal_ids WHERE usage = 6
- SQL
-
- execute(sql)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200120083607_remove_storage_version_column_from_snippets.rb b/db/post_migrate/20200120083607_remove_storage_version_column_from_snippets.rb
deleted file mode 100644
index 62bb3f46cae..00000000000
--- a/db/post_migrate/20200120083607_remove_storage_version_column_from_snippets.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class RemoveStorageVersionColumnFromSnippets < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- return unless column_exists?(:snippets, :storage_version)
-
- remove_column :snippets, :storage_version
- end
-
- def down
- return if column_exists?(:snippets, :storage_version)
-
- add_column_with_default( # rubocop:disable Migration/AddColumnWithDefault
- :snippets,
- :storage_version,
- :integer,
- default: 2,
- allow_null: false
- )
- end
-end
diff --git a/db/post_migrate/20200122123016_backfill_project_settings.rb b/db/post_migrate/20200122123016_backfill_project_settings.rb
deleted file mode 100644
index 80ca79e979e..00000000000
--- a/db/post_migrate/20200122123016_backfill_project_settings.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillProjectSettings < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- MIGRATION = 'BackfillProjectSettings'
- DELAY_INTERVAL = 2.minutes
- BATCH_SIZE = 10_000
-
- disable_ddl_transaction!
-
- class Project < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'projects'
- end
-
- def up
- say "Scheduling `#{MIGRATION}` jobs"
-
- queue_background_migration_jobs_by_range_at_intervals(Project, MIGRATION, DELAY_INTERVAL, batch_size: BATCH_SIZE)
- end
-
- def down
- # NOOP
- end
-end
diff --git a/db/post_migrate/20200122144759_drop_kibana_column.rb b/db/post_migrate/20200122144759_drop_kibana_column.rb
deleted file mode 100644
index ce94ca2dc27..00000000000
--- a/db/post_migrate/20200122144759_drop_kibana_column.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class DropKibanaColumn < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- remove_column :clusters_applications_elastic_stacks, :kibana_hostname, :string, limit: 255
- end
-end
diff --git a/db/post_migrate/20200123155929_remove_invalid_jira_data.rb b/db/post_migrate/20200123155929_remove_invalid_jira_data.rb
deleted file mode 100644
index 7ddac15c3fb..00000000000
--- a/db/post_migrate/20200123155929_remove_invalid_jira_data.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class RemoveInvalidJiraData < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- sql = "DELETE FROM jira_tracker_data WHERE \
- (length(encrypted_api_url) > 0 AND encrypted_api_url_iv IS NULL) \
- OR (length(encrypted_url) > 0 AND encrypted_url_iv IS NULL) \
- OR (length(encrypted_username) > 0 AND encrypted_username_iv IS NULL) \
- OR (length(encrypted_password) > 0 AND encrypted_password_iv IS NULL)"
-
- execute(sql)
- end
-
- def down
- # We need to figure out why migrating data to jira_tracker_data table
- # failed and then can recreate the data
- end
-end
diff --git a/db/post_migrate/20200124110831_migrate_design_notes_mentions_to_db.rb b/db/post_migrate/20200124110831_migrate_design_notes_mentions_to_db.rb
deleted file mode 100644
index f1e4ee9807b..00000000000
--- a/db/post_migrate/20200124110831_migrate_design_notes_mentions_to_db.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateDesignNotesMentionsToDb < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- DELAY = 2.minutes.to_i
- BATCH_SIZE = 10000
- MIGRATION = 'UserMentions::CreateResourceUserMention'
-
- INDEX_NAME = 'design_mentions_temp_index'
- INDEX_CONDITION = "note LIKE '%@%'::text AND notes.noteable_type = 'DesignManagement::Design'"
- QUERY_CONDITIONS = "#{INDEX_CONDITION} AND design_user_mentions.design_id IS NULL"
- JOIN = 'INNER JOIN design_management_designs ON design_management_designs.id = notes.noteable_id LEFT JOIN design_user_mentions ON notes.id = design_user_mentions.note_id'
-
- class DesignUserMention < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'design_user_mentions'
- end
-
- class Note < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'notes'
- end
-
- def up
- return unless Gitlab.ee?
-
- # cleanup design user mentions with no actual mentions,
- # re https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24586#note_285982468
- DesignUserMention
- .where(mentioned_users_ids: nil)
- .where(mentioned_groups_ids: nil)
- .where(mentioned_projects_ids: nil)
- .each_batch(of: BATCH_SIZE) do |batch|
- batch.delete_all
- end
-
- # create temporary index for notes with mentions, may take well over 1h
- add_concurrent_index(:notes, :id, where: INDEX_CONDITION, name: INDEX_NAME)
-
- Note
- .joins(JOIN)
- .where(QUERY_CONDITIONS)
- .each_batch(of: BATCH_SIZE) do |batch, index|
- range = batch.pluck(Arel.sql('MIN(notes.id)'), Arel.sql('MAX(notes.id)')).first
- BackgroundMigrationWorker.perform_in(index * DELAY, MIGRATION, ['DesignManagement::Design', JOIN, QUERY_CONDITIONS, true, *range])
- end
- end
-
- def down
- # no-op
- # temporary index is to be dropped in a different migration in an upcoming release:
- # https://gitlab.com/gitlab-org/gitlab/issues/196842
- end
-end
diff --git a/db/post_migrate/20200127090233_remove_invalid_issue_tracker_data.rb b/db/post_migrate/20200127090233_remove_invalid_issue_tracker_data.rb
deleted file mode 100644
index 6d64dd3d0d1..00000000000
--- a/db/post_migrate/20200127090233_remove_invalid_issue_tracker_data.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class RemoveInvalidIssueTrackerData < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- sql = "DELETE FROM issue_tracker_data WHERE \
- (length(encrypted_issues_url) > 0 AND encrypted_issues_url_iv IS NULL) \
- OR (length(encrypted_new_issue_url) > 0 AND encrypted_new_issue_url_iv IS NULL) \
- OR (length(encrypted_project_url) > 0 AND encrypted_project_url_iv IS NULL)"
-
- execute(sql)
- end
-
- def down
- # We need to figure out why migrating data to issue_tracker_data table
- # failed and then can recreate the data
- end
-end
diff --git a/db/post_migrate/20200127111840_fix_projects_without_project_feature.rb b/db/post_migrate/20200127111840_fix_projects_without_project_feature.rb
deleted file mode 100644
index 66e892444d1..00000000000
--- a/db/post_migrate/20200127111840_fix_projects_without_project_feature.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class FixProjectsWithoutProjectFeature < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- BATCH_SIZE = 50_000
- MIGRATION = 'FixProjectsWithoutProjectFeature'
-
- disable_ddl_transaction!
-
- class Project < ActiveRecord::Base
- include EachBatch
- end
-
- def up
- queue_background_migration_jobs_by_range_at_intervals(Project, MIGRATION, 2.minutes, batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200128132510_add_temporary_index_for_notes_with_mentions.rb b/db/post_migrate/20200128132510_add_temporary_index_for_notes_with_mentions.rb
deleted file mode 100644
index bd55485f871..00000000000
--- a/db/post_migrate/20200128132510_add_temporary_index_for_notes_with_mentions.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class AddTemporaryIndexForNotesWithMentions < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- INDEX_CONDITION = "note LIKE '%@%'::text"
- INDEX_NAME = 'note_mentions_temp_index'
-
- EPIC_MENTIONS_INDEX_NAME = 'epic_mentions_temp_index'
- DESIGN_MENTIONS_INDEX_NAME = 'design_mentions_temp_index'
-
- def up
- # create temporary index for notes with mentions, may take well over 1h
- add_concurrent_index(:notes, [:id, :noteable_type], where: INDEX_CONDITION, name: INDEX_NAME)
-
- # cleanup previous temporary indexes, as we'll be usig the single one
- remove_concurrent_index(:notes, :id, name: EPIC_MENTIONS_INDEX_NAME)
- remove_concurrent_index(:notes, :id, name: DESIGN_MENTIONS_INDEX_NAME)
- end
-
- def down
- remove_concurrent_index(:notes, :id, name: INDEX_NAME)
-
- add_concurrent_index(:notes, :id, where: "#{INDEX_CONDITION} AND noteable_type='Epic'", name: EPIC_MENTIONS_INDEX_NAME)
- add_concurrent_index(:notes, :id, where: "#{INDEX_CONDITION} AND noteable_type='DesignManagement::Design'", name: DESIGN_MENTIONS_INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200128133510_cleanup_empty_commit_user_mentions.rb b/db/post_migrate/20200128133510_cleanup_empty_commit_user_mentions.rb
deleted file mode 100644
index 362aa3a60f7..00000000000
--- a/db/post_migrate/20200128133510_cleanup_empty_commit_user_mentions.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupEmptyCommitUserMentions < ActiveRecord::Migration[5.2]
- DOWNTIME = false
- BATCH_SIZE = 10_000
-
- class CommitUserMention < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'commit_user_mentions'
- end
-
- def up
- # cleanup commit user mentions with no actual mentions,
- # re https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24586#note_285982468
- CommitUserMention
- .where(mentioned_users_ids: nil)
- .where(mentioned_groups_ids: nil)
- .where(mentioned_projects_ids: nil)
- .each_batch(of: BATCH_SIZE) do |batch|
- batch.delete_all
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200128134110_migrate_commit_notes_mentions_to_db.rb b/db/post_migrate/20200128134110_migrate_commit_notes_mentions_to_db.rb
deleted file mode 100644
index 5b8ed99fb7a..00000000000
--- a/db/post_migrate/20200128134110_migrate_commit_notes_mentions_to_db.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateCommitNotesMentionsToDb < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
- DELAY = 3.minutes.to_i
- BATCH_SIZE = 1_000
- MIGRATION = 'UserMentions::CreateResourceUserMention'
-
- QUERY_CONDITIONS = "note LIKE '%@%'::text AND notes.noteable_type = 'Commit' AND commit_user_mentions.commit_id IS NULL"
- JOIN = 'LEFT JOIN commit_user_mentions ON notes.id = commit_user_mentions.note_id'
-
- class Note < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'notes'
- end
-
- def up
- Note
- .joins(JOIN)
- .where(QUERY_CONDITIONS)
- .each_batch(of: BATCH_SIZE) do |batch, index|
- range = batch.pluck(Arel.sql('MIN(notes.id)'), Arel.sql('MAX(notes.id)')).first
- migrate_in(index * DELAY, MIGRATION, ['Commit', JOIN, QUERY_CONDITIONS, true, *range])
- end
- end
-
- def down
- # no-op
- # temporary index is to be dropped in a different migration in an upcoming release:
- # https://gitlab.com/gitlab-org/gitlab/issues/196842
- end
-end
diff --git a/db/post_migrate/20200128210353_cleanup_optimistic_locking_nulls.rb b/db/post_migrate/20200128210353_cleanup_optimistic_locking_nulls.rb
deleted file mode 100644
index 5c172159561..00000000000
--- a/db/post_migrate/20200128210353_cleanup_optimistic_locking_nulls.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class CleanupOptimisticLockingNulls < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- TABLES = %w(epics merge_requests issues).freeze
- BATCH_SIZE = 10_000
-
- def declare_class(table)
- Class.new(ActiveRecord::Base) do
- include EachBatch
-
- self.table_name = table
- self.inheritance_column = :_type_disabled # Disable STI
- end
- end
-
- def up
- TABLES.each do |table|
- add_concurrent_index table.to_sym, :lock_version, where: "lock_version IS NULL"
-
- queue_background_migration_jobs_by_range_at_intervals(
- declare_class(table).where(lock_version: nil),
- 'CleanupOptimisticLockingNulls',
- 2.minutes,
- batch_size: BATCH_SIZE,
- other_job_arguments: [table]
- )
- end
- end
-
- def down
- TABLES.each do |table|
- remove_concurrent_index table.to_sym, :lock_version, where: "lock_version IS NULL"
- end
- end
-end
diff --git a/db/post_migrate/20200129035708_cleanup_rename_pages_domains_domain_type_to_scope.rb b/db/post_migrate/20200129035708_cleanup_rename_pages_domains_domain_type_to_scope.rb
deleted file mode 100644
index d1d2b4962dd..00000000000
--- a/db/post_migrate/20200129035708_cleanup_rename_pages_domains_domain_type_to_scope.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupRenamePagesDomainsDomainTypeToScope < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- cleanup_concurrent_column_rename :pages_domains, :domain_type, :scope
- end
-
- def down
- undo_cleanup_concurrent_column_rename :pages_domains, :domain_type, :scope
- end
-end
diff --git a/db/post_migrate/20200130145430_reschedule_migrate_issue_trackers_data.rb b/db/post_migrate/20200130145430_reschedule_migrate_issue_trackers_data.rb
deleted file mode 100644
index 312a8c95b92..00000000000
--- a/db/post_migrate/20200130145430_reschedule_migrate_issue_trackers_data.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-class RescheduleMigrateIssueTrackersData < ActiveRecord::Migration[5.1]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INTERVAL = 3.minutes.to_i
- BATCH_SIZE = 5_000
- MIGRATION = 'MigrateIssueTrackersSensitiveData'
-
- disable_ddl_transaction!
-
- class Service < ActiveRecord::Base
- self.table_name = 'services'
- self.inheritance_column = :_type_disabled
-
- include ::EachBatch
- end
-
- def up
- relation = Service.where(category: 'issue_tracker').where("properties IS NOT NULL AND properties != '{}' AND properties != ''")
- queue_background_migration_jobs_by_range_at_intervals(relation,
- MIGRATION,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- remove_issue_tracker_data_sql = "DELETE FROM issue_tracker_data WHERE \
- (length(encrypted_issues_url) > 0 AND encrypted_issues_url_iv IS NULL) \
- OR (length(encrypted_new_issue_url) > 0 AND encrypted_new_issue_url_iv IS NULL) \
- OR (length(encrypted_project_url) > 0 AND encrypted_project_url_iv IS NULL)"
-
- execute(remove_issue_tracker_data_sql)
-
- remove_jira_tracker_data_sql = "DELETE FROM jira_tracker_data WHERE \
- (length(encrypted_api_url) > 0 AND encrypted_api_url_iv IS NULL) \
- OR (length(encrypted_url) > 0 AND encrypted_url_iv IS NULL) \
- OR (length(encrypted_username) > 0 AND encrypted_username_iv IS NULL) \
- OR (length(encrypted_password) > 0 AND encrypted_password_iv IS NULL)"
-
- execute(remove_jira_tracker_data_sql)
- end
-end
diff --git a/db/post_migrate/20200203104214_services_remove_temporary_index_on_project_id.rb b/db/post_migrate/20200203104214_services_remove_temporary_index_on_project_id.rb
deleted file mode 100644
index c9566d0256c..00000000000
--- a/db/post_migrate/20200203104214_services_remove_temporary_index_on_project_id.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class ServicesRemoveTemporaryIndexOnProjectId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'tmp_index_on_project_id_partial_with_prometheus_services'
- PARTIAL_FILTER = "type = 'PrometheusService'"
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index :services, :project_id, where: PARTIAL_FILTER, name: INDEX_NAME
- end
-
- def down
- add_concurrent_index :services, :project_id, where: PARTIAL_FILTER, name: INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200204113223_schedule_recalculate_project_authorizations.rb b/db/post_migrate/20200204113223_schedule_recalculate_project_authorizations.rb
deleted file mode 100644
index 83b58300115..00000000000
--- a/db/post_migrate/20200204113223_schedule_recalculate_project_authorizations.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleRecalculateProjectAuthorizations < ActiveRecord::Migration[5.1]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- MIGRATION = 'RecalculateProjectAuthorizations'
- BATCH_SIZE = 2_500
- DELAY_INTERVAL = 2.minutes.to_i
-
- disable_ddl_transaction!
-
- class Namespace < ActiveRecord::Base
- include ::EachBatch
-
- self.table_name = 'namespaces'
- end
-
- class ProjectAuthorization < ActiveRecord::Base
- include ::EachBatch
-
- self.table_name = 'project_authorizations'
- end
-
- def up
- say "Scheduling #{MIGRATION} jobs"
-
- max_group_id = Namespace.where(type: 'Group').maximum(:id)
- project_authorizations = ProjectAuthorization.where('project_id <= ?', max_group_id)
- .select(:user_id)
- .distinct
-
- project_authorizations.each_batch(of: BATCH_SIZE, column: :user_id) do |authorizations, index|
- delay = index * DELAY_INTERVAL
- user_ids = authorizations.map(&:user_id)
- BackgroundMigrationWorker.perform_in(delay, MIGRATION, [user_ids])
- end
- end
-
- def down
- end
-end
diff --git a/db/post_migrate/20200204113224_schedule_recalculate_project_authorizations_second_run.rb b/db/post_migrate/20200204113224_schedule_recalculate_project_authorizations_second_run.rb
deleted file mode 100644
index 8f4a347b5e2..00000000000
--- a/db/post_migrate/20200204113224_schedule_recalculate_project_authorizations_second_run.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleRecalculateProjectAuthorizationsSecondRun < ActiveRecord::Migration[5.1]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- MIGRATION = 'RecalculateProjectAuthorizationsWithMinMaxUserId'
- BATCH_SIZE = 2_500
- DELAY_INTERVAL = 2.minutes.to_i
-
- disable_ddl_transaction!
-
- class User < ActiveRecord::Base
- include ::EachBatch
-
- self.table_name = 'users'
- end
-
- def up
- say "Scheduling #{MIGRATION} jobs"
-
- User.each_batch(of: BATCH_SIZE) do |batch, index|
- delay = index * DELAY_INTERVAL
- range = batch.pluck('MIN(id)', 'MAX(id)').first
- BackgroundMigrationWorker.perform_in(delay, MIGRATION, range)
- end
- end
-
- def down
- end
-end
diff --git a/db/post_migrate/20200204113225_schedule_recalculate_project_authorizations_third_run.rb b/db/post_migrate/20200204113225_schedule_recalculate_project_authorizations_third_run.rb
deleted file mode 100644
index 47b22b4800a..00000000000
--- a/db/post_migrate/20200204113225_schedule_recalculate_project_authorizations_third_run.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleRecalculateProjectAuthorizationsThirdRun < ActiveRecord::Migration[5.1]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- MIGRATION = 'RecalculateProjectAuthorizationsWithMinMaxUserId'
- BATCH_SIZE = 2_500
- DELAY_INTERVAL = 2.minutes.to_i
-
- disable_ddl_transaction!
-
- class User < ActiveRecord::Base
- include ::EachBatch
-
- self.table_name = 'users'
- end
-
- def up
- say "Scheduling #{MIGRATION} jobs"
-
- queue_background_migration_jobs_by_range_at_intervals(User, MIGRATION, DELAY_INTERVAL, batch_size: BATCH_SIZE)
- end
-
- def down
- end
-end
diff --git a/db/post_migrate/20200206091544_migrate_create_commit_signature_worker_sidekiq_queue.rb b/db/post_migrate/20200206091544_migrate_create_commit_signature_worker_sidekiq_queue.rb
deleted file mode 100644
index eec9abf4a31..00000000000
--- a/db/post_migrate/20200206091544_migrate_create_commit_signature_worker_sidekiq_queue.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateCreateCommitSignatureWorkerSidekiqQueue < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- sidekiq_queue_migrate 'create_gpg_signature', to: 'create_commit_signature'
- end
-
- def down
- sidekiq_queue_migrate 'create_commit_signature', to: 'create_gpg_signature'
- end
-end
diff --git a/db/post_migrate/20200206135203_udpate_index_ci_builds_on_name_for_security_products.rb b/db/post_migrate/20200206135203_udpate_index_ci_builds_on_name_for_security_products.rb
deleted file mode 100644
index ddaa3049543..00000000000
--- a/db/post_migrate/20200206135203_udpate_index_ci_builds_on_name_for_security_products.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class UdpateIndexCiBuildsOnNameForSecurityProducts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_ci_builds_on_name_for_security_products_values'
- INDEX_NAME_NEW = 'index_ci_builds_on_name_for_security_reports_values'
- INITIAL_INDEX = "((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:ci_builds,
- :name,
- name: INDEX_NAME_NEW,
- where: INITIAL_INDEX + ", ('license_scanning'::character varying)::text]))")
-
- remove_concurrent_index_by_name(:ci_builds, INDEX_NAME)
- end
-
- def down
- add_concurrent_index(:ci_builds,
- :name,
- name: INDEX_NAME,
- where: INITIAL_INDEX + ']))')
-
- remove_concurrent_index_by_name(:ci_builds, INDEX_NAME_NEW)
- end
-end
diff --git a/db/post_migrate/20200207184023_add_temporary_index_to_promotion_notes.rb b/db/post_migrate/20200207184023_add_temporary_index_to_promotion_notes.rb
deleted file mode 100644
index 44a32938483..00000000000
--- a/db/post_migrate/20200207184023_add_temporary_index_to_promotion_notes.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class AddTemporaryIndexToPromotionNotes < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :notes,
- :note,
- where: "noteable_type = 'Issue' AND system IS TRUE AND note LIKE 'promoted to epic%'",
- name: 'tmp_idx_on_promoted_notes'
- end
-
- def down
- # NO OP
- end
-end
diff --git a/db/post_migrate/20200207185149_schedule_fix_orphan_promoted_issues.rb b/db/post_migrate/20200207185149_schedule_fix_orphan_promoted_issues.rb
deleted file mode 100644
index d25d6ed2dc7..00000000000
--- a/db/post_migrate/20200207185149_schedule_fix_orphan_promoted_issues.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleFixOrphanPromotedIssues < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- BATCH_SIZE = 100
- BACKGROUND_MIGRATION = 'FixOrphanPromotedIssues'
-
- disable_ddl_transaction!
-
- class Note < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'notes'
-
- scope :of_promotion, -> do
- where(noteable_type: 'Issue')
- .where('notes.system IS TRUE')
- .where("notes.note LIKE 'promoted to epic%'")
- end
- end
-
- def up
- Note.of_promotion.each_batch(of: BATCH_SIZE) do |notes, index|
- jobs = notes.map { |note| [BACKGROUND_MIGRATION, [note.id]] }
-
- BackgroundMigrationWorker.bulk_perform_async(jobs)
- end
- end
-
- def down
- # NO OP
- end
-end
diff --git a/db/post_migrate/20200210062432_schedule_link_lfs_objects.rb b/db/post_migrate/20200210062432_schedule_link_lfs_objects.rb
deleted file mode 100644
index b401065dd94..00000000000
--- a/db/post_migrate/20200210062432_schedule_link_lfs_objects.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleLinkLfsObjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- # no-op as background migration being schedule times out in some instances
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200210092405_save_instance_administrators_group_id.rb b/db/post_migrate/20200210092405_save_instance_administrators_group_id.rb
deleted file mode 100644
index e539a187672..00000000000
--- a/db/post_migrate/20200210092405_save_instance_administrators_group_id.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-class SaveInstanceAdministratorsGroupId < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute(
- <<-SQL
- UPDATE
- application_settings
- SET
- instance_administrators_group_id = (
- SELECT
- namespace_id
- FROM
- projects
- WHERE
- id = application_settings.instance_administration_project_id
- )
- WHERE
- instance_administrators_group_id IS NULL
- AND
- instance_administration_project_id IS NOT NULL
- AND
- ID in (
- SELECT
- max(id)
- FROM
- application_settings
- )
- SQL
- )
- end
-
- def down
- # no-op
-
- # The change performed by `up` cannot be reversed because once the migration runs,
- # we do not know what value application_settings.instance_administrators_group_id
- # had before the migration was run.
- end
-end
diff --git a/db/post_migrate/20200211152410_remove_instance_from_services.rb b/db/post_migrate/20200211152410_remove_instance_from_services.rb
deleted file mode 100644
index 1f27455b541..00000000000
--- a/db/post_migrate/20200211152410_remove_instance_from_services.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveInstanceFromServices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- return unless column_exists?(:services, :instance)
-
- undo_rename_column_concurrently :services, :template, :instance
- end
-
- def down
- # This migration should not be rolled back because it
- # removes a column that got added in migrations that
- # have been reverted in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24857
- end
-end
diff --git a/db/post_migrate/20200211155000_cleanup_empty_merge_request_mentions.rb b/db/post_migrate/20200211155000_cleanup_empty_merge_request_mentions.rb
deleted file mode 100644
index e90d192388b..00000000000
--- a/db/post_migrate/20200211155000_cleanup_empty_merge_request_mentions.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupEmptyMergeRequestMentions < ActiveRecord::Migration[5.2]
- DOWNTIME = false
- BATCH_SIZE = 1_000
-
- class MergeRequestUserMention < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'merge_request_user_mentions'
- end
-
- def up
- # cleanup merge request user mentions with no actual mentions,
- # re https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24586#note_285982468
- MergeRequestUserMention
- .where(mentioned_users_ids: nil)
- .where(mentioned_groups_ids: nil)
- .where(mentioned_projects_ids: nil).each_batch(of: BATCH_SIZE) do |batch|
- batch.delete_all
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200211155100_add_temporary_merge_request_with_mentions_index.rb b/db/post_migrate/20200211155100_add_temporary_merge_request_with_mentions_index.rb
deleted file mode 100644
index 5b25f29d5f7..00000000000
--- a/db/post_migrate/20200211155100_add_temporary_merge_request_with_mentions_index.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddTemporaryMergeRequestWithMentionsIndex < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_CONDITION = "description like '%@%' OR title like '%@%'"
- INDEX_NAME = 'merge_request_mentions_temp_index'
-
- disable_ddl_transaction!
-
- def up
- # create temporary index for notes with mentions, may take well over 1h
- add_concurrent_index(:merge_requests, :id, where: INDEX_CONDITION, name: INDEX_NAME)
- end
-
- def down
- remove_concurrent_index(:merge_requests, :id, where: INDEX_CONDITION, name: INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200211155539_migrate_merge_request_mentions_to_db.rb b/db/post_migrate/20200211155539_migrate_merge_request_mentions_to_db.rb
deleted file mode 100644
index b622badb561..00000000000
--- a/db/post_migrate/20200211155539_migrate_merge_request_mentions_to_db.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateMergeRequestMentionsToDb < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- DELAY = 3.minutes.to_i
- BATCH_SIZE = 1_000
- MIGRATION = 'UserMentions::CreateResourceUserMention'
-
- JOIN = "LEFT JOIN merge_request_user_mentions on merge_requests.id = merge_request_user_mentions.merge_request_id"
- QUERY_CONDITIONS = "(description like '%@%' OR title like '%@%') AND merge_request_user_mentions.merge_request_id IS NULL"
-
- disable_ddl_transaction!
-
- class MergeRequest < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'merge_requests'
- end
-
- def up
- MergeRequest
- .joins(JOIN)
- .where(QUERY_CONDITIONS)
- .each_batch(of: BATCH_SIZE) do |batch, index|
- range = batch.pluck(Arel.sql('MIN(merge_requests.id)'), Arel.sql('MAX(merge_requests.id)')).first
- migrate_in(index * DELAY, MIGRATION, ['MergeRequest', JOIN, QUERY_CONDITIONS, false, *range])
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200212052620_readd_template_column_to_services.rb b/db/post_migrate/20200212052620_readd_template_column_to_services.rb
deleted file mode 100644
index c636cb0a07b..00000000000
--- a/db/post_migrate/20200212052620_readd_template_column_to_services.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class ReaddTemplateColumnToServices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # rubocop:disable Migration/UpdateLargeTable
- def up
- return if column_exists? :services, :template
-
- # The migration to drop the template column never actually shipped
- # to production, so we should be okay to re-add it without worrying
- # about doing a data migration. If we needed to restore the value
- # of `template`, we would look for entries with `project_id IS NULL`.
- add_column_with_default :services, :template, :boolean, default: false, allow_null: true # rubocop:disable Migration/AddColumnWithDefault
- end
- # rubocop:enable Migration/UpdateLargeTable
-
- def down
- # NOP since the column is expected to exist
- end
-end
diff --git a/db/post_migrate/20200213204737_remove_unnecessary_milestone_join_tables.rb b/db/post_migrate/20200213204737_remove_unnecessary_milestone_join_tables.rb
deleted file mode 100644
index 19b3af53836..00000000000
--- a/db/post_migrate/20200213204737_remove_unnecessary_milestone_join_tables.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class RemoveUnnecessaryMilestoneJoinTables < ActiveRecord::Migration[6.0]
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- def up
- drop_table :issue_milestones
- drop_table :merge_request_milestones
- end
-
- def down
- create_table :issue_milestones, id: false do |t|
- t.references :issue, foreign_key: { on_delete: :cascade }, index: { unique: true }, null: false
- t.references :milestone, foreign_key: { on_delete: :cascade }, index: true, null: false
- end
-
- add_index :issue_milestones, [:issue_id, :milestone_id], unique: true
-
- create_table :merge_request_milestones, id: false do |t|
- t.references :merge_request, foreign_key: { on_delete: :cascade }, index: { unique: true }, null: false
- t.references :milestone, foreign_key: { on_delete: :cascade }, index: true, null: false
- end
-
- add_index :merge_request_milestones, [:merge_request_id, :milestone_id], name: 'index_mrs_milestones_on_mr_id_and_milestone_id', unique: true
- end
-end
diff --git a/db/post_migrate/20200213220159_migrate_store_security_reports_sidekiq_queue.rb b/db/post_migrate/20200213220159_migrate_store_security_reports_sidekiq_queue.rb
deleted file mode 100644
index 5bba4c95328..00000000000
--- a/db/post_migrate/20200213220159_migrate_store_security_reports_sidekiq_queue.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateStoreSecurityReportsSidekiqQueue < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- sidekiq_queue_migrate 'pipeline_default:store_security_reports', to: 'security_scans:store_security_reports'
- end
-
- def down
- sidekiq_queue_migrate 'security_scans:store_security_reports', to: 'pipeline_default:store_security_reports'
- end
-end
diff --git a/db/post_migrate/20200213220211_migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue.rb b/db/post_migrate/20200213220211_migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue.rb
deleted file mode 100644
index e3ed4c60f21..00000000000
--- a/db/post_migrate/20200213220211_migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateSyncSecurityReportsToReportApprovalRulesSidekiqQueue < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- sidekiq_queue_migrate 'pipeline_default:sync_security_reports_to_report_approval_rules',
- to: 'security_scans:sync_security_reports_to_report_approval_rules'
- end
-
- def down
- sidekiq_queue_migrate 'security_scans:sync_security_reports_to_report_approval_rules',
- to: 'pipeline_default:sync_security_reports_to_report_approval_rules'
- end
-end
diff --git a/db/post_migrate/20200214034836_remove_security_dashboard_feature_flag.rb b/db/post_migrate/20200214034836_remove_security_dashboard_feature_flag.rb
deleted file mode 100644
index 79723619533..00000000000
--- a/db/post_migrate/20200214034836_remove_security_dashboard_feature_flag.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveSecurityDashboardFeatureFlag < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- class FeatureGate < ApplicationRecord
- self.table_name = 'feature_gates'
- end
-
- def up
- FeatureGate.find_by(feature_key: :security_dashboard, key: :boolean)&.delete
- end
-
- def down
- instance_security_dashboard_feature = FeatureGate.find_by(feature_key: :instance_security_dashboard, key: :boolean)
-
- if instance_security_dashboard_feature.present?
- FeatureGate.safe_find_or_create_by!(
- feature_key: :security_dashboard,
- key: instance_security_dashboard_feature.key,
- value: instance_security_dashboard_feature.value
- )
- end
- end
-end
diff --git a/db/post_migrate/20200214214934_create_environment_for_self_monitoring_project.rb b/db/post_migrate/20200214214934_create_environment_for_self_monitoring_project.rb
deleted file mode 100644
index a44efa3c460..00000000000
--- a/db/post_migrate/20200214214934_create_environment_for_self_monitoring_project.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class CreateEnvironmentForSelfMonitoringProject < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute <<~SQL
- INSERT INTO environments (project_id, name, slug, created_at, updated_at)
- SELECT instance_administration_project_id, 'production', 'production', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
- FROM application_settings
- WHERE instance_administration_project_id IS NOT NULL
- AND NOT EXISTS (
- SELECT 1
- FROM environments
- INNER JOIN application_settings
- ON application_settings.instance_administration_project_id = environments.project_id
- )
- SQL
- end
-
- def down
- # no-op
-
- # This migration cannot be reversed because it cannot be ensured that the environment for the Self Monitoring Project
- # did not already exist before the migration ran - in that case, the migration does nothing, and it would be unexpected
- # behavior for that environment to be deleted by reversing this migration.
- end
-end
diff --git a/db/post_migrate/20200217210353_cleanup_optimistic_locking_nulls_pt2.rb b/db/post_migrate/20200217210353_cleanup_optimistic_locking_nulls_pt2.rb
deleted file mode 100644
index 1ec3e817e8e..00000000000
--- a/db/post_migrate/20200217210353_cleanup_optimistic_locking_nulls_pt2.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupOptimisticLockingNullsPt2 < ActiveRecord::Migration[5.2]
- def change
- # no-op: the MR that contained this migration was reverted
- end
-end
diff --git a/db/post_migrate/20200217223651_add_index_to_job_artifact_secure_reports.rb b/db/post_migrate/20200217223651_add_index_to_job_artifact_secure_reports.rb
deleted file mode 100644
index ca297272f8e..00000000000
--- a/db/post_migrate/20200217223651_add_index_to_job_artifact_secure_reports.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToJobArtifactSecureReports < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'job_artifacts_secure_reports_temp_index'
- PARTIAL_FILTER = "file_type BETWEEN 5 AND 8"
-
- disable_ddl_transaction!
-
- def up
- # This is a temporary index used for the migration of Security Reports to Security Scans
- add_concurrent_index(:ci_job_artifacts,
- [:id, :file_type, :job_id, :created_at, :updated_at],
- name: INDEX_NAME,
- where: PARTIAL_FILTER)
- end
-
- def down
- remove_concurrent_index(:ci_job_artifacts,
- [:id, :file_type, :job_id, :created_at, :updated_at])
- end
-end
diff --git a/db/post_migrate/20200217225719_schedule_migrate_security_scans.rb b/db/post_migrate/20200217225719_schedule_migrate_security_scans.rb
deleted file mode 100644
index 087c189f9fd..00000000000
--- a/db/post_migrate/20200217225719_schedule_migrate_security_scans.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleMigrateSecurityScans < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 10_000
- MIGRATION = 'MigrateSecurityScans'
-
- disable_ddl_transaction!
-
- class JobArtifact < ActiveRecord::Base
- include ::EachBatch
-
- self.table_name = 'ci_job_artifacts'
-
- scope :security_reports, -> { where('file_type BETWEEN 5 and 8') }
- end
-
- def up
- queue_background_migration_jobs_by_range_at_intervals(JobArtifact.security_reports,
- MIGRATION,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- # intentionally blank
- end
-end
diff --git a/db/post_migrate/20200219183456_remove_issue_state_indexes.rb b/db/post_migrate/20200219183456_remove_issue_state_indexes.rb
deleted file mode 100644
index cdf10b8172e..00000000000
--- a/db/post_migrate/20200219183456_remove_issue_state_indexes.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIssueStateIndexes < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # issues state column is ignored since 12.6 and will be removed on a following migration
- def up
- remove_concurrent_index_by_name :issues, 'index_issues_on_state'
- remove_concurrent_index_by_name :issues, 'index_issues_on_project_id_and_created_at_and_id_and_state'
- remove_concurrent_index_by_name :issues, 'idx_issues_on_project_id_and_due_date_and_id_and_state_partial'
- remove_concurrent_index_by_name :issues, 'index_issues_on_project_id_and_rel_position_and_state_and_id'
- remove_concurrent_index_by_name :issues, 'index_issues_on_project_id_and_updated_at_and_id_and_state'
- end
-
- def down
- add_concurrent_index :issues, :state, name: 'index_issues_on_state'
-
- add_concurrent_index :issues,
- [:project_id, :created_at, :id, :state],
- name: 'index_issues_on_project_id_and_created_at_and_id_and_state'
-
- add_concurrent_index :issues,
- [:project_id, :due_date, :id, :state],
- where: 'due_date IS NOT NULL',
- name: 'idx_issues_on_project_id_and_due_date_and_id_and_state_partial'
-
- add_concurrent_index :issues,
- [:project_id, :relative_position, :state, :id],
- order: { id: :desc },
- name: 'index_issues_on_project_id_and_rel_position_and_state_and_id'
-
- add_concurrent_index :issues,
- [:project_id, :updated_at, :id, :state],
- name: 'index_issues_on_project_id_and_updated_at_and_id_and_state'
- end
-end
diff --git a/db/post_migrate/20200219184219_remove_merge_request_state_indexes.rb b/db/post_migrate/20200219184219_remove_merge_request_state_indexes.rb
deleted file mode 100644
index deb95acc1cf..00000000000
--- a/db/post_migrate/20200219184219_remove_merge_request_state_indexes.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveMergeRequestStateIndexes < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # merge_requests state column is ignored since 12.6 and will be removed on a following migration
- def up
- remove_concurrent_index_by_name :merge_requests, 'index_merge_requests_on_id_and_merge_jid'
- remove_concurrent_index_by_name :merge_requests, 'index_merge_requests_on_source_project_and_branch_state_opened'
- remove_concurrent_index_by_name :merge_requests, 'index_merge_requests_on_state_and_merge_status'
- remove_concurrent_index_by_name :merge_requests, 'index_merge_requests_on_target_project_id_and_iid_opened'
- end
-
- def down
- add_concurrent_index :merge_requests,
- [:id, :merge_jid],
- where: "merge_jid IS NOT NULL and state = 'locked'",
- name: 'index_merge_requests_on_id_and_merge_jid'
-
- add_concurrent_index :merge_requests,
- [:source_project_id, :source_branch],
- where: "state = 'opened'",
- name: 'index_merge_requests_on_source_project_and_branch_state_opened'
-
- add_concurrent_index :merge_requests,
- [:state, :merge_status],
- where: "state = 'opened' AND merge_status = 'can_be_merged'",
- name: 'index_merge_requests_on_state_and_merge_status'
-
- add_concurrent_index :merge_requests,
- [:target_project_id, :iid],
- where: "state = 'opened'",
- name: 'index_merge_requests_on_target_project_id_and_iid_opened'
- end
-end
diff --git a/db/post_migrate/20200219193058_remove_state_from_issues.rb b/db/post_migrate/20200219193058_remove_state_from_issues.rb
deleted file mode 100644
index 007ba600ce7..00000000000
--- a/db/post_migrate/20200219193058_remove_state_from_issues.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveStateFromIssues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- return unless issue_state_column_exists?
-
- # Ignored in 12.6 - https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19574
- with_lock_retries do
- remove_column :issues, :state, :string
- end
- end
-
- def down
- return if issue_state_column_exists?
-
- with_lock_retries do
- add_column :issues, :state, :string
- end
- end
-
- private
-
- def issue_state_column_exists?
- column_exists?(:issues, :state)
- end
-end
diff --git a/db/post_migrate/20200219193117_remove_state_from_merge_requests.rb b/db/post_migrate/20200219193117_remove_state_from_merge_requests.rb
deleted file mode 100644
index 384a694b549..00000000000
--- a/db/post_migrate/20200219193117_remove_state_from_merge_requests.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveStateFromMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- return unless merge_requests_state_column_exists?
-
- # Ignored in 12.6 - https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19574
- with_lock_retries do
- remove_column :merge_requests, :state, :string
- end
- end
-
- def down
- return if merge_requests_state_column_exists?
-
- with_lock_retries do
- add_column :merge_requests, :state, :string
- end
- end
-
- private
-
- def merge_requests_state_column_exists?
- column_exists?(:merge_requests, :state)
- end
-end
diff --git a/db/post_migrate/20200220115023_fix_projects_without_prometheus_service.rb b/db/post_migrate/20200220115023_fix_projects_without_prometheus_service.rb
deleted file mode 100644
index 274a392a52a..00000000000
--- a/db/post_migrate/20200220115023_fix_projects_without_prometheus_service.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class FixProjectsWithoutPrometheusService < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- BATCH_SIZE = 50_000
- MIGRATION = 'FixProjectsWithoutPrometheusService'
-
- disable_ddl_transaction!
-
- class Project < ActiveRecord::Base
- include EachBatch
- end
-
- def up
- queue_background_migration_jobs_by_range_at_intervals(Project, MIGRATION, 2.minutes, batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200221142216_remove_repository_storage_from_snippets.rb b/db/post_migrate/20200221142216_remove_repository_storage_from_snippets.rb
deleted file mode 100644
index f9ef985218b..00000000000
--- a/db/post_migrate/20200221142216_remove_repository_storage_from_snippets.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveRepositoryStorageFromSnippets < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- return unless column_exists?(:snippets, :repository_storage)
-
- remove_column :snippets, :repository_storage
- end
-
- def down
- return if column_exists?(:snippets, :repository_storage)
-
- add_column_with_default( # rubocop:disable Migration/AddColumnWithDefault
- :snippets,
- :repository_storage,
- :string,
- default: 'default',
- limit: 255,
- allow_null: false
- )
- end
-end
diff --git a/db/post_migrate/20200226124757_remove_health_status_from_epics.rb b/db/post_migrate/20200226124757_remove_health_status_from_epics.rb
deleted file mode 100644
index e59edbacd2b..00000000000
--- a/db/post_migrate/20200226124757_remove_health_status_from_epics.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveHealthStatusFromEpics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- remove_column :epics, :health_status
- end
- end
-
- def down
- with_lock_retries do
- add_column :epics, :health_status, :integer, limit: 2
- end
- end
-end
diff --git a/db/post_migrate/20200226162239_cleanup_closed_at_rename_in_vulnerabilities.rb b/db/post_migrate/20200226162239_cleanup_closed_at_rename_in_vulnerabilities.rb
deleted file mode 100644
index eb7df0b8d22..00000000000
--- a/db/post_migrate/20200226162239_cleanup_closed_at_rename_in_vulnerabilities.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupClosedAtRenameInVulnerabilities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- cleanup_concurrent_column_rename :vulnerabilities, :closed_at, :dismissed_at
- end
-
- def down
- undo_cleanup_concurrent_column_rename :vulnerabilities, :closed_at, :dismissed_at
- end
-end
diff --git a/db/post_migrate/20200226162723_cleanup_closed_by_rename_in_vulnerabilities.rb b/db/post_migrate/20200226162723_cleanup_closed_by_rename_in_vulnerabilities.rb
deleted file mode 100644
index 4aa3568db14..00000000000
--- a/db/post_migrate/20200226162723_cleanup_closed_by_rename_in_vulnerabilities.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupClosedByRenameInVulnerabilities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- cleanup_concurrent_column_rename :vulnerabilities, :closed_by_id, :dismissed_by_id
- end
-
- def down
- undo_cleanup_concurrent_column_rename :vulnerabilities, :closed_by_id, :dismissed_by_id
- end
-end
diff --git a/db/post_migrate/20200227140242_update_occurrence_severity_column.rb b/db/post_migrate/20200227140242_update_occurrence_severity_column.rb
deleted file mode 100644
index 6d250532383..00000000000
--- a/db/post_migrate/20200227140242_update_occurrence_severity_column.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateOccurrenceSeverityColumn < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
- BATCH_SIZE = 1_000
- INTERVAL = 5.minutes
-
- # 23_044 records to be updated on GitLab.com,
- def up
- # create temporary index for undefined vulnerabilities
- add_concurrent_index(:vulnerability_occurrences, :id, where: 'severity = 0', name: 'undefined_vulnerabilities')
-
- return unless Gitlab.ee?
-
- migration = Gitlab::BackgroundMigration::RemoveUndefinedOccurrenceSeverityLevel
- migration_name = migration.to_s.demodulize
- relation = migration::Occurrence.undefined_severity
- queue_background_migration_jobs_by_range_at_intervals(relation,
- migration_name,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- # temporary index is to be dropped in a different migration in an upcoming release
- remove_concurrent_index(:vulnerability_occurrences, :id, where: 'severity = 0', name: 'undefined_vulnerabilities')
- # This migration can not be reversed because we can not know which records had undefined severity
- end
-end
diff --git a/db/post_migrate/20200302142052_update_vulnerability_severity_column.rb b/db/post_migrate/20200302142052_update_vulnerability_severity_column.rb
deleted file mode 100644
index fa38569f35d..00000000000
--- a/db/post_migrate/20200302142052_update_vulnerability_severity_column.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateVulnerabilitySeverityColumn < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
- BATCH_SIZE = 1_000
- INTERVAL = 2.minutes
-
- def up
- # create temporary index for undefined vulnerabilities
- add_concurrent_index(:vulnerabilities, :id, where: 'severity = 0', name: 'undefined_vulnerability')
-
- return unless Gitlab.ee?
-
- migration = Gitlab::BackgroundMigration::RemoveUndefinedVulnerabilitySeverityLevel
- migration_name = migration.to_s.demodulize
- relation = migration::Vulnerability.undefined_severity
- queue_background_migration_jobs_by_range_at_intervals(relation,
- migration_name,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- # This migration can not be reversed because we can not know which records had undefined severity
- end
-end
diff --git a/db/post_migrate/20200304211738_remove_file_type_from_packages_package_files.rb b/db/post_migrate/20200304211738_remove_file_type_from_packages_package_files.rb
deleted file mode 100644
index 98bce8845ab..00000000000
--- a/db/post_migrate/20200304211738_remove_file_type_from_packages_package_files.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveFileTypeFromPackagesPackageFiles < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- remove_column :packages_package_files, :file_type, :integer
- end
-end
diff --git a/db/post_migrate/20200305082754_remove_duplicate_labels_from_project.rb b/db/post_migrate/20200305082754_remove_duplicate_labels_from_project.rb
deleted file mode 100644
index f7df9f28187..00000000000
--- a/db/post_migrate/20200305082754_remove_duplicate_labels_from_project.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveDuplicateLabelsFromProject < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- CREATE = 1
- RENAME = 2
-
- disable_ddl_transaction!
-
- class BackupLabel < Label
- self.inheritance_column = :_type_disabled
-
- self.table_name = 'backup_labels'
- end
-
- class Label < ApplicationRecord
- self.table_name = 'labels'
- end
-
- class Project < ApplicationRecord
- include EachBatch
-
- self.table_name = 'projects'
- end
-
- BATCH_SIZE = 100_000
-
- def up
- # Split to smaller chunks
- # Loop rather than background job, every 100,000
- # there are 45,000,000 projects in total
- Project.each_batch(of: BATCH_SIZE) do |batch|
- range = batch.pluck('MIN(id)', 'MAX(id)').first
-
- transaction do
- remove_full_duplicates(*range)
- end
-
- transaction do
- rename_partial_duplicates(*range)
- end
- end
- end
-
- def down
- Project.each_batch(of: BATCH_SIZE) do |batch|
- range = batch.pluck('MIN(id)', 'MAX(id)').first
-
- restore_renamed_labels(*range)
- restore_deleted_labels(*range)
- end
- end
-
- def remove_full_duplicates(start_id, stop_id)
- # Fields that are considered duplicate:
- # project_id title template description type color
-
- duplicate_labels = ApplicationRecord.connection.execute(<<-SQL.squish)
-WITH data AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- SELECT labels.*,
- row_number() OVER (PARTITION BY labels.project_id, labels.title, labels.template, labels.description, labels.type, labels.color ORDER BY labels.id) AS row_number,
- #{CREATE} AS restore_action
- FROM labels
- WHERE labels.project_id BETWEEN #{start_id} AND #{stop_id}
- AND NOT EXISTS (SELECT * FROM board_labels WHERE board_labels.label_id = labels.id)
- AND NOT EXISTS (SELECT * FROM label_links WHERE label_links.label_id = labels.id)
- AND NOT EXISTS (SELECT * FROM label_priorities WHERE label_priorities.label_id = labels.id)
- AND NOT EXISTS (SELECT * FROM lists WHERE lists.label_id = labels.id)
- AND NOT EXISTS (SELECT * FROM resource_label_events WHERE resource_label_events.label_id = labels.id)
-) SELECT * FROM data WHERE row_number > 1;
- SQL
-
- if duplicate_labels.any?
- # create backup records
- BackupLabel.insert_all!(duplicate_labels.map { |label| label.except("row_number") })
-
- Label.where(id: duplicate_labels.pluck("id")).delete_all
- end
- end
-
- def rename_partial_duplicates(start_id, stop_id)
- # We need to ensure that the new title (with `_duplicate#{ID}`) doesn't exceed the limit.
- # Truncate the original title (if needed) to 245 characters minus the length of the ID
- # then add `_duplicate#{ID}`
-
- soft_duplicates = ApplicationRecord.connection.execute(<<-SQL.squish)
-WITH data AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- SELECT
- *,
- substring(title from 1 for 245 - length(id::text)) || '_duplicate' || id::text as new_title,
- #{RENAME} AS restore_action,
- row_number() OVER (PARTITION BY project_id, title ORDER BY id) AS row_number
- FROM labels
- WHERE project_id BETWEEN #{start_id} AND #{stop_id}
-) SELECT * FROM data WHERE row_number > 1;
- SQL
-
- if soft_duplicates.any?
- # create backup records
- BackupLabel.insert_all!(soft_duplicates.map { |label| label.except("row_number") })
-
- ApplicationRecord.connection.execute(<<-SQL.squish)
-UPDATE labels SET title = substring(title from 1 for 245 - length(id::text)) || '_duplicate' || id::text
-WHERE labels.id IN (#{soft_duplicates.map { |dup| dup["id"] }.join(", ")});
- SQL
- end
- end
-
- def restore_renamed_labels(start_id, stop_id)
- # the backup label IDs are not incremental, they are copied directly from the Labels table
- ApplicationRecord.connection.execute(<<-SQL.squish)
-WITH backups AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- SELECT id, title
- FROM backup_labels
- WHERE project_id BETWEEN #{start_id} AND #{stop_id} AND
- restore_action = #{RENAME}
-) UPDATE labels SET title = backups.title
-FROM backups
-WHERE labels.id = backups.id;
- SQL
- end
-
- def restore_deleted_labels(start_id, stop_id)
- ActiveRecord::Base.connection.execute(<<-SQL.squish)
-INSERT INTO labels
-SELECT id, title, color, project_id, created_at, updated_at, template, description, description_html, type, group_id, cached_markdown_version FROM backup_labels
- WHERE backup_labels.project_id BETWEEN #{start_id} AND #{stop_id}
- AND backup_labels.restore_action = #{CREATE}
- SQL
- end
-end
diff --git a/db/post_migrate/20200305082858_add_uniqueness_index_to_label_title_and_project.rb b/db/post_migrate/20200305082858_add_uniqueness_index_to_label_title_and_project.rb
deleted file mode 100644
index ce235ba4aea..00000000000
--- a/db/post_migrate/20200305082858_add_uniqueness_index_to_label_title_and_project.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddUniquenessIndexToLabelTitleAndProject < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- PROJECT_AND_TITLE = [:project_id, :title]
-
- def up
- add_concurrent_index :labels, PROJECT_AND_TITLE, where: "labels.group_id IS NULL", unique: true, name: "index_labels_on_project_id_and_title_unique"
- remove_concurrent_index :labels, PROJECT_AND_TITLE, name: "index_labels_on_project_id_and_title"
- end
-
- def down
- add_concurrent_index :labels, PROJECT_AND_TITLE, where: "labels.group_id IS NULL", unique: false, name: "index_labels_on_project_id_and_title"
- remove_concurrent_index :labels, PROJECT_AND_TITLE, name: "index_labels_on_project_id_and_title_unique"
- end
-end
diff --git a/db/post_migrate/20200310075115_schedule_link_lfs_objects_projects.rb b/db/post_migrate/20200310075115_schedule_link_lfs_objects_projects.rb
deleted file mode 100644
index d1ed53d8e70..00000000000
--- a/db/post_migrate/20200310075115_schedule_link_lfs_objects_projects.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleLinkLfsObjectsProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- MIGRATION = 'LinkLfsObjectsProjects'
- BATCH_SIZE = 1000
-
- disable_ddl_transaction!
-
- def up
- lfs_objects_projects = Gitlab::BackgroundMigration::LinkLfsObjectsProjects::LfsObjectsProject.linkable
-
- queue_background_migration_jobs_by_range_at_intervals(
- lfs_objects_projects,
- MIGRATION,
- BackgroundMigrationWorker.minimum_interval,
- batch_size: BATCH_SIZE
- )
- end
-
- def down
- # No-op. No need to make this reversible. In case the jobs enqueued runs and
- # fails at some point, some records will be created. When rescheduled, those
- # records won't be re-created. It's also hard to track which records to clean
- # up if ever.
- end
-end
diff --git a/db/post_migrate/20200310135818_remove_temporary_promoted_notes_index.rb b/db/post_migrate/20200310135818_remove_temporary_promoted_notes_index.rb
deleted file mode 100644
index 0b9bbf1e17b..00000000000
--- a/db/post_migrate/20200310135818_remove_temporary_promoted_notes_index.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-# Removes temporary index to fix orphan promoted issues.
-# For more information check: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23916
-class RemoveTemporaryPromotedNotesIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :notes, 'tmp_idx_on_promoted_notes'
- end
-
- def down
- add_concurrent_index :notes,
- :note,
- where: "noteable_type = 'Issue' AND system IS TRUE AND note LIKE 'promoted to epic%'",
- name: 'tmp_idx_on_promoted_notes'
- end
-end
diff --git a/db/post_migrate/20200310215714_migrate_saml_identities_to_scim_identities.rb b/db/post_migrate/20200310215714_migrate_saml_identities_to_scim_identities.rb
deleted file mode 100644
index 570eec53be3..00000000000
--- a/db/post_migrate/20200310215714_migrate_saml_identities_to_scim_identities.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateSamlIdentitiesToScimIdentities < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- class Identity < ActiveRecord::Base
- self.table_name = 'identities'
-
- include ::EachBatch
- end
-
- def up
- Identity
- .joins('INNER JOIN saml_providers ON saml_providers.id = identities.saml_provider_id')
- .where('saml_providers.group_id IN (SELECT group_id FROM scim_oauth_access_tokens)')
- .select('identities.extern_uid, identities.user_id, saml_providers.group_id, TRUE AS active,
- identities.created_at, CURRENT_TIMESTAMP AS updated_at')
- .each_batch do |batch|
- data_to_insert = batch.map do |record|
- record.attributes.extract!("extern_uid", "user_id", "group_id", "active", "created_at", "updated_at")
- end
-
- Gitlab::Database.main.bulk_insert(:scim_identities, data_to_insert, on_conflict: :do_nothing) # rubocop:disable Gitlab/BulkInsert
- end
- end
-
- def down
- end
-end
diff --git a/db/post_migrate/20200311130802_schedule_populate_user_highest_roles_table.rb b/db/post_migrate/20200311130802_schedule_populate_user_highest_roles_table.rb
deleted file mode 100644
index 36f0d42a855..00000000000
--- a/db/post_migrate/20200311130802_schedule_populate_user_highest_roles_table.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class SchedulePopulateUserHighestRolesTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- BATCH_SIZE = 10_000
- DELAY = 5.minutes.to_i
- DOWNTIME = false
- MIGRATION = 'PopulateUserHighestRolesTable'
-
- disable_ddl_transaction!
-
- class User < ActiveRecord::Base
- include EachBatch
-
- scope :active, -> {
- where(state: 'active', user_type: nil, bot_type: nil)
- .where('ghost IS NOT TRUE')
- }
- end
-
- def up
- # We currently have ~5_300_000 users with the state active on GitLab.com.
- # This means it'll schedule ~530 jobs (10k Users each) with a 5 minutes gap,
- # so this should take ~44 hours for all background migrations to complete.
- User.active.each_batch(of: BATCH_SIZE) do |batch, index|
- range = batch.pluck(Arel.sql('MIN(id)'), Arel.sql('MAX(id)')).first
- delay = index * DELAY
-
- migrate_in(delay.seconds, MIGRATION, [*range])
- end
- end
-
- def down
- # nothing
- end
-end
diff --git a/db/post_migrate/20200311192351_add_index_on_noteable_type_and_noteable_id_to_sent_notifications.rb b/db/post_migrate/20200311192351_add_index_on_noteable_type_and_noteable_id_to_sent_notifications.rb
deleted file mode 100644
index fa0246218c3..00000000000
--- a/db/post_migrate/20200311192351_add_index_on_noteable_type_and_noteable_id_to_sent_notifications.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnNoteableTypeAndNoteableIdToSentNotifications < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_sent_notifications_on_noteable_type_noteable_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :sent_notifications,
- [:noteable_id],
- name: INDEX_NAME,
- where: "noteable_type = 'Issue'"
- end
-
- def down
- remove_concurrent_index_by_name :sent_notifications, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200312134637_backfill_environment_id_on_deployment_merge_requests.rb b/db/post_migrate/20200312134637_backfill_environment_id_on_deployment_merge_requests.rb
deleted file mode 100644
index 77cb1ae8508..00000000000
--- a/db/post_migrate/20200312134637_backfill_environment_id_on_deployment_merge_requests.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillEnvironmentIdOnDeploymentMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- # no-op
-
- # this migration is deleted because there is no foreign key for
- # deployments.environment_id and this caused a failure upgrading
- # deployments_merge_requests.environment_id
- #
- # Details on the following issues:
- # * https://gitlab.com/gitlab-org/gitlab/-/issues/217191
- # * https://gitlab.com/gitlab-org/gitlab/-/issues/26229
- end
-
- def down
- # no-op
-
- # this migration is designed to delete duplicated data
- end
-end
diff --git a/db/post_migrate/20200313203550_remove_orphaned_chat_names.rb b/db/post_migrate/20200313203550_remove_orphaned_chat_names.rb
deleted file mode 100644
index 59cd2b31772..00000000000
--- a/db/post_migrate/20200313203550_remove_orphaned_chat_names.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveOrphanedChatNames < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute("DELETE FROM chat_names WHERE service_id NOT IN(SELECT id FROM services WHERE services.type = 'chat')")
- end
-
- def down
- say 'Orphaned user chat names were removed as a part of this migration and are non-recoverable'
- end
-end
diff --git a/db/post_migrate/20200313204021_validate_foreign_key_from_chat_name_to_service.rb b/db/post_migrate/20200313204021_validate_foreign_key_from_chat_name_to_service.rb
deleted file mode 100644
index fd9feab17db..00000000000
--- a/db/post_migrate/20200313204021_validate_foreign_key_from_chat_name_to_service.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateForeignKeyFromChatNameToService < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- def up
- validate_foreign_key :chat_names, :service_id
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200319071702_consume_remaining_link_lfs_objects_projects_jobs.rb b/db/post_migrate/20200319071702_consume_remaining_link_lfs_objects_projects_jobs.rb
deleted file mode 100644
index 63fa0234a5b..00000000000
--- a/db/post_migrate/20200319071702_consume_remaining_link_lfs_objects_projects_jobs.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class ConsumeRemainingLinkLfsObjectsProjectsJobs < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- Gitlab::BackgroundMigration.steal('LinkLfsObjectsProjects')
- end
-
- def down
- # no-op as there is no need to do anything if this gets rolled back
- end
-end
diff --git a/db/post_migrate/20200323011225_complete_migrate_security_scans.rb b/db/post_migrate/20200323011225_complete_migrate_security_scans.rb
deleted file mode 100644
index 39c9a78b1b6..00000000000
--- a/db/post_migrate/20200323011225_complete_migrate_security_scans.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class CompleteMigrateSecurityScans < ActiveRecord::Migration[6.0]
- disable_ddl_transaction!
-
- def up
- Gitlab::BackgroundMigration.steal('MigrateSecurityScans')
- end
-
- def down
- # intentionally blank
- end
-end
diff --git a/db/post_migrate/20200323011955_remove_index_used_for_scan_migration.rb b/db/post_migrate/20200323011955_remove_index_used_for_scan_migration.rb
deleted file mode 100644
index 0568cdb8483..00000000000
--- a/db/post_migrate/20200323011955_remove_index_used_for_scan_migration.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexUsedForScanMigration < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'job_artifacts_secure_reports_temp_index'
- COLUMNS = [:id, :file_type, :job_id, :created_at, :updated_at]
-
- disable_ddl_transaction!
-
- def up
- if index_exists?(:ci_job_artifacts, COLUMNS, name: INDEX_NAME)
- remove_concurrent_index(:ci_job_artifacts, COLUMNS, name: INDEX_NAME)
- end
- end
-
- def down
- add_concurrent_index(:ci_job_artifacts,
- COLUMNS,
- name: INDEX_NAME,
- where: 'file_type BETWEEN 5 AND 8')
- end
-end
diff --git a/db/post_migrate/20200323080714_trigger_background_migration_for_users_bio.rb b/db/post_migrate/20200323080714_trigger_background_migration_for_users_bio.rb
deleted file mode 100644
index 31ab41a6b88..00000000000
--- a/db/post_migrate/20200323080714_trigger_background_migration_for_users_bio.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class TriggerBackgroundMigrationForUsersBio < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 500
- MIGRATION = 'MigrateUsersBioToUserDetails'
-
- disable_ddl_transaction!
-
- class User < ActiveRecord::Base
- self.table_name = 'users'
-
- include ::EachBatch
- end
-
- def up
- relation = User.where("(COALESCE(bio, '') IS DISTINCT FROM '')")
-
- queue_background_migration_jobs_by_range_at_intervals(relation,
- MIGRATION,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200325162730_schedule_backfill_push_rules_id_in_projects.rb b/db/post_migrate/20200325162730_schedule_backfill_push_rules_id_in_projects.rb
deleted file mode 100644
index 984f4f20441..00000000000
--- a/db/post_migrate/20200325162730_schedule_backfill_push_rules_id_in_projects.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleBackfillPushRulesIdInProjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- MIGRATION = 'BackfillPushRulesIdInProjects'
- BATCH_SIZE = 1_000
-
- class PushRules < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'push_rules'
- end
-
- def up
- # Update one record that is connected to the instance
- value_to_be_updated_to = ScheduleBackfillPushRulesIdInProjects::PushRules.find_by(is_sample: true)&.id
-
- if value_to_be_updated_to
- execute "UPDATE application_settings SET push_rule_id = #{value_to_be_updated_to}
- WHERE id IN (SELECT MAX(id) FROM application_settings);"
- end
-
- ApplicationSetting.expire
-
- queue_background_migration_jobs_by_range_at_intervals(ScheduleBackfillPushRulesIdInProjects::PushRules,
- MIGRATION,
- 5.minutes,
- batch_size: BATCH_SIZE)
- end
-
- def down
- execute "UPDATE application_settings SET push_rule_id = NULL"
-
- ApplicationSetting.expire
- end
-end
diff --git a/db/post_migrate/20200401091051_remove_reference_columns_from_resource_milestone_events.rb b/db/post_migrate/20200401091051_remove_reference_columns_from_resource_milestone_events.rb
deleted file mode 100644
index 639ab93cf18..00000000000
--- a/db/post_migrate/20200401091051_remove_reference_columns_from_resource_milestone_events.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveReferenceColumnsFromResourceMilestoneEvents < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- remove_column :resource_milestone_events, :reference, :text
- remove_column :resource_milestone_events, :reference_html, :text
- remove_column :resource_milestone_events, :cached_markdown_version, :integer
- end
-end
diff --git a/db/post_migrate/20200403132349_remove_old_index_pages_domains_need_auto_ssl_renewal.rb b/db/post_migrate/20200403132349_remove_old_index_pages_domains_need_auto_ssl_renewal.rb
deleted file mode 100644
index b36dce188df..00000000000
--- a/db/post_migrate/20200403132349_remove_old_index_pages_domains_need_auto_ssl_renewal.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveOldIndexPagesDomainsNeedAutoSslRenewal < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = 'index_pages_domains_need_auto_ssl_renewal'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index(:pages_domains, [:certificate_source, :certificate_valid_not_after],
- where: "auto_ssl_enabled = true", name: INDEX_NAME)
- end
-
- def down
- add_concurrent_index(:pages_domains, [:certificate_source, :certificate_valid_not_after],
- where: "auto_ssl_enabled = true", name: INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb b/db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb
deleted file mode 100644
index ab217ba92ab..00000000000
--- a/db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class BackfillDeploymentClustersFromDeployments < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- MIGRATION = 'BackfillDeploymentClustersFromDeployments'
- DELAY_INTERVAL = 2.minutes
- BATCH_SIZE = 10_000
-
- disable_ddl_transaction!
-
- class Deployment < ActiveRecord::Base
- include EachBatch
-
- default_scope { where.not(cluster_id: nil) } # rubocop:disable Cop/DefaultScope
-
- self.table_name = 'deployments'
- end
-
- def up
- say "Scheduling `#{MIGRATION}` jobs"
-
- queue_background_migration_jobs_by_range_at_intervals(Deployment, MIGRATION, DELAY_INTERVAL, batch_size: BATCH_SIZE)
- end
-
- def down
- # NOOP
- end
-end
diff --git a/db/post_migrate/20200406193427_add_index_to_issues_health_status.rb b/db/post_migrate/20200406193427_add_index_to_issues_health_status.rb
deleted file mode 100644
index 83baf5b6d75..00000000000
--- a/db/post_migrate/20200406193427_add_index_to_issues_health_status.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToIssuesHealthStatus < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'idx_issues_on_health_status_not_null'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(
- :issues,
- :health_status,
- where: 'health_status IS NOT NULL',
- name: INDEX_NAME
- )
- end
-
- def down
- remove_concurrent_index_by_name(:issues, INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200407094005_drop_vulnerability_severity_index.rb b/db/post_migrate/20200407094005_drop_vulnerability_severity_index.rb
deleted file mode 100644
index 14e6ce32097..00000000000
--- a/db/post_migrate/20200407094005_drop_vulnerability_severity_index.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class DropVulnerabilitySeverityIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
- INDEX_NAME = 'undefined_vulnerabilities'
-
- def up
- remove_concurrent_index_by_name :vulnerability_occurrences, INDEX_NAME
- end
-
- def down
- add_concurrent_index(:vulnerability_occurrences, :id, where: 'severity = 0', name: INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200407094923_drop_vulnerabilities_severity_index.rb b/db/post_migrate/20200407094923_drop_vulnerabilities_severity_index.rb
deleted file mode 100644
index 90ec7dc7ec2..00000000000
--- a/db/post_migrate/20200407094923_drop_vulnerabilities_severity_index.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class DropVulnerabilitiesSeverityIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
- INDEX_NAME = 'undefined_vulnerability'
-
- def up
- remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
- end
-
- def down
- add_concurrent_index(:vulnerabilities, :id, where: 'severity = 0', name: INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200408110856_add_nginx_five_hundred_percentage_metric.rb b/db/post_migrate/20200408110856_add_nginx_five_hundred_percentage_metric.rb
deleted file mode 100644
index a99e0291fe8..00000000000
--- a/db/post_migrate/20200408110856_add_nginx_five_hundred_percentage_metric.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class AddNginxFiveHundredPercentageMetric < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- ::Gitlab::DatabaseImporters::CommonMetrics::Importer.new.execute
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200408132152_remove_namespaces_trial_ends_on.rb b/db/post_migrate/20200408132152_remove_namespaces_trial_ends_on.rb
deleted file mode 100644
index a303b9d1869..00000000000
--- a/db/post_migrate/20200408132152_remove_namespaces_trial_ends_on.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveNamespacesTrialEndsOn < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :namespaces, 'index_namespaces_on_trial_ends_on'
-
- with_lock_retries do
- remove_column :namespaces, :trial_ends_on
- end
- end
-
- def down
- unless column_exists?(:namespaces, :trial_ends_on)
- with_lock_retries do
- add_column :namespaces, :trial_ends_on, :datetime_with_timezone # rubocop:disable Migration/AddColumnsToWideTables
- end
- end
-
- add_concurrent_index :namespaces, :trial_ends_on, using: 'btree', where: 'trial_ends_on IS NOT NULL'
- end
-end
diff --git a/db/post_migrate/20200409211607_migrate_legacy_attachments.rb b/db/post_migrate/20200409211607_migrate_legacy_attachments.rb
deleted file mode 100644
index fb4a996d3b7..00000000000
--- a/db/post_migrate/20200409211607_migrate_legacy_attachments.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateLegacyAttachments < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
-
- MIGRATION = 'LegacyUploadsMigrator'
- BATCH_SIZE = 5000
- INTERVAL = 5.minutes.to_i
-
- class Upload < ActiveRecord::Base
- self.table_name = 'uploads'
-
- include ::EachBatch
- end
-
- def up
- queue_background_migration_jobs_by_range_at_intervals(Upload.where(uploader: 'AttachmentUploader', model_type: 'Note'),
- MIGRATION,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200416111111_migrate_vulnerability_dismissals.rb b/db/post_migrate/20200416111111_migrate_vulnerability_dismissals.rb
deleted file mode 100644
index 6ca3db8902b..00000000000
--- a/db/post_migrate/20200416111111_migrate_vulnerability_dismissals.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateVulnerabilityDismissals < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- MIGRATION = 'UpdateVulnerabilitiesToDismissed'
- BATCH_SIZE = 500
- DELAY_INTERVAL = 2.minutes.to_i
-
- class Vulnerability < ActiveRecord::Base
- self.table_name = 'vulnerabilities'
- self.inheritance_column = :_type_disabled
-
- include ::EachBatch
- end
-
- def up
- return unless Gitlab.ee?
-
- Vulnerability.select('project_id').group(:project_id).each_batch(of: BATCH_SIZE, column: "project_id") do |project_batch, index|
- batch_delay = (index - 1) * BATCH_SIZE * DELAY_INTERVAL
-
- project_batch.each_with_index do |project, project_batch_index|
- project_delay = project_batch_index * DELAY_INTERVAL
- migrate_in(batch_delay + project_delay, MIGRATION, project[:project_id])
- end
- end
- end
-
- def down
- # nothing to do
- end
-end
diff --git a/db/post_migrate/20200420094444_backfill_snippet_repositories.rb b/db/post_migrate/20200420094444_backfill_snippet_repositories.rb
deleted file mode 100644
index 452a1a5330f..00000000000
--- a/db/post_migrate/20200420094444_backfill_snippet_repositories.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillSnippetRepositories < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INTERVAL = 3.minutes
- BATCH_SIZE = 100
- MIGRATION = 'BackfillSnippetRepositories'
-
- disable_ddl_transaction!
-
- class Snippet < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'snippets'
- self.inheritance_column = :_type_disabled
- end
-
- def up
- queue_background_migration_jobs_by_range_at_intervals(Snippet,
- MIGRATION,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200420162730_remove_additional_application_settings_rows.rb b/db/post_migrate/20200420162730_remove_additional_application_settings_rows.rb
deleted file mode 100644
index e4a0ec1eb4a..00000000000
--- a/db/post_migrate/20200420162730_remove_additional_application_settings_rows.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveAdditionalApplicationSettingsRows < ActiveRecord::Migration[6.0]
- class ApplicationSetting < ActiveRecord::Base
- self.table_name = 'application_settings'
- end
-
- def up
- return if ApplicationSetting.count == 1
-
- execute "DELETE from application_settings WHERE id NOT IN (SELECT MAX(id) FROM application_settings);"
- end
-
- def down
- # no changes
- end
-end
diff --git a/db/post_migrate/20200421195234_backfill_status_page_published_incidents.rb b/db/post_migrate/20200421195234_backfill_status_page_published_incidents.rb
deleted file mode 100644
index fa7a5a9d924..00000000000
--- a/db/post_migrate/20200421195234_backfill_status_page_published_incidents.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillStatusPagePublishedIncidents < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- class Incident < ActiveRecord::Base
- self.table_name = 'status_page_published_incidents'
- end
-
- class StatusPageIssue < ActiveRecord::Base
- include ::EachBatch
-
- self.table_name = 'issues'
-
- scope :published_only, -> do
- joins('INNER JOIN status_page_settings ON status_page_settings.project_id = issues.project_id')
- .where('status_page_settings.enabled = true')
- .where(confidential: false)
- end
- end
-
- def up
- current_time = Time.current
-
- StatusPageIssue.published_only.each_batch do |batch|
- incidents = batch.map do |status_page_issue|
- {
- issue_id: status_page_issue.id,
- created_at: current_time,
- updated_at: current_time
- }
- end
-
- Incident.insert_all(incidents, unique_by: :issue_id)
- end
- end
-
- def down
- # no op
-
- # While we expect this table to be empty at the point of
- # the up migration, there is no reliable way to determine
- # whether records were added as a part of the migration
- # or after it has run.
- end
-end
diff --git a/db/post_migrate/20200424043515_drop_namespaces_plan_id.rb b/db/post_migrate/20200424043515_drop_namespaces_plan_id.rb
deleted file mode 100644
index b05f2da648a..00000000000
--- a/db/post_migrate/20200424043515_drop_namespaces_plan_id.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class DropNamespacesPlanId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- remove_column :namespaces, :plan_id
- end
- end
-
- def down
- unless column_exists?(:namespaces, :plan_id)
- with_lock_retries do
- add_column :namespaces, :plan_id, :integer # rubocop:disable Migration/AddColumnsToWideTables
- end
- end
-
- add_concurrent_index :namespaces, :plan_id
- add_concurrent_foreign_key :namespaces, :plans, column: :plan_id, on_delete: :nullify
- end
-end
diff --git a/db/post_migrate/20200427064130_cleanup_optimistic_locking_nulls_pt2_fixed.rb b/db/post_migrate/20200427064130_cleanup_optimistic_locking_nulls_pt2_fixed.rb
deleted file mode 100644
index 63f85fc7156..00000000000
--- a/db/post_migrate/20200427064130_cleanup_optimistic_locking_nulls_pt2_fixed.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupOptimisticLockingNullsPt2Fixed < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- TABLES = %w(ci_stages ci_builds ci_pipelines).freeze
- BATCH_SIZE = 10_000
-
- def declare_class(table)
- Class.new(ActiveRecord::Base) do
- include EachBatch
-
- self.table_name = table
- self.inheritance_column = :_type_disabled # Disable STI
- end
- end
-
- def up
- last_table_final_delay = 0
-
- TABLES.each do |table|
- # cleanup wrong index created in the previous migration, it might be there on staging
- remove_concurrent_index table.to_sym, :lock_version, where: "lock_version IS NULL"
-
- add_concurrent_index table.to_sym, :id, where: "lock_version IS NULL", name: "tmp_index_#{table}_lock_version"
-
- last_table_final_delay = queue_background_migration_jobs_by_range_at_intervals(
- declare_class(table).where(lock_version: nil),
- 'CleanupOptimisticLockingNulls',
- 2.minutes,
- batch_size: BATCH_SIZE,
- other_job_arguments: [table],
- initial_delay: last_table_final_delay
- )
- end
- end
-
- def down
- TABLES.each do |table|
- remove_concurrent_index table.to_sym, :id, where: "lock_version IS NULL", name: "tmp_index_#{table}_lock_version"
- end
- end
-end
diff --git a/db/post_migrate/20200428134356_remove_elastic_experimental_indexer_from_application_settings.rb b/db/post_migrate/20200428134356_remove_elastic_experimental_indexer_from_application_settings.rb
deleted file mode 100644
index a9baf6fd8e3..00000000000
--- a/db/post_migrate/20200428134356_remove_elastic_experimental_indexer_from_application_settings.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-class RemoveElasticExperimentalIndexerFromApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- remove_column :application_settings, :elasticsearch_experimental_indexer, :boolean
- end
-end
diff --git a/db/post_migrate/20200429002150_cleanup_sprints_state_rename.rb b/db/post_migrate/20200429002150_cleanup_sprints_state_rename.rb
deleted file mode 100644
index 7f67a55a19d..00000000000
--- a/db/post_migrate/20200429002150_cleanup_sprints_state_rename.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupSprintsStateRename < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- cleanup_concurrent_column_rename :sprints, :state, :state_enum
- end
-
- def down
- undo_cleanup_concurrent_column_rename :sprints, :state, :state_enum
- end
-end
diff --git a/db/post_migrate/20200506085748_update_undefined_confidence_from_occurrences.rb b/db/post_migrate/20200506085748_update_undefined_confidence_from_occurrences.rb
deleted file mode 100644
index 06c82ad404b..00000000000
--- a/db/post_migrate/20200506085748_update_undefined_confidence_from_occurrences.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateUndefinedConfidenceFromOccurrences < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- INDEX_NAME = 'index_vulnerability_occurrences_on_id_and_confidence_eq_zero'
- DOWNTIME = false
-
- disable_ddl_transaction!
- BATCH_SIZE = 1_000
- INTERVAL = 2.minutes
-
- # 286_159 records to be updated on GitLab.com
- def up
- # create temporary index for undefined vulnerabilities
- add_concurrent_index(:vulnerability_occurrences, :id, where: 'confidence = 0', name: INDEX_NAME)
-
- return unless Gitlab.ee?
-
- migration = Gitlab::BackgroundMigration::RemoveUndefinedOccurrenceConfidenceLevel
- migration_name = migration.to_s.demodulize
- relation = migration::Occurrence.undefined_confidence
- queue_background_migration_jobs_by_range_at_intervals(relation,
- migration_name,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- # temporary index is to be dropped in a different migration in an upcoming release
- remove_concurrent_index(:vulnerability_occurrences, :id, where: 'confidence = 0', name: INDEX_NAME)
- # This migration can not be reversed because we can not know which records had undefined confidence
- end
-end
diff --git a/db/post_migrate/20200506125731_cleanup_user_highest_roles_population.rb b/db/post_migrate/20200506125731_cleanup_user_highest_roles_population.rb
deleted file mode 100644
index 5e613228c56..00000000000
--- a/db/post_migrate/20200506125731_cleanup_user_highest_roles_population.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupUserHighestRolesPopulation < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_for_migrating_user_highest_roles_table'
-
- disable_ddl_transaction!
-
- def up
- Gitlab::BackgroundMigration.steal('PopulateUserHighestRolesTable')
-
- remove_concurrent_index(:users, :id, name: INDEX_NAME)
- end
-
- def down
- add_concurrent_index(:users,
- :id,
- where: "state = 'active' AND user_type IS NULL AND bot_type IS NULL AND ghost IS NOT TRUE",
- name: INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200506154421_migrate_scim_identities_to_saml_for_new_users.rb b/db/post_migrate/20200506154421_migrate_scim_identities_to_saml_for_new_users.rb
deleted file mode 100644
index 718e788aad7..00000000000
--- a/db/post_migrate/20200506154421_migrate_scim_identities_to_saml_for_new_users.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateScimIdentitiesToSamlForNewUsers < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- class ScimIdentity < ActiveRecord::Base
- self.table_name = 'scim_identities'
-
- belongs_to :user
-
- include ::EachBatch
- end
-
- class Identity < ActiveRecord::Base
- self.table_name = 'identities'
-
- belongs_to :saml_provider
- end
-
- def up
- users_with_saml_provider = Identity.select('user_id').joins(:saml_provider)
-
- ScimIdentity.each_batch do |relation|
- identity_records = relation
- .select("scim_identities.extern_uid, 'group_saml', scim_identities.user_id, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, saml_providers.id")
- .joins(:user)
- .joins('inner join saml_providers on saml_providers.group_id=scim_identities.group_id')
- .where("date_trunc('second',scim_identities.created_at) at time zone 'UTC' = date_trunc('second',users.created_at)")
- .where.not(user_id: users_with_saml_provider)
-
- execute "insert into identities (extern_uid, provider, user_id, created_at, updated_at, saml_provider_id) #{identity_records.to_sql} on conflict do nothing"
- end
- end
-
- def down
- end
-end
diff --git a/db/post_migrate/20200508091106_remove_bot_type.rb b/db/post_migrate/20200508091106_remove_bot_type.rb
deleted file mode 100644
index 2afcf5308e7..00000000000
--- a/db/post_migrate/20200508091106_remove_bot_type.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveBotType < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :users, 'index_users_on_bot_type'
-
- with_lock_retries do
- remove_column :users, :bot_type
- end
- end
-
- def down
- unless column_exists?(:users, :bot_type)
- with_lock_retries do
- add_column :users, :bot_type, :integer, limit: 2 # rubocop:disable Migration/AddColumnsToWideTables
- end
- end
-
- execute 'UPDATE users set bot_type = user_type WHERE user_type IN(1,2,3,6)'
-
- add_concurrent_index :users, :bot_type
- end
-end
diff --git a/db/post_migrate/20200511080113_add_projects_foreign_key_to_namespaces.rb b/db/post_migrate/20200511080113_add_projects_foreign_key_to_namespaces.rb
deleted file mode 100644
index a7f67a3b5cd..00000000000
--- a/db/post_migrate/20200511080113_add_projects_foreign_key_to_namespaces.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class AddProjectsForeignKeyToNamespaces < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- FK_NAME = 'fk_projects_namespace_id'
-
- def up
- with_lock_retries do
- add_foreign_key(
- :projects,
- :namespaces,
- column: :namespace_id,
- on_delete: :restrict,
- validate: false,
- name: FK_NAME
- )
- end
- end
-
- def down
- with_lock_retries do
- remove_foreign_key_if_exists :projects, column: :namespace_id, name: FK_NAME
- end
- end
-end
diff --git a/db/post_migrate/20200511083541_cleanup_projects_with_missing_namespace.rb b/db/post_migrate/20200511083541_cleanup_projects_with_missing_namespace.rb
deleted file mode 100644
index 8e6ee0f35ca..00000000000
--- a/db/post_migrate/20200511083541_cleanup_projects_with_missing_namespace.rb
+++ /dev/null
@@ -1,261 +0,0 @@
-# frozen_string_literal: true
-
-# rubocop:disable Migration/PreventStrings
-
-# This migration cleans up Projects that were orphaned when their namespace was deleted
-# Instead of deleting them, we:
-# - Find (or create) the Ghost User
-# - Create (if not already exists) a `lost-and-found` group owned by the Ghost User
-# - Find orphaned projects --> namespace_id can not be found in namespaces
-# - Move the orphaned projects to the `lost-and-found` group
-# (while making them private and setting `archived=true`)
-#
-# On GitLab.com (2020-05-11) this migration will update 66 orphaned projects
-class CleanupProjectsWithMissingNamespace < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- VISIBILITY_PRIVATE = 0
- ACCESS_LEVEL_OWNER = 50
-
- # The batch size of projects to check in each iteration
- # We expect the selectivity for orphaned projects to be very low:
- # (66 orphaned projects out of a total 13.6M)
- # so 10K should be a safe choice
- BATCH_SIZE = 10000
-
- disable_ddl_transaction!
-
- class UserDetail < ActiveRecord::Base
- self.table_name = 'user_details'
-
- belongs_to :user, class_name: 'CleanupProjectsWithMissingNamespace::User'
- end
-
- class User < ActiveRecord::Base
- self.table_name = 'users'
-
- LOST_AND_FOUND_GROUP = 'lost-and-found'
- USER_TYPE_GHOST = 5
- DEFAULT_PROJECTS_LIMIT = 100000
-
- default_value_for :admin, false
- default_value_for :can_create_group, true # we need this to create the group
- default_value_for :can_create_team, false
- default_value_for :project_view, :files
- default_value_for :notified_of_own_activity, false
- default_value_for :preferred_language, I18n.default_locale
-
- has_one :user_detail, class_name: 'CleanupProjectsWithMissingNamespace::UserDetail'
- has_one :namespace, -> { where(type: nil) },
- foreign_key: :owner_id, inverse_of: :owner, autosave: true,
- class_name: 'CleanupProjectsWithMissingNamespace::Namespace'
-
- before_save :ensure_namespace_correct
- before_save :ensure_bio_is_assigned_to_user_details, if: :bio_changed?
-
- enum project_view: { readme: 0, activity: 1, files: 2 }
-
- def ensure_namespace_correct
- if namespace
- namespace.path = username if username_changed?
- namespace.name = name if name_changed?
- else
- build_namespace(path: username, name: name)
- end
- end
-
- def ensure_bio_is_assigned_to_user_details
- user_detail.bio = bio.to_s[0...255]
- end
-
- def user_detail
- super.presence || build_user_detail
- end
-
- # Return (or create if necessary) the `lost-and-found` group
- def lost_and_found_group
- existing_lost_and_found_group || Group.create_unique_group(self, LOST_AND_FOUND_GROUP)
- end
-
- def existing_lost_and_found_group
- # There should only be one Group for User Ghost starting with LOST_AND_FOUND_GROUP
- Group
- .joins('INNER JOIN members ON namespaces.id = members.source_id')
- .where(namespaces: { type: 'Group' })
- .where(members: { type: 'GroupMember' })
- .where(members: { source_type: 'Namespace' })
- .where(members: { user_id: self.id })
- .where(members: { requested_at: nil })
- .where(members: { access_level: ACCESS_LEVEL_OWNER })
- .find_by(Group.arel_table[:name].matches("#{LOST_AND_FOUND_GROUP}%"))
- end
-
- class << self
- # Return (or create if necessary) the ghost user
- def ghost
- email = 'ghost%s@example.com'
-
- unique_internal(where(user_type: USER_TYPE_GHOST), 'ghost', email) do |u|
- u.bio = _('This is a "Ghost User", created to hold all issues authored by users that have since been deleted. This user cannot be removed.')
- u.name = 'Ghost User'
- end
- end
-
- def unique_internal(scope, username, email_pattern, &block)
- scope.first || create_unique_internal(scope, username, email_pattern, &block)
- end
-
- def create_unique_internal(scope, username, email_pattern, &creation_block)
- # Since we only want a single one of these in an instance, we use an
- # exclusive lease to ensure that this block is never run concurrently.
- lease_key = "user:unique_internal:#{username}"
- lease = Gitlab::ExclusiveLease.new(lease_key, timeout: 1.minute.to_i)
-
- until uuid = lease.try_obtain
- # Keep trying until we obtain the lease. To prevent hammering Redis too
- # much we'll wait for a bit between retries.
- sleep(1)
- end
-
- # Recheck if the user is already present. One might have been
- # added between the time we last checked (first line of this method)
- # and the time we acquired the lock.
- existing_user = uncached { scope.first }
- return existing_user if existing_user.present?
-
- uniquify = Uniquify.new
-
- username = uniquify.string(username) { |s| User.find_by_username(s) }
-
- email = uniquify.string(-> (n) { Kernel.sprintf(email_pattern, n) }) do |s|
- User.find_by_email(s)
- end
-
- User.create!(
- username: username,
- email: email,
- user_type: USER_TYPE_GHOST,
- projects_limit: DEFAULT_PROJECTS_LIMIT,
- state: :active,
- &creation_block
- )
- ensure
- Gitlab::ExclusiveLease.cancel(lease_key, uuid)
- end
- end
- end
-
- class Namespace < ActiveRecord::Base
- self.table_name = 'namespaces'
-
- belongs_to :owner, class_name: 'CleanupProjectsWithMissingNamespace::User'
- end
-
- class Group < Namespace
- # Disable STI to allow us to manually set "type = 'Group'"
- # Otherwise rails forces "type = CleanupProjectsWithMissingNamespace::Group"
- self.inheritance_column = :_type_disabled
-
- def self.create_unique_group(user, group_name)
- # 'lost-and-found' may be already defined, find a unique one
- group_name = Uniquify.new.string(group_name) do |str|
- Group.where(parent_id: nil, name: str).exists?
- end
-
- group = Group.create!(
- name: group_name,
- path: group_name,
- type: 'Group',
- description: 'Group to store orphaned projects',
- visibility_level: VISIBILITY_PRIVATE
- )
-
- # No need to create a route for the lost-and-found group
-
- GroupMember.add_user(group, user, ACCESS_LEVEL_OWNER)
-
- group
- end
- end
-
- class Member < ActiveRecord::Base
- self.table_name = 'members'
- end
-
- class GroupMember < Member
- NOTIFICATION_SETTING_GLOBAL = 3
-
- # Disable STI to allow us to manually set "type = 'GroupMember'"
- # Otherwise rails forces "type = CleanupProjectsWithMissingNamespace::GroupMember"
- self.inheritance_column = :_type_disabled
-
- def self.add_user(source, user, access_level)
- GroupMember.create!(
- type: 'GroupMember',
- source_id: source.id,
- user_id: user.id,
- source_type: 'Namespace',
- access_level: access_level,
- notification_level: NOTIFICATION_SETTING_GLOBAL
- )
- end
- end
-
- class Project < ActiveRecord::Base
- self.table_name = 'projects'
-
- include ::EachBatch
-
- def self.without_namespace
- where(
- 'NOT EXISTS (
- SELECT 1
- FROM namespaces
- WHERE projects.namespace_id = namespaces.id
- )'
- )
- end
- end
-
- def up
- # Reset the column information of all the models that update the database
- # to ensure the Active Record's knowledge of the table structure is current
- User.reset_column_information
- Namespace.reset_column_information
- Member.reset_column_information
- Project.reset_column_information
-
- # Find or Create the ghost user
- ghost_user = User.ghost
-
- # Find or Create the `lost-and-found`
- lost_and_found = ghost_user.lost_and_found_group
-
- # With BATCH_SIZE=10K and projects.count=13.6M
- # ~1360 iterations will be run:
- # - each requires on average ~160ms for relation.without_namespace
- # - worst case scenario is that 66 of those batches will trigger an update (~200ms each)
- # In general, we expect less than 5% (=66/13.6M x 10K) to trigger an update
- # Expected total run time: ~235 seconds (== 220 seconds + 14 seconds)
- Project.each_batch(of: BATCH_SIZE) do |relation|
- relation.without_namespace.update_all <<~SQL
- namespace_id = #{lost_and_found.id},
- archived = TRUE,
- visibility_level = #{VISIBILITY_PRIVATE},
-
- -- Names are expected to be unique inside their namespace
- -- (uniqueness validation on namespace_id, name)
- -- Attach the id to the name and path to make sure that they are unique
- name = name || '_' || id::text,
- path = path || '_' || id::text
- SQL
- end
- end
-
- def down
- # no-op: the original state for those projects was inconsistent
- # Also, the original namespace_id for each project is lost during the update
- end
-end
-# rubocop:enable Migration/PreventStrings
diff --git a/db/post_migrate/20200511092714_update_undefined_confidence_from_vulnerabilities.rb b/db/post_migrate/20200511092714_update_undefined_confidence_from_vulnerabilities.rb
deleted file mode 100644
index d6611ddbd66..00000000000
--- a/db/post_migrate/20200511092714_update_undefined_confidence_from_vulnerabilities.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateUndefinedConfidenceFromVulnerabilities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- INDEX_NAME = 'index_vulnerability_on_id_and_confidence_eq_zero'
- DOWNTIME = false
-
- disable_ddl_transaction!
- BATCH_SIZE = 1_000
- INTERVAL = 2.minutes
-
- # 87_602 records to be updated on GitLab.com
- def up
- # create temporary index for undefined vulnerabilities
- add_concurrent_index(:vulnerabilities, :id, where: 'confidence = 0', name: INDEX_NAME)
-
- return unless Gitlab.ee?
-
- migration = Gitlab::BackgroundMigration::RemoveUndefinedVulnerabilityConfidenceLevel
- migration_name = migration.to_s.demodulize
- relation = migration::Vulnerability.undefined_confidence
- queue_background_migration_jobs_by_range_at_intervals(relation,
- migration_name,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- # temporary index is to be dropped in a different migration in an upcoming release
- remove_concurrent_index(:vulnerabilities, :id, where: 'confidence = 0', name: INDEX_NAME)
- # This migration can not be reversed because we can not know which records had undefined confidence
- end
-end
diff --git a/db/post_migrate/20200511130130_ensure_deprecated_jenkins_service_records_removal.rb b/db/post_migrate/20200511130130_ensure_deprecated_jenkins_service_records_removal.rb
deleted file mode 100644
index 4c1f29f8e47..00000000000
--- a/db/post_migrate/20200511130130_ensure_deprecated_jenkins_service_records_removal.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class EnsureDeprecatedJenkinsServiceRecordsRemoval < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute <<~SQL.strip
- DELETE FROM services WHERE type = 'JenkinsDeprecatedService';
- SQL
- end
-
- def down
- # no-op
-
- # The records were removed by `up`
- end
-end
diff --git a/db/post_migrate/20200511145545_change_variable_interpolation_format_in_common_metrics.rb b/db/post_migrate/20200511145545_change_variable_interpolation_format_in_common_metrics.rb
deleted file mode 100644
index ac3c545350d..00000000000
--- a/db/post_migrate/20200511145545_change_variable_interpolation_format_in_common_metrics.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeVariableInterpolationFormatInCommonMetrics < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- ::Gitlab::DatabaseImporters::CommonMetrics::Importer.new.execute
- end
-
- def down
- # no-op
- # The import cannot be reversed since we do not know the state that the
- # common metrics in the PrometheusMetric table were in before the import.
- end
-end
diff --git a/db/post_migrate/20200511162057_add_missing_instance_to_servicess.rb b/db/post_migrate/20200511162057_add_missing_instance_to_servicess.rb
deleted file mode 100644
index efaef085e8c..00000000000
--- a/db/post_migrate/20200511162057_add_missing_instance_to_servicess.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class AddMissingInstanceToServicess < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # This is a corrective migration to keep the instance column.
- # Upgrade from 12.7 to 12.9 removes the instance column as it was first added
- # in the normal migration and then removed in the post migration.
- #
- # 12.8 removed the instance column in a post deployment migration https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24885
- # 12.9 added the instance column in a normal migration https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25714
- #
- # rubocop:disable Migration/AddColumnWithDefault
- # rubocop:disable Migration/UpdateLargeTable
- def up
- unless column_exists?(:services, :instance)
- add_column_with_default(:services, :instance, :boolean, default: false)
- end
- end
- # rubocop:enable Migration/AddColumnWithDefault
- # rubocop:enable Migration/UpdateLargeTable
-
- def down
- # Does not apply
- end
-end
diff --git a/db/post_migrate/20200511162115_add_missing_index_to_service_unique_instance_per_type.rb b/db/post_migrate/20200511162115_add_missing_index_to_service_unique_instance_per_type.rb
deleted file mode 100644
index c9e0193f5d2..00000000000
--- a/db/post_migrate/20200511162115_add_missing_index_to_service_unique_instance_per_type.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class AddMissingIndexToServiceUniqueInstancePerType < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # This is a corrective migration to keep the index on instance column.
- # Upgrade from 12.7 to 12.9 removes the instance column as it was first added
- # in the normal migration and then removed in the post migration.
- #
- # 12.8 removed the instance column in a post deployment migration https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24885
- # 12.9 added the instance column in a normal migration https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25714
- def up
- unless index_exists_by_name?(:services, 'index_services_on_type_and_instance')
- add_concurrent_index(:services, [:type, :instance], unique: true, where: 'instance IS TRUE')
- end
- end
-
- def down
- # Does not apply
- end
-end
diff --git a/db/post_migrate/20200511220023_validate_projects_foreign_key_to_namespaces.rb b/db/post_migrate/20200511220023_validate_projects_foreign_key_to_namespaces.rb
deleted file mode 100644
index 37a761507fc..00000000000
--- a/db/post_migrate/20200511220023_validate_projects_foreign_key_to_namespaces.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateProjectsForeignKeyToNamespaces < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- FK_NAME = 'fk_projects_namespace_id'
-
- def up
- # Validate the FK added with 20200511080113_add_projects_foreign_key_to_namespaces.rb
- validate_foreign_key :projects, :namespace_id, name: FK_NAME
- end
-
- def down
- # no-op: No need to invalidate the foreign key
- # The inconsistent data are permanently fixed with the data migration
- # `20200511083541_cleanup_projects_with_missing_namespace.rb`
- # even if it is rolled back.
- # If there is an issue with the FK, we'll roll back the migration that adds the FK
- end
-end
diff --git a/db/post_migrate/20200513171959_enable_hashed_storage.rb b/db/post_migrate/20200513171959_enable_hashed_storage.rb
deleted file mode 100644
index 53e52b1caff..00000000000
--- a/db/post_migrate/20200513171959_enable_hashed_storage.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class EnableHashedStorage < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- class ApplicationSetting < ActiveRecord::Base
- self.table_name = 'application_settings'
- end
-
- def up
- ApplicationSetting.update_all(hashed_storage_enabled: true)
- end
-
- def down
- # in 13.0 we are forcing hashed storage to always be enabled for new projects
- end
-end
diff --git a/db/post_migrate/20200514000009_add_not_null_constraint_on_file_store_to_lfs_objects.rb b/db/post_migrate/20200514000009_add_not_null_constraint_on_file_store_to_lfs_objects.rb
deleted file mode 100644
index 6b3b9a3155d..00000000000
--- a/db/post_migrate/20200514000009_add_not_null_constraint_on_file_store_to_lfs_objects.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddNotNullConstraintOnFileStoreToLfsObjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_not_null_constraint(:lfs_objects, :file_store, validate: false)
- end
-
- def down
- remove_not_null_constraint(:lfs_objects, :file_store)
- end
-end
diff --git a/db/post_migrate/20200514000132_add_not_null_constraint_on_store_to_uploads.rb b/db/post_migrate/20200514000132_add_not_null_constraint_on_store_to_uploads.rb
deleted file mode 100644
index c5f1cfa79b8..00000000000
--- a/db/post_migrate/20200514000132_add_not_null_constraint_on_store_to_uploads.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddNotNullConstraintOnStoreToUploads < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_not_null_constraint(:uploads, :store, validate: false)
- end
-
- def down
- remove_not_null_constraint(:uploads, :store)
- end
-end
diff --git a/db/post_migrate/20200514000340_add_not_null_constraint_on_file_store_to_ci_jobs_artifacts.rb b/db/post_migrate/20200514000340_add_not_null_constraint_on_file_store_to_ci_jobs_artifacts.rb
deleted file mode 100644
index 5759803e3b7..00000000000
--- a/db/post_migrate/20200514000340_add_not_null_constraint_on_file_store_to_ci_jobs_artifacts.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddNotNullConstraintOnFileStoreToCiJobsArtifacts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_not_null_constraint(:ci_job_artifacts, :file_store, validate: false)
- end
-
- def down
- remove_not_null_constraint(:ci_job_artifacts, :file_store)
- end
-end
diff --git a/db/post_migrate/20200518114540_schedule_fix_ruby_object_in_audit_events.rb b/db/post_migrate/20200518114540_schedule_fix_ruby_object_in_audit_events.rb
deleted file mode 100644
index e4335089540..00000000000
--- a/db/post_migrate/20200518114540_schedule_fix_ruby_object_in_audit_events.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleFixRubyObjectInAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_audit_events_on_ruby_object_in_details'
- INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 1_000
- MIGRATION = 'FixRubyObjectInAuditEvents'
-
- disable_ddl_transaction!
-
- class AuditEvent < ActiveRecord::Base
- self.table_name = 'audit_events'
-
- include ::EachBatch
- end
-
- def up
- return unless Gitlab.ee?
-
- # create temporary index for audit_events with ruby/object in details field, may take well over 1h
- add_concurrent_index(:audit_events, :id, where: "details ~~ '%ruby/object%'", name: INDEX_NAME)
-
- relation = AuditEvent.where("details ~~ '%ruby/object%'")
-
- queue_background_migration_jobs_by_range_at_intervals(
- relation,
- MIGRATION,
- INTERVAL,
- batch_size: BATCH_SIZE
- )
- end
-
- def down
- # temporary index is to be dropped in a different migration in an upcoming release
- # https://gitlab.com/gitlab-org/gitlab/issues/196842
- remove_concurrent_index_by_name(:audit_events, INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200518133123_add_index_on_starting_ending_at_to_metrics_dashboard_annotations.rb b/db/post_migrate/20200518133123_add_index_on_starting_ending_at_to_metrics_dashboard_annotations.rb
deleted file mode 100644
index 3094fff0d1d..00000000000
--- a/db/post_migrate/20200518133123_add_index_on_starting_ending_at_to_metrics_dashboard_annotations.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnStartingEndingAtToMetricsDashboardAnnotations < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_metrics_dashboard_annotations_on_timespan_end'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :metrics_dashboard_annotations, 'COALESCE(ending_at, starting_at)', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index :metrics_dashboard_annotations, 'COALESCE(ending_at, starting_at)', name: INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200519171058_update_index_ci_builds_on_commit_id_and_artifacts_expireatandidpartial.rb b/db/post_migrate/20200519171058_update_index_ci_builds_on_commit_id_and_artifacts_expireatandidpartial.rb
deleted file mode 100644
index e09ad4bdadf..00000000000
--- a/db/post_migrate/20200519171058_update_index_ci_builds_on_commit_id_and_artifacts_expireatandidpartial.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateIndexCiBuildsOnCommitIdAndArtifactsExpireatandidpartial < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- OLD_INDEX_NAME = 'index_ci_builds_on_commit_id_and_artifacts_expireatandidpartial'
- NEW_INDEX_NAME = 'index_ci_builds_on_commit_id_artifacts_expired_at_and_id'
-
- OLD_CLAUSE = "type::text = 'Ci::Build'::text AND (retried = false OR retried IS NULL) AND
- (name::text = ANY (ARRAY['sast'::character varying,
- 'dependency_scanning'::character varying,
- 'sast:container'::character varying,
- 'container_scanning'::character varying,
- 'dast'::character varying]::text[]))"
-
- NEW_CLAUSE = "type::text = 'Ci::Build'::text AND (retried = false OR retried IS NULL) AND
- (name::text = ANY (ARRAY['sast'::character varying,
- 'secret_detection'::character varying,
- 'dependency_scanning'::character varying,
- 'container_scanning'::character varying,
- 'dast'::character varying]::text[]))"
-
- def up
- add_concurrent_index :ci_builds, [:commit_id, :artifacts_expire_at, :id], name: NEW_INDEX_NAME, where: NEW_CLAUSE
- remove_concurrent_index_by_name :ci_builds, OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :ci_builds, [:commit_id, :artifacts_expire_at, :id], name: OLD_INDEX_NAME, where: OLD_CLAUSE
- remove_concurrent_index_by_name :ci_builds, NEW_INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200519201128_migrate_vulnerability_dismissal_feedback.rb b/db/post_migrate/20200519201128_migrate_vulnerability_dismissal_feedback.rb
deleted file mode 100644
index fee2f59abb5..00000000000
--- a/db/post_migrate/20200519201128_migrate_vulnerability_dismissal_feedback.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateVulnerabilityDismissalFeedback < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- MIGRATION = 'UpdateVulnerabilitiesFromDismissalFeedback'
- BATCH_SIZE = 500
- DELAY_INTERVAL = 2.minutes.to_i
-
- class Vulnerability < ActiveRecord::Base
- self.table_name = 'vulnerabilities'
- self.inheritance_column = :_type_disabled
-
- include ::EachBatch
- end
-
- def up
- return unless Gitlab.ee?
-
- Vulnerability.select('project_id').group(:project_id).each_batch(of: BATCH_SIZE, column: "project_id") do |project_batch, index|
- batch_delay = (index - 1) * BATCH_SIZE * DELAY_INTERVAL
-
- project_batch.each_with_index do |project, project_batch_index|
- project_delay = project_batch_index * DELAY_INTERVAL
- migrate_in(batch_delay + project_delay, MIGRATION, project[:project_id])
- end
- end
- end
-
- def down
- # nothing to do
- end
-end
diff --git a/db/post_migrate/20200525121014_drop_users_ghost_column.rb b/db/post_migrate/20200525121014_drop_users_ghost_column.rb
deleted file mode 100644
index 1f80bc74b9d..00000000000
--- a/db/post_migrate/20200525121014_drop_users_ghost_column.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class DropUsersGhostColumn < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :users, 'index_users_on_ghost'
-
- with_lock_retries do
- remove_column :users, :ghost
- end
- end
-
- def down
- unless column_exists?(:users, :ghost)
- with_lock_retries do
- add_column :users, :ghost, :boolean # rubocop:disable Migration/AddColumnsToWideTables
- end
- end
-
- execute 'UPDATE users set ghost = TRUE WHERE user_type = 5'
-
- add_concurrent_index :users, :ghost
- end
-end
diff --git a/db/post_migrate/20200525144525_migrate_stuck_import_jobs_queue_to_stuck_project_import_jobs.rb b/db/post_migrate/20200525144525_migrate_stuck_import_jobs_queue_to_stuck_project_import_jobs.rb
deleted file mode 100644
index 57e25c928f1..00000000000
--- a/db/post_migrate/20200525144525_migrate_stuck_import_jobs_queue_to_stuck_project_import_jobs.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateStuckImportJobsQueueToStuckProjectImportJobs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- sidekiq_queue_migrate 'cronjob:stuck_import_jobs', to: 'cronjob:import_stuck_project_import_jobs'
- end
-
- def down
- sidekiq_queue_migrate 'cronjob:import_stuck_project_import_jobs', to: 'cronjob:stuck_import_jobs'
- end
-end
diff --git a/db/post_migrate/20200526000407_seed_repository_storages_weighted.rb b/db/post_migrate/20200526000407_seed_repository_storages_weighted.rb
deleted file mode 100644
index 979f16e75ed..00000000000
--- a/db/post_migrate/20200526000407_seed_repository_storages_weighted.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class SeedRepositoryStoragesWeighted < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- class ApplicationSetting < ActiveRecord::Base
- serialize :repository_storages
- self.table_name = 'application_settings'
- end
-
- def up
- # We need to flush the cache to ensure the newly-added column is loaded
- ApplicationSetting.reset_column_information
-
- # There should only be one row here due to
- # 20200420162730_remove_additional_application_settings_rows.rb
- ApplicationSetting.all.each do |settings|
- storages = Gitlab.config.repositories.storages.keys.collect do |storage|
- weight = settings.repository_storages.include?(storage) ? 100 : 0
- [storage.to_sym, weight]
- end
-
- settings.repository_storages_weighted = Hash[storages]
- settings.save!
- end
- end
-
- def down
- end
-end
diff --git a/db/post_migrate/20200526115436_dedup_mr_metrics.rb b/db/post_migrate/20200526115436_dedup_mr_metrics.rb
deleted file mode 100644
index d2660504939..00000000000
--- a/db/post_migrate/20200526115436_dedup_mr_metrics.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-class DedupMrMetrics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- TMP_INDEX_NAME = 'tmp_unique_merge_request_metrics_by_merge_request_id'
- INDEX_NAME = 'unique_merge_request_metrics_by_merge_request_id'
-
- disable_ddl_transaction!
-
- class MergeRequestMetrics < ActiveRecord::Base
- self.table_name = 'merge_request_metrics'
-
- include EachBatch
- end
-
- def up
- last_metrics_record_id = MergeRequestMetrics.maximum(:id) || 0
-
- # This index will disallow further duplicates while we're deduplicating the data.
- add_concurrent_index(:merge_request_metrics, :merge_request_id, where: "id > #{Integer(last_metrics_record_id)}", unique: true, name: TMP_INDEX_NAME)
-
- MergeRequestMetrics.each_batch do |relation|
- duplicated_merge_request_ids = MergeRequestMetrics
- .where(merge_request_id: relation.select(:merge_request_id))
- .select(:merge_request_id)
- .group(:merge_request_id)
- .having('COUNT(merge_request_metrics.merge_request_id) > 1')
- .pluck(:merge_request_id)
-
- duplicated_merge_request_ids.each do |merge_request_id|
- deduplicate_item(merge_request_id)
- end
- end
-
- add_concurrent_index(:merge_request_metrics, :merge_request_id, unique: true, name: INDEX_NAME)
- remove_concurrent_index_by_name(:merge_request_metrics, TMP_INDEX_NAME)
- end
-
- def down
- remove_concurrent_index_by_name(:merge_request_metrics, TMP_INDEX_NAME)
- remove_concurrent_index_by_name(:merge_request_metrics, INDEX_NAME)
- end
-
- private
-
- def deduplicate_item(merge_request_id)
- merge_request_metrics_records = MergeRequestMetrics.where(merge_request_id: merge_request_id).order(updated_at: :asc).to_a
-
- attributes = {}
- merge_request_metrics_records.each do |merge_request_metrics_record|
- params = merge_request_metrics_record.attributes.except('id')
- attributes.merge!(params.compact)
- end
-
- ActiveRecord::Base.transaction do
- record_to_keep = merge_request_metrics_records.pop
- records_to_delete = merge_request_metrics_records
-
- MergeRequestMetrics.where(id: records_to_delete.map(&:id)).delete_all
- record_to_keep.update!(attributes)
- end
- end
-end
diff --git a/db/post_migrate/20200527094322_drop_vulnerability_confidence_index.rb b/db/post_migrate/20200527094322_drop_vulnerability_confidence_index.rb
deleted file mode 100644
index e9a9dd5eff8..00000000000
--- a/db/post_migrate/20200527094322_drop_vulnerability_confidence_index.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class DropVulnerabilityConfidenceIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
- INDEX_NAME = 'index_vulnerability_on_id_and_confidence_eq_zero'
-
- def up
- Gitlab::BackgroundMigration.steal('RemoveUndefinedVulnerabilityConfidenceLevel')
-
- remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
- end
-
- def down
- add_concurrent_index(:vulnerabilities, :id, where: 'confidence = 0', name: INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200527095401_drop_vulnerability_occurrence_confidence_index.rb b/db/post_migrate/20200527095401_drop_vulnerability_occurrence_confidence_index.rb
deleted file mode 100644
index 99fe4da7686..00000000000
--- a/db/post_migrate/20200527095401_drop_vulnerability_occurrence_confidence_index.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class DropVulnerabilityOccurrenceConfidenceIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
- INDEX_NAME = 'index_vulnerability_occurrences_on_id_and_confidence_eq_zero'
-
- def up
- Gitlab::BackgroundMigration.steal('RemoveUndefinedOccurrenceConfidenceLevel')
-
- remove_concurrent_index_by_name :vulnerability_occurrences, INDEX_NAME
- end
-
- def down
- add_concurrent_index(:vulnerability_occurrences, :id, where: 'confidence = 0', name: INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200528123703_add_merge_request_partial_index_to_events.rb b/db/post_migrate/20200528123703_add_merge_request_partial_index_to_events.rb
deleted file mode 100644
index bf2269e77ab..00000000000
--- a/db/post_migrate/20200528123703_add_merge_request_partial_index_to_events.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class AddMergeRequestPartialIndexToEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'index_events_on_author_id_and_created_at_merge_requests'
-
- def up
- add_concurrent_index(
- :events,
- [:author_id, :created_at],
- name: INDEX_NAME,
- where: "(target_type = 'MergeRequest')"
- )
- end
-
- def down
- remove_concurrent_index :events, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200601120434_migrate_all_merge_request_user_mentions_to_db.rb b/db/post_migrate/20200601120434_migrate_all_merge_request_user_mentions_to_db.rb
deleted file mode 100644
index fc7b9afe5f9..00000000000
--- a/db/post_migrate/20200601120434_migrate_all_merge_request_user_mentions_to_db.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateAllMergeRequestUserMentionsToDb < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- DELAY = 2.minutes.to_i
- BATCH_SIZE = 100_000
- MIGRATION = 'UserMentions::CreateResourceUserMention'
-
- JOIN = "LEFT JOIN merge_request_user_mentions on merge_requests.id = merge_request_user_mentions.merge_request_id"
- QUERY_CONDITIONS = "(description LIKE '%@%' OR title LIKE '%@%') AND merge_request_user_mentions.merge_request_id IS NULL"
-
- disable_ddl_transaction!
-
- class MergeRequest < ActiveRecord::Base
- include EachBatch
- end
-
- def up
- delay = DELAY
-
- MergeRequest.each_batch(of: BATCH_SIZE) do |batch, _|
- range = batch.pluck('MIN(merge_requests.id)', 'MAX(merge_requests.id)').first
- records_count = MergeRequest.joins(JOIN).where(QUERY_CONDITIONS).where(id: range.first..range.last).count
-
- if records_count > 0
- migrate_in(delay, MIGRATION, ['MergeRequest', JOIN, QUERY_CONDITIONS, false, *range])
- delay += [DELAY, (records_count / 500 + 1).minutes.to_i].max
- end
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200602013900_add_limit_to_designs_filename.rb b/db/post_migrate/20200602013900_add_limit_to_designs_filename.rb
deleted file mode 100644
index 88732648965..00000000000
--- a/db/post_migrate/20200602013900_add_limit_to_designs_filename.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddLimitToDesignsFilename < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit(:design_management_designs, :filename, 255, validate: false)
- end
-
- def down
- remove_text_limit(:design_management_designs, :filename)
- end
-end
diff --git a/db/post_migrate/20200602013901_cap_designs_filename_length_to_new_limit.rb b/db/post_migrate/20200602013901_cap_designs_filename_length_to_new_limit.rb
deleted file mode 100644
index 0458481c6bd..00000000000
--- a/db/post_migrate/20200602013901_cap_designs_filename_length_to_new_limit.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-class CapDesignsFilenameLengthToNewLimit < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- CHAR_LENGTH = 255
- MODIFIED_NAME = 'gitlab-modified-'
- MODIFIED_EXTENSION = '.jpg'
-
- def up
- arel_table = Arel::Table.new(:design_management_designs)
-
- # Design filenames larger than the limit will be renamed to "gitlab-modified-{id}.jpg",
- # which will be valid and unique. The design file itself will appear broken, as it is
- # understood that no designs with filenames that exceed this limit will be legitimate.
- # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33565/diffs#note_355789080
- new_value_clause = Arel::Nodes::NamedFunction.new(
- 'CONCAT',
- [
- Arel::Nodes.build_quoted(MODIFIED_NAME),
- arel_table[:id],
- Arel::Nodes.build_quoted(MODIFIED_EXTENSION)
- ]
- )
- where_clause = Arel::Nodes::NamedFunction.new(
- 'CHAR_LENGTH',
- [arel_table[:filename]]
- ).gt(CHAR_LENGTH)
-
- update_arel = Arel::UpdateManager.new.table(arel_table)
- .set([[arel_table[:filename], new_value_clause]])
- .where(where_clause)
-
- ActiveRecord::Base.connection.execute(update_arel.to_sql)
- end
-
- def down
- # no-op : the original filename is lost forever
- end
-end
diff --git a/db/post_migrate/20200602143020_update_routes_for_lost_and_found_group_and_orphaned_projects.rb b/db/post_migrate/20200602143020_update_routes_for_lost_and_found_group_and_orphaned_projects.rb
deleted file mode 100644
index 2b036a8da80..00000000000
--- a/db/post_migrate/20200602143020_update_routes_for_lost_and_found_group_and_orphaned_projects.rb
+++ /dev/null
@@ -1,188 +0,0 @@
-# frozen_string_literal: true
-
-# This migration adds or updates the routes for all the entities affected by
-# post-migration '20200511083541_cleanup_projects_with_missing_namespace'
-# - A route is added for the 'lost-and-found' group
-# - A route is added for the Ghost user (if not already defined)
-# - The routes for all the orphaned projects that were moved under the 'lost-and-found'
-# group are updated to reflect the new path
-class UpdateRoutesForLostAndFoundGroupAndOrphanedProjects < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- class User < ActiveRecord::Base
- self.table_name = 'users'
-
- LOST_AND_FOUND_GROUP = 'lost-and-found'
- USER_TYPE_GHOST = 5
- ACCESS_LEVEL_OWNER = 50
-
- has_one :namespace, -> { where(type: nil) },
- foreign_key: :owner_id, inverse_of: :owner, autosave: true,
- class_name: 'UpdateRoutesForLostAndFoundGroupAndOrphanedProjects::Namespace'
-
- def lost_and_found_group
- # Find the 'lost-and-found' group
- # There should only be one Group owned by the Ghost user starting with 'lost-and-found'
- Group
- .joins('INNER JOIN members ON namespaces.id = members.source_id')
- .where(namespaces: { type: 'Group' })
- .where(members: { type: 'GroupMember' })
- .where(members: { source_type: 'Namespace' })
- .where(members: { user_id: self.id })
- .where(members: { access_level: ACCESS_LEVEL_OWNER })
- .find_by(Group.arel_table[:name].matches("#{LOST_AND_FOUND_GROUP}%"))
- end
-
- class << self
- # Return the ghost user
- def ghost
- User.find_by(user_type: USER_TYPE_GHOST)
- end
- end
- end
-
- # Temporary Concern to not repeat the same methods twice
- module HasPath
- extend ActiveSupport::Concern
-
- def full_path
- if parent && path
- parent.full_path + '/' + path
- else
- path
- end
- end
-
- def full_name
- if parent && name
- parent.full_name + ' / ' + name
- else
- name
- end
- end
- end
-
- class Namespace < ActiveRecord::Base
- include HasPath
-
- self.table_name = 'namespaces'
-
- belongs_to :owner, class_name: 'UpdateRoutesForLostAndFoundGroupAndOrphanedProjects::User'
- belongs_to :parent, class_name: "UpdateRoutesForLostAndFoundGroupAndOrphanedProjects::Namespace"
- has_many :children, foreign_key: :parent_id,
- class_name: "UpdateRoutesForLostAndFoundGroupAndOrphanedProjects::Namespace"
- has_many :projects, class_name: "UpdateRoutesForLostAndFoundGroupAndOrphanedProjects::Project"
-
- def ensure_route!
- unless Route.for_source('Namespace', self.id)
- Route.create!(
- source_id: self.id,
- source_type: 'Namespace',
- path: self.full_path,
- name: self.full_name
- )
- end
- end
-
- def generate_unique_path
- # Generate a unique path if there is no route for the namespace
- # (an existing route guarantees that the path is already unique)
- unless Route.for_source('Namespace', self.id)
- self.path = Uniquify.new.string(self.path) do |str|
- Route.where(path: str).exists?
- end
- end
- end
- end
-
- class Group < Namespace
- # Disable STI to allow us to manually set "type = 'Group'"
- # Otherwise rails forces "type = CleanupProjectsWithMissingNamespace::Group"
- self.inheritance_column = :_type_disabled
- end
-
- class Route < ActiveRecord::Base
- self.table_name = 'routes'
-
- def self.for_source(source_type, source_id)
- Route.find_by(source_type: source_type, source_id: source_id)
- end
- end
-
- class Project < ActiveRecord::Base
- include HasPath
-
- self.table_name = 'projects'
-
- belongs_to :group, -> { where(type: 'Group') }, foreign_key: 'namespace_id',
- class_name: "UpdateRoutesForLostAndFoundGroupAndOrphanedProjects::Group"
- belongs_to :namespace,
- class_name: "UpdateRoutesForLostAndFoundGroupAndOrphanedProjects::Namespace"
-
- alias_method :parent, :namespace
- alias_attribute :parent_id, :namespace_id
-
- def ensure_route!
- Route.find_or_initialize_by(source_type: 'Project', source_id: self.id).tap do |record|
- record.path = self.full_path
- record.name = self.full_name
- record.save!
- end
- end
- end
-
- def up
- # Reset the column information of all the models that update the database
- # to ensure the Active Record's knowledge of the table structure is current
- Namespace.reset_column_information
- Route.reset_column_information
- User.reset_column_information
-
- # Find the ghost user, its namespace and the "lost and found" group
- ghost_user = User.ghost
- return unless ghost_user # No reason to continue if there is no Ghost user
-
- ghost_namespace = ghost_user.namespace
- lost_and_found_group = ghost_user.lost_and_found_group
-
- # No reason to continue if there is no 'lost-and-found' group
- # 1. No orphaned projects were found in this instance, or
- # 2. The 'lost-and-found' group and the orphaned projects have been already deleted
- return unless lost_and_found_group
-
- # Update the 'lost-and-found' group description to be more self-explanatory
- lost_and_found_group.generate_unique_path
- lost_and_found_group.description =
- 'Group for storing projects that were not properly deleted. '\
- 'It should be considered as a system level Group with non-working '\
- 'projects inside it. The contents may be deleted with a future update. '\
- 'More info: gitlab.com/gitlab-org/gitlab/-/issues/198603'
- lost_and_found_group.save!
-
- # make sure that the ghost namespace has a unique path
- ghost_namespace.generate_unique_path
-
- if ghost_namespace.path_changed?
- ghost_namespace.save!
- # If the path changed, also update the Ghost User's username to match the new path.
- ghost_user.update!(username: ghost_namespace.path)
- end
-
- # Update the routes for the Ghost user, the "lost and found" group
- # and all the orphaned projects
- ghost_namespace.ensure_route!
- lost_and_found_group.ensure_route!
-
- # The following does a fast index scan by namespace_id
- # No reason to process in batches:
- # - 66 projects in GitLab.com, less than 1ms execution time to fetch them
- # with a constant update time for each
- lost_and_found_group.projects.each do |project|
- project.ensure_route!
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200608072931_backfill_imported_snippet_repositories.rb b/db/post_migrate/20200608072931_backfill_imported_snippet_repositories.rb
deleted file mode 100644
index 0566524fa90..00000000000
--- a/db/post_migrate/20200608072931_backfill_imported_snippet_repositories.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillImportedSnippetRepositories < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- DELAY_INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 200
- MIGRATION = 'BackfillSnippetRepositories'
-
- disable_ddl_transaction!
-
- class Snippet < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'snippets'
- self.inheritance_column = :_type_disabled
- end
-
- class SnippetRepository < ActiveRecord::Base
- self.table_name = 'snippet_repositories'
- end
-
- def up
- index = 1
-
- Snippet.select(:id).where.not(id: SnippetRepository.select(:snippet_id)).each_batch(of: BATCH_SIZE, column: 'id') do |batch|
- split_in_consecutive_batches(batch).each do |ids_batch|
- migrate_in(index * DELAY_INTERVAL, MIGRATION, [ids_batch.first, ids_batch.last])
-
- index += 1
- end
- end
- end
-
- def down
- # no-op
- end
-
- private
-
- def split_in_consecutive_batches(relation)
- ids = relation.pluck(:id)
-
- (ids.first..ids.last).to_a.split {|i| !ids.include?(i) }.select(&:present?)
- end
-end
diff --git a/db/post_migrate/20200608075553_add_index_on_user_id_and_created_at_and_source_to_ci_pipelines.rb b/db/post_migrate/20200608075553_add_index_on_user_id_and_created_at_and_source_to_ci_pipelines.rb
deleted file mode 100644
index 5df9cacdff6..00000000000
--- a/db/post_migrate/20200608075553_add_index_on_user_id_and_created_at_and_source_to_ci_pipelines.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnUserIdAndCreatedAtAndSourceToCiPipelines < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_pipelines, [:user_id, :created_at, :source]
- remove_concurrent_index :ci_pipelines, [:user_id, :created_at]
- end
-
- def down
- add_concurrent_index :ci_pipelines, [:user_id, :created_at]
- remove_concurrent_index :ci_pipelines, [:user_id, :created_at, :source]
- end
-end
diff --git a/db/post_migrate/20200608195222_set_lock_version_not_null_constraint.rb b/db/post_migrate/20200608195222_set_lock_version_not_null_constraint.rb
deleted file mode 100644
index ec72053b307..00000000000
--- a/db/post_migrate/20200608195222_set_lock_version_not_null_constraint.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class SetLockVersionNotNullConstraint < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- TABLES = %i(epics merge_requests issues ci_stages ci_builds ci_pipelines).freeze
-
- def up
- TABLES.each do |table|
- add_not_null_constraint table, :lock_version, validate: false
- end
- end
-
- def down
- TABLES.each do |table|
- remove_not_null_constraint table, :lock_version
- end
- end
-end
diff --git a/db/post_migrate/20200608203426_set_proper_lock_version_indices.rb b/db/post_migrate/20200608203426_set_proper_lock_version_indices.rb
deleted file mode 100644
index 924ca73e6cc..00000000000
--- a/db/post_migrate/20200608203426_set_proper_lock_version_indices.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class SetProperLockVersionIndices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index :epics, :lock_version, where: "lock_version IS NULL"
- remove_concurrent_index :merge_requests, :lock_version, where: "lock_version IS NULL"
- remove_concurrent_index :issues, :lock_version, where: "lock_version IS NULL"
-
- add_concurrent_index :epics, :id, where: "lock_version IS NULL", name: 'index_epics_on_id'
- add_concurrent_index :merge_requests, :id, where: "lock_version IS NULL", name: 'index_merge_requests_on_id'
- add_concurrent_index :issues, :id, where: "lock_version IS NULL", name: 'index_issues_on_id'
- end
-
- def down
- add_concurrent_index :epics, :lock_version, where: "lock_version IS NULL"
- add_concurrent_index :merge_requests, :lock_version, where: "lock_version IS NULL"
- add_concurrent_index :issues, :lock_version, where: "lock_version IS NULL"
-
- remove_concurrent_index_by_name :epics, name: 'index_epics_on_id'
- remove_concurrent_index_by_name :merge_requests, name: 'index_merge_requests_on_id'
- remove_concurrent_index_by_name :issues, name: 'index_issues_on_id'
- end
-end
diff --git a/db/post_migrate/20200608205813_set_lock_version_to_not_null.rb b/db/post_migrate/20200608205813_set_lock_version_to_not_null.rb
deleted file mode 100644
index 69f43a8decf..00000000000
--- a/db/post_migrate/20200608205813_set_lock_version_to_not_null.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class SetLockVersionToNotNull < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- TABLES = %w(epics merge_requests issues ci_stages ci_builds ci_pipelines).freeze
- BATCH_SIZE = 10_000
-
- disable_ddl_transaction!
-
- def declare_class(table)
- Class.new(ActiveRecord::Base) do
- include EachBatch
-
- self.table_name = table
- self.inheritance_column = :_type_disabled # Disable STI
- end
- end
-
- def up
- TABLES.each do |table|
- declare_class(table).where(lock_version: nil).each_batch(of: BATCH_SIZE) do |batch|
- batch.update_all(lock_version: 0)
- end
- end
- end
-
- def down
- # Nothing to do...
- end
-end
diff --git a/db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb b/db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb
deleted file mode 100644
index aafa6a83200..00000000000
--- a/db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class LockVersionCleanupForEpics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :epics, :lock_version
- remove_concurrent_index_by_name :epics, name: 'index_epics_on_id'
- end
-
- def down
- add_concurrent_index :epics, :id, where: "lock_version IS NULL", name: 'index_epics_on_id'
- end
-end
diff --git a/db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb b/db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb
deleted file mode 100644
index cb8ab86b6a3..00000000000
--- a/db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class LockVersionCleanupForMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :merge_requests, :lock_version
- remove_concurrent_index_by_name :merge_requests, name: 'index_merge_requests_on_id'
- end
-
- def down
- add_concurrent_index :merge_requests, :id, where: "lock_version IS NULL", name: 'index_merge_requests_on_id'
- end
-end
diff --git a/db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb b/db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb
deleted file mode 100644
index ad3fea8b131..00000000000
--- a/db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class LockVersionCleanupForIssues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :issues, :lock_version
- remove_concurrent_index_by_name :issues, name: 'index_issues_on_id'
- end
-
- def down
- add_concurrent_index :issues, :id, where: "lock_version IS NULL", name: 'index_issues_on_id'
- end
-end
diff --git a/db/post_migrate/20200608212652_lock_version_cleanup_for_ci_stages.rb b/db/post_migrate/20200608212652_lock_version_cleanup_for_ci_stages.rb
deleted file mode 100644
index 12e2897123e..00000000000
--- a/db/post_migrate/20200608212652_lock_version_cleanup_for_ci_stages.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class LockVersionCleanupForCiStages < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :ci_stages, :lock_version
- remove_concurrent_index :ci_stages, :id, where: "lock_version IS NULL", name: "tmp_index_ci_stages_lock_version"
- end
-
- def down
- add_concurrent_index :ci_stages, :id, where: "lock_version IS NULL", name: "tmp_index_ci_stages_lock_version"
- end
-end
diff --git a/db/post_migrate/20200608212807_lock_version_cleanup_for_ci_builds.rb b/db/post_migrate/20200608212807_lock_version_cleanup_for_ci_builds.rb
deleted file mode 100644
index 0512869971b..00000000000
--- a/db/post_migrate/20200608212807_lock_version_cleanup_for_ci_builds.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class LockVersionCleanupForCiBuilds < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :ci_builds, :lock_version
- remove_concurrent_index :ci_builds, :id, where: "lock_version IS NULL", name: "tmp_index_ci_builds_lock_version"
- end
-
- def down
- add_concurrent_index :ci_builds, :id, where: "lock_version IS NULL", name: "tmp_index_ci_builds_lock_version"
- end
-end
diff --git a/db/post_migrate/20200608212824_lock_version_cleanup_for_ci_pipelines.rb b/db/post_migrate/20200608212824_lock_version_cleanup_for_ci_pipelines.rb
deleted file mode 100644
index 228dd72da8d..00000000000
--- a/db/post_migrate/20200608212824_lock_version_cleanup_for_ci_pipelines.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class LockVersionCleanupForCiPipelines < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :ci_pipelines, :lock_version
- remove_concurrent_index :ci_pipelines, :id, where: "lock_version IS NULL", name: "tmp_index_ci_pipelines_lock_version"
- end
-
- def down
- add_concurrent_index :ci_pipelines, :id, where: "lock_version IS NULL", name: "tmp_index_ci_pipelines_lock_version"
- end
-end
diff --git a/db/post_migrate/20200609002841_add_partial_index_on_locked_state_id_to_merge_requests.rb b/db/post_migrate/20200609002841_add_partial_index_on_locked_state_id_to_merge_requests.rb
deleted file mode 100644
index 7602ad00796..00000000000
--- a/db/post_migrate/20200609002841_add_partial_index_on_locked_state_id_to_merge_requests.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddPartialIndexOnLockedStateIdToMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = "idx_merge_requests_on_target_project_id_and_locked_state"
- LOCKED_STATE_ID = 4
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :merge_requests, :target_project_id, where: "(state_id = #{LOCKED_STATE_ID})", name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :merge_requests, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200615111857_unconfirm_wrongfully_verified_emails.rb b/db/post_migrate/20200615111857_unconfirm_wrongfully_verified_emails.rb
deleted file mode 100644
index 62fdfc783bc..00000000000
--- a/db/post_migrate/20200615111857_unconfirm_wrongfully_verified_emails.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-class UnconfirmWrongfullyVerifiedEmails < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INTERVAL = 5.minutes.to_i
- BATCH_SIZE = 500
- MIGRATION = 'WrongfullyConfirmedEmailUnconfirmer'
- EMAIL_INDEX_NAME = 'tmp_index_for_email_unconfirmation_migration'
-
- class ApplicationSetting < ActiveRecord::Base
- self.table_name = 'application_settings'
- end
-
- class Email < ActiveRecord::Base
- include EachBatch
- end
-
- def up
- add_concurrent_index :emails, :id, where: 'confirmed_at IS NOT NULL', name: EMAIL_INDEX_NAME
-
- ApplicationSetting.reset_column_information
-
- setting_record = ApplicationSetting.last
- return unless setting_record&.send_user_confirmation_email
-
- queue_background_migration_jobs_by_range_at_intervals(Email,
- MIGRATION,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- remove_concurrent_index_by_name(:emails, EMAIL_INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200617001637_validate_file_store_not_null_constraint_on_lfs_objects.rb b/db/post_migrate/20200617001637_validate_file_store_not_null_constraint_on_lfs_objects.rb
deleted file mode 100644
index 27a30b1d696..00000000000
--- a/db/post_migrate/20200617001637_validate_file_store_not_null_constraint_on_lfs_objects.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateFileStoreNotNullConstraintOnLfsObjects < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_check_constraint(:lfs_objects, :check_eecfc5717d)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200617001848_validate_store_not_null_constraint_uploads.rb b/db/post_migrate/20200617001848_validate_store_not_null_constraint_uploads.rb
deleted file mode 100644
index 83cb6cb3e85..00000000000
--- a/db/post_migrate/20200617001848_validate_store_not_null_constraint_uploads.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateStoreNotNullConstraintUploads < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_check_constraint(:uploads, :check_5e9547379c)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200617002030_validate_file_store_not_null_constraint_on_ci_job_artifacts.rb b/db/post_migrate/20200617002030_validate_file_store_not_null_constraint_on_ci_job_artifacts.rb
deleted file mode 100644
index 8e766a508b7..00000000000
--- a/db/post_migrate/20200617002030_validate_file_store_not_null_constraint_on_ci_job_artifacts.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateFileStoreNotNullConstraintOnCiJobArtifacts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_check_constraint(:ci_job_artifacts, :check_27f0f6dbab)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200618152212_update_secure_smau_index.rb b/db/post_migrate/20200618152212_update_secure_smau_index.rb
deleted file mode 100644
index ba989c279be..00000000000
--- a/db/post_migrate/20200618152212_update_secure_smau_index.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateSecureSmauIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_secure_ci_builds_on_user_id_created_at'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(
- :ci_builds,
- [:user_id, :created_at],
- where: "(((type)::text = 'Ci::Build'::text) AND ((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('license_scanning'::character varying)::text, ('sast'::character varying)::text, ('secret_detection'::character varying)::text])))",
- name: INDEX_NAME
- )
- end
-
- def down
- remove_concurrent_index_by_name :ci_builds, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200623142159_remove_gitlab_issue_tracker_service_records.rb b/db/post_migrate/20200623142159_remove_gitlab_issue_tracker_service_records.rb
deleted file mode 100644
index 743499e7b76..00000000000
--- a/db/post_migrate/20200623142159_remove_gitlab_issue_tracker_service_records.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveGitlabIssueTrackerServiceRecords < ActiveRecord::Migration[6.0]
- DOWNTIME = false
- BATCH_SIZE = 5000
-
- disable_ddl_transaction!
-
- class Service < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'services'
-
- def self.gitlab_issue_tracker_service
- where(type: 'GitlabIssueTrackerService')
- end
- end
-
- def up
- Service.each_batch(of: BATCH_SIZE) do |services|
- services.gitlab_issue_tracker_service.delete_all
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200626060151_add_disable_overriding_approvers_per_merge_request_indices.rb b/db/post_migrate/20200626060151_add_disable_overriding_approvers_per_merge_request_indices.rb
deleted file mode 100644
index 6f2db4035e2..00000000000
--- a/db/post_migrate/20200626060151_add_disable_overriding_approvers_per_merge_request_indices.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class AddDisableOverridingApproversPerMergeRequestIndices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- DISABLE_OVERRIDING_APPROVERS_TRUE_INDEX_NAME = "idx_projects_id_created_at_disable_overriding_approvers_true"
- DISABLE_OVERRIDING_APPROVERS_FALSE_INDEX_NAME = "idx_projects_id_created_at_disable_overriding_approvers_false"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :projects, [:id, :created_at],
- where: "disable_overriding_approvers_per_merge_request = TRUE",
- name: DISABLE_OVERRIDING_APPROVERS_TRUE_INDEX_NAME
-
- add_concurrent_index :projects, [:id, :created_at],
- where: "(disable_overriding_approvers_per_merge_request = FALSE) OR (disable_overriding_approvers_per_merge_request IS NULL)",
- name: DISABLE_OVERRIDING_APPROVERS_FALSE_INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :projects, DISABLE_OVERRIDING_APPROVERS_TRUE_INDEX_NAME
- remove_concurrent_index_by_name :projects, DISABLE_OVERRIDING_APPROVERS_FALSE_INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200701070435_add_default_value_stream_to_groups_with_group_stages.rb b/db/post_migrate/20200701070435_add_default_value_stream_to_groups_with_group_stages.rb
deleted file mode 100644
index 971eb3c489f..00000000000
--- a/db/post_migrate/20200701070435_add_default_value_stream_to_groups_with_group_stages.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-class AddDefaultValueStreamToGroupsWithGroupStages < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- class Group < ActiveRecord::Base
- def self.find_sti_class(typename)
- if typename == 'Group'
- Group
- else
- super
- end
- end
- self.table_name = 'namespaces'
- has_many :group_value_streams
- has_many :group_stages
- end
-
- class GroupValueStream < ActiveRecord::Base
- self.table_name = 'analytics_cycle_analytics_group_value_streams'
- has_many :group_stages
- belongs_to :group
- end
-
- class GroupStage < ActiveRecord::Base
- self.table_name = 'analytics_cycle_analytics_group_stages'
- belongs_to :group_value_stream
- end
-
- def up
- Group.where(type: 'Group').joins(:group_stages).distinct.find_each do |group|
- Group.transaction do
- group_value_stream = group.group_value_streams.first_or_create!(name: 'default')
- group.group_stages.update_all(group_value_stream_id: group_value_stream.id)
- end
- end
-
- change_column_null :analytics_cycle_analytics_group_stages, :group_value_stream_id, false
- end
-
- def down
- change_column_null :analytics_cycle_analytics_group_stages, :group_value_stream_id, true
-
- GroupValueStream.where(name: 'default').includes(:group_stages).find_each do |value_stream|
- GroupValueStream.transaction do
- value_stream.group_stages.update_all(group_value_stream_id: nil)
- value_stream.destroy!
- end
- end
- end
-end
diff --git a/db/post_migrate/20200701091253_validate_foreign_key_on_cycle_analytics_group_stages.rb b/db/post_migrate/20200701091253_validate_foreign_key_on_cycle_analytics_group_stages.rb
deleted file mode 100644
index 0a8926ed6de..00000000000
--- a/db/post_migrate/20200701091253_validate_foreign_key_on_cycle_analytics_group_stages.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateForeignKeyOnCycleAnalyticsGroupStages < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- # same as in db/migrate/20200701064756_add_not_valid_foreign_key_to_cycle_analytics_group_stages.rb
- CONSTRAINT_NAME = 'fk_analytics_cycle_analytics_group_stages_group_value_stream_id'
-
- def up
- validate_foreign_key :analytics_cycle_analytics_group_stages, :group_value_stream_id, name: CONSTRAINT_NAME
- end
-
- def down
- remove_foreign_key_if_exists :analytics_cycle_analytics_group_stages, column: :group_value_stream_id, name: CONSTRAINT_NAME
- add_foreign_key :analytics_cycle_analytics_group_stages, :analytics_cycle_analytics_group_value_streams,
- column: :group_value_stream_id, name: CONSTRAINT_NAME, on_delete: :cascade, validate: false
- end
-end
diff --git a/db/post_migrate/20200703064117_generate_missing_routes_for_bots.rb b/db/post_migrate/20200703064117_generate_missing_routes_for_bots.rb
deleted file mode 100644
index 1d3f57d3fe6..00000000000
--- a/db/post_migrate/20200703064117_generate_missing_routes_for_bots.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-# frozen_string_literal: true
-
-class GenerateMissingRoutesForBots < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- class User < ActiveRecord::Base
- self.table_name = 'users'
-
- USER_TYPES = {
- human: nil,
- support_bot: 1,
- alert_bot: 2,
- visual_review_bot: 3,
- service_user: 4,
- ghost: 5,
- project_bot: 6,
- migration_bot: 7
- }.with_indifferent_access.freeze
-
- BOT_USER_TYPES = %w[alert_bot project_bot support_bot visual_review_bot migration_bot].freeze
-
- scope :bots, -> { where(user_type: USER_TYPES.values_at(*BOT_USER_TYPES)) }
- end
-
- class Route < ActiveRecord::Base
- self.table_name = 'routes'
-
- validates :path,
- uniqueness: { case_sensitive: false }
- end
-
- class Namespace < ActiveRecord::Base
- self.table_name = 'namespaces'
-
- belongs_to :owner, class_name: 'GenerateMissingRoutesForBots::User'
-
- scope :for_user, -> { where(type: nil) }
- scope :for_bots, -> { for_user.joins(:owner).merge(GenerateMissingRoutesForBots::User.bots) }
-
- scope :without_routes, -> do
- where(
- 'NOT EXISTS (
- SELECT 1
- FROM routes
- WHERE source_type = ?
- AND source_id = namespaces.id
- )',
- self.source_type_for_route
- )
- end
-
- def self.source_type_for_route
- 'Namespace'
- end
-
- def attributes_for_insert
- {
- source_type: self.class.source_type_for_route,
- source_id: id,
- name: name,
- path: path
- }
- end
- end
-
- def up
- # Reset the column information of all the models that update the database
- # to ensure the Active Record's knowledge of the table structure is current
- Route.reset_column_information
-
- logger = Gitlab::BackgroundMigration::Logger.build
- attributes_to_be_logged = %w(id path name)
-
- GenerateMissingRoutesForBots::Namespace.for_bots.without_routes.each do |namespace|
- route = GenerateMissingRoutesForBots::Route.create(namespace.attributes_for_insert)
- namespace_details = namespace.as_json.slice(*attributes_to_be_logged)
-
- if route.persisted?
- logger.info namespace_details.merge(message: 'a new route was created for the namespace')
- else
- errors = route.errors.full_messages.join(',')
- logger.info namespace_details.merge(message: 'route creation failed for the namespace', errors: errors)
- end
- end
- end
-
- def down
- # no op
- end
-end
diff --git a/db/post_migrate/20200703125016_backfill_namespace_settings.rb b/db/post_migrate/20200703125016_backfill_namespace_settings.rb
deleted file mode 100644
index a7335e2d2b8..00000000000
--- a/db/post_migrate/20200703125016_backfill_namespace_settings.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillNamespaceSettings < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- MIGRATION = 'BackfillNamespaceSettings'
- DELAY_INTERVAL = 2.minutes
- BATCH_SIZE = 10_000
-
- disable_ddl_transaction!
-
- class Namespace < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'namespaces'
- end
-
- def up
- say "Scheduling `#{MIGRATION}` jobs"
-
- queue_background_migration_jobs_by_range_at_intervals(Namespace, MIGRATION, DELAY_INTERVAL, batch_size: BATCH_SIZE)
- end
-
- def down
- # NOOP
- end
-end
diff --git a/db/post_migrate/20200703165434_drop_temporary_table_untracked_files_for_uploads_if_exists.rb b/db/post_migrate/20200703165434_drop_temporary_table_untracked_files_for_uploads_if_exists.rb
deleted file mode 100644
index 1f34a05227d..00000000000
--- a/db/post_migrate/20200703165434_drop_temporary_table_untracked_files_for_uploads_if_exists.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class DropTemporaryTableUntrackedFilesForUploadsIfExists < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute 'DROP TABLE IF EXISTS untracked_files_for_uploads'
- end
-
- def down
- # no-op - this table should not exist
- end
-end
diff --git a/db/post_migrate/20200704143633_add_index_on_user_id_and_created_at_where_source_to_ci_pipelines.rb b/db/post_migrate/20200704143633_add_index_on_user_id_and_created_at_where_source_to_ci_pipelines.rb
deleted file mode 100644
index d84b2b4cad3..00000000000
--- a/db/post_migrate/20200704143633_add_index_on_user_id_and_created_at_where_source_to_ci_pipelines.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnUserIdAndCreatedAtWhereSourceToCiPipelines < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_pipelines, [:user_id, :created_at, :config_source]
- end
-
- def down
- remove_concurrent_index :ci_pipelines, [:user_id, :created_at, :config_source]
- end
-end
diff --git a/db/post_migrate/20200704161600_add_index_on_id_and_status_and_created_at_to_deployments.rb b/db/post_migrate/20200704161600_add_index_on_id_and_status_and_created_at_to_deployments.rb
deleted file mode 100644
index 3aab2fd2949..00000000000
--- a/db/post_migrate/20200704161600_add_index_on_id_and_status_and_created_at_to_deployments.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnIdAndStatusAndCreatedAtToDeployments < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :deployments, [:id, :status, :created_at]
- remove_concurrent_index :deployments, [:id, :status]
- end
-
- def down
- add_concurrent_index :deployments, [:id, :status]
- remove_concurrent_index :deployments, [:id, :status, :created_at]
- end
-end
diff --git a/db/post_migrate/20200706154619_drop_ci_daily_report_results_table.rb b/db/post_migrate/20200706154619_drop_ci_daily_report_results_table.rb
deleted file mode 100644
index c6ce52012d6..00000000000
--- a/db/post_migrate/20200706154619_drop_ci_daily_report_results_table.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class DropCiDailyReportResultsTable < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- drop_table :ci_daily_report_results
- end
-
- def down
- create_table :ci_daily_report_results do |t|
- t.date :date, null: false
- t.bigint :project_id, null: false
- t.bigint :last_pipeline_id, null: false
- t.float :value, null: false
- t.integer :param_type, limit: 8, null: false
- t.string :ref_path, null: false
- t.string :title, null: false
-
- t.index :last_pipeline_id
- t.index [:project_id, :ref_path, :param_type, :date, :title], name: 'index_daily_report_results_unique_columns', unique: true
- end
- end
-end
diff --git a/db/post_migrate/20200709101408_schedule_populate_project_snippet_statistics.rb b/db/post_migrate/20200709101408_schedule_populate_project_snippet_statistics.rb
deleted file mode 100644
index 28527e67f4a..00000000000
--- a/db/post_migrate/20200709101408_schedule_populate_project_snippet_statistics.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class SchedulePopulateProjectSnippetStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- DELAY_INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 500
- MIGRATION = 'PopulateProjectSnippetStatistics'
-
- disable_ddl_transaction!
-
- def up
- snippets = exec_query <<~SQL
- SELECT snippets.id
- FROM snippets
- INNER JOIN projects ON projects.id = snippets.project_id
- WHERE snippets.type = 'ProjectSnippet'
- ORDER BY projects.namespace_id ASC, snippets.project_id ASC, snippets.id ASC
- SQL
-
- snippets.rows.flatten.in_groups_of(BATCH_SIZE, false).each_with_index do |snippet_ids, index|
- migrate_in(index * DELAY_INTERVAL, MIGRATION, [snippet_ids])
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200710102418_delete_user_callout_alerts_moved.rb b/db/post_migrate/20200710102418_delete_user_callout_alerts_moved.rb
deleted file mode 100644
index ac605ba494e..00000000000
--- a/db/post_migrate/20200710102418_delete_user_callout_alerts_moved.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class DeleteUserCalloutAlertsMoved < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- class UserCallout < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'user_callouts'
- end
-
- BATCH_SIZE = 1_000
-
- # Inlined from Enums::UserCallout.feature_names
- FEATURE_NAME_ALERTS_MOVED = 20
-
- def up
- UserCallout.each_batch(of: BATCH_SIZE, column: :user_id) do |callout|
- callout.where(feature_name: FEATURE_NAME_ALERTS_MOVED).delete_all
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200710102846_drop_index_ruby_objects_in_details_on_audit_events.rb b/db/post_migrate/20200710102846_drop_index_ruby_objects_in_details_on_audit_events.rb
deleted file mode 100644
index 6869938466a..00000000000
--- a/db/post_migrate/20200710102846_drop_index_ruby_objects_in_details_on_audit_events.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class DropIndexRubyObjectsInDetailsOnAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_audit_events_on_ruby_object_in_details'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name(:audit_events, INDEX_NAME)
- end
-
- def down
- add_concurrent_index(:audit_events, :id, where: "details ~~ '%ruby/object%'", name: INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200713071042_confirm_project_bot_users.rb b/db/post_migrate/20200713071042_confirm_project_bot_users.rb
deleted file mode 100644
index 0578fc42ef2..00000000000
--- a/db/post_migrate/20200713071042_confirm_project_bot_users.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class ConfirmProjectBotUsers < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- class User < ApplicationRecord
- self.table_name = 'users'
-
- include ::EachBatch
-
- USER_TYPE_PROJECT_BOT = 6
-
- scope :project_bots, -> { where(user_type: USER_TYPE_PROJECT_BOT) }
- scope :unconfirmed, -> { where(confirmed_at: nil) }
- end
-
- def up
- User.reset_column_information
-
- User.project_bots.unconfirmed.each_batch do |relation|
- relation.update_all('confirmed_at = created_at')
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200714075739_schedule_populate_personal_snippet_statistics.rb b/db/post_migrate/20200714075739_schedule_populate_personal_snippet_statistics.rb
deleted file mode 100644
index c3033da24fe..00000000000
--- a/db/post_migrate/20200714075739_schedule_populate_personal_snippet_statistics.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class SchedulePopulatePersonalSnippetStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- DELAY_INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 500
- MIGRATION = 'PopulatePersonalSnippetStatistics'
-
- disable_ddl_transaction!
-
- def up
- snippets = exec_query <<~SQL
- SELECT id
- FROM snippets
- WHERE type = 'PersonalSnippet'
- ORDER BY author_id ASC, id ASC
- SQL
-
- snippets.rows.flatten.in_groups_of(BATCH_SIZE, false).each_with_index do |snippet_ids, index|
- migrate_in(index * DELAY_INTERVAL, MIGRATION, [snippet_ids])
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb b/db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb
deleted file mode 100644
index 114276df875..00000000000
--- a/db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb
+++ /dev/null
@@ -1,135 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveDuplicateLabelsFromGroup < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- CREATE = 1
- RENAME = 2
-
- disable_ddl_transaction!
-
- class BackupLabel < ApplicationRecord
- include EachBatch
-
- self.table_name = 'backup_labels'
- end
-
- class Label < ApplicationRecord
- self.table_name = 'labels'
- end
-
- class Group < ApplicationRecord
- include EachBatch
-
- self.table_name = 'namespaces'
- end
-
- BATCH_SIZE = 10_000
-
- def up
- # Split to smaller chunks
- # Loop rather than background job, every 10,000
- # there are ~1,800,000 groups in total (excluding personal namespaces, which can't have labels)
- Group.where(type: 'Group').each_batch(of: BATCH_SIZE) do |batch|
- range = batch.pluck('MIN(id)', 'MAX(id)').first
-
- transaction do
- remove_full_duplicates(*range)
- end
-
- transaction do
- rename_partial_duplicates(*range)
- end
- end
- end
-
- DOWN_BATCH_SIZE = 1000
-
- def down
- BackupLabel.where('project_id IS NULL AND group_id IS NOT NULL').each_batch(of: DOWN_BATCH_SIZE) do |batch|
- range = batch.pluck('MIN(id)', 'MAX(id)').first
-
- restore_renamed_labels(*range)
- restore_deleted_labels(*range)
- end
- end
-
- def remove_full_duplicates(start_id, stop_id)
- # Fields that are considered duplicate:
- # group_id title template description type color
-
- duplicate_labels = ApplicationRecord.connection.execute(<<-SQL.squish)
-WITH data AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- SELECT labels.*,
- row_number() OVER (PARTITION BY labels.group_id, labels.title, labels.template, labels.description, labels.type, labels.color ORDER BY labels.id) AS row_number,
- #{CREATE} AS restore_action
- FROM labels
- WHERE labels.group_id BETWEEN #{start_id} AND #{stop_id}
- AND NOT EXISTS (SELECT * FROM board_labels WHERE board_labels.label_id = labels.id)
- AND NOT EXISTS (SELECT * FROM label_links WHERE label_links.label_id = labels.id)
- AND NOT EXISTS (SELECT * FROM label_priorities WHERE label_priorities.label_id = labels.id)
- AND NOT EXISTS (SELECT * FROM lists WHERE lists.label_id = labels.id)
- AND NOT EXISTS (SELECT * FROM resource_label_events WHERE resource_label_events.label_id = labels.id)
-) SELECT * FROM data WHERE row_number > 1;
- SQL
-
- if duplicate_labels.any?
- # create backup records
- BackupLabel.insert_all!(duplicate_labels.map { |label| label.except("row_number") })
-
- Label.unscoped.where(id: duplicate_labels.pluck("id")).delete_all
- end
- end
-
- def rename_partial_duplicates(start_id, stop_id)
- # We need to ensure that the new title (with `_duplicate#{ID}`) doesn't exceed the limit.
- # Truncate the original title (if needed) to 245 characters minus the length of the ID
- # then add `_duplicate#{ID}`
-
- soft_duplicates = ApplicationRecord.connection.execute(<<-SQL.squish)
-WITH data AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- SELECT
- *,
- substring(title from 1 for 245 - length(id::text)) || '_duplicate' || id::text as new_title,
- #{RENAME} AS restore_action,
- row_number() OVER (PARTITION BY group_id, title ORDER BY id) AS row_number
- FROM labels
- WHERE group_id BETWEEN #{start_id} AND #{stop_id}
-) SELECT * FROM data WHERE row_number > 1;
- SQL
-
- if soft_duplicates.any?
- # create backup records
- BackupLabel.insert_all!(soft_duplicates.map { |label| label.except("row_number") })
-
- ApplicationRecord.connection.execute(<<-SQL.squish)
-UPDATE labels SET title = substring(title from 1 for 245 - length(id::text)) || '_duplicate' || id::text
-WHERE labels.id IN (#{soft_duplicates.map { |dup| dup["id"] }.join(", ")});
- SQL
- end
- end
-
- def restore_renamed_labels(start_id, stop_id)
- # the backup label IDs are not incremental, they are copied directly from the Labels table
- ApplicationRecord.connection.execute(<<-SQL.squish)
-WITH backups AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- SELECT id, title
- FROM backup_labels
- WHERE id BETWEEN #{start_id} AND #{stop_id}
- AND restore_action = #{RENAME}
-) UPDATE labels SET title = backups.title
-FROM backups
-WHERE labels.id = backups.id;
- SQL
- end
-
- def restore_deleted_labels(start_id, stop_id)
- ActiveRecord::Base.connection.execute(<<-SQL.squish)
-INSERT INTO labels
-SELECT id, title, color, group_id, created_at, updated_at, template, description, description_html, type, cached_markdown_version FROM backup_labels
- WHERE backup_labels.id BETWEEN #{start_id} AND #{stop_id}
- AND backup_labels.project_id IS NULL AND backup_labels.group_id IS NOT NULL
- AND backup_labels.restore_action = #{CREATE}
- SQL
- end
-end
diff --git a/db/post_migrate/20200716234518_add_uniqueness_index_to_label_title_and_group.rb b/db/post_migrate/20200716234518_add_uniqueness_index_to_label_title_and_group.rb
deleted file mode 100644
index 08bab811c00..00000000000
--- a/db/post_migrate/20200716234518_add_uniqueness_index_to_label_title_and_group.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddUniquenessIndexToLabelTitleAndGroup < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- GROUP_AND_TITLE = [:group_id, :title]
-
- def up
- add_concurrent_index :labels, GROUP_AND_TITLE, where: "labels.project_id IS NULL", unique: true, name: "index_labels_on_group_id_and_title_unique"
- remove_concurrent_index :labels, GROUP_AND_TITLE, name: "index_labels_on_group_id_and_title"
- end
-
- def down
- add_concurrent_index :labels, GROUP_AND_TITLE, where: "labels.project_id IS NULL", unique: false, name: "index_labels_on_group_id_and_title"
- remove_concurrent_index :labels, GROUP_AND_TITLE, name: "index_labels_on_group_id_and_title_unique"
- end
-end
diff --git a/db/post_migrate/20200721140507_update_index_for_coverage_fuzzing_telemetry.rb b/db/post_migrate/20200721140507_update_index_for_coverage_fuzzing_telemetry.rb
deleted file mode 100644
index 4f884319125..00000000000
--- a/db/post_migrate/20200721140507_update_index_for_coverage_fuzzing_telemetry.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateIndexForCoverageFuzzingTelemetry < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- OLD_INDEX_NAME = 'index_security_ci_builds_on_name_and_id'
- NEW_INDEX_NAME = 'index_security_ci_builds_on_name_and_id_parser_features'
-
- OLD_CLAUSE = "((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text,
- ('dast'::character varying)::text,
- ('dependency_scanning'::character varying)::text,
- ('license_management'::character varying)::text,
- ('sast'::character varying)::text,
- ('secret_detection'::character varying)::text,
- ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text)"
-
- NEW_CLAUSE = "((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text,
- ('dast'::character varying)::text,
- ('dependency_scanning'::character varying)::text,
- ('license_management'::character varying)::text,
- ('sast'::character varying)::text,
- ('secret_detection'::character varying)::text,
- ('coverage_fuzzing'::character varying)::text,
- ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text)"
-
- def up
- add_concurrent_index :ci_builds, [:name, :id], name: NEW_INDEX_NAME, where: NEW_CLAUSE
- remove_concurrent_index_by_name :ci_builds, OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :ci_builds, [:name, :id], name: OLD_INDEX_NAME, where: OLD_CLAUSE
- remove_concurrent_index_by_name :ci_builds, NEW_INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200722202318_backfill_partitioned_audit_events.rb b/db/post_migrate/20200722202318_backfill_partitioned_audit_events.rb
deleted file mode 100644
index 538aa94e22b..00000000000
--- a/db/post_migrate/20200722202318_backfill_partitioned_audit_events.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillPartitionedAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::PartitioningMigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- return if ::Gitlab.com?
-
- enqueue_partitioning_data_migration :audit_events
- end
-
- def down
- return if ::Gitlab.com?
-
- cleanup_partitioning_data_migration :audit_events
- end
-end
diff --git a/db/post_migrate/20200723040950_migrate_incident_issues_to_incident_type.rb b/db/post_migrate/20200723040950_migrate_incident_issues_to_incident_type.rb
deleted file mode 100644
index 0f562630381..00000000000
--- a/db/post_migrate/20200723040950_migrate_incident_issues_to_incident_type.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateIncidentIssuesToIncidentType < ActiveRecord::Migration[6.0]
- DOWNTIME = false
- BATCH_SIZE = 100
-
- disable_ddl_transaction!
-
- LABEL_PROPERTIES = {
- title: 'incident'
- }.freeze
-
- class Issue < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'issues'
-
- scope :incident_labelled, -> do
- joins("INNER JOIN label_links ON label_links.target_type = 'Issue' AND label_links.target_id = issues.id")
- .joins("INNER JOIN labels ON labels.id = label_links.label_id")
- .where(labels: LABEL_PROPERTIES)
- end
-
- enum issue_type: {
- issue: 0,
- incident: 1
- }
-
- scope :incident_typed, -> { where(issue_type: :incident) }
- end
-
- def up
- incident_issues = Issue.incident_labelled
-
- incident_issues.each_batch(of: BATCH_SIZE) do |batch|
- batch.update_all(issue_type: :incident)
- end
- end
-
- def down
- incident_issues = Issue.incident_typed
-
- incident_issues.each_batch(of: BATCH_SIZE) do |batch|
- batch.update_all(issue_type: :issue)
- end
- end
-end
diff --git a/db/post_migrate/20200723132258_schedule_copy_of_mr_target_project_id_to_mr_metrics.rb b/db/post_migrate/20200723132258_schedule_copy_of_mr_target_project_id_to_mr_metrics.rb
deleted file mode 100644
index bca703121bc..00000000000
--- a/db/post_migrate/20200723132258_schedule_copy_of_mr_target_project_id_to_mr_metrics.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleCopyOfMrTargetProjectIdToMrMetrics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 5_000
- MIGRATION = 'CopyMergeRequestTargetProjectToMergeRequestMetrics'
-
- disable_ddl_transaction!
-
- class MergeRequest < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'merge_requests'
- end
-
- def up
- MergeRequest.reset_column_information
-
- queue_background_migration_jobs_by_range_at_intervals(
- MergeRequest,
- MIGRATION,
- INTERVAL,
- batch_size: BATCH_SIZE
- )
- end
-
- def down
- # noop
- end
-end
diff --git a/db/post_migrate/20200724100421_remove_updated_at_from_audit_events.rb b/db/post_migrate/20200724100421_remove_updated_at_from_audit_events.rb
deleted file mode 100644
index 0dc02491db5..00000000000
--- a/db/post_migrate/20200724100421_remove_updated_at_from_audit_events.rb
+++ /dev/null
@@ -1,119 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveUpdatedAtFromAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::SchemaHelpers
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- SOURCE_TABLE_NAME = 'audit_events'
- PARTITIONED_TABLE_NAME = 'audit_events_part_5fc467ac26'
- TRIGGER_FUNCTION_NAME = 'table_sync_function_2be879775d'
-
- def up
- with_lock_retries do
- remove_column SOURCE_TABLE_NAME, :updated_at
-
- create_trigger_function(TRIGGER_FUNCTION_NAME, replace: true) do
- <<~SQL
- IF (TG_OP = 'DELETE') THEN
- DELETE FROM #{PARTITIONED_TABLE_NAME} where id = OLD.id;
- ELSIF (TG_OP = 'UPDATE') THEN
- UPDATE #{PARTITIONED_TABLE_NAME}
- SET author_id = NEW.author_id,
- type = NEW.type,
- entity_id = NEW.entity_id,
- entity_type = NEW.entity_type,
- details = NEW.details,
- ip_address = NEW.ip_address,
- author_name = NEW.author_name,
- entity_path = NEW.entity_path,
- target_details = NEW.target_details,
- created_at = NEW.created_at
- WHERE #{PARTITIONED_TABLE_NAME}.id = NEW.id;
- ELSIF (TG_OP = 'INSERT') THEN
- INSERT INTO #{PARTITIONED_TABLE_NAME} (id,
- author_id,
- type,
- entity_id,
- entity_type,
- details,
- ip_address,
- author_name,
- entity_path,
- target_details,
- created_at)
- VALUES (NEW.id,
- NEW.author_id,
- NEW.type,
- NEW.entity_id,
- NEW.entity_type,
- NEW.details,
- NEW.ip_address,
- NEW.author_name,
- NEW.entity_path,
- NEW.target_details,
- NEW.created_at);
- END IF;
- RETURN NULL;
- SQL
- end
-
- remove_column PARTITIONED_TABLE_NAME, :updated_at
- end
- end
-
- def down
- with_lock_retries do
- add_column SOURCE_TABLE_NAME, :updated_at, :datetime # rubocop:disable Migration/Datetime
- add_column PARTITIONED_TABLE_NAME, :updated_at, :datetime # rubocop:disable Migration/Datetime
-
- create_trigger_function(TRIGGER_FUNCTION_NAME, replace: true) do
- <<~SQL
- IF (TG_OP = 'DELETE') THEN
- DELETE FROM #{PARTITIONED_TABLE_NAME} where id = OLD.id;
- ELSIF (TG_OP = 'UPDATE') THEN
- UPDATE #{PARTITIONED_TABLE_NAME}
- SET author_id = NEW.author_id,
- type = NEW.type,
- entity_id = NEW.entity_id,
- entity_type = NEW.entity_type,
- details = NEW.details,
- updated_at = NEW.updated_at,
- ip_address = NEW.ip_address,
- author_name = NEW.author_name,
- entity_path = NEW.entity_path,
- target_details = NEW.target_details,
- created_at = NEW.created_at
- WHERE #{PARTITIONED_TABLE_NAME}.id = NEW.id;
- ELSIF (TG_OP = 'INSERT') THEN
- INSERT INTO #{PARTITIONED_TABLE_NAME} (id,
- author_id,
- type,
- entity_id,
- entity_type,
- details,
- updated_at,
- ip_address,
- author_name,
- entity_path,
- target_details,
- created_at)
- VALUES (NEW.id,
- NEW.author_id,
- NEW.type,
- NEW.entity_id,
- NEW.entity_type,
- NEW.details,
- NEW.updated_at,
- NEW.ip_address,
- NEW.author_name,
- NEW.entity_path,
- NEW.target_details,
- NEW.created_at);
- END IF;
- RETURN NULL;
- SQL
- end
- end
- end
-end
diff --git a/db/post_migrate/20200724130639_backfill_designs_relative_position.rb b/db/post_migrate/20200724130639_backfill_designs_relative_position.rb
deleted file mode 100644
index ef8b38bf90c..00000000000
--- a/db/post_migrate/20200724130639_backfill_designs_relative_position.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-# This migration is not needed anymore and was disabled, because we're now
-# also backfilling design positions immediately before moving a design.
-#
-# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39555
-class BackfillDesignsRelativePosition < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- # no-op
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200727100631_remove_again_gitlab_issue_tracker_service_records.rb b/db/post_migrate/20200727100631_remove_again_gitlab_issue_tracker_service_records.rb
deleted file mode 100644
index b61da82aef8..00000000000
--- a/db/post_migrate/20200727100631_remove_again_gitlab_issue_tracker_service_records.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveAgainGitlabIssueTrackerServiceRecords < ActiveRecord::Migration[6.0]
- DOWNTIME = false
- BATCH_SIZE = 5000
-
- disable_ddl_transaction!
-
- class Service < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'services'
-
- def self.gitlab_issue_tracker_service
- where(type: 'GitlabIssueTrackerService')
- end
- end
-
- def up
- Service.each_batch(of: BATCH_SIZE) do |services|
- services.gitlab_issue_tracker_service.delete_all
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200727114147_remove_title_and_description_from_services.rb b/db/post_migrate/20200727114147_remove_title_and_description_from_services.rb
deleted file mode 100644
index 0c908e17438..00000000000
--- a/db/post_migrate/20200727114147_remove_title_and_description_from_services.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveTitleAndDescriptionFromServices < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- remove_column :services, :title, :string
- remove_column :services, :description, :string, limit: 500
- end
-end
diff --git a/db/post_migrate/20200730133730_remove_table_vulnerability_export_verification_status.rb b/db/post_migrate/20200730133730_remove_table_vulnerability_export_verification_status.rb
deleted file mode 100644
index 9aa15fa7d1a..00000000000
--- a/db/post_migrate/20200730133730_remove_table_vulnerability_export_verification_status.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveTableVulnerabilityExportVerificationStatus < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- return unless table_exists?(:vulnerability_export_verification_status)
-
- drop_table :vulnerability_export_verification_status
- end
-
- def down
- # no-op because `vulnerability_export_verification_status` table should not
- # be created, see https://gitlab.com/gitlab-org/gitlab/-/issues/232977
- end
-end
diff --git a/db/post_migrate/20200804035230_add_partial_index_on_id_to_merge_request_diffs.rb b/db/post_migrate/20200804035230_add_partial_index_on_id_to_merge_request_diffs.rb
deleted file mode 100644
index 94b939eb811..00000000000
--- a/db/post_migrate/20200804035230_add_partial_index_on_id_to_merge_request_diffs.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddPartialIndexOnIdToMergeRequestDiffs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_merge_request_diffs_external_diff_store_is_null'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :merge_request_diffs, :id, where: 'external_diff_store IS NULL', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :merge_request_diffs, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200804041930_add_not_null_constraint_on_external_diff_store_to_merge_request_diffs.rb b/db/post_migrate/20200804041930_add_not_null_constraint_on_external_diff_store_to_merge_request_diffs.rb
deleted file mode 100644
index c33e790b37b..00000000000
--- a/db/post_migrate/20200804041930_add_not_null_constraint_on_external_diff_store_to_merge_request_diffs.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddNotNullConstraintOnExternalDiffStoreToMergeRequestDiffs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_not_null_constraint(:merge_request_diffs, :external_diff_store, validate: false)
- end
-
- def down
- remove_not_null_constraint(:merge_request_diffs, :external_diff_store)
- end
-end
diff --git a/db/post_migrate/20200805152108_migrate_null_external_diff_store_to_local_value.rb b/db/post_migrate/20200805152108_migrate_null_external_diff_store_to_local_value.rb
deleted file mode 100644
index e42f23d8fae..00000000000
--- a/db/post_migrate/20200805152108_migrate_null_external_diff_store_to_local_value.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateNullExternalDiffStoreToLocalValue < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- JOB_INTERVAL = 2.minutes + 5.seconds
- BATCH_SIZE = 5_000
- MIGRATION = 'SetNullExternalDiffStoreToLocalValue'
-
- disable_ddl_transaction!
-
- class MergeRequestDiff < ActiveRecord::Base
- self.table_name = 'merge_request_diffs'
-
- include ::EachBatch
- end
-
- def up
- # On GitLab.com, 19M of 93M rows have NULL external_diff_store.
- #
- # With batches of 5000 and a background migration job interval of 2m 5s,
- # 3.8K jobs are scheduled over 5.5 days.
- #
- # The index `index_merge_request_diffs_external_diff_store_is_null` is
- # expected to be used here and in the jobs.
- #
- # queue_background_migration_jobs_by_range_at_intervals is not used because
- # it would enqueue 18.6K jobs and we have an index for getting these ranges.
- MergeRequestDiff.where(external_diff_store: nil).each_batch(of: BATCH_SIZE) do |batch, index|
- range = batch.pluck(Arel.sql("MIN(id)"), Arel.sql("MAX(id)")).first
- delay = index * JOB_INTERVAL
-
- migrate_in(delay.seconds, MIGRATION, [*range])
- end
- end
-
- def down
- # noop
- end
-end
diff --git a/db/post_migrate/20200806004742_add_not_null_constraint_on_file_store_to_package_files.rb b/db/post_migrate/20200806004742_add_not_null_constraint_on_file_store_to_package_files.rb
deleted file mode 100644
index 7b7250fef9a..00000000000
--- a/db/post_migrate/20200806004742_add_not_null_constraint_on_file_store_to_package_files.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddNotNullConstraintOnFileStoreToPackageFiles < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_not_null_constraint(:packages_package_files, :file_store, validate: false)
- end
-
- def down
- remove_not_null_constraint(:packages_package_files, :file_store)
- end
-end
diff --git a/db/post_migrate/20200806172909_add_partial_index_on_id_to_package_files.rb b/db/post_migrate/20200806172909_add_partial_index_on_id_to_package_files.rb
deleted file mode 100644
index 7904574f890..00000000000
--- a/db/post_migrate/20200806172909_add_partial_index_on_id_to_package_files.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddPartialIndexOnIdToPackageFiles < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_packages_package_files_file_store_is_null'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :packages_package_files, :id, where: 'file_store IS NULL', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :packages_package_files, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200806173633_migrate_null_package_files_file_store_to_local_value.rb b/db/post_migrate/20200806173633_migrate_null_package_files_file_store_to_local_value.rb
deleted file mode 100644
index 088b85dd5da..00000000000
--- a/db/post_migrate/20200806173633_migrate_null_package_files_file_store_to_local_value.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateNullPackageFilesFileStoreToLocalValue < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- JOB_INTERVAL = 2.minutes + 5.seconds
- BATCH_SIZE = 5_000
- MIGRATION = 'SetNullPackageFilesFileStoreToLocalValue'
-
- disable_ddl_transaction!
-
- class PackageFile < ActiveRecord::Base
- self.table_name = 'packages_package_files'
-
- include ::EachBatch
- end
-
- def up
- # On GitLab.com, there are 2M package files. None have NULL file_store
- # because they are all object stored. This is a no-op for GitLab.com.
- #
- # If a customer had 2M package files with NULL file_store, with batches of
- # 5000 and a background migration job interval of 2m 5s, then 400 jobs would
- # be scheduled over 14 hours.
- #
- # The index `index_packages_package_files_file_store_is_null` is
- # expected to be used here and in the jobs.
- #
- # queue_background_migration_jobs_by_range_at_intervals is not used because
- # it would enqueue 18.6K jobs and we have an index for getting these ranges.
- PackageFile.where(file_store: nil).each_batch(of: BATCH_SIZE) do |batch, index|
- range = batch.pluck(Arel.sql("MIN(id)"), Arel.sql("MAX(id)")).first
- delay = index * JOB_INTERVAL
-
- migrate_in(delay.seconds, MIGRATION, [*range])
- end
- end
-
- def down
- # noop
- end
-end
diff --git a/db/post_migrate/20200807110237_add_migration_index_to_vulnerabilities_occurrences.rb b/db/post_migrate/20200807110237_add_migration_index_to_vulnerabilities_occurrences.rb
deleted file mode 100644
index e806a337f8f..00000000000
--- a/db/post_migrate/20200807110237_add_migration_index_to_vulnerabilities_occurrences.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddMigrationIndexToVulnerabilitiesOccurrences < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :vulnerability_occurrences,
- "project_id, report_type, encode(project_fingerprint, 'hex'::text)",
- name: 'index_vulnerability_occurrences_for_issue_links_migration'
- end
-
- def down
- remove_concurrent_index_by_name :vulnerability_occurrences,
- :index_vulnerability_occurrences_for_issue_links_migration
- end
-end
diff --git a/db/post_migrate/20200807152315_backfill_merge_request_diffs_files_counts.rb b/db/post_migrate/20200807152315_backfill_merge_request_diffs_files_counts.rb
deleted file mode 100644
index bc7e4712d19..00000000000
--- a/db/post_migrate/20200807152315_backfill_merge_request_diffs_files_counts.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillMergeRequestDiffsFilesCounts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- # There are ~72 million records on GitLab.com at time of writing, so go fast
- BATCH_SIZE = 10_000
- DELAY_INTERVAL = 2.minutes.to_i
- MIGRATION = 'SetMergeRequestDiffFilesCount'
-
- disable_ddl_transaction!
-
- class MergeRequestDiff < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'merge_request_diffs'
- end
-
- def up
- queue_background_migration_jobs_by_range_at_intervals(
- MergeRequestDiff, MIGRATION, DELAY_INTERVAL, batch_size: BATCH_SIZE
- )
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200808221641_add_index_for_license_compliance_artifacts.rb b/db/post_migrate/20200808221641_add_index_for_license_compliance_artifacts.rb
deleted file mode 100644
index fce4ee095bd..00000000000
--- a/db/post_migrate/20200808221641_add_index_for_license_compliance_artifacts.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexForLicenseComplianceArtifacts < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_ci_job_artifacts_on_license_compliance_file_types'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_job_artifacts, [:job_id, :file_type], where: 'file_type = 10 OR file_type = 101', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :ci_job_artifacts, name: INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200809221641_migrate_license_management_artifacts_to_license_scanning.rb b/db/post_migrate/20200809221641_migrate_license_management_artifacts_to_license_scanning.rb
deleted file mode 100644
index 66ef4b35dfa..00000000000
--- a/db/post_migrate/20200809221641_migrate_license_management_artifacts_to_license_scanning.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateLicenseManagementArtifactsToLicenseScanning < ActiveRecord::Migration[6.0]
- DOWNTIME = false
- LICENSE_MANAGEMENT_FILE_TYPE = 10
- LICENSE_SCANNING_FILE_TYPE = 101
-
- disable_ddl_transaction!
-
- class JobArtifact < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'ci_job_artifacts'
- end
-
- # We're updating file_type of ci artifacts from license_management to license_scanning
- # But before that we need to delete "rogue" artifacts for CI builds that have associated with them
- # both license_scanning and license_management artifacts. It's an edge case and usually, we don't have
- # such builds in the database.
- def up
- return unless Gitlab.ee?
-
- JobArtifact
- .where("file_type = 10 OR file_type = 101")
- .each_batch(column: :job_id, of: 1000) do |relation|
- min, max = relation.pluck('MIN(job_id)', 'MAX(job_id)').flatten
-
- ActiveRecord::Base.connection.execute <<~SQL
- WITH ci_job_artifacts_with_row_number as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- SELECT job_id, id, ROW_NUMBER() OVER (PARTITION BY job_id ORDER BY id ASC) as row_number
- FROM ci_job_artifacts
- WHERE (file_type = #{LICENSE_SCANNING_FILE_TYPE} OR file_type = #{LICENSE_MANAGEMENT_FILE_TYPE})
- AND job_id >= #{Integer(min)} AND job_id < #{Integer(max)}
- )
- DELETE FROM ci_job_artifacts
- WHERE ci_job_artifacts.id IN (SELECT id from ci_job_artifacts_with_row_number WHERE ci_job_artifacts_with_row_number.row_number > 1)
- SQL
- end
-
- JobArtifact.where(file_type: LICENSE_MANAGEMENT_FILE_TYPE).each_batch(column: :job_id, of: 1000) do |relation|
- relation.update_all(file_type: LICENSE_SCANNING_FILE_TYPE)
- end
- end
-
- def down
- # no-op
- # we're deleting duplicating artifacts and updating file_type for license_management artifacts
- end
-end
diff --git a/db/post_migrate/20200810100921_add_target_type_to_audit_event.rb b/db/post_migrate/20200810100921_add_target_type_to_audit_event.rb
deleted file mode 100644
index 8dde5945f0d..00000000000
--- a/db/post_migrate/20200810100921_add_target_type_to_audit_event.rb
+++ /dev/null
@@ -1,121 +0,0 @@
-# frozen_string_literal: true
-
-class AddTargetTypeToAuditEvent < ActiveRecord::Migration[6.0]
- include Gitlab::Database::SchemaHelpers
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- SOURCE_TABLE_NAME = 'audit_events'
- PARTITIONED_TABLE_NAME = 'audit_events_part_5fc467ac26'
- TRIGGER_FUNCTION_NAME = 'table_sync_function_2be879775d'
-
- def up
- with_lock_retries do
- # rubocop:disable Migration/AddLimitToTextColumns
- add_column('audit_events', :target_type, :text)
- add_column('audit_events_part_5fc467ac26', :target_type, :text)
- # rubocop:enable Migration/AddLimitToTextColumns
-
- create_trigger_function(TRIGGER_FUNCTION_NAME, replace: true) do
- <<~SQL
- IF (TG_OP = 'DELETE') THEN
- DELETE FROM #{PARTITIONED_TABLE_NAME} where id = OLD.id;
- ELSIF (TG_OP = 'UPDATE') THEN
- UPDATE #{PARTITIONED_TABLE_NAME}
- SET author_id = NEW.author_id,
- type = NEW.type,
- entity_id = NEW.entity_id,
- entity_type = NEW.entity_type,
- details = NEW.details,
- ip_address = NEW.ip_address,
- author_name = NEW.author_name,
- entity_path = NEW.entity_path,
- target_details = NEW.target_details,
- target_type = NEW.target_type,
- created_at = NEW.created_at
- WHERE #{PARTITIONED_TABLE_NAME}.id = NEW.id;
- ELSIF (TG_OP = 'INSERT') THEN
- INSERT INTO #{PARTITIONED_TABLE_NAME} (id,
- author_id,
- type,
- entity_id,
- entity_type,
- details,
- ip_address,
- author_name,
- entity_path,
- target_details,
- target_type,
- created_at)
- VALUES (NEW.id,
- NEW.author_id,
- NEW.type,
- NEW.entity_id,
- NEW.entity_type,
- NEW.details,
- NEW.ip_address,
- NEW.author_name,
- NEW.entity_path,
- NEW.target_details,
- NEW.target_type,
- NEW.created_at);
- END IF;
- RETURN NULL;
- SQL
- end
- end
- end
-
- def down
- with_lock_retries do
- remove_column SOURCE_TABLE_NAME, :target_type
-
- create_trigger_function(TRIGGER_FUNCTION_NAME, replace: true) do
- <<~SQL
- IF (TG_OP = 'DELETE') THEN
- DELETE FROM #{PARTITIONED_TABLE_NAME} where id = OLD.id;
- ELSIF (TG_OP = 'UPDATE') THEN
- UPDATE #{PARTITIONED_TABLE_NAME}
- SET author_id = NEW.author_id,
- type = NEW.type,
- entity_id = NEW.entity_id,
- entity_type = NEW.entity_type,
- details = NEW.details,
- ip_address = NEW.ip_address,
- author_name = NEW.author_name,
- entity_path = NEW.entity_path,
- target_details = NEW.target_details,
- created_at = NEW.created_at
- WHERE #{PARTITIONED_TABLE_NAME}.id = NEW.id;
- ELSIF (TG_OP = 'INSERT') THEN
- INSERT INTO #{PARTITIONED_TABLE_NAME} (id,
- author_id,
- type,
- entity_id,
- entity_type,
- details,
- ip_address,
- author_name,
- entity_path,
- target_details,
- created_at)
- VALUES (NEW.id,
- NEW.author_id,
- NEW.type,
- NEW.entity_id,
- NEW.entity_type,
- NEW.details,
- NEW.ip_address,
- NEW.author_name,
- NEW.entity_path,
- NEW.target_details,
- NEW.created_at);
- END IF;
- RETURN NULL;
- SQL
- end
-
- remove_column PARTITIONED_TABLE_NAME, :target_type
- end
- end
-end
diff --git a/db/post_migrate/20200810101029_add_text_limit_to_audit_event_target_type.rb b/db/post_migrate/20200810101029_add_text_limit_to_audit_event_target_type.rb
deleted file mode 100644
index 2a5ea9cd245..00000000000
--- a/db/post_migrate/20200810101029_add_text_limit_to_audit_event_target_type.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class AddTextLimitToAuditEventTargetType < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
- SOURCE_TABLE_NAME = 'audit_events'
- PARTITIONED_TABLE_NAME = 'audit_events_part_5fc467ac26'
-
- disable_ddl_transaction!
-
- def up
- add_text_limit(SOURCE_TABLE_NAME, :target_type, 255)
- add_text_limit(PARTITIONED_TABLE_NAME, :target_type, 255)
- end
-
- def down
- remove_text_limit(SOURCE_TABLE_NAME, :target_type)
- remove_text_limit(PARTITIONED_TABLE_NAME, :target_type)
- end
-end
diff --git a/db/post_migrate/20200810160355_add_not_null_constraint_to_ci_pipeline_artifact_file.rb b/db/post_migrate/20200810160355_add_not_null_constraint_to_ci_pipeline_artifact_file.rb
deleted file mode 100644
index 0c233d44313..00000000000
--- a/db/post_migrate/20200810160355_add_not_null_constraint_to_ci_pipeline_artifact_file.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddNotNullConstraintToCiPipelineArtifactFile < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_not_null_constraint :ci_pipeline_artifacts, :file, validate: true
- end
-
- def down
- remove_not_null_constraint :ci_pipeline_artifacts, :file
- end
-end
diff --git a/db/post_migrate/20200810191256_remove_pipeline_id_from_test_reports.rb b/db/post_migrate/20200810191256_remove_pipeline_id_from_test_reports.rb
deleted file mode 100644
index f99629a921e..00000000000
--- a/db/post_migrate/20200810191256_remove_pipeline_id_from_test_reports.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RemovePipelineIdFromTestReports < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- remove_column :requirements_management_test_reports, :pipeline_id
- end
-
- def down
- add_column :requirements_management_test_reports, :pipeline_id, :integer
-
- with_lock_retries do
- add_foreign_key :requirements_management_test_reports, :ci_pipelines, column: :pipeline_id, on_delete: :nullify
- end
- end
-end
diff --git a/db/post_migrate/20200811130000_create_index_vulnerabilities_feedback_issue_id_not_null.rb b/db/post_migrate/20200811130000_create_index_vulnerabilities_feedback_issue_id_not_null.rb
deleted file mode 100644
index 118076eb254..00000000000
--- a/db/post_migrate/20200811130000_create_index_vulnerabilities_feedback_issue_id_not_null.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class CreateIndexVulnerabilitiesFeedbackIssueIdNotNull < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :vulnerability_feedback, :id, where: 'issue_id IS NOT NULL',
- name: "index_vulnerability_feedback_on_issue_id_not_null"
- end
-
- def down
- remove_concurrent_index_by_name :vulnerability_feedback,
- :index_vulnerability_feedback_on_issue_id_not_null
- end
-end
diff --git a/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb b/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb
deleted file mode 100644
index 031d9ea49e2..00000000000
--- a/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-class CreateMissingVulnerabilitiesIssueLinks < ActiveRecord::Migration[6.0]
- class VulnerabilitiesFeedback < ActiveRecord::Base
- include EachBatch
- self.table_name = 'vulnerability_feedback'
- end
-
- class VulnerabilitiesIssueLink < ActiveRecord::Base
- self.table_name = 'vulnerability_issue_links'
- LINK_TYPE_CREATED = 2
- end
-
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- VulnerabilitiesFeedback.where.not(issue_id: nil).each_batch do |relation|
- timestamp = Time.now
- issue_links = relation
- .joins("JOIN vulnerability_occurrences vo ON vo.project_id = vulnerability_feedback.project_id AND vo.report_type = vulnerability_feedback.category AND encode(vo.project_fingerprint, 'hex') = vulnerability_feedback.project_fingerprint")
- .where.not('vo.vulnerability_id' => nil)
- .pluck(:vulnerability_id, :issue_id)
- .map do |v_id, i_id|
- {
- vulnerability_id: v_id,
- issue_id: i_id,
- link_type: VulnerabilitiesIssueLink::LINK_TYPE_CREATED,
- created_at: timestamp,
- updated_at: timestamp
- }
- end
-
- next if issue_links.empty?
-
- VulnerabilitiesIssueLink.insert_all(
- issue_links,
- returning: false
- )
- end
- end
-
- def down
- end
-end
diff --git a/db/post_migrate/20200811211536_add_index_to_ci_job_artifacts_for_terraform_reports_id.rb b/db/post_migrate/20200811211536_add_index_to_ci_job_artifacts_for_terraform_reports_id.rb
deleted file mode 100644
index 6042f90cf85..00000000000
--- a/db/post_migrate/20200811211536_add_index_to_ci_job_artifacts_for_terraform_reports_id.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexToCiJobArtifactsForTerraformReportsId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_ci_job_artifacts_id_for_terraform_reports'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_job_artifacts, :id, where: 'file_type = 18', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :ci_job_artifacts, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200813153434_import_latest_common_metrics.rb b/db/post_migrate/20200813153434_import_latest_common_metrics.rb
deleted file mode 100644
index 203e495674f..00000000000
--- a/db/post_migrate/20200813153434_import_latest_common_metrics.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class ImportLatestCommonMetrics < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- # The common_metrics queries were updated to work with K8s versions that
- # use the pod/container label names as well as K8s versions that use the
- # older pod_name/container_name convention.
- ::Gitlab::DatabaseImporters::CommonMetrics::Importer.new.execute
- end
-
- def down
- # no-op
- # The import cannot be reversed since we do not know the state that the
- # common metrics in the PrometheusMetric table were in before the import.
-
- # To manually revert this migration.
- # 1. Go back to the previous version of the config/prometheus/common_metrics.yml file. (git checkout 74447f11349617ed8b273196d6a5781d9a67a613)
- # 2. Execute `rails runner '::Gitlab::DatabaseImporters::CommonMetrics::Importer.new.execute'`
- end
-end
diff --git a/db/post_migrate/20200817070126_update_index_secure_for_coverage_fuzzing_telemetry.rb b/db/post_migrate/20200817070126_update_index_secure_for_coverage_fuzzing_telemetry.rb
deleted file mode 100644
index d9aa7314115..00000000000
--- a/db/post_migrate/20200817070126_update_index_secure_for_coverage_fuzzing_telemetry.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateIndexSecureForCoverageFuzzingTelemetry < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- OLD_SECURE_INDEX_NAME = 'index_secure_ci_builds_on_user_id_created_at'
- NEW_SECURE_INDEX_NAME = 'index_secure_ci_builds_on_user_id_created_at_parser_features'
-
- def up
- add_concurrent_index(:ci_builds,
- [:user_id, :created_at],
- where: "(((type)::text = 'Ci::Build'::text) AND ((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('license_scanning'::character varying)::text, ('sast'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('secret_detection'::character varying)::text])))",
- name: NEW_SECURE_INDEX_NAME)
- remove_concurrent_index_by_name :ci_builds, OLD_SECURE_INDEX_NAME
- end
-
- def down
- add_concurrent_index(:ci_builds,
- [:user_id, :created_at],
- where: "(((type)::text = 'Ci::Build'::text) AND ((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('license_scanning'::character varying)::text, ('sast'::character varying)::text, ('secret_detection'::character varying)::text])))",
- name: OLD_SECURE_INDEX_NAME)
- remove_concurrent_index_by_name :ci_builds, NEW_SECURE_INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200817100710_add_section_and_created_at_codeowner_approval_merge_request_index.rb b/db/post_migrate/20200817100710_add_section_and_created_at_codeowner_approval_merge_request_index.rb
deleted file mode 100644
index 33de4f1f790..00000000000
--- a/db/post_migrate/20200817100710_add_section_and_created_at_codeowner_approval_merge_request_index.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddSectionAndCreatedAtCodeownerApprovalMergeRequestIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- SECTION_CREATED_AT_ON_CODEOWNER_APPROVAL_MERGE_REQUEST_RULES = "index_created_at_on_codeowner_approval_merge_request_rules"
- RULE_TYPE_CODEOWNERS = 2
- CODEOWNER_SECTION_DEFAULT = 'codeowners'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :approval_merge_request_rules, :created_at,
- where: "rule_type = #{RULE_TYPE_CODEOWNERS} AND section != '#{CODEOWNER_SECTION_DEFAULT}'::text",
- name: SECTION_CREATED_AT_ON_CODEOWNER_APPROVAL_MERGE_REQUEST_RULES
- end
-
- def down
- remove_concurrent_index_by_name :approval_merge_request_rules, SECTION_CREATED_AT_ON_CODEOWNER_APPROVAL_MERGE_REQUEST_RULES
- end
-end
diff --git a/db/post_migrate/20200819082334_remove_default_from_services.rb b/db/post_migrate/20200819082334_remove_default_from_services.rb
deleted file mode 100644
index 2a990016c95..00000000000
--- a/db/post_migrate/20200819082334_remove_default_from_services.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveDefaultFromServices < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- remove_column :services, :default, :boolean
- end
- end
-
- def down
- with_lock_retries do
- add_column :services, :default, :boolean, default: false
- end
- end
-end
diff --git a/db/post_migrate/20200819113644_add_target_id_to_audit_events.rb b/db/post_migrate/20200819113644_add_target_id_to_audit_events.rb
deleted file mode 100644
index c2d9aff928b..00000000000
--- a/db/post_migrate/20200819113644_add_target_id_to_audit_events.rb
+++ /dev/null
@@ -1,125 +0,0 @@
-# frozen_string_literal: true
-
-class AddTargetIdToAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::SchemaHelpers
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- SOURCE_TABLE_NAME = 'audit_events'
- PARTITIONED_TABLE_NAME = 'audit_events_part_5fc467ac26'
- TRIGGER_FUNCTION_NAME = 'table_sync_function_2be879775d'
-
- def up
- with_lock_retries do
- add_column(SOURCE_TABLE_NAME, :target_id, :bigint)
- add_column(PARTITIONED_TABLE_NAME, :target_id, :bigint)
-
- create_trigger_function(TRIGGER_FUNCTION_NAME, replace: true) do
- <<~SQL
- IF (TG_OP = 'DELETE') THEN
- DELETE FROM #{PARTITIONED_TABLE_NAME} where id = OLD.id;
- ELSIF (TG_OP = 'UPDATE') THEN
- UPDATE #{PARTITIONED_TABLE_NAME}
- SET author_id = NEW.author_id,
- type = NEW.type,
- entity_id = NEW.entity_id,
- entity_type = NEW.entity_type,
- details = NEW.details,
- ip_address = NEW.ip_address,
- author_name = NEW.author_name,
- entity_path = NEW.entity_path,
- target_details = NEW.target_details,
- target_type = NEW.target_type,
- target_id = NEW.target_id,
- created_at = NEW.created_at
- WHERE #{PARTITIONED_TABLE_NAME}.id = NEW.id;
- ELSIF (TG_OP = 'INSERT') THEN
- INSERT INTO #{PARTITIONED_TABLE_NAME} (id,
- author_id,
- type,
- entity_id,
- entity_type,
- details,
- ip_address,
- author_name,
- entity_path,
- target_details,
- target_type,
- target_id,
- created_at)
- VALUES (NEW.id,
- NEW.author_id,
- NEW.type,
- NEW.entity_id,
- NEW.entity_type,
- NEW.details,
- NEW.ip_address,
- NEW.author_name,
- NEW.entity_path,
- NEW.target_details,
- NEW.target_type,
- NEW.target_id,
- NEW.created_at);
- END IF;
- RETURN NULL;
- SQL
- end
- end
- end
-
- def down
- with_lock_retries do
- remove_column SOURCE_TABLE_NAME, :target_id
-
- create_trigger_function(TRIGGER_FUNCTION_NAME, replace: true) do
- <<~SQL
- IF (TG_OP = 'DELETE') THEN
- DELETE FROM #{PARTITIONED_TABLE_NAME} where id = OLD.id;
- ELSIF (TG_OP = 'UPDATE') THEN
- UPDATE #{PARTITIONED_TABLE_NAME}
- SET author_id = NEW.author_id,
- type = NEW.type,
- entity_id = NEW.entity_id,
- entity_type = NEW.entity_type,
- details = NEW.details,
- ip_address = NEW.ip_address,
- author_name = NEW.author_name,
- entity_path = NEW.entity_path,
- target_details = NEW.target_details,
- target_type = NEW.target_type,
- created_at = NEW.created_at
- WHERE #{PARTITIONED_TABLE_NAME}.id = NEW.id;
- ELSIF (TG_OP = 'INSERT') THEN
- INSERT INTO #{PARTITIONED_TABLE_NAME} (id,
- author_id,
- type,
- entity_id,
- entity_type,
- details,
- ip_address,
- author_name,
- entity_path,
- target_details,
- target_type,
- created_at)
- VALUES (NEW.id,
- NEW.author_id,
- NEW.type,
- NEW.entity_id,
- NEW.entity_type,
- NEW.details,
- NEW.ip_address,
- NEW.author_name,
- NEW.entity_path,
- NEW.target_details,
- NEW.target_type,
- NEW.created_at);
- END IF;
- RETURN NULL;
- SQL
- end
-
- remove_column PARTITIONED_TABLE_NAME, :target_id
- end
- end
-end
diff --git a/db/post_migrate/20200819202048_remove_orphaned_emails.rb b/db/post_migrate/20200819202048_remove_orphaned_emails.rb
deleted file mode 100644
index 82cba244ad6..00000000000
--- a/db/post_migrate/20200819202048_remove_orphaned_emails.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveOrphanedEmails < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute <<~SQL
- DELETE FROM emails
- WHERE not exists (
- SELECT 1 FROM users WHERE users.id = emails.user_id
- );
- SQL
-
- execute 'DELETE FROM emails WHERE user_id IS NULL;'
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200819202222_validate_emails_user_id_foreign_key.rb b/db/post_migrate/20200819202222_validate_emails_user_id_foreign_key.rb
deleted file mode 100644
index 4f7f9deb540..00000000000
--- a/db/post_migrate/20200819202222_validate_emails_user_id_foreign_key.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateEmailsUserIdForeignKey < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- CONSTRAINT_NAME = 'fk_emails_user_id'
-
- def up
- validate_foreign_key :emails, :user_id, name: CONSTRAINT_NAME
- end
-
- def down
- # no op
- end
-end
diff --git a/db/post_migrate/20200821224343_schedule_populate_vulnerability_historical_statistics.rb b/db/post_migrate/20200821224343_schedule_populate_vulnerability_historical_statistics.rb
deleted file mode 100644
index f3a57ab78ef..00000000000
--- a/db/post_migrate/20200821224343_schedule_populate_vulnerability_historical_statistics.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class SchedulePopulateVulnerabilityHistoricalStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- DELAY_INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 50
- MIGRATION = 'PopulateVulnerabilityHistoricalStatistics'
-
- disable_ddl_transaction!
-
- class Vulnerability < ActiveRecord::Base
- self.table_name = 'vulnerabilities'
-
- include ::EachBatch
- end
-
- def up
- return unless Gitlab.ee?
-
- Vulnerability.select('project_id').distinct.each_batch(of: BATCH_SIZE, column: 'project_id') do |project_batch, index|
- migrate_in(index * DELAY_INTERVAL, MIGRATION, [project_batch.pluck(:project_id)])
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200824130028_remove_index_on_users_bio.rb b/db/post_migrate/20200824130028_remove_index_on_users_bio.rb
deleted file mode 100644
index d41734eb9ce..00000000000
--- a/db/post_migrate/20200824130028_remove_index_on_users_bio.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexOnUsersBio < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- BACKGROUND_MIGRATION_CLASS = 'MigrateUsersBioToUserDetails'
- INDEX_NAME = 'tmp_idx_on_user_id_where_bio_is_filled'
-
- disable_ddl_transaction!
-
- def up
- Gitlab::BackgroundMigration.steal(BACKGROUND_MIGRATION_CLASS)
- remove_concurrent_index_by_name(:users, INDEX_NAME)
- end
-
- def down
- add_concurrent_index :users, :id, where: "(COALESCE(bio, '') IS DISTINCT FROM '')", name: INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200824130447_remove_users_bio_column.rb b/db/post_migrate/20200824130447_remove_users_bio_column.rb
deleted file mode 100644
index cb630ec7fd5..00000000000
--- a/db/post_migrate/20200824130447_remove_users_bio_column.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveUsersBioColumn < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- remove_column :users, :bio
- end
- end
-
- def down
- with_lock_retries do
- add_column :users, :bio, :string # rubocop: disable Migration/AddColumnsToWideTables
- end
- end
-end
diff --git a/db/post_migrate/20200826053152_add_index_on_ci_pipelines_source_for_on_demand_dast.rb b/db/post_migrate/20200826053152_add_index_on_ci_pipelines_source_for_on_demand_dast.rb
deleted file mode 100644
index 6249adc9798..00000000000
--- a/db/post_migrate/20200826053152_add_index_on_ci_pipelines_source_for_on_demand_dast.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnCiPipelinesSourceForOnDemandDast < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = 'index_ci_pipelines_for_ondemand_dast_scans'
-
- SOURCE_ONDEMAND_DAST_SCAN_PIPELINE = 13
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(
- :ci_pipelines, :id,
- where: "source = #{SOURCE_ONDEMAND_DAST_SCAN_PIPELINE}",
- name: INDEX_NAME
- )
- end
-
- def down
- remove_concurrent_index(
- :ci_pipelines, :id,
- where: "source = #{SOURCE_ONDEMAND_DAST_SCAN_PIPELINE}",
- name: INDEX_NAME
- )
- end
-end
diff --git a/db/post_migrate/20200826121552_remove_ci_job_artifacts_locked.rb b/db/post_migrate/20200826121552_remove_ci_job_artifacts_locked.rb
deleted file mode 100644
index 21c7acca7ac..00000000000
--- a/db/post_migrate/20200826121552_remove_ci_job_artifacts_locked.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveCiJobArtifactsLocked < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- with_lock_retries do
- remove_column :ci_job_artifacts, :locked
- end
- end
-
- def down
- with_lock_retries do
- add_column :ci_job_artifacts, :locked, :boolean
- end
- end
-end
diff --git a/db/post_migrate/20200826220745_add_compound_index_on_vulnerabilities_for_background_migration.rb b/db/post_migrate/20200826220745_add_compound_index_on_vulnerabilities_for_background_migration.rb
deleted file mode 100644
index da95f708cf9..00000000000
--- a/db/post_migrate/20200826220745_add_compound_index_on_vulnerabilities_for_background_migration.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddCompoundIndexOnVulnerabilitiesForBackgroundMigration < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_vulnerabilities_on_project_id_and_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :vulnerabilities, [:project_id, :id], name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200826220746_schedule_populate_resolved_on_default_branch_column.rb b/db/post_migrate/20200826220746_schedule_populate_resolved_on_default_branch_column.rb
deleted file mode 100644
index 6faa4fc8101..00000000000
--- a/db/post_migrate/20200826220746_schedule_populate_resolved_on_default_branch_column.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class SchedulePopulateResolvedOnDefaultBranchColumn < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- BATCH_SIZE = 100
- DELAY_INTERVAL = 5.minutes.to_i
- MIGRATION_CLASS = 'PopulateResolvedOnDefaultBranchColumn'
-
- disable_ddl_transaction!
-
- def up
- return unless Gitlab.ee?
-
- EE::Gitlab::BackgroundMigration::PopulateResolvedOnDefaultBranchColumn::Vulnerability.distinct.each_batch(of: BATCH_SIZE, column: :project_id) do |batch, index|
- project_ids = batch.pluck(:project_id)
- migrate_in(index * DELAY_INTERVAL, MIGRATION_CLASS, project_ids)
- end
- end
-
- def down
- # no-op
- # This migration schedules background tasks to populate
- # `resolved_on_default_branch` column of `vulnerabilities`
- # table so there is no rollback operation needed for this.
- end
-end
diff --git a/db/post_migrate/20200831065320_add_not_valid_not_null_constraint_to_mr_metrics.rb b/db/post_migrate/20200831065320_add_not_valid_not_null_constraint_to_mr_metrics.rb
deleted file mode 100644
index 35bfabc0358..00000000000
--- a/db/post_migrate/20200831065320_add_not_valid_not_null_constraint_to_mr_metrics.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddNotValidNotNullConstraintToMrMetrics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_not_null_constraint :merge_request_metrics, :target_project_id, validate: false
- end
-
- def down
- remove_not_null_constraint :merge_request_metrics, :target_project_id
- end
-end
diff --git a/db/post_migrate/20200831065322_add_tmp_index_to_target_project_id.rb b/db/post_migrate/20200831065322_add_tmp_index_to_target_project_id.rb
deleted file mode 100644
index 5d6d098ebfe..00000000000
--- a/db/post_migrate/20200831065322_add_tmp_index_to_target_project_id.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddTmpIndexToTargetProjectId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- TMP_INDEX_NAME = 'tmp_index_on_mr_metrics_target_project_id_null'
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :merge_request_metrics, :id, where: 'target_project_id IS NULL', name: TMP_INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :merge_request_metrics, name: TMP_INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb b/db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb
deleted file mode 100644
index 8693dca0000..00000000000
--- a/db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-class EnsureTargetProjectIdIsFilled < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- BACKGROUND_MIGRATION_CLASS = 'CopyMergeRequestTargetProjectToMergeRequestMetrics'
- BATCH_SIZE = 1_000
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- class MergeRequest < ActiveRecord::Base
- self.table_name = 'merge_requests'
- end
-
- class MergeRequestMetrics < ActiveRecord::Base
- include EachBatch
-
- belongs_to :merge_request
-
- self.table_name = 'merge_request_metrics'
- end
-
- def up
- Gitlab::BackgroundMigration.steal(BACKGROUND_MIGRATION_CLASS)
-
- # Do a manual update in case we lost BG jobs. The expected record count should be 0 or very low.
- MergeRequestMetrics.where(target_project_id: nil).each_batch do |scope|
- query_for_cte = scope.joins(:merge_request).select(
- MergeRequestMetrics.arel_table[:id].as('id'),
- MergeRequest.arel_table[:target_project_id].as('target_project_id')
- )
-
- MergeRequestMetrics.connection.execute <<-SQL
- WITH target_project_id_and_metrics_id as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- #{query_for_cte.to_sql}
- )
- UPDATE #{MergeRequestMetrics.connection.quote_table_name(MergeRequestMetrics.table_name)}
- SET target_project_id = target_project_id_and_metrics_id.target_project_id
- FROM target_project_id_and_metrics_id
- WHERE merge_request_metrics.id = target_project_id_and_metrics_id.id
- SQL
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200831074356_validate_not_null_constraint_on_mr_metrics.rb b/db/post_migrate/20200831074356_validate_not_null_constraint_on_mr_metrics.rb
deleted file mode 100644
index 8fd54186db3..00000000000
--- a/db/post_migrate/20200831074356_validate_not_null_constraint_on_mr_metrics.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateNotNullConstraintOnMrMetrics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- TMP_INDEX_NAME = 'tmp_index_on_mr_metrics_target_project_id_null'
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :merge_request_metrics, :target_project_id
-
- remove_concurrent_index_by_name :merge_request_metrics, name: TMP_INDEX_NAME
- end
-
- def down
- add_concurrent_index :merge_request_metrics, :id, where: 'target_project_id IS NULL', name: TMP_INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200831224343_populate_vulnerability_historical_statistics_for_year.rb b/db/post_migrate/20200831224343_populate_vulnerability_historical_statistics_for_year.rb
deleted file mode 100644
index 3f4fbfbebde..00000000000
--- a/db/post_migrate/20200831224343_populate_vulnerability_historical_statistics_for_year.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class PopulateVulnerabilityHistoricalStatisticsForYear < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- DELAY_INTERVAL = 5.minutes.to_i
- BATCH_SIZE = 50
- MIGRATION = 'PopulateVulnerabilityHistoricalStatistics'
-
- disable_ddl_transaction!
-
- class Vulnerability < ActiveRecord::Base
- self.table_name = 'vulnerabilities'
-
- include ::EachBatch
- end
-
- def up
- return unless Gitlab.ee?
-
- Vulnerability.select('project_id').distinct.each_batch(of: BATCH_SIZE, column: 'project_id') do |project_batch, index|
- migrate_in(index * DELAY_INTERVAL, MIGRATION, [project_batch.pluck(:project_id), 365])
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200901170135_backfill_modified_column_for_approval_merge_request_rules.rb b/db/post_migrate/20200901170135_backfill_modified_column_for_approval_merge_request_rules.rb
deleted file mode 100644
index 9a9866f38ec..00000000000
--- a/db/post_migrate/20200901170135_backfill_modified_column_for_approval_merge_request_rules.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillModifiedColumnForApprovalMergeRequestRules < ActiveRecord::Migration[6.0]
- include Gitlab::Database::Migrations::BackgroundMigrationHelpers
-
- disable_ddl_transaction!
-
- class ApprovalMergeRequestRule < ActiveRecord::Base
- include ::EachBatch
-
- self.table_name = 'approval_merge_request_rules'
- end
-
- def change
- queue_background_migration_jobs_by_range_at_intervals(ApprovalMergeRequestRule, 'AddModifiedToApprovalMergeRequestRule', 2.minutes, batch_size: 10_000)
- end
-end
diff --git a/db/post_migrate/20200901212304_drop_code_owner_column_from_approval_merge_request_rule.rb b/db/post_migrate/20200901212304_drop_code_owner_column_from_approval_merge_request_rule.rb
deleted file mode 100644
index 7524ae8e15b..00000000000
--- a/db/post_migrate/20200901212304_drop_code_owner_column_from_approval_merge_request_rule.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class DropCodeOwnerColumnFromApprovalMergeRequestRule < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- remove_column :approval_merge_request_rules, :code_owner
- end
- end
-
- def down
- unless column_exists?(:approval_merge_request_rules, :code_owner)
- with_lock_retries do
- add_column :approval_merge_request_rules, :code_owner, :boolean, default: false, null: false
- end
- end
-
- add_concurrent_index(
- :approval_merge_request_rules,
- [:merge_request_id, :code_owner, :name],
- unique: true,
- where: "code_owner = true AND section IS NULL",
- name: "approval_rule_name_index_for_code_owners"
- )
-
- add_concurrent_index(
- :approval_merge_request_rules,
- [:merge_request_id, :code_owner],
- name: "index_approval_merge_request_rules_1"
- )
- end
-end
diff --git a/db/post_migrate/20200903064431_add_created_at_index_to_audit_events.rb b/db/post_migrate/20200903064431_add_created_at_index_to_audit_events.rb
deleted file mode 100644
index 94dc2cb7adf..00000000000
--- a/db/post_migrate/20200903064431_add_created_at_index_to_audit_events.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class AddCreatedAtIndexToAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- INDEX_NAME = 'idx_audit_events_on_entity_id_desc_author_id_created_at'
- OLD_INDEX_NAME = 'index_audit_events_on_entity_id_entity_type_id_desc_author_id'
-
- def up
- add_concurrent_index(:audit_events, [:entity_id, :entity_type, :id, :author_id, :created_at], order: { id: :desc }, name: INDEX_NAME)
- remove_concurrent_index_by_name(:audit_events, OLD_INDEX_NAME)
- end
-
- def down
- add_concurrent_index(:audit_events, [:entity_id, :entity_type, :id, :author_id], order: { id: :desc }, name: OLD_INDEX_NAME)
- remove_concurrent_index_by_name(:audit_events, INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200904174901_backfill_cleanup_for_partitioned_audit_events.rb b/db/post_migrate/20200904174901_backfill_cleanup_for_partitioned_audit_events.rb
deleted file mode 100644
index 1d8240012d1..00000000000
--- a/db/post_migrate/20200904174901_backfill_cleanup_for_partitioned_audit_events.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillCleanupForPartitionedAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::PartitioningMigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- finalize_backfilling_partitioned_table :audit_events
- end
-
- def down
- # no op
- end
-end
diff --git a/db/post_migrate/20200907092715_add_not_null_constraint_to_user_on_group_import_states.rb b/db/post_migrate/20200907092715_add_not_null_constraint_to_user_on_group_import_states.rb
deleted file mode 100644
index 4f2edad43d8..00000000000
--- a/db/post_migrate/20200907092715_add_not_null_constraint_to_user_on_group_import_states.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddNotNullConstraintToUserOnGroupImportStates < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_not_null_constraint :group_import_states, :user_id, validate: false
- end
-
- def down
- remove_not_null_constraint :group_import_states, :user_id
- end
-end
diff --git a/db/post_migrate/20200907124300_complete_namespace_settings_migration.rb b/db/post_migrate/20200907124300_complete_namespace_settings_migration.rb
deleted file mode 100644
index 5881869ee3c..00000000000
--- a/db/post_migrate/20200907124300_complete_namespace_settings_migration.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class CompleteNamespaceSettingsMigration < ActiveRecord::Migration[5.2]
- DOWNTIME = false
- BATCH_SIZE = 10000
-
- class Namespace < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'namespaces'
- end
-
- def up
- Gitlab::BackgroundMigration.steal('BackfillNamespaceSettings')
-
- ensure_data_migration
- end
-
- def down
- # no-op
- end
-
- private
-
- def ensure_data_migration
- Namespace.each_batch(of: BATCH_SIZE) do |query|
- missing_count = query.where("NOT EXISTS (SELECT 1 FROM namespace_settings WHERE namespace_settings.namespace_id=namespaces.id)").limit(1).size
- if missing_count > 0
- min, max = query.pluck("MIN(id), MAX(id)").flatten
- # we expect low record count so inline execution is fine.
- Gitlab::BackgroundMigration::BackfillNamespaceSettings.new.perform(min, max)
- end
- end
- end
-end
diff --git a/db/post_migrate/20200908064229_add_partial_index_to_ci_builds_table_on_user_id_name.rb b/db/post_migrate/20200908064229_add_partial_index_to_ci_builds_table_on_user_id_name.rb
deleted file mode 100644
index 433fa957c38..00000000000
--- a/db/post_migrate/20200908064229_add_partial_index_to_ci_builds_table_on_user_id_name.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class AddPartialIndexToCiBuildsTableOnUserIdName < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- INDEX_NAME = 'index_partial_ci_builds_on_user_id_name_parser_features'
- FILTER_CONDITION = <<~SQL
- (((type)::text = 'Ci::Build'::text) AND
- ((name)::text = ANY (
- ARRAY[
- ('container_scanning'::character varying)::text,
- ('dast'::character varying)::text,
- ('dependency_scanning'::character varying)::text,
- ('license_management'::character varying)::text,
- ('license_scanning'::character varying)::text,
- ('sast'::character varying)::text,
- ('coverage_fuzzing'::character varying)::text,
- ('secret_detection'::character varying)::text
- ]
- ))
- )
- SQL
-
- def up
- add_concurrent_index(:ci_builds,
- [:user_id, :name],
- where: FILTER_CONDITION,
- name: INDEX_NAME)
- end
-
- def down
- remove_concurrent_index_by_name :ci_builds, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200908095446_update_location_fingerprint_column_for_cs.rb b/db/post_migrate/20200908095446_update_location_fingerprint_column_for_cs.rb
deleted file mode 100644
index fc2b7116ed1..00000000000
--- a/db/post_migrate/20200908095446_update_location_fingerprint_column_for_cs.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateLocationFingerprintColumnForCs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- BATCH_SIZE = 1_000
- INTERVAL = 2.minutes
-
- # 883_152 records
- def up
- return unless Gitlab.ee?
-
- migration = Gitlab::BackgroundMigration::UpdateLocationFingerprintForContainerScanningFindings
- migration_name = migration.to_s.demodulize
- relation = migration::Finding.container_scanning
- queue_background_migration_jobs_by_range_at_intervals(relation,
- migration_name,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- # intentionally blank
- end
-end
diff --git a/db/post_migrate/20200909161624_cleanup_group_import_states_with_null_user_id.rb b/db/post_migrate/20200909161624_cleanup_group_import_states_with_null_user_id.rb
deleted file mode 100644
index f956da81528..00000000000
--- a/db/post_migrate/20200909161624_cleanup_group_import_states_with_null_user_id.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupGroupImportStatesWithNullUserId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # With BATCH_SIZE=1000 and group_import_states.count=600 on GitLab.com
- # - 1 iteration will be run
- # - each batch requires on average ~2500ms
- # - 600 rows require on average ~1500ms
- # Expected total run time: ~2500ms
- BATCH_SIZE = 1000
-
- disable_ddl_transaction!
-
- class User < ActiveRecord::Base
- self.table_name = 'users'
- end
-
- class Namespace < ActiveRecord::Base
- self.table_name = 'namespaces'
-
- belongs_to :owner, class_name: 'CleanupGroupImportStatesWithNullUserId::User'
- end
-
- class Member < ActiveRecord::Base
- self.table_name = 'members'
- self.inheritance_column = :_type_disabled
-
- belongs_to :user, class_name: 'CleanupGroupImportStatesWithNullUserId::User'
- end
-
- class Group < Namespace
- OWNER = 50
-
- self.inheritance_column = :_type_disabled
-
- def default_owner
- owners.first || parent&.default_owner || owner
- end
-
- def parent
- Group.find_by_id(parent_id)
- end
-
- def owners
- Member.where(type: 'GroupMember', source_type: 'Namespace', source_id: id, requested_at: nil, access_level: OWNER).map(&:user)
- end
- end
-
- class GroupImportState < ActiveRecord::Base
- include ::EachBatch
-
- self.table_name = 'group_import_states'
-
- belongs_to :group, class_name: 'CleanupGroupImportStatesWithNullUserId::Group'
- belongs_to :user, class_name: 'CleanupGroupImportStatesWithNullUserId::User'
- end
-
- def up
- User.reset_column_information
- Namespace.reset_column_information
- Member.reset_column_information
- Group.reset_column_information
- GroupImportState.reset_column_information
-
- GroupImportState.each_batch(of: BATCH_SIZE) do |batch|
- batch.each do |group_import_state|
- owner_id = Group.find_by_id(group_import_state.group_id)&.default_owner&.id
-
- group_import_state.update!(user_id: owner_id) if owner_id
- end
- end
-
- GroupImportState.where(user_id: nil).delete_all
- end
-
- def down
- # no-op : can't go back to `NULL` without first dropping the `NOT NULL` constraint
- end
-end
diff --git a/db/post_migrate/20200909194014_change_pypi_python_version_type_cleanup.rb b/db/post_migrate/20200909194014_change_pypi_python_version_type_cleanup.rb
deleted file mode 100644
index c94f745e762..00000000000
--- a/db/post_migrate/20200909194014_change_pypi_python_version_type_cleanup.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class ChangePypiPythonVersionTypeCleanup < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- cleanup_concurrent_column_type_change(:packages_pypi_metadata, :required_python)
- end
-
- def down
- execute('UPDATE packages_pypi_metadata SET required_python = substring(required_python from 1 for 50)')
- change_column_type_concurrently :packages_pypi_metadata, :required_python, 'varchar(50)', batch_column_name: :package_id
- end
-end
diff --git a/db/post_migrate/20200909194524_increase_pypi_version_size.rb b/db/post_migrate/20200909194524_increase_pypi_version_size.rb
deleted file mode 100644
index 0273d49bba9..00000000000
--- a/db/post_migrate/20200909194524_increase_pypi_version_size.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class IncreasePypiVersionSize < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_text_limit :packages_pypi_metadata, :required_python, 255
- end
-
- def down
- remove_text_limit :packages_pypi_metadata, :required_python
- end
-end
diff --git a/db/post_migrate/20200910131217_tmp_index_for_fixing_inconsistent_vulnerability_occurrences.rb b/db/post_migrate/20200910131217_tmp_index_for_fixing_inconsistent_vulnerability_occurrences.rb
deleted file mode 100644
index 1985b8f1b67..00000000000
--- a/db/post_migrate/20200910131217_tmp_index_for_fixing_inconsistent_vulnerability_occurrences.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class TmpIndexForFixingInconsistentVulnerabilityOccurrences < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'tmp_index_for_fixing_inconsistent_vulnerability_occurrences'
- disable_ddl_transaction!
-
- def up
- # report_type: 2 container scanning
- add_concurrent_index(:vulnerability_occurrences, :id,
- where: "LENGTH(location_fingerprint) = 40 AND report_type = 2",
- name: INDEX_NAME)
- end
-
- def down
- remove_concurrent_index_by_name(:vulnerability_occurrences, INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200910131218_remove_duplicated_cs_findings.rb b/db/post_migrate/20200910131218_remove_duplicated_cs_findings.rb
deleted file mode 100644
index c5bfddfd265..00000000000
--- a/db/post_migrate/20200910131218_remove_duplicated_cs_findings.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveDuplicatedCsFindings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- BATCH_SIZE = 1_000
- INTERVAL = 2.minutes
-
- # 23_893 records will be updated
- # 23_893 records will be deleted
- def up
- return unless Gitlab.com?
-
- migration = Gitlab::BackgroundMigration::RemoveDuplicateCsFindings
- migration_name = migration.to_s.demodulize
- relation = migration::Finding.container_scanning.where("LENGTH(location_fingerprint) = 40")
- queue_background_migration_jobs_by_range_at_intervals(relation,
- migration_name,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- # intentionally blank
- end
-end
diff --git a/db/post_migrate/20200910155617_backfill_jira_tracker_deployment_type.rb b/db/post_migrate/20200910155617_backfill_jira_tracker_deployment_type.rb
deleted file mode 100644
index 9c978a20d25..00000000000
--- a/db/post_migrate/20200910155617_backfill_jira_tracker_deployment_type.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillJiraTrackerDeploymentType < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- # no-op
- # this migration was reverted
- # in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45205
- # due to https://gitlab.com/gitlab-com/gl-infra/production/-/issues/2820
- end
-
- def down
- # no-op
- # intentionally blank
- end
-end
diff --git a/db/post_migrate/20200910170908_ensure_filled_external_diff_store_on_merge_request_diffs.rb b/db/post_migrate/20200910170908_ensure_filled_external_diff_store_on_merge_request_diffs.rb
deleted file mode 100644
index 5070bd1c2f5..00000000000
--- a/db/post_migrate/20200910170908_ensure_filled_external_diff_store_on_merge_request_diffs.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class EnsureFilledExternalDiffStoreOnMergeRequestDiffs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- BACKGROUND_MIGRATION_CLASS = 'SetNullExternalDiffStoreToLocalValue'
- BATCH_SIZE = 5_000
- LOCAL_STORE = 1 # equal to ObjectStorage::Store::LOCAL
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- class MergeRequestDiff < ActiveRecord::Base
- self.table_name = 'merge_request_diffs'
-
- include ::EachBatch
- end
-
- def up
- Gitlab::BackgroundMigration.steal(BACKGROUND_MIGRATION_CLASS)
-
- # Do a manual update in case we lost BG jobs. The expected record count should be 0 or very low.
- MergeRequestDiff.where(external_diff_store: nil).each_batch(of: BATCH_SIZE) do |batch, index|
- batch.update_all(external_diff_store: LOCAL_STORE)
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200910175553_validate_not_null_external_diff_store_on_merge_request_diffs.rb b/db/post_migrate/20200910175553_validate_not_null_external_diff_store_on_merge_request_diffs.rb
deleted file mode 100644
index 4dc8ac96a4c..00000000000
--- a/db/post_migrate/20200910175553_validate_not_null_external_diff_store_on_merge_request_diffs.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateNotNullExternalDiffStoreOnMergeRequestDiffs < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Remove index which was only added to fill external_diff_store
- INDEX_NAME = 'index_merge_request_diffs_external_diff_store_is_null'
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :merge_request_diffs, :external_diff_store
-
- remove_concurrent_index_by_name :merge_request_diffs, INDEX_NAME
- end
-
- def down
- add_concurrent_index :merge_request_diffs, :id, where: 'external_diff_store IS NULL', name: INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200912153218_cleanup_admin_notification_email_application_setting_rename.rb b/db/post_migrate/20200912153218_cleanup_admin_notification_email_application_setting_rename.rb
deleted file mode 100644
index 35c54b64ddf..00000000000
--- a/db/post_migrate/20200912153218_cleanup_admin_notification_email_application_setting_rename.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupAdminNotificationEmailApplicationSettingRename < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- cleanup_concurrent_column_rename :application_settings, :admin_notification_email, :abuse_notification_email
- end
-
- def down
- undo_cleanup_concurrent_column_rename :application_settings, :admin_notification_email, :abuse_notification_email
- end
-end
diff --git a/db/post_migrate/20200915044225_schedule_migration_to_hashed_storage.rb b/db/post_migrate/20200915044225_schedule_migration_to_hashed_storage.rb
deleted file mode 100644
index 553d060dc58..00000000000
--- a/db/post_migrate/20200915044225_schedule_migration_to_hashed_storage.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleMigrationToHashedStorage < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
- MIGRATION = 'MigrateToHashedStorage'
-
- disable_ddl_transaction!
-
- def up
- migrate_async(MIGRATION)
- end
-
- def down
- # NO-OP
- end
-end
diff --git a/db/post_migrate/20200915185707_ensure_filled_file_store_on_package_files.rb b/db/post_migrate/20200915185707_ensure_filled_file_store_on_package_files.rb
deleted file mode 100644
index ec6f6df27bc..00000000000
--- a/db/post_migrate/20200915185707_ensure_filled_file_store_on_package_files.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class EnsureFilledFileStoreOnPackageFiles < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- BACKGROUND_MIGRATION_CLASS = 'SetNullPackageFilesFileStoreToLocalValue'
- BATCH_SIZE = 5_000
- LOCAL_STORE = 1 # equal to ObjectStorage::Store::LOCAL
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- module Packages
- class PackageFile < ActiveRecord::Base
- self.table_name = 'packages_package_files'
-
- include ::EachBatch
- end
- end
-
- def up
- Gitlab::BackgroundMigration.steal(BACKGROUND_MIGRATION_CLASS)
-
- # Do a manual update in case we lost BG jobs. The expected record count should be 0 or very low.
- Packages::PackageFile.where(file_store: nil).each_batch(of: BATCH_SIZE) do |batch, index|
- batch.update_all(file_store: LOCAL_STORE)
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200915191156_validate_not_null_file_store_on_package_files.rb b/db/post_migrate/20200915191156_validate_not_null_file_store_on_package_files.rb
deleted file mode 100644
index 5e6db9cec3f..00000000000
--- a/db/post_migrate/20200915191156_validate_not_null_file_store_on_package_files.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateNotNullFileStoreOnPackageFiles < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- # Remove index which was only added to fill file_store
- INDEX_NAME = 'index_packages_package_files_file_store_is_null'
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :packages_package_files, :file_store
-
- remove_concurrent_index_by_name :packages_package_files, INDEX_NAME
- end
-
- def down
- add_concurrent_index :packages_package_files, :id, where: 'file_store IS NULL', name: INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200916081749_remove_cycle_analytics_total_stage_data.rb b/db/post_migrate/20200916081749_remove_cycle_analytics_total_stage_data.rb
deleted file mode 100644
index 94c218c0c57..00000000000
--- a/db/post_migrate/20200916081749_remove_cycle_analytics_total_stage_data.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveCycleAnalyticsTotalStageData < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute("DELETE FROM analytics_cycle_analytics_group_stages WHERE name='production'")
- execute("DELETE FROM analytics_cycle_analytics_project_stages WHERE name='production'")
- end
-
- def down
- # Migration is irreversible
- end
-end
diff --git a/db/post_migrate/20200917135802_remove_duplicated_cs_findings_without_vulnerability_id.rb b/db/post_migrate/20200917135802_remove_duplicated_cs_findings_without_vulnerability_id.rb
deleted file mode 100644
index 0e161b5de78..00000000000
--- a/db/post_migrate/20200917135802_remove_duplicated_cs_findings_without_vulnerability_id.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveDuplicatedCsFindingsWithoutVulnerabilityId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- BATCH_SIZE = 1_000
-
- INTERVAL = 2.minutes
-
- # 1_500 records will be deleted
- def up
- return unless Gitlab.com?
-
- migration = Gitlab::BackgroundMigration::RemoveDuplicatedCsFindingsWithoutVulnerabilityId
- migration_name = migration.to_s.demodulize
- relation = migration::Finding.container_scanning.with_broken_fingerprint.where(vulnerability_id: nil)
- queue_background_migration_jobs_by_range_at_intervals(relation,
- migration_name,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20200917165525_update_index_on_namespaces_for_type_and_id.rb b/db/post_migrate/20200917165525_update_index_on_namespaces_for_type_and_id.rb
deleted file mode 100644
index 35b72b4f160..00000000000
--- a/db/post_migrate/20200917165525_update_index_on_namespaces_for_type_and_id.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateIndexOnNamespacesForTypeAndId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- OLD_INDEX_NAME = 'index_namespaces_on_type_partial'
- NEW_INDEX_NAME = 'index_namespaces_on_type_and_id_partial'
-
- def up
- add_concurrent_index(:namespaces, [:type, :id], where: 'type IS NOT NULL', name: NEW_INDEX_NAME)
-
- remove_concurrent_index_by_name(:namespaces, OLD_INDEX_NAME)
- end
-
- def down
- add_concurrent_index(:namespaces, :type, where: 'type IS NOT NULL', name: OLD_INDEX_NAME)
-
- remove_concurrent_index_by_name(:namespaces, NEW_INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20200922054642_drop_snowplow_iglu_registry_url_from_application_settings.rb b/db/post_migrate/20200922054642_drop_snowplow_iglu_registry_url_from_application_settings.rb
deleted file mode 100644
index d3e64f1f4c2..00000000000
--- a/db/post_migrate/20200922054642_drop_snowplow_iglu_registry_url_from_application_settings.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class DropSnowplowIgluRegistryUrlFromApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- remove_column :application_settings, :snowplow_iglu_registry_url, :string, limit: 255
- end
-end
diff --git a/db/post_migrate/20200922095954_remove_instance_statistics_visibility_private_from_application_settings.rb b/db/post_migrate/20200922095954_remove_instance_statistics_visibility_private_from_application_settings.rb
deleted file mode 100644
index 1d01e54013d..00000000000
--- a/db/post_migrate/20200922095954_remove_instance_statistics_visibility_private_from_application_settings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveInstanceStatisticsVisibilityPrivateFromApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- remove_column :application_settings, :instance_statistics_visibility_private
- end
-
- def down
- add_column :application_settings, :instance_statistics_visibility_private, :boolean, default: false, null: false
- end
-end
diff --git a/db/post_migrate/20200922170907_change_index_on_pipeline_status.rb b/db/post_migrate/20200922170907_change_index_on_pipeline_status.rb
deleted file mode 100644
index 61648788d7f..00000000000
--- a/db/post_migrate/20200922170907_change_index_on_pipeline_status.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class ChangeIndexOnPipelineStatus < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- OLD_INDEX_NAME = 'index_ci_pipelines_on_status'
- NEW_INDEX_NAME = 'index_ci_pipelines_on_status_and_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_pipelines, [:status, :id], name: NEW_INDEX_NAME
- remove_concurrent_index_by_name :ci_pipelines, name: OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :ci_pipelines, :status, name: OLD_INDEX_NAME
- remove_concurrent_index_by_name :ci_pipelines, name: NEW_INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20200922231755_remove_created_by_user_id_from_cluster_providers_aws.rb b/db/post_migrate/20200922231755_remove_created_by_user_id_from_cluster_providers_aws.rb
deleted file mode 100644
index 02cc9676202..00000000000
--- a/db/post_migrate/20200922231755_remove_created_by_user_id_from_cluster_providers_aws.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveCreatedByUserIdFromClusterProvidersAws < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_cluster_providers_aws_on_created_by_user_id'
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- remove_column :cluster_providers_aws, :created_by_user_id
- end
- end
-
- def down
- unless column_exists?(:cluster_providers_aws, :created_by_user_id)
- add_column :cluster_providers_aws, :created_by_user_id, :integer
- end
-
- add_concurrent_index :cluster_providers_aws, :created_by_user_id, name: INDEX_NAME
-
- add_concurrent_foreign_key :cluster_providers_aws, :users, column: :created_by_user_id, on_delete: :nullify
- end
-end
diff --git a/db/post_migrate/20200929052138_create_initial_versions_for_pre_versioning_terraform_states.rb b/db/post_migrate/20200929052138_create_initial_versions_for_pre_versioning_terraform_states.rb
deleted file mode 100644
index eff6ebfe5b4..00000000000
--- a/db/post_migrate/20200929052138_create_initial_versions_for_pre_versioning_terraform_states.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class CreateInitialVersionsForPreVersioningTerraformStates < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- execute <<-SQL
- INSERT INTO terraform_state_versions (terraform_state_id, created_at, updated_at, version, file_store, file)
- SELECT id, NOW(), NOW(), 0, file_store, file
- FROM terraform_states
- WHERE versioning_enabled = FALSE
- ON CONFLICT (terraform_state_id, version) DO NOTHING
- SQL
- end
-
- def down
- end
-end
diff --git a/db/post_migrate/20200929113254_remove_type_from_audit_events.rb b/db/post_migrate/20200929113254_remove_type_from_audit_events.rb
deleted file mode 100644
index 000dc0d2865..00000000000
--- a/db/post_migrate/20200929113254_remove_type_from_audit_events.rb
+++ /dev/null
@@ -1,125 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveTypeFromAuditEvents < ActiveRecord::Migration[6.0]
- include Gitlab::Database::SchemaHelpers
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- SOURCE_TABLE_NAME = 'audit_events'
- PARTITIONED_TABLE_NAME = 'audit_events_part_5fc467ac26'
- TRIGGER_FUNCTION_NAME = 'table_sync_function_2be879775d'
-
- def up
- with_lock_retries do
- remove_column SOURCE_TABLE_NAME, :type
-
- create_trigger_function(TRIGGER_FUNCTION_NAME, replace: true) do
- <<~SQL
- IF (TG_OP = 'DELETE') THEN
- DELETE FROM #{PARTITIONED_TABLE_NAME} where id = OLD.id;
- ELSIF (TG_OP = 'UPDATE') THEN
- UPDATE #{PARTITIONED_TABLE_NAME}
- SET author_id = NEW.author_id,
- entity_id = NEW.entity_id,
- entity_type = NEW.entity_type,
- details = NEW.details,
- ip_address = NEW.ip_address,
- author_name = NEW.author_name,
- entity_path = NEW.entity_path,
- target_details = NEW.target_details,
- target_type = NEW.target_type,
- target_id = NEW.target_id,
- created_at = NEW.created_at
- WHERE #{PARTITIONED_TABLE_NAME}.id = NEW.id;
- ELSIF (TG_OP = 'INSERT') THEN
- INSERT INTO #{PARTITIONED_TABLE_NAME} (id,
- author_id,
- entity_id,
- entity_type,
- details,
- ip_address,
- author_name,
- entity_path,
- target_details,
- target_type,
- target_id,
- created_at)
- VALUES (NEW.id,
- NEW.author_id,
- NEW.entity_id,
- NEW.entity_type,
- NEW.details,
- NEW.ip_address,
- NEW.author_name,
- NEW.entity_path,
- NEW.target_details,
- NEW.target_type,
- NEW.target_id,
- NEW.created_at);
- END IF;
- RETURN NULL;
- SQL
- end
-
- remove_column PARTITIONED_TABLE_NAME, :type
- end
- end
-
- def down
- with_lock_retries do
- add_column SOURCE_TABLE_NAME, :type, :string
- add_column PARTITIONED_TABLE_NAME, :type, :string
-
- create_trigger_function(TRIGGER_FUNCTION_NAME, replace: true) do
- <<~SQL
- IF (TG_OP = 'DELETE') THEN
- DELETE FROM #{PARTITIONED_TABLE_NAME} where id = OLD.id;
- ELSIF (TG_OP = 'UPDATE') THEN
- UPDATE #{PARTITIONED_TABLE_NAME}
- SET author_id = NEW.author_id,
- type = NEW.type,
- entity_id = NEW.entity_id,
- entity_type = NEW.entity_type,
- details = NEW.details,
- ip_address = NEW.ip_address,
- author_name = NEW.author_name,
- entity_path = NEW.entity_path,
- target_details = NEW.target_details,
- target_type = NEW.target_type,
- target_id = NEW.target_id,
- created_at = NEW.created_at
- WHERE #{PARTITIONED_TABLE_NAME}.id = NEW.id;
- ELSIF (TG_OP = 'INSERT') THEN
- INSERT INTO #{PARTITIONED_TABLE_NAME} (id,
- author_id,
- type,
- entity_id,
- entity_type,
- details,
- ip_address,
- author_name,
- entity_path,
- target_details,
- target_type,
- target_id,
- created_at)
- VALUES (NEW.id,
- NEW.author_id,
- NEW.type,
- NEW.entity_id,
- NEW.entity_type,
- NEW.details,
- NEW.ip_address,
- NEW.author_name,
- NEW.entity_path,
- NEW.target_details,
- NEW.target_type,
- NEW.target_id,
- NEW.created_at);
- END IF;
- RETURN NULL;
- SQL
- end
- end
- end
-end
diff --git a/db/post_migrate/20200929114107_schedule_migrate_u2f_webauthn.rb b/db/post_migrate/20200929114107_schedule_migrate_u2f_webauthn.rb
deleted file mode 100644
index b118ed271a2..00000000000
--- a/db/post_migrate/20200929114107_schedule_migrate_u2f_webauthn.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleMigrateU2fWebauthn < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- INTERVAL = 2.minutes.to_i
- DOWNTIME = false
- MIGRATION = 'MigrateU2fWebauthn'
- BATCH_SIZE = 1_000
-
- disable_ddl_transaction!
-
- class U2fRegistration < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'u2f_registrations'
- end
-
- def up
- say "Scheduling #{MIGRATION} background migration jobs"
-
- queue_background_migration_jobs_by_range_at_intervals(U2fRegistration, MIGRATION, INTERVAL, batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- # There is no real way back here, because
- # a) The U2fMigrator of webauthn_ruby gem only works in one way
- # b) This migration only pushes jobs to Sidekiq
- end
-end
diff --git a/db/post_migrate/20200930144340_set_job_waiter_ttl.rb b/db/post_migrate/20200930144340_set_job_waiter_ttl.rb
deleted file mode 100644
index 347fa4be5a0..00000000000
--- a/db/post_migrate/20200930144340_set_job_waiter_ttl.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class SetJobWaiterTtl < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- SCRIPT = <<~LUA
- if redis.call("ttl", KEYS[1]) < 0 then
- redis.call("expire", KEYS[1], 21600)
- end
- LUA
-
- def up
- Gitlab::Redis::SharedState.with do |redis|
- cursor_init = '0'
- cursor = cursor_init
-
- loop do
- cursor, keys = redis.scan(cursor, match: 'gitlab:job_waiter:*')
-
- redis.pipelined do |redis|
- keys.each { |k| redis.eval(SCRIPT, keys: [k]) }
- end
-
- break if cursor == cursor_init
- end
- end
- end
-
- def down
- end
-end
diff --git a/db/post_migrate/20201001022100_validate_designs_filename_text_limit.rb b/db/post_migrate/20201001022100_validate_designs_filename_text_limit.rb
deleted file mode 100644
index 35ed8c20671..00000000000
--- a/db/post_migrate/20201001022100_validate_designs_filename_text_limit.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class ValidateDesignsFilenameTextLimit < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_text_limit :design_management_designs, :filename
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20201001101136_remove_index_on_issues_relative_position.rb b/db/post_migrate/20201001101136_remove_index_on_issues_relative_position.rb
deleted file mode 100644
index 605a167c0d5..00000000000
--- a/db/post_migrate/20201001101136_remove_index_on_issues_relative_position.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexOnIssuesRelativePosition < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- INDEX_NAME = 'index_issues_on_relative_position'
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name(:issues, INDEX_NAME)
- end
-
- def down
- add_concurrent_index(:issues, :relative_position, name: INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20201002094617_remove_container_scanning_report_type_index.rb b/db/post_migrate/20201002094617_remove_container_scanning_report_type_index.rb
deleted file mode 100644
index a591fc185c4..00000000000
--- a/db/post_migrate/20201002094617_remove_container_scanning_report_type_index.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveContainerScanningReportTypeIndex < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'idx_container_scanning_findings'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name(:vulnerability_occurrences, INDEX_NAME)
- end
-
- def down
- # report_type: 2 container scanning
- add_concurrent_index(
- :vulnerability_occurrences,
- :id,
- where: 'report_type = 2',
- name: INDEX_NAME
- )
- end
-end
diff --git a/db/post_migrate/20201002175953_add_index_for_merged_merge_requests.rb b/db/post_migrate/20201002175953_add_index_for_merged_merge_requests.rb
deleted file mode 100644
index cd663f3da89..00000000000
--- a/db/post_migrate/20201002175953_add_index_for_merged_merge_requests.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexForMergedMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'idx_merge_requests_on_merged_state'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :merge_requests,
- :id,
- where: 'state_id = 3',
- name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :merge_requests, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20201005094331_migrate_compliance_framework_enum_to_database_framework_record.rb b/db/post_migrate/20201005094331_migrate_compliance_framework_enum_to_database_framework_record.rb
deleted file mode 100644
index a5fab8576e4..00000000000
--- a/db/post_migrate/20201005094331_migrate_compliance_framework_enum_to_database_framework_record.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateComplianceFrameworkEnumToDatabaseFrameworkRecord < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- class TmpComplianceFramework < ActiveRecord::Base
- self.table_name = 'compliance_management_frameworks'
- end
-
- class TmpProjectSettings < ActiveRecord::Base
- # Maps data between ComplianceManagement::ComplianceFramework::FRAMEWORKS(enum) and new ComplianceManagement::Framework model
- ENUM_FRAMEWORK_MAPPING = {
- 1 => {
- name: 'GDPR',
- description: 'General Data Protection Regulation',
- color: '#1aaa55'
- }.freeze,
- 2 => {
- name: 'HIPAA',
- description: 'Health Insurance Portability and Accountability Act',
- color: '#1f75cb'
- }.freeze,
- 3 => {
- name: 'PCI-DSS',
- description: 'Payment Card Industry-Data Security Standard',
- color: '#6666c4'
- }.freeze,
- 4 => {
- name: 'SOC 2',
- description: 'Service Organization Control 2',
- color: '#dd2b0e'
- }.freeze,
- 5 => {
- name: 'SOX',
- description: 'Sarbanes-Oxley',
- color: '#fc9403'
- }.freeze
- }.freeze
-
- self.table_name = 'project_compliance_framework_settings'
-
- include EachBatch
-
- def raw_compliance_framework
- # Because we have an `enum` definition in ComplianceManagement::ComplianceFramework::ProjectSettings, this is very unlikely to fail.
- ENUM_FRAMEWORK_MAPPING.fetch(framework).merge(namespace_id: root_namespace_id)
- end
- end
-
- def up
- TmpComplianceFramework.reset_column_information
- TmpProjectSettings.reset_column_information
-
- # This is our standard recursive namespace query, we use it to determine the root_namespace_id in the same query.
- lateral_join = <<~SQL
- INNER JOIN LATERAL (
- WITH RECURSIVE "base_and_ancestors" AS (
- (
- SELECT "ns".* FROM "namespaces" as ns WHERE "ns"."id" = projects.namespace_id
- ) UNION
- (
- SELECT "ns".* FROM "namespaces" as ns, "base_and_ancestors" WHERE "ns"."id" = "base_and_ancestors"."parent_id"
- )
- ) SELECT "namespaces".* FROM "base_and_ancestors" AS "namespaces" WHERE parent_id IS NULL LIMIT 1) AS root_namespaces ON TRUE
- SQL
-
- TmpProjectSettings.each_batch(of: 100) do |query|
- project_settings_with_root_group = query
- .select(:project_id, :framework, 'root_namespaces.id as root_namespace_id')
- .from("(SELECT * FROM project_compliance_framework_settings) as project_compliance_framework_settings") # this is needed for the LATERAL JOIN
- .joins("INNER JOIN projects on projects.id = project_compliance_framework_settings.project_id")
- .joins(lateral_join)
- .to_a
-
- ActiveRecord::Base.transaction do
- raw_frameworks = project_settings_with_root_group.map(&:raw_compliance_framework)
- TmpComplianceFramework.insert_all(raw_frameworks.uniq) # Create compliance frameworks per group
-
- unique_namespace_ids = project_settings_with_root_group.map(&:root_namespace_id).uniq
-
- framework_records = TmpComplianceFramework.select(:id, :namespace_id, :name).where(namespace_id: unique_namespace_ids)
-
- project_settings_with_root_group.each do |project_setting|
- framework = framework_records.find do |record|
- # name is unique within a group
- record.name == project_setting.raw_compliance_framework[:name] && record[:namespace_id] == project_setting.raw_compliance_framework[:namespace_id]
- end
-
- project_setting.update_column(:framework_id, framework.id)
- end
- end
- end
- end
-
- def down
- # data migration, no-op
- end
-end
diff --git a/db/post_migrate/20201005153955_add_not_null_constraint_to_compliance_project_settings.rb b/db/post_migrate/20201005153955_add_not_null_constraint_to_compliance_project_settings.rb
deleted file mode 100644
index 6d47cbe9f08..00000000000
--- a/db/post_migrate/20201005153955_add_not_null_constraint_to_compliance_project_settings.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddNotNullConstraintToComplianceProjectSettings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_not_null_constraint(:project_compliance_framework_settings, :framework_id)
-
- change_column_null(:compliance_management_frameworks, :namespace_id, false)
- end
-
- def down
- change_column_null(:compliance_management_frameworks, :namespace_id, true)
-
- remove_not_null_constraint(:project_compliance_framework_settings, :framework_id)
- end
-end
diff --git a/db/post_migrate/20201014142521_schedule_sync_blocking_issues_count.rb b/db/post_migrate/20201014142521_schedule_sync_blocking_issues_count.rb
deleted file mode 100644
index 30a8ea591da..00000000000
--- a/db/post_migrate/20201014142521_schedule_sync_blocking_issues_count.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'set'
-
-class ScheduleSyncBlockingIssuesCount < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- BATCH_SIZE = 50
- DELAY_INTERVAL = 120.seconds.to_i
- MIGRATION = 'SyncBlockingIssuesCount'
-
- disable_ddl_transaction!
-
- class TmpIssueLink < ActiveRecord::Base
- self.table_name = 'issue_links'
-
- include EachBatch
- end
-
- def up
- return unless Gitlab.ee?
-
- issue_link_ids = SortedSet.new
-
- TmpIssueLink.distinct.select(:source_id).where(link_type: 1).each_batch(of: 1000, column: :source_id) do |query|
- issue_link_ids.merge(query.pluck(:source_id))
- end
-
- TmpIssueLink.distinct.select(:target_id).where(link_type: 2).each_batch(of: 1000, column: :target_id) do |query|
- issue_link_ids.merge(query.pluck(:target_id))
- end
-
- issue_link_ids.each_slice(BATCH_SIZE).with_index do |items, index|
- start_id, *, end_id = items
-
- arguments = [start_id, end_id]
-
- final_delay = DELAY_INTERVAL * (index + 1)
- migrate_in(final_delay, MIGRATION, arguments)
- end
- end
-
- def down
- # NO OP
- end
-end
diff --git a/db/post_migrate/20201015073808_schedule_blocked_by_links_replacement.rb b/db/post_migrate/20201015073808_schedule_blocked_by_links_replacement.rb
deleted file mode 100644
index dd8cbb57136..00000000000
--- a/db/post_migrate/20201015073808_schedule_blocked_by_links_replacement.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleBlockedByLinksReplacement < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INTERVAL = 2.minutes
- # at the time of writing there were 47600 blocked_by issues:
- # estimated time is 48 batches * 2 minutes -> 100 minutes
- BATCH_SIZE = 1000
- MIGRATION = 'ReplaceBlockedByLinks'
-
- disable_ddl_transaction!
-
- class IssueLink < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'issue_links'
- end
-
- def up
- # no-op
- # superseded by db/post_migrate/20201102073808_schedule_blocked_by_links_replacement_second_try.rb
- end
-
- def down
- end
-end
diff --git a/db/post_migrate/20201015154527_add_index_on_services_for_usage_data.rb b/db/post_migrate/20201015154527_add_index_on_services_for_usage_data.rb
deleted file mode 100644
index f85ab97420b..00000000000
--- a/db/post_migrate/20201015154527_add_index_on_services_for_usage_data.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnServicesForUsageData < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_services_on_type_id_when_active_and_project_id_not_null'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :services, [:type, :id], where: 'active = TRUE AND project_id IS NOT NULL', name: INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :services, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20201019094741_rename_sitemap_root_namespaces.rb b/db/post_migrate/20201019094741_rename_sitemap_root_namespaces.rb
deleted file mode 100644
index 20812a53bfb..00000000000
--- a/db/post_migrate/20201019094741_rename_sitemap_root_namespaces.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class RenameSitemapRootNamespaces < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- include Gitlab::Database::RenameReservedPathsMigration::V1
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # We're taking over the /sitemap.xml and /sitemap.xml.gz namespaces
- # since they're necessary for the default behavior of Sitemaps
- def up
- disable_statement_timeout do
- rename_root_paths(['sitemap.xml', 'sitemap.xml.gz'])
- end
- end
-
- def down
- disable_statement_timeout do
- revert_renames
- end
- end
-end
diff --git a/db/post_migrate/20201020102551_remove_index_service_for_usage_data.rb b/db/post_migrate/20201020102551_remove_index_service_for_usage_data.rb
deleted file mode 100644
index a0d39ecd2c1..00000000000
--- a/db/post_migrate/20201020102551_remove_index_service_for_usage_data.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIndexServiceForUsageData < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_services_on_type_id_when_active_not_instance_not_template'
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :services, INDEX_NAME
- end
-
- def down
- add_concurrent_index :services, [:type, :id], where: 'active = TRUE AND instance = FALSE AND template = FALSE', name: INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20201026051643_remove_scanned_resources_count_from_security_scans.rb b/db/post_migrate/20201026051643_remove_scanned_resources_count_from_security_scans.rb
deleted file mode 100644
index 208448e2278..00000000000
--- a/db/post_migrate/20201026051643_remove_scanned_resources_count_from_security_scans.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveScannedResourcesCountFromSecurityScans < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- remove_column :security_scans, :scanned_resources_count
- end
-
- def down
- add_column :security_scans, :scanned_resources_count, :integer
- end
-end
diff --git a/db/post_migrate/20201026182253_schedule_populate_vulnerability_feedback_pipeline_id.rb b/db/post_migrate/20201026182253_schedule_populate_vulnerability_feedback_pipeline_id.rb
deleted file mode 100644
index 2df475ab2a8..00000000000
--- a/db/post_migrate/20201026182253_schedule_populate_vulnerability_feedback_pipeline_id.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class SchedulePopulateVulnerabilityFeedbackPipelineId < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 100
- MIGRATION = 'PopulateVulnerabilityFeedbackPipelineId'
-
- disable_ddl_transaction!
-
- def up
- return unless Gitlab.ee?
-
- vulnerability_feedback = exec_query <<~SQL
- SELECT DISTINCT "vulnerability_feedback"."project_id"
- FROM "vulnerability_feedback"
- WHERE "vulnerability_feedback"."pipeline_id" IS NULL
- ORDER BY "vulnerability_feedback"."project_id" ASC
- SQL
-
- return if vulnerability_feedback.rows.blank?
-
- vulnerability_feedback.rows.flatten.in_groups_of(BATCH_SIZE, false).each_with_index do |project_ids, index|
- migrate_in(index * INTERVAL, MIGRATION, [project_ids])
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20201026185514_ensure_u2f_registrations_migrated.rb b/db/post_migrate/20201026185514_ensure_u2f_registrations_migrated.rb
deleted file mode 100644
index bb1ac3dee4c..00000000000
--- a/db/post_migrate/20201026185514_ensure_u2f_registrations_migrated.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class EnsureU2fRegistrationsMigrated < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- BACKGROUND_MIGRATION_CLASS = 'MigrateU2fWebauthn'
- BATCH_SIZE = 100
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- class U2fRegistration < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'u2f_registrations'
- end
-
- def up
- Gitlab::BackgroundMigration.steal(BACKGROUND_MIGRATION_CLASS)
-
- # Do a manual update in case we lost BG jobs. The expected record count should be 0 or very low.
- U2fRegistration
- .joins("LEFT JOIN webauthn_registrations ON webauthn_registrations.u2f_registration_id = u2f_registrations.id")
- .where(webauthn_registrations: { u2f_registration_id: nil })
- .each_batch(of: BATCH_SIZE) do |batch, index|
- batch.each do |record|
- Gitlab::BackgroundMigration::MigrateU2fWebauthn.new.perform(record.id, record.id)
- rescue StandardError => e
- Gitlab::ErrorTracking.track_exception(e, u2f_registration_id: record.id)
- end
- end
- end
-
- def down
- # no-op (we can't "unsteal" migrations)
- end
-end
diff --git a/db/post_migrate/20201028160832_schedule_populate_missing_dismissal_information_for_vulnerabilities.rb b/db/post_migrate/20201028160832_schedule_populate_missing_dismissal_information_for_vulnerabilities.rb
deleted file mode 100644
index f358ea863db..00000000000
--- a/db/post_migrate/20201028160832_schedule_populate_missing_dismissal_information_for_vulnerabilities.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class SchedulePopulateMissingDismissalInformationForVulnerabilities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- BATCH_SIZE = 1_000
- DELAY_INTERVAL = 3.minutes.to_i
- MIGRATION_CLASS = 'PopulateMissingVulnerabilityDismissalInformation'
-
- disable_ddl_transaction!
-
- def up
- ::Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation::Vulnerability.broken.each_batch(of: BATCH_SIZE) do |batch, index|
- vulnerability_ids = batch.pluck(:id)
- migrate_in(index * DELAY_INTERVAL, MIGRATION_CLASS, vulnerability_ids)
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20201028182809_backfill_jira_tracker_deployment_type2.rb b/db/post_migrate/20201028182809_backfill_jira_tracker_deployment_type2.rb
deleted file mode 100644
index 63a0554433c..00000000000
--- a/db/post_migrate/20201028182809_backfill_jira_tracker_deployment_type2.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillJiraTrackerDeploymentType2 < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- MIGRATION = 'BackfillJiraTrackerDeploymentType2'
- DELAY_INTERVAL = 2.minutes
- BATCH_SIZE = 1000
-
- disable_ddl_transaction!
-
- class JiraTrackerData < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'jira_tracker_data'
- end
-
- def up
- queue_background_migration_jobs_by_range_at_intervals(
- JiraTrackerData.where(deployment_type: 0),
- MIGRATION,
- DELAY_INTERVAL,
- batch_size: BATCH_SIZE,
- track_jobs: true)
- end
-
- def down
- # NOOP
- end
-end
diff --git a/db/post_migrate/20201029052241_migrate_geo_blob_verification_primary_worker_sidekiq_queue.rb b/db/post_migrate/20201029052241_migrate_geo_blob_verification_primary_worker_sidekiq_queue.rb
deleted file mode 100644
index 64d22863389..00000000000
--- a/db/post_migrate/20201029052241_migrate_geo_blob_verification_primary_worker_sidekiq_queue.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-# See https://docs.gitlab.com/ee/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class MigrateGeoBlobVerificationPrimaryWorkerSidekiqQueue < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- sidekiq_queue_migrate 'geo:geo_blob_verification_primary', to: 'geo:geo_verification'
- end
-
- def down
- sidekiq_queue_migrate 'geo:geo_verification', to: 'geo:geo_blob_verification_primary'
- end
-end
diff --git a/db/post_migrate/20201029144157_cleanup_application_settings_to_allow_deny_rename.rb b/db/post_migrate/20201029144157_cleanup_application_settings_to_allow_deny_rename.rb
deleted file mode 100644
index bb6fe4258c5..00000000000
--- a/db/post_migrate/20201029144157_cleanup_application_settings_to_allow_deny_rename.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupApplicationSettingsToAllowDenyRename < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- def up
- cleanup_concurrent_column_rename :application_settings, :domain_blacklist_enabled, :domain_denylist_enabled
- cleanup_concurrent_column_rename :application_settings, :domain_blacklist, :domain_denylist
- cleanup_concurrent_column_rename :application_settings, :domain_whitelist, :domain_allowlist
- end
-
- def down
- undo_cleanup_concurrent_column_rename :application_settings, :domain_blacklist_enabled, :domain_denylist_enabled
- undo_cleanup_concurrent_column_rename :application_settings, :domain_blacklist, :domain_denylist
- undo_cleanup_concurrent_column_rename :application_settings, :domain_whitelist, :domain_allowlist
- end
-end
diff --git a/db/post_migrate/20201030121314_schedule_update_existing_users_that_require_two_factor_auth.rb b/db/post_migrate/20201030121314_schedule_update_existing_users_that_require_two_factor_auth.rb
deleted file mode 100644
index 6a031c28ed7..00000000000
--- a/db/post_migrate/20201030121314_schedule_update_existing_users_that_require_two_factor_auth.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-# # frozen_string_literal: true
-
-class ScheduleUpdateExistingUsersThatRequireTwoFactorAuth < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- MIGRATION = 'UpdateExistingUsersThatRequireTwoFactorAuth'
- DELAY_INTERVAL = 2.minutes
- BATCH_SIZE = 1000
- INDEX_NAME = 'index_users_on_require_two_factor_authentication_from_group'
-
- disable_ddl_transaction!
-
- class User < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'users'
- end
-
- def up
- add_concurrent_index :users,
- :require_two_factor_authentication_from_group,
- where: 'require_two_factor_authentication_from_group = TRUE',
- name: INDEX_NAME
-
- relation = User.where(require_two_factor_authentication_from_group: true)
-
- queue_background_migration_jobs_by_range_at_intervals(
- relation, MIGRATION, DELAY_INTERVAL, batch_size: BATCH_SIZE)
- end
-
- def down
- remove_concurrent_index_by_name :users, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20201030203854_backfill_design_iids.rb b/db/post_migrate/20201030203854_backfill_design_iids.rb
deleted file mode 100644
index 7acca6ad93d..00000000000
--- a/db/post_migrate/20201030203854_backfill_design_iids.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class BackfillDesignIids < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- class Designs < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'design_management_designs'
- end
-
- def up
- backfill = ::Gitlab::BackgroundMigration::BackfillDesignInternalIds.new(Designs)
-
- Designs.select(:project_id).distinct.each_batch(of: 100, column: :project_id) do |relation|
- backfill.perform(relation)
- end
- end
-
- def down
- # NOOP
- end
-end
diff --git a/db/post_migrate/20201102073808_schedule_blocked_by_links_replacement_second_try.rb b/db/post_migrate/20201102073808_schedule_blocked_by_links_replacement_second_try.rb
deleted file mode 100644
index 217d4f81d26..00000000000
--- a/db/post_migrate/20201102073808_schedule_blocked_by_links_replacement_second_try.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleBlockedByLinksReplacementSecondTry < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INTERVAL = 2.minutes
- # at the time of writing there were 12931 blocked_by issues:
- # estimated time is 13 batches * 2 minutes -> 26 minutes
- BATCH_SIZE = 1000
- MIGRATION = 'ReplaceBlockedByLinks'
-
- disable_ddl_transaction!
-
- class IssueLink < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'issue_links'
- end
-
- def up
- relation = IssueLink.where(link_type: 2)
-
- queue_background_migration_jobs_by_range_at_intervals(
- relation, MIGRATION, INTERVAL, batch_size: BATCH_SIZE)
- end
-
- def down
- end
-end
diff --git a/db/post_migrate/20201102112206_rename_sitemap_namespace.rb b/db/post_migrate/20201102112206_rename_sitemap_namespace.rb
deleted file mode 100644
index b2e610d68db..00000000000
--- a/db/post_migrate/20201102112206_rename_sitemap_namespace.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class RenameSitemapNamespace < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
- include Gitlab::Database::RenameReservedPathsMigration::V1
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- # We're taking over the /sitemap namespace
- # since it's necessary for the default behavior of Sitemaps
- def up
- disable_statement_timeout do
- rename_root_paths(['sitemap'])
- end
- end
-
- def down
- disable_statement_timeout do
- revert_renames
- end
- end
-end
diff --git a/db/post_migrate/20201102114018_remove_storage_size_limit_from_application_settings.rb b/db/post_migrate/20201102114018_remove_storage_size_limit_from_application_settings.rb
deleted file mode 100644
index 6646cf2ad0c..00000000000
--- a/db/post_migrate/20201102114018_remove_storage_size_limit_from_application_settings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveStorageSizeLimitFromApplicationSettings < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def up
- remove_column :application_settings, :namespace_storage_size_limit
- end
-
- def down
- add_column :application_settings, :namespace_storage_size_limit, :bigint, default: 0
- end
-end
diff --git a/db/post_migrate/20201102152554_add_not_null_check_on_iid_on_design_manangement_designs.rb b/db/post_migrate/20201102152554_add_not_null_check_on_iid_on_design_manangement_designs.rb
deleted file mode 100644
index 861a0c3c27a..00000000000
--- a/db/post_migrate/20201102152554_add_not_null_check_on_iid_on_design_manangement_designs.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class AddNotNullCheckOnIidOnDesignManangementDesigns < ActiveRecord::Migration[6.0]
- include ::Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- add_not_null_constraint(:design_management_designs, :iid)
- end
-
- def down
- remove_not_null_constraint(:design_management_designs, :iid)
- end
-end
diff --git a/db/post_migrate/20201102152945_truncate_security_findings_table.rb b/db/post_migrate/20201102152945_truncate_security_findings_table.rb
deleted file mode 100644
index 8bfaa31f0de..00000000000
--- a/db/post_migrate/20201102152945_truncate_security_findings_table.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class TruncateSecurityFindingsTable < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- return unless Gitlab.dev_env_or_com?
-
- with_lock_retries do
- connection.execute('TRUNCATE security_findings RESTART IDENTITY')
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20201103013242_remove_terraform_state_verification_columns.rb b/db/post_migrate/20201103013242_remove_terraform_state_verification_columns.rb
deleted file mode 100644
index b1cd9790ead..00000000000
--- a/db/post_migrate/20201103013242_remove_terraform_state_verification_columns.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveTerraformStateVerificationColumns < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- transaction do
- remove_column :terraform_states, :verification_retry_at, :datetime_with_timezone
- remove_column :terraform_states, :verified_at, :datetime_with_timezone
- remove_column :terraform_states, :verification_retry_count, :integer, limit: 2
- remove_column :terraform_states, :verification_checksum, :binary, using: 'verification_checksum::bytea'
- remove_column :terraform_states, :verification_failure, :text
- end
- end
-
- def down
- add_column(:terraform_states, :verification_retry_at, :datetime_with_timezone) unless column_exists?(:terraform_states, :verification_retry_at)
- add_column(:terraform_states, :verified_at, :datetime_with_timezone) unless column_exists?(:terraform_states, :verified_at)
- add_column(:terraform_states, :verification_retry_count, :integer, limit: 2) unless column_exists?(:terraform_states, :verification_retry_count)
- add_column(:terraform_states, :verification_checksum, :binary, using: 'verification_checksum::bytea') unless column_exists?(:terraform_states, :verification_checksum)
- add_column(:terraform_states, :verification_failure, :text) unless column_exists?(:terraform_states, :verification_failure)
-
- add_text_limit :terraform_states, :verification_failure, 255
- end
-end
diff --git a/db/post_migrate/20201103110018_schedule_merge_request_cleanup_schedules_backfill.rb b/db/post_migrate/20201103110018_schedule_merge_request_cleanup_schedules_backfill.rb
deleted file mode 100644
index 77057205b09..00000000000
--- a/db/post_migrate/20201103110018_schedule_merge_request_cleanup_schedules_backfill.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleMergeRequestCleanupSchedulesBackfill < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- MIGRATION = 'BackfillMergeRequestCleanupSchedules'
- DELAY_INTERVAL = 2.minutes
- BATCH_SIZE = 10_000
- TEMP_INDEX_NAME = 'merge_requests_state_id_temp_index'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :merge_requests, :id, name: TEMP_INDEX_NAME, where: "state_id IN (2, 3)"
-
- eligible_mrs = Gitlab::BackgroundMigration::BackfillMergeRequestCleanupSchedules::MergeRequest.eligible
-
- queue_background_migration_jobs_by_range_at_intervals(
- eligible_mrs,
- MIGRATION,
- DELAY_INTERVAL,
- batch_size: BATCH_SIZE
- )
- end
-
- def down
- remove_concurrent_index_by_name :merge_requests, TEMP_INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20201103192526_schedule_populate_has_vulnerabilities.rb b/db/post_migrate/20201103192526_schedule_populate_has_vulnerabilities.rb
deleted file mode 100644
index bed90af09dc..00000000000
--- a/db/post_migrate/20201103192526_schedule_populate_has_vulnerabilities.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class SchedulePopulateHasVulnerabilities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- BATCH_SIZE = 1_000
- DELAY_INTERVAL = 2.minutes
- MIGRATION_CLASS = 'PopulateHasVulnerabilities'
-
- disable_ddl_transaction!
-
- def up
- Gitlab::BackgroundMigration::PopulateHasVulnerabilities::Vulnerability.distinct.each_batch(of: BATCH_SIZE, column: :project_id) do |batch, index|
- project_ids = batch.pluck(:project_id)
-
- migrate_in(index * DELAY_INTERVAL, MIGRATION_CLASS, project_ids)
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20201104124300_ensure_namespace_settings_creation.rb b/db/post_migrate/20201104124300_ensure_namespace_settings_creation.rb
deleted file mode 100644
index 08f92d21f44..00000000000
--- a/db/post_migrate/20201104124300_ensure_namespace_settings_creation.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-class EnsureNamespaceSettingsCreation < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- BATCH_SIZE = 10000
- MIGRATION = 'BackfillNamespaceSettings'
- DELAY_INTERVAL = 2.minutes.to_i
-
- disable_ddl_transaction!
-
- class Namespace < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'namespaces'
- end
-
- def up
- ensure_data_migration
- end
-
- def down
- # no-op
- end
-
- private
-
- def ensure_data_migration
- Namespace.each_batch(of: BATCH_SIZE) do |query, index|
- missing_count = query.where("NOT EXISTS (SELECT 1 FROM namespace_settings WHERE namespace_settings.namespace_id=namespaces.id)").limit(1).size
-
- if missing_count > 0
- ids_range = query.pluck("MIN(id), MAX(id)").flatten
-
- migrate_in(index * DELAY_INTERVAL, MIGRATION, ids_range)
- end
- end
- end
-end
diff --git a/db/post_migrate/20201106082723_add_merge_request_jira_reference_indexes.rb b/db/post_migrate/20201106082723_add_merge_request_jira_reference_indexes.rb
deleted file mode 100644
index d69f57c6088..00000000000
--- a/db/post_migrate/20201106082723_add_merge_request_jira_reference_indexes.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-class AddMergeRequestJiraReferenceIndexes < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- DESCRIPTION_INDEX_NAME = 'index_merge_requests_on_target_project_id_iid_jira_description'
- TITLE_INDEX_NAME = 'index_merge_requests_on_target_project_id_and_iid_jira_title'
-
- JIRA_KEY_REGEX = '[A-Z][A-Z_0-9]+-\d+'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(
- :merge_requests,
- [:target_project_id, :iid],
- name: TITLE_INDEX_NAME,
- using: :btree,
- where: "(merge_requests.title)::text ~ '#{JIRA_KEY_REGEX}'::text"
- )
-
- add_concurrent_index(
- :merge_requests,
- [:target_project_id, :iid],
- name: DESCRIPTION_INDEX_NAME,
- using: :btree,
- where: "(merge_requests.description)::text ~ '#{JIRA_KEY_REGEX}'::text"
- )
- end
-
- def down
- remove_concurrent_index_by_name(
- :merge_requests,
- TITLE_INDEX_NAME
- )
-
- remove_concurrent_index_by_name(
- :merge_requests,
- DESCRIPTION_INDEX_NAME
- )
- end
-end
diff --git a/db/post_migrate/20201106134950_deduplicate_epic_iids.rb b/db/post_migrate/20201106134950_deduplicate_epic_iids.rb
deleted file mode 100644
index 8fddc81057b..00000000000
--- a/db/post_migrate/20201106134950_deduplicate_epic_iids.rb
+++ /dev/null
@@ -1,121 +0,0 @@
-# frozen_string_literal: true
-
-class DeduplicateEpicIids < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INDEX_NAME = 'index_epics_on_group_id_and_iid'
-
- disable_ddl_transaction!
-
- class Epic < ActiveRecord::Base
- end
-
- class InternalId < ActiveRecord::Base
- class << self
- def generate_next(subject, scope, usage, init)
- InternalIdGenerator.new(subject, scope, usage, init).generate
- end
- end
-
- # Increments #last_value and saves the record
- #
- # The operation locks the record and gathers a `ROW SHARE` lock (in PostgreSQL).
- # As such, the increment is atomic and safe to be called concurrently.
- def increment_and_save!
- update_and_save { self.last_value = (last_value || 0) + 1 }
- end
-
- private
-
- def update_and_save(&block)
- lock!
- yield
- save!
- last_value
- end
- end
-
- # See app/models/internal_id
- class InternalIdGenerator
- attr_reader :subject, :scope, :scope_attrs, :usage, :init
-
- def initialize(subject, scope, usage, init = nil)
- @subject = subject
- @scope = scope
- @usage = usage
- @init = init
-
- raise ArgumentError, 'Scope is not well-defined, need at least one column for scope (given: 0)' if scope.empty? || usage.to_s != 'epics'
- end
-
- # Generates next internal id and returns it
- # init: Block that gets called to initialize InternalId record if not present
- # Make sure to not throw exceptions in the absence of records (if this is expected).
- def generate
- subject.transaction do
- # Create a record in internal_ids if one does not yet exist
- # and increment its last value
- #
- # Note this will acquire a ROW SHARE lock on the InternalId record
- record.increment_and_save!
- end
- end
-
- def record
- @record ||= (lookup || create_record)
- end
-
- def lookup
- InternalId.find_by(**scope, usage: usage_value)
- end
-
- def usage_value
- 4 # see Enums::InternalId - this is the value for epics
- end
-
- # Create InternalId record for (scope, usage) combination, if it doesn't exist
- #
- # We blindly insert without synchronization. If another process
- # was faster in doing this, we'll realize once we hit the unique key constraint
- # violation. We can safely roll-back the nested transaction and perform
- # a lookup instead to retrieve the record.
- def create_record
- raise ArgumentError, 'Cannot initialize without init!' unless init
-
- instance = subject.is_a?(::Class) ? nil : subject
-
- subject.transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
- InternalId.create!(
- **scope,
- usage: usage_value,
- last_value: init.call(instance, scope) || 0
- )
- end
- rescue ActiveRecord::RecordNotUnique
- lookup
- end
- end
-
- def up
- duplicate_epic_ids = ApplicationRecord.connection.execute('SELECT iid, group_id, COUNT(*) FROM epics GROUP BY iid, group_id HAVING COUNT(*) > 1;')
-
- duplicate_epic_ids.each do |dup|
- Epic.where(iid: dup['iid'], group_id: dup['group_id']).last(dup['count'] - 1).each do |epic|
- new_iid = InternalId.generate_next(epic,
- { namespace_id: epic.group_id },
- :epics, ->(instance, _) { instance.class.where(group_id: epic.group_id).maximum(:iid) }
- )
-
- epic.update!(iid: new_iid)
- end
- end
-
- add_concurrent_index :epics, [:group_id, :iid], unique: true, name: INDEX_NAME
- end
-
- def down
- # only remove the index, as we do not want to create the duplicates back
- remove_concurrent_index :epics, [:group_id, :iid], name: INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20201109114603_schedule_remove_inaccessible_epic_todos.rb b/db/post_migrate/20201109114603_schedule_remove_inaccessible_epic_todos.rb
deleted file mode 100644
index 13d12675a28..00000000000
--- a/db/post_migrate/20201109114603_schedule_remove_inaccessible_epic_todos.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleRemoveInaccessibleEpicTodos < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- INTERVAL = 2.minutes
- BATCH_SIZE = 10
- MIGRATION = 'RemoveInaccessibleEpicTodos'
-
- disable_ddl_transaction!
-
- class Epic < ActiveRecord::Base
- include EachBatch
- end
-
- def up
- return unless Gitlab.ee?
-
- relation = Epic.where(confidential: true)
-
- queue_background_migration_jobs_by_range_at_intervals(
- relation, MIGRATION, INTERVAL, batch_size: BATCH_SIZE)
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20201110161542_cleanup_transfered_projects_shared_runners.rb b/db/post_migrate/20201110161542_cleanup_transfered_projects_shared_runners.rb
deleted file mode 100644
index 5e907092e83..00000000000
--- a/db/post_migrate/20201110161542_cleanup_transfered_projects_shared_runners.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class CleanupTransferedProjectsSharedRunners < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- BATCH_SIZE = 25_000
- INTERVAL = 3.minutes
- MIGRATION = 'ResetSharedRunnersForTransferredProjects'
-
- disable_ddl_transaction!
-
- class Namespace < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'namespaces'
- end
-
- def up
- queue_background_migration_jobs_by_range_at_intervals(Namespace,
- MIGRATION,
- INTERVAL,
- batch_size: BATCH_SIZE)
- end
-
- def down
- # This migration fixes an inconsistent database state resulting from https://gitlab.com/gitlab-org/gitlab/-/issues/271728
- # and as such does not require a down migration
- end
-end
diff --git a/db/post_migrate/20201112130710_schedule_remove_duplicate_vulnerabilities_findings.rb b/db/post_migrate/20201112130710_schedule_remove_duplicate_vulnerabilities_findings.rb
deleted file mode 100644
index d05516bd255..00000000000
--- a/db/post_migrate/20201112130710_schedule_remove_duplicate_vulnerabilities_findings.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleRemoveDuplicateVulnerabilitiesFindings < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = 'tmp_idx_deduplicate_vulnerability_occurrences'
-
- MIGRATION = 'RemoveDuplicateVulnerabilitiesFindings'
- DELAY_INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 5_000
-
- disable_ddl_transaction!
-
- class VulnerabilitiesFinding < ActiveRecord::Base
- include ::EachBatch
- self.table_name = "vulnerability_occurrences"
- end
-
- def up
- add_concurrent_index :vulnerability_occurrences,
- %i[project_id report_type location_fingerprint primary_identifier_id id],
- name: INDEX_NAME
-
- say "Scheduling #{MIGRATION} jobs"
- queue_background_migration_jobs_by_range_at_intervals(
- VulnerabilitiesFinding,
- MIGRATION,
- DELAY_INTERVAL,
- batch_size: BATCH_SIZE
- )
- end
-
- def down
- remove_concurrent_index_by_name(:vulnerability_occurrences, INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences.rb b/db/post_migrate/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences.rb
deleted file mode 100644
index 7bb97a39bda..00000000000
--- a/db/post_migrate/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleRecalculateUuidOnVulnerabilitiesOccurrences < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- MIGRATION = 'RecalculateVulnerabilitiesOccurrencesUuid'
- DELAY_INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 2_500
-
- disable_ddl_transaction!
-
- class VulnerabilitiesFinding < ActiveRecord::Base
- include ::EachBatch
-
- self.table_name = "vulnerability_occurrences"
- end
-
- def up
- # Make sure that RemoveDuplicateVulnerabilitiesFindings has finished running
- # so that we don't run into duplicate UUID issues
- Gitlab::BackgroundMigration.steal('RemoveDuplicateVulnerabilitiesFindings')
-
- say "Scheduling #{MIGRATION} jobs"
- queue_background_migration_jobs_by_range_at_intervals(
- VulnerabilitiesFinding,
- MIGRATION,
- DELAY_INTERVAL,
- batch_size: BATCH_SIZE
- )
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20201112145311_add_index_on_sha_for_initial_deployments.rb b/db/post_migrate/20201112145311_add_index_on_sha_for_initial_deployments.rb
deleted file mode 100644
index 15debddb9cc..00000000000
--- a/db/post_migrate/20201112145311_add_index_on_sha_for_initial_deployments.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddIndexOnShaForInitialDeployments < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- NEW_INDEX_NAME = 'index_deployments_on_environment_status_sha'
- OLD_INDEX_NAME = 'index_deployments_on_environment_id_and_status'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :deployments, %i[environment_id status sha], name: NEW_INDEX_NAME
- remove_concurrent_index_by_name :deployments, OLD_INDEX_NAME
- end
-
- def down
- add_concurrent_index :deployments, %i[environment_id status], name: OLD_INDEX_NAME
- remove_concurrent_index_by_name :services, NEW_INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20201113105000_update_index_secure_for_api_fuzzing_telemetry.rb b/db/post_migrate/20201113105000_update_index_secure_for_api_fuzzing_telemetry.rb
deleted file mode 100644
index 9e8313f79f8..00000000000
--- a/db/post_migrate/20201113105000_update_index_secure_for_api_fuzzing_telemetry.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateIndexSecureForApiFuzzingTelemetry < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- disable_ddl_transaction!
-
- OLD_SECURE_INDEX_NAME = 'index_secure_ci_builds_on_user_id_created_at_parser_features'
- NEW_SECURE_INDEX_NAME = 'index_secure_ci_builds_on_user_id_name_created_at'
-
- def up
- add_concurrent_index(:ci_builds,
- [:user_id, :name, :created_at],
- where: "(((type)::text = 'Ci::Build'::text) AND ((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('license_scanning'::character varying)::text, ('sast'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('apifuzzer_fuzz'::character varying)::text, ('apifuzzer_fuzz_dnd'::character varying)::text, ('secret_detection'::character varying)::text])))",
- name: NEW_SECURE_INDEX_NAME)
- remove_concurrent_index_by_name :ci_builds, OLD_SECURE_INDEX_NAME
- end
-
- def down
- add_concurrent_index(:ci_builds,
- [:user_id, :created_at],
- where: "(((type)::text = 'Ci::Build'::text) AND ((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('license_scanning'::character varying)::text, ('sast'::character varying)::text, ('secret_detection'::character varying)::text])))",
- name: OLD_SECURE_INDEX_NAME)
- remove_concurrent_index_by_name :ci_builds, NEW_SECURE_INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20201119092319_schedule_repopulate_historical_vulnerability_statistics.rb b/db/post_migrate/20201119092319_schedule_repopulate_historical_vulnerability_statistics.rb
deleted file mode 100644
index 598cc4d93d0..00000000000
--- a/db/post_migrate/20201119092319_schedule_repopulate_historical_vulnerability_statistics.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleRepopulateHistoricalVulnerabilityStatistics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- BATCH_SIZE = 50
- DELAY_INTERVAL = 5.minutes
- MIGRATION_CLASS = 'PopulateVulnerabilityHistoricalStatistics'
- DAY_COUNT = 365
-
- disable_ddl_transaction!
-
- class ProjectSetting < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'project_settings'
-
- scope :has_vulnerabilities, -> { where('has_vulnerabilities IS TRUE') }
- end
-
- def up
- ProjectSetting.has_vulnerabilities.each_batch(of: BATCH_SIZE) do |batch, index|
- migrate_in(index * DELAY_INTERVAL, MIGRATION_CLASS, [batch.pluck(:project_id), DAY_COUNT])
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20201120071303_drop_feature_filter_type_from_user_preferences.rb b/db/post_migrate/20201120071303_drop_feature_filter_type_from_user_preferences.rb
deleted file mode 100644
index b00ea0aba76..00000000000
--- a/db/post_migrate/20201120071303_drop_feature_filter_type_from_user_preferences.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class DropFeatureFilterTypeFromUserPreferences < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- with_lock_retries do
- remove_column :user_preferences, :feature_filter_type
- end
- end
-
- def down
- with_lock_retries do
- add_column :user_preferences, :feature_filter_type, :bigint
- end
- end
-end
diff --git a/db/post_migrate/20201120140210_add_runner_id_and_id_desc_index_to_ci_builds.rb b/db/post_migrate/20201120140210_add_runner_id_and_id_desc_index_to_ci_builds.rb
deleted file mode 100644
index 5eda0e25dbe..00000000000
--- a/db/post_migrate/20201120140210_add_runner_id_and_id_desc_index_to_ci_builds.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class AddRunnerIdAndIdDescIndexToCiBuilds < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- NEW_INDEX = 'index_ci_builds_on_runner_id_and_id_desc'
- OLD_INDEX = 'index_ci_builds_on_runner_id'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :ci_builds, %i[runner_id id], name: NEW_INDEX, order: { id: :desc }
- remove_concurrent_index_by_name :ci_builds, OLD_INDEX
- end
-
- def down
- add_concurrent_index :ci_builds, %i[runner_id], name: OLD_INDEX
- remove_concurrent_index_by_name :ci_builds, NEW_INDEX
- end
-end
diff --git a/db/post_migrate/20201124122817_populate_remaining_missing_dismissal_information_for_vulnerabilities.rb b/db/post_migrate/20201124122817_populate_remaining_missing_dismissal_information_for_vulnerabilities.rb
deleted file mode 100644
index 9dc41d17231..00000000000
--- a/db/post_migrate/20201124122817_populate_remaining_missing_dismissal_information_for_vulnerabilities.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class PopulateRemainingMissingDismissalInformationForVulnerabilities < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- Gitlab::BackgroundMigration.steal('PopulateMissingVulnerabilityDismissalInformation')
-
- ::Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation::Vulnerability.broken.each_batch(of: 100) do |batch, index|
- vulnerability_ids = batch.pluck(:id)
-
- ::Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation.new.perform(*vulnerability_ids)
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20201124185639_remove_unused_indexes.rb b/db/post_migrate/20201124185639_remove_unused_indexes.rb
deleted file mode 100644
index c4b0d8a84cc..00000000000
--- a/db/post_migrate/20201124185639_remove_unused_indexes.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveUnusedIndexes < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- remove_concurrent_index_by_name :packages_package_files, "packages_packages_verification_failure_partial"
- remove_concurrent_index_by_name :packages_package_files, "packages_packages_verification_checksum_partial"
- remove_concurrent_index_by_name :snippet_repositories, 'snippet_repositories_verification_failure_partial'
- remove_concurrent_index_by_name :snippet_repositories, 'snippet_repositories_verification_checksum_partial'
- remove_concurrent_index_by_name :terraform_state_versions, 'terraform_state_versions_verification_failure_partial'
- remove_concurrent_index_by_name :terraform_state_versions, 'terraform_state_versions_verification_checksum_partial'
- end
-
- def down
- add_concurrent_index :packages_package_files, :verification_failure, where: "(verification_failure IS NOT NULL)", name: "packages_packages_verification_failure_partial"
- add_concurrent_index :packages_package_files, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: "packages_packages_verification_checksum_partial"
- add_concurrent_index :snippet_repositories, :verification_failure, where: "(verification_failure IS NOT NULL)", name: 'snippet_repositories_verification_failure_partial'
- add_concurrent_index :snippet_repositories, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: 'snippet_repositories_verification_checksum_partial'
- add_concurrent_index :terraform_state_versions, :verification_failure, where: "(verification_failure IS NOT NULL)", name: 'terraform_state_versions_verification_failure_partial'
- add_concurrent_index :terraform_state_versions, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: 'terraform_state_versions_verification_checksum_partial'
- end
-end
diff --git a/db/post_migrate/20201128210234_schedule_populate_issue_email_participants.rb b/db/post_migrate/20201128210234_schedule_populate_issue_email_participants.rb
deleted file mode 100644
index 6fea683944c..00000000000
--- a/db/post_migrate/20201128210234_schedule_populate_issue_email_participants.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class SchedulePopulateIssueEmailParticipants < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- BATCH_SIZE = 1_000
- DELAY_INTERVAL = 2.minutes
- MIGRATION = 'PopulateIssueEmailParticipants'
-
- disable_ddl_transaction!
-
- class Issue < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'issues'
- end
-
- def up
- queue_background_migration_jobs_by_range_at_intervals(
- Issue.where.not(service_desk_reply_to: nil),
- MIGRATION,
- DELAY_INTERVAL,
- batch_size: BATCH_SIZE
- )
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20201130103926_schedule_populate_dismissed_state_for_vulnerabilities.rb b/db/post_migrate/20201130103926_schedule_populate_dismissed_state_for_vulnerabilities.rb
deleted file mode 100644
index 5e8da532251..00000000000
--- a/db/post_migrate/20201130103926_schedule_populate_dismissed_state_for_vulnerabilities.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-class SchedulePopulateDismissedStateForVulnerabilities < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- TMP_INDEX_NAME = 'tmp_index_on_vulnerabilities_non_dismissed'
-
- DOWNTIME = false
- BATCH_SIZE = 1_000
- VULNERABILITY_BATCH_SIZE = 5_000
- DELAY_INTERVAL = 3.minutes.to_i
- MIGRATION_CLASS = 'PopulateDismissedStateForVulnerabilities'
-
- VULNERABILITY_JOIN_CONDITION = 'JOIN "vulnerability_occurrences" ON "vulnerability_occurrences"."vulnerability_id" = "vulnerabilities"."id"'
- FEEDBACK_WHERE_CONDITION = <<~SQL
- EXISTS (SELECT 1 FROM vulnerability_feedback
- WHERE "vulnerability_occurrences"."project_id" = "vulnerability_feedback"."project_id"
- AND "vulnerability_occurrences"."report_type" = "vulnerability_feedback"."category"
- AND ENCODE("vulnerability_occurrences"."project_fingerprint", 'hex') = "vulnerability_feedback"."project_fingerprint"
- AND "vulnerability_feedback"."feedback_type" = 0
- )
- SQL
-
- class Vulnerability < ActiveRecord::Base # rubocop:disable Style/Documentation
- include EachBatch
-
- self.table_name = 'vulnerabilities'
- end
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:vulnerabilities, :id, where: 'state <> 2', name: TMP_INDEX_NAME)
-
- batch = []
- index = 1
-
- Vulnerability.where('state <> 2').each_batch(of: VULNERABILITY_BATCH_SIZE) do |relation|
- ids = relation
- .joins(VULNERABILITY_JOIN_CONDITION)
- .where(FEEDBACK_WHERE_CONDITION)
- .pluck('vulnerabilities.id')
-
- ids.each do |id|
- batch << id
-
- if batch.size == BATCH_SIZE
- migrate_in(index * DELAY_INTERVAL, MIGRATION_CLASS, batch)
- index += 1
-
- batch.clear
- end
- end
- end
-
- migrate_in(index * DELAY_INTERVAL, MIGRATION_CLASS, batch) unless batch.empty?
- end
-
- def down
- remove_concurrent_index_by_name(:vulnerabilities, TMP_INDEX_NAME)
- end
-end
diff --git a/db/post_migrate/20201203123201_remove_orphan_service_hooks.rb b/db/post_migrate/20201203123201_remove_orphan_service_hooks.rb
deleted file mode 100644
index c430e2205c2..00000000000
--- a/db/post_migrate/20201203123201_remove_orphan_service_hooks.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveOrphanServiceHooks < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- class WebHook < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'web_hooks'
-
- def self.service_hooks
- where(type: 'ServiceHook')
- end
- end
-
- class Service < ActiveRecord::Base
- self.table_name = 'services'
- end
-
- def up
- WebHook.service_hooks.where.not(service_id: Service.select(:id)).where.not(service_id: nil).each_batch do |relation|
- relation.delete_all
- end
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20201207151651_truncate_security_findings_table_2.rb b/db/post_migrate/20201207151651_truncate_security_findings_table_2.rb
deleted file mode 100644
index 2ac6941be6d..00000000000
--- a/db/post_migrate/20201207151651_truncate_security_findings_table_2.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-require_relative Rails.root.join('db', 'post_migrate', '20201102152945_truncate_security_findings_table.rb')
-
-# This is the second time we are truncating this table
-# so the migration class name has choosen like this for this reason.
-class TruncateSecurityFindingsTable2 < TruncateSecurityFindingsTable; end
diff --git a/db/post_migrate/20201207165956_remove_duplicate_services.rb b/db/post_migrate/20201207165956_remove_duplicate_services.rb
deleted file mode 100644
index 1659b9a2095..00000000000
--- a/db/post_migrate/20201207165956_remove_duplicate_services.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveDuplicateServices < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- # noop, replaced by 20210112143418_remove_duplicate_services.rb
- end
-
- def down
- end
-end
diff --git a/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb b/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb
deleted file mode 100644
index 56db148afe6..00000000000
--- a/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleBackfillingArtifactExpiryMigration < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- SWITCH_DATE = Time.utc(2020, 6, 22).freeze
- INDEX_NAME = 'expired_artifacts_temp_index'
- INDEX_CONDITION = "expire_at IS NULL AND created_at < '#{SWITCH_DATE}'"
-
- disable_ddl_transaction!
-
- class JobArtifact < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'ci_job_artifacts'
-
- scope :without_expiry_date, -> { where(expire_at: nil) }
- scope :before_switch, -> { where('created_at < ?', SWITCH_DATE) }
- end
-
- def up
- # Create temporary index for expired artifacts
- # Needs to be removed in a later migration
- add_concurrent_index(:ci_job_artifacts, %i(id created_at), where: INDEX_CONDITION, name: INDEX_NAME)
-
- # queue_background_migration_jobs_by_range_at_intervals(
- # JobArtifact.without_expiry_date.before_switch,
- # ::Gitlab::BackgroundMigration::BackfillArtifactExpiryDate,
- # 2.minutes,
- # batch_size: 200_000
- # )
- # The scheduling code was using the full class symbol
- # (`::Gitlab::BackgroundMigration::BackfillArtifactExpiryDate`) instead of a
- # string with the class name (`BackfillArtifactExpiryDate`) by mistake,
- # which resulted in an error. It is commented out so it's a no-op to prevent
- # errors and will be reintroduced with
- # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51822.
- end
-
- def down
- remove_concurrent_index_by_name :ci_job_artifacts, INDEX_NAME
- end
-end
diff --git a/db/post_migrate/20210622041846_finalize_push_event_payloads_bigint_conversion.rb b/db/post_migrate/20210622041846_finalize_push_event_payloads_bigint_conversion.rb
index 38b081e3e5e..f37c446f66c 100644
--- a/db/post_migrate/20210622041846_finalize_push_event_payloads_bigint_conversion.rb
+++ b/db/post_migrate/20210622041846_finalize_push_event_payloads_bigint_conversion.rb
@@ -49,7 +49,7 @@ class FinalizePushEventPayloadsBigintConversion < ActiveRecord::Migration[6.1]
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(:event_id, :event_id_convert_to_bigint)
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name(:event_id, :event_id_convert_to_bigint)
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# Swap defaults
diff --git a/db/post_migrate/20210622045705_finalize_events_bigint_conversion.rb b/db/post_migrate/20210622045705_finalize_events_bigint_conversion.rb
index b99a61e8e63..715bc392c68 100644
--- a/db/post_migrate/20210622045705_finalize_events_bigint_conversion.rb
+++ b/db/post_migrate/20210622045705_finalize_events_bigint_conversion.rb
@@ -60,7 +60,7 @@ class FinalizeEventsBigintConversion < ActiveRecord::Migration[6.1]
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(:id, :id_convert_to_bigint)
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name(:id, :id_convert_to_bigint)
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# Swap defaults
diff --git a/db/post_migrate/20210701033622_finalize_ci_builds_needs_bigint_conversion.rb b/db/post_migrate/20210701033622_finalize_ci_builds_needs_bigint_conversion.rb
index baee9fb3848..89a39660a04 100644
--- a/db/post_migrate/20210701033622_finalize_ci_builds_needs_bigint_conversion.rb
+++ b/db/post_migrate/20210701033622_finalize_ci_builds_needs_bigint_conversion.rb
@@ -47,7 +47,7 @@ class FinalizeCiBuildsNeedsBigintConversion < ActiveRecord::Migration[6.1]
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(:build_id, :build_id_convert_to_bigint)
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name(:build_id, :build_id_convert_to_bigint)
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# Swap defaults
diff --git a/db/post_migrate/20210701141346_finalize_ci_builds_stage_id_bigint_conversion.rb b/db/post_migrate/20210701141346_finalize_ci_builds_stage_id_bigint_conversion.rb
index a8a9fe037ec..161366590be 100644
--- a/db/post_migrate/20210701141346_finalize_ci_builds_stage_id_bigint_conversion.rb
+++ b/db/post_migrate/20210701141346_finalize_ci_builds_stage_id_bigint_conversion.rb
@@ -46,7 +46,7 @@ class FinalizeCiBuildsStageIdBigintConversion < ActiveRecord::Migration[6.1]
execute "ALTER TABLE #{quoted_table_name} RENAME COLUMN #{quote_column_name(temporary_name)} TO #{quote_column_name(:stage_id_convert_to_bigint)}"
# Reset the function so PG drops the plan cache for the incorrect integer type
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME)
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection)
.name([:id, :stage_id], [:id_convert_to_bigint, :stage_id_convert_to_bigint])
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
diff --git a/db/post_migrate/20210706212710_finalize_ci_job_artifacts_bigint_conversion.rb b/db/post_migrate/20210706212710_finalize_ci_job_artifacts_bigint_conversion.rb
index 40977277bd1..11045348672 100644
--- a/db/post_migrate/20210706212710_finalize_ci_job_artifacts_bigint_conversion.rb
+++ b/db/post_migrate/20210706212710_finalize_ci_job_artifacts_bigint_conversion.rb
@@ -58,7 +58,7 @@ class FinalizeCiJobArtifactsBigintConversion < ActiveRecord::Migration[6.1]
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name([:id, :job_id], [:id_convert_to_bigint, :job_id_convert_to_bigint])
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name([:id, :job_id], [:id_convert_to_bigint, :job_id_convert_to_bigint])
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# Swap defaults
diff --git a/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb b/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb
index 2e294a0b2e3..dbefbeb26cb 100644
--- a/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb
+++ b/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb
@@ -53,7 +53,7 @@ class FinalizeCiStagesBigintConversion < ActiveRecord::Migration[6.1]
execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN #{id_convert_to_bigint_name} TO #{id_name}"
execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN #{temp_name} TO #{id_convert_to_bigint_name}"
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(:id, :id_convert_to_bigint)
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name(:id, :id_convert_to_bigint)
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# Swap defaults
diff --git a/db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb b/db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb
index f75df04ba48..c2444ccbc6c 100644
--- a/db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb
+++ b/db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb
@@ -53,8 +53,8 @@ class FinalizeCiBuildsMetadataBigintConversion < Gitlab::Database::Migration[1.0
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
- execute "ALTER FUNCTION #{quote_table_name(Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(:id, :id_convert_to_bigint))} RESET ALL"
- execute "ALTER FUNCTION #{quote_table_name(Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(:build_id, :build_id_convert_to_bigint))} RESET ALL"
+ execute "ALTER FUNCTION #{quote_table_name(Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name(:id, :id_convert_to_bigint))} RESET ALL"
+ execute "ALTER FUNCTION #{quote_table_name(Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name(:build_id, :build_id_convert_to_bigint))} RESET ALL"
# Swap defaults for PK
execute "ALTER SEQUENCE ci_builds_metadata_id_seq OWNED BY #{TABLE_NAME}.id"
diff --git a/db/post_migrate/20210713042153_finalize_ci_sources_pipelines_bigint_conversion.rb b/db/post_migrate/20210713042153_finalize_ci_sources_pipelines_bigint_conversion.rb
index 938c8c172a3..38b7852b320 100644
--- a/db/post_migrate/20210713042153_finalize_ci_sources_pipelines_bigint_conversion.rb
+++ b/db/post_migrate/20210713042153_finalize_ci_sources_pipelines_bigint_conversion.rb
@@ -47,7 +47,7 @@ class FinalizeCiSourcesPipelinesBigintConversion < ActiveRecord::Migration[6.1]
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(:source_job_id, :source_job_id_convert_to_bigint)
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name(:source_job_id, :source_job_id_convert_to_bigint)
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# No need to swap defaults, both columns have no default value
diff --git a/db/post_migrate/20210714015537_finalize_ci_build_trace_chunks_bigint_conversion.rb b/db/post_migrate/20210714015537_finalize_ci_build_trace_chunks_bigint_conversion.rb
index 9195b662776..af17b35d47d 100644
--- a/db/post_migrate/20210714015537_finalize_ci_build_trace_chunks_bigint_conversion.rb
+++ b/db/post_migrate/20210714015537_finalize_ci_build_trace_chunks_bigint_conversion.rb
@@ -45,7 +45,7 @@ class FinalizeCiBuildTraceChunksBigintConversion < ActiveRecord::Migration[6.1]
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(:build_id, :build_id_convert_to_bigint)
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name(:build_id, :build_id_convert_to_bigint)
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# Swap defaults
diff --git a/db/post_migrate/20210722155635_finalize_convert_geo_job_artifact_deleted_events_bigint.rb b/db/post_migrate/20210722155635_finalize_convert_geo_job_artifact_deleted_events_bigint.rb
index 7d3809a9dbe..5bf6a9e7911 100644
--- a/db/post_migrate/20210722155635_finalize_convert_geo_job_artifact_deleted_events_bigint.rb
+++ b/db/post_migrate/20210722155635_finalize_convert_geo_job_artifact_deleted_events_bigint.rb
@@ -44,7 +44,7 @@ class FinalizeConvertGeoJobArtifactDeletedEventsBigint < ActiveRecord::Migration
change_column_default TABLE_NAME, COLUMN_NAME, nil
change_column_default TABLE_NAME, COLUMN_NAME_CONVERTED, 0
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(COLUMN_NAME, COLUMN_NAME_CONVERTED)
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name(COLUMN_NAME, COLUMN_NAME_CONVERTED)
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
execute "DROP INDEX #{old_index_name}"
diff --git a/db/post_migrate/20210802043253_finalize_push_event_payloads_bigint_conversion_3.rb b/db/post_migrate/20210802043253_finalize_push_event_payloads_bigint_conversion_3.rb
index 4b825ae72ba..6dab29e10d4 100644
--- a/db/post_migrate/20210802043253_finalize_push_event_payloads_bigint_conversion_3.rb
+++ b/db/post_migrate/20210802043253_finalize_push_event_payloads_bigint_conversion_3.rb
@@ -61,7 +61,7 @@ class FinalizePushEventPayloadsBigintConversion3 < ActiveRecord::Migration[6.1]
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(:event_id, :event_id_convert_to_bigint)
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name(:event_id, :event_id_convert_to_bigint)
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# Swap defaults
diff --git a/db/post_migrate/20210802131812_finalize_convert_deployments_bigint.rb b/db/post_migrate/20210802131812_finalize_convert_deployments_bigint.rb
index 31afb7e0a29..067b7166cf3 100644
--- a/db/post_migrate/20210802131812_finalize_convert_deployments_bigint.rb
+++ b/db/post_migrate/20210802131812_finalize_convert_deployments_bigint.rb
@@ -35,7 +35,7 @@ class FinalizeConvertDeploymentsBigint < ActiveRecord::Migration[6.1]
execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN #{quote_column_name(COLUMN_NAME_BIGINT)} TO #{quote_column_name(COLUMN_NAME)}"
execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN #{quote_column_name(temp_name)} TO #{quote_column_name(COLUMN_NAME_BIGINT)}"
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(COLUMN_NAME, COLUMN_NAME_BIGINT)
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name(COLUMN_NAME, COLUMN_NAME_BIGINT)
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
execute "DROP INDEX #{old_index_name}"
diff --git a/db/post_migrate/20210805131510_finalize_ci_builds_runner_session_bigint_conversion.rb b/db/post_migrate/20210805131510_finalize_ci_builds_runner_session_bigint_conversion.rb
index 9706f0036f3..5e18450f465 100644
--- a/db/post_migrate/20210805131510_finalize_ci_builds_runner_session_bigint_conversion.rb
+++ b/db/post_migrate/20210805131510_finalize_ci_builds_runner_session_bigint_conversion.rb
@@ -44,7 +44,7 @@ class FinalizeCiBuildsRunnerSessionBigintConversion < ActiveRecord::Migration[6.
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(:build_id, :build_id_convert_to_bigint)
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name(:build_id, :build_id_convert_to_bigint)
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# Swap defaults
diff --git a/db/post_migrate/20210806131706_finalize_taggins_bigint_conversion.rb b/db/post_migrate/20210806131706_finalize_taggins_bigint_conversion.rb
index bd76466d43a..5f094e48ed4 100644
--- a/db/post_migrate/20210806131706_finalize_taggins_bigint_conversion.rb
+++ b/db/post_migrate/20210806131706_finalize_taggins_bigint_conversion.rb
@@ -60,7 +60,7 @@ class FinalizeTagginsBigintConversion < ActiveRecord::Migration[6.1]
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name([:id, :taggable_id], [:id_convert_to_bigint, :taggable_id_convert_to_bigint])
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name([:id, :taggable_id], [:id_convert_to_bigint, :taggable_id_convert_to_bigint])
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# Swap defaults
diff --git a/db/post_migrate/20210809143931_finalize_job_id_conversion_to_bigint_for_ci_job_artifacts.rb b/db/post_migrate/20210809143931_finalize_job_id_conversion_to_bigint_for_ci_job_artifacts.rb
index bb12045b1de..5cec6fa30b8 100644
--- a/db/post_migrate/20210809143931_finalize_job_id_conversion_to_bigint_for_ci_job_artifacts.rb
+++ b/db/post_migrate/20210809143931_finalize_job_id_conversion_to_bigint_for_ci_job_artifacts.rb
@@ -55,7 +55,7 @@ class FinalizeJobIdConversionToBigintForCiJobArtifacts < ActiveRecord::Migration
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name([:id, :job_id], [:id_convert_to_bigint, :job_id_convert_to_bigint])
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection).name([:id, :job_id], [:id_convert_to_bigint, :job_id_convert_to_bigint])
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# Swap defaults
diff --git a/db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb b/db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb
index 0a0fda7e870..f63645b4ffa 100644
--- a/db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb
+++ b/db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb
@@ -42,7 +42,7 @@ class PrepareCiBuildsMetadataAndCiBuildAsyncIndexes < ActiveRecord::Migration[6.
return if index_name_exists?(table_name, index_name)
- async_index = Gitlab::Database::AsyncIndexes::PostgresAsyncIndex.safe_find_or_create_by!(name: index_name) do |rec|
+ async_index = Gitlab::Database::AsyncIndexes::PostgresAsyncIndex.find_or_create_by!(name: index_name) do |rec|
rec.table_name = table_name
rec.definition = definition
end
diff --git a/db/post_migrate/20210907211557_finalize_ci_builds_bigint_conversion.rb b/db/post_migrate/20210907211557_finalize_ci_builds_bigint_conversion.rb
index 02f98833703..7544842c196 100644
--- a/db/post_migrate/20210907211557_finalize_ci_builds_bigint_conversion.rb
+++ b/db/post_migrate/20210907211557_finalize_ci_builds_bigint_conversion.rb
@@ -136,7 +136,7 @@ class FinalizeCiBuildsBigintConversion < Gitlab::Database::Migration[1.0]
execute "ALTER TABLE #{quoted_table_name} RENAME COLUMN #{quote_column_name(temporary_name)} TO #{quote_column_name(:id_convert_to_bigint)}"
# Reset the function so PG drops the plan cache for the incorrect integer type
- function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME)
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME, connection: connection)
.name([:id, :stage_id], [:id_convert_to_bigint, :stage_id_convert_to_bigint])
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
diff --git a/db/post_migrate/20210923192648_remove_foreign_keys_from_open_project_data_table.rb b/db/post_migrate/20210923192648_remove_foreign_keys_from_open_project_data_table.rb
new file mode 100644
index 00000000000..1da5aad0fab
--- /dev/null
+++ b/db/post_migrate/20210923192648_remove_foreign_keys_from_open_project_data_table.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveForeignKeysFromOpenProjectDataTable < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ remove_foreign_key :open_project_tracker_data, column: :service_id
+ end
+ end
+
+ def down
+ with_lock_retries do
+ add_foreign_key :open_project_tracker_data, :integrations, column: :service_id, on_delete: :cascade
+ end
+ end
+end
diff --git a/db/post_migrate/20210923192649_remove_open_project_data_table.rb b/db/post_migrate/20210923192649_remove_open_project_data_table.rb
new file mode 100644
index 00000000000..252d7e07261
--- /dev/null
+++ b/db/post_migrate/20210923192649_remove_open_project_data_table.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class RemoveOpenProjectDataTable < Gitlab::Database::Migration[1.0]
+ def up
+ drop_table :open_project_tracker_data
+ end
+
+ def down
+ create_table :open_project_tracker_data do |t|
+ t.integer :service_id, index: { name: 'index_open_project_tracker_data_on_service_id' }, null: false
+ t.timestamps_with_timezone
+ t.string :encrypted_url, limit: 255
+ t.string :encrypted_url_iv, limit: 255
+ t.string :encrypted_api_url, limit: 255
+ t.string :encrypted_api_url_iv, limit: 255
+ t.string :encrypted_token, limit: 255
+ t.string :encrypted_token_iv, limit: 255
+ t.string :closed_status_id, limit: 5
+ t.string :project_identifier_code, limit: 100
+ end
+ end
+end
diff --git a/db/post_migrate/20210930211936_backfill_user_namespace.rb b/db/post_migrate/20210930211936_backfill_user_namespace.rb
new file mode 100644
index 00000000000..c5dd170f18e
--- /dev/null
+++ b/db/post_migrate/20210930211936_backfill_user_namespace.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class BackfillUserNamespace < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'BackfillUserNamespace'
+ INTERVAL = 2.minutes
+ BATCH_SIZE = 1_000
+ SUB_BATCH_SIZE = 200
+ DOWNTIME = false
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :namespaces,
+ :id,
+ job_interval: INTERVAL,
+ batch_size: BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ Gitlab::Database::BackgroundMigration::BatchedMigration
+ .for_configuration(MIGRATION, :namespaces, :id, [])
+ .delete_all
+ end
+end
diff --git a/db/post_migrate/20211004120135_schedule_add_primary_email_to_emails_if_user_confirmed.rb b/db/post_migrate/20211004120135_schedule_add_primary_email_to_emails_if_user_confirmed.rb
new file mode 100644
index 00000000000..d7b213b384a
--- /dev/null
+++ b/db/post_migrate/20211004120135_schedule_add_primary_email_to_emails_if_user_confirmed.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class ScheduleAddPrimaryEmailToEmailsIfUserConfirmed < Gitlab::Database::Migration[1.0]
+ INTERVAL = 2.minutes.to_i
+ BATCH_SIZE = 10_000
+ MIGRATION = 'AddPrimaryEmailToEmailsIfUserConfirmed'
+
+ disable_ddl_transaction!
+
+ class User < ActiveRecord::Base
+ include ::EachBatch
+
+ self.table_name = 'users'
+ self.inheritance_column = :_type_disabled
+ end
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ User,
+ MIGRATION,
+ INTERVAL,
+ batch_size: BATCH_SIZE,
+ track_jobs: true
+ )
+ end
+
+ def down
+ # intentionally blank
+ end
+end
diff --git a/db/post_migrate/20211005194425_schedule_requirements_migration.rb b/db/post_migrate/20211005194425_schedule_requirements_migration.rb
new file mode 100644
index 00000000000..56211989b8e
--- /dev/null
+++ b/db/post_migrate/20211005194425_schedule_requirements_migration.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class ScheduleRequirementsMigration < Gitlab::Database::Migration[1.0]
+ DOWNTIME = false
+
+ # 2021-10-05 requirements count: ~12500
+ #
+ # Using 30 as batch size and 120 seconds default interval will produce:
+ # ~420 jobs - taking ~14 hours to perform
+ BATCH_SIZE = 30
+
+ MIGRATION = 'MigrateRequirementsToWorkItems'
+
+ disable_ddl_transaction!
+
+ class Requirement < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'requirements'
+ end
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ Requirement.where(issue_id: nil),
+ MIGRATION,
+ 2.minutes,
+ batch_size: BATCH_SIZE,
+ track_jobs: true
+ )
+ end
+
+ def down
+ # NO OP
+ end
+end
diff --git a/db/post_migrate/20211011104843_add_new_loose_fk_index.rb b/db/post_migrate/20211011104843_add_new_loose_fk_index.rb
new file mode 100644
index 00000000000..710d0917d7f
--- /dev/null
+++ b/db/post_migrate/20211011104843_add_new_loose_fk_index.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddNewLooseFkIndex < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_loose_foreign_keys_deleted_records_for_loading_records'
+
+ def up
+ add_concurrent_partitioned_index :loose_foreign_keys_deleted_records,
+ %I[fully_qualified_table_name id primary_key_value partition],
+ where: 'status = 1',
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_partitioned_index_by_name :loose_foreign_keys_deleted_records, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211012051221_add_index_btree_namespaces_traversal_ids.rb b/db/post_migrate/20211012051221_add_index_btree_namespaces_traversal_ids.rb
new file mode 100644
index 00000000000..882351ab974
--- /dev/null
+++ b/db/post_migrate/20211012051221_add_index_btree_namespaces_traversal_ids.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexBtreeNamespacesTraversalIds < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_btree_namespaces_traversal_ids'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :namespaces, :traversal_ids, using: :btree, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index :namespaces, :traversal_ids, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211012143815_remove_merge_request_diff_commit_columns.rb b/db/post_migrate/20211012143815_remove_merge_request_diff_commit_columns.rb
new file mode 100644
index 00000000000..80ed834903c
--- /dev/null
+++ b/db/post_migrate/20211012143815_remove_merge_request_diff_commit_columns.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class RemoveMergeRequestDiffCommitColumns < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ COLUMNS = %i[author_name author_email committer_name committer_email].freeze
+
+ def change
+ COLUMNS.each do |column|
+ remove_column(:merge_request_diff_commits, column, :text)
+ end
+ end
+end
diff --git a/db/post_migrate/20211013125341_create_index_security_ci_builds_on_name_and_id_parser_features.rb b/db/post_migrate/20211013125341_create_index_security_ci_builds_on_name_and_id_parser_features.rb
new file mode 100644
index 00000000000..2efbfad6c56
--- /dev/null
+++ b/db/post_migrate/20211013125341_create_index_security_ci_builds_on_name_and_id_parser_features.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class CreateIndexSecurityCiBuildsOnNameAndIdParserFeatures < Gitlab::Database::Migration[1.0]
+ TABLE = "ci_builds"
+ COLUMNS = %i[name id]
+ INDEX_NAME = "index_security_ci_builds_on_name_and_id_parser_features"
+ CONSTRAINTS = "(name::text = ANY (ARRAY['container_scanning'::character varying::text,
+ 'dast'::character varying::text,
+ 'dependency_scanning'::character varying::text,
+ 'license_management'::character varying::text,
+ 'sast'::character varying::text,
+ 'secret_detection'::character varying::text,
+ 'coverage_fuzzing'::character varying::text,
+ 'license_scanning'::character varying::text])
+ ) AND type::text = 'Ci::Build'::text"
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(TABLE, COLUMNS, name: INDEX_NAME, where: CONSTRAINTS)
+ end
+
+ def down
+ remove_concurrent_index(TABLE, COLUMNS, name: INDEX_NAME, where: CONSTRAINTS)
+ end
+end
diff --git a/db/post_migrate/20211018101552_add_index_to_tmp_project_id_column_on_namespaces_table.rb b/db/post_migrate/20211018101552_add_index_to_tmp_project_id_column_on_namespaces_table.rb
new file mode 100644
index 00000000000..b50b7fa21a5
--- /dev/null
+++ b/db/post_migrate/20211018101552_add_index_to_tmp_project_id_column_on_namespaces_table.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexToTmpProjectIdColumnOnNamespacesTable < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'tmp_index_on_tmp_project_id_on_namespaces'
+
+ def up
+ add_concurrent_index :namespaces, :tmp_project_id, name: INDEX_NAME, unique: true
+ end
+
+ def down
+ remove_concurrent_index_by_name :namespaces, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211018101852_add_fk_to_tmp_project_id_column_on_namespaces_table.rb b/db/post_migrate/20211018101852_add_fk_to_tmp_project_id_column_on_namespaces_table.rb
new file mode 100644
index 00000000000..f2772389d02
--- /dev/null
+++ b/db/post_migrate/20211018101852_add_fk_to_tmp_project_id_column_on_namespaces_table.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddFkToTmpProjectIdColumnOnNamespacesTable < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :namespaces, :projects, column: :tmp_project_id
+ end
+
+ def down
+ remove_foreign_key :namespaces, column: :tmp_project_id
+ end
+end
diff --git a/db/post_migrate/20211018102252_add_index_to_group_id_column_on_webhooks_table.rb b/db/post_migrate/20211018102252_add_index_to_group_id_column_on_webhooks_table.rb
new file mode 100644
index 00000000000..d5fac373ca4
--- /dev/null
+++ b/db/post_migrate/20211018102252_add_index_to_group_id_column_on_webhooks_table.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexToGroupIdColumnOnWebhooksTable < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_on_group_id_on_webhooks'
+
+ def up
+ add_concurrent_index :web_hooks, :group_id, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :web_hooks, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211018123316_remove_not_null_constraint_and_default_for_public_email.rb b/db/post_migrate/20211018123316_remove_not_null_constraint_and_default_for_public_email.rb
new file mode 100644
index 00000000000..72a5970b6d7
--- /dev/null
+++ b/db/post_migrate/20211018123316_remove_not_null_constraint_and_default_for_public_email.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoveNotNullConstraintAndDefaultForPublicEmail < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def up
+ change_column_null :users, :public_email, true
+ change_column_default :users, :public_email, from: '', to: nil
+ end
+
+ def down
+ # There may now be nulls in the table, so we cannot re-add the constraint here.
+ change_column_default :users, :public_email, from: nil, to: ''
+ end
+end
diff --git a/db/post_migrate/20211018152654_schedule_remove_duplicate_vulnerabilities_findings3.rb b/db/post_migrate/20211018152654_schedule_remove_duplicate_vulnerabilities_findings3.rb
new file mode 100644
index 00000000000..ecad4466c53
--- /dev/null
+++ b/db/post_migrate/20211018152654_schedule_remove_duplicate_vulnerabilities_findings3.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class ScheduleRemoveDuplicateVulnerabilitiesFindings3 < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ MIGRATION = 'RemoveDuplicateVulnerabilitiesFindings'
+ DELAY_INTERVAL = 2.minutes.to_i
+ BATCH_SIZE = 5_000
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ define_batchable_model('vulnerability_occurrences'),
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20211021131217_add_deployments_environment_id_and_ref_index.rb b/db/post_migrate/20211021131217_add_deployments_environment_id_and_ref_index.rb
new file mode 100644
index 00000000000..8014c006f35
--- /dev/null
+++ b/db/post_migrate/20211021131217_add_deployments_environment_id_and_ref_index.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddDeploymentsEnvironmentIdAndRefIndex < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_deployments_on_environment_id_and_ref'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :deployments, [:environment_id, :ref], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :deployments, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211021140426_remove_geo_upload_deprecated_fields.rb b/db/post_migrate/20211021140426_remove_geo_upload_deprecated_fields.rb
new file mode 100644
index 00000000000..7d0033c0ab9
--- /dev/null
+++ b/db/post_migrate/20211021140426_remove_geo_upload_deprecated_fields.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class RemoveGeoUploadDeprecatedFields < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ remove_column :geo_event_log, :upload_deleted_event_id, :bigint
+ end
+ end
+
+ def down
+ with_lock_retries do
+ add_column(:geo_event_log, :upload_deleted_event_id, :bigint) unless column_exists?(:geo_event_log, :upload_deleted_event_id)
+ end
+
+ add_concurrent_foreign_key :geo_event_log, :geo_upload_deleted_events,
+ column: :upload_deleted_event_id,
+ name: 'fk_c1f241c70d',
+ on_delete: :cascade
+
+ add_concurrent_index :geo_event_log,
+ :upload_deleted_event_id,
+ name: 'index_geo_event_log_on_upload_deleted_event_id',
+ where: "(upload_deleted_event_id IS NOT NULL)"
+ end
+end
diff --git a/db/post_migrate/20211021141930_drop_geo_upload_deleted_events_table.rb b/db/post_migrate/20211021141930_drop_geo_upload_deleted_events_table.rb
new file mode 100644
index 00000000000..b6987e68fb1
--- /dev/null
+++ b/db/post_migrate/20211021141930_drop_geo_upload_deleted_events_table.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class DropGeoUploadDeletedEventsTable < Gitlab::Database::Migration[1.0]
+ def up
+ drop_table :geo_upload_deleted_events
+ end
+
+ def down
+ create_table :geo_upload_deleted_events, id: :bigserial do |t|
+ t.integer :upload_id, null: false, index: true
+ t.string :file_path, null: false
+ t.integer :model_id, null: false
+ t.string :model_type, null: false
+ t.string :uploader, null: false
+ end
+ end
+end
diff --git a/db/post_migrate/20211022112202_add_cluster_id_location_index_to_vulnerability_occurrences.rb b/db/post_migrate/20211022112202_add_cluster_id_location_index_to_vulnerability_occurrences.rb
new file mode 100644
index 00000000000..9c40e81f527
--- /dev/null
+++ b/db/post_migrate/20211022112202_add_cluster_id_location_index_to_vulnerability_occurrences.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddClusterIdLocationIndexToVulnerabilityOccurrences < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_vulnerability_occurrences_on_location_cluster_id'
+
+ def up
+ add_concurrent_index :vulnerability_occurrences, "(location -> 'cluster_id')",
+ using: 'GIN',
+ where: 'report_type = 7',
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerability_occurrences, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211022113000_drop_index_security_ci_builds_on_name_and_id_parser_features_broken.rb b/db/post_migrate/20211022113000_drop_index_security_ci_builds_on_name_and_id_parser_features_broken.rb
new file mode 100644
index 00000000000..9ee1b10a072
--- /dev/null
+++ b/db/post_migrate/20211022113000_drop_index_security_ci_builds_on_name_and_id_parser_features_broken.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class DropIndexSecurityCiBuildsOnNameAndIdParserFeaturesBroken < Gitlab::Database::Migration[1.0]
+ TABLE = "ci_builds"
+ COLUMNS = %i[name id]
+ INDEX_NAME = "index_security_ci_builds_on_name_and_id_parser_features_broken"
+ CONSTRAINTS = "(name::text = ANY (ARRAY['container_scanning'::character varying::text,
+ 'dast'::character varying::text,
+ 'dependency_scanning'::character varying::text,
+ 'license_management'::character varying::text,
+ 'sast'::character varying::text,
+ 'secret_detection'::character varying::text,
+ 'coverage_fuzzing'::character varying::text,
+ 'license_scanning'::character varying::text])
+ ) AND type::text = 'Ci::Build'::text"
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index(TABLE, COLUMNS, name: INDEX_NAME, where: CONSTRAINTS)
+ end
+
+ def down
+ add_concurrent_index(TABLE, COLUMNS, name: INDEX_NAME, where: CONSTRAINTS)
+ end
+end
diff --git a/db/post_migrate/20211022160154_remove_outdated_fields_from_geo_node_status.rb b/db/post_migrate/20211022160154_remove_outdated_fields_from_geo_node_status.rb
new file mode 100644
index 00000000000..5b117f9e4b8
--- /dev/null
+++ b/db/post_migrate/20211022160154_remove_outdated_fields_from_geo_node_status.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class RemoveOutdatedFieldsFromGeoNodeStatus < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ remove_column :geo_node_statuses, :attachments_count, :integer
+ remove_column :geo_node_statuses, :attachments_synced_count, :integer
+ remove_column :geo_node_statuses, :attachments_failed_count, :integer
+ remove_column :geo_node_statuses, :attachments_synced_missing_on_primary_count, :integer
+ end
+end
diff --git a/db/post_migrate/20211027064021_track_deletions_in_ci_runners.rb b/db/post_migrate/20211027064021_track_deletions_in_ci_runners.rb
new file mode 100644
index 00000000000..14cf305fb2e
--- /dev/null
+++ b/db/post_migrate/20211027064021_track_deletions_in_ci_runners.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class TrackDeletionsInCiRunners < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
+
+ enable_lock_retries!
+
+ def up
+ track_record_deletions(:ci_runners)
+ end
+
+ def down
+ untrack_record_deletions(:ci_runners)
+ end
+end
diff --git a/db/post_migrate/20211027064156_track_deletions_in_chat_names.rb b/db/post_migrate/20211027064156_track_deletions_in_chat_names.rb
new file mode 100644
index 00000000000..1c8f9d5196a
--- /dev/null
+++ b/db/post_migrate/20211027064156_track_deletions_in_chat_names.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class TrackDeletionsInChatNames < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
+
+ enable_lock_retries!
+
+ def up
+ track_record_deletions(:chat_names)
+ end
+
+ def down
+ untrack_record_deletions(:chat_names)
+ end
+end
diff --git a/db/post_migrate/20211027112901_drop_index_keys_on_expires_at_and_before_expiry_notification_undelivered.rb b/db/post_migrate/20211027112901_drop_index_keys_on_expires_at_and_before_expiry_notification_undelivered.rb
new file mode 100644
index 00000000000..3447c4da81a
--- /dev/null
+++ b/db/post_migrate/20211027112901_drop_index_keys_on_expires_at_and_before_expiry_notification_undelivered.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class DropIndexKeysOnExpiresAtAndBeforeExpiryNotificationUndelivered < Gitlab::Database::Migration[1.0]
+ DOWNTIME = false
+ INDEX_NAME = 'index_keys_on_expires_at_and_expiry_notification_undelivered'
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name(:keys, INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index :keys,
+ "date(timezone('UTC', expires_at)), expiry_notification_delivered_at",
+ where: 'expiry_notification_delivered_at IS NULL', name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211027204011_remove_index_for_dormant_users.rb b/db/post_migrate/20211027204011_remove_index_for_dormant_users.rb
new file mode 100644
index 00000000000..5e556fe1f32
--- /dev/null
+++ b/db/post_migrate/20211027204011_remove_index_for_dormant_users.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveIndexForDormantUsers < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_users_on_id_and_last_activity_on_for_non_internal_active'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :users, INDEX_NAME
+ end
+
+ def down
+ index_condition = "state = 'active' AND (users.user_type IS NULL OR users.user_type IN (NULL, 6, 4))"
+
+ add_concurrent_index :users, [:id, :last_activity_on], where: index_condition, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211028085926_add_occurrence_id_id_desc_index_to_vulnerability_occurrence_pipelines.rb b/db/post_migrate/20211028085926_add_occurrence_id_id_desc_index_to_vulnerability_occurrence_pipelines.rb
new file mode 100644
index 00000000000..1f03e39aa81
--- /dev/null
+++ b/db/post_migrate/20211028085926_add_occurrence_id_id_desc_index_to_vulnerability_occurrence_pipelines.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class AddOccurrenceIdIdDescIndexToVulnerabilityOccurrencePipelines < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = "index_vulnerability_occurrence_pipelines_occurrence_id_and_id"
+
+ def up
+ add_concurrent_index(
+ :vulnerability_occurrence_pipelines,
+ [:occurrence_id, :id],
+ order: { id: :desc },
+ name: INDEX_NAME
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name(
+ :vulnerability_occurrence_pipelines,
+ INDEX_NAME
+ )
+ end
+end
diff --git a/db/post_migrate/20211028100303_tmp_index_for_delete_issue_merge_request_taggings_records.rb b/db/post_migrate/20211028100303_tmp_index_for_delete_issue_merge_request_taggings_records.rb
new file mode 100644
index 00000000000..98984239ca4
--- /dev/null
+++ b/db/post_migrate/20211028100303_tmp_index_for_delete_issue_merge_request_taggings_records.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class TmpIndexForDeleteIssueMergeRequestTaggingsRecords < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'tmp_index_taggings_on_id_where_taggable_type_issue_mr'
+ INDEX_CONDITION = "taggable_type IN ('Issue', 'MergeRequest')"
+
+ def up
+ add_concurrent_index :taggings, :id, where: INDEX_CONDITION, name: INDEX_NAME # rubocop:disable Migration/PreventIndexCreation
+ end
+
+ def down
+ remove_concurrent_index_by_name :taggings, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211028100843_delete_issue_merge_request_taggings_records.rb b/db/post_migrate/20211028100843_delete_issue_merge_request_taggings_records.rb
new file mode 100644
index 00000000000..1ceaa1b5aef
--- /dev/null
+++ b/db/post_migrate/20211028100843_delete_issue_merge_request_taggings_records.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class DeleteIssueMergeRequestTaggingsRecords < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'tmp_index_taggings_on_id_where_taggable_type_issue_mr'
+
+ BATCH_SIZE = 3_000
+ TAGGABLE_TYPES = %w(Issue MergeRequest)
+
+ def up
+ sleep 2 while ActsAsTaggableOn::Tagging.where(taggable_type: TAGGABLE_TYPES).limit(BATCH_SIZE).delete_all > 0
+
+ remove_concurrent_index_by_name :taggings, INDEX_NAME
+ end
+
+ def down
+ end
+end
diff --git a/db/post_migrate/20211028123412_add_async_index_on_events_using_btree_created_at_id.rb b/db/post_migrate/20211028123412_add_async_index_on_events_using_btree_created_at_id.rb
new file mode 100644
index 00000000000..03e461dfcd0
--- /dev/null
+++ b/db/post_migrate/20211028123412_add_async_index_on_events_using_btree_created_at_id.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddAsyncIndexOnEventsUsingBtreeCreatedAtId < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_events_on_created_at_and_id'
+ TABLE = :events
+ COLUMNS = %i[created_at id]
+ CONSTRAINTS = "created_at > '2021-08-27'"
+
+ def up
+ prepare_async_index TABLE, COLUMNS, name: INDEX_NAME, where: CONSTRAINTS
+ end
+
+ def down
+ unprepare_async_index TABLE, COLUMNS, name: INDEX_NAME, where: CONSTRAINTS
+ end
+end
diff --git a/db/post_migrate/20211028155449_schedule_fix_merge_request_diff_commit_users_migration.rb b/db/post_migrate/20211028155449_schedule_fix_merge_request_diff_commit_users_migration.rb
new file mode 100644
index 00000000000..659cb7b76b2
--- /dev/null
+++ b/db/post_migrate/20211028155449_schedule_fix_merge_request_diff_commit_users_migration.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+class ScheduleFixMergeRequestDiffCommitUsersMigration < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ MIGRATION_CLASS = 'FixMergeRequestDiffCommitUsers'
+
+ class Project < ApplicationRecord
+ include EachBatch
+
+ self.table_name = 'projects'
+ end
+
+ def up
+ # This is the day on which we merged
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63669. Since the
+ # deploy of this MR we may have imported projects using the old format, but
+ # after their merge_request_diff_id range had been migrated by Sidekiq. As a
+ # result, there may be rows without a committer_id or commit_author_id
+ # field.
+ date = '2021-07-07 00:00:00'
+
+ transaction do
+ Project.each_batch(of: 10_000) do |batch|
+ time = Time.now.utc
+ rows = batch
+ .where('created_at >= ?', date)
+ .where(import_type: 'gitlab_project')
+ .pluck(:id)
+ .map do |id|
+ Gitlab::Database::BackgroundMigrationJob.new(
+ class_name: MIGRATION_CLASS,
+ arguments: [id],
+ created_at: time,
+ updated_at: time
+ )
+ end
+
+ Gitlab::Database::BackgroundMigrationJob
+ .bulk_insert!(rows, validate: false)
+ end
+ end
+
+ job = Gitlab::Database::BackgroundMigrationJob
+ .for_migration_class(MIGRATION_CLASS)
+ .pending
+ .first
+
+ migrate_in(2.minutes, MIGRATION_CLASS, job.arguments) if job
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20211029102822_add_open_source_plan.rb b/db/post_migrate/20211029102822_add_open_source_plan.rb
new file mode 100644
index 00000000000..00266640f03
--- /dev/null
+++ b/db/post_migrate/20211029102822_add_open_source_plan.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+class AddOpenSourcePlan < Gitlab::Database::Migration[1.0]
+ class Plan < ActiveRecord::Base
+ self.inheritance_column = :_type_disabled
+
+ has_one :limits, class_name: 'PlanLimits'
+
+ def actual_limits
+ self.limits || self.build_limits
+ end
+ end
+
+ class PlanLimits < ActiveRecord::Base
+ self.inheritance_column = :_type_disabled
+
+ belongs_to :plan
+ end
+
+ def create_plan_limits(plan_limit_name, plan)
+ plan_limit = Plan.find_or_initialize_by(name: plan_limit_name).actual_limits.dup
+ plan_limit.plan = plan
+ plan_limit.save!
+ end
+
+ def up
+ return unless Gitlab.dev_env_or_com?
+
+ opensource = Plan.create!(name: 'opensource', title: 'Open Source Program')
+
+ create_plan_limits('ultimate', opensource)
+ end
+
+ def down
+ return unless Gitlab.dev_env_or_com?
+
+ Plan.where(name: 'opensource').delete_all
+ end
+end
diff --git a/db/post_migrate/20211031152417_add_indexes_to_issue_stage_events.rb b/db/post_migrate/20211031152417_add_indexes_to_issue_stage_events.rb
new file mode 100644
index 00000000000..73b70ad1e27
--- /dev/null
+++ b/db/post_migrate/20211031152417_add_indexes_to_issue_stage_events.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class AddIndexesToIssueStageEvents < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ disable_ddl_transaction!
+
+ GROUP_INDEX_NAME = 'index_issue_stage_events_group_duration'
+ GROUP_IN_PROGRESS_INDEX_NAME = 'index_issue_stage_events_group_in_progress_duration'
+ PROJECT_INDEX_NAME = 'index_issue_stage_events_project_duration'
+ PROJECT_IN_PROGRESS_INDEX_NAME = 'index_issue_stage_events_project_in_progress_duration'
+
+ def up
+ add_concurrent_partitioned_index :analytics_cycle_analytics_issue_stage_events,
+ 'stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp',
+ where: 'end_event_timestamp IS NOT NULL',
+ name: GROUP_INDEX_NAME
+
+ add_concurrent_partitioned_index :analytics_cycle_analytics_issue_stage_events,
+ 'stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp',
+ where: 'end_event_timestamp IS NOT NULL',
+ name: PROJECT_INDEX_NAME
+
+ add_concurrent_partitioned_index :analytics_cycle_analytics_issue_stage_events,
+ 'stage_event_hash_id, group_id, start_event_timestamp, issue_id',
+ where: 'end_event_timestamp IS NULL AND state_id = 1',
+ name: GROUP_IN_PROGRESS_INDEX_NAME
+
+ add_concurrent_partitioned_index :analytics_cycle_analytics_issue_stage_events,
+ 'stage_event_hash_id, project_id, start_event_timestamp, issue_id',
+ where: 'end_event_timestamp IS NULL AND state_id = 1',
+ name: PROJECT_IN_PROGRESS_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_partitioned_index_by_name :analytics_cycle_analytics_issue_stage_events, GROUP_INDEX_NAME
+ remove_concurrent_partitioned_index_by_name :analytics_cycle_analytics_issue_stage_events, PROJECT_INDEX_NAME
+ remove_concurrent_partitioned_index_by_name :analytics_cycle_analytics_issue_stage_events, GROUP_IN_PROGRESS_INDEX_NAME
+ remove_concurrent_partitioned_index_by_name :analytics_cycle_analytics_issue_stage_events, PROJECT_IN_PROGRESS_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211031154919_add_indexes_to_merge_request_stage_events.rb b/db/post_migrate/20211031154919_add_indexes_to_merge_request_stage_events.rb
new file mode 100644
index 00000000000..9cc9d73c968
--- /dev/null
+++ b/db/post_migrate/20211031154919_add_indexes_to_merge_request_stage_events.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class AddIndexesToMergeRequestStageEvents < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ disable_ddl_transaction!
+
+ GROUP_INDEX_NAME = 'index_merge_request_stage_events_group_duration'
+ GROUP_IN_PROGRESS_INDEX_NAME = 'index_merge_request_stage_events_group_in_progress_duration'
+ PROJECT_INDEX_NAME = 'index_merge_request_stage_events_project_duration'
+ PROJECT_IN_PROGRESS_INDEX_NAME = 'index_merge_request_stage_events_project_in_progress_duration'
+
+ def up
+ add_concurrent_partitioned_index :analytics_cycle_analytics_merge_request_stage_events,
+ 'stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp',
+ where: 'end_event_timestamp IS NOT NULL',
+ name: GROUP_INDEX_NAME
+
+ add_concurrent_partitioned_index :analytics_cycle_analytics_merge_request_stage_events,
+ 'stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp',
+ where: 'end_event_timestamp IS NOT NULL',
+ name: PROJECT_INDEX_NAME
+
+ add_concurrent_partitioned_index :analytics_cycle_analytics_merge_request_stage_events,
+ 'stage_event_hash_id, group_id, start_event_timestamp, merge_request_id',
+ where: 'end_event_timestamp IS NULL AND state_id = 1',
+ name: GROUP_IN_PROGRESS_INDEX_NAME
+
+ add_concurrent_partitioned_index :analytics_cycle_analytics_merge_request_stage_events,
+ 'stage_event_hash_id, project_id, start_event_timestamp, merge_request_id',
+ where: 'end_event_timestamp IS NULL AND state_id = 1',
+ name: PROJECT_IN_PROGRESS_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_partitioned_index_by_name :analytics_cycle_analytics_merge_request_stage_events, GROUP_INDEX_NAME
+ remove_concurrent_partitioned_index_by_name :analytics_cycle_analytics_merge_request_stage_events, PROJECT_INDEX_NAME
+ remove_concurrent_partitioned_index_by_name :analytics_cycle_analytics_merge_request_stage_events, GROUP_IN_PROGRESS_INDEX_NAME
+ remove_concurrent_partitioned_index_by_name :analytics_cycle_analytics_merge_request_stage_events, PROJECT_IN_PROGRESS_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211102103127_add_temp_index_to_vulnerability_occurrences.rb b/db/post_migrate/20211102103127_add_temp_index_to_vulnerability_occurrences.rb
new file mode 100644
index 00000000000..4aee79950dc
--- /dev/null
+++ b/db/post_migrate/20211102103127_add_temp_index_to_vulnerability_occurrences.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddTempIndexToVulnerabilityOccurrences < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'vulnerability_occurrences_location_temp_index'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerability_occurrences, :id, where: 'location IS NULL', name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerability_occurrences, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211102114802_update_vulnerability_occurrences_location.rb b/db/post_migrate/20211102114802_update_vulnerability_occurrences_location.rb
new file mode 100644
index 00000000000..44e2630af06
--- /dev/null
+++ b/db/post_migrate/20211102114802_update_vulnerability_occurrences_location.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class UpdateVulnerabilityOccurrencesLocation < Gitlab::Database::Migration[1.0]
+ BATCH_SIZE = 20_000
+ DELAY_INTERVAL = 3.minutes
+ MIGRATION_NAME = 'UpdateVulnerabilityOccurrencesLocation'
+
+ disable_ddl_transaction!
+
+ def up
+ return unless Gitlab.ee?
+
+ relation = Gitlab::BackgroundMigration::UpdateVulnerabilityOccurrencesLocation::Occurrence.where(location: nil)
+ queue_background_migration_jobs_by_range_at_intervals(relation,
+ MIGRATION_NAME,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ track_jobs: true)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20211103162025_add_index_on_events_using_btree_created_at_id.rb b/db/post_migrate/20211103162025_add_index_on_events_using_btree_created_at_id.rb
new file mode 100644
index 00000000000..33d5833db1a
--- /dev/null
+++ b/db/post_migrate/20211103162025_add_index_on_events_using_btree_created_at_id.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexOnEventsUsingBtreeCreatedAtId < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_events_on_created_at_and_id'
+ TABLE = :events
+ COLUMNS = %i[created_at id]
+ CONSTRAINTS = "created_at > '2021-08-27 00:00:00+00'"
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index TABLE, COLUMNS, name: INDEX_NAME, where: CONSTRAINTS
+ end
+
+ def down
+ remove_concurrent_index TABLE, COLUMNS, name: INDEX_NAME, where: CONSTRAINTS
+ end
+end
diff --git a/db/post_migrate/20211104044453_remove_redundant_events_index.rb b/db/post_migrate/20211104044453_remove_redundant_events_index.rb
new file mode 100644
index 00000000000..54e71e1b54b
--- /dev/null
+++ b/db/post_migrate/20211104044453_remove_redundant_events_index.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class RemoveRedundantEventsIndex < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :events, :index_events_on_target_type_and_target_id
+ end
+
+ def down
+ add_concurrent_index :events, [:target_type, :target_id], name: :index_events_on_target_type_and_target_id
+ end
+end
diff --git a/db/post_migrate/20211105135157_drop_ci_build_trace_sections.rb b/db/post_migrate/20211105135157_drop_ci_build_trace_sections.rb
new file mode 100644
index 00000000000..1595068952d
--- /dev/null
+++ b/db/post_migrate/20211105135157_drop_ci_build_trace_sections.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+class DropCiBuildTraceSections < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::SchemaHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ remove_foreign_key_if_exists(:dep_ci_build_trace_sections, column: :project_id)
+ end
+
+ with_lock_retries do
+ remove_foreign_key_if_exists(:dep_ci_build_trace_section_names, column: :project_id)
+ end
+
+ if table_exists?(:dep_ci_build_trace_sections)
+ with_lock_retries do
+ drop_table :dep_ci_build_trace_sections
+ end
+ end
+
+ if table_exists?(:dep_ci_build_trace_section_names)
+ with_lock_retries do
+ drop_table :dep_ci_build_trace_section_names
+ end
+ end
+
+ drop_function('trigger_91dc388a5fe6')
+ end
+
+ def down
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION trigger_91dc388a5fe6() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+ BEGIN
+ NEW."build_id_convert_to_bigint" := NEW."build_id";
+ RETURN NEW;
+ END;
+ $$;
+ SQL
+
+ execute_in_transaction(<<~SQL, !table_exists?(:dep_ci_build_trace_section_names))
+ CREATE TABLE dep_ci_build_trace_section_names (
+ id integer NOT NULL,
+ project_id integer NOT NULL,
+ name character varying NOT NULL
+ );
+
+ CREATE SEQUENCE dep_ci_build_trace_section_names_id_seq
+ AS integer
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ ALTER SEQUENCE dep_ci_build_trace_section_names_id_seq OWNED BY dep_ci_build_trace_section_names.id;
+
+ ALTER TABLE ONLY dep_ci_build_trace_section_names ALTER COLUMN id SET DEFAULT nextval('dep_ci_build_trace_section_names_id_seq'::regclass);
+ ALTER TABLE ONLY dep_ci_build_trace_section_names ADD CONSTRAINT dep_ci_build_trace_section_names_pkey PRIMARY KEY (id);
+ SQL
+
+ execute_in_transaction(<<~SQL, !table_exists?(:dep_ci_build_trace_sections))
+ CREATE TABLE dep_ci_build_trace_sections (
+ project_id integer NOT NULL,
+ date_start timestamp without time zone NOT NULL,
+ date_end timestamp without time zone NOT NULL,
+ byte_start bigint NOT NULL,
+ byte_end bigint NOT NULL,
+ build_id integer NOT NULL,
+ section_name_id integer NOT NULL,
+ build_id_convert_to_bigint bigint DEFAULT 0 NOT NULL
+ );
+
+ ALTER TABLE ONLY dep_ci_build_trace_sections ADD CONSTRAINT ci_build_trace_sections_pkey PRIMARY KEY (build_id, section_name_id);
+ CREATE TRIGGER trigger_91dc388a5fe6 BEFORE INSERT OR UPDATE ON dep_ci_build_trace_sections FOR EACH ROW EXECUTE FUNCTION trigger_91dc388a5fe6();
+ SQL
+
+ add_concurrent_index :dep_ci_build_trace_section_names, [:project_id, :name], unique: true, name: 'index_dep_ci_build_trace_section_names_on_project_id_and_name'
+ add_concurrent_index :dep_ci_build_trace_sections, :project_id, name: 'index_dep_ci_build_trace_sections_on_project_id'
+ add_concurrent_index :dep_ci_build_trace_sections, :section_name_id, name: 'index_dep_ci_build_trace_sections_on_section_name_id'
+
+ add_concurrent_foreign_key :dep_ci_build_trace_sections, :dep_ci_build_trace_section_names, column: :section_name_id, on_delete: :cascade, name: 'fk_264e112c66'
+ add_concurrent_foreign_key :dep_ci_build_trace_sections, :projects, column: :project_id, on_delete: :cascade, name: 'fk_ab7c104e26'
+ add_concurrent_foreign_key :dep_ci_build_trace_section_names, :projects, column: :project_id, on_delete: :cascade, name: 'fk_f8cd72cd26'
+ end
+
+ private
+
+ def execute_in_transaction(sql, condition)
+ return unless condition
+
+ transaction do
+ execute(sql)
+ end
+ end
+end
diff --git a/db/post_migrate/20211109112454_drop_old_loose_fk_deleted_records_index.rb b/db/post_migrate/20211109112454_drop_old_loose_fk_deleted_records_index.rb
new file mode 100644
index 00000000000..ef5a70713d0
--- /dev/null
+++ b/db/post_migrate/20211109112454_drop_old_loose_fk_deleted_records_index.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class DropOldLooseFkDeletedRecordsIndex < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_loose_foreign_keys_deleted_records_for_loading_records'
+
+ def up
+ remove_concurrent_partitioned_index_by_name :loose_foreign_keys_deleted_records, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_partitioned_index :loose_foreign_keys_deleted_records,
+ %I[fully_qualified_table_name id primary_key_value partition],
+ where: 'status = 1',
+ name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211112113300_remove_ci_pipeline_chat_data_fk_on_chat_names.rb b/db/post_migrate/20211112113300_remove_ci_pipeline_chat_data_fk_on_chat_names.rb
new file mode 100644
index 00000000000..19adc6c7084
--- /dev/null
+++ b/db/post_migrate/20211112113300_remove_ci_pipeline_chat_data_fk_on_chat_names.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class RemoveCiPipelineChatDataFkOnChatNames < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ remove_foreign_key_if_exists(:ci_pipeline_chat_data, :chat_names, name: "fk_rails_f300456b63")
+ end
+ end
+
+ def down
+ # Remove orphaned rows
+ execute <<~SQL
+ DELETE FROM ci_pipeline_chat_data
+ WHERE
+ NOT EXISTS (SELECT 1 FROM chat_names WHERE chat_names.id=ci_pipeline_chat_data.chat_name_id)
+ SQL
+
+ add_concurrent_foreign_key(:ci_pipeline_chat_data, :chat_names, name: "fk_rails_f300456b63", column: :chat_name_id, target_column: :id, on_delete: "cascade")
+ end
+end
diff --git a/db/post_migrate/20211115151704_add_index_on_projects_import_type_id.rb b/db/post_migrate/20211115151704_add_index_on_projects_import_type_id.rb
new file mode 100644
index 00000000000..b54edc1cf73
--- /dev/null
+++ b/db/post_migrate/20211115151704_add_index_on_projects_import_type_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexOnProjectsImportTypeId < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_imported_projects_on_import_type_id'
+
+ def up
+ add_concurrent_index(:projects, [:import_type, :id], where: 'import_type IS NOT NULL', name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(:projects, INDEX_NAME)
+ end
+end
diff --git a/db/schema_migrations/20200102140148 b/db/schema_migrations/20200102140148
deleted file mode 100644
index 5238acd0478..00000000000
--- a/db/schema_migrations/20200102140148
+++ /dev/null
@@ -1 +0,0 @@
-c92babf7e04f018d85380348545bd023db0a5337c1ba75341393e2d77921c907 \ No newline at end of file
diff --git a/db/schema_migrations/20200102170221 b/db/schema_migrations/20200102170221
deleted file mode 100644
index f1581b378f6..00000000000
--- a/db/schema_migrations/20200102170221
+++ /dev/null
@@ -1 +0,0 @@
-12373b45cfcef55fe29492ffa24d91770683d8c3f02f3bc7381044e097420da9 \ No newline at end of file
diff --git a/db/schema_migrations/20200103190741 b/db/schema_migrations/20200103190741
deleted file mode 100644
index b84ba1d485e..00000000000
--- a/db/schema_migrations/20200103190741
+++ /dev/null
@@ -1 +0,0 @@
-c648f714c029501e10d1d5aaaa7a8d844e950bdc54e6e675806cfcf310542e6a \ No newline at end of file
diff --git a/db/schema_migrations/20200103192859 b/db/schema_migrations/20200103192859
deleted file mode 100644
index 91eb68d9fe6..00000000000
--- a/db/schema_migrations/20200103192859
+++ /dev/null
@@ -1 +0,0 @@
-903ec05dbe2bf0dd6908ebe536082396a4abfdc4c52d24b5c3d8bf5b567ad6ac \ No newline at end of file
diff --git a/db/schema_migrations/20200103192914 b/db/schema_migrations/20200103192914
deleted file mode 100644
index e83883506d9..00000000000
--- a/db/schema_migrations/20200103192914
+++ /dev/null
@@ -1 +0,0 @@
-ac8d93ce6b0a4c1088673cfe7a86e1dd7d1bf3321ad86b4d626026f866c01343 \ No newline at end of file
diff --git a/db/schema_migrations/20200103195205 b/db/schema_migrations/20200103195205
deleted file mode 100644
index bf519d8198b..00000000000
--- a/db/schema_migrations/20200103195205
+++ /dev/null
@@ -1 +0,0 @@
-13c574741955afcf6c9142710453e4974e014019b1b045ffc7a41ec48d983de6 \ No newline at end of file
diff --git a/db/schema_migrations/20200104113850 b/db/schema_migrations/20200104113850
deleted file mode 100644
index a82ba279b88..00000000000
--- a/db/schema_migrations/20200104113850
+++ /dev/null
@@ -1 +0,0 @@
-c424f5d5b25ba4a7da3757498200cbba3a27693f20db93cf6750c20fccda8de7 \ No newline at end of file
diff --git a/db/schema_migrations/20200106071113 b/db/schema_migrations/20200106071113
deleted file mode 100644
index 4b6b29ebaff..00000000000
--- a/db/schema_migrations/20200106071113
+++ /dev/null
@@ -1 +0,0 @@
-d9f594a3c50f85d4f543e37e45dea45976763ba959fe84dc28a58b87ab60a509 \ No newline at end of file
diff --git a/db/schema_migrations/20200106085831 b/db/schema_migrations/20200106085831
deleted file mode 100644
index ff67d1772f2..00000000000
--- a/db/schema_migrations/20200106085831
+++ /dev/null
@@ -1 +0,0 @@
-f398ad67fdef4992495c3aeaf2be2659cf5a3594ad08112b33471c6cbe496a2b \ No newline at end of file
diff --git a/db/schema_migrations/20200107172020 b/db/schema_migrations/20200107172020
deleted file mode 100644
index 9bcf05557f4..00000000000
--- a/db/schema_migrations/20200107172020
+++ /dev/null
@@ -1 +0,0 @@
-6dfa2dec4773dea596097e3735df899f4fe22d94ec9dcbef70cd610ed848ae4e \ No newline at end of file
diff --git a/db/schema_migrations/20200108100603 b/db/schema_migrations/20200108100603
deleted file mode 100644
index 8f0c730a87b..00000000000
--- a/db/schema_migrations/20200108100603
+++ /dev/null
@@ -1 +0,0 @@
-5c2c00f6ce104f6ba87f3495c0d6464fd553c0c66c83de14ba80af8cff132b64 \ No newline at end of file
diff --git a/db/schema_migrations/20200108155731 b/db/schema_migrations/20200108155731
deleted file mode 100644
index c00bd7bbb6f..00000000000
--- a/db/schema_migrations/20200108155731
+++ /dev/null
@@ -1 +0,0 @@
-dd7df8deaeacebf372507cf636a5750cc0e8afc8f5a0dc80abc928a0c1d6d97c \ No newline at end of file
diff --git a/db/schema_migrations/20200108233040 b/db/schema_migrations/20200108233040
deleted file mode 100644
index 03644c321d7..00000000000
--- a/db/schema_migrations/20200108233040
+++ /dev/null
@@ -1 +0,0 @@
-010c50e90d138ac7d4a1c337cd320526fb6d137e634747977b72ee9306ea05a6 \ No newline at end of file
diff --git a/db/schema_migrations/20200109030418 b/db/schema_migrations/20200109030418
deleted file mode 100644
index 8c95f4745a8..00000000000
--- a/db/schema_migrations/20200109030418
+++ /dev/null
@@ -1 +0,0 @@
-05d9a1433e6c00f9df21430dce8467d4b9b29c9aa38375da8a9dc1d77a54e215 \ No newline at end of file
diff --git a/db/schema_migrations/20200109085206 b/db/schema_migrations/20200109085206
deleted file mode 100644
index 56ad16062fe..00000000000
--- a/db/schema_migrations/20200109085206
+++ /dev/null
@@ -1 +0,0 @@
-ed6174d9e7b660068050f78f8bd9e66f4d7bdaf761da6007cabb7d891ee51605 \ No newline at end of file
diff --git a/db/schema_migrations/20200109233938 b/db/schema_migrations/20200109233938
deleted file mode 100644
index 04a9475c023..00000000000
--- a/db/schema_migrations/20200109233938
+++ /dev/null
@@ -1 +0,0 @@
-3fabb8446e67bbb1fdb111d05bbba68f25d4c2e6518750c535db7d1d23c5fe26 \ No newline at end of file
diff --git a/db/schema_migrations/20200110089001 b/db/schema_migrations/20200110089001
deleted file mode 100644
index 2e09521dcbe..00000000000
--- a/db/schema_migrations/20200110089001
+++ /dev/null
@@ -1 +0,0 @@
-910b8664a55402ca97dd17020c9be4aba5780d1fae6acfab1d930e106968875e \ No newline at end of file
diff --git a/db/schema_migrations/20200110090153 b/db/schema_migrations/20200110090153
deleted file mode 100644
index 3622eff8263..00000000000
--- a/db/schema_migrations/20200110090153
+++ /dev/null
@@ -1 +0,0 @@
-2bf0234bcc5dbb97c38040fd4016b223dc80300592628a8211f2e912bcfc1d8f \ No newline at end of file
diff --git a/db/schema_migrations/20200110121314 b/db/schema_migrations/20200110121314
deleted file mode 100644
index 021f4605524..00000000000
--- a/db/schema_migrations/20200110121314
+++ /dev/null
@@ -1 +0,0 @@
-ac34cb0e41262117918b812e5322f76bda29d35c9b91bee11aad1f8dd16833b1 \ No newline at end of file
diff --git a/db/schema_migrations/20200110144316 b/db/schema_migrations/20200110144316
deleted file mode 100644
index 334423df1ba..00000000000
--- a/db/schema_migrations/20200110144316
+++ /dev/null
@@ -1 +0,0 @@
-6c592c74d8182794ea8e791368f7a72f49ca3e85b4293d7bf2d88060d6223c36 \ No newline at end of file
diff --git a/db/schema_migrations/20200110203532 b/db/schema_migrations/20200110203532
deleted file mode 100644
index 14ab27d84c6..00000000000
--- a/db/schema_migrations/20200110203532
+++ /dev/null
@@ -1 +0,0 @@
-35a709042705267f5b7581c593949c048dc93dd185d914b5e27e2c0735b4fd7d \ No newline at end of file
diff --git a/db/schema_migrations/20200113133352 b/db/schema_migrations/20200113133352
deleted file mode 100644
index fad80f3bbc9..00000000000
--- a/db/schema_migrations/20200113133352
+++ /dev/null
@@ -1 +0,0 @@
-1bdcb05f24558107315b88d26a5aa39a50f9c04871e422290526abaa8e3cbb17 \ No newline at end of file
diff --git a/db/schema_migrations/20200113151354 b/db/schema_migrations/20200113151354
deleted file mode 100644
index 4f92d11f56b..00000000000
--- a/db/schema_migrations/20200113151354
+++ /dev/null
@@ -1 +0,0 @@
-ab7745e3b9beff8e352c097ab08db4ed8da18a41f3463e3077e0d9388753d6c6 \ No newline at end of file
diff --git a/db/schema_migrations/20200114112932 b/db/schema_migrations/20200114112932
deleted file mode 100644
index aa02583018c..00000000000
--- a/db/schema_migrations/20200114112932
+++ /dev/null
@@ -1 +0,0 @@
-f147e272eec80e34957ea4dd80669f7e1e7b49ca9714bf63afe386efaff71a75 \ No newline at end of file
diff --git a/db/schema_migrations/20200114113341 b/db/schema_migrations/20200114113341
deleted file mode 100644
index 0ba8e96275c..00000000000
--- a/db/schema_migrations/20200114113341
+++ /dev/null
@@ -1 +0,0 @@
-59814f51a5849cf979c7b98df8bd6c6eeef754935fbb3a0fe6444b5e3def99af \ No newline at end of file
diff --git a/db/schema_migrations/20200114140305 b/db/schema_migrations/20200114140305
deleted file mode 100644
index 180ee4abc63..00000000000
--- a/db/schema_migrations/20200114140305
+++ /dev/null
@@ -1 +0,0 @@
-57589e2252e1a2aa440b3df13db3c1bc089adf3dd8a159ee7a95f42e80581ec6 \ No newline at end of file
diff --git a/db/schema_migrations/20200114204949 b/db/schema_migrations/20200114204949
deleted file mode 100644
index 02e5970a74d..00000000000
--- a/db/schema_migrations/20200114204949
+++ /dev/null
@@ -1 +0,0 @@
-8acd1453e24c3163b06c3f10a8a01695b00f51be067eb932f459875d03301038 \ No newline at end of file
diff --git a/db/schema_migrations/20200115135132 b/db/schema_migrations/20200115135132
deleted file mode 100644
index 0bb4de40e24..00000000000
--- a/db/schema_migrations/20200115135132
+++ /dev/null
@@ -1 +0,0 @@
-a28043256d4df1ef5b5fa2661a220a54f7440a6b116d2bb9e0ff16f5396c5857 \ No newline at end of file
diff --git a/db/schema_migrations/20200115135234 b/db/schema_migrations/20200115135234
deleted file mode 100644
index a332094fd17..00000000000
--- a/db/schema_migrations/20200115135234
+++ /dev/null
@@ -1 +0,0 @@
-642d13d32940f108e43be044509be9df3be9eeab68f36de6af89f8f94327ca84 \ No newline at end of file
diff --git a/db/schema_migrations/20200116051619 b/db/schema_migrations/20200116051619
deleted file mode 100644
index d5aac9425a2..00000000000
--- a/db/schema_migrations/20200116051619
+++ /dev/null
@@ -1 +0,0 @@
-3f7a744bd4e3cfcd34b158d1c18fe491fd34092cf873faf81af9fe32146e2d4c \ No newline at end of file
diff --git a/db/schema_migrations/20200116175538 b/db/schema_migrations/20200116175538
deleted file mode 100644
index 85045596827..00000000000
--- a/db/schema_migrations/20200116175538
+++ /dev/null
@@ -1 +0,0 @@
-9960ac62201ae313b2b884b027740778ab7fce655a8017d2f966097a537eb9b0 \ No newline at end of file
diff --git a/db/schema_migrations/20200117112554 b/db/schema_migrations/20200117112554
deleted file mode 100644
index 9c1ac447570..00000000000
--- a/db/schema_migrations/20200117112554
+++ /dev/null
@@ -1 +0,0 @@
-d0ee4a357bfbbcb0211623171a48d443a6373b88a409c341ac1a49e3e0a773ce \ No newline at end of file
diff --git a/db/schema_migrations/20200117194830 b/db/schema_migrations/20200117194830
deleted file mode 100644
index d9d2a6a1953..00000000000
--- a/db/schema_migrations/20200117194830
+++ /dev/null
@@ -1 +0,0 @@
-52ae64fef3e148e45a2b65eab37122a6cc7c1c580fc9391aaed898f7b3b3e3aa \ No newline at end of file
diff --git a/db/schema_migrations/20200117194840 b/db/schema_migrations/20200117194840
deleted file mode 100644
index 9673da5ce3f..00000000000
--- a/db/schema_migrations/20200117194840
+++ /dev/null
@@ -1 +0,0 @@
-0a1278d223cafcb4fb164bc8f77b1b1be076ea576b0f610ba63c0a33aed35fc5 \ No newline at end of file
diff --git a/db/schema_migrations/20200117194850 b/db/schema_migrations/20200117194850
deleted file mode 100644
index a388909900b..00000000000
--- a/db/schema_migrations/20200117194850
+++ /dev/null
@@ -1 +0,0 @@
-6da075c7e03efc1d67cc1ad2c3142e748cfe6ca8324174bc4a75fe06bf3a9846 \ No newline at end of file
diff --git a/db/schema_migrations/20200117194900 b/db/schema_migrations/20200117194900
deleted file mode 100644
index e0514abc560..00000000000
--- a/db/schema_migrations/20200117194900
+++ /dev/null
@@ -1 +0,0 @@
-0a0701f610ed956bc57ad5197852acbd7eded9e598ccf30926735cf6209319c9 \ No newline at end of file
diff --git a/db/schema_migrations/20200120083607 b/db/schema_migrations/20200120083607
deleted file mode 100644
index 2c5eb55b2c1..00000000000
--- a/db/schema_migrations/20200120083607
+++ /dev/null
@@ -1 +0,0 @@
-d4949ac7b3ca7d2039daaf2afb39b606ff2cf4413c888958307e865e451a4209 \ No newline at end of file
diff --git a/db/schema_migrations/20200121132641 b/db/schema_migrations/20200121132641
deleted file mode 100644
index 09b12d4aa0a..00000000000
--- a/db/schema_migrations/20200121132641
+++ /dev/null
@@ -1 +0,0 @@
-e94dc0cc71ddba02eeeda68a476220c5912c58f214b83f20d62b98caa142240a \ No newline at end of file
diff --git a/db/schema_migrations/20200121192942 b/db/schema_migrations/20200121192942
deleted file mode 100644
index 91283f119fd..00000000000
--- a/db/schema_migrations/20200121192942
+++ /dev/null
@@ -1 +0,0 @@
-a4b140e11ffccaede80f263ca4bf0a9f72e9bf95f166da519b4ee2054a96ec69 \ No newline at end of file
diff --git a/db/schema_migrations/20200121194000 b/db/schema_migrations/20200121194000
deleted file mode 100644
index 6f2fdc0cc4e..00000000000
--- a/db/schema_migrations/20200121194000
+++ /dev/null
@@ -1 +0,0 @@
-4b799208cf30f9dc30f3bdeb228b6c30b63550a32b897975fa0cbb3079a0c07e \ No newline at end of file
diff --git a/db/schema_migrations/20200121194048 b/db/schema_migrations/20200121194048
deleted file mode 100644
index bddbab9f16b..00000000000
--- a/db/schema_migrations/20200121194048
+++ /dev/null
@@ -1 +0,0 @@
-33ba0b07d98f6902ac198ecd3b14487b525055ddfe9d0d563cc934731ff6767d \ No newline at end of file
diff --git a/db/schema_migrations/20200121194154 b/db/schema_migrations/20200121194154
deleted file mode 100644
index 90260047fb9..00000000000
--- a/db/schema_migrations/20200121194154
+++ /dev/null
@@ -1 +0,0 @@
-f0da6b9af1c5890918837d8c061123c7b961874c3571828daf2931e4a70f0ed1 \ No newline at end of file
diff --git a/db/schema_migrations/20200121200203 b/db/schema_migrations/20200121200203
deleted file mode 100644
index 5f63cbb42e4..00000000000
--- a/db/schema_migrations/20200121200203
+++ /dev/null
@@ -1 +0,0 @@
-ab639a76eeb5524ff8c8b708d26821ddefbf1839e61dcfc884d8a8b18f4c50e4 \ No newline at end of file
diff --git a/db/schema_migrations/20200122123016 b/db/schema_migrations/20200122123016
deleted file mode 100644
index 69584f7dfc7..00000000000
--- a/db/schema_migrations/20200122123016
+++ /dev/null
@@ -1 +0,0 @@
-608e4f1c327085dd1121e7af04be07676a0d7812290ad6bddf92c40a76d8fb21 \ No newline at end of file
diff --git a/db/schema_migrations/20200122144759 b/db/schema_migrations/20200122144759
deleted file mode 100644
index a049c6fe18e..00000000000
--- a/db/schema_migrations/20200122144759
+++ /dev/null
@@ -1 +0,0 @@
-a0af4050dda77d1caf4f3a989f7d4183ffff328af983f691c0ba98329d1283d7 \ No newline at end of file
diff --git a/db/schema_migrations/20200122161638 b/db/schema_migrations/20200122161638
deleted file mode 100644
index a1172c9ae71..00000000000
--- a/db/schema_migrations/20200122161638
+++ /dev/null
@@ -1 +0,0 @@
-9465b28cf31235cab10a0cbcbfc7cdffe3277b5b01d65b390272cfa91af2c5dd \ No newline at end of file
diff --git a/db/schema_migrations/20200123040535 b/db/schema_migrations/20200123040535
deleted file mode 100644
index 52a47270607..00000000000
--- a/db/schema_migrations/20200123040535
+++ /dev/null
@@ -1 +0,0 @@
-e3e21ce28714322b679a59476c9ce449c4ba7d6bee42754ecfa43b4b5fa5da73 \ No newline at end of file
diff --git a/db/schema_migrations/20200123045415 b/db/schema_migrations/20200123045415
deleted file mode 100644
index 673952ec64b..00000000000
--- a/db/schema_migrations/20200123045415
+++ /dev/null
@@ -1 +0,0 @@
-4c97265771d7dd793da2857391bc2d7092ae6c3a92c2a4249abe58420f7ac5f1 \ No newline at end of file
diff --git a/db/schema_migrations/20200123090839 b/db/schema_migrations/20200123090839
deleted file mode 100644
index 94ecb06f298..00000000000
--- a/db/schema_migrations/20200123090839
+++ /dev/null
@@ -1 +0,0 @@
-3b3292b611e5596f02ef63ae09e89f15a897ff748f4fbd8758fa35e30195fb78 \ No newline at end of file
diff --git a/db/schema_migrations/20200123091422 b/db/schema_migrations/20200123091422
deleted file mode 100644
index f65804e4261..00000000000
--- a/db/schema_migrations/20200123091422
+++ /dev/null
@@ -1 +0,0 @@
-f98df22c6c6d522ae4e2b143404d1e4434cc31ff1d8b1c9be8e33cbde8c7ea9d \ No newline at end of file
diff --git a/db/schema_migrations/20200123091622 b/db/schema_migrations/20200123091622
deleted file mode 100644
index 44cc7d7bf6f..00000000000
--- a/db/schema_migrations/20200123091622
+++ /dev/null
@@ -1 +0,0 @@
-028253e34270832d6aa7d7fe69a8f33958d85d5d12cee46b9ea47b523202e48a \ No newline at end of file
diff --git a/db/schema_migrations/20200123091734 b/db/schema_migrations/20200123091734
deleted file mode 100644
index 5e1ac40dcd7..00000000000
--- a/db/schema_migrations/20200123091734
+++ /dev/null
@@ -1 +0,0 @@
-ce02c924eed148ac534b93056691d1d0306c7a45dad92f3dc91fd76b7a0792b7 \ No newline at end of file
diff --git a/db/schema_migrations/20200123091854 b/db/schema_migrations/20200123091854
deleted file mode 100644
index ad06c23b2fd..00000000000
--- a/db/schema_migrations/20200123091854
+++ /dev/null
@@ -1 +0,0 @@
-7094292c63f651c6efa63cd2be16ff9068cb6b914c60aabefe4c9dec98097d0e \ No newline at end of file
diff --git a/db/schema_migrations/20200123155929 b/db/schema_migrations/20200123155929
deleted file mode 100644
index 5bc6645766c..00000000000
--- a/db/schema_migrations/20200123155929
+++ /dev/null
@@ -1 +0,0 @@
-27b0cd6f4503caab38dd480df6c928a00b178accb66f30015159bcc7dd7ce1f5 \ No newline at end of file
diff --git a/db/schema_migrations/20200124053531 b/db/schema_migrations/20200124053531
deleted file mode 100644
index 5deab13f348..00000000000
--- a/db/schema_migrations/20200124053531
+++ /dev/null
@@ -1 +0,0 @@
-809f368efa8d0b3d6129af9d41a59901495bd77e2727f2e16f8f60d3955b907d \ No newline at end of file
diff --git a/db/schema_migrations/20200124110831 b/db/schema_migrations/20200124110831
deleted file mode 100644
index 836990c915d..00000000000
--- a/db/schema_migrations/20200124110831
+++ /dev/null
@@ -1 +0,0 @@
-06cea4564bf349dad9fd3daea7d07d6e20a799d28e4b88bf4a5540b2d3e43312 \ No newline at end of file
diff --git a/db/schema_migrations/20200124143014 b/db/schema_migrations/20200124143014
deleted file mode 100644
index bedad0bc3d2..00000000000
--- a/db/schema_migrations/20200124143014
+++ /dev/null
@@ -1 +0,0 @@
-184b52cc62b60bb5cb591ab97f308cfe9c18c7a50a56a2cda10e3a368ca25eed \ No newline at end of file
diff --git a/db/schema_migrations/20200127090233 b/db/schema_migrations/20200127090233
deleted file mode 100644
index e40ff846729..00000000000
--- a/db/schema_migrations/20200127090233
+++ /dev/null
@@ -1 +0,0 @@
-551f27aa8b30b0bb567f53b0d64035a9d78bac1d41f2092a97393e17e70c699d \ No newline at end of file
diff --git a/db/schema_migrations/20200127111840 b/db/schema_migrations/20200127111840
deleted file mode 100644
index 089d3e2ed4e..00000000000
--- a/db/schema_migrations/20200127111840
+++ /dev/null
@@ -1 +0,0 @@
-6431cf736beb0ce1143e87b79072984f016588eaf5b84524e6c30d6073912aa2 \ No newline at end of file
diff --git a/db/schema_migrations/20200128105731 b/db/schema_migrations/20200128105731
deleted file mode 100644
index c67dff213e8..00000000000
--- a/db/schema_migrations/20200128105731
+++ /dev/null
@@ -1 +0,0 @@
-5f99d04999b9653ad52c45cdf1466f18a5e77642c39b23ee10ffb8f7c0f67c51 \ No newline at end of file
diff --git a/db/schema_migrations/20200128132510 b/db/schema_migrations/20200128132510
deleted file mode 100644
index 4283d949452..00000000000
--- a/db/schema_migrations/20200128132510
+++ /dev/null
@@ -1 +0,0 @@
-b8a2d0b16a9bd1ea04f1f9aff36d70438fddd01a526421e347b69ddf9536a573 \ No newline at end of file
diff --git a/db/schema_migrations/20200128133510 b/db/schema_migrations/20200128133510
deleted file mode 100644
index 176cb596b5b..00000000000
--- a/db/schema_migrations/20200128133510
+++ /dev/null
@@ -1 +0,0 @@
-a58d4bb491a6f263757a45b3e60a54398cab9af071d1a665b315d920281f5dd4 \ No newline at end of file
diff --git a/db/schema_migrations/20200128134110 b/db/schema_migrations/20200128134110
deleted file mode 100644
index b979354def7..00000000000
--- a/db/schema_migrations/20200128134110
+++ /dev/null
@@ -1 +0,0 @@
-d6d0fda1962dd14759f986c5e9b749af56d95fa145a8092bc96b3c90a1f9437a \ No newline at end of file
diff --git a/db/schema_migrations/20200128141125 b/db/schema_migrations/20200128141125
deleted file mode 100644
index 21edb204f8f..00000000000
--- a/db/schema_migrations/20200128141125
+++ /dev/null
@@ -1 +0,0 @@
-180c07b1fb133fb49793fd32ae7d2754ad3868dcc62628ea4f620592239964cc \ No newline at end of file
diff --git a/db/schema_migrations/20200128184209 b/db/schema_migrations/20200128184209
deleted file mode 100644
index 2fc1db50a49..00000000000
--- a/db/schema_migrations/20200128184209
+++ /dev/null
@@ -1 +0,0 @@
-7acc066caad15b0081e68385f88e4c7df202626b4d105dc80249d60fec042674 \ No newline at end of file
diff --git a/db/schema_migrations/20200128210353 b/db/schema_migrations/20200128210353
deleted file mode 100644
index aadede5c768..00000000000
--- a/db/schema_migrations/20200128210353
+++ /dev/null
@@ -1 +0,0 @@
-03a6e7814edab68dccd70b7311c7a4be35012b22e32a24892202ace2de2c1fc2 \ No newline at end of file
diff --git a/db/schema_migrations/20200129034515 b/db/schema_migrations/20200129034515
deleted file mode 100644
index bc0b6847679..00000000000
--- a/db/schema_migrations/20200129034515
+++ /dev/null
@@ -1 +0,0 @@
-fd61c456af5fe87c8b6f4f914c745ac925542f6ac1720ecbbb4b737b0c6ab269 \ No newline at end of file
diff --git a/db/schema_migrations/20200129035446 b/db/schema_migrations/20200129035446
deleted file mode 100644
index 806b6d57607..00000000000
--- a/db/schema_migrations/20200129035446
+++ /dev/null
@@ -1 +0,0 @@
-752c46974acf90a65b8b06890df69a34323f9ced16f6f66b0cc2e7ffde0ed40d \ No newline at end of file
diff --git a/db/schema_migrations/20200129035708 b/db/schema_migrations/20200129035708
deleted file mode 100644
index 781fef03fae..00000000000
--- a/db/schema_migrations/20200129035708
+++ /dev/null
@@ -1 +0,0 @@
-b20f3a33b73b01a377632ad283d750fbc14981703bf81568394a427343600c5d \ No newline at end of file
diff --git a/db/schema_migrations/20200129133716 b/db/schema_migrations/20200129133716
deleted file mode 100644
index 6496b3adfb1..00000000000
--- a/db/schema_migrations/20200129133716
+++ /dev/null
@@ -1 +0,0 @@
-8e81ca233cbdbde9e3cfe80e98cd696215a0afcfffbf7f7beceddd64e4f3e45c \ No newline at end of file
diff --git a/db/schema_migrations/20200129172428 b/db/schema_migrations/20200129172428
deleted file mode 100644
index e340d839982..00000000000
--- a/db/schema_migrations/20200129172428
+++ /dev/null
@@ -1 +0,0 @@
-b31323a82c1dd1a243b239f3dc7e153c5382414d58e4e5705ec1172daf2ed904 \ No newline at end of file
diff --git a/db/schema_migrations/20200130134335 b/db/schema_migrations/20200130134335
deleted file mode 100644
index c367634e88e..00000000000
--- a/db/schema_migrations/20200130134335
+++ /dev/null
@@ -1 +0,0 @@
-42b0bcb9478b21bfe36b706f522840102ac51b262bcb39c8869d08982df5b9d7 \ No newline at end of file
diff --git a/db/schema_migrations/20200130145430 b/db/schema_migrations/20200130145430
deleted file mode 100644
index 3307a7b4644..00000000000
--- a/db/schema_migrations/20200130145430
+++ /dev/null
@@ -1 +0,0 @@
-fa9812acb3fbd3ac0675a2e4b8b507d03bcd6a6511505f80c8ee0fae96d9e533 \ No newline at end of file
diff --git a/db/schema_migrations/20200130161817 b/db/schema_migrations/20200130161817
deleted file mode 100644
index b675f896375..00000000000
--- a/db/schema_migrations/20200130161817
+++ /dev/null
@@ -1 +0,0 @@
-ff833f3f95571a8efadea98a5b8c5752252289ac6a99de8e13f695a25d2c4706 \ No newline at end of file
diff --git a/db/schema_migrations/20200131140428 b/db/schema_migrations/20200131140428
deleted file mode 100644
index 5874ec0f1ce..00000000000
--- a/db/schema_migrations/20200131140428
+++ /dev/null
@@ -1 +0,0 @@
-0dda3b200923e502f27c3b7107cc2ff1967d906987b4065d5992a9c43f73d46f \ No newline at end of file
diff --git a/db/schema_migrations/20200131181354 b/db/schema_migrations/20200131181354
deleted file mode 100644
index 043c3c99347..00000000000
--- a/db/schema_migrations/20200131181354
+++ /dev/null
@@ -1 +0,0 @@
-d7c68a93d9f4251d0b070d1b351afc9acb122b60e7c1456b23b928d4202c7ff5 \ No newline at end of file
diff --git a/db/schema_migrations/20200131191754 b/db/schema_migrations/20200131191754
deleted file mode 100644
index 12d8189825f..00000000000
--- a/db/schema_migrations/20200131191754
+++ /dev/null
@@ -1 +0,0 @@
-4ca4376f967f2e61f19e42ee61504acb30b53be6a1f8bfe3180a55739dcac73d \ No newline at end of file
diff --git a/db/schema_migrations/20200202100932 b/db/schema_migrations/20200202100932
deleted file mode 100644
index 3a42f098816..00000000000
--- a/db/schema_migrations/20200202100932
+++ /dev/null
@@ -1 +0,0 @@
-5b6bf2e370759e18c2a0558b89b215e00bf9d20b28773a72a5935a649c673bfd \ No newline at end of file
diff --git a/db/schema_migrations/20200203015140 b/db/schema_migrations/20200203015140
deleted file mode 100644
index 36669bd5265..00000000000
--- a/db/schema_migrations/20200203015140
+++ /dev/null
@@ -1 +0,0 @@
-b6e93d2a0e293f4701fe9a228deb1926cff595ae50860f783417ac834dcfef4f \ No newline at end of file
diff --git a/db/schema_migrations/20200203025400 b/db/schema_migrations/20200203025400
deleted file mode 100644
index 7f0bcc12d5f..00000000000
--- a/db/schema_migrations/20200203025400
+++ /dev/null
@@ -1 +0,0 @@
-e88f8eb40e5a16da89ba555c26aa886ac0653115dd1333ce1def6ad648cf7f03 \ No newline at end of file
diff --git a/db/schema_migrations/20200203025602 b/db/schema_migrations/20200203025602
deleted file mode 100644
index 8ae10e3e6a8..00000000000
--- a/db/schema_migrations/20200203025602
+++ /dev/null
@@ -1 +0,0 @@
-3867f94f138297bd3219fbc7e52aa5448d24ff9447664869e836d0097cae4b4c \ No newline at end of file
diff --git a/db/schema_migrations/20200203025619 b/db/schema_migrations/20200203025619
deleted file mode 100644
index f5937cf8f3a..00000000000
--- a/db/schema_migrations/20200203025619
+++ /dev/null
@@ -1 +0,0 @@
-202883912d9728bcbad2a63af9935c116833e51c0f8dec198f76c635f76409fa \ No newline at end of file
diff --git a/db/schema_migrations/20200203025744 b/db/schema_migrations/20200203025744
deleted file mode 100644
index 9711a318f91..00000000000
--- a/db/schema_migrations/20200203025744
+++ /dev/null
@@ -1 +0,0 @@
-a20b4d064d76718dc97014b62e751dad983db2730b552a39bd2f5255f50d6a72 \ No newline at end of file
diff --git a/db/schema_migrations/20200203025801 b/db/schema_migrations/20200203025801
deleted file mode 100644
index a892f83100c..00000000000
--- a/db/schema_migrations/20200203025801
+++ /dev/null
@@ -1 +0,0 @@
-906db40d8d7d2f645b42b1a23b2ecbb67efc5bb80d2ff06a7ab17097e9a002e1 \ No newline at end of file
diff --git a/db/schema_migrations/20200203025821 b/db/schema_migrations/20200203025821
deleted file mode 100644
index f1bc002ea10..00000000000
--- a/db/schema_migrations/20200203025821
+++ /dev/null
@@ -1 +0,0 @@
-fe4238c19b0cd8abf83198477fa6d74cca873b111bd3d5e63e13a511aed29022 \ No newline at end of file
diff --git a/db/schema_migrations/20200203104214 b/db/schema_migrations/20200203104214
deleted file mode 100644
index 57996942284..00000000000
--- a/db/schema_migrations/20200203104214
+++ /dev/null
@@ -1 +0,0 @@
-f72dce36394a51516dd9306b1626cde4151317ef891d2d00fd6668e33c734bcd \ No newline at end of file
diff --git a/db/schema_migrations/20200203173508 b/db/schema_migrations/20200203173508
deleted file mode 100644
index 8d9157c61f0..00000000000
--- a/db/schema_migrations/20200203173508
+++ /dev/null
@@ -1 +0,0 @@
-e0a7a10f8e2d21b859b67f51926d8404c650db1642800738938509653f680fd9 \ No newline at end of file
diff --git a/db/schema_migrations/20200203183508 b/db/schema_migrations/20200203183508
deleted file mode 100644
index 63ef7355c99..00000000000
--- a/db/schema_migrations/20200203183508
+++ /dev/null
@@ -1 +0,0 @@
-87cfeb92aa7257a249c3a0504d72a372f8da17671da68373efda75e8d9153be4 \ No newline at end of file
diff --git a/db/schema_migrations/20200203232433 b/db/schema_migrations/20200203232433
deleted file mode 100644
index 2ad3579da47..00000000000
--- a/db/schema_migrations/20200203232433
+++ /dev/null
@@ -1 +0,0 @@
-6a23d6bd7573f193189d224283920da13dde870f432bf4e2d72f256162a87aa4 \ No newline at end of file
diff --git a/db/schema_migrations/20200204070729 b/db/schema_migrations/20200204070729
deleted file mode 100644
index c2e1cc805f7..00000000000
--- a/db/schema_migrations/20200204070729
+++ /dev/null
@@ -1 +0,0 @@
-df733328a6bb6b430d510757104e767ba9a37b6f6ee8b6d1423a4b1579f7a342 \ No newline at end of file
diff --git a/db/schema_migrations/20200204113223 b/db/schema_migrations/20200204113223
deleted file mode 100644
index 4447990a16b..00000000000
--- a/db/schema_migrations/20200204113223
+++ /dev/null
@@ -1 +0,0 @@
-301ec018abcab2311852c952f925460dad9c374ca3df146cbddfcc17821c0d85 \ No newline at end of file
diff --git a/db/schema_migrations/20200204113224 b/db/schema_migrations/20200204113224
deleted file mode 100644
index ce45309a877..00000000000
--- a/db/schema_migrations/20200204113224
+++ /dev/null
@@ -1 +0,0 @@
-4fc5ffc3ce0519a9a79559644f0453439582577fbfffb434c7b0f33c5942aa36 \ No newline at end of file
diff --git a/db/schema_migrations/20200204113225 b/db/schema_migrations/20200204113225
deleted file mode 100644
index 44b779d5f86..00000000000
--- a/db/schema_migrations/20200204113225
+++ /dev/null
@@ -1 +0,0 @@
-13e39ebe5de6076f1702fa92421d9906984587a8acd92d210b96fc14060c555d \ No newline at end of file
diff --git a/db/schema_migrations/20200204131054 b/db/schema_migrations/20200204131054
deleted file mode 100644
index 98dd8225bd8..00000000000
--- a/db/schema_migrations/20200204131054
+++ /dev/null
@@ -1 +0,0 @@
-5eddc68cf19810dd065a687e90e5e487fde581d907490756fc297862e2a56dc3 \ No newline at end of file
diff --git a/db/schema_migrations/20200204131831 b/db/schema_migrations/20200204131831
deleted file mode 100644
index ca41129f6d9..00000000000
--- a/db/schema_migrations/20200204131831
+++ /dev/null
@@ -1 +0,0 @@
-6b0162763fae1fa73ed940928e889637e52dd918af2c3fe4d338b958c1ccbb03 \ No newline at end of file
diff --git a/db/schema_migrations/20200205143231 b/db/schema_migrations/20200205143231
deleted file mode 100644
index 3e7ff885264..00000000000
--- a/db/schema_migrations/20200205143231
+++ /dev/null
@@ -1 +0,0 @@
-c982bf7b26305e060ef268cc5a963f761a3feadbae71ac008a7b3a76a59e71ca \ No newline at end of file
diff --git a/db/schema_migrations/20200206091544 b/db/schema_migrations/20200206091544
deleted file mode 100644
index 55660a6ae53..00000000000
--- a/db/schema_migrations/20200206091544
+++ /dev/null
@@ -1 +0,0 @@
-bce288b2da2165a690e20a1c6ad02bf652ed5bb4b9b249b90ca77aef5ad8006b \ No newline at end of file
diff --git a/db/schema_migrations/20200206112850 b/db/schema_migrations/20200206112850
deleted file mode 100644
index 85d21501d86..00000000000
--- a/db/schema_migrations/20200206112850
+++ /dev/null
@@ -1 +0,0 @@
-05f0fd8358bc134c358365b6fd054e29d9d2aaf4607e6f6e8f0e464cc99b0789 \ No newline at end of file
diff --git a/db/schema_migrations/20200206135203 b/db/schema_migrations/20200206135203
deleted file mode 100644
index 63969a76fb8..00000000000
--- a/db/schema_migrations/20200206135203
+++ /dev/null
@@ -1 +0,0 @@
-3637bebdf55d4210796153fafb481295f2f571552ea941fd02b5c34e753992ad \ No newline at end of file
diff --git a/db/schema_migrations/20200206141511 b/db/schema_migrations/20200206141511
deleted file mode 100644
index 4b7ade65253..00000000000
--- a/db/schema_migrations/20200206141511
+++ /dev/null
@@ -1 +0,0 @@
-49493da849aaa283ad04d44146befabdc917db759eba6e8a9192823655a27321 \ No newline at end of file
diff --git a/db/schema_migrations/20200207062728 b/db/schema_migrations/20200207062728
deleted file mode 100644
index e89908e233b..00000000000
--- a/db/schema_migrations/20200207062728
+++ /dev/null
@@ -1 +0,0 @@
-3dfd44b1ca862a568577b5f5d81727ccdc21e818c55741c60763324084206aff \ No newline at end of file
diff --git a/db/schema_migrations/20200207090921 b/db/schema_migrations/20200207090921
deleted file mode 100644
index fe8b0073109..00000000000
--- a/db/schema_migrations/20200207090921
+++ /dev/null
@@ -1 +0,0 @@
-86d3faf27e816d5f9ef4b7125baa2d24cd8bc0987cdc796fea34e84f7ad15213 \ No newline at end of file
diff --git a/db/schema_migrations/20200207132752 b/db/schema_migrations/20200207132752
deleted file mode 100644
index 5c4d98baf7a..00000000000
--- a/db/schema_migrations/20200207132752
+++ /dev/null
@@ -1 +0,0 @@
-c3b9788fcd9e434a061ed82f481781eb9960829ff6e2174637b17f857f747163 \ No newline at end of file
diff --git a/db/schema_migrations/20200207151640 b/db/schema_migrations/20200207151640
deleted file mode 100644
index 202427114f0..00000000000
--- a/db/schema_migrations/20200207151640
+++ /dev/null
@@ -1 +0,0 @@
-c40ba483437d4cfcff73488d272efc9010922bf58f05790dcab99681653dcec7 \ No newline at end of file
diff --git a/db/schema_migrations/20200207182131 b/db/schema_migrations/20200207182131
deleted file mode 100644
index d57e44c992b..00000000000
--- a/db/schema_migrations/20200207182131
+++ /dev/null
@@ -1 +0,0 @@
-ec80914c6c7ffcede1cba96e99dcb650d497f8f75ac786e449da83cae72284f1 \ No newline at end of file
diff --git a/db/schema_migrations/20200207184023 b/db/schema_migrations/20200207184023
deleted file mode 100644
index 99c06c639b4..00000000000
--- a/db/schema_migrations/20200207184023
+++ /dev/null
@@ -1 +0,0 @@
-de7546a714536c45d64ebc81d6a32e5159baed049b3b0d84c5d0e6f175098f8f \ No newline at end of file
diff --git a/db/schema_migrations/20200207185149 b/db/schema_migrations/20200207185149
deleted file mode 100644
index 8fd081c423b..00000000000
--- a/db/schema_migrations/20200207185149
+++ /dev/null
@@ -1 +0,0 @@
-6f89d4a9bebbfe12efab87caf4715577e33ff3f72c6adb5e847c9a946231eba2 \ No newline at end of file
diff --git a/db/schema_migrations/20200209131152 b/db/schema_migrations/20200209131152
deleted file mode 100644
index 26243203758..00000000000
--- a/db/schema_migrations/20200209131152
+++ /dev/null
@@ -1 +0,0 @@
-cc86dc6e5a4dc194da858e900720be169f0491d8bdf43e3be2c239d835db81a9 \ No newline at end of file
diff --git a/db/schema_migrations/20200210062432 b/db/schema_migrations/20200210062432
deleted file mode 100644
index ed644130bbf..00000000000
--- a/db/schema_migrations/20200210062432
+++ /dev/null
@@ -1 +0,0 @@
-42b2970731451f93f6a704634e91e236fd0303781cd55848d6ea7d8d28993ba6 \ No newline at end of file
diff --git a/db/schema_migrations/20200210092405 b/db/schema_migrations/20200210092405
deleted file mode 100644
index f984f9692db..00000000000
--- a/db/schema_migrations/20200210092405
+++ /dev/null
@@ -1 +0,0 @@
-034b1ef6728823ce13e68223e447713145e2c5ccedcdaee0294cc33a4ea0f345 \ No newline at end of file
diff --git a/db/schema_migrations/20200210135504 b/db/schema_migrations/20200210135504
deleted file mode 100644
index 25c336ea54e..00000000000
--- a/db/schema_migrations/20200210135504
+++ /dev/null
@@ -1 +0,0 @@
-bc188c6727b80851c0d051162ec08c142863854a4aea020f79f986c94425a4f7 \ No newline at end of file
diff --git a/db/schema_migrations/20200210184410 b/db/schema_migrations/20200210184410
deleted file mode 100644
index 51584a0e3f0..00000000000
--- a/db/schema_migrations/20200210184410
+++ /dev/null
@@ -1 +0,0 @@
-6dda1a048429cd241b2556446c3d6b05ac175f16fb024542af30e6047a3638b8 \ No newline at end of file
diff --git a/db/schema_migrations/20200210184420 b/db/schema_migrations/20200210184420
deleted file mode 100644
index 5e527eee87d..00000000000
--- a/db/schema_migrations/20200210184420
+++ /dev/null
@@ -1 +0,0 @@
-9b14148bd5c9137f1b90bfd256f31b2ea292d64e407e1de851fd139af7669db5 \ No newline at end of file
diff --git a/db/schema_migrations/20200211152410 b/db/schema_migrations/20200211152410
deleted file mode 100644
index fb54ddf486c..00000000000
--- a/db/schema_migrations/20200211152410
+++ /dev/null
@@ -1 +0,0 @@
-41958f432ea338232ec656daf78211207d08aa322005aed41d5da48d35b1c9da \ No newline at end of file
diff --git a/db/schema_migrations/20200211155000 b/db/schema_migrations/20200211155000
deleted file mode 100644
index 7a7264ec94b..00000000000
--- a/db/schema_migrations/20200211155000
+++ /dev/null
@@ -1 +0,0 @@
-02f03e83a36adc41dc830ba58346c57195cca016dccd1c1301ac1d8614c68d08 \ No newline at end of file
diff --git a/db/schema_migrations/20200211155100 b/db/schema_migrations/20200211155100
deleted file mode 100644
index a9a12f034a4..00000000000
--- a/db/schema_migrations/20200211155100
+++ /dev/null
@@ -1 +0,0 @@
-669b32d2fe15eeb319efb3a9274cb9b1bc70e3cf6008d3d8df73cdcec657d7cc \ No newline at end of file
diff --git a/db/schema_migrations/20200211155539 b/db/schema_migrations/20200211155539
deleted file mode 100644
index aa9fa6d2ea5..00000000000
--- a/db/schema_migrations/20200211155539
+++ /dev/null
@@ -1 +0,0 @@
-e0ed779651b1a271d4e71836275922e01c37fba895466390ebc30ec27b67b1e6 \ No newline at end of file
diff --git a/db/schema_migrations/20200211174946 b/db/schema_migrations/20200211174946
deleted file mode 100644
index 8bc4d6c52fa..00000000000
--- a/db/schema_migrations/20200211174946
+++ /dev/null
@@ -1 +0,0 @@
-8766a3d8973df6c402059abd7b63dfd52a8e2f49999bb8bb1b5595efa1c13844 \ No newline at end of file
diff --git a/db/schema_migrations/20200212014653 b/db/schema_migrations/20200212014653
deleted file mode 100644
index 5c09818b0c9..00000000000
--- a/db/schema_migrations/20200212014653
+++ /dev/null
@@ -1 +0,0 @@
-145e354e2c5249c75748f91d95d8f174f9b9d20a59dcb1f70d0cfaab6d082c28 \ No newline at end of file
diff --git a/db/schema_migrations/20200212052620 b/db/schema_migrations/20200212052620
deleted file mode 100644
index 4a0adc09483..00000000000
--- a/db/schema_migrations/20200212052620
+++ /dev/null
@@ -1 +0,0 @@
-355923f56df66ac6d4b24c47b9fad214553b783e3d5b45d76128c8872e1ada93 \ No newline at end of file
diff --git a/db/schema_migrations/20200212133945 b/db/schema_migrations/20200212133945
deleted file mode 100644
index d812ae5161a..00000000000
--- a/db/schema_migrations/20200212133945
+++ /dev/null
@@ -1 +0,0 @@
-cd0206f5a636002299b526b13bfcc3a684f74826a7963151c50e35902ba63dc4 \ No newline at end of file
diff --git a/db/schema_migrations/20200212134201 b/db/schema_migrations/20200212134201
deleted file mode 100644
index 5fa3a35de15..00000000000
--- a/db/schema_migrations/20200212134201
+++ /dev/null
@@ -1 +0,0 @@
-b757fdcd5e6afafa966911506d687d78e16e6d51a0a23c96821935e28661d89f \ No newline at end of file
diff --git a/db/schema_migrations/20200213093702 b/db/schema_migrations/20200213093702
deleted file mode 100644
index f41a455a24a..00000000000
--- a/db/schema_migrations/20200213093702
+++ /dev/null
@@ -1 +0,0 @@
-d0fb4e573879340191432e9e653b6326aaf69b53c7f5fe3c18c5cee9d795d169 \ No newline at end of file
diff --git a/db/schema_migrations/20200213100530 b/db/schema_migrations/20200213100530
deleted file mode 100644
index aaa91ba9906..00000000000
--- a/db/schema_migrations/20200213100530
+++ /dev/null
@@ -1 +0,0 @@
-f96d42370627657876a3b2fa30ce40b0988a78132ed97a733e76429023967c31 \ No newline at end of file
diff --git a/db/schema_migrations/20200213155311 b/db/schema_migrations/20200213155311
deleted file mode 100644
index 724b411345e..00000000000
--- a/db/schema_migrations/20200213155311
+++ /dev/null
@@ -1 +0,0 @@
-a2905bcfdda4f5c43cb797653fe06f93e6bdaa28e77d204c64f3299daa58a276 \ No newline at end of file
diff --git a/db/schema_migrations/20200213204737 b/db/schema_migrations/20200213204737
deleted file mode 100644
index 649f9927f7c..00000000000
--- a/db/schema_migrations/20200213204737
+++ /dev/null
@@ -1 +0,0 @@
-2bdaa84098768e63eabbcb282339946404f04a0bcee6df0fb9c55a92bed7ac96 \ No newline at end of file
diff --git a/db/schema_migrations/20200213220159 b/db/schema_migrations/20200213220159
deleted file mode 100644
index 3be052e646d..00000000000
--- a/db/schema_migrations/20200213220159
+++ /dev/null
@@ -1 +0,0 @@
-4cc3d7904c7d8cb8437fa3f0638d250653f9f9d4ba4a749213995565b4d2b453 \ No newline at end of file
diff --git a/db/schema_migrations/20200213220211 b/db/schema_migrations/20200213220211
deleted file mode 100644
index 4083c2dbc86..00000000000
--- a/db/schema_migrations/20200213220211
+++ /dev/null
@@ -1 +0,0 @@
-c9a8e253caf9866b989f91344e51552ace7bcc11a79f8e8532df6c437938003c \ No newline at end of file
diff --git a/db/schema_migrations/20200213224220 b/db/schema_migrations/20200213224220
deleted file mode 100644
index bb2bfec2832..00000000000
--- a/db/schema_migrations/20200213224220
+++ /dev/null
@@ -1 +0,0 @@
-05d38262b89290923aec19056eba00a8033801035584078b114be942602829fd \ No newline at end of file
diff --git a/db/schema_migrations/20200214025454 b/db/schema_migrations/20200214025454
deleted file mode 100644
index dd316902059..00000000000
--- a/db/schema_migrations/20200214025454
+++ /dev/null
@@ -1 +0,0 @@
-9d6f4df037418ec3d15fbf4b478d8436086a14db4cd99fb274821b0d507016da \ No newline at end of file
diff --git a/db/schema_migrations/20200214034836 b/db/schema_migrations/20200214034836
deleted file mode 100644
index ae1fd50853c..00000000000
--- a/db/schema_migrations/20200214034836
+++ /dev/null
@@ -1 +0,0 @@
-9fc56490b8122fe535405b88cd066b955ab8ec26fc9ed930217d8b544ff94924 \ No newline at end of file
diff --git a/db/schema_migrations/20200214085940 b/db/schema_migrations/20200214085940
deleted file mode 100644
index 10c55e8f6f8..00000000000
--- a/db/schema_migrations/20200214085940
+++ /dev/null
@@ -1 +0,0 @@
-785efb7b3966d2eedac586ef9fb76958f4e8569fa26460a9fa1f56c0adffb018 \ No newline at end of file
diff --git a/db/schema_migrations/20200214214934 b/db/schema_migrations/20200214214934
deleted file mode 100644
index d0558255902..00000000000
--- a/db/schema_migrations/20200214214934
+++ /dev/null
@@ -1 +0,0 @@
-08d552ba41c948f9b86d808ab3dfcd3f6d87932bf2a7e8b553931772d538644e \ No newline at end of file
diff --git a/db/schema_migrations/20200215222507 b/db/schema_migrations/20200215222507
deleted file mode 100644
index 9679ada2092..00000000000
--- a/db/schema_migrations/20200215222507
+++ /dev/null
@@ -1 +0,0 @@
-d8e12f44580369a24e4ad521f91038ada113f0c404c5d834a88a2f992cb56fe3 \ No newline at end of file
diff --git a/db/schema_migrations/20200215225103 b/db/schema_migrations/20200215225103
deleted file mode 100644
index 4a10c2d220f..00000000000
--- a/db/schema_migrations/20200215225103
+++ /dev/null
@@ -1 +0,0 @@
-a59ad729a2ec17dde6a663903f0a5154b0cd79fa6dd915e637804c40fc75d27e \ No newline at end of file
diff --git a/db/schema_migrations/20200217210353 b/db/schema_migrations/20200217210353
deleted file mode 100644
index 6209436dd98..00000000000
--- a/db/schema_migrations/20200217210353
+++ /dev/null
@@ -1 +0,0 @@
-1da054d1cc3544e37dbabd61475ac8e7944fa7542fb830d2bb317c1a8e49308e \ No newline at end of file
diff --git a/db/schema_migrations/20200217223651 b/db/schema_migrations/20200217223651
deleted file mode 100644
index c25e0437e2e..00000000000
--- a/db/schema_migrations/20200217223651
+++ /dev/null
@@ -1 +0,0 @@
-c1040531e0993eebc432ecbca4bb44ae81e922689950d437ca0ba671cabaa6da \ No newline at end of file
diff --git a/db/schema_migrations/20200217225719 b/db/schema_migrations/20200217225719
deleted file mode 100644
index fe948d685ac..00000000000
--- a/db/schema_migrations/20200217225719
+++ /dev/null
@@ -1 +0,0 @@
-effe679c2902af4598100760834a1a186a9f9bf4ba9c2bf1b578aa709973c3eb \ No newline at end of file
diff --git a/db/schema_migrations/20200218113721 b/db/schema_migrations/20200218113721
deleted file mode 100644
index 92f27184f71..00000000000
--- a/db/schema_migrations/20200218113721
+++ /dev/null
@@ -1 +0,0 @@
-ebc9e7ab299805e98960828d15129b86364d7553a9479924a2535927f9d04ad0 \ No newline at end of file
diff --git a/db/schema_migrations/20200219105209 b/db/schema_migrations/20200219105209
deleted file mode 100644
index 6339ba9c491..00000000000
--- a/db/schema_migrations/20200219105209
+++ /dev/null
@@ -1 +0,0 @@
-043df0eb40876ff8e211a21fd7044d0e64d22df6a69fb666cbac0b73767dea1e \ No newline at end of file
diff --git a/db/schema_migrations/20200219133859 b/db/schema_migrations/20200219133859
deleted file mode 100644
index 8e8d60c771d..00000000000
--- a/db/schema_migrations/20200219133859
+++ /dev/null
@@ -1 +0,0 @@
-7a98e68a00bc69823ead39868d76b8c1d81cfe491a98481c711effe488ed8544 \ No newline at end of file
diff --git a/db/schema_migrations/20200219135440 b/db/schema_migrations/20200219135440
deleted file mode 100644
index 70e7c5a2dd9..00000000000
--- a/db/schema_migrations/20200219135440
+++ /dev/null
@@ -1 +0,0 @@
-b6aab8e12c460e97d8c84128ad7186286c0a5d6bb94b55e86d5c112296d63e3a \ No newline at end of file
diff --git a/db/schema_migrations/20200219141307 b/db/schema_migrations/20200219141307
deleted file mode 100644
index 9e9fca81c8b..00000000000
--- a/db/schema_migrations/20200219141307
+++ /dev/null
@@ -1 +0,0 @@
-e3a9c39f4d09885b5ddac27da42272e3bc8cab408871c4af0013759b39a1fc47 \ No newline at end of file
diff --git a/db/schema_migrations/20200219142522 b/db/schema_migrations/20200219142522
deleted file mode 100644
index 6b9d9dbf295..00000000000
--- a/db/schema_migrations/20200219142522
+++ /dev/null
@@ -1 +0,0 @@
-5e8ae04a1a398cb0d68c8a2e2eba55132a24049fc382876e657755993c322637 \ No newline at end of file
diff --git a/db/schema_migrations/20200219183456 b/db/schema_migrations/20200219183456
deleted file mode 100644
index 085e82e2466..00000000000
--- a/db/schema_migrations/20200219183456
+++ /dev/null
@@ -1 +0,0 @@
-bcb00dc5e3c6a5b929fa5a09b84a852daeacce3ab349ad3f225aaac7a8877495 \ No newline at end of file
diff --git a/db/schema_migrations/20200219184219 b/db/schema_migrations/20200219184219
deleted file mode 100644
index 42a74bfaae7..00000000000
--- a/db/schema_migrations/20200219184219
+++ /dev/null
@@ -1 +0,0 @@
-909be57df344b07c93404eb2b699f1d269c788bb05021fc89fb06f97a3bef2b3 \ No newline at end of file
diff --git a/db/schema_migrations/20200219193058 b/db/schema_migrations/20200219193058
deleted file mode 100644
index 7ffa3ee314c..00000000000
--- a/db/schema_migrations/20200219193058
+++ /dev/null
@@ -1 +0,0 @@
-8deaeff4e509d62c937be3facd3110ea3cb667df57ae07662b24d81678852fb5 \ No newline at end of file
diff --git a/db/schema_migrations/20200219193117 b/db/schema_migrations/20200219193117
deleted file mode 100644
index d0dafc2a08d..00000000000
--- a/db/schema_migrations/20200219193117
+++ /dev/null
@@ -1 +0,0 @@
-c09ada7750dbd41af67c76c85172e044600ea46011ba74c9e25ea4c818809494 \ No newline at end of file
diff --git a/db/schema_migrations/20200220115023 b/db/schema_migrations/20200220115023
deleted file mode 100644
index b9078b285e5..00000000000
--- a/db/schema_migrations/20200220115023
+++ /dev/null
@@ -1 +0,0 @@
-77d4e8365959a86ea77858273c89c2c0b8c788d2e89659213944edd3d5273813 \ No newline at end of file
diff --git a/db/schema_migrations/20200220180944 b/db/schema_migrations/20200220180944
deleted file mode 100644
index 7dcadb16447..00000000000
--- a/db/schema_migrations/20200220180944
+++ /dev/null
@@ -1 +0,0 @@
-5a2684c95dc33d601403cc775afe52071c55026aaa8744faefde0c15cc1b14fd \ No newline at end of file
diff --git a/db/schema_migrations/20200221023320 b/db/schema_migrations/20200221023320
deleted file mode 100644
index c66a766f493..00000000000
--- a/db/schema_migrations/20200221023320
+++ /dev/null
@@ -1 +0,0 @@
-445c20a2bd9f1fef7f36fb8d3b046aef2fa42b52afada34b69e13d3c24359dd1 \ No newline at end of file
diff --git a/db/schema_migrations/20200221074028 b/db/schema_migrations/20200221074028
deleted file mode 100644
index 444e71a7cac..00000000000
--- a/db/schema_migrations/20200221074028
+++ /dev/null
@@ -1 +0,0 @@
-a4de683b8d61efdf99fdd5f7861619ce17f57b80c56b5a9f8f8cfc81c884882e \ No newline at end of file
diff --git a/db/schema_migrations/20200221100514 b/db/schema_migrations/20200221100514
deleted file mode 100644
index bd6047ddd88..00000000000
--- a/db/schema_migrations/20200221100514
+++ /dev/null
@@ -1 +0,0 @@
-38e915b6d638314cafd6cb02bcf9b8d6a9c41ea2b3ddec55009f06bd30d39884 \ No newline at end of file
diff --git a/db/schema_migrations/20200221105436 b/db/schema_migrations/20200221105436
deleted file mode 100644
index ee97ca1350f..00000000000
--- a/db/schema_migrations/20200221105436
+++ /dev/null
@@ -1 +0,0 @@
-96c2536ce554abbd9080b64eeb5b540c040f812edd5e6dbeb463bded9940b772 \ No newline at end of file
diff --git a/db/schema_migrations/20200221142216 b/db/schema_migrations/20200221142216
deleted file mode 100644
index 6c7a9f712b1..00000000000
--- a/db/schema_migrations/20200221142216
+++ /dev/null
@@ -1 +0,0 @@
-142a4c2c00757bba97fddd8f4bafd00ab7f5861339d25600ad01daddd2e288b5 \ No newline at end of file
diff --git a/db/schema_migrations/20200221144534 b/db/schema_migrations/20200221144534
deleted file mode 100644
index 67b6b33231b..00000000000
--- a/db/schema_migrations/20200221144534
+++ /dev/null
@@ -1 +0,0 @@
-146c882020bb3b75e34a58e16ed456f166a9da61c1fd8b06945336eb0536fce2 \ No newline at end of file
diff --git a/db/schema_migrations/20200222055543 b/db/schema_migrations/20200222055543
deleted file mode 100644
index 6a93c7d04a8..00000000000
--- a/db/schema_migrations/20200222055543
+++ /dev/null
@@ -1 +0,0 @@
-2b3171889c440e68d912ed2809164f39f98992ae2a39874453fcaff56ea6e33c \ No newline at end of file
diff --git a/db/schema_migrations/20200224020219 b/db/schema_migrations/20200224020219
deleted file mode 100644
index c9c528c6ef5..00000000000
--- a/db/schema_migrations/20200224020219
+++ /dev/null
@@ -1 +0,0 @@
-c691d9da73b528a116d4c7a046ff00e6e66dfa9dcecc95fe2509806b78872bef \ No newline at end of file
diff --git a/db/schema_migrations/20200224163804 b/db/schema_migrations/20200224163804
deleted file mode 100644
index f3324434357..00000000000
--- a/db/schema_migrations/20200224163804
+++ /dev/null
@@ -1 +0,0 @@
-9d424b6fa0c80ea93d95ea2c4b40e5c96e4537e0da934aaa11f377c615afb813 \ No newline at end of file
diff --git a/db/schema_migrations/20200224185814 b/db/schema_migrations/20200224185814
deleted file mode 100644
index 5dd2b5914d0..00000000000
--- a/db/schema_migrations/20200224185814
+++ /dev/null
@@ -1 +0,0 @@
-e77d002b5ff690159e3433c9716211184bda2946d55d78001fac985e12fc368a \ No newline at end of file
diff --git a/db/schema_migrations/20200225111018 b/db/schema_migrations/20200225111018
deleted file mode 100644
index 6eec0048c59..00000000000
--- a/db/schema_migrations/20200225111018
+++ /dev/null
@@ -1 +0,0 @@
-5db0994461870588d29b5c4b790d3a95b52fbfcac59798d3c892d397a4c409ec \ No newline at end of file
diff --git a/db/schema_migrations/20200225123228 b/db/schema_migrations/20200225123228
deleted file mode 100644
index 019085f9188..00000000000
--- a/db/schema_migrations/20200225123228
+++ /dev/null
@@ -1 +0,0 @@
-10778414197502a02cbe57830c74287e5632f535322f9b5c5c950c451cb01d71 \ No newline at end of file
diff --git a/db/schema_migrations/20200226100614 b/db/schema_migrations/20200226100614
deleted file mode 100644
index e7659a7253f..00000000000
--- a/db/schema_migrations/20200226100614
+++ /dev/null
@@ -1 +0,0 @@
-c188525e1ac6e4da59b625bf7d91deff1b1812c918c44e5b73eb2bc2e0823f68 \ No newline at end of file
diff --git a/db/schema_migrations/20200226100624 b/db/schema_migrations/20200226100624
deleted file mode 100644
index 8e056e090c9..00000000000
--- a/db/schema_migrations/20200226100624
+++ /dev/null
@@ -1 +0,0 @@
-829f7961954cb6bf41c30dc347033f3db7e6e39038e95c217b7ef9717c3a35eb \ No newline at end of file
diff --git a/db/schema_migrations/20200226100634 b/db/schema_migrations/20200226100634
deleted file mode 100644
index 5e8dee9d149..00000000000
--- a/db/schema_migrations/20200226100634
+++ /dev/null
@@ -1 +0,0 @@
-af0febe1b18421cd8043731157ff9a2823b57cd60b7433ff67d724f210f9971a \ No newline at end of file
diff --git a/db/schema_migrations/20200226124757 b/db/schema_migrations/20200226124757
deleted file mode 100644
index 960eb9df3c0..00000000000
--- a/db/schema_migrations/20200226124757
+++ /dev/null
@@ -1 +0,0 @@
-f73014dcbedc2aebf4da6358d7169d471e0e27fb6644786fe1c0b0403019b900 \ No newline at end of file
diff --git a/db/schema_migrations/20200226162156 b/db/schema_migrations/20200226162156
deleted file mode 100644
index 364b67da3ee..00000000000
--- a/db/schema_migrations/20200226162156
+++ /dev/null
@@ -1 +0,0 @@
-4696b79c9363893fc86300c3214c72dd13d0ab2aeef2ccbc878243c1549e0da5 \ No newline at end of file
diff --git a/db/schema_migrations/20200226162239 b/db/schema_migrations/20200226162239
deleted file mode 100644
index b68bfbbc72a..00000000000
--- a/db/schema_migrations/20200226162239
+++ /dev/null
@@ -1 +0,0 @@
-35c9e2a9eaf7d718d349551f42ac6831db7e53906ba6fcb63bd81ae862a26e30 \ No newline at end of file
diff --git a/db/schema_migrations/20200226162634 b/db/schema_migrations/20200226162634
deleted file mode 100644
index 50ff6751b9a..00000000000
--- a/db/schema_migrations/20200226162634
+++ /dev/null
@@ -1 +0,0 @@
-bd75dacfe0bdfc52579fd82612168968d64e162189aa9aeca9f190d46bc75f65 \ No newline at end of file
diff --git a/db/schema_migrations/20200226162723 b/db/schema_migrations/20200226162723
deleted file mode 100644
index 9da5b508de3..00000000000
--- a/db/schema_migrations/20200226162723
+++ /dev/null
@@ -1 +0,0 @@
-bf3bf81b45ead0a9b9ec66631f1d3dfe351b9e4fccd116bde4d2844181e8aced \ No newline at end of file
diff --git a/db/schema_migrations/20200227140242 b/db/schema_migrations/20200227140242
deleted file mode 100644
index 9d0f534d7f6..00000000000
--- a/db/schema_migrations/20200227140242
+++ /dev/null
@@ -1 +0,0 @@
-6d798d258d1760c64c51b754c0fbf24f387470db7f6f11825d1e5467333086a7 \ No newline at end of file
diff --git a/db/schema_migrations/20200227164113 b/db/schema_migrations/20200227164113
deleted file mode 100644
index 4af123a14fe..00000000000
--- a/db/schema_migrations/20200227164113
+++ /dev/null
@@ -1 +0,0 @@
-2c29f99e94603aec1826717d1a36321d5c19da96acda4c58f74c6669c77e5615 \ No newline at end of file
diff --git a/db/schema_migrations/20200227165129 b/db/schema_migrations/20200227165129
deleted file mode 100644
index 0407c71200f..00000000000
--- a/db/schema_migrations/20200227165129
+++ /dev/null
@@ -1 +0,0 @@
-ad6c0fd0314342c442b1d712758f9cdb9e2067d9db8108ab2d48d29f2a2c816f \ No newline at end of file
diff --git a/db/schema_migrations/20200228160542 b/db/schema_migrations/20200228160542
deleted file mode 100644
index dafd6c44929..00000000000
--- a/db/schema_migrations/20200228160542
+++ /dev/null
@@ -1 +0,0 @@
-df1d9de8bcb29fbb9dd1ae4f6d7016d9e543e3100ea0d832156700df311df345 \ No newline at end of file
diff --git a/db/schema_migrations/20200229171700 b/db/schema_migrations/20200229171700
deleted file mode 100644
index 2c6ad5f1194..00000000000
--- a/db/schema_migrations/20200229171700
+++ /dev/null
@@ -1 +0,0 @@
-edd4919ede4a4d3b81afd1eb5158ba0715eed60f589552e00d0b0c10203eef93 \ No newline at end of file
diff --git a/db/schema_migrations/20200302142052 b/db/schema_migrations/20200302142052
deleted file mode 100644
index 5485ff3b1b3..00000000000
--- a/db/schema_migrations/20200302142052
+++ /dev/null
@@ -1 +0,0 @@
-2a5668a6d45c193d51d0f946384a42a2fb56c9f1f778e95421b9b5bb48766094 \ No newline at end of file
diff --git a/db/schema_migrations/20200302152516 b/db/schema_migrations/20200302152516
deleted file mode 100644
index b53a44c6fb7..00000000000
--- a/db/schema_migrations/20200302152516
+++ /dev/null
@@ -1 +0,0 @@
-e336cdba6c665475254935455fc1f2ca4a8e04675f5aeab1a305e113ae698823 \ No newline at end of file
diff --git a/db/schema_migrations/20200303055348 b/db/schema_migrations/20200303055348
deleted file mode 100644
index 5810297e066..00000000000
--- a/db/schema_migrations/20200303055348
+++ /dev/null
@@ -1 +0,0 @@
-e5897eb553a9c90742b910a7c892e6b97b08e059d3ee3fe7a089ad2b4b5bd1de \ No newline at end of file
diff --git a/db/schema_migrations/20200303074328 b/db/schema_migrations/20200303074328
deleted file mode 100644
index 9b75422c78d..00000000000
--- a/db/schema_migrations/20200303074328
+++ /dev/null
@@ -1 +0,0 @@
-4c577c630f6cba9440437c41628fa86297a9feae910e313a7da601cbbd363ea9 \ No newline at end of file
diff --git a/db/schema_migrations/20200303181648 b/db/schema_migrations/20200303181648
deleted file mode 100644
index 017e9a7abbd..00000000000
--- a/db/schema_migrations/20200303181648
+++ /dev/null
@@ -1 +0,0 @@
-868042e64c19e31071101b49615620c83c7a0e759e81887491212e0e075dfa77 \ No newline at end of file
diff --git a/db/schema_migrations/20200304023245 b/db/schema_migrations/20200304023245
deleted file mode 100644
index 08fb4bf5dfe..00000000000
--- a/db/schema_migrations/20200304023245
+++ /dev/null
@@ -1 +0,0 @@
-2c4c95edac5819f31d15817a15046e3679726924a3dcdbde2004660fc820da31 \ No newline at end of file
diff --git a/db/schema_migrations/20200304023851 b/db/schema_migrations/20200304023851
deleted file mode 100644
index 6064bc6e09b..00000000000
--- a/db/schema_migrations/20200304023851
+++ /dev/null
@@ -1 +0,0 @@
-d75e64d72eec07d96c0fbced1caefc48f9116ba5a73f24ab1e964872a5377dc0 \ No newline at end of file
diff --git a/db/schema_migrations/20200304024025 b/db/schema_migrations/20200304024025
deleted file mode 100644
index d05a054141f..00000000000
--- a/db/schema_migrations/20200304024025
+++ /dev/null
@@ -1 +0,0 @@
-3b92198ed0771cf06ef871fbc160d323fca89e473ed3a037142cdd59e4865819 \ No newline at end of file
diff --git a/db/schema_migrations/20200304024042 b/db/schema_migrations/20200304024042
deleted file mode 100644
index fd74b708b69..00000000000
--- a/db/schema_migrations/20200304024042
+++ /dev/null
@@ -1 +0,0 @@
-aa9b40a163e85908106752b3365ee6bea8c0328b6e4bebb0a9f1ab72c9ad3ab0 \ No newline at end of file
diff --git a/db/schema_migrations/20200304085423 b/db/schema_migrations/20200304085423
deleted file mode 100644
index 5cf97433fa3..00000000000
--- a/db/schema_migrations/20200304085423
+++ /dev/null
@@ -1 +0,0 @@
-e36f3179a9516a655fc3e499d2700e5964ac37db7678737c33c7376b00c6e5be \ No newline at end of file
diff --git a/db/schema_migrations/20200304090155 b/db/schema_migrations/20200304090155
deleted file mode 100644
index d58e94031fd..00000000000
--- a/db/schema_migrations/20200304090155
+++ /dev/null
@@ -1 +0,0 @@
-4eabd24ebbee74cd5420199d5bbd79457daf0195a59cd4705ab4da36ab768cfc \ No newline at end of file
diff --git a/db/schema_migrations/20200304121828 b/db/schema_migrations/20200304121828
deleted file mode 100644
index 21bc444b211..00000000000
--- a/db/schema_migrations/20200304121828
+++ /dev/null
@@ -1 +0,0 @@
-ffdb33a2619c6fd31e70eb62adfbbb7df088ca427613b052acc4b560aaab95e8 \ No newline at end of file
diff --git a/db/schema_migrations/20200304121844 b/db/schema_migrations/20200304121844
deleted file mode 100644
index aed65d42d75..00000000000
--- a/db/schema_migrations/20200304121844
+++ /dev/null
@@ -1 +0,0 @@
-5ba721346282f3bcc213ba5d3c2591fd9893a9bda3c1bd1592a9617ceb8c8215 \ No newline at end of file
diff --git a/db/schema_migrations/20200304124406 b/db/schema_migrations/20200304124406
deleted file mode 100644
index f36befc06d3..00000000000
--- a/db/schema_migrations/20200304124406
+++ /dev/null
@@ -1 +0,0 @@
-d6000f710394784a29cdbb519a2c4c0b58cc1106b1f34fd4926ffdac43689305 \ No newline at end of file
diff --git a/db/schema_migrations/20200304160800 b/db/schema_migrations/20200304160800
deleted file mode 100644
index 532c2ab0e07..00000000000
--- a/db/schema_migrations/20200304160800
+++ /dev/null
@@ -1 +0,0 @@
-f5a17d1b3078552e5152f667c327345885a13a92533a79cce4461fc4015ef9b9 \ No newline at end of file
diff --git a/db/schema_migrations/20200304160801 b/db/schema_migrations/20200304160801
deleted file mode 100644
index ab94c3b8864..00000000000
--- a/db/schema_migrations/20200304160801
+++ /dev/null
@@ -1 +0,0 @@
-6fa1624af4bdb1f8bdeaf2d3c92563004622872e7c996c273bcd405a4311c320 \ No newline at end of file
diff --git a/db/schema_migrations/20200304160823 b/db/schema_migrations/20200304160823
deleted file mode 100644
index cfe062cf2da..00000000000
--- a/db/schema_migrations/20200304160823
+++ /dev/null
@@ -1 +0,0 @@
-0ae0344d60f620c0186607428de4fb9e40afbbb468bfbe84181f16272a90389a \ No newline at end of file
diff --git a/db/schema_migrations/20200304211738 b/db/schema_migrations/20200304211738
deleted file mode 100644
index eacc3deb063..00000000000
--- a/db/schema_migrations/20200304211738
+++ /dev/null
@@ -1 +0,0 @@
-54cbae339253353d594b0797aeb04529bfc67d1dc496f1872288e80e73d3fff5 \ No newline at end of file
diff --git a/db/schema_migrations/20200305020458 b/db/schema_migrations/20200305020458
deleted file mode 100644
index 05b98b20918..00000000000
--- a/db/schema_migrations/20200305020458
+++ /dev/null
@@ -1 +0,0 @@
-711df8d2c11579613771b2efc77917340ec04bc95c030b61463a3be88edace92 \ No newline at end of file
diff --git a/db/schema_migrations/20200305020459 b/db/schema_migrations/20200305020459
deleted file mode 100644
index adfcb205538..00000000000
--- a/db/schema_migrations/20200305020459
+++ /dev/null
@@ -1 +0,0 @@
-6f53fc13e262a806deba49caaebbf1a307938404289edca3394441d7bed07f68 \ No newline at end of file
diff --git a/db/schema_migrations/20200305082754 b/db/schema_migrations/20200305082754
deleted file mode 100644
index 8742b8cc2a4..00000000000
--- a/db/schema_migrations/20200305082754
+++ /dev/null
@@ -1 +0,0 @@
-e9f46e44b0caef2af159ab201d6a2868289fe9a0572c974ddc582dc023372ab6 \ No newline at end of file
diff --git a/db/schema_migrations/20200305082858 b/db/schema_migrations/20200305082858
deleted file mode 100644
index f885f37fdff..00000000000
--- a/db/schema_migrations/20200305082858
+++ /dev/null
@@ -1 +0,0 @@
-3a2954095c15360beaf5f0bb04b8173176a4b8801876eddb304fc1db03db4872 \ No newline at end of file
diff --git a/db/schema_migrations/20200305121159 b/db/schema_migrations/20200305121159
deleted file mode 100644
index 862a3d304e5..00000000000
--- a/db/schema_migrations/20200305121159
+++ /dev/null
@@ -1 +0,0 @@
-13afde45824bffa583d4ca6f891e874462b0bed3abba71322b865f9043a22221 \ No newline at end of file
diff --git a/db/schema_migrations/20200305151736 b/db/schema_migrations/20200305151736
deleted file mode 100644
index bdeb42e8c04..00000000000
--- a/db/schema_migrations/20200305151736
+++ /dev/null
@@ -1 +0,0 @@
-c9dad6555464ddf4e9a4b6a9298f2e6e64f1125ba8626c70b006123d31115d33 \ No newline at end of file
diff --git a/db/schema_migrations/20200305200641 b/db/schema_migrations/20200305200641
deleted file mode 100644
index 12193653dd3..00000000000
--- a/db/schema_migrations/20200305200641
+++ /dev/null
@@ -1 +0,0 @@
-b4c67b819c620a49ce0420fec883d8444e41a2a7970b45f94e9457799a041f7b \ No newline at end of file
diff --git a/db/schema_migrations/20200306095654 b/db/schema_migrations/20200306095654
deleted file mode 100644
index 952ba3063cd..00000000000
--- a/db/schema_migrations/20200306095654
+++ /dev/null
@@ -1 +0,0 @@
-3c5edc5ce531b26a08ae2a8f1b086f03ce63df80fa55ec15817b50a94047f883 \ No newline at end of file
diff --git a/db/schema_migrations/20200306160521 b/db/schema_migrations/20200306160521
deleted file mode 100644
index 66fe6845105..00000000000
--- a/db/schema_migrations/20200306160521
+++ /dev/null
@@ -1 +0,0 @@
-dcfaa4bea94107f3ed16c79701da68a57a8edfa049375f8f1ddf7fe3233004a7 \ No newline at end of file
diff --git a/db/schema_migrations/20200306170211 b/db/schema_migrations/20200306170211
deleted file mode 100644
index deba6e821eb..00000000000
--- a/db/schema_migrations/20200306170211
+++ /dev/null
@@ -1 +0,0 @@
-e04fdcb0454c998e8c0f27d956cf1d19e1182775e0c600eefb8ba85b989b340c \ No newline at end of file
diff --git a/db/schema_migrations/20200306170321 b/db/schema_migrations/20200306170321
deleted file mode 100644
index 2eb720315c4..00000000000
--- a/db/schema_migrations/20200306170321
+++ /dev/null
@@ -1 +0,0 @@
-b4b90b72e78fb77b6578f9f846b38061386fd2c81a2c72bb26fbdfeebbc6633b \ No newline at end of file
diff --git a/db/schema_migrations/20200306170531 b/db/schema_migrations/20200306170531
deleted file mode 100644
index 5ed60ceeb1c..00000000000
--- a/db/schema_migrations/20200306170531
+++ /dev/null
@@ -1 +0,0 @@
-7352528945b66621a7ed1337ad9b518f232b1a5e4af778e3832929a5e4247a6e \ No newline at end of file
diff --git a/db/schema_migrations/20200306192548 b/db/schema_migrations/20200306192548
deleted file mode 100644
index 30c5559936b..00000000000
--- a/db/schema_migrations/20200306192548
+++ /dev/null
@@ -1 +0,0 @@
-a8802d7c6b0b6db73601782ad30b84a745b34623a034de27fc73273deb61be73 \ No newline at end of file
diff --git a/db/schema_migrations/20200306193236 b/db/schema_migrations/20200306193236
deleted file mode 100644
index 2326318c935..00000000000
--- a/db/schema_migrations/20200306193236
+++ /dev/null
@@ -1 +0,0 @@
-7d33b0b8c044396c7cab9e7d70948f192d7e4f4c33a0921c29e3e21cdb6886c0 \ No newline at end of file
diff --git a/db/schema_migrations/20200309140540 b/db/schema_migrations/20200309140540
deleted file mode 100644
index c9578f4e592..00000000000
--- a/db/schema_migrations/20200309140540
+++ /dev/null
@@ -1 +0,0 @@
-a2e1ed7c70984bf045bdb1e9fc45296a5df0cc9464ca2fb297a992737f44d8a5 \ No newline at end of file
diff --git a/db/schema_migrations/20200309162244 b/db/schema_migrations/20200309162244
deleted file mode 100644
index a5ea72c4b0b..00000000000
--- a/db/schema_migrations/20200309162244
+++ /dev/null
@@ -1 +0,0 @@
-51e4ce90feccd894a5064bbb4e58141f5a2ca7c66d329d73b1d46ec54a6838e7 \ No newline at end of file
diff --git a/db/schema_migrations/20200309195209 b/db/schema_migrations/20200309195209
deleted file mode 100644
index e9b65afe467..00000000000
--- a/db/schema_migrations/20200309195209
+++ /dev/null
@@ -1 +0,0 @@
-602a765f26e04b90f726beceadf1834ecdcb8ab3c33cf0aec049219e88b3e2df \ No newline at end of file
diff --git a/db/schema_migrations/20200309195710 b/db/schema_migrations/20200309195710
deleted file mode 100644
index a31b61397ec..00000000000
--- a/db/schema_migrations/20200309195710
+++ /dev/null
@@ -1 +0,0 @@
-ef8bd48e0ed97debb1baf1c0b317e093219e9285cc0dd4be6e9b6ac5659fc7fe \ No newline at end of file
diff --git a/db/schema_migrations/20200310075115 b/db/schema_migrations/20200310075115
deleted file mode 100644
index 93343f7ce71..00000000000
--- a/db/schema_migrations/20200310075115
+++ /dev/null
@@ -1 +0,0 @@
-18e55800f012a784a5b67a104a4c95e1e8c9639c30e3712c79f518e11ef9b574 \ No newline at end of file
diff --git a/db/schema_migrations/20200310123229 b/db/schema_migrations/20200310123229
deleted file mode 100644
index 8f750d1ca27..00000000000
--- a/db/schema_migrations/20200310123229
+++ /dev/null
@@ -1 +0,0 @@
-774729ae47cdfb721f3e6cbfb6bd2b9835e699c236f27beab2674063efa35490 \ No newline at end of file
diff --git a/db/schema_migrations/20200310132654 b/db/schema_migrations/20200310132654
deleted file mode 100644
index 467bc655b5d..00000000000
--- a/db/schema_migrations/20200310132654
+++ /dev/null
@@ -1 +0,0 @@
-afb893004e505821b0c12db31dfc9b979c3a75ebd9a74699f242baecef9a76e3 \ No newline at end of file
diff --git a/db/schema_migrations/20200310133822 b/db/schema_migrations/20200310133822
deleted file mode 100644
index a68413bc2ab..00000000000
--- a/db/schema_migrations/20200310133822
+++ /dev/null
@@ -1 +0,0 @@
-0641a80bb43d760cdb3018f3b7259f4f7d7c5b5d7f5335b584b12a8b2906d44f \ No newline at end of file
diff --git a/db/schema_migrations/20200310135818 b/db/schema_migrations/20200310135818
deleted file mode 100644
index 1957f7bd435..00000000000
--- a/db/schema_migrations/20200310135818
+++ /dev/null
@@ -1 +0,0 @@
-f4070758551c6872379e3ef86a4a25905cf86d85c497f6339f6b6a3c231ec353 \ No newline at end of file
diff --git a/db/schema_migrations/20200310135823 b/db/schema_migrations/20200310135823
deleted file mode 100644
index 8fcd808fedd..00000000000
--- a/db/schema_migrations/20200310135823
+++ /dev/null
@@ -1 +0,0 @@
-0c82a979c3abb9890f133af9ed6d309fdcd42bc80808ef80d5f4b5c1699fdef9 \ No newline at end of file
diff --git a/db/schema_migrations/20200310145304 b/db/schema_migrations/20200310145304
deleted file mode 100644
index b1593a9d69d..00000000000
--- a/db/schema_migrations/20200310145304
+++ /dev/null
@@ -1 +0,0 @@
-a02188273892e26f48d9f83b5b5d3a8ba91f3bfb0d88cf8c6b00df935cdd0970 \ No newline at end of file
diff --git a/db/schema_migrations/20200310215714 b/db/schema_migrations/20200310215714
deleted file mode 100644
index 24a3be57bc3..00000000000
--- a/db/schema_migrations/20200310215714
+++ /dev/null
@@ -1 +0,0 @@
-08721b8f7ca6b10f504cae7f9f29692ae24a4b01e5e039b5f560301b737a99d0 \ No newline at end of file
diff --git a/db/schema_migrations/20200311074438 b/db/schema_migrations/20200311074438
deleted file mode 100644
index de949b8a26b..00000000000
--- a/db/schema_migrations/20200311074438
+++ /dev/null
@@ -1 +0,0 @@
-dcb08c60aafbd8272cf848bc522f52f5e95b8ecc611c4c25bb9fdd97d64906ea \ No newline at end of file
diff --git a/db/schema_migrations/20200311082301 b/db/schema_migrations/20200311082301
deleted file mode 100644
index 2c2645075c9..00000000000
--- a/db/schema_migrations/20200311082301
+++ /dev/null
@@ -1 +0,0 @@
-2dd88c42483913abb2dcf5ef75e0915301ce763af4efac4c8e84c075c38a71fd \ No newline at end of file
diff --git a/db/schema_migrations/20200311084025 b/db/schema_migrations/20200311084025
deleted file mode 100644
index a8583d22146..00000000000
--- a/db/schema_migrations/20200311084025
+++ /dev/null
@@ -1 +0,0 @@
-b8c934fc9d03bb0b9800042806158b7a516995afea6db2f25d2bf4138cb3fca0 \ No newline at end of file
diff --git a/db/schema_migrations/20200311093210 b/db/schema_migrations/20200311093210
deleted file mode 100644
index dfc7d91b288..00000000000
--- a/db/schema_migrations/20200311093210
+++ /dev/null
@@ -1 +0,0 @@
-549476c8bc28208b6be4e0db39e44f82214f4e0891fda09998127a28b8acd915 \ No newline at end of file
diff --git a/db/schema_migrations/20200311094020 b/db/schema_migrations/20200311094020
deleted file mode 100644
index c7ad298ccab..00000000000
--- a/db/schema_migrations/20200311094020
+++ /dev/null
@@ -1 +0,0 @@
-9d35ebc7b3c7a04ae4dd90873b30c8a81bec4a017bc4baba803d850b83e2a84d \ No newline at end of file
diff --git a/db/schema_migrations/20200311130802 b/db/schema_migrations/20200311130802
deleted file mode 100644
index 0305e261260..00000000000
--- a/db/schema_migrations/20200311130802
+++ /dev/null
@@ -1 +0,0 @@
-2ef9122411c81a770b1f1d558e65d192d4e50239b342a091b7317db18f1b3716 \ No newline at end of file
diff --git a/db/schema_migrations/20200311141053 b/db/schema_migrations/20200311141053
deleted file mode 100644
index 2bb2bc9448d..00000000000
--- a/db/schema_migrations/20200311141053
+++ /dev/null
@@ -1 +0,0 @@
-1a8b7230a5024487c88bb8d805e89cdf8afb297872a6a96b71b50a52d39ce970 \ No newline at end of file
diff --git a/db/schema_migrations/20200311141943 b/db/schema_migrations/20200311141943
deleted file mode 100644
index 224f353b8d2..00000000000
--- a/db/schema_migrations/20200311141943
+++ /dev/null
@@ -1 +0,0 @@
-32a0727652c4abffaf4a6871749acc07b56f20c0fc04d97c3d12c4b340f89177 \ No newline at end of file
diff --git a/db/schema_migrations/20200311154110 b/db/schema_migrations/20200311154110
deleted file mode 100644
index 25066a85b63..00000000000
--- a/db/schema_migrations/20200311154110
+++ /dev/null
@@ -1 +0,0 @@
-a98f79efb7145a8ea0c7034f1055dfadb1a3ad37e5498af081e2ee450a594b96 \ No newline at end of file
diff --git a/db/schema_migrations/20200311165635 b/db/schema_migrations/20200311165635
deleted file mode 100644
index e6cf4f1c608..00000000000
--- a/db/schema_migrations/20200311165635
+++ /dev/null
@@ -1 +0,0 @@
-badc13de8e33d9ce3b8068742e42d447ef50fcb73a288478ec2e81d0967495c9 \ No newline at end of file
diff --git a/db/schema_migrations/20200311192351 b/db/schema_migrations/20200311192351
deleted file mode 100644
index 9b9a658a7b8..00000000000
--- a/db/schema_migrations/20200311192351
+++ /dev/null
@@ -1 +0,0 @@
-fdfd959cf2e0f57f8f6259853a7a4607e7086ebf62eba00fa7dff3aef7f75e41 \ No newline at end of file
diff --git a/db/schema_migrations/20200311214912 b/db/schema_migrations/20200311214912
deleted file mode 100644
index 904718d973c..00000000000
--- a/db/schema_migrations/20200311214912
+++ /dev/null
@@ -1 +0,0 @@
-ac785cd0a9670cf6d6e02741dfc5c0d8531fd19f672ac761e59814a6adcf631e \ No newline at end of file
diff --git a/db/schema_migrations/20200312053852 b/db/schema_migrations/20200312053852
deleted file mode 100644
index 85a60ad7a07..00000000000
--- a/db/schema_migrations/20200312053852
+++ /dev/null
@@ -1 +0,0 @@
-18651a257b1a3319eca7c3a57f493efb9c30a87a1f837ddd8b760831fe0c9251 \ No newline at end of file
diff --git a/db/schema_migrations/20200312125121 b/db/schema_migrations/20200312125121
deleted file mode 100644
index 76ab0ef6d74..00000000000
--- a/db/schema_migrations/20200312125121
+++ /dev/null
@@ -1 +0,0 @@
-41e4cba792ef058d93190c9e05299c98e28ab91aabea47fbb4506b818dab001a \ No newline at end of file
diff --git a/db/schema_migrations/20200312134637 b/db/schema_migrations/20200312134637
deleted file mode 100644
index c1520913ba7..00000000000
--- a/db/schema_migrations/20200312134637
+++ /dev/null
@@ -1 +0,0 @@
-6db4c6d05fc80d7567515ed3601de4e099fd1c7012ab713593d8b3ed41c1fc67 \ No newline at end of file
diff --git a/db/schema_migrations/20200312160532 b/db/schema_migrations/20200312160532
deleted file mode 100644
index d203d40429b..00000000000
--- a/db/schema_migrations/20200312160532
+++ /dev/null
@@ -1 +0,0 @@
-40ae4e00c46cb0f09e639bcc20cf4e601ad3096e43586ba70693598ae51616e7 \ No newline at end of file
diff --git a/db/schema_migrations/20200312163407 b/db/schema_migrations/20200312163407
deleted file mode 100644
index bf848fa052d..00000000000
--- a/db/schema_migrations/20200312163407
+++ /dev/null
@@ -1 +0,0 @@
-209648af95eb386b8ccb97eceb34809a601cc876132a2c2d0f4cb8e714429000 \ No newline at end of file
diff --git a/db/schema_migrations/20200313101649 b/db/schema_migrations/20200313101649
deleted file mode 100644
index f3eb89bd49c..00000000000
--- a/db/schema_migrations/20200313101649
+++ /dev/null
@@ -1 +0,0 @@
-42a4437b341329f9eb970525ca247b3dda6fb5d333e1a248b71752466f1d0516 \ No newline at end of file
diff --git a/db/schema_migrations/20200313123934 b/db/schema_migrations/20200313123934
deleted file mode 100644
index 5f5f93f5406..00000000000
--- a/db/schema_migrations/20200313123934
+++ /dev/null
@@ -1 +0,0 @@
-3634ff12a2b164c30643c7a41e2ae0b68c7aa71c86ce0fa7d77472658c7165c3 \ No newline at end of file
diff --git a/db/schema_migrations/20200313202430 b/db/schema_migrations/20200313202430
deleted file mode 100644
index f5e6b0d8371..00000000000
--- a/db/schema_migrations/20200313202430
+++ /dev/null
@@ -1 +0,0 @@
-196f237ecbb591567629015d2765a876084c88f8aef3d647e2ce424fc2564858 \ No newline at end of file
diff --git a/db/schema_migrations/20200313203525 b/db/schema_migrations/20200313203525
deleted file mode 100644
index dc94f9c192e..00000000000
--- a/db/schema_migrations/20200313203525
+++ /dev/null
@@ -1 +0,0 @@
-b504e2dd331a438b780d27250bf85c0a430ec283188a759cc6631b6ff5851216 \ No newline at end of file
diff --git a/db/schema_migrations/20200313203550 b/db/schema_migrations/20200313203550
deleted file mode 100644
index f2600c1f912..00000000000
--- a/db/schema_migrations/20200313203550
+++ /dev/null
@@ -1 +0,0 @@
-579a499a30e42644bc5ab0baf7fdcab76c505e66bfd24cb90923cea41b9d6a30 \ No newline at end of file
diff --git a/db/schema_migrations/20200313204021 b/db/schema_migrations/20200313204021
deleted file mode 100644
index 80912edee66..00000000000
--- a/db/schema_migrations/20200313204021
+++ /dev/null
@@ -1 +0,0 @@
-721037f898a71a327219e5761f175e200df999adb7402de3169158dfd1b50eb5 \ No newline at end of file
diff --git a/db/schema_migrations/20200314060834 b/db/schema_migrations/20200314060834
deleted file mode 100644
index 4ffeae5cfc5..00000000000
--- a/db/schema_migrations/20200314060834
+++ /dev/null
@@ -1 +0,0 @@
-c35ce19cf34ec8479accd180fb576a3e6d652654fa525faf6fce7520d98ce195 \ No newline at end of file
diff --git a/db/schema_migrations/20200316111759 b/db/schema_migrations/20200316111759
deleted file mode 100644
index 74ce2aa78cf..00000000000
--- a/db/schema_migrations/20200316111759
+++ /dev/null
@@ -1 +0,0 @@
-da09454649ee16b8857b027d70515c07c2e0658e53e32475cad1cfaff620a023 \ No newline at end of file
diff --git a/db/schema_migrations/20200316162648 b/db/schema_migrations/20200316162648
deleted file mode 100644
index 63b760cddc1..00000000000
--- a/db/schema_migrations/20200316162648
+++ /dev/null
@@ -1 +0,0 @@
-2ae07c094e3ff6436fa9915e7ccd937ea2b77b4d02482b4d33aca10cbbe2b4cd \ No newline at end of file
diff --git a/db/schema_migrations/20200316173312 b/db/schema_migrations/20200316173312
deleted file mode 100644
index b0486db7e68..00000000000
--- a/db/schema_migrations/20200316173312
+++ /dev/null
@@ -1 +0,0 @@
-a91a2b875fdebeac752ee0c11d5c9713cbb86077bef1f2a3ddd3b4ea4f91fa97 \ No newline at end of file
diff --git a/db/schema_migrations/20200317110602 b/db/schema_migrations/20200317110602
deleted file mode 100644
index 5b9d86bc0c0..00000000000
--- a/db/schema_migrations/20200317110602
+++ /dev/null
@@ -1 +0,0 @@
-e9a391d4bc1b734541f208306112008c15e1f86e6581fe899c6ba680e2658474 \ No newline at end of file
diff --git a/db/schema_migrations/20200317142110 b/db/schema_migrations/20200317142110
deleted file mode 100644
index 66a4d852f10..00000000000
--- a/db/schema_migrations/20200317142110
+++ /dev/null
@@ -1 +0,0 @@
-6d5857c9183da9fe2a0a07d8947c5e97cedbc405c0603b054fbd013081cc1a85 \ No newline at end of file
diff --git a/db/schema_migrations/20200318140400 b/db/schema_migrations/20200318140400
deleted file mode 100644
index c719bb32705..00000000000
--- a/db/schema_migrations/20200318140400
+++ /dev/null
@@ -1 +0,0 @@
-0a51889bd781544a4aa1dd8b1fbb7b204820988fa99e99f937f85c5832cfdf4c \ No newline at end of file
diff --git a/db/schema_migrations/20200318152134 b/db/schema_migrations/20200318152134
deleted file mode 100644
index 44e4fee5d86..00000000000
--- a/db/schema_migrations/20200318152134
+++ /dev/null
@@ -1 +0,0 @@
-7841e14170e1d1e3b6504007d21ecd01d848618465d010feee62c07cd2cd01c6 \ No newline at end of file
diff --git a/db/schema_migrations/20200318162148 b/db/schema_migrations/20200318162148
deleted file mode 100644
index 061c59f594c..00000000000
--- a/db/schema_migrations/20200318162148
+++ /dev/null
@@ -1 +0,0 @@
-2507f0e36664c2b08ab0a4b393c62cda45a36b94e98b95bc698f9683bf852948 \ No newline at end of file
diff --git a/db/schema_migrations/20200318163148 b/db/schema_migrations/20200318163148
deleted file mode 100644
index bbc32ef7f25..00000000000
--- a/db/schema_migrations/20200318163148
+++ /dev/null
@@ -1 +0,0 @@
-5848d98d3b1b8b3b26c46fdc9364707c21aeb0f5fcff1dfa546ad0c00d9f4dcc \ No newline at end of file
diff --git a/db/schema_migrations/20200318164448 b/db/schema_migrations/20200318164448
deleted file mode 100644
index cc021438aae..00000000000
--- a/db/schema_migrations/20200318164448
+++ /dev/null
@@ -1 +0,0 @@
-bae13167af992c8689192066c36de88f9c3149804600813f9bdbc2c484ce047a \ No newline at end of file
diff --git a/db/schema_migrations/20200318165448 b/db/schema_migrations/20200318165448
deleted file mode 100644
index e466b2bc43b..00000000000
--- a/db/schema_migrations/20200318165448
+++ /dev/null
@@ -1 +0,0 @@
-43e6afd5aba2eaae0aa8e4524c1de5c3d65b1c380421f9fd090e56bb4b91829a \ No newline at end of file
diff --git a/db/schema_migrations/20200318175008 b/db/schema_migrations/20200318175008
deleted file mode 100644
index d48a7431b5f..00000000000
--- a/db/schema_migrations/20200318175008
+++ /dev/null
@@ -1 +0,0 @@
-96fae378336e330fce005c5c7a81eaf95b70181ce0be5bcb4b5e6f491328e288 \ No newline at end of file
diff --git a/db/schema_migrations/20200318183553 b/db/schema_migrations/20200318183553
deleted file mode 100644
index 9c8e5f7f279..00000000000
--- a/db/schema_migrations/20200318183553
+++ /dev/null
@@ -1 +0,0 @@
-32c96bda198bf41ba2e92b9e56d0508de394187e16118ae238769b54066a5bfc \ No newline at end of file
diff --git a/db/schema_migrations/20200319071702 b/db/schema_migrations/20200319071702
deleted file mode 100644
index 6e92d37e397..00000000000
--- a/db/schema_migrations/20200319071702
+++ /dev/null
@@ -1 +0,0 @@
-8cc6e9e722d5ec31f8e3912ae39fe09fea01b6ee5130a6baaa86072fd9683cbb \ No newline at end of file
diff --git a/db/schema_migrations/20200319123041 b/db/schema_migrations/20200319123041
deleted file mode 100644
index a507feda89f..00000000000
--- a/db/schema_migrations/20200319123041
+++ /dev/null
@@ -1 +0,0 @@
-11612949c4481c27e502eb6c6cb2bf7ed2a3812d905fcccaa4a047fa90b77dfd \ No newline at end of file
diff --git a/db/schema_migrations/20200319124127 b/db/schema_migrations/20200319124127
deleted file mode 100644
index 78099c75d28..00000000000
--- a/db/schema_migrations/20200319124127
+++ /dev/null
@@ -1 +0,0 @@
-ad6b4f2ca19deec7d8e1b3a26c31995950b2c6de07248a8f684de4b3699eb319 \ No newline at end of file
diff --git a/db/schema_migrations/20200319203901 b/db/schema_migrations/20200319203901
deleted file mode 100644
index 7c78df5001b..00000000000
--- a/db/schema_migrations/20200319203901
+++ /dev/null
@@ -1 +0,0 @@
-356c0961a665eeef74a7f57f8d8bca51ecaa425d683a33621611ed1fd70f1153 \ No newline at end of file
diff --git a/db/schema_migrations/20200320112455 b/db/schema_migrations/20200320112455
deleted file mode 100644
index ee71ec10136..00000000000
--- a/db/schema_migrations/20200320112455
+++ /dev/null
@@ -1 +0,0 @@
-89c33274d4902df5ad710e6678970bc6c0155e39a8084c8f7481dc5105cf783b \ No newline at end of file
diff --git a/db/schema_migrations/20200320123839 b/db/schema_migrations/20200320123839
deleted file mode 100644
index f8b5c779071..00000000000
--- a/db/schema_migrations/20200320123839
+++ /dev/null
@@ -1 +0,0 @@
-b25a96f19c673a0a00efb0226fd117274577f730538acc18791b0e33b8bc6d37 \ No newline at end of file
diff --git a/db/schema_migrations/20200320212400 b/db/schema_migrations/20200320212400
deleted file mode 100644
index a28171d0557..00000000000
--- a/db/schema_migrations/20200320212400
+++ /dev/null
@@ -1 +0,0 @@
-6aa64b6fefa51a01c99e36b56792500df4935b8106a3489e804d157921365437 \ No newline at end of file
diff --git a/db/schema_migrations/20200323011225 b/db/schema_migrations/20200323011225
deleted file mode 100644
index 9d37658a8bf..00000000000
--- a/db/schema_migrations/20200323011225
+++ /dev/null
@@ -1 +0,0 @@
-071e3909530f46f5d794bc0bc351dd7561cf9146ad4145a7fe5ad390974192c5 \ No newline at end of file
diff --git a/db/schema_migrations/20200323011955 b/db/schema_migrations/20200323011955
deleted file mode 100644
index e39e29a73a4..00000000000
--- a/db/schema_migrations/20200323011955
+++ /dev/null
@@ -1 +0,0 @@
-882a00f49cb253cb1a25995196c7667bedc049ec7f5273d76b3cc04686c7ef52 \ No newline at end of file
diff --git a/db/schema_migrations/20200323071918 b/db/schema_migrations/20200323071918
deleted file mode 100644
index 92dd734108a..00000000000
--- a/db/schema_migrations/20200323071918
+++ /dev/null
@@ -1 +0,0 @@
-44900b0260613b740c3845a97e521e28223a9b4ba000c9b1a318f5edef3d8542 \ No newline at end of file
diff --git a/db/schema_migrations/20200323074147 b/db/schema_migrations/20200323074147
deleted file mode 100644
index cd9943747a1..00000000000
--- a/db/schema_migrations/20200323074147
+++ /dev/null
@@ -1 +0,0 @@
-3177b710bbe037d68637c4218b3e957b8aaeb4ee03324b9e041cb1de2777ff09 \ No newline at end of file
diff --git a/db/schema_migrations/20200323075043 b/db/schema_migrations/20200323075043
deleted file mode 100644
index 89a60bb67cf..00000000000
--- a/db/schema_migrations/20200323075043
+++ /dev/null
@@ -1 +0,0 @@
-e1410b0006331f2ebf3dbf08d38ceaa2d69e08e4442b6d725fe046fc1aa5ebd7 \ No newline at end of file
diff --git a/db/schema_migrations/20200323080714 b/db/schema_migrations/20200323080714
deleted file mode 100644
index 65ab49c25f6..00000000000
--- a/db/schema_migrations/20200323080714
+++ /dev/null
@@ -1 +0,0 @@
-ebf04e48435aede0a69ca4e54a91aae20c938e3895458506ee11d33bf621ef22 \ No newline at end of file
diff --git a/db/schema_migrations/20200323122201 b/db/schema_migrations/20200323122201
deleted file mode 100644
index 097933ec705..00000000000
--- a/db/schema_migrations/20200323122201
+++ /dev/null
@@ -1 +0,0 @@
-0b0f8f7be445c37d198d6be81ea98b42151c108fea290f597878ce7b8efdd945 \ No newline at end of file
diff --git a/db/schema_migrations/20200323134519 b/db/schema_migrations/20200323134519
deleted file mode 100644
index 781e49d9d83..00000000000
--- a/db/schema_migrations/20200323134519
+++ /dev/null
@@ -1 +0,0 @@
-cae490689ea7e3addf1350765cfd02a5f0a560d3ef946aaa7f2db67e03a0642a \ No newline at end of file
diff --git a/db/schema_migrations/20200324093258 b/db/schema_migrations/20200324093258
deleted file mode 100644
index c188ab41bc5..00000000000
--- a/db/schema_migrations/20200324093258
+++ /dev/null
@@ -1 +0,0 @@
-73632637610b92b6cc49d833053068cb2f4ac1724d641c1554470649f50177b9 \ No newline at end of file
diff --git a/db/schema_migrations/20200324115359 b/db/schema_migrations/20200324115359
deleted file mode 100644
index 9d1111f7fd0..00000000000
--- a/db/schema_migrations/20200324115359
+++ /dev/null
@@ -1 +0,0 @@
-bcc2e79aef3aec6424c533d777f5b78eb78b4e36a832c25f60f3bfbfe205da0d \ No newline at end of file
diff --git a/db/schema_migrations/20200325094612 b/db/schema_migrations/20200325094612
deleted file mode 100644
index e791a2cc8f2..00000000000
--- a/db/schema_migrations/20200325094612
+++ /dev/null
@@ -1 +0,0 @@
-89bb13eb2e76071e5c2901dfae8fe250094135fb9723e1a94b538596e01b2d01 \ No newline at end of file
diff --git a/db/schema_migrations/20200325104755 b/db/schema_migrations/20200325104755
deleted file mode 100644
index 41a36414b14..00000000000
--- a/db/schema_migrations/20200325104755
+++ /dev/null
@@ -1 +0,0 @@
-be0cde3782a0845f5364493a738a52e3a65b4fb9a86c7e459e0239305e2f17ab \ No newline at end of file
diff --git a/db/schema_migrations/20200325104756 b/db/schema_migrations/20200325104756
deleted file mode 100644
index ada479d8896..00000000000
--- a/db/schema_migrations/20200325104756
+++ /dev/null
@@ -1 +0,0 @@
-1c8000a2f9722795f220d70bf86f877a55f613e44cb7d6cce43e6d0e2639ddb0 \ No newline at end of file
diff --git a/db/schema_migrations/20200325104833 b/db/schema_migrations/20200325104833
deleted file mode 100644
index 03ff24efa4f..00000000000
--- a/db/schema_migrations/20200325104833
+++ /dev/null
@@ -1 +0,0 @@
-576a15f65fd06b783fd0b790b218d0ba14ccf8af29f9851cdad77cb244bb9ce6 \ No newline at end of file
diff --git a/db/schema_migrations/20200325104834 b/db/schema_migrations/20200325104834
deleted file mode 100644
index c43c82d0536..00000000000
--- a/db/schema_migrations/20200325104834
+++ /dev/null
@@ -1 +0,0 @@
-d0071a6c4cddc4fadab8313235756846c5245c9ef113d2d4e8b824e60e0a7195 \ No newline at end of file
diff --git a/db/schema_migrations/20200325111432 b/db/schema_migrations/20200325111432
deleted file mode 100644
index dcf8493f6c9..00000000000
--- a/db/schema_migrations/20200325111432
+++ /dev/null
@@ -1 +0,0 @@
-55e6e67ebd513edfb53601837ba9e5311c0c2562289bf5a0bff3d5c0aa33e3ba \ No newline at end of file
diff --git a/db/schema_migrations/20200325152327 b/db/schema_migrations/20200325152327
deleted file mode 100644
index 04a470f3090..00000000000
--- a/db/schema_migrations/20200325152327
+++ /dev/null
@@ -1 +0,0 @@
-047ead050d2276e977f03fe5176a2e5dd122f6ca0572d510e0ae04298d868798 \ No newline at end of file
diff --git a/db/schema_migrations/20200325160952 b/db/schema_migrations/20200325160952
deleted file mode 100644
index 7c1952374ed..00000000000
--- a/db/schema_migrations/20200325160952
+++ /dev/null
@@ -1 +0,0 @@
-eec09683e458c023414a081232c3852dfd8bb6daa89bbaa61eabaf0f663eaf32 \ No newline at end of file
diff --git a/db/schema_migrations/20200325162730 b/db/schema_migrations/20200325162730
deleted file mode 100644
index e7159a63c5d..00000000000
--- a/db/schema_migrations/20200325162730
+++ /dev/null
@@ -1 +0,0 @@
-8370a5f5603a9e5d327e89ff1b1a8620346610c92ddaaa995589601331146dc8 \ No newline at end of file
diff --git a/db/schema_migrations/20200325183636 b/db/schema_migrations/20200325183636
deleted file mode 100644
index 4b8f549b445..00000000000
--- a/db/schema_migrations/20200325183636
+++ /dev/null
@@ -1 +0,0 @@
-0ff00e587e420e081e3603640d5b78ece243bb3818c1b2ee00fca4a217191ffa \ No newline at end of file
diff --git a/db/schema_migrations/20200326114443 b/db/schema_migrations/20200326114443
deleted file mode 100644
index eb11bc5bf8e..00000000000
--- a/db/schema_migrations/20200326114443
+++ /dev/null
@@ -1 +0,0 @@
-1a3b8152ed77737392af8d3539c84d5fe1743496c05e9d28e0b9d8ad0910199c \ No newline at end of file
diff --git a/db/schema_migrations/20200326122700 b/db/schema_migrations/20200326122700
deleted file mode 100644
index fa36e1f273c..00000000000
--- a/db/schema_migrations/20200326122700
+++ /dev/null
@@ -1 +0,0 @@
-e44d88030f6eb09fae4816b0d59c33bfed8e3606b6778246785a6c59cf8bb08c \ No newline at end of file
diff --git a/db/schema_migrations/20200326124443 b/db/schema_migrations/20200326124443
deleted file mode 100644
index d59477a3dc5..00000000000
--- a/db/schema_migrations/20200326124443
+++ /dev/null
@@ -1 +0,0 @@
-b4c85d097d5b9b7851f0506708b0758271da09c4303e4994a14e3d5d868a1b0d \ No newline at end of file
diff --git a/db/schema_migrations/20200326134443 b/db/schema_migrations/20200326134443
deleted file mode 100644
index 474df3aa07f..00000000000
--- a/db/schema_migrations/20200326134443
+++ /dev/null
@@ -1 +0,0 @@
-05857054d9b4e99bdc60d7afbbf889e704083f92cd6a071094cda3184d170db2 \ No newline at end of file
diff --git a/db/schema_migrations/20200326135443 b/db/schema_migrations/20200326135443
deleted file mode 100644
index 5c2a84df576..00000000000
--- a/db/schema_migrations/20200326135443
+++ /dev/null
@@ -1 +0,0 @@
-a0b50e7e2fba107d4545164eb26b31e35cab78ea77a53e59df22782f2ee4ce1d \ No newline at end of file
diff --git a/db/schema_migrations/20200326144443 b/db/schema_migrations/20200326144443
deleted file mode 100644
index b89062f9d94..00000000000
--- a/db/schema_migrations/20200326144443
+++ /dev/null
@@ -1 +0,0 @@
-1787e42a5c7e551f0e6c706e882fc1987e9fc81d58f0ef6577a9b6b59321068a \ No newline at end of file
diff --git a/db/schema_migrations/20200326145443 b/db/schema_migrations/20200326145443
deleted file mode 100644
index 25a96a6ee19..00000000000
--- a/db/schema_migrations/20200326145443
+++ /dev/null
@@ -1 +0,0 @@
-c230e90f90ffbdfda37aa2a263272904754c46379bf83a35a347e30d91c4fb7c \ No newline at end of file
diff --git a/db/schema_migrations/20200330074719 b/db/schema_migrations/20200330074719
deleted file mode 100644
index 52084e7cde9..00000000000
--- a/db/schema_migrations/20200330074719
+++ /dev/null
@@ -1 +0,0 @@
-5fc04f403f2c97eb76e25948d37d3e66251d3d82020c949e7f841056730d5d89 \ No newline at end of file
diff --git a/db/schema_migrations/20200330121000 b/db/schema_migrations/20200330121000
deleted file mode 100644
index bf27f0af290..00000000000
--- a/db/schema_migrations/20200330121000
+++ /dev/null
@@ -1 +0,0 @@
-639e7e45f4a3027ad934aa28ed838a6db12ddfcacd4492e30b5d03781ecc5956 \ No newline at end of file
diff --git a/db/schema_migrations/20200330123739 b/db/schema_migrations/20200330123739
deleted file mode 100644
index 02deb3a6781..00000000000
--- a/db/schema_migrations/20200330123739
+++ /dev/null
@@ -1 +0,0 @@
-f921cd2ce82286517b9f8eeb753c7d6fd8fa1521e2ac4e721bb2c1753244d24a \ No newline at end of file
diff --git a/db/schema_migrations/20200330132913 b/db/schema_migrations/20200330132913
deleted file mode 100644
index 94787ebd2c2..00000000000
--- a/db/schema_migrations/20200330132913
+++ /dev/null
@@ -1 +0,0 @@
-f64c9fb9222130fbe7f7af8dcaded0e47158b59ae13452a1faa397de428ebcad \ No newline at end of file
diff --git a/db/schema_migrations/20200330203826 b/db/schema_migrations/20200330203826
deleted file mode 100644
index cf1eef6772c..00000000000
--- a/db/schema_migrations/20200330203826
+++ /dev/null
@@ -1 +0,0 @@
-6a43b94f1288e9250b7fbf596987e13bf96e2f6721df864ddda6cb39a30ecf9e \ No newline at end of file
diff --git a/db/schema_migrations/20200330203837 b/db/schema_migrations/20200330203837
deleted file mode 100644
index 2e5e418d326..00000000000
--- a/db/schema_migrations/20200330203837
+++ /dev/null
@@ -1 +0,0 @@
-b7159c82d117371825bd0e0ab865eafc40ffc2821f7bbd93e5b53b4abb131c1a \ No newline at end of file
diff --git a/db/schema_migrations/20200331103637 b/db/schema_migrations/20200331103637
deleted file mode 100644
index 5314e785c43..00000000000
--- a/db/schema_migrations/20200331103637
+++ /dev/null
@@ -1 +0,0 @@
-cb2570258c32c29a8db61740f7cab94339d4abf8402ad0234787ebd9d4ec900f \ No newline at end of file
diff --git a/db/schema_migrations/20200331113728 b/db/schema_migrations/20200331113728
deleted file mode 100644
index 606e88f2a69..00000000000
--- a/db/schema_migrations/20200331113728
+++ /dev/null
@@ -1 +0,0 @@
-2bf98da41385dce10efa06b99c1d11efc71ffa0be1454c95b3095ba66561c2e1 \ No newline at end of file
diff --git a/db/schema_migrations/20200331113738 b/db/schema_migrations/20200331113738
deleted file mode 100644
index 40003a85bc5..00000000000
--- a/db/schema_migrations/20200331113738
+++ /dev/null
@@ -1 +0,0 @@
-1fe7c1b25d5cc5329b4e0799587d2b84431b5ac2811c6e679560c4b0c5e62290 \ No newline at end of file
diff --git a/db/schema_migrations/20200331132103 b/db/schema_migrations/20200331132103
deleted file mode 100644
index e8dd1701bef..00000000000
--- a/db/schema_migrations/20200331132103
+++ /dev/null
@@ -1 +0,0 @@
-d032949c960b1e237bbc5dff6d5cf9a92d2849ca316961335b01fe02dcd2910f \ No newline at end of file
diff --git a/db/schema_migrations/20200331195952 b/db/schema_migrations/20200331195952
deleted file mode 100644
index 65bfd531378..00000000000
--- a/db/schema_migrations/20200331195952
+++ /dev/null
@@ -1 +0,0 @@
-11ffb5e733d4b696d63b74449d52c76c45df6e2bf5d9a758c3b43f59d88fa94d \ No newline at end of file
diff --git a/db/schema_migrations/20200331220930 b/db/schema_migrations/20200331220930
deleted file mode 100644
index 3e0619d1d55..00000000000
--- a/db/schema_migrations/20200331220930
+++ /dev/null
@@ -1 +0,0 @@
-818714755d2ee77c1be834b8ea07b2b06f97f423f00a794da0132277c82cdb36 \ No newline at end of file
diff --git a/db/schema_migrations/20200401091051 b/db/schema_migrations/20200401091051
deleted file mode 100644
index dd1b9eebc39..00000000000
--- a/db/schema_migrations/20200401091051
+++ /dev/null
@@ -1 +0,0 @@
-e11619ace35714e76f2da4d82a95381a3d49a1215fc5def309281f9185d7d400 \ No newline at end of file
diff --git a/db/schema_migrations/20200401095430 b/db/schema_migrations/20200401095430
deleted file mode 100644
index 1cba0e9e789..00000000000
--- a/db/schema_migrations/20200401095430
+++ /dev/null
@@ -1 +0,0 @@
-b0f154bef54b6ab9f9b6722016e1cb8642c567bde1d57a66a31f70d8cca37fda \ No newline at end of file
diff --git a/db/schema_migrations/20200401211005 b/db/schema_migrations/20200401211005
deleted file mode 100644
index 68b2137760b..00000000000
--- a/db/schema_migrations/20200401211005
+++ /dev/null
@@ -1 +0,0 @@
-a7941ffd4617b2a45a74febe9b338bee746df1bfb13349e38c3c519a5b21ca16 \ No newline at end of file
diff --git a/db/schema_migrations/20200402001106 b/db/schema_migrations/20200402001106
deleted file mode 100644
index 42f281c36f0..00000000000
--- a/db/schema_migrations/20200402001106
+++ /dev/null
@@ -1 +0,0 @@
-82fbcc682d7f86c667954d939e4ff747e5dddc91d1a7aa8ecd21911aeae605cb \ No newline at end of file
diff --git a/db/schema_migrations/20200402115013 b/db/schema_migrations/20200402115013
deleted file mode 100644
index 3fe1d246806..00000000000
--- a/db/schema_migrations/20200402115013
+++ /dev/null
@@ -1 +0,0 @@
-5ef3cd4613e901716d9c0a026485076c9319737919a7bbce4c2eee4d4413aeec \ No newline at end of file
diff --git a/db/schema_migrations/20200402115623 b/db/schema_migrations/20200402115623
deleted file mode 100644
index bd93c32995c..00000000000
--- a/db/schema_migrations/20200402115623
+++ /dev/null
@@ -1 +0,0 @@
-5c9ae74ad4efe967310773eefb3f8070ef6955b93ceca910b8e721a05243998e \ No newline at end of file
diff --git a/db/schema_migrations/20200402123926 b/db/schema_migrations/20200402123926
deleted file mode 100644
index 753097dae49..00000000000
--- a/db/schema_migrations/20200402123926
+++ /dev/null
@@ -1 +0,0 @@
-c708ad745a0d858a6ecd993b5ca7f621e3a36b2d770b774c330f285948186311 \ No newline at end of file
diff --git a/db/schema_migrations/20200402124802 b/db/schema_migrations/20200402124802
deleted file mode 100644
index eb23b9ad72d..00000000000
--- a/db/schema_migrations/20200402124802
+++ /dev/null
@@ -1 +0,0 @@
-f27ff20edac6214fc34e19098a022ff0da5c90fa2c4d0051c1ef499022d9a3b6 \ No newline at end of file
diff --git a/db/schema_migrations/20200402135250 b/db/schema_migrations/20200402135250
deleted file mode 100644
index e042be7b268..00000000000
--- a/db/schema_migrations/20200402135250
+++ /dev/null
@@ -1 +0,0 @@
-b359d2f9a7b456aea2e4fa1b5d8ec7d28125cf696bb4d244532bfe448356c186 \ No newline at end of file
diff --git a/db/schema_migrations/20200402185044 b/db/schema_migrations/20200402185044
deleted file mode 100644
index 74b0d9ed394..00000000000
--- a/db/schema_migrations/20200402185044
+++ /dev/null
@@ -1 +0,0 @@
-d9ffe8bc5f2594ce164cf4f51ae969705fa0b5501c9a6e8529819d22cb6159e5 \ No newline at end of file
diff --git a/db/schema_migrations/20200403132349 b/db/schema_migrations/20200403132349
deleted file mode 100644
index 093a56c8fd5..00000000000
--- a/db/schema_migrations/20200403132349
+++ /dev/null
@@ -1 +0,0 @@
-a381d5675c3fa80ed0b3bc9108103e42553e697ac0db4ab78e31a79f93d9de1d \ No newline at end of file
diff --git a/db/schema_migrations/20200403184110 b/db/schema_migrations/20200403184110
deleted file mode 100644
index 5503fff93ac..00000000000
--- a/db/schema_migrations/20200403184110
+++ /dev/null
@@ -1 +0,0 @@
-61c6f41c76381139c56e5ef8674b23f2dc87f76677d8ae16791db27ba129ea0c \ No newline at end of file
diff --git a/db/schema_migrations/20200403185127 b/db/schema_migrations/20200403185127
deleted file mode 100644
index bfe7eb68fe8..00000000000
--- a/db/schema_migrations/20200403185127
+++ /dev/null
@@ -1 +0,0 @@
-134f0f3217952c5dfca109374c9b90cf3d76ceea527530713988ef25e0e237ee \ No newline at end of file
diff --git a/db/schema_migrations/20200403185422 b/db/schema_migrations/20200403185422
deleted file mode 100644
index a2fe5409efc..00000000000
--- a/db/schema_migrations/20200403185422
+++ /dev/null
@@ -1 +0,0 @@
-b65b6a0905672f81d728021940e2480723913053b29eee16f1fa350c9a8b08eb \ No newline at end of file
diff --git a/db/schema_migrations/20200406095930 b/db/schema_migrations/20200406095930
deleted file mode 100644
index 27f74b9d92c..00000000000
--- a/db/schema_migrations/20200406095930
+++ /dev/null
@@ -1 +0,0 @@
-3a5d20d3fa0b73f2e49aa38bed5b3e0aae267788b679f360535190de166e827f \ No newline at end of file
diff --git a/db/schema_migrations/20200406100909 b/db/schema_migrations/20200406100909
deleted file mode 100644
index 2ebe9dd6979..00000000000
--- a/db/schema_migrations/20200406100909
+++ /dev/null
@@ -1 +0,0 @@
-7cf2f4a946bef35e4a8c2a9a45ca7102ad6535791ff84423af0890ea5644abc8 \ No newline at end of file
diff --git a/db/schema_migrations/20200406102111 b/db/schema_migrations/20200406102111
deleted file mode 100644
index e61ba266223..00000000000
--- a/db/schema_migrations/20200406102111
+++ /dev/null
@@ -1 +0,0 @@
-56efa5b6b0545b51d47c27c16b7fb8217d56fba701bff39b5776b5a9a2dbcdf2 \ No newline at end of file
diff --git a/db/schema_migrations/20200406102120 b/db/schema_migrations/20200406102120
deleted file mode 100644
index 31727cf3607..00000000000
--- a/db/schema_migrations/20200406102120
+++ /dev/null
@@ -1 +0,0 @@
-5e7ffbca4477555e55f650037502e38fec63084f6681358614f5caab896417f7 \ No newline at end of file
diff --git a/db/schema_migrations/20200406132529 b/db/schema_migrations/20200406132529
deleted file mode 100644
index 05f9c71723e..00000000000
--- a/db/schema_migrations/20200406132529
+++ /dev/null
@@ -1 +0,0 @@
-4b308b55824c8fc1b7ca6b2f847382be79cc82ecad6896969be551f630face6f \ No newline at end of file
diff --git a/db/schema_migrations/20200406135648 b/db/schema_migrations/20200406135648
deleted file mode 100644
index 563439ec8ba..00000000000
--- a/db/schema_migrations/20200406135648
+++ /dev/null
@@ -1 +0,0 @@
-a9b4b9f33045f13e75cff4e26f0770270f291673776c85bc6d57beef4daad1f7 \ No newline at end of file
diff --git a/db/schema_migrations/20200406141452 b/db/schema_migrations/20200406141452
deleted file mode 100644
index cd509e2fb97..00000000000
--- a/db/schema_migrations/20200406141452
+++ /dev/null
@@ -1 +0,0 @@
-59c110c50bd77d05fffaca466e609090abc7bae9166ec3a754115cc353d2bb04 \ No newline at end of file
diff --git a/db/schema_migrations/20200406192059 b/db/schema_migrations/20200406192059
deleted file mode 100644
index 1e71ed11efe..00000000000
--- a/db/schema_migrations/20200406192059
+++ /dev/null
@@ -1 +0,0 @@
-db5445e1a50de06348cb1e0f4737b7f4f66426595bd7cd2de0078a74346eef5f \ No newline at end of file
diff --git a/db/schema_migrations/20200406193427 b/db/schema_migrations/20200406193427
deleted file mode 100644
index cfe16383f85..00000000000
--- a/db/schema_migrations/20200406193427
+++ /dev/null
@@ -1 +0,0 @@
-26d6182d01dd7958dae153c22f13f2c1b7930cd74b912de067e7a6743084f6fb \ No newline at end of file
diff --git a/db/schema_migrations/20200407094005 b/db/schema_migrations/20200407094005
deleted file mode 100644
index 21bc7433a86..00000000000
--- a/db/schema_migrations/20200407094005
+++ /dev/null
@@ -1 +0,0 @@
-deb40c4055e0c810a98ba26ac51be2be6b424b978a4f2cc64338233128c84927 \ No newline at end of file
diff --git a/db/schema_migrations/20200407094923 b/db/schema_migrations/20200407094923
deleted file mode 100644
index fa71c965570..00000000000
--- a/db/schema_migrations/20200407094923
+++ /dev/null
@@ -1 +0,0 @@
-b48e03a58fbcc140768112d120e5c927c20ceca64e1d5079f938ba75e23d9e43 \ No newline at end of file
diff --git a/db/schema_migrations/20200407120000 b/db/schema_migrations/20200407120000
deleted file mode 100644
index 14df432f6c8..00000000000
--- a/db/schema_migrations/20200407120000
+++ /dev/null
@@ -1 +0,0 @@
-eba6253dbb2ff86c108c801c67665a8e19b6d88293ff824a41006347d0b4a4c3 \ No newline at end of file
diff --git a/db/schema_migrations/20200407121321 b/db/schema_migrations/20200407121321
deleted file mode 100644
index c3bf42bb675..00000000000
--- a/db/schema_migrations/20200407121321
+++ /dev/null
@@ -1 +0,0 @@
-5cb21d0c39526d9d0a8f7e3d76ae41c8e1bc6d2389c597e0143175cd9cbbf93f \ No newline at end of file
diff --git a/db/schema_migrations/20200407171133 b/db/schema_migrations/20200407171133
deleted file mode 100644
index 4201b37e420..00000000000
--- a/db/schema_migrations/20200407171133
+++ /dev/null
@@ -1 +0,0 @@
-3276dfca5d74628c56ee2bf72588faee21d7ca74b3876215c0d449a57d20094d \ No newline at end of file
diff --git a/db/schema_migrations/20200407171417 b/db/schema_migrations/20200407171417
deleted file mode 100644
index 239a4923b8b..00000000000
--- a/db/schema_migrations/20200407171417
+++ /dev/null
@@ -1 +0,0 @@
-a9b99715636ae4cb61b1eb822ca559178a11d2351ae8858c6a68e4f37bf86626 \ No newline at end of file
diff --git a/db/schema_migrations/20200407182205 b/db/schema_migrations/20200407182205
deleted file mode 100644
index 274720357a8..00000000000
--- a/db/schema_migrations/20200407182205
+++ /dev/null
@@ -1 +0,0 @@
-450ebcd6b8ea2f0d29661b83cd601b270e10b332c0ee178e9147b4946f90de82 \ No newline at end of file
diff --git a/db/schema_migrations/20200407222647 b/db/schema_migrations/20200407222647
deleted file mode 100644
index cefab8fbffe..00000000000
--- a/db/schema_migrations/20200407222647
+++ /dev/null
@@ -1 +0,0 @@
-ff735eb514bbe19871943b1d66c19b427b4dc233ca25db81532555654abead4b \ No newline at end of file
diff --git a/db/schema_migrations/20200408110856 b/db/schema_migrations/20200408110856
deleted file mode 100644
index 6afc26ce1db..00000000000
--- a/db/schema_migrations/20200408110856
+++ /dev/null
@@ -1 +0,0 @@
-be8dd7230c7564217758f6731f3406647af0dd283e83c59833e879330f9c9ce3 \ No newline at end of file
diff --git a/db/schema_migrations/20200408125046 b/db/schema_migrations/20200408125046
deleted file mode 100644
index fcfc11208d3..00000000000
--- a/db/schema_migrations/20200408125046
+++ /dev/null
@@ -1 +0,0 @@
-74eb691ef4d0f542ebaf2a0550b55b47ba296e7f623fe67d6f837c9f4d4c677f \ No newline at end of file
diff --git a/db/schema_migrations/20200408132152 b/db/schema_migrations/20200408132152
deleted file mode 100644
index e7cfebd605a..00000000000
--- a/db/schema_migrations/20200408132152
+++ /dev/null
@@ -1 +0,0 @@
-3ccb2170880e362c243b4071f7a9c3c1edafecbef54a09f66f2fdc95e8c936e6 \ No newline at end of file
diff --git a/db/schema_migrations/20200408133211 b/db/schema_migrations/20200408133211
deleted file mode 100644
index 417a58a5f1f..00000000000
--- a/db/schema_migrations/20200408133211
+++ /dev/null
@@ -1 +0,0 @@
-6f780f20897959d4966b5a622cede02ce37b8b89d99f5cbf326cf2704f7f9164 \ No newline at end of file
diff --git a/db/schema_migrations/20200408153842 b/db/schema_migrations/20200408153842
deleted file mode 100644
index 7c54b8f6023..00000000000
--- a/db/schema_migrations/20200408153842
+++ /dev/null
@@ -1 +0,0 @@
-329f5b831d7285973819051c68bb56593f7d755792e745d16781bb947c5f3a24 \ No newline at end of file
diff --git a/db/schema_migrations/20200408154331 b/db/schema_migrations/20200408154331
deleted file mode 100644
index b499cb0c75f..00000000000
--- a/db/schema_migrations/20200408154331
+++ /dev/null
@@ -1 +0,0 @@
-c49fc5d4e91ada6606d2a2823d214bcb8ad6d383778555a0eb881ebc042feeae \ No newline at end of file
diff --git a/db/schema_migrations/20200408154349 b/db/schema_migrations/20200408154349
deleted file mode 100644
index d30aae8e990..00000000000
--- a/db/schema_migrations/20200408154349
+++ /dev/null
@@ -1 +0,0 @@
-c65e4a9d015b0cc188c84b18bbd66b45d76d2d281f0d378946b8519705428350 \ No newline at end of file
diff --git a/db/schema_migrations/20200408154411 b/db/schema_migrations/20200408154411
deleted file mode 100644
index fe885df8f9b..00000000000
--- a/db/schema_migrations/20200408154411
+++ /dev/null
@@ -1 +0,0 @@
-13f95e797975de6456f30301cfc670f411c15470966afb9df83fa2a734edc4cc \ No newline at end of file
diff --git a/db/schema_migrations/20200408154428 b/db/schema_migrations/20200408154428
deleted file mode 100644
index 0d464c5841a..00000000000
--- a/db/schema_migrations/20200408154428
+++ /dev/null
@@ -1 +0,0 @@
-cc52aced123adb89714f854c9f81166d4fd2f5b9c40222163fc7ae65266f0b0f \ No newline at end of file
diff --git a/db/schema_migrations/20200408154455 b/db/schema_migrations/20200408154455
deleted file mode 100644
index 874ee92d3a9..00000000000
--- a/db/schema_migrations/20200408154455
+++ /dev/null
@@ -1 +0,0 @@
-4030a039abadc6200026c82a3a1a1a0731818fb21c2bf456ed2aa7e89b4cc201 \ No newline at end of file
diff --git a/db/schema_migrations/20200408154533 b/db/schema_migrations/20200408154533
deleted file mode 100644
index bb8b13b28e8..00000000000
--- a/db/schema_migrations/20200408154533
+++ /dev/null
@@ -1 +0,0 @@
-937d505687e4d4e2ebd531a02ef2fc1ea6ce3c8f281f859a4e97b3b9f8d53dfb \ No newline at end of file
diff --git a/db/schema_migrations/20200408154604 b/db/schema_migrations/20200408154604
deleted file mode 100644
index 93b5dc3d3a7..00000000000
--- a/db/schema_migrations/20200408154604
+++ /dev/null
@@ -1 +0,0 @@
-49d34581b0a36a39acf5473bb6b90c66adbdc854b755ca4881cab31a4589cede \ No newline at end of file
diff --git a/db/schema_migrations/20200408154624 b/db/schema_migrations/20200408154624
deleted file mode 100644
index acdaafd630f..00000000000
--- a/db/schema_migrations/20200408154624
+++ /dev/null
@@ -1 +0,0 @@
-e35b8efc06c3e9f15a21d9dacf5b2b0694439bc333fd46283d010d7e8dbce227 \ No newline at end of file
diff --git a/db/schema_migrations/20200408175424 b/db/schema_migrations/20200408175424
deleted file mode 100644
index 5134721870e..00000000000
--- a/db/schema_migrations/20200408175424
+++ /dev/null
@@ -1 +0,0 @@
-5a10ec51a9a1eec842931ccbc184988dfad86e1c212fccb61fbc3f59a22fbc33 \ No newline at end of file
diff --git a/db/schema_migrations/20200408212219 b/db/schema_migrations/20200408212219
deleted file mode 100644
index 04c5dae1424..00000000000
--- a/db/schema_migrations/20200408212219
+++ /dev/null
@@ -1 +0,0 @@
-41f095068e12a277174d45e10dbc60cd2104af2f8cfb5d4b82a94b57e3957c44 \ No newline at end of file
diff --git a/db/schema_migrations/20200409085956 b/db/schema_migrations/20200409085956
deleted file mode 100644
index beaa92bdd00..00000000000
--- a/db/schema_migrations/20200409085956
+++ /dev/null
@@ -1 +0,0 @@
-7cabe8105e1714e3387577420fafa06c418219e31c895803fa97908e2cf5b3b2 \ No newline at end of file
diff --git a/db/schema_migrations/20200409105455 b/db/schema_migrations/20200409105455
deleted file mode 100644
index 80aac192a39..00000000000
--- a/db/schema_migrations/20200409105455
+++ /dev/null
@@ -1 +0,0 @@
-5d412bb94282f7ab28848e6f96b9f18eef00ffe5913a33d2c7416a09251ae7c7 \ No newline at end of file
diff --git a/db/schema_migrations/20200409105456 b/db/schema_migrations/20200409105456
deleted file mode 100644
index 20f393625f3..00000000000
--- a/db/schema_migrations/20200409105456
+++ /dev/null
@@ -1 +0,0 @@
-a4a79070cd18c46575e2f9c6d2a798fc8152fbbc0a923244b82b8151d3bf680a \ No newline at end of file
diff --git a/db/schema_migrations/20200409211607 b/db/schema_migrations/20200409211607
deleted file mode 100644
index d7af855a6bd..00000000000
--- a/db/schema_migrations/20200409211607
+++ /dev/null
@@ -1 +0,0 @@
-0468ea64248cb0fdf9acfed9aeff7fd05875dd505b548cfd92e195a8cc82668b \ No newline at end of file
diff --git a/db/schema_migrations/20200410104828 b/db/schema_migrations/20200410104828
deleted file mode 100644
index 665be131b9a..00000000000
--- a/db/schema_migrations/20200410104828
+++ /dev/null
@@ -1 +0,0 @@
-2efdbd11929ce0164c5a035cb7e1d9a386f1bf375aa0dbc08e8bdc2c5788eebf \ No newline at end of file
diff --git a/db/schema_migrations/20200410232012 b/db/schema_migrations/20200410232012
deleted file mode 100644
index 54336ee1c13..00000000000
--- a/db/schema_migrations/20200410232012
+++ /dev/null
@@ -1 +0,0 @@
-f8b29495edc391d3df303356ad6f6219bdfbe2d5655330030b229ab8ccabbc9c \ No newline at end of file
diff --git a/db/schema_migrations/20200411125656 b/db/schema_migrations/20200411125656
deleted file mode 100644
index 9e30c747d19..00000000000
--- a/db/schema_migrations/20200411125656
+++ /dev/null
@@ -1 +0,0 @@
-8dcfe2eb5889767ce2011f9a1a130a7fe208a124f61134d067ec42b5dc021be3 \ No newline at end of file
diff --git a/db/schema_migrations/20200413072059 b/db/schema_migrations/20200413072059
deleted file mode 100644
index ce70578ffc0..00000000000
--- a/db/schema_migrations/20200413072059
+++ /dev/null
@@ -1 +0,0 @@
-f16f0227df3242e1bc4dd71c9dc014345ba9446ba7ab6053b156aef4620488ef \ No newline at end of file
diff --git a/db/schema_migrations/20200413230056 b/db/schema_migrations/20200413230056
deleted file mode 100644
index d352a8e8d92..00000000000
--- a/db/schema_migrations/20200413230056
+++ /dev/null
@@ -1 +0,0 @@
-518f58c0edd4c6176c07d83739d4b990ed3cae490441be55bbdcee80ade127bb \ No newline at end of file
diff --git a/db/schema_migrations/20200414112444 b/db/schema_migrations/20200414112444
deleted file mode 100644
index 202ab7b6f48..00000000000
--- a/db/schema_migrations/20200414112444
+++ /dev/null
@@ -1 +0,0 @@
-9693bca9cb23dcac4b35289ccb62b2ef154476a7460958cb16202f490bbfaf99 \ No newline at end of file
diff --git a/db/schema_migrations/20200414114611 b/db/schema_migrations/20200414114611
deleted file mode 100644
index 5841d6c47be..00000000000
--- a/db/schema_migrations/20200414114611
+++ /dev/null
@@ -1 +0,0 @@
-130600efce08e1dcac88785730ae99b924d484c5314d124998aaff32123490a3 \ No newline at end of file
diff --git a/db/schema_migrations/20200414115801 b/db/schema_migrations/20200414115801
deleted file mode 100644
index ea087a6d98a..00000000000
--- a/db/schema_migrations/20200414115801
+++ /dev/null
@@ -1 +0,0 @@
-e333b6dc2dfc70a82b8573fba748f7f1dcfdf92314657ca2bc98816afce91935 \ No newline at end of file
diff --git a/db/schema_migrations/20200414144547 b/db/schema_migrations/20200414144547
deleted file mode 100644
index 392d4f56b3a..00000000000
--- a/db/schema_migrations/20200414144547
+++ /dev/null
@@ -1 +0,0 @@
-e77b105a041f8dbec55236722f253c089f14f98997b28dc2a43617bfd9cd9b39 \ No newline at end of file
diff --git a/db/schema_migrations/20200415153154 b/db/schema_migrations/20200415153154
deleted file mode 100644
index efbdccfdda7..00000000000
--- a/db/schema_migrations/20200415153154
+++ /dev/null
@@ -1 +0,0 @@
-e288357c25540ce6b9f7e38fcb5e49585fc26929db40c71c14737999987855c1 \ No newline at end of file
diff --git a/db/schema_migrations/20200415160722 b/db/schema_migrations/20200415160722
deleted file mode 100644
index 1252b3a5ab2..00000000000
--- a/db/schema_migrations/20200415160722
+++ /dev/null
@@ -1 +0,0 @@
-c3d28ed4b2eb271d918a1eef1a4cfc0af302f4c8852773db9075d692b1691971 \ No newline at end of file
diff --git a/db/schema_migrations/20200415161021 b/db/schema_migrations/20200415161021
deleted file mode 100644
index c7a0fb6144d..00000000000
--- a/db/schema_migrations/20200415161021
+++ /dev/null
@@ -1 +0,0 @@
-731f7fa44d1b86ed619b7a7e4bd1fad6a943cf84a66b973b95581ae6d7b4a1db \ No newline at end of file
diff --git a/db/schema_migrations/20200415161206 b/db/schema_migrations/20200415161206
deleted file mode 100644
index 8d5b41dd105..00000000000
--- a/db/schema_migrations/20200415161206
+++ /dev/null
@@ -1 +0,0 @@
-eb9abab7fe4e3dd07a8995c3c9f514c13c3dbf4d49b1c100722fc9ada3351d2e \ No newline at end of file
diff --git a/db/schema_migrations/20200415192656 b/db/schema_migrations/20200415192656
deleted file mode 100644
index 859f70b279c..00000000000
--- a/db/schema_migrations/20200415192656
+++ /dev/null
@@ -1 +0,0 @@
-bc728b4d00992542a86324b0fc054ef435c9f35ccb5c31d74e9eef22fc8c03a7 \ No newline at end of file
diff --git a/db/schema_migrations/20200415203024 b/db/schema_migrations/20200415203024
deleted file mode 100644
index 7ac44656255..00000000000
--- a/db/schema_migrations/20200415203024
+++ /dev/null
@@ -1 +0,0 @@
-2fbdc8f9d10f9fbbbd1216b0a43d43183b659e7bcff7ee141d76a16100569005 \ No newline at end of file
diff --git a/db/schema_migrations/20200416005331 b/db/schema_migrations/20200416005331
deleted file mode 100644
index 959c63e1054..00000000000
--- a/db/schema_migrations/20200416005331
+++ /dev/null
@@ -1 +0,0 @@
-262e32b88e88bba1e7133cf002ee4a2209b23b0726b3ad1952a108ccdcf8802b \ No newline at end of file
diff --git a/db/schema_migrations/20200416111111 b/db/schema_migrations/20200416111111
deleted file mode 100644
index 5dacc01d27b..00000000000
--- a/db/schema_migrations/20200416111111
+++ /dev/null
@@ -1 +0,0 @@
-d2c801f6867b16ccd0a20217e0c76a6c689e2fc7c560256460734c91a427e760 \ No newline at end of file
diff --git a/db/schema_migrations/20200416120128 b/db/schema_migrations/20200416120128
deleted file mode 100644
index 14eef050991..00000000000
--- a/db/schema_migrations/20200416120128
+++ /dev/null
@@ -1 +0,0 @@
-8d4b95f1e5aac6d9079b4e4801258259314327baefcd63a5aa50ed05b2450cd0 \ No newline at end of file
diff --git a/db/schema_migrations/20200416120354 b/db/schema_migrations/20200416120354
deleted file mode 100644
index 6987eb606ac..00000000000
--- a/db/schema_migrations/20200416120354
+++ /dev/null
@@ -1 +0,0 @@
-c2f2dadbbff62e1330c6ec10b0b0508bac0e92e780a0113915f348b164372ae7 \ No newline at end of file
diff --git a/db/schema_migrations/20200417044453 b/db/schema_migrations/20200417044453
deleted file mode 100644
index a1d8c20f8da..00000000000
--- a/db/schema_migrations/20200417044453
+++ /dev/null
@@ -1 +0,0 @@
-1f4f7f8c9e61381255a914449053586b7ef89b77c8ca6cc7aab3b0f37b746ada \ No newline at end of file
diff --git a/db/schema_migrations/20200417075843 b/db/schema_migrations/20200417075843
deleted file mode 100644
index 8d4daad0378..00000000000
--- a/db/schema_migrations/20200417075843
+++ /dev/null
@@ -1 +0,0 @@
-b8ce568841406f2422a34c93f7d02d9009fd35d1e3c1f7a21f71f6af1e745919 \ No newline at end of file
diff --git a/db/schema_migrations/20200417145946 b/db/schema_migrations/20200417145946
deleted file mode 100644
index 73d4647db5d..00000000000
--- a/db/schema_migrations/20200417145946
+++ /dev/null
@@ -1 +0,0 @@
-cf47ac4249d03e49851ef6506129939f476218856d5715a719c0b01f258e55f9 \ No newline at end of file
diff --git a/db/schema_migrations/20200420092011 b/db/schema_migrations/20200420092011
deleted file mode 100644
index b5c5d8e4cb0..00000000000
--- a/db/schema_migrations/20200420092011
+++ /dev/null
@@ -1 +0,0 @@
-57c25e79b952319b38b6d913ac1d1fd1252c006cc34c2140a96bcb573f67db36 \ No newline at end of file
diff --git a/db/schema_migrations/20200420094444 b/db/schema_migrations/20200420094444
deleted file mode 100644
index 6b430be98e7..00000000000
--- a/db/schema_migrations/20200420094444
+++ /dev/null
@@ -1 +0,0 @@
-ee3a22f9d26c2a51e09b45ef55564a9770ecb1b523873292cc5c484c961c3573 \ No newline at end of file
diff --git a/db/schema_migrations/20200420104303 b/db/schema_migrations/20200420104303
deleted file mode 100644
index 2be42260faf..00000000000
--- a/db/schema_migrations/20200420104303
+++ /dev/null
@@ -1 +0,0 @@
-b0c3b8fa8257874dd28b6057313390af9261ceb934f1b89e4812f23c23909c9c \ No newline at end of file
diff --git a/db/schema_migrations/20200420104323 b/db/schema_migrations/20200420104323
deleted file mode 100644
index 8335c344f01..00000000000
--- a/db/schema_migrations/20200420104323
+++ /dev/null
@@ -1 +0,0 @@
-c2729622353fec28de04009e1e14d99dd49cbd79ee9834b034858a851fb434e5 \ No newline at end of file
diff --git a/db/schema_migrations/20200420115948 b/db/schema_migrations/20200420115948
deleted file mode 100644
index c6bc76b5c43..00000000000
--- a/db/schema_migrations/20200420115948
+++ /dev/null
@@ -1 +0,0 @@
-d146fefc2c44e68a1067f504fd779328028b4e65a8aad840fff9c6f83fbb3a83 \ No newline at end of file
diff --git a/db/schema_migrations/20200420141733 b/db/schema_migrations/20200420141733
deleted file mode 100644
index e714da7d2c3..00000000000
--- a/db/schema_migrations/20200420141733
+++ /dev/null
@@ -1 +0,0 @@
-ac3ba795b92e8fa9d6d1d9be546f9f3464da8fc2ea4c8d317a64b3eec5631b7d \ No newline at end of file
diff --git a/db/schema_migrations/20200420162730 b/db/schema_migrations/20200420162730
deleted file mode 100644
index ea96207aba2..00000000000
--- a/db/schema_migrations/20200420162730
+++ /dev/null
@@ -1 +0,0 @@
-75bcc7394a5c99cfd3a7156ede94e5a8a561bbed2f7770333dbacdfd6fd30e28 \ No newline at end of file
diff --git a/db/schema_migrations/20200420172113 b/db/schema_migrations/20200420172113
deleted file mode 100644
index 9de48b9a489..00000000000
--- a/db/schema_migrations/20200420172113
+++ /dev/null
@@ -1 +0,0 @@
-9eb84b3a43ad13c2f3559ebf2ef78f8a5ef2eb78819e05db431dac387a6f3e08 \ No newline at end of file
diff --git a/db/schema_migrations/20200420172752 b/db/schema_migrations/20200420172752
deleted file mode 100644
index eac9c38d8fb..00000000000
--- a/db/schema_migrations/20200420172752
+++ /dev/null
@@ -1 +0,0 @@
-57313ed166bf63588d2465b015efb887cabfc0b85d7513c16e91effb42dda3d7 \ No newline at end of file
diff --git a/db/schema_migrations/20200420172927 b/db/schema_migrations/20200420172927
deleted file mode 100644
index f04bb675166..00000000000
--- a/db/schema_migrations/20200420172927
+++ /dev/null
@@ -1 +0,0 @@
-dbf703edbfba23f5ce02ef075136f059a3c16f61d6ad70f084a089f41abb3579 \ No newline at end of file
diff --git a/db/schema_migrations/20200420201933 b/db/schema_migrations/20200420201933
deleted file mode 100644
index fe300d98d2b..00000000000
--- a/db/schema_migrations/20200420201933
+++ /dev/null
@@ -1 +0,0 @@
-2996752313cdf23d29312892f13751b3e37afa60d8353e8ff87354c77b60fc27 \ No newline at end of file
diff --git a/db/schema_migrations/20200421054930 b/db/schema_migrations/20200421054930
deleted file mode 100644
index 9a2bbebd0fe..00000000000
--- a/db/schema_migrations/20200421054930
+++ /dev/null
@@ -1 +0,0 @@
-61b72a69db5bb30f4533807241bba767870e9d04edf5cf2d7439d6a6582d88bb \ No newline at end of file
diff --git a/db/schema_migrations/20200421054948 b/db/schema_migrations/20200421054948
deleted file mode 100644
index 168fa5e9589..00000000000
--- a/db/schema_migrations/20200421054948
+++ /dev/null
@@ -1 +0,0 @@
-5315f43f4049781962b042ce4372741b74585640c4fd82d954e7ef0ba39692cc \ No newline at end of file
diff --git a/db/schema_migrations/20200421092907 b/db/schema_migrations/20200421092907
deleted file mode 100644
index 06e6ee47e05..00000000000
--- a/db/schema_migrations/20200421092907
+++ /dev/null
@@ -1 +0,0 @@
-952580ab54ef8e7380f3c344f09943f484ddedaeeede5d5f891832d54b8c12b3 \ No newline at end of file
diff --git a/db/schema_migrations/20200421111005 b/db/schema_migrations/20200421111005
deleted file mode 100644
index a232b596dd7..00000000000
--- a/db/schema_migrations/20200421111005
+++ /dev/null
@@ -1 +0,0 @@
-99226197b1efc5669616bb66a19d82ea301bfb29450174b0ab461d8fa13c8a59 \ No newline at end of file
diff --git a/db/schema_migrations/20200421195234 b/db/schema_migrations/20200421195234
deleted file mode 100644
index a15e01cef69..00000000000
--- a/db/schema_migrations/20200421195234
+++ /dev/null
@@ -1 +0,0 @@
-f3cb8c96656e246470b6f60fdae16d517ffd986486f640e7ed83e7e5abd5586b \ No newline at end of file
diff --git a/db/schema_migrations/20200421233150 b/db/schema_migrations/20200421233150
deleted file mode 100644
index 873a18e0ebc..00000000000
--- a/db/schema_migrations/20200421233150
+++ /dev/null
@@ -1 +0,0 @@
-82f0d006e56af52b58fc8996729f4978f2aaa0611d546c5fff177952720d2b6b \ No newline at end of file
diff --git a/db/schema_migrations/20200422091541 b/db/schema_migrations/20200422091541
deleted file mode 100644
index dbe87f6ba3b..00000000000
--- a/db/schema_migrations/20200422091541
+++ /dev/null
@@ -1 +0,0 @@
-574914c2c2fa66d7d673eb112bf97a05819f4ffffebeab2af898ebcf701cd90a \ No newline at end of file
diff --git a/db/schema_migrations/20200422213749 b/db/schema_migrations/20200422213749
deleted file mode 100644
index 8a551ff5598..00000000000
--- a/db/schema_migrations/20200422213749
+++ /dev/null
@@ -1 +0,0 @@
-0383e827905b3dae8c489c7f7fafda7e77152eff3af27881d6b6f16091d78761 \ No newline at end of file
diff --git a/db/schema_migrations/20200423075720 b/db/schema_migrations/20200423075720
deleted file mode 100644
index 4c51f084dd3..00000000000
--- a/db/schema_migrations/20200423075720
+++ /dev/null
@@ -1 +0,0 @@
-cdbe8252533ee61c56822d625faae9ddb28f1ae95c76fc71b85a2ca3a95da356 \ No newline at end of file
diff --git a/db/schema_migrations/20200423080334 b/db/schema_migrations/20200423080334
deleted file mode 100644
index 8857680d4a3..00000000000
--- a/db/schema_migrations/20200423080334
+++ /dev/null
@@ -1 +0,0 @@
-6940b4bc344478480d8e048e0d036ddb9ad4edd6daf56b48a7cac5df3fbe6bf4 \ No newline at end of file
diff --git a/db/schema_migrations/20200423080607 b/db/schema_migrations/20200423080607
deleted file mode 100644
index 662d1c68c37..00000000000
--- a/db/schema_migrations/20200423080607
+++ /dev/null
@@ -1 +0,0 @@
-e283adde76a397d4fa3e843a7277e546fcfa158d8f92f4f50f517132244c6e84 \ No newline at end of file
diff --git a/db/schema_migrations/20200423081409 b/db/schema_migrations/20200423081409
deleted file mode 100644
index f6dbd4aa5ff..00000000000
--- a/db/schema_migrations/20200423081409
+++ /dev/null
@@ -1 +0,0 @@
-585a91a06cec65fbb89791df00a5b04a56617734d435bd64a7a6484f00fea509 \ No newline at end of file
diff --git a/db/schema_migrations/20200423081441 b/db/schema_migrations/20200423081441
deleted file mode 100644
index 831110c361f..00000000000
--- a/db/schema_migrations/20200423081441
+++ /dev/null
@@ -1 +0,0 @@
-f8a72dab94a79b4a9fb9d6a84dbe9248602cdcceafff775a37ee53078318dd43 \ No newline at end of file
diff --git a/db/schema_migrations/20200423081519 b/db/schema_migrations/20200423081519
deleted file mode 100644
index ccdab2b88b2..00000000000
--- a/db/schema_migrations/20200423081519
+++ /dev/null
@@ -1 +0,0 @@
-f6415849e3808390f7d760f31cb79f419ce04bc29ef4f1d39ca7f751de47b5d4 \ No newline at end of file
diff --git a/db/schema_migrations/20200423101529 b/db/schema_migrations/20200423101529
deleted file mode 100644
index bd0e92b0cc7..00000000000
--- a/db/schema_migrations/20200423101529
+++ /dev/null
@@ -1 +0,0 @@
-26750021476db448ca0cd22a8a4bc218d5b84e19b20202c9cf0a616461cc1ee1 \ No newline at end of file
diff --git a/db/schema_migrations/20200424043515 b/db/schema_migrations/20200424043515
deleted file mode 100644
index 40a53f2cd0d..00000000000
--- a/db/schema_migrations/20200424043515
+++ /dev/null
@@ -1 +0,0 @@
-c755d36c9e144a3bd6673bacadf24e2d34224c4de060b992dd589a52985ea337 \ No newline at end of file
diff --git a/db/schema_migrations/20200424050250 b/db/schema_migrations/20200424050250
deleted file mode 100644
index 72d64451361..00000000000
--- a/db/schema_migrations/20200424050250
+++ /dev/null
@@ -1 +0,0 @@
-2b2cd2e7101e8225dd177c9437c8fee2039dbca5c5f1558ce1a849d9799cc34c \ No newline at end of file
diff --git a/db/schema_migrations/20200424101920 b/db/schema_migrations/20200424101920
deleted file mode 100644
index 58be080faec..00000000000
--- a/db/schema_migrations/20200424101920
+++ /dev/null
@@ -1 +0,0 @@
-d8f66da9290be14f8885b39be93ef234244a5b9394991d32f1d35a587665d932 \ No newline at end of file
diff --git a/db/schema_migrations/20200424102023 b/db/schema_migrations/20200424102023
deleted file mode 100644
index 3aec6ddeac3..00000000000
--- a/db/schema_migrations/20200424102023
+++ /dev/null
@@ -1 +0,0 @@
-e82c4e3ce433cf563e23fddf1847157ab8d9b01d5a3a996b3983dade301518b7 \ No newline at end of file
diff --git a/db/schema_migrations/20200424135319 b/db/schema_migrations/20200424135319
deleted file mode 100644
index 0e16e201938..00000000000
--- a/db/schema_migrations/20200424135319
+++ /dev/null
@@ -1 +0,0 @@
-d8adbb1b062a124704891926d0c7088b50a9c1fa12cb0145bd19fcf5a3fb4d05 \ No newline at end of file
diff --git a/db/schema_migrations/20200427064130 b/db/schema_migrations/20200427064130
deleted file mode 100644
index 57595ecc200..00000000000
--- a/db/schema_migrations/20200427064130
+++ /dev/null
@@ -1 +0,0 @@
-aaec2551c3b6eb7f8ec345516c681ba4bc33eed9171093ab98799db20efe0e94 \ No newline at end of file
diff --git a/db/schema_migrations/20200428134356 b/db/schema_migrations/20200428134356
deleted file mode 100644
index 59b06c7e7db..00000000000
--- a/db/schema_migrations/20200428134356
+++ /dev/null
@@ -1 +0,0 @@
-6994c8b015d85acc19a440f7d2c6191e927c411eec9e9c1083356a4c598a28f8 \ No newline at end of file
diff --git a/db/schema_migrations/20200429001827 b/db/schema_migrations/20200429001827
deleted file mode 100644
index f74267fee7f..00000000000
--- a/db/schema_migrations/20200429001827
+++ /dev/null
@@ -1 +0,0 @@
-81f35115909806c412ed96487a7692e61df6e6c519d2ad3f95a6089cc48cedab \ No newline at end of file
diff --git a/db/schema_migrations/20200429002150 b/db/schema_migrations/20200429002150
deleted file mode 100644
index f6d9998ea64..00000000000
--- a/db/schema_migrations/20200429002150
+++ /dev/null
@@ -1 +0,0 @@
-0af3d8e0cc9efb4657e6ef93a213ba7edf3e383caf47ddd0809653cfb7418e55 \ No newline at end of file
diff --git a/db/schema_migrations/20200429015603 b/db/schema_migrations/20200429015603
deleted file mode 100644
index b6788efb6f7..00000000000
--- a/db/schema_migrations/20200429015603
+++ /dev/null
@@ -1 +0,0 @@
-ee8afc82ef3af2ec030696560fe195fc2056dddf80ec0cd908b454bd2378f2ae \ No newline at end of file
diff --git a/db/schema_migrations/20200429023324 b/db/schema_migrations/20200429023324
deleted file mode 100644
index 3758f11d8b1..00000000000
--- a/db/schema_migrations/20200429023324
+++ /dev/null
@@ -1 +0,0 @@
-809558d31a390cf0d3a9653c9acb167150311819845a81c57164f74e26545340 \ No newline at end of file
diff --git a/db/schema_migrations/20200429181335 b/db/schema_migrations/20200429181335
deleted file mode 100644
index e29e1758f54..00000000000
--- a/db/schema_migrations/20200429181335
+++ /dev/null
@@ -1 +0,0 @@
-292ba62e0296154a31a2a497bb26b67b83d08d236306939762e48e8f67c6b423 \ No newline at end of file
diff --git a/db/schema_migrations/20200429181955 b/db/schema_migrations/20200429181955
deleted file mode 100644
index dd94ec15a01..00000000000
--- a/db/schema_migrations/20200429181955
+++ /dev/null
@@ -1 +0,0 @@
-73a342805f9857917e059e95793aff5da3049f1e943a883a7546985a6293d9d7 \ No newline at end of file
diff --git a/db/schema_migrations/20200429182245 b/db/schema_migrations/20200429182245
deleted file mode 100644
index d88951fc011..00000000000
--- a/db/schema_migrations/20200429182245
+++ /dev/null
@@ -1 +0,0 @@
-3dd9cc90ac048f208d8a966c72e532c74dca9c60801b29f3fb77e37816f91f16 \ No newline at end of file
diff --git a/db/schema_migrations/20200430103158 b/db/schema_migrations/20200430103158
deleted file mode 100644
index 343599a6052..00000000000
--- a/db/schema_migrations/20200430103158
+++ /dev/null
@@ -1 +0,0 @@
-c4957bc449caee04886713439666755d826120c9d8e5f335ac6eae0b860aa9ba \ No newline at end of file
diff --git a/db/schema_migrations/20200430123614 b/db/schema_migrations/20200430123614
deleted file mode 100644
index 7ea1a7676c4..00000000000
--- a/db/schema_migrations/20200430123614
+++ /dev/null
@@ -1 +0,0 @@
-31dd2da9456eeec204e2008e78558aadf5d3172f66b3c640c87a0fb64e807080 \ No newline at end of file
diff --git a/db/schema_migrations/20200430130048 b/db/schema_migrations/20200430130048
deleted file mode 100644
index e0adbfdc131..00000000000
--- a/db/schema_migrations/20200430130048
+++ /dev/null
@@ -1 +0,0 @@
-4c6304f22783d1c7c142716f984d21b800d2e0c90896302c4861a1641732a805 \ No newline at end of file
diff --git a/db/schema_migrations/20200430174637 b/db/schema_migrations/20200430174637
deleted file mode 100644
index b0790a1bce5..00000000000
--- a/db/schema_migrations/20200430174637
+++ /dev/null
@@ -1 +0,0 @@
-e37a4bf461179c99adab8280d840439534d59ba317a12e1831390cd5f3ae7ef4 \ No newline at end of file
diff --git a/db/schema_migrations/20200504191813 b/db/schema_migrations/20200504191813
deleted file mode 100644
index 0f377a32906..00000000000
--- a/db/schema_migrations/20200504191813
+++ /dev/null
@@ -1 +0,0 @@
-b389d021c04ce2e3b8c35a2a829f0ab8c58ee8b2ab972ae1f7a8abb16a09670f \ No newline at end of file
diff --git a/db/schema_migrations/20200504200709 b/db/schema_migrations/20200504200709
deleted file mode 100644
index 780f3013fa7..00000000000
--- a/db/schema_migrations/20200504200709
+++ /dev/null
@@ -1 +0,0 @@
-976e0c4614b6986f654fca6158c6ed2edf5c4e1031192e4f073fa77179d07eda \ No newline at end of file
diff --git a/db/schema_migrations/20200505164958 b/db/schema_migrations/20200505164958
deleted file mode 100644
index 23a952990cb..00000000000
--- a/db/schema_migrations/20200505164958
+++ /dev/null
@@ -1 +0,0 @@
-b06f7fc8653259060ea2c227130ca3c87bdeba15cf721f21cf524e1658a61272 \ No newline at end of file
diff --git a/db/schema_migrations/20200505171834 b/db/schema_migrations/20200505171834
deleted file mode 100644
index f8b0dd22cd5..00000000000
--- a/db/schema_migrations/20200505171834
+++ /dev/null
@@ -1 +0,0 @@
-bc44ba4cb70c950ca3e8c3c63b73e431c266284dddc7bc8adb909570dfea0048 \ No newline at end of file
diff --git a/db/schema_migrations/20200505172405 b/db/schema_migrations/20200505172405
deleted file mode 100644
index 3c993eff67d..00000000000
--- a/db/schema_migrations/20200505172405
+++ /dev/null
@@ -1 +0,0 @@
-52c3872d632d45bfbcfe4be8a4e4579d135c4291c780950350d6650c54fd1708 \ No newline at end of file
diff --git a/db/schema_migrations/20200506085748 b/db/schema_migrations/20200506085748
deleted file mode 100644
index 9759b03a822..00000000000
--- a/db/schema_migrations/20200506085748
+++ /dev/null
@@ -1 +0,0 @@
-a1861b578967fdefdb15f3be93891c721e96692896f06c2d6198d4431c45cd13 \ No newline at end of file
diff --git a/db/schema_migrations/20200506125731 b/db/schema_migrations/20200506125731
deleted file mode 100644
index 6064f0a487d..00000000000
--- a/db/schema_migrations/20200506125731
+++ /dev/null
@@ -1 +0,0 @@
-d4cda8bcb5bccc1ebad9e6eaa6a4eeb5d0aca382d334fc103d23fe77556c4930 \ No newline at end of file
diff --git a/db/schema_migrations/20200506154421 b/db/schema_migrations/20200506154421
deleted file mode 100644
index 5875086b0e5..00000000000
--- a/db/schema_migrations/20200506154421
+++ /dev/null
@@ -1 +0,0 @@
-02205bcf95962023ca04392d7997f8546725c759660e641086812a2e98473224 \ No newline at end of file
diff --git a/db/schema_migrations/20200507221434 b/db/schema_migrations/20200507221434
deleted file mode 100644
index 3089e877e4c..00000000000
--- a/db/schema_migrations/20200507221434
+++ /dev/null
@@ -1 +0,0 @@
-fac210ae2e6a0d1ddcf3226271e61e5dfa308c23b349bf1641e3c09d9da2af37 \ No newline at end of file
diff --git a/db/schema_migrations/20200508021128 b/db/schema_migrations/20200508021128
deleted file mode 100644
index 3d8681a1849..00000000000
--- a/db/schema_migrations/20200508021128
+++ /dev/null
@@ -1 +0,0 @@
-f28fc16e9369913c2af69c613d5ceeb3fa210dea9314f50856875413e983bd4b \ No newline at end of file
diff --git a/db/schema_migrations/20200508050301 b/db/schema_migrations/20200508050301
deleted file mode 100644
index 880e30b0ed6..00000000000
--- a/db/schema_migrations/20200508050301
+++ /dev/null
@@ -1 +0,0 @@
-f4c503dacfe784392b0b75759d0927bdda501a01a9edac3b41a2f78ec12b5936 \ No newline at end of file
diff --git a/db/schema_migrations/20200508091106 b/db/schema_migrations/20200508091106
deleted file mode 100644
index d22f8d82bfc..00000000000
--- a/db/schema_migrations/20200508091106
+++ /dev/null
@@ -1 +0,0 @@
-7359db223f77da3309198c2cc50f52ff942427a622e42956c987a758d5c2093b \ No newline at end of file
diff --git a/db/schema_migrations/20200508140959 b/db/schema_migrations/20200508140959
deleted file mode 100644
index d5ecd77abd5..00000000000
--- a/db/schema_migrations/20200508140959
+++ /dev/null
@@ -1 +0,0 @@
-7696b248052522c8dd99ba8782c906a638bbdab894b455377f19d5fa3e6f7fd4 \ No newline at end of file
diff --git a/db/schema_migrations/20200508203901 b/db/schema_migrations/20200508203901
deleted file mode 100644
index 08f72372d02..00000000000
--- a/db/schema_migrations/20200508203901
+++ /dev/null
@@ -1 +0,0 @@
-849af945cca0656467a85b2037fd23d38fceba3588fbd053073a04ae20a3ed1f \ No newline at end of file
diff --git a/db/schema_migrations/20200509203901 b/db/schema_migrations/20200509203901
deleted file mode 100644
index f05f0f8ac7e..00000000000
--- a/db/schema_migrations/20200509203901
+++ /dev/null
@@ -1 +0,0 @@
-fb9054b82d996d4e005efa9c05d1544f6d433389e46b715897a3eb5dc84493b5 \ No newline at end of file
diff --git a/db/schema_migrations/20200510181937 b/db/schema_migrations/20200510181937
deleted file mode 100644
index 38d6b6c42a3..00000000000
--- a/db/schema_migrations/20200510181937
+++ /dev/null
@@ -1 +0,0 @@
-31f8b5061bcea304f623cfcf4803bbbd97219acaf82d587a03b2f420253285b1 \ No newline at end of file
diff --git a/db/schema_migrations/20200510182218 b/db/schema_migrations/20200510182218
deleted file mode 100644
index c944628b8ff..00000000000
--- a/db/schema_migrations/20200510182218
+++ /dev/null
@@ -1 +0,0 @@
-25290ca5a685ca8648a626adb62e45b42ea45d91163c4af13761c98804a83af6 \ No newline at end of file
diff --git a/db/schema_migrations/20200510182556 b/db/schema_migrations/20200510182556
deleted file mode 100644
index 0a58bb57500..00000000000
--- a/db/schema_migrations/20200510182556
+++ /dev/null
@@ -1 +0,0 @@
-c23711f8795738bcd41323bfc83512c97fd71ad016c95432b28388c877db55d5 \ No newline at end of file
diff --git a/db/schema_migrations/20200510182824 b/db/schema_migrations/20200510182824
deleted file mode 100644
index 071f2448f77..00000000000
--- a/db/schema_migrations/20200510182824
+++ /dev/null
@@ -1 +0,0 @@
-55cd25621eac293c9616e7f2b211cfd8ed7183721bc6601754b3b8aea8557543 \ No newline at end of file
diff --git a/db/schema_migrations/20200510183128 b/db/schema_migrations/20200510183128
deleted file mode 100644
index bee6fba9f18..00000000000
--- a/db/schema_migrations/20200510183128
+++ /dev/null
@@ -1 +0,0 @@
-59c8b5178a495e8f2f128c50e9adaef1ab53ace9f6a053fc0cacb04672837e05 \ No newline at end of file
diff --git a/db/schema_migrations/20200511080113 b/db/schema_migrations/20200511080113
deleted file mode 100644
index 6f7e5c3d900..00000000000
--- a/db/schema_migrations/20200511080113
+++ /dev/null
@@ -1 +0,0 @@
-7edf72fd93034612ae93ea1999e84bbe8bfa96c7e3844614cb4985a559e40810 \ No newline at end of file
diff --git a/db/schema_migrations/20200511083541 b/db/schema_migrations/20200511083541
deleted file mode 100644
index 3bcca26361e..00000000000
--- a/db/schema_migrations/20200511083541
+++ /dev/null
@@ -1 +0,0 @@
-ccede137ca157c5195d83e8c1af4e29c1f7370b19f7caa4069d334ba1f7ea3a7 \ No newline at end of file
diff --git a/db/schema_migrations/20200511092246 b/db/schema_migrations/20200511092246
deleted file mode 100644
index 83636dbd3e3..00000000000
--- a/db/schema_migrations/20200511092246
+++ /dev/null
@@ -1 +0,0 @@
-0827d802fb94f625878da1ee1bed367b6f4fea795d3effe15000d833c67a5a7f \ No newline at end of file
diff --git a/db/schema_migrations/20200511092505 b/db/schema_migrations/20200511092505
deleted file mode 100644
index 67c2d966ead..00000000000
--- a/db/schema_migrations/20200511092505
+++ /dev/null
@@ -1 +0,0 @@
-524cc3c6a25e12dd1fab7c16f13a0f3f28b7cfdb5d0c3669349ec12e61b54a98 \ No newline at end of file
diff --git a/db/schema_migrations/20200511092714 b/db/schema_migrations/20200511092714
deleted file mode 100644
index 253a9d827ea..00000000000
--- a/db/schema_migrations/20200511092714
+++ /dev/null
@@ -1 +0,0 @@
-8e3395ab9aaef740940cc9067860291410b5ce364769e95b0d04b676e14ef00b \ No newline at end of file
diff --git a/db/schema_migrations/20200511115430 b/db/schema_migrations/20200511115430
deleted file mode 100644
index 98fb6c7b313..00000000000
--- a/db/schema_migrations/20200511115430
+++ /dev/null
@@ -1 +0,0 @@
-0013e34270a2bb137fec0223cff7509db04ef686c792b78ca6c67668b8296c61 \ No newline at end of file
diff --git a/db/schema_migrations/20200511115431 b/db/schema_migrations/20200511115431
deleted file mode 100644
index 78b3fc574ed..00000000000
--- a/db/schema_migrations/20200511115431
+++ /dev/null
@@ -1 +0,0 @@
-f0d0f98fec3649f0b2f2040880d9afff8b10a0943bf289834796c9376ce87932 \ No newline at end of file
diff --git a/db/schema_migrations/20200511121549 b/db/schema_migrations/20200511121549
deleted file mode 100644
index ee9546a8a0c..00000000000
--- a/db/schema_migrations/20200511121549
+++ /dev/null
@@ -1 +0,0 @@
-5101e6b2791c43fb3636a8f95a66fa01825a7bb9e60ea3f5d89606e45d96e9c3 \ No newline at end of file
diff --git a/db/schema_migrations/20200511121610 b/db/schema_migrations/20200511121610
deleted file mode 100644
index ff13ce8c3e9..00000000000
--- a/db/schema_migrations/20200511121610
+++ /dev/null
@@ -1 +0,0 @@
-e951ce098f4190af2e34bb7c0d020efca9ecaa4299d593fa7f0b23125ba5ccac \ No newline at end of file
diff --git a/db/schema_migrations/20200511121620 b/db/schema_migrations/20200511121620
deleted file mode 100644
index aeb38bb19b1..00000000000
--- a/db/schema_migrations/20200511121620
+++ /dev/null
@@ -1 +0,0 @@
-13c7cfc19eba0b69d54eb3ac0b22eae489fb84c8472e3693f84b66b0c64b20b4 \ No newline at end of file
diff --git a/db/schema_migrations/20200511130129 b/db/schema_migrations/20200511130129
deleted file mode 100644
index d30619b5d5a..00000000000
--- a/db/schema_migrations/20200511130129
+++ /dev/null
@@ -1 +0,0 @@
-02e298e5f70427b5f1c74845dfc7ac93b31865dd2a5f431470fc34a9087a0e10 \ No newline at end of file
diff --git a/db/schema_migrations/20200511130130 b/db/schema_migrations/20200511130130
deleted file mode 100644
index d263f6418c5..00000000000
--- a/db/schema_migrations/20200511130130
+++ /dev/null
@@ -1 +0,0 @@
-edf2348492fed26ded2183de9a1154af18570804b8ce83a0ca56a8b0a6d8f3a6 \ No newline at end of file
diff --git a/db/schema_migrations/20200511145545 b/db/schema_migrations/20200511145545
deleted file mode 100644
index be1b94cbf48..00000000000
--- a/db/schema_migrations/20200511145545
+++ /dev/null
@@ -1 +0,0 @@
-50a8f2081d4d794a7b04ef4eec25f99863c2197770096d6999e2e5f18331390a \ No newline at end of file
diff --git a/db/schema_migrations/20200511162057 b/db/schema_migrations/20200511162057
deleted file mode 100644
index b58615221d1..00000000000
--- a/db/schema_migrations/20200511162057
+++ /dev/null
@@ -1 +0,0 @@
-ad166c70d93630ae54fa26b926dade885e7b530f3c8af6a2516d54e05cb38383 \ No newline at end of file
diff --git a/db/schema_migrations/20200511162115 b/db/schema_migrations/20200511162115
deleted file mode 100644
index 011592e64c8..00000000000
--- a/db/schema_migrations/20200511162115
+++ /dev/null
@@ -1 +0,0 @@
-b1a26c6b9924656a61637f221f1e81c0f1d6d782a2e558012f0caf436c92943f \ No newline at end of file
diff --git a/db/schema_migrations/20200511181027 b/db/schema_migrations/20200511181027
deleted file mode 100644
index a918c934d69..00000000000
--- a/db/schema_migrations/20200511181027
+++ /dev/null
@@ -1 +0,0 @@
-d3d5f1ac4411803a04ba7c32a254d1ff6112a3817c91769c2423892b870cc7f8 \ No newline at end of file
diff --git a/db/schema_migrations/20200511191027 b/db/schema_migrations/20200511191027
deleted file mode 100644
index bc2e5e2ae62..00000000000
--- a/db/schema_migrations/20200511191027
+++ /dev/null
@@ -1 +0,0 @@
-46a25f167afe98184717084ce2b893b55cd2849f38aee970bf39728602732588 \ No newline at end of file
diff --git a/db/schema_migrations/20200511208012 b/db/schema_migrations/20200511208012
deleted file mode 100644
index 5eb7c0085b8..00000000000
--- a/db/schema_migrations/20200511208012
+++ /dev/null
@@ -1 +0,0 @@
-0dfe02daa86fc37f067522b6af626cc2150010fc65e83d9430d29ee492f37b6f \ No newline at end of file
diff --git a/db/schema_migrations/20200511220023 b/db/schema_migrations/20200511220023
deleted file mode 100644
index f2316c579bc..00000000000
--- a/db/schema_migrations/20200511220023
+++ /dev/null
@@ -1 +0,0 @@
-b9fb78494d9aa1da1a90e0d4a308b574c21d627d30f4b4bfe358cd7bd8f1bbc1 \ No newline at end of file
diff --git a/db/schema_migrations/20200512085150 b/db/schema_migrations/20200512085150
deleted file mode 100644
index 735a2896f43..00000000000
--- a/db/schema_migrations/20200512085150
+++ /dev/null
@@ -1 +0,0 @@
-c8c83c508e1d54dfd540ca034ef6f3d67184fc513fb4ebab957597e0cd0293b2 \ No newline at end of file
diff --git a/db/schema_migrations/20200512160004 b/db/schema_migrations/20200512160004
deleted file mode 100644
index 16d459a6251..00000000000
--- a/db/schema_migrations/20200512160004
+++ /dev/null
@@ -1 +0,0 @@
-959399fcc81b0fd1d0df938ae8fc2eb24f5fbde88fbeb920292ada6452352e42 \ No newline at end of file
diff --git a/db/schema_migrations/20200512164334 b/db/schema_migrations/20200512164334
deleted file mode 100644
index 42ed77e7b36..00000000000
--- a/db/schema_migrations/20200512164334
+++ /dev/null
@@ -1 +0,0 @@
-c279d7992fc823dc59b62cc14c248db4aab93b603eefc157188f28a13c40508f \ No newline at end of file
diff --git a/db/schema_migrations/20200512195442 b/db/schema_migrations/20200512195442
deleted file mode 100644
index b5ecc583875..00000000000
--- a/db/schema_migrations/20200512195442
+++ /dev/null
@@ -1 +0,0 @@
-214b8a8898c418a1350e23cae443f9649f5a7e0d91ca2494ae8d8dac7f81b37b \ No newline at end of file
diff --git a/db/schema_migrations/20200513160930 b/db/schema_migrations/20200513160930
deleted file mode 100644
index 63cb8caf666..00000000000
--- a/db/schema_migrations/20200513160930
+++ /dev/null
@@ -1 +0,0 @@
-07e36e155a94cf8e71b92e77353509c9d3af781a6f973e0db2848780851ff24e \ No newline at end of file
diff --git a/db/schema_migrations/20200513171959 b/db/schema_migrations/20200513171959
deleted file mode 100644
index f10207a05f6..00000000000
--- a/db/schema_migrations/20200513171959
+++ /dev/null
@@ -1 +0,0 @@
-3fe17fba97304f7143dfdb0c315f87e549e7769723f19fa36288381d1fa9e2d8 \ No newline at end of file
diff --git a/db/schema_migrations/20200513224143 b/db/schema_migrations/20200513224143
deleted file mode 100644
index 06d601a4796..00000000000
--- a/db/schema_migrations/20200513224143
+++ /dev/null
@@ -1 +0,0 @@
-125ef36cc08c11062c00dc586b877bc0b9bda33c1be34ba15fad7ee87dbd0b55 \ No newline at end of file
diff --git a/db/schema_migrations/20200513234502 b/db/schema_migrations/20200513234502
deleted file mode 100644
index 0a40f501312..00000000000
--- a/db/schema_migrations/20200513234502
+++ /dev/null
@@ -1 +0,0 @@
-3cf8ea6787682d82c930779d2fb2068710cd429ae1f57b201c73784b216cb3e5 \ No newline at end of file
diff --git a/db/schema_migrations/20200513235347 b/db/schema_migrations/20200513235347
deleted file mode 100644
index b7b40661167..00000000000
--- a/db/schema_migrations/20200513235347
+++ /dev/null
@@ -1 +0,0 @@
-5fedf359a4f5bf15dbbadb13736bc96c46691f2c952a8cb6459f11c1ecb96400 \ No newline at end of file
diff --git a/db/schema_migrations/20200513235532 b/db/schema_migrations/20200513235532
deleted file mode 100644
index 2bab5e16dfb..00000000000
--- a/db/schema_migrations/20200513235532
+++ /dev/null
@@ -1 +0,0 @@
-877eda087e028dfb9bc838497bf6874d1b23b61353c335cb73bbd94f38889610 \ No newline at end of file
diff --git a/db/schema_migrations/20200514000009 b/db/schema_migrations/20200514000009
deleted file mode 100644
index 1a588cf3812..00000000000
--- a/db/schema_migrations/20200514000009
+++ /dev/null
@@ -1 +0,0 @@
-b9c29ad4b36dbea2e6b2406f56fec2c408845a24b9382bcc32d823fea7a3fbd1 \ No newline at end of file
diff --git a/db/schema_migrations/20200514000132 b/db/schema_migrations/20200514000132
deleted file mode 100644
index a87eb8c4b7a..00000000000
--- a/db/schema_migrations/20200514000132
+++ /dev/null
@@ -1 +0,0 @@
-e441ff2691a70304cda5489ac3e308116e4eaa59ba1dafd6f14f0323f595e982 \ No newline at end of file
diff --git a/db/schema_migrations/20200514000340 b/db/schema_migrations/20200514000340
deleted file mode 100644
index 465e1b97446..00000000000
--- a/db/schema_migrations/20200514000340
+++ /dev/null
@@ -1 +0,0 @@
-b67655bffd1e52005c4f4b997eee17c39b948b9c642a3e3a202d237d7419aaa0 \ No newline at end of file
diff --git a/db/schema_migrations/20200515152649 b/db/schema_migrations/20200515152649
deleted file mode 100644
index 3986afff437..00000000000
--- a/db/schema_migrations/20200515152649
+++ /dev/null
@@ -1 +0,0 @@
-34f0dc965b7f5c9b76a8b0bd7ca3721777c1f3e881c2f2b02806c7a74442343d \ No newline at end of file
diff --git a/db/schema_migrations/20200515153633 b/db/schema_migrations/20200515153633
deleted file mode 100644
index c65ea828aed..00000000000
--- a/db/schema_migrations/20200515153633
+++ /dev/null
@@ -1 +0,0 @@
-dd7fa34ca73822643533b3eb1ee8cf61503cd94ca180602b2263989f2326d7a2 \ No newline at end of file
diff --git a/db/schema_migrations/20200515155620 b/db/schema_migrations/20200515155620
deleted file mode 100644
index 480848a7f29..00000000000
--- a/db/schema_migrations/20200515155620
+++ /dev/null
@@ -1 +0,0 @@
-8fafc0f070f0a40c3ed9d2a25f3874fb5c525f3bcd77382be1947697157c4c2d \ No newline at end of file
diff --git a/db/schema_migrations/20200518091745 b/db/schema_migrations/20200518091745
deleted file mode 100644
index dd2d8c0a465..00000000000
--- a/db/schema_migrations/20200518091745
+++ /dev/null
@@ -1 +0,0 @@
-222bf026288f2704df4ce9c6a72615d13dae11fbf8eb50ec6ce9732dcfc6491b \ No newline at end of file
diff --git a/db/schema_migrations/20200518114540 b/db/schema_migrations/20200518114540
deleted file mode 100644
index 34329daf048..00000000000
--- a/db/schema_migrations/20200518114540
+++ /dev/null
@@ -1 +0,0 @@
-6b7996a6eda2e1b6be4c74825d0401ab88f25677caf016c7ee906c17a5f8f99a \ No newline at end of file
diff --git a/db/schema_migrations/20200518133123 b/db/schema_migrations/20200518133123
deleted file mode 100644
index 736654e9a9f..00000000000
--- a/db/schema_migrations/20200518133123
+++ /dev/null
@@ -1 +0,0 @@
-d713fc941751c192cfd6e5f9dcba7f562ccaf6ac850dac24ea2c51332a916c51 \ No newline at end of file
diff --git a/db/schema_migrations/20200519074709 b/db/schema_migrations/20200519074709
deleted file mode 100644
index 7e5385aec19..00000000000
--- a/db/schema_migrations/20200519074709
+++ /dev/null
@@ -1 +0,0 @@
-bc620d9056a0f615bcb3218d7a5abedbbdf380c9ee964fd50cea867fcbb138db \ No newline at end of file
diff --git a/db/schema_migrations/20200519101002 b/db/schema_migrations/20200519101002
deleted file mode 100644
index 205f5bc3747..00000000000
--- a/db/schema_migrations/20200519101002
+++ /dev/null
@@ -1 +0,0 @@
-746ec3b5e8beb0c87189c04e96974df3ce752e707981ef8564ed4a282d01f8e6 \ No newline at end of file
diff --git a/db/schema_migrations/20200519115908 b/db/schema_migrations/20200519115908
deleted file mode 100644
index cc084e06980..00000000000
--- a/db/schema_migrations/20200519115908
+++ /dev/null
@@ -1 +0,0 @@
-d2a660493f10af362663e5f6c843e4428c704ac842caeab80eacdf42f1d6a7e7 \ No newline at end of file
diff --git a/db/schema_migrations/20200519141534 b/db/schema_migrations/20200519141534
deleted file mode 100644
index c0a53a0e786..00000000000
--- a/db/schema_migrations/20200519141534
+++ /dev/null
@@ -1 +0,0 @@
-85d7059d7fb2703bb9474734d4b41508de8b0e3c630725b74163d268427b4760 \ No newline at end of file
diff --git a/db/schema_migrations/20200519171058 b/db/schema_migrations/20200519171058
deleted file mode 100644
index 1ac4d231079..00000000000
--- a/db/schema_migrations/20200519171058
+++ /dev/null
@@ -1 +0,0 @@
-ad14128704da92a4de51936af6444608331a4d4e960cdf894f3f0301b038fd4f \ No newline at end of file
diff --git a/db/schema_migrations/20200519194042 b/db/schema_migrations/20200519194042
deleted file mode 100644
index 737ec0d46cb..00000000000
--- a/db/schema_migrations/20200519194042
+++ /dev/null
@@ -1 +0,0 @@
-b232109c29d831b8cda9f4bacc2ab4cf4ff290cb6a27d8034c47aacd05b0e522 \ No newline at end of file
diff --git a/db/schema_migrations/20200519201128 b/db/schema_migrations/20200519201128
deleted file mode 100644
index b83727bfef9..00000000000
--- a/db/schema_migrations/20200519201128
+++ /dev/null
@@ -1 +0,0 @@
-94624ba1a2553ed94101de6c40b59ed74c559ae49703b96df72026f9c86ec85c \ No newline at end of file
diff --git a/db/schema_migrations/20200520103514 b/db/schema_migrations/20200520103514
deleted file mode 100644
index 77c8ae6c1d9..00000000000
--- a/db/schema_migrations/20200520103514
+++ /dev/null
@@ -1 +0,0 @@
-1b651eb548366c8c68424061b87e48e5b80e6794d9f911828c09057597dc800e \ No newline at end of file
diff --git a/db/schema_migrations/20200521022725 b/db/schema_migrations/20200521022725
deleted file mode 100644
index 52072620703..00000000000
--- a/db/schema_migrations/20200521022725
+++ /dev/null
@@ -1 +0,0 @@
-703dd07e6aca38d21c9a3bb84d21efd47758c7c4dc7aae6377b490ce5ba4da33 \ No newline at end of file
diff --git a/db/schema_migrations/20200521225327 b/db/schema_migrations/20200521225327
deleted file mode 100644
index 4d6876aee75..00000000000
--- a/db/schema_migrations/20200521225327
+++ /dev/null
@@ -1 +0,0 @@
-b0ddb00ddba5940228c4eabc0ed84ae298cd28e2076ef0317786278dcd4dbf76 \ No newline at end of file
diff --git a/db/schema_migrations/20200521225337 b/db/schema_migrations/20200521225337
deleted file mode 100644
index e022ae88110..00000000000
--- a/db/schema_migrations/20200521225337
+++ /dev/null
@@ -1 +0,0 @@
-e0a36200d9022157bf7cc29fa6142f6e25633ae5c8be0a664818ae5fc1c157f5 \ No newline at end of file
diff --git a/db/schema_migrations/20200521225346 b/db/schema_migrations/20200521225346
deleted file mode 100644
index 05dac61d4a7..00000000000
--- a/db/schema_migrations/20200521225346
+++ /dev/null
@@ -1 +0,0 @@
-6d17c3f483309605718f93ee0935200812b2bb148499458d0fc6842647febbc4 \ No newline at end of file
diff --git a/db/schema_migrations/20200522205606 b/db/schema_migrations/20200522205606
deleted file mode 100644
index dbf798737fa..00000000000
--- a/db/schema_migrations/20200522205606
+++ /dev/null
@@ -1 +0,0 @@
-4bb6c890509ef458734947f872bd0245fb39b479da890a7ee488ab9a8094331e \ No newline at end of file
diff --git a/db/schema_migrations/20200522235146 b/db/schema_migrations/20200522235146
deleted file mode 100644
index 3c3ca57887f..00000000000
--- a/db/schema_migrations/20200522235146
+++ /dev/null
@@ -1 +0,0 @@
-e7c2215d624d7d4a8efa58f2653f5806316de0c5b74e4a621c590044bdff1484 \ No newline at end of file
diff --git a/db/schema_migrations/20200524104346 b/db/schema_migrations/20200524104346
deleted file mode 100644
index b1d6cbad020..00000000000
--- a/db/schema_migrations/20200524104346
+++ /dev/null
@@ -1 +0,0 @@
-c1b2c436c64ef8e9c4ce0d0087a5a5047c2318a09fa82c33c6d3080eb5b55bc2 \ No newline at end of file
diff --git a/db/schema_migrations/20200525114553 b/db/schema_migrations/20200525114553
deleted file mode 100644
index 35f22221f56..00000000000
--- a/db/schema_migrations/20200525114553
+++ /dev/null
@@ -1 +0,0 @@
-788576927e66b178a41adda08faa729ab64a9624900dde8bfe219fb40f1bb3e7 \ No newline at end of file
diff --git a/db/schema_migrations/20200525121014 b/db/schema_migrations/20200525121014
deleted file mode 100644
index f11c80717c0..00000000000
--- a/db/schema_migrations/20200525121014
+++ /dev/null
@@ -1 +0,0 @@
-0ac42fbe9e91c3bcb4ac040aff6249f3911542fdb8e6274289066b23dfcdb957 \ No newline at end of file
diff --git a/db/schema_migrations/20200525144525 b/db/schema_migrations/20200525144525
deleted file mode 100644
index 902d62d58cc..00000000000
--- a/db/schema_migrations/20200525144525
+++ /dev/null
@@ -1 +0,0 @@
-49e2c7f0adb160687823b627607b56a813cb58ed0c529778e2100c5543e5f854 \ No newline at end of file
diff --git a/db/schema_migrations/20200526000407 b/db/schema_migrations/20200526000407
deleted file mode 100644
index 91573e5ba58..00000000000
--- a/db/schema_migrations/20200526000407
+++ /dev/null
@@ -1 +0,0 @@
-ed629ce7654a585ff6ad7d6f65a7beb4207a95b21084b37d5238b728b418f2e6 \ No newline at end of file
diff --git a/db/schema_migrations/20200526013844 b/db/schema_migrations/20200526013844
deleted file mode 100644
index b181bb520bf..00000000000
--- a/db/schema_migrations/20200526013844
+++ /dev/null
@@ -1 +0,0 @@
-962008c38cec92aaad64739883a549ba487aa8d00c5d3be5f755b3d8139341d8 \ No newline at end of file
diff --git a/db/schema_migrations/20200526115436 b/db/schema_migrations/20200526115436
deleted file mode 100644
index 5f071ffc5d1..00000000000
--- a/db/schema_migrations/20200526115436
+++ /dev/null
@@ -1 +0,0 @@
-ff746ede0d78ccc44e5d1bfecae298a5fb0018f37dfaf779687eda5c98987f5f \ No newline at end of file
diff --git a/db/schema_migrations/20200526120714 b/db/schema_migrations/20200526120714
deleted file mode 100644
index 683893f2834..00000000000
--- a/db/schema_migrations/20200526120714
+++ /dev/null
@@ -1 +0,0 @@
-b566f3dfd1fdb6b081e2a030027ad19910b2688bf68cefee246f3df41bda65d4 \ No newline at end of file
diff --git a/db/schema_migrations/20200526142550 b/db/schema_migrations/20200526142550
deleted file mode 100644
index 8986bc2c8bd..00000000000
--- a/db/schema_migrations/20200526142550
+++ /dev/null
@@ -1 +0,0 @@
-6df8ec2ce7c80b41cfccc324d2044ce67c5d60f2dfaf8c1aeede02ce0dc0ac4c \ No newline at end of file
diff --git a/db/schema_migrations/20200526153844 b/db/schema_migrations/20200526153844
deleted file mode 100644
index 543a5a1bfdf..00000000000
--- a/db/schema_migrations/20200526153844
+++ /dev/null
@@ -1 +0,0 @@
-17e38e020ccbcef20287930c0c60d4f265f273a99c8ad08f35a28cab295cc530 \ No newline at end of file
diff --git a/db/schema_migrations/20200526164946 b/db/schema_migrations/20200526164946
deleted file mode 100644
index 352e78d30ac..00000000000
--- a/db/schema_migrations/20200526164946
+++ /dev/null
@@ -1 +0,0 @@
-8e022fbe30ad181816a79a57a2432e6cf763e539a970860195a417d782c880f9 \ No newline at end of file
diff --git a/db/schema_migrations/20200526164947 b/db/schema_migrations/20200526164947
deleted file mode 100644
index a65ffd79b07..00000000000
--- a/db/schema_migrations/20200526164947
+++ /dev/null
@@ -1 +0,0 @@
-e5a4897450454f070950e55907232d3b986dcaac0142dcb23a66db40dac817ba \ No newline at end of file
diff --git a/db/schema_migrations/20200526193555 b/db/schema_migrations/20200526193555
deleted file mode 100644
index 18df757dd50..00000000000
--- a/db/schema_migrations/20200526193555
+++ /dev/null
@@ -1 +0,0 @@
-e50f2bfb991b4ceddf8a580608208402692ad25fcc33b71e5fa82960189882c0 \ No newline at end of file
diff --git a/db/schema_migrations/20200526231421 b/db/schema_migrations/20200526231421
deleted file mode 100644
index b70feb4a080..00000000000
--- a/db/schema_migrations/20200526231421
+++ /dev/null
@@ -1 +0,0 @@
-1b0d5c7b955f25f1f9e86e0315118cd3b9224c329e1b7eae5682292d03878793 \ No newline at end of file
diff --git a/db/schema_migrations/20200527092027 b/db/schema_migrations/20200527092027
deleted file mode 100644
index c4db74d55d4..00000000000
--- a/db/schema_migrations/20200527092027
+++ /dev/null
@@ -1 +0,0 @@
-773f9f6f2b0bd6704485298a80f68b1d68ed28f5178b93bfebc97d2d0c09eb91 \ No newline at end of file
diff --git a/db/schema_migrations/20200527094322 b/db/schema_migrations/20200527094322
deleted file mode 100644
index 86e0b13775a..00000000000
--- a/db/schema_migrations/20200527094322
+++ /dev/null
@@ -1 +0,0 @@
-9efce01d2a677ad03e3aa80d3670a4d8bbab413f61ee89da860d2f92734d0298 \ No newline at end of file
diff --git a/db/schema_migrations/20200527095401 b/db/schema_migrations/20200527095401
deleted file mode 100644
index c9956f361d8..00000000000
--- a/db/schema_migrations/20200527095401
+++ /dev/null
@@ -1 +0,0 @@
-a4ee1c8233f9445b1635ba89d71820cbdd515a4b1512ab40ab58c43cba44217b \ No newline at end of file
diff --git a/db/schema_migrations/20200527135313 b/db/schema_migrations/20200527135313
deleted file mode 100644
index ff955b0b183..00000000000
--- a/db/schema_migrations/20200527135313
+++ /dev/null
@@ -1 +0,0 @@
-1829a85be1a8bfca9526bbc2eaec4b2f5482c41c9d665bb70846a2d97ab8a351 \ No newline at end of file
diff --git a/db/schema_migrations/20200527151413 b/db/schema_migrations/20200527151413
deleted file mode 100644
index 3cd1fd7fefe..00000000000
--- a/db/schema_migrations/20200527151413
+++ /dev/null
@@ -1 +0,0 @@
-7690399e7eb02b4aa906848d6bd5e6992d31df73ab78e8a3654102b11fc05409 \ No newline at end of file
diff --git a/db/schema_migrations/20200527152116 b/db/schema_migrations/20200527152116
deleted file mode 100644
index d701d29cf19..00000000000
--- a/db/schema_migrations/20200527152116
+++ /dev/null
@@ -1 +0,0 @@
-99c0d72b64f7155f845bd6d40dd572ee21106977257a437fda0c7647faa99a10 \ No newline at end of file
diff --git a/db/schema_migrations/20200527152657 b/db/schema_migrations/20200527152657
deleted file mode 100644
index b5c79e49e79..00000000000
--- a/db/schema_migrations/20200527152657
+++ /dev/null
@@ -1 +0,0 @@
-c87f004bc74eafe293c540c9a192808b53ca8a8fe8bd4e48a2a0603f980c7cf4 \ No newline at end of file
diff --git a/db/schema_migrations/20200527170649 b/db/schema_migrations/20200527170649
deleted file mode 100644
index fcbf71c8608..00000000000
--- a/db/schema_migrations/20200527170649
+++ /dev/null
@@ -1 +0,0 @@
-7e494700bbbd596b9c865911c8bc1b1f8b62189b7afb2f8166210c09ba051a74 \ No newline at end of file
diff --git a/db/schema_migrations/20200527211000 b/db/schema_migrations/20200527211000
deleted file mode 100644
index 7a3c79c9c40..00000000000
--- a/db/schema_migrations/20200527211000
+++ /dev/null
@@ -1 +0,0 @@
-d8967bc2dfd52ee1d21ea15e46e88fb6f62325e420d5914cee584e8653ebb538 \ No newline at end of file
diff --git a/db/schema_migrations/20200527211605 b/db/schema_migrations/20200527211605
deleted file mode 100644
index 3ffde83b144..00000000000
--- a/db/schema_migrations/20200527211605
+++ /dev/null
@@ -1 +0,0 @@
-c99ef19e63223bac3271f2bfe4913ba6a97aaaff043c5eab19b990ddf2f10e9a \ No newline at end of file
diff --git a/db/schema_migrations/20200528054112 b/db/schema_migrations/20200528054112
deleted file mode 100644
index 25177d4d981..00000000000
--- a/db/schema_migrations/20200528054112
+++ /dev/null
@@ -1 +0,0 @@
-e3e48bce6e9066d57290fb006bba3491b5844fb15193c319848f5d7d23c85a87 \ No newline at end of file
diff --git a/db/schema_migrations/20200528123703 b/db/schema_migrations/20200528123703
deleted file mode 100644
index 29545b35b3d..00000000000
--- a/db/schema_migrations/20200528123703
+++ /dev/null
@@ -1 +0,0 @@
-1cdeb5966809dbc01963d7359375d9c11dc4516095c46b35c945f619f8ab1ba5 \ No newline at end of file
diff --git a/db/schema_migrations/20200528125905 b/db/schema_migrations/20200528125905
deleted file mode 100644
index ff589220a04..00000000000
--- a/db/schema_migrations/20200528125905
+++ /dev/null
@@ -1 +0,0 @@
-1d1990dabc9e6ac59c82e215edcd97dac99db39258b23dfdfa8875f26978538a \ No newline at end of file
diff --git a/db/schema_migrations/20200528171933 b/db/schema_migrations/20200528171933
deleted file mode 100644
index db10e3cd961..00000000000
--- a/db/schema_migrations/20200528171933
+++ /dev/null
@@ -1 +0,0 @@
-409ecb990f4e7ad2df3b33e12abe757e55c07de74e5226fc334527a67c76f6fa \ No newline at end of file
diff --git a/db/schema_migrations/20200601120434 b/db/schema_migrations/20200601120434
deleted file mode 100644
index efe42e90fa6..00000000000
--- a/db/schema_migrations/20200601120434
+++ /dev/null
@@ -1 +0,0 @@
-dd942c07b653630c6df0c6430061bacc2991829c73ebdd0b8c7ce1ae5102301e \ No newline at end of file
diff --git a/db/schema_migrations/20200601210148 b/db/schema_migrations/20200601210148
deleted file mode 100644
index b7371a1932c..00000000000
--- a/db/schema_migrations/20200601210148
+++ /dev/null
@@ -1 +0,0 @@
-53d6c268f74766f7fd18e480918206ba7fdaa5bbcfcfa552d839d82ccf4c5a77 \ No newline at end of file
diff --git a/db/schema_migrations/20200602013900 b/db/schema_migrations/20200602013900
deleted file mode 100644
index c174fd8210d..00000000000
--- a/db/schema_migrations/20200602013900
+++ /dev/null
@@ -1 +0,0 @@
-3a23025aa0d3cda32aaeaa9fb9ce1fc06fb02ce26333e8c7d7a9ee539ad3903f \ No newline at end of file
diff --git a/db/schema_migrations/20200602013901 b/db/schema_migrations/20200602013901
deleted file mode 100644
index 76b825a1914..00000000000
--- a/db/schema_migrations/20200602013901
+++ /dev/null
@@ -1 +0,0 @@
-e6ebaebe88062d9ead773d7e54de6776be032a740f005470391f1449aa78e169 \ No newline at end of file
diff --git a/db/schema_migrations/20200602143020 b/db/schema_migrations/20200602143020
deleted file mode 100644
index a14ed488d58..00000000000
--- a/db/schema_migrations/20200602143020
+++ /dev/null
@@ -1 +0,0 @@
-4d8fa1902ed7bb0b98ec57a09ec401f9a60a9a67d3341f288c5eef4674590931 \ No newline at end of file
diff --git a/db/schema_migrations/20200603073101 b/db/schema_migrations/20200603073101
deleted file mode 100644
index 7f121b151d1..00000000000
--- a/db/schema_migrations/20200603073101
+++ /dev/null
@@ -1 +0,0 @@
-aa071d4496df240cd7cadb3bcc3c7a5e3debb1c889918793a505941f0307bdf3 \ No newline at end of file
diff --git a/db/schema_migrations/20200603180338 b/db/schema_migrations/20200603180338
deleted file mode 100644
index 71fc063c510..00000000000
--- a/db/schema_migrations/20200603180338
+++ /dev/null
@@ -1 +0,0 @@
-f9aebf8a5b5ca29fc087131adc6b5ccfab31b6a6322b1199011bc8211dc12974 \ No newline at end of file
diff --git a/db/schema_migrations/20200604001128 b/db/schema_migrations/20200604001128
deleted file mode 100644
index cdd8b00129c..00000000000
--- a/db/schema_migrations/20200604001128
+++ /dev/null
@@ -1 +0,0 @@
-151422dcec633fd512162a3b969689195a91199d0858c2128232b6fbc12c75f8 \ No newline at end of file
diff --git a/db/schema_migrations/20200604143628 b/db/schema_migrations/20200604143628
deleted file mode 100644
index c68e6a41c1c..00000000000
--- a/db/schema_migrations/20200604143628
+++ /dev/null
@@ -1 +0,0 @@
-5abe7187c73ad8127051c41de7c56aee5a55422350712532bba5dc802ddd1775 \ No newline at end of file
diff --git a/db/schema_migrations/20200604145731 b/db/schema_migrations/20200604145731
deleted file mode 100644
index 77f4aaf15fc..00000000000
--- a/db/schema_migrations/20200604145731
+++ /dev/null
@@ -1 +0,0 @@
-10f132808cd13198e8832c2c45b34fa374b029b138583f9609a2600bf204a37f \ No newline at end of file
diff --git a/db/schema_migrations/20200604174544 b/db/schema_migrations/20200604174544
deleted file mode 100644
index 8ade298b76b..00000000000
--- a/db/schema_migrations/20200604174544
+++ /dev/null
@@ -1 +0,0 @@
-38d5bdea037b1e5031577851c1fae3354676c77a869b90b9213b36245401dfab \ No newline at end of file
diff --git a/db/schema_migrations/20200604174558 b/db/schema_migrations/20200604174558
deleted file mode 100644
index 969442ca1eb..00000000000
--- a/db/schema_migrations/20200604174558
+++ /dev/null
@@ -1 +0,0 @@
-6879996c3cb53326466d3b967925018facf4c63ad4198a93363f67f8eb614aff \ No newline at end of file
diff --git a/db/schema_migrations/20200605003204 b/db/schema_migrations/20200605003204
deleted file mode 100644
index c2bb57cf458..00000000000
--- a/db/schema_migrations/20200605003204
+++ /dev/null
@@ -1 +0,0 @@
-cd7ea73ae9fc168de4f088395d86e2187e6c7184ed531cce767a8414e764a5d8 \ No newline at end of file
diff --git a/db/schema_migrations/20200605093113 b/db/schema_migrations/20200605093113
deleted file mode 100644
index c63fed7a87c..00000000000
--- a/db/schema_migrations/20200605093113
+++ /dev/null
@@ -1 +0,0 @@
-1dbfc16e8ac9b5ef1d9dda60a7895d084db729bc34b855a2726e62b118e20360 \ No newline at end of file
diff --git a/db/schema_migrations/20200605160806 b/db/schema_migrations/20200605160806
deleted file mode 100644
index bf23d38f2fd..00000000000
--- a/db/schema_migrations/20200605160806
+++ /dev/null
@@ -1 +0,0 @@
-a35514bb4cde5aab9cbd38f19c9d371a091eae486d4d8e994767244c09952cbb \ No newline at end of file
diff --git a/db/schema_migrations/20200605160836 b/db/schema_migrations/20200605160836
deleted file mode 100644
index e77da6e5319..00000000000
--- a/db/schema_migrations/20200605160836
+++ /dev/null
@@ -1 +0,0 @@
-010ff35889dc018c44db523f6f64fd36dd5550292774273d5d57a9c23a96347d \ No newline at end of file
diff --git a/db/schema_migrations/20200605160851 b/db/schema_migrations/20200605160851
deleted file mode 100644
index fc8f26a2a36..00000000000
--- a/db/schema_migrations/20200605160851
+++ /dev/null
@@ -1 +0,0 @@
-ade5567a3dbc449ebfa8c615ad312df874e2baf7fac12d1cdec97a7bfb4f8c49 \ No newline at end of file
diff --git a/db/schema_migrations/20200607223047 b/db/schema_migrations/20200607223047
deleted file mode 100644
index 807592352e5..00000000000
--- a/db/schema_migrations/20200607223047
+++ /dev/null
@@ -1 +0,0 @@
-64e38a5f5a76b549f7e527c34a3e9cf1861ada7e0658408241d1b27fa8d24bb4 \ No newline at end of file
diff --git a/db/schema_migrations/20200607235435 b/db/schema_migrations/20200607235435
deleted file mode 100644
index 462e8438173..00000000000
--- a/db/schema_migrations/20200607235435
+++ /dev/null
@@ -1 +0,0 @@
-67f29055e5ea13ebddcd420e30c806eaebbfb8c224d02a2c5fbaa51eb004c9dd \ No newline at end of file
diff --git a/db/schema_migrations/20200608072931 b/db/schema_migrations/20200608072931
deleted file mode 100644
index 7ab318d89da..00000000000
--- a/db/schema_migrations/20200608072931
+++ /dev/null
@@ -1 +0,0 @@
-9ba0ccfb2ba9a510c04297adab70f1edb47ecb7a65569c944531b5ff82c6e3c1 \ No newline at end of file
diff --git a/db/schema_migrations/20200608075553 b/db/schema_migrations/20200608075553
deleted file mode 100644
index 49bf37f6281..00000000000
--- a/db/schema_migrations/20200608075553
+++ /dev/null
@@ -1 +0,0 @@
-d71e8e8523a101da234f0ae44ef89baa45f397d021a06cfb6c305031ea5ff83b \ No newline at end of file
diff --git a/db/schema_migrations/20200608195222 b/db/schema_migrations/20200608195222
deleted file mode 100644
index 3604d1972ce..00000000000
--- a/db/schema_migrations/20200608195222
+++ /dev/null
@@ -1 +0,0 @@
-a81e2add150add1828be5aa4fb40c1115fe272d59119ae8ac70577614e712034 \ No newline at end of file
diff --git a/db/schema_migrations/20200608203426 b/db/schema_migrations/20200608203426
deleted file mode 100644
index bfc9c73f8f2..00000000000
--- a/db/schema_migrations/20200608203426
+++ /dev/null
@@ -1 +0,0 @@
-4808c4c52eb27adcffadd3e09a9e4a5e1cfeb594c6b8f5db384f68d439e2f8e1 \ No newline at end of file
diff --git a/db/schema_migrations/20200608205813 b/db/schema_migrations/20200608205813
deleted file mode 100644
index af78af53895..00000000000
--- a/db/schema_migrations/20200608205813
+++ /dev/null
@@ -1 +0,0 @@
-f92827e2daae85a4b830f290fb095f2ce0cfe7b0e18d64e9ca2f4ee7a65d41c0 \ No newline at end of file
diff --git a/db/schema_migrations/20200608212030 b/db/schema_migrations/20200608212030
deleted file mode 100644
index 347b40d53c5..00000000000
--- a/db/schema_migrations/20200608212030
+++ /dev/null
@@ -1 +0,0 @@
-be5f4947b22af9cd45e750cb072210ea3b1ac33bfdea41da99d3ddbbff83b34d \ No newline at end of file
diff --git a/db/schema_migrations/20200608212435 b/db/schema_migrations/20200608212435
deleted file mode 100644
index f08c8ba687e..00000000000
--- a/db/schema_migrations/20200608212435
+++ /dev/null
@@ -1 +0,0 @@
-3d0b911fe2fa2dc6b3227cc8a27e111c0b1fcecfca9911af8dbc1a62f0bd7926 \ No newline at end of file
diff --git a/db/schema_migrations/20200608212549 b/db/schema_migrations/20200608212549
deleted file mode 100644
index d556a6f0a4a..00000000000
--- a/db/schema_migrations/20200608212549
+++ /dev/null
@@ -1 +0,0 @@
-9b7a595ef64a605598b0591be106f2535199bdd72ab78c9f21454831aef4a2f7 \ No newline at end of file
diff --git a/db/schema_migrations/20200608212652 b/db/schema_migrations/20200608212652
deleted file mode 100644
index 3056ec757c8..00000000000
--- a/db/schema_migrations/20200608212652
+++ /dev/null
@@ -1 +0,0 @@
-724564628e5bc7485372059d04a394d6db472dcef7ce58b100d2adea8e679235 \ No newline at end of file
diff --git a/db/schema_migrations/20200608212807 b/db/schema_migrations/20200608212807
deleted file mode 100644
index 9efdf7bac02..00000000000
--- a/db/schema_migrations/20200608212807
+++ /dev/null
@@ -1 +0,0 @@
-afeb13580e40f67ef464f77d02a88ea7fbab0b6fcc156f2b24e9fd8f9e33f8ca \ No newline at end of file
diff --git a/db/schema_migrations/20200608212824 b/db/schema_migrations/20200608212824
deleted file mode 100644
index 200f7696846..00000000000
--- a/db/schema_migrations/20200608212824
+++ /dev/null
@@ -1 +0,0 @@
-dc896e00a165354f327c1bae20862b9e7ca610a4ab0253d78e119071185c8422 \ No newline at end of file
diff --git a/db/schema_migrations/20200608214008 b/db/schema_migrations/20200608214008
deleted file mode 100644
index 300c6de28b5..00000000000
--- a/db/schema_migrations/20200608214008
+++ /dev/null
@@ -1 +0,0 @@
-b386197aa520110ece57073eaab7efc543e9765529acaff85d7cc5186455edda \ No newline at end of file
diff --git a/db/schema_migrations/20200609002841 b/db/schema_migrations/20200609002841
deleted file mode 100644
index a93b461cebf..00000000000
--- a/db/schema_migrations/20200609002841
+++ /dev/null
@@ -1 +0,0 @@
-bea84fc1c29d73efe26914ca034f9355c75f9cbd87a3a3ccd71c6acd7ecbffe1 \ No newline at end of file
diff --git a/db/schema_migrations/20200609012539 b/db/schema_migrations/20200609012539
deleted file mode 100644
index 5e989f7411f..00000000000
--- a/db/schema_migrations/20200609012539
+++ /dev/null
@@ -1 +0,0 @@
-758e2c6cae32d919f656b3303f10b3c9bd61de6190c2b85baf2bcb1bcfb7ca2d \ No newline at end of file
diff --git a/db/schema_migrations/20200609142506 b/db/schema_migrations/20200609142506
deleted file mode 100644
index 9d28b9dcc7f..00000000000
--- a/db/schema_migrations/20200609142506
+++ /dev/null
@@ -1 +0,0 @@
-8a84bfcacd88bfd03ec3626a3a9f64bdd5a3997bcedd296a8327751b0708d14c \ No newline at end of file
diff --git a/db/schema_migrations/20200609142507 b/db/schema_migrations/20200609142507
deleted file mode 100644
index 41cd9f1fd49..00000000000
--- a/db/schema_migrations/20200609142507
+++ /dev/null
@@ -1 +0,0 @@
-fd8b872c67bbee78a8c5b11d60286c4a95888c33dc3daaf54d5f8bfe10269af9 \ No newline at end of file
diff --git a/db/schema_migrations/20200609142508 b/db/schema_migrations/20200609142508
deleted file mode 100644
index b39b9b91eb5..00000000000
--- a/db/schema_migrations/20200609142508
+++ /dev/null
@@ -1 +0,0 @@
-7a44279bbfe52fa2f27bcc6d59a69f0545e6cf0bfd18de0047b3009d01396755 \ No newline at end of file
diff --git a/db/schema_migrations/20200609212701 b/db/schema_migrations/20200609212701
deleted file mode 100644
index 6d70df6b8a4..00000000000
--- a/db/schema_migrations/20200609212701
+++ /dev/null
@@ -1 +0,0 @@
-97194e46e893e9424c8309615341b00cfee29e3f20eeee1f8319f53e48a16580 \ No newline at end of file
diff --git a/db/schema_migrations/20200610033228 b/db/schema_migrations/20200610033228
deleted file mode 100644
index 8e02b4c92ec..00000000000
--- a/db/schema_migrations/20200610033228
+++ /dev/null
@@ -1 +0,0 @@
-354524319f4c426328c7485619e248d00df323842873eaf7a2b3fbd2ad93048f \ No newline at end of file
diff --git a/db/schema_migrations/20200610040615 b/db/schema_migrations/20200610040615
deleted file mode 100644
index 6faeed1adaf..00000000000
--- a/db/schema_migrations/20200610040615
+++ /dev/null
@@ -1 +0,0 @@
-1f698671f226289fa1eabbb988b94ecd6486038f4922076bb981e44ee2356b25 \ No newline at end of file
diff --git a/db/schema_migrations/20200610130002 b/db/schema_migrations/20200610130002
deleted file mode 100644
index d17de837ae6..00000000000
--- a/db/schema_migrations/20200610130002
+++ /dev/null
@@ -1 +0,0 @@
-c362fa8b228a00b4733a55da3f2513548eca9044813fdbb8d373987d0b85f929 \ No newline at end of file
diff --git a/db/schema_migrations/20200611013227 b/db/schema_migrations/20200611013227
deleted file mode 100644
index e7f829d1875..00000000000
--- a/db/schema_migrations/20200611013227
+++ /dev/null
@@ -1 +0,0 @@
-d0ede6c4a28988494b0e18c073e56c1d985de73c443cc6b6d99e0b34a7f37642 \ No newline at end of file
diff --git a/db/schema_migrations/20200613104045 b/db/schema_migrations/20200613104045
deleted file mode 100644
index bf633f984fa..00000000000
--- a/db/schema_migrations/20200613104045
+++ /dev/null
@@ -1 +0,0 @@
-fdd78ca60caa3ac4272bdf611cf0885efe648d5d09b2dac470620d49dcd60651 \ No newline at end of file
diff --git a/db/schema_migrations/20200615083635 b/db/schema_migrations/20200615083635
deleted file mode 100644
index 0e8430924d7..00000000000
--- a/db/schema_migrations/20200615083635
+++ /dev/null
@@ -1 +0,0 @@
-67d81dc2b9e6383b636f06d47f89e1f68866d8eee643b5ee73f82e70bd6e303b \ No newline at end of file
diff --git a/db/schema_migrations/20200615111857 b/db/schema_migrations/20200615111857
deleted file mode 100644
index eb6074c7681..00000000000
--- a/db/schema_migrations/20200615111857
+++ /dev/null
@@ -1 +0,0 @@
-dc74a83d153d504b66ebdbd1b0055dc3b623c0eab9d073716fd2f04f2e1daeaa \ No newline at end of file
diff --git a/db/schema_migrations/20200615121217 b/db/schema_migrations/20200615121217
deleted file mode 100644
index 25ff8889fb0..00000000000
--- a/db/schema_migrations/20200615121217
+++ /dev/null
@@ -1 +0,0 @@
-815ea6fa4f05ed202405c934810f768b76c767b549ed6db5373728bc0b1e851e \ No newline at end of file
diff --git a/db/schema_migrations/20200615123055 b/db/schema_migrations/20200615123055
deleted file mode 100644
index 23906a4268b..00000000000
--- a/db/schema_migrations/20200615123055
+++ /dev/null
@@ -1 +0,0 @@
-be3b267fea5cc29b102923fd11893e2a9a7205a69ccf4fc96bb2d072ef2f599b \ No newline at end of file
diff --git a/db/schema_migrations/20200615141554 b/db/schema_migrations/20200615141554
deleted file mode 100644
index 88f8c745dd1..00000000000
--- a/db/schema_migrations/20200615141554
+++ /dev/null
@@ -1 +0,0 @@
-10b1e75870e6d663327fca71a5e4c73eb625196a67e9ce429fa5d0f7f06afc7b \ No newline at end of file
diff --git a/db/schema_migrations/20200615193524 b/db/schema_migrations/20200615193524
deleted file mode 100644
index 4e150108ea6..00000000000
--- a/db/schema_migrations/20200615193524
+++ /dev/null
@@ -1 +0,0 @@
-8d9b1d96db7e20284dc106395df63e26d230f7b7b7bec6d71cbed50ccb94cbd2 \ No newline at end of file
diff --git a/db/schema_migrations/20200615232735 b/db/schema_migrations/20200615232735
deleted file mode 100644
index 39ea96cc513..00000000000
--- a/db/schema_migrations/20200615232735
+++ /dev/null
@@ -1 +0,0 @@
-0ada7b9e9ed5e5fa034174d5aaaeb0062ed6ea8ab6b551a61a5ac0feaa93efab \ No newline at end of file
diff --git a/db/schema_migrations/20200615234047 b/db/schema_migrations/20200615234047
deleted file mode 100644
index aab90468293..00000000000
--- a/db/schema_migrations/20200615234047
+++ /dev/null
@@ -1 +0,0 @@
-6299538c6a2042f29f2831b655f52058f08ab67cc09a276e5ebedf1d52f5a3f3 \ No newline at end of file
diff --git a/db/schema_migrations/20200616124338 b/db/schema_migrations/20200616124338
deleted file mode 100644
index 479730cbf24..00000000000
--- a/db/schema_migrations/20200616124338
+++ /dev/null
@@ -1 +0,0 @@
-aff547c9adf4ff78b4684f65ab1ea206d4a30b7bcdf2bb6e90c56536f359078d \ No newline at end of file
diff --git a/db/schema_migrations/20200616145031 b/db/schema_migrations/20200616145031
deleted file mode 100644
index fbd1ebbb3f5..00000000000
--- a/db/schema_migrations/20200616145031
+++ /dev/null
@@ -1 +0,0 @@
-ddf5cdeff3be85a0843c71c5f6c710ffd0df87327dd775a2d5043bd154d7511a \ No newline at end of file
diff --git a/db/schema_migrations/20200617000757 b/db/schema_migrations/20200617000757
deleted file mode 100644
index 1583932958a..00000000000
--- a/db/schema_migrations/20200617000757
+++ /dev/null
@@ -1 +0,0 @@
-bf05eea2152525112a806452ddacf2ca9fdbfdfe6d8e552ea27e43a020fb9f2a \ No newline at end of file
diff --git a/db/schema_migrations/20200617001001 b/db/schema_migrations/20200617001001
deleted file mode 100644
index 8dbdf29de58..00000000000
--- a/db/schema_migrations/20200617001001
+++ /dev/null
@@ -1 +0,0 @@
-e6165c4152e5cbb6c9d8ea5e60cc66817f027baca245f6cb31f1eb37ac7052b2 \ No newline at end of file
diff --git a/db/schema_migrations/20200617001118 b/db/schema_migrations/20200617001118
deleted file mode 100644
index bb53367d6c9..00000000000
--- a/db/schema_migrations/20200617001118
+++ /dev/null
@@ -1 +0,0 @@
-5568809dbe031907f407ebb1edeb7244c838db221474ceaba0379cdb2eb7726c \ No newline at end of file
diff --git a/db/schema_migrations/20200617001637 b/db/schema_migrations/20200617001637
deleted file mode 100644
index 1df84f55110..00000000000
--- a/db/schema_migrations/20200617001637
+++ /dev/null
@@ -1 +0,0 @@
-5276c47fa4f8168028d7bd92ac8a2d84a8f933ff510d2cf323575b594ffb96a2 \ No newline at end of file
diff --git a/db/schema_migrations/20200617001848 b/db/schema_migrations/20200617001848
deleted file mode 100644
index 1271271a3fc..00000000000
--- a/db/schema_migrations/20200617001848
+++ /dev/null
@@ -1 +0,0 @@
-f16dac222b98e1d4cfc56a5e4bd2f044dddb079781e566a81e1b54ba9b9ef068 \ No newline at end of file
diff --git a/db/schema_migrations/20200617002030 b/db/schema_migrations/20200617002030
deleted file mode 100644
index c7f1c71f005..00000000000
--- a/db/schema_migrations/20200617002030
+++ /dev/null
@@ -1 +0,0 @@
-171b9cb0420eb4d96c3a9828e33bd19776a8657d53ca34c0848d3ce6d4101e98 \ No newline at end of file
diff --git a/db/schema_migrations/20200617150041 b/db/schema_migrations/20200617150041
deleted file mode 100644
index 65dc7fb1a26..00000000000
--- a/db/schema_migrations/20200617150041
+++ /dev/null
@@ -1 +0,0 @@
-26e26c801f66f10e2885defdeef5ce6ef4f85daf8f64d4563ed2792ffb2025f0 \ No newline at end of file
diff --git a/db/schema_migrations/20200617205000 b/db/schema_migrations/20200617205000
deleted file mode 100644
index 9bc1404f8b0..00000000000
--- a/db/schema_migrations/20200617205000
+++ /dev/null
@@ -1 +0,0 @@
-98339ca184cc20894f1141ea8a0e7393f2a3f47d715c8b87f7cab4bca812ffe2 \ No newline at end of file
diff --git a/db/schema_migrations/20200618105638 b/db/schema_migrations/20200618105638
deleted file mode 100644
index 6d13264e6a4..00000000000
--- a/db/schema_migrations/20200618105638
+++ /dev/null
@@ -1 +0,0 @@
-712c660d2a3198979e120473900fbf5bbf355853a2708a91e144942b3742a876 \ No newline at end of file
diff --git a/db/schema_migrations/20200618134223 b/db/schema_migrations/20200618134223
deleted file mode 100644
index a318e1bb96e..00000000000
--- a/db/schema_migrations/20200618134223
+++ /dev/null
@@ -1 +0,0 @@
-e61844f2775ddcfd7baaa954746a1235b38b176e4f460bda9c1a00deac1c284f \ No newline at end of file
diff --git a/db/schema_migrations/20200618134723 b/db/schema_migrations/20200618134723
deleted file mode 100644
index b013d9b48b3..00000000000
--- a/db/schema_migrations/20200618134723
+++ /dev/null
@@ -1 +0,0 @@
-e7e997f8b35b36f48f551e7fe146bd601b30a84e6183a14c8635dc4e68c10213 \ No newline at end of file
diff --git a/db/schema_migrations/20200618152212 b/db/schema_migrations/20200618152212
deleted file mode 100644
index 6d06649e9b6..00000000000
--- a/db/schema_migrations/20200618152212
+++ /dev/null
@@ -1 +0,0 @@
-e08929342b46d5f730cb421e3d65f492b033d4cd16ca06555965f504f64d77ea \ No newline at end of file
diff --git a/db/schema_migrations/20200619000316 b/db/schema_migrations/20200619000316
deleted file mode 100644
index 7e1e535a6bd..00000000000
--- a/db/schema_migrations/20200619000316
+++ /dev/null
@@ -1 +0,0 @@
-91865984629a279ffa024d9317864066d94ddcdc95d3bfeb1633a2ca886afcc2 \ No newline at end of file
diff --git a/db/schema_migrations/20200619154527 b/db/schema_migrations/20200619154527
deleted file mode 100644
index 261140c54c9..00000000000
--- a/db/schema_migrations/20200619154527
+++ /dev/null
@@ -1 +0,0 @@
-196e4e626b3b13b992386441398b6beaba8751cbe4f30f6b7b3424d57f01e19d \ No newline at end of file
diff --git a/db/schema_migrations/20200619154528 b/db/schema_migrations/20200619154528
deleted file mode 100644
index 2997c62a7a5..00000000000
--- a/db/schema_migrations/20200619154528
+++ /dev/null
@@ -1 +0,0 @@
-12d441b626cdaf67cfea8fd35c56c7c6a119bc02f29a0c62e9a12526e3eba702 \ No newline at end of file
diff --git a/db/schema_migrations/20200622040750 b/db/schema_migrations/20200622040750
deleted file mode 100644
index 6fbf0b93335..00000000000
--- a/db/schema_migrations/20200622040750
+++ /dev/null
@@ -1 +0,0 @@
-07e8f1ff41e1de0b3e3341f4ed08e228cc66742434d70284feaa05b743f7617e \ No newline at end of file
diff --git a/db/schema_migrations/20200622070606 b/db/schema_migrations/20200622070606
deleted file mode 100644
index 5c8a68f7218..00000000000
--- a/db/schema_migrations/20200622070606
+++ /dev/null
@@ -1 +0,0 @@
-c39ad3dcf37b8c02e3b121950290c95994ddb9b4bbe487d7d46bb8e468d3c632 \ No newline at end of file
diff --git a/db/schema_migrations/20200622070620 b/db/schema_migrations/20200622070620
deleted file mode 100644
index dcb26f0605e..00000000000
--- a/db/schema_migrations/20200622070620
+++ /dev/null
@@ -1 +0,0 @@
-deee3fd416e17711a39084de30a9bac9a311e7046879982e61b76208f50a8f5a \ No newline at end of file
diff --git a/db/schema_migrations/20200622095419 b/db/schema_migrations/20200622095419
deleted file mode 100644
index 3c6a4678786..00000000000
--- a/db/schema_migrations/20200622095419
+++ /dev/null
@@ -1 +0,0 @@
-a596be36eac444f24040071da6f8e397d549bc605382aa0a1c7ccc9d34260848 \ No newline at end of file
diff --git a/db/schema_migrations/20200622103836 b/db/schema_migrations/20200622103836
deleted file mode 100644
index 80799a19431..00000000000
--- a/db/schema_migrations/20200622103836
+++ /dev/null
@@ -1 +0,0 @@
-bddfca23e8575351d1dede5b3c17b33bac85952fbf97792444bbb5c96982ba66 \ No newline at end of file
diff --git a/db/schema_migrations/20200622104923 b/db/schema_migrations/20200622104923
deleted file mode 100644
index 630ad21d4ea..00000000000
--- a/db/schema_migrations/20200622104923
+++ /dev/null
@@ -1 +0,0 @@
-8054791d77a95553cc48a8e2178ee59146d0e4d72bddf05b4a24fbf6a225b99c \ No newline at end of file
diff --git a/db/schema_migrations/20200622235737 b/db/schema_migrations/20200622235737
deleted file mode 100644
index 0d28de77bfd..00000000000
--- a/db/schema_migrations/20200622235737
+++ /dev/null
@@ -1 +0,0 @@
-6161fca1f9a3f91a4ea88ee918cbdb1834a6e9bb05057e27feab09bd0b6e7cac \ No newline at end of file
diff --git a/db/schema_migrations/20200623000148 b/db/schema_migrations/20200623000148
deleted file mode 100644
index 930f679c952..00000000000
--- a/db/schema_migrations/20200623000148
+++ /dev/null
@@ -1 +0,0 @@
-5db78475ee52fa5fca6cf3befee5f10c86fefe04c27b0b79d4d676c85febaaf5 \ No newline at end of file
diff --git a/db/schema_migrations/20200623000320 b/db/schema_migrations/20200623000320
deleted file mode 100644
index a028c8b1832..00000000000
--- a/db/schema_migrations/20200623000320
+++ /dev/null
@@ -1 +0,0 @@
-6d312d49af3a42088d7781d82a583e99496df3731924fb30060440b169ba6182 \ No newline at end of file
diff --git a/db/schema_migrations/20200623073431 b/db/schema_migrations/20200623073431
deleted file mode 100644
index b21597042b1..00000000000
--- a/db/schema_migrations/20200623073431
+++ /dev/null
@@ -1 +0,0 @@
-56620e9f7767017db25052f55a246284fb294db5c170498b7d4f5ed160a669bc \ No newline at end of file
diff --git a/db/schema_migrations/20200623090030 b/db/schema_migrations/20200623090030
deleted file mode 100644
index fae84c07a75..00000000000
--- a/db/schema_migrations/20200623090030
+++ /dev/null
@@ -1 +0,0 @@
-5199ce1212dc8c9e4da724bf32e2b6ea5970fa0c6ff87e6352665553ebe70fab \ No newline at end of file
diff --git a/db/schema_migrations/20200623121135 b/db/schema_migrations/20200623121135
deleted file mode 100644
index 4b4e9f260ba..00000000000
--- a/db/schema_migrations/20200623121135
+++ /dev/null
@@ -1 +0,0 @@
-9a8a61b6553c5dd25fb1f2a07a4097a4d5cd5d5b0efa8912d76c4e8c4c56351a \ No newline at end of file
diff --git a/db/schema_migrations/20200623141217 b/db/schema_migrations/20200623141217
deleted file mode 100644
index adb80114aad..00000000000
--- a/db/schema_migrations/20200623141217
+++ /dev/null
@@ -1 +0,0 @@
-664fc6b595641eec16eb2dd4993fdf5b73753fbc2a749167c9b7d06ed5959efd \ No newline at end of file
diff --git a/db/schema_migrations/20200623141544 b/db/schema_migrations/20200623141544
deleted file mode 100644
index 187f1aaf8a5..00000000000
--- a/db/schema_migrations/20200623141544
+++ /dev/null
@@ -1 +0,0 @@
-738441d73aa06ef93187a4f5c414f485685328b201ccbbb63d35c9fee2056349 \ No newline at end of file
diff --git a/db/schema_migrations/20200623142159 b/db/schema_migrations/20200623142159
deleted file mode 100644
index fde7c8e8d47..00000000000
--- a/db/schema_migrations/20200623142159
+++ /dev/null
@@ -1 +0,0 @@
-82942944f0315f510ac897c58163031893f8a13904f8e08572696c75832890e0 \ No newline at end of file
diff --git a/db/schema_migrations/20200623170000 b/db/schema_migrations/20200623170000
deleted file mode 100644
index 9bcd1c35c20..00000000000
--- a/db/schema_migrations/20200623170000
+++ /dev/null
@@ -1 +0,0 @@
-7825feecc64a5135f9e4b1cf6af5975f8ae8c2726c8b410615563a004ede28fc \ No newline at end of file
diff --git a/db/schema_migrations/20200623185440 b/db/schema_migrations/20200623185440
deleted file mode 100644
index 0de2ff80e26..00000000000
--- a/db/schema_migrations/20200623185440
+++ /dev/null
@@ -1 +0,0 @@
-d6895533719bc92264fecfdded371927ee117ee48d93a2b1362776f0ce7dac87 \ No newline at end of file
diff --git a/db/schema_migrations/20200624075411 b/db/schema_migrations/20200624075411
deleted file mode 100644
index 77ff9daa076..00000000000
--- a/db/schema_migrations/20200624075411
+++ /dev/null
@@ -1 +0,0 @@
-4e6b9c589339742451ca598ca0a78c678c1513c6fd574b81075f48a0c51c1d5c \ No newline at end of file
diff --git a/db/schema_migrations/20200624142107 b/db/schema_migrations/20200624142107
deleted file mode 100644
index 53f820d9a9e..00000000000
--- a/db/schema_migrations/20200624142107
+++ /dev/null
@@ -1 +0,0 @@
-bb9ff9550f24c8441b955f11fdeed6058f1ce4dc61c4cf4e173a07d1210fac54 \ No newline at end of file
diff --git a/db/schema_migrations/20200624142207 b/db/schema_migrations/20200624142207
deleted file mode 100644
index 2617714d289..00000000000
--- a/db/schema_migrations/20200624142207
+++ /dev/null
@@ -1 +0,0 @@
-4f9d03e365ee98f1c09ff4c2e6950230455b9e48bff4b235e8d1c2fdd022b0a3 \ No newline at end of file
diff --git a/db/schema_migrations/20200624222443 b/db/schema_migrations/20200624222443
deleted file mode 100644
index c0cbec35d8e..00000000000
--- a/db/schema_migrations/20200624222443
+++ /dev/null
@@ -1 +0,0 @@
-8f96ad1dc7b0da8d5615d2cd331d7183a6f4878df32cc3569544438e53719acf \ No newline at end of file
diff --git a/db/schema_migrations/20200625045442 b/db/schema_migrations/20200625045442
deleted file mode 100644
index 6554a438732..00000000000
--- a/db/schema_migrations/20200625045442
+++ /dev/null
@@ -1 +0,0 @@
-6c5484120e2fc4c1a12afc74eb5df99a39532e90cf7054352480abbe52567b1d \ No newline at end of file
diff --git a/db/schema_migrations/20200625082258 b/db/schema_migrations/20200625082258
deleted file mode 100644
index 41b092deba5..00000000000
--- a/db/schema_migrations/20200625082258
+++ /dev/null
@@ -1 +0,0 @@
-b8c133ad205d222c42e029770c5ada3dddc09967e4fdaf7694be54cae2721378 \ No newline at end of file
diff --git a/db/schema_migrations/20200625113337 b/db/schema_migrations/20200625113337
deleted file mode 100644
index 37797a16c61..00000000000
--- a/db/schema_migrations/20200625113337
+++ /dev/null
@@ -1 +0,0 @@
-c698154da27dcf1e0ee106d091340130bb58227f51aed6aa8b4550f51b0b7f76 \ No newline at end of file
diff --git a/db/schema_migrations/20200625174052 b/db/schema_migrations/20200625174052
deleted file mode 100644
index 1e0b9edcc8d..00000000000
--- a/db/schema_migrations/20200625174052
+++ /dev/null
@@ -1 +0,0 @@
-882f9e7a02c9c44ffca11ffc9e3b6785588ff3cb1d8fb3bbf560980691624eb3 \ No newline at end of file
diff --git a/db/schema_migrations/20200625190458 b/db/schema_migrations/20200625190458
deleted file mode 100644
index 039c25a2016..00000000000
--- a/db/schema_migrations/20200625190458
+++ /dev/null
@@ -1 +0,0 @@
-5846a2c22dd2f502c853268adebf7d751e7a5207e5fba6f45e98cb29acb9a7ea \ No newline at end of file
diff --git a/db/schema_migrations/20200625193358 b/db/schema_migrations/20200625193358
deleted file mode 100644
index 06e5c06085f..00000000000
--- a/db/schema_migrations/20200625193358
+++ /dev/null
@@ -1 +0,0 @@
-e691c94223b44a5866f34aab96cc9a8c5857a6302115f977542bacb36e7c010e \ No newline at end of file
diff --git a/db/schema_migrations/20200626060151 b/db/schema_migrations/20200626060151
deleted file mode 100644
index 2d550e28463..00000000000
--- a/db/schema_migrations/20200626060151
+++ /dev/null
@@ -1 +0,0 @@
-baf236b3a0ee8e3dd2b970b1ad64937581a7bb5e1d1795571815638fd2de527f \ No newline at end of file
diff --git a/db/schema_migrations/20200626130220 b/db/schema_migrations/20200626130220
deleted file mode 100644
index 46abe4e610b..00000000000
--- a/db/schema_migrations/20200626130220
+++ /dev/null
@@ -1 +0,0 @@
-fa91292f2616dec3cfcc442601dca425fc395a3b93824f4c01e0c099d55447cf \ No newline at end of file
diff --git a/db/schema_migrations/20200628210938 b/db/schema_migrations/20200628210938
deleted file mode 100644
index 87a4d887b28..00000000000
--- a/db/schema_migrations/20200628210938
+++ /dev/null
@@ -1 +0,0 @@
-b579dec93b04d61e568e0373e591f73fbee4024e6356bea885498091e98d1afb \ No newline at end of file
diff --git a/db/schema_migrations/20200629134747 b/db/schema_migrations/20200629134747
deleted file mode 100644
index 04c2c1632b1..00000000000
--- a/db/schema_migrations/20200629134747
+++ /dev/null
@@ -1 +0,0 @@
-9cd0e15dd2c5e70e53fc154a47a76ec066c741b5f6d148972b96d23888f0fcd4 \ No newline at end of file
diff --git a/db/schema_migrations/20200629192638 b/db/schema_migrations/20200629192638
deleted file mode 100644
index 69d743ec1f8..00000000000
--- a/db/schema_migrations/20200629192638
+++ /dev/null
@@ -1 +0,0 @@
-eb71347da1619598330e8baf5083d99562961d96315242078ac36ff8beb7cc05 \ No newline at end of file
diff --git a/db/schema_migrations/20200630091656 b/db/schema_migrations/20200630091656
deleted file mode 100644
index c12858c4662..00000000000
--- a/db/schema_migrations/20200630091656
+++ /dev/null
@@ -1 +0,0 @@
-3bc17a3539e308a65c4bfbdfd56aeb1ab3562932fe9fc30653bdf26e194c8da9 \ No newline at end of file
diff --git a/db/schema_migrations/20200630110826 b/db/schema_migrations/20200630110826
deleted file mode 100644
index dc8ba062c4b..00000000000
--- a/db/schema_migrations/20200630110826
+++ /dev/null
@@ -1 +0,0 @@
-be35f5a98fc6d7a64dc2249ddf1f0c6a39c9607c119378eb7a6bba97d951e3d3 \ No newline at end of file
diff --git a/db/schema_migrations/20200701064756 b/db/schema_migrations/20200701064756
deleted file mode 100644
index 2a7d94f27fd..00000000000
--- a/db/schema_migrations/20200701064756
+++ /dev/null
@@ -1 +0,0 @@
-1775ba52ee8ac710dbc15fc009ffe68a4abe2513c323ab8af9955a4b8f19aeb1 \ No newline at end of file
diff --git a/db/schema_migrations/20200701070435 b/db/schema_migrations/20200701070435
deleted file mode 100644
index 8307c43131d..00000000000
--- a/db/schema_migrations/20200701070435
+++ /dev/null
@@ -1 +0,0 @@
-9ebe3fc5f75a75e883196fb587930b466c071550e8343f3cc0f98ade01aaba9a \ No newline at end of file
diff --git a/db/schema_migrations/20200701091253 b/db/schema_migrations/20200701091253
deleted file mode 100644
index f34f702d386..00000000000
--- a/db/schema_migrations/20200701091253
+++ /dev/null
@@ -1 +0,0 @@
-73e22a1ecd3c8f9ea637af55bd2bda2ec507b7c0c0499d3a16f11e3a1c14e1a9 \ No newline at end of file
diff --git a/db/schema_migrations/20200701093859 b/db/schema_migrations/20200701093859
deleted file mode 100644
index 947819b9887..00000000000
--- a/db/schema_migrations/20200701093859
+++ /dev/null
@@ -1 +0,0 @@
-b526262371625857dca652fdc6ab69850ccdc71cfad5fee57c4036bdd4705201 \ No newline at end of file
diff --git a/db/schema_migrations/20200701190523 b/db/schema_migrations/20200701190523
deleted file mode 100644
index 7fe184eea63..00000000000
--- a/db/schema_migrations/20200701190523
+++ /dev/null
@@ -1 +0,0 @@
-3be0b46b01cb9ff03706f80e3ec9230eaa52e46890307c85126f49d0e959d930 \ No newline at end of file
diff --git a/db/schema_migrations/20200701205710 b/db/schema_migrations/20200701205710
deleted file mode 100644
index 7630c7d873d..00000000000
--- a/db/schema_migrations/20200701205710
+++ /dev/null
@@ -1 +0,0 @@
-f5e6487c25e67c2d7d1bc51c753e95df20c5fa8528caafa0b1691bf2e60a909a \ No newline at end of file
diff --git a/db/schema_migrations/20200701221303 b/db/schema_migrations/20200701221303
deleted file mode 100644
index f2833ccf7a3..00000000000
--- a/db/schema_migrations/20200701221303
+++ /dev/null
@@ -1 +0,0 @@
-28ccab4f919ccf74d777c152e2c93a2ebf33c1ec1f6626a0708b1e2d5aa73648 \ No newline at end of file
diff --git a/db/schema_migrations/20200702123805 b/db/schema_migrations/20200702123805
deleted file mode 100644
index 741db09263f..00000000000
--- a/db/schema_migrations/20200702123805
+++ /dev/null
@@ -1 +0,0 @@
-6d6dc7b008b295e4b39e60b99ff65b7e647c9db6eec80840e2bc6bb4efe5eda6 \ No newline at end of file
diff --git a/db/schema_migrations/20200702201039 b/db/schema_migrations/20200702201039
deleted file mode 100644
index 4bff44d22e0..00000000000
--- a/db/schema_migrations/20200702201039
+++ /dev/null
@@ -1 +0,0 @@
-d3237c919b13ed370cf88fa44e2d074abad26f9ce2650ba40744d22d896a6ad0 \ No newline at end of file
diff --git a/db/schema_migrations/20200703035021 b/db/schema_migrations/20200703035021
deleted file mode 100644
index 53d81d39d66..00000000000
--- a/db/schema_migrations/20200703035021
+++ /dev/null
@@ -1 +0,0 @@
-acd7bef1e9ba764037fb2c2341a40eec9931b029187b4fc1e0f82d2eba24f413 \ No newline at end of file
diff --git a/db/schema_migrations/20200703064117 b/db/schema_migrations/20200703064117
deleted file mode 100644
index 10610e85b29..00000000000
--- a/db/schema_migrations/20200703064117
+++ /dev/null
@@ -1 +0,0 @@
-1d87f96c7b22f21877a57c0cd62b507af52b96b7c5784900bf4d96b73e5bfe40 \ No newline at end of file
diff --git a/db/schema_migrations/20200703121557 b/db/schema_migrations/20200703121557
deleted file mode 100644
index d570e637d51..00000000000
--- a/db/schema_migrations/20200703121557
+++ /dev/null
@@ -1 +0,0 @@
-276573ccb4e8e68aba9889080854b5e131d28e3c95de4b0fc24ce10f6717fe53 \ No newline at end of file
diff --git a/db/schema_migrations/20200703124823 b/db/schema_migrations/20200703124823
deleted file mode 100644
index f4b934ea6ff..00000000000
--- a/db/schema_migrations/20200703124823
+++ /dev/null
@@ -1 +0,0 @@
-bbe4f98abcd45317b66a137d1428b0a57bf9a075268b9d54cbc55fb0fa7bfbb1 \ No newline at end of file
diff --git a/db/schema_migrations/20200703125016 b/db/schema_migrations/20200703125016
deleted file mode 100644
index d5ee4d9f603..00000000000
--- a/db/schema_migrations/20200703125016
+++ /dev/null
@@ -1 +0,0 @@
-49bffc45e5a45f8c435a522c31b7d79dc6de31322ea5a2d6e23982cb92e0722b \ No newline at end of file
diff --git a/db/schema_migrations/20200703154822 b/db/schema_migrations/20200703154822
deleted file mode 100644
index 7fa87b4b371..00000000000
--- a/db/schema_migrations/20200703154822
+++ /dev/null
@@ -1 +0,0 @@
-8a9e0c601eabe2b22a911dd43fe3aa721d6d273f0bab44efaf50fc265e218f98 \ No newline at end of file
diff --git a/db/schema_migrations/20200703165434 b/db/schema_migrations/20200703165434
deleted file mode 100644
index 4d0452174f8..00000000000
--- a/db/schema_migrations/20200703165434
+++ /dev/null
@@ -1 +0,0 @@
-75e49095b0a8af426ed6d14b13230c5a19b6f225961e4c67ea21db55099e8006 \ No newline at end of file
diff --git a/db/schema_migrations/20200704143633 b/db/schema_migrations/20200704143633
deleted file mode 100644
index d435155df29..00000000000
--- a/db/schema_migrations/20200704143633
+++ /dev/null
@@ -1 +0,0 @@
-ec1273a88e79d23536d4a66324061a6d90ae9bee39dd4da323e951e9e873ff8a \ No newline at end of file
diff --git a/db/schema_migrations/20200704161600 b/db/schema_migrations/20200704161600
deleted file mode 100644
index aba199bb464..00000000000
--- a/db/schema_migrations/20200704161600
+++ /dev/null
@@ -1 +0,0 @@
-6bb78beff6acccd6b08a564d469c0c0cd40e229d084a116ec972a668e20253fa \ No newline at end of file
diff --git a/db/schema_migrations/20200706005325 b/db/schema_migrations/20200706005325
deleted file mode 100644
index e6b6673d660..00000000000
--- a/db/schema_migrations/20200706005325
+++ /dev/null
@@ -1 +0,0 @@
-6feb1c6c8b655617e06ba0fc586f7383aa104d9c8fa0a9d47c66fddc80ce6d46 \ No newline at end of file
diff --git a/db/schema_migrations/20200706035141 b/db/schema_migrations/20200706035141
deleted file mode 100644
index a853faddf1e..00000000000
--- a/db/schema_migrations/20200706035141
+++ /dev/null
@@ -1 +0,0 @@
-eb55d6708d8427f64794b0903b6a251e34db50b435a29310ea254eb2093f760f \ No newline at end of file
diff --git a/db/schema_migrations/20200706154619 b/db/schema_migrations/20200706154619
deleted file mode 100644
index 04faafe58df..00000000000
--- a/db/schema_migrations/20200706154619
+++ /dev/null
@@ -1 +0,0 @@
-30e10375de037c29b48be3f4b0376c28e751c53c08e42b0d936fb7151efeec4b \ No newline at end of file
diff --git a/db/schema_migrations/20200706170536 b/db/schema_migrations/20200706170536
deleted file mode 100644
index a6d59a438b7..00000000000
--- a/db/schema_migrations/20200706170536
+++ /dev/null
@@ -1 +0,0 @@
-a9a93c20cf05cc88d9fd9ed7de6fd8855188c8806d2c5fe8e6ed1f3ea26bf5d4 \ No newline at end of file
diff --git a/db/schema_migrations/20200707071941 b/db/schema_migrations/20200707071941
deleted file mode 100644
index 3e93ecf390e..00000000000
--- a/db/schema_migrations/20200707071941
+++ /dev/null
@@ -1 +0,0 @@
-0a840d40b6e870afe710a0e33fac3390197d02dab8ec371dcb25dd2100dbf1c4 \ No newline at end of file
diff --git a/db/schema_migrations/20200707094341 b/db/schema_migrations/20200707094341
deleted file mode 100644
index 2cae5913f78..00000000000
--- a/db/schema_migrations/20200707094341
+++ /dev/null
@@ -1 +0,0 @@
-2edd84a9c392f7873e30ff599c1fe8eed3f67055212550c6600d70de683fd1fd \ No newline at end of file
diff --git a/db/schema_migrations/20200707095849 b/db/schema_migrations/20200707095849
deleted file mode 100644
index 5903b647ff9..00000000000
--- a/db/schema_migrations/20200707095849
+++ /dev/null
@@ -1 +0,0 @@
-b4709d8dcf2fd6a00f96256ece8feba935b479d10249e5a950b6ecc413eb73b0 \ No newline at end of file
diff --git a/db/schema_migrations/20200708080631 b/db/schema_migrations/20200708080631
deleted file mode 100644
index 4fbdc9a14ae..00000000000
--- a/db/schema_migrations/20200708080631
+++ /dev/null
@@ -1 +0,0 @@
-04a2bab7ff956fe7f1ee21dd0fc11effbc227c70f73f600162bbf067f6ce7488 \ No newline at end of file
diff --git a/db/schema_migrations/20200709101408 b/db/schema_migrations/20200709101408
deleted file mode 100644
index 5a2d78b3b47..00000000000
--- a/db/schema_migrations/20200709101408
+++ /dev/null
@@ -1 +0,0 @@
-90d3e4bca0810485f588af454ed0181214ad3d0d96f2ec62b7fa17f77c63278f \ No newline at end of file
diff --git a/db/schema_migrations/20200710102418 b/db/schema_migrations/20200710102418
deleted file mode 100644
index 7c8349d3c35..00000000000
--- a/db/schema_migrations/20200710102418
+++ /dev/null
@@ -1 +0,0 @@
-85af50da623e9d6b6d05d1288d2be28d1d9e45163a047d46ac069650e88cc9bd \ No newline at end of file
diff --git a/db/schema_migrations/20200710102846 b/db/schema_migrations/20200710102846
deleted file mode 100644
index 7307e06f524..00000000000
--- a/db/schema_migrations/20200710102846
+++ /dev/null
@@ -1 +0,0 @@
-3798b034456371e4d370796e8dbcde3af229f276fa9f4db7a15b9549208004c0 \ No newline at end of file
diff --git a/db/schema_migrations/20200710105332 b/db/schema_migrations/20200710105332
deleted file mode 100644
index 4fc067f4620..00000000000
--- a/db/schema_migrations/20200710105332
+++ /dev/null
@@ -1 +0,0 @@
-51e89bd483fae5e4dc56323ad0246e63d033f4d5b48fe6ab4fddd6dbc0ee40bd \ No newline at end of file
diff --git a/db/schema_migrations/20200710113437 b/db/schema_migrations/20200710113437
deleted file mode 100644
index 02e9161ed7f..00000000000
--- a/db/schema_migrations/20200710113437
+++ /dev/null
@@ -1 +0,0 @@
-3d49c22b718c5b4af0a7372584fe12ab730e1ffca501c7f582f7d01200708eb1 \ No newline at end of file
diff --git a/db/schema_migrations/20200710130234 b/db/schema_migrations/20200710130234
deleted file mode 100644
index aa7869cab52..00000000000
--- a/db/schema_migrations/20200710130234
+++ /dev/null
@@ -1 +0,0 @@
-3bf35c629a3e1ed0ad3d38eeb5f8a960cdb4d935c7725f01206004707926257a \ No newline at end of file
diff --git a/db/schema_migrations/20200710152642 b/db/schema_migrations/20200710152642
deleted file mode 100644
index f3e057df9d2..00000000000
--- a/db/schema_migrations/20200710152642
+++ /dev/null
@@ -1 +0,0 @@
-0e4151d0fa03777383015a9efa6ce7ff6b2ef548978853da313500bf29448530 \ No newline at end of file
diff --git a/db/schema_migrations/20200710153009 b/db/schema_migrations/20200710153009
deleted file mode 100644
index 0a258ce5feb..00000000000
--- a/db/schema_migrations/20200710153009
+++ /dev/null
@@ -1 +0,0 @@
-338199b853aa81cd1cc961eb6d8be313d794f885b182be8e7e3b227a3eca5be5 \ No newline at end of file
diff --git a/db/schema_migrations/20200712084655 b/db/schema_migrations/20200712084655
deleted file mode 100644
index a78ced88ca9..00000000000
--- a/db/schema_migrations/20200712084655
+++ /dev/null
@@ -1 +0,0 @@
-3b9c351fe89fc57b3abaf7ce3a271864121c5c0ec8b4231e8a93e8e20b76f949 \ No newline at end of file
diff --git a/db/schema_migrations/20200712235622 b/db/schema_migrations/20200712235622
deleted file mode 100644
index d168bb326f9..00000000000
--- a/db/schema_migrations/20200712235622
+++ /dev/null
@@ -1 +0,0 @@
-29f7a28183b90535a0b9f6dcf435b4ffa7989f3a407f3a62c798411ad495d748 \ No newline at end of file
diff --git a/db/schema_migrations/20200713071042 b/db/schema_migrations/20200713071042
deleted file mode 100644
index 9f13921437e..00000000000
--- a/db/schema_migrations/20200713071042
+++ /dev/null
@@ -1 +0,0 @@
-0f859ebb7e5af38b45f8ebd67e9ae791592aa3273a3ef22228157d7c91e22bc2 \ No newline at end of file
diff --git a/db/schema_migrations/20200713141854 b/db/schema_migrations/20200713141854
deleted file mode 100644
index 4ed2ec290d3..00000000000
--- a/db/schema_migrations/20200713141854
+++ /dev/null
@@ -1 +0,0 @@
-1f14d14a6103bc4c593b1031485934812782c221c5d3ec193058086b95bd15e2 \ No newline at end of file
diff --git a/db/schema_migrations/20200713152443 b/db/schema_migrations/20200713152443
deleted file mode 100644
index fde7ac94467..00000000000
--- a/db/schema_migrations/20200713152443
+++ /dev/null
@@ -1 +0,0 @@
-9616489e2128cf858ce75baaf97516cb9a721e95a7507b0983f29eb78bdd063f \ No newline at end of file
diff --git a/db/schema_migrations/20200714075739 b/db/schema_migrations/20200714075739
deleted file mode 100644
index 4c3b7680dfe..00000000000
--- a/db/schema_migrations/20200714075739
+++ /dev/null
@@ -1 +0,0 @@
-49dc72bd54781a98cc80af7a0da22234339634c1af9987c150044f29e6a6db1c \ No newline at end of file
diff --git a/db/schema_migrations/20200715124210 b/db/schema_migrations/20200715124210
deleted file mode 100644
index 24775aa2a96..00000000000
--- a/db/schema_migrations/20200715124210
+++ /dev/null
@@ -1 +0,0 @@
-f5e992709af3d28c5d06930fac52529d7c7e4cd7133d836d2b289a2d5f9fab57 \ No newline at end of file
diff --git a/db/schema_migrations/20200715135130 b/db/schema_migrations/20200715135130
deleted file mode 100644
index b52ffa59dcb..00000000000
--- a/db/schema_migrations/20200715135130
+++ /dev/null
@@ -1 +0,0 @@
-422e41e9eb94fb659d0c8ffd2f3da783b1041db6223af78874fd8545d49ac05a \ No newline at end of file
diff --git a/db/schema_migrations/20200715171155 b/db/schema_migrations/20200715171155
deleted file mode 100644
index 8ee7499cd42..00000000000
--- a/db/schema_migrations/20200715171155
+++ /dev/null
@@ -1 +0,0 @@
-8db7f9239f6a817f8ad1a4dea388e1a797009cd21e1729817005b0de36c4300f \ No newline at end of file
diff --git a/db/schema_migrations/20200715202659 b/db/schema_migrations/20200715202659
deleted file mode 100644
index 7cc37659399..00000000000
--- a/db/schema_migrations/20200715202659
+++ /dev/null
@@ -1 +0,0 @@
-312e5f4ec625f4588feddafee7c0dca98a6981f9d0a15abf6d9ce244ebd02bb3 \ No newline at end of file
diff --git a/db/schema_migrations/20200716044023 b/db/schema_migrations/20200716044023
deleted file mode 100644
index 49f5f53e176..00000000000
--- a/db/schema_migrations/20200716044023
+++ /dev/null
@@ -1 +0,0 @@
-b6d060f317ec8b342ed29249a469a6c3548677f339029d14a88775d372bebd8f \ No newline at end of file
diff --git a/db/schema_migrations/20200716120000 b/db/schema_migrations/20200716120000
deleted file mode 100644
index 5bf1c862593..00000000000
--- a/db/schema_migrations/20200716120000
+++ /dev/null
@@ -1 +0,0 @@
-a70e7a6c27a51cc8f37af7e9d8f03870ac60139b179e89416870de0a7e07d104 \ No newline at end of file
diff --git a/db/schema_migrations/20200716120419 b/db/schema_migrations/20200716120419
deleted file mode 100644
index 4305bffa7ff..00000000000
--- a/db/schema_migrations/20200716120419
+++ /dev/null
@@ -1 +0,0 @@
-ca0bed2b4b6cec712c6c8fb55cae995905d9cc64399f670f3ce25298f91241d1 \ No newline at end of file
diff --git a/db/schema_migrations/20200716145156 b/db/schema_migrations/20200716145156
deleted file mode 100644
index 5d489a0f9d1..00000000000
--- a/db/schema_migrations/20200716145156
+++ /dev/null
@@ -1 +0,0 @@
-f84e629adb1db8441287577e52b895fa471c75d6d0578b55a1173f0034d5f02e \ No newline at end of file
diff --git a/db/schema_migrations/20200716234259 b/db/schema_migrations/20200716234259
deleted file mode 100644
index 51916bdc8af..00000000000
--- a/db/schema_migrations/20200716234259
+++ /dev/null
@@ -1 +0,0 @@
-9683f55a327b9579b9b0b9484dd11a07b7ea4244b126c46e0144662cb25da6bb \ No newline at end of file
diff --git a/db/schema_migrations/20200716234518 b/db/schema_migrations/20200716234518
deleted file mode 100644
index c5f438dcfbe..00000000000
--- a/db/schema_migrations/20200716234518
+++ /dev/null
@@ -1 +0,0 @@
-71cd12e553b3acbb665770fe7478365f1f082e2d278c67b166f41461f689aa5e \ No newline at end of file
diff --git a/db/schema_migrations/20200717040735 b/db/schema_migrations/20200717040735
deleted file mode 100644
index 6bfa1dd7261..00000000000
--- a/db/schema_migrations/20200717040735
+++ /dev/null
@@ -1 +0,0 @@
-6b8fa09c9700c494eeb5151f43064f1656eaaea804742629b7bd66483e2b04cb \ No newline at end of file
diff --git a/db/schema_migrations/20200717080257 b/db/schema_migrations/20200717080257
deleted file mode 100644
index 73a5b583f8a..00000000000
--- a/db/schema_migrations/20200717080257
+++ /dev/null
@@ -1 +0,0 @@
-dbb84d05cfe6d2ef143b9321b2b089c66d705f01ced64756032622f64f8e3eed \ No newline at end of file
diff --git a/db/schema_migrations/20200717163656 b/db/schema_migrations/20200717163656
deleted file mode 100644
index e53618b003f..00000000000
--- a/db/schema_migrations/20200717163656
+++ /dev/null
@@ -1 +0,0 @@
-40b9ece83b05dc3ec2c69db2298a051b085d645d2b60719eef4a55d7838ba1fb \ No newline at end of file
diff --git a/db/schema_migrations/20200718040100 b/db/schema_migrations/20200718040100
deleted file mode 100644
index f8844a3e914..00000000000
--- a/db/schema_migrations/20200718040100
+++ /dev/null
@@ -1 +0,0 @@
-9b0bf24c0943422dda627d4b8864cfb639e77c1522f39215b4ec2858be6b2bb0 \ No newline at end of file
diff --git a/db/schema_migrations/20200718040200 b/db/schema_migrations/20200718040200
deleted file mode 100644
index 9f58e2c685a..00000000000
--- a/db/schema_migrations/20200718040200
+++ /dev/null
@@ -1 +0,0 @@
-6b300cb30377b600e0b107fcb5707bb5ffad86aeffcc306404d320e1438a833d \ No newline at end of file
diff --git a/db/schema_migrations/20200718040300 b/db/schema_migrations/20200718040300
deleted file mode 100644
index 21d24ee09e2..00000000000
--- a/db/schema_migrations/20200718040300
+++ /dev/null
@@ -1 +0,0 @@
-512af8b92b1ac74a2c044c08362c18c48772d4b722b18f620593ffa2be551762 \ No newline at end of file
diff --git a/db/schema_migrations/20200720053909 b/db/schema_migrations/20200720053909
deleted file mode 100644
index da9379a4e13..00000000000
--- a/db/schema_migrations/20200720053909
+++ /dev/null
@@ -1 +0,0 @@
-dfe979676a74b09ed6d0ffe258162f7d5af2bdea7c21b307aafbbb9ceb7c0334 \ No newline at end of file
diff --git a/db/schema_migrations/20200720154007 b/db/schema_migrations/20200720154007
deleted file mode 100644
index 6006f5d5301..00000000000
--- a/db/schema_migrations/20200720154007
+++ /dev/null
@@ -1 +0,0 @@
-8da79a65932d06a4a4cf7b601ecac742ae7b785a1c6799019b1ee758f844cacf \ No newline at end of file
diff --git a/db/schema_migrations/20200720154123 b/db/schema_migrations/20200720154123
deleted file mode 100644
index 46bf0eea32a..00000000000
--- a/db/schema_migrations/20200720154123
+++ /dev/null
@@ -1 +0,0 @@
-9ab36f32e5e833acf4b795c0002ad4d3461c950ac7d10eeb12f42a13838b06bf \ No newline at end of file
diff --git a/db/schema_migrations/20200720191134 b/db/schema_migrations/20200720191134
deleted file mode 100644
index 05b27271d48..00000000000
--- a/db/schema_migrations/20200720191134
+++ /dev/null
@@ -1 +0,0 @@
-08566b4094de37395f3ebc3f70eedc9ed6052a78090cf296e66ce4ef167e6bce \ No newline at end of file
diff --git a/db/schema_migrations/20200721034536 b/db/schema_migrations/20200721034536
deleted file mode 100644
index e40424a5069..00000000000
--- a/db/schema_migrations/20200721034536
+++ /dev/null
@@ -1 +0,0 @@
-9d30ae6ea32db6cbc5871e214a9c2bf8f1a37fbb586f5e39f6bc2ab58768607b \ No newline at end of file
diff --git a/db/schema_migrations/20200721043502 b/db/schema_migrations/20200721043502
deleted file mode 100644
index 9d33d6a5e92..00000000000
--- a/db/schema_migrations/20200721043502
+++ /dev/null
@@ -1 +0,0 @@
-13731676720dd93887dc55374c9052f1087a2e817eb347fd63a19d9398899d75 \ No newline at end of file
diff --git a/db/schema_migrations/20200721052853 b/db/schema_migrations/20200721052853
deleted file mode 100644
index 3e0ec8b0d5a..00000000000
--- a/db/schema_migrations/20200721052853
+++ /dev/null
@@ -1 +0,0 @@
-53c373e95eb78ddc79eaa07d7638d9e1dbe055838da435fdae1c3d45c6babe0e \ No newline at end of file
diff --git a/db/schema_migrations/20200721140507 b/db/schema_migrations/20200721140507
deleted file mode 100644
index 3fbd67734c7..00000000000
--- a/db/schema_migrations/20200721140507
+++ /dev/null
@@ -1 +0,0 @@
-9a395ab591542ec49fc17c22747d9bbf085fd5f61ae71f49493dfe34f0389059 \ No newline at end of file
diff --git a/db/schema_migrations/20200721230558 b/db/schema_migrations/20200721230558
deleted file mode 100644
index eb3e43ac095..00000000000
--- a/db/schema_migrations/20200721230558
+++ /dev/null
@@ -1 +0,0 @@
-7409688836e7375423b45d69e6c7b82c6a946c0306435ec341bf216e3f97190f \ No newline at end of file
diff --git a/db/schema_migrations/20200722075411 b/db/schema_migrations/20200722075411
deleted file mode 100644
index 2251597abb1..00000000000
--- a/db/schema_migrations/20200722075411
+++ /dev/null
@@ -1 +0,0 @@
-5b8756999308abb47823c075128c07d62b899d6a39dff23242db6b12f18f239a \ No newline at end of file
diff --git a/db/schema_migrations/20200722084623 b/db/schema_migrations/20200722084623
deleted file mode 100644
index 04e3017558f..00000000000
--- a/db/schema_migrations/20200722084623
+++ /dev/null
@@ -1 +0,0 @@
-15024fbf4fc6be1ece1f25cf46ef1cc27f9d91fcd7cc0285dad68db167f197c9 \ No newline at end of file
diff --git a/db/schema_migrations/20200722091435 b/db/schema_migrations/20200722091435
deleted file mode 100644
index 13b3c855293..00000000000
--- a/db/schema_migrations/20200722091435
+++ /dev/null
@@ -1 +0,0 @@
-d4e389b1469b968b703432de9ece6c362e45ec4ba3ad20d1f6c6418253969379 \ No newline at end of file
diff --git a/db/schema_migrations/20200722131241 b/db/schema_migrations/20200722131241
deleted file mode 100644
index 327486a7367..00000000000
--- a/db/schema_migrations/20200722131241
+++ /dev/null
@@ -1 +0,0 @@
-5fc97e904844b43a331246c68b1d0a879f683d5b36fab6cd024f417922259864 \ No newline at end of file
diff --git a/db/schema_migrations/20200722132040 b/db/schema_migrations/20200722132040
deleted file mode 100644
index 7993eaafe02..00000000000
--- a/db/schema_migrations/20200722132040
+++ /dev/null
@@ -1 +0,0 @@
-7b33a7f96ea02e3d5510cb6a6d75a9c753c1bd24c93d9995f91596d6b1a44592 \ No newline at end of file
diff --git a/db/schema_migrations/20200722132540 b/db/schema_migrations/20200722132540
deleted file mode 100644
index 683c61dd661..00000000000
--- a/db/schema_migrations/20200722132540
+++ /dev/null
@@ -1 +0,0 @@
-543ebc8ab7fad96aeb5a8618bc954babb0eed1d252fe490aa6fab9b8e80ffbf1 \ No newline at end of file
diff --git a/db/schema_migrations/20200722133040 b/db/schema_migrations/20200722133040
deleted file mode 100644
index 602ba562760..00000000000
--- a/db/schema_migrations/20200722133040
+++ /dev/null
@@ -1 +0,0 @@
-4a6a322cf3f6e1622d3244f6faa99a1befcb8c626a8fea36b09d1910b770b88c \ No newline at end of file
diff --git a/db/schema_migrations/20200722133540 b/db/schema_migrations/20200722133540
deleted file mode 100644
index 1a0385bcaea..00000000000
--- a/db/schema_migrations/20200722133540
+++ /dev/null
@@ -1 +0,0 @@
-0307eb0f5082a5da84f5e94084b677d13e03f9cd5011efe3dc7e25645a00082d \ No newline at end of file
diff --git a/db/schema_migrations/20200722202318 b/db/schema_migrations/20200722202318
deleted file mode 100644
index 74b6d2abf26..00000000000
--- a/db/schema_migrations/20200722202318
+++ /dev/null
@@ -1 +0,0 @@
-7a1344af4736eb369996398332653b29ec93fbda92b258fbe95093476c01d29e \ No newline at end of file
diff --git a/db/schema_migrations/20200723040950 b/db/schema_migrations/20200723040950
deleted file mode 100644
index fc2233ef119..00000000000
--- a/db/schema_migrations/20200723040950
+++ /dev/null
@@ -1 +0,0 @@
-085b3ad0f7da78a1e13f5cd3d2e7df297284a682c3bcd3883e487b18497430ff \ No newline at end of file
diff --git a/db/schema_migrations/20200723125205 b/db/schema_migrations/20200723125205
deleted file mode 100644
index ca259978658..00000000000
--- a/db/schema_migrations/20200723125205
+++ /dev/null
@@ -1 +0,0 @@
-630029f7d90da29022404146ce8c488108a2232d2bfd0864a6f5d659f3999af8 \ No newline at end of file
diff --git a/db/schema_migrations/20200723128332 b/db/schema_migrations/20200723128332
deleted file mode 100644
index 2e180ef80f1..00000000000
--- a/db/schema_migrations/20200723128332
+++ /dev/null
@@ -1 +0,0 @@
-7d6f3601187c98f091cb0c5449ff7c6ca53392f006435223dcc067e4a73dab11 \ No newline at end of file
diff --git a/db/schema_migrations/20200723132258 b/db/schema_migrations/20200723132258
deleted file mode 100644
index 3a3c0341f42..00000000000
--- a/db/schema_migrations/20200723132258
+++ /dev/null
@@ -1 +0,0 @@
-b3fcb58bbeae8af800a32158a8d272ec524594391e96357fdad955f70864bc95 \ No newline at end of file
diff --git a/db/schema_migrations/20200724100123 b/db/schema_migrations/20200724100123
deleted file mode 100644
index 8d3fbecedb6..00000000000
--- a/db/schema_migrations/20200724100123
+++ /dev/null
@@ -1 +0,0 @@
-f55dccae8909110396882bd2c28be993eb32f33e880ed4a520d14071f70c9019 \ No newline at end of file
diff --git a/db/schema_migrations/20200724100421 b/db/schema_migrations/20200724100421
deleted file mode 100644
index 93f92046c17..00000000000
--- a/db/schema_migrations/20200724100421
+++ /dev/null
@@ -1 +0,0 @@
-77601e653f7b4f2740db87a7b19b64bb73fffbe4ce59c0f68b0bb65599da0eb3 \ No newline at end of file
diff --git a/db/schema_migrations/20200724130639 b/db/schema_migrations/20200724130639
deleted file mode 100644
index 8a1ba4f6063..00000000000
--- a/db/schema_migrations/20200724130639
+++ /dev/null
@@ -1 +0,0 @@
-9d711a0c4f785660c0a2317e598e427d5e2f91b177e4c0b96cef2958f787aa6e \ No newline at end of file
diff --git a/db/schema_migrations/20200727082309 b/db/schema_migrations/20200727082309
deleted file mode 100644
index 9d89a51f761..00000000000
--- a/db/schema_migrations/20200727082309
+++ /dev/null
@@ -1 +0,0 @@
-72c7ca9e1284483e653d6d8dc16103f104502d7cd569cb3f7ab75e932807a661 \ No newline at end of file
diff --git a/db/schema_migrations/20200727100631 b/db/schema_migrations/20200727100631
deleted file mode 100644
index aa724c13995..00000000000
--- a/db/schema_migrations/20200727100631
+++ /dev/null
@@ -1 +0,0 @@
-83c1dca01d4e56c22f6c1cda249c9b162eb7c31e2b164629bf51ea9aa9dd8fb5 \ No newline at end of file
diff --git a/db/schema_migrations/20200727114147 b/db/schema_migrations/20200727114147
deleted file mode 100644
index 21a5b79b8ea..00000000000
--- a/db/schema_migrations/20200727114147
+++ /dev/null
@@ -1 +0,0 @@
-fd85556cfed27a08aa01a8ee5b4eecfb1de7011b2fcb5c613cf21b9f42e728b9 \ No newline at end of file
diff --git a/db/schema_migrations/20200727142337 b/db/schema_migrations/20200727142337
deleted file mode 100644
index a14fefa51fa..00000000000
--- a/db/schema_migrations/20200727142337
+++ /dev/null
@@ -1 +0,0 @@
-cc88f907caed6045ff2d8b0663a4b64e9d2633f213ffa85274b84c80eb32b94e \ No newline at end of file
diff --git a/db/schema_migrations/20200728080250 b/db/schema_migrations/20200728080250
deleted file mode 100644
index 137290c0e86..00000000000
--- a/db/schema_migrations/20200728080250
+++ /dev/null
@@ -1 +0,0 @@
-546555a009e8923ea8b976ce38d882d387407fb03e7bbcb9c760df53bafd1f91 \ No newline at end of file
diff --git a/db/schema_migrations/20200728163009 b/db/schema_migrations/20200728163009
deleted file mode 100644
index e2236ff61de..00000000000
--- a/db/schema_migrations/20200728163009
+++ /dev/null
@@ -1 +0,0 @@
-6613f518079ead2259b4189c91d3507724af18d1cf9e2014fab9b7543ec3d423 \ No newline at end of file
diff --git a/db/schema_migrations/20200728174137 b/db/schema_migrations/20200728174137
deleted file mode 100644
index 7863b7eb40b..00000000000
--- a/db/schema_migrations/20200728174137
+++ /dev/null
@@ -1 +0,0 @@
-a16e7fdcc62f39af3038317cb39ffb4c35f41ae45f5de429f18837309739110b \ No newline at end of file
diff --git a/db/schema_migrations/20200728175710 b/db/schema_migrations/20200728175710
deleted file mode 100644
index 0ba117d0ead..00000000000
--- a/db/schema_migrations/20200728175710
+++ /dev/null
@@ -1 +0,0 @@
-a3a6d4e488c9979efd61890a15fdfe4ccea044a0b030b392ad39885cc807f22d \ No newline at end of file
diff --git a/db/schema_migrations/20200728182311 b/db/schema_migrations/20200728182311
deleted file mode 100644
index 6bb5a869513..00000000000
--- a/db/schema_migrations/20200728182311
+++ /dev/null
@@ -1 +0,0 @@
-2aab4599404312ddcc5bc9af11b0a21dfd6aa8aa10d4b4b5086a93ce1ffe77b6 \ No newline at end of file
diff --git a/db/schema_migrations/20200729151021 b/db/schema_migrations/20200729151021
deleted file mode 100644
index 2ce06409ac4..00000000000
--- a/db/schema_migrations/20200729151021
+++ /dev/null
@@ -1 +0,0 @@
-0a080250afe61007852cb65e8fd6cdccbdad1666abf12b59d46fb55ec0d455cc \ No newline at end of file
diff --git a/db/schema_migrations/20200729175935 b/db/schema_migrations/20200729175935
deleted file mode 100644
index 65aec146116..00000000000
--- a/db/schema_migrations/20200729175935
+++ /dev/null
@@ -1 +0,0 @@
-5f841d2032b55f01e944c50070a6bb102883c2e4da7ba155fdcf2e90f3b68707 \ No newline at end of file
diff --git a/db/schema_migrations/20200729180539 b/db/schema_migrations/20200729180539
deleted file mode 100644
index faffd8af926..00000000000
--- a/db/schema_migrations/20200729180539
+++ /dev/null
@@ -1 +0,0 @@
-8b6b0179c7027f34390376e06472fa80daa7c13ee7fa6ea52f04fae430309fc7 \ No newline at end of file
diff --git a/db/schema_migrations/20200729181641 b/db/schema_migrations/20200729181641
deleted file mode 100644
index 0d1d959c5a5..00000000000
--- a/db/schema_migrations/20200729181641
+++ /dev/null
@@ -1 +0,0 @@
-5dc4cbfc6d7e79e5909e5250f382bc3c9fa4246b8f2aed81404899aee4eef81b \ No newline at end of file
diff --git a/db/schema_migrations/20200729191227 b/db/schema_migrations/20200729191227
deleted file mode 100644
index e7abca98976..00000000000
--- a/db/schema_migrations/20200729191227
+++ /dev/null
@@ -1 +0,0 @@
-34d53fcb98b82f3da7eeacd7bfabfd4118b51c448418f20227f7d5b05a0077dc \ No newline at end of file
diff --git a/db/schema_migrations/20200729200808 b/db/schema_migrations/20200729200808
deleted file mode 100644
index 99431c08664..00000000000
--- a/db/schema_migrations/20200729200808
+++ /dev/null
@@ -1 +0,0 @@
-a1a896fc3fe060b34da9cde46ac0ddb8b973d077bcae3bb36677f9d02d2a3509 \ No newline at end of file
diff --git a/db/schema_migrations/20200729202222 b/db/schema_migrations/20200729202222
deleted file mode 100644
index 2ab73a764f3..00000000000
--- a/db/schema_migrations/20200729202222
+++ /dev/null
@@ -1 +0,0 @@
-2976f459ac9cd0780e90077ebe4ce5ca8dc41e62b4dab1f96e39738624ad9d04 \ No newline at end of file
diff --git a/db/schema_migrations/20200730044810 b/db/schema_migrations/20200730044810
deleted file mode 100644
index 0532199d8ec..00000000000
--- a/db/schema_migrations/20200730044810
+++ /dev/null
@@ -1 +0,0 @@
-406594bc48558c3ad50680c7e1fa795f38abb92696acbb94ae2dfb13d8dcaf1a \ No newline at end of file
diff --git a/db/schema_migrations/20200730083043 b/db/schema_migrations/20200730083043
deleted file mode 100644
index d927b5204c9..00000000000
--- a/db/schema_migrations/20200730083043
+++ /dev/null
@@ -1 +0,0 @@
-5bda9ae726077c1ea0df2158138f85ca43bfbf5b1a8cf3516bcdf012eac5c0b8 \ No newline at end of file
diff --git a/db/schema_migrations/20200730131946 b/db/schema_migrations/20200730131946
deleted file mode 100644
index dc4e6f96917..00000000000
--- a/db/schema_migrations/20200730131946
+++ /dev/null
@@ -1 +0,0 @@
-4ef0dfb9cdeccd57a3c11d1db0b57448746237d4a1fe001340575c996a6c3c68 \ No newline at end of file
diff --git a/db/schema_migrations/20200730133730 b/db/schema_migrations/20200730133730
deleted file mode 100644
index db276e9606f..00000000000
--- a/db/schema_migrations/20200730133730
+++ /dev/null
@@ -1 +0,0 @@
-bd1c0fd04b1a77492a125417a530ea0482c66330da3d2563c963c097e63b6b39 \ No newline at end of file
diff --git a/db/schema_migrations/20200730210506 b/db/schema_migrations/20200730210506
deleted file mode 100644
index b140941092d..00000000000
--- a/db/schema_migrations/20200730210506
+++ /dev/null
@@ -1 +0,0 @@
-85eb0a510cdb4b315aef1665f05ad3b93d5d39f4ddfe11ed5ddde63aa732f874 \ No newline at end of file
diff --git a/db/schema_migrations/20200731085019 b/db/schema_migrations/20200731085019
deleted file mode 100644
index 55e35ff8f4a..00000000000
--- a/db/schema_migrations/20200731085019
+++ /dev/null
@@ -1 +0,0 @@
-aeeef4762f7ab7c7eefc28995ba198825455a43db38c1ff2aefad8c3c76b5fba \ No newline at end of file
diff --git a/db/schema_migrations/20200731090553 b/db/schema_migrations/20200731090553
deleted file mode 100644
index d991f11eb02..00000000000
--- a/db/schema_migrations/20200731090553
+++ /dev/null
@@ -1 +0,0 @@
-c5775e8150285927b74c2fbf6098d03920e7bea52c3b94ad372fec288835110c \ No newline at end of file
diff --git a/db/schema_migrations/20200731201408 b/db/schema_migrations/20200731201408
deleted file mode 100644
index 1f457761c90..00000000000
--- a/db/schema_migrations/20200731201408
+++ /dev/null
@@ -1 +0,0 @@
-02f3561a5b8fa79c58dccc23ebaecf2c1b8371c86bb360156456bd11e84d13a2 \ No newline at end of file
diff --git a/db/schema_migrations/20200731201834 b/db/schema_migrations/20200731201834
deleted file mode 100644
index 4c4630e54ad..00000000000
--- a/db/schema_migrations/20200731201834
+++ /dev/null
@@ -1 +0,0 @@
-26aa28efa15ebd223feb879d5cb684a53a92bc71e483e8348d0cd9f1ad10e7ae \ No newline at end of file
diff --git a/db/schema_migrations/20200803111512 b/db/schema_migrations/20200803111512
deleted file mode 100644
index aa99ce35559..00000000000
--- a/db/schema_migrations/20200803111512
+++ /dev/null
@@ -1 +0,0 @@
-d0ea5e75c74d8405014fe5be6906e21b009d9eddb8eaefea939a67e01ee146e7 \ No newline at end of file
diff --git a/db/schema_migrations/20200803112806 b/db/schema_migrations/20200803112806
deleted file mode 100644
index 4f7962bfe49..00000000000
--- a/db/schema_migrations/20200803112806
+++ /dev/null
@@ -1 +0,0 @@
-8e6ffd7b1d44ac846b79cf37798abc57eee169fbde0de096ea49df590af864b5 \ No newline at end of file
diff --git a/db/schema_migrations/20200803125340 b/db/schema_migrations/20200803125340
deleted file mode 100644
index d1aed6435ce..00000000000
--- a/db/schema_migrations/20200803125340
+++ /dev/null
@@ -1 +0,0 @@
-78a33c142b6182749291ad963397dcda8efe5fe421381612801e5ccd34267326 \ No newline at end of file
diff --git a/db/schema_migrations/20200804035230 b/db/schema_migrations/20200804035230
deleted file mode 100644
index 02aa4ffb366..00000000000
--- a/db/schema_migrations/20200804035230
+++ /dev/null
@@ -1 +0,0 @@
-f1e2f11710ca7175b7a77b0f52bd204403dfcfd0b6b33cd00e3fa0d020be1287 \ No newline at end of file
diff --git a/db/schema_migrations/20200804041018 b/db/schema_migrations/20200804041018
deleted file mode 100644
index 63c13e6b5d8..00000000000
--- a/db/schema_migrations/20200804041018
+++ /dev/null
@@ -1 +0,0 @@
-ac65340525eba0cd025be706dde4deaf4574f8a7ffb9531d56ffae707e7e8b6d \ No newline at end of file
diff --git a/db/schema_migrations/20200804041930 b/db/schema_migrations/20200804041930
deleted file mode 100644
index f67f8079847..00000000000
--- a/db/schema_migrations/20200804041930
+++ /dev/null
@@ -1 +0,0 @@
-3177e2f9549add35789e64b14c5958c4fb42fdce4b4705505bc9bbe326d9a875 \ No newline at end of file
diff --git a/db/schema_migrations/20200804222543 b/db/schema_migrations/20200804222543
deleted file mode 100644
index d8c99e51bff..00000000000
--- a/db/schema_migrations/20200804222543
+++ /dev/null
@@ -1 +0,0 @@
-21c35b7712ed1933537115a74571904c74b3d61b424b9f954c3ad36e0d1bf139 \ No newline at end of file
diff --git a/db/schema_migrations/20200805071842 b/db/schema_migrations/20200805071842
deleted file mode 100644
index 75810bed0d1..00000000000
--- a/db/schema_migrations/20200805071842
+++ /dev/null
@@ -1 +0,0 @@
-432ef9d45c8242ab8db954ceeb6a68a75ef46181dd868a30d68fef0ed6058caf \ No newline at end of file
diff --git a/db/schema_migrations/20200805150316 b/db/schema_migrations/20200805150316
deleted file mode 100644
index d7560ecc376..00000000000
--- a/db/schema_migrations/20200805150316
+++ /dev/null
@@ -1 +0,0 @@
-983fa89c574e41a7d38eb558779f46d6d42aee5fba92f4185307e1508c401298 \ No newline at end of file
diff --git a/db/schema_migrations/20200805151001 b/db/schema_migrations/20200805151001
deleted file mode 100644
index 54c569efbdc..00000000000
--- a/db/schema_migrations/20200805151001
+++ /dev/null
@@ -1 +0,0 @@
-8fdb1e994ca7a28f7e061fb80cf210c482bafbe2bd0dc19c631c8fe9e0e2bbaf \ No newline at end of file
diff --git a/db/schema_migrations/20200805151726 b/db/schema_migrations/20200805151726
deleted file mode 100644
index 677f44c6380..00000000000
--- a/db/schema_migrations/20200805151726
+++ /dev/null
@@ -1 +0,0 @@
-e992135d6a4d10224b7e3deb304790735b6a35b5fb320670f9a7029e2924efb5 \ No newline at end of file
diff --git a/db/schema_migrations/20200805152108 b/db/schema_migrations/20200805152108
deleted file mode 100644
index 34522de208c..00000000000
--- a/db/schema_migrations/20200805152108
+++ /dev/null
@@ -1 +0,0 @@
-3976a084df88d7b6008a1d115d9c23d9c9084567c2cc5f1ddf68eaf1dc58ef3f \ No newline at end of file
diff --git a/db/schema_migrations/20200806004232 b/db/schema_migrations/20200806004232
deleted file mode 100644
index 840238684f9..00000000000
--- a/db/schema_migrations/20200806004232
+++ /dev/null
@@ -1 +0,0 @@
-4b1f048dfaea1887b20fdc421a08ab6206ab9944201e6517e808b27214be926c \ No newline at end of file
diff --git a/db/schema_migrations/20200806004742 b/db/schema_migrations/20200806004742
deleted file mode 100644
index fb6d9d49acf..00000000000
--- a/db/schema_migrations/20200806004742
+++ /dev/null
@@ -1 +0,0 @@
-acc9d1ab79e277e55910b17c5653088721371fa12b2cf1a5677035fe3b422fc8 \ No newline at end of file
diff --git a/db/schema_migrations/20200806172909 b/db/schema_migrations/20200806172909
deleted file mode 100644
index 44cc78808d5..00000000000
--- a/db/schema_migrations/20200806172909
+++ /dev/null
@@ -1 +0,0 @@
-b05401408faabafa4c2ef5fd241fea88f78fd423a3c462be89ccdbd8d988cfc8 \ No newline at end of file
diff --git a/db/schema_migrations/20200806173633 b/db/schema_migrations/20200806173633
deleted file mode 100644
index a0be6d39ece..00000000000
--- a/db/schema_migrations/20200806173633
+++ /dev/null
@@ -1 +0,0 @@
-5467b9c38186a30d333d9ccff0aeb4a06f97f17fec12488aca5e0a619b11831b \ No newline at end of file
diff --git a/db/schema_migrations/20200807070820 b/db/schema_migrations/20200807070820
deleted file mode 100644
index 61a886c4ce5..00000000000
--- a/db/schema_migrations/20200807070820
+++ /dev/null
@@ -1 +0,0 @@
-a1fb6b5d486eee27aaed5083aa6340073bf05abab8f201fd9097374dbd345b90 \ No newline at end of file
diff --git a/db/schema_migrations/20200807110237 b/db/schema_migrations/20200807110237
deleted file mode 100644
index fd02f50cdff..00000000000
--- a/db/schema_migrations/20200807110237
+++ /dev/null
@@ -1 +0,0 @@
-5aeb0e74859df14e460b39b9f070624a02278c13b1da9393e1671b4c79635f52 \ No newline at end of file
diff --git a/db/schema_migrations/20200807132726 b/db/schema_migrations/20200807132726
deleted file mode 100644
index a74b1ab23b6..00000000000
--- a/db/schema_migrations/20200807132726
+++ /dev/null
@@ -1 +0,0 @@
-867cea94f966c1ad3d9e02f7fa5b641ceac5a71667426330c2c96d6181164f66 \ No newline at end of file
diff --git a/db/schema_migrations/20200807150937 b/db/schema_migrations/20200807150937
deleted file mode 100644
index 8123db278a8..00000000000
--- a/db/schema_migrations/20200807150937
+++ /dev/null
@@ -1 +0,0 @@
-fdb18abe24003a75c76019fccf5ca0aa65a900bc2a86eb578012bc5a032730cf \ No newline at end of file
diff --git a/db/schema_migrations/20200807152315 b/db/schema_migrations/20200807152315
deleted file mode 100644
index 2256313368c..00000000000
--- a/db/schema_migrations/20200807152315
+++ /dev/null
@@ -1 +0,0 @@
-5152e094538b498fbe28f3fd11f6c1b9a9c77dc89ac0079cb39a6090a567db68 \ No newline at end of file
diff --git a/db/schema_migrations/20200808221641 b/db/schema_migrations/20200808221641
deleted file mode 100644
index 05e3769247e..00000000000
--- a/db/schema_migrations/20200808221641
+++ /dev/null
@@ -1 +0,0 @@
-a24aa5052d37bff1bffc5df076d8422ea90f3781ae01ecf626bc59f3e299c90b \ No newline at end of file
diff --git a/db/schema_migrations/20200809221641 b/db/schema_migrations/20200809221641
deleted file mode 100644
index 4e43680663a..00000000000
--- a/db/schema_migrations/20200809221641
+++ /dev/null
@@ -1 +0,0 @@
-4e360aa1b375e391ec1202f1fe2eb26d64895faf326ec9c7a9b8d8351b6f4dc3 \ No newline at end of file
diff --git a/db/schema_migrations/20200810100921 b/db/schema_migrations/20200810100921
deleted file mode 100644
index 14dc5a41721..00000000000
--- a/db/schema_migrations/20200810100921
+++ /dev/null
@@ -1 +0,0 @@
-fe96df46a5f360cafe8f9816c6dfc2d00afdcf458fb38ace37ce59999dba2413 \ No newline at end of file
diff --git a/db/schema_migrations/20200810101029 b/db/schema_migrations/20200810101029
deleted file mode 100644
index 59e0a236f3c..00000000000
--- a/db/schema_migrations/20200810101029
+++ /dev/null
@@ -1 +0,0 @@
-8bb03ea2ded957a41aa1efd60a9908a3c597aaaade9190f8f1515bfd2ab9a282 \ No newline at end of file
diff --git a/db/schema_migrations/20200810152043 b/db/schema_migrations/20200810152043
deleted file mode 100644
index 2b20ae9fdf1..00000000000
--- a/db/schema_migrations/20200810152043
+++ /dev/null
@@ -1 +0,0 @@
-d459b160ae86f035509e382c12b76fdd441f58e0838a983471326a750a48e9fd \ No newline at end of file
diff --git a/db/schema_migrations/20200810160355 b/db/schema_migrations/20200810160355
deleted file mode 100644
index 7e2ea4d495d..00000000000
--- a/db/schema_migrations/20200810160355
+++ /dev/null
@@ -1 +0,0 @@
-b5400a5e292f793986b102c7ddd0df8c7c5a7704b5121086a87792f7cdd0a2aa \ No newline at end of file
diff --git a/db/schema_migrations/20200810191256 b/db/schema_migrations/20200810191256
deleted file mode 100644
index c768252a228..00000000000
--- a/db/schema_migrations/20200810191256
+++ /dev/null
@@ -1 +0,0 @@
-66653e275889da8e695843f648af36c8a4e275b4d3215119eab4942db1b4b823 \ No newline at end of file
diff --git a/db/schema_migrations/20200811055018 b/db/schema_migrations/20200811055018
deleted file mode 100644
index abf090f8281..00000000000
--- a/db/schema_migrations/20200811055018
+++ /dev/null
@@ -1 +0,0 @@
-b7477fbcba166d848e3b1bd7f4a184f50f3b2fafe80bfcf44fd6f4f9979ffcb7 \ No newline at end of file
diff --git a/db/schema_migrations/20200811130000 b/db/schema_migrations/20200811130000
deleted file mode 100644
index a7df459c416..00000000000
--- a/db/schema_migrations/20200811130000
+++ /dev/null
@@ -1 +0,0 @@
-36d3db5618a56a0ea03272563fe254590d6af1f7d2610a1f01a5054b1cda1a7d \ No newline at end of file
diff --git a/db/schema_migrations/20200811130433 b/db/schema_migrations/20200811130433
deleted file mode 100644
index 303468e8949..00000000000
--- a/db/schema_migrations/20200811130433
+++ /dev/null
@@ -1 +0,0 @@
-e8fc0809b5bd3248dc625602deeaaef16e2db6b33d8eaf51fdcc1c67dee49e17 \ No newline at end of file
diff --git a/db/schema_migrations/20200811154630 b/db/schema_migrations/20200811154630
deleted file mode 100644
index 0498382ef2e..00000000000
--- a/db/schema_migrations/20200811154630
+++ /dev/null
@@ -1 +0,0 @@
-c04fe7e1a56bdcd41b5e1af346f9bfcae170d601954c4a0bcfcc9aea19d55528 \ No newline at end of file
diff --git a/db/schema_migrations/20200811154631 b/db/schema_migrations/20200811154631
deleted file mode 100644
index 1817460cd30..00000000000
--- a/db/schema_migrations/20200811154631
+++ /dev/null
@@ -1 +0,0 @@
-0ce17a8ad6c5ca5bba49ff522fede400fe6666490157af123ad98a7643f3ce01 \ No newline at end of file
diff --git a/db/schema_migrations/20200811154632 b/db/schema_migrations/20200811154632
deleted file mode 100644
index bb1167e3182..00000000000
--- a/db/schema_migrations/20200811154632
+++ /dev/null
@@ -1 +0,0 @@
-523f200c635e37ee1ac52257ffd45443a3e17bfe993d22775a5377865e044a46 \ No newline at end of file
diff --git a/db/schema_migrations/20200811194848 b/db/schema_migrations/20200811194848
deleted file mode 100644
index e1e9ad01ee8..00000000000
--- a/db/schema_migrations/20200811194848
+++ /dev/null
@@ -1 +0,0 @@
-c45bbd5aa9143e039d41448f1cb4a2e8e0a7b2c165b50e89b1b829bbbe81f137 \ No newline at end of file
diff --git a/db/schema_migrations/20200811211536 b/db/schema_migrations/20200811211536
deleted file mode 100644
index 1bd013900a3..00000000000
--- a/db/schema_migrations/20200811211536
+++ /dev/null
@@ -1 +0,0 @@
-d4ea24092289f6dba294c502b8ce89748165973fb2d7989fa7615433599a0c0c \ No newline at end of file
diff --git a/db/schema_migrations/20200812112204 b/db/schema_migrations/20200812112204
deleted file mode 100644
index 34ed55dc045..00000000000
--- a/db/schema_migrations/20200812112204
+++ /dev/null
@@ -1 +0,0 @@
-4fb7fda59db193250ca393cae5561fa52d61e025bb93b10829f114ac7fef4cfa \ No newline at end of file
diff --git a/db/schema_migrations/20200812150810 b/db/schema_migrations/20200812150810
deleted file mode 100644
index b5e6ce89ee4..00000000000
--- a/db/schema_migrations/20200812150810
+++ /dev/null
@@ -1 +0,0 @@
-a48d2b0ae00630775a3385aab6b6ae7ac5ebc999228605293c2e824c3651b7da \ No newline at end of file
diff --git a/db/schema_migrations/20200812150811 b/db/schema_migrations/20200812150811
deleted file mode 100644
index 08f760c8325..00000000000
--- a/db/schema_migrations/20200812150811
+++ /dev/null
@@ -1 +0,0 @@
-a7e650ffb9db2068168b486f8cb27c6bcdaad3682309e7c7df7e3c24c34c0498 \ No newline at end of file
diff --git a/db/schema_migrations/20200812150812 b/db/schema_migrations/20200812150812
deleted file mode 100644
index df4035363f6..00000000000
--- a/db/schema_migrations/20200812150812
+++ /dev/null
@@ -1 +0,0 @@
-d51302497aafd672954e1ea7613e33036fd3a083f4b0f349b3710058f1db0810 \ No newline at end of file
diff --git a/db/schema_migrations/20200813135558 b/db/schema_migrations/20200813135558
deleted file mode 100644
index 319f0a0b604..00000000000
--- a/db/schema_migrations/20200813135558
+++ /dev/null
@@ -1 +0,0 @@
-5f7a5fa697d769f5ccc9f0a6f19a91c8935f2559e019d50895574819494baf7e \ No newline at end of file
diff --git a/db/schema_migrations/20200813143304 b/db/schema_migrations/20200813143304
deleted file mode 100644
index 7c6f8560e65..00000000000
--- a/db/schema_migrations/20200813143304
+++ /dev/null
@@ -1 +0,0 @@
-12bb243862adf930fc68f2f7641ee7cc6170bfbcc3aae2b98bfa262dacfeba49 \ No newline at end of file
diff --git a/db/schema_migrations/20200813143356 b/db/schema_migrations/20200813143356
deleted file mode 100644
index bffd3f45ba7..00000000000
--- a/db/schema_migrations/20200813143356
+++ /dev/null
@@ -1 +0,0 @@
-7c4fec044a278fa51fdd23320a372528c420e8a650a26770fccf0cabe91163c5 \ No newline at end of file
diff --git a/db/schema_migrations/20200813153434 b/db/schema_migrations/20200813153434
deleted file mode 100644
index ca7c154abb7..00000000000
--- a/db/schema_migrations/20200813153434
+++ /dev/null
@@ -1 +0,0 @@
-23de9421726337f5279bf434542bffda24cbadc7324b498ff642ec4c0883b5d5 \ No newline at end of file
diff --git a/db/schema_migrations/20200816133024 b/db/schema_migrations/20200816133024
deleted file mode 100644
index 1637f166857..00000000000
--- a/db/schema_migrations/20200816133024
+++ /dev/null
@@ -1 +0,0 @@
-37196d54d03791f7509e411d5c545f22aa70f7c07d1f13d76f70008a06e72b57 \ No newline at end of file
diff --git a/db/schema_migrations/20200817070126 b/db/schema_migrations/20200817070126
deleted file mode 100644
index 8473e46982d..00000000000
--- a/db/schema_migrations/20200817070126
+++ /dev/null
@@ -1 +0,0 @@
-6776d7a401c1c56bd64a5585d123ba5aaba612348d66d4f8704530c5e8cc4f2d \ No newline at end of file
diff --git a/db/schema_migrations/20200817100710 b/db/schema_migrations/20200817100710
deleted file mode 100644
index 8062c3d46e4..00000000000
--- a/db/schema_migrations/20200817100710
+++ /dev/null
@@ -1 +0,0 @@
-87d3529596f5b5adff7280be7c60e4ff290dd05c500bbeb00cda0ac5da6239e0 \ No newline at end of file
diff --git a/db/schema_migrations/20200817142800 b/db/schema_migrations/20200817142800
deleted file mode 100644
index d6db856dac4..00000000000
--- a/db/schema_migrations/20200817142800
+++ /dev/null
@@ -1 +0,0 @@
-b488cd2049300b293f584f193edc5435855f7bc85989648a3310dabc609d0af4 \ No newline at end of file
diff --git a/db/schema_migrations/20200817195628 b/db/schema_migrations/20200817195628
deleted file mode 100644
index 7d919242d89..00000000000
--- a/db/schema_migrations/20200817195628
+++ /dev/null
@@ -1 +0,0 @@
-4da25ee40eabd81765b562929c819da1fc2b0f8afe1f4eefe6b769fcd8f0d4cd \ No newline at end of file
diff --git a/db/schema_migrations/20200818052219 b/db/schema_migrations/20200818052219
deleted file mode 100644
index 1df09a53ca4..00000000000
--- a/db/schema_migrations/20200818052219
+++ /dev/null
@@ -1 +0,0 @@
-94b494b5f8e351cf453699debf03aa28f8a9136c829cb7410c90590b5106cdd5 \ No newline at end of file
diff --git a/db/schema_migrations/20200818092401 b/db/schema_migrations/20200818092401
deleted file mode 100644
index 916b5421e70..00000000000
--- a/db/schema_migrations/20200818092401
+++ /dev/null
@@ -1 +0,0 @@
-39d412a1680d55466c14450943e17802eb183f2f33f2f77078cba571262cd149 \ No newline at end of file
diff --git a/db/schema_migrations/20200818171229 b/db/schema_migrations/20200818171229
deleted file mode 100644
index 91470670c26..00000000000
--- a/db/schema_migrations/20200818171229
+++ /dev/null
@@ -1 +0,0 @@
-987f316571f41ad679cad54089bc523f62d04691c10e5cf1957cf60edd71f889 \ No newline at end of file
diff --git a/db/schema_migrations/20200819082334 b/db/schema_migrations/20200819082334
deleted file mode 100644
index 28d83ca820d..00000000000
--- a/db/schema_migrations/20200819082334
+++ /dev/null
@@ -1 +0,0 @@
-c12f3f5b76e1065867682216348dd95c22d605c30ae54615f2596b1d84aad199 \ No newline at end of file
diff --git a/db/schema_migrations/20200819113644 b/db/schema_migrations/20200819113644
deleted file mode 100644
index 2208ad26134..00000000000
--- a/db/schema_migrations/20200819113644
+++ /dev/null
@@ -1 +0,0 @@
-19c90689d0af6adb017dbd7127c6cd147d9c92581118dbfd99c87bc6a6dda3be \ No newline at end of file
diff --git a/db/schema_migrations/20200819192143 b/db/schema_migrations/20200819192143
deleted file mode 100644
index e0934e15f1f..00000000000
--- a/db/schema_migrations/20200819192143
+++ /dev/null
@@ -1 +0,0 @@
-5a5278fdd9539d33a6de226a84ed39b7c5a26929cec68ec5e8d193afb3cfafa2 \ No newline at end of file
diff --git a/db/schema_migrations/20200819202048 b/db/schema_migrations/20200819202048
deleted file mode 100644
index a5428c7b40a..00000000000
--- a/db/schema_migrations/20200819202048
+++ /dev/null
@@ -1 +0,0 @@
-476bce9b18177f37b31e15d42f5a1391c0bfbbd312a513c1d5b43085b90afb3e \ No newline at end of file
diff --git a/db/schema_migrations/20200819202222 b/db/schema_migrations/20200819202222
deleted file mode 100644
index f633502d0bb..00000000000
--- a/db/schema_migrations/20200819202222
+++ /dev/null
@@ -1 +0,0 @@
-5e2dfdf725ad0a3d90b240ced74cf5a872f7126b716847f9f9e99b4ad2a22109 \ No newline at end of file
diff --git a/db/schema_migrations/20200820105408 b/db/schema_migrations/20200820105408
deleted file mode 100644
index 647a86797dd..00000000000
--- a/db/schema_migrations/20200820105408
+++ /dev/null
@@ -1 +0,0 @@
-e21ae06853e3a071669fa8e9ed2638f0e7854813bc5a1639b31ad6edb50f6427 \ No newline at end of file
diff --git a/db/schema_migrations/20200820130839 b/db/schema_migrations/20200820130839
deleted file mode 100644
index e372e4df2be..00000000000
--- a/db/schema_migrations/20200820130839
+++ /dev/null
@@ -1 +0,0 @@
-751a2c8e06b522b1564ea09f961d8883543a631874ae26bb14c98b7b442d59cc \ No newline at end of file
diff --git a/db/schema_migrations/20200820204041 b/db/schema_migrations/20200820204041
deleted file mode 100644
index 43e564a759d..00000000000
--- a/db/schema_migrations/20200820204041
+++ /dev/null
@@ -1 +0,0 @@
-ce4d108c6587943ab3740dcc39298d6877d7317ec1023d8d263cecd9f1e0f478 \ No newline at end of file
diff --git a/db/schema_migrations/20200821034419 b/db/schema_migrations/20200821034419
deleted file mode 100644
index 56ede8eff69..00000000000
--- a/db/schema_migrations/20200821034419
+++ /dev/null
@@ -1 +0,0 @@
-ddf3452bb44437324d20c9db03e998f8903f5ff9732d29cf85dd5d579507952d \ No newline at end of file
diff --git a/db/schema_migrations/20200821194920 b/db/schema_migrations/20200821194920
deleted file mode 100644
index b681c3269c3..00000000000
--- a/db/schema_migrations/20200821194920
+++ /dev/null
@@ -1 +0,0 @@
-d92cdef33a892fdd1761d9491bc8e4c782e9db348d4a6848a1470e99e644fbfd \ No newline at end of file
diff --git a/db/schema_migrations/20200821224343 b/db/schema_migrations/20200821224343
deleted file mode 100644
index 63a2144dc9d..00000000000
--- a/db/schema_migrations/20200821224343
+++ /dev/null
@@ -1 +0,0 @@
-f5f7cfe4a8f42a7116ecf50230df2705135bea4e5fd4c75512bb9ca15867919b \ No newline at end of file
diff --git a/db/schema_migrations/20200824045812 b/db/schema_migrations/20200824045812
deleted file mode 100644
index c628ca3eb18..00000000000
--- a/db/schema_migrations/20200824045812
+++ /dev/null
@@ -1 +0,0 @@
-4f3528d7df6e61c8b14911644f9223ac5f6e678184d1c8370d1e9a60389cd60c \ No newline at end of file
diff --git a/db/schema_migrations/20200824124623 b/db/schema_migrations/20200824124623
deleted file mode 100644
index 367de6bda2e..00000000000
--- a/db/schema_migrations/20200824124623
+++ /dev/null
@@ -1 +0,0 @@
-b8fcbdab769758753efae992e64bed7f79149c74f08294035a48a03c59bb1c5d \ No newline at end of file
diff --git a/db/schema_migrations/20200824130028 b/db/schema_migrations/20200824130028
deleted file mode 100644
index 961a11848c9..00000000000
--- a/db/schema_migrations/20200824130028
+++ /dev/null
@@ -1 +0,0 @@
-891f1660592c4443aeced7594cea391066cc79b54b40c67a8c973eb6959bf6f1 \ No newline at end of file
diff --git a/db/schema_migrations/20200824130447 b/db/schema_migrations/20200824130447
deleted file mode 100644
index 901d79466b6..00000000000
--- a/db/schema_migrations/20200824130447
+++ /dev/null
@@ -1 +0,0 @@
-e6dcd20fe77c443999aa2373e0acdd77eb68c3a6f0d6d65e86b7f85ac97ddb9a \ No newline at end of file
diff --git a/db/schema_migrations/20200825071735 b/db/schema_migrations/20200825071735
deleted file mode 100644
index fe108bfb9cf..00000000000
--- a/db/schema_migrations/20200825071735
+++ /dev/null
@@ -1 +0,0 @@
-cd8574318fae1f2bb021b53d4e453c6b64c763f0e7cc8836cdb8b12963ff0e18 \ No newline at end of file
diff --git a/db/schema_migrations/20200825081025 b/db/schema_migrations/20200825081025
deleted file mode 100644
index db869574f35..00000000000
--- a/db/schema_migrations/20200825081025
+++ /dev/null
@@ -1 +0,0 @@
-1ee7ae93dde7099f78cd6218b5419a34b2cfebe196521bcbee1583e31f19ffda \ No newline at end of file
diff --git a/db/schema_migrations/20200825081035 b/db/schema_migrations/20200825081035
deleted file mode 100644
index 45bdfd00bf0..00000000000
--- a/db/schema_migrations/20200825081035
+++ /dev/null
@@ -1 +0,0 @@
-26fe286e565f776f64ae8b6b0ad91ef1d3bf2195384f44f8b093a1b66ee0d05d \ No newline at end of file
diff --git a/db/schema_migrations/20200825081045 b/db/schema_migrations/20200825081045
deleted file mode 100644
index 67273493881..00000000000
--- a/db/schema_migrations/20200825081045
+++ /dev/null
@@ -1 +0,0 @@
-deb88efebc989a014b6ecaca4a91624d1b21f34c85cbf6d3460363f1b498b427 \ No newline at end of file
diff --git a/db/schema_migrations/20200825081055 b/db/schema_migrations/20200825081055
deleted file mode 100644
index 7694c97bf9d..00000000000
--- a/db/schema_migrations/20200825081055
+++ /dev/null
@@ -1 +0,0 @@
-8fc437f09321cfe29262075009bce6f7b0047c2291df4a29bcc304c6dd54d27d \ No newline at end of file
diff --git a/db/schema_migrations/20200825084819 b/db/schema_migrations/20200825084819
deleted file mode 100644
index 0ce9dbf863c..00000000000
--- a/db/schema_migrations/20200825084819
+++ /dev/null
@@ -1 +0,0 @@
-d5e81848257b3391d99b198b177531a4c190ca6f19b27c9aedaa931f6eb3165a \ No newline at end of file
diff --git a/db/schema_migrations/20200825154237 b/db/schema_migrations/20200825154237
deleted file mode 100644
index 5f56cf2d631..00000000000
--- a/db/schema_migrations/20200825154237
+++ /dev/null
@@ -1 +0,0 @@
-ff41fa940a0a5c3627dfec22ed4e704d6edc534edf30883a36aa454210bb3d43 \ No newline at end of file
diff --git a/db/schema_migrations/20200825180050 b/db/schema_migrations/20200825180050
deleted file mode 100644
index 0e2e9220740..00000000000
--- a/db/schema_migrations/20200825180050
+++ /dev/null
@@ -1 +0,0 @@
-330340ef4d525e1e13ed28d71d23594627453955ce5f810e370d07bb3623bf35 \ No newline at end of file
diff --git a/db/schema_migrations/20200826053152 b/db/schema_migrations/20200826053152
deleted file mode 100644
index 26cf99ee7f2..00000000000
--- a/db/schema_migrations/20200826053152
+++ /dev/null
@@ -1 +0,0 @@
-d7dd6ef7c39576988d1efd7bb179f75e3104fc8058a671e47c7b68ba2ddc9ba8 \ No newline at end of file
diff --git a/db/schema_migrations/20200826073745 b/db/schema_migrations/20200826073745
deleted file mode 100644
index 0200c7bc66a..00000000000
--- a/db/schema_migrations/20200826073745
+++ /dev/null
@@ -1 +0,0 @@
-d3b15469120ed213363de33a4b268ed71a710c40f02d4a669edf2c5412907209 \ No newline at end of file
diff --git a/db/schema_migrations/20200826092324 b/db/schema_migrations/20200826092324
deleted file mode 100644
index 8745b628965..00000000000
--- a/db/schema_migrations/20200826092324
+++ /dev/null
@@ -1 +0,0 @@
-35c37b8dcdca08d48086dc8164c2f6a69f563366ec9bce1f60299978a94de9bc \ No newline at end of file
diff --git a/db/schema_migrations/20200826121552 b/db/schema_migrations/20200826121552
deleted file mode 100644
index e794680240a..00000000000
--- a/db/schema_migrations/20200826121552
+++ /dev/null
@@ -1 +0,0 @@
-8667c30042b19428b97e0995821c183e69f73394503c83a55ba7bd870df7c3e8 \ No newline at end of file
diff --git a/db/schema_migrations/20200826212800 b/db/schema_migrations/20200826212800
deleted file mode 100644
index 3eaae5c48c8..00000000000
--- a/db/schema_migrations/20200826212800
+++ /dev/null
@@ -1 +0,0 @@
-360c42f4d34c3b03e7a0375a0ff2776f066888f0a40131180bf301b876ea58db \ No newline at end of file
diff --git a/db/schema_migrations/20200826220745 b/db/schema_migrations/20200826220745
deleted file mode 100644
index 39134fb6223..00000000000
--- a/db/schema_migrations/20200826220745
+++ /dev/null
@@ -1 +0,0 @@
-ee38dd60087a8879c4686214da1d25a60ab74306eb07b938efb1a8dfc46cc73a \ No newline at end of file
diff --git a/db/schema_migrations/20200826220746 b/db/schema_migrations/20200826220746
deleted file mode 100644
index 1ff87e8df6d..00000000000
--- a/db/schema_migrations/20200826220746
+++ /dev/null
@@ -1 +0,0 @@
-2564c387b727e557b2988996aa533ba5e4e6d7b01515407bd2692c09644ac2be \ No newline at end of file
diff --git a/db/schema_migrations/20200827005322 b/db/schema_migrations/20200827005322
deleted file mode 100644
index 23ae58e766c..00000000000
--- a/db/schema_migrations/20200827005322
+++ /dev/null
@@ -1 +0,0 @@
-f4f1efcc93476a1d70add93e166f4c702ad7dfc97ad29c3455722fd98824498f \ No newline at end of file
diff --git a/db/schema_migrations/20200827060911 b/db/schema_migrations/20200827060911
deleted file mode 100644
index a93302067cd..00000000000
--- a/db/schema_migrations/20200827060911
+++ /dev/null
@@ -1 +0,0 @@
-124f6ba79f71e2de510741b22d3dd5cf15378b5476c759484bd814377a644256 \ No newline at end of file
diff --git a/db/schema_migrations/20200827060932 b/db/schema_migrations/20200827060932
deleted file mode 100644
index af7d00f21f2..00000000000
--- a/db/schema_migrations/20200827060932
+++ /dev/null
@@ -1 +0,0 @@
-ba2e32b4836062631308937023470d31b3f808b468999ba15374c3b953377402 \ No newline at end of file
diff --git a/db/schema_migrations/20200827085101 b/db/schema_migrations/20200827085101
deleted file mode 100644
index 930e0176a52..00000000000
--- a/db/schema_migrations/20200827085101
+++ /dev/null
@@ -1 +0,0 @@
-bdcfd7dbccc73d6e2754d67bf099cc2dd2b919e4125cec47e853ff91911cc82e \ No newline at end of file
diff --git a/db/schema_migrations/20200827102234 b/db/schema_migrations/20200827102234
deleted file mode 100644
index 8f5656a92c6..00000000000
--- a/db/schema_migrations/20200827102234
+++ /dev/null
@@ -1 +0,0 @@
-d38ef8ccd627e70adf0dd9ac8161235e21afccbc59f1e8d95f379f66eb84630e \ No newline at end of file
diff --git a/db/schema_migrations/20200827104432 b/db/schema_migrations/20200827104432
deleted file mode 100644
index 351974f884b..00000000000
--- a/db/schema_migrations/20200827104432
+++ /dev/null
@@ -1 +0,0 @@
-99d95dea0dbb10bcaca5515c144c7fcd1e365e69be5eded223379bf61df69bc3 \ No newline at end of file
diff --git a/db/schema_migrations/20200827114902 b/db/schema_migrations/20200827114902
deleted file mode 100644
index 769a0a56b4b..00000000000
--- a/db/schema_migrations/20200827114902
+++ /dev/null
@@ -1 +0,0 @@
-f581bd5f5ec26dc33643c77fb8c7a64a9053b55c3f6a7281fea89ac4790a58d2 \ No newline at end of file
diff --git a/db/schema_migrations/20200827142811 b/db/schema_migrations/20200827142811
deleted file mode 100644
index c1edecb9575..00000000000
--- a/db/schema_migrations/20200827142811
+++ /dev/null
@@ -1 +0,0 @@
-0e2b3433577946177876f14ec414a1653c1edeaa796eea24f12740958f964442 \ No newline at end of file
diff --git a/db/schema_migrations/20200827150057 b/db/schema_migrations/20200827150057
deleted file mode 100644
index 31a7d2e3f2e..00000000000
--- a/db/schema_migrations/20200827150057
+++ /dev/null
@@ -1 +0,0 @@
-85b7ffba53c9cec30e9778dd806277ca8e9877c9a18dc1d6004402c0e66b8ef1 \ No newline at end of file
diff --git a/db/schema_migrations/20200828155134 b/db/schema_migrations/20200828155134
deleted file mode 100644
index f622a308fcc..00000000000
--- a/db/schema_migrations/20200828155134
+++ /dev/null
@@ -1 +0,0 @@
-b3ee994231a8da694dbcda227b37e19a2112be666648d918425b064ec19d239e \ No newline at end of file
diff --git a/db/schema_migrations/20200828155205 b/db/schema_migrations/20200828155205
deleted file mode 100644
index d864c122afa..00000000000
--- a/db/schema_migrations/20200828155205
+++ /dev/null
@@ -1 +0,0 @@
-b575558752206149171a05231e4167e1ac3e1295f76d800edfe3d61c1b996b52 \ No newline at end of file
diff --git a/db/schema_migrations/20200830201204 b/db/schema_migrations/20200830201204
deleted file mode 100644
index 370640eb119..00000000000
--- a/db/schema_migrations/20200830201204
+++ /dev/null
@@ -1 +0,0 @@
-1e8dd4542b13009b748d352933a4a59fcabb31e916226fcbf87043396f94e09f \ No newline at end of file
diff --git a/db/schema_migrations/20200831065320 b/db/schema_migrations/20200831065320
deleted file mode 100644
index 127a6a18d9d..00000000000
--- a/db/schema_migrations/20200831065320
+++ /dev/null
@@ -1 +0,0 @@
-3e704cf329786e89f43fdefbc6a91272bebc6af5653dd83b5a81567937f75752 \ No newline at end of file
diff --git a/db/schema_migrations/20200831065322 b/db/schema_migrations/20200831065322
deleted file mode 100644
index ab56be867e8..00000000000
--- a/db/schema_migrations/20200831065322
+++ /dev/null
@@ -1 +0,0 @@
-4cb28d6da005682bb077427f4f544996065e86f0e76d5de98fc1761555a0535b \ No newline at end of file
diff --git a/db/schema_migrations/20200831065705 b/db/schema_migrations/20200831065705
deleted file mode 100644
index 385a9511d91..00000000000
--- a/db/schema_migrations/20200831065705
+++ /dev/null
@@ -1 +0,0 @@
-c1457272bd8f0055992df5d4a8ba1a62cb74d3af3fff25447b3abd2eb090841e \ No newline at end of file
diff --git a/db/schema_migrations/20200831074356 b/db/schema_migrations/20200831074356
deleted file mode 100644
index cea1905fd1b..00000000000
--- a/db/schema_migrations/20200831074356
+++ /dev/null
@@ -1 +0,0 @@
-8605268a026d4c66653008bb051c567c251044232b925b89f4407f9ad70f639c \ No newline at end of file
diff --git a/db/schema_migrations/20200831204646 b/db/schema_migrations/20200831204646
deleted file mode 100644
index ff4f71e8fc7..00000000000
--- a/db/schema_migrations/20200831204646
+++ /dev/null
@@ -1 +0,0 @@
-06e87d83d5520e6ffbfb839d15a6dd02ad2caf5737136441d496e29e03a07e64 \ No newline at end of file
diff --git a/db/schema_migrations/20200831222347 b/db/schema_migrations/20200831222347
deleted file mode 100644
index 6a01ea5cdc3..00000000000
--- a/db/schema_migrations/20200831222347
+++ /dev/null
@@ -1 +0,0 @@
-00af22b19af29b453f0022ded835bd9246c602c63a04a51ef93cbedd47047753 \ No newline at end of file
diff --git a/db/schema_migrations/20200831224343 b/db/schema_migrations/20200831224343
deleted file mode 100644
index 5aabfb7d1cf..00000000000
--- a/db/schema_migrations/20200831224343
+++ /dev/null
@@ -1 +0,0 @@
-ce72274a7cc38c3708a03b8a301c6dafa6543acb03c8638a972c197657182ccf \ No newline at end of file
diff --git a/db/schema_migrations/20200901170135 b/db/schema_migrations/20200901170135
deleted file mode 100644
index 4f0f5213a98..00000000000
--- a/db/schema_migrations/20200901170135
+++ /dev/null
@@ -1 +0,0 @@
-fca99780272ca4ceb42fd38d16f67cd4a0a675ecdaf91e51c4c0728205212ed0 \ No newline at end of file
diff --git a/db/schema_migrations/20200901203055 b/db/schema_migrations/20200901203055
deleted file mode 100644
index 166f9069f40..00000000000
--- a/db/schema_migrations/20200901203055
+++ /dev/null
@@ -1 +0,0 @@
-eb13fb285ac9af83bbc66397a5352a824575ad4af93178b98fbfc1be2e11ce8b \ No newline at end of file
diff --git a/db/schema_migrations/20200901212304 b/db/schema_migrations/20200901212304
deleted file mode 100644
index 3dcc9cdd8f0..00000000000
--- a/db/schema_migrations/20200901212304
+++ /dev/null
@@ -1 +0,0 @@
-6fb93002ffd5c1d1bfff5bea8a99cbbfc7cefefbc450a9d067ee0cfab8d11e9e \ No newline at end of file
diff --git a/db/schema_migrations/20200901214416 b/db/schema_migrations/20200901214416
deleted file mode 100644
index bb7481c254d..00000000000
--- a/db/schema_migrations/20200901214416
+++ /dev/null
@@ -1 +0,0 @@
-b196c8ce85631432e712a977b09cdba70872f42b16bca53eda1bc8558f57ea24 \ No newline at end of file
diff --git a/db/schema_migrations/20200902135542 b/db/schema_migrations/20200902135542
deleted file mode 100644
index 96ee06f291b..00000000000
--- a/db/schema_migrations/20200902135542
+++ /dev/null
@@ -1 +0,0 @@
-58e1e87a9a0159d62db761d8caa91a5bf2cc1a2ccceb1b57ff35b53f7698d08f \ No newline at end of file
diff --git a/db/schema_migrations/20200903054946 b/db/schema_migrations/20200903054946
deleted file mode 100644
index 20a4874b1bc..00000000000
--- a/db/schema_migrations/20200903054946
+++ /dev/null
@@ -1 +0,0 @@
-f9aa112661a55c9eeed1a6aa05dd4c28d6f88971dc14bb606e677d4b4a4e5947 \ No newline at end of file
diff --git a/db/schema_migrations/20200903064431 b/db/schema_migrations/20200903064431
deleted file mode 100644
index a3351912182..00000000000
--- a/db/schema_migrations/20200903064431
+++ /dev/null
@@ -1 +0,0 @@
-5c065dc7905fd1292e270d2248810d71fa71d6b6996e9d60c463a7eb36042881 \ No newline at end of file
diff --git a/db/schema_migrations/20200903092241 b/db/schema_migrations/20200903092241
deleted file mode 100644
index bedd97c3918..00000000000
--- a/db/schema_migrations/20200903092241
+++ /dev/null
@@ -1 +0,0 @@
-e6c3d5352feed1adc82b14218a6f47fa55df9e0add8a59228d128e4e7f39614b \ No newline at end of file
diff --git a/db/schema_migrations/20200904092131 b/db/schema_migrations/20200904092131
deleted file mode 100644
index ab6f0aaa8ad..00000000000
--- a/db/schema_migrations/20200904092131
+++ /dev/null
@@ -1 +0,0 @@
-024d4448f6cd9b9fd8f6d1892882de596928d0265e91f79c6a52431c8fb3c08b \ No newline at end of file
diff --git a/db/schema_migrations/20200904131544 b/db/schema_migrations/20200904131544
deleted file mode 100644
index 62ff8ff56e7..00000000000
--- a/db/schema_migrations/20200904131544
+++ /dev/null
@@ -1 +0,0 @@
-08c9c6e5cd19aac17de7fc639eaca5ddba3e8280452821b8a72f05dcde790feb \ No newline at end of file
diff --git a/db/schema_migrations/20200904174901 b/db/schema_migrations/20200904174901
deleted file mode 100644
index 6803b8ba0e2..00000000000
--- a/db/schema_migrations/20200904174901
+++ /dev/null
@@ -1 +0,0 @@
-739a4d5374ae2be419c5a2f8c1427f85a0b76c90233918b7b43f1c166ab06cec \ No newline at end of file
diff --git a/db/schema_migrations/20200905013247 b/db/schema_migrations/20200905013247
deleted file mode 100644
index b0926ca1d99..00000000000
--- a/db/schema_migrations/20200905013247
+++ /dev/null
@@ -1 +0,0 @@
-860c45fd6293f2f8f10d7351cb5a2fbab2cc9147e56b538cb62d75469b039ef0 \ No newline at end of file
diff --git a/db/schema_migrations/20200907021256 b/db/schema_migrations/20200907021256
deleted file mode 100644
index a8e8b257104..00000000000
--- a/db/schema_migrations/20200907021256
+++ /dev/null
@@ -1 +0,0 @@
-5fba5213226186a1506f672eb3eab2d07f58b019c4ba13760663cb119f62d4e2 \ No newline at end of file
diff --git a/db/schema_migrations/20200907062101 b/db/schema_migrations/20200907062101
deleted file mode 100644
index b4bf6bbb781..00000000000
--- a/db/schema_migrations/20200907062101
+++ /dev/null
@@ -1 +0,0 @@
-002c92f830762d97dcbdbcf8a0287ebbb576edc27f4f76f4bb18d043e956ba7a \ No newline at end of file
diff --git a/db/schema_migrations/20200907092610 b/db/schema_migrations/20200907092610
deleted file mode 100644
index 63eecc83a3c..00000000000
--- a/db/schema_migrations/20200907092610
+++ /dev/null
@@ -1 +0,0 @@
-de1051e8f2d9f042ac923686b8c61e743c695736e8c7ebfdf6f87ab1ed09a11f \ No newline at end of file
diff --git a/db/schema_migrations/20200907092715 b/db/schema_migrations/20200907092715
deleted file mode 100644
index 700db177075..00000000000
--- a/db/schema_migrations/20200907092715
+++ /dev/null
@@ -1 +0,0 @@
-2610104c89134b94d460a714f17c23e5e35d76147c1f25be6c02804a39725d6c \ No newline at end of file
diff --git a/db/schema_migrations/20200907124300 b/db/schema_migrations/20200907124300
deleted file mode 100644
index a156f95f428..00000000000
--- a/db/schema_migrations/20200907124300
+++ /dev/null
@@ -1 +0,0 @@
-2311967a9f68e1a428662e0231752ad0d844063d66cca895211d38f9ae928d94 \ No newline at end of file
diff --git a/db/schema_migrations/20200908033805 b/db/schema_migrations/20200908033805
deleted file mode 100644
index dc2103face3..00000000000
--- a/db/schema_migrations/20200908033805
+++ /dev/null
@@ -1 +0,0 @@
-5f932b8a3503fc275ba6d09436115999b32f6438700e3b719f53730c5527a354 \ No newline at end of file
diff --git a/db/schema_migrations/20200908064229 b/db/schema_migrations/20200908064229
deleted file mode 100644
index 37958f04de8..00000000000
--- a/db/schema_migrations/20200908064229
+++ /dev/null
@@ -1 +0,0 @@
-e73076f6d7540372ee16fe26dcb44e8b84dde69e27c46483ee26883e81059501 \ No newline at end of file
diff --git a/db/schema_migrations/20200908094810 b/db/schema_migrations/20200908094810
deleted file mode 100644
index a047e64107b..00000000000
--- a/db/schema_migrations/20200908094810
+++ /dev/null
@@ -1 +0,0 @@
-327cd19cd6c0f273aea61ffebf10046fb7229516bc4ed28f3c0290bb3ad04755 \ No newline at end of file
diff --git a/db/schema_migrations/20200908095446 b/db/schema_migrations/20200908095446
deleted file mode 100644
index dbb164d9695..00000000000
--- a/db/schema_migrations/20200908095446
+++ /dev/null
@@ -1 +0,0 @@
-3cd8614d1d93340b4607d5270b54ec96b60b04a830c0a15a84b9843048515a12 \ No newline at end of file
diff --git a/db/schema_migrations/20200908100053 b/db/schema_migrations/20200908100053
deleted file mode 100644
index f57b8f3a317..00000000000
--- a/db/schema_migrations/20200908100053
+++ /dev/null
@@ -1 +0,0 @@
-5642f7d91bbbd20d1e3a964b6a06a4da14474db58f47e3ee0ce3273f7cd7a9e8 \ No newline at end of file
diff --git a/db/schema_migrations/20200908183231 b/db/schema_migrations/20200908183231
deleted file mode 100644
index e194dc37b36..00000000000
--- a/db/schema_migrations/20200908183231
+++ /dev/null
@@ -1 +0,0 @@
-9eadbb80f137ba0123c96e04ded21cc313560b7a293c241c6a72ebd35248a84b \ No newline at end of file
diff --git a/db/schema_migrations/20200908212414 b/db/schema_migrations/20200908212414
deleted file mode 100644
index 208f9affc91..00000000000
--- a/db/schema_migrations/20200908212414
+++ /dev/null
@@ -1 +0,0 @@
-a9605126178d887bbf526a4a33b7060b072eff7a8d6712e3552099f7e615f88b \ No newline at end of file
diff --git a/db/schema_migrations/20200909040555 b/db/schema_migrations/20200909040555
deleted file mode 100644
index 27855514146..00000000000
--- a/db/schema_migrations/20200909040555
+++ /dev/null
@@ -1 +0,0 @@
-f68d29be164299e5ccf73347841d27b17f028941e37e3510d3da9d513762a17f \ No newline at end of file
diff --git a/db/schema_migrations/20200909083339 b/db/schema_migrations/20200909083339
deleted file mode 100644
index 179a683412c..00000000000
--- a/db/schema_migrations/20200909083339
+++ /dev/null
@@ -1 +0,0 @@
-8b2090e953e6205b65555408a88d3da7f6bce28b0baa52d1a43a3a3e8001b7e1 \ No newline at end of file
diff --git a/db/schema_migrations/20200909161624 b/db/schema_migrations/20200909161624
deleted file mode 100644
index 941af468398..00000000000
--- a/db/schema_migrations/20200909161624
+++ /dev/null
@@ -1 +0,0 @@
-2d7f514429e9a08ce13995feff43e221b3e2e74737ed48f81e104008d8ec24b9 \ No newline at end of file
diff --git a/db/schema_migrations/20200909194014 b/db/schema_migrations/20200909194014
deleted file mode 100644
index ef647b603f3..00000000000
--- a/db/schema_migrations/20200909194014
+++ /dev/null
@@ -1 +0,0 @@
-9579a789ed6256a513a7afb51eeaf11661d1ef2e5d8312e28a69579eb39d8960 \ No newline at end of file
diff --git a/db/schema_migrations/20200909194524 b/db/schema_migrations/20200909194524
deleted file mode 100644
index e4158445318..00000000000
--- a/db/schema_migrations/20200909194524
+++ /dev/null
@@ -1 +0,0 @@
-c0f798f6ffd8d67137e6076242f5fb0004736f03c9cde5556dec228eefa75cb1 \ No newline at end of file
diff --git a/db/schema_migrations/20200910131217 b/db/schema_migrations/20200910131217
deleted file mode 100644
index 6aba73661f7..00000000000
--- a/db/schema_migrations/20200910131217
+++ /dev/null
@@ -1 +0,0 @@
-205580c1ba38fd03ce025dfd1d9be67756ade4fd28ba957bb71cd9e5e89ef190 \ No newline at end of file
diff --git a/db/schema_migrations/20200910131218 b/db/schema_migrations/20200910131218
deleted file mode 100644
index c0e5f36d8d7..00000000000
--- a/db/schema_migrations/20200910131218
+++ /dev/null
@@ -1 +0,0 @@
-ba431f19818b93da91c4ed2c3f25dc8e2f62c6d9ac07b15f6d01f21f085c1730 \ No newline at end of file
diff --git a/db/schema_migrations/20200910155617 b/db/schema_migrations/20200910155617
deleted file mode 100644
index 901b6c0545c..00000000000
--- a/db/schema_migrations/20200910155617
+++ /dev/null
@@ -1 +0,0 @@
-6cba0aecae495458b3b161999417cb9d790e60b4edfb10bb26b9684d466e3fd2 \ No newline at end of file
diff --git a/db/schema_migrations/20200910170908 b/db/schema_migrations/20200910170908
deleted file mode 100644
index 12ab216f093..00000000000
--- a/db/schema_migrations/20200910170908
+++ /dev/null
@@ -1 +0,0 @@
-de13fed042f6e3d2a6612a77acebf168c8beddab5796b96f2d77886dea431ceb \ No newline at end of file
diff --git a/db/schema_migrations/20200910175553 b/db/schema_migrations/20200910175553
deleted file mode 100644
index fff67f5a2f6..00000000000
--- a/db/schema_migrations/20200910175553
+++ /dev/null
@@ -1 +0,0 @@
-904e0a8623df766a1f385bbb3db8942d10c4a92354d8f5e3bc03a813337c5fa1 \ No newline at end of file
diff --git a/db/schema_migrations/20200911120132 b/db/schema_migrations/20200911120132
deleted file mode 100644
index a9ce2c72ac2..00000000000
--- a/db/schema_migrations/20200911120132
+++ /dev/null
@@ -1 +0,0 @@
-8c9a7ead17d7378337e7bcfd25a10064c70a3bbb4604bdbb24065951131045dd \ No newline at end of file
diff --git a/db/schema_migrations/20200911121027 b/db/schema_migrations/20200911121027
deleted file mode 100644
index 495b12264ee..00000000000
--- a/db/schema_migrations/20200911121027
+++ /dev/null
@@ -1 +0,0 @@
-59cbcbe3f8491e150f37a3954c89cc58a52aa0a985c66f252c71d679429ffba1 \ No newline at end of file
diff --git a/db/schema_migrations/20200911121048 b/db/schema_migrations/20200911121048
deleted file mode 100644
index f10c7e0442c..00000000000
--- a/db/schema_migrations/20200911121048
+++ /dev/null
@@ -1 +0,0 @@
-51fe3e71baaf55730bf51f3ad5d429b7cfdc6c43319babb9af28bdc13aab2fc9 \ No newline at end of file
diff --git a/db/schema_migrations/20200912152943 b/db/schema_migrations/20200912152943
deleted file mode 100644
index 4dd1ae708cd..00000000000
--- a/db/schema_migrations/20200912152943
+++ /dev/null
@@ -1 +0,0 @@
-b8d7a2ec9ecf51fd7cb9346e1484b45d5b472a85d90ad270d08c1cca1b44f039 \ No newline at end of file
diff --git a/db/schema_migrations/20200912153218 b/db/schema_migrations/20200912153218
deleted file mode 100644
index 9c013281ea2..00000000000
--- a/db/schema_migrations/20200912153218
+++ /dev/null
@@ -1 +0,0 @@
-fd632247f1588c537e83574edd7936c530e154091e3101d0404da3b7ef8b4bef \ No newline at end of file
diff --git a/db/schema_migrations/20200912193210 b/db/schema_migrations/20200912193210
deleted file mode 100644
index a6ce007630a..00000000000
--- a/db/schema_migrations/20200912193210
+++ /dev/null
@@ -1 +0,0 @@
-bcc84e89e4e9772d3209aa8df1368c188b1c6334114bcf339870cae74e724d01 \ No newline at end of file
diff --git a/db/schema_migrations/20200913115700 b/db/schema_migrations/20200913115700
deleted file mode 100644
index cb0f401efee..00000000000
--- a/db/schema_migrations/20200913115700
+++ /dev/null
@@ -1 +0,0 @@
-dd2ada53f01debcc91070525e4386db959b91881a8945e9082d0b3318ceb35cf \ No newline at end of file
diff --git a/db/schema_migrations/20200914070140 b/db/schema_migrations/20200914070140
deleted file mode 100644
index b9cac3a3726..00000000000
--- a/db/schema_migrations/20200914070140
+++ /dev/null
@@ -1 +0,0 @@
-8cabe224e89ef77fe4a2bc1f8bf7381faaa10d1cab4907a26aeb2162a126af52 \ No newline at end of file
diff --git a/db/schema_migrations/20200914091326 b/db/schema_migrations/20200914091326
deleted file mode 100644
index b3ebcce5749..00000000000
--- a/db/schema_migrations/20200914091326
+++ /dev/null
@@ -1 +0,0 @@
-c46bafefa5fd79a6644cbe259260b66aaded36aad4ae28a84ddd8bb072c2167d \ No newline at end of file
diff --git a/db/schema_migrations/20200914104642 b/db/schema_migrations/20200914104642
deleted file mode 100644
index 849e99fbbb1..00000000000
--- a/db/schema_migrations/20200914104642
+++ /dev/null
@@ -1 +0,0 @@
-49b492717acca6d43e16caafda0b75f6e1a3630592149b04d1148758406ae1a7 \ No newline at end of file
diff --git a/db/schema_migrations/20200914105202 b/db/schema_migrations/20200914105202
deleted file mode 100644
index 3179f267ce2..00000000000
--- a/db/schema_migrations/20200914105202
+++ /dev/null
@@ -1 +0,0 @@
-6cd644220e07f477a87ddc8bb8b2de3ed920c0c76383122bab95c939e21abbb2 \ No newline at end of file
diff --git a/db/schema_migrations/20200914155135 b/db/schema_migrations/20200914155135
deleted file mode 100644
index 17cd6c67033..00000000000
--- a/db/schema_migrations/20200914155135
+++ /dev/null
@@ -1 +0,0 @@
-0b01a251eb736eb9e9986214c69ea5f4a11d8293bc4083af1585ce265c8f69de \ No newline at end of file
diff --git a/db/schema_migrations/20200914183227 b/db/schema_migrations/20200914183227
deleted file mode 100644
index 3fb2d461452..00000000000
--- a/db/schema_migrations/20200914183227
+++ /dev/null
@@ -1 +0,0 @@
-570a7de82da3dabfd12f3099cdc028128d4b61a4ecf6edd4b3102031d914316c \ No newline at end of file
diff --git a/db/schema_migrations/20200914184212 b/db/schema_migrations/20200914184212
deleted file mode 100644
index 1053454b960..00000000000
--- a/db/schema_migrations/20200914184212
+++ /dev/null
@@ -1 +0,0 @@
-dcfd1f006aa6695e0fd8f392c7288f2d80bddfe53827d3a2f079bd039f4fe0de \ No newline at end of file
diff --git a/db/schema_migrations/20200915044225 b/db/schema_migrations/20200915044225
deleted file mode 100644
index 440fddf4080..00000000000
--- a/db/schema_migrations/20200915044225
+++ /dev/null
@@ -1 +0,0 @@
-0c659c7cbbda4d2fbbbd344f0fca50860ccf54ec8b666772d53a4c6fa602d097 \ No newline at end of file
diff --git a/db/schema_migrations/20200915134004 b/db/schema_migrations/20200915134004
deleted file mode 100644
index a8857de0ada..00000000000
--- a/db/schema_migrations/20200915134004
+++ /dev/null
@@ -1 +0,0 @@
-dd630c76819641ad64a5f6ae40ad4f49e7fbe1c783398d97886dc7e9852a245e \ No newline at end of file
diff --git a/db/schema_migrations/20200915152641 b/db/schema_migrations/20200915152641
deleted file mode 100644
index def09e2b14a..00000000000
--- a/db/schema_migrations/20200915152641
+++ /dev/null
@@ -1 +0,0 @@
-b2d8b7aef4e6756f54f2a173280d98e8fc5594075aaa0a46c81b549a96730668 \ No newline at end of file
diff --git a/db/schema_migrations/20200915164448 b/db/schema_migrations/20200915164448
deleted file mode 100644
index 9506a9c7511..00000000000
--- a/db/schema_migrations/20200915164448
+++ /dev/null
@@ -1 +0,0 @@
-46e86bee146e7f9cf9459309f8d386f9616ba59d40a7517e22756a6e51526056 \ No newline at end of file
diff --git a/db/schema_migrations/20200915164844 b/db/schema_migrations/20200915164844
deleted file mode 100644
index e0d7d3f7c45..00000000000
--- a/db/schema_migrations/20200915164844
+++ /dev/null
@@ -1 +0,0 @@
-8b6caa84be77679e8b47dd5f20093e7438d70641d6d5fc498b05b5c35ef3e5e8 \ No newline at end of file
diff --git a/db/schema_migrations/20200915185707 b/db/schema_migrations/20200915185707
deleted file mode 100644
index 2161aa5acf8..00000000000
--- a/db/schema_migrations/20200915185707
+++ /dev/null
@@ -1 +0,0 @@
-e1ae80d6f0a6372bb329d45257d9a0a8ca5b6a83718d2a10ee295b8c4c97f60e \ No newline at end of file
diff --git a/db/schema_migrations/20200915191156 b/db/schema_migrations/20200915191156
deleted file mode 100644
index 5005ee15989..00000000000
--- a/db/schema_migrations/20200915191156
+++ /dev/null
@@ -1 +0,0 @@
-d8ddec6b234d59b3b85705dfa7b724d3be4974bfa57fae70aa5c2dbdd2e73cfa \ No newline at end of file
diff --git a/db/schema_migrations/20200916081749 b/db/schema_migrations/20200916081749
deleted file mode 100644
index ef4e7164d15..00000000000
--- a/db/schema_migrations/20200916081749
+++ /dev/null
@@ -1 +0,0 @@
-dde7a29268d925044d59455db87bfc1aa617eec6e30df1cc9dc531b52c909fe1 \ No newline at end of file
diff --git a/db/schema_migrations/20200916120837 b/db/schema_migrations/20200916120837
deleted file mode 100644
index 41ce56533b2..00000000000
--- a/db/schema_migrations/20200916120837
+++ /dev/null
@@ -1 +0,0 @@
-ff246eb2761c4504b67b7d7b197990a671626038e50f1b82d6b3e4739a1ec3d4 \ No newline at end of file
diff --git a/db/schema_migrations/20200916135044 b/db/schema_migrations/20200916135044
deleted file mode 100644
index 8bb10fbb1e3..00000000000
--- a/db/schema_migrations/20200916135044
+++ /dev/null
@@ -1 +0,0 @@
-299e6fb38da303f06ab006a25701ff1c58ce2abfa8cf93c3c8b866ee0b2bd1cc \ No newline at end of file
diff --git a/db/schema_migrations/20200916151442 b/db/schema_migrations/20200916151442
deleted file mode 100644
index 36b2a4e9962..00000000000
--- a/db/schema_migrations/20200916151442
+++ /dev/null
@@ -1 +0,0 @@
-aef52404e6ce83d5d4b3de65ad00b665334f5ff2e5b7b6c3c622f79313657f26 \ No newline at end of file
diff --git a/db/schema_migrations/20200916165232 b/db/schema_migrations/20200916165232
deleted file mode 100644
index 8e97fcf3efa..00000000000
--- a/db/schema_migrations/20200916165232
+++ /dev/null
@@ -1 +0,0 @@
-18a3981a3becefe6700dd5fea87e8ba9478c0e83ddc80de1b3ee2ed77c221ce6 \ No newline at end of file
diff --git a/db/schema_migrations/20200917121650 b/db/schema_migrations/20200917121650
deleted file mode 100644
index d0f26d40466..00000000000
--- a/db/schema_migrations/20200917121650
+++ /dev/null
@@ -1 +0,0 @@
-3343b646d0c0ca2d92982740abe4372fb80931cb4bb4386229959d5d61c86587 \ No newline at end of file
diff --git a/db/schema_migrations/20200917135802 b/db/schema_migrations/20200917135802
deleted file mode 100644
index 7b948de646b..00000000000
--- a/db/schema_migrations/20200917135802
+++ /dev/null
@@ -1 +0,0 @@
-8d9e75f7c6344b03cb740fa691fcbb5bea1751802741229158701bc1af975897 \ No newline at end of file
diff --git a/db/schema_migrations/20200917165525 b/db/schema_migrations/20200917165525
deleted file mode 100644
index bf01a95ad14..00000000000
--- a/db/schema_migrations/20200917165525
+++ /dev/null
@@ -1 +0,0 @@
-0080b9192ba5b4ea3853cfd930d58e10b9619f3d9a54016b574712e5ec2084f6 \ No newline at end of file
diff --git a/db/schema_migrations/20200919200318 b/db/schema_migrations/20200919200318
deleted file mode 100644
index 29721a3ef2b..00000000000
--- a/db/schema_migrations/20200919200318
+++ /dev/null
@@ -1 +0,0 @@
-f33c66297ca7848c576778dc275e42801f5f9d7cdcf8c4d2fb205d4eb9770937 \ No newline at end of file
diff --git a/db/schema_migrations/20200919204155 b/db/schema_migrations/20200919204155
deleted file mode 100644
index 39b608deed4..00000000000
--- a/db/schema_migrations/20200919204155
+++ /dev/null
@@ -1 +0,0 @@
-097cb7a36fdc831045f3a33a047f8bda6474b8165ef5fc95dbdeea45d0ac04a3 \ No newline at end of file
diff --git a/db/schema_migrations/20200920130356 b/db/schema_migrations/20200920130356
deleted file mode 100644
index ab0575958ec..00000000000
--- a/db/schema_migrations/20200920130356
+++ /dev/null
@@ -1 +0,0 @@
-80d2beb7a1c5f60a4bf3462054fa5bcd0488152b6754f8a7164046201fcb08ed \ No newline at end of file
diff --git a/db/schema_migrations/20200921093826 b/db/schema_migrations/20200921093826
deleted file mode 100644
index 4a405de5215..00000000000
--- a/db/schema_migrations/20200921093826
+++ /dev/null
@@ -1 +0,0 @@
-8d14013bcb4d8302c91e331f619fb6f621ab79907aebc421d99c9484ecd7a5d8 \ No newline at end of file
diff --git a/db/schema_migrations/20200921113722 b/db/schema_migrations/20200921113722
deleted file mode 100644
index 96dc1683f72..00000000000
--- a/db/schema_migrations/20200921113722
+++ /dev/null
@@ -1 +0,0 @@
-723812a28afbabb6b7884fd76dcaf658c5e35a33a46e90a9a94aef12e735e604 \ No newline at end of file
diff --git a/db/schema_migrations/20200921130028 b/db/schema_migrations/20200921130028
deleted file mode 100644
index b718f21c156..00000000000
--- a/db/schema_migrations/20200921130028
+++ /dev/null
@@ -1 +0,0 @@
-60835078e0a0bd191e9b1f0316f894c5223d6849277992b5034ed4ff9a798fe4 \ No newline at end of file
diff --git a/db/schema_migrations/20200921131313 b/db/schema_migrations/20200921131313
deleted file mode 100644
index 559701acf69..00000000000
--- a/db/schema_migrations/20200921131313
+++ /dev/null
@@ -1 +0,0 @@
-e4f9e918c86705409555cde065f30ba0c0c405dfd1918f47a169a5dc5c244a8d \ No newline at end of file
diff --git a/db/schema_migrations/20200921203231 b/db/schema_migrations/20200921203231
deleted file mode 100644
index 544b7146ebf..00000000000
--- a/db/schema_migrations/20200921203231
+++ /dev/null
@@ -1 +0,0 @@
-7f62ce5117a16213bad6537dfeae2af4016262c533f8fa6b7a19572077bcf8d7 \ No newline at end of file
diff --git a/db/schema_migrations/20200922052316 b/db/schema_migrations/20200922052316
deleted file mode 100644
index 31bd12178ef..00000000000
--- a/db/schema_migrations/20200922052316
+++ /dev/null
@@ -1 +0,0 @@
-384d022662437de21b4b3b97bf2f1dec2925be6afe4b62828c97dc9b3b3fc77c \ No newline at end of file
diff --git a/db/schema_migrations/20200922054642 b/db/schema_migrations/20200922054642
deleted file mode 100644
index 443c13c256e..00000000000
--- a/db/schema_migrations/20200922054642
+++ /dev/null
@@ -1 +0,0 @@
-ad63096e49440f7f2a15ea2747689ca39f52fdcebc1949a1feed82a22f432e9e \ No newline at end of file
diff --git a/db/schema_migrations/20200922075244 b/db/schema_migrations/20200922075244
deleted file mode 100644
index 82a2fc5f304..00000000000
--- a/db/schema_migrations/20200922075244
+++ /dev/null
@@ -1 +0,0 @@
-a8450c6c21b1182afd06c88af18c0d9be92b0e7fdc73505c07d4ab3fddd39abf \ No newline at end of file
diff --git a/db/schema_migrations/20200922093004 b/db/schema_migrations/20200922093004
deleted file mode 100644
index 04dd5dbfcf6..00000000000
--- a/db/schema_migrations/20200922093004
+++ /dev/null
@@ -1 +0,0 @@
-705d010620b1aa95e86c8fb5fb9175fe77778376d228003e9fd2c8d0bb20a347 \ No newline at end of file
diff --git a/db/schema_migrations/20200922095954 b/db/schema_migrations/20200922095954
deleted file mode 100644
index 2282da76380..00000000000
--- a/db/schema_migrations/20200922095954
+++ /dev/null
@@ -1 +0,0 @@
-c55f27f817afc60462e5dc43755a4ddd76f1399f5e461bab4b36bf5e5b26ce0a \ No newline at end of file
diff --git a/db/schema_migrations/20200922133949 b/db/schema_migrations/20200922133949
deleted file mode 100644
index 8c1874198bb..00000000000
--- a/db/schema_migrations/20200922133949
+++ /dev/null
@@ -1 +0,0 @@
-8196e28f6fe8cdb4cf710922b5cd218030ba587c629de7ee75dc061d05c7e1a9 \ No newline at end of file
diff --git a/db/schema_migrations/20200922170907 b/db/schema_migrations/20200922170907
deleted file mode 100644
index 66ff701973d..00000000000
--- a/db/schema_migrations/20200922170907
+++ /dev/null
@@ -1 +0,0 @@
-ab044b609a29e9a179813de79dab9770665917a8ed78db907755a64f2d4aa47c \ No newline at end of file
diff --git a/db/schema_migrations/20200922231755 b/db/schema_migrations/20200922231755
deleted file mode 100644
index 504df45b957..00000000000
--- a/db/schema_migrations/20200922231755
+++ /dev/null
@@ -1 +0,0 @@
-0019105cd2112e138b9926dc000b0c54b41fca6dfb2c4f658900040e0ecb3b70 \ No newline at end of file
diff --git a/db/schema_migrations/20200923071622 b/db/schema_migrations/20200923071622
deleted file mode 100644
index 629b241ce0a..00000000000
--- a/db/schema_migrations/20200923071622
+++ /dev/null
@@ -1 +0,0 @@
-1751fa6522a88582cb6a580acc95665f4e3f3a879f2365d5fd0a824ad1b4806d \ No newline at end of file
diff --git a/db/schema_migrations/20200923071644 b/db/schema_migrations/20200923071644
deleted file mode 100644
index 431ed5af1f0..00000000000
--- a/db/schema_migrations/20200923071644
+++ /dev/null
@@ -1 +0,0 @@
-0df2b1e65ef0dc563c55e575968e4fd768cec2e713e3b1c999cf584ef62b629d \ No newline at end of file
diff --git a/db/schema_migrations/20200923102312 b/db/schema_migrations/20200923102312
deleted file mode 100644
index 52ed07034fc..00000000000
--- a/db/schema_migrations/20200923102312
+++ /dev/null
@@ -1 +0,0 @@
-f19e61e3863905885c8b5b2129be2586d912d616a5b3b54e99a72c5760082059 \ No newline at end of file
diff --git a/db/schema_migrations/20200923130057 b/db/schema_migrations/20200923130057
deleted file mode 100644
index e95c2da0a1d..00000000000
--- a/db/schema_migrations/20200923130057
+++ /dev/null
@@ -1 +0,0 @@
-84b272d61f6ab6e9f9f8eb059ba139a3fa0d2f1bbeb337f2e4e7cd4034822b44 \ No newline at end of file
diff --git a/db/schema_migrations/20200923140404 b/db/schema_migrations/20200923140404
deleted file mode 100644
index 9c1bfd59b4c..00000000000
--- a/db/schema_migrations/20200923140404
+++ /dev/null
@@ -1 +0,0 @@
-8a1898f62a47575c7ea428198163e04ff427e7ab6cd04eb9897930a6b7753681 \ No newline at end of file
diff --git a/db/schema_migrations/20200924035825 b/db/schema_migrations/20200924035825
deleted file mode 100644
index 0c27ed47732..00000000000
--- a/db/schema_migrations/20200924035825
+++ /dev/null
@@ -1 +0,0 @@
-d413e19c8ddaba4556cf36a38e03b1c7c46ee7edf7e56692028e066f97605784 \ No newline at end of file
diff --git a/db/schema_migrations/20200925112104 b/db/schema_migrations/20200925112104
deleted file mode 100644
index bb0f8032a84..00000000000
--- a/db/schema_migrations/20200925112104
+++ /dev/null
@@ -1 +0,0 @@
-a14df9e9a115d39636b29bfe73fb175bb1e8d4510bee26e3e0c6c979949b13c4 \ No newline at end of file
diff --git a/db/schema_migrations/20200925114522 b/db/schema_migrations/20200925114522
deleted file mode 100644
index 4b8d893833d..00000000000
--- a/db/schema_migrations/20200925114522
+++ /dev/null
@@ -1 +0,0 @@
-7d43d2fa91e27eaf9399cf0ce9e4375e849deb71b12d4891455bc51392bce14a \ No newline at end of file
diff --git a/db/schema_migrations/20200925125321 b/db/schema_migrations/20200925125321
deleted file mode 100644
index 103cd02c5e1..00000000000
--- a/db/schema_migrations/20200925125321
+++ /dev/null
@@ -1 +0,0 @@
-d1d2f7d5f70e912b1d0a77417a96b9e16ffc620eb8c941ed4aa9a8c166ba26e0 \ No newline at end of file
diff --git a/db/schema_migrations/20200925153423 b/db/schema_migrations/20200925153423
deleted file mode 100644
index ffbdc2c81c2..00000000000
--- a/db/schema_migrations/20200925153423
+++ /dev/null
@@ -1 +0,0 @@
-f445704e51dad2369719d8c0931c3314793fa90ba6b5a383df503ea4f6dafd20 \ No newline at end of file
diff --git a/db/schema_migrations/20200925193815 b/db/schema_migrations/20200925193815
deleted file mode 100644
index fdfa07c5a99..00000000000
--- a/db/schema_migrations/20200925193815
+++ /dev/null
@@ -1 +0,0 @@
-a814b745b4911fc6c80971e6c0c19e6d64ca30cb94fa87a94bc1adf8c07b1c87 \ No newline at end of file
diff --git a/db/schema_migrations/20200925193906 b/db/schema_migrations/20200925193906
deleted file mode 100644
index dd9c1e4cd3b..00000000000
--- a/db/schema_migrations/20200925193906
+++ /dev/null
@@ -1 +0,0 @@
-a915ccf5df0ec803286205916ffcd34b1410d1cc4da84f8299b63b3665d69e09 \ No newline at end of file
diff --git a/db/schema_migrations/20200925194006 b/db/schema_migrations/20200925194006
deleted file mode 100644
index fc89ebb9f7b..00000000000
--- a/db/schema_migrations/20200925194006
+++ /dev/null
@@ -1 +0,0 @@
-28a71a380be0ef08389defac604c351f0a7f31b6c03a7c40aabe47bf09e6a485 \ No newline at end of file
diff --git a/db/schema_migrations/20200927224750 b/db/schema_migrations/20200927224750
deleted file mode 100644
index 9454bec58c5..00000000000
--- a/db/schema_migrations/20200927224750
+++ /dev/null
@@ -1 +0,0 @@
-8e0c5be3d6fe2d0d718c7b7a99d84b14dfc6006f780ec0622eb5aae937e6b367 \ No newline at end of file
diff --git a/db/schema_migrations/20200928095732 b/db/schema_migrations/20200928095732
deleted file mode 100644
index 15f0d5e3eae..00000000000
--- a/db/schema_migrations/20200928095732
+++ /dev/null
@@ -1 +0,0 @@
-5ff9bf6c542f686729abf18f282351d9bb5b895070c6f06c5fc8d125be4a38f7 \ No newline at end of file
diff --git a/db/schema_migrations/20200928100408 b/db/schema_migrations/20200928100408
deleted file mode 100644
index e49c397924d..00000000000
--- a/db/schema_migrations/20200928100408
+++ /dev/null
@@ -1 +0,0 @@
-56984f720cfde6ad28b8612e092809252f948797fecb64dfc3b82d5b3b74f7ec \ No newline at end of file
diff --git a/db/schema_migrations/20200928123510 b/db/schema_migrations/20200928123510
deleted file mode 100644
index db9d2889739..00000000000
--- a/db/schema_migrations/20200928123510
+++ /dev/null
@@ -1 +0,0 @@
-1e274e744ed9e225e2ee09afc15871a1af63857f95c5d787e8efd9943fce1bed \ No newline at end of file
diff --git a/db/schema_migrations/20200928125258 b/db/schema_migrations/20200928125258
deleted file mode 100644
index d9756bd6ee6..00000000000
--- a/db/schema_migrations/20200928125258
+++ /dev/null
@@ -1 +0,0 @@
-46579fd0313068f3c9c1631f1da4a0b20513759a54dad4841bcea7d6c727646a \ No newline at end of file
diff --git a/db/schema_migrations/20200928131934 b/db/schema_migrations/20200928131934
deleted file mode 100644
index 952e2121d35..00000000000
--- a/db/schema_migrations/20200928131934
+++ /dev/null
@@ -1 +0,0 @@
-106757b0f30d3c89fcafa13be92271090fa107831fd538ee087d7ce212842492 \ No newline at end of file
diff --git a/db/schema_migrations/20200928164807 b/db/schema_migrations/20200928164807
deleted file mode 100644
index 3efd3c56402..00000000000
--- a/db/schema_migrations/20200928164807
+++ /dev/null
@@ -1 +0,0 @@
-346d0e913212d6e84528d47228ba7e6d0cf4a396e7fc921f7c684acfaaeeedb8 \ No newline at end of file
diff --git a/db/schema_migrations/20200928203531 b/db/schema_migrations/20200928203531
deleted file mode 100644
index 229e2dc9b1f..00000000000
--- a/db/schema_migrations/20200928203531
+++ /dev/null
@@ -1 +0,0 @@
-fc9719e0822d17eacb375b4adb2eac35afba04cafc2bd429c82c502d2fe5f12e \ No newline at end of file
diff --git a/db/schema_migrations/20200928210524 b/db/schema_migrations/20200928210524
deleted file mode 100644
index 41905703d01..00000000000
--- a/db/schema_migrations/20200928210524
+++ /dev/null
@@ -1 +0,0 @@
-788fd828a7aa8fb8741f13596f54fc4d9f4f5caeaf34d08aed47bbefe363ae75 \ No newline at end of file
diff --git a/db/schema_migrations/20200928233632 b/db/schema_migrations/20200928233632
deleted file mode 100644
index d66fc8310f2..00000000000
--- a/db/schema_migrations/20200928233632
+++ /dev/null
@@ -1 +0,0 @@
-c390843c8a93ca429d1442d7b54f5f9dc01e0343c71ed1a046f11968cc10810d \ No newline at end of file
diff --git a/db/schema_migrations/20200929032729 b/db/schema_migrations/20200929032729
deleted file mode 100644
index cd38d67c78a..00000000000
--- a/db/schema_migrations/20200929032729
+++ /dev/null
@@ -1 +0,0 @@
-77fa26f97216c1fa3d0b046dfabac92a5afa2a0eaf33439117b29ac81e740e4a \ No newline at end of file
diff --git a/db/schema_migrations/20200929052138 b/db/schema_migrations/20200929052138
deleted file mode 100644
index 05c56a31270..00000000000
--- a/db/schema_migrations/20200929052138
+++ /dev/null
@@ -1 +0,0 @@
-30b84d137fcb17eaca86f1bec52d6e20c972f7083d4c983e2bb397c9126b5f0c \ No newline at end of file
diff --git a/db/schema_migrations/20200929063159 b/db/schema_migrations/20200929063159
deleted file mode 100644
index b7815e9bb39..00000000000
--- a/db/schema_migrations/20200929063159
+++ /dev/null
@@ -1 +0,0 @@
-9ef08404b964ccae3e12332340f16c6b8bb2bbdb2c04ba105fe1c0c7e6bf84f2 \ No newline at end of file
diff --git a/db/schema_migrations/20200929113254 b/db/schema_migrations/20200929113254
deleted file mode 100644
index 172a6eabd66..00000000000
--- a/db/schema_migrations/20200929113254
+++ /dev/null
@@ -1 +0,0 @@
-260f392c3ff257960dc7b198473056e7bf9b9a668403d2f05391d2b7989cf83c \ No newline at end of file
diff --git a/db/schema_migrations/20200929114107 b/db/schema_migrations/20200929114107
deleted file mode 100644
index f3b7a7a3bad..00000000000
--- a/db/schema_migrations/20200929114107
+++ /dev/null
@@ -1 +0,0 @@
-f5d4b534c230f9ac7f285bccd096a7d51bf5c9e7a73f293fafaff89bb1ee12e1 \ No newline at end of file
diff --git a/db/schema_migrations/20200930094812 b/db/schema_migrations/20200930094812
deleted file mode 100644
index ad03614e47d..00000000000
--- a/db/schema_migrations/20200930094812
+++ /dev/null
@@ -1 +0,0 @@
-b92b48a17bfd350a70017bfee99bcfb3dbc5ae9e33c8f23ab593666e5c3900aa \ No newline at end of file
diff --git a/db/schema_migrations/20200930131343 b/db/schema_migrations/20200930131343
deleted file mode 100644
index a872607f241..00000000000
--- a/db/schema_migrations/20200930131343
+++ /dev/null
@@ -1 +0,0 @@
-45530bb3090d9e8df3a79f42a06b042e0c40f6e185078c6d79d7ec334175c7d5 \ No newline at end of file
diff --git a/db/schema_migrations/20200930132319 b/db/schema_migrations/20200930132319
deleted file mode 100644
index 7bffd187de2..00000000000
--- a/db/schema_migrations/20200930132319
+++ /dev/null
@@ -1 +0,0 @@
-1ded640c70d5e569f0f26729c96d2dc27c528bcb045e28f073ed8fce9f918d95 \ No newline at end of file
diff --git a/db/schema_migrations/20200930144340 b/db/schema_migrations/20200930144340
deleted file mode 100644
index 4ac1bae7537..00000000000
--- a/db/schema_migrations/20200930144340
+++ /dev/null
@@ -1 +0,0 @@
-febc66dbb48fbd281223ab9466cc5d94e945e8164fa9db0ee149c29e653b3eb2 \ No newline at end of file
diff --git a/db/schema_migrations/20201001022100 b/db/schema_migrations/20201001022100
deleted file mode 100644
index 9c11e9e6094..00000000000
--- a/db/schema_migrations/20201001022100
+++ /dev/null
@@ -1 +0,0 @@
-a581071767c5484e8286951854b0effe04d4b8951f208f10ceb4812940363959 \ No newline at end of file
diff --git a/db/schema_migrations/20201001101136 b/db/schema_migrations/20201001101136
deleted file mode 100644
index ecfc37cdfc5..00000000000
--- a/db/schema_migrations/20201001101136
+++ /dev/null
@@ -1 +0,0 @@
-f3f9dd503d2c2695d5cd32ea87ff11e45832b1650df3186c7f71c984fc59ad24 \ No newline at end of file
diff --git a/db/schema_migrations/20201002012659 b/db/schema_migrations/20201002012659
deleted file mode 100644
index 6a6d33389f9..00000000000
--- a/db/schema_migrations/20201002012659
+++ /dev/null
@@ -1 +0,0 @@
-8a12c3c4f674d2a36df56a89bfd32e0f3945e73605460bdf2a8b0aa1308f5b19 \ No newline at end of file
diff --git a/db/schema_migrations/20201002094617 b/db/schema_migrations/20201002094617
deleted file mode 100644
index 9c4d6155700..00000000000
--- a/db/schema_migrations/20201002094617
+++ /dev/null
@@ -1 +0,0 @@
-823c72852eeb17eaf43c58e936ac25effdacb335f76562c68a4f90d5b1a32021 \ No newline at end of file
diff --git a/db/schema_migrations/20201002175953 b/db/schema_migrations/20201002175953
deleted file mode 100644
index df5f64c0deb..00000000000
--- a/db/schema_migrations/20201002175953
+++ /dev/null
@@ -1 +0,0 @@
-619e788f8868a2ff602a06e0025154b0b10b17cd69edcce70378e11750d5e686 \ No newline at end of file
diff --git a/db/schema_migrations/20201004163918 b/db/schema_migrations/20201004163918
deleted file mode 100644
index e77e000bac8..00000000000
--- a/db/schema_migrations/20201004163918
+++ /dev/null
@@ -1 +0,0 @@
-e25da3da50ed2396afe3bcb1ff441b5f1f0a43c0e23d66140a160d42f1b66a1a \ No newline at end of file
diff --git a/db/schema_migrations/20201005092703 b/db/schema_migrations/20201005092703
deleted file mode 100644
index 54969553788..00000000000
--- a/db/schema_migrations/20201005092703
+++ /dev/null
@@ -1 +0,0 @@
-550fb12fe5e180ab52bd6d012cf1869544130049e83ccbefd4b132831a074f71 \ No newline at end of file
diff --git a/db/schema_migrations/20201005092709 b/db/schema_migrations/20201005092709
deleted file mode 100644
index e0a7ecad91f..00000000000
--- a/db/schema_migrations/20201005092709
+++ /dev/null
@@ -1 +0,0 @@
-5d9dbae8074627c41170e70849a3e6b71e20da473f312227df462c894c194efb \ No newline at end of file
diff --git a/db/schema_migrations/20201005092753 b/db/schema_migrations/20201005092753
deleted file mode 100644
index a519b6b3f1e..00000000000
--- a/db/schema_migrations/20201005092753
+++ /dev/null
@@ -1 +0,0 @@
-b59670c031a146e7a1a8277ba51080a6c120724a00c7612933ff1ed44bc8dd60 \ No newline at end of file
diff --git a/db/schema_migrations/20201005094331 b/db/schema_migrations/20201005094331
deleted file mode 100644
index 63b48d9fdaf..00000000000
--- a/db/schema_migrations/20201005094331
+++ /dev/null
@@ -1 +0,0 @@
-b024bc44406810a30a3aebb33dd1355468448b4ebf9c76fe7811148044241551 \ No newline at end of file
diff --git a/db/schema_migrations/20201005153955 b/db/schema_migrations/20201005153955
deleted file mode 100644
index 19d8b921ceb..00000000000
--- a/db/schema_migrations/20201005153955
+++ /dev/null
@@ -1 +0,0 @@
-563f76e0635b54c2a5cb78cf5e87ea217acf3b6c853518588fcdeadef9dcc951 \ No newline at end of file
diff --git a/db/schema_migrations/20201006014605 b/db/schema_migrations/20201006014605
deleted file mode 100644
index 92209fcd127..00000000000
--- a/db/schema_migrations/20201006014605
+++ /dev/null
@@ -1 +0,0 @@
-d1a636c0b0c7f11bf5d6e882970a5286a28c3f060f89df3ac51df2e7c86f042e \ No newline at end of file
diff --git a/db/schema_migrations/20201007033527 b/db/schema_migrations/20201007033527
deleted file mode 100644
index b2cedd57973..00000000000
--- a/db/schema_migrations/20201007033527
+++ /dev/null
@@ -1 +0,0 @@
-1200747265d5095a86250020786d6f1e9e50bc75328a71de497046807afa89d7 \ No newline at end of file
diff --git a/db/schema_migrations/20201007033723 b/db/schema_migrations/20201007033723
deleted file mode 100644
index c874ae0475b..00000000000
--- a/db/schema_migrations/20201007033723
+++ /dev/null
@@ -1 +0,0 @@
-febefead6f966960f6493d29add5f35fc4a1080b5118c5526502fa5fe1d29023 \ No newline at end of file
diff --git a/db/schema_migrations/20201007115209 b/db/schema_migrations/20201007115209
deleted file mode 100644
index acd0a056bbd..00000000000
--- a/db/schema_migrations/20201007115209
+++ /dev/null
@@ -1 +0,0 @@
-761cad9a584d98e3086e716f7a5c1d9b4aba87b084efcfcee7272cfdf1179372 \ No newline at end of file
diff --git a/db/schema_migrations/20201008011523 b/db/schema_migrations/20201008011523
deleted file mode 100644
index 845ee2f5b96..00000000000
--- a/db/schema_migrations/20201008011523
+++ /dev/null
@@ -1 +0,0 @@
-b7b49ca4c021b7caa9f8612ad9b69d4ec6d79894db2e43266bfe26f2e0bffe08 \ No newline at end of file
diff --git a/db/schema_migrations/20201008011937 b/db/schema_migrations/20201008011937
deleted file mode 100644
index 258daf9a836..00000000000
--- a/db/schema_migrations/20201008011937
+++ /dev/null
@@ -1 +0,0 @@
-8af89bb3e63bfca24cee8fdf6f0dd587fae7d81bfeaf6d427f84c7b37c9664ba \ No newline at end of file
diff --git a/db/schema_migrations/20201008013434 b/db/schema_migrations/20201008013434
deleted file mode 100644
index 9ec9dd8277c..00000000000
--- a/db/schema_migrations/20201008013434
+++ /dev/null
@@ -1 +0,0 @@
-966f6e95189b551cba0ef548cb410911c0beee30d0a265ae21d90321ecbb2a00 \ No newline at end of file
diff --git a/db/schema_migrations/20201008075620 b/db/schema_migrations/20201008075620
deleted file mode 100644
index a0a5d6a7314..00000000000
--- a/db/schema_migrations/20201008075620
+++ /dev/null
@@ -1 +0,0 @@
-f9bc943b61460b1a9a6db8189ab5b21eba46e14650c68658175299b14d48a030 \ No newline at end of file
diff --git a/db/schema_migrations/20201008125643 b/db/schema_migrations/20201008125643
deleted file mode 100644
index 121dcbc0281..00000000000
--- a/db/schema_migrations/20201008125643
+++ /dev/null
@@ -1 +0,0 @@
-b7b15717435e06ea386c941c5a021b73f986ad3f41f2bd6f890738a79b710207 \ No newline at end of file
diff --git a/db/schema_migrations/20201008144854 b/db/schema_migrations/20201008144854
deleted file mode 100644
index f4b71f06acd..00000000000
--- a/db/schema_migrations/20201008144854
+++ /dev/null
@@ -1 +0,0 @@
-250785e18682cc10afb4f04546e5ff6dff9ab6c6673df84692c8221d6fe820ac \ No newline at end of file
diff --git a/db/schema_migrations/20201008224441 b/db/schema_migrations/20201008224441
deleted file mode 100644
index 1f27662d754..00000000000
--- a/db/schema_migrations/20201008224441
+++ /dev/null
@@ -1 +0,0 @@
-d0ca8f0dbe0cf0fbbdd715867f3ae20862683433d919ee5cd942086d21f3b44d \ No newline at end of file
diff --git a/db/schema_migrations/20201009090954 b/db/schema_migrations/20201009090954
deleted file mode 100644
index 5d5ca8ff29b..00000000000
--- a/db/schema_migrations/20201009090954
+++ /dev/null
@@ -1 +0,0 @@
-d0944a864a1a89e9339eb1f8ffab683df1a5bb90f7b7a16cabd4871f34d1cd48 \ No newline at end of file
diff --git a/db/schema_migrations/20201011005400 b/db/schema_migrations/20201011005400
deleted file mode 100644
index 1715d21e424..00000000000
--- a/db/schema_migrations/20201011005400
+++ /dev/null
@@ -1 +0,0 @@
-07bfc8e9a684ae64b7d78c9d867f9bafebd46678f6f168aa87d2ad7f0e85d75e \ No newline at end of file
diff --git a/db/schema_migrations/20201012073022 b/db/schema_migrations/20201012073022
deleted file mode 100644
index b7ce136a7e3..00000000000
--- a/db/schema_migrations/20201012073022
+++ /dev/null
@@ -1 +0,0 @@
-234711b96d3869fe826dfd71ae29e0f75e50302bc29a4e60f436ec76b4be3efb \ No newline at end of file
diff --git a/db/schema_migrations/20201012122428 b/db/schema_migrations/20201012122428
deleted file mode 100644
index 13e7e9c2cd6..00000000000
--- a/db/schema_migrations/20201012122428
+++ /dev/null
@@ -1 +0,0 @@
-d43764a44f6578548d8b7838dc011b7693da0b7d65cbcc1fff96a212d655024e \ No newline at end of file
diff --git a/db/schema_migrations/20201012134230 b/db/schema_migrations/20201012134230
deleted file mode 100644
index 2bf2175ef60..00000000000
--- a/db/schema_migrations/20201012134230
+++ /dev/null
@@ -1 +0,0 @@
-1673018885366e92eb47f5fc705ea8251c2db49b5c14b788e84b10d8db91af48 \ No newline at end of file
diff --git a/db/schema_migrations/20201012135330 b/db/schema_migrations/20201012135330
deleted file mode 100644
index 8ecce197faa..00000000000
--- a/db/schema_migrations/20201012135330
+++ /dev/null
@@ -1 +0,0 @@
-18ccd2059d9a19a51ea0162c46a1293e280759daffa54ba58ba5e431ee7aba93 \ No newline at end of file
diff --git a/db/schema_migrations/20201012140110 b/db/schema_migrations/20201012140110
deleted file mode 100644
index 1bbfe820a5d..00000000000
--- a/db/schema_migrations/20201012140110
+++ /dev/null
@@ -1 +0,0 @@
-e266655483655e1ecbb4f65594ef5b985c3f0449231755f589f3e293e28c9f6b \ No newline at end of file
diff --git a/db/schema_migrations/20201012140452 b/db/schema_migrations/20201012140452
deleted file mode 100644
index 11bc272341d..00000000000
--- a/db/schema_migrations/20201012140452
+++ /dev/null
@@ -1 +0,0 @@
-d62928276708c26656070f803ea6271be74a1fe9802877258d4a8cf19df32d09 \ No newline at end of file
diff --git a/db/schema_migrations/20201012194936 b/db/schema_migrations/20201012194936
deleted file mode 100644
index c626e091e5e..00000000000
--- a/db/schema_migrations/20201012194936
+++ /dev/null
@@ -1 +0,0 @@
-823d23d8ce8959762a7cadb883ed6d36a46fedaf238ea955d93136277d55cad5 \ No newline at end of file
diff --git a/db/schema_migrations/20201014142521 b/db/schema_migrations/20201014142521
deleted file mode 100644
index d87f01628c3..00000000000
--- a/db/schema_migrations/20201014142521
+++ /dev/null
@@ -1 +0,0 @@
-aed103bb25b70eb8f6387d84225a8e51672a83c4586ccc65da3011ef010da4b1 \ No newline at end of file
diff --git a/db/schema_migrations/20201014163633 b/db/schema_migrations/20201014163633
deleted file mode 100644
index 6025edca343..00000000000
--- a/db/schema_migrations/20201014163633
+++ /dev/null
@@ -1 +0,0 @@
-591bb8d685c686cced324825e7bec01711aee328176c1c5396a9e61847cb6fab \ No newline at end of file
diff --git a/db/schema_migrations/20201014205300 b/db/schema_migrations/20201014205300
deleted file mode 100644
index 7d183f22624..00000000000
--- a/db/schema_migrations/20201014205300
+++ /dev/null
@@ -1 +0,0 @@
-05352623a59d56c1633317ba7dbaba7d75bb8e529a748a90512dcf3641b8d3cb \ No newline at end of file
diff --git a/db/schema_migrations/20201015073808 b/db/schema_migrations/20201015073808
deleted file mode 100644
index c14d0b7a528..00000000000
--- a/db/schema_migrations/20201015073808
+++ /dev/null
@@ -1 +0,0 @@
-e44ab2a7b3014b44d7d84de1f7e618d2fc89f98b8d59f5f6fa331544e206355f \ No newline at end of file
diff --git a/db/schema_migrations/20201015121805 b/db/schema_migrations/20201015121805
deleted file mode 100644
index 50c3cd1285c..00000000000
--- a/db/schema_migrations/20201015121805
+++ /dev/null
@@ -1 +0,0 @@
-b8d5890fe5569127e794eea831fc18f8e5708b326e8037963fe2f6ae7f120e27 \ No newline at end of file
diff --git a/db/schema_migrations/20201015121825 b/db/schema_migrations/20201015121825
deleted file mode 100644
index b853c405ba0..00000000000
--- a/db/schema_migrations/20201015121825
+++ /dev/null
@@ -1 +0,0 @@
-76e5a5bb535019da28041d1c7dddd8a18d3b04f688b38edc0c4214d3a4d6e357 \ No newline at end of file
diff --git a/db/schema_migrations/20201015154527 b/db/schema_migrations/20201015154527
deleted file mode 100644
index 995483bef49..00000000000
--- a/db/schema_migrations/20201015154527
+++ /dev/null
@@ -1 +0,0 @@
-319502924c38f5e78e40226a55ad99db53b246aa0d35eb945ac9a96f9e55f584 \ No newline at end of file
diff --git a/db/schema_migrations/20201015194852 b/db/schema_migrations/20201015194852
deleted file mode 100644
index 665135a7e3e..00000000000
--- a/db/schema_migrations/20201015194852
+++ /dev/null
@@ -1 +0,0 @@
-1b12f68f7d8c56ecdd7d6d7551d81f5d95d1b4dc5f8d4c67eb239b8640128531 \ No newline at end of file
diff --git a/db/schema_migrations/20201015231049 b/db/schema_migrations/20201015231049
deleted file mode 100644
index 17a4147993a..00000000000
--- a/db/schema_migrations/20201015231049
+++ /dev/null
@@ -1 +0,0 @@
-cae3c41e344f15fa5a9cf71546a0bf209ead964fd3efefba39aba79afd60e0be \ No newline at end of file
diff --git a/db/schema_migrations/20201016074302 b/db/schema_migrations/20201016074302
deleted file mode 100644
index e0ed03f0ac3..00000000000
--- a/db/schema_migrations/20201016074302
+++ /dev/null
@@ -1 +0,0 @@
-de07bcc8166421d01382038d930cabb6a4749b314f05ca148e8d13cff947447c \ No newline at end of file
diff --git a/db/schema_migrations/20201019091307 b/db/schema_migrations/20201019091307
deleted file mode 100644
index 6b74c804ed8..00000000000
--- a/db/schema_migrations/20201019091307
+++ /dev/null
@@ -1 +0,0 @@
-f19ab0de07415e728849ef4e56804909a3a4a57ad8f55fe71a27bc43c535ac66 \ No newline at end of file
diff --git a/db/schema_migrations/20201019094741 b/db/schema_migrations/20201019094741
deleted file mode 100644
index 5e53ab91e9b..00000000000
--- a/db/schema_migrations/20201019094741
+++ /dev/null
@@ -1 +0,0 @@
-16ef5ba153f1145dcd2578bb8c860d4e1a975d5df3a1b1d9315946e632a95999 \ No newline at end of file
diff --git a/db/schema_migrations/20201019101549 b/db/schema_migrations/20201019101549
deleted file mode 100644
index 9b22cf277fb..00000000000
--- a/db/schema_migrations/20201019101549
+++ /dev/null
@@ -1 +0,0 @@
-1bd99d7d6b972ea66495f21358e3b8731532219fcf75731bf643c312eb56820d \ No newline at end of file
diff --git a/db/schema_migrations/20201019111952 b/db/schema_migrations/20201019111952
deleted file mode 100644
index 7fe9fcf3b2f..00000000000
--- a/db/schema_migrations/20201019111952
+++ /dev/null
@@ -1 +0,0 @@
-82d6ed3e066c15352abdb58d58d195f48aa7b1d17bbb28f58f42c19ae67fab54 \ No newline at end of file
diff --git a/db/schema_migrations/20201019113009 b/db/schema_migrations/20201019113009
deleted file mode 100644
index 88d91b79607..00000000000
--- a/db/schema_migrations/20201019113009
+++ /dev/null
@@ -1 +0,0 @@
-fe57e8e74ebbe0e9567c1487e6e4f8b499afa6404c73424157c43ae79c005f08 \ No newline at end of file
diff --git a/db/schema_migrations/20201019130244 b/db/schema_migrations/20201019130244
deleted file mode 100644
index b37e6eeae70..00000000000
--- a/db/schema_migrations/20201019130244
+++ /dev/null
@@ -1 +0,0 @@
-fcd2cc46dae4f4da96ac5a2100a9de9bd360defee82a9c9d6cfbda0e1507ee66 \ No newline at end of file
diff --git a/db/schema_migrations/20201019152046 b/db/schema_migrations/20201019152046
deleted file mode 100644
index bc364a38a46..00000000000
--- a/db/schema_migrations/20201019152046
+++ /dev/null
@@ -1 +0,0 @@
-e5b3bcac7150df4443879db05b18b6aeb01271d99965b2468278954dedf8413b \ No newline at end of file
diff --git a/db/schema_migrations/20201019161924 b/db/schema_migrations/20201019161924
deleted file mode 100644
index 3857a5cb5a1..00000000000
--- a/db/schema_migrations/20201019161924
+++ /dev/null
@@ -1 +0,0 @@
-47aba29a35e24113c9f198c731ba95597a2a6cd5d16b01a958644ce3e1a96170 \ No newline at end of file
diff --git a/db/schema_migrations/20201019172704 b/db/schema_migrations/20201019172704
deleted file mode 100644
index 0bf2d30205f..00000000000
--- a/db/schema_migrations/20201019172704
+++ /dev/null
@@ -1 +0,0 @@
-2a426e1a7cc6283e777667a1b4a6987f011c6cfd189ec702abc55d13a8499eca \ No newline at end of file
diff --git a/db/schema_migrations/20201020102551 b/db/schema_migrations/20201020102551
deleted file mode 100644
index f658f1fdc0a..00000000000
--- a/db/schema_migrations/20201020102551
+++ /dev/null
@@ -1 +0,0 @@
-ba16ad5a51494f436dc47ffb924f94ce7795bfd3b9061ca58d1c8dda238245e9 \ No newline at end of file
diff --git a/db/schema_migrations/20201021085007 b/db/schema_migrations/20201021085007
deleted file mode 100644
index 59567962e80..00000000000
--- a/db/schema_migrations/20201021085007
+++ /dev/null
@@ -1 +0,0 @@
-552f8a042bdecb7511d63e129438faff3fde8e1086cc88f7a79269b2b7098a65 \ No newline at end of file
diff --git a/db/schema_migrations/20201021101956 b/db/schema_migrations/20201021101956
deleted file mode 100644
index bf3e1092fd1..00000000000
--- a/db/schema_migrations/20201021101956
+++ /dev/null
@@ -1 +0,0 @@
-47158d21bd1a800e5a9da1bfea25870f14cc0b094e5f3e9a4b7608b8a9eca180 \ No newline at end of file
diff --git a/db/schema_migrations/20201021102554 b/db/schema_migrations/20201021102554
deleted file mode 100644
index c2bd788943b..00000000000
--- a/db/schema_migrations/20201021102554
+++ /dev/null
@@ -1 +0,0 @@
-90936786a9c2a9d035d13be87021b2f8278342cd11992d58753ca5a5413ed9d7 \ No newline at end of file
diff --git a/db/schema_migrations/20201021105347 b/db/schema_migrations/20201021105347
deleted file mode 100644
index 86117fd6538..00000000000
--- a/db/schema_migrations/20201021105347
+++ /dev/null
@@ -1 +0,0 @@
-d7683f7a2db6aa27606756c158fa029c932230713b165917bc05a491f10e7adf \ No newline at end of file
diff --git a/db/schema_migrations/20201021105600 b/db/schema_migrations/20201021105600
deleted file mode 100644
index 14d2edb23a6..00000000000
--- a/db/schema_migrations/20201021105600
+++ /dev/null
@@ -1 +0,0 @@
-9b90dd436cc1c315eacc60acbc5f6b3b94029b82b4fcb27a41abc4941ad9a4ad \ No newline at end of file
diff --git a/db/schema_migrations/20201021105959 b/db/schema_migrations/20201021105959
deleted file mode 100644
index 2ddfcb102c9..00000000000
--- a/db/schema_migrations/20201021105959
+++ /dev/null
@@ -1 +0,0 @@
-d924e4ad9ff67d01d660db3b3a1b9e5d74cecb1a127d598d1d1193cbfa499030 \ No newline at end of file
diff --git a/db/schema_migrations/20201021142812 b/db/schema_migrations/20201021142812
deleted file mode 100644
index d4ddf2a3595..00000000000
--- a/db/schema_migrations/20201021142812
+++ /dev/null
@@ -1 +0,0 @@
-81b9b79f2ca8830b9d9e9315d93421875dfe44cfa0da6f4e9166567452a2363b \ No newline at end of file
diff --git a/db/schema_migrations/20201021152210 b/db/schema_migrations/20201021152210
deleted file mode 100644
index 78358b24bad..00000000000
--- a/db/schema_migrations/20201021152210
+++ /dev/null
@@ -1 +0,0 @@
-853dbc604fc8ce4d82e6040aa7a7970ae194f09bafb2749077cd9f48d2708eac \ No newline at end of file
diff --git a/db/schema_migrations/20201021155606 b/db/schema_migrations/20201021155606
deleted file mode 100644
index 958683e9bce..00000000000
--- a/db/schema_migrations/20201021155606
+++ /dev/null
@@ -1 +0,0 @@
-d9151c8cafe7a62be9904cb05cc2a6f6e28c2910e69744df1ddd4ad587c83335 \ No newline at end of file
diff --git a/db/schema_migrations/20201021190539 b/db/schema_migrations/20201021190539
deleted file mode 100644
index 902213f9029..00000000000
--- a/db/schema_migrations/20201021190539
+++ /dev/null
@@ -1 +0,0 @@
-1d0689b5182ac391473075aeabb0e341fb8634dbf0aa87dbb6d48cc0e61d2ada \ No newline at end of file
diff --git a/db/schema_migrations/20201021220101 b/db/schema_migrations/20201021220101
deleted file mode 100644
index cda2e4076a5..00000000000
--- a/db/schema_migrations/20201021220101
+++ /dev/null
@@ -1 +0,0 @@
-72580665fcb0fca332ede450690902c0a7afb6159feff41df1bc10a3cf6607f2 \ No newline at end of file
diff --git a/db/schema_migrations/20201022080802 b/db/schema_migrations/20201022080802
deleted file mode 100644
index c84c8c6ffbe..00000000000
--- a/db/schema_migrations/20201022080802
+++ /dev/null
@@ -1 +0,0 @@
-809d93d367ff9310063904ee3c266914311ef54e8c7f9d6d7fd924d25890bf19 \ No newline at end of file
diff --git a/db/schema_migrations/20201022094845 b/db/schema_migrations/20201022094845
deleted file mode 100644
index 3bc0b95b711..00000000000
--- a/db/schema_migrations/20201022094845
+++ /dev/null
@@ -1 +0,0 @@
-16b402740c6b1dd21908265085e516f63f8858424724ba97f46658e7bd5f7bf2 \ No newline at end of file
diff --git a/db/schema_migrations/20201022094846 b/db/schema_migrations/20201022094846
deleted file mode 100644
index 40ef0760dc8..00000000000
--- a/db/schema_migrations/20201022094846
+++ /dev/null
@@ -1 +0,0 @@
-588c5f99d34652bbd5bde86351cbdb8c0455af0c31a440bfb63df02f12fd588f \ No newline at end of file
diff --git a/db/schema_migrations/20201022103304 b/db/schema_migrations/20201022103304
deleted file mode 100644
index e54cb431bd4..00000000000
--- a/db/schema_migrations/20201022103304
+++ /dev/null
@@ -1 +0,0 @@
-aa15aad0b51f313f3cd59e1065023146fe53c6bd50319656ae992f8f43e1525e \ No newline at end of file
diff --git a/db/schema_migrations/20201022144501 b/db/schema_migrations/20201022144501
deleted file mode 100644
index 4e82b2785d0..00000000000
--- a/db/schema_migrations/20201022144501
+++ /dev/null
@@ -1 +0,0 @@
-f9a573d50f8b4aeb3d8d2cc2f0223ab9970776d663e49e0f022e96158593d929 \ No newline at end of file
diff --git a/db/schema_migrations/20201022191817 b/db/schema_migrations/20201022191817
deleted file mode 100644
index 619ae381a72..00000000000
--- a/db/schema_migrations/20201022191817
+++ /dev/null
@@ -1 +0,0 @@
-205cb628e9637bcd1acb90c5211b71b51015fa5f50aadcacd5fbafc4f09c00d0 \ No newline at end of file
diff --git a/db/schema_migrations/20201022192254 b/db/schema_migrations/20201022192254
deleted file mode 100644
index c09518b0e6c..00000000000
--- a/db/schema_migrations/20201022192254
+++ /dev/null
@@ -1 +0,0 @@
-9f942de6f83629a144e9d460b4bed7a246afe95275b5913745109fc0ab9dacc1 \ No newline at end of file
diff --git a/db/schema_migrations/20201023114628 b/db/schema_migrations/20201023114628
deleted file mode 100644
index 458392082ca..00000000000
--- a/db/schema_migrations/20201023114628
+++ /dev/null
@@ -1 +0,0 @@
-f4fb466c74e1366d5980a54d6e5fc42fe78237cae33d8cdaf5573d2fe75f8a5a \ No newline at end of file
diff --git a/db/schema_migrations/20201026051643 b/db/schema_migrations/20201026051643
deleted file mode 100644
index f3290df0d23..00000000000
--- a/db/schema_migrations/20201026051643
+++ /dev/null
@@ -1 +0,0 @@
-bb20b72c7fa65735f37d896cc098d27edd4cc07c3083fdb567e4b421309703a7 \ No newline at end of file
diff --git a/db/schema_migrations/20201026182253 b/db/schema_migrations/20201026182253
deleted file mode 100644
index a8da92aa906..00000000000
--- a/db/schema_migrations/20201026182253
+++ /dev/null
@@ -1 +0,0 @@
-ab2b8af98a8a29658f92c302d45668c7b9f8f5234ef35f4311a0f0ebbd954ec8 \ No newline at end of file
diff --git a/db/schema_migrations/20201026185514 b/db/schema_migrations/20201026185514
deleted file mode 100644
index f6bdd06e501..00000000000
--- a/db/schema_migrations/20201026185514
+++ /dev/null
@@ -1 +0,0 @@
-a9ae0161c40b9c72371d6eb992bd0da8c3698e7784357faac0821e3f513e48d2 \ No newline at end of file
diff --git a/db/schema_migrations/20201026200736 b/db/schema_migrations/20201026200736
deleted file mode 100644
index 7ed57505c3e..00000000000
--- a/db/schema_migrations/20201026200736
+++ /dev/null
@@ -1 +0,0 @@
-691fe3335de3e072bc5612705c4d16744ff17e334025ddd78eb37309f87441e3 \ No newline at end of file
diff --git a/db/schema_migrations/20201027002551 b/db/schema_migrations/20201027002551
deleted file mode 100644
index f4a5527fac7..00000000000
--- a/db/schema_migrations/20201027002551
+++ /dev/null
@@ -1 +0,0 @@
-34e357b739235d627e543e1bc7202e0cf26f5b1ca8021bb25357e29e883f785b \ No newline at end of file
diff --git a/db/schema_migrations/20201027101010 b/db/schema_migrations/20201027101010
deleted file mode 100644
index 68628373757..00000000000
--- a/db/schema_migrations/20201027101010
+++ /dev/null
@@ -1 +0,0 @@
-d6b324e808265c4ba8b6216c77b7abfa96b4b8b4c9fbd8d0a15240548526c4f3 \ No newline at end of file
diff --git a/db/schema_migrations/20201027135651 b/db/schema_migrations/20201027135651
deleted file mode 100644
index eb3a5080c0f..00000000000
--- a/db/schema_migrations/20201027135651
+++ /dev/null
@@ -1 +0,0 @@
-3f24bfc2d18ffa5f171e027d4e7aaf9994b255e5806e2de57fd36b4a193db122 \ No newline at end of file
diff --git a/db/schema_migrations/20201027210127 b/db/schema_migrations/20201027210127
deleted file mode 100644
index ab0ba73f588..00000000000
--- a/db/schema_migrations/20201027210127
+++ /dev/null
@@ -1 +0,0 @@
-c269a999cabce99d26f3be303656bbb27f2b843b639755b112ad350d4cb5b5c6 \ No newline at end of file
diff --git a/db/schema_migrations/20201027211138 b/db/schema_migrations/20201027211138
deleted file mode 100644
index 5e36445702b..00000000000
--- a/db/schema_migrations/20201027211138
+++ /dev/null
@@ -1 +0,0 @@
-402e9a6e92802888ba01ee216850ab5b0fe9997a84415c9ffe8d5d37a9823220 \ No newline at end of file
diff --git a/db/schema_migrations/20201028160831 b/db/schema_migrations/20201028160831
deleted file mode 100644
index de94901dcc5..00000000000
--- a/db/schema_migrations/20201028160831
+++ /dev/null
@@ -1 +0,0 @@
-4b0c70d8cd2648149011adab4f302922483436406f361c3037f26efb12b19042 \ No newline at end of file
diff --git a/db/schema_migrations/20201028160832 b/db/schema_migrations/20201028160832
deleted file mode 100644
index 4b0da32b638..00000000000
--- a/db/schema_migrations/20201028160832
+++ /dev/null
@@ -1 +0,0 @@
-9ea8e8f1234d6291ea00e725d380bfe33d804853b90da1221be8781b3dd9bb77 \ No newline at end of file
diff --git a/db/schema_migrations/20201028182809 b/db/schema_migrations/20201028182809
deleted file mode 100644
index 6747bd58d72..00000000000
--- a/db/schema_migrations/20201028182809
+++ /dev/null
@@ -1 +0,0 @@
-c51bf825045ef80714f3903f25321785883da3d612725f6fa67ec3ddd12d5808 \ No newline at end of file
diff --git a/db/schema_migrations/20201028184640 b/db/schema_migrations/20201028184640
deleted file mode 100644
index 4cac95e4e7b..00000000000
--- a/db/schema_migrations/20201028184640
+++ /dev/null
@@ -1 +0,0 @@
-5520cca016af07fb2e009c0e3254362f106a9cc808cbb61e280221be82be1b25 \ No newline at end of file
diff --git a/db/schema_migrations/20201028204306 b/db/schema_migrations/20201028204306
deleted file mode 100644
index 03b68c9a0d1..00000000000
--- a/db/schema_migrations/20201028204306
+++ /dev/null
@@ -1 +0,0 @@
-ec5bab20a1b591b77b48b85dc0b871e88a41891d256201b7d8eb86195ef1c4ad \ No newline at end of file
diff --git a/db/schema_migrations/20201029052241 b/db/schema_migrations/20201029052241
deleted file mode 100644
index 8257e4d3681..00000000000
--- a/db/schema_migrations/20201029052241
+++ /dev/null
@@ -1 +0,0 @@
-87e330bc15accb10733825b079cf89e78d905a7c4080075489857085f014bfe7 \ No newline at end of file
diff --git a/db/schema_migrations/20201029143650 b/db/schema_migrations/20201029143650
deleted file mode 100644
index c6f00890f4f..00000000000
--- a/db/schema_migrations/20201029143650
+++ /dev/null
@@ -1 +0,0 @@
-c718bc731f7dc3e1f0104dfdb79a3dc46c46849153ec9b228600eeb5a92465e7 \ No newline at end of file
diff --git a/db/schema_migrations/20201029144157 b/db/schema_migrations/20201029144157
deleted file mode 100644
index 7fdac19230f..00000000000
--- a/db/schema_migrations/20201029144157
+++ /dev/null
@@ -1 +0,0 @@
-a61310c95a1302871ea18881d45bc0c7357baa8f24daa31b7e2174318dab5707 \ No newline at end of file
diff --git a/db/schema_migrations/20201029144444 b/db/schema_migrations/20201029144444
deleted file mode 100644
index 1ab20b33da5..00000000000
--- a/db/schema_migrations/20201029144444
+++ /dev/null
@@ -1 +0,0 @@
-50e4e42c804d3abdcfe9ab2bbb890262d4b2ddd93bff1b2af1da1e55a0300cf5 \ No newline at end of file
diff --git a/db/schema_migrations/20201029144524 b/db/schema_migrations/20201029144524
deleted file mode 100644
index dd25e96ff02..00000000000
--- a/db/schema_migrations/20201029144524
+++ /dev/null
@@ -1 +0,0 @@
-764f08e3083985bb8e206bd25fb27209702110bb4848c8bbfc6546a2777d9157 \ No newline at end of file
diff --git a/db/schema_migrations/20201030092151 b/db/schema_migrations/20201030092151
deleted file mode 100644
index 7b39a8e0dca..00000000000
--- a/db/schema_migrations/20201030092151
+++ /dev/null
@@ -1 +0,0 @@
-ced03562d300f99abf687c258a25bf280a6c4f1798a893ee8a79189c09f19e6e \ No newline at end of file
diff --git a/db/schema_migrations/20201030121314 b/db/schema_migrations/20201030121314
deleted file mode 100644
index b96f100cbd7..00000000000
--- a/db/schema_migrations/20201030121314
+++ /dev/null
@@ -1 +0,0 @@
-4875c1def91676d73f14c2fbff9318fc4ab1f26535503fd9700044b687e9714e \ No newline at end of file
diff --git a/db/schema_migrations/20201030200115 b/db/schema_migrations/20201030200115
deleted file mode 100644
index ed9c743f538..00000000000
--- a/db/schema_migrations/20201030200115
+++ /dev/null
@@ -1 +0,0 @@
-bef50f2417b9676c89aea838f7b9c85fb88af9f52c197d8eb4613a9c91bc7741 \ No newline at end of file
diff --git a/db/schema_migrations/20201030200539 b/db/schema_migrations/20201030200539
deleted file mode 100644
index f8e7642befb..00000000000
--- a/db/schema_migrations/20201030200539
+++ /dev/null
@@ -1 +0,0 @@
-2f6c7efc1716d02dd40adb08bd09b9f1e63e4248619678c0562f4b8d581e6065 \ No newline at end of file
diff --git a/db/schema_migrations/20201030203854 b/db/schema_migrations/20201030203854
deleted file mode 100644
index 6a337c366aa..00000000000
--- a/db/schema_migrations/20201030203854
+++ /dev/null
@@ -1 +0,0 @@
-3937235469c8fb1f2b0af9cdf38933db5ae61552d1a9050755cec5f7c16ebb66 \ No newline at end of file
diff --git a/db/schema_migrations/20201030223933 b/db/schema_migrations/20201030223933
deleted file mode 100644
index 2fb5f394989..00000000000
--- a/db/schema_migrations/20201030223933
+++ /dev/null
@@ -1 +0,0 @@
-a3aa783f2648a95e3ff8b503ef15b8153759c74ac85b30bf94e39710824e57b0 \ No newline at end of file
diff --git a/db/schema_migrations/20201102073808 b/db/schema_migrations/20201102073808
deleted file mode 100644
index 9e77ee028a5..00000000000
--- a/db/schema_migrations/20201102073808
+++ /dev/null
@@ -1 +0,0 @@
-153b437ac481f4d79cd5bdee45dd3932f3cb58bf5dce793573c4b651a3b9314f \ No newline at end of file
diff --git a/db/schema_migrations/20201102112206 b/db/schema_migrations/20201102112206
deleted file mode 100644
index 5bbba26e110..00000000000
--- a/db/schema_migrations/20201102112206
+++ /dev/null
@@ -1 +0,0 @@
-a861c91ebc7f7892020ba10a151df761b38bf69d5e02bcdf72a965eb266e6aff \ No newline at end of file
diff --git a/db/schema_migrations/20201102114018 b/db/schema_migrations/20201102114018
deleted file mode 100644
index 33615073453..00000000000
--- a/db/schema_migrations/20201102114018
+++ /dev/null
@@ -1 +0,0 @@
-dc1c372f4976e3747d7201406123a54e3852d9ea9516089043a93698a09e2f9f \ No newline at end of file
diff --git a/db/schema_migrations/20201102152554 b/db/schema_migrations/20201102152554
deleted file mode 100644
index f52694965c6..00000000000
--- a/db/schema_migrations/20201102152554
+++ /dev/null
@@ -1 +0,0 @@
-7ec73c06ccc4c9f618e0455d0a7aae3b591bf52b5ddb1b3f1678d2fd50b9fd5e \ No newline at end of file
diff --git a/db/schema_migrations/20201102152945 b/db/schema_migrations/20201102152945
deleted file mode 100644
index cb4ae9c2598..00000000000
--- a/db/schema_migrations/20201102152945
+++ /dev/null
@@ -1 +0,0 @@
-55ffd18d5f55ee0fd51a31d50cf2d51595740c72ca23d5134d93e2da3fc186ff \ No newline at end of file
diff --git a/db/schema_migrations/20201102184743 b/db/schema_migrations/20201102184743
deleted file mode 100644
index da002122e5d..00000000000
--- a/db/schema_migrations/20201102184743
+++ /dev/null
@@ -1 +0,0 @@
-040e73d690cb315627fe16c931273aa1f86dfabb481dc2086f787d067b87642f \ No newline at end of file
diff --git a/db/schema_migrations/20201103013242 b/db/schema_migrations/20201103013242
deleted file mode 100644
index 1f592b4a619..00000000000
--- a/db/schema_migrations/20201103013242
+++ /dev/null
@@ -1 +0,0 @@
-8a30cf20f71e0cb198caf6f77a19e4da55b83eb38bdb5888cd2674373d94cede \ No newline at end of file
diff --git a/db/schema_migrations/20201103045515 b/db/schema_migrations/20201103045515
deleted file mode 100644
index 31b56acb147..00000000000
--- a/db/schema_migrations/20201103045515
+++ /dev/null
@@ -1 +0,0 @@
-0172b71564e3d3e30c543890a4672b5a118f8053324b177fbbd9e83357ddf3a8 \ No newline at end of file
diff --git a/db/schema_migrations/20201103095752 b/db/schema_migrations/20201103095752
deleted file mode 100644
index 4888f7c5dfb..00000000000
--- a/db/schema_migrations/20201103095752
+++ /dev/null
@@ -1 +0,0 @@
-3427cf92dc785f399329b00a3dded01dd2a6386cafbd0ef4b732bfcf522ce615 \ No newline at end of file
diff --git a/db/schema_migrations/20201103110018 b/db/schema_migrations/20201103110018
deleted file mode 100644
index 82ab2fda543..00000000000
--- a/db/schema_migrations/20201103110018
+++ /dev/null
@@ -1 +0,0 @@
-8a45a6186d7e18f1dea43593dc0226860fc2e8d3ae386f50a022958b758c7c75 \ No newline at end of file
diff --git a/db/schema_migrations/20201103171537 b/db/schema_migrations/20201103171537
deleted file mode 100644
index 4621c0e4802..00000000000
--- a/db/schema_migrations/20201103171537
+++ /dev/null
@@ -1 +0,0 @@
-3120428427e3c0c94799501b1d31f384c98899f2ef9bda6f95066c94afd5ecf8 \ No newline at end of file
diff --git a/db/schema_migrations/20201103184333 b/db/schema_migrations/20201103184333
deleted file mode 100644
index 0475ea2b466..00000000000
--- a/db/schema_migrations/20201103184333
+++ /dev/null
@@ -1 +0,0 @@
-a3117169b472fffd6302a4da17850a11474c196fd06ebeb3f6b28705d59c74ba \ No newline at end of file
diff --git a/db/schema_migrations/20201103192526 b/db/schema_migrations/20201103192526
deleted file mode 100644
index 8fe11ed16d6..00000000000
--- a/db/schema_migrations/20201103192526
+++ /dev/null
@@ -1 +0,0 @@
-bb137c3a41a40e740f8ae65b43d7f9218f52d6d5eaf53c8a64b3336a8f16141b \ No newline at end of file
diff --git a/db/schema_migrations/20201103202213 b/db/schema_migrations/20201103202213
deleted file mode 100644
index 74b0b1888d2..00000000000
--- a/db/schema_migrations/20201103202213
+++ /dev/null
@@ -1 +0,0 @@
-af006a3c01620c258a253b5c9ccca6faa4cb46a97dddbfeecc0ecc4454eb46e6 \ No newline at end of file
diff --git a/db/schema_migrations/20201104124300 b/db/schema_migrations/20201104124300
deleted file mode 100644
index 6c54da0da54..00000000000
--- a/db/schema_migrations/20201104124300
+++ /dev/null
@@ -1 +0,0 @@
-e17da7eebb6d054a711368369d2b4fa684e96344f845bb7c6b3c89a9b4c4e067 \ No newline at end of file
diff --git a/db/schema_migrations/20201104142036 b/db/schema_migrations/20201104142036
deleted file mode 100644
index 9c41c9c9724..00000000000
--- a/db/schema_migrations/20201104142036
+++ /dev/null
@@ -1 +0,0 @@
-bde71afbe34006eedbd97ac457df31b247fc89a572ca8900c60b16c4d6a8ef93 \ No newline at end of file
diff --git a/db/schema_migrations/20201104204739 b/db/schema_migrations/20201104204739
deleted file mode 100644
index 83794fd569f..00000000000
--- a/db/schema_migrations/20201104204739
+++ /dev/null
@@ -1 +0,0 @@
-9431c771b14d61851e8e69b3a789f222463bbe460078a35c8ad3cbcf8df8b077 \ No newline at end of file
diff --git a/db/schema_migrations/20201105021637 b/db/schema_migrations/20201105021637
deleted file mode 100644
index 05a76d22568..00000000000
--- a/db/schema_migrations/20201105021637
+++ /dev/null
@@ -1 +0,0 @@
-b04e37c8713a333afbff4c7034d9f3ffca4a4490d0b563b73d9e6bffd45f3f6a \ No newline at end of file
diff --git a/db/schema_migrations/20201105024127 b/db/schema_migrations/20201105024127
deleted file mode 100644
index fecda19cb2f..00000000000
--- a/db/schema_migrations/20201105024127
+++ /dev/null
@@ -1 +0,0 @@
-afeff8d6bf5ca14f955f5d387e8d219e852e9617b80fe07ed2e1b57af19fd4fa \ No newline at end of file
diff --git a/db/schema_migrations/20201105135051 b/db/schema_migrations/20201105135051
deleted file mode 100644
index 26ebc47fd3a..00000000000
--- a/db/schema_migrations/20201105135051
+++ /dev/null
@@ -1 +0,0 @@
-41cc59ebfeed647b2525191befa43c1faeb1c133a687a5c93124f4b4c745117a \ No newline at end of file
diff --git a/db/schema_migrations/20201105143211 b/db/schema_migrations/20201105143211
deleted file mode 100644
index 6ddf20c1d68..00000000000
--- a/db/schema_migrations/20201105143211
+++ /dev/null
@@ -1 +0,0 @@
-b614435cdb654ebbd11bcc5ac0ed69352219e51b368d8f10c0b2998c5258caf9 \ No newline at end of file
diff --git a/db/schema_migrations/20201105143312 b/db/schema_migrations/20201105143312
deleted file mode 100644
index fe616c85dc9..00000000000
--- a/db/schema_migrations/20201105143312
+++ /dev/null
@@ -1 +0,0 @@
-decdc314dbcf6b8ac2ce140f81f9d342efca0d98bbeff10c7a041568a67b63f3 \ No newline at end of file
diff --git a/db/schema_migrations/20201106082723 b/db/schema_migrations/20201106082723
deleted file mode 100644
index 0bb6a3b85b8..00000000000
--- a/db/schema_migrations/20201106082723
+++ /dev/null
@@ -1 +0,0 @@
-a2dc0d31af6834adf6634f6051d7d451fc48d31492d96efe57547c3e9d61a64d \ No newline at end of file
diff --git a/db/schema_migrations/20201106134139 b/db/schema_migrations/20201106134139
deleted file mode 100644
index 245cbbf712e..00000000000
--- a/db/schema_migrations/20201106134139
+++ /dev/null
@@ -1 +0,0 @@
-9b1008df64741ad313ddf51969c18d609cd01a7255563fe0395d2bbf4d288e30 \ No newline at end of file
diff --git a/db/schema_migrations/20201106134950 b/db/schema_migrations/20201106134950
deleted file mode 100644
index b36cccd4c40..00000000000
--- a/db/schema_migrations/20201106134950
+++ /dev/null
@@ -1 +0,0 @@
-f6e4e62dbd992fc8283f3d7872bb33f1b6bea1b366806caf8f7a65140584c0c1 \ No newline at end of file
diff --git a/db/schema_migrations/20201106135608 b/db/schema_migrations/20201106135608
deleted file mode 100644
index ce6570d9dbf..00000000000
--- a/db/schema_migrations/20201106135608
+++ /dev/null
@@ -1 +0,0 @@
-52c8fb75035a08e212db52d032638a0c8f9d91306bfb8015fb3fc403a1cff1ec \ No newline at end of file
diff --git a/db/schema_migrations/20201106193452 b/db/schema_migrations/20201106193452
deleted file mode 100644
index c5ce966adfc..00000000000
--- a/db/schema_migrations/20201106193452
+++ /dev/null
@@ -1 +0,0 @@
-dedc2eba6614c61df6e907ddd9813eea2b00fc43bccc6c3325674ad39950df62 \ No newline at end of file
diff --git a/db/schema_migrations/20201107032257 b/db/schema_migrations/20201107032257
deleted file mode 100644
index 4ea5f763dc0..00000000000
--- a/db/schema_migrations/20201107032257
+++ /dev/null
@@ -1 +0,0 @@
-07160ee3c92e68273042df979640c3927abbb187f79e1a4645471e28061e1c2c \ No newline at end of file
diff --git a/db/schema_migrations/20201108134919 b/db/schema_migrations/20201108134919
deleted file mode 100644
index 10e88ae9359..00000000000
--- a/db/schema_migrations/20201108134919
+++ /dev/null
@@ -1 +0,0 @@
-6643e5b4c5597d92c94115f392bfbd5cfce9884eb0bcb18f9629855f3711eed0 \ No newline at end of file
diff --git a/db/schema_migrations/20201109080645 b/db/schema_migrations/20201109080645
deleted file mode 100644
index 403f1951b8b..00000000000
--- a/db/schema_migrations/20201109080645
+++ /dev/null
@@ -1 +0,0 @@
-27ee3c5429dba139e6c300961172c4f90d25397e3d1e13d0654e049b63ac3325 \ No newline at end of file
diff --git a/db/schema_migrations/20201109080646 b/db/schema_migrations/20201109080646
deleted file mode 100644
index ef0edcba9cf..00000000000
--- a/db/schema_migrations/20201109080646
+++ /dev/null
@@ -1 +0,0 @@
-bdbf3cf39228c9b65b02391a9aa030bdeb06aa3fc9955e2fd53bd784bea37b66 \ No newline at end of file
diff --git a/db/schema_migrations/20201109114603 b/db/schema_migrations/20201109114603
deleted file mode 100644
index c1df2223dbd..00000000000
--- a/db/schema_migrations/20201109114603
+++ /dev/null
@@ -1 +0,0 @@
-ae8034ec52df47ce2ce3397715dd18347e4d297a963c17c7b26321f414dfa632 \ No newline at end of file
diff --git a/db/schema_migrations/20201109144634 b/db/schema_migrations/20201109144634
deleted file mode 100644
index 8f47a75dfb8..00000000000
--- a/db/schema_migrations/20201109144634
+++ /dev/null
@@ -1 +0,0 @@
-cbb2a2027fb6083771e97510a00c07a4ded0576e89fafd6cff4faba4e21c82c0 \ No newline at end of file
diff --git a/db/schema_migrations/20201109180311 b/db/schema_migrations/20201109180311
deleted file mode 100644
index 0752e2dabb3..00000000000
--- a/db/schema_migrations/20201109180311
+++ /dev/null
@@ -1 +0,0 @@
-49143d2a7dd0a53c051151b0cdc93745a0fa1b01e6d54bb663e147c2064d9290 \ No newline at end of file
diff --git a/db/schema_migrations/20201109184023 b/db/schema_migrations/20201109184023
deleted file mode 100644
index 7a66c0f0f4c..00000000000
--- a/db/schema_migrations/20201109184023
+++ /dev/null
@@ -1 +0,0 @@
-698bcedf387fc01fbb7f1899f0f7660ba86a197fa72cf71d998cc90e3d1da9f3 \ No newline at end of file
diff --git a/db/schema_migrations/20201110035029 b/db/schema_migrations/20201110035029
deleted file mode 100644
index 9631f17bce0..00000000000
--- a/db/schema_migrations/20201110035029
+++ /dev/null
@@ -1 +0,0 @@
-21245809e056dfefedc4d2c6a8e2bf642bfcee480a863f8707ba6fa6b748a2e0 \ No newline at end of file
diff --git a/db/schema_migrations/20201110110454 b/db/schema_migrations/20201110110454
deleted file mode 100644
index 5b721550325..00000000000
--- a/db/schema_migrations/20201110110454
+++ /dev/null
@@ -1 +0,0 @@
-f008d77d2a0aef463a924923d5a338030758d6b9c194756a0490b51a95681127 \ No newline at end of file
diff --git a/db/schema_migrations/20201110133629 b/db/schema_migrations/20201110133629
deleted file mode 100644
index 487b5eab7c1..00000000000
--- a/db/schema_migrations/20201110133629
+++ /dev/null
@@ -1 +0,0 @@
-83773b825db9b2671fd4ffb2c0d6733036737385ce7a933040011026b34ba1e1 \ No newline at end of file
diff --git a/db/schema_migrations/20201110161542 b/db/schema_migrations/20201110161542
deleted file mode 100644
index 1d4ca947738..00000000000
--- a/db/schema_migrations/20201110161542
+++ /dev/null
@@ -1 +0,0 @@
-ebc304867bab499da3f9fa69b32373a328948b5068b226df5166042d1c1c7604 \ No newline at end of file
diff --git a/db/schema_migrations/20201110221400 b/db/schema_migrations/20201110221400
deleted file mode 100644
index 703dcba863a..00000000000
--- a/db/schema_migrations/20201110221400
+++ /dev/null
@@ -1 +0,0 @@
-9fba60d8805915fcf6af7812e2c752007ac17bb92c8a02c942c0c790d2997441 \ No newline at end of file
diff --git a/db/schema_migrations/20201111051655 b/db/schema_migrations/20201111051655
deleted file mode 100644
index a2fff09e4b0..00000000000
--- a/db/schema_migrations/20201111051655
+++ /dev/null
@@ -1 +0,0 @@
-4340d0f6d3b660b336fdc3166a4960865c79e90f505b1173bab4e0d11c1199b3 \ No newline at end of file
diff --git a/db/schema_migrations/20201111051847 b/db/schema_migrations/20201111051847
deleted file mode 100644
index 6d593fc1497..00000000000
--- a/db/schema_migrations/20201111051847
+++ /dev/null
@@ -1 +0,0 @@
-8180908c5e577757b3f518d312cbf0ba77c65b39fa55dde487036541f49114a1 \ No newline at end of file
diff --git a/db/schema_migrations/20201111051904 b/db/schema_migrations/20201111051904
deleted file mode 100644
index 857f3a58788..00000000000
--- a/db/schema_migrations/20201111051904
+++ /dev/null
@@ -1 +0,0 @@
-c228aa5c16e63af7520dd1bd90cefb1f74ec2371af3b0e839938d8c628f70e8a \ No newline at end of file
diff --git a/db/schema_migrations/20201111100136 b/db/schema_migrations/20201111100136
deleted file mode 100644
index da41078fafb..00000000000
--- a/db/schema_migrations/20201111100136
+++ /dev/null
@@ -1 +0,0 @@
-7a905f8e636be21e328a622d9871018903982989836e6e0def09fd2c2826691f \ No newline at end of file
diff --git a/db/schema_migrations/20201111110318 b/db/schema_migrations/20201111110318
deleted file mode 100644
index 0a88f8f09df..00000000000
--- a/db/schema_migrations/20201111110318
+++ /dev/null
@@ -1 +0,0 @@
-4168c39fe93b1c11d8080e07167f79c8234c74a7b274332174d9e861f2084ada \ No newline at end of file
diff --git a/db/schema_migrations/20201111110918 b/db/schema_migrations/20201111110918
deleted file mode 100644
index cfc30e2bcfc..00000000000
--- a/db/schema_migrations/20201111110918
+++ /dev/null
@@ -1 +0,0 @@
-f5705da7bce46d98ca798c85f08d8a6a0577839aabacd0ba9b50e0b7351a4e96 \ No newline at end of file
diff --git a/db/schema_migrations/20201111115414 b/db/schema_migrations/20201111115414
deleted file mode 100644
index b6fc30be8df..00000000000
--- a/db/schema_migrations/20201111115414
+++ /dev/null
@@ -1 +0,0 @@
-0efb2dcfc65da007a67a15857d0a283dad301650f999a4227aa54ea00dca24bf \ No newline at end of file
diff --git a/db/schema_migrations/20201111145317 b/db/schema_migrations/20201111145317
deleted file mode 100644
index b6b33df7645..00000000000
--- a/db/schema_migrations/20201111145317
+++ /dev/null
@@ -1 +0,0 @@
-51d26848722466503e43b0f41e2fa43ee6073a16b358311a0aff6d77fbb12b1d \ No newline at end of file
diff --git a/db/schema_migrations/20201111152859 b/db/schema_migrations/20201111152859
deleted file mode 100644
index 2d5b337b857..00000000000
--- a/db/schema_migrations/20201111152859
+++ /dev/null
@@ -1 +0,0 @@
-4c5baa6a09a339fac544f830d5ef822b1e7e4eae8431bd91df5113125accbc77 \ No newline at end of file
diff --git a/db/schema_migrations/20201112130710 b/db/schema_migrations/20201112130710
deleted file mode 100644
index a13668cf3ce..00000000000
--- a/db/schema_migrations/20201112130710
+++ /dev/null
@@ -1 +0,0 @@
-322d7270e942c161cc8b50b8c3f531c93b6e6e938e415c1b6010a70b630bf82e \ No newline at end of file
diff --git a/db/schema_migrations/20201112130715 b/db/schema_migrations/20201112130715
deleted file mode 100644
index b241214e15e..00000000000
--- a/db/schema_migrations/20201112130715
+++ /dev/null
@@ -1 +0,0 @@
-fc821ffb2e2298bfdf3555bb255e2300f3722141cadc8f89e62646fd6f22faf0 \ No newline at end of file
diff --git a/db/schema_migrations/20201112132808 b/db/schema_migrations/20201112132808
deleted file mode 100644
index d6cc9595c80..00000000000
--- a/db/schema_migrations/20201112132808
+++ /dev/null
@@ -1 +0,0 @@
-2b30b1ba41a49ce4a81711e6fef1dbcdaf8b76f824aaf83702cd27833815e57b \ No newline at end of file
diff --git a/db/schema_migrations/20201112145311 b/db/schema_migrations/20201112145311
deleted file mode 100644
index b6b88862a38..00000000000
--- a/db/schema_migrations/20201112145311
+++ /dev/null
@@ -1 +0,0 @@
-085bb21bdbe3d062b3000d63c111aab5ba75c7e049c32779cccac5c320583759 \ No newline at end of file
diff --git a/db/schema_migrations/20201112173532 b/db/schema_migrations/20201112173532
deleted file mode 100644
index a0c879e5b36..00000000000
--- a/db/schema_migrations/20201112173532
+++ /dev/null
@@ -1 +0,0 @@
-d88a47333a4cc2b6c4aafa817c766822728d14b947a195c7c40b39e0c8b41610 \ No newline at end of file
diff --git a/db/schema_migrations/20201112173911 b/db/schema_migrations/20201112173911
deleted file mode 100644
index aa98ecb7f14..00000000000
--- a/db/schema_migrations/20201112173911
+++ /dev/null
@@ -1 +0,0 @@
-dde78a32d53a695e82b44574458b3670dce4803ffc6f34a1216f3671cca470ed \ No newline at end of file
diff --git a/db/schema_migrations/20201112195322 b/db/schema_migrations/20201112195322
deleted file mode 100644
index ba4c7e9d50f..00000000000
--- a/db/schema_migrations/20201112195322
+++ /dev/null
@@ -1 +0,0 @@
-644bf793b3b62330bfb1f4dc406e6dd01cbcf4651ebfd2873fb551c757c8a3b4 \ No newline at end of file
diff --git a/db/schema_migrations/20201112215028 b/db/schema_migrations/20201112215028
deleted file mode 100644
index 07cedc7a146..00000000000
--- a/db/schema_migrations/20201112215028
+++ /dev/null
@@ -1 +0,0 @@
-d8d774e788eeaaecbda3cb7c5530926e74843d844bfad27b6a6e65bf5f89ac8a \ No newline at end of file
diff --git a/db/schema_migrations/20201112215132 b/db/schema_migrations/20201112215132
deleted file mode 100644
index e478dd0f9bf..00000000000
--- a/db/schema_migrations/20201112215132
+++ /dev/null
@@ -1 +0,0 @@
-a436597e876a6d9efc2c1558e05dc576cbbc6f829dc8059d62fc231bbf0ce2fa \ No newline at end of file
diff --git a/db/schema_migrations/20201113105000 b/db/schema_migrations/20201113105000
deleted file mode 100644
index 0fe67898517..00000000000
--- a/db/schema_migrations/20201113105000
+++ /dev/null
@@ -1 +0,0 @@
-9f2c60df8e89f89d721f7f7917048eb914fa7c7726ec42dcb772ff7a90c54a9c \ No newline at end of file
diff --git a/db/schema_migrations/20201116090328 b/db/schema_migrations/20201116090328
deleted file mode 100644
index 423eb54ff21..00000000000
--- a/db/schema_migrations/20201116090328
+++ /dev/null
@@ -1 +0,0 @@
-39a109d2a0daaac6e5d40b13ee48f5388b85320c1ae6214408596417794307f3 \ No newline at end of file
diff --git a/db/schema_migrations/20201116211829 b/db/schema_migrations/20201116211829
deleted file mode 100644
index bc583573000..00000000000
--- a/db/schema_migrations/20201116211829
+++ /dev/null
@@ -1 +0,0 @@
-ecec9923058e58a5279f75dd9c2ff61263f187a1d893bb84241c57a4061dadf8 \ No newline at end of file
diff --git a/db/schema_migrations/20201117054609 b/db/schema_migrations/20201117054609
deleted file mode 100644
index 624c12754d3..00000000000
--- a/db/schema_migrations/20201117054609
+++ /dev/null
@@ -1 +0,0 @@
-119afd73a58c247522446bc9693ece5c83a25c279e4dd7dfb942f7febd5b7a82 \ No newline at end of file
diff --git a/db/schema_migrations/20201117075742 b/db/schema_migrations/20201117075742
deleted file mode 100644
index b3efeee7e0b..00000000000
--- a/db/schema_migrations/20201117075742
+++ /dev/null
@@ -1 +0,0 @@
-a39bad8b213833c84370cf64188a3ce444fd8aeeff239c29f5f2f633d94ac6bb \ No newline at end of file
diff --git a/db/schema_migrations/20201117153333 b/db/schema_migrations/20201117153333
deleted file mode 100644
index ee496f91777..00000000000
--- a/db/schema_migrations/20201117153333
+++ /dev/null
@@ -1 +0,0 @@
-008f3a69d23abbd513336c5a48b2448e470a9413920beeb6a1684d0c6840d6a4 \ No newline at end of file
diff --git a/db/schema_migrations/20201117184334 b/db/schema_migrations/20201117184334
deleted file mode 100644
index 347d6ca087c..00000000000
--- a/db/schema_migrations/20201117184334
+++ /dev/null
@@ -1 +0,0 @@
-7988d01be5fac0f2a28cc97e309bfa16450d2e376888401fc2ad521aa0082020 \ No newline at end of file
diff --git a/db/schema_migrations/20201117203224 b/db/schema_migrations/20201117203224
deleted file mode 100644
index c161bc5c404..00000000000
--- a/db/schema_migrations/20201117203224
+++ /dev/null
@@ -1 +0,0 @@
-4c66fd85d6c219d9bedb06c3a38610ecd2c2b1fcb668b132624d7bb76ae2a1ee \ No newline at end of file
diff --git a/db/schema_migrations/20201117213024 b/db/schema_migrations/20201117213024
deleted file mode 100644
index 209e170caa0..00000000000
--- a/db/schema_migrations/20201117213024
+++ /dev/null
@@ -1 +0,0 @@
-13b30e906a473ead632b808dca2dea2f9fff63920c4e55b97c43d2b30955c0c2 \ No newline at end of file
diff --git a/db/schema_migrations/20201118093135 b/db/schema_migrations/20201118093135
deleted file mode 100644
index 7bf60967db0..00000000000
--- a/db/schema_migrations/20201118093135
+++ /dev/null
@@ -1 +0,0 @@
-4be52737be2bc74e666e973fa42f17a16e652cb4fa2368c7f347c3f1f8941dbb \ No newline at end of file
diff --git a/db/schema_migrations/20201119031515 b/db/schema_migrations/20201119031515
deleted file mode 100644
index 3abfe9de238..00000000000
--- a/db/schema_migrations/20201119031515
+++ /dev/null
@@ -1 +0,0 @@
-6d2e6937c9e41975b1fd402bf2985796792a1e5f8e4f4f98bc76b65ff73c4e02 \ No newline at end of file
diff --git a/db/schema_migrations/20201119053603 b/db/schema_migrations/20201119053603
deleted file mode 100644
index 7555dbfb2ca..00000000000
--- a/db/schema_migrations/20201119053603
+++ /dev/null
@@ -1 +0,0 @@
-c7567489156bbc047cf9f7827f060ad507fd5d328179f2796566a7dc54806e3e \ No newline at end of file
diff --git a/db/schema_migrations/20201119092319 b/db/schema_migrations/20201119092319
deleted file mode 100644
index c48e0fc2563..00000000000
--- a/db/schema_migrations/20201119092319
+++ /dev/null
@@ -1 +0,0 @@
-9ff8ddefff1df81f1eac2ccfc6f3019bb77a6129280e799c0abe54f51e09277a \ No newline at end of file
diff --git a/db/schema_migrations/20201119125730 b/db/schema_migrations/20201119125730
deleted file mode 100644
index 39de483e890..00000000000
--- a/db/schema_migrations/20201119125730
+++ /dev/null
@@ -1 +0,0 @@
-9fb3c338c999617b40e4c63f24ea037b5b1403354b93c2117e028ad8348d96aa \ No newline at end of file
diff --git a/db/schema_migrations/20201119133534 b/db/schema_migrations/20201119133534
deleted file mode 100644
index b3999923381..00000000000
--- a/db/schema_migrations/20201119133534
+++ /dev/null
@@ -1 +0,0 @@
-6c8fc7904f50a792e10b5f1b0abe90ba21b1bdfd47430b3caa0df870c0a24079 \ No newline at end of file
diff --git a/db/schema_migrations/20201119133604 b/db/schema_migrations/20201119133604
deleted file mode 100644
index 865ce7db9e7..00000000000
--- a/db/schema_migrations/20201119133604
+++ /dev/null
@@ -1 +0,0 @@
-bfb8ac3b697675bd4fca53273c6c6feb2f7a5659cbdaf57b9b4adb3e189b74ad \ No newline at end of file
diff --git a/db/schema_migrations/20201119162801 b/db/schema_migrations/20201119162801
deleted file mode 100644
index b6aa67ad5f6..00000000000
--- a/db/schema_migrations/20201119162801
+++ /dev/null
@@ -1 +0,0 @@
-c41f4649540c23d25f0ae26c3754476409b5e77f53b96db65f2c1fd4a6caf087 \ No newline at end of file
diff --git a/db/schema_migrations/20201119164605 b/db/schema_migrations/20201119164605
deleted file mode 100644
index 61e4c88a241..00000000000
--- a/db/schema_migrations/20201119164605
+++ /dev/null
@@ -1 +0,0 @@
-5abd2cfdf96b493f8d3ecc857f850acb95e3ea30307a72c2e6f20c5feff8f5e7 \ No newline at end of file
diff --git a/db/schema_migrations/20201119213406 b/db/schema_migrations/20201119213406
deleted file mode 100644
index 0bd2418a6ee..00000000000
--- a/db/schema_migrations/20201119213406
+++ /dev/null
@@ -1 +0,0 @@
-33970a1295b84040c82034041c99f13578352844c9c6cb092b5cc35913576a7e \ No newline at end of file
diff --git a/db/schema_migrations/20201120071303 b/db/schema_migrations/20201120071303
deleted file mode 100644
index 23d712c9993..00000000000
--- a/db/schema_migrations/20201120071303
+++ /dev/null
@@ -1 +0,0 @@
-9684403a075bd1ddf3ae9290ad9a39ed24f4624d99498f8b8ed567588c15e082 \ No newline at end of file
diff --git a/db/schema_migrations/20201120092000 b/db/schema_migrations/20201120092000
deleted file mode 100644
index eaa6c37cff2..00000000000
--- a/db/schema_migrations/20201120092000
+++ /dev/null
@@ -1 +0,0 @@
-c8f837a5fe7a1959af41f19f93b6dd96d8907a476626f124876ee8b10b120b71 \ No newline at end of file
diff --git a/db/schema_migrations/20201120125953 b/db/schema_migrations/20201120125953
deleted file mode 100644
index 23aca1557e0..00000000000
--- a/db/schema_migrations/20201120125953
+++ /dev/null
@@ -1 +0,0 @@
-8b60a6bc892f9700df81de9909595544f9f820621a210906a249428ddec9eefa \ No newline at end of file
diff --git a/db/schema_migrations/20201120140210 b/db/schema_migrations/20201120140210
deleted file mode 100644
index 5a281f95f5d..00000000000
--- a/db/schema_migrations/20201120140210
+++ /dev/null
@@ -1 +0,0 @@
-6b88d79aa8d373fa1d9aa2698a9d20c09aff14ef16af4c123abd4e7c98e41311 \ No newline at end of file
diff --git a/db/schema_migrations/20201120144823 b/db/schema_migrations/20201120144823
deleted file mode 100644
index 4f0c5c43978..00000000000
--- a/db/schema_migrations/20201120144823
+++ /dev/null
@@ -1 +0,0 @@
-dde424c434c78e22087123fa30eec75c07268a9079fea44339915747aae235e0 \ No newline at end of file
diff --git a/db/schema_migrations/20201123081307 b/db/schema_migrations/20201123081307
deleted file mode 100644
index 5169f80108d..00000000000
--- a/db/schema_migrations/20201123081307
+++ /dev/null
@@ -1 +0,0 @@
-9b212f5fd6f58123f0d46249c82b2da49af9bcdd36bcc0de610c4be186b17345 \ No newline at end of file
diff --git a/db/schema_migrations/20201123161611 b/db/schema_migrations/20201123161611
deleted file mode 100644
index bcd28f2b4da..00000000000
--- a/db/schema_migrations/20201123161611
+++ /dev/null
@@ -1 +0,0 @@
-9d69938cda6db1510ed17d087cc1a582af1e5482d65e4fb457e34011e09c3469 \ No newline at end of file
diff --git a/db/schema_migrations/20201124030537 b/db/schema_migrations/20201124030537
deleted file mode 100644
index 6754e179ae3..00000000000
--- a/db/schema_migrations/20201124030537
+++ /dev/null
@@ -1 +0,0 @@
-2929b74d9b9d6e205c0e1fb2aaaffe323394058f6e583c56035a2c83b4d4ff03 \ No newline at end of file
diff --git a/db/schema_migrations/20201124075951 b/db/schema_migrations/20201124075951
deleted file mode 100644
index b659c83ad21..00000000000
--- a/db/schema_migrations/20201124075951
+++ /dev/null
@@ -1 +0,0 @@
-6779e92fa65ff206b19bb99a5a242e3ab5fd7a8d15be89dee925d1fbb5b00632 \ No newline at end of file
diff --git a/db/schema_migrations/20201124122817 b/db/schema_migrations/20201124122817
deleted file mode 100644
index d7fd2707dd3..00000000000
--- a/db/schema_migrations/20201124122817
+++ /dev/null
@@ -1 +0,0 @@
-1113642dfc9069dcea01ac12b1653dfcf67b3aea449538e9747d3bc857ce88d8 \ No newline at end of file
diff --git a/db/schema_migrations/20201124185639 b/db/schema_migrations/20201124185639
deleted file mode 100644
index 9ca03d7d837..00000000000
--- a/db/schema_migrations/20201124185639
+++ /dev/null
@@ -1 +0,0 @@
-dd36b2815c62ef9710d88fa92c410398a228c50a7e51d44ce02e85c9f63d648e \ No newline at end of file
diff --git a/db/schema_migrations/20201125030847 b/db/schema_migrations/20201125030847
deleted file mode 100644
index 2b88d374d52..00000000000
--- a/db/schema_migrations/20201125030847
+++ /dev/null
@@ -1 +0,0 @@
-e19c6d019f1478e5998b2a264c5327dc82da7fde7edd19b15da70a30c5779844 \ No newline at end of file
diff --git a/db/schema_migrations/20201125233219 b/db/schema_migrations/20201125233219
deleted file mode 100644
index 54728b704e9..00000000000
--- a/db/schema_migrations/20201125233219
+++ /dev/null
@@ -1 +0,0 @@
-451d7f29392f965467f364c7b119d269551e2dc1485e8cb15ebd14753fdb6e6a \ No newline at end of file
diff --git a/db/schema_migrations/20201126165919 b/db/schema_migrations/20201126165919
deleted file mode 100644
index 533273ec9a2..00000000000
--- a/db/schema_migrations/20201126165919
+++ /dev/null
@@ -1 +0,0 @@
-a68c609800f5bdb0a77e39f706b410477493e7b7db3af11e4b2a67534df31079 \ No newline at end of file
diff --git a/db/schema_migrations/20201126172030 b/db/schema_migrations/20201126172030
deleted file mode 100644
index 789a914af41..00000000000
--- a/db/schema_migrations/20201126172030
+++ /dev/null
@@ -1 +0,0 @@
-65dcc2a53d48acc83dbfc5276e8cfc1eee5f20ffea8355d86df1f2d5b329061b \ No newline at end of file
diff --git a/db/schema_migrations/20201126190039 b/db/schema_migrations/20201126190039
deleted file mode 100644
index 0e70a7e92bf..00000000000
--- a/db/schema_migrations/20201126190039
+++ /dev/null
@@ -1 +0,0 @@
-65935afe9b4ad195aaf31cddb915dcd62b23674e278e93ce7ff9b4ae98e32331 \ No newline at end of file
diff --git a/db/schema_migrations/20201127104228 b/db/schema_migrations/20201127104228
deleted file mode 100644
index 9a582600854..00000000000
--- a/db/schema_migrations/20201127104228
+++ /dev/null
@@ -1 +0,0 @@
-a66f13cf62740c590aa195dd510f1e9f4a36e12d29fd0c824fbd0ace03717706 \ No newline at end of file
diff --git a/db/schema_migrations/20201127141433 b/db/schema_migrations/20201127141433
deleted file mode 100644
index b3db67b566e..00000000000
--- a/db/schema_migrations/20201127141433
+++ /dev/null
@@ -1 +0,0 @@
-70fae11d6a73ea8b2ad75c574716f48e9cc78a58ae23db48e74840646fd46672 \ No newline at end of file
diff --git a/db/schema_migrations/20201127170848 b/db/schema_migrations/20201127170848
deleted file mode 100644
index 11c7ccbb236..00000000000
--- a/db/schema_migrations/20201127170848
+++ /dev/null
@@ -1 +0,0 @@
-ef378c2512a2c3940016bcc82bc8885762ed1a982e38cba1c452a9063e0717e2 \ No newline at end of file
diff --git a/db/schema_migrations/20201128210000 b/db/schema_migrations/20201128210000
deleted file mode 100644
index 9ce8d37ff37..00000000000
--- a/db/schema_migrations/20201128210000
+++ /dev/null
@@ -1 +0,0 @@
-2f7415e3e3e66f326f2f65c38406c2103d5075493c86a836497c3541655f4e86 \ No newline at end of file
diff --git a/db/schema_migrations/20201128210234 b/db/schema_migrations/20201128210234
deleted file mode 100644
index 6c85130bf58..00000000000
--- a/db/schema_migrations/20201128210234
+++ /dev/null
@@ -1 +0,0 @@
-7c2f83a5821765f3657a6dd6f69bc8711a3b9388aec7335293748b883f7ab872 \ No newline at end of file
diff --git a/db/schema_migrations/20201130103926 b/db/schema_migrations/20201130103926
deleted file mode 100644
index 518d58860af..00000000000
--- a/db/schema_migrations/20201130103926
+++ /dev/null
@@ -1 +0,0 @@
-27cd7e7cd01175c157e6aa666b2263bf29210277d5acd997a0619cee67870345 \ No newline at end of file
diff --git a/db/schema_migrations/20201201033202 b/db/schema_migrations/20201201033202
deleted file mode 100644
index a061dc5f404..00000000000
--- a/db/schema_migrations/20201201033202
+++ /dev/null
@@ -1 +0,0 @@
-418481f8281f8908740d3a8378b420f4d83853aab139b3401f7e410fc97d2488 \ No newline at end of file
diff --git a/db/schema_migrations/20201201034258 b/db/schema_migrations/20201201034258
deleted file mode 100644
index 6cf3caf2a06..00000000000
--- a/db/schema_migrations/20201201034258
+++ /dev/null
@@ -1 +0,0 @@
-12cc1beb73bcc31f6546066842913284aabba22ea4e93095271c0cfdacfd0858 \ No newline at end of file
diff --git a/db/schema_migrations/20201201161655 b/db/schema_migrations/20201201161655
deleted file mode 100644
index 892d2bfc08d..00000000000
--- a/db/schema_migrations/20201201161655
+++ /dev/null
@@ -1 +0,0 @@
-d9ad12dce02d6823536f3206e9c90a0da82c08089c3ce252e8ef28a59589e747 \ No newline at end of file
diff --git a/db/schema_migrations/20201201163227 b/db/schema_migrations/20201201163227
deleted file mode 100644
index 0366850ee2f..00000000000
--- a/db/schema_migrations/20201201163227
+++ /dev/null
@@ -1 +0,0 @@
-cc978ac56ed177575706436c52125b51915dff97a20ed47ae0c7b16caa837313 \ No newline at end of file
diff --git a/db/schema_migrations/20201201175656 b/db/schema_migrations/20201201175656
deleted file mode 100644
index 52c98e28eee..00000000000
--- a/db/schema_migrations/20201201175656
+++ /dev/null
@@ -1 +0,0 @@
-54ed18361a28d0b750cbbdb3bfb53b7e4bbe3d1d7264de51522796d3bd15f7a5 \ No newline at end of file
diff --git a/db/schema_migrations/20201201190002 b/db/schema_migrations/20201201190002
deleted file mode 100644
index aac9ac34c64..00000000000
--- a/db/schema_migrations/20201201190002
+++ /dev/null
@@ -1 +0,0 @@
-f4ec800e68cbe092775b428d3ff85a4a84be0d55d70e59d23de390847ea3c2b7 \ No newline at end of file
diff --git a/db/schema_migrations/20201201192112 b/db/schema_migrations/20201201192112
deleted file mode 100644
index 26e17430dbe..00000000000
--- a/db/schema_migrations/20201201192112
+++ /dev/null
@@ -1 +0,0 @@
-bd10ddc5e78ff2d878f3ce6a45a3e808b89e0885dcc710b87f44ede15ace372b \ No newline at end of file
diff --git a/db/schema_migrations/20201202003042 b/db/schema_migrations/20201202003042
deleted file mode 100644
index 13bbfe9f8af..00000000000
--- a/db/schema_migrations/20201202003042
+++ /dev/null
@@ -1 +0,0 @@
-779effb1db70aa8b9a24942ec3e0681064c01b69ee4731f82477c54361a670b0 \ No newline at end of file
diff --git a/db/schema_migrations/20201202025644 b/db/schema_migrations/20201202025644
deleted file mode 100644
index 189704a6d1e..00000000000
--- a/db/schema_migrations/20201202025644
+++ /dev/null
@@ -1 +0,0 @@
-3b0e685327e2199e0a6721e00d1fa3c9fee3a173ce1cf5ddd99df3349a28fea9 \ No newline at end of file
diff --git a/db/schema_migrations/20201202025937 b/db/schema_migrations/20201202025937
deleted file mode 100644
index eb2088259a5..00000000000
--- a/db/schema_migrations/20201202025937
+++ /dev/null
@@ -1 +0,0 @@
-d0706f4a60ae6f26be206aee80fdeb4a7e5c4c0b99e518140ae3cb8c47ed7a82 \ No newline at end of file
diff --git a/db/schema_migrations/20201202133606 b/db/schema_migrations/20201202133606
deleted file mode 100644
index 693c4fc074e..00000000000
--- a/db/schema_migrations/20201202133606
+++ /dev/null
@@ -1 +0,0 @@
-83c7e30abb0c8f4e11faa648a4a509029aafa3230e64fe7b14d63f0a39df05ad \ No newline at end of file
diff --git a/db/schema_migrations/20201202142751 b/db/schema_migrations/20201202142751
deleted file mode 100644
index cb0013a5d70..00000000000
--- a/db/schema_migrations/20201202142751
+++ /dev/null
@@ -1 +0,0 @@
-cb11dc9996b1706feaa8a53f96cbaa6209a4d07b3be9e88ebc3d1e1ada561287 \ No newline at end of file
diff --git a/db/schema_migrations/20201202150001 b/db/schema_migrations/20201202150001
deleted file mode 100644
index a22d35f424e..00000000000
--- a/db/schema_migrations/20201202150001
+++ /dev/null
@@ -1 +0,0 @@
-af9d8c7cda142e2a96a289ebd7afef73367bd544a60794c9e0414c7b82bef8a2 \ No newline at end of file
diff --git a/db/schema_migrations/20201202155913 b/db/schema_migrations/20201202155913
deleted file mode 100644
index 7cb0055455d..00000000000
--- a/db/schema_migrations/20201202155913
+++ /dev/null
@@ -1 +0,0 @@
-926f54b5756fa9495e71f2340823418b5679195d5720212dddda0d0c6396629e \ No newline at end of file
diff --git a/db/schema_migrations/20201202160105 b/db/schema_migrations/20201202160105
deleted file mode 100644
index ff2e6f4ddbc..00000000000
--- a/db/schema_migrations/20201202160105
+++ /dev/null
@@ -1 +0,0 @@
-a011331d225cef852d2402add6fb2b77e7325b87d58343a9367e0dd31a32ed7f \ No newline at end of file
diff --git a/db/schema_migrations/20201202161021 b/db/schema_migrations/20201202161021
deleted file mode 100644
index eae05342e40..00000000000
--- a/db/schema_migrations/20201202161021
+++ /dev/null
@@ -1 +0,0 @@
-696c1d9f8cc90337549530e129e6abf4429d218f151cefaacacacb6e3f33d1c7 \ No newline at end of file
diff --git a/db/schema_migrations/20201203123201 b/db/schema_migrations/20201203123201
deleted file mode 100644
index e3799665ffc..00000000000
--- a/db/schema_migrations/20201203123201
+++ /dev/null
@@ -1 +0,0 @@
-85a642d60e92a880e0a0699f8dcca42aebe2b5363bfcc3010e647734c7cb7dec \ No newline at end of file
diff --git a/db/schema_migrations/20201203123524 b/db/schema_migrations/20201203123524
deleted file mode 100644
index 27f47a237c0..00000000000
--- a/db/schema_migrations/20201203123524
+++ /dev/null
@@ -1 +0,0 @@
-4bb54293c339e20082a739f7724b02141d8fb3b0b140e21ac2acab6cbd2d2f01 \ No newline at end of file
diff --git a/db/schema_migrations/20201203144655 b/db/schema_migrations/20201203144655
deleted file mode 100644
index 50c5e928c82..00000000000
--- a/db/schema_migrations/20201203144655
+++ /dev/null
@@ -1 +0,0 @@
-700e5d0d5615080f7d747cc71dc437abd24a76b5783f8db7d613036142841e09 \ No newline at end of file
diff --git a/db/schema_migrations/20201203171631 b/db/schema_migrations/20201203171631
deleted file mode 100644
index e93633344b9..00000000000
--- a/db/schema_migrations/20201203171631
+++ /dev/null
@@ -1 +0,0 @@
-3b6d3fb9c279f5e8c76921e654b188a5a5ba0fddd7ff753a03706b41f43240ed \ No newline at end of file
diff --git a/db/schema_migrations/20201204085522 b/db/schema_migrations/20201204085522
deleted file mode 100644
index 21009a5d34a..00000000000
--- a/db/schema_migrations/20201204085522
+++ /dev/null
@@ -1 +0,0 @@
-a1d8228731066fb6dfe436b4d8d034353421d1f45f3896e963f3c7f15fb09fbc \ No newline at end of file
diff --git a/db/schema_migrations/20201204090855 b/db/schema_migrations/20201204090855
deleted file mode 100644
index 7e6bb71d977..00000000000
--- a/db/schema_migrations/20201204090855
+++ /dev/null
@@ -1 +0,0 @@
-01712e32d95578fe701738529abfa0e051ef68ed646f7a9c7f775f8a8d108578 \ No newline at end of file
diff --git a/db/schema_migrations/20201204105300 b/db/schema_migrations/20201204105300
deleted file mode 100644
index e54d4f939b9..00000000000
--- a/db/schema_migrations/20201204105300
+++ /dev/null
@@ -1 +0,0 @@
-15f48c654c08b58c90e46ce6e6413efa14d5a6e8299f100fc65f09f38190132a \ No newline at end of file
diff --git a/db/schema_migrations/20201204110700 b/db/schema_migrations/20201204110700
deleted file mode 100644
index b69e93149c2..00000000000
--- a/db/schema_migrations/20201204110700
+++ /dev/null
@@ -1 +0,0 @@
-986ffa5e3e168ce9acf9b346c94bdee05d85c71abe238b8aa21f95cc472faabc \ No newline at end of file
diff --git a/db/schema_migrations/20201204110800 b/db/schema_migrations/20201204110800
deleted file mode 100644
index de1fdf7442a..00000000000
--- a/db/schema_migrations/20201204110800
+++ /dev/null
@@ -1 +0,0 @@
-aecf517402d3decf8f7323e8f43fdfe7160cbe7542a474e392996abd75b2d70f \ No newline at end of file
diff --git a/db/schema_migrations/20201204111000 b/db/schema_migrations/20201204111000
deleted file mode 100644
index be3078cf503..00000000000
--- a/db/schema_migrations/20201204111000
+++ /dev/null
@@ -1 +0,0 @@
-e9ca7eb8a47f6c48667135eca26f729471f8bb4ffa91dfceea87d98c8f2a616b \ No newline at end of file
diff --git a/db/schema_migrations/20201204111100 b/db/schema_migrations/20201204111100
deleted file mode 100644
index db3832d5331..00000000000
--- a/db/schema_migrations/20201204111100
+++ /dev/null
@@ -1 +0,0 @@
-b613f8654641948b2933910ebbfc926fd801b18c00a5d23b1c801a9ba9925520 \ No newline at end of file
diff --git a/db/schema_migrations/20201204111200 b/db/schema_migrations/20201204111200
deleted file mode 100644
index 34628516bf8..00000000000
--- a/db/schema_migrations/20201204111200
+++ /dev/null
@@ -1 +0,0 @@
-2aad94b0577882df4fec3df3806993858dad9f4eb20db71c94f8590c6640d62e \ No newline at end of file
diff --git a/db/schema_migrations/20201204111300 b/db/schema_migrations/20201204111300
deleted file mode 100644
index 69a114bed98..00000000000
--- a/db/schema_migrations/20201204111300
+++ /dev/null
@@ -1 +0,0 @@
-e1265a293640d0d067672cb0426987c4a308025cf5a15b17bac8e30267dc8eaf \ No newline at end of file
diff --git a/db/schema_migrations/20201204111400 b/db/schema_migrations/20201204111400
deleted file mode 100644
index 54fcc022f10..00000000000
--- a/db/schema_migrations/20201204111400
+++ /dev/null
@@ -1 +0,0 @@
-6fcaa4184ae69fabd6f2668cad19c38a8ae7c187053d60cdf4fcbdbc0443aa42 \ No newline at end of file
diff --git a/db/schema_migrations/20201204111500 b/db/schema_migrations/20201204111500
deleted file mode 100644
index d482fb6d31a..00000000000
--- a/db/schema_migrations/20201204111500
+++ /dev/null
@@ -1 +0,0 @@
-3f422a916b50cafd46b4a7486b6c3cc0a9992831a7dbc40c51323c835d845a0a \ No newline at end of file
diff --git a/db/schema_migrations/20201204111600 b/db/schema_migrations/20201204111600
deleted file mode 100644
index d6c5e232962..00000000000
--- a/db/schema_migrations/20201204111600
+++ /dev/null
@@ -1 +0,0 @@
-51967d740ce184b27d0d9417fc86cb896fd3e3aa8a5e40759b290f47b9f3e99b \ No newline at end of file
diff --git a/db/schema_migrations/20201204141038 b/db/schema_migrations/20201204141038
deleted file mode 100644
index c422a095eda..00000000000
--- a/db/schema_migrations/20201204141038
+++ /dev/null
@@ -1 +0,0 @@
-9dc8d6b557198a60def4690ea06ec3dc9a29deca9082b7b03666aaed483a42f1 \ No newline at end of file
diff --git a/db/schema_migrations/20201204193952 b/db/schema_migrations/20201204193952
deleted file mode 100644
index 4dcea03722f..00000000000
--- a/db/schema_migrations/20201204193952
+++ /dev/null
@@ -1 +0,0 @@
-39e5550b6ad6f718a51cf9838ac9148bcaa070aff60f6114bd96e4a76faf2ca1 \ No newline at end of file
diff --git a/db/schema_migrations/20201204205814 b/db/schema_migrations/20201204205814
deleted file mode 100644
index 2308ba1245c..00000000000
--- a/db/schema_migrations/20201204205814
+++ /dev/null
@@ -1 +0,0 @@
-8178b8a9acf7d2d8990bb6f7d984eb9e3b77d45cb2a8b54b56500ef6f93772ad \ No newline at end of file
diff --git a/db/schema_migrations/20201204215353 b/db/schema_migrations/20201204215353
deleted file mode 100644
index 08305f419eb..00000000000
--- a/db/schema_migrations/20201204215353
+++ /dev/null
@@ -1 +0,0 @@
-a3dd8cfe4a5d83ca370cac90acf127facf40c0fd63ae8d1d3f99418295bae148 \ No newline at end of file
diff --git a/db/schema_migrations/20201207151651 b/db/schema_migrations/20201207151651
deleted file mode 100644
index 92d8fbec6bd..00000000000
--- a/db/schema_migrations/20201207151651
+++ /dev/null
@@ -1 +0,0 @@
-93def9138efddc9cd0ace5524dc5cf6cdc0221977083324c5c0ad3cf3fb75e55 \ No newline at end of file
diff --git a/db/schema_migrations/20201207165956 b/db/schema_migrations/20201207165956
deleted file mode 100644
index 4bded1d3152..00000000000
--- a/db/schema_migrations/20201207165956
+++ /dev/null
@@ -1 +0,0 @@
-1ad19d6b4bc37d24f61f158aa58e4ce6be75cc54722cdc59427c00522fd40b4c \ No newline at end of file
diff --git a/db/schema_migrations/20201208081429 b/db/schema_migrations/20201208081429
deleted file mode 100644
index c7156129ecc..00000000000
--- a/db/schema_migrations/20201208081429
+++ /dev/null
@@ -1 +0,0 @@
-5c429e8090fd779ba29a8bd78d69e78d1d5d143a6fd3097a715e178fb150d877 \ No newline at end of file
diff --git a/db/schema_migrations/20201208143911 b/db/schema_migrations/20201208143911
deleted file mode 100644
index b953bd502f1..00000000000
--- a/db/schema_migrations/20201208143911
+++ /dev/null
@@ -1 +0,0 @@
-1e55cafd8b7c5b13514a8709c05d75c8ef0bdd99ea1a5bd3d36f8d20fc0ead2b \ No newline at end of file
diff --git a/db/schema_migrations/20201208175117 b/db/schema_migrations/20201208175117
deleted file mode 100644
index caa1bcaedd8..00000000000
--- a/db/schema_migrations/20201208175117
+++ /dev/null
@@ -1 +0,0 @@
-68971e7f9a722e98d9e611f614b5465de83ff3d4dc8c7a8078ed1db8f21e6590 \ No newline at end of file
diff --git a/db/schema_migrations/20201208181411 b/db/schema_migrations/20201208181411
deleted file mode 100644
index 951925cef9d..00000000000
--- a/db/schema_migrations/20201208181411
+++ /dev/null
@@ -1 +0,0 @@
-7bbd0cfb98c3e051942bf062444d2586588fe029d9a9548f0e50e0fbad10a490 \ No newline at end of file
diff --git a/db/schema_migrations/20201208210209 b/db/schema_migrations/20201208210209
deleted file mode 100644
index 61679844170..00000000000
--- a/db/schema_migrations/20201208210209
+++ /dev/null
@@ -1 +0,0 @@
-90b661656195e61c3b3ac43b8eebcdc06f462eb7e73a6201b2f2a8bc9dd519bf \ No newline at end of file
diff --git a/db/schema_migrations/20201209154746 b/db/schema_migrations/20201209154746
deleted file mode 100644
index 3f88f88dc50..00000000000
--- a/db/schema_migrations/20201209154746
+++ /dev/null
@@ -1 +0,0 @@
-98e132fd1daadca14b4313783691c523290efdc81372ec8416bcea1a597376bf \ No newline at end of file
diff --git a/db/schema_migrations/20201209163113 b/db/schema_migrations/20201209163113
deleted file mode 100644
index a850a8d90a2..00000000000
--- a/db/schema_migrations/20201209163113
+++ /dev/null
@@ -1 +0,0 @@
-a7397b8f5d00b85f8c963f04ae062393b21313d97c9b9875a88a76608b98f826 \ No newline at end of file
diff --git a/db/schema_migrations/20201209163958 b/db/schema_migrations/20201209163958
deleted file mode 100644
index 081f12e64ea..00000000000
--- a/db/schema_migrations/20201209163958
+++ /dev/null
@@ -1 +0,0 @@
-4bdd5eba48a76d8feab948857ec32ef7fe25e04e8633ee7d94fd059e73703472 \ No newline at end of file
diff --git a/db/schema_migrations/20201209193551 b/db/schema_migrations/20201209193551
deleted file mode 100644
index 2eb96840500..00000000000
--- a/db/schema_migrations/20201209193551
+++ /dev/null
@@ -1 +0,0 @@
-2278b1e4e19b5306e4b616eb87b622427ef2dcf73dae761739cb3106d5e64718 \ No newline at end of file
diff --git a/db/schema_migrations/20201210101250 b/db/schema_migrations/20201210101250
deleted file mode 100644
index 4657c9f264e..00000000000
--- a/db/schema_migrations/20201210101250
+++ /dev/null
@@ -1 +0,0 @@
-734ef1c319549df72bbbfe3acf93ca05f7a6c5547a1efdcaba780195181f5f9a \ No newline at end of file
diff --git a/db/schema_migrations/20201210175044 b/db/schema_migrations/20201210175044
deleted file mode 100644
index 63da0b55aed..00000000000
--- a/db/schema_migrations/20201210175044
+++ /dev/null
@@ -1 +0,0 @@
-32f0889266a05c12f1bba6d3d8646c6cd5c27ffcc01e4cc0cb1721c495e17237 \ No newline at end of file
diff --git a/db/schema_migrations/20201211042306 b/db/schema_migrations/20201211042306
deleted file mode 100644
index 07d4bc66b63..00000000000
--- a/db/schema_migrations/20201211042306
+++ /dev/null
@@ -1 +0,0 @@
-a4d82ca9610a1426bb026c43a00791bcdae38d49ed3ca59285d5a752124a7f20 \ No newline at end of file
diff --git a/db/schema_migrations/20210923192648 b/db/schema_migrations/20210923192648
new file mode 100644
index 00000000000..5514ec65903
--- /dev/null
+++ b/db/schema_migrations/20210923192648
@@ -0,0 +1 @@
+d9cb520f198893019b24c970ba409471e3d98581eb62f746320fc6e81a16af08 \ No newline at end of file
diff --git a/db/schema_migrations/20210923192649 b/db/schema_migrations/20210923192649
new file mode 100644
index 00000000000..e91955f09fe
--- /dev/null
+++ b/db/schema_migrations/20210923192649
@@ -0,0 +1 @@
+12fb550e936ede5a8e83ab06f2fc535201e7a276295a2103564412ded32958f8 \ No newline at end of file
diff --git a/db/schema_migrations/20210930211936 b/db/schema_migrations/20210930211936
new file mode 100644
index 00000000000..4538ddf180d
--- /dev/null
+++ b/db/schema_migrations/20210930211936
@@ -0,0 +1 @@
+3aaf2a4fa834331768e2acc10f67b8d456e70aca9784787e40b55dade7b6f64c \ No newline at end of file
diff --git a/db/schema_migrations/20211004120135 b/db/schema_migrations/20211004120135
new file mode 100644
index 00000000000..e03dc56e002
--- /dev/null
+++ b/db/schema_migrations/20211004120135
@@ -0,0 +1 @@
+9cefd32c003a68752f257973a983f77215b02011b7ca792de06c0e92c2462745 \ No newline at end of file
diff --git a/db/schema_migrations/20211004122540 b/db/schema_migrations/20211004122540
new file mode 100644
index 00000000000..1c7fc785b29
--- /dev/null
+++ b/db/schema_migrations/20211004122540
@@ -0,0 +1 @@
+72358f01061f5296e21647d5da9bbb6a33e94055c9c9aded6088cfb9126564b2 \ No newline at end of file
diff --git a/db/schema_migrations/20211005112404 b/db/schema_migrations/20211005112404
new file mode 100644
index 00000000000..80ce0534de8
--- /dev/null
+++ b/db/schema_migrations/20211005112404
@@ -0,0 +1 @@
+f4fe6c4a2860dd35f767d98d5025326142cab7fc9c12b5efb1541e2604791691 \ No newline at end of file
diff --git a/db/schema_migrations/20211005112645 b/db/schema_migrations/20211005112645
new file mode 100644
index 00000000000..e17b00586e5
--- /dev/null
+++ b/db/schema_migrations/20211005112645
@@ -0,0 +1 @@
+59e5de7766dc55e820ec714fbb61b5db61a73959f1e877e66caf668f93d0d633 \ No newline at end of file
diff --git a/db/schema_migrations/20211005194425 b/db/schema_migrations/20211005194425
new file mode 100644
index 00000000000..cd3710a6492
--- /dev/null
+++ b/db/schema_migrations/20211005194425
@@ -0,0 +1 @@
+6647e94d315c76629f9726e26bafd124fb2fed361568d65315e7c7557f8d9ecf \ No newline at end of file
diff --git a/db/schema_migrations/20211008193137 b/db/schema_migrations/20211008193137
new file mode 100644
index 00000000000..57d2f8cfbc8
--- /dev/null
+++ b/db/schema_migrations/20211008193137
@@ -0,0 +1 @@
+97efc3bb2039b66dac98135d93baefc780a62571bd80aa39d7458f37ce92905b \ No newline at end of file
diff --git a/db/schema_migrations/20211011004242 b/db/schema_migrations/20211011004242
new file mode 100644
index 00000000000..f25581cae75
--- /dev/null
+++ b/db/schema_migrations/20211011004242
@@ -0,0 +1 @@
+88bb0ca64281134fd97be474a1bb2be3ee60e59f10b9e144776a3282bba5a4c5 \ No newline at end of file
diff --git a/db/schema_migrations/20211011104843 b/db/schema_migrations/20211011104843
new file mode 100644
index 00000000000..78789b94ece
--- /dev/null
+++ b/db/schema_migrations/20211011104843
@@ -0,0 +1 @@
+e2812344b16cd51c544235bae8a365713ab7e34652c2c05511a7fe9d84c05fb1 \ No newline at end of file
diff --git a/db/schema_migrations/20211012015903 b/db/schema_migrations/20211012015903
new file mode 100644
index 00000000000..bfa36780370
--- /dev/null
+++ b/db/schema_migrations/20211012015903
@@ -0,0 +1 @@
+4c3a55f7891dab4ee1ae019d97cf9d40e7bba81d87a544d6aa23a7f57e6d0f70 \ No newline at end of file
diff --git a/db/schema_migrations/20211012051221 b/db/schema_migrations/20211012051221
new file mode 100644
index 00000000000..0dc5e9331e1
--- /dev/null
+++ b/db/schema_migrations/20211012051221
@@ -0,0 +1 @@
+52b2a6d78fa649078167e842061ab7c04e3c41c0fc4a092a0a6123dad202fb0e \ No newline at end of file
diff --git a/db/schema_migrations/20211012134316 b/db/schema_migrations/20211012134316
new file mode 100644
index 00000000000..72e01841ddf
--- /dev/null
+++ b/db/schema_migrations/20211012134316
@@ -0,0 +1 @@
+0f2578f0266154ad2790cc808233c71566b3a3ea87c40909feba9ccc5872927c \ No newline at end of file
diff --git a/db/schema_migrations/20211012143815 b/db/schema_migrations/20211012143815
new file mode 100644
index 00000000000..6e6a5493e99
--- /dev/null
+++ b/db/schema_migrations/20211012143815
@@ -0,0 +1 @@
+2685a534728ab1a50acb49a7a5ac7d9285fdc36ec3610b93a4219e6687c22b06 \ No newline at end of file
diff --git a/db/schema_migrations/20211013014228 b/db/schema_migrations/20211013014228
new file mode 100644
index 00000000000..5a833b7ee14
--- /dev/null
+++ b/db/schema_migrations/20211013014228
@@ -0,0 +1 @@
+5316cfddc074ae5a320ba763dd9481b46ba47d30eefa28d6bb5caa9368027598 \ No newline at end of file
diff --git a/db/schema_migrations/20211013080714 b/db/schema_migrations/20211013080714
new file mode 100644
index 00000000000..3579bdf3c78
--- /dev/null
+++ b/db/schema_migrations/20211013080714
@@ -0,0 +1 @@
+5c5adaf0f6f053c7e737051fbccf61d1fc36e20360a82d5fca142883d3e3bfdd \ No newline at end of file
diff --git a/db/schema_migrations/20211013080715 b/db/schema_migrations/20211013080715
new file mode 100644
index 00000000000..ff2d473c946
--- /dev/null
+++ b/db/schema_migrations/20211013080715
@@ -0,0 +1 @@
+06d6458f7b85b3e729c3c8a8ae29c29f7c5504ea330ae3a3bcf1e0074ed66cf6 \ No newline at end of file
diff --git a/db/schema_migrations/20211013080716 b/db/schema_migrations/20211013080716
new file mode 100644
index 00000000000..d2131eb811a
--- /dev/null
+++ b/db/schema_migrations/20211013080716
@@ -0,0 +1 @@
+a5928cef69626ad5e972e8cb7a570ca83201cdfe7ec4f2401f2aa14c34b9cfb8 \ No newline at end of file
diff --git a/db/schema_migrations/20211013125341 b/db/schema_migrations/20211013125341
new file mode 100644
index 00000000000..6177dfa56bc
--- /dev/null
+++ b/db/schema_migrations/20211013125341
@@ -0,0 +1 @@
+933c37a1a44869588b6586d34dec6bc8d731c81b6e5889ce588d535c011b9340 \ No newline at end of file
diff --git a/db/schema_migrations/20211013192749 b/db/schema_migrations/20211013192749
new file mode 100644
index 00000000000..54f05dc3fd6
--- /dev/null
+++ b/db/schema_migrations/20211013192749
@@ -0,0 +1 @@
+eeda27c42a80d23851bb58b00cee79feeffbe9ae1fef76b3034f92c8610a8aaf \ No newline at end of file
diff --git a/db/schema_migrations/20211015021114 b/db/schema_migrations/20211015021114
new file mode 100644
index 00000000000..1acbe9eded3
--- /dev/null
+++ b/db/schema_migrations/20211015021114
@@ -0,0 +1 @@
+687fa7d06a8d74b561d2b392e706fb209dbb1c0c8a483ad066820d29f7df059b \ No newline at end of file
diff --git a/db/schema_migrations/20211015024135 b/db/schema_migrations/20211015024135
new file mode 100644
index 00000000000..9f40fe5b71c
--- /dev/null
+++ b/db/schema_migrations/20211015024135
@@ -0,0 +1 @@
+d3cafd6eb712ba3f11aa0e2bddc15bf312230e52d53ba8b7ae6c8d3cfd4aabcc \ No newline at end of file
diff --git a/db/schema_migrations/20211018101034 b/db/schema_migrations/20211018101034
new file mode 100644
index 00000000000..57b1cc1e3c2
--- /dev/null
+++ b/db/schema_migrations/20211018101034
@@ -0,0 +1 @@
+1cadc3a932d5b62cfeafcd4090eddc37b44997dbbd0b34da1c7c87a5774bb683 \ No newline at end of file
diff --git a/db/schema_migrations/20211018101552 b/db/schema_migrations/20211018101552
new file mode 100644
index 00000000000..3814122d9a3
--- /dev/null
+++ b/db/schema_migrations/20211018101552
@@ -0,0 +1 @@
+9a62f0ec43ab295619d82494090c38539cb16408c8971bdde86bb8d02546f558 \ No newline at end of file
diff --git a/db/schema_migrations/20211018101852 b/db/schema_migrations/20211018101852
new file mode 100644
index 00000000000..5288e753211
--- /dev/null
+++ b/db/schema_migrations/20211018101852
@@ -0,0 +1 @@
+30e9632877d3ad33528be0f56962c0ab57f5eee3889183d9638cbaea903a3d82 \ No newline at end of file
diff --git a/db/schema_migrations/20211018102252 b/db/schema_migrations/20211018102252
new file mode 100644
index 00000000000..7d8b2c19da1
--- /dev/null
+++ b/db/schema_migrations/20211018102252
@@ -0,0 +1 @@
+14bb815cbdad2db56dafb7eaaff893de96116a1a9e8d6c5ed95f4bef9b9717fc \ No newline at end of file
diff --git a/db/schema_migrations/20211018123316 b/db/schema_migrations/20211018123316
new file mode 100644
index 00000000000..37bf0b261f1
--- /dev/null
+++ b/db/schema_migrations/20211018123316
@@ -0,0 +1 @@
+fcee17f25ad3a8b6fb56c23b72978f4a6952200264d285b9e3df4b5e7733e8f6 \ No newline at end of file
diff --git a/db/schema_migrations/20211018152654 b/db/schema_migrations/20211018152654
new file mode 100644
index 00000000000..86e9980ad10
--- /dev/null
+++ b/db/schema_migrations/20211018152654
@@ -0,0 +1 @@
+fd7b6eb9439c00334f613e3e4977e44054930c1343e5df32bbe82c64acd6ca7b \ No newline at end of file
diff --git a/db/schema_migrations/20211018161447 b/db/schema_migrations/20211018161447
new file mode 100644
index 00000000000..e10f5b06d9a
--- /dev/null
+++ b/db/schema_migrations/20211018161447
@@ -0,0 +1 @@
+168b383c4a85de35ade8a26e442ca49a40342ba05fb23fab4f0444814d976f65 \ No newline at end of file
diff --git a/db/schema_migrations/20211019153615 b/db/schema_migrations/20211019153615
new file mode 100644
index 00000000000..7c1c7d7775f
--- /dev/null
+++ b/db/schema_migrations/20211019153615
@@ -0,0 +1 @@
+713efc9673bc6cda8eff4e433c3c85f0cc4b8b8ca7b5cc4308e57a6d0b0040a0 \ No newline at end of file
diff --git a/db/schema_migrations/20211020030948 b/db/schema_migrations/20211020030948
new file mode 100644
index 00000000000..1964b852444
--- /dev/null
+++ b/db/schema_migrations/20211020030948
@@ -0,0 +1 @@
+97e8b2ce324594581ec0af65840a0dde8271b1b2712e22059f5c26b30d7d5cac \ No newline at end of file
diff --git a/db/schema_migrations/20211020095357 b/db/schema_migrations/20211020095357
new file mode 100644
index 00000000000..7fcb8fa6866
--- /dev/null
+++ b/db/schema_migrations/20211020095357
@@ -0,0 +1 @@
+a62ac8920223469c6e4c5a7f67ce9eec972189c98a8c542b377afe4ab28ee25a \ No newline at end of file
diff --git a/db/schema_migrations/20211021125908 b/db/schema_migrations/20211021125908
new file mode 100644
index 00000000000..9cb92e1eabe
--- /dev/null
+++ b/db/schema_migrations/20211021125908
@@ -0,0 +1 @@
+d6fbe3efc3e45b750d82e277e30b7b0048b960d9f9f5b4f7c6a7a1ed869e76b5 \ No newline at end of file
diff --git a/db/schema_migrations/20211021131217 b/db/schema_migrations/20211021131217
new file mode 100644
index 00000000000..70b45512900
--- /dev/null
+++ b/db/schema_migrations/20211021131217
@@ -0,0 +1 @@
+87834e00821eb1ed8489c1d772dc3ac743bcf84669e78c04c7988f6f761970b8 \ No newline at end of file
diff --git a/db/schema_migrations/20211021134458 b/db/schema_migrations/20211021134458
new file mode 100644
index 00000000000..dc168e12229
--- /dev/null
+++ b/db/schema_migrations/20211021134458
@@ -0,0 +1 @@
+1baa8db0d42a8d99e48b61930f5c42d1af5f86555488419b6551e1dbf417d3ad \ No newline at end of file
diff --git a/db/schema_migrations/20211021140426 b/db/schema_migrations/20211021140426
new file mode 100644
index 00000000000..c32db84a138
--- /dev/null
+++ b/db/schema_migrations/20211021140426
@@ -0,0 +1 @@
+bc7974917509bfbda47375299009295bc5a55970b92443dd5d7134075b161279 \ No newline at end of file
diff --git a/db/schema_migrations/20211021141930 b/db/schema_migrations/20211021141930
new file mode 100644
index 00000000000..294e1c80aea
--- /dev/null
+++ b/db/schema_migrations/20211021141930
@@ -0,0 +1 @@
+483e4cbe2a0be2afbda511f2298e3715abaca29afafeeae26449fc862f49a08f \ No newline at end of file
diff --git a/db/schema_migrations/20211022112202 b/db/schema_migrations/20211022112202
new file mode 100644
index 00000000000..6ef610f80bc
--- /dev/null
+++ b/db/schema_migrations/20211022112202
@@ -0,0 +1 @@
+b5fbbfe186b3eeeb88bfd901ac426fc52355b71b67c5f5b42373008c19c35bee \ No newline at end of file
diff --git a/db/schema_migrations/20211022113000 b/db/schema_migrations/20211022113000
new file mode 100644
index 00000000000..85044f34206
--- /dev/null
+++ b/db/schema_migrations/20211022113000
@@ -0,0 +1 @@
+ded528d0485951403f1c5af804f40b1c0a7c71a0dc67f24fadbc357a45fb1a19 \ No newline at end of file
diff --git a/db/schema_migrations/20211022160154 b/db/schema_migrations/20211022160154
new file mode 100644
index 00000000000..2a76379bc66
--- /dev/null
+++ b/db/schema_migrations/20211022160154
@@ -0,0 +1 @@
+c474870a626c909da772a1c9f459f369d50658ce8f585a35e7cc3c7ef64af657 \ No newline at end of file
diff --git a/db/schema_migrations/20211025103744 b/db/schema_migrations/20211025103744
new file mode 100644
index 00000000000..29c49c81606
--- /dev/null
+++ b/db/schema_migrations/20211025103744
@@ -0,0 +1 @@
+56f86f2a20509f2052d0eab918a6d2bbb679d785cf5349916ba695aa92f0609f \ No newline at end of file
diff --git a/db/schema_migrations/20211025103758 b/db/schema_migrations/20211025103758
new file mode 100644
index 00000000000..902973a42d9
--- /dev/null
+++ b/db/schema_migrations/20211025103758
@@ -0,0 +1 @@
+1722382c5141157497f48b209c0fa60c5959fa16c53d09fb6e8e6b2cb6e6ab9b \ No newline at end of file
diff --git a/db/schema_migrations/20211026143238 b/db/schema_migrations/20211026143238
new file mode 100644
index 00000000000..9f0e7f76cd9
--- /dev/null
+++ b/db/schema_migrations/20211026143238
@@ -0,0 +1 @@
+6b1377dd7e9b78a35c2f5635d2d11f5fe254aa772576510b41fcf1e03ad56c87 \ No newline at end of file
diff --git a/db/schema_migrations/20211027064021 b/db/schema_migrations/20211027064021
new file mode 100644
index 00000000000..3bd57b30583
--- /dev/null
+++ b/db/schema_migrations/20211027064021
@@ -0,0 +1 @@
+f1b218eaddb9bcc5e4d854a6b43fc5e122b38dc989225327a1c4a899f41e5ac6 \ No newline at end of file
diff --git a/db/schema_migrations/20211027064156 b/db/schema_migrations/20211027064156
new file mode 100644
index 00000000000..880b7a00694
--- /dev/null
+++ b/db/schema_migrations/20211027064156
@@ -0,0 +1 @@
+3d7b72684102836d7a7efcab7590b3d14bc63eb3e1bfbc7a95fb5eb5c6a906af \ No newline at end of file
diff --git a/db/schema_migrations/20211027112901 b/db/schema_migrations/20211027112901
new file mode 100644
index 00000000000..0e4cb808f00
--- /dev/null
+++ b/db/schema_migrations/20211027112901
@@ -0,0 +1 @@
+83c1d699e5de98007ef815b5f9dfbc9a644c6289bf86832af1d5b8a6d3d83659 \ No newline at end of file
diff --git a/db/schema_migrations/20211027203950 b/db/schema_migrations/20211027203950
new file mode 100644
index 00000000000..4e4265a34c9
--- /dev/null
+++ b/db/schema_migrations/20211027203950
@@ -0,0 +1 @@
+38643fbd719e7d65e5e79eeb279a5732cee5c28774a300859a2bace13d882ee2 \ No newline at end of file
diff --git a/db/schema_migrations/20211027204011 b/db/schema_migrations/20211027204011
new file mode 100644
index 00000000000..7c1e07a87c0
--- /dev/null
+++ b/db/schema_migrations/20211027204011
@@ -0,0 +1 @@
+8542de6f3bf260b4e7596ed497ff8ed4204c81519d8f19e64ac86cd5532e7a61 \ No newline at end of file
diff --git a/db/schema_migrations/20211028085926 b/db/schema_migrations/20211028085926
new file mode 100644
index 00000000000..c1e8d928fa0
--- /dev/null
+++ b/db/schema_migrations/20211028085926
@@ -0,0 +1 @@
+ed6939c1e89f78290c312bf005cb33bd1a5ee778e8d9be3ae2eb04cc25416b92 \ No newline at end of file
diff --git a/db/schema_migrations/20211028100303 b/db/schema_migrations/20211028100303
new file mode 100644
index 00000000000..472b2ce78ef
--- /dev/null
+++ b/db/schema_migrations/20211028100303
@@ -0,0 +1 @@
+bb28267d020cbc26614e4635c803af0168ab5606f3aadc40e1c0e0bc6d988254 \ No newline at end of file
diff --git a/db/schema_migrations/20211028100843 b/db/schema_migrations/20211028100843
new file mode 100644
index 00000000000..4be06f29039
--- /dev/null
+++ b/db/schema_migrations/20211028100843
@@ -0,0 +1 @@
+27578f62b5cde4fdbfe79eb717404a5cef62b8c17170525428dbf81e6b394ce9 \ No newline at end of file
diff --git a/db/schema_migrations/20211028123412 b/db/schema_migrations/20211028123412
new file mode 100644
index 00000000000..d32c7c95d8f
--- /dev/null
+++ b/db/schema_migrations/20211028123412
@@ -0,0 +1 @@
+d7655fb2a01e389f59990b395ed7ef683b21a3371b7e68d3eb29def85eea1888 \ No newline at end of file
diff --git a/db/schema_migrations/20211028132247 b/db/schema_migrations/20211028132247
new file mode 100644
index 00000000000..ab8fa3b55eb
--- /dev/null
+++ b/db/schema_migrations/20211028132247
@@ -0,0 +1 @@
+50a5c8af2cde1ae79d627f70d3b266488f76f76b481aefca8516db5360cfa843 \ No newline at end of file
diff --git a/db/schema_migrations/20211028155449 b/db/schema_migrations/20211028155449
new file mode 100644
index 00000000000..00b1c4e14dd
--- /dev/null
+++ b/db/schema_migrations/20211028155449
@@ -0,0 +1 @@
+385c540b1f80c31a5ba009ae3507d2b855a737389bcb75c07a8872f26f8a9b44 \ No newline at end of file
diff --git a/db/schema_migrations/20211028212259 b/db/schema_migrations/20211028212259
new file mode 100644
index 00000000000..777c5546592
--- /dev/null
+++ b/db/schema_migrations/20211028212259
@@ -0,0 +1 @@
+56af9791c8625d99e9a53690135086afccdbe8f58a5c236d6805b0883fb971b0 \ No newline at end of file
diff --git a/db/schema_migrations/20211029102822 b/db/schema_migrations/20211029102822
new file mode 100644
index 00000000000..72198f302b3
--- /dev/null
+++ b/db/schema_migrations/20211029102822
@@ -0,0 +1 @@
+e1f9d87287048010e9816fd5b4a9a2d30b64d2ad150226852f6679b950031914 \ No newline at end of file
diff --git a/db/schema_migrations/20211031152417 b/db/schema_migrations/20211031152417
new file mode 100644
index 00000000000..429c7dc0d8c
--- /dev/null
+++ b/db/schema_migrations/20211031152417
@@ -0,0 +1 @@
+f46a0dd662a80d38a4e8d3e6c4db05e61563a959b75d30a4c3724ae6afc2647f \ No newline at end of file
diff --git a/db/schema_migrations/20211031154919 b/db/schema_migrations/20211031154919
new file mode 100644
index 00000000000..29cf7cc1580
--- /dev/null
+++ b/db/schema_migrations/20211031154919
@@ -0,0 +1 @@
+08399bfbf62533c00dfe3ca3434f6be292ec768f053d3b1fde41d2d68de32fe7 \ No newline at end of file
diff --git a/db/schema_migrations/20211101132310 b/db/schema_migrations/20211101132310
new file mode 100644
index 00000000000..08a95d2747e
--- /dev/null
+++ b/db/schema_migrations/20211101132310
@@ -0,0 +1 @@
+3e02605ce307d0ce37c3830e6909e7cfe5632408a757adf59209a70da92c0bc6 \ No newline at end of file
diff --git a/db/schema_migrations/20211102103127 b/db/schema_migrations/20211102103127
new file mode 100644
index 00000000000..2ce33ad085a
--- /dev/null
+++ b/db/schema_migrations/20211102103127
@@ -0,0 +1 @@
+450028c90cb92f5ce3f8239eb56364b83ed025839aaf305b7ceb4fda077681b1 \ No newline at end of file
diff --git a/db/schema_migrations/20211102114802 b/db/schema_migrations/20211102114802
new file mode 100644
index 00000000000..35d3a25f3cb
--- /dev/null
+++ b/db/schema_migrations/20211102114802
@@ -0,0 +1 @@
+a3f9fcac354cccfdfc42b8f5baab651cb65ca60e4474ce937ab25b552bfe483c \ No newline at end of file
diff --git a/db/schema_migrations/20211103062728 b/db/schema_migrations/20211103062728
new file mode 100644
index 00000000000..45bb2fcda65
--- /dev/null
+++ b/db/schema_migrations/20211103062728
@@ -0,0 +1 @@
+a22322122144f28306b3b38dbe50b3465ad623c389f8bfe6fa97a0f71b1c7c21 \ No newline at end of file
diff --git a/db/schema_migrations/20211103162025 b/db/schema_migrations/20211103162025
new file mode 100644
index 00000000000..e6cb01358d4
--- /dev/null
+++ b/db/schema_migrations/20211103162025
@@ -0,0 +1 @@
+2ed9198926eb0579fccd4a8b1866f10ba4f42683d676e0664db3fadefe0bed39 \ No newline at end of file
diff --git a/db/schema_migrations/20211104012209 b/db/schema_migrations/20211104012209
new file mode 100644
index 00000000000..8a81fbdf9b8
--- /dev/null
+++ b/db/schema_migrations/20211104012209
@@ -0,0 +1 @@
+e7cf08543f911b5f95f08d4aa6063e05b026e463e71a65b6b8200191de1b02a1 \ No newline at end of file
diff --git a/db/schema_migrations/20211104044453 b/db/schema_migrations/20211104044453
new file mode 100644
index 00000000000..7d39c0e48e8
--- /dev/null
+++ b/db/schema_migrations/20211104044453
@@ -0,0 +1 @@
+fc5a60c27ca89b122d798abe8f55a0951fece712c885555df0d2f37b565d6f94 \ No newline at end of file
diff --git a/db/schema_migrations/20211105010101 b/db/schema_migrations/20211105010101
new file mode 100644
index 00000000000..a7f79387e9f
--- /dev/null
+++ b/db/schema_migrations/20211105010101
@@ -0,0 +1 @@
+26c534cdae8630e3f28ad2b61a1049aaab5c5b7a1b761f0961831b621e148ed3 \ No newline at end of file
diff --git a/db/schema_migrations/20211105125756 b/db/schema_migrations/20211105125756
new file mode 100644
index 00000000000..842187d9ae2
--- /dev/null
+++ b/db/schema_migrations/20211105125756
@@ -0,0 +1 @@
+13cf3d164d541df48b6d14d7cc1953113476ba8ea5975d7d0c5f84098e2e0e61 \ No newline at end of file
diff --git a/db/schema_migrations/20211105125813 b/db/schema_migrations/20211105125813
new file mode 100644
index 00000000000..449c3d95d6a
--- /dev/null
+++ b/db/schema_migrations/20211105125813
@@ -0,0 +1 @@
+a48f62bed7e4c4a0e69acd3b340065317aff71602e696970276a4e443f1dcabf \ No newline at end of file
diff --git a/db/schema_migrations/20211105135157 b/db/schema_migrations/20211105135157
new file mode 100644
index 00000000000..694509bfafd
--- /dev/null
+++ b/db/schema_migrations/20211105135157
@@ -0,0 +1 @@
+20f10ae28d439de1d07357ab7e977dae88feaaedb16770820350a9bf8242817f \ No newline at end of file
diff --git a/db/schema_migrations/20211105160316 b/db/schema_migrations/20211105160316
new file mode 100644
index 00000000000..493dfb4afbd
--- /dev/null
+++ b/db/schema_migrations/20211105160316
@@ -0,0 +1 @@
+afb9552a4104b10b25d65a9fec478c5c28a31ec31402400554db4288033bacb6 \ No newline at end of file
diff --git a/db/schema_migrations/20211105161404 b/db/schema_migrations/20211105161404
new file mode 100644
index 00000000000..98b4bcdacfb
--- /dev/null
+++ b/db/schema_migrations/20211105161404
@@ -0,0 +1 @@
+911cc21de320d0d5716ce80ebca56433b793c2072cb62da783605c99bb9aada9 \ No newline at end of file
diff --git a/db/schema_migrations/20211108154510 b/db/schema_migrations/20211108154510
new file mode 100644
index 00000000000..c978d671d29
--- /dev/null
+++ b/db/schema_migrations/20211108154510
@@ -0,0 +1 @@
+024c123bf06b796341a22e54f4c34b967d84aeb9b2006acf5cfef96a6161c13d \ No newline at end of file
diff --git a/db/schema_migrations/20211108154841 b/db/schema_migrations/20211108154841
new file mode 100644
index 00000000000..c602a1b6c24
--- /dev/null
+++ b/db/schema_migrations/20211108154841
@@ -0,0 +1 @@
+03842b87c4118f0e2aba1597ff08a6830b1dd5442a455e4bc9774b93b36a09b5 \ No newline at end of file
diff --git a/db/schema_migrations/20211108203248 b/db/schema_migrations/20211108203248
new file mode 100644
index 00000000000..4f8c570b627
--- /dev/null
+++ b/db/schema_migrations/20211108203248
@@ -0,0 +1 @@
+a2556a3d8b21e59caa6cbf7f83d621fef391904d0c13c77c0e5da713a580b4c9 \ No newline at end of file
diff --git a/db/schema_migrations/20211108211434 b/db/schema_migrations/20211108211434
new file mode 100644
index 00000000000..17a90668900
--- /dev/null
+++ b/db/schema_migrations/20211108211434
@@ -0,0 +1 @@
+06cbecc52e62a48664ae486181047d8ca4d71a7991ba36bdca4bfa44257627f3 \ No newline at end of file
diff --git a/db/schema_migrations/20211109100050 b/db/schema_migrations/20211109100050
new file mode 100644
index 00000000000..94f9612277f
--- /dev/null
+++ b/db/schema_migrations/20211109100050
@@ -0,0 +1 @@
+86aa6ad1759a00c2cc5cb6dc2e381aead2910a24f0e37933a5e72af56d08101a \ No newline at end of file
diff --git a/db/schema_migrations/20211109101010 b/db/schema_migrations/20211109101010
new file mode 100644
index 00000000000..ea24f5e7e37
--- /dev/null
+++ b/db/schema_migrations/20211109101010
@@ -0,0 +1 @@
+30eb98b8fdb24bc5de357b0ec14a6b92d520db025c82bd7b9448f71542c7d7e3 \ No newline at end of file
diff --git a/db/schema_migrations/20211109112454 b/db/schema_migrations/20211109112454
new file mode 100644
index 00000000000..6fdb1e344b9
--- /dev/null
+++ b/db/schema_migrations/20211109112454
@@ -0,0 +1 @@
+1bc48cdae55eea5a5963edd3a138d7d6859afa6caafe0b793c553fdfabe9f488 \ No newline at end of file
diff --git a/db/schema_migrations/20211110010101 b/db/schema_migrations/20211110010101
new file mode 100644
index 00000000000..bedcfdb2b3b
--- /dev/null
+++ b/db/schema_migrations/20211110010101
@@ -0,0 +1 @@
+63495b9f9ca2d4fa121b75eea36f2923942a6e11f27bef2c51414e00ccd48973 \ No newline at end of file
diff --git a/db/schema_migrations/20211110100050 b/db/schema_migrations/20211110100050
new file mode 100644
index 00000000000..eed0afbac1c
--- /dev/null
+++ b/db/schema_migrations/20211110100050
@@ -0,0 +1 @@
+54b83ba1f8e8aa8a23f230664bcd6cc068a2df2d669e395713f0805d0f054f9c \ No newline at end of file
diff --git a/db/schema_migrations/20211112113300 b/db/schema_migrations/20211112113300
new file mode 100644
index 00000000000..8074c437751
--- /dev/null
+++ b/db/schema_migrations/20211112113300
@@ -0,0 +1 @@
+be11c0b1c7b9c99c28d44c164742815da57bfc4a32afd54df9135e3ce6edeff9 \ No newline at end of file
diff --git a/db/schema_migrations/20211112155416 b/db/schema_migrations/20211112155416
new file mode 100644
index 00000000000..91037c578a7
--- /dev/null
+++ b/db/schema_migrations/20211112155416
@@ -0,0 +1 @@
+0c5627518093f6261679940402cbd756a91bf4617a37eecdbbc82dc57856dcec \ No newline at end of file
diff --git a/db/schema_migrations/20211115151704 b/db/schema_migrations/20211115151704
new file mode 100644
index 00000000000..03093ade126
--- /dev/null
+++ b/db/schema_migrations/20211115151704
@@ -0,0 +1 @@
+3db18116febc760bcfeab597e0508d5b2835d0135068d79073770d343aa4b09c \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index c73ade92f80..5373aa7a31e 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -46,6 +46,15 @@ RETURN NULL;
END
$$;
+CREATE FUNCTION next_traversal_ids_sibling(traversal_ids integer[]) RETURNS integer[]
+ LANGUAGE plpgsql IMMUTABLE STRICT
+ AS $$
+BEGIN
+ return traversal_ids[1:array_length(traversal_ids, 1)-1] ||
+ ARRAY[traversal_ids[array_length(traversal_ids, 1)]+1];
+END;
+$$;
+
CREATE FUNCTION set_has_external_issue_tracker() RETURNS trigger
LANGUAGE plpgsql
AS $$
@@ -77,15 +86,6 @@ RETURN NULL;
END
$$;
-CREATE FUNCTION trigger_91dc388a5fe6() RETURNS trigger
- LANGUAGE plpgsql
- AS $$
-BEGIN
- NEW."build_id_convert_to_bigint" := NEW."build_id";
- RETURN NEW;
-END;
-$$;
-
CREATE TABLE audit_events (
id bigint NOT NULL,
author_id integer NOT NULL,
@@ -126,6 +126,19 @@ CREATE TABLE incident_management_pending_issue_escalations (
)
PARTITION BY RANGE (process_at);
+CREATE TABLE verification_codes (
+ created_at timestamp with time zone DEFAULT now() NOT NULL,
+ visitor_id_code text NOT NULL,
+ code text NOT NULL,
+ phone text NOT NULL,
+ CONSTRAINT check_9b84e6aaff CHECK ((char_length(code) <= 8)),
+ CONSTRAINT check_ccc542256b CHECK ((char_length(visitor_id_code) <= 64)),
+ CONSTRAINT check_f5684c195b CHECK ((char_length(phone) <= 32))
+)
+PARTITION BY RANGE (created_at);
+
+COMMENT ON TABLE verification_codes IS 'JiHu-specific table';
+
CREATE TABLE web_hook_logs (
id bigint NOT NULL,
web_hook_id integer NOT NULL,
@@ -151,7 +164,8 @@ CREATE TABLE analytics_cycle_analytics_issue_stage_events (
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
)
PARTITION BY HASH (stage_event_hash_id);
@@ -163,7 +177,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_00 FOR VALUES WITH (modulus 32, remainder 0);
@@ -175,7 +190,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_01 FOR VALUES WITH (modulus 32, remainder 1);
@@ -187,7 +203,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_02 FOR VALUES WITH (modulus 32, remainder 2);
@@ -199,7 +216,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_03 FOR VALUES WITH (modulus 32, remainder 3);
@@ -211,7 +229,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_04 FOR VALUES WITH (modulus 32, remainder 4);
@@ -223,7 +242,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_05 FOR VALUES WITH (modulus 32, remainder 5);
@@ -235,7 +255,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_06 FOR VALUES WITH (modulus 32, remainder 6);
@@ -247,7 +268,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_07 FOR VALUES WITH (modulus 32, remainder 7);
@@ -259,7 +281,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_08 FOR VALUES WITH (modulus 32, remainder 8);
@@ -271,7 +294,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_09 FOR VALUES WITH (modulus 32, remainder 9);
@@ -283,7 +307,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_10 FOR VALUES WITH (modulus 32, remainder 10);
@@ -295,7 +320,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_11 FOR VALUES WITH (modulus 32, remainder 11);
@@ -307,7 +333,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_12 FOR VALUES WITH (modulus 32, remainder 12);
@@ -319,7 +346,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_13 FOR VALUES WITH (modulus 32, remainder 13);
@@ -331,7 +359,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_14 FOR VALUES WITH (modulus 32, remainder 14);
@@ -343,7 +372,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_15 FOR VALUES WITH (modulus 32, remainder 15);
@@ -355,7 +385,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_16 FOR VALUES WITH (modulus 32, remainder 16);
@@ -367,7 +398,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_17 FOR VALUES WITH (modulus 32, remainder 17);
@@ -379,7 +411,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_18 FOR VALUES WITH (modulus 32, remainder 18);
@@ -391,7 +424,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_19 FOR VALUES WITH (modulus 32, remainder 19);
@@ -403,7 +437,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_20 FOR VALUES WITH (modulus 32, remainder 20);
@@ -415,7 +450,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_21 FOR VALUES WITH (modulus 32, remainder 21);
@@ -427,7 +463,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_22 FOR VALUES WITH (modulus 32, remainder 22);
@@ -439,7 +476,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_23 FOR VALUES WITH (modulus 32, remainder 23);
@@ -451,7 +489,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_24 FOR VALUES WITH (modulus 32, remainder 24);
@@ -463,7 +502,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_25 FOR VALUES WITH (modulus 32, remainder 25);
@@ -475,7 +515,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_26 FOR VALUES WITH (modulus 32, remainder 26);
@@ -487,7 +528,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_27 FOR VALUES WITH (modulus 32, remainder 27);
@@ -499,7 +541,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_28 FOR VALUES WITH (modulus 32, remainder 28);
@@ -511,7 +554,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_29 FOR VALUES WITH (modulus 32, remainder 29);
@@ -523,7 +567,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_30 FOR VALUES WITH (modulus 32, remainder 30);
@@ -535,7 +580,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_31 FOR VALUES WITH (modulus 32, remainder 31);
@@ -547,7 +593,8 @@ CREATE TABLE analytics_cycle_analytics_merge_request_stage_events (
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
)
PARTITION BY HASH (stage_event_hash_id);
@@ -559,7 +606,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_00 FOR VALUES WITH (modulus 32, remainder 0);
@@ -571,7 +619,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_01 FOR VALUES WITH (modulus 32, remainder 1);
@@ -583,7 +632,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_02 FOR VALUES WITH (modulus 32, remainder 2);
@@ -595,7 +645,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_03 FOR VALUES WITH (modulus 32, remainder 3);
@@ -607,7 +658,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_04 FOR VALUES WITH (modulus 32, remainder 4);
@@ -619,7 +671,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_05 FOR VALUES WITH (modulus 32, remainder 5);
@@ -631,7 +684,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_06 FOR VALUES WITH (modulus 32, remainder 6);
@@ -643,7 +697,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_07 FOR VALUES WITH (modulus 32, remainder 7);
@@ -655,7 +710,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_08 FOR VALUES WITH (modulus 32, remainder 8);
@@ -667,7 +723,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_09 FOR VALUES WITH (modulus 32, remainder 9);
@@ -679,7 +736,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_10 FOR VALUES WITH (modulus 32, remainder 10);
@@ -691,7 +749,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_11 FOR VALUES WITH (modulus 32, remainder 11);
@@ -703,7 +762,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_12 FOR VALUES WITH (modulus 32, remainder 12);
@@ -715,7 +775,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_13 FOR VALUES WITH (modulus 32, remainder 13);
@@ -727,7 +788,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_14 FOR VALUES WITH (modulus 32, remainder 14);
@@ -739,7 +801,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_15 FOR VALUES WITH (modulus 32, remainder 15);
@@ -751,7 +814,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_16 FOR VALUES WITH (modulus 32, remainder 16);
@@ -763,7 +827,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_17 FOR VALUES WITH (modulus 32, remainder 17);
@@ -775,7 +840,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_18 FOR VALUES WITH (modulus 32, remainder 18);
@@ -787,7 +853,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_19 FOR VALUES WITH (modulus 32, remainder 19);
@@ -799,7 +866,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_20 FOR VALUES WITH (modulus 32, remainder 20);
@@ -811,7 +879,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_21 FOR VALUES WITH (modulus 32, remainder 21);
@@ -823,7 +892,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_22 FOR VALUES WITH (modulus 32, remainder 22);
@@ -835,7 +905,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_23 FOR VALUES WITH (modulus 32, remainder 23);
@@ -847,7 +918,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_24 FOR VALUES WITH (modulus 32, remainder 24);
@@ -859,7 +931,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_25 FOR VALUES WITH (modulus 32, remainder 25);
@@ -871,7 +944,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_26 FOR VALUES WITH (modulus 32, remainder 26);
@@ -883,7 +957,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_27 FOR VALUES WITH (modulus 32, remainder 27);
@@ -895,7 +970,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_28 FOR VALUES WITH (modulus 32, remainder 28);
@@ -907,7 +983,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_29 FOR VALUES WITH (modulus 32, remainder 29);
@@ -919,7 +996,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_30 FOR VALUES WITH (modulus 32, remainder 30);
@@ -931,7 +1009,8 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
milestone_id bigint,
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
- end_event_timestamp timestamp with time zone
+ end_event_timestamp timestamp with time zone,
+ state_id smallint DEFAULT 1 NOT NULL
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_31 FOR VALUES WITH (modulus 32, remainder 31);
@@ -942,6 +1021,7 @@ CREATE TABLE loose_foreign_keys_deleted_records (
status smallint DEFAULT 1 NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
fully_qualified_table_name text NOT NULL,
+ consume_after timestamp with time zone DEFAULT now(),
CONSTRAINT check_1a541f3235 CHECK ((char_length(fully_qualified_table_name) <= 150))
)
PARTITION BY LIST (partition);
@@ -962,6 +1042,7 @@ CREATE TABLE gitlab_partitions_static.loose_foreign_keys_deleted_records_1 (
status smallint DEFAULT 1 NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
fully_qualified_table_name text NOT NULL,
+ consume_after timestamp with time zone DEFAULT now(),
CONSTRAINT check_1a541f3235 CHECK ((char_length(fully_qualified_table_name) <= 150))
);
ALTER TABLE ONLY loose_foreign_keys_deleted_records ATTACH PARTITION gitlab_partitions_static.loose_foreign_keys_deleted_records_1 FOR VALUES IN ('1');
@@ -10295,7 +10376,7 @@ CREATE TABLE application_settings (
encrypted_cloud_license_auth_token_iv text,
secret_detection_revocation_token_types_url text,
disable_feed_token boolean DEFAULT false NOT NULL,
- personal_access_token_prefix text,
+ personal_access_token_prefix text DEFAULT 'glpat-'::text,
rate_limiting_response_text text,
invisible_captcha_enabled boolean DEFAULT false NOT NULL,
container_registry_cleanup_tags_service_max_list_size integer DEFAULT 200 NOT NULL,
@@ -10365,6 +10446,14 @@ CREATE TABLE application_settings (
throttle_authenticated_deprecated_api_period_in_seconds integer DEFAULT 3600 NOT NULL,
throttle_authenticated_deprecated_api_enabled boolean DEFAULT false NOT NULL,
dependency_proxy_ttl_group_policy_worker_capacity smallint DEFAULT 2 NOT NULL,
+ content_validation_endpoint_url text,
+ encrypted_content_validation_api_key bytea,
+ encrypted_content_validation_api_key_iv bytea,
+ content_validation_endpoint_enabled boolean DEFAULT false NOT NULL,
+ sentry_enabled boolean DEFAULT false NOT NULL,
+ sentry_dsn text,
+ sentry_clientside_dsn text,
+ sentry_environment text,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
CONSTRAINT app_settings_ext_pipeline_validation_service_url_text_limit CHECK ((char_length(external_pipeline_validation_service_url) <= 255)),
@@ -10373,8 +10462,12 @@ CREATE TABLE application_settings (
CONSTRAINT app_settings_yaml_max_size_positive CHECK ((max_yaml_size_bytes > 0)),
CONSTRAINT check_17d9558205 CHECK ((char_length((kroki_url)::text) <= 1024)),
CONSTRAINT check_2dba05b802 CHECK ((char_length(gitpod_url) <= 255)),
+ CONSTRAINT check_3def0f1829 CHECK ((char_length(sentry_clientside_dsn) <= 255)),
+ CONSTRAINT check_4f8b811780 CHECK ((char_length(sentry_dsn) <= 255)),
CONSTRAINT check_51700b31b5 CHECK ((char_length(default_branch_name) <= 255)),
CONSTRAINT check_57123c9593 CHECK ((char_length(help_page_documentation_base_url) <= 255)),
+ CONSTRAINT check_5a84c3ffdc CHECK ((char_length(content_validation_endpoint_url) <= 255)),
+ CONSTRAINT check_5bcba483c4 CHECK ((char_length(sentry_environment) <= 255)),
CONSTRAINT check_718b4458ae CHECK ((char_length(personal_access_token_prefix) <= 20)),
CONSTRAINT check_7227fad848 CHECK ((char_length(rate_limiting_response_text) <= 255)),
CONSTRAINT check_85a39b68ff CHECK ((char_length(encrypted_ci_jwt_signing_key_iv) <= 255)),
@@ -10388,6 +10481,14 @@ CREATE TABLE application_settings (
CONSTRAINT check_ef6176834f CHECK ((char_length(encrypted_cloud_license_auth_token_iv) <= 255))
);
+COMMENT ON COLUMN application_settings.content_validation_endpoint_url IS 'JiHu-specific column';
+
+COMMENT ON COLUMN application_settings.encrypted_content_validation_api_key IS 'JiHu-specific column';
+
+COMMENT ON COLUMN application_settings.encrypted_content_validation_api_key_iv IS 'JiHu-specific column';
+
+COMMENT ON COLUMN application_settings.content_validation_endpoint_enabled IS 'JiHu-specific column';
+
CREATE SEQUENCE application_settings_id_seq
START WITH 1
INCREMENT BY 1
@@ -10491,7 +10592,8 @@ CREATE TABLE approval_project_rules (
scanners text[],
vulnerabilities_allowed smallint DEFAULT 0 NOT NULL,
severity_levels text[] DEFAULT '{}'::text[] NOT NULL,
- report_type smallint
+ report_type smallint,
+ vulnerability_states text[] DEFAULT '{newly_detected}'::text[] NOT NULL
);
CREATE TABLE approval_project_rules_groups (
@@ -11419,7 +11521,8 @@ CREATE TABLE ci_builds_metadata (
secrets jsonb DEFAULT '{}'::jsonb NOT NULL,
build_id bigint NOT NULL,
id bigint NOT NULL,
- runner_features jsonb DEFAULT '{}'::jsonb NOT NULL
+ runner_features jsonb DEFAULT '{}'::jsonb NOT NULL,
+ runtime_runner_features jsonb DEFAULT '{}'::jsonb NOT NULL
);
CREATE SEQUENCE ci_builds_metadata_id_seq
@@ -12619,7 +12722,8 @@ CREATE TABLE clusters_integration_prometheus (
cluster_id bigint NOT NULL,
enabled boolean DEFAULT false NOT NULL,
encrypted_alert_manager_token text,
- encrypted_alert_manager_token_iv text
+ encrypted_alert_manager_token_iv text,
+ health_status smallint DEFAULT 0 NOT NULL
);
CREATE TABLE clusters_kubernetes_namespaces (
@@ -12721,6 +12825,29 @@ CREATE SEQUENCE container_repositories_id_seq
ALTER SEQUENCE container_repositories_id_seq OWNED BY container_repositories.id;
+CREATE TABLE content_blocked_states (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ commit_sha bytea NOT NULL,
+ blob_sha bytea NOT NULL,
+ path text NOT NULL,
+ container_identifier text NOT NULL,
+ CONSTRAINT check_023093d38f CHECK ((char_length(container_identifier) <= 255)),
+ CONSTRAINT check_1870100678 CHECK ((char_length(path) <= 2048))
+);
+
+COMMENT ON TABLE content_blocked_states IS 'JiHu-specific table';
+
+CREATE SEQUENCE content_blocked_states_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE content_blocked_states_id_seq OWNED BY content_blocked_states.id;
+
CREATE TABLE conversational_development_index_metrics (
id integer NOT NULL,
leader_issues double precision NOT NULL,
@@ -13101,33 +13228,6 @@ CREATE SEQUENCE dast_sites_id_seq
ALTER SEQUENCE dast_sites_id_seq OWNED BY dast_sites.id;
-CREATE TABLE dep_ci_build_trace_section_names (
- id integer NOT NULL,
- project_id integer NOT NULL,
- name character varying NOT NULL
-);
-
-CREATE SEQUENCE dep_ci_build_trace_section_names_id_seq
- AS integer
- START WITH 1
- INCREMENT BY 1
- NO MINVALUE
- NO MAXVALUE
- CACHE 1;
-
-ALTER SEQUENCE dep_ci_build_trace_section_names_id_seq OWNED BY dep_ci_build_trace_section_names.id;
-
-CREATE TABLE dep_ci_build_trace_sections (
- project_id integer NOT NULL,
- date_start timestamp without time zone NOT NULL,
- date_end timestamp without time zone NOT NULL,
- byte_start bigint NOT NULL,
- byte_end bigint NOT NULL,
- build_id integer NOT NULL,
- section_name_id integer NOT NULL,
- build_id_convert_to_bigint bigint DEFAULT 0 NOT NULL
-);
-
CREATE TABLE dependency_proxy_blobs (
id integer NOT NULL,
group_id integer NOT NULL,
@@ -13137,7 +13237,8 @@ CREATE TABLE dependency_proxy_blobs (
file_store integer,
file_name character varying NOT NULL,
file text NOT NULL,
- status smallint DEFAULT 0 NOT NULL
+ status smallint DEFAULT 0 NOT NULL,
+ read_at timestamp with time zone DEFAULT now() NOT NULL
);
CREATE SEQUENCE dependency_proxy_blobs_id_seq
@@ -13186,6 +13287,7 @@ CREATE TABLE dependency_proxy_manifests (
digest text NOT NULL,
content_type text,
status smallint DEFAULT 0 NOT NULL,
+ read_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT check_079b293a7b CHECK ((char_length(file) <= 255)),
CONSTRAINT check_167a9a8a91 CHECK ((char_length(content_type) <= 255)),
CONSTRAINT check_c579e3f586 CHECK ((char_length(file_name) <= 255)),
@@ -13273,7 +13375,8 @@ CREATE TABLE deployments (
status smallint NOT NULL,
finished_at timestamp with time zone,
cluster_id integer,
- deployable_id bigint
+ deployable_id bigint,
+ archived boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE deployments_id_seq
@@ -14068,7 +14171,6 @@ CREATE TABLE geo_event_log (
hashed_storage_migrated_event_id bigint,
lfs_object_deleted_event_id bigint,
hashed_storage_attachments_event_id bigint,
- upload_deleted_event_id bigint,
job_artifact_deleted_event_id bigint,
reset_checksum_event_id bigint,
cache_invalidation_event_id bigint,
@@ -14198,9 +14300,6 @@ CREATE TABLE geo_node_statuses (
lfs_objects_count integer,
lfs_objects_synced_count integer,
lfs_objects_failed_count integer,
- attachments_count integer,
- attachments_synced_count integer,
- attachments_failed_count integer,
last_event_id integer,
last_event_date timestamp without time zone,
cursor_last_event_id integer,
@@ -14225,7 +14324,6 @@ CREATE TABLE geo_node_statuses (
wikis_verification_failed_count integer,
lfs_objects_synced_missing_on_primary_count integer,
job_artifacts_synced_missing_on_primary_count integer,
- attachments_synced_missing_on_primary_count integer,
repositories_checksummed_count integer,
repositories_checksum_failed_count integer,
repositories_checksum_mismatch_count integer,
@@ -14394,24 +14492,6 @@ CREATE SEQUENCE geo_reset_checksum_events_id_seq
ALTER SEQUENCE geo_reset_checksum_events_id_seq OWNED BY geo_reset_checksum_events.id;
-CREATE TABLE geo_upload_deleted_events (
- id bigint NOT NULL,
- upload_id integer NOT NULL,
- file_path character varying NOT NULL,
- model_id integer NOT NULL,
- model_type character varying NOT NULL,
- uploader character varying NOT NULL
-);
-
-CREATE SEQUENCE geo_upload_deleted_events_id_seq
- START WITH 1
- INCREMENT BY 1
- NO MINVALUE
- NO MAXVALUE
- CACHE 1;
-
-ALTER SEQUENCE geo_upload_deleted_events_id_seq OWNED BY geo_upload_deleted_events.id;
-
CREATE TABLE gitlab_subscription_histories (
id bigint NOT NULL,
gitlab_subscription_created_at timestamp with time zone,
@@ -15661,6 +15741,24 @@ CREATE SEQUENCE lists_id_seq
ALTER SEQUENCE lists_id_seq OWNED BY lists.id;
+CREATE TABLE member_tasks (
+ id bigint NOT NULL,
+ member_id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ tasks smallint[] DEFAULT '{}'::smallint[] NOT NULL
+);
+
+CREATE SEQUENCE member_tasks_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE member_tasks_id_seq OWNED BY member_tasks.id;
+
CREATE TABLE members (
id integer NOT NULL,
access_level integer NOT NULL,
@@ -15696,7 +15794,8 @@ CREATE TABLE merge_request_assignees (
id bigint NOT NULL,
user_id integer NOT NULL,
merge_request_id integer NOT NULL,
- created_at timestamp with time zone
+ created_at timestamp with time zone,
+ state smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE merge_request_assignees_id_seq
@@ -15808,10 +15907,6 @@ CREATE TABLE merge_request_diff_commits (
merge_request_diff_id integer NOT NULL,
relative_order integer NOT NULL,
sha bytea NOT NULL,
- author_name text,
- author_email text,
- committer_name text,
- committer_email text,
message text,
trailers jsonb DEFAULT '{}'::jsonb NOT NULL,
commit_author_id bigint,
@@ -16258,7 +16353,8 @@ CREATE TABLE namespaces (
push_rule_id bigint,
shared_runners_enabled boolean DEFAULT true NOT NULL,
allow_descendants_override_disabled_shared_runners boolean DEFAULT false NOT NULL,
- traversal_ids integer[] DEFAULT '{}'::integer[] NOT NULL
+ traversal_ids integer[] DEFAULT '{}'::integer[] NOT NULL,
+ tmp_project_id integer
);
CREATE SEQUENCE namespaces_id_seq
@@ -16488,30 +16584,6 @@ CREATE SEQUENCE onboarding_progresses_id_seq
ALTER SEQUENCE onboarding_progresses_id_seq OWNED BY onboarding_progresses.id;
-CREATE TABLE open_project_tracker_data (
- id bigint NOT NULL,
- service_id integer NOT NULL,
- created_at timestamp with time zone NOT NULL,
- updated_at timestamp with time zone NOT NULL,
- encrypted_url character varying(255),
- encrypted_url_iv character varying(255),
- encrypted_api_url character varying(255),
- encrypted_api_url_iv character varying(255),
- encrypted_token character varying(255),
- encrypted_token_iv character varying(255),
- closed_status_id character varying(5),
- project_identifier_code character varying(100)
-);
-
-CREATE SEQUENCE open_project_tracker_data_id_seq
- START WITH 1
- INCREMENT BY 1
- NO MINVALUE
- NO MAXVALUE
- CACHE 1;
-
-ALTER SEQUENCE open_project_tracker_data_id_seq OWNED BY open_project_tracker_data.id;
-
CREATE TABLE operations_feature_flag_scopes (
id bigint NOT NULL,
feature_flag_id bigint NOT NULL,
@@ -17084,6 +17156,12 @@ CREATE SEQUENCE packages_maven_metadata_id_seq
ALTER SEQUENCE packages_maven_metadata_id_seq OWNED BY packages_maven_metadata.id;
+CREATE TABLE packages_npm_metadata (
+ package_id bigint NOT NULL,
+ package_json jsonb DEFAULT '{}'::jsonb NOT NULL,
+ CONSTRAINT chk_rails_e5cbc301ae CHECK ((char_length((package_json)::text) < 20000))
+);
+
CREATE TABLE packages_nuget_dependency_link_metadata (
dependency_link_id bigint NOT NULL,
target_framework text NOT NULL,
@@ -17451,7 +17529,10 @@ CREATE TABLE plan_limits (
ci_jobs_trace_size_limit integer DEFAULT 100 NOT NULL,
pages_file_entries integer DEFAULT 200000 NOT NULL,
dast_profile_schedules integer DEFAULT 1 NOT NULL,
- external_audit_event_destinations integer DEFAULT 5 NOT NULL
+ external_audit_event_destinations integer DEFAULT 5 NOT NULL,
+ dotenv_variables integer DEFAULT 20 NOT NULL,
+ dotenv_size integer DEFAULT 5120 NOT NULL,
+ pipeline_triggers integer DEFAULT 25000 NOT NULL
);
CREATE SEQUENCE plan_limits_id_seq
@@ -17660,7 +17741,7 @@ CREATE VIEW postgres_indexes AS
FROM ((((pg_index
JOIN pg_class i ON ((i.oid = pg_index.indexrelid)))
JOIN pg_namespace ON ((i.relnamespace = pg_namespace.oid)))
- JOIN pg_indexes ON ((i.relname = pg_indexes.indexname)))
+ JOIN pg_indexes ON (((i.relname = pg_indexes.indexname) AND (pg_namespace.nspname = pg_indexes.schemaname))))
JOIN pg_am a ON ((i.relam = a.oid)))
WHERE ((pg_namespace.nspname <> 'pg_catalog'::name) AND (pg_namespace.nspname = ANY (ARRAY["current_schema"(), 'gitlab_partitions_dynamic'::name, 'gitlab_partitions_static'::name])));
@@ -17727,6 +17808,24 @@ CREATE SEQUENCE postgres_reindex_actions_id_seq
ALTER SEQUENCE postgres_reindex_actions_id_seq OWNED BY postgres_reindex_actions.id;
+CREATE TABLE postgres_reindex_queued_actions (
+ id bigint NOT NULL,
+ index_identifier text NOT NULL,
+ state smallint DEFAULT 0 NOT NULL,
+ created_at timestamp with time zone DEFAULT now() NOT NULL,
+ updated_at timestamp with time zone DEFAULT now() NOT NULL,
+ CONSTRAINT check_e4b01395c0 CHECK ((char_length(index_identifier) <= 255))
+);
+
+CREATE SEQUENCE postgres_reindex_queued_actions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE postgres_reindex_queued_actions_id_seq OWNED BY postgres_reindex_queued_actions.id;
+
CREATE TABLE programming_languages (
id integer NOT NULL,
name character varying NOT NULL,
@@ -18157,8 +18256,11 @@ CREATE TABLE project_settings (
mr_default_target_self boolean DEFAULT false NOT NULL,
previous_default_branch text,
warn_about_potentially_unwanted_characters boolean DEFAULT true NOT NULL,
+ merge_commit_template text,
+ has_shimo boolean DEFAULT false NOT NULL,
CONSTRAINT check_3a03e7557a CHECK ((char_length(previous_default_branch) <= 4096)),
- CONSTRAINT check_bde223416c CHECK ((show_default_award_emojis IS NOT NULL))
+ CONSTRAINT check_bde223416c CHECK ((show_default_award_emojis IS NOT NULL)),
+ CONSTRAINT check_eaf7cfb6a7 CHECK ((char_length(merge_commit_template) <= 500))
);
CREATE TABLE project_statistics (
@@ -19819,6 +19921,8 @@ CREATE TABLE user_credit_card_validations (
expiration_date date,
last_digits smallint,
holder_name text,
+ network text,
+ CONSTRAINT check_1765e2b30f CHECK ((char_length(network) <= 32)),
CONSTRAINT check_3eea080c91 CHECK (((last_digits >= 0) AND (last_digits <= 9999))),
CONSTRAINT check_eafe45d88b CHECK ((char_length(holder_name) <= 26))
);
@@ -20045,7 +20149,7 @@ CREATE TABLE users (
encrypted_otp_secret_salt character varying,
otp_required_for_login boolean DEFAULT false NOT NULL,
otp_backup_codes text,
- public_email character varying DEFAULT ''::character varying NOT NULL,
+ public_email character varying,
dashboard integer DEFAULT 0,
project_view integer DEFAULT 0,
consumed_timestep integer,
@@ -20142,7 +20246,8 @@ CREATE TABLE users_statistics (
with_highest_role_maintainer integer DEFAULT 0 NOT NULL,
with_highest_role_owner integer DEFAULT 0 NOT NULL,
bots integer DEFAULT 0 NOT NULL,
- blocked integer DEFAULT 0 NOT NULL
+ blocked integer DEFAULT 0 NOT NULL,
+ with_highest_role_minimal_access integer DEFAULT 0 NOT NULL
);
CREATE SEQUENCE users_statistics_id_seq
@@ -20154,19 +20259,6 @@ CREATE SEQUENCE users_statistics_id_seq
ALTER SEQUENCE users_statistics_id_seq OWNED BY users_statistics.id;
-CREATE TABLE verification_codes (
- created_at timestamp with time zone DEFAULT now() NOT NULL,
- visitor_id_code text NOT NULL,
- code text NOT NULL,
- phone text NOT NULL,
- CONSTRAINT check_9b84e6aaff CHECK ((char_length(code) <= 8)),
- CONSTRAINT check_ccc542256b CHECK ((char_length(visitor_id_code) <= 64)),
- CONSTRAINT check_f5684c195b CHECK ((char_length(phone) <= 32))
-)
-PARTITION BY RANGE (created_at);
-
-COMMENT ON TABLE verification_codes IS 'JiHu-specific table';
-
CREATE TABLE vulnerabilities (
id bigint NOT NULL,
milestone_id bigint,
@@ -21224,6 +21316,8 @@ ALTER TABLE ONLY compliance_management_frameworks ALTER COLUMN id SET DEFAULT ne
ALTER TABLE ONLY container_repositories ALTER COLUMN id SET DEFAULT nextval('container_repositories_id_seq'::regclass);
+ALTER TABLE ONLY content_blocked_states ALTER COLUMN id SET DEFAULT nextval('content_blocked_states_id_seq'::regclass);
+
ALTER TABLE ONLY conversational_development_index_metrics ALTER COLUMN id SET DEFAULT nextval('conversational_development_index_metrics_id_seq'::regclass);
ALTER TABLE ONLY coverage_fuzzing_corpuses ALTER COLUMN id SET DEFAULT nextval('coverage_fuzzing_corpuses_id_seq'::regclass);
@@ -21252,8 +21346,6 @@ ALTER TABLE ONLY dast_site_validations ALTER COLUMN id SET DEFAULT nextval('dast
ALTER TABLE ONLY dast_sites ALTER COLUMN id SET DEFAULT nextval('dast_sites_id_seq'::regclass);
-ALTER TABLE ONLY dep_ci_build_trace_section_names ALTER COLUMN id SET DEFAULT nextval('dep_ci_build_trace_section_names_id_seq'::regclass);
-
ALTER TABLE ONLY dependency_proxy_blobs ALTER COLUMN id SET DEFAULT nextval('dependency_proxy_blobs_id_seq'::regclass);
ALTER TABLE ONLY dependency_proxy_group_settings ALTER COLUMN id SET DEFAULT nextval('dependency_proxy_group_settings_id_seq'::regclass);
@@ -21372,8 +21464,6 @@ ALTER TABLE ONLY geo_repository_updated_events ALTER COLUMN id SET DEFAULT nextv
ALTER TABLE ONLY geo_reset_checksum_events ALTER COLUMN id SET DEFAULT nextval('geo_reset_checksum_events_id_seq'::regclass);
-ALTER TABLE ONLY geo_upload_deleted_events ALTER COLUMN id SET DEFAULT nextval('geo_upload_deleted_events_id_seq'::regclass);
-
ALTER TABLE ONLY gitlab_subscription_histories ALTER COLUMN id SET DEFAULT nextval('gitlab_subscription_histories_id_seq'::regclass);
ALTER TABLE ONLY gitlab_subscriptions ALTER COLUMN id SET DEFAULT nextval('gitlab_subscriptions_id_seq'::regclass);
@@ -21492,6 +21582,8 @@ ALTER TABLE ONLY lists ALTER COLUMN id SET DEFAULT nextval('lists_id_seq'::regcl
ALTER TABLE ONLY loose_foreign_keys_deleted_records ALTER COLUMN id SET DEFAULT nextval('loose_foreign_keys_deleted_records_id_seq'::regclass);
+ALTER TABLE ONLY member_tasks ALTER COLUMN id SET DEFAULT nextval('member_tasks_id_seq'::regclass);
+
ALTER TABLE ONLY members ALTER COLUMN id SET DEFAULT nextval('members_id_seq'::regclass);
ALTER TABLE ONLY merge_request_assignees ALTER COLUMN id SET DEFAULT nextval('merge_request_assignees_id_seq'::regclass);
@@ -21548,8 +21640,6 @@ ALTER TABLE ONLY oauth_openid_requests ALTER COLUMN id SET DEFAULT nextval('oaut
ALTER TABLE ONLY onboarding_progresses ALTER COLUMN id SET DEFAULT nextval('onboarding_progresses_id_seq'::regclass);
-ALTER TABLE ONLY open_project_tracker_data ALTER COLUMN id SET DEFAULT nextval('open_project_tracker_data_id_seq'::regclass);
-
ALTER TABLE ONLY operations_feature_flag_scopes ALTER COLUMN id SET DEFAULT nextval('operations_feature_flag_scopes_id_seq'::regclass);
ALTER TABLE ONLY operations_feature_flags ALTER COLUMN id SET DEFAULT nextval('operations_feature_flags_id_seq'::regclass);
@@ -21634,6 +21724,8 @@ ALTER TABLE ONLY postgres_async_indexes ALTER COLUMN id SET DEFAULT nextval('pos
ALTER TABLE ONLY postgres_reindex_actions ALTER COLUMN id SET DEFAULT nextval('postgres_reindex_actions_id_seq'::regclass);
+ALTER TABLE ONLY postgres_reindex_queued_actions ALTER COLUMN id SET DEFAULT nextval('postgres_reindex_queued_actions_id_seq'::regclass);
+
ALTER TABLE ONLY product_analytics_events_experimental ALTER COLUMN id SET DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass);
ALTER TABLE ONLY programming_languages ALTER COLUMN id SET DEFAULT nextval('programming_languages_id_seq'::regclass);
@@ -22543,9 +22635,6 @@ ALTER TABLE ONLY ci_build_trace_chunks
ALTER TABLE ONLY ci_build_trace_metadata
ADD CONSTRAINT ci_build_trace_metadata_pkey PRIMARY KEY (build_id);
-ALTER TABLE ONLY dep_ci_build_trace_sections
- ADD CONSTRAINT ci_build_trace_sections_pkey PRIMARY KEY (build_id, section_name_id);
-
ALTER TABLE ONLY ci_builds_metadata
ADD CONSTRAINT ci_builds_metadata_pkey PRIMARY KEY (id);
@@ -22741,6 +22830,9 @@ ALTER TABLE ONLY container_expiration_policies
ALTER TABLE ONLY container_repositories
ADD CONSTRAINT container_repositories_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY content_blocked_states
+ ADD CONSTRAINT content_blocked_states_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY conversational_development_index_metrics
ADD CONSTRAINT conversational_development_index_metrics_pkey PRIMARY KEY (id);
@@ -22795,9 +22887,6 @@ ALTER TABLE ONLY dast_site_validations
ALTER TABLE ONLY dast_sites
ADD CONSTRAINT dast_sites_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY dep_ci_build_trace_section_names
- ADD CONSTRAINT dep_ci_build_trace_section_names_pkey PRIMARY KEY (id);
-
ALTER TABLE ONLY dependency_proxy_blobs
ADD CONSTRAINT dependency_proxy_blobs_pkey PRIMARY KEY (id);
@@ -22990,9 +23079,6 @@ ALTER TABLE ONLY geo_repository_updated_events
ALTER TABLE ONLY geo_reset_checksum_events
ADD CONSTRAINT geo_reset_checksum_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY geo_upload_deleted_events
- ADD CONSTRAINT geo_upload_deleted_events_pkey PRIMARY KEY (id);
-
ALTER TABLE ONLY gitlab_subscription_histories
ADD CONSTRAINT gitlab_subscription_histories_pkey PRIMARY KEY (id);
@@ -23194,6 +23280,9 @@ ALTER TABLE ONLY list_user_preferences
ALTER TABLE ONLY lists
ADD CONSTRAINT lists_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY member_tasks
+ ADD CONSTRAINT member_tasks_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY members
ADD CONSTRAINT members_pkey PRIMARY KEY (id);
@@ -23305,9 +23394,6 @@ ALTER TABLE ONLY oauth_openid_requests
ALTER TABLE ONLY onboarding_progresses
ADD CONSTRAINT onboarding_progresses_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY open_project_tracker_data
- ADD CONSTRAINT open_project_tracker_data_pkey PRIMARY KEY (id);
-
ALTER TABLE ONLY operations_feature_flag_scopes
ADD CONSTRAINT operations_feature_flag_scopes_pkey PRIMARY KEY (id);
@@ -23398,6 +23484,9 @@ ALTER TABLE ONLY packages_helm_file_metadata
ALTER TABLE ONLY packages_maven_metadata
ADD CONSTRAINT packages_maven_metadata_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_npm_metadata
+ ADD CONSTRAINT packages_npm_metadata_pkey PRIMARY KEY (package_id);
+
ALTER TABLE ONLY packages_nuget_dependency_link_metadata
ADD CONSTRAINT packages_nuget_dependency_link_metadata_pkey PRIMARY KEY (dependency_link_id);
@@ -23455,6 +23544,9 @@ ALTER TABLE ONLY postgres_async_indexes
ALTER TABLE ONLY postgres_reindex_actions
ADD CONSTRAINT postgres_reindex_actions_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY postgres_reindex_queued_actions
+ ADD CONSTRAINT postgres_reindex_queued_actions_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY programming_languages
ADD CONSTRAINT programming_languages_pkey PRIMARY KEY (id);
@@ -23938,6 +24030,538 @@ ALTER TABLE ONLY zentao_tracker_data
ALTER TABLE ONLY zoom_meetings
ADD CONSTRAINT zoom_meetings_pkey PRIMARY KEY (id);
+CREATE INDEX index_issue_stage_events_project_duration ON ONLY analytics_cycle_analytics_issue_stage_events USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_000925dbd7 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_11 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_merge_request_stage_events_project_duration ON ONLY analytics_cycle_analytics_merge_request_stage_events USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_006f943df6 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_16 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_loose_foreign_keys_deleted_records_for_partitioned_query ON ONLY loose_foreign_keys_deleted_records USING btree (partition, fully_qualified_table_name, consume_after, id) WHERE (status = 1);
+
+CREATE INDEX index_01e3390fac ON gitlab_partitions_static.loose_foreign_keys_deleted_records_1 USING btree (partition, fully_qualified_table_name, consume_after, id) WHERE (status = 1);
+
+CREATE INDEX index_02749b504c ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_11 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_merge_request_stage_events_group_duration ON ONLY analytics_cycle_analytics_merge_request_stage_events USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_0287f5ba09 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_29 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_03aa30a758 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_23 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_issue_stage_events_group_duration ON ONLY analytics_cycle_analytics_issue_stage_events USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_055179c3ea ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_10 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_061fe00461 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_19 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_070cef72c3 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_02 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_08e3cfc564 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_30 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_merge_request_stage_events_group_in_progress_duration ON ONLY analytics_cycle_analytics_merge_request_stage_events USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_09af45dd6f ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_13 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_0c153e2eae ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_13 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_issue_stage_events_group_in_progress_duration ON ONLY analytics_cycle_analytics_issue_stage_events USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_0ca85f3d71 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_30 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_issue_stage_events_project_in_progress_duration ON ONLY analytics_cycle_analytics_issue_stage_events USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_0d837a5dda ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_03 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_0f28a65451 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_09 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_10588dbff0 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_13 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_107e123e17 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_25 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_1230a7a402 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_25 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_142c4e7ea4 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_08 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_merge_request_stage_events_project_in_progress_duration ON ONLY analytics_cycle_analytics_merge_request_stage_events USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_14e4fa1d7d ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_28 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_14f3645821 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_28 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_16627b455e ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_27 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_1a0388713a ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_22 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_1a349ed064 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_24 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_1af932a3c7 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_27 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_1b0ea30bdb ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_21 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_1f6c3faabe ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_00 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_1f8af04ed1 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_19 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_201c5ddbe9 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_00 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_20353089e0 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_20 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_206349925b ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_01 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_21db459e34 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_19 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_21e262390a ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_16 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_2208bd7d7f ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_28 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_223592b4a1 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_07 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_22acc9ab11 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_27 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_22ed8f01dd ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_10 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_234d38a657 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_02 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_23783dc748 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_01 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_241e9a574c ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_08 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_24ac321751 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_02 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_25e2aaee9b ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_12 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_2653e7eeb8 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_06 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_2745f5a388 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_31 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_27759556bc ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_01 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_27d7ad78d8 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_31 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_281840d2d1 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_06 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_296f64df5c ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_01 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_2ad4b4fdbc ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_05 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_2b7c0a294e ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_05 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_2c6422f668 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_30 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_2dfcdbe81e ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_14 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_2e1054b181 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_24 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_2e6991d05b ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_28 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_2f80c360c3 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_10 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_2fc271c673 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_12 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_2fcfd0dc70 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_16 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_3005c75335 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_23 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_3206c1e6af ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_29 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_3249505125 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_18 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_331eb67441 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_30 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_3640194b77 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_29 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_372160a706 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_28 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_38a538234e ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_09 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_39625b8a41 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_05 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_399dc06649 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_30 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_3a10b315c0 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_28 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_3c2a3a6ac9 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_06 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_3e6be332b7 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_27 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_41a1c3a4c6 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_29 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_435802dd01 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_01 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_436fa9ad5f ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_13 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_453a659cb6 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_16 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_46b989b294 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_02 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_47638677a3 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_04 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_4810ac88f5 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_24 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_491b4b749e ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_20 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_4a243772d7 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_15 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_4b1793a4c4 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_07 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_4b22560035 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_22 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_4c2645eef2 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_21 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_4c9d14f978 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_12 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_4d04210a95 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_21 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_4d4f2f7de6 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_31 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_4db5aa5872 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_10 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_4dead6f314 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_17 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_4e6ce1c371 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_30 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_4f2eb7a06b ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_08 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_4f6fc34e57 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_31 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_50c09f6e04 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_06 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_5111e3e7e7 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_18 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_52ea79bf8e ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_14 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_541cc045fc ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_26 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_551676e972 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_01 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_56281bfb73 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_21 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_5660b1b38e ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_24 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_59a8209ab6 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_07 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_59ce40fcc4 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_24 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_5a5f39d824 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_19 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_5b613b5fcf ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_25 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_5b944f308d ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_11 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_5bc2f32084 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_13 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_5c4053b63d ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_19 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_5db09170d4 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_16 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_5ee060202f ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_20 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_5f24f6ead2 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_05 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_5f96b344e2 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_14 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_5fb1867c41 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_17 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_5fe1d00845 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_05 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_60e3480f23 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_22 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_6137e27484 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_10 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_620fe77c99 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_22 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_625ed9e965 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_27 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_64e3a1dfa1 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_04 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_64eb4cf8bd ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_12 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_6580ecb2db ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_18 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_682eba05f6 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_04 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_69bdcf213e ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_09 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_6a39f6d5ac ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_24 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_6add8e74cf ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_11 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_6b1ce61c8f ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_02 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_6cfb391b86 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_21 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_6e6c2e6a1d ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_04 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_6ea423bbd1 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_30 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_6ec4c4afd4 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_04 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_6f4e0abe54 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_26 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_6fa47e1334 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_23 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_70c657954b ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_18 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_71c2b26944 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_08 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_72027c157f ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_27 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_739845f617 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_31 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_74addd1240 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_12 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_75dc81d1d7 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_14 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_765b0cd8db ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_16 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_77096a1dc6 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_07 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_77c6293242 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_10 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_7b7c85eceb ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_05 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_7da2307d2e ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_07 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_7ead2300ca ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_15 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_7ecb5b68b4 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_07 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_807671c4be ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_13 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_807fa83fc0 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_31 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_80c65daf20 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_10 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_81b9cf594f ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_15 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_82c675952c ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_14 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_83c5049b3e ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_31 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_83edf231b8 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_21 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_844abd2888 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_24 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_8464227c80 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_26 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_8685d7c69c ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_25 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_8688b40056 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_29 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_87d40fb9f9 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_03 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_88b40d6740 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_23 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_89c79afe5c ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_28 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_8a0fc3de4f ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_29 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_8b9f9a19a4 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_18 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_8fb48e72ce ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_26 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_9201b952a0 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_13 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_92c09e352b ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_02 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_9490e0e0b7 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_12 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_95a353f50b ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_27 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_971af9481e ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_10 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_9955b1dc59 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_03 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_9b8e89ae41 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_08 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_9ee83b068b ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_25 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_a1a9dc36c1 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_11 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_a2d9f185a5 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_19 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_a3feed3097 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_21 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_a6999c65c9 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_09 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_a6c68d16b2 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_14 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_a8276a450f ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_05 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_a88f20fc98 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_11 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_a9424aa392 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_01 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_a99cee1904 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_23 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_a9deff2159 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_26 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_aabc184267 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_25 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_ab22231a16 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_09 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_abbdf80ab1 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_26 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_adc159c3fe ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_17 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_aed7f7b10c ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_02 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_aee84adb5b ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_15 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_b1dda405af ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_29 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_b607012614 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_17 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_b7f21460bb ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_23 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_b83fe1306b ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_03 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_bc189e47ab ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_11 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_bca83177ef ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_20 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_bedd7e160b ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_17 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_bee2b94a80 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_17 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_c08e669dfa ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_11 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_c09bb66559 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_09 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_c119f5b92e ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_19 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_c17dae3605 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_00 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_c1cdd90d0d ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_15 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_c2b951bf20 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_20 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_c42b2e7eae ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_05 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_c435d904ce ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_08 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_c473921734 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_30 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_c546bb0736 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_00 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_c59cde6209 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_14 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_c66758baa7 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_00 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_c6ea8a0e26 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_04 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_c8c4219c0a ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_26 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_c971e6c5ce ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_19 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_c9b14a3d9f ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_08 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_cbb61ea269 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_12 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_cc0ba6343b ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_09 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_cd2b2939a4 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_03 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_cda41e106e ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_22 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_cfa4237c83 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_24 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_d01ea0126a ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_25 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_d0d285c264 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_22 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_d27b4c84e7 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_18 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_d2fe918e83 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_08 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_d35c969634 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_09 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_d6047ee813 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_06 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_d69c2485f4 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_29 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_d8fa9793ad ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_00 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_d9384b768d ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_15 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_dc571ba649 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_01 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_df62a8c50e ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_07 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_e1a4f994d8 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_06 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_e3d1fd5b19 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_04 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_e3d6234929 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_03 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_e54adf9acb ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_06 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_e6405afea0 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_12 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_e64588e276 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_00 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_e716b8ac3f ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_22 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_e73bc5ba6a ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_20 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_e8f3a327b2 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_18 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_ea0c2d3361 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_17 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_eb558957f0 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_31 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_ec25d494e6 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_25 USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_ed094a4f13 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_20 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_ee4c549a2d ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_20 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_ef6a48bd29 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_06 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_ef7be2ae94 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_22 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_f0cdd09a5e ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_13 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_f112fae8ac ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_23 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_f1c3d14cdc ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_18 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_f256d3f6a1 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_16 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_f2848acfc7 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_02 USING btree (stage_event_hash_id, group_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_f3d7d86e09 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_17 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_f47327ec1f ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_27 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_f6b0d458a3 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_15 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_f705dc8541 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_21 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_f76e8a5304 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_14 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_f86acdc2ff ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_23 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_f878aab8e3 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_15 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_f902c261ce ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_16 USING btree (stage_event_hash_id, project_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_fbccc855cf ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_26 USING btree (stage_event_hash_id, group_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_fbf2d3310b ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_00 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_fccbe45c32 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_03 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_fee429223e ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_07 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_ff00c038cc ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_03 USING btree (stage_event_hash_id, project_id, start_event_timestamp, merge_request_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
+CREATE INDEX index_ff39be5400 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_04 USING btree (stage_event_hash_id, project_id, end_event_timestamp, issue_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
+
+CREATE INDEX index_ff8741d8d7 ON gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_28 USING btree (stage_event_hash_id, group_id, start_event_timestamp, issue_id) WHERE ((end_event_timestamp IS NULL) AND (state_id = 1));
+
CREATE INDEX index_product_analytics_events_experimental_project_and_time ON ONLY product_analytics_events_experimental USING btree (project_id, collector_tstamp);
CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx10 ON gitlab_partitions_static.product_analytics_events_experimental_10 USING btree (project_id, collector_tstamp);
@@ -24512,6 +25136,8 @@ CREATE INDEX index_boards_on_project_id ON boards USING btree (project_id);
CREATE INDEX index_broadcast_message_on_ends_at_and_broadcast_type_and_id ON broadcast_messages USING btree (ends_at, broadcast_type, id);
+CREATE INDEX index_btree_namespaces_traversal_ids ON namespaces USING btree (traversal_ids);
+
CREATE INDEX index_bulk_import_configurations_on_bulk_import_id ON bulk_import_configurations USING btree (bulk_import_id);
CREATE INDEX index_bulk_import_entities_on_bulk_import_id_and_status ON bulk_import_entities USING btree (bulk_import_id, status);
@@ -24904,6 +25530,8 @@ CREATE UNIQUE INDEX index_container_repositories_on_project_id_and_name ON conta
CREATE INDEX index_container_repository_on_name_trigram ON container_repositories USING gin (name gin_trgm_ops);
+CREATE UNIQUE INDEX index_content_blocked_states_on_container_id_commit_sha_path ON content_blocked_states USING btree (container_identifier, commit_sha, path);
+
CREATE INDEX index_coverage_fuzzing_corpuses_on_package_id ON coverage_fuzzing_corpuses USING btree (package_id);
CREATE INDEX index_coverage_fuzzing_corpuses_on_project_id ON coverage_fuzzing_corpuses USING btree (project_id);
@@ -24968,23 +25596,17 @@ CREATE INDEX index_dast_sites_on_dast_site_validation_id ON dast_sites USING btr
CREATE UNIQUE INDEX index_dast_sites_on_project_id_and_url ON dast_sites USING btree (project_id, url);
-CREATE UNIQUE INDEX index_dep_ci_build_trace_section_names_on_project_id_and_name ON dep_ci_build_trace_section_names USING btree (project_id, name);
-
-CREATE INDEX index_dep_ci_build_trace_sections_on_project_id ON dep_ci_build_trace_sections USING btree (project_id);
-
-CREATE INDEX index_dep_ci_build_trace_sections_on_section_name_id ON dep_ci_build_trace_sections USING btree (section_name_id);
-
CREATE UNIQUE INDEX index_dep_prox_manifests_on_group_id_file_name_and_status ON dependency_proxy_manifests USING btree (group_id, file_name, status);
CREATE INDEX index_dependency_proxy_blobs_on_group_id_and_file_name ON dependency_proxy_blobs USING btree (group_id, file_name);
-CREATE INDEX index_dependency_proxy_blobs_on_group_id_status_and_id ON dependency_proxy_blobs USING btree (group_id, status, id);
+CREATE INDEX index_dependency_proxy_blobs_on_group_id_status_read_at_id ON dependency_proxy_blobs USING btree (group_id, status, read_at, id);
CREATE INDEX index_dependency_proxy_blobs_on_status ON dependency_proxy_blobs USING btree (status);
CREATE INDEX index_dependency_proxy_group_settings_on_group_id ON dependency_proxy_group_settings USING btree (group_id);
-CREATE INDEX index_dependency_proxy_manifests_on_group_id_status_and_id ON dependency_proxy_manifests USING btree (group_id, status, id);
+CREATE INDEX index_dependency_proxy_manifests_on_group_id_status_read_at_id ON dependency_proxy_manifests USING btree (group_id, status, read_at, id);
CREATE INDEX index_dependency_proxy_manifests_on_status ON dependency_proxy_manifests USING btree (status);
@@ -25004,6 +25626,8 @@ CREATE UNIQUE INDEX index_deployment_clusters_on_cluster_id_and_deployment_id ON
CREATE INDEX index_deployment_merge_requests_on_merge_request_id ON deployment_merge_requests USING btree (merge_request_id);
+CREATE INDEX index_deployments_on_archived_project_id_iid ON deployments USING btree (archived, project_id, iid);
+
CREATE INDEX index_deployments_on_cluster_id_and_status ON deployments USING btree (cluster_id, status);
CREATE INDEX index_deployments_on_created_at ON deployments USING btree (created_at);
@@ -25014,6 +25638,8 @@ CREATE INDEX index_deployments_on_environment_id_and_id ON deployments USING btr
CREATE INDEX index_deployments_on_environment_id_and_iid_and_project_id ON deployments USING btree (environment_id, iid, project_id);
+CREATE INDEX index_deployments_on_environment_id_and_ref ON deployments USING btree (environment_id, ref);
+
CREATE INDEX index_deployments_on_environment_id_status_and_finished_at ON deployments USING btree (environment_id, status, finished_at);
CREATE INDEX index_deployments_on_environment_id_status_and_id ON deployments USING btree (environment_id, status, id);
@@ -25192,6 +25818,8 @@ CREATE INDEX index_events_on_author_id_and_created_at_merge_requests ON events U
CREATE INDEX index_events_on_author_id_and_project_id ON events USING btree (author_id, project_id);
+CREATE INDEX index_events_on_created_at_and_id ON events USING btree (created_at, id) WHERE (created_at > '2021-08-27 00:00:00+00'::timestamp with time zone);
+
CREATE INDEX index_events_on_group_id_partial ON events USING btree (group_id) WHERE (group_id IS NOT NULL);
CREATE INDEX index_events_on_project_id_and_created_at ON events USING btree (project_id, created_at);
@@ -25200,8 +25828,6 @@ CREATE INDEX index_events_on_project_id_and_id ON events USING btree (project_id
CREATE INDEX index_events_on_project_id_and_id_desc_on_merged_action ON events USING btree (project_id, id DESC) WHERE (action = 7);
-CREATE INDEX index_events_on_target_type_and_target_id ON events USING btree (target_type, target_id);
-
CREATE UNIQUE INDEX index_events_on_target_type_and_target_id_and_fingerprint ON events USING btree (target_type, target_id, fingerprint);
CREATE INDEX index_evidences_on_release_id ON evidences USING btree (release_id);
@@ -25234,8 +25860,6 @@ CREATE UNIQUE INDEX index_feature_gates_on_feature_key_and_key_and_value ON feat
CREATE UNIQUE INDEX index_features_on_key ON features USING btree (key);
-CREATE INDEX index_for_resource_group ON ci_builds USING btree (resource_group_id, id) WHERE (resource_group_id IS NOT NULL);
-
CREATE INDEX index_for_status_per_branch_per_project ON merge_trains USING btree (target_project_id, target_branch, status);
CREATE INDEX index_fork_network_members_on_fork_network_id ON fork_network_members USING btree (fork_network_id);
@@ -25272,8 +25896,6 @@ CREATE INDEX index_geo_event_log_on_repository_updated_event_id ON geo_event_log
CREATE INDEX index_geo_event_log_on_reset_checksum_event_id ON geo_event_log USING btree (reset_checksum_event_id) WHERE (reset_checksum_event_id IS NOT NULL);
-CREATE INDEX index_geo_event_log_on_upload_deleted_event_id ON geo_event_log USING btree (upload_deleted_event_id) WHERE (upload_deleted_event_id IS NOT NULL);
-
CREATE INDEX index_geo_hashed_storage_attachments_events_on_project_id ON geo_hashed_storage_attachments_events USING btree (project_id);
CREATE INDEX index_geo_hashed_storage_migrated_events_on_project_id ON geo_hashed_storage_migrated_events USING btree (project_id);
@@ -25310,8 +25932,6 @@ CREATE INDEX index_geo_repository_updated_events_on_source ON geo_repository_upd
CREATE INDEX index_geo_reset_checksum_events_on_project_id ON geo_reset_checksum_events USING btree (project_id);
-CREATE INDEX index_geo_upload_deleted_events_on_upload_id ON geo_upload_deleted_events USING btree (upload_id);
-
CREATE INDEX index_gin_ci_pending_builds_on_namespace_traversal_ids ON ci_pending_builds USING gin (namespace_traversal_ids);
CREATE INDEX index_gitlab_subscription_histories_on_gitlab_subscription_id ON gitlab_subscription_histories USING btree (gitlab_subscription_id);
@@ -25418,6 +26038,8 @@ CREATE INDEX index_import_failures_on_project_id_not_null ON import_failures USI
CREATE INDEX index_imported_projects_on_import_type_creator_id_created_at ON projects USING btree (import_type, creator_id, created_at) WHERE (import_type IS NOT NULL);
+CREATE INDEX index_imported_projects_on_import_type_id ON projects USING btree (import_type, id) WHERE (import_type IS NOT NULL);
+
CREATE INDEX index_in_product_marketing_emails_on_user_id ON in_product_marketing_emails USING btree (user_id);
CREATE UNIQUE INDEX index_in_product_marketing_emails_on_user_track_series ON in_product_marketing_emails USING btree (user_id, track, series);
@@ -25568,8 +26190,6 @@ CREATE INDEX index_jira_imports_on_user_id ON jira_imports USING btree (user_id)
CREATE INDEX index_jira_tracker_data_on_service_id ON jira_tracker_data USING btree (service_id);
-CREATE INDEX index_keys_on_expires_at_and_expiry_notification_undelivered ON keys USING btree (date(timezone('UTC'::text, expires_at)), expiry_notification_delivered_at) WHERE (expiry_notification_delivered_at IS NULL);
-
CREATE INDEX index_keys_on_expires_at_and_id ON keys USING btree (date(timezone('UTC'::text, expires_at)), id) WHERE (expiry_notification_delivered_at IS NULL);
CREATE UNIQUE INDEX index_keys_on_fingerprint ON keys USING btree (fingerprint);
@@ -25638,6 +26258,12 @@ CREATE INDEX index_lists_on_milestone_id ON lists USING btree (milestone_id);
CREATE INDEX index_lists_on_user_id ON lists USING btree (user_id);
+CREATE INDEX index_member_tasks_on_member_id ON member_tasks USING btree (member_id);
+
+CREATE UNIQUE INDEX index_member_tasks_on_member_id_and_project_id ON member_tasks USING btree (member_id, project_id);
+
+CREATE INDEX index_member_tasks_on_project_id ON member_tasks USING btree (project_id);
+
CREATE INDEX index_members_on_access_level ON members USING btree (access_level);
CREATE INDEX index_members_on_expires_at ON members USING btree (expires_at);
@@ -25856,6 +26482,8 @@ CREATE INDEX index_namespaces_on_shared_and_extra_runners_minutes_limit ON names
CREATE INDEX index_namespaces_on_traversal_ids ON namespaces USING gin (traversal_ids);
+CREATE INDEX index_namespaces_on_traversal_ids_for_groups ON namespaces USING gin (traversal_ids) WHERE ((type)::text = 'Group'::text);
+
CREATE INDEX index_namespaces_on_type_and_id ON namespaces USING btree (type, id);
CREATE INDEX index_namespaces_public_groups_name_id ON namespaces USING btree (name, id) WHERE (((type)::text = 'Group'::text) AND (visibility_level = 20));
@@ -25910,6 +26538,8 @@ CREATE INDEX index_oauth_openid_requests_on_access_grant_id ON oauth_openid_requ
CREATE UNIQUE INDEX index_on_deploy_keys_id_and_type_and_public ON keys USING btree (id, type) WHERE (public = true);
+CREATE INDEX index_on_group_id_on_webhooks ON web_hooks USING btree (group_id);
+
CREATE INDEX index_on_identities_lower_extern_uid_and_provider ON identities USING btree (lower((extern_uid)::text), provider);
CREATE UNIQUE INDEX index_on_instance_statistics_recorded_at_and_identifier ON analytics_usage_trends_measurements USING btree (identifier, recorded_at);
@@ -25952,8 +26582,6 @@ CREATE UNIQUE INDEX index_onboarding_progresses_on_namespace_id ON onboarding_pr
CREATE INDEX index_oncall_shifts_on_rotation_id_and_starts_at_and_ends_at ON incident_management_oncall_shifts USING btree (rotation_id, starts_at, ends_at);
-CREATE INDEX index_open_project_tracker_data_on_service_id ON open_project_tracker_data USING btree (service_id);
-
CREATE INDEX index_operations_feature_flags_issues_on_issue_id ON operations_feature_flags_issues USING btree (issue_id);
CREATE UNIQUE INDEX index_operations_feature_flags_on_project_id_and_iid ON operations_feature_flags USING btree (project_id, iid);
@@ -26120,6 +26748,8 @@ CREATE UNIQUE INDEX index_postgres_async_indexes_on_name ON postgres_async_index
CREATE INDEX index_postgres_reindex_actions_on_index_identifier ON postgres_reindex_actions USING btree (index_identifier);
+CREATE INDEX index_postgres_reindex_queued_actions_on_state ON postgres_reindex_queued_actions USING btree (state);
+
CREATE UNIQUE INDEX index_programming_languages_on_name ON programming_languages USING btree (name);
CREATE INDEX index_project_access_tokens_on_project_id ON project_access_tokens USING btree (project_id);
@@ -26396,8 +27026,6 @@ CREATE UNIQUE INDEX index_release_links_on_release_id_and_name ON release_links
CREATE UNIQUE INDEX index_release_links_on_release_id_and_url ON release_links USING btree (release_id, url);
-CREATE INDEX index_releases_on_author_id ON releases USING btree (author_id);
-
CREATE INDEX index_releases_on_author_id_id_created_at ON releases USING btree (author_id, id, created_at);
CREATE INDEX index_releases_on_project_id_and_tag ON releases USING btree (project_id, tag);
@@ -26512,7 +27140,7 @@ CREATE UNIQUE INDEX index_scim_oauth_access_tokens_on_group_id_and_token_encrypt
CREATE INDEX index_secure_ci_builds_on_user_id_name_created_at ON ci_builds USING btree (user_id, name, created_at) WHERE (((type)::text = 'Ci::Build'::text) AND ((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('license_scanning'::character varying)::text, ('sast'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('apifuzzer_fuzz'::character varying)::text, ('apifuzzer_fuzz_dnd'::character varying)::text, ('secret_detection'::character varying)::text])));
-CREATE INDEX index_security_ci_builds_on_name_and_id_parser_features_broken ON ci_builds USING btree (name, id) WHERE (((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text, ('secret_detection'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text));
+CREATE INDEX index_security_ci_builds_on_name_and_id_parser_features ON ci_builds USING btree (name, id) WHERE (((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text, ('secret_detection'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text));
CREATE INDEX index_security_findings_on_confidence ON security_findings USING btree (confidence);
@@ -26778,6 +27406,8 @@ CREATE UNIQUE INDEX index_user_canonical_emails_on_user_id_and_canonical_email O
CREATE INDEX index_user_credit_card_validations_meta_data_full_match ON user_credit_card_validations USING btree (holder_name, expiration_date, last_digits, credit_card_validated_at);
+CREATE INDEX index_user_credit_card_validations_meta_data_partial_match ON user_credit_card_validations USING btree (expiration_date, last_digits, network, credit_card_validated_at);
+
CREATE INDEX index_user_custom_attributes_on_key_and_value ON user_custom_attributes USING btree (key, value);
CREATE UNIQUE INDEX index_user_custom_attributes_on_user_id_and_key ON user_custom_attributes USING btree (user_id, key);
@@ -26824,7 +27454,7 @@ CREATE INDEX index_users_on_feed_token ON users USING btree (feed_token);
CREATE INDEX index_users_on_group_view ON users USING btree (group_view);
-CREATE INDEX index_users_on_id_and_last_activity_on_for_non_internal_active ON users USING btree (id, last_activity_on) WHERE (((state)::text = 'active'::text) AND ((user_type IS NULL) OR (user_type = ANY (ARRAY[NULL::integer, 6, 4]))));
+CREATE INDEX index_users_on_id_and_last_activity_on_for_active_human_service ON users USING btree (id, last_activity_on) WHERE (((state)::text = 'active'::text) AND ((user_type IS NULL) OR (user_type = 4)));
CREATE INDEX index_users_on_incoming_email_token ON users USING btree (incoming_email_token);
@@ -26944,12 +27574,16 @@ CREATE INDEX index_vulnerability_occurrence_identifiers_on_identifier_id ON vuln
CREATE UNIQUE INDEX index_vulnerability_occurrence_identifiers_on_unique_keys ON vulnerability_occurrence_identifiers USING btree (occurrence_id, identifier_id);
+CREATE INDEX index_vulnerability_occurrence_pipelines_occurrence_id_and_id ON vulnerability_occurrence_pipelines USING btree (occurrence_id, id DESC);
+
CREATE INDEX index_vulnerability_occurrence_pipelines_on_pipeline_id ON vulnerability_occurrence_pipelines USING btree (pipeline_id);
CREATE INDEX index_vulnerability_occurrences_deduplication ON vulnerability_occurrences USING btree (project_id, report_type, project_fingerprint);
CREATE INDEX index_vulnerability_occurrences_for_issue_links_migration ON vulnerability_occurrences USING btree (project_id, report_type, encode(project_fingerprint, 'hex'::text));
+CREATE INDEX index_vulnerability_occurrences_on_location_cluster_id ON vulnerability_occurrences USING gin (((location -> 'cluster_id'::text))) WHERE (report_type = 7);
+
CREATE INDEX index_vulnerability_occurrences_on_location_image ON vulnerability_occurrences USING gin (((location -> 'image'::text))) WHERE (report_type = ANY (ARRAY[2, 7]));
CREATE INDEX index_vulnerability_occurrences_on_primary_identifier_id ON vulnerability_occurrences USING btree (primary_identifier_id);
@@ -27082,6 +27716,8 @@ CREATE INDEX tmp_index_namespaces_empty_traversal_ids_with_child_namespaces ON n
CREATE INDEX tmp_index_namespaces_empty_traversal_ids_with_root_namespaces ON namespaces USING btree (id) WHERE ((parent_id IS NULL) AND (traversal_ids = '{}'::integer[]));
+CREATE UNIQUE INDEX tmp_index_on_tmp_project_id_on_namespaces ON namespaces USING btree (tmp_project_id);
+
CREATE INDEX tmp_index_on_vulnerabilities_non_dismissed ON vulnerabilities USING btree (id) WHERE (state <> 2);
CREATE UNIQUE INDEX uniq_pkgs_deb_grp_architectures_on_distribution_id_and_name ON packages_debian_group_architectures USING btree (distribution_id, name);
@@ -27108,6 +27744,8 @@ CREATE UNIQUE INDEX vulnerability_feedback_unique_idx ON vulnerability_feedback
CREATE UNIQUE INDEX vulnerability_occurrence_pipelines_on_unique_keys ON vulnerability_occurrence_pipelines USING btree (occurrence_id, pipeline_id);
+CREATE INDEX vulnerability_occurrences_location_temp_index ON vulnerability_occurrences USING btree (id) WHERE (location IS NULL);
+
CREATE UNIQUE INDEX work_item_types_namespace_id_and_name_unique ON work_item_types USING btree (namespace_id, btrim(lower(name)));
ALTER INDEX analytics_cycle_analytics_issue_stage_events_pkey ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_00_pkey;
@@ -27238,6 +27876,520 @@ ALTER INDEX analytics_cycle_analytics_merge_request_stage_events_pkey ATTACH PAR
ALTER INDEX analytics_cycle_analytics_merge_request_stage_events_pkey ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_31_pkey;
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_000925dbd7;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_006f943df6;
+
+ALTER INDEX index_loose_foreign_keys_deleted_records_for_partitioned_query ATTACH PARTITION gitlab_partitions_static.index_01e3390fac;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_02749b504c;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_0287f5ba09;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_03aa30a758;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_055179c3ea;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_061fe00461;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_070cef72c3;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_08e3cfc564;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_09af45dd6f;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_0c153e2eae;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_0ca85f3d71;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_0d837a5dda;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_0f28a65451;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_10588dbff0;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_107e123e17;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_1230a7a402;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_142c4e7ea4;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_14e4fa1d7d;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_14f3645821;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_16627b455e;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_1a0388713a;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_1a349ed064;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_1af932a3c7;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_1b0ea30bdb;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_1f6c3faabe;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_1f8af04ed1;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_201c5ddbe9;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_20353089e0;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_206349925b;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_21db459e34;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_21e262390a;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_2208bd7d7f;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_223592b4a1;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_22acc9ab11;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_22ed8f01dd;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_234d38a657;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_23783dc748;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_241e9a574c;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_24ac321751;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_25e2aaee9b;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_2653e7eeb8;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_2745f5a388;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_27759556bc;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_27d7ad78d8;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_281840d2d1;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_296f64df5c;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_2ad4b4fdbc;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_2b7c0a294e;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_2c6422f668;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_2dfcdbe81e;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_2e1054b181;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_2e6991d05b;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_2f80c360c3;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_2fc271c673;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_2fcfd0dc70;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_3005c75335;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_3206c1e6af;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_3249505125;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_331eb67441;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_3640194b77;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_372160a706;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_38a538234e;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_39625b8a41;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_399dc06649;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_3a10b315c0;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_3c2a3a6ac9;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_3e6be332b7;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_41a1c3a4c6;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_435802dd01;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_436fa9ad5f;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_453a659cb6;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_46b989b294;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_47638677a3;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_4810ac88f5;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_491b4b749e;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_4a243772d7;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_4b1793a4c4;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_4b22560035;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_4c2645eef2;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_4c9d14f978;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_4d04210a95;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_4d4f2f7de6;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_4db5aa5872;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_4dead6f314;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_4e6ce1c371;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_4f2eb7a06b;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_4f6fc34e57;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_50c09f6e04;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_5111e3e7e7;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_52ea79bf8e;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_541cc045fc;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_551676e972;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_56281bfb73;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_5660b1b38e;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_59a8209ab6;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_59ce40fcc4;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_5a5f39d824;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_5b613b5fcf;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_5b944f308d;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_5bc2f32084;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_5c4053b63d;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_5db09170d4;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_5ee060202f;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_5f24f6ead2;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_5f96b344e2;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_5fb1867c41;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_5fe1d00845;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_60e3480f23;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_6137e27484;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_620fe77c99;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_625ed9e965;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_64e3a1dfa1;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_64eb4cf8bd;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_6580ecb2db;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_682eba05f6;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_69bdcf213e;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_6a39f6d5ac;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_6add8e74cf;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_6b1ce61c8f;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_6cfb391b86;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_6e6c2e6a1d;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_6ea423bbd1;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_6ec4c4afd4;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_6f4e0abe54;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_6fa47e1334;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_70c657954b;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_71c2b26944;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_72027c157f;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_739845f617;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_74addd1240;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_75dc81d1d7;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_765b0cd8db;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_77096a1dc6;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_77c6293242;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_7b7c85eceb;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_7da2307d2e;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_7ead2300ca;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_7ecb5b68b4;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_807671c4be;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_807fa83fc0;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_80c65daf20;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_81b9cf594f;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_82c675952c;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_83c5049b3e;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_83edf231b8;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_844abd2888;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_8464227c80;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_8685d7c69c;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_8688b40056;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_87d40fb9f9;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_88b40d6740;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_89c79afe5c;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_8a0fc3de4f;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_8b9f9a19a4;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_8fb48e72ce;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_9201b952a0;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_92c09e352b;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_9490e0e0b7;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_95a353f50b;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_971af9481e;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_9955b1dc59;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_9b8e89ae41;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_9ee83b068b;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_a1a9dc36c1;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_a2d9f185a5;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_a3feed3097;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_a6999c65c9;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_a6c68d16b2;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_a8276a450f;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_a88f20fc98;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_a9424aa392;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_a99cee1904;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_a9deff2159;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_aabc184267;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_ab22231a16;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_abbdf80ab1;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_adc159c3fe;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_aed7f7b10c;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_aee84adb5b;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_b1dda405af;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_b607012614;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_b7f21460bb;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_b83fe1306b;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_bc189e47ab;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_bca83177ef;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_bedd7e160b;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_bee2b94a80;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_c08e669dfa;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_c09bb66559;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_c119f5b92e;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_c17dae3605;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_c1cdd90d0d;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_c2b951bf20;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_c42b2e7eae;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_c435d904ce;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_c473921734;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_c546bb0736;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_c59cde6209;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_c66758baa7;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_c6ea8a0e26;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_c8c4219c0a;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_c971e6c5ce;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_c9b14a3d9f;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_cbb61ea269;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_cc0ba6343b;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_cd2b2939a4;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_cda41e106e;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_cfa4237c83;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_d01ea0126a;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_d0d285c264;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_d27b4c84e7;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_d2fe918e83;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_d35c969634;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_d6047ee813;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_d69c2485f4;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_d8fa9793ad;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_d9384b768d;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_dc571ba649;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_df62a8c50e;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_e1a4f994d8;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_e3d1fd5b19;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_e3d6234929;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_e54adf9acb;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_e6405afea0;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_e64588e276;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_e716b8ac3f;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_e73bc5ba6a;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_e8f3a327b2;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_ea0c2d3361;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_eb558957f0;
+
+ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_ec25d494e6;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_ed094a4f13;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_ee4c549a2d;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_ef6a48bd29;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_ef7be2ae94;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_f0cdd09a5e;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_f112fae8ac;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_f1c3d14cdc;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_f256d3f6a1;
+
+ALTER INDEX index_issue_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_f2848acfc7;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_f3d7d86e09;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_f47327ec1f;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_f6b0d458a3;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_f705dc8541;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_f76e8a5304;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_f86acdc2ff;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_f878aab8e3;
+
+ALTER INDEX index_issue_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_f902c261ce;
+
+ALTER INDEX index_merge_request_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_fbccc855cf;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_fbf2d3310b;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_fccbe45c32;
+
+ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_fee429223e;
+
+ALTER INDEX index_merge_request_stage_events_project_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_ff00c038cc;
+
+ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_ff39be5400;
+
+ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_ff8741d8d7;
+
ALTER INDEX loose_foreign_keys_deleted_records_pkey ATTACH PARTITION gitlab_partitions_static.loose_foreign_keys_deleted_records_1_pkey;
ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx10;
@@ -27496,7 +28648,9 @@ ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_p
ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_63_pkey;
-CREATE TRIGGER trigger_91dc388a5fe6 BEFORE INSERT OR UPDATE ON dep_ci_build_trace_sections FOR EACH ROW EXECUTE FUNCTION trigger_91dc388a5fe6();
+CREATE TRIGGER chat_names_loose_fk_trigger AFTER DELETE ON chat_names REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
+
+CREATE TRIGGER ci_runners_loose_fk_trigger AFTER DELETE ON ci_runners REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
CREATE TRIGGER trigger_delete_project_namespace_on_project_delete AFTER DELETE ON projects FOR EACH ROW WHEN ((old.project_namespace_id IS NOT NULL)) EXECUTE FUNCTION delete_associated_project_namespace();
@@ -27570,6 +28724,9 @@ ALTER TABLE ONLY project_pages_metadata
ALTER TABLE ONLY group_deletion_schedules
ADD CONSTRAINT fk_11e3ebfcdd FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY member_tasks
+ ADD CONSTRAINT fk_12816d4bbb FOREIGN KEY (member_id) REFERENCES members(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT fk_1302949740 FOREIGN KEY (last_edited_by_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -27648,9 +28805,6 @@ ALTER TABLE ONLY projects
ALTER TABLE ONLY ci_pipelines
ADD CONSTRAINT fk_262d4c2d19 FOREIGN KEY (auto_canceled_by_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-ALTER TABLE ONLY dep_ci_build_trace_sections
- ADD CONSTRAINT fk_264e112c66 FOREIGN KEY (section_name_id) REFERENCES dep_ci_build_trace_section_names(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_27548c6db3 FOREIGN KEY (hashed_storage_migrated_event_id) REFERENCES geo_hashed_storage_migrated_events(id) ON DELETE CASCADE;
@@ -27807,6 +28961,9 @@ ALTER TABLE ONLY application_settings
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_6a5165a692 FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
+ALTER TABLE ONLY namespaces
+ ADD CONSTRAINT fk_6a77f66919 FOREIGN KEY (tmp_project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_6ada82d42a FOREIGN KEY (container_repository_updated_event_id) REFERENCES geo_container_repository_updated_events(id) ON DELETE CASCADE;
@@ -28050,8 +29207,8 @@ ALTER TABLE ONLY identities
ALTER TABLE ONLY boards
ADD CONSTRAINT fk_ab0a250ff6 FOREIGN KEY (iteration_cadence_id) REFERENCES iterations_cadences(id) ON DELETE CASCADE;
-ALTER TABLE ONLY dep_ci_build_trace_sections
- ADD CONSTRAINT fk_ab7c104e26 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY member_tasks
+ ADD CONSTRAINT fk_ab636303dd FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_sources_pipelines
ADD CONSTRAINT fk_acd9737679 FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -28137,9 +29294,6 @@ ALTER TABLE ONLY design_management_versions
ALTER TABLE ONLY packages_packages
ADD CONSTRAINT fk_c188f0dba4 FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY geo_event_log
- ADD CONSTRAINT fk_c1f241c70d FOREIGN KEY (upload_deleted_event_id) REFERENCES geo_upload_deleted_events(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY analytics_cycle_analytics_project_stages
ADD CONSTRAINT fk_c3339bdfc9 FOREIGN KEY (stage_event_hash_id) REFERENCES analytics_cycle_analytics_stage_event_hashes(id) ON DELETE CASCADE;
@@ -28344,9 +29498,6 @@ ALTER TABLE ONLY cluster_agents
ALTER TABLE ONLY protected_tag_create_access_levels
ADD CONSTRAINT fk_f7dfda8c51 FOREIGN KEY (protected_tag_id) REFERENCES protected_tags(id) ON DELETE CASCADE;
-ALTER TABLE ONLY dep_ci_build_trace_section_names
- ADD CONSTRAINT fk_f8cd72cd26 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY ci_stages
ADD CONSTRAINT fk_fb57e6cc56 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
@@ -28545,9 +29696,6 @@ ALTER TABLE ONLY bulk_import_failures
ALTER TABLE ONLY group_wiki_repositories
ADD CONSTRAINT fk_rails_19755e374b FOREIGN KEY (shard_id) REFERENCES shards(id) ON DELETE RESTRICT;
-ALTER TABLE ONLY open_project_tracker_data
- ADD CONSTRAINT fk_rails_1987546e48 FOREIGN KEY (service_id) REFERENCES integrations(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY gpg_signatures
ADD CONSTRAINT fk_rails_19d4f1c6f9 FOREIGN KEY (gpg_key_subkey_id) REFERENCES gpg_key_subkeys(id) ON DELETE SET NULL;
@@ -29595,6 +30743,9 @@ ALTER TABLE ONLY atlassian_identities
ALTER TABLE ONLY serverless_domain_cluster
ADD CONSTRAINT fk_rails_c09009dee1 FOREIGN KEY (pages_domain_id) REFERENCES pages_domains(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_npm_metadata
+ ADD CONSTRAINT fk_rails_c0e5fce6f3 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY labels
ADD CONSTRAINT fk_rails_c1ac5161d8 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -29898,9 +31049,6 @@ ALTER TABLE ONLY snippet_repositories
ALTER TABLE ONLY elastic_reindexing_subtasks
ADD CONSTRAINT fk_rails_f2cc190164 FOREIGN KEY (elastic_reindexing_task_id) REFERENCES elastic_reindexing_tasks(id) ON DELETE CASCADE;
-ALTER TABLE ONLY ci_pipeline_chat_data
- ADD CONSTRAINT fk_rails_f300456b63 FOREIGN KEY (chat_name_id) REFERENCES chat_names(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY approval_project_rules_users
ADD CONSTRAINT fk_rails_f365da8250 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml
index b75f81dd075..23285fd0038 100644
--- a/doc/.vale/gitlab/Acronyms.yml
+++ b/doc/.vale/gitlab/Acronyms.yml
@@ -55,6 +55,7 @@ exceptions:
- FAQ
- FIFO
- FIPS
+ - FLAG
- FOSS
- FQDN
- FREE
@@ -140,6 +141,7 @@ exceptions:
- RPM
- RPS
- RSA
+ - RDS
- RSS
- RVM
- SAAS
diff --git a/doc/.vale/gitlab/British.yml b/doc/.vale/gitlab/British.yml
index 152723ead26..f724eb19fa9 100644
--- a/doc/.vale/gitlab/British.yml
+++ b/doc/.vale/gitlab/British.yml
@@ -19,6 +19,10 @@ swap:
analyse: analyze
annexe: annex
apologise: apologize
+ authorise: authorize
+ authorised: authorized
+ authorisation: authorization
+ authorising: authorizing
behaviour: behavior
busses: buses
calibre: caliber
diff --git a/doc/.vale/gitlab/Substitutions.yml b/doc/.vale/gitlab/Substitutions.yml
index e6c150fb8be..dde05b993ec 100644
--- a/doc/.vale/gitlab/Substitutions.yml
+++ b/doc/.vale/gitlab/Substitutions.yml
@@ -41,9 +41,15 @@ swap:
developer access: the Developer role
developer permission: the Developer role
developer permissions: the Developer role
+ guest access: the Guest role
+ guest permission: the Guest role
+ guest permissions: the Guest role
maintainer access: the Maintainer role
maintainer permission: the Maintainer role
maintainer permissions: the Maintainer role
owner access: the Owner role
owner permission: the Owner role
owner permissions: the Owner role
+ reporter access: the Reporter role
+ reporter permission: the Reporter role
+ reporter permissions: the Reporter role
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index d397a436ff9..df228e61278 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -45,8 +45,8 @@ autoscales
autoscaling
awardable
awardables
-Ayoa
Axios
+Ayoa
Azure
B-tree
backfilling
@@ -93,9 +93,9 @@ canonicalized
captcha
CentOS
Certbot
+chai
changeset
changesets
-chai
ChaosKube
chatbot
chatbots
@@ -150,6 +150,7 @@ denormalized
denormalizes
denormalizing
denylist
+denylisted
denylisting
denylists
deployer
@@ -186,6 +187,7 @@ downvotes
Dpl
Dreamweaver
Ecto
+ElastiCache
Elasticsearch
enablement
enqueued
@@ -683,8 +685,8 @@ triaged
triages
triaging
Trivy
-truthy
Truststore
+truthy
Twilio
Twitter
TypeScript
diff --git a/doc/administration/audit_event_streaming.md b/doc/administration/audit_event_streaming.md
new file mode 100644
index 00000000000..cee6cddbbf0
--- /dev/null
+++ b/doc/administration/audit_event_streaming.md
@@ -0,0 +1,70 @@
+---
+stage: Manage
+group: Compliance
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Audit event streaming **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332747) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available per group, ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. On GitLab.com, this feature is not available.
+You should not use this feature for production environments.
+
+Event streaming allows owners of top-level groups to set an HTTP endpoint to receive **all** audit events about the group, and its
+subgroups and projects.
+
+Top-level group owners can manage their audit logs in third-party systems such as Splunk, using the Splunk
+[HTTP Event Collector](https://docs.splunk.com/Documentation/Splunk/8.2.2/Data/UsetheHTTPEventCollector). Any service that can receive
+structured JSON data can be used as the endpoint.
+
+NOTE:
+GitLab can stream a single event more than once to the same destination. Use the `id` key in the payload to deduplicate incoming data.
+
+## Add a new event streaming destination
+
+WARNING:
+Event streaming destinations will receive **all** audit event data, which could include sensitive information. Make sure you trust the destination endpoint.
+
+To enable event streaming, a group owner must add a new event streaming destination using the `externalAuditEventDestinationCreate` mutation
+in the GraphQL API.
+
+```graphql
+mutation {
+ externalAuditEventDestinationCreate(input: { destinationUrl: "https://mydomain.io/endpoint/ingest", groupPath: "my-group" } ) {
+ errors
+ externalAuditEventDestination {
+ destinationUrl
+ group {
+ name
+ }
+ }
+ }
+}
+```
+
+Event streaming is enabled if:
+
+- The returned `errors` object is empty.
+- The API responds with `200 OK`.
+
+## List currently enabled streaming destinations
+
+Group owners can view a list of event streaming destinations at any time using the `externalAuditEventDesinations` query type.
+
+```graphql
+query {
+ group(fullPath: "my-group") {
+ id
+ externalAuditEventDestinations {
+ nodes {
+ destinationUrl
+ id
+ }
+ }
+ }
+}
+```
+
+If the resulting list is empty, then audit event streaming is not enabled for that group.
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index 572c341f2b2..2062016ef03 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -12,7 +12,10 @@ on a [paid plan](https://about.gitlab.com/pricing/).
GitLab system administrators can also take advantage of the logs located on the
file system. See [the logs system documentation](logs.md#audit_jsonlog) for more details.
-You can generate an [Audit report](audit_reports.md) of audit events.
+You can:
+
+- Generate an [audit report](audit_reports.md) of audit events.
+- [Stream audit events](audit_event_streaming.md) to an external endpoint.
## Overview
@@ -70,6 +73,17 @@ From there, you can see the following actions:
- Group changed visibility.
- User was added to group and with which [permissions](../user/permissions.md).
- User sign-in via [Group SAML](../user/group/saml_sso/index.md).
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8071) in GitLab 14.5, changes to the following
+ [group SAML](../user/group/saml_sso/index.md) configuration:
+ - Enabled status.
+ - Enforcing SSO-only authentication for web activity.
+ - Enforcing SSO-only authentication for Git and Dependency Proxy activity.
+ - Enforcing users to have dedicated group-managed accounts.
+ - Prohibiting outer forks.
+ - Identity provider SSO URL.
+ - Certificate fingerprint.
+ - Default membership role.
+ - SSO-SAML group sync configuration.
- Permissions changes of a user assigned to a group.
- Removed user from group.
- Project repository imported into group.
@@ -83,6 +97,7 @@ From there, you can see the following actions:
- 2FA enforcement or grace period changed.
- Roles allowed to create project changed.
- Group CI/CD variable added, removed, or protected status changed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30857) in GitLab 13.3.
+- Compliance framework created, updated, or deleted. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340649) in GitLab 14.6.
Group events can also be accessed via the [Group Audit Events API](../api/audit_events.md#group-audit-events)
@@ -186,9 +201,16 @@ successful sign-in events:
After upgrading from GitLab Free to a paid tier, successful sign-in events are the only Audit
Events visible in Audit Events views until more events are logged.
+### "Deleted User" events
+
+Audit events can be created for a user after the user is deleted. The user name associated with the event is set to
+"Deleted User" because the actual user name is unknowable. For example, if a deleted user's access to a project is
+removed automatically due to expiration, the audit event is created for "Deleted User". We are [investigating](https://gitlab.com/gitlab-org/gitlab/-/issues/343933)
+whether this is avoidable.
+
### Missing events
-Some events are not tracked in Audit Events. See the following
+Some events are not tracked in audit events. See the following
epics for more detail on which events are not being tracked, and our progress
on adding these events into GitLab:
@@ -196,10 +218,12 @@ on adding these events into GitLab:
- [Group settings and activity](https://gitlab.com/groups/gitlab-org/-/epics/475)
- [Instance-level settings and activity](https://gitlab.com/groups/gitlab-org/-/epics/476)
-Don't see the event you want in any of the epics linked above? You can use the **Audit Event
-Proposal** issue template to
-[create an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Audit%20Event%20Proposal)
-to request it, or you can [add it yourself](../development/audit_event_guide/).
+Don't see the event you want in any of the epics linked above? You can either:
+
+- Use the **Audit Event Proposal** issue template to
+ [create an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Audit%20Event%20Proposal) to
+ request it.
+- [Add it yourself](../development/audit_event_guide/).
### Disabled events
@@ -240,7 +264,7 @@ The search filters you can see depends on which audit level you are at.
| Scope (Instance level) | A specific group, project, or user that the action was scoped to. |
| Date range | Either via the date range buttons or pickers (maximum range of 31 days). Default is from the first day of the month to today's date. |
-![audit events](img/audit_log_v13_6.png)
+![audit events](img/audit_events_v14_5.png)
## Export to CSV **(PREMIUM SELF)**
@@ -251,7 +275,7 @@ Export to CSV allows customers to export the current filter view of your audit e
CSV file, which stores tabular data in plain text. The data provides a comprehensive view with respect to
audit events.
-To export the Audit Events to CSV:
+To export the audit events to CSV:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Monitoring > Audit Events**.
@@ -284,5 +308,5 @@ The first row contains the headers, which are listed in the following table alon
### Limitation
-The Audit Events CSV file is limited to a maximum of `100,000` events.
+The audit events CSV file is limited to a maximum of `100,000` events.
The remaining records are truncated when this limit is reached.
diff --git a/doc/administration/auth/atlassian.md b/doc/administration/auth/atlassian.md
index b58bbfa8eac..14c48231a3d 100644
--- a/doc/administration/auth/atlassian.md
+++ b/doc/administration/auth/atlassian.md
@@ -41,7 +41,7 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu
sudo -u git -H editor /home/git/gitlab/config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration) for initial settings to enable single sign-on and add `atlassian_oauth2` as an OAuth provider.
+1. See [Configure initial settings](../../integration/omniauth.md#configure-initial-settings) for initial settings to enable single sign-on and add `atlassian_oauth2` as an OAuth provider.
1. Add the provider configuration for Atlassian:
For Omnibus GitLab installations:
diff --git a/doc/administration/auth/authentiq.md b/doc/administration/auth/authentiq.md
index 835293ff500..19ee143a72a 100644
--- a/doc/administration/auth/authentiq.md
+++ b/doc/administration/auth/authentiq.md
@@ -27,7 +27,7 @@ Authentiq generates a Client ID and the accompanying Client Secret for you to us
sudo -u git -H editor /home/git/gitlab/config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration) for initial settings to enable single sign-on and add Authentiq as an OAuth provider.
+1. See [Configure initial settings](../../integration/omniauth.md#configure-initial-settings) for initial settings to enable single sign-on and add Authentiq as an OAuth provider.
1. Add the provider configuration for Authentiq:
diff --git a/doc/administration/auth/cognito.md b/doc/administration/auth/cognito.md
index 41e77c10e27..d137489a838 100644
--- a/doc/administration/auth/cognito.md
+++ b/doc/administration/auth/cognito.md
@@ -40,7 +40,7 @@ The following steps enable AWS Cognito as an authentication provider:
## Configure GitLab
-1. See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration) for initial settings.
+1. See [Configure initial settings](../../integration/omniauth.md#configure-initial-settings) for initial settings.
1. On your GitLab server, open the configuration file.
**For Omnibus installations**
@@ -88,4 +88,4 @@ Your sign-in page should now display a Cognito button below the regular sign-in
To begin the authentication process, click the icon, and AWS Cognito asks the user to sign in and authorize the GitLab application.
If successful, the user is redirected and signed in to your GitLab instance.
-For more information, see the [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration).
+For more information, see [Configure initial settings](../../integration/omniauth.md#configure-initial-settings).
diff --git a/doc/administration/auth/crowd.md b/doc/administration/auth/crowd.md
index f83710ef4c7..466e208a52e 100644
--- a/doc/administration/auth/crowd.md
+++ b/doc/administration/auth/crowd.md
@@ -36,7 +36,7 @@ this provider also allows Crowd authentication for Git-over-https requests.
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration)
+1. See [Configure initial settings](../../integration/omniauth.md#configure-initial-settings)
for initial settings.
1. Add the provider configuration:
@@ -84,7 +84,7 @@ could not authorize you from Crowd because invalid credentials
```
Ensure the Crowd users who need to sign in to GitLab are authorized to the
-[application](#configure-a-new-crowd-application) in the **Authorisation** step.
+[application](#configure-a-new-crowd-application) in the **Authorization** step.
This could be verified by trying "Authentication test" for Crowd (as of 2.11).
-![Example Crowd application authorisation configuration](img/crowd_application_authorisation.png)
+![Example Crowd application authorization configuration](img/crowd_application_authorisation.png)
diff --git a/doc/administration/auth/jwt.md b/doc/administration/auth/jwt.md
index b74b70ee8c0..26e523cb802 100644
--- a/doc/administration/auth/jwt.md
+++ b/doc/administration/auth/jwt.md
@@ -25,7 +25,7 @@ JWT will provide you with a secret key for you to use.
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration) for initial settings.
+1. See [Configure initial settings](../../integration/omniauth.md#configure-initial-settings) for initial settings.
1. Add the provider configuration.
For Omnibus GitLab:
diff --git a/doc/administration/auth/ldap/google_secure_ldap.md b/doc/administration/auth/ldap/google_secure_ldap.md
index e5af8e8256a..69f0bfdce4c 100644
--- a/doc/administration/auth/ldap/google_secure_ldap.md
+++ b/doc/administration/auth/ldap/google_secure_ldap.md
@@ -35,7 +35,7 @@ The steps below cover:
credentials' and 'Read user information'. Select 'Add LDAP Client'
NOTE:
- If you plan to use GitLab [LDAP Group Sync](index.md#group-sync)
+ If you plan to use GitLab [LDAP Group Sync](ldap_synchronization.md#group-sync)
, turn on 'Read group information'.
![Add LDAP Client Step 2](img/google_secure_ldap_add_step_2.png)
diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index 92815f10b92..9047cfae1e9 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -19,58 +19,52 @@ This integration works with most LDAP-compliant directory servers, including:
- Open LDAP.
- 389 Server.
-Users added through LDAP take a [licensed seat](../../../subscriptions/self_managed/index.md#billable-users).
+Users added through LDAP:
-## Security
+- Take a [licensed seat](../../../subscriptions/self_managed/index.md#billable-users).
+- Can authenticate with Git using either their GitLab username or their email and LDAP password,
+ even if password authentication for Git
+ [is disabled](../../../user/admin_area/settings/sign_in_restrictions.md#password-authentication-enabled).
-GitLab assumes that LDAP users:
+The LDAP DN is associated with existing GitLab users when:
-- Are not able to change their LDAP `mail`, `email`, or `userPrincipalName` attributes.
- An LDAP user allowed to change their email on the LDAP server can potentially
- [take over any account](#enable-ldap-sign-in-for-existing-gitlab-users)
- on your GitLab server.
-- Have unique email addresses. If not, it's possible for LDAP users with the same
- email address to share the same GitLab account.
+- The existing user signs in to GitLab with LDAP for the first time.
+- The LDAP email address is the primary email address of an existing GitLab user. If the LDAP email
+ attribute isn't found in the GitLab user database, a new user is created.
-We recommend against using LDAP integration if your LDAP users are
-allowed to change their `mail`, `email` or `userPrincipalName` attributes on
-the LDAP server, or share email addresses.
+If an existing GitLab user wants to enable LDAP sign-in for themselves, they should:
-### User deletion
+1. Check that their GitLab email address matches their LDAP email address.
+1. Sign in to GitLab by using their LDAP credentials.
-Users deleted from the LDAP server are immediately blocked from signing in
-to GitLab and [no longer consumes a
-license](../../../user/admin_area/moderate_users.md).
-However, there's an LDAP check cache time of one hour (which is
-[configurable](#adjust-ldap-user-sync-schedule) for GitLab Premium users).
-This means users already signed-in or who are using Git over SSH can access
-GitLab for up to one hour. Manually block the user in the GitLab Admin Area
-to immediately block all access.
+## Security
-## Git password authentication
+GitLab has multiple mechanisms to verify a user is still active in LDAP. If the user is no longer active in
+LDAP, they are placed in an `ldap_blocked` status and are signed out. They are unable to sign in using any authentication provider until they are
+reactivated in LDAP.
-LDAP-enabled users can authenticate with Git using their GitLab username or
-email and LDAP password, even if password authentication for Git is disabled
-in the application settings.
+Users are considered inactive in LDAP when they:
-## Enable LDAP sign-in for existing GitLab users
+- Are removed from the directory completely.
+- Reside outside the configured `base` DN or `user_filter` search.
+- Are marked as disabled or deactivated in Active Directory through the user account control attribute. This means attribute
+ `userAccountControl:1.2.840.113556.1.4.803` has bit 2 set.
-When a user signs in to GitLab with LDAP for the first time and their LDAP
-email address is the primary email address of an existing GitLab user, the
-LDAP DN is associated with the existing user. If the LDAP email attribute
-isn't found in the GitLab user database, a new user is created.
+Status is checked for all LDAP users:
-In other words, if an existing GitLab user wants to enable LDAP sign-in for
-themselves, they should check that their GitLab email address matches their
-LDAP email address, and then sign into GitLab by using their LDAP credentials.
+- When signing in using any authentication provider.
+- Once per hour for active web sessions or Git requests using tokens or SSH keys.
+- When performing Git over HTTP requests using LDAP username and password.
+- Once per day during [User Sync](ldap_synchronization.md#user-sync).
-## Google Secure LDAP
+### Security risks
-> Introduced in GitLab 11.9.
+You should only use LDAP integration if your LDAP users cannot:
-[Google Cloud Identity](https://cloud.google.com/identity/) provides a Secure
-LDAP service that can be configured with GitLab for authentication and group sync.
-See [Google Secure LDAP](google_secure_ldap.md) for detailed configuration instructions.
+- Change their `mail`, `email` or `userPrincipalName` attributes on the LDAP server. These
+ users can potentially take over any account on your GitLab server.
+- Share email addresses. LDAP users with the same email address can share the same GitLab
+ account.
## Configure LDAP
@@ -109,7 +103,6 @@ gitlab_rails['ldap_servers'] = {
'verify_certificates' => true,
'bind_dn' => '_the_full_dn_of_the_user_you_will_bind_with',
'password' => '_the_password_of_the_bind_user',
- 'verify_certificates' => true,
'tls_options' => {
'ca_file' => '',
'ssl_version' => '',
@@ -170,7 +163,7 @@ These configuration settings are available:
| `bind_dn` | The full DN of the user you bind with. | **{dotted-circle}** No | `'america\momo'` or `'CN=Gitlab,OU=Users,DC=domain,DC=com'` |
| `password` | The password of the bind user. | **{dotted-circle}** No | `'your_great_password'` |
| `encryption` | Encryption method. The `method` key is deprecated in favor of `encryption`. | **{check-circle}** Yes | `'start_tls'` or `'simple_tls'` or `'plain'` |
-| `verify_certificates` | Enables SSL certificate verification if encryption method is `start_tls` or `simple_tls`. Defaults to true. | **{dotted-circle}** No | boolean |
+| `verify_certificates` | Enables SSL certificate verification if encryption method is `start_tls` or `simple_tls`. If set to false, no validation of the LDAP server's SSL certificate is performed. Defaults to true. | **{dotted-circle}** No | boolean |
| `timeout` | Set a timeout, in seconds, for LDAP queries. This helps avoid blocking a request if the LDAP server becomes unresponsive. A value of `0` means there is no timeout. (default: `10`) | **{dotted-circle}** No | `10` or `30` |
| `active_directory` | This setting specifies if LDAP server is Active Directory LDAP server. For non-AD servers it skips the AD specific queries. If your LDAP server is not AD, set this to false. | **{dotted-circle}** No | boolean |
| `allow_username_or_email_login` | If enabled, GitLab ignores everything after the first `@` in the LDAP username submitted by the user on sign-in. If you are using `uid: 'userPrincipalName'` on ActiveDirectory you must disable this setting, because the userPrincipalName contains an `@`. | **{dotted-circle}** No | boolean |
@@ -266,7 +259,7 @@ For more information about `LDAP_MATCHING_RULE_IN_CHAIN` filters, see
[Search Filter Syntax](https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax).
Support for nested members in the user filter shouldn't be confused with
-[group sync nested groups](#supported-ldap-group-typesattributes) support.
+[group sync nested groups](ldap_synchronization.md#supported-ldap-group-typesattributes) support.
GitLab does not support the custom filter syntax used by OmniAuth LDAP.
@@ -347,7 +340,7 @@ sync, while also allowing your SAML identity provider to handle additional
checks like custom 2FA.
When LDAP web sign in is disabled, users don't see an **LDAP** tab on the sign-in page.
-This does not disable [using LDAP credentials for Git access](#git-password-authentication).
+This does not disable using LDAP credentials for Git access.
**Omnibus configuration**
@@ -458,26 +451,6 @@ If initially your LDAP configuration looked like:
1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-## Encryption
-
-### TLS server authentication
-
-`simple_tls` and `start_tls` are the two available encryption methods.
-
-For either encryption method, if setting `verify_certificates: false`, TLS
-encryption is established with the LDAP server before any LDAP-protocol data is
-exchanged but no validation of the LDAP server's SSL certificate is performed.
-
-### Limitations
-
-#### TLS client authentication
-
-Not implemented by `Net::LDAP`.
-
-You should disable anonymous LDAP authentication and enable simple or Simple Authentication
-and Security Layer (SASL) authentication. The TLS client authentication setting in your LDAP server
-cannot be mandatory and clients cannot be authenticated with the TLS protocol.
-
## Multiple LDAP servers **(PREMIUM SELF)**
With GitLab, you can configure multiple LDAP servers that your GitLab instance
@@ -528,342 +501,43 @@ If you configure multiple LDAP servers, use a unique naming convention for the
`label` section of each entry. That label is used as the display name of the tab
shown on the sign-in page.
-## User sync **(PREMIUM SELF)**
-
-Once per day, GitLab runs a worker to check and update GitLab
-users against LDAP.
-
-The process executes the following access checks:
-
-- Ensure the user is still present in LDAP.
-- If the LDAP server is Active Directory, ensure the user is active (not
- blocked/disabled state). This check is performed only if
- `active_directory: true` is set in the LDAP configuration.
-
-In Active Directory, a user is marked as disabled/blocked if the user
-account control attribute (`userAccountControl:1.2.840.113556.1.4.803`)
-has bit 2 set.
-
-<!-- vale gitlab.Spelling = NO -->
-
-For more information, see [Bitmask Searches in LDAP](https://ctovswild.com/2009/09/03/bitmask-searches-in-ldap/).
-
-<!-- vale gitlab.Spelling = YES -->
+## Disable anonymous LDAP authentication
-The user is set to an `ldap_blocked` state in GitLab if the previous conditions
-fail. This means the user cannot sign in or push or pull code.
+GitLab doesn't support TLS client authentication. Complete these steps on your LDAP server.
-The process also updates the following user information:
-
-- Email address
-- SSH public keys (if `sync_ssh_keys` is set)
-- Kerberos identity (if Kerberos is enabled)
-
-The LDAP sync process:
-
-- Updates existing users.
-- Creates new users on first sign in.
-
-### Adjust LDAP user sync schedule **(PREMIUM SELF)**
-
-By default, GitLab runs a worker once per day at 01:30 a.m. server time to
-check and update GitLab users against LDAP.
-
-You can manually configure LDAP user sync times by setting the
-following configuration values, in cron format. If needed, you can
-use a [crontab generator](http://www.crontabgenerator.com).
-The example below shows how to set LDAP user
-sync to run once every 12 hours at the top of the hour.
-
-**Omnibus installations**
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_rails['ldap_sync_worker_cron'] = "0 */12 * * *"
- ```
-
-1. [Reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-**Source installations**
-
-1. Edit `config/gitlab.yaml`:
-
- ```yaml
- cron_jobs:
- ldap_sync_worker_cron:
- "0 */12 * * *"
- ```
-
-1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
+1. Disable anonymous authentication.
+1. Enable one of the following authentication types:
+ - Simple authentication.
+ - Simple Authentication and Security Layer (SASL) authentication.
-## Group Sync **(PREMIUM SELF)**
+The TLS client authentication setting in your LDAP server cannot be mandatory and clients cannot be
+authenticated with the TLS protocol.
-If your LDAP supports the `memberof` property, when the user signs in for the
-first time GitLab triggers a sync for groups the user should be a member of.
-That way they don't have to wait for the hourly sync to be granted
-access to their groups and projects.
+## Deleting users
-A group sync process runs every hour on the hour, and `group_base` must be set
-in LDAP configuration for LDAP synchronizations based on group CN to work. This allows
-GitLab group membership to be automatically updated based on LDAP group members.
+Users deleted from the LDAP server:
-The `group_base` configuration should be a base LDAP 'container', such as an
-'organization' or 'organizational unit', that contains LDAP groups that should
-be available to GitLab. For example, `group_base` could be
-`ou=groups,dc=example,dc=com`. In the configuration file it looks like the
-following.
+- Are immediately blocked from signing in to GitLab.
+- [No longer consume a license](../../../user/admin_area/moderate_users.md).
-**Omnibus configuration**
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_rails['ldap_servers'] = {
- 'main' => {
- # snip...
- 'group_base' => 'ou=groups,dc=example,dc=com',
- }
- }
- ```
-
-1. [Apply your changes to GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure).
-
-**Source configuration**
-
-1. Edit `/home/git/gitlab/config/gitlab.yml`:
-
- ```yaml
- production:
- ldap:
- servers:
- main:
- # snip...
- group_base: ou=groups,dc=example,dc=com
- ```
-
-1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-To take advantage of group sync, group owners or maintainers must [create one
-or more LDAP group links](#add-group-links).
-
-### Add group links **(PREMIUM SELF)**
-
-For information on adding group links by using CNs and filters, refer to the
-[GitLab groups documentation](../../../user/group/index.md#manage-group-memberships-via-ldap).
-
-### Administrator sync **(PREMIUM SELF)**
-
-As an extension of group sync, you can automatically manage your global GitLab
-administrators. Specify a group CN for `admin_group` and all members of the
-LDAP group are given administrator privileges. The configuration looks
-like the following.
-
-NOTE:
-Administrators are not synced unless `group_base` is also
-specified alongside `admin_group`. Also, only specify the CN of the `admin_group`,
-as opposed to the full DN.
-Additionally, if an LDAP user has an `admin` role, but is not a member of the `admin_group`
-group, GitLab revokes their `admin` role when syncing.
-
-**Omnibus configuration**
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_rails['ldap_servers'] = {
- 'main' => {
- # snip...
- 'group_base' => 'ou=groups,dc=example,dc=com',
- 'admin_group' => 'my_admin_group',
- }
- }
- ```
+However, these users can continue to use Git with SSH until the next time the
+[LDAP check cache runs](ldap_synchronization.md#adjust-ldap-user-sync-schedule).
-1. [Apply your changes to GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure).
+To delete the account immediately, you can manually
+[block the user](../../../user/admin_area/moderate_users.md#block-a-user).
-**Source configuration**
-
-1. Edit `/home/git/gitlab/config/gitlab.yml`:
-
- ```yaml
- production:
- ldap:
- servers:
- main:
- # snip...
- group_base: ou=groups,dc=example,dc=com
- admin_group: my_admin_group
- ```
-
-1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-### Global group memberships lock **(PREMIUM SELF)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1793) in GitLab 12.0.
-
-"Lock memberships to LDAP synchronization" setting allows instance administrators
-to lock down user abilities to invite new members to a group.
-
-When enabled, the following applies:
-
-- Only administrator can manage memberships of any group including access levels.
-- Users are not allowed to share project with other groups or invite members to
- a project created in a group.
-
-To enable it, you must:
-
-1. [Configure LDAP](#configure-ldap).
-1. On the top bar, select **Menu > Admin**.
-1. On the left sidebar, select **Settings > General**.
-1. Expand the **Visibility and access controls** section.
-1. Ensure the **Lock memberships to LDAP synchronization** checkbox is selected.
-
-### Adjust LDAP group sync schedule **(PREMIUM SELF)**
-
-By default, GitLab runs a group sync process every hour, on the hour.
-The values shown are in cron format. If needed, you can use a
-[Crontab Generator](http://www.crontabgenerator.com).
-
-WARNING:
-Do not start the sync process too frequently as this
-could lead to multiple syncs running concurrently. This concern is primarily
-for installations with a large number of LDAP users. Review the
-[LDAP group sync benchmark metrics](#benchmarks) to see how
-your installation compares before proceeding.
-
-You can manually configure LDAP group sync times by setting the
-following configuration values. The example below shows how to set group
-sync to run once every two hours at the top of the hour.
-
-**Omnibus installations**
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_rails['ldap_group_sync_worker_cron'] = "0 */2 * * * *"
- ```
-
-1. [Reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-**Source installations**
-
-1. Edit `config/gitlab.yaml`:
-
- ```yaml
- cron_jobs:
- ldap_group_sync_worker_cron:
- "*/30 * * * *"
- ```
-
-1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-### External groups **(PREMIUM SELF)**
-
-Using the `external_groups` setting allows you to mark all users belonging
-to these groups as [external users](../../../user/permissions.md#external-users).
-Group membership is checked periodically through the `LdapGroupSync` background
-task.
-
-**Omnibus configuration**
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_rails['ldap_servers'] = {
- 'main' => {
- # snip...
- 'external_groups' => ['interns', 'contractors'],
- }
- }
- ```
-
-1. [Apply your changes to GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure).
-
-**Source configuration**
-
-1. Edit `config/gitlab.yaml`:
-
- ```yaml
- production:
- ldap:
- servers:
- main:
- # snip...
- external_groups: ['interns', 'contractors']
- ```
-
-1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-### Group sync technical details
-
-This section outlines what LDAP queries are executed and what behavior you
-can expect from group sync.
-
-Group member access are downgraded from a higher level if their LDAP group
-membership changes. For example, if a user the Owner role in a group and the
-next group sync reveals they should only have the Developer role, their
-access is adjusted accordingly. The only exception is if the user is the
-last owner in a group. Groups need at least one owner to fulfill
-administrative duties.
-
-#### Supported LDAP group types/attributes
-
-GitLab supports LDAP groups that use member attributes:
-
-- `member`
-- `submember`
-- `uniquemember`
-- `memberof`
-- `memberuid`
-
-This means group sync supports (at least) LDAP groups with the following object
-classes:
-
-- `groupOfNames`
-- `posixGroup`
-- `groupOfUniqueNames`
-
-Other object classes should work if members are defined as one of the
-mentioned attributes.
-
-Active Directory supports nested groups. Group sync recursively resolves
-membership if `active_directory: true` is set in the configuration file.
-
-##### Nested group memberships
-
-Nested group memberships are resolved only if the nested group
-is found in the configured `group_base`. For example, if GitLab sees a
-nested group with DN `cn=nested_group,ou=special_groups,dc=example,dc=com` but
-the configured `group_base` is `ou=groups,dc=example,dc=com`, `cn=nested_group`
-is ignored.
-
-#### Queries
-
-- Each LDAP group is queried a maximum of one time with base `group_base` and
- filter `(cn=<cn_from_group_link>)`.
-- If the LDAP group has the `memberuid` attribute, GitLab executes another
- LDAP query per member to obtain each user's full DN. These queries are
- executed with base `base`, scope 'base object', and a filter depending on
- whether `user_filter` is set. Filter may be `(uid=<uid_from_group>)` or a
- joining of `user_filter`.
-
-#### Benchmarks
+## Google Secure LDAP
-Group sync was written to be as performant as possible. Data is cached, database
-queries are optimized, and LDAP queries are minimized. The last benchmark run
-revealed the following metrics:
+> Introduced in GitLab 11.9.
-For 20,000 LDAP users, 11,000 LDAP groups, and 1,000 GitLab groups with 10
-LDAP group links each:
+[Google Cloud Identity](https://cloud.google.com/identity/) provides a Secure
+LDAP service that can be configured with GitLab for authentication and group sync.
+See [Google Secure LDAP](google_secure_ldap.md) for detailed configuration instructions.
-- Initial sync (no existing members assigned in GitLab) took 1.8 hours
-- Subsequent syncs (checking membership, no writes) took 15 minutes
+## Synchronize users and groups
-These metrics are meant to provide a baseline and performance may vary based on
-any number of factors. This benchmark was extreme and most instances don't
-have near this many users or groups. Disk speed, database performance,
-network and LDAP server response time affects these metrics.
+For more information on synchronizing users and groups between LDAP and GitLab, see
+[LDAP synchronization](ldap_synchronization.md).
## Troubleshooting
diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md
index 4757725d0bd..aa40060c4c1 100644
--- a/doc/administration/auth/ldap/ldap-troubleshooting.md
+++ b/doc/administration/auth/ldap/ldap-troubleshooting.md
@@ -229,7 +229,7 @@ ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt -b "$ba
#### Sync all users **(PREMIUM SELF)**
-The output from a manual [user sync](index.md#user-sync) can show you what happens when
+The output from a manual [user sync](ldap_synchronization.md#user-sync) can show you what happens when
GitLab tries to sync its users against LDAP. Enter the [rails console](#rails-console)
and then run:
@@ -239,8 +239,7 @@ Rails.logger.level = Logger::DEBUG
LdapSyncWorker.new.perform
```
-Next, [learn how to read the
-output](#example-console-output-after-a-user-sync).
+Next, [learn how to read the output](#example-console-output-after-a-user-sync).
##### Example console output after a user sync **(PREMIUM SELF)**
@@ -342,9 +341,8 @@ LDAP group sync, but for some reason it's not happening. There are several
things to check to debug the situation.
- Ensure LDAP configuration has a `group_base` specified.
- [This configuration](index.md#group-sync) is required for group sync to work properly.
-- Ensure the correct [LDAP group link is added to the GitLab
- group](index.md#add-group-links).
+ [This configuration](ldap_synchronization.md#group-sync) is required for group sync to work properly.
+- Ensure the correct [LDAP group link is added to the GitLab group](ldap_synchronization.md#add-group-links).
- Check that the user has an LDAP identity:
1. Sign in to GitLab as an administrator user.
1. On the top bar, select **Menu > Admin**.
@@ -354,7 +352,7 @@ things to check to debug the situation.
1. Select the **Identities** tab. There should be an LDAP identity with
an LDAP DN as the 'Identifier'. If not, this user hasn't signed in with
LDAP yet and must do so first.
-- You've waited an hour or [the configured interval](index.md#adjust-ldap-group-sync-schedule) for
+- You've waited an hour or [the configured interval](ldap_synchronization.md#adjust-ldap-group-sync-schedule) for
the group to sync. To speed up the process, either go to the GitLab group **Group information > Members**
and press **Sync now** (sync one group) or [run the group sync Rake task](../../raketasks/ldap.md#run-a-group-sync)
(sync all groups).
@@ -366,8 +364,7 @@ the rails console.
1. Choose a GitLab group to test with. This group should have an LDAP group link
already configured.
1. [Enable debug logging, find the above GitLab group, and sync it with LDAP](#sync-one-group).
-1. Look through the output of the sync. See [example log
- output](#example-console-output-after-a-group-sync)
+1. Look through the output of the sync. See [example log output](#example-console-output-after-a-group-sync)
for how to read the output.
1. If you still aren't able to see why the user isn't being added, [query the LDAP group directly](#query-a-group-in-ldap)
to see what members are listed.
@@ -377,20 +374,20 @@ the rails console.
#### Administrator privileges not granted
-When [Administrator sync](index.md#administrator-sync) has been configured
+When [Administrator sync](ldap_synchronization.md#administrator-sync) has been configured
but the configured users aren't granted the correct administrator privileges, confirm
the following are true:
-- A [`group_base` is also configured](index.md#group-sync).
+- A [`group_base` is also configured](ldap_synchronization.md#group-sync).
- The configured `admin_group` in the `gitlab.rb` is a CN, rather than a DN or an array.
- This CN falls under the scope of the configured `group_base`.
- The members of the `admin_group` have already signed into GitLab with their LDAP
credentials. GitLab only grants the Administrator role to the users whose
accounts are already connected to LDAP.
-If all the above are true and the users are still not getting access, [run a manual
-group sync](#sync-all-groups) in the rails console and [look through the
-output](#example-console-output-after-a-group-sync) to see what happens when
+If all the above are true and the users are still not getting access,
+[run a manual group sync](#sync-all-groups) in the rails console and
+[look through the output](#example-console-output-after-a-group-sync) to see what happens when
GitLab syncs the `admin_group`.
#### Sync all groups
@@ -399,7 +396,7 @@ NOTE:
To sync all groups manually when debugging is unnecessary,
[use the Rake task](../../raketasks/ldap.md#run-a-group-sync) instead.
-The output from a manual [group sync](index.md#group-sync) can show you what happens
+The output from a manual [group sync](ldap_synchronization.md#group-sync) can show you what happens
when GitLab syncs its LDAP group memberships against LDAP.
```ruby
@@ -494,7 +491,7 @@ this line indicates the sync is finished:
Finished syncing admin users for 'ldapmain' provider
```
-If [administrator sync](index.md#administrator-sync) is not configured, you see a message
+If [administrator sync](ldap_synchronization.md#administrator-sync) is not configured, you see a message
stating as such:
```shell
@@ -583,6 +580,25 @@ end
You can then [run a UserSync](#sync-all-users) **(PREMIUM SELF)** to sync the latest DN
for each of these users.
+## Expired license causes errors with multiple LDAP servers
+
+Using [multiple LDAP servers](index.md#multiple-ldap-servers) requires a valid license. An expired
+license can cause:
+
+- `502` errors in the web interface.
+- The following error in logs (the actual strategy name depends on the name configured in `/etc/gitlab/gitlab.rb`):
+
+ ```plaintext
+ Could not find a strategy with name `Ldapsecondary'. Please ensure it is required or explicitly set it using the :strategy_class option. (Devise::OmniAuth::StrategyNotFound)
+ ```
+
+To resolve this error, you must apply a new license to the GitLab instance without the web interface:
+
+1. Remove or comment out the GitLab configuration lines for all non-primary LDAP servers.
+1. [Reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) so that it temporarily uses only one LDAP server.
+1. Enter the [Rails console and add the license key](../../troubleshooting/gitlab_rails_cheat_sheet.md#add-a-license-through-the-console).
+1. Re-enable the additional LDAP servers in the GitLab configuration and reconfigure GitLab again.
+
## Debugging Tools
### LDAP check
@@ -610,8 +626,7 @@ If a user account is blocked or unblocked due to the LDAP configuration, a
message is [logged to `application.log`](../../logs.md#applicationlog).
If there is an unexpected error during an LDAP lookup (configuration error,
-timeout), the sign-in is rejected and a message is [logged to
-`production.log`](../../logs.md#productionlog).
+timeout), the sign-in is rejected and a message is [logged to `production.log`](../../logs.md#productionlog).
### ldapsearch
diff --git a/doc/administration/auth/ldap/ldap_synchronization.md b/doc/administration/auth/ldap/ldap_synchronization.md
new file mode 100644
index 00000000000..2673a8374ec
--- /dev/null
+++ b/doc/administration/auth/ldap/ldap_synchronization.md
@@ -0,0 +1,349 @@
+---
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# LDAP synchronization **(PREMIUM SELF)**
+
+If you have [configured LDAP to work with GitLab](index.md), GitLab can automatically synchronize
+users and groups. This process updates user and group information.
+
+You can change when synchronization occurs.
+
+## User sync
+
+Once per day, GitLab runs a worker to check and update GitLab
+users against LDAP.
+
+The process executes the following access checks:
+
+- Ensure the user is still present in LDAP.
+- If the LDAP server is Active Directory, ensure the user is active (not
+ blocked/disabled state). This check is performed only if
+ `active_directory: true` is set in the LDAP configuration.
+
+In Active Directory, a user is marked as disabled/blocked if the user
+account control attribute (`userAccountControl:1.2.840.113556.1.4.803`)
+has bit 2 set.
+
+<!-- vale gitlab.Spelling = NO -->
+
+For more information, see [Bitmask Searches in LDAP](https://ctovswild.com/2009/09/03/bitmask-searches-in-ldap/).
+
+<!-- vale gitlab.Spelling = YES -->
+
+The user is set to an `ldap_blocked` state in GitLab if the previous conditions
+fail. This means the user cannot sign in or push or pull code.
+
+The process also updates the following user information:
+
+- Email address
+- SSH public keys (if `sync_ssh_keys` is set)
+- Kerberos identity (if Kerberos is enabled)
+
+The LDAP sync process:
+
+- Updates existing users.
+- Creates new users on first sign in.
+
+### Adjust LDAP user sync schedule
+
+By default, GitLab runs a worker once per day at 01:30 a.m. server time to
+check and update GitLab users against LDAP.
+
+You can manually configure LDAP user sync times by setting the
+following configuration values, in cron format. If needed, you can
+use a [crontab generator](http://www.crontabgenerator.com).
+The example below shows how to set LDAP user
+sync to run once every 12 hours at the top of the hour.
+
+**Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['ldap_sync_worker_cron'] = "0 */12 * * *"
+ ```
+
+1. [Reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+**Source installations**
+
+1. Edit `config/gitlab.yaml`:
+
+ ```yaml
+ cron_jobs:
+ ldap_sync_worker_cron:
+ "0 */12 * * *"
+ ```
+
+1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
+
+## Group sync
+
+If your LDAP supports the `memberof` property, when the user signs in for the
+first time GitLab triggers a sync for groups the user should be a member of.
+That way they don't have to wait for the hourly sync to be granted
+access to their groups and projects.
+
+A group sync process runs every hour on the hour, and `group_base` must be set
+in LDAP configuration for LDAP synchronizations based on group CN to work. This allows
+GitLab group membership to be automatically updated based on LDAP group members.
+
+The `group_base` configuration should be a base LDAP 'container', such as an
+'organization' or 'organizational unit', that contains LDAP groups that should
+be available to GitLab. For example, `group_base` could be
+`ou=groups,dc=example,dc=com`. In the configuration file it looks like the
+following.
+
+**Omnibus configuration**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['ldap_servers'] = {
+ 'main' => {
+ # snip...
+ 'group_base' => 'ou=groups,dc=example,dc=com',
+ }
+ }
+ ```
+
+1. [Apply your changes to GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
+**Source configuration**
+
+1. Edit `/home/git/gitlab/config/gitlab.yml`:
+
+ ```yaml
+ production:
+ ldap:
+ servers:
+ main:
+ # snip...
+ group_base: ou=groups,dc=example,dc=com
+ ```
+
+1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
+
+To take advantage of group sync, group owners or maintainers must [create one
+or more LDAP group links](#add-group-links).
+
+### Add group links
+
+For information on adding group links by using CNs and filters, refer to the
+[GitLab groups documentation](../../../user/group/index.md#manage-group-memberships-via-ldap).
+
+### Administrator sync
+
+As an extension of group sync, you can automatically manage your global GitLab
+administrators. Specify a group CN for `admin_group` and all members of the
+LDAP group are given administrator privileges. The configuration looks
+like the following.
+
+NOTE:
+Administrators are not synced unless `group_base` is also
+specified alongside `admin_group`. Also, only specify the CN of the `admin_group`,
+as opposed to the full DN.
+Additionally, if an LDAP user has an `admin` role, but is not a member of the `admin_group`
+group, GitLab revokes their `admin` role when syncing.
+
+**Omnibus configuration**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['ldap_servers'] = {
+ 'main' => {
+ # snip...
+ 'group_base' => 'ou=groups,dc=example,dc=com',
+ 'admin_group' => 'my_admin_group',
+ }
+ }
+ ```
+
+1. [Apply your changes to GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
+**Source configuration**
+
+1. Edit `/home/git/gitlab/config/gitlab.yml`:
+
+ ```yaml
+ production:
+ ldap:
+ servers:
+ main:
+ # snip...
+ group_base: ou=groups,dc=example,dc=com
+ admin_group: my_admin_group
+ ```
+
+1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
+
+### Global group memberships lock
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1793) in GitLab 12.0.
+
+"Lock memberships to LDAP synchronization" setting allows instance administrators
+to lock down user abilities to invite new members to a group.
+
+When enabled, the following applies:
+
+- Only administrator can manage memberships of any group including access levels.
+- Users are not allowed to share project with other groups or invite members to
+ a project created in a group.
+
+To enable it, you must:
+
+1. [Configure LDAP](index.md#configure-ldap).
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Settings > General**.
+1. Expand the **Visibility and access controls** section.
+1. Ensure the **Lock memberships to LDAP synchronization** checkbox is selected.
+
+### Adjust LDAP group sync schedule
+
+By default, GitLab runs a group sync process every hour, on the hour.
+The values shown are in cron format. If needed, you can use a
+[Crontab Generator](http://www.crontabgenerator.com).
+
+WARNING:
+Do not start the sync process too frequently as this
+could lead to multiple syncs running concurrently. This concern is primarily
+for installations with a large number of LDAP users. Review the
+[LDAP group sync benchmark metrics](#benchmarks) to see how
+your installation compares before proceeding.
+
+You can manually configure LDAP group sync times by setting the
+following configuration values. The example below shows how to set group
+sync to run once every two hours at the top of the hour.
+
+**Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['ldap_group_sync_worker_cron'] = "0 */2 * * * *"
+ ```
+
+1. [Reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+**Source installations**
+
+1. Edit `config/gitlab.yaml`:
+
+ ```yaml
+ cron_jobs:
+ ldap_group_sync_worker_cron:
+ "*/30 * * * *"
+ ```
+
+1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
+
+### External groups
+
+Using the `external_groups` setting allows you to mark all users belonging
+to these groups as [external users](../../../user/permissions.md#external-users).
+Group membership is checked periodically through the `LdapGroupSync` background
+task.
+
+**Omnibus configuration**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['ldap_servers'] = {
+ 'main' => {
+ # snip...
+ 'external_groups' => ['interns', 'contractors'],
+ }
+ }
+ ```
+
+1. [Apply your changes to GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
+**Source configuration**
+
+1. Edit `config/gitlab.yaml`:
+
+ ```yaml
+ production:
+ ldap:
+ servers:
+ main:
+ # snip...
+ external_groups: ['interns', 'contractors']
+ ```
+
+1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
+
+### Group sync technical details
+
+This section outlines what LDAP queries are executed and what behavior you
+can expect from group sync.
+
+Group member access are downgraded from a higher level if their LDAP group
+membership changes. For example, if a user the Owner role in a group and the
+next group sync reveals they should only have the Developer role, their
+access is adjusted accordingly. The only exception is if the user is the
+last owner in a group. Groups need at least one owner to fulfill
+administrative duties.
+
+#### Supported LDAP group types/attributes
+
+GitLab supports LDAP groups that use member attributes:
+
+- `member`
+- `submember`
+- `uniquemember`
+- `memberof`
+- `memberuid`
+
+This means group sync supports (at least) LDAP groups with the following object
+classes:
+
+- `groupOfNames`
+- `posixGroup`
+- `groupOfUniqueNames`
+
+Other object classes should work if members are defined as one of the
+mentioned attributes.
+
+Active Directory supports nested groups. Group sync recursively resolves
+membership if `active_directory: true` is set in the configuration file.
+
+##### Nested group memberships
+
+Nested group memberships are resolved only if the nested group
+is found in the configured `group_base`. For example, if GitLab sees a
+nested group with DN `cn=nested_group,ou=special_groups,dc=example,dc=com` but
+the configured `group_base` is `ou=groups,dc=example,dc=com`, `cn=nested_group`
+is ignored.
+
+#### Queries
+
+- Each LDAP group is queried a maximum of one time with base `group_base` and
+ filter `(cn=<cn_from_group_link>)`.
+- If the LDAP group has the `memberuid` attribute, GitLab executes another
+ LDAP query per member to obtain each user's full DN. These queries are
+ executed with base `base`, scope 'base object', and a filter depending on
+ whether `user_filter` is set. Filter may be `(uid=<uid_from_group>)` or a
+ joining of `user_filter`.
+
+#### Benchmarks
+
+Group sync was written to be as performant as possible. Data is cached, database
+queries are optimized, and LDAP queries are minimized. The last benchmark run
+revealed the following metrics:
+
+For 20,000 LDAP users, 11,000 LDAP groups, and 1,000 GitLab groups with 10
+LDAP group links each:
+
+- Initial sync (no existing members assigned in GitLab) took 1.8 hours
+- Subsequent syncs (checking membership, no writes) took 15 minutes
+
+These metrics are meant to provide a baseline and performance may vary based on
+any number of factors. This benchmark was extreme and most instances don't
+have near this many users or groups. Disk speed, database performance,
+network and LDAP server response time affects these metrics.
diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md
index 12729f2050b..b8c443ae4d4 100644
--- a/doc/administration/auth/oidc.md
+++ b/doc/administration/auth/oidc.md
@@ -27,7 +27,7 @@ The OpenID Connect provides you with a client's details and secret for you to us
sudo -u git -H editor config/gitlab.yml
```
- See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration) for initial settings.
+ See [Configure initial settings](../../integration/omniauth.md#configure-initial-settings) for initial settings.
1. Add the provider configuration.
@@ -40,7 +40,7 @@ The OpenID Connect provides you with a client's details and secret for you to us
'icon' => '<custom_provider_icon>',
'args' => {
'name' => 'openid_connect',
- 'scope' => ['openid','profile'],
+ 'scope' => ['openid','profile','email'],
'response_type' => 'code',
'issuer' => '<your_oidc_url>',
'discovery' => true,
@@ -65,7 +65,7 @@ The OpenID Connect provides you with a client's details and secret for you to us
icon: '<custom_provider_icon>',
args: {
name: 'openid_connect',
- scope: ['openid','profile'],
+ scope: ['openid','profile','email'],
response_type: 'code',
issuer: '<your_oidc_url>',
discovery: true,
@@ -228,7 +228,7 @@ Azure B2C [offers two ways of defining the business logic for logging in a user]
While cumbersome to configure, custom policies are required because
standard Azure B2C user flows [do not send the OpenID `email` claim](https://github.com/MicrosoftDocs/azure-docs/issues/16566). In
-other words, they do not work with the [`allow_single_sign_on` or `auto_link_user` parameters](../../integration/omniauth.md#initial-omniauth-configuration).
+other words, they do not work with the [`allow_single_sign_on` or `auto_link_user` parameters](../../integration/omniauth.md#configure-initial-settings).
With a standard Azure B2C policy, GitLab cannot create a new account or
link to an existing one with an email address.
diff --git a/doc/administration/cicd.md b/doc/administration/cicd.md
index 89fc31822ee..d53290f1d5d 100644
--- a/doc/administration/cicd.md
+++ b/doc/administration/cicd.md
@@ -7,22 +7,18 @@ type: howto
# GitLab CI/CD instance configuration **(FREE SELF)**
-GitLab CI/CD is enabled by default in all new projects on an instance. You can configure
-the instance to have [GitLab CI/CD disabled by default](#disable-gitlab-cicd-in-new-projects)
-in new projects.
-
-You can still choose to [enable GitLab CI/CD in individual projects](../ci/enable_or_disable_ci.md#enable-cicd-in-a-project)
-at any time.
+GitLab administrators can manage the GitLab CI/CD configuration for their instance.
## Disable GitLab CI/CD in new projects
-You can set GitLab CI/CD to be disabled by default in all new projects by modifying the settings in:
+GitLab CI/CD is enabled by default in all new projects on an instance. You can set
+CI/CD to be disabled by default in new projects by modifying the settings in:
- `gitlab.yml` for source installations.
- `gitlab.rb` for Omnibus GitLab installations.
Existing projects that already had CI/CD enabled are unchanged. Also, this setting only changes
-the project default, so project owners can still enable CI/CD in the project settings.
+the project default, so project owners [can still enable CI/CD in the project settings](../ci/enable_or_disable_ci.md#enable-cicd-in-a-project).
For installations from source:
@@ -62,6 +58,19 @@ For Omnibus GitLab installations:
sudo gitlab-ctl reconfigure
```
+## Set the `needs:` job limit **(FREE SELF)**
+
+The maximum number of jobs that can be defined in `needs:` defaults to 50.
+
+A GitLab administrator with [access to the GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session)
+can choose a custom limit. For example, to set the limit to `100`:
+
+```ruby
+Plan.default.actual_limits.update!(ci_needs_size_limit: 100)
+```
+
+To disable directed acyclic graphs (DAG), set the limit to `0`.
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/administration/clusters/kas.md b/doc/administration/clusters/kas.md
index 226710a8911..93b24007de8 100644
--- a/doc/administration/clusters/kas.md
+++ b/doc/administration/clusters/kas.md
@@ -10,7 +10,7 @@ The Kubernetes Agent Server (KAS) is a GitLab backend service dedicated to
managing [Kubernetes Agents](../../user/clusters/agent/index.md).
The KAS is already installed and available in GitLab.com under `wss://kas.gitlab.com`.
-See [how to use GitLab.com's KAS](../../user/clusters/agent/index.md#set-up-the-kubernetes-agent-server).
+See [how to use GitLab.com's KAS](../../user/clusters/agent/install/index.md#set-up-the-kubernetes-agent-server).
This document describes how to install a KAS for GitLab self-managed instances.
## Installation options
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index 1761af1ffa1..a05495c024e 100644
--- a/doc/administration/compliance.md
+++ b/doc/administration/compliance.md
@@ -6,29 +6,81 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Compliance features **(FREE)**
-You can configure the following GitLab features to help ensure that your GitLab
-instance meets common compliance standards. Click a feature name for additional
-documentation.
-
-The [security features](../security/index.md) in GitLab may also help you meet
-relevant compliance standards.
-
-| Feature | GitLab tier | GitLab SaaS | Product level |
-|----------|:-----------:|:-----------:|:-------------:|
-|**[Restrict SSH Keys](../security/ssh_keys_restrictions.md)**<br>Control the technology and key length of SSH keys used to access GitLab. | Free+ | **{dotted-circle}** No | Instance |
-|**[Granular user roles and flexible permissions](../user/permissions.md)**<br>Manage access and permissions with five different user roles and settings for external users. Set permissions according to people's role, rather than either read or write access to a repository. Don't share the source code with people that only need access to the issue tracker. | Free+ | **{check-circle}** Yes | Instance, Group, Project |
-|**[Generate reports on permission levels of users](../user/admin_area/index.md#user-permission-export)**<br>Administrators can generate a report listing all users' access permissions for groups and projects in the instance. | Premium+ | **{dotted-circle}** No | Instance |
-|**[Enforce TOS acceptance](../user/admin_area/settings/terms.md)**<br>Enforce your users accepting new terms of service by blocking GitLab traffic. | Free+ | **{dotted-circle}** No | Instance |
-|**[Email all users of a project, group, or entire server](../tools/email.md)**<br>An administrator can email groups of users based on project or group membership, or email everyone using the GitLab instance. This is great for scheduled maintenance or upgrades. | Premium+ | **{dotted-circle}** No | Instance |
-|**[Omnibus package supports log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-forwarding)**<br>Forward your logs to a central system. | Premium+ | **{dotted-circle}** No | Instance |
-|**[Lock project membership to group](../user/group/index.md#prevent-members-from-being-added-to-a-group)**<br>Group owners can prevent new members from being added to projects within a group. | Premium+ | **{check-circle}** Yes | Group |
-|**[LDAP group sync](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition gives administrators the ability to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your product, not configuring your tools. | Premium+ | **{dotted-circle}** No | Instance |
-|**[LDAP group sync filters](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition Premium gives more flexibility to synchronize with LDAP based on filters, meaning you can leverage LDAP attributes to map GitLab permissions. | Premium+ | **{dotted-circle}** No | Instance |
-|**[Audit events](audit_events.md)**<br>To maintain the integrity of your code, GitLab Enterprise Edition Premium gives administrators the ability to view any modifications made within the GitLab server in an advanced audit events system, so you can control, analyze, and track every change. | Premium+ | **{check-circle}** Yes | Instance, Group, Project |
-|**[Auditor users](auditor_users.md)**<br>Auditor users are users who are given read-only access to all projects, groups, and other resources on the GitLab instance. | Premium+ | **{dotted-circle}** No | Instance |
-|**[Credentials inventory](../user/admin_area/credentials_inventory.md)**<br>With a credentials inventory, GitLab administrators can keep track of the credentials used by all of the users in their GitLab instance. | Ultimate | **{dotted-circle}** No | Instance |
-|**Separation of Duties using [Protected branches](../user/project/protected_branches.md#require-code-owner-approval-on-a-protected-branch) and [custom CI Configuration Paths](../ci/pipelines/settings.md#specify-a-custom-cicd-configuration-file)**<br> GitLab Premium users can leverage the GitLab cross-project YAML configurations to define deployers of code and developers of code. View the [Separation of Duties Deploy Project](https://gitlab.com/guided-explorations/separation-of-duties-deploy/blob/master/README.md) and [Separation of Duties Project](https://gitlab.com/guided-explorations/separation-of-duties/blob/master/README.md) to see how to use this set up to define these roles. | Premium+ | **{check-circle}** Yes | Project |
-|**[Compliance frameworks](../user/project/settings/index.md#compliance-frameworks)**<br>Create a custom compliance framework at the group level to describe the type of compliance requirements any child project needs to follow. | Premium+ | **{check-circle}** Yes | Group |
-|**[Compliance pipelines](../user/project/settings/index.md#compliance-pipeline-configuration)**<br>Define a pipeline configuration to run for any projects with a given compliance framework. | Ultimate | **{check-circle}** Yes | Group |
-|**[Compliance report](../user/compliance/compliance_report/index.md)**<br>Quickly get visibility into the compliance posture of your organization. | Ultimate | **{check-circle}** Yes | Group |
-|**[External Status Checks](../user/project/merge_requests/status_checks.md)**<br>Interface with third party systems you already use during development to ensure you remain compliant. | Ultimate | **{check-circle}** Yes | Project |
+These GitLab features can help ensure that your GitLab instance meets common compliance standards. For more information
+about compliance management, see the compliance management [solutions page](https://about.gitlab.com/solutions/compliance/).
+
+The [security features](../security/index.md) in GitLab may also help you meet relevant compliance standards.
+
+## Policy management
+
+Organizations have unique policy requirements, either due to organizational standards or mandates from regulatory bodies.
+The following features help you define rules and policies to adhere to workflow requirements, separation of duties, and
+secure supply chain best practices:
+
+- [**Credentials inventory**](../user/admin_area/credentials_inventory.md) (for instances): With a credentials inventory,
+ GitLab administrators can keep track of the credentials used by all of the users in their GitLab instance.
+- [**Granular user roles and flexible permissions**](../user/permissions.md) (for instances, groups, and projects): Manage
+ access and permissions with five different user roles and settings for external users. Set permissions according to people's
+ role, rather than either read or write access to a repository. Don't share the source code with people that only need
+ access to the issue tracker.
+- [**Merge request approvals**](../user/project/merge_requests/approvals/index.md) (for instances, groups, and projects):
+ Configure approvals required for merge requests.
+- [**Push rules**](../push_rules/push_rules.md) (for instances, groups, and projects): Control pushes to your
+ repositories.
+- Separation of duties using [**protected branches**](../user/project/protected_branches.md#require-code-owner-approval-on-a-protected-branch)
+ and [**custom CI/CD configuration paths**](../ci/pipelines/settings.md#specify-a-custom-cicd-configuration-file) (for projects):
+ Users can leverage the GitLab cross-project YAML configurations to define deployers of code and developers of code.
+ See how to use this setup to define these roles in:
+ - The [Separation of Duties deploy project](https://gitlab.com/guided-explorations/separation-of-duties-deploy/blob/master/README.md).
+ - The [Separation of Duties project](https://gitlab.com/guided-explorations/separation-of-duties/blob/master/README.md).
+
+## Compliant workflow automation
+
+It is important for compliance teams to be confident that their controls and requirements are set up correctly, but also that they _stay_ set up correctly. One way of doing this is manually checking settings periodically, but this is error prone and time consuming. A better approach is to use single-source-of-truth settings and automation to ensure that whatever a compliance team has configured, stays configured and working correctly. These features can help you automate compliance:
+
+- [**Compliance frameworks**](../user/project/settings/index.md#compliance-frameworks) (for groups): Create a custom
+ compliance framework at the group level to describe the type of compliance requirements any child project needs to follow.
+- [**Compliance pipelines**](../user/project/settings/index.md#compliance-pipeline-configuration) (for groups): Define a
+ pipeline configuration to run for any projects with a given compliance framework.
+
+## Audit management
+
+An important part of any compliance program is being able to go back and understand what happened, when
+it happened, and who was responsible. This is useful in audit situations as well as for understanding
+the root cause of issues when they occur. It is useful to have both low-level, raw lists of audit data
+as well as high-level, summary lists of audit data. Between these two, compliance teams can quickly
+identify if problems exist and then drill down into the specifics of those issues. These features can help provide visibility into GitLab and audit what is happening:
+
+- [**Audit events**](audit_events.md) (for instances, groups, and projects): To maintain the integrity of your code,
+ audit events give administrators the ability to view any modifications made within the GitLab
+ server in an advanced audit events system, so you can control, analyze, and track every change.
+- [**Auditor users**](auditor_users.md) (for instances): Auditor users are users who are given read-only access to all
+ projects, groups, and other resources on the GitLab instance.
+- [**Compliance report**](../user/compliance/compliance_report/index.md) (for groups): Quickly get visibility into the
+ compliance posture of your organization.
+
+## Other compliance features
+
+These features can also help with compliance requirements:
+
+- [**Email all users of a project, group, or entire server**](../tools/email.md) (for instances): An administrator can
+ email groups of users based on project or group membership, or email everyone using the GitLab instance. These emails
+ are great for scheduled maintenance or upgrades.
+- [**Enforce ToS acceptance**](../user/admin_area/settings/terms.md) (for instances): Enforce your users accepting new
+ terms of service by blocking GitLab traffic.
+- [**External Status Checks**](../user/project/merge_requests/status_checks.md) (for projects): Interface with third-party
+ systems you already use during development to ensure you remain compliant.
+- [**Generate reports on permission levels of users**](../user/admin_area/index.md#user-permission-export) (for
+ instances): Administrators can generate a report listing all users' access permissions for groups and projects in the
+ instance.
+- [**Lock project membership to group**](../user/group/index.md#prevent-members-from-being-added-to-a-group) (for
+ groups): Group owners can prevent new members from being added to projects within a group.
+- [**LDAP group sync**](auth/ldap/ldap_synchronization.md#group-sync) (for instances): Gives administrators the ability
+ to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your
+ product, not configuring your tools.
+- [**LDAP group sync filters**](auth/ldap/ldap_synchronization.md#group-sync) (for instances): Gives more flexibility to
+ synchronize with LDAP based on filters, meaning you can leverage LDAP attributes to map GitLab permissions.
+- [**Omnibus GitLab package supports log forwarding**](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-forwarding)
+ (for instances): Forward your logs to a central system.
+- [**Restrict SSH Keys**](../security/ssh_keys_restrictions.md) (for instances): Control the technology and key length
+ of SSH keys used to access GitLab.
diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md
index 3af80363916..21e32d145bd 100644
--- a/doc/administration/environment_variables.md
+++ b/doc/administration/environment_variables.md
@@ -20,7 +20,7 @@ You can use the following environment variables to override certain values:
| Variable | Type | Description |
|--------------------------------------------|---------|---------------------------------------------------------------------------------------------------------|
| `DATABASE_URL` | string | The database URL; is of the form: `postgresql://localhost/blog_development`. |
-| `ENABLE_BOOTSNAP` | string | Enables Bootsnap for speeding up initial Rails boot (`1` to enable). |
+| `ENABLE_BOOTSNAP` | string | Toggles [Bootsnap](https://github.com/Shopify/bootsnap) for speeding up initial Rails boot. Enabled by default for non-production environments. Set to `0` to disable. |
| `EXTERNAL_URL` | string | Specify the external URL at the [time of installation](https://docs.gitlab.com/omnibus/settings/configuration.html#specifying-the-external-url-at-the-time-of-installation). |
| `EXTERNAL_VALIDATION_SERVICE_TIMEOUT` | integer | Timeout, in seconds, for an [external CI/CD pipeline validation service](external_pipeline_validation.md). Default is `5`. |
| `EXTERNAL_VALIDATION_SERVICE_URL` | string | URL to an [external CI/CD pipeline validation service](external_pipeline_validation.md). |
diff --git a/doc/administration/feature_flags.md b/doc/administration/feature_flags.md
index f2067e7a2d1..afbf0759452 100644
--- a/doc/administration/feature_flags.md
+++ b/doc/administration/feature_flags.md
@@ -42,11 +42,15 @@ GitLab to an earlier version, the feature flag status may change.
Features that are disabled by default may change or be removed without notice in a future version of GitLab.
-Data corruption, stability degradation, or performance degradation might occur if
+Data corruption, stability degradation, performance degradation, or security issues might occur if
you enable a feature that's disabled by default. Problems caused by using a default
disabled feature aren't covered by GitLab support, unless you were directed by GitLab
to enable the feature.
+Security issues found in features that are disabled by default are patched in regular releases
+and do not follow our regular [maintenance policy](../policy/maintenance.md#security-releases)
+with regards to backporting the fix.
+
## Risks when disabling released features
In most cases, the feature flag code is removed in a future version of GitLab.
diff --git a/doc/administration/geo/disaster_recovery/bring_primary_back.md b/doc/administration/geo/disaster_recovery/bring_primary_back.md
index d06f11bbe09..64673b9ee8d 100644
--- a/doc/administration/geo/disaster_recovery/bring_primary_back.md
+++ b/doc/administration/geo/disaster_recovery/bring_primary_back.md
@@ -5,27 +5,27 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Bring a demoted primary node back online **(PREMIUM SELF)**
+# Bring a demoted primary site back online **(PREMIUM SELF)**
-After a failover, it is possible to fail back to the demoted **primary** node to
+After a failover, it is possible to fail back to the demoted **primary** site to
restore your original configuration. This process consists of two steps:
-1. Making the old **primary** node a **secondary** node.
-1. Promoting a **secondary** node to a **primary** node.
+1. Making the old **primary** site a **secondary** site.
+1. Promoting a **secondary** site to a **primary** site.
WARNING:
-If you have any doubts about the consistency of the data on this node, we recommend setting it up from scratch.
+If you have any doubts about the consistency of the data on this site, we recommend setting it up from scratch.
-## Configure the former **primary** node to be a **secondary** node
+## Configure the former **primary** site to be a **secondary** site
-Since the former **primary** node will be out of sync with the current **primary** node, the first step is to bring the former **primary** node up to date. Note, deletion of data stored on disk like
-repositories and uploads will not be replayed when bringing the former **primary** node back
+Since the former **primary** site will be out of sync with the current **primary** site, the first step is to bring the former **primary** site up to date. Note, deletion of data stored on disk like
+repositories and uploads will not be replayed when bringing the former **primary** site back
into sync, which may result in increased disk usage.
Alternatively, you can [set up a new **secondary** GitLab instance](../setup/index.md) to avoid this.
-To bring the former **primary** node up to date:
+To bring the former **primary** site up to date:
-1. SSH into the former **primary** node that has fallen behind.
+1. SSH into the former **primary** site that has fallen behind.
1. Make sure all the services are up:
```shell
@@ -33,36 +33,36 @@ To bring the former **primary** node up to date:
```
NOTE:
- If you [disabled the **primary** node permanently](index.md#step-2-permanently-disable-the-primary-node),
+ If you [disabled the **primary** site permanently](index.md#step-2-permanently-disable-the-primary-site),
you need to undo those steps now. For Debian/Ubuntu you just need to run
`sudo systemctl enable gitlab-runsvdir`. For CentOS 6, you need to install
- the GitLab instance from scratch and set it up as a **secondary** node by
+ the GitLab instance from scratch and set it up as a **secondary** site by
following [Setup instructions](../setup/index.md). In this case, you don't need to follow the next step.
NOTE:
If you [changed the DNS records](index.md#step-4-optional-updating-the-primary-domain-dns-record)
- for this node during disaster recovery procedure you may need to [block
- all the writes to this node](planned_failover.md#prevent-updates-to-the-primary-node)
+ for this site during disaster recovery procedure you may need to [block
+ all the writes to this site](planned_failover.md#prevent-updates-to-the-primary-node)
during this procedure.
-1. [Set up database replication](../setup/database.md). In this case, the **secondary** node
- refers to the former **primary** node.
- 1. If [PgBouncer](../../postgresql/pgbouncer.md) was enabled on the **current secondary** node
- (when it was a primary node) disable it by editing `/etc/gitlab/gitlab.rb`
+1. [Set up database replication](../setup/database.md). In this case, the **secondary** site
+ refers to the former **primary** site.
+ 1. If [PgBouncer](../../postgresql/pgbouncer.md) was enabled on the **current secondary** site
+ (when it was a primary site) disable it by editing `/etc/gitlab/gitlab.rb`
and running `sudo gitlab-ctl reconfigure`.
- 1. You can then set up database replication on the **secondary** node.
+ 1. You can then set up database replication on the **secondary** site.
-If you have lost your original **primary** node, follow the
-[setup instructions](../setup/index.md) to set up a new **secondary** node.
+If you have lost your original **primary** site, follow the
+[setup instructions](../setup/index.md) to set up a new **secondary** site.
-## Promote the **secondary** node to **primary** node
+## Promote the **secondary** site to **primary** site
-When the initial replication is complete and the **primary** node and **secondary** node are
+When the initial replication is complete and the **primary** site and **secondary** site are
closely in sync, you can do a [planned failover](planned_failover.md).
-## Restore the **secondary** node
+## Restore the **secondary** site
-If your objective is to have two nodes again, you need to bring your **secondary**
-node back online as well by repeating the first step
-([configure the former **primary** node to be a **secondary** node](#configure-the-former-primary-node-to-be-a-secondary-node))
-for the **secondary** node.
+If your objective is to have two sites again, you need to bring your **secondary**
+site back online as well by repeating the first step
+([configure the former **primary** site to be a **secondary** site](#configure-the-former-primary-site-to-be-a-secondary-site))
+for the **secondary** site.
diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md
index f6f88e9b193..bf28eb76ffd 100644
--- a/doc/administration/geo/disaster_recovery/index.md
+++ b/doc/administration/geo/disaster_recovery/index.md
@@ -16,36 +16,36 @@ For the latest updates, check the [Disaster Recovery epic for complete maturity]
Multi-secondary configurations require the complete re-synchronization and re-configuration of all non-promoted secondaries and
causes downtime.
-## Promoting a **secondary** Geo node in single-secondary configurations
+## Promoting a **secondary** Geo site in single-secondary configurations
We don't currently provide an automated way to promote a Geo replica and do a
failover, but you can do it manually if you have `root` access to the machine.
-This process promotes a **secondary** Geo node to a **primary** node. To regain
-geographic redundancy as quickly as possible, you should add a new **secondary** node
+This process promotes a **secondary** Geo site to a **primary** site. To regain
+geographic redundancy as quickly as possible, you should add a new **secondary** site
immediately after following these instructions.
### Step 1. Allow replication to finish if possible
-If the **secondary** node is still replicating data from the **primary** node, follow
+If the **secondary** site is still replicating data from the **primary** site, follow
[the planned failover docs](planned_failover.md) as closely as possible in
order to avoid unnecessary data loss.
-### Step 2. Permanently disable the **primary** node
+### Step 2. Permanently disable the **primary** site
WARNING:
-If the **primary** node goes offline, there may be data saved on the **primary** node
-that have not been replicated to the **secondary** node. This data should be treated
+If the **primary** site goes offline, there may be data saved on the **primary** site
+that have not been replicated to the **secondary** site. This data should be treated
as lost if you proceed.
-If an outage on the **primary** node happens, you should do everything possible to
+If an outage on the **primary** site happens, you should do everything possible to
avoid a split-brain situation where writes can occur in two different GitLab
instances, complicating recovery efforts. So to prepare for the failover, we
-must disable the **primary** node.
+must disable the **primary** site.
- If you have SSH access:
- 1. SSH into the **primary** node to stop and disable GitLab:
+ 1. SSH into the **primary** site to stop and disable GitLab:
```shell
sudo gitlab-ctl stop
@@ -57,35 +57,35 @@ must disable the **primary** node.
sudo systemctl disable gitlab-runsvdir
```
-- If you do not have SSH access to the **primary** node, take the machine offline and
+- If you do not have SSH access to the **primary** site, take the machine offline and
prevent it from rebooting by any means at your disposal.
You might need to:
- Reconfigure the load balancers.
- Change DNS records (for example, point the primary DNS record to the
- **secondary** node to stop usage of the **primary** node).
+ **secondary** site to stop usage of the **primary** site).
- Stop the virtual servers.
- Block traffic through a firewall.
- - Revoke object storage permissions from the **primary** node.
+ - Revoke object storage permissions from the **primary** site.
- Physically disconnect a machine.
If you plan to [update the primary domain DNS record](#step-4-optional-updating-the-primary-domain-dns-record),
you may wish to lower the TTL now to speed up propagation.
-### Step 3. Promoting a **secondary** node
+### Step 3. Promoting a **secondary** site
WARNING:
-In GitLab 13.2 and 13.3, promoting a secondary node to a primary while the
+In GitLab 13.2 and 13.3, promoting a secondary site to a primary while the
secondary is paused fails. Do not pause replication before promoting a
-secondary. If the node is paused, be sure to resume before promoting.
+secondary. If the secondary site is paused, be sure to resume before promoting.
This issue has been fixed in GitLab 13.4 and later.
Note the following when promoting a secondary:
-- If replication was paused on the secondary node (for example as a part of
+- If replication was paused on the secondary site (for example as a part of
upgrading, while you were running a version of GitLab earlier than 13.4), you
- _must_ [enable the node by using the database](../replication/troubleshooting.md#message-activerecordrecordinvalid-validation-failed-enabled-geo-primary-node-cannot-be-disabled)
- before proceeding. If the secondary node
+ _must_ [enable the site by using the database](../replication/troubleshooting.md#message-activerecordrecordinvalid-validation-failed-enabled-geo-primary-node-cannot-be-disabled)
+ before proceeding. If the secondary site
[has been paused](../../geo/index.md#pausing-and-resuming-replication), the promotion
performs a point-in-time recovery to the last known state.
Data that was created on the primary while the secondary was paused is lost.
@@ -99,7 +99,32 @@ Note the following when promoting a secondary:
for more information, see this
[troubleshooting advice](../replication/troubleshooting.md#errors-when-using---skip-preflight-checks-or---force).
-#### Promoting a **secondary** node running on a single machine
+#### Promoting a **secondary** site running on a single node running GitLab 14.5 and later
+
+1. SSH in to your **secondary** node and execute:
+
+ - To promote the secondary node to primary:
+
+ ```shell
+ sudo gitlab-ctl geo promote
+ ```
+
+ - To promote the secondary node to primary **without any further confirmation**:
+
+ ```shell
+ sudo gitlab-ctl geo promote --force
+ ```
+
+1. Verify you can connect to the newly-promoted **primary** site using the URL used
+ previously for the **secondary** site.
+1. If successful, the **secondary** site is now promoted to the **primary** site.
+
+#### Promoting a **secondary** site running on a single node running GitLab 14.4 and earlier
+
+WARNING:
+The `gitlab-ctl promote-to-primary-node` and `gitlab-ctl promoted-db` commands are
+deprecated in GitLab 14.5 and later, and are scheduled to [be removed in GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/345207).
+Use `gitlab-ctl geo promote` instead.
1. SSH in to your **secondary** node and login as root:
@@ -116,7 +141,7 @@ Note the following when promoting a secondary:
roles ['geo_secondary_role']
```
-1. Promote the **secondary** node to the **primary** node:
+1. Promote the **secondary** site to the **primary** site:
- To promote the secondary node to primary along with [preflight checks](planned_failover.md#preflight-checks):
@@ -146,18 +171,57 @@ Note the following when promoting a secondary:
gitlab-ctl promote-to-primary-node --force
```
-1. Verify you can connect to the newly-promoted **primary** node using the URL used
- previously for the **secondary** node.
-1. If successful, the **secondary** node is now promoted to the **primary** node.
+1. Verify you can connect to the newly-promoted **primary** site using the URL used
+ previously for the **secondary** site.
+1. If successful, the **secondary** site is now promoted to the **primary** site.
-#### Promoting a **secondary** node with multiple servers
+#### Promoting a **secondary** site with multiple nodes running GitLab 14.5 and later
+
+1. SSH to every Sidekiq, PostgresSQL, and Gitaly node in the **secondary** site and run one of the following commands:
+
+ - To promote the secondary node to primary:
+
+ ```shell
+ sudo gitlab-ctl geo promote
+ ```
+
+ - To promote the secondary node to primary **without any further confirmation**:
+
+ ```shell
+ sudo gitlab-ctl geo promote --force
+ ```
+
+1. SSH into each Rails node on your **secondary** site and run one of the following commands:
+
+ - To promote the secondary node to primary:
+
+ ```shell
+ sudo gitlab-ctl geo promote
+ ```
+
+ - To promote the secondary node to primary **without any further confirmation**:
+
+ ```shell
+ sudo gitlab-ctl geo promote --force
+ ```
+
+1. Verify you can connect to the newly-promoted **primary** site using the URL used
+ previously for the **secondary** site.
+1. If successful, the **secondary** site is now promoted to the **primary** site.
+
+#### Promoting a **secondary** site with multiple nodes running GitLab 14.4 and earlier
+
+WARNING:
+The `gitlab-ctl promote-to-primary-node` and `gitlab-ctl promoted-db` commands are
+deprecated in GitLab 14.5 and later, and are scheduled to [be removed in GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/345207).
+Use `gitlab-ctl geo promote` instead.
The `gitlab-ctl promote-to-primary-node` command cannot be used yet in
-conjunction with multiple servers, as it can only
-perform changes on a **secondary** with only a single machine. Instead, you must
+conjunction with multiple nodes, as it can only perform changes on
+a **secondary** with only a single node. Instead, you must
do this manually.
-1. SSH in to the database node in the **secondary** and trigger PostgreSQL to
+1. SSH in to the database node in the **secondary** site and trigger PostgreSQL to
promote to read-write:
```shell
@@ -187,16 +251,54 @@ do this manually.
1. Verify you can connect to the newly-promoted **primary** using the URL used
previously for the **secondary**.
-1. If successful, the **secondary** node is now promoted to the **primary** node.
+1. If successful, the **secondary** site is now promoted to the **primary** site.
+
+#### Promoting a **secondary** site with a Patroni standby cluster running GitLab 14.5 and later
+
+1. SSH to every Sidekiq, PostgresSQL, and Gitaly node in the **secondary** site and run one of the following commands:
+
+ - To promote the secondary node to primary:
+
+ ```shell
+ sudo gitlab-ctl geo promote
+ ```
+
+ - To promote the secondary node to primary **without any further confirmation**:
+
+ ```shell
+ sudo gitlab-ctl geo promote --force
+ ```
+
+1. SSH into each Rails node on your **secondary** site and run one of the following commands:
-#### Promoting a **secondary** node with a Patroni standby cluster
+ - To promote the secondary node to primary:
+
+ ```shell
+ sudo gitlab-ctl geo promote
+ ```
+
+ - To promote the secondary node to primary **without any further confirmation**:
+
+ ```shell
+ sudo gitlab-ctl geo promote --force
+ ```
+
+1. Verify you can connect to the newly-promoted **primary** site using the URL used
+ previously for the **secondary** site.
+1. If successful, the **secondary** site is now promoted to the **primary** site.
+
+#### Promoting a **secondary** site with a Patroni standby cluster running GitLab 14.4 and earlier
+
+WARNING:
+The `gitlab-ctl promote-to-primary-node` and `gitlab-ctl promoted-db` commands are
+deprecated in GitLab 14.5 and later, and are scheduled to [be removed in GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/345207).
+Use `gitlab-ctl geo promote` instead.
The `gitlab-ctl promote-to-primary-node` command cannot be used yet in
-conjunction with a Patroni standby cluster, as it can only
-perform changes on a **secondary** with only a single machine. Instead, you must
-do this manually.
+conjunction with a Patroni standby cluster, as it can only perform changes on
+a **secondary** with only a single node. Instead, you must do this manually.
-1. SSH in to the Standby Leader database node in the **secondary** and trigger PostgreSQL to
+1. SSH in to the Standby Leader database node in the **secondary** site and trigger PostgreSQL to
promote to read-write:
```shell
@@ -230,9 +332,81 @@ do this manually.
1. Verify you can connect to the newly-promoted **primary** using the URL used
previously for the **secondary**.
-1. If successful, the **secondary** node is now promoted to the **primary** node.
+1. If successful, the **secondary** site is now promoted to the **primary** site.
+
+#### Promoting a **secondary** site with an external PostgreSQL database running GitLab 14.5 and later
+
+The `gitlab-ctl geo promote` command can be used in conjunction with
+an external PostgreSQL database, but it can only perform changes on
+a **secondary** PostgreSQL database managed by Omnibus.
+You must promote the replica database associated with the **secondary**
+site first.
+
+1. Promote the replica database associated with the **secondary** site. This
+ sets the database to read-write. The instructions vary depending on where your database is hosted:
+ - [Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Promote)
+ - [Azure PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal#stop-replication)
+ - [Google Cloud SQL](https://cloud.google.com/sql/docs/mysql/replication/manage-replicas#promote-replica)
+ - For other external PostgreSQL databases, save the following script in your
+ secondary node, for example `/tmp/geo_promote.sh`, and modify the connection
+ parameters to match your environment. Then, execute it to promote the replica:
+
+ ```shell
+ #!/bin/bash
-#### Promoting a **secondary** node with an external PostgreSQL database
+ PG_SUPERUSER=postgres
+
+ # The path to your pg_ctl binary. You may need to adjust this path to match
+ # your PostgreSQL installation
+ PG_CTL_BINARY=/usr/lib/postgresql/10/bin/pg_ctl
+
+ # The path to your PostgreSQL data directory. You may need to adjust this
+ # path to match your PostgreSQL installation. You can also run
+ # `SHOW data_directory;` from PostgreSQL to find your data directory
+ PG_DATA_DIRECTORY=/etc/postgresql/10/main
+
+ # Promote the PostgreSQL database and allow read/write operations
+ sudo -u $PG_SUPERUSER $PG_CTL_BINARY -D $PG_DATA_DIRECTORY promote
+ ```
+
+1. SSH to every Sidekiq, PostgresSQL, and Gitaly node in the **secondary** site and run one of the following commands:
+
+ - To promote the secondary node to primary:
+
+ ```shell
+ sudo gitlab-ctl geo promote
+ ```
+
+ - To promote the secondary node to primary **without any further confirmation**:
+
+ ```shell
+ sudo gitlab-ctl geo promote --force
+ ```
+
+1. SSH into each Rails node on your **secondary** site and run one of the following commands:
+
+ - To promote the secondary node to primary:
+
+ ```shell
+ sudo gitlab-ctl geo promote
+ ```
+
+ - To promote the secondary node to primary **without any further confirmation**:
+
+ ```shell
+ sudo gitlab-ctl geo promote --force
+ ```
+
+1. Verify you can connect to the newly-promoted **primary** site using the URL used
+ previously for the **secondary** site.
+1. If successful, the **secondary** site is now promoted to the **primary** site.
+
+#### Promoting a **secondary** site with an external PostgreSQL database running GitLab 14.4 and earlier
+
+WARNING:
+The `gitlab-ctl promote-to-primary-node` and `gitlab-ctl promoted-db` commands are
+deprecated in GitLab 14.5 and later, and are scheduled to [be removed in GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/345207).
+Use `gitlab-ctl geo promote` instead.
The `gitlab-ctl promote-to-primary-node` command cannot be used in conjunction with
an external PostgreSQL database, as it can only perform changes on a **secondary**
@@ -287,23 +461,23 @@ required:
1. Verify you can connect to the newly-promoted **primary** using the URL used
previously for the **secondary**.
-1. If successful, the **secondary** node is now promoted to the **primary** node.
+1. If successful, the **secondary** site is now promoted to the **primary** site.
### Step 4. (Optional) Updating the primary domain DNS record
-Updating the DNS records for the primary domain to point to the **secondary** node
+Updating the DNS records for the primary domain to point to the **secondary** site
to prevent the need to update all references to the primary domain to the
secondary domain, like changing Git remotes and API URLs.
-1. SSH into the **secondary** node and login as root:
+1. SSH into the **secondary** site and login as root:
```shell
sudo -i
```
1. Update the primary domain's DNS record. After updating the primary domain's
- DNS records to point to the **secondary** node, edit `/etc/gitlab/gitlab.rb` on the
- **secondary** node to reflect the new URL:
+ DNS records to point to the **secondary** site, edit `/etc/gitlab/gitlab.rb` on the
+ **secondary** site to reflect the new URL:
```ruby
# Change the existing external_url configuration
@@ -314,13 +488,13 @@ secondary domain, like changing Git remotes and API URLs.
Changing `external_url` does not prevent access via the old secondary URL, as
long as the secondary DNS records are still intact.
-1. Reconfigure the **secondary** node for the change to take effect:
+1. Reconfigure the **secondary** site for the change to take effect:
```shell
gitlab-ctl reconfigure
```
-1. Execute the command below to update the newly promoted **primary** node URL:
+1. Execute the command below to update the newly promoted **primary** site URL:
```shell
gitlab-rake geo:update_primary_node_url
@@ -335,14 +509,14 @@ secondary domain, like changing Git remotes and API URLs.
To determine if you need to do this, search for the
`gitlab_rails["geo_node_name"]` setting in your `/etc/gitlab/gitlab.rb`
file. If it is commented out with `#` or not found at all, then you
- need to update the **primary** node's name in the database. You can search for it
+ need to update the **primary** site's name in the database. You can search for it
like so:
```shell
grep "geo_node_name" /etc/gitlab/gitlab.rb
```
- To update the **primary** node's name in the database:
+ To update the **primary** site's name in the database:
```shell
gitlab-rails runner 'Gitlab::Geo.primary_node.update!(name: GeoNode.current_node_name)'
@@ -352,12 +526,12 @@ secondary domain, like changing Git remotes and API URLs.
If you updated the DNS records for the primary domain, these changes may
not have yet propagated depending on the previous DNS records TTL.
-### Step 5. (Optional) Add **secondary** Geo node to a promoted **primary** node
+### Step 5. (Optional) Add **secondary** Geo site to a promoted **primary** site
-Promoting a **secondary** node to **primary** node using the process above does not enable
-Geo on the new **primary** node.
+Promoting a **secondary** site to **primary** site using the process above does not enable
+Geo on the new **primary** site.
-To bring a new **secondary** node online, follow the [Geo setup instructions](../index.md#setup-instructions).
+To bring a new **secondary** site online, follow the [Geo setup instructions](../index.md#setup-instructions).
### Step 6. (Optional) Removing the secondary's tracking database
@@ -376,13 +550,13 @@ for the changes to take effect.
## Promoting secondary Geo replica in multi-secondary configurations
-If you have more than one **secondary** node and you need to promote one of them, we suggest you follow
-[Promoting a **secondary** Geo node in single-secondary configurations](#promoting-a-secondary-geo-node-in-single-secondary-configurations)
+If you have more than one **secondary** site and you need to promote one of them, we suggest you follow
+[Promoting a **secondary** Geo site in single-secondary configurations](#promoting-a-secondary-geo-site-in-single-secondary-configurations)
and after that you also need two extra steps.
-### Step 1. Prepare the new **primary** node to serve one or more **secondary** nodes
+### Step 1. Prepare the new **primary** site to serve one or more **secondary** sites
-1. SSH into the new **primary** node and login as root:
+1. SSH into the new **primary** site and login as root:
```shell
sudo -i
@@ -442,13 +616,13 @@ and after that you also need two extra steps.
### Step 2. Initiate the replication process
-Now we need to make each **secondary** node listen to changes on the new **primary** node. To do that you need
+Now we need to make each **secondary** site listen to changes on the new **primary** site. To do that you need
to [initiate the replication process](../setup/database.md#step-3-initiate-the-replication-process) again but this time
-for another **primary** node. All the old replication settings are overwritten.
+for another **primary** site. All the old replication settings are overwritten.
## Promoting a secondary Geo cluster in GitLab Cloud Native Helm Charts
-When updating a Cloud Native Geo deployment, the process for updating any node that is external to the secondary Kubernetes cluster does not differ from the non Cloud Native approach. As such, you can always defer to [Promoting a secondary Geo node in single-secondary configurations](#promoting-a-secondary-geo-node-in-single-secondary-configurations) for more information.
+When updating a Cloud Native Geo deployment, the process for updating any node that is external to the secondary Kubernetes cluster does not differ from the non Cloud Native approach. As such, you can always defer to [Promoting a secondary Geo site in single-secondary configurations](#promoting-a-secondary-geo-site-in-single-secondary-configurations) for more information.
The following sections assume you are using the `gitlab` namespace. If you used a different namespace when setting up your cluster, you should also replace `--namespace gitlab` with your namespace.
@@ -489,13 +663,45 @@ must disable the **primary** site:
- Revoke object storage permissions from the **primary** site.
- Physically disconnect a machine.
-### Step 2. Promote all **secondary** nodes external to the cluster
+### Step 2. Promote all **secondary** sites external to the cluster
WARNING:
If the secondary site [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs
a point-in-time recovery to the last known state.
Data that was created on the primary while the secondary was paused is lost.
+If you are running GitLab 14.5 and later:
+
+1. SSH to every Sidekiq, PostgresSQL, and Gitaly node in the **secondary** site and run one of the following commands:
+
+ - To promote the secondary node to primary:
+
+ ```shell
+ sudo gitlab-ctl geo promote
+ ```
+
+ - To promote the secondary node to primary **without any further confirmation**:
+
+ ```shell
+ sudo gitlab-ctl geo promote --force
+ ```
+
+1. SSH into each Rails node on your **secondary** site and run one of the following commands:
+
+ - To promote the secondary node to primary:
+
+ ```shell
+ sudo gitlab-ctl geo promote
+ ```
+
+ - To promote the secondary node to primary **without any further confirmation**:
+
+ ```shell
+ sudo gitlab-ctl geo promote --force
+ ```
+
+If you are running GitLab 14.4 and earlier:
+
1. SSH in to the database node in the **secondary** and trigger PostgreSQL to
promote to read-write:
@@ -522,8 +728,6 @@ Data that was created on the primary while the secondary was paused is lost.
After making these changes, [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) on the database node.
-### Step 3. Promote the **secondary** cluster
-
1. Find the task runner pod:
```shell
@@ -536,6 +740,8 @@ Data that was created on the primary while the secondary was paused is lost.
kubectl --namespace gitlab exec -ti gitlab-geo-task-runner-XXX -- gitlab-rake geo:set_secondary_as_primary
```
+### Step 3. Promote the **secondary** cluster
+
1. Update the existing cluster configuration.
You can retrieve the existing configuration with Helm:
diff --git a/doc/administration/geo/disaster_recovery/planned_failover.md b/doc/administration/geo/disaster_recovery/planned_failover.md
index 6312ed669ae..939b4aec968 100644
--- a/doc/administration/geo/disaster_recovery/planned_failover.md
+++ b/doc/administration/geo/disaster_recovery/planned_failover.md
@@ -204,4 +204,4 @@ in the loss of any data uploaded to the new **primary** in the meantime.
Don't forget to remove the broadcast message after the failover is complete.
-Finally, you can bring the [old site back as a secondary](bring_primary_back.md#configure-the-former-primary-node-to-be-a-secondary-node).
+Finally, you can bring the [old site back as a secondary](bring_primary_back.md#configure-the-former-primary-site-to-be-a-secondary-site).
diff --git a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md
index 3eb7bc2a8e0..3c7af309f78 100644
--- a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md
+++ b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md
@@ -66,13 +66,13 @@ promote a Geo replica and perform a failover.
NOTE:
GitLab 13.9 through GitLab 14.3 are affected by a bug in which the Geo secondary site statuses will appear to stop updating and become unhealthy. For more information, see [Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](../../replication/troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
-On the **secondary** node:
+On the **secondary** site:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Geo > Nodes** to see its status.
Replicated objects (shown in green) should be close to 100%,
and there should be no failures (shown in red). If a large proportion of
- objects aren't yet replicated (shown in gray), consider giving the node more
+ objects aren't yet replicated (shown in gray), consider giving the site more
time to complete.
![Replication status](../../replication/img/geo_dashboard_v14_0.png)
@@ -85,20 +85,20 @@ You can use the
[Geo status API](../../../../api/geo_nodes.md#retrieve-project-sync-or-verification-failures-that-occurred-on-the-current-node)
to review failed objects and the reasons for failure.
A common cause of replication failures is the data being missing on the
-**primary** node - you can resolve these failures by restoring the data from backup,
+**primary** site - you can resolve these failures by restoring the data from backup,
or removing references to the missing data.
The maintenance window won't end until Geo replication and verification is
completely finished. To keep the window as short as possible, you should
ensure these processes are close to 100% as possible during active use.
-If the **secondary** node is still replicating data from the **primary** node,
+If the **secondary** site is still replicating data from the **primary** site,
follow these steps to avoid unnecessary data loss:
1. Until a [read-only mode](https://gitlab.com/gitlab-org/gitlab/-/issues/14609)
is implemented, updates must be prevented from happening manually to the
- **primary**. Your **secondary** node still needs read-only
- access to the **primary** node during the maintenance window:
+ **primary**. Your **secondary** site still needs read-only
+ access to the **primary** site during the maintenance window:
1. At the scheduled time, using your cloud provider or your node's firewall, block
all HTTP, HTTPS and SSH traffic to/from the **primary** node, **except** for your IP and
@@ -121,18 +121,18 @@ follow these steps to avoid unnecessary data loss:
```
From this point, users are unable to view their data or make changes on the
- **primary** node. They are also unable to log in to the **secondary** node.
+ **primary** site. They are also unable to log in to the **secondary** site.
However, existing sessions need to work for the remainder of the maintenance period, and
so public data is accessible throughout.
- 1. Verify the **primary** node is blocked to HTTP traffic by visiting it in browser via
+ 1. Verify the **primary** site is blocked to HTTP traffic by visiting it in browser via
another IP. The server should refuse connection.
- 1. Verify the **primary** node is blocked to Git over SSH traffic by attempting to pull an
+ 1. Verify the **primary** site is blocked to Git over SSH traffic by attempting to pull an
existing Git repository with an SSH remote URL. The server should refuse
connection.
- 1. On the **primary** node:
+ 1. On the **primary** site:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Monitoring > Background Jobs**.
1. On the Sidekiq dhasboard, select **Cron**.
@@ -150,7 +150,7 @@ follow these steps to avoid unnecessary data loss:
1. If you are manually replicating any
[data not managed by Geo](../../replication/datatypes.md#limitations-on-replicationverification),
trigger the final replication process now.
- 1. On the **primary** node:
+ 1. On the **primary** site:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Monitoring > Background Jobs**.
1. On the Sidekiq dashboard, select **Queues**, and wait for all queues except
@@ -165,7 +165,7 @@ follow these steps to avoid unnecessary data loss:
- Database replication lag is 0ms.
- The Geo log cursor is up to date (0 events behind).
- 1. On the **secondary** node:
+ 1. On the **secondary** site:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Monitoring > Background Jobs**.
1. On the Sidekiq dashboard, select **Queues**, and wait for all the `geo`
@@ -173,14 +173,14 @@ follow these steps to avoid unnecessary data loss:
1. [Run an integrity check](../../../raketasks/check.md) to verify the integrity
of CI artifacts, LFS objects, and uploads in file storage.
- At this point, your **secondary** node contains an up-to-date copy of everything the
- **primary** node has, meaning nothing is lost when you fail over.
+ At this point, your **secondary** site contains an up-to-date copy of everything the
+ **primary** site has, meaning nothing is lost when you fail over.
-1. In this final step, you need to permanently disable the **primary** node.
+1. In this final step, you need to permanently disable the **primary** site.
WARNING:
- When the **primary** node goes offline, there may be data saved on the **primary** node
- that has not been replicated to the **secondary** node. This data should be treated
+ When the **primary** site goes offline, there may be data saved on the **primary** site
+ that has not been replicated to the **secondary** site. This data should be treated
as lost if you proceed.
NOTE:
@@ -189,9 +189,9 @@ follow these steps to avoid unnecessary data loss:
When performing a failover, we want to avoid a split-brain situation where
writes can occur in two different GitLab instances. So to prepare for the
- failover, you must disable the **primary** node:
+ failover, you must disable the **primary** site:
- - If you have SSH access to the **primary** node, stop and disable GitLab:
+ - If you have SSH access to the **primary** site, stop and disable GitLab:
```shell
sudo gitlab-ctl stop
@@ -214,19 +214,58 @@ follow these steps to avoid unnecessary data loss:
from starting if the machine reboots as `root` with
`initctl stop gitlab-runsvvdir && echo 'manual' > /etc/init/gitlab-runsvdir.override && initctl reload-configuration`.
- - If you do not have SSH access to the **primary** node, take the machine offline and
+ - If you do not have SSH access to the **primary** site, take the machine offline and
prevent it from rebooting. Since there are many ways you may prefer to accomplish
this, we avoid a single recommendation. You may need to:
- Reconfigure the load balancers.
- Change DNS records (for example, point the **primary** DNS record to the
- **secondary** node to stop using the **primary** node).
+ **secondary** site to stop using the **primary** site).
- Stop the virtual servers.
- Block traffic through a firewall.
- - Revoke object storage permissions from the **primary** node.
+ - Revoke object storage permissions from the **primary** site.
- Physically disconnect a machine.
-### Promoting the **secondary** node
+### Promoting the **secondary** site running GitLab 14.5 and later
+
+1. SSH to every Sidekiq, PostgresSQL, and Gitaly node in the **secondary** site and run one of the following commands:
+
+ - To promote the secondary node to primary:
+
+ ```shell
+ sudo gitlab-ctl geo promote
+ ```
+
+ - To promote the secondary node to primary **without any further confirmation**:
+
+ ```shell
+ sudo gitlab-ctl geo promote --force
+ ```
+
+1. SSH into each Rails node on your **secondary** site and run one of the following commands:
+
+ - To promote the secondary node to primary:
+
+ ```shell
+ sudo gitlab-ctl geo promote
+ ```
+
+ - To promote the secondary node to primary **without any further confirmation**:
+
+ ```shell
+ sudo gitlab-ctl geo promote --force
+ ```
+
+1. Verify you can connect to the newly promoted **primary** site using the URL used
+ previously for the **secondary** site.
+1. If successful, the **secondary** site is now promoted to the **primary** site.
+
+### Promoting the **secondary** site running GitLab 14.4 and earlier
+
+WARNING:
+The `gitlab-ctl promote-to-primary-node` and `gitlab-ctl promoted-db` commands are
+deprecated in GitLab 14.5 and later, and are scheduled to [be removed in GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/345207).
+Use `gitlab-ctl geo promote` instead.
NOTE:
A new **secondary** should not be added at this time. If you want to add a new
@@ -243,13 +282,13 @@ perform changes on a **secondary** with only a single machine. Instead, you must
do this manually.
WARNING:
-In GitLab 13.2 and 13.3, promoting a secondary node to a primary while the
+In GitLab 13.2 and 13.3, promoting a secondary site to a primary while the
secondary is paused fails. Do not pause replication before promoting a
-secondary. If the node is paused, be sure to resume before promoting. This
+secondary. If the site is paused, be sure to resume before promoting. This
issue has been fixed in GitLab 13.4 and later.
WARNING:
- If the secondary node [has been paused](../../../geo/index.md#pausing-and-resuming-replication), this performs
+If the secondary site [has been paused](../../../geo/index.md#pausing-and-resuming-replication), this performs
a point-in-time recovery to the last known state.
Data that was created on the primary while the secondary was paused is lost.
@@ -291,6 +330,6 @@ Data that was created on the primary while the secondary was paused is lost.
### Next steps
To regain geographic redundancy as quickly as possible, you should
-[add a new **secondary** node](../../setup/index.md). To
+[add a new **secondary** site](../../setup/index.md). To
do that, you can re-add the old **primary** as a new secondary and bring it back
online.
diff --git a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md
index d4782144df8..8a4f2ed4306 100644
--- a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md
+++ b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md
@@ -54,10 +54,10 @@ promote a Geo replica and perform a failover.
NOTE:
GitLab 13.9 through GitLab 14.3 are affected by a bug in which the Geo secondary site statuses will appear to stop updating and become unhealthy. For more information, see [Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](../../replication/troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
-On the **secondary** node, navigate to the **Admin Area > Geo** dashboard to
+On the **secondary** site, navigate to the **Admin Area > Geo** dashboard to
review its status. Replicated objects (shown in green) should be close to 100%,
and there should be no failures (shown in red). If a large proportion of
-objects aren't yet replicated (shown in gray), consider giving the node more
+objects aren't yet replicated (shown in gray), consider giving the site more
time to complete.
![Replication status](../../replication/img/geo_dashboard_v14_0.png)
@@ -70,20 +70,20 @@ You can use the
[Geo status API](../../../../api/geo_nodes.md#retrieve-project-sync-or-verification-failures-that-occurred-on-the-current-node)
to review failed objects and the reasons for failure.
A common cause of replication failures is the data being missing on the
-**primary** node - you can resolve these failures by restoring the data from backup,
+**primary** site - you can resolve these failures by restoring the data from backup,
or removing references to the missing data.
The maintenance window won't end until Geo replication and verification is
completely finished. To keep the window as short as possible, you should
ensure these processes are close to 100% as possible during active use.
-If the **secondary** node is still replicating data from the **primary** node,
+If the **secondary** site is still replicating data from the **primary** site,
follow these steps to avoid unnecessary data loss:
1. Until a [read-only mode](https://gitlab.com/gitlab-org/gitlab/-/issues/14609)
is implemented, updates must be prevented from happening manually to the
- **primary**. Your **secondary** node still needs read-only
- access to the **primary** node during the maintenance window:
+ **primary**. Your **secondary** site still needs read-only
+ access to the **primary** site during the maintenance window:
1. At the scheduled time, using your cloud provider or your node's firewall, block
all HTTP, HTTPS and SSH traffic to/from the **primary** node, **except** for your IP and
@@ -106,18 +106,18 @@ follow these steps to avoid unnecessary data loss:
```
From this point, users are unable to view their data or make changes on the
- **primary** node. They are also unable to log in to the **secondary** node.
+ **primary** site. They are also unable to log in to the **secondary** site.
However, existing sessions need to work for the remainder of the maintenance period, and
so public data is accessible throughout.
- 1. Verify the **primary** node is blocked to HTTP traffic by visiting it in browser via
+ 1. Verify the **primary** site is blocked to HTTP traffic by visiting it in browser via
another IP. The server should refuse connection.
- 1. Verify the **primary** node is blocked to Git over SSH traffic by attempting to pull an
+ 1. Verify the **primary** site is blocked to Git over SSH traffic by attempting to pull an
existing Git repository with an SSH remote URL. The server should refuse
connection.
- 1. On the **primary** node:
+ 1. On the **primary** site:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Monitoring > Background Jobs**.
1. On the Sidekiq dhasboard, select **Cron**.
@@ -135,7 +135,7 @@ follow these steps to avoid unnecessary data loss:
1. If you are manually replicating any
[data not managed by Geo](../../replication/datatypes.md#limitations-on-replicationverification),
trigger the final replication process now.
- 1. On the **primary** node:
+ 1. On the **primary** site:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Monitoring > Background Jobs**.
1. On the Sidekiq dashboard, select **Queues**, and wait for all queues except
@@ -143,14 +143,14 @@ follow these steps to avoid unnecessary data loss:
These queues contain work that has been submitted by your users; failing over
before it is completed, causes the work to be lost.
1. On the left sidebar, select **Geo > Nodes** and wait for the
- following conditions to be true of the **secondary** node you are failing over to:
+ following conditions to be true of the **secondary** site you are failing over to:
- All replication meters reach 100% replicated, 0% failures.
- All verification meters reach 100% verified, 0% failures.
- Database replication lag is 0ms.
- The Geo log cursor is up to date (0 events behind).
- 1. On the **secondary** node:
+ 1. On the **secondary** site:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Monitoring > Background Jobs**.
1. On the Sidekiq dashboard, select **Queues**, and wait for all the `geo`
@@ -158,14 +158,14 @@ follow these steps to avoid unnecessary data loss:
1. [Run an integrity check](../../../raketasks/check.md) to verify the integrity
of CI artifacts, LFS objects, and uploads in file storage.
- At this point, your **secondary** node contains an up-to-date copy of everything the
- **primary** node has, meaning nothing is lost when you fail over.
+ At this point, your **secondary** site contains an up-to-date copy of everything the
+ **primary** site has, meaning nothing is lost when you fail over.
-1. In this final step, you need to permanently disable the **primary** node.
+1. In this final step, you need to permanently disable the **primary** site.
WARNING:
- When the **primary** node goes offline, there may be data saved on the **primary** node
- that has not been replicated to the **secondary** node. This data should be treated
+ When the **primary** site goes offline, there may be data saved on the **primary** site
+ that has not been replicated to the **secondary** site. This data should be treated
as lost if you proceed.
NOTE:
@@ -174,9 +174,9 @@ follow these steps to avoid unnecessary data loss:
When performing a failover, we want to avoid a split-brain situation where
writes can occur in two different GitLab instances. So to prepare for the
- failover, you must disable the **primary** node:
+ failover, you must disable the **primary** site:
- - If you have SSH access to the **primary** node, stop and disable GitLab:
+ - If you have SSH access to the **primary** site, stop and disable GitLab:
```shell
sudo gitlab-ctl stop
@@ -199,19 +199,19 @@ follow these steps to avoid unnecessary data loss:
from starting if the machine reboots as `root` with
`initctl stop gitlab-runsvvdir && echo 'manual' > /etc/init/gitlab-runsvdir.override && initctl reload-configuration`.
- - If you do not have SSH access to the **primary** node, take the machine offline and
+ - If you do not have SSH access to the **primary** site, take the machine offline and
prevent it from rebooting. Since there are many ways you may prefer to accomplish
this, we avoid a single recommendation. You may need to:
- Reconfigure the load balancers.
- Change DNS records (for example, point the **primary** DNS record to the
- **secondary** node to stop using the **primary** node).
+ **secondary** site to stop using the **primary** site).
- Stop the virtual servers.
- Block traffic through a firewall.
- - Revoke object storage permissions from the **primary** node.
+ - Revoke object storage permissions from the **primary** site.
- Physically disconnect a machine.
-### Promoting the **secondary** node
+### Promoting the **secondary** site
Note the following when promoting a secondary:
@@ -222,9 +222,35 @@ Note the following when promoting a secondary:
error during this process, read
[the troubleshooting advice](../../replication/troubleshooting.md#fixing-errors-during-a-failover-or-when-promoting-a-secondary-to-a-primary-node).
-To promote the secondary node:
+To promote the secondary site running GitLab 14.5 and later:
-1. SSH in to your **secondary** node and login as root:
+1. SSH in to your **secondary** node and run one of the following commands:
+
+ - To promote the secondary node to primary:
+
+ ```shell
+ sudo gitlab-ctl geo promote
+ ```
+
+ - To promote the secondary node to primary **without any further confirmation**:
+
+ ```shell
+ sudo gitlab-ctl geo promote --force
+ ```
+
+1. Verify you can connect to the newly promoted **primary** site using the URL used
+ previously for the **secondary** site.
+
+ If successful, the **secondary** site is now promoted to the **primary** site.
+
+To promote the secondary site running GitLab 14.4 and earlier:
+
+WARNING:
+The `gitlab-ctl promote-to-primary-node` and `gitlab-ctl promoted-db` commands are
+deprecated in GitLab 14.5 and later, and are scheduled to [be removed in GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/345207).
+Use `gitlab-ctl geo promote` instead.
+
+1. SSH in to your **secondary** site and login as root:
```shell
sudo -i
@@ -275,20 +301,20 @@ To promote the secondary node:
gitlab-ctl promote-to-primary-node --skip-preflight-check
```
- You can also promote the secondary node to primary **without any further confirmation**, even when preflight checks fail:
+ You can also promote the secondary site to primary **without any further confirmation**, even when preflight checks fail:
```shell
sudo gitlab-ctl promote-to-primary-node --force
```
-1. Verify you can connect to the newly promoted **primary** node using the URL used
- previously for the **secondary** node.
+1. Verify you can connect to the newly promoted **primary** site using the URL used
+ previously for the **secondary** site.
- If successful, the **secondary** node has now been promoted to the **primary** node.
+ If successful, the **secondary** site is now promoted to the **primary** site.
### Next steps
To regain geographic redundancy as quickly as possible, you should
-[add a new **secondary** node](../../setup/index.md). To
+[add a new **secondary** site](../../setup/index.md). To
do that, you can re-add the old **primary** as a new secondary and bring it back
online.
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
index 48091967189..30d8d765dc5 100644
--- a/doc/administration/geo/index.md
+++ b/doc/administration/geo/index.md
@@ -129,25 +129,38 @@ and we recommend you use:
### Firewall rules
-The following table lists basic ports that must be open between the **primary** and **secondary** sites for Geo.
+The following table lists basic ports that must be open between the **primary** and **secondary** sites for Geo. To simplify failovers, we recommend opening ports in both directions.
-| **Primary** site | **Secondary** site | Protocol |
-|:-----------------|:-------------------|:-------------|
-| 80 | 80 | HTTP |
-| 443 | 443 | TCP or HTTPS |
-| 22 | 22 | TCP |
-| 5432 | | PostgreSQL |
+| Source site | Source port | Destination site | Destination port | Protocol |
+|-------------|-------------|------------------|------------------|-------------|
+| Primary | Any | Secondary | 80 | TCP (HTTP) |
+| Primary | Any | Secondary | 443 | TCP (HTTPS) |
+| Secondary | Any | Primary | 80 | TCP (HTTP) |
+| Secondary | Any | Primary | 443 | TCP (HTTPS) |
+| Secondary | Any | Primary | 5432 | TCP |
See the full list of ports used by GitLab in [Package defaults](../package_information/defaults.md)
NOTE:
-[Web terminal](../../ci/environments/index.md#web-terminals) support requires your load balancer to correctly handle WebSocket connections.
+[Web terminal](../../ci/environments/index.md#web-terminals-deprecated) support requires your load balancer to correctly handle WebSocket connections.
When using HTTP or HTTPS proxying, your load balancer must be configured to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the [web terminal](../integration/terminal.md) integration guide for more details.
NOTE:
When using HTTPS protocol for port 443, you need to add an SSL certificate to the load balancers.
If you wish to terminate SSL at the GitLab application server instead, use TCP protocol.
+#### Internal URL
+
+HTTP requests from any Geo secondary site to the primary Geo site use the Internal URL of the primary
+Geo site. If this is not explicitly defined in the primary Geo site settings in the Admin Area, the
+public URL of the primary site will be used.
+
+To update the internal URL of the primary Geo site:
+
+1. On the top bar, go to **Menu > Admin > Geo > Sites**.
+1. Select **Edit** on the primary site.
+1. Change the **Internal URL**, then select **Save changes**.
+
### LDAP
We recommend that if you use LDAP on your **primary** site, you also set up secondary LDAP servers on each **secondary** site. Otherwise, users are unable to perform Git operations over HTTP(s) on the **secondary** site using HTTP Basic Authentication. However, Git via SSH and personal access tokens still works.
@@ -258,6 +271,10 @@ For information on using Geo in disaster recovery situations to mitigate data-lo
For more information on how to replicate the Container Registry, see [Docker Registry for a **secondary** site](replication/docker_registry.md).
+### Geo secondary proxy
+
+For more information on using Geo proxying on secondary nodes, see [Geo proxying for secondary sites](secondary_proxy/index.md).
+
### Security Review
For more information on Geo security, see [Geo security review](replication/security_review.md).
diff --git a/doc/administration/geo/replication/datatypes.md b/doc/administration/geo/replication/datatypes.md
index e8e87f92481..c98436157fc 100644
--- a/doc/administration/geo/replication/datatypes.md
+++ b/doc/administration/geo/replication/datatypes.md
@@ -183,14 +183,13 @@ successfully, you must replicate their data using some other means.
|[Application data in PostgreSQL](../../postgresql/index.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
|[Project repository](../../../user/project/repository/) | **Yes** (10.2) | **Yes** (10.7) | No | |
|[Project wiki repository](../../../user/project/wiki/) | **Yes** (10.2) | **Yes** (10.7) | No | |
-|[Group wiki repository](../../../user/project/wiki/index.md#group-wikis) | [**Yes** (13.10)](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | No | No | Behind feature flag `geo_group_wiki_repository_replication`, enabled by default. |
+|[Group wiki repository](../../../user/project/wiki/group.md) | [**Yes** (13.10)](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | No | No | Behind feature flag `geo_group_wiki_repository_replication`, enabled by default. |
|[Uploads](../../uploads.md) | **Yes** (10.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | No | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them. |
|[LFS objects](../../lfs/index.md) | **Yes** (10.2) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8922) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them. GitLab versions 11.11.x and 12.0.x are affected by [a bug that prevents any new LFS objects from replicating](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).<br /><br />Behind feature flag `geo_lfs_object_replication`, enabled by default. |
|[Personal snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
|[Project snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
-|[CI job artifacts (other than Job Logs)](../../../ci/pipelines/job_artifacts.md) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them. |
+|[CI job artifacts](../../../ci/pipelines/job_artifacts.md) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them. Job logs also verified on transfer. |
|[CI Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/pipeline_artifact.rb) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | Via Object Storage provider if supported. Native Geo support (Beta). | Persists additional artifacts after a pipeline completes |
-|[Job logs](../../job_logs.md) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them. |
|[Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | No | Disabled by default. See [instructions](docker_registry.md) to enable. |
|[Content in object storage (beta)](object_storage.md) | **Yes** (12.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/13845) | No | |
|[Infrastructure Registry](../../../user/packages/infrastructure_registry/index.md) | **Yes** (14.0) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (14.0) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
diff --git a/doc/administration/geo/replication/disable_geo.md b/doc/administration/geo/replication/disable_geo.md
index ae2597ad649..02a65f0b8e1 100644
--- a/doc/administration/geo/replication/disable_geo.md
+++ b/doc/administration/geo/replication/disable_geo.md
@@ -28,7 +28,7 @@ To disable Geo, you need to first remove all your secondary Geo sites, which mea
anymore on these sites. You can follow our docs to [remove your secondary Geo sites](remove_geo_site.md).
If the current site that you want to keep using is a secondary site, you need to first promote it to primary.
-You can use our steps on [how to promote a secondary site](../disaster_recovery/#step-3-promoting-a-secondary-node)
+You can use our steps on [how to promote a secondary site](../disaster_recovery/#step-3-promoting-a-secondary-site)
to do that.
## Remove the primary site from the UI
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index b7370d32056..432d042608c 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -455,7 +455,7 @@ To solve this:
1. Back up [the `.git` folder](../../repository_storage_types.md#translate-hashed-storage-paths).
-1. Optional: [Spot-check](../../troubleshooting/log_parsing.md#find-all-projects-affected-by-a-fatal-git-problem))
+1. Optional: [Spot-check](../../troubleshooting/log_parsing.md#find-all-projects-affected-by-a-fatal-git-problem)
a few of those IDs whether they indeed correspond
to a project with known Geo replication failures.
Use `fatal: 'geo'` as the `grep` term and the following API call:
@@ -683,7 +683,7 @@ when promoting a secondary to a primary node with strategies to resolve them.
### Message: ActiveRecord::RecordInvalid: Validation failed: Name has already been taken
-When [promoting a **secondary** node](../disaster_recovery/index.md#step-3-promoting-a-secondary-node),
+When [promoting a **secondary** site](../disaster_recovery/index.md#step-3-promoting-a-secondary-site),
you might encounter the following error:
```plaintext
@@ -723,21 +723,35 @@ If you disabled a secondary node, either with the [replication pause task](../in
(13.2) or by using the user interface (13.1 and earlier), you must first
re-enable the node before you can continue. This is fixed in 13.4.
-Run the following command, replacing `https://<secondary url>/` with the URL
-for your secondary server, using either `http` or `https`, and ensuring that you
-end the URL with a slash (`/`):
+This can be fixed in the database.
-```shell
-sudo gitlab-rails dbconsole
+1. Start a database console:
-UPDATE geo_nodes SET enabled = true WHERE url = 'https://<secondary url>/' AND enabled = false;"
-```
+ In [GitLab 14.2 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/341210):
+
+ ```shell
+ sudo gitlab-rails dbconsole --database main
+ ```
+
+ In GitLab 14.1 and earlier:
+
+ ```shell
+ sudo gitlab-rails dbconsole
+ ```
+
+1. Run the following command, replacing `https://<secondary url>/` with the URL
+ for your secondary server. You can use either `http` or `https`, but ensure that you
+ end the URL with a slash (`/`):
+
+ ```sql
+ UPDATE geo_nodes SET enabled = true WHERE url = 'https://<secondary url>/' AND enabled = false;"
+ ```
-This should update 1 row.
+ This should update 1 row.
### Message: ``NoMethodError: undefined method `secondary?' for nil:NilClass``
-When [promoting a **secondary** node](../disaster_recovery/index.md#step-3-promoting-a-secondary-node),
+When [promoting a **secondary** site](../disaster_recovery/index.md#step-3-promoting-a-secondary-site),
you might encounter the following error:
```plaintext
@@ -753,13 +767,13 @@ Tasks: TOP => geo:set_secondary_as_primary
(See full trace by running task with --trace)
```
-This command is intended to be executed on a secondary node only, and this error
-is displayed if you attempt to run this command on a primary node.
+This command is intended to be executed on a secondary site only, and this error
+is displayed if you attempt to run this command on a primary site.
### Message: `sudo: gitlab-pg-ctl: command not found`
When
-[promoting a **secondary** node with multiple servers](../disaster_recovery/index.md#promoting-a-secondary-node-with-multiple-servers),
+[promoting a **secondary** site with multiple nodes](../disaster_recovery/index.md#promoting-a-secondary-site-with-multiple-nodes-running-gitlab-144-and-earlier),
you need to run the `gitlab-pg-ctl` command to promote the PostgreSQL
read-replica database.
diff --git a/doc/administration/geo/secondary_proxy/img/single_url_add_traffic_policy_endpoints.png b/doc/administration/geo/secondary_proxy/img/single_url_add_traffic_policy_endpoints.png
new file mode 100644
index 00000000000..d1c4afceb04
--- /dev/null
+++ b/doc/administration/geo/secondary_proxy/img/single_url_add_traffic_policy_endpoints.png
Binary files differ
diff --git a/doc/administration/geo/secondary_proxy/img/single_url_create_policy_records_with_traffic_policy.png b/doc/administration/geo/secondary_proxy/img/single_url_create_policy_records_with_traffic_policy.png
new file mode 100644
index 00000000000..3bad391f220
--- /dev/null
+++ b/doc/administration/geo/secondary_proxy/img/single_url_create_policy_records_with_traffic_policy.png
Binary files differ
diff --git a/doc/administration/geo/secondary_proxy/index.md b/doc/administration/geo/secondary_proxy/index.md
new file mode 100644
index 00000000000..2b8c0d1e6fa
--- /dev/null
+++ b/doc/administration/geo/secondary_proxy/index.md
@@ -0,0 +1,127 @@
+---
+stage: Enablement
+group: Geo
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: howto
+---
+
+# Geo proxying for secondary sites **(PREMIUM SELF)**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5914) in GitLab 14.4 [with a flag](../../feature_flags.md) named `geo_secondary_proxy`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. See below to [Set up a unified URL for Geo sites](#set-up-a-unified-url-for-geo-sites).
+The feature is not ready for production use.
+
+Use Geo proxying to:
+
+- Have secondary sites serve read-write traffic by proxying to the primary site.
+- Selectively accelerate replicated data types by directing read-only operations to the local site instead.
+
+When enabled, users of the secondary site can use the WebUI as if they were accessing the
+primary site's UI. This significantly improves the overall user experience of secondary sites.
+
+With secondary proxying, web requests to secondary Geo sites are
+proxied directly to the primary, and appear to act as a read-write site.
+
+Proxying is done by the [`gitlab-workhorse`](https://gitlab.com/gitlab-org/gitlab-workhorse) component.
+Traffic usually sent to the Rails application on the Geo secondary site is proxied
+to the [internal URL](../index.md#internal-url) of the primary Geo site instead.
+
+Use secondary proxying for use-cases including:
+
+- Having all Geo sites behind a single URL.
+- Geographically load-balancing traffic without worrying about write access.
+
+## Set up a unified URL for Geo sites
+
+Secondary sites can transparently serve read-write traffic. You can
+use a single external URL so that requests can hit either the primary Geo site
+or any secondary Geo sites that use Geo proxying.
+
+### Configure an external URL to send traffic to both sites
+
+Follow the [Location-aware public URL](location_aware_external_url.md) steps to create
+a single URL used by all Geo sites, including the primary.
+
+### Update the Geo sites to use the same external URL
+
+1. On your Geo sites, SSH **into each node running Rails (Puma, Sidekiq, Log-Cursor)
+ and change the `external_url` to that of the single URL:
+
+ ```shell
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+1. Reconfigure the updated nodes for the change to take effect if the URL was different than the one already set:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
+1. To match the new external URL set on the secondary Geo sites, the primary database
+ needs to reflect this change.
+
+ In the Geo administration page of the **primary** site, edit each Geo secondary that
+ is using the secondary proxying and set the `URL` field to the single URL.
+ Make sure the primary site is also using this URL.
+
+### Enable secondary proxying
+
+1. SSH into each application node (serving user traffic directly) on your secondary Geo site
+ and add the following environment variable:
+
+ ```shell
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ ```ruby
+ gitlab_workhorse['env'] = {
+ "GEO_SECONDARY_PROXY" => "1"
+ }
+ ```
+
+1. Reconfigure the updated nodes for the change to take effect:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
+1. SSH into one node running Rails on your primary Geo site and enable the Geo secondary proxy feature flag:
+
+ ```shell
+ sudo gitlab-rails runner "Feature.enable(:geo_secondary_proxy)"
+ ```
+
+## Enable Geo proxying with Separate URLs
+
+The ability to use proxying with separate URLs is still in development. You can follow the
+["Geo secondary proxying with separate URLs" epic](https://gitlab.com/groups/gitlab-org/-/epics/6865)
+for progress.
+
+## Features accelerated by secondary Geo sites
+
+Most HTTP traffic sent to a secondary Geo site can be proxied to the primary Geo site. With this architecture,
+secondary Geo sites are able to support write requests. Certain **read** requests are handled locally by secondary
+sites for improved latency and bandwidth nearby. All write requests are proxied to the primary site.
+
+The following table details the components currently tested through the Geo secondary site Workhorse proxy.
+It does not cover all data types, more will be added in the future as they are tested.
+
+| Feature / component | Accelerated reads? |
+|:----------------------------------------------------|:-----------------------|
+| Project, wiki, design repository (using the web UI) | **{dotted-circle}** No |
+| Project, wiki repository (using Git) | **{check-circle}** Yes <sup>1</sup> |
+| Project, Personal Snippet (using the web UI) | **{dotted-circle}** No |
+| Project, Personal Snippet (using Git) | **{check-circle}** Yes <sup>1</sup> |
+| Group wiki repository (using the web UI) | **{dotted-circle}** No |
+| Group wiki repository (using Git) | **{check-circle}** Yes <sup>1</sup> |
+| User uploads | **{dotted-circle}** No |
+| LFS objects (using the web UI) | **{dotted-circle}** No |
+| LFS objects (using Git) | **{check-circle}** Yes |
+| Pages | **{dotted-circle}** No <sup>2</sup> |
+| Advanced search (using the web UI) | **{dotted-circle}** No |
+
+1. Git reads are served from the local secondary while pushes get proxied to the primary.
+ Selective sync or cases where repositories don't exist locally on the Geo secondary throw a "not found" error.
+1. Pages can use the same URL (without access control), but must be configured separately and are not proxied.
diff --git a/doc/administration/geo/secondary_proxy/location_aware_external_url.md b/doc/administration/geo/secondary_proxy/location_aware_external_url.md
new file mode 100644
index 00000000000..b5a8d4baa1f
--- /dev/null
+++ b/doc/administration/geo/secondary_proxy/location_aware_external_url.md
@@ -0,0 +1,83 @@
+---
+stage: Enablement
+group: Geo
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: howto
+---
+
+# Location-aware public URL **(PREMIUM SELF)**
+
+With [Geo proxying for secondary sites](index.md), you can provide GitLab users
+with a single URL that automatically uses the Geo site closest to them.
+Users don't need to use different URLs or worry about read-only operations to take
+advantage of closer Geo sites as they move.
+
+With [Geo proxying for secondary sites](index.md) web and Git requests are proxied
+from **secondary** sites to the **primary**.
+
+Though these instructions use [AWS Route53](https://aws.amazon.com/route53/),
+other services such as [Cloudflare](https://www.cloudflare.com/) can be used
+as well.
+
+## Prerequisites
+
+This example creates a `gitlab.example.com` subdomain that automatically directs
+requests:
+
+- From Europe to a **secondary** site.
+- From all other locations to the **primary** site.
+
+The URLs to access each node by itself are:
+
+- `primary.example.com` as a Geo **primary** site.
+- `secondary.example.com` as a Geo **secondary** site.
+
+For this example, you need:
+
+- A working GitLab **primary** site that is accessible at `gitlab.example.com` _and_ `primary.example.com`.
+- A working GitLab **secondary** site.
+- A Route53 Hosted Zone managing your domain for the Route53 setup.
+
+If you haven't yet set up a Geo _primary_ site and _secondary_ site, see the
+[Geo setup instructions](../index.md#setup-instructions).
+
+## AWS Route53
+
+### Create a traffic policy
+
+In a Route53 Hosted Zone, traffic policies can be used to set up a variety of
+routing configurations.
+
+1. Go to the
+[Route53 dashboard](https://console.aws.amazon.com/route53/home) and select
+**Traffic policies**.
+
+1. Select **Create traffic policy**.
+1. Fill in the **Policy Name** field with `Single Git Host` and select **Next**.
+1. Leave **DNS type** as `A: IP Address in IPv4 format`.
+1. Select **Connect to...**, then **Geolocation rule**.
+1. For the first **Location**:
+ 1. Leave it as `Default`.
+ 1. Select **Connect to...**, then **New endpoint**.
+ 1. Choose **Type** `value` and fill it in with `<your **primary** IP address>`.
+
+1. For the second **Location**:
+ 1. Choose `Europe`.
+ 1. Select **Connect to...** and select **New endpoint**.
+ 1. Choose **Type** `value` and fill it in with `<your **secondary** IP address>`.
+
+ ![Add traffic policy endpoints](img/single_url_add_traffic_policy_endpoints.png)
+
+1. Select **Create traffic policy**.
+1. Fill in **Policy record DNS name** with `gitlab`.
+
+ ![Create policy records with traffic policy](img/single_url_create_policy_records_with_traffic_policy.png)
+
+1. Select **Create policy records**.
+
+You have successfully set up a single host, like `gitlab.example.com`, which
+distributes traffic to your Geo sites by geolocation.
+
+## Enable Geo proxying for secondary sites
+
+After setting up a single URL to use for all Geo sites, continue with the [steps to enable Geo proxying for secondary sites](index.md).
diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md
index d72bb0737ae..7f4c771c962 100644
--- a/doc/administration/geo/setup/database.md
+++ b/doc/administration/geo/setup/database.md
@@ -7,23 +7,21 @@ type: howto
# Geo database replication **(PREMIUM SELF)**
-NOTE:
-If your GitLab installation uses external (not managed by Omnibus) PostgreSQL
-instances, the Omnibus roles are unable to perform all necessary
-configuration steps. In this case,
-[follow the Geo with external PostgreSQL instances document instead](external_database.md).
+This document describes the minimal required steps to replicate your primary
+GitLab database to a secondary node's database. You may have to change some
+values, based on attributes including your database's setup and size.
NOTE:
-The stages of the setup process must be completed in the documented order.
-Before attempting the steps in this stage, [complete all prior stages](../setup/index.md#using-omnibus-gitlab).
+If your GitLab installation uses external (not managed by Omnibus GitLab)
+PostgreSQL instances, the Omnibus roles cannot perform all necessary
+configuration steps. In this case, use the [Geo with external PostgreSQL instances](external_database.md)
+process instead.
-This document describes the minimal steps you have to take to replicate your
-**primary** GitLab database to a **secondary** node's database. You may have to
-change some values, based on attributes including your database's setup and
-size.
+The stages of the setup process must be completed in the documented order.
+Before you attempt the steps in this stage, [complete all prior stages](../setup/index.md#using-omnibus-gitlab).
-You are encouraged to first read through all the steps before executing them
-in your testing/production environment.
+Be sure to read and review all of these steps before you execute them in your
+testing or production environments.
## Single instance database replication
@@ -214,7 +212,7 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
## - Prevents automatic upgrade of Postgres since it requires downtime of
## streaming replication to Geo secondary sites
## - Enables standard single-node GitLab services like NGINX, Puma, Redis,
- ## Sidekiq, etc. If you are segregating services, then you will need to
+ ## or Sidekiq. If you are segregating services, then you will need to
## explicitly disable unwanted services.
##
roles(['geo_primary_role'])
@@ -690,8 +688,8 @@ could do it with [HAProxy](https://www.haproxy.org/).
The following IPs and names are used as an example:
- `10.6.0.21`: Patroni 1 (`patroni1.internal`)
-- `10.6.0.21`: Patroni 2 (`patroni2.internal`)
-- `10.6.0.22`: Patroni 3 (`patroni3.internal`)
+- `10.6.0.22`: Patroni 2 (`patroni2.internal`)
+- `10.6.0.23`: Patroni 3 (`patroni3.internal`)
```plaintext
global
@@ -716,7 +714,7 @@ backend postgresql
server patroni1.internal 10.6.0.21:5432 maxconn 100 check port 8008
server patroni2.internal 10.6.0.22:5432 maxconn 100 check port 8008
- server patroni3.internal 10.6.0.23.195:5432 maxconn 100 check port 8008
+ server patroni3.internal 10.6.0.23:5432 maxconn 100 check port 8008
```
Refer to your preferred Load Balancer's documentation for further guidance.
diff --git a/doc/administration/geo/setup/external_database.md b/doc/administration/geo/setup/external_database.md
index 13dbf9d1434..756e73f022f 100644
--- a/doc/administration/geo/setup/external_database.md
+++ b/doc/administration/geo/setup/external_database.md
@@ -8,7 +8,7 @@ type: howto
# Geo with external PostgreSQL instances **(PREMIUM SELF)**
This document is relevant if you are using a PostgreSQL instance that is *not
-managed by Omnibus*. This includes cloud-managed instances like AWS RDS, or
+managed by Omnibus*. This includes cloud-managed instances like Amazon RDS, or
manually installed and configured PostgreSQL instances.
NOTE:
@@ -58,7 +58,7 @@ developed and tested. We aim to be compatible with most external
To set up an external database, you can either:
-- Set up [streaming replication](https://www.postgresql.org/docs/12/warm-standby.html#STREAMING-REPLICATION-SLOTS) yourself (for example AWS RDS, bare metal not managed by Omnibus, and so on).
+- Set up [streaming replication](https://www.postgresql.org/docs/12/warm-standby.html#STREAMING-REPLICATION-SLOTS) yourself (for example Amazon RDS, bare metal not managed by Omnibus, and so on).
- Perform the Omnibus configuration manually as follows.
#### Leverage your cloud provider's tools to replicate the primary database
@@ -200,7 +200,7 @@ This is for the installation of extensions during installation and upgrades. As
To setup an external tracking database, follow the instructions below:
NOTE:
-If you want to use AWS RDS as a tracking database, make sure it has access to
+If you want to use Amazon RDS as a tracking database, make sure it has access to
the secondary database. Unfortunately, just assigning the same security group is not enough as
outbound rules do not apply to RDS PostgreSQL databases. Therefore, you need to explicitly add an inbound
rule to the read-replica's security group allowing any TCP traffic from
diff --git a/doc/administration/get_started.md b/doc/administration/get_started.md
index 2455aecafea..bff2aee1d2d 100644
--- a/doc/administration/get_started.md
+++ b/doc/administration/get_started.md
@@ -44,7 +44,7 @@ Get started:
**More resources**
- Learn more about [running multiple Agile teams](https://www.youtube.com/watch?v=VR2r1TJCDew).
-- Sync group memberships [by using LDAP](../administration/auth/ldap/index.md#group-sync).
+- Sync group memberships [by using LDAP](../administration/auth/ldap/ldap_synchronization.md#group-sync).
- Manage user access with inherited permissions. Use up to 20 levels of subgroups to organize both teams and projects.
- Learn more about [inherited permissions](../user/project/members/index.md#inherited-membership).
- View [nested category examples](../user/group/subgroups/index.md#overview).
@@ -231,7 +231,7 @@ Rate limits also improve the security of your application.
### Configure rate limits for self-managed GitLab
-You can make changes to your default rate limits from the Admin Area. For more information about configuration, see the [Admin Area page](../security/rate_limits.md#admin-area-settings).
+You can make changes to your default rate limits from the Admin Area. For more information about configuration, see the [Admin Area page](../security/rate_limits.md#configurable-limits).
- Define [issues rate limits](../user/admin_area/settings/rate_limit_on_issues_creation.md) to set a maximum number of issue creation requests per minute, per user.
- Enforce [user and IP rate limits](../user/admin_area/settings/user_and_ip_rate_limits.md) for unauthenticated web requests.
@@ -249,7 +249,7 @@ Rate limits also improve the security of your application.
### Configure rate limits for GitLab SaaS
-You can make changes to your default rate limits from the Admin Area. For more information about configuration, see the [Admin Area page](../security/rate_limits.md#admin-area-settings).
+You can make changes to your default rate limits from the Admin Area. For more information about configuration, see the [Admin Area page](../security/rate_limits.md#configurable-limits).
- Review the rate limit page.
- Read our [API page](../api/index.md) for more information about API and rate limiting.
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index d3ea71bc8d2..da456131a52 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -851,6 +851,10 @@ of choice already. Some examples include [HAProxy](https://www.haproxy.org/)
Big-IP LTM, and Citrix Net Scaler. This documentation outlines what ports
and protocols you need configure.
+WARNING:
+Long-running background jobs can maintain an idle connection with Praefect for up 6 hours. Set your load balancer timeout to be at least
+6 hours long.
+
| LB Port | Backend Port | Protocol |
|:--------|:-------------|:---------|
| 2305 | 2305 | TCP |
diff --git a/doc/administration/gitaly/troubleshooting.md b/doc/administration/gitaly/troubleshooting.md
index 1f90ebb7565..d6d93b8af94 100644
--- a/doc/administration/gitaly/troubleshooting.md
+++ b/doc/administration/gitaly/troubleshooting.md
@@ -157,7 +157,7 @@ Confirm the following are all true:
successfully creates the project but doesn't create the README.
- When [tailing the logs](https://docs.gitlab.com/omnibus/settings/logs.html#tail-logs-in-a-console-on-the-server)
on a Gitaly client and reproducing the error, you get `401` errors
- when reaching the [`/api/v4/internal/allowed`](../../development/internal_api.md) endpoint:
+ when reaching the [`/api/v4/internal/allowed`](../../development/internal_api/index.md) endpoint:
```shell
# api_json.log
diff --git a/doc/administration/img/audit_events_v14_5.png b/doc/administration/img/audit_events_v14_5.png
new file mode 100644
index 00000000000..57190463d05
--- /dev/null
+++ b/doc/administration/img/audit_events_v14_5.png
Binary files differ
diff --git a/doc/administration/img/audit_log_v13_6.png b/doc/administration/img/audit_log_v13_6.png
deleted file mode 100644
index 82ff3e9c87b..00000000000
--- a/doc/administration/img/audit_log_v13_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index 5b72583bc95..6b390cfc77a 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -155,6 +155,50 @@ Reply by email should now be working.
1. Find the `incoming_email` section in `config/gitlab.yml`, enable the feature
and fill in the details for your specific IMAP server and email account (see [examples](#configuration-examples) below).
+If you use systemd units to manage GitLab:
+
+1. Add `gitlab-mailroom.service` as a dependency to `gitlab.target`:
+
+ ```shell
+ sudo systemctl edit gitlab.target
+ ```
+
+ In the editor that opens, add the following and save the file:
+
+ ```plaintext
+ [Unit]
+ Wants=gitlab-mailroom.service
+ ```
+
+1. If you run Redis and PostgreSQL on the same machine, you should add a
+ dependency on Redis. Run:
+
+ ```shell
+ sudo systemctl edit gitlab-mailroom.service
+ ```
+
+ In the editor that opens, add the following and save the file:
+
+ ```plaintext
+ [Unit]
+ Wants=redis-server.service
+ After=redis-server.service
+ ```
+
+1. Start `gitlab-mailroom.service`:
+
+ ```shell
+ sudo systemctl start gitlab-mailroom.service
+ ```
+
+1. Verify that everything is configured correctly:
+
+ ```shell
+ sudo -u git -H bundle exec rake gitlab:incoming_email:check RAILS_ENV=production
+ ```
+
+If you use the SysV init script to manage GitLab:
+
1. Enable `mail_room` in the init script at `/etc/default/gitlab`:
```shell
diff --git a/doc/administration/index.md b/doc/administration/index.md
index ee17edc35fc..53a3c305aab 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -114,7 +114,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Mattermost](../integration/mattermost/index.md): Integrate with [Mattermost](https://mattermost.com), an open source, private cloud workplace for web messaging.
- [PlantUML](integration/plantuml.md): Create diagrams in AsciiDoc and Markdown documents
created in snippets, wikis, and repositories.
-- [Web terminals](integration/terminal.md): Provide terminal access to your applications deployed to Kubernetes from GitLab CI/CD [environments](../ci/environments/index.md#web-terminals).
+- [Web terminals](integration/terminal.md): Provide terminal access to your applications deployed to Kubernetes from GitLab CI/CD [environments](../ci/environments/index.md#web-terminals-deprecated).
## User settings and permissions
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index a2729e60545..0b470146b14 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -15,9 +15,7 @@ performance, data, or could even exhaust the allocated resources for the applica
Rate limits can be used to improve the security and durability of GitLab.
-For example, one script can make thousands of web requests per second. Whether malicious, apathetic, or just a bug, your application and infrastructure may not be able to cope with the load. Rate limits can help to mitigate these types of attacks.
-
-Read more about [configuring rate limits](../security/rate_limits.md) in the Security documentation.
+Read more about [configuring rate limits](../security/rate_limits.md).
### Issue creation
@@ -128,16 +126,6 @@ This setting limits the import/export actions for groups and projects.
Read more about [import/export rate limits](../user/admin_area/settings/import_export_rate_limits.md).
-### Rack attack
-
-This method of rate limiting is cumbersome, but has some advantages. It allows
-throttling of specific paths, and is also integrated into Git and container
-registry requests.
-
-Read more about the [Rack Attack initializer](../security/rack_attack.md) method of setting rate limits.
-
-- **Default rate limit**: Disabled.
-
### Member Invitations
Limit the maximum daily member invitations allowed per group hierarchy.
@@ -155,6 +143,9 @@ This only applies to project and group webhooks.
Calls over the rate limit are logged into `auth.log`.
+To set this limit for a self-managed installation, run the following in the
+[GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
+
```ruby
# If limits don't exist for the default plan, you can create one with:
# Plan.default.create_limits!
@@ -222,10 +213,12 @@ When the number exceeds the limit the page displays an alert and links to a pagi
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51401) in GitLab 11.10.
The number of pipelines that can be created in a single push is 4.
-This is to prevent the accidental creation of pipelines when `git push --all`
+This limit prevents the accidental creation of pipelines when `git push --all`
or `git push --mirror` is used.
-Read more in the [CI documentation](../ci/yaml/index.md#processing-git-pushes).
+This limit does not affect any of the updated merge request pipelines.
+All updated merge requests have a pipeline created when using
+[pipelines for merge requests](../ci/pipelines/merge_request_pipelines.md).
## Retention of activity history
@@ -397,6 +390,27 @@ Plan.default.actual_limits.update!(ci_project_subscriptions: 500)
Set the limit to `0` to disable it.
+### Limit the number of pipeline triggers
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33696) in GitLab 14.6.
+
+You can set a limit on the maximum number of pipeline triggers per project. This
+limit is checked every time a new trigger is created.
+
+If a new trigger would cause the total number of pipeline triggers to exceed the
+limit, the trigger is considered invalid.
+
+Set the limit to `0` to disable it. Defaults to `0` on self-managed instances.
+
+To set this limit to `100` on a self-managed installation, run the following in the
+[GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
+
+```ruby
+Plan.default.actual_limits.update!(pipeline_triggers: 100)
+```
+
+This limit is [enabled on GitLab.com](../user/gitlab_com/index.md#gitlab-cicd).
+
### Number of pipeline schedules
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29566) in GitLab 12.10.
@@ -543,6 +557,7 @@ Plan.default.actual_limits.update!(pages_file_entries: 100)
The total number of registered runners is limited at the group and project levels. Each time a new runner is registered,
GitLab checks these limits against runners that have been active in the last 3 months.
A runner's registration fails if it exceeds the limit for the scope determined by the runner registration token.
+If the limit value is set to zero, the limit is disabled.
- GitLab SaaS subscribers have different limits defined per plan, affecting all projects using that plan.
- Self-managed GitLab Premium and Ultimate limits are defined by a default plan that affects all projects:
@@ -590,25 +605,64 @@ Plan.default.actual_limits.update!(dast_profile_schedules: 50)
### Maximum size and depth of CI/CD configuration YAML files
-The default maximum size of a CI/CD configuration YAML file is 1 megabyte and the default depth is 100.
+The default maximum size of a CI/CD configuration YAML file is 1 megabyte and the
+default depth is 100.
+
+You can change these limits in the [GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
+
+- To update the maximum YAML size, update `max_yaml_size_bytes` with the new value in megabytes:
+
+ ```ruby
+ ApplicationSetting.update!(max_yaml_size_bytes: 2.megabytes)
+ ```
-You can change these limits in the [GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session).
-Update `max_yaml_size_bytes` with the new value in megabytes:
+ The `max_yaml_size_bytes` value is not directly tied to the size of the YAML file,
+ but rather the memory allocated for the relevant objects.
+
+- To update the maximum YAML depth, update `max_yaml_depth` with the new value in megabytes:
+
+ ```ruby
+ ApplicationSetting.update!(max_yaml_depth: 125)
+ ```
+
+To disable this limitation entirely, disable the feature flag in the console:
```ruby
-ApplicationSetting.update!(max_yaml_size_bytes: 2.megabytes)
+Feature.disable(:ci_yaml_limit_size)
```
-Update `max_yaml_depth` with the new value in megabytes:
+### Limit dotenv variables
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321552) in GitLab 14.5.
+
+You can set a limit on the maximum number of variables inside of a dotenv artifact.
+This limit is checked every time a dotenv file is exported as an artifact.
+
+Set the limit to `0` to disable it. Defaults to `0` on self-managed instances.
+
+To set this limit to `100` on a self-managed instance, run the following command in the
+[GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
```ruby
-ApplicationSetting.update!(max_yaml_depth: 125)
+Plan.default.actual_limits.update!(dotenv_variable_limit: 100)
```
-To disable this limitation entirely, disable the feature flag in the console:
+This limit is [enabled on GitLab.com](../user/gitlab_com/index.md#gitlab-cicd).
+
+### Limit dotenv file size
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321552) in GitLab 14.5.
+
+You can set a limit on the maximum size of a dotenv artifact. This limit is checked
+every time a dotenv file is exported as an artifact.
+
+Set the limit to `0` to disable it. Defaults to 5KB.
+
+To set this limit to 5KB on a self-managed installation, run the following in the
+[GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
```ruby
-Feature.disable(:ci_yaml_limit_size)
+Plan.default.actual_limits.update!(dotenv_size_limit: 5.kilobytes)
```
## Instance monitoring and metrics
@@ -837,6 +891,17 @@ Set the limit to `0` to allow any file size.
When asking for versions of a given NuGet package name, the GitLab Package Registry returns a maximum of 300 versions.
+## Dependency Proxy Limits
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6396) in GitLab 14.5.
+
+The maximum file size for an image cached in the
+[Dependency Proxy](../user/packages/dependency_proxy/index.md)
+varies by file type:
+
+- Image blob: 5 GB
+- Image manifest: 10 MB
+
## Branch retargeting on merge
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/320902) in GitLab 13.9.
diff --git a/doc/administration/integration/terminal.md b/doc/administration/integration/terminal.md
index 45b94781adc..07b9ba87d8e 100644
--- a/doc/administration/integration/terminal.md
+++ b/doc/administration/integration/terminal.md
@@ -4,12 +4,17 @@ group: Integrations
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Web terminals **(FREE)**
+# Web terminals (DEPRECATED) **(FREE)**
+
+> [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
With the introduction of the [Kubernetes integration](../../user/infrastructure/clusters/index.md),
GitLab can store and use credentials for a Kubernetes cluster.
GitLab uses these credentials to provide access to
-[web terminals](../../ci/environments/index.md#web-terminals) for environments.
+[web terminals](../../ci/environments/index.md#web-terminals-deprecated) for environments.
NOTE:
Only project maintainers and owners can access web terminals.
diff --git a/doc/administration/load_balancer.md b/doc/administration/load_balancer.md
index ca66791166e..60293e56202 100644
--- a/doc/administration/load_balancer.md
+++ b/doc/administration/load_balancer.md
@@ -7,7 +7,7 @@ type: reference
# Load Balancer for multi-node GitLab **(FREE SELF)**
-In an multi-node GitLab configuration, you need a load balancer to route
+In a multi-node GitLab configuration, you need a load balancer to route
traffic to the application servers. The specifics on which load balancer to use
or the exact configuration is beyond the scope of GitLab documentation. We hope
that if you're managing HA systems like GitLab you have a load balancer of
@@ -69,7 +69,7 @@ for details on managing SSL certificates and configuring NGINX.
| 443 | 443 | TCP or HTTPS (*1*) (*2*) |
| 22 | 22 | TCP |
-- (*1*): [Web terminal](../ci/environments/index.md#web-terminals) support requires
+- (*1*): [Web terminal](../ci/environments/index.md#web-terminals-deprecated) support requires
your load balancer to correctly handle WebSocket connections. When using
HTTP or HTTPS proxying, this means your load balancer must be configured
to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index a9fd698a525..bf74a96a627 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -752,7 +752,6 @@ Depending on your installation method, this file is located at:
This log records:
-- Information whenever [Rack Attack](../security/rack_attack.md) registers an abusive request.
- Requests over the [Rate Limit](../user/admin_area/settings/rate_limits_on_raw_endpoints.md) on raw endpoints.
- [Protected paths](../user/admin_area/settings/protected_paths.md) abusive requests.
- In GitLab versions [12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/29239) and later,
diff --git a/doc/administration/maintenance_mode/index.md b/doc/administration/maintenance_mode/index.md
index d5bcd132665..2d17062e955 100644
--- a/doc/administration/maintenance_mode/index.md
+++ b/doc/administration/maintenance_mode/index.md
@@ -119,7 +119,7 @@ For most JSON requests, POST, PUT, PATCH, and DELETE are blocked, and the API re
| POST | `/admin/session`, `/admin/session/destroy` | To allow [Administrator mode for GitLab administrators](https://gitlab.com/groups/gitlab-org/-/epics/2158) |
| POST | Paths ending with `/compare`| Git revision routes. |
| POST | `.git/git-upload-pack` | To allow Git pull/clone. |
-| POST | `/api/v4/internal` | [internal API routes](../../development/internal_api.md) |
+| POST | `/api/v4/internal` | [internal API routes](../../development/internal_api/index.md) |
| POST | `/admin/sidekiq` | To allow management of background jobs in the Admin UI |
| POST | `/admin/geo` | To allow updating Geo Nodes in the administrator UI |
| POST | `/api/v4/geo_replication`| To allow certain Geo-specific administrator UI actions on secondary sites |
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index 0befd9eac5b..d798feb71a9 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -114,7 +114,7 @@ for a given group:
1. On the left sidebar, select **Settings > Metrics and profiling**
(`admin/application_settings/metrics_and_profiling`), and expand
**Profiling - Performance bar**.
-1. Click **Allow non-administrators to access to the performance bar**.
+1. Click **Allow non-administrators access to the performance bar**.
1. In the **Allow access to members of the following group** field, provide the full path of the
group allowed to access the performance.
1. Click **Save changes**.
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index 1d275010556..2f9c1e3bc9c 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -41,6 +41,7 @@ The following metrics are available:
| `gitlab_cache_misses_total` | Counter | 10.2 | Cache read miss | `controller`, `action` |
| `gitlab_cache_operation_duration_seconds` | Histogram | 10.2 | Cache access time | |
| `gitlab_cache_operations_total` | Counter | 12.2 | Cache operations by controller or action | `controller`, `action`, `operation` |
+| `gitlab_ci_pipeline_builder_scoped_variables_duration` | Histogram | 14.5 | Time in seconds it takes to create the scoped variables for a CI/CD job
| `gitlab_ci_pipeline_creation_duration_seconds` | Histogram | 13.0 | Time in seconds it takes to create a CI/CD pipeline | |
| `gitlab_ci_pipeline_size_builds` | Histogram | 13.1 | Total number of builds within a pipeline grouped by a pipeline source | `source` |
| `job_waiter_started_total` | Counter | 12.9 | Number of batches of jobs started where a web request is waiting for the jobs to complete | `worker` |
@@ -143,7 +144,7 @@ The following metrics are available:
| `gitlab_snowplow_events_total` | Counter | 14.1 | Total number of GitLab Snowplow product intelligence events emitted | |
| `gitlab_snowplow_failed_events_total` | Counter | 14.1 | Total number of GitLab Snowplow product intelligence events emission failures | |
| `gitlab_snowplow_successful_events_total` | Counter | 14.1 | Total number of GitLab Snowplow product intelligence events emission successes | |
-| `gitlab_ci_build_trace_errors_total` | Counter | 14.4 | Total amount of different error types on a build trace | `type` |
+| `gitlab_ci_build_trace_errors_total` | Counter | 14.4 | Total amount of different error types on a build trace | `error_reason` |
## Metrics controlled by a feature flag
@@ -189,9 +190,6 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `geo_lfs_objects` | Gauge | 10.2 | Total number of LFS objects available on primary | `url` |
| `geo_lfs_objects_synced` | Gauge | 10.2 | Number of LFS objects synced on secondary | `url` |
| `geo_lfs_objects_failed` | Gauge | 10.2 | Number of LFS objects failed to sync on secondary | `url` |
-| `geo_attachments` | Gauge | 10.2 | Total number of file attachments available on primary | `url` |
-| `geo_attachments_synced` | Gauge | 10.2 | Number of attachments synced on secondary | `url` |
-| `geo_attachments_failed` | Gauge | 10.2 | Number of attachments failed to sync on secondary | `url` |
| `geo_last_event_id` | Gauge | 10.2 | Database ID of the latest event log entry on the primary | `url` |
| `geo_last_event_timestamp` | Gauge | 10.2 | UNIX timestamp of the latest event log entry on the primary | `url` |
| `geo_cursor_last_event_id` | Gauge | 10.2 | Last database ID of the event log processed by the secondary | `url` |
@@ -200,7 +198,6 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `geo_last_successful_status_check_timestamp` | Gauge | 10.2 | Last timestamp when the status was successfully updated | `url` |
| `geo_lfs_objects_synced_missing_on_primary` | Gauge | 10.7 | Number of LFS objects marked as synced due to the file missing on the primary | `url` |
| `geo_job_artifacts_synced_missing_on_primary` | Gauge | 10.7 | Number of job artifacts marked as synced due to the file missing on the primary | `url` |
-| `geo_attachments_synced_missing_on_primary` | Gauge | 10.7 | Number of attachments marked as synced due to the file missing on the primary | `url` |
| `geo_repositories_checksummed` | Gauge | 10.7 | Number of repositories checksummed on primary | `url` |
| `geo_repositories_checksum_failed` | Gauge | 10.7 | Number of repositories failed to calculate the checksum on primary | `url` |
| `geo_wikis_checksummed` | Gauge | 10.7 | Number of wikis checksummed on primary | `url` |
@@ -275,6 +272,8 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `geo_uploads_synced` | Gauge | 14.1 | Number of uploads synced on secondary | `url` |
| `geo_uploads_failed` | Gauge | 14.1 | Number of syncable uploads failed to sync on secondary | `url` |
| `geo_uploads_registry` | Gauge | 14.1 | Number of uploads in the registry | `url` |
+| `gitlab_sli:rails_request_apdex:total` | Counter | 14.4 | The number of request-apdex measurements, [more information the development documentation](../../../development/application_slis/rails_request_apdex.md) | `endpoint_id`, `feature_category`, `request_urgency` |
+| `gitlab_sli:rails_request_apdex:success_total` | Counter | 14.4 | The number of succesful requests that met the target duration for their urgency. Devide by `gitlab_sli:rails_requests_apdex:total` to get a success ratio | `endpoint_id`, `feature_category`, `request_urgency` |
## Database load balancing metrics **(PREMIUM SELF)**
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
index e04aad9c6b8..e86ca596955 100644
--- a/doc/administration/monitoring/prometheus/index.md
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -345,6 +345,12 @@ memory, disk, and CPU utilization.
[Read more about the node exporter](node_exporter.md).
+### Puma exporter
+
+The Puma exporter allows you to measure various Puma metrics.
+
+[Read more about the Puma exporter](puma_exporter.md).
+
### Redis exporter
The Redis exporter allows you to measure various Redis metrics.
diff --git a/doc/administration/monitoring/prometheus/puma_exporter.md b/doc/administration/monitoring/prometheus/puma_exporter.md
index c348e74afaf..804c4243cfa 100644
--- a/doc/administration/monitoring/prometheus/puma_exporter.md
+++ b/doc/administration/monitoring/prometheus/puma_exporter.md
@@ -25,3 +25,5 @@ To enable the Puma exporter:
for the changes to take effect.
Prometheus begins collecting performance data from the Puma exporter exposed at `localhost:8083`.
+
+For more information on using Puma with GitLab, see [Puma](../../operations/puma.md).
diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md
index f18c39af24a..2a2e9f05312 100644
--- a/doc/administration/nfs.md
+++ b/doc/administration/nfs.md
@@ -93,6 +93,27 @@ is moved to NFS.
We are investigating the use of
[fast lookup as the default](https://gitlab.com/groups/gitlab-org/-/epics/3104).
+## Improving NFS performance with GitLab
+
+NFS performance with GitLab can in some cases be improved with
+[direct Git access](gitaly/index.md#direct-access-to-git-in-gitlab) using
+[Rugged](https://github.com/libgit2/rugged).
+
+From GitLab 12.1, GitLab automatically detects if Rugged can and should be used per storage.
+If you previously enabled Rugged using the feature flag and you want to use automatic detection instead,
+you must unset the feature flag:
+
+```shell
+sudo gitlab-rake gitlab:features:unset_rugged
+```
+
+If the Rugged feature flag is explicitly set to either `true` or `false`, GitLab uses the value explicitly set.
+
+From GitLab 12.7, Rugged is only automatically enabled for use with Puma
+if the [Puma thread count is set to `1`](../install/requirements.md#puma-settings).
+
+To use Rugged with a Puma thread count of more than `1`, enable Rugged using the [feature flag](../development/gitaly.md#legacy-rugged-code).
+
## NFS server
Installing the `nfs-kernel-server` package allows you to share directories with
@@ -165,32 +186,6 @@ You may not need to disable NFS server delegation if you know you are using a ve
the Linux kernel that has been fixed. That said, GitLab still encourages instance
administrators to keep NFS server delegation disabled.
-### Improving NFS performance with GitLab
-
-NFS performance with GitLab can in some cases be improved with
-[direct Git access](gitaly/index.md#direct-access-to-git-in-gitlab) using
-[Rugged](https://github.com/libgit2/rugged).
-
-NOTE:
-From GitLab 12.1, it automatically detects if Rugged can and should be used per storage.
-
-If you previously enabled Rugged using the feature flag, you need to unset the feature flag by using:
-
-```shell
-sudo gitlab-rake gitlab:features:unset_rugged
-```
-
-If the Rugged feature flag is explicitly set to either `true` or `false`, GitLab uses the value explicitly set.
-
-#### Improving NFS performance with Puma
-
-NOTE:
-From GitLab 12.7, Rugged is not automatically enabled if Puma thread count is greater than `1`.
-
-If you want to use Rugged with Puma, [set Puma thread count to `1`](../install/requirements.md#puma-settings).
-
-If you want to use Rugged with Puma thread count more than `1`, Rugged can be enabled using the [feature flag](../development/gitaly.md#legacy-rugged-code).
-
## NFS client
The `nfs-common` provides NFS functionality without installing server components which
@@ -232,7 +227,7 @@ Note there are several options that you should consider using:
It's recommended that you use `hard` in your mount options, unless you have a specific
reason to use `soft`.
-On GitLab.com, we use `soft` because there were times when we had NFS servers
+When GitLab.com used NFS, we used `soft` because there were times when we had NFS servers
reboot and `soft` improved availability, but everyone's infrastructure is different.
If your NFS is provided by on-premise storage arrays with redundant controllers,
for example, you shouldn't need to worry about NFS server availability.
diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md
index 6c77576cb27..8576b429213 100644
--- a/doc/administration/object_storage.md
+++ b/doc/administration/object_storage.md
@@ -2,7 +2,6 @@
stage: Enablement
group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: reference
---
# Object storage **(FREE SELF)**
@@ -77,7 +76,13 @@ Mattermost. See the [full table for a complete list](#storage-specific-configura
However, backups can be configured with [server side encryption](../raketasks/backup_restore.md#s3-encrypted-buckets) separately.
Enabling consolidated object storage enables object storage for all object
-types. If you want to use local storage for specific object types, you can
+types. If not all buckets are specified, `sudo gitlab-ctl reconfigure` may fail with the error like:
+
+```plaintext
+Object storage for <object type> must have a bucket specified
+```
+
+If you want to use local storage for specific object types, you can
[selectively disable object storages](#selectively-disabling-object-storage).
Most types of objects, such as CI artifacts, LFS files, upload
@@ -123,8 +128,8 @@ See the section on [ETag mismatch errors](#etag-mismatch) for more details.
gitlab_rails['object_store']['objects']['pages']['bucket'] = '<pages>'
```
- For GitLab 9.4 or later, if you're using AWS IAM profiles, be sure to omit the
- AWS access key and secret access key/value pairs. For example:
+ If you're using AWS IAM profiles, omit the AWS access key and secret access
+ key/value pairs. For example:
```ruby
gitlab_rails['object_store']['connection'] = {
@@ -558,7 +563,7 @@ supported by consolidated configuration form, refer to the following guides:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| **{dotted-circle}** No |
| [Packages](packages/index.md#using-object-storage) (optional feature) | **{check-circle}** Yes |
| [Dependency Proxy](packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM SELF)** | **{check-circle}** Yes |
-| [Pseudonymizer](pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | **{dotted-circle}** No |
+| [Pseudonymizer](pseudonymizer.md) (optional feature) | **{dotted-circle}** No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | **{dotted-circle}** No |
| [Terraform state files](terraform_state.md#using-object-storage) | **{check-circle}** Yes |
| [GitLab Pages content](pages/index.md#using-object-storage) | **{check-circle}** Yes |
diff --git a/doc/administration/operations/extra_sidekiq_processes.md b/doc/administration/operations/extra_sidekiq_processes.md
index 31cbd6c457b..02cb7ad0bca 100644
--- a/doc/administration/operations/extra_sidekiq_processes.md
+++ b/doc/administration/operations/extra_sidekiq_processes.md
@@ -30,6 +30,11 @@ can be started.
> - [Sidekiq cluster moved](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) to GitLab Free in 12.10.
> - [Sidekiq cluster became default](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4140) in GitLab 13.0.
+When starting multiple processes, the number of processes should
+equal (and **not** exceed) the number of CPU cores you want to
+dedicate to Sidekiq. Each Sidekiq process can use only 1 CPU
+core, subject to the available workload and concurrency settings.
+
To start multiple processes:
1. Using the `sidekiq['queue_groups']` array setting, specify how many processes to
@@ -166,23 +171,41 @@ one only processes imports and the other processes all other queues:
## Number of threads
-Each process defined under `sidekiq` starts with a
+By default each process defined under `sidekiq` starts with a
number of threads that equals the number of queues, plus one spare thread.
For example, a process that handles the `process_commit` and `post_receive`
queues uses three threads in total.
-## Manage concurrency
+These thread run inside a single Ruby process, and each process
+can only use a single CPU core. The usefulness of threading depends
+on the work having some external dependencies to wait on, like database queries or
+HTTP requests. Most Sidekiq deployments benefit from this threading, and when
+running fewer queues in a process, increasing the thread count might be
+even more desirable to make the most effective use of CPU resources.
+
+### Manage thread counts explicitly
+
+The correct maximum thread count (also called concurrency) depends on the workload.
+Typical values range from `1` for highly CPU-bound tasks to `15` or higher for mixed
+low-priority work. A reasonable starting range is `15` to `25` for a non-specialized
+deployment.
+
+You can find example values used by GitLab.com by searching for `concurrency:` in
+[the Helm charts](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/blob/master/releases/gitlab/values/gprd.yaml.gotmpl).
+The values vary according to the work each specific deployment of Sidekiq does.
+Any other specialized deployments with processes dedicated to specific queues should
+have the concurrency tuned according to:
+have the concurrency tuned according to:
-When setting the maximum concurrency, keep in mind this normally should
-not exceed the number of CPU cores available. The values in the examples
-below are arbitrary and not particular recommendations.
+- The CPU usage of each type of process.
+- The throughput achieved.
Each thread requires a Redis connection, so adding threads may increase Redis
latency and potentially cause client timeouts. See the [Sidekiq documentation
about Redis](https://github.com/mperham/sidekiq/wiki/Using-Redis) for more
details.
-### When running Sidekiq cluster (default)
+#### When running Sidekiq cluster (default)
Running Sidekiq cluster is the default in GitLab 13.0 and later.
@@ -203,7 +226,7 @@ Running Sidekiq cluster is the default in GitLab 13.0 and later.
the other. Setting `min_concurrency` to `0` disables the limit.
For each queue group, let `N` be one more than the number of queues. The
-concurrency factor are set to:
+concurrency is set to:
1. `N`, if it's between `min_concurrency` and `max_concurrency`.
1. `max_concurrency`, if `N` exceeds this value.
@@ -215,7 +238,7 @@ regardless of the number of queues.
When `min_concurrency` is greater than `max_concurrency`, it is treated as
being equal to `max_concurrency`.
-### When running a single Sidekiq process
+#### When running a single Sidekiq process
Running a single Sidekiq process is the default in GitLab 12.10 and earlier.
diff --git a/doc/administration/operations/fast_ssh_key_lookup.md b/doc/administration/operations/fast_ssh_key_lookup.md
index 8aa5af4c2bf..c99f94589d7 100644
--- a/doc/administration/operations/fast_ssh_key_lookup.md
+++ b/doc/administration/operations/fast_ssh_key_lookup.md
@@ -26,11 +26,8 @@ indexed lookup in the GitLab database. This page describes how to enable the fas
lookup of authorized SSH keys.
WARNING:
-OpenSSH version 6.9+ is required because
-`AuthorizedKeysCommand` must be able to accept a fingerprint. These
-instructions break installations that use older versions of OpenSSH, such as
-those included with CentOS 6 as of September 2017. If you want to use this
-feature for CentOS 6, follow [the instructions on how to build and install a custom OpenSSH package](#compiling-a-custom-version-of-openssh-for-centos-6) before continuing.
+OpenSSH version 6.9+ is required because `AuthorizedKeysCommand` must be
+able to accept a fingerprint. Check the version of OpenSSH on your server.
## Fast lookup is required for Geo **(PREMIUM)**
@@ -132,100 +129,43 @@ This is a brief overview. Please refer to the above instructions for more contex
1. Remove the `AuthorizedKeysCommand` lines from `/etc/ssh/sshd_config` or from `/assets/sshd_config` if you are using Omnibus Docker.
1. Reload `sshd`: `sudo service sshd reload`.
-## Compiling a custom version of OpenSSH for CentOS 6
+## Use `gitlab-sshd` instead of OpenSSH
-Building a custom version of OpenSSH is not necessary for Ubuntu 16.04 users,
-since Ubuntu 16.04 ships with OpenSSH 7.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299109) in GitLab 14.5.
-It is also unnecessary for CentOS 7.4 users, as that version ships with
-OpenSSH 7.4. If you are using CentOS 7.0 - 7.3, we strongly recommend that you
-upgrade to CentOS 7.4 instead of following this procedure. This should be as
-simple as running `yum update`.
-
-CentOS 6 users must build their own OpenSSH package to enable SSH lookups via
-the database. The following instructions can be used to build OpenSSH 7.5:
-
-1. First, download the package and install the required packages:
-
- ```shell
- sudo su -
- cd /tmp
- curl --remote-name "https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-7.5p1.tar.gz"
- tar xzvf openssh-7.5p1.tar.gz
- yum install rpm-build gcc make wget openssl-devel krb5-devel pam-devel libX11-devel xmkmf libXt-devel
- ```
-
-1. Prepare the build by copying files to the right place:
-
- ```shell
- mkdir -p /root/rpmbuild/{SOURCES,SPECS}
- cp ./openssh-7.5p1/contrib/redhat/openssh.spec /root/rpmbuild/SPECS/
- cp openssh-7.5p1.tar.gz /root/rpmbuild/SOURCES/
- cd /root/rpmbuild/SPECS
- ```
-
-1. Next, set the spec settings properly:
-
- ```shell
- sed -i -e "s/%define no_gnome_askpass 0/%define no_gnome_askpass 1/g" openssh.spec
- sed -i -e "s/%define no_x11_askpass 0/%define no_x11_askpass 1/g" openssh.spec
- sed -i -e "s/BuildPreReq/BuildRequires/g" openssh.spec
- ```
-
-1. Build the RPMs:
-
- ```shell
- rpmbuild -bb openssh.spec
- ```
-
-1. Ensure the RPMs were built:
-
- ```shell
- ls -al /root/rpmbuild/RPMS/x86_64/
- ```
-
- You should see something as the following:
-
- ```plaintext
- total 1324
- drwxr-xr-x. 2 root root 4096 Jun 20 19:37 .
- drwxr-xr-x. 3 root root 19 Jun 20 19:37 ..
- -rw-r--r--. 1 root root 470828 Jun 20 19:37 openssh-7.5p1-1.x86_64.rpm
- -rw-r--r--. 1 root root 490716 Jun 20 19:37 openssh-clients-7.5p1-1.x86_64.rpm
- -rw-r--r--. 1 root root 17020 Jun 20 19:37 openssh-debuginfo-7.5p1-1.x86_64.rpm
- -rw-r--r--. 1 root root 367516 Jun 20 19:37 openssh-server-7.5p1-1.x86_64.rpm
- ```
-
-1. Install the packages. OpenSSH packages replace `/etc/pam.d/sshd`
- with their own versions, which may prevent users from logging in, so be sure
- that the file is backed up and restored after installation:
-
- ```shell
- timestamp=$(date +%s)
- cp /etc/pam.d/sshd pam-ssh-conf-$timestamp
- rpm -Uvh /root/rpmbuild/RPMS/x86_64/*.rpm
- yes | cp pam-ssh-conf-$timestamp /etc/pam.d/sshd
- ```
-
-1. Verify the installed version. In another window, attempt to sign in to the
- server:
-
- ```shell
- ssh -v <your-centos-machine>
+WARNING:
+`gitlab-sshd` is in [**Alpha**](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga).
+It is not ready for production use.
+
+`gitlab-sshd` is [a standalone SSH server](https://gitlab.com/gitlab-org/gitlab-shell/-/tree/main/internal/sshd)
+ written in Go. It is provided as a part of `gitlab-shell` package. It has a lower memory
+ use as a OpenSSH alternative and supports
+ [group access restriction by IP address](../../user/group/index.md) for applications
+ running behind the proxy.
+
+If you are considering switching from OpenSSH to `gitlab-sshd`, consider these concerns:
+
+- The `gitlab-sshd` component is only available for
+ [Cloud Native Helm Charts](https://docs.gitlab.com/charts/) deployments.
+- `gitlab-sshd` supports the PROXY protocol. It can run behind proxy servers that rely
+ on it, such as HAProxy.
+- `gitlab-sshd` does not share a SSH port with the system administrator's OpenSSH,
+ and requires a bind to port 22.
+- `gitlab-sshd` **does not** support SSH certificates.
+
+To switch from OpenSSH to `gitlab-sshd`:
+
+1. Set the `gitlab-shell` charts `sshDaemon` option to
+ [`gitlab-sshd`](https://docs.gitlab.com/charts/charts/gitlab/gitlab-shell/index.html#installation-command-line-options).
+ For example:
+
+ ```yaml
+ gitlab:
+ gitlab-shell:
+ sshDaemon: gitlab-sshd
```
- You should see a line that reads: "debug1: Remote protocol version 2.0, remote software version OpenSSH_7.5"
-
- If not, you may need to restart `sshd` (for example, `systemctl restart sshd.service`).
-
-1. *IMPORTANT!* Open a new SSH session to your server before exiting to make
- sure everything is working! If you need to downgrade, simple install the
- older package:
-
- ```shell
- # Only run this if you run into a problem logging in
- yum downgrade openssh-server openssh openssh-clients
- ```
+1. Perform a Helm upgrade.
## SELinux support and limitations
diff --git a/doc/administration/operations/moving_repositories.md b/doc/administration/operations/moving_repositories.md
index 8aeaadc17e9..9cf7ac18c81 100644
--- a/doc/administration/operations/moving_repositories.md
+++ b/doc/administration/operations/moving_repositories.md
@@ -49,8 +49,8 @@ until the move has completed.
To move repositories:
-1. Ensure all storages are accessible to the GitLab instance. In this example, these are
- `<original_storage_name>` and `<cluster_storage_name>`.
+1. Ensure all [local and cluster storages](../gitaly/configure_gitaly.md#mixed-configuration) are accessible to the GitLab instance. In
+ this example, these are `<original_storage_name>` and `<cluster_storage_name>`.
1. [Configure repository storage weights](../repository_storage_paths.md#configure-where-new-repositories-are-stored)
so that the new storages receives all new projects. This stops new projects from being created
on existing storages while the migration is in progress.
diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md
index 775761d655d..f1f02b606f5 100644
--- a/doc/administration/operations/puma.md
+++ b/doc/administration/operations/puma.md
@@ -224,3 +224,8 @@ in Puma when using the Linux package, and which ones have no corresponding count
| `unicorn['exporter_enabled']` | `puma['exporter_enabled']` |
| `unicorn['exporter_address']` | `puma['exporter_address']` |
| `unicorn['exporter_port']` | `puma['exporter_port']` |
+
+## Puma exporter
+
+You can use the Puma exporter to measure various Puma metrics. For more information, see
+[Puma exporter](../monitoring/prometheus/puma_exporter.md).
diff --git a/doc/administration/operations/ssh_certificates.md b/doc/administration/operations/ssh_certificates.md
index 77dc4eb180b..4fcc5d7c916 100644
--- a/doc/administration/operations/ssh_certificates.md
+++ b/doc/administration/operations/ssh_certificates.md
@@ -19,10 +19,8 @@ In such setups some external automated process is needed to constantly
upload the new keys to GitLab.
WARNING:
-OpenSSH version 6.9+ is required because that version
-introduced the `AuthorizedPrincipalsCommand` configuration option. If
-using CentOS 6, you can [follow these instructions](fast_ssh_key_lookup.md#compiling-a-custom-version-of-openssh-for-centos-6)
-to compile an up-to-date version.
+OpenSSH version 6.9+ is required because `AuthorizedKeysCommand` must be
+able to accept a fingerprint. Check the version of OpenSSH on your server.
## Why use OpenSSH certificates?
diff --git a/doc/administration/package_information/deprecated_os.md b/doc/administration/package_information/deprecated_os.md
index 35b333241b2..7234d68e4b2 100644
--- a/doc/administration/package_information/deprecated_os.md
+++ b/doc/administration/package_information/deprecated_os.md
@@ -64,6 +64,7 @@ The following lists the currently supported OSs and their possible EOL dates.
| Debian 9 | GitLab CE / GitLab EE 9.3.0 | amd64 | 2022 | <https://wiki.debian.org/DebianReleases#Production_Releases> |
| Debian 10 | GitLab CE / GitLab EE 12.2.0 | amd64, arm64 | TBD | <https://wiki.debian.org/DebianReleases#Production_Releases> |
| OpenSUSE 15.2 | GitLab CE / GitLab EE 13.11.0 | x86_64, aarch64 | Dec 2021 | <https://en.opensuse.org/Lifetime> |
+| OpenSUSE 15.3 | GitLab CE / GitLab EE 14.5.0 | x86_64, aarch64 | Nov 2022 | <https://en.opensuse.org/Lifetime> |
| SLES 12 | GitLab EE 9.0.0 | x86_64 | Oct 2027 | <https://www.suse.com/lifecycle/> |
| Ubuntu 18.04 | GitLab CE / GitLab EE 10.7.0 | amd64 | April 2023 | <https://wiki.ubuntu.com/Releases> |
| Ubuntu 20.04 | GitLab CE / GitLab EE 13.2.0 | amd64, arm64 | April 2025 | <https://wiki.ubuntu.com/Releases> |
diff --git a/doc/administration/package_information/deprecation_policy.md b/doc/administration/package_information/deprecation_policy.md
index 80ce72d54f5..d45c2ea3127 100644
--- a/doc/administration/package_information/deprecation_policy.md
+++ b/doc/administration/package_information/deprecation_policy.md
@@ -1,7 +1,7 @@
---
stage: Enablement
group: Distribution
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Deprecation policy **(FREE SELF)**
@@ -35,9 +35,11 @@ This section lists steps necessary for deprecating and removing configuration.
We can differentiate two different types of configuration:
-- Sensitive: Configuration that can cause major service outage ( Data integrity,
- installation integrity, preventing users from reaching the installation, etc.)
-- Regular: Configuration that can make a feature unavailable but still makes the installation useable ( Change in default project/group settings, miscommunication with other components and similar )
+- Sensitive: Configuration that can cause major service outage (like data integrity,
+ installation integrity, or preventing users from reaching the installation)
+- Regular: Configuration that can make a feature unavailable but still makes the
+ installation useable (like a change in default project/group settings, or
+ miscommunication with other components)
We also need to differentiate deprecation and removal procedure.
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 8a0d3f552bf..163eb5388b6 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -237,6 +237,7 @@ control over how the Pages daemon runs and serves content in your environment.
| `log_verbose` | Verbose logging, true/false. |
| `propagate_correlation_id` | Set to true (false by default) to re-use existing Correlation ID from the incoming request header `X-Request-ID` if present. If a reverse proxy sets this header, the value is propagated in the request chain. |
| `max_connections` | Limit on the number of concurrent connections to the HTTP, HTTPS or proxy listeners. |
+| `max_uri_length` | The maximum length of URIs accepted by GitLab Pages. Set to 0 for unlimited length. [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/659) in GitLab 14.5.
| `metrics_address` | The address to listen on for metrics requests. |
| `redirect_http` | Redirect pages from HTTP to HTTPS, true/false. |
| `sentry_dsn` | The address for sending Sentry crash reporting to. |
@@ -258,8 +259,8 @@ control over how the Pages daemon runs and serves content in your environment.
| `FF_ENABLE_REDIRECTS` | Feature flag to enable/disable redirects (enabled by default). Read the [redirects documentation](../../user/project/pages/redirects.md#feature-flag-for-redirects) for more information. |
| `FF_ENABLE_PLACEHOLDERS` | Feature flag to enable/disable rewrites (disabled by default). Read the [redirects documentation](../../user/project/pages/redirects.md#feature-flag-for-rewrites) for more information. |
| `use_legacy_storage` | Temporarily-introduced parameter allowing to use legacy domain configuration source and storage. [Removed in 14.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6166). |
-
----
+| `rate_limit_source_ip` | Rate limit per source IP in number of requests per second. Set to `0` to disable this feature. |
+| `rate_limit_source_ip_burst` | Rate limit per source IP maximum burst allowed per second. |
## Advanced configuration
@@ -647,7 +648,7 @@ To override the global maximum pages size for a specific group:
## Running GitLab Pages on a separate server
You can run the GitLab Pages daemon on a separate server to decrease the load on
-your main application server.
+your main application server. This configuration does not support mutual TLS (mTLS). See the [corresponding feature proposal](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/548) for more information.
To configure GitLab Pages on a separate server:
@@ -1031,6 +1032,38 @@ GitLab Pages are part of the [regular backup](../../raketasks/backup_restore.md)
You should strongly consider running GitLab Pages under a different hostname
than GitLab to prevent XSS attacks.
+### Rate limits
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/631) in GitLab 14.5.
+
+You can enforce source-IP rate limits to help minimize the risk of a Denial of Service (DoS) attack. GitLab Pages
+uses a [token bucket algorithm](https://en.wikipedia.org/wiki/Token_bucket) to enforce rate limiting. By default,
+requests that exceed the specified limits are reported but not rejected.
+
+Source-IP rate limits are enforced using the following:
+
+- `rate_limit_source_ip`: Set the maximum threshold in number of requests per second. Set to 0 to disable this feature.
+- `rate_limit_source_ip_burst`: Sets the maximum threshold of number of requests allowed in an initial outburst of requests.
+ For example, when you load a web page that loads a number of resources at the same time.
+
+#### Enable source-IP rate limits
+
+1. Set rate limits in `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_pages['rate_limit_source_ip'] = 20.0
+ gitlab_pages['rate_limit_source_ip_burst'] = 600
+ ```
+
+1. To reject requests that exceed the specified limits, enable the `FF_ENABLE_RATE_LIMITER` feature flag in
+ `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_pages['env'] = {'FF_ENABLE_RATE_LIMITER' => 'true'}
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
index 278d792052a..3a277204d21 100644
--- a/doc/administration/pages/source.md
+++ b/doc/administration/pages/source.md
@@ -132,11 +132,11 @@ The Pages daemon doesn't listen to the outside world.
https: false
artifacts_server: false
external_http: ["127.0.0.1:8090"]
- secret_file: /home/git/gitlab/gitlab-pages/gitlab-pages-secret
+ secret_file: /home/git/gitlab/gitlab-pages-secret
```
1. Add the following configuration file to
- `/home/git/gitlab/gitlab-pages/gitlab-pages.conf`, and be sure to change
+ `/home/git/gitlab-pages/gitlab-pages.conf`, and be sure to change
`example.io` to the FQDN from which you want to serve GitLab Pages and
`gitlab.example.com` to the URL of your GitLab instance:
@@ -159,12 +159,27 @@ The Pages daemon doesn't listen to the outside world.
sudo -u git -H openssl rand -base64 32 > /home/git/gitlab/gitlab-pages-secret
```
-1. Edit `/etc/default/gitlab` and set `gitlab_pages_enabled` to `true` in
- order to enable the pages daemon:
+1. To enable the pages daemon:
- ```ini
- gitlab_pages_enabled=true
- ```
+ - If your system uses systemd as init, run:
+
+ ```shell
+ sudo systemctl edit gitlab.target
+ ```
+
+ In the editor that opens, add the following and save the file:
+
+ ```plaintext
+ [Unit]
+ Wants=gitlab-pages.service
+ ```
+
+ - If your system uses SysV init instead, edit `/etc/default/gitlab` and set
+ `gitlab_pages_enabled` to `true`:
+
+ ```ini
+ gitlab_pages_enabled=true
+ ```
1. Copy the `gitlab-pages` NGINX configuration file:
diff --git a/doc/administration/postgresql/external.md b/doc/administration/postgresql/external.md
index 8f0fe0ace87..67c5448a8a0 100644
--- a/doc/administration/postgresql/external.md
+++ b/doc/administration/postgresql/external.md
@@ -4,7 +4,7 @@ group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Configure GitLab using an external PostgreSQL service
+# Configure GitLab using an external PostgreSQL service **(FREE SELF)**
If you're hosting GitLab on a cloud provider, you can optionally use a
managed service for PostgreSQL. For example, AWS offers a managed Relational
diff --git a/doc/administration/postgresql/index.md b/doc/administration/postgresql/index.md
index bce78bbccff..15425a6d9f2 100644
--- a/doc/administration/postgresql/index.md
+++ b/doc/administration/postgresql/index.md
@@ -2,26 +2,15 @@
stage: Enablement
group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: reference
---
-# Configuring PostgreSQL for scaling
+# Configuring PostgreSQL for scaling **(FREE SELF)**
In this section, you'll be guided through configuring a PostgreSQL database to
be used with GitLab in one of our [reference architectures](../reference_architectures/index.md).
There are essentially three setups to choose from.
-## PostgreSQL replication and failover with Omnibus GitLab **(PREMIUM SELF)**
-
-This setup is for when you have installed GitLab using the
-[Omnibus GitLab **Enterprise Edition** (EE) package](https://about.gitlab.com/install/?version=ee).
-
-All the tools that are needed like PostgreSQL, PgBouncer, and Patroni are bundled in
-the package, so you can it to set up the whole PostgreSQL infrastructure (primary, replica).
-
-[> Read how to set up PostgreSQL replication and failover using Omnibus GitLab](replication_and_failover.md)
-
-## Standalone PostgreSQL using Omnibus GitLab **(FREE SELF)**
+## Standalone PostgreSQL using Omnibus GitLab
This setup is for when you have installed the
[Omnibus GitLab packages](https://about.gitlab.com/install/) (CE or EE),
@@ -29,7 +18,7 @@ to use the bundled PostgreSQL having only its service enabled.
[> Read how to set up a standalone PostgreSQL instance using Omnibus GitLab](standalone.md)
-## Provide your own PostgreSQL instance **(FREE SELF)**
+## Provide your own PostgreSQL instance
This setup is for when you have installed GitLab using the
[Omnibus GitLab packages](https://about.gitlab.com/install/) (CE or EE),
@@ -37,3 +26,13 @@ or installed it [from source](../../install/installation.md), but you want to us
your own external PostgreSQL server.
[> Read how to set up an external PostgreSQL instance](external.md)
+
+## PostgreSQL replication and failover with Omnibus GitLab **(PREMIUM SELF)**
+
+This setup is for when you have installed GitLab using the
+[Omnibus GitLab **Enterprise Edition** (EE) package](https://about.gitlab.com/install/?version=ee).
+
+All the tools that are needed like PostgreSQL, PgBouncer, and Patroni are bundled in
+the package, so you can use it to set up the whole PostgreSQL infrastructure (primary, replica).
+
+[> Read how to set up PostgreSQL replication and failover using Omnibus GitLab](replication_and_failover.md)
diff --git a/doc/administration/postgresql/pgbouncer.md b/doc/administration/postgresql/pgbouncer.md
index e215622bbc7..e5fef61540a 100644
--- a/doc/administration/postgresql/pgbouncer.md
+++ b/doc/administration/postgresql/pgbouncer.md
@@ -84,7 +84,7 @@ This content has been moved to a [new location](replication_and_failover.md#conf
Do not backup or restore GitLab through a PgBouncer connection: it causes a GitLab outage.
-[Read more about this and how to reconfigure backups](../../raketasks/backup_restore.md#backup-and-restore-for-installations-using-pgbouncer).
+[Read more about this and how to reconfigure backups](../../raketasks/backup_restore.md#back-up-and-restore-for-installations-using-pgbouncer).
## Enable Monitoring
@@ -172,7 +172,7 @@ ote_pid | tls
Some database changes have to be done directly, and not through PgBouncer.
-Read more about the affected tasks: [database restores](../../raketasks/backup_restore.md#backup-and-restore-for-installations-using-pgbouncer)
+Read more about the affected tasks: [database restores](../../raketasks/backup_restore.md#back-up-and-restore-for-installations-using-pgbouncer)
and [GitLab upgrades](../../update/zero_downtime.md#use-postgresql-ha).
1. To find the primary node, run the following on a database node:
diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md
index dc569a81abf..01fe4bf64ba 100644
--- a/doc/administration/postgresql/replication_and_failover.md
+++ b/doc/administration/postgresql/replication_and_failover.md
@@ -501,7 +501,7 @@ in the Troubleshooting section before proceeding.
Do not backup or restore GitLab through a PgBouncer connection: this causes a GitLab outage.
-[Read more about this and how to reconfigure backups](../../raketasks/backup_restore.md#backup-and-restore-for-installations-using-pgbouncer).
+[Read more about this and how to reconfigure backups](../../raketasks/backup_restore.md#back-up-and-restore-for-installations-using-pgbouncer).
### Ensure GitLab is running
diff --git a/doc/administration/pseudonymizer.md b/doc/administration/pseudonymizer.md
index da3a2e4b34c..bd6982bea12 100644
--- a/doc/administration/pseudonymizer.md
+++ b/doc/administration/pseudonymizer.md
@@ -6,33 +6,38 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Pseudonymizer **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5532) in GitLab 11.1.
+Your GitLab database contains sensitive information. To protect sensitive information
+when you run analytics on your database, you can use the Pseudonymizer service, which:
-As the GitLab database hosts sensitive information, using it unfiltered for analytics
-implies high security requirements. To help alleviate this constraint, the Pseudonymizer
-service is used to export GitLab data in a pseudonymized way.
+1. Uses `HMAC(SHA256)` to mutate fields containing sensitive information.
+1. Preserves references (referential integrity) between fields.
+1. Exports your GitLab data, scrubbed of sensitive material.
WARNING:
-This process is not impervious. If the source data is available, it's possible for
-a user to correlate data to the pseudonymized version.
+If the source data is available, users can compare and correlate the scrubbed data
+with the original.
-The Pseudonymizer currently uses `HMAC(SHA256)` to mutate fields that shouldn't
-be textually exported. This ensures that:
+To generate a pseudonymized data set:
-- the end-user of the data source cannot infer/revert the pseudonymized fields
-- the referential integrity is maintained
+1. [Configure Pseudonymizer](#configure-pseudonymizer) fields and output location.
+1. [Enable Pseudonymizer data collection](#enable-pseudonymizer-data-collection).
+1. Optional. [Generate a data set manually](#generate-data-set-manually).
-## Configuration
+## Configure Pseudonymizer
-To configure the Pseudonymizer, you need to:
+To use the Pseudonymizer, configure both the fields you want to anonymize, and the location to
+store the scrubbed data:
-- Provide a manifest file that describes which fields should be included or
- pseudonymized ([example `manifest.yml` file](https://gitlab.com/gitlab-org/gitlab/-/tree/master/config/pseudonymizer.yml)).
- A default manifest is provided with the GitLab installation, using a relative file path that resolves from the Rails root.
- Alternatively, you can use an absolute file path.
-- Use an object storage and specify the connection parameters in the `pseudonymizer.upload.connection` configuration option.
-
-[Read more about using object storage with GitLab](object_storage.md).
+1. **Create a manifest file**: This file describes the fields to include or pseudonymize.
+ - **Default manifest** - GitLab provides a default manifest in your GitLab installation
+ ([example `manifest.yml` file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/pseudonymizer.yml)).
+ To use the example manifest file, use the `config/pseudonymizer.yml` relative path
+ when you configure connection parameters.
+ - **Custom manifest** - To use a custom manifest file, use the absolute path to
+ the file when you configure the connection parameters.
+1. **Configure connection parameters**: In the configuration method appropriate for
+ your version of GitLab, specify the [object storage](object_storage.md)
+ connection parameters (`pseudonymizer.upload.connection`).
**For Omnibus installations:**
@@ -50,7 +55,7 @@ To configure the Pseudonymizer, you need to:
}
```
- If you are using AWS IAM profiles, be sure to omit the AWS access key and secret access key/value pairs.
+ If you are using AWS IAM profiles, omit the AWS access key and secret access key/value pairs.
```ruby
gitlab_rails['pseudonymizer_upload_connection'] = {
@@ -85,24 +90,34 @@ To configure the Pseudonymizer, you need to:
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source)
for the changes to take effect.
-## Usage
+## Enable Pseudonymizer data collection
+
+To enable data collection:
+
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Settings > Metrics and Profiling**, then expand
+ **Pseudonymizer data collection**.
+1. Select **Enable Pseudonymizer data collection**.
+1. Select **Save changes**.
-You can optionally run the Pseudonymizer using the following environment variables:
+## Generate data set manually
-- `PSEUDONYMIZER_OUTPUT_DIR` - where to store the output CSV files (defaults to `/tmp`)
-- `PSEUDONYMIZER_BATCH` - the batch size when querying the DB (defaults to `100000`)
+You can also run the Pseudonymizer manually:
-```shell
-## Omnibus
-sudo gitlab-rake gitlab:db:pseudonymizer
+1. Set these environment variables:
+ - `PSEUDONYMIZER_OUTPUT_DIR` - Where to store the output CSV files. Defaults to `/tmp`.
+ These commands produce CSV files that can be quite large. Make sure the directory
+ can store a file at least 10% of the size of your database.
+ - `PSEUDONYMIZER_BATCH` - The batch size when querying the database. Defaults to `100000`.
+1. Run the command appropriate for your application:
+ - **Omnibus GitLab**:
+ `sudo gitlab-rake gitlab:db:pseudonymizer`
+ - **Installations from source**:
+ `sudo -u git -H bundle exec rake gitlab:db:pseudonymizer RAILS_ENV=production`
-## Source
-sudo -u git -H bundle exec rake gitlab:db:pseudonymizer RAILS_ENV=production
-```
+After you run the command, upload the output CSV files to your configured object
+storage. After the upload completes, delete the output file from the local disk.
-This produces some CSV files that might be very large, so make sure the
-`PSEUDONYMIZER_OUTPUT_DIR` has sufficient space. As a rule of thumb, at least
-10% of the database size is recommended.
+## Related topics
-After the pseudonymizer has run, the output CSV files should be uploaded to the
-configured object storage and deleted from the local disk.
+- [Using object storage with GitLab](object_storage.md).
diff --git a/doc/administration/raketasks/github_import.md b/doc/administration/raketasks/github_import.md
index f29e2a6c7f6..0cdfd1c28ff 100644
--- a/doc/administration/raketasks/github_import.md
+++ b/doc/administration/raketasks/github_import.md
@@ -6,8 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitHub import **(FREE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10308) in GitLab 9.1.
-
To retrieve and import GitHub repositories, you need a [GitHub personal access token](https://github.com/settings/tokens).
A username should be passed as the second argument to the Rake task,
which becomes the owner of the project. You can resume an import
diff --git a/doc/administration/raketasks/ldap.md b/doc/administration/raketasks/ldap.md
index 585d254e41d..62ddd9be2b3 100644
--- a/doc/administration/raketasks/ldap.md
+++ b/doc/administration/raketasks/ldap.md
@@ -38,13 +38,13 @@ rake gitlab:ldap:check[50]
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14735) in GitLab 12.2.
-The following task runs a [group sync](../auth/ldap/index.md#group-sync) immediately. This is valuable
-when you'd like to update all configured group memberships against LDAP without
+The following task runs a [group sync](../auth/ldap/ldap_synchronization.md#group-sync) immediately.
+This is valuable when you'd like to update all configured group memberships against LDAP without
waiting for the next scheduled group sync to be run.
NOTE:
If you'd like to change the frequency at which a group sync is performed,
-[adjust the cron schedule](../auth/ldap/index.md#adjust-ldap-group-sync-schedule)
+[adjust the cron schedule](../auth/ldap/ldap_synchronization.md#adjust-ldap-group-sync-schedule)
instead.
**Omnibus Installation**
diff --git a/doc/administration/raketasks/project_import_export.md b/doc/administration/raketasks/project_import_export.md
index e0ca7bfdeaf..13f8dfdccc2 100644
--- a/doc/administration/raketasks/project_import_export.md
+++ b/doc/administration/raketasks/project_import_export.md
@@ -6,9 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Project import/export administration **(FREE SELF)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3050) in GitLab 8.9.
-> - From GitLab 11.3, import/export can use object storage automatically.
-
GitLab provides Rake tasks relating to project import and export. For more information, see:
- [Project import/export documentation](../../user/project/settings/import_export.md).
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index e731085b0ce..9c3c33e1fa8 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -12,9 +12,10 @@ full list of reference architectures, see
> - **Supported users (approximate):** 10,000
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
-> - **Cloud Native Hybrid:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
-> - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git (Pull): 20 RPS, Git (Push): 4 RPS
-> - **[Latest 10k weekly performance testing results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k)**
+> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
+> - **Performance tested daily with the [GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance)**:
+> - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git (Pull): 20 RPS, Git (Push): 4 RPS
+> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k)**
| Service | Nodes | Configuration | GCP | AWS | Azure |
|-----------------------------------------------------|-------------|-------------------------|------------------|--------------|-----------|
@@ -36,7 +37,7 @@ full list of reference architectures, see
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -279,7 +280,7 @@ The basic ports to be used are shown in the table below.
| 443 | 443 | TCP or HTTPS (*1*) (*2*) |
| 22 | 22 | TCP |
-- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals) support requires
+- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals-deprecated) support requires
your load balancer to correctly handle WebSocket connections. When using
HTTP or HTTPS proxying, this means your load balancer must be configured
to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the
@@ -2085,7 +2086,7 @@ on what features you intend to use:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | Yes |
-| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
+| [Pseudonymizer](../pseudonymizer.md) (optional feature) | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](../terraform_state.md#using-object-storage) | Yes |
@@ -2199,7 +2200,7 @@ services where applicable):
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
diff --git a/doc/administration/reference_architectures/1k_users.md b/doc/administration/reference_architectures/1k_users.md
index ae832c2226f..5488d8d33a6 100644
--- a/doc/administration/reference_architectures/1k_users.md
+++ b/doc/administration/reference_architectures/1k_users.md
@@ -20,8 +20,9 @@ many organizations.
> follow a modified [3K reference architecture](3k_users.md#supported-modifications-for-lower-user-counts-ha).
> - **Cloud Native Hybrid:** No. For a cloud native hybrid environment, you
> can follow a [modified hybrid reference architecture](#cloud-native-hybrid-reference-architecture-with-helm-charts).
-> - **Test requests per second (RPS) rates:** API: 20 RPS, Web: 2 RPS, Git (Pull): 2 RPS, Git (Push): 1 RPS
-> - **[Latest 1k weekly performance testing results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/1k)**
+> - **Performance tested daily with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
+> - **Test requests per second (RPS) rates:** API: 20 RPS, Web: 2 RPS, Git (Pull): 2 RPS, Git (Push): 1 RPS
+> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/1k)**
| Users | Configuration | GCP | AWS | Azure |
|--------------|-------------------------|----------------|--------------|----------|
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index 267f81efd91..25cafbe667b 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -12,9 +12,10 @@ full list of reference architectures, see
> - **Supported users (approximate):** 25,000
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
-> - **Cloud Native Hybrid:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
-> - **Test requests per second (RPS) rates:** API: 500 RPS, Web: 50 RPS, Git (Pull): 50 RPS, Git (Push): 10 RPS
-> - **[Latest 25k weekly performance testing results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/25k)**
+> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
+> - **Performance tested weekly with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
+> - **Test requests per second (RPS) rates:** API: 500 RPS, Web: 50 RPS, Git (Pull): 50 RPS, Git (Push): 10 RPS
+> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/25k)**
| Service | Nodes | Configuration | GCP | AWS | Azure |
|---------------------------------------------------|-------------|-------------------------|------------------|--------------|-----------|
@@ -36,7 +37,7 @@ full list of reference architectures, see
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -282,7 +283,7 @@ The basic ports to be used are shown in the table below.
| 443 | 443 | TCP or HTTPS (*1*) (*2*) |
| 22 | 22 | TCP |
-- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals) support requires
+- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals-deprecated) support requires
your load balancer to correctly handle WebSocket connections. When using
HTTP or HTTPS proxying, this means your load balancer must be configured
to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the
@@ -2091,7 +2092,7 @@ on what features you intend to use:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | Yes |
-| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
+| [Pseudonymizer](../pseudonymizer.md) (optional feature) | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](../terraform_state.md#using-object-storage) | Yes |
@@ -2199,7 +2200,7 @@ services where applicable):
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index 23b15b563f7..e619294704f 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -14,8 +14,9 @@ For a full list of reference architectures, see
> - **High Availability:** No. For a highly-available environment, you can
> follow a modified [3K reference architecture](3k_users.md#supported-modifications-for-lower-user-counts-ha).
> - **Cloud Native Hybrid:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
-> - **Test requests per second (RPS) rates:** API: 40 RPS, Web: 4 RPS, Git (Pull): 4 RPS, Git (Push): 1 RPS
-> - **[Latest 2k weekly performance testing results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/2k)**
+> - **Performance tested daily with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
+> - **Test requests per second (RPS) rates:** API: 40 RPS, Web: 4 RPS, Git (Pull): 4 RPS, Git (Push): 1 RPS
+> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/2k)**
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|--------|-------------------------|-----------------|--------------|----------|
@@ -29,7 +30,7 @@ For a full list of reference architectures, see
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run as reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run as reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -176,7 +177,7 @@ table:
| 443 | 443 | TCP or HTTPS (*1*) (*2*) |
| 22 | 22 | TCP |
-- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals) support
+- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals-deprecated) support
requires your load balancer to correctly handle WebSocket connections.
When using HTTP or HTTPS proxying, your load balancer must be configured
to pass through the `Connection` and `Upgrade` hop-by-hop headers. For
@@ -352,7 +353,7 @@ Omnibus:
```ruby
## Enable Redis
redis['enable'] = true
-
+
# Avoid running unnecessary services on the Redis server
gitaly['enable'] = false
postgresql['enable'] = false
@@ -922,7 +923,7 @@ on what features you intend to use:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | Yes |
-| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
+| [Pseudonymizer](../pseudonymizer.md) (optional feature) | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](../terraform_state.md#using-object-storage) | Yes |
@@ -1027,7 +1028,7 @@ services where applicable):
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index 575dd22b729..9332ae8d271 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -22,9 +22,10 @@ For a full list of reference architectures, see
> - **Supported users (approximate):** 3,000
> - **High Availability:** Yes, although [Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution
-> - **Cloud Native Hybrid:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
-> - **Test requests per second (RPS) rates:** API: 60 RPS, Web: 6 RPS, Git (Pull): 6 RPS, Git (Push): 1 RPS
-> - **[Latest 3k weekly performance testing results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/3k)**
+> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
+> - **Performance tested weekly with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
+> - **Test requests per second (RPS) rates:** API: 60 RPS, Web: 6 RPS, Git (Pull): 6 RPS, Git (Push): 1 RPS
+> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/3k)**
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-----------------------|-----------------|--------------|----------|
@@ -45,7 +46,7 @@ For a full list of reference architectures, see
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -296,7 +297,7 @@ The basic ports to be used are shown in the table below.
| 443 | 443 | TCP or HTTPS (*1*) (*2*) |
| 22 | 22 | TCP |
-- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals) support requires
+- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals-deprecated) support requires
your load balancer to correctly handle WebSocket connections. When using
HTTP or HTTPS proxying, this means your load balancer must be configured
to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the
@@ -2039,7 +2040,7 @@ on what features you intend to use:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | Yes |
-| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
+| [Pseudonymizer](../pseudonymizer.md) (optional feature) | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](../terraform_state.md#using-object-storage) | Yes |
@@ -2106,7 +2107,7 @@ but with smaller performance requirements, several modifications can be consider
- GitLab Rails and Sidekiq: Stateless services don't have a minimum node count. Two are enough for redundancy.
- Gitaly and Praefect: A quorum is not strictly necessary. Two Gitaly nodes and two Praefect nodes are enough for redundancy.
- Running select components in reputable Cloud PaaS solutions: Select components of the GitLab setup can instead be run on Cloud Provider PaaS solutions. By doing this, additional dependent components can also be removed:
- - PostgreSQL: Can be run on reputable Cloud PaaS solutions such as Google Cloud SQL or AWS RDS. In this setup, the PgBouncer and Consul nodes are no longer required:
+ - PostgreSQL: Can be run on reputable Cloud PaaS solutions such as Google Cloud SQL or Amazon RDS. In this setup, the PgBouncer and Consul nodes are no longer required:
- Consul may still be desired if [Prometheus](../monitoring/prometheus/index.md) auto discovery is a requirement, otherwise you would need to [manually add scrape configurations](../monitoring/prometheus/index.md#adding-custom-scrape-configurations) for all nodes.
- As Redis Sentinel runs on the same box as Consul in this architecture, it may need to be run on a separate box if Redis is still being run via Omnibus.
- Redis: Can be run on reputable Cloud PaaS solutions such as Google Memorystore and AWS ElastiCache. In this setup, the Redis Sentinel is no longer required.
@@ -2170,7 +2171,7 @@ services where applicable):
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index be44f464e7e..bbdf798d9ad 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -12,9 +12,10 @@ full list of reference architectures, see
> - **Supported users (approximate):** 50,000
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
-> - **Cloud Native Hybrid:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
-> - **Test requests per second (RPS) rates:** API: 1000 RPS, Web: 100 RPS, Git (Pull): 100 RPS, Git (Push): 20 RPS
-> - **[Latest 50k weekly performance testing results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/50k)**
+> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
+> - **Performance tested weekly with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
+> - **Test requests per second (RPS) rates:** API: 1000 RPS, Web: 100 RPS, Git (Pull): 100 RPS, Git (Push): 20 RPS
+> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/50k)**
| Service | Nodes | Configuration | GCP | AWS | Azure |
|---------------------------------------------------|-------------|-------------------------|------------------|---------------|-----------|
@@ -36,7 +37,7 @@ full list of reference architectures, see
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -288,7 +289,7 @@ The basic ports to be used are shown in the table below.
| 443 | 443 | TCP or HTTPS (*1*) (*2*) |
| 22 | 22 | TCP |
-- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals) support requires
+- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals-deprecated) support requires
your load balancer to correctly handle WebSocket connections. When using
HTTP or HTTPS proxying, this means your load balancer must be configured
to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the
@@ -2105,7 +2106,7 @@ on what features you intend to use:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | Yes |
-| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
+| [Pseudonymizer](../pseudonymizer.md) (optional feature) | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](../terraform_state.md#using-object-storage) | Yes |
@@ -2213,7 +2214,7 @@ services where applicable):
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index a5526986be1..a1921f50e4e 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -19,9 +19,10 @@ costly-to-operate environment by using the
> - **Supported users (approximate):** 5,000
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
-> - **Cloud Native Hybrid:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
-> - **Test requests per second (RPS) rates:** API: 100 RPS, Web: 10 RPS, Git (Pull): 10 RPS, Git (Push): 2 RPS
-> - **[Latest 5k weekly performance testing results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/5k)**
+> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
+> - **Performance tested weekly with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
+> - **Test requests per second (RPS) rates:** API: 100 RPS, Web: 10 RPS, Git (Pull): 10 RPS, Git (Push): 2 RPS
+> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/5k)**
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|-----------------|--------------|----------|
@@ -288,7 +289,7 @@ The basic ports to be used are shown in the table below.
| 443 | 443 | TCP or HTTPS (*1*) (*2*) |
| 22 | 22 | TCP |
-- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals) support requires
+- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals-deprecated) support requires
your load balancer to correctly handle WebSocket connections. When using
HTTP or HTTPS proxying, this means your load balancer must be configured
to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the
@@ -2033,7 +2034,7 @@ on what features you intend to use:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | Yes |
-| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
+| [Pseudonymizer](../pseudonymizer.md) (optional feature) | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](../terraform_state.md#using-object-storage) | Yes |
diff --git a/doc/administration/repository_storage_paths.md b/doc/administration/repository_storage_paths.md
index ed50d0e7263..00aa8c214c5 100644
--- a/doc/administration/repository_storage_paths.md
+++ b/doc/administration/repository_storage_paths.md
@@ -14,7 +14,7 @@ storage is either:
- A `path`, which points directly to the directory where the repositories are stored. GitLab
directly accessing a directory containing repositories
[is deprecated](https://gitlab.com/gitlab-org/gitaly/-/issues/1690).
- GitLab should be configured to access GitLab repositories though a `gitaly_address`.
+ GitLab should be configured to access GitLab repositories through a `gitaly_address`.
GitLab allows you to define multiple repository storages to distribute the storage load between
several mount points. For example:
diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md
index d2bab9a1e04..a85f678fe95 100644
--- a/doc/administration/repository_storage_types.md
+++ b/doc/administration/repository_storage_types.md
@@ -101,8 +101,12 @@ To look up a project's hash path using a Rails console:
#### From hashed path to project name
-Administrators can look up a project's name from its hashed storage path using a Rails console. To
-look up a project's name from its hashed storage path:
+Administrators can look up a project's name from its hashed storage path using:
+
+- A Rails console.
+- The `config` file in the `*.git` directory.
+
+To look up a project's name using the Rails console:
1. Start a [Rails console](operations/rails_console.md#starting-a-rails-console-session).
1. Run a command similar to this example:
@@ -121,6 +125,14 @@ The output includes the project ID and the project name. For example:
=> #<Project id:16 it/supportteam/ticketsystem>
```
+To look up a project's name using the `config` file in the `*.git` directory:
+
+1. Navigate to the to the `*.git` directory. This directory is located in `/var/opt/gitlab/git-data/repositories/@hashed/`, where the first four
+ characters of the hash are the first two directories in the path under `@hashed/`. For example, on a default Omnibus GitLab installation the
+ `*.git` directory of the hash `b17eb17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9` would be
+ `/var/opt/gitlab/git-data/repositories/@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git`.
+1. Open the `config` file and locate the `fullpath=` key under `[gitlab]`.
+
### Hashed object pools
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/1606) in GitLab 12.1.
diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md
index b8f09b00773..9579d413bf8 100644
--- a/doc/administration/restart_gitlab.md
+++ b/doc/administration/restart_gitlab.md
@@ -103,39 +103,15 @@ If you have followed the official installation guide to [install GitLab from
source](../install/installation.md), run the following command to restart GitLab:
```shell
-sudo service gitlab restart
-```
+# For systems running systemd
+sudo systemctl restart gitlab.target
-The output should be similar to this:
-
-```plaintext
-Shutting down GitLab Puma
-Shutting down GitLab Sidekiq
-Shutting down GitLab Workhorse
-Shutting down GitLab MailRoom
-...
-GitLab is not running.
-Starting GitLab Puma
-Starting GitLab Sidekiq
-Starting GitLab Workhorse
-Starting GitLab MailRoom
-...
-The GitLab Puma web server with pid 28059 is running.
-The GitLab Sidekiq job dispatcher with pid 28176 is running.
-The GitLab Workhorse with pid 28122 is running.
-The GitLab MailRoom email processor with pid 28114 is running.
-GitLab and all its components are up and running.
+# For systems running SysV init
+sudo service gitlab restart
```
This should restart Puma, Sidekiq, GitLab Workhorse, and [Mailroom](reply_by_email.md)
-(if enabled). The init service file that does all the magic can be found on
-your server in `/etc/init.d/gitlab`.
-
----
-
-If you are using other init systems, like `systemd`, you can check the
-[GitLab Recipes](https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/init) repository for some unofficial services. These are
-**not** officially supported so use them at your own risk.
+(if enabled).
## Helm chart installations
diff --git a/doc/administration/sidekiq.md b/doc/administration/sidekiq.md
index 4aee88ed9cb..8f1119f6868 100644
--- a/doc/administration/sidekiq.md
+++ b/doc/administration/sidekiq.md
@@ -74,6 +74,20 @@ you want using steps 1 and 2 from the GitLab downloads page.
postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32 10.10.1.31/32 10.10.1.32/32 10.10.1.33/32 10.10.1.38/32)
```
+1. If you run multiple Sidekiq nodes with a shared file storage, such as NFS, you must
+ specify the UIDs and GIDs to ensure they match between servers. Specifying the UIDs
+ and GIDs prevents permissions issues in the file system. This advice is similar to the
+ [advice for Geo setups](geo/replication/multiple_servers.md#step-4-configure-the-frontend-application-nodes-on-the-geo-secondary-site):
+
+ ```ruby
+ user['uid'] = 9000
+ user['gid'] = 9000
+ web_server['uid'] = 9001
+ web_server['gid'] = 9001
+ registry['uid'] = 9002
+ registry['gid'] = 9002
+ ```
+
1. Disable other services:
```ruby
diff --git a/doc/administration/troubleshooting/debug.md b/doc/administration/troubleshooting/debug.md
index e00243aca0a..744e12d4da1 100644
--- a/doc/administration/troubleshooting/debug.md
+++ b/doc/administration/troubleshooting/debug.md
@@ -258,7 +258,7 @@ separate Rails process to debug the issue:
### GitLab: API is not accessible
This often occurs when GitLab Shell attempts to request authorization via the
-[internal API](../../development/internal_api.md) (for example, `http://localhost:8080/api/v4/internal/allowed`), and
+[internal API](../../development/internal_api/index.md) (for example, `http://localhost:8080/api/v4/internal/allowed`), and
something in the check fails. There are many reasons why this may happen:
1. Timeout connecting to a database (for example, PostgreSQL or Redis)
@@ -275,7 +275,7 @@ strace -ttTfyyy -s 1024 -p <PID of puma worker> -o /tmp/puma.txt
If you cannot isolate which Unicorn worker is the issue, try to run `strace`
on all the Unicorn workers to see where the
-[`/internal/allowed`](../../development/internal_api.md) endpoint gets stuck:
+[`/internal/allowed`](../../development/internal_api/index.md) endpoint gets stuck:
```shell
ps auwx | grep puma | awk '{ print " -p " $2}' | xargs strace -ttTfyyy -s 1024 -o /tmp/puma.txt
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 109f451be5a..87f514a2fdd 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -965,6 +965,22 @@ license.save
License.current # check to make sure it applied
```
+This is needed for example in a known edge-case with
+[expired license and multiple LDAP servers](../auth/ldap/ldap-troubleshooting.md#expired-license-causes-errors-with-multiple-ldap-servers).
+
+### Remove licenses
+
+To clean up the [License History table](../../user/admin_area/license.md#license-history):
+
+```ruby
+TYPE = :trial?
+# or :expired?
+
+License.select(&TYPE).each(&:destroy!)
+
+# or even License.all.each(&:destroy!)
+```
+
## Registry
### Registry Disk Space Usage by Project
diff --git a/doc/administration/troubleshooting/kubernetes_cheat_sheet.md b/doc/administration/troubleshooting/kubernetes_cheat_sheet.md
index abeba514e4b..64a6979c016 100644
--- a/doc/administration/troubleshooting/kubernetes_cheat_sheet.md
+++ b/doc/administration/troubleshooting/kubernetes_cheat_sheet.md
@@ -165,8 +165,16 @@ and they will assist you with any issues you are having.
- How to connect to a GitLab PostgreSQL database:
+ In GitLab 14.2 (chart 5.2) and later:
+
+ ```shell
+ kubectl exec -it <task-runner-pod-name> -- /srv/gitlab/bin/rails dbconsole --include-password --database main
+ ```
+
+ In GitLab 14.1 (chart 5.1) and earlier:
+
```shell
- kubectl exec -it <task-runner-pod-name> -- /srv/gitlab/bin/rails dbconsole -p
+ kubectl exec -it <task-runner-pod-name> -- /srv/gitlab/bin/rails dbconsole --include-password
```
- How to get information about Helm installation status:
diff --git a/doc/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md
index 3df957bacf9..f8cb45dd00d 100644
--- a/doc/administration/troubleshooting/postgresql.md
+++ b/doc/administration/troubleshooting/postgresql.md
@@ -2,10 +2,9 @@
stage: Enablement
group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: reference
---
-# PostgreSQL
+# PostgreSQL **(FREE SELF)**
This page contains information about PostgreSQL the GitLab Support team uses
when troubleshooting. GitLab makes this information public, so that anyone can
diff --git a/doc/api/admin_sidekiq_queues.md b/doc/api/admin_sidekiq_queues.md
index 569dfd4c413..079ab96c938 100644
--- a/doc/api/admin_sidekiq_queues.md
+++ b/doc/api/admin_sidekiq_queues.md
@@ -35,7 +35,7 @@ DELETE /admin/sidekiq/queues/:queue_name
| `root_namespace` | string | no | The root namespace of the project |
| `subscription_plan` | string | no | The subscription plan of the root namespace (GitLab.com only) |
| `caller_id` | string | no | The endpoint or background job that schedule the job (for example: `ProjectsController#create`, `/api/:version/projects/:id`, `PostReceive`) |
-| `feature_category` | string | no | The feature category of the background job (for example: `issue_tracking` or `code_review`) |
+| `feature_category` | string | no | The feature category of the background job (for example: `team_planning` or `code_review`) |
| `worker_class` | string | no | The class of the background job worker (for example: `PostReceive` or `MergeWorker`) |
At least one attribute, other than `queue_name`, is required.
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index 7dc3fd1db21..d496ecbca5b 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -71,6 +71,7 @@ The following API resources are available in the project context:
| [Project milestones](milestones.md) | `/projects/:id/milestones` |
| [Project snippets](project_snippets.md) | `/projects/:id/snippets` |
| [Project templates](project_templates.md) | `/projects/:id/templates` |
+| [Project vulnerabilities](project_vulnerabilities.md) **(ULTIMATE)** | `/projects/:id/templates` |
| [Protected environments](protected_environments.md) | `/projects/:id/protected_environments` |
| [Protected branches](protected_branches.md) | `/projects/:id/protected_branches` |
| [Protected tags](protected_tags.md) | `/projects/:id/protected_tags` |
@@ -88,8 +89,7 @@ The following API resources are available in the project context:
| [User-starred metrics dashboards](metrics_user_starred_dashboards.md ) | `/projects/:id/metrics/user_starred_dashboards` |
| [Visual Review discussions](visual_review_discussions.md) **(PREMIUM)** | `/projects/:id/merge_requests/:merge_request_id/visual_review_discussions` |
| [Vulnerabilities](vulnerabilities.md) **(ULTIMATE)** | `/vulnerabilities/:id` |
-| [Vulnerability exports](vulnerability_exports.md) **(ULTIMATE)** | `/projects/:id/vulnerability_exports` |
-| [Project vulnerabilities](project_vulnerabilities.md) **(ULTIMATE)** | `/projects/:id/vulnerabilities` |
+| [Vulnerability exports](vulnerability_exports.md) **(ULTIMATE)** | `/projects/:id/vulnerability_exports` |
| [Vulnerability findings](vulnerability_findings.md) **(ULTIMATE)** | `/projects/:id/vulnerability_findings` |
| [Project wikis](wikis.md) | `/projects/:id/wikis` |
@@ -171,6 +171,7 @@ The following API resources are available outside of project and group contexts
| [Suggestions](suggestions.md) | `/suggestions` |
| [System hooks](system_hooks.md) | `/hooks` |
| [To-dos](todos.md) | `/todos` |
+| [Topics](topics.md) | `/topics` |
| [Service Data](usage_data.md) | `/usage_data` (For GitLab instance [Administrator](../user/permissions.md) users only) |
| [Users](users.md) | `/users` |
| [Validate `.gitlab-ci.yml` file](lint.md) | `/lint` |
diff --git a/doc/api/dependencies.md b/doc/api/dependencies.md
index b421a32b88a..1ecb78aa26d 100644
--- a/doc/api/dependencies.md
+++ b/doc/api/dependencies.md
@@ -34,7 +34,7 @@ GET /projects/:id/dependencies?package_manager=yarn,bundler
| Attribute | Type | Required | Description |
| ------------- | -------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
-| `package_manager` | string array | no | Returns dependencies belonging to specified package manager. Valid values: `bundler`, `composer`, `conan`, `go`, `maven`, `npm`, `nuget`, `pip`, `yarn`, or `sbt`. |
+| `package_manager` | string array | no | Returns dependencies belonging to specified package manager. Valid values: `bundler`, `composer`, `conan`, `go`, `gradle`, `maven`, `npm`, `nuget`, `pip`, `pipenv`, `yarn`, `sbt`, or `setuptools`. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/4/dependencies"
diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md
index bb719b5bc79..b244384bd6a 100644
--- a/doc/api/deploy_keys.md
+++ b/doc/api/deploy_keys.md
@@ -15,8 +15,16 @@ endpoint requires an administrator role and is not available on GitLab.com.
GET /deploy_keys
```
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|:------------|:---------|:---------|:----------------------|
+| `public` | boolean | **{dotted-circle}** No | Only return deploy keys that are public. Defaults to `false`. |
+
+Example request:
+
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/deploy_keys"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/deploy_keys?public=true"
```
Example response:
@@ -27,13 +35,36 @@ Example response:
"id": 1,
"title": "Public key",
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
- "created_at": "2013-10-02T10:12:29Z"
+ "fingerprint": "7f:72:08:7d:0e:47:48:ec:37:79:b2:76:68:b5:87:65",
+ "created_at": "2013-10-02T10:12:29Z",
+ "projects_with_write_access": [
+ {
+ "id": 73,
+ "description": null,
+ "name": "project2",
+ "name_with_namespace": "Sidney Jones / project2",
+ "path": "project2",
+ "path_with_namespace": "sidney_jones/project2",
+ "created_at": "2021-10-25T18:33:17.550Z"
+ },
+ {
+ "id": 74,
+ "description": null,
+ "name": "project3",
+ "name_with_namespace": "Sidney Jones / project3",
+ "path": "project3",
+ "path_with_namespace": "sidney_jones/project3",
+ "created_at": "2021-10-25T18:33:17.666Z"
+ }
+ ]
},
{
"id": 3,
"title": "Another Public key",
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
- "created_at": "2013-10-02T11:12:29Z"
+ "fingerprint": "64:d3:73:d4:83:70:ab:41:96:68:d5:3d:a5:b0:34:ea",
+ "created_at": "2013-10-02T11:12:29Z",
+ "projects_with_write_access": []
}
]
```
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index 5f710271d60..253bc76737b 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -358,6 +358,12 @@ Example response:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35739) in GitLab 12.7.
+NOTE:
+Not all deployments can be associated with merge requests.
+Please see
+[Track what merge requests were deployed to an environment](../ci/environments/index.md#track-newly-included-merge-requests-per-deployment)
+for more information.
+
This API retrieves the list of merge requests shipped with a given deployment:
```plaintext
diff --git a/doc/api/dora/metrics.md b/doc/api/dora/metrics.md
index 4fbd2b0fa80..3e7b7800034 100644
--- a/doc/api/dora/metrics.md
+++ b/doc/api/dora/metrics.md
@@ -10,7 +10,7 @@ type: reference, api
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in GitLab 13.10.
> - The legacy key/value pair `{ "<date>" => "<value>" }` was removed from the payload in GitLab 14.0.
-All methods require [reporter permissions and above](../../user/permissions.md).
+All methods require at least the Reporter [role](../../user/permissions.md).
## Get project-level DORA metrics
diff --git a/doc/api/events.md b/doc/api/events.md
index 2d173f0053f..265fc0e5fd2 100644
--- a/doc/api/events.md
+++ b/doc/api/events.md
@@ -8,55 +8,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Filter parameters
-### Action Types
-
-Available types for the `action` parameter, and the resources that might be affected:
-
-- `approved`
- - Merge request
-- `closed`
- - Epic **(PREMIUM)**
- - Issue
- - Merge request
- - Milestone
-- `commented` on any `Noteable` record.
- - Alert
- - Commit
- - Design
- - Issue
- - Merge request
- - Snippet
-- `created`
- - Design
- - Epic **(PREMIUM)**
- - Issue
- - Merge request
- - Milestone
- - Project
- - Wiki page
-- `destroyed`
- - Design
- - Milestone
- - Wiki page
-- `expired`
- - Project membership
-- `joined`
- - Project membership
-- `left`
- - Project membership
-- `merged`
- - Merge request
-- `pushed` commits to (or deleted commits from) a repository, individually or in bulk.
- - Project
-- `reopened`
- - Epic **(PREMIUM)**
- - Issue
- - Merge request
- - Milestone
-- `updated`
- - Design
- - Wiki page
+### Actions
+See [User contribution events](../user/index.md#user-contribution-events) for available types for the `action` parameter.
These options are in lowercase.
### Target Types
@@ -72,6 +26,7 @@ Available target types for the `target_type` parameter are:
- `user`
These options are in lowercase.
+Events associated with epics are not available using the API.
### Date formatting
@@ -88,6 +43,7 @@ GitLab removes events older than 3 years from the events table for performance r
## List currently authenticated user's events
Get a list of events for the authenticated user. Scope `read_user` or `api` is required.
+Events associated with epics are not available using the API.
```plaintext
GET /events
@@ -97,7 +53,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `action` | string | no | Include only events of a particular [action type](#action-types) |
+| `action` | string | no | Include only events of a particular [action type](#actions) |
| `target_type` | string | no | Include only events of a particular [target type](#target-types) |
| `before` | date | no | Include only events created before a particular date. [View how to format dates](#date-formatting). |
| `after` | date | no | Include only events created after a particular date. [View how to format dates](#date-formatting). |
@@ -160,6 +116,7 @@ Example response:
### Get user contribution events
Get the contribution events for the specified user, sorted from newest to oldest. Scope `read_user` or `api` is required.
+Events associated with epics are not available using API.
```plaintext
GET /users/:id/events
@@ -170,7 +127,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer | yes | The ID or Username of the user |
-| `action` | string | no | Include only events of a particular [action type](#action-types) |
+| `action` | string | no | Include only events of a particular [action type](#actions) |
| `target_type` | string | no | Include only events of a particular [target type](#target-types) |
| `before` | date | no | Include only events created before a particular date. [View how to format dates](#date-formatting). |
| `after` | date | no | Include only events created after a particular date. [View how to format dates](#date-formatting). |
@@ -308,7 +265,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `project_id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
-| `action` | string | no | Include only events of a particular [action type](#action-types) |
+| `action` | string | no | Include only events of a particular [action type](#actions) |
| `target_type` | string | no | Include only events of a particular [target type](#target-types) |
| `before` | date | no | Include only events created before a particular date. [View how to format dates](#date-formatting). |
| `after` | date | no | Include only events created after a particular date. [View how to format dates](#date-formatting). |
diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md
index d9b23485fd5..fb821824dd1 100644
--- a/doc/api/geo_nodes.md
+++ b/doc/api/geo_nodes.md
@@ -306,11 +306,6 @@ Example response:
"health": "Healthy",
"health_status": "Healthy",
"missing_oauth_application": false,
- "attachments_count": 1,
- "attachments_synced_count": null,
- "attachments_failed_count": null,
- "attachments_synced_missing_on_primary_count": 0,
- "attachments_synced_in_percentage": "0.00%",
"db_replication_lag_seconds": null,
"lfs_objects_count": 0,
"lfs_objects_synced_count": null,
@@ -465,11 +460,6 @@ Example response:
"health": "Healthy",
"health_status": "Healthy",
"missing_oauth_application": false,
- "attachments_count": 1,
- "attachments_synced_count": 1,
- "attachments_failed_count": 0,
- "attachments_synced_missing_on_primary_count": 0,
- "attachments_synced_in_percentage": "100.00%",
"db_replication_lag_seconds": 0,
"lfs_objects_count": 0,
"lfs_objects_synced_count": 0,
@@ -628,11 +618,6 @@ Example response:
"health": "Healthy",
"health_status": "Healthy",
"missing_oauth_application": false,
- "attachments_count": 1,
- "attachments_synced_count": 1,
- "attachments_failed_count": 0,
- "attachments_synced_missing_on_primary_count": 0,
- "attachments_synced_in_percentage": "100.00%",
"db_replication_lag_seconds": 0,
"lfs_objects_count": 0,
"lfs_objects_synced_count": 0,
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index e0f18f931f5..34af9736056 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -419,6 +419,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="querytimelogsstarttime"></a>`startTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or after startTime. |
| <a id="querytimelogsusername"></a>`username` | [`String`](#string) | List timelogs for a user. |
+### `Query.topics`
+
+Find project topics.
+
+Returns [`TopicConnection`](#topicconnection).
+
+This field returns a [connection](#connections). It accepts the
+four standard [pagination arguments](#connection-pagination-arguments):
+`before: String`, `after: String`, `first: Int`, `last: Int`.
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="querytopicssearch"></a>`search` | [`String`](#string) | Search query for topic name. |
+
### `Query.usageTrendsMeasurements`
Get statistics on the instance.
@@ -484,6 +500,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="queryvulnerabilitiesclusterid"></a>`clusterId` | [`[ClustersClusterID!]`](#clustersclusterid) | Filter vulnerabilities by `cluster_id`. Vulnerabilities with a `reportType` of `cluster_image_scanning` are only included with this filter. |
| <a id="queryvulnerabilitieshasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have linked issues. |
| <a id="queryvulnerabilitieshasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have been resolved on default branch. |
| <a id="queryvulnerabilitiesimage"></a>`image` | [`[String!]`](#string) | Filter vulnerabilities by location image. When this filter is present, the response only matches entries for a `reportType` that includes `container_scanning`, `cluster_image_scanning`. |
@@ -1009,6 +1026,31 @@ Input type: `ConfigureSastInput`
| <a id="mutationconfiguresasterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationconfiguresastsuccesspath"></a>`successPath` | [`String`](#string) | Redirect path to use when the response is successful. |
+### `Mutation.configureSastIac`
+
+Enable SAST IaC for a project in a new or
+modified `.gitlab-ci.yml` file in a new branch. The new
+branch and a URL to create a merge request are a part of the
+response.
+
+Input type: `ConfigureSastIacInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationconfiguresastiacclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationconfiguresastiacprojectpath"></a>`projectPath` | [`ID!`](#id) | Full path of the project. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationconfiguresastiacbranch"></a>`branch` | [`String`](#string) | Branch that has the new/modified `.gitlab-ci.yml` file. |
+| <a id="mutationconfiguresastiacclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationconfiguresastiacerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationconfiguresastiacsuccesspath"></a>`successPath` | [`String`](#string) | Redirect path to use when the response is successful. |
+
### `Mutation.configureSecretDetection`
Configure Secret Detection for a project by enabling Secret Detection
@@ -1034,6 +1076,27 @@ Input type: `ConfigureSecretDetectionInput`
| <a id="mutationconfiguresecretdetectionerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationconfiguresecretdetectionsuccesspath"></a>`successPath` | [`String`](#string) | Redirect path to use when the response is successful. |
+### `Mutation.corpusCreate`
+
+Available only when feature flag `corpus_management` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice.
+
+Input type: `CorpusCreateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationcorpuscreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationcorpuscreatefullpath"></a>`fullPath` | [`ID!`](#id) | Project the corpus belongs to. |
+| <a id="mutationcorpuscreatepackageid"></a>`packageId` | [`PackagesPackageID!`](#packagespackageid) | ID of the corpus package. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationcorpuscreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationcorpuscreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
### `Mutation.createAlertIssue`
Input type: `CreateAlertIssueInput`
@@ -1554,7 +1617,7 @@ Input type: `DastProfileCreateInput`
| ---- | ---- | ----------- |
| <a id="mutationdastprofilecreatebranchname"></a>`branchName` | [`String`](#string) | Associated branch. |
| <a id="mutationdastprofilecreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdastprofilecreatedastprofileschedule"></a>`dastProfileSchedule` | [`DastProfileScheduleInput`](#dastprofilescheduleinput) | Represents a DAST Profile Schedule. Results in an error if `dast_on_demand_scans_scheduler` feature flag is disabled. |
+| <a id="mutationdastprofilecreatedastprofileschedule"></a>`dastProfileSchedule` | [`DastProfileScheduleInput`](#dastprofilescheduleinput) | Represents a DAST Profile Schedule. |
| <a id="mutationdastprofilecreatedastscannerprofileid"></a>`dastScannerProfileId` | [`DastScannerProfileID!`](#dastscannerprofileid) | ID of the scanner profile to be associated. |
| <a id="mutationdastprofilecreatedastsiteprofileid"></a>`dastSiteProfileId` | [`DastSiteProfileID!`](#dastsiteprofileid) | ID of the site profile to be associated. |
| <a id="mutationdastprofilecreatedescription"></a>`description` | [`String`](#string) | Description of the profile. Defaults to an empty string. |
@@ -1598,7 +1661,7 @@ Input type: `DastProfileRunInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationdastprofilerunclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdastprofilerunfullpath"></a>`fullPath` | [`ID!`](#id) | Full path for the project the scanner profile belongs to. |
+| <a id="mutationdastprofilerunfullpath"></a>`fullPath` **{warning-solid}** | [`ID`](#id) | **Deprecated:** Full path not required to qualify Global ID. Deprecated in 14.5. |
| <a id="mutationdastprofilerunid"></a>`id` | [`DastProfileID!`](#dastprofileid) | ID of the profile to be used for the scan. |
#### Fields
@@ -1619,11 +1682,11 @@ Input type: `DastProfileUpdateInput`
| ---- | ---- | ----------- |
| <a id="mutationdastprofileupdatebranchname"></a>`branchName` | [`String`](#string) | Associated branch. |
| <a id="mutationdastprofileupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdastprofileupdatedastprofileschedule"></a>`dastProfileSchedule` | [`DastProfileScheduleInput`](#dastprofilescheduleinput) | Represents a DAST profile schedule. Results in an error if `dast_on_demand_scans_scheduler` feature flag is disabled. |
+| <a id="mutationdastprofileupdatedastprofileschedule"></a>`dastProfileSchedule` | [`DastProfileScheduleInput`](#dastprofilescheduleinput) | Represents a DAST profile schedule. |
| <a id="mutationdastprofileupdatedastscannerprofileid"></a>`dastScannerProfileId` | [`DastScannerProfileID`](#dastscannerprofileid) | ID of the scanner profile to be associated. |
| <a id="mutationdastprofileupdatedastsiteprofileid"></a>`dastSiteProfileId` | [`DastSiteProfileID`](#dastsiteprofileid) | ID of the site profile to be associated. |
| <a id="mutationdastprofileupdatedescription"></a>`description` | [`String`](#string) | Description of the profile. Defaults to an empty string. |
-| <a id="mutationdastprofileupdatefullpath"></a>`fullPath` | [`ID!`](#id) | Project the profile belongs to. |
+| <a id="mutationdastprofileupdatefullpath"></a>`fullPath` **{warning-solid}** | [`ID`](#id) | **Deprecated:** Full path not required to qualify Global ID. Deprecated in 14.5. |
| <a id="mutationdastprofileupdateid"></a>`id` | [`DastProfileID!`](#dastprofileid) | ID of the profile to be deleted. |
| <a id="mutationdastprofileupdatename"></a>`name` | [`String`](#string) | Name of the profile. |
| <a id="mutationdastprofileupdaterunafterupdate"></a>`runAfterUpdate` | [`Boolean`](#boolean) | Run scan using profile after update. Defaults to false. |
@@ -1671,7 +1734,7 @@ Input type: `DastScannerProfileDeleteInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationdastscannerprofiledeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdastscannerprofiledeletefullpath"></a>`fullPath` | [`ID!`](#id) | Full path for the project the scanner profile belongs to. |
+| <a id="mutationdastscannerprofiledeletefullpath"></a>`fullPath` **{warning-solid}** | [`ID`](#id) | **Deprecated:** Full path not required to qualify Global ID. Deprecated in 14.5. |
| <a id="mutationdastscannerprofiledeleteid"></a>`id` | [`DastScannerProfileID!`](#dastscannerprofileid) | ID of the scanner profile to be deleted. |
#### Fields
@@ -1690,7 +1753,7 @@ Input type: `DastScannerProfileUpdateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationdastscannerprofileupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdastscannerprofileupdatefullpath"></a>`fullPath` | [`ID!`](#id) | Project the scanner profile belongs to. |
+| <a id="mutationdastscannerprofileupdatefullpath"></a>`fullPath` **{warning-solid}** | [`ID`](#id) | **Deprecated:** Full path not required to qualify Global ID. Deprecated in 14.5. |
| <a id="mutationdastscannerprofileupdateid"></a>`id` | [`DastScannerProfileID!`](#dastscannerprofileid) | ID of the scanner profile to be updated. |
| <a id="mutationdastscannerprofileupdateprofilename"></a>`profileName` | [`String!`](#string) | Name of the scanner profile. |
| <a id="mutationdastscannerprofileupdatescantype"></a>`scanType` | [`DastScanTypeEnum`](#dastscantypeenum) | Indicates the type of DAST scan that will run. Either a Passive Scan or an Active Scan. |
@@ -1741,7 +1804,7 @@ Input type: `DastSiteProfileDeleteInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationdastsiteprofiledeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdastsiteprofiledeletefullpath"></a>`fullPath` | [`ID!`](#id) | Project the site profile belongs to. |
+| <a id="mutationdastsiteprofiledeletefullpath"></a>`fullPath` **{warning-solid}** | [`ID`](#id) | **Deprecated:** Full path not required to qualify Global ID. Deprecated in 14.5. |
| <a id="mutationdastsiteprofiledeleteid"></a>`id` | [`DastSiteProfileID!`](#dastsiteprofileid) | ID of the site profile to be deleted. |
#### Fields
@@ -1762,7 +1825,7 @@ Input type: `DastSiteProfileUpdateInput`
| <a id="mutationdastsiteprofileupdateauth"></a>`auth` | [`DastSiteProfileAuthInput`](#dastsiteprofileauthinput) | Parameters for authentication. |
| <a id="mutationdastsiteprofileupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationdastsiteprofileupdateexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | URLs to skip during an authenticated scan. |
-| <a id="mutationdastsiteprofileupdatefullpath"></a>`fullPath` | [`ID!`](#id) | Project the site profile belongs to. |
+| <a id="mutationdastsiteprofileupdatefullpath"></a>`fullPath` **{warning-solid}** | [`ID`](#id) | **Deprecated:** Full path not required to qualify Global ID. Deprecated in 14.5. |
| <a id="mutationdastsiteprofileupdateid"></a>`id` | [`DastSiteProfileID!`](#dastsiteprofileid) | ID of the site profile to be updated. |
| <a id="mutationdastsiteprofileupdateprofilename"></a>`profileName` | [`String!`](#string) | Name of the site profile. |
| <a id="mutationdastsiteprofileupdaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
@@ -2774,6 +2837,28 @@ Input type: `IssueSetConfidentialInput`
| <a id="mutationissuesetconfidentialerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationissuesetconfidentialissue"></a>`issue` | [`Issue`](#issue) | Issue after mutation. |
+### `Mutation.issueSetCrmContacts`
+
+Input type: `IssueSetCrmContactsInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationissuesetcrmcontactsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationissuesetcrmcontactscrmcontactids"></a>`crmContactIds` | [`[CustomerRelationsContactID!]!`](#customerrelationscontactid) | Customer relations contact IDs to set. Replaces existing contacts by default. |
+| <a id="mutationissuesetcrmcontactsiid"></a>`iid` | [`String!`](#string) | IID of the issue to mutate. |
+| <a id="mutationissuesetcrmcontactsoperationmode"></a>`operationMode` | [`MutationOperationMode`](#mutationoperationmode) | Changes the operation mode. Defaults to REPLACE. |
+| <a id="mutationissuesetcrmcontactsprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the issue to mutate is in. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationissuesetcrmcontactsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationissuesetcrmcontactserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationissuesetcrmcontactsissue"></a>`issue` | [`Issue`](#issue) | Issue after mutation. |
+
### `Mutation.issueSetDueDate`
Input type: `IssueSetDueDateInput`
@@ -3401,30 +3486,28 @@ Input type: `MergeRequestSetSubscriptionInput`
| <a id="mutationmergerequestsetsubscriptionerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationmergerequestsetsubscriptionmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
-### `Mutation.mergeRequestSetWip`
+### `Mutation.mergeRequestToggleAttentionRequested`
-WARNING:
-**Deprecated** in 13.12.
-Use mergeRequestSetDraft.
+Available only when feature flag `mr_attention_requests` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice.
-Input type: `MergeRequestSetWipInput`
+Input type: `MergeRequestToggleAttentionRequestedInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationmergerequestsetwipclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationmergerequestsetwipiid"></a>`iid` | [`String!`](#string) | IID of the merge request to mutate. |
-| <a id="mutationmergerequestsetwipprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the merge request to mutate is in. |
-| <a id="mutationmergerequestsetwipwip"></a>`wip` | [`Boolean!`](#boolean) | Whether or not to set the merge request as a draft. |
+| <a id="mutationmergerequesttoggleattentionrequestedclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationmergerequesttoggleattentionrequestediid"></a>`iid` | [`String!`](#string) | IID of the merge request to mutate. |
+| <a id="mutationmergerequesttoggleattentionrequestedprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the merge request to mutate is in. |
+| <a id="mutationmergerequesttoggleattentionrequesteduserid"></a>`userId` | [`UserID!`](#userid) | User ID for the user to toggle attention requested. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationmergerequestsetwipclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationmergerequestsetwiperrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationmergerequestsetwipmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
+| <a id="mutationmergerequesttoggleattentionrequestedclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationmergerequesttoggleattentionrequestederrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationmergerequesttoggleattentionrequestedmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
### `Mutation.mergeRequestUpdate`
@@ -4042,6 +4125,7 @@ Input type: `ScanExecutionPolicyCommitInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationscanexecutionpolicycommitclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationscanexecutionpolicycommitname"></a>`name` | [`String`](#string) | Name of the policy. If the name is null, the `name` field from `policy_yaml` is used. |
| <a id="mutationscanexecutionpolicycommitoperationmode"></a>`operationMode` | [`MutationOperationMode!`](#mutationoperationmode) | Changes the operation mode. |
| <a id="mutationscanexecutionpolicycommitpolicyyaml"></a>`policyYaml` | [`String!`](#string) | YAML snippet of the policy. |
| <a id="mutationscanexecutionpolicycommitprojectpath"></a>`projectPath` | [`ID!`](#id) | Full path of the project. |
@@ -4096,6 +4180,26 @@ Input type: `SecurityPolicyProjectCreateInput`
| <a id="mutationsecuritypolicyprojectcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationsecuritypolicyprojectcreateproject"></a>`project` | [`Project`](#project) | Security Policy Project that was created. |
+### `Mutation.securityPolicyProjectUnassign`
+
+Unassigns the security policy project for the given project(`project_path`).
+
+Input type: `SecurityPolicyProjectUnassignInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationsecuritypolicyprojectunassignclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationsecuritypolicyprojectunassignprojectpath"></a>`projectPath` | [`ID!`](#id) | Full path of the project. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationsecuritypolicyprojectunassignclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationsecuritypolicyprojectunassignerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
### `Mutation.terraformStateDelete`
Input type: `TerraformStateDeleteInput`
@@ -4710,17 +4814,17 @@ Input type: `VulnerabilityCreateInput`
| <a id="mutationvulnerabilitycreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationvulnerabilitycreateconfidence"></a>`confidence` | [`VulnerabilityConfidence`](#vulnerabilityconfidence) | Confidence of the vulnerability (defaults to `unknown`). |
| <a id="mutationvulnerabilitycreateconfirmedat"></a>`confirmedAt` | [`Time`](#time) | Timestamp of when the vulnerability state changed to confirmed (defaults to creation time if status is `confirmed`). |
-| <a id="mutationvulnerabilitycreatedescription"></a>`description` | [`String!`](#string) | Description of the vulnerability. |
+| <a id="mutationvulnerabilitycreatedescription"></a>`description` | [`String!`](#string) | Long text section that describes the vulnerability in more detail. |
| <a id="mutationvulnerabilitycreatedetectedat"></a>`detectedAt` | [`Time`](#time) | Timestamp of when the vulnerability was first detected (defaults to creation time). |
| <a id="mutationvulnerabilitycreatedismissedat"></a>`dismissedAt` | [`Time`](#time) | Timestamp of when the vulnerability state changed to dismissed (defaults to creation time if status is `dismissed`). |
| <a id="mutationvulnerabilitycreateidentifiers"></a>`identifiers` | [`[VulnerabilityIdentifierInput!]!`](#vulnerabilityidentifierinput) | Array of CVE or CWE identifiers for the vulnerability. |
-| <a id="mutationvulnerabilitycreatemessage"></a>`message` | [`String`](#string) | Additional information about the vulnerability. |
+| <a id="mutationvulnerabilitycreatemessage"></a>`message` | [`String`](#string) | Short text section that describes the vulnerability. This may include the finding's specific information. |
| <a id="mutationvulnerabilitycreatename"></a>`name` | [`String!`](#string) | Name of the vulnerability. |
| <a id="mutationvulnerabilitycreateproject"></a>`project` | [`ProjectID!`](#projectid) | ID of the project to attach the vulnerability to. |
| <a id="mutationvulnerabilitycreateresolvedat"></a>`resolvedAt` | [`Time`](#time) | Timestamp of when the vulnerability state changed to resolved (defaults to creation time if status is `resolved`). |
| <a id="mutationvulnerabilitycreatescanner"></a>`scanner` | [`VulnerabilityScannerInput!`](#vulnerabilityscannerinput) | Information about the scanner used to discover the vulnerability. |
| <a id="mutationvulnerabilitycreateseverity"></a>`severity` | [`VulnerabilitySeverity`](#vulnerabilityseverity) | Severity of the vulnerability (defaults to `unknown`). |
-| <a id="mutationvulnerabilitycreatesolution"></a>`solution` | [`String`](#string) | How to fix this vulnerability. |
+| <a id="mutationvulnerabilitycreatesolution"></a>`solution` | [`String`](#string) | Instructions for how to fix the vulnerability. |
| <a id="mutationvulnerabilitycreatestate"></a>`state` | [`VulnerabilityState`](#vulnerabilitystate) | State of the vulnerability (defaults to `detected`). |
#### Fields
@@ -5563,6 +5667,29 @@ The edge type for [`ContainerRepositoryTag`](#containerrepositorytag).
| <a id="containerrepositorytagedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="containerrepositorytagedgenode"></a>`node` | [`ContainerRepositoryTag`](#containerrepositorytag) | The item at the end of the edge. |
+#### `CoverageFuzzingCorpusConnection`
+
+The connection type for [`CoverageFuzzingCorpus`](#coveragefuzzingcorpus).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="coveragefuzzingcorpusconnectionedges"></a>`edges` | [`[CoverageFuzzingCorpusEdge]`](#coveragefuzzingcorpusedge) | A list of edges. |
+| <a id="coveragefuzzingcorpusconnectionnodes"></a>`nodes` | [`[CoverageFuzzingCorpus]`](#coveragefuzzingcorpus) | A list of nodes. |
+| <a id="coveragefuzzingcorpusconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `CoverageFuzzingCorpusEdge`
+
+The edge type for [`CoverageFuzzingCorpus`](#coveragefuzzingcorpus).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="coveragefuzzingcorpusedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="coveragefuzzingcorpusedgenode"></a>`node` | [`CoverageFuzzingCorpus`](#coveragefuzzingcorpus) | The item at the end of the edge. |
+
#### `CustomEmojiConnection`
The connection type for [`CustomEmoji`](#customemoji).
@@ -7577,6 +7704,29 @@ The edge type for [`Todo`](#todo).
| <a id="todoedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="todoedgenode"></a>`node` | [`Todo`](#todo) | The item at the end of the edge. |
+#### `TopicConnection`
+
+The connection type for [`Topic`](#topic).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="topicconnectionedges"></a>`edges` | [`[TopicEdge]`](#topicedge) | A list of edges. |
+| <a id="topicconnectionnodes"></a>`nodes` | [`[Topic]`](#topic) | A list of nodes. |
+| <a id="topicconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `TopicEdge`
+
+The edge type for [`Topic`](#topic).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="topicedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="topicedgenode"></a>`node` | [`Topic`](#topic) | The item at the end of the edge. |
+
#### `TreeConnection`
The connection type for [`Tree`](#tree).
@@ -8535,6 +8685,7 @@ Represents the total number of issues and their weights for a particular day.
| ---- | ---- | ----------- |
| <a id="cijobartifactdownloadpath"></a>`downloadPath` | [`String`](#string) | URL for downloading the artifact's file. |
| <a id="cijobartifactfiletype"></a>`fileType` | [`JobArtifactFileType`](#jobartifactfiletype) | File type of the artifact. |
+| <a id="cijobartifactname"></a>`name` | [`String`](#string) | File name of the artifact. |
### `CiJobTokenScopeType`
@@ -8553,6 +8704,7 @@ Represents the total number of issues and their weights for a particular day.
| <a id="ciminutesnamespacemonthlyusageminutes"></a>`minutes` | [`Int`](#int) | Total number of minutes used by all projects in the namespace. |
| <a id="ciminutesnamespacemonthlyusagemonth"></a>`month` | [`String`](#string) | Month related to the usage data. |
| <a id="ciminutesnamespacemonthlyusageprojects"></a>`projects` | [`CiMinutesProjectMonthlyUsageConnection`](#ciminutesprojectmonthlyusageconnection) | CI minutes usage data for projects in the namespace. (see [Connections](#connections)) |
+| <a id="ciminutesnamespacemonthlyusagesharedrunnersduration"></a>`sharedRunnersDuration` | [`Int`](#int) | Total numbers of minutes used by the shared runners in the namespace. |
### `CiMinutesProjectMonthlyUsage`
@@ -8696,6 +8848,8 @@ Represents a code quality degradation on the pipeline.
| <a id="commitauthoreddate"></a>`authoredDate` | [`Time`](#time) | Timestamp of when the commit was authored. |
| <a id="commitdescription"></a>`description` | [`String`](#string) | Description of the commit message. |
| <a id="commitdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
+| <a id="commitfulltitle"></a>`fullTitle` | [`String`](#string) | Full title of the commit message. |
+| <a id="commitfulltitlehtml"></a>`fullTitleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `full_title`. |
| <a id="commitid"></a>`id` | [`ID!`](#id) | ID (global ID) of the commit. |
| <a id="commitmessage"></a>`message` | [`String`](#string) | Raw commit message. |
| <a id="commitsha"></a>`sha` | [`String!`](#string) | SHA1 ID of the commit. |
@@ -8723,6 +8877,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="commitpipelinesref"></a>`ref` | [`String`](#string) | Filter pipelines by the ref they are run for. |
+| <a id="commitpipelinesscope"></a>`scope` | [`PipelineScopeEnum`](#pipelinescopeenum) | Filter pipelines by scope. |
| <a id="commitpipelinessha"></a>`sha` | [`String`](#string) | Filter pipelines by the sha of the commit they are run for. |
| <a id="commitpipelinessource"></a>`source` | [`String`](#string) | Filter pipelines by their source. Will be ignored if `dast_view_scans` feature flag is disabled. |
| <a id="commitpipelinesstatus"></a>`status` | [`PipelineStatusEnum`](#pipelinestatusenum) | Filter pipelines by their status. |
@@ -8875,6 +9030,17 @@ A tag from a container repository.
| <a id="containerrepositorytagshortrevision"></a>`shortRevision` | [`String`](#string) | Short revision of the tag. |
| <a id="containerrepositorytagtotalsize"></a>`totalSize` | [`BigInt`](#bigint) | Size of the tag. |
+### `CoverageFuzzingCorpus`
+
+Corpus for a coverage fuzzing job.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="coveragefuzzingcorpusid"></a>`id` | [`AppSecFuzzingCoverageCorpusID!`](#appsecfuzzingcoveragecorpusid) | ID of the corpus. |
+| <a id="coveragefuzzingcorpuspackage"></a>`package` | [`PackageDetailsType!`](#packagedetailstype) | Package of the corpus. |
+
### `CurrentLicense`
Represents the current license.
@@ -8887,6 +9053,7 @@ Represents the current license.
| <a id="currentlicensebillableuserscount"></a>`billableUsersCount` | [`Int`](#int) | Number of billable users on the system. |
| <a id="currentlicenseblockchangesat"></a>`blockChangesAt` | [`Date`](#date) | Date, including grace period, when licensed features will be blocked. |
| <a id="currentlicensecompany"></a>`company` | [`String`](#string) | Company of the licensee. |
+| <a id="currentlicensecreatedat"></a>`createdAt` | [`Date`](#date) | Date when the license was added. |
| <a id="currentlicenseemail"></a>`email` | [`String`](#string) | Email of the licensee. |
| <a id="currentlicenseexpiresat"></a>`expiresAt` | [`Date`](#date) | Date when the license expires. |
| <a id="currentlicenseid"></a>`id` | [`ID!`](#id) | ID of the license. |
@@ -8950,7 +9117,7 @@ Represents a DAST Profile.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="dastprofilebranch"></a>`branch` | [`DastProfileBranch`](#dastprofilebranch) | Associated branch. |
-| <a id="dastprofiledastprofileschedule"></a>`dastProfileSchedule` | [`DastProfileSchedule`](#dastprofileschedule) | Associated profile schedule. Will always return `null` if `dast_on_demand_scans_scheduler` feature flag is disabled. |
+| <a id="dastprofiledastprofileschedule"></a>`dastProfileSchedule` | [`DastProfileSchedule`](#dastprofileschedule) | Associated profile schedule. |
| <a id="dastprofiledastscannerprofile"></a>`dastScannerProfile` | [`DastScannerProfile`](#dastscannerprofile) | Associated scanner profile. |
| <a id="dastprofiledastsiteprofile"></a>`dastSiteProfile` | [`DastSiteProfile`](#dastsiteprofile) | Associated site profile. |
| <a id="dastprofiledescription"></a>`description` | [`String`](#string) | Description of the scan. |
@@ -9120,6 +9287,7 @@ Dependency proxy manifest.
| <a id="dependencyproxymanifestcreatedat"></a>`createdAt` | [`Time!`](#time) | Date of creation. |
| <a id="dependencyproxymanifestdigest"></a>`digest` | [`String!`](#string) | Digest of the manifest. |
| <a id="dependencyproxymanifestfilename"></a>`fileName` | [`String!`](#string) | Name of the manifest. |
+| <a id="dependencyproxymanifestid"></a>`id` | [`DependencyProxyManifestID!`](#dependencyproxymanifestid) | ID of the manifest. |
| <a id="dependencyproxymanifestimagename"></a>`imageName` | [`String!`](#string) | Name of the image. |
| <a id="dependencyproxymanifestsize"></a>`size` | [`String!`](#string) | Size of the manifest file. |
| <a id="dependencyproxymanifestupdatedat"></a>`updatedAt` | [`Time!`](#time) | Date of most recent update. |
@@ -10226,7 +10394,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupemailsdisabled"></a>`emailsDisabled` | [`Boolean`](#boolean) | Indicates if a group has email notifications disabled. |
| <a id="groupepicboards"></a>`epicBoards` | [`EpicBoardConnection`](#epicboardconnection) | Find epic boards. (see [Connections](#connections)) |
| <a id="groupepicsenabled"></a>`epicsEnabled` | [`Boolean`](#boolean) | Indicates if Epics are enabled for namespace. |
-| <a id="groupexternalauditeventdestinations"></a>`externalAuditEventDestinations` | [`ExternalAuditEventDestinationConnection`](#externalauditeventdestinationconnection) | External locations that receive audit events belonging to the group. Available only when feature flag `ff_external_audit_events_namespace` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. (see [Connections](#connections)) |
+| <a id="groupexternalauditeventdestinations"></a>`externalAuditEventDestinations` | [`ExternalAuditEventDestinationConnection`](#externalauditeventdestinationconnection) | External locations that receive audit events belonging to the group. (see [Connections](#connections)) |
| <a id="groupfullname"></a>`fullName` | [`String!`](#string) | Full name of the namespace. |
| <a id="groupfullpath"></a>`fullPath` | [`ID!`](#id) | Full path of the namespace. |
| <a id="groupid"></a>`id` | [`ID!`](#id) | ID of the namespace. |
@@ -10580,6 +10748,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="groupmergerequestsassigneeusername"></a>`assigneeUsername` | [`String`](#string) | Username of the assignee. |
| <a id="groupmergerequestsauthorusername"></a>`authorUsername` | [`String`](#string) | Username of the author. |
+| <a id="groupmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="groupmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="groupmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="groupmergerequestsincludesubgroups"></a>`includeSubgroups` | [`Boolean`](#boolean) | Include merge requests belonging to subgroups. |
| <a id="groupmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
@@ -10716,6 +10886,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="groupvulnerabilitiesclusterid"></a>`clusterId` | [`[ClustersClusterID!]`](#clustersclusterid) | Filter vulnerabilities by `cluster_id`. Vulnerabilities with a `reportType` of `cluster_image_scanning` are only included with this filter. |
| <a id="groupvulnerabilitieshasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have linked issues. |
| <a id="groupvulnerabilitieshasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have been resolved on default branch. |
| <a id="groupvulnerabilitiesimage"></a>`image` | [`[String!]`](#string) | Filter vulnerabilities by location image. When this filter is present, the response only matches entries for a `reportType` that includes `container_scanning`, `cluster_image_scanning`. |
@@ -10840,6 +11011,19 @@ Represents the Geo sync and verification state of a group wiki repository.
| <a id="groupwikirepositoryregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the GroupWikiRepositoryRegistry. |
| <a id="groupwikirepositoryregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the GroupWikiRepositoryRegistry. |
+### `HelmFileMetadata`
+
+Helm file metadata.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="helmfilemetadatachannel"></a>`channel` | [`String!`](#string) | Channel of the Helm chart. |
+| <a id="helmfilemetadatacreatedat"></a>`createdAt` | [`Time!`](#time) | Date of creation. |
+| <a id="helmfilemetadatametadata"></a>`metadata` | [`PackageHelmMetadataType!`](#packagehelmmetadatatype) | Metadata of the Helm chart. |
+| <a id="helmfilemetadataupdatedat"></a>`updatedAt` | [`Time!`](#time) | Date of most recent update. |
+
### `IncidentManagementOncallRotation`
Describes an incident management on-call rotation.
@@ -11258,6 +11442,7 @@ Represents an entry from the Cloud License history.
| <a id="licensehistoryentryactivatedat"></a>`activatedAt` | [`Date`](#date) | Date when the license was activated. |
| <a id="licensehistoryentryblockchangesat"></a>`blockChangesAt` | [`Date`](#date) | Date, including grace period, when licensed features will be blocked. |
| <a id="licensehistoryentrycompany"></a>`company` | [`String`](#string) | Company of the licensee. |
+| <a id="licensehistoryentrycreatedat"></a>`createdAt` | [`Date`](#date) | Date when the license was added. |
| <a id="licensehistoryentryemail"></a>`email` | [`String`](#string) | Email of the licensee. |
| <a id="licensehistoryentryexpiresat"></a>`expiresAt` | [`Date`](#date) | Date when the license expires. |
| <a id="licensehistoryentryid"></a>`id` | [`ID!`](#id) | ID of the license. |
@@ -11305,7 +11490,7 @@ Maven metadata.
| <a id="mergerequestconflicts"></a>`conflicts` | [`Boolean!`](#boolean) | Indicates if the merge request has conflicts. |
| <a id="mergerequestcreatedat"></a>`createdAt` | [`Time!`](#time) | Timestamp of when the merge request was created. |
| <a id="mergerequestdefaultmergecommitmessage"></a>`defaultMergeCommitMessage` | [`String`](#string) | Default merge commit message of the merge request. |
-| <a id="mergerequestdefaultmergecommitmessagewithdescription"></a>`defaultMergeCommitMessageWithDescription` | [`String`](#string) | Default merge commit message of the merge request with description. |
+| <a id="mergerequestdefaultmergecommitmessagewithdescription"></a>`defaultMergeCommitMessageWithDescription` **{warning-solid}** | [`String`](#string) | **Deprecated** in 14.5. Define merge commit template in project and use `defaultMergeCommitMessage`. |
| <a id="mergerequestdefaultsquashcommitmessage"></a>`defaultSquashCommitMessage` | [`String`](#string) | Default squash commit message of the merge request. |
| <a id="mergerequestdescription"></a>`description` | [`String`](#string) | Description of the merge request (Markdown rendered as HTML for caching). |
| <a id="mergerequestdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
@@ -11375,7 +11560,6 @@ Maven metadata.
| <a id="mergerequestusernotescount"></a>`userNotesCount` | [`Int`](#int) | User notes count of the merge request. |
| <a id="mergerequestuserpermissions"></a>`userPermissions` | [`MergeRequestPermissions!`](#mergerequestpermissions) | Permissions for the current user on the resource. |
| <a id="mergerequestweburl"></a>`webUrl` | [`String`](#string) | Web URL of the merge request. |
-| <a id="mergerequestworkinprogress"></a>`workInProgress` **{warning-solid}** | [`Boolean!`](#boolean) | **Deprecated** in 13.12. Use `draft`. |
#### Fields with arguments
@@ -11422,6 +11606,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mergerequestpipelinesref"></a>`ref` | [`String`](#string) | Filter pipelines by the ref they are run for. |
+| <a id="mergerequestpipelinesscope"></a>`scope` | [`PipelineScopeEnum`](#pipelinescopeenum) | Filter pipelines by scope. |
| <a id="mergerequestpipelinessha"></a>`sha` | [`String`](#string) | Filter pipelines by the sha of the commit they are run for. |
| <a id="mergerequestpipelinessource"></a>`source` | [`String`](#string) | Filter pipelines by their source. Will be ignored if `dast_view_scans` feature flag is disabled. |
| <a id="mergerequestpipelinesstatus"></a>`status` | [`PipelineStatusEnum`](#pipelinestatusenum) | Filter pipelines by their status. |
@@ -11494,6 +11679,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mergerequestassigneeassignedmergerequestsauthorusername"></a>`authorUsername` | [`String`](#string) | Username of the author. |
+| <a id="mergerequestassigneeassignedmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="mergerequestassigneeassignedmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="mergerequestassigneeassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestassigneeassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestassigneeassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -11523,6 +11710,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mergerequestassigneeauthoredmergerequestsassigneeusername"></a>`assigneeUsername` | [`String`](#string) | Username of the assignee. |
+| <a id="mergerequestassigneeauthoredmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="mergerequestassigneeauthoredmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="mergerequestassigneeauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestassigneeauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestassigneeauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -11570,6 +11759,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="mergerequestassigneereviewrequestedmergerequestsassigneeusername"></a>`assigneeUsername` | [`String`](#string) | Username of the assignee. |
| <a id="mergerequestassigneereviewrequestedmergerequestsauthorusername"></a>`authorUsername` | [`String`](#string) | Username of the author. |
+| <a id="mergerequestassigneereviewrequestedmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="mergerequestassigneereviewrequestedmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="mergerequestassigneereviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestassigneereviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestassigneereviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -11740,6 +11931,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mergerequestreviewerassignedmergerequestsauthorusername"></a>`authorUsername` | [`String`](#string) | Username of the author. |
+| <a id="mergerequestreviewerassignedmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="mergerequestreviewerassignedmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="mergerequestreviewerassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestreviewerassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestreviewerassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -11769,6 +11962,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mergerequestreviewerauthoredmergerequestsassigneeusername"></a>`assigneeUsername` | [`String`](#string) | Username of the assignee. |
+| <a id="mergerequestreviewerauthoredmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="mergerequestreviewerauthoredmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="mergerequestreviewerauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestreviewerauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestreviewerauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -11816,6 +12011,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="mergerequestreviewerreviewrequestedmergerequestsassigneeusername"></a>`assigneeUsername` | [`String`](#string) | Username of the assignee. |
| <a id="mergerequestreviewerreviewrequestedmergerequestsauthorusername"></a>`authorUsername` | [`String`](#string) | Username of the author. |
+| <a id="mergerequestreviewerreviewrequestedmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="mergerequestreviewerreviewrequestedmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="mergerequestreviewerreviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestreviewerreviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestreviewerreviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -12297,6 +12494,61 @@ Represents the Geo sync and verification state of a package file.
| <a id="packagefileregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the PackageFileRegistry. |
| <a id="packagefileregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the PackageFileRegistry. |
+### `PackageHelmDependencyType`
+
+Represents a Helm dependency.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="packagehelmdependencytypealias"></a>`alias` | [`String`](#string) | Alias of the dependency. |
+| <a id="packagehelmdependencytypecondition"></a>`condition` | [`String`](#string) | Condition of the dependency. |
+| <a id="packagehelmdependencytypeenabled"></a>`enabled` | [`Boolean`](#boolean) | Indicates the dependency is enabled. |
+| <a id="packagehelmdependencytypeimportvalues"></a>`importValues` | [`[JSON!]`](#json) | Import-values of the dependency. |
+| <a id="packagehelmdependencytypename"></a>`name` | [`String`](#string) | Name of the dependency. |
+| <a id="packagehelmdependencytyperepository"></a>`repository` | [`String`](#string) | Repository of the dependency. |
+| <a id="packagehelmdependencytypetags"></a>`tags` | [`[String!]`](#string) | Tags of the dependency. |
+| <a id="packagehelmdependencytypeversion"></a>`version` | [`String`](#string) | Version of the dependency. |
+
+### `PackageHelmMaintainerType`
+
+Represents a Helm maintainer.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="packagehelmmaintainertypeemail"></a>`email` | [`String`](#string) | Email of the maintainer. |
+| <a id="packagehelmmaintainertypename"></a>`name` | [`String`](#string) | Name of the maintainer. |
+| <a id="packagehelmmaintainertypeurl"></a>`url` | [`String`](#string) | URL of the maintainer. |
+
+### `PackageHelmMetadataType`
+
+Represents the contents of a Helm Chart.yml file.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="packagehelmmetadatatypeannotations"></a>`annotations` | [`JSON`](#json) | Annotations for the chart. |
+| <a id="packagehelmmetadatatypeapiversion"></a>`apiVersion` | [`String!`](#string) | API version of the chart. |
+| <a id="packagehelmmetadatatypeappversion"></a>`appVersion` | [`String`](#string) | App version of the chart. |
+| <a id="packagehelmmetadatatypecondition"></a>`condition` | [`String`](#string) | Condition for the chart. |
+| <a id="packagehelmmetadatatypedependencies"></a>`dependencies` | [`[PackageHelmDependencyType!]`](#packagehelmdependencytype) | Dependencies of the chart. |
+| <a id="packagehelmmetadatatypedeprecated"></a>`deprecated` | [`Boolean`](#boolean) | Indicates if the chart is deprecated. |
+| <a id="packagehelmmetadatatypedescription"></a>`description` | [`String`](#string) | Description of the chart. |
+| <a id="packagehelmmetadatatypehome"></a>`home` | [`String`](#string) | URL of the home page. |
+| <a id="packagehelmmetadatatypeicon"></a>`icon` | [`String`](#string) | URL to an SVG or PNG image for the chart. |
+| <a id="packagehelmmetadatatypekeywords"></a>`keywords` | [`[String!]`](#string) | Keywords for the chart. |
+| <a id="packagehelmmetadatatypekubeversion"></a>`kubeVersion` | [`String`](#string) | Kubernetes versions for the chart. |
+| <a id="packagehelmmetadatatypemaintainers"></a>`maintainers` | [`[PackageHelmMaintainerType!]`](#packagehelmmaintainertype) | Maintainers of the chart. |
+| <a id="packagehelmmetadatatypename"></a>`name` | [`String!`](#string) | Name of the chart. |
+| <a id="packagehelmmetadatatypesources"></a>`sources` | [`[String!]`](#string) | URLs of the source code for the chart. |
+| <a id="packagehelmmetadatatypetags"></a>`tags` | [`String`](#string) | Tags for the chart. |
+| <a id="packagehelmmetadatatypetype"></a>`type` | [`String`](#string) | Type of the chart. |
+| <a id="packagehelmmetadatatypeversion"></a>`version` | [`String!`](#string) | Version of the chart. |
+
### `PackageSettings`
Namespace-level Package Registry settings.
@@ -12375,6 +12627,7 @@ Represents a file or directory in the project repository that has been locked.
| <a id="pipelinebeforesha"></a>`beforeSha` | [`String`](#string) | Base SHA of the source branch. |
| <a id="pipelinecancelable"></a>`cancelable` | [`Boolean!`](#boolean) | Specifies if a pipeline can be canceled. |
| <a id="pipelinecodequalityreports"></a>`codeQualityReports` | [`CodeQualityDegradationConnection`](#codequalitydegradationconnection) | Code Quality degradations reported on the pipeline. (see [Connections](#connections)) |
+| <a id="pipelinecommit"></a>`commit` | [`Commit`](#commit) | Git commit of the pipeline. |
| <a id="pipelinecommitpath"></a>`commitPath` | [`String`](#string) | Path to the commit that triggered the pipeline. |
| <a id="pipelinecommittedat"></a>`committedAt` | [`Time`](#time) | Timestamp of the pipeline's commit. |
| <a id="pipelinecomplete"></a>`complete` | [`Boolean!`](#boolean) | Indicates if a pipeline is complete. |
@@ -12388,6 +12641,7 @@ Represents a file or directory in the project repository that has been locked.
| <a id="pipelinefinishedat"></a>`finishedAt` | [`Time`](#time) | Timestamp of the pipeline's completion. |
| <a id="pipelineid"></a>`id` | [`ID!`](#id) | ID of the pipeline. |
| <a id="pipelineiid"></a>`iid` | [`String!`](#string) | Internal ID of the pipeline. |
+| <a id="pipelinejobartifacts"></a>`jobArtifacts` | [`[CiJobArtifact!]`](#cijobartifact) | Job artifacts of the pipeline. |
| <a id="pipelinepath"></a>`path` | [`String`](#string) | Relative path to the pipeline's page. |
| <a id="pipelineproject"></a>`project` | [`Project`](#project) | Project the pipeline belongs to. |
| <a id="pipelinequeuedduration"></a>`queuedDuration` | [`Duration`](#duration) | How long the pipeline was queued before starting. |
@@ -12559,8 +12813,8 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectcontainerexpirationpolicy"></a>`containerExpirationPolicy` | [`ContainerExpirationPolicy`](#containerexpirationpolicy) | Container expiration policy of the project. |
| <a id="projectcontainerregistryenabled"></a>`containerRegistryEnabled` | [`Boolean`](#boolean) | Indicates if Container Registry is enabled for the current user. |
| <a id="projectcontainerrepositoriescount"></a>`containerRepositoriesCount` | [`Int!`](#int) | Number of container repositories in the project. |
+| <a id="projectcorpuses"></a>`corpuses` | [`CoverageFuzzingCorpusConnection`](#coveragefuzzingcorpusconnection) | Find corpuses of the project. Available only when feature flag `corpus_management` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. (see [Connections](#connections)) |
| <a id="projectcreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp of the project creation. |
-| <a id="projectdastprofiles"></a>`dastProfiles` | [`DastProfileConnection`](#dastprofileconnection) | DAST Profiles associated with the project. (see [Connections](#connections)) |
| <a id="projectdastscannerprofiles"></a>`dastScannerProfiles` | [`DastScannerProfileConnection`](#dastscannerprofileconnection) | DAST scanner profiles associated with the project. (see [Connections](#connections)) |
| <a id="projectdastsiteprofiles"></a>`dastSiteProfiles` | [`DastSiteProfileConnection`](#dastsiteprofileconnection) | DAST Site Profiles associated with the project. (see [Connections](#connections)) |
| <a id="projectdescription"></a>`description` | [`String`](#string) | Short description of the project. |
@@ -12580,6 +12834,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectjobsenabled"></a>`jobsEnabled` | [`Boolean`](#boolean) | Indicates if CI/CD pipeline jobs are enabled for the current user. |
| <a id="projectlastactivityat"></a>`lastActivityAt` | [`Time`](#time) | Timestamp of the project last activity. |
| <a id="projectlfsenabled"></a>`lfsEnabled` | [`Boolean`](#boolean) | Indicates if the project has Large File Storage (LFS) enabled. |
+| <a id="projectmergecommittemplate"></a>`mergeCommitTemplate` | [`String`](#string) | Template used to create merge commit message in merge requests. |
| <a id="projectmergerequestsenabled"></a>`mergeRequestsEnabled` | [`Boolean`](#boolean) | Indicates if Merge Requests are enabled for the current user. |
| <a id="projectmergerequestsffonlyenabled"></a>`mergeRequestsFfOnlyEnabled` | [`Boolean`](#boolean) | Indicates if no merge commits should be created and all merges should instead be fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. |
| <a id="projectname"></a>`name` | [`String!`](#string) | Name of the project (without namespace). |
@@ -12600,7 +12855,6 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectrequestaccessenabled"></a>`requestAccessEnabled` | [`Boolean`](#boolean) | Indicates if users can request member access to the project. |
| <a id="projectrequirementstatescount"></a>`requirementStatesCount` | [`RequirementStatesCount`](#requirementstatescount) | Number of requirements for the project by their state. |
| <a id="projectsastciconfiguration"></a>`sastCiConfiguration` | [`SastCiConfiguration`](#sastciconfiguration) | SAST CI configuration for the project. |
-| <a id="projectscanexecutionpolicies"></a>`scanExecutionPolicies` | [`ScanExecutionPolicyConnection`](#scanexecutionpolicyconnection) | Scan Execution Policies of the project. (see [Connections](#connections)) |
| <a id="projectsecuritydashboardpath"></a>`securityDashboardPath` | [`String`](#string) | Path to project's security dashboard. |
| <a id="projectsecurityscanners"></a>`securityScanners` | [`SecurityScanners`](#securityscanners) | Information about security analyzers used in the project. |
| <a id="projectsentryerrors"></a>`sentryErrors` | [`SentryErrorCollection`](#sentryerrorcollection) | Paginated collection of Sentry errors on the project. |
@@ -12798,8 +13052,25 @@ Returns [`DastProfile`](#dastprofile).
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="projectdastprofilehasdastprofileschedule"></a>`hasDastProfileSchedule` | [`Boolean`](#boolean) | Filter DAST Profiles by whether or not they have a schedule. Will be ignored if `dast_view_scans` feature flag is disabled. |
| <a id="projectdastprofileid"></a>`id` | [`DastProfileID!`](#dastprofileid) | ID of the DAST Profile. |
+##### `Project.dastProfiles`
+
+DAST Profiles associated with the project.
+
+Returns [`DastProfileConnection`](#dastprofileconnection).
+
+This field returns a [connection](#connections). It accepts the
+four standard [pagination arguments](#connection-pagination-arguments):
+`before: String`, `after: String`, `first: Int`, `last: Int`.
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="projectdastprofileshasdastprofileschedule"></a>`hasDastProfileSchedule` | [`Boolean`](#boolean) | Filter DAST Profiles by whether or not they have a schedule. Will be ignored if `dast_view_scans` feature flag is disabled. |
+
##### `Project.dastSiteProfile`
DAST Site Profile associated with the project.
@@ -12919,6 +13190,8 @@ Returns [`Issue`](#issue).
| <a id="projectissuemilestonewildcardid"></a>`milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. |
| <a id="projectissuemyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. Wildcard values "NONE" and "ANY" are supported. |
| <a id="projectissuenot"></a>`not` | [`NegatedIssueFilterInput`](#negatedissuefilterinput) | Negated arguments. |
+| <a id="projectissuereleasetag"></a>`releaseTag` | [`[String!]`](#string) | Release tag associated with the issue's milestone. |
+| <a id="projectissuereleasetagwildcardid"></a>`releaseTagWildcardId` | [`ReleaseTagWildcardId`](#releasetagwildcardid) | Filter issues by release tag ID wildcard. |
| <a id="projectissuesearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="projectissuesort"></a>`sort` | [`IssueSort`](#issuesort) | Sort issues by this criteria. |
| <a id="projectissuestate"></a>`state` | [`IssuableState`](#issuablestate) | Current state of this issue. |
@@ -12953,6 +13226,8 @@ Returns [`IssueStatusCountsType`](#issuestatuscountstype).
| <a id="projectissuestatuscountsmilestonewildcardid"></a>`milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. |
| <a id="projectissuestatuscountsmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. Wildcard values "NONE" and "ANY" are supported. |
| <a id="projectissuestatuscountsnot"></a>`not` | [`NegatedIssueFilterInput`](#negatedissuefilterinput) | Negated arguments. |
+| <a id="projectissuestatuscountsreleasetag"></a>`releaseTag` | [`[String!]`](#string) | Release tag associated with the issue's milestone. |
+| <a id="projectissuestatuscountsreleasetagwildcardid"></a>`releaseTagWildcardId` | [`ReleaseTagWildcardId`](#releasetagwildcardid) | Filter issues by release tag ID wildcard. |
| <a id="projectissuestatuscountssearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="projectissuestatuscountstypes"></a>`types` | [`[IssueType!]`](#issuetype) | Filter issues by the given issue types. |
| <a id="projectissuestatuscountsupdatedafter"></a>`updatedAfter` | [`Time`](#time) | Issues updated after this date. |
@@ -12992,6 +13267,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="projectissuesmilestonewildcardid"></a>`milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. |
| <a id="projectissuesmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. Wildcard values "NONE" and "ANY" are supported. |
| <a id="projectissuesnot"></a>`not` | [`NegatedIssueFilterInput`](#negatedissuefilterinput) | Negated arguments. |
+| <a id="projectissuesreleasetag"></a>`releaseTag` | [`[String!]`](#string) | Release tag associated with the issue's milestone. |
+| <a id="projectissuesreleasetagwildcardid"></a>`releaseTagWildcardId` | [`ReleaseTagWildcardId`](#releasetagwildcardid) | Filter issues by release tag ID wildcard. |
| <a id="projectissuessearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="projectissuessort"></a>`sort` | [`IssueSort`](#issuesort) | Sort issues by this criteria. |
| <a id="projectissuesstate"></a>`state` | [`IssuableState`](#issuablestate) | Current state of this issue. |
@@ -13118,6 +13395,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="projectmergerequestsassigneeusername"></a>`assigneeUsername` | [`String`](#string) | Username of the assignee. |
| <a id="projectmergerequestsauthorusername"></a>`authorUsername` | [`String`](#string) | Username of the author. |
+| <a id="projectmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="projectmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="projectmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="projectmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="projectmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -13219,6 +13498,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="projectpipelinesref"></a>`ref` | [`String`](#string) | Filter pipelines by the ref they are run for. |
+| <a id="projectpipelinesscope"></a>`scope` | [`PipelineScopeEnum`](#pipelinescopeenum) | Filter pipelines by scope. |
| <a id="projectpipelinessha"></a>`sha` | [`String`](#string) | Filter pipelines by the sha of the commit they are run for. |
| <a id="projectpipelinessource"></a>`source` | [`String`](#string) | Filter pipelines by their source. Will be ignored if `dast_view_scans` feature flag is disabled. |
| <a id="projectpipelinesstatus"></a>`status` | [`PipelineStatusEnum`](#pipelinestatusenum) | Filter pipelines by their status. |
@@ -13308,6 +13588,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="projectrequirementssort"></a>`sort` | [`Sort`](#sort) | List requirements by sort order. |
| <a id="projectrequirementsstate"></a>`state` | [`RequirementState`](#requirementstate) | Filter requirements by state. |
+##### `Project.scanExecutionPolicies`
+
+Scan Execution Policies of the project.
+
+Returns [`ScanExecutionPolicyConnection`](#scanexecutionpolicyconnection).
+
+This field returns a [connection](#connections). It accepts the
+four standard [pagination arguments](#connection-pagination-arguments):
+`before: String`, `after: String`, `first: Int`, `last: Int`.
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="projectscanexecutionpoliciesactionscantypes"></a>`actionScanTypes` | [`[SecurityReportTypeEnum!]`](#securityreporttypeenum) | Filters policies by the action scan type. Only these scan types are supported: `dast`, `secret_detection`, `cluster_image_scanning`, `container_scanning`. |
+
##### `Project.sentryDetailedError`
Detailed version of a Sentry error on the project.
@@ -13402,6 +13698,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="projectvulnerabilitiesclusterid"></a>`clusterId` | [`[ClustersClusterID!]`](#clustersclusterid) | Filter vulnerabilities by `cluster_id`. Vulnerabilities with a `reportType` of `cluster_image_scanning` are only included with this filter. |
| <a id="projectvulnerabilitieshasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have linked issues. |
| <a id="projectvulnerabilitieshasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have been resolved on default branch. |
| <a id="projectvulnerabilitiesimage"></a>`image` | [`[String!]`](#string) | Filter vulnerabilities by location image. When this filter is present, the response only matches entries for a `reportType` that includes `container_scanning`, `cluster_image_scanning`. |
@@ -13733,7 +14030,7 @@ Returns [`[String!]`](#string).
##### `Repository.paginatedTree`
-Paginated tree of the repository. Available only when feature flag `paginated_tree_graphql_query` is enabled. This flag is enabled by default.
+Paginated tree of the repository.
Returns [`TreeConnection`](#treeconnection).
@@ -13782,6 +14079,7 @@ Returns [`Tree`](#tree).
| <a id="repositoryblobname"></a>`name` | [`String`](#string) | Blob name. |
| <a id="repositorybloboid"></a>`oid` | [`String!`](#string) | OID of the blob. |
| <a id="repositoryblobpath"></a>`path` | [`String!`](#string) | Path of the blob. |
+| <a id="repositoryblobpipelineeditorpath"></a>`pipelineEditorPath` | [`String`](#string) | Web path to edit .gitlab-ci.yml file. |
| <a id="repositoryblobplaindata"></a>`plainData` | [`String`](#string) | Blob plain highlighted data. |
| <a id="repositoryblobrawblob"></a>`rawBlob` | [`String`](#string) | Raw content of the blob. |
| <a id="repositoryblobrawpath"></a>`rawPath` | [`String`](#string) | Web path to download the raw blob. |
@@ -13912,7 +14210,7 @@ Counts of requirements by their state.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="runnersetupinstallinstructions"></a>`installInstructions` | [`String!`](#string) | Instructions for installing the runner on the specified architecture. |
-| <a id="runnersetupregisterinstructions"></a>`registerInstructions` | [`String`](#string) | Instructions for registering the runner. |
+| <a id="runnersetupregisterinstructions"></a>`registerInstructions` | [`String`](#string) | Instructions for registering the runner. The actual registration tokens are not included in the commands. Instead, a placeholder `$REGISTRATION_TOKEN` is shown. |
### `SastCiConfiguration`
@@ -14578,6 +14876,18 @@ Representing a to-do entry.
| <a id="todostate"></a>`state` | [`TodoStateEnum!`](#todostateenum) | State of the to-do item. |
| <a id="todotargettype"></a>`targetType` | [`TodoTargetEnum!`](#todotargetenum) | Target type of the to-do item. |
+### `Topic`
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="topicavatarurl"></a>`avatarUrl` | [`String`](#string) | URL to avatar image file of the topic. |
+| <a id="topicdescription"></a>`description` | [`String`](#string) | Description of the topic. |
+| <a id="topicdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
+| <a id="topicid"></a>`id` | [`ID!`](#id) | ID of the topic. |
+| <a id="topicname"></a>`name` | [`String!`](#string) | Name of the topic. |
+
### `Tree`
#### Fields
@@ -14688,6 +14998,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="usercoreassignedmergerequestsauthorusername"></a>`authorUsername` | [`String`](#string) | Username of the author. |
+| <a id="usercoreassignedmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="usercoreassignedmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="usercoreassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="usercoreassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="usercoreassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -14717,6 +15029,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="usercoreauthoredmergerequestsassigneeusername"></a>`assigneeUsername` | [`String`](#string) | Username of the assignee. |
+| <a id="usercoreauthoredmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="usercoreauthoredmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="usercoreauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="usercoreauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="usercoreauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -14764,6 +15078,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="usercorereviewrequestedmergerequestsassigneeusername"></a>`assigneeUsername` | [`String`](#string) | Username of the assignee. |
| <a id="usercorereviewrequestedmergerequestsauthorusername"></a>`authorUsername` | [`String`](#string) | Username of the author. |
+| <a id="usercorereviewrequestedmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="usercorereviewrequestedmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="usercorereviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="usercorereviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="usercorereviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -16158,6 +16474,7 @@ State of a review of a GitLab merge request.
| Value | Description |
| ----- | ----------- |
+| <a id="mergerequestreviewstateattention_requested"></a>`ATTENTION_REQUESTED` | The merge request is attention_requested. |
| <a id="mergerequestreviewstatereviewed"></a>`REVIEWED` | The merge request is reviewed. |
| <a id="mergerequestreviewstateunreviewed"></a>`UNREVIEWED` | The merge request is unreviewed. |
@@ -16402,6 +16719,16 @@ Values for sorting package.
| <a id="pipelineconfigsourceenumunknown_source"></a>`UNKNOWN_SOURCE` | Unknown source. |
| <a id="pipelineconfigsourceenumwebide_source"></a>`WEBIDE_SOURCE` | Webide source. |
+### `PipelineScopeEnum`
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="pipelinescopeenumbranches"></a>`BRANCHES` | Branches. |
+| <a id="pipelinescopeenumfinished"></a>`FINISHED` | Pipeline has completed. |
+| <a id="pipelinescopeenumpending"></a>`PENDING` | Pipeline has not started running yet. |
+| <a id="pipelinescopeenumrunning"></a>`RUNNING` | Pipeline is running. |
+| <a id="pipelinescopeenumtags"></a>`TAGS` | Tags. |
+
### `PipelineStatusEnum`
| Value | Description |
@@ -16462,6 +16789,15 @@ Values for sorting releases.
| <a id="releasesortreleased_at_asc"></a>`RELEASED_AT_ASC` | Released at by ascending order. |
| <a id="releasesortreleased_at_desc"></a>`RELEASED_AT_DESC` | Released at by descending order. |
+### `ReleaseTagWildcardId`
+
+Release tag ID wildcard values.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="releasetagwildcardidany"></a>`ANY` | Release tag is assigned. |
+| <a id="releasetagwildcardidnone"></a>`NONE` | No release tag is assigned. |
+
### `RequirementState`
State of a requirement.
@@ -16511,6 +16847,7 @@ Size of UI component in SAST configuration page.
| <a id="securityreporttypeenumdast"></a>`DAST` | DAST scan report. |
| <a id="securityreporttypeenumdependency_scanning"></a>`DEPENDENCY_SCANNING` | DEPENDENCY SCANNING scan report. |
| <a id="securityreporttypeenumsast"></a>`SAST` | SAST scan report. |
+| <a id="securityreporttypeenumsast_iac"></a>`SAST_IAC` | SAST IAC scan report. |
| <a id="securityreporttypeenumsecret_detection"></a>`SECRET_DETECTION` | SECRET DETECTION scan report. |
### `SecurityScannerType`
@@ -16526,6 +16863,7 @@ The type of the security scanner.
| <a id="securityscannertypedast"></a>`DAST` | DAST scanner. |
| <a id="securityscannertypedependency_scanning"></a>`DEPENDENCY_SCANNING` | Dependency Scanning scanner. |
| <a id="securityscannertypesast"></a>`SAST` | SAST scanner. |
+| <a id="securityscannertypesast_iac"></a>`SAST_IAC` | Sast Iac scanner. |
| <a id="securityscannertypesecret_detection"></a>`SECRET_DETECTION` | Secret Detection scanner. |
### `SentryErrorStatus`
@@ -16572,12 +16910,14 @@ State of a Sentry error.
| <a id="servicetypeprometheus_service"></a>`PROMETHEUS_SERVICE` | PrometheusService type. |
| <a id="servicetypepushover_service"></a>`PUSHOVER_SERVICE` | PushoverService type. |
| <a id="servicetyperedmine_service"></a>`REDMINE_SERVICE` | RedmineService type. |
+| <a id="servicetypeshimo_service"></a>`SHIMO_SERVICE` | ShimoService type. |
| <a id="servicetypeslack_service"></a>`SLACK_SERVICE` | SlackService type. |
| <a id="servicetypeslack_slash_commands_service"></a>`SLACK_SLASH_COMMANDS_SERVICE` | SlackSlashCommandsService type. |
| <a id="servicetypeteamcity_service"></a>`TEAMCITY_SERVICE` | TeamcityService type. |
| <a id="servicetypeunify_circuit_service"></a>`UNIFY_CIRCUIT_SERVICE` | UnifyCircuitService type. |
| <a id="servicetypewebex_teams_service"></a>`WEBEX_TEAMS_SERVICE` | WebexTeamsService type. |
| <a id="servicetypeyoutrack_service"></a>`YOUTRACK_SERVICE` | YoutrackService type. |
+| <a id="servicetypezentao_service"></a>`ZENTAO_SERVICE` | ZentaoService type. |
### `SharedRunnersSetting`
@@ -16889,6 +17229,12 @@ A `AnalyticsDevopsAdoptionEnabledNamespaceID` is a global ID. It is encoded as a
An example `AnalyticsDevopsAdoptionEnabledNamespaceID` is: `"gid://gitlab/Analytics::DevopsAdoption::EnabledNamespace/1"`.
+### `AppSecFuzzingCoverageCorpusID`
+
+A `AppSecFuzzingCoverageCorpusID` is a global ID. It is encoded as a string.
+
+An example `AppSecFuzzingCoverageCorpusID` is: `"gid://gitlab/AppSec::Fuzzing::Coverage::Corpus/1"`.
+
### `AuditEventsExternalAuditEventDestinationID`
A `AuditEventsExternalAuditEventDestinationID` is a global ID. It is encoded as a string.
@@ -17033,6 +17379,12 @@ An example `DastSiteValidationID` is: `"gid://gitlab/DastSiteValidation/1"`.
Date represented in ISO 8601.
+### `DependencyProxyManifestID`
+
+A `DependencyProxyManifestID` is a global ID. It is encoded as a string.
+
+An example `DependencyProxyManifestID` is: `"gid://gitlab/DependencyProxy::Manifest/1"`.
+
### `DesignManagementDesignAtVersionID`
A `DesignManagementDesignAtVersionID` is a global ID. It is encoded as a string.
@@ -17632,6 +17984,7 @@ Represents metadata associated with a Package file.
Implementations:
- [`ConanFileMetadata`](#conanfilemetadata)
+- [`HelmFileMetadata`](#helmfilemetadata)
##### Fields
@@ -17733,6 +18086,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="userassignedmergerequestsauthorusername"></a>`authorUsername` | [`String`](#string) | Username of the author. |
+| <a id="userassignedmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="userassignedmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="userassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="userassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="userassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -17762,6 +18117,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="userauthoredmergerequestsassigneeusername"></a>`assigneeUsername` | [`String`](#string) | Username of the assignee. |
+| <a id="userauthoredmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="userauthoredmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="userauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="userauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="userauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -17809,6 +18166,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="userreviewrequestedmergerequestsassigneeusername"></a>`assigneeUsername` | [`String`](#string) | Username of the assignee. |
| <a id="userreviewrequestedmergerequestsauthorusername"></a>`authorUsername` | [`String`](#string) | Username of the author. |
+| <a id="userreviewrequestedmergerequestscreatedafter"></a>`createdAfter` | [`Time`](#time) | Merge requests created after this timestamp. |
+| <a id="userreviewrequestedmergerequestscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Merge requests created before this timestamp. |
| <a id="userreviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="userreviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="userreviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after this date. |
@@ -18161,6 +18520,7 @@ Represents an escalation rule.
| <a id="negatedissuefilterinputmilestonetitle"></a>`milestoneTitle` | [`[String!]`](#string) | Milestone not applied to this issue. |
| <a id="negatedissuefilterinputmilestonewildcardid"></a>`milestoneWildcardId` | [`NegatedMilestoneWildcardId`](#negatedmilestonewildcardid) | Filter by negated milestone wildcard values. |
| <a id="negatedissuefilterinputmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
+| <a id="negatedissuefilterinputreleasetag"></a>`releaseTag` | [`[String!]`](#string) | Release tag not associated with the issue's milestone. Ignored when parent is a group. |
| <a id="negatedissuefilterinputtypes"></a>`types` | [`[IssueType!]`](#issuetype) | Filters out issues by the given issue types. |
| <a id="negatedissuefilterinputweight"></a>`weight` | [`String`](#string) | Weight not applied to the issue. |
diff --git a/doc/api/group_clusters.md b/doc/api/group_clusters.md
index 81ca45c4531..eaecc74a96e 100644
--- a/doc/api/group_clusters.md
+++ b/doc/api/group_clusters.md
@@ -4,9 +4,13 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Group clusters API **(FREE)**
+# Group clusters API (certificate-based) (DEPRECATED) **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30213) in GitLab 12.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30213) in GitLab 12.1.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
Similarly to [project-level](../user/project/clusters/index.md) and
[instance-level](../user/instance/clusters/index.md) Kubernetes clusters,
diff --git a/doc/api/group_repository_storage_moves.md b/doc/api/group_repository_storage_moves.md
index 9d4120ec355..1d6e08b5840 100644
--- a/doc/api/group_repository_storage_moves.md
+++ b/doc/api/group_repository_storage_moves.md
@@ -11,7 +11,7 @@ type: reference
Group repositories can be moved between storages. This API can help you when
[migrating to Gitaly Cluster](../administration/gitaly/index.md#migrating-to-gitaly-cluster), for
-example, or to migrate a [group wiki](../user/project/wiki/index.md#group-wikis).
+example, or to migrate a [group wiki](../user/project/wiki/group.md).
As group repository storage moves are processed, they transition through different states. Values
of `state` are:
diff --git a/doc/api/group_wikis.md b/doc/api/group_wikis.md
index 17337934a92..4af907bd387 100644
--- a/doc/api/group_wikis.md
+++ b/doc/api/group_wikis.md
@@ -9,7 +9,7 @@ type: reference, api
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212199) in GitLab 13.5.
-The [group wikis](../user/project/wiki/index.md#group-wikis) API is available only in APIv4.
+The [group wikis](../user/project/wiki/group.md) API is available only in APIv4.
An API for [project wikis](wikis.md) is also available.
## List wiki pages
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 7efecfc2c9c..5faa63585c1 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -100,13 +100,15 @@ GET /groups?statistics=true
"parent_id": null,
"created_at": "2020-01-15T12:36:29.590Z",
"statistics": {
- "storage_size" : 363,
- "repository_size" : 33,
- "wiki_size" : 100,
- "lfs_objects_size" : 123,
- "job_artifacts_size" : 57,
+ "storage_size": 363,
+ "repository_size": 33,
+ "wiki_size": 100,
+ "lfs_objects_size": 123,
+ "job_artifacts_size": 57,
+ "pipeline_artifacts_size": 0,
"packages_size": 0,
- "snippets_size" : 50
+ "snippets_size": 50,
+ "uploads_size": 0
}
}
]
diff --git a/doc/api/import.md b/doc/api/import.md
index d556c8af971..18c0eb04fff 100644
--- a/doc/api/import.md
+++ b/doc/api/import.md
@@ -83,3 +83,8 @@ curl --request POST \
"bitbucket_server_repo": "my-repo"
}'
```
+
+## Automate group and project import **(PREMIUM)**
+
+For information on automating user, group, and project import API calls, see
+[Automate group and project import](../user/project/import/index.md#automate-group-and-project-import).
diff --git a/doc/api/instance_clusters.md b/doc/api/instance_clusters.md
index 58f88b26bc4..85046388275 100644
--- a/doc/api/instance_clusters.md
+++ b/doc/api/instance_clusters.md
@@ -4,9 +4,13 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Instance clusters API **(FREE SELF)**
+# Instance clusters API (certificate-based) (DEPRECATED) **(FREE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36001) in GitLab 13.2.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36001) in GitLab 13.2.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
With [instance-level Kubernetes clusters](../user/instance/clusters/index.md),
you can connect a Kubernetes cluster to the GitLab instance and use the same cluster across all of
diff --git a/doc/api/integrations.md b/doc/api/integrations.md
index 3c649e8d044..8f57e915b4e 100644
--- a/doc/api/integrations.md
+++ b/doc/api/integrations.md
@@ -94,9 +94,9 @@ Parameters:
| `restrict_to_branch` | string | false | Comma-separated list of branches to be are automatically inspected. Leave blank to include all branches. |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete Asana integration
+### Disable Asana integration
-Delete Asana integration for a project.
+Disable the Asana integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/asana
@@ -130,9 +130,9 @@ Parameters:
| `subdomain` | string | false | The subdomain setting |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete Assembla integration
+### Disable Assembla integration
-Delete Assembla integration for a project.
+Disable the Assembla integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/assembla
@@ -170,9 +170,9 @@ Parameters:
| `password` | string | true | Password of the user |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete Atlassian Bamboo CI integration
+### Disable Atlassian Bamboo CI integration
-Delete Atlassian Bamboo CI integration for a project.
+Disable the Atlassian Bamboo CI integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/bamboo
@@ -209,9 +209,9 @@ Parameters:
| `title` | string | false | Title |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete Bugzilla integration
+### Disable Bugzilla integration
-Delete Bugzilla integration for a project.
+Disable the Bugzilla integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/bugzilla
@@ -246,9 +246,9 @@ Parameters:
| `enable_ssl_verification` | boolean | false | DEPRECATED: This parameter has no effect since SSL verification is always enabled |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete Buildkite integration
+### Disable Buildkite integration
-Delete Buildkite integration for a project.
+Disable the Buildkite integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/buildkite
@@ -284,9 +284,9 @@ Parameters:
| `room` | string | false | Campfire room. The last part of the URL when you're in a room. |
| `push_events` | boolean | false | Enable notifications for push events. |
-### Delete Campfire integration
+### Disable Campfire integration
-Delete Campfire integration for a project.
+Disable the Campfire integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/campfire
@@ -322,9 +322,9 @@ Parameters:
| `datadog_service` | string | false | Name of this GitLab instance that all data will be tagged with |
| `datadog_env` | string | false | The environment tag that traces will be tagged with |
-### Delete Datadog integration
+### Disable Datadog integration
-Delete Datadog integration for a project.
+Disable the Datadog integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/datadog
@@ -367,9 +367,9 @@ Parameters:
| `pipeline_events` | boolean | false | Enable notifications for pipeline events |
| `wiki_page_events` | boolean | false | Enable notifications for wiki page events |
-### Delete Unify Circuit integration
+### Disable Unify Circuit integration
-Delete Unify Circuit integration for a project.
+Disable the Unify Circuit integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/unify-circuit
@@ -412,9 +412,9 @@ Parameters:
| `pipeline_events` | boolean | false | Enable notifications for pipeline events |
| `wiki_page_events` | boolean | false | Enable notifications for wiki page events |
-### Delete Webex Teams integration
+### Disable Webex Teams integration
-Delete Webex Teams integration for a project.
+Disable the Webex Teams integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/webex-teams
@@ -451,9 +451,9 @@ Parameters:
| `title` | string | false | Title |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete Custom Issue Tracker integration
+### Disable Custom Issue Tracker integration
-Delete Custom Issue Tracker integration for a project.
+Disable the Custom Issue Tracker integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/custom-issue-tracker
@@ -485,9 +485,9 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `webhook` | string | true | Discord webhook. For example, `https://discord.com/api/webhooks/…` |
-### Delete Discord integration
+### Disable Discord integration
-Delete Discord integration for a project.
+Disable the Discord integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/discord
@@ -524,9 +524,9 @@ Parameters:
| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
| `tag_push_events` | boolean | false | Enable notifications for tag push events |
-### Delete Drone CI integration
+### Disable Drone CI integration
-Delete Drone CI integration for a project.
+Disable the Drone CI integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/drone-ci
@@ -563,9 +563,9 @@ Parameters:
| `tag_push_events` | boolean | false | Enable notifications for tag push events |
| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected". Notifications are always fired for tag pushes. The default value is "all" |
-### Delete Emails on Push integration
+### Disable Emails on Push integration
-Delete Emails on Push integration for a project.
+Disable the Emails on Push integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/emails-on-push
@@ -599,9 +599,9 @@ Parameters:
| `project_url` | string | true | The URL to the project in EWM |
| `issues_url` | string | true | The URL to view an issue in EWM. Must contain `:id` |
-### Delete EWM integration
+### Disable EWM integration
-Delete EWM integration for a project.
+Disable the EWM integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/ewm
@@ -635,9 +635,9 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `confluence_url` | string | true | The URL of the Confluence Cloud Workspace hosted on atlassian.net. |
-### Delete Confluence integration
+### Disable Confluence integration
-Delete Confluence integration for a project.
+Disable the Confluence integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/confluence
@@ -669,9 +669,9 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `external_wiki_url` | string | true | The URL of the external wiki |
-### Delete External wiki integration
+### Disable External wiki integration
-Delete External wiki integration for a project.
+Disable the External wiki integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/external-wiki
@@ -706,9 +706,9 @@ Parameters:
| `token` | string | true | Flowdock Git source token |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete Flowdock integration
+### Disable Flowdock integration
-Delete Flowdock integration for a project.
+Disable the Flowdock integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/flowdock
@@ -740,11 +740,11 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `token` | string | true | GitHub API token with `repo:status` OAuth scope |
| `repository_url` | string | true | GitHub repository URL |
-| `static_context` | boolean | false | Append instance name instead of branch to [status check name](../user/project/integrations/github.md#static--dynamic-status-check-names) |
+| `static_context` | boolean | false | Append instance name instead of branch to [status check name](../user/project/integrations/github.md#static-or-dynamic-status-check-names) |
-### Delete GitHub integration
+### Disable GitHub integration
-Delete GitHub integration for a project.
+Disable the GitHub integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/github
@@ -788,9 +788,9 @@ Parameters:
| `pipeline_events` | boolean | false | Enable notifications for pipeline events |
| `wiki_page_events` | boolean | false | Enable notifications for wiki page events |
-### Delete Hangouts Chat integration
+### Disable Hangouts Chat integration
-Delete Hangouts Chat integration for a project.
+Disable the Hangouts Chat integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/hangouts-chat
@@ -829,9 +829,9 @@ Parameters:
| `colorize_messages` | boolean | false | Colorize messages |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete Irker (IRC gateway) integration
+### Disable Irker (IRC gateway) integration
-Delete Irker (IRC gateway) integration for a project.
+Disable the Irker (IRC gateway) integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/irker
@@ -880,9 +880,9 @@ Parameters:
| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
| `comment_on_event_enabled` | boolean | false | Enable comments inside Jira issues on each GitLab event (commit / merge request) |
-### Delete Jira integration
+### Disable Jira integration
-Remove all previously Jira integrations from a project.
+Disable the Jira integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/jira
@@ -939,9 +939,9 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `token` | string | yes | The Slack token |
-### Delete Slack Slash Command integration
+### Disable Slack Slash Command integration
-Delete Slack Slash Command integration for a project.
+Disable the Slack Slash Command integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/slack-slash-commands
@@ -974,9 +974,9 @@ Parameters:
| `token` | string | yes | The Mattermost token |
| `username` | string | no | The username to use to post the message |
-### Delete Mattermost Slash Command integration
+### Disable Mattermost Slash Command integration
-Delete Mattermost Slash Command integration for a project.
+Disable the Mattermost Slash Command integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/mattermost-slash-commands
@@ -1005,9 +1005,9 @@ Parameters:
| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
| `tag_push_events` | boolean | false | Enable notifications for tag push events |
-### Delete Packagist integration
+### Disable Packagist integration
-Delete Packagist integration for a project.
+Disable the Packagist integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/packagist
@@ -1044,9 +1044,9 @@ Parameters:
| `notify_only_default_branch` | boolean | no | Send notifications only for the default branch ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28271)) |
| `pipeline_events` | boolean | false | Enable notifications for pipeline events |
-### Delete Pipeline-Emails integration
+### Disable Pipeline-Emails integration
-Delete Pipeline-Emails integration for a project.
+Disable the Pipeline-Emails integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/pipelines-email
@@ -1082,9 +1082,9 @@ Parameters:
| `restrict_to_branch` | boolean | false | Comma-separated list of branches to automatically inspect. Leave blank to include all branches. |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete Pivotal Tracker integration
+### Disable Pivotal Tracker integration
-Delete Pivotal Tracker integration for a project.
+Disable the Pivotal Tracker integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/pivotaltracker
@@ -1118,9 +1118,9 @@ Parameters:
| `google_iap_audience_client_id` | string | false | Client ID of the IAP secured resource (looks like IAP_CLIENT_ID.apps.googleusercontent.com) |
| `google_iap_service_account_json` | string | false | `credentials.json` file for your service account, like { "type": "service_account", "project_id": ... } |
-### Delete Prometheus integration
+### Disable Prometheus integration
-Delete Prometheus integration for a project.
+Disable the Prometheus integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/prometheus
@@ -1157,9 +1157,9 @@ Parameters:
| `sound` | string | false | The sound of the notification |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete Pushover integration
+### Disable Pushover integration
-Delete Pushover integration for a project.
+Disable the Pushover integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/pushover
@@ -1195,9 +1195,9 @@ Parameters:
| `description` | string | false | Description |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete Redmine integration
+### Disable Redmine integration
-Delete Redmine integration for a project.
+Disable the Redmine integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/redmine
@@ -1256,9 +1256,9 @@ Parameters:
| `wiki_page_channel` | string | false | The name of the channel to receive wiki page events notifications |
| `wiki_page_events` | boolean | false | Enable notifications for wiki page events |
-### Delete Slack integration
+### Disable Slack integration
-Delete Slack integration for a project.
+Disable the Slack integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/slack
@@ -1302,9 +1302,9 @@ Parameters:
| `pipeline_events` | boolean | false | Enable notifications for pipeline events |
| `wiki_page_events` | boolean | false | Enable notifications for wiki page events |
-### Delete Microsoft Teams integration
+### Disable Microsoft Teams integration
-Delete Microsoft Teams integration for a project.
+Disable the Microsoft Teams integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/microsoft-teams
@@ -1359,9 +1359,9 @@ Parameters:
| `pipeline_channel` | string | false | The name of the channel to receive pipeline events notifications |
| `wiki_page_channel` | string | false | The name of the channel to receive wiki page events notifications |
-### Delete Mattermost notifications integration
+### Disable Mattermost notifications integration
-Delete Mattermost notifications integration for a project.
+Disable the Mattermost notifications integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/mattermost
@@ -1399,9 +1399,9 @@ Parameters:
| `password` | string | true | The password of the user |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete JetBrains TeamCity CI integration
+### Disable JetBrains TeamCity CI integration
-Delete JetBrains TeamCity CI integration for a project.
+Disable the JetBrains TeamCity CI integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/teamcity
@@ -1439,9 +1439,9 @@ Parameters:
| `merge_requests_events` | boolean | false | Enable notifications for merge request events. |
| `tag_push_events` | boolean | false | Enable notifications for tag push events. |
-### Delete Jenkins CI integration
+### Disable Jenkins CI integration
-Delete Jenkins CI integration for a project.
+Disable the Jenkins CI integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/jenkins
@@ -1476,9 +1476,9 @@ Parameters:
- `multiproject_enabled` (optional) - Multi-project mode is configured in Jenkins GitLab Hook plugin
- `pass_unstable` (optional) - Unstable builds are treated as passing
-### Delete Jenkins CI (Deprecated) integration
+### Disable Jenkins CI (Deprecated) integration
-Delete Jenkins CI (Deprecated) integration for a project.
+Disable the Jenkins CI (Deprecated) integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/jenkins-deprecated
@@ -1512,9 +1512,9 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `mock_service_url` | string | true | `http://localhost:4004` |
-### Delete MockCI integration
+### Disable MockCI integration
-Delete MockCI integration for a project.
+Disable the MockCI integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/mock-ci
@@ -1549,9 +1549,9 @@ Parameters:
| `description` | string | false | Description |
| `push_events` | boolean | false | Enable notifications for push events |
-### Delete YouTrack integration
+### Disable YouTrack integration
-Delete YouTrack integration for a project.
+Disable the YouTrack integration for a project. Integration settings are preserved.
```plaintext
DELETE /projects/:id/integrations/youtrack
diff --git a/doc/api/invitations.md b/doc/api/invitations.md
index 26e85a9d9f3..80a05f8ea0d 100644
--- a/doc/api/invitations.md
+++ b/doc/api/invitations.md
@@ -43,6 +43,8 @@ POST /projects/:id/invitations
| `expires_at` | string | no | A date string in the format YEAR-MONTH-DAY |
| `invite_source` | string | no | The source of the invitation that starts the member creation process. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/327120). |
| `areas_of_focus` | string | no | Areas the inviter wants the member to focus upon. |
+| `tasks_to_be_done` | array of strings | no | Tasks the inviter wants the member to focus on. The tasks are added as issues to a specified project. The possible values are: `ci`, `code` and `issues`. If specified, requires `tasks_project_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `invite_members_for_task`. Disabled by default. |
+| `tasks_project_id` | integer | no | The project ID in which to create the task issues. If specified, requires `tasks_to_be_done`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `invite_members_for_task`. Disabled by default. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index ac8b756beac..2a07e2d92c5 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -294,7 +294,7 @@ Example of response
]
```
-In GitLab 13.3 and later, this endpoint [returns data for any pipeline](pipelines.md#single-pipeline-requests)
+In GitLab 13.3 and later, this endpoint [returns data for any pipeline](pipelines.md#get-a-single-pipeline)
including [child pipelines](../ci/pipelines/parent_child_pipelines.md).
In GitLab 13.5 and later, this endpoint does not return retried jobs in the response
@@ -400,11 +400,12 @@ Retrieve the job that generated a job token.
GET /job
```
-Examples
+Examples (must run as part of the [`script`](../ci/yaml/index.md#script) section of a [CI/CD job](../ci/jobs/index.md)):
```shell
-curl --header "JOB-TOKEN: <your_job_token>" "https://gitlab.example.com/api/v4/job"
-curl "https://gitlab.example.com/api/v4/job?job_token=<your_job_token>"
+curl --header "Authorization: Bearer $CI_JOB_TOKEN" "${CI_API_V4_URL}/job"
+curl --header "JOB-TOKEN: $CI_JOB_TOKEN" "${CI_API_V4_URL}/job"
+curl "${CI_API_V4_URL}/job?job_token=$CI_JOB_TOKEN"
```
Example of response
diff --git a/doc/api/lint.md b/doc/api/lint.md
index 9f95b9a94ae..e5b5e0e2be8 100644
--- a/doc/api/lint.md
+++ b/doc/api/lint.md
@@ -30,6 +30,7 @@ POST /ci/lint
| ---------- | ------- | -------- | -------- |
| `content` | string | yes | The CI/CD configuration content. |
| `include_merged_yaml` | boolean | no | If the [expanded CI/CD configuration](#yaml-expansion) should be included in the response. |
+| `include_jobs` | boolean | no | If the list of jobs should be included in the response. This is false by default. |
```shell
curl --header "Content-Type: application/json" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/ci/lint" --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
@@ -91,7 +92,7 @@ work for CI configuration added with [`include: local`](../ci/yaml/index.md#incl
or with [`extends:`](../ci/yaml/index.md#extends).
Example contents of a `.gitlab-ci.yml` passed to the CI Lint API with
-`include_merged_yaml` set as true:
+`include_merged_yaml` and `include_jobs` set as true:
```yaml
include:
@@ -118,7 +119,39 @@ Example response:
{
"status": "valid",
"errors": [],
- "merged_yaml": "---\n:another_test:\n :stage: test\n :script: echo 2\n:test:\n :stage: test\n :script: echo 1\n"
+ "merged_yaml": "---\n:another_test:\n :stage: test\n :script: echo 2\n:test:\n :stage: test\n :script: echo 1\n",
+ "jobs": [
+ {
+ "name":"test",
+ "stage":"test",
+ "before_script":[],
+ "script":["echo 1"],
+ "after_script":[],
+ "tag_list":[],
+ "environment":null,
+ "when":"on_success",
+ "allow_failure":false,
+ "only":{
+ "refs":["branches","tags"]
+ },
+ "except":null
+ },
+ {
+ "name":"another_test",
+ "stage":"test",
+ "before_script":[],
+ "script":["echo 2"],
+ "after_script":[],
+ "tag_list":[],
+ "environment":null,
+ "when":"on_success",
+ "allow_failure":false,
+ "only":{
+ "refs":["branches","tags"]
+ },
+ "except":null
+ }
+ ]
}
```
@@ -137,6 +170,7 @@ POST /projects/:id/ci/lint
| ---------- | ------- | -------- | -------- |
| `content` | string | yes | The CI/CD configuration content. |
| `dry_run` | boolean | no | Run [pipeline creation simulation](../ci/lint.md#pipeline-simulation), or only do static check. This is false by default. |
+| `include_jobs` | boolean | no | If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. This is false by default. |
Example request:
@@ -185,6 +219,7 @@ GET /projects/:id/ci/lint
| Attribute | Type | Required | Description |
| ---------- | ------- | -------- | -------- |
| `dry_run` | boolean | no | Run pipeline creation simulation, or only do static check. |
+| `include_jobs` | boolean | no | If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. This is false by default. |
Example request:
diff --git a/doc/api/members.md b/doc/api/members.md
index 44e58f49d3b..ce276487f21 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -422,6 +422,8 @@ POST /projects/:id/members
| `expires_at` | string | no | A date string in the format `YEAR-MONTH-DAY` |
| `invite_source` | string | no | The source of the invitation that starts the member creation process. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/327120). |
| `areas_of_focus` | string | no | Areas the inviter wants the member to focus upon. |
+| `tasks_to_be_done` | array of strings | no | Tasks the inviter wants the member to focus on. The tasks are added as issues to a specified project. The possible values are: `ci`, `code` and `issues`. If specified, requires `tasks_project_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `invite_members_for_task`. Disabled by default. |
+| `tasks_project_id` | integer | no | The project ID in which to create the task issues. If specified, requires `tasks_to_be_done`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `invite_members_for_task`. Disabled by default. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
@@ -587,6 +589,43 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/members/:user_id"
```
+## Approve a member for a group
+
+Approves a pending user for a group and its subgroups and projects.
+
+```plaintext
+PUT /groups/:id/members/:user_id/approve
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the root group](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `user_id` | integer | yes | The user ID of the member |
+
+Example request:
+
+```shell
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/approve"
+```
+
+## Approve all pending members for a group
+
+Approves all pending users for a group and its subgroups and projects.
+
+```plaintext
+POST /groups/:id/members/approve_all
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the root group](index.md#namespaced-path-encoding) owned by the authenticated user |
+
+Example request:
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/approve_all"
+```
+
## Give a group access to a project
See [share project with group](projects.md#share-project-with-group)
diff --git a/doc/api/packages/debian_group_distributions.md b/doc/api/packages/debian_group_distributions.md
index c5d2effcf44..0a1b7b4571e 100644
--- a/doc/api/packages/debian_group_distributions.md
+++ b/doc/api/packages/debian_group_distributions.md
@@ -107,6 +107,43 @@ Example response:
}
```
+## Single Debian group distribution key
+
+Gets a single Debian group distribution key.
+
+```plaintext
+GET /groups/:id/debian_distributions/:codename/key.asc
+```
+
+| Attribute | Type | Required | Description |
+| ---------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](../index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `codename` | integer | yes | The `codename` of a distribution. |
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/debian_distributions/unstable/key.asc"
+```
+
+Example response:
+
+```plaintext
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Comment: Alice's OpenPGP certificate
+Comment: https://www.ietf.org/id/draft-bre-openpgp-samples-01.html
+
+mDMEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U
+b7O1u120JkFsaWNlIExvdmVsYWNlIDxhbGljZUBvcGVucGdwLmV4YW1wbGU+iJAE
+ExYIADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQTrhbtfozp14V6UTmPy
+MVUMT0fjjgUCXaWfOgAKCRDyMVUMT0fjjukrAPoDnHBSogOmsHOsd9qGsiZpgRnO
+dypvbm+QtXZqth9rvwD9HcDC0tC+PHAsO7OTh1S1TC9RiJsvawAfCPaQZoed8gK4
+OARcRwTpEgorBgEEAZdVAQUBAQdAQv8GIa2rSTzgqbXCpDDYMiKRVitCsy203x3s
+E9+eviIDAQgHiHgEGBYIACAWIQTrhbtfozp14V6UTmPyMVUMT0fjjgUCXEcE6QIb
+DAAKCRDyMVUMT0fjjlnQAQDFHUs6TIcxrNTtEZFjUFm1M0PJ1Dng/cDW4xN80fsn
+0QEA22Kr7VkCjeAEC08VSTeV+QFsmz55/lntWkwYWhmvOgE=
+=iIGO
+-----END PGP PUBLIC KEY BLOCK-----
+```
+
## Create a Debian group distribution
Creates a Debian group distribution.
diff --git a/doc/api/packages/debian_project_distributions.md b/doc/api/packages/debian_project_distributions.md
index bedf3f1f27a..533742642fd 100644
--- a/doc/api/packages/debian_project_distributions.md
+++ b/doc/api/packages/debian_project_distributions.md
@@ -106,6 +106,43 @@ Example response:
}
```
+## Single Debian project distribution key
+
+Gets a single Debian project distribution key.
+
+```plaintext
+GET /projects/:id/debian_distributions/:codename/key.asc
+```
+
+| Attribute | Type | Required | Description |
+| ---------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `codename` | integer | yes | The `codename` of a distribution. |
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/debian_distributions/unstable/key.asc"
+```
+
+Example response:
+
+```plaintext
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Comment: Alice's OpenPGP certificate
+Comment: https://www.ietf.org/id/draft-bre-openpgp-samples-01.html
+
+mDMEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U
+b7O1u120JkFsaWNlIExvdmVsYWNlIDxhbGljZUBvcGVucGdwLmV4YW1wbGU+iJAE
+ExYIADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQTrhbtfozp14V6UTmPy
+MVUMT0fjjgUCXaWfOgAKCRDyMVUMT0fjjukrAPoDnHBSogOmsHOsd9qGsiZpgRnO
+dypvbm+QtXZqth9rvwD9HcDC0tC+PHAsO7OTh1S1TC9RiJsvawAfCPaQZoed8gK4
+OARcRwTpEgorBgEEAZdVAQUBAQdAQv8GIa2rSTzgqbXCpDDYMiKRVitCsy203x3s
+E9+eviIDAQgHiHgEGBYIACAWIQTrhbtfozp14V6UTmPyMVUMT0fjjgUCXEcE6QIb
+DAAKCRDyMVUMT0fjjlnQAQDFHUs6TIcxrNTtEZFjUFm1M0PJ1Dng/cDW4xN80fsn
+0QEA22Kr7VkCjeAEC08VSTeV+QFsmz55/lntWkwYWhmvOgE=
+=iIGO
+-----END PGP PUBLIC KEY BLOCK-----
+```
+
## Create a Debian project distribution
Creates a Debian project distribution.
diff --git a/doc/api/packages/maven.md b/doc/api/packages/maven.md
index b4b3d579ffb..b046b0dc411 100644
--- a/doc/api/packages/maven.md
+++ b/doc/api/packages/maven.md
@@ -36,13 +36,13 @@ GET packages/maven/*path/:file_name
| `file_name` | string | yes | The name of the Maven package file. |
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.jar"
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/maven/foo/bar/mypkg/1.0-SNAPSHOT/mypkg-1.0-SNAPSHOT.jar"
```
To write the output to file:
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.jar" >> mypkg-1.0-SNAPSHOT.jar
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/maven/foo/bar/mypkg/1.0-SNAPSHOT/mypkg-1.0-SNAPSHOT.jar" >> mypkg-1.0-SNAPSHOT.jar
```
This writes the downloaded file to `mypkg-1.0-SNAPSHOT.jar` in the current directory.
@@ -63,13 +63,13 @@ GET groups/:id/-/packages/maven/*path/:file_name
| `file_name` | string | yes | The name of the Maven package file. |
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/groups/1/-/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.jar"
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/groups/1/-/packages/maven/foo/bar/mypkg/1.0-SNAPSHOT/mypkg-1.0-SNAPSHOT.jar"
```
To write the output to file:
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/groups/1/-/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.jar" >> mypkg-1.0-SNAPSHOT.jar
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/groups/1/-/packages/maven/foo/bar/mypkg/1.0-SNAPSHOT/mypkg-1.0-SNAPSHOT.jar" >> mypkg-1.0-SNAPSHOT.jar
```
This writes the downloaded file to `mypkg-1.0-SNAPSHOT.jar` in the current directory.
@@ -90,13 +90,13 @@ GET projects/:id/packages/maven/*path/:file_name
| `file_name` | string | yes | The name of the Maven package file. |
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.jar"
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/maven/foo/bar/mypkg/1.0-SNAPSHOT/mypkg-1.0-SNAPSHOT.jar"
```
To write the output to file:
```shell
-curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.jar" >> mypkg-1.0-SNAPSHOT.jar
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/maven/foo/bar/mypkg/1.0-SNAPSHOT/mypkg-1.0-SNAPSHOT.jar" >> mypkg-1.0-SNAPSHOT.jar
```
This writes the downloaded file to `mypkg-1.0-SNAPSHOT.jar` in the current directory.
@@ -120,5 +120,5 @@ PUT projects/:id/packages/maven/*path/:file_name
curl --request PUT \
--upload-file path/to/mypkg-1.0-SNAPSHOT.pom \
--header "Private-Token: <personal_access_token>" \
- "https://gitlab.example.com/api/v4/projects/1/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.pom"
+ "https://gitlab.example.com/api/v4/projects/1/packages/maven/foo/bar/mypkg/1.0-SNAPSHOT/mypkg-1.0-SNAPSHOT.pom"
```
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index f3c30a414ea..4dddbbc7826 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -6,14 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Pipelines API **(FREE)**
-## Single Pipeline Requests
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36494) in GitLab 13.3.
-
-Endpoints that request information about a single pipeline return data for any pipeline.
-Before 13.3, requests for [child pipelines](../ci/pipelines/parent_child_pipelines.md) returned
-a 404 error.
-
## Pipelines pagination
By default, `GET` requests return 20 results at a time because the API results
@@ -23,6 +15,9 @@ Read more on [pagination](index.md#pagination).
## List project pipelines
+List pipelines in a project. Child pipelines are not included in the results,
+but you can [get child pipeline](pipelines.md#get-a-single-pipeline) individually.
+
```plaintext
GET /projects/:id/pipelines
```
@@ -79,6 +74,11 @@ Example of response
## Get a single pipeline
+Get one pipeline from a project.
+
+You can also get a single [child pipeline](../ci/pipelines/parent_child_pipelines.md).
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36494) in GitLab 13.3.
+
```plaintext
GET /projects/:id/pipelines/:pipeline_id
```
diff --git a/doc/api/project_clusters.md b/doc/api/project_clusters.md
index bb05e4788d0..d2a574b5cbd 100644
--- a/doc/api/project_clusters.md
+++ b/doc/api/project_clusters.md
@@ -4,9 +4,13 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Project clusters API **(FREE)**
+# Project clusters API (certificate-based) (DEPRECATED) **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23922) in GitLab 11.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23922) in GitLab 11.7.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
Users need at least the [Maintainer](../user/permissions.md) role to use these endpoints.
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 024362f3246..d19019c9597 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -182,6 +182,7 @@ When the user is authenticated and `simple` is not set this returns something li
"squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on
"marked_for_deletion_on": "2020-04-03",
"statistics": {
@@ -191,8 +192,10 @@ When the user is authenticated and `simple` is not set this returns something li
"wiki_size" : 0,
"lfs_objects_size": 0,
"job_artifacts_size": 0,
+ "pipeline_artifacts_size": 0,
"packages_size": 0,
- "snippets_size": 0
+ "snippets_size": 0,
+ "uploads_size": 0
},
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-client",
"_links": {
@@ -296,6 +299,7 @@ When the user is authenticated and `simple` is not set this returns something li
"service_desk_address": null,
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"statistics": {
"commit_count": 12,
"storage_size": 2066080,
@@ -303,8 +307,10 @@ When the user is authenticated and `simple` is not set this returns something li
"wiki_size" : 0,
"lfs_objects_size": 0,
"job_artifacts_size": 0,
+ "pipeline_artifacts_size": 0,
"packages_size": 0,
- "snippets_size": 0
+ "snippets_size": 0,
+ "uploads_size": 0
},
"container_registry_image_prefix": "registry.example.com/brightbox/puppet",
"_links": {
@@ -460,6 +466,7 @@ GET /users/:user_id/projects
"squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on
"marked_for_deletion_on": "2020-04-03",
"statistics": {
@@ -469,8 +476,10 @@ GET /users/:user_id/projects
"wiki_size" : 0,
"lfs_objects_size": 0,
"job_artifacts_size": 0,
+ "pipeline_artifacts_size": 0,
"packages_size": 0,
- "snippets_size": 0
+ "snippets_size": 0,
+ "uploads_size": 0
},
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-client",
"_links": {
@@ -574,6 +583,7 @@ GET /users/:user_id/projects
"service_desk_address": null,
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"statistics": {
"commit_count": 12,
"storage_size": 2066080,
@@ -581,8 +591,10 @@ GET /users/:user_id/projects
"wiki_size" : 0,
"lfs_objects_size": 0,
"job_artifacts_size": 0,
+ "pipeline_artifacts_size": 0,
"packages_size": 0,
- "snippets_size": 0
+ "snippets_size": 0,
+ "uploads_size": 0
},
"container_registry_image_prefix": "registry.example.com/brightbox/puppet",
"_links": {
@@ -698,12 +710,17 @@ Example response:
"squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"statistics": {
"commit_count": 37,
"storage_size": 1038090,
"repository_size": 1038090,
"lfs_objects_size": 0,
"job_artifacts_size": 0
+ "pipeline_artifacts_size": 0,
+ "packages_size": 0,
+ "snippets_size": 0,
+ "uploads_size": 0
},
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-client",
"_links": {
@@ -805,12 +822,17 @@ Example response:
"service_desk_address": null,
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"statistics": {
"commit_count": 12,
"storage_size": 2066080,
"repository_size": 2066080,
"lfs_objects_size": 0,
"job_artifacts_size": 0
+ "pipeline_artifacts_size": 0,
+ "packages_size": 0,
+ "snippets_size": 0,
+ "uploads_size": 0
},
"container_registry_image_prefix": "registry.example.com/brightbox/puppet",
"_links": {
@@ -968,6 +990,7 @@ GET /projects/:id
"service_desk_address": null,
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on
"marked_for_deletion_on": "2020-04-03",
"compliance_frameworks": [ "sox" ],
@@ -978,8 +1001,10 @@ GET /projects/:id
"wiki_size" : 0,
"lfs_objects_size": 0,
"job_artifacts_size": 0,
+ "pipeline_artifacts_size": 0,
"packages_size": 0,
- "snippets_size": 0
+ "snippets_size": 0,
+ "uploads_size": 0
},
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-client",
"_links": {
@@ -1278,6 +1303,7 @@ POST /projects/user/:user_id
| `issues_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable issues for this project. Use `issues_access_level` instead. |
| `jobs_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable jobs for this project. Use `builds_access_level` instead. |
| `lfs_enabled` | boolean | **{dotted-circle}** No | Enable LFS. |
+| `merge_commit_template` | string | **{dotted-circle}** No | [Template](../user/project/merge_requests/commit_templates.md) used to create merge commit message in merge requests. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20263) in GitLab 14.5.)_ |
| `merge_method` | string | **{dotted-circle}** No | Set the [merge method](#project-merge-method) used. |
| `merge_requests_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `merge_requests_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable merge requests for this project. Use `merge_requests_access_level` instead. |
@@ -1355,6 +1381,7 @@ PUT /projects/:id
| `issues_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable issues for this project. Use `issues_access_level` instead. |
| `jobs_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable jobs for this project. Use `builds_access_level` instead. |
| `lfs_enabled` | boolean | **{dotted-circle}** No | Enable LFS. |
+| `merge_commit_template` | string | **{dotted-circle}** No | [Template](../user/project/merge_requests/commit_templates.md) used to create merge commit message in merge requests. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20263) in GitLab 14.5.)_ |
| `merge_method` | string | **{dotted-circle}** No | Set the [merge method](#project-merge-method) used. |
| `merge_requests_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `merge_requests_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable merge requests for this project. Use `merge_requests_access_level` instead. |
@@ -1513,6 +1540,7 @@ Example responses:
"squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-project-site",
"_links": {
"self": "http://example.com/api/v4/projects",
@@ -1614,6 +1642,7 @@ Example response:
"squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-project-site",
"_links": {
"self": "http://example.com/api/v4/projects",
@@ -1713,6 +1742,7 @@ Example response:
"squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-project-site",
"_links": {
"self": "http://example.com/api/v4/projects",
@@ -1906,6 +1936,7 @@ Example response:
"squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-project-site",
"_links": {
"self": "http://example.com/api/v4/projects",
@@ -2026,6 +2057,7 @@ Example response:
"squash_option": "default_on",
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"container_registry_image_prefix": "registry.example.com/diaspora/diaspora-project-site",
"_links": {
"self": "http://example.com/api/v4/projects",
@@ -2652,6 +2684,7 @@ Example response:
"merge_method": "merge",
"squash_option": "default_on",
"suggestion_commit_message": null,
+ "merge_commit_template": null,
"auto_devops_enabled": true,
"auto_devops_deploy_strategy": "continuous",
"autoclose_referenced_issues": true,
@@ -2673,6 +2706,10 @@ Read more in the [Project import/export](project_import_export.md) documentation
Read more in the [Project members](members.md) documentation.
+## Project vulnerabilities
+
+Read more in the [Project vulnerabilities](project_vulnerabilities.md) documentation.
+
## Configure pull mirroring for a project **(PREMIUM)**
> - Introduced in GitLab 11.
diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md
index ded47b24c12..c253358f01f 100644
--- a/doc/api/releases/index.md
+++ b/doc/api/releases/index.md
@@ -26,6 +26,8 @@ For authentication, the Releases API accepts either:
## List Releases
+> [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72448) to allow for `JOB-TOKEN` in GitLab 14.5.
+
Paginated list of Releases, sorted by `released_at`.
```plaintext
@@ -231,6 +233,8 @@ Example response:
## Get a Release by a tag name
+> [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72448) to allow for `JOB-TOKEN` in GitLab 14.5.
+
Get a Release for the given tag.
```plaintext
@@ -508,7 +512,8 @@ adding milestones for ancestor groups raises an error.
## Collect release evidence **(PREMIUM SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199065) in GitLab 12.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199065) in GitLab 12.10.
+> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72448) to allow for `JOB-TOKEN` in GitLab 14.5.
Create Evidence for an existing Release.
@@ -535,6 +540,8 @@ Example response:
## Update a release
+> [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72448) to allow for `JOB-TOKEN` in GitLab 14.5.
+
Update a release. Developer level access to the project is required to update a release.
```plaintext
@@ -642,6 +649,8 @@ Example response:
## Delete a Release
+> [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72448) to allow for `JOB-TOKEN` in GitLab 14.5.
+
Delete a release. Deleting a release doesn't delete the associated tag. Maintainer level access to the project is required to delete a release.
```plaintext
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index 4fb1a94e294..cc210eacd49 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -185,7 +185,7 @@ POST /projects/:id/repository/files/:file_path
```shell
curl --request POST --header 'PRIVATE-TOKEN: <your_access_token>' \
--header "Content-Type: application/json" \
- --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
+ --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname",
"content": "some content", "commit_message": "create a new file"}' \
"https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb"
```
@@ -221,7 +221,7 @@ PUT /projects/:id/repository/files/:file_path
```shell
curl --request PUT --header 'PRIVATE-TOKEN: <your_access_token>' \
--header "Content-Type: application/json" \
- --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
+ --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname",
"content": "some content", "commit_message": "update file"}' \
"https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb"
```
@@ -268,7 +268,7 @@ DELETE /projects/:id/repository/files/:file_path
```shell
curl --request DELETE --header 'PRIVATE-TOKEN: <your_access_token>' \
--header "Content-Type: application/json" \
- --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
+ --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname",
"commit_message": "delete file"}' \
"https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb"
```
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 7b8778973f2..dd32c882860 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -85,7 +85,7 @@ Example response:
"raw_blob_request_limit": 300,
"wiki_page_max_content_bytes": 52428800,
"require_admin_approval_after_user_signup": false,
- "personal_access_token_prefix": "GL-",
+ "personal_access_token_prefix": "glpat-",
"rate_limiting_response_text": null,
"keep_latest_artifact": true,
"admin_mode": false,
@@ -187,7 +187,7 @@ Example response:
"raw_blob_request_limit": 300,
"wiki_page_max_content_bytes": 52428800,
"require_admin_approval_after_user_signup": false,
- "personal_access_token_prefix": "GL-",
+ "personal_access_token_prefix": "glpat-",
"rate_limiting_response_text": null,
"keep_latest_artifact": true,
"admin_mode": false,
@@ -411,11 +411,11 @@ listed in the descriptions of the relevant settings.
| `terminal_max_session_time` | integer | no | Maximum time for web terminal websocket connection (in seconds). Set to `0` for unlimited time. |
| `terms` | text | required by: `enforce_terms` | (**Required by:** `enforce_terms`) Markdown content for the ToS. |
| `throttle_authenticated_api_enabled` | boolean | no | (**If enabled, requires:** `throttle_authenticated_api_period_in_seconds` and `throttle_authenticated_api_requests_per_period`) Enable authenticated API request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). |
-| `throttle_authenticated_api_period_in_seconds` | integer | required by:<br>`throttle_authenticated_api_enabled` | Rate limit period in seconds. |
-| `throttle_authenticated_api_requests_per_period` | integer | required by:<br>`throttle_authenticated_api_enabled` | Max requests per period per user. |
+| `throttle_authenticated_api_period_in_seconds` | integer | required by:<br>`throttle_authenticated_api_enabled` | Rate limit period (in seconds). |
+| `throttle_authenticated_api_requests_per_period` | integer | required by:<br>`throttle_authenticated_api_enabled` | Maximum requests per period per user. |
| `throttle_authenticated_web_enabled` | boolean | no | (**If enabled, requires:** `throttle_authenticated_web_period_in_seconds` and `throttle_authenticated_web_requests_per_period`) Enable authenticated web request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). |
-| `throttle_authenticated_web_period_in_seconds` | integer | required by:<br>`throttle_authenticated_web_enabled` | Rate limit period in seconds. |
-| `throttle_authenticated_web_requests_per_period` | integer | required by:<br>`throttle_authenticated_web_enabled` | Max requests per period per user. |
+| `throttle_authenticated_web_period_in_seconds` | integer | required by:<br>`throttle_authenticated_web_enabled` | Rate limit period (in seconds). |
+| `throttle_authenticated_web_requests_per_period` | integer | required by:<br>`throttle_authenticated_web_enabled` | Maximum requests per period per user. |
| `throttle_unauthenticated_enabled` | boolean | no | ([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/335300) in GitLab 14.3. Use `throttle_unauthenticated_web_enabled` or `throttle_unauthenticated_api_enabled` instead.) (**If enabled, requires:** `throttle_unauthenticated_period_in_seconds` and `throttle_unauthenticated_requests_per_period`) Enable unauthenticated web request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). |
| `throttle_unauthenticated_period_in_seconds` | integer | required by:<br>`throttle_unauthenticated_enabled` | ([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/335300) in GitLab 14.3. Use `throttle_unauthenticated_web_period_in_seconds` or `throttle_unauthenticated_api_period_in_seconds` instead.) Rate limit period in seconds. |
| `throttle_unauthenticated_requests_per_period` | integer | required by:<br>`throttle_unauthenticated_enabled` | ([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/335300) in GitLab 14.3. Use `throttle_unauthenticated_web_requests_per_period` or `throttle_unauthenticated_api_requests_per_period` instead.) Max requests per period per IP. |
diff --git a/doc/api/sidekiq_metrics.md b/doc/api/sidekiq_metrics.md
index bcb59a6dad3..2be2e71e551 100644
--- a/doc/api/sidekiq_metrics.md
+++ b/doc/api/sidekiq_metrics.md
@@ -6,8 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Sidekiq Metrics API **(FREE SELF)**
-> Introduced in GitLab 8.9.
-
This API endpoint allows you to retrieve some information about the current state
of Sidekiq, its jobs, queues, and processes.
diff --git a/doc/api/todos.md b/doc/api/todos.md
index 737bfb11da9..98f254f6620 100644
--- a/doc/api/todos.md
+++ b/doc/api/todos.md
@@ -27,7 +27,7 @@ Parameters:
| `project_id` | integer | no | The ID of a project |
| `group_id` | integer | no | The ID of a group |
| `state` | string | no | The state of the to-do item. Can be either `pending` or `done` |
-| `type` | string | no | The type of to-do item. Can be either `Issue`, `MergeRequest`, `DesignManagement::Design` or `AlertManagement::Alert` |
+| `type` | string | no | The type of to-do item. Can be either `Issue`, `MergeRequest`, `Commit`, `Epic`, `DesignManagement::Design` or `AlertManagement::Alert` |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/todos"
diff --git a/doc/api/topics.md b/doc/api/topics.md
new file mode 100644
index 00000000000..5e9e1b8fc12
--- /dev/null
+++ b/doc/api/topics.md
@@ -0,0 +1,190 @@
+---
+stage: Manage
+group: Workspace
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Topics API **(FREE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340920) in GitLab 14.5.
+
+Interact with project topics using the REST API.
+
+## List topics
+
+Returns a list of project topics in the GitLab instance ordered by number of associated projects.
+
+```plaintext
+GET /topics
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| ---------- | ------- | ---------------------- | ----------- |
+| `page` | integer | **{dotted-circle}** No | Page to retrieve. Defaults to `1`. |
+| `per_page` | integer | **{dotted-circle}** No | Number of records to return per page. Defaults to `20`. |
+| `search` | string | **{dotted-circle}** No | Search topics against their `name`. |
+
+Example request:
+
+```shell
+curl "https://gitlab.example.com/api/v4/topics?search=git"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 1,
+ "name": "GitLab",
+ "description": "GitLab is an open source end-to-end software development platform with built-in version control, issue tracking, code review, CI/CD, and more.",
+ "total_projects_count": 1000,
+ "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon"
+ },
+ {
+ "id": 3,
+ "name": "Git",
+ "description": "Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.",
+ "total_projects_count": 900,
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
+ },
+ {
+ "id": 2,
+ "name": "Git LFS",
+ "description": null,
+ "total_projects_count": 300,
+ "avatar_url": null
+ }
+]
+```
+
+## Get a topic
+
+Get a project topic by ID.
+
+```plaintext
+GET /topics/:id
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| --------- | ------- | ---------------------- | ------------------- |
+| `id` | integer | **{check-circle}** Yes | ID of project topic |
+
+Example request:
+
+```shell
+curl "https://gitlab.example.com/api/v4/topics/1"
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "name": "GitLab",
+ "description": "GitLab is an open source end-to-end software development platform with built-in version control, issue tracking, code review, CI/CD, and more.",
+ "total_projects_count": 1000,
+ "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon"
+}
+```
+
+## List projects assigned to a topic
+
+Use the [Projects API](projects.md#list-all-projects) to list all projects assigned to a specific topic.
+
+```plaintext
+GET /projects?topic=<topic_name>
+```
+
+## Create a project topic
+
+Create a new project topic. Only available to administrators.
+
+```plaintext
+POST /topics
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| ------------- | ------- | ---------------------- | ----------- |
+| `name` | string | **{check-circle}** Yes | Name |
+| `avatar` | file | **{dotted-circle}** No | Avatar |
+| `description` | string | **{dotted-circle}** No | Description |
+
+Example request:
+
+```shell
+curl --request POST \
+ --data "name=topic1" \
+ --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/topics"
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "name": "topic1",
+ "description": null,
+ "total_projects_count": 0,
+ "avatar_url": null
+}
+```
+
+## Update a project topic
+
+Update a project topic. Only available to administrators.
+
+```plaintext
+PUT /topics/:id
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| ------------- | ------- | ---------------------- | ------------------- |
+| `id` | integer | **{check-circle}** Yes | ID of project topic |
+| `avatar` | file | **{dotted-circle}** No | Avatar |
+| `description` | string | **{dotted-circle}** No | Description |
+| `name` | string | **{dotted-circle}** No | Name |
+
+Example request:
+
+```shell
+curl --request PUT \
+ --data "name=topic1" \
+ --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/topics/1"
+
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "name": "topic1",
+ "description": null,
+ "total_projects_count": 0,
+ "avatar_url": null
+}
+```
+
+### Upload a topic avatar
+
+To upload an avatar file from your file system, use the `--form` argument. This argument causes
+cURL to post data using the header `Content-Type: multipart/form-data`. The
+`file=` parameter must point to a file on your file system and be preceded by
+`@`. For example:
+
+```shell
+curl --request PUT \
+ --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/topics/1" \
+ --form "avatar=@/tmp/example.png"
+```
diff --git a/doc/architecture/blueprints/ci_scale/index.md b/doc/architecture/blueprints/ci_scale/index.md
index 6afa13bf207..3e9fbc534d5 100644
--- a/doc/architecture/blueprints/ci_scale/index.md
+++ b/doc/architecture/blueprints/ci_scale/index.md
@@ -60,6 +60,9 @@ that have the same problem.
Primary keys problem will be tackled by our Database Team.
+Status: As of October 2021 the primary keys in CI tables have been migrated to
+big integers.
+
### The table is too large
There is more than a billion rows in `ci_builds` table. We store more than 2
@@ -111,6 +114,12 @@ table that will accelerate SQL queries used to build
queues](https://gitlab.com/gitlab-org/gitlab/-/issues/322766) and we want to
explore them.
+Status: the new architecture [has been implemented on GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/5909#note_680407908).
+
+The following epic tracks making it generally available: [Make the new pending
+builds architecture generally available](
+https://gitlab.com/groups/gitlab-org/-/epics/6954).
+
### Moving big amounts of data is challenging
We store a significant amount of data in `ci_builds` table. Some of the columns
@@ -127,6 +136,8 @@ columns, tables, partitions or database shards.
Effort to improve background migrations will be owned by our Database Team.
+Status: In progress.
+
### Development velocity is negatively affected
Team members and the wider community members are struggling to contribute the
@@ -168,7 +179,12 @@ target](https://gitlab.com/groups/gitlab-org/-/epics/5745) epic.
## Status
-In progress.
+|-------------|--------------|
+| Created at | 21.01.2021 |
+| Approved at | 26.04.2021 |
+| Updated at | 28.10.2021 |
+
+Status: In progress.
## Who
@@ -180,7 +196,7 @@ Proposal:
|------------------------------|-------------------------|
| Author | Grzegorz Bizon |
| Architecture Evolution Coach | Kamil Trzciński |
-| Engineering Leader | Darby Frey |
+| Engineering Leader | Cheryl Li |
| Product Manager | Jackie Porter |
| Domain Expert / Verify | Fabio Pitino |
| Domain Expert / Database | Jose Finotto |
@@ -190,7 +206,7 @@ DRIs:
| Role | Who
|------------------------------|------------------------|
-| Leadership | Darby Frey |
+| Leadership | Cheryl Li |
| Product | Jackie Porter |
| Engineering | Grzegorz Bizon |
diff --git a/doc/architecture/blueprints/consolidating_groups_and_projects/index.md b/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
index a8d87e5f967..53357220755 100644
--- a/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
+++ b/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
@@ -6,7 +6,7 @@ comments: false
description: Consolidating groups and projects
---
-# Consolidating Group and Project
+# Consolidating Groups and Projects
There are numerous features that exist exclusively within groups or
projects. The boundary between group and project features used to be clear.
@@ -127,6 +127,22 @@ The work required to establish `Namespace` as a container for our features is
tracked under [Consolidate Groups and Projects](https://gitlab.com/groups/gitlab-org/-/epics/6473)
epic.
+## Migrating features to Namespaces
+
+The initial iteration will provide a framework to house features under `Namespaces`. Stage groups will eventually need to migrate their own features and functionality over to `Namespaces`. This may impact these features in unexpected ways. Therefore, to minimize UX debt and maintain product consistency, stage groups will have to consider a number of factors when migrating their features over to `Namespaces`:
+
+1. **Conceptual model**: What are the current and future state conceptual models of these features ([see object modeling for designers](https://hpadkisson.medium.com/object-modeling-for-designers-an-introduction-7871bdcf8baf))? These should be documented in Pajamas (example: [Merge Requests](https://design.gitlab.com/objects/merge-request)).
+1. **Merge conflicts**: What inconsistencies are there across project, group, and admin levels? How might these be addressed? For an example of how we rationalized this for labels, please see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338820).
+1. **Inheritence & information flow**: How is information inherited across our container hierarchy currently? How might this be impacted if complying with the new [inheritence behavior](https://gitlab.com/gitlab-org/gitlab/-/issues/343316) framework?
+1. **Settings**: Where can settings for this feature be found currently? How will these be impacted by `Namespaces`?
+1. **Access**: Who can access this feature and is that impacted by the new container structure? Are there any role or privacy considerations?
+1. **Tier**: Is there any tier functionality that is differentiated by projects and groups?
+1. **Documentation**: Is the structure and content of documentation impacted by these changes at all?
+1. **Solution proposal**:
+ - Think big: This analysis provides a great opportunity to zoom out and consider the feature UX as a whole. How could you make this feature lovable based on the new structure, inheritance, and capabilities afforded by `Namespaces`? Is there any UI which doesn't comply with Pajamas?
+ - Start small: What are the product changes that need to be made to assist with the migration?
+ - Move fast: Prioritise these solution ideas, document in issues, and create a roadmap for implementation.
+
## Who
Proposal:
@@ -151,5 +167,10 @@ DRIs:
| Product | Melissa Ushakov |
| Leadership | Michelle Gill |
| Engineering | Imre Farkas |
+| Design | Nick Post |
<!-- vale gitlab.Spelling = YES -->
+
+## Related topics
+
+- [Workspaces developer documentation](../../../development/workspaces/index.md)
diff --git a/doc/architecture/blueprints/container_registry_metadata_database/index.md b/doc/architecture/blueprints/container_registry_metadata_database/index.md
index f52635baf7b..7bbaefb8e1e 100644
--- a/doc/architecture/blueprints/container_registry_metadata_database/index.md
+++ b/doc/architecture/blueprints/container_registry_metadata_database/index.md
@@ -193,13 +193,19 @@ PostgreSQL introduced significant improvements for partitioning in [version 12](
- Bulk load (`COPY`) now uses bulk inserts instead of inserting one row at a time;
To leverage these features and performance improvements, we need to use PostgreSQL 12 from the start.
-
-GitLab currently ships with PostgreSQL 11 for self-managed instances. That is _likely_ to change in 14.0, with PostgreSQL 12 becoming the minimum required version, which will likely happen before the upgraded registry becomes available for self-managed instances. If not, self-managed instances will have two options:
-
-1. Administrators can manually provision and configure a separate PostgreSQL 12 database for the registry, allowing them to benefit from features provided by the new registry and its metadata database.
-1. Continue to use the current registry without the database if online garbage collection is not a concern or provisioning a separate database is not possible. We will continue supporting the current version with security backports and bug fixes for the foreseeable feature.
-
-It's important to note that apart from online garbage collection, the metadata database's availability will unblock the implementation of many requested features for the GitLab Container Registry, which will only be available for instances using the new version backed by the metadata database.
+GitLab 14.0 and later [ships with PostgreSQL 12](../../../administration/package_information/postgresql_versions.md)
+for self-managed instances. Customers not able to upgrade to PostgreSQL 12 have two options:
+
+- Administrators can manually provision and configure a separate PostgreSQL 12 database for the
+ registry. This lets you benefit from the features provided by the new registry and its metadata
+ database.
+- If online garbage collection isn't a concern or provisioning a separate database isn't possible,
+ continue to use the current registry without the database. GitLab supports the current version
+ with security backports and bug fixes.
+
+Apart from online garbage collection, the metadata database's availability unblocks the
+implementation of many requested features for the GitLab Container Registry. These features are only
+available for instances using the new version backed by the metadata database.
### Availability
diff --git a/doc/architecture/blueprints/feature_flags_development/index.md b/doc/architecture/blueprints/feature_flags_development/index.md
index a5e46d25921..94d52ea3474 100644
--- a/doc/architecture/blueprints/feature_flags_development/index.md
+++ b/doc/architecture/blueprints/feature_flags_development/index.md
@@ -29,7 +29,7 @@ The extensive usage of feature flags poses a few challenges
We sometimes forget how our feature flags are configured or why we haven't
yet removed the feature flag.
- The usage of feature flags can also be confusing to people outside of
- development that might not fully understand dependence of ~feature or ~bug
+ development that might not fully understand dependence of ~"type::feature" or ~"type::bug"
fix on feature flag and how this feature flag is configured. Or if the feature
should be announced as part of release post.
- Maintaining feature flags poses additional challenge of having to manage
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index 29a03fe06ab..57cbf387115 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -134,7 +134,7 @@ job:
## Inherit global configuration, but override specific settings per job
You can override cache settings without overwriting the global cache by using
-[anchors](../yaml/index.md#anchors). For example, if you want to override the
+[anchors](../yaml/yaml_optimization.md#anchors). For example, if you want to override the
`policy` for one job:
```yaml
diff --git a/doc/ci/cloud_deployment/index.md b/doc/ci/cloud_deployment/index.md
index 408d68fb726..80e4d8fbe27 100644
--- a/doc/ci/cloud_deployment/index.md
+++ b/doc/ci/cloud_deployment/index.md
@@ -104,7 +104,7 @@ GitLab also provides [Docker images](https://gitlab.com/gitlab-org/cloud-deploy/
- Use `registry.gitlab.com/gitlab-org/cloud-deploy/aws-ecs:latest` to deploy your application to AWS ECS.
Before getting started with this process, you need a cluster on AWS ECS, as well as related
-components, like an ECS service, ECS task definition, a database on AWS RDS, and so on.
+components, like an ECS service, ECS task definition, a database on Amazon RDS, and so on.
[Read more about AWS ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html).
The ECS task definition can be:
diff --git a/doc/ci/directed_acyclic_graph/index.md b/doc/ci/directed_acyclic_graph/index.md
index 11ba1e40b3e..f26a678962a 100644
--- a/doc/ci/directed_acyclic_graph/index.md
+++ b/doc/ci/directed_acyclic_graph/index.md
@@ -74,9 +74,9 @@ giving you powerful options for parallelization within your pipeline.
## Limitations
A directed acyclic graph is a complicated feature, and as of the initial MVC there
-are certain use cases that you may need to work around. For more information:
+are certain use cases that you may need to work around. For more information, check the:
-- [`needs` requirements and limitations](../yaml/index.md#requirements-and-limitations).
+- [`needs` additional details](../yaml/index.md#needs).
- Related epic [tracking planned improvements](https://gitlab.com/groups/gitlab-org/-/epics/1716).
## Needs Visualization
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 9a4290ead4c..f6a6e892177 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -841,6 +841,8 @@ This issue occurs because Docker starts on TLS automatically.
- If you are upgrading from v18.09 or earlier, read our
[upgrade guide](https://about.gitlab.com/blog/2019/07/31/docker-in-docker-with-docker-19-dot-03/).
+This error can also occur with the [Kubernetes executor](https://docs.gitlab.com/runner/executors/kubernetes.html#using-dockerdind) when attempts are made to access the Docker-in-Docker service before it has had time to fully start up. For a more detailed explanation, see [this issue](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27215).
+
### Docker `no such host` error
You may get an error that says
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index 79c23d73a68..def7703231c 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -132,16 +132,7 @@ For example, the following two definitions are equal:
When a CI job runs in a Docker container, the `before_script`, `script`, and `after_script` commands run in the `/builds/<project-path>/` directory. Your image may have a different default `WORKDIR` defined. To move to your `WORKDIR`, save the `WORKDIR` as an environment variable so you can reference it in the container during the job's runtime.
-### Available settings for `image`
-
-> Introduced in GitLab and GitLab Runner 9.4.
-
-| Setting | Required | Description |
-|------------|----------| ----------- |
-| `name` | Yes, when used with any other option. | Full name of the image. It should contain the registry part if needed. |
-| `entrypoint` | No. | Command or script to execute as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. |
-
-### Overriding the entrypoint of an image
+### Override the entrypoint of an image
> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](../docker/using_docker_images.md#extended-docker-configuration-options).
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index 69c4557dcbe..ea3e81329d3 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -37,7 +37,7 @@ few important details:
- The kaniko debug image is recommended (`gcr.io/kaniko-project/executor:debug`)
because it has a shell, and a shell is required for an image to be used with
GitLab CI/CD.
-- The entrypoint needs to be [overridden](using_docker_images.md#overriding-the-entrypoint-of-an-image),
+- The entrypoint needs to be [overridden](using_docker_images.md#override-the-entrypoint-of-an-image),
otherwise the build script doesn't run.
- A Docker `config.json` file needs to be created with the authentication
information for the desired container registry.
@@ -64,8 +64,12 @@ build:
entrypoint: [""]
script:
- mkdir -p /kaniko/.docker
- - echo "{\"auths\":{\"$CI_REGISTRY\":{\"auth\":\"$(echo -n ${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD} | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
- - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
+ - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
+ - >-
+ /kaniko/executor
+ --context "${CI_PROJECT_DIR}"
+ --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
+ --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
rules:
- if: $CI_COMMIT_TAG
```
@@ -91,14 +95,19 @@ build:
- mkdir -p /kaniko/.docker
- |-
KANIKOPROXYBUILDARGS=""
- KANIKOCFG="{\"auths\":{\"$CI_REGISTRY\":{\"auth\":\"$(echo -n ${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD} | base64 | tr -d '\n')\"}}}"
+ KANIKOCFG="\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}"
if [ "x${http_proxy}" != "x" -o "x${https_proxy}" != "x" ]; then
KANIKOCFG="${KANIKOCFG}, \"proxies\": { \"default\": { \"httpProxy\": \"${http_proxy}\", \"httpsProxy\": \"${https_proxy}\", \"noProxy\": \"${no_proxy}\"}}"
KANIKOPROXYBUILDARGS="--build-arg http_proxy=${http_proxy} --build-arg https_proxy=${https_proxy} --build-arg no_proxy=${no_proxy}"
fi
- KANIKOCFG="${KANIKOCFG} }"
+ KANIKOCFG="{ ${KANIKOCFG} }"
echo "${KANIKOCFG}" > /kaniko/.docker/config.json
- - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile $KANIKOPROXYBUILDARGS --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
+ - >-
+ /kaniko/executor
+ --context "${CI_PROJECT_DIR}"
+ --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
+ "${KANIKOPROXYBUILDARGS}"
+ --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
rules:
- if: $CI_COMMIT_TAG
```
@@ -120,7 +129,7 @@ store:
```yaml
before_script:
- mkdir -p /kaniko/.docker
- - echo "{\"auths\":{\"$CI_REGISTRY\":{\"auth\":\"$(echo -n ${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD} | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
+ - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
- |
echo "-----BEGIN CERTIFICATE-----
...
diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md
index ca81ad30317..87d7b9f9e30 100644
--- a/doc/ci/environments/index.md
+++ b/doc/ci/environments/index.md
@@ -21,13 +21,13 @@ GitLab:
If you have a deployment service like [Kubernetes](../../user/infrastructure/clusters/index.md)
associated with your project, you can use it to assist with your deployments.
-You can even access a [web terminal](#web-terminals) for your environment from within GitLab.
+You can even access a [web terminal](#web-terminals-deprecated) for your environment from within GitLab.
## View environments and deployments
Prerequisites:
-- You must have a minimum of [Reporter permission](../../user/permissions.md#project-members-permissions).
+- You must have at least the Reporter [role](../../user/permissions.md#project-members-permissions).
To view a list of environments and deployments:
@@ -159,9 +159,9 @@ deploy_prod:
environment:
name: production
url: https://example.com
- when: manual
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ when: manual
```
The `when: manual` action:
@@ -171,9 +171,13 @@ The `when: manual` action:
You can find the play button in the pipelines, environments, deployments, and jobs views.
-## Configure Kubernetes deployments
+## Configure Kubernetes deployments (DEPRECATED)
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) in GitLab 12.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) in GitLab 12.6.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
If you are deploying to a [Kubernetes cluster](../../user/infrastructure/clusters/index.md)
associated with your project, you can configure these deployments from your
@@ -308,6 +312,31 @@ Note the following:
for these jobs. This ensures that runners can fetch the repository even after a feature branch is
deleted. For more information, see [Ref Specs for Runners](../pipelines/index.md#ref-specs-for-runners).
+## Track newly included merge requests per deployment
+
+GitLab can track newly included merge requests per deployment.
+When a deployment succeeded, the system calculates commit-diffs between the latest deployment and the previous deployment.
+This tracking information can be fetched via the [Deployment API](../../api/deployments.md#list-of-merge-requests-associated-with-a-deployment)
+and displayed at a post-merge pipeline in [merge request pages](../../user/project/merge_requests/index.md).
+
+To activate this tracking, your environment must be configured in the following:
+
+- [Environment name](../yaml/index.md#environmentname) is not foldered with `/` (that is, top-level/long-lived environments), _OR_
+- [Environment tier](#deployment-tier-of-environments) is either `production` or `staging`.
+
+Here are the example setups of [`environment` keyword](../yaml/index.md#environment) in `.gitlab-ci.yml`:
+
+```yaml
+# Trackable
+environment: production
+environment: production/aws
+environment: development
+
+# Non Trackable
+environment: review/$CI_COMMIT_REF_SLUG
+environment: testing/aws
+```
+
## Working with environments
Once environments are configured, GitLab provides many features for working with them,
@@ -631,7 +660,12 @@ It may take a minute or two for data to appear after initial deployment.
Metric charts can be embedded in GitLab Flavored Markdown. See [Embedding Metrics in GitLab Flavored Markdown](../../operations/metrics/embed.md) for more details.
-### Web terminals
+### Web terminals (DEPRECATED)
+
+> [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
If you deploy to your environments with the help of a deployment service (for example,
the [Kubernetes integration](../../user/infrastructure/clusters/index.md)), GitLab can open
@@ -680,6 +714,29 @@ fetch line:
fetch = +refs/environments/*:refs/remotes/origin/environments/*
```
+### Archive Old Deployments
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73628) in GitLab 14.5.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `deployments_archive`. On GitLab.com, this feature will be rolled out gradually.
+
+When a new deployment happens in your project,
+GitLab creates [a special Git-ref to the deployment](#check-out-deployments-locally).
+Since these Git-refs are populated from the remote GitLab repository,
+you could find that some Git operations, such as `git-fetch` and `git-pull`,
+become slower as the number of deployments in your project increases.
+
+To maintain the efficiency of your Git operations, GitLab keeps
+only recent deployment refs (up to 50,000) and deletes the rest of the old deployment refs.
+Archived deployments are still available, in the UI or by using the API, for auditing purposes.
+Also, you can still fetch the deployed commit from the repository
+with specifying the commit SHA (for example, `git checkout <deployment-sha>`), even after archive.
+
+NOTE:
+GitLab preserves all commits as [`keep-around` refs](../../user/project/repository/reducing_the_repo_size_using_git.md)
+so that deployed commits are not garbage collected, even if it's not referenced by the deployment refs.
+
### Scope environments with specs
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2112) in GitLab Premium 9.4.
@@ -822,7 +879,9 @@ To ensure the `action: stop` can always run when needed, you can:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21182) in GitLab 14.4.
FLAG:
-On self-managed GitLab, by default this bug fix is not available. To make it available per project or for your entire instance, ask an administrator to [enable the `surface_environment_creation_failure` flag](../../administration/feature_flags.md). On GitLab.com, this bug fix is not available, but will be rolled out shortly.
+On self-managed GitLab, by default this bug fix is available. To hide the bug fix per project,
+ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `surface_environment_creation_failure`.
+On GitLab.com, this bug fix is available.
If your project is configured to [create a dynamic environment](#create-a-dynamic-environment),
you might encounter this error because the dynamically generated parameter can't be used for creating an environment.
@@ -875,3 +934,19 @@ To fix this, use one of the following solutions:
script: deploy review app
environment: review/$CI_COMMIT_REF_SLUG
```
+
+### Deployment refs are not found
+
+Starting from GitLab 14.5, GitLab [deletes old deployment refs](#archive-old-deployments)
+to keep your Git repository performant.
+
+If you have to restore archived Git-refs, please ask an administrator of your self-managed GitLab instance
+to execute the following command on Rails console:
+
+```ruby
+Project.find_by_full_path(<your-project-full-path>).deployments.where(archived: true).each(&:create_ref)
+```
+
+Please note that GitLab could drop this support in the future for the performance concern.
+You can open an issue in [GitLab Issue Tracker](https://gitlab.com/gitlab-org/gitlab/-/issues/new)
+to discuss the behavior of this feature.
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index 47f93b03136..55b63dd090d 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -102,10 +102,9 @@ The group now has access and can be seen in the UI.
## Environment access by group membership
-A user may be granted access to protected environments as part of
-[group membership](../../user/group/index.md). Users with
-[Reporter permissions](../../user/permissions.md), can only be granted access to
-protected environments with this method.
+A user may be granted access to protected environments as part of [group membership](../../user/group/index.md). Users
+with the Reporter [role](../../user/permissions.md) can only be granted access to protected environments with this
+method.
## Deployment branch access
@@ -120,14 +119,14 @@ they have the following privileges:
- [Stop an environment](index.md#stop-an-environment).
- [Delete a stopped environment](index.md#delete-a-stopped-environment).
-- [Create an environment terminal](index.md#web-terminals).
+- [Create an environment terminal](index.md#web-terminals-deprecated).
## Deployment-only access to protected environments
Users granted access to a protected environment, but not push or merge access
to the branch deployed to it, are only granted access to deploy the environment. An individual in a
-group with the Reporter permission, or in groups added to the project with Reporter permissions,
-appears in the dropdown menu for deployment-only access.
+group with the Reporter [role](../../user/permissions.md), or in groups added to the project with the Reporter
+role, appears in the dropdown menu for deployment-only access.
To add deployment-only access:
@@ -136,7 +135,8 @@ To add deployment-only access:
1. Invite the group to be a project member.
1. Follow the steps in [Protecting Environments](#protecting-environments).
-Note that deployment-only access is the only possible access level for groups with [Reporter permissions](../../user/permissions.md).
+Note that deployment-only access is the only possible access level for groups with the Reporter
+[role](../../user/permissions.md).
## Modifying and unprotecting environments
diff --git a/doc/ci/git_submodules.md b/doc/ci/git_submodules.md
index 0df653acca4..dc5faf0188e 100644
--- a/doc/ci/git_submodules.md
+++ b/doc/ci/git_submodules.md
@@ -59,3 +59,8 @@ To make submodules work correctly in CI/CD jobs:
variables:
GIT_SUBMODULE_STRATEGY: recursive
```
+
+If you use the [`CI_JOB_TOKEN`](jobs/ci_job_token.md) to clone a submodule in a
+pipeline job, the user executing the job must be assigned to a role that has
+[permission](../user/permissions.md#gitlab-cicd-permissions) to trigger a pipeline
+in the upstream submodule project.
diff --git a/doc/ci/index.md b/doc/ci/index.md
index 2f18bd28642..5dcb0bcb242 100644
--- a/doc/ci/index.md
+++ b/doc/ci/index.md
@@ -86,10 +86,10 @@ GitLab CI/CD features, grouped by DevOps stage, include:
| [Browser Performance Testing](../user/project/merge_requests/browser_performance_testing.md) | Quickly determine the browser performance impact of pending code changes. |
| [Load Performance Testing](../user/project/merge_requests/load_performance_testing.md) | Quickly determine the server performance impact of pending code changes. |
| [CI services](services/index.md) | Link Docker containers with your base image. |
-| [Code Quality](../user/project/merge_requests/code_quality.md) | Analyze your source code quality. |
| [GitLab CI/CD for external repositories](ci_cd_for_external_repos/index.md) **(PREMIUM)** | Get the benefits of GitLab CI/CD combined with repositories in GitHub and Bitbucket Cloud. |
| [Interactive Web Terminals](interactive_web_terminal/index.md) **(FREE SELF)** | Open an interactive web terminal to debug the running jobs. |
-| [Unit test reports](unit_test_reports.md) | Identify script failures directly on merge requests. |
+| [Review Apps](review_apps/index.md) | Configure GitLab CI/CD to preview code changes. |
+| [Unit test reports](unit_test_reports.md) | Identify test failures directly on merge requests. |
| [Using Docker images](docker/using_docker_images.md) | Use GitLab and GitLab Runner with Docker to build and test applications. |
|-------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------|
| **Release** | |
@@ -100,10 +100,10 @@ GitLab CI/CD features, grouped by DevOps stage, include:
| [Feature Flags](../operations/feature_flags.md) | Deploy your features behind Feature Flags. |
| [GitLab Pages](../user/project/pages/index.md) | Deploy static websites. |
| [GitLab Releases](../user/project/releases/index.md) | Add release notes to Git tags. |
-| [Review Apps](review_apps/index.md) | Configure GitLab CI/CD to preview code changes. |
| [Cloud deployment](cloud_deployment/index.md) | Deploy your application to a main cloud provider. |
|-------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------|
| **Secure** | |
+| [Code Quality](../user/project/merge_requests/code_quality.md) | Analyze your source code quality. |
| [Container Scanning](../user/application_security/container_scanning/index.md) **(ULTIMATE)** | Check your Docker containers for known vulnerabilities. |
| [Dependency Scanning](../user/application_security/dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. |
| [License Compliance](../user/compliance/license_compliance/index.md) **(ULTIMATE)** | Search your project dependencies for their licenses. |
@@ -129,13 +129,17 @@ See also:
- [Enable or disable GitLab CI/CD in a project](enable_or_disable_ci.md).
-## References
+## Related topics
Learn more about GitLab CI/CD:
- [Why you might choose GitLab CI/CD](https://about.gitlab.com/blog/2016/10/17/gitlab-ci-oohlala/).
- [Reasons you might migrate from another platform](https://about.gitlab.com/blog/2016/07/22/building-our-web-app-on-gitlab-ci/).
- [5 Teams that made the switch to GitLab CI/CD](https://about.gitlab.com/blog/2019/04/25/5-teams-that-made-the-switch-to-gitlab-ci-cd/)
+- If you use VS Code to edit your GitLab CI/CD configuration, the
+ [GitLab Workflow VS Code extension](../user/project/repository/vscode.md) helps you
+ [validate your configuration](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#validate-gitlab-ci-configuration)
+ and [view your pipeline status](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#information-about-your-branch-pipelines-mr-closing-issue).
See also the [Why CI/CD?](https://docs.google.com/presentation/d/1OGgk2Tcxbpl7DJaIOzCX4Vqg3dlwfELC3u2jEeCBbDk) presentation.
@@ -144,6 +148,10 @@ See also the [Why CI/CD?](https://docs.google.com/presentation/d/1OGgk2Tcxbpl7DJ
As GitLab CI/CD has evolved, certain breaking changes have
been necessary.
+#### 14.0
+
+- No breaking changes.
+
#### 13.0
- [Remove Backported `os.Expand`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4915).
diff --git a/doc/ci/jobs/ci_job_token.md b/doc/ci/jobs/ci_job_token.md
index 308f38b22b7..b6a3011a3d6 100644
--- a/doc/ci/jobs/ci_job_token.md
+++ b/doc/ci/jobs/ci_job_token.md
@@ -20,7 +20,7 @@ You can use a GitLab CI/CD job token to authenticate with specific API endpoints
- [Get job artifacts](../../api/job_artifacts.md#get-job-artifacts).
- [Get job token's job](../../api/jobs.md#get-job-tokens-job).
- [Pipeline triggers](../../api/pipeline_triggers.md), using the `token=` parameter.
-- [Release creation](../../api/releases/index.md#create-a-release).
+- [Releases](../../api/releases/index.md).
- [Terraform plan](../../user/infrastructure/index.md).
The token has the same permissions to access the API as the user that executes the
diff --git a/doc/ci/jobs/index.md b/doc/ci/jobs/index.md
index cb3b11ebf99..104badb782c 100644
--- a/doc/ci/jobs/index.md
+++ b/doc/ci/jobs/index.md
@@ -82,6 +82,24 @@ For example:
![Pipeline mini graph sorting](img/pipelines_mini_graph_sorting.png)
+## Job name limitations
+
+You can't use these keywords as job names:
+
+- `image`
+- `services`
+- `stages`
+- `types`
+- `before_script`
+- `after_script`
+- `variables`
+- `cache`
+- `include`
+
+Job names must be 255 characters or less. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342800)
+in GitLab 14.5, [with a feature flag](../../administration/feature_flags.md) named `ci_validate_job_length`.
+Enabled by default. To disable it, ask an administrator to [disable the feature flag](../../administration/feature_flags.md).
+
## Group jobs in a pipeline
If you have many similar jobs, your [pipeline graph](../pipelines/index.md#visualize-pipelines) becomes long and hard
@@ -139,6 +157,89 @@ In [GitLab 13.8 and earlier](https://gitlab.com/gitlab-org/gitlab/-/merge_reques
the regular expression is `\d+[\s:\/\\]+\d+\s*`. [Feature flag](../../user/feature_flags.md)
removed in [GitLab 13.11](https://gitlab.com/gitlab-org/gitlab/-/issues/322080).
+## Hide jobs
+
+To temporarily disable a job without deleting it from the configuration
+file:
+
+- Comment out the job's configuration:
+
+ ```yaml
+ # hidden_job:
+ # script:
+ # - run test
+ ```
+
+- Start the job name with a dot (`.`) and it is not processed by GitLab CI/CD:
+
+ ```yaml
+ .hidden_job:
+ script:
+ - run test
+ ```
+
+You can use hidden jobs that start with `.` as templates for reusable configuration with:
+
+- The [`extends` keyword](../yaml/index.md#extends).
+- [YAML anchors](../yaml/yaml_optimization.md#anchors).
+
+## Control the inheritance of default keywords and global variables
+
+You can control the inheritance of:
+
+- [default keywords](../yaml/index.md#default) with [`inherit:default`](../yaml/index.md#inheritdefault).
+- [global variables](../yaml/index.md#default) with [`inherit:variables`](../yaml/index.md#inheritvariables).
+
+For example:
+
+```yaml
+default:
+ image: 'ruby:2.4'
+ before_script:
+ - echo Hello World
+
+variables:
+ DOMAIN: example.com
+ WEBHOOK_URL: https://my-webhook.example.com
+
+rubocop:
+ inherit:
+ default: false
+ variables: false
+ script: bundle exec rubocop
+
+rspec:
+ inherit:
+ default: [image]
+ variables: [WEBHOOK_URL]
+ script: bundle exec rspec
+
+capybara:
+ inherit:
+ variables: false
+ script: bundle exec capybara
+
+karma:
+ inherit:
+ default: true
+ variables: [DOMAIN]
+ script: karma
+```
+
+In this example:
+
+- `rubocop`:
+ - inherits: Nothing.
+- `rspec`:
+ - inherits: the default `image` and the `WEBHOOK_URL` variable.
+ - does **not** inherit: the default `before_script` and the `DOMAIN` variable.
+- `capybara`:
+ - inherits: the default `before_script` and `image`.
+ - does **not** inherit: the `DOMAIN` and `WEBHOOK_URL` variables.
+- `karma`:
+ - inherits: the default `image` and `before_script`, and the `DOMAIN` variable.
+ - does **not** inherit: `WEBHOOK_URL` variable.
+
## Specifying variables when running manual jobs
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30485) in GitLab 12.2.
diff --git a/doc/ci/jobs/job_control.md b/doc/ci/jobs/job_control.md
index ad2bbbc883c..0f92ae5ca49 100644
--- a/doc/ci/jobs/job_control.md
+++ b/doc/ci/jobs/job_control.md
@@ -179,7 +179,7 @@ job:
```
You should not include both push and merge request pipelines in the same job without
-[`workflow:rules` that prevent duplicate pipelines](../yaml/index.md#switch-between-branch-pipelines-and-merge-request-pipelines):
+[`workflow:rules` that prevent duplicate pipelines](../yaml/workflow.md#switch-between-branch-pipelines-and-merge-request-pipelines):
```yaml
job:
@@ -294,7 +294,7 @@ You can use the `$` character for both variables and paths. For example, if the
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322992) in GitLab 14.3.
-Use [`!reference` tags](../yaml/index.md#reference-tags) to reuse rules in different
+Use [`!reference` tags](../yaml/yaml_optimization.md#reference-tags) to reuse rules in different
jobs. You can combine `!reference` rules with regular job-defined rules:
```yaml
@@ -640,6 +640,106 @@ This job can no longer be scheduled to run automatically. You can, however, exec
To start a delayed job immediately, select **Play** (**{play}**).
Soon GitLab Runner starts the job.
+## Parallelize large jobs
+
+To split a large job into multiple smaller jobs that run in parallel, use the
+[`parallel`](../yaml/index.md#parallel) keyword in your `.gitlab-ci.yml` file.
+
+Different languages and test suites have different methods to enable parallelization.
+For example, use [Semaphore Test Boosters](https://github.com/renderedtext/test-boosters)
+and RSpec to run Ruby tests in parallel:
+
+```ruby
+# Gemfile
+source 'https://rubygems.org'
+
+gem 'rspec'
+gem 'semaphore_test_boosters'
+```
+
+```yaml
+test:
+ parallel: 3
+ script:
+ - bundle
+ - bundle exec rspec_booster --job $CI_NODE_INDEX/$CI_NODE_TOTAL
+```
+
+You can then navigate to the **Jobs** tab of a new pipeline build and see your RSpec
+job split into three separate jobs.
+
+WARNING:
+Test Boosters reports usage statistics to the author.
+
+### Run a one-dimensional matrix of parallel jobs
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26362) in GitLab 13.5.
+
+You can create a one-dimensional matrix of parallel jobs:
+
+```yaml
+deploystacks:
+ stage: deploy
+ script:
+ - bin/deploy
+ parallel:
+ matrix:
+ - PROVIDER: [aws, ovh, gcp, vultr]
+```
+
+You can also [create a multi-dimensional matrix](../yaml/index.md#parallelmatrix).
+
+### Run a matrix of parallel trigger jobs
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/270957) in GitLab 13.10.
+
+You can run a [trigger](../yaml/index.md#trigger) job multiple times in parallel in a single pipeline,
+but with different variable values for each instance of the job.
+
+```yaml
+deploystacks:
+ stage: deploy
+ trigger:
+ include: path/to/child-pipeline.yml
+ parallel:
+ matrix:
+ - PROVIDER: aws
+ STACK: [monitoring, app1]
+ - PROVIDER: ovh
+ STACK: [monitoring, backup]
+ - PROVIDER: [gcp, vultr]
+ STACK: [data]
+```
+
+This example generates 6 parallel `deploystacks` trigger jobs, each with different values
+for `PROVIDER` and `STACK`, and they create 6 different child pipelines with those variables.
+
+```plaintext
+deploystacks: [aws, monitoring]
+deploystacks: [aws, app1]
+deploystacks: [ovh, monitoring]
+deploystacks: [ovh, backup]
+deploystacks: [gcp, data]
+deploystacks: [vultr, data]
+```
+
+In [GitLab 14.1 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/239737), you can
+use the variables defined in `parallel: matrix` with the [`tags`](../yaml/index.md#tags) keyword for
+dynamic runner selection.
+
+```yaml
+deploystacks:
+ stage: deploy
+ parallel:
+ matrix:
+ - PROVIDER: aws
+ STACK: [monitoring, app1]
+ - PROVIDER: gcp
+ STACK: [data]
+ tags:
+ - ${PROVIDER}-${STACK}
+```
+
## Use predefined CI/CD variables to run jobs only in specific pipeline types
You can use [predefined CI/CD variables](../variables/predefined_variables.md) to choose
diff --git a/doc/ci/large_repositories/index.md b/doc/ci/large_repositories/index.md
index 07b4cd80d6a..76e34df1f8c 100644
--- a/doc/ci/large_repositories/index.md
+++ b/doc/ci/large_repositories/index.md
@@ -250,12 +250,14 @@ concurrent = 4
This makes the cloning configuration to be part of the given runner
and does not require us to update each `.gitlab-ci.yml`.
-## Pre-clone step
+## Git fetch caching or pre-clone step
-> [An issue exists](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/463) to remove the need for this optimization.
+For very active repositories with a large number of references and files, you can either (or both):
-For very active repositories with a large number of references and files, you can also
-optimize your CI jobs by seeding repository data with GitLab Runner's [`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section).
-
-See [our development documentation](../../development/pipelines.md#pre-clone-step) for
-an overview of how we implemented this approach on GitLab.com for the main GitLab repository.
+- Consider using the [Gitaly pack-objects cache](../../administration/gitaly/configure_gitaly.md#pack-objects-cache) instead of a
+ pre-clone step. This is easier to set up and it benefits all repositories on your GitLab server, unlike the pre-clone step that
+ must be configured per-repository. The pack-objects cache also automatically works for forks. On GitLab.com, where the pack-objects cache is
+ enabled on all Gitaly servers, we found that we no longer need a pre-clone step for `gitlab-org/gitlab` development.
+- Optimize your CI/CD jobs by seeding repository data in a pre-clone step with the
+ [`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) of GitLab Runner. See the
+ [Runner Cloud for Linux](../runners/runner_cloud/linux_runner_cloud.md#pre-clone-script) for more details.
diff --git a/doc/ci/lint.md b/doc/ci/lint.md
index 45152e5a0df..e58907ee0bd 100644
--- a/doc/ci/lint.md
+++ b/doc/ci/lint.md
@@ -14,6 +14,9 @@ issues as well.
To access the CI Lint tool, navigate to **CI/CD > Pipelines** or **CI/CD > Jobs**
in your project and click **CI lint**.
+If you use VS Code, you can also validate your CI/CD configuration with the
+[GitLab Workflow VS Code extension](../user/project/repository/vscode.md).
+
## Validate basic logic and syntax
By default, the CI lint checks the syntax of your CI YAML configuration and also runs
diff --git a/doc/ci/pipeline_editor/index.md b/doc/ci/pipeline_editor/index.md
index 10a6d34b076..5be016aff40 100644
--- a/doc/ci/pipeline_editor/index.md
+++ b/doc/ci/pipeline_editor/index.md
@@ -82,8 +82,8 @@ where:
- Configuration imported with [`include`](../yaml/index.md#include) is copied into the view.
- Jobs that use [`extends`](../yaml/index.md#extends) display with the
- [extended configuration merged into the job](../yaml/index.md#merge-details).
-- YAML anchors are [replaced with the linked configuration](../yaml/index.md#anchors).
+ [extended configuration merged into the job](../yaml/yaml_optimization.md#merge-details).
+- YAML anchors are [replaced with the linked configuration](../yaml/yaml_optimization.md#anchors).
## Commit changes to CI configuration
diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md
index 69e974406e2..24e518b1f69 100644
--- a/doc/ci/pipelines/index.md
+++ b/doc/ci/pipelines/index.md
@@ -77,7 +77,7 @@ You can also configure specific aspects of your pipelines through the GitLab UI.
- [Pipeline schedules](schedules.md).
- [Custom CI/CD variables](../variables/index.md#custom-cicd-variables).
-### Ref Specs for Runners
+### Ref specs for runners
When a runner picks a pipeline job, GitLab provides that job's metadata. This includes the [Git refspecs](https://git-scm.com/book/en/v2/Git-Internals-The-Refspec),
which indicate which ref (branch, tag, and so on) and commit (SHA1) are checked out from your
@@ -87,9 +87,9 @@ This table lists the refspecs injected for each pipeline type:
| Pipeline type | Refspecs |
|--------------- |---------------------------------------- |
-| Pipeline for Branches | `+<sha>:refs/pipelines/<id>` and `+refs/heads/<name>:refs/remotes/origin/<name>` |
-| pipeline for Tags | `+<sha>:refs/pipelines/<id>` and `+refs/tags/<name>:refs/tags/<name>` |
-| [Pipeline for Merge Requests](../pipelines/merge_request_pipelines.md) | `+<sha>:refs/pipelines/<id>` |
+| pipeline for branches | `+<sha>:refs/pipelines/<id>` and `+refs/heads/<name>:refs/remotes/origin/<name>` |
+| pipeline for tags | `+<sha>:refs/pipelines/<id>` and `+refs/tags/<name>:refs/tags/<name>` |
+| [pipeline for merge requests](../pipelines/merge_request_pipelines.md) | `+<sha>:refs/pipelines/<id>` |
The refs `refs/heads/<name>` and `refs/tags/<name>` exist in your
project repository. GitLab generates the special ref `refs/pipelines/<id>` during a
@@ -127,6 +127,11 @@ you can filter the pipeline list by:
[Starting in GitLab 14.2](https://gitlab.com/gitlab-org/gitlab/-/issues/26621), you can change the
pipeline column to display the pipeline ID or the pipeline IID.
+If you use VS Code to edit your GitLab CI/CD configuration, the
+[GitLab Workflow VS Code extension](../../user/project/repository/vscode.md) helps you
+[validate your configuration](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#validate-gitlab-ci-configuration)
+and [view your pipeline status](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#information-about-your-branch-pipelines-mr-closing-issue).
+
### Run a pipeline manually
Pipelines can be manually executed, with predefined or manually-specified [variables](../variables/index.md).
@@ -150,7 +155,7 @@ The pipeline now executes the jobs as configured.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30101) in GitLab 13.7.
-You can use the [`value` and `description`](../yaml/index.md#prefill-variables-in-manual-pipelines)
+You can use the [`value` and `description`](../yaml/index.md#variablesdescription)
keywords to define
[pipeline-level (global) variables](../variables/index.md#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file)
that are prefilled when running a pipeline manually.
@@ -159,7 +164,7 @@ In pipelines triggered manually, the **Run pipelines** page displays all top-lev
with a `description` and `value` defined in the `.gitlab-ci.yml` file. The values
can then be modified if needed, which overrides the value for that single pipeline run.
-The description is displayed below the variable. It can be used to explain what
+The description is displayed next to the variable. It can be used to explain what
the variable is used for, what the acceptable values are, and so on:
```yaml
@@ -229,6 +234,15 @@ This functionality is only available:
- For users with at least the Developer role.
- If the stage contains [manual actions](#add-manual-interaction-to-your-pipeline).
+### Skip a pipeline
+
+To push a commit without triggering a pipeline, add `[ci skip]` or `[skip ci]`, using any
+capitalization, to your commit message.
+
+Alternatively, if you are using Git 2.10 or later, use the `ci.skip` [Git push option](../../user/project/push_options.md#push-options-for-gitlab-cicd).
+The `ci.skip` push option does not skip merge request
+pipelines.
+
### Delete a pipeline
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24851) in GitLab 12.7.
@@ -391,6 +405,7 @@ be found when you go to:
- The pipelines index page.
- A single commit page.
- A merge request page.
+- The [pipeline editor](../pipeline_editor/index.md), [in GitLab 14.5](https://gitlab.com/gitlab-org/gitlab/-/issues/337514) and later.
Pipeline mini graphs allow you to see all related jobs for a single commit and the net result
of each stage of your pipeline. This allows you to quickly see what failed and
diff --git a/doc/ci/pipelines/merge_request_pipelines.md b/doc/ci/pipelines/merge_request_pipelines.md
index 5b40744aa79..119633d38e2 100644
--- a/doc/ci/pipelines/merge_request_pipelines.md
+++ b/doc/ci/pipelines/merge_request_pipelines.md
@@ -45,7 +45,7 @@ To do this, you can use [`rules`](#use-rules-to-run-pipelines-for-merge-requests
### Use `rules` to run pipelines for merge requests
GitLab recommends that you use the `rules` keyword, which is available in
-[`workflow:rules` templates](../yaml/index.md#workflowrules-templates).
+[`workflow:rules` templates](../yaml/workflow.md#workflowrules-templates).
### Use `only` or `except` to run pipelines for merge requests
@@ -199,7 +199,7 @@ If you are seeing two pipelines when using `only/except`, please see the caveats
related to using `only/except` above (or, consider moving to `rules`).
In [GitLab 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/201845),
-you can add `workflow:rules` to [switch from branch pipelines to merge request pipelines](../yaml/index.md#switch-between-branch-pipelines-and-merge-request-pipelines).
+you can add `workflow:rules` to [switch from branch pipelines to merge request pipelines](../yaml/workflow.md#switch-between-branch-pipelines-and-merge-request-pipelines).
After a merge request is open on the branch, the pipeline switches to a merge request pipeline.
### Two pipelines created when pushing an invalid CI configuration file
diff --git a/doc/ci/pipelines/multi_project_pipelines.md b/doc/ci/pipelines/multi_project_pipelines.md
index 184961f4c95..30b3bc2e277 100644
--- a/doc/ci/pipelines/multi_project_pipelines.md
+++ b/doc/ci/pipelines/multi_project_pipelines.md
@@ -88,7 +88,7 @@ The keywords available for use in trigger jobs are:
- [`only` and `except`](../yaml/index.md#only--except)
- [`when`](../yaml/index.md#when) (only with a value of `on_success`, `on_failure`, or `always`)
- [`extends`](../yaml/index.md#extends)
-- [`needs`](../yaml/index.md#needs), but not [cross project artifact downloads with `needs`](../yaml/index.md#cross-project-artifact-downloads-with-needs)
+- [`needs`](../yaml/index.md#needs), but not [`needs:project`](../yaml/index.md#needsproject)
#### Specify a downstream pipeline branch
@@ -154,7 +154,7 @@ trigger-downstream:
trigger: my/project
```
-You can stop global variables from reaching the downstream pipeline by using the [`inherit` keyword](../yaml/index.md#inherit).
+You can stop global variables from reaching the downstream pipeline by using the [`inherit:variables` keyword](../yaml/index.md#inheritvariables).
In this example, the `MY_GLOBAL_VAR` variable is not available in the triggered pipeline:
```yaml
@@ -190,7 +190,7 @@ the ones defined in the upstream project take precedence.
#### Pass CI/CD variables to a downstream pipeline by using variable inheritance
-You can pass variables to a downstream pipeline with [`dotenv` variable inheritance](../variables/index.md#pass-an-environment-variable-to-another-job) and [cross project artifact downloads](../yaml/index.md#cross-project-artifact-downloads-with-needs).
+You can pass variables to a downstream pipeline with [`dotenv` variable inheritance](../variables/index.md#pass-an-environment-variable-to-another-job) and [`needs:project`](../yaml/index.md#needsproject).
In the upstream pipeline:
@@ -254,21 +254,6 @@ trigger_job:
strategy: depend
```
-#### Mirror status from upstream pipeline
-
-You can mirror the pipeline status from an upstream pipeline to a bridge job by
-using the `needs:pipeline` keyword. The latest pipeline status from the default branch is
-replicated to the bridge job.
-
-For example:
-
-```yaml
-upstream_bridge:
- stage: test
- needs:
- pipeline: other/project
-```
-
### Create multi-project pipelines by using the API
> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/31573) to GitLab Free in 12.4.
diff --git a/doc/ci/pipelines/parent_child_pipelines.md b/doc/ci/pipelines/parent_child_pipelines.md
index e48728a904a..64f4160c963 100644
--- a/doc/ci/pipelines/parent_child_pipelines.md
+++ b/doc/ci/pipelines/parent_child_pipelines.md
@@ -81,7 +81,8 @@ microservice_a:
trigger:
include:
- project: 'my-group/my-pipeline-library'
- file: 'path/to/ci-config.yml'
+ ref: 'main'
+ file: '/path/to/child-pipeline.yml'
```
The maximum number of entries that are accepted for `trigger:include:` is three.
@@ -98,7 +99,7 @@ microservice_a:
strategy: depend
```
-## Merge Request child pipelines
+## Merge request child pipelines
To trigger a child pipeline as a [Merge Request Pipeline](merge_request_pipelines.md) we need to:
@@ -149,7 +150,7 @@ microservice_a:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35632) in GitLab 12.9.
Instead of running a child pipeline from a static YAML file, you can define a job that runs
-your own script to generate a YAML file, which is then [used to trigger a child pipeline](../yaml/index.md#trigger-child-pipeline-with-generated-configuration-file).
+your own script to generate a YAML file, which is then used to trigger a child pipeline.
This technique can be very powerful in generating pipelines targeting content that changed or to
build a matrix of targets and architectures.
@@ -171,6 +172,31 @@ configuration for jobs, like scripts, that use the Windows runner would use `\`.
In GitLab 12.9, the child pipeline could fail to be created in certain cases, causing the parent pipeline to fail.
This is [resolved](https://gitlab.com/gitlab-org/gitlab/-/issues/209070) in GitLab 12.10.
+### Dynamic child pipeline example
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35632) in GitLab 12.9.
+
+You can trigger a child pipeline from a [dynamically generated configuration file](../pipelines/parent_child_pipelines.md#dynamic-child-pipelines):
+
+```yaml
+generate-config:
+ stage: build
+ script: generate-ci-config > generated-config.yml
+ artifacts:
+ paths:
+ - generated-config.yml
+
+child-pipeline:
+ stage: test
+ trigger:
+ include:
+ - artifact: generated-config.yml
+ job: generate-config
+```
+
+The `generated-config.yml` is extracted from the artifacts and used as the configuration
+for triggering the child pipeline.
+
## Nested child pipelines
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29651) in GitLab 13.4.
diff --git a/doc/ci/pipelines/pipeline_artifacts.md b/doc/ci/pipelines/pipeline_artifacts.md
index 55555571f97..b174b6af9f9 100644
--- a/doc/ci/pipelines/pipeline_artifacts.md
+++ b/doc/ci/pipelines/pipeline_artifacts.md
@@ -7,20 +7,24 @@ type: reference, howto
# Pipeline artifacts **(FREE)**
-Pipeline artifacts are files created by GitLab after a pipeline finishes. These are different than [job artifacts](job_artifacts.md) because they are not explicitly managed by the `.gitlab-ci.yml` definitions.
+Pipeline artifacts are files created by GitLab after a pipeline finishes. Pipeline artifacts are
+different to [job artifacts](job_artifacts.md) because they are not explicitly managed by
+`.gitlab-ci.yml` definitions.
-Pipeline artifacts are used by the [test coverage visualization feature](../../user/project/merge_requests/test_coverage_visualization.md) to collect coverage information. It uses the [`artifacts: reports`](../yaml/index.md#artifactsreports) CI/CD keyword.
+Pipeline artifacts are used by the [test coverage visualization feature](../../user/project/merge_requests/test_coverage_visualization.md)
+to collect coverage information. It uses the [`artifacts: reports`](../yaml/index.md#artifactsreports) CI/CD keyword.
## Storage
-Pipeline artifacts are saved to disk or object storage. They count towards a project's [storage usage quota](../../user/usage_quotas.md#storage-usage-quota). The **Artifacts** on the Usage Quotas page is the sum of all job artifacts and pipeline artifacts.
+Pipeline artifacts are saved to disk or object storage. They count towards a project's [storage usage quota](../../user/usage_quotas.md#storage-usage-quota).
+The **Artifacts** on the Usage Quotas page is the sum of all job artifacts and pipeline artifacts.
## When pipeline artifacts are deleted
-Pipeline artifacts are deleted either:
+Pipeline artifacts from:
-- Seven days after creation.
-- After another pipeline runs successfully, if they are from the most recent successful
- pipeline.
+- The latest pipeline are kept forever.
+- Pipelines superseded by a newer pipeline are deleted seven days after their creation date.
-This deletion may take up to two days.
+It can take up to two days for GitLab to delete pipeline artifacts from when they are due to be
+deleted.
diff --git a/doc/ci/pipelines/schedules.md b/doc/ci/pipelines/schedules.md
index 90494a715ea..692460120fe 100644
--- a/doc/ci/pipelines/schedules.md
+++ b/doc/ci/pipelines/schedules.md
@@ -12,14 +12,16 @@ Pipelines are normally run based on certain conditions being met. For example, w
Pipeline schedules can be used to also run [pipelines](index.md) at specific intervals. For example:
-- Every month on the 22nd for a certain branch.
-- Once every day.
+- Every month on the 22nd (cron example: `0 0 22 * *`) for a certain branch.
+- Every month on the 2nd Monday (cron example: `0 0 * * 1#2`).
+- Every other Sunday at 0900 hours (cron example: `0 9 * * sun%2`).
+- Once every day (cron example: `0 0 * * *`).
+
+Schedule timing is configured with cron notation, parsed by [Fugit](https://github.com/floraison/fugit).
In addition to using the GitLab UI, pipeline schedules can be maintained using the
[Pipeline schedules API](../../api/pipeline_schedules.md).
-Schedule timing is configured with cron notation, parsed by [Fugit](https://github.com/floraison/fugit).
-
## Prerequisites
In order for a scheduled pipeline to be created successfully:
diff --git a/doc/ci/pipelines/settings.md b/doc/ci/pipelines/settings.md
index e14c1aa621f..a8ecb5e0d74 100644
--- a/doc/ci/pipelines/settings.md
+++ b/doc/ci/pipelines/settings.md
@@ -78,7 +78,7 @@ To avoid this scenario:
1. Select the **Skip outdated deployment jobs** checkbox.
1. Select **Save changes**.
-Older deployment job are skipped when a new deployment starts.
+Older deployment jobs are skipped when a new deployment starts.
For more information, see [Deployment safety](../environments/deployment_safety.md).
diff --git a/doc/ci/quick_start/index.md b/doc/ci/quick_start/index.md
index 4006a1c9c3c..77a666c0cca 100644
--- a/doc/ci/quick_start/index.md
+++ b/doc/ci/quick_start/index.md
@@ -119,6 +119,11 @@ The pipeline starts when the commit is committed.
#### `.gitlab-ci.yml` tips
+- After you create your first `.gitlab-ci.yml` file, use the [pipeline editor](../pipeline_editor/index.md)
+ for all future edits to the file. With the pipeline editor, you can:
+ - Edit the pipeline configuration with automatic syntax highlighting and validation.
+ - View the [CI/CD configuration visualization](../pipeline_editor/index.md#visualize-ci-configuration),
+ a graphical representation of your `.gitlab-ci.yml` file.
- If you want the runner to [use a Docker container to run the jobs](../docker/using_docker_images.md),
edit the `.gitlab-ci.yml` file
to include an image name:
@@ -136,12 +141,8 @@ The pipeline starts when the commit is committed.
Your application does not need to be built as a Docker container to
run CI/CD jobs in Docker containers.
-- To validate your `.gitlab-ci.yml` file, use the
- [CI Lint tool](../lint.md), which is available in every project.
-- You can also use [CI/CD configuration visualization](../pipeline_editor/index.md#visualize-ci-configuration) to
- view a graphical representation of your `.gitlab-ci.yml` file.
- Each job contains scripts and stages:
- - The [`default`](../yaml/index.md#custom-default-keyword-values) keyword is for
+ - The [`default`](../yaml/index.md#default) keyword is for
custom defaults, for example with [`before_script`](../yaml/index.md#before_script)
and [`after_script`](../yaml/index.md#after_script).
- [`stage`](../yaml/index.md#stage) describes the sequential execution of jobs.
diff --git a/doc/ci/resource_groups/index.md b/doc/ci/resource_groups/index.md
index 7de3643c0d4..25dacc9c437 100644
--- a/doc/ci/resource_groups/index.md
+++ b/doc/ci/resource_groups/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
description: Control the job concurrency in GitLab CI/CD
---
-# Resource Group **(FREE)**
+# Resource group **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15536) in GitLab 12.7.
@@ -13,7 +13,7 @@ By default, pipelines in GitLab CI/CD run in parallel. The parallelization is an
the feedback loop in merge requests, however, there are some situations that
you may want to limit the concurrency on deployment
jobs to run them one by one.
-Resource Group allows you to strategically control
+Use resource groups to strategically control
the concurrency of the jobs for optimizing your continuous deployments workflow with safety.
## Add a resource group
@@ -139,9 +139,59 @@ Depending on the process mode of the resource group:
- `deploy-1`, `deploy-2`, and `deploy-3` do not run in parallel.
- `deploy-3` runs first, `deploy-2` runs second and `deploy-1` runs last.
-## Pipeline-level concurrency control with Cross-Project/Parent-Child pipelines
+## Pipeline-level concurrency control with cross-project/parent-child pipelines
-See the how to [control the pipeline concurrency in cross-project pipelines](../yaml/index.md#pipeline-level-concurrency-control-with-cross-projectparent-child-pipelines).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39057) in GitLab 13.9.
+
+You can define `resource_group` for downstream pipelines that are sensitive to concurrent
+executions. The [`trigger` keyword](../yaml/index.md#trigger) can trigger downstream pipelines and the
+[`resource_group` keyword](../yaml/index.md#resource_group) can co-exist with it. `resource_group` is useful to control the
+concurrency of deployment pipelines, while other jobs can continue to run concurrently.
+
+The following example has two pipeline configurations in a project. When a pipeline starts running,
+non-sensitive jobs are executed first and aren't affected by concurrent executions in other
+pipelines. However, GitLab ensures that there are no other deployment pipelines running before
+triggering a deployment (child) pipeline. If other deployment pipelines are running, GitLab waits
+until those pipelines finish before running another one.
+
+```yaml
+# .gitlab-ci.yml (parent pipeline)
+
+build:
+ stage: build
+ script: echo "Building..."
+
+test:
+ stage: test
+ script: echo "Testing..."
+
+deploy:
+ stage: deploy
+ trigger:
+ include: deploy.gitlab-ci.yml
+ strategy: depend
+ resource_group: AWS-production
+```
+
+```yaml
+# deploy.gitlab-ci.yml (child pipeline)
+
+stages:
+ - provision
+ - deploy
+
+provision:
+ stage: provision
+ script: echo "Provisioning..."
+
+deployment:
+ stage: deploy
+ script: echo "Deploying..."
+```
+
+You must define [`strategy: depend`](../yaml/index.md#triggerstrategy)
+with the `trigger` keyword. This ensures that the lock isn't released until the downstream pipeline
+finishes.
## API
@@ -177,7 +227,7 @@ deploy:
```
In a parent pipeline, it runs the `test` job that subsequently runs a child pipeline,
-and the [`strategy: depend` option](../yaml/index.md#linking-pipelines-with-triggerstrategy) makes the `test` job wait until the child pipeline has finished.
+and the [`strategy: depend` option](../yaml/index.md#triggerstrategy) makes the `test` job wait until the child pipeline has finished.
The parent pipeline runs the `deploy` job in the next stage, that requires a resource from the `production` resource group.
If the process mode is `oldest_first`, it executes the jobs from the oldest pipelines, meaning the `deploy` job is going to be executed next.
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index 1b926d506c4..c67282643a4 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -1,6 +1,6 @@
---
-stage: Release
-group: Release
+stage: Verify
+group: Testing
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
type: reference
---
@@ -98,6 +98,7 @@ The following are example projects that demonstrate Review App configuration:
- [NGINX](https://gitlab.com/gitlab-examples/review-apps-nginx).
- [OpenShift](https://gitlab.com/gitlab-examples/review-apps-openshift).
+- [HashiCorp Nomad](https://gitlab.com/gitlab-examples/review-apps-nomad).
Other examples of Review Apps:
diff --git a/doc/ci/runners/build_cloud/linux_build_cloud.md b/doc/ci/runners/build_cloud/linux_build_cloud.md
index 6cdc93591a7..e8bad31c821 100644
--- a/doc/ci/runners/build_cloud/linux_build_cloud.md
+++ b/doc/ci/runners/build_cloud/linux_build_cloud.md
@@ -1,127 +1,9 @@
---
-stage: Verify
-group: Runner
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../runner_cloud/linux_runner_cloud.md'
+remove_date: '2022-02-05'
---
-# Build Cloud runners for Linux **(FREE)**
+This document was moved to [another location](../runner_cloud/linux_runner_cloud.md).
-GitLab Build Cloud runners for Linux run in autoscale mode and are powered by Google Cloud Platform.
-
-Autoscaling means reduced queue times to spin up CI/CD jobs, and isolated VMs for each job, thus maximizing security. These shared runners are available on GitLab.com.
-
-GitLab offers Ultimate tier capabilities and included CI/CD minutes per group per month for our [Open Source](https://about.gitlab.com/solutions/open-source/join/), [Education](https://about.gitlab.com/solutions/education/), and [Startups](https://about.gitlab.com/solutions/startups/) programs. For private projects, GitLab offers various [plans](https://about.gitlab.com/pricing/), starting with a Free tier.
-
-All your CI/CD jobs run on [n1-standard-1 instances](https://cloud.google.com/compute/docs/machine-types) with 3.75GB of RAM, CoreOS and the latest Docker Engine
-installed. Instances provide 1 vCPU and 25GB of HDD disk space. The default
-region of the VMs is US East1.
-Each instance is used only for one job. This ensures that any sensitive data left on the system can't be accessed by other people's CI/CD jobs.
-
-The `gitlab-shared-runners-manager-X.gitlab.com` fleet of runners are dedicated for GitLab projects as well as community forks of them. They use a slightly larger machine type (n1-standard-2) and have a bigger SSD disk size. They don't run untagged jobs and unlike the general fleet of shared runners, the instances are re-used up to 40 times.
-
-Jobs handled by the shared runners on GitLab.com (`shared-runners-manager-X.gitlab.com`),
-**time out after 3 hours**, regardless of the timeout configured in a
-project. Check the issues [#4010](https://gitlab.com/gitlab-com/infrastructure/-/issues/4010) and [#4070](https://gitlab.com/gitlab-com/infrastructure/-/issues/4070) for the reference.
-
-Below are the runners' settings.
-
-| Setting | GitLab.com | Default |
-| ----------- | ----------------- | ---------- |
-| Executor | `docker+machine` | - |
-| Default Docker image | `ruby:2.5` | - |
-| `privileged` (run [Docker in Docker](https://hub.docker.com/_/docker/)) | `true` | `false` |
-
-## Pre-clone script
-
-Build Cloud runners for Linux provide a way to run commands in a CI
-job before the runner attempts to run `git init` and `git fetch` to
-download a GitLab repository. The
-[`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
-can be used for:
-
-- Seeding the build directory with repository data
-- Sending a request to a server
-- Downloading assets from a CDN
-- Any other commands that must run before the `git init`
-
-To use this feature, define a [CI/CD variable](../../../ci/variables/index.md#custom-cicd-variables) called
-`CI_PRE_CLONE_SCRIPT` that contains a bash script.
-
-[This example](../../../development/pipelines.md#pre-clone-step)
-demonstrates how you might use a pre-clone step to seed the build
-directory.
-
-NOTE:
-The `CI_PRE_CLONE_SCRIPT` variable does not work on Windows runners.
-
-## `config.toml`
-
-The full contents of our `config.toml` are:
-
-NOTE:
-Settings that are not public are shown as `X`.
-
-**Google Cloud Platform**
-
-```toml
-concurrent = X
-check_interval = 1
-metrics_server = "X"
-sentry_dsn = "X"
-
-[[runners]]
- name = "docker-auto-scale"
- request_concurrency = X
- url = "https://gitlab.com/"
- token = "SHARED_RUNNER_TOKEN"
- pre_clone_script = "eval \"$CI_PRE_CLONE_SCRIPT\""
- executor = "docker+machine"
- environment = [
- "DOCKER_DRIVER=overlay2",
- "DOCKER_TLS_CERTDIR="
- ]
- limit = X
- [runners.docker]
- image = "ruby:2.5"
- privileged = true
- volumes = [
- "/certs/client",
- "/dummy-sys-class-dmi-id:/sys/class/dmi/id:ro" # Make kaniko builds work on GCP.
- ]
- [runners.machine]
- IdleCount = 50
- IdleTime = 3600
- MaxBuilds = 1 # For security reasons we delete the VM after job has finished so it's not reused.
- MachineName = "srm-%s"
- MachineDriver = "google"
- MachineOptions = [
- "google-project=PROJECT",
- "google-disk-size=25",
- "google-machine-type=n1-standard-1",
- "google-username=core",
- "google-tags=gitlab-com,srm",
- "google-use-internal-ip",
- "google-zone=us-east1-d",
- "engine-opt=mtu=1460", # Set MTU for container interface, for more information check https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3214#note_82892928
- "google-machine-image=PROJECT/global/images/IMAGE",
- "engine-opt=ipv6", # This will create IPv6 interfaces in the containers.
- "engine-opt=fixed-cidr-v6=fc00::/7",
- "google-operation-backoff-initial-interval=2" # Custom flag from forked docker-machine, for more information check https://github.com/docker/machine/pull/4600
- ]
- [[runners.machine.autoscaling]]
- Periods = ["* * * * * sat,sun *"]
- Timezone = "UTC"
- IdleCount = 70
- IdleTime = 3600
- [[runners.machine.autoscaling]]
- Periods = ["* 30-59 3 * * * *", "* 0-30 4 * * * *"]
- Timezone = "UTC"
- IdleCount = 700
- IdleTime = 3600
- [runners.cache]
- Type = "gcs"
- Shared = true
- [runners.cache.gcs]
- CredentialsFile = "/path/to/file"
- BucketName = "bucket-name"
-```
+<!-- This redirect file can be deleted after 2022-02-05. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/runners/build_cloud/macos/environment.md b/doc/ci/runners/build_cloud/macos/environment.md
index 8a2417186ae..aaef0d07098 100644
--- a/doc/ci/runners/build_cloud/macos/environment.md
+++ b/doc/ci/runners/build_cloud/macos/environment.md
@@ -1,43 +1,9 @@
---
-stage: Verify
-group: Runner
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../runner_cloud/macos/environment.md'
+remove_date: '2022-02-05'
---
-# VM instances and images for Build Cloud for macOS **(FREE)**
+This document was moved to [another location](../../runner_cloud/macos/environment.md).
-When you use the Build Cloud for macOS:
-
-- Each of your jobs runs in a newly provisioned VM, which is dedicated to the specific job.
-- The VM is active only for the duration of the job and immediately deleted.
-
-## VM types
-
-The virtual machine where your job runs has `sudo` access with no password.
-For the Beta, there is only one available machine type, `gbc-macos-large`.
-
-| Instance type | vCPUS | Memory (GB) |
-| --------- | --- | ------- |
-| `gbc-macos-large` | 4 | 10 |
-
-## VM images
-
-You can execute your build on one of the following images.
-You specify this image in your `.gitlab-ci.yml` file.
-
-Each image is running a specific version of macOS and Xcode.
-
-| VM image | Included software |
-|---------------------------|--------------------|
-| macos-10.13-xcode-7 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
-| macos-10.13-xcode-8 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
-| macos-10.13-xcode-9 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
-| macos-10.14-xcode-10 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/mojave.yml> |
-| macos-10.15-xcode-11 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/catalina.yml> |
-| macos-11-xcode-12 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/big-sur.yml> |
-
-### Image update policy
-
-- Support for new macOS versions is planned.
-- Additional details on the support policy and image update release process are documented
- [in this project](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/55bf59c8fa88712960afff2bf6ecc5daa879a8f5/docs/overview.md#os-images).
+<!-- This redirect file can be deleted after 2022-02-05. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/runners/build_cloud/macos_build_cloud.md b/doc/ci/runners/build_cloud/macos_build_cloud.md
index 5d55462fb63..e478f93f34c 100644
--- a/doc/ci/runners/build_cloud/macos_build_cloud.md
+++ b/doc/ci/runners/build_cloud/macos_build_cloud.md
@@ -1,62 +1,9 @@
---
-stage: Verify
-group: Runner
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../runner_cloud/macos_runner_cloud.md'
+remove_date: '2022-02-05'
---
-# Build Cloud runners for macOS (Beta) **(FREE SAAS)**
+This document was moved to [another location](../runner_cloud/macos_runner_cloud.md).
-The GitLab Build Cloud for macOS Beta provides on-demand runners integrated with GitLab SaaS [CI/CD](../../../ci/index.md).
-Use these runners to build, test, and deploy apps for the Apple ecosystem (macOS, iOS, tvOS). You can take advantage
-of all the capabilities of the GitLab single DevOps platform and not have to manage or operate a
-build environment.
-
-Build Cloud runners for macOS are in [Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
-and shouldn't be relied upon for mission-critical production jobs.
-
-## Quickstart
-
-To start using Build Cloud for macOS Beta, you must submit an access request [issue](https://gitlab.com/gitlab-com/macos-buildcloud-runners-beta/-/issues/new?issuable_template=beta_access_request). After your
-access has been granted and your build environment configured, you must configure your
-`.gitlab-ci.yml` pipeline file:
-
-1. Add a `.gitlab-ci.yml` file to your project repository.
-1. Specify the [image](macos/environment.md#vm-images) you want to use.
-1. Commit a change to your repository.
-
-The runners automatically run your build.
-
-## Example `.gitlab-ci.yml` file
-
-The following sample `.gitlab-ci.yml` file shows how to start using the runners for macOS:
-
-```yaml
-.macos_buildcloud_runners:
- tags:
- - shared-macos-amd64
- image: macos-11-xcode-12
-
-stages:
- - build
- - test
-
-before_script:
- - echo "started by ${GITLAB_USER_NAME}"
-
-build:
- extends:
- - .macos_buildcloud_runners
- stage: build
- script:
- - echo "running scripts in the build job"
-
-test:
- extends:
- - .macos_buildcloud_runners
- stage: test
- script:
- - echo "running scripts in the test job"
-```
-
-NOTE:
-During the Beta period, the architecture of this solution will change. Rather than the jobs running on a specific VM instance, they will run on an ephemeral VM instance that is created by an autoscaling instance, known as the Runner Manager. We will notify all Beta participants of any downtime required to do this work.
+<!-- This redirect file can be deleted after 2022-02-05. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/runners/build_cloud/windows_build_cloud.md b/doc/ci/runners/build_cloud/windows_build_cloud.md
index e01de723055..8d57ecf27ed 100644
--- a/doc/ci/runners/build_cloud/windows_build_cloud.md
+++ b/doc/ci/runners/build_cloud/windows_build_cloud.md
@@ -1,155 +1,9 @@
---
-stage: Verify
-group: Runner
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../runner_cloud/windows_runner_cloud.md'
+remove_date: '2022-02-05'
---
-# Build Cloud runners for Windows (beta) **(FREE)**
+This document was moved to [another location](../runner_cloud/windows_runner_cloud.md).
-GitLab Build Cloud runners for Windows are in [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
-and shouldn't be used for production workloads.
-
-During this beta period, the [shared runner pipeline quota](../../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota)
-applies for groups and projects in the same manner as Linux runners. This may
-change when the beta period ends, as discussed in this [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/30834).
-
-Windows runners on GitLab.com autoscale by launching virtual machines on
-the Google Cloud Platform. This solution uses an
-[autoscaling driver](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md)
-developed by GitLab for the [custom executor](https://docs.gitlab.com/runner/executors/custom.html).
-Windows runners execute your CI/CD jobs on `n1-standard-2` instances with
-2 vCPUs and 7.5 GB RAM. You can find a full list of available Windows packages in
-the [package documentation](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/main/cookbooks/preinstalled-software/README.md).
-
-We want to keep iterating to get Windows runners in a stable state and
-[generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga).
-You can follow our work towards this goal in the
-[related epic](https://gitlab.com/groups/gitlab-org/-/epics/2162).
-
-## Configuration
-
-The full contents of our `config.toml` are:
-
-NOTE:
-Settings that aren't public are shown as `X`.
-
-```toml
-concurrent = X
-check_interval = 3
-
-[[runners]]
- name = "windows-runner"
- url = "https://gitlab.com/"
- token = "TOKEN"
- executor = "custom"
- builds_dir = "C:\\GitLab-Runner\\builds"
- cache_dir = "C:\\GitLab-Runner\\cache"
- shell = "powershell"
- [runners.custom]
- config_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
- config_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "config"]
- prepare_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
- prepare_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "prepare"]
- run_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
- run_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "run"]
- cleanup_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
- cleanup_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "cleanup"]
-```
-
-The full contents of our `autoscaler/config.toml` are:
-
-```toml
-Provider = "gcp"
-Executor = "winrm"
-OS = "windows"
-LogLevel = "info"
-LogFormat = "text"
-LogFile = "C:\\GitLab-Runner\\autoscaler\\autoscaler.log"
-VMTag = "windows"
-
-[GCP]
- ServiceAccountFile = "PATH"
- Project = "some-project-df9323"
- Zone = "us-east1-c"
- MachineType = "n1-standard-2"
- Image = "IMAGE"
- DiskSize = 50
- DiskType = "pd-standard"
- Subnetwork = "default"
- Network = "default"
- Tags = ["TAGS"]
- Username = "gitlab_runner"
-
-[WinRM]
- MaximumTimeout = 3600
- ExecutionMaxRetries = 0
-
-[ProviderCache]
- Enabled = true
- Directory = "C:\\GitLab-Runner\\autoscaler\\machines"
-```
-
-## Example `.gitlab-ci.yml` file
-
-Below is a sample `.gitlab-ci.yml` file that shows how to start using the runners for Windows:
-
-```yaml
-.shared_windows_runners:
- tags:
- - shared-windows
- - windows
- - windows-1809
-
-stages:
- - build
- - test
-
-before_script:
- - Set-Variable -Name "time" -Value (date -Format "%H:%m")
- - echo ${time}
- - echo "started by ${GITLAB_USER_NAME}"
-
-build:
- extends:
- - .shared_windows_runners
- stage: build
- script:
- - echo "running scripts in the build job"
-
-test:
- extends:
- - .shared_windows_runners
- stage: test
- script:
- - echo "running scripts in the test job"
-```
-
-## Limitations and known issues
-
-- All the limitations mentioned in our [beta
- definition](https://about.gitlab.com/handbook/product/#beta).
-- The average provisioning time for a new Windows VM is 5 minutes.
- This means that you may notice slower build start times
- on the Windows runner fleet during the beta. In a future
- release we intend to update the autoscaler to enable
- the pre-provisioning of virtual machines. This is intended to significantly reduce
- the time it takes to provision a VM on the Windows fleet. You can
- follow along in the [related issue](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/-/issues/32).
-- The Windows runner fleet may be unavailable occasionally
- for maintenance or updates.
-- The Windows runner virtual machine instances do not use the
- GitLab Docker executor. This means that you can't specify
- [`image`](../../../ci/yaml/index.md#image) or [`services`](../../../ci/yaml/index.md#services) in
- your pipeline configuration.
-- For the beta release, we have included a set of software packages in
- the base VM image. If your CI job requires additional software that's
- not included in this list, then you must add installation
- commands to [`before_script`](../../../ci/yaml/index.md#before_script) or [`script`](../../../ci/yaml/index.md#script) to install the required
- software. Note that each job runs on a new VM instance, so the
- installation of additional software packages needs to be repeated for
- each job in your pipeline.
-- The job may stay in a pending state for longer than the
- Linux runners.
-- There is the possibility that we introduce breaking changes which will
- require updates to pipelines that are using the Windows runner
- fleet.
+<!-- This redirect file can be deleted after 2022-02-05. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/runners/configure_runners.md b/doc/ci/runners/configure_runners.md
index 13897b934c5..9e30f4dbf4d 100644
--- a/doc/ci/runners/configure_runners.md
+++ b/doc/ci/runners/configure_runners.md
@@ -156,7 +156,7 @@ the GitLab instance. To determine this:
1. On the left sidebar, select **Overview > Runners**.
1. Find the runner in the table and view the **IP Address** column.
-![shared runner IP address](img/shared_runner_ip_address_14_1.png)
+![shared runner IP address](img/shared_runner_ip_address_14_5.png)
### Determine the IP address of a specific runner
@@ -294,6 +294,9 @@ globally or for individual jobs:
- [`GIT_FETCH_EXTRA_FLAGS`](#git-fetch-extra-flags)
- [`GIT_DEPTH`](#shallow-cloning) (shallow cloning)
- [`GIT_CLONE_PATH`](#custom-build-directories) (custom build directories)
+- [`TRANSFER_METER_FREQUENCY`](#artifact-and-cache-settings) (artifact/cache meter update frequency)
+- [`ARTIFACT_COMPRESSION_LEVEL`](#artifact-and-cache-settings) (artifact archiver compression level)
+- [`CACHE_COMPRESSION_LEVEL`](#artifact-and-cache-settings) (cache archiver compression level)
You can also use variables to configure how many times a runner
[attempts certain stages of job execution](#job-stages-attempts).
diff --git a/doc/ci/runners/img/shared_runner_ip_address_14_1.png b/doc/ci/runners/img/shared_runner_ip_address_14_1.png
deleted file mode 100644
index d7eeeae7a3c..00000000000
--- a/doc/ci/runners/img/shared_runner_ip_address_14_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/runners/img/shared_runner_ip_address_14_5.png b/doc/ci/runners/img/shared_runner_ip_address_14_5.png
new file mode 100644
index 00000000000..9a579f69303
--- /dev/null
+++ b/doc/ci/runners/img/shared_runner_ip_address_14_5.png
Binary files differ
diff --git a/doc/ci/runners/index.md b/doc/ci/runners/index.md
index 9acca60c4b4..d408bc46609 100644
--- a/doc/ci/runners/index.md
+++ b/doc/ci/runners/index.md
@@ -5,12 +5,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# GitLab Build Cloud runners **(FREE)**
+# GitLab Runner Cloud **(FREE)**
If you are using self-managed GitLab or you want to use your own runners on GitLab.com, you can
[install and configure your own runners](https://docs.gitlab.com/runner/install/).
-If you are using GitLab SaaS (GitLab.com), your CI jobs automatically run on runners in the GitLab Build Cloud.
+If you are using GitLab SaaS (GitLab.com), your CI jobs automatically run on runners in the GitLab Runner Cloud.
No configuration is required. Your jobs can run on:
- [Linux runners](build_cloud/linux_build_cloud.md).
diff --git a/doc/ci/runners/runner_cloud/linux_runner_cloud.md b/doc/ci/runners/runner_cloud/linux_runner_cloud.md
new file mode 100644
index 00000000000..d0fedfcabb2
--- /dev/null
+++ b/doc/ci/runners/runner_cloud/linux_runner_cloud.md
@@ -0,0 +1,186 @@
+---
+stage: Verify
+group: Runner
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Runner Cloud for Linux **(FREE)**
+
+Runner Cloud runners for Linux run in autoscale mode and are powered by Google Cloud Platform.
+
+Autoscaling means reduced queue times to spin up CI/CD jobs, and isolated VMs for each job, thus maximizing security. These shared runners are available on GitLab.com.
+
+GitLab offers Ultimate tier capabilities and included CI/CD minutes per group per month for our [Open Source](https://about.gitlab.com/solutions/open-source/join/), [Education](https://about.gitlab.com/solutions/education/), and [Startups](https://about.gitlab.com/solutions/startups/) programs. For private projects, GitLab offers various [plans](https://about.gitlab.com/pricing/), starting with a Free tier.
+
+All your CI/CD jobs run on [n1-standard-1 instances](https://cloud.google.com/compute/docs/machine-types) with 3.75GB of RAM, Google COS and the latest Docker Engine
+installed. Instances provide 1 vCPU and 25GB of HDD disk space. The default
+region of the VMs is US East1.
+Each instance is used only for one job. This ensures that any sensitive data left on the system can't be accessed by other people's CI/CD jobs.
+
+NOTE:
+The final disk space your jobs can use will be less than 25GB. Some disk space allocated to the instance will be occupied by the operating system, the Docker image, and a copy of your cloned repository.
+
+The `gitlab-shared-runners-manager-X.gitlab.com` fleet of runners are dedicated for GitLab projects as well as community forks of them. They use a slightly larger machine type (n1-standard-2) and have a bigger SSD disk size. They don't run untagged jobs and unlike the general fleet of shared runners, the instances are re-used up to 40 times.
+
+Jobs handled by the shared runners on GitLab.com (`shared-runners-manager-X.gitlab.com`),
+**time out after 3 hours**, regardless of the timeout configured in a
+project. Check the issues [#4010](https://gitlab.com/gitlab-com/infrastructure/-/issues/4010) and [#4070](https://gitlab.com/gitlab-com/infrastructure/-/issues/4070) for the reference.
+
+Below are the runners' settings.
+
+| Setting | GitLab.com | Default |
+| ----------- | ----------------- | ---------- |
+| Executor | `docker+machine` | - |
+| Default Docker image | `ruby:2.5` | - |
+| `privileged` (run [Docker in Docker](https://hub.docker.com/_/docker/)) | `true` | `false` |
+
+These runners share a [distributed cache](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) through use of a Google Cloud Storage (GCS) bucket. Cache contents not updated within the last 14 days are automatically removed through use of an [object lifecycle management policy](https://cloud.google.com/storage/docs/lifecycle).
+
+## Pre-clone script
+
+Cloud runners for Linux provide a way to run commands in a CI
+job before the runner attempts to run `git init` and `git fetch` to
+download a GitLab repository. The
+[`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
+can be used for:
+
+- Seeding the build directory with repository data
+- Sending a request to a server
+- Downloading assets from a CDN
+- Any other commands that must run before the `git init`
+
+To use this feature, define a [CI/CD variable](../../../ci/variables/index.md#custom-cicd-variables) called
+`CI_PRE_CLONE_SCRIPT` that contains a bash script.
+
+NOTE:
+The `CI_PRE_CLONE_SCRIPT` variable does not work on Windows runners.
+
+### Pre-clone script example
+
+This example was used in the `gitlab-org/gitlab` project until November 2021.
+The project no longer uses this optimization because the [pack-objects cache](../../../administration/gitaly/configure_gitaly.md#pack-objects-cache)
+lets Gitaly serve the full CI/CD fetch traffic. See [Git fetch caching](../../../development/pipelines.md#git-fetch-caching).
+
+The `CI_PRE_CLONE_SCRIPT` was defined as a project CI/CD variable:
+
+```shell
+(
+ echo "Downloading archived master..."
+ wget -O /tmp/gitlab.tar.gz https://storage.googleapis.com/gitlab-ci-git-repo-cache/project-278964/gitlab-master-shallow.tar.gz
+
+ if [ ! -f /tmp/gitlab.tar.gz ]; then
+ echo "Repository cache not available, cloning a new directory..."
+ exit
+ fi
+
+ rm -rf $CI_PROJECT_DIR
+ echo "Extracting tarball into $CI_PROJECT_DIR..."
+ mkdir -p $CI_PROJECT_DIR
+ cd $CI_PROJECT_DIR
+ tar xzf /tmp/gitlab.tar.gz
+ rm -f /tmp/gitlab.tar.gz
+ chmod a+w $CI_PROJECT_DIR
+)
+```
+
+The first step of the script downloads `gitlab-master.tar.gz` from Google Cloud Storage.
+There was a [GitLab CI/CD job named `cache-repo`](https://gitlab.com/gitlab-org/gitlab/-/blob/5fb40526c8c8aaafc5f92eab36d5bbddaca3893d/.gitlab/ci/cache-repo.gitlab-ci.yml)
+that was responsible for keeping that archive up-to-date. Every two hours on a scheduled pipeline,
+it did the following:
+
+1. Create a fresh clone of the `gitlab-org/gitlab` repository on GitLab.com.
+1. Save the data as a `.tar.gz`.
+1. Upload it into the Google Cloud Storage bucket.
+
+When a job ran with this configuration, the output looked similar to:
+
+```shell
+$ eval "$CI_PRE_CLONE_SCRIPT"
+Downloading archived master...
+Extracting tarball into /builds/gitlab-org/gitlab...
+Fetching changes...
+Reinitialized existing Git repository in /builds/gitlab-org/gitlab/.git/
+```
+
+The `Reinitialized existing Git repository` message shows that
+the pre-clone step worked. The runner runs `git init`, which
+overwrites the Git configuration with the appropriate settings to fetch
+from the GitLab repository.
+
+`CI_REPO_CACHE_CREDENTIALS` must contain the Google Cloud service account
+JSON for uploading to the `gitlab-ci-git-repo-cache` bucket.
+
+Note that this bucket should be located in the same continent as the
+runner, or [you can incur network egress charges](https://cloud.google.com/storage/pricing).
+
+## `config.toml`
+
+The full contents of our `config.toml` are:
+
+NOTE:
+Settings that are not public are shown as `X`.
+
+**Google Cloud Platform**
+
+```toml
+concurrent = X
+check_interval = 1
+metrics_server = "X"
+sentry_dsn = "X"
+
+[[runners]]
+ name = "docker-auto-scale"
+ request_concurrency = X
+ url = "https://gitlab.com/"
+ token = "SHARED_RUNNER_TOKEN"
+ pre_clone_script = "eval \"$CI_PRE_CLONE_SCRIPT\""
+ executor = "docker+machine"
+ environment = [
+ "DOCKER_DRIVER=overlay2",
+ "DOCKER_TLS_CERTDIR="
+ ]
+ limit = X
+ [runners.docker]
+ image = "ruby:2.5"
+ privileged = true
+ volumes = [
+ "/certs/client",
+ "/dummy-sys-class-dmi-id:/sys/class/dmi/id:ro" # Make kaniko builds work on GCP.
+ ]
+ [runners.machine]
+ IdleCount = 50
+ IdleTime = 3600
+ MaxBuilds = 1 # For security reasons we delete the VM after job has finished so it's not reused.
+ MachineName = "srm-%s"
+ MachineDriver = "google"
+ MachineOptions = [
+ "google-project=PROJECT",
+ "google-disk-size=25",
+ "google-machine-type=n1-standard-1",
+ "google-username=core",
+ "google-tags=gitlab-com,srm",
+ "google-use-internal-ip",
+ "google-zone=us-east1-d",
+ "engine-opt=mtu=1460", # Set MTU for container interface, for more information check https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3214#note_82892928
+ "google-machine-image=PROJECT/global/images/IMAGE",
+ "engine-opt=ipv6", # This will create IPv6 interfaces in the containers.
+ "engine-opt=fixed-cidr-v6=fc00::/7",
+ "google-operation-backoff-initial-interval=2" # Custom flag from forked docker-machine, for more information check https://github.com/docker/machine/pull/4600
+ ]
+ [[runners.machine.autoscaling]]
+ Periods = ["* * * * * sat,sun *"]
+ Timezone = "UTC"
+ IdleCount = 70
+ IdleTime = 3600
+ [[runners.machine.autoscaling]]
+ Periods = ["* 30-59 3 * * * *", "* 0-30 4 * * * *"]
+ Timezone = "UTC"
+ IdleCount = 700
+ IdleTime = 3600
+ [runners.cache]
+ Type = "gcs"
+ Shared = true
+ [runners.cache.gcs]
+ CredentialsFile = "/path/to/file"
+ BucketName = "bucket-name"
+```
diff --git a/doc/ci/runners/runner_cloud/macos/environment.md b/doc/ci/runners/runner_cloud/macos/environment.md
new file mode 100644
index 00000000000..ddefad775c1
--- /dev/null
+++ b/doc/ci/runners/runner_cloud/macos/environment.md
@@ -0,0 +1,43 @@
+---
+stage: Verify
+group: Runner
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# VM instances and images for Runner Cloud for macOS **(FREE)**
+
+When you use the Runner Cloud for macOS:
+
+- Each of your jobs runs in a newly provisioned VM, which is dedicated to the specific job.
+- The VM is active only for the duration of the job and immediately deleted.
+
+## VM types
+
+The virtual machine where your job runs has `sudo` access with no password.
+For the Beta, there is only one available machine type, `gbc-macos-large`.
+
+| Instance type | vCPUS | Memory (GB) |
+| --------- | --- | ------- |
+| `gbc-macos-large` | 4 | 10 |
+
+## VM images
+
+You can execute your build on one of the following images.
+You specify this image in your `.gitlab-ci.yml` file.
+
+Each image is running a specific version of macOS and Xcode.
+
+| VM image | Included software |
+|---------------------------|--------------------|
+| macos-10.13-xcode-7 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
+| macos-10.13-xcode-8 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
+| macos-10.13-xcode-9 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
+| macos-10.14-xcode-10 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/mojave.yml> |
+| macos-10.15-xcode-11 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/catalina.yml> |
+| macos-11-xcode-12 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/big-sur.yml> |
+
+### Image update policy
+
+- Support for new macOS versions is planned.
+- Additional details on the support policy and image update release process are documented
+ [in this project](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/55bf59c8fa88712960afff2bf6ecc5daa879a8f5/docs/overview.md#os-images).
diff --git a/doc/ci/runners/runner_cloud/macos_runner_cloud.md b/doc/ci/runners/runner_cloud/macos_runner_cloud.md
new file mode 100644
index 00000000000..332284fa8c1
--- /dev/null
+++ b/doc/ci/runners/runner_cloud/macos_runner_cloud.md
@@ -0,0 +1,62 @@
+---
+stage: Verify
+group: Runner
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Runner Cloud for macOS (Beta) **(FREE SAAS)**
+
+The Runner Cloud for macOS Beta provides on-demand runners integrated with GitLab SaaS [CI/CD](../../../ci/index.md).
+Use these runners to build, test, and deploy apps for the Apple ecosystem (macOS, iOS, tvOS). You can take advantage
+of all the capabilities of the GitLab single DevOps platform and not have to manage or operate a
+build environment.
+
+Cloud runners for macOS are in [Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
+and shouldn't be relied upon for mission-critical production jobs.
+
+## Quickstart
+
+To start using Runner Cloud for macOS Beta, you must submit an access request [issue](https://gitlab.com/gitlab-com/macos-buildcloud-runners-beta/-/issues/new?issuable_template=beta_access_request). After your
+access has been granted and your build environment configured, you must configure your
+`.gitlab-ci.yml` pipeline file:
+
+1. Add a `.gitlab-ci.yml` file to your project repository.
+1. Specify the [image](macos/environment.md#vm-images) you want to use.
+1. Commit a change to your repository.
+
+The runners automatically run your build.
+
+## Example `.gitlab-ci.yml` file
+
+The following sample `.gitlab-ci.yml` file shows how to start using the runners for macOS:
+
+```yaml
+.macos_buildcloud_runners:
+ tags:
+ - shared-macos-amd64
+ image: macos-11-xcode-12
+
+stages:
+ - build
+ - test
+
+before_script:
+ - echo "started by ${GITLAB_USER_NAME}"
+
+build:
+ extends:
+ - .macos_buildcloud_runners
+ stage: build
+ script:
+ - echo "running scripts in the build job"
+
+test:
+ extends:
+ - .macos_buildcloud_runners
+ stage: test
+ script:
+ - echo "running scripts in the test job"
+```
+
+NOTE:
+During the Beta period, the architecture of this solution will change. Rather than the jobs running on a specific VM instance, they will run on an ephemeral VM instance that is created by an autoscaling instance, known as the Runner Manager. We will notify all Beta participants of any downtime required to do this work.
diff --git a/doc/ci/runners/runner_cloud/windows_runner_cloud.md b/doc/ci/runners/runner_cloud/windows_runner_cloud.md
new file mode 100644
index 00000000000..ef4d4076c91
--- /dev/null
+++ b/doc/ci/runners/runner_cloud/windows_runner_cloud.md
@@ -0,0 +1,155 @@
+---
+stage: Verify
+group: Runner
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Runner Cloud for Windows (beta) **(FREE)**
+
+Runner Cloud runners for Windows are in [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
+and shouldn't be used for production workloads.
+
+During this beta period, the [shared runner pipeline quota](../../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota)
+applies for groups and projects in the same manner as Linux runners. This may
+change when the beta period ends, as discussed in this [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/30834).
+
+Windows runners on GitLab.com autoscale by launching virtual machines on
+the Google Cloud Platform. This solution uses an
+[autoscaling driver](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md)
+developed by GitLab for the [custom executor](https://docs.gitlab.com/runner/executors/custom.html).
+Windows runners execute your CI/CD jobs on `n1-standard-2` instances with
+2 vCPUs and 7.5 GB RAM. You can find a full list of available Windows packages in
+the [package documentation](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/main/cookbooks/preinstalled-software/README.md).
+
+We want to keep iterating to get Windows runners in a stable state and
+[generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga).
+You can follow our work towards this goal in the
+[related epic](https://gitlab.com/groups/gitlab-org/-/epics/2162).
+
+## Configuration
+
+The full contents of our `config.toml` are:
+
+NOTE:
+Settings that aren't public are shown as `X`.
+
+```toml
+concurrent = X
+check_interval = 3
+
+[[runners]]
+ name = "windows-runner"
+ url = "https://gitlab.com/"
+ token = "TOKEN"
+ executor = "custom"
+ builds_dir = "C:\\GitLab-Runner\\builds"
+ cache_dir = "C:\\GitLab-Runner\\cache"
+ shell = "powershell"
+ [runners.custom]
+ config_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
+ config_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "config"]
+ prepare_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
+ prepare_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "prepare"]
+ run_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
+ run_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "run"]
+ cleanup_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
+ cleanup_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "cleanup"]
+```
+
+The full contents of our `autoscaler/config.toml` are:
+
+```toml
+Provider = "gcp"
+Executor = "winrm"
+OS = "windows"
+LogLevel = "info"
+LogFormat = "text"
+LogFile = "C:\\GitLab-Runner\\autoscaler\\autoscaler.log"
+VMTag = "windows"
+
+[GCP]
+ ServiceAccountFile = "PATH"
+ Project = "some-project-df9323"
+ Zone = "us-east1-c"
+ MachineType = "n1-standard-2"
+ Image = "IMAGE"
+ DiskSize = 50
+ DiskType = "pd-standard"
+ Subnetwork = "default"
+ Network = "default"
+ Tags = ["TAGS"]
+ Username = "gitlab_runner"
+
+[WinRM]
+ MaximumTimeout = 3600
+ ExecutionMaxRetries = 0
+
+[ProviderCache]
+ Enabled = true
+ Directory = "C:\\GitLab-Runner\\autoscaler\\machines"
+```
+
+## Example `.gitlab-ci.yml` file
+
+Below is a sample `.gitlab-ci.yml` file that shows how to start using the runners for Windows:
+
+```yaml
+.shared_windows_runners:
+ tags:
+ - shared-windows
+ - windows
+ - windows-1809
+
+stages:
+ - build
+ - test
+
+before_script:
+ - Set-Variable -Name "time" -Value (date -Format "%H:%m")
+ - echo ${time}
+ - echo "started by ${GITLAB_USER_NAME}"
+
+build:
+ extends:
+ - .shared_windows_runners
+ stage: build
+ script:
+ - echo "running scripts in the build job"
+
+test:
+ extends:
+ - .shared_windows_runners
+ stage: test
+ script:
+ - echo "running scripts in the test job"
+```
+
+## Limitations and known issues
+
+- All the limitations mentioned in our [beta
+ definition](https://about.gitlab.com/handbook/product/#beta).
+- The average provisioning time for a new Windows VM is 5 minutes.
+ This means that you may notice slower build start times
+ on the Windows runner fleet during the beta. In a future
+ release we intend to update the autoscaler to enable
+ the pre-provisioning of virtual machines. This is intended to significantly reduce
+ the time it takes to provision a VM on the Windows fleet. You can
+ follow along in the [related issue](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/-/issues/32).
+- The Windows runner fleet may be unavailable occasionally
+ for maintenance or updates.
+- The Windows runner virtual machine instances do not use the
+ GitLab Docker executor. This means that you can't specify
+ [`image`](../../../ci/yaml/index.md#image) or [`services`](../../../ci/yaml/index.md#services) in
+ your pipeline configuration.
+- For the beta release, we have included a set of software packages in
+ the base VM image. If your CI job requires additional software that's
+ not included in this list, then you must add installation
+ commands to [`before_script`](../../../ci/yaml/index.md#before_script) or [`script`](../../../ci/yaml/index.md#script) to install the required
+ software. Note that each job runs on a new VM instance, so the
+ installation of additional software packages needs to be repeated for
+ each job in your pipeline.
+- The job may stay in a pending state for longer than the
+ Linux runners.
+- There is the possibility that we introduce breaking changes which will
+ require updates to pipelines that are using the Windows runner
+ fleet.
diff --git a/doc/ci/services/index.md b/doc/ci/services/index.md
index 4114833d1c8..51df8c102f7 100644
--- a/doc/ci/services/index.md
+++ b/doc/ci/services/index.md
@@ -259,7 +259,8 @@ test:
| `name` | yes, when used with any other option | 9.4 | Full name of the image to use. If the full image name includes a registry hostname, use the `alias` option to define a shorter service access name. For more information, see [Accessing the services](#accessing-the-services). |
| `entrypoint` | no | 9.4 |Command or script to execute as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. |
| `command` | no | 9.4 |Command or script that should be used as the container's command. It's translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`](https://docs.docker.com/engine/reference/builder/#cmd) directive, where each shell token is a separate string in the array. |
-| `alias` (1) | no | 9.4 |Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. |
+| `alias` (1) | no | 9.4 | Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. |
+| `variables` | no | 14.5 | Additional environment variables that are passed exclusively to the service. The syntax is the same as [Job Variables](../variables/index.md). |
(1) Alias support for the Kubernetes executor was [introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2229) in GitLab Runner 12.8, and is only available for Kubernetes version 1.7 or later.
diff --git a/doc/ci/services/postgres.md b/doc/ci/services/postgres.md
index 62838e04969..0bd43917cd1 100644
--- a/doc/ci/services/postgres.md
+++ b/doc/ci/services/postgres.md
@@ -37,9 +37,9 @@ And then configure your application to use the database, for example:
```yaml
Host: postgres
-User: $PG_USER
-Password: $PG_PASSWORD
-Database: $PG_DB
+User: $POSTGRES_USER
+Password: $POSTGRES_PASSWORD
+Database: $POSTGRES_DB
```
If you're wondering why we used `postgres` for the `Host`, read more at
diff --git a/doc/ci/test_cases/index.md b/doc/ci/test_cases/index.md
index 4bd38f4043a..384bfc10779 100644
--- a/doc/ci/test_cases/index.md
+++ b/doc/ci/test_cases/index.md
@@ -18,7 +18,9 @@ use external test planning tools, which require additional overhead, context swi
## Create a test case
-Users with Reporter or higher [permissions](../../user/permissions.md) can create test cases.
+Prerequisite:
+
+- You must have at least the Reporter [role](../../user/permissions.md).
To create a test case in a GitLab project:
@@ -32,7 +34,9 @@ To create a test case in a GitLab project:
You can view all test cases in the project in the Test Cases list. Filter the
issue list with a search query, including labels or the test case's title.
-Users with Guest or higher [permissions](../../user/permissions.md) can view test cases.
+Prerequisite:
+
+- You must have at least the Guest [role](../../user/permissions.md).
To view a test case:
@@ -45,8 +49,10 @@ To view a test case:
You can edit a test case's title and description.
-Users with Reporter or higher [permissions](../../user/permissions.md) can edit test cases.
-Users demoted to the Guest role can continue to edit the test cases they created
+Prerequisite:
+
+- You must have at least the Reporter [role](../../user/permissions.md).
+- Users demoted to the Guest role can continue to edit the test cases they created
when they were in the higher role.
To edit a test case:
@@ -60,7 +66,9 @@ To edit a test case:
When you want to stop using a test case, you can archive it. You can [reopen an archived test case](#reopen-an-archived-test-case) later.
-Users with Reporter or higher [permissions](../../user/permissions.md) can archive test cases.
+Prerequisite:
+
+- You must have at least the Reporter [role](../../user/permissions.md).
To archive a test case, on the test case's page, select the **Archive test case** button.
@@ -73,6 +81,6 @@ To view archived test cases:
If you decide to start using an archived test case again, you can reopen it.
-Users with Reporter or higher [permissions](../../user/permissions.md) can reopen test cases.
+You must have at least the Reporter [role](../../user/permissions.md).
To reopen an archived test case, on the test case's page, select **Reopen test case**.
diff --git a/doc/ci/triggers/index.md b/doc/ci/triggers/index.md
index a2dd4ac91d5..afcf8ae629a 100644
--- a/doc/ci/triggers/index.md
+++ b/doc/ci/triggers/index.md
@@ -113,6 +113,9 @@ This means that whenever a new tag is pushed on project A, the job runs and the
`stage: deploy` ensures that this job runs only after all jobs with
`stage: test` complete successfully.
+NOTE:
+You [cannot use the API to start `when:manual` trigger jobs](https://gitlab.com/gitlab-org/gitlab/-/issues/284086).
+
## Triggering a pipeline from a webhook
To trigger a job from a webhook of another project you need to add the following
diff --git a/doc/ci/troubleshooting.md b/doc/ci/troubleshooting.md
index 994e9294ff6..037e8d3497d 100644
--- a/doc/ci/troubleshooting.md
+++ b/doc/ci/troubleshooting.md
@@ -16,12 +16,15 @@ This guide also lists common issues and possible solutions.
An early source of problems can be incorrect syntax. The pipeline shows a `yaml invalid`
badge and does not start running if any syntax or formatting problems are found.
-### Edit `gitlab-ci.yml` with the Web IDE
+### Edit `gitlab-ci.yml` with the pipeline editor
-The [GitLab Web IDE](../user/project/web_ide/index.md) offers advanced authoring tools,
-including syntax highlighting for the `.gitlab-ci.yml`, and is the recommended editing
-experience (rather than the single file editor). It offers code completion suggestions
-that ensure you are only using accepted keywords.
+The [pipeline editor](pipeline_editor/index.md) is the recommended editing
+experience (rather than the single file editor or the Web IDE). It includes:
+
+- Code completion suggestions that ensure you are only using accepted keywords.
+- Automatic syntax highlighting and validation.
+- The [CI/CD configuration visualization](pipeline_editor/index.md#visualize-ci-configuration),
+ a graphical representation of your `.gitlab-ci.yml` file.
If you prefer to use another editor, you can use a schema like [the Schemastore `gitlab-ci` schema](https://json.schemastore.org/gitlab-ci)
with your editor of choice.
@@ -246,6 +249,39 @@ If the merge train pipeline was canceled before the merge request was merged, wi
- Add it to the train again.
+### Project `group/project` not found or access denied
+
+This message is shown if configuration is added with [`include`](yaml/index.md#include) and one of the following:
+
+- The configuration refers to a project that can't be found.
+- The user that is running the pipeline is unable to access any included projects.
+
+To resolve this, check that:
+
+- The path of the project is in the format `my-group/my-project` and does not include
+ any folders in the repository.
+- The user running the pipeline is a [member of the projects](../user/project/members/index.md#add-users-to-a-project)
+ that contain the included files. Users must also have the [permission](../user/permissions.md#job-permissions)
+ to run CI/CD jobs in the same projects.
+
+### "The parsed YAML is too big" message
+
+This message displays when the YAML configuration is too large or nested too deeply.
+YAML files with a large number of includes, and thousands of lines overall, are
+more likely to hit this memory limit. For example, a YAML file that is 200kb is
+likely to hit the default memory limit.
+
+To reduce the configuration size, you can:
+
+- Check the length of the expanded CI/CD configuration in the pipeline editor's
+ [merged YAML](pipeline_editor/index.md#view-expanded-configuration) tab. Look for
+ duplicated configuration that can be removed or simplified.
+- Move long or repeated `script` sections into standalone scripts in the project.
+- Use [parent and child pipelines](pipelines/parent_child_pipelines.md) to move some
+ work to jobs in an independent child pipeline.
+
+On a self-managed instance, you can [increase the size limits](../administration/instance_limits.md#maximum-size-and-depth-of-cicd-configuration-yaml-files).
+
## Pipeline warnings
Pipeline configuration warnings are shown when you:
diff --git a/doc/ci/unit_test_reports.md b/doc/ci/unit_test_reports.md
index c37d7f27970..e758fbc91dd 100644
--- a/doc/ci/unit_test_reports.md
+++ b/doc/ci/unit_test_reports.md
@@ -290,6 +290,24 @@ javascript:
- junit.xml
```
+#### Mocha
+
+The [JUnit Reporter for Mocha](https://github.com/michaelleeallen/mocha-junit-reporter) NPM package can generate test reports for JavaScript
+applications.
+In the following `.gitlab-ci.yml` example, the `javascript` job uses Mocha to generate the test reports:
+
+```yaml
+javascript:
+ stage: test
+ script:
+ - mocha --reporter mocha-junit-reporter --reporter-options mochaFile=junit.xml
+ artifacts:
+ when: always
+ reports:
+ junit:
+ - junit.xml
+```
+
### Flutter / Dart example
This example `.gitlab-ci.yml` file uses the [JUnit Report](https://pub.dev/packages/junitreport) package to convert the `flutter test` output into JUnit report XML format:
diff --git a/doc/ci/variables/index.md b/doc/ci/variables/index.md
index 8650adf0351..a0c8dbd4e4a 100644
--- a/doc/ci/variables/index.md
+++ b/doc/ci/variables/index.md
@@ -121,7 +121,7 @@ job1:
- echo This job does not need any variables
```
-Use the [`value` and `description`](../yaml/index.md#prefill-variables-in-manual-pipelines)
+Use the [`value` and `description`](../yaml/index.md#variablesdescription)
keywords to define [variables that are prefilled](../pipelines/index.md#prefill-variables-in-manual-pipelines)
for [manually-triggered pipelines](../pipelines/index.md#run-a-pipeline-manually).
@@ -557,7 +557,7 @@ they can be used in job scripts.
1. Save the `.env` file as an [`artifacts:reports:dotenv`](../yaml/index.md#artifactsreportsdotenv)
artifact.
1. Set a job in a later stage to receive the artifact by using the [`dependencies`](../yaml/index.md#dependencies)
- or the [`needs`](../yaml/index.md#artifact-downloads-with-needs) keywords.
+ or the [`needs`](../yaml/index.md#needs) keywords.
1. The later job can then [use the variable in scripts](#use-cicd-variables-in-job-scripts).
For example, with the [`dependencies`](../yaml/index.md#dependencies) keyword:
@@ -579,7 +579,7 @@ deploy:
- build
```
-For example, with the [`needs`](../yaml/index.md#artifact-downloads-with-needs) keyword:
+For example, with the [`needs:artifacts`](../yaml/index.md#needsartifacts) keyword:
```yaml
build:
diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md
index 9fd1e3eb1a4..e32f0391d2e 100644
--- a/doc/ci/variables/where_variables_can_be_used.md
+++ b/doc/ci/variables/where_variables_can_be_used.md
@@ -63,14 +63,12 @@ because the expansion is done in GitLab before any runner gets the job.
#### Nested variable expansion
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48627) in GitLab 13.10. [Deployed behind the `variable_inside_variable` feature flag](../../user/feature_flags.md), disabled by default.
-> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/297382) in GitLab 14.3.
-> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/297382) in GitLab 14.4.
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48627) in GitLab 13.10. [Deployed behind the `variable_inside_variable` feature flag](../../user/feature_flags.md), disabled by default.
+- [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/297382) in GitLab 14.3.
+- [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/297382) in GitLab 14.4.
+- Feature flag `variable_inside_variable` removed in GitLab 14.5.
-FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `variable_inside_variable`. On GitLab.com, this feature is available.
-
-GitLab expands job variable values recursively before sending them to the runner. For example:
+GitLab expands job variable values recursively before sending them to the runner. For example, in the following scenario:
```yaml
- BUILD_ROOT_DIR: '${CI_BUILDS_DIR}'
@@ -78,10 +76,7 @@ GitLab expands job variable values recursively before sending them to the runner
- PACKAGE_PATH: '${OUT_PATH}/pkg'
```
-If nested variable expansion is:
-
-- **Disabled**: the runner receives `${BUILD_ROOT_DIR}/out/pkg`. This is not a valid path.
-- **Enabled**: the runner receives a valid, fully-formed path. For example, if `${CI_BUILDS_DIR}` is `/output`, then `PACKAGE_PATH` would be `/output/out/pkg`.
+The runner receives a valid, fully-formed path. For example, if `${CI_BUILDS_DIR}` is `/output`, then `PACKAGE_PATH` would be `/output/out/pkg`.
References to unavailable variables are left intact. In this case, the runner
[attempts to expand the variable value](#gitlab-runner-internal-variable-expansion-mechanism) at runtime.
diff --git a/doc/ci/yaml/gitlab_ci_yaml.md b/doc/ci/yaml/gitlab_ci_yaml.md
index ea05aa45b0b..9bab4a7fc77 100644
--- a/doc/ci/yaml/gitlab_ci_yaml.md
+++ b/doc/ci/yaml/gitlab_ci_yaml.md
@@ -24,7 +24,7 @@ In the `.gitlab-ci.yml` file, you can define:
The scripts are grouped into **jobs**, and jobs run as part of a larger
**pipeline**. You can group multiple independent jobs into **stages** that run in a defined order.
-The CI/CD configuration needs at least one job that is [not hidden](index.md#hide-jobs).
+The CI/CD configuration needs at least one job that is [not hidden](../jobs/index.md#hide-jobs).
You should organize your jobs in a sequence that suits your application and is in accordance with
the tests you wish to perform. To [visualize](../pipeline_editor/index.md#visualize-ci-configuration) the process, imagine
diff --git a/doc/ci/yaml/includes.md b/doc/ci/yaml/includes.md
index 92bf44cca7f..5e2eb53a0ea 100644
--- a/doc/ci/yaml/includes.md
+++ b/doc/ci/yaml/includes.md
@@ -69,7 +69,7 @@ You can include an array of configuration files:
## Use `default` configuration from an included configuration file
-You can define a [`default`](index.md#custom-default-keyword-values) section in a
+You can define a [`default`](index.md#default) section in a
configuration file. When you use a `default` section with the `include` keyword, the defaults apply to
all jobs in the pipeline.
@@ -216,3 +216,120 @@ default:
after_script:
- echo "Job complete."
```
+
+## Use variables with `include`
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/284883) in GitLab 13.8.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/294294) in GitLab 13.9.
+> - [Support for project, group, and instance variables added](https://gitlab.com/gitlab-org/gitlab/-/issues/219065) in GitLab 14.2.
+> - [Support for pipeline variables added](https://gitlab.com/gitlab-org/gitlab/-/issues/337633) in GitLab 14.5.
+
+In `include` sections in your `.gitlab-ci.yml` file, you can use:
+
+- [Project variables](../variables/index.md#add-a-cicd-variable-to-a-project)
+- [Group variables](../variables/index.md#add-a-cicd-variable-to-a-group)
+- [Instance variables](../variables/index.md#add-a-cicd-variable-to-an-instance)
+- Project [predefined variables](../variables/predefined_variables.md)
+- In GitLab 14.2 and later, the `$CI_COMMIT_REF_NAME` [predefined variable](../variables/predefined_variables.md).
+
+ When used in `include`, the `CI_COMMIT_REF_NAME` variable returns the full
+ ref path, like `refs/heads/branch-name`. In `include:rules`, you might need to use
+ `if: $CI_COMMIT_REF_NAME =~ /main/` (not `== main`). This behavior is resolved in GitLab 14.5.
+
+In GitLab 14.5 and later, you can also use:
+
+- [Trigger variables](../triggers/index.md#making-use-of-trigger-variables).
+- [Scheduled pipeline variables](../pipelines/schedules.md#using-variables).
+- [Manual pipeline run variables](../variables/index.md#override-a-variable-when-running-a-pipeline-manually).
+- Pipeline [predefined variables](../variables/predefined_variables.md).
+
+ YAML files are parsed before the pipeline is created, so the following pipeline predefined variables
+ are **not** available:
+
+ - `CI_PIPELINE_ID`
+ - `CI_PIPELINE_URL`
+ - `CI_PIPELINE_IID`
+ - `CI_PIPELINE_CREATED_AT`
+
+For example:
+
+```yaml
+include:
+ project: '$CI_PROJECT_PATH'
+ file: '.compliance-gitlab-ci.yml'
+```
+
+For an example of how you can include these predefined variables, and the variables' impact on CI/CD jobs,
+see this [CI/CD variable demo](https://youtu.be/4XR8gw3Pkos).
+
+## Use `rules` with `include`
+
+> - Introduced in GitLab 14.2 [with a flag](../../administration/feature_flags.md) named `ci_include_rules`. Disabled by default.
+> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/337507) in GitLab 14.3.
+> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/337507) GitLab 14.3.
+> - [Feature flag `ci_include_rules` removed](https://gitlab.com/gitlab-org/gitlab/-/issues/337507) in GitLab 14.4.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/337507) in GitLab 14.4.
+> - [Support for `exists` keyword added](https://gitlab.com/gitlab-org/gitlab/-/issues/341511) in GitLab 14.5.
+
+You can use [`rules`](index.md#rules) with `include` to conditionally include other configuration files.
+
+You can only use the following rules with `include` (and only with [certain variables](#use-variables-with-include)):
+
+- [`if` rules](index.md#rulesif). For example:
+
+ ```yaml
+ include:
+ - local: builds.yml
+ rules:
+ - if: '$INCLUDE_BUILDS == "true"'
+ - local: deploys.yml
+ rules:
+ - if: $CI_COMMIT_BRANCH == "main"
+
+ test:
+ stage: test
+ script: exit 0
+ ```
+
+- [`exists` rules](index.md#rulesexists). For example:
+
+ ```yaml
+ include:
+ - local: builds.yml
+ rules:
+ - exists:
+ - file.md
+
+ test:
+ stage: test
+ script: exit 0
+ ```
+
+`rules` keyword `changes` is not supported.
+
+## Use `include:local` with wildcard file paths
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25921) in GitLab 13.11.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/327315) in GitLab 14.2.
+
+You can use wildcard paths (`*` and `**`) with `include:local`.
+
+Example:
+
+```yaml
+include: 'configs/*.yml'
+```
+
+When the pipeline runs, GitLab:
+
+- Adds all `.yml` files in the `configs` directory into the pipeline configuration.
+- Does not add `.yml` files in subfolders of the `configs` directory. To allow this,
+ add the following configuration:
+
+ ```yaml
+ # This matches all `.yml` files in `configs` and any subfolder in it.
+ include: 'configs/**.yml'
+
+ # This matches all `.yml` files only in subfolders of `configs`.
+ include: 'configs/**/*.yml'
+ ```
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index aa44400fffc..5702c7a7dfd 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -16,67 +16,68 @@ This document lists the configuration options for your GitLab `.gitlab-ci.yml` f
When you are editing your `.gitlab-ci.yml` file, you can validate it with the
[CI Lint](../lint.md) tool.
-## Job keywords
+## Keywords
+
+A GitLab CI/CD pipeline configuration includes:
+
+- [Global keywords](#global-keywords) that configure pipeline behavior:
+
+ | Keyword | Description |
+ |-------------------------|:------------|
+ | [`default`](#default) | Custom default values for job keywords. |
+ | [`stages`](#stages) | The names and order of the pipeline stages. |
+ | [`workflow`](#workflow) | Control what types of pipeline run. |
+ | [`include`](#include) | Import configuration from other YAML files. |
+
+- [Jobs](../jobs/index.md) configured with [job keywords](#job-keywords):
+
+ | Keyword | Description |
+ | :-------------------------------------------|:------------|
+ | [`after_script`](#after_script) | Override a set of commands that are executed after job. |
+ | [`allow_failure`](#allow_failure) | Allow job to fail. A failed job does not cause the pipeline to fail. |
+ | [`artifacts`](#artifacts) | List of files and directories to attach to a job on success. |
+ | [`before_script`](#before_script) | Override a set of commands that are executed before job. |
+ | [`cache`](#cache) | List of files that should be cached between subsequent runs. |
+ | [`coverage`](#coverage) | Code coverage settings for a given job. |
+ | [`dast_configuration`](#dast_configuration) | Use configuration from DAST profiles on a job level. |
+ | [`dependencies`](#dependencies) | Restrict which artifacts are passed to a specific job by providing a list of jobs to fetch artifacts from. |
+ | [`environment`](#environment) | Name of an environment to which the job deploys. |
+ | [`except`](#only--except) | Control when jobs are not created. |
+ | [`extends`](#extends) | Configuration entries that this job inherits from. |
+ | [`image`](#image) | Use Docker images. |
+ | [`inherit`](#inherit) | Select which global defaults all jobs inherit. |
+ | [`interruptible`](#interruptible) | Defines if a job can be canceled when made redundant by a newer run. |
+ | [`needs`](#needs) | Execute jobs earlier than the stage ordering. |
+ | [`only`](#only--except) | Control when jobs are created. |
+ | [`pages`](#pages) | Upload the result of a job to use with GitLab Pages. |
+ | [`parallel`](#parallel) | How many instances of a job should be run in parallel. |
+ | [`release`](#release) | Instructs the runner to generate a [release](../../user/project/releases/index.md) object. |
+ | [`resource_group`](#resource_group) | Limit job concurrency. |
+ | [`retry`](#retry) | When and how many times a job can be auto-retried in case of a failure. |
+ | [`rules`](#rules) | List of conditions to evaluate and determine selected attributes of a job, and whether or not it's created. |
+ | [`script`](#script) | Shell script that is executed by a runner. |
+ | [`secrets`](#secrets) | The CI/CD secrets the job needs. |
+ | [`services`](#services) | Use Docker services images. |
+ | [`stage`](#stage) | Defines a job stage. |
+ | [`tags`](#tags) | List of tags that are used to select a runner. |
+ | [`timeout`](#timeout) | Define a custom job-level timeout that takes precedence over the project-wide setting. |
+ | [`trigger`](#trigger) | Defines a downstream pipeline trigger. |
+ | [`variables`](#variables) | Define job variables on a job level. |
+ | [`when`](#when) | When to run job. |
-A job is defined as a list of keywords that define the job's behavior.
-
-The keywords available for jobs are:
-
-| Keyword | Description |
-| :-------------------------------------------|:------------|
-| [`after_script`](#after_script) | Override a set of commands that are executed after job. |
-| [`allow_failure`](#allow_failure) | Allow job to fail. A failed job does not cause the pipeline to fail. |
-| [`artifacts`](#artifacts) | List of files and directories to attach to a job on success. |
-| [`before_script`](#before_script) | Override a set of commands that are executed before job. |
-| [`cache`](#cache) | List of files that should be cached between subsequent runs. |
-| [`coverage`](#coverage) | Code coverage settings for a given job. |
-| [`dast_configuration`](#dast_configuration) | Use configuration from DAST profiles on a job level. |
-| [`dependencies`](#dependencies) | Restrict which artifacts are passed to a specific job by providing a list of jobs to fetch artifacts from. |
-| [`environment`](#environment) | Name of an environment to which the job deploys. |
-| [`except`](#only--except) | Control when jobs are not created. |
-| [`extends`](#extends) | Configuration entries that this job inherits from. |
-| [`image`](#image) | Use Docker images. |
-| [`include`](#include) | Include external YAML files. |
-| [`inherit`](#inherit) | Select which global defaults all jobs inherit. |
-| [`interruptible`](#interruptible) | Defines if a job can be canceled when made redundant by a newer run. |
-| [`needs`](#needs) | Execute jobs earlier than the stage ordering. |
-| [`only`](#only--except) | Control when jobs are created. |
-| [`pages`](#pages) | Upload the result of a job to use with GitLab Pages. |
-| [`parallel`](#parallel) | How many instances of a job should be run in parallel. |
-| [`release`](#release) | Instructs the runner to generate a [release](../../user/project/releases/index.md) object. |
-| [`resource_group`](#resource_group) | Limit job concurrency. |
-| [`retry`](#retry) | When and how many times a job can be auto-retried in case of a failure. |
-| [`rules`](#rules) | List of conditions to evaluate and determine selected attributes of a job, and whether or not it's created. |
-| [`script`](#script) | Shell script that is executed by a runner. |
-| [`secrets`](#secrets) | The CI/CD secrets the job needs. |
-| [`services`](#services) | Use Docker services images. |
-| [`stage`](#stage) | Defines a job stage. |
-| [`tags`](#tags) | List of tags that are used to select a runner. |
-| [`timeout`](#timeout) | Define a custom job-level timeout that takes precedence over the project-wide setting. |
-| [`trigger`](#trigger) | Defines a downstream pipeline trigger. |
-| [`variables`](#variables) | Define job variables on a job level. |
-| [`when`](#when) | When to run job. |
-
-### Unavailable names for jobs
-
-You can't use these keywords as job names:
-
-- `image`
-- `services`
-- `stages`
-- `types`
-- `before_script`
-- `after_script`
-- `variables`
-- `cache`
-- `include`
+## Global keywords
+
+Some keywords are not defined in a job. These keywords control pipeline behavior
+or import additional pipeline configuration.
-### Custom default keyword values
+### `default`
You can set global defaults for some keywords. Jobs that do not define one or more
of the listed keywords use the value defined in the `default:` section.
-These job keywords can be defined inside a `default:` section:
+**Keyword type**: Global keyword.
+
+**Possible inputs**: These keywords can have custom defaults:
- [`after_script`](#after_script)
- [`artifacts`](#artifacts)
@@ -89,9 +90,7 @@ These job keywords can be defined inside a `default:` section:
- [`tags`](#tags)
- [`timeout`](#timeout)
-The following example sets the `ruby:3.0` image as the default for all jobs in the pipeline.
-The `rspec 2.7` job does not use the default, because it overrides the default with
-a job-specific `image:` section:
+**Example of `default`:**
```yaml
default:
@@ -105,25 +104,24 @@ rspec 2.7:
script: bundle exec rspec
```
-## Global keywords
+In this example, `ruby:3.0` is the default `image` value for all jobs in the pipeline.
+The `rspec 2.7` job does not use the default, because it overrides the default with
+a job-specific `image:` section:
-Some keywords are not defined in a job. These keywords control pipeline behavior
-or import additional pipeline configuration:
+**Additional details**:
-| Keyword | Description |
-|-------------------------|:------------|
-| [`stages`](#stages) | The names and order of the pipeline stages. |
-| [`workflow`](#workflow) | Control what types of pipeline run. |
-| [`include`](#include) | Import configuration from other YAML files. |
+- When the pipeline is created, each default is copied to all jobs that don't have
+ that keyword defined.
+- If a job already has one of the keywords configured, the configuration in the job
+ takes precedence and is not replaced by the default.
+- Control inheritance of default keywords in jobs with [`inherit:default`](#inheritdefault).
### `stages`
-Use `stages` to define stages that contain groups of jobs. `stages` is defined globally
-for the pipeline. Use [`stage`](#stage) in a job to define which stage the job is
-part of.
+Use `stages` to define stages that contain groups of jobs. Use [`stage`](#stage)
+in a job to configure the job to run in a specific stage.
-If `stages` is not defined in the `.gitlab-ci.yml` file, then the default
-pipeline stages are:
+If `stages` is not defined in the `.gitlab-ci.yml` file, the default pipeline stages are:
- [`.pre`](#stage-pre)
- `build`
@@ -131,12 +129,14 @@ pipeline stages are:
- `deploy`
- [`.post`](#stage-post)
-The order of the `stages` items defines the execution order for jobs:
+The order of the items in `stages` defines the execution order for jobs:
- Jobs in the same stage run in parallel.
- Jobs in the next stage run after the jobs from the previous stage complete successfully.
-For example:
+**Keyword type**: Global keyword.
+
+**Example of `stages`:**
```yaml
stages:
@@ -145,6 +145,8 @@ stages:
- deploy
```
+In this example:
+
1. All jobs in `build` execute in parallel.
1. If all jobs in `build` succeed, the `test` jobs execute in parallel.
1. If all jobs in `test` succeed, the `deploy` jobs execute in parallel.
@@ -153,94 +155,92 @@ stages:
If any job fails, the pipeline is marked as `failed` and jobs in later stages do not
start. Jobs in the current stage are not stopped and continue to run.
-If a job does not specify a [`stage`](#stage), the job is assigned the `test` stage.
+**Additional details**:
-If a stage is defined, but no jobs use it, the stage is not visible in the pipeline. This is
-useful for [compliance pipeline configuration](../../user/project/settings/index.md#compliance-pipeline-configuration)
-because:
+- If a job does not specify a [`stage`](#stage), the job is assigned the `test` stage.
+- If a stage is defined but no jobs use it, the stage is not visible in the pipeline,
+ which can help [compliance pipeline configurations](../../user/project/settings/index.md#compliance-pipeline-configuration):
+ - Stages can be defined in the compliance configuration but remain hidden if not used.
+ - The defined stages become visible when developers use them in job definitions.
-- Stages can be defined in the compliance configuration but remain hidden if not used.
-- The defined stages become visible when developers use them in job definitions.
+**Related topics**:
-To make a job start earlier and ignore the stage order, use
-the [`needs`](#needs) keyword.
+- To make a job start earlier and ignore the stage order, use the [`needs`](#needs) keyword.
### `workflow`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29654) in GitLab 12.5
-Use `workflow:` to determine whether or not a pipeline is created.
-Define this keyword at the top level, with a single `rules:` keyword that
-is similar to [`rules:` defined in jobs](#rules).
+Use [`workflow`](workflow.md) to control pipeline behavior.
-You can use the [`workflow:rules` templates](#workflowrules-templates) to import
-a preconfigured `workflow: rules` entry.
+**Related topics**:
-`workflow: rules` accepts these keywords:
+- [`workflow: rules` examples](workflow.md#workflow-rules-examples)
+- [Switch between branch pipelines and merge request pipelines](workflow.md#switch-between-branch-pipelines-and-merge-request-pipelines)
-- [`if`](#rulesif): Check this rule to determine when to run a pipeline.
-- [`when`](#when): Specify what to do when the `if` rule evaluates to true.
- - To run a pipeline, set to `always`.
- - To prevent pipelines from running, set to `never`.
-- [`variables`](#workflowrulesvariables): If not defined, uses the [variables defined elsewhere](#variables).
+#### `workflow:rules`
-When no rules evaluate to true, the pipeline does not run.
+The `rules` keyword in `workflow` is similar to [`rules:` defined in jobs](#rules),
+but controls whether or not a whole pipeline is created.
-Some example `if` clauses for `workflow: rules`:
+When no rules evaluate to true, the pipeline does not run.
-| Example rules | Details |
-|------------------------------------------------------|-----------------------------------------------------------|
-| `if: '$CI_PIPELINE_SOURCE == "merge_request_event"'` | Control when merge request pipelines run. |
-| `if: '$CI_PIPELINE_SOURCE == "push"'` | Control when both branch pipelines and tag pipelines run. |
-| `if: $CI_COMMIT_TAG` | Control when tag pipelines run. |
-| `if: $CI_COMMIT_BRANCH` | Control when branch pipelines run. |
+**Possible inputs**: You can use some of the same keywords as job-level [`rules`](#rules):
-See the [common `if` clauses for `rules`](../jobs/job_control.md#common-if-clauses-for-rules) for more examples.
+- [`rules: if`](#rulesif).
+- [`rules: changes`](#ruleschanges).
+- [`rules: exists`](#rulesexists).
+- [`when`](#when), can only be `always` or `never` when used with `workflow`.
+- [`variables`](#workflowrulesvariables).
-In the following example, pipelines run for all `push` events (changes to
-branches and new tags). Pipelines for push events with `-draft` in the commit message
-don't run, because they are set to `when: never`. Pipelines for schedules or merge requests
-don't run either, because no rules evaluate to true for them:
+**Example of `workflow:rules`:**
```yaml
workflow:
rules:
- if: $CI_COMMIT_MESSAGE =~ /-draft$/
when: never
- - if: '$CI_PIPELINE_SOURCE == "push"'
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```
-This example has strict rules, and pipelines do **not** run in any other case.
+In this example, pipelines run if the commit message does not have `-drafts` in it
+and the pipeline is for either:
-Alternatively, all of the rules can be `when: never`, with a final
-`when: always` rule. Pipelines that match the `when: never` rules do not run.
-All other pipeline types run:
+- A merge request
+- The default branch.
-```yaml
-workflow:
- rules:
- - if: '$CI_PIPELINE_SOURCE == "schedule"'
- when: never
- - if: '$CI_PIPELINE_SOURCE == "push"'
- when: never
- - when: always
-```
+**Additional details**:
-This example prevents pipelines for schedules or `push` (branches and tags) pipelines.
-The final `when: always` rule runs all other pipeline types, **including** merge
-request pipelines.
+- If your rules match both branch pipelines (other than the default branch) and merge request pipelines,
+ [duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines) can occur.
-If your rules match both branch pipelines and merge request pipelines,
-[duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines) can occur.
+**Related topics**:
+
+- You can use the [`workflow:rules` templates](workflow.md#workflowrules-templates) to import
+ a preconfigured `workflow: rules` entry.
+- [Common `if` clauses for `workflow:rules`](workflow.md#common-if-clauses-for-workflowrules).
#### `workflow:rules:variables`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294232) in GitLab 13.11.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/300997) in GitLab 14.1.
-You can use [`variables`](#variables) in `workflow:rules:` to define variables for specific pipeline conditions.
+You can use [`variables`](#variables) in `workflow:rules:` to define variables for
+specific pipeline conditions.
-For example:
+When the condition matches, the variable is created and can be used by all jobs
+in the pipeline. If the variable is already defined at the global level, the `workflow`
+variable takes precedence and overrides the global variable.
+
+**Keyword type**: Global keyword.
+
+**Possible inputs**: Variable name and value pairs:
+
+- The name can use only numbers, letters, and underscores (`_`).
+- The value must be a string.
+
+**Example of `workflow:rules:variables`:**
```yaml
variables:
@@ -289,198 +289,61 @@ When the branch is something else:
- job1's `DEPLOY_VARIABLE` is `job1-default-deploy`.
- job2's `DEPLOY_VARIABLE` is `default-deploy`.
-#### `workflow:rules` templates
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217732) in GitLab 13.0.
-
-GitLab provides templates that set up `workflow: rules`
-for common scenarios. These templates help prevent duplicate pipelines.
-
-The [`Branch-Pipelines` template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Workflows/Branch-Pipelines.gitlab-ci.yml)
-makes your pipelines run for branches and tags.
-
-Branch pipeline status is displayed in merge requests that use the branch
-as a source. However, this pipeline type does not support any features offered by
-[merge request pipelines](../pipelines/merge_request_pipelines.md), like
-[pipelines for merged results](../pipelines/pipelines_for_merged_results.md)
-or [merge trains](../pipelines/merge_trains.md).
-This template intentionally avoids those features.
-
-To [include](#include) it:
-
-```yaml
-include:
- - template: 'Workflows/Branch-Pipelines.gitlab-ci.yml'
-```
-
-The [`MergeRequest-Pipelines` template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Workflows/MergeRequest-Pipelines.gitlab-ci.yml)
-makes your pipelines run for the default branch, tags, and
-all types of merge request pipelines. Use this template if you use any of the
-the [pipelines for merge requests features](../pipelines/merge_request_pipelines.md).
-
-To [include](#include) it:
-
-```yaml
-include:
- - template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml'
-```
-
-#### Switch between branch pipelines and merge request pipelines
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/201845) in GitLab 13.8.
-
-To make the pipeline switch from branch pipelines to merge request pipelines after
-a merge request is created, add a `workflow: rules` section to your `.gitlab-ci.yml` file.
-
-If you use both pipeline types at the same time, [duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines)
-might run at the same time. To prevent duplicate pipelines, use the
-[`CI_OPEN_MERGE_REQUESTS` variable](../variables/predefined_variables.md).
-
-The following example is for a project that runs branch and merge request pipelines only,
-but does not run pipelines for any other case. It runs:
-
-- Branch pipelines when a merge request is not open for the branch.
-- Merge request pipelines when a merge request is open for the branch.
-
-```yaml
-workflow:
- rules:
- - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
- when: never
- - if: '$CI_COMMIT_BRANCH'
-```
-
-If the pipeline is triggered by:
-
-- A merge request, run a merge request pipeline. For example, a merge request pipeline
- can be triggered by a push to a branch with an associated open merge request.
-- A change to a branch, but a merge request is open for that branch, do not run a branch pipeline.
-- A change to a branch, but without any open merge requests, run a branch pipeline.
-
-You can also add a rule to an existing `workflow` section to switch from branch pipelines
-to merge request pipelines when a merge request is created.
-
-Add this rule to the top of the `workflow` section, followed by the other rules that
-were already present:
-
-```yaml
-workflow:
- rules:
- - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
- when: never
- - ... # Previously defined workflow rules here
-```
-
-[Triggered pipelines](../triggers/index.md) that run on a branch have a `$CI_COMMIT_BRANCH`
-set and could be blocked by a similar rule. Triggered pipelines have a pipeline source
-of `trigger` or `pipeline`, so `&& $CI_PIPELINE_SOURCE == "push"` ensures the rule
-does not block triggered pipelines.
-
### `include`
> [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/42861) to GitLab Free in 11.4.
Use `include` to include external YAML files in your CI/CD configuration.
-You can break down one long `.gitlab-ci.yml` file into multiple files to increase readability,
+You can split one long `.gitlab-ci.yml` file into multiple files to increase readability,
or reduce duplication of the same configuration in multiple places.
-You can also store template files in a central repository and `include` them in projects.
-
-`include` requires the external YAML file to have the extensions `.yml` or `.yaml`,
-otherwise the external file is not included.
-
-You can't use [YAML anchors](#anchors) across different YAML files sourced by `include`.
-You can only refer to anchors in the same file. To reuse configuration from different
-YAML files, use [`!reference` tags](#reference-tags) or the [`extends` keyword](#extends).
-
-`include` supports the following inclusion methods:
-
-| Keyword | Method |
-|:--------------------------------|:------------------------------------------------------------------|
-| [`local`](#includelocal) | Include a file from the local project repository. |
-| [`file`](#includefile) | Include a file from a different project repository. |
-| [`remote`](#includeremote) | Include a file from a remote URL. Must be publicly accessible. |
-| [`template`](#includetemplate) | Include templates that are provided by GitLab. |
-
-When the pipeline starts, the `.gitlab-ci.yml` file configuration included by all methods is evaluated.
-The configuration is a snapshot in time and persists in the database. GitLab does not reflect any changes to
-the referenced `.gitlab-ci.yml` file configuration until the next pipeline starts.
+You can also store template files in a central repository and include them in projects.
The `include` files are:
-- Deep merged with those in the `.gitlab-ci.yml` file.
-- Always evaluated first and merged with the content of the `.gitlab-ci.yml` file,
+- Merged with those in the `.gitlab-ci.yml` file.
+- Always evaluated first and then merged with the content of the `.gitlab-ci.yml` file,
regardless of the position of the `include` keyword.
-NOTE:
-Use merging to customize and override included CI/CD configurations with local
-configurations. Local configurations in the `.gitlab-ci.yml` file override included configurations.
-
-#### Variables with `include`
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/284883) in GitLab 13.8.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/294294) in GitLab 13.9.
-> - [Support for project, group, and instance variables added](https://gitlab.com/gitlab-org/gitlab/-/issues/219065) in GitLab 14.2.
+You can [nest](includes.md#use-nested-includes) up to 100 includes, but you can't have duplicate includes.
+In [GitLab 12.4 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/28212),
+the time limit to resolve all files is 30 seconds.
-In `include` sections in your `.gitlab-ci.yml` file, you can use:
+**Keyword type**: Global keyword.
-- `$CI_COMMIT_REF_NAME` [predefined variable](../variables/predefined_variables.md) in GitLab 14.2
- and later.
-- [Project variables](../variables/index.md#add-a-cicd-variable-to-a-project)
-- [Group variables](../variables/index.md#add-a-cicd-variable-to-a-group)
-- [Instance variables](../variables/index.md#add-a-cicd-variable-to-an-instance)
-- Project [predefined variables](../variables/predefined_variables.md).
+**Possible inputs**: The `include` subkeys:
-```yaml
-include:
- project: '$CI_PROJECT_PATH'
- file: '.compliance-gitlab-ci.yml'
-```
-
-For an example of how you can include these predefined variables, and the variables' impact on CI/CD jobs,
-see this [CI/CD variable demo](https://youtu.be/4XR8gw3Pkos).
-
-There is a [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/337633)
-that proposes expanding this feature to support more variables.
+- [`include:local`](#includelocal)
+- [`include:file`](#includefile)
+- [`include:remote`](#includeremote)
+- [`include:template`](#includetemplate)
-#### `rules` with `include`
-
-> - Introduced in GitLab 14.2 [with a flag](../../administration/feature_flags.md) named `ci_include_rules`. Disabled by default.
-> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/337507) in GitLab 14.3.
-> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/337507) GitLab 14.3.
-> - [Feature flag `ci_include_rules` removed](https://gitlab.com/gitlab-org/gitlab/-/issues/337507) in GitLab 14.4.
-> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/337507) in GitLab 14.4.
+**Additional details**:
-You can use [`rules`](#rules) with `include` to conditionally include other configuration files.
-You can only use [`if` rules](#rulesif) in `include`, and only with [certain variables](#variables-with-include).
-`rules` keywords such as `changes` and `exists` are not supported.
+- Use merging to customize and override included CI/CD configurations with local
+- You can override included configuration by having the same job name or global keyword
+ in the `.gitlab-ci.yml` file. The two configurations are merged together, and the
+ configuration in the `.gitlab-ci.yml` file takes precedence over the included configuration.
-```yaml
-include:
- - local: builds.yml
- rules:
- - if: '$INCLUDE_BUILDS == "true"'
+**Related topics**:
-test:
- stage: test
- script: exit 0
-```
+- [Use variables with `include`](includes.md#use-variables-with-include).
+- [Use `rules` with `include`](includes.md#use-rules-with-include).
#### `include:local`
Use `include:local` to include a file that is in the same repository as the `.gitlab-ci.yml` file.
-Use a full path relative to the root directory (`/`).
+Use `include:local` instead of symbolic links.
-If you use `include:local`, make sure that both the `.gitlab-ci.yml` file and the local file
-are on the same branch.
+**Keyword type**: Global keyword.
-You can't include local files through Git submodules paths.
+**Possible inputs**:
-All [nested includes](#nested-includes) are executed in the scope of the same project,
-so it's possible to use local, project, remote, or template includes.
+- A full path relative to the root directory (`/`).
+- The YAML file must have the extension `.yml` or `.yaml`.
+- You can [use `*` and `**` wildcards in the file path](includes.md#use-includelocal-with-wildcard-file-paths).
-Example:
+**Example of `include:local`**:
```yaml
include:
@@ -493,44 +356,26 @@ You can also use shorter syntax to define the path:
include: '.gitlab-ci-production.yml'
```
-Use local includes instead of symbolic links.
-
-##### `include:local` with wildcard file paths
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25921) in GitLab 13.11.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/327315) in GitLab 14.2.
-
-You can use wildcard paths (`*` and `**`) with `include:local`.
-
-Example:
-
-```yaml
-include: 'configs/*.yml'
-```
-
-When the pipeline runs, GitLab:
-
-- Adds all `.yml` files in the `configs` directory into the pipeline configuration.
-- Does not add `.yml` files in subfolders of the `configs` directory. To allow this,
- add the following configuration:
-
- ```yaml
- # This matches all `.yml` files in `configs` and any subfolder in it.
- include: 'configs/**.yml'
+**Additional details**:
- # This matches all `.yml` files only in subfolders of `configs`.
- include: 'configs/**/*.yml'
- ```
+- The `.gitlab-ci.yml` file and the local file must be on the same branch.
+- You can't include local files through Git submodules paths.
+- All [nested includes](includes.md#use-nested-includes) are executed in the scope of the same project,
+ so you can use local, project, remote, or template includes.
#### `include:file`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53903) in GitLab 11.7.
+> Including multiple files from the same project [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26793) in GitLab 13.6. [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/271560) in GitLab 13.8.
To include files from another private project on the same GitLab instance,
use `include:file`. You can use `include:file` in combination with `include:project` only.
-Use a full path, relative to the root directory (`/`).
-For example:
+**Keyword type**: Global keyword.
+
+**Possible inputs**: A full path, relative to the root directory (`/`).
+The YAML file must have the extension `.yml` or `.yaml`.
+
+**Example of `include:file`**:
```yaml
include:
@@ -555,14 +400,6 @@ include:
file: '/templates/.gitlab-ci-template.yml'
```
-All [nested includes](#nested-includes) are executed in the scope of the target project.
-You can use local (relative to target project), project, remote, or template includes.
-
-##### Multiple files from a project
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26793) in GitLab 13.6.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/271560) in GitLab 13.8.
-
You can include multiple files from the same project:
```yaml
@@ -574,28 +411,52 @@ include:
- '/templates/.tests.yml'
```
+**Additional details**:
+
+- All [nested includes](includes.md#use-nested-includes) are executed in the scope of the target project.
+ You can use `local` (relative to the target project), `project`, `remote`, or `template` includes.
+- When the pipeline starts, the `.gitlab-ci.yml` file configuration included by all methods is evaluated.
+ The configuration is a snapshot in time and persists in the database. GitLab does not reflect any changes to
+ the referenced `.gitlab-ci.yml` file configuration until the next pipeline starts.
+- When you include a YAML file from another private project, the user running the pipeline
+ must be a member of both projects and have the appropriate permissions to run pipelines.
+ A `not found or access denied` error may be displayed if the user does not have access to any of the included files.
+
#### `include:remote`
Use `include:remote` with a full URL to include a file from a different location.
-The remote file must be publicly accessible by an HTTP/HTTPS `GET` request, because
-authentication in the remote URL is not supported. For example:
+
+**Keyword type**: Global keyword.
+
+**Possible inputs**: A public URL accessible by an HTTP/HTTPS `GET` request.
+Authentication with the remote URL is not supported.
+
+The YAML file must have the extension `.yml` or `.yaml`.
+
+**Example of `include:remote`**:
```yaml
include:
- remote: 'https://gitlab.com/example-project/-/raw/main/.gitlab-ci.yml'
```
-All [nested includes](#nested-includes) execute without context as a public user,
-so you can only `include` public projects or templates.
+**Additional details**:
+
+- All [nested includes](includes.md#use-nested-includes) execute without context as a public user,
+ so you can only include public projects or templates.
+- Be careful when including a remote CI/CD configuration file. No pipelines or notifications
+ trigger when external CI/CD configuration files change. From a security perspective,
+ this is similar to pulling a third-party dependency.
#### `include:template`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53445) in GitLab 11.7.
+Use `include:template` to include [`.gitlab-ci.yml` templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
-Use `include:template` to include `.gitlab-ci.yml` templates that are
-[shipped with GitLab](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
+**Keyword type**: Global keyword.
-For example:
+**Possible inputs**: [`.gitlab-ci.yml` templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
+
+**Example of `include:template`**:
```yaml
# File sourced from the GitLab template collection
@@ -611,82 +472,145 @@ include:
- template: Auto-DevOps.gitlab-ci.yml
```
-All [nested includes](#nested-includes) are executed only with the permission of the user,
-so it's possible to use project, remote or template includes.
+**Additional details**:
-#### Nested includes
+- All [nested includes](includes.md#use-nested-includes) are executed only with the permission of the user,
+ so it's possible to use `project`, `remote`, or `template` includes.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/56836) in GitLab 11.9.
+## Job keywords
-Use nested includes to compose a set of includes.
+The following topics explain how to use keywords to configure CI/CD pipelines.
-You can have up to 100 includes, but you can't have duplicate includes.
+### `image`
-In [GitLab 12.4 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/28212), the time limit
-to resolve all files is 30 seconds.
+Use `image` to specify a Docker image that the job runs in.
-#### Additional `includes` examples
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default:` section](#default).
-View [additional `includes` examples](includes.md).
+**Possible inputs**: The name of the image, including the registry path if needed, in one of these formats:
-## Keyword details
+- `<image-name>` (Same as using `<image-name>` with the `latest` tag)
+- `<image-name>:<tag>`
+- `<image-name>@<digest>`
-The following topics explain how to use keywords to configure CI/CD pipelines.
+**Example of `image`**:
-### `image`
+```yaml
+default:
+ image: ruby:3.0
-Use `image` to specify [a Docker image](../docker/using_docker_images.md#what-is-an-image) to use for the job.
+rspec:
+ script: bundle exec rspec
-For:
+rspec 2.7:
+ image: registry.example.com/my-group/my-project/ruby:2.7
+ script: bundle exec rspec
+```
-- Usage examples, see [Define `image` in the `.gitlab-ci.yml` file](../docker/using_docker_images.md#define-image-in-the-gitlab-ciyml-file).
-- Detailed usage information, refer to [Docker integration](../docker/index.md) documentation.
+In this example, the `ruby:3.0` image is the default for all jobs in the pipeline.
+The `rspec 2.7` job does not use the default, because it overrides the default with
+a job-specific `image:` section.
+
+**Related topics**:
+
+- [Run your CI/CD jobs in Docker containers](../docker/using_docker_images.md).
#### `image:name`
-An [extended Docker configuration option](../docker/using_docker_images.md#extended-docker-configuration-options).
+The name of the Docker image that the job runs in. Similar to [`image:`](#image) used by itself.
+
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default:` section](#default).
+
+**Possible inputs**: The name of the image, including the registry path if needed, in one of these formats:
+
+- `<image-name>` (Same as using `<image-name>` with the `latest` tag)
+- `<image-name>:<tag>`
+- `<image-name>@<digest>`
-For more information, see [Available settings for `image`](../docker/using_docker_images.md#available-settings-for-image).
+**Example of `image:name`**:
+
+```yaml
+image:
+ name: "registry.example.com/my/image:latest"
+```
+
+**Related topics**:
+
+- [Run your CI/CD jobs in Docker containers](../docker/using_docker_images.md).
#### `image:entrypoint`
-An [extended Docker configuration option](../docker/using_docker_images.md#extended-docker-configuration-options).
+Command or script to execute as the container's entry point.
-For more information, see [Available settings for `image`](../docker/using_docker_images.md#available-settings-for-image).
+When the Docker container is created, the `entrypoint` is translated to the Docker `--entrypoint` option.
+The syntax is similar to the [Dockerfile `ENTRYPOINT` directive](https://docs.docker.com/engine/reference/builder/#entrypoint),
+where each shell token is a separate string in the array.
-#### `services`
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default:` section](#default).
-Use `services` to specify a [service Docker image](../services/index.md), linked to a base image specified in [`image`](#image).
+**Possible inputs**: A string.
-For:
+**Example of `image:entrypoint`**:
-- Usage examples, see [Define `services` in the `.gitlab-ci.yml` file](../services/index.md#define-services-in-the-gitlab-ciyml-file).
-- Detailed usage information, refer to [Docker integration](../docker/index.md) documentation.
-- Example services, see [GitLab CI/CD Services](../services/index.md).
+```yaml
+image:
+ name: super/sql:experimental
+ entrypoint: [""]
+```
+
+**Related topics**:
+
+- [Override the entrypoint of an image](../docker/using_docker_images.md#override-the-entrypoint-of-an-image).
-##### `services:name`
+#### `services`
+
+Use `services` to specify an additional Docker image to run scripts in. The [`services` image](../services/index.md) is linked
+to the image specified in the [`image`](#image) keyword.
-An [extended Docker configuration option](../docker/using_docker_images.md#extended-docker-configuration-options).
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default:` section](#default).
-For more information, see [Available settings for `services`](../services/index.md#available-settings-for-services).
+**Possible inputs**: The name of the services image, including the registry path if needed, in one of these formats:
-##### `services:alias`
+- `<image-name>` (Same as using `<image-name>` with the `latest` tag)
+- `<image-name>:<tag>`
+- `<image-name>@<digest>`
-An [extended Docker configuration option](../docker/using_docker_images.md#extended-docker-configuration-options).
+**Example of `services`**:
-For more information, see [Available settings for `services`](../services/index.md#available-settings-for-services).
+```yaml
+default:
+ image:
+ name: ruby:2.6
+ entrypoint: ["/bin/bash"]
-##### `services:entrypoint`
+ services:
+ - name: my-postgres:11.7
+ alias: db-postgres
+ entrypoint: ["/usr/local/bin/db-postgres"]
+ command: ["start"]
-An [extended Docker configuration option](../docker/using_docker_images.md#extended-docker-configuration-options).
+ before_script:
+ - bundle install
-For more information, see [Available settings for `services`](../services/index.md#available-settings-for-services).
+test:
+ script:
+ - bundle exec rake spec
+```
-##### `services:command`
+In this example, the job launches a Ruby container. Then, from that container, the job launches
+another container that's running PostgreSQL. Then the job then runs scripts
+in that container.
-An [extended Docker configuration option](../docker/using_docker_images.md#extended-docker-configuration-options).
+**Related topics**:
-For more information, see [Available settings for `services`](../services/index.md#available-settings-for-services).
+- [Available settings for `services`](../services/index.md#available-settings-for-services).
+- [Define `services` in the `.gitlab-ci.yml` file](../services/index.md#define-services-in-the-gitlab-ciyml-file).
+- [Run your CI/CD jobs in Docker containers](../docker/using_docker_images.md).
+- [Use Docker to build Docker images](../docker/using_docker_build.md).
### `script`
@@ -700,7 +624,7 @@ All jobs except [trigger jobs](#trigger) require a `script` keyword.
- Single line commands.
- Long commands [split over multiple lines](script.md#split-long-commands).
-- [YAML anchors](#yaml-anchors-for-scripts).
+- [YAML anchors](yaml_optimization.md#yaml-anchors-for-scripts).
**Example of `script`:**
@@ -716,8 +640,7 @@ job2:
**Additional details**:
-You might need to use single quotes (`'`) or double quotes (`"`) when using
-[special characters in `script`](script.md#use-special-characters-with-script).
+- When you use [these special characters in `script`](script.md#use-special-characters-with-script), you must use single quotes (`'`) or double quotes (`"`) .
**Related topics**:
@@ -733,13 +656,13 @@ Use `before_script` to define an array of commands that should run before each j
`script` commands, but after [artifacts](#artifacts) are restored.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#custom-default-keyword-values).
+[`default:` section](#default).
**Possible inputs**: An array including:
- Single line commands.
- Long commands [split over multiple lines](script.md#split-long-commands).
-- [YAML anchors](#yaml-anchors-for-scripts).
+- [YAML anchors](yaml_optimization.md#yaml-anchors-for-scripts).
**Example of `before_script`:**
@@ -753,8 +676,8 @@ job:
**Additional details**:
-Scripts you specify in `before_script` are concatenated with any scripts you specify
-in the main [`script`](#script). The combined scripts execute together in a single shell.
+- Scripts you specify in `before_script` are concatenated with any scripts you specify
+ in the main [`script`](#script). The combined scripts execute together in a single shell.
**Related topics**:
@@ -771,13 +694,13 @@ in the main [`script`](#script). The combined scripts execute together in a sing
Use `after_script` to define an array of commands that run after each job, including failed jobs.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#custom-default-keyword-values).
+[`default:` section](#default).
**Possible inputs**: An array including:
- Single line commands.
- Long commands [split over multiple lines](script.md#split-long-commands).
-- [YAML anchors](#yaml-anchors-for-scripts).
+- [YAML anchors](yaml_optimization.md#yaml-anchors-for-scripts).
**Example of `after_script`:**
@@ -794,7 +717,7 @@ job:
Scripts you specify in `after_script` execute in a new shell, separate from any
`before_script` or `script` commands. As a result, they:
-- Have the current working directory set back to the default (according to the [variables which define how the runner processes Git requests](#configure-runner-behavior-with-variables)).
+- Have the current working directory set back to the default (according to the [variables which define how the runner processes Git requests](../runners/configure_runners.md#configure-runner-behavior-with-variables)).
- Don't have access to changes done by commands defined in the `before_script` or `script`,
including:
- Command aliases and variables exported in `script` scripts.
@@ -872,7 +795,7 @@ job4:
Use the `.pre` stage to make a job run at the start of a pipeline. `.pre` is
always the first stage in a pipeline. User-defined stages execute after `.pre`.
-You do not need to define `.pre` in [`stages`](#stages).
+You do not have to define `.pre` in [`stages`](#stages).
You must have a job in at least one stage other than `.pre` or `.post`.
@@ -907,7 +830,7 @@ job2:
Use the `.post` stage to make a job run at the end of a pipeline. `.post`
is always the last stage in a pipeline. User-defined stages execute before `.post`.
-You do not need to define `.post` in [`stages`](#stages).
+You do not have to define `.post` in [`stages`](#stages).
You must have a job in at least one stage other than `.pre` or `.post`.
@@ -938,18 +861,17 @@ job2:
### `extends`
-> Introduced in GitLab 11.3.
+Use `extends` to reuse configuration sections. It's an alternative to [YAML anchors](yaml_optimization.md#anchors)
+and is a little more flexible and readable.
-Use `extends` to reuse configuration sections. It's an alternative to [YAML anchors](#anchors)
-and is a little more flexible and readable. You can use `extends` to reuse configuration
-from [included configuration files](#use-extends-and-include-together).
+**Keyword type**: Job keyword. You can use it only as part of a job.
-In the following example, the `rspec` job uses the configuration from the `.tests` template job.
-GitLab:
+**Possible inputs:**
-- Performs a reverse deep merge based on the keys.
-- Merges the `.tests` content with the `rspec` job.
-- Doesn't merge the values of the keys.
+- The name of another job in the pipeline.
+- A list (array) of names of other jobs in the pipeline.
+
+**Example of `extends`:**
```yaml
.tests:
@@ -967,6 +889,13 @@ rspec:
- $RSPEC
```
+In this example, the `rspec` job uses the configuration from the `.tests` template job.
+When creating the pipeline, GitLab:
+
+- Performs a reverse deep merge based on the keys.
+- Merges the `.tests` content with the `rspec` job.
+- Doesn't merge the values of the keys.
+
The result is this `rspec` job:
```yaml
@@ -980,127 +909,18 @@ rspec:
- $RSPEC
```
-`.tests` in this example is a [hidden job](#hide-jobs), but it's
-possible to extend configuration from regular jobs as well.
-
-`extends` supports multi-level inheritance. You should avoid using more than three levels,
-but you can use as many as eleven. The following example has two levels of inheritance:
-
-```yaml
-.tests:
- rules:
- - if: $CI_PIPELINE_SOURCE == "push"
-
-.rspec:
- extends: .tests
- script: rake rspec
-
-rspec 1:
- variables:
- RSPEC_SUITE: '1'
- extends: .rspec
-
-rspec 2:
- variables:
- RSPEC_SUITE: '2'
- extends: .rspec
-
-spinach:
- extends: .tests
- script: rake spinach
-```
-
-In GitLab 12.0 and later, it's also possible to use multiple parents for
-`extends`.
-
-#### Merge details
-
-You can use `extends` to merge hashes but not arrays.
-The algorithm used for merge is "closest scope wins," so
-keys from the last member always override anything defined on other
-levels. For example:
-
-```yaml
-.only-important:
- variables:
- URL: "http://my-url.internal"
- IMPORTANT_VAR: "the details"
- rules:
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- - if: $CI_COMMIT_BRANCH == "stable"
- tags:
- - production
- script:
- - echo "Hello world!"
-
-.in-docker:
- variables:
- URL: "http://docker-url.internal"
- tags:
- - docker
- image: alpine
-
-rspec:
- variables:
- GITLAB: "is-awesome"
- extends:
- - .only-important
- - .in-docker
- script:
- - rake rspec
-```
-
-The result is this `rspec` job:
-
-```yaml
-rspec:
- variables:
- URL: "http://docker-url.internal"
- IMPORTANT_VAR: "the details"
- GITLAB: "is-awesome"
- rules:
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- - if: $CI_COMMIT_BRANCH == "stable"
- tags:
- - docker
- image: alpine
- script:
- - rake rspec
-```
-
-In this example:
-
-- The `variables` sections merge, but `URL: "http://docker-url.internal"` overwrites `URL: "http://my-url.internal"`.
-- `tags: ['docker']` overwrites `tags: ['production']`.
-- `script` does not merge, but `script: ['rake rspec']` overwrites
- `script: ['echo "Hello world!"']`. You can use [YAML anchors](#anchors) to merge arrays.
-
-#### Use `extends` and `include` together
-
-To reuse configuration from different configuration files,
-combine `extends` and [`include`](#include).
-
-In the following example, a `script` is defined in the `included.yml` file.
-Then, in the `.gitlab-ci.yml` file, `extends` refers
-to the contents of the `script`:
-
-- `included.yml`:
-
- ```yaml
- .template:
- script:
- - echo Hello!
- ```
+**Additional details:**
-- `.gitlab-ci.yml`:
+- In GitLab 12.0 and later, you can use multiple parents for `extends`.
+- The `extends` keyword supports up to eleven levels of inheritance, but you should
+ avoid using more than three levels.
+- In the example above, `.tests` is a [hidden job](../jobs/index.md#hide-jobs),
+ but you can extend configuration from regular jobs as well.
- ```yaml
- include: included.yml
+**Related topics:**
- useTemplate:
- image: alpine
- extends: .template
- ```
+- [Reuse configuration sections by using `extends`](yaml_optimization.md#use-extends-to-reuse-configuration-sections).
+- Use `extends` to reuse configuration from [included configuration files](yaml_optimization.md#use-extends-and-include-together).
### `rules`
@@ -1108,8 +928,11 @@ to the contents of the `script`:
Use `rules` to include or exclude jobs in pipelines.
-Rules are evaluated *in order* until the first match. When a match is found, the job
-is either included or excluded from the pipeline, depending on the configuration.
+Rules are evaluated when the pipeline is created, and evaluated *in order*
+until the first match. When a match is found, the job is either included or excluded from the pipeline,
+depending on the configuration.
+
+You cannot use dotenv variables created in job scripts in rules, because rules are evaluated before any jobs run.
`rules` replaces [`only/except`](#only--except) and they can't be used together
in the same job. If you configure one job to use both keywords, the GitLab returns
@@ -1137,7 +960,7 @@ The job is not added to the pipeline:
- If no rules match.
- If a rule matches and has `when: never`.
-You can use [`!reference` tags](#reference-tags) to [reuse `rules` configuration](../jobs/job_control.md#reuse-rules-in-different-jobs)
+You can use [`!reference` tags](yaml_optimization.md#reference-tags) to [reuse `rules` configuration](../jobs/job_control.md#reuse-rules-in-different-jobs)
in different jobs.
#### `rules:if`
@@ -1178,7 +1001,7 @@ job:
all rules. You can't mix `when` at the job-level with `when` in rules.
- Unlike variables in [`script`](../variables/index.md#use-cicd-variables-in-job-scripts)
sections, variables in rules expressions are always formatted as `$VARIABLE`.
- - You can use `rules:if` with `include` to [conditionally include other configuration files](#rules-with-include).
+ - You can use `rules:if` with `include` to [conditionally include other configuration files](includes.md#use-rules-with-include).
**Related topics**:
@@ -1225,6 +1048,7 @@ docker build:
- `rules: changes` works the same way as [`only: changes` and `except: changes`](#onlychanges--exceptchanges).
- You can use `when: never` to implement a rule similar to [`except:changes`](#onlychanges--exceptchanges).
+- `changes` resolves to `true` if any of the matching files are changed (an `OR` operation).
#### `rules:exists`
@@ -1257,6 +1081,7 @@ job:
file paths. After the 10,000th check, rules with patterned globs always match.
In other words, the `exists` rule always assumes a match in projects with more
than 10,000 files.
+- `exists` resolves to `true` if any of the listed files are found (an `OR` operation).
#### `rules:allow_failure`
@@ -1369,7 +1194,7 @@ pipeline based on branch names or pipeline types.
| `schedules` | For [scheduled pipelines](../pipelines/schedules.md). |
| `tags` | When the Git reference for a pipeline is a tag. |
| `triggers` | For pipelines created by using a [trigger token](../triggers/index.md#authentication-tokens). |
- | `web` | For pipelines created by using **Run pipeline** button in the GitLab UI, from the project's **CI/CD > Pipelines** section. |
+ | `web` | For pipelines created by selecting **Run pipeline** in the GitLab UI, from the project's **CI/CD > Pipelines** section. |
**Example of `only:refs` and `except:refs`**:
@@ -1453,8 +1278,6 @@ deploy:
#### `only:changes` / `except:changes`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/19232) in GitLab 11.4.
-
Use the `changes` keyword with `only` to run a job, or with `except` to skip a job,
when a Git push event modifies a file.
@@ -1489,10 +1312,12 @@ docker build:
- docker/scripts/*
- dockerfiles/**/*
- more_scripts/*.{rb,py,sh}
+ - "**/*.json"
```
**Additional details**:
+- `changes` resolves to `true` if any of the matching files are changed (an `OR` operation).
- If you use refs other than `branches`, `external_pull_requests`, or `merge_requests`,
`changes` can't determine if a given file is new or old and always returns `true`.
- If you use `only: changes` with other refs, jobs ignore the changes and always run.
@@ -1539,16 +1364,14 @@ that use `needs` can be visualized as a [directed acyclic graph](../directed_acy
You can ignore stage ordering and run some jobs without waiting for others to complete.
Jobs in multiple stages can run concurrently.
-The following example creates four paths of execution:
+**Keyword type**: Job keyword. You can use it only as part of a job.
-- Linter: the `lint` job runs immediately without waiting for the `build` stage
- to complete because it has no needs (`needs: []`).
-- Linux path: the `linux:rspec` and `linux:rubocop` jobs runs as soon as the `linux:build`
- job finishes without waiting for `mac:build` to finish.
-- macOS path: the `mac:rspec` and `mac:rubocop` jobs runs as soon as the `mac:build`
- job finishes, without waiting for `linux:build` to finish.
-- The `production` job runs as soon as all previous jobs finish; in this case:
- `linux:build`, `linux:rspec`, `linux:rubocop`, `mac:build`, `mac:rspec`, `mac:rubocop`.
+**Possible inputs**:
+
+- An array of jobs.
+- An empty array (`[]`), to set the job to start as soon as the pipeline is created.
+
+**Example of `needs`**:
```yaml
linux:build:
@@ -1569,32 +1392,33 @@ linux:rspec:
needs: ["linux:build"]
script: echo "Running rspec on linux..."
-linux:rubocop:
- stage: test
- needs: ["linux:build"]
- script: echo "Running rubocop on linux..."
-
mac:rspec:
stage: test
needs: ["mac:build"]
script: echo "Running rspec on mac..."
-mac:rubocop:
- stage: test
- needs: ["mac:build"]
- script: echo "Running rubocop on mac..."
-
production:
stage: deploy
script: echo "Running production..."
```
-#### Requirements and limitations
+This example creates four paths of execution:
+
+- Linter: The `lint` job runs immediately without waiting for the `build` stage
+ to complete because it has no needs (`needs: []`).
+- Linux path: The `linux:rspec` job runs as soon as the `linux:build`
+ job finishes, without waiting for `mac:build` to finish.
+- macOS path: The `mac:rspec` jobs runs as soon as the `mac:build`
+ job finishes, without waiting for `linux:build` to finish.
+- The `production` job runs as soon as all previous jobs finish:
+ `linux:build`, `linux:rspec`, `mac:build`, `mac:rspec`.
+
+**Additional details**:
-- The maximum number of jobs that a single job can need in the `needs:` array is limited:
+- The maximum number of jobs that a single job can have in the `needs:` array is limited:
- For GitLab.com, the limit is 50. For more information, see our
[infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7541).
- - For self-managed instances, the default limit is 50. This limit [can be changed](#changing-the-needs-job-limit).
+ - For self-managed instances, the default limit is 50. This limit [can be changed](../../administration/cicd.md#set-the-needs-job-limit).
- If `needs:` refers to a job that uses the [`parallel`](#parallel) keyword,
it depends on all jobs created in parallel, not just one job. It also downloads
artifacts from all the parallel jobs by default. If the artifacts have the same
@@ -1609,20 +1433,7 @@ production:
- In GitLab 13.9 and older, if `needs:` refers to a job that might not be added to
a pipeline because of `only`, `except`, or `rules`, the pipeline might fail to create.
-##### Changing the `needs:` job limit **(FREE SELF)**
-
-The maximum number of jobs that can be defined in `needs:` defaults to 50.
-
-A GitLab administrator with [access to the GitLab Rails console](../../administration/feature_flags.md)
-can choose a custom limit. For example, to set the limit to 100:
-
-```ruby
-Plan.default.actual_limits.update!(ci_needs_size_limit: 100)
-```
-
-To disable directed acyclic graphs (DAG), set the limit to `0`.
-
-#### Artifact downloads with `needs`
+#### `needs:artifacts`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14311) in GitLab 12.6.
@@ -1633,84 +1444,72 @@ by default, because jobs with `needs` can start before earlier stages complete.
Use `artifacts: true` (default) or `artifacts: false` to control when artifacts are
downloaded in jobs that use `needs`.
-In the following example, the `rspec` job downloads the `build_job` artifacts, but the
-`rubocop` job does not:
+**Keyword type**: Job keyword. You can use it only as part of a job. Must be used with `needs:job`.
-```yaml
-build_job:
- stage: build
- artifacts:
- paths:
- - binaries/
+**Possible inputs**:
-rspec:
+- `true` (default) or `false`.
+
+**Example of `needs:artifacts`**:
+
+```yaml
+test-job1:
stage: test
needs:
- - job: build_job
+ - job: build_job1
artifacts: true
-rubocop:
+test-job2:
stage: test
needs:
- - job: build_job
+ - job: build_job2
artifacts: false
-```
-
-In the following example, the `rspec` job downloads the artifacts from all three `build_jobs`.
-`artifacts` is:
-- Set to true for `build_job_1`.
-- Defaults to true for both `build_job_2` and `build_job_3`.
-
-```yaml
-rspec:
+test-job3:
needs:
- - job: build_job_1
+ - job: build_job1
artifacts: true
- - job: build_job_2
- - build_job_3
+ - job: build_job2
+ - build_job3
```
-In GitLab 12.6 and later, you can't combine the [`dependencies`](#dependencies) keyword
-with `needs`.
+In this example:
+
+- The `test-job1` job downloads the `build_job1` artifacts
+- The `test-job2` job does not download the `build_job2` artifacts.
+- The `test-job3` job downloads the artifacts from all three `build_jobs`, because
+ `artifacts:` is `true`, or defaults to `true`, for all three needed jobs.
-#### Cross project artifact downloads with `needs` **(PREMIUM)**
+**Additional details**:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14311) in GitLab 12.7.
+- In GitLab 12.6 and later, you can't combine the [`dependencies`](#dependencies) keyword
+ with `needs`.
-Use `needs` to download artifacts from up to five jobs in pipelines:
+#### `needs:project` **(PREMIUM)**
-- [On other refs in the same project](#artifact-downloads-between-pipelines-in-the-same-project).
-- In different projects, groups and namespaces.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14311) in GitLab 12.7.
-```yaml
-build_job:
- stage: build
- script:
- - ls -lhR
- needs:
- - project: namespace/group/project-name
- job: build-1
- ref: main
- artifacts: true
-```
+Use `needs:project` to download artifacts from up to five jobs in other pipelines.
+The artifacts are downloaded from the latest successful pipeline for the specified ref.
-`build_job` downloads the artifacts from the latest successful `build-1` job
-on the `main` branch in the `group/project-name` project. If the project is in the
-same group or namespace, you can omit them from the `project:` keyword. For example,
-`project: group/project-name` or `project: project-name`.
+If there is a pipeline running for the specified ref, a job with `needs:project`
+does not wait for the pipeline to complete. Instead, the job downloads the artifact
+from the latest pipeline that completed successfully.
-The user running the pipeline must have at least `reporter` access to the group or project, or the group/project must have public visibility.
+`needs:project` must be used with `job:`, `ref:`, and `artifacts:`.
-You cannot use cross project artifact downloads in the same job as [`trigger`](#trigger).
+**Keyword type**: Job keyword. You can use it only as part of a job.
-##### Artifact downloads between pipelines in the same project
+**Possible inputs**:
-Use `needs` to download artifacts from different pipelines in the current project.
-Set the `project` keyword as the current project's name, and specify a ref.
+- `needs:project`: A full project path, including namespace and group. If the
+ project is in the same group or namespace, you can omit them from the `project:`
+ keyword. For example: `project: group/project-name` or `project: project-name`.
+- `job`: The job to download artifacts from.
+- `ref`: The ref to download artifacts from.
+- `artifacts`: Must be `true` to download artifacts.
-In the following example, `build_job` downloads the artifacts for the latest successful
-`build-1` job with the `other-ref` ref:
+**Examples of `needs:project`**:
```yaml
build_job:
@@ -1718,16 +1517,17 @@ build_job:
script:
- ls -lhR
needs:
- - project: group/same-project-name
+ - project: namespace/group/project-name
job: build-1
- ref: other-ref
+ ref: main
artifacts: true
```
-CI/CD variable support for `project:`, `job:`, and `ref` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202093)
-in GitLab 13.3. [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235761) in GitLab 13.4.
+In this example, `build_job` downloads the artifacts from the latest successful `build-1` job
+on the `main` branch in the `group/project-name` project.
-For example:
+In GitLab 13.3 and later, you can use [CI/CD variables](../variables/index.md) in `needs:project`,
+for example:
```yaml
build_job:
@@ -1741,57 +1541,83 @@ build_job:
artifacts: true
```
-You can't download artifacts from jobs that run in [`parallel:`](#parallel).
+**Additional details**:
-To download artifacts between [parent-child pipelines](../pipelines/parent_child_pipelines.md),
-use [`needs:pipeline`](#artifact-downloads-to-child-pipelines).
+- To download artifacts from a different pipeline in the current project, set `project:`
+ to be the same as the current project, but use a different ref than the current pipeline.
+ Concurrent pipelines running on the same ref could override the artifacts.
+- The user running the pipeline must have at least the Reporter role for the group or project,
+ or the group/project must have public visibility.
+- You can't use `needs:project` in the same job as [`trigger`](#trigger).
+- When using `needs:project` to download artifacts from another pipeline, the job does not wait for
+ the needed job to complete. [Directed acyclic graph](../directed_acyclic_graph/index.md)
+ behavior is limited to jobs in the same pipeline. Make sure that the needed job in the other
+ pipeline completes before the job that needs it tries to download the artifacts.
+- You can't download artifacts from jobs that run in [`parallel:`](#parallel).
+- Support for [CI/CD variables](../variables/index.md) in `project`, `job`, and `ref` was
+ [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202093) in GitLab 13.3.
+ [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235761) in GitLab 13.4.
-You should not download artifacts from the same ref as a running pipeline. Concurrent
-pipelines running on the same ref could override the artifacts.
+**Related topics**:
-#### Artifact downloads to child pipelines
+- To download artifacts between [parent-child pipelines](../pipelines/parent_child_pipelines.md),
+ use [`needs:pipeline:job`](#needspipelinejob).
+
+#### `needs:pipeline:job`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255983) in GitLab 13.7.
A [child pipeline](../pipelines/parent_child_pipelines.md) can download artifacts from a job in
its parent pipeline or another child pipeline in the same parent-child pipeline hierarchy.
-For example, with the following parent pipeline that has a job that creates some artifacts:
+**Keyword type**: Job keyword. You can use it only as part of a job.
-```yaml
-create-artifact:
- stage: build
- script: echo 'sample artifact' > artifact.txt
- artifacts:
- paths: [artifact.txt]
+**Possible inputs**:
-child-pipeline:
- stage: test
- trigger:
- include: child.yml
- strategy: depend
- variables:
- PARENT_PIPELINE_ID: $CI_PIPELINE_ID
-```
+- `needs:pipeline`: A pipeline ID. Must be a pipeline present in the same parent-child pipeline hierarchy.
+- `job:`: The job to download artifacts from.
-A job in the child pipeline can download artifacts from the `create-artifact` job in
-the parent pipeline:
+**Example of `needs:pipeline:job`**:
-```yaml
-use-artifact:
- script: cat artifact.txt
- needs:
- - pipeline: $PARENT_PIPELINE_ID
- job: create-artifact
-```
+- Parent pipeline (`.gitlab-ci.yml`):
-The `pipeline` attribute accepts a pipeline ID and it must be a pipeline present
-in the same parent-child pipeline hierarchy of the given pipeline.
+ ```yaml
+ create-artifact:
+ stage: build
+ script: echo 'sample artifact' > artifact.txt
+ artifacts:
+ paths: [artifact.txt]
-The `pipeline` attribute does not accept the current pipeline ID (`$CI_PIPELINE_ID`).
-To download artifacts from a job in the current pipeline, use the basic form of [`needs`](#artifact-downloads-with-needs).
+ child-pipeline:
+ stage: test
+ trigger:
+ include: child.yml
+ strategy: depend
+ variables:
+ PARENT_PIPELINE_ID: $CI_PIPELINE_ID
+ ```
-#### Optional `needs`
+- Child pipeline (`child.yml`):
+
+ ```yaml
+ use-artifact:
+ script: cat artifact.txt
+ needs:
+ - pipeline: $PARENT_PIPELINE_ID
+ job: create-artifact
+ ```
+
+In this example, the `create-artifact` job in the parent pipeline creates some artifacts.
+The `child-pipeline` job triggers a child pipeline, and passes the `CI_PIPELINE_ID`
+variable to the child pipeline as a new `PARENT_PIPELINE_ID` variable. The child pipeline
+can use that variable in `needs:pipeline` to download artifacts from the parent pipeline.
+
+**Additional details**:
+
+- The `pipeline` attribute does not accept the current pipeline ID (`$CI_PIPELINE_ID`).
+ To download artifacts from a job in the current pipeline, use [`needs`](#needsartifacts).
+
+#### `needs:optional`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30680) in GitLab 13.10.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323891) in GitLab 14.0.
@@ -1800,20 +1626,21 @@ To need a job that sometimes does not exist in the pipeline, add `optional: true
to the `needs` configuration. If not defined, `optional: false` is the default.
Jobs that use [`rules`](#rules), [`only`, or `except`](#only--except), might
-not always exist in a pipeline. When the pipeline starts, it checks the `needs`
-relationships before running. Without `optional: true`, needs relationships that
+not always exist in a pipeline. When the pipeline is created, GitLab checks the `needs`
+relationships before starting it. Without `optional: true`, needs relationships that
point to a job that does not exist stops the pipeline from starting and causes a pipeline
error similar to:
- `'job1' job needs 'job2' job, but it was not added to the pipeline`
-In this example:
+**Keyword type**: Job keyword. You can use it only as part of a job.
-- When the branch is the default branch, the `build` job exists in the pipeline, and the `rspec`
- job waits for it to complete before starting.
-- When the branch is not the default branch, the `build` job does not exist in the pipeline.
- The `rspec` job runs immediately (similar to `needs: []`) because its `needs`
- relationship to the `build` job is optional.
+**Possible inputs**:
+
+- `job:`: The job to make optional.
+- `true` or `false` (default).
+
+**Example of `needs:optional`**:
```yaml
build:
@@ -1828,6 +1655,42 @@ rspec:
optional: true
```
+In this example:
+
+- When the branch is the default branch, the `build` job exists in the pipeline, and the `rspec`
+ job waits for it to complete before starting.
+- When the branch is not the default branch, the `build` job does not exist in the pipeline.
+ The `rspec` job runs immediately (similar to `needs: []`) because its `needs`
+ relationship to the `build` job is optional.
+
+#### `needs:pipeline`
+
+You can mirror the pipeline status from an upstream pipeline to a bridge job by
+using the `needs:pipeline` keyword. The latest pipeline status from the default branch is
+replicated to the bridge job.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**:
+
+- A full project path, including namespace and group. If the
+ project is in the same group or namespace, you can omit them from the `project:`
+ keyword. For example: `project: group/project-name` or `project: project-name`.
+
+**Example of `needs:pipeline`**:
+
+```yaml
+upstream_bridge:
+ stage: test
+ needs:
+ pipeline: other/project
+```
+
+**Additional details**:
+
+- If you add the `job` keyword to `needs:pipeline`, the job no longer mirrors the
+ pipeline status. The behavior changes to [`needs:pipeline:job`](#needspipelinejob).
+
### `tags`
> - A limit of 50 tags per job [enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/338929) in GitLab 14.3.
@@ -1841,7 +1704,7 @@ example `ruby`, `postgres`, or `development`. To pick up and run a job, a runner
be assigned every tag listed in the job.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#custom-default-keyword-values).
+[`default:` section](#default).
**Possible inputs**:
@@ -2043,7 +1906,17 @@ In this example, the script:
### `environment`
Use `environment` to define the [environment](../environments/index.md) that a job deploys to.
-For example:
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**: The name of the environment the job deploys to, in one of these
+formats:
+
+- Plain text, including letters, digits, spaces, and these characters: `-`, `_`, `/`, `$`, `{`, `}`.
+- CI/CD variables, including predefined, secure, or variables defined in the
+ `.gitlab-ci.yml` file. You can't use variables defined in a `script` section.
+
+**Example of `environment`**:
```yaml
deploy to production:
@@ -2052,20 +1925,27 @@ deploy to production:
environment: production
```
-You can assign a value to the `environment` keyword by using:
+**Additional details**:
-- Plain text, like `production`.
-- Variables, including CI/CD variables, predefined, secure, or variables
- defined in the `.gitlab-ci.yml` file.
+- If you specify an `environment` and no environment with that name exists, an environment is
+ created.
-You can't use variables defined in a `script` section.
+#### `environment:name`
-If you specify an `environment` and no environment with that name exists,
-an environment is created.
+Set a name for an [environment](../environments/index.md).
-#### `environment:name`
+Common environment names are `qa`, `staging`, and `production`, but you can use any name.
-Set a name for an [environment](../environments/index.md). For example:
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**: The name of the environment the job deploys to, in one of these
+formats:
+
+- Plain text, including letters, digits, spaces, and these characters: `-`, `_`, `/`, `$`, `{`, `}`.
+- CI/CD variables, including predefined, secure, or variables defined in the
+ `.gitlab-ci.yml` file. You can't use variables defined in a `script` section.
+
+**Example of `environment:name`**:
```yaml
deploy to production:
@@ -2075,32 +1955,19 @@ deploy to production:
name: production
```
-Common environment names are `qa`, `staging`, and `production`, but you can use any
-name you want.
-
-You can assign a value to the `name` keyword by using:
-
-- Plain text, like `staging`.
-- Variables, including CI/CD variables, predefined, secure, or variables
- defined in the `.gitlab-ci.yml` file.
+#### `environment:url`
-You can't use variables defined in a `script` section.
+Set a URL for an [environment](../environments/index.md).
-The environment `name` can contain:
+**Keyword type**: Job keyword. You can use it only as part of a job.
-- Letters
-- Digits
-- Spaces
-- `-`
-- `_`
-- `/`
-- `$`
-- `{`
-- `}`
+**Possible inputs**: A single URL, in one of these formats:
-#### `environment:url`
+- Plain text, like `https://prod.example.com`.
+- CI/CD variables, including predefined, secure, or variables defined in the
+ `.gitlab-ci.yml` file. You can't use variables defined in a `script` section.
-Set a URL for an [environment](../environments/index.md). For example:
+**Example of `environment:url`**:
```yaml
deploy to production:
@@ -2111,16 +1978,10 @@ deploy to production:
url: https://prod.example.com
```
-After the job completes, you can access the URL by using a button in the merge request,
-environment, or deployment pages.
-
-You can assign a value to the `url` keyword by using:
-
-- Plain text, like `https://prod.example.com`.
-- Variables, including CI/CD variables, predefined, secure, or variables
- defined in the `.gitlab-ci.yml` file.
+**Additional details**:
-You can't use variables defined in a `script` section.
+- After the job completes, you can access the URL by selecting a button in the merge request,
+ environment, or deployment pages.
#### `environment:on_stop`
@@ -2128,7 +1989,11 @@ Closing (stopping) environments can be achieved with the `on_stop` keyword
defined under `environment`. It declares a different job that runs to close the
environment.
-Read the `environment:action` section for an example.
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Additional details**:
+
+- See [`environment:action`](#environmentaction) for more details and an example.
#### `environment:action`
@@ -2174,7 +2039,7 @@ Also in the example, `GIT_STRATEGY` is set to `none`. If the
the runner won't try to check out the code after the branch is deleted.
The example also overwrites global variables. If your `stop` `environment` job depends
-on global variables, use [anchor variables](#yaml-anchors-for-variables) when you set the `GIT_STRATEGY`
+on global variables, use [anchor variables](yaml_optimization.md#yaml-anchors-for-variables) when you set the `GIT_STRATEGY`
to change the job without overriding the global variables.
The `stop_review_app` job is **required** to have the following keywords defined:
@@ -2199,10 +2064,19 @@ In the examples above, if the configuration is not identical:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20956) in GitLab 12.8.
-The `auto_stop_in` keyword is for specifying the lifetime of the environment,
-that when expired, GitLab automatically stops them.
+The `auto_stop_in` keyword specifies the lifetime of the environment. When an environment expires, GitLab
+automatically stops it.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**: A period of time written in natural language. For example,
+these are all equivalent:
+
+- `168 hours`
+- `7 days`
+- `one week`
-For example,
+**Example of `environment:auto_stop_in`**:
```yaml
review_app:
@@ -2215,8 +2089,9 @@ review_app:
When the environment for `review_app` is created, the environment's lifetime is set to `1 day`.
Every time the review app is deployed, that lifetime is also reset to `1 day`.
-For more information, see
-[the environments auto-stop documentation](../environments/index.md#stop-an-environment-after-a-certain-time-period)
+**Related topics**:
+
+- [Environments auto-stop documentation](../environments/index.md#stop-an-environment-after-a-certain-time-period).
#### `environment:kubernetes`
@@ -2225,7 +2100,9 @@ For more information, see
Use the `kubernetes` keyword to configure deployments to a
[Kubernetes cluster](../../user/infrastructure/clusters/index.md) that is associated with your project.
-For example:
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Example of `environment:kubernetes`**:
```yaml
deploy:
@@ -2241,20 +2118,34 @@ This configuration sets up the `deploy` job to deploy to the `production`
environment, using the `production`
[Kubernetes namespace](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/).
-For more information, see
-[Available settings for `kubernetes`](../environments/index.md#configure-kubernetes-deployments).
+**Additional details**:
-NOTE:
-Kubernetes configuration is not supported for Kubernetes clusters
-that are [managed by GitLab](../../user/project/clusters/gitlab_managed_clusters.md).
-To follow progress on support for GitLab-managed clusters, see the
-[relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/38054).
+- Kubernetes configuration is not supported for Kubernetes clusters
+ that are [managed by GitLab](../../user/project/clusters/gitlab_managed_clusters.md).
+ To follow progress on support for GitLab-managed clusters, see the
+ [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/38054).
+
+**Related topics**:
+
+- [Available settings for `kubernetes`](../environments/index.md#configure-kubernetes-deployments-deprecated).
#### `environment:deployment_tier`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300741) in GitLab 13.10.
-Use the `deployment_tier` keyword to specify the tier of the deployment environment:
+Use the `deployment_tier` keyword to specify the tier of the deployment environment.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**: One of the following:
+
+- `production`
+- `staging`
+- `testing`
+- `development`
+- `other`
+
+**Example of `environment:deployment_tier`**:
```yaml
deploy:
@@ -2264,8 +2155,9 @@ deploy:
deployment_tier: production
```
-For more information,
-see [Deployment tier of environments](../environments/index.md#deployment-tier-of-environments).
+**Related topics**:
+
+- [Deployment tier of environments](../environments/index.md#deployment-tier-of-environments).
#### Dynamic environments
@@ -2306,7 +2198,8 @@ Learn more about caches in [Caching in GitLab CI/CD](../caching/index.md).
Use the `cache:paths` keyword to choose which files or directories to cache.
-**Keyword type**: Job-specific. You can use it only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default:` section](#default).
**Possible inputs**: An array of paths relative to the project directory (`$CI_PROJECT_DIR`).
You can use wildcards that use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
@@ -2345,7 +2238,8 @@ that use the same cache key use the same cache, including in different pipelines
If not set, the default key is `default`. All jobs with the `cache:` keyword but
no `cache:key` share the `default` cache.
-**Keyword type**: Job-specific. You can use it only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default:` section](#default).
**Possible inputs**:
@@ -2367,7 +2261,7 @@ cache-job:
**Additional details**:
-- If you use **Windows Batch** to run your shell scripts you need to replace
+- If you use **Windows Batch** to run your shell scripts you must replace
`$` with `%`. For example: `key: %CI_COMMIT_REF_SLUG%`
- The `cache:key` value can't contain:
@@ -2394,7 +2288,8 @@ Use the `cache:key:files` keyword to generate a new key when one or two specific
change. `cache:key:files` lets you reuse some caches, and rebuild them less often,
which speeds up subsequent pipeline runs.
-**Keyword type**: Job-specific. You can use it only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default:` section](#default).
**Possible inputs**: An array of one or two file paths.
@@ -2420,9 +2315,11 @@ these files changes, a new cache key is computed and a new cache is created. Any
job runs that use the same `Gemfile.lock` and `package.json` with `cache:key:files`
use the new cache, instead of rebuilding the dependencies.
-**Additional details**: The cache `key` is a SHA computed from the most recent commits
-that changed each listed file. If neither file is changed in any commits, the
-fallback key is `default`.
+**Additional details**:
+
+- The cache `key` is a SHA computed from the most recent commits
+that changed each listed file.
+ If neither file is changed in any commits, the fallback key is `default`.
##### `cache:key:prefix`
@@ -2430,7 +2327,8 @@ fallback key is `default`.
Use `cache:key:prefix` to combine a prefix with the SHA computed for [`cache:key:files`](#cachekeyfiles).
-**Keyword type**: Job-specific. You can use it only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default:` section](#default).
**Possible inputs**:
@@ -2458,14 +2356,16 @@ If a branch changes `Gemfile.lock`, that branch has a new SHA checksum for `cach
A new cache key is generated, and a new cache is created for that key. If `Gemfile.lock`
is not found, the prefix is added to `default`, so the key in the example would be `rspec-default`.
-**Additional details**: If no file in `cache:key:files` is changed in any commits,
-the prefix is added to the `default` key.
+**Additional details**:
+
+- If no file in `cache:key:files` is changed in any commits, the prefix is added to the `default` key.
#### `cache:untracked`
Use `untracked: true` to cache all files that are untracked in your Git repository:
-**Keyword type**: Job-specific. You can use it only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default:` section](#default).
**Possible inputs**: `true` or `false` (default).
@@ -2498,7 +2398,8 @@ rspec:
Use `cache:when` to define when to save the cache, based on the status of the job.
-**Keyword type**: Job-specific. You can use it only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default:` section](#default).
**Possible inputs**:
@@ -2523,7 +2424,7 @@ This example stores the cache whether or not the job fails or succeeds.
To change the upload and download behavior of a cache, use the `cache:policy` keyword.
By default, the job downloads the cache when the job starts, and uploads changes
-to the cache when the job ends. This is the `pull-push` policy (default).
+to the cache when the job ends. This caching style is the `pull-push` policy (default).
To set a job to only download the cache when the job starts, but never upload changes
when the job finishes, use `cache:policy:pull`.
@@ -2535,7 +2436,8 @@ Use the `pull` policy when you have many jobs executing in parallel that use the
This policy speeds up job execution and reduces load on the cache server. You can
use a job with the `push` policy to build the cache.
-**Keyword type**: Job-specific. You can use it only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default:` section](#default).
**Possible inputs**:
@@ -2569,74 +2471,44 @@ faster-test-job:
- echo "Running tests..."
```
-### `artifacts`
-
-Use `artifacts` to specify a list of files and directories that are
-attached to the job when it [succeeds, fails, or always](#artifactswhen).
-
-The artifacts are sent to GitLab after the job finishes. They are
-available for download in the GitLab UI if the size is not
-larger than the [maximum artifact size](../../user/gitlab_com/index.md#gitlab-cicd).
-
-By default, jobs in later stages automatically download all the artifacts created
-by jobs in earlier stages. You can control artifact download behavior in jobs with
-[`dependencies`](#dependencies).
-
-When using the [`needs`](#artifact-downloads-with-needs) keyword, jobs can only download
-artifacts from the jobs defined in the `needs` configuration.
-
-Job artifacts are only collected for successful jobs by default, and
-artifacts are restored after [caches](#cache).
-
-[Read more about artifacts](../pipelines/job_artifacts.md).
-
-#### `dependencies`
-
-By default, all `artifacts` from previous stages
-are passed to each job. However, you can use the `dependencies` keyword to
-define a limited list of jobs to fetch artifacts from. You can also set a job to download no artifacts at all.
+### `dependencies`
-To use this feature, define `dependencies` in context of the job and pass
-a list of all previous jobs the artifacts should be downloaded from.
+Use the `dependencies` keyword to define a list of jobs to fetch [artifacts](#artifacts) from.
+You can also set a job to download no artifacts at all.
-You can define jobs from stages that were executed before the current one.
-An error occurs if you define jobs from the current or an upcoming stage.
+If you do not use `dependencies`, all artifacts from previous stages are passed to each job.
-To prevent a job from downloading artifacts, define an empty array.
+**Keyword type**: Job keyword. You can use it only as part of a job.
-When you use `dependencies`, the status of the previous job is not considered.
-If a job fails or it's a manual job that isn't triggered, no error occurs.
+**Possible inputs**:
-The following example defines two jobs with artifacts: `build:osx` and
-`build:linux`. When the `test:osx` is executed, the artifacts from `build:osx`
-are downloaded and extracted in the context of the build. The same happens
-for `test:linux` and artifacts from `build:linux`.
+- The names of jobs to fetch artifacts from.
+- An empty array (`[]`), to configure the job to not download any artifacts.
-The job `deploy` downloads artifacts from all previous jobs because of
-the [stage](#stages) precedence:
+**Example of `dependencies`**:
```yaml
-build:osx:
+build osx:
stage: build
script: make build:osx
artifacts:
paths:
- binaries/
-build:linux:
+build linux:
stage: build
script: make build:linux
artifacts:
paths:
- binaries/
-test:osx:
+test osx:
stage: test
script: make test:osx
dependencies:
- build:osx
-test:linux:
+test linux:
stage: test
script: make test:linux
dependencies:
@@ -2647,14 +2519,39 @@ deploy:
script: make deploy
```
-##### When a dependent job fails
+In this example, two jobs have artifacts: `build osx` and `build linux`. When `test osx` is executed,
+the artifacts from `build osx` are downloaded and extracted in the context of the build.
+The same thing happens for `test linux` and artifacts from `build linux`.
-> Introduced in GitLab 10.3.
+The `deploy` job downloads artifacts from all previous jobs because of
+the [stage](#stages) precedence.
-If the artifacts of the job that is set as a dependency are
-[expired](#artifactsexpire_in) or
-[deleted](../pipelines/job_artifacts.md#delete-job-artifacts), then
-the dependent job fails.
+**Additional details**:
+
+- The job status does not matter. If a job fails or it's a manual job that isn't triggered, no error occurs.
+- If the artifacts of a dependent job are [expired](#artifactsexpire_in) or
+ [deleted](../pipelines/job_artifacts.md#delete-job-artifacts), then the job fails.
+
+### `artifacts`
+
+Use `artifacts` to specify a list of files and directories that are
+attached to the job when it [succeeds, fails, or always](#artifactswhen).
+
+The artifacts are sent to GitLab after the job finishes. They are
+available for download in the GitLab UI if the size is not
+larger than the [maximum artifact size](../../user/gitlab_com/index.md#gitlab-cicd).
+
+By default, jobs in later stages automatically download all the artifacts created
+by jobs in earlier stages. You can control artifact download behavior in jobs with
+[`dependencies`](#dependencies).
+
+When using the [`needs`](#needs) keyword, jobs can only download
+artifacts from the jobs defined in the `needs` configuration.
+
+Job artifacts are only collected for successful jobs by default, and
+artifacts are restored after [caches](#cache).
+
+[Read more about artifacts](../pipelines/job_artifacts.md).
#### `artifacts:exclude`
@@ -2706,13 +2603,12 @@ Files matched by [`artifacts:untracked`](#artifactsuntracked) can be excluded us
Use `expire_in` to specify how long [job artifacts](../pipelines/job_artifacts.md) are stored before
they expire and are deleted. The `expire_in` setting does not affect:
-- Artifacts from the latest job, unless this keeping the latest job artifacts is:
+- Artifacts from the latest job, unless keeping the latest job artifacts is:
- [Disabled at the project level](../pipelines/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs).
- [Disabled instance-wide](../../user/admin_area/settings/continuous_integration.md#keep-the-latest-artifacts-for-all-jobs-in-the-latest-successful-pipelines).
-- [Pipeline artifacts](../pipelines/pipeline_artifacts.md). It's not possible to specify an
- expiration date for these:
- - Pipeline artifacts from the latest pipeline are kept forever.
- - Other pipeline artifacts are erased after one week.
+- [Pipeline artifacts](../pipelines/pipeline_artifacts.md). You can't specify an expiration date for
+ pipeline artifacts. See [When pipeline artifacts are deleted](../pipelines/pipeline_artifacts.md#when-pipeline-artifacts-are-deleted)
+ for more information.
The value of `expire_in` is an elapsed time in seconds, unless a unit is provided. Valid values
include:
@@ -2742,7 +2638,7 @@ time is not defined, it defaults to the
To override the expiration date and protect artifacts from being automatically deleted:
-- Use the **Keep** button on the job page.
+- Select **Keep** on the job page.
- [In GitLab 13.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/22761), set the value of
`expire_in` to `never`.
@@ -2847,7 +2743,7 @@ job:
---
-If you use **Windows Batch** to run your shell scripts you need to replace
+If you use **Windows Batch** to run your shell scripts you must replace
`$` with `%`:
```yaml
@@ -2858,7 +2754,7 @@ job:
- binaries/
```
-If you use **Windows PowerShell** to run your shell scripts you need to replace
+If you use **Windows PowerShell** to run your shell scripts you must replace
`$` with `$env:`:
```yaml
@@ -2876,9 +2772,8 @@ link outside it. You can use Wildcards that use [glob](https://en.wikipedia.org/
patterns and:
- In [GitLab Runner 13.0 and later](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620),
-[`doublestar.Glob`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#Match).
-- In GitLab Runner 12.10 and earlier,
-[`filepath.Match`](https://pkg.go.dev/path/filepath#Match).
+ [`doublestar.Glob`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#Match).
+- In GitLab Runner 12.10 and earlier, [`filepath.Match`](https://pkg.go.dev/path/filepath#Match).
To restrict which jobs a specific job fetches artifacts from, see [dependencies](#dependencies).
@@ -2959,19 +2854,39 @@ artifacts:
#### `artifacts:reports`
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20390) in GitLab 11.2.
-> - Requires GitLab Runner 11.2 and above.
+Use [`artifacts:reports`](#artifactsreports) to:
-Use [`artifacts:reports`](#artifactsreports)
-to collect test reports, code quality reports, and security reports from jobs.
-It also exposes these reports in the GitLab UI (merge requests, pipeline views, and security dashboards).
+- Collect test reports, code quality reports, security reports, and other artifacts generated by included templates in
+ jobs.
+- Some of these reports are used to display information in:
+ - Merge requests.
+ - Pipeline views.
+ - [Security dashboards](../../user/application_security/security_dashboard/index.md).
The test reports are collected regardless of the job results (success or failure).
You can use [`artifacts:expire_in`](#artifactsexpire_in) to set up an expiration
date for their artifacts.
-If you also want the ability to browse the report output files, include the
-[`artifacts:paths`](#artifactspaths) keyword.
+Some `artifacts:reports` types can be generated by multiple jobs in the same pipeline, and used by merge request or
+pipeline features from each job.
+
+To be able to browse the report output files, include the [`artifacts:paths`](#artifactspaths) keyword.
+
+NOTE:
+Combined reports in parent pipelines using [artifacts from child pipelines](#needspipelinejob) is
+not supported. Track progress on adding support in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/215725).
+
+##### `artifacts:reports:accessibility` **(FREE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39425) in GitLab 12.8.
+
+The `accessibility` report uses [pa11y](https://pa11y.org/) to report on the accessibility impact
+of changes introduced in merge requests.
+
+GitLab can display the results of one or more reports in the merge request
+[accessibility widget](../../user/project/merge_requests/accessibility_testing.md#accessibility-merge-request-widget).
+
+For more information, see [Accessibility testing](../../user/project/merge_requests/accessibility_testing.md).
##### `artifacts:reports:api_fuzzing` **(ULTIMATE)**
@@ -2981,100 +2896,128 @@ If you also want the ability to browse the report output files, include the
The `api_fuzzing` report collects [API Fuzzing bugs](../../user/application_security/api_fuzzing/index.md)
as artifacts.
-The collected API Fuzzing report uploads to GitLab as an artifact and is summarized in merge
-requests and the pipeline view. It's also used to provide data for security dashboards.
+GitLab can display the results of one or more reports in:
+
+- The merge request [security widget](../../user/application_security/api_fuzzing/index.md#view-details-of-an-api-fuzzing-vulnerability).
+- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
+- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
+- The [security dashboard](../../user/application_security/api_fuzzing/index.md#security-dashboard).
+
+##### `artifacts:reports:browser_performance` **(PREMIUM)**
+
+> [Name changed](https://gitlab.com/gitlab-org/gitlab/-/issues/225914) from `artifacts:reports:performance` in GitLab 14.0.
+
+The `browser_performance` report collects [Browser Performance Testing metrics](../../user/project/merge_requests/browser_performance_testing.md)
+as artifacts.
+
+GitLab can display the results of one report in the merge request
+[browser performance testing widget](../../user/project/merge_requests/browser_performance_testing.md#how-browser-performance-testing-works).
+
+GitLab cannot display the combined results of multiple `browser_performance` reports.
+
+##### `artifacts:reports:cluster_image_scanning` **(ULTIMATE)**
+
+> - Introduced in GitLab 14.1.
+> - Requires GitLab Runner 14.1 and above.
+
+The `cluster_image_scanning` report collects `CLUSTER_IMAGE_SCANNING` vulnerabilities. The collected
+`CLUSTER_IMAGE_SCANNING` report uploads to GitLab as an artifact.
+
+GitLab can display the results of one or more reports in:
+
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
##### `artifacts:reports:cobertura`
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) in GitLab 12.9.
-> - Requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 and above.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) in GitLab 12.9.
The `cobertura` report collects [Cobertura coverage XML files](../../user/project/merge_requests/test_coverage_visualization.md).
-The collected Cobertura coverage reports upload to GitLab as an artifact
-and display in merge requests.
+The collected Cobertura coverage reports upload to GitLab as an artifact.
-Cobertura was originally developed for Java, but there are many
-third party ports for other languages like JavaScript, Python, Ruby, and so on.
+GitLab can display the results of one or more reports in the merge request
+[diff annotations](../../user/project/merge_requests/test_coverage_visualization.md).
+
+Cobertura was originally developed for Java, but there are many third-party ports for other languages such as
+JavaScript, Python, and Ruby.
##### `artifacts:reports:codequality`
-> - Introduced in GitLab 11.5.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) to GitLab Free in 13.2.
-> - Requires GitLab Runner 11.5 and above.
+> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) to GitLab Free in 13.2.
-The `codequality` report collects [Code Quality issues](../../user/project/merge_requests/code_quality.md)
-as artifacts.
+The `codequality` report collects [code quality issues](../../user/project/merge_requests/code_quality.md). The
+collected code quality report uploads to GitLab as an artifact.
+
+GitLab can display the results of:
-The collected Code Quality report uploads to GitLab as an artifact and is summarized in merge requests.
+- One or more reports in the merge request [code quality widget](../../user/project/merge_requests/code_quality.md#code-quality-widget).
+- Only one report in:
+ - The merge request [diff annotations](../../user/project/merge_requests/code_quality.md#code-quality-in-diff-view).
+ Track progress on adding support for multiple reports in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/328257).
+ - The [full report](../metrics_reports.md). Track progress on adding support for multiple reports in
+ [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/9014).
##### `artifacts:reports:container_scanning` **(ULTIMATE)**
-> - Introduced in GitLab 11.5.
-> - Requires GitLab Runner 11.5 and above.
+The `container_scanning` report collects [Container Scanning vulnerabilities](../../user/application_security/container_scanning/index.md).
+The collected Container Scanning report uploads to GitLab as an artifact.
-The `container_scanning` report collects [Container Scanning vulnerabilities](../../user/application_security/container_scanning/index.md)
-as artifacts.
+GitLab can display the results of one or more reports in:
-The collected Container Scanning report uploads to GitLab as an artifact and
-is summarized in merge requests and the pipeline view. It's also used to provide data for security
-dashboards.
+- The merge request [container scanning widget](../../user/application_security/container_scanning/index.md).
+- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
##### `artifacts:reports:coverage_fuzzing` **(ULTIMATE)**
> - Introduced in GitLab 13.4.
> - Requires GitLab Runner 13.4 or later.
-The `coverage_fuzzing` report collects [coverage fuzzing bugs](../../user/application_security/coverage_fuzzing/index.md)
-as artifacts.
-
-The collected coverage fuzzing report uploads to GitLab as an artifact and is summarized in merge
-requests and the pipeline view. It's also used to provide data for security dashboards.
+The `coverage_fuzzing` report collects [coverage fuzzing bugs](../../user/application_security/coverage_fuzzing/index.md).
+The collected coverage fuzzing report uploads to GitLab as an artifact.
+GitLab can display the results of one or more reports in:
-##### `artifacts:reports:cluster_image_scanning` **(ULTIMATE)**
-
-> - Introduced in GitLab 14.1.
-> - Requires GitLab Runner 14.1 and above.
-
-The `cluster_image_scanning` report collects `CLUSTER_IMAGE_SCANNING` vulnerabilities
-as artifacts.
-
-The collected `CLUSTER_IMAGE_SCANNING` report uploads to GitLab as an artifact and
-is summarized in the pipeline view. It's also used to provide data for security
-dashboards.
+- The merge request [coverage fuzzing widget](../../user/application_security/coverage_fuzzing/index.md#interacting-with-the-vulnerabilities).
+- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
+- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
##### `artifacts:reports:dast` **(ULTIMATE)**
-> - Introduced in GitLab 11.5.
-> - Requires GitLab Runner 11.5 and above.
+The `dast` report collects [DAST vulnerabilities](../../user/application_security/dast/index.md). The collected DAST
+report uploads to GitLab as an artifact.
-The `dast` report collects [DAST vulnerabilities](../../user/application_security/dast/index.md)
-as artifacts.
+GitLab can display the results of one or more reports in:
-The collected DAST report uploads to GitLab as an artifact and is summarized in merge requests and the pipeline view. It's also used to provide data for security
-dashboards.
+- The merge request [security widget](../../user/application_security/dast/index.md#view-details-of-a-vulnerability-detected-by-dast).
+- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
+- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
##### `artifacts:reports:dependency_scanning` **(ULTIMATE)**
-> - Introduced in GitLab 11.5.
-> - Requires GitLab Runner 11.5 and above.
+The `dependency_scanning` report collects [Dependency Scanning vulnerabilities](../../user/application_security/dependency_scanning/index.md).
+The collected Dependency Scanning report uploads to GitLab as an artifact.
-The `dependency_scanning` report collects [Dependency Scanning vulnerabilities](../../user/application_security/dependency_scanning/index.md)
-as artifacts.
+GitLab can display the results of one or more reports in:
-The collected Dependency Scanning report uploads to GitLab as an artifact and is summarized in merge requests and the pipeline view. It's also used to provide data for security
-dashboards.
+- The merge request [dependency scanning widget](../../user/application_security/dependency_scanning/index.md#overview).
+- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
+- The [dependency list](../../user/application_security/dependency_list/).
##### `artifacts:reports:dotenv`
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17066) in GitLab 12.9.
-> - Requires GitLab Runner 11.5 and later.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17066) in GitLab 12.9.
The `dotenv` report collects a set of environment variables as artifacts.
The collected variables are registered as runtime-created variables of the job,
which is useful to [set dynamic environment URLs after a job finishes](../environments/index.md#set-dynamic-environment-urls-after-a-job-finishes).
-There are a couple of exceptions to the [original dotenv rules](https://github.com/motdotla/dotenv#rules):
+The exceptions to the [original dotenv rules](https://github.com/motdotla/dotenv#rules) are:
- The variable key can contain only letters, digits, and underscores (`_`).
- The maximum size of the `.env` file is 5 KB.
@@ -3088,13 +3031,9 @@ There are a couple of exceptions to the [original dotenv rules](https://github.c
##### `artifacts:reports:junit`
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20390) in GitLab 11.2.
-> - Requires GitLab Runner 11.2 and above.
-
-The `junit` report collects [JUnit report format XML files](https://www.ibm.com/docs/en/adfz/developer-for-zos/14.1.0?topic=formats-junit-xml-format)
-as artifacts. Although JUnit was originally developed in Java, there are many
-third party ports for other
-languages like JavaScript, Python, Ruby, and so on.
+The `junit` report collects [JUnit report format XML files](https://www.ibm.com/docs/en/adfz/developer-for-zos/14.1.0?topic=formats-junit-xml-format).
+The collected Unit test reports upload to GitLab as an artifact. Although JUnit was originally developed in Java, there
+are many third-party ports for other languages such as JavaScript, Python, and Ruby.
See [Unit test reports](../unit_test_reports.md) for more details and examples.
Below is an example of collecting a JUnit report format XML file from Ruby's RSpec test tool:
@@ -3110,79 +3049,72 @@ rspec:
junit: rspec.xml
```
-The collected Unit test reports upload to GitLab as an artifact and display in merge requests.
+GitLab can display the results of one or more reports in:
-If the JUnit tool you use exports to multiple XML files, specify
-multiple test report paths within a single job to
-concatenate them into a single file. Use a filename pattern (`junit: rspec-*.xml`),
-an array of filenames (`junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]`), or a
-combination thereof (`junit: [rspec.xml, test-results/TEST-*.xml]`).
+- The merge request [code quality widget](../../ci/unit_test_reports.md#how-it-works).
+- The [full report](../../ci/unit_test_reports.md#viewing-unit-test-reports-on-gitlab).
+
+Some JUnit tools export to multiple XML files. You can specify multiple test report paths in a single job to
+concatenate them into a single file. Use either:
+
+- A filename pattern (`junit: rspec-*.xml`).
+- an array of filenames (`junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]`).
+- A Combination of both (`junit: [rspec.xml, test-results/TEST-*.xml]`).
##### `artifacts:reports:license_scanning` **(ULTIMATE)**
-> - Introduced in GitLab 12.8.
-> - Requires GitLab Runner 11.5 and above.
+> Introduced in GitLab 12.8.
-The `license_scanning` report collects [Licenses](../../user/compliance/license_compliance/index.md)
-as artifacts.
+The License Compliance report collects [Licenses](../../user/compliance/license_compliance/index.md). The License
+Compliance report uploads to GitLab as an artifact.
-The License Compliance report uploads to GitLab as an artifact and displays automatically in merge requests and the pipeline view, and provide data for security
-dashboards.
+GitLab can display the results of one or more reports in:
+
+- The merge request [license compliance widget](../../user/compliance/license_compliance/index.md).
+- The [license list](../../user/compliance/license_compliance/index.md#license-list).
##### `artifacts:reports:load_performance` **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35260) in GitLab 13.2.
> - Requires GitLab Runner 11.5 and above.
-The `load_performance` report collects [Load Performance Testing metrics](../../user/project/merge_requests/load_performance_testing.md)
-as artifacts.
-
-The report is uploaded to GitLab as an artifact and is
-shown in merge requests automatically.
+The `load_performance` report collects [Load Performance Testing metrics](../../user/project/merge_requests/load_performance_testing.md).
+The report is uploaded to GitLab as an artifact.
-##### `artifacts:reports:metrics` **(PREMIUM)**
+GitLab can display the results of only one report in the merge request
+[load testing widget](../../user/project/merge_requests/load_performance_testing.md#how-load-performance-testing-works).
-> Introduced in GitLab 11.10.
+GitLab cannot display the combined results of multiple `load_performance` reports.
-The `metrics` report collects [Metrics](../metrics_reports.md)
-as artifacts.
-
-The collected Metrics report uploads to GitLab as an artifact and displays in merge requests.
-
-##### `artifacts:reports:browser_performance` **(PREMIUM)**
-
-> - Introduced in GitLab 11.5.
-> - Requires GitLab Runner 11.5 and above.
-> - [Name changed](https://gitlab.com/gitlab-org/gitlab/-/issues/225914) from `artifacts:reports:performance` in GitLab 14.0.
+##### `artifacts:reports:metrics` **(PREMIUM)**
-The `browser_performance` report collects [Browser Performance Testing metrics](../../user/project/merge_requests/browser_performance_testing.md)
-as artifacts.
+The `metrics` report collects [Metrics](../metrics_reports.md). The collected Metrics report uploads to GitLab as an
+artifact.
-The collected Browser Performance report uploads to GitLab as an artifact and displays in merge requests.
+GitLab can display the results of one or more reports in the merge request
+[metrics reports widget](../../ci/metrics_reports.md#metrics-reports).
##### `artifacts:reports:requirements` **(ULTIMATE)**
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2859) in GitLab 13.1.
-> - Requires GitLab Runner 11.5 and above.
-The `requirements` report collects `requirements.json` files as artifacts.
+The `requirements` report collects `requirements.json` files. The collected Requirements report uploads to GitLab as an
+artifact and existing [requirements](../../user/project/requirements/index.md) are marked as Satisfied.
-The collected Requirements report uploads to GitLab as an artifact and
-existing [requirements](../../user/project/requirements/index.md) are
-marked as Satisfied.
+GitLab can display the results of one or more reports in the
+[project requirements](../../user/project/requirements/index.md#view-a-requirement).
##### `artifacts:reports:sast`
-> - Introduced in GitLab 11.5.
> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) from GitLab Ultimate to GitLab Free in 13.3.
-> - Requires GitLab Runner 11.5 and above.
-The `sast` report collects [SAST vulnerabilities](../../user/application_security/sast/index.md)
-as artifacts.
+The `sast` report collects [SAST vulnerabilities](../../user/application_security/sast/index.md). The collected SAST
+report uploads to GitLab as an artifact.
+
+GitLab can display the results of one or more reports in:
-The collected SAST report uploads to GitLab as an artifact and is summarized
-in merge requests and the pipeline view. It's also used to provide data for security
-dashboards.
+- The merge request [SAST widget](../../user/application_security/sast/index.md#static-application-security-testing-sast).
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
##### `artifacts:reports:secret_detection`
@@ -3190,22 +3122,27 @@ dashboards.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/222788) to GitLab Free in 13.3.
> - Requires GitLab Runner 11.5 and above.
-The `secret-detection` report collects [detected secrets](../../user/application_security/secret_detection/index.md)
-as artifacts.
+The `secret-detection` report collects [detected secrets](../../user/application_security/secret_detection/index.md).
+The collected Secret Detection report is uploaded to GitLab.
+
+GitLab can display the results of one or more reports in:
-The collected Secret Detection report is uploaded to GitLab as an artifact and summarized
-in the merge requests and pipeline view. It's also used to provide data for security
-dashboards.
+- The merge request [secret scanning widget](../../user/application_security/secret_detection/index.md).
+- The [pipeline **Security** tab](../../user/application_security/index.md#view-security-scan-information-in-the-pipeline-security-tab).
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
##### `artifacts:reports:terraform`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207528) in GitLab 13.0.
> - Requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 and above.
-The `terraform` report obtains a Terraform `tfplan.json` file. [JQ processing required to remove credentials](../../user/infrastructure/iac/mr_integration.md#configure-terraform-report-artifacts). The collected Terraform
-plan report uploads to GitLab as an artifact and displays
-in merge requests. For more information, see
-[Output `terraform plan` information into a merge request](../../user/infrastructure/iac/mr_integration.md).
+The `terraform` report obtains a Terraform `tfplan.json` file. [JQ processing required to remove credentials](../../user/infrastructure/iac/mr_integration.md#configure-terraform-report-artifacts).
+The collected Terraform plan report uploads to GitLab as an artifact.
+
+GitLab can display the results of one or more reports in the merge request
+[terraform widget](../../user/infrastructure/iac/mr_integration.md#output-terraform-plan-information-into-a-merge-request).
+
+For more information, see [Output `terraform plan` information into a merge request](../../user/infrastructure/iac/mr_integration.md).
#### `artifacts:untracked`
@@ -3247,7 +3184,7 @@ failure.
1. `on_success` (default): Upload artifacts only when the job succeeds.
1. `on_failure`: Upload artifacts only when the job fails.
-1. `always`: Always upload artifacts. Useful, for example, when
+1. `always`: Always upload artifacts. For example, when
[uploading artifacts](../unit_test_reports.md#viewing-junit-screenshots-on-gitlab) required to
troubleshoot failing tests.
@@ -3339,8 +3276,6 @@ to select a specific site profile and scanner profile.
### `retry`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3515) in GitLab 11.5, you can control which failures to retry on.
-
Use `retry` to configure how many times a job is retried if it fails.
If not defined, defaults to `0` and jobs do not retry.
@@ -3351,7 +3286,7 @@ By default, all failure types cause the job to be retried. Use [`retry:when`](#r
to select which failures to retry on.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#custom-default-keyword-values).
+[`default:` section](#default).
**Possible inputs**: `0` (default), `1`, or `2`.
@@ -3370,7 +3305,7 @@ Use `retry:when` with `retry:max` to retry jobs for only specific failure cases.
`0`, `1`, or `2`.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#custom-default-keyword-values).
+[`default:` section](#default).
**Possible inputs**: A single failure type, or an array of one or more failure types:
@@ -3436,7 +3371,7 @@ The job-level timeout can be longer than the [project-level timeout](../pipeline
but can't be longer than the [runner's timeout](../runners/configure_runners.md#set-maximum-job-timeout-for-a-runner).
**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#custom-default-keyword-values).
+[`default:` section](#default).
**Possible inputs**: A period of time written in natural language. For example, these are all equivalent:
@@ -3458,13 +3393,17 @@ test:
### `parallel`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21480) in GitLab 11.5.
+Use `parallel` to run a job multiple times in parallel in a single pipeline.
+
+Multiple runners must exist, or a single runner must be configured to run multiple jobs concurrently.
+
+Parallel jobs are named sequentially from `job_name 1/N` to `job_name N/N`.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
-Use `parallel` to configure how many instances of a job to run in parallel.
-The value can be from 2 to 50.
+**Possible inputs**: A numeric value from `2` to `50`.
-The `parallel` keyword creates N instances of the same job that run in parallel.
-They are named sequentially from `job_name 1/N` to `job_name N/N`:
+**Example of `parallel`**:
```yaml
test:
@@ -3472,47 +3411,32 @@ test:
parallel: 5
```
-Every parallel job has a `CI_NODE_INDEX` and `CI_NODE_TOTAL`
-[predefined CI/CD variable](../variables/index.md#predefined-cicd-variables) set.
+This example creates 5 jobs that run in parallel, named `test 1/5` to `test 5/5`.
-Different languages and test suites have different methods to enable parallelization.
-For example, use [Semaphore Test Boosters](https://github.com/renderedtext/test-boosters)
-and RSpec to run Ruby tests in parallel:
-
-```ruby
-# Gemfile
-source 'https://rubygems.org'
+**Additional details**:
-gem 'rspec'
-gem 'semaphore_test_boosters'
-```
+- Every parallel job has a `CI_NODE_INDEX` and `CI_NODE_TOTAL`
+ [predefined CI/CD variable](../variables/index.md#predefined-cicd-variables) set.
-```yaml
-test:
- parallel: 3
- script:
- - bundle
- - bundle exec rspec_booster --job $CI_NODE_INDEX/$CI_NODE_TOTAL
-```
-
-WARNING:
-Test Boosters reports usage statistics to the author.
+**Related topics**:
-You can then navigate to the **Jobs** tab of a new pipeline build and see your RSpec
-job split into three separate jobs.
+- [Parallelize large jobs](../jobs/job_control.md#parallelize-large-jobs).
-#### Parallel `matrix` jobs
+#### `parallel:matrix`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15356) in GitLab 13.3.
+> - The job naming style was [improved in GitLab 13.4](https://gitlab.com/gitlab-org/gitlab/-/issues/230452).
-Use `matrix:` to run a job multiple times in parallel in a single pipeline,
+Use `parallel:matrix` to run a job multiple times in parallel in a single pipeline,
but with different variable values for each instance of the job.
-There can be from 2 to 50 jobs.
-Jobs can only run in parallel if there are multiple runners, or a single runner is
-configured to run multiple jobs concurrently.
+Multiple runners must exist, or a single runner must be configured to run multiple jobs concurrently.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**: A numeric value from `2` to `50`.
-Every job gets the same `CI_NODE_TOTAL` [CI/CD variable](../variables/index.md#predefined-cicd-variables) value, and a unique `CI_NODE_INDEX` value.
+**Example of `parallel:matrix`**:
```yaml
deploystacks:
@@ -3532,7 +3456,7 @@ deploystacks:
STACK: [data, processing]
```
-The following example generates 10 parallel `deploystacks` jobs, each with different values
+The example generates 10 parallel `deploystacks` jobs, each with different values
for `PROVIDER` and `STACK`:
```plaintext
@@ -3548,105 +3472,29 @@ deploystacks: [vultr, data]
deploystacks: [vultr, processing]
```
-The job naming style was [improved in GitLab 13.4](https://gitlab.com/gitlab-org/gitlab/-/issues/230452).
-
-##### One-dimensional `matrix` jobs
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26362) in GitLab 13.5.
-
-You can also have one-dimensional matrices with a single job:
-
-```yaml
-deploystacks:
- stage: deploy
- script:
- - bin/deploy
- parallel:
- matrix:
- - PROVIDER: [aws, ovh, gcp, vultr]
-```
-
-##### Parallel `matrix` trigger jobs
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/270957) in GitLab 13.10.
-
-Use `matrix:` to run a [trigger](#trigger) job multiple times in parallel in a single pipeline,
-but with different variable values for each instance of the job.
-
-```yaml
-deploystacks:
- stage: deploy
- trigger:
- include: path/to/child-pipeline.yml
- parallel:
- matrix:
- - PROVIDER: aws
- STACK: [monitoring, app1]
- - PROVIDER: ovh
- STACK: [monitoring, backup]
- - PROVIDER: [gcp, vultr]
- STACK: [data]
-```
-
-This example generates 6 parallel `deploystacks` trigger jobs, each with different values
-for `PROVIDER` and `STACK`, and they create 6 different child pipelines with those variables.
-
-```plaintext
-deploystacks: [aws, monitoring]
-deploystacks: [aws, app1]
-deploystacks: [ovh, monitoring]
-deploystacks: [ovh, backup]
-deploystacks: [gcp, data]
-deploystacks: [vultr, data]
-```
+**Related topics**:
-In [GitLab 14.1 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/239737), you can
-use the variables defined in `parallel: matrix` with the [`tags`](#tags) keyword for
-dynamic runner selection.
-
-```yaml
-deploystacks:
- stage: deploy
- parallel:
- matrix:
- - PROVIDER: aws
- STACK: [monitoring, app1]
- - PROVIDER: gcp
- STACK: [data]
- tags:
- - ${PROVIDER}-${STACK}
-```
+- [Run a one-dimensional matrix of parallel jobs](../jobs/job_control.md#run-a-one-dimensional-matrix-of-parallel-jobs).
+- [Run a matrix of triggered parallel jobs](../jobs/job_control.md#run-a-matrix-of-parallel-trigger-jobs).
### `trigger`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) in GitLab Premium 11.8.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
-Use `trigger` to define a downstream pipeline trigger. When GitLab starts a `trigger` job,
-a downstream pipeline is created.
-
-Jobs with `trigger` can only use a [limited set of keywords](../pipelines/multi_project_pipelines.md#define-multi-project-pipelines-in-your-gitlab-ciyml-file).
-For example, you can't run commands with [`script`](#script), [`before_script`](#before_script),
-or [`after_script`](#after_script).
-
-You can use this keyword to create two different types of downstream pipelines:
+Use `trigger` to start a downstream pipeline that is either:
-- [Multi-project pipelines](../pipelines/multi_project_pipelines.md#define-multi-project-pipelines-in-your-gitlab-ciyml-file)
-- [Child pipelines](../pipelines/parent_child_pipelines.md)
+- [A multi-project pipeline](../pipelines/multi_project_pipelines.md).
+- [A child pipeline](../pipelines/parent_child_pipelines.md).
-In [GitLab 13.2 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/197140/), you can
-view which job triggered a downstream pipeline. In the [pipeline graph](../pipelines/index.md#visualize-pipelines),
-hover over the downstream pipeline job.
+**Keyword type**: Job keyword. You can use it only as part of a job.
-In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/201938), you
-can use [`when:manual`](#when) in the same job as `trigger`. In GitLab 13.4 and
-earlier, using them together causes the error `jobs:#{job-name} when should be on_success, on_failure or always`.
-You [cannot start `manual` trigger jobs with the API](https://gitlab.com/gitlab-org/gitlab/-/issues/284086).
+**Possible inputs**:
-#### Basic `trigger` syntax for multi-project pipelines
+- For multi-project pipelines, path to the downstream project.
+- For child pipelines, path to the child pipeline CI/CD configuration file.
-You can configure a downstream trigger by using the `trigger` keyword
-with a full path to a downstream project:
+**Example of `trigger` for multi-project pipeline**:
```yaml
rspec:
@@ -3658,47 +3506,7 @@ staging:
trigger: my/deployment
```
-#### Complex `trigger` syntax for multi-project pipelines
-
-You can configure a branch name that GitLab uses to create
-a downstream pipeline with:
-
-```yaml
-rspec:
- stage: test
- script: bundle exec rspec
-
-staging:
- stage: deploy
- trigger:
- project: my/deployment
- branch: stable
-```
-
-To mirror the status from a triggered pipeline:
-
-```yaml
-trigger_job:
- trigger:
- project: my/project
- strategy: depend
-```
-
-To mirror the status from an upstream pipeline:
-
-```yaml
-upstream_bridge:
- stage: test
- needs:
- pipeline: other/project
-```
-
-#### `trigger` syntax for child pipeline
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16094) in GitLab 12.7.
-
-To create a [child pipeline](../pipelines/parent_child_pipelines.md), specify the path to the
-YAML file that contains the configuration of the child pipeline:
+**Example of `trigger` for child pipelines**:
```yaml
trigger_job:
@@ -3706,71 +3514,36 @@ trigger_job:
include: path/to/child-pipeline.yml
```
-Similar to [multi-project pipelines](../pipelines/multi_project_pipelines.md#mirror-status-of-a-triggered-pipeline-in-the-trigger-job),
-it's possible to mirror the status from a triggered pipeline:
-
-```yaml
-trigger_job:
- trigger:
- include:
- - local: path/to/child-pipeline.yml
- strategy: depend
-```
-
-##### Trigger child pipeline with generated configuration file
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35632) in GitLab 12.9.
-
-You can also trigger a child pipeline from a [dynamically generated configuration file](../pipelines/parent_child_pipelines.md#dynamic-child-pipelines):
-
-```yaml
-generate-config:
- stage: build
- script: generate-ci-config > generated-config.yml
- artifacts:
- paths:
- - generated-config.yml
-
-child-pipeline:
- stage: test
- trigger:
- include:
- - artifact: generated-config.yml
- job: generate-config
-```
-
-The `generated-config.yml` is extracted from the artifacts and used as the configuration
-for triggering the child pipeline.
+**Additional details**:
-##### Trigger child pipeline with files from another project
+- Jobs with `trigger` can only use a [limited set of keywords](../pipelines/multi_project_pipelines.md#define-multi-project-pipelines-in-your-gitlab-ciyml-file).
+ For example, you can't run commands with [`script`](#script), [`before_script`](#before_script),
+ or [`after_script`](#after_script).
+- In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/201938), you
+ can use [`when:manual`](#when) in the same job as `trigger`. In GitLab 13.4 and
+ earlier, using them together causes the error `jobs:#{job-name} when should be on_success, on_failure or always`.
+- In [GitLab 13.2 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/197140/), you can
+ view which job triggered a downstream pipeline in the [pipeline graph](../pipelines/index.md#visualize-pipelines).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/205157) in GitLab 13.5.
+**Related topics**:
-To trigger child pipelines with files from another private project under the same
-GitLab instance, use [`include:file`](#includefile):
+- [Multi-project pipeline configuration examples](../pipelines/multi_project_pipelines.md#define-multi-project-pipelines-in-your-gitlab-ciyml-file).
+- [Child pipeline configuration examples](../pipelines/parent_child_pipelines.md#examples).
+- To force a rebuild of a specific branch, tag, or commit, you can
+ [use an API call with a trigger token](../triggers/index.md).
+ The trigger token is different than the `trigger` keyword.
-```yaml
-child-pipeline:
- trigger:
- include:
- - project: 'my-group/my-pipeline-library'
- ref: 'main'
- file: '/path/to/child-pipeline.yml'
-```
+#### `trigger:strategy`
-#### Linking pipelines with `trigger:strategy`
+Use `trigger:strategy` to force the `trigger` job to wait for the downstream pipeline to complete
+before it is marked as **success**.
-By default, the `trigger` job completes with the `success` status
-as soon as the downstream pipeline is created.
+This behavior is different than the default, which is for the `trigger` job to be marked as
+**success** as soon as the downstream pipeline is created.
-To force the `trigger` job to wait for the downstream (multi-project or child) pipeline to complete, use
-`strategy: depend`. This setting makes the trigger job wait with a "running" status until the triggered
-pipeline completes. At that point, the `trigger` job completes and displays the same status as
-the downstream job.
+This setting makes your pipeline execution linear rather than parallel.
-This setting can help keep your pipeline execution linear. In the following example, jobs from
-subsequent stages wait for the triggered pipeline to successfully complete before
-starting, which reduces parallelization.
+**Example of `trigger:strategy`**:
```yaml
trigger_job:
@@ -3779,14 +3552,8 @@ trigger_job:
strategy: depend
```
-#### Trigger a pipeline by API call
-
-To force a rebuild of a specific branch, tag, or commit, you can use an API call
-with a trigger token.
-
-The trigger token is different than the [`trigger`](#trigger) keyword.
-
-[Read more in the triggers documentation.](../triggers/index.md)
+In this example, jobs from subsequent stages wait for the triggered pipeline to
+successfully complete before starting.
### `interruptible`
@@ -3800,7 +3567,8 @@ a new pipeline starts on the same branch.
You can't cancel subsequent jobs after a job with `interruptible: false` starts.
-**Keyword type**: Job keyword. You can use it only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default:` section](#default).
**Possible inputs**: `true` or `false` (default).
@@ -3846,304 +3614,180 @@ In this example, a new pipeline causes a running pipeline to be:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15536) in GitLab 12.7.
-Sometimes running multiple jobs at the same time in an environment
-can lead to errors during the deployment.
-
-To avoid these errors, use the `resource_group` attribute to make sure that
-the runner doesn't run certain jobs concurrently. Resource groups behave similar
-to semaphores in other programming languages.
-
-When the `resource_group` keyword is defined for a job in the `.gitlab-ci.yml` file,
-job executions are mutually exclusive across different pipelines for the same project.
-If multiple jobs belonging to the same resource group are enqueued simultaneously,
-only one of the jobs is picked by the runner. The other jobs wait until the
-`resource_group` is free.
+Use `resource_group` to create a [resource group](../resource_groups/index.md) that
+ensures a job is mutually exclusive across different pipelines for the same project.
-For example:
-
-```yaml
-deploy-to-production:
- script: deploy
- resource_group: production
-```
+For example, if multiple jobs that belong to the same resource group are queued simultaneously,
+only one of the jobs starts. The other jobs wait until the `resource_group` is free.
-In this case, two `deploy-to-production` jobs in two separate pipelines can never run at the same time. As a result,
-you can ensure that concurrent deployments never happen to the production environment.
+Resource groups behave similar to semaphores in other programming languages.
You can define multiple resource groups per environment. For example,
-when deploying to physical devices, you may have multiple physical devices. Each device
-can be deployed to, but there can be only one deployment per device at any given time.
+when deploying to physical devices, you might have multiple physical devices. Each device
+can be deployed to, but only one deployment can occur per device at any given time.
-The `resource_group` value can only contain letters, digits, `-`, `_`, `/`, `$`, `{`, `}`, `.`, and spaces.
-It can't start or end with `/`.
-
-For more information, see [Resource Group documentation](../resource_groups/index.md).
-
-#### Pipeline-level concurrency control with Cross-Project/Parent-Child pipelines
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39057) in GitLab 13.9.
+**Keyword type**: Job keyword. You can use it only as part of a job.
-You can define `resource_group` for downstream pipelines that are sensitive to concurrent
-executions. The [`trigger` keyword](#trigger) can trigger downstream pipelines. The
-[`resource_group` keyword](#resource_group) can co-exist with it. This is useful to control the
-concurrency for deployment pipelines, while running non-sensitive jobs concurrently.
+**Possible inputs**: Only letters, digits, `-`, `_`, `/`, `$`, `{`, `}`, `.`, and spaces.
+It can't start or end with `/`.
-The following example has two pipeline configurations in a project. When a pipeline starts running,
-non-sensitive jobs are executed first and aren't affected by concurrent executions in other
-pipelines. However, GitLab ensures that there are no other deployment pipelines running before
-triggering a deployment (child) pipeline. If other deployment pipelines are running, GitLab waits
-until those pipelines finish before running another one.
+**Example of `resource_group`**:
```yaml
-# .gitlab-ci.yml (parent pipeline)
-
-build:
- stage: build
- script: echo "Building..."
-
-test:
- stage: test
- script: echo "Testing..."
-
-deploy:
- stage: deploy
- trigger:
- include: deploy.gitlab-ci.yml
- strategy: depend
- resource_group: AWS-production
+deploy-to-production:
+ script: deploy
+ resource_group: production
```
-```yaml
-# deploy.gitlab-ci.yml (child pipeline)
-
-stages:
- - provision
- - deploy
-
-provision:
- stage: provision
- script: echo "Provisioning..."
+In this example, two `deploy-to-production` jobs in two separate pipelines can never run at the same time. As a result,
+you can ensure that concurrent deployments never happen to the production environment.
-deployment:
- stage: deploy
- script: echo "Deploying..."
-```
+**Related topics**:
-You must define [`strategy: depend`](#linking-pipelines-with-triggerstrategy)
-with the `trigger` keyword. This ensures that the lock isn't released until the downstream pipeline
-finishes.
+- [Pipeline-level concurrency control with cross-project/parent-child pipelines](../resource_groups/index.md#pipeline-level-concurrency-control-with-cross-projectparent-child-pipelines).
### `release`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19298) in GitLab 13.2.
Use `release` to create a [release](../../user/project/releases/index.md).
-Requires the [`release-cli`](https://gitlab.com/gitlab-org/release-cli/-/tree/master/docs)
-to be available in your GitLab Runner Docker or shell executor.
-These keywords are supported:
+The release job must have access to the [`release-cli`](https://gitlab.com/gitlab-org/release-cli/-/tree/master/docs),
+which must be in the `$PATH`.
+
+If you use the [Docker executor](https://docs.gitlab.com/runner/executors/docker.html),
+you can use this image from the GitLab Container Registry: `registry.gitlab.com/gitlab-org/release-cli:latest`
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**: The `release:` subkeys:
- [`tag_name`](#releasetag_name)
-- [`description`](#releasedescription)
- [`name`](#releasename) (optional)
+- [`description`](#releasedescription)
- [`ref`](#releaseref) (optional)
- [`milestones`](#releasemilestones) (optional)
- [`released_at`](#releasereleased_at) (optional)
- [`assets:links`](#releaseassetslinks) (optional)
-The release is created only if the job processes without error. If the Rails API
-returns an error during release creation, the `release` job fails.
-
-#### `release-cli` Docker image
-
-You must specify the Docker image to use for the `release-cli`:
-
-```yaml
-image: registry.gitlab.com/gitlab-org/release-cli:latest
-```
-
-#### `release-cli` for shell executors
-
-> - [Introduced](https://gitlab.com/gitlab-org/release-cli/-/issues/21) in GitLab 13.8.
-> - [Changed](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/108): the `release-cli` binaries are also
-[available in the Package Registry](https://gitlab.com/jaime/release-cli/-/packages)
-starting from GitLab 14.2.
-
-For GitLab Runner shell executors, you can download and install the `release-cli` manually for your [supported OS and architecture](https://release-cli-downloads.s3.amazonaws.com/latest/index.html).
-Once installed, the `release` keyword should be available to you.
-
-**Install on Unix/Linux**
-
-1. Download the binary for your system from S3, in the following example for amd64 systems:
-
- ```shell
- curl --location --output /usr/local/bin/release-cli "https://release-cli-downloads.s3.amazonaws.com/latest/release-cli-linux-amd64"
- ```
+**Example of `release` keyword**:
-Or from the GitLab package registry:
-
- ```shell
- curl --location --output /usr/local/bin/release-cli "https://gitlab.com/api/v4/projects/gitlab-org%2Frelease-cli/packages/generic/release-cli/latest/release-cli-darwin-amd64"
- ```
-
-1. Give it permissions to execute:
-
- ```shell
- sudo chmod +x /usr/local/bin/release-cli
- ```
-
-1. Verify `release-cli` is available:
-
- ```shell
- $ release-cli -v
-
- release-cli version 0.6.0
- ```
-
-**Install on Windows PowerShell**
-
-1. Create a folder somewhere in your system, for example `C:\GitLab\Release-CLI\bin`
-
- ```shell
- New-Item -Path 'C:\GitLab\Release-CLI\bin' -ItemType Directory
- ```
-
-1. Download the executable file:
-
- ```shell
- PS C:\> Invoke-WebRequest -Uri "https://release-cli-downloads.s3.amazonaws.com/latest/release-cli-windows-amd64.exe" -OutFile "C:\GitLab\Release-CLI\bin\release-cli.exe"
-
- Directory: C:\GitLab\Release-CLI
- Mode LastWriteTime Length Name
- ---- ------------- ------ ----
- d----- 3/16/2021 4:17 AM bin
-
- ```
-
-1. Add the directory to your `$env:PATH`:
-
- ```shell
- $env:PATH += ";C:\GitLab\Release-CLI\bin"
+ ```yaml
+ release_job:
+ stage: release
+ image: registry.gitlab.com/gitlab-org/release-cli:latest
+ rules:
+ - if: $CI_COMMIT_TAG # Run this job when a tag is created manually
+ script:
+ - echo 'Running the release job.'
+ release:
+ name: 'Release $CI_COMMIT_TAG'
+ description: 'Release created using the release-cli.'
```
-1. Verify `release-cli` is available:
-
- ```shell
- PS C:\> release-cli -v
+This example creates a release:
- release-cli version 0.6.0
- ```
+- When you push a Git tag.
+- When you add a Git tag in the UI at **Repository > Tags**.
-#### Use a custom SSL CA certificate authority
+**Additional details**:
-You can use the `ADDITIONAL_CA_CERT_BUNDLE` CI/CD variable to configure a custom SSL CA certificate authority,
-which is used to verify the peer when the `release-cli` creates a release through the API using HTTPS with custom certificates.
-The `ADDITIONAL_CA_CERT_BUNDLE` value should contain the
-[text representation of the X.509 PEM public-key certificate](https://tools.ietf.org/html/rfc7468#section-5.1)
-or the `path/to/file` containing the certificate authority.
-For example, to configure this value in the `.gitlab-ci.yml` file, use the following:
+- All release jobs, except [trigger](#trigger) jobs, must include the `script` keyword. A release
+ job can use the output from script commands. If you don't need the script, you can use a placeholder:
-```yaml
-release:
- variables:
- ADDITIONAL_CA_CERT_BUNDLE: |
- -----BEGIN CERTIFICATE-----
- MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
- ...
- jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
- -----END CERTIFICATE-----
+ ```yaml
script:
- - echo "Create release"
- release:
- name: 'My awesome release'
- tag_name: '$CI_COMMIT_TAG'
-```
+ - echo 'release job'
+ ```
-The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a
-[custom variable in the UI](../variables/index.md#custom-cicd-variables),
-either as a `file`, which requires the path to the certificate, or as a variable,
-which requires the text representation of the certificate.
+ An [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/223856) exists to remove this requirement.
-#### `script`
+- The `release` section executes after the `script` keyword and before the `after_script`.
+- A release is created only if the job's main script succeeds.
+- If the release already exists, it is not updated and the job with the `release` keyword fails.
+- If you use the [Shell executor](https://docs.gitlab.com/runner/executors/shell.html) or similar,
+ [install `release-cli`](../../user/project/releases/release_cli.md) on the server where the runner is registered.
-All jobs except [trigger](#trigger) jobs must have the `script` keyword. A `release`
-job can use the output from script commands, but you can use a placeholder script if
-the script is not needed:
+**Related topics**:
-```yaml
-script:
- - echo 'release job'
-```
+- [CI/CD example of the `release` keyword](../../user/project/releases/index.md#cicd-example-of-the-release-keyword).
+- [Create multiple releases in a single pipeline](../../user/project/releases/index.md#create-multiple-releases-in-a-single-pipeline).
+- [Use a custom SSL CA certificate authority](../../user/project/releases/index.md#use-a-custom-ssl-ca-certificate-authority).
-An [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/223856) exists to remove this requirement in an upcoming version of GitLab.
+#### `release:tag_name`
-A pipeline can have multiple `release` jobs, for example:
+Required. The Git tag for the release.
-```yaml
-ios-release:
- script:
- - echo 'iOS release job'
- release:
- tag_name: v1.0.0-ios
- description: 'iOS release v1.0.0'
+If the tag does not exist in the project yet, it is created at the same time as the release.
+New tags use the SHA associated with the pipeline.
-android-release:
- script:
- - echo 'Android release job'
- release:
- tag_name: v1.0.0-android
- description: 'Android release v1.0.0'
-```
+**Keyword type**: Job keyword. You can use it only as part of a job.
-#### `release:tag_name`
+**Possible inputs**: A tag name. Can use [CI/CD variables](../variables/index.md).
-You must specify a `tag_name` for the release. The tag can refer to an existing Git tag or
-you can specify a new tag.
+**Example of `release:tag_name`**:
-When the specified tag doesn't exist in the repository, a new tag is created from the associated SHA of the pipeline.
+To create a release when a new tag is added to the project:
-For example, when creating a release from a Git tag:
+- Use the `$CI_COMMIT_TAG` CI/CD variable as the `tag_name`.
+- Use [`rules:if`](#rulesif) or [`only: tags`](#onlyrefs--exceptrefs) to configure
+ the job to run only for new tags.
```yaml
job:
+ script: echo 'Running the release job for the new tag.'
release:
tag_name: $CI_COMMIT_TAG
description: 'Release description'
+ rules:
+ - if: $CI_COMMIT_TAG
```
-It is also possible for the release job to automatically create a new unique tag. In that case,
-do not use [`rules`](#rules) or [`only`](#only--except) to configure the job to
-only run for tags.
-
-A semantic versioning example:
+To create a release and a new tag at the same time, your [`rules`](#rules) or [`only`](#only--except)
+should **not** configure the job to run only for new tags. A semantic versioning example:
```yaml
job:
+ script: echo 'Running the release job and creating a new tag.'
release:
tag_name: ${MAJOR}_${MINOR}_${REVISION}
description: 'Release description'
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "schedule"
```
-- The release is created only if the job's main script succeeds.
-- If the release already exists, it is not updated and the job with the `release` keyword fails.
-- The `release` section executes after the `script` tag and before the `after_script`.
-
#### `release:name`
The release name. If omitted, it is populated with the value of `release: tag_name`.
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**: A text string.
+
+**Example of `release:name`**:
+
+```yaml
+ release_job:
+ stage: release
+ release:
+ name: 'Release $CI_COMMIT_TAG'
+```
+
#### `release:description`
-Specifies the long description of the release. You can also specify a file that contains the
-description.
+The long description of the release.
-##### Read description from a file
+**Keyword type**: Job keyword. You can use it only as part of a job.
-> [Introduced](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/67) in GitLab 13.7.
+**Possible inputs**:
-You can specify a file in `$CI_PROJECT_DIR` that contains the description. The file must be relative
-to the project directory (`$CI_PROJECT_DIR`), and if the file is a symbolic link it can't reside
-outside of `$CI_PROJECT_DIR`. The `./path/to/file` and filename can't contain spaces.
+- A string with the long description.
+- The path to a file that contains the description. Introduced in [GitLab 13.7](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/67).
+ - The file location must be relative to the project directory (`$CI_PROJECT_DIR`).
+ - If the file is a symbolic link, it must be in the `$CI_PROJECT_DIR`.
+ - The `./path/to/file` and filename can't contain spaces.
+
+**Example of `release:description`**:
```yaml
job:
@@ -4154,8 +3798,13 @@ job:
#### `release:ref`
-If the `release: tag_name` doesn't exist yet, the release is created from `ref`.
-`ref` can be a commit SHA, another tag name, or a branch name.
+The `ref` for the release, if the `release: tag_name` doesn't exist yet.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**:
+
+- A commit SHA, another tag name, or a branch name.
#### `release:milestones`
@@ -4163,21 +3812,31 @@ The title of each milestone the release is associated with.
#### `release:released_at`
-The date and time when the release is ready. Defaults to the current date and time if not
-defined. Should be enclosed in quotes and expressed in ISO 8601 format.
+The date and time when the release is ready.
-```json
+**Possible inputs**:
+
+- A date enclosed in quotes and expressed in ISO 8601 format.
+
+**Example of `release:released_at`**:
+
+```yaml
released_at: '2021-03-15T08:00:00Z'
```
+**Additional details**:
+
+- If it is not defined, the current date and time is used.
+
#### `release:assets:links`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/271454) in GitLab 13.12.
-Include [asset links](../../user/project/releases/index.md#release-assets) in the release.
+Use `release:assets:links` to include [asset links](../../user/project/releases/index.md#release-assets) in the release.
-NOTE:
-Requires `release-cli` version v0.4.0 or higher.
+Requires `release-cli` version v0.4.0 or later.
+
+**Example of `release:assets:links`**:
```yaml
assets:
@@ -4190,174 +3849,86 @@ assets:
link_type: 'other' # optional
```
-#### Complete example for `release`
-
-If you combine the previous examples for `release`, you get two options, depending on how you generate the
-tags. You can't use these options together, so choose one:
-
-- To create a release when you push a Git tag, or when you add a Git tag
- in the UI by going to **Repository > Tags**:
-
- ```yaml
- release_job:
- stage: release
- image: registry.gitlab.com/gitlab-org/release-cli:latest
- rules:
- - if: $CI_COMMIT_TAG # Run this job when a tag is created manually
- script:
- - echo 'running release_job'
- release:
- name: 'Release $CI_COMMIT_TAG'
- description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION must be defined
- tag_name: '$CI_COMMIT_TAG' # elsewhere in the pipeline.
- ref: '$CI_COMMIT_TAG'
- milestones:
- - 'm1'
- - 'm2'
- - 'm3'
- released_at: '2020-07-15T08:00:00Z' # Optional, is auto generated if not defined, or can use a variable.
- assets: # Optional, multiple asset links
- links:
- - name: 'asset1'
- url: 'https://example.com/assets/1'
- - name: 'asset2'
- url: 'https://example.com/assets/2'
- filepath: '/pretty/url/1' # optional
- link_type: 'other' # optional
- ```
-
-- To create a release automatically when commits are pushed or merged to the default branch,
- using a new Git tag that is defined with variables:
-
- NOTE:
- Environment variables set in `before_script` or `script` are not available for expanding
- in the same job. Read more about
- [potentially making variables available for expanding](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6400).
+### `secrets` **(PREMIUM)**
- ```yaml
- prepare_job:
- stage: prepare # This stage must run before the release stage
- rules:
- - if: $CI_COMMIT_TAG
- when: never # Do not run this job when a tag is created manually
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
- script:
- - echo "EXTRA_DESCRIPTION=some message" >> variables.env # Generate the EXTRA_DESCRIPTION and TAG environment variables
- - echo "TAG=v$(cat VERSION)" >> variables.env # and append to the variables.env file
- artifacts:
- reports:
- dotenv: variables.env # Use artifacts:reports:dotenv to expose the variables to other jobs
-
- release_job:
- stage: release
- image: registry.gitlab.com/gitlab-org/release-cli:latest
- needs:
- - job: prepare_job
- artifacts: true
- rules:
- - if: $CI_COMMIT_TAG
- when: never # Do not run this job when a tag is created manually
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
- script:
- - echo 'running release_job for $TAG'
- release:
- name: 'Release $TAG'
- description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION and the $TAG
- tag_name: '$TAG' # variables must be defined elsewhere
- ref: '$CI_COMMIT_SHA' # in the pipeline. For example, in the
- milestones: # prepare_job
- - 'm1'
- - 'm2'
- - 'm3'
- released_at: '2020-07-15T08:00:00Z' # Optional, is auto generated if not defined, or can use a variable.
- assets:
- links:
- - name: 'asset1'
- url: 'https://example.com/assets/1'
- - name: 'asset2'
- url: 'https://example.com/assets/2'
- filepath: '/pretty/url/1' # optional
- link_type: 'other' # optional
- ```
-
-#### Release assets as Generic packages
-
-You can use [Generic packages](../../user/packages/generic_packages/) to host your release assets.
-For a complete example, see the [Release assets as Generic packages](https://gitlab.com/gitlab-org/release-cli/-/tree/master/docs/examples/release-assets-as-generic-package/)
-project.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33014) in GitLab 13.4.
-#### `release-cli` command line
+Use `secrets` to specify [CI/CD secrets](../secrets/index.md) to:
-The entries under the `release` node are transformed into a `bash` command line and sent
-to the Docker container, which contains the [release-cli](https://gitlab.com/gitlab-org/release-cli).
-You can also call the `release-cli` directly from a `script` entry.
+- Retrieve from an external secrets provider.
+- Make available in the job as [CI/CD variables](../variables/index.md)
+ ([`file` type](../variables/index.md#cicd-variable-types) by default).
-For example, if you use the YAML described previously:
+This keyword must be used with `secrets:vault`.
-```shell
-release-cli create --name "Release $CI_COMMIT_SHA" --description "Created using the release-cli $EXTRA_DESCRIPTION" --tag-name "v${MAJOR}.${MINOR}.${REVISION}" --ref "$CI_COMMIT_SHA" --released-at "2020-07-15T08:00:00Z" --milestone "m1" --milestone "m2" --milestone "m3" --assets-link "{\"name\":\"asset1\",\"url\":\"https://example.com/assets/1\",\"link_type\":\"other\"}
-```
+#### `secrets:vault`
-### `secrets`
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28321) in GitLab 13.4 and GitLab Runner 13.4.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33014) in GitLab 13.4.
+Use `secrets:vault` to specify secrets provided by a [HashiCorp Vault](https://www.vaultproject.io/).
-Use `secrets` to specify the [CI/CD Secrets](../secrets/index.md) the job needs. It should be a hash,
-and the keys should be the names of the variables that are made available to the job.
-The value of each secret is saved in a temporary file. This file's path is stored in these
-variables.
+**Keyword type**: Job keyword. You can use it only as part of a job.
-#### `secrets:vault` **(PREMIUM)**
+**Possible inputs**:
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28321) in GitLab 13.4 and GitLab Runner 13.4.
+- `engine:name`: Name of the secrets engine.
+- `engine:path`: Path to the secrets engine.
+- `path`: Path to the secret.
+- `field`: Name of the field where the password is stored.
-Use `vault` to specify secrets provided by [Hashicorp's Vault](https://www.vaultproject.io/).
+**Example of `secrets:vault`**:
-This syntax has multiple forms. The shortest form assumes the use of the
-[KV-V2](https://www.vaultproject.io/docs/secrets/kv/kv-v2) secrets engine,
-mounted at the default path `kv-v2`. The last part of the secret's path is the
-field to fetch the value for:
+To specify all details explicitly and use the [KV-V2](https://www.vaultproject.io/docs/secrets/kv/kv-v2) secrets engine:
```yaml
job:
secrets:
- DATABASE_PASSWORD:
- vault: production/db/password # translates to secret `kv-v2/data/production/db`, field `password`
+ DATABASE_PASSWORD: # Store the path to the secret in this CI/CD variable
+ vault: # Translates to secret: `ops/data/production/db`, field: `password`
+ engine:
+ name: kv-v2
+ path: ops
+ path: production/db
+ field: password
```
-You can specify a custom secrets engine path by adding a suffix starting with `@`:
+You can shorten this syntax. With the short syntax, `engine:name` and `engine:path`
+both default to `kv-v2`:
```yaml
job:
secrets:
- DATABASE_PASSWORD:
- vault: production/db/password@ops # translates to secret `ops/data/production/db`, field `password`
+ DATABASE_PASSWORD: # Store the path to the secret in this CI/CD variable
+ vault: production/db/password # Translates to secret: `kv-v2/data/production/db`, field: `password`
```
-In the detailed form of the syntax, you can specify all details explicitly:
+To specify a custom secrets engine path in the short syntax, add a suffix that starts with `@`:
```yaml
job:
secrets:
- DATABASE_PASSWORD: # translates to secret `ops/data/production/db`, field `password`
- vault:
- engine:
- name: kv-v2
- path: ops
- path: production/db
- field: password
+ DATABASE_PASSWORD: # Store the path to the secret in this CI/CD variable
+ vault: production/db/password@ops # Translates to secret: `ops/data/production/db`, field: `password`
```
-#### `secrets:file` **(PREMIUM)**
+#### `secrets:file`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250695) in GitLab 14.1 and GitLab Runner 14.1.
-By default, the secret is passed to the job context as a variable of type
-[`file`](../variables/index.md#cicd-variable-types). The value of the
-secret is stored in a file and the variable `DATABASE_PASSWORD` contains a path to the file.
+Use `secrets:file` to configure the secret to be stored as either a
+[`file` or `variable` type CI/CD variable](../variables/index.md#cicd-variable-types)
-However, some software does not work with file variables and might require the secret value to be stored
-directly in the environment variable. For that case, define a `file` setting:
+By default, the secret is passed to the job as a `file` type CI/CD variable. The value
+of the secret is stored in the file and the variable contains the path to the file.
+
+If your software can't use `file` type CI/CD variables, set `file: false` to store
+the secret value directly in the variable.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**: `true` (default) or `false`.
+
+**Example of `secrets:file`**:
```yaml
job:
@@ -4367,11 +3938,10 @@ job:
file: false
```
-When you set `file: false`, no files are created for that variable. It contains the secret
-itself instead.
+**Additional details**:
-The `file` is a setting of the secret, so it belongs directly under the variable
-name level and not in the `vault` section.
+- The `file` keyword is a setting for the CI/CD variable and must be nested under
+ the CI/CD variable name, not in the `vault` section.
### `pages`
@@ -4410,484 +3980,154 @@ You must:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207484) in GitLab 12.9.
-Use `inherit:` to control inheritance of globally-defined defaults
-and variables.
-
-To enable or disable the inheritance of all `default:` or `variables:` keywords, use:
+Use `inherit:` to [control inheritance of globally-defined defaults and variables](../jobs/index.md#control-the-inheritance-of-default-keywords-and-global-variables).
-- `default: true` or `default: false`
-- `variables: true` or `variables: false`
+#### `inherit:default`
-To inherit only a subset of `default:` keywords or `variables:`, specify what
-you wish to inherit. Anything not listed is **not** inherited. Use
-one of the following formats:
+Use `inherit:default` to control the inheritance of [default keywords](#default).
-```yaml
-inherit:
- default: [keyword1, keyword2]
- variables: [VARIABLE1, VARIABLE2]
-```
-
-Or:
+**Keyword type**: Job keyword. You can use it only as part of a job.
-```yaml
-inherit:
- default:
- - keyword1
- - keyword2
- variables:
- - VARIABLE1
- - VARIABLE2
-```
+**Possible inputs**:
-In the following example:
+- `true` (default) or `false` to enable or disable the inheritance of all default keywords.
+- A list of specific default keywords to inherit.
-- `rubocop`:
- - inherits: Nothing.
-- `rspec`:
- - inherits: the default `image` and the `WEBHOOK_URL` variable.
- - does **not** inherit: the default `before_script` and the `DOMAIN` variable.
-- `capybara`:
- - inherits: the default `before_script` and `image`.
- - does **not** inherit: the `DOMAIN` and `WEBHOOK_URL` variables.
-- `karma`:
- - inherits: the default `image` and `before_script`, and the `DOMAIN` variable.
- - does **not** inherit: `WEBHOOK_URL` variable.
+**Example of `inherit:default`:**
```yaml
default:
- image: 'ruby:2.4'
- before_script:
- - echo Hello World
-
-variables:
- DOMAIN: example.com
- WEBHOOK_URL: https://my-webhook.example.com
+ retry: 2
+ image: ruby:3.0
+ interruptible: true
-rubocop:
+job1:
+ script: echo "This job does not inherit any default keywords."
inherit:
default: false
- variables: false
- script: bundle exec rubocop
-rspec:
- inherit:
- default: [image]
- variables: [WEBHOOK_URL]
- script: bundle exec rspec
-
-capybara:
- inherit:
- variables: false
- script: bundle exec capybara
-
-karma:
+job2:
+ script: echo "This job inherits only the two listed default keywords. It does not inherit 'interruptible'."
inherit:
- default: true
- variables: [DOMAIN]
- script: karma
+ default:
+ - retry
+ - image
```
-## `variables`
-
-> Introduced in GitLab Runner v0.5.0.
-
-[CI/CD variables](../variables/index.md) are configurable values that are passed to jobs.
-They can be set globally and per-job.
-
-There are two types of variables.
-
-- [Custom variables](../variables/index.md#custom-cicd-variables):
- You can define their values in the `.gitlab-ci.yml` file, in the GitLab UI,
- or by using the API. You can also input variables in the GitLab UI when
- [running a pipeline manually](../pipelines/index.md#run-a-pipeline-manually).
-- [Predefined variables](../variables/predefined_variables.md):
- These values are set by the runner itself.
- One example is `CI_COMMIT_REF_NAME`, which is the branch or tag the project is built for.
-
-After you define a variable, you can use it in all executed commands and scripts.
-
-Variables are meant for non-sensitive project configuration, for example:
-
-```yaml
-variables:
- DEPLOY_SITE: "https://example.com/"
-
-deploy_job:
- stage: deploy
- script:
- - deploy-script --url $DEPLOY_SITE --path "/"
-
-deploy_review_job:
- stage: deploy
- variables:
- REVIEW_PATH: "/review"
- script:
- - deploy-review-script --url $DEPLOY_SITE --path $REVIEW_PATH
-```
-
-You can use only integers and strings for the variable's name and value.
+**Additional details:**
-If you define a variable at the top level of the `.gitlab-ci.yml` file, it is global,
-meaning it applies to all jobs. If you define a variable in a job, it's available
-to that job only.
+- You can also list default keywords to inherit on one line: `default: [keyword1, keyword2]`
-If a variable of the same name is defined globally and for a specific job, the
-[job-specific variable overrides the global variable](../variables/index.md#cicd-variable-precedence).
+#### `inherit:variables`
-All YAML-defined variables are also set to any linked
-[Docker service containers](../services/index.md).
+Use `inherit:variables` to control the inheritance of [global variables](#variables) keywords.
-You can use [YAML anchors for variables](#yaml-anchors-for-variables).
+**Keyword type**: Job keyword. You can use it only as part of a job.
-### Prefill variables in manual pipelines
+**Possible inputs**:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30101) in GitLab 13.7.
+- `true` (default) or `false` to enable or disable the inheritance of all global variables.
+- A list of specific variables to inherit.
-Use the `value` and `description` keywords to define [pipeline-level (global) variables that are prefilled](../pipelines/index.md#prefill-variables-in-manual-pipelines)
-when [running a pipeline manually](../pipelines/index.md#run-a-pipeline-manually):
+**Example of `inherit:variables`:**
```yaml
variables:
- DEPLOY_ENVIRONMENT:
- value: "staging" # Deploy to staging by default
- description: "The deployment target. Change this variable to 'canary' or 'production' if needed."
-```
-
-You cannot set job-level variables to be pre-filled when you run a pipeline manually.
-
-### Configure runner behavior with variables
-
-You can use [CI/CD variables](../variables/index.md) to configure how the runner processes Git requests:
+ VARIABLE1: "This is variable 1"
+ VARIABLE2: "This is variable 2"
+ VARIABLE3: "This is variable 3"
-- [`GIT_STRATEGY`](../runners/configure_runners.md#git-strategy)
-- [`GIT_SUBMODULE_STRATEGY`](../runners/configure_runners.md#git-submodule-strategy)
-- [`GIT_CHECKOUT`](../runners/configure_runners.md#git-checkout)
-- [`GIT_CLEAN_FLAGS`](../runners/configure_runners.md#git-clean-flags)
-- [`GIT_FETCH_EXTRA_FLAGS`](../runners/configure_runners.md#git-fetch-extra-flags)
-- [`GIT_DEPTH`](../runners/configure_runners.md#shallow-cloning) (shallow cloning)
-- [`GIT_CLONE_PATH`](../runners/configure_runners.md#custom-build-directories) (custom build directories)
-- [`TRANSFER_METER_FREQUENCY`](../runners/configure_runners.md#artifact-and-cache-settings) (artifact/cache meter update frequency)
-- [`ARTIFACT_COMPRESSION_LEVEL`](../runners/configure_runners.md#artifact-and-cache-settings) (artifact archiver compression level)
-- [`CACHE_COMPRESSION_LEVEL`](../runners/configure_runners.md#artifact-and-cache-settings) (cache archiver compression level)
-
-You can also use variables to configure how many times a runner
-[attempts certain stages of job execution](../runners/configure_runners.md#job-stages-attempts).
-
-## YAML-specific features
-
-In your `.gitlab-ci.yml` file, you can use YAML-specific features like anchors (`&`), aliases (`*`),
-and map merging (`<<`). Use these features to reduce the complexity
-of the code in the `.gitlab-ci.yml` file.
-
-Read more about the various [YAML features](https://learnxinyminutes.com/docs/yaml/).
-
-In most cases, the [`extends` keyword](#extends) is more user friendly and you should
-use it when possible.
-
-You can use YAML anchors to merge YAML arrays.
-
-### Anchors
-
-YAML has a feature called 'anchors' that you can use to duplicate
-content across your document.
-
-Use anchors to duplicate or inherit properties. Use anchors with [hidden jobs](#hide-jobs)
-to provide templates for your jobs. When there are duplicate keys, GitLab
-performs a reverse deep merge based on the keys.
-
-You can't use YAML anchors across multiple files when using the [`include`](#include)
-keyword. Anchors are only valid in the file they were defined in. To reuse configuration
-from different YAML files, use [`!reference` tags](#reference-tags) or the
-[`extends` keyword](#extends).
-
-The following example uses anchors and map merging. It creates two jobs,
-`test1` and `test2`, that inherit the `.job_template` configuration, each
-with their own custom `script` defined:
-
-```yaml
-.job_template: &job_configuration # Hidden yaml configuration that defines an anchor named 'job_configuration'
- image: ruby:2.6
- services:
- - postgres
- - redis
-
-test1:
- <<: *job_configuration # Merge the contents of the 'job_configuration' alias
- script:
- - test1 project
+job1:
+ script: echo "This job does not inherit any global variables."
+ inherit:
+ variables: false
-test2:
- <<: *job_configuration # Merge the contents of the 'job_configuration' alias
- script:
- - test2 project
+job2:
+ script: echo "This job inherits only the two listed global variables. It does not inherit 'VARIABLE3'."
+ inherit:
+ variables:
+ - VARIABLE1
+ - VARIABLE2
```
-`&` sets up the name of the anchor (`job_configuration`), `<<` means "merge the
-given hash into the current one," and `*` includes the named anchor
-(`job_configuration` again). The expanded version of this example is:
-
-```yaml
-.job_template:
- image: ruby:2.6
- services:
- - postgres
- - redis
+**Additional details:**
-test1:
- image: ruby:2.6
- services:
- - postgres
- - redis
- script:
- - test1 project
+- You can also list global variables to inherit on one line: `variables: [VARIABLE1, VARIABLE2]`
-test2:
- image: ruby:2.6
- services:
- - postgres
- - redis
- script:
- - test2 project
-```
+## `variables`
-You can use anchors to define two sets of services. For example, `test:postgres`
-and `test:mysql` share the `script` defined in `.job_template`, but use different
-`services`, defined in `.postgres_services` and `.mysql_services`:
+[CI/CD variables](../variables/index.md) are configurable values that are passed to jobs.
+Use `variables` to create [custom variables](../variables/index.md#custom-cicd-variables).
-```yaml
-.job_template: &job_configuration
- script:
- - test project
- tags:
- - dev
+Variables are always available in `script`, `before_script`, and `after_script` commands.
+You can also use variables as inputs in some job keywords.
-.postgres_services:
- services: &postgres_configuration
- - postgres
- - ruby
+**Keyword type**: Global and job keyword. You can use it at the global level,
+and also at the job level.
-.mysql_services:
- services: &mysql_configuration
- - mysql
- - ruby
+If you define `variables` at the global level, each variable is copied to
+every job configuration when the pipeline is created. If the job already has that
+variable defined, the [job-level variable takes precedence](../variables/index.md#cicd-variable-precedence).
-test:postgres:
- <<: *job_configuration
- services: *postgres_configuration
- tags:
- - postgres
+**Possible inputs**: Variable name and value pairs:
-test:mysql:
- <<: *job_configuration
- services: *mysql_configuration
-```
+- The name can use only numbers, letters, and underscores (`_`).
+- The value must be a string.
-The expanded version is:
+**Examples of `variables`:**
```yaml
-.job_template:
- script:
- - test project
- tags:
- - dev
-
-.postgres_services:
- services:
- - postgres
- - ruby
-
-.mysql_services:
- services:
- - mysql
- - ruby
-
-test:postgres:
- script:
- - test project
- services:
- - postgres
- - ruby
- tags:
- - postgres
-
-test:mysql:
- script:
- - test project
- services:
- - mysql
- - ruby
- tags:
- - dev
-```
-
-You can see that the hidden jobs are conveniently used as templates, and
-`tags: [postgres]` overwrites `tags: [dev]`.
-
-#### YAML anchors for scripts
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23005) in GitLab 12.5.
-
-You can use [YAML anchors](#anchors) with [script](#script), [`before_script`](#before_script),
-and [`after_script`](#after_script) to use predefined commands in multiple jobs:
-
-```yaml
-.some-script-before: &some-script-before
- - echo "Execute this script first"
-
-.some-script: &some-script
- - echo "Execute this script second"
- - echo "Execute this script too"
-
-.some-script-after: &some-script-after
- - echo "Execute this script last"
-
-job1:
- before_script:
- - *some-script-before
- script:
- - *some-script
- - echo "Execute something, for this job only"
- after_script:
- - *some-script-after
+variables:
+ DEPLOY_SITE: "https://example.com/"
-job2:
+deploy_job:
+ stage: deploy
script:
- - *some-script-before
- - *some-script
- - echo "Execute something else, for this job only"
- - *some-script-after
-```
-
-#### YAML anchors for variables
-
-Use [YAML anchors](#anchors) with `variables` to repeat assignment
-of variables across multiple jobs. You can also use YAML anchors when a job
-requires a specific `variables` block that would otherwise override the global variables.
-
-The following example shows how override the `GIT_STRATEGY` variable without affecting
-the use of the `SAMPLE_VARIABLE` variable:
-
-```yaml
-# global variables
-variables: &global-variables
- SAMPLE_VARIABLE: sample_variable_value
- ANOTHER_SAMPLE_VARIABLE: another_sample_variable_value
+ - deploy-script --url $DEPLOY_SITE --path "/"
-# a job that must set the GIT_STRATEGY variable, yet depend on global variables
-job_no_git_strategy:
- stage: cleanup
+deploy_review_job:
+ stage: deploy
variables:
- <<: *global-variables
- GIT_STRATEGY: none
- script: echo $SAMPLE_VARIABLE
-```
-
-### Hide jobs
-
-If you want to temporarily disable a job, rather than commenting out all the
-lines where the job is defined:
-
-```yaml
-# hidden_job:
-# script:
-# - run test
-```
-
-Instead, you can start its name with a dot (`.`) and it is not processed by
-GitLab CI/CD. In the following example, `.hidden_job` is ignored:
-
-```yaml
-.hidden_job:
+ REVIEW_PATH: "/review"
script:
- - run test
+ - deploy-review-script --url $DEPLOY_SITE --path $REVIEW_PATH
```
-Use this feature to ignore jobs, or use the
-[YAML-specific features](#yaml-specific-features) and transform the hidden jobs
-into templates.
-
-### `!reference` tags
+**Additional details**:
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/266173) in GitLab 13.9.
-> - `rules` keyword support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322992) in GitLab 14.3.
+- All YAML-defined variables are also set to any linked [Docker service containers](../services/index.md).
+- YAML-defined variables are meant for non-sensitive project configuration. Store sensitive information
+ in [protected variables](../variables/index.md#protect-a-cicd-variable) or [CI/CD secrets](../secrets/index.md).
-Use the `!reference` custom YAML tag to select keyword configuration from other job
-sections and reuse it in the current section. Unlike [YAML anchors](#anchors), you can
-use `!reference` tags to reuse configuration from [included](#include) configuration
-files as well.
+**Related topics**:
-In the following example, a `script` and an `after_script` from two different locations are
-reused in the `test` job:
+- You can use [YAML anchors for variables](yaml_optimization.md#yaml-anchors-for-variables).
+- [Predefined variables](../variables/predefined_variables.md) are variables the runner
+ automatically creates and makes available in the job.
+- You can [configure runner behavior with variables](../runners/configure_runners.md#configure-runner-behavior-with-variables).
-- `setup.yml`:
+### `variables:description`
- ```yaml
- .setup:
- script:
- - echo creating environment
- ```
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30101) in GitLab 13.7.
-- `.gitlab-ci.yml`:
+Use the `description` keyword to define a [pipeline-level (global) variable that is prefilled](../pipelines/index.md#prefill-variables-in-manual-pipelines)
+when [running a pipeline manually](../pipelines/index.md#run-a-pipeline-manually).
- ```yaml
- include:
- - local: setup.yml
+Must be used with `value`, for the variable value.
- .teardown:
- after_script:
- - echo deleting environment
+**Keyword type**: Global keyword. You cannot set job-level variables to be pre-filled when you run a pipeline manually.
- test:
- script:
- - !reference [.setup, script]
- - echo running my own command
- after_script:
- - !reference [.teardown, after_script]
- ```
+**Possible inputs**: A string.
-In the following example, `test-vars-1` reuses all the variables in `.vars`, while `test-vars-2`
-selects a specific variable and reuses it as a new `MY_VAR` variable.
+**Example of `variables:description`**:
```yaml
-.vars:
- variables:
- URL: "http://my-url.internal"
- IMPORTANT_VAR: "the details"
-
-test-vars-1:
- variables: !reference [.vars, variables]
- script:
- - printenv
-
-test-vars-2:
- variables:
- MY_VAR: !reference [.vars, variables, IMPORTANT_VAR]
- script:
- - printenv
+variables:
+ DEPLOY_ENVIRONMENT:
+ value: "staging"
+ description: "The deployment target. Change this variable to 'canary' or 'production' if needed."
```
-You can't reuse a section that already includes a `!reference` tag. Only one level
-of nesting is supported.
-
-## Skip Pipeline
-
-To push a commit without triggering a pipeline, add `[ci skip]` or `[skip ci]`, using any
-capitalization, to your commit message.
-
-Alternatively, if you are using Git 2.10 or later, use the `ci.skip` [Git push option](../../user/project/push_options.md#push-options-for-gitlab-cicd).
-The `ci.skip` push option does not skip merge request
-pipelines.
-
-## Processing Git pushes
-
-GitLab creates at most four branch and tag pipelines when
-pushing multiple changes in a single `git push` invocation.
-
-This limitation does not affect any of the updated merge request pipelines.
-All updated merge requests have a pipeline created when using
-[pipelines for merge requests](../pipelines/merge_request_pipelines.md).
-
## Deprecated keywords
The following keywords are deprecated.
@@ -4910,7 +4150,7 @@ Defining `image`, `services`, `cache`, `before_script`, and
`after_script` globally is deprecated. Support could be removed
from a future release.
-Use [`default:`](#custom-default-keyword-values) instead. For example:
+Use [`default:`](#default) instead. For example:
```yaml
default:
diff --git a/doc/ci/yaml/script.md b/doc/ci/yaml/script.md
index 626ede21fa5..c1b283ff10f 100644
--- a/doc/ci/yaml/script.md
+++ b/doc/ci/yaml/script.md
@@ -2,7 +2,6 @@
stage: Verify
group: Pipeline Authoring
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: reference
---
# GitLab CI/CD script syntax **(FREE)**
@@ -62,7 +61,7 @@ job:
## Set a default `before_script` or `after_script` for all jobs
You can use [`before_script`](index.md#before_script) and [`after_script`](index.md#after_script)
-with [`default`](index.md#custom-default-keyword-values):
+with [`default`](index.md#default):
- Use `before_script` with `default` to define a default array of commands that
should run before the `script` commands in all jobs.
diff --git a/doc/ci/yaml/workflow.md b/doc/ci/yaml/workflow.md
new file mode 100644
index 00000000000..67ca1150553
--- /dev/null
+++ b/doc/ci/yaml/workflow.md
@@ -0,0 +1,150 @@
+---
+stage: Verify
+group: Pipeline Authoring
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# GitLab CI/CD `workflow` keyword
+
+Use the [`workflow`](index.md#workflow) keyword to control when pipelines are created.
+
+The `workflow` keyword is evaluated before jobs. For example, if a job is configured to run
+for tags, but the workflow prevents tag pipelines, the job never runs.
+
+## Common `if` clauses for `workflow:rules`
+
+Some example `if` clauses for `workflow: rules`:
+
+| Example rules | Details |
+|------------------------------------------------------|-----------------------------------------------------------|
+| `if: '$CI_PIPELINE_SOURCE == "merge_request_event"'` | Control when merge request pipelines run. |
+| `if: '$CI_PIPELINE_SOURCE == "push"'` | Control when both branch pipelines and tag pipelines run. |
+| `if: $CI_COMMIT_TAG` | Control when tag pipelines run. |
+| `if: $CI_COMMIT_BRANCH` | Control when branch pipelines run. |
+
+See the [common `if` clauses for `rules`](../jobs/job_control.md#common-if-clauses-for-rules) for more examples.
+
+## `workflow: rules` examples
+
+In the following example:
+
+- Pipelines run for all `push` events (changes to branches and new tags).
+- Pipelines for push events with `-draft` in the commit message don't run, because
+ they are set to `when: never`.
+- Pipelines for schedules or merge requests don't run either, because no rules evaluate to true for them.
+
+```yaml
+workflow:
+ rules:
+ - if: $CI_COMMIT_MESSAGE =~ /-draft$/
+ when: never
+ - if: '$CI_PIPELINE_SOURCE == "push"'
+```
+
+This example has strict rules, and pipelines do **not** run in any other case.
+
+Alternatively, all of the rules can be `when: never`, with a final
+`when: always` rule. Pipelines that match the `when: never` rules do not run.
+All other pipeline types run. For example:
+
+```yaml
+workflow:
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ when: never
+ - if: '$CI_PIPELINE_SOURCE == "push"'
+ when: never
+ - when: always
+```
+
+This example prevents pipelines for schedules or `push` (branches and tags) pipelines.
+The final `when: always` rule runs all other pipeline types, **including** merge
+request pipelines.
+
+## Switch between branch pipelines and merge request pipelines
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/201845) in GitLab 13.8.
+
+To make the pipeline switch from branch pipelines to merge request pipelines after
+a merge request is created, add a `workflow: rules` section to your `.gitlab-ci.yml` file.
+
+If you use both pipeline types at the same time, [duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines)
+might run at the same time. To prevent duplicate pipelines, use the
+[`CI_OPEN_MERGE_REQUESTS` variable](../variables/predefined_variables.md).
+
+The following example is for a project that runs branch and merge request pipelines only,
+but does not run pipelines for any other case. It runs:
+
+- Branch pipelines when a merge request is not open for the branch.
+- Merge request pipelines when a merge request is open for the branch.
+
+```yaml
+workflow:
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+ - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
+ when: never
+ - if: '$CI_COMMIT_BRANCH'
+```
+
+If the pipeline is triggered by:
+
+- A merge request, run a merge request pipeline. For example, a merge request pipeline
+ can be triggered by a push to a branch with an associated open merge request.
+- A change to a branch, but a merge request is open for that branch, do not run a branch pipeline.
+- A change to a branch, but without any open merge requests, run a branch pipeline.
+
+You can also add a rule to an existing `workflow` section to switch from branch pipelines
+to merge request pipelines when a merge request is created.
+
+Add this rule to the top of the `workflow` section, followed by the other rules that
+were already present:
+
+```yaml
+workflow:
+ rules:
+ - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
+ when: never
+ - ... # Previously defined workflow rules here
+```
+
+[Triggered pipelines](../triggers/index.md) that run on a branch have a `$CI_COMMIT_BRANCH`
+set and could be blocked by a similar rule. Triggered pipelines have a pipeline source
+of `trigger` or `pipeline`, so `&& $CI_PIPELINE_SOURCE == "push"` ensures the rule
+does not block triggered pipelines.
+
+## `workflow:rules` templates
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217732) in GitLab 13.0.
+
+GitLab provides templates that set up `workflow: rules`
+for common scenarios. These templates help prevent duplicate pipelines.
+
+The [`Branch-Pipelines` template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Workflows/Branch-Pipelines.gitlab-ci.yml)
+makes your pipelines run for branches and tags.
+
+Branch pipeline status is displayed in merge requests that use the branch
+as a source. However, this pipeline type does not support any features offered by
+[merge request pipelines](../pipelines/merge_request_pipelines.md), like
+[pipelines for merged results](../pipelines/pipelines_for_merged_results.md)
+or [merge trains](../pipelines/merge_trains.md).
+This template intentionally avoids those features.
+
+To [include](index.md#include) it:
+
+```yaml
+include:
+ - template: 'Workflows/Branch-Pipelines.gitlab-ci.yml'
+```
+
+The [`MergeRequest-Pipelines` template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Workflows/MergeRequest-Pipelines.gitlab-ci.yml)
+makes your pipelines run for the default branch, tags, and
+all types of merge request pipelines. Use this template if you use any of the
+the [pipelines for merge requests features](../pipelines/merge_request_pipelines.md).
+
+To [include](index.md#include) it:
+
+```yaml
+include:
+ - template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml'
+```
diff --git a/doc/ci/yaml/yaml_optimization.md b/doc/ci/yaml/yaml_optimization.md
new file mode 100644
index 00000000000..503ba9bbd80
--- /dev/null
+++ b/doc/ci/yaml/yaml_optimization.md
@@ -0,0 +1,454 @@
+---
+stage: Verify
+group: Pipeline Authoring
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference
+---
+
+# Optimize GitLab CI/CD configuration files **(FREE)**
+
+You can reduce complexity and duplicated configuration in your GitLab CI/CD configuration
+files by using:
+
+- YAML-specific features like [anchors (`&`)](#anchors), aliases (`*`), and map merging (`<<`).
+ Read more about the various [YAML features](https://learnxinyminutes.com/docs/yaml/).
+- The [`extends` keyword](#use-extends-to-reuse-configuration-sections),
+ which is more flexible and readable. We recommend you use `extends` where possible.
+
+## Anchors
+
+YAML has a feature called 'anchors' that you can use to duplicate
+content across your document.
+
+Use anchors to duplicate or inherit properties. Use anchors with [hidden jobs](../jobs/index.md#hide-jobs)
+to provide templates for your jobs. When there are duplicate keys, GitLab
+performs a reverse deep merge based on the keys.
+
+You can use YAML anchors to merge YAML arrays.
+
+You can't use YAML anchors across multiple files when using the [`include`](index.md#include)
+keyword. Anchors are only valid in the file they were defined in. To reuse configuration
+from different YAML files, use [`!reference` tags](#reference-tags) or the
+[`extends` keyword](#use-extends-to-reuse-configuration-sections).
+
+The following example uses anchors and map merging. It creates two jobs,
+`test1` and `test2`, that inherit the `.job_template` configuration, each
+with their own custom `script` defined:
+
+```yaml
+.job_template: &job_configuration # Hidden yaml configuration that defines an anchor named 'job_configuration'
+ image: ruby:2.6
+ services:
+ - postgres
+ - redis
+
+test1:
+ <<: *job_configuration # Merge the contents of the 'job_configuration' alias
+ script:
+ - test1 project
+
+test2:
+ <<: *job_configuration # Merge the contents of the 'job_configuration' alias
+ script:
+ - test2 project
+```
+
+`&` sets up the name of the anchor (`job_configuration`), `<<` means "merge the
+given hash into the current one," and `*` includes the named anchor
+(`job_configuration` again). The expanded version of this example is:
+
+```yaml
+.job_template:
+ image: ruby:2.6
+ services:
+ - postgres
+ - redis
+
+test1:
+ image: ruby:2.6
+ services:
+ - postgres
+ - redis
+ script:
+ - test1 project
+
+test2:
+ image: ruby:2.6
+ services:
+ - postgres
+ - redis
+ script:
+ - test2 project
+```
+
+You can use anchors to define two sets of services. For example, `test:postgres`
+and `test:mysql` share the `script` defined in `.job_template`, but use different
+`services`, defined in `.postgres_services` and `.mysql_services`:
+
+```yaml
+.job_template: &job_configuration
+ script:
+ - test project
+ tags:
+ - dev
+
+.postgres_services:
+ services: &postgres_configuration
+ - postgres
+ - ruby
+
+.mysql_services:
+ services: &mysql_configuration
+ - mysql
+ - ruby
+
+test:postgres:
+ <<: *job_configuration
+ services: *postgres_configuration
+ tags:
+ - postgres
+
+test:mysql:
+ <<: *job_configuration
+ services: *mysql_configuration
+```
+
+The expanded version is:
+
+```yaml
+.job_template:
+ script:
+ - test project
+ tags:
+ - dev
+
+.postgres_services:
+ services:
+ - postgres
+ - ruby
+
+.mysql_services:
+ services:
+ - mysql
+ - ruby
+
+test:postgres:
+ script:
+ - test project
+ services:
+ - postgres
+ - ruby
+ tags:
+ - postgres
+
+test:mysql:
+ script:
+ - test project
+ services:
+ - mysql
+ - ruby
+ tags:
+ - dev
+```
+
+You can see that the hidden jobs are conveniently used as templates, and
+`tags: [postgres]` overwrites `tags: [dev]`.
+
+### YAML anchors for scripts
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23005) in GitLab 12.5.
+
+You can use [YAML anchors](#anchors) with [script](index.md#script), [`before_script`](index.md#before_script),
+and [`after_script`](index.md#after_script) to use predefined commands in multiple jobs:
+
+```yaml
+.some-script-before: &some-script-before
+ - echo "Execute this script first"
+
+.some-script: &some-script
+ - echo "Execute this script second"
+ - echo "Execute this script too"
+
+.some-script-after: &some-script-after
+ - echo "Execute this script last"
+
+job1:
+ before_script:
+ - *some-script-before
+ script:
+ - *some-script
+ - echo "Execute something, for this job only"
+ after_script:
+ - *some-script-after
+
+job2:
+ script:
+ - *some-script-before
+ - *some-script
+ - echo "Execute something else, for this job only"
+ - *some-script-after
+```
+
+### YAML anchors for variables
+
+Use [YAML anchors](#anchors) with `variables` to repeat assignment
+of variables across multiple jobs. You can also use YAML anchors when a job
+requires a specific `variables` block that would otherwise override the global variables.
+
+The following example shows how override the `GIT_STRATEGY` variable without affecting
+the use of the `SAMPLE_VARIABLE` variable:
+
+```yaml
+# global variables
+variables: &global-variables
+ SAMPLE_VARIABLE: sample_variable_value
+ ANOTHER_SAMPLE_VARIABLE: another_sample_variable_value
+
+# a job that must set the GIT_STRATEGY variable, yet depend on global variables
+job_no_git_strategy:
+ stage: cleanup
+ variables:
+ <<: *global-variables
+ GIT_STRATEGY: none
+ script: echo $SAMPLE_VARIABLE
+```
+
+## Use `extends` to reuse configuration sections
+
+You can use the [`extends` keyword](index.md#extends) to reuse configuration in
+multiple jobs. It is similar to [YAML anchors](#anchors), but simpler and you can
+[use `extends` with `includes`](#use-extends-and-include-together).
+
+`extends` supports multi-level inheritance. You should avoid using more than three levels,
+but you can use as many as eleven. The following example has two levels of inheritance:
+
+```yaml
+.tests:
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "push"
+
+.rspec:
+ extends: .tests
+ script: rake rspec
+
+rspec 1:
+ variables:
+ RSPEC_SUITE: '1'
+ extends: .rspec
+
+rspec 2:
+ variables:
+ RSPEC_SUITE: '2'
+ extends: .rspec
+
+spinach:
+ extends: .tests
+ script: rake spinach
+```
+
+### Exclude a key from `extends`
+
+To exclude a key from the extended content, you must assign it to `null`, for example:
+
+```yaml
+.base:
+ script: test
+ variables:
+ VAR1: base var 1
+
+test1:
+ extends: .base
+ variables:
+ VAR1: test1 var 1
+ VAR2: test2 var 2
+
+test2:
+ extends: .base
+ variables:
+ VAR2: test2 var 2
+
+test3:
+ extends: .base
+ variables: {}
+
+test4:
+ extends: .base
+ variables: null
+```
+
+Merged configuration:
+
+```yaml
+test1:
+ script: test
+ variables:
+ VAR1: test1 var 1
+ VAR2: test2 var 2
+
+test2:
+ script: test
+ variables:
+ VAR1: base var 1
+ VAR2: test2 var 2
+
+test3:
+ script: test
+ variables:
+ VAR1: base var 1
+
+test4:
+ script: test
+ variables: null
+```
+
+### Use `extends` and `include` together
+
+To reuse configuration from different configuration files,
+combine `extends` and [`include`](index.md#include).
+
+In the following example, a `script` is defined in the `included.yml` file.
+Then, in the `.gitlab-ci.yml` file, `extends` refers
+to the contents of the `script`:
+
+- `included.yml`:
+
+ ```yaml
+ .template:
+ script:
+ - echo Hello!
+ ```
+
+- `.gitlab-ci.yml`:
+
+ ```yaml
+ include: included.yml
+
+ useTemplate:
+ image: alpine
+ extends: .template
+ ```
+
+### Merge details
+
+You can use `extends` to merge hashes but not arrays.
+The algorithm used for merge is "closest scope wins," so
+keys from the last member always override anything defined on other
+levels. For example:
+
+```yaml
+.only-important:
+ variables:
+ URL: "http://my-url.internal"
+ IMPORTANT_VAR: "the details"
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ - if: $CI_COMMIT_BRANCH == "stable"
+ tags:
+ - production
+ script:
+ - echo "Hello world!"
+
+.in-docker:
+ variables:
+ URL: "http://docker-url.internal"
+ tags:
+ - docker
+ image: alpine
+
+rspec:
+ variables:
+ GITLAB: "is-awesome"
+ extends:
+ - .only-important
+ - .in-docker
+ script:
+ - rake rspec
+```
+
+The result is this `rspec` job:
+
+```yaml
+rspec:
+ variables:
+ URL: "http://docker-url.internal"
+ IMPORTANT_VAR: "the details"
+ GITLAB: "is-awesome"
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ - if: $CI_COMMIT_BRANCH == "stable"
+ tags:
+ - docker
+ image: alpine
+ script:
+ - rake rspec
+```
+
+In this example:
+
+- The `variables` sections merge, but `URL: "http://docker-url.internal"` overwrites `URL: "http://my-url.internal"`.
+- `tags: ['docker']` overwrites `tags: ['production']`.
+- `script` does not merge, but `script: ['rake rspec']` overwrites
+ `script: ['echo "Hello world!"']`. You can use [YAML anchors](yaml_optimization.md#anchors) to merge arrays.
+
+## `!reference` tags
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/266173) in GitLab 13.9.
+> - `rules` keyword support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322992) in GitLab 14.3.
+
+Use the `!reference` custom YAML tag to select keyword configuration from other job
+sections and reuse it in the current section. Unlike [YAML anchors](#anchors), you can
+use `!reference` tags to reuse configuration from [included](index.md#include) configuration
+files as well.
+
+In the following example, a `script` and an `after_script` from two different locations are
+reused in the `test` job:
+
+- `setup.yml`:
+
+ ```yaml
+ .setup:
+ script:
+ - echo creating environment
+ ```
+
+- `.gitlab-ci.yml`:
+
+ ```yaml
+ include:
+ - local: setup.yml
+
+ .teardown:
+ after_script:
+ - echo deleting environment
+
+ test:
+ script:
+ - !reference [.setup, script]
+ - echo running my own command
+ after_script:
+ - !reference [.teardown, after_script]
+ ```
+
+In the following example, `test-vars-1` reuses all the variables in `.vars`, while `test-vars-2`
+selects a specific variable and reuses it as a new `MY_VAR` variable.
+
+```yaml
+.vars:
+ variables:
+ URL: "http://my-url.internal"
+ IMPORTANT_VAR: "the details"
+
+test-vars-1:
+ variables: !reference [.vars, variables]
+ script:
+ - printenv
+
+test-vars-2:
+ variables:
+ MY_VAR: !reference [.vars, variables, IMPORTANT_VAR]
+ script:
+ - printenv
+```
+
+You can't reuse a section that already includes a `!reference` tag. Only one level
+of nesting is supported.
diff --git a/doc/development/adding_database_indexes.md b/doc/development/adding_database_indexes.md
index 9ca08ab1dc2..571d2f353d4 100644
--- a/doc/development/adding_database_indexes.md
+++ b/doc/development/adding_database_indexes.md
@@ -312,3 +312,16 @@ def down
remove_concurrent_index_by_name :ci_builds, INDEX_NAME
end
```
+
+## Test database index changes locally
+
+You must test the database index changes locally before creating a merge request.
+
+### Verify indexes created asynchronously
+
+Use the asynchronous index helpers on your local environment to test changes for creating an index:
+
+1. Enable the feature flags by running `Feature.enable(:database_async_index_creation)` and `Feature.enable(:database_reindexing)` in the Rails console.
+1. Run `bundle exec rails db:migrate` so that it creates an entry in the `postgres_async_indexes` table.
+1. Run `bundle exec rails gitlab:db:reindex` so that the index is created asynchronously.
+1. To verify the index, open the PostgreSQL console using the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md) command `gdk psql` and run the command `\d <index_name>` to check that your newly created index exists.
diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md
index 73814399d2e..df2f3c337cd 100644
--- a/doc/development/api_styleguide.md
+++ b/doc/development/api_styleguide.md
@@ -240,7 +240,7 @@ it's own file in the [`validators`](https://gitlab.com/gitlab-org/gitlab/-/blob/
## Internal API
-The [internal API](internal_api.md) is documented for internal use. Please keep it up to date so we know what endpoints
+The [internal API](internal_api/index.md) is documented for internal use. Please keep it up to date so we know what endpoints
different components are making use of.
## Avoiding N+1 problems
diff --git a/doc/development/application_slis/index.md b/doc/development/application_slis/index.md
index c1d7ac9fa0c..5bc6fffdb48 100644
--- a/doc/development/application_slis/index.md
+++ b/doc/development/application_slis/index.md
@@ -43,7 +43,7 @@ example:
```ruby
Gitlab::Metrics::Sli.initialize_sli(:received_email, [
{
- feature_category: :issue_tracking,
+ feature_category: :team_planning,
email_type: :create_issue
},
{
@@ -110,21 +110,79 @@ will also be incremented:
gitlab_sli:received_email:success_total{ feature_category='service_desk', email_type='service_desk' }
```
+So far, only tracking `apdex` using a success rate is supported. If you
+need to track errors this way, please upvote
+[this issue](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1395)
+and leave a comment so we can prioritize this.
+
## Using the SLI in service monitoring and alerts
-When the application is emitting metrics for the new SLI, those need
-to be consumed in the service catalog to result in alerts, and be
-included in the error budget for stage groups and GitLab.com's overall
-availability.
+When the application is emitting metrics for a new SLI, they need
+to be consumed from the [metrics catalog](https://gitlab.com/gitlab-com/runbooks/-/tree/master/metrics-catalog)
+to result in alerts, and included in the error budget for stage
+groups and GitLab.com's overall availability.
+
+Start by adding the new SLI to the
+[Application-SLI library](https://gitlab.com/gitlab-com/runbooks/-/blob/d109886dfd5170793eeb8de3d69aafd4a9da78f6/metrics-catalog/gitlab-slis/library.libsonnet#L4).
+After that, add the following information:
+
+- `name`: the name of the SLI as defined in code. For example
+ `received_email`.
+- `significantLabels`: an array of Prometheus labels that belong to the
+ metrics. For example: `["email_type"]`. If the significant labels
+ for the SLI include `feature_category`, the metrics will also
+ feed into the
+ [error budgets for stage groups](../stage_group_dashboards.md#error-budget).
+- `featureCategory`: if the SLI applies to a single feature category,
+ you can specify it statically through this field to feed the SLI
+ into the error budgets for stage groups.
+- `description`: a Markdown string explaining the SLI. It will
+ be shown on dashboards and alerts.
+- `kind`: the kind of indicator. Only `sliDefinition.apdexKind` is supported at the moment.
+ Reach out in
+ [this issue](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1395)
+ if you want to implement an SLI for success or error rates.
+
+When done, run `make generate` to generate recording rules for
+the new SLI. This command creates recordings for all services
+emitting these metrics aggregated over `significantLabels`.
+
+Open up a merge request with these changes and request review from a Scalability
+team member.
+
+When these changes are merged, and the aggregations in
+[Thanos](https://thanos.gitlab.net) recorded, query Thanos to see
+the success ratio of the new aggregated metrics. For example:
+
+```prometheus
+sum by (environment, stage, type)(gitlab_sli_aggregation:rails_request_apdex:apdex:success:rate_1h)
+/
+sum by (environment, stage, type)(gitlab_sli_aggregation:rails_request_apdex:apdex:weight:rate_1h)
+```
+
+This shows the success ratio, which can guide you to set an
+appropriate SLO when adding this SLI to a service.
+
+Then, add the SLI to the appropriate service
+catalog file. For example, the [`web` service](https://gitlab.com/gitlab-com/runbooks/-/blob/2b7be37a006c236bd684a4e6a1fbf4c66158292a/metrics-catalog/services/web.jsonnet#L198):
+
+```jsonnet
+rails_requests:
+ sliLibrary.get('rails_request_apdex')
+ .generateServiceLevelIndicator({ job: 'gitlab-rails' })
+```
+
+To pass extra selectors and override properties of the SLI, see the
+[service monitoring documentation](https://gitlab.com/gitlab-com/runbooks/blob/master/metrics-catalog/README.md).
-This is currently being worked on in [this
-project](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/573). As
-part of [this
-issue](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1307)
-we will update the documentation.
+SLIs with statically defined feature categories can already receive
+alerts about the SLI in specified Slack channels. For more information, read the
+[alert routing documentation](https://gitlab.com/gitlab-com/runbooks/-/blob/master/docs/uncategorized/alert-routing.md).
+In [this project](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/614)
+we are extending this so alerts for SLIs with a `feature_category`
+label in the souce metrics can also be routed.
-For any question, please don't hesitate to createan issue in [the
-Scalability issue
-tracker](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues)
+For any question, please don't hesitate to create an issue in
+[the Scalability issue tracker](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues)
or come find us in
[#g_scalability](https://gitlab.slack.com/archives/CMMF8TKR9) on Slack.
diff --git a/doc/development/application_slis/rails_request_apdex.md b/doc/development/application_slis/rails_request_apdex.md
index e1ab5368578..b31c7d8756b 100644
--- a/doc/development/application_slis/rails_request_apdex.md
+++ b/doc/development/application_slis/rails_request_apdex.md
@@ -4,184 +4,171 @@ group: Scalability
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Rails request apdex SLI
+# Rails request Apdex SLI
> [Introduced](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/525) in GitLab 14.4
NOTE:
-This SLI is not yet used in [error budgets for stage
-groups](../stage_group_dashboards.md#error-budget) or service
-monitoring. This is being worked on in [this
-project](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/573).
+This SLI is used for service monitoring. But not for [error budgets for stage groups](../stage_group_dashboards.md#error-budget)
+by default. You can [opt in](#error-budget-attribution-and-ownership).
-The request apdex SLI is [an SLI defined in the application](index.md)
-that measures the duration of successful requests as an indicator for
+The request Apdex SLI (Service Level Indicator) is [an SLI defined in the application](index.md).
+It measures the duration of successful requests as an indicator for
application performance. This includes the REST and GraphQL API, and the
regular controller endpoints. It consists of these counters:
1. `gitlab_sli:rails_request_apdex:total`: This counter gets
incremented for every request that did not result in a response
- with a 5xx status code. This means that slow failures don't get
- counted twice: The request is already counted in the error-SLI.
+ with a `5xx` status code. It ensures slow failures are not
+ counted twice, because the request is already counted in the error SLI.
1. `gitlab_sli:rails_request_apdex:success_total`: This counter gets
incremented for every successful request that performed faster than
- the [defined target duration depending on the endpoint's
- urgency](#adjusting-request-urgency).
+ the [defined target duration depending on the endpoint's urgency](#adjusting-request-urgency).
Both these counters are labeled with:
1. `endpoint_id`: The identification of the Rails Controller or the
- Grape-API endpoint
+ Grape-API endpoint.
1. `feature_category`: The feature category specified for that
controller or API endpoint.
## Request Apdex SLO
-These counters can be combined into a success ratio, the objective for
-this ratio is defined in the service catalog per service:
+These counters can be combined into a success ratio. The objective for
+this ratio is defined in the service catalog per service. For this SLI to meet SLO,
+the ratio recorded must be higher than:
-1. [Web: 0.998](https://gitlab.com/gitlab-com/runbooks/blob/master/metrics-catalog/services/web.jsonnet#L19)
-1. [API: 0.995](https://gitlab.com/gitlab-com/runbooks/blob/master/metrics-catalog/services/api.jsonnet#L19)
-1. [Git: 0.998](https://gitlab.com/gitlab-com/runbooks/blob/master/metrics-catalog/services/git.jsonnet#L22)
-
-This means that for this SLI to meet SLO, the ratio recorded needs to
-be higher than those defined above.
+- [Web: 0.998](https://gitlab.com/gitlab-com/runbooks/blob/master/metrics-catalog/services/web.jsonnet#L19)
+- [API: 0.995](https://gitlab.com/gitlab-com/runbooks/blob/master/metrics-catalog/services/api.jsonnet#L19)
+- [Git: 0.998](https://gitlab.com/gitlab-com/runbooks/blob/master/metrics-catalog/services/git.jsonnet#L22)
For example: for the web-service, we want at least 99.8% of requests
to be faster than their target duration.
-These are the targets we use for alerting and service montoring. So
-durations should be set keeping those into account. So we would not
-cause alerts. But the goal would be to set the urgency to a target
-that users would be satisfied with.
+We use these targets for alerting and service monitoring. Set durations taking
+these targets into account, so we don't cause alerts. The goal, however, is to
+set the urgency to a target that satisfies our users.
-Both successful measurements and unsuccessful ones have an impact on the
+Both successful measurements and unsuccessful ones affect the
error budget for stage groups.
## Adjusting request urgency
Not all endpoints perform the same type of work, so it is possible to
-define different urgencies for different endpoints. An endpoint with a
-lower urgency can have a longer request duration than endpoints that
-are high urgency.
-
-Long-running requests are more expensive for our
-infrastructure: while one request is being served, the thread remains
-occupied for the duration of that request. So nothing else can be handled by that
-thread. Because of Ruby's Global VM Lock, the thread might keep the
+define different urgency levels for different endpoints. An endpoint with a
+lower urgency can have a longer request duration than endpoints with high urgency.
+
+Long-running requests are more expensive for our infrastructure. While serving
+one request, the thread remains occupied for the duration of that request. The thread
+can handle nothing else. Due to Ruby's Global VM Lock, the thread might keep the
lock and stall other requests handled by the same Puma worker
-process. The request is in fact a noisy neighbor for other requests
-handled by the worker. This is why the upper bound for a target
-duration is capped at 5 seconds.
+process. The request is, in fact, a noisy neighbor for other requests
+handled by the worker. We cap the upper bound for a target duration at 5 seconds
+for this reason.
## Decreasing the urgency (setting a higher target duration)
-Increasing the urgency on an existing endpoint can be done on
-a case-by-case basis. Please take the following into account:
+You can decrease the urgency on an existing endpoint on
+a case-by-case basis. Take the following into account:
-1. Apdex is about perceived performance, if a user is actively waiting
+1. Apdex is about perceived performance. If a user is actively waiting
for the result of a request, waiting 5 seconds might not be
- acceptable. While if the endpoint is used by an automation
- requiring a lot of data, 5 seconds could be okay.
+ acceptable. However, if the endpoint is used by an automation
+ requiring a lot of data, 5 seconds could be acceptable.
A product manager can help to identify how an endpoint is used.
1. The workload for some endpoints can sometimes differ greatly
depending on the parameters specified by the caller. The urgency
- needs to accomodate that. In some cases, it might be interesting to
+ needs to accommodate those differences. In some cases, you could
define a separate [application SLI](index.md#defining-a-new-sli)
for what the endpoint is doing.
When the endpoints in certain cases turn into no-ops, making them
very fast, we should ignore these fast requests when setting the
target. For example, if the `MergeRequests::DraftsController` is
- hit for every merge request being viewed, but doesn't need to
- render anything in most cases, then we should pick the target that
- would still accomodate the endpoint performing work.
+ hit for every merge request being viewed, but rarely renders
+ anything, then we should pick the target that
+ would still accommodate the endpoint performing work.
1. Consider the dependent resources consumed by the endpoint. If the endpoint
- loads a lot of data from Gitaly or the database and this is causing
- it to not perform satisfactory. It could be better to optimize the
+ loads a lot of data from Gitaly or the database, and this causes
+ unsatisfactory performance, consider optimizing the
way the data is loaded rather than increasing the target duration
by lowering the urgency.
- In cases like this, it might be appropriate to temporarily decrease
+ In these cases, it might be appropriate to temporarily decrease
urgency to make the endpoint meet SLO, if this is bearable for the
- infrastructure. In such cases, please link an issue from a code
- comment.
+ infrastructure. In such cases, create a code comment linking to an issue.
If the endpoint consumes a lot of CPU time, we should also consider
this: these kinds of requests are the kind of noisy neighbors we
should try to keep as short as possible.
-1. Traffic characteristics should also be taken into account: if the
- trafic to the endpoint is bursty, like CI traffic spinning up a
+1. Traffic characteristics should also be taken into account. If the
+ traffic to the endpoint is bursty, like CI traffic spinning up a
big batch of jobs hitting the same endpoint, then having these
- endpoints take 5s is not acceptable from an infrastructure point of
- view. We cannot scale up the fleet fast enough to accomodate for
+ endpoints take five seconds is unacceptable from an infrastructure point of
+ view. We cannot scale up the fleet fast enough to accommodate for
the incoming slow requests alongside the regular traffic.
When lowering the urgency for an existing endpoint, please involve a
[Scalability team member](https://about.gitlab.com/handbook/engineering/infrastructure/team/scalability/#team-members)
in the review. We can use request rates and durations available in the
-logs to come up with a recommendation. Picking a threshold can be done
-using the same process as for [increasing
-urgency](#increasing-urgency-setting-a-lower-target-duration), picking
-a duration that is higher than the SLO for the service.
+logs to come up with a recommendation. You can pick a threshold
+using the same process as for
+[increasing urgency](#increasing-urgency-setting-a-lower-target-duration),
+picking a duration that is higher than the SLO for the service.
We shouldn't set the longest durations on endpoints in the merge
-requests that introduces them, since we don't yet have data to support
+requests that introduces them, because we don't yet have data to support
the decision.
## Increasing urgency (setting a lower target duration)
-When decreasing the target duration, we need to make sure the endpoint
+When increasing the urgency, we must make sure the endpoint
still meets SLO for the fleet that handles the request. You can use the
-information in the logs to determine this:
+information in the logs to check:
-1. Open [this table in
- Kibana](https://log.gprd.gitlab.net/goto/bbb6465c68eb83642269e64a467df3df)
+1. Open [this table in Kibana](https://log.gprd.gitlab.net/goto/bbb6465c68eb83642269e64a467df3df)
1. The table loads information for the busiest endpoints by
- default. You can speed things up by adding a filter for
- `json.caller_id.keyword` and adding the identifier you're intersted
- in (for example: `Projects::RawController#show`).
+ default. To speed the response, add both:
+ - A filter for `json.caller_id.keyword`.
+ - The identifier you're interested in, such as `Projects::RawController#show`.
1. Check the [appropriate percentile duration](#request-apdex-slo) for
- the service the endpoint is handled by. The overall duration should
- be lower than the target you intend to set.
+ the service handling the endpoint. The overall duration should
+ be lower than your intended target.
-1. If the overall duration is below the intended targed. Please also
- check the peaks over time in [this
- graph](https://log.gprd.gitlab.net/goto/9319c4a402461d204d13f3a4924a89fc)
+1. If the overall duration is below the intended target, check the peaks over time
+ in [this graph](https://log.gprd.gitlab.net/goto/9319c4a402461d204d13f3a4924a89fc)
in Kibana. Here, the percentile in question should not peak above
the target duration we want to set.
-Since decreasing a threshold too much could result in alerts for the
-apdex degradation, please also involve a Scalability team member in
-the merge reqeust.
+As decreasing a threshold too much could result in alerts for the
+Apdex degradation, please also involve a Scalability team member in
+the merge request.
## How to adjust the urgency
-The urgency can be specified similar to how endpoints [get a feature
-category](../feature_categorization/index.md).
-
-For endpoints that don't have a specific target, the default urgency (1s duration) will be used.
+You can specify urgency similar to how endpoints
+[get a feature category](../feature_categorization/index.md). Endpoints without a
+specific target use the default urgency: 1s duration. These configurations
+are available:
-The following configurations are available:
-
-| Urgency | Duration in seconds | Notes |
-|----------|---------------------|-----------------------------------------------|
-| :high | 0.25s | |
-| :medium | 0.5s | |
-| :default | 1s | This is the default when nothing is specified |
-| :low | 5s | |
+| Urgency | Duration in seconds | Notes |
+|------------|---------------------|-----------------------------------------------|
+| `:high` | 0.25s | |
+| `:medium` | 0.5s | |
+| `:default` | 1s | The default when nothing is specified. |
+| `:low` | 5s | |
### Rails controller
-An urgency can be specified for all actions in a controller like this:
+An urgency can be specified for all actions in a controller:
```ruby
class Boards::ListsController < ApplicationController
@@ -189,8 +176,7 @@ class Boards::ListsController < ApplicationController
end
```
-To specify the urgency also for certain actions in a controller, they
-can be specified like this:
+To also specify the urgency for certain actions in a controller:
```ruby
class Boards::ListsController < ApplicationController
@@ -200,8 +186,7 @@ end
### Grape endpoints
-To specify the urgency for an entire API class, this can be done as
-follows:
+To specify the urgency for an entire API class:
```ruby
module API
@@ -211,8 +196,7 @@ module API
end
```
-To specify the urgency also for certain actions in a API class, they
-can be specified like this:
+To specify the urgency also for certain actions in a API class:
```ruby
module API
@@ -232,3 +216,33 @@ get 'client/features', urgency: :low do
# endpoint logic
end
```
+
+### Error budget attribution and ownership
+
+This SLI is used for service level monitoring. It feeds into the
+[error budget for stage
+groups](../stage_group_dashboards.md#error-budget). For this
+particular SLI, we have opted everyone out by default to give time to
+set the correct urgencies on endpoints before it affects a group's
+error budget.
+
+To include this SLI in the error budget, remove the `rails_requests`
+from the `ignored_components` array in the entry for your group. Read
+more about what is configurable in the
+[runbooks documentation](https://gitlab.com/gitlab-com/runbooks/-/tree/master/services#teamsyml).
+
+For more information, read the epic for
+[defining custom SLIs and incorporating them into error budgets](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/525)).
+The endpoints for the SLI feed into a group's error budget based on the
+[feature category declared on it](../feature_categorization/index.md).
+
+To know which endpoints are included for your group, you can see the
+request rates on the
+[group dashboard for your group](https://dashboards.gitlab.net/dashboards/f/stage-groups/stage-groups).
+In the **Budget Attribution** row, the **Puma Apdex** log link shows you
+how many requests are not meeting a 1s or 5s target.
+
+Learn more about the content of the dashboard in the documentation for
+[Dashboards for stage groups](../stage_group_dashboards.md). For more information
+on our exploration of the error budget itself, read the infrastructure issue
+[Stage group error budget exploration dashboard](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1365).
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index 9accd4a3595..38d0d5d7843 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -348,7 +348,6 @@ Component statuses are linked to configuration documentation for each component.
| [Gitaly](#gitaly) | Git RPC service for handling all Git calls made by GitLab | ✅ | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE |
| [GitLab Exporter](#gitlab-exporter) | Generates a variety of GitLab metrics | ✅ | ✅ | ✅ | ✅ | ✅ | ⌠| ⌠| CE & EE |
| [GitLab Geo Node](#gitlab-geo) | Geographically distributed GitLab nodes | ⚙ | ⚙ | ⌠| ⌠| ✅ | ⌠| ⚙ | EE Only |
-| [GitLab Kubernetes Agent](#gitlab-kubernetes-agent) | Integrate Kubernetes clusters in a cloud-native way | ⚙ | ⚙ | ⚙ | ⌠| ⌠| ⤓ | ⚙ | EE Only |
| [GitLab Pages](#gitlab-pages) | Hosts static websites | ⚙ | ⚙ | ⌠| ⌠| ✅ | ⚙ | ⚙ | CE & EE |
| [GitLab Kubernetes Agent](#gitlab-kubernetes-agent) | Integrate Kubernetes clusters in a cloud-native way | ⚙ | ⚙ | ⚙ | ⌠| ⌠| ⤓ | ⚙ | EE Only |
| [GitLab self-monitoring: Alertmanager](#alertmanager) | Deduplicates, groups, and routes alerts from Prometheus | ⚙ | ⚙ | ✅ | ⚙ | ✅ | ⌠| ⌠| CE & EE |
@@ -977,12 +976,12 @@ in Rails, scheduled to run whenever an SSH key is modified by a user.
instead of keys. In this case, `AuthorizedKeysCommand` is replaced with an
`AuthorizedPrincipalsCommand`. This extracts a username from the certificate
without using the Rails internal API, which is used instead of `key_id` in the
-[`/api/internal/allowed`](internal_api.md) call later.
+[`/api/internal/allowed`](internal_api/index.md) call later.
GitLab Shell also has a few operations that do not involve Gitaly, such as
resetting two-factor authentication codes. These are handled in the same way,
except there is no round-trip into Gitaly - Rails performs the action as part
-of the [internal API](internal_api.md) call, and GitLab Shell streams the
+of the [internal API](internal_api/index.md) call, and GitLab Shell streams the
response back to the user directly.
## System layout
diff --git a/doc/development/avoiding_downtime_in_migrations.md b/doc/development/avoiding_downtime_in_migrations.md
index 9418eafa487..a5fc1909551 100644
--- a/doc/development/avoiding_downtime_in_migrations.md
+++ b/doc/development/avoiding_downtime_in_migrations.md
@@ -377,7 +377,181 @@ ensures that no downtime is needed.
This operation does not require downtime.
-## Data Migrations
+## Migrating `integer` primary keys to `bigint`
+
+To [prevent the overflow risk](https://gitlab.com/groups/gitlab-org/-/epics/4785) for some tables
+with `integer` primary key (PK), we have to migrate their PK to `bigint`. The process to do this
+without downtime and causing too much load on the database is described below.
+
+### Initialize the conversion and start migrating existing data (release N)
+
+To start the process, add a regular migration to create the new `bigint` columns. Use the provided
+`initialize_conversion_of_integer_to_bigint` helper. The helper also creates a database trigger
+to keep in sync both columns for any new records ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/migrate/20210608072312_initialize_conversion_of_ci_stages_to_bigint.rb)):
+
+```ruby
+class InitializeConversionOfCiStagesToBigint < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :ci_stages
+ COLUMNS = %i(id)
+
+ def up
+ initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+
+ def down
+ revert_initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+end
+```
+
+Ignore the new `bigint` columns:
+
+```ruby
+module Ci
+ class Stage < Ci::ApplicationRecord
+ include IgnorableColumns
+ ignore_column :id_convert_to_bigint, remove_with: '14.2', remove_after: '2021-08-22'
+ end
+```
+
+To migrate existing data, we introduced new type of _batched background migrations_.
+Unlike the classic background migrations, built on top of Sidekiq, batched background migrations
+don't have to enqueue and schedule all the background jobs at the beginning.
+They also have other advantages, like automatic tuning of the batch size, better progress visibility,
+and collecting metrics. To start the process, use the provided `backfill_conversion_of_integer_to_bigint`
+helper ([example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/migrate/20210608072346_backfill_ci_stages_for_bigint_conversion.rb)):
+
+```ruby
+class BackfillCiStagesForBigintConversion < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :ci_stages
+ COLUMNS = %i(id)
+
+ def up
+ backfill_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+
+ def down
+ revert_backfill_conversion_of_integer_to_bigint(TABLE, COLUMNS)
+ end
+end
+```
+
+### Monitor the background migration
+
+Check how the migration is performing while it's running. Multiple ways to do this are described below.
+
+#### High-level status of batched background migrations
+
+See how to [check the status of batched background migrations](../update/index.md#checking-for-background-migrations-before-upgrading).
+
+#### Query the database
+
+We can query the related database tables directly. Requires access to read-only replica.
+Example queries:
+
+```sql
+-- Get details for batched background migration for given table
+SELECT * FROM batched_background_migrations WHERE table_name = 'namespaces'\gx
+
+-- Get count of batched background migration jobs by status for given table
+SELECT
+ batched_background_migrations.id, batched_background_migration_jobs.status, COUNT(*)
+FROM
+ batched_background_migrations
+ JOIN batched_background_migration_jobs ON batched_background_migrations.id = batched_background_migration_jobs.batched_background_migration_id
+WHERE
+ table_name = 'namespaces'
+GROUP BY
+ batched_background_migrations.id, batched_background_migration_jobs.status;
+
+-- Batched background migration progress for given table (based on estimated total number of tuples)
+SELECT
+ m.table_name,
+ LEAST(100 * sum(j.batch_size) / pg_class.reltuples, 100) AS percentage_complete
+FROM
+ batched_background_migrations m
+ JOIN batched_background_migration_jobs j ON j.batched_background_migration_id = m.id
+ JOIN pg_class ON pg_class.relname = m.table_name
+WHERE
+ j.status = 3 AND m.table_name = 'namespaces'
+GROUP BY m.id, pg_class.reltuples;
+```
+
+#### Sidekiq logs
+
+We can also use the Sidekiq logs to monitor the worker that executes the batched background
+migrations:
+
+1. Sign in to [Kibana](https://log.gprd.gitlab.net) with a `@gitlab.com` email address.
+1. Change the index pattern to `pubsub-sidekiq-inf-gprd*`.
+1. Add filter for `json.queue: cronjob:database_batched_background_migration`.
+
+#### PostgerSQL slow queries log
+
+Slow queries log keeps track of low queries that took above 1 second to execute. To see them
+for batched background migration:
+
+1. Sign in to [Kibana](https://log.gprd.gitlab.net) with a `@gitlab.com` email address.
+1. Change the index pattern to `pubsub-postgres-inf-gprd*`.
+1. Add filter for `json.endpoint_id.keyword: Database::BatchedBackgroundMigrationWorker`.
+1. Optional. To see only updates, add a filter for `json.command_tag.keyword: UPDATE`.
+1. Optional. To see only failed statements, add a filter for `json.error_severiry.keyword: ERROR`.
+1. Optional. Add a filter by table name.
+
+#### Grafana dashboards
+
+To monitor the health of the database, use these additional metrics:
+
+- [PostgreSQL Tuple Statistics](https://dashboards.gitlab.net/d/000000167/postgresql-tuple-statistics?orgId=1&refresh=1m): if you see high rate of updates for the tables being actively converted, or increasing percentage of dead tuples for this table, it might mean that autovacuum cannot keep up.
+- [PostgreSQL Overview](https://dashboards.gitlab.net/d/000000144/postgresql-overview?orgId=1): if you see high system usage or transactions per second (TPS) on the primary database server, it might mean that the migration is causing problems.
+
+### Prometheus metrics
+
+Number of [metrics](https://gitlab.com/gitlab-org/gitlab/-/blob/294a92484ce4611f660439aa48eee4dfec2230b5/lib/gitlab/database/background_migration/batched_migration_wrapper.rb#L90-128)
+for each batched background migration are published to Prometheus. These metrics can be searched for and
+visualized in Thanos ([see an example](https://thanos-query.ops.gitlab.net/graph?g0.expr=sum%20(rate(batched_migration_job_updated_tuples_total%7Benv%3D%22gprd%22%7D%5B5m%5D))%20by%20(migration_id)%20&g0.tab=0&g0.stacked=0&g0.range_input=3d&g0.max_source_resolution=0s&g0.deduplicate=1&g0.partial_response=0&g0.store_matches=%5B%5D&g0.end_input=2021-06-13%2012%3A18%3A24&g0.moment_input=2021-06-13%2012%3A18%3A24)).
+
+### Swap the columns (release N + 1)
+
+After the background is completed and the new `bigint` columns are populated for all records, we can
+swap the columns. Swapping is done with post-deployment migration. The exact process depends on the
+table being converted, but in general it's done in the following steps:
+
+1. Using the provided `ensure_batched_background_migration_is_finished` helper, make sure the batched
+migration has finished ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L13-18)).
+If the migration has not completed, the subsequent steps fail anyway. By checking in advance we
+aim to have more helpful error message.
+1. Create indexes using the `bigint` columns that match the existing indexes using the `integer`
+column ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L28-34)).
+1. Create foreign keys (FK) using the `bigint` columns that match the existing FKs using the
+`integer` column. Do this both for FK referencing other tables, and FKs that reference the table
+that is being migrated ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L36-43)).
+1. Inside a transaction, swap the columns:
+ 1. Lock the tables involved. To reduce the chance of hitting a deadlock, we recommended to do this in parent to child order ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L47)).
+ 1. Rename the columns to swap names ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L49-54))
+ 1. Reset the trigger function ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L56-57)).
+ 1. Swap the defaults ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L59-62)).
+ 1. Swap the PK constraint (if any) ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L64-68)).
+ 1. Remove old indexes and rename new ones ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L70-72)).
+ 1. Remove old FKs (if still present) and rename new ones ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L74)).
+
+See example [merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66088), and [migration](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb).
+
+### Remove the trigger and old `integer` columns (release N + 2)
+
+Using post-deployment migration and the provided `cleanup_conversion_of_integer_to_bigint` helper,
+drop the database trigger and the old `integer` columns ([see an example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69714)).
+
+### Remove ignore rules (release N + 3)
+
+In the next release after the columns were dropped, remove the ignore rules as we do not need them
+anymore ([see an example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71161)).
+
+## Data migrations
Data migrations can be tricky. The usual approach to migrate data is to take a 3
step approach:
diff --git a/doc/development/chaos_endpoints.md b/doc/development/chaos_endpoints.md
index b0de00648ba..838235fd795 100644
--- a/doc/development/chaos_endpoints.md
+++ b/doc/development/chaos_endpoints.md
@@ -37,7 +37,7 @@ For example, when using the [GDK](https://gitlab.com/gitlab-org/gitlab-developme
this can be done with the following command:
```shell
-GITLAB_CHAOS_SECRET=secret gdk run
+GITLAB_CHAOS_SECRET=secret gdk start
```
Replace `secret` with your own secret token.
diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md
index b74a1d0d58a..46442aa6106 100644
--- a/doc/development/cicd/templates.md
+++ b/doc/development/cicd/templates.md
@@ -60,7 +60,7 @@ don't have any other `.gitlab-ci.yml` files.
When authoring pipeline templates:
- Place any [global keywords](../../ci/yaml/index.md#global-keywords) like `image`
- or `before_script` in a [`default`](../../ci/yaml/index.md#custom-default-keyword-values)
+ or `before_script` in a [`default`](../../ci/yaml/index.md#default)
section at the top of the template.
- Note clearly in the [code comments](#explain-the-template-with-comments) if the
template is designed to be used with the `includes` keyword in an existing
@@ -77,7 +77,7 @@ other pipeline configuration.
When authoring job templates:
-- Do not use [global](../../ci/yaml/index.md#global-keywords) or [`default`](../../ci/yaml/index.md#custom-default-keyword-values)
+- Do not use [global](../../ci/yaml/index.md#global-keywords) or [`default`](../../ci/yaml/index.md#default)
keywords. When a root `.gitlab-ci.yml` includes a template, global or default keywords
might be overridden and cause unexpected behavior. If a job template requires a
specific stage, explain in the code comments that users must manually add the stage
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 89516c2168b..7e797309a26 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -152,7 +152,7 @@ See the [test engineering process](https://about.gitlab.com/handbook/engineering
1. For the code that this change impacts, I believe that the automated tests ([Testing Guide](testing_guide/index.md)) validate functionality that is highly important to users (including consideration of [all test levels](testing_guide/testing_levels.md)).
1. If the existing automated tests do not cover the above functionality, I have added the necessary additional tests or added an issue to describe the automation testing gap and linked it to this MR.
1. I have considered the technical aspects of this change's impact on GitLab.com hosted customers and self-managed customers.
-1. I have considered the impact of this change on the frontend, backend, and database portions of the system where appropriate and applied the `~frontend`, `~backend`, and `~database` labels accordingly.
+1. I have considered the impact of this change on the frontend, backend, and database portions of the system where appropriate and applied the `~ux`, `~frontend`, `~backend`, and `~database` labels accordingly.
1. I have tested this MR in [all supported browsers](../install/requirements.md#supported-web-browsers), or determined that this testing is not needed.
1. I have confirmed that this change is [backwards compatible across updates](multi_version_compatibility.md), or I have decided that this does not apply.
1. I have properly separated EE content from FOSS, or this MR is FOSS only.
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index d0f107ba98a..6a7bbb2e302 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -45,7 +45,7 @@ scheduling into milestones. Labeling is a task for everyone. (For some projects,
Most issues will have labels for at least one of the following:
-- Type. For example: `~feature`, `~bug`, `~tooling`, or `~documentation`.
+- Type. For example: `~"type::feature"`, `~"type::bug"`, or `~"type::tooling"`.
- Stage. For example: `~"devops::plan"` or `~"devops::create"`.
- Group. For example: `~"group::source code"`, `~"group::knowledge"`, or `~"group::editor"`.
- Category. For example: `~"Category:Code Analytics"`, `~"Category:DevOps Reports"`, or `~"Category:Templates"`.
@@ -70,12 +70,12 @@ issue should have one and only one.
The current type labels are:
-- `~feature`
+- `~"type::feature"`
- `~"feature::addition"`
- `~"feature::enhancement"`
- - `~"feature::maintenance"`
-- `~bug`
-- `~tooling`
+- `~"type::maintenance"`
+- `~"type::bug"`
+- `~"type::tooling"`
- `~"tooling::pipelines"`
- `~"tooling::workflow"`
- `~"support request"`
@@ -168,7 +168,7 @@ their color is `#428BCA`.
`<Category Name>` is the category name as it is in the single source of truth for categories at
<https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml>.
-For instance, the "DevOps Report" category is represented by the
+For instance, the "DevOps Reports" category is represented by the
~"Category:DevOps Reports" label in the `gitlab-org` group since its
`devops_reports.name` value is "DevOps Reports".
@@ -342,11 +342,11 @@ To create a feature proposal, open an issue on the
[issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues).
In order to help track the feature proposals, we have created a
-[`feature`](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name=feature) label.
+[`~"type::feature"`](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name=type::feature) label.
For the time being, users that are not members of the project cannot add labels.
You can instead ask one of the [core team](https://about.gitlab.com/community/core-team/)
-members to add the label `~feature` to the issue or add the following
-code snippet right after your description in a new line: `~feature`.
+members to add the label `~"type::feature"` to the issue or add the following
+code snippet right after your description in a new line: `~"type::feature"`.
Please keep feature proposals as small and simple as possible, complex ones
might be edited to make them small and simple.
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index a521d89db2b..82fd62d8d79 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -83,6 +83,24 @@ request is as follows:
migrations on a fresh database before the MR is reviewed. If the review leads
to large changes in the MR, execute the migrations again once the review is complete.
1. Write tests for more complex migrations.
+1. If your merge request adds new validations to existing models, to make sure the
+ data processing is backwards compatible:
+
+ - Ask in the [`#database`](https://gitlab.slack.com/archives/CNZ8E900G) Slack channel
+ for assistance to execute the database query that checks the existing rows to
+ ensure existing rows aren't impacted by the change.
+ - Add the necessary validation with a feature flag to be gradually rolled out
+ following [the rollout steps](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#rollout).
+
+ If this merge request is urgent, the code owners should make the final call on
+ whether reviewing existing rows should be included as an immediate follow-up task
+ to the merge request.
+
+ NOTE:
+ There isn't a way to know anything about our customers' data on their
+ [self-managed instances](../../subscriptions/self_managed/index.md), so keep
+ that in mind for any data implications with your merge request.
+
1. Merge requests **must** adhere to the [merge request performance guidelines](../merge_request_performance_guidelines.md).
1. For tests that use Capybara, read
[how to write reliable, asynchronous integration tests](https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara).
@@ -240,6 +258,7 @@ requirements.
1. Working and clean code that is commented where needed.
1. [Unit, integration, and system tests](../testing_guide/index.md) that all pass
on the CI server.
+1. Peer member testing is optional but recommended when the risk of a change is high. This includes when the changes are [far-reaching](https://about.gitlab.com/handbook/engineering/development/#reducing-the-impact-of-far-reaching-work) or are for [components critical for security](../code_review.md#security).
1. Regressions and bugs are covered with tests that reduce the risk of the issue happening
again.
1. [Performance guidelines](../merge_request_performance_guidelines.md) have been followed.
diff --git a/doc/development/dangerbot.md b/doc/development/dangerbot.md
index aca37e2182a..829f6af76be 100644
--- a/doc/development/dangerbot.md
+++ b/doc/development/dangerbot.md
@@ -118,6 +118,23 @@ However, you can speed these cycles up somewhat by emptying the
`.gitlab/ci/rails.gitlab-ci.yml` file in your merge request. Just don't forget
to revert the change before merging!
+#### Adding labels via Danger
+
+NOTE:
+This is currently applicable to the [`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab)
+project only.
+
+Danger is often used to improve MR hygiene by adding labels. Instead of calling the
+API directly in your `Dangerfile`, add the labels to the `project_helper.labels_to_add` array.
+The main `Dangerfile` will then take care of adding the labels to the MR with a single API call.
+
+#### Shared rules and plugins
+
+If the rule or plugin you implement can be useful for other projects, think about
+upstreaming them to the [`gitlab-org/gitlab-dangerfiles`](https://gitlab.com/gitlab-org/gitlab-dangerfiles) project.
+
+#### Enable Danger on a project
+
To enable the Dangerfile on another existing GitLab project, run the following
extra steps:
diff --git a/doc/development/database/loose_foreign_keys.md b/doc/development/database/loose_foreign_keys.md
new file mode 100644
index 00000000000..157c1284512
--- /dev/null
+++ b/doc/development/database/loose_foreign_keys.md
@@ -0,0 +1,182 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Loose foreign keys
+
+## Problem statement
+
+In relational databases (including PostgreSQL), foreign keys provide a way to link
+two database tables together, and ensure data-consistency between them. In GitLab,
+[foreign keys](../foreign_keys.md) are vital part of the database design process.
+Most of our database tables have foreign keys.
+
+With the ongoing database [decomposition work](https://gitlab.com/groups/gitlab-org/-/epics/6168),
+linked records might be present on two different database servers. Ensuring data consistency
+between two databases is not possible with standard PostgreSQL foreign keys. PostgreSQL
+does not support foreign keys operating within a single database server, defining
+a link between two database tables in two different database servers over the network.
+
+Example:
+
+- Database "Main": `projects` table
+- Database "CI": `ci_pipelines` table
+
+A project can have many pipelines. When a project is deleted, the associated `ci_pipeline` (via the
+`project_id` column) records must be also deleted.
+
+With a multi-database setup, this cannot be achieved with foreign keys.
+
+## Asynchronous approach
+
+Our preferred approach to this problem is eventual consistency. With the loose foreign keys
+feature, we can configure delayed association cleanup without negatively affecting the
+application performance.
+
+### How it works
+
+In the previous example, a record in the `projects` table can have multiple `ci_pipeline`
+records. To keep the cleanup process separate from the actual parent record deletion,
+we can:
+
+1. Create a `DELETE` trigger on the `projects` table.
+ Record the deletions in a separate table (`deleted_records`).
+1. A job checks the `deleted_records` table every 5 minutes.
+1. For each record in the table, delete the associated `ci_pipelines` records
+ using the `project_id` column.
+
+NOTE:
+For this procedure to work, we must register which tables to clean up asynchronously.
+
+## Example migration and configuration
+
+### Configure the model
+
+First, tell the application that the `projects` table has a new loose foreign key.
+You can do this in the `Project` model:
+
+```ruby
+class Project < ApplicationRecord
+ # ...
+
+ include LooseForeignKey
+
+ loose_foreign_key :ci_pipelines, :project_id, on_delete: :async_delete # or async_nullify
+
+ # ...
+end
+```
+
+This instruction ensures the asynchronous cleanup process knows about the association, and the
+how to do the cleanup. In this case, the associated `ci_pipelines` records are deleted.
+
+### Track record changes
+
+To know about deletions in the `projects` table, configure a `DELETE` trigger using a database
+migration (post-migration). The trigger needs to be configured only once. If the model already has
+at least one `loose_foreign_key` definition, then this step can be skipped:
+
+```ruby
+class TrackProjectRecordChanges < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
+
+ enable_lock_retries!
+
+ def up
+ track_record_deletions(:projects)
+ end
+
+ def down
+ untrack_record_deletions(:projects)
+ end
+end
+```
+
+### Remove the foreign key
+
+If there is an existing foreign key, then it can be removed from the database. As of GitLab 14.5,
+the following foreign key describes the link between the `projects` and `ci_pipelines` tables:
+
+```sql
+ALTER TABLE ONLY ci_pipelines
+ADD CONSTRAINT fk_86635dbd80
+FOREIGN KEY (project_id)
+REFERENCES projects(id)
+ON DELETE CASCADE;
+```
+
+The migration should run after the `DELETE` trigger is installed. If the foreign key is deleted
+earlier, there is a good chance of introducing data inconsistency which needs manual cleanup:
+
+```ruby
+class RemoveProjectsCiPipelineFk < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def up
+ remove_foreign_key_if_exists(:ci_pipelines, :projects, name: "fk_86635dbd80")
+ end
+
+ def down
+ add_concurrent_foreign_key(:ci_pipelines, :projects, name: "fk_86635dbd80", column: :project_id, target_column: :id, on_delete: "cascade")
+ end
+end
+```
+
+At this point, the setup phase is concluded. The deleted `projects` records should be automatically
+picked up by the scheduled cleanup worker job.
+
+## Caveats of loose foreign keys
+
+### Record creation
+
+The feature provides an efficient way of cleaning up associated records after the parent record is
+deleted. Without foreign keys, it's the application's responsibility to validate if the parent record
+exists when a new associated record is created.
+
+A bad example: record creation with the given ID (`project_id` comes from user input).
+In this example, nothing prevents us from passing a random project ID:
+
+```ruby
+Ci::Pipeline.create!(project_id: params[:project_id])
+```
+
+A good example: record creation with extra check:
+
+```ruby
+project = Project.find(params[:project_id])
+Ci::Pipeline.create!(project_id: project.id)
+```
+
+### Association lookup
+
+Consider the following HTTP request:
+
+```plaintext
+GET /projects/5/pipelines/100
+```
+
+The controller action ignores the `project_id` parameter and finds the pipeline using the ID:
+
+```ruby
+ def show
+ # bad, avoid it
+ pipeline = Ci::Pipeline.find(params[:id]) # 100
+end
+```
+
+This endpoint still works when the parent `Project` model is deleted. This can be considered a
+a data leak which should not happen under normal circumstances:
+
+```ruby
+def show
+ # good
+ project = Project.find(params[:project_id])
+ pipeline = project.pipelines.find(params[:pipeline_id]) # 100
+end
+```
+
+NOTE:
+This example is unlikely in GitLab, because we usually look up the parent models to perform
+permission checks.
diff --git a/doc/development/database/multiple_databases.md b/doc/development/database/multiple_databases.md
index 0ba752ba3a6..a17ad798305 100644
--- a/doc/development/database/multiple_databases.md
+++ b/doc/development/database/multiple_databases.md
@@ -88,16 +88,6 @@ test: &test
statement_timeout: 120s
```
-### Migrations
-
-Place any migrations that affect `Ci::CiDatabaseRecord` models
-and their tables in two directories:
-
-- `db/migrate`
-- `db/ci_migrate`
-
-We aim to keep the schema for both tables the same across both databases.
-
<!--
NOTE: The `validate_cross_joins!` method in `spec/support/database/prevent_cross_joins.rb` references
the following heading in the code, so if you make a change to this heading, make sure to update
@@ -272,6 +262,62 @@ logic to delete these rows if or whenever necessary in your domain.
Finally, this de-normalization and new query also improves performance because
it does less joins and needs less filtering.
+##### Remove a redundant join
+
+Sometimes there are cases where a query is doing excess (or redundant) joins.
+
+A common example occurs where a query is joining from `A` to `C`, via some
+table with both foreign keys, `B`.
+When you only care about counting how
+many rows there are in `C` and if there are foreign keys and `NOT NULL` constraints
+on the foreign keys in `B`, then it might be enough to count those rows.
+For example, in
+[MR 71811](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71811), it was
+previously doing `project.runners.count`, which would produce a query like:
+
+```sql
+select count(*) from projects
+inner join ci_runner_projects on ci_runner_projects.project_id = projects.id
+where ci_runner_projects.runner_id IN (1, 2, 3)
+```
+
+This was changed to avoid the cross-join by changing the code to
+`project.runner_projects.count`. It produces the same response with the
+following query:
+
+```sql
+select count(*) from ci_runner_projects
+where ci_runner_projects.runner_id IN (1, 2, 3)
+```
+
+Another common redundant join is joining all the way to another table,
+then filtering by primary key when you could have instead filtered on a foreign
+key. See an example in
+[MR 71614](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71614). The previous
+code was `joins(scan: :build).where(ci_builds: { id: build_ids })`, which
+generated a query like:
+
+```sql
+select ...
+inner join security_scans
+inner join ci_builds on security_scans.build_id = ci_builds.id
+where ci_builds.id IN (1, 2, 3)
+```
+
+However, as `security_scans` already has a foreign key `build_id`, the code
+can be changed to `joins(:scan).where(security_scans: { build_id: build_ids })`,
+which produces the same response with the following query:
+
+```sql
+select ...
+inner join security_scans
+where security_scans.build_id IN (1, 2, 3)
+```
+
+Both of these examples of removing redundant joins remove the cross-joins,
+but they have the added benefit of producing simpler and faster
+queries.
+
##### Use `disable_joins` for `has_one` or `has_many` `through:` relations
Sometimes a join query is caused by using `has_one ... through:` or `has_many
diff --git a/doc/development/database_review.md b/doc/development/database_review.md
index dcd5baab177..45be797b720 100644
--- a/doc/development/database_review.md
+++ b/doc/development/database_review.md
@@ -172,7 +172,9 @@ test its execution using `CREATE INDEX CONCURRENTLY` in the `#database-lab` Slac
`gitlab-org/gitlab-foss` (`project_id = 13083`) or the `gitlab-org/gitlab` (`project_id = 278964`)
projects provide enough data to serve as a good example.
- That means that no query plan should return 0 records or less records than the provided limit (if a limit is included). If a query is used in batching, a proper example batch with adequate included results should be identified and provided.
- - If your queries belong to a new feature in GitLab.com and thus they don't return data in production, it's suggested to analyze the query and to provide the plan from a local environment.
+ - If your queries belong to a new feature in GitLab.com and thus they don't return data in production:
+ - You may analyze the query and to provide the plan from a local environment.
+ - `#database-lab` and [postgres.ai](https://postgres.ai/) both allow updates to data (`exec UPDATE issues SET ...`) and creation of new tables and columns (`exec ALTER TABLE issues ADD COLUMN ...`).
- More information on how to find the number of actual returned records in [Understanding EXPLAIN plans](understanding_explain_plans.md)
- For query changes, it is best to provide both the SQL queries along with the
plan _before_ and _after_ the change. This helps spot differences quickly.
diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md
index c169af1958e..8fc6f2e2641 100644
--- a/doc/development/documentation/feature_flags.md
+++ b/doc/development/documentation/feature_flags.md
@@ -71,8 +71,14 @@ Possible version history entries are:
> - [Enabled on GitLab.com](issue-link) in GitLab X.X.
> - [Enabled on GitLab.com](issue-link) in GitLab X.X. Available to GitLab.com administrators only.
> - [Enabled on self-managed](issue-link) in GitLab X.X.
-> - [Feature flag <flag name> removed](issue-link) in GitLab X.X.
-> - [Generally available](issue-link) in GitLab X.X.
+> - [Generally available](issue-link) in GitLab X.Y. [Feature flag <flag name>](issue-link) removed.
+```
+
+You can combine entries if they happened in the same release:
+
+```markdown
+> - Introduced in GitLab 14.2 [with a flag](../../administration/feature_flags.md) named `ci_include_rules`. Disabled by default.
+> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/337507) in GitLab 14.3.
```
## Feature flag documentation examples
@@ -84,7 +90,7 @@ The following examples show the progression of a feature flag.
FLAG:
On self-managed GitLab, by default this feature is not available. To make it available,
-ask an administrator to [enable the featured flag](../administration/feature_flags.md) named `forti_token_cloud`.
+ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `forti_token_cloud`.
The feature is not ready for production use.
```
@@ -105,6 +111,5 @@ And, when the feature is done and fully available to all users:
> - Introduced in GitLab 13.7 [with a flag](../../administration/feature_flags.md) named `forti_token_cloud`. Disabled by default.
> - [Enabled on self-managed](https://gitlab.com/issue/etc) GitLab 13.8.
> - [Enabled on GitLab.com](https://gitlab.com/issue/etc) in GitLab 13.9.
-> - [Feature flag removed](https://gitlab.com/issue/etc) in GitLab 14.0.
-> - [Generally available](issue-link) in GitLab 14.0.
+> - [Generally available](issue-link) in GitLab 14.0. [Feature flag <flag name>](issue-link) removed.
```
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 75538fe1fe7..776e5aefd00 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -170,22 +170,33 @@ it increases the work of the release managers.
## GitLab `/help`
-Every GitLab instance includes the documentation, which is available at `/help`
-(`https://gitlab.example.com/help`). For example, <https://gitlab.com/help>.
-
-The documentation available online on <https://docs.gitlab.com> is deployed every
-four hours from the `main` branch of GitLab, Omnibus, and Runner. Therefore,
-after a merge request gets merged, it is available online on the same day.
-However, it's shipped (and available on `/help`) within the milestone assigned
-to the MR.
-
-For example, let's say your merge request has a milestone set to 11.3, which
-a release date of 2018-09-22. If it gets merged on 2018-09-15, it is
-available online on 2018-09-15, but, as the feature freeze date has passed, if
-the MR does not have a `~"Pick into 11.3"` label, the milestone has to be changed
-to 11.4 and it ships with all GitLab packages only on 2018-10-22,
-with GitLab 11.4. Meaning, it's available only with `/help` from GitLab
-11.4 onward, but available on <https://docs.gitlab.com/> on the same day it was merged.
+Every GitLab instance includes documentation at `/help` (`https://gitlab.example.com/help`)
+that matches the version of the instance. For example, <https://gitlab.com/help>.
+
+The documentation available online at <https://docs.gitlab.com> is deployed every
+four hours from the default branch of [GitLab, Omnibus, Runner, and Charts](#source-files-and-rendered-web-locations).
+After a merge request that updates documentation is merged, it is available online
+in 4 hours or less.
+
+However, it's only available at `/help` on self-managed instances in the next released
+version. The date an update is merged can impact which self-managed release the update
+is present in.
+
+For example:
+
+1. A merge request in `gitlab` updates documentation. It has a milestone of 14.4,
+ with an expected release date of 2021-10-22.
+1. It is merged on 2021-10-19 and available online the same day at <https://docs.gitlab.com>.
+1. GitLab 14.4 is released on 2021-10-22, based on the `gitlab` codebase from 2021-10-18
+ (one day *before* the update was merged).
+1. The change shows up in the 14.5 self-managed release, due to missing the release cutoff
+ for 14.4.
+
+The exact cutoff date for each release is flexible, and can be earlier or later
+than expected due to holidays, weekends, or other events. In general, MRs merged
+by the 17th should be present in the release on the 22nd, though it is not guaranteed.
+If it is important that a documentation update is present in that month's release,
+merge it as early as possible.
### Linking to `/help`
diff --git a/doc/development/documentation/restful_api_styleguide.md b/doc/development/documentation/restful_api_styleguide.md
index b3d3e2641b7..03980a42381 100644
--- a/doc/development/documentation/restful_api_styleguide.md
+++ b/doc/development/documentation/restful_api_styleguide.md
@@ -49,8 +49,8 @@ METHOD /endpoint
Supported attributes:
-| Attribute | Type | Required | Description |
-|:------------|:---------|:---------|:----------------------|
+| Attribute | Type | Required | Description |
+| :---------- | :------- | :--------------------- | :-------------------- |
| `attribute` | datatype | **{check-circle}** Yes | Detailed description. |
| `attribute` | datatype | **{dotted-circle}** No | Detailed description. |
| `attribute` | datatype | **{dotted-circle}** No | Detailed description. |
@@ -80,16 +80,23 @@ to describe the GitLab release that introduced the API call.
Use the following table headers to describe the methods. Attributes should
always be in code blocks using backticks (`` ` ``).
+Sort the attributes in the table: first, required, then alphabetically.
+
```markdown
-| Attribute | Type | Required | Description |
-|:----------|:-----|:---------|:------------|
+| Attribute | Type | Required | Description |
+| :------------- | :------------ | :--------------------- | :--------------------------------------------------- |
+| `user` | string | **{check-circle}** Yes | The GitLab username. |
+| `assignee_ids` | integer array | **{dotted-circle}** No | The IDs of the users to assign the issue to. |
+| `confidential` | boolean | **{dotted-circle}** No | Set an issue to be confidential. Default is `false`. |
```
Rendered example:
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:--------------------|
-| `user` | string | yes | The GitLab username. |
+| Attribute | Type | Required | Description |
+| :------------- | :------------ | :--------------------- | :--------------------------------------------------- |
+| `user` | string | **{check-circle}** Yes | The GitLab username. |
+| `assignee_ids` | integer array | **{dotted-circle}** No | The IDs of the users to assign the issue to. |
+| `confidential` | boolean | **{dotted-circle}** No | Set an issue to be confidential. Default is `false`. |
## cURL commands
@@ -101,12 +108,12 @@ Rendered example:
- Prefer to use examples using the personal access token and don't pass data of
username and password.
-| Methods | Description |
-|:------------------------------------------- |:------------------------------------------------------|
+| Methods | Description |
+| :---------------------------------------------- | :----------------------------------------------------- |
| `--header "PRIVATE-TOKEN: <your_access_token>"` | Use this method as is, whenever authentication needed. |
-| `--request POST` | Use this method when creating new objects |
-| `--request PUT` | Use this method when updating existing objects |
-| `--request DELETE` | Use this method when removing existing objects |
+| `--request POST` | Use this method when creating new objects |
+| `--request PUT` | Use this method when updating existing objects |
+| `--request DELETE` | Use this method when removing existing objects |
## cURL Examples
diff --git a/doc/development/documentation/site_architecture/deployment_process.md b/doc/development/documentation/site_architecture/deployment_process.md
index 1b764ada87b..c038ee96dbf 100644
--- a/doc/development/documentation/site_architecture/deployment_process.md
+++ b/doc/development/documentation/site_architecture/deployment_process.md
@@ -4,26 +4,158 @@ group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Documentation deployment process
+# Documentation deployments
+
+The documentation [release process](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/releases.md)
+involves:
+
+- Merge requests, to make changes to the `main` and relevant stable branches.
+- Pipelines, to build and deploy Docker images to the [`gitlab-docs` container registry](https://gitlab.com/gitlab-org/gitlab-docs/container_registry)
+ for the relevant stable branches.
+- Docker images used to build and deploy all the online documentation, including stable versions and the latest documentation.
+
+Documentation deployments have dependencies on pipelines and Docker images as follows:
+
+- The latest documentation pipelines and images depend on the stable documentation pipelines and images.
+- The Pages deployment pipelines depend on the latest documentation images (which, in turn, depend on the stable
+ pipelines and images.)
+
+For general information on using Docker with CI/CD pipelines, see [Docker integration](../../../ci/docker/index.md).
+
+## Stable branches
+
+Stable branches for documentation include the relevant stable branches of all the projects required to publish the entire
+documentation suite. For example, the stable version of documentation for version `14.4` includes:
+
+- The [`14.4`](https://gitlab.com/gitlab-org/gitlab-docs/-/tree/14.4) branch of the `gitlab-docs` project.
+- The [`14-4-stable-ee`](https://gitlab.com/gitlab-org/gitlab/-/tree/14-4-stable-ee) branch of the `gitlab` project.
+- The [`14-4-stable`](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/14-4-stable) branch of the `gitlab-runner` project.
+- The [`14-4-stable`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/tree/14-4-stable) branch of the `omnibus-gitlab` project.
+- The [`5-4-stable`](https://gitlab.com/gitlab-org/charts/gitlab/-/tree/5-4-stable) branch of the `charts/gitlab` project.
+ `charts/gitlab` versions are [mapped](https://docs.gitlab.com/charts/installation/version_mappings.html) to GitLab
+ versions.
+
+The Technical Writing team
+[creates the stable branch](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/releases.md#create-stable-branch-and-docker-image-for-release)
+for the `gitlab-docs` project, which makes use of the stable branches created by other teams.
+
+## Stable documentation
+
+When merge requests are merged that target stable branches of `gitlab-docs`, a pipeline builds
+that stable documentation and deploys it to the registry. For example:
+
+- [14.4 merge request pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/394459635).
+- [14.3 merge request pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/393774811).
+- [14.2 merge request pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/393774758).
+- [13.12 merge request pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/395365202).
+- [12.10 merge request pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/395365405).
+
+In particular, the [`image:docs-single` job](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/4c18963fe0a414ad62f55b9e18f922588b2dd155/.gitlab-ci.yml#L655) in each pipeline
+takes what is built, and pushes it to the [container registry](https://gitlab.com/gitlab-org/gitlab-docs/container_registry/631635).
+
+```mermaid
+graph TD
+ A["14.4 MR merged"]
+ B["14.3 MR merged"]
+ C["14.2 MR merged"]
+ D["13.12 MR merged"]
+ E["12.10 MR merged"]
+ F{{"Container registry on `gitlab-docs` project"}}
+ A--"`image:docs-single`<br>job runs and pushes<br>`gitlab-docs:14.4` image"-->F
+ B--"`image:docs-single`<br>job runs and pushes<br>`gitlab-docs:14.3` image"-->F
+ C--"`image:docs-single`<br>job runs and pushes<br>`gitlab-docs:14.2` image"-->F
+ D--"`image:docs-single`<br>job runs and pushes<br>`gitlab-docs:13.12` image"-->F
+ E--"`image:docs-single`<br>job runs and pushes<br>`gitlab-docs:12.10` image"-->F
+```
-The [`dockerfiles` directory](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/)
-contains all needed Dockerfiles to build and deploy <https://docs.gitlab.com>. It
-is heavily inspired by Docker's
-[Dockerfile](https://github.com/docker/docker.github.io/blob/06ed03db13895bfe867761b6fc2ad40acf6026dd/Dockerfile).
+### Rebuild stable documentation images
+
+To rebuild any of the stable documentation images, create a [new pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/new)
+for the stable branch of the image to rebuild. You might do this:
+
+- To include new documentation changes from an upstream stable branch into a stable version Docker image. For example,
+ rebuild the `14.4` Docker image to include changes subsequently merged in the `gitlab` project's
+ [`14-4-stable-ee`](https://gitlab.com/gitlab-org/gitlab/-/tree/14-4-stable-ee) branch.
+- To incorporate changes made to the `gitlab-docs` project itself to a stable branch. For example:
+ - CSS style changes.
+ - Changes to the [version menu for a new release](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/releases.md#update-dropdown-for-online-versions).
+
+## Latest documentation
+
+A Docker image (tagged `latest`) is built that contains:
+
+- The latest online version of the documentation.
+- The documentation from the stable branches of upstream projects.
+
+The [`image:docs-latest` job](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/4c18963fe0a414ad62f55b9e18f922588b2dd155/.gitlab-ci.yml#L678):
+
+- Pulls the latest documentation from the default branches of the relevant upstream projects.
+- Pulls the Docker images previously built by the `image:docs-single` jobs.
+
+For example, [a pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/399233948) containing the
+[`image:docs-latest` job](https://gitlab.com/gitlab-org/gitlab-docs/-/jobs/1733948330):
+
+```mermaid
+graph TD
+ A["Latest `gitlab`, `gitlab-runner`<br>`omnibus-gitlab`, and `charts`"]
+ subgraph "Container registry on `gitlab-docs` project"
+ B["14.4 versioned docs<br>`gitlab-docs:14.4`"]
+ C["14.3 versioned docs<br>`gitlab-docs:14.3`"]
+ D["14.2 versioned docs<br>`gitlab-docs:14.2`"]
+ E["13.12 versioned docs<br>`gitlab-docs:13.12`"]
+ F["12.10 versioned docs<br>`gitlab-docs:12.10`"]
+ end
+ G[["Scheduled pipeline<br>`image:docs-latest` job<br>combines all these"]]
+ A--"Default branches<br>pulled down"-->G
+ B--"`gitlab-docs:14.4` image<br>pulled down"-->G
+ C--"`gitlab-docs:14.3` image<br>pulled down"-->G
+ D--"`gitlab-docs:14.2` image<br>pulled down"-->G
+ E--"`gitlab-docs:13.12` image<br>pulled down"-->G
+ F--"`gitlab-docs:12.10` image<br>pulled down"-->G
+ H{{"Container registry on gitlab-docs project"}}
+ G--"Latest `gitlab-docs:latest` image<br>pushed up"-->H
+```
+
+## Documentation Pages deployment
+
+[GitLab Docs](https://docs.gitlab.com) is a [Pages site](../../../user/project/pages/index.md) and documentation updates
+for it must be deployed to become available.
+
+The [`pages`](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/4c18963fe0a414ad62f55b9e18f922588b2dd155/.gitlab-ci.yml#L491)
+job runs the necessary commands to combine:
+
+- A very up-to-date build of the `gitlab-docs` site code.
+- The latest docs from the default branches of the upstream projects.
+- The documentation from `image:docs-latest`.
+
+For example, [a pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/399233948) containing the
+[`pages` job](https://gitlab.com/gitlab-org/gitlab-docs/-/jobs/1733948332).
+
+```mermaid
+graph LR
+ A{{"Container registry on gitlab-docs project"}}
+ B[["Scheduled pipeline<br>`pages` and<br>`pages:deploy` job"]]
+ C([docs.gitlab.com])
+ A--"`gitlab-docs:latest`<br>pulled"-->B
+ B--"Unpacked documentation uploaded"-->C
+```
-The following Dockerfiles are used.
+## Docker files
-| Dockerfile | Docker image | Description |
-| ---------- | ------------ | ----------- |
-| [`Dockerfile.bootstrap`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.bootstrap) | `gitlab-docs:bootstrap` | Contains all the dependencies that are needed to build the website. If the gems are updated and `Gemfile{,.lock}` changes, the image must be rebuilt. |
-| [`Dockerfile.builder.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.builder.onbuild) | `gitlab-docs:builder-onbuild` | Base image to build the docs website. It uses `ONBUILD` to perform all steps and depends on `gitlab-docs:bootstrap`. |
-| [`Dockerfile.nginx.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.nginx.onbuild) | `gitlab-docs:nginx-onbuild` | Base image to use for building documentation archives. It uses `ONBUILD` to perform all required steps to copy the archive, and relies upon its parent `Dockerfile.builder.onbuild` that is invoked when building single documentation archives (see the `Dockerfile` of each branch. |
-| [`Dockerfile.archives`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.archives) | `gitlab-docs:archives` | Contains all the versions of the website in one archive. It copies all generated HTML files from every version in one location. |
+The [`dockerfiles` directory](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/) contains all needed
+Dockerfiles to build and deploy <https://docs.gitlab.com>. It is heavily inspired by Docker's
+[Dockerfile](https://github.com/docker/docker.github.io/blob/06ed03db13895bfe867761b6fc2ad40acf6026dd/Dockerfile).
+
+| Dockerfile | Docker image | Description |
+|:---------------------------------------------------------------------------------------------------------------------------|:------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [`Dockerfile.bootstrap`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.bootstrap) | `gitlab-docs:bootstrap` | Contains all the dependencies that are needed to build the website. If the gems are updated and `Gemfile{,.lock}` changes, the image must be rebuilt. |
+| [`Dockerfile.builder.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.builder.onbuild) | `gitlab-docs:builder-onbuild` | Base image to build the docs website. It uses `ONBUILD` to perform all steps and depends on `gitlab-docs:bootstrap`. |
+| [`Dockerfile.nginx.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.nginx.onbuild) | `gitlab-docs:nginx-onbuild` | Base image to use for building documentation archives. It uses `ONBUILD` to perform all required steps to copy the archive, and relies upon its parent `Dockerfile.builder.onbuild` that is invoked when building single documentation archives (see the `Dockerfile` of each branch) |
+| [`Dockerfile.archives`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.archives) | `gitlab-docs:archives` | Contains all the versions of the website in one archive. It copies all generated HTML files from every version in one location. |
-## How to build the images
+### How to build the images
-Although build images are built automatically via GitLab CI/CD, you can build
-and tag all tooling images locally:
+Although build images are built automatically via GitLab CI/CD, you can build and tag all tooling images locally:
1. Make sure you have [Docker installed](https://docs.docker.com/install/).
1. Make sure you're in the `dockerfiles/` directory of the `gitlab-docs` repository.
@@ -37,28 +169,3 @@ and tag all tooling images locally:
For each image, there's a manual job under the `images` stage in
[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/.gitlab-ci.yml) which can be invoked at any time.
-
-## Update an old Docker image with new upstream docs content
-
-If there are any changes to any of the stable branches of the products that are
-not included in the single Docker image, just rerun the pipeline (`https://gitlab.com/gitlab-org/gitlab-docs/pipelines/new`)
-for the version in question.
-
-## Porting new website changes to old versions
-
-WARNING:
-Porting changes to older branches can have unintended effects as we're constantly
-changing the backend of the website. Use only when you know what you're doing
-and make sure to test locally.
-
-The website keeps changing and being improved. In order to consolidate
-those changes to the stable branches, we'd need to pick certain changes
-from time to time.
-
-If this is not possible or there are many changes, merge main into them:
-
-```shell
-git branch 12.0
-git fetch origin main
-git merge origin/main
-```
diff --git a/doc/development/documentation/site_architecture/global_nav.md b/doc/development/documentation/site_architecture/global_nav.md
index 3845586ce60..6d2b93b9462 100644
--- a/doc/development/documentation/site_architecture/global_nav.md
+++ b/doc/development/documentation/site_architecture/global_nav.md
@@ -97,20 +97,13 @@ mechanics of what is required is [documented below](#data-file) but, in principl
The global nav has five levels:
-- **Section**
+- Section
- Category
- Doc
- Doc
- Doc
-The majority of the links available on the nav were added according to the UI.
-The match is not perfect, as for some UI nav items the documentation doesn't
-apply, and there are also other links to help the new users to discover the
-documentation. The docs under **Administration** are ordered alphabetically
-for clarity.
-
-To see the improvements planned, check the
-[global nav epic](https://gitlab.com/groups/gitlab-org/-/epics/1599).
+You can view this structure in [the navigation.yml file](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/content/_data/navigation.yaml).
**Do not** [add items](#add-a-navigation-entry) to the global nav without
the consent of one of the technical writers.
diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md
index d1736e10000..60894430d15 100644
--- a/doc/development/documentation/site_architecture/index.md
+++ b/doc/development/documentation/site_architecture/index.md
@@ -124,12 +124,12 @@ Every four hours a scheduled pipeline builds and deploys the docs site. The pipe
fetches the current docs from the main project's main branch, builds it with Nanoc
and deploys it to <https://docs.gitlab.com>.
-If you need to build and deploy the site immediately (must have maintainer level permissions):
+To build and deploy the site immediately (must have the Maintainer role):
1. In [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs), go to **{rocket}** **CI/CD > Schedules**.
1. For the `Build docs.gitlab.com every 4 hours` scheduled pipeline, click the **play** (**{play}**) button.
-Read more about the [deployment process](deployment_process.md).
+Read more about [documentation deployments](deployment_process.md).
## Using YAML data files
@@ -163,6 +163,35 @@ We can then loop over the `versions` array with something like:
Note that the data file must have the `yaml` extension (not `yml`) and that
we reference the array with a symbol (`:versions`).
+## Archived documentation banner
+
+A banner is displayed on archived documentation pages with the text `This is archived documentation for
+GitLab. Go to the latest.` when either:
+
+- The version of the documentation displayed is not the first version entry in `online` in
+ `content/_data/versions.yaml`.
+- The documentation was built from the default branch (`main`).
+
+For example, if the `online` entries for `content/_data/versions.yaml` are:
+
+```yaml
+online:
+ - "14.4"
+ - "14.3"
+ - "14.2"
+```
+
+In this case, the archived documentation banner isn't displayed:
+
+- For 14.4, the docs built from the `14.4` branch. The branch name is the first entry in `online`.
+- For 14.5-pre, the docs built from the default project branch (`main`).
+
+The archived documentation banner is displayed:
+
+- For 14.3.
+- For 14.2.
+- For any other version.
+
## Bumping versions of CSS and JavaScript
Whenever the custom CSS and JavaScript files under `content/assets/` change,
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index 229dbb077fe..fac83af89f4 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -234,9 +234,21 @@ If you need to add more than one task,
consider using subsections for each distinct task.
```
+### Related topics
+
+If inline links are not sufficient, you can create a topic called **Related topics**
+and include a bulleted list of related topics. This topic should be above the Troubleshooting section.
+
+```markdown
+# Related topics
+
+- [Configure your pipeline](link-to-topic)
+- [Trigger a pipeline manually](link-to-topic)
+```
+
### Topics and resources pages
-This is a page with a list of links that point to important sections
+This page has a list of links that point to important sections
of documentation for a specific GitLab feature or tool.
We do not encourage the use of these types of pages.
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index 72491ab3a33..1382ec263f2 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -317,8 +317,8 @@ create an issue or an MR to propose a change to the user interface text.
#### Feature names
-- *Feature names are typically lowercase*.
-- *Some features are capitalized*, typically nouns naming GitLab-specific
+- Feature names are typically lowercase.
+- Some features are capitalized, typically nouns that name GitLab-specific
capabilities or tools.
See the [word list](word_list.md) for details.
@@ -404,13 +404,13 @@ Some contractions, however, should be avoided:
| Do | Don't |
|------------------------------------------|-----------------------------------------|
- | Do *not* install X with Y. | *Don't* install X with Y. |
+ | Do not install X with Y. | Don't install X with Y. |
- Do not use contractions in reference documentation. For example:
| Do | Don't |
|------------------------------------------|-----------------------------------------|
- | Do *not* set a limit greater than 1000. | *Don't* set a limit greater than 1000. |
+ | Do not set a limit greater than 1000. | Don't set a limit greater than 1000. |
| For `parameter1`, the default is 10. | For `parameter1`, the default's 10. |
- Avoid contractions in error messages. Examples:
@@ -701,7 +701,7 @@ that's best described by a matrix, tables are the best choice.
To keep tables accessible and scannable, tables should not have any
empty cells. If there is no otherwise meaningful value for a cell, consider entering
-*N/A* (for 'not applicable') or *none*.
+**N/A** for 'not applicable' or **None**.
To help tables be easier to maintain, consider adding additional spaces to the
column widths to make them consistent. For example:
@@ -1026,18 +1026,13 @@ document to ensure it links to the most recent version of the file.
When documenting how to navigate through the GitLab UI:
- Always use location, then action.
- - `From the **Visibility** list,` (location) `select **Public**.` (action)
+ - From the **Visibility** dropdown list (location), select **Public** (action).
- Be brief and specific. For example:
- - Avoid: `Select **Save** for the changes to take effect.`
- - Use instead: `Select **Save**.`
-- When selecting from high-level UI elements, use the word **on**.
- - Avoid: `From the left sidebar...` or `In the left sidebar...`
- - Use instead: `On the left sidebar...`
-- If a step must include a reason, start the step with it.
- - Avoid: `Select the link in the merge request to view the changes.`
- - Use instead: `To view the changes, select the link in the merge request.`
-- If a step is optional, start the step with the word `Optional` followed by a period.
- - `1. Optional. Enter a name for the dog.`
+ - Do: Select **Save**.
+ - Do not: Select **Save** for the changes to take effect.
+- If a step must include a reason, start the step with it. This helps the user scan more quickly.
+ - Do: To view the changes, in the merge request, select the link.
+ - Do not: Select the link in the merge request to view the changes.
### Names for menus
@@ -1060,15 +1055,19 @@ Guidance for each individual UI element is in [the word list](word_list.md).
To be consistent, use this format when you write navigation steps in a task topic.
+```markdown
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **General pipelines**.
+```
Another example:
+```markdown
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **General pipelines**.
+```
An Admin Area example:
@@ -1082,6 +1081,42 @@ To select your avatar:
1. On the top bar, in the top right corner, select your avatar.
```
+### Optional steps
+
+If a step is optional, start the step with the word `Optional` followed by a period.
+
+For example:
+
+```markdown
+1. Optional. Enter a description for the job.
+```
+
+### Documenting multiple fields at once
+
+If the UI text sufficiently explains the fields in a section, do not include a task step for every field.
+Instead, summarize multiple fields in a single task step.
+
+Use the phrase **Complete the fields**.
+
+For example:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Push rules**.
+1. Complete the fields.
+
+If you are documenting multiple fields and only one field needs explanation, do it in the same step:
+
+1. Expand **Push rules**.
+1. Complete the fields. **Branch name** must be a regular expression.
+
+To describe multiple fields, use bullets:
+
+1. Expand **General pipelines**.
+1. Complete the fields.
+ - **Branch name** must be a regular expression.
+ - **User** must be a user with at least the **Maintainer** role.
+
## Images
Images, including screenshots, can help a reader better understand a concept.
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
index f1e6a147571..595dab09bf5 100644
--- a/doc/development/documentation/styleguide/word_list.md
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -259,6 +259,16 @@ Use **box** instead of **field** or **text box**.
- Do: In the **Variable name** box, enter `my text`.
- Do not: In the **Variable name** field, enter `my text`.
+However, you can make an exception when you are writing a task and you need to refer to all
+of the fields at once. For example:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **General pipelines**.
+1. Complete the fields.
+
+Learn more about [documenting multiple fields at once](index.md#documenting-multiple-fields-at-once).
+
## foo
Do not use **foo** in product documentation. You can use it in our API and contributor documentation, but try to use a clearer and more meaningful example instead.
@@ -454,6 +464,13 @@ Do not use **note that** because it's wordy.
- Do: You can change the settings.
- Do not: Note that you can change the settings.
+## on
+
+When documenting how to select high-level UI elements, use the word **on**.
+
+- Do: `On the left sidebar...`
+- Do not: `From the left sidebar...` or `In the left sidebar...`
+
## once
The word **once** means **one time**. Don't use it to mean **after** or **when**.
@@ -524,8 +541,8 @@ Use lowercase for **runners**. These are the agents that run CI/CD jobs. See als
Do not use **(s)** to make a word optionally plural. It can slow down comprehension. For example:
-Do: Select the jobs you want.
-Do not: Select the job(s) you want.
+- Do: Select the jobs you want.
+- Do not: Select the job(s) you want.
If you can select multiples of something, then write the word as plural.
@@ -555,6 +572,10 @@ or collapsing a section, don't include the word **section**.
Use **select** with buttons, links, menu items, and lists. **Select** applies to more devices,
while **click** is more specific to a mouse.
+## Service Desk
+
+Use title case for **Service Desk**.
+
## setup, set up
Use **setup** as a noun, and **set up** as a verb. For example:
diff --git a/doc/development/documentation/workflow.md b/doc/development/documentation/workflow.md
index 90c1137e5c5..782cd3411b1 100644
--- a/doc/development/documentation/workflow.md
+++ b/doc/development/documentation/workflow.md
@@ -39,7 +39,7 @@ The following are also added by members of the Technical Writing team:
- The `~Technical Writing` [team label](../contributing/issue_workflow.md#team-labels).
Documentation changes that are not associated with the release of a new or updated feature
-do not take the `~feature` label, but still need the `~documentation` label.
+do not take the `~"type::feature"` label, but still need the `~documentation` label.
They may include:
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
index 68d8b424331..7c67b3495ba 100644
--- a/doc/development/elasticsearch.md
+++ b/doc/development/elasticsearch.md
@@ -250,6 +250,11 @@ the migration runs and set it back to that value when the migration is completed
will halt the migration if the storage required is not available when the migration runs. The migration must provide
the space required in bytes by defining a `space_required_bytes` method.
+- `retry_on_failure` - Enable the retry on failure feature. By default, it retries
+ the migration 30 times. After it runs out of retries, the migration is marked as halted.
+ To customize the number of retries, pass the `max_attempts` argument:
+ `retry_on_failure max_attempts: 10`
+
```ruby
# frozen_string_literal: true
@@ -259,6 +264,7 @@ class BatchedMigrationName < Elastic::Migration
throttle_delay 10.minutes
pause_indexing!
space_requirements!
+ retry_on_failure
# ...
end
@@ -359,17 +365,15 @@ being upgraded to, we do the following:
### Prometheus
-GitLab exports [Prometheus
-metrics](../administration/monitoring/prometheus/gitlab_metrics.md) relating to
-the number of requests and timing for all web/API requests and Sidekiq jobs,
+GitLab exports [Prometheus metrics](../administration/monitoring/prometheus/gitlab_metrics.md)
+relating to the number of requests and timing for all web/API requests and Sidekiq jobs,
which can help diagnose performance trends and compare how Elasticsearch timing
is impacting overall performance relative to the time spent doing other things.
#### Indexing queues
-GitLab also exports [Prometheus
-metrics](../administration/monitoring/prometheus/gitlab_metrics.md) for
-indexing queues, which can help diagnose performance bottlenecks and determine
+GitLab also exports [Prometheus metrics](../administration/monitoring/prometheus/gitlab_metrics.md)
+for indexing queues, which can help diagnose performance bottlenecks and determine
whether or not your GitLab instance or Elasticsearch server can keep up with
the volume of updates.
diff --git a/doc/development/experiment_guide/gitlab_experiment.md b/doc/development/experiment_guide/gitlab_experiment.md
index 1cd3fefb7cf..af4512dcde0 100644
--- a/doc/development/experiment_guide/gitlab_experiment.md
+++ b/doc/development/experiment_guide/gitlab_experiment.md
@@ -92,7 +92,7 @@ end
```
When this code executes, the experiment is run, a variant is assigned, and (if within a
-controller or view) a `window.gon.experiment.pill_color` object will be available in the
+controller or view) a `window.gl.experiments.pill_color` object will be available in the
client layer, with details like:
- The assigned variant.
@@ -522,14 +522,14 @@ shared example: [tracks assignment and records the subject](https://gitlab.com/g
This is in flux as of GitLab 13.10, and can't be documented just yet.
-Any experiment that's been run in the request lifecycle surfaces in `window.gon.experiment`,
+Any experiment that's been run in the request lifecycle surfaces in and `window.gl.experiments`,
and matches [this schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/1-0-0)
so you can use it when resolving some concepts around experimentation in the client layer.
### Use experiments in Vue
With the `gitlab-experiment` component, you can define slots that match the name of the
-variants pushed to `window.gon.experiment`. For example, if we alter the `pill_color`
+variants pushed to `window.gl.experiments`. For example, if we alter the `pill_color`
experiment to just use the default variants of `control` and `candidate` like so:
```ruby
@@ -587,7 +587,51 @@ For example, the Vue component for the previously-defined `pill_color` experimen
```
NOTE:
-When there is no experiment data in the `window.gon.experiment` object for the given experiment name, the `control` slot will be used, if it exists.
+When there is no experiment data in the `window.gl.experiments` object for the given experiment name, the `control` slot will be used, if it exists.
+
+## Test with Jest
+
+### Stub Helpers
+
+You can stub experiments using the `stubExperiments` helper defined in `spec/frontend/__helpers__/experimentation_helper.js`.
+
+```javascript
+import { stubExperiments } from 'helpers/experimentation_helper';
+import { getExperimentData } from '~/experimentation/utils';
+
+describe('when my_experiment is enabled', () => {
+ beforeEach(() => {
+ stubExperiments({ my_experiment: 'candidate' });
+ });
+
+ it('sets the correct data', () => {
+ expect(getExperimentData('my_experiment')).toEqual({ experiment: 'my_experiment', variant: 'candidate' });
+ });
+});
+```
+
+NOTE:
+This method of stubbing in Jest specs will not automatically un-stub itself at the end of the test. We merge our stubbed experiment in with all the other global data in `window.gl`. If you need to remove the stubbed experiment(s) after your test or ensure a clean global object before your test, you'll need to manage the global object directly yourself:
+
+```javascript
+desribe('tests that care about global state', () => {
+ const originalObjects = [];
+
+ beforeEach(() => {
+ // For backwards compatibility for now, we're using both window.gon & window.gl
+ originalObjects.push(window.gon, window.gl);
+ });
+
+ afterEach(() => {
+ [window.gon, window.gl] = originalObjects;
+ });
+
+ it('stubs experiment in fresh global state', () => {
+ stubExperiment({ my_experiment: 'candidate' });
+ // ...
+ });
+})
+```
## Notes on feature flags
diff --git a/doc/development/fe_guide/accessibility.md b/doc/development/fe_guide/accessibility.md
index c4ebef4c289..e71e414002a 100644
--- a/doc/development/fe_guide/accessibility.md
+++ b/doc/development/fe_guide/accessibility.md
@@ -23,6 +23,17 @@ they found that "ARIA correlated to higher detectable errors".
It is likely that *misuse* of ARIA is a big cause of increased errors,
so when in doubt don't use `aria-*`, `role`, and `tabindex` and stick with semantic HTML.
+## Enable keyboard navigation on macOS
+
+By default, macOS limits the <kbd>tab</kbd> key to **Text boxes and lists only**. To enable full keyboard navigation:
+
+1. Open **System Preferences**.
+1. Select **Keyboard**.
+1. Open the **Shortcuts** tab.
+1. Enable the setting **Use keyboard navigation to move focus between controls**.
+
+You can read more about enabling browser-specific keyboard navigation on [a11yproject](https://www.a11yproject.com/posts/2017-12-29-macos-browser-keyboard-navigation/).
+
## Quick checklist
- [Text](#text-inputs-with-accessible-names),
diff --git a/doc/development/fe_guide/development_process.md b/doc/development/fe_guide/development_process.md
index 4e50621add4..cd82a7dadc3 100644
--- a/doc/development/fe_guide/development_process.md
+++ b/doc/development/fe_guide/development_process.md
@@ -56,7 +56,7 @@ Please use your best judgment when to use it and please contribute new points th
- [ ] **Performance** Have you checked performance? For example do the same thing with 500 comments instead of 1. Document the tests and possible findings in the MR so a reviewer can directly see it.
- [ ] Have you tested with a variety of our [supported browsers](../../install/requirements.md#supported-web-browsers)? You can use [browserstack](https://www.browserstack.com/) to be able to access a wide variety of browsers and operating systems.
- [ ] Did you check the mobile view?
-- [ ] Check the built webpack bundle (For the report run `WEBPACK_REPORT=true gdk run`, then open `webpack-report/index.html`) if we have unnecessary bloat due to wrong references, including libraries multiple times, etc.. If you need help contact the webpack [domain expert](https://about.gitlab.com/handbook/engineering/frontend/#frontend-domain-experts)
+- [ ] Check the built webpack bundle (For the report run `WEBPACK_REPORT=true gdk start`, then open `webpack-report/index.html`) if we have unnecessary bloat due to wrong references, including libraries multiple times, etc.. If you need help contact the webpack [domain expert](https://about.gitlab.com/handbook/engineering/frontend/#frontend-domain-experts)
- [ ] **Tests** Not only greenfield tests - Test also all bad cases that come to your mind.
- [ ] If you have multiple MR's then also smoke test against the final merge.
- [ ] Are there any big changes on how and especially how frequently we use the API then let production know about it
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index 0229aa0123a..44d43a32803 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -103,7 +103,6 @@ Default client accepts two parameters: `resolvers` and `config`.
- `config` parameter takes an object of configuration settings:
- `cacheConfig` field accepts an optional object of settings to [customize Apollo cache](https://www.apollographql.com/docs/react/caching/cache-configuration/#configuring-the-cache)
- `baseUrl` allows us to pass a URL for GraphQL endpoint different from our main endpoint (for example, `${gon.relative_url_root}/api/graphql`)
- - `assumeImmutableResults` (set to `false` by default) - this setting, when set to `true`, assumes that every single operation on updating Apollo Cache is immutable. It also sets `freezeResults` to `true`, so any attempt on mutating Apollo Cache throws a console warning in development environment. Please ensure you're following the immutability pattern on cache update operations before setting this option to `true`.
- `fetchPolicy` determines how you want your component to interact with the Apollo cache. Defaults to "cache-first".
### Multiple client queries for the same object
@@ -179,7 +178,7 @@ with a **new and updated** object.
To facilitate the process of updating the cache and returning the new object we
use the library [Immer](https://immerjs.github.io/immer/).
-When possible, follow these conventions:
+Please, follow these conventions:
- The updated cache is named `data`.
- The original cache data is named `sourceData`.
@@ -204,11 +203,6 @@ client.writeQuery({
As shown in the code example by using `produce`, we can perform any kind of direct manipulation of the
`draftState`. Besides, `immer` guarantees that a new state which includes the changes to `draftState` is generated.
-Finally, to verify whether the immutable cache update is working properly, we need to change
-`assumeImmutableResults` to `true` in the default client configuration. See [Apollo Client](#apollo-client) for more information.
-
-If everything is working properly `assumeImmutableResults` should remain set to `true`.
-
## Usage in Vue
To use Vue Apollo, import the [Vue Apollo](https://github.com/vuejs/vue-apollo) plugin as well
@@ -1106,17 +1100,15 @@ To test the logic of Apollo cache updates, we might want to mock an Apollo Clien
To separate tests with mocked client from 'usual' unit tests, create an additional factory and pass the created `mockApollo` as an option to the `createComponent`-factory. This way we only create Apollo Client instance when it's necessary.
-We need to inject `VueApollo` to the Vue local instance and, likewise, it is recommended to call `localVue.use()` in `createMockApolloProvider()` to only load it when it is necessary.
+We need to inject `VueApollo` into the Vue instance by calling `Vue.use(VueApollo)`. This will install `VueApollo` globally for all the tests in the file. It is recommended to call `Vue.use(VueApollo)` just after the imports.
```javascript
import VueApollo from 'vue-apollo';
-import { createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
-const localVue = createLocalVue();
+Vue.use(VueApollo);
function createMockApolloProvider() {
- localVue.use(VueApollo);
-
return createMockApollo(requestHandlers);
}
@@ -1124,7 +1116,6 @@ function createComponent(options = {}) {
const { mockApollo } = options;
...
return shallowMount(..., {
- localVue,
apolloProvider: mockApollo,
...
});
@@ -1194,7 +1185,6 @@ describe('Some component', () => {
const { mockApollo } = options;
return shallowMount(Index, {
- localVue,
apolloProvider: mockApollo,
});
}
@@ -1281,7 +1271,6 @@ function createComponent(options = {}) {
const { mockApollo } = options;
return shallowMount(Index, {
- localVue,
apolloProvider: mockApollo,
});
}
@@ -1414,7 +1403,6 @@ const createComponentWithApollo = ({ props = {} } = {}) => {
mockApollo = createMockApollo([], mockResolvers); // resolvers are the second parameter
wrapper = shallowMount(MyComponent, {
- localVue,
propsData: {},
apolloProvider: mockApollo,
// ...
@@ -1482,7 +1470,6 @@ function createComponent(options = {}) {
const { mockApollo } = options;
return shallowMount(Index, {
- localVue,
apolloProvider: mockApollo,
});
}
diff --git a/doc/development/fe_guide/storybook.md b/doc/development/fe_guide/storybook.md
index a46157d2cad..9c4bcf02389 100644
--- a/doc/development/fe_guide/storybook.md
+++ b/doc/development/fe_guide/storybook.md
@@ -47,8 +47,9 @@ To add a story:
1. Write the story as per the [official Storybook instructions](https://storybook.js.org/docs/vue/writing-stories/introduction/)
Notes:
- - Specify the `title` field of the story as the component's file path from the `javascripts/` directory,
- e.g. if the component is located at `app/assets/javascripts/vue_shared/components/sidebar/todo_toggle/todo_button.vue`, specify the story `title` as `vue_shared/components/sidebar/todo_toggle/todo_button`. This will ensure the Storybook navigation maps closely to our internal directory structure.
+ - Specify the `title` field of the story as the component's file path from the `javascripts/` directory.
+
+ For example, if the component is located at `app/assets/javascripts/vue_shared/components/sidebar/todo_toggle/todo_button.vue`, specify the story `title` as `vue_shared/components/sidebar/todo_toggle/todo_button`. This will ensure the Storybook navigation maps closely to our internal directory structure.
## Mock backend APIs
diff --git a/doc/development/fe_guide/style/scss.md b/doc/development/fe_guide/style/scss.md
index ffaaa3e87c7..5d5b250e9a9 100644
--- a/doc/development/fe_guide/style/scss.md
+++ b/doc/development/fe_guide/style/scss.md
@@ -133,6 +133,40 @@ Before adding a new variable for a color or a size, guarantee:
- There isn't an existing one.
- There isn't a similar one we can use instead.
+### Using `extend` at-rule
+
+Usage of the `extend` at-rule is prohibited due to [memory leaks](https://gitlab.com/gitlab-org/gitlab/-/issues/323021) and [the rule doesn't work as it should to](https://sass-lang.com/documentation/breaking-changes/extend-compound). Use mixins instead:
+
+```scss
+// Bad
+.gl-pt-3 {
+ padding-top: 12px;
+}
+
+.my-element {
+ @extend .gl-pt-3;
+}
+
+// compiles to
+.gl-pt-3, .my-element {
+ padding-top: 12px;
+}
+
+// Good
+@mixing gl-pt-3 {
+ padding-top: 12px;
+}
+
+.my-element {
+ @include gl-pt-3;
+}
+
+// compiles to
+.my-element {
+ padding-top: 12px;
+}
+```
+
## Linting
We use [stylelint](https://stylelint.io) to check for style guide conformity. It uses the
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 509e2f4b688..5d5d37e0398 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -73,9 +73,8 @@ component, is that you avoid the need to create a fixture or an HTML element in
##### provide/inject
Vue supports dependency injection through [provide/inject](https://vuejs.org/v2/api/#provide-inject).
-Values passed to the component through `provide` can be accessed in the component the `inject` configuration.
-In the following example of a Vue app initialization, a value from HAML is passed to the component
-through the `provide` configuration:
+In the component the `inject` configuration accesses the values `provide` passes down.
+This example of a Vue app initialization shows how the `provide` configuration passes a value from HAML to the component:
```javascript
#js-vue-app{ data: { endpoint: 'foo' }}
@@ -251,7 +250,7 @@ return new Vue({
render(createElement) {
return createElement('my-component', {
props: {
- username: gon.current_username,
+ avatarUrl: gl.avatarUrl,
},
});
},
diff --git a/doc/development/fe_guide/vue3_migration.md b/doc/development/fe_guide/vue3_migration.md
index 7da462a5f89..c6f480deb22 100644
--- a/doc/development/fe_guide/vue3_migration.md
+++ b/doc/development/fe_guide/vue3_migration.md
@@ -29,6 +29,12 @@ Component's computed properties / methods or external helpers.
`$on`, `$once`, and `$off` methods [are removed](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0020-events-api-change.md) from the Vue instance, so in Vue 3 it can't be used to create an event hub.
+**When to use**
+
+If you are in a Vue app that doesn't use any event hub, try to avoid adding a new one unless absolutely necessary. For example, if you need a child component to react to its parent's event, it's preferred to pass a prop down. Then, use the watch property on that prop in the child component to create the desired side effect.
+
+If you need cross-component communication (between different Vue apps), then perhaps introducing a hub is the right decision.
+
**What to use instead**
Vue documentation recommends using the [mitt](https://github.com/developit/mitt) library. It's relatively small (200 bytes, compressed) and has a clear API:
diff --git a/doc/development/feature_categorization/index.md b/doc/development/feature_categorization/index.md
index 20325facc75..d6b64001e13 100644
--- a/doc/development/feature_categorization/index.md
+++ b/doc/development/feature_categorization/index.md
@@ -96,7 +96,7 @@ second argument:
```ruby
class DashboardController < ApplicationController
- feature_category :issue_tracking, [:issues, :issues_calendar]
+ feature_category :team_planning, [:issues, :issues_calendar]
feature_category :code_review, [:merge_requests]
end
```
@@ -137,7 +137,7 @@ Grape API endpoints can use the `feature_category` class method, like
```ruby
module API
class Issues < ::API::Base
- feature_category :issue_tracking
+ feature_category :team_planning
end
end
```
diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md
index 35dbc2703f9..abb100c659e 100644
--- a/doc/development/feature_flags/controls.md
+++ b/doc/development/feature_flags/controls.md
@@ -90,9 +90,9 @@ This depends on the feature and what sort of impact it might have.
Guidelines:
-1. If the feature meets the requirements for creating a [Change Management](https://about.gitlab.com/handbook/engineering/infrastructure/change-management/#feature-flags-and-the-change-management-process) issue, create a Change Management issue per [criticality guidelines](https://about.gitlab.com/handbook/engineering/infrastructure/change-management/#change-request-workflows).
-1. For simple, low-risk, easily reverted features, proceed and [enable the feature in `#production`](#process).
-1. For features that impact the user experience, consider notifying `#support_gitlab-com` beforehand.
+- Consider notifying `#support_gitlab-com` beforehand. So in case if the feature has any side effects on user experience, they can mitigate and disable the feature flag to reduce some impact.
+- If the feature meets the requirements for creating a [Change Management](https://about.gitlab.com/handbook/engineering/infrastructure/change-management/#feature-flags-and-the-change-management-process) issue, create a Change Management issue per [criticality guidelines](https://about.gitlab.com/handbook/engineering/infrastructure/change-management/#change-request-workflows).
+- For simple, low-risk, easily reverted features, proceed and [enable the feature in `#production`](#process).
#### Process
diff --git a/doc/development/feature_flags/index.md b/doc/development/feature_flags/index.md
index 987ff7c9fe8..86dc4c73062 100644
--- a/doc/development/feature_flags/index.md
+++ b/doc/development/feature_flags/index.md
@@ -535,7 +535,7 @@ to ensure the feature works properly.
When using the testing environment, all feature flags are enabled by default.
WARNING:
-This does not apply to end-to-end (QA) tests, which [do not disable feature flags by default](#end-to-end-qa-tests). There is a different [process for using feature flags in end-to-end tests](../testing_guide/end_to_end/feature_flags.md).
+This does not apply to end-to-end (QA) tests, which [do not enable feature flags by default](#end-to-end-qa-tests). There is a different [process for using feature flags in end-to-end tests](../testing_guide/end_to_end/feature_flags.md).
To disable a feature flag in a test, use the `stub_feature_flags`
helper. For example, to globally disable the `ci_live_trace` feature
diff --git a/doc/development/gemfile.md b/doc/development/gemfile.md
index e071aa4ffd9..5ff1bc7b127 100644
--- a/doc/development/gemfile.md
+++ b/doc/development/gemfile.md
@@ -55,8 +55,10 @@ to a gem, go through these steps:
- For an example, see the [merge request !57805](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57805).
1. Once the gem is stable - we have been using it in production for a
while with few, if any, changes - extract to its own project under
- the `gitlab-org` namespace.
- 1. When creating the project, follow the [instructions for new projects](https://about.gitlab.com/handbook/engineering/#creating-a-new-project).
+ the [`gitlab-org/ruby/gems` namespace](https://gitlab.com/gitlab-org/ruby/gems/).
+
+ - To create this project:
+ 1. Follow the [instructions for new projects](https://about.gitlab.com/handbook/engineering/#creating-a-new-project).
1. Follow the instructions for setting up a [CI/CD configuration](https://about.gitlab.com/handbook/engineering/#cicd-configuration).
1. Follow the instructions for [publishing a project](https://about.gitlab.com/handbook/engineering/#publishing-a-project).
- See [issue
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index fa4fa59e35d..5a7a5a6abcb 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -53,7 +53,7 @@ immediately after the Gitaly one. This allows you to test your changes before
they are merged.
- See [below](#running-tests-with-a-locally-modified-version-of-gitaly) for instructions on running GitLab tests with a modified version of Gitaly.
-- In GDK run `gdk install` and restart `gdk run` (or `gdk run app`) to use a locally modified Gitaly version for development
+- In GDK run `gdk install` and restart GDK using `gdk restart` to use a locally modified Gitaly version for development
### `gitaly-ruby`
diff --git a/doc/development/go_guide/go_upgrade.md b/doc/development/go_guide/go_upgrade.md
index 75a093a55ac..53f2d7d176a 100644
--- a/doc/development/go_guide/go_upgrade.md
+++ b/doc/development/go_guide/go_upgrade.md
@@ -89,10 +89,14 @@ if you need help finding the correct person or labels:
1. Schedule an update with the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit/-/issues):
- Title the issue `Support using Go version <VERSION_NUMBER>`.
- Set the issue as related to every issue created in the previous step.
-1. Schedule one issue per Secure Stage team and add the `devops::secure` label to each:
+1. Schedule one issue per Sec Section team that maintains Go based Security Analyzers and add the `section::sec` label to each:
- [Static Analysis tracker](https://gitlab.com/gitlab-org/gitlab/-/issues).
- [Composition Analysis tracker](https://gitlab.com/gitlab-org/gitlab/-/issues).
- [Container Security tracker](https://gitlab.com/gitlab-org/gitlab/-/issues).
+
+ NOTE:
+ Updates to these Security analyzers should not block upgrades to Charts or Omnibus since
+ the analyzers are built independently as separate container images.
1. Schedule builder updates with Distribution projects:
- Dependency and GitLab Development Kit issues created in previous steps should be set as blockers.
- Each issue should have the title `Support building with Go <VERSION_NUMBER>` and description as noted:
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index 44f8924be04..9bf8b7ef89a 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -364,8 +364,7 @@ JSON format, as all our infrastructure assumes that. When using
[Logrus](https://github.com/sirupsen/logrus) you can turn on structured
logging simply by using the build in [JSON
formatter](https://github.com/sirupsen/logrus#formatters). This follows the
-same logging type we use in our [Ruby
-applications](../logging.md#use-structured-json-logging).
+same logging type we use in our [Ruby applications](../logging.md#use-structured-json-logging).
#### How to use Logrus
@@ -451,6 +450,78 @@ The conventional Secure [analyzer](https://gitlab.com/gitlab-org/security-produc
If the scanner report is small, less than 35 lines, then feel free to [inline the report](https://gitlab.com/gitlab-org/security-products/analyzers/sobelow/-/blob/8bd2428a/convert/convert_test.go#L13-77) rather than use a `testdata` directory.
+#### Test Diffs
+
+The [go-cmp]<https://github.com/google/go-cmp> package should be used when comparing large structs in tests. It makes it possible to output a specific diff where the two structs differ, rather than seeing the whole of both structs printed out in the test logs. Here is a small example:
+
+```golang
+package main
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+type Foo struct {
+ Desc Bar
+ Point Baz
+}
+
+type Bar struct {
+ A string
+ B string
+}
+
+type Baz struct {
+ X int
+ Y int
+}
+
+func TestHelloWorld(t *testing.T) {
+ want := Foo{
+ Desc: Bar{A: "a", B: "b"},
+ Point: Baz{X: 1, Y: 2},
+ }
+
+ got := Foo{
+ Desc: Bar{A: "a", B: "b"},
+ Point: Baz{X: 2, Y: 2},
+ }
+
+ t.Log("reflect comparison:")
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Wrong result. want:\n%v\nGot:\n%v", want, got)
+ }
+
+ t.Log("cmp comparison:")
+ if diff := cmp.Diff(want, got); diff != "" {
+ t.Errorf("Wrong result. (-want +got):\n%s", diff)
+ }
+}
+```
+
+The output demonstrates why `go-cmp` is far superior when comparing large structs. Even though you could spot the difference with this small difference, it quickly gets unwieldy as the data grows.
+
+```plaintext
+ main_test.go:36: reflect comparison:
+ main_test.go:38: Wrong result. want:
+ {{a b} {1 2}}
+ Got:
+ {{a b} {2 2}}
+ main_test.go:41: cmp comparison:
+ main_test.go:43: Wrong result. (-want +got):
+ main.Foo{
+ Desc: {A: "a", B: "b"},
+ Point: main.Baz{
+ - X: 1,
+ + X: 2,
+ Y: 2,
+ },
+ }
+```
+
---
[Return to Development documentation](../index.md).
diff --git a/doc/development/i18n/translation.md b/doc/development/i18n/translation.md
index 34b7f5e8763..04a9f68abec 100644
--- a/doc/development/i18n/translation.md
+++ b/doc/development/i18n/translation.md
@@ -48,10 +48,10 @@ Be sure to check the following guidelines before you translate any strings.
### Namespaced strings
-When an externalized string is prepended with a namespace (for example,
-`s_('OpenedNDaysAgo|Opened')`), the namespace should be removed from the final translation. For
-example, in French, `OpenedNDaysAgo|Opened` is translated to `Ouvert•e`, not
-`OpenedNDaysAgo|Ouvert•e`.
+A namespace precedes the string and is separated from it by a `|` (`namespace|string`). When you see
+a namespace before an externalized string, you should remove the namespace from the final
+translation. For example, in `OpenedNDaysAgo|Opened`, remove `OpenedNDaysAgo|`. If translating to
+French, translate `OpenedNDaysAgo|Opened` to `Ouvert•e`, not `OpenedNDaysAgo|Ouvert•e`.
### Technical terms
@@ -61,6 +61,12 @@ should always be in English are noted in the glossary when using
This helps maintain a logical connection and consistency between tools (for example, a Git client)
and GitLab.
+To find the list of technical terms:
+
+1. Go to [`translate.gitlab.com`](https://translate.gitlab.com).
+1. Select the language to translate.
+1. Select **Glossary**.
+
### Formality
The level of formality used in software varies by language:
diff --git a/doc/development/index.md b/doc/development/index.md
index 3780c986367..fa49d43d46c 100644
--- a/doc/development/index.md
+++ b/doc/development/index.md
@@ -122,7 +122,7 @@ In these cases, use the following workflow:
- [User Experience (UX)](https://about.gitlab.com/handbook/engineering/ux/)
- [Security](https://about.gitlab.com/handbook/engineering/security/)
- [Quality](https://about.gitlab.com/handbook/engineering/quality/)
- - [Engineering Productivity](https://about.gitlab.com/handbook/engineering/quality/engineering-productivity-team/)
+ - [Engineering Productivity](https://about.gitlab.com/handbook/engineering/quality/engineering-productivity/)
- [Infrastructure](https://about.gitlab.com/handbook/engineering/infrastructure/)
- [Technical Writing](https://about.gitlab.com/handbook/engineering/ux/technical-writing/)
@@ -181,6 +181,7 @@ the [reviewer values](https://about.gitlab.com/handbook/engineering/workflow/rev
- [Avoid modules with instance variables](module_with_instance_variables.md), if
possible
- [Guidelines for reusing abstractions](reusing_abstractions.md)
+- [Ruby 3 gotchas](ruby3_gotchas.md)
### Rails Framework related
diff --git a/doc/development/internal_api.md b/doc/development/internal_api.md
index 660d8c60ba8..7790a5e23e6 100644
--- a/doc/development/internal_api.md
+++ b/doc/development/internal_api.md
@@ -1,829 +1,9 @@
---
-stage: Create
-group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
-type: reference, api
+redirect_to: 'internal_api/index.md'
+remove_date: '2022-02-09'
---
-# Internal API **(FREE)**
+This document was moved to [another location](internal_api/index.md).
-The internal API is used by different GitLab components, it can not be
-used by other consumers. This documentation is intended for people
-working on the GitLab codebase.
-
-This documentation does not yet include the internal API used by
-GitLab Pages.
-
-## Adding new endpoints
-
-API endpoints should be externally accessible by default, with proper authentication and authorization.
-Before adding a new internal endpoint, consider if the API would potentially be
-useful to the wider GitLab community and can be made externally accessible.
-
-One reason we might favor internal API endpoints sometimes is when using such an endpoint requires
-internal data that external actors can not have. For example, in the internal Pages API we might use
-a secret token that identifies a request as internal or sign a request with a public key that is
-not available to a wider community.
-
-Another reason to separate something into an internal API is when request to such API endpoint
-should never go through an edge (public) load balancer. This way we can configure different rate
-limiting rules and policies around how the endpoint is being accessed, because we know that only
-internal requests can be made to that endpoint going through an internal load balancer.
-
-## Authentication
-
-These methods are all authenticated using a shared secret. This secret
-is stored in a file at the path configured in `config/gitlab.yml` by
-default this is in the root of the rails app named
-`.gitlab_shell_secret`
-
-To authenticate using that token, clients read the contents of that
-file, and include the token Base64 encoded in a `secret_token` parameter
-or in the `Gitlab-Shared-Secret` header.
-
-NOTE:
-The internal API used by GitLab Pages, and GitLab Kubernetes Agent Server (`kas`) uses JSON Web Token (JWT)
-authentication, which is different from GitLab Shell.
-
-## Git Authentication
-
-This is called by [Gitaly](https://gitlab.com/gitlab-org/gitaly) and
-[GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell) to check access to a
-repository.
-
-- **When called from GitLab Shell**: No changes are passed, and the internal
- API replies with the information needed to pass the request on to Gitaly.
-- **When called from Gitaly in a `pre-receive` hook**: The changes are passed
- and validated to determine if the push is allowed.
-
-Calls are limited to 50 seconds each.
-
-```plaintext
-POST /internal/allowed
-```
-
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:------------|
-| `key_id` | string | no | ID of the SSH-key used to connect to GitLab Shell |
-| `username` | string | no | Username from the certificate used to connect to GitLab Shell |
-| `project` | string | no (if `gl_repository` is passed) | Path to the project |
-| `gl_repository` | string | no (if `project` is passed) | Repository identifier, such as `project-7` |
-| `protocol` | string | yes | SSH when called from GitLab Shell, HTTP or SSH when called from Gitaly |
-| `action` | string | yes | Git command being run (`git-upload-pack`, `git-receive-pack`, `git-upload-archive`) |
-| `changes` | string | yes | `<oldrev> <newrev> <refname>` when called from Gitaly, the magic string `_any` when called from GitLab Shell |
-| `check_ip` | string | no | IP address from which call to GitLab Shell was made |
-
-Example request:
-
-```shell
-curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded token>" \
- --data "key_id=11&project=gnuwget/wget2&action=git-upload-pack&protocol=ssh" \
- "http://localhost:3001/api/v4/internal/allowed"
-```
-
-Example response:
-
-```json
-{
- "status": true,
- "gl_repository": "project-3",
- "gl_project_path": "gnuwget/wget2",
- "gl_id": "user-1",
- "gl_username": "root",
- "git_config_options": [],
- "gitaly": {
- "repository": {
- "storage_name": "default",
- "relative_path": "@hashed/4e/07/4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce.git",
- "git_object_directory": "",
- "git_alternate_object_directories": [],
- "gl_repository": "project-3",
- "gl_project_path": "gnuwget/wget2"
- },
- "address": "unix:/Users/bvl/repos/gitlab/gitaly.socket",
- "token": null
- },
- "gl_console_messages": []
-}
-```
-
-### Known consumers
-
-- Gitaly
-- GitLab Shell
-
-## LFS Authentication
-
-This is the endpoint that gets called from GitLab Shell to provide
-information for LFS clients when the repository is accessed over SSH.
-
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:------------|
-| `key_id` | string | no | ID of the SSH-key used to connect to GitLab Shell |
-| `username`| string | no | Username from the certificate used to connect to GitLab Shell |
-| `project` | string | no | Path to the project |
-
-Example request:
-
-```shell
-curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded token>" \
- --data "key_id=11&project=gnuwget/wget2" "http://localhost:3001/api/v4/internal/lfs_authenticate"
-```
-
-```json
-{
- "username": "root",
- "lfs_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7ImFjdG9yIjoicm9vdCJ9LCJqdGkiOiIyYWJhZDcxZC0xNDFlLTQ2NGUtOTZlMi1mODllYWRiMGVmZTYiLCJpYXQiOjE1NzAxMTc2NzYsIm5iZiI6MTU3MDExNzY3MSwiZXhwIjoxNTcwMTE5NDc2fQ.g7atlBw1QMY7QEBVPE0LZ8ZlKtaRzaMRmNn41r2YITM",
- "repository_http_path": "http://localhost:3001/gnuwget/wget2.git",
- "expires_in": 1800
-}
-```
-
-### Known consumers
-
-- GitLab Shell
-
-## Authorized Keys Check
-
-This endpoint is called by the GitLab Shell authorized keys
-check. Which is called by OpenSSH for [fast SSH key
-lookup](../administration/operations/fast_ssh_key_lookup.md).
-
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:------------|
-| `key` | string | yes | SSH key as passed by OpenSSH to GitLab Shell |
-
-```plaintext
-GET /internal/authorized_keys
-```
-
-Example request:
-
-```shell
-curl --request GET --header "Gitlab-Shared-Secret: <Base64 encoded secret>" "http://localhost:3001/api/v4/internal/authorized_keys?key=<key as passed by OpenSSH>"
-```
-
-Example response:
-
-```json
-{
- "id": 11,
- "title": "admin@example.com",
- "key": "ssh-rsa ...",
- "created_at": "2019-06-27T15:29:02.219Z"
-}
-```
-
-### Known consumers
-
-- GitLab Shell
-
-## Get user for user ID or key
-
-This endpoint is used when a user performs `ssh git@gitlab.com`. It
-discovers the user associated with an SSH key.
-
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:------------|
-| `key_id` | integer | no | The ID of the SSH key used as found in the authorized-keys file or through the `/authorized_keys` check |
-| `username` | string | no | Username of the user being looked up, used by GitLab Shell when authenticating using a certificate |
-
-```plaintext
-GET /internal/discover
-```
-
-Example request:
-
-```shell
-curl --request GET --header "Gitlab-Shared-Secret: <Base64 encoded secret>" "http://localhost:3001/api/v4/internal/discover?key_id=7"
-```
-
-Example response:
-
-```json
-{
- "id": 7,
- "name": "Dede Eichmann",
- "username": "rubi"
-}
-```
-
-### Known consumers
-
-- GitLab Shell
-
-## Instance information
-
-This gets some generic information about the instance. This is used
-by Geo nodes to get information about each other.
-
-```plaintext
-GET /internal/check
-```
-
-Example request:
-
-```shell
-curl --request GET --header "Gitlab-Shared-Secret: <Base64 encoded secret>" "http://localhost:3001/api/v4/internal/check"
-```
-
-Example response:
-
-```json
-{
- "api_version": "v4",
- "gitlab_version": "12.3.0-pre",
- "gitlab_rev": "d69c988e6a6",
- "redis": true
-}
-```
-
-### Known consumers
-
-- GitLab Geo
-- GitLab Shell's `bin/check`
-- Gitaly
-
-## Get new 2FA recovery codes using an SSH key
-
-This is called from GitLab Shell and allows users to get new 2FA
-recovery codes based on their SSH key.
-
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:------------|
-| `key_id` | integer | no | The ID of the SSH key used as found in the authorized-keys file or through the `/authorized_keys` check |
-| `user_id` | integer | no | **Deprecated** User_id for which to generate new recovery codes |
-
-```plaintext
-GET /internal/two_factor_recovery_codes
-```
-
-Example request:
-
-```shell
-curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
- --data "key_id=7" "http://localhost:3001/api/v4/internal/two_factor_recovery_codes"
-```
-
-Example response:
-
-```json
-{
- "success": true,
- "recovery_codes": [
- "d93ee7037944afd5",
- "19d7b84862de93dd",
- "1e8c52169195bf71",
- "be50444dddb7ca84",
- "26048c77d161d5b7",
- "482d5c03d1628c47",
- "d2c695e309ce7679",
- "dfb4748afc4f12a7",
- "0e5f53d1399d7979",
- "af04d5622153b020"
- ]
-}
-```
-
-### Known consumers
-
-- GitLab Shell
-
-## Get new personal access-token
-
-This is called from GitLab Shell and allows users to generate a new
-personal access token.
-
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:------------|
-| `name` | string | yes | The name of the new token |
-| `scopes` | string array | yes | The authorization scopes for the new token, these must be valid token scopes |
-| `expires_at` | string | no | The expiry date for the new token |
-| `key_id` | integer | no | The ID of the SSH key used as found in the authorized-keys file or through the `/authorized_keys` check |
-| `user_id` | integer | no | User\_id for which to generate the new token |
-
-```plaintext
-POST /internal/personal_access_token
-```
-
-Example request:
-
-```shell
-curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
- --data "user_id=29&name=mytokenname&scopes[]=read_user&scopes[]=read_repository&expires_at=2020-07-24" \
- "http://localhost:3001/api/v4/internal/personal_access_token"
-```
-
-Example response:
-
-```json
-{
- "success": true,
- "token": "Hf_79B288hRv_3-TSD1R",
- "scopes": ["read_user","read_repository"],
- "expires_at": "2020-07-24"
-}
-```
-
-### Known consumers
-
-- GitLab Shell
-
-## Incrementing counter on pre-receive
-
-This is called from the Gitaly hooks increasing the reference counter
-for a push that might be accepted.
-
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:------------|
-| `gl_repository` | string | yes | repository identifier for the repository receiving the push |
-
-```plaintext
-POST /internal/pre_receive
-```
-
-Example request:
-
-```shell
-curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
- --data "gl_repository=project-7" "http://localhost:3001/api/v4/internal/pre_receive"
-```
-
-Example response:
-
-```json
-{
- "reference_counter_increased": true
-}
-```
-
-## PostReceive
-
-Called from Gitaly after a receiving a push. This triggers the
-`PostReceive`-worker in Sidekiq, processes the passed push options and
-builds the response including messages that need to be displayed to
-the user.
-
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:------------|
-| `identifier` | string | yes | `user-[id]` or `key-[id]` Identifying the user performing the push |
-| `gl_repository` | string | yes | identifier of the repository being pushed to |
-| `push_options` | string array | no | array of push options |
-| `changes` | string | no | refs to be updated in the push in the format `oldrev newrev refname\n`. |
-
-```plaintext
-POST /internal/post_receive
-```
-
-Example Request:
-
-```shell
-curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
- --data "gl_repository=project-7" --data "identifier=user-1" \
- --data "changes=0000000000000000000000000000000000000000 fd9e76b9136bdd9fe217061b497745792fe5a5ee gh-pages\n" \
- "http://localhost:3001/api/v4/internal/post_receive"
-```
-
-Example response:
-
-```json
-{
- "messages": [
- {
- "message": "Hello from post-receive",
- "type": "alert"
- }
- ],
- "reference_counter_decreased": true
-}
-```
-
-## Kubernetes agent endpoints
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41045) in GitLab 13.4.
-> - This feature is not deployed on GitLab.com
-> - It's not recommended for production use.
-
-The following endpoints are used by the GitLab Kubernetes Agent Server (`kas`)
-for various purposes.
-
-These endpoints are all authenticated using JWT. The JWT secret is stored in a file
-specified in `config/gitlab.yml`. By default, the location is in the root of the
-GitLab Rails app in a file called `.gitlab_kas_secret`.
-
-WARNING:
-The Kubernetes agent is under development and is not recommended for production use.
-
-### Kubernetes agent information
-
-Called from GitLab Kubernetes Agent Server (`kas`) to retrieve agent
-information for the given agent token. This returns the Gitaly connection
-information for the agent's project in order for `kas` to fetch and update
-the agent's configuration.
-
-```plaintext
-GET /internal/kubernetes/agent_info
-```
-
-Example Request:
-
-```shell
-curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" \
- --header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/agent_info"
-```
-
-### Kubernetes agent project information
-
-Called from GitLab Kubernetes Agent Server (`kas`) to retrieve project
-information for the given agent token. This returns the Gitaly
-connection for the requested project. GitLab `kas` uses this to configure
-the agent to fetch Kubernetes resources from the project repository to
-sync.
-
-Only public projects are supported. For private projects, the ability for the
-agent to be authorized is [not yet implemented](https://gitlab.com/gitlab-org/gitlab/-/issues/220912).
-
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../api/index.md#namespaced-path-encoding) |
-
-```plaintext
-GET /internal/kubernetes/project_info
-```
-
-Example Request:
-
-```shell
-curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" \
- --header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/project_info?id=7"
-```
-
-### Kubernetes agent usage metrics
-
-Called from GitLab Kubernetes Agent Server (`kas`) to increase the usage
-metric counters.
-
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:------------|
-| `gitops_sync_count` | integer| no | The number to increase the `gitops_sync_count` counter by |
-| `k8s_api_proxy_request_count` | integer| no | The number to increase the `k8s_api_proxy_request_count` counter by |
-
-```plaintext
-POST /internal/kubernetes/usage_metrics
-```
-
-Example Request:
-
-```shell
-curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Content-Type: application/json" \
- --data '{"gitops_sync_count":1}' "http://localhost:3000/api/v4/internal/kubernetes/usage_metrics"
-```
-
-### Kubernetes agent alert metrics
-
-Called from GitLab Kubernetes Agent Server (KAS) to save alerts derived from Cilium on Kubernetes
-Cluster.
-
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:------------|
-| `alert` | Hash | yes | Alerts detail. Same format as [3rd party alert](../operations/incident_management/integrations.md#customize-the-alert-payload-outside-of-gitlab). |
-
-```plaintext
-POST internal/kubernetes/modules/cilium_alert
-```
-
-Example Request:
-
-```shell
-curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" \
- --header "Authorization: Bearer <agent token>" --header "Content-Type: application/json" \
- --data '"{\"alert\":{\"title\":\"minimal\",\"message\":\"network problem\",\"evalMatches\":[{\"value\":1,\"metric\":\"Count\",\"tags\":{}}]}}"' \
- "http://localhost:3000/api/v4/internal/kubernetes/modules/cilium_alert"
-```
-
-### Create Starboard vulnerability
-
-Called from the GitLab Kubernetes Agent Server (`kas`) to create a security vulnerability
-from a Starboard vulnerability report. This request is idempotent. Multiple requests with the same data
-create a single vulnerability.
-
-| Attribute | Type | Required | Description |
-|:----------------|:-------|:---------|:------------|
-| `vulnerability` | Hash | yes | Vulnerability data matching the security report schema [`vulnerability` field](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/src/security-report-format.json). |
-| `scanner` | Hash | yes | Scanner data matching the security report schema [`scanner` field](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/src/security-report-format.json). |
-
-```plaintext
-PUT internal/kubernetes/modules/starboard_vulnerability
-```
-
-Example Request:
-
-```shell
-curl --request PUT --header "Gitlab-Kas-Api-Request: <JWT token>" \
- --header "Authorization: Bearer <agent token>" --header "Content-Type: application/json" \
- --url "http://localhost:3000/api/v4/internal/kubernetes/modules/starboard_vulnerability" \
- --data '{
- "vulnerability": {
- "name": "CVE-123-4567 in libc",
- "severity": "high",
- "confidence": "unknown",
- "location": {
- "kubernetes_resource": {
- "namespace": "production",
- "kind": "deployment",
- "name": "nginx",
- "container": "nginx"
- }
- },
- "identifiers": [
- {
- "type": "cve",
- "name": "CVE-123-4567",
- "value": "CVE-123-4567"
- }
- ]
- },
- "scanner": {
- "id": "starboard_trivy",
- "name": "Trivy (via Starboard Operator)",
- "vendor": "GitLab"
- }
-}'
-```
-
-## Subscriptions
-
-The subscriptions endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)
-in order to apply subscriptions including trials, and add-on purchases, for personal namespaces or top-level groups within GitLab.com.
-
-### Creating a subscription
-
-Use a POST to create a subscription.
-
-```plaintext
-POST /namespaces/:id/gitlab_subscription
-```
-
-| Attribute | Type | Required | Description |
-|:------------|:--------|:---------|:------------|
-| `start_date` | date | yes | Start date of subscription |
-| `end_date` | date | no | End date of subscription |
-| `plan_code` | string | no | Subscription tier code |
-| `seats` | integer | no | Number of seats in subscription |
-| `max_seats_used` | integer | no | Highest number of active users in the last month |
-| `auto_renew` | boolean | no | Whether subscription auto-renews on end date |
-| `trial` | boolean | no | Whether subscription is a trial |
-| `trial_starts_on` | date | no | Start date of trial |
-| `trial_ends_on` | date | no | End date of trial |
-
-Example request:
-
-```shell
-curl --request POST --header "TOKEN: <admin_access_token>" "https://gitlab.com/api/v4/namespaces/1234/gitlab_subscription?start_date="2020-07-15"&plan="premium"&seats=10"
-```
-
-Example response:
-
-```json
-{
- "plan": {
- "code":"premium",
- "name":"premium",
- "trial":false,
- "auto_renew":null,
- "upgradable":false
- },
- "usage": {
- "seats_in_subscription":10,
- "seats_in_use":1,
- "max_seats_used":0,
- "seats_owed":0
- },
- "billing": {
- "subscription_start_date":"2020-07-15",
- "subscription_end_date":null,
- "trial_ends_on":null
- }
-}
-```
-
-### Updating a subscription
-
-Use a PUT command to update an existing subscription.
-
-```plaintext
-PUT /namespaces/:id/gitlab_subscription
-```
-
-| Attribute | Type | Required | Description |
-|:------------|:--------|:---------|:------------|
-| `start_date` | date | no | Start date of subscription |
-| `end_date` | date | no | End date of subscription |
-| `plan_code` | string | no | Subscription tier code |
-| `seats` | integer | no | Number of seats in subscription |
-| `max_seats_used` | integer | no | Highest number of active users in the last month |
-| `auto_renew` | boolean | no | Whether subscription auto-renews on end date |
-| `trial` | boolean | no | Whether subscription is a trial |
-| `trial_starts_on` | date | no | Start date of trial. Required if trial is true. |
-| `trial_ends_on` | date | no | End date of trial |
-
-Example request:
-
-```shell
-curl --request PUT --header "TOKEN: <admin_access_token>" "https://gitlab.com/api/v4/namespaces/1234/gitlab_subscription?max_seats_used=0"
-```
-
-Example response:
-
-```json
-{
- "plan": {
- "code":"premium",
- "name":"premium",
- "trial":false,
- "auto_renew":null,
- "upgradable":false
- },
- "usage": {
- "seats_in_subscription":80,
- "seats_in_use":82,
- "max_seats_used":0,
- "seats_owed":2
- },
- "billing": {
- "subscription_start_date":"2020-07-15",
- "subscription_end_date":"2021-07-15",
- "trial_ends_on":null
- }
-}
-```
-
-### Retrieving a subscription
-
-Use a GET command to view an existing subscription.
-
-```plaintext
-GET /namespaces/:id/gitlab_subscription
-```
-
-Example request:
-
-```shell
-curl --header "TOKEN: <admin_access_token>" "https://gitlab.com/api/v4/namespaces/1234/gitlab_subscription"
-```
-
-Example response:
-
-```json
-{
- "plan": {
- "code":"premium",
- "name":"premium",
- "trial":false,
- "auto_renew":null,
- "upgradable":false
- },
- "usage": {
- "seats_in_subscription":80,
- "seats_in_use":82,
- "max_seats_used":82,
- "seats_owed":2
- },
- "billing": {
- "subscription_start_date":"2020-07-15",
- "subscription_end_date":"2021-07-15",
- "trial_ends_on":null
- }
-}
-```
-
-### Known consumers
-
-- CustomersDot
-
-## CI minute provisioning
-
-The CI Minute endpoints are used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)
-to apply additional packs of CI minutes, for personal namespaces or top-level groups within GitLab.com.
-
-### Creating an additional pack
-
-Use a POST to create additional packs.
-
-```plaintext
-POST /namespaces/:id/minutes
-```
-
-| Attribute | Type | Required | Description |
-|:------------|:--------|:---------|:------------|
-| `packs` | array | yes | An array of purchased minutes packs |
-| `packs[expires_at]` | date | yes | Expiry date of the purchased pack|
-| `packs[number_of_minutes]` | integer | yes | Number of additional minutes |
-| `packs[purchase_xid]` | string | yes | The unique ID of the purchase |
-
-Example request:
-
-```shell
-curl --request POST \
- --url "http://localhost:3000/api/v4/namespaces/123/minutes" \
- --header 'Content-Type: application/json' \
- --header 'PRIVATE-TOKEN: <admin access token>' \
- --data '{
- "packs": [
- {
- "number_of_minutes": 10000,
- "expires_at": "2022-01-01",
- "purchase_xid": "46952fe69bebc1a4de10b2b4ff439d0c"
- }
- ]
- }'
-```
-
-Example response:
-
-```json
-[
- {
- "namespace_id": 123,
- "expires_at": "2022-01-01",
- "number_of_minutes": 10000,
- "purchase_xid": "46952fe69bebc1a4de10b2b4ff439d0c"
- }
-]
-```
-
-### Moving additional packs
-
-Use a PATCH to move additional packs from one namespace to another.
-
-```plaintext
-PATCH /namespaces/:id/minutes/move/:target_id
-```
-
-| Attribute | Type | Required | Description |
-|:------------|:--------|:---------|:------------|
-| `id` | string | yes | The ID of the namespace to transfer packs from |
-| `target_id` | string | yes | The ID of the target namespace to transfer the packs to |
-
-Example request:
-
-```shell
-curl --request PATCH \
- --url "http://localhost:3000/api/v4/namespaces/123/minutes/move/321" \
- --header 'PRIVATE-TOKEN: <admin access token>'
-```
-
-Example response:
-
-```json
-{
- "message": "202 Accepted"
-}
-```
-
-### Known consumers
-
-- CustomersDot
-
-## Upcoming reconciliations
-
-The `upcoming_reconciliations` endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)
-to update upcoming reconciliations for namespaces.
-
-### Updating `upcoming_reconciliations`
-
-Use a PUT command to update `upcoming_reconciliations`.
-
-```plaintext
-PUT /internal/upcoming_reconciliations
-```
-
-| Attribute | Type | Required | Description |
-|:-------------------|:-----------|:---------|:------------|
-| `upcoming_reconciliations` | array | yes | Array of upcoming reconciliations |
-
-Each array element contains:
-
-| Attribute | Type | Required | Description |
-|:-------------------|:-----------|:---------|:------------|
-| `namespace_id` | integer | yes | ID of the namespace to be reconciled |
-| `next_reconciliation_date` | date | yes | Date when next reconciliation will happen |
-| `display_alert_from` | date | yes | Start date to display alert of upcoming reconciliation |
-
-Example request:
-
-```shell
-curl --request PUT --header "PRIVATE-TOKEN: <admin_access_token>" --header "Content-Type: application/json" \
- --data '{"upcoming_reconciliations": [{"namespace_id": 127, "next_reconciliation_date": "13 Jun 2021", "display_alert_from": "06 Jun 2021"}, {"namespace_id": 129, "next_reconciliation_date": "12 Jun 2021", "display_alert_from": "05 Jun 2021"}]}' \
- "https://gitlab.com/api/v4/internal/upcoming_reconciliations"
-```
-
-Example response:
-
-```plaintext
-200
-```
-
-### Known consumers
-
-- CustomersDot
+<!-- This redirect file can be deleted after <2022-02-09>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md
new file mode 100644
index 00000000000..0fe9a5362cf
--- /dev/null
+++ b/doc/development/internal_api/index.md
@@ -0,0 +1,831 @@
+---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+type: reference, api
+---
+
+# Internal API **(FREE)**
+
+The internal API is used by different GitLab components, it can not be
+used by other consumers. This documentation is intended for people
+working on the GitLab codebase.
+
+This documentation does not yet include the internal API used by
+GitLab Pages.
+
+## Adding new endpoints
+
+API endpoints should be externally accessible by default, with proper authentication and authorization.
+Before adding a new internal endpoint, consider if the API would potentially be
+useful to the wider GitLab community and can be made externally accessible.
+
+One reason we might favor internal API endpoints sometimes is when using such an endpoint requires
+internal data that external actors can not have. For example, in the internal Pages API we might use
+a secret token that identifies a request as internal or sign a request with a public key that is
+not available to a wider community.
+
+Another reason to separate something into an internal API is when request to such API endpoint
+should never go through an edge (public) load balancer. This way we can configure different rate
+limiting rules and policies around how the endpoint is being accessed, because we know that only
+internal requests can be made to that endpoint going through an internal load balancer.
+
+## Authentication
+
+These methods are all authenticated using a shared secret. This secret
+is stored in a file at the path configured in `config/gitlab.yml` by
+default this is in the root of the rails app named
+`.gitlab_shell_secret`
+
+To authenticate using that token, clients read the contents of that
+file, and include the token Base64 encoded in a `secret_token` parameter
+or in the `Gitlab-Shared-Secret` header.
+
+NOTE:
+The internal API used by GitLab Pages, and GitLab Kubernetes Agent Server (`kas`) uses JSON Web Token (JWT)
+authentication, which is different from GitLab Shell.
+
+## Git Authentication
+
+This is called by [Gitaly](https://gitlab.com/gitlab-org/gitaly) and
+[GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell) to check access to a
+repository.
+
+- **When called from GitLab Shell**: No changes are passed, and the internal
+ API replies with the information needed to pass the request on to Gitaly.
+- **When called from Gitaly in a `pre-receive` hook**: The changes are passed
+ and validated to determine if the push is allowed.
+
+Calls are limited to 50 seconds each.
+
+This endpoint is covered in more detail on [its own page](internal_api_allowed.md), due to the scope of what it covers.
+
+```plaintext
+POST /internal/allowed
+```
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `key_id` | string | no | ID of the SSH-key used to connect to GitLab Shell |
+| `username` | string | no | Username from the certificate used to connect to GitLab Shell |
+| `project` | string | no (if `gl_repository` is passed) | Path to the project |
+| `gl_repository` | string | no (if `project` is passed) | Repository identifier, such as `project-7` |
+| `protocol` | string | yes | SSH when called from GitLab Shell, HTTP or SSH when called from Gitaly |
+| `action` | string | yes | Git command being run (`git-upload-pack`, `git-receive-pack`, `git-upload-archive`) |
+| `changes` | string | yes | `<oldrev> <newrev> <refname>` when called from Gitaly, the magic string `_any` when called from GitLab Shell |
+| `check_ip` | string | no | IP address from which call to GitLab Shell was made |
+
+Example request:
+
+```shell
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded token>" \
+ --data "key_id=11&project=gnuwget/wget2&action=git-upload-pack&protocol=ssh" \
+ "http://localhost:3001/api/v4/internal/allowed"
+```
+
+Example response:
+
+```json
+{
+ "status": true,
+ "gl_repository": "project-3",
+ "gl_project_path": "gnuwget/wget2",
+ "gl_id": "user-1",
+ "gl_username": "root",
+ "git_config_options": [],
+ "gitaly": {
+ "repository": {
+ "storage_name": "default",
+ "relative_path": "@hashed/4e/07/4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce.git",
+ "git_object_directory": "",
+ "git_alternate_object_directories": [],
+ "gl_repository": "project-3",
+ "gl_project_path": "gnuwget/wget2"
+ },
+ "address": "unix:/Users/bvl/repos/gitlab/gitaly.socket",
+ "token": null
+ },
+ "gl_console_messages": []
+}
+```
+
+### Known consumers
+
+- Gitaly
+- GitLab Shell
+
+## LFS Authentication
+
+This is the endpoint that gets called from GitLab Shell to provide
+information for LFS clients when the repository is accessed over SSH.
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `key_id` | string | no | ID of the SSH-key used to connect to GitLab Shell |
+| `username`| string | no | Username from the certificate used to connect to GitLab Shell |
+| `project` | string | no | Path to the project |
+
+Example request:
+
+```shell
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded token>" \
+ --data "key_id=11&project=gnuwget/wget2" "http://localhost:3001/api/v4/internal/lfs_authenticate"
+```
+
+```json
+{
+ "username": "root",
+ "lfs_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7ImFjdG9yIjoicm9vdCJ9LCJqdGkiOiIyYWJhZDcxZC0xNDFlLTQ2NGUtOTZlMi1mODllYWRiMGVmZTYiLCJpYXQiOjE1NzAxMTc2NzYsIm5iZiI6MTU3MDExNzY3MSwiZXhwIjoxNTcwMTE5NDc2fQ.g7atlBw1QMY7QEBVPE0LZ8ZlKtaRzaMRmNn41r2YITM",
+ "repository_http_path": "http://localhost:3001/gnuwget/wget2.git",
+ "expires_in": 1800
+}
+```
+
+### Known consumers
+
+- GitLab Shell
+
+## Authorized Keys Check
+
+This endpoint is called by the GitLab Shell authorized keys
+check. Which is called by OpenSSH for [fast SSH key
+lookup](../../administration/operations/fast_ssh_key_lookup.md).
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `key` | string | yes | SSH key as passed by OpenSSH to GitLab Shell |
+
+```plaintext
+GET /internal/authorized_keys
+```
+
+Example request:
+
+```shell
+curl --request GET --header "Gitlab-Shared-Secret: <Base64 encoded secret>" "http://localhost:3001/api/v4/internal/authorized_keys?key=<key as passed by OpenSSH>"
+```
+
+Example response:
+
+```json
+{
+ "id": 11,
+ "title": "admin@example.com",
+ "key": "ssh-rsa ...",
+ "created_at": "2019-06-27T15:29:02.219Z"
+}
+```
+
+### Known consumers
+
+- GitLab Shell
+
+## Get user for user ID or key
+
+This endpoint is used when a user performs `ssh git@gitlab.com`. It
+discovers the user associated with an SSH key.
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `key_id` | integer | no | The ID of the SSH key used as found in the authorized-keys file or through the `/authorized_keys` check |
+| `username` | string | no | Username of the user being looked up, used by GitLab Shell when authenticating using a certificate |
+
+```plaintext
+GET /internal/discover
+```
+
+Example request:
+
+```shell
+curl --request GET --header "Gitlab-Shared-Secret: <Base64 encoded secret>" "http://localhost:3001/api/v4/internal/discover?key_id=7"
+```
+
+Example response:
+
+```json
+{
+ "id": 7,
+ "name": "Dede Eichmann",
+ "username": "rubi"
+}
+```
+
+### Known consumers
+
+- GitLab Shell
+
+## Instance information
+
+This gets some generic information about the instance. This is used
+by Geo nodes to get information about each other.
+
+```plaintext
+GET /internal/check
+```
+
+Example request:
+
+```shell
+curl --request GET --header "Gitlab-Shared-Secret: <Base64 encoded secret>" "http://localhost:3001/api/v4/internal/check"
+```
+
+Example response:
+
+```json
+{
+ "api_version": "v4",
+ "gitlab_version": "12.3.0-pre",
+ "gitlab_rev": "d69c988e6a6",
+ "redis": true
+}
+```
+
+### Known consumers
+
+- GitLab Geo
+- GitLab Shell's `bin/check`
+- Gitaly
+
+## Get new 2FA recovery codes using an SSH key
+
+This is called from GitLab Shell and allows users to get new 2FA
+recovery codes based on their SSH key.
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `key_id` | integer | no | The ID of the SSH key used as found in the authorized-keys file or through the `/authorized_keys` check |
+| `user_id` | integer | no | **Deprecated** User_id for which to generate new recovery codes |
+
+```plaintext
+GET /internal/two_factor_recovery_codes
+```
+
+Example request:
+
+```shell
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
+ --data "key_id=7" "http://localhost:3001/api/v4/internal/two_factor_recovery_codes"
+```
+
+Example response:
+
+```json
+{
+ "success": true,
+ "recovery_codes": [
+ "d93ee7037944afd5",
+ "19d7b84862de93dd",
+ "1e8c52169195bf71",
+ "be50444dddb7ca84",
+ "26048c77d161d5b7",
+ "482d5c03d1628c47",
+ "d2c695e309ce7679",
+ "dfb4748afc4f12a7",
+ "0e5f53d1399d7979",
+ "af04d5622153b020"
+ ]
+}
+```
+
+### Known consumers
+
+- GitLab Shell
+
+## Get new personal access-token
+
+This is called from GitLab Shell and allows users to generate a new
+personal access token.
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `name` | string | yes | The name of the new token |
+| `scopes` | string array | yes | The authorization scopes for the new token, these must be valid token scopes |
+| `expires_at` | string | no | The expiry date for the new token |
+| `key_id` | integer | no | The ID of the SSH key used as found in the authorized-keys file or through the `/authorized_keys` check |
+| `user_id` | integer | no | User ID for which to generate the new token |
+
+```plaintext
+POST /internal/personal_access_token
+```
+
+Example request:
+
+```shell
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
+ --data "user_id=29&name=mytokenname&scopes[]=read_user&scopes[]=read_repository&expires_at=2020-07-24" \
+ "http://localhost:3001/api/v4/internal/personal_access_token"
+```
+
+Example response:
+
+```json
+{
+ "success": true,
+ "token": "Hf_79B288hRv_3-TSD1R",
+ "scopes": ["read_user","read_repository"],
+ "expires_at": "2020-07-24"
+}
+```
+
+### Known consumers
+
+- GitLab Shell
+
+## Incrementing counter on pre-receive
+
+This is called from the Gitaly hooks increasing the reference counter
+for a push that might be accepted.
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `gl_repository` | string | yes | repository identifier for the repository receiving the push |
+
+```plaintext
+POST /internal/pre_receive
+```
+
+Example request:
+
+```shell
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
+ --data "gl_repository=project-7" "http://localhost:3001/api/v4/internal/pre_receive"
+```
+
+Example response:
+
+```json
+{
+ "reference_counter_increased": true
+}
+```
+
+## PostReceive
+
+Called from Gitaly after a receiving a push. This triggers the
+`PostReceive`-worker in Sidekiq, processes the passed push options and
+builds the response including messages that need to be displayed to
+the user.
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `identifier` | string | yes | `user-[id]` or `key-[id]` Identifying the user performing the push |
+| `gl_repository` | string | yes | identifier of the repository being pushed to |
+| `push_options` | string array | no | array of push options |
+| `changes` | string | no | refs to be updated in the push in the format `oldrev newrev refname\n`. |
+
+```plaintext
+POST /internal/post_receive
+```
+
+Example Request:
+
+```shell
+curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded secret>" \
+ --data "gl_repository=project-7" --data "identifier=user-1" \
+ --data "changes=0000000000000000000000000000000000000000 fd9e76b9136bdd9fe217061b497745792fe5a5ee gh-pages\n" \
+ "http://localhost:3001/api/v4/internal/post_receive"
+```
+
+Example response:
+
+```json
+{
+ "messages": [
+ {
+ "message": "Hello from post-receive",
+ "type": "alert"
+ }
+ ],
+ "reference_counter_decreased": true
+}
+```
+
+## Kubernetes agent endpoints
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41045) in GitLab 13.4.
+> - This feature is not deployed on GitLab.com
+> - It's not recommended for production use.
+
+The following endpoints are used by the GitLab Kubernetes Agent Server (`kas`)
+for various purposes.
+
+These endpoints are all authenticated using JWT. The JWT secret is stored in a file
+specified in `config/gitlab.yml`. By default, the location is in the root of the
+GitLab Rails app in a file called `.gitlab_kas_secret`.
+
+WARNING:
+The Kubernetes agent is under development and is not recommended for production use.
+
+### Kubernetes agent information
+
+Called from GitLab Kubernetes Agent Server (`kas`) to retrieve agent
+information for the given agent token. This returns the Gitaly connection
+information for the agent's project in order for `kas` to fetch and update
+the agent's configuration.
+
+```plaintext
+GET /internal/kubernetes/agent_info
+```
+
+Example Request:
+
+```shell
+curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" \
+ --header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/agent_info"
+```
+
+### Kubernetes agent project information
+
+Called from GitLab Kubernetes Agent Server (`kas`) to retrieve project
+information for the given agent token. This returns the Gitaly
+connection for the requested project. GitLab `kas` uses this to configure
+the agent to fetch Kubernetes resources from the project repository to
+sync.
+
+Only public projects are supported. For private projects, the ability for the
+agent to be authorized is [not yet implemented](https://gitlab.com/gitlab-org/gitlab/-/issues/220912).
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../../api/index.md#namespaced-path-encoding) |
+
+```plaintext
+GET /internal/kubernetes/project_info
+```
+
+Example Request:
+
+```shell
+curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" \
+ --header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/project_info?id=7"
+```
+
+### Kubernetes agent usage metrics
+
+Called from GitLab Kubernetes Agent Server (`kas`) to increase the usage
+metric counters.
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `gitops_sync_count` | integer| no | The number to increase the `gitops_sync_count` counter by |
+| `k8s_api_proxy_request_count` | integer| no | The number to increase the `k8s_api_proxy_request_count` counter by |
+
+```plaintext
+POST /internal/kubernetes/usage_metrics
+```
+
+Example Request:
+
+```shell
+curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Content-Type: application/json" \
+ --data '{"gitops_sync_count":1}' "http://localhost:3000/api/v4/internal/kubernetes/usage_metrics"
+```
+
+### Kubernetes agent alert metrics
+
+Called from GitLab Kubernetes Agent Server (KAS) to save alerts derived from Cilium on Kubernetes
+Cluster.
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `alert` | Hash | yes | Alerts detail. Same format as [3rd party alert](../../operations/incident_management/integrations.md#customize-the-alert-payload-outside-of-gitlab). |
+
+```plaintext
+POST internal/kubernetes/modules/cilium_alert
+```
+
+Example Request:
+
+```shell
+curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" \
+ --header "Authorization: Bearer <agent token>" --header "Content-Type: application/json" \
+ --data '"{\"alert\":{\"title\":\"minimal\",\"message\":\"network problem\",\"evalMatches\":[{\"value\":1,\"metric\":\"Count\",\"tags\":{}}]}}"' \
+ "http://localhost:3000/api/v4/internal/kubernetes/modules/cilium_alert"
+```
+
+### Create Starboard vulnerability
+
+Called from the GitLab Kubernetes Agent Server (`kas`) to create a security vulnerability
+from a Starboard vulnerability report. This request is idempotent. Multiple requests with the same data
+create a single vulnerability.
+
+| Attribute | Type | Required | Description |
+|:----------------|:-------|:---------|:------------|
+| `vulnerability` | Hash | yes | Vulnerability data matching the security report schema [`vulnerability` field](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/src/security-report-format.json). |
+| `scanner` | Hash | yes | Scanner data matching the security report schema [`scanner` field](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/src/security-report-format.json). |
+
+```plaintext
+PUT internal/kubernetes/modules/starboard_vulnerability
+```
+
+Example Request:
+
+```shell
+curl --request PUT --header "Gitlab-Kas-Api-Request: <JWT token>" \
+ --header "Authorization: Bearer <agent token>" --header "Content-Type: application/json" \
+ --url "http://localhost:3000/api/v4/internal/kubernetes/modules/starboard_vulnerability" \
+ --data '{
+ "vulnerability": {
+ "name": "CVE-123-4567 in libc",
+ "severity": "high",
+ "confidence": "unknown",
+ "location": {
+ "kubernetes_resource": {
+ "namespace": "production",
+ "kind": "deployment",
+ "name": "nginx",
+ "container": "nginx"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "cve",
+ "name": "CVE-123-4567",
+ "value": "CVE-123-4567"
+ }
+ ]
+ },
+ "scanner": {
+ "id": "starboard_trivy",
+ "name": "Trivy (via Starboard Operator)",
+ "vendor": "GitLab"
+ }
+}'
+```
+
+## Subscriptions
+
+The subscriptions endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)
+in order to apply subscriptions including trials, and add-on purchases, for personal namespaces or top-level groups within GitLab.com.
+
+### Creating a subscription
+
+Use a POST to create a subscription.
+
+```plaintext
+POST /namespaces/:id/gitlab_subscription
+```
+
+| Attribute | Type | Required | Description |
+|:------------|:--------|:---------|:------------|
+| `start_date` | date | yes | Start date of subscription |
+| `end_date` | date | no | End date of subscription |
+| `plan_code` | string | no | Subscription tier code |
+| `seats` | integer | no | Number of seats in subscription |
+| `max_seats_used` | integer | no | Highest number of active users in the last month |
+| `auto_renew` | boolean | no | Whether subscription auto-renews on end date |
+| `trial` | boolean | no | Whether subscription is a trial |
+| `trial_starts_on` | date | no | Start date of trial |
+| `trial_ends_on` | date | no | End date of trial |
+
+Example request:
+
+```shell
+curl --request POST --header "TOKEN: <admin_access_token>" "https://gitlab.com/api/v4/namespaces/1234/gitlab_subscription?start_date="2020-07-15"&plan="premium"&seats=10"
+```
+
+Example response:
+
+```json
+{
+ "plan": {
+ "code":"premium",
+ "name":"premium",
+ "trial":false,
+ "auto_renew":null,
+ "upgradable":false
+ },
+ "usage": {
+ "seats_in_subscription":10,
+ "seats_in_use":1,
+ "max_seats_used":0,
+ "seats_owed":0
+ },
+ "billing": {
+ "subscription_start_date":"2020-07-15",
+ "subscription_end_date":null,
+ "trial_ends_on":null
+ }
+}
+```
+
+### Updating a subscription
+
+Use a PUT command to update an existing subscription.
+
+```plaintext
+PUT /namespaces/:id/gitlab_subscription
+```
+
+| Attribute | Type | Required | Description |
+|:------------|:--------|:---------|:------------|
+| `start_date` | date | no | Start date of subscription |
+| `end_date` | date | no | End date of subscription |
+| `plan_code` | string | no | Subscription tier code |
+| `seats` | integer | no | Number of seats in subscription |
+| `max_seats_used` | integer | no | Highest number of active users in the last month |
+| `auto_renew` | boolean | no | Whether subscription auto-renews on end date |
+| `trial` | boolean | no | Whether subscription is a trial |
+| `trial_starts_on` | date | no | Start date of trial. Required if trial is true. |
+| `trial_ends_on` | date | no | End date of trial |
+
+Example request:
+
+```shell
+curl --request PUT --header "TOKEN: <admin_access_token>" "https://gitlab.com/api/v4/namespaces/1234/gitlab_subscription?max_seats_used=0"
+```
+
+Example response:
+
+```json
+{
+ "plan": {
+ "code":"premium",
+ "name":"premium",
+ "trial":false,
+ "auto_renew":null,
+ "upgradable":false
+ },
+ "usage": {
+ "seats_in_subscription":80,
+ "seats_in_use":82,
+ "max_seats_used":0,
+ "seats_owed":2
+ },
+ "billing": {
+ "subscription_start_date":"2020-07-15",
+ "subscription_end_date":"2021-07-15",
+ "trial_ends_on":null
+ }
+}
+```
+
+### Retrieving a subscription
+
+Use a GET command to view an existing subscription.
+
+```plaintext
+GET /namespaces/:id/gitlab_subscription
+```
+
+Example request:
+
+```shell
+curl --header "TOKEN: <admin_access_token>" "https://gitlab.com/api/v4/namespaces/1234/gitlab_subscription"
+```
+
+Example response:
+
+```json
+{
+ "plan": {
+ "code":"premium",
+ "name":"premium",
+ "trial":false,
+ "auto_renew":null,
+ "upgradable":false
+ },
+ "usage": {
+ "seats_in_subscription":80,
+ "seats_in_use":82,
+ "max_seats_used":82,
+ "seats_owed":2
+ },
+ "billing": {
+ "subscription_start_date":"2020-07-15",
+ "subscription_end_date":"2021-07-15",
+ "trial_ends_on":null
+ }
+}
+```
+
+### Known consumers
+
+- CustomersDot
+
+## CI minute provisioning
+
+The CI Minute endpoints are used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)
+to apply additional packs of CI minutes, for personal namespaces or top-level groups within GitLab.com.
+
+### Creating an additional pack
+
+Use a POST to create additional packs.
+
+```plaintext
+POST /namespaces/:id/minutes
+```
+
+| Attribute | Type | Required | Description |
+|:------------|:--------|:---------|:------------|
+| `packs` | array | yes | An array of purchased minutes packs |
+| `packs[expires_at]` | date | yes | Expiry date of the purchased pack|
+| `packs[number_of_minutes]` | integer | yes | Number of additional minutes |
+| `packs[purchase_xid]` | string | yes | The unique ID of the purchase |
+
+Example request:
+
+```shell
+curl --request POST \
+ --url "http://localhost:3000/api/v4/namespaces/123/minutes" \
+ --header 'Content-Type: application/json' \
+ --header 'PRIVATE-TOKEN: <admin access token>' \
+ --data '{
+ "packs": [
+ {
+ "number_of_minutes": 10000,
+ "expires_at": "2022-01-01",
+ "purchase_xid": "46952fe69bebc1a4de10b2b4ff439d0c"
+ }
+ ]
+ }'
+```
+
+Example response:
+
+```json
+[
+ {
+ "namespace_id": 123,
+ "expires_at": "2022-01-01",
+ "number_of_minutes": 10000,
+ "purchase_xid": "46952fe69bebc1a4de10b2b4ff439d0c"
+ }
+]
+```
+
+### Moving additional packs
+
+Use a PATCH to move additional packs from one namespace to another.
+
+```plaintext
+PATCH /namespaces/:id/minutes/move/:target_id
+```
+
+| Attribute | Type | Required | Description |
+|:------------|:--------|:---------|:------------|
+| `id` | string | yes | The ID of the namespace to transfer packs from |
+| `target_id` | string | yes | The ID of the target namespace to transfer the packs to |
+
+Example request:
+
+```shell
+curl --request PATCH \
+ --url "http://localhost:3000/api/v4/namespaces/123/minutes/move/321" \
+ --header 'PRIVATE-TOKEN: <admin access token>'
+```
+
+Example response:
+
+```json
+{
+ "message": "202 Accepted"
+}
+```
+
+### Known consumers
+
+- CustomersDot
+
+## Upcoming reconciliations
+
+The `upcoming_reconciliations` endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)
+to update upcoming reconciliations for namespaces.
+
+### Updating `upcoming_reconciliations`
+
+Use a PUT command to update `upcoming_reconciliations`.
+
+```plaintext
+PUT /internal/upcoming_reconciliations
+```
+
+| Attribute | Type | Required | Description |
+|:-------------------|:-----------|:---------|:------------|
+| `upcoming_reconciliations` | array | yes | Array of upcoming reconciliations |
+
+Each array element contains:
+
+| Attribute | Type | Required | Description |
+|:-------------------|:-----------|:---------|:------------|
+| `namespace_id` | integer | yes | ID of the namespace to be reconciled |
+| `next_reconciliation_date` | date | yes | Date when next reconciliation will happen |
+| `display_alert_from` | date | yes | Start date to display alert of upcoming reconciliation |
+
+Example request:
+
+```shell
+curl --request PUT --header "PRIVATE-TOKEN: <admin_access_token>" --header "Content-Type: application/json" \
+ --data '{"upcoming_reconciliations": [{"namespace_id": 127, "next_reconciliation_date": "13 Jun 2021", "display_alert_from": "06 Jun 2021"}, {"namespace_id": 129, "next_reconciliation_date": "12 Jun 2021", "display_alert_from": "05 Jun 2021"}]}' \
+ "https://gitlab.com/api/v4/internal/upcoming_reconciliations"
+```
+
+Example response:
+
+```plaintext
+200
+```
+
+### Known consumers
+
+- CustomersDot
diff --git a/doc/development/internal_api/internal_api_allowed.md b/doc/development/internal_api/internal_api_allowed.md
new file mode 100644
index 00000000000..83dbb54babd
--- /dev/null
+++ b/doc/development/internal_api/internal_api_allowed.md
@@ -0,0 +1,109 @@
+---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+type: reference, api
+---
+
+# Internal allowed API
+
+The `internal/allowed` endpoint assesses whether a user has permission to perform
+certain operations on the Git repository. It performs multiple checks, such as:
+
+- Ensuring the branch or tag name is acceptable.
+- Whether or not the user has the authority to perform that action.
+
+## Endpoint definition
+
+The internal API endpoints are defined under
+[`lib/api/internal`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/api/internal),
+and the `/allowed` path is in
+[`lib/api/internal/base.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/internal/base.rb).
+
+## Use the endpoint
+
+`internal/allowed` is called when you:
+
+- Push to the repository.
+- Perform actions on the repository through the GitLab user interface, such as
+ applying suggestions or using the GitLab IDE.
+
+Gitaly typically calls this endpoint. It is only called internally (by other parts
+of the application) rather than by external users of the API.
+
+## Push checks
+
+A key part of the `internal/allowed` flow is the call to
+`EE::Gitlab::Checks::PushRuleCheck`, which can perform the following checks:
+
+- `EE::Gitlab::Checks::PushRules::CommitCheck`
+- `EE::Gitlab::Checks::PushRules::TagCheck`
+- `EE::Gitlab::Checks::PushRules::BranchCheck`
+- `EE::Gitlab::Checks::PushRules::FileSizeCheck`
+
+## Recursion
+
+Some of the Gitaly RPCs called by `internal/allowed` then, themselves, make calls
+back to `internal/allowed`. These calls are now correlated with the original request.
+Gitaly relies on the Rails application for authorization, and maintains no permissions model itself.
+
+These calls show up in the logs differently to the initial requests. {example}
+
+Because this endpoint can be called recursively, slow performance on this endpoint can result in an exponential performance impact. This documentation is in fact adapted from [the investigation into its performance](https://gitlab.com/gitlab-org/gitlab/-/issues/222247).
+
+## Known performance issues
+
+### Refs
+
+The number of [`refs`](https://git-scm.com/book/en/v2/Git-Internals-Git-References)
+on the Git repository have a notable effect on the performance of `git` commands
+called upon it. Gitaly RPCs are similarly affected. Certain `git` commands scan
+through all refs, causing a notable impact on the speed of those commands.
+
+On the `internal/allowed` endpoint, the recursive nature of RPC calls mean the
+ref counts have an exponential effect on performance.
+
+#### Environment refs
+
+[Stale environment refs](https://gitlab.com/gitlab-org/gitlab/-/issues/296625)
+are a common example of excessive refs causing performance issues. Stale environment
+refs can number into the tens of thousands on busy repositories, as they aren't
+cleared up automatically.
+
+#### Dangling refs
+
+Dangling refs are created to prevent accidental deletion of objects from object pools.
+Large numbers of these refs can exist, which may have potential performance implications.
+For existing discussion around this issue, read
+[`gitaly#1900`](https://gitlab.com/gitlab-org/gitaly/-/issues/1900). This issue
+appears to have less effect than stale environment refs.
+
+### Pool repositories
+
+When a fork is created on GitLab, a central pool repository is created and the forks
+are linked to it. This pool repository prevents duplication of data by storing
+data common to other forks. However, the pool repository is not cleaned up in the
+same manner as the standard repositories, and is more prone to the refs issue.
+
+## Feature flags
+
+### Parallel push checks
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available,
+ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `parallel_push_checks`.
+On GitLab.com, by default this feature is not available. To make it available
+per project, ask GitLab.com administrator to
+[enable the feature flag](../../administration/feature_flags.md) named `parallel_push_checks`.
+You should not use this feature for production environments.
+
+This experimental feature flag enables the endpoint to run multiple RPCs simultaneously,
+reducing the overall time taken by roughly half. This time savings is achieved through
+threading, and has potential side effects at large scale. On GitLab.com, this feature flag
+is enabled only for `gitlab-org/gitlab` and `gitlab-com/www-gitlab-com` projects.
+Without it, those projects routinely time out requests to the endpoint. When this
+feature was deployed to all of GitLab.com, some pushes failed, presumably due to
+exhausting resources like database connection pools.
+
+We recommend you enable this feature flag only if you are experiencing timeouts, and
+only enable it for that specific project.
diff --git a/doc/development/iterating_tables_in_batches.md b/doc/development/iterating_tables_in_batches.md
index fba6f2f616d..9ea7fd3dc29 100644
--- a/doc/development/iterating_tables_in_batches.md
+++ b/doc/development/iterating_tables_in_batches.md
@@ -142,7 +142,7 @@ database query:
SELECT "users"."id" FROM "users" ORDER BY "users"."id" ASC LIMIT 1
```
-![Reading the start id value](img/each_batch_users_table_iteration_1_v13_7.png)
+![Reading the start `id` value](img/each_batch_users_table_iteration_1_v13_7.png)
Notice that the query only reads data from the index (`INDEX ONLY SCAN`), the table is not
accessed. Database indexes are sorted so taking out the first item is a very cheap operation.
@@ -155,7 +155,7 @@ to get a "shifted" `id` value.
SELECT "users"."id" FROM "users" WHERE "users"."id" >= 1 ORDER BY "users"."id" ASC LIMIT 1 OFFSET 5
```
-![Reading the end id value](img/each_batch_users_table_iteration_2_v13_7.png)
+![Reading the end `id` value](img/each_batch_users_table_iteration_2_v13_7.png)
Again, the query only looks into the index. The `OFFSET 5` takes out the sixth `id` value: this
query reads a maximum of six items from the index regardless of the table size or the iteration
@@ -181,7 +181,7 @@ previous iteration in order to find out the next end `id` value.
SELECT "users"."id" FROM "users" WHERE "users"."id" >= 302 ORDER BY "users"."id" ASC LIMIT 1 OFFSET 5
```
-![Reading the second end id value](img/each_batch_users_table_iteration_4_v13_7.png)
+![Reading the second end `id` value](img/each_batch_users_table_iteration_4_v13_7.png)
Now we can easily construct the `users` query for the second iteration.
diff --git a/doc/development/jh_features_review.md b/doc/development/jh_features_review.md
index cb0f8ddbd13..858048c1e7c 100644
--- a/doc/development/jh_features_review.md
+++ b/doc/development/jh_features_review.md
@@ -23,6 +23,14 @@ We have two kinds of changes related to JH:
If needed, review the corresponding JH merge request located at [JH repository](https://gitlab.com/gitlab-jh/gitlab)
+## When to merge files to the GitLab Inc. repository
+
+Files that are added to the `gitlab-jh` repository outside of `jh/` must be mirrored in the GitLab Inc. repository.
+
+If code that is added to the GitLab Inc. repository references (for example, `render_if_exists`) any `gitlab-jh` file that does not
+exist in the GitLab Inc. codebase, add a comment with a link to the JiHu merge request or file. This is to prevent
+the reference from being misidentified as a missing partial and subsequently deleted in the `gitlab` codebase.
+
## Process overview
See the [merge request process](https://about.gitlab.com/handbook/ceo/chief-of-staff-team/jihu-support/#merge-request-process)
diff --git a/doc/development/maintenance_mode.md b/doc/development/maintenance_mode.md
index e308ab26c27..c2fd4bab605 100644
--- a/doc/development/maintenance_mode.md
+++ b/doc/development/maintenance_mode.md
@@ -13,7 +13,7 @@ GitLab Maintenance Mode **only** blocks writes from HTTP and SSH requests at the
- [the read-only database method](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/database.rb#L13), which toggles special behavior when we are not allowed to write to the database. [Search the codebase for `Gitlab::Database.read_only?`.](https://gitlab.com/search?search=Gitlab%3A%3ADatabase.read_only%3F&group_id=9970&project_id=278964&scope=blobs&search_code=false&snippets=false&repository_ref=)
- [the read-only middleware](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/ee/gitlab/middleware/read_only/controller.rb), where HTTP requests that cause database writes are blocked, unless explicitly allowed.
-- [Git push access via SSH is denied](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/git_access.rb#L13) by returning 401 when `gitlab-shell` POSTs to [`/internal/allowed`](internal_api.md) to [check if access is allowed](internal_api.md#git-authentication).
+- [Git push access via SSH is denied](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/git_access.rb#L13) by returning 401 when `gitlab-shell` POSTs to [`/internal/allowed`](internal_api/index.md) to [check if access is allowed](internal_api/index.md#git-authentication).
- [Container registry authentication service](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/app/services/ee/auth/container_registry_authentication_service.rb#L12), where updates to the container registry are blocked.
The database itself is not in read-only mode (except in a Geo secondary site) and can be written by sources other than the ones blocked.
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index e03b96a0e14..0bd9979e790 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -135,6 +135,7 @@ various database operations, such as:
- [dropping and renaming columns](avoiding_downtime_in_migrations.md#dropping-columns)
- [changing column constraints and types](avoiding_downtime_in_migrations.md#changing-column-constraints)
- [adding and dropping indexes, tables, and foreign keys](avoiding_downtime_in_migrations.md#adding-indexes)
+- [migrating `integer` primary keys to `bigint`](avoiding_downtime_in_migrations.md#migrating-integer-primary-keys-to-bigint)
and explains how to perform them without requiring downtime.
@@ -312,12 +313,8 @@ A better strategy is to split the migration, so that we only need to acquire one
```ruby
enable_lock_retries!
-def up
- remove_column :users, :full_name
-end
-
-def down
- add_column :users, :full_name, :string
+def change
+ remove_column :users, :full_name, :string
end
```
@@ -587,8 +584,6 @@ class like so:
```ruby
class MyMigration < Gitlab::Database::Migration[1.0]
- include Gitlab::Database::MigrationHelpers
-
disable_ddl_transaction!
INDEX_NAME = 'index_name'
@@ -632,8 +627,6 @@ be used with a name option. For example:
```ruby
class MyMigration < Gitlab::Database::Migration[1.0]
- include Gitlab::Database::MigrationHelpers
-
INDEX_NAME = 'index_name'
def up
diff --git a/doc/development/multi_version_compatibility.md b/doc/development/multi_version_compatibility.md
index f834f4f4ee3..27a7cd6e85e 100644
--- a/doc/development/multi_version_compatibility.md
+++ b/doc/development/multi_version_compatibility.md
@@ -49,7 +49,15 @@ Is it ok that some nodes have the new Rails version, but some nodes have the old
## A walkthrough of an update
-Backwards compatibility problems during updates are often very subtle. This is why it is worth familiarizing yourself with [update instructions](../update/index.md), [reference architectures](../administration/reference_architectures/index.md), and [GitLab.com's architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/). But to illustrate how these problems arise, take a look at this example of a simple update.
+Backward compatibility problems during updates are often very subtle. This is why it is worth
+familiarizing yourself with:
+
+- [Update instructions](../update/index.md)
+- [Reference architectures](../administration/reference_architectures/index.md)
+- [GitLab.com's architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/)
+- [GitLab.com's upgrade pipeline](https://gitlab.com/gitlab-org/release/docs/blob/master/general/deploy/gitlab-com-deployer.md#upgrade-pipeline-default)
+
+To illustrate how these problems arise, take a look at this example:
- 🚢 New version
- 🙂 Old version
diff --git a/doc/development/namespaces_storage_statistics.md b/doc/development/namespaces_storage_statistics.md
index c6af0ddf9ea..e5263288210 100644
--- a/doc/development/namespaces_storage_statistics.md
+++ b/doc/development/namespaces_storage_statistics.md
@@ -53,7 +53,10 @@ SELECT split_part("rs".path, '/', 1) as root_path,
COALESCE(SUM(ps.wiki_size), 0) AS wiki_size,
COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size,
COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size,
- COALESCE(SUM(ps.packages_size), 0) AS packages_size
+ COALESCE(SUM(ps.pipeline_artifacts_size), 0) AS pipeline_artifacts_size,
+ COALESCE(SUM(ps.packages_size), 0) AS packages_size,
+ COALESCE(SUM(ps.snippets_size), 0) AS snippets_size,
+ COALESCE(SUM(ps.uploads_size), 0) AS uploads_size
FROM "projects"
INNER JOIN routes rs ON rs.source_id = projects.id AND rs.source_type = 'Project'
INNER JOIN project_statistics ps ON ps.project_id = projects.id
@@ -83,7 +86,10 @@ WITH refresh AS (
COALESCE(SUM(ps.wiki_size), 0) AS wiki_size,
COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size,
COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size,
- COALESCE(SUM(ps.packages_size), 0) AS packages_size
+ COALESCE(SUM(ps.pipeline_artifacts_size), 0) AS pipeline_artifacts_size,
+ COALESCE(SUM(ps.packages_size), 0) AS packages_size,
+ COALESCE(SUM(ps.snippets_size), 0) AS snippets_size,
+ COALESCE(SUM(ps.uploads_size), 0) AS uploads_size
FROM "projects"
INNER JOIN routes rs ON rs.source_id = projects.id AND rs.source_type = 'Project'
INNER JOIN project_statistics ps ON ps.project_id = projects.id
@@ -94,7 +100,10 @@ SET storage_size = refresh.storage_size,
wiki_size = refresh.wiki_size,
lfs_objects_size = refresh.lfs_objects_size,
build_artifacts_size = refresh.build_artifacts_size,
- packages_size = refresh.packages_size
+ pipeline_artifacts_size = refresh.pipeline_artifacts_size,
+ packages_size = refresh.packages_size,
+ snippets_size = refresh.snippets_size,
+ uploads_size = refresh.uploads_size
FROM refresh
INNER JOIN routes rs ON rs.path = refresh.root_path AND rs.source_type = 'Namespace'
WHERE namespace_storage_statistics.namespace_id = rs.source_id
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index 45982d6075b..71a11d2024c 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -23,6 +23,30 @@ as much as possible.
After a merge request has been approved, the pipeline would contain the full RSpec & Jest tests. This will ensure that all tests
have been run before a merge request is merged.
+### Overview of the GitLab project test dependency
+
+To understand how the minimal test jobs are executed, we need to understand the dependency between
+GitLab code (frontend and backend) and the respective tests (Jest and RSpec).
+This dependency can be visualized in the following diagram:
+
+```mermaid
+flowchart LR
+ subgraph frontend
+ fe["Frontend code"]--tested with-->jest
+ end
+ subgraph backend
+ be["Backend code"]--tested with-->rspec
+ end
+
+ be--generates-->fixtures["frontend fixtures"]
+ fixtures--used in-->jest
+```
+
+In summary:
+
+- RSpec tests are dependent on the backend code.
+- Jest tests are dependent on both frontend and backend code, the latter through the frontend fixtures.
+
### RSpec minimal jobs
#### Determining related RSpec test files in a merge request
@@ -57,7 +81,7 @@ In this mode, `jest` would resolve all the dependencies of related to the change
In addition, there are a few circumstances where we would always run the full Jest tests:
-- when the `pipeline:run-all-rspec` label is set on the merge request
+- when the `pipeline:run-all-jest` label is set on the merge request
- when the merge request is created by an automation (e.g. Gitaly update or MR targeting a stable branch)
- when any CI config file is changed (i.e. `.gitlab-ci.yml` or `.gitlab/ci/**/*`)
- when any frontend "core" file is changed (i.e. `package.json`, `yarn.lock`, `babel.config.js`, `jest.config.*.js`, `config/helpers/**/*.js`)
@@ -142,6 +166,13 @@ Our current RSpec tests parallelization setup is as follows:
After that, the next pipeline uses the up-to-date `knapsack/report-master.json` file.
+### Flaky tests
+
+Tests that are [known to be flaky](testing_guide/flaky_tests.md#automatic-retries-and-flaky-tests-detection) are:
+
+- skipped if the `$SKIP_FLAKY_TESTS_AUTOMATICALLY` variable is set to `true` (`false` by default)
+- run if `$SKIP_FLAKY_TESTS_AUTOMATICALLY` variable is not set to `true` or if the `~"pipeline:run-flaky-tests"` label is set on the MR
+
### Monitoring
The GitLab test suite is [monitored](performance.md#rspec-profiling) for the `main` branch, and any branch
@@ -157,6 +188,8 @@ that includes `rspec-profile` in their name.
Consult the [Review Apps](testing_guide/review_apps.md) dedicated page for more information.
+If you want to force a Review App to be deployed regardless of your changes, you can add the `pipeline:run-review-app` label to the merge request.
+
## As-if-FOSS jobs
The `* as-if-foss` jobs run the GitLab test suite "as if FOSS", meaning as if the jobs would run in the context
@@ -590,7 +623,8 @@ The current stages are:
- `build-images`: This stage includes jobs that prepare Docker images
that are needed by jobs in subsequent stages or downstream pipelines.
- `fixtures`: This stage includes jobs that prepare fixtures needed by frontend tests.
-- `test`: This stage includes most of the tests, DB/migration jobs, and static analysis jobs.
+- `lint`: This stage includes linting and static analysis jobs.
+- `test`: This stage includes most of the tests, and DB/migration jobs.
- `post-test`: This stage includes jobs that build reports or gather data from
the `test` stage's jobs (for example, coverage, Knapsack metadata, and so on).
- `review-prepare`: This stage includes a job that build the CNG images that are
@@ -664,7 +698,7 @@ then included in individual jobs via [`extends`](../ci/yaml/index.md#extends).
The `rules` definitions are composed of `if:` conditions and `changes:` patterns,
which are also defined in
[`rules.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rules.gitlab-ci.yml)
-and included in `rules` definitions via [YAML anchors](../ci/yaml/index.md#anchors)
+and included in `rules` definitions via [YAML anchors](../ci/yaml/yaml_optimization.md#anchors)
#### `if:` conditions
@@ -696,7 +730,6 @@ and included in `rules` definitions via [YAML anchors](../ci/yaml/index.md#ancho
| `if-dot-com-gitlab-org-and-security-merge-request` | Limit jobs creation to merge requests for the `gitlab-org` and `gitlab-org/security` groups on GitLab.com. | |
| `if-dot-com-gitlab-org-and-security-tag` | Limit jobs creation to tags for the `gitlab-org` and `gitlab-org/security` groups on GitLab.com. | |
| `if-dot-com-ee-schedule` | Limits jobs to scheduled pipelines for the `gitlab-org/gitlab` project on GitLab.com. | |
-| `if-cache-credentials-schedule` | Limits jobs to scheduled pipelines with the `$CI_REPO_CACHE_CREDENTIALS` variable set. | |
| `if-security-pipeline-merge-result` | Matches if the pipeline is for a security merge request triggered by `@gitlab-release-tools-bot`. | |
<!-- vale gitlab.Substitutions = YES -->
@@ -741,8 +774,10 @@ request, be sure to start the `dont-interrupt-me` job before pushing.
[`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/global.gitlab-ci.yml),
with fixed keys:
- `.setup-test-env-cache`
+ - `.ruby-cache`
- `.rails-cache`
- `.static-analysis-cache`
+ - `.rubocop-cache`
- `.coverage-cache`
- `.danger-review-cache`
- `.qa-cache`
@@ -752,7 +787,7 @@ request, be sure to start the `dont-interrupt-me` job before pushing.
1. Only the following jobs, running in 2-hourly scheduled pipelines, are pushing (that is, updating) to the caches:
- `update-setup-test-env-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
- `update-gitaly-binaries-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
- - `update-static-analysis-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
+ - `update-rubocop-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
- `update-qa-cache`, defined in [`.gitlab/ci/qa.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/qa.gitlab-ci.yml).
- `update-assets-compile-production-cache`, defined in [`.gitlab/ci/frontend.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/frontend.gitlab-ci.yml).
- `update-assets-compile-test-cache`, defined in [`.gitlab/ci/frontend.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/frontend.gitlab-ci.yml).
@@ -764,71 +799,28 @@ request, be sure to start the `dont-interrupt-me` job before pushing.
We limit the artifacts that are saved and retrieved by jobs to the minimum in order to reduce the upload/download time and costs, as well as the artifacts storage.
-### Pre-clone step
-
-The `gitlab-org/gitlab` project on GitLab.com uses a [pre-clone step](https://gitlab.com/gitlab-org/gitlab/-/issues/39134)
-to seed the project with a recent archive of the repository. This is done for
-several reasons:
-
-- It speeds up builds because a 800 MB download only takes seconds, as opposed to a full Git clone.
-- It significantly reduces load on the file server, as smaller deltas mean less time spent in `git pack-objects`.
-
-The pre-clone step works by using the `CI_PRE_CLONE_SCRIPT` variable
-[defined by GitLab.com shared runners](../ci/runners/build_cloud/linux_build_cloud.md#pre-clone-script).
-
-The `CI_PRE_CLONE_SCRIPT` is currently defined as a project CI/CD variable:
-
-```shell
-(
- echo "Downloading archived master..."
- wget -O /tmp/gitlab.tar.gz https://storage.googleapis.com/gitlab-ci-git-repo-cache/project-278964/gitlab-master-shallow.tar.gz
-
- if [ ! -f /tmp/gitlab.tar.gz ]; then
- echo "Repository cache not available, cloning a new directory..."
- exit
- fi
-
- rm -rf $CI_PROJECT_DIR
- echo "Extracting tarball into $CI_PROJECT_DIR..."
- mkdir -p $CI_PROJECT_DIR
- cd $CI_PROJECT_DIR
- tar xzf /tmp/gitlab.tar.gz
- rm -f /tmp/gitlab.tar.gz
- chmod a+w $CI_PROJECT_DIR
-)
-```
-
-The first step of the script downloads `gitlab-master.tar.gz` from
-Google Cloud Storage. There is a [GitLab CI job named `cache-repo`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/cache-repo.gitlab-ci.yml#L5)
-that is responsible for keeping that archive up-to-date. Every two hours
-on a scheduled pipeline, it does the following:
+### Git fetch caching
-1. Creates a fresh clone of the `gitlab-org/gitlab` repository on GitLab.com.
-1. Saves the data as a `.tar.gz`.
-1. Uploads it into the Google Cloud Storage bucket.
+Because GitLab.com uses the [pack-objects cache](../administration/gitaly/configure_gitaly.md#pack-objects-cache),
+concurrent Git fetches of the same pipeline ref are deduplicated on
+the Gitaly server (always) and served from cache (when available).
-When a CI job runs with this configuration, the output looks something like this:
+This works well for the following reasons:
-```shell
-$ eval "$CI_PRE_CLONE_SCRIPT"
-Downloading archived master...
-Extracting tarball into /builds/group/project...
-Fetching changes...
-Reinitialized existing Git repository in /builds/group/project/.git/
-```
+- The pack-objects cache is enabled on all Gitaly servers on GitLab.com.
+- The CI/CD [Git strategy setting](../ci/pipelines/settings.md#choose-the-default-git-strategy) for `gitlab-org/gitlab` is **Git clone**,
+ causing all jobs to fetch the same data, which maximizes the cache hit ratio.
+- We use [shallow clone](../ci/pipelines/settings.md#limit-the-number-of-changes-fetched-during-clone) to avoid downloading the full Git
+ history for every job.
-Note that the `Reinitialized existing Git repository` message shows that
-the pre-clone step worked. The runner runs `git init`, which
-overwrites the Git configuration with the appropriate settings to fetch
-from the GitLab repository.
+### Pre-clone step
-`CI_REPO_CACHE_CREDENTIALS` contains the Google Cloud service account
-JSON for uploading to the `gitlab-ci-git-repo-cache` bucket. (If you're a
-GitLab Team Member, find credentials in the
-[GitLab shared 1Password account](https://about.gitlab.com/handbook/security/#1password-for-teams).
+NOTE:
+We no longer use this optimization for `gitlab-org/gitlab` because the [pack-objects cache](../administration/gitaly/configure_gitaly.md#pack-objects-cache)
+allows Gitaly to serve the full CI/CD fetch traffic now. See [Git fetch caching](#git-fetch-caching).
-Note that this bucket should be located in the same continent as the
-runner, or [you can incur network egress charges](https://cloud.google.com/storage/pricing).
+The pre-clone step works by using the `CI_PRE_CLONE_SCRIPT` variable
+[defined by GitLab.com shared runners](../ci/runners/runner_cloud/linux_runner_cloud.md#pre-clone-script).
---
diff --git a/doc/development/policies.md b/doc/development/policies.md
index 8ad3d3f42ba..e5191f00d9a 100644
--- a/doc/development/policies.md
+++ b/doc/development/policies.md
@@ -111,7 +111,7 @@ Each line represents a rule that was evaluated. There are a few things to note:
Here you can see that the first four rules were evaluated `false` for
which user and subject. For example, you can see in the last line that
-the rule was activated because the user `john` had Reporter access to
+the rule was activated because the user `john` had the Reporter [role](../user/permissions.md) on
`Project/4`.
When a policy is asked whether a particular ability is allowed
diff --git a/doc/development/reactive_caching.md b/doc/development/reactive_caching.md
index 3c0a1419604..5aaf4c72e64 100644
--- a/doc/development/reactive_caching.md
+++ b/doc/development/reactive_caching.md
@@ -74,7 +74,7 @@ For more information, read the internal issue
### In models and integrations
-The ReactiveCaching concern can be used in models as well as `integrations`
+The ReactiveCaching concern can be used in models as well as integrations
(`app/models/integrations`).
1. Include the concern in your model or integration.
@@ -88,7 +88,7 @@ The ReactiveCaching concern can be used in models as well as `integrations`
To include the concern in an integration:
```ruby
- include ReactiveService
+ include Integrations::ReactivelyCached
```
1. Implement the `calculate_reactive_cache` method in your model or integration.
@@ -201,15 +201,15 @@ There are some `class_attribute` options which can be tweaked.
and `"ExampleModel:1:arg1:arg2:alive"` respectively, where `ExampleModel` is the
name of the model, `1` is the ID of the record, `arg1` and `arg2` are parameters
passed to `with_reactive_cache`.
-- If you're including this concern in a service instead, you must override
- the default by adding the following to your service:
+- If you're including this concern in an integration (`app/models/integrations/`) instead, you must override
+ the default by adding the following to your integration:
```ruby
- self.reactive_cache_key = ->(service) { [service.class.model_name.singular, service.project_id] }
+ self.reactive_cache_key = ->(integration) { [integration.class.model_name.singular, integration.project_id] }
```
If your reactive_cache_key is exactly like the above, you can use the existing
- `ReactiveService` concern instead.
+ `Integrations::ReactivelyCached` concern instead.
#### `self.reactive_cache_lease_timeout`
diff --git a/doc/development/redis.md b/doc/development/redis.md
index fa07cebdc61..75170b8c746 100644
--- a/doc/development/redis.md
+++ b/doc/development/redis.md
@@ -21,8 +21,7 @@ GitLab uses [Redis](https://redis.io) for the following distinct purposes:
In most environments (including the GDK), all of these point to the same
Redis instance.
-On GitLab.com, we use [separate Redis
-instances](../administration/redis/replication_and_failover.md#running-multiple-redis-clusters).
+On GitLab.com, we use [separate Redis instances](../administration/redis/replication_and_failover.md#running-multiple-redis-clusters).
See the [Redis SRE guide](https://gitlab.com/gitlab-com/runbooks/-/blob/master/docs/redis/redis-survival-guide-for-sres.md)
for more details on our setup.
@@ -121,8 +120,7 @@ on GitLab.com
On GitLab.com, entries from the [Redis
slow log](https://redis.io/commands/slowlog) are available in the
-`pubsub-redis-inf-gprd*` index with the [`redis.slowlog`
-tag](https://log.gprd.gitlab.net/app/kibana#/discover?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-1d,to:now))&_a=(columns:!(json.type,json.command,json.exec_time_s),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:AWSQX_Vf93rHTYrsexmk,key:json.tag,negate:!f,params:(query:redis.slowlog),type:phrase),query:(match:(json.tag:(query:redis.slowlog,type:phrase))))),index:AWSQX_Vf93rHTYrsexmk)).
+`pubsub-redis-inf-gprd*` index with the [`redis.slowlog` tag](https://log.gprd.gitlab.net/app/kibana#/discover?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-1d,to:now))&_a=(columns:!(json.type,json.command,json.exec_time_s),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:AWSQX_Vf93rHTYrsexmk,key:json.tag,negate:!f,params:(query:redis.slowlog),type:phrase),query:(match:(json.tag:(query:redis.slowlog,type:phrase))))),index:AWSQX_Vf93rHTYrsexmk)).
This shows commands that have taken a long time and may be a performance
concern.
diff --git a/doc/development/reusing_abstractions.md b/doc/development/reusing_abstractions.md
index 568e8a9d123..ccf82dc6c77 100644
--- a/doc/development/reusing_abstractions.md
+++ b/doc/development/reusing_abstractions.md
@@ -133,8 +133,20 @@ Everything in `lib/api`.
Everything that resides in `app/services`.
+Services should consider inheriting from:
+
+- `BaseContainerService` for services scoped by container (project or group)
+- `BaseProjectService` for services scoped to projects
+- `BaseGroupService` for services scoped to groups
+
+or, create a new base class and update the list above.
+
+Legacy classes inherited from `BaseService` for historical reasons.
+
In Service classes the use of `execute` and `#execute` is preferred over `call` and `#call`.
+Classes that are not service objects should be [created elsewhere](directory_structure.md#use-namespaces-to-define-bounded-contexts), such as in `lib`.
+
#### ServiceResponse
Service classes usually have an `execute` method, which can return a
diff --git a/doc/development/ruby3_gotchas.md b/doc/development/ruby3_gotchas.md
new file mode 100644
index 00000000000..e4ed5039e3c
--- /dev/null
+++ b/doc/development/ruby3_gotchas.md
@@ -0,0 +1,140 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Ruby 3 gotchas
+
+This section documents several problems we found while working on [Ruby 3 support](https://gitlab.com/groups/gitlab-org/-/epics/5149)
+and which led to subtle bugs or test failures that were difficult to understand. We encourage every GitLab contributor
+who writes Ruby code on a regular basis to familiarize themselves with these issues.
+
+To find the complete list of changes to the Ruby 3 language and standard library, see
+[Ruby Changes](https://rubyreferences.github.io/rubychanges/3.0.html).
+
+## `Hash#each` consistently yields a 2-element array to lambdas
+
+Consider the following code snippet:
+
+```ruby
+def foo(a, b)
+ p [a, b]
+end
+
+def bar(a, b = 2)
+ p [a, b]
+end
+
+foo_lambda = method(:foo).to_proc
+bar_lambda = method(:bar).to_proc
+
+{ a: 1 }.each(&foo_lambda)
+{ a: 1 }.each(&bar_lambda)
+```
+
+In Ruby 2.7, the output of this program suggests that yielding hash entries to lambdas behaves
+differently depending on how many required arguments there are:
+
+```ruby
+# Ruby 2.7
+{ a: 1 }.each(&foo_lambda) # prints [:a, 1]
+{ a: 1 }.each(&bar_lambda) # prints [[:a, 1], 2]
+```
+
+Ruby 3 makes this behavior consistent and always attempts to yield hash entries as a single `[key, value]` array:
+
+```ruby
+# Ruby 3.0
+{ a: 1 }.each(&foo_lambda) # `foo': wrong number of arguments (given 1, expected 2) (ArgumentError)
+{ a: 1 }.each(&bar_lambda) # prints [[:a, 1], 2]
+```
+
+To write code that works under both 2.7 and 3.0, consider the following options:
+
+- Always pass the lambda body as a block: `{ a: 1 }.each { |a, b| p [a, b] }`.
+- Deconstruct the lambda arguments: `{ a: 1 }.each(&->((a, b)) { p [a, b] })`.
+
+We recommend always passing the block explicitly, and prefer two required arguments as block parameters.
+
+To learn more, see [Ruby issue 12706](https://bugs.ruby-lang.org/issues/12706).
+
+## `Symbol#to_proc` returns signature metadata consistent with lambdas
+
+A common idiom in Ruby is to obtain `Proc` objects using the `&:<symbol>` shorthand and
+pass them to higher-order functions:
+
+```ruby
+[1, 2, 3].each(&:to_s)
+```
+
+Ruby desugars `&:<symbol>` to `Symbol#to_proc`. We can call it with
+the method _receiver_ as its first argument (here: `Integer`), and all method _arguments_
+(here: none) as its remaining arguments.
+
+This behaves the same in both Ruby 2.7 and Ruby 3. Where Ruby 3 diverges is when capturing
+this `Proc` object and inspecting its call signature.
+This is often done when writing DSLs or using other forms of meta-programming:
+
+```ruby
+p = :foo.to_proc # This usually happens via a conversion through `&:foo`
+
+# Ruby 2.7: prints [[:rest]] (-1)
+# Ruby 3.0: prints [[:req], [:rest]] (-2)
+puts "#{p.parameters} (#{p.arity})"
+```
+
+Ruby 2.7 reports zero required and one optional parameter for this `Proc` object, while Ruby 3 reports one required
+and one optional parameter. Ruby 2.7 is incorrect: the first argument must
+always be passed, as it is the receiver of the method the `Proc` object represents, and methods cannot be
+called without a receiver.
+
+Ruby 3 corrects this: the code that tests `Proc` object arity or parameter lists might now break and
+has to be updated.
+
+To learn more, see [Ruby issue 16260](https://bugs.ruby-lang.org/issues/16260).
+
+## `OpenStruct` does not evaluate fields lazily
+
+The `OpenStruct` implementation has undergone a partial rewrite in Ruby 3, resulting in
+behavioral changes. In Ruby 2.7, `OpenStruct` defines methods lazily, when the method is first accessed.
+In Ruby 3.0, it defines these methods eagerly in the initializer, which can break classes that inherit from `OpenStruct`
+and override these methods.
+
+Don't inherit from `OpenStruct` for these reasons; ideally, don't use it at all.
+`OpenStruct` is [considered problematic](https://ruby-doc.org/stdlib-3.0.2/libdoc/ostruct/rdoc/OpenStruct.html#class-OpenStruct-label-Caveats).
+When writing new code, prefer a `Struct` instead, which is simpler in implementation, although less flexible.
+
+## `Regexp` and `Range` instances are frozen
+
+It is not necessary anymore to explicitly freeze `Regexp` or `Range` instances because Ruby 3 freezes
+them automatically upon creation.
+
+This has a subtle side-effect: Tests that stub method calls on these types now fail with an error because
+RSpec cannot stub frozen objects:
+
+```ruby
+# Ruby 2.7: works
+# Ruby 3.0: error: "can't modify frozen object"
+allow(subject.function_returning_range).to receive(:max).and_return(42)
+```
+
+Rewrite affected tests by not stubbing method calls on frozen objects. The example above can be rewritten as:
+
+```ruby
+# Works with any Ruby version
+allow(subject).to receive(:function_returning_range).and_return(1..42)
+```
+
+## Table tests fail with Ruby 3.0.2
+
+Ruby 3.0.2 has a known bug that causes [table tests](testing_guide/best_practices.md#table-based--parameterized-tests)
+to fail when table values consist of integer values.
+The reasons are documented in [issue 337614](https://gitlab.com/gitlab-org/gitlab/-/issues/337614).
+This problem has been fixed in Ruby and the fix is expected to be included in Ruby 3.0.3.
+
+The problem only affects users who run an unpatched Ruby 3.0.2. This is likely the case when you
+installed Ruby manually or via tools like `asdf`. Users of the `gitlab-development-kit (GDK)`
+are also affected by this problem.
+
+Build images are not affected because they include the patch set addressing this bug.
diff --git a/doc/development/ruby_upgrade.md b/doc/development/ruby_upgrade.md
index ad6bff8499a..f9816986b2d 100644
--- a/doc/development/ruby_upgrade.md
+++ b/doc/development/ruby_upgrade.md
@@ -137,7 +137,7 @@ This is typically necessary, since gems or Ruby applications that we maintain ou
update these repositories for the GitLab Rails application to work with a new Ruby,
it is good practice to keep Ruby versions in lock-step across all our repositories. For minor and major
upgrades, add new CI/CD jobs to these repositories using the new Ruby.
-A [build matrix definition](../ci/yaml/index.md#parallel-matrix-jobs) can do this efficiently.
+A [build matrix definition](../ci/yaml/index.md#parallelmatrix) can do this efficiently.
#### Decide which repositories to update
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index 0f13b8ecae9..65fdb815f87 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -540,6 +540,94 @@ out, _ = exec.Command("sh", "-c", "echo 1 | cat /etc/passwd").Output()
This outputs `1` followed by the content of `/etc/passwd`.
+## General recommendations
+
+### TLS minimum recommended version
+
+As we have [moved away from supporting TLS 1.0 and 1.1](https://about.gitlab.com/blog/2018/10/15/gitlab-to-deprecate-older-tls/), we should only use TLS 1.2 and above.
+
+#### Ciphers
+
+We recommend using the ciphers that Mozilla is providing in their [recommended SSL configuration generator](https://ssl-config.mozilla.org/#server=go&version=1.17&config=intermediate&guideline=5.6) for TLS 1.2:
+
+- `ECDHE-ECDSA-AES128-GCM-SHA256`
+- `ECDHE-RSA-AES128-GCM-SHA256`
+- `ECDHE-ECDSA-AES256-GCM-SHA384`
+- `ECDHE-RSA-AES256-GCM-SHA384`
+- `ECDHE-ECDSA-CHACHA20-POLY1305`
+- `ECDHE-RSA-CHACHA20-POLY1305`
+
+And the following cipher suites (according to the [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446#appendix-B.4)) for TLS 1.3:
+
+- `TLS_AES_128_GCM_SHA256`
+- `TLS_AES_256_GCM_SHA384`
+- `TLS_CHACHA20_POLY1305_SHA256`
+
+*Note*: **Golang** does [not support](https://github.com/golang/go/blob/go1.17/src/crypto/tls/cipher_suites.go#L676) all cipher suites with TLS 1.3.
+
+##### Implementation examples
+
+##### TLS 1.3
+
+For TLS 1.3, **Golang** only supports [3 cipher suites](https://github.com/golang/go/blob/go1.17/src/crypto/tls/cipher_suites.go#L676), as such we only need to set the TLS version:
+
+```golang
+cfg := &tls.Config{
+ MinVersion: tls.VersionTLS13,
+}
+```
+
+For **Ruby**, you can use [HTTParty](https://github.com/jnunemaker/httparty) and specify TLS 1.3 version as well as ciphers:
+
+Whenever possible this example should be **avoided** for security purposes:
+
+```ruby
+response = HTTParty.get('https://gitlab.com', ssl_version: :TLSv1_3, ciphers: ['TLS_AES_128_GCM_SHA256', 'TLS_AES_256_GCM_SHA384', 'TLS_CHACHA20_POLY1305_SHA256'])
+```
+
+When using [`GitLab::HTTP`](#gitlab-http-library), the code looks like:
+
+This is the **recommended** implementation to avoid security issues such as SSRF:
+
+```ruby
+response = GitLab::HTTP.perform_request(Net::HTTP::Get, 'https://gitlab.com', ssl_version: :TLSv1_3, ciphers: ['TLS_AES_128_GCM_SHA256', 'TLS_AES_256_GCM_SHA384', 'TLS_CHACHA20_POLY1305_SHA256'])
+```
+
+##### TLS 1.2
+
+**Golang** does support multiple cipher suites that we do not want to use with TLS 1.2. We need to explicitly list authorized ciphers:
+
+```golang
+func secureCipherSuites() []uint16 {
+ return []uint16{
+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+ tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+ }
+```
+
+And then use `secureCipherSuites()` in `tls.Config`:
+
+```golang
+tls.Config{
+ (...),
+ CipherSuites: secureCipherSuites(),
+ MinVersion: tls.VersionTLS12,
+ (...),
+}
+```
+
+This example was taken [here](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/871b52dc700f1a66f6644fbb1e78a6d463a6ff83/internal/tool/tlstool/tlstool.go#L72).
+
+For **Ruby**, you can use again [HTTParty](https://github.com/jnunemaker/httparty) and specify this time TLS 1.2 version alongside with the recommended ciphers:
+
+```ruby
+response = GitLab::HTTP.perform_request(Net::HTTP::Get, 'https://gitlab.com', ssl_version: :TLSv1_2, ciphers: ['ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-ECDSA-AES256-GCM-SHA384', 'ECDHE-RSA-AES256-GCM-SHA384', 'ECDHE-ECDSA-CHACHA20-POLY1305', 'ECDHE-RSA-CHACHA20-POLY1305'])
+```
+
## GitLab Internal Authorization
### Introduction
@@ -592,3 +680,90 @@ In order to prevent this from happening, it is recommended to use the method `us
forbidden!(api_access_denied_message(user))
end
```
+
+## Guidelines when defining missing methods with metaprogramming
+
+Metaprogramming is a way to define methods **at runtime**, instead of at the time of writing and deploying the code. It is a powerful tool, but can be dangerous if we allow untrusted actors (like users) to define their own arbitrary methods. For example, imagine we accidentally let an attacker overwrite an access control method to always return true! It can lead to many classes of vulnerabilities such as access control bypass, information disclosure, arbitrary file reads, and remote code execution.
+
+Key methods to watch out for are `method_missing`, `define_method`, `delegate`, and similar methods.
+
+### Insecure metaprogramming example
+
+This example is adapted from an example submitted by [@jobert](https://hackerone.com/jobert?type=user) through our HackerOne bug bounty program.
+Thank you for your contribution!
+
+Before Ruby 2.5.1, you could implement delegators using the `delegate` or `method_missing` methods. For example:
+
+```ruby
+class User
+ def initialize(attributes)
+ @options = OpenStruct.new(attributes)
+ end
+
+ def is_admin?
+ name.eql?("Sid") # Note - never do this!
+ end
+
+ def method_missing(method, *args)
+ @options.send(method, *args)
+ end
+end
+```
+
+When a method was called on a `User` instance that didn't exist, it passed it along to the `@options` instance variable.
+
+```ruby
+User.new({name: "Jeeves"}).is_admin?
+# => false
+
+User.new(name: "Sid").is_admin?
+# => true
+
+User.new(name: "Jeeves", "is_admin?" => true).is_admin?
+# => false
+```
+
+Because the `is_admin?` method is already defined on the class, its behavior is not overridden when passing `is_admin?` to the initializer.
+
+This class can be refactored to use the `Forwardable` method and `def_delegators`:
+
+```ruby
+class User
+ extend Forwardable
+
+ def initialize(attributes)
+ @options = OpenStruct.new(attributes)
+
+ self.class.instance_eval do
+ def_delegators :@options, *attributes.keys
+ end
+ end
+
+ def is_admin?
+ name.eql?("Sid") # Note - never do this!
+ end
+end
+```
+
+It might seem like this example has the same behavior as the first code example. However, there's one crucial difference: **because the delegators are meta-programmed after the class is loaded, it can overwrite existing methods**:
+
+```ruby
+User.new({name: "Jeeves"}).is_admin?
+# => false
+
+User.new(name: "Sid").is_admin?
+# => true
+
+User.new(name: "Jeeves", "is_admin?" => true).is_admin?
+# => true
+# ^------------------ The method is overwritten! Sneaky Jeeves!
+```
+
+In the example above, the `is_admin?` method is overwritten when passing it to the initializer.
+
+### Best practices
+
+- Never pass user-provided details into method-defining metaprogramming methods.
+ - If you must, be **very** confident that you've sanitized the values correctly.
+ Consider creating an allowlist of values, and validating the user input against that.
+- When extending classes that use metaprogramming, make sure you don't inadvertently override any method definition safety checks.
diff --git a/doc/development/service_ping/implement.md b/doc/development/service_ping/implement.md
index 34a845147dc..65a8b4c1cad 100644
--- a/doc/development/service_ping/implement.md
+++ b/doc/development/service_ping/implement.md
@@ -295,19 +295,22 @@ Examples of implementation:
- Using Redis methods [`INCR`](https://redis.io/commands/incr), [`GET`](https://redis.io/commands/get), and [`Gitlab::UsageDataCounters::WikiPageCounter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/wiki_page_counter.rb)
- Using Redis methods [`HINCRBY`](https://redis.io/commands/hincrby), [`HGETALL`](https://redis.io/commands/hgetall), and [`Gitlab::UsageCounters::PodLogs`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_counters/pod_logs.rb)
-##### UsageData API tracking
+##### `UsageData` API
-<!-- There's nearly identical content in `##### Adding new events`. If you fix errors here, you may need to fix the same errors in the other location. -->
+You can use the `UsageData` API to track events.
+To track events, the `usage_data_api` feature flag must
+be enabled (set to `default_enabled: true`).
+Enabled by default in GitLab 13.7 and later.
-1. Track event using `UsageData` API
+##### UsageData API tracking
- Increment event count using ordinary Redis counter, for given event name.
+1. Track events using the [`UsageData` API](#usagedata-api).
- Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default.
+ Increment event count using an ordinary Redis counter, for a given event name.
API requests are protected by checking for a valid CSRF token.
- To be able to increment the values, the related feature `usage_data_<event_name>` should be enabled.
+ To increment the values, the related feature `usage_data_<event_name>` must be enabled.
```plaintext
POST /usage_data/increment_counter
@@ -315,18 +318,18 @@ Examples of implementation:
| Attribute | Type | Required | Description |
| :-------- | :--- | :------- | :---------- |
- | `event` | string | yes | The event name it should be tracked |
+ | `event` | string | yes | The event name to track. |
Response:
- - `200` if event was tracked
- - `400 Bad request` if event parameter is missing
- - `401 Unauthorized` if user is not authenticated
- - `403 Forbidden` for invalid CSRF token provided
+ - `200` if the event was tracked.
+ - `400 Bad request` if the event parameter is missing.
+ - `401 Unauthorized` if the user is not authenticated.
+ - `403 Forbidden` if an invalid CSRF token is provided.
-1. Track events using JavaScript/Vue API helper which calls the API above
+1. Track events using the JavaScript/Vue API helper which calls the [`UsageData` API](#usagedata-api).
- Note that `usage_data_api` and `usage_data_#{event_name}` should be enabled to be able to track events
+ To track events, `usage_data_api` and `usage_data_#{event_name}` must be enabled.
```javascript
import api from '~/api';
@@ -460,14 +463,10 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
track_usage_event(:incident_management_incident_created, current_user.id)
```
- - Using the `UsageData` API.
- <!-- There's nearly identical content in `##### UsageData API Tracking`. If you find / fix errors here, you may need to fix errors in that section too. -->
+ - Using the [`UsageData` API](#usagedata-api).
Increment unique users count using Redis HLL, for a given event name.
- To track events using the `UsageData` API, ensure the `usage_data_api` feature flag
- is set to `default_enabled: true`. Enabled by default in GitLab 13.7 and later.
-
API requests are protected by checking for a valid CSRF token.
```plaintext
@@ -485,10 +484,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
- `401 Unauthorized` if the user is not authenticated.
- `403 Forbidden` if an invalid CSRF token is provided.
- - Using the JavaScript/Vue API helper, which calls the `UsageData` API.
-
- To track events using the `UsageData` API, ensure the `usage_data_api` feature flag
- is set to `default_enabled: true`. Enabled by default in GitLab 13.7 and later.
+ - Using the JavaScript/Vue API helper, which calls the [`UsageData` API](#usagedata-api).
Example for an existing event already defined in [known events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/):
@@ -559,13 +555,18 @@ We can also disable tracking completely by using the global flag:
##### Known events are added automatically in Service Data payload
-All events added in [`known_events/common.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml) are automatically added to Service Data generation under the `redis_hll_counters` key. This column is stored in [version-app as a JSON](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L209).
+Service Ping adds all events [`known_events/*.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events) to Service Data generation under the `redis_hll_counters` key. This column is stored in [version-app as a JSON](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L209).
For each event we add metrics for the weekly and monthly time frames, and totals for each where applicable:
- `#{event_name}_weekly`: Data for 7 days for daily [aggregation](#add-new-events) events and data for the last complete week for weekly [aggregation](#add-new-events) events.
- `#{event_name}_monthly`: Data for 28 days for daily [aggregation](#add-new-events) events and data for the last 4 complete weeks for weekly [aggregation](#add-new-events) events.
-Redis HLL implementation calculates automatic total metrics, if there are more than one metric for the same category, aggregation, and Redis slot.
+Redis HLL implementation calculates total metrics when both of these conditions are met:
+
+- The category is manually included in [CATEGORIES_FOR_TOTALS](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/hll_redis_counter.rb#L21).
+- There is more than one metric for the same category, aggregation, and Redis slot.
+
+We add total unique counts for the weekly and monthly time frames where applicable:
- `#{category}_total_unique_counts_weekly`: Total unique counts for events in the same category for the last 7 days or the last complete week, if events are in the same Redis slot and we have more than one metric.
- `#{category}_total_unique_counts_monthly`: Total unique counts for events in same category for the last 28 days or the last 4 complete weeks, if events are in the same Redis slot and we have more than one metric.
diff --git a/doc/development/service_ping/index.md b/doc/development/service_ping/index.md
index 19bf7446da9..6ddbe2f9646 100644
--- a/doc/development/service_ping/index.md
+++ b/doc/development/service_ping/index.md
@@ -50,35 +50,57 @@ We use the following terminology to describe the Service Ping components:
- **Metrics**: primarily made up of row counts for different tables in an instance's database. Each
metric has a corresponding [metric definition](metrics_dictionary.md#metrics-definition-and-validation)
in a YAML file.
+- **MAU**: monthly active users.
+- **WAU**: weekly active users.
### Why should we enable Service Ping?
- The main purpose of Service Ping is to build a better GitLab. Data about how GitLab is used is collected to better understand feature/stage adoption and usage, which helps us understand how GitLab is adding value and helps our team better understand the reasons why people use GitLab and with this knowledge we're able to make better product decisions.
- As a benefit of having Service Ping active, GitLab lets you analyze the users' activities over time of your GitLab installation.
-- As a benefit of having Service Ping active, GitLab provides you with The DevOps Report,which gives you an overview of your entire instance's adoption of Concurrent DevOps from planning to monitoring.
+- As a benefit of having Service Ping active, GitLab provides you with [DevOps Score](../../user/admin_area/analytics/dev_ops_report.md#devops-score), which gives you an overview of your entire instance's adoption of Concurrent DevOps from planning to monitoring.
- You get better, more proactive support. (assuming that our TAMs and support organization used the data to deliver more value)
- You get insight and advice into how to get the most value out of your investment in GitLab. Wouldn't you want to know that a number of features or values are not being adopted in your organization?
- You get a report that illustrates how you compare against other similar organizations (anonymized), with specific advice and recommendations on how to improve your DevOps processes.
- Service Ping is enabled by default. To disable it, see [Disable Service Ping](#disable-service-ping).
- When Service Ping is enabled, you have the option to participate in our [Registration Features Program](#registration-features-program) and receive free paid features.
-#### Registration Features Program
+### Limitations
+
+- Service Ping does not track frontend events things like page views, link clicks, or user sessions.
+- Service Ping focuses only on aggregated backend events.
+
+Because of these limitations we recommend you:
+
+- Instrument your products with Snowplow for more detailed analytics on GitLab.com.
+- Use Service Ping to track aggregated backend events on self-managed instances.
+
+### Registration Features Program
> Introduced in GitLab 14.1.
-Starting with GitLab version 14.1, free self-managed users running [GitLab EE](../ee_features.md) can receive paid features by registering with GitLab and sending us activity data via [Service Ping](#what-is-service-ping). Features introduced here do not remove the feature from its paid tier. Users can continue to access the features in a paid tier without sharing usage data.
+In GitLab versions 14.1 and later, free self-managed users running [GitLab EE](../ee_features.md) can receive paid features by registering with GitLab and sending us activity data through [Service Ping](#what-is-service-ping). Features introduced here do not remove the feature from its paid tier. Users can continue to access the features in a paid tier without sharing usage data.
-##### Features available in 14.1 and later
+#### Features available in 14.1 and later
1. [Email from GitLab](../../tools/email.md).
+#### Features available in 14.4 and later
+
+1. [Repository size limit](../../user/admin_area/settings/account_and_limit_settings.md#repository-size-limit).
+1. [Restrict group access by IP address](../../user/group/index.md#restrict-group-access-by-ip-address).
+
NOTE:
Registration is not yet required for participation, but will be added in a future milestone.
-### Limitations
+#### Enable Registration Features
-- Service Ping does not track frontend events things like page views, link clicks, or user sessions, and only focuses on aggregated backend events.
-- Because of these limitations we recommend instrumenting your products with Snowplow for more detailed analytics on GitLab.com and use Service Ping to track aggregated backend events on self-managed.
+1. Sign in as a user with the [Administrator](../../user/permissions.md) role.
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Settings > Metrics and profiling**.
+1. Expand the **Usage statistics** section.
+1. If not enabled, select the **Enable Service Ping** checkbox.
+1. Select the **Enable Registration Features** checkbox.
+1. Select **Save changes**.
## View the Service Ping payload **(FREE SELF)**
@@ -180,7 +202,7 @@ sequenceDiagram
S3 Bucket->>Snowflake DW: Import data
Snowflake DW->>Snowflake DW: Transform data using dbt
Snowflake DW->>Sisense Dashboards: Data available for querying
- Versions Application->>GitLab Instance: DevOps Report (Conversational Development Index)
+ Versions Application->>GitLab Instance: DevOps Score (Conversational Development Index)
```
## How Service Ping works
@@ -209,10 +231,6 @@ We also collect metrics specific to [Geo](../../administration/geo/index.md) sec
"repositories_replication_enabled"=>true,
"repositories_synced_count"=>24,
"repositories_failed_count"=>0,
- "attachments_replication_enabled"=>true,
- "attachments_count"=>1,
- "attachments_synced_count"=>1,
- "attachments_failed_count"=>0,
"git_fetch_event_count_weekly"=>nil,
"git_push_event_count_weekly"=>nil,
... other geo node status fields
@@ -450,27 +468,56 @@ bin/rake gitlab:usage_data:dump_sql_in_json
bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02.yaml
```
-## Generating and troubleshooting Service Ping
-
-This activity is to be done via a detached screen session on a remote server.
+## Generate Service Ping
-Before you begin these steps, make sure the key is added to the SSH agent locally
-with the `ssh-add` command.
+To generate Service Ping, use [Teleport](https://goteleport.com/docs/) or a detached screen session on a remote server.
### Triggering
-1. Connect to bastion with agent forwarding: `$ ssh -A lb-bastion.gprd.gitlab.com`
-1. Create named screen: `$ screen -S <username>_usage_ping_<date>`
-1. Connect to console host: `$ ssh $USER-rails@console-01-sv-gprd.c.gitlab-production.internal`
-1. Run `SubmitUsagePingService.new.execute`
-1. Detach from screen: `ctrl + a, ctrl + d`
-1. Exit from bastion: `$ exit`
+#### Trigger Service Ping with Teleport
+
+1. Request temporary [access](https://gitlab.com/gitlab-com/runbooks/-/blob/master/docs/Teleport/Connect_to_Rails_Console_via_Teleport.md#how-to-use-teleport-to-connect-to-rails-console) to the required environment.
+1. After your approval is issued, [access the Rails console](https://gitlab.com/gitlab-com/runbooks/-/blob/master/docs/Teleport/Connect_to_Rails_Console_via_Teleport.md#access-approval).
+1. Run `ServicePing::SubmitService.new.execute`.
+
+#### Trigger Service Ping with a detached screen session
+
+1. Connect to bastion with agent forwarding:
+
+ `$ ssh -A lb-bastion.gprd.gitlab.com`.
+1. Create named screen:
+
+ `$ screen -S <username>_usage_ping_<date>`.
+1. Connect to console host:
+
+ `$ ssh $USER-rails@console-01-sv-gprd.c.gitlab-production.internal`.
+1. Run `ServicePing::SubmitService.new.execute`
+1. Detach from screen:
+
+ `ctrl + a, ctrl + d`
+1. Exit from bastion:
+
+ `$ exit`
### Verification (After approx 30 hours)
-1. Reconnect to bastion: `$ ssh -A lb-bastion.gprd.gitlab.com`
-1. Find your screen session: `$ screen -ls`
-1. Attach to your screen session: `$ screen -x 14226.mwawrzyniak_usage_ping_2021_01_22`
+#### Verify with a detached screen session
+
+1. Follow [the steps](https://gitlab.com/gitlab-com/runbooks/-/blob/master/docs/Teleport/Connect_to_Rails_Console_via_Teleport.md#how-to-use-teleport-to-connect-to-rails-console) to request a new access to the required environment and connect to the Rails console
+1. Check the last payload in `raw_usage_data` table: `RawUsageData.last.payload`
+1. Check the when the payload was sent: `RawUsageData.last.sent_at`
+
+#### Verify using detached screen session
+
+1. Reconnect to bastion:
+
+ `$ ssh -A lb-bastion.gprd.gitlab.com`
+1. Find your screen session:
+
+ `$ screen -ls`
+1. Attach to your screen session:
+
+ `$ screen -x 14226.mwawrzyniak_usage_ping_2021_01_22`
1. Check the last payload in `raw_usage_data` table: `RawUsageData.last.payload`
1. Check the when the payload was sent: `RawUsageData.last.sent_at`
diff --git a/doc/development/service_ping/metrics_dictionary.md b/doc/development/service_ping/metrics_dictionary.md
index c1478e6290e..b3c404de150 100644
--- a/doc/development/service_ping/metrics_dictionary.md
+++ b/doc/development/service_ping/metrics_dictionary.md
@@ -197,18 +197,28 @@ tier:
The GitLab codebase provides a dedicated [generator](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/generators/gitlab/usage_metric_definition_generator.rb) to create new metric definitions.
-For uniqueness, the generated file includes a timestamp prefix, in ISO 8601 format.
+For uniqueness, the generated files include a timestamp prefix in ISO 8601 format.
-The generator takes the key path argument and 2 options and creates the metric YAML definition in corresponding location:
+The generator takes a list of key paths and 2 options as arguments. It creates metric YAML definitions in the corresponding location:
- `--ee`, `--no-ee` Indicates if metric is for EE.
-- `--dir=DIR` indicates the metric directory. It must be one of: `counts_7d`, `7d`, `counts_28d`, `28d`, `counts_all`, `all`, `settings`, `license`.
+- `--dir=DIR` Indicates the metric directory. It must be one of: `counts_7d`, `7d`, `counts_28d`, `28d`, `counts_all`, `all`, `settings`, `license`.
+
+**Single metric example**
```shell
bundle exec rails generate gitlab:usage_metric_definition counts.issues --dir=7d
create config/metrics/counts_7d/issues.yml
```
+**Multiple metrics example**
+
+```shell
+bundle exec rails generate gitlab:usage_metric_definition counts.issues counts.users --dir=7d
+create config/metrics/counts_7d/issues.yml
+create config/metrics/counts_7d/users.yml
+```
+
NOTE:
To create a metric definition used in EE, add the `--ee` flag.
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index d45e2073fe7..e28a328888d 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -255,6 +255,11 @@ module Ci
end
```
+Also, you can pass `if_deduplicated: :reschedule_once` option to re-run a job once after
+the currently running job finished and deduplication happened at least once.
+This ensures that the latest result is always produced even if a race condition
+happened. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/342123) for more information.
+
#### Scheduling jobs in the future
GitLab doesn't skip jobs scheduled in the future, as we assume that
@@ -279,6 +284,36 @@ module AuthorizedProjectUpdate
end
```
+### Setting the deduplication time-to-live (TTL)
+
+Deduplication depends on an idempotency key that is stored in Redis. This is normally
+cleared by the configured deduplication strategy.
+
+However, the key can remain until its TTL in certain cases like:
+
+1. `until_executing` is used but the job was never enqueued or executed after the Sidekiq
+ client middleware was run.
+
+1. `until_executed` is used but the job fails to finish due to retry exhaustion, gets
+ interrupted the maximum number of times, or gets lost.
+
+The default value is 6 hours. During this time, jobs won't be enqueued even if the first
+job never executed or finished.
+
+The TTL can be configured with:
+
+```ruby
+class ProjectImportScheduleWorker
+ include ApplicationWorker
+
+ idempotent!
+ deduplicate :until_executing, ttl: 5.minutes
+end
+```
+
+Duplicate jobs can happen when the TTL is reached, so make sure you lower this only for jobs
+that can tolerate some duplication.
+
### Deduplication with load balancing
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6763) in GitLab 14.4.
@@ -740,8 +775,7 @@ We use the following approach to determine whether a worker is CPU-bound:
## Feature category
-All Sidekiq workers must define a known [feature
-category](feature_categorization/index.md#sidekiq-workers).
+All Sidekiq workers must define a known [feature category](feature_categorization/index.md#sidekiq-workers).
## Job weights
diff --git a/doc/development/snowplow/implementation.md b/doc/development/snowplow/implementation.md
index 0d81b442850..fe1de789eae 100644
--- a/doc/development/snowplow/implementation.md
+++ b/doc/development/snowplow/implementation.md
@@ -102,14 +102,12 @@ track_action: "click_button" })
### Implement Vue component tracking
For custom event tracking, use a Vue `mixin` in components. Vue `mixin` exposes the `Tracking.event`
-static method and the `track` method called from components or templates. You can specify tracking
-options in `data` or `computed`. These options override any defaults and allow the values to be dynamic
-from props or based on state.
+static method and the `track` method. You can specify tracking options in `data` or `computed`.
+These options override any defaults and allow the values to be dynamic from props or based on state.
-Default options are passed when an event is tracked from the component. If you don't specify an option,
-the default `document.body.dataset.page` is used. The default options are:
+Several default options are passed when an event is tracked from the component:
-- `category`
+- `category`: If you don't specify, by default `document.body.dataset.page` is used.
- `label`
- `property`
- `value`
@@ -426,7 +424,7 @@ records the same events as the full Snowplow pipeline. To query events, use the
To install and run Snowplow Micro, complete these steps to modify the
[GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit):
-1. Ensure Docker is installed and running.
+1. Ensure [Docker is installed](https://docs.docker.com/get-docker/) and running.
1. To install Snowplow Micro, clone the settings in
[this project](https://gitlab.com/gitlab-org/snowplow-micro-configuration).
@@ -438,73 +436,18 @@ To install and run Snowplow Micro, complete these steps to modify the
./snowplow-micro.sh
```
-1. Use GDK to start the PostgreSQL terminal and connect
- to the `gitlabhq_development` database:
+1. Set the environment variable to tell the GDK to use Snowplow Micro in development. This overrides two `application_settings` options:
+ - `snowplow_enabled` setting will instead return `true` from `Gitlab::Tracking.enabled?`
+ - `snowplow_collector_hostname` setting will instead always return `localhost:9090` (or whatever is set for `SNOWPLOW_MICRO_URI`) from `Gitlab::Tracking.collector_hostname`.
```shell
- gdk psql -d gitlabhq_development
+ export SNOWPLOW_MICRO_ENABLE=1
```
-1. Update your instance's settings to enable Snowplow events and
- point to the Snowplow Micro collector:
+ Optionally, you can set the URI for you Snowplow Micro instance as well (the default value is `http://localhost:9090`):
```shell
- update application_settings set snowplow_collector_hostname='localhost:9090', snowplow_enabled=true, snowplow_cookie_domain='.gitlab.com';
- ```
-
-1. Update `DEFAULT_SNOWPLOW_OPTIONS` in `app/assets/javascripts/tracking/constants.js` to remove `forceSecureTracker: true`:
-
- ```diff
- diff --git a/app/assets/javascripts/tracking/constants.js b/app/assets/javascripts/tracking/constants.js
- index 598111e4086..eff38074d4c 100644
- --- a/app/assets/javascripts/tracking/constants.js
- +++ b/app/assets/javascripts/tracking/constants.js
- @@ -7,7 +7,6 @@ export const DEFAULT_SNOWPLOW_OPTIONS = {
- appId: '',
- userFingerprint: false,
- respectDoNotTrack: true,
- - forceSecureTracker: true,
- eventMethod: 'post',
- contexts: { webPage: true, performanceTiming: true },
- formTracking: false,
- ```
-
-1. Update `options` in `lib/gitlab/tracking.rb` to add `protocol` and `port`:
-
- ```diff
- diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
- index 618e359211b..e9084623c43 100644
- --- a/lib/gitlab/tracking.rb
- +++ b/lib/gitlab/tracking.rb
- @@ -41,7 +41,9 @@ def options(group)
- cookie_domain: Gitlab::CurrentSettings.snowplow_cookie_domain,
- app_id: Gitlab::CurrentSettings.snowplow_app_id,
- form_tracking: additional_features,
- - link_click_tracking: additional_features
- + link_click_tracking: additional_features,
- + protocol: 'http',
- + port: 9090
- }.transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
- end
- ```
-
-1. Update `emitter` in `lib/gitlab/tracking/destinations/snowplow.rb` to change `protocol`:
-
- ```diff
- diff --git a/lib/gitlab/tracking/destinations/snowplow.rb b/lib/gitlab/tracking/destinations/snowplow.rb
- index 4fa844de325..5dd9d0eacfb 100644
- --- a/lib/gitlab/tracking/destinations/snowplow.rb
- +++ b/lib/gitlab/tracking/destinations/snowplow.rb
- @@ -40,7 +40,7 @@ def tracker
- def emitter
- SnowplowTracker::AsyncEmitter.new(
- Gitlab::CurrentSettings.snowplow_collector_hostname,
- - protocol: 'https'
- + protocol: 'http'
- )
- end
- end
-
+ export SNOWPLOW_MICRO_URI=https://127.0.0.1:8080
```
1. Restart GDK:
diff --git a/doc/development/snowplow/index.md b/doc/development/snowplow/index.md
index b8b35857adf..f4f41221699 100644
--- a/doc/development/snowplow/index.md
+++ b/doc/development/snowplow/index.md
@@ -6,10 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Snowplow
-This page provides an overview of how Snowplow works and how to enable it.
-
-## What is Snowplow
-
Snowplow is an enterprise-grade marketing and Product Intelligence platform that tracks how users engage with our website and application.
[Snowplow](https://snowplowanalytics.com) consists of several loosely-coupled sub-systems:
@@ -23,12 +19,6 @@ Snowplow is an enterprise-grade marketing and Product Intelligence platform that
![snowplow_flow](../img/snowplow_flow.png)
-### Useful links
-
-- [Snowplow data structure](https://docs.snowplowanalytics.com/docs/understanding-your-pipeline/canonical-event/)
-- [Our Iglu schema registry](https://gitlab.com/gitlab-org/iglu)
-- [List of events used in our codebase (Event Dictionary)](https://metrics.gitlab.com/snowplow.html)
-
## Enable Snowplow tracking
Tracking can be enabled at:
@@ -165,6 +155,9 @@ Snowplow JavaScript adds [web-specific parameters](https://docs.snowplowanalytic
## Related topics
+- [Snowplow data structure](https://docs.snowplowanalytics.com/docs/understanding-your-pipeline/canonical-event/)
+- [Our Iglu schema registry](https://gitlab.com/gitlab-org/iglu)
+- [List of events used in our codebase (Event Dictionary)](https://metrics.gitlab.com/snowplow.html)
- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
- [Service Ping Guide](../service_ping/index.md)
- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/)
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index 52e89a10556..6a739d9e1a5 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -50,6 +50,23 @@ bundle exec guard
When using spring and guard together, use `SPRING=1 bundle exec guard` instead to make use of spring.
+### Eager loading the application code
+
+By default, the application code:
+
+- Isn't eagerly loaded in the `test` environment.
+- Is eagerly loaded in CI/CD (when `ENV['CI'].present?`) to surface any potential loading issues.
+
+If you need to enable eager loading when executing tests,
+use the `GITLAB_TEST_EAGER_LOAD` environment variable:
+
+```shell
+GITLAB_TEST_EAGER_LOAD=1 bin/rspec spec/models/project_spec.rb
+```
+
+If your test depends on all the application code that is being loaded, add the `:eager_load` tag.
+This ensures that the application code is eagerly loaded before the test execution.
+
### Ruby warnings
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47767) in GitLab 13.7.
diff --git a/doc/development/testing_guide/end_to_end/beginners_guide.md b/doc/development/testing_guide/end_to_end/beginners_guide.md
index 7370cc5771b..27a87d25170 100644
--- a/doc/development/testing_guide/end_to_end/beginners_guide.md
+++ b/doc/development/testing_guide/end_to_end/beginners_guide.md
@@ -350,7 +350,7 @@ GITLAB_PASSWORD=<GDK root password> bundle exec bin/qa Test::Instance::All http:
Where `<test_file>` is:
- `qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb` when running the Login example.
-- `qa/specs/features/browser_ui/2_plan/issues/create_issue_spec.rb` when running the Issue example.
+- `qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb` when running the Issue example.
## End-to-end test merge request template
diff --git a/doc/development/testing_guide/end_to_end/feature_flags.md b/doc/development/testing_guide/end_to_end/feature_flags.md
index 994ee3f253c..52212410cc6 100644
--- a/doc/development/testing_guide/end_to_end/feature_flags.md
+++ b/doc/development/testing_guide/end_to_end/feature_flags.md
@@ -79,11 +79,21 @@ for details.
End-to-end tests should pass with a feature flag enabled before it is enabled on Staging or on GitLab.com. Tests that need to be updated should be identified as part of [quad-planning](https://about.gitlab.com/handbook/engineering/quality/quad-planning/). The relevant [counterpart Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) is responsible for updating the tests or assisting another engineer to do so. However, if a change does not go through quad-planning and a required test update is not made, test failures could block deployment.
-If a test enables a feature flag as describe above, it is sufficient to run the `package-and-qa` job in a merge request containing the relevant changes.
-Or, if the feature flag and relevant changes have already been merged, you can confirm that the tests
-pass on `main`. The end-to-end tests run on `main` every two hours, and the results are posted to a [Test
-Session Report, which is available in the testcase-sessions project](https://gitlab.com/gitlab-org/quality/testcase-sessions/-/issues?label_name%5B%5D=found%3Amaster).
+### Automatic test execution when a feature flag definition changes
-If the relevant tests do not enable the feature flag themselves, you can check if the tests will need
-to be updated by opening a draft merge request that enables the flag by default and then running the `package-and-qa` job.
+If a merge request adds or edits a [feature flag definition file](../../feature_flags/index.md#feature-flag-definition-and-validation),
+two `package-and-qa` jobs will be included automatically in the merge request pipeline. One job will enable the defined
+feature flag and the other will disable it. The jobs execute the same suite of tests to confirm that they pass with if
+the feature flag is either enabled or disabled.
+
+### Test execution during feature development
+
+If an end-to-end test enables a feature flag, the end-to-end test suite can be used to test changes in a merge request
+by running the `package-and-qa` job in the merge request pipeline. If the feature flag and relevant changes have already been merged, you can confirm that the tests
+pass on the default branch. The end-to-end tests run on the default branch every two hours, and the results are posted to a [Test
+Session Report, which is available in the testcase-sessions project](https://gitlab.com/gitlab-org/quality/testcase-sessions/-/issues?label_name%5B%5D=found%3Amain).
+
+If the relevant tests do not enable the feature flag themselves, you can check if the tests will need to be updated by opening
+a draft merge request that enables the flag by default via a [feature flag definition file](../../feature_flags/index.md#feature-flag-definition-and-validation).
+That will [automatically execute the end-to-end test suite](#automatic-test-execution-when-a-feature-flag-definition-changes).
The merge request can be closed once the tests pass. If you need assistance to update the tests, please contact the relevant [stable counterpart in the Quality department](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors), or any Software Engineer in Test if there is no stable counterpart for your group.
diff --git a/doc/development/testing_guide/end_to_end/index.md b/doc/development/testing_guide/end_to_end/index.md
index b097d6b0729..57c8c3bf59c 100644
--- a/doc/development/testing_guide/end_to_end/index.md
+++ b/doc/development/testing_guide/end_to_end/index.md
@@ -147,7 +147,7 @@ as well as these:
| Variable | Description |
|-|-|
| `QA_SCENARIO` | The scenario to run (default `Test::Instance::Image`) |
-| `QA_TESTS` | The test(s) to run (no default, which means run all the tests in the scenario). Use file paths as you would when running tests via RSpec, e.g., `qa/specs/features/ee/browser_ui` would include all the `EE` UI tests. |
+| `QA_TESTS` | The test(s) to run (no default, which means run all the tests in the scenario). Use file paths as you would when running tests via RSpec, for example, `qa/specs/features/ee/browser_ui` would include all the `EE` UI tests. |
| `QA_RSPEC_TAGS` | The RSpec tags to add (no default) |
For now [manual jobs with custom variables don't use the same variable
diff --git a/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md b/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md
index eadd0ef49a0..95984a701e7 100644
--- a/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md
+++ b/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md
@@ -165,20 +165,20 @@ QA_DEBUG=true WEBDRIVER_HEADLESS=false GITLAB_ADMIN_USERNAME=rootusername GITLAB
The following includes more information on the command:
--`QA_DEBUG` - Set to `true` to verbosely log page object actions.
--`WEBDRIVER_HEADLESS` - When running locally, set to `false` to allow browser tests to be visible - watch your tests being run.
--`GITLAB_ADMIN_USERNAME` - Administrator username to use when adding a license.
--`GITLAB_ADMIN_PASSWORD` - Administrator password to use when adding a license.
--`GITLAB_QA_ACCESS_TOKEN` and `GITLAB_QA_ADMIN_ACCESS_TOKEN` - A valid personal access token with the `api` scope. This is used for API access during tests, and is used in the version that staging is currently running. The `ADMIN_ACCESS_TOKEN` is from a user with administrator access. Used for API access as an administrator during tests.
--`CLUSTER_API_URL` - Use the address `https://kubernetes.docker.internal:6443` . This address is used to enable the cluster to be network accessible while deploying using Auto DevOps.
--`https://[YOUR-PORT].qa-tunnel.gitlab.info/` - The address of your local GDK
--`qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb` - The path to the monitor core specs
--`--tag` - the meta-tags used to filter the specs correctly
+- `QA_DEBUG` - Set to `true` to verbosely log page object actions.
+- `WEBDRIVER_HEADLESS` - When running locally, set to `false` to allow browser tests to be visible - watch your tests being run.
+- `GITLAB_ADMIN_USERNAME` - Administrator username to use when adding a license.
+- `GITLAB_ADMIN_PASSWORD` - Administrator password to use when adding a license.
+- `GITLAB_QA_ACCESS_TOKEN` and `GITLAB_QA_ADMIN_ACCESS_TOKEN` - A valid personal access token with the `api` scope. This is used for API access during tests, and is used in the version that staging is currently running. The `ADMIN_ACCESS_TOKEN` is from a user with administrator access. Used for API access as an administrator during tests.
+- `CLUSTER_API_URL` - Use the address `https://kubernetes.docker.internal:6443` . This address is used to enable the cluster to be network accessible while deploying using Auto DevOps.
+- `https://[YOUR-PORT].qa-tunnel.gitlab.info/` - The address of your local GDK
+- `qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb` - The path to the monitor core specs
+- `--tag` - the meta-tags used to filter the specs correctly
At the moment of this writing, there are two specs which run monitor tests:
--`qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb` - has the specs of features in GitLab Free
--`qa/specs/features/ee/browser_ui/8_monitor/all_monitor_features_spec.rb` - has the specs of features for paid GitLab (Enterprise Edition)
+- `qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb` - has the specs of features in GitLab Free
+- `qa/specs/features/ee/browser_ui/8_monitor/all_monitor_features_spec.rb` - has the specs of features for paid GitLab (Enterprise Edition)
### How to debug
@@ -485,3 +485,109 @@ To run the LDAP tests on your local with TLS disabled, follow these steps:
```shell
GITLAB_LDAP_USERNAME="tanuki" GITLAB_LDAP_PASSWORD="password" QA_DEBUG=true WEBDRIVER_HEADLESS=false bin/qa Test::Instance::All http://localhost qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
```
+
+## Guide to the mobile suite
+
+### What are mobile tests
+
+Tests that are tagged with `:mobile` can be run against specified mobile devices using cloud emulator/simulator services.
+
+### How to run mobile tests with Sauce Labs
+
+Running directly against an environment like staging is not recommended because Sauce Labs test logs expose credentials. Therefore, it is best practice and the default to use a tunnel.
+
+Tunnel installation instructions are here [https://docs.saucelabs.com/secure-connections/sauce-connect/installation]. To start the tunnel, after following the installation above, copy the run command in Sauce Labs > Tunnels (must be logged in to Sauce Labs with the credentials found in 1Password) and run in terminal.
+
+NOTE:
+It is highly recommended to use `GITLAB_QA_ACCESS_TOKEN` to speed up tests and reduce flakiness.
+
+`QA_REMOTE_MOBILE_DEVICE_NAME` can be any device name listed in [https://saucelabs.com/platform/supported-browsers-devices] under Emulators/simulators and the latest versions of Android or iOS. `QA_BROWSER` must be set to `safari` for iOS devices and `chrome` for Android devices.
+
+1. To test against a local instance with a tunnel running, in `gitlab/qa` run:
+
+```shell
+$ QA_BROWSER="safari" \
+ QA_REMOTE_MOBILE_DEVICE_NAME="iPhone 12 Simulator" \
+ QA_REMOTE_GRID="ondemand.saucelabs.com:80" \
+ QA_REMOTE_GRID_USERNAME="gitlab-sl" \
+ QA_REMOTE_GRID_ACCESS_KEY="<found in Sauce Lab account>" \
+ GITLAB_QA_ACCESS_TOKEN="<token>" \
+ bundle exec bin/qa Test::Instance::All http://<local_ip>:3000 -- <relative_spec_path>
+```
+
+Results can be watched in real time while logged into Sauce Labs under AUTOMATED > Test Results.
+
+### How to add an existing test to the mobile suite
+
+The main reason a test might fail when adding the `:mobile` tag is navigation differences in desktop vs mobile layouts, therefore the test needs to be updated to use mobile navigation when running mobile tests.
+
+If an existing method needs to be changed or a new one created, a new mobile page object should be created in `qa/qa/mobile/page/` and it should be prepended in the original page object by adding:
+
+```ruby
+prepend Mobile::Page::NewPageObject if Runtime::Env.mobile_layout?
+```
+
+For example to change an existing method when running mobile tests:
+
+New mobile page object:
+
+```ruby
+module QA
+ module Mobile
+ module Page
+ module Project
+ module Show
+ extend QA::Page::PageConcern
+
+ def self.prepended(base)
+ super
+
+ base.class_eval do
+ prepend QA::Mobile::Page::Main::Menu
+
+ view 'app/assets/javascripts/nav/components/top_nav_new_dropdown.vue' do
+ element :new_issue_mobile_button
+ end
+ end
+ end
+
+ def go_to_new_issue
+ open_mobile_new_dropdown
+
+ click_element(:new_issue_mobile_button)
+ end
+ end
+ end
+ end
+ end
+end
+```
+
+Original page object prepending the new mobile if there's a mobile layout:
+
+```ruby
+module QA
+ module Page
+ module Project
+ class Show < Page::Base
+ prepend Mobile::Page::Project::Show if Runtime::Env.mobile_layout?
+
+ view 'app/views/layouts/header/_new_dropdown.html.haml' do
+ element :new_menu_toggle
+ end
+
+ view 'app/helpers/nav/new_dropdown_helper.rb' do
+ element :new_issue_link
+ end
+
+ def go_to_new_issue
+ click_element(:new_menu_toggle)
+ click_element(:new_issue_link)
+ end
+ end
+ end
+ end
+end
+```
+
+When running mobile tests for phone layouts, both `remote_mobile_device_name` and `mobile_layout` are `true` but when using a tablet layout, only `remote_mobile_device_name` is true. This is because phone layouts have more menus closed by default such as how both tablets and phones have the left nav closed but unlike phone layouts, tablets have the regular top navigation bar, not the mobile one. So in the case where the navigation being edited needs to be used in tablet layouts as well, use `remote_mobile_device_name` instead of `mobile_layout?` when prepending so it will use it if it's a tablet layout as well.
diff --git a/doc/development/testing_guide/end_to_end/style_guide.md b/doc/development/testing_guide/end_to_end/style_guide.md
index 22ddae6e836..a9571df1188 100644
--- a/doc/development/testing_guide/end_to_end/style_guide.md
+++ b/doc/development/testing_guide/end_to_end/style_guide.md
@@ -14,7 +14,7 @@ This document describes the conventions used at GitLab for writing End-to-end (E
When clicking in a single link to navigate, use `click_`.
-E.g.:
+For example:
```ruby
def click_ci_cd_pipelines
@@ -33,7 +33,7 @@ From a testing perspective, if we want to check that clicking a link, or a butto
When interacting with multiple elements to go to a page, use `go_to_`.
-E.g.:
+For example:
```ruby
def go_to_operations_environments
@@ -63,12 +63,12 @@ We follow a simple formula roughly based on Hungarian notation.
- `type`: A generic control on the page that can be seen by a user.
- `_button`
- `_checkbox`
- - `_container`: an element that includes other elements, but doesn't present visible content itself. E.g., an element that has a third-party editor inside it, but which isn't the editor itself and so doesn't include the editor's content.
+ - `_container`: an element that includes other elements, but doesn't present visible content itself. For example, an element that has a third-party editor inside it, but which isn't the editor itself and so doesn't include the editor's content.
- `_content`: any element that contains text, images, or any other content displayed to the user.
- `_dropdown`
- `_field`: a text input element.
- `_link`
- - `_modal`: a popup modal dialog, e.g., a confirmation prompt.
+ - `_modal`: a popup modal dialog, for example, a confirmation prompt.
- `_placeholder`: a temporary element that appears while content is loading. For example, the elements that are displayed instead of discussions while the discussions are being fetched.
- `_radio`
- `_tab`
@@ -116,7 +116,7 @@ we use the name of the page object in [snake_case](https://en.wikipedia.org/wiki
(all lowercase, with words separated by an underscore). See good and bad examples below.
While we prefer to follow the standard in most cases, it is also acceptable to
-use common abbreviations (e.g., `mr`) or other alternatives, as long as
+use common abbreviations (for example, `mr`) or other alternatives, as long as
the name is not ambiguous. This can include appending `_page` if it helps to
avoid confusion or make the code more readable. For example, if a page object is
named `New`, it could be confusing to name the block argument `new` because that
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index 0e721ba2760..3096386d7c3 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -423,7 +423,8 @@ it('passes', () => {
### Waiting in tests
Sometimes a test needs to wait for something to happen in the application before it continues.
-Avoid using [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)
+Avoid using [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout)
+
because it makes the reason for waiting unclear. Instead use one of the following approaches.
#### Promises and Ajax calls
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 4091f213a8f..3190ab6c899 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -16,6 +16,7 @@ For any of the following scenarios, the `start-review-app-pipeline` job would be
- for merge requests with frontend changes
- for merge requests with QA changes
- for scheduled pipelines
+- the MR has the `pipeline:run-review-app` label set
## QA runs on Review Apps
@@ -37,6 +38,15 @@ browser performance testing using a
## How to
+### Redeploy Review App from a clean slate
+
+To reset Review App and redeploy from a clean slate, do the following:
+
+1. Run `review-stop` job.
+1. Re-deploy by running or retrying `review-deploy` job.
+
+Doing this will remove all existing data from a previously deployed Review App.
+
### Get access to the GCP Review Apps cluster
You need to [open an access request (internal link)](https://gitlab.com/gitlab-com/access-requests/-/issues/new)
@@ -180,7 +190,7 @@ subgraph "CNG-mirror pipeline"
**Additional notes:**
- If the `review-deploy` job keeps failing (and a manual retry didn't help),
- please post a message in the `#g_qe_engineering_productivity` channel and/or create a `~"Engineering Productivity"` `~"ep::review apps"` `~bug`
+ please post a message in the `#g_qe_engineering_productivity` channel and/or create a `~"Engineering Productivity"` `~"ep::review apps"` `~"type::bug"`
issue with a link to your merge request. Note that the deployment failure can
reveal an actual problem introduced in your merge request (i.e. this isn't
necessarily a transient failure)!
@@ -189,7 +199,7 @@ subgraph "CNG-mirror pipeline"
your merge request. You can also download the artifacts to see screenshots of
the page at the time the failures occurred. If you don't find the cause of the
failure or if it seems unrelated to your change, please post a message in the
- `#quality` channel and/or create a ~Quality ~bug issue with a link to your
+ `#quality` channel and/or create a ~Quality ~"type::bug" issue with a link to your
merge request.
- The manual `review-stop` can be used to
stop a Review App manually, and is also started by GitLab once a merge
@@ -238,6 +248,16 @@ Leading indicators may be health check failures leading to restarts or majority
The [Review Apps Overview dashboard](https://console.cloud.google.com/monitoring/classic/dashboards/6798952013815386466?project=gitlab-review-apps&timeDomain=1d)
aids in identifying load spikes on the cluster, and if nodes are problematic or the entire cluster is trending towards unhealthy.
+### Database related errors in `review-deploy` or `review-qa-smoke`
+
+Occasionally the state of a Review App's database could diverge from the database schema. This could be caused by
+changes to migration files or schema, such as a migration being renamed or deleted. This typically manifest in migration errors such as:
+
+- migration job failing with a column that already exists
+- migration job failing with a column that does not exist
+
+To recover from this, please attempt to [redeploy Review App from a clean slate](#redeploy-review-app-from-a-clean-slate)
+
### Release failed with `ImagePullBackOff`
**Potential cause:**
diff --git a/doc/development/testing_guide/testing_migrations_guide.md b/doc/development/testing_guide/testing_migrations_guide.md
index 757a70fb4e0..4092c1a2f6d 100644
--- a/doc/development/testing_guide/testing_migrations_guide.md
+++ b/doc/development/testing_guide/testing_migrations_guide.md
@@ -38,7 +38,7 @@ ensures proper isolation.
## Testing an `ActiveRecord::Migration` class
-To test an `ActiveRecord::Migration` class (i.e., a
+To test an `ActiveRecord::Migration` class (for example, a
regular migration `db/migrate` or a post-migration `db/post_migrate`), you
must load the migration file by using the `require_migration!` helper
method because it is not autoloaded by Rails.
@@ -61,14 +61,35 @@ Since the migration files are not autoloaded by Rails, you must manually
load the migration file. To do so, you can use the `require_migration!` helper method
which can automatically load the correct migration file based on the spec filename.
-For example, if your spec file is named as `populate_foo_column_spec.rb` then the
-helper method tries to load `${schema_version}_populate_foo_column.rb` migration file.
+In GitLab 14.4 and later, you can use `require_migration!` to load migration files from spec files
+that contain the schema version in the filename (for example,
+`2021101412150000_populate_foo_column_spec.rb`).
-In case there is no pattern between your spec file and the actual migration file,
-you can provide the migration filename without the schema version, like so:
+```ruby
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe PopulateFooColumn do
+ ...
+end
+```
+
+In some cases, you must require multiple migration files to use them in your specs. Here, there's no
+pattern between your spec file and the other migration file. You can provide the migration filename
+like so:
```ruby
-require_migration!('populate_foo_column')
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+require_migration!('populate_bar_column')
+
+RSpec.describe PopulateFooColumn do
+ ...
+end
```
#### `table`
@@ -213,54 +234,65 @@ Migration tests depend on what the migration does exactly, the most common types
#### Example of a data migration test
This spec tests the
-[`db/post_migrate/20170526185842_migrate_pipeline_stages.rb`](https://gitlab.com/gitlab-org/gitlab-foss/blob/v11.6.5/db/post_migrate/20170526185842_migrate_pipeline_stages.rb)
+[`db/post_migrate/20200723040950_migrate_incident_issues_to_incident_type.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/db/post_migrate/20200723040950_migrate_incident_issues_to_incident_type.rb)
migration. You can find the complete spec in
-[`spec/migrations/migrate_pipeline_stages_spec.rb`](https://gitlab.com/gitlab-org/gitlab-foss/blob/v11.6.5/spec/migrations/migrate_pipeline_stages_spec.rb).
+[`spec/migrations/migrate_incident_issues_to_incident_type_spec.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/migrations/migrate_incident_issues_to_incident_type_spec.rb).
```ruby
-require 'spec_helper'
+# frozen_string_literal: true
+require 'spec_helper'
require_migration!
-RSpec.describe MigratePipelineStages do
- # Create test data - pipeline and CI/CD jobs.
- let(:jobs) { table(:ci_builds) }
- let(:stages) { table(:ci_stages) }
- let(:pipelines) { table(:ci_pipelines) }
+RSpec.describe MigrateIncidentIssuesToIncidentType do
+ let(:migration) { described_class.new }
+
let(:projects) { table(:projects) }
+ let(:namespaces) { table(:namespaces) }
+ let(:labels) { table(:labels) }
+ let(:issues) { table(:issues) }
+ let(:label_links) { table(:label_links) }
+ let(:label_props) { IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES }
+
+ let(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
+ let!(:project) { projects.create!(namespace_id: namespace.id) }
+ let(:label) { labels.create!(project_id: project.id, **label_props) }
+ let!(:incident_issue) { issues.create!(project_id: project.id) }
+ let!(:other_issue) { issues.create!(project_id: project.id) }
+
+ # Issue issue_type enum
+ let(:issue_type) { 0 }
+ let(:incident_type) { 1 }
before do
- projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1')
- pipelines.create!(id: 1, project_id: 123, ref: 'master', sha: 'adf43c3a')
- jobs.create!(id: 1, commit_id: 1, project_id: 123, stage_idx: 2, stage: 'build')
- jobs.create!(id: 2, commit_id: 1, project_id: 123, stage_idx: 1, stage: 'test')
+ label_links.create!(target_id: incident_issue.id, label_id: label.id, target_type: 'Issue')
end
- # Test just the up migration.
- it 'correctly migrates pipeline stages' do
- expect(stages.count).to be_zero
-
- migrate!
+ describe '#up' do
+ it 'updates the incident issue type' do
+ expect { migrate! }
+ .to change { incident_issue.reload.issue_type }
+ .from(issue_type)
+ .to(incident_type)
- expect(stages.count).to eq 2
- expect(stages.all.pluck(:name)).to match_array %w[test build]
+ expect(other_issue.reload.issue_type).to eql(issue_type)
+ end
end
- # Test a reversible migration.
- it 'correctly migrates up and down pipeline stages' do
- reversible_migration do |migration|
- # Expectations will run before the up migration,
- # and then again after the down migration
- migration.before -> {
- expect(stages.count).to be_zero
- }
-
- # Expectations will run after the up migration.
- migration.after -> {
- expect(stages.count).to eq 2
- expect(stages.all.pluck(:name)).to match_array %w[test build]
- }
+ describe '#down' do
+ let!(:incident_issue) { issues.create!(project_id: project.id, issue_type: issue_type) }
+
+ it 'updates the incident issue type' do
+ migration.up
+
+ expect { migration.down }
+ .to change { incident_issue.reload.issue_type }
+ .from(incident_type)
+ .to(issue_type)
+
+ expect(other_issue.reload.issue_type).to eql(issue_type)
end
+ end
end
```
@@ -336,41 +368,62 @@ end
### Example background migration test
This spec tests the
-[`lib/gitlab/background_migration/archive_legacy_traces.rb`](https://gitlab.com/gitlab-org/gitlab-foss/blob/v11.6.5/lib/gitlab/background_migration/archive_legacy_traces.rb)
+[`lib/gitlab/background_migration/backfill_draft_status_on_merge_requests.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/background_migration/backfill_draft_status_on_merge_requests.rb)
background migration. You can find the complete spec on
-[`spec/lib/gitlab/background_migration/archive_legacy_traces_spec.rb`](https://gitlab.com/gitlab-org/gitlab-foss/blob/v11.6.5/spec/lib/gitlab/background_migration/archive_legacy_traces_spec.rb)
+[`spec/lib/gitlab/background_migration/backfill_draft_status_on_merge_requests_spec.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/lib/gitlab/background_migration/backfill_draft_status_on_merge_requests_spec.rb)
```ruby
+# frozen_string_literal: true
+
require 'spec_helper'
-describe Gitlab::BackgroundMigration::ArchiveLegacyTraces, schema: 20180529152628 do
- include TraceHelpers
+RSpec.describe Gitlab::BackgroundMigration::BackfillDraftStatusOnMergeRequests do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:merge_requests) { table(:merge_requests) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:builds) { table(:ci_builds) }
- let(:job_artifacts) { table(:ci_job_artifacts) }
+ let(:group) { namespaces.create!(name: 'gitlab', path: 'gitlab') }
+ let(:project) { projects.create!(namespace_id: group.id) }
- before do
- namespaces.create!(id: 123, name: 'gitlab1', path: 'gitlab1')
- projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1', namespace_id: 123)
- @build = builds.create!(id: 1, project_id: 123, status: 'success', type: 'Ci::Build')
+ let(:draft_prefixes) { ["[Draft]", "(Draft)", "Draft:", "Draft", "[WIP]", "WIP:", "WIP"] }
+
+ def create_merge_request(params)
+ common_params = {
+ target_project_id: project.id,
+ target_branch: 'feature1',
+ source_branch: 'master'
+ }
+
+ merge_requests.create!(common_params.merge(params))
end
- context 'when trace file exists at the right place' do
+ context "for MRs with #draft? == true titles but draft attribute false" do
+ let(:mr_ids) { merge_requests.all.collect(&:id) }
+
before do
- create_legacy_trace(@build, 'trace in file')
+ draft_prefixes.each do |prefix|
+ (1..4).each do |n|
+ create_merge_request(
+ title: "#{prefix} This is a title",
+ draft: false,
+ state_id: n
+ )
+ end
+ end
end
- it 'correctly archive legacy traces' do
- expect(job_artifacts.count).to eq(0)
- expect(File.exist?(legacy_trace_path(@build))).to be_truthy
+ it "updates all open draft merge request's draft field to true" do
+ mr_count = merge_requests.all.count
+
+ expect { subject.perform(mr_ids.first, mr_ids.last) }
+ .to change { MergeRequest.where(draft: false).count }
+ .from(mr_count).to(mr_count - draft_prefixes.length)
+ end
- described_class.new.perform(1, 1)
+ it "marks successful slices as completed" do
+ expect(subject).to receive(:mark_job_as_succeeded).with(mr_ids.first, mr_ids.last)
- expect(job_artifacts.count).to eq(1)
- expect(File.exist?(legacy_trace_path(@build))).to be_falsy
- expect(File.read(archived_trace_path(job_artifacts.first))).to eq('trace in file')
+ subject.perform(mr_ids.first, mr_ids.last)
end
end
end
diff --git a/doc/development/understanding_explain_plans.md b/doc/development/understanding_explain_plans.md
index c3dfeaa6b92..e06ece38135 100644
--- a/doc/development/understanding_explain_plans.md
+++ b/doc/development/understanding_explain_plans.md
@@ -172,7 +172,7 @@ cost describing how expensive the entire node was. In general: the greater the
values, the more expensive the node.
When using `EXPLAIN ANALYZE`, these statistics will also include the actual time
-(in milliseconds) spent, and other runtime statistics (e.g. the actual number of
+(in milliseconds) spent, and other runtime statistics (for example, the actual number of
produced rows):
```sql
@@ -555,7 +555,7 @@ There are two terms commonly used for databases: cardinality, and selectivity.
Cardinality refers to the number of unique values in a particular column in a
table.
-Selectivity is the number of unique values produced by an operation (e.g. an
+Selectivity is the number of unique values produced by an operation (for example, an
index scan or filter), relative to the total number of rows. The higher the
selectivity, the more likely PostgreSQL is able to use an index.
@@ -675,8 +675,8 @@ best avoided in most cases, such as:
- Sequential scans on large tables
- Filters that remove a lot of rows
-- Performing a certain step (e.g. an index scan) that requires _a lot_ of
- buffers (e.g. more than 512 MB for GitLab.com).
+- Performing a certain step that requires _a lot_ of
+ buffers (for example, an index scan for GitLab.com that requires more than 512 MB).
As a general guideline, aim for a query that:
diff --git a/doc/development/uploads.md b/doc/development/uploads.md
index 9c5686db0f6..6d8b951be83 100644
--- a/doc/development/uploads.md
+++ b/doc/development/uploads.md
@@ -7,12 +7,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Uploads development documentation
[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) has special rules for handling uploads.
-To prevent occupying a Ruby process on I/O operations, we process the upload in workhorse, where is cheaper.
+We process the upload in Workhorse to prevent occupying a Ruby process on I/O operations and because it is cheaper.
This process can also directly upload to object storage.
## The problem description
-The following graph explains machine boundaries in a scalable GitLab installation. Without any workhorse optimization in place, we can expect incoming requests to follow the numbers on the arrows.
+The following graph explains machine boundaries in a scalable GitLab installation. Without any Workhorse optimization in place, we can expect incoming requests to follow the numbers on the arrows.
```mermaid
graph TB
@@ -27,10 +27,10 @@ graph TB
subgraph "redis cluster"
r(persisted redis)
end
- LB-- 1 -->workhorse
+ LB-- 1 -->Workhorse
subgraph "web or API fleet"
- workhorse-- 2 -->rails
+ Workhorse-- 2 -->rails
end
rails-- "3 (write files)" -->nfs
rails-- "4 (schedule a job)" -->r
@@ -63,12 +63,12 @@ graph TB
subgraph "redis cluster"
r(persisted redis)
end
- LB-- 1 -->workhorse
+ LB-- 1 -->Workhorse
subgraph "web or API fleet"
- workhorse-- "3 (without files)" -->rails
+ Workhorse-- "3 (without files)" -->rails
end
- workhorse -- "2 (write files)" -->nfs
+ Workhorse -- "2 (write files)" -->nfs
rails-- "4 (schedule a job)" -->r
subgraph sidekiq
@@ -120,7 +120,7 @@ We have three kinds of file encoding in our uploads:
1. <i class="fa fa-check-circle"></i> **multipart**: `multipart/form-data` is the most common, a file is encoded as a part of a multipart encoded request.
1. <i class="fa fa-check-circle"></i> **body**: some APIs uploads files as the whole request body.
-1. <i class="fa fa-times-circle"></i> **JSON**: some JSON API uploads files as base64 encoded strings. This requires a change to GitLab Workhorse,
+1. <i class="fa fa-times-circle"></i> **JSON**: some JSON APIs upload files as base64-encoded strings. This requires a change to GitLab Workhorse,
which is tracked [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/325068).
## Uploading technologies
@@ -131,9 +131,9 @@ GitLab supports 3 kinds of uploading technologies, here follows a brief descript
### Rack Multipart upload
-This is the default kind of upload, and it's most expensive in terms of resources.
+This is the default kind of upload, and it's the most expensive in terms of resources.
-In this case, workhorse is unaware of files being uploaded and acts as a regular proxy.
+In this case, Workhorse is unaware of files being uploaded and acts as a regular proxy.
When a multipart request reaches the rails application, `Rack::Multipart` leaves behind temporary files in `/tmp` and uses valuable Ruby process time to copy files around.
@@ -213,7 +213,7 @@ sequenceDiagram
This is the more advanced acceleration technique we have in place.
-Workhorse asks rails for temporary pre-signed object storage URLs and directly uploads to object storage.
+Workhorse asks Rails for temporary pre-signed object storage URLs and directly uploads to object storage.
In this setup, an extra Rails route must be implemented in order to handle authorization. Examples of this can be found in:
@@ -221,7 +221,7 @@ In this setup, an extra Rails route must be implemented in order to handle autho
and [its routes](https://gitlab.com/gitlab-org/gitlab/-/blob/cc723071ad337573e0360a879cbf99bc4fb7adb9/config/routes/git_http.rb#L31-32).
- [API endpoints for uploading packages](packages.md#file-uploads).
-This falls back to _disk buffered upload_ when `direct_upload` is disabled inside the [object storage setting](../administration/uploads.md#object-storage-settings).
+Direct upload falls back to _disk buffered upload_ when `direct_upload` is disabled inside the [object storage setting](../administration/uploads.md#object-storage-settings).
The answer to the `/authorize` call contains only a file system path.
```mermaid
@@ -275,7 +275,7 @@ sequenceDiagram
In this section, we describe how to add a new upload route [accelerated](#uploading-technologies) by Workhorse for [body and multipart](#upload-encodings) encoded uploads.
-Uploads routes belong to one of these categories:
+Upload routes belong to one of these categories:
1. Rails controllers: uploads handled by Rails controllers.
1. Grape API: uploads handled by a Grape API endpoint.
@@ -289,7 +289,7 @@ GraphQL uploads do not support [direct upload](#direct-upload) yet. Depending on
For both the Rails controller and Grape API uploads, Workhorse has to be updated in order to get the
support for the new upload route.
-1. Open an new issue in the [Workhorse tracker](https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/new) describing precisely the new upload route:
+1. Open a new issue in the [Workhorse tracker](https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/new) describing precisely the new upload route:
- The route's URL.
- The [upload encoding](#upload-encodings).
- If possible, provide a dump of the upload request.
diff --git a/doc/development/verifying_database_capabilities.md b/doc/development/verifying_database_capabilities.md
index c5e854701c2..bda9c68eae5 100644
--- a/doc/development/verifying_database_capabilities.md
+++ b/doc/development/verifying_database_capabilities.md
@@ -12,13 +12,13 @@ necessary to add database (version) specific behavior.
To facilitate this we have the following methods that you can use:
-- `Gitlab::Database.main.version`: returns the PostgreSQL version number as a string
+- `ApplicationRecord.database.version`: returns the PostgreSQL version number as a string
in the format `X.Y.Z`.
This allows you to write code such as:
```ruby
-if Gitlab::Database.main.version.to_f >= 11.7
+if ApplicationRecord.database.version.to_f >= 11.7
run_really_fast_query
else
run_fast_query
diff --git a/doc/development/workspaces/index.md b/doc/development/workspaces/index.md
new file mode 100644
index 00000000000..b36c79e84d7
--- /dev/null
+++ b/doc/development/workspaces/index.md
@@ -0,0 +1,120 @@
+---
+comments: false
+type: index, dev
+stage: none
+group: Development
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+description: "Development Guidelines: learn about workspaces when developing GitLab."
+---
+
+# Workspaces
+
+The [Workspaces initiative](../../user/workspace/index.md) focuses on reaching feature parity between
+SaaS and self-managed installations.
+
+## Consolidate groups and projects
+
+- [Architecture blueprint](../../architecture/blueprints/consolidating_groups_and_projects/index.md)
+
+One facet of the workspaces initiative is to consolidate groups and projects,
+addressing the feature disparity between them. Some features, such as epics, are
+only available at the group level. Some features, such as issues, are only available
+at the project level. Other features, such as milestones, are available to both groups
+and projects.
+
+We receive many requests to add features either to the group or project level.
+Moving features around to different levels is problematic on multiple levels:
+
+- It requires engineering time to move the features.
+- It requires UX overhead to maintain mental models of feature availability.
+- It creates redundant code.
+
+When features are copied from one level (project, group, or instance) to another,
+the copies often have small, nuanced differences between them. These nuances cause
+extra engineering time when fixes are needed, because the fix must be copied to
+several locations. These nuances also create different user experiences when the
+feature is used in different places.
+
+A solution for this problem is to consolidate groups and projects into a single
+entity, `namespace`. The work on this solution is split into several phases and
+is tracked in [epic 6473](https://gitlab.com/groups/gitlab-org/-/epics/6473).
+
+### Phase 1
+
+- [Phase 1 epic](https://gitlab.com/groups/gitlab-org/-/epics/6697).
+- **Goals**:
+ 1. Ensure every project receives a corresponding record in the `namespaces`
+ table with `type='Project'`.
+ 1. For user namespaces, the type changes from `NULL` to `User`.
+
+We should make sure that projects, and the project namespace, are equivalent:
+
+- **Create project:** use Rails callbacks to ensure a new project namespace is
+ created for each project. Project namespace records should contain `created_at` and
+ `updated_at` attributes equal to the project's `created_at`/`updated_at` attributes.
+- **Update project:** use the `after_save` callback in Rails to ensure some
+ attributes are kept in sync between project and project namespaces.
+ Read [`project#after_save`](https://gitlab.com/gitlab-org/gitlab/blob/6d26634e864d7b748dda0e283eb2477362263bc3/app/models/project.rb#L101-L101)
+ for more information.
+- **Delete project:** use FKs cascade delete or Rails callbacks to ensure when a `Project`
+ or its `ProjectNamespace` is removed, its corresponding `ProjectNamespace` or `Project`
+ is also removed.
+- **Transfer project to a different group:** make sure that when a project is transferred,
+ its corresponding project namespace is transferred to the same group.
+- **Transfer group:** make sure when transferring a group that all of its sub-projects,
+ either direct or through descendant groups, have their corresponding project
+ namespaces transferred correctly as well.
+- **Export or import project**
+ - **Export project** continues to export only the project, and not its project namespace,
+ in this phase. The project namespace does not contain any specific information
+ to export at this point. Eventually we want the project namespace to be exported as well.
+ - **Import project** creates a new project, so the project namespace is created through
+ Rails `after_save` callback on the project model.
+- **Export or import group:** when importing or exporting a `Group`, projects are not
+ included in the operation. If that feature is changed to include `Project` when its group is
+ imported or exported, the logic must include their corresponding project namespaces
+ in the import or export.
+
+After ensuring these points, run a database migration to create a `ProjectNamespace`
+record for every `Project`. Project namespace records created during the migration
+should have `created_at` and `updated_at` attributes set to the migration runtime.
+The project namespaces' `created_at` and `updated_at` attributes would not match
+their corresponding project's `created_at` and `updated_at` attributes. We want
+the different dates to help audit any of the created project namespaces, in case we need it.
+After this work completes, we must migrate data as described in
+[Backfill `ProjectNamespace` for every Project](https://gitlab.com/gitlab-org/gitlab/-/issues/337100).
+
+### Phase 2
+
+- [Phase 2 epic](https://gitlab.com/groups/gitlab-org/-/epics/6768).
+- **Goal**: Make `ProjectNamespace` the front entity to interact with instead of `Project`.
+
+In this phase:
+
+- Communicate the changes company-wide at the engineering level. We want to make
+ engineers aware of the upcoming changes, even though teams are not expected to
+ collaborate actively until phase 3.
+- Raise awareness to avoid regressions, and conflicting or duplicate work that
+ can be dealt with before phase 3.
+
+Problems to solve as part of this phase:
+
+- Routes handling through `ProjectNamespace` rather than `Project`.
+- Memberships handling.
+- Policies handling.
+- Import and export.
+- Other interactions between project namespace and project models.
+
+### Phase 3
+
+- [Phase 3 epic](https://gitlab.com/groups/gitlab-org/-/epics/6585).
+- **Goal**: Feature parity between the namespace types.
+
+Phase 3 is when the active migration of features from `Project` to `ProjectNamespace`,
+or directly to `Namespace`, happens.
+
+## Related topics
+
+- [Consolidating groups and projects](../../architecture/blueprints/consolidating_groups_and_projects/index.md)
+ architecture documentation
+- [Workspace user documentation](../../user/workspace/index.md)
diff --git a/doc/gitlab-basics/feature_branch_workflow.md b/doc/gitlab-basics/feature_branch_workflow.md
index 99d346f2b01..989a1557ef2 100644
--- a/doc/gitlab-basics/feature_branch_workflow.md
+++ b/doc/gitlab-basics/feature_branch_workflow.md
@@ -16,7 +16,7 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/workflow.html'
1. Create branch with your feature:
```shell
- git checkout -b $feature_name
+ git checkout -b feature_name
```
1. Write code. Commit changes:
@@ -28,7 +28,7 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/workflow.html'
1. Push your branch to GitLab:
```shell
- git push origin $feature_name
+ git push origin feature_name
```
1. Review your code on commits page.
diff --git a/doc/index.md b/doc/index.md
index a638647e3e3..57eb9e195ff 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -6,12 +6,18 @@ comments: false
description: 'Learn how to use and administer GitLab, the most scalable Git-based fully integrated platform for software development.'
---
+<!-- markdownlint-disable MD044 -->
+<!-- MD044/proper-names test disabled after this line to make page compatible with markdownlint-cli 0.29.0. -->
+<!-- See https://docs.gitlab.com/ee/development/documentation/testing.html#disable-markdownlint-tests -->
+
<div class="d-none">
<h3>Visit <a href="https://docs.gitlab.com/ee/">docs.gitlab.com</a> for the latest version
of this help information with enhanced navigation, discoverability, and readability.</h3>
</div>
<!-- the div above will not display on the docs site but will display on /help -->
+<!-- markdownlint-enable MD044 -->
+
# GitLab Docs
Welcome to [GitLab](https://about.gitlab.com/) documentation.
diff --git a/doc/install/aws/eks_clusters_aws.md b/doc/install/aws/eks_clusters_aws.md
index 3c19a83f128..86318467a91 100644
--- a/doc/install/aws/eks_clusters_aws.md
+++ b/doc/install/aws/eks_clusters_aws.md
@@ -1,7 +1,6 @@
---
-type: reference, concepts
stage: Enablement
-group: Alliances
+group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/install/aws/gitlab_hybrid_on_aws.md b/doc/install/aws/gitlab_hybrid_on_aws.md
index 4d22a29ad0a..3c035b33be8 100644
--- a/doc/install/aws/gitlab_hybrid_on_aws.md
+++ b/doc/install/aws/gitlab_hybrid_on_aws.md
@@ -1,7 +1,6 @@
---
-type: reference, concepts
stage: Enablement
-group: Alliances
+group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -9,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Provision GitLab Cloud Native Hybrid on AWS EKS **(FREE SELF)**
-GitLab "Cloud Native Hybrid" is a hybrid of the cloud native technology Kubernetes (EKS) and EC2. While as much of the GitLab application as possible runs in Kubernetes or on AWS services (PaaS), the GitLab service Gitaly must still be run on Ec2. Gitaly is a layer designed to overcome limitations of the Git binaries in a horizontally scaled architecture. You can read more here about why Gitaly was built and why the limitations of Git mean that it must currently run on instance compute in [Git Characteristics That Make Horizontal Scaling Difficult](https://gitlab.com/gitlab-org/gitaly/-/blob/master/doc/DESIGN.md#git-characteristics-that-make-horizontal-scaling-difficult)
+GitLab "Cloud Native Hybrid" is a hybrid of the cloud native technology Kubernetes (EKS) and EC2. While as much of the GitLab application as possible runs in Kubernetes or on AWS services (PaaS), the GitLab service Gitaly must still be run on Ec2. Gitaly is a layer designed to overcome limitations of the Git binaries in a horizontally scaled architecture. You can read more here about why Gitaly was built and why the limitations of Git mean that it must currently run on instance compute in [Git Characteristics That Make Horizontal Scaling Difficult](https://gitlab.com/gitlab-org/gitaly/-/blob/master/doc/DESIGN.md#git-characteristics-that-make-horizontal-scaling-difficult).
Amazon provides a managed Kubernetes service offering known as [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/).
@@ -18,10 +17,10 @@ Amazon provides a managed Kubernetes service offering known as [Amazon Elastic K
| GitLab Cloud Native Hybrid Ref Arch | GitLab Baseline Perf Test Results Omnibus on Instances | AWS Bill of Materials (BOM) for CNH | AWS Build Performance Testing Results for [CNH](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt) | CNH Cost Estimate 3 AZs* |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| [2K Omnibus](../../administration/reference_architectures/2k_users.md) | [2K Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/2k) | [2K Cloud Native Hybrid on EKS](#2k-cloud-native-hybrid-on-eks) | GPT Test Results | [1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=544bcf1162beae6b8130ad257d081cdf9d4504e3)<br />(2 AZ Cost Estimate is in BOM Below) |
-| [3K](../../administration/reference_architectures/3k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [3k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/3k) | [3K Cloud Native Hybrid on EKS](#3k-cloud-native-hybrid-on-eks) | [3K Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216_results.txt)<br /><br />[3K AutoScale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200_results.txt) | [1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=f1294fec554e21be999711cddcdab9c5e7f83f14)<br />(2 AZ Cost Estimate is in BOM Below) |
-| [5K](../../administration/reference_architectures/5k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [5k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/5k) | [5K Cloud Native Hybrid on EKS](#5k-cloud-native-hybrid-on-eks) | [5K Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt)<br /><br />[5K AutoScale from 25% GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717_results.txt) | [1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=330ee43c5b14662db5df6e52b34898d181a09e16) |
-| [10K](../../administration/reference_architectures/10k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [10k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k) | [10K Cloud Native Hybrid on EKS](#10k-cloud-native-hybrid-on-eks) | [10K Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647_results.txt)<br /><br />[10K AutoScale GPT Test Results](hhttps://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139_results.txt) | [10K 1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=5ac2e07a22e01c36ee76b5477c5a046cd1bea792) |
-| [50K](../../administration/reference_architectures/50k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [50k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/50k) | [50K Cloud Native Hybrid on EKS](#50k-cloud-native-hybrid-on-eks) | [50K Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819_results.txt)<br /><br />[10K AutoScale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633.txt) | [50K 1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=b9c9d6ac1d4a7848011d2050cef3120931fb7c22) |
+| [3K](../../administration/reference_architectures/3k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [3k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/3k) | [3K Cloud Native Hybrid on EKS](#3k-cloud-native-hybrid-on-eks) | [3K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216_results.txt)<br /><br />[3K Elastic Auto Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200_results.txt) | [1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=f1294fec554e21be999711cddcdab9c5e7f83f14)<br />(2 AZ Cost Estimate is in BOM Below) |
+| [5K](../../administration/reference_architectures/5k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [5k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/5k) | [5K Cloud Native Hybrid on EKS](#5k-cloud-native-hybrid-on-eks) | [5K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt)<br /><br />[5K AutoScale from 25% GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717_results.txt) | [1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=330ee43c5b14662db5df6e52b34898d181a09e16) |
+| [10K](../../administration/reference_architectures/10k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [10k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k) | [10K Cloud Native Hybrid on EKS](#10k-cloud-native-hybrid-on-eks) | [10K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647_results.txt)<br /><br />[10K Elastic Auto Scale GPT Test Results](hhttps://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139_results.txt) | [10K 1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=5ac2e07a22e01c36ee76b5477c5a046cd1bea792) |
+| [50K](../../administration/reference_architectures/50k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [50k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/50k) | [50K Cloud Native Hybrid on EKS](#50k-cloud-native-hybrid-on-eks) | [50K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819_results.txt)<br /><br />[10K Elastic Auto Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633.txt) | [50K 1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=b9c9d6ac1d4a7848011d2050cef3120931fb7c22) |
\*Cost calculations for actual implementations are a rough guideline with the following considerations:
@@ -36,7 +35,8 @@ Amazon provides a managed Kubernetes service offering known as [Amazon Elastic K
The [AWS Quick Start for GitLab Cloud Native Hybrid on EKS](https://aws-quickstart.github.io/quickstart-eks-gitlab/) is developed by AWS, GitLab, and the community that contributes to AWS Quick Starts, whether directly to the GitLab Quick Start or to the underlying Quick Start dependencies GitLab inherits (for example, EKS Quick Start).
NOTE:
-This automation is in **Developer Preview**. GitLab is working with AWS on [these outstanding issues](https://github.com/aws-quickstart/quickstart-eks-gitlab/issues?q=is%3Aissue+is%3Aopen+%5BHL%5D) before it is fully released.
+This automation is in **Developer Preview**. GitLab is working with AWS on resolving [the outstanding issues](https://github.com/aws-quickstart/quickstart-eks-gitlab/issues?q=is%3Aissue+is%3Aopen+%5BHL%5D) before it is fully released. You can subscribe to this issue to be notified of progress and release announcements: [AWS Quick Start for GitLab Cloud Native Hybrid on EKS Status: DEVELOPER PREVIEW](https://gitlab.com/gitlab-com/alliances/aws/public-tracker/-/issues/11).<br><br>
+The developer preview deploys Aurora PostgreSQL, but the release version will deploy Amazon RDS PostgreSQL due to [known issues](https://gitlab.com/gitlab-com/alliances/aws/public-tracker/-/issues?label_name%5B%5D=AWS+Known+Issue) with Aurora. All performance testing results will also be redone after this change has been made.
The [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/tree/master) is an effort made by GitLab to create a multi-cloud, multi-GitLab (Omnibus + Cloud Native Hybrid) toolkit to provision GitLab. GET is developed by GitLab developers and is open to community contributions.
It is helpful to review the [GitLab Environment Toolkit (GET) Issues](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/issues) to understand if any of them may affect your provisioning plans.
@@ -79,7 +79,7 @@ The AWS Quick Start for GitLab Cloud Native Hybrid on EKS has been tested with G
| **Request AWS Certificate Manager SSL certificate** | CreateSslCertificate | No |
- The Quick Start creates public load balancer IPs, so that you can easily configure your local hosts file to get to the GUI for GitLab when deploying tests. However, you may need to manually alter this if public load balancers are not part of your provisioning plan. We are planning to make non-public load balancers a configuration option issue link: [Short Term: Documentation and/or Automation for private GitLab instance with no internet Ingress](https://github.com/aws-quickstart/quickstart-eks-gitlab/issues/55)
-- As of 2021-08-19, AWS GovCloud has Graviton instances for Aurora PostgreSQL available, but does not for ElastiCache Redis.
+- As of 2021-08-19, AWS GovCloud has Graviton instances for Amazon RDS PostgreSQL available, but does not for ElastiCache Redis.
- It is challenging to get the Quick Start template to load in GovCloud from the Standard Quick Start URL, so the generic ones are provided here:
- [Launch for New VPC in us-gov-east-1](https://us-gov-east-1.console.amazonaws-us-gov.com/cloudformation/home?region=us-gov-east-1#/stacks/quickcreate?templateUrl=https://aws-quickstart.s3.us-east-1.amazonaws.com/quickstart-eks-gitlab/templates/gitlab-entry-new-vpc.template.yaml&stackName=Gitlab-for-EKS-New-VPC)
- [Launch for New VPC in us-gov-west-1](https://us-gov-west-1.console.amazonaws-us-gov.com/cloudformation/home?region=us-gov-west-1#/stacks/quickcreate?templateUrl=https://aws-quickstart.s3.us-east-1.amazonaws.com/quickstart-eks-gitlab/templates/gitlab-entry-new-vpc.template.yaml&stackName=Gitlab-for-EKS-New-VPC)
@@ -95,7 +95,7 @@ Some services, such as log aggregation, outbound email are not specified by GitL
| GitLab Services | AWS PaaS (Tested) | Provided by AWS Cloud <br />Native Hybrid Quick Start |
| ------------------------------------------------------------ | ------------------------------ | ------------------------------------------------------------ |
| <u>Tested PaaS Mentioned in Reference Architectures</u> | | |
-| **PostgreSQL Database** | Aurora RDS | Yes. |
+| **PostgreSQL Database** | Amazon RDS PostgreSQL | Yes. |
| **Redis Caching** | Redis Elasticache | Yes. |
| **Gitaly Cluster (Git Repository Storage)**<br />(Including Praefect and PostgreSQL) | ASG and Instances | Yes - ASG and Instances<br />**Note: Gitaly cannot be put into a Kubernetes Cluster.** |
| **All GitLab storages besides Git Repository Storage**<br />(Includes Git-LFS which is S3 Compatible) | AWS S3 | Yes |
@@ -126,9 +126,7 @@ Some services, such as log aggregation, outbound email are not specified by GitL
**GPT Test Results**
-- [3K Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216_results.txt)
-
-- [3K AutoScale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200_results.txt)
+- TBD
**Deploy Now**
Deploy Now links leverage the AWS Quick Start automation and only prepopulate the number of instances and instance types for the Quick Start based on the Bill of Meterials below. You must provide appropriate input for all other parameters by following the guidance in the [Quick Start documentation's Deployment steps](https://aws-quickstart.github.io/quickstart-eks-gitlab/#_deployment_steps) section.
@@ -158,17 +156,17 @@ On Demand pricing is used in this table for comparisons, but should not be used
NOTE:
If EKS node autoscaling is employed, it is likely that your average loading will run lower than this, especially during non-working hours and weekends.
-| Non-Kubernetes Compute | Ref Arch Raw Total | AWS BOM<br />(Directly Usable in AWS Quick Start) | Example Cost<br />US East, 3 AZ | Example Cost<br />US East, 2 AZ |
-| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------- | ------------------------------- | ---------------------------------------------------- |
-| **Bastion Host (Quick Start)** | 1 HA instance in ASG | **t2.micro** for prod, **m4.2xlarge** for perf. testing | | |
-| **PostgreSQL**<br />AWS Aurora RDS Nodes Configuration (GPT tested) | 2vCPU, 7.5 GB<br />Tested with Graviton ARM | **db.r6g.large** x 3 nodes <br />(6vCPU, 48 GB) | 3 nodes x $0.26 = $0.78/hr | 3 nodes x $0.26 = $0.78/hr<br />(Aurora is always 3) |
-| **Redis** | 1vCPU, 3.75GB<br />(across 12 nodes for Redis Cache, Redis Queues/Shared State, Sentinel Cache, Sentinel Queues/Shared State) | **cache.m6g.large** x 3 nodes<br />(6vCPU, 19GB) | 3 nodes x $0.15 = $0.45/hr | 2 nodes x $0.15 = $0.30/hr |
-| **<u>Gitaly Cluster</u>** [Details](gitlab_sre_for_aws.md#gitaly-sre-considerations) | [Gitaly & Praefect Must Have an Uneven Node Count for HA](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) | | | |
-| Gitaly Instances (in ASG) | 12 vCPU, 45GB<br />(across 3 nodes) | **m5.xlarge** x 3 nodes<br />(48 vCPU, 180 GB) | $0.192 x 3 = $0.58/hr | $0.192 x 3 = $0.58/hr |
-| | The GitLab Reference architecture for 2K is not Highly Available and therefore has a single Gitaly no Praefect. AWS Quick Starts MUST be HA, so it implements Prafect from the 3K Ref Architecture to meet that requirement | | | |
-| Praefect (Instances in ASG with load balancer) | 6 vCPU, 10 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | **c5.large** x 3 nodes<br />(6 vCPU, 12 GB) | $0.09 x 3 = $0.21/hr | $0.09 x 3 = $0.21/hr |
-| Praefect PostgreSQL(1) (AWS RDS) | 6 vCPU, 5.4 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | N/A Reuses GitLab PostgreSQL | $0 | $0 |
-| Internal Load Balancing Node | 2 vCPU, 1.8 GB | AWS ELB | $0.10/hr | $0.10/hr |
+| Non-Kubernetes Compute | Ref Arch Raw Total | AWS BOM<br />(Directly Usable in AWS Quick Start) | Example Cost<br />US East, 3 AZ | Example Cost<br />US East, 2 AZ |
+| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------- | ------------------------------- | ------------------------------- |
+| **Bastion Host (Quick Start)** | 1 HA instance in ASG | **t2.micro** for prod, **m4.2xlarge** for perf. testing | | |
+| **PostgreSQL**<br />AWS Amazon RDS PostgreSQL Nodes Configuration (GPT tested) | 2vCPU, 7.5 GB<br />Tested with Graviton ARM | **db.r6g.large** x 3 nodes <br />(6vCPU, 48 GB) | 3 nodes x $0.26 = $0.78/hr | 3 nodes x $0.26 = $0.78/hr |
+| **Redis** | 1vCPU, 3.75GB<br />(across 12 nodes for Redis Cache, Redis Queues/Shared State, Sentinel Cache, Sentinel Queues/Shared State) | **cache.m6g.large** x 3 nodes<br />(6vCPU, 19GB) | 3 nodes x $0.15 = $0.45/hr | 2 nodes x $0.15 = $0.30/hr |
+| **<u>Gitaly Cluster</u>** [Details](gitlab_sre_for_aws.md#gitaly-sre-considerations) | [Gitaly & Praefect Must Have an Uneven Node Count for HA](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) | | | |
+| Gitaly Instances (in ASG) | 12 vCPU, 45GB<br />(across 3 nodes) | **m5.xlarge** x 3 nodes<br />(48 vCPU, 180 GB) | $0.192 x 3 = $0.58/hr | $0.192 x 3 = $0.58/hr |
+| | The GitLab Reference architecture for 2K is not Highly Available and therefore has a single Gitaly no Praefect. AWS Quick Starts MUST be HA, so it implements Prafect from the 3K Ref Architecture to meet that requirement | | | |
+| Praefect (Instances in ASG with load balancer) | 6 vCPU, 10 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | **c5.large** x 3 nodes<br />(6 vCPU, 12 GB) | $0.09 x 3 = $0.21/hr | $0.09 x 3 = $0.21/hr |
+| Praefect PostgreSQL(1) (AWS RDS) | 6 vCPU, 5.4 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | N/A Reuses GitLab PostgreSQL | $0 | $0 |
+| Internal Load Balancing Node | 2 vCPU, 1.8 GB | AWS ELB | $0.10/hr | $0.10/hr |
### 3K Cloud Native Hybrid on EKS
@@ -176,8 +174,11 @@ If EKS node autoscaling is employed, it is likely that your average loading will
**GPT Test Results**
-- [5K Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt)
-- [5K AutoScale from 25% GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717_results.txt)
+- [3K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216_results.txt)
+
+- [3K AutoScale from 25% GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200_results.txt)
+
+ Elastic Auto Scale GPT Test Results start with an idle scaled cluster and then start the standard GPT test to determine if the EKS Auto Scaler performs well enough to keep up with performance test demands. In general this is substantially harder ramping than the scaling required when the ramping is driven my normal production workloads.
**Deploy Now**
@@ -202,7 +203,7 @@ On Demand pricing is used in this table for comparisons, but should not be used
| Supporting services such as NGINX, Prometheus, etc | [2 allocations](../../administration/reference_architectures/3k_users.md#cluster-topology) x ([2 vCPU and 7.5 GB](../../administration/reference_architectures/3k_users.md#cluster-topology)) = <br />4 vCPU, 15 GB | | |
| **GitLab Ref Arch Raw Total K8s Node Capacity** | 32 vCPU, 56 GB | | |
| One Node for Overhead and Miscellaneous (EKS Cluster AutoScaler, Grafana, Prometheus, etc) | + 16 vCPU, 32GB | | |
-| **Grand Total w/ Overheads Full Scale**<br />Minimum hosts = 3 | 48 vCPU, 88 GB | **c5.2xlarge** (8vcpu/16GB) x 5 nodes<br />40 vCPU, 80 GB<br />[Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216_results.txt) | $1.70/hr |
+| **Grand Total w/ Overheads Full Scale**<br />Minimum hosts = 3 | 48 vCPU, 88 GB | **c5.2xlarge** (8vcpu/16GB) x 5 nodes<br />40 vCPU, 80 GB<br />[Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216_results.txt) | $1.70/hr |
| **Possible Idle Configuration (Scaled-In 75% - round up)**<br />Pod autoscaling must be also adjusted to enable lower idling configuration. | 24 vCPU, 48 GB | c5.2xlarge x 4 | $1.36/hr |
Other combinations of node type and quantity can be used to meet the Grand Total. Due to the properties of pods, hosts that are overly small may have significant unused capacity.
@@ -213,12 +214,12 @@ If EKS node autoscaling is employed, it is likely that your average loading will
| Non-Kubernetes Compute | Ref Arch Raw Total | AWS BOM<br />(Directly Usable in AWS Quick Start) | Example Cost<br />US East, 3 AZ | Example Cost<br />US East, 2 AZ |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------- | ------------------------------- | ------------------------------------------------------------ |
| **Bastion Host (Quick Start)** | 1 HA instance in ASG | **t2.micro** for prod, **m4.2xlarge** for perf. testing | | |
-| **PostgreSQL**<br />AWS Aurora RDS Nodes Configuration (GPT tested) | 18vCPU, 36 GB <br />(across 9 nodes for PostgreSQL, PgBouncer, Consul)<br />Tested with Graviton ARM | **db.r6g.xlarge** x 3 nodes <br />(12vCPU, 96 GB) | 3 nodes x $0.52 = $1.56/hr | 3 nodes x $0.52 = $1.56/hr<br />(Aurora is always 3) |
+| **PostgreSQL**<br />Amazon RDS PostgreSQL Nodes Configuration (GPT tested) | 18vCPU, 36 GB <br />(across 9 nodes for PostgreSQL, PgBouncer, Consul)<br />Tested with Graviton ARM | **db.r6g.xlarge** x 3 nodes <br />(12vCPU, 96 GB) | 3 nodes x $0.52 = $1.56/hr | 3 nodes x $0.52 = $1.56/hr |
| **Redis** | 6vCPU, 18GB<br />(across 6 nodes for Redis Cache, Sentinel) | **cache.m6g.large** x 3 nodes<br />(6vCPU, 19GB) | 3 nodes x $0.15 = $0.45/hr | 2 nodes x $0.15 = $0.30/hr |
-| **<u>Gitaly Cluster</u>** [Details](gitlab_sre_for_aws.md#gitaly-sre-considerations) | | | | |
+| **<u>Gitaly Cluster</u>** [Details](gitlab_sre_for_aws.md#gitaly-sre-considerations) | | | | |
| Gitaly Instances (in ASG) | 12 vCPU, 45GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | **m5.large** x 3 nodes<br />(12 vCPU, 48 GB) | $0.192 x 3 = $0.58/hr | [Gitaly & Praefect Must Have an Uneven Node Count for HA](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) |
| Praefect (Instances in ASG with load balancer) | 6 vCPU, 5.4 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | **c5.large** x 3 nodes<br />(6 vCPU, 12 GB) | $0.09 x 3 = $0.21/hr | [Gitaly & Praefect Must Have an Uneven Node Count for HA](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) |
-| Praefect PostgreSQL(1) (AWS RDS) | 6 vCPU, 5.4 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | N/A Reuses GitLab PostgreSQL | $0 | |
+| Praefect PostgreSQL(1) (Amazon RDS) | 6 vCPU, 5.4 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | N/A Reuses GitLab PostgreSQL | $0 | |
| Internal Load Balancing Node | 2 vCPU, 1.8 GB | AWS ELB | $0.10/hr | $0.10/hr |
### 5K Cloud Native Hybrid on EKS
@@ -227,9 +228,12 @@ If EKS node autoscaling is employed, it is likely that your average loading will
**GPT Test Results**
-- [5K Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt)
+- [5K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt)
+
- [5K AutoScale from 25% GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717_results.txt)
+ Elastic Auto Scale GPT Test Results start with an idle scaled cluster and then start the standard GPT test to determine if the EKS Auto Scaler performs well enough to keep up with performance test demands. In general this is substantially harder ramping than the scaling required when the ramping is driven my normal production workloads.
+
**Deploy Now**
Deploy Now links leverage the AWS Quick Start automation and only prepopulate the number of instances and instance types for the Quick Start based on the Bill of Meterials below. You must provide appropriate input for all other parameters by following the guidance in the [Quick Start documentation's Deployment steps](https://aws-quickstart.github.io/quickstart-eks-gitlab/#_deployment_steps) section.
@@ -253,7 +257,7 @@ On Demand pricing is used in this table for comparisons, but should not be used
| Supporting services such as NGINX, Prometheus, etc | [2 allocations](../../administration/reference_architectures/5k_users.md#cluster-topology) x ([2 vCPU and 7.5 GB](../../administration/reference_architectures/5k_users.md#cluster-topology)) = <br />4 vCPU, 15 GB | | |
| **GitLab Ref Arch Raw Total K8s Node Capacity** | 62 vCPU, 96.5 GB | | |
| One Node for Quick Start Overhead and Miscellaneous (EKS Cluster AutoScaler, Grafana, Prometheus, etc) | + 8 vCPU, 16GB | | |
-| **Grand Total w/ Overheads Full Scale**<br />Minimum hosts = 3 | 70 vCPU, 112.5 GB | **c5.2xlarge** (8vcpu/16GB) x 9 nodes<br />72 vCPU, 144 GB<br />[Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt) | $2.38/hr |
+| **Grand Total w/ Overheads Full Scale**<br />Minimum hosts = 3 | 70 vCPU, 112.5 GB | **c5.2xlarge** (8vcpu/16GB) x 9 nodes<br />72 vCPU, 144 GB<br />[Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt) | $2.38/hr |
| **Possible Idle Configuration (Scaled-In 75% - round up)**<br />Pod autoscaling must be also adjusted to enable lower idling configuration. | 24 vCPU, 48 GB | c5.2xlarge x 7 | $1.85/hr |
Other combinations of node type and quantity can be used to meet the Grand Total. Due to the cpu and memory requirements of pods, hosts that are overly small may have significant unused capacity.
@@ -264,12 +268,12 @@ If EKS node autoscaling is employed, it is likely that your average loading will
| Non-Kubernetes Compute | Ref Arch Raw Total | AWS BOM<br />(Directly Usable in AWS Quick Start) | Example Cost<br />US East, 3 AZ | Example Cost<br />US East, 2 AZ |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------- | ------------------------------- | ------------------------------------------------------------ |
| **Bastion Host (Quick Start)** | 1 HA instance in ASG | **t2.micro** for prod, **m4.2xlarge** for perf. testing | | |
-| **PostgreSQL**<br />AWS Aurora RDS Nodes Configuration (GPT tested) | 21vCPU, 51 GB <br />(across 9 nodes for PostgreSQL, PgBouncer, Consul)<br />Tested with Graviton ARM | **db.r6g.2xlarge** x 3 nodes <br />(24vCPU, 192 GB) | 3 nodes x $1.04 = $3.12/hr | 3 nodes x $1.04 = $3.12/hr<br />(Aurora is always 3) |
+| **PostgreSQL**<br />Amazon RDS PostgreSQL Nodes Configuration (GPT tested) | 21vCPU, 51 GB <br />(across 9 nodes for PostgreSQL, PgBouncer, Consul)<br />Tested with Graviton ARM | **db.r6g.2xlarge** x 3 nodes <br />(24vCPU, 192 GB) | 3 nodes x $1.04 = $3.12/hr | 3 nodes x $1.04 = $3.12/hr |
| **Redis** | 9vCPU, 27GB<br />(across 6 nodes for Redis, Sentinel) | **cache.m6g.xlarge** x 3 nodes<br />(12vCPU, 39GB) | 3 nodes x $0.30 = $0.90/hr | 2 nodes x $0.30 = $0.60/hr |
-| **<u>Gitaly Cluster</u>** [Details](gitlab_sre_for_aws.md#gitaly-sre-considerations) | | | | |
+| **<u>Gitaly Cluster</u>** [Details](gitlab_sre_for_aws.md#gitaly-sre-considerations) | | | | |
| Gitaly Instances (in ASG) | 24 vCPU, 90GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | **m5.2xlarge** x 3 nodes<br />(24 vCPU, 96GB) | $0.384 x 3 = $1.15/hr | [Gitaly & Praefect Must Have an Uneven Node Count for HA](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) |
| Praefect (Instances in ASG with load balancer) | 6 vCPU, 5.4 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | **c5.large** x 3 nodes<br />(6 vCPU, 12 GB) | $0.09 x 3 = $0.21/hr | [Gitaly & Praefect Must Have an Uneven Node Count for HA](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) |
-| Praefect PostgreSQL(1) (AWS RDS) | 6 vCPU, 5.4 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | N/A Reuses GitLab PostgreSQL | $0 | |
+| Praefect PostgreSQL(1) (Amazon RDS) | 6 vCPU, 5.4 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | N/A Reuses GitLab PostgreSQL | $0 | |
| Internal Load Balancing Node | 2 vCPU, 1.8 GB | AWS ELB | $0.10/hr | $0.10/hr |
### 10K Cloud Native Hybrid on EKS
@@ -278,8 +282,11 @@ If EKS node autoscaling is employed, it is likely that your average loading will
**GPT Test Results**
-- [10K Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647_results.txt)
-- [10K AutoScale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139_results.txt)
+- [10K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647_results.txt)
+
+- [10K Elastic Auto Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139_results.txt)
+
+ Elastic Auto Scale GPT Test Results start with an idle scaled cluster and then start the standard GPT test to determine if the EKS Auto Scaler performs well enough to keep up with performance test demands. In general this is substantially harder ramping than the scaling required when the ramping is driven my normal production workloads.
**Deploy Now**
@@ -303,8 +310,8 @@ On Demand pricing is used in this table for comparisons, but should not be used
| Supporting services such as NGINX, Prometheus, etc | [2 allocations](../../administration/reference_architectures/10k_users.md#cluster-topology) x ([2 vCPU and 7.5 GB](../../administration/reference_architectures/10k_users.md#cluster-topology))<br />4 vCPU, 15 GB | | |
| **GitLab Ref Arch Raw Total K8s Node Capacity** | 128 vCPU, 158 GB | | |
| One Node for Overhead and Miscellaneous (EKS Cluster AutoScaler, Grafana, Prometheus, etc) | + 16 vCPU, 32GB | | |
-| **Grand Total w/ Overheads Fully Scaled**<br />Minimum hosts = 3 | 142 vCPU, 190 GB | **c5.4xlarge** (16vcpu/32GB) x 9 nodes<br />144 vCPU, 288GB<br /><br />[Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647_results.txt) | $6.12/hr |
-| **Possible Idle Configuration (Scaled-In 75% - round up)**<br />Pod autoscaling must be also adjusted to enable lower idling configuration. | 40 vCPU, 80 GB | c5.4xlarge x 7<br /><br />[AutoScale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139_results.txt) | $4.76/hr |
+| **Grand Total w/ Overheads Fully Scaled**<br />Minimum hosts = 3 | 142 vCPU, 190 GB | **c5.4xlarge** (16vcpu/32GB) x 9 nodes<br />144 vCPU, 288GB<br /><br />[Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647_results.txt) | $6.12/hr |
+| **Possible Idle Configuration (Scaled-In 75% - round up)**<br />Pod autoscaling must be also adjusted to enable lower idling configuration. | 40 vCPU, 80 GB | c5.4xlarge x 7<br /><br />[Elastic Auto Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139_results.txt) | $4.76/hr |
Other combinations of node type and quantity can be used to meet the Grand Total. Due to the cpu and memory requirements of pods, hosts that are overly small may have significant unused capacity.
@@ -314,12 +321,12 @@ If EKS node autoscaling is employed, it is likely that your average loading will
| Non-Kubernetes Compute | Ref Arch Raw Total | AWS BOM | Example Cost<br />US East, 3 AZ | Example Cost<br />US East, 2 AZ |
| ------------------------------------------------------------ | ------------------------------ | ------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| **Bastion Host (Quick Start)** | 1 HA instance in ASG | **t2.micro** for prod, **m4.2xlarge** for perf. testing | | |
-| **PostgreSQL**<br />AWS Aurora RDS Nodes Configuration (GPT tested) | 36vCPU, 102 GB <br />(across 9 nodes for PostgreSQL, PgBouncer, Consul) | **db.r6g.2xlarge** x 3 nodes <br />(24vCPU, 192 GB) | 3 nodes x $1.04 = $3.12/hr | 3 nodes x $1.04 = $3.12/hr<br />(Aurora is always 3) |
+| **PostgreSQL**<br />Amazon RDS PostgreSQL Nodes Configuration (GPT tested) | 36vCPU, 102 GB <br />(across 9 nodes for PostgreSQL, PgBouncer, Consul) | **db.r6g.2xlarge** x 3 nodes <br />(24vCPU, 192 GB) | 3 nodes x $1.04 = $3.12/hr | 3 nodes x $1.04 = $3.12/hr |
| **Redis** | 30vCPU, 114GB<br />(across 12 nodes for Redis Cache, Redis Queues/Shared State, Sentinel Cache, Sentinel Queues/Shared State) | **cache.m5.2xlarge** x 3 nodes<br />(24vCPU, 78GB) | 3 nodes x $0.62 = $1.86/hr | 2 nodes x $0.62 = $1.24/hr |
| **<u>Gitaly Cluster</u>** [Details](gitlab_sre_for_aws.md#gitaly-sre-considerations) | | | | |
| Gitaly Instances (in ASG) | 48 vCPU, 180GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | **m5.4xlarge** x 3 nodes<br />(48 vCPU, 180 GB) | $0.77 x 3 = $2.31/hr | [Gitaly & Praefect Must Have an Uneven Node Count for HA](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) |
| Praefect (Instances in ASG with load balancer) | 6 vCPU, 5.4 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | **c5.large** x 3 nodes<br />(6 vCPU, 12 GB) | $0.09 x 3 = $0.21/hr | [Gitaly & Praefect Must Have an Uneven Node Count for HA](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) |
-| Praefect PostgreSQL(1) (AWS RDS) | 6 vCPU, 5.4 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | N/A Reuses GitLab PostgreSQL | $0 | |
+| Praefect PostgreSQL(1) (Amazon RDS) | 6 vCPU, 5.4 GB<br />([across 3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections)) | N/A Reuses GitLab PostgreSQL | $0 | |
| Internal Load Balancing Node | 2 vCPU, 1.8 GB | AWS ELB | $0.10/hr | $0.10/hr |
### 50K Cloud Native Hybrid on EKS
@@ -328,8 +335,11 @@ If EKS node autoscaling is employed, it is likely that your average loading will
**GPT Test Results**
-- [50K Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819_results.txt)
-- [50K AutoScale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633.txt)
+- [50K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819_results.txt)
+
+- [50K Elastic Auto Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633.txt)
+
+ Elastic Auto Scale GPT Test Results start with an idle scaled cluster and then start the standard GPT test to determine if the EKS Auto Scaler performs well enough to keep up with performance test demands. In general this is substantially harder ramping than the scaling required when the ramping is driven my normal production workloads.
**Deploy Now**
@@ -353,8 +363,8 @@ On Demand pricing is used in this table for comparisons, but should not be used
| Supporting services such as NGINX, Prometheus, etc | [2 allocations](../../administration/reference_architectures/10k_users.md#cluster-topology) x ([2 vCPU and 7.5 GB](../../administration/reference_architectures/10k_users.md#cluster-topology))<br />4 vCPU, 15 GB | | |
| **GitLab Ref Arch Raw Total K8s Node Capacity** | 428 vCPU, 533 GB | | |
| One Node for Overhead and Miscellaneous (EKS Cluster AutoScaler, Grafana, Prometheus, etc) | + 16 vCPU, 32GB | | |
-| **Grand Total w/ Overheads Fully Scaled**<br />Minimum hosts = 3 | 444 vCPU, 565 GB | **c5.4xlarge** (16vcpu/32GB) x 28 nodes<br />448 vCPU, 896GB<br /><br />[Full Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819_results.txt) | $19.04/hr |
-| **Possible Idle Configuration (Scaled-In 75% - round up)**<br />Pod autoscaling must be also adjusted to enable lower idling configuration. | 40 vCPU, 80 GB | c5.2xlarge x 10<br /><br />[AutoScale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633.txt) | $6.80/hr |
+| **Grand Total w/ Overheads Fully Scaled**<br />Minimum hosts = 3 | 444 vCPU, 565 GB | **c5.4xlarge** (16vcpu/32GB) x 28 nodes<br />448 vCPU, 896GB<br /><br />[Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819_results.txt) | $19.04/hr |
+| **Possible Idle Configuration (Scaled-In 75% - round up)**<br />Pod autoscaling must be also adjusted to enable lower idling configuration. | 40 vCPU, 80 GB | c5.2xlarge x 10<br /><br />[Elastic Auto Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633.txt) | $6.80/hr |
Other combinations of node type and quantity can be used to meet the Grand Total. Due to the cpu and memory requirements of pods, hosts that are overly small may have significant unused capacity.
@@ -364,9 +374,9 @@ If EKS node autoscaling is employed, it is likely that your average loading will
| Non-Kubernetes Compute | Ref Arch Raw Total | AWS BOM | Example Cost<br />US East, 3 AZ | Example Cost<br />US East, 2 AZ |
| ------------------------------------------------------------ | ------------------------------------------------------------ | --------------------------------------------------------- | ------------------------------- | ------------------------------------------------------------ |
| **Bastion Host (Quick Start)** | 1 HA instance in ASG | **t2.micro** for prod, **m4.2xlarge** for perf. testing | | |
-| **PostgreSQL**<br />AWS Aurora RDS Nodes Configuration (GPT tested) | 96vCPU, 360 GB <br />(across 3 nodes) | **db.r6g.8xlarge** x 3 nodes <br />(96vCPU, 768 GB total) | 3 nodes x $4.15 = $12.45/hr | 3 nodes x $4.15 = $12.45/hr<br />(Aurora is always 3) |
+| **PostgreSQL**<br />Amazon RDS PostgreSQL Nodes Configuration (GPT tested) | 96vCPU, 360 GB <br />(across 3 nodes) | **db.r6g.8xlarge** x 3 nodes <br />(96vCPU, 768 GB total) | 3 nodes x $4.15 = $12.45/hr | 3 nodes x $4.15 = $12.45/hr |
| **Redis** | 30vCPU, 114GB<br />(across 12 nodes for Redis Cache, Redis Queues/Shared State, Sentinel Cache, Sentinel Queues/Shared State) | **cache.m6g.2xlarge** x 3 nodes<br />(24vCPU, 78GB total) | 3 nodes x $0.60 = $1.80/hr | 2 nodes x $0.60 = $1.20/hr |
-| **<u>Gitaly Cluster</u>** [Details](gitlab_sre_for_aws.md#gitaly-sre-considerations) | | | | |
+| **<u>Gitaly Cluster</u>** [Details](gitlab_sre_for_aws.md#gitaly-sre-considerations) | | | | |
| Gitaly Instances (in ASG) | 64 vCPU, 240GB x [3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) | **m5.16xlarge** x 3 nodes<br />(64 vCPU, 256 GB each) | $3.07 x 3 = $9.21/hr | [Gitaly & Praefect Must Have an Uneven Node Count for HA](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) |
| Praefect (Instances in ASG with load balancer) | 4 vCPU, 3.6 GB x [3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) | **c5.xlarge** x 3 nodes<br />(4 vCPU, 8 GB each) | $0.17 x 3 = $0.51/hr | [Gitaly & Praefect Must Have an Uneven Node Count for HA](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) |
| Praefect PostgreSQL(1) (AWS RDS) | 2 vCPU, 1.8 GB x [3 nodes](gitlab_sre_for_aws.md#gitaly-and-praefect-elections) | N/A Reuses GitLab PostgreSQL | $0 | |
@@ -375,3 +385,11 @@ If EKS node autoscaling is employed, it is likely that your average loading will
## Helpful Resources
- [Architecting Kubernetes clusters — choosing a worker node size](https://learnk8s.io/kubernetes-node-size)
+
+DISCLAIMER:
+This page contains information related to upcoming products, features, and functionality.
+It is important to note that the information presented is for informational purposes only.
+Please do not rely on this information for purchasing or planning purposes.
+As with all projects, the items mentioned on this page are subject to change or delay.
+The development, release, and timing of any products, features, or functionality remain at the
+sole discretion of GitLab Inc.
diff --git a/doc/install/aws/gitlab_sre_for_aws.md b/doc/install/aws/gitlab_sre_for_aws.md
index 06e3bf784bd..faec73801ab 100644
--- a/doc/install/aws/gitlab_sre_for_aws.md
+++ b/doc/install/aws/gitlab_sre_for_aws.md
@@ -1,20 +1,13 @@
---
stage: Enablement
-group: Alliances
+group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
comments: false
description: Doing SRE for GitLab instances and runners on AWS.
-type: index
---
# GitLab Site Reliability Engineering for AWS **(FREE SELF)**
-## AWS known issues list
-
-Known issues are gathered from within GitLab and from customer reported issues. Customers successfully implement GitLab with a variety of "as a Service" components that GitLab has not specifically been designed for, nor has ongoing testing for. While GitLab does take partner technologies very seriously, the highlighting of known issues here is a convenience for implementers and it does not imply that GitLab has targeted compatibility with, nor carries any type of guarantee of running on the partner technology where the issues occur. Please consult individual issues to understand GitLabs stance and plans on any given known issue.
-
-See the [GitLab AWS known issues list](https://gitlab.com/gitlab-com/alliances/aws/public-tracker/-/issues?label_name%5B%5D=AWS+Known+Issue) for a complete list.
-
## Gitaly SRE considerations
Gitaly is an embedded service for Git Repository Storage. Gitaly and Gitaly Cluster have been engineered by GitLab to overcome fundamental challenges with horizontal scaling of the open source Git binaries that must be used on the service side of GitLab. Here is indepth technical reading on the topic:
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
index 80193d882dd..563673c3260 100644
--- a/doc/install/aws/index.md
+++ b/doc/install/aws/index.md
@@ -1,6 +1,6 @@
---
stage: Enablement
-group: Alliances
+group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
comments: false
description: Read through the GitLab installation methods.
@@ -11,30 +11,38 @@ type: index
GitLab [Reference Architectures](../../administration/reference_architectures/index.md) give qualified and tested guidance on the recommended ways GitLab can be configured to meet the performance requirements of various workloads. Reference Architectures are purpose-designed to be non-implementation specific so they can be extrapolated to as many environments as possible. This generally means they have a highly-granular "machine" to "server role" specification and focus on system elements that impact performance. This is what enables Reference Architectures to be adaptable to the broadest number of supported implementations.
-Implementation patterns are built on the foundational information and testing done for Reference Architectures and allow architects and implementers at GitLab, GitLab Customers, and GitLab Partners to build out deployments with less experimentation and a higher degree of confidence that the results will perform as expected.
+Implementation patterns are built on the foundational information and testing done for Reference Architectures and allow architects and implementers at GitLab, GitLab Customers, and GitLab Partners to build out deployments with less experimentation and a higher degree of confidence that the results will perform as expected. A more thorough discussion of implementation patterns is below in [Additional details on implementation patterns](#additional-details-on-implementation-patterns).
-## Implementation patterns information
+## AWS Implementation patterns information
-### Install GitLab Cloud Native Hybrid on AWS EKS (HA)
+The following are the currently available implementation patterns for GitLab when it is implemented on AWS.
-[Provision GitLab Cloud Native Hybrid on AWS EKS (HA)](gitlab_hybrid_on_aws.md). This document includes instructions, patterns, and automation for installing GitLab Cloud Native Hybrid on AWS EKS. It also includes [Bill of Materials](https://en.wikipedia.org/wiki/Bill_of_materials) listings and links to Infrastructure as Code. GitLab Cloud Native Hybrid is the supported way to put as much of GitLab as possible into Kubernetes.
+### GitLab Site Reliability Engineering (SRE) for AWS
-### Install Omnibus GitLab on AWS EC2 (HA)
+[GitLab Site Reliability Engineering (SRE) for AWS](gitlab_sre_for_aws.md) - information for planning, implementing, upgrading and long term management of GitLab instances and runners on AWS.
-[Omnibus GitLab on AWS EC2 (HA)](manual_install_aws.md) - instructions for installing GitLab on EC2 instances. Manual instructions from which you may build out a GitLab instance or create your own Infrastructure as Code (IaC).
+### Patterns to Install GitLab Cloud Native Hybrid on AWS EKS (HA)
-### GitLab Site Reliability Engineering (SRE) for AWS
+[Provision GitLab Cloud Native Hybrid on AWS EKS (HA)](gitlab_hybrid_on_aws.md). This document includes instructions, patterns, and automation for installing GitLab Cloud Native Hybrid on AWS EKS. It also includes [Bill of Materials](https://en.wikipedia.org/wiki/Bill_of_materials) listings and links to Infrastructure as Code. GitLab Cloud Native Hybrid is the supported way to put as much of GitLab as possible into Kubernetes.
-[GitLab SRE Considerations for AWS](gitlab_sre_for_aws.md) - important information and known issues for planning, implementing, upgrading and long term management of GitLab instances and runners on AWS.
+### Patterns to Install Omnibus GitLab on AWS EC2 (HA)
-### EKS cluster provisioning best practices
+[Omnibus GitLab on AWS EC2 (HA)](manual_install_aws.md) - instructions for installing GitLab on EC2 instances. Manual instructions to build a GitLab instance or create your own Infrastructure as Code (IaC).
+
+### Patterns for EKS cluster provisioning
[EKS Cluster Provisioning Patterns](eks_clusters_aws.md) - considerations for setting up EKS cluster for runners and for integrating.
-### Scaling HA GitLab Runner on AWS EC2 ASG
+### Patterns for Scaling HA GitLab Runner on AWS EC2 ASG
The following repository is self-contained in regard to enabling this pattern: [GitLab HA Scaling Runner Vending Machine for AWS EC2 ASG](https://gitlab.com/guided-explorations/aws/gitlab-runner-autoscaling-aws-asg/). The [feature list for this implementation pattern](https://gitlab.com/guided-explorations/aws/gitlab-runner-autoscaling-aws-asg/-/blob/main/FEATURES.md) is good to review to understand the complete value it can deliver.
+## AWS known issues list
+
+Known issues are gathered from within GitLab and from customer reported issues. Customers successfully implement GitLab with a variety of "as a Service" components that GitLab has not specifically been designed for, nor has ongoing testing for. While GitLab does take partner technologies very seriously, the highlighting of known issues here is a convenience for implementers and it does not imply that GitLab has targeted compatibility with, nor carries any type of guarantee of running on the partner technology where the issues occur. Please consult individual issues to understand GitLabs stance and plans on any given known issue.
+
+See the [GitLab AWS known issues list](https://gitlab.com/gitlab-com/alliances/aws/public-tracker/-/issues?label_name%5B%5D=AWS+Known+Issue) for a complete list.
+
## Additional details on implementation patterns
GitLab implementation patterns build upon [GitLab Reference Architectures](../../administration/reference_architectures/index.md) in the following ways.
@@ -61,7 +69,7 @@ Implementation patterns enable platform-specific terminology, best practice arch
Platform as a Service options are a huge portion of the value provided by Cloud Platforms as they simplify operational complexity and reduce the SRE and security skilling required to operate advanced, highly available technology services. Implementation patterns can be prequalified against the partner PaaS options.
-- Implementation patterns help implementers understand what PaaS options are known to work and how to choose between PaaS solutions when a single platform has more than one PaaS option for the same GitLab role (for example, AWS RDS versus AWS Aurora RDS).
+- Implementation patterns help implementers understand what PaaS options are known to work and how to choose between PaaS solutions when a single platform has more than one PaaS option for the same GitLab role.
- For instance, where reference architectures do not have a specific recommendation on what technology is leveraged for GitLab outbound email services or what the sizing should be - a Reference Implementation may advise using a cloud providers Email as a Service (PaaS) and possibly even with specific settings.
### Cost optimizing engineering
diff --git a/doc/install/aws/manual_install_aws.md b/doc/install/aws/manual_install_aws.md
index 2ad54a17715..6fff4225346 100644
--- a/doc/install/aws/manual_install_aws.md
+++ b/doc/install/aws/manual_install_aws.md
@@ -2,7 +2,6 @@
stage: Enablement
group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: howto
---
{::options parse_block_html="true" /}
@@ -33,7 +32,7 @@ For the Cloud Native Hybrid architectures there are two Infrastructure as Code o
## Introduction
-For the most part, we'll make use of Omnibus GitLab in our setup, but we'll also leverage native AWS services. Instead of using the Omnibus bundled PostgreSQL and Redis, we will use AWS RDS and ElastiCache.
+For the most part, we'll make use of Omnibus GitLab in our setup, but we'll also leverage native AWS services. Instead of using the Omnibus bundled PostgreSQL and Redis, we will use Amazon RDS and ElastiCache.
In this guide, we'll go through a multi-node setup where we'll start by
configuring our Virtual Private Cloud and subnets to later integrate
@@ -410,7 +409,10 @@ persistence and is used to store session data, temporary cache information, and
## Setting up Bastion Hosts
-Since our GitLab instances will be in private subnets, we need a way to connect to these instances via SSH to make configuration changes, perform upgrades, etc. One way of doing this is via a [bastion host](https://en.wikipedia.org/wiki/Bastion_host), sometimes also referred to as a jump box.
+Because our GitLab instances are in private subnets, we need a way to connect
+to these instances with SSH for actions that include making configuration changes
+and performing upgrades. One way of doing this is by using a [bastion host](https://en.wikipedia.org/wiki/Bastion_host),
+sometimes also referred to as a jump box.
NOTE:
If you do not want to maintain bastion hosts, you can set up [AWS Systems Manager Session Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html) for access to instances. This is beyond the scope of this document.
@@ -669,8 +671,13 @@ That concludes the configuration changes for our GitLab instance. Next, we'll cr
### Log in for the first time
Using the domain name you used when setting up [DNS for the load balancer](#configure-dns-for-load-balancer), you should now be able to visit GitLab in your browser.
-If you didn't change the password by any other means, the default password will be the same as the instance ID. To change the default password, login as the `root` user
-with the default password and [change it in the user profile](../../user/profile#change-your-password).
+
+Depending on how you installed GitLab and if you did not change the password by any other means, the default password is either:
+
+- Your instance ID if you used the official GitLab AMI.
+- A randomly generated password stored for 24 hours in `/etc/gitlab/initial_root_password`.
+
+To change the default password, log in as the `root` user with the default password and [change it in the user profile](../../user/profile#change-your-password).
When our [auto scaling group](#create-an-auto-scaling-group) spins up new instances, we'll be able to log in with username `root` and the newly created password.
diff --git a/doc/install/docker.md b/doc/install/docker.md
index b3e7e758ec3..00e19e2977b 100644
--- a/doc/install/docker.md
+++ b/doc/install/docker.md
@@ -27,7 +27,7 @@ WARNING:
Docker for Windows is not officially supported. There are known issues with volume
permissions, and potentially other unknown issues. If you are trying to run on Docker
for Windows, see the [getting help page](https://about.gitlab.com/get-help/) for links
-to community resources (IRC, forum, etc.) to seek help from other users.
+to community resources (such as IRC or forums) to seek help from other users.
## Prerequisites
diff --git a/doc/install/google_cloud_platform/index.md b/doc/install/google_cloud_platform/index.md
index bda98ead1f5..b3d0863f6a3 100644
--- a/doc/install/google_cloud_platform/index.md
+++ b/doc/install/google_cloud_platform/index.md
@@ -3,7 +3,6 @@ stage: Enablement
group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
description: 'Learn how to install a GitLab instance on Google Cloud Platform.'
-type: howto
---
# Installing GitLab on Google Cloud Platform **(FREE SELF)**
@@ -11,9 +10,11 @@ type: howto
This guide will help you install GitLab on a [Google Cloud Platform (GCP)](https://cloud.google.com/) using the official GitLab Linux package. You should customize it to accommodate your needs.
NOTE:
-Google provides a whitepaper for [deploying production-ready GitLab on
-Google Kubernetes Engine](https://cloud.google.com/architecture/deploying-production-ready-gitlab-on-gke),
-including all steps and external resource configuration. These are an alternative to using a GCP VM, and use
+To deploy production-ready GitLab on
+Google Kubernetes Engine,
+you can follow Google Cloud Platform's
+[Click to Deploy steps](https://github.com/GoogleCloudPlatform/click-to-deploy/blob/master/k8s/gitlab/README.md)
+It's an alternative to using a GCP VM, and uses
the [Cloud native GitLab Helm chart](https://docs.gitlab.com/charts/).
## Prerequisites
@@ -126,8 +127,8 @@ Check the [Omnibus documentation](https://docs.gitlab.com/omnibus/settings/smtp.
## Further reading
-GitLab can be configured to authenticate with other OAuth providers, LDAP, SAML,
-Kerberos, etc. Here are some documents you might be interested in reading:
+GitLab can be configured to authenticate with other OAuth providers, like LDAP,
+SAML, and Kerberos. Here are some documents you might be interested in reading:
- [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/)
- [Integration documentation](../../integration/index.md)
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 7c8718a7005..cd00593a99b 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -2,7 +2,6 @@
stage: Enablement
group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: howto
---
# Installation from source **(FREE SELF)**
@@ -424,6 +423,49 @@ echo 'unixsocket /var/run/redis/redis.sock' | sudo tee -a /etc/redis/redis.conf
# Grant permission to the socket to all members of the redis group
echo 'unixsocketperm 770' | sudo tee -a /etc/redis/redis.conf
+# Add git to the redis group
+sudo usermod -aG redis git
+```
+
+### Supervise Redis with systemd
+
+If your distribution uses systemd init and the output of the following command is `notify`,
+you do not need to make any changes:
+
+```shell
+systemctl show --value --property=Type redis-server.service
+```
+
+If the output is **not** `notify`, run:
+
+```shell
+# Configure Redis to not daemonize, but be supervised by systemd instead and disable the pidfile
+sudo sed -i \
+ -e 's/^daemonize yes$/daemonize no/' \
+ -e 's/^supervised no$/supervised systemd/' \
+ -e 's/^pidfile/# pidfile/' /etc/redis/redis.conf
+sudo chown redis:redis /etc/redis/redis.conf
+
+# Make the same changes to the systemd unit file
+sudo mkdir -p /etc/systemd/system/redis-server.service.d
+sudo tee /etc/systemd/system/redis-server.service.d/10fix_type.conf <<EOF
+[Service]
+Type=notify
+PIDFile=
+EOF
+
+# Reload the redis service
+sudo systemctl daemon-reload
+
+# Activate the changes to redis.conf
+sudo systemctl restart redis-server.service
+```
+
+### Leave Redis unsupervised
+
+If your system uses SysV init, run these commands:
+
+```shell
# Create the directory which contains the socket
sudo mkdir -p /var/run/redis
sudo chown redis:redis /var/run/redis
@@ -436,9 +478,6 @@ fi
# Activate the changes to redis.conf
sudo service redis-server restart
-
-# Add git to the redis group
-sudo usermod -aG redis git
```
## 8. GitLab
@@ -688,48 +727,79 @@ sudo -u git -H editor config.toml
For more information about configuring Gitaly see
[the Gitaly documentation](../administration/gitaly/index.md).
-### Start Gitaly
+### Install the service
-Gitaly must be running for the next section.
+GitLab has always supported SysV init scripts, which are widely supported and portable, but now systemd is the standard for service supervision and is used by all major Linux distributions. You should use native systemd services if you can to benefit from automatic restarts, better sandboxing and resource control.
-```shell
-gitlab_path=/home/git/gitlab
-gitaly_path=/home/git/gitaly
+#### Install systemd units
-sudo -u git -H sh -c "$gitlab_path/bin/daemon_with_pidfile $gitlab_path/tmp/pids/gitaly.pid \
- $gitaly_path/_build/bin/gitaly $gitaly_path/config.toml >> $gitlab_path/log/gitaly.log 2>&1 &"
-```
+Use these steps if you use systemd as init. Otherwise, follow the [SysV init script steps](#install-sysv-init-script).
-### Initialize Database and Activate Advanced Features
+Copy the services and run `systemctl daemon-reload` so that systemd picks them up:
```shell
cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
-# Type 'yes' to create the database tables.
+sudo mkdir -p /usr/local/lib/systemd/system
+sudo cp lib/support/systemd/* /usr/local/lib/systemd/system/
+sudo systemctl daemon-reload
+```
-# or you can skip the question by adding force=yes
-sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production force=yes
+The units provided by GitLab make very little assumptions about where you are running Redis and PostgreSQL.
-# When done, you see 'Administrator account created:'
-```
+If you installed GitLab in another directory or as a user other than the default, you need to change these values in the units as well.
-You can set the Administrator/root password and email by supplying them in environmental variables, `GITLAB_ROOT_PASSWORD` and `GITLAB_ROOT_EMAIL` respectively, as seen below. If you don't set the password (and it is set to the default one), wait to expose GitLab to the public internet until the installation is done and you've logged into the server the first time. During the first login, you'll be forced to change the default password. An Enterprise Edition license may also be installed at this time by supplying a full path in the `GITLAB_LICENSE_FILE` environment variable.
+For example, if you're running Redis and PostgreSQL on the same machine as GitLab, you should:
+
+- Edit the Puma service:
+
+ ```shell
+ sudo systemctl edit gitlab-puma.service
+ ```
+
+ In the editor that opens, add the following and save the file:
+
+ ```plaintext
+ [Unit]
+ Wants=redis-server.service postgresql.service
+ After=redis-server.service postgresql.service
+ ```
+
+- Edit the Sidekiq service:
+
+ ```shell
+ sudo systemctl edit gitlab-sidekiq.service
+ ```
+
+ Add the following and save the file:
+
+ ```plaintext
+ [Unit]
+ Wants=redis-server.service postgresql.service
+ After=redis-server.service postgresql.service
+ ```
+
+`systemctl edit` installs drop-in configuration files at `/etc/systemd/system/<name of the unit>.d/override.conf`, so your local configuration is not overwritten when updating the unit files later. To split up your drop-in configuration files, you can add the above snippets to `.conf` files under `/etc/systemd/system/<name of the unit>.d/`.
+
+If you manually made changes to the unit files or added drop-in configuration files (without using `systemctl edit`), run the following command for them to take effect:
```shell
-sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=yourpassword GITLAB_ROOT_EMAIL=youremail GITLAB_LICENSE_FILE="/path/to/license"
+sudo systemctl daemon-reload
```
-### Secure secrets.yml
+Make GitLab start on boot:
-The `secrets.yml` file stores encryption keys for sessions and secure variables.
-Backup `secrets.yml` someplace safe, but don't store it in the same place as your database backups.
-Otherwise, your secrets are exposed if one of your backups is compromised.
+```shell
+sudo systemctl enable gitlab.target
+```
+
+#### Install SysV init script
-### Install Init Script
+Use these steps if you use the SysV init script. If you use systemd, follow the [systemd unit steps](#install-systemd-units).
Download the init script (is `/etc/init.d/gitlab`):
```shell
+cd /home/git/gitlab
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
```
@@ -745,6 +815,9 @@ Make GitLab start on boot:
```shell
sudo update-rc.d gitlab defaults 21
+# or if running this on a machine running systemd
+sudo systemctl daemon-reload
+sudo systemctl enable gitlab.service
```
### Set up Logrotate
@@ -753,6 +826,51 @@ sudo update-rc.d gitlab defaults 21
sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
```
+### Start Gitaly
+
+Gitaly must be running for the next section.
+
+- To start Gitaly using systemd:
+
+ ```shell
+ sudo systemctl start gitlab-gitaly.service
+ ```
+
+- To manually start Gitaly for SysV:
+
+ ```shell
+ gitlab_path=/home/git/gitlab
+ gitaly_path=/home/git/gitaly
+
+ sudo -u git -H sh -c "$gitlab_path/bin/daemon_with_pidfile $gitlab_path/tmp/pids/gitaly.pid \
+ $gitaly_path/_build/bin/gitaly $gitaly_path/config.toml >> $gitlab_path/log/gitaly.log 2>&1 &"
+ ```
+
+### Initialize Database and Activate Advanced Features
+
+```shell
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
+# Type 'yes' to create the database tables.
+
+# or you can skip the question by adding force=yes
+sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production force=yes
+
+# When done, you see 'Administrator account created:'
+```
+
+You can set the Administrator/root password and email by supplying them in environmental variables, `GITLAB_ROOT_PASSWORD` and `GITLAB_ROOT_EMAIL` respectively, as seen below. If you don't set the password (and it is set to the default one), wait to expose GitLab to the public internet until the installation is done and you've logged into the server the first time. During the first login, you'll be forced to change the default password. An Enterprise Edition license may also be installed at this time by supplying a full path in the `GITLAB_LICENSE_FILE` environment variable.
+
+```shell
+sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=yourpassword GITLAB_ROOT_EMAIL=youremail GITLAB_LICENSE_FILE="/path/to/license"
+```
+
+### Secure secrets.yml
+
+The `secrets.yml` file stores encryption keys for sessions and secure variables.
+Backup `secrets.yml` someplace safe, but don't store it in the same place as your database backups.
+Otherwise, your secrets are exposed if one of your backups is compromised.
+
### Check Application Status
Check if GitLab and its environment are configured correctly:
@@ -783,9 +901,11 @@ sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_
### Start Your GitLab Instance
```shell
+# For systems running systemd
+sudo systemctl start gitlab.target
+
+# For systems running SysV init
sudo service gitlab start
-# or
-sudo /etc/init.d/gitlab restart
```
## 9. NGINX
@@ -838,7 +958,9 @@ Validate your `gitlab` or `gitlab-ssl` NGINX configuration file with the followi
sudo nginx -t
```
-You should receive `syntax is okay` and `test is successful` messages. If you receive errors check your `gitlab` or `gitlab-ssl` NGINX configuration file for typos, etc. as indicated in the error message given.
+You should receive `syntax is okay` and `test is successful` messages. If you
+receive error messages, check your `gitlab` or `gitlab-ssl` NGINX configuration
+file for typos, as indicated in the provided error message.
Verify that the installed version is greater than 1.12.1:
@@ -856,6 +978,10 @@ nginx: configuration file /etc/nginx/nginx.conf test failed
### Restart
```shell
+# For systems running systemd
+sudo systemctl restart nginx.service
+
+# For systems running SysV init
sudo service nginx restart
```
@@ -888,7 +1014,10 @@ earlier and login. After login, you can change the username if you wish.
**Enjoy!**
-You can use `sudo service gitlab start` and `sudo service gitlab stop` to start and stop GitLab.
+To start and stop GitLab when using:
+
+- systemd units: use `sudo systemctl start gitlab.target` or `sudo systemctl stop gitlab.target`.
+- The SysV init script: use `sudo service gitlab start` or `sudo service gitlab stop`.
## Advanced Setup Tips
@@ -1026,7 +1155,7 @@ misconfigured GitLab Workhorse instance. Double-check that you've
[installed Go](#3-go), [installed GitLab Workhorse](#install-gitlab-workhorse),
and correctly [configured NGINX](#site-configuration).
-### `google-protobuf` "LoadError: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14' not found"
+### `google-protobuf` "LoadError: /lib/x86_64-linux-gnu/libc.so.6: version 'GLIBC_2.14' not found"
This can happen on some platforms for some versions of the
`google-protobuf` gem. The workaround is to install a source-only
diff --git a/doc/install/openshift_and_gitlab/index.md b/doc/install/openshift_and_gitlab/index.md
index 3b7ea5c1975..f74e9f26362 100644
--- a/doc/install/openshift_and_gitlab/index.md
+++ b/doc/install/openshift_and_gitlab/index.md
@@ -1,9 +1,45 @@
---
-redirect_to: 'https://docs.gitlab.com/charts/installation/operator.html'
-remove_date: '2022-09-22'
+stage: Enablement
+group: Distribution
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-This file was moved to [another location](https://docs.gitlab.com/charts/installation/operator.html).
+# OpenShift support
-<!-- This redirect file can be deleted after <2022-09-22>. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
+OpenShift - GitLab compatibility can be addressed in three different aspects. This page helps navigating between these aspects and provides introductory information for getting started with OpenShift and GitLab.
+
+## What is OpenShift
+
+OpenShift helps you to develop, deploy, and manage container-based applications. It provides you with a self-service platform to create, modify, and deploy applications on demand, thus enabling faster development and release life cycles.
+
+## Use OpenShift to run GitLab Self-Managed
+
+Running GitLab within an OpenShift cluster is officially supported using the GitLab Operator. You can learn more on
+[setting up GitLab on OpenShift on the GitLab Operator's documentation](https://docs.gitlab.com/charts/installation/operator.html).
+Some components (documented on the GitLab Operator doc) are not supported yet.
+
+## Deploy to and integrate with OpenShift from GitLab
+
+Deploying custom or COTS applications on top of OpenShift from GitLab is supported using [the GitLab Kubernetes Agent](../../user/clusters/agent/index.md).
+
+## Use OpenShift to run a GitLab Runner Fleet
+
+The GitLab Operator does not include the GitLab Runner. To install and manage a GitLab Runner fleet in an OpenShift cluster, use the
+[GitLab Runner Operator](https://gitlab.com/gitlab-org/gl-openshift/gitlab-runner-operator).
+
+## Unsupported GitLab features
+
+### Docker-in-Docker
+
+When using OpenShift to run a GitLab Runner Fleet, we do not support some GitLab features given OpenShift's security model.
+Features requiring Docker-in-Docker might not work.
+
+For Auto DevOps, the following features are not supported yet:
+
+- Auto Code Quality
+- Auto License Compliance
+- Auto Browser Performance Testing
+- Auto Build
+
+For Auto Build, there's a [possible workaround using `kaniko`](../../ci/docker/using_kaniko.md).
+You can check the progress of the implementation in this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/332560).
diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md
index 8b629e9084e..569f6e02ea4 100644
--- a/doc/install/relative_url.md
+++ b/doc/install/relative_url.md
@@ -2,7 +2,6 @@
stage: Enablement
group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: reference
---
# Install GitLab under a relative URL **(FREE SELF)**
@@ -37,11 +36,11 @@ After all the changes you need to recompile the assets and [restart GitLab](../a
## Relative URL requirements
-If you configure GitLab with a relative URL, the assets (JavaScript, CSS, fonts,
-images, etc.) will need to be recompiled, which is a task which consumes a lot
-of CPU and memory resources. To avoid out-of-memory errors, you should have at
-least 2GB of RAM available on your system, while we recommend 4GB RAM, and 4 or
-8 CPU cores.
+If you configure GitLab with a relative URL, the assets (including JavaScript,
+CSS, fonts, and images) must be recompiled, which can consume a lot of CPU and
+memory resources. To avoid out-of-memory errors, you should have at least 2 GB
+of RAM available on your computer, and we recommend 4 GB RAM, and four or eight
+CPU cores.
See the [requirements](requirements.md) document for more information.
@@ -102,8 +101,9 @@ Make sure to follow all steps below:
gitlab_url: http://127.0.0.1/gitlab
```
-1. Make sure you have copied the supplied init script and the defaults file
- as stated in the [installation guide](installation.md#install-init-script).
+1. Make sure you have copied either the supplied systemd services, or the init
+ script and the defaults file, as stated in the
+ [installation guide](installation.md#install-the-service).
Then, edit `/etc/default/gitlab` and set in `gitlab_workhorse_options` the
`-authBackend` setting to read like:
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index c136fb21a90..5dbe9a1154f 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -2,7 +2,6 @@
stage: Enablement
group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: reference
---
# Installation requirements **(FREE SELF)**
@@ -119,7 +118,6 @@ the following table) as these were used for development and testing:
| GitLab version | Minimum PostgreSQL version |
|----------------|----------------------------|
-| 10.0 | 9.6 |
| 13.0 | 11 |
| 14.0 | 12 |
@@ -272,9 +270,9 @@ On a very active server (10,000 billable users) the Sidekiq process can use 1GB+
## Prometheus and its exporters
-As of Omnibus GitLab 9.0, [Prometheus](https://prometheus.io) and its related
-exporters are enabled by default, to enable easy and in depth monitoring of
-GitLab. With default settings, these processes consume approximately 200MB of memory.
+[Prometheus](https://prometheus.io) and its related exporters are enabled by
+default to enable in depth monitoring of GitLab. With default settings, these
+processes consume approximately 200 MB of memory.
If you would like to disable Prometheus and it's exporters or read more information
about it, check the [Prometheus documentation](../administration/monitoring/prometheus/index.md).
@@ -304,7 +302,7 @@ The GitLab Runner server requirements depend on:
Since the nature of the jobs varies for each use case, you need to experiment by adjusting the job concurrency to get the optimum setting.
-For reference, the GitLab.com Build Cloud [auto-scaling runner for Linux](../ci/runners/build_cloud/linux_build_cloud.md) is configured so that a **single job** runs in a **single instance** with:
+For reference, the GitLab.com Runner Cloud [auto-scaling runner for Linux](../ci/runners/build_cloud/linux_build_cloud.md) is configured so that a **single job** runs in a **single instance** with:
- 1 vCPU.
- 3.75 GB of RAM.
diff --git a/doc/integration/akismet.md b/doc/integration/akismet.md
index d216b827676..d5e39a59dff 100644
--- a/doc/integration/akismet.md
+++ b/doc/integration/akismet.md
@@ -8,7 +8,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
GitLab uses [Akismet](https://akismet.com/) to prevent the creation of
spam issues on public projects. Issues created through the web UI or the API can be submitted to
-Akismet for review.
+Akismet for review, and instance administrators can
+[mark snippets as spam](../user/snippets.md#mark-snippet-as-spam).
Detected spam is rejected, and an entry is added in the **Spam Log** section of the
Admin page.
diff --git a/doc/integration/auth0.md b/doc/integration/auth0.md
index 870da6cdb3d..e243e1defe8 100644
--- a/doc/integration/auth0.md
+++ b/doc/integration/auth0.md
@@ -48,7 +48,7 @@ application.
sudo -u git -H editor config/gitlab.yml
```
-1. Read [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration)
+1. Read [Configure initial settings](omniauth.md#configure-initial-settings)
for initial settings.
1. Add the provider configuration:
diff --git a/doc/integration/azure.md b/doc/integration/azure.md
index 3eb0344edda..bd16c8c0069 100644
--- a/doc/integration/azure.md
+++ b/doc/integration/azure.md
@@ -48,7 +48,7 @@ As you go through the Microsoft procedure, keep the following in mind:
sudo -u git -H editor config/gitlab.yml
```
-1. Refer to [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration)
+1. Refer to [Configure initial settings](omniauth.md#configure-initial-settings)
for initial settings.
1. Add the provider configuration:
@@ -136,6 +136,8 @@ After you have created an application, follow the [Microsoft Quickstart document
- `openid`
- `profile`
+Alternatively, add the `User.Read.All` application permission.
+
### Configuring GitLab
1. On your GitLab server, open the configuration file.
@@ -154,7 +156,7 @@ After you have created an application, follow the [Microsoft Quickstart document
sudo -u git -H editor config/gitlab.yml
```
-1. Refer to [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration)
+1. Refer to [Configure initial settings](omniauth.md#configure-initial-settings)
for initial settings.
1. Add the provider configuration:
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
index 471b1e4e262..4699f7147aa 100644
--- a/doc/integration/cas.md
+++ b/doc/integration/cas.md
@@ -28,7 +28,7 @@ configure CAS for back-channel logout.
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings.
1. Add the provider configuration:
diff --git a/doc/integration/ding_talk.md b/doc/integration/ding_talk.md
new file mode 100644
index 00000000000..55d51a5ebff
--- /dev/null
+++ b/doc/integration/ding_talk.md
@@ -0,0 +1,84 @@
+---
+stage: Ecosystem
+group: Integrations
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# DingTalk OAuth 2.0 OmniAuth provider **(FREE SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/341898) in GitLab 14.5.
+
+You can sign in to GitLab using your DingTalk account.
+Sign in to DingTalk Open Platform and create an application on it. DingTalk generates a client ID and secret key for you to use.
+
+1. Sign in to [DingTalk Open Platform](https://open-dev.dingtalk.com/).
+
+1. On the top bar, select **Application development > Enterprise internal development** and then select **Create Application**.
+
+ ![DingTalk menu](img/ding_talk_menu.png)
+
+1. Fill in the application details:
+
+ - **Application Name**: This can be anything. Consider something like `<Organization>'s GitLab`, or `<Your Name>'s GitLab`, or something else descriptive.
+ - **Application Description**: Create a description.
+ - **Application icon**: Upload qualified icons if needed.
+
+ ![DingTalk create application](img/ding_talk_create_application.png)
+
+1. Select **Confirm and create**.
+
+1. On the left sidebar, select **DingTalk Application** and find your application. Select it and go to the application information page.
+
+ ![DingTalk your application](img/ding_talk_your_application.png)
+
+1. Under the **Application Credentials** section, there should be an AppKey and AppSecret (see the screenshot). Keep this page open as you continue the configuration.
+
+ ![DingTalk credentials](img/ding_talk_credentials.png)
+
+1. On your GitLab server, open the configuration file.
+
+ For Omnibus package:
+
+ ```shell
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ For installations from source:
+
+ ```shell
+ cd /home/git/gitlab
+
+ sudo -u git -H editor config/gitlab.yml
+ ```
+
+1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings.
+
+1. Add the provider configuration:
+
+ For Omnibus package:
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ "name" => "ding_talk",
+ "app_id" => "YOUR_APP_ID",
+ "app_secret" => "YOUR_APP_SECRET"
+ }
+ ]
+ ```
+
+ For installations from source:
+
+ ```yaml
+ - { name: 'ding_talk',
+ app_id: 'YOUR_APP_ID',
+ app_secret: 'YOUR_APP_SECRET' }
+ ```
+
+1. Change `YOUR_APP_ID` to the AppKey from the application information page in step 6.
+
+1. Change `YOUR_APP_SECRET` to the AppSecret from the application information page in step 6.
+
+1. Save the configuration file.
+
+1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index b5b09fcd813..20f8fdc55f2 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -93,7 +93,7 @@ the indexer itself.
This project relies on [International Components for Unicode](https://icu.unicode.org/) (ICU) for text encoding,
therefore we must ensure the development packages for your platform are
-installed before running `make`.
+installed before running `make`.
#### Debian / Ubuntu
@@ -113,6 +113,9 @@ sudo yum install libicu-devel
#### macOS
+NOTE:
+You must first [install Homebrew](https://brew.sh/).
+
To install on macOS, run:
```shell
diff --git a/doc/integration/facebook.md b/doc/integration/facebook.md
index 58c53db7996..1a3360aa470 100644
--- a/doc/integration/facebook.md
+++ b/doc/integration/facebook.md
@@ -72,7 +72,7 @@ Facebook. Facebook generates an app ID and secret key for you to use.
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings.
1. Add the provider configuration:
diff --git a/doc/integration/github.md b/doc/integration/github.md
index 16241c9293b..11a9a5ea64d 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -29,7 +29,7 @@ When you create an OAuth 2 app in GitHub, you need the following information:
- The URL of your GitLab instance, such as `https://gitlab.example.com`.
- The authorization callback URL; in this case, `https://gitlab.example.com/users/auth`. Include the port number if your GitLab instance uses a non-default port.
-See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings.
After you have configured the GitHub provider, you need the following information. You must substitute that information in the GitLab configuration file in these next steps.
diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md
index 5e28765bb86..b69147b3829 100644
--- a/doc/integration/gitlab.md
+++ b/doc/integration/gitlab.md
@@ -45,7 +45,7 @@ GitLab.com generates an application ID and secret key for you to use.
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings.
1. Add the provider configuration:
For Omnibus installations authenticating against **GitLab.com**:
diff --git a/doc/integration/gmail_action_buttons_for_gitlab.md b/doc/integration/gmail_action_buttons_for_gitlab.md
index 0468e5d0a42..8b984122c8b 100644
--- a/doc/integration/gmail_action_buttons_for_gitlab.md
+++ b/doc/integration/gmail_action_buttons_for_gitlab.md
@@ -10,7 +10,7 @@ GitLab supports [Google actions in email](https://developers.google.com/gmail/ma
If correctly set up, emails that require an action are marked in Gmail.
-![GMail actions button](img/gmail_action_buttons_for_gitlab.png)
+![Gmail actions button](img/gmail_action_buttons_for_gitlab.png)
To get this functioning, you must be registered with Google. For instructions, see
[Register with Google](https://developers.google.com/gmail/markup/registering-with-google).
diff --git a/doc/integration/google.md b/doc/integration/google.md
index 172015f7528..5df76ebb3d1 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -71,7 +71,7 @@ On your GitLab server:
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings.
1. Add the provider configuration:
For Omnibus GitLab:
diff --git a/doc/integration/img/ding_talk_create_application.png b/doc/integration/img/ding_talk_create_application.png
new file mode 100644
index 00000000000..7e58dae8299
--- /dev/null
+++ b/doc/integration/img/ding_talk_create_application.png
Binary files differ
diff --git a/doc/integration/img/ding_talk_credentials.png b/doc/integration/img/ding_talk_credentials.png
new file mode 100644
index 00000000000..f9fef7f9e51
--- /dev/null
+++ b/doc/integration/img/ding_talk_credentials.png
Binary files differ
diff --git a/doc/integration/img/ding_talk_menu.png b/doc/integration/img/ding_talk_menu.png
new file mode 100644
index 00000000000..2c5a23435fa
--- /dev/null
+++ b/doc/integration/img/ding_talk_menu.png
Binary files differ
diff --git a/doc/integration/img/ding_talk_your_application.png b/doc/integration/img/ding_talk_your_application.png
new file mode 100644
index 00000000000..0864b54cc43
--- /dev/null
+++ b/doc/integration/img/ding_talk_your_application.png
Binary files differ
diff --git a/doc/integration/img/enabled-oauth-sign-in-sources_v13_10.png b/doc/integration/img/enabled-oauth-sign-in-sources_v13_10.png
deleted file mode 100644
index 86f6402c168..00000000000
--- a/doc/integration/img/enabled-oauth-sign-in-sources_v13_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/jira/connect-app.md b/doc/integration/jira/connect-app.md
index d274710b3cd..27f482ee2ba 100644
--- a/doc/integration/jira/connect-app.md
+++ b/doc/integration/jira/connect-app.md
@@ -6,34 +6,39 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab.com for Jira Cloud app **(FREE)**
+You can integrate GitLab and Jira Cloud using the
+[GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud)
+app in the Atlassian Marketplace.
+
NOTE:
-Only Jira users with administrator level access are able to install or configure
+Only Jira users with the administrator role can install or configure
the GitLab.com for Jira Cloud app.
-## GitLab.com for Jira Cloud app **(FREE SAAS)**
+## Install the GitLab.com for Jira Cloud app **(FREE SAAS)**
-You can integrate GitLab.com and Jira Cloud using the
-[GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud)
-app in the Atlassian Marketplace. The user configuring GitLab.com for Jira Cloud app must have
-[Maintainer](../../user/permissions.md) permissions in the GitLab.com namespace.
+If you use GitLab.com and Jira Cloud, you can install the GitLab.com for Jira Cloud app.
+If you do not use both of these environments, use the [Jira DVCS Connector](dvcs.md) or
+[install GitLab.com for Jira Cloud app for self-managed instances](#install-the-gitlabcom-for-jira-cloud-app-for-self-managed-instances).
+We recommend the GitLab.com for Jira Cloud app, because data is
+synchronized in real time. The DVCS connector updates data only once per hour.
-This integration method supports [smart commits](dvcs.md#smart-commits).
+The user configuring the GitLab.com for Jira Cloud app must have
+at least the [Maintainer](../../user/permissions.md) role in the GitLab.com namespace.
-This method is recommended when using GitLab.com and Jira Cloud because data is
-synchronized in real-time. The DVCS connector updates data only once per hour.
-If you are not using both of these environments, use the [Jira DVCS Connector](dvcs.md) method or
-[steps to install GitLab.com for Jira Cloud app for self-managed instances](#install-the-gitlabcom-for-jira-cloud-app-for-self-managed-instances).
+This integration method supports [Smart Commits](dvcs.md#smart-commits).
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For a walkthrough of the integration with GitLab.com for Jira Cloud app, watch
[Configure GitLab.com Jira Could Integration using Marketplace App](https://youtu.be/SwR-g1s1zTo) on YouTube.
-1. Go to **Jira Settings > Apps > Find new apps**, then search for GitLab.
-1. Click **GitLab.com for Jira Cloud**, then click **Get it now**, or go to the
+To install the GitLab.com for Jira Cloud app:
+
+1. In Jira, go to **Jira Settings > Apps > Find new apps**, then search for GitLab.
+1. Select **GitLab.com for Jira Cloud**, then select **Get it now**, or go to the
[App in the marketplace directly](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud).
![Install GitLab.com app on Jira Cloud](img/jira_dev_panel_setup_com_1.png)
-1. After installing, click **Get started** to go to the configurations page.
+1. After installing, to go to the configurations page, select **Get started**.
This page is always available under **Jira Settings > Apps > Manage apps**.
![Start GitLab.com app configuration on Jira Cloud](img/jira_dev_panel_setup_com_2.png)
@@ -41,7 +46,7 @@ For a walkthrough of the integration with GitLab.com for Jira Cloud app, watch
[Maintainer](../../user/permissions.md) permissions to add namespaces.
![Sign in to GitLab.com in GitLab.com for Jira Cloud app](img/jira_dev_panel_setup_com_3_v13_9.png)
-1. Select **Add namespace** to open the list of available namespaces.
+1. To open the list of available namespaces, select **Add namespace**.
1. Identify the namespace you want to link, and select **Link**. Only Jira site
administrators are permitted to add or remove namespaces for an installation.
@@ -89,30 +94,30 @@ from outside the Marketplace, which allows you to install the application:
1. Sign in to your Jira instance as a user with an Administrator role.
1. Place your Jira instance into
[development mode](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/#step-2--enable-development-mode).
-1. Sign in to your GitLab application as a user with an [Administrator](../../user/permissions.md) role.
+1. Sign in to your GitLab application as an [administrator](../../user/permissions.md).
1. Install the GitLab application from your self-managed GitLab instance, as
described in the [Atlassian developer guides](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/#step-3--install-and-test-your-app):
- 1. In your Jira instance, go to **Apps > Manage Apps** and click **Upload app**:
+ 1. In your Jira instance, go to **Apps > Manage Apps** and select **Upload app**:
- ![Image showing button labeled "upload app"](img/jira-upload-app_v13_11.png)
+ ![Button labeled "upload app"](img/jira-upload-app_v13_11.png)
- 1. For **App descriptor URL**, provide full URL to your manifest file, modifying this
- URL based on your instance configuration: `https://your.domain/your-path/-/jira_connect/app_descriptor.json`
- 1. Click **Upload**, and Jira fetches the content of your `app_descriptor` file and installs
- it for you.
+ 1. For **App descriptor URL**, provide the full URL to your manifest file, based
+ on your instance configuration. For example: `https://your.domain/your-path/-/jira_connect/app_descriptor.json`.
+ 1. Select **Upload**. Jira fetches the content of your `app_descriptor` file and installs
+ it.
1. If the upload is successful, Jira displays a modal panel: **Installed and ready to go!**
- Click **Get started** to configure the integration.
+ To configure the integration, select **Get started**.
- ![Image showing success modal](img/jira-upload-app-success_v13_11.png)
+ ![Success modal](img/jira-upload-app-success_v13_11.png)
1. Disable [development mode](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/#step-2--enable-development-mode) on your Jira instance.
The **GitLab.com for Jira Cloud** app now displays under **Manage apps**. You can also
-click **Get started** to open the configuration page rendered from your GitLab instance.
+select **Get started** to open the configuration page rendered from your GitLab instance.
NOTE:
-If a GitLab update makes changes to the application descriptor, you must uninstall, then reinstall, the
-application.
+If a GitLab update makes changes to the application descriptor, you must uninstall,
+then reinstall the application.
### Create a Marketplace listing
@@ -120,31 +125,33 @@ If you prefer to not use development mode on your Jira instance, you can create
your own Marketplace listing for your instance. This enables your application
to be installed from the Atlassian Marketplace.
-For full instructions, review the Atlassian [guide to creating a marketplace listing](https://developer.atlassian.com/platform/marketplace/installing-cloud-apps/#creating-the-marketplace-listing). To create a
-Marketplace listing, you must:
+For full instructions, review the Atlassian [guide to creating a marketplace listing](https://developer.atlassian.com/platform/marketplace/installing-cloud-apps/#creating-the-marketplace-listing).
+To create a Marketplace listing:
1. Register as a Marketplace vendor.
-1. List your application, using the application descriptor URL.
+1. List your application using the application descriptor URL.
- Your manifest file is located at: `https://your.domain/your-path/-/jira_connect/app_descriptor.json`
- - GitLab recommends you list your application as `private`, because public
+ - We recommend you list your application as `private`, because public
applications can be viewed and installed by any user.
1. Generate test license tokens for your application.
-Review the
-[official Atlassian documentation](https://developer.atlassian.com/platform/marketplace/installing-cloud-apps/#creating-the-marketplace-listing)
-for details.
-
NOTE:
-Using this method, [updates are automated](#update-the-gitlabcom-for-jira-cloud-app)
-the same way as when using our GitLab.com Marketplace listing.
+This method uses [automated updates](#update-the-gitlabcom-for-jira-cloud-app)
+the same way as our GitLab.com Marketplace listing.
## Troubleshoot GitLab.com for Jira Cloud app
-The GitLab.com for Jira Cloud app uses an iframe to add namespaces on the
-settings page. Some browsers block cross-site cookies, which can lead to a
-message saying that the user needs to log in on GitLab.com even though the user
-is already logged in.
+### Browser displays sign-in message when already signed in
+
+You might get the following message prompting you to sign in to GitLab.com
+when you're already signed in:
+
+```plaintext
+You need to sign in or sign up before continuing.
+```
-> "You need to sign in or sign up before continuing."
+GitLab.com for Jira Cloud app uses an iframe to add namespaces on the
+settings page. Some browsers block cross-site cookies, which can lead to this issue.
-In this case, use [Firefox](https://www.mozilla.org/en-US/firefox/), [Google Chrome](https://www.google.com/chrome/), or enable cross-site cookies in your browser.
+To resolve this issue, use [Firefox](https://www.mozilla.org/en-US/firefox/),
+[Google Chrome](https://www.google.com/chrome/), or enable cross-site cookies in your browser.
diff --git a/doc/integration/jira/development_panel.md b/doc/integration/jira/development_panel.md
index 6fa084ee872..8f66edcffa8 100644
--- a/doc/integration/jira/development_panel.md
+++ b/doc/integration/jira/development_panel.md
@@ -38,7 +38,7 @@ After the integration is [set up on GitLab and Jira](#configure-the-integration)
- Refer to any Jira issue by its ID (in uppercase) in GitLab branch names,
commit messages, and merge request titles.
- See the linked branches, commits, and merge requests in Jira issues.
-- Create GitLab branches from Jira issues ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66032) in GitLab 14.2).
+- Create GitLab branches from Jira Cloud issues ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66032) in GitLab 14.2).
At this time, merge requests are called "pull requests" in Jira issues.
This name may change in a future Jira release.
@@ -89,7 +89,10 @@ This integration is not supported on GitLab instances under a
[relative URL](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab).
For example, `http://example.com/gitlab`.
-## Troubleshooting
+## Troubleshoot the Development Panel
+
+If you use Jira on your own server, go to the [Atlassian documentation](https://confluence.atlassian.com/jirakb/troubleshoot-the-development-panel-in-jira-server-574685212.html)
+for general troubleshooting information.
### Cookies for Oracle's Access Manager
diff --git a/doc/integration/jira/dvcs.md b/doc/integration/jira/dvcs.md
index 664a0361da4..2b7cc5ff0a6 100644
--- a/doc/integration/jira/dvcs.md
+++ b/doc/integration/jira/dvcs.md
@@ -19,7 +19,7 @@ are accessible.
- **Jira Server**: Your network must allow access to your instance.
- **Jira Cloud**: Your instance must be accessible through the internet.
-## Smart commits
+## Smart Commits
When connecting GitLab with Jira with DVCS, you can process your Jira issues using
special commands, called
@@ -48,17 +48,24 @@ Smart Commits should follow the pattern of:
Some examples:
-- Adding a comment to a Jira issue: `KEY-123 fixes a bug #comment Bug is fixed.`
-- Recording time tracking: `KEY-123 #time 2w 4d 10h 52m Tracking work time.`
-- Closing an issue: `KEY-123 #close Closing issue`
+- Add a comment to a Jira issue: `KEY-123 fixes a bug #comment Bug is fixed.`
+- Record time tracking: `KEY-123 #time 2w 4d 10h 52m Tracking work time.`
+- Close an issue: `KEY-123 #close Closing issue`
A Smart Commit message must not span more than one line (no carriage returns) but
-you can still perform multiple actions in a single commit:
+you can still perform multiple actions in a single commit. For example:
-- Time tracking, commenting, and transitioning to **Closed**:
- `KEY-123 #time 2d 5h #comment Task completed ahead of schedule #close`.
-- Commenting, transitioning to **In-progress**, and time tracking:
- `KEY-123 #comment started working on the issue #in-progress #time 12d 5h`.
+- Add time tracking, add a comment, and transition to **Closed**:
+
+ ```plaintext
+ KEY-123 #time 2d 5h #comment Task completed ahead of schedule #close
+ ```
+
+- Add a comment, transition to **In-progress**, and add time tracking:
+
+ ```plaintext
+ KEY-123 #comment started working on the issue #in-progress #time 12d 5h
+ ```
## Configure a GitLab application for DVCS
@@ -69,9 +76,9 @@ you can set up this integration with your own account instead.
1. In GitLab, [create a user](../../user/profile/account/create_accounts.md) for Jira to
use to connect to GitLab. This user must be added to each project you want Jira to have access to,
- or have an [Administrator](../../user/permissions.md) role to access all projects.
+ or be an administrator to access all projects.
1. Sign in as the `jira` user.
-1. In the top right corner, click the account's avatar, and select **Edit profile**.
+1. On the top bar, in the top right corner, select the user's avatar, and select **Edit profile**.
1. On the left sidebar, select **Applications**.
1. In the **Name** field, enter a descriptive name for the integration, such as `Jira`.
1. In the **Redirect URI** field, enter the URI appropriate for your version of GitLab,
@@ -86,9 +93,10 @@ you can set up this integration with your own account instead.
`https://<gitlab.example.com>/-/jira/login/oauth/callback`.
1. For **Scopes**, select `api` and clear any other checkboxes.
+ - The DVCS connector requires a _write-enabled_ `api` scope to automatically create and manage required webhooks.
1. Select **Submit**.
-1. GitLab displays the generated **Application ID**
- and **Secret** values. Copy these values, as you need them to configure Jira.
+1. Copy the **Application ID** and **Secret** values.
+ You need them to configure Jira.
## Configure Jira for DVCS
@@ -96,19 +104,21 @@ Configure this connection when you want to import all GitLab commits and branche
for the groups you specify, into Jira. This import takes a few minutes and, after
it completes, refreshes every 60 minutes:
-1. Ensure you have completed the [GitLab configuration](#configure-a-gitlab-application-for-dvcs).
+1. Complete the [GitLab configuration](#configure-a-gitlab-application-for-dvcs).
1. Go to your DVCS accounts:
- - *For Jira Server,* go to **Settings (gear) > Applications > DVCS accounts**.
- - *For Jira Cloud,* go to **Settings (gear) > Products > DVCS accounts**.
+ - *For Jira Server,* select **Settings (gear) > Applications > DVCS accounts**.
+ - *For Jira Cloud,* select **Settings (gear) > Products > DVCS accounts**.
1. To create a new integration, select the appropriate value for **Host**:
- *For Jira versions 8.14 and later:* Select **GitLab** or
**GitLab Self-Managed**.
- - *For Jira versions 8.13 and earlier:* Select **GitHub Enterprise**.
+ - *For Jira Cloud or Jira versions 8.13 and earlier:* Select **GitHub Enterprise**.
1. For **Team or User Account**, enter either:
- *For Jira versions 8.14 and later:*
- - The relative path of a top-level GitLab group that [the GitLab user](#configure-a-gitlab-application-for-dvcs) has access to.
- - *For Jira versions 8.13 and earlier:*
- - The relative path of a top-level GitLab group that [the GitLab user](#configure-a-gitlab-application-for-dvcs) has access to.
+ - The relative path of a top-level GitLab group that
+ [the GitLab user](#configure-a-gitlab-application-for-dvcs) has access to.
+ - *For Jira Cloud or Jira versions 8.13 and earlier:*
+ - The relative path of a top-level GitLab group that
+ [the GitLab user](#configure-a-gitlab-application-for-dvcs) has access to.
- The relative path of your personal namespace.
1. In the **Host URL** field, enter the URI appropriate for your version of GitLab,
@@ -119,13 +129,13 @@ it completes, refreshes every 60 minutes:
1. For **Client ID**, use the **Application ID** value from the previous section.
1. For **Client Secret**, use the **Secret** value from the previous section.
-1. Ensure that the rest of the checkboxes are checked.
-1. Select **Add** and then **Continue** to create the DVCS account.
-1. Jira redirects to GitLab where you have to confirm the authorization,
- and then GitLab redirects back to Jira where you should see the synced
- projects show up inside the new account.
+1. Ensure that the rest of the checkboxes are selected.
+1. To create the DVCS account, select **Add** and then **Continue**.
+1. Jira redirects to GitLab where you have to confirm the authorization.
+ GitLab then redirects back to Jira where the synced
+ projects should display in the new account.
-To connect additional GitLab projects from other GitLab top-level groups, or
+To connect additional GitLab projects from other GitLab top-level groups or
personal namespaces, repeat the previous steps with additional Jira DVCS accounts.
After you configure the integration, read more about [how to test and use it](development_panel.md).
@@ -171,9 +181,8 @@ Error obtaining access token. Cannot access https://gitlab.example.com from Jira
as GitLab is the TLS client.
- The Jira Development panel integration requires Jira to connect to GitLab, which
causes Jira to be the TLS client. If your GitLab server's certificate is not
- issued by a public certificate authority, the Java Truststore on Jira's server
- must have the appropriate certificate (such as your organization's
- root certificate) added to it .
+ issued by a public certificate authority, add the appropriate certificate
+ (such as your organization's root certificate) to the Java Truststore on Jira's server.
Refer to Atlassian's documentation and Atlassian Support for assistance setting
up Jira correctly:
@@ -186,8 +195,8 @@ up Jira correctly:
- If the integration stops working after upgrading Jira's Java runtime, the
`cacerts` Truststore may have been replaced during the upgrade.
-- Troubleshooting connectivity [up to and including TLS handshaking](https://confluence.atlassian.com/kb/unable-to-connect-to-ssl-services-due-to-pkix-path-building-failed-error-779355358.html),
- using the a java class called `SSLPoke`.
+- Troubleshoot connectivity [up to and including TLS handshaking](https://confluence.atlassian.com/kb/unable-to-connect-to-ssl-services-due-to-pkix-path-building-failed-error-779355358.html),
+ using the `SSLPoke` Java class.
- Download the class from Atlassian's knowledge base to a directory on Jira's server, such as `/tmp`.
- Use the same Java runtime as Jira.
- Pass all networking-related parameters that Jira is called with, such as proxy
@@ -202,7 +211,7 @@ The message `Successfully connected` indicates a successful TLS handshake.
If there are problems, the Java TLS library generates errors that you can
look up for more detail.
-### Scope error when connecting Jira via DVCS
+### Scope error when connecting to Jira using DVCS
```plaintext
The requested scope is invalid, unknown, or malformed.
@@ -223,12 +232,12 @@ After you complete the **Add New Account** form in Jira and authorize access, yo
encounter these issues:
- An `Error! Failed adding the account: [Error retrieving list of repositories]` error.
-- An `Account is already integrated with JIRA` error when you click **Try Again**.
+- An `Account is already integrated with JIRA` error when you select **Try Again**.
- An account is visible in the DVCS accounts view, but no repositories are listed.
To resolve this issue:
-- If you're using GitLab Free, be sure you're using GitLab 13.4 or later.
+- If you're using GitLab Free, ensure you're using GitLab 13.4 or later.
- If you're using GitLab versions 11.10-12.7, upgrade to GitLab 12.8.10 or later
to resolve [an identified issue](https://gitlab.com/gitlab-org/gitlab/-/issues/37012).
@@ -242,17 +251,17 @@ This issue occurs when you use the Jira DVCS connector and your integration is c
For more information and possible fixes, see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/340160).
-### Fix synchronization issues
+### Synchronization issues
If Jira displays incorrect information, such as deleted branches, you may have to
-resynchronize the information. To do so:
-
-1. In Jira, go to **Jira Administration > Applications > DVCS accounts**.
-1. At the account (group or subgroup) level, Jira displays an option to
- **Refresh repositories** in the **{ellipsis_h}** (ellipsis) menu.
-1. For each project, there's a sync button displayed next to the **last activity** date.
- - To perform a *soft resync*, click the button.
- - To complete a *full sync*, shift-click the button.
+resynchronize the information:
+
+1. In Jira, select **Jira Administration > Applications > DVCS accounts**.
+1. For the account (group or subgroup), select
+ **Refresh repositories** from the **{ellipsis_h}** (ellipsis) menu.
+1. For each project, next to the **Last activity** date:
+ - To perform a *soft resync*, select the sync icon.
+ - To complete a *full sync*, press `Shift` and select the sync icon.
For more information, read
[Atlassian's documentation](https://support.atlassian.com/jira-cloud-administration/docs/synchronize-jira-cloud-to-bitbucket/).
diff --git a/doc/integration/jira/index.md b/doc/integration/jira/index.md
index f5f7e8c33fc..3052d85b2cb 100644
--- a/doc/integration/jira/index.md
+++ b/doc/integration/jira/index.md
@@ -10,7 +10,7 @@ If your organization uses [Jira](https://www.atlassian.com/software/jira) issues
you can [migrate your issues from Jira](../../user/project/import/jira.md) and work
exclusively in GitLab. However, if you'd like to continue to use Jira, you can
integrate it with GitLab. GitLab offers two types of Jira integrations, and you
-can use one or both depending on the capabilities you need. It is recommended that you enable both.
+can use one or both depending on the capabilities you need. We recommend you enable both.
## Compare integrations
@@ -41,7 +41,7 @@ or the Jira DVCS (distributed version control system) connector,
### Direct feature comparison
-| Capability | Jira integration | Jira Development panel integration |
+| Capability | Jira integration | Jira development panel integration |
|-|-|-|
| Mention a Jira issue ID in a GitLab commit or merge request, and a link to the Jira issue is created. | Yes. | No. |
| Mention a Jira issue ID in GitLab and the Jira issue shows the GitLab issue or merge request. | Yes. A Jira comment with the GitLab issue or MR title links to GitLab. The first mention is also added to the Jira issue under **Web links**. | Yes, in the issue's [development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/). |
@@ -55,15 +55,15 @@ or the Jira DVCS (distributed version control system) connector,
## Authentication in Jira
-The process for configuring Jira depends on whether you host Jira on your own server or on
+The authentication method in Jira depends on whether you host Jira on your own server or on
[Atlassian cloud](https://www.atlassian.com/cloud):
- **Jira Server** supports basic authentication. When connecting, a **username and password** are
- required. Connecting to Jira Server via CAS is not possible. For more information, read
+ required. Connecting to Jira Server using the Central Authentication Service (CAS) is not possible. For more information, read
how to [set up a user in Jira Server](jira_server_configuration.md).
- **Jira on Atlassian cloud** supports authentication through an API token. When connecting to Jira on
Atlassian cloud, an email and API token are required. For more information, read
- [set up a user in Jira on Atlassian cloud](jira_cloud_configuration.md).
+ [create an API token for Jira in Atlassian cloud](jira_cloud_configuration.md).
## Privacy considerations
@@ -72,11 +72,16 @@ actions in GitLab issues and merge requests linked to a Jira issue leak informat
about the private project to non-administrator Jira users. If your installation uses Jira Cloud,
you can use the [GitLab.com for Jira Cloud app](connect-app.md) to avoid this risk.
+## Third-party Jira integrations
+
+Developers have built several third-party Jira integrations for GitLab that are
+listed on the [Atlassian Marketplace](https://marketplace.atlassian.com/search?product=jira&query=gitlab).
+
## Troubleshooting
If these features do not work as expected, it is likely due to a problem with the way the integration settings were configured.
-### GitLab is unable to comment on a Jira issue
+### GitLab cannot comment on a Jira issue
If GitLab cannot comment on Jira issues, make sure the Jira user you
set up for the integration has permission to:
@@ -86,14 +91,16 @@ set up for the integration has permission to:
Jira issue references and update comments do not work if the GitLab issue tracker is disabled.
-### GitLab is unable to close a Jira issue
+### GitLab cannot close a Jira issue
+
+If GitLab cannot close a Jira issue:
-Make sure the `Transition ID` you set in the Jira settings matches the one
-your project needs to close an issue.
+- Make sure the `Transition ID` you set in the Jira settings matches the one
+ your project needs to close an issue.
-Make sure that the Jira issue is not already marked as resolved. That is,
-the Jira issue resolution field is not set, and the issue is not struck through in
-Jira lists.
+- Make sure the Jira issue is not already marked as resolved:
+ - Check the Jira issue resolution field is not set.
+ - Check the issue is not struck through in Jira lists.
### CAPTCHA
@@ -104,8 +111,3 @@ authenticate with the Jira site.
To fix this error, sign in to your Jira instance
and complete the CAPTCHA.
-
-## Third-party Jira integrations
-
-Developers have built several third-party Jira integrations for GitLab that are
-listed on the [Atlassian Marketplace](https://marketplace.atlassian.com/search?product=jira&query=gitlab).
diff --git a/doc/integration/jira/jira_cloud_configuration.md b/doc/integration/jira/jira_cloud_configuration.md
index 0cfffdb8ba4..08cd34860ff 100644
--- a/doc/integration/jira/jira_cloud_configuration.md
+++ b/doc/integration/jira/jira_cloud_configuration.md
@@ -4,18 +4,19 @@ group: Integrations
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Create an API token in Jira on Atlassian cloud **(FREE)**
+# Create an API token for Jira in Atlassian cloud **(FREE)**
You need an API token to [integrate with Jira](index.md)
on Atlassian cloud. To create the API token:
-1. Sign in to [`id.atlassian.com`](https://id.atlassian.com/manage-profile/security/api-tokens)
- with your email address. Use an account with *write* access to Jira projects.
-1. Go to **Settings > Atlassian account settings > Security > Create and manage API tokens**.
-1. Select **Create API token** to display a modal window with an API token.
+1. Sign in to [Atlassian](https://id.atlassian.com/manage-profile/security/api-tokens)
+ using an account with *write* access to Jira projects.
+
+ The link opens the API tokens page. Alternatively, to go to this page from your Atlassian
+ profile, select **Account Settings > Security > Create and manage API tokens**.
+1. Select **Create API token**.
1. In the dialog, enter a label for your token and select **Create**.
-1. To copy the API token, select **Copy**, then paste the token somewhere safe. You need this value when you
- [configure GitLab](configure.md).
+1. To copy the API token, select **Copy**, then paste the token somewhere safe.
You need the newly created token, and the email
address you used when you created it, when you
diff --git a/doc/integration/jira/jira_server_configuration.md b/doc/integration/jira/jira_server_configuration.md
index 32a8cd430f9..63625dd5065 100644
--- a/doc/integration/jira/jira_server_configuration.md
+++ b/doc/integration/jira/jira_server_configuration.md
@@ -17,9 +17,9 @@ credentials, you must:
## Create a Jira Server user
-This process creates a user named `gitlab` and adds it to a new group named `gitlab-developers`:
+This process creates a user named `gitlab`:
-1. Sign in to your Jira instance as an administrator.
+1. Sign in to your Jira instance as a Jira administrator.
1. In the upper right corner of the top menu, go to the gear icon and
select **User Management**.
1. Create a new user account (`gitlab`) with write access to
@@ -37,13 +37,15 @@ After you create the user, create a group for it.
## Create a Jira Server group
-After you [create a Jira Server user](#create-a-jira-server-user), you can create a
-group to assign permissions to the user:
+After you [create a Jira Server user](#create-a-jira-server-user), create a
+group to assign permissions to the user.
-1. Sign in to your Jira instance as an administrator.
+This process adds the `gitlab` user you created to a new group named `gitlab-developers`:
+
+1. Sign in to your Jira instance as a Jira administrator.
1. In the upper right corner of the top menu, go to the gear icon and
select **User Management**.
-1. From the sidebar, select **Groups**.
+1. On the sidebar, select **Groups**.
![Jira create new user](img/jira_create_new_group.png)
@@ -52,12 +54,12 @@ group to assign permissions to the user:
1. To add the `gitlab` user to the `gitlab-developers` group, select **Edit members**.
The `gitlab-developers` group should be listed in the leftmost box as a
selected group.
-1. In the **Add members to selected group(s)** area, enter `gitlab`.
+1. In the **Add members to selected group(s)** section, enter `gitlab`.
1. Select **Add selected users**.
-Jira saves your selection, and `gitlab` should appear in the **Group member(s)**
-area.
+ The `gitlab` user appears in the **Group member(s)**
+ section.
-![Jira added user to group](img/jira_added_user_to_group.png)
+ ![Jira added user to group](img/jira_added_user_to_group.png)
Next, create a permission scheme for your group.
@@ -65,16 +67,16 @@ Next, create a permission scheme for your group.
After creating the group in Jira, grant permissions to the group by creating a permission scheme:
-1. Sign in to your Jira instance as an administrator.
+1. Sign in to your Jira instance as a Jira administrator.
1. In the upper right corner of the top menu, go to the gear icon and
select **Issues**.
-1. From the sidebar, select **Permission Schemes**.
+1. On the sidebar, select **Permission Schemes**.
1. Select **Add Permission Scheme**, enter a **Name** and (optionally) a
**Description**, and then select **Add**.
1. In the permissions scheme list, locate your new permissions scheme, and
select **Permissions**.
-1. Next to **Administer Projects**, select **Edit**. In
- the **Group** list, select `gitlab-developers`.
+1. Next to **Administer Projects**, select **Edit**.
+1. From the **Group** dropdown list, select `gitlab-developers`, and then select **Grant**.
![Jira group access](img/jira_group_access.png)
diff --git a/doc/integration/kerberos.md b/doc/integration/kerberos.md
index 2d4abb75875..0f9bf3ba1d1 100644
--- a/doc/integration/kerberos.md
+++ b/doc/integration/kerberos.md
@@ -100,7 +100,7 @@ to authenticate with Kerberos tokens.
#### Enable single sign-on
-See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration)
+See [Configure initial settings](omniauth.md#configure-initial-settings)
for initial settings to enable single sign-on and add Kerberos servers
as an identity provider.
@@ -137,7 +137,7 @@ with your Kerberos credentials.
The first time users sign in to GitLab with their Kerberos accounts,
GitLab creates a matching account.
-Before you continue, review the [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) options in Omnibus and GitLab source. You must also include `kerberos`.
+Before you continue, review the [Configure initial settings](omniauth.md#configure-initial-settings) options in Omnibus and GitLab source. You must also include `kerberos`.
With that information at hand:
diff --git a/doc/integration/mattermost/index.md b/doc/integration/mattermost/index.md
index 39005940dfc..0489ccd431c 100644
--- a/doc/integration/mattermost/index.md
+++ b/doc/integration/mattermost/index.md
@@ -1,7 +1,7 @@
---
stage: Enablement
group: Distribution
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# GitLab Mattermost
@@ -428,7 +428,7 @@ mattermost['env'] = {
Refer to the [Mattermost Configuration Settings
documentation](https://docs.mattermost.com/administration/config-settings.html)
-for details about categories, configuration values, etc.
+for details about categories and configuration values.
There are a few exceptions to this rule:
diff --git a/doc/integration/oauth2_generic.md b/doc/integration/oauth2_generic.md
index bdf6a0e687d..cdc7e6db61c 100644
--- a/doc/integration/oauth2_generic.md
+++ b/doc/integration/oauth2_generic.md
@@ -55,9 +55,42 @@ This strategy is designed to allow configuration of the simple OmniAuth SSO proc
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings
+1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings
+
+1. Add the provider-specific configuration for your provider, for example:
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ { 'name' => 'oauth2_generic',
+ 'label' => '<your_oauth2_label>',
+ 'app_id' => '<your_app_client_id>',
+ 'app_secret' => '<your_app_client_secret>',
+ 'args' => {
+ client_options: {
+ 'site' => '<your_auth_server_url>',
+ 'user_info_url' => '/oauth2/v1/userinfo',
+ 'authorize_url' => '/oauth2/v1/authorize',
+ 'token_url' => '/oauth2/v1/token'
+ },
+ user_response_structure: {
+ root_path: [],
+ id_path: ['sub'],
+ attributes: {
+ email: 'email',
+ name: 'name'
+ }
+ },
+ authorize_params: {
+ scope: 'openid profile email'
+ },
+ strategy_class: "OmniAuth::Strategies::OAuth2Generic"
+ }
+ }
+ }
+ ]
+ ```
-1. Add the provider-specific configuration for your provider, as [described in the gem's README](https://gitlab.com/satorix/omniauth-oauth2-generic#gitlab-config-example)
+ For more information about these settings, see [the gem's README](https://gitlab.com/satorix/omniauth-oauth2-generic#gitlab-config-example).
1. Save the configuration file
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index 6c154ee7f5b..5e96a1e7c65 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -6,25 +6,16 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# OmniAuth **(FREE SELF)**
-GitLab leverages OmniAuth to allow users to sign in using Twitter, GitHub, and
-other popular services. [OmniAuth](https://rubygems.org/gems/omniauth/) is a
-"generalized Rack framework for multiple-provider authentication" built on Ruby.
+Users can sign in to GitLab by using their credentials from Twitter, GitHub, and other popular services.
+[OmniAuth](https://rubygems.org/gems/omniauth/) is the Rack
+framework that GitLab uses to provide this authentication.
-Configuring OmniAuth does not prevent standard GitLab authentication or LDAP
-(if configured) from continuing to work. Users can choose to sign in using any
-of the configured mechanisms.
+If you configure OmniAuth, users can continue to sign in using other
+mechanisms, including standard GitLab authentication or LDAP (if configured).
-- [Initial OmniAuth Configuration](#initial-omniauth-configuration)
-- [Supported Providers](#supported-providers)
-- [Enable OmniAuth for an Existing User](#enable-omniauth-for-an-existing-user)
-- [OmniAuth configuration sample when using Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master#omniauth-google-twitter-github-login)
-- [Enable or disable Sign In with an OmniAuth provider without disabling import sources](#enable-or-disable-sign-in-with-an-omniauth-provider-without-disabling-import-sources)
+## Supported providers
-## Supported Providers
-
-This is a list of the current supported OmniAuth providers. Before proceeding on
-each provider's documentation, make sure to first read this document as it
-contains some settings that are common for all providers.
+GitLab supports the following OmniAuth providers.
| Provider documentation | OmniAuth provider name |
|---------------------------------------------------------------------|----------------------------|
@@ -37,6 +28,7 @@ contains some settings that are common for all providers.
| [Azure v1](azure.md) | `azure_oauth2` |
| [Bitbucket Cloud](bitbucket.md) | `bitbucket` |
| [CAS](cas.md) | `cas3` |
+| [DingTalk](ding_talk.md) | `ding_talk` |
| [Facebook](facebook.md) | `facebook` |
| [Generic OAuth 2.0](oauth2_generic.md) | `oauth2_generic` |
| [GitHub](github.md) | `github` |
@@ -50,127 +42,101 @@ contains some settings that are common for all providers.
| [Shibboleth](saml.md) | `shibboleth` |
| [Twitter](twitter.md) | `twitter` |
-## Initial OmniAuth Configuration
-
-The OmniAuth provider names from the table above are needed to configure a few
-global settings that are in common for all providers.
+## Configure initial settings
NOTE:
-Starting from GitLab 11.4, OmniAuth is enabled by default. If you're using an
+In GitLab 11.4 and later, OmniAuth is enabled by default. If you're using an
earlier version, you must explicitly enable it.
-- `allow_single_sign_on` allows you to specify the providers that automatically
- create a GitLab account. For example, if you wish to enable Azure (v2) and Google,
- in Omnibus, specify a list of provider names:
-
- ```ruby
- gitlab_rails['omniauth_allow_single_sign_on'] = ['azure_activedirectory_v2', 'google_oauth2']
- ```
-
- The value defaults to `false`. If `false` users must be created manually, or
- they can't sign in by using OmniAuth.
-
-- `auto_link_ldap_user` can be used if you have [LDAP / ActiveDirectory](../administration/auth/ldap/index.md)
- integration enabled. It defaults to `false`. When enabled, users automatically
- created through an OmniAuth provider have their LDAP identity created in GitLab as well.
-- `block_auto_created_users` defaults to `true`. If `true`, auto created users will
- be blocked pending approval by an administrator before they are able to sign in.
-
-NOTE:
-If you set `block_auto_created_users` to `false`, make sure to only
-define providers under `allow_single_sign_on` that you are able to control, like
-SAML, Shibboleth, Crowd, or Google. Otherwise, set it to `true`, or any user on
-the Internet can successfully sign in to your GitLab without
-administrative approval.
+Before you configure the OmniAuth provider,
+configure the settings that are common for all providers.
-NOTE:
-`auto_link_ldap_user` requires the `uid` of the user to be the same in both LDAP
-and the OmniAuth provider.
+Setting | Description | Default value
+---------------------------|-------------|--------------
+`allow_single_sign_on` | Enables you to list the providers that automatically create a GitLab account. The provider names are available in the **OmniAuth provider name** column in the [supported providers table](#supported-providers). | The default is `false`. If `false`, users must be created manually, or they can't sign in using OmniAuth.
+`auto_link_ldap_user` | If enabled, creates an LDAP identity in GitLab for users that are created through an OmniAuth provider. You can enable this setting if you have the [LDAP (ActiveDirectory)](../administration/auth/ldap/index.md) integration enabled. Requires the `uid` of the user to be the same in both LDAP and the OmniAuth provider. | The default is `false`.
+`block_auto_created_users` | If enabled, blocks users that are automatically created from signing in until they are approved by an administrator. | The default is `true`. If you set the value to `false`, make sure you only define providers for `allow_single_sign_on` that you can control, like SAML, Shibboleth, Crowd, or Google. Otherwise, any user on the internet can sign in to GitLab without an administrator's approval.
To change these settings:
- **For Omnibus package**
- Open the configuration file:
+ 1. Open the configuration file:
- ```shell
- sudo editor /etc/gitlab/gitlab.rb
- ```
+ ```shell
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
- and change:
+ 1. Update the following section:
- ```ruby
- # CAUTION!
- # This allows users to sign in without having a user account first. Define the allowed providers
- # using an array, for example, ["saml", "twitter"], or as true/false to allow all providers or none.
- # User accounts will be created automatically when authentication was successful.
- gitlab_rails['omniauth_allow_single_sign_on'] = ['saml', 'twitter']
- gitlab_rails['omniauth_auto_link_ldap_user'] = true
- gitlab_rails['omniauth_block_auto_created_users'] = true
- ```
+ ```ruby
+ # CAUTION!
+ # This allows users to sign in without having a user account first. Define the allowed providers
+ # using an array, for example, ["saml", "twitter"], or as true/false to allow all providers or none.
+ # User accounts will be created automatically when authentication was successful.
+ gitlab_rails['omniauth_allow_single_sign_on'] = ['saml', 'twitter']
+ gitlab_rails['omniauth_auto_link_ldap_user'] = true
+ gitlab_rails['omniauth_block_auto_created_users'] = true
+ ```
- **For installations from source**
- Open the configuration file:
+ 1. Open the configuration file:
- ```shell
- cd /home/git/gitlab
+ ```shell
+ cd /home/git/gitlab
- sudo -u git -H editor config/gitlab.yml
- ```
+ sudo -u git -H editor config/gitlab.yml
+ ```
- and change the following section:
+ 1. Update the following section:
- ```yaml
- ## OmniAuth settings
- omniauth:
- # Allow sign-in by using Twitter, Google, etc. using OmniAuth providers
- # Versions prior to 11.4 require this to be set to true
- # enabled: true
+ ```yaml
+ ## OmniAuth settings
+ omniauth:
+ # Allow sign-in by using Twitter, Google, etc. using OmniAuth providers
+ # Versions prior to 11.4 require this to be set to true
+ # enabled: true
- # CAUTION!
- # This allows users to sign in without having a user account first. Define the allowed providers
- # using an array, for example, ["saml", "twitter"], or as true/false to allow all providers or none.
- # User accounts will be created automatically when authentication was successful.
- allow_single_sign_on: ["saml", "twitter"]
+ # CAUTION!
+ # This allows users to sign in without having a user account first. Define the allowed providers
+ # using an array, for example, ["saml", "twitter"], or as true/false to allow all providers or none.
+ # User accounts will be created automatically when authentication was successful.
+ allow_single_sign_on: ["saml", "twitter"]
- auto_link_ldap_user: true
+ auto_link_ldap_user: true
- # Locks down those users until they have been cleared by the admin (default: true).
- block_auto_created_users: true
- ```
+ # Locks down those users until they have been cleared by the admin (default: true).
+ block_auto_created_users: true
+ ```
-Now we can choose one or more of the [Supported Providers](#supported-providers)
-listed above to continue the configuration process.
+After configuring these settings, you can configure
+your chosen [provider](#supported-providers).
-## Enable OmniAuth for an Existing User
+## Enable OmniAuth for an existing user
-Existing users can enable OmniAuth for specific providers after the account is
-created. For example, if the user originally signed in with LDAP, an OmniAuth
-provider such as Twitter can be enabled. Follow the steps below to enable an
-OmniAuth provider for an existing user.
+If you're an existing user, after your GitLab account is
+created, you can activate an OmniAuth provider. For example, if you originally signed in with LDAP, you can enable an OmniAuth
+provider like Twitter.
-1. Sign in normally - whether standard sign in, LDAP, or another OmniAuth provider.
-1. In the top-right corner, select your avatar.
+1. Sign in to GitLab with your GitLab credentials, LDAP, or another OmniAuth provider.
+1. On the top bar, in the top right corner, select your avatar.
1. Select **Edit profile**.
1. On the left sidebar, select **Account**.
-1. In the **Connected Accounts** section, select the desired OmniAuth provider, such as Twitter.
-1. The user is redirected to the provider. After the user authorizes GitLab,
- they are redirected back to GitLab.
+1. In the **Connected Accounts** section, select the OmniAuth provider, such as Twitter.
+1. You are redirected to the provider. After you authorize GitLab,
+ you are redirected back to GitLab.
-The chosen OmniAuth provider is now active and can be used to sign in to GitLab from then on.
+You can now use your chosen OmniAuth provider to sign in to GitLab.
-## Automatically Link Existing Users to OmniAuth Users
+## Link existing users to OmniAuth users
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36664) in GitLab 13.4.
You can automatically link OmniAuth users with existing GitLab users if their email addresses match.
-Automatic linking using this method works for all providers
-[except the SAML provider](https://gitlab.com/gitlab-org/gitlab/-/issues/338293). For automatic
-linking using the SAML provider, see [SAML-specific](saml.md#general-setup) instructions.
-As an example, the following configuration is used to enable the auto link
-feature for both an **OpenID Connect provider** and a **Twitter OAuth provider**.
+The following example enables automatic linking
+for the OpenID Connect provider and the Twitter OAuth provider.
- **For Omnibus installations**
@@ -185,18 +151,23 @@ feature for both an **OpenID Connect provider** and a **Twitter OAuth provider**
auto_link_user: ["openid_connect", "twitter"]
```
-## Configure OmniAuth Providers as External
+This method of enabling automatic linking works for all providers
+[except SAML](https://gitlab.com/gitlab-org/gitlab/-/issues/338293).
+To enable automatic linking for SAML, see the [SAML setup instructions](saml.md#general-setup).
-You can define which OmniAuth providers you want to be `external`. Users
-creating accounts, or logging in by using these `external` providers cannot have
-access to internal projects. You must use the full name of the provider,
-like `google_oauth2` for Google. Refer to the examples for the full names of the
-supported providers.
+## Create an external providers list
+
+You can define a list of external OmniAuth providers.
+Users who create accounts or sign in to GitLab through the listed providers do not get access to [internal projects](../public_access/public_access.md#internal-projects-and-groups).
+
+To define the external providers list, use the full name of the provider,
+for example, `google_oauth2` for Google. For provider names, see the
+**OmniAuth provider name** column in the [supported providers table](#supported-providers).
NOTE:
-If you decide to remove an OmniAuth provider from the external providers list,
-you must manually update the users that use this method to sign in if you want
-their accounts to be upgraded to full internal accounts.
+If you remove an OmniAuth provider from the external providers list,
+you must manually update the users that use this sign-in method so their
+accounts are upgraded to full internal accounts.
- **For Omnibus installations**
@@ -211,75 +182,70 @@ their accounts to be upgraded to full internal accounts.
external_providers: ['twitter', 'google_oauth2']
```
-## Using Custom OmniAuth Providers
+## Use a custom OmniAuth provider
NOTE:
-The following information only applies for installations from source.
+The following information only applies to installations from source.
-GitLab uses [OmniAuth](https://github.com/omniauth/omniauth) for authentication and already ships
-with a few providers pre-installed, such as LDAP, GitHub, and Twitter. You may also
-have to integrate with other authentication solutions. For
-these cases, you can use the OmniAuth provider.
+If you have to integrate with an authentication solution other than the [OmniAuth](https://github.com/omniauth/omniauth) providers included with GitLab,
+you can use a custom OmniAuth provider.
-### Steps
+These steps are general. Read the OmniAuth provider's documentation for the exact
+implementation details.
-These steps are fairly general and you must figure out the exact details
-from the OmniAuth provider's documentation.
+1. Stop GitLab:
-- Stop GitLab:
-
- ```shell
- sudo service gitlab stop
- ```
+ ```shell
+ sudo service gitlab stop
+ ```
-- Add the gem to your [`Gemfile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/Gemfile):
+1. Add the gem to your [`Gemfile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/Gemfile):
- ```shell
- gem "omniauth-your-auth-provider"
- ```
+ ```shell
+ gem "omniauth-your-auth-provider"
+ ```
-- Install the new OmniAuth provider gem by running the following command:
+1. Install the new OmniAuth provider gem:
- ```shell
- sudo -u git -H bundle install --without development test mysql --path vendor/bundle --no-deployment
- ```
+ ```shell
+ sudo -u git -H bundle install --without development test mysql --path vendor/bundle --no-deployment
+ ```
- > These are the same commands you used during initial installation in the [Install Gems section](../install/installation.md#install-gems) with `--path vendor/bundle --no-deployment` instead of `--deployment`.
+ These commands are the same as the commands for [installing gems](../install/installation.md#install-gems)
+ during initial installation, with `--path vendor/bundle --no-deployment` instead of `--deployment`.
-- Start GitLab:
+1. Start GitLab:
- ```shell
- sudo service gitlab start
- ```
+ ```shell
+ sudo service gitlab start
+ ```
-### Examples
+### Custom OmniAuth provider examples
-If you have successfully set up a provider that is not shipped with GitLab itself,
-please let us know.
+If you have successfully set up a provider that is not already integrated with GitLab,
+let us know.
-While we can't officially support every possible authentication mechanism out there,
-we'd like to at least help those with specific needs.
+We can't officially support every possible authentication mechanism available,
+but we'd like to at least help those with specific needs.
-## Enable or disable Sign In with an OmniAuth provider without disabling import sources
+## Enable or disable sign-in with an OmniAuth provider without disabling import sources
-Administrators are able to enable or disable **Sign In** by using some OmniAuth providers.
+Administrators can enable or disable sign-in for some OmniAuth providers.
NOTE:
-By default, **Sign In** is enabled by using all the OAuth Providers that have been configured in `config/gitlab.yml`.
+By default, sign-in is enabled for all the OAuth providers configured in `config/gitlab.yml`.
-To enable/disable an OmniAuth provider:
+To enable or disable an OmniAuth provider:
1. On the top bar, select **Menu > Admin**.
-1. On the left sidebar, go to **Settings**.
-1. Scroll to the **Sign-in Restrictions** section, and click **Expand**.
-1. Below **Enabled OAuth Sign-In sources**, select the checkbox for each provider you want to enable or disable.
+1. On the left sidebar, select **Settings**.
+1. Expand **Sign-in restrictions**.
+1. In the **Enabled OAuth authentication sources** section, select or clear the checkbox for each provider you want to enable or disable.
- ![Enabled OAuth Sign-In sources](img/enabled-oauth-sign-in-sources_v13_10.png)
+## Disable OmniAuth
-## Disabling OmniAuth
-
-Starting from version 11.4 of GitLab, OmniAuth is enabled by default. This only
-has an effect if providers are configured and [enabled](#enable-or-disable-sign-in-with-an-omniauth-provider-without-disabling-import-sources).
+In GitLab 11.4 and later, OmniAuth is enabled by default. However, OmniAuth only works
+if providers are configured and [enabled](#enable-or-disable-sign-in-with-an-omniauth-provider-without-disabling-import-sources).
If OmniAuth providers are causing problems even when individually disabled, you
can disable the entire OmniAuth subsystem by modifying the configuration file:
@@ -299,7 +265,8 @@ can disable the entire OmniAuth subsystem by modifying the configuration file:
## Keep OmniAuth user profiles up to date
-You can enable profile syncing from selected OmniAuth providers and for all or for specific user information.
+You can enable profile syncing from selected OmniAuth providers. You can sync
+all or specific user information.
When authenticating using LDAP, the user's name and email are always synced.
@@ -318,15 +285,22 @@ When authenticating using LDAP, the user's name and email are always synced.
sync_profile_attributes: ['email', 'location']
```
-## Bypassing two factor authentication
+## Bypass two-factor authentication
+
+> Introduced in GitLab 12.3.
-In GitLab 12.3 or later, users can sign in with specified providers _without_
-using two factor authentication.
+With certain OmniAuth providers, users can sign in without
+using two-factor authentication.
-Define the allowed providers using an array (for example, `["twitter", 'google_oauth2']`),
-or as `true` or `false` to allow all providers (or none). This option should be
-configured only for providers which already have two factor authentication
-(default: false). This configuration doesn't apply to SAML.
+To bypass two-factor authentication, you can either:
+
+- Define the allowed providers using an array (for example, `['twitter', 'google_oauth2']`).
+- Specify `true` to allow all providers, or `false` to allow none.
+
+This option should be configured only for providers that already have
+two-factor authentication. The default is `false`.
+
+This configuration doesn't apply to SAML.
- **For Omnibus package**
@@ -341,14 +315,14 @@ configured only for providers which already have two factor authentication
allow_bypass_two_factor: ['twitter', 'google_oauth2']
```
-## Automatically sign in with provider
+## Sign in with a provider automatically
You can add the `auto_sign_in_with_provider` setting to your GitLab
configuration to redirect login requests to your OmniAuth provider for
-authentication. This removes the need to click a button before actually signing in.
+authentication. This removes the need to select the provider before signing in.
-For example, when using the [Azure v2 integration](azure.md#microsoft-azure-oauth-20-omniauth-provider-v2), set the following to enable auto
-sign-in:
+For example, to enable automatic sign-in for the
+[Azure v2 integration](azure.md#microsoft-azure-oauth-20-omniauth-provider-v2):
- **For Omnibus package**
@@ -364,10 +338,10 @@ sign-in:
```
Keep in mind that every sign-in attempt is redirected to the OmniAuth
-provider; you can't sign in using local credentials. Ensure at least
-one of the OmniAuth users has an administrator role.
+provider, so you can't sign in using local credentials. Ensure at least
+one of the OmniAuth users is an administrator.
-You may also bypass the auto sign in feature by browsing to
+You can also bypass automatic sign-in by browsing to
`https://gitlab.example.com/users/sign_in?auto_sign_in=false`.
## Passwords for users created via OmniAuth
@@ -376,11 +350,12 @@ The [Generated passwords for users created through integrated authentication](..
guide provides an overview about how GitLab generates and sets passwords for
users created with OmniAuth.
-## Custom OmniAuth provider icon
+## Use a custom OmniAuth provider icon
Most supported providers include a built-in icon for the rendered sign-in button.
-After you ensure your image is optimized for rendering at 64 x 64 pixels,
-you can override this icon in one of two ways:
+
+To use your own icon, ensure your image is optimized for rendering at 64 x 64 pixels,
+then override the icon in one of two ways:
- **Provide a custom image path**:
@@ -391,11 +366,11 @@ you can override this icon in one of two ways:
to your GitLab configuration file. Read [OpenID Connect OmniAuth provider](../administration/auth/oidc.md)
for an example for the OpenID Connect provider.
-- **Directly embed an image in a configuration file**: This example creates a Base64-encoded
+- **Embed an image directly in a configuration file**: This example creates a Base64-encoded
version of your image you can serve through a
[Data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs):
- 1. Encode your image file with GNU `base64` command (such as `base64 -w 0 <logo.png>`)
+ 1. Encode your image file with a GNU `base64` command (such as `base64 -w 0 <logo.png>`)
which returns a single-line `<base64-data>` string.
1. Add the Base64-encoded data to a custom `icon` parameter in your GitLab
configuration file:
diff --git a/doc/integration/salesforce.md b/doc/integration/salesforce.md
index 9555c762761..68daced3521 100644
--- a/doc/integration/salesforce.md
+++ b/doc/integration/salesforce.md
@@ -11,7 +11,7 @@ You can integrate your GitLab instance with [Salesforce](https://www.salesforce.
## Create a Salesforce Connected App
To enable Salesforce OmniAuth provider, you must use Salesforce's credentials for your GitLab instance.
-To get the credentials (a pair of Client ID and Client Secret), you must [create a Connected App](https://help.salesforce.com/articleView?id=connected_app_create.htm&type=5) on Salesforce.
+To get the credentials (a pair of Client ID and Client Secret), you must [create a Connected App](https://help.salesforce.com/s/articleView?id=connected_app_create.htm&type=5) on Salesforce.
1. Sign in to [Salesforce](https://login.salesforce.com/).
@@ -48,7 +48,7 @@ To get the credentials (a pair of Client ID and Client Secret), you must [create
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings.
1. Add the provider configuration:
@@ -79,7 +79,9 @@ To get the credentials (a pair of Client ID and Client Secret), you must [create
![Salesforce App Secret Details](img/salesforce_app_secret_details.png)
1. Save the configuration file.
-1. [Reconfigure GitLab]( ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure ) or [restart GitLab]( ../administration/restart_gitlab.md#installations-from-source ) for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
+1. [Reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or
+ [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes
+ to take effect if you installed GitLab via Omnibus or from source respectively.
On the sign in page, there should now be a Salesforce icon below the regular sign in form.
Click the icon to begin the authentication process. Salesforce asks the user to sign in and authorize the GitLab application.
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index 876eb7ba80b..47a35cf21a8 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -53,7 +53,7 @@ in your SAML IdP:
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings.
1. To allow your users to use SAML to sign up without having to manually create
an account first, add the following values to your configuration:
@@ -269,7 +269,7 @@ Example:
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
} }
```
@@ -311,7 +311,7 @@ The requirements are the same as the previous settings:
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
} }
```
@@ -335,7 +335,7 @@ The requirements are the same as the previous settings:
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
} }
```
diff --git a/doc/integration/security_partners/index.md b/doc/integration/security_partners/index.md
index b8c7a0163f5..2c7641124a0 100644
--- a/doc/integration/security_partners/index.md
+++ b/doc/integration/security_partners/index.md
@@ -18,7 +18,7 @@ each security partner:
- [Checkmarx](https://checkmarx.atlassian.net/wiki/spaces/SD/pages/1929937052/GitLab+Integration)
- [Deepfactor](https://docs.deepfactor.io/hc/en-us/articles/1500008981941)
- [GrammaTech](https://www.grammatech.com/codesonar-gitlab-integration)
-- [Indeni](https://indeni.com/doc-indeni-cloudrail/integrate-with-ci-cd/gitlab-instructions/)
+- [Indeni](https://cloudrail.app/doc/integrate-with-ci-cd/gitlab-instructions/)
- [JScrambler](https://docs.jscrambler.com/code-integrity/documentation/gitlab-ci-integration)
- [Semgrep](https://semgrep.dev/for/gitlab)
- [StackHawk](https://docs.stackhawk.com/continuous-integration/gitlab.html)
diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md
index f8dd552ec6a..50ef04681f0 100644
--- a/doc/integration/twitter.md
+++ b/doc/integration/twitter.md
@@ -53,7 +53,7 @@ Twitter. Twitter generates a client ID and secret key for you to use.
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings.
1. Add the provider configuration:
diff --git a/doc/operations/error_tracking.md b/doc/operations/error_tracking.md
index 88785196f6e..70e3115a98e 100644
--- a/doc/operations/error_tracking.md
+++ b/doc/operations/error_tracking.md
@@ -169,5 +169,6 @@ You can do so by managing client keys with the [error tracking API](../api/error
#### Limitations
-The Integrated Error Tracking feature was built and tested with Sentry SDK for Ruby. Other languages and frameworks
-are not tested and might not work. Check [the compatibility issue](https://gitlab.com/gitlab-org/gitlab/-/issues/340178) for more information.
+The Integrated Error Tracking feature was built and tested with Sentry SDK for Ruby on Rails.
+Support for other languages and frameworks is not guaranteed. For up-to-date information, see the
+[compatibility issue](https://gitlab.com/gitlab-org/gitlab/-/issues/340178).
diff --git a/doc/operations/feature_flags.md b/doc/operations/feature_flags.md
index 2af4ee47292..2ef193b0f5d 100644
--- a/doc/operations/feature_flags.md
+++ b/doc/operations/feature_flags.md
@@ -38,11 +38,12 @@ with GitLab, so it's up to developers to use a compatible client library and
To create and enable a feature flag:
-1. Navigate to your project's **Deployments > Feature Flags**.
-1. Click the **New feature flag** button.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Deployments > Feature Flags**.
+1. Select **New feature flag**.
1. Enter a name that starts with a letter and contains only lowercase letters, digits, underscores (`_`),
or dashes (`-`), and does not end with a dash (`-`) or underscore (`_`).
-1. Enter a description (optional, 255 characters max).
+1. Optional. Enter a description (255 characters maximum).
1. Enter details about how the flag should be applied:
- In GitLab 13.0 and earlier, add **Environment specs**. For each environment,
include the **Status** (default enabled) and [**Rollout strategy**](#rollout-strategy-legacy)
@@ -50,9 +51,9 @@ To create and enable a feature flag:
- In GitLab 13.1 and later, add Feature Flag [**Strategies**](#feature-flag-strategies).
For each strategy, include the **Type** (defaults to [**All users**](#all-users))
and **Environments** (defaults to all environments).
-1. Click **Create feature flag**.
+1. Select **Create feature flag**.
-You can change these settings by clicking the **{pencil}** (edit) button
+To change these settings, select **Edit** (**{pencil}**).
next to any feature flag in the list.
## Maximum number of feature flags
@@ -91,7 +92,7 @@ and the supported strategies are:
Strategies can be added to feature flags when [creating a feature flag](#create-a-feature-flag),
or by editing an existing feature flag after creation by navigating to **Deployments > Feature Flags**
-and clicking **{pencil}** (edit).
+and selecting **Edit** (**{pencil}**).
### All users
@@ -204,14 +205,15 @@ For example:
To create a user list:
-1. In your project, navigate to **Deployments > Feature Flags**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Deployments > Feature Flags**.
1. Select **View user lists**
1. Select **New user list**.
1. Enter a name for the list.
1. Select **Create**.
-You can view a list's User IDs by clicking the **{pencil}** (edit) button next to it.
-When viewing a list, you can rename it by clicking the **Edit** button.
+You can view a list's User IDs by selecting **Edit** (**{pencil}**) next to it.
+When viewing a list, you can rename it by selecting **Edit** (**{pencil}**).
#### Add users to a user list
@@ -219,12 +221,13 @@ When viewing a list, you can rename it by clicking the **Edit** button.
To add users to a user list:
-1. In your project, navigate to **Deployments > Feature Flags**.
-1. Click on the **{pencil}** (edit) button next to the list you want to add users to.
-1. Click on **Add Users**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Deployments > Feature Flags**.
+1. Select **Edit** (**{pencil}**) next to the list you want to add users to.
+1. Select **Add Users**.
1. Enter the user IDs as a comma-separated list of values. For example,
`user@example.com, user2@example.com`, or `username1,username2,username3`, and so on.
-1. Click on **Add**.
+1. Select **Add**.
#### Remove users from a user list
@@ -232,9 +235,10 @@ To add users to a user list:
To remove users from a user list:
-1. In your project, navigate to **Deployments > Feature Flags**.
-1. Click on the **{pencil}** (edit) button next to the list you want to change.
-1. Click on the **{remove}** (remove) button next to the ID you want to remove.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Deployments > Feature Flags**.
+1. Select **Edit** (**{pencil}**) next to the list you want to change.
+1. Select **Remove** (**{remove}**) next to the ID you want to remove.
## Rollout strategy (legacy)
@@ -270,21 +274,23 @@ See [this video tutorial](https://www.youtube.com/watch?v=CAJY2IGep7Y) for help
In [GitLab 13.0 and earlier](https://gitlab.com/gitlab-org/gitlab/-/issues/8621),
to disable a feature flag for a specific environment:
-1. Navigate to your project's **Deployments > Feature Flags**.
-1. For the feature flag you want to disable, click the Pencil icon.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Deployments > Feature Flags**.
+1. For the feature flag you want to disable, select **Edit** (**{pencil}**).
1. To disable the flag:
- In GitLab 13.0 and earlier: Slide the Status toggle for the environment. Or, to delete the
- environment spec, on the right, click the **Remove (X)** icon.
+ environment spec, on the right, select **Remove (X)**.
- In GitLab 13.1 and later: For each strategy it applies to, under **Environments**, delete the environment.
-1. Click **Save changes**.
+1. Select **Save changes**.
## Disable a feature flag for all environments
To disable a feature flag for all environments:
-1. Navigate to your project's **Deployments > Feature Flags**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Deployments > Feature Flags**.
1. For the feature flag you want to disable, slide the Status toggle to **Disabled**.
The feature flag is displayed on the **Disabled** tab.
@@ -298,8 +304,9 @@ Then prepare your application with a client library.
To get the access credentials that your application needs to communicate with GitLab:
-1. Navigate to your project's **Deployments > Feature Flags**.
-1. Click the **Configure** button to view the following:
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Deployments > Feature Flags**.
+1. Select **Configure** to view the following:
- **API URL**: URL where the client (application) connects to get a list of feature flags.
- **Instance ID**: Unique token that authorizes the retrieval of the feature flags.
- **Application name**: The name of the *environment* the application runs in
@@ -403,6 +410,31 @@ else
end
```
+### Unleash Proxy example
+
+As of [Unleash Proxy](https://docs.getunleash.io/sdks/unleash-proxy) version
+0.2, the proxy is compatible with feature flags. To run a Docker container to
+connect to your project's feature flags, run the following command:
+
+```shell
+docker run \
+ -e UNLEASH_PROXY_SECRETS=<secret> \
+ -e UNLEASH_URL=<project feature flags URL> \
+ -e UNLEASH_INSTANCE_ID=<project feature flags instance ID> \
+ -e UNLEASH_APP_NAME=<project environment> \
+ -e UNLEASH_API_TOKEN=<tokenNotUsed> \
+ -p 3000:3000 \
+ unleashorg/unleash-proxy
+```
+
+| Variable | Value |
+| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
+| `UNLEASH_PROXY_SECRETS` | Shared secret used to configure an [Unleash Proxy client](https://docs.getunleash.io/sdks/unleash-proxy#how-to-connect-to-the-proxy). |
+| `UNLEASH_URL` | Your project's API URL. For more details, read [Get access credentials](#get-access-credentials). |
+| `UNLEASH_INSTANCE_ID` | Your project's Instance ID. For more details, read [Get access credentials](#get-access-credentials). |
+| `UNLEASH_APP_NAME` | The name of the environment the application runs in. For more details, read [Get access credentials](#get-access-credentials). |
+| `UNLEASH_API_TOKEN` | Required to start the Unleash Proxy, but not used to connect to GitLab. Can be set to any value. |
+
## Feature Flag Related Issues **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36617) in GitLab 13.2.
diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md
index 2d9ef21f1ce..64dea795d3c 100644
--- a/doc/operations/incident_management/incidents.md
+++ b/doc/operations/incident_management/incidents.md
@@ -19,20 +19,21 @@ You can create an incident manually or automatically.
### Create incidents manually
-If you have at least Guest [permissions](../../user/permissions.md), to create an
-Incident, you have two options to do this manually.
+> - [Moved](https://gitlab.com/gitlab-org/monitor/monitor/-/issues/24) to GitLab Free in 13.3.
+> - [Permission changed](https://gitlab.com/gitlab-org/gitlab/-/issues/336624) from Guest to Reporter in GitLab 14.5.
-**From the Incidents List:**
+If you have at least Reporter [permissions](../../user/permissions.md),
+you can create an incident manually from the Incidents List or the Issues List.
-> [Moved](https://gitlab.com/gitlab-org/monitor/monitor/-/issues/24) to GitLab Free in 13.3.
+To create an incident from the Incidents List:
-- Navigate to **Monitor > Incidents** and click **Create Incident**.
-- Create a new issue using the `incident` template available when creating it.
-- Create a new issue and assign the `incident` label to it.
+1. Navigate to **Monitor > Incidents** and click **Create Incident**.
+1. Create a new issue using the `incident` template available when creating it.
+1. Create a new issue and assign the `incident` label to it.
![Incident List Create](img/incident_list_create_v13_3.png)
-**From the Issues List:**
+To create an incident from the Issues List:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230857) in GitLab 13.4.
diff --git a/doc/operations/incident_management/integrations.md b/doc/operations/incident_management/integrations.md
index 1426148d163..92f5a50b1c3 100644
--- a/doc/operations/incident_management/integrations.md
+++ b/doc/operations/incident_management/integrations.md
@@ -196,6 +196,27 @@ WARNING:
Using your authorization key in the URL is insecure, as it's visible in server logs. We recommend
using one of the above header options if your tooling supports it.
+## Response body
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342730) in GitLab 14.5.
+
+The JSON response body contains a list of any alerts created within the request:
+
+```json
+[
+ {
+ "iid": 1,
+ "title": "Incident title"
+ },
+ {
+ "iid": 2,
+ "title": "Second Incident title"
+ }
+]
+```
+
+Successful responses return a `200` response code.
+
## Triggering test alerts
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab in 13.2.
diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md
index 3d0e4fdbe49..37aeb335825 100644
--- a/doc/push_rules/push_rules.md
+++ b/doc/push_rules/push_rules.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# Push Rules **(PREMIUM)**
+# Push rules **(PREMIUM)**
Gain additional control over what can and can't be pushed to your repository by using
regular expressions to reject pushes based on commit contents, branch names or file details.
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 89b727cf570..cd541e7827f 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -22,7 +22,7 @@ backups with your object storage provider, if desired.
## Requirements
-To be able to backup and restore, ensure that Rsync is installed on your
+To be able to back up and restore, ensure that Rsync is installed on your
system. If you installed GitLab:
- _Using the Omnibus package_, you're all set.
@@ -61,7 +61,7 @@ including:
- Container Registry images
- GitLab Pages content
- Snippets
-- [Group wikis](../user/project/wiki/index.md#group-wikis)
+- [Group wikis](../user/project/wiki/group.md)
Backups do not include:
@@ -74,7 +74,7 @@ GitLab does not back up any configuration files, SSL certificates, or system
files. You are highly advised to read about [storing configuration files](#storing-configuration-files).
WARNING:
-The backup command requires [additional parameters](#backup-and-restore-for-installations-using-pgbouncer) when
+The backup command requires [additional parameters](#back-up-and-restore-for-installations-using-pgbouncer) when
your installation is using PgBouncer, for either performance reasons or when using it with a Patroni cluster.
Depending on your version of GitLab, use the following command if you installed
@@ -168,7 +168,7 @@ as its key defeats the purpose of using encryption in the first place.
WARNING:
The secrets file is essential to preserve your database encryption key.
-At the very **minimum**, you must backup:
+At the very **minimum**, you must back up:
For Omnibus:
@@ -187,7 +187,7 @@ the GitLab container according to the documentation, it should be in the
For [GitLab Helm chart installations](https://gitlab.com/gitlab-org/charts/gitlab)
on a Kubernetes cluster, you must follow the
-[Backup the secrets](https://docs.gitlab.com/charts/backup-restore/backup.html#backup-the-secrets)
+[Back up the secrets](https://docs.gitlab.com/charts/backup-restore/backup.html#backup-the-secrets)
instructions.
You may also want to back up any TLS keys and certificates, and your
@@ -409,6 +409,8 @@ For Omnibus GitLab packages:
##### S3 Encrypted Buckets
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64765) in GitLab 14.3.
+
AWS supports these [modes for server side encryption](https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html):
- Amazon S3-Managed Keys (SSE-S3)
@@ -787,7 +789,7 @@ For installations from source:
#### Configuring cron to make daily backups
WARNING:
-The following cron jobs do not [backup your GitLab configuration files](#storing-configuration-files)
+The following cron jobs do not [back up your GitLab configuration files](#storing-configuration-files)
or [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
You can schedule a cron job that backs up your repositories and GitLab metadata.
@@ -974,7 +976,7 @@ message. Install the [correct GitLab version](https://packages.gitlab.com/gitlab
and then try again.
WARNING:
-The restore command requires [additional parameters](#backup-and-restore-for-installations-using-pgbouncer) when
+The restore command requires [additional parameters](#back-up-and-restore-for-installations-using-pgbouncer) when
your installation is using PgBouncer, for either performance reasons or when using it with a Patroni cluster.
Next, restore `/etc/gitlab/gitlab-secrets.json` if necessary,
@@ -1020,7 +1022,7 @@ docker exec -it <name of container> gitlab-ctl stop sidekiq
# Verify that the processes are all down before continuing
docker exec -it <name of container> gitlab-ctl status
-# Run the restore
+# Run the restore. NOTE: "_gitlab_backup.tar" is omitted from the name
docker exec -it <name of container> gitlab-backup restore BACKUP=11493107454_2018_04_25_10.6.4-ce
# Restart the GitLab container
@@ -1215,9 +1217,9 @@ There are a few possible downsides to this:
There is an **experimental** script that attempts to automate this process in
[the Geo team Runbooks project](https://gitlab.com/gitlab-org/geo-team/runbooks/-/tree/main/experimental-online-backup-through-rsync).
-## Backup and restore for installations using PgBouncer
+## Back up and restore for installations using PgBouncer
-Do NOT backup or restore GitLab through a PgBouncer connection. These
+Do NOT back up or restore GitLab through a PgBouncer connection. These
tasks must [bypass PgBouncer and connect directly to the PostgreSQL primary database node](#bypassing-pgbouncer),
or they cause a GitLab outage.
@@ -1377,18 +1379,30 @@ after which users must reactivate 2FA.
1. Enter the database console:
- For Omnibus GitLab packages:
+ For Omnibus GitLab 14.1 and earlier:
```shell
sudo gitlab-rails dbconsole
```
- For installations from source:
+ For Omnibus GitLab 14.2 and later:
+
+ ```shell
+ sudo gitlab-rails dbconsole --database main
+ ```
+
+ For installations from source, GitLab 14.1 and earlier:
```shell
sudo -u git -H bundle exec rails dbconsole -e production
```
+ For installations from source, GitLab 14.2 and later:
+
+ ```shell
+ sudo -u git -H bundle exec rails dbconsole -e production --database main
+ ```
+
1. Examine the `ci_group_variables` and `ci_variables` tables:
```sql
@@ -1411,18 +1425,30 @@ You may need to reconfigure or restart GitLab for the changes to take effect.
1. Enter the database console:
- For Omnibus GitLab packages:
+ For Omnibus GitLab 14.1 and earlier:
```shell
sudo gitlab-rails dbconsole
```
- For installations from source:
+ For Omnibus GitLab 14.2 and later:
+
+ ```shell
+ sudo gitlab-rails dbconsole --database main
+ ```
+
+ For installations from source, GitLab 14.1 and earlier:
```shell
sudo -u git -H bundle exec rails dbconsole -e production
```
+ For installations from source, GitLab 14.2 and later:
+
+ ```shell
+ sudo -u git -H bundle exec rails dbconsole -e production --database main
+ ```
+
1. Clear all tokens for projects, groups, and the entire instance:
WARNING:
@@ -1448,18 +1474,30 @@ You may need to reconfigure or restart GitLab for the changes to take effect.
1. Enter the database console:
- For Omnibus GitLab packages:
+ For Omnibus GitLab 14.1 and earlier:
```shell
sudo gitlab-rails dbconsole
```
- For installations from source:
+ For Omnibus GitLab 14.2 and later:
+
+ ```shell
+ sudo gitlab-rails dbconsole --database main
+ ```
+
+ For installations from source, GitLab 14.1 and earlier:
```shell
sudo -u git -H bundle exec rails dbconsole -e production
```
+ For installations from source, GitLab 14.2 and later:
+
+ ```shell
+ sudo -u git -H bundle exec rails dbconsole -e production --database main
+ ```
+
1. Clear all the tokens for pending jobs:
```sql
@@ -1480,18 +1518,30 @@ The fix is to truncate the `web_hooks` table:
1. Enter the database console:
- For Omnibus GitLab packages:
+ For Omnibus GitLab 14.1 and earlier:
```shell
sudo gitlab-rails dbconsole
```
- For installations from source:
+ For Omnibus GitLab 14.2 and later:
+
+ ```shell
+ sudo gitlab-rails dbconsole --database main
+ ```
+
+ For installations from source, GitLab 14.1 and earlier:
```shell
sudo -u git -H bundle exec rails dbconsole -e production
```
+ For installations from source, GitLab 14.2 and later:
+
+ ```shell
+ sudo -u git -H bundle exec rails dbconsole -e production --database main
+ ```
+
1. Truncate the table:
```sql
diff --git a/doc/raketasks/import.md b/doc/raketasks/import.md
index 7f817f9c422..45d51fe9dfa 100644
--- a/doc/raketasks/import.md
+++ b/doc/raketasks/import.md
@@ -58,7 +58,7 @@ To import bare repositories into a GitLab instance:
- Omnibus Installation
```shell
- sudo gitlab-rake gitlab:import:repos['/var/opt/gitlab/git-data/repository-import-$(date "+%Y-%m-%d")']
+ sudo gitlab-rake gitlab:import:repos["/var/opt/gitlab/git-data/repository-import-$(date "+%Y-%m-%d")"]
```
- Installation from source. Before running this command you need to change to the directory where
@@ -66,7 +66,7 @@ To import bare repositories into a GitLab instance:
```shell
cd /home/git/gitlab
- sudo -u git -H bundle exec rake gitlab:import:repos['/var/opt/gitlab/git-data/repository-import-$(date "+%Y-%m-%d")'] RAILS_ENV=production
+ sudo -u git -H bundle exec rake gitlab:import:repos["/var/opt/gitlab/git-data/repository-import-$(date "+%Y-%m-%d")"] RAILS_ENV=production
```
## Example output
diff --git a/doc/raketasks/spdx.md b/doc/raketasks/spdx.md
index f330698daba..18f058f695e 100644
--- a/doc/raketasks/spdx.md
+++ b/doc/raketasks/spdx.md
@@ -4,7 +4,7 @@ group: Composition Analysis
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# SPDX license list import **(PREMIUM SELF)**
+# SPDX license list import **(ULTIMATE SELF)**
GitLab provides a Rake task for uploading a fresh copy of the [SPDX license list](https://spdx.org/licenses/)
to a GitLab instance. This list is needed for matching the names of [License Compliance policies](../user/compliance/license_compliance/index.md).
diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md
index b0bebc5a956..a8b55007d2e 100644
--- a/doc/security/rack_attack.md
+++ b/doc/security/rack_attack.md
@@ -1,195 +1,9 @@
---
-stage: Manage
-group: Access
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: reference, howto
+redirect_to: '../user/admin_area/settings/protected_paths.md'
+remove_date: '2022-01-14'
---
-# Rack Attack initializer **(FREE SELF)**
+This document was moved to [another location](../user/admin_area/settings/protected_paths.md).
-[Rack Attack](https://github.com/kickstarter/rack-attack), also known as Rack::Attack, is a Ruby gem
-that is meant to protect GitLab with the ability to customize throttling and
-to block user IP addresses.
-
-You can prevent brute-force passwords attacks, scrapers, or any other offenders
-by throttling requests from IP addresses that are making large volumes of requests.
-If you find throttling is not enough to protect you against abusive clients,
-Rack Attack offers IP whitelisting, blacklisting, Fail2ban style filtering, and
-tracking.
-
-For more information on how to use these options see the [Rack Attack README](https://github.com/kickstarter/rack-attack/blob/master/README.md).
-
-NOTE:
-See
-[User and IP rate limits](../user/admin_area/settings/user_and_ip_rate_limits.md)
-for simpler limits that are configured in the UI.
-
-NOTE:
-Starting with GitLab 11.2, Rack Attack is disabled by default. If your
-instance is not exposed to the public internet, it is recommended that you leave
-Rack Attack disabled.
-
-## Behavior
-
-If set up as described in the [Settings](#settings) section below, two behaviors
-are enabled:
-
-- Protected paths are throttled.
-- Failed authentications for Git and container registry requests trigger a temporary IP ban.
-
-### Protected paths throttle
-
-GitLab responds with HTTP status code `429` to POST requests at protected paths
-that exceed 10 requests per minute per IP address.
-
-By default, protected paths are:
-
-- `/users/password`
-- `/users/sign_in`
-- `/api/#{API::API.version}/session.json`
-- `/api/#{API::API.version}/session`
-- `/users`
-- `/users/confirmation`
-- `/unsubscribes/`
-- `/import/github/personal_access_token`
-- `/admin/session`
-
-See [User and IP rate limits](../user/admin_area/settings/user_and_ip_rate_limits.md#response-headers) for the headers responded to blocked requests.
-
-For example, the following are limited to a maximum 10 requests per minute:
-
-- User sign-in
-- User sign-up (if enabled)
-- User password reset
-
-After 10 requests, the client must wait a minute before it can
-try again.
-
-### Git and container registry failed authentication ban
-
-GitLab responds with HTTP status code `403` for 1 hour, if 30 failed
-authentication requests were received in a 3-minute period from a single IP address.
-
-This applies only to Git requests and container registry (`/jwt/auth`) requests
-(combined).
-
-This limit:
-
-- Is reset by requests that authenticate successfully. For example, 29
- failed authentication requests followed by 1 successful request, followed by 29
- more failed authentication requests would not trigger a ban.
-- Does not apply to JWT requests authenticated by `gitlab-ci-token`.
-
-No response headers are provided.
-
-## Settings
-
-**Omnibus GitLab**
-
-1. Open `/etc/gitlab/gitlab.rb` with your editor
-1. Add the following:
-
- ```ruby
- gitlab_rails['rack_attack_git_basic_auth'] = {
- 'enabled' => true,
- 'ip_whitelist' => ["127.0.0.1"],
- 'maxretry' => 10, # Limit the number of Git HTTP authentication attempts per IP
- 'findtime' => 60, # Reset the auth attempt counter per IP after 60 seconds
- 'bantime' => 3600 # Ban an IP for one hour (3600s) after too many auth attempts
- }
- ```
-
-1. Reconfigure GitLab:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-The following settings can be configured:
-
-- `enabled`: By default this is set to `false`. Set this to `true` to enable Rack Attack.
-- `ip_whitelist`: Whitelist any IPs from being blocked. They must be formatted as strings within a Ruby array.
- CIDR notation is supported in GitLab 12.1 and later.
- For example, `["127.0.0.1", "127.0.0.2", "127.0.0.3", "192.168.0.1/24"]`.
-- `maxretry`: The maximum amount of times a request can be made in the
- specified time.
-- `findtime`: The maximum amount of time that failed requests can count against an IP
- before it's blacklisted (in seconds).
-- `bantime`: The total amount of time that a blacklisted IP is blocked (in
- seconds).
-
-**Installations from source**
-
-These settings can be found in `config/initializers/rack_attack.rb`. If you are
-missing `config/initializers/rack_attack.rb`, the following steps need to be
-taken in order to enable protection for your GitLab instance:
-
-1. In `config/application.rb` find and uncomment the following line:
-
- ```ruby
- config.middleware.use Rack::Attack
- ```
-
-1. Restart GitLab:
-
- ```shell
- sudo service gitlab restart
- ```
-
-If you want more restrictive/relaxed throttle rules, edit
-`config/initializers/rack_attack.rb` and change the `limit` or `period` values.
-For example, you can set more relaxed throttle rules with
-`limit: 3` and `period: 1.seconds`, allowing 3 requests per second.
-You can also add other paths to the protected list by adding to `paths_to_be_protected`
-variable. If you change any of these settings you must restart your
-GitLab instance.
-
-## Remove blocked IPs from Rack Attack via Redis
-
-In case you want to remove a blocked IP, follow these steps:
-
-1. Find the IPs that have been blocked in the production log:
-
- ```shell
- grep "Rack_Attack" /var/log/gitlab/gitlab-rails/auth.log
- ```
-
-1. Since the blacklist is stored in Redis, you need to open up `redis-cli`:
-
- ```shell
- /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.socket
- ```
-
-1. You can remove the block using the following syntax, replacing `<ip>` with
- the actual IP that is blacklisted:
-
- ```plaintext
- del cache:gitlab:rack::attack:allow2ban:ban:<ip>
- ```
-
-1. Confirm that the key with the IP no longer shows up:
-
- ```plaintext
- keys *rack::attack*
- ```
-
-1. Optionally, add the IP to the whitelist to prevent it from being blacklisted
- again (see [settings](#settings)).
-
-## Troubleshooting
-
-### Rack attack is blacklisting the load balancer
-
-Rack Attack may block your load balancer if all traffic appears to come from
-the load balancer. In that case, you must:
-
-1. [Configure `nginx[real_ip_trusted_addresses]`](https://docs.gitlab.com/omnibus/settings/nginx.html#configuring-gitlab-trusted_proxies-and-the-nginx-real_ip-module).
- This keeps users' IPs from being listed as the load balancer IPs.
-1. Whitelist the load balancer's IP address(es) in the Rack Attack [settings](#settings).
-1. Reconfigure GitLab:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-1. [Remove the block via Redis.](#remove-blocked-ips-from-rack-attack-via-redis)
+<!-- This redirect file can be deleted after <2022-01-14>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/security/rate_limits.md b/doc/security/rate_limits.md
index 4585748ffc2..9d49297c9de 100644
--- a/doc/security/rate_limits.md
+++ b/doc/security/rate_limits.md
@@ -14,18 +14,22 @@ For GitLab.com, please see
Rate limiting is a common technique used to improve the security and durability
of a web application.
-For example, a simple script can make thousands of web requests per second.
-Whether malicious, apathetic, or just a bug, your application and infrastructure
-may not be able to cope with the load. For more details, see
+For example, a simple script can make thousands of web requests per second. The requests could be:
+
+- Malicious.
+- Apathetic.
+- Just a bug.
+
+Your application and infrastructure may not be able to cope with the load. For more details, see
[Denial-of-service attack](https://en.wikipedia.org/wiki/Denial-of-service_attack).
Most cases can be mitigated by limiting the rate of requests from a single IP address.
Most [brute-force attacks](https://en.wikipedia.org/wiki/Brute-force_attack) are
similarly mitigated by a rate limit.
-## Admin Area settings
+## Configurable limits
-These are rate limits you can set in the Admin Area of your instance:
+You can set these rate limits in the Admin Area of your instance:
- [Import/Export rate limits](../user/admin_area/settings/import_export_rate_limits.md)
- [Issues rate limits](../user/admin_area/settings/rate_limit_on_issues_creation.md)
@@ -38,14 +42,40 @@ These are rate limits you can set in the Admin Area of your instance:
- [Files API rate limits](../user/admin_area/settings/files_api_rate_limits.md)
- [Deprecated API rate limits](../user/admin_area/settings/deprecated_api_rate_limits.md)
+You can set these rate limits using the Rails console:
+
+- [Webhook rate limit](../administration/instance_limits.md#webhook-rate-limit)
+
+## Failed authentication ban for Git and container registry
+
+GitLab returns HTTP status code `403` for 1 hour, if 30 failed authentication requests were received
+in a 3-minute period from a single IP address. This applies only to combined:
+
+- Git requests.
+- Container registry (`/jwt/auth`) requests.
+
+This limit:
+
+- Is reset by requests that authenticate successfully. For example, 29 failed authentication
+ requests followed by 1 successful request, followed by 29 more failed authentication requests
+ would not trigger a ban.
+- Does not apply to JWT requests authenticated by `gitlab-ci-token`.
+- Is disabled by default.
+
+No response headers are provided.
+
+For configuration information, see
+[Omnibus GitLab configuration options](https://docs.gitlab.com/omnibus/settings/configuration.html#configure-a-failed-authentication-ban).
+
## Non-configurable limits
### Repository archives
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25750) in GitLab 12.9.
-There is a rate limit for [downloading repository archives](../api/repositories.md#get-file-archive),
-which applies to the project and to the user initiating the download either through the UI or the API.
+A rate limit for [downloading repository archives](../api/repositories.md#get-file-archive) is
+available. The limit applies to the project and to the user initiating the download either through
+the UI or the API.
The **rate limit** is 5 requests per minute per user.
@@ -57,8 +87,52 @@ There is a rate limit for [testing webhooks](../user/project/integrations/webhoo
The **rate limit** is 5 requests per minute per user.
-## Rack Attack initializer
+## Troubleshooting
+
+### Rack Attack is denylisting the load balancer
+
+Rack Attack may block your load balancer if all traffic appears to come from
+the load balancer. In that case, you must:
+
+1. [Configure `nginx[real_ip_trusted_addresses]`](https://docs.gitlab.com/omnibus/settings/nginx.html#configuring-gitlab-trusted_proxies-and-the-nginx-real_ip-module).
+ This keeps users' IPs from being listed as the load balancer IPs.
+1. Allowlist the load balancer's IP addresses.
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+### Remove blocked IPs from Rack Attack with Redis
+
+To remove a blocked IP:
+
+1. Find the IPs that have been blocked in the production log:
+
+ ```shell
+ grep "Rack_Attack" /var/log/gitlab/gitlab-rails/auth.log
+ ```
+
+1. Since the denylist is stored in Redis, you must open up `redis-cli`:
+
+ ```shell
+ /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.socket
+ ```
+
+1. You can remove the block using the following syntax, replacing `<ip>` with
+ the actual IP that is denylisted:
+
+ ```plaintext
+ del cache:gitlab:rack::attack:allow2ban:ban:<ip>
+ ```
+
+1. Confirm that the key with the IP no longer shows up:
+
+ ```plaintext
+ keys *rack::attack*
+ ```
+
+ By default, the [`keys` command is disabled](https://docs.gitlab.com/omnibus/settings/redis.html#renamed-commands).
-This method of rate limiting is cumbersome, but has some advantages. It allows
-throttling of specific paths, and is also integrated into Git and container
-registry requests. See [Rack Attack initializer](rack_attack.md).
+1. Optionally, add [the IP to the allowlist](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-rack-attack)
+ to prevent it being denylisted again.
diff --git a/doc/security/token_overview.md b/doc/security/token_overview.md
index 2a971b21840..333548fa1c9 100644
--- a/doc/security/token_overview.md
+++ b/doc/security/token_overview.md
@@ -117,4 +117,9 @@ Instead, API calls can be passed an access token using headers, like [the `Priva
Tokens can also be stored using a [Git credential storage](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage).
+Tokens should not be committed to your source code. Instead, consider an approach such as [using external secrets in CI](../ci/secrets/index.md).
+
When creating a scoped token, consider using the most limited scope possible to reduce the impact of accidentally leaking the token.
+
+When creating a token, consider setting a token that expires when your task is complete. For example, if performing a one-off import, set the
+token to expire after a few hours or a day. This reduces the impact of a token that is accidentally leaked because it is useless when it expires.
diff --git a/doc/subscriptions/bronze_starter.md b/doc/subscriptions/bronze_starter.md
index bb2a2303d29..78a9e324ada 100644
--- a/doc/subscriptions/bronze_starter.md
+++ b/doc/subscriptions/bronze_starter.md
@@ -50,15 +50,15 @@ the tiers are no longer mentioned in GitLab documentation:
- [Group management through LDAP](../administration/auth/ldap/ldap-troubleshooting.md#group-memberships)
- Syncing information through LDAP:
- Groups: [one group](../administration/auth/ldap/ldap-troubleshooting.md#sync-one-group),
- [all groups programmatically](../administration/auth/ldap/index.md#group-sync),
- [group sync schedule](../administration/auth/ldap/index.md#adjust-ldap-group-sync-schedule), and
+ [all groups programmatically](../administration/auth/ldap/ldap_synchronization.md#group-sync),
+ [group sync schedule](../administration/auth/ldap/ldap_synchronization.md#adjust-ldap-group-sync-schedule), and
[all groups manually](../administration/auth/ldap/ldap-troubleshooting.md#sync-all-groups)
- [Configuration settings](../administration/auth/ldap/index.md#ldap-sync-configuration-settings)
- - Users: [all users](../administration/auth/ldap/index.md#user-sync),
- [administrators](../administration/auth/ldap/index.md#administrator-sync),
- [user sync schedule](../administration/auth/ldap/index.md#adjust-ldap-user-sync-schedule)
- - [Adding group links](../administration/auth/ldap/index.md#add-group-links)
- - [Lock memberships to LDAP synchronization](../administration/auth/ldap/index.md#global-group-memberships-lock)
+ - Users: [all users](../administration/auth/ldap/ldap_synchronization.md#user-sync),
+ [administrators](../administration/auth/ldap/ldap_synchronization.md#administrator-sync),
+ [user sync schedule](../administration/auth/ldap/ldap_synchronization.md#adjust-ldap-user-sync-schedule)
+ - [Adding group links](../administration/auth/ldap/ldap_synchronization.md#add-group-links)
+ - [Lock memberships to LDAP synchronization](../administration/auth/ldap/ldap_synchronization.md#global-group-memberships-lock)
- Rake tasks for [LDAP tasks](../administration/raketasks/ldap.md), including
[syncing groups](../administration/raketasks/ldap.md#run-a-group-sync)
- Logging:
@@ -92,11 +92,11 @@ the tiers are no longer mentioned in GitLab documentation:
- [Pull mirroring](../user/project/repository/mirror/pull.md) outside repositories in a GitLab repository
- [Overwrite diverged branches](../user/project/repository/mirror/pull.md#overwrite-diverged-branches)
- [Trigger pipelines for mirror updates](../user/project/repository/mirror/pull.md#trigger-pipelines-for-mirror-updates)
- - [Hard failures](../user/project/repository/mirror/pull.md#hard-failure) when mirroring fails
+ - [Fix hard failures when mirroring](../user/project/repository/mirror/pull.md#fix-hard-failures-when-mirroring)
- [Trigger pull mirroring from the API](../user/project/repository/mirror/pull.md#trigger-an-update-by-using-the-api)
- [Mirror only protected branches](../user/project/repository/mirror/index.md#mirror-only-protected-branches)
- [Bidirectional mirroring](../user/project/repository/mirror/bidirectional.md)
- - [Mirror with Perforce Helix via Git Fusion](../user/project/repository/mirror/bidirectional.md#mirror-with-perforce-helix-via-git-fusion)
+ - [Mirror with Perforce Helix with Git Fusion](../user/project/repository/mirror/bidirectional.md#mirror-with-perforce-helix-with-git-fusion)
- Runners:
- Run pipelines in the parent project [for merge requests from a forked project](../ci/pipelines/merge_request_pipelines.md#run-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project)
- [Shared runners pipeline minutes quota](../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota)
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
index a8e02251b64..a26feb6d97e 100644
--- a/doc/subscriptions/gitlab_com/index.md
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -311,8 +311,8 @@ Your own runners can still be used even if you reach your limits.
If you're using GitLab SaaS, you can purchase additional CI minutes so your
pipelines aren't blocked after you have used all your CI minutes from your
-main quota. You can find pricing for additional CI/CD minutes in the
-[GitLab Customers Portal](https://customers.gitlab.com/plans). Additional minutes:
+main quota. You can find pricing for additional CI/CD minutes on the
+[GitLab Pricing page](https://about.gitlab.com/pricing/). Additional minutes:
- Are only used after the shared quota included in your subscription runs out.
- Roll over month to month.
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index acdbdefc671..aee18e3d763 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -108,7 +108,7 @@ GitLab has several features which can help you manage the number of users:
- Enable the [**Require administrator approval for new sign ups**](../../user/admin_area/settings/sign_up_restrictions.md#require-administrator-approval-for-new-sign-ups)
option.
-- Enable `block_auto_created_users` for new sign-ups via [LDAP](../../administration/auth/ldap/index.md#basic-configuration-settings) or [OmniAuth](../../integration/omniauth.md#initial-omniauth-configuration).
+- Enable `block_auto_created_users` for new sign-ups via [LDAP](../../administration/auth/ldap/index.md#basic-configuration-settings) or [OmniAuth](../../integration/omniauth.md#configure-initial-settings).
- Enable the [User cap](../../user/admin_area/settings/sign_up_restrictions.md#user-cap)
option. **Available in GitLab 13.7 and later**.
- [Disable new sign-ups](../../user/admin_area/settings/sign_up_restrictions.md), and instead manage new
@@ -181,9 +181,9 @@ The daily job provides **only** the following information to the Customers Porta
- Instance ID
- MD5 hash of license
-<details>
-<summary>Click here to view an example of a cloud licensing sync request.</summary>
-<pre><code>
+Example of a cloud licensing sync request:
+
+```json
{
"gitlab_version": "14.1.0-pre",
"timestamp": "2021-06-14T12:00:09Z",
@@ -231,8 +231,7 @@ The daily job provides **only** the following information to the Customers Porta
"instance_id": "9367590b-82ad-48cb-9da7-938134c29088",
"license_md5": "002f02470fe45ef6a333a4282aca6222"
}
-</code></pre>
-</details>
+```
#### Sync subscription details
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index fbeee7b96bc..dcab56a0d0f 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Ecosystem
+group: Integrations
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
type: reference
---
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index c01ed4a49d0..906fea2e6ad 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -93,6 +93,28 @@ Avoid passing secrets as Docker build arguments if possible, as they may be
persisted in your image. See
[this discussion of best practices with secrets](https://github.com/moby/moby/issues/13490) for details.
+## Custom container image
+
+By default, [Auto Deploy](stages.md#auto-deploy) deploys a container image built and pushed to the GitLab registry by [Auto Build](stages.md#auto-build).
+You can override this behavior by defining specific variables:
+
+| Entry | Default | Can be overridden by |
+| ----- | ----- | ----- |
+| Image Path | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` for branch pipelines. `$CI_REGISTRY_IMAGE` for tag pipelines. | `$CI_APPLICATION_REPOSITORY` |
+| Image Tag | `$CI_COMMIT_SHA` for branch pipelines. `$CI_COMMIT_TAG` for tag pipelines. | `$CI_APPLICATION_TAG` |
+
+These variables also affect Auto Build. If you don't want to build and push an image to
+`$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG`, consider
+including only `Jobs/Deploy.gitlab-ci.yml`, or [disabling the `build` jobs](#disable-jobs).
+
+Here is an example setup in your `.gitlab-ci.yml`:
+
+```yaml
+variables:
+ CI_APPLICATION_REPOSITORY: <your-image-repository>
+ CI_APPLICATION_TAG: <the-tag>
+```
+
## Extend Auto DevOps with the API
You can extend and manage your Auto DevOps configuration with GitLab APIs:
@@ -218,7 +240,7 @@ See [Multiple Kubernetes clusters for Auto DevOps](multiple_clusters_auto_devops
For clusters not managed by GitLab, you can customize the namespace in
`.gitlab-ci.yml` by specifying
-[`environment:kubernetes:namespace`](../../ci/environments/index.md#configure-kubernetes-deployments).
+[`environment:kubernetes:namespace`](../../ci/environments/index.md#configure-kubernetes-deployments-deprecated).
For example, the following configuration overrides the namespace used for
`production` deployments:
@@ -392,6 +414,8 @@ applications.
| `CANARY_ENABLED` | From GitLab 11.0, used to define a [deploy policy for canary environments](#deploy-policy-for-canary-environments). |
| `CANARY_PRODUCTION_REPLICAS` | Number of canary replicas to deploy for [Canary Deployments](../../user/project/canary_deployments.md) in the production environment. Takes precedence over `CANARY_REPLICAS`. Defaults to 1. |
| `CANARY_REPLICAS` | Number of canary replicas to deploy for [Canary Deployments](../../user/project/canary_deployments.md). Defaults to 1. |
+| `CI_APPLICATION_REPOSITORY` | The repository of container image being built or deployed, `$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG`. For more details, read [Custom container image](#custom-container-image). |
+| `CI_APPLICATION_TAG` | The tag of the container image being built or deployed, `$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG`. For more details, read [Custom container image](#custom-container-image). |
| `DAST_AUTO_DEPLOY_IMAGE_VERSION` | Customize the image version used for DAST deployments on the default branch. Should usually be the same as `AUTO_DEPLOY_IMAGE_VERSION`. See [list of versions](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/releases). |
| `DOCKERFILE_PATH` | From GitLab 13.2, allows overriding the [default Dockerfile path for the build stage](#custom-dockerfile) |
| `HELM_RELEASE_NAME` | From GitLab 12.1, allows the `helm` release name to be overridden. Can be used to assign unique release names when deploying multiple projects to a single namespace. |
@@ -399,7 +423,10 @@ applications.
| `HELM_UPGRADE_EXTRA_ARGS` | From GitLab 11.11, allows extra options in `helm upgrade` commands when deploying the application. Note that using quotes doesn't prevent word splitting. |
| `INCREMENTAL_ROLLOUT_MODE` | From GitLab 11.4, if present, can be used to enable an [incremental rollout](#incremental-rollout-to-production) of your application for the production environment. Set to `manual` for manual deployment jobs or `timed` for automatic rollout deployments with a 5 minute delay each one. |
| `K8S_SECRET_*` | From GitLab 11.7, any variable prefixed with [`K8S_SECRET_`](#application-secret-variables) is made available by Auto DevOps as environment variables to the deployed application. |
+| `KUBE_CONTEXT` | From GitLab 14.5, can be used to select which context to use from `KUBECONFIG`. When `KUBE_CONTEXT` is blank, the default context in `KUBECONFIG` (if any) will be used. A context must be selected when using the [CI/CD tunnel](../../user/clusters/agent/ci_cd_tunnel.md). |
| `KUBE_INGRESS_BASE_DOMAIN` | From GitLab 11.8, can be used to set a domain per cluster. See [cluster domains](../../user/project/clusters/gitlab_managed_clusters.md#base-domain) for more information. |
+| `KUBE_NAMESPACE` | The namespace used for deployments. When using certificate-based clusters, [this value should not be overwritten directly](../../user/project/clusters/deploy_to_cluster.md#custom-namespace). |
+| `KUBECONFIG` | The kubeconfig to use for deployments. User-provided values take priority over GitLab-provided values. |
| `PRODUCTION_REPLICAS` | Number of replicas to deploy in the production environment. Takes precedence over `REPLICAS` and defaults to 1. For zero downtime upgrades, set to 2 or greater. |
| `REPLICAS` | Number of replicas to deploy. Defaults to 1. |
| `ROLLOUT_RESOURCE_TYPE` | From GitLab 11.9, allows specification of the resource type being deployed when using a custom Helm chart. Default value is `deployment`. |
diff --git a/doc/topics/autodevops/multiple_clusters_auto_devops.md b/doc/topics/autodevops/multiple_clusters_auto_devops.md
index 2191ab9ee8b..c6df5ac9e02 100644
--- a/doc/topics/autodevops/multiple_clusters_auto_devops.md
+++ b/doc/topics/autodevops/multiple_clusters_auto_devops.md
@@ -35,8 +35,8 @@ To add a different cluster for each environment:
1. Navigate to your project's **Infrastructure > Kubernetes clusters**.
1. Create the Kubernetes clusters with their respective environment scope, as
described from the table above.
-1. After creating the clusters, navigate to each cluster and [install
- Ingress](quick_start_guide.md#install-ingress). Wait for the Ingress IP address to be assigned.
+1. After creating the clusters, navigate to each cluster and [install Ingress](quick_start_guide.md#install-ingress).
+ Wait for the Ingress IP address to be assigned.
1. Make sure you've [configured your DNS](requirements.md#auto-devops-base-domain) with the
specified Auto DevOps domains.
1. Navigate to each cluster's page, through **Infrastructure > Kubernetes clusters**,
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index c84b5e4d9c7..1fc2bd7c2c0 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.md
@@ -236,7 +236,7 @@ you to common environment tasks:
about the Kubernetes cluster and how the application
affects it in terms of memory usage, CPU usage, and latency
- **Deploy to** (**{play}** **{angle-down}**) - Displays a list of environments you can deploy to
-- **Terminal** (**{terminal}**) - Opens a [web terminal](../../ci/environments/index.md#web-terminals)
+- **Terminal** (**{terminal}**) - Opens a [web terminal](../../ci/environments/index.md#web-terminals-deprecated)
session inside the container where the application is running
- **Re-deploy to environment** (**{repeat}**) - For more information, see
[Retrying and rolling back](../../ci/environments/index.md#retry-or-roll-back-a-deployment)
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index ead2e957684..039c369ce9b 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.md
@@ -663,7 +663,7 @@ may require commands to be wrapped as follows:
Some of the reasons you may need to wrap commands:
- Attaching using `kubectl exec`.
-- Using the GitLab [Web Terminal](../../ci/environments/index.md#web-terminals).
+- Using the GitLab [Web Terminal](../../ci/environments/index.md#web-terminals-deprecated).
For example, to start a Rails console from the application root directory, run:
diff --git a/doc/topics/git/getting_started.md b/doc/topics/git/getting_started.md
index 7e04eae622f..7a836e5b659 100644
--- a/doc/topics/git/getting_started.md
+++ b/doc/topics/git/getting_started.md
@@ -21,6 +21,12 @@ comments: false
git clone <url>
```
+NOTE:
+You can also clone GitLab projects with the
+[GitLab Workflow VS Code extension](../../user/project/repository/vscode.md).
+To learn more, read about the extension's
+[`Git: Clone` command](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#clone-gitlab-projects).
+
## Central Repositories
- To instantiate a central repository a `--bare` flag is required.
diff --git a/doc/topics/git/git_rebase.md b/doc/topics/git/git_rebase.md
index b09f9fa0f6c..c0bc7ed4e5c 100644
--- a/doc/topics/git/git_rebase.md
+++ b/doc/topics/git/git_rebase.md
@@ -3,13 +3,13 @@ stage: Create
group: Source Code
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
type: concepts, howto
-description: "Introduction to Git rebase, force-push, and resolving merge conflicts through the command line."
+description: "Introduction to Git rebase and force-push, methods to resolve merge conflicts through the command line."
---
-# Introduction to Git rebase, force-push, and merge conflicts **(FREE)**
+# Introduction to Git rebase and force-push **(FREE)**
This guide helps you to get started with rebasing, force-pushing, and fixing
-merge conflicts locally.
+[merge conflicts](../../user/project/merge_requests/conflicts.md) locally.
Before diving into this document, make sure you are familiar with using
[Git through the command line](../../gitlab-basics/start-using-git.md).
@@ -26,7 +26,8 @@ Git. There are the following rebase options:
WARNING:
`git rebase` rewrites the commit history. It **can be harmful** to do it in
-shared branches. It can cause complex and hard to resolve merge conflicts. In
+shared branches. It can cause complex and hard to resolve
+[merge conflicts](../../user/project/merge_requests/conflicts.md). In
these cases, instead of rebasing your branch against the default branch,
consider pulling it instead (`git pull origin master`). It has a similar
effect without compromising the work of your contributors.
@@ -117,7 +118,7 @@ example, `release-10-3`. You can also replace `origin` with other remote
repositories, for example, `upstream`. To check what remotes you have linked to your local
repository, you can run `git remote -v`.
-If there are [merge conflicts](#merge-conflicts), Git prompts you to fix
+If there are merge conflicts, Git prompts you to fix
them before continuing the rebase.
To learn more, check Git's documentation on [rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing)
@@ -129,7 +130,7 @@ You can rebase your feature branch directly from the merge request through a
[quick action](../../user/project/quick_actions.md#issues-merge-requests-and-epics),
if all of these conditions are met:
-- No [merge conflicts](#merge-conflicts) exist for your feature branch.
+- No merge conflicts exist for your feature branch.
- You have the **Developer** role for the source project. This role grants you
permission to push to the source branch for the source project.
- If the merge request is in a fork, the fork must allow commits
@@ -144,6 +145,11 @@ To rebase from the UI:
GitLab schedules a rebase of the feature branch against the default branch and
executes it as soon as possible.
+The user performing the rebase action is considered
+a user that added commits to the merge request. When the merge request approvals setting
+[**Prevent approvals by users who add commits**](../../user/project/merge_requests/approvals/settings.md#prevent-approvals-by-users-who-add-commits)
+is enabled, this setting prevents the user from also approving the merge request.
+
### Interactive rebase
You can use interactive rebase to modify commits. For example, amend a commit
@@ -235,70 +241,3 @@ you can't force push to it unless you either:
to it.
Then you can force push and protect it again.
-
-## Merge conflicts
-
-As Git is based on comparing versions of a file
-line-by-line, whenever a line changed in your branch coincides with the same
-line changed in the target branch (after the moment you created your feature branch from it), Git
-identifies these changes as a merge conflict. To fix it, you need to choose
-which version of that line you want to keep.
-
-Most conflicts can be [resolved through the GitLab UI](../../user/project/merge_requests/resolve_conflicts.md).
-
-For more complex cases, there are various methods for resolving them. There are
-also [Git GUI apps](https://git-scm.com/downloads/guis) that can help by
-visualizing the differences.
-
-To fix conflicts locally, you can use the following method:
-
-1. Open the terminal and checkout your feature branch, for example, `my-feature-branch`:
-
- ```shell
- git checkout my-feature-branch
- ```
-
-1. [Rebase](#regular-rebase) your branch against the target branch so Git
- prompts you with the conflicts:
-
- ```shell
- git rebase origin/master
- ```
-
-1. Open the conflicting file in a code editor of your preference.
-1. Look for the conflict block:
- - It begins with the marker: `<<<<<<< HEAD`.
- - Below, there is the content with your changes.
- - The marker: `=======` indicates the end of your changes.
- - Below, there's the content of the latest changes in the target branch.
- - The marker `>>>>>>>` indicates the end of the conflict.
-1. Edit the file: choose which version (before or after `=======`) you want to
- keep, and then delete the portion of the content you don't want in the file.
-1. Delete the markers.
-1. Save the file.
-1. Repeat the process if there are other conflicting files.
-1. Stage your changes:
-
- ```shell
- git add .
- ```
-
-1. Commit your changes:
-
- ```shell
- git commit -m "Fix merge conflicts"
- ```
-
-1. Continue rebasing:
-
- ```shell
- git rebase --continue
- ```
-
- WARNING:
- Up to this point, you can run `git rebase --abort` to stop the process.
- Git aborts the rebase and rolls back the branch to the state you had before
- running `git rebase`.
- After you run `git rebase --continue` the rebase **cannot** be aborted.
-
-1. [Force-push](#force-push) to your remote branch.
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index 0b4fd335455..b21237203d7 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -42,6 +42,7 @@ Documentation for GitLab instance administrators is under [LFS administration do
credentials store is recommended.
- Git LFS always assumes HTTPS so if you have GitLab server on HTTP you must
[add the URL to Git configuration manually](#troubleshooting).
+- [Group wikis](../../../user/project/wiki/group.md) do not support Git LFS.
NOTE:
With 8.12 GitLab added LFS support to SSH. The Git LFS communication
diff --git a/doc/topics/index.md b/doc/topics/index.md
index fde420c64f6..6d2c839430b 100644
--- a/doc/topics/index.md
+++ b/doc/topics/index.md
@@ -1,24 +1,9 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../index.md'
+remove_date: '2022-02-03'
---
-# Topics
+This document was moved to [another location](../index.md).
-Welcome to Topics! We have organized our content resources into topics
-to get you started on areas of your interest. Each topic page
-consists of an index listing all related content. It guides
-you through better understanding GitLab concepts
-through our regular docs, and, when available, through articles (guides,
-tutorials, technical overviews, blog posts) and videos.
-
-- [Auto DevOps](autodevops/index.md)
-- [Authentication](authentication/index.md)
-- [Continuous Integration (GitLab CI/CD)](../ci/index.md)
-- [Cron](cron/index.md)
-- [Git](git/index.md)
-- [GitLab Flow](gitlab_flow.md)
-- [GitLab Installation](../install/index.md)
-- [GitLab Pages](../user/project/pages/index.md)
-- [Offline GitLab](offline/index.md)
+<!-- This redirect file can be deleted after <2022-02-03>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/topics/plan_and_track.md b/doc/topics/plan_and_track.md
index 86c5287b331..abede62c00b 100644
--- a/doc/topics/plan_and_track.md
+++ b/doc/topics/plan_and_track.md
@@ -31,6 +31,7 @@ Get work done as a team.
- [Labels](../user/project/labels.md)
- [Milestones](../user/project/milestones/index.md)
- [Requirements](../user/project/requirements/index.md)
+- [Tasks](../user/tasks.md)
- [Time tracking](../user/project/time_tracking.md)
- [Wikis](../user/project/wiki/index.md)
diff --git a/doc/topics/release_your_application.md b/doc/topics/release_your_application.md
index 31eb7705760..cbd7cfab720 100644
--- a/doc/topics/release_your_application.md
+++ b/doc/topics/release_your_application.md
@@ -4,10 +4,11 @@ group:
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Release your application **(FREE)**
+# Deploy and release your application **(FREE)**
-Release your application internally or to the public. Use
+Deploy your application internally or to the public. Use
flags to release features incrementally.
+- [Environments and deployments](../ci/environments/index.md)
- [Releases](../user/project/releases/index.md)
- [Feature flags](../operations/feature_flags.md)
diff --git a/doc/topics/use_gitlab.md b/doc/topics/use_gitlab.md
index f45dc91131c..f73e41c251b 100644
--- a/doc/topics/use_gitlab.md
+++ b/doc/topics/use_gitlab.md
@@ -16,4 +16,6 @@ organize your work, create and secure your application, and analyze its performa
- [Secure your application](../user/application_security/index.md)
- [Release your application](release_your_application.md)
- [Monitor application performance](../operations/index.md)
+- [Monitor runner performance](https://docs.gitlab.com/runner/monitoring/index.html)
+- [Manage your infrastructure](../user/infrastructure/index.md)
- [Analyze GitLab usage](../user/analytics/index.md)
diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md
index e2af4f453c0..42bd41ed74b 100644
--- a/doc/update/deprecations.md
+++ b/doc/update/deprecations.md
@@ -17,16 +17,26 @@ sole discretion of GitLab Inc.
<!-- vale off -->
<!--
+DO NOT EDIT THIS PAGE DIRECTLY
+
This page is automatically generated from the YAML files in `/data/deprecations` by the rake task
located at `lib/tasks/gitlab/docs/compile_deprecations.rake`.
-Do not edit this page directly.
+For deprecation authors (usually Product Managers and Engineering Managers):
+
+- To add a deprecation, use the example.yml file in `/data/deprecations/templates` as a template.
+- For more information about authoring deprecations, check the the deprecation item guidance:
+ https://about.gitlab.com/handbook/marketing/blog/release-posts/#creating-a-deprecation-entry
+
+For deprecation reviewers (Technical Writers only):
-To add a deprecation, use the example.yml file in `/data/deprecations/templates` as a template,
-then run `bin/rake gitlab:docs:compile_deprecations`.
+- To update the deprecation doc, run: `bin/rake gitlab:docs:compile_deprecations`
+- To verify the deprecations doc is up to date, run: `bin/rake gitlab:docs:check_deprecations`
+- For more information about updating the deprecation doc, see the deprecation doc update guidance:
+ https://about.gitlab.com/handbook/marketing/blog/release-posts/#update-the-deprecations-doc
-->
-## 14.4
+## 14.5
### Rename Task Runner pod to Toolbox
@@ -44,17 +54,17 @@ The [release-cli](https://gitlab.com/gitlab-org/release-cli) will be released as
Announced: 2021-08-22
-## 15.0
+## 14.8
-### Legacy database configuration
+### openSUSE Leap 15.2 packages
-The syntax of [GitLabs database](https://docs.gitlab.com/omnibus/settings/database.html)
-configuration located in `database.yml` is changing and the legacy format is deprecated. The legacy format
-supported using a single PostgreSQL adapter, whereas the new format is changing to support multiple databases. The `main:` database needs to be defined as a first configuration item.
+Distribution support and security updates for openSUSE Leap 15.2 are [ending December 2021](https://en.opensuse.org/Lifetime#openSUSE_Leap).
-This deprecation mainly impacts users compiling GitLab from source because Omnibus will handle this configuration automatically.
+Starting in 14.5 we are providing packages for openSUSE Leap 15.3, and will stop providing packages for openSUSE Leap 15.2 in the 14.8 milestone.
-Announced: 2021-09-22
+Announced: 2021-11-22
+
+## 15.0
### Audit events for repository push events
@@ -66,15 +76,39 @@ dramatically slow down GitLab instances. For this reason, they are being removed
Announced: 2021-09-22
-### OmniAuth Kerberos gem
+### Certificate-based integration with Kubernetes
-The `omniauth-kerberos` gem will be removed in our next major release, GitLab 15.0.
+[We are deprecating the certificate-based integration with Kubernetes](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
+The timeline of removal of the integration from the product is not yet planned and we will communicate
+more details as they emerge. The certificate-based integration will continue to receive security and
+critical fixes, and features built on the integration will continue to work with supported Kubernetes
+versions. We will provide migration plans in a future iteration. See [the list of features affected by this deprecation](https://docs.gitlab.com/ee/user/infrastructure/clusters/#deprecated-features).
+For updates and details, follow this [epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
-This gem has not been maintained and has very little usage. We therefore plan to remove support for this authentication method and recommend using the Kerberos [SPNEGO](https://en.wikipedia.org/wiki/SPNEGO) integration instead. You can follow the [upgrade instructions](https://docs.gitlab.com/ee/integration/kerberos.html#upgrading-from-password-based-to-ticket-based-kerberos-sign-ins) to upgrade from the `omniauth-kerberos` integration to the supported one.
+For a more robust, secure, forthcoming, and reliable integration with Kubernetes, we recommend the use of the
+[Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab.
-Note that we are not deprecating the Kerberos SPNEGO integration, only the old password-based Kerberos integration.
+Announced: 2021-11-15
-Announced: 2021-09-22
+### Converting an instance (shared) runner to a project (specific) runner is deprecated
+
+In GitLab 15.0, we will remove the feature that enables you to convert an instance (shared) runner to a project (specific) runner. Users who need to add a runner to only a particular project can register a runner to the project directly.
+
+Announced: 2021-11-22
+
+### Deprecate `Versions` on base `PackageType`
+
+As part of the work to create a [Package Registry GraphQL API](https://gitlab.com/groups/gitlab-org/-/epics/6318), the Package group deprecated the `Version` type for the basic `PackageType` type and moved it to [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#packagedetailstype).
+
+In milestone 15.0, we will completely remove `Version` from `PackageType`.
+
+Announced: 2021-11-22
+
+### Deprecate support for SLES 12 SP2
+
+Long term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 12 SP2 [ended on March 31, 2021](https://www.suse.com/lifecycle/). The CA certificates on SP2 include the expired DST root certificate, and it's not getting new CA certificate package updates. We have implemented some [workarounds](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/191), but we will not be able to continue to keep the build running properly.
+
+Announced: 2021-11-22
### GitLab Serverless
@@ -84,7 +118,23 @@ We decided to remove the GitLab Serverless features as they never really resonat
Announced: 2021-09-22
-## 15.2
+### Known host required for GitLab Runner SSH executor
+
+In [GitLab 14.3](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/3074), we added a configuration setting in the GitLab Runner `config.toml` file. This setting, [`[runners.ssh.disable_strict_host_key_checking]`](https://docs.gitlab.com/runner/executors/ssh.html#security), controls whether or not to use strict host key checking with the SSH executor.
+
+In GitLab 15.0 and later, the default value for this configuration option will change from `true` to `false`. This means that strict host key checking will be enforced when using the GitLab Runner SSH executor.
+
+Announced: 2021-11-22
+
+### Legacy database configuration
+
+The syntax of [GitLabs database](https://docs.gitlab.com/omnibus/settings/database.html)
+configuration located in `database.yml` is changing and the legacy format is deprecated. The legacy format
+supported using a single PostgreSQL adapter, whereas the new format is changing to support multiple databases. The `main:` database needs to be defined as a first configuration item.
+
+This deprecation mainly impacts users compiling GitLab from source because Omnibus will handle this configuration automatically.
+
+Announced: 2021-09-22
### NFS for Git repository storage deprecated
@@ -99,3 +149,95 @@ Gitaly Cluster offers tremendous benefits for our customers such as:
We encourage customers currently using NFS for Git repositories to plan their migration by reviewing our documentation on [migrating to Gitaly Cluster](https://docs.gitlab.com/ee/administration/gitaly/index.html#migrate-to-gitaly-cluster).
Announced: 2021-06-22
+
+### OmniAuth Kerberos gem
+
+The `omniauth-kerberos` gem will be removed in our next major release, GitLab 15.0.
+
+This gem has not been maintained and has very little usage. We therefore plan to remove support for this authentication method and recommend using the Kerberos [SPNEGO](https://en.wikipedia.org/wiki/SPNEGO) integration instead. You can follow the [upgrade instructions](https://docs.gitlab.com/ee/integration/kerberos.html#upgrading-from-password-based-to-ticket-based-kerberos-sign-ins) to upgrade from the `omniauth-kerberos` integration to the supported one.
+
+Note that we are not deprecating the Kerberos SPNEGO integration, only the old password-based Kerberos integration.
+
+Announced: 2021-09-22
+
+### Package pipelines in API payload is paginated
+
+A request to the API for `/api/v4/projects/:id/packages` returns a paginated result of packages. Each package lists all of its pipelines in this response. This is a performance concern, as it's possible for a package to have hundreds or thousands of associated pipelines.
+
+In milestone 15.0, we will remove the `pipelines` attribute from the API response.
+
+Announced: 2021-11-22
+
+### REST API Runner will not contain `paused`
+
+Runner REST API will not return `paused` as a status in GitLab 15.0.
+
+Paused runners' status will only relate to runner contact status, such as:
+`online`, `offline`, or `not_connected`. Status `paused` will not appear when the runner is
+not active.
+
+When checking if a runner is `paused`, API users are advised to check the boolean attribute
+`active` to be `false` instead.
+
+Announced: 2021-11-22
+
+### Removal of `promote-db` command from `gitlab-ctl`
+
+In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-db` which is used to promote database nodes in multi-node Geo secondary sites. `gitlab-ctl promote-db` will continue to function as-is and be available until GitLab 15.0. We recommend that Geo customers begin testing the new `gitlab-ctl promote` command in their staging environments and incorporating the new command in their failover procedures.
+
+Announced: 2021-11-22
+
+### Removal of `promote-to-primary-node` command from `gitlab-ctl`
+
+In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-to-primary-node` which was only usable for single-node Geo sites. `gitlab-ctl promote-to-primary-node` will continue to function as-is and be available until GitLab 15.0. We recommend that Geo customers begin testing the new `gitlab-ctl promote` command in their staging environments and incorporating the new command in their failover procedures.
+
+Announced: 2021-11-22
+
+### Remove the `:dependency_proxy_for_private_groups` feature flag
+
+We added a feature flag because [GitLab-#11582](https://gitlab.com/gitlab-org/gitlab/-/issues/11582) changed how public groups use the Dependency Proxy. Prior to this change, you could use the Dependency Proxy without authentication. The change requires authentication to use the Dependency Proxy.
+
+In milestone 15.0, we will remove the feature flag entirely. Moving forward, you must authenticate when using the Dependency Proxy.
+
+Announced: 2021-11-22
+
+### Remove the `pipelines` field from the `version` field
+
+In GraphQL, there are two `pipelines` fields that you can use in a [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/#packagedetailstype) to get the pipelines for package versions:
+
+- The `versions` field's `pipelines` field. This returns all the pipelines associated with all the package's versions, which can pull an unbounded number of objects in memory and create performance concerns.
+- The `pipelines` field of a specific `version`. This returns only the pipelines associated with that single package version.
+
+To mitigate possible performance problems, we will remove the `versions` field's `pipelines` field in milestone 15.0. Although you will no longer be able to get all pipelines for all versions of a package, you can still get the pipelines of a single version through the remaining `pipelines` field for that version.
+
+Announced: 2021-11-22
+
+### Update to the Container Registry group-level API
+
+In milestone 15.0, support for the `tags` and `tags_count` parameters will be removed from the Container Registry API that [gets registry repositories from a group](../api/container_registry.md#within-a-group).
+
+The `GET /groups/:id/registry/repositories` endpoint will remain, but won't return any info about tags. To get the info about tags, you can use the existing `GET /registry/repositories/:id` endpoint, which will continue to support the `tags` and `tag_count` options as it does today. The latter must be called once per image repository.
+
+Announced: 2021-11-22
+
+### Value Stream Analytics filtering calculation change
+
+We are changing how the date filter works in Value Stream Analytics. Instead of filtering by the time that the issue or merge request was created, the date filter will filter by the end event time of the given stage. This will result in completely different figures after this change has rolled out.
+
+If you monitor Value Stream Analytics metrics and rely on the date filter, to avoid losing data, you must save the data prior to this change.
+
+Announced: 2021-11-22
+
+### `AuthenticationType` for `[runners.cache.s3]` must be explicitly assigned
+
+In GitLab 15.0 and later, to access the AWS S3 cache, you must specify the `AuthenticationType` for [`[runners.cache.s3]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscaches3-section). The `AuthenticationType` must be `IAM` or `credentials`.
+
+Prior to 14.5, if you did not define the `AuthenticationType`, GitLab Runner chose a type for you.
+
+Announced: 2021-11-22
+
+### defaultMergeCommitMessageWithDescription GraphQL API field will be removed in GitLab 15.0
+
+The GraphQL API field `defaultMergeCommitMessageWithDescription` has been deprecated and will be removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template.
+
+Announced: 2021-11-22
diff --git a/doc/update/index.md b/doc/update/index.md
index b719c47ae26..bb7fdaa93c0 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -12,6 +12,11 @@ GitLab version is, if you're upgrading to a major version, and so on.
Make sure to read the whole page as it contains information related to every upgrade method.
+NOTE:
+Upgrade GitLab to the latest available patch release, for example `13.8.8` rather than `13.8.0`.
+This includes [versions you must stop at on the upgrade path](#upgrade-paths) as there may
+be fixes for issues relating to the upgrade process.
+
The [maintenance policy documentation](../policy/maintenance.md)
has additional information about upgrading, including:
@@ -76,22 +81,44 @@ See the guide to [plan your GitLab upgrade](plan_your_upgrade.md).
## Checking for background migrations before upgrading
-Certain major/minor releases may require different migrations to be
-finished before you update to the newer version.
+Certain releases may require different migrations to be
+finished before you update to the newer version. Additionally check
+[batched migrations](#batched-background-migrations) from GitLab 14.0.
Decrease the time required to complete these migrations by increasing the number of
[Sidekiq workers](../administration/operations/extra_sidekiq_processes.md)
that can process jobs in the `background_migration` queue.
-**For GitLab 14.0 and newer**
+**For Omnibus installations:**
+
+```shell
+sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
+```
+
+**For installations from source:**
+
+```shell
+cd /home/git/gitlab
+sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
+```
+
+### Batched background migrations
+
+GitLab 14.0 introduced [batched background migrations](../user/admin_area/monitoring/background_migrations.md).
-To check the status of [batched background migrations](../user/admin_area/monitoring/background_migrations.md):
+Some installations [may need to run GitLab 14.0 for at least a day](#1400) to complete the database changes introduced by that upgrade.
+
+#### Check the status of batched background migrations
+
+To check the status of batched background migrations:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Monitoring > Background Migrations**.
![queued batched background migrations table](img/batched_background_migrations_queued_v14_0.png)
+All migrations must have a `Finished` status before you upgrade GitLab.
+
The status of batched background migrations can also be queried directly in the database.
1. Log into a `psql` prompt according to the directions for your instance's installation method
@@ -102,20 +129,14 @@ The status of batched background migrations can also be queried directly in the
select job_class_name, table_name, column_name, job_arguments from batched_background_migrations where status <> 3;
```
-**For Omnibus installations**
+If the migrations are not finished and you try to update to a later version,
+GitLab prompts you with an error:
-You can also run:
-
-```shell
-sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
+```plaintext
+Expected batched background migration for the given configuration to be marked as 'finished', but it is 'active':
```
-**For installations from source**
-
-```shell
-cd /home/git/gitlab
-sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
-```
+If you get this error, [check the batched background migration options](../user/admin_area/monitoring/background_migrations.md#database-migrations-failing-because-of-batched-background-migration-not-finished) to complete the upgrade.
### What do I do if my background migrations are stuck?
@@ -148,6 +169,10 @@ pending_job_classes = scheduled_queue.select { |job| job["class"] == "Background
pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) }
```
+**Batched migrations (GitLab 14.0 and newer):**
+
+See [troubleshooting batched background migrations](../user/admin_area/monitoring/background_migrations.md#troubleshooting).
+
## Dealing with running CI/CD pipelines and jobs
If you upgrade your GitLab instance while the GitLab Runner is processing jobs, the trace updates fail. When GitLab is back online, the trace updates should self-heal. However, depending on the error, the GitLab Runner either retries or eventually terminates job handling.
@@ -163,12 +188,10 @@ To address the above two scenario's, it is advised to do the following prior to
## Checking for pending Advanced Search migrations
-This section is only applicable if you have enabled the [Elasticsearch
-integration](../integration/elasticsearch.md).
+This section is only applicable if you have enabled the [Elasticsearch integration](../integration/elasticsearch.md).
-Major releases require all [Advanced Search
-migrations](../integration/elasticsearch.md#advanced-search-migrations) to
-be finished from the most recent minor release in your current version
+Major releases require all [Advanced Search migrations](../integration/elasticsearch.md#advanced-search-migrations)
+to be finished from the most recent minor release in your current version
before the major version upgrade. You can find pending migrations by
running the following command:
@@ -187,8 +210,7 @@ sudo -u git -H bundle exec rake gitlab:elastic:list_pending_migrations
### What do I do if my Advanced Search migrations are stuck?
-See [how to retry a halted
-migration](../integration/elasticsearch.md#retry-a-halted-migration).
+See [how to retry a halted migration](../integration/elasticsearch.md#retry-a-halted-migration).
## Upgrade paths
@@ -200,7 +222,7 @@ Find where your version sits in the upgrade path below, and upgrade GitLab
accordingly, while also consulting the
[version-specific upgrade instructions](#version-specific-upgrading-instructions):
-`8.11.Z` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> [`11.11.8`](#1200) -> `12.0.12` -> [`12.1.17`](#1210) -> `12.10.14` -> `13.0.14` -> [`13.1.11`](#1310) -> [`13.8.8`](#1388) -> [latest `13.12.Z`](https://about.gitlab.com/releases/categories/releases/) -> [latest `14.0.Z`](#1400) -> [latest `14.Y.Z`](https://about.gitlab.com/releases/categories/releases/)
+`8.11.Z` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> [`11.11.8`](#1200) -> `12.0.12` -> [`12.1.17`](#1210) -> `12.10.14` -> `13.0.14` -> [`13.1.11`](#1310) -> [`13.8.8`](#1388) -> [`13.12.15`](https://about.gitlab.com/releases/categories/releases/) -> [latest `14.0.Z`](#1400) -> [latest `14.1.Z`](#1410) -> [latest `14.Y.Z`](https://about.gitlab.com/releases/categories/releases/)
The following table, while not exhaustive, shows some examples of the supported
upgrade paths.
@@ -234,12 +256,11 @@ It's also important to ensure that any background migrations have been fully com
before upgrading to a new major version. To see the current size of the `background_migration` queue,
[Check for background migrations before upgrading](#checking-for-background-migrations-before-upgrading).
-If you have enabled the [Elasticsearch
-integration](../integration/elasticsearch.md), then ensure
+If you have enabled the [Elasticsearch integration](../integration/elasticsearch.md), then ensure
all Advanced Search migrations are completed in the last minor version within
-your current version. Be sure to [check for pending Advanced Search
-migrations](#checking-for-pending-advanced-search-migrations) before proceeding
-with the major version upgrade.
+your current version. Be sure to
+[check for pending Advanced Search migrations](#checking-for-pending-advanced-search-migrations)
+before proceeding with the major version upgrade.
If your GitLab instance has any runners associated with it, it is very
important to upgrade GitLab Runner to match the GitLab minor version that was
@@ -307,6 +328,33 @@ NOTE:
Specific information that follow related to Ruby and Git versions do not apply to [Omnibus installations](https://docs.gitlab.com/omnibus/)
and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with appropriate Ruby and Git versions and are not using system binaries for Ruby and Git. There is no need to install Ruby or Git when utilizing these two approaches.
+### 14.5.0
+
+- When `make` is run, Gitaly builds are now created in `_build/bin` and no longer in the root directory of the source directory. If you
+are using a source install, update paths to these binaries in your [systemd unit files](upgrading_from_source.md#configure-systemd-units)
+or [init scripts](upgrading_from_source.md#configure-sysv-init-script) by [following the documentation](upgrading_from_source.md).
+
+- Connections between Workhorse and Gitaly use the Gitaly `backchannel` protocol by default. If you deployed a gRPC proxy between Workhorse and Gitaly,
+ Workhorse can no longer connect. As a workaround, [disable the temporary `workhorse_use_sidechannel`](../administration/feature_flags.md#enable-or-disable-the-feature)
+ feature flag. If you need a proxy between Workhorse and Gitaly, use a TCP proxy. If you have feedback about this change, please go to [this issue](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1301).
+
+- In 14.1 we introduced a background migration that changes how we store merge request diff commits
+ in order to significantly reduce the amount of storage needed.
+ In 14.5 we introduce a set of migrations that wrap up this process by making sure
+ that all remaining jobs over the `merge_request_diff_commits` table are completed.
+ These jobs will have already been processed in most cases so that no extra time is necessary during an upgrade to 14.5.
+ But if there are remaining jobs, the deployment may take a few extra minutes to complete.
+
+ All merge request diff commits will automatically incorporate these changes, and there are no
+ additional requirements to perform the upgrade.
+ Existing data in the `merge_request_diff_commits` table remains unpacked until you run `VACUUM FULL merge_request_diff_commits`.
+ But note that the `VACUUM FULL` operation locks and rewrites the entire `merge_request_diff_commits` table,
+ so the operation takes some time to complete and it blocks access to this table until the end of the process.
+ We advise you to only run this command while GitLab is not actively used or it is taken offline for the duration of the process.
+ The time it takes to complete depends on the size of the table, which can be obtained by using `select pg_size_pretty(pg_total_relation_size('merge_request_diff_commits'));`.
+
+ For more information, refer to [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/331823).
+
### 14.4.0
Git 2.33.x and later is required. We recommend you use the
@@ -314,9 +362,11 @@ Git 2.33.x and later is required. We recommend you use the
### 14.3.0
-Ruby 2.7.4 is required. Refer to [the Ruby installation instructions](../install/installation.md#2-ruby)
+- [Instances running 14.0.0 - 14.0.4 should not upgrade directly to GitLab 14.2 or later](#upgrading-to-later-14y-releases).
+- Ensure [batched background migrations finish](#batched-background-migrations) before upgrading
+ to 14.3.Z from earlier GitLab 14 releases.
+- Ruby 2.7.4 is required. Refer to [the Ruby installation instructions](../install/installation.md#2-ruby)
for how to proceed.
-
- GitLab 14.3.0 contains post-deployment migrations to [address Primary Key overflow risk for tables with an integer PK](https://gitlab.com/groups/gitlab-org/-/epics/4785) for the tables listed below:
- [`ci_builds.id`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70245)
@@ -337,13 +387,10 @@ for how to proceed.
### 14.2.0
-- Due to an issue where `BatchedBackgroundMigrationWorkers` were
- [not working](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/2785#note_614738345)
- for self-managed instances, a [fix was created](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65106)
- and a [14.0.Z](#1400) version was released. If you haven't updated to 14.0.5, you need
- to update to at least 14.1.0 that contains the same fix before you update to 14.2.
+- [Instances running 14.0.0 - 14.0.4 should not upgrade directly to GitLab 14.2 or later](#upgrading-to-later-14y-releases).
+- Ensure [batched background migrations finish](#batched-background-migrations) before upgrading
+ to 14.2.Z from earlier GitLab 14 releases.
- GitLab 14.2.0 contains background migrations to [address Primary Key overflow risk for tables with an integer PK](https://gitlab.com/groups/gitlab-org/-/epics/4785) for the tables listed below:
-
- [`ci_build_needs`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65216)
- [`ci_build_trace_chunks`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66123)
- [`ci_builds_runner_session`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66433)
@@ -366,35 +413,24 @@ for how to proceed.
### 14.1.0
-- Due to an issue where `BatchedBackgroundMigrationWorkers` were
- [not working](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/2785#note_614738345)
- for self-managed instances, a [fix was created](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65106)
- and a [14.0.Z](#1400) version was released. If you haven't updated to 14.0.5, you need
- to update to at least 14.1.0 that contains the same fix before you update to
- a later version.
-
- After you update to 14.1.0,
- [batched background migrations need to finish](../user/admin_area/monitoring/background_migrations.md#check-the-status-of-background-migrations)
- before you update to a later version.
-
- If the migrations are not finished and you try to update to a later version,
- you'll see an error like:
-
- ```plaintext
- Expected batched background migration for the given configuration to be marked as 'finished', but it is 'active':
- ```
-
- See how to [resolve this error](../user/admin_area/monitoring/background_migrations.md#database-migrations-failing-because-of-batched-background-migration-not-finished).
+- [Instances running 14.0.0 - 14.0.4 should not upgrade directly to GitLab 14.2 or later](#upgrading-to-later-14y-releases)
+ but can upgrade to 14.1.Z.
+- It is not required for instances already running 14.0.5 (or higher) to stop at 14.1.Z.
+ 14.1 is included on the upgrade path for the broadest compatibility
+ with self-managed installations, and ensure 14.0.0-14.0.4 installations do not
+ encounter issues with [batched background migrations](#batched-background-migrations).
### 14.0.0
+- Database changes made by the upgrade to GitLab 14.0 can take hours or days to complete on larger GitLab instances.
+ These [batched background migrations](#batched-background-migrations) update whole database tables to mitigate primary key overflow and must be finished before upgrading to GitLab 14.2 or higher.
- Due to an issue where `BatchedBackgroundMigrationWorkers` were
[not working](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/2785#note_614738345)
for self-managed instances, a [fix was created](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65106)
- that requires an update to at least 14.0.5.
+ that requires an update to at least 14.0.5. The fix was also released in [14.1.0](#1410).
After you update to 14.0.5 or a later 14.0 patch version,
- [batched background migrations need to finish](../user/admin_area/monitoring/background_migrations.md#check-the-status-of-background-migrations)
+ [batched background migrations need to finish](#batched-background-migrations)
before you update to a later version.
If the migrations are not finished and you try to update to a later version,
@@ -413,6 +449,16 @@ for how to proceed.
You should instead follow a [supported upgrade path](#upgrade-paths).
- The support of PostgreSQL 11 [has been dropped](../install/requirements.md#database). Make sure to [update your database](https://docs.gitlab.com/omnibus/settings/database.html#upgrade-packaged-postgresql-server) to version 12 before updating to GitLab 14.0.
+#### Upgrading to later 14.Y releases
+
+- Instances running 14.0.0 - 14.0.4 should not upgrade directly to GitLab 14.2 or later,
+ because of [batched background migrations](#batched-background-migrations).
+ 1. Upgrade first to either:
+ - 14.0.5 or a later 14.0.Z patch release.
+ - 14.1.0 or a later 14.1.Z patch release.
+ 1. [Batched background migrations need to finish](#batched-background-migrations)
+ before you update to a later version [and may take longer than usual](#1400).
+
### 13.11.0
Git 2.31.x and later is required. We recommend you use the
diff --git a/doc/update/package/index.md b/doc/update/package/index.md
index 776a7111188..27845caed76 100644
--- a/doc/update/package/index.md
+++ b/doc/update/package/index.md
@@ -262,21 +262,36 @@ unable to add the `commit_message_regex_change` column.
This results in the [backport migration of EE tables](https://gitlab.com/gitlab-org/gitlab/-/blob/cf00e431024018ddd82158f8a9210f113d0f4dbc/db/migrate/20190402150158_backport_enterprise_schema.rb#L1619) not working correctly.
The backport migration assumes that certain tables in the database do not exist when running CE.
-To fix this issue, manually add the missing `commit_message_negative_regex` column and restart GitLab:
+To fix this issue:
-```shell
-# Access psql
-sudo gitlab-rails dbconsole
+1. Start a database console:
-# Add the missing column
-ALTER TABLE push_rules ADD COLUMN commit_message_negative_regex VARCHAR;
+ In GitLab 14.2 and later:
-# Exit psql
-\q
+ ```shell
+ sudo gitlab-rails dbconsole --database main
+ ```
-# Restart GitLab
-sudo gitlab-ctl restart
-```
+ In GitLab 14.1 and earlier:
+
+ ```shell
+ sudo gitlab-rails dbconsole
+ ```
+
+1. Manually add the missing `commit_message_negative_regex` column:
+
+ ```sql
+ ALTER TABLE push_rules ADD COLUMN commit_message_negative_regex VARCHAR;
+
+ # Exit psql
+ \q
+ ```
+
+1. Restart GitLab:
+
+ ```shell
+ sudo gitlab-ctl restart
+ ```
### Error `Failed to connect to the internal GitLab API` on a separate GitLab Pages server
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index d09f19d143b..a2d672e00ac 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -20,6 +20,10 @@ It's useful to make a backup just in case things go south. Depending on the inst
### 1. Stop server
```shell
+# For systems running systemd
+sudo systemctl stop gitlab.target
+
+# For systems running SysV init
sudo service gitlab stop
```
@@ -108,6 +112,11 @@ Please follow the [install instruction](../integration/elasticsearch.md#install-
### 9. Start application
```shell
+# For systems running systemd
+sudo systemctl start gitlab.target
+sudo systemctl restart nginx.service
+
+# For systems running SysV init
sudo service gitlab start
sudo service nginx restart
```
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index d882de62c06..4343b464ba6 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -54,6 +54,10 @@ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
### 2. Stop server
```shell
+# For systems running systemd
+sudo systemctl stop gitlab.target
+
+# For systems running SysV init
sudo service gitlab stop
```
@@ -229,7 +233,29 @@ ActionMailer::Base.delivery_method = :smtp
See [`smtp_settings.rb.sample`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/initializers/smtp_settings.rb.sample#L13) as an example.
-#### Init script
+#### Configure systemd units
+
+If using the SysV init script, see [Configure SysV init script](#configure-sysv-init-script).
+
+Check if the systemd units have been updated:
+
+```shell
+cd /home/git/gitlab
+
+git diff origin/PREVIOUS_BRANCH:lib/support/systemd origin/BRANCH:lib/support/systemd
+```
+
+Copy them over:
+
+```shell
+sudo mkdir -p /usr/local/lib/systemd/system
+sudo cp lib/support/systemd/* /usr/local/lib/systemd/system/
+sudo systemctl daemon-reload
+```
+
+#### Configure SysV init script
+
+If using systemd units, see [Configure systemd units](#configure-systemd-units).
There might be new configuration options available for
[`gitlab.default.example`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/support/init.d/gitlab.default.example).
@@ -249,7 +275,7 @@ cd /home/git/gitlab
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
```
-For Ubuntu 16.04.1 LTS:
+If you are using the init script on a system running systemd as init, because you have not switched to native systemd units yet, run:
```shell
sudo systemctl daemon-reload
@@ -341,6 +367,11 @@ sudo -u git -H make
### 15. Start application
```shell
+# For systems running systemd
+sudo systemctl start gitlab.target
+sudo systemctl restart nginx.service
+
+# For systems running SysV init
sudo service gitlab start
sudo service nginx restart
```
diff --git a/doc/update/zero_downtime.md b/doc/update/zero_downtime.md
index 7a74435267f..a311731cadd 100644
--- a/doc/update/zero_downtime.md
+++ b/doc/update/zero_downtime.md
@@ -1,17 +1,17 @@
---
stage: Enablement
group: Distribution
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Zero downtime upgrades **(FREE SELF)**
-Starting with GitLab 9.1.0 it's possible to upgrade to a newer major, minor, or
-patch version of GitLab without having to take your GitLab instance offline.
-However, for this to work there are the following requirements:
+It's possible to upgrade to a newer major, minor, or patch version of GitLab
+without having to take your GitLab instance offline. However, for this to work
+there are the following requirements:
-- You can only upgrade 1 minor release at a time. So from 9.1 to 9.2, not to
- 9.3. If you skip releases, database modifications may be run in the wrong
+- You can only upgrade one minor release at a time. So from 13.1 to 13.2, not to
+ 13.3. If you skip releases, database modifications may be run in the wrong
sequence [and leave the database schema in a broken state](https://gitlab.com/gitlab-org/gitlab/-/issues/321542).
- You have to use [post-deployment migrations](../development/post_deployment_migrations.md).
- You are using PostgreSQL. Starting from GitLab 12.1, MySQL is not supported.
@@ -36,10 +36,10 @@ to re-read any database changes that have been made by post-deployment migration
Most of the time you can safely upgrade from a patch release to the next minor
release if the patch release is not the latest. For example, upgrading from
-9.1.1 to 9.2.0 should be safe even if 9.1.2 has been released. We do recommend
+14.1.1 to 14.2.0 should be safe even if 14.1.2 has been released. We do recommend
you check the release posts of any releases between your current and target
version just in case they include any migrations that may require you to upgrade
-1 release at a time.
+one release at a time.
Some releases may also include so called "background migrations". These
migrations are performed in the background by Sidekiq and are often used for
@@ -63,21 +63,21 @@ the migrations that are being performed.
To help explain this, let's look at some examples:
-**Example 1:** You are running a large GitLab installation using version 9.4.2,
-which is the latest patch release of 9.4. When GitLab 9.5.0 is released this
-installation can be safely upgraded to 9.5.0 without requiring downtime if the
-requirements mentioned above are met. You can also skip 9.5.0 and upgrade to
-9.5.1 after it's released, but you **can not** upgrade straight to 9.6.0; you
-_have_ to first upgrade to a 9.5.Z release.
-
-**Example 2:** You are running a large GitLab installation using version 9.4.2,
-which is the latest patch release of 9.4. GitLab 9.5 includes some background
-migrations, and 10.0 requires these to be completed (processing any
-remaining jobs for you). Skipping 9.5 is not possible without downtime, and due
+**Example 1:** You are running a large GitLab installation using version 13.4.2,
+which is the latest patch release of 13.4. When GitLab 13.5.0 is released this
+installation can be safely upgraded to 13.5.0 without requiring downtime if the
+requirements mentioned above are met. You can also skip 13.5.0 and upgrade to
+13.5.1 after it's released, but you **can not** upgrade straight to 13.6.0; you
+_have_ to first upgrade to a 13.5.Z release.
+
+**Example 2:** You are running a large GitLab installation using version 13.4.2,
+which is the latest patch release of 13.4. GitLab 13.5 includes some background
+migrations, and 14.0 requires these to be completed (processing any
+remaining jobs for you). Skipping 13.5 is not possible without downtime, and due
to the background migrations would require potentially hours of downtime
depending on how long it takes for the background migrations to complete. To
-work around this you have to upgrade to 9.5.Z first, then wait at least a
-week before upgrading to 10.0.
+work around this you have to upgrade to 13.5.Z first, then wait at least a
+week before upgrading to 14.0.
**Example 3:** You use MySQL as the database for GitLab. Any upgrade to a new
major/minor release requires downtime. If a release includes any background
@@ -89,7 +89,7 @@ meet the other online upgrade requirements mentioned above.
Before following these instructions, note the following **important** information:
-- You can only upgrade 1 minor release at a time. So from 13.6 to 13.7, not to 13.8.
+- You can only upgrade one minor release at a time. So from 13.6 to 13.7, not to 13.8.
If you attempt more than one minor release, the upgrade may fail.
- On single-node Omnibus deployments, updates with no downtime are not possible when
using Puma because Puma always requires a complete restart. This is because the
@@ -100,6 +100,8 @@ Before following these instructions, note the following **important** informatio
these instructions, **it is not possible to always achieve true zero downtime
updates**. Users may see some connections timeout or be refused for a few minutes,
depending on which services need to restart.
+- On Omnibus deployments, the `/etc/gitlab/gitlab.rb` configuration file must **not** have
+ `gitlab_rails['auto_migrate'] = true`.
1. Create an empty file at `/etc/gitlab/skip-auto-reconfigure`. This prevents upgrades from running `gitlab-ctl reconfigure`, which by default automatically stops GitLab, runs all database migrations, and restarts GitLab.
@@ -156,7 +158,7 @@ you've completed these steps.
## Multi-node / HA deployment
-You can only upgrade 1 minor release at a time. So from 13.6 to 13.7, not to 13.8.
+You can only upgrade one minor release at a time. So from 13.6 to 13.7, not to 13.8.
If you attempt more than one minor release, the upgrade may fail.
### Use a load balancer in front of web (Puma) nodes
@@ -208,7 +210,9 @@ load balancer to latest GitLab version.
If you are an Enterprise Edition user, replace `gitlab-ce` with
`gitlab-ee` in the above command.
- 1. Get the regular migrations and latest code in place:
+ 1. Get the regular migrations and latest code in place. Before running this step,
+ the deploy node's `/etc/gitlab/gitlab.rb` configuration file must have
+ `gitlab_rails['auto_migrate'] = true` to permit regular migrations.
```shell
sudo SKIP_POST_DEPLOYMENT_MIGRATIONS=true gitlab-ctl reconfigure
diff --git a/doc/user/admin_area/analytics/dev_ops_report.md b/doc/user/admin_area/analytics/dev_ops_report.md
index b5294bb265d..62fea3c266a 100644
--- a/doc/user/admin_area/analytics/dev_ops_report.md
+++ b/doc/user/admin_area/analytics/dev_ops_report.md
@@ -4,21 +4,21 @@ group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# DevOps Report **(FREE SELF)**
+# DevOps Reports **(FREE SELF)**
-> [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/20976) from Conversational Development Index in GitLab 12.6.
-
-The DevOps Report gives you an overview of your entire instance's adoption of
+DevOps Reports give you an overview of your entire instance's adoption of
[Concurrent DevOps](https://about.gitlab.com/topics/concurrent-devops/)
from planning to monitoring.
-To see DevOps Report:
+To see DevOps Reports:
1. On the top bar, select **Menu > Admin**.
-1. On the left sidebar, select **Analytics > DevOps Report**.
+1. On the left sidebar, select **Analytics > DevOps Reports**.
## DevOps Score
+> [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/20976) from Conversational Development Index in GitLab 12.6.
+
NOTE:
To see the DevOps score, you must activate your GitLab instance's [Service Ping](../settings/usage_statistics.md#service-ping). This is because DevOps Score is a comparative tool, so your score data must be centrally processed by GitLab Inc. first.
@@ -72,4 +72,4 @@ DevOps Adoption allows you to:
- Identify specific groups that are lagging in their adoption of GitLab, so you can help them along in their DevOps journey.
- Find the groups that have adopted certain features, and can provide guidance to other groups on how to use those features.
-![DevOps Report](img/admin_devops_adoption_v14_2.png)
+![DevOps Adoption](img/admin_devops_adoption_v14_2.png)
diff --git a/doc/user/admin_area/analytics/index.md b/doc/user/admin_area/analytics/index.md
index dd1efc913fa..cd505e154c6 100644
--- a/doc/user/admin_area/analytics/index.md
+++ b/doc/user/admin_area/analytics/index.md
@@ -15,5 +15,5 @@ Administrators have access to instance-wide analytics:
There are several kinds of statistics:
-- [DevOps Report](dev_ops_report.md): Provides an overview of your entire instance's feature usage.
+- [DevOps Reports](dev_ops_report.md): Provides an overview of your entire instance's feature usage.
- [Usage Trends](usage_trends.md): Shows how much data your instance contains, and how that is changing.
diff --git a/doc/user/admin_area/img/index_runners_search_or_filter_v14_1.png b/doc/user/admin_area/img/index_runners_search_or_filter_v14_1.png
deleted file mode 100644
index ab196a0ca9e..00000000000
--- a/doc/user/admin_area/img/index_runners_search_or_filter_v14_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/img/index_runners_search_or_filter_v14_5.png b/doc/user/admin_area/img/index_runners_search_or_filter_v14_5.png
new file mode 100644
index 00000000000..10b8cc01103
--- /dev/null
+++ b/doc/user/admin_area/img/index_runners_search_or_filter_v14_5.png
Binary files differ
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index 27d2bd8f764..4de2397706b 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -107,6 +107,22 @@ You can combine the filter options. For example, to list only public projects wi
1. Click the **Public** tab.
1. Enter `score` in the **Filter by name...** input box.
+#### Deleted projects **(PREMIUM SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37014) in GitLab 13.3.
+
+When delayed project deletion is [enabled for a group](../group/index.md#enable-delayed-project-removal),
+projects within that group are not deleted immediately, but only after a delay. To access a list of all projects that are pending deletion:
+
+1. On the top bar, select **Menu > Projects > Explore projects**.
+1. Select the **Deleted projects** tab.
+
+Listed for each project is:
+
+- The time the project was marked for deletion.
+- The time the project is scheduled for final deletion.
+- A **Restore** link to stop the project being eventually deleted.
+
### Administering Users
You can administer all users in the GitLab instance from the Admin Area's Users page:
@@ -241,21 +257,27 @@ To [Create a new group](../group/index.md#create-a-group) click **New group**.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340920) in GitLab 14.4.
-You can administer all topics in the GitLab instance from the Admin Area's Topics page.
+You can administer all [topics](../project/working_with_projects.md#explore-topics) in the
+GitLab instance from the Admin Area's Topics page.
To access the Topics page:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Overview > Topics**.
-For each topic, the page displays their name and number of projects labeled with the topic.
+For each topic, the page displays its name and the number of projects labeled with the topic.
To create a new topic, select **New topic**.
To edit a topic, select **Edit** in that topic's row.
To search for topics by name, enter your criteria in the search box. The topic search is case
-insensitive, and applies partial matching.
+insensitive and applies partial matching.
+
+NOTE:
+The assigned topics are visible only to everyone with access to the project,
+but everyone can see which topics exist at all on the GitLab instance.
+Do not include sensitive information in the name of a topic.
### Administering Jobs
@@ -309,11 +331,11 @@ To search runners' descriptions:
You can also filter runners by status, type, and tag. To filter:
-1. Click in the **Search or filter results...** field.
-1. Select **Status**, **Type**, or **Tags**.
+1. Select a tab or the **Search or filter results...** field.
+1. Select any **Type**, or filter by **Status** or **Tags**.
1. Select or enter your search criteria.
-![Attributes of a runner, with the **Search or filter results...** field active](img/index_runners_search_or_filter_v14_1.png)
+![Attributes of a runner, with the **Search or filter results...** field active](img/index_runners_search_or_filter_v14_5.png)
For each runner, the following attributes are listed:
diff --git a/doc/user/admin_area/merge_requests_approvals.md b/doc/user/admin_area/merge_requests_approvals.md
index 18151fc17d5..0ecf76902e1 100644
--- a/doc/user/admin_area/merge_requests_approvals.md
+++ b/doc/user/admin_area/merge_requests_approvals.md
@@ -5,34 +5,37 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, concepts
---
-# Merge request approval rules **(PREMIUM SELF)**
+# Merge request approvals **(PREMIUM SELF)**
-> Introduced in [GitLab Premium](https://gitlab.com/gitlab-org/gitlab/-/issues/39060) 12.8.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39060) in GitLab 12.8.
-Merge request approval rules prevent users from overriding certain settings on the project
-level. When enabled at the instance level, these settings are no longer editable on the
-project level.
+Merge request approval rules prevent users from overriding certain settings on the project level.
+When enabled at the instance level, these settings [cascade](../project/merge_requests/approvals/settings.md#settings-cascading)
+and can no longer be changed:
-To enable merge request approval rules for an instance:
+- In projects.
+- In groups. Cascading to groups was [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/285410)
+ in GitLab 14.5.
+
+To enable merge request approval settings for an instance:
1. On the top bar, select **Menu > Admin**.
-1. On the left sidebar, select **{push-rules}** **Push Rules**, and expand **Merge request (MR) approvals**.
-1. Set the required rule.
+1. On the left sidebar, select **{push-rules}** **Push Rules**, and expand **Merge request approvals**.
+1. Choose the required options.
1. Click **Save changes**.
## Available rules
-Merge request approval rules that can be set at an instance level are:
+Merge request approval settings that can be set at an instance level are:
-- **Prevent approval by author**. Prevents project
-maintainers from allowing request authors to merge their own merge requests.
-- **Prevent approvals by users who add commits**. Prevents project
-maintainers from allowing users to approve merge requests if they have submitted
-any commits to the source branch.
-- **Prevent editing approval rules in projects and merge requests**. Prevents users from
-modifying the approvers list in project settings or in individual merge requests.
+- **Prevent approval by author**. Prevents project maintainers from allowing request authors to
+ merge their own merge requests.
+- **Prevent approvals by users who add commits**. Prevents project maintainers from allowing users
+ to approve merge requests if they have submitted any commits to the source branch.
+- **Prevent editing approval rules in projects and merge requests**. Prevents users from modifying
+ the approvers list in project settings or in individual merge requests.
See also the following, which are affected by instance-level rules:
-- [Project-level merge request approval rules](../project/merge_requests/approvals/index.md).
-- [Group-level merge request approval rules](../group/index.md#group-approval-rules) available in GitLab 13.9 and later.
+- [Project merge request approval rules](../project/merge_requests/approvals/index.md).
+- [Group merge request approval rules](../group/index.md#group-approval-rules) available in GitLab 13.9 and later.
diff --git a/doc/user/admin_area/moderate_users.md b/doc/user/admin_area/moderate_users.md
index c8f160f729f..a98250dfc56 100644
--- a/doc/user/admin_area/moderate_users.md
+++ b/doc/user/admin_area/moderate_users.md
@@ -17,7 +17,7 @@ pending approval state because an administrator has enabled any of the following
- [Require admin approval for new sign-ups](settings/sign_up_restrictions.md#require-administrator-approval-for-new-sign-ups) setting.
- [User cap](settings/sign_up_restrictions.md#user-cap).
-- [Block auto-created users (OmniAuth)](../../integration/omniauth.md#initial-omniauth-configuration)
+- [Block auto-created users (OmniAuth)](../../integration/omniauth.md#configure-initial-settings)
- [Block auto-created users (LDAP)](../../administration/auth/ldap/index.md#basic-configuration-settings)
When a user registers for an account while this setting is enabled:
diff --git a/doc/user/admin_area/monitoring/background_migrations.md b/doc/user/admin_area/monitoring/background_migrations.md
index da245300e1d..66001a987a4 100644
--- a/doc/user/admin_area/monitoring/background_migrations.md
+++ b/doc/user/admin_area/monitoring/background_migrations.md
@@ -24,7 +24,7 @@ prevent integer overflow for some tables.
## Check the status of background migrations
All migrations must have a `Finished` status before you [upgrade GitLab](../../../update/index.md).
-You can [check the status of existing migrations](../../../update/index.md#checking-for-background-migrations-before-upgrading).
+You can [check the status of existing migrations](../../../update/index.md#batched-background-migrations).
## Enable or disable batched background migrations
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
index c5ffb032afd..1d2d7be146c 100644
--- a/doc/user/admin_area/monitoring/health_check.md
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -1,8 +1,7 @@
---
-stage: none
-group: unassigned
+stage: Monitor
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: concepts, howto
---
# Health Check **(FREE SELF)**
diff --git a/doc/user/admin_area/settings/account_and_limit_settings.md b/doc/user/admin_area/settings/account_and_limit_settings.md
index 3549aa5323b..c511e85f3ce 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -61,10 +61,15 @@ details.
## Personal Access Token prefix
+> [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/342327) in GitLab 14.5. Default prefix added.
+
You can set a global prefix for all generated Personal Access Tokens.
A prefix can help you identify PATs visually, as well as with automation tools.
+NOTE:
+For GitLab.com and self-managed instances, the default prefix is `glpat-`.
+
### Set a prefix
Only a GitLab administrator can set the prefix, which is a global setting applied
@@ -125,7 +130,7 @@ is rejected.
NOTE:
The repository size limit includes repository files and LFS, but does not include artifacts, uploads,
-wiki, packages, or snippets.
+wiki, packages, or snippets. The repository size limit applies to both private and public projects.
For details on manually purging files, see [reducing the repository size using Git](../../project/repository/reducing_the_repo_size_using_git.md).
@@ -148,7 +153,7 @@ add the line below to `/etc/gitlab/gitlab.rb` before increasing the max attachme
nginx['client_max_body_size'] = "200m"
```
-## Customize session duration for Git Operations when 2FA is enabled **(PREMIUM)**
+## Customize session duration for Git Operations when 2FA is enabled **(PREMIUM SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/296669) in GitLab 13.9.
> - It's deployed behind a feature flag, disabled by default.
@@ -173,7 +178,7 @@ To set a limit on how long these sessions are valid:
## Limit the lifetime of personal access tokens **(ULTIMATE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) in GitLab Ultimate 12.6.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) in GitLab 12.6.
Users can optionally specify a lifetime for
[personal access tokens](../../profile/personal_access_tokens.md).
@@ -222,7 +227,7 @@ Disabling SSH key expiration immediately enables all expired SSH keys.
## Allow expired Personal Access Tokens to be used **(ULTIMATE SELF)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214723) in GitLab Ultimate 13.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214723) in GitLab 13.1.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/296881) in GitLab 13.9.
By default, expired personal access tokens (PATs) **are not usable**.
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index 1b6da0e2806..565e905d732 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -221,7 +221,7 @@ It is also possible to specify a [custom CI/CD configuration file for a specific
By default, a banner displays in merge requests with no pipeline suggesting a
walkthrough on how to add one.
-![Suggest pipeline banner](img/suggest_pipeline_banner.png)
+![Suggest pipeline banner](img/suggest_pipeline_banner_v14_5.png)
To enable or disable the banner:
diff --git a/doc/user/admin_area/settings/deprecated_api_rate_limits.md b/doc/user/admin_area/settings/deprecated_api_rate_limits.md
index a2edb6da86e..9be703f3b82 100644
--- a/doc/user/admin_area/settings/deprecated_api_rate_limits.md
+++ b/doc/user/admin_area/settings/deprecated_api_rate_limits.md
@@ -47,7 +47,7 @@ To override the general user and IP rate limits for requests to deprecated API e
1. Select the **Maximum authenticated API requests per period per user**.
1. Select the **Authenticated API rate limit period in seconds**.
-## Resources
+## Related topics
- [Rate limits](../../../security/rate_limits.md)
- [User and IP rate limits](user_and_ip_rate_limits.md)
diff --git a/doc/user/admin_area/settings/files_api_rate_limits.md b/doc/user/admin_area/settings/files_api_rate_limits.md
index f91d4b2fb0c..4f0f50dbcd2 100644
--- a/doc/user/admin_area/settings/files_api_rate_limits.md
+++ b/doc/user/admin_area/settings/files_api_rate_limits.md
@@ -49,7 +49,7 @@ To override the general user and IP rate limits for requests to the Repository f
1. Select the **Max authenticated API requests per period per user**.
1. Select the **Authenticated API rate limit period in seconds**.
-## Resources
+## Related topics
- [Rate limits](../../../security/rate_limits.md)
- [Repository files API](../../../api/repository_files.md)
diff --git a/doc/user/admin_area/settings/git_lfs_rate_limits.md b/doc/user/admin_area/settings/git_lfs_rate_limits.md
index 8a0754374e2..adc6cc2b11b 100644
--- a/doc/user/admin_area/settings/git_lfs_rate_limits.md
+++ b/doc/user/admin_area/settings/git_lfs_rate_limits.md
@@ -29,7 +29,7 @@ supersede the [general user and IP rate limits](user_and_ip_rate_limits.md):
1. Enter a value for **Authenticated Git LFS rate limit period in seconds**.
1. Select **Save changes**.
-## Resources
+## Related topics
- [Rate limiting](../../../security/rate_limits.md)
- [User and IP rate limits](user_and_ip_rate_limits.md)
diff --git a/doc/user/admin_area/settings/img/suggest_pipeline_banner.png b/doc/user/admin_area/settings/img/suggest_pipeline_banner.png
deleted file mode 100644
index 9f118ccc5ed..00000000000
--- a/doc/user/admin_area/settings/img/suggest_pipeline_banner.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/settings/img/suggest_pipeline_banner_v14_5.png b/doc/user/admin_area/settings/img/suggest_pipeline_banner_v14_5.png
new file mode 100644
index 00000000000..0d9bfa4a173
--- /dev/null
+++ b/doc/user/admin_area/settings/img/suggest_pipeline_banner_v14_5.png
Binary files differ
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index 688734849e5..7945e5d790f 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -7,124 +7,186 @@ type: index
# Admin Area settings **(FREE SELF)**
-As an administrator of a GitLab self-managed instance, you can manage the behavior of your deployment. To do so, select **Admin Area > Settings**.
+As an administrator of a GitLab self-managed instance, you can manage the behavior of your
+deployment.
-The Admin Area is not accessible on GitLab.com, and settings can only be changed by the
-GitLab.com administrators. See the [GitLab.com settings](../../gitlab_com/index.md)
-documentation for all current settings and limits on the GitLab.com instance.
+The **Admin Area** is not accessible on GitLab.com, and settings can only be changed by the
+GitLab.com administrators. For the settings and limits on the GitLab.com instance,
+read [GitLab.com settings](../../gitlab_com/index.md).
-## General
+## Access the Admin Area
-To access the default page for Admin Area settings:
+To access the **Admin Area**:
+1. Sign in to your GitLab instance as an administrator.
1. On the top bar, select **Menu > Admin**.
-1. On the left sidebar, select **Settings > General**.
-
-| Option | Description |
-| ------ | ----------- |
-| [Visibility and access controls](visibility_and_access_controls.md) | Set default and restrict visibility levels. Configure import sources and Git access protocol. |
-| [Account and limit](account_and_limit_settings.md) | Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan. |
-| [Diff limits](../diff_limits.md) | Diff content limits. |
-| [Sign-up restrictions](sign_up_restrictions.md) | Configure the way a user creates a new account. |
-| [Sign in restrictions](sign_in_restrictions.md) | Set requirements for a user to sign in. Enable mandatory two-factor authentication. |
-| [Terms of Service and Privacy Policy](terms.md) | Include a Terms of Service agreement and Privacy Policy that all users must accept. |
-| [External Authentication](external_authorization.md#configuration) | External Classification Policy Authorization |
-| [Web terminal](../../../administration/integration/terminal.md#limiting-websocket-connection-time) | Set max session time for web terminal. |
-| [Web IDE](../../project/web_ide/index.md#enable-live-preview) | Manage Web IDE features. |
-| [FLoC](floc.md) | Enable or disable [Federated Learning of Cohorts (FLoC)](https://en.wikipedia.org/wiki/Federated_Learning_of_Cohorts) tracking. |
-
-## Integrations
-
-| Option | Description |
-| ------ | ----------- |
-| [Elasticsearch](../../../integration/elasticsearch.md#enable-advanced-search) | Elasticsearch integration. Elasticsearch AWS IAM. |
-| [Kroki](../../../administration/integration/kroki.md#enable-kroki-in-gitlab) | Allow rendering of diagrams in AsciiDoc and Markdown documents using [kroki.io](https://kroki.io). |
-| [Mailgun](../../../administration/integration/mailgun.md) | Enable your GitLab instance to receive invite email bounce events from Mailgun, if it is your email provider. |
-| [PlantUML](../../../administration/integration/plantuml.md) | Allow rendering of PlantUML diagrams in documents. |
-| [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) **(FREE SAAS)** | Slack integration allows you to interact with GitLab via slash commands in a chat window. This option is only available on GitLab.com, though it may be [available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164). |
-| [Third party offers](third_party_offers.md) | Control the display of third party offers. |
-| [Snowplow](../../../development/snowplow/index.md) | Configure the Snowplow integration. |
-| [Google GKE](../../project/clusters/add_gke_clusters.md) | Google GKE integration allows you to provision GKE clusters from GitLab. |
-| [Amazon EKS](../../project/clusters/add_eks_clusters.md) | Amazon EKS integration allows you to provision EKS clusters from GitLab. |
-
-## Repository
-
-| Option | Description |
-| ------ | ----------- |
-| [Repository's custom initial branch name](../../project/repository/branches/default.md#instance-level-custom-initial-branch-name) | Set a custom branch name for new repositories created in your instance. |
-| [Repository mirror](visibility_and_access_controls.md#enable-project-mirroring) | Configure repository mirroring. |
-| [Repository storage](../../../administration/repository_storage_types.md) | Configure storage path settings. |
-| Repository maintenance | ([Repository checks](../../../administration/repository_checks.md) and [Housekeeping](../../../administration/housekeeping.md)). Configure automatic Git checks and housekeeping on repositories. |
-| [Repository static objects](../../../administration/static_objects_external_storage.md) | Serve repository static objects (for example, archives and blobs) from an external storage (for example, a CDN). |
-
-## Templates **(PREMIUM SELF)**
-
-| Option | Description |
-| ------ | ----------- |
-| [Templates](instance_template_repository.md#configuration) | Set instance-wide template repository. |
-| [Custom project templates](../custom_project_templates.md) | Select the custom project template source group. |
-
-## CI/CD
-
-| Option | Description |
-| ------ | ----------- |
-| [Continuous Integration and Deployment](continuous_integration.md) | Auto DevOps, runners and job artifacts. |
-| [Required pipeline configuration](continuous_integration.md#required-pipeline-configuration) **(PREMIUM SELF)** | Set an instance-wide auto included [pipeline configuration](../../../ci/yaml/index.md). This pipeline configuration is run after the project's own configuration. |
-| [Package Registry](continuous_integration.md#package-registry-configuration) | Settings related to the use and experience of using the GitLab Package Registry. Note there are [risks involved](../../packages/container_registry/index.md#use-with-external-container-registries) in enabling some of these settings. |
-
-## Reporting
-
-| Option | Description |
-| ------ | ----------- |
-| [Spam and Anti-bot Protection](../../../integration/recaptcha.md) | Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support [v2](https://developers.google.com/recaptcha/docs/versions). |
-| [Abuse reports](../review_abuse_reports.md) | Set notification email for abuse reports. |
-
-## Metrics and profiling
-
-| Option | Description |
-| ------ | ----------- |
-| [Metrics - Prometheus](../../../administration/monitoring/prometheus/gitlab_metrics.md) | Enable and configure Prometheus metrics. |
-| [Metrics - Grafana](../../../administration/monitoring/performance/grafana_configuration.md#integration-with-gitlab-ui) | Enable and configure Grafana. |
-| [Profiling - Performance bar](../../../administration/monitoring/performance/performance_bar.md#enable-the-performance-bar-for-non-administrators) | Enable access to the Performance Bar for non-administrator users in a given group. |
-| [Self monitoring](../../../administration/monitoring/gitlab_self_monitoring_project/index.md#create-the-self-monitoring-project) | Enable or disable instance self monitoring. |
-| [Usage statistics](usage_statistics.md) | Enable or disable version check and Service Ping. |
-| [Pseudonymizer data collection](../../../administration/pseudonymizer.md) **(ULTIMATE)** | Enable or disable the Pseudonymizer data collection. |
-
-## Network
-
-| Option | Description |
-| ------ | ----------- |
-| Performance optimization | [Write to "authorized_keys" file](../../../administration/operations/fast_ssh_key_lookup.md#setting-up-fast-lookup-via-gitlab-shell) and [Push event activities limit and bulk push events](push_event_activities_limit.md). Various settings that affect GitLab performance. |
-| [User and IP rate limits](user_and_ip_rate_limits.md) | Configure limits for web and API requests. |
-| [Package Registry Rate Limits](package_registry_rate_limits.md) | Configure specific limits for Packages API requests that supersede the user and IP rate limits. |
-| [Git LFS Rate Limits](git_lfs_rate_limits.md) | Configure specific limits for Git LFS requests that supersede the user and IP rate limits. |
-| [Files API Rate Limits](files_api_rate_limits.md) | Configure specific limits for Files API requests that supersede the user and IP rate limits. |
-| [Deprecated API Rate Limits](deprecated_api_rate_limits.md) | Configure specific limits for deprecated API requests that supersede the user and IP rate limits. |
-| [Outbound requests](../../../security/webhooks.md) | Allow requests to the local network from hooks and services. |
-| [Protected Paths](protected_paths.md) | Configure paths to be protected by Rack Attack. |
-| [Incident Management](../../../operations/incident_management/index.md) Limits | Limit the number of inbound alerts that can be sent to a project. |
-| [Notes creation limit](rate_limit_on_notes_creation.md)| Set a rate limit on the note creation requests. |
-
-## Geo
-
-| Option | Description |
-| ------ | ----------- |
-| Geo | Geo allows you to replicate your GitLab instance to other geographical locations. Redirects to **Admin Area > Geo > Settings** are no longer available at **Admin Area > Settings > Geo** in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/36896). |
-
-## Preferences
-
-| Option | Description |
-| ------ | ----------- |
-| [Email](email.md) | Various email settings. |
-| [What's new](../../../administration/whats-new.md) | Configure What's new drawer and content. |
-| [Help page](help_page.md) | Help page text and support page URL. |
-| [Pages](../../../administration/pages/index.md#custom-domain-verification) | Size and domain settings for static websites |
-| [Polling interval multiplier](../../../administration/polling.md) | Configure how frequently the GitLab UI polls for updates. |
-| [Gitaly timeouts](gitaly_timeouts.md) | Configure Gitaly timeouts. |
-| Localization | [Default first day of the week](../../profile/preferences.md) and [Time tracking](../../project/time_tracking.md#limit-displayed-units-to-hours). |
-| [Sidekiq Job Limits](sidekiq_job_limits.md) | Limit the size of Sidekiq jobs stored in Redis. |
-
-### Default first day of the week
+1. On the left sidebar, select **Settings**, and the group of settings to view:
+ - [General](#general)
+ - [Geo](#geo)
+ - [CI/CD](#cicd)
+ - [Integrations](#integrations)
+ - [Metrics and profiling](#metrics-and-profiling)
+ - [Network](#network)
+ - [Preferences](#preferences)
+ - [Reporting](#reporting)
+ - [Repository](#repository)
+ - [Templates](#templates)
+
+### General
+
+The **General** settings contain:
+
+- [Visibility and access controls](visibility_and_access_controls.md) - Set default and
+ restrict visibility levels. Configure import sources and Git access protocol.
+- [Account and limit](account_and_limit_settings.md) - Set projects and maximum size limits,
+ session duration, user options, and check feature availability for namespace plan.
+- [Diff limits](../diff_limits.md) - Diff content limits.
+- [Sign-up restrictions](sign_up_restrictions.md) - Configure the way a user creates a new account.
+- [Sign in restrictions](sign_in_restrictions.md) - Set requirements for a user to sign in.
+ Enable mandatory two-factor authentication.
+- [Terms of Service and Privacy Policy](terms.md) - Include a Terms of Service agreement
+ and Privacy Policy that all users must accept.
+- [External Authentication](external_authorization.md#configuration) - External Classification Policy Authorization.
+- [Web terminal](../../../administration/integration/terminal.md#limiting-websocket-connection-time) -
+ Set max session time for web terminal.
+- [Web IDE](../../project/web_ide/index.md#enable-live-preview) - Manage Web IDE features.
+- [FLoC](floc.md) - Enable or disable
+ [Federated Learning of Cohorts (FLoC)](https://en.wikipedia.org/wiki/Federated_Learning_of_Cohorts) tracking.
+
+### CI/CD
+
+The **CI/CD** settings contain:
+
+- [Continuous Integration and Deployment](continuous_integration.md) -
+ Auto DevOps, runners and job artifacts.
+- [Required pipeline configuration](continuous_integration.md#required-pipeline-configuration) -
+ Set an instance-wide auto included [pipeline configuration](../../../ci/yaml/index.md).
+ This pipeline configuration is run after the project's own configuration.
+- [Package Registry](continuous_integration.md#package-registry-configuration) -
+ Settings related to the use and experience of using the GitLab Package Registry. Some
+ [risks are involved](../../packages/container_registry/index.md#use-with-external-container-registries)
+ in enabling some of these settings.
+
+### Geo **(PREMIUM SELF)**
+
+The **Geo** setting contains:
+
+- [Geo](../../../administration/geo/index.md) - Replicate your GitLab instance to other
+ geographical locations. Redirects to **Admin Area > Geo > Settings** are no
+ longer available at **Admin Area > Settings > Geo** in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/36896).
+
+### Integrations
+
+The **Integrations** settings contain:
+
+- [Elasticsearch](../../../integration/elasticsearch.md#enable-advanced-search) -
+ Elasticsearch integration. Elasticsearch AWS IAM.
+- [Kroki](../../../administration/integration/kroki.md#enable-kroki-in-gitlab) -
+ Allow rendering of diagrams in AsciiDoc and Markdown documents using [kroki.io](https://kroki.io).
+- [Mailgun](../../../administration/integration/mailgun.md) - Enable your GitLab instance
+ to receive invite email bounce events from Mailgun, if it is your email provider.
+- [PlantUML](../../../administration/integration/plantuml.md) - Allow rendering of PlantUML
+ diagrams in documents.
+- [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) -
+ Slack integration allows you to interact with GitLab via slash commands in a chat window.
+ This option is only available on GitLab.com, though it may be
+ [available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164).
+- [Third party offers](third_party_offers.md) - Control the display of third-party offers.
+- [Snowplow](../../../development/snowplow/index.md) - Configure the Snowplow integration.
+- [Google GKE](../../project/clusters/add_gke_clusters.md) - Google GKE integration enables
+ you to provision GKE clusters from GitLab.
+- [Amazon EKS](../../project/clusters/add_eks_clusters.md) - Amazon EKS integration enables
+ you to provision EKS clusters from GitLab.
+
+### Metrics and profiling
+
+The **Metrics and profiling** settings contain:
+
+- [Metrics - Prometheus](../../../administration/monitoring/prometheus/gitlab_metrics.md) -
+ Enable and configure Prometheus metrics.
+- [Metrics - Grafana](../../../administration/monitoring/performance/grafana_configuration.md#integration-with-gitlab-ui) -
+ Enable and configure Grafana.
+- [Profiling - Performance bar](../../../administration/monitoring/performance/performance_bar.md#enable-the-performance-bar-for-non-administrators) -
+ Enable access to the Performance Bar for non-administrator users in a given group.
+- [Self monitoring](../../../administration/monitoring/gitlab_self_monitoring_project/index.md#create-the-self-monitoring-project) -
+ Enable or disable instance self monitoring.
+- [Usage statistics](usage_statistics.md) - Enable or disable version check and Service Ping.
+- [Pseudonymizer data collection](../../../administration/pseudonymizer.md) -
+ Enable or disable the Pseudonymizer data collection.
+
+### Network
+
+The **Network** settings contain:
+
+- Performance optimization - Various settings that affect GitLab performance, including:
+ - [Write to `authorized_keys` file](../../../administration/operations/fast_ssh_key_lookup.md#setting-up-fast-lookup-via-gitlab-shell).
+ - [Push event activities limit and bulk push events](push_event_activities_limit.md).
+- [User and IP rate limits](user_and_ip_rate_limits.md) - Configure limits for web and API requests.
+ These rate limits can be overridden:
+ - [Package Registry Rate Limits](package_registry_rate_limits.md) - Configure specific
+ limits for Packages API requests that supersede the user and IP rate limits.
+ - [Git LFS Rate Limits](git_lfs_rate_limits.md) - Configure specific limits for
+ Git LFS requests that supersede the user and IP rate limits.
+ - [Files API Rate Limits](files_api_rate_limits.md) - Configure specific limits for
+ Files API requests that supersede the user and IP rate limits.
+ - [Deprecated API Rate Limits](deprecated_api_rate_limits.md) - Configure specific limits
+ for deprecated API requests that supersede the user and IP rate limits.
+- [Outbound requests](../../../security/webhooks.md) - Allow requests to the local network from hooks and services.
+- [Protected Paths](protected_paths.md) - Configure paths to be protected by Rack Attack.
+- [Incident Management Limits](../../../operations/incident_management/index.md) - Limit the
+ number of inbound alerts that can be sent to a project.
+- [Notes creation limit](rate_limit_on_notes_creation.md) - Set a rate limit on the note creation requests.
+
+### Preferences
+
+The **Preferences** settings contain:
+
+- [Email](email.md) - Various email settings.
+- [What's new](../../../administration/whats-new.md) - Configure **What's new** drawer and content.
+- [Help page](help_page.md) - Help page text and support page URL.
+- [Pages](../../../administration/pages/index.md#custom-domain-verification) -
+ Size and domain settings for static websites.
+- [Polling interval multiplier](../../../administration/polling.md) -
+ Configure how frequently the GitLab UI polls for updates.
+- [Gitaly timeouts](gitaly_timeouts.md) - Configure Gitaly timeouts.
+- Localization:
+ - [Default first day of the week](../../profile/preferences.md).
+ - [Time tracking](../../project/time_tracking.md#limit-displayed-units-to-hours).
+- [Sidekiq Job Limits](sidekiq_job_limits.md) - Limit the size of Sidekiq jobs stored in Redis.
+
+### Reporting
+
+The **Reporting** settings contain:
+
+- [Spam and Anti-bot Protection](../../../integration/recaptcha.md) -
+ Enable anti-spam services, like reCAPTCHA or Akismet, and set IP limits.
+- [Abuse reports](../review_abuse_reports.md) - Set notification email for abuse reports.
+
+### Repository
+
+The **Repository** settings contain:
+
+- [Repository's custom initial branch name](../../project/repository/branches/default.md#instance-level-custom-initial-branch-name) -
+ Set a custom branch name for new repositories created in your instance.
+- [Repository mirror](visibility_and_access_controls.md#enable-project-mirroring) -
+ Configure repository mirroring.
+- [Repository storage](../../../administration/repository_storage_types.md) - Configure storage path settings.
+- Repository maintenance:
+ - [Repository checks](../../../administration/repository_checks.md) - Configure
+ automatic Git checks on repositories.
+ - [Housekeeping](../../../administration/housekeeping.md)). Configure automatic
+ Git housekeeping on repositories.
+- [Repository static objects](../../../administration/static_objects_external_storage.md) -
+ Serve repository static objects (for example, archives and blobs) from an external storage (for example, a CDN).
+
+### Templates **(PREMIUM SELF)**
+
+The **Templates** settings contain:
+
+- [Templates](instance_template_repository.md#configuration) - Set instance-wide template repository.
+- [Custom project templates](../custom_project_templates.md) - Select the custom project template source group.
+
+## Default first day of the week
You can change the [Default first day of the week](../../profile/preferences.md)
for the entire GitLab instance:
diff --git a/doc/user/admin_area/settings/instance_template_repository.md b/doc/user/admin_area/settings/instance_template_repository.md
index 044863729db..71eb7bbbdc9 100644
--- a/doc/user/admin_area/settings/instance_template_repository.md
+++ b/doc/user/admin_area/settings/instance_template_repository.md
@@ -7,7 +7,7 @@ type: reference
# Instance template repository **(PREMIUM SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5986) in GitLab Premium 11.3.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5986) in GitLab 11.3.
In hosted systems, enterprises often have a need to share their own templates
across teams. This feature allows an administrator to pick a project to be the
diff --git a/doc/user/admin_area/settings/protected_paths.md b/doc/user/admin_area/settings/protected_paths.md
index dc328fe8b7c..e686c65fe9a 100644
--- a/doc/user/admin_area/settings/protected_paths.md
+++ b/doc/user/admin_area/settings/protected_paths.md
@@ -7,28 +7,11 @@ type: reference
# Protected paths **(FREE SELF)**
-Rate limiting is a common technique used to improve the security and durability
-of a web application. For more details, see
-[Rate limits](../../../security/rate_limits.md).
+Rate limiting is a technique that improves the security and durability of a web
+application. For more details, see [Rate limits](../../../security/rate_limits.md).
-GitLab rate limits the following paths with Rack Attack by default:
-
-```plaintext
-'/users/password',
-'/users/sign_in',
-'/api/#{API::API.version}/session.json',
-'/api/#{API::API.version}/session',
-'/users',
-'/users/confirmation',
-'/unsubscribes/',
-'/import/github/personal_access_token',
-'/admin/session'
-```
-
-GitLab responds with HTTP status code `429` to POST requests at protected paths
-that exceed 10 requests per minute per IP address.
-
-See [User and IP rate limits](../../admin_area/settings/user_and_ip_rate_limits.md#response-headers) for the headers responded to blocked requests.
+You can rate limit (protect) specified paths. For these paths, GitLab responds with HTTP status
+code `429` to POST requests at protected paths that exceed 10 requests per minute per IP address.
For example, the following are limited to a maximum 10 requests per minute:
@@ -36,10 +19,15 @@ For example, the following are limited to a maximum 10 requests per minute:
- User sign-up (if enabled)
- User password reset
-After 10 requests, the client must wait 60 seconds before it can
-try again.
+After 10 requests, the client must wait 60 seconds before it can try again.
+
+See also:
+
+- List of paths [protected by default](../../../administration/instance_limits.md#by-protected-path).
+- [User and IP rate limits](../../admin_area/settings/user_and_ip_rate_limits.md#response-headers)
+ for the headers returned to blocked requests.
-## Configure using GitLab UI
+## Configure protected paths
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31246) in GitLab 12.4.
diff --git a/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md b/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
index 020d02b1635..028d5e4c2f3 100644
--- a/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
+++ b/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
@@ -7,7 +7,7 @@ type: reference
# Rate limits on raw endpoints **(FREE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30829) in GitLab 12.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30635) in GitLab 12.2.
This setting defaults to `300` requests per minute, and allows you to rate limit the requests to raw endpoints:
@@ -21,7 +21,7 @@ For example, requests over `300` per minute to `https://gitlab.com/gitlab-org/gi
This limit is:
-- Applied independently per project, per commit and per file path.
+- Applied independently per project, per file path.
- Not applied per IP address.
- Active by default. To disable, set the option to `0`.
diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md
index ed80bca470e..8ce3b4f1c18 100644
--- a/doc/user/admin_area/settings/sign_up_restrictions.md
+++ b/doc/user/admin_area/settings/sign_up_restrictions.md
@@ -48,7 +48,7 @@ automatically approved in a background job.
NOTE:
This setting doesn't apply to LDAP or OmniAuth users. To enforce approvals for new users
signing up using OmniAuth or LDAP, set `block_auto_created_users` to `true` in the
-[OmniAuth configuration](../../../integration/omniauth.md#initial-omniauth-configuration) or
+[OmniAuth configuration](../../../integration/omniauth.md#configure-initial-settings) or
[LDAP configuration](../../../administration/auth/ldap/index.md#basic-configuration-settings).
## Require email confirmation
diff --git a/doc/user/admin_area/settings/terms.md b/doc/user/admin_area/settings/terms.md
index c7c41e665ec..693b3e6c7b6 100644
--- a/doc/user/admin_area/settings/terms.md
+++ b/doc/user/admin_area/settings/terms.md
@@ -28,13 +28,13 @@ To enforce acceptance of a Terms of Service and Privacy Policy:
For each update to the terms, a new version is stored. When a user accepts or declines the terms,
GitLab records which version they accepted or declined.
+Existing users must accept the terms on their next GitLab interaction.
+If a signed-in user declines the terms, they are signed out.
+
When enabled, it adds a mandatory checkbox to the sign up page for new users:
![Sign up form](img/sign_up_terms.png)
-Existing users must accept the terms on their next GitLab interaction.
-If a logged-in user declines the terms, they are signed out.
-
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/admin_area/settings/user_and_ip_rate_limits.md b/doc/user/admin_area/settings/user_and_ip_rate_limits.md
index ac6fe29da28..d713ef4b4e0 100644
--- a/doc/user/admin_area/settings/user_and_ip_rate_limits.md
+++ b/doc/user/admin_area/settings/user_and_ip_rate_limits.md
@@ -76,7 +76,9 @@ To enable the unauthenticated request rate limit:
## Use a custom rate limit response
-A request that exceeds a rate limit returns a 429 response code and a
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50693) in GitLab 13.8.
+
+A request that exceeds a rate limit returns a `429` response code and a
plain-text body, which by default is `Retry later`.
To use a custom response:
@@ -88,7 +90,7 @@ To use a custom response:
## Response headers
-> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/731) in GitLab 13.8, the `Rate-Limit` headers. `Retry-After` was introduced in an earlier version.
+> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/731) in GitLab 13.8, the `RateLimit` headers. `Retry-After` was introduced in an earlier version.
When a client exceeds the associated rate limit, the following requests are
blocked. The server may respond with rate-limiting information allowing the
diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md
index 075becfd32f..fd44d6445cf 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -68,7 +68,7 @@ GitLab administrators can still update the default branch protection of a group.
## Define which roles can create projects
Instance-level protections for project creation define which roles can
-[add projects to a group](../../group/index.md#specify-who-can-add-projects-to-a-group)]
+[add projects to a group](../../group/index.md#specify-who-can-add-projects-to-a-group)
on the instance. To alter which roles have permission to create projects:
1. Sign in to GitLab as a user with [Administrator role](../../permissions.md).
diff --git a/doc/user/analytics/ci_cd_analytics.md b/doc/user/analytics/ci_cd_analytics.md
index 4a42133c308..e949f968c2b 100644
--- a/doc/user/analytics/ci_cd_analytics.md
+++ b/doc/user/analytics/ci_cd_analytics.md
@@ -21,6 +21,12 @@ View pipeline duration history:
![Pipeline duration](img/pipelines_duration_chart.png)
+Pipeline statistics are gathered by collecting all available pipelines for the
+project regardless of status. The data available for each individual day is based
+on when the pipeline was created. The total pipeline calculation includes child
+pipelines and pipelines that failed with invalid YAML. If you are interested in
+filtering pipelines based on other attributes, consider using the [Pipelines API](../../api/pipelines.md#list-project-pipelines).
+
## DevOps Research and Assessment (DORA) key metrics **(ULTIMATE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275991) in GitLab 13.7.
diff --git a/doc/user/analytics/code_review_analytics.md b/doc/user/analytics/code_review_analytics.md
index fe091fc9899..496e768456f 100644
--- a/doc/user/analytics/code_review_analytics.md
+++ b/doc/user/analytics/code_review_analytics.md
@@ -22,7 +22,7 @@ Initially, no data appears. Data is populated as users comment on open merge req
## Overview
-Code Review Analytics is available to users with Reporter access and above, and displays a table of open merge requests that have at least one non-author comment. The review time is measured from the time the first non-author comment was submitted.
+Code Review Analytics is available to users with at least the Reporter [role](../permissions.md), and displays a table of open merge requests that have at least one non-author comment. The review time is measured from the time the first non-author comment was submitted.
To access Code Review Analytics, from your project's menu, go to **Analytics > Code Review**.
diff --git a/doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.png b/doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.png
new file mode 100644
index 00000000000..649416c02c0
--- /dev/null
+++ b/doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.png
Binary files differ
diff --git a/doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.png b/doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.png
new file mode 100644
index 00000000000..b5d0dd4d2ea
--- /dev/null
+++ b/doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.png
Binary files differ
diff --git a/doc/user/analytics/img/productivity_analytics_trendline_v14_4.png b/doc/user/analytics/img/productivity_analytics_trendline_v14_4.png
new file mode 100644
index 00000000000..da5d3aec957
--- /dev/null
+++ b/doc/user/analytics/img/productivity_analytics_trendline_v14_4.png
Binary files differ
diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md
index c01788f4fc4..0cc21e3f390 100644
--- a/doc/user/analytics/index.md
+++ b/doc/user/analytics/index.md
@@ -6,65 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Analyze GitLab usage **(FREE)**
-## Definitions
-
-When we describe GitLab analytics, we use the following terms:
-
-- **Cycle time:** The duration of only the execution work. Cycle time is often displayed in combination with the lead time, which is longer than the cycle time. GitLab measures cycle time from the earliest commit of a [linked issue's merge request](../project/issues/crosslinking_issues.md) to when that issue is closed. The cycle time approach underestimates the lead time because merge request creation is always later than commit time. GitLab displays cycle time in [group-level Value Stream Analytics](../group/value_stream_analytics/index.md) and [project-level Value Stream Analytics](../analytics/value_stream_analytics.md).
-- **Deploys:** The total number of successful deployments to production in the given time frame (across all applicable projects). GitLab displays deploys in [group-level Value Stream Analytics](../group/value_stream_analytics/index.md) and [project-level Value Stream Analytics](value_stream_analytics.md).
-- **DORA (DevOps Research and Assessment)** ["Four Keys"](https://cloud.google.com/blog/products/devops-sre/using-the-four-keys-to-measure-your-devops-performance):
- - **Speed/Velocity**
-
- - **Deployment frequency:** The relative frequency of successful deployments to production
- (hourly, daily, weekly, monthly, or yearly).
- This effectively measures how often you are delivering value to end users. A higher deployment
- frequency means you are able to get feedback and iterate more quickly in delivering
- improvements and features faster. GitLab measures this as the number of deployments to a
- [production environment](../../ci/environments/index.md#deployment-tier-of-environments) in
- the given time period.
- GitLab displays deployment frequency in [group-level Value Stream Analytics](../group/value_stream_analytics/index.md) and [project-level Value Stream Analytics](value_stream_analytics.md).
- - **Lead Time for Changes:** The time it takes for a commit to get into production. (1) GitLab
- measures this as the median duration between merge request merge and deployment to a
- [production environment](../../ci/environments/index.md#deployment-tier-of-environments) for
- all MRs deployed in the given time period. This measure under-estimates lead time because
- merge time is always later than commit time. The
- [standard definition](https://github.com/GoogleCloudPlatform/fourkeys/blob/main/METRICS.md#lead-time-for-changes) uses median commit time.
- [An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/328459) to start
- measuring from "issue first commit" as a better proxy, although still imperfect.
-
- - **Stability**
- - **Change Failure Rate:** The percentage of deployments causing a failure in production.
- GitLab measures this as the number of [incidents](../../operations/incident_management/incidents.md)
- divided by the number of deployments to a
- [production environment](../../ci/environments/index.md#deployment-tier-of-environments) in
- the given time period. This assumes:
-
- - All incidents are related to a production environment.
- - Incidents and deployments have a strictly one-to-one relationship (meaning any incident is
- related to only one production deployment, and any production deployment is related to no
- more than one incident).
-
- - **Time to Restore Service:** How long it takes an organization to recover from a failure in
- production. GitLab measures this as the average time required to close the
- [incidents](../../operations/incident_management/incidents.md) in the given time period.
- This assumes:
-
- - All incidents are related to a [production environment](../../ci/environments/index.md#deployment-tier-of-environments).
- - Incidents and deployments have a strictly one-to-one relationship (meaning any incident is related to only one production deployment, and any production deployment is related to no more than one incident).
-
-- **Lead time:** The duration of your value stream, from start to finish. Different from [Lead time for changes](#lead-time-for-changes). Often displayed in combination with "cycle time," which is shorter. GitLab measures lead time from issue creation to issue close. GitLab displays lead time in [group-level Value Stream Analytics](../group/value_stream_analytics/index.md).
-- **MTTC (Mean Time to Change):** The average duration between idea and delivery. GitLab measures MTTC from issue creation to the issue's latest related merge request's deployment to production.
-- **MTTD (Mean Time to Detect):** The average duration that a bug goes undetected in production. GitLab measures MTTD from deployment of bug to issue creation.
-- **MTTM (Mean Time To Merge):** The average lifespan of a merge request. GitLab measures MTTM from merge request creation to merge request merge (and closed/un-merged merge requests are excluded). For more information, see [Merge Request Analytics](merge_request_analytics.md).
-- **MTTR (Mean Time to Recover/Repair/Resolution/Resolve/Restore):** The average duration that a bug is not fixed in production. GitLab measures MTTR from deployment of bug to deployment of fix.
-- **Throughput:** The number of issues closed or merge requests merged (not closed) in some period of time. Often measured per sprint. GitLab displays merge request throughput in [Merge Request Analytics](merge_request_analytics.md).
-- **Value Stream:** The entire work process that is followed to deliver value to customers. For example, the [DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/) is a value stream that starts with "plan" and ends with "monitor". GitLab helps you track your value stream using [Value Stream Analytics](value_stream_analytics.md).
-- **Velocity:** The total issue burden completed in some period of time. The burden is usually measured in points or weight, often per sprint. For example, your velocity may be "30 points per sprint". GitLab measures velocity as the total points/weight of issues closed in a given period of time.
-
-### Lead time for changes
-
-"Lead Time for Changes" differs from ordinary "Lead Time" because it "focuses on measuring only the time to deliver a feature once it has been developed", as described in ([Measuring DevOps Performance](https://devops.com/measuring-devops-performance/)).
-
## Instance-level analytics
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12077) in GitLab 12.2.
@@ -112,3 +53,76 @@ The following analytics features are available for users to create personalized
- [Application Security](../application_security/security_dashboard/#security-center)
Be sure to review the documentation page for this feature for GitLab tier requirements.
+
+## Definitions
+
+We use the following terms to describe GitLab analytics:
+
+- **Cycle time:** The duration of only the execution work. Cycle time is often displayed in combination with the lead time, which is longer than the cycle time. GitLab measures cycle time from the earliest commit of a [linked issue's merge request](../project/issues/crosslinking_issues.md) to when that issue is closed. The cycle time approach underestimates the lead time because merge request creation is always later than commit time. GitLab displays cycle time in [group-level Value Stream Analytics](../group/value_stream_analytics/index.md) and [project-level Value Stream Analytics](../analytics/value_stream_analytics.md).
+- **Deploys:** The total number of successful deployments to production in the given time frame (across all applicable projects). GitLab displays deploys in [group-level Value Stream Analytics](../group/value_stream_analytics/index.md) and [project-level Value Stream Analytics](value_stream_analytics.md).
+- **DORA (DevOps Research and Assessment)** ["Four Keys"](https://cloud.google.com/blog/products/devops-sre/using-the-four-keys-to-measure-your-devops-performance):
+ - **Speed/Velocity**
+
+ - **Deployment frequency:** The relative frequency of successful deployments to production
+ (hourly, daily, weekly, monthly, or yearly).
+ This measures how often you are delivering value to end users. A higher deployment
+ frequency means you are able to get feedback and iterate faster to deliver
+ improvements and features. GitLab measures this as the number of deployments to a
+ [production environment](../../ci/environments/index.md#deployment-tier-of-environments) in
+ the given time period.
+ GitLab displays deployment frequency in [group-level Value Stream Analytics](../group/value_stream_analytics/index.md) and [project-level Value Stream Analytics](value_stream_analytics.md).
+ - **Lead Time for Changes:** The time it takes for a commit to get into production. GitLab
+ measures this as the median duration between merge request merge and deployment to a
+ [production environment](../../ci/environments/index.md#deployment-tier-of-environments) for
+ all MRs deployed in the given time period. This measure under estimates lead time because
+ merge time is always later than commit time. The
+ [standard definition](https://github.com/GoogleCloudPlatform/fourkeys/blob/main/METRICS.md#lead-time-for-changes) uses median commit time.
+ [An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/328459) to start
+ measuring from "issue first commit" as a better proxy, although still imperfect.
+
+ - **Stability**
+ - **Change Failure Rate:** The percentage of deployments causing a failure in production.
+ GitLab measures this as the number of [incidents](../../operations/incident_management/incidents.md)
+ divided by the number of deployments to a
+ [production environment](../../ci/environments/index.md#deployment-tier-of-environments) in
+ the given time period. This assumes:
+
+ - All incidents are related to a production environment.
+ - Incidents and deployments have a strictly one-to-one relationship (meaning any incident is
+ related to only one production deployment, and any production deployment is related to no
+ more than one incident).
+
+ - **Time to Restore Service:** How long it takes an organization to recover from a failure in
+ production. GitLab measures this as the average time required to close the
+ [incidents](../../operations/incident_management/incidents.md) in the given time period.
+ This assumes:
+
+ - All incidents are related to a [production environment](../../ci/environments/index.md#deployment-tier-of-environments).
+ - Incidents and deployments have a strictly one-to-one relationship (meaning any incident is related to only one production deployment, and any production deployment is related to no more than one incident).
+
+- **Lead time:** The duration of your value stream, from start to finish. Different to
+[Lead time for changes](#lead-time-for-changes). Often displayed in combination with "cycle time,"
+which is shorter. GitLab measures lead time from issue creation to issue close. GitLab displays lead
+time in [group-level Value Stream Analytics](../group/value_stream_analytics/index.md).
+- **Mean Time to Change (MTTC):** The average duration between idea and delivery. GitLab measures
+MTTC from issue creation to the issue's latest related merge request's deployment to production.
+- **Mean Time to Detect (MTTD):** The average duration that a bug goes undetected in production.
+GitLab measures MTTD from deployment of bug to issue creation.
+- **Mean Time To Merge (MTTM):** The average lifespan of a merge request. GitLab measures MTTM from
+merge request creation to merge request merge (and closed/un-merged merge requests are excluded).
+For more information, see [Merge Request Analytics](merge_request_analytics.md).
+- **Mean Time to Recover/Repair/Resolution/Resolve/Restore (MTTR):** The average duration that a bug
+is not fixed in production. GitLab measures MTTR from deployment of bug to deployment of fix.
+- **Throughput:** The number of issues closed or merge requests merged (not closed) in a period of
+time. Often measured per sprint. GitLab displays merge request throughput in [Merge Request Analytics](merge_request_analytics.md).
+- **Value Stream:** The entire work process that is followed to deliver value to customers. For example,
+the [DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/) is a value stream that starts
+with "plan" and ends with "monitor". GitLab helps you track your value stream using [Value Stream Analytics](value_stream_analytics.md).
+- **Velocity:** The total issue burden completed in some period of time. The burden is usually measured
+in points or weight, often per sprint. For example, your velocity may be "30 points per sprint". GitLab
+measures velocity as the total points or weight of issues closed in a given period of time.
+
+## Lead time for changes
+
+"Lead Time for Changes" differs from "Lead Time" because it "focuses on measuring only the time to
+deliver a feature once it has been developed", as described in ([Measuring DevOps Performance](https://devops.com/measuring-devops-performance/)).
diff --git a/doc/user/analytics/merge_request_analytics.md b/doc/user/analytics/merge_request_analytics.md
index 2ff15c00a3f..bb110ab495f 100644
--- a/doc/user/analytics/merge_request_analytics.md
+++ b/doc/user/analytics/merge_request_analytics.md
@@ -116,4 +116,4 @@ bookmark for those preferred settings in your browser.
The **Merge Request Analytics** feature can be accessed only:
- On [GitLab Premium](https://about.gitlab.com/pricing/) and above.
-- By users with [Reporter access](../permissions.md) and above.
+- By users with at least the Reporter [role](../permissions.md).
diff --git a/doc/user/analytics/productivity_analytics.md b/doc/user/analytics/productivity_analytics.md
index dbe71d5f743..da55a0f093c 100644
--- a/doc/user/analytics/productivity_analytics.md
+++ b/doc/user/analytics/productivity_analytics.md
@@ -16,37 +16,79 @@ long, on average, it takes to deliver features is an enormous endeavor.
While [Value Stream Analytics](../analytics/value_stream_analytics.md) focuses on the entire
Software Development Life Cycle (SDLC) process, Productivity Analytics provides a way for Engineering Management to drill down in a systematic way to uncover patterns and causes for success or failure at an individual, project, or group level.
-Productivity can slow down for many reasons ranging from degrading codebase to quickly growing teams. In order to investigate, department or team leaders can start by visualizing the time it takes for merge requests to be merged.
+Productivity can slow down for many reasons ranging from degrading codebase to quickly growing teams. To investigate, department or team leaders can start by visualizing the time it takes for merge requests to be merged.
-## Supported features
+## Visualizations and metrics
-Productivity Analytics allows GitLab users to:
+With Productivity Analytics, GitLab users can:
-- Visualize typical merge request (MR) lifetime and statistics. Use a histogram that shows the distribution of the time elapsed between creating and merging merge requests.
-- Drill down into the most time consuming merge requests, select a number of outliers, and filter down all subsequent charts to investigate potential causes.
+- Visualize typical merge request (MR) lifetime and statistics. A histogram shows the distribution of the time elapsed between creating and merging merge requests.
+- Drill down into the most time consuming merge requests, select outliers, and filter subsequent charts to investigate potential causes.
- Filter by group, project, author, label, milestone, or a specific date range. For example, filter down to the merge requests of a specific author in a group or project during a milestone or specific date range.
-- Measure velocity over time. Visualize the trends of each metric from the charts above over time in order to observe progress. Zoom in on a particular date range if you notice outliers.
+- Measure velocity over time. To observe progress, visualize the trends of each metric from the charts over time. Zoom in on a particular date range if you notice outliers.
-## Accessing metrics and visualizations
+## Metrics charts
-To access the chart, navigate to a group's sidebar and select **Analytics > Productivity Analytics**.
+To access the charts, navigate to a group's sidebar and select **Analytics > Productivity Analytics**.
+Metrics and visualizations of **merged** merge requests are available on a project or group level.
-The following metrics and visualizations are available on a project or group level - currently only covering **merged** merge requests:
+### Time to merge
-- Histogram showing the number of merge request that took a specified number of days to merge after creation. Select a specific column to filter down subsequent charts.
-- Histogram showing a breakdown of the time taken (in hours) to merge a merge request. The following intervals are available:
- - Time from first commit to first comment.
- - Time from first comment until last commit.
- - Time from last commit to merge.
-- Histogram showing the size or complexity of a merge request, using the following:
- - Number of commits per merge request.
- - Number of lines of code per commit.
- - Number of files touched.
-- Scatterplot showing all MRs merged on a certain date, together with the days it took to complete the action and a 30 day rolling median.
-- Table showing the list of merge requests with their respective time duration metrics.
- - Users can sort by any of the above metrics.
+The **Time to merge** histogram shows the number of merge requests and the number
+of days it took to merge after creation. Select a column to filter subsequent charts.
-## Date ranges
+![Metrics for number of days merge requests per number of days](img/productivity_analytics_time_to_merge_v14_4.png)
+
+### Trendline
+
+The **Trendline** scatterplot shows all merge requests on a certain date,
+and the days it took to complete the action and a 30 day rolling median. Select the dropdown to view:
+
+- Time from first commit to first comment.
+- Time from first comment until last commit.
+- Time from last commit to merge.
+- Number of commits per merge request.
+- Number of lines of code (LOC) per commit.
+- Number of files touched.
+
+![Metrics for amount of merge requests merged on a certain date](img/productivity_analytics_trendline_v14_4.png)
+
+### Commits and merge request size
+
+Under the **Trendline** scatterplot, the left-side histogram shows
+the time taken (in hours) between commits and comments until the merge
+request is merged. Select the dropdown to view:
+
+- Time from first commit to first comment.
+- Time from first comment until last commit.
+- Time from last commit to merge.
+
+The right-side histogram shows the size or complexity of a merge request.
+Select the dropdown to view:
+
+- Number of commits per merge request.
+- Number of lines of code (LOC) per commit.
+- Number of files touched.
+
+![Metrics for amount of commits and complexity of changes per merge request.](img/product_analytics_commits_per_mr_v14_4.png)
+
+### Merge request list
+
+The **List** table shows a list of merge requests with their respective time duration metrics.
+
+Sort metrics by:
+
+- Time from first commit to first comment.
+- Time from first comment until last commit.
+- Time from last commit to merge.
+
+Filter metrics by:
+
+- Number of commits per merge request.
+- Number of lines of code per commit.
+- Number of files touched.
+
+## Filter by date range
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13188) in GitLab 12.4.
@@ -61,4 +103,4 @@ You can filter analytics based on a date range. To filter results:
The **Productivity Analytics** dashboard can be accessed only:
- On [GitLab Premium](https://about.gitlab.com/pricing/) and above.
-- By users with [Reporter access](../permissions.md) and above.
+- By users with at least the Reporter [role](../permissions.md).
diff --git a/doc/user/analytics/repository_analytics.md b/doc/user/analytics/repository_analytics.md
index e8f8acf5661..936504187b4 100644
--- a/doc/user/analytics/repository_analytics.md
+++ b/doc/user/analytics/repository_analytics.md
@@ -29,7 +29,7 @@ Commits in a project's [wiki](../project/wiki/index.md#track-wiki-events) are no
### Charts
-The data in the charts are updated soon after each commit in the default branch.
+The data in the charts are queued. Background workers update the charts 10 minutes after each commit in the default branch. Depending on the size of the GitLab installation, it may take longer for data to refresh due to variations in the size of background job queues.
Available charts:
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
index e32989c2915..5cef0040ac3 100644
--- a/doc/user/application_security/api_fuzzing/index.md
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -111,12 +111,9 @@ To generate an API Fuzzing configuration snippet:
### OpenAPI Specification
-> Support for OpenAPI Specification v3.1 was
-> [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327268) in GitLab 14.2.
-> Support for OpenAPI Specification using YAML format was
-> [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330583) in GitLab 14.0.
-> Support for OpenAPI Specification v3.0 was
-> [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/228652) in GitLab 13.9.
+> - Support for OpenAPI Specification v3.0 was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/228652) in GitLab 13.9.
+> - Support for OpenAPI Specification using YAML format was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330583) in GitLab 14.0.
+> - Support for OpenAPI Specification v3.1 was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327268) in GitLab 14.2.
The [OpenAPI Specification](https://www.openapis.org/) (formerly the Swagger Specification) is an API description format for REST APIs.
This section shows you how to configure API fuzzing using an OpenAPI Specification to provide information about the target API to test.
@@ -214,7 +211,7 @@ To configure API fuzzing to use a HAR file:
```
1. Provide the location of the HAR specification. You can provide the specification as a file
- or URL. [URL support was introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285020)
+ or URL. URL support was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285020)
in GitLab 13.10 and later. Specify the location by adding the `FUZZAPI_HAR` variable.
1. The target API instance's base URL is also required. Provide it by using the `FUZZAPI_TARGET_URL`
@@ -285,7 +282,7 @@ To configure API fuzzing to use a Postman Collection file:
```
1. Provide the location of the Postman Collection specification. You can provide the specification
- as a file or URL. [URL support was introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285020)
+ as a file or URL. URL support was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285020)
in GitLab 13.10 and later. Specify the location by adding the `FUZZAPI_POSTMAN_COLLECTION`
variable.
@@ -613,15 +610,15 @@ Overrides use a JSON document, where each type of override is represented by a J
},
"body-form": {
"form-param1": "value",
- "form-param1": "value",
+ "form-param2": "value"
},
"body-json": {
"json-path1": "value",
- "json-path2": "value",
+ "json-path2": "value"
},
"body-xml" : {
"xpath1": "value",
- "xpath2": "value",
+ "xpath2": "value"
}
}
```
@@ -975,7 +972,7 @@ reported.
### View details of an API Fuzzing vulnerability
-> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.7.
+> Introduced in GitLab 13.7.
Faults detected by API Fuzzing occur in the live web application, and require manual investigation
to determine if they are vulnerabilities. Fuzzing faults are included as vulnerabilities with a
@@ -1156,12 +1153,41 @@ Profiles:
## Running API fuzzing in an offline environment
-For self-managed GitLab instances in an environment with limited, restricted, or intermittent access
-to external resources through the internet, some adjustments are required for the Web API Fuzz testing job to
-successfully run. For more information, see [Offline environments](../offline_deployments/index.md).
+For self-managed GitLab instances in an environment with limited, restricted, or intermittent access to external resources through the internet, some adjustments are required for the Web API Fuzz testing job to successfully run.
+
+Steps:
+
+1. Host the Docker image in a local container registry.
+1. Set the `SECURE_ANALYZERS_PREFIX` to the local container registry.
+
+The Docker image for API Fuzzing must be pulled (downloaded) from the public registry and then pushed (imported) into a local registry. The GitLab container registry can be used to locally host the Docker image. This process can be performed using a special template. See [loading Docker images onto your offline host](../offline_deployments/index.md#loading-docker-images-onto-your-offline-host) for instructions.
+
+Once the Docker image is hosted locally, the `SECURE_ANALYZERS_PREFIX` variable is set with the location of the local registry. The variable must be set such that concatenating `/api-fuzzing:1` results in a valid image location.
+
+For example, the below line sets a registry for the image `registry.gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing:1`:
+
+`SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"`
+
+NOTE:
+Setting `SECURE_ANALYZERS_PREFIX` changes the Docker image registry location for all GitLab Secure templates.
+
+For more information, see [Offline environments](../offline_deployments/index.md).
## Troubleshooting
+### Error waiting for API Security 'http://127.0.0.1:5000' to become available
+
+A bug exists in versions of the API Fuzzing analyzer prior to v1.6.196 that can cause a background process to fail under certain conditions. The solution is to update to a newer version of the DAST API analyzer.
+
+The version information can be found in the job details for the `apifuzzer_fuzz` job.
+
+If the issue is occuring with versions v1.6.196 or greater, please contact Support and provide the following information:
+
+1. Reference this troubleshooting section and ask for the issue to be escalated to the Dynamic Analysis Team.
+1. The full console output of the job.
+1. The `gl-api-security-scanner.log` file available as a job artifact. In the right-hand panel of the job details page, select the **Browse** button.
+1. The `apifuzzer_fuzz` job definition from your `.gitlab-ci.yml` file.
+
### Error, the OpenAPI document is not valid. Errors were found during validation of the document using the published OpenAPI schema
At the start of an API Fuzzing job the OpenAPI Specification is validated against the [published schema](https://github.com/OAI/OpenAPI-Specification/tree/master/schemas). This error is shown when the provided OpenAPI Specification has validation errors. Errors can be introduced when creating an OpenAPI Specification manually, and also when the schema is generated.
diff --git a/doc/user/application_security/cluster_image_scanning/index.md b/doc/user/application_security/cluster_image_scanning/index.md
index abbe00a85ab..790b428bac9 100644
--- a/doc/user/application_security/cluster_image_scanning/index.md
+++ b/doc/user/application_security/cluster_image_scanning/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Cluster Image Scanning **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 14.1.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/) in GitLab 14.1.
WARNING:
This analyzer is in [Alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha)
@@ -26,10 +26,18 @@ GitLab provides integration with open-source tools for vulnerability analysis in
To integrate GitLab with security scanners other than those listed here, see
[Security scanner integration](../../../development/integrations/secure.md).
-You can enable cluster image scanning by [including the CI job](#configuration)
+You can use cluster image scanning through the following methods:
+
+- [The cluster image scanning analyzer](#use-the-cluster-image-scanning-analyzer)
+- [The GitLab Kubernetes agent](#cluster-image-scanning-with-the-gitlab-kubernetes-agent)
+
+## Use the cluster image scanning analyzer
+
+You can use the cluster image scanning analyzer to run cluster image scanning with [GitLab CI/CD](../../../ci/index.md).
+To enable the cluster image scanning analyzer, [include the CI job](#configuration)
in your existing `.gitlab-ci.yml` file.
-## Prerequisites
+### Prerequisites
To enable cluster image scanning in your pipeline, you need the following:
@@ -45,7 +53,7 @@ To enable cluster image scanning in your pipeline, you need the following:
[configuration variable](#cicd-variables-for-cluster-image-scanning)
with the type set to `File` (see [Configuring the cluster](#configuring-the-cluster)).
-## Configuring the cluster
+### Configuring the cluster
1. Create a new service account.
@@ -128,7 +136,7 @@ only. You can apply additional protection to your cluster by
and [configuring Starboard Operator](https://aquasecurity.github.io/starboard/v0.10.3/operator/configuration/#install-modes)
to install in restricted mode.
-## Configuration
+### Configuration
To include the `Cluster-Image-Scanning.gitlab-ci.yml` template (GitLab 14.1 and later), add the
following to your `.gitlab-ci.yml` file:
@@ -149,7 +157,7 @@ GitLab saves the results as a
that you can download and analyze later. When downloading, you always receive the most recent
artifact.
-### Customize the cluster image scanning settings
+#### Customize the cluster image scanning settings
You can customize how GitLab scans your cluster. For example, to restrict the analyzer to get
results for only a certain workload, use the [`variables`](../../../ci/yaml/index.md#variables)
@@ -157,7 +165,7 @@ parameter in your `.gitlab-ci.yml` to set [CI/CD variables](#cicd-variables-for-
The variables you set in your `.gitlab-ci.yml` overwrite those in
`Cluster-Image-Scanning.gitlab-ci.yml`.
-#### CI/CD variables for cluster image scanning
+##### CI/CD variables for cluster image scanning
You can [configure](#customize-the-cluster-image-scanning-settings) analyzers by using the following CI/CD variables:
@@ -168,8 +176,9 @@ You can [configure](#customize-the-cluster-image-scanning-settings) analyzers by
| `CIS_RESOURCE_NAME` | `""` | Name of the Kubernetes resource you want to filter vulnerabilities for. For example, `nginx`. |
| `CIS_RESOURCE_NAMESPACE` | `""` | Namespace of the Kubernetes resource you want to filter vulnerabilities for. For example, `production`. |
| `CIS_RESOURCE_KIND` | `""` | Kind of the Kubernetes resource you want to filter vulnerabilities for. For example, `deployment`. |
+| `CIS_CLUSTER_IDENTIFIER` | `""` | ID of the Kubernetes cluster integrated with GitLab. This is used to map vulnerabilities to the cluster so they can be filtered in the Vulnerability Report page. |
-### Override the cluster image scanning template
+#### Override the cluster image scanning template
If you want to override the job definition (for example, to change properties like `variables`), you
must declare and override a job after the template inclusion, and then
@@ -186,7 +195,7 @@ cluster_image_scanning:
CIS_RESOURCE_NAME: nginx
```
-### Connect with Kubernetes cluster associated to the project
+#### Connect with Kubernetes cluster associated to the project
If you want to connect to the Kubernetes cluster associated with the project and run Cluster Image Scanning jobs without
configuring the `CIS_KUBECONFIG` variable, you must extend `cluster_image_scanning` and specify the environment you want to scan.
@@ -200,7 +209,7 @@ cluster_image_scanning:
action: prepare
```
-## Reports JSON format
+### Reports JSON format
The cluster image scanning tool emits a JSON report file. For more information, see the
[schema for this report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json).
@@ -208,7 +217,7 @@ The cluster image scanning tool emits a JSON report file. For more information,
Here's an example cluster image scanning report:
```json-doc
-{{
+{
"version": "14.0.2",
"scan": {
"scanner": {
@@ -265,6 +274,27 @@ Here's an example cluster image scanning report:
}
```
+## Cluster image scanning with the GitLab Kubernetes Agent
+
+You can use the [GitLab Kubernetes Agent](../../clusters/agent/index.md) to
+scan images from within your Kubernetes cluster and record the vulnerabilities in GitLab.
+
+### Prerequisites
+
+- [Starboard Operator](https://aquasecurity.github.io/starboard/v0.10.3/operator/installation/kubectl/)
+ installed and configured in your cluster.
+- [GitLab Kubernetes Agent](../../clusters/agent/install/index.md)
+ set up in GitLab, installed in your cluster, and configured using a configuration repository.
+
+### Configuration
+
+The GitLab Kubernetes agent begins to run cluster image scanning once the `cluster_image_scanning`
+directive is added to your Kubernetes Agent configuration repository.
+
+See the [Kubernetes agent configuration repository](../../clusters/agent/repository.md#scan-your-container-images-for-vulnerabilities)
+reference to learn more about the cluster image scanning configuration options for the
+GitLab Kubernetes agent.
+
## Security Dashboard
The [Security Dashboard](../security_dashboard/index.md) shows you an overview of all
diff --git a/doc/user/application_security/configuration/index.md b/doc/user/application_security/configuration/index.md
index 674eee5e80a..a913d5fba92 100644
--- a/doc/user/application_security/configuration/index.md
+++ b/doc/user/application_security/configuration/index.md
@@ -7,9 +7,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Security Configuration **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20711) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6. **(ULTIMATE)**
-> - SAST configuration was [enabled](https://gitlab.com/groups/gitlab-org/-/epics/3659) in 13.3 and [improved](https://gitlab.com/gitlab-org/gitlab/-/issues/232862) in 13.4. **(ULTIMATE)**
-> - DAST Profiles feature was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40474) in 13.4. **(ULTIMATE)**
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20711) in GitLab 12.6.
+> - SAST configuration was [enabled](https://gitlab.com/groups/gitlab-org/-/epics/3659) in 13.3 and [improved](https://gitlab.com/gitlab-org/gitlab/-/issues/232862) in 13.4.
+> - DAST Profiles feature was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40474) in 13.4.
> - A simplified version was made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/294076) in GitLab 13.10.
> - [Redesigned](https://gitlab.com/gitlab-org/gitlab/-/issues/326926) in 14.2.
@@ -38,31 +38,31 @@ Select **Configuration history** to see the `.gitlab-ci.yml` file's history.
You can configure the following security controls:
-- Static Application Security Testing (SAST) **(FREE)**
+- [Static Application Security Testing](../sast/index.md) (SAST)
- Select **Enable SAST** to configure SAST for the current project.
For more details, read [Configure SAST in the UI](../sast/index.md#configure-sast-in-the-ui).
-- Dynamic Application Security Testing (DAST) **(ULTIMATE)**
+- [Dynamic Application Security Testing](../dast/index.md) (DAST)
- Select **Enable DAST** to configure DAST for the current project.
- Select **Manage scans** to manage the saved DAST scans, site profiles, and scanner profiles.
For more details, read [DAST on-demand scans](../dast/index.md#on-demand-scans).
-- Dependency Scanning **(ULTIMATE)**
+- [Dependency Scanning](../dependency_scanning/index.md)
- Select **Configure via Merge Request** to create a merge request with the changes required to
enable Dependency Scanning. For more details, see [Enable Dependency Scanning via an automatic merge request](../dependency_scanning/index.md#enable-dependency-scanning-via-an-automatic-merge-request).
-- Container Scanning **(ULTIMATE)**
+- [Container Scanning](../container_scanning/index.md)
- Can be configured with `.gitlab-ci.yml`. For more details, read [Container Scanning](../../../user/application_security/container_scanning/index.md#configuration).
-- Cluster Image Scanning **(ULTIMATE)**
+- [Cluster Image Scanning](../cluster_image_scanning/index.md)
- Can be configured with `.gitlab-ci.yml`. For more details, read [Cluster Image Scanning](../../../user/application_security/cluster_image_scanning/#configuration).
-- Secret Detection
+- [Secret Detection](../secret_detection/index.md)
- Select **Configure via Merge Request** to create a merge request with the changes required to
enable Secret Detection. For more details, read [Enable Secret Detection via an automatic merge request](../secret_detection/index.md#enable-secret-detection-via-an-automatic-merge-request).
-- API Fuzzing **(ULTIMATE)**
+- [API Fuzzing](../api_fuzzing/index.md)
- Select **Enable API Fuzzing** to use API Fuzzing for the current project. For more details, read [API Fuzzing](../../../user/application_security/api_fuzzing/index.md#enable-web-api-fuzzing).
-- Coverage Fuzzing **(ULTIMATE)**
+- [Coverage Fuzzing](../coverage_fuzzing/index.md)
- Can be configured with `.gitlab-ci.yml`. For more details, read [Coverage Fuzzing](../../../user/application_security/coverage_fuzzing/index.md#configuration).
## Compliance **(ULTIMATE)**
You can configure the following security controls:
-- License Compliance **(ULTIMATE)**
+- [License Compliance](../../../user/compliance/license_compliance/index.md)
- Can be configured with `.gitlab-ci.yml`. For more details, read [License Compliance](../../../user/compliance/license_compliance/index.md#configuration).
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index 22b54bf019c..da2816ab6ed 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Container Scanning **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in GitLab 10.4.
Your application's Docker image may itself be based on Docker images that contain known
vulnerabilities. By including an extra job in your pipeline that scans for those vulnerabilities and
@@ -148,7 +148,7 @@ Support depends on the scanner:
#### UBI-based images
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5775) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 14.1.
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5775) in GitLab 14.1.
GitLab also offers [Red Hat UBI](https://www.redhat.com/en/blog/introducing-red-hat-universal-base-image)
versions of the container-scanning images. You can therefore replace standard images with UBI-based
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index cdb2e7109bf..9bb13d26d90 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -70,7 +70,7 @@ my_fuzz_target:
- ./gitlab-cov-fuzz run --regression=$REGRESSION -- <your fuzz target>
```
-The included template makes available the [hidden job](../../../ci/yaml/index.md#hide-jobs)
+The included template makes available the [hidden job](../../../ci/jobs/index.md#hide-jobs)
`.fuzz_base`, which you must [extend](../../../ci/yaml/index.md#extends) for each of your fuzz
targets. Each fuzz target **must** have a separate job. For example, the
[go-fuzzing-example project](https://gitlab.com/gitlab-org/security-products/demos/go-fuzzing-example)
@@ -146,7 +146,7 @@ corpus.
### Reports JSON format
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220062) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3 as an [Alpha feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220062) in GitLab 13.3 as an [Alpha feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha).
The `gitlab-cov-fuzz` tool emits a JSON report file. For more information, see the
[schema for this report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/coverage-fuzzing-report-format.json).
diff --git a/doc/user/application_security/dast/browser_based.md b/doc/user/application_security/dast/browser_based.md
index 9c5b84f4f36..10ca3430b48 100644
--- a/doc/user/application_security/dast/browser_based.md
+++ b/doc/user/application_security/dast/browser_based.md
@@ -54,6 +54,7 @@ The browser-based crawler can be configured using CI/CD variables.
| `DAST_BROWSER_SCAN` | boolean | `true` | Configures DAST to use the browser-based crawler engine. |
| `DAST_BROWSER_ALLOWED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are considered in scope when crawled. By default the `DAST_WEBSITE` hostname is included in the allowed hosts list. |
| `DAST_BROWSER_EXCLUDED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are considered excluded and connections are forcibly dropped. |
+| `DAST_BROWSER_EXCLUDED_ELEMENTS` | selector | `a[href='2.html'],css:.no-follow` | Comma-separated list of selectors that are ignored when scanning. |
| `DAST_BROWSER_IGNORED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are accessed but not reported against. |
| `DAST_BROWSER_MAX_ACTIONS` | number | `10000` | The maximum number of actions that the crawler performs. For example, clicking a link, or filling a form. |
| `DAST_BROWSER_MAX_DEPTH` | number | `10` | The maximum number of chained actions that the crawler takes. For example, `Click -> Form Fill -> Click` is a depth of three. |
@@ -127,7 +128,6 @@ dast:
DAST_BROWSER_ACTION_TIMEOUT: "10s"
DAST_BROWSER_STABILITY_TIMEOUT: "15s"
DAST_BROWSER_NAVIGATION_STABILITY_TIMEOUT: "15s"
- DAST_BROWSER_ACTION_TIMEOUT: "10s"
DAST_BROWSER_ACTION_STABILITY_TIMEOUT: "3s"
```
diff --git a/doc/user/application_security/dast/checks/1004.1.md b/doc/user/application_security/dast/checks/1004.1.md
new file mode 100644
index 00000000000..cbbcea1d34d
--- /dev/null
+++ b/doc/user/application_security/dast/checks/1004.1.md
@@ -0,0 +1,41 @@
+---
+stage: Secure
+group: Dynamic Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Sensitive cookie without `HttpOnly` attribute
+
+## Description
+
+The {cookie_name} cookie was transmitted in a `Set-Cookie` header without the `HttpOnly` attribute set.
+To prevent JavaScript being able to access the cookie value - usually via `document.cookies` - all
+cookies that are used for authorization or contain sensitive information should have the `HttpOnly` attribute
+set.
+
+## Remediation
+
+Most web application frameworks allow configuring how cookies are sent to user-agents. Consult your framework's
+documentation for more information on how to enable various security directives when assigning cookies to clients.
+
+If the application is assigning cookies via writing to the response headers directly, ensure all responses include
+the `HttpOnly` attribute. By enabling this protection, the application is able to mitigate the impact of
+certain Cross-Site Scripting (XSS) attacks.
+
+Example:
+
+```http
+Set-Cookie: {cookie_name}=<random secure value>; HttpOnly
+```
+
+## Details
+
+| ID | Aggregated | CWE | Type | Risk |
+|:---|:--------|:--------|:--------|:--------|
+| 1004.1 | false | 1004 | Passive | Low |
+
+## Links
+
+- [owasp](https://owasp.org/www-community/HttpOnly)
+- [cwe](https://cwe.mitre.org/data/definitions/1004.html)
+- [Mozilla MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)
diff --git a/doc/user/application_security/dast/checks/16.1.md b/doc/user/application_security/dast/checks/16.1.md
new file mode 100644
index 00000000000..bb030d2f9c4
--- /dev/null
+++ b/doc/user/application_security/dast/checks/16.1.md
@@ -0,0 +1,33 @@
+---
+stage: Secure
+group: Dynamic Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Missing Content-Type header
+
+## Description
+
+The `Content-Type` header ensures that user agents correctly interpret the data being received. Without this header
+being sent, the browser may misinterpret the data, leading to MIME confusion attacks. If an attacker were able
+to upload files that are accessible by using a browser, they could upload files that may be interpreted as
+HTML and so execute Cross-Site Scripting (XSS) attacks.
+
+## Remediation
+
+Ensure all resources return a proper `Content-Type` header that matches their format. As an example,
+when returning JavaScript files, the response header should be: `Content-Type: application/javascript`
+
+For added protection, we recommend that all resources return the `X-Content-Type-Options: nosniff`
+header to disable user agents from mis-interpreting resources.
+
+## Details
+
+| ID | Aggregated | CWE | Type | Risk |
+|:---|:--------|:--------|:--------|:--------|
+| 16.1 | true | 16 | Passive | Low |
+
+## Links
+
+- [cwe](https://cwe.mitre.org/data/definitions/16.html)
+- [Mozilla Blog on MIME Confusion attacks](https://blog.mozilla.org/security/2016/08/26/mitigating-mime-confusion-attacks-in-firefox/)
diff --git a/doc/user/application_security/dast/checks/16.2.md b/doc/user/application_security/dast/checks/16.2.md
new file mode 100644
index 00000000000..95461e8677d
--- /dev/null
+++ b/doc/user/application_security/dast/checks/16.2.md
@@ -0,0 +1,44 @@
+---
+stage: Secure
+group: Dynamic Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Server header exposes version information
+
+## Description
+
+The target website returns the `Server` header and version information of this website. By
+exposing these values, attackers may attempt to identify if the target software is vulnerable to known
+vulnerabilities, or catalog known sites running particular versions to exploit in the future when a
+vulnerability is identified in the particular version.
+
+## Remediation
+
+We recommend that the version information be removed from the `Server` header.
+
+Apache:
+For Apache based web sites, set the `ServerTokens` to `Prod` in the `httpd.conf` configuration file.
+
+NGINX:
+For NGINX based websites, set the `server_tokens` configuration value to `off` in the `nginx.conf` file.
+
+IIS:
+For IIS based websites version 10 and above you can use the `removeServerHeader` element to the `requestFiltering`
+section of the `Web.config` file.
+
+For all other server types, please consult your product's documentation on how to redact the version information from
+the `Server` header.
+
+## Details
+
+| ID | Aggregated | CWE | Type | Risk |
+|:---|:--------|:--------|:--------|:--------|
+| 16.2 | true | 16 | Passive | Low |
+
+## Links
+
+- [cwe](https://cwe.mitre.org/data/definitions/16.html)
+- [Apache ServerTokens](https://blog.mozilla.org/security/2016/08/26/mitigating-mime-confusion-attacks-in-firefox/)
+- [NGINX server_tokens](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens)
+- [IIS 10 Remove Server Header](https://docs.microsoft.com/en-us/iis/configuration/system.webserver/security/requestfiltering/#attributes)
diff --git a/doc/user/application_security/dast/checks/16.3.md b/doc/user/application_security/dast/checks/16.3.md
new file mode 100644
index 00000000000..e4dcf3ece4b
--- /dev/null
+++ b/doc/user/application_security/dast/checks/16.3.md
@@ -0,0 +1,35 @@
+---
+stage: Secure
+group: Dynamic Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# X-Powered-By header exposes version information
+
+## Description
+
+The target website returns the `X-Powered-By` header and version information of this website. By
+exposing these values, attackers may attempt to identify if the target software is vulnerable to known
+vulnerabilities, or catalog known sites running particular versions to exploit in the future when a
+vulnerability is identified in the particular version.
+
+## Remediation
+
+We recommend that the version information be removed from the `X-Powered-By` header.
+
+PHP:
+For PHP based web sites, set the `expose_php` option to `off` in the `php.ini` configuration file.
+
+For all other server types, please consult your product's documentation on how to redact the version
+information from the `X-Powered-By` header.
+
+## Details
+
+| ID | Aggregated | CWE | Type | Risk |
+|:---|:--------|:--------|:--------|:--------|
+| 16.3 | true | 16 | Passive | Low |
+
+## Links
+
+- [cwe](https://cwe.mitre.org/data/definitions/16.html)
+- [PHP expose_php](https://www.php.net/manual/en/ini.core.php#ini.expose-php)
diff --git a/doc/user/application_security/dast/checks/16.4.md b/doc/user/application_security/dast/checks/16.4.md
new file mode 100644
index 00000000000..c0161c910b0
--- /dev/null
+++ b/doc/user/application_security/dast/checks/16.4.md
@@ -0,0 +1,28 @@
+---
+stage: Secure
+group: Dynamic Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# X-Backend-Server header exposes server information
+
+## Description
+
+The target website returns the `X-Backend-Server` header which includes potentially internal/hidden IP addresses
+or hostnames. By exposing these values, attackers may attempt to circumvent security proxies and access these
+hosts directly.
+
+## Remediation
+
+Consult your proxy/load balancer documentation or provider on how to disable revealing the
+`X-Backend-Server` header value.
+
+## Details
+
+| ID | Aggregated | CWE | Type | Risk |
+|:---|:--------|:--------|:--------|:--------|
+| 16.4 | true | 16 | Passive | Info |
+
+## Links
+
+- [cwe](https://cwe.mitre.org/data/definitions/16.html)
diff --git a/doc/user/application_security/dast/checks/16.5.md b/doc/user/application_security/dast/checks/16.5.md
new file mode 100644
index 00000000000..8a6f3cd8b6a
--- /dev/null
+++ b/doc/user/application_security/dast/checks/16.5.md
@@ -0,0 +1,30 @@
+---
+stage: Secure
+group: Dynamic Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# AspNet Header(s) exposes version information
+
+## Description
+
+The target website returns AspNet header(s) and version information of this website. By
+exposing these values attackers may attempt to identify if the target software is vulnerable to known
+vulnerabilities, or catalog known sites running particular versions to exploit in the future when a
+vulnerability is identified in the particular version.
+
+## Remediation
+
+To remove the `X-AspNet-Version` header set `<httpRuntime enableVersionHeader="false" />` in the `<system.Web>`
+section of the `Web.config` file.
+
+## Details
+
+| ID | Aggregated | CWE | Type | Risk |
+|:---|:--------|:--------|:--------|:--------|
+| 16.5 | true | 16 | Passive | Low |
+
+## Links
+
+- [cwe](https://cwe.mitre.org/data/definitions/16.html)
+- [IIS Remove Unwanted Headers](https://techcommunity.microsoft.com/t5/iis-support-blog/remove-unwanted-http-response-headers/ba-p/369710)
diff --git a/doc/user/application_security/dast/checks/614.1.md b/doc/user/application_security/dast/checks/614.1.md
new file mode 100644
index 00000000000..74ac73935f1
--- /dev/null
+++ b/doc/user/application_security/dast/checks/614.1.md
@@ -0,0 +1,40 @@
+---
+stage: Secure
+group: Dynamic Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Sensitive cookie without `Secure` attribute
+
+## Description
+
+The {cookie_name} cookie was transmitted in a `Set-Cookie` response without the `Secure` attribute set.
+To prevent sensitive cookie values being accidentally transmitted over clear-text HTTP we
+recommended that cookies are declared with the `Secure` attribute.
+
+## Remediation
+
+Most web application frameworks allow configuring how cookies are sent to user agents. Consult your framework's
+documentation for more information on how to enable various security attributes when assigning cookies to clients.
+
+If the application is assigning cookies via writing to the response headers directly, ensure all responses include
+the `Secure` attribute. By enabling this protection, the application will no longer send sensitive cookies over
+HTTP.
+
+Example:
+
+```http
+Set-Cookie: {cookie_name}=<random secure value>; Secure
+```
+
+## Details
+
+| ID | Aggregated | CWE | Type | Risk |
+|:---|:--------|:--------|:--------|:--------|
+| 614.1 | false | 614 | Passive | Low |
+
+## Links
+
+- [owasp](https://owasp.org/www-community/controls/SecureCookieAttribute)
+- [cwe](https://cwe.mitre.org/data/definitions/614.html)
+- [Mozilla MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)
diff --git a/doc/user/application_security/dast/checks/693.1.md b/doc/user/application_security/dast/checks/693.1.md
new file mode 100644
index 00000000000..07cb368b39a
--- /dev/null
+++ b/doc/user/application_security/dast/checks/693.1.md
@@ -0,0 +1,36 @@
+---
+stage: Secure
+group: Dynamic Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Missing X-Content-Type-Options: nosniff
+
+## Description
+
+The `X-Content-Type-Options` header with the value `nosniff` ensures that user agents do not attempt to
+guess the format of the data being received. User Agents such as browsers, commonly attempt to guess
+what the resource type being requested is, through a process called MIME type sniffing.
+
+Without this header being sent, the browser may misinterpret the data, leading to MIME confusion attacks.
+If an attacker were able to upload files that are accessible by using a browser, they could upload files
+that could be interpreted as HTML and execute Cross-Site Scripting (XSS) attacks.
+
+## Remediation
+
+We recommend that the header and value of `X-Content-Type-Options: nosniff` be set server wide.
+This ensures any resources that are mistakenly missing a `Content-Type` value are not
+misinterpreted.
+
+## Details
+
+| ID | Aggregated | CWE | Type | Risk |
+|:---|:--------|:--------|:--------|:--------|
+| 693.1 | true | 693 | Passive | Low |
+
+## Links
+
+- [owasp](https://owasp.org/www-project-secure-headers/#x-content-type-options)
+- [cwe](https://cwe.mitre.org/data/definitions/693.html)
+- [Mozilla Blog on MIME Confusion attacks](https://blog.mozilla.org/security/2016/08/26/mitigating-mime-confusion-attacks-in-firefox/)
+- [Mozilla MDN on X-Content-Type-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options)
diff --git a/doc/user/application_security/dast/checks/index.md b/doc/user/application_security/dast/checks/index.md
new file mode 100644
index 00000000000..f1a68387eb1
--- /dev/null
+++ b/doc/user/application_security/dast/checks/index.md
@@ -0,0 +1,20 @@
+---
+stage: Secure
+group: Dynamic Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# DAST browser-based crawler vulnerability checks **(ULTIMATE)**
+
+The [DAST browser-based crawler](../browser_based.md) provides a number of vulnerability checks that are used to scan for vulnerabilities in the site under test.
+
+| ID | Check | Severity | Type |
+|:---|:------|:---------|:-----|
+| [1004.1](1004.1.md) | Sensitive cookie without `HttpOnly` attribute | Low | Passive |
+| [16.1](16.1.md) | Missing Content-Type header | Low | Passive |
+| [16.2](16.2.md) | Server header exposes version information | Low | Passive |
+| [16.3](16.3.md) | X-Powered-By header exposes version information | Low | Passive |
+| [16.4](16.4.md) | X-Backend-Server header exposes server information | Info | Passive |
+| [16.5](16.5.md) | AspNet Header(s) exposes version information | Low | Passive |
+| [614.1](614.1.md) | Sensitive cookie without `Secure` attribute | Low | Passive |
+| [693.1](693.1.md) | Missing X-Content-Type-Options: nosniff | Low | Passive |
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index 09b55e7b395..0d8b55a92a9 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -320,8 +320,8 @@ tips for optimizing DAST scans in a [blog post](https://about.gitlab.com/blog/20
### API scan
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10928) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
-> - A new DAST API scanning engine was introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10928) in GitLab 12.10.
+> - A new DAST API scanning engine was introduced in GitLab 13.10.
Using an API specification as a scan's target is a useful way to seed URLs for scanning an API.
Vulnerability rules in an API scan are different than those in a normal website scan.
@@ -416,7 +416,7 @@ variables:
### URL scan
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4.
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/273141) in GitLab 13.11.
A URL scan allows you to specify which parts of a website are scanned by DAST.
@@ -492,7 +492,7 @@ Click **View details** to view the web console output which includes the list of
### View details of a vulnerability detected by DAST
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36332) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36332) in GitLab 13.1.
Vulnerabilities detected by DAST occur in the live web application. Addressing these types of
vulnerabilities requires specific information. DAST provides the information required to
@@ -954,6 +954,11 @@ An on-demand scan can be run in active or passive mode:
minimize the risk of accidental damage, running an active scan requires a [validated site
profile](#site-profile-validation).
+### View on-demand DAST scans
+
+To view running and completed on-demand DAST scans for a project, go to
+**Security & Compliance > On-demand Scans** in the left sidebar.
+
### Run an on-demand DAST scan
Prerequisites:
@@ -987,6 +992,7 @@ To run an on-demand scan either at a scheduled date or frequency, read
1. From your project's home page, go to **Security & Compliance > On-demand Scans** in the left
sidebar.
+1. Select **New DAST scan**.
1. Complete the **Scan name** and **Description** fields.
1. In GitLab 13.10 and later, select the desired branch from the **Branch** dropdown.
1. In **Scanner profile**, select a scanner profile from the dropdown.
@@ -1017,17 +1023,13 @@ The on-demand DAST scan runs, and the project's dashboard shows the results.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/328749) in GitLab 14.3. [Deployed behind the `dast_on_demand_scans_scheduler` flag](../../../administration/feature_flags.md), disabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/328749) in GitLab 14.4.
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/328749) in GitLab 14.4.
-
-FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature, ask an
-administrator to [disable the feature flag](../../../administration/feature_flags.md) named
-`dast_on_demand_scans_scheduler`.
-On GitLab.com, this feature is available.
+> - [Feature flag dast_on_demand_scans_scheduler removed](https://gitlab.com/gitlab-org/gitlab/-/issues/328749) in GitLab 14.5.
To schedule a scan:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Security & Compliance > On-demand Scans**.
+1. Select **New DAST scan**.
1. Complete the **Scan name** and **Description** text boxes.
1. In GitLab 13.10 and later, from the **Branch** dropdown list, select the desired branch.
1. In the **Scanner profile** section, from the dropdown list, select a scanner profile.
diff --git a/doc/user/application_security/dast/run_dast_offline.md b/doc/user/application_security/dast/run_dast_offline.md
index 39747a5cbe5..86621d73524 100644
--- a/doc/user/application_security/dast/run_dast_offline.md
+++ b/doc/user/application_security/dast/run_dast_offline.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Run DAST in an offline environment
+# Run DAST in an offline environment **(ULTIMATE)**
For self-managed GitLab instances in an environment with limited, restricted, or intermittent access
to external resources through the internet, some adjustments are required for the DAST job to
diff --git a/doc/user/application_security/dast_api/index.md b/doc/user/application_security/dast_api/index.md
index 3b1c91b0be4..f3ab25ccffa 100644
--- a/doc/user/application_security/dast_api/index.md
+++ b/doc/user/application_security/dast_api/index.md
@@ -681,15 +681,15 @@ Overrides use a JSON document, where each type of override is represented by a J
},
"body-form": {
"form-param1": "value",
- "form-param1": "value",
+ "form-param2": "value"
},
"body-json": {
"json-path1": "value",
- "json-path2": "value",
+ "json-path2": "value"
},
"body-xml" : {
"xpath1": "value",
- "xpath2": "value",
+ "xpath2": "value"
}
}
```
@@ -968,16 +968,16 @@ Follow these steps to view details of a vulnerability:
| Field | Description |
|:--------------------|:----------------------------------------------------------------------------------------|
- | Description | Description of the vulnerability including what was modified. |
+ | Description | Description of the vulnerability including what was modified. |
| Project | Namespace and project in which the vulnerability was detected. |
| Method | HTTP method used to detect the vulnerability. |
| URL | URL at which the vulnerability was detected. |
- | Request | The HTTP request that caused the vulnerability. |
+ | Request | The HTTP request that caused the vulnerability. |
| Unmodified Response | Response from an unmodified request. This is what a normal working response looks like. |
- | Actual Response | Response received from test request. |
- | Evidence | How we determined a vulnerability occurred. |
- | Identifiers | The DAST API check used to find this vulnerability. |
- | Severity | Severity of the vulnerability. |
+ | Actual Response | Response received from test request. |
+ | Evidence | How we determined a vulnerability occurred. |
+ | Identifiers | The DAST API check used to find this vulnerability. |
+ | Severity | Severity of the vulnerability. |
| Scanner Type | Scanner used to perform testing. |
### Security Dashboard
@@ -1105,8 +1105,46 @@ Profiles:
- Name: XmlInjectionCheck
```
+## Running DAST API in an offline environment
+
+For self-managed GitLab instances in an environment with limited, restricted, or intermittent access to external resources through the internet, some adjustments are required for the DAST API testing job to successfully run.
+
+Steps:
+
+1. Host the Docker image in a local container registry.
+1. Set the `SECURE_ANALYZERS_PREFIX` to the local container registry.
+
+The Docker image for DAST API must be pulled (downloaded) from the public registry and then pushed (imported) into a local registry. The GitLab container registry can be used to locally host the Docker image. This process can be performed using a special template. See [loading Docker images onto your offline host](../offline_deployments/index.md#loading-docker-images-onto-your-offline-host) for instructions.
+
+Once the Docker image is hosted locally, the `SECURE_ANALYZERS_PREFIX` variable is set with the location of the local registry. The variable must be set such that concatenating `/api-fuzzing:1` results in a valid image location.
+
+NOTE:
+DAST API and API Fuzzing both use the same underlying Docker image `api-fuzzing:1`.
+
+For example, the below line sets a registry for the image `registry.gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing:1`:
+
+`SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"`
+
+NOTE:
+Setting `SECURE_ANALYZERS_PREFIX` changes the Docker image registry location for all GitLab Secure templates.
+
+For more information, see [Offline environments](../offline_deployments/index.md).
+
## Troubleshooting
+### Error waiting for API Security 'http://127.0.0.1:5000' to become available
+
+A bug exists in versions of the DAST API analyzer prior to v1.6.196 that can cause a background process to fail under certain conditions. The solution is to update to a newer version of the DAST API analyzer.
+
+The version information can be found in the job details for the `dast_api` job.
+
+If the issue is occuring with versions v1.6.196 or greater, please contact Support and provide the following information:
+
+1. Reference this troubleshooting section and ask for the issue to be escalated to the Dynamic Analysis Team.
+1. The full console output of the job.
+1. The `gl-api-security-scanner.log` file available as a job artifact. In the right-hand panel of the job details page, select the **Browse** button.
+1. The `dast_api` job definition from your `.gitlab-ci.yml` file.
+
### Failed to start scanner session (version header not found)
The DAST API engine outputs an error message when it cannot establish a connection with the scanner application component. The error message is shown in the job output window of the `dast_api` job. A common cause of this issue is changing the `DAST_API_API` variable from its default.
@@ -1114,7 +1152,7 @@ The DAST API engine outputs an error message when it cannot establish a connecti
**Error message**
- In [GitLab 13.11 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/323939), `Failed to start scanner session (version header not found).`
-- In GitLab 13.10 and earlier, `API Security version header not found. Are you sure that you are connecting to the API Security server?`.
+- In GitLab 13.10 and earlier, `API Security version header not found. Are you sure that you are connecting to the API Security server?`.
**Solution**
diff --git a/doc/user/application_security/dependency_list/index.md b/doc/user/application_security/dependency_list/index.md
index edfd0333d54..b0d8af2606f 100644
--- a/doc/user/application_security/dependency_list/index.md
+++ b/doc/user/application_security/dependency_list/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Dependency list **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10075) in GitLab Ultimate 12.0.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10075) in GitLab 12.0.
Use the dependency list to review your project's dependencies and key
details about those dependencies, including their known vulnerabilities. It is a collection of dependencies in your project, including existing and new findings.
@@ -66,7 +66,7 @@ Dependency paths are supported for the following package managers:
## Licenses
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10536) in GitLab Ultimate 12.3.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10536) in GitLab 12.3.
If the [License Compliance](../../compliance/license_compliance/index.md) CI job is configured,
[discovered licenses](../../compliance/license_compliance/index.md#supported-languages-and-package-managers) are displayed on this page.
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 1f840c96663..3c6db8c3ee9 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -89,12 +89,13 @@ table.supported-languages ul {
}
</style>
+<!-- markdownlint-disable MD044 -->
<table class="supported-languages">
<thead>
<tr>
<th>Language</th>
+ <th>Language Versions</th>
<th>Package Manager</th>
- <th>Package Manager Versions</th>
<th>Supported files</th>
<th>Analyzer</th>
<th><a href="#how-multiple-files-are-processed">Processes multiple files?</a></th>
@@ -103,8 +104,8 @@ table.supported-languages ul {
<tbody>
<tr>
<td rowspan="2">Ruby</td>
+ <td rowspan="2">N/A</td>
<td rowspan="2"><a href="https://bundler.io/">Bundler</a></td>
- <td rowspan="2">Any</td>
<td>
<ul>
<li><code>Gemfile.lock</code></li>
@@ -121,16 +122,16 @@ table.supported-languages ul {
</tr>
<tr>
<td>PHP</td>
+ <td>N/A</td>
<td><a href="https://getcomposer.org/">Composer</a></td>
- <td>Any</td>
<td><code>composer.lock</code></td>
<td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>Y</td>
</tr>
<tr>
<td>C</td>
+ <td rowspan="2">N/A</td>
<td rowspan="2"><a href="https://conan.io/">Conan</a></td>
- <td rowspan="2">Any</td>
<td rowspan="2"><a href="https://docs.conan.io/en/latest/versioning/lockfiles.html"><code>conan.lock</code></a></td>
<td rowspan="2"><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td rowspan="2">Y</td>
@@ -140,16 +141,16 @@ table.supported-languages ul {
</tr>
<tr>
<td>Go</td>
- <td><a href="https://golang.org/">Golang</a></td>
- <td>Any</td>
+ <td>N/A</td>
+ <td><a href="https://golang.org/">Go</a></td>
<td><code>go.sum</code></td>
<td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>Y</td>
</tr>
<tr>
<td rowspan="2">Java</td>
- <td><a href="https://gradle.org/">Gradle</a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers">1</a></b></sup></td>
- <td>Any</td>
+ <td rowspan="2">8, 11, 13, 14, 15, or 16</td>
+ <td><a href="https://gradle.org/">Gradle</a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers-1">1</a></b></sup></td>
<td>
<ul>
<li><code>build.gradle</code></li>
@@ -161,15 +162,14 @@ table.supported-languages ul {
</tr>
<tr>
<td><a href="https://maven.apache.org/">Maven</a></td>
- <td>Any</td>
<td><code>pom.xml</code></td>
<td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>N</td>
</tr>
<tr>
<td rowspan="3">JavaScript</td>
+ <td rowspan="2">N/A</td>
<td rowspan="2"><a href="https://www.npmjs.com/">npm</a></td>
- <td rowspan="2">Any</td>
<td>
<ul>
<li><code>package-lock.json</code></li>
@@ -185,16 +185,16 @@ table.supported-languages ul {
<td>N</td>
</tr>
<tr>
+ <td>N/A</td>
<td><a href="https://classic.yarnpkg.com/en/">yarn</a></td>
- <td>1.x</td>
<td><code>yarn.lock</code></td>
<td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>Y</td>
</tr>
<tr>
<td>.NET</td>
+ <td rowspan="2">N/A</td>
<td rowspan="2"><a href="https://www.nuget.org/">NuGet</a></td>
- <td rowspan="2">&gt;= 4.9</td>
<td rowspan="2"><a href="https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#enabling-lock-file"><code>packages.lock.json</code></a></td>
<td rowspan="2"><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td rowspan="2">Y</td>
@@ -204,15 +204,14 @@ table.supported-languages ul {
</tr>
<tr>
<td rowspan="3">Python</td>
+ <td rowspan="3">3.6</td>
<td><a href="https://setuptools.readthedocs.io/en/latest/">setuptools</a></td>
- <td>Any</td>
<td><code>setup.py</code></td>
<td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>N</td>
</tr>
<tr>
<td><a href="https://pip.pypa.io/en/stable/">pip</a></td>
- <td>Any</td>
<td>
<ul>
<li><code>requirements.txt</code></li>
@@ -225,11 +224,10 @@ table.supported-languages ul {
</tr>
<tr>
<td><a href="https://pipenv.pypa.io/en/latest/">Pipenv</a></td>
- <td>Any</td>
<td>
<ul>
<li><a href="https://pipenv.pypa.io/en/latest/basics/#example-pipfile-pipfile-lock"><code>Pipfile</code></a></li>
- <li><a href="https://pipenv.pypa.io/en/latest/basics/#example-pipfile-pipfile-lock"><code>Pipfile.lock</code></a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers">2</a></b></sup></li>
+ <li><a href="https://pipenv.pypa.io/en/latest/basics/#example-pipfile-pipfile-lock"><code>Pipfile.lock</code></a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers-2">2</a></b></sup></li>
</ul>
</td>
<td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
@@ -237,8 +235,8 @@ table.supported-languages ul {
</tr>
<tr>
<td>Scala</td>
- <td><a href="https://www.scala-sbt.org/">sbt</a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers">3</a></b></sup></td>
- <td>Any</td>
+ <td>N/A</td>
+ <td><a href="https://www.scala-sbt.org/">sbt</a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers-3">3</a></b></sup></td>
<td><code>build.sbt</code></td>
<td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>N</td>
@@ -246,18 +244,91 @@ table.supported-languages ul {
</tbody>
</table>
-### Notes regarding supported languages and package managers
-
-1. Although Gradle with Java 8 is supported, there are other issues such that Android project builds are not supported at this time. Please see the backlog issue [Android support for Dependency Scanning (gemnasium-maven)](https://gitlab.com/gitlab-org/gitlab/-/issues/336866) for more details.
-
-1. The presence of a `Pipfile.lock` file alone will _not_ trigger the analyzer; the presence of a `Pipfile` is still required in order
-for the analyzer to be executed. However, if a `Pipfile.lock` file is found, it will be used by `Gemnasium` to scan the exact package
-versions listed in this file.
-
- Support for `Pipfile.lock` files without requiring the presence of a `Pipfile` will be implemented in the following upcoming issue:
- [Dependency Scanning of Pipfile.lock without installing project dependencies](https://gitlab.com/gitlab-org/gitlab/-/issues/299294).
-
-1. Support for [sbt](https://www.scala-sbt.org/) 1.3 and above was added in GitLab 13.9.
+<ol>
+ <li>
+ <a id="notes-regarding-supported-languages-and-package-managers-1"></a>
+ <p>
+ Although Gradle with Java 8 is supported, there are other issues such that Android project builds are not supported at this time.
+ Please see the backlog issue <a href="https://gitlab.com/gitlab-org/gitlab/-/issues/336866">Android support for Dependency
+ Scanning (gemnasium-maven)</a> for more details.
+ </p>
+ </li>
+ <li>
+ <a id="notes-regarding-supported-languages-and-package-managers-2"></a>
+ <p>
+ The presence of a <code>Pipfile.lock</code> file alone will <i>not</i> trigger the analyzer; the presence of a <code>Pipfile</code> is
+ still required in order for the analyzer to be executed. However, if a <code>Pipfile.lock</code> file is found, it will be used by
+ <code>Gemnasium</code> to scan the exact package versions listed in this file.
+ </p>
+ <p>
+ Support for <code>Pipfile.lock</code> files without requiring the presence of a <code>Pipfile</code> is tracked in
+ issue: <a href="https://gitlab.com/gitlab-org/gitlab/-/issues/299294">Dependency Scanning of Pipfile.lock without
+ installing project dependencies</a>.
+ </p>
+ </li>
+ <li>
+ <a id="notes-regarding-supported-languages-and-package-managers-3"></a>
+ <p>
+ Support for <a href="https://www.scala-sbt.org/">sbt</a> 1.3 and above was added in GitLab 13.9.
+ </p>
+ </li>
+</ol>
+<!-- markdownlint-enable MD044 -->
+
+### How analyzers obtain dependency information
+
+GitLab analyzers obtain dependency information using one of the following two methods:
+
+1. [Parsing lockfiles directly.](#obtaining-dependendency-information-by-parsing-lockfiles)
+1. [Running a package manager or build tool to generate a dependency information file which is then parsed.](#obtaining-dependendency-information-by-running-a-package-manager-to-generate-a-parsable-file)
+
+#### Obtaining dependendency information by parsing lockfiles
+
+The following package managers use lockfiles that GitLab analyzers are capable of parsing directly:
+
+| Package Manager | Supported File Format Versions | Tested Versions |
+| ------ | ------ | ------ |
+| Bundler | N/A | [1.17.3](https://gitlab.com/gitlab-org/security-products/tests/ruby-bundler/-/blob/master/Gemfile.lock#L118), [2.1.4](https://gitlab.com/gitlab-org/security-products/tests/ruby-bundler/-/blob/bundler2-FREEZE/Gemfile.lock#L118) |
+| Composer | N/A | [1.x](https://gitlab.com/gitlab-org/security-products/tests/php-composer/-/blob/master/composer.lock) |
+| Conan | 0.4 | [1.x](https://gitlab.com/gitlab-org/security-products/tests/c-conan/-/blob/master/conan.lock) |
+| Go | N/A | [1.x](https://gitlab.com/gitlab-org/security-products/tests/go-modules/-/blob/master/go.mod) |
+| NuGet | v1 | [4.9](https://gitlab.com/gitlab-org/security-products/tests/csharp-nuget-dotnetcore/-/blob/master/src/web.api/packages.lock.json#L2) |
+| npm | v1, v2 | [6.x](https://gitlab.com/gitlab-org/security-products/tests/js-npm/-/blob/master/package-lock.json#L4), [7.x](https://gitlab.com/gitlab-org/security-products/tests/js-npm/-/blob/lockfile-v2-FREEZE/package-lock.json#L4) |
+| yarn | v1 | [1.x](https://gitlab.com/gitlab-org/security-products/tests/js-yarn/-/blob/master/yarn.lock) |
+
+#### Obtaining dependendency information by running a package manager to generate a parsable file
+
+To support the following package managers, the GitLab analyzers proceed in two steps:
+
+1. Execute the package manager or a specific task, to export the dependency information.
+1. Parse the exported dependency information.
+
+| Package Manager | Preinstalled Versions | Tested Versions |
+| ------ | ------ | ------ |
+| Bundler | [2.1.4](https://gitlab.com/gitlab-org/security-products/analyzers/bundler-audit/-/blob/v2.11.3/Dockerfile#L15)<sup><b><a href="#exported-dependency-information-notes-1">1</a></b></sup> | [1.17.3](https://gitlab.com/gitlab-org/security-products/tests/ruby-bundler/-/blob/master/Gemfile.lock#L118), [2.1.4](https://gitlab.com/gitlab-org/security-products/tests/ruby-bundler/-/blob/bundler2-FREEZE/Gemfile.lock#L118) |
+| sbt | [1.3.8](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.23.0/config/.tool-versions#L4) | [1.0.4](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L263), [1.1.4](https://gitlab.com/gitlab-org/security-products/tests/scala-sbt-multiproject/-/blob/main/project/build.properties#L1), [1.1.6](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L272), [1.2.8](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L281), [1.3.12](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L290), [1.4.6](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L299) |
+| Maven | [3.6.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.23.0/config/.tool-versions#L3) | [3.6.3](https://gitlab.com/gitlab-org/security-products/tests/java-maven/-/blob/master/pom.xml#L3) |
+| Gradle | [6.7.1](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.23.0/config/.tool-versions#L5) | [5.6.4](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/master/gradle/wrapper/gradle-wrapper.properties#L3), [6.5](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-14/gradle/wrapper/gradle-wrapper.properties#L3), [6.7-rc-1](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-15/gradle/wrapper/gradle-wrapper.properties#L3), [6.9](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-14-gradle-6-9/gradle/wrapper/gradle-wrapper.properties#L3), [7.0-rc-2](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-16/gradle/wrapper/gradle-wrapper.properties#L3) |
+| setuptools | [50.3.2](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v2.29.9/Dockerfile#L27) | |
+| pip | [20.2.4](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v2.29.9/Dockerfile#L26) | [20.x](https://gitlab.com/gitlab-org/security-products/tests/python-pip/-/blob/master/requirements.txt) |
+| Pipenv | [2018.11.26](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python/-/blob/v2.18.4/requirements.txt#L13) | [2018.11.26](https://gitlab.com/gitlab-org/security-products/tests/python-pipenv/-/blob/pipfile-lock-FREEZE/Pipfile.lock#L6)<sup><b><a href="#exported-dependency-information-notes-2">2</a></b></sup>, [2018.11.26](https://gitlab.com/gitlab-org/security-products/tests/python-pipenv/-/blob/master/Pipfile) |
+
+<!-- markdownlint-disable MD044 -->
+<ol>
+ <li>
+ <a id="exported-dependency-information-notes-1"></a>
+ <p>
+ The installed version of <code>Bundler</code> is only used for the <a href="https://gitlab.com/gitlab-org/security-products/analyzers/bundler-audit">bundler-audit</a> analyzer, and is not used for <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">gemnasium</a>
+ </p>
+ </li>
+ <li>
+ <a id="exported-dependency-information-notes-2"></a>
+ <p>
+ This test confirms that if a <code>Pipfile.lock</code> file is found, it will be used by <a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a> to scan the exact package versions listed in this file.
+ </p>
+ </li>
+</ol>
+<!-- markdownlint-enable MD044 -->
### How analyzers are triggered
@@ -321,15 +392,16 @@ We execute both analyzers because they use different sources of vulnerability da
The analyzer for these languages supports multiple lockfiles.
-### Future support for additional languages
+### Support for additional languages
-Plans are underway for supporting the following languages, dependency managers, and dependency files. For details, see the issue link for each.
-For workarounds, see the [Troubleshooting section](#troubleshooting)
+Support for additional languages, dependency managers, and dependency files are tracked in the following issues:
| Package Managers | Languages | Supported files | Scan tools | Issue |
| ------------------- | --------- | --------------- | ---------- | ----- |
| [Poetry](https://python-poetry.org/) | Python | `poetry.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium) | [GitLab#7006](https://gitlab.com/gitlab-org/gitlab/-/issues/7006) |
+For workarounds, see the [Troubleshooting section](#troubleshooting).
+
## Contribute your scanner
The [Security Scanner Integration](../../../development/integrations/secure.md) documentation explains how to integrate other security scanners into GitLab.
@@ -359,8 +431,8 @@ always take the latest dependency scanning artifact available.
### Enable Dependency Scanning via an automatic merge request
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4908) in GitLab 14.1.
-> - [Enabled with `sec_dependency_scanning_ui_enable` flag](https://gitlab.com/gitlab-org/gitlab/-/issues/282533) for self-managed GitLab in GitLab 14.1 and is ready for production use.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4908) in GitLab 14.1 [with a flag](../../../administration/feature_flags.md) named `sec_dependency_scanning_ui_enable`. Enabled by default.
+> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/282533) in GitLab 14.1.
> - [Feature flag sec_dependency_scanning_ui_enable removed](https://gitlab.com/gitlab-org/gitlab/-/issues/326005) in GitLab 14.2.
To enable Dependency Scanning in a project, you can create a merge request
diff --git a/doc/user/application_security/iac_scanning/index.md b/doc/user/application_security/iac_scanning/index.md
new file mode 100644
index 00000000000..a58a00a869b
--- /dev/null
+++ b/doc/user/application_security/iac_scanning/index.md
@@ -0,0 +1,98 @@
+---
+stage: Secure
+group: Static Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Infrastructure as Code (IaC) Scanning
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6655) in GitLab 14.5.
+
+Infrastructure as Code (IaC) Scanning scans your IaC configuration files for known vulnerabilities.
+
+Currently, IaC scanning supports configuration files for Terraform, Ansible, AWS CloudFormation, and Kubernetes.
+
+## Requirements
+
+To run IaC scanning jobs, by default, you need GitLab Runner with the
+[`docker`](https://docs.gitlab.com/runner/executors/docker.html) or
+[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html) executor.
+If you're using the shared runners on GitLab.com, this is enabled by default.
+
+WARNING:
+Our IaC scanning jobs require a Linux container type. Windows containers are not yet supported.
+
+WARNING:
+If you use your own runners, make sure the Docker version installed
+is **not** `19.03.0`. See [troubleshooting information](../sast/index.md#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) for details.
+
+## Supported languages and frameworks
+
+GitLab IaC scanning supports a variety of IaC configuration files. Our IaC security scanners also feature automatic language detection which works even for mixed-language projects. If any supported configuration files are detected in project source code we automatically run the appropriate IaC analyzers.
+
+| Configuration File Type | Scan tool | Introduced in GitLab Version |
+|------------------------------------------|----------------------------------|-------------------------------|
+| Ansible | [kics](https://kics.io/) | 14.5 |
+| AWS CloudFormation | [kics](https://kics.io/) | 14.5 |
+| Kubernetes | [kics](https://kics.io/) | 14.5 |
+| Terraform | [kics](https://kics.io/) | 14.5 |
+
+### Making IaC analyzers available to all GitLab tiers
+
+All open source (OSS) analyzers are availibile with the GitLab Free tier. Future propietary analyzers may be restricted to higher tiers.
+
+#### Summary of features per tier
+
+Different features are available in different [GitLab tiers](https://about.gitlab.com/pricing/),
+as shown in the following table:
+
+| Capability | In Free | In Ultimate |
+|:---------------------------------------------------------------------------------------|:--------------------|:-------------------|
+| [Configure IaC Scanners](#configuration) v | **{check-circle}** | **{check-circle}** |
+| View [JSON Report](#reports-json-format) | **{check-circle}** | **{check-circle}** |
+| Presentation of JSON Report in Merge Request | **{dotted-circle}** | **{check-circle}** |
+| [Address vulnerabilities](../../application_security/vulnerabilities/index.md) | **{dotted-circle}** | **{check-circle}** |
+| [Access to Security Dashboard](../../application_security/security_dashboard/index.md) | **{dotted-circle}** | **{check-circle}** |
+
+## Contribute your scanner
+
+The [Security Scanner Integration](../../../development/integrations/secure.md) documentation explains how to integrate other security scanners into GitLab.
+
+## Configuration
+
+To configure IaC Scanning for a project you can:
+
+- [Configure IaC Scanning manually](#configure-iac-scanning-manually)
+- [Enable IaC Scanning via an automatic merge request](#enable-iac-scanning-via-an-automatic-merge-request)
+
+### Configure IaC Scanning manually
+
+To enable IaC Scanning you must [include](../../../ci/yaml/index.md#includetemplate) the
+[`SAST-IaC.latest.gitlab-ci.yml template`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST-IaC.latest.gitlab-ci.yml) provided as part of your GitLab installation.
+
+The included template creates IaC scanning jobs in your CI/CD pipeline and scans
+your project's configuration files for possible vulnerabilities.
+
+The results are saved as a
+[SAST report artifact](../../../ci/yaml/index.md#artifactsreportssast)
+that you can download and analyze.
+
+### Enable IaC Scanning via an automatic merge request
+
+To enable IaC Scanning in a project, you can create a merge request
+from the Security Configuration page:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Security & Compliance > Configuration**.
+1. In the **Infrastructure as Code (IaC) Scanning** row, select **Configure via Merge Request**.
+
+This automatically creates a merge request with the changes necessary to enable IaC Scanning
+that you can review and merge to complete the configuration.
+
+## Reports JSON format
+
+The IaC tool emits a JSON report file in the existing SAST report format. For more information, see the
+[schema for this report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/sast-report-format.json).
+
+The JSON report file can be downloaded from the CI pipelines page, or the
+pipelines tab on merge requests by [setting `artifacts: paths`](../../../ci/yaml/index.md#artifactspaths) to `gl-sast-report.json`. For more information see [Downloading artifacts](../../../ci/pipelines/job_artifacts.md).
diff --git a/doc/user/application_security/img/vulnerability-check_v14_2.png b/doc/user/application_security/img/vulnerability-check_v14_2.png
deleted file mode 100644
index 655e43221c7..00000000000
--- a/doc/user/application_security/img/vulnerability-check_v14_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index 7b95769a81f..d5e801ced9c 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -31,19 +31,20 @@ For an overview of GitLab application security, see [Shifting Security Left](htt
GitLab uses the following tools to scan and report known vulnerabilities found in your project.
-| Secure scanning tool | Description |
-|:-----------------------------------------------------------------------------|:-----------------------------------------------------------------------|
-| [Container Scanning](container_scanning/index.md) **(ULTIMATE)** | Scan Docker containers for known vulnerabilities. |
-| [Dependency List](dependency_list/index.md) **(ULTIMATE)** | View your project's dependencies and their known vulnerabilities. |
-| [Dependency Scanning](dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. |
-| [Dynamic Application Security Testing (DAST)](dast/index.md) **(ULTIMATE)** | Analyze running web applications for known vulnerabilities. |
-| [DAST API](dast_api/index.md) **(ULTIMATE)** | Analyze running web APIs for known vulnerabilities. |
-| [API fuzzing](api_fuzzing/index.md) **(ULTIMATE)** | Find unknown bugs and vulnerabilities in web APIs with fuzzing. |
-| [Secret Detection](secret_detection/index.md) | Analyze Git history for leaked secrets. |
-| [Security Dashboard](security_dashboard/index.md) **(ULTIMATE)** | View vulnerabilities in all your projects and groups. |
-| [Static Application Security Testing (SAST)](sast/index.md) | Analyze source code for known vulnerabilities. |
-| [Coverage fuzzing](coverage_fuzzing/index.md) **(ULTIMATE)** | Find unknown bugs and vulnerabilities with coverage-guided fuzzing. |
-| [Cluster Image Scanning](cluster_image_scanning/index.md) **(ULTIMATE)** | Scan Kubernetes clusters for known vulnerabilities. |
+| Secure scanning tool | Description |
+| :------------------------------------------------------------- | :------------------------------------------------------------------ |
+| [Container Scanning](container_scanning/index.md) | Scan Docker containers for known vulnerabilities. |
+| [Dependency List](dependency_list/index.md) | View your project's dependencies and their known vulnerabilities. |
+| [Dependency Scanning](dependency_scanning/index.md) | Analyze your dependencies for known vulnerabilities. |
+| [Dynamic Application Security Testing (DAST)](dast/index.md) | Analyze running web applications for known vulnerabilities. |
+| [DAST API](dast_api/index.md) | Analyze running web APIs for known vulnerabilities. |
+| [API fuzzing](api_fuzzing/index.md) | Find unknown bugs and vulnerabilities in web APIs with fuzzing. |
+| [Secret Detection](secret_detection/index.md) | Analyze Git history for leaked secrets. |
+| [Security Dashboard](security_dashboard/index.md) | View vulnerabilities in all your projects and groups. |
+| [Static Application Security Testing (SAST)](sast/index.md) | Analyze source code for known vulnerabilities. |
+| [Infrastructure as Code (IaC) Scanning](iac_scanning/index.md) | Analyze your IaC coniguration files for known vulnerabilities. |
+| [Coverage fuzzing](coverage_fuzzing/index.md) | Find unknown bugs and vulnerabilities with coverage-guided fuzzing. |
+| [Cluster Image Scanning](cluster_image_scanning/index.md) | Scan Kubernetes clusters for known vulnerabilities. |
## Security scanning with Auto DevOps
@@ -185,61 +186,51 @@ By default, the vulnerability report does not show vulnerabilities of `dismissed
## Security approvals in merge requests
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9928) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9928) in GitLab 12.2.
-You can implement merge request approvals to require approval by selected users or a group when a
-merge request would introduce one of the following security issues:
+You can enforce an additional approval for merge requests that would introduce one of the following
+security issues:
-- A security vulnerability
-- A software license compliance violation
+- A security vulnerability. For more details, read
+ [Vulnerability-Check rule](#vulnerability-check-rule).
+- A software license compliance violation. For more details, read
+ [Enabling license approvals within a project](../compliance/license_compliance/index.md#enabling-license-approvals-within-a-project).
-When the Vulnerability-Check merge request rule is enabled, additional merge request approval
+### Vulnerability-Check rule
+
+To prevent a merge request introducing a security vulnerability in a project, enable the
+Vulnerability-Check rule. While this rule is enabled, additional merge request approval by
+[eligible approvers](../project/merge_requests/approvals/rules.md#eligible-approvers)
is required when the latest security report in a merge request:
-- Contains vulnerabilities that are not present in the
- target branch. Note that approval is still required for dismissed vulnerabilities.
+- Contains vulnerabilities with states (for example, `previously detected`, `dismissed`) matching the rule's vulnerability states. Only `newly detected` will be considered if the target branch differs from the project default branch.
- Contains vulnerabilities with severity levels (for example, `high`, `critical`, or `unknown`)
matching the rule's severity levels.
- Contains a vulnerability count higher than the rule allows.
-- Is not generated during pipeline execution.
+- Is not yet generated (until pipeline completion).
An approval is optional when the security report:
-- Contains no new vulnerabilities when compared to the target branch.
+- Contains only vulnerabilities with states (for example, `newly detected`, `resolved`) **NOT** matching the rule's vulnerability states.
- Contains only vulnerabilities with severity levels (for example, `low`, `medium`) **NOT** matching
the rule's severity levels.
- Contains a vulnerability count equal to or less than what the rule allows.
-When the License-Check merge request rule is enabled, additional approval is required if a merge
-request contains a denied license. For more details, see [Enabling license approvals within a project](../compliance/license_compliance/index.md#enabling-license-approvals-within-a-project).
-
-### Enable the Vulnerability-Check rule
-
-Prerequisites:
-
-- Maintainer or Owner [role](../permissions.md#project-members-permissions).
+Project members assigned [at least the Maintainer role](../permissions.md#project-members-permissions) can enable or edit
+the Vulnerability-Check rule.
-For this approval group, you must set the number of approvals required to greater than zero.
+#### Enable the Vulnerability-Check rule
-Follow these steps to enable `Vulnerability-Check`:
+To enable or edit the Vulnerability-Check rule:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > General**.
1. Expand **Merge request approvals**.
-1. Select **Enable** or **Edit**.
-1. Set the **Security scanners** that the rule applies to.
-1. Select the **Target branch**.
-1. Set the **Vulnerabilities allowed** to the number of vulnerabilities allowed before the rule is
- triggered.
-1. Set the **Severity levels** to the severity levels that the rule applies to.
-1. Set the **Approvals required** to the number of approvals that the rule requires.
-1. Select the users or groups to provide approval.
+1. Select **Activate** or **Edit** of the Vulnerability-Check.
+1. Complete the fields. **Approvals required** must be at least 1.
1. Select **Add approval rule**.
-Once this group is added to your project, the approval rule is enabled for all merge requests.
-Any code changes cause the approvals required to reset.
-
-![Vulnerability Check Approver Rule](img/vulnerability-check_v14_2.png)
+The approval rule is enabled for all merge requests. Any code changes reset the approvals required.
## Using private Maven repositories
@@ -270,28 +261,44 @@ under your project's settings:
</settings>
```
-## DAST On-Demand Scans
+## Using a custom scanning stage
-If you don't want scans running in your normal DevOps process you can use on-demand scans instead. For more details, see [on-demand scans](dast/index.md#on-demand-scans). This feature is only available for DAST. If you run an on-demand scan against the default branch, it is reported as a "successful pipeline" and these results are included in the security dashboard and vulnerability report.
+When security scanning is enabled by including CI/CD templates as described in the
+[Security scanning without Auto DevOps](#security-scanning-without-auto-devops) section, the scanning jobs
+use the predefined `test` stage by default. If you specify a custom stage in your `.gitlab-ci.yml` file without
+including a `test` stage, an error occurs.
-## Security report validation
+For example, the following attempts to use a `unit-tests` stage:
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321918) in GitLab 13.11.
-> - Schema validation message [added](https://gitlab.com/gitlab-org/gitlab/-/issues/321730) in GitLab 14.0.
+```yaml
+include:
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
+ - template: Security/License-Scanning.gitlab-ci.yml
+ - template: Security/SAST.gitlab-ci.yml
+ - template: Security/Secret-Detection.gitlab-ci.yml
-You can optionally enable validation of the security report artifacts based on the
-[report schemas](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/tree/master/dist).
-If you enable validation, GitLab validates the report artifacts before ingesting the vulnerabilities.
-This prevents ingestion of broken vulnerability data into the database.
+stages:
+ - unit-tests
-In GitLab 14.0 and later, the pipeline's **Security** tab lists any report artifacts
-that failed validation. Security report validation must first be enabled.
+custom job:
+ stage: unit-tests
+ script:
+ - echo "custom job"
+```
-### Enable security report validation
+The above `.gitlab-ci.yml` causes a linting error:
-To enable report artifacts validation, set the `VALIDATE_SCHEMA` environment variable to `"true"` for the jobs in the `.gitlab-ci.yml` file.
+```plaintext
+Found errors in your .gitlab-ci.yml:
+- dependency_scanning job: chosen stage does not exist; available stages are .pre
+- unit-tests
+- .post
+```
+
+This error appears because the `test` stage used by the security scanning jobs isn't declared in the `.gitlab-ci.yml` file.
+To fix this issue, you can either:
-For example, the configuration below enables validation for only the `sast` job:
+- Add a `test` stage in your `.gitlab-ci.yml`:
```yaml
include:
@@ -301,26 +308,98 @@ For example, the configuration below enables validation for only the `sast` job:
- template: Security/Secret-Detection.gitlab-ci.yml
stages:
- - security-scan
+ - test
+ - unit-tests
+
+ custom job:
+ stage: unit-tests
+ script:
+ - echo "custom job"
+ ```
+
+- Override the default stage of each security job. For example, to use a pre-defined stage named `unit-tests`:
+
+ ```yaml
+ include:
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
+ - template: Security/License-Scanning.gitlab-ci.yml
+ - template: Security/SAST.gitlab-ci.yml
+ - template: Security/Secret-Detection.gitlab-ci.yml
+
+ stages:
+ - unit-tests
dependency_scanning:
- stage: security-scan
+ stage: unit-tests
license_scanning:
- stage: security-scan
+ stage: unit-tests
sast:
- stage: security-scan
- variables:
- VALIDATE_SCHEMA: "true"
+ stage: unit-tests
.secret-analyzer:
- stage: security-scan
+ stage: unit-tests
+
+ custom job:
+ stage: unit-tests
+ script:
+ - echo "custom job"
```
-## Interacting with findings and vulnerabilities
+Learn more on overriding security jobs:
+
+- [Overriding SAST jobs](sast/index.md#overriding-sast-jobs).
+- [Overriding Dependency Scanning jobs](dependency_scanning/index.md#overriding-dependency-scanning-jobs).
+- [Overriding Container Scanning jobs](container_scanning/index.md#overriding-the-container-scanning-template).
+- [Overriding Secret Detection jobs](secret_detection/index.md#customizing-settings).
+- [Overriding DAST jobs](dast/index.md#customize-dast-settings).
+- [Overriding License Compliance jobs](../compliance/license_compliance/index.md#overriding-the-template).
+
+All the security scanning tools define their stage, so this error can occur with all of them.
+
+## Security report validation
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321918) in GitLab 13.11.
+> - Schema validation message [added](https://gitlab.com/gitlab-org/gitlab/-/issues/321730) in GitLab 14.0.
+
+You can enforce validation of the security report artifacts before ingesting the vulnerabilities.
+This prevents ingestion of broken vulnerability data into the database. GitLab validates the
+artifacts based on the [report schemas](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/tree/master/dist).
+
+In GitLab 14.0 and later, when artifact validation is enabled, the pipeline's **Security** tab lists
+any report artifacts that failed validation.
+
+### Enable security report validation
+
+To enable report artifacts validation, set the `VALIDATE_SCHEMA` environment variable to `"true"`
+for the desired jobs in the `.gitlab-ci.yml` file.
-There are a variety of locations and ways to interact with the results of the security scanning tools:
+For example, to enable validation for only the `sast` job:
+
+```yaml
+include:
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
+ - template: Security/License-Scanning.gitlab-ci.yml
+ - template: Security/SAST.gitlab-ci.yml
+ - template: Security/Secret-Detection.gitlab-ci.yml
+stages:
+ - security-scan
+dependency_scanning:
+ stage: security-scan
+license_scanning:
+ stage: security-scan
+sast:
+ stage: security-scan
+ variables:
+ VALIDATE_SCHEMA: "true"
+.secret-analyzer:
+ stage: security-scan
+```
+
+## Interact with findings and vulnerabilities
+
+You can interact with the results of the security scanning tools in several locations:
- [Scan information in merge requests](#view-security-scan-information-in-merge-requests)
- [Project Security Dashboard](security_dashboard/#project-security-dashboard)
@@ -331,13 +410,33 @@ There are a variety of locations and ways to interact with the results of the se
- [Vulnerability Pages](vulnerabilities/index.md)
- [Dependency List](dependency_list/index.md)
-For more details about which findings or vulnerabilities you can view in each of those locations, select the respective link. Each page details the ways in which you can interact with the findings and vulnerabilities. As an example, in most cases findings start out as _detected_ status. You have the option to:
+For more details about which findings or vulnerabilities you can view in each of those locations,
+select the respective link. Each page details the ways in which you can interact with the findings
+and vulnerabilities. As an example, in most cases findings start out as _detected_ status.
+
+You have the option to:
- Change the status.
- Create an issue.
- Link it to an existing issue.
- [Resolve the vulnerability](vulnerabilities/index.md#resolve-a-vulnerability), if a solution is known.
+## Security scanning configuration tips
+
+Each GitLab security scanning tool has a default
+[CI/CD configuration file](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Security),
+also known as a _template_.
+
+When customizing the configuration:
+
+- [Include](../../ci/yaml/index.md#include) the scanning tool's CI/CD template. Don't _copy_ the content
+ of the template.
+- Use the [stable](../../development/cicd/templates.md#stable-version) version of each template
+ for production workflows. The stable version changes less often, and breaking changes are only
+ made between major GitLab versions. The [latest](../../development/cicd/templates.md#latest-version)
+ version contains the most recent changes, but may have significant changes between minor GitLab versions.
+- Only override values in the template as needed. All other values are inherited from the template.
+
## Troubleshooting
### Secure job failing with exit code 1
@@ -352,8 +451,8 @@ variables:
### Outdated security reports
-When a security report generated for a merge request becomes outdated, the merge request shows a warning
-message in the security widget and prompts you to take an appropriate action.
+When a security report generated for a merge request becomes outdated, the merge request shows a
+warning message in the security widget and prompts you to take an appropriate action.
This can happen in two scenarios:
@@ -362,73 +461,28 @@ This can happen in two scenarios:
#### Source branch is behind the target branch
-This means the most recent common ancestor commit between the target branch and the source branch is
-not the most recent commit on the target branch. This is by far the most common situation.
+A security report can be out of date when the most recent common ancestor commit between the
+target branch and the source branch is not the most recent commit on the target branch.
-In this case you must rebase or merge to incorporate the changes from the target branch.
+To fix this issue, rebase or merge to incorporate the changes from the target branch.
![Incorporate target branch changes](img/outdated_report_branch_v12_9.png)
#### Target branch security report is out of date
-This can happen for many reasons, including failed jobs or new advisories. When the merge request shows that a
-security report is out of date, you must run a new pipeline on the target branch.
-You can do it quickly by following the hyperlink given to run a new pipeline.
+This can happen for many reasons, including failed jobs or new advisories. When the merge request
+shows that a security report is out of date, you must run a new pipeline on the target branch.
+Select **new pipeline** to run a new pipeline.
![Run a new pipeline](img/outdated_report_pipeline_v12_9.png)
-### Getting error message `sast job: stage parameter should be [some stage name here]`
-
-When [including](../../ci/yaml/index.md#includetemplate) a `.gitlab-ci.yml` template
-like [`SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml),
-the following error may occur, depending on your GitLab CI/CD configuration:
-
-```plaintext
-Found errors in your .gitlab-ci.yml:
-
-* sast job: stage parameter should be unit-tests
-```
-
-This error appears when the included job's stage (named `test`) isn't declared in `.gitlab-ci.yml`.
-To fix this issue, you can either:
-
-- Add a `test` stage in your `.gitlab-ci.yml`.
-- Override the default stage of each security job. For example, to use a pre-defined stage name `unit-tests`:
-
- ```yaml
- include:
- - template: Security/Dependency-Scanning.gitlab-ci.yml
- - template: Security/License-Scanning.gitlab-ci.yml
- - template: Security/SAST.gitlab-ci.yml
- - template: Security/Secret-Detection.gitlab-ci.yml
-
- stages:
- - unit-tests
-
- dependency_scanning:
- stage: unit-tests
-
- license_scanning:
- stage: unit-tests
-
- sast:
- stage: unit-tests
-
- .secret-analyzer:
- stage: unit-tests
- ```
-
-[Learn more on overriding SAST jobs](sast/index.md#overriding-sast-jobs).
-All the security scanning tools define their stage, so this error can occur with all of them.
-
### Getting warning messages `… report.json: no matching files`
-This is often followed by the [error `No files to upload`](../../ci/pipelines/job_artifacts.md#error-message-no-files-to-upload),
-and preceded by other errors or warnings that indicate why the JSON report wasn't generated. Please
-check the entire job log for such messages. If you don't find these messages, retry the failed job
-after setting `SECURE_LOG_LEVEL: "debug"` as a
-[custom CI/CD variable](../../ci/variables/index.md#custom-cicd-variables).
-This provides useful information to investigate further.
+This message is often followed by the [error `No files to upload`](../../ci/pipelines/job_artifacts.md#error-message-no-files-to-upload),
+and preceded by other errors or warnings that indicate why the JSON report wasn't generated. Check
+the entire job log for such messages. If you don't find these messages, retry the failed job after
+setting `SECURE_LOG_LEVEL: "debug"` as a [custom CI/CD variable](../../ci/variables/index.md#custom-cicd-variables).
+This provides extra information to investigate further.
### Getting error message `sast job: config key may not be used with 'rules': only/except`
@@ -526,23 +580,24 @@ involve pinning to the previous template versions, for example:
```
Additionally, we provide a dedicated project containing the versioned legacy templates.
-This can be useful for offline setups or anyone wishing to use [Auto DevOps](../../topics/autodevops/index.md).
+This can be used for offline setups or anyone wishing to use [Auto DevOps](../../topics/autodevops/index.md).
Instructions are available in the [legacy template project](https://gitlab.com/gitlab-org/auto-devops-v12-10).
#### Vulnerabilities are found, but the job succeeds. How can I have a pipeline fail instead?
-This is the current default behavior, because the job's status indicates success or failure of the analyzer itself.
-Analyzer results are displayed in the [job logs](../../ci/jobs/index.md#expand-and-collapse-job-log-sections),
-[Merge Request widget](#view-security-scan-information-in-merge-requests)
-or [Security Dashboard](security_dashboard/index.md).
+In these circumstances, that the job succeeds is the default behavior. The job's status indicates
+success or failure of the analyzer itself. Analyzer results are displayed in the
+[job logs](../../ci/jobs/index.md#expand-and-collapse-job-log-sections),
+[Merge Request widget](#view-security-scan-information-in-merge-requests) or
+[Security Dashboard](security_dashboard/index.md).
### Error: job `is used for configuration only, and its script should not be executed`
[Changes made in GitLab 13.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41260)
to the `Security/Dependency-Scanning.gitlab-ci.yml` and `Security/SAST.gitlab-ci.yml`
templates mean that if you enable the `sast` or `dependency_scanning` jobs by setting the `rules` attribute,
-they will fail with the error `(job) is used for configuration only, and its script should not be executed`.
+they fail with the error `(job) is used for configuration only, and its script should not be executed`.
The `sast` or `dependency_scanning` stanzas can be used to make changes to all SAST or Dependency Scanning,
such as changing `variables` or the `stage`, but they cannot be used to define shared `rules`.
diff --git a/doc/user/application_security/offline_deployments/index.md b/doc/user/application_security/offline_deployments/index.md
index cdf54070d69..915e43d0fa5 100644
--- a/doc/user/application_security/offline_deployments/index.md
+++ b/doc/user/application_security/offline_deployments/index.md
@@ -87,7 +87,9 @@ above. You can find more information at each of the pages below:
- [Container scanning offline directions](../container_scanning/index.md#running-container-scanning-in-an-offline-environment)
- [SAST offline directions](../sast/index.md#running-sast-in-an-offline-environment)
+- [Secret Detection offline directions](../secret_detection/#running-secret-detection-in-an-offline-environment)
- [DAST offline directions](../dast/run_dast_offline.md#run-dast-in-an-offline-environment)
+- [API Fuzzing offline directions](../api_fuzzing/#running-api-fuzzing-in-an-offline-environment)
- [License Compliance offline directions](../../compliance/license_compliance/index.md#running-license-compliance-in-an-offline-environment)
- [Dependency Scanning offline directions](../dependency_scanning/index.md#running-dependency-scanning-in-an-offline-environment)
diff --git a/doc/user/application_security/policies/index.md b/doc/user/application_security/policies/index.md
index e1ddb3167ff..4d8be411dc5 100644
--- a/doc/user/application_security/policies/index.md
+++ b/doc/user/application_security/policies/index.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Policies **(ULTIMATE)**
-> - Introduced in GitLab Ultimate 13.10 [with a flag](https://gitlab.com/groups/gitlab-org/-/epics/5329) named `security_orchestration_policies_configuration`. Disabled by default.
-> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/321258) in GitLab Ultimate 14.3.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5329) in GitLab 13.10 with a flag named `security_orchestration_policies_configuration`. Disabled by default.
+> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/321258) in GitLab 14.3.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/321258) in GitLab 14.4.
Policies in GitLab provide security teams a way to require scans of their choice to be run
@@ -49,7 +49,7 @@ users must make changes by following the
## Policy editor
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3403) in GitLab Ultimate 13.4.
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3403) in GitLab 13.4.
You can use the policy editor to create, edit, and delete policies:
@@ -79,7 +79,7 @@ mode to fix your policy before Rule mode is available again.
## Container Network Policy
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32365) in GitLab Ultimate 12.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32365) in GitLab 12.9.
The **Container Network Policy** section provides packet flow metrics for
your application's Kubernetes namespace. This section has the following
@@ -118,9 +118,9 @@ examining the Cilium logs:
kubectl -n gitlab-managed-apps logs -l k8s-app=cilium -c cilium-monitor
```
-### Change the enforcement status
+### Change the status
-To change a network policy's enforcement status:
+To change a network policy's status:
- Select the network policy you want to update.
- Select **Edit policy**.
@@ -154,12 +154,12 @@ at the bottom of the editor.
### Configure a Network Policy Alert
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) and [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in GitLab Ultimate 13.9.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) and [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in GitLab 13.9.
> - The feature flag was removed and the Threat Monitoring Alerts Project was [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in GitLab 14.0.
You can use policy alerts to track your policy's impact. Alerts are only available if you've
[installed](../../clusters/agent/repository.md)
-and [configured](../../clusters/agent/index.md#create-an-agent-record-in-gitlab)
+and [configured](../../clusters/agent/install/index.md#create-an-agent-record-in-gitlab)
a Kubernetes Agent for this project.
There are two ways to create policy alerts:
diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md
index d399dcaf4a9..06c57e68121 100644
--- a/doc/user/application_security/sast/analyzers.md
+++ b/doc/user/application_security/sast/analyzers.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# SAST Analyzers **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3775) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.3.
-> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) to GitLab Free in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3775) in GitLab 10.3.
+> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) from GitLab Ultimate to GitLab Free in 13.3.
SAST relies on underlying third party tools that are wrapped into what we call
"Analyzers". An analyzer is a
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index 7ffefd34e40..af8585c6a18 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -7,8 +7,8 @@ type: reference, howto
# Static Application Security Testing (SAST) **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3775) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.3.
-> - All open source (OSS) analyzers were moved to GitLab Free in GitLab 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3775) in GitLab 10.3.
+> - All open source (OSS) analyzers were moved from GitLab Ultimate to GitLab Free in GitLab 13.3.
NOTE:
The whitepaper ["A Seismic Shift in Application Security"](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)
@@ -16,11 +16,10 @@ explains how 4 of the top 6 attacks were application based. Download it to learn
organization.
If you're using [GitLab CI/CD](../../../ci/index.md), you can use Static Application Security
-Testing (SAST) to check your source code for known vulnerabilities. When a pipeline completes,
-the results of the SAST analysis are processed and shown in the pipeline's Security tab. If the
-pipeline is associated with a merge request, the SAST analysis is compared with the results of
+Testing (SAST) to check your source code for known vulnerabilities.
+If the pipeline is associated with a merge request, the SAST analysis is compared with the results of
the target branch's analysis (if available). The results of that comparison are shown in the merge
-request. **(ULTIMATE)** If the pipeline is running from the default branch, the results of the SAST
+request. If the pipeline is running from the default branch, the results of the SAST
analysis are available in the [security dashboards](../security_dashboard/index.md).
![SAST results shown in the MR widget](img/sast_results_in_mr_v14_0.png)
@@ -197,7 +196,7 @@ Use the method that best meets your needs.
- [Configure SAST in the UI with default settings](#configure-sast-in-the-ui-with-default-settings)
- [Configure SAST in the UI with customizations](#configure-sast-in-the-ui-with-customizations)
-### Configure SAST in the UI with default settings **(FREE)**
+### Configure SAST in the UI with default settings
> [Introduced](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#security-configuration-page-for-all-users) in GitLab 13.9
@@ -217,9 +216,9 @@ successfully, and an error may occur.
### Configure SAST in the UI with customizations **(ULTIMATE)**
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3659) in GitLab Ultimate 13.3.
-> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/232862) in GitLab Ultimate 13.4.
-> - [Improved](https://gitlab.com/groups/gitlab-org/-/epics/3635) in GitLab Ultimate 13.5.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3659) in GitLab 13.3.
+> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/232862) in GitLab 13.4.
+> - [Improved](https://gitlab.com/groups/gitlab-org/-/epics/3635) in GitLab 13.5.
To enable and configure SAST with customizations:
@@ -402,7 +401,7 @@ To create a custom ruleset:
### False Positive Detection **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292686) in GitLab 14.2.
+> Introduced in GitLab 14.2.
Vulnerabilities that have been detected and are false positives will be flagged as false positives in the security dashboard.
@@ -423,7 +422,7 @@ Read more on [how to use private Maven repositories](../index.md#using-private-m
### Enabling Kubesec analyzer
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12752) in GitLab Ultimate 12.6.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12752) in GitLab 12.6.
You need to set `SCAN_KUBERNETES_MANIFESTS` to `"true"` to enable the
Kubesec analyzer. In `.gitlab-ci.yml`, define:
@@ -569,7 +568,7 @@ Some analyzers can be customized with CI/CD variables.
#### Custom CI/CD variables
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18193) in GitLab Ultimate 12.5.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18193) in GitLab 12.5.
In addition to the aforementioned SAST configuration CI/CD variables,
all [custom variables](../../../ci/variables/index.md#custom-cicd-variables) are propagated
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index 5933496ea00..140f660d729 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -7,8 +7,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Secret Detection **(FREE)**
-> - [Introduced](https://about.gitlab.com/releases/2019/03/22/gitlab-11-9-released/#detect-secrets-and-credentials-in-the-repository) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9.
-> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/222788) in 13.3.
+> - [Introduced](https://about.gitlab.com/releases/2019/03/22/gitlab-11-9-released/#detect-secrets-and-credentials-in-the-repository) in GitLab 11.9.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/222788) from GitLab Ultimate to GitLab Free in 13.3.
A recurring problem when developing applications is that developers may unintentionally commit
secrets and credentials to their remote repositories. If other people have access to the source,
@@ -138,9 +138,9 @@ The results are saved as a
that you can later download and analyze. Due to implementation limitations, we
always take the latest Secret Detection artifact available.
-### Enable Secret Detection via an automatic merge request **(FREE)**
+### Enable Secret Detection via an automatic merge request
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4496) in GitLab 13.11, behind a feature flag, enabled by default.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4496) in GitLab 13.11, deployed behind a feature flag, enabled by default.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/329886) in GitLab 14.1.
To enable Secret Detection in a project, you can create a merge request
@@ -165,7 +165,7 @@ by using the
[`variables`](../../../ci/yaml/index.md#variables) parameter in `.gitlab-ci.yml`.
To override a job definition, (for example, change properties like `variables` or `dependencies`),
-declare a job with the same name as the SAST job to override. Place this new job after the template
+declare a job with the same name as the secret detection job to override. Place this new job after the template
inclusion and specify any additional keys under it.
WARNING:
@@ -202,8 +202,9 @@ Secret Detection can be customized by defining available CI/CD variables:
| CI/CD variable | Default value | Description |
|-----------------------------------|---------------|-------------|
-| `SECRET_DETECTION_COMMIT_FROM` | - | The commit a Gitleaks scan starts at. |
-| `SECRET_DETECTION_COMMIT_TO` | - | The commit a Gitleaks scan ends at. |
+| `SECRET_DETECTION_COMMIT_FROM` | - | The commit a Gitleaks scan starts at. [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/243564) in GitLab 13.5. Replaced with `SECRET_DETECTION_COMMITS`. |
+| `SECRET_DETECTION_COMMIT_TO` | - | The commit a Gitleaks scan ends at. [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/243564) in GitLab 13.5. Replaced with `SECRET_DETECTION_COMMITS`. |
+| `SECRET_DETECTION_COMMITS` | - | The list of commits that Gitleaks should scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/243564) in GitLab 13.5. |
| `SECRET_DETECTION_EXCLUDED_PATHS` | "" | Exclude vulnerabilities from output based on the paths. This is a comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec` ). Parent directories also match patterns. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225273) in GitLab 13.3. |
| `SECRET_DETECTION_HISTORIC_SCAN` | false | Flag to enable a historic Gitleaks scan. |
@@ -348,6 +349,22 @@ For details on saving and transporting Docker images as a file, see Docker's doc
[`docker save`](https://docs.docker.com/engine/reference/commandline/save/), [`docker load`](https://docs.docker.com/engine/reference/commandline/load/),
[`docker export`](https://docs.docker.com/engine/reference/commandline/export/), and [`docker import`](https://docs.docker.com/engine/reference/commandline/import/).
+### Set Secret Detection CI/CD variables to use the local Secret Detection analyzer container image
+
+Add the following configuration to your `.gitlab-ci.yml` file. You must replace
+`SECURE_ANALYZERS_PREFIX` to refer to your local Docker container registry:
+
+```yaml
+include:
+ - template: Security/Secret-Detection.gitlab-ci.yml
+
+variables:
+ SECURE_ANALYZERS_PREFIX: "localhost:5000/analyzers"
+```
+
+The Secret Detection job should now use the local copy of the Secret Detection analyzer Docker image to scan your code and generate
+security reports without requiring internet access.
+
#### If support for Custom Certificate Authorities are needed
Support for custom certificate authorities was introduced in the following versions.
@@ -371,22 +388,6 @@ variables:
The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a [custom variable in the UI](../../../ci/variables/index.md#custom-cicd-variables), either as a `file`, which requires the path to the certificate, or as a variable, which requires the text representation of the certificate.
-### Set Secret Detection CI/CD variables to use local Secret Detection analyzer
-
-Add the following configuration to your `.gitlab-ci.yml` file. You must replace
-`SECURE_ANALYZERS_PREFIX` to refer to your local Docker container registry:
-
-```yaml
-include:
- - template: Security/Secret-Detection.gitlab-ci.yml
-
-variables:
- SECURE_ANALYZERS_PREFIX: "localhost:5000/analyzers"
-```
-
-The Secret Detection job should now use local copies of the Secret Detection analyzer to scan your code and generate
-security reports without requiring internet access.
-
## Troubleshooting
### Getting warning message `gl-secret-detection-report.json: no matching files`
diff --git a/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_2.png b/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_2.png
deleted file mode 100644
index 52249cef343..00000000000
--- a/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_4.png b/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_4.png
new file mode 100644
index 00000000000..ac123d2b528
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_4.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md
index c78179e9693..87875ec15ba 100644
--- a/doc/user/application_security/security_dashboard/index.md
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -51,7 +51,7 @@ The security dashboard and vulnerability report displays information about vulne
At the pipeline level, the Security section displays the vulnerabilities present in the branch of
the project the pipeline ran against.
-![Pipeline Security Dashboard](img/pipeline_security_dashboard_v14_2.png)
+![Pipeline Security Dashboard](img/pipeline_security_dashboard_v14_4.png)
Visit the page for any pipeline that ran any of the [supported reports](#supported-reports). To view
the pipeline's security findings, select the **Security** tab when viewing the pipeline.
@@ -64,11 +64,15 @@ the analyzer outputs an
### Scan details
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3728) in GitLab 13.10.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3728) in GitLab 13.10.
+> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/333660) in GitLab 14.2.
-The **Scan details** section lists the scans run in the pipeline and the total number of
-vulnerabilities per scan. For the DAST scan, select **Download scanned resources** to download a
-CSV file containing details of the resources scanned.
+The **Scan details** section lists the scans run in the pipeline and the total number of vulnerabilities
+per scan.
+
+You can download the JSON artifacts from each security scan. Select **Download results** then
+select the JSON artifact. Additionally for the DAST scan, from the **Download results** dropdown select
+**Download scanned resources** to download a CSV file containing details of the resources scanned.
## Project Security Dashboard
diff --git a/doc/user/application_security/threat_monitoring/index.md b/doc/user/application_security/threat_monitoring/index.md
index 79f202a6edb..ae5f6ba0fe1 100644
--- a/doc/user/application_security/threat_monitoring/index.md
+++ b/doc/user/application_security/threat_monitoring/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Threat Monitoring **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14707) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14707) in GitLab 12.9.
The **Threat Monitoring** page provides alerts and metrics
for the GitLab application runtime security features. You can access
@@ -20,7 +20,7 @@ GitLab supports statistics for the following security features:
## Container Network Policy Alert list
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.9.
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) in GitLab 13.9.
The policy alert list displays your policy's alert activity. You can sort the list by these columns:
@@ -44,5 +44,3 @@ Clicking an alert's row opens the alert drawer, which shows more information abo
can also create an incident from the alert and update the alert status in the alert drawer.
Clicking an alert's name takes the user to the [alert details page](../../../operations/incident_management/alerts.md#alert-details-page).
-
-For information on work in progress for the alerts dashboard, see [this epic](https://gitlab.com/groups/gitlab-org/-/epics/5041).
diff --git a/doc/user/application_security/vulnerabilities/index.md b/doc/user/application_security/vulnerabilities/index.md
index 9ebecc67704..7bdc8cc8479 100644
--- a/doc/user/application_security/vulnerabilities/index.md
+++ b/doc/user/application_security/vulnerabilities/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Vulnerability Pages **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13561) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13561) in GitLab 13.0.
Each vulnerability in a project has a Vulnerability Page. This page contains details of the
vulnerability. The details included vary according to the type of vulnerability. Details of each
@@ -20,6 +20,9 @@ vulnerability include:
- Linked issues
- Actions log
+In GitLab 14.3 and later, if the scanner determined the vulnerability to be a false positive, an
+alert message is included at the top of the vulnerability's page.
+
On the vulnerability's page, you can:
- [Change the vulnerability's status](#change-vulnerability-status).
diff --git a/doc/user/application_security/vulnerability_report/img/group_vulnerability_report_v14_2.png b/doc/user/application_security/vulnerability_report/img/group_vulnerability_report_v14_2.png
deleted file mode 100644
index 44c689eda3e..00000000000
--- a/doc/user/application_security/vulnerability_report/img/group_vulnerability_report_v14_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/vulnerability_report/img/project_level_vulnerability_report_v14_5.png b/doc/user/application_security/vulnerability_report/img/project_level_vulnerability_report_v14_5.png
new file mode 100644
index 00000000000..ac996fa32db
--- /dev/null
+++ b/doc/user/application_security/vulnerability_report/img/project_level_vulnerability_report_v14_5.png
Binary files differ
diff --git a/doc/user/application_security/vulnerability_report/index.md b/doc/user/application_security/vulnerability_report/index.md
index f5b0194c320..d13647937a2 100644
--- a/doc/user/application_security/vulnerability_report/index.md
+++ b/doc/user/application_security/vulnerability_report/index.md
@@ -16,7 +16,16 @@ At all levels, the Vulnerability Report contains:
- Filters for common vulnerability attributes.
- Details of each vulnerability, presented in tabular layout.
-![Vulnerability Report](img/group_vulnerability_report_v14_2.png)
+The **Activity** column contains icons to indicate the activity, if any, taken on the vulnerability
+in that row:
+
+- Issues **{issues}**: Links to issues created for the vulnerability. For more details, read
+ [Create an issue for a vulnerability](../vulnerabilities/index.md#create-an-issue-for-a-vulnerability).
+- Wrench **{admin}**: The vulnerability has been remediated.
+- False positive **{false-positive}**: The scanner determined this vulnerability to be a false
+ positive.
+
+![Example project-level Vulnerability Report](img/project_level_vulnerability_report_v14_5.png)
## Project-level Vulnerability Report
@@ -151,7 +160,7 @@ To change the status of vulnerabilities in the table:
### Change status of multiple vulnerabilities
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35816) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35816) in GitLab 12.9.
You can change the status of multiple vulnerabilities at once:
@@ -162,8 +171,8 @@ You can change the status of multiple vulnerabilities at once:
## Export vulnerability details
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213014) in the Security Center (previously known as the Instance Security Dashboard) and project-level Vulnerability Report (previously known as the Project Security Dashboard) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0.
-> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/213013) to the group-level Vulnerability Report in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213014) in the Security Center (previously known as the Instance Security Dashboard) and project-level Vulnerability Report (previously known as the Project Security Dashboard) in GitLab 13.0.
+> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/213013) to the group-level Vulnerability Report in GitLab 13.1.
You can export details of the vulnerabilities listed in the Vulnerability Report. The export format
is CSV (comma separated values). Note that all vulnerabilities are included because filters don't
@@ -197,7 +206,7 @@ thousands of vulnerabilities. Don't close the page until the download finishes.
## Dismiss a vulnerability
-> The option of adding a dismissal reason was introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
+> The option of adding a dismissal reason was introduced in GitLab 12.0.
You can dismiss a vulnerability for the entire project:
diff --git a/doc/user/clusters/agent/ci_cd_tunnel.md b/doc/user/clusters/agent/ci_cd_tunnel.md
index 6c8b7c95771..0dfdb37dc1f 100644
--- a/doc/user/clusters/agent/ci_cd_tunnel.md
+++ b/doc/user/clusters/agent/ci_cd_tunnel.md
@@ -4,15 +4,13 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# CI/CD Tunnel **(PREMIUM)**
+# CI/CD Tunnel **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327409) in GitLab 14.1.
> - The pre-configured `KUBECONFIG` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/324275) in GitLab 14.2.
> - The ability to authorize groups was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
-
-WARNING:
-The CI/CD Tunnel is not supported for GitLab self-managed instances installed via Omnibus. We
-plan to [add support for Omnibus](https://gitlab.com/gitlab-org/gitlab/-/issues/324272) in the future.
+> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) to GitLab Free in 14.5.
+> - Support for Omnibus installations was [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5686) in GitLab 14.5.
The CI/CD Tunnel enables users to access Kubernetes clusters from GitLab CI/CD jobs even if there is no network
connectivity between GitLab Runner and a cluster. GitLab Runner does not have to be running in the same cluster.
@@ -21,11 +19,11 @@ Only CI/CD jobs set in the configuration project can access one of the configure
## Prerequisites
-- A running [`kas` instance](index.md#set-up-the-kubernetes-agent-server).
-- A [configuration repository](index.md#define-a-configuration-repository) with an Agent config file
+- A running [`kas` instance](install/index.md#set-up-the-kubernetes-agent-server).
+- A [configuration repository](install/index.md#define-a-configuration-repository) with an Agent config file
installed (`.gitlab/agents/<agent-name>/config.yaml`).
-- An [Agent record](index.md#create-an-agent-record-in-gitlab).
-- The Agent [installed in the cluster](index.md#install-the-agent-into-the-cluster).
+- An [Agent record](install/index.md#create-an-agent-record-in-gitlab).
+- The Agent [installed in the cluster](install/index.md#install-the-agent-into-the-cluster).
## Use the CI/CD Tunnel to run Kubernetes commands from GitLab CI/CD
@@ -37,6 +35,16 @@ there isn't any context selected.
Contexts are named in the following format: `<agent-configuration-project-path>:<agent-name>`.
To get the list of available contexts, run `kubectl config get-contexts`.
+## Share the CI/CD Tunnel provided by an Agent with other projects and groups
+
+The Agent can be configured to enable access to the CI/CD Tunnel to other projects or all the projects under a given group. This way you can have a single agent serving all the requests for several projects saving on resources and maintenance.
+
+You can read more on how to [authorize access in the Agent configuration reference](repository.md#authorize-projects-and-groups-to-use-an-agent).
+
+## Restrict access of authorized projects and groups **(PREMIUM)**
+
+You can [configure various impersonations](repository.md#use-impersonation-to-restrict-project-and-group-access) to restrict the permissions of a shared CI/CD Tunnel.
+
## Example for a `kubectl` command using the CI/CD Tunnel
The following example shows a CI/CD job that runs a `kubectl` command using the CI/CD Tunnel.
diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md
index 557d389147d..80b9f3f17f5 100644
--- a/doc/user/clusters/agent/index.md
+++ b/doc/user/clusters/agent/index.md
@@ -4,31 +4,58 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab Kubernetes Agent **(PREMIUM)**
+# GitLab Kubernetes Agent **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223061) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
-> - [Introduced](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/7) in GitLab 13.6, `grpcs` is supported.
+> - Support for `grpcs` [introduced](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/7) in GitLab 13.6.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300960) in GitLab 13.10, KAS became available on GitLab.com under `wss://kas.gitlab.com` through an Early Adopter Program.
> - Introduced in GitLab 13.11, the GitLab Kubernetes Agent became available to every project on GitLab.com.
+> - The GitLab Kubernetes Agent was [moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) to GitLab Free in 14.5.
-The [GitLab Kubernetes Agent](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent)
-is an active in-cluster component for solving GitLab and Kubernetes integration
-tasks in a secure and cloud-native way. It enables:
+The [GitLab Kubernetes Agent](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent) ("Agent", for short)
+is an active in-cluster component for connecting Kubernetes clusters to GitLab safely to support cloud-native deployment, management, and monitoring.
-- GitLab integration with a Kubernetes cluster behind a firewall or NAT
- (network address translation).
-- Pull-based GitOps deployments.
-- [Inventory object](../../infrastructure/clusters/deploy/inventory_object.md) to keep track of objects applied to your cluster.
-- Real-time access to API endpoints in a cluster.
-- Alert generation based on [Container network policy](../../application_security/policies/index.md#container-network-policy).
-- [CI/CD Tunnel](ci_cd_tunnel.md) that enables users to access Kubernetes clusters from GitLab CI/CD jobs even if there is no network connectivity between GitLab Runner and a cluster.
+The Agent is installed into the cluster through code, providing you with a fast, safe, stable, and scalable solution.
-Many more features are planned. Please review [our roadmap](https://gitlab.com/groups/gitlab-org/-/epics/3329)
-and [our development documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/doc).
+With GitOps, you can manage containerized clusters and applications from a Git repository that:
-## GitLab Agent GitOps workflow
+- Is the single source of truth of your system.
+- Is the single place where you operate your system.
+- Is a single resource to monitor your system.
-The GitLab Agent, herein _Agent_, uses multiple GitLab projects to provide a flexible workflow
+By combining GitLab, Kubernetes, and GitOps, it results in a robust infrastructure:
+
+- GitLab as the GitOps operator.
+- Kubernetes as the automation and convergence system.
+- GitLab CI/CD as the Continuous Integration and Continuous Deployment engine.
+
+Beyond that, you can use all the features offered by GitLab as
+the all-in-one DevOps platform for your product and your team.
+
+## Agent's features
+
+By using the GitLab Kubernetes Agent, you can:
+
+- Connect GitLab with a Kubernetes cluster behind a firewall or a
+Network Address Translation (NAT).
+- Have real-time access to API endpoints in your cluster from GitLab CI/CD.
+- Use GitOps to configure your cluster through the [Agent's repository](repository.md).
+- Perform pull-based or push-based GitOps deployments.
+- Configure [Network Security Alerts](#kubernetes-network-security-alerts)
+based on [Container Network Policies](../../application_security/policies/index.md#container-network-policy).
+- Track objects applied to your cluster through [inventory objects](../../infrastructure/clusters/deploy/inventory_object.md).
+- Use the [CI/CD Tunnel](ci_cd_tunnel.md) to access Kubernetes clusters
+from GitLab CI/CD jobs while keeping the cluster's APIs safe and unexposed
+to the internet.
+- [Deploy the GitLab Runner in a Kubernetes cluster](https://docs.gitlab.com/runner/install/kubernetes-agent.html).
+
+See the [GitLab Kubernetes Agent roadmap](https://gitlab.com/groups/gitlab-org/-/epics/3329) to track its development.
+
+To contribute to the Agent, see the [Agent's development documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/doc).
+
+## Agent's GitOps workflow **(PREMIUM)**
+
+The Agent uses multiple GitLab projects to provide a flexible workflow
that can suit various needs. This diagram shows these repositories and the main
actors involved in a deployment:
@@ -50,365 +77,35 @@ sequenceDiagram
end
```
-There are several components that work in concert for the Agent to accomplish GitOps deployments:
-
-- A properly-configured Kubernetes cluster where the Agent is running.
-- A configuration repository that contains a `config.yaml` file, which tells the
- Agent the repositories to synchronize with the cluster.
-- A manifest repository that contains manifest files. Any changes to manifest files are applied to the cluster.
-
-You can use the same GitLab project or projects for configuration and manifest files, as follows:
-
-- Single GitLab project (recommended): when you use a single repository to hold both the manifest and the configuration files, these projects can be either private or public, as you prefer.
-- Two GitLab projects: when you opt to use two different GitLab projects, one for manifest files, and another for configuration files, the manifests project must be public, while the configuration project can be either private or public. Our backlog contains issues for adding support for
-[private manifest repositories outside of the configuration project](https://gitlab.com/gitlab-org/gitlab/-/issues/220912) and
-[group level agents](https://gitlab.com/gitlab-org/gitlab/-/issues/283885) in the future.
-
-For more details, please refer to our [full architecture documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md#high-level-architecture) in the Agent project.
-
-## Get started with GitOps and the GitLab Agent
-
-The setup process involves a few steps to enable GitOps deployments:
-
-1. [Set up the Kubernetes Agent Server](#set-up-the-kubernetes-agent-server) for your GitLab instance.
-1. [Define a configuration repository](#define-a-configuration-repository).
-1. [Create an Agent record in GitLab](#create-an-agent-record-in-gitlab).
-1. [Install the Agent into the cluster](#install-the-agent-into-the-cluster).
-1. [Generate and copy a Secret token used to connect to the Agent](#create-the-kubernetes-secret).
-1. [Create manifest files](#create-manifest-files).
-
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> Watch a GitLab 14.2 [walking-through video](https://www.youtube.com/watch?v=XuBpKtsgGkE) with this process.
-
-### Upgrades and version compatibility
-
-As the GitLab Kubernetes Agent is a new product, we are constantly adding new features
-to it. As a result, while shipped features are production ready, its internal API is
-neither stable nor versioned yet. For this reason, GitLab only guarantees compatibility
-between corresponding major.minor (X.Y) versions of GitLab and its cluster side
-component, `agentk`.
-
-Upgrade your agent installations together with GitLab upgrades. To decide which version of `agentk` to install follow:
-
-1. Open the [`GITLAB_KAS_VERSION`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/GITLAB_KAS_VERSION) file from the GitLab Repository, which contains the latest `agentk` version associated with the `master` branch.
-1. Change the `master` branch and select the Git tag associated with your version. For instance, you could change it to GitLab [v13.5.3-ee release](https://gitlab.com/gitlab-org/gitlab/-/blob/v13.5.3-ee/GITLAB_KAS_VERSION)
-
-The available `agentk` and `kas` versions can be found in
-[the container registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/).
-
-### Set up the Kubernetes Agent Server
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.10, the GitLab Kubernetes Agent Server (KAS) became available on GitLab.com under `wss://kas.gitlab.com`.
-
-To use the KAS:
-
-- If you are a self-managed user, follow the instructions to [install the Kubernetes Agent Server](../../../administration/clusters/kas.md).
-- If you are a GitLab.com user, when you [set up the configuration repository](#define-a-configuration-repository) for your agent, use `wss://kas.gitlab.com` as the `--kas-address`.
-
-### Define a configuration repository
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in GitLab 13.7, the Agent manifest configuration can be added to multiple directories (or subdirectories) of its repository.
-> - Group authorization was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
-
-To configure an Agent, you need:
-
-1. A GitLab repository to hold the configuration file.
-1. Install the Agent in a cluster.
-
-After installed, when you update the configuration file, GitLab transmits the
-information to the cluster automatically without downtime.
-
-In your repository, add the Agent configuration file under:
-
-```plaintext
-.gitlab/agents/<agent-name>/config.yaml
-```
-
-Your `config.yaml` file specifies all configurations of the Agent, such as:
-
-- The manifest projects to synchronize.
-- The groups that can access this Agent via the [CI/CD Tunnel](ci_cd_tunnel.md).
-- The address of the `hubble-relay` for the Network Security policy integrations.
-
-As an example, a minimal Agent configuration that sets up only the manifest
-synchronizations is:
-
-```yaml
-gitops:
- manifest_projects:
- - id: "path-to/your-manifest-project-1"
- paths:
- - glob: '/**/*.{yaml,yml,json}'
-```
-
-All the options for the [Kubernetes Agent configuration repository](repository.md) are documented separately.
-
-### Create an Agent record in GitLab
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5786) in GitLab 14.1, you can create a new Agent record directly from the GitLab UI.
-
-Next, create a GitLab Rails Agent record to associate it with
-the configuration repository project. Creating this record also creates a Secret needed to configure
-the Agent in subsequent steps.
-
-In GitLab:
-
-1. From your project's sidebar, select **Infrastructure > Kubernetes clusters**.
-1. Select the **GitLab Agent managed clusters** tab.
-1. Select **Integrate with the GitLab Agent**.
-1. From the **Select an Agent** dropdown menu, select the Agent you want to connect and select **Next** to access the installation form.
-1. The form reveals your registration token. Securely store this secret token as you cannot view it again.
-1. Copy the command under **Recommended installation method**.
-
-In your computer:
-
-1. Open your local terminal and connect to your cluster.
-1. Run the command you copied from the installation form.
-
-### Install the Agent into the cluster
-
-To install the in-cluster component of the Agent, first you need to define a namespace. To create a new namespace,
-for example, `gitlab-kubernetes-agent`, run:
-
-```shell
-kubectl create namespace gitlab-kubernetes-agent
-```
-
-To perform a one-liner installation, run the command below. Make sure to replace:
-
-- `your-agent-token` with the token received from the previous step (identified as `secret` in the JSON output).
-- `gitlab-kubernetes-agent` with the namespace you defined in the previous step.
-- `wss://kas.gitlab.example.com` with the configured access of the Kubernetes Agent Server (KAS). For GitLab.com users, the KAS is available under `wss://kas.gitlab.com`.
-- `--agent-version=vX.Y.Z` with the latest released patch version matching your GitLab installation's major and minor versions. For example, for GitLab v13.9.0, use `--agent-version=v13.9.1`. You can find your GitLab version under the "Help/Help" menu.
-
-```shell
-docker run --pull=always --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate --agent-token=your-agent-token --kas-address=wss://kas.gitlab.example.com --agent-version=vX.Y.Z --namespace gitlab-kubernetes-agent | kubectl apply -f -
-```
-
-WARNING:
-`--agent-version stable` can be used to refer to the latest stable release at the time when the command runs. It's fine for
-testing purposes but for production please make sure to specify a matching version explicitly.
-
-To find out the various options the above Docker container supports, run:
-
-```shell
-docker run --pull=always --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate --help
-```
-
-#### Advanced installation
-
-For more advanced configurations, we recommend to use [the `kpt` based installation method](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/build/deployment/gitlab-agent).
-
-Otherwise, follow the manual installation steps described below.
-
-### Create the Kubernetes secret
-
-After generating the token, you must apply it to the Kubernetes cluster.
-
-To create your Secret, run:
-
-```shell
-kubectl create secret generic -n gitlab-kubernetes-agent gitlab-kubernetes-agent-token --from-literal=token='YOUR_AGENT_TOKEN'
-```
-
-The following example file contains the
-Kubernetes resources required for the Agent to be installed. You can modify this
-example [`resources.yml` file](#example-resourcesyml-file) in the following ways:
-
-- Replace `namespace: gitlab-kubernetes-agent` with `namespace: <YOUR-DESIRED-NAMESPACE>`.
-- You can configure `kas-address` (Kubernetes Agent Server) in several ways.
- The agent can use the WebSockets or gRPC protocols to connect to the Agent Server.
- Select the option appropriate for your cluster configuration and GitLab architecture:
- - The `wss` scheme (an encrypted WebSockets connection) is specified by default
- after you install the `gitlab-kas` sub-chart, or enable `gitlab-kas` for Omnibus GitLab.
- When using the sub-chart, you must set `wss://kas.host.tld:443` as
- `kas-address`, where `host.tld` is the domain you've setup for your GitLab installation.
- When using Omnibus GitLab, you must set `wss://GitLab.host.tld:443/-/kubernetes-agent/` as
- `kas-address`, where `GitLab.host.tld` is your GitLab hostname.
- - When using the sub-chart, specify the `ws` scheme (such as `ws://kas.host.tld:80`)
- to use an unencrypted WebSockets connection.
- When using the Omnibus GitLab, specify the `ws` scheme (such as `ws://GitLab.host.tld:80/-/kubernetes-agent/`).
- - Specify the `grpc` scheme if both Agent and Server are installed in one cluster.
- In this case, you may specify `kas-address` value as
- `grpc://gitlab-kas.<your-namespace>:8150`) to use gRPC directly, where `gitlab-kas`
- is the name of the service created by `gitlab-kas` chart, and `<your-namespace>`
- is the namespace where the chart was installed.
- - Specify the `grpcs` scheme to use an encrypted gRPC connection.
- - When deploying KAS through the [GitLab chart](https://docs.gitlab.com/charts/), it's possible to customize the
- `kas-address` for `wss` and `ws` schemes to whatever you need.
- Check the [chart's KAS Ingress documentation](https://docs.gitlab.com/charts/charts/gitlab/kas/#ingress)
- to learn more about it.
- - In the near future, Omnibus GitLab intends to provision `gitlab-kas` under a sub-domain by default, instead of the `/-/kubernetes-agent/` path. Please follow [this issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5784) for details.
-- If you defined your own secret name, replace `gitlab-kubernetes-agent-token` with your
- secret name in the `secretName:` section.
-
-To apply this file, run the following command:
-
-```shell
-kubectl apply -n gitlab-kubernetes-agent -f ./resources.yml
-```
-
-To review your configuration, run the following command:
-
-```shell
-$ kubectl get pods -n gitlab-kubernetes-agent
-
-NAMESPACE NAME READY STATUS RESTARTS AGE
-gitlab-kubernetes-agent gitlab-kubernetes-agent-77689f7dcb-5skqk 1/1 Running 0 51s
-```
-
-#### Example `resources.yml` file
-
-```yaml
----
-apiVersion: v1
-kind: Namespace
-metadata:
- name: gitlab-kubernetes-agent
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
- name: gitlab-kubernetes-agent
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: gitlab-kubernetes-agent
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: gitlab-kubernetes-agent
- template:
- metadata:
- labels:
- app: gitlab-kubernetes-agent
- spec:
- serviceAccountName: gitlab-kubernetes-agent
- containers:
- - name: agent
- # Make sure to specify a matching version for production
- image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:vX.Y.Z
- args:
- - --token-file=/config/token
- - --kas-address
- - wss://kas.host.tld:443 # replace this line with the line below if using Omnibus GitLab or GitLab.com.
- # - wss://gitlab.host.tld:443/-/kubernetes-agent/
- # - wss://kas.gitlab.com # for GitLab.com users, use this KAS.
- # - grpc://host.docker.internal:8150 # use this attribute when connecting from Docker.
- volumeMounts:
- - name: token-volume
- mountPath: /config
- volumes:
- - name: token-volume
- secret:
- secretName: gitlab-kubernetes-agent-token
- strategy:
- type: RollingUpdate
- rollingUpdate:
- maxSurge: 0
- maxUnavailable: 1
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
- name: gitlab-kubernetes-agent-write
-rules:
-- resources:
- - '*'
- apiGroups:
- - '*'
- verbs:
- - create
- - update
- - delete
- - patch
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRoleBinding
-metadata:
- name: gitlab-kubernetes-agent-write-binding
-roleRef:
- name: gitlab-kubernetes-agent-write
- kind: ClusterRole
- apiGroup: rbac.authorization.k8s.io
-subjects:
-- name: gitlab-kubernetes-agent
- kind: ServiceAccount
- namespace: gitlab-kubernetes-agent
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
- name: gitlab-kubernetes-agent-read
-rules:
-- resources:
- - '*'
- apiGroups:
- - '*'
- verbs:
- - get
- - list
- - watch
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRoleBinding
-metadata:
- name: gitlab-kubernetes-agent-read-binding
-roleRef:
- name: gitlab-kubernetes-agent-read
- kind: ClusterRole
- apiGroup: rbac.authorization.k8s.io
-subjects:
-- name: gitlab-kubernetes-agent
- kind: ServiceAccount
- namespace: gitlab-kubernetes-agent
-```
-
-### Create manifest files
-
-In a previous step, you configured a `config.yaml` to point to the GitLab projects
-the Agent should synchronize. Agent monitors each of those projects for changes to the manifest files it contains. You can auto-generate manifest files with a
-templating engine or other means.
-
-The agent is authorized to download manifests for the configuration
-project, and public projects. Support for other private projects is
-planned in the issue [Agent authorization for private manifest
-projects](https://gitlab.com/gitlab-org/gitlab/-/issues/220912).
-
-Each time you push a change to a monitored manifest repository, the Agent logs the change:
-
-```plaintext
-2020-09-15_14:09:04.87946 gitlab-k8s-agent : time="2020-09-15T10:09:04-04:00" level=info msg="Config: new commit" agent_id=1 commit_id=e6a3651f1faa2e928fe6120e254c122451be4eea
-```
+For more details, refer to our [architecture documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md#high-level-architecture) in the Agent project.
-#### Example manifest file
+## Install the Agent in your cluster
-This file creates a minimal `ConfigMap`:
+See how to [install the GitLab Kubernetes Agent in your cluster](install/index.md).
-```yaml
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: demo-map
- namespace: gitlab-kubernetes-agent # Can be any namespace managed by you that the agent has access to.
-data:
- key: value
-```
+## GitOps deployments **(PREMIUM)**
-## Example projects
+To perform GitOps deployments with the Agent, you need:
-The following example projects can help you get started with the Kubernetes Agent.
+- A properly-configured Kubernetes cluster where the Agent is running.
+- A [configuration repository](repository.md) that contains a
+`config.yaml` file, which tells the Agent the repositories to synchronize
+with the cluster.
+- A manifest repository that contains manifest files. Any changes to manifest files are applied to the cluster.
-- [Configuration repository](https://gitlab.com/gitlab-org/configure/examples/kubernetes-agent)
-- This basic GitOps example deploys NGINX: [Manifest repository](https://gitlab.com/gitlab-org/configure/examples/gitops-project)
+You can use a single GitLab project or different projects for the Agent
+configuration and manifest files, as follows:
-### GitLab Runner Deployment with the Agent
+- Single GitLab project (recommended): When you use a single repository to hold
+ both the manifest and the configuration files, these projects can be either
+ private or public.
+- Two GitLab projects: When you use two different GitLab projects (one for
+ manifest files and another for configuration files), the manifests project must
+ be public, while the configuration project can be either private or public.
-You can use the Kubernetes Agent to
-[deploy GitLab Runner in a Kubernetes cluster](https://docs.gitlab.com/runner/install/kubernetes-agent.html).
+Support for separated private manifest and configuration repositories is tracked in this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/220912).
-## Kubernetes Network Security Alerts
+## Kubernetes Network Security Alerts **(ULTIMATE)**
The GitLab Agent also provides an integration with Cilium. This integration provides a simple way to
generate network policy-related alerts and to surface those alerts in GitLab.
@@ -426,24 +123,12 @@ There are several components that work in concert for the Agent to generate the
- Add the required labels and annotations to existing network policies.
- A configuration repository with [Cilium configured in `config.yaml`](repository.md#surface-network-security-alerts-from-cluster-to-gitlab)
-The setup process follows the same steps as [GitOps](#get-started-with-gitops-and-the-gitlab-agent),
+The setup process follows the same [Agent's installation steps](install/index.md),
with the following differences:
- When you define a configuration repository, you must do so with [Cilium settings](repository.md#surface-network-security-alerts-from-cluster-to-gitlab).
- You do not need to specify the `gitops` configuration section.
-## Management interfaces
-
-Users with at least the [Developer](../../permissions.md) can access the user interface
-for the GitLab Kubernetes agent at **Infrastructure > Kubernetes clusters**, under the
-**GitLab Agent managed clusters** tab. This page lists all registered agents for
-the current project, and the configuration directory for each agent:
-
-![GitLab Kubernetes Agent list UI](../img/kubernetes-agent-ui-list_v13_8.png)
-
-Additional management interfaces are planned for the GitLab Kubernetes Agent.
-[Provide more feedback in the related epic](https://gitlab.com/groups/gitlab-org/-/epics/4739).
-
## Remove the GitLab Kubernetes Agent
1. Remove an Agent record with GraphQL by deleting the `clusterAgent` and the `clusterAgentToken`.
@@ -518,7 +203,7 @@ specified the `kas-address` correctly.
```
This error occurs if the `kas-address` doesn't include a trailing slash. To fix it, make sure that the
-`wss` or `ws` URL ends with a training slash, such as `wss://GitLab.host.tld:443/-/kubernetes-agent/`
+`wss` or `ws` URL ends with a trailing slash, such as `wss://GitLab.host.tld:443/-/kubernetes-agent/`
or `ws://GitLab.host.tld:80/-/kubernetes-agent/`.
#### ValidationError(Deployment.metadata)
diff --git a/doc/user/clusters/agent/install/index.md b/doc/user/clusters/agent/install/index.md
new file mode 100644
index 00000000000..fad9d4f08f1
--- /dev/null
+++ b/doc/user/clusters/agent/install/index.md
@@ -0,0 +1,369 @@
+---
+stage: Configure
+group: Configure
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Install the GitLab Kubernetes Agent **(FREE)**
+
+> [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) to GitLab Free in 14.5.
+
+To get started with the GitLab Kubernetes Agent, install it in your cluster.
+
+Pre-requisites:
+
+- An existing Kubernetes cluster.
+- An account on GitLab.
+
+## Installation steps
+
+To install the [GitLab Kubernetes Agent](../index.md) in your cluster:
+
+1. [Set up the Kubernetes Agent Server](#set-up-the-kubernetes-agent-server) for your GitLab instance.
+1. [Define a configuration repository](#define-a-configuration-repository).
+1. [Create an Agent record in GitLab](#create-an-agent-record-in-gitlab).
+1. [Install the Agent into the cluster](#install-the-agent-into-the-cluster).
+1. [Generate and copy a Secret token used to connect to the Agent](#create-the-kubernetes-secret).
+1. [Create manifest files](#create-manifest-files).
+
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> Watch a GitLab 14.2 [walking-through video](https://www.youtube.com/watch?v=XuBpKtsgGkE) with this process.
+
+### Set up the Kubernetes Agent Server
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.10, the GitLab Kubernetes Agent Server (KAS) became available on GitLab.com under `wss://kas.gitlab.com`.
+
+To use the KAS:
+
+- If you are a self-managed user, follow the instructions to [install the Kubernetes Agent Server](../../../../administration/clusters/kas.md).
+- If you are a GitLab.com user, when you [set up the configuration repository](#define-a-configuration-repository) for your agent, use `wss://kas.gitlab.com` as the `--kas-address`.
+
+### Define a configuration repository
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in GitLab 13.7, the Agent manifest configuration can be added to multiple directories (or subdirectories) of its repository.
+> - Group authorization was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
+
+To configure an Agent, you need:
+
+1. A GitLab repository to hold the configuration file.
+1. Install the Agent in a cluster.
+
+After installed, when you update the configuration file, GitLab transmits the
+information to the cluster automatically without downtime.
+
+In your repository, add the Agent configuration file under:
+
+```plaintext
+.gitlab/agents/<agent-name>/config.yaml
+```
+
+Make sure that `<agent-name>` conforms to the [Agent's naming format](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/identity_and_auth.md#agent-identity-and-name).
+
+Your `config.yaml` file specifies all configurations of the Agent, such as:
+
+- The manifest projects to synchronize.
+- The groups that can access this Agent via the [CI/CD Tunnel](../ci_cd_tunnel.md).
+- The address of the `hubble-relay` for the Network Security policy integrations.
+
+As an example, a minimal Agent configuration that sets up only the manifest
+synchronizations is:
+
+```yaml
+gitops:
+ manifest_projects:
+ # The `id` is the path to the Git repository holding your manifest files
+ - id: "path/to/your-manifest-project-1"
+ paths:
+ - glob: '/**/*.{yaml,yml,json}'
+```
+
+All the options for the [Kubernetes Agent configuration repository](../repository.md) are documented separately.
+
+### Create an Agent record in GitLab
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5786) in GitLab 14.1, you can create a new Agent record directly from the GitLab UI.
+
+Next, create a GitLab Rails Agent record to associate it with
+the configuration repository project. Creating this record also creates a Secret needed to configure
+the Agent in subsequent steps.
+
+In GitLab:
+
+1. Ensure that [GitLab CI/CD is enabled in your project](../../../../ci/enable_or_disable_ci.md#enable-cicd-in-a-project).
+1. From your project's sidebar, select **Infrastructure > Kubernetes clusters**.
+1. Select **Actions**.
+1. From the **Select an Agent** dropdown, select the Agent you want to connect and select **Register Agent** to access the installation form.
+1. The form reveals your registration token. Securely store this secret token as you cannot view it again.
+1. Copy the command under **Recommended installation method**.
+
+In your computer:
+
+1. Open your local terminal and connect to your cluster.
+1. Run the command you copied from the installation form.
+
+### Install the Agent into the cluster
+
+To install the in-cluster component of the Agent, first you need to define a namespace. To create a new namespace,
+for example, `gitlab-kubernetes-agent`, run:
+
+```shell
+kubectl create namespace gitlab-kubernetes-agent
+```
+
+To perform a one-liner installation, run the command below. Make sure to replace:
+
+- `your-agent-token` with the token received from the previous step (identified as `secret` in the JSON output).
+- `gitlab-kubernetes-agent` with the namespace you defined in the previous step.
+- `wss://kas.gitlab.example.com` with the configured access of the Kubernetes Agent Server (KAS). For GitLab.com users, the KAS is available under `wss://kas.gitlab.com`.
+- `--agent-version=vX.Y.Z` with the latest released patch version matching your GitLab installation's major and minor versions. For example, for GitLab v13.9.0, use `--agent-version=v13.9.1`. You can find your GitLab version under the "Help/Help" menu.
+
+```shell
+docker run --pull=always --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate --agent-token=your-agent-token --kas-address=wss://kas.gitlab.example.com --agent-version=vX.Y.Z --namespace gitlab-kubernetes-agent | kubectl apply -f -
+```
+
+WARNING:
+`--agent-version stable` can be used to refer to the latest stable release at the time when the command runs. It's fine for
+testing purposes but for production please make sure to specify a matching version explicitly.
+
+To find out the various options the above Docker container supports, run:
+
+```shell
+docker run --pull=always --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate --help
+```
+
+## Advanced installation
+
+For more advanced configurations, we recommend to use [the `kpt` based installation method](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/build/deployment/gitlab-agent).
+
+Otherwise, follow the manual installation steps described below.
+
+### Create the Kubernetes secret
+
+After generating the token, you must apply it to the Kubernetes cluster.
+
+To create your Secret, run:
+
+```shell
+kubectl create secret generic -n gitlab-kubernetes-agent gitlab-kubernetes-agent-token --from-literal=token='YOUR_AGENT_TOKEN'
+```
+
+The following example file contains the
+Kubernetes resources required for the Agent to be installed. You can modify this
+example [`resources.yml` file](#example-resourcesyml-file) in the following ways:
+
+- Replace `namespace: gitlab-kubernetes-agent` with `namespace: <YOUR-DESIRED-NAMESPACE>`.
+- You can configure `kas-address` (Kubernetes Agent Server) in several ways.
+ The agent can use the WebSockets or gRPC protocols to connect to the Agent Server.
+ Select the option appropriate for your cluster configuration and GitLab architecture:
+ - The `wss` scheme (an encrypted WebSockets connection) is specified by default
+ after you install the `gitlab-kas` sub-chart, or enable `gitlab-kas` for Omnibus GitLab.
+ When using the sub-chart, you must set `wss://kas.host.tld:443` as
+ `kas-address`, where `host.tld` is the domain you've setup for your GitLab installation.
+ When using Omnibus GitLab, you must set `wss://GitLab.host.tld:443/-/kubernetes-agent/` as
+ `kas-address`, where `GitLab.host.tld` is your GitLab hostname.
+ - When using the sub-chart, specify the `ws` scheme (such as `ws://kas.host.tld:80`)
+ to use an unencrypted WebSockets connection.
+ When using the Omnibus GitLab, specify the `ws` scheme (such as `ws://GitLab.host.tld:80/-/kubernetes-agent/`).
+ - Specify the `grpc` scheme if both Agent and Server are installed in one cluster.
+ In this case, you may specify `kas-address` value as
+ `grpc://gitlab-kas.<your-namespace>:8150`) to use gRPC directly, where `gitlab-kas`
+ is the name of the service created by `gitlab-kas` chart, and `<your-namespace>`
+ is the namespace where the chart was installed.
+ - Specify the `grpcs` scheme to use an encrypted gRPC connection.
+ - When deploying KAS through the [GitLab chart](https://docs.gitlab.com/charts/), it's possible to customize the
+ `kas-address` for `wss` and `ws` schemes to whatever you need.
+ Check the [chart's KAS Ingress documentation](https://docs.gitlab.com/charts/charts/gitlab/kas/#ingress)
+ to learn more about it.
+ - In the near future, Omnibus GitLab intends to provision `gitlab-kas` under a sub-domain by default, instead of the `/-/kubernetes-agent/` path. Please follow [this issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5784) for details.
+- If you defined your own secret name, replace `gitlab-kubernetes-agent-token` with your
+ secret name in the `secretName:` section.
+
+To apply this file, run the following command:
+
+```shell
+kubectl apply -n gitlab-kubernetes-agent -f ./resources.yml
+```
+
+To review your configuration, run the following command:
+
+```shell
+$ kubectl get pods -n gitlab-kubernetes-agent
+
+NAMESPACE NAME READY STATUS RESTARTS AGE
+gitlab-kubernetes-agent gitlab-kubernetes-agent-77689f7dcb-5skqk 1/1 Running 0 51s
+```
+
+#### Example `resources.yml` file
+
+```yaml
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: gitlab-kubernetes-agent
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: gitlab-kubernetes-agent
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: gitlab-kubernetes-agent
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: gitlab-kubernetes-agent
+ template:
+ metadata:
+ labels:
+ app: gitlab-kubernetes-agent
+ spec:
+ serviceAccountName: gitlab-kubernetes-agent
+ containers:
+ - name: agent
+ # Make sure to specify a matching version for production
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:vX.Y.Z"
+ args:
+ - --token-file=/config/token
+ - --kas-address
+ - wss://kas.host.tld:443 # replace this line with the line below if using Omnibus GitLab or GitLab.com.
+ # - wss://gitlab.host.tld:443/-/kubernetes-agent/
+ # - wss://kas.gitlab.com # for GitLab.com users, use this KAS.
+ # - grpc://host.docker.internal:8150 # use this attribute when connecting from Docker.
+ volumeMounts:
+ - name: token-volume
+ mountPath: /config
+ volumes:
+ - name: token-volume
+ secret:
+ secretName: gitlab-kubernetes-agent-token
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 0
+ maxUnavailable: 1
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: gitlab-kubernetes-agent-write
+rules:
+- resources:
+ - '*'
+ apiGroups:
+ - '*'
+ verbs:
+ - create
+ - update
+ - delete
+ - patch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: gitlab-kubernetes-agent-write-binding
+roleRef:
+ name: gitlab-kubernetes-agent-write
+ kind: ClusterRole
+ apiGroup: rbac.authorization.k8s.io
+subjects:
+- name: gitlab-kubernetes-agent
+ kind: ServiceAccount
+ namespace: gitlab-kubernetes-agent
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: gitlab-kubernetes-agent-read
+rules:
+- resources:
+ - '*'
+ apiGroups:
+ - '*'
+ verbs:
+ - get
+ - list
+ - watch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: gitlab-kubernetes-agent-read-binding
+roleRef:
+ name: gitlab-kubernetes-agent-read
+ kind: ClusterRole
+ apiGroup: rbac.authorization.k8s.io
+subjects:
+- name: gitlab-kubernetes-agent
+ kind: ServiceAccount
+ namespace: gitlab-kubernetes-agent
+```
+
+### Create manifest files
+
+In a previous step, you configured a `config.yaml` to point to the GitLab projects
+the Agent should synchronize. Agent monitors each of those projects for changes to the manifest files it contains. You can auto-generate manifest files with a
+templating engine or other means.
+
+The agent is authorized to download manifests for the configuration
+project, and public projects. Support for other private projects is
+planned in the issue [Agent authorization for private manifest
+projects](https://gitlab.com/gitlab-org/gitlab/-/issues/220912).
+
+Each time you push a change to a monitored manifest repository, the Agent logs the change:
+
+```plaintext
+2020-09-15_14:09:04.87946 gitlab-k8s-agent : time="2020-09-15T10:09:04-04:00" level=info msg="Config: new commit" agent_id=1 commit_id=e6a3651f1faa2e928fe6120e254c122451be4eea
+```
+
+#### Example manifest file
+
+This file creates a minimal `ConfigMap`:
+
+```yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: demo-map
+ namespace: gitlab-kubernetes-agent # Can be any namespace managed by you that the agent has access to.
+data:
+ key: value
+```
+
+## Example projects
+
+The following example projects can help you get started with the Kubernetes Agent.
+
+- [Configuration repository](https://gitlab.com/gitlab-org/configure/examples/kubernetes-agent)
+- This basic GitOps example deploys NGINX: [Manifest repository](https://gitlab.com/gitlab-org/configure/examples/gitops-project)
+
+## View installed Agents
+
+Users with at least the [Developer](../../../permissions.md) can access the user interface
+for the GitLab Kubernetes Agent at **Infrastructure > Kubernetes clusters**, under the
+**Agent** tab. This page lists all registered agents for the current project,
+and the configuration directory for each agent:
+
+![GitLab Kubernetes Agent list UI](../../img/kubernetes-agent-ui-list_v14_5.png)
+
+Additional management interfaces are planned for the GitLab Kubernetes Agent.
+[Provide more feedback in the related epic](https://gitlab.com/groups/gitlab-org/-/epics/4739).
+
+## Upgrades and version compatibility
+
+The GitLab Kubernetes Agent is comprised of two major components: `agentk` and `kas`.
+As we provide `kas` installers built into the various GitLab installation methods, the required `kas` version corresponds to the GitLab `major.minor` (X.Y) versions.
+
+At the same time, `agentk` and `kas` can differ by 1 minor version in either direction. For example,
+`agentk` 14.4 supports `kas` 14.3, 14.4, and 14.5 (regardless of the patch).
+
+A feature introduced in a given GitLab minor version might work with other `agentk` or `kas` versions.
+To make sure that it works, use at least the same `agentk` and `kas` minor version. For example,
+if your GitLab version is 14.2, use at least `agentk` 14.2 and `kas` 14.2.
+
+We recommend upgrading your `kas` installations together with GitLab instances' upgrades, and to upgrade the `agentk` installations after upgrading GitLab.
+
+The available `agentk` and `kas` versions can be found in
+[the container registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/).
diff --git a/doc/user/clusters/agent/repository.md b/doc/user/clusters/agent/repository.md
index cbb27a3f343..6ceb2766cc9 100644
--- a/doc/user/clusters/agent/repository.md
+++ b/doc/user/clusters/agent/repository.md
@@ -4,12 +4,13 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Kubernetes Agent configuration repository **(PREMIUM)**
+# Kubernetes Agent configuration repository **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.7.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in GitLab 13.11, the Kubernetes Agent became available on GitLab.com.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332227) in GitLab 14.0, the `resource_inclusions` and `resource_exclusions` attributes were removed and `reconcile_timeout`, `dry_run_strategy`, `prune`, `prune_timeout`, `prune_propagation_policy`, and `inventory_policy` attributes were added.
> - The `ci_access` attribute was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
+> - The GitLab Kubernetes Agent was [moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) to GitLab Free in 14.5.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -22,17 +23,19 @@ The Agent bootstraps with the GitLab installation URL and an authentication toke
and you provide the rest of the configuration in your repository, following
Infrastructure as Code (IaaC) best practices.
-A minimal repository layout looks like this, with `my_agent_1` as the name
+A minimal repository layout looks like this, with `my-agent-1` as the name
of your Agent:
```plaintext
|- .gitlab
|- agents
- |- my_agent_1
+ |- my-agent-1
|- config.yaml
```
-## Synchronize manifest projects
+Make sure that `<agent-name>` conforms to the [Agent's naming format](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/identity_and_auth.md#agent-identity-and-name).
+
+## Synchronize manifest projects **(PREMIUM)**
Your `config.yaml` file contains a `gitops` section, which contains a `manifest_projects`
section. Each `id` in the `manifest_projects` section is the path to a Git repository
@@ -132,7 +135,7 @@ INCORRECT - both globs match `*.yaml` files in the root directory:
```yaml
gitops:
manifest_projects:
- - id: project1
+ - id: project1
paths:
- glob: '/**/*.yaml'
- glob: '/*.yaml'
@@ -143,51 +146,140 @@ CORRECT - single globs matches all `*.yaml` files recursively:
```yaml
gitops:
manifest_projects:
- - id: project1
+ - id: project1
paths:
- glob: '/**/*.yaml'
```
-## Authorize groups to use an Agent
+## Authorize projects and groups to use an Agent
+
+> - Group authorization [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
+> - Project authorization [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327850) in GitLab 14.4.
+
+If you use the same cluster across multiple projects, you can set up the [CI/CD Tunnel](ci_cd_tunnel.md)
+to grant access to an Agent from one or more projects or groups. This way, all the authorized
+projects can access the same Agent, which facilitates you to save resources and have a scalable setup.
+
+When you authorize a project to use an agent through the [CI/CD Tunnel](ci_cd_tunnel.md),
+the selected Kubernetes context is automatically injected into CI/CD jobs, allowing you to
+run Kubernetes commands from your authorized projects' scripts. When you authorize a group,
+all the projects that belong to that group can access the selected agent.
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
+An Agent can only authorize projects or groups in the same group hierarchy as the Agent's configuration
+project. You can authorize up to 100 projects and 100 groups per Agent.
-FLAG:
-On self-managed GitLab, by default this feature is not available. To make it available,
-ask an administrator to [enable the `group_authorized_agents` flag](../../../administration/feature_flags.md).
-On GitLab.com, this feature is available.
+### Authorize projects to use an Agent
-If you use the same cluster across multiple projects, you can set up the CI/CD Tunnel
-to grant the Agent access to one or more groups. This way, all the projects that belong
-to the authorized groups can access the same Agent. This enables you to save resources and
-have a scalable setup.
+To grant projects access to the Agent through the [CI/CD Tunnel](ci_cd_tunnel.md):
-When you authorize a group, the agent's Kubernetes context is automatically injected
-into every project of the authorized group, and users can select the connection as
-described in the [CI/CD Tunnel documentation](ci_cd_tunnel.md).
-To authorize a group to access the Agent through the [CI/CD Tunnel](ci_cd_tunnel.md),
-use the `ci_access` attribute in your `config.yaml` configuration file.
+1. Go to your Agent's configuration project.
+1. Edit the Agent's configuration file (`config.yaml`).
+1. Add the `projects` attribute into `ci_access`.
+1. Identify the project through its path:
-An Agent can only authorize groups in the same group hierarchy as the Agent's configuration project. At most
-100 groups can be authorized per Agent.
+ ```yaml
+ ci_access:
+ projects:
+ - id: path/to/project
+ ```
-To authorize a group:
+### Authorize groups to use an Agent
-1. Edit your `config.yaml` file under the `.gitlab/agents/<agent name>` directory.
-1. Add the `ci_access` root attribute.
+To grant access to all projects within a group:
+
+1. Go to your Agent's configuration project.
+1. Edit the Agent's configuration file (`config.yaml`).
1. Add the `groups` attribute into `ci_access`.
-1. Add the group `id` into `groups`, identifying the authorized group through its path.
+1. Identify the group or subgroup through its path:
+
+ ```yaml
+ ci_access:
+ groups:
+ - id: path/to/group/subgroup
+ ```
+
+### Use impersonation to restrict project and group access **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345014) in GitLab 14.5.
+
+By default, the [CI/CD Tunnel](ci_cd_tunnel.md) inherits all the permissions from the service account used to install the
+Agent in the cluster.
+To restrict access to your cluster, you can use [impersonation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation).
+
+To specify impersonations, use the `access_as` attribute in your Agent's configuration file and use Kubernetes RBAC rules to manage impersonated account permissions.
+
+You can impersonate:
+
+- The Agent itself (default).
+- The CI job that accesses the cluster.
+- A specific user or system account defined within the cluster.
+
+#### Impersonate the Agent
-For example:
+The Agent is impersonated by default. You don't need to do anything to impersonate it.
+
+#### Impersonate the CI job that accesses the cluster
+
+To impersonate the CI job that accesses the cluster, add the `ci_job: {}` key-value
+under the `access_as` key.
+
+When the agent makes the request to the actual Kubernetes API, it sets the
+impersonation credentials in the following way:
+
+- `UserName` is set to `gitlab:ci_job:<job id>`. Example: `gitlab:ci_job:1074499489`.
+- `Groups` is set to:
+ - `gitlab:ci_job` to identify all requests coming from CI jobs.
+ - The list of IDs of groups the project is in.
+ - The project ID.
+ - The slug of the environment this job belongs to.
+
+ Example: for a CI job in `group1/group1-1/project1` where:
+
+ - Group `group1` has ID 23.
+ - Group `group1/group1-1` has ID 25.
+ - Project `group1/group1-1/project1` has ID 150.
+ - Job running in a prod environment.
+
+ Group list would be `[gitlab:ci_job, gitlab:group:23, gitlab:group:25, gitlab:project:150, gitlab:project_env:150:prod]`.
+
+- `Extra` carries extra information about the request. The following properties are set on the impersonated identity:
+
+| Property | Description |
+| -------- | ----------- |
+| `agent.gitlab.com/id` | Contains the agent ID. |
+| `agent.gitlab.com/config_project_id` | Contains the agent's configuration project ID. |
+| `agent.gitlab.com/project_id` | Contains the CI project ID. |
+| `agent.gitlab.com/ci_pipeline_id` | Contains the CI pipeline ID. |
+| `agent.gitlab.com/ci_job_id` | Contains the CI job ID. |
+| `agent.gitlab.com/username` | Contains the username of the user the CI job is running as. |
+| `agent.gitlab.com/environment_slug` | Contains the slug of the environment. Only set if running in an environment. |
+
+Example to restrict access by the CI job's identity:
```yaml
ci_access:
- # This agent is accessible from CI jobs in projects in these groups
- groups:
- - id: group/subgroup
+ projects:
+ - id: path/to/project
+ access_as:
+ ci_job: {}
```
-## Surface network security alerts from cluster to GitLab
+#### Impersonate a static identity
+
+For the given CI/CD Tunnel connection, you can use a static identity for the impersonation.
+
+Add the `impersonate` key under the `access_as` key to make the request using the provided identity.
+
+The identity can be specified with the following keys:
+
+- `username` (required)
+- `uid`
+- `groups`
+- `extra`
+
+See the [official Kubernetes documentation for more details](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation) on the usage of these keys.
+
+## Surface network security alerts from cluster to GitLab **(ULTIMATE)**
The GitLab Agent provides an [integration with Cilium](index.md#kubernetes-network-security-alerts).
To integrate, add a top-level `cilium` section to your `config.yml` file. Currently, the
@@ -207,6 +299,90 @@ cilium:
hubble_relay_address: "hubble-relay.gitlab-managed-apps.svc.cluster.local:80"
```
+## Scan your container images for vulnerabilities
+
+You can use [cluster image scanning](../../application_security/cluster_image_scanning/index.md)
+to scan container images in your cluster for security vulnerabilities.
+
+To begin scanning all resources in your cluster, add a `starboard`
+configuration block to your agent's `config.yaml` with no `filters`:
+
+```yaml
+starboard:
+ vulnerability_report:
+ filters: []
+```
+
+The namespaces that are able to be scanned depend on the [Starboard Operator install mode](https://aquasecurity.github.io/starboard/latest/operator/configuration/#install-modes).
+By default, the Starboard Operator only scans resources in the `default` namespace. To change this
+behavior, edit the `STARBOARD_OPERATOR` environment variable in the `starboard-operator` deployment
+definition.
+
+By adding filters, you can limit scans by:
+
+- Resource name
+- Kind
+- Container name
+- Namespace
+
+```yaml
+starboard:
+ vulnerability_report:
+ filters:
+ - namespaces:
+ - staging
+ - production
+ kinds:
+ - Deployment
+ - DaemonSet
+ containers:
+ - ruby
+ - postgres
+ - nginx
+ resources:
+ - my-app-name
+ - postgres
+ - ingress-nginx
+```
+
+A resource is scanned if the resource matches any of the given names and all of the given filter
+types (`namespaces`, `kinds`, `containers`, `resources`). If a filter type is omitted, then all
+names are scanned. In this example, a resource isn't scanned unless it has a container named `ruby`,
+`postgres`, or `nginx`, and it's a `Deployment`:
+
+```yaml
+starboard:
+ vulnerability_report:
+ filters:
+ - kinds:
+ - Deployment
+ containers:
+ - ruby
+ - postgres
+ - nginx
+```
+
+There is also a global `namespaces` field that applies to all filters:
+
+```yaml
+starboard:
+ vulnerability_report:
+ namespaces:
+ - production
+ filters:
+ - kinds:
+ - Deployment
+ - kinds:
+ - DaemonSet
+ resources:
+ - log-collector
+```
+
+In this example, the following resources are scanned:
+
+- All deployments (`Deployment`) in the `production` namespace
+- All daemon sets (`DaemonSet`) named `log-collector` in the `production` namespace
+
## Debugging
To debug the cluster-side component (`agentk`) of the GitLab Kubernetes Agent, set the log
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index 31dd503a0cf..88382648b04 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -20,7 +20,7 @@ methods: "one-click install" and "CI/CD template". Both methods are **deprecated
Both methods were limiting as you couldn't fully customize your third-party apps installed
through GitLab Managed Apps. Therefore, we decided to deprecate this feature and provide
-better [GitOps-driven alternatives](https://about.gitlab.com/direction/configure/kubernetes_management/#gitlab-managed-applications) to our users, such as [cluster integrations](integrations.md#cluster-integrations) and [cluster management project](management_project.md).
+better [GitOps-driven alternatives](https://about.gitlab.com/direction/configure/kubernetes_management/#gitlab-managed-applications) to our users, such as [cluster integrations](integrations.md) and [cluster management project](management_project.md).
## Install using GitLab CI/CD (DEPRECATED)
diff --git a/doc/user/clusters/cost_management.md b/doc/user/clusters/cost_management.md
index 26611c26e5e..3ad994ecd7e 100644
--- a/doc/user/clusters/cost_management.md
+++ b/doc/user/clusters/cost_management.md
@@ -4,9 +4,13 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Cluster cost management **(ULTIMATE)**
+# Cluster cost management (DEPRECATED) **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216737) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216737) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.5.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
Cluster cost management provides insights into cluster resource usage. GitLab provides an example
[`kubecost-cost-model`](https://gitlab.com/gitlab-examples/kubecost-cost-model/)
diff --git a/doc/user/clusters/crossplane.md b/doc/user/clusters/crossplane.md
index 8906d1224b1..e6540e68f71 100644
--- a/doc/user/clusters/crossplane.md
+++ b/doc/user/clusters/crossplane.md
@@ -4,7 +4,12 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Crossplane configuration **(FREE)**
+# Crossplane configuration (DEPRECATED) **(FREE)**
+
+> [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
After [installing](applications.md#install-crossplane-using-gitlab-cicd) Crossplane, you must configure it for use.
The process of configuring Crossplane includes:
diff --git a/doc/user/clusters/environments.md b/doc/user/clusters/environments.md
index 470f65db61b..72bc7b398dc 100644
--- a/doc/user/clusters/environments.md
+++ b/doc/user/clusters/environments.md
@@ -4,10 +4,14 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Cluster Environments **(PREMIUM)**
+# Cluster Environments (DEPRECATED) **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13392) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3 for group-level clusters.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14809) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4 for instance-level clusters.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
Cluster environments provide a consolidated view of which CI [environments](../../ci/environments/index.md) are
deployed to the Kubernetes cluster and it:
diff --git a/doc/user/clusters/img/kubernetes-agent-ui-list_v13_8.png b/doc/user/clusters/img/kubernetes-agent-ui-list_v13_8.png
deleted file mode 100644
index 3f9cc41838a..00000000000
--- a/doc/user/clusters/img/kubernetes-agent-ui-list_v13_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/clusters/img/kubernetes-agent-ui-list_v14_5.png b/doc/user/clusters/img/kubernetes-agent-ui-list_v14_5.png
new file mode 100644
index 00000000000..3463eeb5d93
--- /dev/null
+++ b/doc/user/clusters/img/kubernetes-agent-ui-list_v14_5.png
Binary files differ
diff --git a/doc/user/clusters/integrations.md b/doc/user/clusters/integrations.md
index 70f940c775b..d04cf64d93a 100644
--- a/doc/user/clusters/integrations.md
+++ b/doc/user/clusters/integrations.md
@@ -4,14 +4,19 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Cluster integrations **(FREE)**
+# Cluster integrations (DEPRECATED) **(FREE)**
+
+> [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
GitLab provides several ways to integrate applications to your
Kubernetes cluster.
To enable cluster integrations, first add a Kubernetes cluster to a GitLab
[project](../project/clusters/add_remove_clusters.md) or
-[group](../group/clusters/index.md#group-level-kubernetes-clusters) or
+[group](../group/clusters/index.md) or
[instance](../instance/clusters/index.md).
You can install your applications manually as shown in the following sections, or use the
@@ -25,10 +30,22 @@ or [Enable Elastic Stack integration for your cluster](#enable-elastic-stack-int
depending on which application you are installing. [An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/326565)
to automate this step.
+Prometheus and Elastic Stack cluster integrations can only be enabled for clusters [connected through cluster certificates](../project/clusters/add_existing_cluster.md).
+
+To enable Prometheus for your cluster connected through the [GitLab Kubernetes Agent](agent/index.md), you can [integrate it manually](../project/integrations/prometheus.md#manual-configuration-of-prometheus).
+
+There is no option to enable Elastic Stack for your cluster if it is connected with the GitLab Kubernetes Agent.
+Follow this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/300230) for updates.
+
## Prometheus cluster integration
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55244) in GitLab 13.11.
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. However, you can **still use** Prometheus
+for Kubernetes clusters connected to GitLab through the
+[GitLab Kubernetes Agent](agent/index.md) by [enabling Prometheus manually](../project/integrations/prometheus.md#manual-configuration-of-prometheus).
+
You can integrate your Kubernetes cluster with
[Prometheus](https://prometheus.io/) for monitoring key metrics of your
apps directly from the GitLab UI.
diff --git a/doc/user/clusters/management_project.md b/doc/user/clusters/management_project.md
index ca6843f6fde..1332310b850 100644
--- a/doc/user/clusters/management_project.md
+++ b/doc/user/clusters/management_project.md
@@ -4,9 +4,15 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Cluster management project **(FREE)**
+# Cluster management project (DEPRECATED) **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32810) in GitLab 12.5
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32810) in GitLab 12.5.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+The cluster management project was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+To manage cluster applications, use the [GitLab Kubernetes Agent](agent/index.md)
+with the [Cluster Management Project Template](management_project_template.md).
A project can be designated as the management project for a cluster.
A management project can be used to run deployment jobs with
@@ -37,8 +43,7 @@ Management projects are restricted to the following:
To use a cluster management project to manage your cluster:
1. Create a new project to serve as the cluster management project
-for your cluster. We recommend that you
-[create this project based on the Cluster Management project template](management_project_template.md#create-a-new-project-based-on-the-cluster-management-template).
+for your cluster.
1. [Associate the cluster with the management project](#associate-the-cluster-management-project-with-the-cluster).
1. [Configure your cluster's pipelines](#configuring-your-pipeline).
1. [Set the environment scope](#setting-the-environment-scope).
diff --git a/doc/user/clusters/management_project_template.md b/doc/user/clusters/management_project_template.md
index 305f66c5ec5..c663246cdd8 100644
--- a/doc/user/clusters/management_project_template.md
+++ b/doc/user/clusters/management_project_template.md
@@ -4,15 +4,17 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Cluster Management project template **(FREE)**
+# Manage cluster applications **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25318) in GitLab 12.10 with Helmfile support via Helm v2.
> - Helm v2 support was [dropped](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63577) in GitLab 14.0. Use Helm v3 instead.
+> - [Migrated](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/24) to the GitLab Kubernetes Agent in GitLab 14.5.
-With a [cluster management project](management_project.md) you can manage
-your cluster's deployment and applications through a repository in GitLab.
+Use a repository to install, manage, and deploy clusters applications through code.
-The Cluster Management project template provides you a baseline to get
+## Cluster Management Project Template
+
+The Cluster Management Project Template provides you a baseline to get
started and flexibility to customize your project to your cluster's needs.
For instance, you can:
@@ -21,49 +23,78 @@ For instance, you can:
- Remove the built-in cluster applications you don't need.
- Add other cluster applications using the same structure as the ones already available.
-The template contains the following [components](#available-components):
+The template contains the following [components](#configure-the-available-components):
-- A pre-configured GitLab CI/CD file so that you can configure deployment pipelines.
+- A pre-configured GitLab CI/CD file so that you can configure CI/CD pipelines using the [CI/CD Tunnel](agent/ci_cd_tunnel.md).
- A pre-configured [Helmfile](https://github.com/roboll/helmfile) so that
you can manage cluster applications with [Helm v3](https://helm.sh/).
- An `applications` directory with a `helmfile.yaml` configured for each
application available in the template.
-WARNING:
-If you used [GitLab Managed Apps](applications.md) to manage your
-cluster from GitLab, see how to [migrate from GitLab Managed Apps](migrating_from_gma_to_project_template.md) to the Cluster Management
-project.
+## Use the Kubernetes Agent with the Cluster Management Project Template
+
+To use a new project created from the Cluster Management Project Template
+with a cluster connected to GitLab through the [GitLab Kubernetes Agent](agent/index.md),
+you have two options:
+
+- [Use one single project](#single-project) to configure the Agent and manage cluster applications.
+- [Use separate projects](#separate-projects) - one to configure the Agent and another to manage cluster applications.
+
+### Single project
+
+This setup is particularly useful when you haven't connected your cluster
+to GitLab through the Agent yet and you want to use the Cluster Management
+Project Template to manage cluster applications.
+
+To use one single project to configure the Agent and to manage cluster applications:
+
+1. [Create a new project from the Cluster Management Project Template](#create-a-new-project-based-on-the-cluster-management-template).
+1. Configure the new project as the [Agent's configuration repository](agent/repository.md)
+(where the Agent is registered and its `config.yaml` is stored).
+1. From your project's settings, add a [new environment variable](../../ci/variables/index.md#add-a-cicd-variable-to-a-project) `$KUBE_CONTEXT` and set it to `path/to/agent-configuration-project:your-agent-name`.
+1. [Configure the components](#configure-the-available-components) inherited from the template.
+
+### Separate projects
+
+This setup is particularly useful **when you already have a cluster** connected
+to GitLab through the Agent and want to use the Cluster Management
+Project Template to manage cluster applications.
-## Set up the management project from the Cluster Management project template
+To use one project to configure the Agent ("project A") and another project to
+manage cluster applications ("project B"), follow the steps below.
-To set up your cluster's management project off of the Cluster Management project template:
+We assume that you already have a cluster connected through the Agent and
+[configured through the Agent's configuration repository](agent/repository.md)
+("project A").
-1. [Create a new project based on the Cluster Management template](#create-a-new-project-based-on-the-cluster-management-template).
-1. [Associate the cluster management project with your cluster](management_project.md#associate-the-cluster-management-project-with-the-cluster).
-1. Use the [available components](#available-components) to manage your cluster.
+1. [Create a new project from the Cluster Management Project Template](#create-a-new-project-based-on-the-cluster-management-template).
+This new project is "project B".
+1. In your "project A", [grant the Agent access to the new project (B) through the CI/CD Tunnel](agent/repository.md#authorize-projects-to-use-an-agent).
+1. From the "project's B" settings, add a [new environment variable](../../ci/variables/index.md#add-a-cicd-variable-to-a-project) `$KUBE_CONTEXT` and set it to `path/to/agent-configuration-project:your-agent-name`.
+1. In "project B", [configure the components](#configure-the-available-components) inherited from the template.
-### Create a new project based on the Cluster Management template
+## Create a new project based on the Cluster Management Template
To get started, create a new project based on the Cluster Management
project template to use as a cluster management project.
-You can either create the [new project](../project/working_with_projects.md#create-a-project)
-from the template or import the project from the URL. Importing
-the project is useful if you are using a GitLab self-managed
-instance that may not have the latest version of the template.
+You can either create the new project from the template or import the
+project from the URL. Importing the project is useful if you are using
+a GitLab self-managed instance that may not have the latest version of
+the template.
-To create the new project:
+To [create the new project](../project/working_with_projects.md#create-a-project):
- From the template: select the **GitLab Cluster Management** project template.
- Importing from the URL: use `https://gitlab.com/gitlab-org/project-templates/cluster-management.git`.
-## Available components
+## Configure the available components
-Use the available components to configure your cluster:
+Use the available components to configure your cluster applications:
-- [A `.gitlab-ci.yml` file](#the-gitlab-ciyml-file).
-- [A main `helmfile.yml` file](#the-main-helmfileyml-file).
-- [A directory with built-in applications](#built-in-applications).
+- [The `.gitlab-ci.yml` file](#the-gitlab-ciyml-file).
+- [The main `helmfile.yml` file](#the-main-helmfileyml-file).
+- [The directory with built-in applications](#built-in-applications).
### The `.gitlab-ci.yml` file
@@ -107,8 +138,8 @@ The [built-in supported applications](https://gitlab.com/gitlab-org/project-temp
- [Sentry](../infrastructure/clusters/manage/management_project_applications/sentry.md)
- [Vault](../infrastructure/clusters/manage/management_project_applications/vault.md)
-#### How to customize your applications
+#### Customize your applications
-Each app has an `applications/{app}/values.yaml` file (`applicaton/{app}/values.yaml.gotmpl` in case of GitLab Runner). This is the
+Each app has an `applications/{app}/values.yaml` file (`applications/{app}/values.yaml.gotmpl` in case of GitLab Runner). This is the
place where you can define default values for your app's Helm chart. Some apps already have defaults
pre-defined by GitLab.
diff --git a/doc/user/compliance/compliance_report/index.md b/doc/user/compliance/compliance_report/index.md
index 63dd06bcfdb..d98a0a145f2 100644
--- a/doc/user/compliance/compliance_report/index.md
+++ b/doc/user/compliance/compliance_report/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Compliance report **(ULTIMATE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36524) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.8 as Compliance Dashboard.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36524) in GitLab 12.8 as Compliance Dashboard.
> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/299360) to compliance report in GitLab 14.2.
Compliance report gives you the ability to see a group's merge request activity. It provides a
@@ -53,7 +53,7 @@ request:
## Approval status and separation of duties
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217939) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217939) in GitLab 13.3.
We support a separation of duties policy between users who create and approve merge requests.
The approval status column can help you identify violations of this policy.
@@ -75,9 +75,9 @@ This column has four states:
If you see a non-success state, review the criteria for the merge request's project to ensure it complies with the separation of duties.
-## Chain of Custody report **(ULTIMATE)**
+## Chain of Custody report
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213364) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213364) in GitLab 13.3.
The Chain of Custody report allows customers to export a list of merge commits within the group.
The data provides a comprehensive view with respect to merge commits. It includes the merge commit SHA,
@@ -90,9 +90,9 @@ To download the Chain of Custody report:
1. On the left sidebar, select **Security & Compliance > Compliance report**.
1. Select **List of all merge commits**.
-### Commit-specific Chain of Custody Report **(ULTIMATE)**
+### Commit-specific Chain of Custody Report
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267629) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.6.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267629) in GitLab 13.6.
You can generate a commit-specific Chain of Custody report for a given commit SHA.
diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md
index 5318f4deed1..319c1ca6278 100644
--- a/doc/user/compliance/license_compliance/index.md
+++ b/doc/user/compliance/license_compliance/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# License Compliance **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5483) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5483) in GitLab 11.0.
If you're using [GitLab CI/CD](../../../ci/index.md), you can use License Compliance to search your
project's dependencies for their licenses. You can then decide whether to allow or deny the use of
@@ -162,7 +162,7 @@ License Compliance can be configured using CI/CD variables.
### Installing custom dependencies
-> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.4.
+> Introduced in GitLab 11.4.
The `license_finder` image already embeds many auto-detection scripts, languages,
and packages. Nevertheless, it's almost impossible to cover all cases for all projects.
@@ -188,6 +188,21 @@ variables:
In this example, `my-custom-install-script.sh` is a shell script at the root
directory of your project.
+### Working with Monorepos
+
+Depending on your language, you may need to specify the path to the individual
+projects of a monorepo using the `LICENSE_FINDER_CLI_OPTS` variable. Passing in
+the project paths can significantly speed up builds over using the `--recursive`
+license_finder option.
+
+```yaml
+include:
+ - template: Security/License-Scanning.gitlab-ci.yml
+
+variables:
+ LICENSE_FINDER_CLI_OPTS: "--aggregate_paths=relative-path/to/sub-project/one relative-path/to/sub-project/two"
+```
+
### Overriding the template
WARNING:
@@ -262,7 +277,7 @@ License Compliance uses Java 8 by default. You can specify a different Java vers
### Selecting the version of Python
-> - [Introduced](https://gitlab.com/gitlab-org/security-products/license-management/-/merge_requests/36) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
+> - [Introduced](https://gitlab.com/gitlab-org/security-products/license-management/-/merge_requests/36) in GitLab 12.0.
> - In [GitLab 12.2](https://gitlab.com/gitlab-org/gitlab/-/issues/12032), Python 3.5 became the default.
> - In [GitLab 12.7](https://gitlab.com/gitlab-org/security-products/license-management/-/merge_requests/101), Python 3.8 became the default.
@@ -695,7 +710,7 @@ Additional configuration may be needed for connecting to private registries for:
### SPDX license list name matching
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212388) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212388) in GitLab 13.3.
Prior to GitLab 13.3, offline environments required an exact name match for [project policies](#policies).
In GitLab 13.3 and later, GitLab matches the name of [project policies](#policies)
@@ -705,7 +720,7 @@ instance's administrator can manually update it with a [Rake task](../../../rake
## License list
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13582) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.7.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13582) in GitLab 12.7.
The License list allows you to see your project's licenses and key
details about them.
@@ -729,7 +744,7 @@ The licenses are displayed, where:
## Policies
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22465) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22465) in GitLab 12.9.
Policies allow you to specify licenses that are `allowed` or `denied` in a project. If a `denied`
license is newly committed it blocks the merge request and instructs the developer to remove it.
@@ -752,7 +767,7 @@ Developers of the project can view the policies configured in a project.
## Enabling License Approvals within a project
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13067) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.3.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13067) in GitLab 12.3.
Prerequisites:
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index aa4e3ce6f49..4d6cff96169 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -10,7 +10,7 @@ type: reference, howto
GitLab encourages communication through comments, threads, and
[code suggestions](../project/merge_requests/reviews/suggestions.md).
-There are two types of comments:
+Two types of comments are available:
- A standard comment.
- A comment in a thread, which can be [resolved](#resolve-a-thread).
@@ -119,16 +119,15 @@ Notes are added to the page details.
If an issue or merge request is locked and closed, you cannot reopen it.
-## Mark a comment as confidential
+## Mark a comment as confidential **(FREE SELF)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207473) in GitLab 13.9.
-> - [Deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - Disabled on GitLab.com.
-> - Not recommended for production use.
-> - To use in GitLab self-managed instances, ask a GitLab administrator to enable it. **(FREE SELF)**
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207473) in GitLab 13.9 [with a flag](../../administration/feature_flags.md) named `confidential_notes`. Disabled by default.
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available,
+ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `confidential_notes`.
+On GitLab.com, this feature is not available.
+You should not use this feature for production environments.
You can make a comment confidential, so that it is visible only to project members
who have at least the Reporter role.
@@ -142,8 +141,6 @@ You can also make an [entire issue confidential](../project/issues/confidential_
## Show only comments
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26723) in GitLab 11.5.
-
For issues and merge requests with many comments, you can filter the page to show comments only.
1. Open a merge request's **Discussion** tab, or epic or issue's **Overview** tab.
@@ -171,14 +168,12 @@ You can assign an issue to a user who made a comment.
## Create a thread by replying to a standard comment
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30299) in GitLab 11.9.
-
When you reply to a standard comment, you create a thread.
Prerequisites:
- You must have at least the [Guest role](../permissions.md#project-members-permissions).
-- You must be in an issue, merge request, or epic. Commits and snippets threads are not supported.
+- You must be in an issue, merge request, or epic. Threads in commits and snippets are not supported.
To create a thread by replying to a comment:
@@ -186,7 +181,7 @@ To create a thread by replying to a comment:
![Reply to comment button](img/reply_to_comment_button.png)
- The reply area is displayed.
+ The reply section is displayed.
1. Enter your reply.
1. Select **Comment** or **Add comment now** (depending on where in the UI you are replying).
@@ -215,8 +210,7 @@ A threaded comment is created.
## Resolve a thread
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5022) in GitLab 8.11.
-> - Resolving comments individually was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/28750) in GitLab 13.6.
+> Resolving comments individually was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/28750) in GitLab 13.6.
In a merge request, you can resolve a thread when you want to finish a conversation.
@@ -286,22 +280,3 @@ with a new push.
Threads are now resolved if a push makes a diff section outdated.
Threads on lines that don't change and top-level resolvable threads are not resolved.
-
-## Enable or disable confidential comments **(FREE SELF)**
-
-Confidential comments are under development and not ready for production use. The feature is
-deployed behind a feature flag that is **disabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can enable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:confidential_notes)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:confidential_notes)
-```
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index e0cc79fe0fb..a3aecff6f73 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -135,11 +135,13 @@ the related documentation.
| Scheduled Pipeline Cron | `*/5 * * * *` | `3-59/10 * * * *` |
| [Max jobs in active pipelines](../../administration/instance_limits.md#number-of-jobs-in-active-pipelines) | `500` for Free tier, unlimited otherwise | Unlimited |
| [Max CI/CD subscriptions to a project](../../administration/instance_limits.md#number-of-cicd-subscriptions-to-a-project) | `2` | Unlimited |
+| [Max number of pipeline triggers in a project](../../administration/instance_limits.md#limit-the-number-of-pipeline-triggers) | `25000` for Free tier, Unlimited for all paid tiers | Unlimited |
| [Max pipeline schedules in projects](../../administration/instance_limits.md#number-of-pipeline-schedules) | `10` for Free tier, `50` for all paid tiers | Unlimited |
| [Max pipelines per schedule](../../administration/instance_limits.md#limit-the-number-of-pipelines-created-by-a-pipeline-schedule-per-day) | `24` for Free tier, `288` for all paid tiers | Unlimited |
| [Scheduled Job Archival](../../user/admin_area/settings/continuous_integration.md#archive-jobs) | 3 months | Never |
| Max test cases per [unit test report](../../ci/unit_test_reports.md) | `500_000` | Unlimited |
| [Max registered runners](../../administration/instance_limits.md#number-of-registered-runners-per-scope) | Free tier: `50` per-group / `50` per-project <br/> All paid tiers: `1_000` per-group / `1_000` per-project | `1_000` per-group / `1_000` per-project |
+| [Limit dotenv variables](../../administration/instance_limits.md#limit-dotenv-variables) | Free tier: `50` / Premium tier: `100` / Ultimate tier: `150` | Unlimited |
## Account and limit settings
@@ -158,7 +160,7 @@ If you are near or over the repository size limit, you can either
NOTE:
`git push` and GitLab project imports are limited to 5 GB per request through
Cloudflare. Git LFS and imports other than a file upload are not affected by
-this limit.
+this limit. Repository limits apply to both public and private projects.
## IP range
@@ -198,11 +200,11 @@ The following limits apply for [Webhooks](../project/integrations/webhooks.md):
| [Number of webhooks](../../administration/instance_limits.md#number-of-webhooks) | `100` per project, `50` per group | `100` per project, `50` per group |
| Maximum payload size | 25 MB | 25 MB |
-## Shared Build Cloud runners
+## Shared Runner Cloud runners
GitLab has shared runners on GitLab.com that you can use to run your CI jobs.
-For more information, see [GitLab Build Cloud runners](../../ci/runners/index.md).
+For more information, see [GitLab Runner Cloud runners](../../ci/runners/index.md).
## Sidekiq
@@ -296,6 +298,7 @@ after the limits change in January, 2021:
| **All** traffic (from a given **IP address**) | **600** requests per minute | **2,000** requests per minute | **2,000** requests per minute |
| **Issue creation** | | **300** requests per minute | **300** requests per minute |
| **Note creation** (on issues and merge requests) | | **300** requests per minute | **60** requests per minute |
+| **Advanced, project, and group search** API (for a given **IP address**) | | | **10** requests per minute |
More details are available on the rate limits for [protected
paths](#protected-paths-throttle) and [raw
diff --git a/doc/user/group/clusters/index.md b/doc/user/group/clusters/index.md
index 25eff076d8d..9c95b2b21a4 100644
--- a/doc/user/group/clusters/index.md
+++ b/doc/user/group/clusters/index.md
@@ -5,9 +5,14 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Group-level Kubernetes clusters **(FREE)**
+# Group-level Kubernetes clusters (certificate-based) (DEPRECATED) **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34758) in GitLab 11.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34758) in GitLab 11.6.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. To connect clusters to GitLab,
+use the [GitLab Kubernetes Agent](../../clusters/agent/index.md).
Similar to [project-level](../../project/clusters/index.md) and
[instance-level](../../instance/clusters/index.md) Kubernetes clusters,
@@ -28,7 +33,7 @@ installation, such as an Ingress controller.
## RBAC compatibility
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29398) in GitLab 11.4.
-> - [Project namespace restriction](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51716) was introduced in GitLab 11.5.
+> - Project namespace restriction was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51716) in GitLab 11.5.
For each project under a group with a Kubernetes cluster, GitLab creates a restricted
service account with [`edit` privileges](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)
@@ -44,7 +49,7 @@ to the project, provided the cluster is not disabled.
## Multiple Kubernetes clusters
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094) in GitLab Free 13.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094) in GitLab 13.2.
You can associate more than one Kubernetes cluster to your group, and maintain different clusters
for different environments, such as development, staging, and production.
diff --git a/doc/user/group/contribution_analytics/index.md b/doc/user/group/contribution_analytics/index.md
index b13dd3f63cb..76a8eb77e72 100644
--- a/doc/user/group/contribution_analytics/index.md
+++ b/doc/user/group/contribution_analytics/index.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3090) in GitLab 12.2 for subgroups.
-With Contribution Analytics you can get an overview of the [contribution actions](../../../api/events.md#action-types) in your
+With Contribution Analytics, you can get an overview of the [contribution events](../../index.md#user-contribution-events) in your
group.
- Analyze your team's contributions over a period of time, and offer a bonus for the top
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
index a9c56139b4d..9378b3922b5 100644
--- a/doc/user/group/custom_project_templates.md
+++ b/doc/user/group/custom_project_templates.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Custom group-level project templates **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6861) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.6.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6861) in GitLab 11.6.
[Group owners](../permissions.md#group-members-permissions) can set a subgroup to
be the source of project templates that are selectable when a new project is created
diff --git a/doc/user/group/devops_adoption/index.md b/doc/user/group/devops_adoption/index.md
index e3b858aff7d..36ccfc1031f 100644
--- a/doc/user/group/devops_adoption/index.md
+++ b/doc/user/group/devops_adoption/index.md
@@ -48,7 +48,7 @@ With DevOps Adoption you can:
- Identify specific subgroups that are lagging in their adoption of GitLab, so you can help them along in their DevOps journey.
- Find the subgroups that have adopted certain features, and can provide guidance to other subgroups on how to use those features.
-![DevOps Report](img/group_devops_adoption_v14_2.png)
+![DevOps Adoption](img/group_devops_adoption_v14_2.png)
Feature adoption is based on usage in the previous calendar month. Data is updated on the first day
of each month. If the monthly update fails, it tries again daily until successful.
diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md
index 68df71d1c5d..65e0f31324b 100644
--- a/doc/user/group/epics/index.md
+++ b/doc/user/group/epics/index.md
@@ -7,8 +7,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Epics **(PREMIUM)**
-> - Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.2.
-> - Single-level epics [were moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) to [GitLab Premium](https://about.gitlab.com/pricing/) in 12.8.
+> - Introduced in GitLab 10.2.
+> - Single-level epics were [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) from GitLab Ultimate to GitLab Premium in 12.8.
When [issues](../../project/issues/index.md) share a theme across projects and milestones,
you can manage them by using epics.
@@ -39,7 +39,7 @@ graph TD
## Roadmap in epics **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7327) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7327) in GitLab 11.10.
If your epic contains one or more [child epics](manage_epics.md#multi-level-child-epics) that
have a start or due date, a visual
diff --git a/doc/user/group/epics/manage_epics.md b/doc/user/group/epics/manage_epics.md
index 1b36d6f03df..72fa9e1e310 100644
--- a/doc/user/group/epics/manage_epics.md
+++ b/doc/user/group/epics/manage_epics.md
@@ -12,7 +12,7 @@ to them.
## Create an epic
-> - The New Epic form [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211533) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
+> - The New Epic form [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211533) in GitLab 13.2.
> - In [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/issues/229621) and later, the New Epic button on the Epics list opens the New Epic form.
> - In [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45948) and later, you can create a new epic from an empty roadmap.
@@ -25,10 +25,11 @@ To create an epic in the group you're in:
- In an empty [roadmap](../roadmap/index.md), select **New epic**.
1. Enter a title.
-1. Optional. Enter a description.
-1. Optional. To make the epic confidential, select the [Confidentiality checkbox](#make-an-epic-confidential).
-1. Optional. Choose labels.
-1. Optional. Select a start and due date, or [inherit](#start-and-due-date-inheritance) them.
+1. Complete the fields.
+ - Enter a description.
+ - To [make the epic confidential](#make-an-epic-confidential), select the checkbox under **Confidentiality**.
+ - Choose labels.
+ - Select a start and due date, or [inherit](#start-and-due-date-inheritance) them.
1. Select **Create epic**.
The newly created epic opens.
@@ -69,38 +70,41 @@ After you create an epic, you can edit the following details:
To edit an epic's title or description:
-1. Select the **Edit title and description** **{pencil}** button.
+1. Select **Edit title and description** **{pencil}**.
1. Make your changes.
1. Select **Save changes**.
To edit an epic's start date, due date, or labels:
-1. Select **Edit** next to each section in the epic sidebar.
+1. Next to each section in the right sidebar, select **Edit**.
1. Select the dates or labels for your epic.
## Bulk edit epics
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7250) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7250) in GitLab 12.2.
-Users with permission level of [Reporter or higher](../../permissions.md) can manage epics.
+Users with at least the [Reporter role](../../permissions.md) can manage epics.
When bulk editing epics in a group, you can edit their labels.
To update multiple epics at the same time:
1. In a group, go to **Epics > List**.
-1. Click **Edit epics**. A sidebar on the right-hand side of your screen appears with editable fields.
-1. Check the checkboxes next to each epic you want to edit.
+1. Select **Edit epics**. A sidebar on the right appears with editable fields.
+1. Select the checkboxes next to each epic you want to edit.
1. Select the appropriate fields and their values from the sidebar.
-1. Click **Update all**.
+1. Select **Update all**.
## Delete an epic
NOTE:
-To delete an epic, you need to be an [Owner](../../permissions.md#group-members-permissions) of a group/subgroup.
+To delete an epic, you must be an [Owner](../../permissions.md#group-members-permissions) of a group
+or subgroup.
-When editing the description of an epic, select the **Delete** button to delete the epic.
-A modal appears to confirm your action.
+To delete the epic:
+
+1. Select **Edit title and description** **{pencil}**.
+1. Select **Delete**. A modal appears to confirm your action.
Deleting an epic releases all existing issues from their associated epic in the system.
@@ -112,38 +116,56 @@ If you delete an epic, all its child epics and their descendants are deleted as
Whenever you decide that there is no longer need for that epic,
close the epic by:
-- Selecting the **Close epic** button.
+- Selecting **Close epic**.
![close epic - button](img/button_close_epic.png)
-- Using a [quick action](../../project/quick_actions.md).
+- Using the `/close` [quick action](../../project/quick_actions.md).
## Reopen a closed epic
You can reopen an epic that was closed by:
-- Clicking the **Reopen epic** button.
+- Selecting **Reopen epic**.
![reopen epic - button](img/button_reopen_epic.png)
-- Using a [quick action](../../project/quick_actions.md).
+- Using the `/reopen` [quick action](../../project/quick_actions.md).
## Go to an epic from an issue
-If an issue belongs to an epic, you can navigate to the containing epic with the
-link in the issue sidebar.
+If an issue belongs to an epic, you can go to the parent epic with the
+link in the right sidebar.
![containing epic](img/containing_epic.png)
+## View epics list
+
+In a group, the left sidebar displays the total count of open epics.
+This number indicates all epics associated with the group and its subgroups, including epics you
+might not have permission to view.
+
+To view epics in a group:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Epics**.
+
+### Cached epic count
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299540) in GitLab 13.11 [with a flag](../../../administration/feature_flags.md) named `cached_sidebar_open_epics_count`. Enabled by default.
+> - Enabled on self-managed and on GitLab.com in GitLab 14.0. [Feature flag `cached_sidebar_open_epics_count`](https://gitlab.com/gitlab-org/gitlab/-/issues/327320) removed.
+
+The total count of open epics displayed in the sidebar is cached if higher
+than 1000. The cached value is rounded to thousands or millions and updated every 24 hours.
+
## Search for an epic from epics list page
-> - Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.5.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) to the [Premium](https://about.gitlab.com/pricing/) tier in GitLab 12.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) from GitLab Ultimate to GitLab Premium in 12.8.
> - Searching by the user's reaction emoji [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/325630) in GitLab 13.11.
> - Sorting by epic titles [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/331625) in GitLab 14.1.
-You can search for an epic from the list of epics using filtered search bar (similar to
-that of issues and merge requests) based on following parameters:
+You can search for an epic from the list of epics using filtered search bar based on following
+parameters:
- Title or description
- Author name / username
@@ -152,10 +174,13 @@ that of issues and merge requests) based on following parameters:
![epics search](img/epics_search_v13_11.png)
-To search, go to the list of epics and select the field **Search or filter results**.
-It displays a dropdown menu, from which you can add an author. You can also enter plain
-text to search by epic title or description. When done, press <kbd>Enter</kbd> on your
-keyboard to filter the list.
+To search:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Epics**.
+1. Select the field **Search or filter results**.
+1. From the dropdown menu, select the scope or enter plain text to search by epic title or description.
+1. Press <kbd>Enter</kbd> on your keyboard. The list is filtered.
You can also sort epics list by:
@@ -173,22 +198,22 @@ The sort option and order is saved and used wherever you browse epics, including
## Change activity sort order
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214364) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214364) in GitLab 13.2.
You can reverse the default order and interact with the activity feed sorted by most recent items
at the top. Your preference is saved via local storage and automatically applied to every epic and issue
you view.
-To change the activity sort order, click the **Oldest first** dropdown menu and select either oldest
+To change the activity sort order, select the **Oldest first** dropdown menu and select either oldest
or newest items to be shown first.
![Issue activity sort order dropdown button](img/epic_activity_sort_order_v13_2.png)
## Make an epic confidential
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213068) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0 behind a feature flag, disabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/224513) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
-> - You can [use the Confidentiality option in the epic sidebar](https://gitlab.com/gitlab-org/gitlab/-/issues/197340) in GitLab [Premium](https://about.gitlab.com/pricing/) 13.3 and later.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213068) in GitLab 13.0 behind a feature flag, disabled by default.
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/224513) in GitLab 13.2.
+> - You can [use the Confidentiality option in the epic sidebar](https://gitlab.com/gitlab-org/gitlab/-/issues/197340) in GitLab 13.3 and later.
If you're working on items that contain private information, you can make an epic confidential.
@@ -200,8 +225,8 @@ to learn how to create a confidential merge request.
To make an epic confidential:
-- **When creating an epic:** select the checkbox **Make this epic confidential**.
-- **In an existing epic:** in the epic's sidebar, select **Edit** next to **Confidentiality** then
+- **When creating an epic:** select the checkbox under **Confidentiality**.
+- **In an existing epic:** on the right sidebar, select **Edit** next to **Confidentiality**, and then
select **Turn on**.
## Manage issues assigned to an epic
@@ -233,12 +258,12 @@ current parent.
To add a new issue to an epic:
-1. On the epic's page, under **Epics and Issues**, select the **Add** dropdown button.
+1. On the epic's page, under **Epics and Issues**, select **Add**.
1. Select **Add an existing issue**.
1. Identify the issue to be added, using either of the following methods:
- Paste the link of the issue.
- Search for the desired issue by entering part of the issue's title, then selecting the desired
- match (introduced in [GitLab 12.5](https://gitlab.com/gitlab-org/gitlab/-/issues/9126)).
+ match ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9126) in GitLab 12.5).
If there are multiple issues to be added, press <kbd>Space</kbd> and repeat this step.
1. Select **Add**.
@@ -252,7 +277,7 @@ while dividing work into smaller parts.
To create an issue from an epic:
-1. On the epic's page, under **Epics and Issues**, select the **Add** dropdown button.
+1. On the epic's page, under **Epics and Issues**, select **Add**.
1. Select **Add a new issue**.
1. Under **Title**, enter the title for the new issue.
1. From the **Project** dropdown, select the project in which the issue should be created.
@@ -265,7 +290,7 @@ After you remove an issue from an epic, the issue is no longer associated with t
To remove an issue from an epic:
-1. Select the **Remove** (**{close}**) button next to the issue you want to remove.
+1. Next to the issue you want to remove, select **Remove** (**{close}**).
The **Remove issue** warning appears.
1. Select **Remove**.
@@ -285,7 +310,7 @@ To reorder issues assigned to an epic:
### Move issues between epics **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33039) in GitLab 13.0.
New issues appear at the top of the list in the **Epics and Issues**
tab. You can move issues from one epic to another.
@@ -297,8 +322,8 @@ To move an issue to another epic:
### Promote an issue to an epic
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3777) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) to [GitLab Premium](https://about.gitlab.com/pricing/) in 12.8.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3777) in GitLab 11.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) from GitLab Ultimate to GitLab Premium in 12.8.
If you have the necessary [permissions](../../permissions.md) to close an issue and create an
epic in the immediate parent group, you can promote an issue to an epic with the `/promote`
@@ -318,7 +343,7 @@ The following issue metadata is copied to the epic:
- Upvotes/downvotes.
- Participants.
- Group labels that the issue already has.
-- Parent epic. **(ULTIMATE)**
+- Parent epic.
### Use an epic template for repeating issues
@@ -331,8 +356,6 @@ For more on epic templates, see [Epic Templates - Repeatable sets of issues](htt
## Multi-level child epics **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8333) in GitLab Ultimate 11.7.
-
You can add any epic that belongs to a group or subgroup of the parent epic's group.
New child epics appear at the top of the list of epics in the **Epics and Issues** tab.
@@ -344,19 +367,19 @@ Epics can contain multiple nested child epics, up to a total of seven levels dee
To add a child epic to an epic:
-1. Select the **Add** dropdown button.
+1. Select **Add**.
1. Select **Add a new epic**.
1. Identify the epic to be added, using either of the following methods:
- Paste the link of the epic.
- Search for the desired issue by entering part of the epic's title, then selecting the desired
- match (introduced in [GitLab 12.5](https://gitlab.com/gitlab-org/gitlab/-/issues/9126)).
+ match ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9126) in GitLab 12.5).
If there are multiple epics to be added, press <kbd>Space</kbd> and repeat this step.
1. Select **Add**.
### Move child epics between epics
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33039) in GitLab 13.0.
New child epics appear at the top of the list in the **Epics and Issues** tab.
You can move child epics from one epic to another.
@@ -384,13 +407,6 @@ To reorder child epics assigned to an epic:
To remove a child epic from a parent epic:
-1. Select the <kbd>x</kbd> button in the parent epic's list of epics.
-1. Select **Remove** in the **Remove epic** warning message.
-
-## Cached epic count
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299540) in GitLab 13.11.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/327320) in GitLab 14.0.
-
-In a group, the sidebar displays the total count of open epics and this value is cached if higher
-than 1000. The cached value is rounded to thousands (or millions) and updated every 24 hours.
+1. Select **Remove** (**{close}**) in the parent epic's list of epics.
+ The **Remove epic** warning appears.
+1. Select **Remove**.
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
index 1f5de36303e..70406cfe8e8 100644
--- a/doc/user/group/import/index.md
+++ b/doc/user/group/import/index.md
@@ -7,9 +7,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Migrate groups from another instance of GitLab **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/249160) in GitLab 13.7.
-> - [Deployed behind a feature flag](../../feature_flags.md), disabled by default.
-> - Enabled on GitLab.com.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/249160) in GitLab 13.7 [with a flag](../../feature_flags.md) named `bulk_import`. Disabled by default.
+> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338985) in GitLab 14.3.
NOTE:
The importer migrates **only** the group data listed on this page. To leave feedback on this
@@ -19,23 +18,23 @@ Using GitLab Group Migration, you can migrate existing top-level groups from Git
The following resources are migrated to the target instance:
-- Groups ([Introduced in 13.7](https://gitlab.com/groups/gitlab-org/-/epics/4374))
+- Groups ([Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4374) in 13.7)
- description
- attributes
- subgroups
- - avatar ([Introduced in 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/322904))
-- Group Labels ([Introduced in 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/292429))
+ - avatar ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322904) in 14.0)
+- Group Labels ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292429) in 13.9)
- title
- description
- color
- - created_at ([Introduced in 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/300007))
- - updated_at ([Introduced in 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/300007))
-- Members ([Introduced in 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/299415))
+ - created_at ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300007) in 13.10)
+ - updated_at ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300007) in 13.10)
+- Members ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299415) in 13.9)
Group members are associated with the imported group if:
- The user already exists in the target GitLab instance and
- The user has a public email in the source GitLab instance that matches a
confirmed email in the target GitLab instance
-- Epics ([Introduced in 13.7](https://gitlab.com/gitlab-org/gitlab/-/issues/250281))
+- Epics ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250281) in 13.7)
- title
- description
- state (open / closed)
@@ -43,12 +42,12 @@ The following resources are migrated to the target instance:
- due date
- epic order on boards
- confidentiality
- - labels ([Introduced in 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/297460))
- - author ([Introduced in 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/298745))
- - parent epic ([Introduced in 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/297459))
- - emoji award ([Introduced in 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/297466))
- - events ([Introduced in 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/297465))
-- Milestones ([Introduced in 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/292427))
+ - labels ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/297460) in 13.9)
+ - author ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/298745) in 13.9)
+ - parent epic ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/297459) in 13.9)
+ - emoji award ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/297466) in 13.9)
+ - events ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/297465) in 13.10)
+- Milestones ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292427) in 13.10)
- title
- description
- state (active / closed)
@@ -56,8 +55,8 @@ The following resources are migrated to the target instance:
- due date
- created at
- updated at
- - iid ([Introduced in 13.11](https://gitlab.com/gitlab-org/gitlab/-/issues/326157))
-- Iterations ([Introduced in 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/292428))
+ - iid ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326157) in 13.11)
+- Iterations ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292428) in 13.10)
- iid
- title
- description
@@ -66,7 +65,7 @@ The following resources are migrated to the target instance:
- due date
- created at
- updated at
-- Badges ([Introduced in 13.11](https://gitlab.com/gitlab-org/gitlab/-/issues/292431))
+- Badges ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292431) in 13.11)
- name
- link URL
- image URL
@@ -77,19 +76,20 @@ Any other items are **not** migrated.
## Enable or disable GitLab Group Migration
-GitLab Migration is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) can enable it.
+GitLab Migration is deployed behind the `bulk_import` feature flag, which is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can disable it.
-To enable it:
+To disable it:
```ruby
-Feature.enable(:bulk_import)
+Feature.disable(:bulk_import)
```
-To disable it:
+To enable it:
```ruby
-Feature.disable(:bulk_import)
+Feature.enable(:bulk_import)
```
## Import your groups into GitLab
@@ -130,3 +130,8 @@ Migration importer page. The remote groups you have the Owner role for are liste
1. After a group has been imported, select its GitLab path to open its GitLab URL.
![Group Importer page](img/bulk_imports_v14_1.png)
+
+## Automate group and project import **(PREMIUM)**
+
+For information on automating user, group, and project import API calls, see
+[Automate group and project import](../../project/import/index.md#automate-group-and-project-import).
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 15d2da50012..f0e08301a1b 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -95,10 +95,8 @@ For details about groups, watch [GitLab Namespaces (users, groups and subgroups)
You can give a user access to all projects in a group.
-1. On the top bar, select **Menu > Groups**.
-1. Select **Your Groups**.
-1. Find your group and select it.
-1. From the left sidebar, select **Group information > Members**.
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Group information > Members**.
1. Fill in the fields.
- The role applies to all projects in the group. [Learn more about permissions](../permissions.md).
- On the **Access expiration date**, the user can no longer access projects in the group.
@@ -107,9 +105,7 @@ You can give a user access to all projects in a group.
As a user, you can request to be a member of a group, if an administrator allows it.
-1. On the top bar, select **Menu > Groups**.
-1. Select **Your Groups**.
-1. Find the group and select it.
+1. On the top bar, select **Menu > Groups** and find your group.
1. Under the group name, select **Request Access**.
As many as ten of the most-recently-active group owners receive an email with your request.
@@ -219,10 +215,13 @@ By default, every group inherits the branch protection set at the global level.
To change this setting for a specific group:
-1. Go to the group's **Settings > General** page.
+1. On the top bar, select **Menu > Groups**.
+1. Select **Your Groups**.
+1. Find the group and select it.
+1. From the left menu, select **Settings > General**.
1. Expand the **Permissions, LFS, 2FA** section.
1. Select the desired option in the **Default branch protection** dropdown list.
-1. Click **Save changes**.
+1. Select **Save changes**.
To change this setting globally, see [Default branch protection](../admin_area/settings/visibility_and_access_controls.md#protect-default-branches).
@@ -240,24 +239,26 @@ There are two different ways to add a new project to a group:
### Specify who can add projects to a group
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2534) in GitLab Premium 10.5.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25975) to GitLab Free in 11.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2534) in GitLab 10.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25975) from GitLab Premium to GitLab Free in 11.10.
By default, [Developers and Maintainers](../permissions.md#group-members-permissions) can create projects under a group.
To change this setting for a specific group:
-1. Go to the group's **Settings > General** page.
+1. On the top bar, select **Menu > Groups**.
+1. Select **Your Groups**.
+1. Find the group and select it.
+1. From the left menu, select **Settings > General**.
1. Expand the **Permissions, LFS, 2FA** section.
1. Select the desired option in the **Allowed to create projects** dropdown list.
-1. Click **Save changes**.
+1. Select **Save changes**.
To change this setting globally, see [Default project creation protection](../admin_area/settings/visibility_and_access_controls.md#define-which-roles-can-create-projects).
## Group activity analytics **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207164) in GitLab 12.10 as
-a [beta feature](https://about.gitlab.com/handbook/product/#beta).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207164) in GitLab 12.10 as a [beta feature](https://about.gitlab.com/handbook/product/#beta).
For a group, you can view how many merge requests, issues, and members were created in the last 90 days.
@@ -265,6 +266,8 @@ These Group Activity Analytics can be enabled with the `group_activity_analytics
![Recent Group Activity](img/group_activity_analytics_v13_10.png)
+Changes to [group wikis](../project/wiki/group.md) do not appear in group activity analytics.
+
### View group activity
You can view the most recent actions taken in a group, either in your browser or in an RSS feed:
@@ -307,7 +310,7 @@ All the members of the `Engineering` group are added to the `Frontend` group.
> - Enabled on GitLab.com.
> - Recommended for production use.
> - Replaces the existing form with buttons to open a modal window.
-> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](../project/members/index.md#enable-or-disable-modal-window). **(FREE SELF)**
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](../project/members/index.md#enable-or-disable-modal-window).
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -327,7 +330,7 @@ Group syncing allows LDAP groups to be mapped to GitLab groups. This provides mo
Group links can be created by using either a CN or a filter. To create these group links, go to the group's **Settings > LDAP Synchronization** page. After configuring the link, it may take more than an hour for the users to sync with the GitLab group.
-For more information on the administration of LDAP and group sync, refer to the [main LDAP documentation](../../administration/auth/ldap/index.md#group-sync).
+For more information on the administration of LDAP and group sync, refer to the [main LDAP documentation](../../administration/auth/ldap/ldap_synchronization.md#group-sync).
NOTE:
When you add LDAP synchronization, if an LDAP user is a group member and they are not part of the LDAP group, they are removed from the group.
@@ -410,7 +413,7 @@ because the project cannot be moved.
## Use a custom name for the initial branch
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43290) in GitLab 13.6.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43290) in GitLab 13.6.
When you create a new project in GitLab, a default branch is created with the
first push. The group owner can
@@ -430,7 +433,7 @@ This action removes the group. It also adds a background job to delete all proje
Specifically:
-- In [GitLab 12.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [Premium](https://about.gitlab.com/pricing/premium/) or higher tiers, this action adds a background job to mark a group for deletion. By default, the job schedules the deletion 7 days in the future. You can modify this waiting period through the [instance settings](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
+- In [GitLab 12.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [GitLab Premium](https://about.gitlab.com/pricing/premium/) or higher tiers, this action adds a background job to mark a group for deletion. By default, the job schedules the deletion 7 days in the future. You can modify this waiting period through the [instance settings](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
- In [GitLab 13.6 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/39504), if the user who sets up the deletion is removed from the group before the
deletion happens, the job is cancelled, and the group is no longer scheduled for deletion.
@@ -502,6 +505,9 @@ To prevent a project from being shared with other groups:
1. Select **Prevent sharing a project within `<group_name>` with other groups**.
1. Select **Save changes**.
+This setting applies to all subgroups unless overridden by a group owner. Groups already
+added to a project lose access when the setting is enabled.
+
## Prevent members from being added to a group **(PREMIUM)**
As a group owner, you can prevent any new project membership for all
@@ -522,10 +528,8 @@ API requests to add a new user to a project are not possible.
## Export members as CSV **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/287940) in GitLab 14.2.
-
-FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature per group, ask an administrator to [disable the :ff_group_membership_export flag](../../administration/feature_flags.md). On GitLab.com, this feature is available.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/287940) in GitLab 14.2.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/336520) in GitLab 14.5.
You can export a list of members in a group as a CSV.
@@ -535,8 +539,8 @@ You can export a list of members in a group as a CSV.
## Restrict group access by IP address **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1985) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215410) to [GitLab Premium](https://about.gitlab.com/pricing/) in 13.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1985) in GitLab 12.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215410) from GitLab Ultimate to GitLab Premium in 13.1.
To ensure only people from your organization can access particular
resources, you can restrict access to groups by IP address. This group-level setting
@@ -571,7 +575,7 @@ To restrict group access by IP address:
## Restrict group access by domain **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7297) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.2.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7297) in GitLab 12.2.
> - Support for specifying multiple email domains [added](https://gitlab.com/gitlab-org/gitlab/-/issues/33143) in GitLab 13.1.
> - Support for restricting access to projects within the group [added](https://gitlab.com/gitlab-org/gitlab/-/issues/14004) in GitLab 14.1.2.
@@ -614,7 +618,7 @@ To learn how to create templates for issues and merge requests, see
[Description templates](../project/description_templates.md).
Define project templates at a group level by setting a group as the template source.
-[Learn more about group-level project templates](custom_project_templates.md). **(PREMIUM)**
+[Learn more about group-level project templates](custom_project_templates.md).
### Enable group file template **(PREMIUM)**
@@ -693,7 +697,7 @@ In GitLab 13.11 and above the group setting for delayed project removal is inher
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216987) in GitLab 13.3.
By default, projects in a group can be forked.
-Optionally, on [Premium](https://about.gitlab.com/pricing/) or higher tiers,
+Optionally, on [GitLab Premium](https://about.gitlab.com/pricing/) or higher tiers,
you can prevent the projects in a group from being forked outside of the current top-level group.
Previously, this setting was available only for groups enforcing a
@@ -732,19 +736,17 @@ The group's new subgroups have push rules set for them based on either:
## Group approval rules **(PREMIUM)**
-> Introduced in GitLab 13.9. [Deployed behind the `group_merge_request_approval_settings_feature_flag` flag](../../administration/feature_flags.md), disabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285458) in GitLab 13.9. [Deployed behind the `group_merge_request_approval_settings_feature_flag` flag](../../administration/feature_flags.md), disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/285410) in GitLab 14.5.
FLAG:
-On self-managed GitLab, by default this feature is not available. To make it available,
-per group, ask an administrator to [enable the `group_merge_request_approval_settings_feature_flag` flag](../../administration/feature_flags.md).
-The feature is not ready for production use.
+On self-managed GitLab, by default this feature is available. To hide the feature per group, ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `group_merge_request_approval_settings_feature_flag`. On GitLab.com, this feature is available.
-Group approval rules are an in-development feature that provides an interface for managing
-[project merge request approval rules](../project/merge_requests/approvals/index.md) at the
-top-level group level. When rules are configured [at the instance level](../admin_area/merge_requests_approvals.md),
-you can't edit locked rules.
+Group approval rules manage [project merge request approval rules](../project/merge_requests/approvals/index.md)
+at the top-level group level. These rules [cascade to all projects](../project/merge_requests/approvals/settings.md#settings-cascading)
+that belong to the group.
-To view the merge request approval rules UI for a group:
+To view the merge request approval rules for a group:
1. Go to the top-level group's **Settings > General** page.
1. Expand the **Merge request approvals** section.
@@ -754,20 +756,20 @@ To view the merge request approval rules UI for a group:
## Related topics
- [Group wikis](../project/wiki/index.md)
-- [Maximum artifacts size](../admin_area/settings/continuous_integration.md#maximum-artifacts-size). **(FREE SELF)**
-- [Repositories analytics](repositories_analytics/index.md): View overall activity of all projects with code coverage. **(PREMIUM)**
+- [Maximum artifacts size](../admin_area/settings/continuous_integration.md#maximum-artifacts-size).
+- [Repositories analytics](repositories_analytics/index.md): View overall activity of all projects with code coverage.
- [Contribution analytics](contribution_analytics/index.md): View the contributions (pushes, merge requests,
- and issues) of group members. **(PREMIUM)**
-- [Issue analytics](issues_analytics/index.md): View a bar chart of your group's number of issues per month. **(PREMIUM)**
+ and issues) of group members.
+- [Issue analytics](issues_analytics/index.md): View a bar chart of your group's number of issues per month.
- Use GitLab as a [dependency proxy](../packages/dependency_proxy/index.md) for upstream Docker images.
-- [Epics](epics/index.md): Track groups of issues that share a theme. **(ULTIMATE)**
+- [Epics](epics/index.md): Track groups of issues that share a theme.
- [Security Dashboard](../application_security/security_dashboard/index.md): View the vulnerabilities of all
- the projects in a group and its subgroups. **(ULTIMATE)**
+ the projects in a group and its subgroups.
- [Insights](insights/index.md): Configure insights like triage hygiene, issues created/closed per a given period, and
- average time for merge requests to be merged. **(ULTIMATE)**
+ average time for merge requests to be merged.
- [Webhooks](../project/integrations/webhooks.md).
- [Kubernetes cluster integration](clusters/index.md).
-- [Audit Events](../../administration/audit_events.md#group-events). **(PREMIUM)**
+- [Audit Events](../../administration/audit_events.md#group-events).
- [Pipelines quota](../admin_area/settings/continuous_integration.md): Keep track of the pipeline quota for the group.
- [Integrations](../admin_area/settings/project_integration_management.md).
- [Transfer a project into a group](../project/settings/index.md#transferring-an-existing-project-into-another-namespace).
@@ -775,7 +777,7 @@ To view the merge request approval rules UI for a group:
- [Lock the sharing with group feature](#prevent-a-project-from-being-shared-with-groups).
- [Enforce two-factor authentication (2FA)](../../security/two_factor_authentication.md#enforce-2fa-for-all-users-in-a-group): Enforce 2FA
for all group members.
-- Namespaces [API](../../api/namespaces.md) and [Rake tasks](../../raketasks/features.md)..
+- Namespaces [API](../../api/namespaces.md) and [Rake tasks](../../raketasks/features.md).
## Troubleshooting
diff --git a/doc/user/group/insights/index.md b/doc/user/group/insights/index.md
index 9f841691eb8..b3fdeb0ab41 100644
--- a/doc/user/group/insights/index.md
+++ b/doc/user/group/insights/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Insights **(ULTIMATE)**
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in GitLab 12.0.
Configure the Insights that matter for your groups. Explore data such as
triage hygiene, issues created or closed for a given period, average time for merge
diff --git a/doc/user/group/issues_analytics/index.md b/doc/user/group/issues_analytics/index.md
index 3d28ef5306d..ac5df6b052f 100644
--- a/doc/user/group/issues_analytics/index.md
+++ b/doc/user/group/issues_analytics/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Issue Analytics **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7478) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.5.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7478) in GitLab 11.5.
Issue Analytics is a bar graph which illustrates the number of issues created each month.
The default time span is 13 months, which includes the current month, and the 12 months
diff --git a/doc/user/group/iterations/index.md b/doc/user/group/iterations/index.md
index 70fa3ba639d..7a1cbe86d58 100644
--- a/doc/user/group/iterations/index.md
+++ b/doc/user/group/iterations/index.md
@@ -13,7 +13,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - Enabled on GitLab.com.
> - Can be enabled or disabled per-group.
> - Recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-iterations). **(PREMIUM ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-iterations).
> - Moved to GitLab Premium in 13.9.
Iterations are a way to track issues over a period of time. This allows teams
@@ -38,7 +38,7 @@ In GitLab, iterations are similar to milestones, with a few differences:
> - Deployed behind a [feature flag](../../feature_flags.md), disabled by default.
> - Disabled on GitLab.com.
> - Not recommended for production use.
-> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-iteration-cadences). **(PREMIUM SELF)**
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-iteration-cadences).
This in-development feature might not be available for your use. There can be
[risks when enabling features still in development](../../../administration/feature_flags.md#risks-when-enabling-features-still-in-development).
@@ -144,7 +144,7 @@ To view an iteration report, go to the iterations list page and select an iterat
### Iteration burndown and burnup charts
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222750) in GitLab 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222750) in GitLab 13.6.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/269972) in GitLab 13.7.
The iteration report includes [burndown and burnup charts](../../project/milestones/burndown_and_burnup_charts.md),
diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md
index 656c40d1915..206f3172170 100644
--- a/doc/user/group/roadmap/index.md
+++ b/doc/user/group/roadmap/index.md
@@ -7,11 +7,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Roadmap **(PREMIUM)**
-> - Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.5.
-> - In [GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/198062), Roadmaps were moved to the Premium tier.
+> - Introduced in GitLab 10.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/198062) from GitLab Ultimate to GitLab Premium in 12.9.
> - In [GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/5164) and later, the epic bars show epics' title, progress, and completed weight percentage.
> - Milestones appear in roadmaps in [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/issues/6802), and later.
-> - Feature flag for milestones visible in roadmaps removed in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29641).
+> - Feature flag for milestones visible in roadmaps [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29641) in GitLab 13.0.
> - In [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/214375) and later, the Roadmap also shows milestones in projects in a group.
> - In [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/212494) and later, milestone bars can be collapsed and expanded.
@@ -36,13 +36,10 @@ toggle the list of the milestone bars.
## Sort and filter the Roadmap
-> - Filtering roadmaps by milestone [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218621) in GitLab 13.7.
-> - Filtering roadmaps by milestone is [deployed behind a feature flag](../../feature_flags.md), enabled by default.
-> - Filtering roadmaps by milestone is enabled on GitLab.com.
-> - Filtering roadmaps by milestone is recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-filtering-roadmaps-by-milestone). **(PREMIUM SELF)**
+> - Filtering by milestone [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218621) in GitLab 13.7 [with a flag](../../../administration/feature_flags.md) named `roadmap_daterange_filter`. Enabled by default.
> - Filtering by epic confidentiality [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218624) in GitLab 13.9.
> - Filtering by epic [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218623) in GitLab 13.11.
+> - Filtering by milestone [feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323917) in GitLab 14.5.
WARNING:
Filtering roadmaps by milestone might not be available to you. Check the **version history** note above for details.
@@ -56,8 +53,6 @@ A dropdown menu lets you show only open or closed epics. By default, all epics a
You can sort epics in the Roadmap view by:
-- Created date
-- Last updated
- Start date
- Due date
@@ -77,40 +72,16 @@ You can also filter epics in the Roadmap view by the epics':
Roadmaps can also be [visualized inside an epic](../epics/index.md#roadmap-in-epics).
-### Enable or disable filtering roadmaps by milestone **(PREMIUM SELF)**
-
-Filtering roadmaps by milestone is under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can opt to disable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:async_filtering)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:async_filtering)
-```
-
## Timeline duration
-> - Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0.
-> - In [GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/198062), Timelines were moved to the Premium tier.
+> - Introduced in GitLab 11.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/198062) from GitLab Ultimate to GitLab Premium in 12.9.
### Date range presets
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/204994) in GitLab 14.3. [Deployed behind the `roadmap_daterange_filter` flag](../../../administration/feature_flags.md), disabled by default.
-> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/323917) in GitLab 14.3.
-
-FLAG:
-On self-managed GitLab, by default this feature is not available. To make it available per group,
-ask an administrator to [enable the `roadmap_daterange_filter` flag](../../../administration/feature_flags.md).
-On GitLab.com, this feature is available.
-The feature is ready for production use.
+> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/323917) in GitLab 14.3.
+> - [Feature flag `roadmap_daterange_filter` removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72419) in GitLab 14.5.
Roadmap provides three date range options, each with predetermined timeline duration:
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 1c894550a14..402007b85b2 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -118,8 +118,9 @@ SSO has the following effects when enabled:
- For groups, users can't share a project in the group outside the top-level group,
even if the project is forked.
-- For a Git activity, users must be signed-in through SSO before they can push to or
- pull from a GitLab repository.
+- For Git activity over SSH and HTTPS, users must have at least one active session signed-in through SSO before they can push to or
+ pull from a GitLab repository.
+- Credentials that are not tied to regular users (for example, access tokens and deploy keys) do not have the SSO check enforced.
- Users must be signed-in through SSO before they can pull images using the [Dependency Proxy](../../packages/dependency_proxy/index.md).
<!-- Add bullet for API activity when https://gitlab.com/gitlab-org/gitlab/-/issues/9152 is complete -->
@@ -242,11 +243,12 @@ On subsequent visits, you should be able to go [sign in to GitLab.com with SAML]
### Configure user settings from SAML response
-[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263661) in GitLab 13.7.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263661) in GitLab 13.7.
GitLab allows setting certain user attributes based on values from the SAML response.
-This affects users created on first sign-in via Group SAML. Existing users'
-attributes are not affected regardless of the values sent in the SAML response.
+Existing users will have these attributes updated if the user was originally
+provisioned by the group. Users are provisioned by the group when the account was
+created via [SCIM](scim_setup.md) or by first sign-in with SAML SSO for GitLab.com groups.
#### Supported user attributes
@@ -341,9 +343,8 @@ Ensure your SAML identity provider sends an attribute statement named `Groups` o
```
NOTE:
+The value for `Groups` or `groups` in the SAML response can be either the group name or the group ID.
To inspect the SAML response, you can use one of these [SAML debugging tools](#saml-debugging-tools).
-Also note that the value for `Groups` or `groups` in the SAML response can be either the group name or
-the group ID depending what the IdP sends to GitLab.
When SAML SSO is enabled for the top-level group, `Maintainer` and `Owner` level users
see a new menu item in group **Settings > SAML Group Links**. You can configure one or more **SAML Group Links** to map
@@ -516,6 +517,13 @@ Here are possible causes and solutions:
| ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| When a user account with the email address already exists in GitLab, but the user does not have the SAML identity tied to their account. | The user needs to [link their account](#user-access-and-management). |
+User accounts are created in one of the following ways:
+
+- User registration
+- Sign in through OAuth
+- Sign in through SAML
+- SCIM provisioning
+
### Message: "SAML authentication failed: Extern UID has already been taken, User has already been taken"
Getting both of these errors at the same time suggests the NameID capitalization provided by the identity provider didn't exactly match the previous value for that user.
@@ -531,6 +539,16 @@ Alternatively, the SAML response may be missing the `InResponseTo` attribute in
The identity provider administrator should ensure that the login is
initiated by the service provider and not the identity provider.
+### Message: "Login to a GitLab account to link with your SAML identity"
+
+A user can see this message when they are trying to [manually link SAML to their existing GitLab.com account](#linking-saml-to-your-existing-gitlabcom-account).
+
+To resolve this problem, the user should check they are using the correct GitLab password to log in. They first need to
+[reset their password](https://gitlab.com/users/password/new) if both:
+
+- The account was provisioned by SCIM.
+- This is the first time the user has logged in the username and password.
+
### Stuck in a login "loop"
Ensure that the **GitLab single sign-on URL** has been configured as "Login URL" (or similarly named field) in the identity provider's SAML app.
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index 5e90501d487..dd4558b4a3e 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# SCIM provisioning using SAML SSO for GitLab.com groups **(PREMIUM SAAS)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in GitLab Premium 11.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in GitLab 11.10.
System for Cross-domain Identity Management (SCIM), is an open standard that enables the
automation of user provisioning. When SCIM is provisioned for a GitLab group, membership of
@@ -35,9 +35,10 @@ The following identity providers are supported:
Once [Group Single Sign-On](index.md) has been configured, we can:
-1. Navigate to the group and click **Administration > SAML SSO**.
-1. Click on the **Generate a SCIM token** button.
-1. Save the token and URL so they can be used in the next step.
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > SAML SSO**.
+1. Select **Generate a SCIM token**.
+1. Save the token and URL for use in the next step.
![SCIM token configuration](img/scim_token_v13_3.png)
@@ -50,14 +51,14 @@ Once [Group Single Sign-On](index.md) has been configured, we can:
The SAML application that was created during [Single sign-on](index.md) setup for [Azure](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) now needs to be set up for SCIM.
-1. Set up automatic provisioning and administrative credentials by following the
+1. Enable automatic provisioning and administrative credentials by following the
[Azure's SCIM setup documentation](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#provisioning-users-and-groups-to-applications-that-support-scim).
During this configuration, note the following:
-- The `Tenant URL` and `secret token` are the ones retrieved in the
+- The `Tenant URL` and `secret token` are the items retrieved in the
[previous step](#gitlab-configuration).
-- It is recommended to set a notification email and check the **Send an email notification when a failure occurs** checkbox.
+- We recommend setting a notification email and selecting the **Send an email notification when a failure occurs** checkbox.
- For mappings, we only leave `Synchronize Azure Active Directory Users to AppName` enabled.
`Synchronize Azure Active Directory Groups to AppName` is usually disabled. However, this
does not mean Azure AD users cannot be provisioned in groups. Leaving it enabled does not break
@@ -113,29 +114,27 @@ Make sure that the Okta setup matches our documentation exactly, especially the
configuration. Otherwise, the Okta SCIM app may not work properly.
1. Sign in to Okta.
-1. If you see an **Admin** button in the top right, click the button. This will
- ensure you are in the Admin area.
+1. Ensure you are in the Admin section by selecting the **Admin** button located in the top right. The admin button is not visible from the admin page.
NOTE:
- If you're using the Developer Console, click **Developer Console** in the top
- bar and select **Classic UI**. Otherwise, you may not see the buttons described
- in the following steps:
+ If you're using the Developer Console, select **Developer Console** in the top
+ bar and then select **Classic UI**. Otherwise, you may not see the buttons described in the following steps:
-1. In the **Application** tab, click **Add Application**.
-1. Search for **GitLab**, find and click on the 'GitLab' application.
-1. On the GitLab application overview page, click **Add**.
+1. In the **Application** tab, select **Add Application**.
+1. Search for **GitLab**, find and select on the 'GitLab' application.
+1. On the GitLab application overview page, select **Add**.
1. Under **Application Visibility** select both checkboxes. Currently the GitLab application does not support SAML authentication so the icon should not be shown to users.
-1. Click **Done** to finish adding the application.
-1. In the **Provisioning** tab, click **Configure API integration**.
+1. Select **Done** to finish adding the application.
+1. In the **Provisioning** tab, select **Configure API integration**.
1. Select **Enable API integration**.
- For **Base URL** enter the URL obtained from the GitLab SCIM configuration page
- For **API Token** enter the SCIM token obtained from the GitLab SCIM configuration page
-1. Click 'Test API Credentials' to verify configuration.
-1. Click **Save** to apply the settings.
-1. After saving the API integration details, new settings tabs appear on the left. Choose **To App**.
-1. Click **Edit**.
-1. Check the box to **Enable** for both **Create Users** and **Deactivate Users**.
-1. Click **Save**.
+1. Select 'Test API Credentials' to verify configuration.
+1. Select **Save** to apply the settings.
+1. After saving the API integration details, new settings tabs appear on the left. Select **To App**.
+1. Select **Edit**.
+1. Select the **Enable** checkbox for both **Create Users** and **Deactivate Users**.
+1. Select **Save**.
1. Assign users in the **Assignments** tab. Assigned users are created and
managed in your GitLab group.
@@ -147,8 +146,8 @@ application described above.
### OneLogin
-OneLogin provides a "GitLab (SaaS)" app in their catalog, which includes a SCIM integration.
-As the app is developed by OneLogin, please reach out to OneLogin if you encounter issues.
+As the developers of this app, OneLogin provides a "GitLab (SaaS)" app in their catalog, which includes a SCIM integration.
+Please reach out to OneLogin if you encounter issues.
## User access and linking setup
@@ -177,8 +176,8 @@ As long as [Group SAML](index.md) has been configured, existing GitLab.com users
- By following these steps:
1. Sign in to GitLab.com if needed.
- 1. Click on the GitLab app in the identity provider's dashboard or visit the **GitLab single sign-on URL**.
- 1. Click on the **Authorize** button.
+ 1. In the identity provider's dashboard select the GitLab app or visit the **GitLab single sign-on URL**.
+ 1. Select the **Authorize**.
We recommend users do this prior to turning on sync, because while synchronization is active, there may be provisioning errors for existing users.
diff --git a/doc/user/group/settings/import_export.md b/doc/user/group/settings/import_export.md
index 3f9d94f044e..3692a2636ab 100644
--- a/doc/user/group/settings/import_export.md
+++ b/doc/user/group/settings/import_export.md
@@ -40,7 +40,7 @@ be imported into the desired group structure.
- To preserve the member list and their respective permissions on imported groups, review the users in these groups. Make
sure these users exist before importing the desired groups.
-### Exported Contents
+### Exported contents
The following items are exported:
@@ -51,8 +51,8 @@ The following items are exported:
- Subgroups (including all the aforementioned data)
- Epics
- Events
-- [Wikis](../../project/wiki/index.md#group-wikis) **(PREMIUM SELF)**
- (Introduced in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53247))
+- [Wikis](../../project/wiki/group.md)
+ ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53247) in GitLab 13.9)
The following items are **not** exported:
@@ -109,6 +109,11 @@ The Enterprise Edition retains some group data that isn't part of the Community
Your newly imported group page appears after the operation completes.
+## Automate group and project import **(PREMIUM)**
+
+For information on automating user, group, and project import API calls, see
+[Automate group and project import](../../project/import/index.md#automate-group-and-project-import).
+
## Version history
### 14.0+
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index 49032d0a2ef..acce296da93 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto, concepts
---
-# Subgroups
+# Subgroups **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/2772) in GitLab 9.0.
diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md
index 5c8393f30ab..a0a13c71d95 100644
--- a/doc/user/group/value_stream_analytics/index.md
+++ b/doc/user/group/value_stream_analytics/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Value Stream Analytics **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196455) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.9 for groups.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196455) in GitLab 12.9 for groups.
Value Stream Analytics measures the time spent to go from an
[idea to production](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab)
@@ -27,6 +27,7 @@ To view group-level Value Stream Analytics:
Value Stream Analytics at the group level includes data for the selected group and its subgroups.
+NOTE:
[Project-level Value Stream Analytics](../../analytics/value_stream_analytics.md) is also available.
## Default stages
@@ -77,16 +78,41 @@ Data is shown for workflow items created during the selected date range. To filt
1. Optionally select a project.
1. Select a date range using the available date pickers.
+### Upcoming date filter change
+
+In the [epics](https://gitlab.com/groups/gitlab-org/-/epics/6046), we plan to alter
+the date filter behavior to filter the end event time of the currently selected stage.
+
+The change makes it possible to get a much better picture about the completed items within the
+stage and helps uncover long-running items.
+
+For example, an issue was created a year ago and the current stage was finished in the current month.
+If you were to look at the metrics for the last three months, this issue would not be included in the calculation of
+the stage metrics. With the new date filter, this item would be included.
+
+DISCLAIMER:
+This page contains information related to upcoming products, features, and functionality.
+It is important to note that the information presented is for informational purposes only.
+Please do not rely on this information for purchasing or planning purposes.
+As with all projects, the items mentioned on this page are subject to change or delay.
+The development, release, and timing of any products, features, or functionality remain at the
+sole discretion of GitLab Inc.
+
## How metrics are measured
-> DORA API-based deployment metrics [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/337256)
-> to Premium in GitLab 14.3 for group-level Value Stream Analytics.
+> DORA API-based deployment metrics for group-level Value Stream Analytics were
+> [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/337256) from GitLab Ultimate to GitLab Premium in 14.3.
The "Time" metrics near the top of the page are measured as follows:
- **Lead time**: median time from issue created to issue closed.
- **Cycle time**: median time from first commit to issue closed. (You can associate a commit with an
issue by [crosslinking in the commit message](../../project/issues/crosslinking_issues.md#from-commit-messages).)
+- **Lead Time for Changes**: median time between when a merge request is merged and deployed to a
+production environment for all merge requests deployed in the given time period.
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340150) in GitLab 14.5.
+
+- **Lead Time for Changes**: median duration between merge request merge and deployment to a production environment for all MRs deployed in the given time period. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340150) in GitLab 14.5.
The "Recent Activity" metrics near the top of the page are measured as follows:
@@ -391,8 +417,8 @@ To delete a custom value stream:
## Days to completion chart
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21631) in GitLab 12.6.
-> - [Chart median line removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235455) in GitLab 13.4.
-> - [Totals replaced with averages](https://gitlab.com/gitlab-org/gitlab/-/issues/262070) in GitLab 13.12.
+> - Chart median line [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235455) in GitLab 13.4.
+> - Totals [replaced](https://gitlab.com/gitlab-org/gitlab/-/issues/262070) with averages in GitLab 13.12.
This chart visually depicts the average number of days it takes for cycles to be completed.
@@ -404,7 +430,7 @@ The chart data is limited to the last 500 items.
## Type of work - Tasks by type chart
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32421) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32421) in GitLab 12.10.
This chart shows a cumulative count of issues and merge requests per day.
diff --git a/doc/user/index.md b/doc/user/index.md
index c9f20af9668..a3b7cfc4b3c 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -85,6 +85,7 @@ There are several types of users in GitLab:
## User activity
+GitLab tracks user contribution activity.
You can follow or unfollow other users from their [user profiles](profile/index.md#access-your-user-profile).
To view a user's activity in a top-level Activity view:
@@ -92,6 +93,55 @@ To view a user's activity in a top-level Activity view:
1. In the GitLab menu, select **Activity**.
1. Select the **Followed users** tab.
+### User contribution events
+
+Each of these contribution events is tracked:
+
+- `approved`
+ - Merge request
+- `closed`
+ - [Epic](group/epics/index.md)
+ - Issue
+ - Merge request
+ - Milestone
+- `commented` on any `Noteable` record.
+ - Alert
+ - Commit
+ - Design
+ - Issue
+ - Merge request
+ - Snippet
+- `created`
+ - Design
+ - [Epic](group/epics/index.md)
+ - Issue
+ - Merge request
+ - Milestone
+ - Project
+ - Wiki page
+- `destroyed`
+ - Design
+ - Milestone
+ - Wiki page
+- `expired`
+ - Project membership
+- `joined`
+ - Project membership
+- `left`
+ - Project membership
+- `merged`
+ - Merge request
+- `pushed` commits to (or deleted commits from) a repository, individually or in bulk.
+ - Project
+- `reopened`
+ - [Epic](group/epics/index.md)
+ - Issue
+ - Merge request
+ - Milestone
+- `updated`
+ - Design
+ - Wiki page
+
## Projects
In GitLab, you can create [projects](project/index.md) to host
diff --git a/doc/user/infrastructure/clusters/connect/index.md b/doc/user/infrastructure/clusters/connect/index.md
index 636cb1bb457..21387998a17 100644
--- a/doc/user/infrastructure/clusters/connect/index.md
+++ b/doc/user/infrastructure/clusters/connect/index.md
@@ -6,62 +6,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Connect a cluster to GitLab **(FREE)**
-You can create new or connect existing clusters to GitLab through different [levels](#cluster-levels),
-using different [methods](#methods-to-connect-a-cluster-to-gitlab).
+The [certificate-based Kubernetes integration with GitLab](../index.md)
+was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8)
+in GitLab 14.5. To connect your clusters, use the [GitLab Kubernetes Agent](../../../clusters/agent/index.md).
-Before getting started:
-
-1. Check the [supported Kubernetes cluster versions](#supported-cluster-versions).
-1. Define the [cluster level](#cluster-levels) according to your case.
-
-After that:
-
-1. Choose the [method](#methods-to-connect-a-cluster-to-gitlab)
-to connect your cluster according to your case.
-1. [View your clusters](#view-your-clusters) connected to GitLab.
-
-## Methods to connect a cluster to GitLab
-
-GitLab offers three methods to connect existing and create new clusters:
-
-- **GitLab Kubernetes Agent**: the best solution to
-[connect existing clusters](#connect-existing-clusters-to-gitlab).
-- **Infrastructure as Code**: it's a broader infrastructure management
-toolset that includes managing your cluster. It's the recommended
-solution to [create a new cluster](#create-new-clusters-from-gitlab)
-from GitLab.
-- **Certificate-based method**: our first and legacy solution uses
-cluster certificates to connect your cluster to GitLab. It is no longer
-recommended for [security implications](#security-implications-for-clusters-connected-with-certificates).
-
-### Connect existing clusters to GitLab
-
-To safely connect and configure an existing cluster on the **project level**,
-we **recommend** using the [GitLab Kubernetes Agent](../../../clusters/agent/index.md).
-We are working to support [the Agent for connecting a cluster at the group level](https://gitlab.com/groups/gitlab-org/-/epics/5784).
-
-Alternatively, you can use [cluster certificates](../../../project/clusters/add_existing_cluster.md)
-to connect clusters in all levels (projects, group, instance). However,
-for [security implications](#security-implications-for-clusters-connected-with-certificates),
-we don't recommend using this method.
-
-### Create new clusters from GitLab
-
-To safely create new clusters from GitLab, use
-[Infrastructure as Code](../../iac/index.md#create-a-new-cluster-through-iac).
-
-The [certificate-based method to create a new cluster](../../../project/clusters/add_remove_clusters.md)
-is still available through the GitLab UI but was **deprecated** in GitLab 14.0.
-If possible, we don't recommend using this method.
-
-### Connect multiple clusters to a single project
-
-To connect multiple clusters to a single project in GitLab,
-we **recommend** using the [GitLab Kubernetes Agent](../../../clusters/agent/index.md).
-
-You can also use the [certificate-based method](../../../project/clusters/multiple_kubernetes_clusters.md),
-but, for [security implications](#security-implications-for-clusters-connected-with-certificates),
-we don't recommend using this method.
+<!-- TBA: (We need to resolve https://gitlab.com/gitlab-org/gitlab/-/issues/343660 before adding this line)
+If you don't have a cluster yet, create one and connect it to GitLab through the Agent.
+You can also create a new cluster from GitLab using [Infrastructure as Code](../../iac/index.md#create-a-new-cluster-through-iac).
+-->
## Supported cluster versions
@@ -85,7 +37,13 @@ Kubernetes version to any supported version at any time:
Some GitLab features may support versions outside the range provided here.
-## Cluster levels
+## Cluster levels (DEPRECATED)
+
+> [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+The [concept of cluster levels was deprecated](../index.md#cluster-levels)
+in GitLab 14.5.
Choose your cluster's level according to its purpose:
@@ -118,6 +76,8 @@ your cluster's level.
## Security implications for clusters connected with certificates
+> Connecting clusters to GitLab through cluster certificates was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
WARNING:
The whole cluster security is based on a model where [developers](../../../permissions.md)
are trusted, so **only trusted users should be allowed to control your clusters**.
diff --git a/doc/user/infrastructure/clusters/connect/new_gke_cluster.md b/doc/user/infrastructure/clusters/connect/new_gke_cluster.md
index 3c934b72886..d1e3bd47b89 100644
--- a/doc/user/infrastructure/clusters/connect/new_gke_cluster.md
+++ b/doc/user/infrastructure/clusters/connect/new_gke_cluster.md
@@ -4,7 +4,16 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# New GKE cluster through IaC
+# New GKE cluster through IaC (DEPRECATED)
+
+> [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+The process described on this page uses cluster certificates to connect the
+new cluster to GitLab, [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+You can still create a cluster and then connect it to GitLab through the [Agent](../index.md).
+[An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/343660)
+to migrate this functionality to the [Agent](../index.md).
Learn how to create a new cluster on Google Kubernetes Engine (GKE) through
[Infrastructure as Code (IaC)](../../index.md).
diff --git a/doc/user/infrastructure/clusters/index.md b/doc/user/infrastructure/clusters/index.md
index 16ca6d02865..06a77912876 100644
--- a/doc/user/infrastructure/clusters/index.md
+++ b/doc/user/infrastructure/clusters/index.md
@@ -6,61 +6,68 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Kubernetes clusters **(FREE)**
-> - Project-level clusters [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35954) in GitLab 10.1.
-> - Group-level clusters [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34758) in GitLab 11.6.
-> - Instance-level clusters [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39840) in GitLab 11.11.
-
-Kubernetes is a container orchestration platform to deploy applications
-in a cluster without downtime and that scales as you need.
-
-With the GitLab integration with Kubernetes, you can:
-
-1. [Connect your cluster](#connect-your-cluster-to-gitlab).
-1. [Manage your cluster](#manage-your-cluster).
-1. [Deploy your cluster](#deploy-to-your-cluster).
-
-See the [Kubernetes clusters versions supported by GitLab](connect/index.md#supported-cluster-versions).
-
-## Connect your cluster to GitLab
-
-Learn how to [create new and connect existing clusters to GitLab](connect/index.md).
-
-## Manage your cluster
-
-- [Cluster Management Project](../../clusters/management_project.md):
-create a project to manage your cluster's shared resources requiring
-`cluster-admin` privileges such as an Ingress controller.
- - [Cluster Management Project Template](../../clusters/management_project_template.md): start a cluster management project directly from a template.
- - [Migrate to Cluster Management Project](../../clusters/migrating_from_gma_to_project_template.md): migrate from the deprecated GitLab Managed Apps to Cluster Management Projects.
- - [GitLab Managed Apps](../../clusters/applications.md) (deprecated in favor of Cluster Management Projects): configure applications in your cluster directly from GitLab.
-- [Cluster integrations](../../clusters/integrations.md): install
-third-party applications into your cluster and manage them from GitLab.
-- [GitLab-managed clusters](../../project/clusters/gitlab_managed_clusters.md):
-enable GitLab to automatically create resources for your clusters.
-- [Cost management](../../clusters/cost_management.md): see insights into your cluster's resource usage.
-- [Crossplane integration](../../clusters/crossplane.md): manage your cluster's resources and cloud infrastructure with Crossplane.
-
-### Monitor your cluster
-
-- [Prometheus monitoring](../../project/integrations/prometheus_library/kubernetes.md): detect and monitor Kubernetes metrics with Prometheus.
-- [NGINX monitoring](../../project/integrations/prometheus_library/nginx.md): automatically monitor NGINX Ingress.
-- [Clusters health](manage/clusters_health.md): monitor your cluster's health, such as CPU and memory usage.
-
-### Secure your cluster
-
-- [Container Host Security](../../project/clusters/protect/container_host_security/index.md): monitor and block activity inside a container and enforce security policies across the cluster.
-- [Container Network security](../../project/clusters/protect/container_network_security/index.md): filter traffic going in and out of the cluster and traffic between pods through a firewall with Cilium NetworkPolicies.
-
-## Deploy to your cluster
-
-- [CI/CD Tunnel](../../clusters/agent/ci_cd_tunnel.md): use the CI/CD Tunnel to run Kubernetes commands from different projects.
-- [Inventory object](deploy/inventory_object.md): track objects applied to a cluster configured with the Kubernetes Agent.
-- [Auto DevOps](../../../topics/autodevops/index.md): enable Auto DevOps
-to allow GitLab automatically detect, build, test, and deploy applications.
-- [Cluster environments](../../clusters/environments.md): view CI/CD environments deployed to Kubernetes clusters.
-- [Canary Deployments](../../project/canary_deployments.md): deploy app updates to a small portion of the fleet with this Continuous Delivery strategy.
-- [Deploy to your cluster](../../project/clusters/deploy_to_cluster.md):
-deploy applications into your cluster using cluster certificates.
-- [Deploy Boards](../../project/deploy_boards.md): view the current health and status of each CI/CD environment running on your cluster, and the status of deployment pods.
-- [Pod logs](../../project/clusters/kubernetes_pod_logs.md): view the logs of your cluster's running pods.
-- [Serverless](../../project/clusters/serverless/index.md) (deprecated): deploy Serverless applications in Kubernetes environments and cloud Function as a Service (FaaS) environments.
+To connect clusters to GitLab, use the [GitLab Kubernetes Agent](../../clusters/agent/index.md).
+
+## Certificate-based Kubernetes integration (DEPRECATED)
+
+WARNING:
+In GitLab 14.5, the certificate-based method to connect Kubernetes clusters
+to GitLab was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8),
+as well as its related [features](#deprecated-features).
+
+The certificate-based Kubernetes integration with GitLab is deprecated.
+It had the following issues:
+
+- There were security issues as it required direct access to the Kube API by GitLab.
+- The configuration options weren't flexible.
+- The integration was flaky.
+- Users were constantly reporting issues with features based on this model.
+
+For this reason, we started to build features based on a new model, the
+[GitLab Kubernetes Agent](../../clusters/agent/index.md).
+Maintaining both methods in parallel caused a lot of confusion
+and significantly increased the complexity to use, develop, maintain, and
+document them. For this reason, we decided to deprecate them to focus on the
+new model.
+
+Certificate-based features will continue to receive security and critical
+fixes, and features built on top of it will continue to work with the supported
+Kubernetes versions. The removal of these features from GitLab is not
+scheduled yet.
+Follow this [epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8)
+for updates.
+
+You can find technical information about why we moved away from cluster certificates into
+the Kubernetes Agent model on the [Agent's blueprint documentation](../../../architecture/blueprints/gitlab_to_kubernetes_communication/index.md).
+
+## Deprecated features
+
+- [Create a new cluster through cluster certificates](../../project/clusters/add_remove_clusters.md)
+- [Connect an existing cluster through cluster certificates](../../project/clusters/add_existing_cluster.md)
+- [Access controls](../../project/clusters/cluster_access.md)
+- [GitLab-managed clusters](../../project/clusters/gitlab_managed_clusters.md)
+- [GitLab Managed Apps](../../clusters/applications.md)
+- [Deploy applications through certificate-based connection](../../project/clusters/deploy_to_cluster.md)
+- [Cluster Management Project](../../clusters/management_project.md)
+- [Cluster integrations](../../clusters/integrations.md)
+- [Cluster cost management](../../clusters/cost_management.md)
+- [Cluster environments](../../clusters/environments.md)
+- [Canary Deployments](../../project/canary_deployments.md)
+- [Serverless](../../project/clusters/serverless/index.md)
+- [Deploy Boards](../../project/deploy_boards.md)
+- [Pod logs](../../project/clusters/kubernetes_pod_logs.md)
+- [Clusters health](manage/clusters_health.md)
+- [Crossplane integration](../../clusters/crossplane.md)
+- [Auto Deploy](../../../topics/autodevops/stages.md#auto-deploy)
+- [Web terminals](../../../administration/integration/terminal.md)
+
+### Cluster levels
+
+The concept of [project-level](../../project/clusters/index.md),
+[group-level](../../group/clusters/index.md), and
+[instance-level](../../instance/clusters/index.md) clusters becomes
+extinct in the new model, although the functionality remains to some extent.
+
+The Agent is always configured in a single GitLab project, but you can use the CI/CD Tunnel to
+[authorize other projects and groups to use the same Agent](../../clusters/agent/repository.md#authorize-projects-and-groups-to-use-an-agent).
+By doing so, you are granting these projects and groups access to the same cluster, which is similar to group-level clusters' use case.
diff --git a/doc/user/infrastructure/clusters/manage/clusters_health.md b/doc/user/infrastructure/clusters/manage/clusters_health.md
index 009945589ad..eeb931f392f 100644
--- a/doc/user/infrastructure/clusters/manage/clusters_health.md
+++ b/doc/user/infrastructure/clusters/manage/clusters_health.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Clusters health **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4701) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/208224) to GitLab Free in 13.2.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4701) in GitLab 10.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/208224) from GitLab Ultimate to GitLab Free in 13.2.
When [the Prometheus cluster integration is enabled](../../../clusters/integrations.md#prometheus-cluster-integration), GitLab monitors the cluster's health. At the top of the cluster settings page, CPU and Memory utilization is displayed, along with the total amount available. Keeping an eye on cluster resources can be important, if the cluster runs out of memory pods may be shutdown or fail to start.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/apparmor.md b/doc/user/infrastructure/clusters/manage/management_project_applications/apparmor.md
index 7fbbbac866c..ae335a180e8 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/apparmor.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/apparmor.md
@@ -4,7 +4,7 @@ group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Install AppArmor with a cluster management project
+# Install AppArmor with a cluster management project **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md b/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md
index 9ef7bd0f3ff..12f99af8d8d 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md
@@ -4,7 +4,7 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Install cert-manager with a cluster management project
+# Install cert-manager with a cluster management project **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
> - Support for cert-manager v1.4 was [introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/69405) in GitLab 14.3.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/cilium.md b/doc/user/infrastructure/clusters/manage/management_project_applications/cilium.md
index c19bfbfb1b1..b5959624954 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/cilium.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/cilium.md
@@ -4,7 +4,7 @@ group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Install Cilium with a cluster management project
+# Install Cilium with a cluster management project **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md b/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md
index dbde9bd90b0..3bd675b7439 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md
@@ -4,7 +4,7 @@ group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Install Elastic Stack with a cluster management project
+# Install Elastic Stack with a cluster management project **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/falco.md b/doc/user/infrastructure/clusters/manage/management_project_applications/falco.md
index 7bd2a4a5133..50401e9a391 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/falco.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/falco.md
@@ -4,7 +4,7 @@ group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Install Falco with a cluster management project
+# Install Falco with a cluster management project **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/fluentd.md b/doc/user/infrastructure/clusters/manage/management_project_applications/fluentd.md
index c5de0511c2f..ea3a3503f9b 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/fluentd.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/fluentd.md
@@ -4,7 +4,7 @@ group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Install Fluentd with a cluster management project
+# Install Fluentd with a cluster management project **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md b/doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md
index 5ee26db754e..503f077df14 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md
@@ -4,7 +4,7 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Install Ingress with a cluster management project
+# Install Ingress with a cluster management project **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md b/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md
index 3420f340c94..fd2eed25997 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md
@@ -4,7 +4,7 @@ group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Install Prometheus with a cluster management project
+# Install Prometheus with a cluster management project **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md b/doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md
index 300350010af..9e5d7860a67 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md
@@ -4,7 +4,7 @@ group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Install Sentry with a cluster management project
+# Install Sentry with a cluster management project **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md b/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md
index d6b4eb5c157..4618a95f986 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md
@@ -1,10 +1,10 @@
---
-stage: Release
-group: Release
+stage: Configure
+group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Install Vault with a cluster management project
+# Install Vault with a cluster management project **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
diff --git a/doc/user/infrastructure/iac/mr_integration.md b/doc/user/infrastructure/iac/mr_integration.md
index 853a39a59a8..e92b2d919ae 100644
--- a/doc/user/infrastructure/iac/mr_integration.md
+++ b/doc/user/infrastructure/iac/mr_integration.md
@@ -16,7 +16,7 @@ enabling you to see statistics about the resources that Terraform creates,
modifies, or destroys.
WARNING:
-Like any other job artifact, Terraform Plan data is [viewable by anyone with Guest access](../../permissions.md) to the repository.
+Like any other job artifact, Terraform Plan data is viewable by anyone with the Guest [role](../../permissions.md) on the repository.
Neither Terraform nor GitLab encrypts the plan file by default. If your Terraform Plan
includes sensitive data such as passwords, access tokens, or certificates, we strongly
recommend encrypting plan output or modifying the project visibility settings.
@@ -77,8 +77,7 @@ To manually configure a GitLab Terraform Report artifact:
terraform: $PLAN_JSON
```
- For a full example using the pre-built image, see [Example `.gitlab-ci.yml`
- file](#example-gitlab-ciyml-file).
+ For a full example using the pre-built image, see [Example `.gitlab-ci.yml` file](#example-gitlab-ciyml-file).
For an example displaying multiple reports, see [`.gitlab-ci.yml` multiple reports file](#multiple-terraform-plan-reports).
diff --git a/doc/user/infrastructure/iac/terraform_state.md b/doc/user/infrastructure/iac/terraform_state.md
index fb051c7fa14..84d1edbe2f7 100644
--- a/doc/user/infrastructure/iac/terraform_state.md
+++ b/doc/user/infrastructure/iac/terraform_state.md
@@ -205,7 +205,7 @@ and the CI YAML file:
The output from the above `terraform` commands should be viewable in the job logs.
WARNING:
-Like any other job artifact, Terraform plan data is [viewable by anyone with Guest access](../../permissions.md) to the repository.
+Like any other job artifact, Terraform plan data is viewable by anyone with the Guest [role](../../permissions.md) on the repository.
Neither Terraform nor GitLab encrypts the plan file by default. If your Terraform plan
includes sensitive data such as passwords, access tokens, or certificates, GitLab strongly
recommends encrypting plan output or modifying the project visibility settings.
diff --git a/doc/user/infrastructure/index.md b/doc/user/infrastructure/index.md
index e99dc691774..3bb518596cc 100644
--- a/doc/user/infrastructure/index.md
+++ b/doc/user/infrastructure/index.md
@@ -29,13 +29,12 @@ Learn more about how GitLab can help you run [Infrastructure as Code](iac/index.
## Integrated Kubernetes management
-GitLab has special integrations with Kubernetes to help you deploy, manage and troubleshoot
-third-party or custom applications in Kubernetes clusters. Auto DevOps provides a full
-DevSecOps pipeline by default targeted at Kubernetes based deployments. To support
-all the GitLab features, GitLab offers a cluster management project for easy onboarding.
-The deploy boards provide quick insights into your cluster, including pod logs tailing.
+The GitLab integration with Kubernetes helps you to install, configure, manage, deploy, and troubleshoot
+cluster applications. With the GitLab Kubernetes Agent, you can connect clusters behind a firewall,
+have real-time access to API endpoints, perform pull-based or push-based deployments for production
+and non-production environments, and much more.
-Learn more about the [GitLab integration with Kubernetes](clusters/index.md).
+Learn more about the [GitLab Kubernetes Agent](../clusters/agent/index.md).
## Runbooks in GitLab
diff --git a/doc/user/instance/clusters/index.md b/doc/user/instance/clusters/index.md
index de09cd4845e..4bbd82d01a8 100644
--- a/doc/user/instance/clusters/index.md
+++ b/doc/user/instance/clusters/index.md
@@ -4,9 +4,14 @@ group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Instance-level Kubernetes clusters **(FREE SELF)**
+# Instance-level Kubernetes clusters (certificate-based) (DEPRECATED) **(FREE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39840) in GitLab 11.11.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/39840) in GitLab 11.11.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. To connect clusters to GitLab,
+use the [GitLab Kubernetes Agent](../../clusters/agent/index.md).
Similar to [project-level](../../project/clusters/index.md)
and [group-level](../../group/clusters/index.md) Kubernetes clusters,
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index 5e600b6e0d1..d20e9c7a30e 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -125,8 +125,6 @@ You can also use [Kroki](https://kroki.io) to create a wide variety of diagrams.
#### Mermaid
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15107) in GitLab 10.3.
-
Visit the [official page](https://mermaidjs.github.io/) for more details. The
[Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/) helps you
learn Mermaid and debug issues in your Mermaid code. Use it to identify and resolve
@@ -211,20 +209,20 @@ Sometimes you want to :monkey: around a bit and add some :star2: to your :speech
You can use it to point out a :bug: or warn about :speak_no_evil: patches. And if someone improves your really :snail: code, send them some :birthday:. People :heart: you for that.
-If you're new to this, don't be :fearful:. You can join the emoji :family:. All you need to do is to look up one of the supported codes.
+If you're new to this, don't be :fearful:. You can join the emoji :family:. Just look up one of the supported codes.
Consult the [Emoji Cheat Sheet](https://www.emojicopy.com) for a list of all supported emoji codes. :thumbsup:
```
-Sometimes you want to <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/monkey.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> around a bit and add some <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/star2.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> to your <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/speech_balloon.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">. Well we have a gift for you:
+Sometimes you want to <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/monkey.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> around a bit and add some <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/star2.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> to your <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/speech_balloon.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">. Well we have a gift for you:
-<img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/zap.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">You can use emoji anywhere GitLab Flavored Markdown is supported. <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/v.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">
+<img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/zap.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">You can use emoji anywhere GitLab Flavored Markdown is supported. <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/v.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">
-You can use it to point out a<img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/bug.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> or warn about <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/speak_no_evil.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> patches. If someone improves your really <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/snail.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> code, send them some <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/birthday.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">. People <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/heart.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> you for that.
+You can use it to point out a<img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/bug.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> or warn about <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/speak_no_evil.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> patches. If someone improves your really <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/snail.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> code, send them some <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/birthday.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">. People <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/heart.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> you for that.
-If you're new to this, don't be <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/fearful.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">. You can join the emoji <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/family.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">. All you need to do is to look up one of the supported codes.
+If you're new to this, don't be <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/fearful.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">. You can join the emoji <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/family.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">. Just look up one of the supported codes.
-Consult the [Emoji Cheat Sheet](https://www.webfx.com/tools/emoji-cheat-sheet/) for a list of all supported emoji codes. <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/thumbsup.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">
+Consult the [Emoji Cheat Sheet](https://www.webfx.com/tools/emoji-cheat-sheet/) for a list of all supported emoji codes. <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/public/-/emojis/2/thumbsup.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">
#### Emojis and your operating system
@@ -236,7 +234,7 @@ emojis where there is no support.
<!-- vale gitlab.Spelling = NO -->
-On Linux, you can download [Noto Color Emoji](https://www.google.com/get/noto/help/emoji/)
+On Linux, you can download [Noto Color Emoji](https://github.com/googlefonts/noto-emoji)
to get full native emoji support. Ubuntu 18.04 (like many modern Linux distributions) has
this font installed by default.
@@ -244,8 +242,6 @@ this font installed by default.
### Front matter
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23331) in GitLab 11.6.
-
Front matter is metadata included at the beginning of a Markdown document, preceding
the content. This data can be used by static site generators like [Jekyll](https://jekyllrb.com/docs/front-matter/),
[Hugo](https://gohugo.io/content-management/front-matter/), and many other applications.
@@ -356,18 +352,18 @@ in a [code block](#code-spans-and-blocks) with the language declared as `math` i
on a separate line:
````markdown
-This math is inline $`a^2+b^2=c^2`$.
+This math is inline: $`a^2+b^2=c^2`$.
-This is on a separate line:
+This math is on a separate line:
```math
a^2+b^2=c^2
```
````
-This math is inline $`a^2+b^2=c^2`$.
+This math is inline: $`a^2+b^2=c^2`$.
-This is on a separate line
+This math is on a separate line:
```math
a^2+b^2=c^2
@@ -408,16 +404,17 @@ To create a task list, follow the format of an ordered or unordered list:
### Table of contents
A table of contents is an unordered list that links to subheadings in the document.
-
-To add a table of contents to a Markdown file, wiki page, issue request, or merge request
-description, add either the `[[_TOC_]]` or `[TOC]` tag on its own line.
-
-NOTE:
You can add a table of contents to issues and merge requests, but you can't add one
-to notes or comments.
+to notes or comments. Add either the `[[_TOC_]]` or `[TOC]` tag on its own line
+to the **Description** field of any of the supported content types:
+
+- Markdown files.
+- Wiki pages.
+- Issues.
+- Merge requests.
```markdown
-This is an intro sentence to my Wiki page.
+This sentence introduces my wiki page.
[[_TOC_]]
@@ -579,7 +576,7 @@ by starting the lines of the blockquote with `>`:
Quote break.
-> This is a very long line that is still quoted properly when it wraps. Keep writing to make sure this line is long enough to actually wrap for everyone. You can also *add* **Markdown** into a blockquote.
+> This very long line is still quoted properly when it wraps. Keep writing to make sure this line is long enough to actually wrap for everyone. You can also *add* **Markdown** into a blockquote.
```
> Blockquotes help you emulate reply text.
@@ -587,7 +584,7 @@ Quote break.
Quote break.
-> This is a very long line that is still quoted properly when it wraps. Keep writing to make sure this line is long enough to actually wrap for everyone. You can also *add* **Markdown** into a blockquote.
+> This very long line is still quoted properly when it wraps. Keep writing to make sure this line is long enough to actually wrap for everyone. You can also *add* **Markdown** into a blockquote.
#### Multiline blockquote
@@ -706,7 +703,7 @@ puts markdown.to_html
```
No language indicated, so no syntax highlighting.
-s = "There is no highlighting for this."
+s = "No highlighting is shown for this line."
But let's throw in a <b>tag</b>.
```
````
@@ -733,13 +730,13 @@ puts markdown.to_html
```plaintext
No language indicated, so no syntax highlighting.
-s = "There is no highlighting for this."
+s = "No highlighting is shown for this line."
But let's throw in a <b>tag</b>.
```
### Emphasis
-There are multiple ways to emphasize text in Markdown. You can italicize, bold, strikethrough,
+In Markdown, you can emphasize text in multiple ways. You can italicize, bold, strikethrough,
and combine these emphasis styles together.
Strikethrough is not part of the core Markdown standard, but is part of GitLab Flavored Markdown.
@@ -811,10 +808,6 @@ the note content.
Regardless of the tag names, the relative order of the reference tags determines the rendered
numbering.
-Reference tags can use letters and other characters. Avoid using lowercase `w` or an underscore
-(`_`) in footnote tag names until [this bug](https://gitlab.com/gitlab-org/gitlab/-/issues/24423) is
-resolved.
-
<!--
Do not edit the following codeblock. It uses HTML to skip the Vale ReferenceLinks test.
-->
@@ -823,9 +816,9 @@ Do not edit the following codeblock. It uses HTML to skip the Vale ReferenceLink
This reference tag is a mix of letters and numbers. [^footnote-42]
-&#91;^1]: This is the text inside a footnote.
+&#91;^1]: This text is inside a footnote.
-&#91;^footnote-42]: This is another footnote.
+&#91;^footnote-42]: This text is another footnote.
</code></pre>
A footnote reference tag looks like this:[^1]
@@ -837,9 +830,9 @@ Do not delete the single space before the [^1] and [^footnotes] references below
These are used to force the Vale ReferenceLinks check to skip these examples.
-->
- [^1]: This is the text inside a footnote.
+ [^1]: This text is inside a footnote.
- [^footnote-42]: This is another footnote.
+ [^footnote-42]: This text is another footnote.
### Headers
@@ -897,8 +890,8 @@ Would generate the following link IDs:
1. `this-header-has-spaces-in-it-2`
1. `this-header-has-3-5-in-it-and-parentheses`
-Note that the emoji processing happens before the header IDs are generated, so the
-emoji is converted to an image which is then removed from the ID.
+Emoji processing happens before the header IDs are generated. The
+emoji is converted to an image, which is then removed from the ID.
### Horizontal Rule
@@ -938,7 +931,7 @@ Reference-style (hover to see title text):
</code></pre>
<!--
-DO NOT change the name of markdown_logo.png. This is used for a test in
+DO NOT change the name of markdown_logo.png. This file is used for a test in
spec/controllers/help_controller_spec.rb.
-->
@@ -955,7 +948,7 @@ Do not change to a reference style link.
![alt text](img/markdown_logo.png "Title Text")
-In the rare case where you need to set a specific height or width for an image,
+In the rare case where you must set a specific height or width for an image,
you can use the `img` HTML tag instead of Markdown and set its `height` and
`width` parameters.
@@ -1133,8 +1126,8 @@ These details <em>remain</em> <b>hidden</b> until expanded.
### Line breaks
A line break is inserted (a new paragraph starts) if the previous text is
-ended with two newlines, like when you hit <kbd>Enter</kbd> twice in a row. If you only
-use one newline (hit <kbd>Enter</kbd> once), the next sentence remains part of the
+ended with two newlines, like when you press <kbd>Enter</kbd> twice in a row. If you only
+use one newline (select <kbd>Enter</kbd> once), the next sentence remains part of the
same paragraph. Use this approach if you want to keep long lines from wrapping, and keep
them editable:
@@ -1160,7 +1153,8 @@ in the *same paragraph*.
#### Newlines
-GitLab Flavored Markdown adheres to the Markdown specification in how [paragraphs and line breaks are handled](https://spec.commonmark.org/current/).
+GitLab Flavored Markdown adheres to the Markdown specification for handling
+[paragraphs and line breaks](https://spec.commonmark.org/current/).
A paragraph is one or more consecutive lines of text, separated by one or
more blank lines (two newlines at the end of the first paragraph), as [explained above](#line-breaks).
@@ -1182,25 +1176,25 @@ A new line due to the previous backslash.
### Links
-There are two ways to create links, inline-style and reference-style:
+You can create links two ways: inline-style and reference-style. For example:
<!--
Do not edit the following codeblock. It uses HTML to skip the Vale ReferenceLinks test.
-->
-<pre class="highlight"><code>- This is an [inline-style link](https://www.google.com)
-- This is a [link to a repository file in the same directory](index.md)
-- This is a [relative link to a readme one directory higher](../index.md)
-- This is a [link that also has title text](https://www.google.com "This link takes you to Google!")
+<pre class="highlight"><code>- This line shows an [inline-style link](https://www.google.com)
+- This line shows a [link to a repository file in the same directory](index.md)
+- This line shows a [relative link to a readme one directory higher](../index.md)
+- This line shows a [link that also has title text](https://www.google.com "This link takes you to Google!")
Using header ID anchors:
-- This links to [a section on a different Markdown page, using a "#" and the header ID](index.md#overview)
-- This links to [a different section on the same page, using a "#" and the header ID](#header-ids-and-links)
+- This line links to [a section on a different Markdown page, using a "#" and the header ID](index.md#overview)
+- This line links to [a different section on the same page, using a "#" and the header ID](#header-ids-and-links)
Using references:
-- This is a [reference-style link, see below][Arbitrary case-insensitive reference text]
+- This line shows a [reference-style link, see below][Arbitrary case-insensitive reference text]
- You can [use numbers for reference-style link definitions, see below][1]
- Or leave it empty and use the [link text itself][], see below.
@@ -1211,15 +1205,15 @@ Some text to show that the reference links can follow later.
&#91;link text itself]: https://www.reddit.com
</code></pre>
-- This is an [inline-style link](https://www.google.com)
-- This is a [link to a repository file in the same directory](index.md)
-- This is a [relative link to a README one directory higher](../index.md)
-- This is a [link that also has title text](https://www.google.com "This link takes you to Google!")
+- This line shows an [inline-style link](https://www.google.com)
+- This line shows a [link to a repository file in the same directory](index.md)
+- This line shows a [relative link to a README one directory higher](../index.md)
+- This line shows a [link that also has title text](https://www.google.com "This link takes you to Google!")
Using header ID anchors:
-- This links to [a section on a different Markdown page, using a "#" and the header ID](index.md#overview)
-- This links to [a different section on the same page, using a "#" and the header ID](#header-ids-and-links)
+- This line links to [a section on a different Markdown page, using a "#" and the header ID](index.md#overview)
+- This line links to [a different section on the same page, using a "#" and the header ID](#header-ids-and-links)
Using references:
@@ -1228,7 +1222,7 @@ The example below uses in-line links to pass the Vale ReferenceLinks test.
Do not change to reference style links.
-->
-- This is a [reference-style link, see below](https://www.mozilla.org/en-US/)
+- This line is a [reference-style link, see below](https://www.mozilla.org/en-US/)
- You can [use numbers for reference-style link definitions, see below](https://slashdot.org)
- Or leave it empty and use the [link text itself](https://www.reddit.com), see below.
@@ -1236,7 +1230,7 @@ Some text to show that the reference links can follow later.
NOTE:
Relative links do not allow the referencing of project files in a wiki
-page, or a wiki page in a project file. The reason for this is that a wiki is always
+page, or a wiki page in a project file. The reason: a wiki is always
in a separate Git repository in GitLab. For example, `[I'm a reference-style link](style)`
points the link to `wikis/style` only when the link is inside of a wiki Markdown file.
@@ -1265,14 +1259,14 @@ GitLab Flavored Markdown auto-links almost any URL you put into your text:
<!-- vale gitlab.Spelling = YES -->
### Lists
-Ordered and unordered lists can be created.
+You can create ordered and unordered lists.
For an ordered list, add the number you want the list
to start with, like `1.`, followed by a space, at the start of each line for ordered lists.
-After the first number, it does not matter what number you use, ordered lists are
+After the first number, it does not matter what number you use. Ordered lists are
numbered automatically by vertical order, so repeating `1.` for all items in the
same list is common. If you start with a number other than `1.`, it uses that as the first
-number, and count up from there.
+number, and counts up from there.
Examples:
@@ -1364,10 +1358,9 @@ Example:
---
-If the paragraph of the first item is not indented with the proper number of spaces,
+If the first item's paragraph isn't indented with the proper number of spaces,
the paragraph appears outside the list, instead of properly indented under the list item.
-
-Example:
+For example:
```markdown
1. First ordered list item
@@ -1459,13 +1452,13 @@ use `<br>` tags to force a cell to have multiple lines:
```markdown
| Name | Details |
| --- | --- |
-| Item1 | This is on one line |
+| Item1 | This text is on one line |
| Item2 | This item has:<br>- Multiple items<br>- That we want listed separately |
```
| Name | Details |
| --- | --- |
-| Item1 | This is on one line |
+| Item1 | This text is on one line |
| Item2 | This item has:<br>- Multiple items<br>- That we want listed separately |
You can use HTML formatting in GitLab itself to add [task lists](#task-lists) with checkboxes,
diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md
index 6e3af45df17..7861258e23f 100644
--- a/doc/user/packages/composer_repository/index.md
+++ b/doc/user/packages/composer_repository/index.md
@@ -6,9 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Composer packages in the Package Registry **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15886) in GitLab Premium 13.2.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
-> - Support for Composer 2.0 [added](https://gitlab.com/gitlab-org/gitlab/-/issues/259840) in GitLab Free 13.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15886) in GitLab 13.2.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
+> - Support for Composer 2.0 [added](https://gitlab.com/gitlab-org/gitlab/-/issues/259840) in GitLab 13.10.
WARNING:
The Composer package registry for GitLab is under development and isn't ready for production use due to
@@ -149,7 +149,7 @@ Do not save unless you want to overwrite the existing CI/CD file.
When you publish:
- The same package with different data, it overwrites the existing package.
-- The same package with the same data, a `404 Bad request` error occurs.
+- The same package with the same data, a `400 Bad request` error occurs.
## Install a Composer package
diff --git a/doc/user/packages/conan_repository/index.md b/doc/user/packages/conan_repository/index.md
index 33c48478921..0f32f68d250 100644
--- a/doc/user/packages/conan_repository/index.md
+++ b/doc/user/packages/conan_repository/index.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Conan packages in the Package Registry **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8248) in GitLab Premium 12.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8248) in GitLab 12.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
WARNING:
The Conan package registry for GitLab is under development and isn't ready for production use due to
@@ -265,7 +265,8 @@ conan upload Hello/0.1@mycompany/beta --all
## Publish a Conan package by using CI/CD
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11678) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11678) in GitLab 12.7.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
To work with Conan commands in [GitLab CI/CD](../../../ci/index.md), you can
use `CI_JOB_TOKEN` in place of the personal access token in your commands.
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index c39552c1edb..c9cdc8643f4 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -157,7 +157,7 @@ To use CI/CD to authenticate, you can use:
- A [CI job token](../../../ci/jobs/ci_job_token.md).
```shell
- docker login -u $CI_JOB_USER -p $CI_JOB_TOKEN $CI_REGISTRY
+ docker login -u $CI_REGISTRY_USER -p $CI_JOB_TOKEN $CI_REGISTRY
```
- A [deploy token](../../project/deploy_tokens/index.md#gitlab-deploy-token) with the minimum scope of:
@@ -309,7 +309,7 @@ in addition to the steps in the
[Docker-in-Docker](../../../ci/docker/using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker) section:
1. Update the `image` and `service` to point to your registry.
-1. Add a service [alias](../../../ci/yaml/index.md#servicesalias).
+1. Add a service [alias](../../../ci/services/index.md#available-settings-for-services).
Below is an example of what your `.gitlab-ci.yml` should look like:
@@ -339,7 +339,7 @@ in addition to the steps in the
[Docker-in-Docker](../../../ci/docker/using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker) section:
1. Update the `image` and `service` to point to your registry.
-1. Add a service [alias](../../../ci/yaml/index.md#servicesalias).
+1. Add a service [alias](../../../ci/services/index.md#available-settings-for-services).
Below is an example of what your `.gitlab-ci.yml` should look like:
diff --git a/doc/user/packages/debian_repository/index.md b/doc/user/packages/debian_repository/index.md
index 36d85d94161..89427174dcd 100644
--- a/doc/user/packages/debian_repository/index.md
+++ b/doc/user/packages/debian_repository/index.md
@@ -79,10 +79,10 @@ packages on the group level, create a distribution with the same `codename`.
To create a project-level distribution:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/debian_distributions?codename=unstable"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/debian_distributions?codename=<codename>"
```
-Example response:
+Example response with `codename=unstable`:
```json
{
@@ -146,10 +146,23 @@ To install a package:
| sudo tee /etc/apt/auth.conf.d/gitlab_project.conf
```
+ Download your distribution key:
+
+ ```shell
+ sudo mkdir -p /usr/local/share/keyrings
+ curl --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/<project_id>/debian_distributions/<codename>/key.asc" \
+ | \
+ gpg --dearmor \
+ | \
+ sudo tee /usr/local/share/keyrings/<codename>-archive-keyring.gpg \
+ > /dev/null
+ ```
+
Add your project as a source:
```shell
- echo 'deb [trusted=yes] https://gitlab.example.com/api/v4/projects/<project_id>/packages/debian <codename> <component1> <component2>' \
+ echo 'deb [ signed-by=/usr/local/share/keyrings/<codename>-archive-keyring.gpg ] https://gitlab.example.com/api/v4/projects/<project_id>/packages/debian <codename> <component1> <component2>' \
| sudo tee /etc/apt/sources.list.d/gitlab_project.list
sudo apt-get update
```
diff --git a/doc/user/packages/dependency_proxy/index.md b/doc/user/packages/dependency_proxy/index.md
index 5d482a15460..fbd1cb84580 100644
--- a/doc/user/packages/dependency_proxy/index.md
+++ b/doc/user/packages/dependency_proxy/index.md
@@ -6,11 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Dependency Proxy **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.11.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/273655) to GitLab Free in GitLab 13.6.
-> - [Support for private groups](https://gitlab.com/gitlab-org/gitlab/-/issues/11582) in GitLab Free 13.7.
-> - Anonymous access to images in public groups is no longer available starting in GitLab Free 13.7.
-> - [Support for pull-by-digest and Docker version 20.x](https://gitlab.com/gitlab-org/gitlab/-/issues/290944) in GitLab Free 13.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7934) in GitLab 11.11.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/273655) from GitLab Premium to GitLab Free in 13.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11582) support for private groups in GitLab 13.7.
+> - Anonymous access to images in public groups is no longer available starting in GitLab 13.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/290944) support for pull-by-digest and Docker version 20.x in GitLab 13.10.
The GitLab Dependency Proxy is a local proxy you can use for your frequently-accessed
upstream images.
@@ -59,7 +59,7 @@ Prerequisites:
### Authenticate with the Dependency Proxy
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11582) in GitLab Free 13.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11582) in GitLab 13.7.
> - It's [deployed behind a feature flag](../../feature_flags.md), enabled by default.
> - It's enabled on GitLab.com.
> - It's recommended for production use.
@@ -98,7 +98,7 @@ Proxy.
#### Authenticate within CI/CD
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/280582) in GitLab 13.7.
-> - Automatic runner authentication [added](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27302) in GitLab 13.9.
+> - Automatic runner authentication, when using the Dependency Proxy to pull the image for the job, was [added](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27302) in GitLab 13.9.
> - The prefix for group names containing uppercase letters was [fixed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54559) in GitLab 13.10.
Runners log in to the Dependency Proxy automatically. To pull through
@@ -134,6 +134,32 @@ Proxy manually without including the port:
docker pull gitlab.example.com:443/my-group/dependency_proxy/containers/alpine:latest
```
+Example when using the Dependency Proxy to build an image:
+
+```plaintext
+# Dockerfile
+FROM gitlab.example.com:443/my-group/dependency_proxy/containers/alpine:latest
+```
+
+```yaml
+# .gitlab-ci.yml
+image: docker:19.03.12
+
+variables:
+ DOCKER_HOST: tcp://docker:2375
+ DOCKER_TLS_CERTDIR: ""
+
+services:
+ - docker:19.03.12-dind
+
+build:
+ image: docker:19.03.12
+ before_script:
+ - docker login -u $CI_DEPENDENCY_PROXY_USER -p $CI_DEPENDENCY_PROXY_PASSWORD $CI_DEPENDENCY_PROXY_SERVER
+ script:
+ - docker build -t test .
+```
+
You can also use [custom CI/CD variables](../../../ci/variables/index.md#custom-cicd-variables) to store and access your personal access token or deploy token.
### Store a Docker image in Dependency Proxy cache
@@ -189,7 +215,7 @@ If you clear the cache, the next time a pipeline runs it must pull an image or t
### Cleanup policies
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294187) in GitLab Free 14.4.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294187) in GitLab 14.4.
The cleanup policy is a scheduled job you can use to clear cached images that are no longer used,
freeing up additional storage space. The policies use time-to-live (TTL) logic:
@@ -229,7 +255,7 @@ files are ignored and new files are downloaded and cached from the external regi
## Docker Hub rate limits and the Dependency Proxy
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241639) in GitLab Free 13.7.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241639) in GitLab 13.7.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
Watch how to [use the Dependency Proxy to help avoid Docker Hub rate limits](https://youtu.be/Nc4nUo7Pq08).
diff --git a/doc/user/packages/generic_packages/index.md b/doc/user/packages/generic_packages/index.md
index 6d35273ae6f..5b7316a495e 100644
--- a/doc/user/packages/generic_packages/index.md
+++ b/doc/user/packages/generic_packages/index.md
@@ -35,7 +35,10 @@ When you publish a package file, if the package does not exist, it is created.
Prerequisites:
-- You need to [authenticate with the API](../../../api/index.md#authentication). If authenticating with a deploy token, it must be configured with the `write_package_registry` scope.
+- You must [authenticate with the API](../../../api/index.md#authentication).
+ If authenticating with a deploy token, it must be configured with the `write_package_registry`
+ scope. If authenticating with a personal access token or project access token, it must be
+ configured with the `api` scope.
```plaintext
PUT /projects/:id/packages/generic/:package_name/:package_version/:file_name?status=:status
@@ -48,6 +51,7 @@ PUT /projects/:id/packages/generic/:package_name/:package_version/:file_name?sta
| `package_version` | string | yes | The package version. The following regex validates this: `\A(\.?[\w\+-]+\.?)+\z`. You can test your version strings on [Rubular](https://rubular.com/r/aNCV0wG5K14uq8).
| `file_name` | string | yes | The filename. It can contain only lowercase letters (`a-z`), uppercase letter (`A-Z`), numbers (`0-9`), dots (`.`), hyphens (`-`), or underscores (`_`).
| `status` | string | no | The package status. It can be `default` (default) or `hidden`. Hidden packages do not appear in the UI or [package API list endpoints](../../../api/packages.md).
+| `select` | string | no | The response payload. By default, the response is empty. Valid values are: `package_file`. `package_file` returns details of the package file record created by this request.
Provide the file context in the request body.
@@ -59,7 +63,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" \
"https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt?status=hidden"
```
-Example response:
+Example response without attribute `select`:
```json
{
@@ -67,6 +71,34 @@ Example response:
}
```
+Example response with attribute `select = package_file`:
+
+```json
+{
+ "id": 1,
+ "package_id": 1,
+ "created_at": "2021-10-12T12:05:23.387Z",
+ "updated_at": "2021-10-12T12:05:23.387Z",
+ "size": 0,
+ "file_store": 1,
+ "file_md5": null,
+ "file_sha1": null,
+ "file_name": "file.txt",
+ "file": {
+ "url": "/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b/packages/26/files/36/file.txt"
+ },
+ "file_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "verification_retry_at": null,
+ "verified_at": null,
+ "verification_failure": null,
+ "verification_retry_count": null,
+ "verification_checksum": null,
+ "verification_state": 0,
+ "verification_started_at": null,
+ "new_file_path": null
+}
+```
+
### Publishing a package with the same name or version
When you publish a package with the same name and version as an existing package, the new package
@@ -76,7 +108,7 @@ API or the UI.
#### Do not allow duplicate Generic packages
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/293755) in GitLab Free 13.12.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/293755) in GitLab 13.12.
To prevent users from publishing duplicate generic packages, you can use the [GraphQl API](../../../api/graphql/reference/index.md#packagesettings)
or the UI.
diff --git a/doc/user/packages/go_proxy/index.md b/doc/user/packages/go_proxy/index.md
index f17910cd46d..1cf3132489a 100644
--- a/doc/user/packages/go_proxy/index.md
+++ b/doc/user/packages/go_proxy/index.md
@@ -6,11 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Go proxy for GitLab **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27376) in GitLab Premium 13.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27376) in GitLab 13.1.
> - It's deployed behind a feature flag, disabled by default.
> - It's disabled for GitLab.com.
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-the-go-proxy).
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
WARNING:
The Go package registry for GitLab is under development and isn't ready for production use due to
diff --git a/doc/user/packages/index.md b/doc/user/packages/index.md
index a8f1b1998ae..86cfa8986bb 100644
--- a/doc/user/packages/index.md
+++ b/doc/user/packages/index.md
@@ -10,56 +10,6 @@ The GitLab [Package Registry](package_registry/index.md) acts as a private or pu
for a variety of common package managers. You can publish and share
packages, which can be easily consumed as a dependency in downstream projects.
-WARNING:
-Not all package manager formats are ready for production use. To view each format's status, see the
-table's **Status** column.
-
-The Package Registry supports the following formats:
-
-| Package type | GitLab version | Status |
-| ------------ | -------------- |------- |
-| [Maven](maven_repository/index.md) | 11.3+ | Stable |
-| [npm](npm_registry/index.md) | 11.7+ | Stable |
-| [NuGet](nuget_repository/index.md) | 12.8+ | Stable |
-| [PyPI](pypi_repository/index.md) | 12.10+ | Stable |
-| [Generic packages](generic_packages/index.md) | 13.5+ | Stable |
-| [Composer](composer_repository/index.md) | 13.2+ | [Beta](https://gitlab.com/groups/gitlab-org/-/epics/6817) |
-| [Conan](conan_repository/index.md) | 12.6+ | [Beta](https://gitlab.com/groups/gitlab-org/-/epics/6816) |
-| [Helm](helm_repository/index.md) | 14.1+ | [Beta](https://gitlab.com/groups/gitlab-org/-/epics/6366) |
-| [Debian](debian_repository/index.md) | 14.2+ | [Alpha](https://gitlab.com/groups/gitlab-org/-/epics/6057) |
-| [Go](go_proxy/index.md) | 13.1+ | [Alpha](https://gitlab.com/groups/gitlab-org/-/epics/3043) |
-| [Ruby gems](rubygems_registry/index.md) | 13.10+ | [Alpha](https://gitlab.com/groups/gitlab-org/-/epics/3200) |
-
-Status:
-
-- Alpha: behind a feature flag and not officially supported.
-- Beta: several known issues that may prevent expected use.
-- Stable: ready for production use.
-
-You can also use the [API](../../api/packages.md) to administer the Package Registry.
-
-## Accepting contributions
-
-The below table lists formats that are not supported, but are accepting Community contributions for. Consider contributing to GitLab. This [development documentation](../../development/packages.md)
-guides you through the process.
-
-<!-- vale gitlab.Spelling = NO -->
-
-| Format | Status |
-| ------ | ------ |
-| Chef | [#36889](https://gitlab.com/gitlab-org/gitlab/-/issues/36889) |
-| CocoaPods | [#36890](https://gitlab.com/gitlab-org/gitlab/-/issues/36890) |
-| Conda | [#36891](https://gitlab.com/gitlab-org/gitlab/-/issues/36891) |
-| CRAN | [#36892](https://gitlab.com/gitlab-org/gitlab/-/issues/36892) |
-| Opkg | [#36894](https://gitlab.com/gitlab-org/gitlab/-/issues/36894) |
-| P2 | [#36895](https://gitlab.com/gitlab-org/gitlab/-/issues/36895) |
-| Puppet | [#36897](https://gitlab.com/gitlab-org/gitlab/-/issues/36897) |
-| RPM | [#5932](https://gitlab.com/groups/gitlab-org/-/epics/5128) |
-| SBT | [#36898](https://gitlab.com/gitlab-org/gitlab/-/issues/36898) |
-| Swift | [#12233](https://gitlab.com/gitlab-org/gitlab/-/issues/12233) |
-| Vagrant | [#36899](https://gitlab.com/gitlab-org/gitlab/-/issues/36899) |
-
-<!-- vale gitlab.Spelling = YES -->
## Container Registry
The GitLab [Container Registry](container_registry/index.md) is a secure and private registry for container images. It's built on open source software and completely integrated within GitLab. Use GitLab CI/CD to create and publish images. Use the GitLab [API](../../api/container_registry.md) to manage the registry across groups and projects.
diff --git a/doc/user/packages/infrastructure_registry/index.md b/doc/user/packages/infrastructure_registry/index.md
index 86b85d0c9f5..47f563fd7e7 100644
--- a/doc/user/packages/infrastructure_registry/index.md
+++ b/doc/user/packages/infrastructure_registry/index.md
@@ -82,7 +82,7 @@ The Infrastructure Registry is automatically enabled.
For self-managed instances, a GitLab administrator can
[disable](../../../administration/packages/index.md) **Packages & Registries**,
-which removes this menu item from the sidebar. **(FREE SELF)**
+which removes this menu item from the sidebar.
You can also remove the Infrastructure Registry for a specific project:
diff --git a/doc/user/packages/maven_repository/index.md b/doc/user/packages/maven_repository/index.md
index 17571047353..1ca4bb2759d 100644
--- a/doc/user/packages/maven_repository/index.md
+++ b/doc/user/packages/maven_repository/index.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Maven packages in the Package Repository **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5811) in GitLab Premium 11.3.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5811) in GitLab 11.3.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
Publish [Maven](https://maven.apache.org) artifacts in your project's Package Registry.
Then, install the packages whenever you need to use them as a dependency.
@@ -222,8 +222,8 @@ The `name` must be `Private-Token`.
### Authenticate with a deploy token in Maven
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) deploy token authentication in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) deploy token authentication in GitLab 13.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
To use a deploy token, add this section to your
[`settings.xml`](https://maven.apache.org/settings.html) file.
@@ -418,8 +418,8 @@ repositories {
### Group-level Maven endpoint
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8798) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8798) in GitLab 11.7.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
If you rely on many packages, it might be inefficient to include the `repository` section
with a unique URL for each package. Instead, you can use the group-level endpoint for
@@ -476,8 +476,8 @@ repositories {
### Instance-level Maven endpoint
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8274) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8274) in GitLab 11.7.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
If you rely on many packages, it might be inefficient to include the `repository` section
with a unique URL for each package. Instead, you can use the instance-level endpoint for
@@ -619,7 +619,7 @@ To delete these older package versions, consider using the Packages API or the U
#### Do not allow duplicate Maven packages
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/296895) in GitLab Free 13.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/296895) in GitLab 13.9.
To prevent users from publishing duplicate Maven packages, you can use the [GraphQl API](../../../api/graphql/reference/index.md#packagesettings) or the UI.
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
index b07ae72e273..03209da7ac8 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# npm packages in the Package Registry **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5934) in GitLab Premium 11.7.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5934) in GitLab 11.7.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
Publish npm packages in your project's Package Registry. Then install the
packages whenever you need to use them as a dependency.
@@ -164,8 +164,8 @@ If you encounter an error with [Yarn](https://classic.yarnpkg.com/en/), view
### Authenticate with a CI job token
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9104) in GitLab Premium 12.5.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9104) in GitLab 12.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
If you're using npm with GitLab CI/CD, a CI job token can be used instead of a personal access token or deploy token.
The token inherits the permissions of the user that generates the pipeline.
@@ -208,6 +208,15 @@ Then, you can run `npm publish` either locally or by using GitLab CI/CD.
- **GitLab CI/CD:** Set an `NPM_TOKEN` [CI/CD variable](../../../ci/variables/index.md)
under your project's **Settings > CI/CD > Variables**.
+## Working with private registries
+
+When working with private repositories, you may want to configure additional settings to ensure a secure communication channel:
+
+```shell
+# Force npm to always require authentication when accessing the registry, even for GET requests.
+npm config set always-auth true
+```
+
## Package naming convention
When you use the [instance-level endpoint](#use-the-gitlab-endpoint-for-npm-packages), only the packages with names in the format of `@scope/package-name` are available.
@@ -363,6 +372,10 @@ This rule has a different impact depending on the package name:
This aligns with npmjs.org's behavior. However, npmjs.org does not ever let you publish
the same version more than once, even if it has been deleted.
+## `package.json` limitations
+
+You can't publish a package if its `package.json` file exceeds 20,000 characters.
+
## Install a package
npm packages are commonly-installed by using the `npm` or `yarn` commands
@@ -427,27 +440,34 @@ and use your organization's URL. The name is case-sensitive and must match the n
//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken= "<your_token>"
```
-### npm dependencies metadata
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11867) in GitLab Premium 12.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
-
-In GitLab 12.6 and later, packages published to the Package Registry expose the following attributes to the npm client:
-
-- name
-- version
-- dist-tags
-- dependencies
- - dependencies
- - devDependencies
- - bundleDependencies
- - peerDependencies
- - deprecated
+### npm metadata
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11867) in GitLab 12.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
+> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/330929) in GitLab 14.5.
+
+The GitLab Package Registry exposes the following attributes to the npm client.
+These are similar to the [abbreviated metadata format](https://github.com/npm/registry/blob/9e368cf6aaca608da5b2c378c0d53f475298b916/docs/responses/package-metadata.md#abbreviated-metadata-format):
+
+- `name`
+- `versions`
+ - `name`
+ - `version`
+ - `deprecated`
+ - `dependencies`
+ - `devDependencies`
+ - `bundleDependencies`
+ - `peerDependencies`
+ - `bin`
+ - `directories`
+ - `dist`
+ - `engines`
+ - `_hasShrinkwrap`
## Add npm distribution tags
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9425) in GitLab Premium 12.8.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9425) in GitLab 12.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
You can add [distribution tags](https://docs.npmjs.com/cli/dist-tag/) to newly-published packages.
Tags are optional and can be assigned to only one package at a time.
@@ -549,6 +569,8 @@ NPM_TOKEN=<your_token> npm install
If you get this error, ensure that:
+- The Package Registry is enabled in your project settings. Although the Package Registry is enabled
+ by default, it's possible to [disable it](../package_registry/#disable-the-package-registry).
- Your token is not expired and has appropriate permissions.
- A package with the same name or version doesn't already exist within the given scope.
- Your NPM package name does not contain a dot `.`. This is a [known issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/10248)
@@ -577,6 +599,10 @@ root namespace and therefore cannot be published again using the same name.
This is also true even if the prior published package shares the same name,
but not the version.
+#### Package JSON file is too large
+
+Make sure that your `package.json` file does not [exceed `20,000` characters](#packagejson-limitations).
+
### `npm publish` returns `npm ERR! 500 Internal Server Error - PUT`
This is a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/238950) in GitLab
diff --git a/doc/user/packages/nuget_repository/index.md b/doc/user/packages/nuget_repository/index.md
index 2af6dc60078..98cccd72425 100644
--- a/doc/user/packages/nuget_repository/index.md
+++ b/doc/user/packages/nuget_repository/index.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# NuGet packages in the Package Registry **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20050) in GitLab Premium 12.8.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20050) in GitLab 12.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
> - Symbol package support [added](https://gitlab.com/gitlab-org/gitlab/-/issues/262081) in GitLab 14.1.
Publish NuGet packages in your project's Package Registry. Then, install the
diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md
index cb4e677687e..3204ac07d6a 100644
--- a/doc/user/packages/package_registry/index.md
+++ b/doc/user/packages/package_registry/index.md
@@ -6,11 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Package Registry **(FREE)**
-> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
-With the GitLab Package Registry, you can use GitLab as a private or public registry
-for a variety of common package managers. You can publish and share
-packages, which can be easily consumed as a dependency in downstream projects.
+With the GitLab Package Registry, you can use GitLab as a private or public registry for a variety
+of [supported package managers](#supported-package-managers).
+You can publish and share packages, which can be consumed as a dependency in downstream projects.
## View packages
@@ -48,8 +48,8 @@ Learn more about using the GitLab Package Registry with CI/CD:
- [Maven](../maven_repository/index.md#create-maven-packages-with-gitlab-cicd)
- [npm](../npm_registry/index.md#publish-an-npm-package-by-using-cicd)
- [NuGet](../nuget_repository/index.md#publish-a-nuget-package-by-using-cicd)
-- [PyPI](../pypi_repository/#authenticate-with-a-ci-job-token)
-- [RubyGems](../rubygems_registry/#authenticate-with-a-ci-job-token)
+- [PyPI](../pypi_repository/index.md#authenticate-with-a-ci-job-token)
+- [RubyGems](../rubygems_registry/index.md#authenticate-with-a-ci-job-token)
If you use CI/CD to build a package, extended activity information is displayed
when you view the package details:
@@ -124,3 +124,57 @@ Learn how to use the GitLab Package Registry to build your own custom package wo
to publish all of your packages to one project.
- Publish multiple different packages from one [monorepo project](../workflows/working_with_monorepos.md).
+
+## Supported package managers
+
+WARNING:
+Not all package manager formats are ready for production use. To view each format's status, see the
+table's **Status** column.
+
+The Package Registry supports the following formats:
+
+| Package type | GitLab version | Status |
+| ------------ | -------------- |------- |
+| [Maven](../maven_repository/index.md) | 11.3+ | GA |
+| [npm](../npm_registry/index.md) | 11.7+ | GA |
+| [NuGet](../nuget_repository/index.md) | 12.8+ | GA |
+| [PyPI](../pypi_repository/index.md) | 12.10+ | GA |
+| [Generic packages](../generic_packages/index.md) | 13.5+ | GA |
+| [Composer](../composer_repository/index.md) | 13.2+ | [Beta](https://gitlab.com/groups/gitlab-org/-/epics/6817) |
+| [Conan](../conan_repository/index.md) | 12.6+ | [Beta](https://gitlab.com/groups/gitlab-org/-/epics/6816) |
+| [Helm](../helm_repository/index.md) | 14.1+ | [Beta](https://gitlab.com/groups/gitlab-org/-/epics/6366) |
+| [Debian](../debian_repository/index.md) | 14.2+ | [Alpha](https://gitlab.com/groups/gitlab-org/-/epics/6057) |
+| [Go](../go_proxy/index.md) | 13.1+ | [Alpha](https://gitlab.com/groups/gitlab-org/-/epics/3043) |
+| [Ruby gems](../rubygems_registry/index.md) | 13.10+ | [Alpha](https://gitlab.com/groups/gitlab-org/-/epics/3200) |
+
+[Status](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga):
+
+- Alpha: behind a feature flag and not officially supported.
+- Beta: several known issues that may prevent expected use.
+- GA (Generally Available): ready for production use at any scale.
+
+You can also use the [API](../../../api/packages.md) to administer the Package Registry.
+
+## Accepting contributions
+
+This table lists unsupported package manager formats that we are accepting contributions for.
+Consider contributing to GitLab. This [development documentation](../../../development/packages.md)
+guides you through the process.
+
+<!-- vale gitlab.Spelling = NO -->
+
+| Format | Status |
+| ------ | ------ |
+| Chef | [#36889](https://gitlab.com/gitlab-org/gitlab/-/issues/36889) |
+| CocoaPods | [#36890](https://gitlab.com/gitlab-org/gitlab/-/issues/36890) |
+| Conda | [#36891](https://gitlab.com/gitlab-org/gitlab/-/issues/36891) |
+| CRAN | [#36892](https://gitlab.com/gitlab-org/gitlab/-/issues/36892) |
+| Opkg | [#36894](https://gitlab.com/gitlab-org/gitlab/-/issues/36894) |
+| P2 | [#36895](https://gitlab.com/gitlab-org/gitlab/-/issues/36895) |
+| Puppet | [#36897](https://gitlab.com/gitlab-org/gitlab/-/issues/36897) |
+| RPM | [#5932](https://gitlab.com/groups/gitlab-org/-/epics/5128) |
+| SBT | [#36898](https://gitlab.com/gitlab-org/gitlab/-/issues/36898) |
+| Swift | [#12233](https://gitlab.com/gitlab-org/gitlab/-/issues/12233) |
+| Vagrant | [#36899](https://gitlab.com/gitlab-org/gitlab/-/issues/36899) |
+
+<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/user/packages/pypi_repository/index.md b/doc/user/packages/pypi_repository/index.md
index 2d54cfc5f7d..4151346ec98 100644
--- a/doc/user/packages/pypi_repository/index.md
+++ b/doc/user/packages/pypi_repository/index.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# PyPI packages in the Package Registry **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208747) in GitLab Premium 12.10.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208747) in GitLab 12.10.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
Publish PyPI packages in your project's Package Registry. Then install the
packages whenever you need to use them as a dependency.
diff --git a/doc/user/packages/rubygems_registry/index.md b/doc/user/packages/rubygems_registry/index.md
index e31bd8bd0bf..05113d0bc10 100644
--- a/doc/user/packages/rubygems_registry/index.md
+++ b/doc/user/packages/rubygems_registry/index.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Ruby gems in the Package Registry **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/803) in [GitLab Free](https://about.gitlab.com/pricing/) 13.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/803) in GitLab 13.10.
WARNING:
The Ruby gems package registry for GitLab is under development and isn't ready for production use due to
diff --git a/doc/user/packages/workflows/working_with_monorepos.md b/doc/user/packages/workflows/working_with_monorepos.md
index 4e431b036de..ab10e746302 100644
--- a/doc/user/packages/workflows/working_with_monorepos.md
+++ b/doc/user/packages/workflows/working_with_monorepos.md
@@ -4,7 +4,7 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Monorepo package management workflows
+# Monorepo package management workflows **(FREE)**
One project or Git repository can contain multiple different subprojects or submodules that are all
packaged and published individually.
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 10147e7f69c..eb79d5099eb 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -33,8 +33,13 @@ usernames. A GitLab administrator can configure the GitLab instance to
## Project members permissions
-The Owner role is only available at the group or personal namespace level (and for instance administrators) and is inherited by its projects.
-While Maintainer is the highest project-level role, some actions can only be performed by a personal namespace or group owner, or an instance administrator, who receives all permissions.
+A user's role determines what permissions they have on a project. The Owner role provides all permissions but is
+available only:
+
+- For group owners. The role is inherited for a group's projects.
+- For Administrators.
+
+Personal namespace owners have the same permissions as an Owner, but are displayed with the Maintainer role on projects created in their personal namespace.
For more information, see [projects members documentation](project/members/index.md).
The following table lists project permissions available for each role:
@@ -70,7 +75,7 @@ The following table lists project permissions available for each role:
| [CI/CD](../ci/index.md):<br>Manage job triggers | | | | ✓ | ✓ |
| [CI/CD](../ci/index.md):<br>Manage runners | | | | ✓ | ✓ |
| [CI/CD](../ci/index.md):<br>Run Web IDE's Interactive Web Terminals **(ULTIMATE ONLY)** | | | | ✓ | ✓ |
-| [CI/CD](../ci/index.md):<br>Use [environment terminals](../ci/environments/index.md#web-terminals) | | | | ✓ | ✓ |
+| [CI/CD](../ci/index.md):<br>Use [environment terminals](../ci/environments/index.md#web-terminals-deprecated) | | | | ✓ | ✓ |
| [CI/CD](../ci/index.md):<br>Delete pipelines | | | | | ✓ |
| [Clusters](infrastructure/clusters/index.md):<br>View [pod logs](project/clusters/kubernetes_pod_logs.md) | | | ✓ | ✓ | ✓ |
| [Clusters](infrastructure/clusters/index.md):<br>Manage clusters | | | | ✓ | ✓ |
@@ -81,6 +86,15 @@ The following table lists project permissions available for each role:
| [GitLab Pages](project/pages/index.md):<br>Manage | | | | ✓ | ✓ |
| [GitLab Pages](project/pages/index.md):<br>Manage GitLab Pages domains and certificates | | | | ✓ | ✓ |
| [GitLab Pages](project/pages/index.md):<br>Remove GitLab Pages | | | | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>View [alerts](../operations/incident_management/alerts.md) | | ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>Assign an alert | ✓| ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>View [incident](../operations/incident_management/incidents.md) | ✓| ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>Create [incident](../operations/incident_management/incidents.md) | (*17*) | ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>View [on-call schedules](../operations/incident_management/oncall_schedules.md) | | ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>Participate in on-call rotation | ✓| ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>View [escalation policies](../operations/incident_management/escalation_policies.md) | | ✓ | ✓ | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>Manage [on-call schedules](../operations/incident_management/oncall_schedules.md) | | | | ✓ | ✓ |
+| [Incident Management](../operations/incident_management/index.md):<br>Manage [escalation policies](../operations/incident_management/escalation_policies.md)| | | | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Add Labels | ✓ (*16*) | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Assign | ✓ (*16*) | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Create | ✓ | ✓ | ✓ | ✓ | ✓ |
@@ -140,7 +154,7 @@ The following table lists project permissions available for each role:
| [Projects](project/index.md):<br>Add new team members | | | | ✓ | ✓ |
| [Projects](project/index.md):<br>Change [project features visibility](../public_access/public_access.md) level | | | | ✓ (14) | ✓ |
| [Projects](project/index.md):<br>Configure [webhooks](project/integrations/webhooks.md) | | | | ✓ | ✓ |
-| [Projects](project/index.md):<br>Delete [wiki](project/wiki/index.md) pages | | | | ✓ | ✓ |
+| [Projects](project/index.md):<br>Delete [wiki](project/wiki/index.md) pages | | | ✓ | ✓ | ✓ |
| [Projects](project/index.md):<br>Edit comments (posted by any user) | | | | ✓ | ✓ |
| [Projects](project/index.md):<br>Edit project badges | | | | ✓ | ✓ |
| [Projects](project/index.md):<br>Edit project settings | | | | ✓ | ✓ |
@@ -169,7 +183,7 @@ The following table lists project permissions available for each role:
| [Repository](project/repository/index.md):<br>Enable or disable branch protection | | | | ✓ | ✓ |
| [Repository](project/repository/index.md):<br>Enable or disable tag protection | | | | ✓ | ✓ |
| [Repository](project/repository/index.md):<br>Manage [push rules](../push_rules/push_rules.md) | | | | ✓ | ✓ |
-| [Repository](project/repository/index.md):<br>Push to protected branches | | | | ✓ | ✓ |
+| [Repository](project/repository/index.md):<br>Push to protected branches (*5*) | | | | ✓ | ✓ |
| [Repository](project/repository/index.md):<br>Turn on or off protected branch push for developers | | | | ✓ | ✓ |
| [Repository](project/repository/index.md):<br>Remove fork relationship | | | | | ✓ |
| [Repository](project/repository/index.md):<br>Force push to protected branches (*4*) | | | | | |
@@ -202,7 +216,7 @@ The following table lists project permissions available for each role:
1. If **Public pipelines** is enabled in **Project Settings > CI/CD**.
1. Not allowed for Guest, Reporter, Developer, Maintainer, or Owner. See [protected branches](project/protected_branches.md).
1. If the [branch is protected](project/protected_branches.md), this depends on the access Developers and Maintainers are given.
-1. Guest users can access GitLab [**Releases**](project/releases/index.md) for downloading assets but are not allowed to download the source code nor see repository information like tags and commits.
+1. Guest users can access GitLab [**Releases**](project/releases/index.md) for downloading assets but are not allowed to download the source code nor see [repository information like commits and release evidence](project/releases/index.md#view-a-release-and-download-assets).
1. Actions are limited only to records owned (referenced) by user.
1. When [Share Group Lock](group/index.md#prevent-a-project-from-being-shared-with-groups) is enabled the project can't be shared with other groups. It does not affect group with group sharing.
1. For information on eligible approvers for merge requests, see
@@ -216,7 +230,9 @@ The following table lists project permissions available for each role:
[project visibility](../public_access/public_access.md) is set to private.
1. Attached design files are moved together with the issue even if the user doesn't have the
Developer role.
-1. Guest users can set metadata (for example, labels, assignees, or milestones) when creating an issue.
+1. Guest users can only set metadata (for example, labels, assignees, or milestones)
+ when creating an issue. They cannot change the metadata on existing issues.
+1. In GitLab 14.5 or later, Guests are not allowed to [create incidents](../operations/incident_management/incidents.md#incident-creation).
## Project features permissions
@@ -305,7 +321,7 @@ The following table lists group permissions available for each role:
| Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
| View group Audit Events | | | ✓ (7) | ✓ (7) | ✓ |
| Create subgroup | | | | ✓ (1) | ✓ |
-| Delete group wiki pages **(PREMIUM)** | | | | ✓ | ✓ |
+| Delete group wiki pages **(PREMIUM)** | | | ✓ | ✓ | ✓ |
| Edit epic comments (posted by any user) **(ULTIMATE)** | | | | ✓ (2) | ✓ (2) |
| List group deploy tokens | | | | ✓ | ✓ |
| Manage [group push rules](group/index.md#group-push-rules) **(PREMIUM)** | | | | ✓ | ✓ |
@@ -384,8 +400,10 @@ An administrator can flag a user as external by either of the following methods:
1. On the left sidebar, select **Overview > Users** to create a new user or edit an existing one.
There, you can find the option to flag the user as external.
-Additionally users can be set as external users using [SAML groups](../integration/saml.md#external-groups)
-and [LDAP groups](../administration/auth/ldap/index.md#external-groups).
+Additionally users can be set as external users using:
+
+- [SAML groups](../integration/saml.md#external-groups).
+- [LDAP groups](../administration/auth/ldap/ldap_synchronization.md#external-groups).
### Setting new users to external
@@ -416,7 +434,7 @@ Be aware that this regex could lead to a
## Free Guest users **(ULTIMATE)**
-When a user is given Guest permissions on a project, group, or both, and holds no
+When a user is given the Guest role on a project, group, or both, and holds no
higher permission level on any other project or group on the GitLab instance,
the user is considered a guest user by GitLab and does not consume a license seat.
There is no other specific "guest" designation for newly created users.
@@ -466,22 +484,20 @@ subscriptions.
Project features like wiki and issues can be hidden from users depending on
which visibility level you select on project settings.
-- Disabled: disabled for everyone
-- Only team members: only team members will see even if your project is public or internal
-- Everyone with access: everyone can see depending on your project visibility level
-- Everyone: enabled for everyone (only available for GitLab Pages)
+- Disabled: disabled for everyone.
+- Only team members: only team members can see, even if your project is public or internal.
+- Everyone with access: everyone can see depending on your project visibility level.
+- Everyone: enabled for everyone (only available for GitLab Pages).
## GitLab CI/CD permissions
-GitLab CI/CD permissions rely on the role the user has in GitLab. There are four
-roles:
+GitLab CI/CD permissions rely on the role the user has in GitLab:
-- Administrator
- Maintainer
- Developer
- Guest/Reporter
-The Administrator role can perform any action on GitLab CI/CD in scope of the GitLab
+GitLab administrators can perform any action on GitLab CI/CD in scope of the GitLab
instance and project.
| Action | Guest, Reporter | Developer |Maintainer| Administrator |
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index 6fe4b457fac..e4e7e7b9c1a 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -61,7 +61,7 @@ To enable 2FA:
- [Authenticator](https://mattrubin.me/authenticator/)
- [andOTP](https://github.com/andOTP/andOTP)
- [Google Authenticator](https://support.google.com/accounts/answer/1066447?hl=en)
- - [Microsoft Authenticator](https://www.microsoft.com/en-us/account/authenticator)
+ - [Microsoft Authenticator](https://www.microsoft.com/en-us/security/mobile-authenticator-app)
- [SailOTP](https://openrepos.net/content/seiichiro0185/sailotp)
1. In the application, add a new entry in one of two ways:
- Scan the code presented in GitLab with your device's camera to add the
@@ -238,6 +238,9 @@ GitLab officially only supports [YubiKey](https://www.yubico.com/products/)
U2F devices, but users have successfully used [SoloKeys](https://solokeys.com/)
or [Google Titan Security Key](https://cloud.google.com/titan-security-key).
+NOTE:
+2FA must be configured before U2F.
+
The U2F workflow is [supported by](https://caniuse.com/#search=U2F) the
following desktop browsers:
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index 7f16c4e244e..d9f10b58c3f 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -49,7 +49,7 @@ Prerequisites:
- Your namespace cannot contain a project with [Container Registry](../packages/container_registry/index.md) tags.
- Your namespace cannot have a project that hosts [GitLab Pages](../project/pages/index.md). For more information,
- see [this procedure in the GitLab Team Handbook](https://about.gitlab.com/handbook/tools-and-tips/#how-to-change-your-username-at-gitlabcom).
+ see [this procedure in the GitLab Team Handbook](https://about.gitlab.com/handbook/tools-and-tips/#change-your-username-at-gitlabcom).
To change your username:
@@ -100,6 +100,18 @@ When visiting the public page of a user, you can only see the projects which you
If the [public level is restricted](../admin_area/settings/visibility_and_access_controls.md#restrict-visibility-levels),
user profiles are only visible to signed-in users.
+## User profile README
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232157) in GitLab 14.5.
+
+You can add a README section to your profile that can include more information and [formatting](../markdown.md) than
+your profile's bio.
+
+To add a README to your profile:
+
+1. Create a new public project with the same name as your GitLab username.
+1. Create a README file inside this project. The file can be any valid [README or index file](../project/repository/index.md#readme-and-index-files).
+
## Add external accounts to your user profile page
You can add links to certain other external accounts you might have, like Skype and Twitter.
@@ -117,7 +129,7 @@ To add links to other accounts:
## Show private contributions on your user profile page
-In the user contribution calendar graph and recent activity list, you can see your [contribution actions](../../api/events.md#action-types) to private projects.
+In the user contribution calendar graph and recent activity list, you can see your [contribution actions](../index.md#user-contribution-events) to private projects.
To show private contributions:
@@ -219,6 +231,12 @@ To set the busy status indicator, either:
## Set your time zone
+You can set your local time zone to:
+
+- Display your local time on your profile, and in places where hovering over your name shows information about you.
+- Align your contribution calendar with your local time to better reflect when your contributions were made
+ ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335343) in GitLab 14.5).
+
To set your time zone:
1. On the top bar, in the top-right corner, select your avatar.
diff --git a/doc/user/profile/notifications.md b/doc/user/profile/notifications.md
index 6de09f5538f..9faa4b78f8c 100644
--- a/doc/user/profile/notifications.md
+++ b/doc/user/profile/notifications.md
@@ -24,6 +24,7 @@ You might receive notifications for one of the following reasons:
or edit, or someone mentions you.
- You've [enabled notifications in an issue, merge request, or epic](#notifications-on-issues-merge-requests-and-epics).
- You've configured notifications for the [project](#change-level-of-project-notifications) or [group](#group-notifications).
+- You're subscribed to group or project pipeline notifications via the pipeline emails [integration](../project/integrations/overview.md).
NOTE:
Administrators can block notifications, preventing them from being sent.
@@ -353,3 +354,19 @@ For example, an alert notification email can have one of
Expanding the list of events included in the `X-GitLab-NotificationReason` header is tracked in
[issue 20689](https://gitlab.com/gitlab-org/gitlab/-/issues/20689).
+
+## Troubleshooting
+
+### Pull a list of recipients for notifications
+
+If you want to pull a list of recipients to receive notifications from a project
+(mainly used for troubleshooting custom notifications),
+in a Rails console, run `sudo gitlab-rails c` and be sure to update the project name:
+
+```plaintext
+project = Project.find_by_full_path '<project_name>'
+merge_request = project.merge_requests.find_by(iid: 1)
+current_user = User.first
+recipients = NotificationRecipients::BuildService.build_recipients(merge_request, current_user, action: "push_to"); recipients.count
+recipients.each { |notify| puts notify.user.username }
+```
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index bdd49b00a15..197ba4647b2 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -62,6 +62,10 @@ to the URL. For example:
https://gitlab.example.com/-/profile/personal_access_tokens?name=Example+Access+token&scopes=api,read_user,read_registry
```
+WARNING:
+Personal access tokens must be treated carefully. Read our [token security considerations](../../security/token_overview.md#security-considerations)
+for guidance on managing personal access tokens (for example, setting a short expiry and using minimal scopes).
+
## Revoke a personal access token
At any time, you can revoke a personal access token.
diff --git a/doc/user/project/badges.md b/doc/user/project/badges.md
index d54edc7e6d3..9ca11d43864 100644
--- a/doc/user/project/badges.md
+++ b/doc/user/project/badges.md
@@ -56,11 +56,18 @@ To add this badge to a project:
## Group badges
-Badges can be added to a group and are visible on every project's
-overview page that's under that group. In this case, they cannot be edited or
-deleted on the project level. If you need to have individual badges for each
-project, consider adding them on the [project level](#project-badges) or use
-[placeholders](#placeholders).
+By adding a badge to a group, you add and enforce a project-level badge
+for all projects in the group. The group badge is visible on the **Overview**
+page of any project that belongs to the group.
+
+NOTE:
+While these badges appear as project-level badges in the codebase, they
+cannot be edited or deleted at the project level.
+
+If you need individual badges for each project, either:
+
+- Add the badge at the [project level](#project-badges).
+- Use [placeholders](#placeholders).
To add a new badge to a group:
diff --git a/doc/user/project/canary_deployments.md b/doc/user/project/canary_deployments.md
index 6d1fb0f6755..77cf04cc7eb 100644
--- a/doc/user/project/canary_deployments.md
+++ b/doc/user/project/canary_deployments.md
@@ -69,10 +69,14 @@ can easily notice them.
![Canary deployments on deploy board](img/deploy_boards_canary_deployments.png)
-### Advanced traffic control with Canary Ingress
+### Advanced traffic control with Canary Ingress (DEPRECATED)
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215501) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212320) to Free in GitLab 13.8.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
Canary deployments can be more strategic with [Canary Ingress](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary),
which is an advanced traffic routing service that controls incoming HTTP
diff --git a/doc/user/project/clusters/add_eks_clusters.md b/doc/user/project/clusters/add_eks_clusters.md
index 0db0f14b633..e03e5b10236 100644
--- a/doc/user/project/clusters/add_eks_clusters.md
+++ b/doc/user/project/clusters/add_eks_clusters.md
@@ -4,12 +4,13 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Connect EKS clusters through cluster certificates **(FREE)**
+# Connect EKS clusters through cluster certificates (DEPRECATED) **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22392) in GitLab 12.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22392) in GitLab 12.5.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
WARNING:
-Use [Infrastrucure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac)
+This feature was deprecated in GitLab 14.5. Use [Infrastrucure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac)
to create new clusters.
Through GitLab, you can create new clusters and add existing clusters hosted on Amazon Elastic
@@ -20,18 +21,10 @@ Kubernetes Service (EKS).
If you already have an EKS cluster and want to connect it to GitLab,
use the [GitLab Kubernetes Agent](../../clusters/agent/index.md).
-Alternatively, you can [connect them with cluster certificates](add_existing_cluster.md),
-although this method is not recommended for [security implications](../../infrastructure/clusters/connect/index.md#security-implications-for-clusters-connected-with-certificates).
-
## Create a new EKS cluster
To create a new cluster from GitLab, use [Infrastructure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac).
-Alternatively, you can [create new EKS clusters using cluster certificates](#how-to-create-a-new-cluster-on-eks-through-cluster-certificates-deprecated).
-Although still available on the GitLab UI, this method was deprecated
-in GitLab 14.0 and is scheduled for removal in GitLab 15.0.
-It also has [security implications](../../infrastructure/clusters/connect/index.md#security-implications-for-clusters-connected-with-certificates).
-
### How to create a new cluster on EKS through cluster certificates (DEPRECATED)
> [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/327908) in GitLab 14.0.
diff --git a/doc/user/project/clusters/add_existing_cluster.md b/doc/user/project/clusters/add_existing_cluster.md
index 3347ef9a437..fcf2583d3ab 100644
--- a/doc/user/project/clusters/add_existing_cluster.md
+++ b/doc/user/project/clusters/add_existing_cluster.md
@@ -4,16 +4,17 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Connect existing clusters through cluster certificates
+# Connect existing clusters through cluster certificates **(DEPRECATED)**
-If you have an existing Kubernetes cluster, you can add it to a project, group,
-or instance and benefit from the integration with GitLab.
+> [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
WARNING:
-The process described on this page uses cluster certificates to connect your cluster
-to GitLab. Although this method still works, it is **no longer recommended**.
-To connect your cluster to GitLab, we **recommend** using the [GitLab Kubernetes Agent](../../clusters/agent/index.md)
-instead. **(PREMIUM)**
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+To connect your cluster to GitLab, use the [GitLab Kubernetes Agent](../../clusters/agent/index.md)
+instead.
+
+If you have an existing Kubernetes cluster, you can add it to a project, group,
+or instance and benefit from the integration with GitLab.
## Prerequisites
diff --git a/doc/user/project/clusters/add_gke_clusters.md b/doc/user/project/clusters/add_gke_clusters.md
index 0d35e89a560..30be319f2df 100644
--- a/doc/user/project/clusters/add_gke_clusters.md
+++ b/doc/user/project/clusters/add_gke_clusters.md
@@ -4,9 +4,12 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Connect GKE clusters through cluster certificates **(FREE)**
+# Connect GKE clusters through cluster certificates (DEPRECATED) **(FREE)**
+
+> [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
Use [Infrastrucure as Code](../../infrastructure/clusters/connect/new_gke_cluster.md)
to create a cluster hosted on Google Kubernetes Engine (GKE).
@@ -18,21 +21,13 @@ hosted on Google Kubernetes Engine (GKE).
If you already have a GKE cluster and want to connect it to GitLab,
use the [GitLab Kubernetes Agent](../../clusters/agent/index.md).
-Alternatively, you can [connect them with cluster certificates](add_existing_cluster.md),
-altough this method is not recommended for [security implications](../../infrastructure/clusters/connect/index.md#security-implications-for-clusters-connected-with-certificates).
-
## Create a new GKE cluster from GitLab
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25925) in GitLab 12.4, all the GKE clusters provisioned by GitLab are [VPC-native](https://cloud.google.com/kubernetes-engine/docs/how-to/alias-ips).
To create a new GKE cluster from GitLab, use [Infrastructure as Code](../../infrastructure/clusters/connect/new_gke_cluster.md).
-Alternatively, you can [create new GKE clusters using cluster certificates](#create-a-new-cluster-on-gke-through-cluster-certificates-deprecated).
-Although still available in the GitLab UI, this method was deprecated
-in GitLab 14.0 and is scheduled for removal in GitLab 15.0.
-It also has [security implications](../../infrastructure/clusters/connect/index.md#security-implications-for-clusters-connected-with-certificates).
-
-## Create a new cluster on GKE through cluster certificates (DEPRECATED)
+## Create a new cluster on GKE through cluster certificates
> [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/6049) in GitLab 14.0.
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index 4f2bc5526e0..49708e3b6aa 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.md
@@ -9,9 +9,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/327908) in GitLab 14.0.
WARNING:
-Creating a new cluster through cluster certificates
-is deprecated and no longer recommended. To create a new cluster use
-[Infrastructure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac).
+This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/327908) in GitLab 14.0.
+To create a new cluster use [Infrastructure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac).
NOTE:
Every new Google Cloud Platform (GCP) account receives
diff --git a/doc/user/project/clusters/cluster_access.md b/doc/user/project/clusters/cluster_access.md
index 452f5727620..510aad821cf 100644
--- a/doc/user/project/clusters/cluster_access.md
+++ b/doc/user/project/clusters/cluster_access.md
@@ -4,9 +4,15 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Cluster access controls (RBAC or ABAC)
+# Access controls with cluster certificates (RBAC or ABAC) (DEPRECATED) **(FREE)**
-> Restricted service account for deployment was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51716) in GitLab 11.5.
+> - Restricted service account for deployment was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51716) in GitLab 11.5.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+To connect your cluster to GitLab, use the [GitLab Kubernetes Agent](../../clusters/agent/index.md)
+instead.
When creating a cluster in GitLab, you are asked if you would like to create either:
diff --git a/doc/user/project/clusters/deploy_to_cluster.md b/doc/user/project/clusters/deploy_to_cluster.md
index 54141fe1103..c3a71ec8585 100644
--- a/doc/user/project/clusters/deploy_to_cluster.md
+++ b/doc/user/project/clusters/deploy_to_cluster.md
@@ -4,13 +4,14 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Deploy to a Kubernetes cluster with cluster certificates
+# Deploy to a Kubernetes cluster with cluster certificates (DEPRECATED) **(FREE)**
+
+> [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
WARNING:
-The process described on this page uses cluster certificates to deploy to your cluster
-from GitLab. Although this method still works, it is **no longer recommended**.
-To deploy to your cluster from GitLab, we **recommend** using the [GitLab Kubernetes Agent](../../clusters/agent/index.md)
-instead. **(PREMIUM)**
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+To connect your cluster to GitLab, use the [GitLab Kubernetes Agent](../../clusters/agent/index.md).
+To deploy with the Agent, use the [CI/CD Tunnel](../../clusters/agent/ci_cd_tunnel.md).
A Kubernetes cluster can be the destination for a deployment job. If
@@ -77,7 +78,7 @@ You can customize the deployment namespace in a few ways:
- For **non-managed** clusters, the auto-generated namespace is set in the `KUBECONFIG`,
but the user is responsible for ensuring its existence. You can fully customize
this value using
- [`environment:kubernetes:namespace`](../../../ci/environments/index.md#configure-kubernetes-deployments)
+ [`environment:kubernetes:namespace`](../../../ci/environments/index.md#configure-kubernetes-deployments-deprecated)
in `.gitlab-ci.yml`.
When you customize the namespace, existing environments remain linked to their current
@@ -100,7 +101,7 @@ combined with *one* of the following:
> Introduced in GitLab 8.15.
-The Kubernetes integration adds [web terminal](../../../ci/environments/index.md#web-terminals)
+The Kubernetes integration adds [web terminal](../../../ci/environments/index.md#web-terminals-deprecated)
support to your [environments](../../../ci/environments/index.md). This is based
on the `exec` functionality found in Docker and Kubernetes, so you get a new
shell session in your existing containers. To use this integration, you
diff --git a/doc/user/project/clusters/gitlab_managed_clusters.md b/doc/user/project/clusters/gitlab_managed_clusters.md
index 77921ec1dff..ad378be2d9a 100644
--- a/doc/user/project/clusters/gitlab_managed_clusters.md
+++ b/doc/user/project/clusters/gitlab_managed_clusters.md
@@ -4,10 +4,16 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab-managed clusters
+# GitLab-managed clusters (DEPRECATED) **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22011) in GitLab 11.5.
> - Became [optional](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26565) in GitLab 11.11.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+To connect your cluster to GitLab, use the [GitLab Kubernetes Agent](../../../user/clusters/agent/index.md).
+To manage applications, use the [Cluster Project Management Template](../../../user/clusters/management_project_template.md).
You can choose to allow GitLab to manage your cluster for you. If your cluster
is managed by GitLab, resources for your projects are automatically created. See
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index ac59f874244..c16c6446acd 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -4,19 +4,22 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Project-level Kubernetes clusters **(FREE)**
+# Project-level Kubernetes clusters (certificate-based) (DEPRECATED) **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35954) in GitLab 10.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35954) in GitLab 10.1.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
-[Project-level Kubernetes clusters](../../infrastructure/clusters/connect/index.md#cluster-levels)
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8)
+in GitLab 14.5. To connect clusters to GitLab, use the
+[GitLab Kubernetes Agent](../../clusters/agent/index.md).
+
+[Project-level](../../infrastructure/clusters/connect/index.md#cluster-levels-deprecated) Kubernetes clusters
allow you to connect a Kubernetes cluster to a project in GitLab.
You can also [connect multiple clusters](multiple_kubernetes_clusters.md)
to a single project.
-After connecting a cluster to GitLab, you can benefit from the large number of
-[GitLab features available for Kubernetes clusters](../../infrastructure/clusters/index.md) to manage and deploy to your cluster.
-
## View your project-level clusters
To view project-level Kubernetes clusters:
diff --git a/doc/user/project/clusters/kubernetes_pod_logs.md b/doc/user/project/clusters/kubernetes_pod_logs.md
index eb0e8d0e91c..19166a1ff8c 100644
--- a/doc/user/project/clusters/kubernetes_pod_logs.md
+++ b/doc/user/project/clusters/kubernetes_pod_logs.md
@@ -4,10 +4,14 @@ group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Kubernetes Logs **(FREE)**
+# Kubernetes Logs (DEPRECATED) **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4752) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26383) to [GitLab Free](https://about.gitlab.com/pricing/) 12.9.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
GitLab makes it easy to view the logs of running pods in
[connected Kubernetes clusters](index.md). By displaying the logs directly in GitLab
diff --git a/doc/user/project/clusters/multiple_kubernetes_clusters.md b/doc/user/project/clusters/multiple_kubernetes_clusters.md
index e2eae011b8c..540907bf915 100644
--- a/doc/user/project/clusters/multiple_kubernetes_clusters.md
+++ b/doc/user/project/clusters/multiple_kubernetes_clusters.md
@@ -4,10 +4,16 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Multiple Kubernetes clusters for a single project
+# Multiple clusters per project with cluster certificates (DEPRECATED) **(FREE)**
> - Introduced in [GitLab Premium](https://about.gitlab.com/pricing/) 10.3
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094) to GitLab Free in 13.2.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+Using multiple Kubernetes clusters for a single project **with cluster
+certificates** was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+To connect clusters to GitLab, use the [GitLab Kubernetes Agent](../../../user/clusters/agent/index.md).
You can associate more than one Kubernetes cluster to your
project. That way you can have different clusters for different environments,
diff --git a/doc/user/project/clusters/protect/container_host_security/index.md b/doc/user/project/clusters/protect/container_host_security/index.md
index 5e4df6009f0..c005ce64bb5 100644
--- a/doc/user/project/clusters/protect/container_host_security/index.md
+++ b/doc/user/project/clusters/protect/container_host_security/index.md
@@ -6,6 +6,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Container Host Security **(FREE)**
+NOTE:
+In GitLab 14.5, using a certificate to connect GitLab to a Kubernetes cluster is [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
+You can continue using Container Host Security, even though it relies on this certificate-based
+method. The work to allow all aspects of Container Host Security to function through the [GitLab Kubernetes Agent](../../../../clusters/agent/index.md)
+instead of the certificate-based method can be tracked [in this GitLab issue](https://gitlab.com/gitlab-org/gitlab/-/issues/299350).
+
Container Host Security in GitLab provides Intrusion Detection and Prevention capabilities that can
monitor and (optionally) block activity inside the containers themselves. This is done by leveraging
an integration with Falco to provide the monitoring capabilities and an integration with Pod
diff --git a/doc/user/project/clusters/protect/container_network_security/index.md b/doc/user/project/clusters/protect/container_network_security/index.md
index 3daa48e1811..eb15675da19 100644
--- a/doc/user/project/clusters/protect/container_network_security/index.md
+++ b/doc/user/project/clusters/protect/container_network_security/index.md
@@ -6,6 +6,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Container Network Security **(FREE)**
+NOTE:
+In GitLab 14.5, using a certificate to connect GitLab to a Kubernetes cluster is [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
+You can continue using Container Network Security, even though it relies on this certificate-based
+method. The work to allow all aspects of Container Network Security to function through the [GitLab Kubernetes Agent](../../../../clusters/agent/index.md)
+instead of the certificate-based method can be tracked [in this GitLab issue](https://gitlab.com/gitlab-org/gitlab/-/issues/299350) and [this GitLab Epic](https://gitlab.com/groups/gitlab-org/-/epics/7057).
+
Container Network Security in GitLab provides basic firewall functionality by leveraging Cilium
NetworkPolicies to filter traffic going in and out of the cluster as well as traffic between pods
inside the cluster. Container Network Security can be used to enforce L3, L4, and L7 policies and
diff --git a/doc/user/project/clusters/serverless/aws.md b/doc/user/project/clusters/serverless/aws.md
index 6eafb4530d3..06fa18d80c9 100644
--- a/doc/user/project/clusters/serverless/aws.md
+++ b/doc/user/project/clusters/serverless/aws.md
@@ -434,11 +434,11 @@ To test the application you deployed, please go to the build log and follow the
1. Click on "Show complete raw" on the upper right-hand corner:
- ![sam-complete-raw](img/sam-complete-raw.png)
+ ![SAM complete raw](img/sam-complete-raw.png)
1. Look for HelloWorldApi – API Gateway endpoint similar to shown below:
- ![sam-api-endpoint](img/sam-api-endpoint.png)
+ ![SAM API endpoint](img/sam-api-endpoint.png)
1. Use curl to test the API. For example:
diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md
index 7d51fb59793..c138dc64d19 100644
--- a/doc/user/project/code_owners.md
+++ b/doc/user/project/code_owners.md
@@ -84,6 +84,10 @@ so that their members also become eligible Code Owners.
If you do not invite **Subgroup Y** to **Project A**, but make them Code Owners, their approval
of the merge request becomes optional.
+Inviting **Subgroup Y** to a parent group of **Project A**
+[is not supported](https://gitlab.com/gitlab-org/gitlab/-/issues/288851). To set **Subgroup Y** as
+Code Owners, add this group directly to the project itself.
+
### Add a group as a Code Owner
To set a group as a Code Owner:
diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md
index 6e2635b89f0..15490ab0b94 100644
--- a/doc/user/project/deploy_boards.md
+++ b/doc/user/project/deploy_boards.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto, reference
---
-# Deploy boards **(FREE)**
+# Deploy boards (DEPRECATED) **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1589) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212320) to GitLab Free in 13.8.
@@ -15,6 +15,12 @@ type: howto, reference
> - In GitLab 13.11 and earlier, environments in folders do not show deploy boards.
> This is [fixed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60525) in
> GitLab 13.12.
+> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
+[An epic exists](https://gitlab.com/groups/gitlab-org/-/epics/2493)
+to add this functionality to the [Agent](../index.md).
GitLab deploy boards offer a consolidated view of the current health and
status of each CI [environment](../../ci/environments/index.md) running on [Kubernetes](https://kubernetes.io), displaying the status
diff --git a/doc/user/project/deploy_keys/index.md b/doc/user/project/deploy_keys/index.md
index 61dccf1cb1b..c5950347ae9 100644
--- a/doc/user/project/deploy_keys/index.md
+++ b/doc/user/project/deploy_keys/index.md
@@ -81,10 +81,11 @@ help you access a repository, but there are some notables differences between th
[Project maintainers and owners](../../permissions.md#project-members-permissions)
can add or enable a deploy key for a project repository:
-1. Navigate to the project's **Settings > Repository** page.
-1. Expand the **Deploy keys** section.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Deploy keys**.
1. Specify a title for the new deploy key and paste your public SSH key.
-1. (Optional) Check **Grant write permissions to this key** to allow `read-write` access. Leave it unchecked for `read-only` access.
+1. Optional. To allow `read-write` access, select the **Grant write permissions to this key** checkbox. Leave it unchecked for `read-only` access.
There are three lists of project deploy keys:
@@ -164,9 +165,10 @@ configuration.
[Project maintainers and owners](../../permissions.md#project-members-permissions)
can remove or disable a deploy key for a project repository:
-1. Navigate to the project's **Settings > Repository** page.
-1. Expand the **Deploy keys** section.
-1. Select the **{remove}** or **{cancel}** button.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Deploy keys**.
+1. Select **Disable** (**{cancel}**).
NOTE:
Any service that relies on a deploy key stops working after that key is removed.
diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md
index 483de3b21bd..c840f6c8698 100644
--- a/doc/user/project/deploy_tokens/index.md
+++ b/doc/user/project/deploy_tokens/index.md
@@ -29,14 +29,15 @@ You can create as many deploy tokens as you need from the settings of your
project. Alternatively, you can also create [group-scoped deploy tokens](#group-deploy-token).
1. Sign in to your GitLab account.
-1. Go to the project (or group) you want to create deploy tokens for.
-1. Go to **Settings > Repository**.
-1. Expand the **Deploy tokens** section.
-1. Choose a name, expiry date (optional), and username (optional) for the token.
+1. On the top bar, select **Menu > Projects** or **Menu > Groups** to find your project or group.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Deploy tokens**.
+1. Choose a name, and optionally, an expiration date and username for the token.
1. Choose the [desired scopes](#limiting-scopes-of-a-deploy-token).
1. Select **Create deploy token**.
-1. Save the deploy token somewhere safe. After you leave or refresh
- the page, **you can't access it again**.
+
+Save the deploy token somewhere safe. After you leave or refresh
+the page, **you can't access it again**.
![Personal access tokens page](img/deploy_tokens_ui.png)
@@ -46,8 +47,12 @@ Deploy tokens expire at midnight UTC on the date you define.
## Revoking a deploy token
-To revoke a deploy token, under the **Active deploy tokens** area,
-select the respective **Revoke** button.
+To revoke a deploy token:
+
+1. On the top bar, select **Menu > Projects** or **Menu > Groups** to find your project or group.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Deploy tokens**.
+1. In the **Active Deploy Tokens** section, by the token you want to revoke, select **Revoke**.
## Limiting scopes of a deploy token
diff --git a/doc/user/project/file_lock.md b/doc/user/project/file_lock.md
index db8c6f24063..10dcbddac17 100644
--- a/doc/user/project/file_lock.md
+++ b/doc/user/project/file_lock.md
@@ -212,20 +212,21 @@ requests that modify locked files. Unlock the file to allow changes.
To lock a file:
1. Open the file or directory in GitLab.
-1. Click the **Lock** button, located near the Web IDE button.
+1. On the top right, above the file, select **Lock**.
+1. On the confirmation dialog box, select **OK**.
- ![Locking file](img/file_lock.png)
+If you do not have permission to lock the file, the button is not enabled.
-An **Unlock** button is displayed if the file is already locked, and
-is disabled if you do not have permission to unlock the file.
-
-If you did not lock the file, hovering your cursor over the button shows
-who locked the file.
+To view the user who locked the file (if it was not you), hover over the button.
### View and remove existing locks
-The **Locked Files**, accessed from **Project > Repository** left menu, lists
-all file and directory locks. Locks can be removed by their author, or any user
-with the [Maintainer role](../permissions.md) and above.
+To view and remove file locks:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Repository > Locked Files**.
This list shows all the files locked either through LFS or GitLab UI.
+
+Locks can be removed by their author, or any user
+with at least the [Maintainer role](../permissions.md).
diff --git a/doc/user/project/img/file_lock.png b/doc/user/project/img/file_lock.png
deleted file mode 100644
index e881442630b..00000000000
--- a/doc/user/project/img/file_lock.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/bitbucket.md b/doc/user/project/import/bitbucket.md
index cda018a0c37..0c50fc77e33 100644
--- a/doc/user/project/import/bitbucket.md
+++ b/doc/user/project/import/bitbucket.md
@@ -52,20 +52,18 @@ namespace that started the import process.
## Import your Bitbucket repositories
-1. Sign in to GitLab and go to your dashboard.
-1. Click on **New project**.
-
-1. Click on the "Bitbucket Cloud" button.
-
- ![Bitbucket](img/import_projects_from_new_project_page.png)
-
-1. Grant GitLab access to your Bitbucket account
+1. Sign in to GitLab.
+1. On the top bar, select **New** (**{plus}**).
+1. Select **New project/repository**.
+1. Select **Import project**.
+1. Select **Bitbucket Cloud**.
+1. Log in to Bitbucket and grant GitLab access to your Bitbucket account.
![Grant access](img/bitbucket_import_grant_access.png)
-1. Click on the projects that you'd like to import or **Import all projects**.
- You can also filter projects by name and select the namespace under which
- each project will be imported.
+1. Select the projects that you'd like to import or import all projects.
+ You can filter projects by name and select the namespace
+ each project will be imported for.
![Import projects](img/bitbucket_import_select_project_v12_3.png)
diff --git a/doc/user/project/import/bitbucket_server.md b/doc/user/project/import/bitbucket_server.md
index 2715804b37a..81e7d159a06 100644
--- a/doc/user/project/import/bitbucket_server.md
+++ b/doc/user/project/import/bitbucket_server.md
@@ -78,10 +78,7 @@ the author's:
- `slug`
- `displayName`
-If the user is not found by any of these properties, the search falls back to the author's
-`email` address.
-
-Alternatively, if there is also no email address, the project creator is set as the author.
+If the user is not found by any of these properties, the project creator is set as the author.
##### Enable or disable User assignment by username
@@ -104,22 +101,27 @@ Feature.disable(:bitbucket_server_user_mapping_by_username)
## Import your Bitbucket repositories
-1. Sign in to GitLab and go to your dashboard.
-1. Click on **New project**.
-1. Click on the "Bitbucket Server" button. If the button is not present, enable the importer in
- **Admin > Application Settings > Visibility and access controls > Import sources**.
+Prerequisite:
- ![Bitbucket](img/import_projects_from_new_project_page.png)
+- An administrator must have enabled the importer in
+ **Admin > Application Settings > Visibility and access controls > Import sources**.
-1. Enter your Bitbucket Server credentials.
+To import your Bitbucket repositories:
- ![Grant access](img/bitbucket_server_import_credentials.png)
+1. Sign in to GitLab.
+1. On the top bar, select **New** (**{plus}**).
+1. Select **New project/repository**.
+1. Select **Import project**.
+1. Select **Bitbucket Server**.
+1. Log in to Bitbucket and grant GitLab access to your Bitbucket account.
+1. Select the projects that you'd like to import or import all projects.
+ You can filter projects by name and select the namespace
+ each project will be imported for.
-1. Click on the projects that you'd like to import or **Import all projects**.
- You can also filter projects by name and select the namespace under which each project is
- imported.
+## Automate group and project import **(PREMIUM)**
- ![Import projects](img/bitbucket_server_import_select_project_v12_3.png)
+For information on automating user, group, and project import API calls, see
+[Automate group and project import](index.md#automate-group-and-project-import).
## Troubleshooting
diff --git a/doc/user/project/import/fogbugz.md b/doc/user/project/import/fogbugz.md
index 982bc6d90e8..3458c7fe4a7 100644
--- a/doc/user/project/import/fogbugz.md
+++ b/doc/user/project/import/fogbugz.md
@@ -16,15 +16,16 @@ users.
To import your project from FogBugz:
-1. From your GitLab dashboard, select **New project**.
-1. Select the **FogBugz** button.
- ![FogBugz](img/fogbugz_import_select_fogbogz.png)
+1. Sign in to GitLab.
+1. On the top bar, select **New** (**{plus}**).
+1. Select **New project/repository**.
+1. Select **Import project**.
+1. Select **FogBugz**.
1. Enter your FogBugz URL, email address, and password.
- ![Login](img/fogbugz_import_login.png)
1. Create a mapping from FogBugz users to GitLab users.
![User Map](img/fogbugz_import_user_map.png)
-1. Select **Import** for the projects you want to import.
+1. For the projects you want to import, select **Import**.
![Import Project](img/fogbugz_import_select_project.png)
-1. After the import finishes, click the link to go to the project
+1. After the import finishes, select the link to go to the project
dashboard. Follow the directions to push your existing repository.
![Finished](img/fogbugz_import_finished.png)
diff --git a/doc/user/project/import/gitea.md b/doc/user/project/import/gitea.md
index 3bbc70b4337..db55330f806 100644
--- a/doc/user/project/import/gitea.md
+++ b/doc/user/project/import/gitea.md
@@ -38,8 +38,6 @@ that started the import process.
The importer page is visible when you create a new project.
-![New project page on GitLab](img/import_projects_from_new_project_page.png)
-
Select the **Gitea** link to start the import authorization process.
![New Gitea project import](img/import_projects_from_gitea_new_import.png)
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index eff733b0b3d..e1a81ae1bba 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -25,6 +25,7 @@ The following aspects of a project are imported:
- Pull request "merged by" information (GitLab.com & 13.7+)
- Regular issue and pull request comments
- [Git Large File Storage (LFS) Objects](../../../topics/git/lfs/index.md)
+- Pull request comments replies in discussions ([GitLab.com & 14.5+](https://gitlab.com/gitlab-org/gitlab/-/issues/336596))
References to pull requests and issues are preserved (GitLab.com & 8.7+), and
each imported repository maintains visibility level unless that [visibility
@@ -67,7 +68,7 @@ For this association to succeed, each GitHub author and assignee in the reposito
must meet one of the following conditions prior to the import:
- Have previously logged in to a GitLab account using the GitHub icon.
-- Have a GitHub account with a [public-facing email address](https://docs.github.com/en/github/setting-up-and-managing-your-github-user-account/managing-email-preferences/setting-your-commit-email-address)
+- Have a GitHub account with a [public-facing email address](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-user-account/managing-email-preferences/setting-your-commit-email-address)
that matches their GitLab account's email address.
NOTE:
@@ -240,3 +241,8 @@ To disable the feature, run this command:
# Disable
Feature.disable(:github_importer_lower_per_page_limit, group)
```
+
+## Automate group and project import **(PREMIUM)**
+
+For information on automating user, group, and project import API calls, see
+[Automate group and project import](index.md#automate-group-and-project-import).
diff --git a/doc/user/project/import/gitlab_com.md b/doc/user/project/import/gitlab_com.md
index f25b29317a7..bcbc6e09f1b 100644
--- a/doc/user/project/import/gitlab_com.md
+++ b/doc/user/project/import/gitlab_com.md
@@ -26,3 +26,8 @@ for permission to access your projects. After accepting, you are automatically r
To import a project, click "Import". The importer imports your repository and issues.
Once the importer is done, a new GitLab project is created with your imported data.
+
+## Automate group and project import **(PREMIUM)**
+
+For information on automating user, group, and project import API calls, see
+[Automate group and project import](index.md#automate-group-and-project-import).
diff --git a/doc/user/project/import/img/bitbucket_server_import_credentials.png b/doc/user/project/import/img/bitbucket_server_import_credentials.png
deleted file mode 100644
index 25bcc3ab6e6..00000000000
--- a/doc/user/project/import/img/bitbucket_server_import_credentials.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/img/bitbucket_server_import_select_project_v12_3.png b/doc/user/project/import/img/bitbucket_server_import_select_project_v12_3.png
deleted file mode 100644
index 3f94dd83dd6..00000000000
--- a/doc/user/project/import/img/bitbucket_server_import_select_project_v12_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/img/fogbugz_import_login.png b/doc/user/project/import/img/fogbugz_import_login.png
deleted file mode 100644
index 6ba4d443f1a..00000000000
--- a/doc/user/project/import/img/fogbugz_import_login.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/img/fogbugz_import_select_fogbogz.png b/doc/user/project/import/img/fogbugz_import_select_fogbogz.png
deleted file mode 100644
index d207646a6f2..00000000000
--- a/doc/user/project/import/img/fogbugz_import_select_fogbogz.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/img/import_projects_from_new_project_page.png b/doc/user/project/import/img/import_projects_from_new_project_page.png
deleted file mode 100644
index 7c32d3555d1..00000000000
--- a/doc/user/project/import/img/import_projects_from_new_project_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index 887eb546148..6e02a9bf5ab 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -102,3 +102,18 @@ After an administrator creates an alias for a project, you can use the alias to
repository. For example, if an administrator creates the alias `gitlab` for the project
`https://gitlab.com/gitlab-org/gitlab`, you can clone the project with
`git clone git@gitlab.com:gitlab.git` instead of `git clone git@gitlab.com:gitlab-org/gitlab.git`.
+
+## Automate group and project import **(PREMIUM)**
+
+The GitLab Professional Services team uses [Congregate](https://gitlab.com/gitlab-org/professional-services-automation/tools/migration/congregate)
+to orchestrate user, group, and project import API calls. With Congregate, you can migrate data to
+GitLab from:
+
+- Other GitLab instances
+- GitHub Enterprise
+- GitHub.com
+- Bitbucket Server
+- Bitbucket Data Center
+
+See the [Quick Start Guide](https://gitlab.com/gitlab-org/professional-services-automation/tools/migration/congregate/-/blob/master/docs/using-congregate.md#quick-start)
+to learn how to use this approach for migrating users, groups, and projects at scale.
diff --git a/doc/user/project/import/perforce.md b/doc/user/project/import/perforce.md
index f3843396b79..aa256e07b30 100644
--- a/doc/user/project/import/perforce.md
+++ b/doc/user/project/import/perforce.md
@@ -61,3 +61,7 @@ creating small and efficient Git pack files. So it might be a good
idea to spend time and CPU to properly repack your repository before
sending it for the first time to your GitLab server. See
[this StackOverflow question](https://stackoverflow.com/questions/28720151/git-gc-aggressive-vs-git-repack/).
+
+## Related topics
+
+- [Mirror with Perforce Helix with Git Fusion](../repository/mirror/bidirectional.md#mirror-with-perforce-helix-with-git-fusion)
diff --git a/doc/user/project/import/repo_by_url.md b/doc/user/project/import/repo_by_url.md
index e504f3678a7..0b96238006e 100644
--- a/doc/user/project/import/repo_by_url.md
+++ b/doc/user/project/import/repo_by_url.md
@@ -23,3 +23,8 @@ You can import your existing repositories by providing the Git URL:
<!-- vale gitlab.SubstitutionWarning = YES -->
![Import project by repository URL](img/import_projects_from_repo_url.png)
+
+## Automate group and project import **(PREMIUM)**
+
+For information on automating user, group, and project import API calls, see
+[Automate group and project import](index.md#automate-group-and-project-import).
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index f3173736e9b..78cd2f8fb79 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -47,7 +47,7 @@ Projects include the following [features](https://about.gitlab.com/features/):
strategy and get reviewed by your team.
- [Merge Request Approvals](merge_requests/approvals/index.md): Ask for approval before
implementing a change.
- - [Fix merge conflicts from the UI](merge_requests/resolve_conflicts.md): View Git diffs from the GitLab UI.
+ - [Fix merge conflicts from the UI](merge_requests/conflicts.md): View Git diffs from the GitLab UI.
- [Review Apps](../../ci/review_apps/index.md): By branch, preview the results
of the changes proposed in a merge request.
- [Labels](labels.md): Organize issues and merge requests by labels.
diff --git a/doc/user/project/integrations/custom_issue_tracker.md b/doc/user/project/integrations/custom_issue_tracker.md
index eaab1933b79..d155f91e40b 100644
--- a/doc/user/project/integrations/custom_issue_tracker.md
+++ b/doc/user/project/integrations/custom_issue_tracker.md
@@ -4,31 +4,40 @@ group: Integrations
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Custom issue tracker service **(FREE)**
+# Custom issue tracker **(FREE)**
-Use a custom issue tracker that is not in the integration list.
+You can integrate an [external issue tracker](../../../integration/external-issue-tracker.md)
+with GitLab. If your preferred issue tracker is not listed in the
+[integrations list](../../../integration/external-issue-tracker.md#integration),
+you can enable a custom issue tracker.
+
+After you enable the custom issue tracker, a link to the issue tracker displays
+on the left sidebar in your project.
+
+![Custom issue tracker link](img/custom_issue_tracker_v14_5.png)
+
+## Enable a custom issue tracker
To enable a custom issue tracker in a project:
-1. Go to the [Integrations page](overview.md#accessing-integrations).
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Integrations**.
1. Select **Custom issue tracker**.
1. Select the checkbox under **Enable integration**.
1. Fill in the required fields:
- **Project URL**: The URL to view all the issues in the custom issue tracker.
- **Issue URL**: The URL to view an issue in the custom issue tracker. The URL must contain `:id`.
- GitLab replaces `:id` with the issue number (for example,
- `https://customissuetracker.com/project-name/:id`, which becomes `https://customissuetracker.com/project-name/123`).
+ GitLab replaces `:id` with the issue number (for example,
+ `https://customissuetracker.com/project-name/:id`, which becomes
+ `https://customissuetracker.com/project-name/123`).
- **New issue URL**:
<!-- The line below was originally added in January 2018: https://gitlab.com/gitlab-org/gitlab/-/commit/778b231f3a5dd42ebe195d4719a26bf675093350 -->
- **This URL is not used and removal is planned in a future release.**
- Enter any URL here.
- For more information, see [issue 327503](https://gitlab.com/gitlab-org/gitlab/-/issues/327503).
-
-1. Select **Save changes** or optionally select **Test settings**.
+ **This URL is not used and an [issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/327503) to remove it.**
+ Enter any URL.
-After you configure and enable the custom issue tracker service, a link appears on the GitLab
-project pages. This link takes you to the custom issue tracker.
+1. Optional. Select **Test settings**.
+1. Select **Save changes**.
## Reference issues in a custom issue tracker
diff --git a/doc/user/project/integrations/github.md b/doc/user/project/integrations/github.md
index 3177aaefb75..47a81594ca9 100644
--- a/doc/user/project/integrations/github.md
+++ b/doc/user/project/integrations/github.md
@@ -37,20 +37,20 @@ Complete these steps in GitLab:
1. Ensure that the **Active** toggle is enabled.
1. Paste the token you generated on GitHub.
1. Enter the path to your project on GitHub, such as `https://github.com/username/repository`.
-1. (Optional) To disable static status check names, clear the **Static status check names** checkbox.
+1. (Optional) To disable static status check names, clear the **Enable static status check names** checkbox.
1. Select **Save changes** or optionally select **Test settings**.
After configuring the integration, see [Pipelines for external pull requests](../../../ci/ci_cd_for_external_repos/#pipelines-for-external-pull-requests)
to configure pipelines to run for open pull requests.
-### Static / dynamic status check names
+### Static or dynamic status check names
> - Introduced in GitLab 11.5: using static status check names as opt-in option.
> - [In GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/issues/9931), static status check names is default behavior for new projects.
This makes it possible to mark these status checks as **Required** on GitHub.
-When **Static status check names** is enabled on the integration page, your
+When **Enable static status check names** is checked on the integration page, your
GitLab instance host name is appended to a status check name.
-When disabled, it uses dynamic status check names and appends the branch name.
+When unchecked, it uses dynamic status check names and appends the branch name.
diff --git a/doc/user/project/integrations/img/custom_issue_tracker_v14_5.png b/doc/user/project/integrations/img/custom_issue_tracker_v14_5.png
new file mode 100644
index 00000000000..e316a2acc39
--- /dev/null
+++ b/doc/user/project/integrations/img/custom_issue_tracker_v14_5.png
Binary files differ
diff --git a/doc/user/project/integrations/img/zentao_product_id.png b/doc/user/project/integrations/img/zentao_product_id.png
new file mode 100644
index 00000000000..a91b4c3f82d
--- /dev/null
+++ b/doc/user/project/integrations/img/zentao_product_id.png
Binary files differ
diff --git a/doc/user/project/integrations/mattermost.md b/doc/user/project/integrations/mattermost.md
index 92e5feefb73..119f219499c 100644
--- a/doc/user/project/integrations/mattermost.md
+++ b/doc/user/project/integrations/mattermost.md
@@ -54,7 +54,7 @@ Then fill in the integration configuration:
To change the bot's username, provide a value.
- **Notify only broken pipelines**: If you enable the **Pipeline** event, and you want
notifications about failed pipelines only.
-- **Branches to be notified**: The branches to send notifications for.
+- **Branches for which notifications are to be sent**: The branches to send notifications for.
- **Labels to be notified**: (Optional) Labels required for the issue or merge request
to trigger a notification. Leave blank to notify for all issues and merge requests.
- **Labels to be notified behavior**: When you use the **Labels to be notified** filter,
diff --git a/doc/user/project/integrations/microsoft_teams.md b/doc/user/project/integrations/microsoft_teams.md
index fac26f8e70c..6679bab745b 100644
--- a/doc/user/project/integrations/microsoft_teams.md
+++ b/doc/user/project/integrations/microsoft_teams.md
@@ -18,8 +18,8 @@ in Microsoft Teams. To integrate the services, you must:
To configure Microsoft Teams to listen for notifications from GitLab:
-1. In Microsoft Teams, search for "incoming webhook" in the search bar, and select the
- **Incoming Webhook** item:
+1. In Microsoft Teams, type `incoming webhook` in the search bar, and select
+ **Incoming Webhook**:
![Select Incoming Webhook](img/microsoft_teams_select_incoming_webhook.png)
@@ -34,11 +34,12 @@ To configure Microsoft Teams to listen for notifications from GitLab:
After you configure Microsoft Teams to receive notifications, you must configure
GitLab to send the notifications:
-1. Sign in to GitLab as a user with [Administrator](../../permissions.md) and go
- to your project's page.
-1. Go to **Settings > Integrations** and select **Microsoft Teams Notification**.
-1. Select **Active** to enable the integration.
-1. Select the checkbox next to each **Trigger** to enable:
+1. Sign in to GitLab as an administrator.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Integrations**.
+1. Select **Microsoft Teams notifications**.
+1. To enable the integration, select **Active**.
+1. In the **Trigger** section, select the checkbox next to each event to enable it:
- Push
- Issue
- Confidential issue
@@ -46,15 +47,15 @@ GitLab to send the notifications:
- Note
- Confidential note
- Tag push
- - Pipeline - If you enable this trigger, you can also select **Notify only broken pipelines** to be notified only about failed pipelines.
+ - Pipeline
- Wiki page
1. In **Webhook**, paste the URL you copied when you
[configured Microsoft Teams](#configure-microsoft-teams).
-1. (Optional) If you enabled the pipeline trigger, you can select the
+1. Optional. If you enable the pipeline trigger, select the
**Notify only broken pipelines** checkbox to push notifications only when pipelines break.
1. Select the branches you want to send notifications for.
-1. Click **Save changes**.
+1. Select **Save changes**.
-## Resources
+## Related topics
- [Setting up an incoming webhook on Microsoft Teams](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using#setting-up-a-custom-incoming-webhook).
diff --git a/doc/user/project/integrations/overview.md b/doc/user/project/integrations/overview.md
index 2c154467115..819c17c12fd 100644
--- a/doc/user/project/integrations/overview.md
+++ b/doc/user/project/integrations/overview.md
@@ -62,6 +62,7 @@ Click on the service links to see further configuration instructions and details
| [Unify Circuit](unify_circuit.md) | Send notifications about project events to Unify Circuit. | **{dotted-circle}** No |
| [Webex Teams](webex_teams.md) | Receive events notifications. | **{dotted-circle}** No |
| [YouTrack](youtrack.md) | Use YouTrack as the issue tracker. | **{dotted-circle}** No |
+| [ZenTao](zentao.md) | Use ZenTao as the issue tracker. | **{dotted-circle}** No |
## Push hooks limit
diff --git a/doc/user/project/integrations/slack.md b/doc/user/project/integrations/slack.md
index a38d2157699..d399c7f2901 100644
--- a/doc/user/project/integrations/slack.md
+++ b/doc/user/project/integrations/slack.md
@@ -45,7 +45,7 @@ to control GitLab from Slack. Slash commands are configured separately.
1. (Optional) In **Username**, enter the username of the Slack bot that sends
the notifications.
1. Select the **Notify only broken pipelines** checkbox to notify only on failures.
-1. In the **Branches to be notified** dropdown, select which types of branches
+1. In the **Branches for which notifications are to be sent** dropdown, select which types of branches
to send notifications for.
1. Leave the **Labels to be notified** field blank to get all notifications, or
add labels that the issue or merge request must have to trigger a
diff --git a/doc/user/project/integrations/unify_circuit.md b/doc/user/project/integrations/unify_circuit.md
index 814c64d8140..daab24a8ab9 100644
--- a/doc/user/project/integrations/unify_circuit.md
+++ b/doc/user/project/integrations/unify_circuit.md
@@ -21,7 +21,7 @@ In GitLab:
1. Select the checkboxes corresponding to the GitLab events you want to receive in Unify Circuit.
1. Paste the **Webhook URL** that you copied from the Unify Circuit configuration step.
1. Select the **Notify only broken pipelines** checkbox to notify only on failures.
-1. In the **Branches to be notified** dropdown, select which types of branches to send notifications for.
+1. In the **Branches for which notifications are to be sent** dropdown, select which types of branches to send notifications for.
1. Select `Save changes` or optionally select **Test settings**.
Your Unify Circuit conversation now starts receiving GitLab event notifications.
diff --git a/doc/user/project/integrations/webhook_events.md b/doc/user/project/integrations/webhook_events.md
index 9b07e6322bc..ab70a2d43f4 100644
--- a/doc/user/project/integrations/webhook_events.md
+++ b/doc/user/project/integrations/webhook_events.md
@@ -9,31 +9,50 @@ info: To determine the technical writer assigned to the Stage/Group associated w
You can configure a [webhook](webhooks.md) in your project that triggers when
an event occurs. The following events are supported.
+Event type | Trigger
+---------------------------------------------|-----------------------------------------------------------------------------
+[Push event](#push-events) | A push is made to the repository.
+[Tag event](#tag-events) | Tags are created or deleted in the repository.
+[Issue event](#issue-events) | A new issue is created or an existing issue is updated, closed, or reopened.
+[Comment event](#comment-events) | A new comment is made on commits, merge requests, issues, and code snippets.
+[Merge request event](#merge-request-events) | A merge request is created, updated, merged, or closed, or a commit is added in the source branch.
+[Wiki page event](#wiki-page-events) | A wiki page is created, updated, or deleted.
+[Pipeline event](#pipeline-events) | A pipeline status changes.
+[Job event](#job-events) | A job status changes.
+[Deployment event](#deployment-events) | A deployment starts, succeeds, fails, or is canceled.
+[Group member event](#group-member-events) | A user is added or removed from a group, or a user's access level or access expiration date changes.
+[Subgroup event](#subgroup-events) | A subgroup is created or removed from a group.
+[Feature flag event](#feature-flag-events) | A feature flag is turned on or off.
+[Release event](#release-events) | A release is created or updated.
+
+NOTE:
+If an author has no public email listed in their
+[GitLab profile](https://gitlab.com/-/profile), the `email` attribute in the
+webhook payload displays a value of `[REDACTED]`.
+
## Push events
-Triggered when you push to the repository except when pushing tags.
+Push events are triggered when you push to the repository, except when:
-NOTE:
-When more than 20 commits are pushed at once, the `commits` webhook
-attribute only contains the newest 20 for performance reasons. Loading
-detailed commit data is expensive. Note that despite only 20 commits being
-present in the `commits` attribute, the `total_commits_count` attribute contains the actual total.
+- You push tags.
+- A single push includes changes for more than three branches by default
+ (depending on the [`push_event_hooks_limit` setting](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls)).
-NOTE:
-If a branch creation push event is generated without new commits being introduced, the
-`commits` attribute in the payload is empty.
+If you push more than 20 commits at once, the `commits`
+attribute in the payload contains information about the newest 20 commits only.
+Loading detailed commit data is expensive, so this restriction exists for performance reasons.
+The `total_commits_count` attribute contains the actual number of commits.
-Also, if a single push includes changes for more than three (by default, depending on
-[`push_event_hooks_limit` setting](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls))
-branches, this hook isn't executed.
+If you create and push a branch without any new commits, the
+`commits` attribute in the payload is empty.
-**Request header**:
+Request header:
```plaintext
X-Gitlab-Event: Push Hook
```
-**Payload example:**
+Payload example:
```json
{
@@ -111,20 +130,19 @@ X-Gitlab-Event: Push Hook
## Tag events
-Triggered when you create (or delete) tags to the repository.
+Tag events are triggered when you create or delete tags in the repository.
-NOTE:
-If a single push includes changes for more than three (by default, depending on
-[`push_event_hooks_limit` setting](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls))
-tags, this hook is not executed.
+This hook is not executed if a single push includes changes for more than three
+tags by default (depending on the
+[`push_event_hooks_limit` setting](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls)).
-**Request header**:
+Request header:
```plaintext
X-Gitlab-Event: Tag Push Hook
```
-**Payload example:**
+Payload example:
```json
{
@@ -171,22 +189,26 @@ X-Gitlab-Event: Tag Push Hook
## Issue events
-Triggered when a new issue is created or an existing issue was updated/closed/reopened.
+Issue events are triggered when a new issue is created or
+an existing issue is updated, closed, or reopened.
-**Request header**:
-
-```plaintext
-X-Gitlab-Event: Issue Hook
-```
-
-**Available `object_attributes.action`:**
+The available values for `object_attributes.action` in the payload are:
- `open`
- `close`
- `reopen`
- `update`
-**Payload example:**
+The `assignee` and `assignee_id` keys are deprecated
+and contain the first assignee only.
+
+Request header:
+
+```plaintext
+X-Gitlab-Event: Issue Hook
+```
+
+Payload example:
```json
{
@@ -329,31 +351,31 @@ X-Gitlab-Event: Issue Hook
}
```
-NOTE:
-`assignee` and `assignee_id` keys are deprecated and now show the first assignee only.
-
## Comment events
-Triggered when a new comment is made on commits, merge requests, issues, and code snippets.
-The note data is stored in `object_attributes` (for example, `note` or `noteable_type`). The
-payload also includes information about the target of the comment. For example,
-a comment on an issue includes the specific issue information under the `issue` key.
-Valid target types:
+Comment events are triggered when a new comment is made on commits,
+merge requests, issues, and code snippets.
+
+The note data is stored in `object_attributes` (for example, `note` or `noteable_type`).
+The payload includes information about the target of the comment. For example,
+a comment on an issue includes specific issue information under the `issue` key.
+
+The valid target types are:
- `commit`
- `merge_request`
- `issue`
- `snippet`
-### Comment on commit
+### Comment on a commit
-**Request header**:
+Request header:
```plaintext
X-Gitlab-Event: Note Hook
```
-**Payload example:**
+Payload example:
```json
{
@@ -428,15 +450,15 @@ X-Gitlab-Event: Note Hook
}
```
-### Comment on merge request
+### Comment on a merge request
-**Request header**:
+Request header:
```plaintext
X-Gitlab-Event: Note Hook
```
-**Payload example:**
+Payload example:
```json
{
@@ -558,15 +580,18 @@ X-Gitlab-Event: Note Hook
}
```
-### Comment on issue
+### Comment on an issue
+
+- The `assignee_id` field is deprecated and shows the first assignee only.
+- The `event_type` is set to `confidential_note` for confidential issues.
-**Request header**:
+Request header:
```plaintext
X-Gitlab-Event: Note Hook
```
-**Payload example:**
+Payload example:
```json
{
@@ -664,21 +689,15 @@ X-Gitlab-Event: Note Hook
}
```
-NOTE:
-`assignee_id` field is deprecated and now shows the first assignee only.
-
-NOTE:
-`event_type` is set to `confidential_note` for confidential issues.
-
-### Comment on code snippet
+### Comment on a code snippet
-**Request header**:
+Request header:
```plaintext
X-Gitlab-Event: Note Hook
```
-**Payload example:**
+Payload example:
```json
{
@@ -749,15 +768,13 @@ X-Gitlab-Event: Note Hook
## Merge request events
-Triggered when a new merge request is created, an existing merge request was updated/merged/closed or a commit is added in the source branch.
+Merge request events are triggered when:
-**Request header**:
+- A new merge request is created.
+- An existing merge request is updated, approved, unapproved, merged, or closed.
+- A commit is added in the source branch.
-```plaintext
-X-Gitlab-Event: Merge Request Hook
-```
-
-**Available `object_attributes.action`:**
+The available values for `object_attributes.action` in the payload are:
- `open`
- `close`
@@ -767,7 +784,13 @@ X-Gitlab-Event: Merge Request Hook
- `unapproved`
- `merge`
-**Payload example:**
+Request header:
+
+```plaintext
+X-Gitlab-Event: Merge Request Hook
+```
+
+Payload example:
```json
{
@@ -921,17 +944,17 @@ X-Gitlab-Event: Merge Request Hook
}
```
-## Wiki Page events
+## Wiki page events
-Triggered when a wiki page is created, updated or deleted.
+Wiki page events are triggered when a wiki page is created, updated, or deleted.
-**Request Header**:
+Request header:
```plaintext
X-Gitlab-Event: Wiki Page Hook
```
-**Payload example**:
+Payload example:
```json
{
@@ -981,18 +1004,18 @@ X-Gitlab-Event: Wiki Page Hook
## Pipeline events
+Pipeline events are triggered when the status of a pipeline changes.
+
In [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53159)
and later, the pipeline webhook returns only the latest jobs.
-Triggered on status change of Pipeline.
-
-**Request Header**:
+Request header:
```plaintext
X-Gitlab-Event: Pipeline Hook
```
-**Payload example**:
+Payload example:
```json
{
@@ -1233,15 +1256,17 @@ X-Gitlab-Event: Pipeline Hook
## Job events
-Triggered on status change of a job.
+Job events are triggered when the status of a job changes.
+
+The `commit.id` in the payload is the ID of the pipeline, not the ID of the commit.
-**Request Header**:
+Request header:
```plaintext
X-Gitlab-Event: Job Hook
```
-**Payload example**:
+Payload example:
```json
{
@@ -1303,24 +1328,24 @@ X-Gitlab-Event: Job Hook
}
```
-Note that `commit.id` is the ID of the pipeline, not the ID of the commit.
-
## Deployment events
-Triggered when a deployment:
+Deployment events are triggered when a deployment:
-- Starts ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41214) in GitLab 13.5.)
+- Starts ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41214) in GitLab 13.5)
- Succeeds
- Fails
- Is cancelled
-**Request Header**:
+The `deployable_id` in the payload is the ID of the CI/CD job.
+
+Request header:
```plaintext
X-Gitlab-Event: Deployment Hook
```
-**Payload example**:
+Payload example:
```json
{
@@ -1363,28 +1388,26 @@ X-Gitlab-Event: Deployment Hook
}
```
-Note that `deployable_id` is the ID of the CI job.
-
## Group member events **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/260347) in GitLab 13.7.
Member events are triggered when:
-- A user is added as a group member
-- The access level of a user has changed
-- The expiration date for user access has been updated
-- A user has been removed from the group
+- A user is added as a group member.
+- The access level of a user changes.
+- The expiration date for user access is updated.
+- A user is removed from the group.
### Add member to group
-**Request Header**:
+Request header:
```plaintext
X-Gitlab-Event: Member Hook
```
-**Payload example**:
+Payload example:
```json
{
@@ -1406,13 +1429,13 @@ X-Gitlab-Event: Member Hook
### Update member access level or expiration date
-**Request Header**:
+Request header:
```plaintext
X-Gitlab-Event: Member Hook
```
-**Payload example**:
+Payload example:
```json
{
@@ -1434,13 +1457,13 @@ X-Gitlab-Event: Member Hook
### Remove member from group
-**Request Header**:
+Request header:
```plaintext
X-Gitlab-Event: Member Hook
```
-**Payload example**:
+Payload example:
```json
{
@@ -1466,18 +1489,18 @@ X-Gitlab-Event: Member Hook
Subgroup events are triggered when:
-- A [subgroup is created in a group](#subgroup-created-in-a-group)
-- A [subgroup is removed from a group](#subgroup-removed-from-a-group)
+- A [subgroup is created in a group](#create-a-subgroup-in-a-group).
+- A [subgroup is removed from a group](#remove-a-subgroup-from-a-group).
-### Subgroup created in a group
+### Create a subgroup in a group
-**Request Header**:
+Request header:
```plaintext
X-Gitlab-Event: Subgroup Hook
```
-**Payload example**:
+Payload example:
```json
{
@@ -1497,15 +1520,17 @@ X-Gitlab-Event: Subgroup Hook
}
```
-### Subgroup removed from a group
+### Remove a subgroup from a group
-**Request Header**:
+This webhook is not triggered when a [subgroup is transferred to a new parent group](../../group/index.md#transfer-a-group).
+
+Request header:
```plaintext
X-Gitlab-Event: Subgroup Hook
```
-**Payload example**:
+Payload example:
```json
{
@@ -1525,20 +1550,17 @@ X-Gitlab-Event: Subgroup Hook
}
```
-NOTE:
-Webhooks for when a [subgroup is removed from a group](#subgroup-removed-from-a-group) are not triggered when a [subgroup is transferred to a new parent group](../../group/index.md#transfer-a-group)
+## Feature flag events
-## Feature Flag events
+Feature flag events are triggered when a feature flag is turned on or off.
-Triggered when a feature flag is turned on or off.
-
-**Request Header**:
+Request header:
```plaintext
X-Gitlab-Event: Feature Flag Hook
```
-**Payload example**:
+Payload example:
```json
{
@@ -1580,20 +1602,20 @@ X-Gitlab-Event: Feature Flag Hook
## Release events
-Triggered when a release is created or updated.
+Release events are triggered when a release is created or updated.
-**Request Header**:
+The available values for `object_attributes.action` in the payload are:
+
+- `create`
+- `update`
+
+Request header:
```plaintext
X-Gitlab-Event: Release Hook
```
-**Available `object_attributes.action`:**
-
-- `create`
-- `update`
-
-**Payload example**:
+Payload example:
```json
{
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index 0891d48c038..e0405955d3d 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -40,8 +40,14 @@ including:
## Group webhooks **(PREMIUM)**
-You can configure a webhook for a group to ensure all projects in the group
-receive the same webhook settings.
+You can configure a group webhook, which is triggered by events
+that occur across all projects in the group.
+
+Group webhooks can also be configured to listen for events that are
+specific to a group, including:
+
+- [Group member events](webhook_events.md#group-member-events)
+- [Subgroup events](webhook_events.md#subgroup-events)
## Configure a webhook
diff --git a/doc/user/project/integrations/zentao.md b/doc/user/project/integrations/zentao.md
new file mode 100644
index 00000000000..67125c3ebbf
--- /dev/null
+++ b/doc/user/project/integrations/zentao.md
@@ -0,0 +1,42 @@
+---
+stage: Ecosystem
+group: Integrations
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# ZenTao product integration **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/338178) in GitLab 14.5.
+
+[ZenTao](https://www.zentao.net/) is a web-based project management platform.
+
+## Configure ZenTao
+
+This integration requires a ZenTao API secret key.
+
+Complete these steps in ZenTao:
+
+1. Go to your **Admin** page and select **Develop > Application**.
+1. Select **Add Application**.
+1. Under **Name** and **Code**, enter a name and a code for the new secret key.
+1. Under **Account**, select an existing account name.
+1. Select **Save**.
+1. Copy the generated key to use in GitLab.
+
+## Configure GitLab
+
+Complete these steps in GitLab:
+
+1. Go to your project and select **Settings > Integrations**.
+1. Select **ZenTao**.
+1. Turn on the **Active** toggle under **Enable Integration**.
+1. Provide the ZenTao configuration information:
+ - **ZenTao Web URL**: The base URL of the ZenTao instance web interface you're linking to this GitLab project (for example, `example.zentao.net`).
+ - **ZenTao API URL** (optional): The base URL to the ZenTao instance API. Defaults to the Web URL value if not set.
+ - **ZenTao API token**: Use the key you generated when you [configured ZenTao](#configure-zentao).
+ - **ZenTao Product ID**: To display issues from a single ZenTao product in a given GitLab project. The Product ID can be found in the ZenTao product page under **Settings > Overview**.
+
+ ![ZenTao settings page](img/zentao_product_id.png)
+
+1. To verify the ZenTao connection is working, select **Test settings**.
+1. Select **Save changes**.
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index 8a599608f71..4c35f007fc7 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -197,21 +197,22 @@ card includes:
Users with the [Reporter and higher roles](../permissions.md) can use all the functionality of the
issue board feature to create or delete lists. They can also drag issues from one list to another.
-## How GitLab orders issues in a list
-
-When visiting a board, issues appear ordered in any list. You're able to change
-that order by dragging the issues. The changed order is saved, so that anybody who visits the same
-board later sees the reordering, with some exceptions.
+## Ordering issues in a list
When an issue is created, the system assigns a relative order value that is greater than the maximum value
of that issue's project or root group. This means the issue will be at the bottom of any issue list that
it appears in.
+When you visit a board, issues appear ordered in any list. You're able to change
+that order by dragging the issues. The changed order is saved, so that anybody who visits the same
+board later sees the reordering, with some exceptions.
+
Any time you drag and reorder the issue, its relative order value changes accordingly.
Then, any time that issue appears in any board, the ordering is done according to
the updated relative order value. If a user in your GitLab instance
drags issue `A` above issue `B`, the ordering is maintained when these two issues are subsequently
-loaded in any board in the same instance. This could be a different project board or a different group
+loaded in any board in the same instance.
+This could be a different project board or a different group
board, for example.
This ordering also affects [issue lists](issues/sorting_issue_lists.md).
@@ -593,7 +594,7 @@ You can move issues and lists by dragging them.
Prerequisites:
-- A minimum of [Reporter](../permissions.md#project-members-permissions) access to a project in GitLab.
+- You must have at least the Reporter [role](../permissions.md#project-members-permissions) for a project in GitLab.
To move an issue, select the issue card and drag it to another position in its current list or
into a different list. Learn about possible effects in [Dragging issues between lists](#dragging-issues-between-lists).
diff --git a/doc/user/project/issues/associate_zoom_meeting.md b/doc/user/project/issues/associate_zoom_meeting.md
index e020bdee737..aba8c45699c 100644
--- a/doc/user/project/issues/associate_zoom_meeting.md
+++ b/doc/user/project/issues/associate_zoom_meeting.md
@@ -25,7 +25,7 @@ In an issue, leave a comment using the `/zoom` quick action followed by a valid
/zoom https://zoom.us/j/123456789
```
-If the Zoom meeting URL is valid and you have at least [Reporter permissions](../../permissions.md),
+If the Zoom meeting URL is valid and you have at least the Reporter [role](../../permissions.md),
a system alert notifies you of its successful addition.
The issue's description is automatically edited to include the Zoom link, and a button
appears right under the issue's title.
@@ -44,5 +44,5 @@ Similarly to adding a Zoom meeting, you can remove it with a quick action:
/remove_zoom
```
-If you have at least [Reporter permissions](../../permissions.md),
+If you have at least the Reporter [role](../../permissions.md),
a system alert notifies you that the meeting URL was successfully removed.
diff --git a/doc/user/project/issues/confidential_issues.md b/doc/user/project/issues/confidential_issues.md
index 136e8ee2ebb..b8a01f7ccd6 100644
--- a/doc/user/project/issues/confidential_issues.md
+++ b/doc/user/project/issues/confidential_issues.md
@@ -77,14 +77,14 @@ that prevent leaks of private data.
There are two kinds of level access for confidential issues. The general rule
is that confidential issues are visible only to members of a project with at
-least [Reporter access](../../permissions.md#project-members-permissions). However, a guest user can also create
+least the Reporter [role](../../permissions.md#project-members-permissions). However, a guest user can also create
confidential issues, but can only view the ones that they created themselves.
Confidential issues are also hidden in search results for unprivileged users.
-For example, here's what a user with the [Maintainer role](../../permissions.md) and Guest access
+For example, here's what a user with the [Maintainer role](../../permissions.md) and the Guest role
sees in the project's search results respectively.
-| Maintainer role | Guest access |
+| Maintainer role | Guest role |
|:---------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------|
| ![Confidential issues search by maintainer](img/confidential_issues_search_master.png) | ![Confidential issues search by guest](img/confidential_issues_search_guest.png) |
diff --git a/doc/user/project/issues/due_dates.md b/doc/user/project/issues/due_dates.md
index 94a5fdc3f0f..2c20ccdcee0 100644
--- a/doc/user/project/issues/due_dates.md
+++ b/doc/user/project/issues/due_dates.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Due dates **(FREE)**
Due dates can be used in [issues](index.md) to keep track of deadlines and make sure features are
-shipped on time. Users need at least [Reporter permissions](../../permissions.md)
+shipped on time. Users need at least the Reporter [role](../../permissions.md)
to be able to edit the due date. All users with permission to view
the issue can view the due date.
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index 9842b0820e6..64838b261ce 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -49,3 +49,4 @@ To learn how the GitLab Strategic Marketing department uses GitLab issues with [
- [Issues API](../../../api/issues.md)
- [Configure an external issue tracker](../../../integration/external-issue-tracker.md)
- [Parts of an issue](issue_data_and_actions.md)
+- [Tasks](../../tasks.md)
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index a2fa044be6b..6b3d5d6563a 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -380,12 +380,18 @@ You can also use the `/iteration`
[quick action](../quick_actions.md#issues-merge-requests-and-epics)
in a comment or description field.
-## Real-time sidebar **(FREE SELF)**
+## Real-time sidebar
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17589) in GitLab 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17589) in GitLab 13.3. Disabled by default.
+> - [Enabled on GitLab.com](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/3413) in GitLab 13.9.
+> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/17589) in GitLab 14.5.
-Assignees in the sidebar are updated in real time. This feature is **disabled by default**.
-To enable it, you need to enable [Action Cable in-app mode](https://docs.gitlab.com/omnibus/settings/actioncable.html).
+FLAG:
+On self-managed GitLab, by default this feature is available. To hide the feature per project or for your entire instance, ask an administrator to
+[disable the feature flags](../../../administration/feature_flags.md) named `real_time_issue_sidebar` and `broadcast_issue_updates`.
+On GitLab.com, this feature is available.
+
+Assignees in the sidebar are updated in real time.
## Similar issues
diff --git a/doc/user/project/issues/sorting_issue_lists.md b/doc/user/project/issues/sorting_issue_lists.md
index aed346fb504..ebfc723280f 100644
--- a/doc/user/project/issues/sorting_issue_lists.md
+++ b/doc/user/project/issues/sorting_issue_lists.md
@@ -8,34 +8,59 @@ info: To determine the technical writer assigned to the Stage/Group associated w
You can sort a list of issues several ways, including by:
-- Blocking **(PREMIUM)**
-- Created date
-- Due date
-- Label priority
-- Last updated
-- Milestone due date
-- Popularity
-- Priority
-- Title ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67234) in GitLab 14.3)
-- Weight
+- [Blocking issues](#sorting-by-blocking-issues)
+- [Created date](#sorting-by-created-date)
+- [Due date](#sorting-by-due-date)
+- [Label priority](#sorting-by-label-priority)
+- [Last updated](#sorting-by-last-updated)
+- [Manual sorting](#manual-sorting)
+- [Milestone due date](#sorting-by-milestone-due-date)
+- [Popularity](#sorting-by-popularity)
+- [Priority](#sorting-by-priority)
+- [Title](#sorting-by-title)
+- [Weight](#sorting-by-weight)
The available sorting options can change based on the context of the list.
-For sorting by issue priority, see [Label Priority](../labels.md#label-priority).
-In group and project issue lists, it is also possible to order issues manually,
-similar to [issue boards](../issue_board.md#how-gitlab-orders-issues-in-a-list).
+## Sorting by blocking issues **(PREMIUM)**
-## Sorting by popularity
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34247/) in GitLab 13.7.
-When you select sorting by **Popularity**, the issue order changes to sort descending by the
-number of upvotes ([awarded](../../award_emojis.md) "thumbs up" emoji)
-on each issue. You can use this to identify issues that are in high demand.
+When you sort by **Blocking**, the issue list changes to sort descending by the
+number of issues each issue is blocking.
+
+## Sorting by created date
+
+When you sort by **Created date**, the issue list changes to sort descending by the issue
+creation date. Issues created most recently are first.
+
+## Sorting by due date
+
+When you sort by **Due date**, the issue list changes to sort ascending by the issue
+[due date](issue_data_and_actions.md#due-date). Issues with the earliest due date are first,
+and issues without a due date are last.
+
+## Sorting by label priority
+
+When you sort by **Label priority**, the issue list changes to sort descending.
+Issues with the highest priority label are first, then all other issues.
+
+Ties are broken arbitrarily. Only the highest prioritized label is checked,
+and labels with a lower priority are ignored.
+For more information, see [issue 14523](https://gitlab.com/gitlab-org/gitlab/-/issues/14523).
+
+To learn more about priority labels, read the [Labels](../labels.md#label-priority) documentation.
+
+## Sorting by last updated
+
+When you sort by **Last updated**, the issue list changes to sort by the time of a last
+update. Issues changed the most recently are first.
## Manual sorting
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62178) in GitLab 12.2.
-When you select **Manual** sorting, you can change
+When you sort by **Manual** order, you can change
the order by dragging and dropping the issues. The changed order persists, and
everyone who visits the same list sees the updated issue order, with some exceptions.
@@ -48,13 +73,47 @@ the updated relative order value is used for the ordering.
So, if anyone drags issue `A` above issue `B` in your GitLab instance,
this ordering is maintained whenever they appear together in any list.
-This ordering also affects [issue boards](../issue_board.md#how-gitlab-orders-issues-in-a-list).
+This ordering also affects [issue boards](../issue_board.md#ordering-issues-in-a-list).
Changing the order in an issue list changes the ordering in an issue board,
-and vice versa.
+and the other way around.
-## Sorting by blocking issues **(PREMIUM)**
+## Sorting by milestone due date
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34247/) in GitLab 13.7.
+When you sort by **Milestone due date**, the issue list changes to sort ascending by the
+assigned milestone due date. Issues with milestones with the earliest due date are first,
+then issues with a milestone without a due date.
+
+## Sorting by popularity
+
+When you sort by **Popularity**, the issue order changes to sort descending by the
+number of upvotes ([awarded](../../award_emojis.md) a "thumbs up" emoji)
+on each issue. You can use this to identify issues that are in high demand.
+
+## Sorting by priority
+
+When you sort by **Priority**, the issue order changes to sort in this order:
+
+1. Issues with milestones that have due dates, where the soonest assigned milestone is listed first.
+1. Issues with milestones with no due dates.
+1. Issues with a higher priority label.
+1. Issues without a prioritized label.
+
+To learn more about priority, read the [Labels](../labels.md#label-priority) documentation.
+
+## Sorting by title
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67234) in GitLab 14.3.
+
+When you sort by **Title**, the issue order changes to sort alphabetically by the issue
+title in this order:
+
+- Emoji
+- Special characters
+- Numbers
+- Letters: first Latin, then accented (for example, `ö`)
+
+## Sorting by weight
-When you select to sort by **Blocking**, the issue list changes to sort descending by the
-number of issues each issue is blocking. You can use this to determine the critical path for your backlog.
+When you sort by **Weight**, the issue list changes to sort ascending by the
+[issue weight](issue_weight.md).
+Issues with lowest weight are first, and issues without a weight are last.
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index f9788ef18ec..adf0a115c6e 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -120,8 +120,8 @@ To remove a member from a project:
1. Optional. In the confirmation box, select the
**Also unassign this user from related issues and merge requests** checkbox.
1. To prevent leaks of sensitive information from private projects, verify the
- user has not forked the private repository. Existing forks continue to receive
- changes from the upstream project. You may also want to configure your project
+ user has not forked the private repository or created webhooks. Existing forks continue to receive
+ changes from the upstream project, and webhooks continue to receive updates. You may also want to configure your project
to prevent projects in a group
[from being forked outside their group](../../group/index.md#prevent-project-forking-outside-group).
1. Select **Remove member**.
diff --git a/doc/user/project/merge_requests/accessibility_testing.md b/doc/user/project/merge_requests/accessibility_testing.md
index 2bc6d5bb148..8f803f9207c 100644
--- a/doc/user/project/merge_requests/accessibility_testing.md
+++ b/doc/user/project/merge_requests/accessibility_testing.md
@@ -21,6 +21,9 @@ measuring the accessibility of web sites, and has built a simple
This job outputs accessibility violations, warnings, and notices for each page
analyzed to a file called `accessibility`.
+From [GitLab 14.5](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73309), the version of `pa11y` uses
+[WCAG 2.1 rules](https://www.w3.org/TR/WCAG21/#new-features-in-wcag-2-1), which may report more issues.
+
## Accessibility merge request widget
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39425) in GitLab 13.0 behind the disabled [feature flag](../../../administration/feature_flags.md) `:accessibility_report_view`.
diff --git a/doc/user/project/merge_requests/approvals/index.md b/doc/user/project/merge_requests/approvals/index.md
index aff55419a88..d873f715557 100644
--- a/doc/user/project/merge_requests/approvals/index.md
+++ b/doc/user/project/merge_requests/approvals/index.md
@@ -3,7 +3,7 @@ stage: Create
group: Source Code
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
type: reference, concepts
-disqus_identifier: 'https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html'
+disqus_identifier: 'https://docs.gitlab.com/ee/user/project/merge_requests/approvals/index.html'
---
# Merge request approvals **(FREE)**
diff --git a/doc/user/project/merge_requests/approvals/rules.md b/doc/user/project/merge_requests/approvals/rules.md
index b422982c0e7..1249aa826fa 100644
--- a/doc/user/project/merge_requests/approvals/rules.md
+++ b/doc/user/project/merge_requests/approvals/rules.md
@@ -167,7 +167,7 @@ for protected branches. **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40491) in GitLab 13.4.
> - Moved to GitLab Premium in 13.9.
-You may need to grant users with [Reporter permissions](../../../permissions.md#project-members-permissions),
+You may have to grant users with the Reporter [role](../../../permissions.md#project-members-permissions)
permission to approve merge requests before they can merge to a protected branch.
Some users (like managers) may not need permission to push or merge code, but still need
oversight on proposed work. To enable approval permissions for these users without
diff --git a/doc/user/project/merge_requests/approvals/settings.md b/doc/user/project/merge_requests/approvals/settings.md
index 1c56e91ed6b..56e93741c1a 100644
--- a/doc/user/project/merge_requests/approvals/settings.md
+++ b/doc/user/project/merge_requests/approvals/settings.md
@@ -39,7 +39,7 @@ By default, the author of a merge request cannot approve it. To change this sett
1. Go to your project and select **Settings > General**.
1. Expand **Merge request (MR) approvals**.
-1. Clear the **Prevent MR approval by the author** checkbox.
+1. Clear the **Prevent approval by author** checkbox.
1. Select **Save changes**.
Authors can edit the approval rule in an individual merge request and override
@@ -64,14 +64,20 @@ their own. To do this:
1. Go to your project and select **Settings > General**.
1. Expand **Merge request (MR) approvals**.
-1. Select the **Prevent MR approvals from users who make commits to the MR** checkbox.
+1. Select the **Prevent approvals by users who add commits** checkbox.
If this checkbox is cleared, an administrator has disabled it
[at the instance level](../../../admin_area/merge_requests_approvals.md), and
it can't be changed at the project level.
1. Select **Save changes**.
-Even with this configuration, [code owners](../../code_owners.md) who contribute
-to a merge request can approve merge requests that affect files they own.
+Depending on your version of GitLab, [code owners](../../code_owners.md) who commit
+to a merge request may or may not be able to approve the work:
+
+- In GitLab 13.10 and earlier, [code owners](../../code_owners.md) who commit
+ to a merge request can approve it, even if the merge request affects files they own.
+- In [GitLab 13.11 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/331548),
+ [code owners](../../code_owners.md) who commit
+ to a merge request cannot approve it, when the merge request affects files they own.
To learn more about the [differences between authors and committers](https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History),
read the official Git documentation for an explanation.
@@ -84,7 +90,7 @@ on merge requests, you can disable this setting:
1. Go to your project and select **Settings > General**.
1. Expand **Merge request (MR) approvals**.
-1. Select the **Prevent users from modifying MR approval rules in merge requests** checkbox.
+1. Select the **Prevent editing approval rules in merge requests** checkbox.
1. Select **Save changes**.
This change affects all open merge requests.
@@ -102,7 +108,7 @@ permission enables an electronic signature for approvals, such as the one define
[sign-in restrictions documentation](../../../admin_area/settings/sign_in_restrictions.md#password-authentication-enabled).
1. Go to your project and select **Settings > General**.
1. Expand **Merge request (MR) approvals**.
-1. Select the **Require user password for approvals** checkbox.
+1. Select the **Require user password to approve** checkbox.
1. Select **Save changes**.
## Remove all approvals when commits are added to the source branch
@@ -113,7 +119,7 @@ when more changes are added to it:
1. Go to your project and select **Settings > General**.
1. Expand **Merge request (MR) approvals**.
-1. Select the **Require new approvals when new commits are added to an MR** checkbox.
+1. Select the **Remove all approvals when commits are added to the source branch** checkbox.
1. Select **Save changes**.
Approvals aren't reset when a merge request is [rebased from the UI](../fast_forward_merge.md)
@@ -133,21 +139,23 @@ coverage.
To learn more, see [Coverage check approval rule](../../../../ci/pipelines/settings.md#coverage-check-approval-rule).
-## Merge request approval settings cascading
+## Settings cascading
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285410) in GitLab 14.4. [Deployed behind the `group_merge_request_approval_settings_feature_flag` flag](../../../../administration/feature_flags.md), disabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285410) in GitLab 14.4. [Deployed behind the `group_merge_request_approval_settings_feature_flag` flag](../../../../administration/feature_flags.md), disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/285410) in GitLab 14.5.
FLAG:
-On self-managed GitLab, by default this feature is not available. To make it available per group, ask an administrator to [enable the `group_merge_request_approval_settings_feature_flag` flag](../../../../administration/feature_flags.md). On GitLab.com, this feature is not available.
-You should not use this feature for production environments
+On self-managed GitLab, by default this feature is available. To hide the feature per group, ask an administrator to [disable the feature flag](../../../../administration/feature_flags.md) named `group_merge_request_approval_settings_feature_flag`. On GitLab.com, this feature is available.
You can also enforce merge request approval settings:
-- At the [instance level](../../../admin_area/merge_requests_approvals.md), which apply to all groups on an instance and, therefore, all
- projects.
-- On a [top-level group](../../../group/index.md#group-approval-rules), which apply to all subgroups and projects.
+- At the [instance level](../../../admin_area/merge_requests_approvals.md), which apply to all groups
+ on an instance and, therefore, all projects.
+- On a [top-level group](../../../group/index.md#group-approval-rules), which apply to all subgroups
+ and projects.
-If the settings are inherited by a group or project, they cannot be overridden by the group or project that inherited them.
+If the settings are inherited by a group or project, they cannot be changed in the group or project
+that inherited them.
## Related links
diff --git a/doc/user/project/merge_requests/authorization_for_merge_requests.md b/doc/user/project/merge_requests/authorization_for_merge_requests.md
index 339f67f828f..4ae59a76a9a 100644
--- a/doc/user/project/merge_requests/authorization_for_merge_requests.md
+++ b/doc/user/project/merge_requests/authorization_for_merge_requests.md
@@ -40,7 +40,7 @@ protected branch.
## Forking workflow
With the forking workflow, maintainers get the [Maintainer role](../../permissions.md) and regular
-developers get Reporter access to the authoritative repository, which prohibits
+developers get the Reporter role on the authoritative repository, which prohibits
them from pushing any changes to it.
Developers create forks of the authoritative project and push their feature
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
index e9f1874eb96..9bfbbd8fc6f 100644
--- a/doc/user/project/merge_requests/code_quality.md
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -343,8 +343,7 @@ It's possible to have a custom tool provide Code Quality reports in GitLab. To
do this:
1. Define a job in your `.gitlab-ci.yml` file that generates the
- [Code Quality report
- artifact](../../../ci/yaml/index.md#artifactsreportscodequality).
+ [Code Quality report artifact](../../../ci/yaml/index.md#artifactsreportscodequality).
1. Configure your tool to generate the Code Quality report artifact as a JSON
file that implements a subset of the [Code Climate
spec](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#data-types).
diff --git a/doc/user/project/merge_requests/commit_templates.md b/doc/user/project/merge_requests/commit_templates.md
new file mode 100644
index 00000000000..b615c86288c
--- /dev/null
+++ b/doc/user/project/merge_requests/commit_templates.md
@@ -0,0 +1,51 @@
+---
+stage: Create
+group: Code Review
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference, howto
+---
+
+# Commit message templates **(FREE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20263) in GitLab 14.5.
+
+## Merge commit message template
+
+As a project maintainer, you're able to configure merge commit message template. It will be used during merge to
+create commit message. Template uses similar syntax to
+[review suggestions](reviews/suggestions.md#configure-the-commit-message-for-applied-suggestions).
+
+Default merge commit message can be recreated using following template:
+
+```plaintext
+Merge branch '%{source_branch}' into '%{target_branch}'
+
+%{title}
+
+%{issues}
+
+See merge request %{reference}
+```
+
+This commit message can be customized to follow any guidelines you might have.
+To do so, expand the **Merge requests** tab within your project's **General**
+settings and change the **Merge commit message template** text:
+
+![Custom commit message for applied suggestions](img/merge_commit_message_template_v14_5.png)
+
+You can use static text and following variables:
+
+| Variable | Description | Output example |
+|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------|
+| `%{source_branch}` | The name of the branch that is being merged. | `my-feature-branch` |
+| `%{target_branch}` | The name of the branch that the changes are applied to. | `master` |
+| `%{title}` | Title of the merge request. | Fix stuff |
+| `%{issues}` | String with phrase "Closes <issue numbers>" with all issues mentioned in the MR description matching [issue closing patterns](../issues/managing_issues.md#closing-issues-automatically). It will be empty when no issues were mentioned. | `Closes #465, #190 and #400` |
+| `%{description}` | Description of the merge request. | Merge request description.<br>Can be multiline. |
+| `%{reference}` | Reference to the merge request. | group-name/project-name!72359 |
+
+NOTE:
+Empty variables that are the only word in a line will be removed along with all newline characters preceding it.
+
+Merge commit template field has a limit of 500 characters. This limit only applies to the template
+itself.
diff --git a/doc/user/project/merge_requests/conflicts.md b/doc/user/project/merge_requests/conflicts.md
new file mode 100644
index 00000000000..dc128f89fcd
--- /dev/null
+++ b/doc/user/project/merge_requests/conflicts.md
@@ -0,0 +1,177 @@
+---
+stage: Create
+group: Code Review
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference, concepts
+---
+
+# Merge conflicts **(FREE)**
+
+_Merge conflicts_ happen when the two branches in a merge request (the source and target) each have different
+changes, and you must decide which change to accept. In a merge request, Git compares
+the two versions of the files line by line. In most cases, GitLab can merge changes
+together. However, if two branches both change the same lines, GitLab blocks the merge,
+and you must choose which change you want to keep.
+
+A merge request cannot merge until you either:
+
+- Create a merge commit.
+- Resolve the conflict through a rebase.
+
+![Merge request widget](img/merge_request_widget.png)
+
+## Conflicts you can resolve in the user interface
+
+If your merge conflict meets all of the following conditions, you can resolve the
+merge conflict in the GitLab user interface:
+
+- The file is text, not binary.
+- The file is in a UTF-8 compatible encoding.
+- The file does not already contain conflict markers.
+- The file, with conflict markers added, is less than 200 KB in size.
+- The file exists under the same path in both branches.
+
+If any file in your merge request contains conflicts, but can't meet all of these
+criteria, you must resolve the conflict manually.
+
+## Conflicts GitLab can't detect
+
+GitLab does not detect conflicts when both branches rename a file to different names.
+For example, these changes don't create a conflict:
+
+1. On branch `a`, doing `git mv example.txt example1.txt`
+1. On branch `b`, doing `git mv example1.txt example3.txt`.
+
+When these branches merge, both `example1.txt` and `example3.txt` are present.
+
+## Methods of resolving conflicts
+
+GitLab shows [conflicts available for resolution](#conflicts-you-can-resolve-in-the-user-interface)
+in the user interface, and you can also resolve conflicts locally through the command line:
+
+- [Interactive mode](#resolve-conflicts-in-interactive-mode): UI method best for
+ conflicts that only require you to select which version of a line to keep, without edits.
+- [Inline editor](#resolve-conflicts-in-the-inline-editor): UI method best for more complex conflicts that require you to
+ edit lines and manually blend changes together.
+- [Command line](#resolve-conflicts-from-the-command-line): provides complete control over the most complex conflicts.
+
+## Resolve conflicts in interactive mode
+
+To resolve less-complex conflicts from the GitLab user interface:
+
+1. Go to your merge request.
+1. Select **Overview**, and scroll to the merge request reports section.
+1. Find the merge conflicts message, and select **Resolve conflicts**.
+ GitLab shows a list of files with merge conflicts. The conflicts are
+ highlighted:
+
+ ![Conflict section](img/conflict_section.png)
+1. For each conflict, select **Use ours** or **Use theirs** to mark the version
+ of the conflicted lines you want to keep. This decision is known as
+ "resolving the conflict."
+1. Enter a **Commit message**.
+1. Select **Commit to source branch**.
+
+Resolving conflicts merges the target branch of the merge request into the
+source branch, using the version of the text you chose. If the source branch is
+`feature` and the target branch is `main`, these actions are similar to running
+`git checkout feature; git merge main` locally.
+
+## Resolve conflicts in the inline editor
+
+Some merge conflicts are more complex, requiring you to manually modify lines to
+resolve their conflicts. Use the merge conflict resolution editor to resolve complex
+conflicts in the GitLab interface:
+
+1. Go to your merge request.
+1. Select **Overview**, and scroll to the merge request reports section.
+1. Find the merge conflicts message, and select **Resolve conflicts**.
+ GitLab shows a list of files with merge conflicts.
+1. Select **Edit inline** to open the editor:
+ ![Merge conflict editor](img/merge_conflict_editor.png)
+1. After you resolve the conflict, enter a **Commit message**.
+1. Select **Commit to source branch**.
+
+## Resolve conflicts from the command line
+
+While most conflicts can be resolved through the GitLab user interface, some are too complex.
+Complex conflicts are best fixed locally, from the command line, to give you the
+most control over each change:
+
+1. Open the terminal and check out your feature branch. For example, `my-feature-branch`:
+
+ ```shell
+ git checkout my-feature-branch
+ ```
+
+1. [Rebase your branch](../../../topics/git/git_rebase.md#regular-rebase) against the
+ target branch (here, `main`) so Git prompts you with the conflicts:
+
+ ```shell
+ git fetch
+ git rebase origin/main
+ ```
+
+1. Open the conflicting file in your preferred code editor.
+1. Find the conflict block:
+ - It begins with the marker: `<<<<<<< HEAD`.
+ - Next, it displays your changes.
+ - The marker `=======` indicates the end of your changes.
+ - Next, it displays the latest changes in the target branch.
+ - The marker `>>>>>>>` indicates the end of the conflict.
+1. Edit the file:
+ 1. Choose which version (before or after `=======`) you want to keep.
+ 1. Delete the version you don't want to keep.
+ 1. Delete the conflict markers.
+1. Save the file.
+1. Repeat the process for each file that contains conflicts.
+1. Stage your changes in Git:
+
+ ```shell
+ git add .
+ ```
+
+1. Commit your changes:
+
+ ```shell
+ git commit -m "Fix merge conflicts"
+ ```
+
+1. Continue the rebase:
+
+ ```shell
+ git rebase --continue
+ ```
+
+ WARNING:
+ Up to this point, you can run `git rebase --abort` to stop the process.
+ Git aborts the rebase and rolls back the branch to the state you had before
+ running `git rebase`.
+ After you run `git rebase --continue`, you cannot abort the rebase.
+
+1. [Force-push](../../../topics/git/git_rebase.md#force-push) the changes to your
+ remote branch.
+
+## Merge commit strategy
+
+GitLab resolves conflicts by creating a merge commit in the source branch, but
+does not merge it into the target branch. You can then review and test the
+merge commit. Verify it contains no unintended changes and doesn't break your build.
+
+## Related topics
+
+- [Introduction to Git rebase and force-push](../../../topics/git/git_rebase.md).
+- [Git GUI apps](https://git-scm.com/downloads/guis) to help you visualize the
+ differences between branches and resolve them.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/fast_forward_merge.md b/doc/user/project/merge_requests/fast_forward_merge.md
index 7edc379399b..078f8048900 100644
--- a/doc/user/project/merge_requests/fast_forward_merge.md
+++ b/doc/user/project/merge_requests/fast_forward_merge.md
@@ -38,6 +38,8 @@ Now, when you visit the merge request page, you can accept it
If a fast-forward merge is not possible but a conflict free rebase is possible,
a rebase button is offered.
+The rebase action is also available as a [quick action command: `/rebase`](../../../topics/git/git_rebase.md#rebase-from-the-gitlab-ui).
+
![Fast forward merge request](img/ff_merge_rebase.png)
If the target branch is ahead of the source branch and a conflict free rebase is
diff --git a/doc/user/project/merge_requests/getting_started.md b/doc/user/project/merge_requests/getting_started.md
index cee4df1f61e..006e6d4a8aa 100644
--- a/doc/user/project/merge_requests/getting_started.md
+++ b/doc/user/project/merge_requests/getting_started.md
@@ -172,11 +172,6 @@ is set for deletion, the merge request widget displays the
> - [Disabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/320902) in GitLab 13.9.
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/320895) GitLab 13.10.
-FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature,
-ask an administrator to
-[disable the `retarget_merge_requests` flag](../../../administration/feature_flags.md).
-
In specific circumstances, GitLab can retarget the destination branch of
open merge request, if the destination branch merges while the merge request is
open. Merge requests are often chained in this manner, with one merge request
diff --git a/doc/user/project/merge_requests/img/merge_commit_message_template_v14_5.png b/doc/user/project/merge_requests/img/merge_commit_message_template_v14_5.png
new file mode 100644
index 00000000000..f18ca640d38
--- /dev/null
+++ b/doc/user/project/merge_requests/img/merge_commit_message_template_v14_5.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_request_tab_position_v13_11.png b/doc/user/project/merge_requests/img/merge_request_tab_position_v13_11.png
deleted file mode 100644
index 52c715840f1..00000000000
--- a/doc/user/project/merge_requests/img/merge_request_tab_position_v13_11.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/project_merge_requests_list_view_v13_5.png b/doc/user/project/merge_requests/img/project_merge_requests_list_view_v13_5.png
deleted file mode 100644
index 625d47b1142..00000000000
--- a/doc/user/project/merge_requests/img/project_merge_requests_list_view_v13_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index 2c062c2c592..54b97eb5732 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -17,75 +17,50 @@ Merge requests include:
- A comment section for discussion threads.
- The list of commits.
-To get started, read the [introduction to merge requests](getting_started.md).
+Read more about [how to get started](getting_started.md).
-## Merge request tabs
+## View merge requests
-Merge requests contain tabs at the top of the page to help you navigate to
-important parts of the merge request:
+You can view merge requests for your project, group, or yourself.
-![Merge request tab positions](img/merge_request_tab_position_v13_11.png)
+### View merge requests for a project
-- **Overview**: Contains the description, notifications from pipelines, and a
- discussion area for [comment threads](../../discussions/index.md#resolve-a-thread)
- and [code suggestions](reviews/suggestions.md). The right sidebar provides fields
- to add assignees, reviewers, labels, and a milestone to your work, and the
- [merge request widgets area](widgets.md) reports results from pipelines and tests.
-- **Commits**: Contains a list of commits added to this merge request. For more
- information, read [Commits tab in merge requests](commits.md).
-- **Pipelines**: If configured, contains a list of recent [GitLab CI/CD](../../../ci/index.md)
- pipelines and their status.
-- **Changes**: Contains the diffs of files changed by this merge request. You can
- [configure the display](changes.md).
+To view all merge requests for a project:
-## View merge requests
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Merge requests**.
+
+Or, to use a [keyboard shortcut](../../shortcuts.md), press <kbd>g</kbd> + <kbd>m</kbd>.
+
+### View merge requests for all projects in a group
-To view a list of merge requests:
+To view merge requests for all projects in a group:
-- **Merge requests for a project**: Go to your project and select **Merge requests**, or use
- the <kbd>g</kbd> + <kbd>m</kbd> [keyboard shortcut](../../shortcuts.md) from a page in your project.
-- **All projects in a group**: Go to your group and select **Merge requests**.
- If your group contains subgroups, this view also displays merge requests from the subgroup projects.
- GitLab displays a count of open merge requests in the left sidebar, but
- [caches the value](reviews/index.md#cached-merge-request-count) for groups with a large number of
- open merge requests.
-- **Merge requests assigned to you**: On any GitLab page, select **Merge requests**
- in the top bar, or use the <kbd>Shift</kbd> + <kbd>m</kbd>
- [global keyboard shortcut](../../shortcuts.md).
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Merge requests**.
-GitLab displays open merge requests, with tabs to filter the list by open and closed status:
+If your group contains subgroups, this view also displays merge requests from the subgroup projects.
-![Project merge requests list view](img/project_merge_requests_list_view_v13_5.png)
+## View all merge requests assigned to you
+
+To view all merge requests assigned to you:
+
+1. On the top bar, put your cursor in the **Search** box.
+1. From the dropdown list, select **Merge requests assigned to me**.
+
+Or, to use a [keyboard shortcut](../../shortcuts.md), press <kbd>Shift</kbd> + <kbd>m</kbd>.
You can [search and filter](../../search/index.md#filter-issue-and-merge-request-lists),
the results, or select a merge request to begin a review.
-## Merge request sidebar
-
-The **Overview** tab of a merge request displays a sidebar. In this sidebar, you
-can assign, categorize, and track progress on a merge request:
-
-- [**Assignee**](getting_started.md#assignee): Designate the directly responsible
- individual (DRI) for a merge request. With
- [multiple assignees](getting_started.md#multiple-assignees), you can assign a
- merge request to more than one person at a time.
-- [**Reviewer**](reviews/index.md): Designate a team member to review a merge request.
- Higher tiers can assign multiple reviewers, and [require approvals](approvals/index.md)
- from these reviewers.
-- [**Milestone**](../milestones/index.md): Track time-sensitive changes.
-- [**Time tracking**](../time_tracking.md): Time spent on a merge request.
-- [**Labels**](../labels.md): Categorize a merge request and display it on
- appropriate [issue boards](../issue_board.md).
-- **Participants**: A list of users participating or watching a merge request.
-- [**Notifications**](../../profile/notifications.md): A toggle to select whether
- or not to receive notifications for updates to a merge request.
-
## Add changes to a merge request
If you have permission to add changes to a merge request, you can add your changes
-to an existing merge request in several ways, depending on the complexity of your change and whether you need access to a development environment:
+to an existing merge request in several ways, depending on the complexity of your
+change and whether you need access to a development environment:
-- [Edit changes in the Web IDE](../web_ide/index.md) in your browser. Use this
+- [Edit changes in the Web IDE](../web_ide/index.md) in your browser with the
+ <kbd>.</kbd> [keyboard shortcut](../../shortcuts.md). Use this
browser-based method to edit multiple files, or if you are not comfortable with Git commands.
You cannot run tests from the Web IDE.
- [Edit changes in Gitpod](../../../integration/gitpod.md#launch-gitpod-in-gitlab), if you
@@ -158,3 +133,7 @@ For a web developer writing a webpage for your company's website:
- [Authorization for merge requests](authorization_for_merge_requests.md)
- [Testing and reports](testing_and_reports_in_merge_requests.md)
- [GitLab keyboard shortcuts](../../shortcuts.md)
+- [Comments and threads](../../discussions/index.md)
+- [Suggest code changes](reviews/suggestions.md)
+- [Commits](commits.md)
+- [CI/CD pipelines](../../../ci/index.md)
diff --git a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
index d7c9c0f73ee..256dde4fa17 100644
--- a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
+++ b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
@@ -101,7 +101,7 @@ for details on avoiding two pipelines for a single merge request.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211482) in GitLab 13.1.
-When the **Pipelines must succeed** checkbox is checked, [skipped pipelines](../../../ci/yaml/index.md#skip-pipeline) prevent
+When the **Pipelines must succeed** checkbox is checked, [skipped pipelines](../../../ci/pipelines/index.md#skip-a-pipeline) prevent
merge requests from being merged. To change this behavior:
1. Navigate to your project's **Settings > General** page.
diff --git a/doc/user/project/merge_requests/resolve_conflicts.md b/doc/user/project/merge_requests/resolve_conflicts.md
index 4681ef09388..611f37a949b 100644
--- a/doc/user/project/merge_requests/resolve_conflicts.md
+++ b/doc/user/project/merge_requests/resolve_conflicts.md
@@ -1,85 +1,9 @@
---
-stage: Create
-group: Code Review
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: reference, concepts
+redirect_to: 'conflicts.md'
+remove_date: '2022-01-26'
---
-# Merge request conflict resolution **(FREE)**
+This document was moved to [another location](conflicts.md).
-Merge conflicts occur when two branches have different changes that cannot be
-merged automatically.
-
-Git can merge changes between branches in most cases, but
-occasionally Git requires your assistance to resolve the
-conflicts manually. Typically, this is necessary when people change the same
-parts of the same files.
-
-GitLab prevents merge requests from being merged until all conflicts are
-resolved. Conflicts can be resolved locally, or in many cases in GitLab
-(see [conflicts available for resolution](#conflicts-available-for-resolution)
-for information on when this is available).
-
-![Merge request widget](img/merge_request_widget.png)
-
-NOTE:
-GitLab resolves conflicts by creating a merge commit in the source branch that
-is not automatically merged into the target branch. The merge
-commit can be reviewed and tested before the changes are merged. This prevents
-unintended changes entering the target branch without review or breaking the
-build.
-
-## Resolve conflicts: interactive mode
-
-Clicking **Resolve Conflicts** displays a list of files with conflicts, with conflict sections
-highlighted:
-
-![Conflict section](img/conflict_section.png)
-
-After all conflicts have been marked as using 'ours' or 'theirs', the conflict
-can be resolved. Resolving conflicts merges the target branch of the merge
-request into the source branch, using the options
-chosen. If the source branch is `feature` and the target branch is `main`,
-this is similar to performing `git checkout feature; git merge main` locally.
-
-## Resolve conflicts: inline editor
-
-Some merge conflicts are more complex, requiring you to manually modify a file to
-resolve them. Use the merge conflict resolution editor to resolve complex
-conflicts in the GitLab interface. Click **Edit inline** to open the editor.
-After you're sure about your changes, click **Commit to source branch**.
-
-![Merge conflict editor](img/merge_conflict_editor.png)
-
-## Conflicts available for resolution
-
-GitLab allows resolving conflicts in a file where all of the below are true:
-
-- The file is text, not binary
-- The file is in a UTF-8 compatible encoding
-- The file does not already contain conflict markers
-- The file, with conflict markers added, is not over 200 KB in size
-- The file exists under the same path in both branches
-
-If any file in your merge request containing conflicts can't meet all of these
-criteria, you can't resolve the merge conflict in the UI.
-
-Additionally, GitLab does not detect conflicts in renames away from a path. For
-example, this does not create a conflict:
-
-1. On branch `a`, doing `git mv file1 file2`
-1. On branch `b`, doing `git mv file1 file3`.
-
-Instead, both files are present in the branch after the merge request is merged.
-
-<!-- ## Troubleshooting
-
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask.
-
-Each scenario can be a third-level heading, e.g. `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
+<!-- This redirect file can be deleted after <2022-01-26>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/merge_requests/reviews/index.md b/doc/user/project/merge_requests/reviews/index.md
index e6f84f1c357..597dcb3dfb9 100644
--- a/doc/user/project/merge_requests/reviews/index.md
+++ b/doc/user/project/merge_requests/reviews/index.md
@@ -17,6 +17,10 @@ your merge request, and makes [code suggestions](suggestions.md) you can accept
from the user interface. When your work is reviewed, your team members can choose
to accept or reject it.
+You can review merge requests from the GitLab interface. If you install the
+[GitLab Workflow VS Code extension](../../repository/vscode.md), you can also
+review merge requests in Visual Studio Code.
+
## Review a merge request
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4213) in GitLab Premium 11.4.
@@ -207,7 +211,7 @@ These features are associated with merge requests:
When viewing the commit details page, GitLab links to the merge request(s) containing that commit.
- [Merge requests versions](../versions.md):
Select and compare the different versions of merge request diffs
-- [Resolve conflicts](../resolve_conflicts.md):
+- [Resolve conflicts](../conflicts.md):
GitLab can provide the option to resolve certain merge request conflicts in the GitLab UI.
- [Revert changes](../revert_changes.md):
Revert changes from any commit from a merge request.
diff --git a/doc/user/project/merge_requests/reviews/suggestions.md b/doc/user/project/merge_requests/reviews/suggestions.md
index ac1cd57fb99..7bfb8e52279 100644
--- a/doc/user/project/merge_requests/reviews/suggestions.md
+++ b/doc/user/project/merge_requests/reviews/suggestions.md
@@ -7,14 +7,13 @@ type: index, reference
# Suggest changes **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/18008) in GitLab 11.6.
-> - Custom commit messages for suggestions was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25381) in GitLab 13.9 behind a [feature flag](../../../feature_flags.md), disabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25381) custom commit messages for suggestions in GitLab 13.9 [with a flag](../../../../administration/feature_flags.md) named `suggestions_custom_commit`. Disabled by default.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/297404) in GitLab 13.10.
As a reviewer, you're able to suggest code changes with a Markdown syntax in merge request
diff threads. Then, the merge request author (or other users with appropriate
-[permission](../../../permissions.md)) is able to apply these suggestions with a click,
-which generates a commit in the merge request authored by the user that suggested the changes.
+[permission](../../../permissions.md)) can apply these suggestions with a click.
+This action generates a commit in the merge request, authored by the user that suggested the changes.
1. Choose a line of code to be changed, add a new comment, then select
the **Insert suggestion** icon in the toolbar:
@@ -38,14 +37,15 @@ which generates a commit in the merge request authored by the user that suggeste
![Custom commit](img/custom_commit_v13_9.png)
-After the author applies a suggestion, it's marked with the **Applied** label,
-the thread is automatically resolved, and GitLab creates a new commit
-and pushes the suggested change directly into the codebase in the merge request's
-branch. The [Developer role](../../../permissions.md) is required to do so.
+After the author applies a suggestion:
-## Multi-line suggestions
+1. The suggestion is marked as **Applied**.
+1. The thread is resolved.
+1. GitLab creates a new commit with the changes.
+1. If the user has the [Developer role](../../../permissions.md), GitLab pushes
+ the suggested change directly into the codebase in the merge request's branch.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53310) in GitLab 11.10.
+## Multi-line suggestions
Reviewers can also suggest changes to multiple lines with a single suggestion
within merge request diff threads by adjusting the range offsets. The
@@ -67,9 +67,9 @@ suggestion.
## Code block nested in suggestions
-If you need to make a suggestion that involves a
-[fenced code block](../../../markdown.md#code-spans-and-blocks), wrap your suggestion in four backticks
-instead of the usual three.
+To add a suggestion that includes a
+[fenced code block](../../../markdown.md#code-spans-and-blocks), wrap your suggestion
+in four backticks instead of three:
![A comment editor with a suggestion with a fenced code block](img/suggestion_code_block_editor_v12_8.png)
@@ -95,14 +95,14 @@ You can also use following variables besides static text:
| Variable | Description | Output example |
|------------------------|-------------|----------------|
-| `%{branch_name}` | The name of the branch the suggestion(s) was(were) applied to. | `my-feature-branch` |
-| `%{files_count}` | The number of file(s) to which suggestion(s) was(were) applied.| **2** |
-| `%{file_paths}` | The path(s) of the file(s) suggestion(s) was(were) applied to. Paths are separated by commas.| `docs/index.md, docs/about.md` |
+| `%{branch_name}` | The name of the branch to which suggestions were applied. | `my-feature-branch` |
+| `%{files_count}` | The number of files to which suggestions were applied.| **2** |
+| `%{file_paths}` | The paths of the file to which suggestions were applied. Paths are separated by commas.| `docs/index.md, docs/about.md` |
| `%{project_path}` | The project path. | `my-group/my-project` |
| `%{project_name}` | The human-readable name of the project. | **My Project** |
| `%{suggestions_count}` | The number of suggestions applied.| **3** |
-| `%{username}` | The username of the user applying suggestion(s). | `user_1` |
-| `%{user_full_name}` | The full name of the user applying suggestion(s). | **User 1** |
+| `%{username}` | The username of the user applying suggestions. | `user_1` |
+| `%{user_full_name}` | The full name of the user applying suggestions. | **User 1** |
For example, to customize the commit message to output
**Addresses user_1's review**, set the custom text to
@@ -114,32 +114,32 @@ introduced by [#25381](https://gitlab.com/gitlab-org/gitlab/-/issues/25381).
## Batch suggestions
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25486) in GitLab 13.1 as an [alpha feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha) behind a feature flag, disabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25486) in GitLab 13.1 as an [alpha feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha) with a flag named `batch_suggestions`, disabled by default.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/227799) in GitLab 13.2.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/320755) in GitLab 13.11.
-> - Custom commit messages for batch suggestions [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326168) in GitLab 14.4.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/320755) in GitLab 13.11. [Feature flag `batch_suggestions`](https://gitlab.com/gitlab-org/gitlab/-/issues/320755) removed.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326168) custom commit messages for batch suggestions in GitLab 14.4.
You can apply multiple suggestions at once to reduce the number of commits added
to your branch to address your reviewers' requests.
1. To start a batch of suggestions to apply with a single commit, select **Add suggestion to batch**:
- ![A code change suggestion displayed, with the button to add the suggestion to a batch highlighted.](img/add_first_suggestion_to_batch_v13_1.jpg "Add a suggestion to a batch")
+ ![A code change suggestion displayed, with the add-suggestion option highlighted.](img/add_first_suggestion_to_batch_v13_1.jpg "Add a suggestion to a batch")
1. Add as many additional suggestions to the batch as you wish:
- ![A code change suggestion displayed, with the button to add an additional suggestion to a batch highlighted.](img/add_another_suggestion_to_batch_v13_1.jpg "Add another suggestion to a batch")
+ ![A code change suggestion displayed, with the add-more suggestion option highlighted.](img/add_another_suggestion_to_batch_v13_1.jpg "Add another suggestion to a batch")
1. To remove suggestions, select **Remove from batch**:
- ![A code change suggestion displayed, with the button to remove that suggestion from its batch highlighted.](img/remove_suggestion_from_batch_v13_1.jpg "Remove a suggestion from a batch")
+ ![A code change suggestion displayed, with the option to remove that suggestion from its batch highlighted.](img/remove_suggestion_from_batch_v13_1.jpg "Remove a suggestion from a batch")
1. Having added all the suggestions to your liking, when ready, select **Apply suggestions**. You
can optionally specify a custom commit message for [batch suggestions](#batch-suggestions)
(GitLab 14.4 and later) to describe your change. If you don't specify it, the default commit
message is used.
- ![A code change suggestion displayed, with the button to apply the batch of suggestions highlighted.](img/apply_batch_of_suggestions_v13_1.jpg "Apply a batch of suggestions")
+ ![A code change suggestion displayed, with the option to apply the batch of suggestions highlighted.](img/apply_batch_of_suggestions_v13_1.jpg "Apply a batch of suggestions")
WARNING:
Suggestions applied from multiple authors creates a commit authored by the user applying the suggestions.
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md
index 27487003697..ee4320d5ea1 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md
@@ -27,6 +27,17 @@ and steps below.
- Access to your domain's server control panel to set up DNS records:
- A DNS A or CNAME record pointing your domain to GitLab Pages server.
- A DNS `TXT` record to verify your domain's ownership.
+- Set either `external_http` or `external_https` in `/etc/gitlab/gitlab.rb` to the IP and port of
+ your [Pages Daemon](../../../../administration/pages/index.md#overview).
+ If you don't have IPv6, you can omit the IPv6 address.
+
+ Example:
+
+ ```ruby
+ # Redirect pages from HTTP to HTTPS
+ gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001:db8::2]:80'] # The secondary IPs for the GitLab Pages daemon
+ gitlab_pages['external_https'] = ['192.0.2.2:443', '[2001:db8::2]:443'] # The secondary IPs for the GitLab Pages daemon
+ ```
### Steps
diff --git a/doc/user/project/pages/getting_started/pages_ci_cd_template.md b/doc/user/project/pages/getting_started/pages_ci_cd_template.md
index 4f2b62beab1..25382778b1d 100644
--- a/doc/user/project/pages/getting_started/pages_ci_cd_template.md
+++ b/doc/user/project/pages/getting_started/pages_ci_cd_template.md
@@ -13,31 +13,16 @@ the CI/CD pipeline to generate a Pages website.
Use a `.gitlab-ci.yml` template when you have an existing project that you want to add a Pages site to.
-Your GitLab repository should contain files specific to an SSG, or plain HTML.
-After you complete these steps, you may need to do additional
-configuration for the Pages site to generate properly.
-
-1. On the left sidebar, select **Project information**.
-1. Click **Set up CI/CD**.
-
- ![setup GitLab CI/CD](../img/setup_ci_v13_1.png)
-
- If this button is not available, CI/CD is already configured for
- your project. You may want to browse the `.gitlab-ci.yml` files
- [in these projects instead](https://gitlab.com/pages).
-
-1. From the **Apply a template** list, choose a template for the SSG you're using.
- You can also choose plain HTML.
-
- ![gitlab-ci templates](../img/choose_ci_template_v13_1.png)
-
- If you don't find a corresponding template, you can view the
- [GitLab Pages group of sample projects](https://gitlab.com/pages).
- These projects contain `.gitlab-ci.yml` files that you can modify for your needs.
- You can also [learn how to write your own `.gitlab-ci.yml`
- file for GitLab Pages](pages_from_scratch.md).
-
-1. Save and commit the `.gitlab-ci.yml` file.
+Your GitLab repository should contain files specific to an SSG, or plain HTML. After you complete
+these steps, you may have to do additional configuration for the Pages site to generate properly.
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select the project's name.
+1. From the **Add** (**{plus}**) dropdown, select **New file**.
+1. From the **Select a template type** dropdown, select `.gitlab-ci.yml`.
+1. From the **Apply a template** dropdown, in the **Pages** section, select the name of your SSG.
+1. In the **Commit message** box, type the commit message.
+1. Select **Commit changes**.
If everything is configured correctly, the site can take approximately 30 minutes to deploy.
diff --git a/doc/user/project/pages/img/choose_ci_template_v13_1.png b/doc/user/project/pages/img/choose_ci_template_v13_1.png
deleted file mode 100644
index a0c25ba1642..00000000000
--- a/doc/user/project/pages/img/choose_ci_template_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/img/setup_ci_v13_1.png b/doc/user/project/pages/img/setup_ci_v13_1.png
deleted file mode 100644
index 2cf1c05d6d8..00000000000
--- a/doc/user/project/pages/img/setup_ci_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index 45c2f1aaf04..59a2f0c2eba 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -223,16 +223,13 @@ Consider a Pages site deployed with the following files:
```plaintext
public/
-├─┬ index.html
-│ ├ data.html
-│ └ info.html
-│
+├── index.html
+├── data.html
+├── info.html
├── data/
│ └── index.html
-├── info/
-│ └── details.html
-└── other/
- └── index.html
+└── info/
+ └── details.html
```
Pages supports reaching each of these files through several different URLs. In
@@ -241,23 +238,19 @@ specifies the directory. If the URL references a file that doesn't exist, but
adding `.html` to the URL leads to a file that *does* exist, it's served
instead. Here are some examples of what happens given the above Pages site:
-| URL path | HTTP response | File served |
-| -------------------- | ------------- | ----------- |
-| `/` | `200 OK` | `public/index.html` |
-| `/index.html` | `200 OK` | `public/index.html` |
-| `/index` | `200 OK` | `public/index.html` |
-| `/data` | `200 OK` | `public/data/index.html` |
-| `/data/` | `200 OK` | `public/data/index.html` |
-| `/data.html` | `200 OK` | `public/data.html` |
-| `/info` | `200 OK` | `public/info.html` |
-| `/info/` | `200 OK` | `public/info.html` |
-| `/info.html` | `200 OK` | `public/info.html` |
-| `/info/details` | `200 OK` | `public/info/details.html` |
-| `/info/details.html` | `200 OK` | `public/info/details.html` |
-| `/other` | `302 Found` | `public/other/index.html` |
-| `/other/` | `200 OK` | `public/other/index.html` |
-| `/other/index` | `200 OK` | `public/other/index.html` |
-| `/other/index.html` | `200 OK` | `public/other/index.html` |
+| URL path | HTTP response |
+| -------------------- | ------------- |
+| `/` | `200 OK`: `public/index.html` |
+| `/index.html` | `200 OK`: `public/index.html` |
+| `/index` | `200 OK`: `public/index.html` |
+| `/data` | `302 Found`: redirecting to `/data/` |
+| `/data/` | `200 OK`: `public/data/index.html` |
+| `/data.html` | `200 OK`: `public/data.html` |
+| `/info` | `302 Found`: redirecting to `/info/` |
+| `/info/` | `404 Not Found` Error Page |
+| `/info.html` | `200 OK`: `public/info.html` |
+| `/info/details` | `200 OK`: `public/info/details.html` |
+| `/info/details.html` | `200 OK`: `public/info/details.html` |
Note that when `public/data/index.html` exists, it takes priority over the `public/data.html` file
for both the `/data` and `/data/` URL paths.
diff --git a/doc/user/project/push_options.md b/doc/user/project/push_options.md
index 305bbb2ded0..15df69ee68c 100644
--- a/doc/user/project/push_options.md
+++ b/doc/user/project/push_options.md
@@ -69,8 +69,8 @@ time as pushing changes:
| `merge_request.milestone="<milestone>"` | Set the milestone of the merge request. Ex: `git push -o merge_request.milestone="3.0"`. | [14.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63960) |
| `merge_request.label="<label>"` | Add labels to the merge request. If the label does not exist, it is created. For example, for two labels: `git push -o merge_request.label="label1" -o merge_request.label="label2"`. | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) |
| `merge_request.unlabel="<label>"` | Remove labels from the merge request. For example, for two labels: `git push -o merge_request.unlabel="label1" -o merge_request.unlabel="label2"`. | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) |
-| `merge_request.assign="<user>"` | Assign users to the merge request. For example, for two users: `git push -o merge_request.assign="user1" -o merge_request.assign="user2"`. | [13.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25904) |
-| `merge_request.unassign="<user>"` | Remove assigned users from the merge request. For example, for two users: `git push -o merge_request.unassign="user1" -o merge_request.unassign="user2"`. | [13.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25904) |
+| `merge_request.assign="<user>"` | Assign users to the merge request. Accepts username or user ID. For example, for two users: `git push -o merge_request.assign="user1" -o merge_request.assign="user2"`. | [13.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25904) |
+| `merge_request.unassign="<user>"` | Remove assigned users from the merge request. Accepts username or user ID.For example, for two users: `git push -o merge_request.unassign="user1" -o merge_request.unassign="user2"`. | [13.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25904) |
If you use a push option that requires text with spaces in it, you need to enclose it
in quotes (`"`). You can omit the quotes if there are no spaces. Some examples:
@@ -117,3 +117,13 @@ pipeline succeeds:
```shell
git mwps origin <local-branch-name>
```
+
+## Troubleshooting
+
+## Push options for merge request assignment ignored
+
+When you push a branch to GitLab, you can use push options to assign to (`merge_request.assign="<USERNAME>"`)
+or unassign from (`merge_request.unassign="<USERNAME>"`) a user. If GitLab creates
+the merge request successfully, but fails to assign or unassign the merge request
+correctly, you can use the user ID instead. For more information, read the issue
+[Push option `merge_request.(un)assign` seems to be ignored](https://gitlab.com/gitlab-org/gitlab/-/issues/325169).
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 45a83394c41..a4d7b94506b 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -78,6 +78,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/move <path/to/project>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Move this issue to another project. |
| `/parent_epic <epic>` | **{dotted-circle}** No | **{dotted-circle}** No | **{check-circle}** Yes | Set parent epic to `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic ([introduced in GitLab 12.1](https://gitlab.com/gitlab-org/gitlab/-/issues/10556)). |
| `/promote` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Promote issue to epic. |
+| `/promote_to_incident` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Promote issue to incident ([introduced in GitLab 14.5](https://gitlab.com/gitlab-org/gitlab/-/issues/296787)). |
| `/publish` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Publish issue to an associated [Status Page](../../operations/incident_management/status_page.md) ([Introduced in GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30906)) |
| `/reassign @user1 @user2` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Replace current assignees with those specified. |
| `/rebase` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Rebase source branch. This schedules a background task that attempts to rebase the changes in the source branch on the latest commit of the target branch. If `/rebase` is used, `/merge` is ignored to avoid a race condition where the source branch is merged or deleted before it is rebased. If there are merge conflicts, GitLab displays a message that a rebase cannot be scheduled. Rebase failures are displayed with the merge request status. |
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index 9e4d621dbc6..abedae5d10b 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -78,17 +78,172 @@ To create a new release through the GitLab UI:
[release notes](#release-notes-description), or [assets links](#links).
1. Click **Create release**.
-### Create release from GitLab CI
+## Create a release by using a CI/CD job
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19298) in GitLab 12.7.
-You can [create a release directly from the GitLab CI pipeline](../../../ci/yaml/index.md#release)
-by using a `release` node in the job definition.
+You can create a release directly as part of the GitLab CI/CD pipeline
+by using [the `release` keyword](../../../ci/yaml/index.md#release) in the job definition.
The release is created only if the job processes without error. If the Rails API returns an error
during release creation, the release job fails.
-### Upcoming releases
+### CI/CD example of the `release` keyword
+
+To create a release when you push a Git tag, or when you add a Git tag
+in the UI by going to **Repository > Tags**:
+
+```yaml
+release_job:
+ stage: release
+ image: registry.gitlab.com/gitlab-org/release-cli:latest
+ rules:
+ - if: $CI_COMMIT_TAG # Run this job when a tag is created manually
+ script:
+ - echo 'running release_job'
+ release:
+ name: 'Release $CI_COMMIT_TAG'
+ description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION must be defined
+ tag_name: '$CI_COMMIT_TAG' # elsewhere in the pipeline.
+ ref: '$CI_COMMIT_TAG'
+ milestones:
+ - 'm1'
+ - 'm2'
+ - 'm3'
+ released_at: '2020-07-15T08:00:00Z' # Optional, is auto generated if not defined, or can use a variable.
+ assets: # Optional, multiple asset links
+ links:
+ - name: 'asset1'
+ url: 'https://example.com/assets/1'
+ - name: 'asset2'
+ url: 'https://example.com/assets/2'
+ filepath: '/pretty/url/1' # optional
+ link_type: 'other' # optional
+```
+
+To create a release automatically when commits are pushed or merged to the default branch,
+using a new Git tag that is defined with variables:
+
+```yaml
+prepare_job:
+ stage: prepare # This stage must run before the release stage
+ rules:
+ - if: $CI_COMMIT_TAG
+ when: never # Do not run this job when a tag is created manually
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
+ script:
+ - echo "EXTRA_DESCRIPTION=some message" >> variables.env # Generate the EXTRA_DESCRIPTION and TAG environment variables
+ - echo "TAG=v$(cat VERSION)" >> variables.env # and append to the variables.env file
+ artifacts:
+ reports:
+ dotenv: variables.env # Use artifacts:reports:dotenv to expose the variables to other jobs
+
+release_job:
+ stage: release
+ image: registry.gitlab.com/gitlab-org/release-cli:latest
+ needs:
+ - job: prepare_job
+ artifacts: true
+ rules:
+ - if: $CI_COMMIT_TAG
+ when: never # Do not run this job when a tag is created manually
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
+ script:
+ - echo 'running release_job for $TAG'
+ release:
+ name: 'Release $TAG'
+ description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION and the $TAG
+ tag_name: '$TAG' # variables must be defined elsewhere
+ ref: '$CI_COMMIT_SHA' # in the pipeline. For example, in the
+ milestones: # prepare_job
+ - 'm1'
+ - 'm2'
+ - 'm3'
+ released_at: '2020-07-15T08:00:00Z' # Optional, is auto generated if not defined, or can use a variable.
+ assets:
+ links:
+ - name: 'asset1'
+ url: 'https://example.com/assets/1'
+ - name: 'asset2'
+ url: 'https://example.com/assets/2'
+ filepath: '/pretty/url/1' # optional
+ link_type: 'other' # optional
+```
+
+NOTE:
+Environment variables set in `before_script` or `script` are not available for expanding
+in the same job. Read more about
+[potentially making variables available for expanding](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6400).
+
+### Use a custom SSL CA certificate authority
+
+You can use the `ADDITIONAL_CA_CERT_BUNDLE` CI/CD variable to configure a custom SSL CA certificate authority,
+which is used to verify the peer when the `release-cli` creates a release through the API using HTTPS with custom certificates.
+The `ADDITIONAL_CA_CERT_BUNDLE` value should contain the
+[text representation of the X.509 PEM public-key certificate](https://tools.ietf.org/html/rfc7468#section-5.1)
+or the `path/to/file` containing the certificate authority.
+For example, to configure this value in the `.gitlab-ci.yml` file, use the following:
+
+```yaml
+release:
+ variables:
+ ADDITIONAL_CA_CERT_BUNDLE: |
+ -----BEGIN CERTIFICATE-----
+ MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
+ ...
+ jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
+ -----END CERTIFICATE-----
+ script:
+ - echo "Create release"
+ release:
+ name: 'My awesome release'
+ tag_name: '$CI_COMMIT_TAG'
+```
+
+The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a
+[custom variable in the UI](../../../ci/variables/index.md#custom-cicd-variables),
+either as a `file`, which requires the path to the certificate, or as a variable,
+which requires the text representation of the certificate.
+
+### `release-cli` command line
+
+The entries under the `release` node are transformed into a `bash` command line and sent
+to the Docker container, which contains the [release-cli](https://gitlab.com/gitlab-org/release-cli).
+You can also call the `release-cli` directly from a `script` entry.
+
+For example, if you use the YAML described previously:
+
+```shell
+release-cli create --name "Release $CI_COMMIT_SHA" --description "Created using the release-cli $EXTRA_DESCRIPTION" --tag-name "v${MAJOR}.${MINOR}.${REVISION}" --ref "$CI_COMMIT_SHA" --released-at "2020-07-15T08:00:00Z" --milestone "m1" --milestone "m2" --milestone "m3" --assets-link "{\"name\":\"asset1\",\"url\":\"https://example.com/assets/1\",\"link_type\":\"other\"}
+```
+
+### Create multiple releases in a single pipeline
+
+A pipeline can have multiple `release` jobs, for example:
+
+```yaml
+ios-release:
+ script:
+ - echo 'iOS release job'
+ release:
+ tag_name: v1.0.0-ios
+ description: 'iOS release v1.0.0'
+
+android-release:
+ script:
+ - echo 'Android release job'
+ release:
+ tag_name: v1.0.0-android
+ description: 'Android release v1.0.0'
+```
+
+### Release assets as Generic packages
+
+You can use [Generic packages](../../packages/generic_packages/index.md) to host your release assets.
+For a complete example, see the [Release assets as Generic packages](https://gitlab.com/gitlab-org/release-cli/-/tree/master/docs/examples/release-assets-as-generic-package/)
+project.
+
+## Upcoming releases
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/38105) in GitLab 12.1.
@@ -238,14 +393,6 @@ The release title can be customized using the **Release title** field when
creating or editing a release. If no title is provided, the release's tag name
is used instead.
-Guest users of private projects are allowed to view the **Releases** page
-but are _not_ allowed to view details about the Git repository (in particular,
-tag names). Because of this, release titles are replaced with a generic
-title like "Release-1234" for Guest users to avoid leaking tag name information.
-
-See the [Release permissions](#release-permissions) section for
-more information about permissions.
-
### Tag name
The release tag name should include the release version. GitLab uses [Semantic Versioning](https://semver.org/)
@@ -569,11 +716,14 @@ In the API:
### View a release and download assets
-- Users with [Reporter role or above](../../../user/permissions.md#project-members-permissions)
+> [Changes were made to the Guest role access](https://gitlab.com/gitlab-org/gitlab/-/issues/335209) in GitLab 14.5.
+
+- Users with the [Reporter role or above](../../../user/permissions.md#project-members-permissions)
+ have read and download access to the project releases.
+- Users with the [Guest role](../../../user/permissions.md#project-members-permissions)
have read and download access to the project releases.
-- Users with [Guest role](../../../user/permissions.md#project-members-permissions)
- have read and download access to the project releases, however,
- repository-related information are redacted (for example the Git tag name).
+ This includes associated Git-tag-names, release description, author information of the releases.
+ However, other repository-related information, such as [source code](#source-code), [release evidence](#release-evidence) are redacted.
### Create, update, and delete a release and its assets
diff --git a/doc/user/project/releases/release_cli.md b/doc/user/project/releases/release_cli.md
new file mode 100644
index 00000000000..c23ceaa1aba
--- /dev/null
+++ b/doc/user/project/releases/release_cli.md
@@ -0,0 +1,76 @@
+---
+type: reference, howto
+stage: Release
+group: Release
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Install the `release-cli` for the Shell executor
+
+> - [Introduced](https://gitlab.com/gitlab-org/release-cli/-/issues/21) in GitLab 13.8.
+> - [Changed](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/108) in GitLab 14.2, the `release-cli` binaries are also [available in the Package Registry](https://gitlab.com/jaime/release-cli/-/packages).
+
+When you use a runner with the Shell executor, you can download and install
+the `release-cli` manually for your [supported OS and architecture](https://release-cli-downloads.s3.amazonaws.com/latest/index.html).
+Once installed, [the `release` keyword](../../../ci/yaml/index.md#release) is available to use in your CI/CD jobs.
+
+## Install on Unix/Linux
+
+1. Download the binary for your system from S3, in the following example for amd64 systems:
+
+ ```shell
+ curl --location --output /usr/local/bin/release-cli "https://release-cli-downloads.s3.amazonaws.com/latest/release-cli-linux-amd64"
+ ```
+
+ Or from the GitLab Package Registry:
+
+ ```shell
+ curl --location --output /usr/local/bin/release-cli "https://gitlab.com/api/v4/projects/gitlab-org%2Frelease-cli/packages/generic/release-cli/latest/release-cli-darwin-amd64"
+ ```
+
+1. Give it permissions to execute:
+
+ ```shell
+ sudo chmod +x /usr/local/bin/release-cli
+ ```
+
+1. Verify `release-cli` is available:
+
+ ```shell
+ $ release-cli -v
+
+ release-cli version 0.6.0
+ ```
+
+## Install on Windows PowerShell
+
+1. Create a folder somewhere in your system, for example `C:\GitLab\Release-CLI\bin`
+
+ ```shell
+ New-Item -Path 'C:\GitLab\Release-CLI\bin' -ItemType Directory
+ ```
+
+1. Download the executable file:
+
+ ```shell
+ PS C:\> Invoke-WebRequest -Uri "https://release-cli-downloads.s3.amazonaws.com/latest/release-cli-windows-amd64.exe" -OutFile "C:\GitLab\Release-CLI\bin\release-cli.exe"
+
+ Directory: C:\GitLab\Release-CLI
+ Mode LastWriteTime Length Name
+ ---- ------------- ------ ----
+ d----- 3/16/2021 4:17 AM bin
+ ```
+
+1. Add the directory to your `$env:PATH`:
+
+ ```shell
+ $env:PATH += ";C:\GitLab\Release-CLI\bin"
+ ```
+
+1. Verify `release-cli` is available:
+
+ ```shell
+ PS C:\> release-cli -v
+
+ release-cli version 0.6.0
+ ```
diff --git a/doc/user/project/repository/branches/default.md b/doc/user/project/repository/branches/default.md
index 5cd025f017d..bc6bc799670 100644
--- a/doc/user/project/repository/branches/default.md
+++ b/doc/user/project/repository/branches/default.md
@@ -167,7 +167,7 @@ changed, GitLab records the name of the old default branch. If that branch is
deleted, attempts to view a file or directory on it are redirected to the
current default branch, instead of displaying the "not found" page.
-## Resources
+## Related topics
- [Configure a default branch for your wiki](../../wiki/index.md)
- [Discussion of default branch renaming](https://lore.kernel.org/git/pull.656.v4.git.1593009996.gitgitgadget@gmail.com/)
diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md
index 23d7aecc960..6aa32b1b816 100644
--- a/doc/user/project/repository/gpg_signed_commits/index.md
+++ b/doc/user/project/repository/gpg_signed_commits/index.md
@@ -39,7 +39,10 @@ For a commit to be verified by GitLab:
- The committer's public key must have been uploaded to their GitLab
account.
- One of the emails in the GPG key must match a **verified** email address
- used by the committer in GitLab.
+ used by the committer in GitLab. This address will be part of the public key.
+ If you want to keep this address private, use the automatically generated
+ [private commit email address](../../../profile/index.md#use-an-automatically-generated-private-commit-email)
+ GitLab provides in your profile.
- The committer's email address must match the verified email address from the
GPG key.
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index de7459e6278..bb1a55f6b2b 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -41,7 +41,7 @@ to a branch in the repository. When you use the command line, you can commit mul
If the project is configured with [GitLab CI/CD](../../../ci/index.md),
you trigger a pipeline per push, not per commit.
- **Skip pipelines:**
- Add the [`ci skip`](../../../ci/yaml/index.md#skip-pipeline) keyword to
+ Add the [`ci skip`](../../../ci/pipelines/index.md#skip-a-pipeline) keyword to
your commit message to make GitLab CI/CD skip the pipeline.
- **Cross-link issues and merge requests:**
Use [cross-linking](../issues/crosslinking_issues.md#from-commit-messages)
@@ -82,14 +82,19 @@ prompted to open XCode.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220957) in GitLab 13.10.
-All projects can be cloned into Visual Studio Code. To do that:
+All projects can be cloned into Visual Studio Code from the GitLab user interface, but you
+can also install the [GitLab Workflow VS Code extension](vscode.md) to clone from
+Visual Studio Code:
-1. From the GitLab UI, go to the project's overview page.
-1. Click **Clone**.
-1. Select **Clone with Visual Studio Code** under either HTTPS or SSH method.
-1. Select a folder to clone the project into.
+- From the GitLab interface:
+ 1. Go to the project's overview page.
+ 1. Select **Clone**.
+ 1. Under either the **HTTPS** or **SSH** method, select **Clone with Visual Studio Code**.
+ 1. Select a folder to clone the project into.
-When VS Code has successfully cloned your project, it opens the folder.
+ After Visual Studio Code clones your project, it opens the folder.
+- From Visual Studio Code, with the [extension](vscode.md) installed, use the
+ extension's [`Git: Clone` command](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#clone-gitlab-projects).
## Download the code in a repository
@@ -243,6 +248,10 @@ When you [rename a user](../../profile/index.md#change-your-username),
- The redirects are available as long as the original path is not claimed by
another group, user, or project.
+## Related links
+
+- [GitLab Workflow VS Code extension](vscode.md)
+
## Troubleshooting
### Repository Languages: excessive CPU use
diff --git a/doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook_diff_v14_5.png b/doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook_diff_v14_5.png
new file mode 100644
index 00000000000..bc63322cd65
--- /dev/null
+++ b/doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook_diff_v14_5.png
Binary files differ
diff --git a/doc/user/project/repository/jupyter_notebooks/index.md b/doc/user/project/repository/jupyter_notebooks/index.md
index 2ad1504aac3..d040cc93876 100644
--- a/doc/user/project/repository/jupyter_notebooks/index.md
+++ b/doc/user/project/repository/jupyter_notebooks/index.md
@@ -4,22 +4,42 @@ group: Source Code
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
type: reference
---
-# Jupyter Notebook Files **(FREE)**
+# Jupyter Notebook files **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/2508/) in GitLab 9.1.
+[Jupyter Notebook](https://jupyter.org/) (previously, IPython Notebook) files are used for
+interactive computing in many fields. They contain a complete record of the
+user's sessions and include:
-[Jupyter](https://jupyter.org/) Notebook (previously IPython Notebook) files are used for
-interactive computing in many fields and contain a complete record of the
-user's sessions and include code, narrative text, equations, and rich output.
+- Code.
+- Narrative text.
+- Equations.
+- Rich output.
-When added to a repository, Jupyter Notebooks with a `.ipynb` extension are
-rendered to HTML when viewed:
+When you add a Jupyter Notebook (with `.ipynb` extension) to your repository,
+it's rendered into HTML when you view it:
![Jupyter Notebook Rich Output](img/jupyter_notebook.png)
Interactive features, including JavaScript plots, don't work when viewed in
GitLab.
+## Cleaner diffs
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/epics/6589) in GitLab 14.5 [with a flag](../../../../administration/feature_flags.md) named `jupyter_clean_diffs`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../../../administration/feature_flags.md) named `jupyter_clean_diffs`.
+On GitLab.com, this feature is available.
+
+When commits include changes to Jupyter Notebook files, GitLab:
+
+- Transforms the machine-readable `.ipynb` file into a human-readable Markdown file.
+- Displays a cleaner version of the diff that includes syntax highlighting.
+
+Code suggestions are not available on diffs and merge requests for `.ipynb` files.
+
+![Jupyter Notebook Clean Diff](img/jupyter_notebook_diff_v14_5.png)
+
## Jupyter Git integration
Jupyter can be configured as an OAuth application with repository access, acting
diff --git a/doc/user/project/repository/mirror/bidirectional.md b/doc/user/project/repository/mirror/bidirectional.md
index c4254655fcc..340d7b48a47 100644
--- a/doc/user/project/repository/mirror/bidirectional.md
+++ b/doc/user/project/repository/mirror/bidirectional.md
@@ -139,7 +139,7 @@ This sample has a few limitations:
- The script circumvents the Git hook quarantine environment because the update of `$TARGET_REPO`
is seen as a ref update, and Git displays warnings about it.
-## Mirror with Perforce Helix via Git Fusion **(PREMIUM)**
+## Mirror with Perforce Helix with Git Fusion **(PREMIUM)**
> Moved to GitLab Premium in 13.9.
diff --git a/doc/user/project/repository/mirror/img/repository_mirroring_copy_ssh_public_key_button.png b/doc/user/project/repository/mirror/img/repository_mirroring_copy_ssh_public_key_button.png
deleted file mode 100644
index e20dae09a4d..00000000000
--- a/doc/user/project/repository/mirror/img/repository_mirroring_copy_ssh_public_key_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/repository/mirror/index.md b/doc/user/project/repository/mirror/index.md
index 4532a80c2f5..361c0902ebf 100644
--- a/doc/user/project/repository/mirror/index.md
+++ b/doc/user/project/repository/mirror/index.md
@@ -7,102 +7,162 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.htm
# Repository mirroring **(FREE)**
-Repository mirroring allows for the mirroring of repositories to and from external sources. You
-can use it to mirror branches, tags, and commits between repositories. It helps you use
-a repository outside of GitLab.
+You can _mirror_ a repository to and from external sources. You can select which
+repository serves as the source, and modify which parts of the repository are copied.
+Branches, tags, and commits can be mirrored.
-A repository mirror at GitLab updates automatically. You can also manually trigger an update:
-
-- At most once every five minutes on GitLab.com.
-- According to a [limit set by the administrator](../../../../administration/instance_limits.md#pull-mirroring-interval)
- on self-managed instances.
-
-There are two kinds of repository mirroring supported by GitLab:
+Several mirroring methods exist:
- [Push](push.md): for mirroring a GitLab repository to another location.
- [Pull](pull.md): for mirroring a repository from another location to GitLab.
+- [Bidirectional](bidirectional.md) mirroring is also available, but can cause conflicts.
+
+Mirror a repository when:
+
+- The canonical version of your project has migrated to GitLab. To keep providing a
+ copy of your project at its previous home, configure your GitLab repository as a
+ [push mirror](push.md). Changes you make to your GitLab repository are copied to
+ the old location.
+- Your GitLab project is private, but some components can be shared publicly.
+ Configure your primary repository as a [push mirror](push.md) and push the portions
+ you want to make public. With this configuration, you can open-source specific
+ projects, contribute back to the open-source community, and protect the sensitive
+ parts of your project.
+- You migrated to GitLab, but the canonical version of your project is somewhere else.
+ Configure your GitLab repository as a [pull mirror](pull.md) of the other project.
+ Your GitLab repository pulls copies of the commits, tags, and branches of project.
+ They become available to use on GitLab.
+
+## Create a repository mirror
+
+Prerequisite:
+
+- You must have at least the [Maintainer role](../../../permissions.md) for the project.
+- If your mirror connects with `ssh://`, the host key must be detectable on the server,
+ or you must have a local copy of the key.
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Mirroring repositories**.
+1. Enter a **Git repository URL**. For security reasons, the URL to the original
+ repository is only displayed to users with the [Maintainer role](../../../permissions.md)
+ or the [Owner role](../../../permissions.md) for the mirrored project.
+1. Select a **Mirror direction**.
+1. If you entered a `ssh://` URL, select either:
+ - **Detect host keys**: GitLab fetches the host keys from the server and displays the fingerprints.
+ - **Input host keys manually**, and enter the host key into **SSH host key**.
+
+ When mirroring the repository, GitLab confirms at least one of the stored host keys
+ matches before connecting. This check can protect your mirror from malicious code injections,
+ or your password from being stolen.
+1. Select an **Authentication method**. To learn more, read
+ [Authentication methods for mirrors](#authentication-methods-for-mirrors).
+1. If you authenticate with SSH host keys, [verify the host key](#verify-a-host-key)
+ to ensure it is correct.
+1. To prevent force-pushing over diverged refs, select [**Keep divergent refs**](push.md#keep-divergent-refs).
+1. Optional. Select [**Mirror only protected branches**](#mirror-only-protected-branches).
+1. Select **Mirror repository**.
+
+If you select `SSH public key` as your authentication method, GitLab generates a
+public key for your GitLab repository. You must provide this key to the non-GitLab server.
+To learn more, read [Get your SSH public key](#get-your-ssh-public-key).
+
+## Update a mirror
When the mirror repository is updated, all new branches, tags, and commits are visible in the
-project's activity feed.
+project's activity feed. A repository mirror at GitLab updates automatically.
+You can also manually trigger an update:
-Users with the [Maintainer role](../../../permissions.md) for the project can also force an
-immediate update, unless:
+- At most once every five minutes on GitLab.com.
+- According to [the pull mirroring interval limit](../../../../administration/instance_limits.md#pull-mirroring-interval)
+ set by the administrator on self-managed instances.
-- The mirror is already being updated.
-- The [limit for pull mirroring interval seconds](../../../../administration/instance_limits.md#pull-mirroring-interval) has not elapsed after its last update.
+### Force an update
-For security reasons, the URL to the original repository is only displayed to users with the
-[Maintainer role](../../../permissions.md) or the [Owner role](../../../permissions.md) for the mirrored
-project.
+While mirrors are scheduled to update automatically, you can force an immediate update unless:
-## Use cases
+- The mirror is already being updated.
+- The [interval, in seconds](../../../../administration/instance_limits.md#pull-mirroring-interval)
+ for pull mirroring limits has not elapsed after its last update.
-The following are some possible use cases for repository mirroring:
+Prerequisite:
-- You migrated to GitLab but still must keep your project in another source. In that case, you
- can set it up to mirror to GitLab (pull) and all the essential history of commits, tags,
- and branches are available in your GitLab instance. **(PREMIUM)**
-- You have old projects in another source that you don't use actively anymore, but don't want to
- remove for archiving purposes. In that case, you can create a push mirror so that your active
- GitLab repository can push its changes to the old location.
-- You are a GitLab self-managed user for privacy reasons and your instance is closed to the public,
- but you still have certain software components that you want open sourced. In this case, utilizing
- GitLab to be your primary repository which is closed from the public, and using push mirroring to a
- GitLab.com repository that's public, allows you to open source specific projects and contribute back
- to the open source community.
+- You must have at least the [Maintainer role](../../../permissions.md) for the project.
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Mirroring repositories**.
+1. Scroll to **Mirrored repositories** and identify the mirror to update.
+1. Select **Update now** (**{retry}**):
+ ![Repository mirroring force update user interface](img/repository_mirroring_force_update.png)
## Mirror only protected branches **(PREMIUM)**
> Moved to GitLab Premium in 13.9.
-Based on the mirror direction that you choose, you can opt to mirror only the
+You can choose to mirror only the
[protected branches](../../protected_branches.md) in the mirroring project,
-either from or to your remote repository. For pull mirroring, non-protected branches in
-the mirroring project are not mirrored and can diverge.
+either from or to your remote repository. For [pull mirroring](pull.md),
+non-protected branches in the mirroring project are not mirrored and can diverge.
+
+To use this option, select **Only mirror protected branches** when you create a repository mirror.
-To use this option, check the **Only mirror protected branches** box when
-creating a repository mirror. **(PREMIUM)**
+## Authentication methods for mirrors
-## SSH authentication
+When you create a mirror, you must configure the authentication method for it.
+GitLab supports these authentication methods:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22982) in GitLab 11.6 for Push mirroring.
+- [SSH authentication](#ssh-authentication).
+- Password.
+
+### SSH authentication
SSH authentication is mutual:
-- You have to prove to the server that you're allowed to access the repository.
-- The server also has to prove to *you* that it's who it claims to be.
+- You must prove to the server that you're allowed to access the repository.
+- The server must also *prove to you* that it's who it claims to be.
-You provide your credentials as a password or public key. The server that the
-other repository resides on provides its credentials as a "host key", the
-fingerprint of which needs to be verified manually.
+For SSH authentication, you provide your credentials as a password or _public key_.
+The server that the other repository resides on provides its credentials as a _host key_.
+You must [verify the fingerprint](#verify-a-host-key) of this host key manually.
If you're mirroring over SSH (using an `ssh://` URL), you can authenticate using:
- Password-based authentication, just as over HTTPS.
-- Public key authentication. This is often more secure than password authentication,
+- Public key authentication. This method is often more secure than password authentication,
especially when the other repository supports [deploy keys](../../deploy_keys/index.md).
-To get started:
-
-1. In your project, go to **Settings > Repository**, and then expand the **Mirroring repositories** section.
-1. Enter an `ssh://` URL for mirroring.
+### Get your SSH public key
-NOTE:
-SCP-style URLs (that is, `git@example.com:group/project.git`) are not supported at this time.
+When you mirror a repository and select the **SSH public key** as your
+authentication method, GitLab generates a public key for you. The non-GitLab server
+needs this key to establish trust with your GitLab repository. To copy your SSH public key:
-Entering the URL adds two buttons to the page:
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Mirroring repositories**.
+1. Scroll to **Mirrored repositories**.
+1. Identify the correct repository, and select **Copy SSH public key** (**{copy-to-clipboard}**).
+1. Add the public SSH key to the other repository's configuration:
+ - If the other repository is hosted on GitLab, add the public SSH key
+ as a [deploy key](../../../project/deploy_keys/index.md).
+ - If the other repository is hosted elsewhere, add the key to
+ your user's `authorized_keys` file. Paste the entire public SSH key into the
+ file on its own line and save it.
-- **Detect host keys**.
-- **Input host keys manually**.
+If you must change the key at any time, you can remove and re-add the mirror
+to generate a new key. Update the other repository with the new
+key to keep the mirror running.
-If you select the:
+NOTE:
+The generated keys are stored in the GitLab database, not in the file system. Therefore,
+SSH public key authentication for mirrors cannot be used in a pre-receive hook.
-- **Detect host keys** button, GitLab fetches the host keys from the server and display the fingerprints.
-- **Input host keys manually** button, a field is displayed where you can paste in host keys.
+### Verify a host key
-Assuming you used the former, you now must verify that the fingerprints are
-those you expect. GitLab.com and other code hosting sites publish their
-fingerprints in the open for you to check:
+When using a host key, always verify the fingerprints match what you expect.
+GitLab.com and other code hosting sites publish their fingerprints
+for you to check:
- [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/regions.html#regions-fingerprints)
- [Bitbucket](https://support.atlassian.com/bitbucket-cloud/docs/configure-ssh-and-two-step-verification/)
@@ -112,9 +172,11 @@ fingerprints in the open for you to check:
- [Savannah](http://savannah.gnu.org/maintenance/SshAccess/)
- [SourceForge](https://sourceforge.net/p/forge/documentation/SSH%20Key%20Fingerprints/)
-Other providers vary. If you're running self-managed GitLab, or otherwise
-have access to the server for the other repository, you can securely gather the
-key fingerprints:
+Other providers vary. You can securely gather key fingerprints with the following
+command if you:
+
+- Run self-managed GitLab.
+- Have access to the server for the other repository.
```shell
$ cat /etc/ssh/ssh_host*pub | ssh-keygen -E md5 -l -f -
@@ -123,45 +185,9 @@ $ cat /etc/ssh/ssh_host*pub | ssh-keygen -E md5 -l -f -
2048 MD5:3f:72:be:3d:62:03:5c:62:83:e8:6e:14:34:3a:85:1d root@example.com (RSA)
```
-NOTE:
-You must exclude `-E md5` for some older versions of SSH.
-
-When mirroring the repository, GitLab checks that at least one of the
-stored host keys matches before connecting. This can prevent malicious code from
-being injected into your mirror, or your password being stolen.
-
-### SSH public key authentication
-
-To use SSH public key authentication, you must also choose that option
-from the **Authentication method** dropdown. When the mirror is created,
-GitLab generates a 4096-bit RSA key that can be copied by selecting the **Copy SSH public key** button.
-
-![Repository mirroring copy SSH public key to clipboard button](img/repository_mirroring_copy_ssh_public_key_button.png)
+Older versions of SSH may require you to remove `-E md5` from the command.
-You then must add the public SSH key to the other repository's configuration:
-
-- If the other repository is hosted on GitLab, you should add the public SSH key
- as a [deploy key](../../../project/deploy_keys/index.md).
-- If the other repository is hosted elsewhere, you must add the key to
- your user's `authorized_keys` file. Paste the entire public SSH key into the
- file on its own line and save it.
-
-If you must change the key at any time, you can remove and re-add the mirror
-to generate a new key. Update the other repository with the new
-key to keep the mirror running.
-
-NOTE:
-The generated keys are stored in the GitLab database, not in the file system. Therefore,
-SSH public key authentication for mirrors cannot be used in a pre-receive hook.
-
-## Force an update **(FREE)**
-
-While mirrors are scheduled to update automatically, you can always force an update by using the
-update button which is available on the **Mirroring repositories** section of the **Repository Settings** page.
-
-![Repository mirroring force update user interface](img/repository_mirroring_force_update.png)
-
-## Resources
+## Related topics
- Configure a [Pull Mirroring Interval](../../../../administration/instance_limits.md#pull-mirroring-interval)
- [Disable mirrors for a project](../../../admin_area/settings/visibility_and_access_controls.md#enable-project-mirroring)
@@ -171,24 +197,33 @@ update button which is available on the **Mirroring repositories** section of th
Should an error occur during a push, GitLab displays an **Error** highlight for that repository. Details on the error can then be seen by hovering over the highlight text.
-### 13:Received RST_STREAM with error code 2 with GitHub
+### Received RST_STREAM with error code 2 with GitHub
+
+If you receive this message while mirroring to a GitHub repository:
+
+```plaintext
+13:Received RST_STREAM with error code 2
+```
+
+Your GitHub settings might be set to block pushes that expose your email address
+used in commits. To fix this problem, either:
-If you receive a "13:Received RST_STREAM with error code 2" message while mirroring to a GitHub repository,
-your GitHub settings might be set to block pushes that expose your email address used in commits. Either
-set your email address on GitHub to be public, or disable the [Block command line pushes that expose my email](https://github.com/settings/emails) setting.
+- Set your GitHub email address to public.
+- Disable the [Block command line pushes that expose my email](https://github.com/settings/emails) setting.
-### 4:Deadline Exceeded
+### Deadline Exceeded
-When upgrading to GitLab 11.11.8 or newer, a change in how usernames are represented means that you
+When upgrading to GitLab 11.11.8 or later, a change in how usernames are represented means that you
must update your mirroring username and password to ensure that `%40` characters are replaced with `@`.
### Connection blocked because server only allows public key authentication
-As the error indicates, the connection is getting blocked between GitLab and the remote repository. Even if a
-[TCP Check](../../../../administration/raketasks/maintenance.md#check-tcp-connectivity-to-a-remote-site) is successful,
-you must check any networking components in the route from GitLab to the remote Server to ensure there's no blockage.
+The connection between GitLab and the remote repository is blocked. Even if a
+[TCP Check](../../../../administration/raketasks/maintenance.md#check-tcp-connectivity-to-a-remote-site)
+is successful, you must check any networking components in the route from GitLab
+to the remote server for blockage.
-For example, we've seen this error when a Firewall was performing a `Deep SSH Inspection` on outgoing packets.
+This error can occur when a firewall performs a `Deep SSH Inspection` on outgoing packets.
### Could not read username: terminal prompts disabled
@@ -196,29 +231,31 @@ If you receive this error after creating a new project using
[GitLab CI/CD for external repositories](../../../../ci/ci_cd_for_external_repos/):
```plaintext
-"2:fetch remote: "fatal: could not read Username for 'https://bitbucket.org': terminal prompts disabled\n": exit status 128."
+"2:fetch remote: "fatal: could not read Username for 'https://bitbucket.org':
+terminal prompts disabled\n": exit status 128."
```
Check if the repository owner is specified in the URL of your mirrored repository:
-1. Go to your project.
+1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > Repository**.
-1. Select **Mirroring repositories**.
-1. If no repository owner is specified, delete and add the URL again in this format:
+1. Expand **Mirroring repositories**.
+1. If no repository owner is specified, delete and add the URL again in this format,
+ replacing `OWNER`, `ACCOUNTNAME`, and `REPONAME` with your values:
```plaintext
- https://**<repo_owner>**@bitbucket.org/<accountname>/<reponame>.git
+ https://OWNER@bitbucket.org/ACCOUNTNAME/REPONAME.git
```
-The repository owner is needed for Bitbucket to connect to the repository for mirroring.
+When connecting to the repository for mirroring, Bitbucket requires the repository owner in the string.
### Pull mirror is missing LFS files
In some cases, pull mirroring does not transfer LFS files. This issue occurs when:
- You use an SSH repository URL. The workaround is to use an HTTPS repository URL instead.
- There is [an issue to fix this for SSH URLs](https://gitlab.com/gitlab-org/gitlab/-/issues/11997).
+ An issue exists [to fix this problem for SSH URLs](https://gitlab.com/gitlab-org/gitlab/-/issues/11997).
- You're using GitLab 14.0 or older, and the source repository is a public Bitbucket URL.
- This was [fixed in GitLab 14.0.6](https://gitlab.com/gitlab-org/gitlab/-/issues/335123).
+ [Fixed](https://gitlab.com/gitlab-org/gitlab/-/issues/335123) in GitLab 14.0.6.
- You mirror an external repository using object storage.
- There is [an issue to fix this](https://gitlab.com/gitlab-org/gitlab/-/issues/335495).
+ An issue exists [to fix this problem](https://gitlab.com/gitlab-org/gitlab/-/issues/335495).
diff --git a/doc/user/project/repository/mirror/pull.md b/doc/user/project/repository/mirror/pull.md
index d1943cbfd71..4c437d0f8c8 100644
--- a/doc/user/project/repository/mirror/pull.md
+++ b/doc/user/project/repository/mirror/pull.md
@@ -41,7 +41,7 @@ After you configure a GitLab repository as a pull mirror:
1. Sidekiq becomes available to process updates, mirrors are updated. If the update process:
- **Succeeds**: An update is enqueued again with at least a 30 minute wait.
- **Fails**: The update is attempted again later. After 14 failures, a mirror is marked as a
- [hard failure](#hard-failure) and is no longer enqueued for updates. A branch diverging
+ [hard failure](#fix-hard-failures-when-mirroring) and is no longer enqueued for updates. A branch diverging
from its upstream counterpart can cause failures. To prevent branches from
diverging, configure [Overwrite diverged branches](#overwrite-diverged-branches) when
you create your mirror.
@@ -102,7 +102,7 @@ updates are pulled immediately.
For more information, read
[Start the pull mirroring process for a project](../../../../api/projects.md#start-the-pull-mirroring-process-for-a-project).
-## Hard failure
+## Fix hard failures when mirroring
> Moved to GitLab Premium in 13.9.
@@ -112,7 +112,7 @@ and mirroring attempts stop. This failure is visible in either the:
- Project's main dashboard.
- Pull mirror settings page.
-You can resume the project mirroring again by [forcing an update](index.md#force-an-update).
+To resume project mirroring, [force an update](index.md#force-an-update).
## Related topics
diff --git a/doc/user/project/repository/vscode.md b/doc/user/project/repository/vscode.md
new file mode 100644
index 00000000000..bbf14a71653
--- /dev/null
+++ b/doc/user/project/repository/vscode.md
@@ -0,0 +1,47 @@
+---
+stage: Create
+group: Code Review
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# GitLab Workflow extension for VS Code **(FREE)**
+
+The [GitLab Workflow extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
+integrates GitLab with Visual Studio Code. You can decrease context switching and
+do more day-to-day tasks in Visual Studio Code, such as:
+
+- [View issues](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#browse-issues-review-mrs).
+- Run [common commands](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#commands)
+ from the Visual Studio Code [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
+- Create and [review](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#merge-request-reviews)
+ merge requests directly from Visual Studio Code.
+- [Validate your GitLab CI configuration](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#validate-gitlab-ci-configuration).
+- [View the status of your pipeline](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#information-about-your-branch-pipelines-mr-closing-issue).
+- [Create](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#create-snippet)
+ and paste snippets to, and from, your editor.
+- [Browse repositories](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#browse-a-repository-without-cloning)
+ without cloning them.
+
+## Download the extension
+
+Download the extension from the [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow).
+
+## Configure the extension
+
+After you [download the extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
+you can [configure](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#extension-settings):
+
+- [Features to display or hide](https://gitlab.com/gitlab-org/gitlab-vscode-extension#extension-settings).
+- [Self-signed certificate](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#self-signed-certificates) information.
+
+## Report issues with the extension
+
+Report any issues, bugs, or feature requests in the
+[`gitlab-vscode-extension` issue queue](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues).
+
+## Related topics
+
+- [Download the extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
+- [Extension documentation](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md)
+- The extension source code is available in the
+ [`gitlab-vscode-extension`](https://gitlab.com/gitlab-org/gitlab-vscode-extension/) project.
diff --git a/doc/user/project/repository/x509_signed_commits/index.md b/doc/user/project/repository/x509_signed_commits/index.md
index 17031dd29af..2db7ae308bd 100644
--- a/doc/user/project/repository/x509_signed_commits/index.md
+++ b/doc/user/project/repository/x509_signed_commits/index.md
@@ -158,7 +158,7 @@ can start signing your tags:
git config --global tag.gpgsign true
```
-## Resources
+## Related topics
- [Rake task for X.509 signatures](../../../../raketasks/x509_signatures.md)
diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md
index 661bd3e0598..6ee23c91680 100644
--- a/doc/user/project/requirements/index.md
+++ b/doc/user/project/requirements/index.md
@@ -38,7 +38,9 @@ see [GitLab Requirements Traceability Walkthrough](https://youtu.be/VIiuTQYFVa0)
A paginated list of requirements is available in each project, and there you
can create a new requirement.
-Users with Reporter or higher [permissions](../../permissions.md) can create requirements.
+Prerequisite:
+
+- You must have at least the Reporter [role](../../permissions.md).
To create a requirement:
@@ -66,7 +68,9 @@ next to the requirement title.
You can edit a requirement from the requirements list page.
-Users with Reporter or higher [permissions](../../permissions.md) can edit requirements.
+Prerequisite:
+
+- You must have at least the Reporter [role](../../permissions.md).
To edit a requirement:
@@ -80,7 +84,9 @@ To edit a requirement:
You can archive an open requirement while
you're in the **Open** tab.
-Users with Reporter or higher [permissions](../../permissions.md) can archive requirements.
+Prerequisite:
+
+- You must have at least the Reporter [role](../../permissions.md).
To archive a requirement, select **Archive** (**{archive}**).
@@ -90,7 +96,9 @@ As soon as a requirement is archived, it no longer appears in the **Open** tab.
You can view the list of archived requirements in the **Archived** tab.
-Users with Reporter or higher [permissions](../../permissions.md) can reopen archived requirements.
+Prerequisite:
+
+- You must have at least the Reporter [role](../../permissions.md).
![archived requirements list](img/requirements_archived_list_view_v13_1.png)
@@ -209,13 +217,13 @@ requirements_confirmation:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/246857) in GitLab 13.7.
+You must have at least the Reporter [role](../../permissions.md).
+
You can import requirements to a project by uploading a [CSV file](https://en.wikipedia.org/wiki/Comma-separated_values)
with the columns `title` and `description`.
After the import, the user uploading the CSV file is set as the author of the imported requirements.
-Users with Reporter or higher [permissions](../../permissions.md) can import requirements.
-
### Import the file
Before you import your file:
@@ -281,7 +289,9 @@ By exporting requirements, you and your team can import them into another tool o
your customers. Exporting requirements can aid collaboration with higher-level systems, as well as
audit and regulatory compliance tasks.
-Users with Reporter or higher [permissions](../../permissions.md) can export requirements.
+Prerequisite:
+
+- You must have at least the Reporter [role](../../permissions.md).
To export requirements:
diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md
index fa5ef35418a..4f8e068ca2d 100644
--- a/doc/user/project/service_desk.md
+++ b/doc/user/project/service_desk.md
@@ -86,10 +86,10 @@ To improve your project's security, we recommend the following:
- [Enable Akismet](../../integration/akismet.md) on your GitLab instance to add spam checking to this service.
Unblocked email spam can result in many spam issues being created.
-The unique internal email address is visible to project members with Maintainer (or higher)
-[permission level](../permissions.md)
-in your GitLab instance. However, when using an email alias externally, an end user
-(issue creator) cannot see the internal email address displayed in the information note.
+The unique internal email address is visible to project members at least
+the Reporter [role](../permissions.md) in your GitLab instance.
+An external user (issue creator) cannot see the internal email address
+displayed in the information note.
### Using customized email templates
@@ -137,15 +137,23 @@ You can use these placeholders to be automatically replaced in each email:
#### New Service Desk issues
-You can select one [issue description template](description_templates.md#create-an-issue-template)
+You can select one [description template](description_templates.md#create-an-issue-template)
**per project** to be appended to every new Service Desk issue's description.
-Issue description templates should reside in your repository's `.gitlab/issue_templates/` directory.
-To use a custom issue template with Service Desk, in your project:
+You can set description templates at various levels:
-1. [Create a description template](description_templates.md#create-an-issue-template)
-1. Go to **Settings > General > Service Desk**.
-1. From the dropdown **Template to append to all Service Desk issues**, select your template.
+- The entire [instance](description_templates.md#set-instance-level-description-templates).
+- A specific [group or subgroup](description_templates.md#set-group-level-description-templates).
+- A specific [project](description_templates.md#set-a-default-template-for-merge-requests-and-issues).
+
+The templates are inherited. For example, in a project, you can also access templates set for the instance or the project’s parent groups.
+
+To use a custom description template with Service Desk:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. [Create a description template](description_templates.md#create-an-issue-template).
+1. On the left sidebar, select **Settings > General > Service Desk**.
+1. From the dropdown **Template to append to all Service Desk issues**, search or select your template.
### Using a custom email display name
@@ -156,7 +164,8 @@ this name in the `From` header. The default display name is `GitLab Support Bot`
To edit the custom email display name:
-1. In a project, go to **Settings > General > Service Desk**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > General > Service Desk**.
1. Enter a new name in **Email display name**.
1. Select **Save Changes**.
@@ -166,13 +175,13 @@ To edit the custom email display name:
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/284656) in GitLab 13.8.
It is possible to customize the email address used by Service Desk. To do this, you must configure
-both a [custom mailbox](#configuring-a-custom-mailbox) and a
+a [custom mailbox](#configuring-a-custom-mailbox). If you want you can also configure a
[custom suffix](#configuring-a-custom-email-address-suffix).
#### Configuring a custom mailbox
NOTE:
-On GitLab.com a custom mailbox is already configured with `contact-project+%{key}@incoming.gitlab.com` as the email address, so you only have to configure the
+On GitLab.com a custom mailbox is already configured with `contact-project+%{key}@incoming.gitlab.com` as the email address, you can still configure the
[custom suffix](#configuring-a-custom-email-address-suffix) in project settings.
Using the `service_desk_email` configuration, you can customize the mailbox
@@ -198,7 +207,7 @@ To configure a custom mailbox for Service Desk with IMAP, add the following snip
service_desk_email:
enabled: true
address: "project_contact+%{key}@example.com"
- user: "project_support@example.com"
+ user: "project_contact@example.com"
password: "[REDACTED]"
host: "imap.gmail.com"
port: 993
@@ -215,7 +224,7 @@ To configure a custom mailbox for Service Desk with IMAP, add the following snip
```ruby
gitlab_rails['service_desk_email_enabled'] = true
gitlab_rails['service_desk_email_address'] = "project_contact+%{key}@gmail.com"
- gitlab_rails['service_desk_email_email'] = "project_support@gmail.com"
+ gitlab_rails['service_desk_email_email'] = "project_contact@gmail.com"
gitlab_rails['service_desk_email_password'] = "[REDACTED]"
gitlab_rails['service_desk_email_mailbox_name'] = "inbox"
gitlab_rails['service_desk_email_idle_timeout'] = 60
@@ -271,6 +280,8 @@ For example, suppose the `mygroup/myproject` project Service Desk settings has t
The Service Desk email address for this project is: `contact+mygroup-myproject-support@example.com`.
The [incoming email](../../administration/incoming_email.md) address still works.
+If you don't configure the custom suffix, the default project identification will be used for identifying the project. You can see that email address in the project settings.
+
## Using Service Desk
You can use Service Desk to [create an issue](#as-an-end-user-issue-creator) or [respond to one](#as-a-responder-to-the-issue).
diff --git a/doc/user/project/settings/img/general_settings_v13_11.png b/doc/user/project/settings/img/general_settings_v13_11.png
deleted file mode 100644
index 9da5acdf82e..00000000000
--- a/doc/user/project/settings/img/general_settings_v13_11.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_download_export.png b/doc/user/project/settings/img/import_export_download_export.png
index c7ab7565fc7..62292e99e8e 100644
--- a/doc/user/project/settings/img/import_export_download_export.png
+++ b/doc/user/project/settings/img/import_export_download_export.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_export_button.png b/doc/user/project/settings/img/import_export_export_button.png
index 6933e3edfcc..6f3663d64e8 100644
--- a/doc/user/project/settings/img/import_export_export_button.png
+++ b/doc/user/project/settings/img/import_export_export_button.png
Binary files differ
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 6c3bf731cf8..74879dae2d6 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -2,7 +2,6 @@
stage: Manage
group: Import
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
-type: reference, howto
---
# Project import/export **(FREE)**
@@ -159,7 +158,9 @@ To export a project and its data, follow these steps:
1. Go to your project's homepage.
-1. Click **Settings** in the sidebar.
+1. Select **Settings** in the sidebar.
+
+1. Scroll down and expand the **Advanced** section.
1. Scroll down to find the **Export project** button:
@@ -178,12 +179,14 @@ To export a project and its data, follow these steps:
## Import the project
+> Default maximum import file size [changed](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50 MB to unlimited in GitLab 13.8.
+
WARNING:
Only import projects from sources you trust. If you import a project from an untrusted source, it
may be possible for an attacker to steal your sensitive data.
1. The GitLab project import feature is the first import option when creating a
- new project. Click on **GitLab export**:
+ new project. Select **GitLab export**:
![New project](img/import_export_new_project.png)
@@ -191,7 +194,7 @@ may be possible for an attacker to steal your sensitive data.
![Select file](img/import_export_select_file.png)
-1. Click on **Import project** to begin importing. Your newly imported project
+1. Select **Import project** to begin importing. Your newly imported project
page appears shortly.
NOTE:
@@ -199,9 +202,8 @@ If use of the `Internal` visibility level
[is restricted](../../../public_access/public_access.md#restrict-use-of-public-or-internal-projects),
all imported projects are given the visibility of `Private`.
-NOTE:
-The maximum import file size can be set by the Administrator, default is `0` (unlimited).
-As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](../../../api/settings.md#change-application-settings) or the [Admin Area UI](../../admin_area/settings/account_and_limit_settings.md). Default [modified](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50MB to 0 in GitLab 13.8.
+The maximum import file size can be set by the Administrator, and the default is `0` (unlimited).
+As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](../../../api/settings.md#change-application-settings) or the [Admin Area UI](../../admin_area/settings/account_and_limit_settings.md).
### Project import status
@@ -224,6 +226,11 @@ To help avoid abuse, by default, users are rate limited to:
GitLab.com may have [different settings](../../gitlab_com/index.md#importexport) from the defaults.
+## Automate group and project import **(PREMIUM)**
+
+For information on automating user, group, and project import API calls, see
+[Automate group and project import](../import/index.md#automate-group-and-project-import).
+
## Troubleshooting
### Project fails to import due to mismatch
@@ -233,15 +240,18 @@ does not match between the exported project, and the project import, the project
Review [issue 276930](https://gitlab.com/gitlab-org/gitlab/-/issues/276930), and either:
- Ensure shared runners are enabled in both the source and destination projects.
-- Disable shared runners on the parent group when you import the project.
+- Disable shared runners on the parent group when you import the project.
-### Import workaround for large repositories
+### Import workarounds for large repositories
[Maximum import size limitations](#import-the-project)
-can prevent an import from being successful.
-If changing the import limits is not possible,
-the following local workflow can be used to temporarily
-reduce the repository size for another import attempt.
+can prevent an import from being successful. If changing the import limits is not possible, you can
+try one of the workarounds listed here.
+
+#### Workaround option 1
+
+The following local workflow can be used to temporarily
+reduce the repository size for another import attempt:
1. Create a temporary working directory from the export:
@@ -291,6 +301,58 @@ reduce the repository size for another import attempt.
delete the temporary, `smaller-tmp-main` branch, and
the local, temporary data.
+#### Workaround option 2
+
+Rather than attempting to push all changes at once, this workaround:
+
+- Separates the project import from the Git Repository import
+- Incrementally pushes the repository to GitLab
+
+1. Make a local clone of the repository to migrate. In a later step, you push this clone outside of
+ the project export.
+1. Download the export and remove the `project.bundle` (which contains the Git repository):
+
+ ```shell
+ tar -czvf new_export.tar.gz --exclude='project.bundle' @old_export.tar.gz
+ ```
+
+1. Import the export without a Git repository. It asks you to confirm to import without a
+ repository.
+1. Save this bash script as a file and run it after adding the appropriate origin.
+
+ ```shell
+ #!/bin/sh
+
+ # ASSUMPTIONS:
+ # - The GitLab location is "origin"
+ # - The default branch is "main"
+ # - This will attempt to push in chunks of 500MB (dividing the total size by 500MB).
+ # Decrease this size to push in smaller chunks if you still receive timeouts.
+
+ git gc
+ SIZE=$(git count-objects -v 2> /dev/null | grep size-pack | awk '{print $2}')
+
+ # Be conservative... and try to push 2GB at a time
+ # (given this assumes each commit is the same size - which is wrong)
+ BATCHES=$(($SIZE / 500000))
+ TOTAL_COMMITS=$(git rev-list --count HEAD)
+ if (( BATCHES > TOTAL_COMMITS )); then
+ BATCHES=$TOTAL_COMMITS
+ fi
+
+ INCREMENTS=$(( ($TOTAL_COMMITS / $BATCHES) - 1 ))
+
+ for (( BATCH=BATCHES; BATCH>=1; BATCH-- ))
+ do
+ COMMIT_NUM=$(( $BATCH - $INCREMENTS ))
+ COMMIT_SHA=$(git log -n $COMMIT_NUM --format=format:%H | tail -1)
+ git push -u origin ${COMMIT_SHA}:refs/heads/main
+ done
+ git push -u origin main
+ git push -u origin -—all
+ git push -u origin -—tags
+ ```
+
### Manually execute export steps
Exports sometimes fail without giving enough information to troubleshoot. In these cases, it can be
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index 30def6ae80f..5c4d4649240 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -28,12 +28,32 @@ functionality of a project.
Adjust your project's name, description, avatar, [default branch](../repository/branches/default.md), and topics:
-![general project settings](img/general_settings_v13_11.png)
-
The project description also partially supports [standard Markdown](../../markdown.md#features-extended-from-standard-markdown).
You can use [emphasis](../../markdown.md#emphasis), [links](../../markdown.md#links), and
[line-breaks](../../markdown.md#line-breaks) to add more context to the project description.
+#### Topics
+
+Use topics to categorize projects and find similar new projects.
+
+To assign topics to a project:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings** > **General**.
+1. Under **Topics**, enter the project topics. Existing popular topics are suggested as you type.
+1. Select **Save changes**.
+
+For GitLab.com, explore popular topics on the [Explore topics page](../working_with_projects.md#explore-topics).
+When you select a topic, you can see relevant projects.
+
+NOTE:
+The assigned topics are visible only to everyone with access to the project,
+but everyone can see which topics exist at all on the GitLab instance.
+Do not include sensitive information in the name of a topic.
+
+If you're an instance administrator, see also
+[Administering topics](../../admin_area/index.md#administering-topics).
+
#### Compliance frameworks **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276221) in GitLab 13.9.
@@ -157,7 +177,9 @@ audit trail:
include: # Execute individual project's configuration (if project contains .gitlab-ci.yml)
project: '$CI_PROJECT_PATH'
file: '$CI_CONFIG_PATH'
- ref: '$CI_COMMIT_REF_NAME' # Must be defined or MR pipelines always use the use default branch.
+ ref: '$CI_COMMIT_REF_NAME' # Must be defined or MR pipelines always use the use default branch
+ rules:
+ - exists: '$CI_CONFIG_PATH'
```
##### Ensure compliance jobs are always run
@@ -236,7 +258,7 @@ Use the switches to enable or disable the following features:
| **Wiki** | ✓ | Enables a separate system for [documentation](../wiki/). |
| **Snippets** | ✓ | Enables [sharing of code and text](../../snippets.md). |
| **Pages** | ✓ | Allows you to [publish static websites](../pages/). |
-| **Operations** | ✓ | Control access to [operations dashboard](../../../operations/index.md). |
+| **Operations** | ✓ | Control access to Operations-related features, including [Operations Dashboard](../../../operations/index.md), [Environments and Deployments](../../../ci/environments/index.md), [Feature Flags](../../../operations/feature_flags.md). |
| **Metrics Dashboard** | ✓ | Control access to [metrics dashboard](../integrations/prometheus.md). |
Some features depend on others:
@@ -293,6 +315,7 @@ Set up your project's merge request settings:
- Enable [require an associated issue from Jira](../../../integration/jira/issues.md#require-associated-jira-issue-for-merge-requests-to-be-merged).
- Enable [`delete source branch after merge` option by default](../merge_requests/getting_started.md#deleting-the-source-branch).
- Configure [suggested changes commit messages](../merge_requests/reviews/suggestions.md#configure-the-commit-message-for-applied-suggestions).
+- Configure [merge commit message template](../merge_requests/commit_templates.md).
- Configure [the default target project](../merge_requests/creating_merge_requests.md#set-the-default-target-project) for merge requests coming from forks.
### Service Desk
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index cae9276eafd..85e412e7a41 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -10,6 +10,7 @@ type: reference, howto
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210181) in GitLab 13.0.
> - [Became available on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/235765) in GitLab 13.5 for paid groups only.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235765) in GitLab 13.5.
+> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/342327) in GitLab 14.5. Default prefix added.
Project access tokens are similar to [personal access tokens](../../profile/personal_access_tokens.md)
except they are attached to a project rather than a user. They can be used to:
@@ -32,6 +33,9 @@ Project access tokens:
For examples of how you can use a project access token to authenticate with the API, see the
[relevant section from our API Docs](../../../api/index.md#personalproject-access-tokens).
+NOTE:
+For GitLab.com and self-managed instances, the default prefix is `glpat-`.
+
## Creating a project access token
1. Log in to GitLab.
@@ -58,7 +62,9 @@ For the bot:
- The name is set to the name of the token.
- The username is set to `project_{project_id}_bot` for the first access token, such as `project_123_bot`.
-- The username is set to `project_{project_id}_bot{bot_count}` for further access tokens, such as `project_123_bot1`.
+- The email is set to `project{project_id}_bot@example.com`, for example `project123_bot@example.com`.
+- For additional access tokens in the same project, the username is set to `project_{project_id}_bot{bot_count}`, for example `project_123_bot1`.
+- For additional acess tokens in the same project, the email is set to `project{project_id}_bot{bot_count}@example.com`, for example `project123_bot1@example.com`
API calls made with a project access token are associated with the corresponding bot user.
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index 71cf0c03549..d75a180492e 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -15,7 +15,8 @@ projects by providing an advanced editor with commit staging.
## Open the Web IDE
-You can open the Web IDE when viewing a file, from the repository file list,
+Use the <kbd>.</kbd> [keyboard shortcut](../../shortcuts.md) to open the Web IDE.
+You can also open the Web IDE when viewing a file, from the repository file list,
and from merge requests:
- *When viewing a file, or the repository file list* -
@@ -100,12 +101,13 @@ same core features for highlighting and linking to particular lines in the edite
## Schema based validation
-> - Support for validation based on predefined schemas [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218472) in GitLab 13.2.
-> - It was deployed behind a feature flag, disabled by default.
-> - It's enabled on GitLab.com.
-> - It cannot be enabled or disabled per-project.
-> - For GitLab self-managed instances, GitLab administrators can opt to [enable it](#enable-or-disable-validation-based-on-predefined-schemas).
-> - Support for validation based on custom schemas [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/226982) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218472) validation based on predefined schemas in GitLab 13.2 [with a flag](../../../administration/feature_flags.md) named `schema_linting`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available for your entire instance, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `schema_linting`.
+This feature cannot be enabled or disabled per-project.
+On GitLab.com, this feature is available.
+You should not use this feature for production environments.
The Web IDE provides validation support for certain JSON and YAML files using schemas
based on the [JSON Schema Store](https://www.schemastore.org/json/).
@@ -115,28 +117,9 @@ based on the [JSON Schema Store](https://www.schemastore.org/json/).
The Web IDE has validation for certain files built in. This feature is only supported for
the `*.gitlab-ci.yml` files.
-#### Enable or disable validation based on predefined schemas **(FREE SELF)**
-
-Validation based on predefined schemas is under development and not ready for production use. It is
-deployed behind a feature flag that is **disabled by default** for self-managed instances,
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can enable it for your instance.
-
-To enable it:
-
-```ruby
-Feature.enable(:schema_linting)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:schema_linting)
-```
-
### Custom schemas **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/226982) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/226982) in GitLab 13.4.
The Web IDE also allows you to define custom schemas for certain JSON/YAML files in your project.
You can do so by defining a `schemas` entry in the `.gitlab/.gitlab-webide.yml` file inside the
diff --git a/doc/user/project/wiki/group.md b/doc/user/project/wiki/group.md
new file mode 100644
index 00000000000..731fed2595a
--- /dev/null
+++ b/doc/user/project/wiki/group.md
@@ -0,0 +1,71 @@
+---
+stage: Create
+group: Editor
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+type: reference, how-to
+---
+
+# Group wikis **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13195) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5.
+
+If you use GitLab groups to manage multiple projects, some of your documentation
+might span multiple groups. You can create group wikis, instead of [project wikis](index.md),
+to ensure all group members have the correct access permissions to contribute.
+Group wikis are similar to [project wikis](index.md), with a few limitations:
+
+- [Git LFS](../../../topics/git/lfs/index.md) is not supported.
+- Group wikis are not included in [global search](../../search/advanced_search.md).
+- Changes to group wikis don't show up in the [group's activity feed](../../group/index.md#group-activity-analytics).
+- Group wikis are enabled by default for **(PREMIUM)** and higher tiers.
+ You [can't turn them off from the GitLab user interface](https://gitlab.com/gitlab-org/gitlab/-/issues/208413).
+
+For updates, follow [the epic that tracks feature parity with project wikis](https://gitlab.com/groups/gitlab-org/-/epics/2782).
+
+Similar to project wikis, group members with the [Developer role](../../permissions.md#group-members-permissions)
+and higher can edit group wikis. Group wiki repositories can be moved using the
+[Group repository storage moves API](../../../api/group_repository_storage_moves.md).
+
+## View a group wiki
+
+To access a group wiki:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. To display the wiki, either:
+ - On the left sidebar, select **Wiki**.
+ - On any page in the project, use the <kbd>g</kbd> + <kbd>w</kbd>
+ [wiki keyboard shortcut](../../shortcuts.md).
+
+## Export a group wiki
+
+> Introduced in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53247).
+
+Users with the [Owner role](../../permissions.md) in a group can
+[import and export group wikis](../../group/settings/import_export.md) when importing
+or exporting a group.
+
+Content created in a group wiki is not deleted when an account is downgraded or a
+GitLab trial ends. The group wiki data is exported whenever the group owner of
+the wiki is exported.
+
+To access the group wiki data from the export file if the feature is no longer
+available, you have to:
+
+1. Extract the [export file tarball](../../group/settings/import_export.md) with
+ this command, replacing `FILENAME` with your file's name:
+ `tar -xvzf FILENAME.tar.gz`
+1. Browse to the `repositories` directory. This directory contains a
+ [Git bundle](https://git-scm.com/docs/git-bundle) with the extension `.wiki.bundle`.
+1. Clone the Git bundle into a new repository, replacing `FILENAME` with
+ your bundle's name: `git clone FILENAME.wiki.bundle`
+
+All files in the wiki are available in this Git repository.
+
+## Related topics
+
+- [Wiki settings for administrators](../../../administration/wikis/index.md)
+- [Project wikis API](../../../api/wikis.md)
+- [Group repository storage moves API](../../../api/group_repository_storage_moves.md)
+- [Group wikis API](../../../api/group_wikis.md)
+- [Wiki keyboard shortcuts](../../shortcuts.md#wiki-pages)
+- [Epic: Feature parity with project wikis](https://gitlab.com/groups/gitlab-org/-/epics/2782)
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index e2a8167b14c..5d2a0530f68 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -12,16 +12,6 @@ to keep it in the same project as your code, you can use the wiki GitLab provide
in each GitLab project. Every wiki is a separate Git repository, so you can create
wiki pages in the web interface, or [locally using Git](#create-or-edit-wiki-pages-locally).
-To access the wiki for a project or group, go to the page for your project or group
-and either:
-
-- In the left sidebar, select **Wiki**.
-- On any page in the project, use the <kbd>g</kbd> + <kbd>w</kbd>
- [wiki keyboard shortcut](../../shortcuts.md).
-
-If **Wiki** is not listed in the left sidebar of your project, a project administrator
-has [disabled it](#enable-or-disable-a-project-wiki).
-
GitLab wikis support Markdown, RDoc, AsciiDoc, and Org for content.
Wiki pages written in Markdown support all [Markdown features](../../markdown.md),
and also provide some [wiki-specific behavior](../../markdown.md#wiki-specific-markdown)
@@ -35,6 +25,19 @@ with sibling pages listed in alphabetical order. To view a list of all pages, se
![Wiki sidebar](img/wiki_sidebar_v13_5.png)
+## View a project wiki
+
+To access a project wiki:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. To display the wiki, either:
+ - On the left sidebar, select **Wiki**.
+ - On any page in the project, use the <kbd>g</kbd> + <kbd>w</kbd>
+ [wiki keyboard shortcut](../../shortcuts.md).
+
+If **Wiki** is not listed in the left sidebar of your project, a project administrator
+has [disabled it](#enable-or-disable-a-project-wiki).
+
## Configure a default branch for your wiki
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221159) in GitLab 14.1.
@@ -56,7 +59,10 @@ When a wiki is created, it is empty. On your first visit, you can create the
home page users see when viewing the wiki. This page requires a specific title
to be used as your wiki's home page. To create it:
-1. Go to your project or group and select **Wiki**.
+1. On the top bar, select **Menu**.
+ - For project wikis, select **Projects** and find your project.
+ - For group wikis, select **Groups** and find your group.
+1. On the left sidebar, select **Wiki**.
1. Select **Create your first page**.
1. GitLab requires this first page be titled `home`. The page with this
title serves as the front page for your wiki.
@@ -71,7 +77,10 @@ to be used as your wiki's home page. To create it:
Users with the [Developer role](../../permissions.md) can create new wiki pages:
-1. Go to your project or group and select **Wiki**.
+1. On the top bar, select **Menu**.
+ - For project wikis, select **Projects** and find your project.
+ - For group wikis, select **Groups** and find your group.
+1. On the left sidebar, select **Wiki**.
1. Select **New page** on this page, or any other wiki page.
1. Select a content format.
1. Add a title for your new page. Page titles use
@@ -135,7 +144,10 @@ may not be able to check out the wiki locally afterward.
You need at least the [Developer role](../../permissions.md) to edit a wiki page:
-1. Go to your project or group and select **Wiki**.
+1. On the top bar, select **Menu**.
+ - For project wikis, select **Projects** and find your project.
+ - For group wikis, select **Groups** and find your group.
+1. On the left sidebar, select **Wiki**.
1. Go to the page you want to edit, and either:
- Use the <kbd>e</kbd> wiki [keyboard shortcut](../../shortcuts.md#wiki-pages).
- Select the edit icon (**{pencil}**).
@@ -151,7 +163,10 @@ For an example, read [Table of contents](../../markdown.md#table-of-contents).
You need at least the [Developer role](../../permissions.md) to delete a wiki page:
-1. Go to your project or group and select **Wiki**.
+1. On the top bar, select **Menu**.
+ - For project wikis, select **Projects** and find your project.
+ - For group wikis, select **Groups** and find your group.
+1. On the left sidebar, select **Wiki**.
1. Go to the page you want to delete.
1. Select the edit icon (**{pencil}**).
1. Select **Delete page**.
@@ -161,7 +176,10 @@ You need at least the [Developer role](../../permissions.md) to delete a wiki pa
You need at least the [Developer role](../../permissions.md) to move a wiki page:
-1. Go to your project or group and select **Wiki**.
+1. On the top bar, select **Menu**.
+ - For project wikis, select **Projects** and find your project.
+ - For group wikis, select **Groups** and find your group.
+1. On the left sidebar, select **Wiki**.
1. Go to the page you want to move.
1. Select the edit icon (**{pencil}**).
1. Add the new path to the **Title** field. For example, if you have a wiki page
@@ -172,9 +190,7 @@ You need at least the [Developer role](../../permissions.md) to move a wiki page
## View history of a wiki page
The changes of a wiki page over time are recorded in the wiki's Git repository.
-To view the changes for a wiki page, select **Page history**.
-
-From the history page you can see:
+The history page shows:
![Wiki page history](img/wiki_page_history.png)
@@ -184,13 +200,25 @@ From the history page you can see:
- The last update.
- Previous revisions, by selecting a revision number in the **Page version** column.
+To view the changes for a wiki page:
+
+1. On the top bar, select **Menu**.
+ - For project wikis, select **Projects** and find your project.
+ - For group wikis, select **Groups** and find your group.
+1. On the left sidebar, select **Wiki**.
+1. Go to the page you want to view history for.
+1. Select **Page history**.
+
### View changes between page versions
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15242) in GitLab 13.2.
You can see the changes made in a version of a wiki page, similar to versioned diff file views:
-1. Go to your project or group and select **Wiki**.
+1. On the top bar, select **Menu**.
+ - For project wikis, select **Projects** and find your project.
+ - For group wikis, select **Groups** and find your group.
+1. On the left sidebar, select **Wiki**.
1. Go to the wiki page you're interested in.
1. Select **Page history** to see all page versions.
1. Select the commit message in the **Changes** column for the version you're interested in.
@@ -203,10 +231,12 @@ You can see the changes made in a version of a wiki page, similar to versioned d
> - Git events were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216014) in **GitLab 13.0.**
> - [Feature flag for Git events was removed](https://gitlab.com/gitlab-org/gitlab/-/issues/258665) in **GitLab 13.5**
-GitLab tracks wiki creation, deletion, and update events. These events are displayed on the
-[user profile](../../profile/index.md#access-your-user-profile),
-[group](../../group/index.md#view-group-activity),
-and [project](../working_with_projects.md#project-activity) activity pages.
+GitLab tracks wiki creation, deletion, and update events. These events are displayed on these pages:
+
+- [User profile](../../profile/index.md#access-your-user-profile).
+- Activity pages, depending on the type of wiki:
+ - [Group activity](../../group/index.md#view-group-activity).
+ - [Project activity](../working_with_projects.md#project-activity).
Commits to wikis are not counted in [repository analytics](../../analytics/repository_analytics.md).
@@ -218,7 +248,10 @@ You need at least the [Developer role](../../permissions.md) to customize the wi
navigation sidebar. This process creates a wiki page named `_sidebar` which fully
replaces the default sidebar navigation:
-1. Go to your project or group and select **Wiki**.
+1. On the top bar, select **Menu**.
+ - For project wikis, select **Projects** and find your project.
+ - For group wikis, select **Groups** and find your group.
+1. On the left sidebar, select **Wiki**.
1. In the top right corner of the page, select **Edit sidebar**.
1. When complete, select **Save changes**.
@@ -241,42 +274,20 @@ Support for displaying a generated table of contents with a custom side navigati
## Enable or disable a project wiki
Wikis are enabled by default in GitLab. Project [administrators](../../permissions.md)
-can enable or disable the project wiki by following the instructions in
+can enable or disable a project wiki by following the instructions in
[Sharing and permissions](../settings/index.md#sharing-and-permissions).
Administrators for self-managed GitLab installs can
[configure additional wiki settings](../../../administration/wikis/index.md).
-## Group wikis **(PREMIUM)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13195) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5.
-
-Group wikis work the same way as project wikis. Their usage is similar to project
-wikis, with a few limitations:
-
-- Git LFS is not supported.
-- Group wikis are not included in global search.
-- Changes to group wikis don't show up in the group's activity feed.
-
-For updates, follow [the epic that tracks feature parity with project wikis](https://gitlab.com/groups/gitlab-org/-/epics/2782).
-
-Group wikis can be edited by members with the [Developer role](../../permissions.md#group-members-permissions)
-and above. Group wiki repositories can be moved using the
-[Group repository storage moves API](../../../api/group_repository_storage_moves.md).
-
-### Export a group wiki **(PREMIUM)**
-
-Users with the [Owner role](../../permissions.md) in a group can
-[import and export group wikis](../../group/settings/import_export.md) when importing
-or exporting a group.
-
-Content created in a group wiki is not deleted when an account is downgraded or a GitLab trial ends.
+You can't disable [group wikis](group.md) from the GitLab user interface.
## Link an external wiki
To add a link to an external wiki from a project's left sidebar:
-1. Go to your project and select **Settings > Integrations**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Integrations**.
1. Select **External wiki**.
1. Add the URL to your external wiki.
1. (Optional) Select **Test settings** to verify the connection.
@@ -291,7 +302,8 @@ To hide the internal wiki from the sidebar, [disable the project's wiki](#disabl
To hide the link to an external wiki:
-1. Go to your project and select **Settings > Integrations**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Integrations**.
1. Select **External wiki**.
1. In the **Enable integration** section, clear the **Active** checkbox.
1. Select **Save changes**.
@@ -300,6 +312,7 @@ To hide the link to an external wiki:
To disable a project's internal wiki:
+1. On the top bar, select **Menu > Projects** and find your project.
1. Go to your project and select **Settings > General**.
1. Expand **Visibility, project features, permissions**.
1. Scroll down to find **Wiki** and toggle it off (in gray).
@@ -356,7 +369,7 @@ For the status of the ongoing development for CommonMark and GitLab Flavored Mar
- [Basic Markdown formatting extensions](https://gitlab.com/groups/gitlab-org/-/epics/5404) epic.
- [GitLab Flavored Markdown extensions](https://gitlab.com/groups/gitlab-org/-/epics/5438) epic.
-## Resources
+## Related topics
- [Wiki settings for administrators](../../../administration/wikis/index.md)
- [Project wikis API](../../../api/wikis.md)
diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md
index 11b570f19e5..3c82e544e26 100644
--- a/doc/user/project/working_with_projects.md
+++ b/doc/user/project/working_with_projects.md
@@ -13,7 +13,7 @@ code are saved in projects, and most features are in the scope of projects.
You can explore other popular projects available on GitLab. To explore projects:
-1. On the top bar, select **Menu > Project**.
+1. On the top bar, select **Menu > Projects**.
1. Select **Explore projects**.
GitLab displays a list of projects, sorted by last updated date. To view
@@ -25,12 +25,27 @@ By default, `/explore` is visible to unauthenticated users. However, if the
[**Public** visibility level](../admin_area/settings/visibility_and_access_controls.md#restrict-visibility-levels)
is restricted, `/explore` is visible only to signed-in users.
+## Explore topics
+
+You can explore popular project topics available on GitLab. To explore project topics:
+
+1. On the top bar, select **Menu > Projects**.
+1. Select **Explore topics**.
+
+GitLab displays a list of topics sorted by the number of associated projects.
+To view projects associated with a topic, select a topic from the list.
+
+You can assign topics to a project on the [Project Settings page](settings/index.md#topics).
+
+If you're an instance administrator, you can administer all project topics from the
+[Admin Area's Topics page](../admin_area/index.md#administering-topics).
+
## Create a project
To create a project in GitLab:
-1. In your dashboard, click the green **New project** button or use the plus
- icon in the navigation bar. This opens the **New project** page.
+1. In your dashboard, select **New project** or use the **New...** **{plus-square}** icon
+on the top bar. The **New project** page opens.
1. On the **New project** page, choose if you want to:
- Create a [blank project](#blank-projects).
- Create a project using one of the available [project templates](#project-templates).
@@ -213,7 +228,7 @@ To star a project:
To view your starred projects:
-1. On the top bar, select **Menu > Project**.
+1. On the top bar, select **Menu > Projects**.
1. Select **Starred Projects**.
1. GitLab displays information about your starred projects, including:
diff --git a/doc/user/report_abuse.md b/doc/user/report_abuse.md
index a8107d77113..810e1427e11 100644
--- a/doc/user/report_abuse.md
+++ b/doc/user/report_abuse.md
@@ -19,6 +19,7 @@ You can report a user through their:
- [Profile](#reporting-abuse-through-a-users-profile)
- [Comments](#reporting-abuse-through-a-users-comment)
- [Issues and Merge requests](#reporting-abuse-through-a-users-issue-or-merge-request)
+- [Snippets](snippets.md#mark-snippet-as-spam)
## Reporting abuse through a user's profile
diff --git a/doc/user/search/advanced_search.md b/doc/user/search/advanced_search.md
index f994539b9fc..f68951badff 100644
--- a/doc/user/search/advanced_search.md
+++ b/doc/user/search/advanced_search.md
@@ -26,7 +26,7 @@ when searching in:
- Comments
- Code
- Commits
-- Wiki
+- Wiki (except [group wikis](../project/wiki/group.md))
- Users
The Advanced Search can be useful in various scenarios:
@@ -139,4 +139,4 @@ its performance:
| Commits | `global_search_commits_tab` | When enabled, the global search includes commits as part of the search. |
| Issues | `global_search_issues_tab` | When enabled, the global search includes issues as part of the search. |
| Merge Requests | `global_search_merge_requests_tab` | When enabled, the global search includes merge requests as part of the search. |
-| Wiki | `global_search_wiki_tab` | When enabled, the global search includes wiki as part of the search. |
+| Wiki | `global_search_wiki_tab` | When enabled, the global search includes wiki as part of the search. [Group wikis](../project/wiki/group.md) are not included. |
diff --git a/doc/user/search/img/basic_search.png b/doc/user/search/img/basic_search_v14_4.png
index 86aab68f1f0..86aab68f1f0 100644
--- a/doc/user/search/img/basic_search.png
+++ b/doc/user/search/img/basic_search_v14_4.png
Binary files differ
diff --git a/doc/user/search/img/issues_mrs_shortcut.png b/doc/user/search/img/issues_mrs_shortcut.png
deleted file mode 100644
index 5be8079030a..00000000000
--- a/doc/user/search/img/issues_mrs_shortcut.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/issues_mrs_shortcut_v14_4.png b/doc/user/search/img/issues_mrs_shortcut_v14_4.png
new file mode 100644
index 00000000000..2610e611446
--- /dev/null
+++ b/doc/user/search/img/issues_mrs_shortcut_v14_4.png
Binary files differ
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 7cf62f09303..325e5386417 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -35,7 +35,7 @@ You can also filter the results using the search and filter field, as described
GitLab shows shortcuts to issues and merge requests created by you or assigned to you
in the search field in the upper right corner:
-![shortcut to your issues and merge requests](img/issues_mrs_shortcut.png)
+![shortcut to your issues and merge requests](img/issues_mrs_shortcut_v14_4.png)
### Filter issue and merge request lists
@@ -118,7 +118,7 @@ You can add this URL to your feed reader.
You can filter the **Issues** list to individual instances by their ID. For example, enter filter `#10` to return only issue 10. The same applies to the **Merge Requests** list. Enter filter `#30` to return only merge request 30.
-![filter issues by specific id](img/issue_search_by_id.png)
+![filter issues by specific ID](img/issue_search_by_id.png)
### Filtering merge requests by approvers **(PREMIUM)**
@@ -290,7 +290,7 @@ To start a search, type into the search bar on the top-right of the screen. You
in all GitLab and may also see the options to search in a group or project if you are in the
group or project dashboard.
-![basic search](img/basic_search.png)
+![basic search](img/basic_search_v14_4.png)
After the results are returned, you can modify the search, select a different type of data to
search, or choose a specific group or project.
@@ -321,9 +321,10 @@ GitLab instance.
## Search settings
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292941) in GitLab 13.8 behind a feature flag, disabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292941) in GitLab 13.8 [with a flag](../../administration/feature_flags.md) named `search_settings_in_page`. Disabled by default.
> - [Added to Group, Administrator, and User settings](https://gitlab.com/groups/gitlab-org/-/epics/4842) in GitLab 13.9.
-> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/294025) in GitLab 13.11.
+> - [Feature flag `search_settings_in_page` removed](https://gitlab.com/gitlab-org/gitlab/-/issues/294025) in GitLab 13.11.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/294025) in GitLab 13.11.
You can search inside a Project, Group, Administrator, or User's settings by entering
a search term in the search box located at the top of the page. The search results
diff --git a/doc/user/shortcuts.md b/doc/user/shortcuts.md
index f46c5428248..d6cbbf352fc 100644
--- a/doc/user/shortcuts.md
+++ b/doc/user/shortcuts.md
@@ -43,6 +43,7 @@ These shortcuts are available in most areas of GitLab:
| <kbd>Shift</kbd> + <kbd>t</kbd> | Go to your To-Do List page. |
| <kbd>p</kbd> + <kbd>b</kbd> | Show or hide the Performance Bar. |
| <kbd>g</kbd> + <kbd>x</kbd> | Toggle between [GitLab](https://gitlab.com/) and [GitLab Next](https://next.gitlab.com/) (GitLab SaaS only). |
+| <kbd>.</kbd> | Open the [Web IDE](project/web_ide/index.md). |
Additionally, the following shortcuts are available when editing text in text
fields (for example, comments, replies, issue descriptions, and merge request
@@ -101,6 +102,7 @@ These shortcuts are available when viewing issues and [merge requests](project/m
| <kbd>]</kbd> or <kbd>j</kbd> | Move to next file (merge requests only). |
| <kbd>[</kbd> or <kbd>k</kbd> | Move to previous file (merge requests only). |
| <kbd>b</kbd> | Copy source branch name (merge requests only). |
+| <kbd>.</kbd> | Open the [Web IDE](project/web_ide/index.md). |
### Project files
@@ -114,6 +116,7 @@ These shortcuts are available when browsing the files in a project (go to
| <kbd>enter</kbd> | Open selection. |
| <kbd>Escape</kbd> | Go back to file list screen (only while searching for files, **Repository > Files**, then select **Find File**). |
| <kbd>y</kbd> | Go to file permalink (only while viewing a file). |
+| <kbd>.</kbd> | Open the [Web IDE](project/web_ide/index.md). |
### Web IDE
diff --git a/doc/user/snippets.md b/doc/user/snippets.md
index 64da024f5ba..e2cb9937f76 100644
--- a/doc/user/snippets.md
+++ b/doc/user/snippets.md
@@ -14,6 +14,9 @@ You can [comment on](#comment-on-snippets), [clone](#clone-snippets), and
[syntax highlighting](#filenames), [embedding](#embed-snippets), [downloading](#download-snippets),
and you can maintain your snippets with the [snippets API](../api/snippets.md).
+You can create and manage your snippets through the GitLab user interface, or by
+using the [GitLab Workflow VS Code extension](project/repository/vscode.md).
+
![Example of snippet](img/snippet_intro_v13_11.png)
GitLab provides two types of snippets:
@@ -39,6 +42,8 @@ You can create snippets in multiple ways, depending on whether you want to creat
- *For all other pages,* select the plus icon (**{plus-square-o}**)
in the top navigation bar, then select **New snippet** from the dropdown
menu.
+ - If you installed the [GitLab Workflow VS Code extension](project/repository/vscode.md),
+ use the [`Gitlab: Create snippet` command](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#create-snippet).
- **To create a project snippet**: Go to your project's page. Select the
plus icon (**{plus-square-o}**), and then select **New snippet** from the
**This project** section of the dropdown menu.
@@ -127,7 +132,7 @@ A single snippet can support up to 10 files, which helps keep related files toge
If you need more than 10 files for your snippet, we recommend you create a
[wiki](project/wiki/index.md) instead. Wikis are available for projects at all
-subscription levels, and [groups](project/wiki/index.md#group-wikis) for
+subscription levels, and [groups](project/wiki/group.md) for
[GitLab Premium](https://about.gitlab.com/pricing/).
Snippets with multiple files display a file count in the [snippet list](https://gitlab.com/dashboard/snippets):
@@ -206,6 +211,24 @@ snippet was created using the GitLab web interface the original line ending is W
With snippets, you engage in a conversation about that piece of code,
which can encourage user collaboration.
+## Mark snippet as spam **(FREE SELF)**
+
+Administrators on self-managed GitLab instances can mark snippets as spam.
+
+Prerequisites:
+
+- You must be the administrator for your instance.
+- [Akismet](../integration/akismet.md) spam protection must be enabled on the instance.
+
+To do this task:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Snippets**.
+1. Select the snippet you want to report as spam.
+1. Select **Submit as spam**.
+
+GitLab forwards the spam to Akismet.
+
## Troubleshooting
### Snippet limitations
diff --git a/doc/user/tasks.md b/doc/user/tasks.md
new file mode 100644
index 00000000000..e5e5510407e
--- /dev/null
+++ b/doc/user/tasks.md
@@ -0,0 +1,34 @@
+---
+stage: Plan
+group: Project Management
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Tasks **(FREE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334812) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `work_items`. Disabled by default.
+
+WARNING:
+Tasks are in **Alpha**. Current implementation does not have any API requests and works with mocked data.
+For the latest updates, check the [Tasks Roadmap](https://gitlab.com/groups/gitlab-org/-/epics/7103).
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available,
+ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `work_items`.
+The feature is not ready for production use.
+
+Use tasks to track steps needed for the [issue](project/issues/index.md) to be closed.
+
+When planning an issue, you need a way to capture and break down technical
+requirements or steps necessary to complete it. An issue with tasks is better defined,
+and so you can provide a more accurate issue weight and completion criteria.
+
+To see the roadmap for migrating issues and [epics](group/epics/index.md)
+to work items and adding custom work item types, visit
+[epic 6033](https://gitlab.com/groups/gitlab-org/-/epics/6033) or
+[Plan direction page](https://about.gitlab.com/direction/plan/).
+
+## View a task
+
+The only way to view a task is to open it with a deep link,
+for example: `/<group_name>/<project_name>/-/work_item/1`
diff --git a/doc/user/usage_quotas.md b/doc/user/usage_quotas.md
index 5a48353c9d4..16b6424b232 100644
--- a/doc/user/usage_quotas.md
+++ b/doc/user/usage_quotas.md
@@ -36,9 +36,8 @@ namespace to recalculate the storage.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68898) project-level graph in GitLab 14.4 [with a flag](../administration/feature_flags.md) named `project_storage_ui`. Disabled by default.
> - Enabled on GitLab.com in GitLab 14.4.
-
-FLAG:
-On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `project_storage_ui`. On GitLab.com, this feature is available.
+> - Enabled on self-managed in GitLab 14.5.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71270) in GitLab 14.5.
The following storage usage statistics are available to an owner:
diff --git a/doc/user/workspace/index.md b/doc/user/workspace/index.md
index d75d91f087d..8ca7f7defb2 100644
--- a/doc/user/workspace/index.md
+++ b/doc/user/workspace/index.md
@@ -46,3 +46,7 @@ The following provide a preview to the Workspace concept.
![Admin Overview](img/Admin_Settings.png)
![Admin Overview](img/hardware_settings.png)
+
+## Related topics
+
+- [Workspaces developer documentation](../../development/workspaces/index.md)
diff --git a/fixtures/emojis/aliases.json b/fixtures/emojis/aliases.json
index 415dd5a54e0..f549d20cd73 100644
--- a/fixtures/emojis/aliases.json
+++ b/fixtures/emojis/aliases.json
@@ -337,7 +337,6 @@
"fox_face":"fox",
"frame_with_picture":"frame_photo",
"baguette_bread":"french_bread",
- "anguished":"frowning",
"white_frowning_face":"frowning2",
"rainbow_flag":"gay_pride_flag",
"goal_net":"goal",
diff --git a/fixtures/emojis/digests.json b/fixtures/emojis/digests.json
index 3c8f6426f93..4b8a74d62e5 100644
--- a/fixtures/emojis/digests.json
+++ b/fixtures/emojis/digests.json
@@ -4,12550 +4,12557 @@
"moji": "💯",
"description": "hundred points symbol",
"unicodeVersion": "6.0",
- "digest": "add3bd7d06b6dd445788b277f8c9e5dcf42a54d3ec8b7fb9e7a39695dd95d094"
+ "digest": "66b1338bd0bc6efa35033dec6d9f8962c98f1eda08e50bae6a319e7f069ae861"
},
"1234": {
"category": "symbols",
"moji": "🔢",
"description": "input symbol for numbers",
"unicodeVersion": "6.0",
- "digest": "c5ac5c8147f5bfd644fad6b470432bba86ffc7bcee04a0e0d277cd1ca485207f"
+ "digest": "6f276a9127f2de22f508978bd645974d5e21dfd3cf138e0cb00f33599677b533"
},
"8ball": {
"category": "activity",
"moji": "🎱",
"description": "billiards",
"unicodeVersion": "6.0",
- "digest": "a6e6855775b66c505adee65926a264103ebddf2e2d963db7c009b4fec3a24178"
+ "digest": "de5dbbd700f078ed6d780e79cb1b5b3214180b42a38917b3e1222af731cf5e3d"
},
"a": {
"category": "symbols",
"moji": "🅰",
"description": "negative squared latin capital letter a",
"unicodeVersion": "6.0",
- "digest": "bddbb39e8a1d35d42b7c08e7d47f63988cb4d8614b79f74e70b9c67c221896cc"
+ "digest": "3a5aea7fbabb9e1a5e364f937704fd21296323470fdb1e2bf767d07516c94d21"
},
"ab": {
"category": "symbols",
"moji": "🆎",
"description": "negative squared ab",
"unicodeVersion": "6.0",
- "digest": "67430fe5fce981160e2ea9052962e49f264322d3abfc2828fbc311b6cdf67ae8"
+ "digest": "2a58932a5ab57aa3c82f77e5df5cd9ce5103667483bb93a6c96f31e171577654"
},
"abc": {
"category": "symbols",
"moji": "🔤",
"description": "input symbol for latin letters",
"unicodeVersion": "6.0",
- "digest": "282c817ee3414d77a74b815962c33dd9fe71fabaea8c7a9cec466100fbe32187"
+ "digest": "9991fd68e58377848e6e1b8d4b74bdbfd09e575686047651f139c126e9df6c4c"
},
"abcd": {
"category": "symbols",
"moji": "🔡",
"description": "input symbol for latin small letters",
"unicodeVersion": "6.0",
- "digest": "686728c759f4683c64762ee4eda0a91bf2041f0ae4f358aacf6c09bf51892eff"
+ "digest": "ad9982f0e3f4c346a6536d8b2a65c625f05278510910f656e59a6d280a90d3c2"
},
"accept": {
"category": "symbols",
"moji": "🉑",
"description": "circled ideograph accept",
"unicodeVersion": "6.0",
- "digest": "7208d34c761f10a7fd28f98e25535eba13ff91a64442fc282a98bb77722614f1"
+ "digest": "d4dcdfdb5dfcd5374044568d879662e89bb5269fb789901e5468c07243f32143"
},
"aerial_tramway": {
"category": "travel",
"moji": "🚡",
"description": "aerial tramway",
"unicodeVersion": "6.0",
- "digest": "98df666f34370fc34ce280d84bba5a7e617f733fbbfe66caa424b2afa6ab6777"
+ "digest": "716dae206b786d985ddfa6b311369a708d00539f35b2612500afb19ac537261d"
},
"airplane": {
"category": "travel",
"moji": "✈",
"description": "airplane",
"unicodeVersion": "1.1",
- "digest": "cc12cf259ef88e57717620cd2bd5aa6a02a8631ee532a3bde24bee78edc5de33"
+ "digest": "b223b20d905ace04c602f7fcf22eb66c8defb22f2589434a83ae39e1622dcc67"
},
"airplane_arriving": {
"category": "travel",
"moji": "🛬",
"description": "airplane arriving",
"unicodeVersion": "7.0",
- "digest": "80d5b4675f91c4cff06d146d795a065b0ce2a74557df4d9e3314e3d3b5c4ae82"
+ "digest": "a8ea037bc27226bd7e7ce07fdcedfcc74d0cd9c99737c93f2a588066c01fe1fe"
},
"airplane_departure": {
"category": "travel",
"moji": "🛫",
"description": "airplane departure",
"unicodeVersion": "7.0",
- "digest": "5544eace06b8e1b6ea91940e893e013d33d6b166e14e6d128a87f2cd2de88332"
+ "digest": "c371879cd5b6bd5df2954f5c6c7eb5b07b3358253e8b35cd806ca21e2af2d794"
},
"airplane_small": {
"category": "travel",
"moji": "🛩",
"description": "small airplane",
"unicodeVersion": "7.0",
- "digest": "1a2e07abbbe90d05cee7ff8dd52f443d595ccb38959f3089fe016b77e5d6de7d"
+ "digest": "ad2f6b4f6f141bd184c743c31fa0eadbef7653f1915b410c8144293dbb4b3720"
},
"alarm_clock": {
"category": "objects",
"moji": "â°",
"description": "alarm clock",
"unicodeVersion": "6.0",
- "digest": "fef05a3cd1cddbeca4de8091b94bddb93790b03fa213da86c0eec420f8c49599"
+ "digest": "b125863048df0f332c2af68df61d919d3ff61863bced1aca9269759aff4dfe10"
},
"alembic": {
"category": "objects",
"moji": "âš—",
"description": "alembic",
"unicodeVersion": "4.1",
- "digest": "c94b2a4bf24ccf4db27a22c9725cfe900f4a99ec49ef2411d67952bcb2ca1bfb"
+ "digest": "9af1181b6190b06ed4fd78d13c64d17c16a59f9b1b512fb0b92a9be9cfb92a2b"
},
"alien": {
"category": "people",
"moji": "👽",
"description": "extraterrestrial alien",
"unicodeVersion": "6.0",
- "digest": "856ba98202b244c13a5ee3014a6f7ad592d8c119a30d79e4fc790b74b0e321f7"
+ "digest": "77ecf901092da0e96501eb86281f2d85d5c813dba15dbaf490f024a835c8da58"
},
"ambulance": {
"category": "travel",
"moji": "🚑",
"description": "ambulance",
"unicodeVersion": "6.0",
- "digest": "d9b3c1873de496a4554e715342c72290fb69a9c6766d7885f38bfe9491d052da"
+ "digest": "1ca176a46c2f020e0386e7a0ab662711f66af1683ae165c06853ec5b6bcc4cf1"
},
"amphora": {
"category": "objects",
"moji": "ðŸº",
"description": "amphora",
"unicodeVersion": "8.0",
- "digest": "4015f907b649b5e348502cc0e3685ed184e180dca5cc81c43ec516e14df127bf"
+ "digest": "ce9f7d0bd6b4d04c033eb2b3b8c2d339e4a8d19ef46cb23e500cd2854578d4e5"
},
"anchor": {
"category": "travel",
"moji": "âš“",
"description": "anchor",
"unicodeVersion": "4.1",
- "digest": "2b29b34ef896ebab70016301e3d1880209bbc3c5a5b8d832e43afff9b17ad792"
+ "digest": "b5f2eacb26d6e550286eb7c01beb0bd5072baf33f6c68c8d7110f634a8b2fdf6"
},
"angel": {
"category": "people",
"moji": "👼",
"description": "baby angel",
"unicodeVersion": "6.0",
- "digest": "db75c2460aaf9cd07cb41fe22c8a6079f3667ffe612a71611358720e2b5512a4"
+ "digest": "93d8abd48b9a0eac8332ed79e1f95c206dd29895e74d31931db32f4feab664fb"
},
"angel_tone1": {
"category": "people",
"moji": "👼ðŸ»",
"description": "baby angel tone 1",
"unicodeVersion": "8.0",
- "digest": "5871a622469b96296365adaf77d83167759692124c20e5a6e062a525af33472a"
+ "digest": "032faac5736197bb9a75da5743891334264d278378f8510b40623c02bc597601"
},
"angel_tone2": {
"category": "people",
"moji": "👼ðŸ¼",
"description": "baby angel tone 2",
"unicodeVersion": "8.0",
- "digest": "f5993198a5d9daf39e761c783461f07bca237f4e9b739ac300bb8ca001a69a1a"
+ "digest": "2f37a1d960eba5ada71b166c4371fdeb69f560f57759de1b24984d0848f74c68"
},
"angel_tone3": {
"category": "people",
"moji": "👼ðŸ½",
"description": "baby angel tone 3",
"unicodeVersion": "8.0",
- "digest": "f0c97a7c4354626267d6ab0f388e4297ad255ab9b061f9c68fbcaa0abfc52783"
+ "digest": "96fb1d8e568752aed2c716a062ef650cf4ccca609fdf78cde2e81e3e8f86a098"
},
"angel_tone4": {
"category": "people",
"moji": "👼ðŸ¾",
"description": "baby angel tone 4",
"unicodeVersion": "8.0",
- "digest": "6e5dc724c1939d1b0d1a91343662b5bd61ced7709c97802977145ffab6a1f7ac"
+ "digest": "b17721fd657278ee719963b0df074a9290c52cf58d094ed2722881030f57a79e"
},
"angel_tone5": {
"category": "people",
"moji": "👼ðŸ¿",
"description": "baby angel tone 5",
"unicodeVersion": "8.0",
- "digest": "52186e1de350c27d25d6010edf44f64a30338b65912ca178429fbcfbd88113c2"
+ "digest": "c6ebaa89eb3b2e6ee6e16b483587a6f6b341cae187d282e27cf71d1a18117735"
},
"anger": {
"category": "symbols",
"moji": "💢",
"description": "anger symbol",
"unicodeVersion": "6.0",
- "digest": "332493913891aa0eda2743b4bb16c4682400f249998bf34eb292246c9009e17f"
+ "digest": "f63add6c0e9483fb1ee5d2fffdc6e0a818b233713a6da85f6ce1ec3da0a7049a"
},
"anger_right": {
"category": "symbols",
"moji": "🗯",
"description": "right anger bubble",
"unicodeVersion": "7.0",
- "digest": "8b049511ef3b1b28325841e2f87c60773eaf2f65cabba58d8b0ec3de9b10c0ae"
+ "digest": "f47446e92c821d4f4d1d9861b99b3b3fff69ef52364c0aea3d99dc8e5fa40c3e"
},
"angry": {
"category": "people",
"moji": "😠",
"description": "angry face",
"unicodeVersion": "6.0",
- "digest": "7e09e7e821f511606341fb5ce4011a8ed9809766ab86b7983ffa6ea352b39ec1"
+ "digest": "f4fb17bf4cacd87fefdf9f235a9f6d77a5b12514061bc277645bccd410d3720a"
+ },
+ "anguished": {
+ "category": "people",
+ "moji": "😧",
+ "description": "anguished face",
+ "unicodeVersion": "6.1",
+ "digest": "b0670af3e3d615d03f5e20b371b6ca7852583f5ac0b272018ac71cc67096dc56"
},
"ant": {
"category": "nature",
"moji": "ðŸœ",
"description": "ant",
"unicodeVersion": "6.0",
- "digest": "929abeaff7ba21ab71cd1ab798af7a6b611e3b3ce1af80cede09a116b223e442"
+ "digest": "d60a32588453dd0a17b55358089bc62e53f09fc262c7aa30a1d6fc2c1e7cde2c"
},
"apple": {
"category": "food",
"moji": "ðŸŽ",
"description": "red apple",
"unicodeVersion": "6.0",
- "digest": "2a1b85ce57e3d236ae7777dcf332ec37d03bfd7b19806521a353bc532083224d"
+ "digest": "2a2d7a1fb558b2f77f9ef57b11229992a6ba4a1a679707f6339fc47744d64df2"
},
"aquarius": {
"category": "symbols",
"moji": "â™’",
"description": "aquarius",
"unicodeVersion": "1.1",
- "digest": "fdc42cd41b0dace5eae6baba3143f1e40295d48a29e7103a5bba1d84a056c39d"
+ "digest": "a40fb6ccb866eaf296e083c57f46ca29f3d9732de897e62a8201481b526ae6b9"
},
"aries": {
"category": "symbols",
"moji": "♈",
"description": "aries",
"unicodeVersion": "1.1",
- "digest": "deb135debcde0a98f40361a84ab64d57c18b5b445cd2f4199e8936f052899737"
+ "digest": "4e35bd481a7c73be42faba7afa67c522b4340180efa18f0523e394a90a2944aa"
},
"arrow_backward": {
"category": "symbols",
"moji": "â—€",
"description": "black left-pointing triangle",
"unicodeVersion": "1.1",
- "digest": "e162ac82e90d1e925d479fa5c45b9340e0a53287be04e43cbbb2a89c7e7e45e4"
+ "digest": "c4e1ba32b806674ba5f7cdb1433d4b45cf9b31f546918aa5ad169c0c8af50a8a"
},
"arrow_double_down": {
"category": "symbols",
"moji": "â¬",
"description": "black down-pointing double triangle",
"unicodeVersion": "6.0",
- "digest": "03ca890b05338d40972c7a056d672df620a203c6ca52ff3ff530f1a710905507"
+ "digest": "079bfc85ed3a1b354a6c8d9d041ed2049c449a696a2a2d1ff11e65efc91bc420"
},
"arrow_double_up": {
"category": "symbols",
"moji": "â«",
"description": "black up-pointing double triangle",
"unicodeVersion": "6.0",
- "digest": "e753f05bce993d62d5dc79e33c441ced059381b6ce21fa3ea4200f1b3236e59d"
+ "digest": "79fe28485f924df1c66447c2e633ebc02d01ab46c0d2ad4b319f950f060d5525"
},
"arrow_down": {
"category": "symbols",
"moji": "⬇",
"description": "downwards black arrow",
"unicodeVersion": "4.0",
- "digest": "9bf1bd2ea652ca9321087de58c7a112ea04c35676a6ee0766154183f8b95af6c"
+ "digest": "70c8ffa3178143b62de0d2e739700456ed470f5990599f86f518307d77bace97"
},
"arrow_down_small": {
"category": "symbols",
"moji": "🔽",
"description": "down-pointing small red triangle",
"unicodeVersion": "6.0",
- "digest": "7766198bc60cf59d6cdaeeaa700c2282bfff2f0fdeb22cf4581ca284b87a3bb7"
+ "digest": "6432caec004e9eadb0d160cb857a2eeb43cfab1ace23a904fa5a624f56bfca95"
},
"arrow_forward": {
"category": "symbols",
"moji": "â–¶",
"description": "black right-pointing triangle",
"unicodeVersion": "1.1",
- "digest": "db77d9accd1e02224f5d612f79cd691e6befdf22063475204836be6572510fb7"
+ "digest": "b3f0c8db863157c1c4121602ecaee91845346b2b7a1ef0ad4d46744db7866e98"
},
"arrow_heading_down": {
"category": "symbols",
"moji": "⤵",
"description": "arrow pointing rightwards then curving downwards",
"unicodeVersion": "3.2",
- "digest": "f5396069c8f63c13e6c3e0ecd34267c932451309ade9c1171d410563153bf909"
+ "digest": "f351d6b66a0e73f41bc58446486c5fbe35d70b715fdc4ae9adef474df7aa1f69"
},
"arrow_heading_up": {
"category": "symbols",
"moji": "⤴",
"description": "arrow pointing rightwards then curving upwards",
"unicodeVersion": "3.2",
- "digest": "1cad71923fa3df24cf543cae4ce775b0f74936f2edd685fd86a7525c41a14568"
+ "digest": "b684802de1239962bd0c076a5a0aeb268d2cf43620dde214520817e522a60792"
},
"arrow_left": {
"category": "symbols",
"moji": "⬅",
"description": "leftwards black arrow",
"unicodeVersion": "4.0",
- "digest": "b629bb3dbe161ef89cfcfced0c7968a68e44a019ad509132987e4973bdc874e7"
+ "digest": "431289c3759f093a1a2f3460d6b912897098d3344a23a31fa9ce778c484f60ba"
},
"arrow_lower_left": {
"category": "symbols",
"moji": "↙",
"description": "south west arrow",
"unicodeVersion": "1.1",
- "digest": "879136ba0e24e6bf3be70118abcb716d71bd74f7b62347bc052b6533c0ea534d"
+ "digest": "53a95853a65f3add101d64cd4ca26d677b1519d388d9c5ac75088e1965e8b856"
},
"arrow_lower_right": {
"category": "symbols",
"moji": "↘",
"description": "south east arrow",
"unicodeVersion": "1.1",
- "digest": "86d52ac9b961991e3aaa6a9f9b5ace4db6ffd1b5c171c09c23b516473b55066d"
+ "digest": "603a00a2370d8872a037fdd195315bbbe936ccf12db2801bd93211a55068daa7"
},
"arrow_right": {
"category": "symbols",
"moji": "âž¡",
"description": "black rightwards arrow",
"unicodeVersion": "1.1",
- "digest": "45f26a1cbb0f00ed3609b39da52e9d9e896a77e361c4c8036b1bf8038171bd49"
+ "digest": "cca969d90670944613bcaa9463a35abfdbfa6474d1177683e2fa1327d8b52c91"
},
"arrow_right_hook": {
"category": "symbols",
"moji": "↪",
"description": "rightwards arrow with hook",
"unicodeVersion": "1.1",
- "digest": "4f452679c71bcea4fc4a701c55156fef3ddc1ebbc70570bedfc9d3a029637ab1"
+ "digest": "65e1489951134f221d8b7d45d6857321530dfad720c43fa0590d123b3cf29c00"
},
"arrow_up": {
"category": "symbols",
"moji": "⬆",
"description": "upwards black arrow",
"unicodeVersion": "4.0",
- "digest": "982b988ef6651d8a71867ba7c87f640f62dd0eeb0b7c358f5a5c37e8fe507b8b"
+ "digest": "9ea5aba6d658bc8bed6a8eb9ea073e010d916dd7e6cde9de71a760026754ed6a"
},
"arrow_up_down": {
"category": "symbols",
"moji": "↕",
"description": "up down arrow",
"unicodeVersion": "1.1",
- "digest": "645ed8fb6646f49bfd95af1752336deacdadbe5cba13904023a704288f3b0e2c"
+ "digest": "83bda8fd50d42e169679a9825df1f5d5b7c421c710fb965b9ad4885c3c61268a"
},
"arrow_up_small": {
"category": "symbols",
"moji": "🔼",
"description": "up-pointing small red triangle",
"unicodeVersion": "6.0",
- "digest": "4a8c5789c13a852517e639e7a62c2d331464e6fb0358985aa97c1515e97b5e8b"
+ "digest": "2335b064c64d375d54e4e59111cd169781e633969b57d57dd9e1abba7555e9f1"
},
"arrow_upper_left": {
"category": "symbols",
"moji": "↖",
"description": "north west arrow",
"unicodeVersion": "1.1",
- "digest": "79026f828d6ceb7c55a9542770962ba6dcd08203995f6ceeb70333a12307d376"
+ "digest": "035fd0f1149c8af6bec2c3dd09465b494427fcc34213749802e2e18e5ae8159a"
},
"arrow_upper_right": {
"category": "symbols",
"moji": "↗",
"description": "north east arrow",
"unicodeVersion": "1.1",
- "digest": "7e0f33dfbe65628991c170130d366a3e2cedaf8862ddfcaf3960f395d3da1926"
+ "digest": "e8894fed9c62b652add3bac3ad3dd84bf3a215c45a0883c6e701cc02f89e5bfc"
},
"arrows_clockwise": {
"category": "symbols",
"moji": "🔃",
"description": "clockwise downwards and upwards open circle arrows",
"unicodeVersion": "6.0",
- "digest": "88669679977f7157f0acaa9d6a1b77ccf84d25eb78c5bc8afcde38d3635e7144"
+ "digest": "0f4be61ded4f219dc1582b002635b538c15d40234e8571a3bfbc35921f0e83a6"
},
"arrows_counterclockwise": {
"category": "symbols",
"moji": "🔄",
"description": "anticlockwise downwards and upwards open circle ar",
"unicodeVersion": "6.0",
- "digest": "a2c6a6d3643c128aee3304cd03bb3d7cfe4d35d3ba825bc9c1142d7832b4426e"
+ "digest": "e94e5cd47117e7dd196d0b1f32a97f2f87e76b6ad2652359849cda8d773c284c"
},
"art": {
"category": "activity",
"moji": "🎨",
"description": "artist palette",
"unicodeVersion": "6.0",
- "digest": "b6bc6c4bfb594aadcbb641d006031867678504764bbe0ab84e7b08567a9498da"
+ "digest": "ee525dbf572a127ac99ccc165520e429e3d24f7cf3b8d787496b63415454d49c"
},
"articulated_lorry": {
"category": "travel",
"moji": "🚛",
"description": "articulated lorry",
"unicodeVersion": "6.0",
- "digest": "c115e6613ebd718268aa31d265e017138b9fb58bbb8201eb3f40de2380e460aa"
+ "digest": "35d63d2bb71429a9da433fa2464827f53996a738e22efd275b2326a6cc30063c"
},
"asterisk": {
"category": "symbols",
"moji": "*⃣",
"description": "keycap asterisk",
"unicodeVersion": "3.0",
- "digest": "33d92093f2914448d5a939cf62e8ee3e32931923abdef5f0210e8a8150fa312d"
+ "digest": "7f65396609bdbffe6bf305cbfe56c4274f063f235d9e505b66367a71ee1cf233"
},
"astonished": {
"category": "people",
"moji": "😲",
"description": "astonished face",
"unicodeVersion": "6.0",
- "digest": "f8531bdda5070d10492709085f4ff652b8be9be6458758940358b9fc594a1f14"
+ "digest": "ecfb4bc1b9617e8de75b5c7b97e09e97e7bac08de23d4e76ce27b3c04277ab0e"
},
"athletic_shoe": {
"category": "people",
"moji": "👟",
"description": "athletic shoe",
"unicodeVersion": "6.0",
- "digest": "1f90dc390e0dea679085465b7f9e786dfd7dd56a3b219987144ed37ab1e9bf95"
+ "digest": "74ad8b5b9f0612ab983841e94637e02e91fc0de90b4a12997be5d2a2eb56d12c"
},
"atm": {
"category": "symbols",
"moji": "ðŸ§",
"description": "automated teller machine",
"unicodeVersion": "6.0",
- "digest": "7d3ce6a6afb4951546883404b8e36904179f88f1aa533706cf7bf0bbe0d6fd3c"
+ "digest": "58d4d4ab5df9de2f88f7ce4af21f1e5146ebd61731967d47ec5209affd987a24"
},
"atom": {
"category": "symbols",
"moji": "âš›",
"description": "atom symbol",
"unicodeVersion": "4.1",
- "digest": "6b6bb83b00707a314e46ff8eefbda40978a291ec7881caba1b1ee273f49c1368"
+ "digest": "1a7ca89822b91c1acfe7a10d57c859bfa87b6797713efa2ec87f01d36d302056"
},
"avocado": {
"category": "food",
"moji": "🥑",
"description": "avocado",
"unicodeVersion": "9.0",
- "digest": "bc1fb203d63b18985598400925de24050bb192afda1cbf0813f85cb139869eff"
+ "digest": "465bdf47c670c469b14e17a61f6d60b5975aa8d2c1e8764c8e7305185f831d58"
},
"b": {
"category": "symbols",
"moji": "🅱",
"description": "negative squared latin capital letter b",
"unicodeVersion": "6.0",
- "digest": "722f9db9442e7c0fc0d0ac0f5291fbf47c6a0ac4d8abd42e97957da705fb82bf"
+ "digest": "ae89fc972ef5c80863022ef169e3ceb4bfdece3cf052fe9023516904db23b8a0"
},
"baby": {
"category": "people",
"moji": "👶",
"description": "baby",
"unicodeVersion": "6.0",
- "digest": "219ae5a571aaf90c060956cd1c56dcc27708c827cecdca3ba1122058a3c4847b"
+ "digest": "16999f24cdb63691baf5a2a8252de265a8a73bbd10ba0d4214c85b2f43c5b02e"
},
"baby_bottle": {
"category": "food",
"moji": "ðŸ¼",
"description": "baby bottle",
"unicodeVersion": "6.0",
- "digest": "4fb71689e9d634e8d1699cf454a71e43f2b5b1a5dbab0bf186626934fdf5b782"
+ "digest": "2bd1cb4a294c83eb07b6d12e2abf8ab42a5083941096dd11ee772cdb1b1e3091"
},
"baby_chick": {
"category": "nature",
"moji": "ðŸ¤",
"description": "baby chick",
"unicodeVersion": "6.0",
- "digest": "14119874e9b5548028dfb9cc593a541efc1d075ac839a565b92e0c3253cffe7e"
+ "digest": "997e1f93ed8fb08c4362d5b0907b8243dc623a62e6cf0b3a9034112f187a3314"
},
"baby_symbol": {
"category": "symbols",
"moji": "🚼",
"description": "baby symbol",
"unicodeVersion": "6.0",
- "digest": "fb4db66868cda45ea3879ffc2ff4f763c56d2d889ae0ab17fe171129ede02f98"
+ "digest": "19ea4b3a81368933b6e78901205747e4fbc1dcdbfc3162f27191c1a8e0c395f7"
},
"baby_tone1": {
"category": "people",
"moji": "👶ðŸ»",
"description": "baby tone 1",
"unicodeVersion": "8.0",
- "digest": "cd3faf223a298c34e05d469d9d0db08438d97df7fd82c0973f8a9e07d553f5b1"
+ "digest": "f6262f7773de6b2cdbd5f0464ccbdd9584d8077d11c8b27cf353329d8dfdbded"
},
"baby_tone2": {
"category": "people",
"moji": "👶ðŸ¼",
"description": "baby tone 2",
"unicodeVersion": "8.0",
- "digest": "5b4539e22e0dd726c27eb8af2357f9240a52aed3f710f3234571cff029cc6198"
+ "digest": "c90cf6fa9a95e38ab449cfd25bd422e4ead60351666dc9221ade4e2eac17f38e"
},
"baby_tone3": {
"category": "people",
"moji": "👶ðŸ½",
"description": "baby tone 3",
"unicodeVersion": "8.0",
- "digest": "720e740e1ac63c6372269132b1fb6e07a6b91f5c808cc3adef59f0b4500e5e72"
+ "digest": "290215d0ad2cd110ea918fa7020aff5b5e8b08849ff2a5acae5ed1f8e9f59958"
},
"baby_tone4": {
"category": "people",
"moji": "👶ðŸ¾",
"description": "baby tone 4",
"unicodeVersion": "8.0",
- "digest": "5e43b69c509bd526ad6f081764578c30b6f3285fb7442222e05ccf62e53bfb64"
+ "digest": "dfda26c31ab16afde0500631e08875205deb3ebd87bbb96e8b746ae49ecefa11"
},
"baby_tone5": {
"category": "people",
"moji": "👶ðŸ¿",
"description": "baby tone 5",
"unicodeVersion": "8.0",
- "digest": "85bba6e0940ccfb99999fe124e815f9dd340d00a5568e13967b02245a62dbf54"
+ "digest": "8c32dba5be741fb3c009e55e9766526dbfec3e90977c4ab24b8ee3472a38f8e8"
},
"back": {
"category": "symbols",
"moji": "🔙",
"description": "back with leftwards arrow above",
"unicodeVersion": "6.0",
- "digest": "083e4e48b51092c28efb4532e840e1091b5d4b685c6e0f221aa0228f061cd91e"
+ "digest": "c473fa1c3be08fb1920ce88072cf4f6ce3a031707d765d5e24b47aab0aac45be"
},
"bacon": {
"category": "food",
"moji": "🥓",
"description": "bacon",
"unicodeVersion": "9.0",
- "digest": "18ad3817f1f88a69706db5727a58e763dde6c21a2d4f184c3d728c32dc5fa05a"
+ "digest": "a076ea85c09e7783948f5710294c32d34487402779227bf47dc6f8d0fe7a9689"
},
"badminton": {
"category": "activity",
"moji": "ðŸ¸",
"description": "badminton racquet",
"unicodeVersion": "8.0",
- "digest": "353eb7ee93decd9fe0072e4d78a5618d5e2d9e77a6e4de9fe171870d75e02a66"
+ "digest": "52efeaba6a27cef40bbd624eb945bf8712c8ce3a135de8b979c1e04b440ec51a"
},
"baggage_claim": {
"category": "symbols",
"moji": "🛄",
"description": "baggage claim",
"unicodeVersion": "6.0",
- "digest": "7d6bceca92c266da6d2b91dfcf244546fc11022e039e7da8e6888c1696bb2186"
+ "digest": "c99d1d554d119f4a1f8ffa7f6c53d03071972d2f0907ffcba4f5ef92739edb1d"
},
"balloon": {
"category": "objects",
"moji": "🎈",
"description": "balloon",
"unicodeVersion": "6.0",
- "digest": "65760aedc1503b426927cff78c24449d563843a274961d962718fa9638375d54"
+ "digest": "9f76188ad32199d081dfc6757b68f66c8b4e8629f420e85d4cb88e00a72256ab"
},
"ballot_box": {
"category": "objects",
"moji": "🗳",
"description": "ballot box with ballot",
"unicodeVersion": "7.0",
- "digest": "4175a56eca5c6458574a681e109b1403fbb143cf27f69ae6c1917650f3e08892"
+ "digest": "375bf5ca28895dd54acc3f7927d62fed9d56ad79b5218f6f3be2533929ad47a5"
},
"ballot_box_with_check": {
"category": "symbols",
"moji": "☑",
"description": "ballot box with check",
"unicodeVersion": "1.1",
- "digest": "c98d6f3588dd87e2f318bbfe6c646399a905450edfd814edae4e5b1bddef2134"
+ "digest": "81e61184a557724ccfe7c2f8e2005f053e134ed19c9c8e4aa5890d9fefc32392"
},
"bamboo": {
"category": "nature",
"moji": "ðŸŽ",
"description": "pine decoration",
"unicodeVersion": "6.0",
- "digest": "e4ee65088df43d7081b1ce6fd996f66f3e0accd88840855c47a98a22997823dd"
+ "digest": "1d26da431d87de2787fc0b8a18559ea14cc2fdbb928d40bcc0de6810a84be2bd"
},
"banana": {
"category": "food",
"moji": "ðŸŒ",
"description": "banana",
"unicodeVersion": "6.0",
- "digest": "f9e8ff910c282c20a8907ff64926b5de4ee250529a1ed718fb33302e6fff8dd9"
+ "digest": "9e11c486281f89713ed8853946434210f068e7cc5e26776f80125d7c1c303a84"
},
"bangbang": {
"category": "symbols",
"moji": "‼",
"description": "double exclamation mark",
"unicodeVersion": "1.1",
- "digest": "76536fee63fe964a3f3839d309b1f45028fb0c43f4d1eeee495f17e1532b4def"
+ "digest": "905c1dc3100192f2052c72531cf796e106815f1ce11ba1993d18c0585ed75e18"
},
"bank": {
"category": "travel",
"moji": "ðŸ¦",
"description": "bank",
"unicodeVersion": "6.0",
- "digest": "f5d2976bf6d521638ccacc74be06bd4abfeab06c5d898a9d245edad45a5b6306"
+ "digest": "ec529c75f3ccf2110adbe912d06269357d84f831ba737eab90aa408d8097bb35"
},
"bar_chart": {
"category": "objects",
"moji": "📊",
"description": "bar chart",
"unicodeVersion": "6.0",
- "digest": "65a328a1b2d7a5332dd4d93f4dbca13d976f0a505b00835c3fc458e394804240"
+ "digest": "ba858a33edbab84f6c0505404a0f10cd89031747ab4e9104524973813d05970a"
},
"barber": {
"category": "objects",
"moji": "💈",
"description": "barber pole",
"unicodeVersion": "6.0",
- "digest": "5e8053d3bb3765a8632fd1cbfe21163f74ed79f6be377eb9603eaaf883d8dc46"
+ "digest": "9ef01a8d9556863264c72b59b404f302f870b676a836ba3beb8892f745b40c80"
},
"baseball": {
"category": "activity",
"moji": "âš¾",
"description": "baseball",
"unicodeVersion": "5.2",
- "digest": "46ac16f8b5455b942f6dbff9483a6fd277721e6719d2731573baabd21c44b34f"
+ "digest": "8c9c750fe39ff65807d9deabccce9dbf96cdff585f320919973576027093c7a6"
},
"basketball": {
"category": "activity",
"moji": "ðŸ€",
"description": "basketball and hoop",
"unicodeVersion": "6.0",
- "digest": "cc83e2aea8fcd2e9a5789e1932ee3766c40843c142fd3565c4e77dafb21ec7d7"
+ "digest": "1c38475863ccaf78b869bdd50d0eb71d189299e189be0ab8b00405096a047628"
},
"basketball_player": {
"category": "activity",
"moji": "⛹",
"description": "person with ball",
"unicodeVersion": "5.2",
- "digest": "793ba53c95e8def769383b612037bc9b9bceecaf1e0430c50a4cc128ad18d9b9"
+ "digest": "518a3f9b20138447812b9ea81f879c035a03694c426f77d8bdc8cef51c04592f"
},
"basketball_player_tone1": {
"category": "activity",
"moji": "⛹ðŸ»",
"description": "person with ball tone 1",
"unicodeVersion": "8.0",
- "digest": "2a06522b971e68ee5b8777a58253009b548f4da2fb723c638acb3d7b04edba8f"
+ "digest": "e34414295433335df2783de205076e9c44cdbd7e07a041d2695a83e4fe4f70ba"
},
"basketball_player_tone2": {
"category": "activity",
"moji": "⛹ðŸ¼",
"description": "person with ball tone 2",
"unicodeVersion": "8.0",
- "digest": "ecc0e44ab9bc478ba45a055fd69a3a38377b917aac5047963fe80ff8ae5fd8e3"
+ "digest": "59308fa1cbe4b778990ced93eb866bbad7f88fda3c1b68837d0da822801f0f20"
},
"basketball_player_tone3": {
"category": "activity",
"moji": "⛹ðŸ½",
"description": "person with ball tone 3",
"unicodeVersion": "8.0",
- "digest": "2d38f1851c685d29532c042461d7b5b996e5f04f0ed54857c66073c62a99ceac"
+ "digest": "e334bddf438b49c145a5c11c010a05964dc50495510017dc37ea8bd6ddc400b3"
},
"basketball_player_tone4": {
"category": "activity",
"moji": "⛹ðŸ¾",
"description": "person with ball tone 4",
"unicodeVersion": "8.0",
- "digest": "09e957c6e9ffc196415f28073aa261feba8efba0bdc694dc08f8f7cd1f88f720"
+ "digest": "24a472bcb4f27a2d8fe2dce4ed6a060391a798721b2146cf6921ff7059bb8446"
},
"basketball_player_tone5": {
"category": "activity",
"moji": "⛹ðŸ¿",
"description": "person with ball tone 5",
"unicodeVersion": "8.0",
- "digest": "c631cefc5d2a0a31bdb9f0a0d97ea68b1c6928e565468998403034644572a0b0"
+ "digest": "8c6a17f2c938aa60aba16634d81dcb069f2c6e7bbf8d79bf36fe888ff83951ae"
},
"bat": {
"category": "nature",
"moji": "🦇",
"description": "bat",
"unicodeVersion": "9.0",
- "digest": "8fc19e0d7d6f80906bdbc06d616a810de66180d96cf28070a53fa61b88904535"
+ "digest": "5f66d15070c283ae9a293719ada7d88d6837f858dda94c61cf56835f734985d8"
},
"bath": {
"category": "activity",
"moji": "🛀",
"description": "bath",
"unicodeVersion": "6.0",
- "digest": "33b371832f90aad50baf5296f3ad4cc081c319b279f989c74409903d8568e917"
+ "digest": "2cac99346c8054b8f883c45194395b35121e7108aaa36ecddccc16d30c32efae"
},
"bath_tone1": {
"category": "activity",
"moji": "🛀ðŸ»",
"description": "bath tone 1",
"unicodeVersion": "8.0",
- "digest": "7ae2989e47788ba71359d52da68feec95aaff68a77d5a6556957df1617af8536"
+ "digest": "17a3cd2bf235984c097eb1ab875b44516e1deba49c9237d0d25585b3df326a57"
},
"bath_tone2": {
"category": "activity",
"moji": "🛀ðŸ¼",
"description": "bath tone 2",
"unicodeVersion": "8.0",
- "digest": "2e86f8edad54d15a7094cd52160cbe51d10aa1750cfb0b3b58e93533f070e327"
+ "digest": "4ca1d1c1a48290c175551fe9ec30d1b82dc7a952530e978d085d72180c1886e0"
},
"bath_tone3": {
"category": "activity",
"moji": "🛀ðŸ½",
"description": "bath tone 3",
"unicodeVersion": "8.0",
- "digest": "654c0cd083a67ff330a38d07352876d265390e5399e5352598d64a6c7e5eeba7"
+ "digest": "084a77c7f583653d8c1d228432144b3210fcd50ed96630591663b3c4dff282fd"
},
"bath_tone4": {
"category": "activity",
"moji": "🛀ðŸ¾",
"description": "bath tone 4",
"unicodeVersion": "8.0",
- "digest": "adad88c6830f31c4b5be194d1987d6aadf4adf45e4cb7f2e4657f0d20c0d663a"
+ "digest": "c605e25a1efd41be4ded235b71924c495b0aa861bdd6f43d9f5137c51de14bb1"
},
"bath_tone5": {
"category": "activity",
"moji": "🛀ðŸ¿",
"description": "bath tone 5",
"unicodeVersion": "8.0",
- "digest": "952c4c9bf24e001e23a33ebf97bd92969cd9143e28ce93f9aafc708a8f966903"
+ "digest": "e15b1bd11177d6a342dfe5eadb52969d60e6b7a1662afe55610aebbcc1a44242"
},
"bathtub": {
"category": "objects",
"moji": "ðŸ›",
"description": "bathtub",
"unicodeVersion": "6.0",
- "digest": "844dffb87ef872594195069b0d0df27c3fe51f3967ccbc8b2df811a086dd483a"
+ "digest": "1caecc05b8ae78774b7620480f4cfbbb549ca2bf6b2fb93badecf440db9ce9c8"
},
"battery": {
"category": "objects",
"moji": "🔋",
"description": "battery",
"unicodeVersion": "6.0",
- "digest": "949ae06648667fb13d9121a6dfdd03bf8692794b28c36e9a8e8ac4515664449a"
+ "digest": "8c50a487dfc349dd3b57ab4000e892efaeec967e5862485b3a023fb63c8c2949"
},
"beach": {
"category": "travel",
"moji": "ðŸ–",
"description": "beach with umbrella",
"unicodeVersion": "7.0",
- "digest": "37fa2158977d470186caaa1aa06669b6dc5026ba49a0c44c5255541f8e974e26"
+ "digest": "98bb54c59c818b30ae9024d85156424a345f2912ca2b37b0ef18f2ef60b96619"
},
"beach_umbrella": {
"category": "objects",
"moji": "â›±",
"description": "umbrella on ground",
"unicodeVersion": "5.2",
- "digest": "d045f1de10038b9fb1eaa2529b2f80b7e3be1cff503efcc2d680663d1fbbc18f"
+ "digest": "8222557bcf3669971279b80855fad3d97cd891e8a446b2e82ca220627a4283d5"
},
"bear": {
"category": "nature",
"moji": "ðŸ»",
"description": "bear face",
"unicodeVersion": "6.0",
- "digest": "a4b9066eaa5681e6af06e596a96a5217037460ffc3b013e8db4d34d762413246"
+ "digest": "6d7ed0e469e7146c5fa5caf7496e516f553eecf2b212ec7835a0636cff147a51"
},
"bed": {
"category": "objects",
"moji": "ðŸ›",
"description": "bed",
"unicodeVersion": "7.0",
- "digest": "08f6e20db51b1fb650b390a0a3074938646772f3fcee8c295d47742e44fe1e30"
+ "digest": "73395ab70c867c776ef56dd14507f7feeaa7871f98e0c0c417df5345e8034976"
},
"bee": {
"category": "nature",
"moji": "ðŸ",
"description": "honeybee",
"unicodeVersion": "6.0",
- "digest": "5beb9a1650681b4adf69999d4808231c38f41a3ec693480b807cda86f964c570"
+ "digest": "57d564f50abfd154473c3ebb16aeac058dc15253fed2b319daf1f2cb063e29af"
},
"beer": {
"category": "food",
"moji": "ðŸº",
"description": "beer mug",
"unicodeVersion": "6.0",
- "digest": "69e227104976548ee0f37375fe1526fd65ef0a328d2d92db2feb1edfd7032bd4"
+ "digest": "c7e45519f39d1cfb1c97d05bca80ee8881dca7aced770d3dac5f282f5bb34773"
},
"beers": {
"category": "food",
"moji": "ðŸ»",
"description": "clinking beer mugs",
"unicodeVersion": "6.0",
- "digest": "db8b32d93bf6d161a3b027e55651d8f51231b13928b3610987ef62bb634d7501"
+ "digest": "8f11a1397605165bfd346619faa5fcddfd1f6b4f9fc2ddc4756cd2518ed92062"
},
"beetle": {
"category": "nature",
"moji": "ðŸž",
"description": "lady beetle",
"unicodeVersion": "6.0",
- "digest": "5aaa428e3f63f7cd1696839ab05be03fa0cd0cbed30a05c36cb270da330c3849"
+ "digest": "c05375aae35bdedd627fa55d63bda6ec9351d9a261a4a60145a8a775d99deaee"
},
"beginner": {
"category": "symbols",
"moji": "🔰",
"description": "japanese symbol for beginner",
"unicodeVersion": "6.0",
- "digest": "2de4fdf92f182c42b12b7527034eaf767d996848b61f31ee69167728411ca0b1"
+ "digest": "330defe4283c7387645422a58f8ccdba013087938a21e726bad64abaafc5d2c3"
},
"bell": {
"category": "symbols",
"moji": "🔔",
"description": "bell",
"unicodeVersion": "6.0",
- "digest": "18d419417746ead408072b78fe2edb6314cdb49492873966fa9f9f06be09899b"
+ "digest": "dae95427928c10693b249c1d324838702dd43295658faa85a9687ae4ea8cc36d"
},
"bellhop": {
"category": "objects",
"moji": "🛎",
"description": "bellhop bell",
"unicodeVersion": "7.0",
- "digest": "b8187bc4059f6a0924a47fe3f6c07f656bed0334bbcbfa1e89f800fe6594ff08"
+ "digest": "9ea748fc595b9bdc1f012b38d2b86d42092baa8d4c58dc38040f624c0a893f2a"
},
"bento": {
"category": "food",
"moji": "ðŸ±",
"description": "bento box",
"unicodeVersion": "6.0",
- "digest": "d46d4f681c5da7f7678b51be3445454a8ed18d917e132ae79077f05310e485f1"
+ "digest": "dee568150c21a99f0b6ce11af58ac7c8a298443fc3971e3efead7728b1bc7459"
},
"bicyclist": {
"category": "activity",
"moji": "🚴",
"description": "bicyclist",
"unicodeVersion": "6.0",
- "digest": "3302147b6b47c16adb97d78b7b761a1ca80e6d0b41d0b60f4da338d2f55f968b"
+ "digest": "3dd17f72beea2fcc4fc9124af3f4997ac00009c699096495b3515cd3ad2453f7"
},
"bicyclist_tone1": {
"category": "activity",
"moji": "🚴ðŸ»",
"description": "bicyclist tone 1",
"unicodeVersion": "8.0",
- "digest": "27eaae0eb61f5e7b3cd9faf02c042d6643a368051a7c9d7da4e0fb9802d39242"
+ "digest": "9bb97a68bdb7d081c1ddfa277be0842fccf3497752fde007e08e46ff831ab4dc"
},
"bicyclist_tone2": {
"category": "activity",
"moji": "🚴ðŸ¼",
"description": "bicyclist tone 2",
"unicodeVersion": "8.0",
- "digest": "39ee9e1071700da7079ad0146bf5711c3a222991eeca8b29b72a65677604444d"
+ "digest": "36329bb0d01bfbd7f99458081ea6ff071317de2525879dc211dafc4e2e7c299b"
},
"bicyclist_tone3": {
"category": "activity",
"moji": "🚴ðŸ½",
"description": "bicyclist tone 3",
"unicodeVersion": "8.0",
- "digest": "03e1d2c4232c896147a9d4bf43becd61edbb5c84fc7193ecea474c0f9fb36817"
+ "digest": "0ef3ff2cbf408d29b7921ffcdcea3ad7d1faa6ec6a1c1b20582a58e4850c6569"
},
"bicyclist_tone4": {
"category": "activity",
"moji": "🚴ðŸ¾",
"description": "bicyclist tone 4",
"unicodeVersion": "8.0",
- "digest": "61393d9c4805be0379d86dd5bec9a1b02314433ab36cfd85bb48dfd073746617"
+ "digest": "9283b7e63bd6a17048e33661e6792568d889ba0f3655a359db159589d6767a47"
},
"bicyclist_tone5": {
"category": "activity",
"moji": "🚴ðŸ¿",
"description": "bicyclist tone 5",
"unicodeVersion": "8.0",
- "digest": "2b46d5f8303e5710dbf5db3a4edc9d88a032fe123fe79158024c9f51df5458c6"
+ "digest": "c2849bb847cc9cbe75ec219ebbd2968891c1ebc2fca62bf86f362eba5e3d78f6"
},
"bike": {
"category": "travel",
"moji": "🚲",
"description": "bicycle",
"unicodeVersion": "6.0",
- "digest": "b41daa7c549d483e2336186a28baaa8ecb11986f490c0c54c793c44900c8f652"
+ "digest": "65d94129ac0445495a0cf55f529f416682fa7a1dc7a16b275e3c267a132777ee"
},
"bikini": {
"category": "people",
"moji": "👙",
"description": "bikini",
"unicodeVersion": "6.0",
- "digest": "07fe156f64673818d69ce3bf03950ca59e3b5d346e45ca541da4078ab791f5ae"
+ "digest": "f7bf17cea90c1d7e18c55af498ea3019e1515efefd4f692b868998861d40000e"
},
"biohazard": {
"category": "symbols",
"moji": "☣",
"description": "biohazard sign",
"unicodeVersion": "1.1",
- "digest": "96163e31f0b8dc5a59772133ede9cc2f40f94330d0b15e3d044b28747e2be788"
+ "digest": "aac5d8bf19b5e33c0a1d600a5e86522023415fb2a98160c58f541c862e439f9a"
},
"bird": {
"category": "nature",
"moji": "ðŸ¦",
"description": "bird",
"unicodeVersion": "6.0",
- "digest": "f916eaf8f271b3767ade9eabb69594c0479f45472d471cabaf59f6e965c161e0"
+ "digest": "b19660ba47b3a0151dc470064a6594cdb9aaaa14a42a0a18d70c253206c954e5"
},
"birthday": {
"category": "food",
"moji": "🎂",
"description": "birthday cake",
"unicodeVersion": "6.0",
- "digest": "89e7c4c598ebee8ec8ab11ebe4ccc6defb7c4d2987ee2379a19b3b59827dd98a"
+ "digest": "f8087a3df94702f990da6a6dd1a0f143f679aa84ea0d178e030dd13e9d414bfa"
},
"black_circle": {
"category": "symbols",
"moji": "âš«",
"description": "medium black circle",
"unicodeVersion": "4.1",
- "digest": "c2ba672994ad0f99d7fdc449f3fee45a2dca68a58f9fe95825b38465a30ef44e"
+ "digest": "dd472d37a09519c4b35d7cce0c1d988cc78abc7eec6ab794f49c75ac1c506450"
},
"black_heart": {
"category": "symbols",
"moji": "🖤",
"description": "black heart",
"unicodeVersion": "9.0",
- "digest": "f334679168d6dd7328c28e9ae3cb2b1fca0e9c2777938d586bfe623db2a688b9"
+ "digest": "d32225e69f8013ed033687a275d2cf0bf19bc7d38f54353ae8441ec50ca25e0b"
},
"black_joker": {
"category": "symbols",
"moji": "ðŸƒ",
"description": "playing card black joker",
"unicodeVersion": "6.0",
- "digest": "d004b25f186494d5b2c65204caa9daecd749c840a0bea5718735e18109e5394d"
+ "digest": "40b7dccd258d4d1323fc744fb545e0e06c1e813bc9030147fb28e0f5b3a76ef3"
},
"black_large_square": {
"category": "symbols",
"moji": "⬛",
"description": "black large square",
"unicodeVersion": "5.1",
- "digest": "cbd90dcbc2f674eafa53820548b5263c18c9845ab39937f085e85aca0aebb479"
+ "digest": "2c606063c452385e38808861d820d799c25450d777c58faa3a58030e32d40d0c"
},
"black_medium_small_square": {
"category": "symbols",
"moji": "â—¾",
"description": "black medium small square",
"unicodeVersion": "3.2",
- "digest": "ab38363c2e862b8f67c719397a09a18e1ef996eec190691fdf769f5cfb209660"
+ "digest": "abd57777f919013b8c0686541263d62492ffd042a1d4b05000856dd1a3ff33ef"
},
"black_medium_square": {
"category": "symbols",
"moji": "â—¼",
"description": "black medium square",
"unicodeVersion": "3.2",
- "digest": "c9ffa87c37e8ee65fadcf755176949901aec7367e02abb85e63cad60cd922116"
+ "digest": "7811b577922f508cf89ac34abdbe5285213b3519de340fe1d57ca6780a500066"
},
"black_nib": {
"category": "objects",
"moji": "✒",
"description": "black nib",
"unicodeVersion": "1.1",
- "digest": "58fb23b1155102970eaa23765e7d529a21e8e545e076ec1158bf11b4de5f51a8"
+ "digest": "196230be1ae39d5841e9ed322f74816c61e47c4235dab7abff0e6d86fba786ed"
},
"black_small_square": {
"category": "symbols",
"moji": "â–ª",
"description": "black small square",
"unicodeVersion": "1.1",
- "digest": "f69be6de578fffce5a3e60eda690104b2ef6a855c630040104fb760a02ff1aef"
+ "digest": "958483632202cf3181ef96532b0371cad1ea9b693100def41df69388b1ee468a"
},
"black_square_button": {
"category": "symbols",
"moji": "🔲",
"description": "black square button",
"unicodeVersion": "6.0",
- "digest": "9d818fcd08ed38cd0bbbcfd83e665aa29b3761c0d8b9806d8954d36785e267a8"
+ "digest": "2211e8f2193751c4d1716a4d13145e945293f0158d413333829e7a20a265e55b"
},
"blossom": {
"category": "nature",
"moji": "🌼",
"description": "blossom",
"unicodeVersion": "6.0",
- "digest": "e8cf369d4e4cdb4eccc2ebcbb35439b0344221115701daae642e58dff8544922"
+ "digest": "4b330c92cc58a402534cb0bbbde2d18d680a88da5e1321d460e2d5ce2644d774"
},
"blowfish": {
"category": "nature",
"moji": "ðŸ¡",
"description": "blowfish",
"unicodeVersion": "6.0",
- "digest": "e706849ed00f08a82312381c76f6f9ba6cc261fbf87a839c85e7dd54138f9dc3"
+ "digest": "084c33958f40081d19012e35fcf72f085cf1f749964ba7256d8721e8a2d929e0"
},
"blue_book": {
"category": "objects",
"moji": "📘",
"description": "blue book",
"unicodeVersion": "6.0",
- "digest": "4c845748fe890516b32981b0b62bf3e8e9d906840c2060179f4f844100780615"
+ "digest": "bc47b3b8f1bfa21c2a4bf185cc247e0c9fc7f4f221292c3b0286e13b32f7a6da"
},
"blue_car": {
"category": "travel",
"moji": "🚙",
"description": "recreational vehicle",
"unicodeVersion": "6.0",
- "digest": "eca91934eb5481726cfd897b1ed5eac306e14d02499fbe49316aaec6c72b6707"
+ "digest": "c0faa7f7d4344391478aba15cb4cbfbbe1eb5fd5cdcdb9afdb7d49984abb8108"
},
"blue_heart": {
"category": "symbols",
"moji": "💙",
"description": "blue heart",
"unicodeVersion": "6.0",
- "digest": "2caa0c8d18538cc871c6fe328a52f71e1df8aabf4d1cc2f5324b261d1b8cb99a"
+ "digest": "dde3ac8cbd84903c39310d0a9a0121f47e1701bf3298d0cecaba552076b462c1"
},
"blush": {
"category": "people",
"moji": "😊",
"description": "smiling face with smiling eyes",
"unicodeVersion": "6.0",
- "digest": "3bfe8d603cfa39999c164779f666d39bbc507f124ba80233ee72da7b3b0c0457"
+ "digest": "3d7d115f7da861e3565a446d9aea177c7bc27592bac17d0d96d815d853b68467"
},
"boar": {
"category": "nature",
"moji": "ðŸ—",
"description": "boar",
"unicodeVersion": "6.0",
- "digest": "c9d67479cace427ac3c30460fcffa1bf9a8e5262c0390962405dbbe6bf830fa6"
+ "digest": "0e6774094f935bf5eaccc85077e357d2f002276a76aa7a3ba8457e11c7458314"
},
"bomb": {
"category": "objects",
"moji": "💣",
"description": "bomb",
"unicodeVersion": "6.0",
- "digest": "0155559abc4084f80e9b0b2a2091b8710ddd6369993b7fdd0685f4f8c2fd7e6c"
+ "digest": "c06294f2bc2ca60c09544598a699662609f41bd06efa01d92d8ab7b48356b830"
},
"book": {
"category": "objects",
"moji": "📖",
"description": "open book",
"unicodeVersion": "6.0",
- "digest": "9d912a9d1bb10dc7f2645b345ed09e90461e83df0de275acb806f1f75cef1fcf"
+ "digest": "07f1af90a8f2bdddaa585b4da1da9ac7c52dbb7365d409d264e2b66f43b165d7"
},
"bookmark": {
"category": "objects",
"moji": "🔖",
"description": "bookmark",
"unicodeVersion": "6.0",
- "digest": "5705e3108259d6900649157843c50e22d0086c3630b291d3f942da1a736e3e3d"
+ "digest": "cafb404fab72e67a7c0254ebe91f9631be9a6f7da763bbd948358e8544e2fd53"
},
"bookmark_tabs": {
"category": "objects",
"moji": "📑",
"description": "bookmark tabs",
"unicodeVersion": "6.0",
- "digest": "c8fc7c9f3f82e1ccc97fc591345fdd88b09eec0fca428d8d4632a121cf1bc39a"
+ "digest": "78450d6c894fee9badbed92a07144718908a305be825304dc47839e259884e9c"
},
"books": {
"category": "objects",
"moji": "📚",
"description": "books",
"unicodeVersion": "6.0",
- "digest": "cbcf55d39dd05d26ef7350bc51e0e2f064f78bb8f59d407b516d63f68558f8e4"
+ "digest": "566cb93cf32782ae39aec670e22b711fa33afd52bc75c9e7069174cd252125d1"
},
"boom": {
"category": "nature",
"moji": "💥",
"description": "collision symbol",
"unicodeVersion": "6.0",
- "digest": "f5400e9583f7f997cd2385f21379f6229424a9b221445bc8f36c0bb64bdb3168"
+ "digest": "eb699268e39f7fa16a39fc731a7ebed9f7dcdbde083e222cffbac860c1bc643b"
},
"boot": {
"category": "people",
"moji": "👢",
"description": "womans boots",
"unicodeVersion": "6.0",
- "digest": "b4706ff35909a6fb759a3b8a797e90cb67ffc60e4853386a7d89ace9693a9364"
+ "digest": "3ac88fcfbe55d073949e89aeeadf168c04633c9af4ce6673c897358e595511c2"
},
"bouquet": {
"category": "nature",
"moji": "ðŸ’",
"description": "bouquet",
"unicodeVersion": "6.0",
- "digest": "b93751a27b40f6185a22b3e8b413f0fe09b6010d1057c672e1a23088e0b8286f"
+ "digest": "0d737305d51cced40a4de5da6dacb5dfb049c7d8ad4136c312193049a9915a3b"
},
"bow": {
"category": "people",
"moji": "🙇",
"description": "person bowing deeply",
"unicodeVersion": "6.0",
- "digest": "33cd6da4d408f18d98bebc6a277dea8b914150e32ee472586ce3f1eb814462bd"
+ "digest": "7f87a4acccfe257981459813185e6379477e5a892241c30e035db16d661119fe"
},
"bow_and_arrow": {
"category": "activity",
"moji": "ðŸ¹",
"description": "bow and arrow",
"unicodeVersion": "8.0",
- "digest": "051b4d50ab21a68b8583a6313ec183e3e1e96f493b0f4541fbb888f0b95fdd4d"
+ "digest": "c98949db3391c74e299232ea99a28e035cc1cd747e281e52ccb9afd6a6ac40c3"
},
"bow_tone1": {
"category": "people",
"moji": "🙇ðŸ»",
"description": "person bowing deeply tone 1",
"unicodeVersion": "8.0",
- "digest": "995c8400ad60d5adc66c9ae5e3c0ecf56c48b478ad79418d45b6289933d25bdd"
+ "digest": "d2d51f5c1188f78787c6d04dc684718039a3acde2ed0b78f016d93ae1e7b0077"
},
"bow_tone2": {
"category": "people",
"moji": "🙇ðŸ¼",
"description": "person bowing deeply tone 2",
"unicodeVersion": "8.0",
- "digest": "af89eec2fccda99d9bdd373b2345595882fee1c0a15d29af9028089e20255325"
+ "digest": "b98552745d6332558f0bcca21744b4efa3f0da508f21a3cf6e30f4f272ae855e"
},
"bow_tone3": {
"category": "people",
"moji": "🙇ðŸ½",
"description": "person bowing deeply tone 3",
"unicodeVersion": "8.0",
- "digest": "015d8122abdf2d0caa03815545f50fb7a71e05dacd46aaa133cc9ace5192f266"
+ "digest": "4640674043701bc1e0a71c3101543582fcb2224f21253436aeb798cc7213738e"
},
"bow_tone4": {
"category": "people",
"moji": "🙇ðŸ¾",
"description": "person bowing deeply tone 4",
"unicodeVersion": "8.0",
- "digest": "e8409096a795b775def654d36aeccb8eb91e83d7d1b32145cd73fd0b7b9e885c"
+ "digest": "213b699929dd9cf438d0ffb531c740cadec4e8ed71e583b2c5a932fada2c0984"
},
"bow_tone5": {
"category": "people",
"moji": "🙇ðŸ¿",
"description": "person bowing deeply tone 5",
"unicodeVersion": "8.0",
- "digest": "d87042cde8dbad9fb1a91a2ec60116e27b4a76388b5779d771a0bbae12a2814d"
+ "digest": "123679fd642e0b47297e69becaa3d490e52c6b45a3ec810f50fe4e75744bf990"
},
"bowling": {
"category": "activity",
"moji": "🎳",
"description": "bowling",
"unicodeVersion": "6.0",
- "digest": "737f2cdfa4ac964baade585a39771b18080bd5e9b55c8661d3518f468f344662"
+ "digest": "2bc7f10afb9d6c61e015e4b6ca8c65c038a6a802840e1879142ee9bb86369b38"
},
"boxing_glove": {
"category": "activity",
"moji": "🥊",
"description": "boxing glove",
"unicodeVersion": "9.0",
- "digest": "c914b2ce45f20afad66ad6f0d1b0750c4469e4f48b686dfc4aad1ec8d289c563"
+ "digest": "4acdaf7627f8a70148dadec0012474c3eb5042d2a165522c9a221cb6c63376c3"
},
"boy": {
"category": "people",
"moji": "👦",
"description": "boy",
"unicodeVersion": "6.0",
- "digest": "7bc0173d8c88f3f12d41f213f7a3a9f5ebf65efad610fd5a2a31935128a6a6c1"
+ "digest": "7a5a1eb2e38f835e8fe6506a78f0f05dd4e831bdd8ea30f3f5f473bc1d28baa2"
},
"boy_tone1": {
"category": "people",
"moji": "👦ðŸ»",
"description": "boy tone 1",
"unicodeVersion": "8.0",
- "digest": "c0e2f0483715b239fe145b0056566f7a3a722319d9a87c1e66733dff1916a19f"
+ "digest": "b0edd5f1171b2969e5273cb0be90d57f2d7c605ff413478eabecb9501bcfe811"
},
"boy_tone2": {
"category": "people",
"moji": "👦ðŸ¼",
"description": "boy tone 2",
"unicodeVersion": "8.0",
- "digest": "0001d0bd1ff4dbd898604ba965b4039d09667d955bc0349301b992f9ab6dd7fd"
+ "digest": "52f5dba881f3fb1867619dfc35d503022e6455a475137d2d5366830fe6966e09"
},
"boy_tone3": {
"category": "people",
"moji": "👦ðŸ½",
"description": "boy tone 3",
"unicodeVersion": "8.0",
- "digest": "e0f08755955fd2e0bd1c5d5e84429b2a234b24a744bb50bb9f1148495b2b29f9"
+ "digest": "57d11252ed3e92e5093ee70a11549f98f70f623a18b75dd8736dc5908f361c8c"
},
"boy_tone4": {
"category": "people",
"moji": "👦ðŸ¾",
"description": "boy tone 4",
"unicodeVersion": "8.0",
- "digest": "04b6bfee58a26b1ce2e5b403504a7033aaf395f03f5cd23e824f32c90c395fe6"
+ "digest": "b18387f39f18a50afc737c13d5387a904d27210e5e147e0ad4f0966f9091156b"
},
"boy_tone5": {
"category": "people",
"moji": "👦ðŸ¿",
"description": "boy tone 5",
"unicodeVersion": "8.0",
- "digest": "0f76e97237203950da36c737dcc6f56dcd6c123401a8c817a0636376c7f38ef5"
+ "digest": "37527ef42b6e163d273b95178e0c385c46172e45bac09070e421fa8230d5b04c"
},
"bread": {
"category": "food",
"moji": "ðŸž",
"description": "bread",
"unicodeVersion": "6.0",
- "digest": "81739830f16f33e6a1dd7cc17c25df207846062bb5167bb8abed7fdd49268b86"
+ "digest": "6108ad957056be1eeeb3c28e5fbd1b215becb07ad8669513466a26dfd481fe74"
},
"bride_with_veil": {
"category": "people",
"moji": "👰",
"description": "bride with veil",
"unicodeVersion": "6.0",
- "digest": "8e24bd91c3f564cf6148f2b3b4a7d692c11dd059e76a13331fdfb04ae060ea70"
+ "digest": "165cb38a4e761a00fd685e5ba946f03274a78738317d799177dfe399b1284f82"
},
"bride_with_veil_tone1": {
"category": "people",
"moji": "👰ðŸ»",
"description": "bride with veil tone 1",
"unicodeVersion": "8.0",
- "digest": "0bd2f16f72586f50e768b14b9b353f2e98ccbb2581a568c33b06be56e70ca063"
+ "digest": "226116d9783ac937da561f4396e1d71001c54eccd8dfdbd2716dc2d6168fb5b1"
},
"bride_with_veil_tone2": {
"category": "people",
"moji": "👰ðŸ¼",
"description": "bride with veil tone 2",
"unicodeVersion": "8.0",
- "digest": "e5463f811b2075754f0718b891757cd2e81071edf7af2215581227e1aad1d068"
+ "digest": "c9bbfd4b769ca43b17a76e73ed9add549a6ec9a4ea07929d065ba39f1903261f"
},
"bride_with_veil_tone3": {
"category": "people",
"moji": "👰ðŸ½",
"description": "bride with veil tone 3",
"unicodeVersion": "8.0",
- "digest": "e5a053a26f7ccebae7eb12f638be5ed80f77b744708d783eab2eb8aa091cf516"
+ "digest": "3a9022ee11dcdfbb70d5c21f329c14c4ff1893c5d1796d1b2a1cc497ac847258"
},
"bride_with_veil_tone4": {
"category": "people",
"moji": "👰ðŸ¾",
"description": "bride with veil tone 4",
"unicodeVersion": "8.0",
- "digest": "410e23825e4401460946dc67a618bd3ace6e1a7c07dd88580a2349423685261f"
+ "digest": "6fb039930bed25f6e7c568668eaa215779f15e20c8116923e8039c98a8e17d10"
},
"bride_with_veil_tone5": {
"category": "people",
"moji": "👰ðŸ¿",
"description": "bride with veil tone 5",
"unicodeVersion": "8.0",
- "digest": "454e87e5a74e13e5b4993541231516fbbe6dbe9f990e1a6f3f4a744d7d4c1615"
+ "digest": "e542a466332ea26f2b94a6504912659d4ed72e6fcf399830828a478124e2d79c"
},
"bridge_at_night": {
"category": "travel",
"moji": "🌉",
"description": "bridge at night",
"unicodeVersion": "6.0",
- "digest": "9d3cda5a59e27e3c90939f1ddbe7e998b3ea4fcacfa1467dea0edf39613c2d7f"
+ "digest": "212feaa05b96bff46d9699d3e9f1d61f6fc0e228414534b1bf8f1383c591784c"
},
"briefcase": {
"category": "people",
"moji": "💼",
"description": "briefcase",
"unicodeVersion": "6.0",
- "digest": "9d00d6a92632aaadc71b017f448c883b27eb31a7554ebb51f7e3a9841f0f7f2b"
+ "digest": "f72220b3fa933c6b503c041643543369177efc2bee094d392cbf8ee9d5cf11a0"
},
"broken_heart": {
"category": "symbols",
"moji": "💔",
"description": "broken heart",
"unicodeVersion": "6.0",
- "digest": "c7ca53f444d72e596af46b61ffbc9e7c18a645020c22691e44f967db98dbf853"
+ "digest": "6b60f5c0d0a7702308a85e0d8eca3ca54ac348a9f66bb56f89f9f3aae9303ca4"
},
"bug": {
"category": "nature",
"moji": "ðŸ›",
"description": "bug",
"unicodeVersion": "6.0",
- "digest": "0dccb1d5eb91769377b4c5b310f007b60f54a5c48ba9e467b3a06898a4831b90"
+ "digest": "8c3a35433d6c2d63c57d2fdfa8be50bd35c334dfe0ba1b1554555e872091b857"
},
"bulb": {
"category": "objects",
"moji": "💡",
"description": "electric light bulb",
"unicodeVersion": "6.0",
- "digest": "ccdaa2dfde5a88a347035a94b9d4d86cfc335ce0a73292423f5788a4bd21a5a8"
+ "digest": "2cdc43e4bb17fc00c903a911e065fe1bb96f4f57103a3836cfa908c4618e6d45"
},
"bullettrain_front": {
"category": "travel",
"moji": "🚅",
"description": "high-speed train with bullet nose",
"unicodeVersion": "6.0",
- "digest": "5195a6a6d23f28e1aa5ebac6ede0f6c6a8b7ff33a9edf034814f227fe976177a"
+ "digest": "b8cd48a543a5ed0cf750cfa8bcfa536e26b72a77e4b7f506041b623e9081fb69"
},
"bullettrain_side": {
"category": "travel",
"moji": "🚄",
"description": "high-speed train",
"unicodeVersion": "6.0",
- "digest": "96e74842e919716b7bbbab57339bfd70f099a9bcb4710dffd7c80cf38a7bbff7"
+ "digest": "401e85f01801e39f8325a96bdee7e27626fc4124d92eeb3e39227d78ef7d26c0"
},
"burrito": {
"category": "food",
"moji": "🌯",
"description": "burrito",
"unicodeVersion": "8.0",
- "digest": "b2cf81f1efdf87e674461f73f67cd4b58a5f695e65598d0dd3899f2597da43cf"
+ "digest": "99ad1315f80dd9c1a9dab3a88e4c272d813b072a10f085c44ec4d261f7cb1d83"
},
"bus": {
"category": "travel",
"moji": "🚌",
"description": "bus",
"unicodeVersion": "6.0",
- "digest": "192850b762edad21ac8770df38b9cae6d2bc1697a838462f3e36066bfb4eee50"
+ "digest": "70534ef30162b8af4b548c3fc0f4d7964e01c8bcb2b52c3b2dc2df4854aa308c"
},
"busstop": {
"category": "travel",
"moji": "ðŸš",
"description": "bus stop",
"unicodeVersion": "6.0",
- "digest": "adabb1ec36402b33feb636eae3656e5a8b51ff1071bcb14125d8ab80d6d12d2a"
+ "digest": "ccb2c93fe9f2a03c0674d921bb3a6a6c80e2eef64a274bd31b1efb3147785e6f"
},
"bust_in_silhouette": {
"category": "people",
"moji": "👤",
"description": "bust in silhouette",
"unicodeVersion": "6.0",
- "digest": "277ae43301f1e49e0be03c8e52f0dc7b70c67f9d146bca0a14172e0098f115e6"
+ "digest": "17f35781aa264a26812ca9a13a32e7ab73a7eb95af1bc0b812a35d6fc9ac521f"
},
"busts_in_silhouette": {
"category": "people",
"moji": "👥",
"description": "busts in silhouette",
"unicodeVersion": "6.0",
- "digest": "7fee96f1b68bb2c6002e47f2ed13c06baa6a3168441b9aca572db7ec45612f7b"
+ "digest": "f9aa0c03d90e5d0f57f8114b998019452c5756a8dcbf1750b07f9aeae2f4ab08"
},
"butterfly": {
"category": "nature",
"moji": "🦋",
"description": "butterfly",
"unicodeVersion": "9.0",
- "digest": "a91b6598c17b44a8dc8935a1d99e25f4483ea41470cdd2da343039a9eec29ef1"
+ "digest": "a7c33f816a9705a83a0debf8cbeb1ff9dc430200f52e8d0f5682fe11c39b4473"
},
"cactus": {
"category": "nature",
"moji": "🌵",
"description": "cactus",
"unicodeVersion": "6.0",
- "digest": "2c5c4c35f26c7046fdc002b337e0d939729b33a26980e675950f9934c91e40fd"
+ "digest": "1690158bb63afbe907bbc343627b9c353198ad611b9bb195f5eda5c3545aa2e9"
},
"cake": {
"category": "food",
"moji": "ðŸ°",
"description": "shortcake",
"unicodeVersion": "6.0",
- "digest": "b928902df8084210d51c1da36f9119164a325393c391b28cd8ea914e0b95c17b"
+ "digest": "807cc6dd0621c1c4dbd5380191d056ce44ccd2b92dda0cad6ca1c57e19e9f785"
},
"calendar": {
"category": "objects",
"moji": "📆",
"description": "tear-off calendar",
"unicodeVersion": "6.0",
- "digest": "9d990be27778daab041a3583edbd8f83fc8957e42a3aec729c0e2e224a8d05e3"
+ "digest": "275fa5b2c113c3d117b1c8970f01dd897b90405db7a55ff6a3dda767817ed4f5"
},
"calendar_spiral": {
"category": "objects",
"moji": "🗓",
"description": "spiral calendar pad",
"unicodeVersion": "7.0",
- "digest": "441a0750eade7ce33e28e58bec76958990c412b68409fcdde59ebad1f25361bb"
+ "digest": "01aefae6a6d0d517be52e7918d6893d55a9fa5b7480d60cb8b8b5a743573ea0b"
},
"call_me": {
"category": "people",
"moji": "🤙",
"description": "call me hand",
"unicodeVersion": "9.0",
- "digest": "83d2ed96dcb8b4adf4f4d030ffd07e25ca16351e1a4fbefdf9f46f5ca496a55f"
+ "digest": "3701197e18ffedc242a6b20ab74e7a339c7f77df27c5f92d5124a42e39a9502a"
},
"call_me_tone1": {
"category": "people",
"moji": "🤙ðŸ»",
"description": "call me hand tone 1",
"unicodeVersion": "9.0",
- "digest": "4a5748efa83e7294e8338b8795d4d315ff1cd31ead6759004d0eb330e50de8cd"
+ "digest": "1c5c681c9b588a2b07a57d27d3aaf209e7d23c4cba938ffce07bfa4a53d720e9"
},
"call_me_tone2": {
"category": "people",
"moji": "🤙ðŸ¼",
"description": "call me hand tone 2",
"unicodeVersion": "9.0",
- "digest": "54feaa6e3c5789ae6e15622127f0e0213234b4b886e1588ce95814348b1f1519"
+ "digest": "4c848da3d8849de81922aa2eb6611489ad72649cf189849176217e946cf9aad8"
},
"call_me_tone3": {
"category": "people",
"moji": "🤙ðŸ½",
"description": "call me hand tone 3",
"unicodeVersion": "9.0",
- "digest": "57e949b951e14843b712dab5a828f915ee255f5bb973db33946aab4057427419"
+ "digest": "b697c1a4aa15f7793002b79aee8e5240f48b832b33f8ad39b8d46b90624c6c0a"
},
"call_me_tone4": {
"category": "people",
"moji": "🤙ðŸ¾",
"description": "call me hand tone 4",
"unicodeVersion": "9.0",
- "digest": "f7787e933978a09c7b8ab8d3b1e1ab395aaae998c455e93bb3db24a4c8a60fe0"
+ "digest": "f1b07c2a8071f5f704b5354277777aa651202f56ef7d334ce66e0475fdba086a"
},
"call_me_tone5": {
"category": "people",
"moji": "🤙ðŸ¿",
"description": "call me hand tone 5",
"unicodeVersion": "9.0",
- "digest": "1fdb7d833d000b117d20d48142d3026a61cc9c8b712ebb498fa66bf75c74d7a5"
+ "digest": "d7d8d96a3980e3c558d3e3ef62aa49dc237c075f0c3dfb0b06ae33fc98f565c5"
},
"calling": {
"category": "objects",
"moji": "📲",
"description": "mobile phone with rightwards arrow at left",
"unicodeVersion": "6.0",
- "digest": "acf668c75c11c36686005788266524a972fa1c5bcf666ff3403d909edc5cee91"
+ "digest": "3fc285fd0fc7a6beb6c64091671d0f789458e32aaba9d9fd74dfac16b9549826"
},
"camel": {
"category": "nature",
"moji": "ðŸ«",
"description": "bactrian camel",
"unicodeVersion": "6.0",
- "digest": "5f927927a7ab1277d0dc8b8211436957968b1e11365a8bf535e9bb94f92c5631"
+ "digest": "666d8efce2033fd7a69fa8537a0d724b3e1e0d9d5093b8d7666a45a4f7d1831f"
},
"camera": {
"category": "objects",
"moji": "📷",
"description": "camera",
"unicodeVersion": "6.0",
- "digest": "fde03e396822a36cd6ae756ede885b945a074395264162731ca5db47a3b39d80"
+ "digest": "5d86baa4baede9c6d02fbe02fd2d4ad07a47a77e09c1d2d045ea20b36bd2938c"
},
"camera_with_flash": {
"category": "objects",
"moji": "📸",
"description": "camera with flash",
"unicodeVersion": "7.0",
- "digest": "9afd380208187780f00244c45d4db6c5ea1ea088d4a1bd8fc92a8f3877149750"
+ "digest": "9b701460de9ba318811d771bb451fb109850bc08ad6592f9365bc350de571f9f"
},
"camping": {
"category": "travel",
"moji": "ðŸ•",
"description": "camping",
"unicodeVersion": "7.0",
- "digest": "a42a4ff9521affa72db7b0f01da169b4cb6afb9db1c5dfad47dd4c507bfc30d9"
+ "digest": "70c596c5d9ab030e26b46c95e011a28050aa6082f4ba2b8b197f24915ce03c86"
},
"cancer": {
"category": "symbols",
"moji": "♋",
"description": "cancer",
"unicodeVersion": "1.1",
- "digest": "528c6f21df99a756b553d93a7f395b0f662b30a323affd05f0cedee8ff7b41d6"
+ "digest": "f707db14878e03608dee3eca4eacf0a0be4a709c6d33b2d5b7ab0e8f05473b2b"
},
"candle": {
"category": "objects",
"moji": "🕯",
"description": "candle",
"unicodeVersion": "7.0",
- "digest": "211c04dc3a91b071c284d4180ed09f9d3320e3fd6ba8a9fddd0677bc97fd12cb"
+ "digest": "67400dd5e800a6e496a661da639d4964bf6646525bcf6d6c4773529ae5f7f075"
},
"candy": {
"category": "food",
"moji": "ðŸ¬",
"description": "candy",
"unicodeVersion": "6.0",
- "digest": "9cff4538918f60f770fceb96e964f5dc3ce31fd08ddd2ab3bfdf2981bfa74100"
+ "digest": "7064f2eb0dc768e3deb1e6ebe449950eb5a72ea882fb13bb06e23e7e2012c740"
},
"canoe": {
"category": "travel",
"moji": "🛶",
"description": "canoe",
"unicodeVersion": "9.0",
- "digest": "56ca308cc2ad4827468cf58c4ccf6ef6b3382835a91e935540a2b973e01d2572"
+ "digest": "20d70c92c33a8bc6629e6d0b87bfca0dbbc9c32458d253ee62eb0845398fe095"
},
"capital_abcd": {
"category": "symbols",
"moji": "🔠",
"description": "input symbol for latin capital letters",
"unicodeVersion": "6.0",
- "digest": "a416d0b3f564037b680f801fb773b6eaf67225e2cbbfd2cb8a5db0de044321fa"
+ "digest": "6cd31a4765c108d5e85f0ad9e25dee8e8f8af1fc40de161c0407f4041db9e288"
},
"capricorn": {
"category": "symbols",
"moji": "♑",
"description": "capricorn",
"unicodeVersion": "1.1",
- "digest": "f11abad102603737b55486fe2ea4d01f28b203394bcd84f19a7948156e6c4b96"
+ "digest": "d769793914f9c1ea4237aea85d288344c7422ccb286f8c1d3b18fa99ee8fa7ce"
},
"card_box": {
"category": "objects",
"moji": "🗃",
"description": "card file box",
"unicodeVersion": "7.0",
- "digest": "7a6199d562f30e02ed31094de6aebeb99eae8ac156f6910463dfed73256f4c9a"
+ "digest": "25acb25ee37044c67b69ce3a7cb412f7ec2fad76009b9e022cf45b58e0d1d898"
},
"card_index": {
"category": "objects",
"moji": "📇",
"description": "card index",
"unicodeVersion": "6.0",
- "digest": "86e187e0a72ca5d00207d6ef34d66ce15046848a831c2b5184fb840c5332a2a8"
+ "digest": "262bfa04568a192dd8696ec43c6f916a45e16a7c19d77f830e366de0d930bb7a"
},
"carousel_horse": {
"category": "travel",
"moji": "🎠",
"description": "carousel horse",
"unicodeVersion": "6.0",
- "digest": "c0e7059efc39a64233f774c02ddb1ab51888fff180f906ce13a6e4f9509672fe"
+ "digest": "d8a609d98fab29e04443f12457a8c8c7fe321b3b940289f1c9fe55f711583b20"
},
"carrot": {
"category": "food",
"moji": "🥕",
"description": "carrot",
"unicodeVersion": "9.0",
- "digest": "3a6fd98b63ee73d982a9cdacb08cf7b4014368cde8ffce6056b7df25a5a472b1"
+ "digest": "8d8a49f70f7f339347d4a59afcb9a58d9113ebb4d7488d681e409cefd5cb9e47"
},
"cartwheel": {
"category": "activity",
"moji": "🤸",
"description": "person doing cartwheel",
"unicodeVersion": "9.0",
- "digest": "d78de3435e0b04a9b1a1048ae12e63e3248f9ace3a0db4d3bda584f22af18863"
+ "digest": "2601e720cad24b46e10f7063c369d14f0da4436a82a7e19b8ea77acbfbef34d1"
},
"cartwheel_tone1": {
"category": "activity",
"moji": "🤸ðŸ»",
"description": "person doing cartwheel tone 1",
"unicodeVersion": "9.0",
- "digest": "39a49781a269bb40d8efc8fd73c973b00fb2e192850ea6073062b5dea0cd5b74"
+ "digest": "2346e968d9f62b44cfed94354fcfc171a6588a8d4b2f9b49b667aa8987ced6b1"
},
"cartwheel_tone2": {
"category": "activity",
"moji": "🤸ðŸ¼",
"description": "person doing cartwheel tone 2",
"unicodeVersion": "9.0",
- "digest": "6231eb35be45457fd648f8f4b79983f03705c9d983a18067f7e6d9ae47bc1958"
+ "digest": "1038eedf481d46a42a42b9c7ff281b5a8c99793549a5c12984cf70641d411b70"
},
"cartwheel_tone3": {
"category": "activity",
"moji": "🤸ðŸ½",
"description": "person doing cartwheel tone 3",
"unicodeVersion": "9.0",
- "digest": "ca483c78cc823811a8c279c501d9b283e4c990dafc5995ad40e68ecb0af554df"
+ "digest": "662221a5603894c966b72217f4db74fdf02da22b9716f106b456e56277c361f6"
},
"cartwheel_tone4": {
"category": "activity",
"moji": "🤸ðŸ¾",
"description": "person doing cartwheel tone 4",
"unicodeVersion": "9.0",
- "digest": "8253afb672431c84e498014c30babb00b9284bec773009e79f7f06aa7108643e"
+ "digest": "14ad120f2f0778ee4ede3578e61707dc92a3d4658553a0c2cb0087f9e3c965cf"
},
"cartwheel_tone5": {
"category": "activity",
"moji": "🤸ðŸ¿",
"description": "person doing cartwheel tone 5",
"unicodeVersion": "9.0",
- "digest": "6fd92baff57c38b3adb6753d9e7e547e762971a8872fd3f1e71c6aaf0b1d3ab9"
+ "digest": "b9a51589e53cb61afe0b470de87deb135b8396d8300848bf7a240190787b5863"
},
"cat": {
"category": "nature",
"moji": "ðŸ±",
"description": "cat face",
"unicodeVersion": "6.0",
- "digest": "e52d0d3a205a0ba99094717e171a7f572b713a0e21b276ffa4a826596fe5cafc"
+ "digest": "c843d3b4d50b6928c55c3b8c408e54510be69961e098a631e9e1d18c2932f4e0"
},
"cat2": {
"category": "nature",
"moji": "ðŸˆ",
"description": "cat",
"unicodeVersion": "6.0",
- "digest": "46aa67a99f782935932c77b8de93287142297abe52928c173191cf55bb8f4339"
+ "digest": "a12d0ab04554c3a7c2b45e6501da312773777587bef28ba233202f3812901af4"
},
"cd": {
"category": "objects",
"moji": "💿",
"description": "optical disc",
"unicodeVersion": "6.0",
- "digest": "16363d8a34b873c12df6354b99f575cae3d80e0d27100ed7eea70f0310953c7b"
+ "digest": "d7242edbba09de17d223d7e3178a241b1aafe05d14a19000428522dc9b2891f4"
},
"chains": {
"category": "objects",
"moji": "⛓",
"description": "chains",
"unicodeVersion": "5.2",
- "digest": "3884cdbc6f2b433062af06f942552e563231c24727a2f10fa280b3bb7aa614e2"
+ "digest": "245a60d0dcdf759898d5f6093d3b67e7e3234a5799de52af87166886bb8e67ff"
},
"champagne": {
"category": "food",
"moji": "ðŸ¾",
"description": "bottle with popping cork",
"unicodeVersion": "8.0",
- "digest": "9e6e8987f30a37ae0f3d7dab2f5eeb50aa32b4f31402b29315eb2994afc72457"
+ "digest": "6e686856c9e39b9947ef669394e6621fffd2a91ebe8f21c2cdc06b06669d1160"
},
"champagne_glass": {
"category": "food",
"moji": "🥂",
"description": "clinking glasses",
"unicodeVersion": "9.0",
- "digest": "5a2e4773f7eb126a00122cbfa4dc535da51ce00e0bf0d8d6ff8bab8b3365f8d2"
+ "digest": "8e59ae799d7c7844dc19f5fd4fbefebc34f597059373c94e8639a7ce73d13519"
},
"chart": {
"category": "symbols",
"moji": "💹",
"description": "chart with upwards trend and yen sign",
"unicodeVersion": "6.0",
- "digest": "a092dbc08f925b028286b2b495a5f59033b8537a586a694f46f4c1e7c3a1e27f"
+ "digest": "b513f5b5ff0e9a8139aaa378982e1937b09da1827adef70158d07d8c4a288139"
},
"chart_with_downwards_trend": {
"category": "objects",
"moji": "📉",
"description": "chart with downwards trend",
"unicodeVersion": "6.0",
- "digest": "5db7ccbc37665736a9c0b2f50247dcc09e404ec37f39db45b7b8b9464172a18c"
+ "digest": "0c12dfccd80564f29dc56d3e994e55793ec02d1bd4e3109c7e1b003163579ecc"
},
"chart_with_upwards_trend": {
"category": "objects",
"moji": "📈",
"description": "chart with upwards trend",
"unicodeVersion": "6.0",
- "digest": "bc4ea250b102fe5c09847e471478aff065ad3df755d9717896d38d887d9c6733"
+ "digest": "c09ad5dd7817106a1df65a1f8da086006de804d2de22107423a5805da5ee3f9f"
},
"checkered_flag": {
"category": "travel",
"moji": "ðŸ",
"description": "chequered flag",
"unicodeVersion": "6.0",
- "digest": "0e77180e0cf9fc87e755a5a42cf23aec6bf30931db41331311e97ba0be178b78"
+ "digest": "b2527f2ce6797b261083947b9e9dd588382da6e7e46f81a1919d0f039635f21b"
},
"cheese": {
"category": "food",
"moji": "🧀",
"description": "cheese wedge",
"unicodeVersion": "8.0",
- "digest": "50a6cb906c2120e2bbc0e22105924262007cfe1554d7b02b8cc84b6adedc6a0b"
+ "digest": "5d0152d394bb97558cdd52eb5c9c6f9924e04071e7aa76fa1abde43ae727ca78"
},
"cherries": {
"category": "food",
"moji": "ðŸ’",
"description": "cherries",
"unicodeVersion": "6.0",
- "digest": "13b8db9e7e6eec8509aa80c762966e1bf3538fcb1ac3d6eab18ee4da1528cf84"
+ "digest": "49f2c738ad924302542d2c0b6d1f30076c77f9651234e1c6d57bc200540f0476"
},
"cherry_blossom": {
"category": "nature",
"moji": "🌸",
"description": "cherry blossom",
"unicodeVersion": "6.0",
- "digest": "af3083f5f8dd94936113f2e16caba5aec7a774d5589aa08bf5de82a2d278cc66"
+ "digest": "67e42777b2d2b8e71dc303c096b45f5b66733d2099533c6c6f798c98e314234d"
},
"chestnut": {
"category": "nature",
"moji": "🌰",
"description": "chestnut",
"unicodeVersion": "6.0",
- "digest": "9f85b79b207a69ab81ab88dcef04954000965b039b4cf57de5f1b381745ab98b"
+ "digest": "0a6528154b5f4039d32a2e7e0550b1e2666bee8d55d4195402829d169fed350c"
},
"chicken": {
"category": "nature",
"moji": "ðŸ”",
"description": "chicken",
"unicodeVersion": "6.0",
- "digest": "57ceb4459d183740009caac6ebed089d2f1e12f67c138e1be1d0f992313c0ac4"
+ "digest": "6fb2f9392e8e78ec3e46187013e53a19dcb319e9528c27e453ae2dc470d91cf3"
},
"children_crossing": {
"category": "symbols",
"moji": "🚸",
"description": "children crossing",
"unicodeVersion": "6.0",
- "digest": "0ded7d9aca0161e8ef8e2858c3c198e70e4badc7105ac3a6886e06975de19106"
+ "digest": "092e5fa179cce029edae31733f6c1dc0e147cde9050183b3f7b121cc7839c2ab"
},
"chipmunk": {
"category": "nature",
"moji": "ðŸ¿",
"description": "chipmunk",
"unicodeVersion": "7.0",
- "digest": "5b0dc1a859163097727ba2ba5ffca38b0a54d925eebb089977d28d0b4d917a3f"
+ "digest": "ec1f696b11273364e8c7f386d38bbb133e5d7c387b9ea7ebc49b4fd5c84717c4"
},
"chocolate_bar": {
"category": "food",
"moji": "ðŸ«",
"description": "chocolate bar",
"unicodeVersion": "6.0",
- "digest": "dd273e5050488acaf885f8a18b6e2b3901f69c5b39fa6465fb60621783d4109a"
+ "digest": "89fbf46c19d87b7d86c400a54929fc7c3a0c4bd2a7c19f76f31e47486080b37f"
},
"christmas_tree": {
"category": "nature",
"moji": "🎄",
"description": "christmas tree",
"unicodeVersion": "6.0",
- "digest": "ce60cbe2ebbe8057be8edea2392455fedd2bcda64a0a831f6a1942028af7e747"
+ "digest": "cb28845d8770cc86de0034f03e38e46b251fb5bd4357a923c107404e8c5116bb"
},
"church": {
"category": "travel",
"moji": "⛪",
"description": "church",
"unicodeVersion": "5.2",
- "digest": "2c328456528f7336e59443e20ec3ab22fe71f1fccb1dd50d0ad68eb206937557"
+ "digest": "5920057525f6b395d3aead6f44f5a1cbf76662fac740f993694afe8f482c0864"
},
"cinema": {
"category": "symbols",
"moji": "🎦",
"description": "cinema",
"unicodeVersion": "6.0",
- "digest": "4c26dcdc76f93dbc2a1dc49ed4e132b8e8f2b7cdc1acf5e09b3dfd99430d97cd"
+ "digest": "acfdea199d4ab48103e5491dd3ab0a616ffbef57641a07aef315273559ccf690"
},
"circus_tent": {
"category": "activity",
"moji": "🎪",
"description": "circus tent",
"unicodeVersion": "6.0",
- "digest": "fec5f2a06222be8be549178b29720343cc00145177ec387ca4e6f3432481fe77"
+ "digest": "5bc6aae497746b5af5cbc03d703df1754903cc71c25a2c7fc8a068292f5614fc"
},
"city_dusk": {
"category": "travel",
"moji": "🌆",
"description": "cityscape at dusk",
"unicodeVersion": "6.0",
- "digest": "bba345e949dcc51f5f018220f000223797970c82ead2ab9c822f9dc0847aa155"
+ "digest": "19bc4c1367c0a6e925c7dd9421d41bfb688903ef08531df05809b5bbda429d03"
},
"city_sunset": {
"category": "travel",
"moji": "🌇",
"description": "sunset over buildings",
"unicodeVersion": "6.0",
- "digest": "a846df1a4c7c778f8e1729804aece86eb29d2fcb95dc39eaaf2aae1897f3dcc7"
+ "digest": "7da54c98e269c041a20dc94861338b546af78ffaa577249e14f1258e232ca5dc"
},
"cityscape": {
"category": "travel",
"moji": "ðŸ™",
"description": "cityscape",
"unicodeVersion": "7.0",
- "digest": "ee360be7514c4bfb0d539dd28f3b2031ebcef04e850723ec0685fb54bd8e6d5f"
+ "digest": "1ae1932db38c72652e85dfe56dd173a37ed96b6913ec74f1718d19fd6ea948ac"
},
"cl": {
"category": "symbols",
"moji": "🆑",
"description": "squared cl",
"unicodeVersion": "6.0",
- "digest": "fcec2855dbad9fda11d6e2802bc0dcaabab0b5be233508f5e439f156f07602c1"
+ "digest": "071117bab8c92f8ea4b734b358d3591ef4b4df067514b80f747b6293efc77ec7"
},
"clap": {
"category": "people",
"moji": "ðŸ‘",
"description": "clapping hands sign",
"unicodeVersion": "6.0",
- "digest": "a1860ce7812a9f6fb55e45761e1b79a2f8f0620eb04f80748a38420889d58a2a"
+ "digest": "68fca08d9340cd18b061a9ceef10111b006df9f888b534dd9b307c490cdb045c"
},
"clap_tone1": {
"category": "people",
"moji": "ðŸ‘ðŸ»",
"description": "clapping hands sign tone 1",
"unicodeVersion": "8.0",
- "digest": "18a7022e08223fb2109af5a9b9a5b4f47dc870ce4453f4987d2d0b729ef54586"
+ "digest": "dc842eb100206a92eab5cefadeb5dab004ee34d054b0adc02de27f525a0a724c"
},
"clap_tone2": {
"category": "people",
"moji": "ðŸ‘ðŸ¼",
"description": "clapping hands sign tone 2",
"unicodeVersion": "8.0",
- "digest": "5954c8658b15e755d2018d8674df84d38e22ffededc4d726c6a33b709f71426a"
+ "digest": "6a92a954a6ea47ce0e42dceee82cd4220f710582f7589cb86037555f0a5e9dce"
},
"clap_tone3": {
"category": "people",
"moji": "ðŸ‘ðŸ½",
"description": "clapping hands sign tone 3",
"unicodeVersion": "8.0",
- "digest": "22639b6bd3c53784a2f855d6db7bdf31621519f19dfc29a6bc310eee6421f742"
+ "digest": "6b7dfeae569488df0bd85c16233abcf770bc2bb5942c178cbe5107e798a9ca88"
},
"clap_tone4": {
"category": "people",
"moji": "ðŸ‘ðŸ¾",
"description": "clapping hands sign tone 4",
"unicodeVersion": "8.0",
- "digest": "e55248dc163d1bbd118b50cd8767750ead86d082151febbc0a75b32d63abceec"
+ "digest": "2fa8961ad763675c6619b5f4137e912ce4126fb9b5df71d23c59b05e54533afa"
},
"clap_tone5": {
"category": "people",
"moji": "ðŸ‘ðŸ¿",
"description": "clapping hands sign tone 5",
"unicodeVersion": "8.0",
- "digest": "76046b8157dabbe048a07fc318122456020c9c980fc1b8ab76802330e07b3b53"
+ "digest": "7b8b5e0befd920ac4e02ef1823b63c2513dbe58fe6471dc54b8265b75b4c8f41"
},
"clapper": {
"category": "activity",
"moji": "🎬",
"description": "clapper board",
"unicodeVersion": "6.0",
- "digest": "8149752a0e3e8abede2d433d1afab6d217877d0c76adb1e2845a0142c0cdcbaa"
+ "digest": "73820f057b2d7d50f6be4a51c0ebaa39a4e0463f0f1121471fb3816fdd05f5bd"
},
"classical_building": {
"category": "travel",
"moji": "ðŸ›",
"description": "classical building",
"unicodeVersion": "7.0",
- "digest": "9ee0d00c43d6e22b6a3ddea67619737270cc7e9294797a19c7c60d5f92aa44fa"
+ "digest": "73e1b32e337042475e76fdbdb03c0b04588f626018bd81adce7f3183be907a92"
},
"clipboard": {
"category": "objects",
"moji": "📋",
"description": "clipboard",
"unicodeVersion": "6.0",
- "digest": "bdd7f7d973c714e59d2903d401a876e6018794c7987c9ca57108c137c5edc25f"
+ "digest": "d3d42f1ff9c8dacfd8219d9563e3fab709290d887695d3bf0a0e51afac7b7149"
},
"clock": {
"category": "objects",
"moji": "🕰",
"description": "mantlepiece clock",
"unicodeVersion": "7.0",
- "digest": "302835eab2637db799acf69b3d795571ef3432251267050db0704f2954e8b190"
+ "digest": "c62364007eb0e3a3c873476ff4b97c832947769502944f11875fab15c41dbe36"
},
"clock1": {
"category": "symbols",
"moji": "ðŸ•",
"description": "clock face one oclock",
"unicodeVersion": "6.0",
- "digest": "1778eec07ce061c9393e5abee5ca83b24e1ce61d8a75fa2e39efcb31aa160395"
+ "digest": "633f923dc3e76cd6e502f60e7445c81dc00372bb9aaae80e702c601ddcfb4821"
},
"clock10": {
"category": "symbols",
"moji": "🕙",
"description": "clock face ten oclock",
"unicodeVersion": "6.0",
- "digest": "601fc12ea5280a54c2e69dbb685f454e4165fe771756ed6f89016e29e683a24f"
+ "digest": "d993967e8116003d6de796cba9caf743297fdf8f900bc8d1f0b7eb9bd3a5194f"
},
"clock1030": {
"category": "symbols",
"moji": "🕥",
"description": "clock face ten-thirty",
"unicodeVersion": "6.0",
- "digest": "4fd155f08f797542d52cff4b0aa3ca9f080f37a41c301b82f90ff6d4693c890e"
+ "digest": "fe6cdac5e9d3f8177ab18efd7f2acce65314964872fd659b7b498049bbf1a0eb"
},
"clock11": {
"category": "symbols",
"moji": "🕚",
"description": "clock face eleven oclock",
"unicodeVersion": "6.0",
- "digest": "5c79dc812e812e8a01993ea633b323d654ce3a7ea258692781a4896e4ad2017e"
+ "digest": "2e676cc1f8a7dcbe76ba414a2a2a4b5724a0cda372d936cb869a4cfa540b0728"
},
"clock1130": {
"category": "symbols",
"moji": "🕦",
"description": "clock face eleven-thirty",
"unicodeVersion": "6.0",
- "digest": "41497ee2020ee5ac9aa5f9b07560f7afca7c422b04214449cfc5cea9f020f52e"
+ "digest": "0b95e14406f4b60ba855a4b2d7655a9af98601ce0306f1d113569e033ba054f8"
},
"clock12": {
"category": "symbols",
"moji": "🕛",
"description": "clock face twelve oclock",
"unicodeVersion": "6.0",
- "digest": "046bb7ffa5f5d27c2e3411ba543484d9dabb8ebf6d6e7a7e9bfb088c1813500c"
+ "digest": "62ef023ec5c1a784d39f6af646f7243707d3e318e982fde15adffc9359eabdb8"
},
"clock1230": {
"category": "symbols",
"moji": "🕧",
"description": "clock face twelve-thirty",
"unicodeVersion": "6.0",
- "digest": "bbfe9db5a2043aaba19a7a2a0185c7efcebf1e8c9263b8233f75b53c4825f0f4"
+ "digest": "112ac4095b40ea4fffb33c0341e6bdfff09fca08b4c748eb7ece8544111d02e1"
},
"clock130": {
"category": "symbols",
"moji": "🕜",
"description": "clock face one-thirty",
"unicodeVersion": "6.0",
- "digest": "8662cb395ee680c2781123305c4c8ce8c0df9565c2c942668940be540cc0c094"
+ "digest": "f458c49cccf45aacacc880d56e5e8df03ae5b0974565a46cf63211af054f5b64"
},
"clock2": {
"category": "symbols",
"moji": "🕑",
"description": "clock face two oclock",
"unicodeVersion": "6.0",
- "digest": "42f7429748b612dce7de77221cbbc710655811f7bb23e2a986c36e6d662f0ec4"
+ "digest": "5fb6d50f15f14cc1b95c36b141b6c9f4dc5dd4b16a975f1d500fc6068d048139"
},
"clock230": {
"category": "symbols",
"moji": "ðŸ•",
"description": "clock face two-thirty",
"unicodeVersion": "6.0",
- "digest": "e710b6ef14227cd240ea3e2a867c8ef45b5c060adf3cb30ba9077c2351fe6677"
+ "digest": "8fe558db783dd92c5440e16e1601665732e0867904c0b5cb84b789051cf86e3e"
},
"clock3": {
"category": "symbols",
"moji": "🕒",
"description": "clock face three oclock",
"unicodeVersion": "6.0",
- "digest": "7340d465b398a378211dff9ec806db579d061206fd6fc238623d070cfe0a55ce"
+ "digest": "68750f9fd558c2767bfe227b096b11e468fee50eab0c102c0075c5f0f7102e85"
},
"clock330": {
"category": "symbols",
"moji": "🕞",
"description": "clock face three-thirty",
"unicodeVersion": "6.0",
- "digest": "7aa4a15cc8de04ed3bdeb0f8a54a7915065f2809a07054e002d89926c9766831"
+ "digest": "ebd4e3211197cde5dad9d15f6072e1b4170d9eda723b39cc89717f8d41258f06"
},
"clock4": {
"category": "symbols",
"moji": "🕓",
"description": "clock face four oclock",
"unicodeVersion": "6.0",
- "digest": "36fd88e81ad488b0ec49a911a838693281573fa14736ae4a6dd1c40a4ff69bb1"
+ "digest": "b2bd5e021748355c68e86f6675c0a377084cbc0d9aff36216a08cd467a297ad2"
},
"clock430": {
"category": "symbols",
"moji": "🕟",
"description": "clock face four-thirty",
"unicodeVersion": "6.0",
- "digest": "7bd5dd71e89d95dcf18b9e8c1fe2a353a7da3b69aadb8dda80ee9bafb05da58d"
+ "digest": "48ece793fbbcef573ac41bd266dd2846d73e1ec39aba6a686eaf30db111ec316"
},
"clock5": {
"category": "symbols",
"moji": "🕔",
"description": "clock face five oclock",
"unicodeVersion": "6.0",
- "digest": "aa406409e56a0bfd8c850e44efe45fd190ffd7bf7061e934ed7928dfbdfc9eba"
+ "digest": "0833f9541c01ddd02abca0a77f8330e0cc9808239a828bf46552d73f4201de52"
},
"clock530": {
"category": "symbols",
"moji": "🕠",
"description": "clock face five-thirty",
"unicodeVersion": "6.0",
- "digest": "25dd3bcc53ddd98eeea498d7dbd4c306ef39dd033f15909063388a0800febf41"
+ "digest": "18714913412c75d6a63ce81f5c7352d7de903236d3bd66c5289360693b218c79"
},
"clock6": {
"category": "symbols",
"moji": "🕕",
"description": "clock face six oclock",
"unicodeVersion": "6.0",
- "digest": "0a321eaf1bc5db8436bbadac66c45ba257fc98ad4c7569ce3fc6602c824b6d7c"
+ "digest": "0353aca1545ed3d257bbeb2411485b14a7f2f9d5cdabfb71cf4be1d56ec43672"
},
"clock630": {
"category": "symbols",
"moji": "🕡",
"description": "clock face six-thirty",
"unicodeVersion": "6.0",
- "digest": "55a4c5a665fdd38a724e9357a93c55401fcd5f1b13078c25754bd70c3fc4ccec"
+ "digest": "1b0509664d686555e22158ca916173442e28d3a20482235b03dcc65b11cf8c9c"
},
"clock7": {
"category": "symbols",
"moji": "🕖",
"description": "clock face seven oclock",
"unicodeVersion": "6.0",
- "digest": "6154306545716e865da0ec537ee4f22bfe6c7294502a64a2dcf425c587d0e2a2"
+ "digest": "b8a51e0db28e84ae9ff3e3c35b8372d39f1e00d38e3d1955dd6e20df0117a24f"
},
"clock730": {
"category": "symbols",
"moji": "🕢",
"description": "clock face seven-thirty",
"unicodeVersion": "6.0",
- "digest": "6925654de642e50f84661f94364a96c87757d73fffe766aacbf4bbd70130547b"
+ "digest": "5fc1ed251ed36b55987faa970091aa7003d1a2ec4450326f557fad23e10b9b51"
},
"clock8": {
"category": "symbols",
"moji": "🕗",
"description": "clock face eight oclock",
"unicodeVersion": "6.0",
- "digest": "9be2d189c7ea56d39fd259f84853d753c1cf33e64f8ed57f86f822d9ae23a1ee"
+ "digest": "8630ef0007be79086814447406449c1a2fe0e8c94b2abd890062d33c0d06f5e1"
},
"clock830": {
"category": "symbols",
"moji": "🕣",
"description": "clock face eight-thirty",
"unicodeVersion": "6.0",
- "digest": "16878613c0000d2f558c88d080551f424a8bd9df1358e0f931dd25c3da68f2d9"
+ "digest": "dfaf3bbb3634a30fb8073d5fb41d8201743d596d88276a6592ea78fb3c68a3e4"
},
"clock9": {
"category": "symbols",
"moji": "🕘",
"description": "clock face nine oclock",
"unicodeVersion": "6.0",
- "digest": "1d1e7e3c9d085ffa5b7c0f3d9fd394b734f16ae3b60df09af50fe6c8d4f3c8bb"
+ "digest": "23bed79d4e2fbe374d0cfd51baff6ec1524e4ae4b71bf02938e40d34c8fe9dd9"
},
"clock930": {
"category": "symbols",
"moji": "🕤",
"description": "clock face nine-thirty",
"unicodeVersion": "6.0",
- "digest": "9fdef6a4939315c017b165e1dbac7710fb335df8c309be3fe2a011ef7fc28d74"
+ "digest": "6a9e6a5775f11cea55103d4c3c02fef87da6196c4d4b58b91820b0074fabfa67"
},
"closed_book": {
"category": "objects",
"moji": "📕",
"description": "closed book",
"unicodeVersion": "6.0",
- "digest": "b18288629d201bfdfc5d66ec47df89809d00642b15732757e6a04789f36a7d9f"
+ "digest": "2b60f7ca436be9aa12cc95d9733e3c72cf36ca7c98a83be70748d1452fa758da"
},
"closed_lock_with_key": {
"category": "objects",
"moji": "ðŸ”",
"description": "closed lock with key",
"unicodeVersion": "6.0",
- "digest": "e39adfe9b30973bca16472c2b7e6462b064a93b9d452aa48edd74c727641a83d"
+ "digest": "5772854e275a722c97338858e416961e9812c19a6e908323f02d400158fbd6da"
},
"closed_umbrella": {
"category": "people",
"moji": "🌂",
"description": "closed umbrella",
"unicodeVersion": "6.0",
- "digest": "2cc0592c74601f7439e88c3c1ec4f05e3459608ef1ea6558c5824ed7c3889727"
+ "digest": "464550b8a3f71825b81ba11f158b815dd54d33e010c1bc1ba67ea196efcbccb3"
},
"cloud": {
"category": "nature",
"moji": "â˜",
"description": "cloud",
"unicodeVersion": "1.1",
- "digest": "5b3a19718dfa8a381929665afdc2284464d24020c8dd0caff4dad465a1f536ba"
+ "digest": "5a44592a6e7185d800b540d087049b75c1a8fd706725c980001633f64dad1472"
},
"cloud_lightning": {
"category": "nature",
"moji": "🌩",
"description": "cloud with lightning",
"unicodeVersion": "7.0",
- "digest": "2b32f6d87726df2935ad81870879ccec30ce9b4fd5861d1a6317f9eca2f013d9"
+ "digest": "6e0db4d854dfb78548f458630b0f66a2a5bfa415116d87e89c9ee3c1595eccdb"
},
"cloud_rain": {
"category": "nature",
"moji": "🌧",
"description": "cloud with rain",
"unicodeVersion": "7.0",
- "digest": "1e1e8bc59e168e1d2e72bf11f2d43cb578cbf0a5f1daf383bba5c56fb750ee71"
+ "digest": "34a9645f4842e11f88490cb90868f0eda46848c0ca691220eb7d9e789bb5735c"
},
"cloud_snow": {
"category": "nature",
"moji": "🌨",
"description": "cloud with snow",
"unicodeVersion": "7.0",
- "digest": "2d364f859b83e684213e8eece1640208d80a8de0a49d0fc8e0e24c5a8493a3b1"
+ "digest": "34fadb93556a1c2b94104ba4b533b0a2b56399f41f4d4e9f4898a8c8add204b6"
},
"cloud_tornado": {
"category": "nature",
"moji": "🌪",
"description": "cloud with tornado",
"unicodeVersion": "7.0",
- "digest": "7cbed2343c280ba3996082b3d0fb9d8cd57d6e62fe6c9ecb159f46b4a2e49151"
+ "digest": "d7ff0075ec6ad30866c1f44d6b091e11e9d56ec5395481f9372edf08cfb7e002"
},
"clown": {
"category": "people",
"moji": "🤡",
"description": "clown face",
"unicodeVersion": "9.0",
- "digest": "eea95687caabc9e808514c2450ba599e5e24ef47923dbec86f5297a64438e2e5"
+ "digest": "4cabd73ae323f53200eb179e177ffbcc984f07847b71912f0c2874fa9c5e53f3"
},
"clubs": {
"category": "symbols",
"moji": "♣",
"description": "black club suit",
"unicodeVersion": "1.1",
- "digest": "b8cf72ecd8568ced077b475d94788fb282bdb06d25031b5d54dd63e25effb138"
+ "digest": "eca840fc5c181df26e30df8ac9de5303c534d7532d86a4c4f29e029ebb1eb18d"
},
"cocktail": {
"category": "food",
"moji": "ðŸ¸",
"description": "cocktail glass",
"unicodeVersion": "6.0",
- "digest": "3792def2cde885cf32167f04904d3b0b788388e8af410c63e4cd31550feba775"
+ "digest": "91b4e4dc85b87b50d85d4831a18de7dd952c45c427f46a1a2c55d0abf4c4f5dd"
},
"coffee": {
"category": "food",
"moji": "☕",
"description": "hot beverage",
"unicodeVersion": "4.0",
- "digest": "0d29615a7a67d3aafa257b909bb915dc74fa8f854acb0d9a2c29e94eedf80326"
+ "digest": "bd09e4d36ebe4df49c695147a2d1ae91b6cbdd7eb7bb5066a1bada8ca2fa7c6f"
},
"coffin": {
"category": "objects",
"moji": "âš°",
"description": "coffin",
"unicodeVersion": "4.1",
- "digest": "78eccc1aad2a822649fba8503d4d30354bef367c4271193c40ddb692308f9db8"
+ "digest": "08e3596ffa53801967dd6ff1715999513d8d9b3ae1f1f7c2b841a414981ee5d4"
},
"cold_sweat": {
"category": "people",
"moji": "😰",
"description": "face with open mouth and cold sweat",
"unicodeVersion": "6.0",
- "digest": "f53aab523ed3fa2224a16881d263fb5e039f163380f92feb2c63c20f9b14dcd2"
+ "digest": "d96b966a52919667857c96c5d03596cb29daa1a7d87acba0286556f5dcaa25af"
},
"comet": {
"category": "nature",
"moji": "☄",
"description": "comet",
"unicodeVersion": "1.1",
- "digest": "40ce93e55c6e57a88d80670b37171190bd5ffc87b7078891d8de5b15795385c5"
+ "digest": "647209d932dbca09e1a0f3e13b0579251f76ba5f314faf6fc010eee6eb1606bb"
},
"compression": {
"category": "objects",
"moji": "🗜",
"description": "compression",
"unicodeVersion": "7.0",
- "digest": "c8841f7afb5345f1c31da116a7fb41d07232ea58d3f7f1a75c5890aa1a80bfd6"
+ "digest": "e762761f41d6c41d204ca149b161ea4286ae71517ea714fa75951c0eea600eeb"
},
"computer": {
"category": "objects",
"moji": "💻",
"description": "personal computer",
"unicodeVersion": "6.0",
- "digest": "c970ce76b5607434895b0407bdaa93140f887930781a17dd7dcf16f711451d93"
+ "digest": "08200fc0c04bb776d3b7e187de415a1a6a6bc82a7beb70829e03c40c5312d7d1"
},
"confetti_ball": {
"category": "objects",
"moji": "🎊",
"description": "confetti ball",
"unicodeVersion": "6.0",
- "digest": "a638b16f1acdbcf69edf760161b1bd7ff1fd5426c5b1203ad9d294dcc0701f10"
+ "digest": "745790484353edffb62c78d1460baa049411e32fed88bd6424c0fd804fe67ca8"
},
"confounded": {
"category": "people",
"moji": "😖",
"description": "confounded face",
"unicodeVersion": "6.0",
- "digest": "e2ff3b4df65d00c1ca9ae0cb379f959ea2cecefb3d676d4f8c2c5f2c103da4f6"
+ "digest": "084da8b9e9e24eaee418df200ed9369e04fded381d756382b34f96a362d2c93c"
},
"confused": {
"category": "people",
"moji": "😕",
"description": "confused face",
"unicodeVersion": "6.1",
- "digest": "118d7f830ec08a3ac4b798eebb77a989b8c142f2588727181be4a2548e3c4f06"
+ "digest": "4b8a05e1d84cb6314b217fdd4f89065411021f3ed3f5a824dbf538d54b5c3132"
},
"congratulations": {
"category": "symbols",
"moji": "㊗",
"description": "circled ideograph congratulation",
"unicodeVersion": "1.1",
- "digest": "02fd1338c54fe5f9a0fd861f23c56edc1d39bcd3140b68f0f626f9e2494d2d1c"
+ "digest": "3c4f04a0b13353e975bdcd489f5cc2899b3dace2c83ca3012605f1b2801b581e"
},
"construction": {
"category": "travel",
"moji": "🚧",
"description": "construction sign",
"unicodeVersion": "6.0",
- "digest": "c3a0401331111b9eda1206bee5f322db80b0870547d307b10dcac1314e4078c8"
+ "digest": "3a406d5baeede21f5ae078a4a641ee42d36c1b877a97bb10191fec729a6c0fb1"
},
"construction_site": {
"category": "travel",
"moji": "ðŸ—",
"description": "building construction",
"unicodeVersion": "7.0",
- "digest": "c611f0a5de10f000a0756935f226845c7292f19ff5581d1f7a7554316338bbcb"
+ "digest": "5973b6f1b1c75fd083d975c2c11f68fff6583f10056418c699da1cd3049a5f89"
},
"construction_worker": {
"category": "people",
"moji": "👷",
"description": "construction worker",
"unicodeVersion": "6.0",
- "digest": "8c094733987e7c4da8d3aa4588b530ae07042bd70cf337b1fd412a70ee8f0ed6"
+ "digest": "47476b5eb51a1e00d0c95f032c79ca6472b41ece0bdf057bbb87da088605c589"
},
"construction_worker_tone1": {
"category": "people",
"moji": "👷ðŸ»",
"description": "construction worker tone 1",
"unicodeVersion": "8.0",
- "digest": "fcd927405fef4486105cd3aff62155467d21cebbc013924d4b52b717b566602b"
+ "digest": "087fe998c1e316591d4a0c09c7ef80b0cf73d7f0f295e4bc18405e9153eb7b6c"
},
"construction_worker_tone2": {
"category": "people",
"moji": "👷ðŸ¼",
"description": "construction worker tone 2",
"unicodeVersion": "8.0",
- "digest": "d1ec773828936c703dd6e334e696dc3cf7c34c0a8ec691564a384b735cdeaaba"
+ "digest": "2a829b907f78a0d197677d19be96e177e0a021a04decb3c0bbf637cf74716787"
},
"construction_worker_tone3": {
"category": "people",
"moji": "👷ðŸ½",
"description": "construction worker tone 3",
"unicodeVersion": "8.0",
- "digest": "37c114d6879b9b32b800b0d4cf770dcbe04d1455698130ecd709a0cb9dea880b"
+ "digest": "551d3bddffe6e7c739732a1d759994e2a8090e81df401a70c5b4eab315242840"
},
"construction_worker_tone4": {
"category": "people",
"moji": "👷ðŸ¾",
"description": "construction worker tone 4",
"unicodeVersion": "8.0",
- "digest": "5264996c1bedb6061a0dfdddce233d863bf308d27127ad152b63bfd983162cf7"
+ "digest": "d563f84633598c86bbad12a96418eee7e7a6cd945d9ecdb60d93be56697b8d96"
},
"construction_worker_tone5": {
"category": "people",
"moji": "👷ðŸ¿",
"description": "construction worker tone 5",
"unicodeVersion": "8.0",
- "digest": "87051aec81fd5dfd4dc44ff0411a528ee08253e9494d37efa550694e28dde6d3"
+ "digest": "56950bb7e235ccd82c8b1e689268ecd471809b8b65ec8654949a15cd6b42e7b5"
},
"control_knobs": {
"category": "objects",
"moji": "🎛",
"description": "control knobs",
"unicodeVersion": "7.0",
- "digest": "0d7f33ff7acc1cc3a81e6a786ff007df20da145e3070f338505dfed5100e9fcb"
+ "digest": "437abc26fe18f903c498b5223ab35de813b8166e8460cfe9bc5b59177d949bc1"
},
"convenience_store": {
"category": "travel",
"moji": "ðŸª",
"description": "convenience store",
"unicodeVersion": "6.0",
- "digest": "975dcf9b8e9e3fb1e29574b41300b9d96fd64703b3c18ff52f9f1875d1cf1b52"
+ "digest": "07d3989157223a8249db3532a642050529831d47f05c0733fbe2cb6a6a780ea6"
},
"cookie": {
"category": "food",
"moji": "ðŸª",
"description": "cookie",
"unicodeVersion": "6.0",
- "digest": "4bed3522bd50091ac5b68ca760661eb484d7f1b9c9d564d2097bd812b7f28ae4"
+ "digest": "246ade6def10ac3e98af1ba9517990a4b41e391b9f1d8323a333d4cb69acbe36"
},
"cooking": {
"category": "food",
"moji": "ðŸ³",
"description": "cooking",
"unicodeVersion": "6.0",
- "digest": "563ffd6cae381ce1e318cdacc54e70040d6a01a50d0db8aeb50edbbe413eac58"
+ "digest": "b4bcd344fb394300464b8a81f325f8652c032f39ebe2acf85e046d594a58b84a"
},
"cool": {
"category": "symbols",
"moji": "🆒",
"description": "squared cool",
"unicodeVersion": "6.0",
- "digest": "5739a37341c782a4736adfce804e12776ae33081098a3d052d8ae9a64b4d22d1"
+ "digest": "d9e004043f68d0dfea5cb4ae961c4e66edf32a840bf5f1dae43df3c522db6322"
},
"cop": {
"category": "people",
"moji": "👮",
"description": "police officer",
"unicodeVersion": "6.0",
- "digest": "78996521bbe231d03ebea355226d8a1515f47cde7b2fbeca1037e7b7e5133466"
+ "digest": "ca75e6722bc6520f3375af4d588cd5af15b52d5a856a67d99414e149d8ea9ca0"
},
"cop_tone1": {
"category": "people",
"moji": "👮ðŸ»",
"description": "police officer tone 1",
"unicodeVersion": "8.0",
- "digest": "8a38cd107f5f4c0b821ac43f32df5dc57facaf39fbafb98483ec00fd7df41baf"
+ "digest": "309280c5b2f6f957134015fe62a262b7853b67c6d7a020e59e942a21ac52c561"
},
"cop_tone2": {
"category": "people",
"moji": "👮ðŸ¼",
"description": "police officer tone 2",
"unicodeVersion": "8.0",
- "digest": "8ab8ab086f3ff82aa4bf4760c3c822846ec2696c41d21dffdac12d5afbe398b7"
+ "digest": "2db60b30bb0533a82590190ba1e9aa2a4a21b13219c9b5fdf67e0c88a63cac59"
},
"cop_tone3": {
"category": "people",
"moji": "👮ðŸ½",
"description": "police officer tone 3",
"unicodeVersion": "8.0",
- "digest": "fce710a99fd44a7c8af3ea01b2007e46d3ff38d7a0dff1ef26d6f893ede7e6d2"
+ "digest": "724bf942373fe976683449d871bd76275f0b21966abd69dfe046249731f17fee"
},
"cop_tone4": {
"category": "people",
"moji": "👮ðŸ¾",
"description": "police officer tone 4",
"unicodeVersion": "8.0",
- "digest": "3017dd73ef475379911c5e6c79bd0f9f533dbbc5057bce6a11244faa12996ba0"
+ "digest": "c95ba196d60964cdc5252cef740ee98369ce6a9553f6da55e8b0dc3e6cfc345b"
},
"cop_tone5": {
"category": "people",
"moji": "👮ðŸ¿",
"description": "police officer tone 5",
"unicodeVersion": "8.0",
- "digest": "a3b8807b3f2a8d6ee9bcec0339355bda486e8c930f727139f5447a4b046a6307"
+ "digest": "8aa857e06fa050ae584e2be28e61944e336f7b53d94ec10763be04ce9b59a812"
},
"copyright": {
"category": "symbols",
- "moji": "©",
+ "moji": "©ï¸",
"description": "copyright sign",
"unicodeVersion": "1.1",
- "digest": "cc28663cdd3f8333d9bb57b511348cde4e51bda19cf0629dccb05c8fc425e079"
+ "digest": "681f772f6710df90e3b53e2ee6c3170f344873bd4c1e41e2016a411125b90f4a"
},
"corn": {
"category": "food",
"moji": "🌽",
"description": "ear of maize",
"unicodeVersion": "6.0",
- "digest": "a099a0b291fa758690e6ee6c762b9ade9a0e3350a707c52d968dfffbcc467de5"
+ "digest": "18c605b675251470f411303851450e3010e6a4683c06f1ad0df48eb2c8560a46"
},
"couch": {
"category": "objects",
"moji": "🛋",
"description": "couch and lamp",
"unicodeVersion": "7.0",
- "digest": "84cd734dbaa7f9f519438036d687e7a53217130779bc3de30258f163521b9474"
+ "digest": "e9421d26e96ce4d68b09280e77e699963a3d8259385a12fd28375d61de4aff6b"
},
"couple": {
"category": "people",
"moji": "👫",
"description": "man and woman holding hands",
"unicodeVersion": "6.0",
- "digest": "c897ba76e24e2f43a4aa261c2754800a8473f43c7ce53f9909a6af2c4897732a"
+ "digest": "d6523ae18c5e2a10b355dda179ca7b172ece9ef3ac70548dba3c45a5d5169e70"
},
"couple_mm": {
"category": "people",
"moji": "👨â€â¤ï¸â€ðŸ‘¨",
"description": "couple (man,man)",
"unicodeVersion": "6.0",
- "digest": "c812471d35d46e12270653039a907d1dfa2dea0defd65596283e5b8e03cea803"
+ "digest": "0c3344e2abffd74868fb52ffa5614c77737094bac369030ceac6218eee2a0edf"
},
"couple_with_heart": {
"category": "people",
"moji": "💑",
"description": "couple with heart",
"unicodeVersion": "6.0",
- "digest": "420bfa81bad10365550c77a98e1c07eb00d03663fe7b610fab1aca8a0a9d201b"
+ "digest": "224c8f5d7c5a446b69e7175dfa6b07a9d36f2b2db3f908579813b6bcffb35f92"
},
"couple_ww": {
"category": "people",
"moji": "👩â€â¤ï¸â€ðŸ‘©",
"description": "couple (woman,woman)",
"unicodeVersion": "6.0",
- "digest": "7ac49153a612d63302299eee996308b7dcafa0a152473dab679215036fe6567e"
+ "digest": "56651c521bbaade1979708f52d827e2251581b576c3afa651c89ea4c63739916"
},
"couplekiss": {
"category": "people",
"moji": "ðŸ’",
"description": "kiss",
"unicodeVersion": "6.0",
- "digest": "1acfef9d375c4c1deb235babd856b0f90ad4f3194751694cb6abb44f00f29e42"
+ "digest": "14c66d83cace54fb7326ef04eb989ee27d5f2dec2e3884374cd346cd30340d5e"
},
"cow": {
"category": "nature",
"moji": "ðŸ®",
"description": "cow face",
"unicodeVersion": "6.0",
- "digest": "d71c854ff8b343ee24b8c2b9d56c7cb3fc6fa1a6dc0d7a137841b9f646e6d71b"
+ "digest": "9959b4d621471e4c3ddd23f52ddeb5ddb5792a0b6ac8697d2c2940bd6cb01b82"
},
"cow2": {
"category": "nature",
"moji": "ðŸ„",
"description": "cow",
"unicodeVersion": "6.0",
- "digest": "e7a5131d7dee0f3356814b0ac1ea8ff280b12a7b580181e20ddb0b7eeb7e7339"
+ "digest": "a9f5cdb317d96e7536d87faff2f2c651d6fb5bd00b89991c977b270e9f522820"
},
"cowboy": {
"category": "people",
"moji": "🤠",
"description": "face with cowboy hat",
"unicodeVersion": "9.0",
- "digest": "1aabf23f6b95a9b772fdb8eb45b8ec93584a5357f9131c6eabc9d1b83fe67e89"
+ "digest": "0c3a81e8bc276a84073ae94db2cf08d378b3e17ca09e2e03abf248c66c00f34b"
},
"crab": {
"category": "nature",
"moji": "🦀",
"description": "crab",
"unicodeVersion": "8.0",
- "digest": "e6be16699fdb5d87f42f28f6cc141a44b7ffd834ecdd536813c4b5b86d3fc4a5"
+ "digest": "8cdd21a6eaa56df3e503e8710e703b60ba6b059eaf2a9e93d8d25a4cbe2b55dc"
},
"crayon": {
"category": "objects",
"moji": "ðŸ–",
"description": "lower left crayon",
"unicodeVersion": "7.0",
- "digest": "b180d6afa4777861222a4228164ce284230fe90c589f52ffa9351bac777e901a"
+ "digest": "d2d609470d943ad4a320273180eb9c9bced90c472e24cac3f0a52f238f8caaf9"
},
"credit_card": {
"category": "objects",
"moji": "💳",
"description": "credit card",
"unicodeVersion": "6.0",
- "digest": "808cd120fd3738eb2be1f6c6c029d98387b0e03fca7d1451e8fbf9c5ab3f643f"
+ "digest": "b96a52f41dfd125f63f3f927e8333db5dd31388e3b9cfce4664bad8bc6a750a3"
},
"crescent_moon": {
"category": "nature",
"moji": "🌙",
"description": "crescent moon",
"unicodeVersion": "6.0",
- "digest": "042e7e01e6e88b97a763b7cc41e2a2b3fe68a649bacf4a090cd28fc653baf640"
+ "digest": "bab44314af40c16b245f2e91b2cec98592cddda05630012ac9d6554e1d9b8b43"
},
"cricket": {
"category": "activity",
"moji": "ðŸ",
"description": "cricket bat and ball",
- "unicodeVersion": "8.0",
- "digest": "4c4559d0b4efe24cc248fa57f413541307992e519d0cb9fb8828637ac2f4cc16"
+ "unicodeVersion": "10.0",
+ "digest": "c0447966114b1db5c9d1dd5e47bd7f85a19accb8c6daeb9984644834e72e7598"
},
"crocodile": {
"category": "nature",
"moji": "ðŸŠ",
"description": "crocodile",
"unicodeVersion": "6.0",
- "digest": "59cb4164c50b6bc9ae311ce6f7610467c1aaafa848b5fff7614f064715f91992"
+ "digest": "94f36ae30277cc802bbe827c727358540548ebdd85d3e1f70e976e205a885756"
},
"croissant": {
"category": "food",
"moji": "ðŸ¥",
"description": "croissant",
"unicodeVersion": "9.0",
- "digest": "b751e287157a1e276617a841a5b5f7f1208ca226cfd8fa947f144390b65a5e16"
+ "digest": "8524b964d39d5193569c03177162dc3bf2d6b2e1d4b5ba2b651cd906199f053f"
},
"cross": {
"category": "symbols",
"moji": "âœ",
"description": "latin cross",
"unicodeVersion": "1.1",
- "digest": "a6b07c838fb75ef2ebefa2df6005e8d784753239ec03c37695a13e3b1954d653"
+ "digest": "4c96506b864fefcb67c75ab76262065ca34dc247bdf0a65a859a7c18051aa8be"
},
"crossed_flags": {
"category": "objects",
"moji": "🎌",
"description": "crossed flags",
"unicodeVersion": "6.0",
- "digest": "2841c671075e6f1a79c61c2d716423159fb0bc0786e3fb0049697766533bf262"
+ "digest": "451e17cbb40af3f42c7f687186c3ba7d8c9a99826635f3733256c663a0be31cb"
},
"crossed_swords": {
"category": "objects",
"moji": "âš”",
"description": "crossed swords",
"unicodeVersion": "4.1",
- "digest": "3771a5b26b514236521ce44e15f7730fa9148c6a782b9b600ab870a1f7de6f9f"
+ "digest": "a69a11c517efe421e0c36c3e231520967e8791d41b7a83370229e166b7a25d13"
},
"crown": {
"category": "people",
"moji": "👑",
"description": "crown",
"unicodeVersion": "6.0",
- "digest": "6741e58d8f823194e0a3484ac1563e20d9e0b44c1bc46d82444dfffa092cdfc7"
+ "digest": "6fd07901b1aedf7f0fe7ebcdbd6f7fe40f768a66a0e862203274097b16b5431d"
},
"cruise_ship": {
"category": "travel",
"moji": "🛳",
"description": "passenger ship",
"unicodeVersion": "7.0",
- "digest": "2b7b62db5d118a632673564099e3405ea6d61ea9b8e123b5a2aaf011bb2a54a4"
+ "digest": "8dc923a465e8183b0a1410f810825c190e494c77b01de7c2f5ee0a64f7580206"
},
"cry": {
"category": "people",
"moji": "😢",
"description": "crying face",
"unicodeVersion": "6.0",
- "digest": "fc3307ec4fe75539770c1123a0e8e721d9e021009a502655132f68d7cc453816"
+ "digest": "5b16d711fc3d2e611dbd406e5849c22ebdad9c9812fd6897f304a89f21f05755"
},
"crying_cat_face": {
"category": "people",
"moji": "😿",
"description": "crying cat face",
"unicodeVersion": "6.0",
- "digest": "4942c24935c22babdcb8af41d2c0a7588356b6b674bc238902e2f10ad03e2c5b"
+ "digest": "32cc70455196cddbd0664789c5b1dc7d777a81884b748bdf43c8de6cd892d498"
},
"crystal_ball": {
"category": "objects",
"moji": "🔮",
"description": "crystal ball",
"unicodeVersion": "6.0",
- "digest": "05f73b30b1e5b0fc66fb5dc6caddd2d547ee7b9d2f97513dc908ba1a2e352e30"
+ "digest": "225f048f2fefb378d3178931ad5e5e8feb419a19436e45d03c199bd726ec5151"
},
"cucumber": {
"category": "food",
"moji": "🥒",
"description": "cucumber",
"unicodeVersion": "9.0",
- "digest": "d1196e23f2f155ef5c1330f8497f40957a7357cb177127f457c5c471f0a23727"
+ "digest": "752ddddf7b18831b74cc2b14b3fd787f9f914c1a9e72b7119f2e0b7267e4f749"
},
"cupid": {
"category": "symbols",
"moji": "💘",
"description": "heart with arrow",
"unicodeVersion": "6.0",
- "digest": "246e71f44c6ebc2e4f887e25438e4f894e8cc92e06069e711b893ff391abb658"
+ "digest": "c13b5e7a7a9824b3921b07805ffc08bb07e01f5384c49909ac375e9f55a3102c"
},
"curly_loop": {
"category": "symbols",
"moji": "âž°",
"description": "curly loop",
"unicodeVersion": "6.0",
- "digest": "9e4eb98d6597888f91208080c6a79824adb432ea34f46c85da26cb630bd1cc73"
+ "digest": "365b37a4afb451ace34de1a59727467bfe6f501437dc3459ec55a0234d98e307"
},
"currency_exchange": {
"category": "symbols",
"moji": "💱",
"description": "currency exchange",
"unicodeVersion": "6.0",
- "digest": "b85377265b9876888969aa42b65bba0be523a370175baf226f20131e535af554"
+ "digest": "3703307c690bd113fbe5826720c6466ee9dccc80ef8d3556cfe2ba7401240df8"
},
"curry": {
"category": "food",
"moji": "ðŸ›",
"description": "curry and rice",
"unicodeVersion": "6.0",
- "digest": "a01c0a713662817720b485f7739f57e61afc025f5c43792f4de961c94f92f31e"
+ "digest": "6c317ba8a3dba9a294c2a3cb3b6385c946549a06bf934fd4b6964304f3b9a9b3"
},
"custard": {
"category": "food",
"moji": "ðŸ®",
"description": "custard",
"unicodeVersion": "6.0",
- "digest": "85c2b9ac904134a6c3587eb0a0806f2ab4282c5ed5c79d41734f3203998f757e"
+ "digest": "9790383c5841ec63d87182fc0f4dd05862c973b0e1b9f2fc2c047654089a404c"
},
"customs": {
"category": "symbols",
"moji": "🛃",
"description": "customs",
"unicodeVersion": "6.0",
- "digest": "eb2546e1e617d4c1a1f614318af5e5dacf3e8d9479ffa08108977defa83ded32"
+ "digest": "0f374b6f60c5bc6da41b0682a352304bc258ef6274da8afd6820ff9bb50a5c39"
},
"cyclone": {
"category": "symbols",
"moji": "🌀",
"description": "cyclone",
"unicodeVersion": "6.0",
- "digest": "7a0f8564d76adf2d0ed272f56dc0d01fb7b557852e0ca797e73f5472b8630bf3"
+ "digest": "ead05cbe9adcf38310712af602c8caea12eac26e87756579efb8c542dde8b391"
},
"dagger": {
"category": "objects",
"moji": "🗡",
"description": "dagger knife",
"unicodeVersion": "7.0",
- "digest": "35a179168198d03295e626cc27d3b92d30a732c55a2ca75d7a11a0fbed414772"
+ "digest": "6038c5c863bdacbade2f2426a48bd530e286d6624813960ae0e390d71d4cd58e"
},
"dancer": {
"category": "people",
"moji": "💃",
"description": "dancer",
"unicodeVersion": "6.0",
- "digest": "66ffa86827e85acae4aa870c0859fe3a9dad03d21ff4bc800b61c95c902a8a90"
+ "digest": "21117e63374e501b1daf8350d5921314cc8b306558c8d6803d43c71066438648"
},
"dancer_tone1": {
"category": "people",
"moji": "💃ðŸ»",
"description": "dancer tone 1",
"unicodeVersion": "8.0",
- "digest": "bdbee740addc890e369d3469a3585eb0d1e4fbc7e04dd6f6aca762d8aeee6a8c"
+ "digest": "35c64d92577272999d1151cacb584e248a2a005ce9388ce64250bcc8a7178dc1"
},
"dancer_tone2": {
"category": "people",
"moji": "💃ðŸ¼",
"description": "dancer tone 2",
"unicodeVersion": "8.0",
- "digest": "9f7b4c627241eaa2def9717a5286a423f0b9c1b044dd9ea4442a76f1858d14a4"
+ "digest": "9dfdd28db7267f172b1bae228216d0111583c4903934e4afa081cdbf83facd45"
},
"dancer_tone3": {
"category": "people",
"moji": "💃ðŸ½",
"description": "dancer tone 3",
"unicodeVersion": "8.0",
- "digest": "a6bd49a377ce6c2004bf126b6f66d0b21d8c14103c2add7b10f12ed9e1c2d302"
+ "digest": "79b7c1e313b235e0acec3ff50d3eb7ecff53b5ae4a2ba7d363b0992fa939ac9b"
},
"dancer_tone4": {
"category": "people",
"moji": "💃ðŸ¾",
"description": "dancer tone 4",
"unicodeVersion": "8.0",
- "digest": "4ec2a7629c01b0e9006b5cda4deae3bf297ce3b71d18063f93eeb5c14be19a1a"
+ "digest": "16e6f14fef6464ac20273713c196e189eab75f3ecab98b9eee172bc33c8f2847"
},
"dancer_tone5": {
"category": "people",
"moji": "💃ðŸ¿",
"description": "dancer tone 5",
"unicodeVersion": "8.0",
- "digest": "2b48e3a6b366c6f55f73b816e6fb03c39e9890f586f7e9c9043cf0c013d9cdd5"
+ "digest": "c090f007657b775acab02656ad3de9d02f97373d6b897a7052e1aa5b032de2ee"
},
"dancers": {
"category": "people",
"moji": "👯",
"description": "woman with bunny ears",
"unicodeVersion": "6.0",
- "digest": "12be66ed19d232bb387270f40bece68bd0cb2342b318f6c9bb8b49c64ff7d0ad"
+ "digest": "8449ee0de1754c317e82371ae80d7f6b840b69b657960953a50ddcb918f363c2"
},
"dango": {
"category": "food",
"moji": "ðŸ¡",
"description": "dango",
"unicodeVersion": "6.0",
- "digest": "34e8cd153c50f2d725abe8934c35c96a3ab533f0cc5fbb1e1474eafad1dc1fc2"
+ "digest": "c3047205e462d958f6e5ab2ad318bc70e903343c4a87956055f76ea8adcc9456"
},
"dark_sunglasses": {
"category": "people",
"moji": "🕶",
"description": "dark sunglasses",
"unicodeVersion": "7.0",
- "digest": "d0a735ad5bf0ece00af2a21abf950b89292ebd8ca6e28b1dbb1368252fb44afe"
+ "digest": "0f941dc4ed9dcc861863176f49812966bcae7e3179044c1c8fa22de9ed8dbd09"
},
"dart": {
"category": "activity",
"moji": "🎯",
"description": "direct hit",
"unicodeVersion": "6.0",
- "digest": "998642f06a875905e0a6bf30963c025baff1cf55b8e76884b9119f2d71188b0c"
+ "digest": "01d4bb3f51417e7861404746bbebc4704edf5fa80bde6ad9cf9e12c238a1206c"
},
"dash": {
"category": "nature",
"moji": "💨",
"description": "dash symbol",
"unicodeVersion": "6.0",
- "digest": "f7aae7d3887c67d76f3329c2dc9e6807dc580a4b07ab35599c7805e41823a345"
+ "digest": "6c0ab681346b90d7b75e1e16531890a6ebed5c7b8bc63b269cc4a6080328fd6f"
},
"date": {
"category": "objects",
"moji": "📅",
"description": "calendar",
"unicodeVersion": "6.0",
- "digest": "d0b695e4a7cfbbe71b4fbebf345b66ca98f0cf1c751362928e54c23ca78d4c7b"
+ "digest": "3d0a59825a932b1a12f6b0980aaabc93b77f55499d5c6d81f61cf03dbb7188cb"
},
"deciduous_tree": {
"category": "nature",
"moji": "🌳",
"description": "deciduous tree",
"unicodeVersion": "6.0",
- "digest": "3c70f1a77f2754f41c830e88d43b7d53c14311d64626ded164aa9ac7d2695790"
+ "digest": "89804981f62825a45150919436442c70838d90a015de398d2bb9aaffa4b2e998"
},
"deer": {
"category": "nature",
"moji": "🦌",
"description": "deer",
"unicodeVersion": "9.0",
- "digest": "7f4302ca68fd121ee73be48d0a0a0fb9e7e2741071a491ad2b7b0eab9f11ad25"
+ "digest": "83a9c2a0bfb5d82631dc653337279545d72ccea10fb2ccf6da6ab82586fb1d56"
},
"department_store": {
"category": "travel",
"moji": "ðŸ¬",
"description": "department store",
"unicodeVersion": "6.0",
- "digest": "4be910d2efe74d8ce2c1f41d7753c8873579faca83fcf779a4887d8ab9e5923b"
+ "digest": "0cbab31777aeecc148e54777e1a65e794eb4b5f45e0f8ecaffa990efd06a0fb2"
},
"desert": {
"category": "travel",
"moji": "ðŸœ",
"description": "desert",
"unicodeVersion": "7.0",
- "digest": "d4b1a11c5130debe042df6cc2b3389f15c68a5cb32dc1b3a82b78f733d0c9e4e"
+ "digest": "c60bd12a5864c0789c2e8fb93a392a42600e08cc23450c716c0bd008c16e1c93"
},
"desktop": {
"category": "objects",
"moji": "🖥",
"description": "desktop computer",
"unicodeVersion": "7.0",
- "digest": "cde5bfb6c71bb7d663808a3561b24cb5b5560f95f510b40f81250cac1b21933e"
+ "digest": "a4d1664692b50035f04b1236960a59c61fd5bedd35b77ce0772aabb776631fa1"
},
"diamond_shape_with_a_dot_inside": {
"category": "symbols",
"moji": "💠",
"description": "diamond shape with a dot inside",
"unicodeVersion": "6.0",
- "digest": "e91323577ab89e95b0fa0b9272ea0c797b76908f24d36992630e9325273a4ce3"
+ "digest": "785dedaf65b4c8a8b2a758608563528cae6d65864e36b17a45b7b4b15fce67e5"
},
"diamonds": {
"category": "symbols",
"moji": "♦",
"description": "black diamond suit",
"unicodeVersion": "1.1",
- "digest": "bf3d9a020afe8aa226db73590bc193a9c2c3e6e642edd2445c5960c3e67cf153"
+ "digest": "77c773b770a293129c33513fc22124c6953db07d1b254905b0c734c853e65387"
},
"disappointed": {
"category": "people",
"moji": "😞",
"description": "disappointed face",
"unicodeVersion": "6.0",
- "digest": "c0f406c6beea0fd1328adefc097d04aa16b72f7a5afa0867967d8ea25d72db17"
+ "digest": "0e8f9fdef204d2684a92666709ff4d785d5b3690f1ff0f7ebed9f37d2a3651f5"
},
"disappointed_relieved": {
"category": "people",
"moji": "😥",
"description": "disappointed but relieved face",
"unicodeVersion": "6.0",
- "digest": "c826f5dd4f2f7e5289d720851d4826ab8284d915606c1b152ab229b7fadbba14"
+ "digest": "cfe92ebfbaaa0b02b84b05c17c94f07db315a8771d3ebfea8043862559c6ce74"
},
"dividers": {
"category": "objects",
"moji": "🗂",
"description": "card index dividers",
"unicodeVersion": "7.0",
- "digest": "4b2c653b18cf0fa31f1f0ac94a6fbd214ea0d1b0a90a450ab6e169906fc5764f"
+ "digest": "e0b0b297473b27e2163e7b9d38be02a98a025b9c0c679da3bb5af2af7b4d5001"
},
"dizzy": {
"category": "nature",
"moji": "💫",
"description": "dizzy symbol",
"unicodeVersion": "6.0",
- "digest": "d577545c2de42389695447c6ebbfef895f30f0fda84eef45684f9bf4a9c27ff1"
+ "digest": "b3d16f5748abede6f133bac2104e51eaff0e59f184256aa6902ebb6d8a3e32b7"
},
"dizzy_face": {
"category": "people",
"moji": "😵",
"description": "dizzy face",
"unicodeVersion": "6.0",
- "digest": "7b3aeaffb4e15ccf633b91dda4a44847a1eb28d78ce58b4d171b20a771bde414"
+ "digest": "5e3c7e1f97d4d9a330b89358c89d2fbdf31a945f3be40c352600a985ac49b197"
},
"do_not_litter": {
"category": "symbols",
"moji": "🚯",
"description": "do not litter symbol",
"unicodeVersion": "6.0",
- "digest": "98b07fbbcdb438d1b8a755869fa2de8e180a77fce359ec830eb46d38ec3e67cb"
+ "digest": "13dd4fc59cd518187d2827a935ad7ca61c8f4542ff9843d882ee44c942e57045"
},
"dog": {
"category": "nature",
"moji": "ðŸ¶",
"description": "dog face",
"unicodeVersion": "6.0",
- "digest": "3b31ce067b13e463284ce85536512cb1f8cd8b52fe73659f69971d0d6c1dfc11"
+ "digest": "d6ee83df6b3a233b90c0b589c6f290164239fb4062be21566430183d9b4e507a"
},
"dog2": {
"category": "nature",
"moji": "ðŸ•",
"description": "dog",
"unicodeVersion": "6.0",
- "digest": "0a8901bce5ed994533ff84299b2a1364de28d872c9f9510d3426a83e8a9d2e34"
+ "digest": "ba52e04ae1e024c596fc453b9af53347ecf76d342150b7701eccb83ef2df67f0"
},
"dollar": {
"category": "objects",
"moji": "💵",
"description": "banknote with dollar sign",
"unicodeVersion": "6.0",
- "digest": "52438e38867aedc021740bb41f9ba336e75a50faa148419412a01d75d8c93155"
+ "digest": "8e7ee431f4c5afac19aa8d93a433619c96952178e6cf7e20c6e6e0768cccf7e0"
},
"dolls": {
"category": "objects",
"moji": "🎎",
"description": "japanese dolls",
"unicodeVersion": "6.0",
- "digest": "a687184e9a0915deef44bb3cacfb19d3f3f19cf2c110f1da90191dd567333c57"
+ "digest": "da477dfcb1ecfab98835f4ed721354240d1a7f82e1d7df4b80e67baabb237b9f"
},
"dolphin": {
"category": "nature",
"moji": "ðŸ¬",
"description": "dolphin",
"unicodeVersion": "6.0",
- "digest": "0b7ee08f4236232ca533ed3a3023d28020d36f178efaec5ce8b0e13a84778512"
+ "digest": "92298c8287cbda0eaad24b50145236bb29ff9a6473a6faac07deddd8ae97ff1b"
},
"door": {
"category": "objects",
"moji": "🚪",
"description": "door",
"unicodeVersion": "6.0",
- "digest": "984a9ca88852ebdb539e0c385d9c6ffe5010e9189bc372a3d00f5c8d44c8e6f5"
+ "digest": "4e3117984e88544efda68c78d0f90e7ba44533ba74beba28e7ea6b9718ca3225"
},
"doughnut": {
"category": "food",
"moji": "ðŸ©",
"description": "doughnut",
"unicodeVersion": "6.0",
- "digest": "27634587e6a53807baa32157bb06b0e115c8ad8aefebba7ebb0b65a084170e3a"
+ "digest": "f249df4adc65187348d3a57d110c672dbf9e5a4d7919db473aab71f24f85e9b6"
},
"dove": {
"category": "nature",
"moji": "🕊",
"description": "dove of peace",
"unicodeVersion": "7.0",
- "digest": "7c665f8594ffa53e72b01647e9d27360fb87d52d02fe9f20fc5fda08f9797dc3"
+ "digest": "66d335c04e2daef92ed0ee5979d6b072d99551e2950cdbc78882bf28269773f8"
},
"dragon": {
"category": "nature",
"moji": "ðŸ‰",
"description": "dragon",
"unicodeVersion": "6.0",
- "digest": "2abcb3d945d848e34ffc76203b29ef26df7458856166fffd155611f7bbe72652"
+ "digest": "460c7674101d32edf90b563329947c620c1e6bea9dfe2c81483e3313248d498c"
},
"dragon_face": {
"category": "nature",
"moji": "ðŸ²",
"description": "dragon face",
"unicodeVersion": "6.0",
- "digest": "0030548931b931e3b51f26cf660394aee36499e688ba83ce9cfccb635dcd4d54"
+ "digest": "8990c5f5a5cf7d94e4eafb7515e6367cfaeea6bd648c36d65dca1525b60d591c"
},
"dress": {
"category": "people",
"moji": "👗",
"description": "dress",
"unicodeVersion": "6.0",
- "digest": "96ceba928fb356f7c0ae99bf22552321f08a65d5f1c0340ab89641219ad366ad"
+ "digest": "9a1c024dd6f402a2764ad097eeb5656488df5bd60905e8deb04dc3f91ab890f4"
},
"dromedary_camel": {
"category": "nature",
"moji": "ðŸª",
"description": "dromedary camel",
"unicodeVersion": "6.0",
- "digest": "e06ef69c29f0fb12481727c0b4124e700572d3d7955e173279320f43f286518d"
+ "digest": "8401968c38aa200463e4f8dd68287cff7ccc0c2be93c425329ccc56bcfa1b672"
},
"drooling_face": {
"category": "people",
"moji": "🤤",
"description": "drooling face",
"unicodeVersion": "9.0",
- "digest": "5203cb05cd266d7a7c929ab40364ad68571d380d9c7ff93a8d6d55261abaa1ba"
+ "digest": "bed3de639ae375a5683806f5661cda66790f0e991912044ec6d8bcdf6ab56b55"
},
"droplet": {
"category": "nature",
"moji": "💧",
"description": "droplet",
"unicodeVersion": "6.0",
- "digest": "6475b4a4460a672c436a68f282ac97fb31e2934db4b80620063ee816159aa7c3"
+ "digest": "df3a38da24ffe4b245eaffe3a16c9f8d995a23f07030d4de3d7244a057939a5a"
},
"drum": {
"category": "activity",
"moji": "ðŸ¥",
"description": "drum with drumsticks",
"unicodeVersion": "9.0",
- "digest": "0d0639980b1a5dcbf1c3e7ef47263fb6543b871242c58452a8c2f642525d9dd8"
+ "digest": "ba6e2d42af351338819b48803792d5dd1597e831fbae53d2f2aaef275306c8ed"
},
"duck": {
"category": "nature",
"moji": "🦆",
"description": "duck",
"unicodeVersion": "9.0",
- "digest": "8f8373798a7727368b32328e7a9a349727a949e7391ddd243b6456141a4f7e94"
+ "digest": "41f179dcac9de4a0eb5335ce435176db90fb1e35c043a100a9be09ce1ce3fac0"
},
"dvd": {
"category": "objects",
"moji": "📀",
"description": "dvd",
"unicodeVersion": "6.0",
- "digest": "3b7903285d91277181c26fdc9df857761bbac509d352e320c2519ea3b132704f"
+ "digest": "06080cd1b46afcbdd854c06936389fc990aec029dd6909345861ff18d2275045"
},
"e-mail": {
"category": "objects",
"moji": "📧",
"description": "e-mail symbol",
"unicodeVersion": "6.0",
- "digest": "39b5a57a2376e4a1137e381be02a1775bd580e0371438f5297a401ea634f1830"
+ "digest": "7ca1119b9683e5e34185c9cbee9bcd59b6e24feae3a691826672c72d1d7401d1"
},
"eagle": {
"category": "nature",
"moji": "🦅",
"description": "eagle",
"unicodeVersion": "9.0",
- "digest": "b44fd4f61b83c5114358a272343ac9b0eabbc70847f739bbdbf8aae3ade5bc1d"
+ "digest": "996a7d29861f0ebd0762baeefccd1a8f7179b52bbb16e34e54787c9f6e959857"
},
"ear": {
"category": "people",
"moji": "👂",
"description": "ear",
"unicodeVersion": "6.0",
- "digest": "4fdeb5a46e69311ecfd09c5b45c9018c24b625e28475cca8fa516b086ef952f8"
+ "digest": "29f21bcb6963c709173aa895704029e48f233493ece1f0bb442705d90713e20e"
},
"ear_of_rice": {
"category": "nature",
"moji": "🌾",
"description": "ear of rice",
"unicodeVersion": "6.0",
- "digest": "2997c340c2b333d6ba9b73f94ff1a1881735fe0cc4f0c72d7719b305499fc425"
+ "digest": "9ea7efc5ebf3cea2cfd17ac2318a1ea0dd1519af6a60a95af33aabe1baa9042e"
},
"ear_tone1": {
"category": "people",
"moji": "👂ðŸ»",
"description": "ear tone 1",
"unicodeVersion": "8.0",
- "digest": "5ca759b8569a377a4e63e30d94b585b9f76d15348a8a0c1ba19fdc522790615e"
+ "digest": "5974f347c09ed99eb26af3b38ed5ff6d270920d5a5cf4bc2ca1e4ce1c6ca86d8"
},
"ear_tone2": {
"category": "people",
"moji": "👂ðŸ¼",
"description": "ear tone 2",
"unicodeVersion": "8.0",
- "digest": "12aafb3ef2cfcdc892b2877c2e24920620f0f77f850e12afbfe55eadce9e37df"
+ "digest": "10a215f5a1b0ca5c39abb4b2ba1c95fc541b21d03eb74b437a732bc155772b7f"
},
"ear_tone3": {
"category": "people",
"moji": "👂ðŸ½",
"description": "ear tone 3",
"unicodeVersion": "8.0",
- "digest": "f4d28d9f72cf116ac92d80061eb84c918d6523bf53b2ad526f5457aba487d527"
+ "digest": "339cb06fc200e7a2f175de0862fa0f69792725532002e26446a64b47bae4e7f0"
},
"ear_tone4": {
"category": "people",
"moji": "👂ðŸ¾",
"description": "ear tone 4",
"unicodeVersion": "8.0",
- "digest": "eaa9453670f7e3adc6ec6934ee70efc9bf60fe6c99c5804b7ba9e3804aec65de"
+ "digest": "4fc70d5c353ad59518bb3829b0c544a4092b59924bf6fe0dd573f8fee3d00c68"
},
"ear_tone5": {
"category": "people",
"moji": "👂ðŸ¿",
"description": "ear tone 5",
"unicodeVersion": "8.0",
- "digest": "54bd0782419489556b80e9e0d15b05df74757aa4e04ba565f45c20d3dd60e3f1"
+ "digest": "fa4d1bdab5ed8dc2e8976edb389571c21942cbdcf7ad51281b4e064a2b260a58"
},
"earth_africa": {
"category": "nature",
"moji": "ðŸŒ",
"description": "earth globe europe-africa",
"unicodeVersion": "6.0",
- "digest": "c691a6f591f5a07b268fd64efe113e81cec8d5963ad83ced2537422343ff7ecf"
+ "digest": "597e652a0be2d59d9f0190423767a763500c724ac53321c1cb6fc7fc0f9b9e8c"
},
"earth_americas": {
"category": "nature",
"moji": "🌎",
"description": "earth globe americas",
"unicodeVersion": "6.0",
- "digest": "a9c60cf8341ff59a9cc1a715b7144af734fcd28915a8e003a31ebf2abf9aedb1"
+ "digest": "b65c2ce55702e00286792a5007609bafdf1f184e2da5a8c6b949054534d5e8ad"
},
"earth_asia": {
"category": "nature",
"moji": "ðŸŒ",
"description": "earth globe asia-australia",
"unicodeVersion": "6.0",
- "digest": "ee2beb61fb8c87279161c5a8c4ad17bb71ce790123f8fa33522941d027e060a5"
+ "digest": "0334bd2fcfd55b0759c7bf900c7ef9a70fb3408ecb7762038e6b587d8226d204"
},
"egg": {
"category": "food",
"moji": "🥚",
"description": "egg",
"unicodeVersion": "9.0",
- "digest": "72b9c841af784e7cbccbbe48ba833df5cecdd284397c199cab079872e879d92f"
+ "digest": "97287d7b86252a2e3b8a112aaa1a3096f48ee930691e200470e6b35876d9d3c3"
},
"eggplant": {
"category": "food",
"moji": "ðŸ†",
"description": "aubergine",
"unicodeVersion": "6.0",
- "digest": "ec0a460e0cf0e615f51279677594a899672e1b4ecd9396e17a8cfa2a3efe5238"
+ "digest": "717719283180637a9929192d3af0459a871c144a5d6134cd1b31482cf065fc04"
},
"eight": {
"category": "symbols",
"moji": "8ï¸âƒ£",
"description": "keycap digit eight",
"unicodeVersion": "3.0",
- "digest": "57ff905033a32747690adba6486d12b09eb4d45de556f4e1ab6fb04e1fb861a8"
+ "digest": "0cc5beaaf4cf5efc0dc7450327ca264669641deebe0696997b578ca603eadd80"
},
"eight_pointed_black_star": {
"category": "symbols",
"moji": "✴",
"description": "eight pointed black star",
"unicodeVersion": "1.1",
- "digest": "7bf11f6e28591e3d0625296aaabf4ecb75c982e425abf3049339e93494acc17e"
+ "digest": "a06b0825d8288487c0a27cf858b1bdc3f9144683fe9ceb9608450f21dc278db8"
},
"eight_spoked_asterisk": {
"category": "symbols",
"moji": "✳",
"description": "eight spoked asterisk",
"unicodeVersion": "1.1",
- "digest": "bb0758e7cc0e357285937671a91489bd32ce9d248eecdcc9c275a53a66325b26"
+ "digest": "65fb63267575cb5637fed6ff99327cab54301baa39024ffae8fc8dd3db3516f9"
},
"eject": {
"category": "symbols",
"moji": "â",
"description": "eject symbol",
"unicodeVersion": "4.0",
- "digest": "eeb0cd23ead0c965e307de517a6805265f0c780c3e454e64bc4c1425dfe7548e"
+ "digest": "d12767c5ad910e8718971d315520934e86d607f3493a72a984545a4fee7a0b0c"
},
"electric_plug": {
"category": "objects",
"moji": "🔌",
"description": "electric plug",
"unicodeVersion": "6.0",
- "digest": "b10ce87af86fa4f4022572ceb5ecd73bea867347a86832a7ea248364b0aad8d0"
+ "digest": "78feabb40b541ad46e396f9508de72a52f0e4ca2f48717078eea100b3c125a24"
},
"elephant": {
"category": "nature",
"moji": "ðŸ˜",
"description": "elephant",
"unicodeVersion": "6.0",
- "digest": "b7750f4b013fbd28ac5330e1694ef4d3b4a9c6fc7b807879db0c24b035a16c29"
+ "digest": "c151ce8cf6aee435ed27099fac1d5e55501e643f69d7e39476fa6bcd73be9559"
},
"end": {
"category": "symbols",
"moji": "🔚",
"description": "end with leftwards arrow above",
"unicodeVersion": "6.0",
- "digest": "dd93aee6986eb637a8b58f234da47568b88525599f73246e322af030351997a2"
+ "digest": "b809c2bda4b924a3e2f43ae45a3bfc1a3e09d1750b1f17a19b82f66a2456038b"
},
"envelope": {
"category": "objects",
"moji": "✉",
"description": "envelope",
"unicodeVersion": "1.1",
- "digest": "f5a512022a2f5280f372ff39c22cbda815f698710ca66f8f8c4d08418f98ca78"
+ "digest": "ff00c491ba40989d83d6586ebb8e18e1507cdf55e056981803c3f77d0b246314"
},
"envelope_with_arrow": {
"category": "objects",
"moji": "📩",
"description": "envelope with downwards arrow above",
"unicodeVersion": "6.0",
- "digest": "f8643212e6a94f58ccf2bcedc54c5fda8ebeab274f4a8803f253de5f50ddb1d6"
+ "digest": "1af1da925637995928c8f83f7f5effee40db1f5a33f1cd7d626ff9ed408bfe19"
},
"euro": {
"category": "objects",
"moji": "💶",
"description": "banknote with euro sign",
"unicodeVersion": "6.0",
- "digest": "3af3e223e8f26468a94f6f5c17198432656e8d20b3bab31566c2b5a86e717df4"
+ "digest": "5c08342b52ba2417f1daf6c357107eddc3ed9e46ed82443665859dba944b0754"
},
"european_castle": {
"category": "travel",
"moji": "ðŸ°",
"description": "european castle",
"unicodeVersion": "6.0",
- "digest": "21082d0be7e3b2794e59ff0170da0cfe42a9b734cf02704603e3b52ff48202ba"
+ "digest": "183e813391199158b855481acefea11061b1722e51f2d2880486782b7639598d"
},
"european_post_office": {
"category": "travel",
"moji": "ðŸ¤",
"description": "european post office",
"unicodeVersion": "6.0",
- "digest": "02b4c7602939f0cb9cb2b4e05996bcdb6bd93cf8025c2ea02db8cbe13ca397d0"
+ "digest": "664ed0206445f1511bc2ecdfaf77c3df14dfd4e98fd73b58c6272e54e4117810"
},
"evergreen_tree": {
"category": "nature",
"moji": "🌲",
"description": "evergreen tree",
"unicodeVersion": "6.0",
- "digest": "74b226098e66c0a94a92e0f22b9d631736e12dca72c34182c9d0ba56aa593172"
+ "digest": "62ae1c4109a7458bcc754f89311fa37be31a0cdc63ee96f420482568bc74000c"
},
"exclamation": {
"category": "symbols",
"moji": "â—",
"description": "heavy exclamation mark symbol",
"unicodeVersion": "5.2",
- "digest": "45b87ae4593656d7da49ff5645fb6a2a18d582553295358da9f09f1ae8272445"
+ "digest": "8caf962a884874258642f7df358cd2693c85a111d96d0e72a26d7010ac595c61"
},
"expressionless": {
"category": "people",
"moji": "😑",
"description": "expressionless face",
"unicodeVersion": "6.1",
- "digest": "34e2a1c8121f4f0bc4ce33d226d8cc1a4ebf5260746df2b23e29eef24ee9372e"
+ "digest": "d818ca9cf4ba0c02756559d0e870517f298a88466b3e27002a86389942d89145"
},
"eye": {
"category": "people",
"moji": "ðŸ‘",
"description": "eye",
"unicodeVersion": "7.0",
- "digest": "79ecff79c2edee630e72725b54e67ee2e96d24ca03fef2954a56a09c0a2227f8"
+ "digest": "d48868ab77a09456b5f80553f08af363983ead45173759e3ff8a9ddf626effc2"
},
"eye_in_speech_bubble": {
"category": "symbols",
"moji": "ðŸ‘â€ðŸ—¨",
"description": "eye in speech bubble",
"unicodeVersion": "7.0",
- "digest": "c0050c026c2a3060723cab2df2603c1c7da7ed81faedb9ebe16cd89721928a55"
+ "digest": "4b4d96038c0883d99091f9718a3c1e9c096268a3bcead903a7f6551db2b779a8"
},
"eyeglasses": {
"category": "people",
"moji": "👓",
"description": "eyeglasses",
"unicodeVersion": "6.0",
- "digest": "d4a9585d6c43ef514a97c45c64607162e775a45544821f1470c6f8f25b93ab81"
+ "digest": "7f413b054509c24ee233b944df5a0b314ede67006d64f03df4a1c055a45245ee"
},
"eyes": {
"category": "people",
"moji": "👀",
"description": "eyes",
"unicodeVersion": "6.0",
- "digest": "1d5cae0b9b2e51e1de54295685d7f0c72ee794e2e6335a95b1d056c7e77260e8"
+ "digest": "659c9a040950bd320a33177be730c086cc6cf390d1b99d7cbf3e6bc7705f21bf"
},
"face_palm": {
"category": "people",
"moji": "🤦",
"description": "face palm",
"unicodeVersion": "9.0",
- "digest": "4ec873048b34b1bb34430724cf28e4bee6c0a9eee88ce39b9d1565047dc92420"
+ "digest": "60baca7855516c86883de6fd63f154b047d27325590c751089404e7287df56aa"
},
"face_palm_tone1": {
"category": "people",
"moji": "🤦ðŸ»",
"description": "face palm tone 1",
"unicodeVersion": "9.0",
- "digest": "e93ef92b4c01dbea6c400e708e23dd36da92ccfbf5eb4f177b3b20c3a46bdc19"
+ "digest": "f505ab5fc98f2e3bf5893f59484b90900e7c04c6f0467e0c89ccf99c5fd76715"
},
"face_palm_tone2": {
"category": "people",
"moji": "🤦ðŸ¼",
"description": "face palm tone 2",
"unicodeVersion": "9.0",
- "digest": "22c8bf9fd9fa2ed9dca7a6397ed00ba6cfe9aeef2b0fb7b516ee4dda0df050ea"
+ "digest": "9a3361cef95736983bbd54375ce9bf59c0fb1608f445da9dce79617cf05841bb"
},
"face_palm_tone3": {
"category": "people",
"moji": "🤦ðŸ½",
"description": "face palm tone 3",
"unicodeVersion": "9.0",
- "digest": "c0b8bb9d2423e6787b6bdf1ca5a13f52853e4f48a9a1af0f2d4af1364fff022e"
+ "digest": "d53cda9e9909988ec6ca4b9ee5735bac82ca53ee890f1c0eca50471ddbb044d3"
},
"face_palm_tone4": {
"category": "people",
"moji": "🤦ðŸ¾",
"description": "face palm tone 4",
"unicodeVersion": "9.0",
- "digest": "f522ab186adcbb4549ea2c03500cdd7a86add548e43ebf7a54d58cc24deea072"
+ "digest": "51d8cd0103356c08c4fe5cb6d68ac09688d08ea9253d6ccc09b4900730a89d80"
},
"face_palm_tone5": {
"category": "people",
"moji": "🤦ðŸ¿",
"description": "face palm tone 5",
"unicodeVersion": "9.0",
- "digest": "363507ae7178b5ec583635f47bcab10c897346f48b85d8759b1004c32cd8ad65"
+ "digest": "7c044e1662880c143f8f2b15eee0d5aeb2c6831ee70ff5dcc3796f2585f5f6b0"
},
"factory": {
"category": "travel",
"moji": "ðŸ­",
"description": "factory",
"unicodeVersion": "6.0",
- "digest": "c7aeb61ed8b0ac5c91d5197c73f1e2bb801921c22a76bb82c7659d990680dcb0"
+ "digest": "e71fc6d2fb903490f28565cbea6c3ca7384adc24aa0ba3ae481ca12255a015d3"
},
"fallen_leaf": {
"category": "nature",
"moji": "ðŸ‚",
"description": "fallen leaf",
"unicodeVersion": "6.0",
- "digest": "81fce04231d48db0e55f3697f930e9a7e3306bed5e35f1234e98c40a24ac5626"
+ "digest": "96c9e1139937dc4be942855f4b1f140cb06809c51a818d078f4680e0375ddc1c"
},
"family": {
"category": "people",
"moji": "👪",
"description": "family",
"unicodeVersion": "6.0",
- "digest": "06f2ce63768ffe43b3d9b2a9660b34d043f37b3c91610dd62343ba21df8ecbe5"
+ "digest": "363da6588b6816c4f9811c76fee6601e3111030a1ba86fea9464c60568144c50"
},
"family_mmb": {
"category": "people",
"moji": "👨â€ðŸ‘¨â€ðŸ‘¦",
"description": "family (man,man,boy)",
"unicodeVersion": "6.0",
- "digest": "41a18405be796699a7eb7c36ab6f7d898e322749997f45387377acf5bb16a50f"
+ "digest": "4464331734f8afbc33ebd38552ea1452813dc9e0295e315e4bcadf4876444474"
},
"family_mmbb": {
"category": "people",
"moji": "👨â€ðŸ‘¨â€ðŸ‘¦â€ðŸ‘¦",
"description": "family (man,man,boy,boy)",
"unicodeVersion": "6.0",
- "digest": "87255d1d18c6971c8c083c818e598424c1bd717eed892478b7e9516639dbfb45"
+ "digest": "ad976771f346f8c48d0a0077ee8ec427048937814a03a8691d422dd664991734"
},
"family_mmg": {
"category": "people",
"moji": "👨â€ðŸ‘¨â€ðŸ‘§",
"description": "family (man,man,girl)",
"unicodeVersion": "6.0",
- "digest": "a132b1b8f10b318d8e23aee15dab4caa14528aeb3c89966d4bcc25fb54af72ad"
+ "digest": "961e428e8dfccab9575c6add7fc1523643caa2da47890b2baaa265c5f0ea0d8b"
},
"family_mmgb": {
"category": "people",
"moji": "👨â€ðŸ‘¨â€ðŸ‘§â€ðŸ‘¦",
"description": "family (man,man,girl,boy)",
"unicodeVersion": "6.0",
- "digest": "eb2bc1966df406aaf38ce5a58db9324162799cdacf31f74f40e6384807a8efc2"
+ "digest": "7240b99930a16295b3396d7183ecad125423d019b08f11746969c3939005ceff"
},
"family_mmgg": {
"category": "people",
"moji": "👨â€ðŸ‘¨â€ðŸ‘§â€ðŸ‘§",
"description": "family (man,man,girl,girl)",
"unicodeVersion": "6.0",
- "digest": "24f3d60f98fbd6b687f7cacfb629390b90509a754036e5439ae5294759c0606b"
+ "digest": "2f2d726791f01c880df79431dc9472724f61d621b8b17344a9839db6f65b8cd7"
},
"family_mwbb": {
"category": "people",
"moji": "👨â€ðŸ‘©â€ðŸ‘¦â€ðŸ‘¦",
"description": "family (man,woman,boy,boy)",
"unicodeVersion": "6.0",
- "digest": "2f77692bcb9275c4df501b64a18401dcaf8c68b21f26fbdad59b1feab0c98fd1"
+ "digest": "e0056e604ec4d411ebb4aefc079f47efb11bf7db4c3ebf9d17759f40075a19a5"
},
"family_mwg": {
"category": "people",
"moji": "👨â€ðŸ‘©â€ðŸ‘§",
"description": "family (man,woman,girl)",
"unicodeVersion": "6.0",
- "digest": "1a976d13127665d9386cebfdb24e5572dc499bda484c0ee05585886edc616130"
+ "digest": "3c256c9982e40db556a4667e6a666c06f6088249b5cc260e92bd443cc5d85b1c"
},
"family_mwgb": {
"category": "people",
"moji": "👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦",
"description": "family (man,woman,girl,boy)",
"unicodeVersion": "6.0",
- "digest": "960ec2cbac13ef208e73644cd36711b83e6c070c36950f834f3669812839b7f8"
+ "digest": "09481d128ece6416b169b99a9b770a1c72f662adde86fa6c214a1f979e98f8bd"
},
"family_mwgg": {
"category": "people",
"moji": "👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘§",
"description": "family (man,woman,girl,girl)",
"unicodeVersion": "6.0",
- "digest": "8353b03dfa5c24aba75a0abdfdac01603f593819d54b4c7f2f88aafb31da0c6a"
+ "digest": "2e9670f98d310c15491a66a4108773cc994401cc864923c0fc1c61123b99c1b5"
},
"family_wwb": {
"category": "people",
"moji": "👩â€ðŸ‘©â€ðŸ‘¦",
"description": "family (woman,woman,boy)",
"unicodeVersion": "6.0",
- "digest": "07a5dd397718c553573689f6512f386729c13a12d5dc78be47c06405769cd98a"
+ "digest": "df970eeb8fe917398b9dfd68b181ec6cfe1f7e981af2f67e5d8c96a228aa8147"
},
"family_wwbb": {
"category": "people",
"moji": "👩â€ðŸ‘©â€ðŸ‘¦â€ðŸ‘¦",
"description": "family (woman,woman,boy,boy)",
"unicodeVersion": "6.0",
- "digest": "b627f460f1da0d47b0b662402940b2b77c9538d380d05436dfca4b456c50c939"
+ "digest": "d6e262911da6a7fc47d49642666f5068e597976c1760d25758114cad16b1ac1c"
},
"family_wwg": {
"category": "people",
"moji": "👩â€ðŸ‘©â€ðŸ‘§",
"description": "family (woman,woman,girl)",
"unicodeVersion": "6.0",
- "digest": "2d6f373bed53f1028f0fbe9caf036465a351f37b9e00fca7d722cc5a1984f251"
+ "digest": "1f64c8a10f813344c4d10ab78fb55c2a2c221101e8645c6b6dcc0c8ca40c029c"
},
"family_wwgb": {
"category": "people",
"moji": "👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦",
"description": "family (woman,woman,girl,boy)",
"unicodeVersion": "6.0",
- "digest": "72be5c85e1621f73d6794edd6e428febdb366b9e4c816f7829897fd1ab34642b"
+ "digest": "d0962105cff6755305a08c0a0f748cb4fdfe3f78c9add25640dac05a8e4200e6"
},
"family_wwgg": {
"category": "people",
"moji": "👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘§",
"description": "family (woman,woman,girl,girl)",
"unicodeVersion": "6.0",
- "digest": "c39e0916069460d2d9741bddf58e76f5d6a09254cba0eeb262345adf8630bc32"
+ "digest": "9733e9a03cccda66612c0274842e514092d1816dba914f337ba422e988225352"
},
"fast_forward": {
"category": "symbols",
"moji": "â©",
"description": "black right-pointing double triangle",
"unicodeVersion": "6.0",
- "digest": "e7d2d8085cfd406c2b096e8dd147dd3722290a5727b1f7df185989526a2335ec"
+ "digest": "4ad792e67e07120968468561f20df83f39fa5800b8212a64e76fc36cf27464c3"
},
"fax": {
"category": "objects",
"moji": "📠",
"description": "fax machine",
"unicodeVersion": "6.0",
- "digest": "ff85ffa440c5379c9b138ebe2d7912d6098da3b37a051b80442d5557b7f993b0"
+ "digest": "cf7823d54b57edbf46384c7833efc4ce9ddef29786d74a89a8af1e8ed2e7d599"
},
"fearful": {
"category": "people",
"moji": "😨",
"description": "fearful face",
"unicodeVersion": "6.0",
- "digest": "b72bdf7d075d5c4e38bbd8512fb45fda2e85c9c8732a47e67575ae9f2ed4c5df"
+ "digest": "ce0c48c3ede7231acd645ffa0fe3dfec012e6f88a30431c44e3b816063ac42b4"
},
"feet": {
"category": "nature",
"moji": "ðŸ¾",
"description": "paw prints",
"unicodeVersion": "6.0",
- "digest": "45aca538d3a9831a0c7de491e5656c17705c07b8f4ac8e85254656b608976016"
+ "digest": "cb4b59f2c5df407bae3d02b638721b7f47b685d4e03f7ddb8d1fedaae9e2179a"
},
"fencer": {
"category": "activity",
"moji": "🤺",
"description": "fencer",
"unicodeVersion": "9.0",
- "digest": "5db00fa456af9f6c7cb88d300579dd63e426bcb97ad25486b664aff25c688e21"
+ "digest": "8fe2320e2bf8ae87bdd7b2cb519146fba1cc5f1df8c426f83a780544bfec3785"
},
"ferris_wheel": {
"category": "travel",
"moji": "🎡",
"description": "ferris wheel",
"unicodeVersion": "6.0",
- "digest": "24b4551b7b79a2a5fd73de61542f2b444f896a52030c5f29791c8fcfcc28b95c"
+ "digest": "a2eabc2a9f677373e013a100fc0f3b1e55d9aab24fc77056ee2bfef7dfc19add"
},
"ferry": {
"category": "travel",
"moji": "â›´",
"description": "ferry",
"unicodeVersion": "5.2",
- "digest": "5002a72af2e3c4cef9a36ad5987aeed7d99f96bfd13e56f78957315ec7e749a3"
+ "digest": "977c47292fd51ecd5d558a309405b15fc64b9b8edbedf95d8af30fa40636e6d0"
},
"field_hockey": {
"category": "activity",
"moji": "ðŸ‘",
"description": "field hockey stick and ball",
"unicodeVersion": "8.0",
- "digest": "4ee091d96161ba719ab8fd6f2b03f96d902a6f22cffe0563b930618bb8ac2b67"
+ "digest": "8608cd6944c9d3791e5c0b3111f7c5ca6155f64552ae9ab3e2f93514d053e042"
},
"file_cabinet": {
"category": "objects",
"moji": "🗄",
"description": "file cabinet",
"unicodeVersion": "7.0",
- "digest": "92914147bf93e6d64271ff99d217a18a9850a367d08a5f9f458ecf9311a5bbe9"
+ "digest": "29cf5c9587eb08a6736e37a6c7e01ad7e1453dd770c02c743604c2abf314d90f"
},
"file_folder": {
"category": "objects",
"moji": "ðŸ“",
"description": "file folder",
"unicodeVersion": "6.0",
- "digest": "62a42a929267cfbfdb795ead381c9657c343458bc5fca95ea8a0ab892c61d4f6"
+ "digest": "25f9840f4a2bc80558ef9ed231f88a7031bc4b0aad087a7be9748fb006a37288"
},
"film_frames": {
"category": "objects",
"moji": "🎞",
"description": "film frames",
"unicodeVersion": "7.0",
- "digest": "4da212148cadb9c4ea91e60d2d8316e38cea99ef4f14afc023711dd7c54ade5a"
+ "digest": "ddc2c8bf00765b8a91bff22a06dba1cef2a78d89afb9515e55dc417cfcba570e"
},
"fingers_crossed": {
"category": "people",
"moji": "🤞",
"description": "hand with first and index finger crossed",
"unicodeVersion": "9.0",
- "digest": "a5c797ead191b9712e185083266b455cdf09f6a34c10f8c51aa145e6073427e1"
+ "digest": "fee443087ed38c26487edd1bd8866ce399ef6a8eb98342fc0110bd2f77835253"
},
"fingers_crossed_tone1": {
"category": "people",
"moji": "🤞ðŸ»",
"description": "hand with index and middle fingers crossed tone 1",
"unicodeVersion": "9.0",
- "digest": "db56d47bf887f2d8459a3aaba23f15c0087234ae5a54125052e7046e034a4988"
+ "digest": "b91c28f9644867ff41f22c1f80b6c9ee120413ae62f30772c9853d76987fed05"
},
"fingers_crossed_tone2": {
"category": "people",
"moji": "🤞ðŸ¼",
"description": "hand with index and middle fingers crossed tone 2",
"unicodeVersion": "9.0",
- "digest": "19f1bcca3991db7ed2037278c0baab6cd7f12aeaf2e0074de402c4d9e45c1899"
+ "digest": "9d4ea025f1daa063d14e8d26c3c94a0c86379b214ac8125acc404820fd1ddbb5"
},
"fingers_crossed_tone3": {
"category": "people",
"moji": "🤞ðŸ½",
"description": "hand with index and middle fingers crossed tone 3",
"unicodeVersion": "9.0",
- "digest": "895a3314f6a310f31f7e728bcca20ff834fbfac62ce00e27e3ea5ad0dfc1ba35"
+ "digest": "23ee099706ec89b6bbc6f2911f9f1571822192d913516279a5318d92d01bc754"
},
"fingers_crossed_tone4": {
"category": "people",
"moji": "🤞ðŸ¾",
"description": "hand with index and middle fingers crossed tone 4",
"unicodeVersion": "9.0",
- "digest": "fcb5c4de2001d23a5df1b8702624d134b7f94e93e2dcc8adf6c1033c77722b0e"
+ "digest": "cda52831530605511b13a4953136dd5f36fca1fbf3d11ac261caac862086aff9"
},
"fingers_crossed_tone5": {
"category": "people",
"moji": "🤞ðŸ¿",
"description": "hand with index and middle fingers crossed tone 5",
"unicodeVersion": "9.0",
- "digest": "50132c78d530b048c21be4e788b446872a79b3b3a91009db12f4021c44c8469d"
+ "digest": "b49c1b15808715547f6f04113cf1631f4d79f8c1fec5f9ecdeea60284f9b4dad"
},
"fire": {
"category": "nature",
"moji": "🔥",
"description": "fire",
"unicodeVersion": "6.0",
- "digest": "b3e67c913903d900f5e50e7e7e4d7e9370bb6ceedfbee548be39e4c9e4b69416"
+ "digest": "37ab0faba2cb2a665775cdde7aaf4b4a0dfdd21030b57a613ddc9cb91883d7e4"
},
"fire_engine": {
"category": "travel",
"moji": "🚒",
"description": "fire engine",
"unicodeVersion": "6.0",
- "digest": "c3a518f27d625e3b62dffa227eb82764bf0a147f10ec0e7f4f43f3f96751af20"
+ "digest": "c81e1df702689c4c3895862e2da1092f30f5c415c0e9726f0b2c5c42ed9660ce"
},
"fireworks": {
"category": "travel",
"moji": "🎆",
"description": "fireworks",
"unicodeVersion": "6.0",
- "digest": "b62ae08a00c0cc6eba8f9666c8fd9946ce57c3cfc01fe99542a8690a4a566a65"
+ "digest": "6242b48df4b30753b154ec6d5f3883646fa42b55a629a7a1273d290e97df8a41"
},
"first_place": {
"category": "activity",
"moji": "🥇",
"description": "first place medal",
"unicodeVersion": "9.0",
- "digest": "e3de5d9f14f05544dbee5965cc2baa20e7b417a488c8a18598979038860fd901"
+ "digest": "d250c1890f341665d689d705c13fc4c5448d870d193b8b3405832e2fd92f5385"
},
"first_quarter_moon": {
"category": "nature",
"moji": "🌓",
"description": "first quarter moon symbol",
"unicodeVersion": "6.0",
- "digest": "a207ce93084448622a4a5c49c85c566a9fda6be7337c86a013eeb713fe47fd29"
+ "digest": "8bcc5d70d27f52098378fc800041429f726323ee840276c7901f4b525778a8f2"
},
"first_quarter_moon_with_face": {
"category": "nature",
"moji": "🌛",
"description": "first quarter moon with face",
"unicodeVersion": "6.0",
- "digest": "1d1f54a5075f2311bcc017c44898b9d8c58edc13b298d58c238fff9ab8ee2ef3"
+ "digest": "a878335d845f1ec830614307fe3d48e346730ec62d3334687aaef43d4a9033e6"
},
"fish": {
"category": "nature",
"moji": "ðŸŸ",
"description": "fish",
"unicodeVersion": "6.0",
- "digest": "8f62f08fbeaf39694c19816b5c7d4f292017fe5bf9f8dd7e40f1630f5f83b28b"
+ "digest": "036332286b852c6dd8c672f1540a4b4c5082885555f60a7d0f93b82c2acdc0f5"
},
"fish_cake": {
"category": "food",
"moji": "ðŸ¥",
"description": "fish cake with swirl design",
"unicodeVersion": "6.0",
- "digest": "5a6ca2100c8830927b22afa6f1d2fc821f5692cd23507fe5a776f6e085cbbfb2"
+ "digest": "2289ec22dc4e1cb1e143c56809f4d4f920e221f11237533cee95472a30985068"
},
"fishing_pole_and_fish": {
"category": "activity",
"moji": "🎣",
"description": "fishing pole and fish",
"unicodeVersion": "6.0",
- "digest": "f8fb84eccceec88321b0a2a46f732ecfc378f787c19c27ac1327735f1ca9a48b"
+ "digest": "539df418ee29c240216b28aa1af12feefe9273de148a80289c2a512785d98aee"
},
"fist": {
"category": "people",
"moji": "✊",
"description": "raised fist",
"unicodeVersion": "6.0",
- "digest": "557f96d85615b8d78436bc67266115bfc8556c97c14f7909dfda1cf134e8344f"
+ "digest": "5902870e6121df3f316a3c5f62b3e0a32679f3fca37fda165267d15001fbcfe4"
},
"fist_tone1": {
"category": "people",
"moji": "✊ðŸ»",
"description": "raised fist tone 1",
"unicodeVersion": "8.0",
- "digest": "6c1b946f9e01abc39b5085e24e8b6077fc0e34188e8daa30c6a3adddd387413e"
+ "digest": "9c4e0289af6fd5a9fdb5b77396d37d93f97bf0f302c20a980dc4663121b31eb9"
},
"fist_tone2": {
"category": "people",
"moji": "✊ðŸ¼",
"description": "raised fist tone 2",
"unicodeVersion": "8.0",
- "digest": "e9b9e1ec638dca4d5e1519bca7338f58cce2f2a282ee4c3581e8643166fc415f"
+ "digest": "6784ddda1bef3dee456860266c9d408efddbfd50566115f674091ae338d8a8bd"
},
"fist_tone3": {
"category": "people",
"moji": "✊ðŸ½",
"description": "raised fist tone 3",
"unicodeVersion": "8.0",
- "digest": "8c14d24055c143960b3d2a27fe23c55d2d3ac5f84f87e4e876616235e8698c7f"
+ "digest": "0355b2238cabd2edcedbb47b548db789bcb1ccbd1fc56090e2b5976db0f792ef"
},
"fist_tone4": {
"category": "people",
"moji": "✊ðŸ¾",
"description": "raised fist tone 4",
"unicodeVersion": "8.0",
- "digest": "923f034f481e952e6e5d1664588f99f79bd5416d4197b0ade6621f2669ce5765"
+ "digest": "2e29b3c36c7260c6f327941b4345be2642f034f36c6b5cb9ffcff0ee7a6140b3"
},
"fist_tone5": {
"category": "people",
"moji": "✊ðŸ¿",
"description": "raised fist tone 5",
"unicodeVersion": "8.0",
- "digest": "d691d2902216080916a29047e07d7a5bf2aed07e062067ca9d01cbf6fdf48c8d"
+ "digest": "3d69c0e6b12f4e6ec6b9e6a3b2974b880c4017d92bfe77bf5e14e8cc713d1c8c"
},
"five": {
"category": "symbols",
"moji": "5ï¸âƒ£",
"description": "keycap digit five",
"unicodeVersion": "3.0",
- "digest": "8f03f62fdbf744ae49c8a60fbf715ebfccbd6b62d91148e0923907006f3c2726"
+ "digest": "f763042ce9ec1e56342edf89b643c68019b103e0b1c812e130289d2534d6d914"
},
"flag_ac": {
"category": "flags",
"moji": "🇦🇨",
"description": "ascension",
"unicodeVersion": "6.0",
- "digest": "2e5c08535dc8ea96422d56a36b4fffc0b3bd2a13f2ab0d8dbd0e3a29bf3fc40c"
+ "digest": "49218bb103f3e0786d7e233c47aaabbb8c1ff98fc67dda9b4fd33a514af38ad9"
},
"flag_ad": {
"category": "flags",
"moji": "🇦🇩",
"description": "andorra",
"unicodeVersion": "6.0",
- "digest": "184fdcf790b8e2fd851b2b2b32f8636c595dd289734d12dc01ae4aa177e2043a"
+ "digest": "b51dc5658f05649dd6f75dd7f6c487bd67be41bd1d41aa5e251a7d04e0dd2ebe"
},
"flag_ae": {
"category": "flags",
"moji": "🇦🇪",
"description": "the united arab emirates",
"unicodeVersion": "6.0",
- "digest": "4a3257a9ce118e97567e76280f24d60fb555f1bada2eb26a2442a47f9398d21e"
+ "digest": "a3cd4c4da5af6583b1d9d3d9d3b29d8698848208ee18b00214d26e57f64d380b"
},
"flag_af": {
"category": "flags",
"moji": "🇦🇫",
"description": "afghanistan",
"unicodeVersion": "6.0",
- "digest": "0f6c719cac7ab3140694f6b580787ecdbf503e38f16de7ec5803f7d06a088ec3"
+ "digest": "a36a1087f2ec9f8770d33b9d4b356b92ee80980db68abae3124503884d5f1dd8"
},
"flag_ag": {
"category": "flags",
"moji": "🇦🇬",
"description": "antigua and barbuda",
"unicodeVersion": "6.0",
- "digest": "92bf5a0e74564739862e9ba79331ffa656b7bae2ace0fc8dfd288984e4d510d4"
+ "digest": "aab677f44cbfa303bc3eee5fb53f8e0dcce01e77a8b59b78ad6b409465fe0b9a"
},
"flag_ai": {
"category": "flags",
"moji": "🇦🇮",
"description": "anguilla",
"unicodeVersion": "6.0",
- "digest": "aeaadc7ffafd8a1e01fdabc69d35f725d5f737b4c284a36191d96729f4e66e8f"
+ "digest": "94b449a49ee58ea838e8b67a5183d7ea85efd06eee116672d29a8c184ca79b18"
},
"flag_al": {
"category": "flags",
"moji": "🇦🇱",
"description": "albania",
"unicodeVersion": "6.0",
- "digest": "5ce7866d214d18c5f3438d480d14e77d104c4de679f0fdfca8cf0a44ce48eeea"
+ "digest": "eb1bff57c565f3887a7e3eac736f3697cefd4a503dfb5e426d2c3d2f4e83cbed"
},
"flag_am": {
"category": "flags",
"moji": "🇦🇲",
"description": "armenia",
"unicodeVersion": "6.0",
- "digest": "b40f5705f0cf9ef0fa7ffff0b371c4099319001ce79f894c317912f4dc5de4c8"
+ "digest": "a31dc825f977821693acefcc58eb036b95487cbd5decfe29476ccf0582dc60fb"
},
"flag_ao": {
"category": "flags",
"moji": "🇦🇴",
"description": "angola",
"unicodeVersion": "6.0",
- "digest": "eab6fbc1824d6e3cd152e8ec1d82e1beaebe02b53b35c6f7a883b8548af02f3a"
+ "digest": "af4f7a1cec9b20ca67acc462321015b02f1625d4bfe4a3bde60d2d1b5fe31eab"
},
"flag_aq": {
"category": "flags",
"moji": "🇦🇶",
"description": "antarctica",
"unicodeVersion": "6.0",
- "digest": "367f6677a683a5f0e7248ab3a8f46d06ba146a0fd75004c70bac0e913147cdaa"
+ "digest": "8a57229626474007eedd28e401b9b17fd2362593d5d359e328a7d16b32e4164d"
},
"flag_ar": {
"category": "flags",
"moji": "🇦🇷",
"description": "argentina",
"unicodeVersion": "6.0",
- "digest": "f0dc466b3216957f2679d7208c2d7cf288448b0739b9270a7c5fa717577bdf25"
+ "digest": "11d850d4a4d3c2667570eda376aaec15999b6c45c890706962f6eebbfcf11d44"
},
"flag_as": {
"category": "flags",
"moji": "🇦🇸",
"description": "american samoa",
"unicodeVersion": "6.0",
- "digest": "fcb7a865c7763c63b23485cc27207b99a3a8492e83d5b5ee2df259a9f68f77d6"
+ "digest": "7302d679108897778ac84a2334ac193df9c9dcfe6946f6d4c8ab8e881a698ae6"
},
"flag_at": {
"category": "flags",
"moji": "🇦🇹",
"description": "austria",
"unicodeVersion": "6.0",
- "digest": "1d3d58e9abc034f9a093a94716eddf9811d54dfaf27969fd322b3809fac70217"
+ "digest": "0f7c31a5fdcd202811dc10d319016313cebab4c2b5455765ef3cee331991ad38"
},
"flag_au": {
"category": "flags",
"moji": "🇦🇺",
"description": "australia",
"unicodeVersion": "6.0",
- "digest": "789563b64c71a5ad49078d335dc166ef614edb56d1e401885d32fb191c198fbd"
+ "digest": "a0f178063d1c9628914dcece5ccd205b1293536903f4bf12192e15835ea39c8d"
},
"flag_aw": {
"category": "flags",
"moji": "🇦🇼",
"description": "aruba",
"unicodeVersion": "6.0",
- "digest": "1504dc3fd8457b44fdf75c15e136dc46a13e8342d1f98949728cdc1238843e0c"
+ "digest": "fd417c5cffef102ad3a8dc43364d2924edc9178e82c41d1d0584aece61507716"
},
"flag_ax": {
"category": "flags",
"moji": "🇦🇽",
"description": "Ã¥land islands",
"unicodeVersion": "6.0",
- "digest": "e96fa3525f3be25016a4cf8428261735f3ed5fc9fe5b827b461746a3f08877bf"
+ "digest": "84db67b31fc150410cceb2ff709f74f64252a9421a0cb6763c0ed836e9a6ab84"
},
"flag_az": {
"category": "flags",
"moji": "🇦🇿",
"description": "azerbaijan",
"unicodeVersion": "6.0",
- "digest": "12c366ac2c38b91314fb29056e09fa6e7417766cebde3045859cdb127549f4a2"
+ "digest": "5250b64a249ad421e5e596378e1911892ff78dba51c2765431b88a2b6bdfa78e"
},
"flag_ba": {
"category": "flags",
"moji": "🇧🇦",
"description": "bosnia and herzegovina",
"unicodeVersion": "6.0",
- "digest": "0819ea3901510ac20c7f10e67e5f6c818210f17a362c1d12e299c41feb07f828"
+ "digest": "faa5d072490d703f3673a58d2773518868c9eb59c841b85a1735d0dd387f083f"
},
"flag_bb": {
"category": "flags",
"moji": "🇧🇧",
"description": "barbados",
"unicodeVersion": "6.0",
- "digest": "cf32778a272ed6cbc8e783b59befd9b204009c69c61a425e148d867808b7fab9"
+ "digest": "fef79aec7009052da4296b6a176e3547d9a8a188b013858863c231991dd965b8"
},
"flag_bd": {
"category": "flags",
"moji": "🇧🇩",
"description": "bangladesh",
"unicodeVersion": "6.0",
- "digest": "e6ed186644a874588e879513aec92f8107220dcdd14c766dee61f266ce045665"
+ "digest": "3ba7cdcffef867e32ae7fda72842ee4340f394f6de3b9ce37d12aa800526f570"
},
"flag_be": {
"category": "flags",
"moji": "🇧🇪",
"description": "belgium",
"unicodeVersion": "6.0",
- "digest": "4d941011d15d9f6e755d6f7694884758baf17ac0691bf5d63700f8d6dbcdb948"
+ "digest": "1aae2a532f94b336f29962ce4a07e575f7f8f4a4d1381d90eefb0ced86406a35"
},
"flag_bf": {
"category": "flags",
"moji": "🇧🇫",
"description": "burkina faso",
"unicodeVersion": "6.0",
- "digest": "fcc57dbda9a86f725f558b6c6309484c97e65f1644aae4f9fb5e642681f6c2e0"
+ "digest": "12198ae4eeaff20e57223cb832fa2d27558eaeebde9c04a4a73bb2700eecad1d"
},
"flag_bg": {
"category": "flags",
"moji": "🇧🇬",
"description": "bulgaria",
"unicodeVersion": "6.0",
- "digest": "816c47ed96c36c90723da150645902ea8ba18b44757fdd776c7b3542cfecfb18"
+ "digest": "2b848714c60a9fb3d5128740f97fa1a5fc67e56fcd76f5be8fadaad7f9fc89a8"
},
"flag_bh": {
"category": "flags",
"moji": "🇧🇭",
"description": "bahrain",
"unicodeVersion": "6.0",
- "digest": "2cd5c21775a6e73f59d08c9ee0cedf4e8241e562eab939573501d47681987737"
+ "digest": "f95a8ae0d272bfaa26eaae82046afb87075e705ea595bfb0815ccf6177f932b8"
},
"flag_bi": {
"category": "flags",
"moji": "🇧🇮",
"description": "burundi",
"unicodeVersion": "6.0",
- "digest": "2da82acbec5518360633c1b0b56d55a79b67237f67d92af5e5cd75a2f3bd550e"
+ "digest": "78392dfbf6711a35722e50985865d7699b1bf2f9df4834461df5ffc8e6778485"
},
"flag_bj": {
"category": "flags",
"moji": "🇧🇯",
"description": "benin",
"unicodeVersion": "6.0",
- "digest": "8fe8c34651eb4e28ab395261a5b72b6f37579535ed676d15de131914e19c0436"
+ "digest": "0cb9ba7d57c62cf149a93c0775eddc2c2d61fcf10e986b528bcee3441b62c3ae"
},
"flag_bl": {
"category": "flags",
"moji": "🇧🇱",
"description": "saint barthélemy",
"unicodeVersion": "6.0",
- "digest": "d37f2a215ee7ef5b5ab62d2a0c87e90553b17c6ee310f803a71e9fd72db880e7"
+ "digest": "0d322e0289bab47daf300db3c0b88dc348548f62adb27abb20b972e409e2c0c6"
},
"flag_black": {
"category": "objects",
"moji": "ðŸ´",
"description": "waving black flag",
- "unicodeVersion": "6.0",
- "digest": "3740bfc9bcb3b46b697b8b7c47ab2c3e95eca9dbcba12f2bf98a01302704f203"
+ "unicodeVersion": "7.0",
+ "digest": "f147434c7baea64732877fa3d6e821071f31dad1ac50dcd77a991bd1c9052611"
},
"flag_bm": {
"category": "flags",
"moji": "🇧🇲",
"description": "bermuda",
"unicodeVersion": "6.0",
- "digest": "ccd21655573f3c955d616c5c7b1eac2be1d4772ff611648d6713ba55d9e4aa9b"
+ "digest": "4043cd7d92ea6a43b6f853a4313a6cb165b4812d00036ce7b9cac8952965880e"
},
"flag_bn": {
"category": "flags",
"moji": "🇧🇳",
"description": "brunei",
"unicodeVersion": "6.0",
- "digest": "54330c3d7a37392e69098c213fd8c78f3faab4e7e5909c039188110422514228"
+ "digest": "fd617c6d51568f0f9cc00b8f55f281be7174620955e200182da7e3b1817db0bf"
},
"flag_bo": {
"category": "flags",
"moji": "🇧🇴",
"description": "bolivia",
"unicodeVersion": "6.0",
- "digest": "32aff973b26f4f91ca19dddd7861b564da43cfbee87603d8c004f1111342366c"
+ "digest": "4d9ed61c97bf894a75333c04c227cd91f24c4df12bc3ae2cfe79c6ae61f173a7"
},
"flag_bq": {
"category": "flags",
"moji": "🇧🇶",
"description": "caribbean netherlands",
"unicodeVersion": "6.0",
- "digest": "b1ebc959c43f706ca430d8633d9efaa9c60133871506b5f030b730cfb4c19e6f"
+ "digest": "9ca29fbfb5ec4603f851bec8ba1a31801e83f869bc8a85a3385f15e6d9679358"
},
"flag_br": {
"category": "flags",
"moji": "🇧🇷",
"description": "brazil",
"unicodeVersion": "6.0",
- "digest": "64fb154d71fa34ff4838bc405f3e58a4102cf0cb49ca4b06fc3c7a6bf39671f0"
+ "digest": "472324ced70d2af3eb6a9337afa12460da53cb19e2c3cf9fbc0425db8885c510"
},
"flag_bs": {
"category": "flags",
"moji": "🇧🇸",
"description": "the bahamas",
"unicodeVersion": "6.0",
- "digest": "c4b07e5f652ab06ece95d3774ce8b1399a935f8a28d440cb13cc8bd0b9728ed5"
+ "digest": "48a0ea0bece279b7a9fbbb9439807de966f0b820bbb8da0d1a3c8dda3fec311a"
},
"flag_bt": {
"category": "flags",
"moji": "🇧🇹",
"description": "bhutan",
"unicodeVersion": "6.0",
- "digest": "901ddbd999dd89a87c1e1208b1470cb4e604a9bc023d0cbcdee64e1bc54079ba"
+ "digest": "d4edd71953053c95b9aa7f5cd5bf671a9984c149809e81ba4456d242ac2c0fee"
},
"flag_bv": {
"category": "flags",
"moji": "🇧🇻",
"description": "bouvet island",
"unicodeVersion": "6.0",
- "digest": "bbf6daa6174c6fbbbf541c8274f31b6757c3a16007c2687015ea041fd1e2c6b6"
+ "digest": "473f79dc252e5029ce80980408fce347e31d1902ebf278ddc5d30006e8e83d45"
},
"flag_bw": {
"category": "flags",
"moji": "🇧🇼",
"description": "botswana",
"unicodeVersion": "6.0",
- "digest": "05aa351bc04dc0fe2669441ab500e000d48b1f0d7ad9e885c7abfb898aa0eb3f"
+ "digest": "5542b507be1b059c7befd338e7672c44a0b720cf2cb626ed9e2cd276e532ef64"
},
"flag_by": {
"category": "flags",
"moji": "🇧🇾",
"description": "belarus",
"unicodeVersion": "6.0",
- "digest": "6eda3b87336ecf0aae4963986d86b916a055d8268c70520303288f235a93b0d9"
+ "digest": "ed5bf970c40e08a06e73e250a9b8209abb2bcaa4f7e99f11fd8b8d00581f7c3a"
},
"flag_bz": {
"category": "flags",
"moji": "🇧🇿",
"description": "belize",
"unicodeVersion": "6.0",
- "digest": "d76ed945b1408558a30a99b8eed6712de968fc49fba1721b5660b8f48087e45a"
+ "digest": "28eb6050ad7daac7ff547ba920532a0f588404694598afdc36a19442f9a7c1fe"
},
"flag_ca": {
"category": "flags",
"moji": "🇨🇦",
"description": "canada",
"unicodeVersion": "6.0",
- "digest": "2fd036047d89751c05de5577909b58347883bc89c3b7d90bec28ad4770a98ecd"
+ "digest": "fb86372252d96dc0165c943fb74159dc19309ca47059861c46a9ff0bc3b1fe08"
},
"flag_cc": {
"category": "flags",
"moji": "🇨🇨",
"description": "cocos (keeling) islands",
"unicodeVersion": "6.0",
- "digest": "837ba181a01c71f05d438d205efaaee99f93b2370c97b13e6132f99860323e36"
+ "digest": "4bbd89e474ffc7981159d5050f3b3cd11a19261536bd6905faad58510bb2012a"
},
"flag_cd": {
"category": "flags",
"moji": "🇨🇩",
"description": "the democratic republic of the congo",
"unicodeVersion": "6.0",
- "digest": "318689274b4b3b58aed7fc1654127499a9da69bff1b83e592e86e69d167ce16f"
+ "digest": "91d7eeb76ac2d6f3c690e858e221ecc98b5fbf66b26ade3070524f09741aa9a9"
},
"flag_cf": {
"category": "flags",
"moji": "🇨🇫",
"description": "central african republic",
"unicodeVersion": "6.0",
- "digest": "06d6042849d3b7b217c2b18ba787aae449e8c7d2537e2e5974744ec196062228"
+ "digest": "9defc65e91df00ab2584137b9ed27e0b90296fc114164b66049a97161b9c055b"
},
"flag_cg": {
"category": "flags",
"moji": "🇨🇬",
"description": "the republic of the congo",
"unicodeVersion": "6.0",
- "digest": "09f45d2dcb5a24d8349ef86e7405cc29ef3d65a908c0bff3221c3b4546547813"
+ "digest": "de52df149377478025ef5424ef2a2d517f9275175021a436a36b2704593f331d"
},
"flag_ch": {
"category": "flags",
"moji": "🇨🇭",
"description": "switzerland",
"unicodeVersion": "6.0",
- "digest": "53d6d35aeeebb0b4b1ad858dc3691e649ac73d30b3be76f96d5fe9605fa99386"
+ "digest": "f95c47ab736c544a7aba7dc91f99f8555b974d4958c28b1234e15f0f0e478327"
},
"flag_ci": {
"category": "flags",
"moji": "🇨🇮",
"description": "cote d'ivoire",
"unicodeVersion": "6.0",
- "digest": "7d85a0c314b7397c9397a54ce2f3a4dc5f40d0234e586dbd8a541a8666f0f51e"
+ "digest": "e6aa5046857bf04f60c53716797ff77c94672195711a78b82123b1f87033c8d5"
},
"flag_ck": {
"category": "flags",
"moji": "🇨🇰",
"description": "cook islands",
"unicodeVersion": "6.0",
- "digest": "c1aa105fe106ed09ed59a596859a0ce4e65a415c59f63df51961491cb947b136"
+ "digest": "3b5d864054fd6d573aa3b65a11def76b979096ed8f04382819bea8e84c5f68eb"
},
"flag_cl": {
"category": "flags",
"moji": "🇨🇱",
"description": "chile",
"unicodeVersion": "6.0",
- "digest": "0fffdad0d892f5c08aaa332af1ed2c228583d89a43190e979a3c3cb020d5a723"
+ "digest": "59ad062f80828d97ce3f19d6b620561c88a3d67c3f2c888dde02a63a09953529"
},
"flag_cm": {
"category": "flags",
"moji": "🇨🇲",
"description": "cameroon",
"unicodeVersion": "6.0",
- "digest": "e9f55e41a1fd2735a82ad7a7ac39326a944cb20423ffba3608ac53a46036caad"
+ "digest": "cf90b6841f8c0b3b286b0f2723b4bb03ca360a44991c92644be3f805fdb1d995"
},
"flag_cn": {
"category": "flags",
"moji": "🇨🇳",
"description": "china",
"unicodeVersion": "6.0",
- "digest": "e2c8fee7e3bd51b13d6083d5bf344abe6b9b642e3cbb099d38b4ce341c99d890"
+ "digest": "f91bd474165cfe86fc9472e2ff9b9ed6938f78b217a7b68dbd6f4be40817f82c"
},
"flag_co": {
"category": "flags",
"moji": "🇨🇴",
"description": "colombia",
"unicodeVersion": "6.0",
- "digest": "51c60d0979bf8342eaff7cda9faf4b0dfab38efaf5ddf3717eb8f0e2a595b15f"
+ "digest": "96a79f28f7be6c5dd516bd7c6e811e6dcb0c03e6eb21aecedc68d1a2e57c8e18"
},
"flag_cp": {
"category": "flags",
"moji": "🇨🇵",
"description": "clipperton island",
"unicodeVersion": "6.0",
- "digest": "a0124683aa88cd7da886da70c65796c5ad84eb3751e356e9b2aa8ac249cf0bf9"
+ "digest": "9befa6ec576904fcb416549cc82a28dd2a64a80d3854416578ca1d36ec984bb9"
},
"flag_cr": {
"category": "flags",
"moji": "🇨🇷",
"description": "costa rica",
"unicodeVersion": "6.0",
- "digest": "907905971b219e617a34eef4839b0bd08d98f3480e2631bce523120dcef95196"
+ "digest": "39d9c545b555dbe42492c24be34d3cef71888d43d227582b4f3058970b0273e2"
},
"flag_cu": {
"category": "flags",
"moji": "🇨🇺",
"description": "cuba",
"unicodeVersion": "6.0",
- "digest": "d88cea729dc9dbbbcadac0409ec561995f061b2280577c01c6c6b37de347f150"
+ "digest": "488ae18785f0f86ad3caa2ea435318b6b4d6359d275a8dfe8c64c1c4bd038a00"
},
"flag_cv": {
"category": "flags",
"moji": "🇨🇻",
"description": "cape verde",
"unicodeVersion": "6.0",
- "digest": "5ce97944adfce09e96387e6f872256482ac99ccbc60017c4d58ddd15b6fb67a7"
+ "digest": "ec4bb6a33ffee5ab475b666b0e5e30bf7926674727bc6c81bff4c66c0ce6501d"
},
"flag_cw": {
"category": "flags",
"moji": "🇨🇼",
"description": "curaçao",
"unicodeVersion": "6.0",
- "digest": "a6fc31bd66ddc2ee8e7bde3aeabfe1c4ad00c9688abae234a541cc1236d68c1b"
+ "digest": "194099dd276e82906cacc51cc16b5e5f96552f9f15c3fbd9d237a680c619dabd"
},
"flag_cx": {
"category": "flags",
"moji": "🇨🇽",
"description": "christmas island",
"unicodeVersion": "6.0",
- "digest": "1261b32bfa22fa1441f5390ff499ac6b921d7ac59cc8acda3deb3a2beb4fb345"
+ "digest": "1910c2b062aa90816f1071ed6f319fedb7ce30a9be2eb66e9e016012f124342f"
},
"flag_cy": {
"category": "flags",
"moji": "🇨🇾",
"description": "cyprus",
"unicodeVersion": "6.0",
- "digest": "82b1baa05ecffa0ea1f9a83b518163cbd7910985a21955740520bb16b7bb624f"
+ "digest": "0f373bb9585e3a79baefb722d43bb02e0bce6eb7cf29f98a28701b842847e896"
},
"flag_cz": {
"category": "flags",
"moji": "🇨🇿",
"description": "the czech republic",
"unicodeVersion": "6.0",
- "digest": "a169b18968992a52299b67c24fba495e84de28dec2ebb947a08e0d615ac54a5a"
+ "digest": "805e9c0a2aeeaada2c78a40c8fb96bffde5af5f34d310b40ac14a36c27de8865"
},
"flag_de": {
"category": "flags",
"moji": "🇩🇪",
"description": "germany",
"unicodeVersion": "6.0",
- "digest": "99d1906944966a188c72ae592362ed907e2a0bfe95263955c34a0941507b30c1"
+ "digest": "ca81b828d961cb978809cf21beeb4d606063b701ffafdc775435b024e39a08f7"
},
"flag_dg": {
"category": "flags",
"moji": "🇩🇬",
"description": "diego garcia",
"unicodeVersion": "6.0",
- "digest": "dd45e1afe792fca57d4161434bf611bcb7170072d63e4a27fb9dcd6e8912621e"
+ "digest": "2d73500020be8720e3e246acb84509a6588469ebfd176e0ac37c169611d34b84"
},
"flag_dj": {
"category": "flags",
"moji": "🇩🇯",
"description": "djibouti",
"unicodeVersion": "6.0",
- "digest": "e90ba4e98fca71ff0ca5e65c28b911cc52f043428f375d8f954ecbd3b0c8f4dd"
+ "digest": "d91870a775bd58106f6f753901056d1aedf9eec008f93386093842b29d7878fc"
},
"flag_dk": {
"category": "flags",
"moji": "🇩🇰",
"description": "denmark",
"unicodeVersion": "6.0",
- "digest": "65b3b5f31935a4969d81fedbb8279c7ad32da454d15c5eafcceba5d140927c77"
+ "digest": "5ea827605cc2122b74479e14f42b6d8ae8214d411a33cfa2d72324f36e9fa472"
},
"flag_dm": {
"category": "flags",
"moji": "🇩🇲",
"description": "dominica",
"unicodeVersion": "6.0",
- "digest": "f6225ded6d2cfd6c182ab1a53b8c49dc9df195df11eb7ff27b15f5d3721ba0eb"
+ "digest": "e8d75021e4d877e277e119737c2d53ed7974393ace33768e007f7a03accd4984"
},
"flag_do": {
"category": "flags",
"moji": "🇩🇴",
"description": "the dominican republic",
"unicodeVersion": "6.0",
- "digest": "dc2ad6856cebbe47c5bd7f5dcf087e4f680d396b2d49440a9b71f0ad49fb8102"
+ "digest": "f94f2a08ba47ca0d5115ddbd6a6fdac44859c1be76e21723bf96fc2b03498fa3"
},
"flag_dz": {
"category": "flags",
"moji": "🇩🇿",
"description": "algeria",
"unicodeVersion": "6.0",
- "digest": "ea69fffc4d545f9c0fcef6768257501952955ba4d274c9b81843229a1265c5ed"
+ "digest": "6d8503291ddaff0df8993a2aaddad6b5e2a3886f5a4acede58491eb2db199051"
},
"flag_ea": {
"category": "flags",
"moji": "🇪🇦",
"description": "ceuta, melilla",
"unicodeVersion": "6.0",
- "digest": "e63bfe15428c481dd23b569e7aaf0a76106e58a946995b4415a81097ecd53b7d"
+ "digest": "a0bb9a81e9ac618a9d748e1dcb7bf68df3bdb7a0153c0ca66728bd4db3c7a31a"
},
"flag_ec": {
"category": "flags",
"moji": "🇪🇨",
"description": "ecuador",
"unicodeVersion": "6.0",
- "digest": "0cdabf85cd567047fda1d9a4508220cab829943a7c542c315078db0aac33edac"
+ "digest": "db349447120f648b542b184217f5fb950034495947619148279afa16e185748c"
},
"flag_ee": {
"category": "flags",
"moji": "🇪🇪",
"description": "estonia",
"unicodeVersion": "6.0",
- "digest": "6dc4e3377e8e2af3ff40cf940a914bc7840980b4a14e7da86954343f2b1025fe"
+ "digest": "0f4fa19e9768d0df68dc1f3525d6c84f44f109c14e8c5ae66c3bd1700e48cd66"
},
"flag_eg": {
"category": "flags",
"moji": "🇪🇬",
"description": "egypt",
"unicodeVersion": "6.0",
- "digest": "2ed6bc056015694d75993eb5ee3c1850921d5630681207b04dfbdb982ab346a2"
+ "digest": "98279109db8e0c70f8360360790d5292e46e2ae6392d23f4e0d2efed7337245f"
},
"flag_eh": {
"category": "flags",
"moji": "🇪🇭",
"description": "western sahara",
"unicodeVersion": "6.0",
- "digest": "72adb55943e4df99c00843c65463718609d937480f73dcf4a4451d46b9967a5e"
+ "digest": "87a588e0fa22413f5c2d513aa502c1d5cb29fa44d733b1f38da7ba0f0b7d7a41"
},
"flag_er": {
"category": "flags",
"moji": "🇪🇷",
"description": "eritrea",
"unicodeVersion": "6.0",
- "digest": "3fa59331eb5300c8c1f7b1f1bc15cfcfe688da6fa4a79341854598086a44eebc"
+ "digest": "40521ce78dd1572651183a7c2b5da77063e905547b227396836e57a7d3a45ca5"
},
"flag_es": {
"category": "flags",
"moji": "🇪🇸",
"description": "spain",
"unicodeVersion": "6.0",
- "digest": "1fa1d5cb0a7e8b14aaec758b2e7bf49cdf8f3d09bbcc7dfd589053a432eeae25"
+ "digest": "a0bb9a81e9ac618a9d748e1dcb7bf68df3bdb7a0153c0ca66728bd4db3c7a31a"
},
"flag_et": {
"category": "flags",
"moji": "🇪🇹",
"description": "ethiopia",
"unicodeVersion": "6.0",
- "digest": "72771decfb214394e4beb594e848ea590c3615800adbba24b5df4c5db6ee9617"
+ "digest": "5cd94075ff5c44aa50791a95b23eb4e25c5a269a9c9276e07fd16b9fe7fdba4a"
},
"flag_eu": {
"category": "flags",
"moji": "🇪🇺",
"description": "european union",
"unicodeVersion": "6.0",
- "digest": "4bfa1b2ef23764ead5ef7899806f93e13fd29a09c75e61431579a4116c836aa4"
+ "digest": "bef40bbabf6bf17653306fcf8db5722f64b67c7feff46f9c64b4ac4fb08f29e5"
},
"flag_fi": {
"category": "flags",
"moji": "🇫🇮",
"description": "finland",
"unicodeVersion": "6.0",
- "digest": "d0208cdd5b153a2865f9f674179c62871d4675abb0fb639fba88fcd62553f54e"
+ "digest": "ee894bd88268047f066c6889ce6130b0b9f196a43076c8a5c6a2d7b2ac46b664"
},
"flag_fj": {
"category": "flags",
"moji": "🇫🇯",
"description": "fiji",
"unicodeVersion": "6.0",
- "digest": "6c5ec41114af3846b093a418f6e2b5ff7a83cb72cecde75a7dc62e8cb6dcfe45"
+ "digest": "8c797bde789e70ee8bc5729086c4be884c86fc84c77721f2bc26e8b9497f5ab7"
},
"flag_fk": {
"category": "flags",
"moji": "🇫🇰",
"description": "falkland islands",
"unicodeVersion": "6.0",
- "digest": "c69ad641d53785deff5c3934b7dcfcd3dc32ffc31b6d3e799d0555b03c23fc15"
+ "digest": "8506c6cfe34559ff2aee78b3fc5445ab3a9e281ad1db5cf0085027f5925c8fe6"
},
"flag_fm": {
"category": "flags",
"moji": "🇫🇲",
"description": "micronesia",
"unicodeVersion": "6.0",
- "digest": "1e29fb06b273f253c23a9e4aa8ff84bfe22cffb5fa158a0c6f4cdeabe0216990"
+ "digest": "e32e8625a754f6a88c96a932d9ec5910dd845501eedaee71d94732c01c7b67b3"
},
"flag_fo": {
"category": "flags",
"moji": "🇫🇴",
"description": "faroe islands",
"unicodeVersion": "6.0",
- "digest": "f4907d2f606f4f9d3bef06c6d38e8e88f2a148197b1573668866431a007afc2e"
+ "digest": "b7df6f2650f1de5877cc0f435f341398929f03b9827ca0c5aba7a27c0831e04d"
},
"flag_fr": {
"category": "flags",
"moji": "🇫🇷",
"description": "france",
"unicodeVersion": "6.0",
- "digest": "5a1308ab3cbf6bffcab12588cf3325151a6c72990db7408c2b8605d89f94ed6e"
+ "digest": "9befa6ec576904fcb416549cc82a28dd2a64a80d3854416578ca1d36ec984bb9"
},
"flag_ga": {
"category": "flags",
"moji": "🇬🇦",
"description": "gabon",
"unicodeVersion": "6.0",
- "digest": "ddc32dee2976507be878ec3d3d2408632ca21bc434cd9f58db4f6ac9774a2db5"
+ "digest": "56c1dfbc184a64a3485f5c26ebe6334613e6470432b303f9e7ac065f5ef8a951"
},
"flag_gb": {
"category": "flags",
"moji": "🇬🇧",
"description": "great britain",
"unicodeVersion": "6.0",
- "digest": "6b3bb254d134870b02cb066b06e206f652638a915c84b8649ceb30ec67fbebde"
+ "digest": "4fbe942f87f2779c94cff5179e235e002c968a66591967e32f723882ab67ccd1"
},
"flag_gd": {
"category": "flags",
"moji": "🇬🇩",
"description": "grenada",
"unicodeVersion": "6.0",
- "digest": "b6a210541ca22d816405f2a7d0d5241dc4d5488c8a36e15bd1e3063f9c41327f"
+ "digest": "3a47a0f033ddafa97f186d71104dabbfdb3107b8818c4c7dbd065656d0db494e"
},
"flag_ge": {
"category": "flags",
"moji": "🇬🇪",
"description": "georgia",
"unicodeVersion": "6.0",
- "digest": "e9a5035b7a46b925737e7f7b0ae2419cc4af0e980fbee5bd916edeef13823367"
+ "digest": "7e35be45e85ba5d6e4f781f111cf896b318d2109a3e0f542bd8082aef744a7ed"
},
"flag_gf": {
"category": "flags",
"moji": "🇬🇫",
"description": "french guiana",
"unicodeVersion": "6.0",
- "digest": "ce1bcd8c303897c1c22c5994182f21240b4aa635f0d7ce9944f76cbdbf0e4956"
+ "digest": "50b2004848f0aa7a3d6cbb96ef657e7e6ec3cdd32968bd1e238e1772e781253c"
},
"flag_gg": {
"category": "flags",
"moji": "🇬🇬",
"description": "guernsey",
"unicodeVersion": "6.0",
- "digest": "a435aab3609533ab2d68acd97deba844bfb0fc27b2adac68668223011f23ae5d"
+ "digest": "32cb5c12dec3a8d3b3c4c254d8cb5596f6ef591ff8f36d45cf976179ec379591"
},
"flag_gh": {
"category": "flags",
"moji": "🇬🇭",
"description": "ghana",
"unicodeVersion": "6.0",
- "digest": "7cad43b40f69b9b00cc1b38036789ce774fd3d597c89f0bf38433847ea69be26"
+ "digest": "11b545e6770cd546fb936e9348bdd34b77f4519fd1d7476e6ff19f3e25b2f17e"
},
"flag_gi": {
"category": "flags",
"moji": "🇬🇮",
"description": "gibraltar",
"unicodeVersion": "6.0",
- "digest": "70e9b17d18bf3e0e4d03f4f824323a57909416e4082ca9d8a0796a6959de4f07"
+ "digest": "17a64465507f9fa106b7a42124378a01b3d4eea983e358fbda5db3af9c126801"
},
"flag_gl": {
"category": "flags",
"moji": "🇬🇱",
"description": "greenland",
"unicodeVersion": "6.0",
- "digest": "1963d8cca1c1f06b7536b7fb8f5a4782ac0bb05afdf6e481101bce45c58cdd4b"
+ "digest": "cdc8831d7cad5f3cc1af595d8d08274363e4d97e80d70215b500f7972648c902"
},
"flag_gm": {
"category": "flags",
"moji": "🇬🇲",
"description": "the gambia",
"unicodeVersion": "6.0",
- "digest": "6c776a8daa3f4daa2597b0025aec06fc0a53aed262e845d4da3897cd7a89c6a1"
+ "digest": "95e52c4d904a9b7334b3ae78bfa3610accec562e15c742e15de924b8ed07e62e"
},
"flag_gn": {
"category": "flags",
"moji": "🇬🇳",
"description": "guinea",
"unicodeVersion": "6.0",
- "digest": "134cf7c839370d171ae80a72e5d18d32ea1967df19c191d1a4ea446d649e9558"
+ "digest": "86b344b5ebaff1fe176b8b4766a3caf9052f0516fa11202b0b2499c31047237c"
},
"flag_gp": {
"category": "flags",
"moji": "🇬🇵",
"description": "guadeloupe",
"unicodeVersion": "6.0",
- "digest": "be3e906b039ba4884053c78f4f14de9aa87c5573860ccb69ec766068ae3887c2"
+ "digest": "d8a954681d151bd0f8b633a405e0b1578560f717f313ce2ec610f896d3ab1862"
},
"flag_gq": {
"category": "flags",
"moji": "🇬🇶",
"description": "equatorial guinea",
"unicodeVersion": "6.0",
- "digest": "d476059c4ab41f5a1ef88583087362a5bc57cede930126f37041d1546564ab70"
+ "digest": "79bb35d3bb762493d73e99ff1097cc8d9c24bb2c6b4703772b58bcfbae69783a"
},
"flag_gr": {
"category": "flags",
"moji": "🇬🇷",
"description": "greece",
"unicodeVersion": "6.0",
- "digest": "b9fa9304647aaa08167a07858bb18d778dcc399375f86f580b8d4244794678bc"
+ "digest": "3e1d276628d76a1d6fb9d6fae0a9745f71ad1af5d1abf248fa6a312c995e558f"
},
"flag_gs": {
"category": "flags",
"moji": "🇬🇸",
"description": "south georgia",
"unicodeVersion": "6.0",
- "digest": "de33fbef6e294eb7af36e5b94d8ff573b354a4ff1ebdccf50ca528b86ed601d9"
+ "digest": "0e0f20d991cb05f161363559f56331d9da08b1f87c419bb7315d19b07560a3cc"
},
"flag_gt": {
"category": "flags",
"moji": "🇬🇹",
"description": "guatemala",
"unicodeVersion": "6.0",
- "digest": "4160843e5d642df597c8423eb8e3b74deafe304f3d141c8a4d2fc07509e44832"
+ "digest": "71d0ff372814a42595062bb1d6d3e5d12fee4f5953d3928c928be2054bbbd06c"
},
"flag_gu": {
"category": "flags",
"moji": "🇬🇺",
"description": "guam",
"unicodeVersion": "6.0",
- "digest": "3b0cb257ba5b1c3e15d9102410c5f7418da03372e91ce90513de25b9f45283e3"
+ "digest": "dc46c08c39ef0a3c28d9349ac07aa37b31ab5191ee3653244830f52f9cdfbb80"
},
"flag_gw": {
"category": "flags",
"moji": "🇬🇼",
"description": "guinea-bissau",
"unicodeVersion": "6.0",
- "digest": "bdf07a8f93c0f0a573af5f5361be404a3ba65b729c1a4c05b7632c03d85efc72"
+ "digest": "f6c1801bc90c25ec3553b03f53e1e9693ef371ed2151c31770ec7ae2cc62129b"
},
"flag_gy": {
"category": "flags",
"moji": "🇬🇾",
"description": "guyana",
"unicodeVersion": "6.0",
- "digest": "b47d8c98b747556f827ad0d1169264eb68ecaf9d2fb76595e8c31866361cbfc6"
+ "digest": "6d8a3555025d55ace126fc82e226fc7d9ae908252e7680b6ed5345bd61355e0a"
},
"flag_hk": {
"category": "flags",
"moji": "🇭🇰",
"description": "hong kong",
"unicodeVersion": "6.0",
- "digest": "8e5a54b2e4bd4f5182085299b9648062463da05d535cf0e46a7d9c58eaeb171f"
+ "digest": "94cded43ade6331506183d5c4d9269dd98d5b30a3293540d245a84548847a7df"
},
"flag_hm": {
"category": "flags",
"moji": "🇭🇲",
"description": "heard island and mcdonald islands",
"unicodeVersion": "6.0",
- "digest": "63c3e080c5e82a72c6d4cf5997ac823dc02184719ec59aadea6dd41b127abf22"
+ "digest": "a0f178063d1c9628914dcece5ccd205b1293536903f4bf12192e15835ea39c8d"
},
"flag_hn": {
"category": "flags",
"moji": "🇭🇳",
"description": "honduras",
"unicodeVersion": "6.0",
- "digest": "87c1d160db810b5ed208fb33add54f96c17b0f08d87b81f6f09429abf6ec93ac"
+ "digest": "51ad3bc94bf7cd3fe5bfda61c8d4f7f7e7d7ad91a3b6b01babe9a969cf10712b"
},
"flag_hr": {
"category": "flags",
"moji": "🇭🇷",
"description": "croatia",
"unicodeVersion": "6.0",
- "digest": "8b68112f79baea38565673acf4f1cb90675a5829ff17e4cf9415c928b62aed88"
+ "digest": "f706fba43e3e480863b03c18ff2099452efdc04ee29c7a888077af786343f4ac"
},
"flag_ht": {
"category": "flags",
"moji": "🇭🇹",
"description": "haiti",
"unicodeVersion": "6.0",
- "digest": "05dbd548c310ef1ebd1724aa85d821f8320106b16ddbf1f6442ea37e4407d5e1"
+ "digest": "2b95c7c031991d6bfcf3d43f38dd71cf1b3fff7289daa12e230ad7d945c91fdc"
},
"flag_hu": {
"category": "flags",
"moji": "🇭🇺",
"description": "hungary",
"unicodeVersion": "6.0",
- "digest": "5079f3d6f1459e6df8dda5c19d2367ead8f5a755b8874ac999bae58e3c9f47a7"
+ "digest": "e5d409e98c4d69966ea34aa6cdb2f7ed18cbf0073b58e0cb590b0de31962b189"
},
"flag_ic": {
"category": "flags",
"moji": "🇮🇨",
"description": "canary islands",
"unicodeVersion": "6.0",
- "digest": "8dcb18c4b75a60867a68d2f6edbf81e782aafb4b9a0404c8081f872dfe71e432"
+ "digest": "24cb53cec148c62dbc7dbf9ed30811d893fd1db5c67aec8d7a0fc3695e8ceff5"
},
"flag_id": {
"category": "flags",
"moji": "🇮🇩",
"description": "indonesia",
"unicodeVersion": "6.0",
- "digest": "1b0eb69a158ed3afe24be448d44751f95dcc5cbc7d1393a5753293f16ef0a66c"
+ "digest": "15c6f0879b4ef9ed4c22873eb14d53b1a4cf35630d477208f30b61abe9a98169"
},
"flag_ie": {
"category": "flags",
"moji": "🇮🇪",
"description": "ireland",
"unicodeVersion": "6.0",
- "digest": "5fc8c101ad7296224455f72f73c335aa4f676023b68645bafaf69087f69af390"
+ "digest": "393a9547a688913216222943ab7b6b0f7a58169320edf23734f254bb031116e9"
},
"flag_il": {
"category": "flags",
"moji": "🇮🇱",
"description": "israel",
"unicodeVersion": "6.0",
- "digest": "5aea4207415b7615dcdd69413705aefda700aefd0d27010cd0a0a338d879d9b8"
+ "digest": "74efe8d05aa9a204ee3fb24a0081f5445e17fe3c8a6179f029b83399af7848c3"
},
"flag_im": {
"category": "flags",
"moji": "🇮🇲",
"description": "isle of man",
"unicodeVersion": "6.0",
- "digest": "1ee9b3a5f1a52fc6d8369bfd81995fc0567e7a61deacd013701b3ec5fd64502e"
+ "digest": "5cddae6e5104e01ac5b4646c66851dfd6cce78a7159d35d84c2e983f6a69d534"
},
"flag_in": {
"category": "flags",
"moji": "🇮🇳",
"description": "india",
"unicodeVersion": "6.0",
- "digest": "202ede502f34d55d180726ac2f29141c6875516f1b3e7ee99f266b16c2fe4bfd"
+ "digest": "f101b075e929dc89cba9e7bbdab4eefabb7281bf60929cb19650ce514d9562c6"
},
"flag_io": {
"category": "flags",
"moji": "🇮🇴",
"description": "british indian ocean territory",
"unicodeVersion": "6.0",
- "digest": "dd45e1afe792fca57d4161434bf611bcb7170072d63e4a27fb9dcd6e8912621e"
+ "digest": "2d73500020be8720e3e246acb84509a6588469ebfd176e0ac37c169611d34b84"
},
"flag_iq": {
"category": "flags",
"moji": "🇮🇶",
"description": "iraq",
"unicodeVersion": "6.0",
- "digest": "bef294772b5ffccd6c061c19d60af66f61b248d78705faf347ade9ebfca2b46d"
+ "digest": "b7c87d70cfec7223a80968c653936877d850828cab957bab68441880f0190744"
},
"flag_ir": {
"category": "flags",
"moji": "🇮🇷",
"description": "iran",
"unicodeVersion": "6.0",
- "digest": "d4faca93577a5546330ab6a09252307e19fb420d89912c0b48ceb90bf409d48e"
+ "digest": "460ca178e11a7758b0794009021eb5c1dd4dd9895fe00ba738a78aab7c0951b4"
},
"flag_is": {
"category": "flags",
"moji": "🇮🇸",
"description": "iceland",
"unicodeVersion": "6.0",
- "digest": "b2fc04226b274009b4d99d92bcb72b255b534b6fd4b76d82dce1575ad975a456"
+ "digest": "2cd53b0e7caa9955bd51aa80700cb3ee1efe3296005b2f0a9f190633e123e1e1"
},
"flag_it": {
"category": "flags",
"moji": "🇮🇹",
"description": "italy",
"unicodeVersion": "6.0",
- "digest": "735760f193855d55460a0fb93dad55ff67253cab63176eceb90b9bde1faead1e"
+ "digest": "293966902f72b4251ea9e0ca3ee8e07e80260b927acd4cfc53d0c21f6e9c4ca6"
},
"flag_je": {
"category": "flags",
"moji": "🇯🇪",
"description": "jersey",
"unicodeVersion": "6.0",
- "digest": "671a487a60571d928d2abaf306d0a9ba50239ec54ada14ea29a9a99df658d3cc"
+ "digest": "57777951e3daed5db18380bcddf79d6ffb82f51129117c000c52dead790c640e"
},
"flag_jm": {
"category": "flags",
"moji": "🇯🇲",
"description": "jamaica",
"unicodeVersion": "6.0",
- "digest": "fb9047199d030b78fc0dcfc58d9b524fdb929238d922809da88147b7cebf4211"
+ "digest": "40d69fdb14fc3a1a7cfec9a6b64654e549873f3ed9d30e054ada2690c5f09f5c"
},
"flag_jo": {
"category": "flags",
"moji": "🇯🇴",
"description": "jordan",
"unicodeVersion": "6.0",
- "digest": "19f7d536d0293ebf3db49e05a158097cbde467115ef96523a0553808fd0b4178"
+ "digest": "26b5445e2d30acd52afb1e1595cf805bb8759209b81686d3aeaa9205a288d3f2"
},
"flag_jp": {
"category": "flags",
"moji": "🇯🇵",
"description": "japan",
"unicodeVersion": "6.0",
- "digest": "51e971f777fe481ca9f7e077ecb2ce252c3cc0086b76384e7b965cdc337f3f9e"
+ "digest": "e027f2b4bf3f70bbd4db60cdf3627c73db8a2af74352d38028ffccf7b0023321"
},
"flag_ke": {
"category": "flags",
"moji": "🇰🇪",
"description": "kenya",
"unicodeVersion": "6.0",
- "digest": "0cec8f068548cfd3e7a20c10af84f97ca415fd6f8ab8b50783bf982e77d7260e"
+ "digest": "0e24515d79f21b048ebab1f5cb1b13e7b9ec47bec6be14dfca6616d790def902"
},
"flag_kg": {
"category": "flags",
"moji": "🇰🇬",
"description": "kyrgyzstan",
"unicodeVersion": "6.0",
- "digest": "5803ea6ab028261923fd7570c670a50518c6f462a2fb4d463531b12c3e382e6f"
+ "digest": "a2ddb2330522d7fed347484e387df1f3624c750598163835b36bccea5804769b"
},
"flag_kh": {
"category": "flags",
"moji": "🇰🇭",
"description": "cambodia",
"unicodeVersion": "6.0",
- "digest": "287d357afe47179853fd485fb102834ead145598ed892664fc62d245cac16080"
+ "digest": "2bda6ba32b606f9c38fd523f9c5751827e171356e5838dc2a896ed99614f2604"
},
"flag_ki": {
"category": "flags",
"moji": "🇰🇮",
"description": "kiribati",
"unicodeVersion": "6.0",
- "digest": "ae4aee0d9cd7a21d4e250d45a484f5f641acdab3d79b437337b25fe34a0b49b0"
+ "digest": "ade73185e59ff92da90e83a57f70543316d20d3b4e621979527f3278925f09bc"
},
"flag_km": {
"category": "flags",
"moji": "🇰🇲",
"description": "the comoros",
"unicodeVersion": "6.0",
- "digest": "2d1730acbf5421fd02bd5483e26a86d82ec2fa99f0ff75bfd728a9df7914ad3b"
+ "digest": "1df769ea0b30f346061bd1fa92aa15092770a5f774083060798beffb17537df7"
},
"flag_kn": {
"category": "flags",
"moji": "🇰🇳",
"description": "saint kitts and nevis",
"unicodeVersion": "6.0",
- "digest": "b9ed979db9c6d243b00f61f19a9ec0f2c2390b2e5cace5ad61d9371dc8c670ac"
+ "digest": "c8c37a3fc3de6fb7fe0f46a3c344aef5680b6f04dea8ac2ebadc2a497c42a5df"
},
"flag_kp": {
"category": "flags",
"moji": "🇰🇵",
"description": "north korea",
"unicodeVersion": "6.0",
- "digest": "1bab0b9cab8028a95ce7231ad8d88ebcd31601cfa321284bba017ead47f6c729"
+ "digest": "a3e62ba6e95dffd83afff06f5b5a61070f616650e8657ec58b23f1e87731d789"
},
"flag_kr": {
"category": "flags",
"moji": "🇰🇷",
"description": "korea",
"unicodeVersion": "6.0",
- "digest": "33be8c09ebe273e203aa703cc827d52a6d9bf1699f5445bba13a77af2df45fa6"
+ "digest": "6742981d05cb0f4d2be094b44b4db222f25b23102e68a7fa72f915417f1b41d9"
},
"flag_kw": {
"category": "flags",
"moji": "🇰🇼",
"description": "kuwait",
"unicodeVersion": "6.0",
- "digest": "04d901a92ea55b13dc4983a9e3adb52dc89c9f3decee86fd06022aa902678b6d"
+ "digest": "470ec6649e3b3726bfca9cfa8254a7af46b3e3e5fb32c9b23b1b6225251676b2"
},
"flag_ky": {
"category": "flags",
"moji": "🇰🇾",
"description": "cayman islands",
"unicodeVersion": "6.0",
- "digest": "10f4d02f33cadd34da89de71a3b763809bad480cd9ae9d2ec000db026bd94cd1"
+ "digest": "5f985d9fb33d9556499e2380429b36fdebf0c747acce24b0cbde7e94a52945c8"
},
"flag_kz": {
"category": "flags",
"moji": "🇰🇿",
"description": "kazakhstan",
"unicodeVersion": "6.0",
- "digest": "dfaff69a78cf635f7fad41bd5bdcc8003298454708a6178ba7348b1b40c360c1"
+ "digest": "39997272a8a1185962b2fe0b5eb672f8265858cb5ad4617ca33dc415552ff60e"
},
"flag_la": {
"category": "flags",
"moji": "🇱🇦",
"description": "laos",
"unicodeVersion": "6.0",
- "digest": "4fcfbdc694cf99ae3f832500cdcdedb88c444b6df88bc9b7141f4f26ba3d5bfd"
+ "digest": "1e883029005dd0e2486be6e54266125757d66d87d8b7d000f1fa66fe58de85fc"
},
"flag_lb": {
"category": "flags",
"moji": "🇱🇧",
"description": "lebanon",
"unicodeVersion": "6.0",
- "digest": "af4b1f784bea0ec7a712495491dffbd1152cc857a99fd433f76bfeb313819a62"
+ "digest": "4d7709289c1b3258197b7241432e1f3e57c0153a1ae6411aea07e5c46713bbab"
},
"flag_lc": {
"category": "flags",
"moji": "🇱🇨",
"description": "saint lucia",
"unicodeVersion": "6.0",
- "digest": "40784aa558b75d07ae499c004e2cc5d0b2efdfc3e5be705b5a9f6b70d681c396"
+ "digest": "928d8795e7f6aad53cda39308027ca22c8f654e6d0d5fcc0b5f2ebd97d5e5edf"
},
"flag_li": {
"category": "flags",
"moji": "🇱🇮",
"description": "liechtenstein",
"unicodeVersion": "6.0",
- "digest": "c4eb4c43f457ce60ff9d046adb512c1d3462203403eeb595bff3ebc010ed6633"
+ "digest": "513db4f951ed12f103e70ac05121701795b4e24e4cc1fb2241802eea4fb2c80c"
},
"flag_lk": {
"category": "flags",
"moji": "🇱🇰",
"description": "sri lanka",
"unicodeVersion": "6.0",
- "digest": "a5285cdfdc3715fa3941f5f0eb03dc425969eaaf22c719c27ab4418628d09bc5"
+ "digest": "29e035ca237aa9fa82c9461e73e26edc39384f7869753949dc0efa15cb05673e"
},
"flag_lr": {
"category": "flags",
"moji": "🇱🇷",
"description": "liberia",
"unicodeVersion": "6.0",
- "digest": "ed04334264953b4da570db8c392b99d2fab4e0b7efc2331427016c6a08e818be"
+ "digest": "2144d754061c34fec7f0929bb498465d93d10431686f3105c94987bf5ce21ae0"
},
"flag_ls": {
"category": "flags",
"moji": "🇱🇸",
"description": "lesotho",
"unicodeVersion": "6.0",
- "digest": "cd56022106d027317cc9bf4c848758cf29ffe277ce71fdb9c1cf89ac4fd6e6db"
+ "digest": "b65a30f810fba0b10e13e029b14e334365abf7a482d77e2d3eeb593733ca1313"
},
"flag_lt": {
"category": "flags",
"moji": "🇱🇹",
"description": "lithuania",
"unicodeVersion": "6.0",
- "digest": "3c4395b068e421100fd97a102f170cb8d5c093885eef7cb40d3faff4f4e47fe9"
+ "digest": "124639833b8ecd1338096be80b5fbf4d8aa988e3b64ab244a2d16fa485d5a1f8"
},
"flag_lu": {
"category": "flags",
"moji": "🇱🇺",
"description": "luxembourg",
"unicodeVersion": "6.0",
- "digest": "df15a2c47eecad17e0cc169bdf0d31c6a51eb22de7ca4e70d2431359a33f930d"
+ "digest": "c76b3fcddb7690815b111be7579395b182f2314a50617d7e59e3afdaffafaf49"
},
"flag_lv": {
"category": "flags",
"moji": "🇱🇻",
"description": "latvia",
"unicodeVersion": "6.0",
- "digest": "9b53c6ce23287935200da8ca8a8af78013a4b1572f9821e7e1724cbad248e7e2"
+ "digest": "544ef9b126d723290102e14522bfce331db48271b4763b049350d77ba10bc897"
},
"flag_ly": {
"category": "flags",
"moji": "🇱🇾",
"description": "libya",
"unicodeVersion": "6.0",
- "digest": "42efa9f3526ef006d6723fa17538a98ab9556ae25f14df1b06d21361bf7e1a44"
+ "digest": "6421bc96f7dacdcb900891ea9635bd1f7683cbb8aa388cff3c5218fc60403fe7"
},
"flag_ma": {
"category": "flags",
"moji": "🇲🇦",
"description": "morocco",
"unicodeVersion": "6.0",
- "digest": "96c07296cfd7aa1cb642faed8ace26744105b81ca880157a4ef4caee0befe26e"
+ "digest": "60723c7b383c001ccc8947d39d89ddf3ea6c08df57e782ab5ca5f2ddd65acc64"
},
"flag_mc": {
"category": "flags",
"moji": "🇲🇨",
"description": "monaco",
"unicodeVersion": "6.0",
- "digest": "6b44608842fe849ae2b4bae5eb87ccd436459a427051dfda25080196273d4b9f"
+ "digest": "cef4ad68dc0a9f2691837fec6499bf317d0d65e8d04ede19db4318b8441b15de"
},
"flag_md": {
"category": "flags",
"moji": "🇲🇩",
"description": "moldova",
"unicodeVersion": "6.0",
- "digest": "78c7b01c698873a9129d52ba38b3eb4cfc683ef2ae10b7b922b17c07f1c938c8"
+ "digest": "893c17bf710df2f37d124d2072f50b0289a495a45ae05edf1a6a11a3f828b73e"
},
"flag_me": {
"category": "flags",
"moji": "🇲🇪",
"description": "montenegro",
"unicodeVersion": "6.0",
- "digest": "01aa0f9df89302edc4ae319b5dd78069ba8807c3f38cc7bfe01bff67c8efd416"
+ "digest": "725b02fadc44e2f13a845fda34a8d497d812a084bf798bc14e775c44a15ebee4"
},
"flag_mf": {
"category": "flags",
"moji": "🇲🇫",
"description": "saint martin",
"unicodeVersion": "6.0",
- "digest": "a0124683aa88cd7da886da70c65796c5ad84eb3751e356e9b2aa8ac249cf0bf9"
+ "digest": "9befa6ec576904fcb416549cc82a28dd2a64a80d3854416578ca1d36ec984bb9"
},
"flag_mg": {
"category": "flags",
"moji": "🇲🇬",
"description": "madagascar",
"unicodeVersion": "6.0",
- "digest": "56ebcd2a2e144d656d3b38a62595138fe6e50f9c1144f70b0a120cce7a72eb5b"
+ "digest": "988268ce3bf1025329371c5b7e331915851fe8ee0a60a2e97ea14f7db6ecf5ca"
},
"flag_mh": {
"category": "flags",
"moji": "🇲🇭",
"description": "the marshall islands",
"unicodeVersion": "6.0",
- "digest": "008660adc4c2e4d04830498988184d1ef8a372a6c085da369a94ee6b820dbbb7"
+ "digest": "7406e8b96c7f6896a6168caa58319713c3012ef1b1d93cbceb3cbb6033ef258f"
},
"flag_mk": {
"category": "flags",
"moji": "🇲🇰",
"description": "macedonia",
"unicodeVersion": "6.0",
- "digest": "f3c4c5106ace81c21fc0c6a7cc5c5e04e9453468fbc6ccbc851bb8dd61ff237f"
+ "digest": "2b65acb553fddbf6ce468159dfe0aea76d7fb2094a6d0fbe96deff92bb721a12"
},
"flag_ml": {
"category": "flags",
"moji": "🇲🇱",
"description": "mali",
"unicodeVersion": "6.0",
- "digest": "e70a6b30e46adc2e19684308a848fef2c3ad76e2cac4bb493ee3270ad39f9d1b"
+ "digest": "21b19884406361f128e0ac39c6d7fc91b0452e355ddaedff1ca2236cf38ecb1b"
},
"flag_mm": {
"category": "flags",
"moji": "🇲🇲",
"description": "myanmar",
"unicodeVersion": "6.0",
- "digest": "720f5d38887202ba049cd5a46c183679be6a01f169d99e6e656c73b515793a7d"
+ "digest": "a8657c723ad79b74ff6a1be00d98d3f554279ff45c97b81b65241c39d860130b"
},
"flag_mn": {
"category": "flags",
"moji": "🇲🇳",
"description": "mongolia",
"unicodeVersion": "6.0",
- "digest": "5f0fd6fcb2ed73a5a6d9396c3703612503c1f16283bbb4e9362a1c8324b762ad"
+ "digest": "66c696f64bfbcf749e1be19195be7b61e2652c27efcb33f181d07305071662a6"
},
"flag_mo": {
"category": "flags",
"moji": "🇲🇴",
"description": "macau",
"unicodeVersion": "6.0",
- "digest": "fc2a9e7323867cf195f551e59afdab778c56b84c96af28c20207c9870caa2c39"
+ "digest": "8b867cb8690bdb63c516ad04c1862d8d4a93ad50eb63bf67392ec917f1eeb54f"
},
"flag_mp": {
"category": "flags",
"moji": "🇲🇵",
"description": "northern mariana islands",
"unicodeVersion": "6.0",
- "digest": "ddce3be9d72914240c42e1b97ea97af01016d0a3879999cb0e447552682c06ba"
+ "digest": "900487ee59fe27599fa632351e37a97a8bfc55be19c7cee4bccfc9349db50f11"
},
"flag_mq": {
"category": "flags",
"moji": "🇲🇶",
"description": "martinique",
"unicodeVersion": "6.0",
- "digest": "888f455b1322d6fb83dc9f469f5505fea3dd6ece77d17d0d7345319c3ebcec0e"
+ "digest": "6ec18a3d696913f8e17426ab473b2eb2575b52f82859e09d03492a2ec388ac99"
},
"flag_mr": {
"category": "flags",
"moji": "🇲🇷",
"description": "mauritania",
"unicodeVersion": "6.0",
- "digest": "72621914c92dd9c9f3ac9973ee3589583bfe42b841cdd35f47af75e2f629726c"
+ "digest": "b25ec19d502a7c41cf860eebb8057b0349ef1542f0f87c0ac53661ce0d6383c9"
},
"flag_ms": {
"category": "flags",
"moji": "🇲🇸",
"description": "montserrat",
"unicodeVersion": "6.0",
- "digest": "5944996295132f41ec55261ff7927518bd47aec95d274a6ff257c357b43657bc"
+ "digest": "2aa4c37c4e46a80e258542b283f285650d6033fd20c6ba42dc9780f6617bbecd"
},
"flag_mt": {
"category": "flags",
"moji": "🇲🇹",
"description": "malta",
"unicodeVersion": "6.0",
- "digest": "95f0550e8823441a4e69b26c540baea94f3ddcc282100fd0239021c00df0b469"
+ "digest": "8ad1f6fe41838db1265a82e64429c9975b69e768ff75cc421ae8a2ace5fdbbcb"
},
"flag_mu": {
"category": "flags",
"moji": "🇲🇺",
"description": "mauritius",
"unicodeVersion": "6.0",
- "digest": "5fda78a6df0ea7f5cac5fb4c8fd68529c14c5e15bac4e0b167493cb6ac459253"
+ "digest": "4170bd01f143e46f3661905c99b7600a08e15647f0863a40ca5d560257646935"
},
"flag_mv": {
"category": "flags",
"moji": "🇲🇻",
"description": "maldives",
"unicodeVersion": "6.0",
- "digest": "f75c8f6fd3a68f2944a04c833c649d4b576997f491100cf3f3160fe77117fabb"
+ "digest": "af4f4fa274a9aa13ff85d31d3b4297109066c71b6ee0d2960ddcfc11d126d3e7"
},
"flag_mw": {
"category": "flags",
"moji": "🇲🇼",
"description": "malawi",
"unicodeVersion": "6.0",
- "digest": "d46b484a97e5b90b6b259f8de1712b553f93f0dfb6391209200358bb9429ebf5"
+ "digest": "6f96e6a8393c3a30ca264adfdb27d38f455b878298b53dc7c53943032dfec843"
},
"flag_mx": {
"category": "flags",
"moji": "🇲🇽",
"description": "mexico",
"unicodeVersion": "6.0",
- "digest": "dc57c10307fc0aa09bd7fcd25ee0fca561f3b382276faa8432a927c1baea53fd"
+ "digest": "f051655378ac2d34259427277f769a45fbdce14779b2220e1364e2b82574bcd2"
},
"flag_my": {
"category": "flags",
"moji": "🇲🇾",
"description": "malaysia",
"unicodeVersion": "6.0",
- "digest": "15ca00660a1eb0096fdaa00b85a7b95fcf192bf2ee4781ba72c36d2d2cb015ef"
+ "digest": "3556cfbd5c81371e5a742af8b94a6bb920a621156aa45b96a359626baa0d58ad"
},
"flag_mz": {
"category": "flags",
"moji": "🇲🇿",
"description": "mozambique",
"unicodeVersion": "6.0",
- "digest": "0c8605a9319dcf86672a833b4c4d6acea5f6aa25a3f8e1dfac78fbf7c452ba97"
+ "digest": "7b74419cc136257ee2a20a221b2f1de704d2088a3cbac7c3802d683de796e11d"
},
"flag_na": {
"category": "flags",
"moji": "🇳🇦",
"description": "namibia",
"unicodeVersion": "6.0",
- "digest": "e63cde5ee49d3ada1e33d2ab15dc24fbb129b90d65b6fd1d7c07455f71a53601"
+ "digest": "090c9f0e66c647fc46c52294656e1be17231b8b0e8a8676ee0c645ddf34c5ff4"
},
"flag_nc": {
"category": "flags",
"moji": "🇳🇨",
"description": "new caledonia",
"unicodeVersion": "6.0",
- "digest": "a4a350ce7404ba7bdda9a341e7a48fcfe16312be4964b1bd6eed7115acd2e329"
+ "digest": "dcdf1c451d81cadff2b293793e155d92991b5116c1c6dac6507ad7a67c3e494b"
},
"flag_ne": {
"category": "flags",
"moji": "🇳🇪",
"description": "niger",
"unicodeVersion": "6.0",
- "digest": "6b32483b4445bc52855509f618c570b9c9606de5649e4878b71b44ff2acbc9fd"
+ "digest": "385354f4d65bc6a6d912b894b49f47b0abaf3e74f142aeecd1940a24448d1b9d"
},
"flag_nf": {
"category": "flags",
"moji": "🇳🇫",
"description": "norfolk island",
"unicodeVersion": "6.0",
- "digest": "96b1ec33acbd2b1ffe42703c11a2a633b036e6779849b0e6fa8f399167820584"
+ "digest": "fb772f17fa5448f9b5bd0c5f9fc7f56236a92e0895c96daa08ef689ebdf11290"
},
"flag_ng": {
"category": "flags",
"moji": "🇳🇬",
"description": "nigeria",
"unicodeVersion": "6.0",
- "digest": "f97d0630cbfa5e75440251df7529a67b58c22598643390cbeea82fb04a1cd956"
+ "digest": "6388983bd628568ee1ca1ccea31c349ec831046b4c325b60f85583dc044cfaa0"
},
"flag_ni": {
"category": "flags",
"moji": "🇳🇮",
"description": "nicaragua",
"unicodeVersion": "6.0",
- "digest": "c52fb5f9134122a91defa75425be2c6b3c909e051d546244e0e7bdf5f9ee1710"
+ "digest": "8b501d22cc4eb9ed680943cbb881e038cac5e430794265918b874ef582fd325c"
},
"flag_nl": {
"category": "flags",
"moji": "🇳🇱",
"description": "the netherlands",
"unicodeVersion": "6.0",
- "digest": "b8918f9c0c92513aa0ec6ba6cee5448270168cbe6f0a970fb06e7ceb9f52ec71"
+ "digest": "20019b864f43c199b8c425914b32ede6e792ef9ede384c59293ec095bdf2c5cb"
},
"flag_no": {
"category": "flags",
"moji": "🇳🇴",
"description": "norway",
"unicodeVersion": "6.0",
- "digest": "05ce84095f8d93407d611b39d8b6a67fd9f11df6cfab7a185bcb4eec186d85ef"
+ "digest": "473f79dc252e5029ce80980408fce347e31d1902ebf278ddc5d30006e8e83d45"
},
"flag_np": {
"category": "flags",
"moji": "🇳🇵",
"description": "nepal",
"unicodeVersion": "6.0",
- "digest": "cc41c2f97ec2b38fe5781d553792f6aab5d37cc3be02586f361fe89d12683bee"
+ "digest": "b6bfbb5935b6a6562e2d22219ed4550fa790e7036c92b98d3ce3cb47e3ec436b"
},
"flag_nr": {
"category": "flags",
"moji": "🇳🇷",
"description": "nauru",
"unicodeVersion": "6.0",
- "digest": "7837edf59ec33a25380d76afea5f04cfcab4f17df4e33fca0dcaacb517c5cbec"
+ "digest": "36d35a88f6524691c1feea15f43b94ea17afe0c85d183c3a215482ec7bbe2c3d"
},
"flag_nu": {
"category": "flags",
"moji": "🇳🇺",
"description": "niue",
"unicodeVersion": "6.0",
- "digest": "fd9ab45c6f32bc4da47542392e5beba73ddac302a4a9a00e6deedc913a4c087d"
+ "digest": "8927e4bbe71a570f5e0c95cba05cc1c217f17b10ced51f76e134c98392814c45"
},
"flag_nz": {
"category": "flags",
"moji": "🇳🇿",
"description": "new zealand",
"unicodeVersion": "6.0",
- "digest": "0719830dcca400cefb30ce399bb03f49dd84c9a98f7d6a28270f9278e2a7af75"
+ "digest": "8ff5c61a364bd39ad4560333ca57b14a0495b4664fae4b04eed7de8c75a443d3"
},
"flag_om": {
"category": "flags",
"moji": "🇴🇲",
"description": "oman",
"unicodeVersion": "6.0",
- "digest": "3f9039becd52e3454fdf7611cdb0d7fb1196e053eea29ef87daab6c21a94f1ee"
+ "digest": "e5b91ea7ea3ffabfb2ef1176363272702ca02030768166af94b5ef84771df633"
},
"flag_pa": {
"category": "flags",
"moji": "🇵🇦",
"description": "panama",
"unicodeVersion": "6.0",
- "digest": "1adf0e5d4084e072aa44bd9978829e77546e0be75785e9be69f92e326bd714a7"
+ "digest": "9cac49d2a1ae56445463f0932ee7b554304d9c8ad3d969266177072608d374f1"
},
"flag_pe": {
"category": "flags",
"moji": "🇵🇪",
"description": "peru",
"unicodeVersion": "6.0",
- "digest": "f8a4e257676f4ab8962ffe5509b8417777a8be2f0e9dc7735d3e014ff221aab1"
+ "digest": "00b83a6c8df3a00f9d4d87166ae9cd545d783e0128adef6a16e195de77b82ae4"
},
"flag_pf": {
"category": "flags",
"moji": "🇵🇫",
"description": "french polynesia",
"unicodeVersion": "6.0",
- "digest": "1ace6cc71d130cdf09246297740a911f14828c322e35330cc548ca5975015c23"
+ "digest": "707a68684fd203ddf3dc9d8832b5253977281908747b18fa2c37988d82c40f8c"
},
"flag_pg": {
"category": "flags",
"moji": "🇵🇬",
"description": "papua new guinea",
"unicodeVersion": "6.0",
- "digest": "9c37719d9f51ef31fec0f898d38e522b4253cd00344408e3f660132514efddb7"
+ "digest": "2b8eb063ad2794b3c5acb2c152bcb7de78728139d4a6a5730c4c949bd14b685a"
},
"flag_ph": {
"category": "flags",
"moji": "🇵🇭",
"description": "the philippines",
"unicodeVersion": "6.0",
- "digest": "f1af628cf6d1d290cedef3d564b2386e2d6f14ba4426d3fefc0312cb8772e517"
+ "digest": "86b7c2e87f3c903626b5c64a4c66fc37401ab4d031e3510a2d73f0fe43399943"
},
"flag_pk": {
"category": "flags",
"moji": "🇵🇰",
"description": "pakistan",
"unicodeVersion": "6.0",
- "digest": "61c77f73d2a10a5acb289fadfe0d25d1a1c343e1223bd802099ff4e0e9356521"
+ "digest": "29075418db07bf24338784e697606b55ff0f6fa127458052259de7604ac77b2f"
},
"flag_pl": {
"category": "flags",
"moji": "🇵🇱",
"description": "poland",
"unicodeVersion": "6.0",
- "digest": "38c2c8618446e1f72cf983ab33e736d943f0db7c4cce52a187299e8cec2ea895"
+ "digest": "42667e24a5747a9a27149dacee9681a3759b7e2e38343346d349ca1066f9b6f3"
},
"flag_pm": {
"category": "flags",
"moji": "🇵🇲",
"description": "saint pierre and miquelon",
"unicodeVersion": "6.0",
- "digest": "656be9ea1a79c3885a759c7ce353d338345a198d7939556949affaf5490cb644"
+ "digest": "15059d9274ba5c5bf2723e02a432be7085b13f3fd1b5c631c76a0b857dcec493"
},
"flag_pn": {
"category": "flags",
"moji": "🇵🇳",
"description": "pitcairn",
"unicodeVersion": "6.0",
- "digest": "2792260d8087ab0253b1214c1420f0160ab2eef9afe7315f9e7ff0b87cd15d72"
+ "digest": "807ef63ecc2ab0bf3f858bd5be33200021b543f2e746639dc4afa215480ce7a2"
},
"flag_pr": {
"category": "flags",
"moji": "🇵🇷",
"description": "puerto rico",
"unicodeVersion": "6.0",
- "digest": "c4cfa1f2201dcda9de310a8247e6ce32d2798ae426a14dd70a9ebb00a2804d46"
+ "digest": "a506ccdf7201fd7100accaac6f6138973a365a6adb1f3dc96ca3db20c0531951"
},
"flag_ps": {
"category": "flags",
"moji": "🇵🇸",
"description": "palestinian authority",
"unicodeVersion": "6.0",
- "digest": "197f2ec6294bf0ee4a08cf2f2d1e237ee867c98b3085454a3f42abc955eeb289"
+ "digest": "47f9495970023276191a7d3a76b32b272bb8e046882152871efb3c64345feb31"
},
"flag_pt": {
"category": "flags",
"moji": "🇵🇹",
"description": "portugal",
"unicodeVersion": "6.0",
- "digest": "86a50827963756b5bf471ed9df5b3f2a2058b4c5d778a303414b6b0556e2082b"
+ "digest": "852de5a00f3b14896f3b990092bb890564fd21f6ac0924a9a4b209a52a8bcdb3"
},
"flag_pw": {
"category": "flags",
"moji": "🇵🇼",
"description": "palau",
"unicodeVersion": "6.0",
- "digest": "a6321c47a0cd188fbfdf3b55f17a7170c63080d28d50e4f5463eb1ee09af2412"
+ "digest": "5ba4a0387820031ea77ca1e878b7d40af3d8665ccdcf8c00739a8baba05e8907"
},
"flag_py": {
"category": "flags",
"moji": "🇵🇾",
"description": "paraguay",
"unicodeVersion": "6.0",
- "digest": "1a169e8d8703c510c5a2265b57dbed2f811b03ec375bcb341ab4cd0b100a9dd6"
+ "digest": "6055729c4933faaf91d052d95dd4bc939126413affc263c0cb30a0caf4ff3f87"
},
"flag_qa": {
"category": "flags",
"moji": "🇶🇦",
"description": "qatar",
"unicodeVersion": "6.0",
- "digest": "de6283965cd98a244b7fa6288174f9ff0d8feb497f191f2e4ab3b690138a3d5d"
+ "digest": "9dc210aa3dec2400ee6d988ca72c0a0a7f5826cd80ddb64601b59f0f26ff96c8"
},
"flag_re": {
"category": "flags",
"moji": "🇷🇪",
"description": "réunion",
"unicodeVersion": "6.0",
- "digest": "260e1b97abc1562e5a73d7e53652ffed8059fc9b1c969741c466f48ec6ab0e80"
+ "digest": "6e4fa6fcb92a1342bcd12edbd11cb572d68c7070451204e5faa9e8eaeef13cbd"
},
"flag_ro": {
"category": "flags",
"moji": "🇷🇴",
"description": "romania",
"unicodeVersion": "6.0",
- "digest": "6d648e03955fa2a9fd2bad6f60ec96d3e20ee57f5855f3721a4d4e0c8e99f95c"
+ "digest": "3c31155f57c6734b1ceb048eb147bd95e218902bd2b1525e1c1bfb7ad5aa98f6"
},
"flag_rs": {
"category": "flags",
"moji": "🇷🇸",
"description": "serbia",
"unicodeVersion": "6.0",
- "digest": "95cd5e197ed364e403eeb7f1d18a83487d89166910ba8119ea994e5e19d6a7ee"
+ "digest": "d26f808ff881c57e95c4ee23e5f33bc0d35e30c6e68f4c8fbda977f932471687"
},
"flag_ru": {
"category": "flags",
"moji": "🇷🇺",
"description": "russia",
"unicodeVersion": "6.0",
- "digest": "a4a81617a59d9eaf3c526431ca6f90ed334a7c1f516bf70cbd3f1fdc6e6103d7"
+ "digest": "d3379379f152666108348229ea530a5276f49e9c5cf4611feddbbb7ffd9a88b7"
},
"flag_rw": {
"category": "flags",
"moji": "🇷🇼",
"description": "rwanda",
"unicodeVersion": "6.0",
- "digest": "7a369f60db0876ffef111c319a3e8c9eaed620c875c51b98ed9ad5207b836dca"
+ "digest": "cb70230a12a97f08029330418b35b26ad2ec9ed451bf3f3a969dfcb038a06c7e"
},
"flag_sa": {
"category": "flags",
"moji": "🇸🇦",
"description": "saudi arabia",
"unicodeVersion": "6.0",
- "digest": "b249fbfd7ed415943f60bbd841965cf721979f960ccbe09396aebac1eca913d7"
+ "digest": "0a95fabb0f1e1bb49f8a013bbf2f54b5afbde8706d9f82099d984d6f4668d5db"
},
"flag_sb": {
"category": "flags",
"moji": "🇸🇧",
"description": "the solomon islands",
"unicodeVersion": "6.0",
- "digest": "526b411260024ea7b6ea6c47f2549345c6cc6960e9a29bfa9aaec0772664d2dc"
+ "digest": "32d20f460f322238e5ed9e30b853d204b0987816353e7ca6674a82ac8b6ec970"
},
"flag_sc": {
"category": "flags",
"moji": "🇸🇨",
"description": "the seychelles",
"unicodeVersion": "6.0",
- "digest": "d036b0d068745926120eaf746fa2e4433306e2e14c6b540d0cd6265e34471056"
+ "digest": "99b03abf840b9bbbc7e69dc4a7075c6bd850350199faa4af0883c1fce719748b"
},
"flag_sd": {
"category": "flags",
"moji": "🇸🇩",
"description": "sudan",
"unicodeVersion": "6.0",
- "digest": "889615bdb9b1f9c59c5f83ed4d22d54a0ed5dd5de263e729c58544cb06c55885"
+ "digest": "b989a3e33109c6fc69cd1260bd0df28b7b20ed0f320a00c18ca1b20eb878099e"
},
"flag_se": {
"category": "flags",
"moji": "🇸🇪",
"description": "sweden",
"unicodeVersion": "6.0",
- "digest": "f471d80cfff340960a752c8c152ed4fb482df2a3712b0a56dfab31b9b806926a"
+ "digest": "dc98edc1ec1feb22a19a256157a7d567f5e9bec09dce3e3b4e4a4a7a46c0f013"
},
"flag_sg": {
"category": "flags",
"moji": "🇸🇬",
"description": "singapore",
"unicodeVersion": "6.0",
- "digest": "82f58a09f98593cc87e545f7e5c03d2aedaf82e54e73f71f58c18e994c3085ac"
+ "digest": "83a53836145d55a1ff08e64f86d9e998d83f26ee5d30e9a5039fa516805625a9"
},
"flag_sh": {
"category": "flags",
"moji": "🇸🇭",
"description": "saint helena",
"unicodeVersion": "6.0",
- "digest": "53914b1fa8c1b4f30bae6c1f6717f138fb4dbf482c3e20e33f7aea4ecfc0438d"
+ "digest": "a218433c33e93c2dafc2f7f6ce0bb8aa1c513dd680257d08381137cfaf2c020a"
},
"flag_si": {
"category": "flags",
"moji": "🇸🇮",
"description": "slovenia",
"unicodeVersion": "6.0",
- "digest": "65d491daa69f9a11cec9ccc4df3a669f12ef95a5c312137776d4472719940ba3"
+ "digest": "ed5b1ce703396cad861aa4faf2bc3a990f33df80c7b5021e5bc98fc9056a0de8"
},
"flag_sj": {
"category": "flags",
"moji": "🇸🇯",
"description": "svalbard and jan mayen",
"unicodeVersion": "6.0",
- "digest": "bbf6daa6174c6fbbbf541c8274f31b6757c3a16007c2687015ea041fd1e2c6b6"
+ "digest": "473f79dc252e5029ce80980408fce347e31d1902ebf278ddc5d30006e8e83d45"
},
"flag_sk": {
"category": "flags",
"moji": "🇸🇰",
"description": "slovakia",
"unicodeVersion": "6.0",
- "digest": "d4fd03eca5bd3c9fb324ee04fae37c9a2d852bac8335369e3e720ef9b98fff36"
+ "digest": "cea0ae548486af5613fde64c6e493eb8a836102cdb09f093955e0c09ec0c5b9e"
},
"flag_sl": {
"category": "flags",
"moji": "🇸🇱",
"description": "sierra leone",
"unicodeVersion": "6.0",
- "digest": "1455c98c11c248623d82be5484ab1c4dcd1dae449adc393eb1aa2d8c74aa3f02"
+ "digest": "07e43bde4854dd09b44cd5d333136af2c112a4488cc02fae900f378f34414807"
},
"flag_sm": {
"category": "flags",
"moji": "🇸🇲",
"description": "san marino",
"unicodeVersion": "6.0",
- "digest": "daec5864ac50c625d7bf49d6c1a170a094cf0d1b9a0bdf62a62406e7ec500a94"
+ "digest": "86e65252b3ae31e755c0e9794a0dc3310992cacd374f15e8537d53d61e52a20e"
},
"flag_sn": {
"category": "flags",
"moji": "🇸🇳",
"description": "senegal",
"unicodeVersion": "6.0",
- "digest": "4e4d43c467e5eb84c70f535f37f4f468319bd4b06c6ec3db3b54f69efdafd334"
+ "digest": "17f3259dd6c8599b689034abb6bd4dd9b911c6370d370f3ec232c114150dfbe3"
},
"flag_so": {
"category": "flags",
"moji": "🇸🇴",
"description": "somalia",
"unicodeVersion": "6.0",
- "digest": "c1434dca361563a8e3ba88f1ad19c3f6c9cbb8f3ebc17ce128fde2351ff67d0c"
+ "digest": "5610be7800bff418c6c03ac42a0fe8699df6c2d21b7e0cf370c8d554a38735cc"
},
"flag_sr": {
"category": "flags",
"moji": "🇸🇷",
"description": "suriname",
"unicodeVersion": "6.0",
- "digest": "f3c6bfee2a052f03d56ba917b88595450cef111ffa9e92c7f39ef8c3c3bd12d1"
+ "digest": "a97c581cb85e2eee3cee728e6812485ac53f33279b4998f054de7ec68b802238"
},
"flag_ss": {
"category": "flags",
"moji": "🇸🇸",
"description": "south sudan",
"unicodeVersion": "6.0",
- "digest": "c0ed7e4f41206f5363e8ebdc6c3f28080e2f07d99e6fb73c1f6226d83310e69d"
+ "digest": "5f5fa6ccd8e15a2e7026dc5f16b409fb340ec136896569b62bc0f5008bd650f7"
},
"flag_st": {
"category": "flags",
"moji": "🇸🇹",
"description": "sao tome and principe",
"unicodeVersion": "6.0",
- "digest": "b022ae5d6885e28c6e9c83c17dd0c24c731d4f3d5773c49051768cdd4df51330"
+ "digest": "050ae7266ee72c6bf145e26287307f9538ce4f0869780d0c952e974c2a587687"
},
"flag_sv": {
"category": "flags",
"moji": "🇸🇻",
"description": "el salvador",
"unicodeVersion": "6.0",
- "digest": "5bafdd04d243ee3f3998f4ec0a3d03ff5a3975e771b1f94f89d7713193d7a242"
+ "digest": "825c738f84fd15979f9d94e05bab37a81101d4457030a1b29e6b6c1d5b907cd2"
},
"flag_sx": {
"category": "flags",
"moji": "🇸🇽",
"description": "sint maarten",
"unicodeVersion": "6.0",
- "digest": "fb92e9f514bcc2f7abbd4e146edde50f030c940c833f184618cbb48e56af22bd"
+ "digest": "67da61f8e366430e86b7a1c63d9434445d0b7a3234ca1b928d2be5a228bd63bf"
},
"flag_sy": {
"category": "flags",
"moji": "🇸🇾",
"description": "syria",
"unicodeVersion": "6.0",
- "digest": "ee330da644d4ce1fdba98be5eaab5054aed8d91a34ab617199a4b2b77f62a10b"
+ "digest": "56cfb878960e6fbe54d75ad3111e5b5fe2359ca66e47219d4a69b012e43337a4"
},
"flag_sz": {
"category": "flags",
"moji": "🇸🇿",
"description": "swaziland",
"unicodeVersion": "6.0",
- "digest": "7fe0c7429efd9682cc39e57f4bba8d1491d301643ba999d57c4e1bc37517ed64"
+ "digest": "d1f91b0e7d8846c9a4612810d63577c72cd921852afa5c2b50c2df44c2f530b2"
},
"flag_ta": {
"category": "flags",
"moji": "🇹🇦",
"description": "tristan da cunha",
"unicodeVersion": "6.0",
- "digest": "b47e245a2708072a4dbaf190c9606baa4daf02e51627eeae6f20c3b4c95024c0"
+ "digest": "83ebdc5f9e525796348a810b90e8cc58680defdaebb6805182cf34ff1716dd07"
},
"flag_tc": {
"category": "flags",
"moji": "🇹🇨",
"description": "turks and caicos islands",
"unicodeVersion": "6.0",
- "digest": "18cfff14c2503b9d24c91c668583d4a14efb17657d800eca86ae49b547c9da5c"
+ "digest": "494af08aafc701e0c8aed946e8b3f195da6798d8a650ada9f8ca24c02c3fc1da"
},
"flag_td": {
"category": "flags",
"moji": "🇹🇩",
"description": "chad",
"unicodeVersion": "6.0",
- "digest": "73d1db3365736915c4cdf9ba9343d9fd78962203b60334e8f3724d4b330b17db"
+ "digest": "d7b4b921d6d13b3932e13c56ddde2e1c0d695a748ea41cc4b9c2f7f49abef4ff"
},
"flag_tf": {
"category": "flags",
"moji": "🇹🇫",
"description": "french southern territories",
"unicodeVersion": "6.0",
- "digest": "3bffeb4bc9ceb9cbb150de88e957b6e46509862ca7d616d5693124af084eb435"
+ "digest": "bf98d7139c4505d960d15746e6559b2ebc33192bee1c45e75784f45b1b500844"
},
"flag_tg": {
"category": "flags",
"moji": "🇹🇬",
"description": "togo",
"unicodeVersion": "6.0",
- "digest": "eb13a0e85baf73326f3ae3bc75e8406eca42000d7e42b0641120e64c0ab7ebaa"
+ "digest": "d7277859a1cce9a4f1441edc97ec4b1a58f98d3443646a4c4ca9d19d8714ecf6"
},
"flag_th": {
"category": "flags",
"moji": "🇹🇭",
"description": "thailand",
"unicodeVersion": "6.0",
- "digest": "a4e42efa4bb94e90f3a92ae9ce14affaacd3a142c1e0da40d8cc839500e771fd"
+ "digest": "2c1e7626469da34f8b09c845015402f1d8c372228d091bdf809ec375202eb87f"
},
"flag_tj": {
"category": "flags",
"moji": "🇹🇯",
"description": "tajikistan",
"unicodeVersion": "6.0",
- "digest": "ff926fa3e86e095683a61c4754355a5b4dd0ecb74393306bd791d130fd1a909d"
+ "digest": "160707c20084dd076449800bd38391a2708251952e636ac542d69b15c592eb27"
},
"flag_tk": {
"category": "flags",
"moji": "🇹🇰",
"description": "tokelau",
"unicodeVersion": "6.0",
- "digest": "3fa732d457ded6c83cd5f73d934f64c4e687eb0cde7c157d2fdcdccaf3b5fb52"
+ "digest": "468b86b6eb8ac0a80fd696e3b7ceba26c9edbeb89ca459d4ef1aa66e7687ebd3"
},
"flag_tl": {
"category": "flags",
"moji": "🇹🇱",
"description": "east timor",
"unicodeVersion": "6.0",
- "digest": "0ec2a4d22fb832060693089e518bbe370a4e13bfc28748f110fc13726409f473"
+ "digest": "2eae18e02ac4ba9a709d8d23a2a4852b01f1231cf0c646f29d3b4f5794cd45b9"
},
"flag_tm": {
"category": "flags",
"moji": "🇹🇲",
"description": "turkmenistan",
"unicodeVersion": "6.0",
- "digest": "b4724aa7ad13352f16a0936e61cbb85f0bd147583fc66597aff7e8ee7cf19c21"
+ "digest": "f910c8937ed0c18d5ab6f1c00fa0e565d28cc090708d045e99d4fac98210bfeb"
},
"flag_tn": {
"category": "flags",
"moji": "🇹🇳",
"description": "tunisia",
"unicodeVersion": "6.0",
- "digest": "5ab308ffdde40f504d6ee080817bbddbe4f3f4ddb71f508c75e0144a8c8044d9"
+ "digest": "cde7120807046adf1fec022caa62e2ddc4060982a0fa4a40f01294f8ac6f1fc4"
},
"flag_to": {
"category": "flags",
"moji": "🇹🇴",
"description": "tonga",
"unicodeVersion": "6.0",
- "digest": "75b7e7198fa42f87986882b8ca251a229afcaa0a1188ae7b9f5ece87dc31a723"
+ "digest": "e2c36fe8836a973915f4f90f9912a36f7a1b94060f9278b75122f897305896dd"
},
"flag_tr": {
"category": "flags",
"moji": "🇹🇷",
"description": "turkey",
"unicodeVersion": "6.0",
- "digest": "9cc48a8f8fa9c17c1627272f68d4740da0e7ce17a2cf8c6b5c08cc9b95e1390c"
+ "digest": "b9044c830bf8424c4882c2325d5c98d31709d1d33d62e82a37a08ba09bed8826"
},
"flag_tt": {
"category": "flags",
"moji": "🇹🇹",
"description": "trinidad and tobago",
"unicodeVersion": "6.0",
- "digest": "f9e63543121bb3cd2e41bc7b0c2c4ba662bc1cc0520b79fc4e201ec6456fdf59"
+ "digest": "abb12ae217657b3cfdc204adec7204d2e3c6c5b51af62645f5e81ee251fcdc5c"
},
"flag_tv": {
"category": "flags",
"moji": "🇹🇻",
"description": "tuvalu",
"unicodeVersion": "6.0",
- "digest": "6431e5f06cc7995ae7208c429ecf39339b545854cb6d6b7447f465fe53614dfc"
+ "digest": "70e00fe3b89c1d5dba1edb8e29e1e1cbbf21357a11b7410b1867fcb7cd25a01c"
},
"flag_tw": {
"category": "flags",
"moji": "🇹🇼",
"description": "the republic of china",
"unicodeVersion": "6.0",
- "digest": "8395ab3c6a595023b006518a5345ac3612f2893d3a8f011b7e5802414236b03c"
+ "digest": "b14215e4a8167cae265fd180ca2fb95ff13fc2447a3091cf82dd6616a984a911"
},
"flag_tz": {
"category": "flags",
"moji": "🇹🇿",
"description": "tanzania",
"unicodeVersion": "6.0",
- "digest": "716181733cd9ac7a8f51a9a64bc5d21020e8112f6768e8c49c4d651a3ee0b8a4"
+ "digest": "a775b26da1248510227e5b90813125267aef6907b39a9361b0589507320f69dc"
},
"flag_ua": {
"category": "flags",
"moji": "🇺🇦",
"description": "ukraine",
"unicodeVersion": "6.0",
- "digest": "304570736345e28734f5ff84a2b0481c2bb00bf29d9892bd749b57dec7741e30"
+ "digest": "89fc6fb053fb2175e44a8f7410cc80115ddf5a701c19714bd1d9a8b8ba537471"
},
"flag_ug": {
"category": "flags",
"moji": "🇺🇬",
"description": "uganda",
"unicodeVersion": "6.0",
- "digest": "a1bafb74c54ee8c92cb025b55aebdb6081eec3fda6a7f86f2ee14d1b801a8e9c"
+ "digest": "af9014731cbc4b019a21a2f8f47accfc421f7ca0b95b3b814d4c508d0ca2b2bf"
},
"flag_um": {
"category": "flags",
"moji": "🇺🇲",
"description": "united states minor outlying islands",
"unicodeVersion": "6.0",
- "digest": "b3c9ac72211f481f50cde09e10b92aa03b1ea90abf85418e60a35b84963273ee"
+ "digest": "113f0c1110dccc6f5c415e357b59ee13322230d67331f3cd3a0a8780d5772833"
},
"flag_us": {
"category": "flags",
"moji": "🇺🇸",
"description": "united states",
"unicodeVersion": "6.0",
- "digest": "da79f9af0a188178a82e7dc3a62298fa416f4cfbcae432838df1abebca5c0d63"
+ "digest": "113f0c1110dccc6f5c415e357b59ee13322230d67331f3cd3a0a8780d5772833"
},
"flag_uy": {
"category": "flags",
"moji": "🇺🇾",
"description": "uruguay",
"unicodeVersion": "6.0",
- "digest": "8348e901d775722497ee911c9c9b4bd767710760c507630a67ecb6d47cc646c7"
+ "digest": "5466414a8f1459172ef9956465abd15a4a4cd9cff1ebb730562e5d87c16d7074"
},
"flag_uz": {
"category": "flags",
"moji": "🇺🇿",
"description": "uzbekistan",
"unicodeVersion": "6.0",
- "digest": "2a1dc1e9469e01c58ea91f545ef3fe0bdfe5544a73a80407f8960d01b1e5db5c"
+ "digest": "3c637d904a47b2a7ffd0a800143fd5c18ae3ef1f7a2503d65e4340a5a12e1068"
},
"flag_va": {
"category": "flags",
"moji": "🇻🇦",
"description": "the vatican city",
"unicodeVersion": "6.0",
- "digest": "0e8134ec94bff032bfc63b0b08587d5298c9b7f31edd5a5b35633ae911434e61"
+ "digest": "2c4c0976ea37173ae352f0ae57801dacdcb0adc158ef1b66bd24c9fcb85762d9"
},
"flag_vc": {
"category": "flags",
"moji": "🇻🇨",
"description": "saint vincent and the grenadines",
"unicodeVersion": "6.0",
- "digest": "e0290e1be72c8939ee6c398f00a107703b21b97d91b9bf465e553ffbf00304a7"
+ "digest": "6728d4e99bf3ecaf01fd8bc5332abce19a513a9454c59457409ba2664c2a0152"
},
"flag_ve": {
"category": "flags",
"moji": "🇻🇪",
"description": "venezuela",
"unicodeVersion": "6.0",
- "digest": "76a6a6c2353def1f984d1a6980831e63f3aea5af2201b574197834e7c203d57a"
+ "digest": "0f666b1a4d4006bdf5cf06c2e777a54d00e515fec3f90c77fcee53f045459e54"
},
"flag_vg": {
"category": "flags",
"moji": "🇻🇬",
"description": "british virgin islands",
"unicodeVersion": "6.0",
- "digest": "56fc9317b8dd62cccc60010819f8b895dd4569a9b06368a9250f815c39177b8a"
+ "digest": "1fac6a3edbcea9aced505e84a83c77e59199797e30719770f00fe44ca480a5f2"
},
"flag_vi": {
"category": "flags",
"moji": "🇻🇮",
"description": "u.s. virgin islands",
"unicodeVersion": "6.0",
- "digest": "2526a3e13b8ccd301f0763580430898c227bd209e3ce482c7951140b28948375"
+ "digest": "42674c2856fecd45a505f1505b9dc2a005c481a2f5f90e19ba15ab822d24385e"
},
"flag_vn": {
"category": "flags",
"moji": "🇻🇳",
"description": "vietnam",
"unicodeVersion": "6.0",
- "digest": "0cf6b9896bbe4da8ed7718d0abfd56cef1a8321e26f89d3ad1b48488eaffb7a5"
+ "digest": "1d49a9f4117b01c18c8ef9572025e2ed2b0e0b730f85861d2eed036754577f3e"
},
"flag_vu": {
"category": "flags",
"moji": "🇻🇺",
"description": "vanuatu",
"unicodeVersion": "6.0",
- "digest": "9dfa282ce1aafc62beacab76e1fc19a141c8bdeaa30898f69b083067b775d362"
+ "digest": "00092aea36521743ebea4c1ab72208e331c57185b35efc5a78cc8e974eaa5578"
},
"flag_wf": {
"category": "flags",
"moji": "🇼🇫",
"description": "wallis and futuna",
"unicodeVersion": "6.0",
- "digest": "a0124683aa88cd7da886da70c65796c5ad84eb3751e356e9b2aa8ac249cf0bf9"
+ "digest": "9c3a87c9a8d72e7158ff64fd73754dab8df3c36ae7ffb1fac8e6326cac226995"
},
"flag_white": {
"category": "objects",
"moji": "ðŸ³",
"description": "waving white flag",
- "unicodeVersion": "6.0",
- "digest": "d9be4b7ceb8309c48f88cfd07a9f7ce6758ea6e620e73293cf14baec03ca381c"
+ "unicodeVersion": "7.0",
+ "digest": "9793e7ce774497489f7b6023b7b2d51ce01d83dda21b0903432883905cd5aa0b"
},
"flag_ws": {
"category": "flags",
"moji": "🇼🇸",
"description": "samoa",
"unicodeVersion": "6.0",
- "digest": "53addd0dc304a3c8893389ed227986ef2431828b8c071926aa09f9efd815b649"
+ "digest": "bc955c3e92aad4130846ac341a65125ec83755aeb33737e37bc22e840c278477"
},
"flag_xk": {
"category": "flags",
"moji": "🇽🇰",
"description": "kosovo",
"unicodeVersion": "6.0",
- "digest": "eba1a832e489e1c2734e773e685df5d128271fa5559d23c060e68be067bf6469"
+ "digest": "bb1dd44a79677f4205578cfc530addf504a2e9890abc7493457fac2dbe39e025"
},
"flag_ye": {
"category": "flags",
"moji": "🇾🇪",
"description": "yemen",
"unicodeVersion": "6.0",
- "digest": "edfa14266785042b6d5fe0f64fafa630b16a3ee7d010501de7cc8554c959afb0"
+ "digest": "337389aadcf666ab1a5eda2bcde8f4cb547282324457c8e5279da9897a24bf7a"
},
"flag_yt": {
"category": "flags",
"moji": "🇾🇹",
"description": "mayotte",
"unicodeVersion": "6.0",
- "digest": "472ebc676b5d31dec2ac5e02ce69014a3dd94609d30a95f39f3a752f49c85e8b"
+ "digest": "6e063cf7f6efd74268b56bfbfcf056cf30b37036ff16c8b39421289dc4d9a632"
},
"flag_za": {
"category": "flags",
"moji": "🇿🇦",
"description": "south africa",
"unicodeVersion": "6.0",
- "digest": "dad162942a43392b4cff6929bd5cbf58c382a03dbc0e552f03c07ad2d8ff08ce"
+ "digest": "ee7f95de38ae72b91c8f67b731ef8aab1dac790a8fb8777d011078ba782df3bf"
},
"flag_zm": {
"category": "flags",
"moji": "🇿🇲",
"description": "zambia",
"unicodeVersion": "6.0",
- "digest": "1521ecaf1d1fdc8c15f0c96a6b04e6d4050f26f943a826b3d3d661f6ded6d438"
+ "digest": "2074a55a2c71d7a040b30b8c1132ca3cec7a85139e310083c4af0e71c5131808"
},
"flag_zw": {
"category": "flags",
"moji": "🇿🇼",
"description": "zimbabwe",
"unicodeVersion": "6.0",
- "digest": "46d05b597c5c77c8e2dc7bd6d8dd62ebca01bc9c9dc9915dafe694ca56402825"
+ "digest": "5c78e2789c261c2e8fddb8a790d5b6e0dfb4c4922de54a8fa26b1ecdc89eb58d"
},
"flags": {
"category": "objects",
"moji": "ðŸŽ",
"description": "carp streamer",
"unicodeVersion": "6.0",
- "digest": "f860aa4df587cf140c3e9735bbd101e9fd5a1bfcea42e420d85ac0a9877fa21d"
+ "digest": "fe687c07453ae2869f11816bc2c604c67ba8c3754e597ce6871289cc358253c1"
},
"flashlight": {
"category": "objects",
"moji": "🔦",
"description": "electric torch",
"unicodeVersion": "6.0",
- "digest": "e929bbe76e0fd2dc5bd6476858a0bbc717fd21467710435d35d80efb38033d73"
+ "digest": "2fd24a87d1609384d671d0d6b6c5d27afde221e28e0ce1443f09b8ab96200329"
},
"fleur-de-lis": {
"category": "symbols",
"moji": "⚜",
"description": "fleur-de-lis",
"unicodeVersion": "4.1",
- "digest": "ebf49007f367dc05580e9dab942e93e9dda12fa1dc2caa410ac7f8d8cd55d2a3"
+ "digest": "aad1d75ba9bce98d639b82b8c2f6481947edec6ceaa48cb890f2503eb2964202"
},
"floppy_disk": {
"category": "objects",
"moji": "💾",
"description": "floppy disk",
"unicodeVersion": "6.0",
- "digest": "4ee0b5bba41b9e301ed125d3ee1c263bef171ca499e6e1b89276b09af2bc03a0"
+ "digest": "24b4d593478f5619160a95967deb34662d0b1a3f6da96f84910d749914179e13"
},
"flower_playing_cards": {
"category": "symbols",
"moji": "🎴",
"description": "flower playing cards",
"unicodeVersion": "6.0",
- "digest": "edba47c2e3051b2c7effd98794ec977174052782edcb491daec82a2b0d853869"
+ "digest": "814948cd185c22b3a394a5bb15924ddf6cf07b612658bd79c5192cd453057681"
},
"flushed": {
"category": "people",
"moji": "😳",
"description": "flushed face",
"unicodeVersion": "6.0",
- "digest": "e759d46bab92af5494d78b6c712c06568759afe397e7828ca0a0de1e3eab0165"
+ "digest": "d29c62b5892744d9d95cd876c703d079f1e8eed6091e51291e01667b8f4a6c7a"
},
"fog": {
"category": "nature",
"moji": "🌫",
"description": "fog",
"unicodeVersion": "7.0",
- "digest": "0cbd4733961d30fe0f40f95dd1f37254aebbef26f82dd18ad2000e799eb2898e"
+ "digest": "d216852000dd40e0f8b4c407368631b60a56d8eac32832461b303cc8f4d47488"
},
"foggy": {
"category": "travel",
"moji": "ðŸŒ",
"description": "foggy",
"unicodeVersion": "6.0",
- "digest": "bc3631a4e9e8473b92e842008937add2cd9ffad5b7d772ce759fb5ff6c0e3dca"
+ "digest": "0ccc53edb0aba767c59682d74a29221f829297e334120d3b90e3030054698ec7"
},
"football": {
"category": "activity",
"moji": "ðŸˆ",
"description": "american football",
"unicodeVersion": "6.0",
- "digest": "ebd790471c3a28d3077818e3b31d915ffe443e06e299bc5cf0dd2534d080634c"
+ "digest": "aefdff9cd010c9d82e2cdd83c4430db38bf311bfeac7f86583b122cba146c73f"
},
"footprints": {
"category": "people",
"moji": "👣",
"description": "footprints",
"unicodeVersion": "6.0",
- "digest": "85bbf2bc0ae8e6259d83a06f513600095d7fcfc44372670f5b2405d380b78811"
+ "digest": "43a8daa470e070c1cfdf541a502076f0a258e8cde2f707ad842bc24e499ad69c"
},
"fork_and_knife": {
"category": "food",
"moji": "ðŸ´",
"description": "fork and knife",
"unicodeVersion": "6.0",
- "digest": "f228accd36ddccb4ec636207c19d7185191ec79723b780a1bd5c3d00a4b1ef3b"
+ "digest": "a22c9fabbcae702d4043e4bfab3f15cd96e585a291f93f820f01723c0465410c"
},
"fork_knife_plate": {
"category": "food",
"moji": "ðŸ½",
"description": "fork and knife with plate",
"unicodeVersion": "7.0",
- "digest": "ec6be99dac8efd3d145807fa60d2b6d8f6d3c02cb95552b55cc0fac39a4db48e"
+ "digest": "3161044fa7ac67ef1f09c35ecde7ca8eca471a36e3e67ccbaa3a42f35dd67f16"
},
"fountain": {
"category": "travel",
"moji": "⛲",
"description": "fountain",
"unicodeVersion": "5.2",
- "digest": "87043f9256e1d4615159307fcfd21bf6ae2aba0bada7de2bd50d7d6f2ab82395"
+ "digest": "f940be34d7db82c7dcf5e4343c05f74e5834f1123edd0382b9aa0c3b8b72e90d"
},
"four": {
"category": "symbols",
"moji": "4ï¸âƒ£",
"description": "keycap digit four",
"unicodeVersion": "3.0",
- "digest": "c2c82a966bbb599aae557d930a4fc42604f2081aa45528872f5caf4942ee79d9"
+ "digest": "10495232058ba7d32dad0aae87f30c50a96a95055dd4fa0f278fcc8c1aa24d84"
},
"four_leaf_clover": {
"category": "nature",
"moji": "ðŸ€",
"description": "four leaf clover",
"unicodeVersion": "6.0",
- "digest": "ebee16e86bc9be843dfc72ab5372fb462f06be4486b5b25d7d4cac9b2c8b01c8"
+ "digest": "a9ca1028812de7da08319eb0403b28951d381ace771b1050e90d1aa05e62baef"
},
"fox": {
"category": "nature",
"moji": "🦊",
"description": "fox face",
"unicodeVersion": "9.0",
- "digest": "e9903cb0396f7e49bdd2c384b38e614c13bfa576b3ecc1ec7b9819e4a40d91d1"
+ "digest": "0d98c8fd904dceaa53041b5c8dcf7c357805712ed547668ee53ab48808c6255b"
},
"frame_photo": {
"category": "objects",
"moji": "🖼",
"description": "frame with picture",
"unicodeVersion": "7.0",
- "digest": "d5074f748a15055ec1fb812c1e5e169e6e3cc73c522c54be1359b0e26c0fc75c"
+ "digest": "bcc4eade7fb066c301457bfd79daae84f0b2a4aa56c71dcb6bcb8fb76c2c4a96"
},
"free": {
"category": "symbols",
"moji": "🆓",
"description": "squared free",
"unicodeVersion": "6.0",
- "digest": "9973522457158362fc5bdd7da858e6371e28a8403d1ef9e4b6427195c7f72cfa"
+ "digest": "a3afee0d4e8da8f6fc2dc42b453b6f0aa9b6e159e24fce1afa04e92b74a69fc4"
},
"french_bread": {
"category": "food",
"moji": "🥖",
"description": "baguette bread",
"unicodeVersion": "9.0",
- "digest": "47518a4312f57207b8e8c38188d4a2bd8b16830a885cfcf2d281cfab50c1bc6e"
+ "digest": "356771456e476bfc85b9ba08b8bd8473fef0e8045af88bafe563aed815cba8e9"
},
"fried_shrimp": {
"category": "food",
"moji": "ðŸ¤",
"description": "fried shrimp",
"unicodeVersion": "6.0",
- "digest": "0792bdc4484852de970c8f43bc3a1a339dc0e48090ec77d6de97cbfcdd17f9e1"
+ "digest": "77985671090380d5e36b5c1bed476dcfe8e6e09d7a3f090aaae534be6297ecfd"
},
"fries": {
"category": "food",
"moji": "ðŸŸ",
"description": "french fries",
"unicodeVersion": "6.0",
- "digest": "47915aea67251d358d91a0e4dc3dcc347155336007d6b931a192be72a743b4e9"
+ "digest": "492b7d015ce5bcd3b9674049e5421cd2c65451c65a175f2e7ffca391b178d1e5"
},
"frog": {
"category": "nature",
"moji": "ðŸ¸",
"description": "frog face",
"unicodeVersion": "6.0",
- "digest": "d024b2ce771df64040534fb0906737d18b562bc3578dee62c2f25ec03c7caffd"
+ "digest": "f1b86d108560eb022ed026b7158477f664bdebe2b313bf49e4bd4f3c79278bf3"
},
"frowning": {
"category": "people",
"moji": "😦",
"description": "frowning face with open mouth",
"unicodeVersion": "6.1",
- "digest": "c01af48537b0011d313d8f65103e1401fce4f5c0269c68e0e9806926c59acc44"
+ "digest": "615dc050d755f9fb9aa325fba6efc812ec78984dd282c8e81e4b0bf2ffb00b79"
},
"frowning2": {
"category": "people",
"moji": "☹",
"description": "white frowning face",
"unicodeVersion": "1.1",
- "digest": "6568ee393b950c852d440112e86908c456b89fb7780e27778c5fcec168373fbf"
+ "digest": "aa6b9f39cd2511d918a395f1e363a34642761cdc7f5a0170405b40455a47f0b6"
},
"fuelpump": {
"category": "travel",
"moji": "⛽",
"description": "fuel pump",
"unicodeVersion": "5.2",
- "digest": "105e736469f19911b8bab4ab6d29f949ded4b061b54e3dd763726577d6453095"
+ "digest": "7c8c6c22de83e52ef399607cd6b17b535bf5e3a0aa29a9739f20c6bfe64d52d6"
},
"full_moon": {
"category": "nature",
"moji": "🌕",
"description": "full moon symbol",
"unicodeVersion": "6.0",
- "digest": "aaa87f4676a5aaa29c1b721a3b582e89db6c1f35a25c52e4b480bd193ef39c43"
+ "digest": "094a0a8bbf01f188d48c6bd1bbb035be622f2046d8b0c1a1252a96424e95d856"
},
"full_moon_with_face": {
"category": "nature",
"moji": "ðŸŒ",
"description": "full moon with face",
"unicodeVersion": "6.0",
- "digest": "05c4b9c339fcdf81ae67027641522baa99c370d87873ff4c8133b8349e627e33"
+ "digest": "aeccdf5baf685650ee34da23f14cb4d659598c44c260a8f549489cbed1d46058"
},
"game_die": {
"category": "activity",
"moji": "🎲",
"description": "game die",
"unicodeVersion": "6.0",
- "digest": "00d19ce8e21dba2cdfeb18709fa8741f3af9d6207f81d5657b68e05e64f105a8"
+ "digest": "9a9eb1efd149aa229f39ffb93605f7c231a149892d9cedfeebc6e15eb7235656"
},
"gear": {
"category": "objects",
"moji": "âš™",
"description": "gear",
"unicodeVersion": "4.1",
- "digest": "c5ba354c0f7a36dce95477091984e352ecc59af8c9f26a94ad8e296dc042b9de"
+ "digest": "c752b015d8b37be10c77820e951f9d999ac5860a7a0c453c5eceaf0eb442103b"
},
"gem": {
"category": "objects",
"moji": "💎",
"description": "gem stone",
"unicodeVersion": "6.0",
- "digest": "180e66f19d9285e02d0a5e859722c608206826e80323942b9938fc49d44973b1"
+ "digest": "abb9f5097963624e3e1e0ef7dd973a264910c22baa549d24f396defc0fcd8ef6"
},
"gay_pride_flag": {
"category": "flags",
- "moji": "ðŸ³ðŸŒˆ",
+ "moji": "ðŸ³ï¸â€ðŸŒˆ",
"description": "gay_pride_flag",
- "unicodeVersion": "6.0",
- "digest": "924e668c559db61b7f4724a661223081c2fc60d55169f3fe1ad6156934d1d37f"
+ "unicodeVersion": "7.0",
+ "digest": "f23d3e6d08cda225b5778b7f2ffe7ef6ab32709f43bd1e7ccb453ee660f64fa1"
},
"gemini": {
"category": "symbols",
"moji": "♊",
"description": "gemini",
"unicodeVersion": "1.1",
- "digest": "278239c598d490a110f1f3f52fc3b85259be8e76034b38228ef3f68d7ddd8cdd"
+ "digest": "3ddb938fe1196593b21a3380b20107ea22253c6fcf5b9fccdca6badf7384047b"
},
"ghost": {
"category": "people",
"moji": "👻",
"description": "ghost",
"unicodeVersion": "6.0",
- "digest": "80d528fcf8ef9198631527547e43a608a4332a799f9e5550b8318dec67c9c4d2"
+ "digest": "02e92350f546b637c7070d01b71d84062b6cdc72cde79fce39b41c5945c5ff6c"
},
"gift": {
"category": "objects",
"moji": "ðŸŽ",
"description": "wrapped present",
"unicodeVersion": "6.0",
- "digest": "4061a84a59f0300473299678c43e533341eb965db09597fffc6e221fd7b77376"
+ "digest": "f05374b0464ab426379251722208599f95b4dc00f8ca551b5fbd6cea5ee98ee6"
},
"gift_heart": {
"category": "symbols",
"moji": "ðŸ’",
"description": "heart with ribbon",
"unicodeVersion": "6.0",
- "digest": "5420199b515b9b32c964a3c19d87e07461639e3068a939dae26c6436335c0cee"
+ "digest": "9d747c69520b804e5cf3810475ff764a1d88f9f4e90f2fb3030a85ea35cd63a2"
},
"girl": {
"category": "people",
"moji": "👧",
"description": "girl",
"unicodeVersion": "6.0",
- "digest": "8d2d0b72a91e6e44921b71030ffc4c89c0f50f1364787784afe1e7e568cf1bc6"
+ "digest": "5b6e2d936ee671b82328adbb0d77a8a23ad169aa455f8f3e07a974620d62b698"
},
"girl_tone1": {
"category": "people",
"moji": "👧ðŸ»",
"description": "girl tone 1",
"unicodeVersion": "8.0",
- "digest": "bda12a6b38994a578ee65166bbdd93ea04df4101697b52ed236de8d687df09de"
+ "digest": "34f82173f73d9e3048ffd339c480ae72017be5fb99616f40cb90ca507ce81365"
},
"girl_tone2": {
"category": "people",
"moji": "👧ðŸ¼",
"description": "girl tone 2",
"unicodeVersion": "8.0",
- "digest": "de7a0925c30b7181a289f71b1a849c1b7751ee8c104e8f2029bd9c2fe3f91c64"
+ "digest": "e1efcff7f827dbea4258ec5cb0b40555266119e1f2e4526c251ea166ec252eb7"
},
"girl_tone3": {
"category": "people",
"moji": "👧ðŸ½",
"description": "girl tone 3",
"unicodeVersion": "8.0",
- "digest": "e41272816db0e642d003dce7cb262e1593a592251f46729f7830f4515149e1f2"
+ "digest": "2589873f9c4792091359126462bfb83d3f14bf1bcf977b834e33d11969c551d5"
},
"girl_tone4": {
"category": "people",
"moji": "👧ðŸ¾",
"description": "girl tone 4",
"unicodeVersion": "8.0",
- "digest": "8d6a4513ecbf08408c0ecc5336767777a2216f7a19437faf9e51f65101822469"
+ "digest": "af208f0ab6e4e26b80d6bb02994ef6f38d9395414e23978973d651c4bc895367"
},
"girl_tone5": {
"category": "people",
"moji": "👧ðŸ¿",
"description": "girl tone 5",
"unicodeVersion": "8.0",
- "digest": "f55e4b16a41b6f5e3c817a301420360ba4486e4e82e1092a56a3e3cc4069087d"
+ "digest": "253012160b7a9a57708377062b43396ef620b9b63784736e1e6180f320715dfb"
},
"globe_with_meridians": {
"category": "symbols",
"moji": "ðŸŒ",
"description": "globe with meridians",
"unicodeVersion": "6.0",
- "digest": "725bebeb3c09a9e3701ebe49e672dcfbf2b73575e05f0821263511577b013b75"
+ "digest": "e85db2d778b99bf7557d48fed2ff9ed1db94a615124b47d85ed5a3eeb5c3b554"
},
"goal": {
"category": "activity",
"moji": "🥅",
"description": "goal net",
"unicodeVersion": "9.0",
- "digest": "7088c432f276ff6f447dc0d431b9062b394fb401de1072fe59ca56267bfd6717"
+ "digest": "e867e3f1d97159e2301c2903bbfab130921490cbf4d5fdc4d5d0a62088dbfda8"
},
"goat": {
"category": "nature",
"moji": "ðŸ",
"description": "goat",
"unicodeVersion": "6.0",
- "digest": "d07e384d08529ddcaddd2710f2ad913e5665dc15d5f99c28e16dadd245a111e8"
+ "digest": "83e2498db2f088b8bfaf7614a543bc691da93eec2d8a156cfdde67e86ccbade8"
},
"golf": {
"category": "activity",
"moji": "⛳",
"description": "flag in hole",
"unicodeVersion": "5.2",
- "digest": "eed79364754eec97855e3c7b584f347ae139d9ddb4eb7fb66c00867610b8f1c1"
+ "digest": "90dbc9461dfb3f37bcf171eedaf1131d4567ceace94a86f21f6e6befd6473a98"
},
"golfer": {
"category": "activity",
"moji": "ðŸŒ",
"description": "golfer",
"unicodeVersion": "7.0",
- "digest": "7d7ecc6e226596f646030a4109c2b0001ef0cc690e4863e450bf5d29e7a90344"
+ "digest": "969e342b2749a357f110ebd60fc3f8e49899e0a0777304f8bb4d03416f076d75"
},
"gorilla": {
"category": "nature",
"moji": "ðŸ¦",
"description": "gorilla",
"unicodeVersion": "9.0",
- "digest": "4a564dc14f8ae5450d094f6410ec7f099a7f07dc5254b6395f44a35527bdb4b7"
+ "digest": "bfd0ef21e14e0e11f426dca6ed062fbc360038df043855dde873bed4cef247bd"
},
"grapes": {
"category": "food",
"moji": "ðŸ‡",
"description": "grapes",
"unicodeVersion": "6.0",
- "digest": "74d1a09ab411234a84d025a2e717e7ec5791bc02aad29853896d21c0f0283c50"
+ "digest": "6df4590ee90aa5dd376597fa8e500ad99b4dacae5ceaad8d0b5c2a4662e09e74"
},
"green_apple": {
"category": "food",
"moji": "ðŸ",
"description": "green apple",
"unicodeVersion": "6.0",
- "digest": "457490e9b2b20894f50768262d63f1021717079da104d4847076b3fa779e9a21"
+ "digest": "7f07991633eb29615cd7da645921adfdf01dfd83186d30f29c9ca02b6ed4384b"
},
"green_book": {
"category": "objects",
"moji": "📗",
"description": "green book",
"unicodeVersion": "6.0",
- "digest": "370f635b200efe5e4a9f17da58bd22500e258e61d17795cef375f19c9a45468f"
+ "digest": "6a638f78d0ccb18907a2606afb45e9d32852fbaeee2e41250432e102b8366984"
},
"green_heart": {
"category": "symbols",
"moji": "💚",
"description": "green heart",
"unicodeVersion": "6.0",
- "digest": "f71e30416d9019873f2ed38ef375c48386424ff60b5a07b89b15dc9e0a3970f9"
+ "digest": "426e89957ea1b6631948c5607f1806695af2a339a27159bf93c4c42a6110595c"
},
"grey_exclamation": {
"category": "symbols",
"moji": "â•",
"description": "white exclamation mark ornament",
"unicodeVersion": "6.0",
- "digest": "2fa1d356e12c17cc4025e43afb6c3070385f677102a35223302fda46c47a9b03"
+ "digest": "75bdc292ebb381f9c5bd236e8298665f3c536d049ea8df735b677f5997dc9df5"
},
"grey_question": {
"category": "symbols",
"moji": "â”",
"description": "white question mark ornament",
"unicodeVersion": "6.0",
- "digest": "e1035bcbf0f66d238ef478ba451f5cf2c51627fbf101ed03bad3b2bf38db8aa2"
+ "digest": "54b5c454718c213942187fe846ee10466d1144050456559e3782799ed631f72f"
},
"grimacing": {
"category": "people",
"moji": "😬",
"description": "grimacing face",
"unicodeVersion": "6.1",
- "digest": "2cedad13b8b2a1d4385ca6fa88a251eb7757a4c65dd6d362267864a01247846b"
+ "digest": "781a6548b4b6e394bfd08d57ad222def3eb28d1f1743c9f305296b6108a93958"
},
"grin": {
"category": "people",
"moji": "ðŸ˜",
"description": "grinning face with smiling eyes",
"unicodeVersion": "6.0",
- "digest": "634b2f37e32e57ed6edc7f371993a92e34137dd21ba393de5227cfbbe2422815"
+ "digest": "15b73c02a8456b4b41164090c27409606a60440bbe1a1932ee58702ecacabcbe"
},
"grinning": {
"category": "people",
"moji": "😀",
"description": "grinning face",
"unicodeVersion": "6.1",
- "digest": "cef76aa41771db9fd1d6bd9b4233c22c1fb1931494af54cab29e6347ed9b678d"
+ "digest": "c83774596b63aed388259582de228aab02f912bc79200e6368a7926df2a1fad8"
},
"guardsman": {
"category": "people",
"moji": "💂",
"description": "guardsman",
"unicodeVersion": "6.0",
- "digest": "17bc7fad6b8c8dbd015bb709380d129f8b8e1e971062d15e6ab0b2e63e500564"
+ "digest": "b8fe4960df2f06ada3c1d6d8a7c53bb7c01b976a7f43afce50c7dadc4840771b"
},
"guardsman_tone1": {
"category": "people",
"moji": "💂ðŸ»",
"description": "guardsman tone 1",
"unicodeVersion": "8.0",
- "digest": "c531ecb101bdf9ce1db18e1567882e6db927410237100b0a2492a1401860246e"
+ "digest": "0e7fbf3faddaac2246c318fac9a8f40908ad44c98bd6543091c601abe62a5c96"
},
"guardsman_tone2": {
"category": "people",
"moji": "💂ðŸ¼",
"description": "guardsman tone 2",
"unicodeVersion": "8.0",
- "digest": "602168c5204af0f1de8b4aa5863b192ef20c19d263999377aa5eb60f98311732"
+ "digest": "56a81767c023dd6ac42b586fc50804b34b4da8fcbbffe9a6d6e5dc12e89868f8"
},
"guardsman_tone3": {
"category": "people",
"moji": "💂ðŸ½",
"description": "guardsman tone 3",
"unicodeVersion": "8.0",
- "digest": "d0a85de46dd02c7bd6cb14bff0f22d2db9083d4b171a8806c83363b49f3dd9ef"
+ "digest": "1c15ae587f90408781f5560366febafbee7e5318d1f618135408827ef82b09ee"
},
"guardsman_tone4": {
"category": "people",
"moji": "💂ðŸ¾",
"description": "guardsman tone 4",
"unicodeVersion": "8.0",
- "digest": "1c9d4d72b6b50bdac8271613b6d2a38340ec2067bc344e8ee2a3c863fd5c23a1"
+ "digest": "4fd65aa93d212fd58e5c41dc70816d691635fa6fb271bf55d72c33f3acc72c4a"
},
"guardsman_tone5": {
"category": "people",
"moji": "💂ðŸ¿",
"description": "guardsman tone 5",
"unicodeVersion": "8.0",
- "digest": "9899a796d01842e495d716fbe737a16d85724f7d3e23f50807ec2bc70f057318"
+ "digest": "dcf7b0462d5b5b0ae09673c8ea3b7e48648edc28541680dc0adbaef1fb7e738d"
},
"guitar": {
"category": "activity",
"moji": "🎸",
"description": "guitar",
"unicodeVersion": "6.0",
- "digest": "a1027ceae4dd3ea270740587c9d373329e5677e375c9e00af6ae3275e0b67500"
+ "digest": "c51339829b282ea6007d42be71949ff646bb978d5e8989d15b21857aeb2b5f12"
},
"gun": {
"category": "objects",
"moji": "🔫",
"description": "pistol",
"unicodeVersion": "6.0",
- "digest": "fc12b577df2283e7b336f23774f9cfe5b79f1d26ddd28a64a560519b28d94ca5"
+ "digest": "586379358f302248a7be52d185997a0904e31635d32a0fac86366d98ac1ab242"
},
"haircut": {
"category": "people",
"moji": "💇",
"description": "haircut",
"unicodeVersion": "6.0",
- "digest": "b243a04f5ca889accd45e7abe095ac5caa92274ed95103f5966a36b415fff412"
+ "digest": "d6da39a1156f21ca140f28c5477fbbc37c2a9903bb2eb183e9288e16eedf134e"
},
"haircut_tone1": {
"category": "people",
"moji": "💇ðŸ»",
"description": "haircut tone 1",
"unicodeVersion": "8.0",
- "digest": "a58d0cff1427b80dfd7a9ea5267b4a181e9faaac6a51a0165db522f668b4cf91"
+ "digest": "186dfd3d0512fc316dd48a75b4201cb9006bf1f01ad17afe41c1e9fc4f1b440a"
},
"haircut_tone2": {
"category": "people",
"moji": "💇ðŸ¼",
"description": "haircut tone 2",
"unicodeVersion": "8.0",
- "digest": "675083ff40001405f8de99268477d50dd8594ff6ca40ddfd442dd42ad76e8216"
+ "digest": "4e85e6281419b2bc948d529d883bdcea6c115a4195299c1fc3c0bb839ac95b26"
},
"haircut_tone3": {
"category": "people",
"moji": "💇ðŸ½",
"description": "haircut tone 3",
"unicodeVersion": "8.0",
- "digest": "70d7581e49c315a3771dd61a3713229886db32aaaeb3af078a69cc042f809150"
+ "digest": "08d8b031cb43180346a7be2e6e010b31abfdc091471c357ff1d428bd8bd66bba"
},
"haircut_tone4": {
"category": "people",
"moji": "💇ðŸ¾",
"description": "haircut tone 4",
"unicodeVersion": "8.0",
- "digest": "ec5e3e909eb3bc375ef9cc0fe0e0f90b33f44f273ada91ccf415bbc43b8ffbfc"
+ "digest": "b3d2c66952b6d141ab000c6c99a4b8a978f135e2b880aed83517fb5cbced7f14"
},
"haircut_tone5": {
"category": "people",
"moji": "💇ðŸ¿",
"description": "haircut tone 5",
"unicodeVersion": "8.0",
- "digest": "7c89739ee458546a808fded7f96d9354c47a76883ebb262d5f5abeafd021260e"
+ "digest": "eab0facef35c9b3e920c79adce756116b68fe8042bc77f9505d93cdd75a58e79"
},
"hamburger": {
"category": "food",
"moji": "ðŸ”",
"description": "hamburger",
"unicodeVersion": "6.0",
- "digest": "48204235238bd89d3a69f319f65135102f3d6b181eec241d4d86b302bbffa9bf"
+ "digest": "5d302067792941f85238d73dabc26e5565891ffd23514c93a26e5ac759d86198"
},
"hammer": {
"category": "objects",
"moji": "🔨",
"description": "hammer",
"unicodeVersion": "6.0",
- "digest": "d0e7830539d935fcd82820c4e0c1d724f0756dfc83a51171fe0f4b36b69fac42"
+ "digest": "ad9c4c0d7613bf9022426fbd46fe1966c98a46222f81fc13402a93d5101ba3ca"
},
"hammer_pick": {
"category": "objects",
"moji": "âš’",
"description": "hammer and pick",
"unicodeVersion": "4.1",
- "digest": "aa0445f43bca58d17afa7f3577632ca7775f5a28336385b3020b268b15b18142"
+ "digest": "e5fd4464456d11cfe9fb50c460cf784174a36013a81771d029c8cfbb73c5ce9a"
},
"hamster": {
"category": "nature",
"moji": "ðŸ¹",
"description": "hamster face",
"unicodeVersion": "6.0",
- "digest": "a7e7582e8b1bccd5b7df27ccb05e353a3f0e39bdeb40877732706b9d74a70de1"
+ "digest": "aa2bb7c3ca254800ae7bb02b49ae4206984d4a07350be9fe8e0d645133918863"
},
"hand_splayed": {
"category": "people",
"moji": "ðŸ–",
"description": "raised hand with fingers splayed",
"unicodeVersion": "7.0",
- "digest": "c51a30cb7e575d29ffed16780a6c95ae3f300b8ac523012f4a6e116d68c1fd15"
+ "digest": "cf0d977763f453074d581b2f305065ec0237ff8d242ea99641b85e1041c4aa62"
},
"hand_splayed_tone1": {
"category": "people",
"moji": "ðŸ–ðŸ»",
"description": "raised hand with fingers splayed tone 1",
"unicodeVersion": "8.0",
- "digest": "c31fb44a982ed8808e1c311ec1b0b9c5afcb47f16bb1fc731dc483adf8f0d049"
+ "digest": "33aeacad6f84a936dbcc8787d49cb0358afbde289bc324320f00f9582512762e"
},
"hand_splayed_tone2": {
"category": "people",
"moji": "ðŸ–ðŸ¼",
"description": "raised hand with fingers splayed tone 2",
"unicodeVersion": "8.0",
- "digest": "56a236881184e9ffad54613fa08a67368c432af738f5254fb1cd87b20368acdf"
+ "digest": "e78d9a420e4b28549c90869764b09edb030884049e49202515cf31d3f95e04e3"
},
"hand_splayed_tone3": {
"category": "people",
"moji": "ðŸ–ðŸ½",
"description": "raised hand with fingers splayed tone 3",
"unicodeVersion": "8.0",
- "digest": "9242ca97dfd2bbc1947228f6535029afb31f8feb72c14ff4b7f2deea30217425"
+ "digest": "252148eb798f804b341c862ca04b64bc499eef820e95d481abf85d88d2cadca7"
},
"hand_splayed_tone4": {
"category": "people",
"moji": "ðŸ–ðŸ¾",
"description": "raised hand with fingers splayed tone 4",
"unicodeVersion": "8.0",
- "digest": "43348d9fd3d43b3c45cebaf663bf181bcad3b6df841a5aeed838180db2cdd481"
+ "digest": "551ed9bcf75b5fd83b8d4d5e4d01700b494fd8787a40ab84db4783e670fa404c"
},
"hand_splayed_tone5": {
"category": "people",
"moji": "ðŸ–ðŸ¿",
"description": "raised hand with fingers splayed tone 5",
"unicodeVersion": "8.0",
- "digest": "4b3a0aba7829772fec09f26d6facc19a2f822d2998015297b18b5cab85190ee2"
+ "digest": "a1b05e2a3dbd79b673e058f22533142c2e4bf6c542054ffbf3f61dc48f3aa274"
},
"handbag": {
"category": "people",
"moji": "👜",
"description": "handbag",
"unicodeVersion": "6.0",
- "digest": "45410a3eed0c2e3f68748d7649fa9e33a90f4e80d5291206bdd0b40380c6da45"
+ "digest": "0f1d0849440c523c026b3dea64850f48c3fccbc01fc08878927a25900f393a76"
},
"handball": {
"category": "activity",
"moji": "🤾",
"description": "handball",
"unicodeVersion": "9.0",
- "digest": "94ceb28024eb3259d8b137cafd7438773e717fbc04f5da810f85e43ca0fa9e00"
+ "digest": "66eb58f2b6fed026008dc73d99259f3023145b3955a52e47033f09055502992e"
},
"handball_tone1": {
"category": "activity",
"moji": "🤾ðŸ»",
"description": "handball tone 1",
"unicodeVersion": "9.0",
- "digest": "8bec4de0d05c80e335e44d65598d186ca92696977353c9fd9c2a5efa122cb842"
+ "digest": "52b5a29715638415371c6546795930fa3b589e0723f59af9969a0de6822cfe04"
},
"handball_tone2": {
"category": "activity",
"moji": "🤾ðŸ¼",
"description": "handball tone 2",
"unicodeVersion": "9.0",
- "digest": "2ff4131e1e2f089b315d8e176c9348877c26c2bd03706fb75d41bc61bc99bf93"
+ "digest": "8454813e2e2aabd6eb897bb973129c41d3628e0418e611c4968e8aee477b077d"
},
"handball_tone3": {
"category": "activity",
"moji": "🤾ðŸ½",
"description": "handball tone 3",
"unicodeVersion": "9.0",
- "digest": "224a71f94dd37d3729325d11412334667a81422e21f6d7c008730ff350f51a80"
+ "digest": "b7f821482e3bcb63e36ba9b5d3838f1444c35095a9d68648cec24438cc860f4f"
},
"handball_tone4": {
"category": "activity",
"moji": "🤾ðŸ¾",
"description": "handball tone 4",
"unicodeVersion": "9.0",
- "digest": "a5f7a9db790565981bad2d0d9e09554c8c509a8179b4705a418300d58a7894b4"
+ "digest": "604e7948a99d23d469e3914040eea00e40faeab8e0f92d837fc1aebb7953104b"
},
"handball_tone5": {
"category": "activity",
"moji": "🤾ðŸ¿",
"description": "handball tone 5",
"unicodeVersion": "9.0",
- "digest": "00404572d4683f2e8e8a494aa733e96fbec1723634d0a8cb8d75f2829a789d27"
+ "digest": "d989a7bd045a77163055d7973ee4ccbd3b04029a06df25cecd50a76466ca1526"
},
"handshake": {
"category": "people",
"moji": "ðŸ¤",
"description": "handshake",
"unicodeVersion": "9.0",
- "digest": "cb4b08b70560908f96bda0aecd2f4c966bea180f9b7200e4c81d342dc8d36087"
+ "digest": "59e0dfc9059d643a6e88a2c498ac62175876f78394c68605e984d25597f4e177"
},
"handshake_tone1": {
"category": "people",
"moji": "ðŸ¤ðŸ»",
"description": "handshake tone 1",
"unicodeVersion": "9.0",
- "digest": "40470e224683ba375ed8698c0cbd560556be5a8898237ddf504377a3a7e89ff0"
+ "digest": "d16474fe7d1eb0e3b6441111370051caf5b20847d4080a89c4474a6af8c9f711"
},
"handshake_tone2": {
"category": "people",
"moji": "ðŸ¤ðŸ¼",
"description": "handshake tone 2",
"unicodeVersion": "9.0",
- "digest": "77ed378243bf682f1f4f1a8caeabcbedf772f54631cc40ea46c099e46a499b18"
+ "digest": "f101fcd171fedad33bb5a90bc51cdbd5041902adef5e94f4893eafdac76512a0"
},
"handshake_tone3": {
"category": "people",
"moji": "ðŸ¤ðŸ½",
"description": "handshake tone 3",
"unicodeVersion": "9.0",
- "digest": "81b95050f0878b617f5d2640e34031c26a0072e46ca5a688eb4356e48bc74c92"
+ "digest": "9a519adf10d9bd3ef8f0c94beeeb64de8922d85b428e74663f9a9eec3be15a71"
},
"handshake_tone4": {
"category": "people",
"moji": "ðŸ¤ðŸ¾",
"description": "handshake tone 4",
"unicodeVersion": "9.0",
- "digest": "74919a6f026fbbd0ccdbdbd4288d1b2ef3bda8930e9142c07736db4a7f3ef345"
+ "digest": "e0aff05eaed64f9c03c91a821982d425bd4f237b0fb09fffb23476912b100ffa"
},
"handshake_tone5": {
"category": "people",
"moji": "ðŸ¤ðŸ¿",
"description": "handshake tone 5",
"unicodeVersion": "9.0",
- "digest": "a30d662bfad0074ca7e32cf6f7229b643b636c4beaec496777eb7e1d5b6fc470"
+ "digest": "76ec70c0b6bfca7dfc3d2b202f36c6cd59c030e6414c49f3f1e3f68cee77be9b"
},
"hash": {
"category": "symbols",
"moji": "#⃣",
"description": "number sign",
"unicodeVersion": "3.0",
- "digest": "01c8b577953010bff0c20f797c2c96ab5d98d4e6ac179c4895a78f34ea904655"
+ "digest": "941108d47089055455e13b981cd37b0437cd72d5c19ad397254494184060366e"
},
"hatched_chick": {
"category": "nature",
"moji": "ðŸ¥",
"description": "front-facing baby chick",
"unicodeVersion": "6.0",
- "digest": "006571b9e9e839ec9fcb1a911b935c8ca71eb8bcdce9775bee6a2a4c7c927277"
+ "digest": "e87f9edbc75c2f65940e59ec3ee752bf15cca10767e83766d3bb2e2cacbb30d1"
},
"hatching_chick": {
"category": "nature",
"moji": "ðŸ£",
"description": "hatching chick",
"unicodeVersion": "6.0",
- "digest": "fd7f69fa186407f80de59dec5116e318325a5743ee0e8bba1db541f1e57e7f74"
+ "digest": "839de0c6a31a0c0ff1e4ee36f64fe462667d15acda79747dd0a362f59a37f144"
},
"head_bandage": {
"category": "people",
"moji": "🤕",
"description": "face with head-bandage",
"unicodeVersion": "8.0",
- "digest": "d09019a73e203b38cc43729a96163147de88e09eab8adb073888e55366854c72"
+ "digest": "53fef09c38e83bc82c90bd3d63e01767767d2f25cec1cd5a6742e3be8cb0ef12"
},
"headphones": {
"category": "activity",
"moji": "🎧",
"description": "headphone",
"unicodeVersion": "6.0",
- "digest": "34f9d5598158d5d6f978a5ea5c5aa9948bb2990625565a3afad7710f864fbe2f"
+ "digest": "ca903e1013a0be982e3281dd357b9acf3cccd41db7021385a6d4d84ce1f31c04"
},
"hear_no_evil": {
"category": "nature",
"moji": "🙉",
"description": "hear-no-evil monkey",
"unicodeVersion": "6.0",
- "digest": "53b030b6d6f4ed1a734fa7d48b46f42eb1b2b01653202c1838b742082f08c4bf"
+ "digest": "6358afb4d187b86c325b5b0113b46d0ab080968fbd8c477d54f733c169b0242e"
},
"heart": {
"category": "symbols",
"moji": "â¤",
"description": "heavy black heart",
"unicodeVersion": "1.1",
- "digest": "92be652ec3e50c6e7393440b5d52b88a367f98a28dffe12660095ed3253aa6c0"
+ "digest": "f4f1ba1aa7118b2ccb2693eeb523fd1ef44766e88bbda830fe2154a7791bb677"
},
"heart_decoration": {
"category": "symbols",
"moji": "💟",
"description": "heart decoration",
"unicodeVersion": "6.0",
- "digest": "6ec5bbf3aa75c6f43eb3dc05e9204366936e8b6b4219310bacdc2fc45f51e245"
+ "digest": "f68f4ff3043101c8bb2ce52257ee918a016128a962ba3d8e0bb4a640076743f9"
},
"heart_exclamation": {
"category": "symbols",
"moji": "â£",
"description": "heavy heart exclamation mark ornament",
"unicodeVersion": "1.1",
- "digest": "5985ea4d82232a2a07052a59db268aed9ac943895d0c82f637595bb5386329a6"
+ "digest": "35c8dd5c38c09f8bcee07145e68f299f662866c7d05294aff6ab2a9b11bb83de"
},
"heart_eyes": {
"category": "people",
"moji": "ðŸ˜",
"description": "smiling face with heart-shaped eyes",
"unicodeVersion": "6.0",
- "digest": "0eff616517a6252ec89d47d9b4ad85589bcf2bdc7f490578934350acb84b2fcc"
+ "digest": "997c08afa77ab1bd0b08ae58854024286669ce94385c2a5c7bcab02d219a3667"
},
"heart_eyes_cat": {
"category": "people",
"moji": "😻",
"description": "smiling cat face with heart-shaped eyes",
"unicodeVersion": "6.0",
- "digest": "8a1f28b97d661ca4cff5ee13889ca61b5fa745ccb590e80832b7d7701df101d6"
+ "digest": "9ea3bd6876a5833b702730a8b21ba0a20b3f95c64131e46414402ad485719069"
},
"heartbeat": {
"category": "symbols",
"moji": "💓",
"description": "beating heart",
"unicodeVersion": "6.0",
- "digest": "c9ec024943439d476df6f5ec3a6b30508365a7af3427671a80de3ef2f4f95ffe"
+ "digest": "1b8ecc1830cb706a354bd340c6c127bf045102a5fe7e1f472daecf13a772628f"
},
"heartpulse": {
"category": "symbols",
"moji": "💗",
"description": "growing heart",
"unicodeVersion": "6.0",
- "digest": "281d8aebfea37db5b7fe82d9115be167006881fe29ab64a5b09ac92ac27a2309"
+ "digest": "bb45713a2195b5f4742bc57aa4e72e26a850c8860e0ca395fcc8e2a64e13334b"
},
"hearts": {
"category": "symbols",
"moji": "♥",
"description": "black heart suit",
"unicodeVersion": "1.1",
- "digest": "271429d12c40be921897005b7bdd08f9518960af1e1e6f56bb0060f1f183651e"
+ "digest": "86712f800e461be471d9d64d427f4e751eab584cae33b2c7a72634161c51e622"
},
"heavy_check_mark": {
"category": "symbols",
"moji": "✔",
"description": "heavy check mark",
"unicodeVersion": "1.1",
- "digest": "e347728e1290eb9e7b0742d628e2fd124fc049e0774f8a6ddf8e5286e7318718"
+ "digest": "206dc92526366341e4eef274354104ac2d6a464dfc253c0459c6943556ab3d64"
},
"heavy_division_sign": {
"category": "symbols",
"moji": "âž—",
"description": "heavy division sign",
"unicodeVersion": "6.0",
- "digest": "c1e8c40f0788f140b1c5fcb81ed9b5ce1bcfa5988bb8140ed2808e9cb7e0d651"
+ "digest": "563f5723eb45d2903a37ae66b3a388b06c1576a35cbcf203a6ea951bbbcb10f3"
},
"heavy_dollar_sign": {
"category": "symbols",
"moji": "💲",
"description": "heavy dollar sign",
"unicodeVersion": "6.0",
- "digest": "7cdeef38348654b93d566e01a48973281cb404a63d0b75b3bad51032887f3f55"
+ "digest": "25a39a89a62f45d7bd4948682ed23753d16179fe0c80dc60ff06bc29549fd04f"
},
"heavy_minus_sign": {
"category": "symbols",
"moji": "âž–",
"description": "heavy minus sign",
"unicodeVersion": "6.0",
- "digest": "e5335cc6b22abdce49a6127c34269b65a4a6643ddd3253d9baac425089143e7d"
+ "digest": "9f2d6d303ab3c87bfdc78a933351f1659304758a330828961bc053fac1f5cdae"
},
"heavy_multiplication_x": {
"category": "symbols",
"moji": "✖",
"description": "heavy multiplication x",
"unicodeVersion": "1.1",
- "digest": "64bbe9e9716a922e405d2f6d3b6d803863a53fac80ff8cd775899971046cb1ca"
+ "digest": "879a6b81e3fba890a3261029c611bc8baf6371e012b70a648fec0c2156e690d7"
},
"heavy_plus_sign": {
"category": "symbols",
"moji": "âž•",
"description": "heavy plus sign",
"unicodeVersion": "6.0",
- "digest": "d0d8ade2020ceb252205180b85c66e665856e6cb505518d395b9913b0b24b746"
+ "digest": "d7e684b6d4a4f0f9fa51dddf10c844616d0bb14184ba8b015088b5a4793aa4c4"
},
"helicopter": {
"category": "travel",
"moji": "ðŸš",
"description": "helicopter",
"unicodeVersion": "6.0",
- "digest": "4bd6fd13650fbe3a19cfffeffe6c21b1cda74bd6af64c5dc5999185e35444bc3"
+ "digest": "e5cacdf04612e3e2bb7a1c8f6968c2dd5b0b715ee2bdbfa703d5d0ddedf6be5e"
},
"helmet_with_cross": {
"category": "people",
"moji": "⛑",
"description": "helmet with white cross",
"unicodeVersion": "5.2",
- "digest": "8286107391d44b9cd7fce5dc83bfdebbcdcf5a8214c46a8990732ec40263ed77"
+ "digest": "12a73fcfb9d2a62305f4a59f028215c81868a4b8de862b276c3b508872ac70ad"
},
"herb": {
"category": "nature",
"moji": "🌿",
"description": "herb",
"unicodeVersion": "6.0",
- "digest": "9fe8ed65515ede59d0926dcf98f14e2498785e1965610aa0dd56eca9b4bedad9"
+ "digest": "26a5958f4afaa7ec0f0fbbddfe50b6a467dff109fab45345c5a63b0316d20370"
},
"hibiscus": {
"category": "nature",
"moji": "🌺",
"description": "hibiscus",
"unicodeVersion": "6.0",
- "digest": "c442e8eacbd8727bd154bd39692a9a2a03ea2f674b9670ad8361f78a038afe49"
+ "digest": "2dc90fc37f140ac3a56600042ba44116f28e40bdda1d041d2218a6251099cbf6"
},
"high_brightness": {
"category": "symbols",
"moji": "🔆",
"description": "high brightness symbol",
"unicodeVersion": "6.0",
- "digest": "35ced42426dcfd5214c2c6c577dce84bb708156433945e6b6adaff7ea530cc57"
+ "digest": "9ee294cb514a00f831f3fec6275d75685f157b6d22a7ee1417c28b4c93e1d3ba"
},
"high_heel": {
"category": "people",
"moji": "👠",
"description": "high-heeled shoe",
"unicodeVersion": "6.0",
- "digest": "1e7c7aba50eb1d02cf1d9aa372caca741a6005cf47f68dfa75b7310c3cb18f05"
+ "digest": "f2aee61e8ae1cb532d9f005317476bbbe26b6e7d18cf2b2cac3d21ab39a86dd1"
},
"hockey": {
"category": "activity",
"moji": "ðŸ’",
"description": "ice hockey stick and puck",
"unicodeVersion": "8.0",
- "digest": "2d00fb17baa617e799db8e9b1771cc365bb4545c7633df0123e66e1a6e2ed25d"
+ "digest": "9c5e4e47bca98e73610173eb568ab9f2abf6cbdb8357438db30244946ebd7dac"
},
"hole": {
"category": "objects",
"moji": "🕳",
"description": "hole",
"unicodeVersion": "7.0",
- "digest": "8b5539f6f24f09d5d68ffd56be5aa2a8a2f753a8dfbf64892fb02c8f2703e920"
+ "digest": "a486f10fd58f9e9424feb4b1409e5fccac7706952b616460156a55db836a46f0"
},
"homes": {
"category": "travel",
"moji": "ðŸ˜",
"description": "house buildings",
"unicodeVersion": "7.0",
- "digest": "cd512f2b4ce747325607d47da48e083dbfe38a44b85b2522bc372bd105afd25f"
+ "digest": "2ffdafabb89623b096e12f9a81936e699c436d0e948af6c1dd8786690b1a601b"
},
"honey_pot": {
"category": "food",
"moji": "ðŸ¯",
"description": "honey pot",
"unicodeVersion": "6.0",
- "digest": "f6eec8c32fbd1b461446dc6c5d5031c43e6ee9685dc9b1ea1b839114e48c4eee"
+ "digest": "bc66ee9940f2c1af04e066e78d4a61bc261f1dca4419d028b133ea9bc42e24d4"
},
"horse": {
"category": "nature",
"moji": "ðŸ´",
"description": "horse face",
"unicodeVersion": "6.0",
- "digest": "e377649a9549835770a2a721a92570f699255f88efa646029638eb8ec5f10e3d"
+ "digest": "fa6681d0536051b55e189bdd7435edfd4d4967cc28c255b55baf25cb25f40865"
},
"horse_racing": {
"category": "activity",
"moji": "ðŸ‡",
"description": "horse racing",
"unicodeVersion": "6.0",
- "digest": "3b98e94e9c028ad85b9a750cc61db5ee3ac23cf5ad9243ea3e996b1f772bad54"
+ "digest": "1c1a2fa09a64da5b442f334a45054b7cbe39dbf7ac1d2a26d7a1ef2bb2debdc4"
},
"horse_racing_tone1": {
"category": "activity",
"moji": "ðŸ‡ðŸ»",
"description": "horse racing tone 1",
"unicodeVersion": "8.0",
- "digest": "382d8e4502ed34fc1bbf1779ce483bc2e22b83f89c91746c11a5d7aea656d446"
+ "digest": "5d55d2cc1a8efc0b754cd75d56d2643784aa41fc7a09e1e9d4ddee767f35ffd6"
},
"horse_racing_tone2": {
"category": "activity",
"moji": "ðŸ‡ðŸ¼",
"description": "horse racing tone 2",
"unicodeVersion": "8.0",
- "digest": "198df9973b492ea63e5cfc210dd9591750ccce04a6380adc1dc5b4cb0462a8cd"
+ "digest": "f8b5b8f7247f6526ea3bca0e6a1136978449815a105f766b42ff6a2bfe24a7a3"
},
"horse_racing_tone3": {
"category": "activity",
"moji": "ðŸ‡ðŸ½",
"description": "horse racing tone 3",
"unicodeVersion": "8.0",
- "digest": "a67f95fc92c366750ebad3c4db92982893d67a5ed78163c8cc809ac40d2ab9a3"
+ "digest": "13a6b8ceeba67ea1dcda173f8c4ce012ec5333460bff51646ecd3c26092b492b"
},
"horse_racing_tone4": {
"category": "activity",
"moji": "ðŸ‡ðŸ¾",
"description": "horse racing tone 4",
"unicodeVersion": "8.0",
- "digest": "986b1706c4a3395b58a8ae3b7609ffdd4424dfefcbf26c88c8085f4f6379734e"
+ "digest": "042cb542ea8008f51f7750923a8f88090bc91c9301234b6eb39284735930f5ae"
},
"horse_racing_tone5": {
"category": "activity",
"moji": "ðŸ‡ðŸ¿",
"description": "horse racing tone 5",
"unicodeVersion": "8.0",
- "digest": "66656b5e3d0f43f16f983f9db6214b07aac73b143eeff6475782f98aa5b9ba53"
+ "digest": "07a0a17002c5f623540377cf24a86d364bcb42b57b759e41d07af17ae36c1206"
},
"hospital": {
"category": "travel",
"moji": "ðŸ¥",
"description": "hospital",
"unicodeVersion": "6.0",
- "digest": "034573e76df444f5b0eb7aff3a4103e4b49a1813869155ab3ae29a6fc0c6c8a2"
+ "digest": "84895d822ef2e2a77b3703b80c5d5b29574f655b88420ef6f39ab3d93bb123df"
},
"hot_pepper": {
"category": "food",
"moji": "🌶",
"description": "hot pepper",
"unicodeVersion": "7.0",
- "digest": "0b05777d42698196a10db17d04030175b1dfa772d06288f71d666d5f8d3fddbc"
+ "digest": "78301b29d9426d81938771c3c25a95d70c9eecf78b39a3f49f30cb63f0cf6c50"
},
"hotdog": {
"category": "food",
"moji": "🌭",
"description": "hot dog",
"unicodeVersion": "8.0",
- "digest": "7a25bbd1a7531fd34a22c654c0931d9e74bea2bbe7baa9f9cbd88f43baa79fb5"
+ "digest": "09bc0ee460411220b1e853893eb161106d173909d7754b35c36d16e99b54a30f"
},
"hotel": {
"category": "travel",
"moji": "ðŸ¨",
"description": "hotel",
"unicodeVersion": "6.0",
- "digest": "2d78e0ad4cfb0caad778c7de49fefd6e8356afe902a43e3f1c40bceb6b0be422"
+ "digest": "7f04757da4f1a537cb92ac9a0537e3a7ebd90ae9e2c3e73ad79c95623b3126ef"
},
"hotsprings": {
"category": "symbols",
"moji": "♨",
"description": "hot springs",
"unicodeVersion": "1.1",
- "digest": "4c10c3a974b44693e8cbe91365c8b8d7f14f62db234cc516b6e54c08a6bacaed"
+ "digest": "755da4733bacad870d226b5ec054c803368c4ab10ae577e193a3015ee25a8271"
},
"hourglass": {
"category": "objects",
"moji": "⌛",
"description": "hourglass",
"unicodeVersion": "1.1",
- "digest": "f0bae8392aaf6f75a83f5d8914936b8650665b24ba1b232fa546b71545dd9acd"
+ "digest": "88925df394060ad7e8285bc7cc6cdb3c54453316b75658c780bb956ca812d2fc"
},
"hourglass_flowing_sand": {
"category": "objects",
"moji": "â³",
"description": "hourglass with flowing sand",
"unicodeVersion": "6.0",
- "digest": "2d077729f40fc04007a933e97356bd511cbd8be76b8c55962ca3fa0d8b828e23"
+ "digest": "899fa78157223e27acf260c2cd902646b7271087aabd4724a2d05095484ac724"
},
"house": {
"category": "travel",
"moji": "ðŸ ",
"description": "house building",
"unicodeVersion": "6.0",
- "digest": "b4ac25979fbe161ada0d2a75769aa7552d2371d37d78cddba4ffdc7f076d3279"
+ "digest": "6be52f020a7e12a3298044d270d9322742e930cc7543e2d6dfb9c26f25b529ec"
},
"house_abandoned": {
"category": "travel",
"moji": "ðŸš",
"description": "derelict house building",
"unicodeVersion": "7.0",
- "digest": "6e1a58533fbfe88a0eb03668c9f17c5c654a6cc7734ed798d4a885400f823610"
+ "digest": "0931ce0e42ca7206910a62452e1b7975aed4692d362c81bf62cafef25f2bcefa"
},
"house_with_garden": {
"category": "travel",
"moji": "ðŸ¡",
"description": "house with garden",
"unicodeVersion": "6.0",
- "digest": "817463f23ec0a849393ba75c333e822b4d253cd4db998c127e90d1b924f35d20"
+ "digest": "b62e44e69e1a04f88280518fd48c4870035f0abb5ae6a6664daa7cf005c8f8de"
},
"hugging": {
"category": "people",
"moji": "🤗",
"description": "hugging face",
"unicodeVersion": "8.0",
- "digest": "69810a98b1247e1f1e496aa757e428189ef5cc086764fabd8189cf1eef82234f"
+ "digest": "c52e3522e798301a973ab2e8829ba85d50b428ac853dbe096dd09a81d2fc5b29"
},
"hushed": {
"category": "people",
"moji": "😯",
"description": "hushed face",
"unicodeVersion": "6.1",
- "digest": "22586107f7399eff64538a52929dade152633aa268fc5ec4e6fe1c0e00a7bd89"
+ "digest": "a1b0d468e68dff4b3ab40b5980c838635e9680cfb35592ee62260b597cc8b551"
},
"ice_cream": {
"category": "food",
"moji": "ðŸ¨",
"description": "ice cream",
"unicodeVersion": "6.0",
- "digest": "d1a8e685f2ecf83dead28733859e369d6ce120a2669cdab97dc4423547d472ac"
+ "digest": "3294b57aa673511686ad1c6a01f6e4c0ecb0eb7d5472c3015c3271b4f6e16d50"
},
"ice_skate": {
"category": "activity",
"moji": "⛸",
"description": "ice skate",
"unicodeVersion": "5.2",
- "digest": "41ef65c143bc068868fa64080ffd447d91aa3fe2a39e69ecaa97022820af4dcd"
+ "digest": "e06869a74874d409372ef2714ca8f3e3050ad8a81e589709ecb541d5c77603df"
},
"icecream": {
"category": "food",
"moji": "ðŸ¦",
"description": "soft ice cream",
"unicodeVersion": "6.0",
- "digest": "22cfe17b80cbd2a0377ee90da45bd40d33533c914b2639d363fbb1f00714e194"
+ "digest": "434307d583d20429b1646cbe1bd8317a53f445cae61e8d8ff1258d3996e6b9fe"
},
"id": {
"category": "symbols",
"moji": "🆔",
"description": "squared id",
"unicodeVersion": "6.0",
- "digest": "bcf0922e083821d3be7951893084ea0d72a0110ef0b20d11dfec24dd70633893"
+ "digest": "63c1717c82c487db9a3e2a31be498e3cc88349cb0f2a5010b77be4bd51ba012b"
},
"ideograph_advantage": {
"category": "symbols",
"moji": "ðŸ‰",
"description": "circled ideograph advantage",
"unicodeVersion": "6.0",
- "digest": "0b6bf59f63fda1afa92d652814a778a056c3f4abdd9cf3f6796068bd71783051"
+ "digest": "b07fab8069772a132928e38b64d8e35661b33757176572c153f4563460dd5ddc"
},
"imp": {
"category": "people",
"moji": "👿",
"description": "imp",
"unicodeVersion": "6.0",
- "digest": "52598cf2441988f875ccb4e479637baefc679e3ca64e9a6400e56488b0fde811"
+ "digest": "bf3ec6b5b728a98f16b630cea877fe3cef79e5ebe7e58ee0caec197279ed3a80"
},
"inbox_tray": {
"category": "objects",
"moji": "📥",
"description": "inbox tray",
"unicodeVersion": "6.0",
- "digest": "d5d9497022b5318fcfbfdfcd56df9c65dd8f4a4cb5e6283ca260836df57da301"
+ "digest": "fa79ca5efc93767858677871df687d0666cc9174e7f226d7acb65c15a4cad0df"
},
"incoming_envelope": {
"category": "objects",
"moji": "📨",
"description": "incoming envelope",
"unicodeVersion": "6.0",
- "digest": "310b7bdcca93452fe10c72c03d0aafa12b98e5d3408896d275d06d3693812c7a"
+ "digest": "c23f819ce0abd3b695b05051f8c9e9be72f9bf5176207106c56e30015c199252"
},
"information_desk_person": {
"category": "people",
"moji": "ðŸ’",
"description": "information desk person",
"unicodeVersion": "6.0",
- "digest": "9f12a4a58a650e8e1d3836ef857003c3ccd42ad4203a2479eb95100bf6559064"
+ "digest": "ee9a1e94470a107b494840ac5b9bd0d59c38fcbc5d6a9f0842c910688ea9ec74"
},
"information_desk_person_tone1": {
"category": "people",
"moji": "ðŸ’ðŸ»",
"description": "information desk person tone 1",
"unicodeVersion": "8.0",
- "digest": "6674f2e059eff7cfd7fd6abc800da37c4f1087feb4ff26c9e4e31aa29fdf9921"
+ "digest": "bb91f3dedc55cca320cd14343c04c388b4dfa870a9d5860957a0180f24161fea"
},
"information_desk_person_tone2": {
"category": "people",
"moji": "ðŸ’ðŸ¼",
"description": "information desk person tone 2",
"unicodeVersion": "8.0",
- "digest": "9983412ecd130b7e9cfb078167016c06fd043b6f9f3c26d21733ca3f059fd109"
+ "digest": "a556b596a0d9cd480adaff344d3ba5c02a16ef2eb73695e9d9fc231ab8e3599f"
},
"information_desk_person_tone3": {
"category": "people",
"moji": "ðŸ’ðŸ½",
"description": "information desk person tone 3",
"unicodeVersion": "8.0",
- "digest": "d8907bf47af5722127afca8fc0da587eab33044a6c60a94890983deb8d6f7a66"
+ "digest": "b5a7ca77e15e749731fcd63da9c274c47eade033da8cfc8a6ab5413d939a8a8e"
},
"information_desk_person_tone4": {
"category": "people",
"moji": "ðŸ’ðŸ¾",
"description": "information desk person tone 4",
"unicodeVersion": "8.0",
- "digest": "3be086d4edfe9ca8e4a364b4e8d09b81b5b594b5eeb9ffdf6370179fb3118658"
+ "digest": "a7912c3121b1bb31b55c528812f54b89cdbc1982045e226c3cbce29c83970a59"
},
"information_desk_person_tone5": {
"category": "people",
"moji": "ðŸ’ðŸ¿",
"description": "information desk person tone 5",
"unicodeVersion": "8.0",
- "digest": "2fde4e98dd11c5c29c89cad7cbb7bd2d5077dfad07913b20e01955b2d0dfad40"
+ "digest": "a3e3fb0ae133513f565e5331a699a6d147200a5141a4e692fec86cfca03b9f5f"
},
"information_source": {
"category": "symbols",
"moji": "ℹ",
"description": "information source",
"unicodeVersion": "3.0",
- "digest": "b6bf3cce86d42c2e3c46470baab4af01e900b8ae337b605c3da07c3eba671269"
+ "digest": "9deada49f605373b64d9eefa432f73cf07287ebe254233823109d133dc86dc23"
},
"innocent": {
"category": "people",
"moji": "😇",
"description": "smiling face with halo",
"unicodeVersion": "6.0",
- "digest": "20f8d856bc3e46f4b1173cea05d4577e1c61f06b2daba46e57db90f4066bb428"
+ "digest": "3571bdd00112793ecf4ade131f2e50b6234b6f794fcb799e6dadacbb4106a92d"
},
"interrobang": {
"category": "symbols",
"moji": "â‰",
"description": "exclamation question mark",
"unicodeVersion": "3.0",
- "digest": "92a2d5b4c0bd6714e402f6f12fe19774cb41d081b5e9c23c415ce794224d8117"
+ "digest": "d209c9aa46c89e290a053d458f6cda0c719831518ce91265680673065cfb77d5"
},
"iphone": {
"category": "objects",
"moji": "📱",
"description": "mobile phone",
"unicodeVersion": "6.0",
- "digest": "1ebc54215713cd4bf1c1e50770999f2512bb4fea29e37d0bb3a8aa2460ff875d"
+ "digest": "6ef1372438c96383e375ab88a965db818efe0e3ae4b87f49870487c72f62ab9f"
},
"island": {
"category": "travel",
"moji": "ðŸ",
"description": "desert island",
"unicodeVersion": "7.0",
- "digest": "7f9eb5c0cd865762f7a0f187e09c1be442de7010e7c2e113d56aae998597c90d"
+ "digest": "9cd601f946f247ad80810f256b5c4f0c71658e9e52b974c3d8d36173eedcd05e"
},
"izakaya_lantern": {
"category": "objects",
"moji": "ðŸ®",
"description": "izakaya lantern",
"unicodeVersion": "6.0",
- "digest": "fbdc290e666d43d0776a73b955c26df4518692b35e72742e073705fc4ca2ae88"
+ "digest": "de36e5f5fe5da0c922e194b1ae93ed07039620b83e518a259c374563a166f4bf"
},
"jack_o_lantern": {
"category": "nature",
"moji": "🎃",
"description": "jack-o-lantern",
"unicodeVersion": "6.0",
- "digest": "78d666c2e80f64bfb6796f53e5ba4960a83ec36192110e8661031bee2b5e370a"
+ "digest": "876808e4ffa5ef7d736b88d9b1d646ea1af3bdf91f494190740502491d82edbd"
},
"japan": {
"category": "travel",
"moji": "🗾",
"description": "silhouette of japan",
"unicodeVersion": "6.0",
- "digest": "e7d9d6ebf9047fdd3c52e074ba259659c6d8e51a6abae3cdb8d6cf6dbf9a93fe"
+ "digest": "a27fd17e252497aa0220540d778427dc5fba138b6adeac10b132feae8175d554"
},
"japanese_castle": {
"category": "travel",
"moji": "ðŸ¯",
"description": "japanese castle",
"unicodeVersion": "6.0",
- "digest": "938ae132c403330288223b88d28c19a47224d4f254fbc2366ecef73d9633112c"
+ "digest": "4beaf1e9f6d7e25d3faa5076896f337fce68e75d25acdd91ceaceb9c15faa5eb"
},
"japanese_goblin": {
"category": "people",
"moji": "👺",
"description": "japanese goblin",
"unicodeVersion": "6.0",
- "digest": "63d4bcf58b9d0c29612994432aad2ae35819fdd2890674e60a2f1d51601b742e"
+ "digest": "4c5b8cfc3b172269a943341583e938cd1c8030e9de9fc9008ec0cfbca53d2f81"
},
"japanese_ogre": {
"category": "people",
"moji": "👹",
"description": "japanese ogre",
"unicodeVersion": "6.0",
- "digest": "434ceedd102e7dcbc07e086811673dd63659ddf8c3ec4d029a3d759a0abfcbdb"
+ "digest": "3ecbc95d1e43ebda0a0c9988e8dc012dc4985cdaa2b8e81a42cbf8cff30a93e3"
},
"jeans": {
"category": "people",
"moji": "👖",
"description": "jeans",
"unicodeVersion": "6.0",
- "digest": "f986ad32e419cca81c995f8371f0189d1490172a97ebbeac60054a1af08949c5"
+ "digest": "e470f82274f2b149f98d4620e61c374c3737e722bd0a08576335cc269e86f83f"
},
"joy": {
"category": "people",
"moji": "😂",
"description": "face with tears of joy",
"unicodeVersion": "6.0",
- "digest": "75d7a05043523d290c46d3b313b19ed3c95271f1110bcf234cf13d4273625b08"
+ "digest": "3c7d20273bbe976dc8cf8d5cf44ac4cb9c71b02ec358b50427e9d0662e67a557"
},
"joy_cat": {
"category": "people",
"moji": "😹",
"description": "cat face with tears of joy",
"unicodeVersion": "6.0",
- "digest": "a65c999604147e5e20170fcb14f80a1ff0a633f991492e1f790b2ad4caec7b7e"
+ "digest": "fd65d87249121b7e1b1b48af53179ff8ccc7d5f072fcb07e498dc20e9370c436"
},
"joystick": {
"category": "objects",
"moji": "🕹",
"description": "joystick",
"unicodeVersion": "7.0",
- "digest": "671ee588f397a96f27056a67e6a06d6e8d22c2109ec57b2859badb5fec9cf8dd"
+ "digest": "def1450af8fc7e3e4d968a6f6a2f5644b17f2786941d49c688c91dc4fde36836"
},
"juggling": {
"category": "activity",
"moji": "🤹",
"description": "juggling",
"unicodeVersion": "9.0",
- "digest": "1f5dafa78de8b37f3df88fdf3084d2380666bd74ab2f449754d8724f6f8dbfa5"
+ "digest": "dbc4b794cb55d03b091b86d1b1b0682535c4a2f9a4d6d6b4ad5c413f1279a4f6"
},
"juggling_tone1": {
"category": "activity",
"moji": "🤹ðŸ»",
"description": "juggling tone 1",
"unicodeVersion": "9.0",
- "digest": "b0b4d020148c896be69c28b08e3c486f6db270d138c7ccf4be362b29eb99878d"
+ "digest": "124e52052704f34a91e0cf8ef9ec7d08176942b8bee6faf2e4214df827443ae2"
},
"juggling_tone2": {
"category": "activity",
"moji": "🤹ðŸ¼",
"description": "juggling tone 2",
"unicodeVersion": "9.0",
- "digest": "cfe0c1649b2fdca03673e0e64f3a7d06d4bd49b8954c769aeb7eb88b70ec99f4"
+ "digest": "1d8609d3e765fbbed6659e5fbd5026911a276b5703b1e7593b12702de2d0555e"
},
"juggling_tone3": {
"category": "activity",
"moji": "🤹ðŸ½",
"description": "juggling tone 3",
"unicodeVersion": "9.0",
- "digest": "7f87022722008bb265abe245e8157dc7a61944f5da62b3cf86f26ee1b3bdef63"
+ "digest": "1666f54f93b744f8ee5cf8cc29be022ea5d3afd15436e642c5592d583c87830b"
},
"juggling_tone4": {
"category": "activity",
"moji": "🤹ðŸ¾",
"description": "juggling tone 4",
"unicodeVersion": "9.0",
- "digest": "1f00da8c05582c95501cc6c3fe5ce0f9bfbc16789dcee59844a8fe7831198583"
+ "digest": "efe82bf4c3759b48435a7575ff0b016035d505dbdb2c7a3774d3878eed671602"
},
"juggling_tone5": {
"category": "activity",
"moji": "🤹ðŸ¿",
"description": "juggling tone 5",
"unicodeVersion": "9.0",
- "digest": "a195bf734788eb7961c00dbc05255a49da8b9d5042fada29b26cc20393d3ce52"
+ "digest": "ebf39b7b85e8c5e2fc899bb98de9f35739b7e656efd0526d9a50e8039e7bee86"
},
"kaaba": {
"category": "travel",
"moji": "🕋",
"description": "kaaba",
"unicodeVersion": "8.0",
- "digest": "a4618782f9583f077bd383965f1c91b9985a949bb7b6cec7af22914e7f5e9ab6"
+ "digest": "363ef4a89268542427e494f0dbe04f04eabad2849fa24be57a77eb55a3d45122"
},
"key": {
"category": "objects",
"moji": "🔑",
"description": "key",
"unicodeVersion": "6.0",
- "digest": "66719fa77a50a0827c8d47237e2704c03e38186e6fef80627a765473b2294c2e"
+ "digest": "8f2ac6bfd01430b2350a91b747c58d9d7a20e58096e22f1b73ea8e1d53dd2ac7"
},
"key2": {
"category": "objects",
"moji": "ðŸ—",
"description": "old key",
"unicodeVersion": "7.0",
- "digest": "f57240a014a9da5da3d4d98c17d0a55e0ff2e5f2d22731d2fc867105cff54c6e"
+ "digest": "f1e9a01ce355b9be051eca6f2211d542f190a77ccb95e1d5b148dca8da422bce"
},
"keyboard": {
"category": "objects",
"moji": "⌨",
"description": "keyboard",
"unicodeVersion": "1.1",
- "digest": "34da8ff62ca964142f9281b80123dbba74deaac8d77fa61758c30cfb36c31386"
+ "digest": "0f3ca37b19de485983e39b02db94b0f6243d94081918703510e020ef1d269810"
},
"kimono": {
"category": "people",
"moji": "👘",
"description": "kimono",
"unicodeVersion": "6.0",
- "digest": "637182590e256c8fb74ce4c0565f5180c07f06e3bdebf30138ed3259b209c27f"
+ "digest": "987ec803ad9f64bd7ab8c41b487df6afd3416ef25fba11df698c2dddc779e59e"
},
"kiss": {
"category": "people",
"moji": "💋",
"description": "kiss mark",
"unicodeVersion": "6.0",
- "digest": "62f9b9ffcb01558cd5bb829344a1d1d399511663ff5235405c1f786c9416a94d"
+ "digest": "751426045d0e8e59b148b2f2dd275373d361ac8e90d9e6ee65f356a8a9c5e24c"
},
"kiss_mm": {
"category": "people",
"moji": "👨â€â¤ï¸â€ðŸ’‹â€ðŸ‘¨",
"description": "kiss (man,man)",
"unicodeVersion": "6.0",
- "digest": "6b0ae32ecb7ec0f0f43dc7a1350711185cce114c52752395f364ddbfb4f1fff4"
+ "digest": "a256b66869e47ee51a6b3b08c56e9ecfe9f0ed5279aeb15e0045be30891ac70f"
},
"kiss_ww": {
"category": "people",
"moji": "👩â€â¤ï¸â€ðŸ’‹â€ðŸ‘©",
"description": "kiss (woman,woman)",
"unicodeVersion": "6.0",
- "digest": "6de420cf752e706b1b7e9522b1b9be62eda069cb028c8fd587caf39f6a142e6a"
+ "digest": "989937e58c7862cd6cedc74b8c7774fb01efaa7ab3b424f4472b638d101abdd9"
},
"kissing": {
"category": "people",
"moji": "😗",
"description": "kissing face",
"unicodeVersion": "6.1",
- "digest": "b4a505f9e3d7fbd0ac60111f0e678cf425a5fd1abc65a3e9db59ae4abcfb8e85"
+ "digest": "9339112fdb5a89aca2b8baed88215ba09c698487713ea6c3a4906d6370ba8a8e"
},
"kissing_cat": {
"category": "people",
"moji": "😽",
"description": "kissing cat face with closed eyes",
"unicodeVersion": "6.0",
- "digest": "a00431bf10601db4998e78433279167e52cbd36aed885399482529d5cdab8636"
+ "digest": "e4c818629b8482ec9f3747125dbc4ea0c08ca12c151eb29f103e19d66ba39e78"
},
"kissing_closed_eyes": {
"category": "people",
"moji": "😚",
"description": "kissing face with closed eyes",
"unicodeVersion": "6.0",
- "digest": "ae474db7daf80fe0b82ae1f2a11672cfcd9f9126e100f6e6d4b8a0d135dce39d"
+ "digest": "0a58401451a4c7daad884fbcc0343f6d08efc5ce4f97cb9c455019ed57b7a979"
},
"kissing_heart": {
"category": "people",
"moji": "😘",
"description": "face throwing a kiss",
"unicodeVersion": "6.0",
- "digest": "bce372573bd3b347b555c1cd22087e03e650df73c8e0284ab668bf6633251632"
+ "digest": "6dd07e9fa9892aec92ba42b78fe23646d31701fb1d29f968ce5cf7f3c5f1336e"
},
"kissing_smiling_eyes": {
"category": "people",
"moji": "😙",
"description": "kissing face with smiling eyes",
"unicodeVersion": "6.1",
- "digest": "f0f8636cb1a02b93cc72ce1b194b890fca823d91e35926b889be3ecfae79207f"
+ "digest": "75b7829612e5e0a3c96c33cb3add78892ef8fb2012b95d24bb9e45888091648e"
},
"kiwi": {
"category": "food",
"moji": "ðŸ¥",
"description": "kiwifruit",
"unicodeVersion": "9.0",
- "digest": "70a3a05f333d9455d2da12eed970bc3baae416286848fed8e5dd31b5be0819be"
+ "digest": "bc2ee501a2c313cee1816720975228ab34fda6b83581248012112af1ba5ce1ae"
},
"knife": {
"category": "objects",
"moji": "🔪",
"description": "hocho",
"unicodeVersion": "6.0",
- "digest": "e6189e4843c6e80875b4952fcddb0c858f7c6039b9214bbec6a261a1358425df"
+ "digest": "bf3934138e3dd112241807efbe2aa91ec9913fad890236276d4c36c710c400b8"
},
"koala": {
"category": "nature",
"moji": "ðŸ¨",
"description": "koala",
"unicodeVersion": "6.0",
- "digest": "c58f7e0abae42c2218a85efed0e04151df67187815bebca7f3db6f435e0dab4d"
+ "digest": "73549917efa845ecc4a5b4c347fc6f686717e95323fed97977e6677c881f801d"
},
"koko": {
"category": "symbols",
"moji": "ðŸˆ",
"description": "squared katakana koko",
"unicodeVersion": "6.0",
- "digest": "5f45eb49bbf298e1fadedfe6cccc297850fcaaa4535e4cc911d48d979af55807"
+ "digest": "3d49c8510a5e6c915d88c026897987d8a1d52aca5d498ef7d86fcc76ebb838e9"
},
"label": {
"category": "objects",
"moji": "ðŸ·",
"description": "label",
"unicodeVersion": "7.0",
- "digest": "9550ed50cedbc56eb1bd22a8a0809d837048a33d6e2e6e7d65c50d95fa05a85d"
+ "digest": "ad9f3bfc709138edfb61c692d96c1ca08b0bd97203d370342e7b70f46ae23aa8"
},
"large_blue_circle": {
"category": "symbols",
"moji": "🔵",
"description": "large blue circle",
"unicodeVersion": "6.0",
- "digest": "0df3fb3b09a6269459a3d9a1fe78db572190a948680844cfe758f53b6a482ff4"
+ "digest": "7588a2b1c1baef733d6e7572580c51dcd81bb0c85c77080dfd136d3a995ef3cc"
},
"large_blue_diamond": {
"category": "symbols",
"moji": "🔷",
"description": "large blue diamond",
"unicodeVersion": "6.0",
- "digest": "7f646b4e9de2788ed09e45f72cb512c269dda4989029b39bf9a2556659321651"
+ "digest": "2e69e9e80dee0192403fe95aab3223208ccf97963dff54a061b6f2e3419820ef"
},
"large_orange_diamond": {
"category": "symbols",
"moji": "🔶",
"description": "large orange diamond",
"unicodeVersion": "6.0",
- "digest": "80ae005ef9d79190c777f00de0993f8b3cb783f7051d76e971640c8c0827c338"
+ "digest": "30bee888a5d3dc39a11132fac8a490d8dab4237cc62f1529f5c3e6e77b8f29a4"
},
"last_quarter_moon": {
"category": "nature",
"moji": "🌗",
"description": "last quarter moon symbol",
"unicodeVersion": "6.0",
- "digest": "3d1f276607c685d50f4b70d00a57750a57ad9ad84256dafd2dc8eef8c72300c3"
+ "digest": "7801bf738898b75b09c7ee3f89d71fb11f41bf838f2766b8e80c1028b2873f88"
},
"last_quarter_moon_with_face": {
"category": "nature",
"moji": "🌜",
"description": "last quarter moon with face",
"unicodeVersion": "6.0",
- "digest": "d516825ba52dc67f5a01433fb9df2aa77742d38efde4225983ebc4882cbdfe5d"
+ "digest": "e1e5678ea54dfafb83bb94879150bc43c495dc546be92c8780469f24b52d036e"
},
"laughing": {
"category": "people",
"moji": "😆",
"description": "smiling face with open mouth and tightly-closed ey",
"unicodeVersion": "6.0",
- "digest": "e9ea994b39650740c4961f070ed492d86b3acf6e6a830a6dadaa3a6872e81b81"
+ "digest": "43f119b4cac94c33c49e35381710d74d4f81883364ade30088cd92e5130287e1"
},
"leaves": {
"category": "nature",
"moji": "ðŸƒ",
"description": "leaf fluttering in wind",
"unicodeVersion": "6.0",
- "digest": "56a7a0e767a6f214d340d1b5989efd99fec52c6aa306ec5c3328e32234a1631b"
+ "digest": "814ac13b38d78820a050dd97155abfcd6c98fc56c5793044de7b7d2855e5acb9"
},
"ledger": {
"category": "objects",
"moji": "📒",
"description": "ledger",
"unicodeVersion": "6.0",
- "digest": "e58cb714353e96a2891a5d97910ff79660e637af909b81c49c919d3735db55b4"
+ "digest": "826379f5164a8c3a10ec43ae1296f994ffd40bc3eb6c0595117993eff65f8f2a"
},
"left_facing_fist": {
"category": "people",
"moji": "🤛",
"description": "left-facing fist",
"unicodeVersion": "9.0",
- "digest": "7861be485beefae0de341df2f21576666e22f63511a033e785752f30c07291da"
+ "digest": "69390c51d4188f7f5381f7d8f4658c8ea4e52455ed648ebf59b6fb3157c5c6e0"
},
"left_facing_fist_tone1": {
"category": "people",
"moji": "🤛ðŸ»",
"description": "left facing fist tone 1",
"unicodeVersion": "9.0",
- "digest": "2e4c4dd96b0e4b46fe0f9ce5666344d266d0f17a8544cbae73d96638d1955296"
+ "digest": "57e9a2288243d2024cf25e4258c48e1b0bfe5c12aee218629bb03f8a5ab0cb61"
},
"left_facing_fist_tone2": {
"category": "people",
"moji": "🤛ðŸ¼",
"description": "left facing fist tone 2",
"unicodeVersion": "9.0",
- "digest": "b96a63a801175ce98a75f0edad7b5574251a3fbbd894d8ab3f21aeeda366cc13"
+ "digest": "061ef44811174e10f7598aadf1f4c69cbc915d029ba83d5101cc34d0cfd44431"
},
"left_facing_fist_tone3": {
"category": "people",
"moji": "🤛ðŸ½",
"description": "left facing fist tone 3",
"unicodeVersion": "9.0",
- "digest": "99df84635513c2ebfef24df1bd3705233e02149eef788c7b82ca0548df6f6ea5"
+ "digest": "c313fcb7d4e1505b76ce25e45b50c0c4d0842be34c472abc328915f07e6b6efe"
},
"left_facing_fist_tone4": {
"category": "people",
"moji": "🤛ðŸ¾",
"description": "left facing fist tone 4",
"unicodeVersion": "9.0",
- "digest": "68954842ca725aec0aa39bce4aa81aad17ac30f5f298561dfa411feb07414cd3"
+ "digest": "825e7feac0a934250246dcb97cae5daafe31aef100c9614a17ba0c7669cb18ee"
},
"left_facing_fist_tone5": {
"category": "people",
"moji": "🤛ðŸ¿",
"description": "left facing fist tone 5",
"unicodeVersion": "9.0",
- "digest": "a419b33fae82612dc860ff48950c0547a1642d4f0c94b6547324440837d3bb21"
+ "digest": "20bfe330f9c1ae22b0cd4d0af0a8a5d062e898fafe10c8a4153f89e582c0de54"
},
"left_luggage": {
"category": "symbols",
"moji": "🛅",
"description": "left luggage",
"unicodeVersion": "6.0",
- "digest": "6625077767a51163ea20cbc299f3c13fd5ccf1b5ce365ee702ef1fef6be3dadf"
+ "digest": "18bade3d46e8ea3ba9d6bc52679e367d7a1721757719ca6903e68331a1fd1c47"
},
"left_right_arrow": {
"category": "symbols",
"moji": "↔",
"description": "left right arrow",
"unicodeVersion": "1.1",
- "digest": "560fcf1b794eb0d5269c73b3f8da57540cbb8a6f1a9af7a9d10b202252247e34"
+ "digest": "292108ff7e529974269eb98b0d417f651a9d97258a8070aaec6579c934139bb0"
},
"leftwards_arrow_with_hook": {
"category": "symbols",
"moji": "↩",
"description": "leftwards arrow with hook",
"unicodeVersion": "1.1",
- "digest": "504714c5559b1bd35aa469be83069a923d1a25f364cac08c10df0195749e7b26"
+ "digest": "1f4c8e03c92083ddd647f3328fd1ff9b919c10a98d0325b877f1b7034a7387ea"
},
"lemon": {
"category": "food",
"moji": "ðŸ‹",
"description": "lemon",
"unicodeVersion": "6.0",
- "digest": "ccca25bb6ac47770dba3aaf75144128f9a73299061969b25a35ad1733dcde5fe"
+ "digest": "b6d67cb631ddc6d448f658fb151d325018ef01b791c005ed1d601f8223b7a722"
},
"leo": {
"category": "symbols",
"moji": "♌",
"description": "leo",
"unicodeVersion": "1.1",
- "digest": "f2ed930e279699962f189e0cac519cc29d339b3e82debfdc90c5b0935a7543bb"
+ "digest": "25787c495211576604fbcdf72aa47ab7e5ad4e8a42905a995edbbec073e20c52"
},
"leopard": {
"category": "nature",
"moji": "ðŸ†",
"description": "leopard",
"unicodeVersion": "6.0",
- "digest": "d4a8964b6f2cdf6ddf074d0f1f2f65783a1a43eb4af426905fad0e60899939c7"
+ "digest": "00204970970b9dd38bb9b1ae30a11832c992ade57bce1496a1f3c366e7d31f00"
},
"level_slider": {
"category": "objects",
"moji": "🎚",
"description": "level slider",
"unicodeVersion": "7.0",
- "digest": "48842324f54d971ebf548a89a82ac7f29e235702081c91b477b1a92d427290e7"
+ "digest": "d57965d6b267a20a4529adbc71dd4efcb7f5e8f1146c03746b65922cd3f271c6"
},
"levitate": {
"category": "activity",
"moji": "🕴",
"description": "man in business suit levitating",
"unicodeVersion": "7.0",
- "digest": "453c24bf2544ed3ef3c710a7fabbd5fdace4dc65cddd377274d30d921523b50b"
+ "digest": "103fabb2260fef61982731785dc3d09884cbfcb6bd4ef93f2d5db8403ae4c40a"
},
"libra": {
"category": "symbols",
"moji": "♎",
"description": "libra",
"unicodeVersion": "1.1",
- "digest": "e330ba05bb449db074bc23d1514246ca5e249110f44ddb5804e5510eef6deac1"
+ "digest": "0189ff934df698ed87a6bac3b29c559567c958a9fbd0259378af8c910e0337e1"
},
"lifter": {
"category": "activity",
"moji": "ðŸ‹",
"description": "weight lifter",
"unicodeVersion": "7.0",
- "digest": "d6c94a32eb863d14a2a01add8ab95040f42a55d9e3f90641a0fe143d58127558"
+ "digest": "d8a22a5258a05e8c31453955103531b59c6018e3e3dfd1f507d6f21ee28b3f00"
},
"lifter_tone1": {
"category": "activity",
"moji": "ðŸ‹ðŸ»",
"description": "weight lifter tone 1",
"unicodeVersion": "8.0",
- "digest": "870acf2f554fce360b58d3e98b4c0558d7ec7775587776c0f9d40c6fb1bdacf9"
+ "digest": "f13372d0812c433eafca5d943a6be6f8f6481bde4e681aa2ee5942bf3a74224f"
},
"lifter_tone2": {
"category": "activity",
"moji": "ðŸ‹ðŸ¼",
"description": "weight lifter tone 2",
"unicodeVersion": "8.0",
- "digest": "1a7ece8512e42241cdd95c85ccc509bc0ff9c7c6ffaff2be343c77f417a27576"
+ "digest": "6a58152d31b5d8992c231e76823beb81dc9d440944d0ebc6bbc7630f9385f163"
},
"lifter_tone3": {
"category": "activity",
"moji": "ðŸ‹ðŸ½",
"description": "weight lifter tone 3",
"unicodeVersion": "8.0",
- "digest": "4bc633ee82a0fb59feba379fb6901a489e4ac849d758f9c8e7a1a0a26eaa380c"
+ "digest": "9fe7befca13df23016568b785e1174122f1b60f8f7a1104bfd1d948ffe2f552e"
},
"lifter_tone4": {
"category": "activity",
"moji": "ðŸ‹ðŸ¾",
"description": "weight lifter tone 4",
"unicodeVersion": "8.0",
- "digest": "d086fe5577b5ba80676f2224d886f8ebe4588314f429f12a34c52c971ed71b5c"
+ "digest": "510cfdae9be775ef9a5866f780a0cd95080b3b6e9959cfbaa41833aa3f24db83"
},
"lifter_tone5": {
"category": "activity",
"moji": "ðŸ‹ðŸ¿",
"description": "weight lifter tone 5",
"unicodeVersion": "8.0",
- "digest": "79b0edf6ce1fd024dd7f458e322ad8588af0b789a04cc1cf38380dc8b9c76f55"
+ "digest": "7347d561a692bd604d3763115cecc66203f1c9a00515de53acecb4d6e0689d65"
},
"light_rail": {
"category": "travel",
"moji": "🚈",
"description": "light rail",
"unicodeVersion": "6.0",
- "digest": "2f30b23a738371690b2f00d96ddb5ceb90a1442b5478754626a3dfa263ed2fc1"
+ "digest": "f7ee16c0a5853c542570a684e25e3fc388e5f52ef8fe7ffaa1120ad7de74a3bd"
},
"link": {
"category": "objects",
"moji": "🔗",
"description": "link symbol",
"unicodeVersion": "6.0",
- "digest": "7bf567aabd1fc38b3d70422f9db3a13b50950cf6207e70962c9938827c196ccb"
+ "digest": "eb23a200ad464e4d16f3d977e8aef3ee0b55da62d2a7cd72743c1f57839c4e02"
},
"lion_face": {
"category": "nature",
"moji": "ðŸ¦",
"description": "lion face",
"unicodeVersion": "8.0",
- "digest": "dd24f2668e973ec973e97dc111f59a2cc14e9b608387401191dd53368d28d4fa"
+ "digest": "59067f1acf8b42395164dc02089624d696549bfdbd60a6dd24d04199a0c3dda2"
},
"lips": {
"category": "people",
"moji": "👄",
"description": "mouth",
"unicodeVersion": "6.0",
- "digest": "8740d8086525c7a836d64625a6915cc1c59af69ba143456dbb59e0179276895e"
+ "digest": "26fb9b50ab57120d2bc613eb1537fc1517f0c962bf3ae0b43fb2da42581dde5c"
},
"lipstick": {
"category": "people",
"moji": "💄",
"description": "lipstick",
"unicodeVersion": "6.0",
- "digest": "751dcb22706a796033b13a2ccb94304236ec13207ad4d011e02d230ae33ab5c1"
+ "digest": "102278217b4f4088fd48ccb08af558822258d85d24a4febdcad1b5cc78cbe2a2"
},
"lizard": {
"category": "nature",
"moji": "🦎",
"description": "lizard",
"unicodeVersion": "9.0",
- "digest": "fb9191f9eab58b8403d4c4626ccbb14ba05c1f6944011751a8edcc4dd03c66e6"
+ "digest": "7c21a4d9e165efe57eca3982944b93ad30bf7ea462bdbf5cb4d63e3dc93e7707"
},
"lock": {
"category": "objects",
"moji": "🔒",
"description": "lock",
"unicodeVersion": "6.0",
- "digest": "043b4fc0b8c79d47a07d91308e628e1ac262aea6c1ec05e6b84bf7bcdf89dc83"
+ "digest": "63408513eaf29059c6025981c27434f71fa2be87dcd060dd9f971d0e54a73922"
},
"lock_with_ink_pen": {
"category": "objects",
"moji": "ðŸ”",
"description": "lock with ink pen",
"unicodeVersion": "6.0",
- "digest": "7b5e959b26cf7296c7b230fc2be9feb9e38391c5001951a019d16b169a71aba9"
+ "digest": "85c1713e44becc6543464d2ff4a07dc46b25a4e40fe233695055236d7c4f62aa"
},
"lollipop": {
"category": "food",
"moji": "ðŸ­",
"description": "lollipop",
"unicodeVersion": "6.0",
- "digest": "17b6a0df47ec758a2f9c087b46a6902cee344d39407ef4c321e408505cbb72ca"
+ "digest": "6499b3140dcc958c4bb99a80ac0424a209d7a978138feb5b919db36443eb529f"
},
"loop": {
"category": "symbols",
"moji": "âž¿",
"description": "double curly loop",
"unicodeVersion": "6.0",
- "digest": "9f20ecc34b3c871789ba7d0712aa31e7a74b6c1558ac8bea385bc40590056726"
+ "digest": "f9044b19663fb8e3e21aeafa6e1022e20be4d61683f13f1472b1feedc0140d7b"
},
"loud_sound": {
"category": "symbols",
"moji": "🔊",
"description": "speaker with three sound waves",
"unicodeVersion": "6.0",
- "digest": "64b12db9ddd8adf74a9fc2bd83c7979ea865113347f7ce8666e9ccf5019e715f"
+ "digest": "6d6affb03b43fbfa71796d83521735af6038bfd236f3dacb77d2097496a73a01"
},
"loudspeaker": {
"category": "symbols",
"moji": "📢",
"description": "public address loudspeaker",
"unicodeVersion": "6.0",
- "digest": "1e1f35d16dd2898ebaa6f2b2868203df6e09c8a70df069c92d6d1b5cb2ac0976"
+ "digest": "04f791bc8d3eb6486448deb2654d9a0cd1c19f946ba623116f556f27399b34a0"
},
"love_hotel": {
"category": "travel",
"moji": "ðŸ©",
"description": "love hotel",
"unicodeVersion": "6.0",
- "digest": "ff8966a50fd47a216855488eb09a367d231fea21f49e7e5325191d32fb494473"
+ "digest": "05e846b25799923b3a85826f40d2d22f9e2ea35855620fdde4d1baec25cf5f25"
},
"love_letter": {
"category": "objects",
"moji": "💌",
"description": "love letter",
"unicodeVersion": "6.0",
- "digest": "037261c8ca4d72f7205e51664591696da2ae7ceb19f1c1c9f6123da5a5979d29"
+ "digest": "2a263ff736055811ce621c61f5ef9d9393bb71e180515a0fdc75107b89c60093"
},
"low_brightness": {
"category": "symbols",
"moji": "🔅",
"description": "low brightness symbol",
"unicodeVersion": "6.0",
- "digest": "a065d00a416e297c168b0a675cafcf492fedf94865cb21801a1be5a3914593d4"
+ "digest": "be7fc79c265d5c02ee7d29fe8290db80cfd794e271463853d6f5d01948c62dfb"
},
"lying_face": {
"category": "people",
"moji": "🤥",
"description": "lying face",
"unicodeVersion": "9.0",
- "digest": "ce836170165e1b70938273f289c02c2106873cd9ab5472dbcd487c2f9f53f13d"
+ "digest": "b7a8bcad9036fa6c0441bbc0558cf6ca32464db8ab7d522af505deb1a07623b3"
},
"m": {
"category": "symbols",
"moji": "â“‚",
"description": "circled latin capital letter m",
"unicodeVersion": "1.1",
- "digest": "54588ac2b7fcd53a96f17124e9de69b617613fcd5af9ad2930a094cb795bb9f4"
+ "digest": "45f66b77808cb780aee7c3440bf57f20f0a7ba3a6048806395e88c47b58263b2"
},
"mag": {
"category": "objects",
"moji": "ðŸ”",
"description": "left-pointing magnifying glass",
"unicodeVersion": "6.0",
- "digest": "a6e31a2efa7d9427aaa30b45d9f4181ee55c44be08aea2df165a86e0e6d9eaa1"
+ "digest": "bfb8b2d3ef82281c7b821c3814c8213d6f853322546f0107575dedc20de31559"
},
"mag_right": {
"category": "objects",
"moji": "🔎",
"description": "right-pointing magnifying glass",
"unicodeVersion": "6.0",
- "digest": "c7d8ceeb05db261e5eaab31dc4da432d0d5592a2ed71e526c5a542daa230bbaf"
+ "digest": "3ee06dcf290a822c5084d8e0cf245a97b354fb03ff0b5f4ae2a7063a6c967ce7"
},
"mahjong": {
"category": "symbols",
"moji": "🀄",
"description": "mahjong tile red dragon",
"unicodeVersion": "5.1",
- "digest": "755d69f988434ce1c17531a8b7ac92ead6f5607c2635a22f10e0ad70f09fc3e6"
+ "digest": "adf2b23065245bbffa1f0e7d0a4656bb2c69d6862f162cd77e9eda26aee06353"
},
"mailbox": {
"category": "objects",
"moji": "📫",
"description": "closed mailbox with raised flag",
"unicodeVersion": "6.0",
- "digest": "2069091be90a530a43ef29d5ec7688c351bf4d5b08d63a0d20d72b67d639ec62"
+ "digest": "492df72deb2679ad387f76edf9c9e7475ef7221c5eb8e24fa6c964e5a3250a61"
},
"mailbox_closed": {
"category": "objects",
"moji": "📪",
"description": "closed mailbox with lowered flag",
"unicodeVersion": "6.0",
- "digest": "d88d65bfebb8216535fd055c69f319564b2cf0b0901820f8312f581864557ed4"
+ "digest": "be27aef10401f26e8f539216b01e2e0774756cb3abb9535d55f91de5415d9737"
},
"mailbox_with_mail": {
"category": "objects",
"moji": "📬",
"description": "open mailbox with raised flag",
"unicodeVersion": "6.0",
- "digest": "69e966b4659128991a70c6a2dd4d647551bedb91bdf5ce688958686bbec56381"
+ "digest": "bfe3df313a2f57bdb99192ce6e674044e385d044020b6e472b2414fe17649805"
},
"mailbox_with_no_mail": {
"category": "objects",
"moji": "📭",
"description": "open mailbox with lowered flag",
"unicodeVersion": "6.0",
- "digest": "9e92d8ee88f660ce56da61077c80ec26c5d8f54ebd2306c4cfa16f6c1b981f83"
+ "digest": "cad6a927c392ed3181284f005eb260976cf69ab6608d59a43ea252a89c89b6e1"
},
"man": {
"category": "people",
"moji": "👨",
"description": "man",
"unicodeVersion": "6.0",
- "digest": "42b882d2c6aa095f1afcf901203838d95c1908bdc725519779186b9c33c728d7"
+ "digest": "72f5a4ee76d2f91fcce52673cdf08867d9322dde33b2b859a2687d20f2875d7a"
},
"man_dancing": {
"category": "people",
"moji": "🕺",
"description": "man dancing",
"unicodeVersion": "9.0",
- "digest": "9f632ee0c886d5f03c61e5f3a27668262c0cc2693b857a91c23c1e5ea3785b9e"
+ "digest": "1d8c16790d9c7affa997923ea15ce09221cdc9d26b6f82150e91d22463b96319"
},
"man_dancing_tone1": {
"category": "activity",
"moji": "🕺ðŸ»",
"description": "man dancing tone 1",
"unicodeVersion": "9.0",
- "digest": "6c56a16cb105bcdd97472645b3a351cebdbb1132cbfd18b0118f289db5fbe741"
+ "digest": "317e619d66577c49fcba699a0b9bf3ee63d100b487c182b4637b5fd46f532bc2"
},
"man_dancing_tone2": {
"category": "activity",
"moji": "🕺ðŸ¼",
"description": "man dancing tone 2",
"unicodeVersion": "9.0",
- "digest": "ed7e78c14d205a03fdd5581e5213add69a55e13b4cbaf76a6d5a0d6c80f53327"
+ "digest": "72a9eea3cee40692a56f234ca59093dfd7ff1113b710a1aaa146b5a137fa213a"
},
"man_dancing_tone3": {
"category": "activity",
"moji": "🕺ðŸ½",
"description": "man dancing tone 3",
"unicodeVersion": "9.0",
- "digest": "13b45403e11800163406206eedeb8b579cc83eca2f60246be97e099164387bc8"
+ "digest": "97824a84dbb9058b4b90e802c1aa72556d3c5f5941599e3e23fd662534b6421a"
},
"man_dancing_tone4": {
"category": "activity",
"moji": "🕺ðŸ¾",
"description": "man dancing tone 4",
"unicodeVersion": "9.0",
- "digest": "f6feb1b0b83565fadcdd1a8737d3daa08893e919547d2a06de899160162d9c4a"
+ "digest": "632fae4e335dae2713a26cc6ac77e62229f88f24db5b33d3c50da13ae7ce8686"
},
"man_dancing_tone5": {
"category": "activity",
"moji": "🕺ðŸ¿",
"description": "man dancing tone 5",
"unicodeVersion": "9.0",
- "digest": "fe20a9ed9ba991653b4d0683de347ed7c226a5d75610307584a2ddd6fcd1e3f2"
+ "digest": "b33a036b2b7f202dc980786796171eeda66caa3cb06320f94617191ec6133ee3"
},
"man_in_tuxedo": {
"category": "people",
"moji": "🤵",
"description": "man in tuxedo",
"unicodeVersion": "9.0",
- "digest": "4d451a971dfefedc4830ba78e19b123f250e09ae65baddccdc56c0f8aa3a9b50"
+ "digest": "2da1693a18afdd9722380c4778183195d006563787b2d8b839a9810a18626798"
},
"man_in_tuxedo_tone1": {
"category": "people",
"moji": "🤵ðŸ»",
"description": "man in tuxedo tone 1",
"unicodeVersion": "9.0",
- "digest": "2814833334fb211ae2ecb1fb5964e9752282d0fb4d7f3477de5dd2a4f812a793"
+ "digest": "506256c184c13806736c599a07f62ac910b5a10130480355d012a53e11894c79"
},
"man_in_tuxedo_tone2": {
"category": "people",
"moji": "🤵ðŸ¼",
"description": "man in tuxedo tone 2",
"unicodeVersion": "9.0",
- "digest": "cd1bab9ee0e2335d3cd99d51216cccdc4fc3c2cf20129b8b7e11a51a77258f68"
+ "digest": "1413dbbe32c1578fbc3a9afe0bec950aab0da5277f6ae286aaae03870aeb0846"
},
"man_in_tuxedo_tone3": {
"category": "people",
"moji": "🤵ðŸ½",
"description": "man in tuxedo tone 3",
"unicodeVersion": "9.0",
- "digest": "f387775f925fe60b9f3e7cad63a55d4d196ddd41658029a70440d14c17cb99f9"
+ "digest": "1c42dc5683bf2f9a5ea719de1eda6f9f872950495581ca2201b61cbcdc74a342"
},
"man_in_tuxedo_tone4": {
"category": "people",
"moji": "🤵ðŸ¾",
"description": "man in tuxedo tone 4",
"unicodeVersion": "9.0",
- "digest": "08debd7a573d1201aee8a2f281ef7cb638d4a2a096222150391f36963f07c622"
+ "digest": "9fcf33a14bec175bd7587db3778fe50c5d31dcf2db37e3e941944df133b5b722"
},
"man_in_tuxedo_tone5": {
"category": "people",
"moji": "🤵ðŸ¿",
"description": "man in tuxedo tone 5",
"unicodeVersion": "9.0",
- "digest": "e3b10e0619f0911cf9b665a265f4ef829b8f6ba6e9c3a021d0539a27e315f8fe"
+ "digest": "941765104eab002f58217ad7ba418a5082732b32faba92e372bafc8debe457f4"
},
"man_tone1": {
"category": "people",
"moji": "👨ðŸ»",
"description": "man tone 1",
"unicodeVersion": "8.0",
- "digest": "7053e265fa7d2594de54a6c5d06c21795b9a7dfb36a1c5594ca43c4c6cc56504"
+ "digest": "fd5531169631dbed6b6380c40732afda0d943980e2a399d9ce65167026f9f33c"
},
"man_tone2": {
"category": "people",
"moji": "👨ðŸ¼",
"description": "man tone 2",
"unicodeVersion": "8.0",
- "digest": "7ebc64de40d3ac60fb761be5cf94f53fa10b4f03fb66add46c90f5d98eaf71eb"
+ "digest": "628574c3994302e2d1ee0742951f26eb3d44aa1abe1161f78df5db3d18bc377f"
},
"man_tone3": {
"category": "people",
"moji": "👨ðŸ½",
"description": "man tone 3",
"unicodeVersion": "8.0",
- "digest": "77ceef4d3740ed4751acb83dd45b6b754cf625c522c6757309cd4d61202d7149"
+ "digest": "431642916465938d09bd6ca5097e716abae550dc5c54dd514519e1561f372b90"
},
"man_tone4": {
"category": "people",
"moji": "👨ðŸ¾",
"description": "man tone 4",
"unicodeVersion": "8.0",
- "digest": "41e6037c393f61cca61b9a81b27ed14a95d75fe380e3a00153c33a371a836ffd"
+ "digest": "26662b4aca1f0a9a24b148a36db1f1119a28e458b1b9addd4ecb4fa36c4c3d3d"
},
"man_tone5": {
"category": "people",
"moji": "👨ðŸ¿",
"description": "man tone 5",
"unicodeVersion": "8.0",
- "digest": "a8cebfd39a5b9c79af7cc37f205e1135376056fee287af967c9f55d415572d99"
+ "digest": "e2f45518af9033350ad4c44a42f564403a7248b4d67c8ec21b19199458aaa4de"
},
"man_with_gua_pi_mao": {
"category": "people",
"moji": "👲",
"description": "man with gua pi mao",
"unicodeVersion": "6.0",
- "digest": "3dae285e900c69986a48db0fa89d4f371a49f38608059cdae52be098030c5ac4"
+ "digest": "f8376151b1df1cca64805f8b64e4b2b3b7358bbd3eb1bbd2cbf363a4a1d542a5"
},
"man_with_gua_pi_mao_tone1": {
"category": "people",
"moji": "👲ðŸ»",
"description": "man with gua pi mao tone 1",
"unicodeVersion": "8.0",
- "digest": "35404d8e266920c78edd9e7143fb052b42f65242a5698494c4f4365e9183cc67"
+ "digest": "858d738820987110c6dc6811b69f4b9b7107304ab4e094c55d2f09e8f506dff4"
},
"man_with_gua_pi_mao_tone2": {
"category": "people",
"moji": "👲ðŸ¼",
"description": "man with gua pi mao tone 2",
"unicodeVersion": "8.0",
- "digest": "82d4f968665a93c7543372c8a1eeb0f25d0ea6842d5e518bd91c226c6c3ab8c2"
+ "digest": "52e61c5ba607cdb6c49a9252bbb9290d117aa991e34c7d352ab82b9ee708680b"
},
"man_with_gua_pi_mao_tone3": {
"category": "people",
"moji": "👲ðŸ½",
"description": "man with gua pi mao tone 3",
"unicodeVersion": "8.0",
- "digest": "f44159f0c672b9b833449382896180e799abf574f5b3c6cd9541caa992fa18ce"
+ "digest": "6ed7de2cb0d2d5434e3fe454b9d56f92f498b7f77a99611ee23f6137627e014c"
},
"man_with_gua_pi_mao_tone4": {
"category": "people",
"moji": "👲ðŸ¾",
"description": "man with gua pi mao tone 4",
"unicodeVersion": "8.0",
- "digest": "c79060188f9461ca34eaa225b7682d8c410883609509fb731c992db69bfeeb50"
+ "digest": "c0c6caca9dfd6e3420483929b16556414d0d64708cecc05b1e6969f9e15cb103"
},
"man_with_gua_pi_mao_tone5": {
"category": "people",
"moji": "👲ðŸ¿",
"description": "man with gua pi mao tone 5",
"unicodeVersion": "8.0",
- "digest": "de9e4acdb10f7abddeeabc0b48d91139fc8b544a601c530db811f099991b0d38"
+ "digest": "a1ce066b7903e2156919a88e1f4824ece7598cc3b8384ee27342cdf4b69310f1"
},
"man_with_turban": {
"category": "people",
"moji": "👳",
"description": "man with turban",
"unicodeVersion": "6.0",
- "digest": "db72c944e93983f38d00e3e936ebb5b243c6069f1f1236d46f6a9f1beb8d6634"
+ "digest": "7741fa53fa283478eec7746c6d3952551980fa2faf2cadd79ad3e60b22413093"
},
"man_with_turban_tone1": {
"category": "people",
"moji": "👳ðŸ»",
"description": "man with turban tone 1",
"unicodeVersion": "8.0",
- "digest": "b6d7489c4cd151af09fff48b62c54c336303e14866e6ef38f94cd834b085d09e"
+ "digest": "e5163b3d793ff9f7f3efe04a4264a160aef3d1c4b6e731a25601a5ebc1f91dc9"
},
"man_with_turban_tone2": {
"category": "people",
"moji": "👳ðŸ¼",
"description": "man with turban tone 2",
"unicodeVersion": "8.0",
- "digest": "7854ef973c21847f452d7e78e5c460ea300e12b539ce92c69dabe8f1bf3a4382"
+ "digest": "f99883c8d09281cdb9a63374e4e418767cf104976fe68f353443e3687b93ecf5"
},
"man_with_turban_tone3": {
"category": "people",
"moji": "👳ðŸ½",
"description": "man with turban tone 3",
"unicodeVersion": "8.0",
- "digest": "1dbd9bd78f5263cbadee7d0d5754c14cfbc914f7329e25fbd97d9f5b8ce0737e"
+ "digest": "168392861e99c39719618454721047f1dc75b8fcef07233079806eccdf0b63be"
},
"man_with_turban_tone4": {
"category": "people",
"moji": "👳ðŸ¾",
"description": "man with turban tone 4",
"unicodeVersion": "8.0",
- "digest": "4f4804da4a7c98ad4f9db3ae3eaf674c8977c638e73414e33ef1f65098e413a3"
+ "digest": "1ed7b32cb652d66421a90378b3fd3dbec0da4124886114152ff199f538d8d593"
},
"man_with_turban_tone5": {
"category": "people",
"moji": "👳ðŸ¿",
"description": "man with turban tone 5",
"unicodeVersion": "8.0",
- "digest": "240282aa346ef9b1d0d475ea93a02597697f0f56f086305879b532b0b933210a"
+ "digest": "0f639e64c4393c5c81d7c8bc3a37b4988acfc7112616dec45c82226fff15f245"
},
"mans_shoe": {
"category": "people",
"moji": "👞",
"description": "mans shoe",
"unicodeVersion": "6.0",
- "digest": "f53fe74abd9906cd3e2dd7e7bddbe1feb9f8f7be28b807fabe452f1f60ca1b84"
+ "digest": "ba3da1749562ad332de9a2c0916c1e72a8b6ccaf277d5c379bf6847f9b6fc148"
},
"map": {
"category": "objects",
"moji": "🗺",
"description": "world map",
"unicodeVersion": "7.0",
- "digest": "84f496a062b5c3ae1e8013506175a69036038c8130891bcf780a69ce7fcbe4de"
+ "digest": "8eb87e7238c5dca1b1b8efb181e42f0d91ca515d3e12dac67aafbe1028338d8e"
},
"maple_leaf": {
"category": "nature",
"moji": "ðŸ",
"description": "maple leaf",
"unicodeVersion": "6.0",
- "digest": "72629a205e33f89337815ad7e51bb5c73947d1a9f98afe5072bdf4846827ae72"
+ "digest": "f16bc6dfd5bd33811f8cbf1bca6733715bb1e8b35109d7038f25497a89e79f8e"
},
"martial_arts_uniform": {
"category": "activity",
"moji": "🥋",
"description": "martial arts uniform",
"unicodeVersion": "9.0",
- "digest": "a1ae797b31081425b388ab31efc635d8eb73a40980fd0fae4708aa5313e2a964"
+ "digest": "d1953d1f75350bcde491bb2a551e55bafc34e14e5de0ca6f27b1d55e0dffa135"
},
"mask": {
"category": "people",
"moji": "😷",
"description": "face with medical mask",
"unicodeVersion": "6.0",
- "digest": "1b58af9ae599308aabf41bbd38f599fa896bd9fe5df7a40be9f2dc7e0e230600"
+ "digest": "20b1988145e75b2ba72f5c595245fc5574315ee8c26fd39f7785c0a6fc5a9906"
},
"massage": {
"category": "people",
"moji": "💆",
"description": "face massage",
"unicodeVersion": "6.0",
- "digest": "6ee48b4d8cec0bf31e11d7803ad9fc1f909457c8c00cb320b5671395af3c170c"
+ "digest": "3c5ede480d35f567954a1dd7082836f0898b44cd41037ce37c0539f8062209a1"
},
"massage_tone1": {
"category": "people",
"moji": "💆ðŸ»",
"description": "face massage tone 1",
"unicodeVersion": "8.0",
- "digest": "9da162c2f39628156b87db986a6ada59372a9e9a6b3f0488d21c9e65ec3309bb"
+ "digest": "d70f8df999a2f2a69eceb60cc09be2d8cabd5121deb051e1e6ef1b60504209c6"
},
"massage_tone2": {
"category": "people",
"moji": "💆ðŸ¼",
"description": "face massage tone 2",
"unicodeVersion": "8.0",
- "digest": "ac259188549b5b429b8c4929e1da2314859e8857ee49720551467aedfcc96567"
+ "digest": "1487da84572a32db39b018369df3ddabb1903294425d9b60091d83ac6b59a48a"
},
"massage_tone3": {
"category": "people",
"moji": "💆ðŸ½",
"description": "face massage tone 3",
"unicodeVersion": "8.0",
- "digest": "cfd9c105b6debc10448f172afcb20d4192899f7ae5aa8af54c834153a5466364"
+ "digest": "c10b984c5225440f3da97df2d00b4a88f41ee1cd9902042f64c557e31ddf944d"
},
"massage_tone4": {
"category": "people",
"moji": "💆ðŸ¾",
"description": "face massage tone 4",
"unicodeVersion": "8.0",
- "digest": "38ab715c621c58454f3cb09153a96380118cf082568554b6edc5f83fb62e9297"
+ "digest": "3140b503be64c8a91a7be46b12585a11b03aba0d3c5186095b734de23b9919e5"
},
"massage_tone5": {
"category": "people",
"moji": "💆ðŸ¿",
"description": "face massage tone 5",
"unicodeVersion": "8.0",
- "digest": "32480457734121b0c83e9be6d693ae379c95535f43f963c0c2f0f20434ee12c6"
+ "digest": "ee0d958448ae7c5f0314520d6dab1220d827ad037d2880a72749433cf6381ab3"
},
"meat_on_bone": {
"category": "food",
"moji": "ðŸ–",
"description": "meat on bone",
"unicodeVersion": "6.0",
- "digest": "d71a8e0b118d5e6ca60690793ce9649afb78e707fcbd7be890a75564c94434fd"
+ "digest": "df7239ae70b5612f38b3bb309d685464cf529a75a6faa27084acbf71dd633a33"
},
"medal": {
"category": "activity",
"moji": "ðŸ…",
"description": "sports medal",
"unicodeVersion": "7.0",
- "digest": "9600cbe57e08da090c60629bcafd2821c87322e738c2454f8e883ceb756e7391"
+ "digest": "b7518a4c832aa937d85741738e1c74c09ff645197fbbdc7d66cd4a8e78977073"
},
"mega": {
"category": "symbols",
"moji": "📣",
"description": "cheering megaphone",
"unicodeVersion": "6.0",
- "digest": "4b1def6b5b051c5045514063f0ac006222ad81fbfe56d840e14bb950713e331b"
+ "digest": "f28088b3880bf25bb1daa9d624ff3d58d8ab768c1d442ab8a9bfec4032b47343"
},
"melon": {
"category": "food",
"moji": "ðŸˆ",
"description": "melon",
"unicodeVersion": "6.0",
- "digest": "0cdd663e6f2129808856cdf0746e6571b62aac641f224adb553baf3bb63ba3bd"
+ "digest": "75e1353511e5b2c345ec411ca9b8dc7d172fcbc7fbe5366ef0ed96c74035ef32"
},
"menorah": {
"category": "symbols",
"moji": "🕎",
"description": "menorah with nine branches",
"unicodeVersion": "8.0",
- "digest": "49fca8c3bc00ea69653ee2f8d4e21e561856ba39716c13e9d107db3e805a2997"
+ "digest": "befdb755f7f872a9061119929ce34d9f0368a5ca7506ba4f3984b24f69b01a27"
},
"mens": {
"category": "symbols",
"moji": "🚹",
"description": "mens symbol",
"unicodeVersion": "6.0",
- "digest": "7d92292586ee12a5d1a557c37da4d14708dc3ce701cf32d3280dcc83d91e5df8"
+ "digest": "eca8312aaade2705ca15be8c1d1fcd897ed4ea0189e995dee3727bcda9d900df"
},
"metal": {
"category": "people",
"moji": "🤘",
"description": "sign of the horns",
"unicodeVersion": "8.0",
- "digest": "ffb750caf187f5d821c990108e2699ac3e216492bcff6ee543f4a7aa55b9fd29"
+ "digest": "9bc7445e2832356d34c88f498c426fcc3fced736323af13cd8bfa18ab4a795f2"
},
"metal_tone1": {
"category": "people",
"moji": "🤘ðŸ»",
"description": "sign of the horns tone 1",
"unicodeVersion": "8.0",
- "digest": "5505f0b0340f9ba572db8897e40adf598cfa784686ad5ee360a7351bf44ddc1d"
+ "digest": "c2107bd9851d508f8128c0dbcd02d3d623597d866d4c938889ec5b4cb2dccf84"
},
"metal_tone2": {
"category": "people",
"moji": "🤘ðŸ¼",
"description": "sign of the horns tone 2",
"unicodeVersion": "8.0",
- "digest": "8f9eee3ad5fc7eeeb30118d16d27467b16fd87297e0ecf02656db77e701f5aeb"
+ "digest": "85583c2c1eff98dc005d2c7cd80f75b18fe4723055b677c8f1bc90207cf0b1fd"
},
"metal_tone3": {
"category": "people",
"moji": "🤘ðŸ½",
"description": "sign of the horns tone 3",
"unicodeVersion": "8.0",
- "digest": "8270a7ecf5eb11431a07ef04cc476c2651ac8aacb0d4768e5cb69355f8a5e84e"
+ "digest": "f004a5b303b1e7bcf20d46bc42214e21f703658f7f83503888c326d9e76cf29f"
},
"metal_tone4": {
"category": "people",
"moji": "🤘ðŸ¾",
"description": "sign of the horns tone 4",
"unicodeVersion": "8.0",
- "digest": "f24f7b137dd6c7899dc0a8794204bbde7ad43ec1e63b419c90dd70a8b77871e8"
+ "digest": "968ebedf7b100f33773f73cfd98c24a62870d022b46ac5c442a8b34184c9a5cf"
},
"metal_tone5": {
"category": "people",
"moji": "🤘ðŸ¿",
"description": "sign of the horns tone 5",
"unicodeVersion": "8.0",
- "digest": "07b0726a632653b980df775f460cd3fe1ea8d4a7b0b46fe29e089b66579482d2"
+ "digest": "be4add5e381ffb482ed191f1f305eeb22707c67e251660ccf76bf550d32e16eb"
},
"metro": {
"category": "travel",
"moji": "🚇",
"description": "metro",
"unicodeVersion": "6.0",
- "digest": "b380247b61b5e2ca1b9b70fabff65907b2c3a5191a14b169ae094af94659b9b1"
+ "digest": "d5053b49a13908a38615c71096d9377d6e8a091f169171eb32d0ab1f209a3424"
},
"microphone": {
"category": "activity",
"moji": "🎤",
"description": "microphone",
"unicodeVersion": "6.0",
- "digest": "9ef4fc2e40d5391c4bb2d30f34f59662cff7cbb1b04341c9dac210d0e21b44ae"
+ "digest": "5d7d70a4347d677eeed8dcd0f87f9ed4b10a14a6ebeb9279eab9d6ed4d505d28"
},
"microphone2": {
"category": "objects",
"moji": "🎙",
"description": "studio microphone",
"unicodeVersion": "7.0",
- "digest": "8a30464d51f7f101335778444c43270ac0679900f49463e6556682d9db1cb4dc"
+ "digest": "c1b14280e7a0bfd9ee4c8f83024f9cbf5a15a5bdadf3a4795f101864a4ad2c6d"
},
"microscope": {
"category": "objects",
"moji": "🔬",
"description": "microscope",
"unicodeVersion": "6.0",
- "digest": "4ca4322c6ba99b8c15acdb8b605f84f87398769e504b262b134c1f3868b2692f"
+ "digest": "b732bdd52a38057a56cfcddf2598c9a2d91f0838686f960a91ddc7333fa0ae12"
},
"middle_finger": {
"category": "people",
"moji": "🖕",
"description": "reversed hand with middle finger extended",
"unicodeVersion": "7.0",
- "digest": "0c3f1cc0ec7323f6d19508ad22fa90050845f7b5cc83f599ab2cacb89cf5dd0e"
+ "digest": "7d543ffbc78a5e8b9162c0f48e4503f6e32efefea7f3b22f436463ace77066fa"
},
"middle_finger_tone1": {
"category": "people",
"moji": "🖕ðŸ»",
"description": "reversed hand with middle finger extended tone 1",
"unicodeVersion": "8.0",
- "digest": "4ebecf1058a3059aaa826eaad39c1a791120f115f65dde6d6ae32fc5561f60f7"
+ "digest": "40a676ff704d57f6b5d2bd8c31b183600781bf3f0ff4342f1e4886717228e0ee"
},
"middle_finger_tone2": {
"category": "people",
"moji": "🖕ðŸ¼",
"description": "reversed hand with middle finger extended tone 2",
"unicodeVersion": "8.0",
- "digest": "85ff506a08c38663c2dfa2e3a90584c02a36aa3dda33af47cdb49834bf9baf83"
+ "digest": "9dcd0cc6a88d67d7fd561fccf95fd3a6030b53598fea69d5de6f14ffd72b3a82"
},
"middle_finger_tone3": {
"category": "people",
"moji": "🖕ðŸ½",
"description": "reversed hand with middle finger extended tone 3",
"unicodeVersion": "8.0",
- "digest": "cac697ff5207bf8a4e091912f3127f4e73c88ef69b5c6561d1d7b12ed60be8f1"
+ "digest": "7787a192eff949d308e925c9df0a44153429df4a290c6f348a950e8414b1d4dc"
},
"middle_finger_tone4": {
"category": "people",
"moji": "🖕ðŸ¾",
"description": "reversed hand with middle finger extended tone 4",
"unicodeVersion": "8.0",
- "digest": "9324a5a4e3986b798ad8c61f31c18fb507ca7a4abfd6e9ae1408b80b185bf8c7"
+ "digest": "b5b4b65aa300d498aaef8753cffb34455111887a12a378b2517297622f428330"
},
"middle_finger_tone5": {
"category": "people",
"moji": "🖕ðŸ¿",
"description": "reversed hand with middle finger extended tone 5",
"unicodeVersion": "8.0",
- "digest": "078f917cd4d8be08a880724e9400449980d92740ccbee4a57f5046a9cf7f6575"
+ "digest": "c08f75c25bd88a288d685849a8575d868b257296c1afae80d241ec5e9193bea3"
},
"military_medal": {
"category": "activity",
"moji": "🎖",
"description": "military medal",
"unicodeVersion": "7.0",
- "digest": "5da18351dc14b66cfc070148c83b7c8e67e6b1e3f515ae501133c38ee5c28d3d"
+ "digest": "745687033024bc5d1dae74f427504058f17f29c1f02a59b25c9d488a6307cae3"
},
"milk": {
"category": "food",
"moji": "🥛",
"description": "glass of milk",
"unicodeVersion": "9.0",
- "digest": "38b28ea40399601fabc95bac5eaaf5a9e4e25548ec80325bd5069395ea884f85"
+ "digest": "3f9229a2c754345be8e721dde032f289fa92c23a11cfd1afe6b38b44d34e435d"
},
"milky_way": {
"category": "travel",
"moji": "🌌",
"description": "milky way",
"unicodeVersion": "6.0",
- "digest": "17405ff31d94b13a1fb0adcda204b8adb95ca340bc3980d9ad9f42ba1e366e7d"
+ "digest": "6664f60e65321fccf491333caca68f961acfdd35a24f299e5909369a94816a6b"
},
"minibus": {
"category": "travel",
"moji": "ðŸš",
"description": "minibus",
"unicodeVersion": "6.0",
- "digest": "08ccb4b1bf397b7c9aed901e2b5dcdd6cb8ca5c5487ef26775bb3120f7b92524"
+ "digest": "7e71052ea22df57fa12c7e3829924ebd3f144b9d71301c34755c10d33ddee697"
},
"minidisc": {
"category": "objects",
"moji": "💽",
"description": "minidisc",
"unicodeVersion": "6.0",
- "digest": "bebf82c0b91ef66321e7ae7a0abf322e59b2f7d8e6fbf9a94243210c00229c59"
+ "digest": "5b6ddb7b5242dffdc04755e8dcac4cc3ae237040481bf076a8c1f95ce0ada3b6"
},
"mobile_phone_off": {
"category": "symbols",
"moji": "📴",
"description": "mobile phone off",
"unicodeVersion": "6.0",
- "digest": "6f9d8d6a32fc998f5d8144a5ff7e2ad00de37ad464cd97285e7c72efb09a1feb"
+ "digest": "93373556567d92fdb11d4e562e74c15ba6b0987cb26dea909b0e922921087628"
},
"money_mouth": {
"category": "people",
"moji": "🤑",
"description": "money-mouth face",
"unicodeVersion": "8.0",
- "digest": "5a43973dadf48a89201b1816fea9972c5cfe501a26fe457b6f7eee0a6362018e"
+ "digest": "99ba4973b84ecb2dbf7e6303190c22c67eedf750f49313135ddbe8e541650688"
},
"money_with_wings": {
"category": "objects",
"moji": "💸",
"description": "money with wings",
"unicodeVersion": "6.0",
- "digest": "15fcf0595021374ba091ca00efdb4167770da4d421eab930964108545f4edab9"
+ "digest": "3d2b0e5939f92d0ab9e40758a9ec239817ad6e9463fd2140803ee229bdc95720"
},
"moneybag": {
"category": "objects",
"moji": "💰",
"description": "money bag",
"unicodeVersion": "6.0",
- "digest": "02d708e2f603b0df6f6c169b5c49b3452e1c02e7d72e96f228b73d0b0a20bff4"
+ "digest": "5fbc74d9eb713ca5d00c8ecb528361bc22c24ab97fdab6606427acc5af480c07"
},
"monkey": {
"category": "nature",
"moji": "ðŸ’",
"description": "monkey",
"unicodeVersion": "6.0",
- "digest": "3588a544d6d9e9995b45d60327a1a42002fa1faa4d48224b140facd249af1c67"
+ "digest": "0e555b55cdaeea97aba5e054ce6c283578036d739466a78be63662872729cf55"
},
"monkey_face": {
"category": "nature",
"moji": "ðŸµ",
"description": "monkey face",
"unicodeVersion": "6.0",
- "digest": "9e263ef5ca42bb76d1b1d1e3cbf020bcf05023a6e9f91301d30c9eb406363a2a"
+ "digest": "f006cc5b32745c0e315ad2b2e995587f7f3dec115f81db7f681e00e040e1ab02"
},
"monorail": {
"category": "travel",
"moji": "ðŸš",
"description": "monorail",
"unicodeVersion": "6.0",
- "digest": "2c9f185babcb4001fcef2b8dfc4a32126729843084d0076c3e3ccdc845ab23ad"
+ "digest": "551b6d88c465c54bd2fc03eb396a6afbc68e24aa41c07203c84fd36e31608836"
},
"mortar_board": {
"category": "people",
"moji": "🎓",
"description": "graduation cap",
"unicodeVersion": "6.0",
- "digest": "d7fbe41d4b340d3564e484aec46a22c9613521414b2ba6eece2180db4d23e410"
+ "digest": "6524faad267ba769fb1997527d41c97cac42cc5d99c57800adaf5a6892c79371"
},
"mosque": {
"category": "travel",
"moji": "🕌",
"description": "mosque",
"unicodeVersion": "8.0",
- "digest": "5f3d3de7feac953a70a318113531c2857d760a516c3d8d6f42d2a3b3b67ed196"
+ "digest": "f15b137d0d23275694d6743602054d05334c9dfb15964378f38defddc8a25b2a"
},
"motor_scooter": {
"category": "travel",
"moji": "🛵",
"description": "motor scooter",
"unicodeVersion": "9.0",
- "digest": "e2dc7c981744a71f46858bd0858ff91af704ac06425ed80377bc3b119e57c872"
+ "digest": "cb76bb0e2f94960426a85f273e2a74046eefebd0b6a265bafecfb8850f0a0c6c"
},
"motorboat": {
"category": "travel",
"moji": "🛥",
"description": "motorboat",
"unicodeVersion": "7.0",
- "digest": "81c156643528c5a94a12d6d478e52a019f5a4e3eb58ee365cdd9d2361a7fdb01"
+ "digest": "edee0a9d9d7b9b9201fc41d5b5a38c939e5f6e2e7baa7891e495b91dc5198e65"
},
"motorcycle": {
"category": "travel",
"moji": "ðŸ",
"description": "racing motorcycle",
"unicodeVersion": "7.0",
- "digest": "354aa8157732184ad50eff9330f7a8915309dc9b7893cc308226adb429311a62"
+ "digest": "b30c2e98f3a439b0c0b6481a5025ee3d380c35a7aa43d7b46c3e948fe732613c"
},
"motorway": {
"category": "travel",
"moji": "🛣",
"description": "motorway",
"unicodeVersion": "7.0",
- "digest": "148c3c13c7c4565453d16e504e0d4b8d007e4f2cad1ab56b1b51fefe39162d17"
+ "digest": "96694ecc0e48e7b0ab1e0a8fdf5e75169ae404fad47620986dfd120571e39e58"
},
"mount_fuji": {
"category": "travel",
"moji": "🗻",
"description": "mount fuji",
"unicodeVersion": "6.0",
- "digest": "f8093b9dba62b22c6c88f137be88b2fd3971c560714db15ec053cf697a3820bc"
+ "digest": "dd27d0550d5df7dd376a43e56e0819a41c48f21cc89e58f36d290140c4effd5e"
},
"mountain": {
"category": "travel",
"moji": "â›°",
"description": "mountain",
"unicodeVersion": "5.2",
- "digest": "07423804ad79da68f140948d29df193f5d5343b7b2c23758c086697c4d3a50da"
+ "digest": "5e0087bb9324c99b5b4f730b8878cadab69cd3af0f580df6c31490a7b7b0abe4"
},
"mountain_bicyclist": {
"category": "activity",
"moji": "🚵",
"description": "mountain bicyclist",
"unicodeVersion": "6.0",
- "digest": "91084b6c887cb7e34f3d7ec30656ecb82c36cc987f53a6c83ccb4c6f7950f96a"
+ "digest": "f3a2fd3bc93fe4e5a039a81e8d5e11b25c949ae041f822a49b15ea7dc35f560e"
},
"mountain_bicyclist_tone1": {
"category": "activity",
"moji": "🚵ðŸ»",
"description": "mountain bicyclist tone 1",
"unicodeVersion": "8.0",
- "digest": "5d57fcfad61bca26c3e8965eb57602a1993a3117ebdda0f24569af730310ab6e"
+ "digest": "dc3b22a219da2c45a6cc45e67ea76e5b35a74eae46f9202dc2f19dd66effc595"
},
"mountain_bicyclist_tone2": {
"category": "activity",
"moji": "🚵ðŸ¼",
"description": "mountain bicyclist tone 2",
"unicodeVersion": "8.0",
- "digest": "c0da7fb85d99aa01a665f64063cd7e2d994f8a16d3f6fbf52df5d471e771a98a"
+ "digest": "1ac6898b085ce24e5d80fbafc2c9c9afe6390beae052097f92bfeb9f85a5f906"
},
"mountain_bicyclist_tone3": {
"category": "activity",
"moji": "🚵ðŸ½",
"description": "mountain bicyclist tone 3",
"unicodeVersion": "8.0",
- "digest": "b099e7ee84eae44ebc99023fa06bdf37ffa0d69767c7c0163a89f7ced2a26765"
+ "digest": "b0c9d179b0ba26c618b69c46aad4f7470b49b9f6c173c452c7a56b61a54537bc"
},
"mountain_bicyclist_tone4": {
"category": "activity",
"moji": "🚵ðŸ¾",
"description": "mountain bicyclist tone 4",
"unicodeVersion": "8.0",
- "digest": "9d09f7b3899ea44e736f237a161ef8d5170dccfa162a872c59532ceaf65ee007"
+ "digest": "e59f743d7e8e8802973da998bc3627f12101508caef7ca2512b8fecb7f9c34d4"
},
"mountain_bicyclist_tone5": {
"category": "activity",
"moji": "🚵ðŸ¿",
"description": "mountain bicyclist tone 5",
"unicodeVersion": "8.0",
- "digest": "71e374981d955056748a60c6d1820b45e9688a156b55318b4ea54a3a67ca801c"
+ "digest": "ca19109c586fc3d0ddf1662b497f517096a813bfcec8184989fa6b578eb57424"
},
"mountain_cableway": {
"category": "travel",
"moji": "🚠",
"description": "mountain cableway",
"unicodeVersion": "6.0",
- "digest": "e261c3292758b1c0063c5a0d0c7f5c9803306d2265e08677027e1210506ced94"
+ "digest": "22969301dc7395450c11ba2c81af096b2ce98da13786109dee70d801563a59b5"
},
"mountain_railway": {
"category": "travel",
"moji": "🚞",
"description": "mountain railway",
"unicodeVersion": "6.0",
- "digest": "b0987f8f391b3cbc7a56b9b8945ebfca240e01d12f8fd163877ebebe51d6b277"
+ "digest": "3ce97b097df39e9e46eb09d1d544b1bd45596a232fd9163b8f02c37ecaffe794"
},
"mountain_snow": {
"category": "travel",
"moji": "ðŸ”",
"description": "snow capped mountain",
"unicodeVersion": "7.0",
- "digest": "49aac2b851aa6f2bd2ca641efa8060f93e89395357f49d211658d46f5a2b0189"
+ "digest": "9b7e802436798fd7eb042bbe31cdb77c124196cd262dca3e671e5ad278fe742f"
},
"mouse": {
"category": "nature",
"moji": "ðŸ­",
"description": "mouse face",
"unicodeVersion": "6.0",
- "digest": "007dd108507b45224f7a1fad3c1de6ecc75f38d71fc142744611eb13555f5eff"
+ "digest": "ba3d78feeca02888c96bc81ffbe07d8be073f695ab17e167d63c4fe0ad2edfc0"
},
"mouse2": {
"category": "nature",
"moji": "ðŸ",
"description": "mouse",
"unicodeVersion": "6.0",
- "digest": "f3ed37b639b7c16aae49502bd423f9fdeabaf15bc6f0f74063954b189e176b5d"
+ "digest": "abd7dded58299599e4cd419c3052e0d4e52ccc788e905201f5dd225b74152aff"
},
"mouse_three_button": {
"category": "objects",
"moji": "🖱",
"description": "three button mouse",
"unicodeVersion": "7.0",
- "digest": "3724341ac5ad0d01027ef1575db64f1db7619f590ca6ada960d1f2c18dc7fc6a"
+ "digest": "aea26b9ebd3ea81d0e8b56c8a0281a94e9862e9deda989ec679150e7aec36b5b"
},
"movie_camera": {
"category": "objects",
"moji": "🎥",
"description": "movie camera",
"unicodeVersion": "6.0",
- "digest": "f7e285eda35b4431c07951e071643ddc34147cd76640e0d516fbfd11208346e9"
+ "digest": "f82751e6f069482fbc01b0d2d135fdf58ef3cf58526b7dbf5b50a71b5ea0ae75"
},
"moyai": {
"category": "objects",
"moji": "🗿",
"description": "moyai",
"unicodeVersion": "6.0",
- "digest": "2c1d0662c95928936e6b9ab5a40c6110ff1cea5339f2803c7b63aabc76115afb"
+ "digest": "19b4b5efdb559f958b114fbaf6a3ad017a42012528de7a1dfedee5dbc3bce3d3"
},
"mrs_claus": {
"category": "people",
"moji": "🤶",
"description": "mother christmas",
"unicodeVersion": "9.0",
- "digest": "357d769371305a8584f46d6087a962d647b6af22fab363a44702f38ab7814091"
+ "digest": "67d7fccbfd20aa195e526485ce40e52994aa4fa9fb71c70533fb579f4ca0ef1f"
},
"mrs_claus_tone1": {
"category": "people",
"moji": "🤶ðŸ»",
"description": "mother christmas tone 1",
"unicodeVersion": "9.0",
- "digest": "244596919e0fed050203cf9e040899de323d7821235929f175852439927bd129"
+ "digest": "c95a39dcdabe20d1f18a2c5cf7cbf1e530fe9ced7ffdbb0f7f8cf833663f8775"
},
"mrs_claus_tone2": {
"category": "people",
"moji": "🤶ðŸ¼",
"description": "mother christmas tone 2",
"unicodeVersion": "9.0",
- "digest": "8cde96e8521f3a90262a7f5f8a2989a9590d9a02cda2c37e92335dc05975c18d"
+ "digest": "425a73cb7d57dbaaf13b1156329ef31a0e9b8cc3917c16b90cc561d4d3373bad"
},
"mrs_claus_tone3": {
"category": "people",
"moji": "🤶ðŸ½",
"description": "mother christmas tone 3",
"unicodeVersion": "9.0",
- "digest": "c39cd4346d4581799dd0e9a6447c91a954a75747bf2682c8e4d79c3b0fcf7405"
+ "digest": "59fd4b47738832f3996b94f67e049edf5d64e0c346b55c9ff09cb893db898fbb"
},
"mrs_claus_tone4": {
"category": "people",
"moji": "🤶ðŸ¾",
"description": "mother christmas tone 4",
"unicodeVersion": "9.0",
- "digest": "84c85cf54559ea2d78d196fee96149a249af4f959b78e223a0ec4fb72abdbcab"
+ "digest": "e96e7945124124002f13cb381f43dad4f40d77b3ec9eb691a58c929ea3214c0d"
},
"mrs_claus_tone5": {
"category": "people",
"moji": "🤶ðŸ¿",
"description": "mother christmas tone 5",
"unicodeVersion": "9.0",
- "digest": "ce26c0e0645713b17e7497d9f2d0484cc5477564dae99320cabf04d160d3b2ff"
+ "digest": "a1639e1ed2d862d48e528a5b3f1da14e8afddbed09fafed8f0ad1dbb75c335dc"
},
"muscle": {
"category": "people",
"moji": "💪",
"description": "flexed biceps",
"unicodeVersion": "6.0",
- "digest": "e4ce52757b2b7982e2516e0e8bf2e2253617cc9f3e6178f1887c61c9039461ba"
+ "digest": "5e6bff383eb4b63009779c1872797eb8b6651788b4005fa0af12b254bb67d404"
},
"muscle_tone1": {
"category": "people",
"moji": "💪ðŸ»",
"description": "flexed biceps tone 1",
"unicodeVersion": "8.0",
- "digest": "4a2fa226a05bb847b62cdd163eb6c2d514d3c2330a727991cf550c0d32b0e818"
+ "digest": "921fd25fcc812896f4d4f8ba7f84af84adc72f624ec464a8a3d7414a788d25e7"
},
"muscle_tone2": {
"category": "people",
"moji": "💪ðŸ¼",
"description": "flexed biceps tone 2",
"unicodeVersion": "8.0",
- "digest": "a8d5ecce335c782ca5f5e55763c06cfefa1c16c24cd6602237cf125d4ff95e47"
+ "digest": "e43dd3f98fa6e0916a3da459a66d8e39cc4d83aab68848343fa830b589ad39d2"
},
"muscle_tone3": {
"category": "people",
"moji": "💪ðŸ½",
"description": "flexed biceps tone 3",
"unicodeVersion": "8.0",
- "digest": "070354b443faec3969663b770545fc4cf5ec75148557b2b9d6fc82ab22b43bd1"
+ "digest": "508b89b10736e79d6e951cdaf0418912dfed191b464ffe93cfd8621493d7b382"
},
"muscle_tone4": {
"category": "people",
"moji": "💪ðŸ¾",
"description": "flexed biceps tone 4",
"unicodeVersion": "8.0",
- "digest": "8eafcdb6a607aeafa673c257df0d2a1b20f00fc0868d811babcbe784490a0dd3"
+ "digest": "ac2e279defdba9ba232b254936f5069f3a17313454d5f2c2f7ca62084a6b50d8"
},
"muscle_tone5": {
"category": "people",
"moji": "💪ðŸ¿",
"description": "flexed biceps tone 5",
"unicodeVersion": "8.0",
- "digest": "85a1e2b5c89907694240e9c5b9d876a741fa7ba38918c5718273e289cbc40efe"
+ "digest": "91b6e61e0815b7f746dae45fae5cdb15d9f4b8608188673260d7e4aa134f58ed"
},
"mushroom": {
"category": "nature",
"moji": "ðŸ„",
"description": "mushroom",
"unicodeVersion": "6.0",
- "digest": "aaca8cf7c5cfa4487b5fef365a231f98be4bbf041197fc022161bcc8ce6f57c8"
+ "digest": "76123b383ae3515904cc8015b730a419c7dac5b16df83e8f0baf7b472e08adbe"
},
"musical_keyboard": {
"category": "activity",
"moji": "🎹",
"description": "musical keyboard",
"unicodeVersion": "6.0",
- "digest": "fb0a726728900377d76d94aac9c94dce29107e8e3f1dcb0599d95bce7169b492"
+ "digest": "85f8bb1668f64cde65c886b207ae588a794e98b6b64dfaee96659b80bc42b644"
},
"musical_note": {
"category": "symbols",
"moji": "🎵",
"description": "musical note",
"unicodeVersion": "6.0",
- "digest": "41288e79b4070bb980281d0e0d1c14d8b144b4aedb2eaadb9f2bebcb4ef892b4"
+ "digest": "9204e70e4d68df5d8ab44087881c90c6d6cce0ac0403d767781cfb8ec23f3a98"
},
"musical_score": {
"category": "activity",
"moji": "🎼",
"description": "musical score",
"unicodeVersion": "6.0",
- "digest": "f0f91b9fa4a2bff7a5a1a11afa6f31cfe7e5fa8b0d6f3cce904b781a28ed0277"
+ "digest": "a379d47ab59308c0faabf74167d53085595a491ced7b1c2d8b9e9fc53575a650"
},
"mute": {
"category": "symbols",
"moji": "🔇",
"description": "speaker with cancellation stroke",
"unicodeVersion": "6.0",
- "digest": "def277da49d744b55c7cdde269a15aa05315898f615e721ee7e9205d7b8030d6"
+ "digest": "5f80daf97d6bffc8451bbf9b4bc3780a2b555e9449c23922a84feef93a238953"
},
"nail_care": {
"category": "people",
"moji": "💅",
"description": "nail polish",
"unicodeVersion": "6.0",
- "digest": "48b33b1dbbd25b4f34ab2ca07bb99ddaaaa741990142c5623310f76b78c076f9"
+ "digest": "1f88d57808e1e93dd8870eb24235b1700337b441ea96b7ddabfdae1377bd5795"
},
"nail_care_tone1": {
"category": "people",
"moji": "💅ðŸ»",
"description": "nail polish tone 1",
"unicodeVersion": "8.0",
- "digest": "a9ac92a34f407e7dd7c71377e6275e66657f7f42e4b911c540d1a66a02d92ac5"
+ "digest": "4faa570dee925e2eaebfc2cd8ccd93dcefd5087e38b6aedadd356ae5234e89a5"
},
"nail_care_tone2": {
"category": "people",
"moji": "💅ðŸ¼",
"description": "nail polish tone 2",
"unicodeVersion": "8.0",
- "digest": "f295ec85980aaa75818fad619c3d25042146ecbbf361db9e9bb96e7bc202bc73"
+ "digest": "320a8d5586f108d66b39cc6df25677fed43bb02914c3c867736881af4195d739"
},
"nail_care_tone3": {
"category": "people",
"moji": "💅ðŸ½",
"description": "nail polish tone 3",
"unicodeVersion": "8.0",
- "digest": "02ec373052a250977298bae85262177910126cc10de9480f1afa328ac2f65a95"
+ "digest": "70d8d5a203e23ada34c18c2f368352efb247823a3db919c75c02f659bdc2601f"
},
"nail_care_tone4": {
"category": "people",
"moji": "💅ðŸ¾",
"description": "nail polish tone 4",
"unicodeVersion": "8.0",
- "digest": "f3d95390ab59caedfda66122bbd0acf3aabedc142fc48352d68900766a7e6f5c"
+ "digest": "71d4e886b73ccdbdab9963bedbd23cbaa3693af5e2b9911db8a51d3d3fbb9843"
},
"nail_care_tone5": {
"category": "people",
"moji": "💅ðŸ¿",
"description": "nail polish tone 5",
"unicodeVersion": "8.0",
- "digest": "009423c97f2aafd24fb8c7c485c58b30bbf9ae6797cc14b80d472b207327b518"
+ "digest": "c3cd47041cf0095e03893e165c9b591d7497abf7271588463ef9e8ca42191108"
},
"name_badge": {
"category": "symbols",
"moji": "📛",
"description": "name badge",
"unicodeVersion": "6.0",
- "digest": "f9f6a4895ff0be8fb2ccc7ad195b94e9650f742f66ead999e90724cfb77af628"
+ "digest": "42cca8b42700765726f33adac7fd6ddb8911d4e2b5ea680c4348c0c699d61c3f"
},
"nauseated_face": {
"category": "people",
"moji": "🤢",
"description": "nauseated face",
"unicodeVersion": "9.0",
- "digest": "f8471cf4720948d8246ec9d30e29783e819f90e3cfe8b1ba628671a1aad1a91c"
+ "digest": "3b3f3fe5fdd6aa6e30bf433d3533438cbee50d337fb2ad83b154873aaac0d9d1"
},
"necktie": {
"category": "people",
"moji": "👔",
"description": "necktie",
"unicodeVersion": "6.0",
- "digest": "01bb18dc8bfe787daa9613b5d09988cd5a065449ef906099ce3cb308c8a7da68"
+ "digest": "1ae4a9a8c38b68c883bf843a044ebb7902ec5c9d73c6bbc1111b847d0353f657"
},
"negative_squared_cross_mark": {
"category": "symbols",
"moji": "âŽ",
"description": "negative squared cross mark",
"unicodeVersion": "6.0",
- "digest": "1cdaf4abc9adafa089c91c2e33a24e9e647aea0f857e767941a899a16ec53b74"
+ "digest": "cb116b6722949b59acdcb92a8a46fb4ab8f0208dafca73a55b49b09b2d8d37a4"
},
"nerd": {
"category": "people",
"moji": "🤓",
"description": "nerd face",
"unicodeVersion": "8.0",
- "digest": "9e5f3c93db25cf1d0f9d6e6bd2993161afec6c30573ba3fe85e13b8c84483d66"
+ "digest": "da428d87fe165911944fb1a15ef2fa4859a1c181fc4dc712907eaea7daba1c85"
},
"neutral_face": {
"category": "people",
"moji": "ðŸ˜",
"description": "neutral face",
"unicodeVersion": "6.0",
- "digest": "7449430a60619956573e9dc80834045296f2b99853737b6c7794c785ff53d64e"
+ "digest": "d69ad475b00bc3770047b0d3e06ebd1f3b6523c285d80402c233bf42fe967e8e"
},
"new": {
"category": "symbols",
"moji": "🆕",
"description": "squared new",
"unicodeVersion": "6.0",
- "digest": "e20bc3e9f40726afd0cfb7268d02f1e1a07343364fd08b252d59f38de067bf06"
+ "digest": "fe42aef2603c69544297c0330168c37a844a191cb541344f49b2b0e3b7b01457"
},
"new_moon": {
"category": "nature",
"moji": "🌑",
"description": "new moon symbol",
"unicodeVersion": "6.0",
- "digest": "dbfc5dcae34b45f15ff767e297cba3a12cb83f3b542db8cfc8dbd9669e0df46c"
+ "digest": "bb7c1576993e7aed13ae107a4f51c41aa1e811038c6c86a82388c8f6fa05dd72"
},
"new_moon_with_face": {
"category": "nature",
"moji": "🌚",
"description": "new moon with face",
"unicodeVersion": "6.0",
- "digest": "c66d347d2222ac8d77d323a07699aff6b168328648db4f885b1ed0e2831fd59b"
+ "digest": "7d341f6f48648d0c4c45677509d3aac49c7b38162a06d28540fca49fb3ec9de6"
},
"newspaper": {
"category": "objects",
"moji": "📰",
"description": "newspaper",
"unicodeVersion": "6.0",
- "digest": "c05e986d9cdac11afa30c6a21a72572ddf50fc64e87ae0c4e0ad57ffe70acc5c"
+ "digest": "591892ad44fd9168ec274c76bf212a15020dd91091623f79526514b9d83f84c3"
},
"newspaper2": {
"category": "objects",
"moji": "🗞",
"description": "rolled-up newspaper",
"unicodeVersion": "7.0",
- "digest": "63db7bcf51effc73e5124392740736383774a4bcfbc1156cf55599504760883d"
+ "digest": "a2d8413b95004751aa47bbb80bd5bd067b0591cf1c832ecb6b7911b88be7043c"
},
"ng": {
"category": "symbols",
"moji": "🆖",
"description": "squared ng",
"unicodeVersion": "6.0",
- "digest": "34d5a11c70f48ea719e602908534f446b192622e775d4160f0e1ec52c342a35c"
+ "digest": "53b461719257c3a5d4c413bebc6a4ab5b6c8c66a76f47f5354fc800746fef815"
},
"night_with_stars": {
"category": "travel",
"moji": "🌃",
"description": "night with stars",
"unicodeVersion": "6.0",
- "digest": "39d9c079be80ee6ce1667531be528a2aa7f8bd46c7b6c2a6ee279d9a207c84a4"
+ "digest": "0ca3f52bf56337784d36c545285fce5777bfe6fb01631c3491e33fec61e12474"
},
"nine": {
"category": "symbols",
"moji": "9ï¸âƒ£",
"description": "keycap digit nine",
"unicodeVersion": "3.0",
- "digest": "8bb40750eda8506ef877c9a3b8e2039d26f20eef345742f635740574a7e8daa6"
+ "digest": "c4f0670503ff77ffd10b8de9f0b5f240283cdf7323889dec6a38240fa5ddeae1"
},
"no_bell": {
"category": "symbols",
"moji": "🔕",
"description": "bell with cancellation stroke",
"unicodeVersion": "6.0",
- "digest": "6542a9a5656c79c153f8c37f12d48f677c89b02ed0989ae37fa5e51ce6895422"
+ "digest": "d04d96e4032e288d191079579c2cc3a24e41e02cc4bb681e85cd0f45e01af0a4"
},
"no_bicycles": {
"category": "symbols",
"moji": "🚳",
"description": "no bicycles",
"unicodeVersion": "6.0",
- "digest": "af71c183545da2ff4c05609f9d572edb64b63ccba7c6a4b208d271558aa92b0a"
+ "digest": "0f0d8e8ab9e421e5f87af7d8dd2afde646d47e35846483e350e11d46039181b6"
},
"no_entry": {
"category": "symbols",
"moji": "â›”",
"description": "no entry",
"unicodeVersion": "5.2",
- "digest": "dc0bac1ed9ab8e9af143f0fce5043fe68f7f46bd80856cdec95d20c3999b637d"
+ "digest": "a960fb2c78aac5ca7ad01e6f5c3dc2212f050f3e4e0dace7bbf79168b63857f6"
},
"no_entry_sign": {
"category": "symbols",
"moji": "🚫",
"description": "no entry sign",
"unicodeVersion": "6.0",
- "digest": "2c1fceef23b62effca68e0e087b8f020125d25b98d61492b1540055d1914fdc3"
+ "digest": "ed0f2355d1edca66757f78849bebeeac010c19bf7d443c04eafa01e15a3f12fe"
},
"no_good": {
"category": "people",
"moji": "🙅",
"description": "face with no good gesture",
"unicodeVersion": "6.0",
- "digest": "6eb970b104389be5d18657d7c04be5149958c26855c52ea68574af852c5f85c4"
+ "digest": "9db57840d894a17c23a77c4a5ed315aa852d85ab2841e3393494c600b635f341"
},
"no_good_tone1": {
"category": "people",
"moji": "🙅ðŸ»",
"description": "face with no good gesture tone 1",
"unicodeVersion": "8.0",
- "digest": "c20a24a1e536240b4dcf90ecb530796de621d7ba1fb9e3fa0f849d048c509c03"
+ "digest": "ecb77f526ecedd1414faf252ec85a7f468ee0429c0684f69eefa28e3cf4e5710"
},
"no_good_tone2": {
"category": "people",
"moji": "🙅ðŸ¼",
"description": "face with no good gesture tone 2",
"unicodeVersion": "8.0",
- "digest": "f31a4628c1f2e6a39288fda8eb19c9ec89983e3726e17a09384d9ecc13ef0b4c"
+ "digest": "509882d9171d11cec481bb561d805c3719828954f71ac6b3ec86b34eeea85bfe"
},
"no_good_tone3": {
"category": "people",
"moji": "🙅ðŸ½",
"description": "face with no good gesture tone 3",
"unicodeVersion": "8.0",
- "digest": "959dec1bfdaf37b20a86ab2bcbdbacd3179c87b163042377d966eab47564c0fb"
+ "digest": "7c8d9ba5acdbcad2e99cee95808de8d65f1d8c8a2474bb1a71aca04158e0a542"
},
"no_good_tone4": {
"category": "people",
"moji": "🙅ðŸ¾",
"description": "face with no good gesture tone 4",
"unicodeVersion": "8.0",
- "digest": "efd931f0080adf2e04129c83a8b24fda0ae7a9fa7c4b463686c0b99023620db8"
+ "digest": "64a58084e10960f9d2c118b927a6bba759f5aa0038988f1984e7578aee4b16e4"
},
"no_good_tone5": {
"category": "people",
"moji": "🙅ðŸ¿",
"description": "face with no good gesture tone 5",
"unicodeVersion": "8.0",
- "digest": "f35df2b26af9baef47c1f8cc97a1b28a58aa7fcb2a13fdac7b2d9189f1e40105"
+ "digest": "20266de1fbdc6ccb83b4da026c7c71c853dc566d49a39ece5b7379f79c3cf68b"
},
"no_mobile_phones": {
"category": "symbols",
"moji": "📵",
"description": "no mobile phones",
"unicodeVersion": "6.0",
- "digest": "a472decd6ac7f9777961c09e00458746b2c04965585e3bee4556be3968e55bcd"
+ "digest": "e7fc1cf8ab08e5144cd9a515098e9ea5e5c6dc7d098b764792a6a175c7ac7cab"
},
"no_mouth": {
"category": "people",
"moji": "😶",
"description": "face without mouth",
"unicodeVersion": "6.0",
- "digest": "72dda8b1e3ad4b05d9b095f9bd05e95d7ba013906c68914976a4554e8edf5866"
+ "digest": "47a0110f84c97673d86cca26854505e47b0e94af996e23eff58e3861baca4b43"
},
"no_pedestrians": {
"category": "symbols",
"moji": "🚷",
"description": "no pedestrians",
"unicodeVersion": "6.0",
- "digest": "062b4a71b338fe09775e465bfba8ac04efbb3640330e8cabe88f3af62b0f4225"
+ "digest": "490933e9068e71aa8ab4e864768dbba8c0dcb76d3958261ba0a3da1139984862"
},
"no_smoking": {
"category": "symbols",
"moji": "🚭",
"description": "no smoking symbol",
"unicodeVersion": "6.0",
- "digest": "ae2ebb331f79f6074091c0ee9cd69fce16d5e12a131d18973fc05520097e14ee"
+ "digest": "90337e0742354ba1e87c0262300e48172cfc5db1c9efb4b6837be49efdec73d3"
},
"non-potable_water": {
"category": "symbols",
"moji": "🚱",
"description": "non-potable water symbol",
"unicodeVersion": "6.0",
- "digest": "32eba0a99b498133c2e4450036f768d3dccaaf5b50adc9ad988757adc777a6a1"
+ "digest": "fded06ba8a998777f04af38833981c8b7980772be1b37509bfbe1692a5e9c81b"
},
"nose": {
"category": "people",
"moji": "👃",
"description": "nose",
"unicodeVersion": "6.0",
- "digest": "9f800e24658ea3cebe1144d5d808cf13a88261f1a7f1f81a10d03b3d9d00e541"
+ "digest": "b53c2b2226bbaf8505e196a760717d503e7bd886c0b3a87c08bc56138867492e"
},
"nose_tone1": {
"category": "people",
"moji": "👃ðŸ»",
"description": "nose tone 1",
"unicodeVersion": "8.0",
- "digest": "a2d0af22284b1d264eb780943b8360f463996a5c9c9584b8473edf8d442d9173"
+ "digest": "bfc69572dac70db3a59abaac127f854ba648d3a8acf4d5dd0478d6c381910776"
},
"nose_tone2": {
"category": "people",
"moji": "👃ðŸ¼",
"description": "nose tone 2",
"unicodeVersion": "8.0",
- "digest": "244dcaa8540024cf521f29f36bd48f933bf82f4833e35e6fa0abf113022038f3"
+ "digest": "b6dfa564b8c1859930b3f01da0131c43e3e96f055e45ff7de166493e1d14aab1"
},
"nose_tone3": {
"category": "people",
"moji": "👃ðŸ½",
"description": "nose tone 3",
"unicodeVersion": "8.0",
- "digest": "c935b64866f0d49da52035aa09f36ff56d238eb7f5b92205386451056e8ea74f"
+ "digest": "1dc363dd57dda74e17467b06eb82bea745bf48faca589ffca709cc1e8dd4ad5e"
},
"nose_tone4": {
"category": "people",
"moji": "👃ðŸ¾",
"description": "nose tone 4",
"unicodeVersion": "8.0",
- "digest": "a87e95fd9319c49e66b6dea0e57319d0ed9921b8d94df037767bf3d5dc7c94f3"
+ "digest": "76c8919041fa06f25d0bc2eb80d8491f673a1f708680bad1e5f8240d1d97949b"
},
"nose_tone5": {
"category": "people",
"moji": "👃ðŸ¿",
"description": "nose tone 5",
"unicodeVersion": "8.0",
- "digest": "1e0f9842e0f8ad5805eabd3f35a6038b7a2e49d566a1f5c17271f9cdf467ca60"
+ "digest": "08db1747f19cf6f1129f38f5e9fcecc51d65043cfd408cb3b6ccbbd9f491165e"
},
"notebook": {
"category": "objects",
"moji": "📓",
"description": "notebook",
"unicodeVersion": "6.0",
- "digest": "fc679d3728f86073d1607a926885dd8b0261132f5c4a0322f1e46ea9f95c8cb8"
+ "digest": "aeb529f82e76ab543f7ab44ef530cbc3558b586559b9e04a6fddc0a0a06ebbb2"
},
"notebook_with_decorative_cover": {
"category": "objects",
"moji": "📔",
"description": "notebook with decorative cover",
"unicodeVersion": "6.0",
- "digest": "d822eda4b49cbfa399b36f134c1a0b8dcfdd27ed89f12c50bc18f6f0a9aa56ef"
+ "digest": "6054dca42cc303e7a8d89111d06aaca38950e179a348fc1a2a7c3405401de8a0"
},
"notepad_spiral": {
"category": "objects",
"moji": "🗒",
"description": "spiral note pad",
"unicodeVersion": "7.0",
- "digest": "c6a8e16aa62474cef13e5659fddb4afc57e3f79635e32e6020edbee2b5b50f18"
+ "digest": "cff2a9d4657b423731ba9d91e366ffd774a8504650039b5757ace4c0911eda9f"
},
"notes": {
"category": "symbols",
"moji": "🎶",
"description": "multiple musical notes",
"unicodeVersion": "6.0",
- "digest": "98467e0adc134d45676ef1c6c459e5853a9db50c8a6e91b6aec7d449aa737f48"
+ "digest": "e18a0e7c520b862def1df85e1d56ef4a18f42e9998a2e9a000045cfddb6bf75d"
},
"nut_and_bolt": {
"category": "objects",
"moji": "🔩",
"description": "nut and bolt",
"unicodeVersion": "6.0",
- "digest": "a77bd72f29a7302195dcec240174b15586de79e3204258e3fb401a6ea90563b3"
+ "digest": "e1a81f58c68ec8371dc7fc146e225fe3b95fcedcea4194da744793a28c3fe263"
},
"o": {
"category": "symbols",
"moji": "â­•",
"description": "heavy large circle",
"unicodeVersion": "5.2",
- "digest": "2387e5fd9ae4c2972d40298d32319b8fa55c50dbfc1c04c5c36088213e6951dd"
+ "digest": "31fd3373121e1690bd2368bb8964007bae2b151345184bd30bc719320b7540b0"
},
"o2": {
"category": "symbols",
"moji": "🅾",
"description": "negative squared latin capital letter o",
"unicodeVersion": "6.0",
- "digest": "6a9ccb0bf394e4d05ffda19327cee18f7b9ed80367fc7f41c93da9bb7efab0bf"
+ "digest": "672d9a179c75b9375f51175db75154a8b0006e60a9b4546658d9cddca8ab0a86"
},
"ocean": {
"category": "nature",
"moji": "🌊",
"description": "water wave",
"unicodeVersion": "6.0",
- "digest": "1a9ca9848d4fb75852addfc10bf84eccf7caa5339714b90e3de4cb6f2518465e"
+ "digest": "495ef59f29b98d5e87b9353274051950dbf7ac9fe486571775389c10e658fa5c"
},
"octagonal_sign": {
"category": "symbols",
"moji": "🛑",
"description": "octagonal sign",
"unicodeVersion": "9.0",
- "digest": "9f6927048e1f9da57f89d1ae1eb86fa4ab7abdbabca756a738a799e948d0b3f9"
+ "digest": "0b138b4b190a12e0601bf71573378d5cce2012d72b9606b01a572ad7f7631c9d"
},
"octopus": {
"category": "nature",
"moji": "ðŸ™",
"description": "octopus",
"unicodeVersion": "6.0",
- "digest": "0fcc65c12f4b29ea75a8c4823d20838a7e6db6978fdcb536943072aa1460bc59"
+ "digest": "215314d376c54c12b73eef4115a8d91a3a21f39e39d41a72b24ef2228595b6af"
},
"oden": {
"category": "food",
"moji": "ðŸ¢",
"description": "oden",
"unicodeVersion": "6.0",
- "digest": "089974cb13a0bef6a245fc73029c5ed5153fd4caae0177b835f779e32200b8aa"
+ "digest": "af6a824831041aacce2e5c510a3bc1a46ddc68f0083bcbfbbd30df941e50ec8b"
},
"office": {
"category": "travel",
"moji": "ðŸ¢",
"description": "office building",
"unicodeVersion": "6.0",
- "digest": "3633a2e91036362e273eef4e0cfbdbbb4cb1208afe2cfa110ebef7b78109a66f"
+ "digest": "404b17445c4da0dc0ec8561604d741bb1c4f1aad8d7d49299249c9732fb33d40"
},
"oil": {
"category": "objects",
"moji": "🛢",
"description": "oil drum",
"unicodeVersion": "7.0",
- "digest": "00b94d33bcc9b9e8a5d4bd6e7f7e2fced9497ce05919edd5e58eafbc011c2caa"
+ "digest": "d2307ad3c2e74c0c5c2594d34e77e0a31a5ef5c0c052a147f24f119054697e1e"
},
"ok": {
"category": "symbols",
"moji": "🆗",
"description": "squared ok",
"unicodeVersion": "6.0",
- "digest": "5f320f9b96e98a2f17ebe240daff9b9fd2ae0727cd6c8e4633b1744356e89365"
+ "digest": "df301dcd8dc7df31e26a6ba360e8f8b3c0f5bd4869301fde41ccfa3271866ab9"
},
"ok_hand": {
"category": "people",
"moji": "👌",
"description": "ok hand sign",
"unicodeVersion": "6.0",
- "digest": "d63002dce3cc3655b67b8765b7c28d370edba0e3758b2329b60e0e61c4d8e78d"
+ "digest": "7ef74c756b59eb60e85daf27cb92962c376733220fbfdb5569be95e67496abc0"
},
"ok_hand_tone1": {
"category": "people",
"moji": "👌ðŸ»",
"description": "ok hand sign tone 1",
"unicodeVersion": "8.0",
- "digest": "ef1508efcf483b09807554fe0e451c2948224f9deb85463e8e0dad6875b54012"
+ "digest": "285a19578d98da6686b597b5e384edab263d8129194dd3672767d9c67632dae5"
},
"ok_hand_tone2": {
"category": "people",
"moji": "👌ðŸ¼",
"description": "ok hand sign tone 2",
"unicodeVersion": "8.0",
- "digest": "1215a101a082fd8e04c5d2f7e3c59d0f480cb0bedd79aeab5d36676bfe760088"
+ "digest": "b746860ad63866d6afac53fb82ac6b593e9fbcedad18728bf874091f12c4284d"
},
"ok_hand_tone3": {
"category": "people",
"moji": "👌ðŸ½",
"description": "ok hand sign tone 3",
"unicodeVersion": "8.0",
- "digest": "6fe0ed9fb42e86bb2bed4cb37b2acacacda1471fb1ee845ad55e54fb0897fbf4"
+ "digest": "b5eba516e1d45861434c3871ef11450771aecc6d219b9328cea618424f2c0f4e"
},
"ok_hand_tone4": {
"category": "people",
"moji": "👌ðŸ¾",
"description": "ok hand sign tone 4",
"unicodeVersion": "8.0",
- "digest": "bfb9041c49d95e901a667264abaf9b398f6c4aa8b52bf5191c122db20c13c020"
+ "digest": "c4f1bf219363ef580b95fcb99e7aa541ddf1464e17d6d837f4a535b8c6eb0b58"
},
"ok_hand_tone5": {
"category": "people",
"moji": "👌ðŸ¿",
"description": "ok hand sign tone 5",
"unicodeVersion": "8.0",
- "digest": "1c218dc04d698da2cbdd7bea1ca3f845f9b386e967b7247c52f4b0f6ec8f5320"
+ "digest": "fccfab629162bb963f7dd60b84a2fd101f52a1f51edaf2e84a4dca5149ec1516"
},
"ok_woman": {
"category": "people",
"moji": "🙆",
"description": "face with ok gesture",
"unicodeVersion": "6.0",
- "digest": "3f8bd4ce2c4497155d697e5a71ebdc9339f65633d07fa9a7903e1bd76cfa4ba1"
+ "digest": "0b08d0e64c0a55e47d0f783034a46fbfe7a742388b2961dd13adcd91217f5551"
},
"ok_woman_tone1": {
"category": "people",
"moji": "🙆ðŸ»",
"description": "face with ok gesture tone1",
"unicodeVersion": "8.0",
- "digest": "1660cd904ccd2ecdc6f4ba00527f7d4ec8c33f3c6183344616f97badae4c3730"
+ "digest": "daaa1c03e25a234c577fa82d868cd7341e4b21262be8a19ebc8ec52c1dfaf3be"
},
"ok_woman_tone2": {
"category": "people",
"moji": "🙆ðŸ¼",
"description": "face with ok gesture tone2",
"unicodeVersion": "8.0",
- "digest": "7ba5fddd1e141424fac6778894dfc5af28e125839c58937c69496f99cd2c4002"
+ "digest": "4441187c1bfb3953731fa3cc98fca07f8ef499001af7c954e9e6c766bc113215"
},
"ok_woman_tone3": {
"category": "people",
"moji": "🙆ðŸ½",
"description": "face with ok gesture tone3",
"unicodeVersion": "8.0",
- "digest": "1d972b8377c52f598406f59ab1e5be41aaf8f027e1fefba3deda66312ccd6a9b"
+ "digest": "08ef7d0a47d54ba9b8ed19c5d317219ea6d675154085c0e311af845a3cc753f9"
},
"ok_woman_tone4": {
"category": "people",
"moji": "🙆ðŸ¾",
"description": "face with ok gesture tone4",
"unicodeVersion": "8.0",
- "digest": "a176328d8f53503aa743448968afd21d72ffd3510555526a3fb38d6b30ee7c15"
+ "digest": "eb8183accaeae7920c7150c13f3d484fefc2868d3203760d4a1e42b04ac14e40"
},
"ok_woman_tone5": {
"category": "people",
"moji": "🙆ðŸ¿",
"description": "face with ok gesture tone5",
"unicodeVersion": "8.0",
- "digest": "13cfc1b589c57e81f768ee07a14b737cafc71407a7eb0956728b2ec4b1df14c4"
+ "digest": "a8fbb88db77c35ce9fdf85ede6ed71de726277464613b46fcc024b0c38acc675"
},
"older_man": {
"category": "people",
"moji": "👴",
"description": "older man",
"unicodeVersion": "6.0",
- "digest": "4c0462b199bf26181c9e4d2d4cb878a32b0294566941212efc67362d0645f948"
+ "digest": "84b2a44e5fcc74bc599566caffd79472cdb5c521d7c1b011753d36b8a629cd3f"
},
"older_man_tone1": {
"category": "people",
"moji": "👴ðŸ»",
"description": "older man tone 1",
"unicodeVersion": "8.0",
- "digest": "99baa083f78cb01166d0a928d0b53682be14be04c29fc17bef14aac1a73a61e6"
+ "digest": "1f9e38cfb593a30d9afc29bdb18fa00ead144290dbd5a1c34190855e58f3f930"
},
"older_man_tone2": {
"category": "people",
"moji": "👴ðŸ¼",
"description": "older man tone 2",
"unicodeVersion": "8.0",
- "digest": "5b4ce713e8820ba517fe92c25f3b93e6a6bf3704d1f982c461d5f31fc02b9d3d"
+ "digest": "ddef54810d7a168ada23e30686ea9a09d2abb440c230ac5c7823ef731b7aac49"
},
"older_man_tone3": {
"category": "people",
"moji": "👴ðŸ½",
"description": "older man tone 3",
"unicodeVersion": "8.0",
- "digest": "0eff72b3226c3a703c635798ee84129a695c896fa011fe1adbc105312eecc083"
+ "digest": "e8f881c06e41460f3e8bb37bba81f11a194b23f2354ddd7ddf3aae44faed2ad9"
},
"older_man_tone4": {
"category": "people",
"moji": "👴ðŸ¾",
"description": "older man tone 4",
"unicodeVersion": "8.0",
- "digest": "ad9ba82b0c5d3b171b0639ee4265370dbddff5e0eeb70729db122659bb8c8f84"
+ "digest": "924a841c5d3ef0a6e3a79d519c38bdff2dff6700dbf51985e06f819f6690b35e"
},
"older_man_tone5": {
"category": "people",
"moji": "👴ðŸ¿",
"description": "older man tone 5",
"unicodeVersion": "8.0",
- "digest": "5eb0a7467cc40e75752e11fd5126b275863dc037557a0d0d3b24b681e00c2386"
+ "digest": "5f893aa727caa220c06c180099c20834abaeeeb7d7b29d64a72259ad7239e487"
},
"older_woman": {
"category": "people",
"moji": "👵",
"description": "older woman",
"unicodeVersion": "6.0",
- "digest": "c261fdf3b01e0c7d949e177144531add5895197fbadf1acbba8eb17d18766bf6"
+ "digest": "b96d5fbaa0fe6d0d21998a617b2c07776542ee2ab1d79424e22b25a1906d42a5"
},
"older_woman_tone1": {
"category": "people",
"moji": "👵ðŸ»",
"description": "older woman tone 1",
"unicodeVersion": "8.0",
- "digest": "1f2bb9e42270a58194498254da27ac2b7a50edaa771b90ee194ccd6d24660c62"
+ "digest": "a5a0475ecc4b452d65f04d31f8ff838531724fbd59c3e00db7c70bc0d87d850f"
},
"older_woman_tone2": {
"category": "people",
"moji": "👵ðŸ¼",
"description": "older woman tone 2",
"unicodeVersion": "8.0",
- "digest": "2e28198e9b7ac08c55980677ed66655fd899e157f14184958bebd87fcd714940"
+ "digest": "0ede94d29641f3cd592c084b1281a475db4e09a0c98ede0af8500b953e26730b"
},
"older_woman_tone3": {
"category": "people",
"moji": "👵ðŸ½",
"description": "older woman tone 3",
"unicodeVersion": "8.0",
- "digest": "c968be0170f7e0c65d4f796337034cfb1daba897884da6fad85635ab5b6edf67"
+ "digest": "6a4878555493bc7f80aea33c0766d2781ef427d96c1e73d623ee74a77c3dab6e"
},
"older_woman_tone4": {
"category": "people",
"moji": "👵ðŸ¾",
"description": "older woman tone 4",
"unicodeVersion": "8.0",
- "digest": "3596a6fa9a643bf79255afcd29657b03850df8499db9669b92ce013af908af44"
+ "digest": "cf7afc02b1d4fb584af1e224be6afa2410a39d3ae1ada553e683b6f14f50dda7"
},
"older_woman_tone5": {
"category": "people",
"moji": "👵ðŸ¿",
"description": "older woman tone 5",
"unicodeVersion": "8.0",
- "digest": "c8998cb3dbd15e22bd1d6dad613d109ce371d9ffca3657e1a8afe5aeb30c1275"
+ "digest": "35aebc57848405f369eacb1defafce49ecc0f3e3833b21e53e46353b8bcdf755"
},
"om_symbol": {
"category": "symbols",
"moji": "🕉",
"description": "om symbol",
"unicodeVersion": "7.0",
- "digest": "5ead73bea546ba9ba6da522f7280cc289c75ff5467742bdba31f92d0e1b3f4e6"
+ "digest": "8cc8000af09220f887582df7d0300da13889d371180fda773894b89ecd0053bb"
},
"on": {
"category": "symbols",
"moji": "🔛",
"description": "on with exclamation mark with left right arrow abo",
"unicodeVersion": "6.0",
- "digest": "9cc61a6b31a30c32dab594191bf23f91e341c4105384ab22158a6d43e6364631"
+ "digest": "2e96678d4a15fd6be2b87c4fbccbe51f4bfafcc9d04c866ce1bc640a80144730"
},
"oncoming_automobile": {
"category": "travel",
"moji": "🚘",
"description": "oncoming automobile",
"unicodeVersion": "6.0",
- "digest": "557c9cacdc3f95215d4f7a6f097a2baa7c007cb9c519492a6717077af4ca6b56"
+ "digest": "a51563ac9f0674e9d398a0da88c94865583f7478b222717e9187064707ec792b"
},
"oncoming_bus": {
"category": "travel",
"moji": "ðŸš",
"description": "oncoming bus",
"unicodeVersion": "6.0",
- "digest": "059f28ce6bfb337e107db5982cbd2004844450ef20b4a54b9ca3cb738360ab05"
+ "digest": "7fba3ec5ef62299568f19384826914c3dd1b4b7d2f27ee575a451e8a764f60a0"
},
"oncoming_police_car": {
"category": "travel",
"moji": "🚔",
"description": "oncoming police car",
"unicodeVersion": "6.0",
- "digest": "aee79306a0d129cfc1980f58db80391eb46d2d7d5f814bf431414dc7680cab72"
+ "digest": "2c13ed1f79d19a50de28061b822b76242ec2ee979a838aa85833a3dc361a3523"
},
"oncoming_taxi": {
"category": "travel",
"moji": "🚖",
"description": "oncoming taxi",
"unicodeVersion": "6.0",
- "digest": "84351489fc86d980b8d3eb9ec4e81120fe700b3ac01346daebe2b7aeb9607a55"
+ "digest": "4cf0f88b9520d40772b743dcf2e618c49c5f74fa57fd46cda4add3bee9e18ef3"
},
"one": {
"category": "symbols",
"moji": "1ï¸âƒ£",
"description": "keycap digit one",
"unicodeVersion": "3.0",
- "digest": "d5d3fff04e68a114ff6464ee06fc831f3f381713045165f62a88d5e8215c195b"
+ "digest": "6e3c571545f5ec85e72b1d694adbcb764099bbcb512b99c89ac8c8b1b6e1de89"
},
"open_file_folder": {
"category": "objects",
"moji": "📂",
"description": "open file folder",
"unicodeVersion": "6.0",
- "digest": "96cfc322ee4903ae8cec07604811742245fd7d14f00bb70276d39d29c48bed28"
+ "digest": "ebcb375b6039c7a7f35fd36bc9240fc401ac9b4225922fc015f7b59773a89e95"
},
"open_hands": {
"category": "people",
"moji": "ðŸ‘",
"description": "open hands sign",
"unicodeVersion": "6.0",
- "digest": "a6c131da2040b48103cea14f280e728675da50fa448d2b3f3438fcbb5bf5596a"
+ "digest": "6200ecf734f542da4a9450f14d4254f2fb5a74fcae3e44a8e96dc639e1271779"
},
"open_hands_tone1": {
"category": "people",
"moji": "ðŸ‘ðŸ»",
"description": "open hands sign tone 1",
"unicodeVersion": "8.0",
- "digest": "867128dff2fa9b860c10c6b792f989f0c057928783696062378f834c0ef89d85"
+ "digest": "d07b0f6efe5a85d1f09f94a297520496659ab93002f9c2ac6d82c73cbadab400"
},
"open_hands_tone2": {
"category": "people",
"moji": "ðŸ‘ðŸ¼",
"description": "open hands sign tone 2",
"unicodeVersion": "8.0",
- "digest": "487ff2745b03d49bb3b1d0acd86ba530fd8cc3f467ca3fa504f88f0ef1cbbc01"
+ "digest": "de7ad131fe4f9e4a20f24fe4bd22fd11a0b896c1bdf216c85045ad2a4407890e"
},
"open_hands_tone3": {
"category": "people",
"moji": "ðŸ‘ðŸ½",
"description": "open hands sign tone 3",
"unicodeVersion": "8.0",
- "digest": "cb8cddc8b8661f874ac9478289d16cc41406b947bb87f3363df518a588a53e16"
+ "digest": "a607b5ca058c240eb530031ec63d57bb4290fa7df42c71a63bc7511759712ae1"
},
"open_hands_tone4": {
"category": "people",
"moji": "ðŸ‘ðŸ¾",
"description": "open hands sign tone 4",
"unicodeVersion": "8.0",
- "digest": "17dcc2c07230846a769f3c79ce618a757c88b9b58c95c6c5b2d7f968814d447d"
+ "digest": "f101e21968a7bc2365758664eb3d121ecc019b2555e2f6d6f984257ba3237b87"
},
"open_hands_tone5": {
"category": "people",
"moji": "ðŸ‘ðŸ¿",
"description": "open hands sign tone 5",
"unicodeVersion": "8.0",
- "digest": "36b2493d67c84cea4f3f85a3088c6abcfd35cf99f7aeaeedfafa420ee878e3d2"
+ "digest": "908cd7f4bdfb6670358287dee92cfdabd18a802f0b7d673f07f3cbb46689e91f"
},
"open_mouth": {
"category": "people",
"moji": "😮",
"description": "face with open mouth",
"unicodeVersion": "6.1",
- "digest": "1906c5100ae0c8326ca5c4f9422976958a38dadd8d77724d68538a25d9623035"
+ "digest": "346f4923115965b864ef63bfc4b34deaadaa2dcbc965ef6285a1b81f9966b9a6"
},
"ophiuchus": {
"category": "symbols",
"moji": "⛎",
"description": "ophiuchus",
"unicodeVersion": "6.0",
- "digest": "6112e2a1656b1cb8bd9a8b0dfa6cbf66d30cae671710a9ef75c821de344aab2b"
+ "digest": "d1b29a9339ee7bce6ff2dc8b12e424ae48f419c8bbf12fb771c0c20c3bcd76ef"
},
"orange_book": {
"category": "objects",
"moji": "📙",
"description": "orange book",
"unicodeVersion": "6.0",
- "digest": "41141b08d2beceded21a94795431603c47fd7d42a3a472a2aa8b2bb25fa87ebf"
+ "digest": "b2744b07ad93a32b7f114bb8e11f0b26445ce0b2b4edf4720f14fc32da3b3cce"
},
"orthodox_cross": {
"category": "symbols",
"moji": "☦",
"description": "orthodox cross",
"unicodeVersion": "1.1",
- "digest": "c16372102f0169dd6d32eb2b27a633aaee74e4e0fddcf723c15ad97f9dc6075c"
+ "digest": "29f438c972e101a1305c0bd5138b6b998778b33bcfd98418538340dc4126a601"
},
"outbox_tray": {
"category": "objects",
"moji": "📤",
"description": "outbox tray",
"unicodeVersion": "6.0",
- "digest": "e47cb481a0ffcb39996f32fd313e19b362a91d8dda15ffca48ac23a3b5bb5baf"
+ "digest": "9ccb7f9dfbec078899a97725772841bc3f2752352abf9fd29765a782169b2330"
},
"owl": {
"category": "nature",
"moji": "🦉",
"description": "owl",
"unicodeVersion": "9.0",
- "digest": "f62ec1ad23ad9038966eea8d8b79660ac212f291af2e89bcdb0fdc683caf41e5"
+ "digest": "f5c1451adf6d1192cc377bc86f25604233d3c9fee42d4b4d4e8b4c4d76d0e981"
},
"ox": {
"category": "nature",
"moji": "ðŸ‚",
"description": "ox",
"unicodeVersion": "6.0",
- "digest": "d13bc60552190bb9936bf32d681bdc742439b702a09cfc62137ea09a98624aed"
+ "digest": "060595f1707bd4b0182c2610e397dbb8800a2410e2205c0156043163b32b9965"
},
"package": {
"category": "objects",
"moji": "📦",
"description": "package",
"unicodeVersion": "6.0",
- "digest": "e82bf5accebb65136e897c15607eef635fb79fd7b2d8c8e19a9eb00b6786918c"
+ "digest": "06ce28df9b4abdb483f7d7eccad4a388fce4ed3596635b8ff148e7399fa99d53"
},
"page_facing_up": {
"category": "objects",
"moji": "📄",
"description": "page facing up",
"unicodeVersion": "6.0",
- "digest": "3884868bdcb2f29615b09a13a30385cbc5269379094a54b5a7e8a5f4e8ce905a"
+ "digest": "d8aa1a6d309f70108aef98ee066419652a91fe5d793a1230f2de922ef6275f03"
},
"page_with_curl": {
"category": "objects",
"moji": "📃",
"description": "page with curl",
"unicodeVersion": "6.0",
- "digest": "3d6257670189f841ad1fa45415c34feb2433b2cb35bb435c4ee122ce89b39669"
+ "digest": "da5752233d152e49c5fac55d89b82fbd1e98b5a6d7f2f574fe7d218879899282"
},
"pager": {
"category": "objects",
"moji": "📟",
"description": "pager",
"unicodeVersion": "6.0",
- "digest": "e21c756cc1c58ebc1b37ebcd38e22a25b31e2e81306c6f18285d6a7671f9eb12"
+ "digest": "196d7a020ab2bb15c8d2ae723c8c8efe161d0e50109af3238727654956c554e5"
},
"paintbrush": {
"category": "objects",
"moji": "🖌",
"description": "lower left paintbrush",
"unicodeVersion": "7.0",
- "digest": "fc0da7a25b726b8be9dd6467953e27293d2313a21eeff21424c2a19be614fff2"
+ "digest": "093064c1459d5b84932aab78fdc8d597e333ab2ce73524733e42c2b609b40f6b"
},
"palm_tree": {
"category": "nature",
"moji": "🌴",
"description": "palm tree",
"unicodeVersion": "6.0",
- "digest": "90fedafd62fe0abf51325174d0f293ebb9a4794913b9ba93b12f2d0119056df1"
+ "digest": "4e5f7c8c216d86839a59a559db1c6b8741d80ec8e2cb8e6c055f7ee5dcf1ceaf"
},
"pancakes": {
"category": "food",
"moji": "🥞",
"description": "pancakes",
"unicodeVersion": "9.0",
- "digest": "5256b4832431e8a88555796b1a9726f12d909a26fb2bdc3a0abff76412c45903"
+ "digest": "5df3886ed4e65b22054269943718a69dcb75744e2dff9e414cf9ab62a2ea0596"
},
"panda_face": {
"category": "nature",
"moji": "ðŸ¼",
"description": "panda face",
"unicodeVersion": "6.0",
- "digest": "56a4b84abe983bd6569be1b81ac5e43071015fd308389a16b92231310ae56a5b"
+ "digest": "8439a209f086e61dde97c5a578dc7b3a23099fd4f5a939e27535956a2c78e5c9"
},
"paperclip": {
"category": "objects",
"moji": "📎",
"description": "paperclip",
"unicodeVersion": "6.0",
- "digest": "d1e2ce94a12b7e8b7a9bba49e47ddc7432ec0288545d3b6817c7a499e806e3f0"
+ "digest": "dbe70e01e1d9bdb96851f18b51cc2380436ab1affe4922c1ad9f4c76811e8453"
},
"paperclips": {
"category": "objects",
"moji": "🖇",
"description": "linked paperclips",
"unicodeVersion": "7.0",
- "digest": "70cefa0d0777f070e393e9f95c24146fe2dd627f30fa3845baa19310d9291fe2"
+ "digest": "d71e54755ddaf37aa86ff2c1cd1d8dc55d2a5b806a0b9080168ea8e28332d46b"
},
"park": {
"category": "travel",
"moji": "ðŸž",
"description": "national park",
"unicodeVersion": "7.0",
- "digest": "444dce8014e0817ddd756c36a38adfbbf7ae4c6aa509e4cae291828f0716d5e7"
+ "digest": "b49486510df4e66e1beb21abdf1eb7745dfb4381a3f76b3f2ffcb2966bf5f5c4"
},
"parking": {
"category": "symbols",
"moji": "🅿",
"description": "negative squared latin capital letter p",
"unicodeVersion": "5.2",
- "digest": "9f1da460a7dd58b26beab8cf701be2691fb812208fbc941c71daa35be1507c2f"
+ "digest": "ccc4a7c9d2d6a1f1fd0788a91618a5178ce8e926d1ebe033ab6d6f77b47b2440"
},
"part_alternation_mark": {
"category": "symbols",
"moji": "〽",
"description": "part alternation mark",
"unicodeVersion": "3.2",
- "digest": "956da19353bb38fd4dfe0ab5360679a9035d566858fb5de62887b85c75fb8eef"
+ "digest": "2cf463fbc9bc4b1f63ec7c4c5cf9601b860c52c6f052c971c8b0c7f4cabe413d"
},
"partly_sunny": {
"category": "nature",
"moji": "â›…",
"description": "sun behind cloud",
"unicodeVersion": "5.2",
- "digest": "8fb9a6d2caf9e0cce58447762f0dfd6aa0b581b2e83fea6411348e0cbc8cf3c4"
+ "digest": "3e3e120cd4b1fc10548064d7cc529ea3c04eec3f8ac457b90628c119ba62d1f6"
},
"passport_control": {
"category": "symbols",
"moji": "🛂",
"description": "passport control",
"unicodeVersion": "6.0",
- "digest": "d9be6eed2c90e1c89171c42d70a06485fdf86a4c68833371832cc1f6897fadd0"
+ "digest": "cd2221bd39e8517b14d1509afcebf3aeb138d0b286c1012544e2950671affa1a"
},
"pause_button": {
"category": "symbols",
"moji": "â¸",
"description": "double vertical bar",
"unicodeVersion": "7.0",
- "digest": "143221d99e82399ed7824b6c5e185700896492058b65c04e4c668291de78b203"
+ "digest": "08bf08733cf20f2afebc56318c86ad3a0a783305dd7c3ee72d7b8898dcd39fc8"
},
"peace": {
"category": "symbols",
"moji": "☮",
"description": "peace symbol",
"unicodeVersion": "1.1",
- "digest": "65181429e373c1f0507bbd98425c1bec0c042d648fb285a392460cbce60f44d4"
+ "digest": "375030a1230116742eed0b632822936e92179f2da97b73faef675140db76f4db"
},
"peach": {
"category": "food",
"moji": "ðŸ‘",
"description": "peach",
"unicodeVersion": "6.0",
- "digest": "768d1f4f29e1e06aff5abb29043be83087ded16427ce6a2d0f682814e665e311"
+ "digest": "952c053be4d68b53c35b0d43e83557606dc235afd821595236c8f80fb8602608"
},
"peanuts": {
"category": "food",
"moji": "🥜",
"description": "peanuts",
"unicodeVersion": "9.0",
- "digest": "e2384846b6e4a6c3a56e991ebb749cb68b330ac00a9e9d888b2c39105ff7ff5d"
+ "digest": "f18fe7dfb1eb5e9db42fc3c37d4c4fb4866d9ad26ecf9f6cf5be798a09fc58eb"
},
"pear": {
"category": "food",
"moji": "ðŸ",
"description": "pear",
"unicodeVersion": "6.0",
- "digest": "b7c9cf90bb979649b863d2f4132f1b51f6f8107d42e08fb8b4033fea32844948"
+ "digest": "73114dab6e3ec572ae1f9a98e85961605b6a98cdd19497e6957eec60941959b5"
},
"pen_ballpoint": {
"category": "objects",
"moji": "🖊",
"description": "lower left ballpoint pen",
"unicodeVersion": "7.0",
- "digest": "aacb20b220f26704e10303deeea33be0eec2d3811dcba7795902ca44b6ae9876"
+ "digest": "7739947fa359e641e04f51bae4ba292613fa2692b17b3f2b3c4bf27c82e97d82"
},
"pen_fountain": {
"category": "objects",
"moji": "🖋",
"description": "lower left fountain pen",
"unicodeVersion": "7.0",
- "digest": "3619913eab2b6291f518b40481bb3eca0820d68b0a1b3c11fb6a69c62b75a626"
+ "digest": "114ba929b5f8812b9767e8260112ebcebd04a46175c3d5d487d71ca36c372d40"
},
"pencil": {
"category": "objects",
"moji": "ðŸ“",
"description": "memo",
"unicodeVersion": "6.0",
- "digest": "accbc3f1439b7faa4411e502385f78a16c8e71851f71fc13582753291ffb507c"
+ "digest": "d18a7c355267e820ac7694c6f7da276b19a59fd42fca4eab74b7f3653e4acdd6"
},
"pencil2": {
"category": "objects",
"moji": "âœ",
"description": "pencil",
"unicodeVersion": "1.1",
- "digest": "9ca1b56b5726f472b1f1b23050ed163e213916dac379d22e38e4c8358fe871e0"
+ "digest": "537f6d69a4039270d8856febea24fd3021005da6f35dca29e5491ee49cc3b217"
},
"penguin": {
"category": "nature",
"moji": "ðŸ§",
"description": "penguin",
"unicodeVersion": "6.0",
- "digest": "a1800ab931d6dc84a9c89bfab2c815198025c276d952509c55b18dd20bd9d316"
+ "digest": "0735168781cd9316b40fbce845a55980acc33491112aea840b26b0cef226ccc0"
},
"pensive": {
"category": "people",
"moji": "😔",
"description": "pensive face",
"unicodeVersion": "6.0",
- "digest": "d237deff9f5ead8a0b281b7e5c6f4b82e98cc30c80c86c22c3fdc6160090b2f2"
+ "digest": "9da78949740dfdb9c72127f5b7aef68c3b0ba1e5462f5cefcd4d22bdbc4857f9"
},
"performing_arts": {
"category": "activity",
"moji": "🎭",
"description": "performing arts",
"unicodeVersion": "6.0",
- "digest": "d7c7bc9213e308ca26286cbbd8012e656b0f9b00293758faf1bfccc4c5ceabed"
+ "digest": "d4f55655f113bc672739e74b6e3b7684b05f49a68a8ce1a230a32295d0d7a847"
},
"persevere": {
"category": "people",
"moji": "😣",
"description": "persevering face",
"unicodeVersion": "6.0",
- "digest": "c361509c9b8663af19a02a1ffff61b1b0d0b4bd75d693ce3d406b0ca1bde1ca0"
+ "digest": "5297ca44798cb08da3651322d7f34d45e88333f820cfcd9cce4a540b3333ca63"
},
"person_frowning": {
"category": "people",
"moji": "ðŸ™",
"description": "person frowning",
"unicodeVersion": "6.0",
- "digest": "b37be8bd95f21a6860ad3f171b8086125ab37331b382d87bcdb4cd684800546b"
+ "digest": "cc38a861c7edbc5eae6bb91beb2acfc5d044453960f612c36693ef71663b1d5e"
},
"person_frowning_tone1": {
"category": "people",
"moji": "ðŸ™ðŸ»",
"description": "person frowning tone 1",
"unicodeVersion": "8.0",
- "digest": "3d5e78a367f9673baed2a86bc11cf04fd44394aadb65291fa51ade8dca318427"
+ "digest": "d7350116b174ba8902292c382a410a458e86d68fd977d7e8e80ce8b47d80eb3e"
},
"person_frowning_tone2": {
"category": "people",
"moji": "ðŸ™ðŸ¼",
"description": "person frowning tone 2",
"unicodeVersion": "8.0",
- "digest": "7456c414c65ad6b6f11855f68a2eedc18113526f86862c4373202397cb1bed2c"
+ "digest": "09bfa39a6b743494967806691248ab94a90bb8efc934a3e08eb13cc9a1221989"
},
"person_frowning_tone3": {
"category": "people",
"moji": "ðŸ™ðŸ½",
"description": "person frowning tone 3",
"unicodeVersion": "8.0",
- "digest": "c86cf2d6951f1e6a7c786a74caaf68a777cf00e88023e23849d4383f864ae437"
+ "digest": "3631d7c4d757007ca5b1543c0819b351fa70dd1fa76dc4e947bb074119837143"
},
"person_frowning_tone4": {
"category": "people",
"moji": "ðŸ™ðŸ¾",
"description": "person frowning tone 4",
"unicodeVersion": "8.0",
- "digest": "944e96ced645ced8db6bb50120c7e37ed46b6960d595cbfe964c81803efa83aa"
+ "digest": "852c4794d10336cb636d615d702504cf58bbdcf5a7269e9bc3e2b215074d11a0"
},
"person_frowning_tone5": {
"category": "people",
"moji": "ðŸ™ðŸ¿",
"description": "person frowning tone 5",
"unicodeVersion": "8.0",
- "digest": "4bd0ea571be6ef9f0493784ef0d12d5e47bc2d6ac610fb42c450bf3d87fb2948"
+ "digest": "ac64dda090f40addeab42d79bee681060d3b43de56b461fb94883d67fb24e1c6"
},
"person_with_blond_hair": {
"category": "people",
"moji": "👱",
"description": "person with blond hair",
"unicodeVersion": "6.0",
- "digest": "a7f94ede2e43308108c2260d83fc10121dda09a67f94a0a840e6d7bba7fd5616"
+ "digest": "9194bee1257b169fdcb1858023922b83a0ea10cb2f6c2bbc8824e1d15250416d"
},
"person_with_blond_hair_tone1": {
"category": "people",
"moji": "👱ðŸ»",
"description": "person with blond hair tone 1",
"unicodeVersion": "8.0",
- "digest": "00a116357a7878554c83e5bade4bddfa9cfabf76a229efa19cbb58e0d216219c"
+ "digest": "bbbd79e4de2b447b081cbc82426f7d2584760489576426768cdf7e1e0e43c249"
},
"person_with_blond_hair_tone2": {
"category": "people",
"moji": "👱ðŸ¼",
"description": "person with blond hair tone 2",
"unicodeVersion": "8.0",
- "digest": "df509ebe92ed3138b9d5bd4645eff4b13f77f714cf62bb949c59eff1adc00019"
+ "digest": "23885c8e9d0d34eadf6941e6001c3f03863ebcef8c97733929cb0f61a03b48a9"
},
"person_with_blond_hair_tone3": {
"category": "people",
"moji": "👱ðŸ½",
"description": "person with blond hair tone 3",
"unicodeVersion": "8.0",
- "digest": "6f328513f440a0c8cd1dc44596a5028fd8f306bdaf57c1e6f3aa94a3aa262b3c"
+ "digest": "87ab121eb227c13fbe454537078761484acf1f09eeae4981bb46021ccd7b71de"
},
"person_with_blond_hair_tone4": {
"category": "people",
"moji": "👱ðŸ¾",
"description": "person with blond hair tone 4",
"unicodeVersion": "8.0",
- "digest": "32df1a577815b009696643ad80d063cc97b35d54add6d4e5517fc936f6da9ee8"
+ "digest": "cd12e7c5a19a4a1b5445ecf98adca9e3ac4361a9b01ff8a18d13693af50bbf3a"
},
"person_with_blond_hair_tone5": {
"category": "people",
"moji": "👱ðŸ¿",
"description": "person with blond hair tone 5",
"unicodeVersion": "8.0",
- "digest": "2e270bb39187d8e36a33f4aa4d6045308189595fafc157cf7993e82d7ce93442"
+ "digest": "d11a5989a12155e1bb3432d672aff88311afc947a65c3e1c640b9e1d42cdeb0c"
},
"person_with_pouting_face": {
"category": "people",
"moji": "🙎",
"description": "person with pouting face",
"unicodeVersion": "6.0",
- "digest": "57e9a6e5f82121516dc189173f2a63b218f726cd51014e24a18c2bdfeeec3a0b"
+ "digest": "687a13af899b65a14f27c205c9fffdc4ce50edc86b55f9dab05711f21a8fa06f"
},
"person_with_pouting_face_tone1": {
"category": "people",
"moji": "🙎ðŸ»",
"description": "person with pouting face tone1",
"unicodeVersion": "8.0",
- "digest": "d10dadb1ac03fc2e221eff77b4c47935dc0b4fe897af3de30461e7226c3b4bbc"
+ "digest": "dd6d64d1d51bca83c0b3212d028394cdb84e8550e6740e3a862ce24379a522ea"
},
"person_with_pouting_face_tone2": {
"category": "people",
"moji": "🙎ðŸ¼",
"description": "person with pouting face tone2",
"unicodeVersion": "8.0",
- "digest": "efface531537ab934b3b96985210a2dac88de812e82e804d6ec12174e536d1cc"
+ "digest": "7ef959a93142351a77e62074a5b339afa63b7019b23e3b823e8d95a5c82863f2"
},
"person_with_pouting_face_tone3": {
"category": "people",
"moji": "🙎ðŸ½",
"description": "person with pouting face tone3",
"unicodeVersion": "8.0",
- "digest": "7ff26ece237216b949bfa96d16bd12cfd248c6fd3e4ed89aa6c735c09eafaeff"
+ "digest": "777c69c3b59b9688b5cda0cd61b67aaedf742c2758b4ea1537170f1648185dcf"
},
"person_with_pouting_face_tone4": {
"category": "people",
"moji": "🙎ðŸ¾",
"description": "person with pouting face tone4",
"unicodeVersion": "8.0",
- "digest": "045c04105df41d94ff4942133c7394e42ff35ef76c4ccb711497ab77ae6219f2"
+ "digest": "ee918ba63a9dbb71aa7a2a19552da4a86ecd3a15ff6b01b00595b04c98a8d3f4"
},
"person_with_pouting_face_tone5": {
"category": "people",
"moji": "🙎ðŸ¿",
"description": "person with pouting face tone5",
"unicodeVersion": "8.0",
- "digest": "783ee37f146fcf61d38af5009f5823cf6526fe99ed891979f454016bce9dd4ba"
+ "digest": "a1d4e4e89b7c8044a38a68d7cdb96d7ee576296689c996225e778af9b033dbfa"
},
"pick": {
"category": "objects",
"moji": "â›",
"description": "pick",
"unicodeVersion": "5.2",
- "digest": "7f0ec5445b4d5c66cf46e2a7332946cce34bd70e9929ac7a119251a7f57f555d"
+ "digest": "c74411a556653f5b4b0825627089ab96c01ecdd8d472697c961c22c8a99a6265"
},
"pig": {
"category": "nature",
"moji": "ðŸ·",
"description": "pig face",
"unicodeVersion": "6.0",
- "digest": "51362570ab36805c8f67622ee4543e38811f8abb20f732a1af2ffbff2d63d042"
+ "digest": "7ce19e18b6fb941b8075e18f8c680048828c8b129d1a74a9ac3c2ae937a02aa5"
},
"pig2": {
"category": "nature",
"moji": "ðŸ–",
"description": "pig",
"unicodeVersion": "6.0",
- "digest": "67010e255f28061b9d9210bcdab6edc072642ad134122a1d0c7e3a6b1795a45b"
+ "digest": "ba4acbc207d817071d485e33186f5ddc20d470a0dc468fb1fea502d4768c25d7"
},
"pig_nose": {
"category": "nature",
"moji": "ðŸ½",
"description": "pig nose",
"unicodeVersion": "6.0",
- "digest": "0b21cac238bf4910939fbea9bed35552378c1b605a3867d7b85c1556dbda22a9"
+ "digest": "f9fb90cd7919ed06aec8bf6b0cda13fcd6a58b25329b48a57714d0909a290e4b"
},
"pill": {
"category": "objects",
"moji": "💊",
"description": "pill",
"unicodeVersion": "6.0",
- "digest": "cb00be361aaba6dbcf8da58bd20b76221dd75031362ecae99496b088ed413a7f"
+ "digest": "dea2366892fb3739ba549da27d7d0f75871d073099ae61a1d0e1c7683bd274d5"
},
"pineapple": {
"category": "food",
"moji": "ðŸ",
"description": "pineapple",
"unicodeVersion": "6.0",
- "digest": "621d4d4c52b59e566c2e29ed7845c8bd2d1da0946577527342097808d170dd70"
+ "digest": "62e7ffdfac3638f71d1381861a87d6f361718912099ddd4df1bc8245d6a1fc2f"
},
"ping_pong": {
"category": "activity",
"moji": "ðŸ“",
"description": "table tennis paddle and ball",
"unicodeVersion": "8.0",
- "digest": "943a858bd054c81a08a08951f8351c27c8009b85a9359729c7362868298b58e1"
+ "digest": "f55f8483698dd2252aa5e2819f98e2f5d753616319446067de16acc5ffe12129"
},
"pisces": {
"category": "symbols",
"moji": "♓",
"description": "pisces",
"unicodeVersion": "1.1",
- "digest": "453c3915122a4b6b32867056d2447be48675a84469145c88d52f8007fcb0861a"
+ "digest": "2b9982d42db6ef3b280174b79faa2ce0178f349b826474883297fbbea088b2ea"
},
"pizza": {
"category": "food",
"moji": "ðŸ•",
"description": "slice of pizza",
"unicodeVersion": "6.0",
- "digest": "169bc6c1e1d7fdab1b8bf2eab0eeec4f9a7ae08b7b9b38f33b0b0c642e72053a"
+ "digest": "74f0ca139931c470d814ed91f1bc7d395205b3d836fa2f425c50dff56d77ccb9"
},
"place_of_worship": {
"category": "symbols",
"moji": "ðŸ›",
"description": "place of worship",
"unicodeVersion": "8.0",
- "digest": "daf271d36a38ee8c0f8b9de84c128ab8b25a5b7df8f107308d0353c961f2c644"
+ "digest": "39562f00c92f6a75028f57faf3f951026866f42bca6e51bcbbf30f442e24c63a"
},
"play_pause": {
"category": "symbols",
"moji": "â¯",
"description": "black right-pointing double triangle with double vertical bar",
"unicodeVersion": "6.0",
- "digest": "af1498f34a3d6e0da8bbd26ebaa447e697e2df08c8eb255437cf7905c93f8c42"
+ "digest": "a4fe3a6a5928f88e77c643e7869e4edade8cd19839ec7e347265439483463019"
},
"point_down": {
"category": "people",
"moji": "👇",
"description": "white down pointing backhand index",
"unicodeVersion": "6.0",
- "digest": "4ecdb3f31c16dc38113b8854ec1a7884613b688a185ebdf967eab9a81018f76d"
+ "digest": "4fa9f01922409ef7831ad0ab78782174dd59c46e74e9a76c38111fcdbc1666a1"
},
"point_down_tone1": {
"category": "people",
"moji": "👇ðŸ»",
"description": "white down pointing backhand index tone 1",
"unicodeVersion": "8.0",
- "digest": "c74a7c94367cddbfa840542dc0924adeb0d108be0c7fde8c25fb95d69115d283"
+ "digest": "e64f86886b78db3088952713caef3144f99ba1d8b5f730e640c4ae42762fb645"
},
"point_down_tone2": {
"category": "people",
"moji": "👇ðŸ¼",
"description": "white down pointing backhand index tone 2",
"unicodeVersion": "8.0",
- "digest": "dc4bda0726d85418b974addb42738f437fbb9cf16e5815cdbab3859c4ada6cae"
+ "digest": "7d44c5c286b83afdc301c8a39bda0e1619d8a099cc576cbcebf55af15931a55e"
},
"point_down_tone3": {
"category": "people",
"moji": "👇ðŸ½",
"description": "white down pointing backhand index tone 3",
"unicodeVersion": "8.0",
- "digest": "e460f81a501376d2f0ed1d45e358c5ed03ba049e8f466e4298afb4f3ca6d24dc"
+ "digest": "33d981c6cd9641f2864b807bc2e288798bbd56bbd413e1aa4d23d42bb6e1af74"
},
"point_down_tone4": {
"category": "people",
"moji": "👇ðŸ¾",
"description": "white down pointing backhand index tone 4",
"unicodeVersion": "8.0",
- "digest": "4bc91cd771f24e0f897a9d8b18f323fec9a82da0fc2429c4a7e4e6a9d885a0a3"
+ "digest": "19dc8c01dd571e65f0314cc18b55bde4038617b782808faae976cffb0fadfce4"
},
"point_down_tone5": {
"category": "people",
"moji": "👇ðŸ¿",
"description": "white down pointing backhand index tone 5",
"unicodeVersion": "8.0",
- "digest": "7e47c6bc73250f36dc7ae1c1c09e7b41f30647b9d0ff703a53a75cc046b5057d"
+ "digest": "67b1413272b5a0c8efbbd5461bd6fd89849ac5f8dc0d1dac26e2edfcc6b9d1ea"
},
"point_left": {
"category": "people",
"moji": "👈",
"description": "white left pointing backhand index",
"unicodeVersion": "6.0",
- "digest": "b5a7e864a0016afbadb3bec41f51ecf8c4af73cc20462e1a08b357f90bca6879"
+ "digest": "b7f186ed45ddd21e5c62cbc3d5040194ae1282caad89508fa628c248b3edf0bd"
},
"point_left_tone1": {
"category": "people",
"moji": "👈ðŸ»",
"description": "white left pointing backhand index tone 1",
"unicodeVersion": "8.0",
- "digest": "9f1868272a10a2b738c065be5d30241643324550cfd47baf01c7a09060e66d31"
+ "digest": "439f771d094340a43f83b8f2e05b39d90b2ec3921756fea2878754119aafd683"
},
"point_left_tone2": {
"category": "people",
"moji": "👈ðŸ¼",
"description": "white left pointing backhand index tone 2",
"unicodeVersion": "8.0",
- "digest": "bf0d58c68178a2c2c01d4a6235a1a66b90073cea170f9f6fe2668b6dd68424f7"
+ "digest": "73d6b8d0df34df349653fcfdbcc2adbc98ba6c25f612d933cc52da1154af37f2"
},
"point_left_tone3": {
"category": "people",
"moji": "👈ðŸ½",
"description": "white left pointing backhand index tone 3",
"unicodeVersion": "8.0",
- "digest": "34d28c97bc8f9d111d14e328153c4298fc32cf18e39e20aacaec17846645ed90"
+ "digest": "1cfd0d1db8a06ead619a12bd248c4c9fda7b6b50309a2526a20bfc66dcb86177"
},
"point_left_tone4": {
"category": "people",
"moji": "👈ðŸ¾",
"description": "white left pointing backhand index tone 4",
"unicodeVersion": "8.0",
- "digest": "c40c8436316915d516c53bb1c98a469528cefd98baa719be7e748c4608cbbcc9"
+ "digest": "26b4755890f8e290e7d8958566612c14caa6522a7bd43a3d7e8c206436fad70b"
},
"point_left_tone5": {
"category": "people",
"moji": "👈ðŸ¿",
"description": "white left pointing backhand index tone 5",
"unicodeVersion": "8.0",
- "digest": "c410fe32e4ce0ded74845a54b86090e59e5820d457837b16e175b36cc71ecb46"
+ "digest": "8ca52d65aaedcf7ca346e90da3f53b50af83dfd544ed8631b4da1ab31e5e1497"
},
"point_right": {
"category": "people",
"moji": "👉",
"description": "white right pointing backhand index",
"unicodeVersion": "6.0",
- "digest": "44d9251ab41f2f48c2250c44a47f92b3476a71f13fbbbfb637547db837fd5a49"
+ "digest": "2d27c0ffba78c5c5fbd502dd42fbbae220c8619c8a2b964bef03e4a84ad4a1b6"
},
"point_right_tone1": {
"category": "people",
"moji": "👉ðŸ»",
"description": "white right pointing backhand index tone 1",
"unicodeVersion": "8.0",
- "digest": "9fcce259eb81c0b52ec7796b98a1653194e3a9021a1d338df1dbbab7522fc406"
+ "digest": "c2f84a57648a6de49b2b9000afd2c45ce1ef8f303d71f248b292e3fe83b8cf94"
},
"point_right_tone2": {
"category": "people",
"moji": "👉ðŸ¼",
"description": "white right pointing backhand index tone 2",
"unicodeVersion": "8.0",
- "digest": "9d00a0b1cfc435674dc56065b3d28d28839196977504cf20581205351d8708f2"
+ "digest": "0a1aae46415401cd3557f61ce491e975acaa995b6c2bf487977beb91e4b1bc7e"
},
"point_right_tone3": {
"category": "people",
"moji": "👉ðŸ½",
"description": "white right pointing backhand index tone 3",
"unicodeVersion": "8.0",
- "digest": "e3026a70630ba73d76892a055a80cac2f78d509faddce737f802d2abefa074ba"
+ "digest": "86c13a18c53b548907ec0ec468922beab040c29a365f55e18f265e79f1bb42bf"
},
"point_right_tone4": {
"category": "people",
"moji": "👉ðŸ¾",
"description": "white right pointing backhand index tone 4",
"unicodeVersion": "8.0",
- "digest": "ea508fde90561460361773b4e1b8e80874667b19ac115926206e7c592587cb76"
+ "digest": "1605160b761b975c0f11490eb1a7b724c674ec371d72e73f824fdbe873aeddb2"
},
"point_right_tone5": {
"category": "people",
"moji": "👉ðŸ¿",
"description": "white right pointing backhand index tone 5",
"unicodeVersion": "8.0",
- "digest": "d59cdb2864eb2929941ecd233f8b8afcddc30fbd4594e5f9acf6386ae06ac12c"
+ "digest": "1cfee9fdcdaa1a790c14a4f8436dad4b3b6677860bf60dd1da3985fc7cb25a00"
},
"point_up": {
"category": "people",
"moji": "â˜",
"description": "white up pointing index",
"unicodeVersion": "1.1",
- "digest": "b69ff4f650989709f2185822d278c7773672bd9eb4a625da80f3038a2b9ce42b"
+ "digest": "dc20d84a1a808e2d207f10f2f292cb78e05b9e67b4a26f7491e0c6c7f8059af5"
},
"point_up_2": {
"category": "people",
"moji": "👆",
"description": "white up pointing backhand index",
"unicodeVersion": "6.0",
- "digest": "e83cd9eff2af5125a25f5a306c3ee3cfea240add683b5c36a86a994a8d8c805c"
+ "digest": "0e5a1d7841d0f54762d0fadf460086cad4fcd05fbf65cabdf1df90d1ab0c3f2b"
},
"point_up_2_tone1": {
"category": "people",
"moji": "👆ðŸ»",
"description": "white up pointing backhand index tone 1",
"unicodeVersion": "8.0",
- "digest": "b02ec3e7e04a83bfb769cffb951cbf32aa78e56fa5a51c097f9326df9e08ed33"
+ "digest": "bdcd26a212498dcddc69342caefe4a68d2b4bfbebcfa94045a1c27dcce158311"
},
"point_up_2_tone2": {
"category": "people",
"moji": "👆ðŸ¼",
"description": "white up pointing backhand index tone 2",
"unicodeVersion": "8.0",
- "digest": "32994b85c8b4a1383ca985ebc3382be88866cea1ff1315adfb71fb05e992a232"
+ "digest": "fd5a6d912f3533b3356392e68df8b155dcacd3bb2d2e1c44d84807d587ef1ed5"
},
"point_up_2_tone3": {
"category": "people",
"moji": "👆ðŸ½",
"description": "white up pointing backhand index tone 3",
"unicodeVersion": "8.0",
- "digest": "9e263bcfb82ada34ff85291f36e64e66b86760fb11a4e0c554e801644d417d6d"
+ "digest": "57af38773077d28200e033dc3dd28913f570311a51b833df32f23a85bfcc530c"
},
"point_up_2_tone4": {
"category": "people",
"moji": "👆ðŸ¾",
"description": "white up pointing backhand index tone 4",
"unicodeVersion": "8.0",
- "digest": "3edc92130a0851ac7b5236772ce7918d088689221df287098688e1ed5b3ff181"
+ "digest": "7110f1d42dffcab536906e176baa36e817142f9d71329fdfc1b74ee9813cffd6"
},
"point_up_2_tone5": {
"category": "people",
"moji": "👆ðŸ¿",
"description": "white up pointing backhand index tone 5",
"unicodeVersion": "8.0",
- "digest": "cabb3b7da9290840ef59d0c8b22625bdb2e94842f01b0a575ccbc348f3069d77"
+ "digest": "1795ede377cdd58189471af3f6488d8197f2a742f817f8a61523ccff8d08581b"
},
"point_up_tone1": {
"category": "people",
"moji": "â˜ðŸ»",
"description": "white up pointing index tone 1",
"unicodeVersion": "8.0",
- "digest": "e496fda349072f8b321ceb7a251175f7244c3076661f5ede48ea75ba1acf8339"
+ "digest": "16f0e85643558fd2f471cc8d317058914f42279f4aef2ba0e8390728efb4992b"
},
"point_up_tone2": {
"category": "people",
"moji": "â˜ðŸ¼",
"description": "white up pointing index tone 2",
"unicodeVersion": "8.0",
- "digest": "5a8081323f3baa67e6431e21e16a36559b339f5175d586644e34947f738dd07a"
+ "digest": "fe8f930134adc4be29b7e659c6acbfa76ba52ab3d0b46dd4797e79c365708666"
},
"point_up_tone3": {
"category": "people",
"moji": "â˜ðŸ½",
"description": "white up pointing index tone 3",
"unicodeVersion": "8.0",
- "digest": "07bf0cea812eb226b443334e026e13d1ec23e013478f4af862a3919703107842"
+ "digest": "d7258aeab80e697649a0e8ad13445380462bb5814c90b1183cc105ebe3eaa5ef"
},
"point_up_tone4": {
"category": "people",
"moji": "â˜ðŸ¾",
"description": "white up pointing index tone 4",
"unicodeVersion": "8.0",
- "digest": "1fbbd71433108143ee157d0fdadd183f7f013bafa96f0dd93b181e1fd5fd4af2"
+ "digest": "4c4aca5e2e436421b26d5d58a82bd52fdb9135593fb1afd92c30fa8f1ed51dd1"
},
"point_up_tone5": {
"category": "people",
"moji": "â˜ðŸ¿",
"description": "white up pointing index tone 5",
"unicodeVersion": "8.0",
- "digest": "ad068ef32df32f8297955490a9a90590a0f93ed5702a052cd0d8f6484c6cc679"
+ "digest": "ab94fd7fe02205894add98c4c97d812f2228c7c766b1b0e01fa1e9e5dc7c669b"
},
"police_car": {
"category": "travel",
"moji": "🚓",
"description": "police car",
"unicodeVersion": "6.0",
- "digest": "0909be1bd615ae331a7cce71e16dee3ca663c721d5170072c593cb7c76f9f661"
+ "digest": "38e3b0bdee599b71a5f556dc86b12aa01df38dcf533179515bbdbf2512828548"
},
"poodle": {
"category": "nature",
"moji": "ðŸ©",
"description": "poodle",
"unicodeVersion": "6.0",
- "digest": "f1742fdf3fd26a8a5cfeaba57026518dacaad364cbd03344c4000a35af13e47a"
+ "digest": "4e73855cbdb10f644146fb3bc1636a74faff02a5d69ad0f91302e920973b03f0"
},
"poop": {
"category": "people",
"moji": "💩",
"description": "pile of poo",
"unicodeVersion": "6.0",
- "digest": "857a61c872138d359a7fe8257bb26118afa49d75186eca2addb415d07c92b3ec"
+ "digest": "b5c6a197435c518508edf1cc7bc015c14c120965b574813838797507fab21994"
},
"popcorn": {
"category": "food",
"moji": "ðŸ¿",
"description": "popcorn",
"unicodeVersion": "8.0",
- "digest": "684f1b7ef34ea7ca933aed41569bc6595a19ef0d546a1b7b9e69f8335540b323"
+ "digest": "6571fce7fb3cdf92db6fdb69b89b21b664eab348f7fd9ccb37da09eefa65d14f"
},
"post_office": {
"category": "travel",
"moji": "ðŸ£",
"description": "japanese post office",
"unicodeVersion": "6.0",
- "digest": "54398ee396c1314a7993b1cb1cba264946b5c9d5a7dbb43fd67286854d1d1a0f"
+ "digest": "7dc4ef6e09bab68f31dfb7f594a6488b62c9dcb956b36ac2788c1fbefa908251"
},
"postal_horn": {
"category": "objects",
"moji": "📯",
"description": "postal horn",
"unicodeVersion": "6.0",
- "digest": "0ea12f44f3bae9a14bde3b37361b48bd738d2f613bb1b53a9204959b70e643f8"
+ "digest": "0cee35210e86afe9bdf0e60345d0c8c23c25d0b43e74bfd4bb8f76e223ffdfe3"
},
"postbox": {
"category": "objects",
"moji": "📮",
"description": "postbox",
"unicodeVersion": "6.0",
- "digest": "bbc424ae8d46de380d7023a43ea064002fd614657d00330d3503275827ac87e2"
+ "digest": "3e12a4b2a7bce5c1257ecd05f69ba6f51d9db39b21f6393c304e6870c5f432da"
},
"potable_water": {
"category": "symbols",
"moji": "🚰",
"description": "potable water symbol",
"unicodeVersion": "6.0",
- "digest": "dbe80d9637837377cc2a290da2e895f81a3108cc18b049e3d87212402c1c2098"
+ "digest": "e35ad512f4da69fa132475c68cdbb831ab617f013127aba15cd7508f0b732d19"
},
"potato": {
"category": "food",
"moji": "🥔",
"description": "potato",
"unicodeVersion": "9.0",
- "digest": "a56a69f36f3a0793f278726d92c0cea2960554f3062ef1a0904526a04511d8e1"
+ "digest": "72e5b1d7dd118dd85886d880a88a92b60e1542587d92591dd42f2d59a721b4c4"
},
"pouch": {
"category": "people",
"moji": "ðŸ‘",
"description": "pouch",
"unicodeVersion": "6.0",
- "digest": "9f012b90310b4a072b6a8fa2c64def087b5f7ffffaafc36e1856ba943a170351"
+ "digest": "e333815505f48dad6240f0d6ac9476ab256b26ec53108c0454f77c6ac31c4874"
},
"poultry_leg": {
"category": "food",
"moji": "ðŸ—",
"description": "poultry leg",
"unicodeVersion": "6.0",
- "digest": "1445ec4f5e68a19e5a84e5537dca8190d62409070c954d112e6097f1a6b7f054"
+ "digest": "c3c667f9795aa2d14fd1a500438d7fd2441e924a3d1af68bd6be1f082b935f4c"
},
"pound": {
"category": "objects",
"moji": "💷",
"description": "banknote with pound sign",
"unicodeVersion": "6.0",
- "digest": "eb11b83eb52adb0a15e69a3bc15788a2dc7825dedee81ac3af84963c9dd517b5"
+ "digest": "2cb892a8131edb282cb8f5dadaa8db602e6b6934fdf06588d8ccb8f3e7e6eae6"
},
"pouting_cat": {
"category": "people",
"moji": "😾",
"description": "pouting cat face",
"unicodeVersion": "6.0",
- "digest": "8822abedf3499cf98278d7eeea0764d1100ec25cad71b4b2e877f9346f8c8138"
+ "digest": "e253bae99f9859322bc02b5e9b87cb33c68a5e38aebaa57478d5f4a5b1c23bb0"
},
"pray": {
"category": "people",
"moji": "ðŸ™",
"description": "person with folded hands",
"unicodeVersion": "6.0",
- "digest": "735b79dab34ac2cf81fd42fdcd7eb1f13c24655e5e343816d5764896c03edeea"
+ "digest": "175a97bcdf0110e4a435cc760d5203b8493c5bbf6d4ce70fb7a5643b2d1021dc"
},
"pray_tone1": {
"category": "people",
"moji": "ðŸ™ðŸ»",
"description": "person with folded hands tone 1",
"unicodeVersion": "8.0",
- "digest": "e8b6103450215e8566797f150978355e297deade4eb47a6371f7a7bc558fed9d"
+ "digest": "0a453f3e7292c7d813da211b9d1359c6d893426077b010bca5a4bc3f17a695c1"
},
"pray_tone2": {
"category": "people",
"moji": "ðŸ™ðŸ¼",
"description": "person with folded hands tone 2",
"unicodeVersion": "8.0",
- "digest": "ee8baacd95d7e8dbad8a1f2d9a12e36c98f3d518db5d3b117d0a18290815e62b"
+ "digest": "f66640530c3818fff333ebd6636dfb912aa6e986060ad03555766bbc5888d8b4"
},
"pray_tone3": {
"category": "people",
"moji": "ðŸ™ðŸ½",
"description": "person with folded hands tone 3",
"unicodeVersion": "8.0",
- "digest": "ae8c0caa9aca0a6c44069e76a7535c961d0284cd701812f76bbd2bd79ce2bd53"
+ "digest": "5d8f49ada7ce2e5c473220aa881b32cda4fe73c024ec9260fd2af09b55478239"
},
"pray_tone4": {
"category": "people",
"moji": "ðŸ™ðŸ¾",
"description": "person with folded hands tone 4",
"unicodeVersion": "8.0",
- "digest": "64f7b3178b8cd6f6a877ed583539eefe068fa87a0dd658fdcd58c8bc809f7e17"
+ "digest": "c830c04f893a424a6694c478d8356a549a43b2ba3e9e912becc018178ca0c54c"
},
"pray_tone5": {
"category": "people",
"moji": "ðŸ™ðŸ¿",
"description": "person with folded hands tone 5",
"unicodeVersion": "8.0",
- "digest": "5bc8cdce937ac06779c87021423efcec4f602aa4a39dba90b00de81033005332"
+ "digest": "3fc8c39440ac0ae1646949dad41cc56305e51fbd299378de5356be3e5b4bda24"
},
"prayer_beads": {
"category": "objects",
"moji": "📿",
"description": "prayer beads",
"unicodeVersion": "8.0",
- "digest": "80177091264430cbcf7c994fbe5ee17319d1a58d933636cc752a54dafcf98a05"
+ "digest": "aedb143e4798a14b97ff6595293d7ed873988023efbc1e3de3aa9f17344359fd"
},
"pregnant_woman": {
"category": "people",
"moji": "🤰",
"description": "pregnant woman",
"unicodeVersion": "9.0",
- "digest": "49abb86409103338bdb6ae43c13a78ca2dc9cd158a26df35eadd0da3c84a4352"
+ "digest": "541e4d6245b5b243121e4666298cd5ae5a31fd38228ca2f527865019d7fa25b5"
},
"pregnant_woman_tone1": {
"category": "people",
"moji": "🤰ðŸ»",
"description": "pregnant woman tone 1",
"unicodeVersion": "9.0",
- "digest": "5a9f8ed2b631ecf8af111803a5c11f4c156435a5293cb50329c7b98697c8da25"
+ "digest": "8c16b193ce1c39aafcc4ba1b7db7524486cfbd640ece996bd795e91198db6196"
},
"pregnant_woman_tone2": {
"category": "people",
"moji": "🤰ðŸ¼",
"description": "pregnant woman tone 2",
"unicodeVersion": "9.0",
- "digest": "279a2eafff603b11629c955b05f5bd3d7da9a271d4fb3f02e9ccd457b8d2d815"
+ "digest": "44261300c22052fdc4f82cb41d63754b5bd9d5bc6dac92ac68440a62f3456b87"
},
"pregnant_woman_tone3": {
"category": "people",
"moji": "🤰ðŸ½",
"description": "pregnant woman tone 3",
"unicodeVersion": "9.0",
- "digest": "93bb63ec2312db315e3f0065520b715cc413ac0fd65538ec9b5cd97df2a42b20"
+ "digest": "f734c133c3d9dc59aeb050024c420e2de231e2fabefda255169666ee955ab8e4"
},
"pregnant_woman_tone4": {
"category": "people",
"moji": "🤰ðŸ¾",
"description": "pregnant woman tone 4",
"unicodeVersion": "9.0",
- "digest": "b8dc3dcec894bfd832a249459b10850f8786b6778d8887a677d1291865623da2"
+ "digest": "6990dabfc19d92c061fdffd82ab99f582378fd84c535db0dc042f20cb9db6c16"
},
"pregnant_woman_tone5": {
"category": "people",
"moji": "🤰ðŸ¿",
"description": "pregnant woman tone 5",
"unicodeVersion": "9.0",
- "digest": "73ee432752f81980f353a7f9b9f7a5ece62512dca08e15c1876b89227face21c"
+ "digest": "6981c98ac30d7ff3dc5b44279a3d3a8891a1fd33de5a41050aced7e37ec9ea21"
},
"prince": {
"category": "people",
"moji": "🤴",
"description": "prince",
"unicodeVersion": "9.0",
- "digest": "34a0e0625f0a9825d3674192d6233b6cae4d8130451293df09f91a6a4165869c"
+ "digest": "07fcbaf5d14e5e77d1a44cae21006ab245da1fd799773aa836a9bb2fdac24f61"
},
"prince_tone1": {
"category": "people",
"moji": "🤴ðŸ»",
"description": "prince tone 1",
"unicodeVersion": "9.0",
- "digest": "ccecdfeccb2ab1fceceae14f3fba875c8c7099785a4c40131c08a697b5b675fc"
+ "digest": "2db61fd0e8bb7d9d5941df7c680d2e4fff6b282d2a356c34bf32e55bf41d1245"
},
"prince_tone2": {
"category": "people",
"moji": "🤴ðŸ¼",
"description": "prince tone 2",
"unicodeVersion": "9.0",
- "digest": "c373fd3e0c1798415e3d8d88fab6c98c1bbdedcbe6f52f3a3899f6e2124a768d"
+ "digest": "283dbc3550fe80ce1bf4f6eabd7e216026f3996f4e0fa9b9b881df8d741c26d3"
},
"prince_tone3": {
"category": "people",
"moji": "🤴ðŸ½",
"description": "prince tone 3",
"unicodeVersion": "9.0",
- "digest": "71d15695ca954d55aa69d3c753c7d31a8ba5329713a8ddbc90dafc11e524c4ef"
+ "digest": "374f58411517a2c3532adad34108db23e8587a86d15e32aa0e67e8a82d1c2ef3"
},
"prince_tone4": {
"category": "people",
"moji": "🤴ðŸ¾",
"description": "prince tone 4",
"unicodeVersion": "9.0",
- "digest": "08f6cb32424f15cc3aaf83c31a5dac7c01a6be2f37ea8f13aed579ce6fb4db19"
+ "digest": "a6d44eb1caf4dc0fbb1b5821809cd55bea127f5a6b4b4b7e259f161ef502a52b"
},
"prince_tone5": {
"category": "people",
"moji": "🤴ðŸ¿",
"description": "prince tone 5",
"unicodeVersion": "9.0",
- "digest": "77d521148efa33fa4d3409693d050fecfd948411e807327484f174e289834649"
+ "digest": "72bbb711de954db8d01bf0270ae23ead3fabc76a1e9edc208b2ee08b3c282c17"
},
"princess": {
"category": "people",
"moji": "👸",
"description": "princess",
"unicodeVersion": "6.0",
- "digest": "efabd28480a843c735f0868734da2f9ce28133933b02ab07b645498f494f3f80"
+ "digest": "0255742ad246f6245302c68965ce7243618c62e27a55927a1101db0a58144205"
},
"princess_tone1": {
"category": "people",
"moji": "👸ðŸ»",
"description": "princess tone 1",
"unicodeVersion": "8.0",
- "digest": "52b88b99ba64f82e8f36e2a1827c85145e4fcd6863478c2345fe9fa9e8901cdf"
+ "digest": "6634c586ce395cc2417acfffc4997bd9152b200abb357921f9bcb37d5501c99b"
},
"princess_tone2": {
"category": "people",
"moji": "👸ðŸ¼",
"description": "princess tone 2",
"unicodeVersion": "8.0",
- "digest": "7e44289404693668f20e681fcdc2e516512d54a69c627eedae958f69dfe6eea9"
+ "digest": "9ef16a00fa3f044559e9a8f5abbd0d8be7c6d665f8007c59094e2581d92236d1"
},
"princess_tone3": {
"category": "people",
"moji": "👸ðŸ½",
"description": "princess tone 3",
"unicodeVersion": "8.0",
- "digest": "96c9a9857348d7a1a8be899c50d55b352b9a9fd5c65e4777bfa199fe7929d41c"
+ "digest": "0a6687e1da8a427e55fc2769f8927fa3f285b9e3dfc4d0a89de2339f9c7ad5d6"
},
"princess_tone4": {
"category": "people",
"moji": "👸ðŸ¾",
"description": "princess tone 4",
"unicodeVersion": "8.0",
- "digest": "67696f96be60f2a36598072172d2db197d007e6c1ac3acef526a5ce6d59bf3f7"
+ "digest": "687368a236801772418314f1ca4271d97511a3c5875a22886abc21e2383d784d"
},
"princess_tone5": {
"category": "people",
"moji": "👸ðŸ¿",
"description": "princess tone 5",
"unicodeVersion": "8.0",
- "digest": "007f624e2fad91bb57ce32ecd35213a796d71807f3b12f3f1575bf50e6a50eeb"
+ "digest": "cd1a5425ebe5bd0334ae35e3fcdbe50fffcceac150a86b842b92bbb78bbb0e3b"
},
"printer": {
"category": "objects",
"moji": "🖨",
"description": "printer",
"unicodeVersion": "7.0",
- "digest": "5e5307e3dc7ec4e16c9978fb00934c99c4adefca7d32732a244d1f2de71ce6f8"
+ "digest": "6d955ef121cac0fb8f24e617c664e13b44cb318db041be39ebbbd158e731ae2f"
},
"projector": {
"category": "objects",
"moji": "📽",
"description": "film projector",
"unicodeVersion": "7.0",
- "digest": "7f8e1fdb89584849a56ee34c62cab808af48b7bd4823467d090af4657a2e0420"
+ "digest": "ad03ae86f9188ccc2909335de034ed0de68dadc4a6e59fb678e752d219c41f92"
},
"punch": {
"category": "people",
"moji": "👊",
"description": "fisted hand sign",
"unicodeVersion": "6.0",
- "digest": "c7e7edf6d64f755db3f02874354f08337b3971aff329476d19ac946e0b421329"
+ "digest": "1f8bdf4ead54a6d9ccad648c98f126a49e4a16a1d525abf8d8194b2e253461e2"
},
"punch_tone1": {
"category": "people",
"moji": "👊ðŸ»",
"description": "fisted hand sign tone 1",
"unicodeVersion": "8.0",
- "digest": "c9ba508b0c36041047473782acfedab5af40dd7946b33daf4d8d54c726e06a11"
+ "digest": "6e368dfc6f762bc1db1127592d91fa29437f182391a71d61472e8459b2dfc770"
},
"punch_tone2": {
"category": "people",
"moji": "👊ðŸ¼",
"description": "fisted hand sign tone 2",
"unicodeVersion": "8.0",
- "digest": "d53011cd2f3334c7b3fffdfe1e2b8cc1c832c74306e1ac6d03f954a1309d7d0b"
+ "digest": "62e40f8ac33d5f28cc2bba06dc0871627db3f40a04f16a7dd2ab426bb9c740a4"
},
"punch_tone3": {
"category": "people",
"moji": "👊ðŸ½",
"description": "fisted hand sign tone 3",
"unicodeVersion": "8.0",
- "digest": "f7522347094e0130ed8e304678106574dbd7dd2b6b3aeb4d8a7a0fef880920b2"
+ "digest": "94a9d410d1ac2252be7386a2110708686ea2bba4859f3fd84a11e64bbd6a1432"
},
"punch_tone4": {
"category": "people",
"moji": "👊ðŸ¾",
"description": "fisted hand sign tone 4",
"unicodeVersion": "8.0",
- "digest": "3e62bdd426f3e6ff175ce3b8dd6f6d3998d9c1506128defa96b528b455295b47"
+ "digest": "b378775978c26547d87fe8d2f7d20a05c2bbca386d40533fe774e4bca2e7540a"
},
"punch_tone5": {
"category": "people",
"moji": "👊ðŸ¿",
"description": "fisted hand sign tone 5",
"unicodeVersion": "8.0",
- "digest": "7d9bff777dc4ec41ac132b1252fa08cf92a398c8dc146c4a5327b45d568982d8"
+ "digest": "4300760b118dee45c53098601e7d8f9d3ec66e87f2d11e87b07adb79793c53e8"
},
"purple_heart": {
"category": "symbols",
"moji": "💜",
"description": "purple heart",
"unicodeVersion": "6.0",
- "digest": "a6bf01de806525942be480e45a4b2879f91df8129b78a1b8734d4f917bcab773"
+ "digest": "68bc43f94a83b183d3ae134cfb36ef801dbb08f8ed46ed2972caa24cad3c8d2c"
},
"purse": {
"category": "people",
"moji": "👛",
"description": "purse",
"unicodeVersion": "6.0",
- "digest": "2b785f36e01875d66cfda2192c8c53606e7224a7c869a4826b62cb61613d60c8"
+ "digest": "069d6ce3046648578d3c04796bb6190ecfb55e1fd708be2021144f1716c3ae2f"
},
"pushpin": {
"category": "objects",
"moji": "📌",
"description": "pushpin",
"unicodeVersion": "6.0",
- "digest": "c3f7d7008be6bab8dc02284d4d759abf7aafbb3dbbe3a53f0f5b2ff685af88f8"
+ "digest": "c8b820588fe733d505e95d93eeadcc3e1073f745b2b53bae8dcc1c0bb8624aa7"
},
"put_litter_in_its_place": {
"category": "symbols",
"moji": "🚮",
"description": "put litter in its place symbol",
"unicodeVersion": "6.0",
- "digest": "f52a57d6f1bada7b6e6b9a6458597d70cb701c01e1120d8cb1d7ff65e01d405c"
+ "digest": "8f4d77e14f81634081b21e9bc062082d5a18cad551560eb8479c0c5d14ab3358"
},
"question": {
"category": "symbols",
"moji": "â“",
"description": "black question mark ornament",
"unicodeVersion": "6.0",
- "digest": "40050a1fd29bed321fd601d13dc33de5d6084121f1d873b29bde9dc3d823a310"
+ "digest": "fd18ff641d27854c3996ec9c58210fde5411537847c0f3c55d9318244c3e8854"
},
"rabbit": {
"category": "nature",
"moji": "ðŸ°",
"description": "rabbit face",
"unicodeVersion": "6.0",
- "digest": "678ad953a7ab8f618c59051449a67c965d1f04f42dd6f6669adaf3fadebd080c"
+ "digest": "1a7201ef67f5ce4c9deb0f5c9e1e14d0e3d6ffaac17bbb73d6ca6c1de62c43ea"
},
"rabbit2": {
"category": "nature",
"moji": "ðŸ‡",
"description": "rabbit",
"unicodeVersion": "6.0",
- "digest": "19b1f5108292472434cc7a49efac4ea9275779735c7aeb0f15c36021d5998ca0"
+ "digest": "120075f5ca435b5dc903bfe3934bbc9adb2c17c16a8b839625320a46c299827a"
},
"race_car": {
"category": "travel",
"moji": "ðŸŽ",
"description": "racing car",
"unicodeVersion": "7.0",
- "digest": "46f4814259d3d17ff35c04110e73e5327aee99f4711cd459ca1ee951508da3a6"
+ "digest": "183bf5e7abb9e7c7e94a08f212040d6dbe24633c2fb25a452096a2062c18acc6"
},
"racehorse": {
"category": "nature",
"moji": "ðŸŽ",
"description": "horse",
"unicodeVersion": "6.0",
- "digest": "a57b7aca35347ada8225eeee06b70cfd040484104963b4df56ea8fec690576b0"
+ "digest": "44ade212bafa562416e9df439229052db2e45cf631d6d32a8261aa541a675a07"
},
"radio": {
"category": "objects",
"moji": "📻",
"description": "radio",
"unicodeVersion": "6.0",
- "digest": "9245951dd779cdd141089891b15a90d3999a6358acf1fc296aa505100f812108"
+ "digest": "a397a47cb1ab6621628112afcdc7ce4338f9e77954f2ef7e9bb461d519705099"
},
"radio_button": {
"category": "symbols",
"moji": "🔘",
"description": "radio button",
"unicodeVersion": "6.0",
- "digest": "565bec59198df2592e96564c6e314d3cde33c47b453db1bec6c5d027b5cb4fd9"
+ "digest": "7e74da4889650286464a22035c3297d914c1e52c266d5accbffe03d8f76069de"
},
"radioactive": {
"category": "symbols",
"moji": "☢",
"description": "radioactive sign",
"unicodeVersion": "1.1",
- "digest": "0ed6634057824e0cfd10b2533753e3632b0624341a7eac8d9835706480335581"
+ "digest": "adae20f9d65f9e4c3d2ff97012c58475ed56d446010999b75af2ddc78961cf54"
},
"rage": {
"category": "people",
"moji": "😡",
"description": "pouting face",
"unicodeVersion": "6.0",
- "digest": "d97ba6bd08eec46dbc7199f530c945b73a87a878e35397b0a3e4f2b45039e89e"
+ "digest": "55c5a1450a9c4ba539c4c2f6760209c7cedfbbc93abee597d63703e7bc96743c"
},
"railway_car": {
"category": "travel",
"moji": "🚃",
"description": "railway car",
"unicodeVersion": "6.0",
- "digest": "2cddc08d555e7fc24e312c3d255ed013fbf9cd2974a6918369c32554049ba2be"
+ "digest": "5aaa2731f58c2a08c2c731cf361da3a9ea407d2754134dcacf14d9ea4cfb702f"
},
"railway_track": {
"category": "travel",
"moji": "🛤",
"description": "railway track",
"unicodeVersion": "7.0",
- "digest": "0da351b6d4e75c6beeaef1225e151d9580d4b5c41dfa1cf192715bf3cec981d7"
+ "digest": "2a36d0f6b16ecb70328a34502c639ce931fcb558c72fad0118b7380a13de2076"
},
"rainbow": {
"category": "travel",
"moji": "🌈",
"description": "rainbow",
"unicodeVersion": "6.0",
- "digest": "a93aceb54e965f35e397e8c8716b1831614933308d026012d5464ee42783ed4d"
+ "digest": "f3e13a1ac2f7a2ae4096f47a2e1a1afd18f2998a67f6491002c3bcb019093222"
},
"raised_back_of_hand": {
"category": "people",
"moji": "🤚",
"description": "raised back of hand",
"unicodeVersion": "9.0",
- "digest": "20973a697e826625deba5ee3c4f25eb5e1737f2e860ac6fe4ee4d0e0c84b5e12"
+ "digest": "3335f2a4f8ac26c22418968e1836e697ee03af488a9349bab6795076ab5dd771"
},
"raised_back_of_hand_tone1": {
"category": "people",
"moji": "🤚ðŸ»",
"description": "raised back of hand tone 1",
"unicodeVersion": "9.0",
- "digest": "06af5941255ca69d10d99d0a512bbda6141a296453835dbccf259ce0afe1dd3d"
+ "digest": "6388f3e4b61cc32967aa6b9bceb60e8673f01cb1cdf94c37332d61040be48d6b"
},
"raised_back_of_hand_tone2": {
"category": "people",
"moji": "🤚ðŸ¼",
"description": "raised back of hand tone 2",
"unicodeVersion": "9.0",
- "digest": "429ed19555c9e5197b729b3e7bd8013346551051cb0b3fbc8a4372717c9a027d"
+ "digest": "66491196ad238a2a12c14d9be5cec12d22788d719725e7d22e6edad40afc0c8e"
},
"raised_back_of_hand_tone3": {
"category": "people",
"moji": "🤚ðŸ½",
"description": "raised back of hand tone 3",
"unicodeVersion": "9.0",
- "digest": "487a1c3f19e77c99b520ec073de2acc4a9e585b739a84b3989f7de85d2c2045c"
+ "digest": "27e2f03168b0733a0492a30df1f2f924783bf309a3a05a22a27529953783d0cd"
},
"raised_back_of_hand_tone4": {
"category": "people",
"moji": "🤚ðŸ¾",
"description": "raised back of hand tone 4",
"unicodeVersion": "9.0",
- "digest": "154254d8500c55ec3de698be4a352f9bcf06e2950cabc4eabaccad0f39a1e1e9"
+ "digest": "729c1c34a2aa7c236d11c73665fa7b29fa1c31cc3ce56ea0a7e46f0754483efd"
},
"raised_back_of_hand_tone5": {
"category": "people",
"moji": "🤚ðŸ¿",
"description": "raised back of hand tone 5",
"unicodeVersion": "9.0",
- "digest": "6e9c0855ecd5f14adca5e5862427c3d39ffcf86f7ddd3aaa1fefc3cefc7483c8"
+ "digest": "50cca64dcbf0dff9a896668c6d909bd91805d699873224933e91af524c781320"
},
"raised_hand": {
"category": "people",
"moji": "✋",
"description": "raised hand",
"unicodeVersion": "6.0",
- "digest": "5cf11be683aea985d5ba51fbd44722c2327311bfe26b61c3d441c90f5d5a195a"
+ "digest": "0bfd815713f428f4408c4225abd10c73e1200dbabe07216cb5d07098f8314270"
},
"raised_hand_tone1": {
"category": "people",
"moji": "✋ðŸ»",
"description": "raised hand tone 1",
"unicodeVersion": "8.0",
- "digest": "865afca29b57577fed8fe8c2be57b74254a008c8cf34194680be2759239b5f5d"
+ "digest": "5d8a093e609223ce89bb3813d1b673d8558b81597ec747002a5e30792e1bcd72"
},
"raised_hand_tone2": {
"category": "people",
"moji": "✋ðŸ¼",
"description": "raised hand tone 2",
"unicodeVersion": "8.0",
- "digest": "832169a0b626a682a58a3b998f68413657b4962c1fab05f1fdc2668e82727210"
+ "digest": "7b76fb17f3da3719ee18ca00903b0b89b4fad7718aa18df52c7920d0ae049fb2"
},
"raised_hand_tone3": {
"category": "people",
"moji": "✋ðŸ½",
"description": "raised hand tone 3",
"unicodeVersion": "8.0",
- "digest": "3959a873ad7671de82c615c4ed840b011e67baafb2bab7dd16859608d3e83cb1"
+ "digest": "44bce7c38e3b814d00fee161df4cdf94b2c73f5e044b65317010588029aae4be"
},
"raised_hand_tone4": {
"category": "people",
"moji": "✋ðŸ¾",
"description": "raised hand tone 4",
"unicodeVersion": "8.0",
- "digest": "db542f65d076ccf3dbfca27cb7c2f135a8bf7a487a81a04873e70172bdfcd579"
+ "digest": "b23fad6235d1e3dfbbf7c613013cf294b9c36c6d1f2228fd97fb4802aa3ef0af"
},
"raised_hand_tone5": {
"category": "people",
"moji": "✋ðŸ¿",
"description": "raised hand tone 5",
"unicodeVersion": "8.0",
- "digest": "88ca884d14baaae48df21d75c22d82fb15bdc395e42026f5ca34cd65e5ae8674"
+ "digest": "a66a0fc82b6d8abd282f5c7f7e35cc31a3f83dd425f4621a3538a2455113b02a"
},
"raised_hands": {
"category": "people",
"moji": "🙌",
"description": "person raising both hands in celebration",
"unicodeVersion": "6.0",
- "digest": "2ee73466a3f5079e542857fe6f5497e9f87753a81854985ce3356a8d3da1d8b8"
+ "digest": "6bc3e746c276ce1ea46ba5233d30ec5cdb8340b5c9c15768873404d59b1f3496"
},
"raised_hands_tone1": {
"category": "people",
"moji": "🙌ðŸ»",
"description": "person raising both hands in celebration tone 1",
"unicodeVersion": "8.0",
- "digest": "43e73c60f040a66374b8ec98f3629a90d13ae9f472446ed7676cd5573e824f4b"
+ "digest": "c3e5095f41e49954c688edefeb223069c57979052735b06277d7f3620161796f"
},
"raised_hands_tone2": {
"category": "people",
"moji": "🙌ðŸ¼",
"description": "person raising both hands in celebration tone 2",
"unicodeVersion": "8.0",
- "digest": "fcc5255bb2b06dc82d6878e74cf34e8ce118c70004a06d39a980683772b98c52"
+ "digest": "4bd2f620dba790a58a42ab6d234de14772e4224994b929d731acc50ed6a8d259"
},
"raised_hands_tone3": {
"category": "people",
"moji": "🙌ðŸ½",
"description": "person raising both hands in celebration tone 3",
"unicodeVersion": "8.0",
- "digest": "3ee3e0aafef486e766a166935e8147fb75a7329cfebc96dec876cc45e83a8754"
+ "digest": "1db8bfc21ab03d98849684f6d32e8e333bb9b33dd540a38c4673a33ea78698d8"
},
"raised_hands_tone4": {
"category": "people",
"moji": "🙌ðŸ¾",
"description": "person raising both hands in celebration tone 4",
"unicodeVersion": "8.0",
- "digest": "78a8cbf6b2b85be4d6b18f0ff6a77f197963117955725fb7e57e0441effb928f"
+ "digest": "65991dd419d1a02f126dfc401252faa929eb9b437d990b7802a2323ce6e929cb"
},
"raised_hands_tone5": {
"category": "people",
"moji": "🙌ðŸ¿",
"description": "person raising both hands in celebration tone 5",
"unicodeVersion": "8.0",
- "digest": "2a5ed7334a17172db0cd820a559e7f75df40ec44de6c25d194c76e1b58c634cb"
+ "digest": "ffe251cc1a777836f40217630cb6652d3ec7f4f80c88045d1ec1430c8ce368d1"
},
"raising_hand": {
"category": "people",
"moji": "🙋",
"description": "happy person raising one hand",
"unicodeVersion": "6.0",
- "digest": "512750b00704f1ccefd3c757743540b785ad7670dbbe4a2c4dca8d93e6701920"
+ "digest": "b9cc5deb1d33ace5ab80f9b4fe7d2d277c2ee04dfdbc8bc3d41ca69edd3d5c52"
},
"raising_hand_tone1": {
"category": "people",
"moji": "🙋ðŸ»",
"description": "happy person raising one hand tone1",
"unicodeVersion": "8.0",
- "digest": "2897722f091c273dd3714cff7423c2475bc3070416c28014ca03322b9ece48bc"
+ "digest": "6d7aea2c2c9620448ffc6be9e5bf5cddcc7a1e18f9f816a030dc818d93d45d61"
},
"raising_hand_tone2": {
"category": "people",
"moji": "🙋ðŸ¼",
"description": "happy person raising one hand tone2",
"unicodeVersion": "8.0",
- "digest": "59199b334b3845911382c1f29bd7c0d5ef9d2486417345e265b166ead7d3e1c1"
+ "digest": "8af44fa3d2d7eadc95c8193993eeeaea3bd764c1ac884d897804a074bba87a21"
},
"raising_hand_tone3": {
"category": "people",
"moji": "🙋ðŸ½",
"description": "happy person raising one hand tone3",
"unicodeVersion": "8.0",
- "digest": "f95b338d5efcf14ef12f415a2c1bba93df48628ddc94f34f70c31e1b3c2e1d28"
+ "digest": "cc39cadc42f9ec7fba6e74661e757f0d7a36fd10807fe90fddd511a07e290059"
},
"raising_hand_tone4": {
"category": "people",
"moji": "🙋ðŸ¾",
"description": "happy person raising one hand tone4",
"unicodeVersion": "8.0",
- "digest": "951ddbfdb57d5a60551b59b3d0f7ca00a64912f4a101a73afaebd68445cd6cec"
+ "digest": "7ef0c37921ced3c64898531b746eaf1e6ed7133ebefd74394e5b0164ee57085d"
},
"raising_hand_tone5": {
"category": "people",
"moji": "🙋ðŸ¿",
"description": "happy person raising one hand tone5",
"unicodeVersion": "8.0",
- "digest": "9370f93704d8f89ca6dc946715eab5e7dba82bf04dd68c00f5c0abb8bc16371e"
+ "digest": "96927ec26049ce6efc65917605f9039f9ec746eff23fe00c4f35ceb29d4f2c93"
},
"ram": {
"category": "nature",
"moji": "ðŸ",
"description": "ram",
"unicodeVersion": "6.0",
- "digest": "2875ab28e1018b39062aeb0c5ce488c48a98f13e9f2364470a0a700b126604f2"
+ "digest": "8f4a19d64e01593a7487fb4d58fe1d300055e458d3daa1659ec59877a8a3b00f"
},
"ramen": {
"category": "food",
"moji": "ðŸœ",
"description": "steaming bowl",
"unicodeVersion": "6.0",
- "digest": "425662a49c4c13577c0de8d45d004e5ba204aaadbaabae62a5c283ecd7a9a2c5"
+ "digest": "2dab0bf5560aacda31e87d8a86a1a39eaaa7f6b4fb3dbc1b9768f3a49a9e20f9"
},
"rat": {
"category": "nature",
"moji": "ðŸ€",
"description": "rat",
"unicodeVersion": "6.0",
- "digest": "14380d65498c6ce037c02a93bca2b24f25a368d85278d6015b8c9f7cd261f8e2"
+ "digest": "7f15ecd2a5c5dd340a5e1c69454a512bf176cbb74b042efc65a7d6c8efad5e6e"
},
"record_button": {
"category": "symbols",
"moji": "âº",
"description": "black circle for record",
"unicodeVersion": "7.0",
- "digest": "92be12161ba206bb2e06a39131711c7b17368d55b4aae0b48f0ac5b6b1cde76b"
+ "digest": "2b7ef01bcbfb5310cceffada4a966b874dd3bf4b8cfa23848effac1386457fc3"
},
"recycle": {
"category": "symbols",
"moji": "â™»",
"description": "black universal recycling symbol",
"unicodeVersion": "3.2",
- "digest": "c377e8537367b05b5de9be860a0fcabd7aed2bf4ba146eefc423671a21530369"
+ "digest": "9256cf44c41b5b3479c92a453c26adcc32800af9ffbf32f2d08e7570732788b2"
},
"red_car": {
"category": "travel",
"moji": "🚗",
"description": "automobile",
"unicodeVersion": "6.0",
- "digest": "8a99832a195263c0e922af53d52dea37aa3e07032b3c2a1977f8527b4a144b9c"
+ "digest": "db3f7e0dd1e1aa92541afc4db067e0c6bf9d325d912b1bafce182e683f68a06e"
},
"red_circle": {
"category": "symbols",
"moji": "🔴",
"description": "large red circle",
"unicodeVersion": "6.0",
- "digest": "9dcf0132f6f2cc81702f0e3b15b37984e8439796705bf98f68ba449b3dfa5307"
+ "digest": "a76514fffb0fec7b8994aa202144350f3257c4562c02a451c5727d20ce0f21ac"
},
"registered": {
"category": "symbols",
- "moji": "®",
+ "moji": "®ï¸",
"description": "registered sign",
"unicodeVersion": "1.1",
- "digest": "9661b1df529ecb752d130820c55c403e5de263748eb02f7fea327818bc282d94"
+ "digest": "aeabdec7e5ddeed91ca77a6b926d76362e90d955225cbba6cee8b26442661e10"
},
"relaxed": {
"category": "people",
"moji": "☺",
"description": "white smiling face",
"unicodeVersion": "1.1",
- "digest": "2d5aed4fb8504c6d6660ef8d3bfe0cc053dcd6099c2f53748c202dc970c639bc"
+ "digest": "27bb85737e7f969e392a23141f27c75c82e327fcd0614a445dec47a00578057d"
},
"relieved": {
"category": "people",
"moji": "😌",
"description": "relieved face",
"unicodeVersion": "6.0",
- "digest": "b4ce2ba6c220d887fe5e333c05ed773df9b6df0ac456879fd8f5103ff68604a5"
+ "digest": "ed96de2532a1fd5f96f52621d233b391830d31119b9604e7505340aac2dd1fa5"
},
"reminder_ribbon": {
"category": "activity",
"moji": "🎗",
"description": "reminder ribbon",
"unicodeVersion": "7.0",
- "digest": "c3de2a7c9350b77a0b86c0dcce9dcd9953ea8a97aa1e7aed149755924742f54d"
+ "digest": "3f3b9a65033a2e9e9d58ee18aa3cb3158ce2bf243c6c0352f7278bf2b4f8106c"
},
"repeat": {
"category": "symbols",
"moji": "ðŸ”",
"description": "clockwise rightwards and leftwards open circle arr",
"unicodeVersion": "6.0",
- "digest": "b9512d508613ed0eb3181eb1030f7f6fd6b994476ecdfa308733c6df975fb99e"
+ "digest": "6e7a4196d2899b28b0c85a77c6abafd202f91189710793e9a6b4a95ab55c0fc5"
},
"repeat_one": {
"category": "symbols",
"moji": "🔂",
"description": "clockwise rightwards and leftwards open circle arr",
"unicodeVersion": "6.0",
- "digest": "53409cf24dd4bb0d7b50ae359f15d06b87b7f4a292ed5c3a09652fa421a90bf2"
+ "digest": "6f6ace59c5d36c66d5816247e9c29f6aa3efef428ee83c99c9d341f7c055a64c"
},
"restroom": {
"category": "symbols",
"moji": "🚻",
"description": "restroom",
"unicodeVersion": "6.0",
- "digest": "2e7a1bfc9a9d49b0272230a91db7369e24d54bf1de8e683d36b85f1d8c037f77"
+ "digest": "f2a6d958afccd904f504425f024c968e22d13466f122006b245ea3db25e22bdd"
},
"revolving_hearts": {
"category": "symbols",
"moji": "💞",
"description": "revolving hearts",
"unicodeVersion": "6.0",
- "digest": "c43d3197cb4cf06659f643638f6c4e91a2889e0f6531b7d81ea826c2a8b784fc"
+ "digest": "f6d44311823de89d93f7f0c0758e60a804491237b18b4b0bd20a9843570c9c04"
},
"rewind": {
"category": "symbols",
"moji": "âª",
"description": "black left-pointing double triangle",
"unicodeVersion": "6.0",
- "digest": "d20c918c1e528ff0947312738501ca9a6fb6ff4016aad07db7a8125d00fd65cd"
+ "digest": "12a3f494d633a469015ed63e737a4bf0fac43206bf4a55c4d0e0c588a81bdffc"
},
"rhino": {
"category": "nature",
"moji": "ðŸ¦",
"description": "rhinoceros",
"unicodeVersion": "9.0",
- "digest": "163fa3acd78eead72c431a1f48b8465a6d45272a9169560e456d30b4df93dc6b"
+ "digest": "6b23d83c2b2cc252e5983b75840086971807c2ea5425f17753d049b5b7a5ebf7"
},
"ribbon": {
"category": "objects",
"moji": "🎀",
"description": "ribbon",
"unicodeVersion": "6.0",
- "digest": "74315fe907f9f0203afe139cd4552aa442eecfa2a64fac12db3e1292fc5a8828"
+ "digest": "498ca699cf15df0de221f962a03566a1944f9eab0cdd44353460d9198265f35c"
},
"rice": {
"category": "food",
"moji": "ðŸš",
"description": "cooked rice",
"unicodeVersion": "6.0",
- "digest": "f544f12606de59d28739798003f14ebd8869856add8e24496ec5dda3e131daf4"
+ "digest": "ca2eb63d32044cf29435eec542dea6d2aad9eed4dcf4d12bb092a221c4e17eac"
},
"rice_ball": {
"category": "food",
"moji": "ðŸ™",
"description": "rice ball",
"unicodeVersion": "6.0",
- "digest": "2cba6f5364cd366859bc8948897b65fc97b225ea7973d9be3b24aba388fed8e8"
+ "digest": "40e8af6fcac8dbc63e18809e12a00e41dc8cf75eba0c856f8c031c866e27099c"
},
"rice_cracker": {
"category": "food",
"moji": "ðŸ˜",
"description": "rice cracker",
"unicodeVersion": "6.0",
- "digest": "ac0f805d41d4f322154c1968bd3ce3e9aabcd39d908182e52fd7d28458dbef92"
+ "digest": "33d54212f8418a5148b4b7e7b38edc72e7f03c5cf54356cdc15319c56160a3f3"
},
"rice_scene": {
"category": "travel",
"moji": "🎑",
"description": "moon viewing ceremony",
"unicodeVersion": "6.0",
- "digest": "b942a06d3da0570aca59bab0af57cd8c16863934f12a38f70339fd0a36f675f5"
+ "digest": "18b94e88b72cd2158d831d86f78c91d3ae44b279ec104b3606fd177a2ab1372f"
},
"right_facing_fist": {
"category": "people",
"moji": "🤜",
"description": "right-facing fist",
"unicodeVersion": "9.0",
- "digest": "f815d1cc0c0345ddcc8886ae9c133582d7dc779732ac9b93dde1ab4fdd3b251d"
+ "digest": "d1abe6e551a7b336ed0c7234db5c5a653db975647ac603a320f05b1635378736"
},
"right_facing_fist_tone1": {
"category": "people",
"moji": "🤜ðŸ»",
"description": "right facing fist tone 1",
"unicodeVersion": "9.0",
- "digest": "0f9269b70cf68071d97389e059a2bdacffd73f2afd2ce6cfd7447bb1a4e9abbb"
+ "digest": "d281365007abb9150174089f9a1baa7033237f6e566aca72763e538861674a74"
},
"right_facing_fist_tone2": {
"category": "people",
"moji": "🤜ðŸ¼",
"description": "right facing fist tone 2",
"unicodeVersion": "9.0",
- "digest": "32a9833db853972e49e65aa227fb0512c57362da190aa1cc40e1d64f238e837e"
+ "digest": "841c242354f94f30eea0e16ab3373d6c6d6d3e6a90ac20baf7765a08bf6e7f07"
},
"right_facing_fist_tone3": {
"category": "people",
"moji": "🤜ðŸ½",
"description": "right facing fist tone 3",
"unicodeVersion": "9.0",
- "digest": "be4706f8bb088411f5cbbf9065a0ae5b773c97456bd975c2b6789765657847b9"
+ "digest": "6843fe9b8f162bc43bff78c16555f9eadece02285ca7758818db5e8c4caf064b"
},
"right_facing_fist_tone4": {
"category": "people",
"moji": "🤜ðŸ¾",
"description": "right facing fist tone 4",
"unicodeVersion": "9.0",
- "digest": "1680862891a9d85c4b6f76232a80e2ef7428bcec93087c86eae2efaba9c6a3f7"
+ "digest": "af349e6f8b54e0124667e7a6cf01fb4eb48eb21653e8f6d0ddd22e8114dde797"
},
"right_facing_fist_tone5": {
"category": "people",
"moji": "🤜ðŸ¿",
"description": "right facing fist tone 5",
"unicodeVersion": "9.0",
- "digest": "388715a4bc2178c52bbb3bc2729f57be50acab5d751784c9f3220e86c6b1fbcc"
+ "digest": "efd40f38ab91c5ea8e66ba129d4aa2d5af2c35c5030182695cfe81d6e9123987"
},
"ring": {
"category": "people",
"moji": "ðŸ’",
"description": "ring",
"unicodeVersion": "6.0",
- "digest": "b5322907222797b5e1786209cda88513e76cd397a40f0a7da24847245c95ef9d"
+ "digest": "ec4386554d3b001d9b64cfa534094b67844b55bcbec118146c5d238079107f6f"
},
"robot": {
"category": "people",
"moji": "🤖",
"description": "robot face",
"unicodeVersion": "8.0",
- "digest": "4d788e6ec89279588b036fca6b17f5a981291681df8f90306ecf5c039de40848"
+ "digest": "363bacd1c9c3bb115d4fe363ac212fc0a81270c057aaf432ab866581b976e38d"
},
"rocket": {
"category": "travel",
"moji": "🚀",
"description": "rocket",
"unicodeVersion": "6.0",
- "digest": "b82e68a95aa89a6de344d6e256fef86a848ebc91de560b043b3e1f7fd072d57d"
+ "digest": "136f56b7d54596e10ba226a05a8f4628eba967d8fc90d55c115bdf4366d102d8"
},
"rofl": {
"category": "people",
"moji": "🤣",
"description": "rolling on the floor laughing",
"unicodeVersion": "9.0",
- "digest": "f4f99ba2ac67b97338f904f9384ff03fb832a2e427bf6e74611bf5fee45f1f48"
+ "digest": "1a997e5e1a86c52ced7f4685ad6eb6ce93d50aef0b4cde72f143dd75e5139b43"
},
"roller_coaster": {
"category": "travel",
"moji": "🎢",
"description": "roller coaster",
"unicodeVersion": "6.0",
- "digest": "a65e9ace1d7900499777af1225995f17af90a398bb414764c20b6e09a8c23a2c"
+ "digest": "5c4c5d8639d4bbeab07bc46304e5233a95f379fad92e395d087afe5af00529fc"
},
"rolling_eyes": {
"category": "people",
"moji": "🙄",
"description": "face with rolling eyes",
"unicodeVersion": "8.0",
- "digest": "23dea8100da488a05721a4e82823eb438393b0ea762211c9ecef011d127aa1b7"
+ "digest": "a5fec5606c1cd4b295fe69c261326c848e246622c02ca6cda9f2c5a5bf0aed98"
},
"rooster": {
"category": "nature",
"moji": "ðŸ“",
"description": "rooster",
"unicodeVersion": "6.0",
- "digest": "2b90c5cf6fa46da13eb77285443d600afcea0c48bd1d215d60167e7dc510da5d"
+ "digest": "8ebd22e8776d16c6557f777a731871e93a20b8b828b718f57267033f13a5e50b"
},
"rose": {
"category": "nature",
"moji": "🌹",
"description": "rose",
"unicodeVersion": "6.0",
- "digest": "73799e459dba188de4de704605d824242feeb65d587c5bf9109acf528d037146"
+ "digest": "a86cff9a79b2296c8c2c39dbeb7bd9e42edf2e5af402ae5dfb63a3bf910083cd"
},
"rosette": {
"category": "activity",
"moji": "ðŸµ",
"description": "rosette",
"unicodeVersion": "7.0",
- "digest": "2537def4deef422d4e669b28b1a0675259306ab38601019df3ec3482b14e52d5"
+ "digest": "b5d6fac78383056f66f48e9576f3e8e1f38c473330f44382e0f2a13bb0b6cf89"
},
"rotating_light": {
"category": "travel",
"moji": "🚨",
"description": "police cars revolving light",
"unicodeVersion": "6.0",
- "digest": "91fcdb85a752ae904d335a978c7e7936aed4c75d414b35219b5a74430e51555f"
+ "digest": "353edbbfb893497b28d753273a11eb94ae67136365dae826ad5c7ac5a37b0d08"
},
"round_pushpin": {
"category": "objects",
"moji": "ðŸ“",
"description": "round pushpin",
"unicodeVersion": "6.0",
- "digest": "8ffca77bbdc6f1f726daf3abd6eff338a5ad1aa9b09dbbd8782c1e7ef5452f30"
+ "digest": "c79c44a8563cd0777ce2f26d1dea54b283d76d4309eccfe048ba3b2ea8a9645b"
},
"rowboat": {
"category": "activity",
"moji": "🚣",
"description": "rowboat",
"unicodeVersion": "6.0",
- "digest": "83715d83a061926d4ad3bb569b21f5d337e3ebd4c9bcdfe493e661c12adc0a16"
+ "digest": "a0a0b5f15fffb7be60e7467c2a0a368b34a8f9d47af65ead06881bad9e0bd8c2"
},
"rowboat_tone1": {
"category": "activity",
"moji": "🚣ðŸ»",
"description": "rowboat tone 1",
"unicodeVersion": "8.0",
- "digest": "e279ac816442c0876fba1f42c700b80f2fb6de671e1a8a9e9d11b71eed5c58e8"
+ "digest": "2f6403643528646b73013979e3564e54a9a529782f019a44a956ff275b2017c0"
},
"rowboat_tone2": {
"category": "activity",
"moji": "🚣ðŸ¼",
"description": "rowboat tone 2",
"unicodeVersion": "8.0",
- "digest": "6a48eba352ed4971d26498b6c622e5772389c89c5205ed02acde8e995dddcc3b"
+ "digest": "cd925816e16fce63bca0dbd0fc2832fd69ff98a9ee7836ddbc939f3bd9b5a189"
},
"rowboat_tone3": {
"category": "activity",
"moji": "🚣ðŸ½",
"description": "rowboat tone 3",
"unicodeVersion": "8.0",
- "digest": "875948f6d8354ebd95ce9a66fde30f06a8366dcd89d5ca3e660845f8801e9305"
+ "digest": "09cee7c79709dfdb07e98b585617a068dd624713a02d0f5c21fd7b09a5695baf"
},
"rowboat_tone4": {
"category": "activity",
"moji": "🚣ðŸ¾",
"description": "rowboat tone 4",
"unicodeVersion": "8.0",
- "digest": "8c7ac7346b0020d0ff5e2f4a1efb1b7785eac637f17556663ec33e2335083f0a"
+ "digest": "12408bd1b720f2799c46fb22d91c9d62fe5fe4f0f2449e2eff921d7f392ab22f"
},
"rowboat_tone5": {
"category": "activity",
"moji": "🚣ðŸ¿",
"description": "rowboat tone 5",
"unicodeVersion": "8.0",
- "digest": "a399dbb647892b22323e0bf17bc36a9b5f1708ebedf9ba525233ee7b9d48339a"
+ "digest": "cb64137080640be1bcb7e577e0984bc5cf5dd524e60e229c09003191c4ca1680"
},
"rugby_football": {
"category": "activity",
"moji": "ðŸ‰",
"description": "rugby football",
"unicodeVersion": "6.0",
- "digest": "cc6f00ade3e0bbb7899e7bfb138b57216dd66de26d7967d5ffa501f382ed09f4"
+ "digest": "db852921f30f88e9604440a5d7f8ce513c3001293a1ffbc35c66c45fee1159c4"
},
"runner": {
"category": "people",
"moji": "ðŸƒ",
"description": "runner",
"unicodeVersion": "6.0",
- "digest": "e9af7b591be60ade2049dbada0f062ba2d3e17f02bec76cbd34ce68854a2a10c"
+ "digest": "6a87e5a783e98a571bdbe4d983b0cce46c0b337707a99a8bea7dcc5a5d78c46e"
},
"runner_tone1": {
"category": "people",
"moji": "ðŸƒðŸ»",
"description": "runner tone 1",
"unicodeVersion": "8.0",
- "digest": "21091cbb09c558712ecf63548bf28b7995df42bdb85235088799a517800e52f5"
+ "digest": "788912454e5a001a96cfbbf7ae07d22c7d53bd0a0a333add62bd38f50f890202"
},
"runner_tone2": {
"category": "people",
"moji": "ðŸƒðŸ¼",
"description": "runner tone 2",
"unicodeVersion": "8.0",
- "digest": "1fe3d194f675a46fe67799394192e66c407dd81163363692c5e7da32ddb9af2b"
+ "digest": "0e0c0509fe054b31b82629bb97d410d56154143e0612af9ced7f754bc16876b8"
},
"runner_tone3": {
"category": "people",
"moji": "ðŸƒðŸ½",
"description": "runner tone 3",
"unicodeVersion": "8.0",
- "digest": "8cea1bf4ef3be71f42dc5bae978d5b7a197a3851543225349ef0dda29a370537"
+ "digest": "33b6233182bec5958325115fc8b238913773b03fe616ceb465152c75a83aa3bd"
},
"runner_tone4": {
"category": "people",
"moji": "ðŸƒðŸ¾",
"description": "runner tone 4",
"unicodeVersion": "8.0",
- "digest": "c33f0b8b5a71d295fb6ba322e79446964a8eca9e4573efd591e4273808b088a0"
+ "digest": "d14b09b58e47a80781df8f7d6687be75f2bc22f312b96129109166c1535e6001"
},
"runner_tone5": {
"category": "people",
"moji": "ðŸƒðŸ¿",
"description": "runner tone 5",
"unicodeVersion": "8.0",
- "digest": "9f59e6dd0fdf2f17bceb41f5c355b4e6f3c8bb8cbd8af0992f0b5630ff8892e8"
+ "digest": "a816106153bf16d304e766386d3ad641fc931faa302d998fc2bd3e3334de5d7f"
},
"running_shirt_with_sash": {
"category": "activity",
"moji": "🎽",
"description": "running shirt with sash",
"unicodeVersion": "6.0",
- "digest": "7542307d3595aca45e8ccae66b6e58b6e92870144b738263d5379ec6dc992b76"
+ "digest": "a5f5ff9bf3e3eab82f370c9b81dc2bce186bb0a667dee54a2066d42f04d97eb4"
},
"sa": {
"category": "symbols",
"moji": "🈂",
"description": "squared katakana sa",
"unicodeVersion": "6.0",
- "digest": "6042bcabd1516ef3847d695aba22851c49421244432d256e24eba04e8a223dab"
+ "digest": "58e18447fd35e85c8a7c45eab01da1e2d6ff67d933e0ea9d5875a5e83273e733"
},
"sagittarius": {
"category": "symbols",
"moji": "â™",
"description": "sagittarius",
"unicodeVersion": "1.1",
- "digest": "a02593e025023f2e82a01c587a8c0bbb1eff88cbcabf535a1558413eb32ed1d5"
+ "digest": "23c2aa3cbb29c0fb6c443d8d388e41454b4da2aae8f239c4572ecf0e9d580276"
},
"sailboat": {
"category": "travel",
"moji": "⛵",
"description": "sailboat",
"unicodeVersion": "5.2",
- "digest": "c95ef4dc939cbdcb757ef3cd90331310e8c0a426add8cc800bae2540148a3195"
+ "digest": "252e917b1bc71019256db272af716e77bbe5839e4e5b77416ee566657ec3ffaf"
},
"sake": {
"category": "food",
"moji": "ðŸ¶",
"description": "sake bottle and cup",
"unicodeVersion": "6.0",
- "digest": "0a786075f3d9da48ae91afccf6ae0d097888da9509d354ee1d3cb99afcc88fe4"
+ "digest": "bd09899bee1411e26464b5f0d86d69a3f57cfd6e3f557f0f87fcb61bd2fc51ba"
},
"salad": {
"category": "food",
"moji": "🥗",
"description": "green salad",
"unicodeVersion": "9.0",
- "digest": "fe321487ab847abe670e68a83f1d9e096129741c689c769ee7de4a65aeac29f8"
+ "digest": "2498d846c9ae599cd1fac3c74e87f595e1938df6b9a0eeb001c7f19ca0c7477d"
},
"sandal": {
"category": "people",
"moji": "👡",
"description": "womans sandal",
"unicodeVersion": "6.0",
- "digest": "03c3077cb4bd900934f9bdf921165b465e5cc9a6bee53e45a091411bceb8892d"
+ "digest": "9737db7518eaf91a7294503c471ba0b015260677ca842988ef3764d30a0d402b"
},
"santa": {
"category": "people",
"moji": "🎅",
"description": "father christmas",
"unicodeVersion": "6.0",
- "digest": "178513e3d815917e59958870f5885b3414b43a16b8056980c863a468dfe00179"
+ "digest": "bc9f3a14f824d9299d2132822c6341c4e87f53ed0c5050c31b5b96d801bc5c3c"
},
"santa_tone1": {
"category": "people",
"moji": "🎅ðŸ»",
"description": "father christmas tone 1",
"unicodeVersion": "8.0",
- "digest": "bf900bbc19bbd329229add9326e28e8197b69d6ddceb69f42162b0200fde5d16"
+ "digest": "7e527394c52da94c740197b0d05d15d7c5ee113dce7a7800ec617bd3a3fa297f"
},
"santa_tone2": {
"category": "people",
"moji": "🎅ðŸ¼",
"description": "father christmas tone 2",
"unicodeVersion": "8.0",
- "digest": "7340f2171adab97198e3eecac8b0d84c4c2a41f84606301a0d10e9fe655c93d1"
+ "digest": "26c649ec3f466952dbb6d3234ad3254c735259c83bfbbf96c68d0203ed5744e1"
},
"santa_tone3": {
"category": "people",
"moji": "🎅ðŸ½",
"description": "father christmas tone 3",
"unicodeVersion": "8.0",
- "digest": "7368ab75454ec28d8f7d6baef6ad69b5278445a9f50753f6624731bffde32054"
+ "digest": "d8e656829487c0808af4efb095e55cbc8a9b18576572ebd61dbac422119a1a01"
},
"santa_tone4": {
"category": "people",
"moji": "🎅ðŸ¾",
"description": "father christmas tone 4",
"unicodeVersion": "8.0",
- "digest": "0ee60188353e0ee7772079c192bebbc6d49e74e63906f840c66da4eb35f4f245"
+ "digest": "e12990b6edb39eea5f8bcd0f3c4d0f404cd47beb8fe180066455f833e7b99cf8"
},
"santa_tone5": {
"category": "people",
"moji": "🎅ðŸ¿",
"description": "father christmas tone 5",
"unicodeVersion": "8.0",
- "digest": "e4378a0cc5d21e9b9fe6e35c32d1ebc6fb8c2e1c09554cd096aeaefd3a6eb511"
+ "digest": "0310b472690b6f3aac9fa4f611fa00c3d9d5d50edb94d08a676c77f28c0913da"
},
"satellite": {
"category": "objects",
"moji": "📡",
"description": "satellite antenna",
"unicodeVersion": "6.0",
- "digest": "c9d63118dcb445856917bb080460ab695cc78e715dcbba30ba18dffa9e906b27"
+ "digest": "84aa893218e8cc97a0f8b74d2d34c0b05a62d8eef47d5f0fede8ee956b222acd"
},
"satellite_orbital": {
"category": "travel",
"moji": "🛰",
"description": "satellite",
"unicodeVersion": "7.0",
- "digest": "beb2f50e7f2b010e76bed9daa95d7329a93c783d3ebc4f0b797dd721c5e3d32d"
+ "digest": "f80a557315729acf11186808c9bf031570a12f34c8da29e6f4506d732609d541"
},
"saxophone": {
"category": "activity",
"moji": "🎷",
"description": "saxophone",
"unicodeVersion": "6.0",
- "digest": "dfd138634f6702a3b89b5a2a50016720eef3f800b0d1d8c9fe097808c9491e96"
+ "digest": "e49b31381a32c4ddf5b47b631e3c260bc62c793084b3cf026af5bea3105b6e0e"
},
"scales": {
"category": "objects",
"moji": "âš–",
"description": "scales",
"unicodeVersion": "4.1",
- "digest": "2280c026f16c6b92e0daa00bc14e718770f8d231c571ab439bde84d837cf31cc"
+ "digest": "2d0fcd2d6d6fe368d142ce7cd1ba78d9fc802131d84e0097d89e49041a9342e8"
},
"school": {
"category": "travel",
"moji": "ðŸ«",
"description": "school",
"unicodeVersion": "6.0",
- "digest": "af198b068a86ccad3daec4c6873e6b4735086c1ecbb3848182e70bae9aa3ee24"
+ "digest": "d6cf41776c0b3c6e3a20d672b85ef91a65085dc7ee40aa4b0c94b0683f3ab2b4"
},
"school_satchel": {
"category": "people",
"moji": "🎒",
"description": "school satchel",
"unicodeVersion": "6.0",
- "digest": "f670ae8aea67eb9d8aaa0bf2748c1cc3e503dcc1dbe999133afcdf21af046b24"
+ "digest": "500fdb662493897890ad00c67200190fc2b48a5629231994d7bf43a5a9897e6d"
},
"scissors": {
"category": "objects",
"moji": "✂",
"description": "black scissors",
"unicodeVersion": "1.1",
- "digest": "95225be28f05d8b5a6b6e6bf58d973f61f183ad4fef55a558dc1b810796b85c8"
+ "digest": "295ce7c48d3f8e58daa454f18d534146bfaf98d46614e2783535927f23d22215"
},
"scooter": {
"category": "travel",
"moji": "🛴",
"description": "scooter",
"unicodeVersion": "9.0",
- "digest": "4a7db148880398db75e059711cb53edefb6b8fa9d442009f52856b887ab1dde4"
+ "digest": "baa3060602995716fba048ed2be1559712abc6edc3d8822b4ae6c0fe185197e4"
},
"scorpion": {
"category": "nature",
"moji": "🦂",
"description": "scorpion",
"unicodeVersion": "8.0",
- "digest": "d41119d1ea5daf727c17dbea7dadec1718c72fc9f98ae88252161df5fde0938a"
+ "digest": "2e97ed412be63a4eaefd4205d13e5d4957389ce7497c4c79e00e9729bdb39e0c"
},
"scorpius": {
"category": "symbols",
"moji": "â™",
"description": "scorpius",
"unicodeVersion": "1.1",
- "digest": "a36404b408814c2ecb8fa8b61f5c5432dfcf54cae8c09cc67b8d0fadf7cbdc03"
+ "digest": "32550597084a3b17fdab6bc4f56513a5952581ad07e79fb56abe05d6665a86af"
},
"scream": {
"category": "people",
"moji": "😱",
"description": "face screaming in fear",
"unicodeVersion": "6.0",
- "digest": "916e4903a4b694da4b00f190f872a4e100e7736b7a2e6171fa1636f46bf646e6"
+ "digest": "3403d66a449c643d1dbc3029d11bf9a9edfd503b5594b524517356a8eeef296e"
},
"scream_cat": {
"category": "people",
"moji": "🙀",
"description": "weary cat face",
"unicodeVersion": "6.0",
- "digest": "f1d3a6ff538064e7d5e0321bbc33aba44e8da703dc1894ef1403c0cd6d63d781"
+ "digest": "e4d277a511c2e1edc5873579e78a94320133ff730502c1ebf36272e4a2e5c598"
},
"scroll": {
"category": "objects",
"moji": "📜",
"description": "scroll",
"unicodeVersion": "6.0",
- "digest": "9b2cb00860bcc2d20017cafb2ed9681b6232dc07273d489d75d53ce29e4ba3ab"
+ "digest": "abdb7024b5f50b04389b1a65e5cb5a3b7929f4e9c5719388684603210774b3c1"
},
"seat": {
"category": "travel",
"moji": "💺",
"description": "seat",
"unicodeVersion": "6.0",
- "digest": "ae68d86fc2a07cae332451b23bd1ceba3f6526a6c56d8c1089777fa4632850e1"
+ "digest": "ef4b820995bafb53c28877312060b1b6ef1d2e5d65268f9942ac3567914ef2da"
},
"second_place": {
"category": "activity",
"moji": "🥈",
"description": "second place medal",
"unicodeVersion": "9.0",
- "digest": "9e2336fc16e532829b55380252f94655b58817d47c909fc2570002c5b06b9c40"
+ "digest": "9c9a125c7085e8ab5b89cbd10d9458eac835330dbb78737e8cf979a39c2ae5fd"
},
"secret": {
"category": "symbols",
"moji": "㊙",
"description": "circled ideograph secret",
"unicodeVersion": "1.1",
- "digest": "1d0b9adde2657f41421b135962de20820cf4b4eb0204044f9859522ab9d211b0"
+ "digest": "a67c62b033cebaec448c90f0f98960058fd020fe523dbd315e6b60966fb89da7"
},
"see_no_evil": {
"category": "nature",
"moji": "🙈",
"description": "see-no-evil monkey",
"unicodeVersion": "6.0",
- "digest": "3ff66d2e84b36d071d0a34f8e41cfd620a56b83131474ea50ed7803b635551ed"
+ "digest": "b5659d1f0ae7dc35ba729bee05ef351dbf8fe299b768937a1e271c19ac1dd9a9"
},
"seedling": {
"category": "nature",
"moji": "🌱",
"description": "seedling",
"unicodeVersion": "6.0",
- "digest": "c0ec5e6d20e1afdc4e78eeddb1301c8b708ad6278e7287a4e4e825417c858e75"
+ "digest": "4227f4780193ccd7d807c0e6d18b42cbaa247554708efbf64dbd3b7c6919a466"
},
"selfie": {
"category": "people",
"moji": "🤳",
"description": "selfie",
"unicodeVersion": "9.0",
- "digest": "2a1bc9f18ad4d6fb893d91c88ef1b2d9bd063dc2bb1a4b08c248c30f52545d4e"
+ "digest": "4914fbc5b8a0838d275c286b7a3626c9353e233ef75f2b1f600a647ff56a7ff4"
},
"selfie_tone1": {
"category": "people",
"moji": "🤳ðŸ»",
"description": "selfie tone 1",
"unicodeVersion": "9.0",
- "digest": "26dc212ffed30c276bd6a66a72bc4513e68098a2205fb4ca5b51ccfa1de5b544"
+ "digest": "0e9e3090566876f49dc5a03321e190dce2737a5c8547b07f0244056d59623182"
},
"selfie_tone2": {
"category": "people",
"moji": "🤳ðŸ¼",
"description": "selfie tone 2",
"unicodeVersion": "9.0",
- "digest": "71eceaefda46e3521f374f76693e7fa8f215067498067900080e2925ca94d7de"
+ "digest": "5d2c271f2cf39d3ffacf1192b1804edef0849a2ad8f0e81e493a752960de97ed"
},
"selfie_tone3": {
"category": "people",
"moji": "🤳ðŸ½",
"description": "selfie tone 3",
"unicodeVersion": "9.0",
- "digest": "53eabbd4f6b8ebbd2f7af7bf5cd64309c4039ac1c5b2180290a547deaafcebdf"
+ "digest": "41670b6b45ab178205692a6bca8816e79f99ed7bbab1754b99bcf973ff178e30"
},
"selfie_tone4": {
"category": "people",
"moji": "🤳ðŸ¾",
"description": "selfie tone 4",
"unicodeVersion": "9.0",
- "digest": "0baad378b09652b99c5d458db2e03b4db14a1557db4ea0969806a0ca1d33d40c"
+ "digest": "4b1c5145f0e454aed5c37b3dd3bef07dfa3576880997e6bd552871de474867ec"
},
"selfie_tone5": {
"category": "people",
"moji": "🤳ðŸ¿",
"description": "selfie tone 5",
"unicodeVersion": "9.0",
- "digest": "9a07608f34ec4dad48764a855f83f3965709d7b2fd2342e6dc9ed61f23f4adfd"
+ "digest": "bbe0db1f762ad830a38a6ff85e36565c0ef446c22b8ab25054d6b266f1b8421d"
},
"seven": {
"category": "symbols",
"moji": "7ï¸âƒ£",
"description": "keycap digit seven",
"unicodeVersion": "3.0",
- "digest": "ae85172d2c76c44afb4e3b45d277d400abb2dc895244b9abfbd1dac1cd7c53c2"
+ "digest": "e9c95466693be79dff2e1d8eadddfc75967e6f7f641a21efcabccf173a8224c7"
},
"shallow_pan_of_food": {
"category": "food",
"moji": "🥘",
"description": "shallow pan of food",
"unicodeVersion": "9.0",
- "digest": "7c7ad9d5d3f7226427d310b5853e8257fad899febe58dcbc5adb4677964f5c6d"
+ "digest": "1c90318cf2f78c965a0e4dfc710781e5da862874fa8e29f010231e5dc5657976"
},
"shamrock": {
"category": "nature",
"moji": "☘",
"description": "shamrock",
"unicodeVersion": "4.1",
- "digest": "68ed70c26e04a818439a1742d2da6bc169edd02db86b6e6f8014b651f3235488"
+ "digest": "cb9408a7b1884bfca8fe7cd2ea93440a49a44b226298325a3f138f6e772f5d64"
},
"shark": {
"category": "nature",
"moji": "🦈",
"description": "shark",
"unicodeVersion": "9.0",
- "digest": "23a2364b6356e7bbb84c138e9cf58e2c68cd8caabb337a0c4d365ce87bf5d2da"
+ "digest": "552b7265f53c435c860583c2aaee8acec5f854fa2092f6e8be74d89f9f3132da"
},
"shaved_ice": {
"category": "food",
"moji": "ðŸ§",
"description": "shaved ice",
"unicodeVersion": "6.0",
- "digest": "54048e77268b7548d03088517bf8558d11324db901ca57f9bec93f1873663a74"
+ "digest": "5f3f65f3974f30d1c9557d2c4af3052c7548f534b854f964647cafc2b4ab73a8"
},
"sheep": {
"category": "nature",
"moji": "ðŸ‘",
"description": "sheep",
"unicodeVersion": "6.0",
- "digest": "c867c8e6e51768f1f51f4fe5abd3fbd5c1d69b01a3cb48b5fb94b6e2338a271c"
+ "digest": "7bd6d2af15a7d13587b9521d80668d5db70c67188df59a33921e78edbf40e42e"
},
"shell": {
"category": "nature",
"moji": "ðŸš",
"description": "spiral shell",
"unicodeVersion": "6.0",
- "digest": "8983652d33ad6ab91195518cecb5a268a1c0ae603d271f0ddd756ff50058ddb3"
+ "digest": "4d30626d66ac2921fb7a81761841923b855e363c4198eea67c76d86c696cc805"
},
"shield": {
"category": "objects",
"moji": "🛡",
"description": "shield",
"unicodeVersion": "7.0",
- "digest": "763d0a56a62c51c730ccb0fbea38ab597cbf41a85ab968198e6ec35630d50aa5"
+ "digest": "ce3512d081c31c26df95a8f791aa413db09d25e8fba29a1e9f6a2470d6cb3430"
},
"shinto_shrine": {
"category": "travel",
"moji": "⛩",
"description": "shinto shrine",
"unicodeVersion": "5.2",
- "digest": "38a6d756c5aa9703510afa5076d75192f7814bbb6632394d4b8253d9ceda7f8c"
+ "digest": "e3027766f283d86acb7f0730dd04cbda16bb6fa16c90edb40dad7f09f1bca3fe"
},
"ship": {
"category": "travel",
"moji": "🚢",
"description": "ship",
"unicodeVersion": "6.0",
- "digest": "79c680845892a3e81ec6af2160ee07c29147155943e5daba6c76d04252014c20"
+ "digest": "9d0c13fcfcefd0a07424396626cc955e0b5e6cdf8b6d7d3ae1c1f746826af89b"
},
"shirt": {
"category": "people",
"moji": "👕",
"description": "t-shirt",
"unicodeVersion": "6.0",
- "digest": "46c7253e15d7cac03699ddb1550fbb7565bbe487310f7e218c0583aa69f9d3c5"
+ "digest": "a165e8bd82e5ef701aafaabcfac6946af3a0c10c22d4c84010103ecf8d74e424"
},
"shopping_bags": {
"category": "objects",
"moji": "ðŸ›",
"description": "shopping bags",
"unicodeVersion": "7.0",
- "digest": "95a3f03c675207bb1354270d02a630c204455c47b3edca23c48523a40cf3ea3b"
+ "digest": "1a6df85fd8117c2c9361c7524a43613a80d6c6d65a1940f2320cbc7d451ebf6f"
},
"shopping_cart": {
"category": "objects",
"moji": "🛒",
"description": "shopping trolley",
"unicodeVersion": "9.0",
- "digest": "4599b63f6861cdb4d8272cac84435c24c1d4d6a73c66d51e04a1cd14a1d333e6"
+ "digest": "cc32f38d94856b58620bd817fe40641c937ceacdc6b3c7e9ed4350c8926f128f"
},
"shower": {
"category": "objects",
"moji": "🚿",
"description": "shower",
"unicodeVersion": "6.0",
- "digest": "6b3c767c0eb472d4861c6c3cc2735a5e2c09681872ef42a11dc89f3c80b9da01"
+ "digest": "dc732f36a76bbd98ccc3ec886bb697fe8b0e799bc063abc1d5aaa9da4adb655a"
},
"shrimp": {
"category": "nature",
"moji": "ðŸ¦",
"description": "shrimp",
"unicodeVersion": "9.0",
- "digest": "b3651f3be3767125076a013fe903854f5b456a8afae865cb219cf528e0f44caa"
+ "digest": "fd240e3208f6221cf6e7053645d40767898ea430733e0ebc5b81a8f834be2eb1"
},
"shrug": {
"category": "people",
"moji": "🤷",
"description": "shrug",
"unicodeVersion": "9.0",
- "digest": "6e264243cc3b6e396069dea4357a958bdcd4081cb1af0ed6aa47235bef88cf27"
+ "digest": "1203afd3973f34c726c8e8ca66b76c2f1e7036a45d595d6f4cfd104c00d76d63"
},
"shrug_tone1": {
"category": "people",
"moji": "🤷ðŸ»",
"description": "shrug tone 1",
"unicodeVersion": "9.0",
- "digest": "0567b9fd95c8a857914003a5465a500ca79c8111811d45b865021b1b1d92d0b1"
+ "digest": "fb6eb588f019cf7a25bac347cb2b5c124f9d333314d040daef8b70ed1de5032d"
},
"shrug_tone2": {
"category": "people",
"moji": "🤷ðŸ¼",
"description": "shrug tone 2",
"unicodeVersion": "9.0",
- "digest": "1557c2f5e3d4599c806d74c0b78afcca940678787534b6862bb89a20601bac8a"
+ "digest": "a3b64ffa33f602adae12924b5576b6ed1f4bebbcf2db4952ec846b9778aadeaa"
},
"shrug_tone3": {
"category": "people",
"moji": "🤷ðŸ½",
"description": "shrug tone 3",
"unicodeVersion": "9.0",
- "digest": "f02754541a7bf74ba7eebe6c27daf1e3e1dac25172c35b8ba45641e278dfda3d"
+ "digest": "e7148fbdb7194182d5f3c66e9a1e7a9e5a8c4d88ceab38f5d0ecd40bc231f6b8"
},
"shrug_tone4": {
"category": "people",
"moji": "🤷ðŸ¾",
"description": "shrug tone 4",
"unicodeVersion": "9.0",
- "digest": "2b5121164cb5f4e253d8fb31f6445cf8afaf30dba41732edc511440cdb78d15c"
+ "digest": "8977c5afbde154d944f965ff7f10d26167ea427b8b191a6ec8708c6517168334"
},
"shrug_tone5": {
"category": "people",
"moji": "🤷ðŸ¿",
"description": "shrug tone 5",
"unicodeVersion": "9.0",
- "digest": "62d99a26bbad479f574f66208c41b9960cd41fb9d79d3a13fbdaa44682077115"
+ "digest": "3968a312496e479a86b63274f529c2b283d180118c04edf3c6b6ea5f812c05bb"
},
"signal_strength": {
"category": "symbols",
"moji": "📶",
"description": "antenna with bars",
"unicodeVersion": "6.0",
- "digest": "2c6f04ba4ecd2d2d423e19eb52cfbfd253f4db6e0908d91c1af4ea6192597447"
+ "digest": "eabf6d0cae69aea6027f1dede7df1ac51fc09d85af8a4ae9b1df1fcb8ee4a0f0"
},
"six": {
"category": "symbols",
"moji": "6ï¸âƒ£",
"description": "keycap digit six",
"unicodeVersion": "3.0",
- "digest": "cede9324261208d0fd5d00fcdfc0df0331944bd9cff4f40b30a582a641526c1c"
+ "digest": "f455fcc89917bf67c1ac4245399146912578582cdff0e1e8bc216a4c4b7c43a0"
},
"six_pointed_star": {
"category": "symbols",
"moji": "🔯",
"description": "six pointed star with middle dot",
"unicodeVersion": "6.0",
- "digest": "9203e3b4f08af439ae0bfb6a7b29a02dceb027b6c2dc5463b524dfd314cbff4e"
+ "digest": "1ee9c385a74dc6954e37727615d99209a61627562c8675d4354262b2c421418f"
},
"ski": {
"category": "activity",
"moji": "🎿",
"description": "ski and ski boot",
"unicodeVersion": "6.0",
- "digest": "80f0ca8660ba373fef823af9e98e148c4ddb1e217eb6d0a0ea2bae2288b57570"
+ "digest": "973ff4abd90a020e2c608c32ab88324e1a11ca7a4541e436f37c5d858681eba6"
},
"skier": {
"category": "activity",
"moji": "â›·",
"description": "skier",
"unicodeVersion": "5.2",
- "digest": "4fff0aa155367f551a59aed9657b8afa159173882b25db9cd8434293d1eed76d"
+ "digest": "7a490189499bc88ed15fe945813665ba3114edc039d25eb003026d27c84b5f78"
},
"skull": {
"category": "people",
"moji": "💀",
"description": "skull",
"unicodeVersion": "6.0",
- "digest": "cdd2031164281bf2b0083df4479651d96bc16d11e44bac4deaf402a9c0d6f40a"
+ "digest": "ccf317cd63caa24cd1a008dd26cda83d6487a0a7fca71843e42715cd8cbaafc9"
},
"skull_crossbones": {
"category": "objects",
"moji": "☠",
"description": "skull and crossbones",
"unicodeVersion": "1.1",
- "digest": "ae764ba21a1fcc4409f4cc9e75a261d70b87548f64158dbd3451374ad5724123"
+ "digest": "81f050043fc49fb83d5e87753337f77fb2acd599e53432212de42ec58345d567"
},
"sleeping": {
"category": "people",
"moji": "😴",
"description": "sleeping face",
"unicodeVersion": "6.1",
- "digest": "1050a011509b56735c9f30a6fccc876256e2a4546dc6052e518151c8aca4b526"
+ "digest": "061017b6fea9012cdfc7f90ab5dbf18a55830743fdd062f1ea0a085f52e0a564"
},
"sleeping_accommodation": {
"category": "objects",
"moji": "🛌",
"description": "sleeping accommodation",
"unicodeVersion": "7.0",
- "digest": "2ce42c027d1d0947abc403c359fd668a7bc44f5ead2582e97f3db7dd4e22e5d5"
+ "digest": "18ea38c6da5ac6f86c56b546c78ba60bca1aca9eba397b9500d91e8533e81823"
},
"sleepy": {
"category": "people",
"moji": "😪",
"description": "sleepy face",
"unicodeVersion": "6.0",
- "digest": "2ee9bb1f72ef99e0e33095ec2bbf7a58ffea0ff7d40b840f4cdba57be9de74b0"
+ "digest": "afc0c40fb97bd1fe79e828f76f03aa08beeed09b42e307b5053758d9889fcc01"
},
"slight_frown": {
"category": "people",
"moji": "ðŸ™",
"description": "slightly frowning face",
"unicodeVersion": "7.0",
- "digest": "d71d564a6c2d366a8e28a78ef4e07d387a77037fe8c99aa0ea1571299dc490c9"
+ "digest": "2bccd273d6445ddf54366b9aa565370af3110b7722cb9a85e76534c729b397b8"
},
"slight_smile": {
"category": "people",
"moji": "🙂",
"description": "slightly smiling face",
"unicodeVersion": "7.0",
- "digest": "10f4b66a755f5c78762a330f20d1866e4a22f3f1d495161d758d3bab8d2f36fe"
+ "digest": "04feb9e847c67936ddd0e40d6dd6c90333abc9bfbd81fae7fef9bd1e5265ba9e"
},
"slot_machine": {
"category": "activity",
"moji": "🎰",
"description": "slot machine",
"unicodeVersion": "6.0",
- "digest": "914184788f8cd865cd074dca25c22acee31f5498117bd9a6e78cae67e6601652"
+ "digest": "c057d62fa2bca301d20f6103606873b82d0136711f4d922eb05ab29d3179ecfe"
},
"small_blue_diamond": {
"category": "symbols",
"moji": "🔹",
"description": "small blue diamond",
"unicodeVersion": "6.0",
- "digest": "0b56d8e6b5ddf1f49fcc76e45e5fb2ee9f99ae6ffe682c26eaea4d9b7faac36c"
+ "digest": "22016e16c1e769099e972a93eaed9fd4131867020c0d6669aeb323d414ef1f93"
},
"small_orange_diamond": {
"category": "symbols",
"moji": "🔸",
"description": "small orange diamond",
"unicodeVersion": "6.0",
- "digest": "a2235830550e289c1608f2dcf5ede48f5c1a0eff45570699c39708c9677ab950"
+ "digest": "7de47af62764c8136415214e7eb7b8e985ec600b79991c0ba44b96824350eeef"
},
"small_red_triangle": {
"category": "symbols",
"moji": "🔺",
"description": "up-pointing red triangle",
"unicodeVersion": "6.0",
- "digest": "8c2985c4e9ce42d2f3b35539b879bc36206c5ef749f39fbd1eac51bd2676e1e5"
+ "digest": "521e2b28387cd5d13d17c5dedf6b944c0139f36bc6136e5bcca5b59ee1a59823"
},
"small_red_triangle_down": {
"category": "symbols",
"moji": "🔻",
"description": "down-pointing red triangle",
"unicodeVersion": "6.0",
- "digest": "46bd328df2fbf5d0597596bbf00d2d5f6e0c65bcb8f3fb325df8ba0c25e445b5"
+ "digest": "cfbea3a1506cd1f26aa11603421d2137c3a847f4dc1d0728c16901e0e4195adc"
},
"smile": {
"category": "people",
"moji": "😄",
"description": "smiling face with open mouth and smiling eyes",
"unicodeVersion": "6.0",
- "digest": "14905c372d5bf7719bd727c9efae31a03291acec79801652a23710c6848c5d14"
+ "digest": "fb06bf4088887ca1aadbc0201b63d75f3d2b5b5779bd81f1767f17e794b0c0a7"
},
"smile_cat": {
"category": "people",
"moji": "😸",
"description": "grinning cat face with smiling eyes",
"unicodeVersion": "6.0",
- "digest": "c35b76d6df100edb4022d762f47abfeb9f5e70886960c1d25908bd5d57ccb47e"
+ "digest": "5882f8784080c11ae3b95bccb4ecf00dacd127047ff76d3b4158fbba0ddb1f14"
},
"smiley": {
"category": "people",
"moji": "😃",
"description": "smiling face with open mouth",
"unicodeVersion": "6.0",
- "digest": "a89f31eb9d814636852517a7f4eadec59195e2ac2cc9f8d124f1a1cc0f775b4a"
+ "digest": "9b0f2fca8ba5bb1b3de39686302f2f9ef7e1c93d4af47c71828931f874bd4db1"
},
"smiley_cat": {
"category": "people",
"moji": "😺",
"description": "smiling cat face with open mouth",
"unicodeVersion": "6.0",
- "digest": "3e66a113c5e3e73fb94be29084cb27986b6bdb0e78ab44785bf2a35a550e71bf"
+ "digest": "eb6c8fa3e46a9ea9c0e79b3db5578299ea041792ae46c54c50799e5c3970c372"
},
"smiling_imp": {
"category": "people",
"moji": "😈",
"description": "smiling face with horns",
"unicodeVersion": "6.0",
- "digest": "3e02131d16525938f6facc7e097365dec7e13c8a0049a3be35fc29c80cc291b3"
+ "digest": "7609669c056339bec4dc916c3b0fb56d4adc55d37b8c3e0fb078af59594500d9"
},
"smirk": {
"category": "people",
"moji": "ðŸ˜",
"description": "smirking face",
"unicodeVersion": "6.0",
- "digest": "3c180d46f5574d6fca3bb68eb02517da60b7008843cb3e90f2f9620d0c8ee943"
+ "digest": "e02911a76fe7c40dde28998741f201789b7ab5c6be6e5168e4eddbd9886ef790"
},
"smirk_cat": {
"category": "people",
"moji": "😼",
"description": "cat face with wry smile",
"unicodeVersion": "6.0",
- "digest": "0683c7f73e1f65984e91313607d7cca21d99acd4b2e9932f00e0fffd0ce90742"
+ "digest": "8aed1a44a0b0673c1f62cf9f77d89239725258b7b3b482b66b5d39c6306b601a"
},
"smoking": {
"category": "objects",
"moji": "🚬",
"description": "smoking symbol",
"unicodeVersion": "6.0",
- "digest": "baa9cb444bf0fe5c74358f981b19bc9e5c0415ced7f042baf93642282476ea61"
+ "digest": "3fa148109d83f785ad90999c0d362fb9d6aadd38986f7d483fd0f70ecb5b0447"
},
"snail": {
"category": "nature",
"moji": "ðŸŒ",
"description": "snail",
"unicodeVersion": "6.0",
- "digest": "5733bf3672ae4b2b3e090fa670aeac70dcbcc04ca5b13abc8c8e53b8b3d4ff33"
+ "digest": "4244f824afbbf8f60e41654f35596395a9a45715a3f229e351aaea6dab361e02"
},
"snake": {
"category": "nature",
"moji": "ðŸ",
"description": "snake",
"unicodeVersion": "6.0",
- "digest": "18da2d97c771149ef5454dd23470e900903a62ab93f9e2ce301aad5a8181d773"
+ "digest": "1b28000702a5b3b294b22c5bd1ad8c203937712fb30dc1cb12f63fc6244e38e6"
},
"sneezing_face": {
"category": "people",
"moji": "🤧",
"description": "sneezing face",
"unicodeVersion": "9.0",
- "digest": "c20ef571dc7e35572fe3c18b7845aefc89af083ea925c48a29de3b7387af6e17"
+ "digest": "fa08b2714d529efb670662a65b19201333217d31152a1e4c48b3ee7ab4398eb5"
},
"snowboarder": {
"category": "activity",
"moji": "ðŸ‚",
"description": "snowboarder",
"unicodeVersion": "6.0",
- "digest": "c6e074139b851aa53b1ba6464d84da14b3da7412fc44c6c196a8469d76915c19"
+ "digest": "b2acc118ae84560f980a44a95af7c2de8e57c2c95ff69ef9c25c9e5d535306b8"
},
"snowflake": {
"category": "nature",
"moji": "â„",
"description": "snowflake",
"unicodeVersion": "1.1",
- "digest": "6556c918e181df01ba849e76c43972d5310439971e5d8fc2409d112c05bf0028"
+ "digest": "256f84d43855ee7699d7bfa2e3bb4cf71ec61ee9cc83a1ffb2973393cc43a5fa"
},
"snowman": {
"category": "nature",
"moji": "⛄",
"description": "snowman without snow",
"unicodeVersion": "5.2",
- "digest": "6137456b2335e88e09c1859615eb22bb636355ef438f7a3949ad2f3d54478dd3"
+ "digest": "c0908d9bc9b9fabff1e5eb18c6db07e981a4b9d886c7babbe2ce109e244f8182"
},
"snowman2": {
"category": "nature",
"moji": "☃",
"description": "snowman",
"unicodeVersion": "1.1",
- "digest": "33ec75c22a13c81fa3c6b24a77ac1a08dc0dbe70b3716cf17b6702014d8a63fe"
+ "digest": "ce7bc1b374999e94c2f4a08f77ed979ccb6ee86ec9a6c1b8f4a93680080a25a7"
},
"sob": {
"category": "people",
"moji": "😭",
"description": "loudly crying face",
"unicodeVersion": "6.0",
- "digest": "d1ed4b31861f9f9fd4e9c95a9c17530e2320a1b4cad6ececb1545ce25d65e4ce"
+ "digest": "2bd275f629a26cb40ce648eff68155a5625e944ed724b8a6d2890a80a099503a"
},
"soccer": {
"category": "activity",
"moji": "âš½",
"description": "soccer ball",
"unicodeVersion": "5.2",
- "digest": "6a3f2e6a9a0b64c3fbf8705995792091daf386a4112dba75507a1f556f662f84"
+ "digest": "1807b8f9e9b0a3cbf390a582f52d2ec4dad7a19008d9d0215ae6cded7b6dd691"
},
"soon": {
"category": "symbols",
"moji": "🔜",
"description": "soon with rightwards arrow above",
"unicodeVersion": "6.0",
- "digest": "a49d1bcfbac3e6ccc05b9a9863eff74b0eb8b4d4b22b8b0f7b2787fcba1c73cc"
+ "digest": "6325b67539559992fc3d1ed23f2dc20ee95b3052b93a674f82ed53dc2e199270"
},
"sos": {
"category": "symbols",
"moji": "🆘",
"description": "squared sos",
"unicodeVersion": "6.0",
- "digest": "2fa7e0274383aeed6019eb9177e778d7aab8b88575b078b0ffeb77cd18df14b3"
+ "digest": "13dcfd9239e12ebdb00b2e3b632e26fa1160ed645226f21b6cef5a7f3a9690fe"
},
"sound": {
"category": "symbols",
"moji": "🔉",
"description": "speaker with one sound wave",
"unicodeVersion": "6.0",
- "digest": "faaca7b315b2495cbc381468580d25f1d11362441c35bb43d8a914f2ec8202d2"
+ "digest": "c1e588da701bb5e139cfb4c8e068b8785d4ac08afc255792d28b06c7e0e565a9"
},
"space_invader": {
"category": "activity",
"moji": "👾",
"description": "alien monster",
"unicodeVersion": "6.0",
- "digest": "e75379cb5063f9a8861d762ad1886097c1697fbb61f2e4e8f531047955a4a2dd"
+ "digest": "84897a48330cb0ae9ac42111cfaa0e0baefb5c314cb49d1eae77c7ace3a7ab25"
},
"spades": {
"category": "symbols",
"moji": "â™ ",
"description": "black spade suit",
"unicodeVersion": "1.1",
- "digest": "2c4d20f6a4893cfc62498d3f1f8f67577f39ed09f3e6682d8cb9cd8f365d30da"
+ "digest": "4581ce17d9b2a29ba4cc38794d7869e12cd1ceda5861e67b2d09130730ccc378"
},
"spaghetti": {
"category": "food",
"moji": "ðŸ",
"description": "spaghetti",
"unicodeVersion": "6.0",
- "digest": "6d3451dc0faa1913539edb99261448f51735f269b61193c53dfe63466c0191e8"
+ "digest": "b2de3171e90345dc777aa7554d97d6de659f4a9928b7da6a871e3925e234484c"
},
"sparkle": {
"category": "symbols",
"moji": "â‡",
"description": "sparkle",
"unicodeVersion": "1.1",
- "digest": "7131163cd6c2f879110c86e9f068c33cf580f7c4b619449c41851fe6083402ee"
+ "digest": "8aab76f3a4f25b2e583fe675546e400e96417bc99e1c7ed08007d3afaaffc9a1"
},
"sparkler": {
"category": "travel",
"moji": "🎇",
"description": "firework sparkler",
"unicodeVersion": "6.0",
- "digest": "88539ed8a13bd66e0c265c0913bd3ec2ddc4d95484323595713beb102221a1f6"
+ "digest": "d603ef03cdc4ec05338005c357c3a41215f180545f422fea5b40b766ecfe6d1f"
},
"sparkles": {
"category": "nature",
"moji": "✨",
"description": "sparkles",
"unicodeVersion": "6.0",
- "digest": "cf84d16b1c0a381d5a7ae79031872747c9a6887eab6e92cc4a10a4b8600ef506"
+ "digest": "8f68cb167489b1055a8acedaf8ea4c0553d0a5f7bf0983fc3660537ff09a5360"
},
"sparkling_heart": {
"category": "symbols",
"moji": "💖",
"description": "sparkling heart",
"unicodeVersion": "6.0",
- "digest": "b80b1ddef83b6528b309a194f6f2faf5acab603daeb9254523efc2b941bcb6d2"
+ "digest": "cc017b631dae27a01e15faa5f7d24c35983a4a2d928c23e9449b1b183636cb05"
},
"speak_no_evil": {
"category": "nature",
"moji": "🙊",
"description": "speak-no-evil monkey",
"unicodeVersion": "6.0",
- "digest": "d2d7cfb4d471928a496bdc146890adc8422a68500b68115630b24c125d18e81f"
+ "digest": "7cb1d4a61d2947bb0624a57a7355089f751d576c3bf26b61e3a2f1c413b4c293"
},
"speaker": {
"category": "symbols",
"moji": "🔈",
"description": "speaker",
"unicodeVersion": "6.0",
- "digest": "dbca5f7181728d2ad67ff76fd566ffbdf53e333e7eeed341f54668bd47969413"
+ "digest": "f83fd9518675bb83fa037a49d762f774eccea08f2a981dc85c37c46a6621cd6d"
},
"speaking_head": {
"category": "people",
"moji": "🗣",
"description": "speaking head in silhouette",
"unicodeVersion": "7.0",
- "digest": "4be1af79b4506c00af4df64663413bcbae195dab0bc63c5011feb8f9663ed544"
+ "digest": "d6e536f54711d04899135d966b9ba64286e58b05879c90855e49e5c64fca7567"
},
"speech_balloon": {
"category": "symbols",
"moji": "💬",
"description": "speech balloon",
"unicodeVersion": "6.0",
- "digest": "817100d9979456e7d2f253ac22e13b7a2302dc1590566214915b003e403c53ca"
+ "digest": "8a0b9329452cb5b6d529bb5a5a56656eceaba92177f566e3748d7910588a938b"
},
"speech_left": {
"category": "symbols",
"moji": "🗨",
"description": "left speech bubble",
"unicodeVersion": "7.0",
- "digest": "912797107d574f5665411498b6e349dbdec69846f085b6dc356548c4155e90b0"
+ "digest": "45487904f8cbf1a1de421f85fbdd212e0a7e51d8540d9f99b65a1aea187477b5"
},
"speedboat": {
"category": "travel",
"moji": "🚤",
"description": "speedboat",
"unicodeVersion": "6.0",
- "digest": "a523b2320f0b24be1e9fdbc1ff828e28d8fd9a64d51e5888ab453ef0bc9f0576"
+ "digest": "54ce5a81c70e2f1e57a8d0f90829db96d146d84911462b8412e1cb6ee62ddf22"
},
"spider": {
"category": "nature",
"moji": "🕷",
"description": "spider",
"unicodeVersion": "7.0",
- "digest": "8411eac0c1b80926fd93cc1d6423e00b05d04c485b79ee232da8f1714e899a37"
+ "digest": "204672675b8f272185eb58517e6cac6e9398a9c27279b8bb0da97330d35da094"
},
"spider_web": {
"category": "nature",
"moji": "🕸",
"description": "spider web",
"unicodeVersion": "7.0",
- "digest": "2434bdfbe56dcc4a43699dd59b638af431486b52fb1d6d685451f3b231b2be23"
+ "digest": "82a223ba2c1dc71ac0945544a16a2f607a679c5727cd86070b537bec6e1fdcb1"
},
"spoon": {
"category": "food",
"moji": "🥄",
"description": "spoon",
"unicodeVersion": "9.0",
- "digest": "4fa31d59e5bffd2c45a8e01fcd5652e78a5691cbfa744e69882bc67173ddea05"
+ "digest": "c5fbd1bd2ca6ca2cf13a6b7bfaeba67305d21b2d86bba97e7d283ca1e9b1aacf"
},
"spy": {
"category": "people",
"moji": "🕵",
"description": "sleuth or spy",
"unicodeVersion": "7.0",
- "digest": "99fe3cdeff934726ee5855b0e401bf32570084aaad4eb10df837fd410ca742aa"
+ "digest": "af9ec39cb9ec28b9b3917628187b28899f8f778b593ce722c59575af6a8cff75"
},
"spy_tone1": {
"category": "people",
"moji": "🕵ðŸ»",
"description": "sleuth or spy tone 1",
"unicodeVersion": "8.0",
- "digest": "1720a99064061c43c7647b6bd517efa2ee2621b355a644adfb347d62849366a2"
+ "digest": "26134ab9a163d03fde9a4ce7e77ba06acfd6a385d6534bd94cbd0430fdb56054"
},
"spy_tone2": {
"category": "people",
"moji": "🕵ðŸ¼",
"description": "sleuth or spy tone 2",
"unicodeVersion": "8.0",
- "digest": "23ff0026723f2b5a46fbfb55e24c4a4a33af2bd96808b3ea3af76aae99965d68"
+ "digest": "6f0d3ae8b0980c4586aaacdc8df8ed5815fe5f1fe18be566316cb0f21b1beeba"
},
"spy_tone3": {
"category": "people",
"moji": "🕵ðŸ½",
"description": "sleuth or spy tone 3",
"unicodeVersion": "8.0",
- "digest": "1d0cb3d54fb61e4763a4f0642ef32094bdd40832be0d42799ce9ba69773616df"
+ "digest": "154818ede71c0b8ae5cdf621efe9560e419f62f67ad03049c29cf505bd160bbc"
},
"spy_tone4": {
"category": "people",
"moji": "🕵ðŸ¾",
"description": "sleuth or spy tone 4",
"unicodeVersion": "8.0",
- "digest": "e36a4b52df6cb954fab9d9128111f1301c6d46bdeacf51993ffb5bb354cd0ad3"
+ "digest": "2ff959799064e9e47c9e1698357b04cc0fd1343bfc8b1be0d20fe49852b05f32"
},
"spy_tone5": {
"category": "people",
"moji": "🕵ðŸ¿",
"description": "sleuth or spy tone 5",
"unicodeVersion": "8.0",
- "digest": "ffc6fefd9a537124ebf0a9ddf387414dce1291335026064644f6cf9315591129"
+ "digest": "6046a8031fd6d410380d41f2a7cd658d9aec9b61a5759265a26ae1e2b9409096"
},
"squid": {
"category": "nature",
"moji": "🦑",
"description": "squid",
"unicodeVersion": "9.0",
- "digest": "65a1b318c2c506b9d26cfd8282a5cf9922109595c8d12e92c3f7481ac7c08c49"
+ "digest": "f483430d758e7432b8696b5f95bf606b17cb017ea0beb5dc97dcf7fae7ed2455"
},
"stadium": {
"category": "travel",
"moji": "ðŸŸ",
"description": "stadium",
"unicodeVersion": "7.0",
- "digest": "73bf955e767ba1518c9c92b2ba59a2aa1ec4b018652dffd97bcd74832a33789f"
+ "digest": "807c4f6f19b9819ca3c846126ccfa2d24a2b00b66cb946e8be75536032426815"
},
"star": {
"category": "nature",
"moji": "â­",
"description": "white medium star",
"unicodeVersion": "5.1",
- "digest": "d78e5c1b78caed103e100150c10b08a9ca3ee30c243943d6fc3cc08f422122e9"
+ "digest": "3dc3b69f9789146c64cd333666f35ce1e1efdd4fe335f6b8574685015bf8bd09"
},
"star2": {
"category": "nature",
"moji": "🌟",
"description": "glowing star",
"unicodeVersion": "6.0",
- "digest": "f91ac4afe3f5d4a52847ae8b4a9704b591e00399aebba553d150d7e34ee939fa"
+ "digest": "c242d4e9c64d0ba3d8b5e3c83888ee4561c4250e48bd72f80d3264497a66ce77"
},
"star_and_crescent": {
"category": "symbols",
"moji": "☪",
"description": "star and crescent",
"unicodeVersion": "1.1",
- "digest": "1bf3d29e50034f5e7c0dccff0a3a533b74bfa9b489e357b2739a473311f1332a"
+ "digest": "550cf94a0efe6ef0211e51e2d84554bd789505c861a16efa79704f8ccda086b1"
},
"star_of_david": {
"category": "symbols",
"moji": "✡",
"description": "star of david",
"unicodeVersion": "1.1",
- "digest": "28a0bd0eeac9d0835ceb8425d72c2472464e863dd09b76a0ddc1c08cf1986402"
+ "digest": "dbe79ef9f506a4f46368a8a5e9953579c97fc1bca97c1ddc7f2bcc76398f0149"
},
"stars": {
"category": "travel",
"moji": "🌠",
"description": "shooting star",
"unicodeVersion": "6.0",
- "digest": "837d9045316b8fb5e533457eac61241534f641eb78d8cb75f688f80fb8e8a7f0"
+ "digest": "46bfa86253fb531e4357590f5244a88c3713926d1f28349ca641705dc069265f"
},
"station": {
"category": "travel",
"moji": "🚉",
"description": "station",
"unicodeVersion": "6.0",
- "digest": "27a163ac0aea4ed247a121cae826eafc475977c68b0d888e9405bea14326ff56"
+ "digest": "a4e784b6c4238269932befca55cd7b41af85fc899f023a49c7f1ceaf81652496"
},
"statue_of_liberty": {
"category": "travel",
"moji": "🗽",
"description": "statue of liberty",
"unicodeVersion": "6.0",
- "digest": "f5a43599ab3f24ed3a78a745e06e2ac3e33107a292386ad81c67935ee5b22493"
+ "digest": "9779b56242c4eb3de2060b060ae39de21ad1082b1135ec9c29f9d1aca6bf13cb"
},
"steam_locomotive": {
"category": "travel",
"moji": "🚂",
"description": "steam locomotive",
"unicodeVersion": "6.0",
- "digest": "52ad0073f37b978faf3884fb193046f2b0614e1557bbcc9de1b020e42aff2dba"
+ "digest": "479aa4a2c2704d79f642036eef9c8ddf00f8df17b9389a87d7d5f688827c7f56"
},
"stew": {
"category": "food",
"moji": "ðŸ²",
"description": "pot of food",
"unicodeVersion": "6.0",
- "digest": "c16f61236db314ad8d9f2dd241ec1e15c8d64e5872cce93ec4d0996490dd39df"
+ "digest": "0c9cdd4de27a6108da2567070dad1ab9220dc513dd8ec6543ad66dddb7c09bdc"
},
"stop_button": {
"category": "symbols",
"moji": "â¹",
"description": "black square for stop",
"unicodeVersion": "7.0",
- "digest": "83f9d0da3ad845fef41b4e8336815d30e9c8f042ab2a8340894ade2f428fc98a"
+ "digest": "ea16a3e7a6ffa4741509cc909944975dd24c4a0678a23cc03e02c3773e6bba92"
},
"stopwatch": {
"category": "objects",
"moji": "â±",
"description": "stopwatch",
"unicodeVersion": "6.0",
- "digest": "9b6b9491a24d8ab4f896eb876da7973f028bd5e7c51a3767ba7e61bb6fbb2be0"
+ "digest": "162489af83ccc7e09349637fa9e23b97a22208b05ff6bfbd31271a50c3745ee9"
},
"straight_ruler": {
"category": "objects",
"moji": "ðŸ“",
"description": "straight ruler",
"unicodeVersion": "6.0",
- "digest": "cee31101767bd3f961363599924dc3790675d05a1285a8396428d2f91771c111"
+ "digest": "ab8b04cfbb19178452fc5eb32eea3a619049b0d46ea21b4c48023e01c30b6510"
},
"strawberry": {
"category": "food",
"moji": "ðŸ“",
"description": "strawberry",
"unicodeVersion": "6.0",
- "digest": "5750a15e12f21259286ddbc3a8222a385b3b97a9f368897f42dd000060343174"
+ "digest": "4563a502fa27cbc543f6ad287a6c40eee76319e29a98fbf818c93e7b48c2249f"
},
"stuck_out_tongue": {
"category": "people",
"moji": "😛",
"description": "face with stuck-out tongue",
"unicodeVersion": "6.1",
- "digest": "92dc42980a6dfdd7204fc874a762d6a0bbf0fdbfb5a7c0698fca04782e99fde6"
+ "digest": "04df5c3e122e85ebafea184a808d090cebe8fda6c08ab08bb756a21d43b6661f"
},
"stuck_out_tongue_closed_eyes": {
"category": "people",
"moji": "ðŸ˜",
"description": "face with stuck-out tongue and tightly-closed eyes",
"unicodeVersion": "6.0",
- "digest": "434d25ac24cad7ba699eae876a25d9a99b584449cca50b124bf6aa7f20a83d51"
+ "digest": "88bceb40811057945decca24c3fb69f5703a15417dd5bf16787019e9067cb125"
},
"stuck_out_tongue_winking_eye": {
"category": "people",
"moji": "😜",
"description": "face with stuck-out tongue and winking eye",
"unicodeVersion": "6.0",
- "digest": "dbacd6428a2a2933212e6a4dc0c7f302177fb23b963626ccb26f27f91737f03d"
+ "digest": "73443f4962da500d4ebe32abf7a9d95a217fa3f58df5567f8ac623b439f8b265"
},
"stuffed_flatbread": {
"category": "food",
"moji": "🥙",
"description": "stuffed flatbread",
"unicodeVersion": "9.0",
- "digest": "9f841f2520640d69be4f20a3199023d5811842b28556b5e1152e5ec11f0fda07"
+ "digest": "ace05b5608aa3c51ad0aff66949ff5c6d06812597d1f55cb21a29834e531c46c"
},
"sun_with_face": {
"category": "nature",
"moji": "🌞",
"description": "sun with face",
"unicodeVersion": "6.0",
- "digest": "7256ff5263006c64c03f1eb66e3ddb56d67d785d65dacc37aa886d0cd4be63be"
+ "digest": "631ad6d36e45769ebfe03c3d9fc18d5ad8f333c58ed7f92dcc5dcb8bf7f6321e"
},
"sunflower": {
"category": "nature",
"moji": "🌻",
"description": "sunflower",
"unicodeVersion": "6.0",
- "digest": "27d1161f50f932a6b26c404cf2e8f7083683ed0f2382d62b7472acccaa6eb695"
+ "digest": "ea2947ff8994128b131e8e692d6183f38553d709fafa7611f3c15d00e5e2b9d6"
},
"sunglasses": {
"category": "people",
"moji": "😎",
"description": "smiling face with sunglasses",
"unicodeVersion": "6.0",
- "digest": "966684382e5c59e98319e4c0ea7c304c61c2638ad5408faa49ce2c83c4416757"
+ "digest": "1b2ba362ef41c55b05bf8d28df5508e8f4f2b0418c22c47ecd9e8e772ac1c19b"
},
"sunny": {
"category": "nature",
"moji": "☀",
"description": "black sun with rays",
"unicodeVersion": "1.1",
- "digest": "460fea4cbbdd1595450c1033a2ee5de7fea2e2f147822efa49f7e204812415aa"
+ "digest": "254e2e15e1e548aeb54048217501d7da60f57ebe8c9de2e61e84e0714deba7a4"
},
"sunrise": {
"category": "travel",
"moji": "🌅",
"description": "sunrise",
"unicodeVersion": "6.0",
- "digest": "7718a49636b0cdd1862ed67c7a9d6e72f471c2591ff0d912485b1be55d1ea115"
+ "digest": "5e1511462f5e0bfaaf865baa62eb7dd1f76ce22acebb0bd5ef27c55e3a69fed3"
},
"sunrise_over_mountains": {
"category": "travel",
"moji": "🌄",
"description": "sunrise over mountains",
"unicodeVersion": "6.0",
- "digest": "743d0701cdbe2a814962363813c3153d3c5e62c3e410349f56d49dbb9581f356"
+ "digest": "089412d5a9ce8f71fa184bc90cd9a092bfea41361a792cc6b9f94ac1bc741fb7"
},
"surfer": {
"category": "activity",
"moji": "ðŸ„",
"description": "surfer",
"unicodeVersion": "6.0",
- "digest": "bb440775e9213430942015c37db8de58b5a561ee971b2a0f3993fc3f1d2554d4"
+ "digest": "39564fb830c8bd3e37cc30f227ffa454bee97a9f5a3df9d062df656fb7cca740"
},
"surfer_tone1": {
"category": "activity",
"moji": "ðŸ„ðŸ»",
"description": "surfer tone 1",
"unicodeVersion": "8.0",
- "digest": "a4937b030aca30b68bb644f37cf63c38aebce3c00b57d1c8a0ffe596b57d2f1e"
+ "digest": "c47d4c1057a86878179b86d4a56e432b9cc9d34f5d3aa9b817c84be29a029904"
},
"surfer_tone2": {
"category": "activity",
"moji": "ðŸ„ðŸ¼",
"description": "surfer tone 2",
"unicodeVersion": "8.0",
- "digest": "1c2a954a9c5284dedf0327d6f3c954c9fdd3953b848076d298874775ad8bf0a3"
+ "digest": "d15f802cf36c352a1817b15bc508a1983c9362e24d2707f12f7e6a2c4b1f8b90"
},
"surfer_tone3": {
"category": "activity",
"moji": "ðŸ„ðŸ½",
"description": "surfer tone 3",
"unicodeVersion": "8.0",
- "digest": "418a3408b9ab026124f067c8597b500217e56bc28d9844a29eea5eee6f604ff8"
+ "digest": "1377c1f74dd0987032b564c7ad55d0a2bb418e1f372937db50cb0e6806e9c11a"
},
"surfer_tone4": {
"category": "activity",
"moji": "ðŸ„ðŸ¾",
"description": "surfer tone 4",
"unicodeVersion": "8.0",
- "digest": "530870b9ac9f4d45ff750e264feb90b44fb93ca2852f323987b06f5f12fb5a4d"
+ "digest": "6155339508cf035a4eab763083f73e6c78bdaa15ce2acba5abe808b6d4f9d9c8"
},
"surfer_tone5": {
"category": "activity",
"moji": "ðŸ„ðŸ¿",
"description": "surfer tone 5",
"unicodeVersion": "8.0",
- "digest": "40e11b1ae652cfd085d083377f1da24160065ed1b67403c6fa4655e6e44169ec"
+ "digest": "c3f84fd38dfe40f539fbf1201c319b990aa4fb81bb57548377a7dfb2e3ee8661"
},
"sushi": {
"category": "food",
"moji": "ðŸ£",
"description": "sushi",
"unicodeVersion": "6.0",
- "digest": "b924c621236ca3284b349b0509ae1043f2fc2c7f6d67615716f9717ada78c992"
+ "digest": "a5bbbe7979621cc830f8a6860623af797530eb1d6cb4fb909f5e728ca8684864"
},
"suspension_railway": {
"category": "travel",
"moji": "🚟",
"description": "suspension railway",
"unicodeVersion": "6.0",
- "digest": "cd3d21da79864f0c018b863e82fb0561fff3c5e3c065303cfcb89c3663d638ba"
+ "digest": "8c3f5852d6b7e363ef8dc14c483154ed7b65456aaf6cbfb16b3f46539de17c8d"
},
"sweat": {
"category": "people",
"moji": "😓",
"description": "face with cold sweat",
"unicodeVersion": "6.0",
- "digest": "1aa771479aa1ac5eeea4bafbe93ebd85a0f692f6d869034f31e25b689c2e264d"
+ "digest": "54f6998fabdc88fd169a6c9013f6471608f29554dd304d3abe9ee246b4a0cb16"
},
"sweat_drops": {
"category": "nature",
"moji": "💦",
"description": "splashing sweat symbol",
"unicodeVersion": "6.0",
- "digest": "b575b85415bc9852cf6415d417ebf799167fde03c6819ebcaa24ae1b3dde8dab"
+ "digest": "48642bb76350a7be33303751b18ca1150085d20070e18eb9e3617833ae406b11"
},
"sweat_smile": {
"category": "people",
"moji": "😅",
"description": "smiling face with open mouth and cold sweat",
"unicodeVersion": "6.0",
- "digest": "171b0d0845d46c33bedb6d3b39fb1ff366e22ba90685eedabebd91bb2b0680de"
+ "digest": "18e9821a9dd3f90342ed952660654ddbb8e46671b5e95ab88df637406b6cc0fb"
},
"sweet_potato": {
"category": "food",
"moji": "ðŸ ",
"description": "roasted sweet potato",
"unicodeVersion": "6.0",
- "digest": "4b91920f0b87d42763313bc476f4c821a74e4c12dc1c92165a859dddeaaf8844"
+ "digest": "0a322b21e76c9c487b8a8cb158c60d6e0be1aaa0495f865262f4c69e55a870b0"
},
"swimmer": {
"category": "activity",
"moji": "ðŸŠ",
"description": "swimmer",
"unicodeVersion": "6.0",
- "digest": "2c4ed4a51aad99d9957ae11a219d5164db9748fc3a65002c6085a9f15adfa9e2"
+ "digest": "16c5a68b9f1cc7d0f5da1f288be73a0419d059e76f22bed5f7d7d902a1320af4"
},
"swimmer_tone1": {
"category": "activity",
"moji": "ðŸŠðŸ»",
"description": "swimmer tone 1",
"unicodeVersion": "8.0",
- "digest": "48588f129ee4af52ca2e0f4594213391978601087cd607896b2f979ca077284b"
+ "digest": "2159c9ecb0580a2183e921e3a3988643caaa56ad3037993b83e2776988a92e70"
},
"swimmer_tone2": {
"category": "activity",
"moji": "ðŸŠðŸ¼",
"description": "swimmer tone 2",
"unicodeVersion": "8.0",
- "digest": "fff209448524bd1ef4d6decabf6c1ead94c8d3d5b1bfb5e54f20cc8e139232fc"
+ "digest": "8aeeafc91941162d71eaf9d2a2313d9af6cfdf4ea081ccacbc6a28389e0e77c0"
},
"swimmer_tone3": {
"category": "activity",
"moji": "ðŸŠðŸ½",
"description": "swimmer tone 3",
"unicodeVersion": "8.0",
- "digest": "2003932cb2cf4ae9a10b23338bf375a9293fb18c0ecf91bdfae73be6eebb3800"
+ "digest": "e6811d73ef31041bb9c602e20e1853b34d6db4774dee657851b0e1952b7a038e"
},
"swimmer_tone4": {
"category": "activity",
"moji": "ðŸŠðŸ¾",
"description": "swimmer tone 4",
"unicodeVersion": "8.0",
- "digest": "20b4bff9baa1c694ad98067dde834c56092f023b9664bec382c2e512232bd480"
+ "digest": "627184d5dae69aea7345661c1c721beb78ccbeae9cf6dc3f844f6368fddf1018"
},
"swimmer_tone5": {
"category": "activity",
"moji": "ðŸŠðŸ¿",
"description": "swimmer tone 5",
"unicodeVersion": "8.0",
- "digest": "0ff8eb57c2be8e80a1bc6ba75b8d9ffb9bd8d3be636150c4c03399ec1886f218"
+ "digest": "db6862ca44bd4375ed8ccf2085398e4003342360f7f8325de3f7126d69716432"
},
"symbols": {
"category": "symbols",
"moji": "🔣",
"description": "input symbol for symbols",
"unicodeVersion": "6.0",
- "digest": "2a2a79816c4d0751a0d73586eec5e63b410653d3c85cc968906bf1fc03d89b94"
+ "digest": "ff91761a5def3885f52b44abc14a3073800f6ca6f5a61480c902917896843dc1"
},
"synagogue": {
"category": "travel",
"moji": "ðŸ•",
"description": "synagogue",
"unicodeVersion": "8.0",
- "digest": "98569cdd7c61528963b67b7891dfa46025c5e810cbb22ee18ddb3bd85de2da69"
+ "digest": "07bcf08d94008462f001e6512e3ba3e9e70cfd57ac4e84e04b94e6f74684f51c"
},
"syringe": {
"category": "objects",
"moji": "💉",
"description": "syringe",
"unicodeVersion": "6.0",
- "digest": "e1538e645ccc571227c994b71b3d1be2c4d072d8bd9c944a42ff4a11c91a34a6"
+ "digest": "7c1f7fcc64d14e129f02f6cdf63ba6d13839be54263c1c9c2471826583ca2431"
},
"taco": {
"category": "food",
"moji": "🌮",
"description": "taco",
"unicodeVersion": "8.0",
- "digest": "e1e45aefdb7445faeae75c3831df6a3d6f2590fcdd48a20d847593c246df613b"
+ "digest": "13802015749117fc3889d27eb8a66846bb81e2a469dfd90a66b9603b54526c5b"
},
"tada": {
"category": "objects",
"moji": "🎉",
"description": "party popper",
"unicodeVersion": "6.0",
- "digest": "1d2e6cbb2a3244240bc70209715d2213d1efee2e370cccfbcc046c333ae2d650"
+ "digest": "879b8a892411b1839ad7c4a4d9ffcae074d3829bb40767c916471b06a39da9ec"
},
"tanabata_tree": {
"category": "nature",
"moji": "🎋",
"description": "tanabata tree",
"unicodeVersion": "6.0",
- "digest": "592f2907ffc1b914390e1a106c15120ff3607e99192158b94d237975647c5540"
+ "digest": "6ec94e277dc3027dbaf8d844dd26202c00b36602f5f73d0d2c36c087d5d674b9"
},
"tangerine": {
"category": "food",
"moji": "ðŸŠ",
"description": "tangerine",
"unicodeVersion": "6.0",
- "digest": "40c9ddcde1b0bcfaeb466629a87825eb8c2037835720cbee5e2fda04be3c8d0a"
+ "digest": "6858dcb7aa079a6639511d86328f55fd70319787efe06934573c774adec2ade0"
},
"taurus": {
"category": "symbols",
"moji": "♉",
"description": "taurus",
"unicodeVersion": "1.1",
- "digest": "21cf24cb6410ab6596e2df8b3e242cc07f9dbb247eabc00c590fe184b373d068"
+ "digest": "e64c53547f42dc3e07c06f0891641395773a9cdca0adb3257ea584a3102d084f"
},
"taxi": {
"category": "travel",
"moji": "🚕",
"description": "taxi",
"unicodeVersion": "6.0",
- "digest": "c546cc743831cfbf0c15452767cf2a4faf3775066797e997ae7c1fcbe4eca479"
+ "digest": "260b37ae31fcfe5b30682f0592ec4e32ce308f9cb9574daa532099c47735252b"
},
"tea": {
"category": "food",
"moji": "ðŸµ",
"description": "teacup without handle",
"unicodeVersion": "6.0",
- "digest": "00e3f1e389fa58c4fcd8c53ebbf83d25872f4315845ab1984b35410ae65553d9"
+ "digest": "520da660803cd133832badfa170c6795e2673b6881b6b52e22db3771c430cafa"
},
"telephone": {
"category": "objects",
"moji": "☎",
"description": "black telephone",
"unicodeVersion": "1.1",
- "digest": "3a53851e641f8ad938ce3597b1afca2ea63c9314ff81f62563b99937496a13d7"
+ "digest": "63655f8f945e2b0a7bb235b7b2d118db845bea995f5d04adab25b9b1ea7fc9ae"
},
"telephone_receiver": {
"category": "objects",
"moji": "📞",
"description": "telephone receiver",
"unicodeVersion": "6.0",
- "digest": "1614d67f3d8814b0d75f39d55f9149e4d28ef57b343498625e62fcfff8365046"
+ "digest": "83bc544dc191e7145a4d59059780fbd5c020c64f090de11816d681a504d65472"
},
"telescope": {
"category": "objects",
"moji": "🔭",
"description": "telescope",
"unicodeVersion": "6.0",
- "digest": "4adf40387870276c4f59fb050d441023e8dac784365b6a8c0282fb519780b495"
+ "digest": "202137ea4dc1f3f544100942d597ec9a31c4c4a96f0386a77d437d2274a3fbe7"
},
"ten": {
"category": "symbols",
"moji": "🔟",
"description": "keycap ten",
"unicodeVersion": "6.0",
- "digest": "c7c9491021740d2c17edddb856f79579b0b943d8dc85a2f48dbaac84f35b8a40"
+ "digest": "4474d95b39371042bf8dfac128d68f391fb10efbc9c245de5dc6aefb10544439"
},
"tennis": {
"category": "activity",
"moji": "🎾",
"description": "tennis racquet and ball",
"unicodeVersion": "6.0",
- "digest": "dc1600b4d8dce3d26259eb0d1c6ab042566565e3c1f2c96112210f1550a716fd"
+ "digest": "857b0f96109f4534cef496348b76036354eecdee640855fb83e0e3b253c7d914"
},
"tent": {
"category": "travel",
"moji": "⛺",
"description": "tent",
"unicodeVersion": "5.2",
- "digest": "30d9b17ac3219d4970ddf54d7c1a288b0ae50f7f3b82ed232c0b1b19ef585662"
+ "digest": "a2fc1e803dc0eef13ea7d3847e1e92a3d0790b1336a7ed5675ea60069fb76676"
},
"thermometer": {
"category": "objects",
"moji": "🌡",
"description": "thermometer",
"unicodeVersion": "7.0",
- "digest": "66616babbcaef256d7b652796c760e8e893cb950c073348a408fe70904f80f25"
+ "digest": "4b54cd4fc758bfc9e8830d36726ba06a0ac9e0d0d397ecba99599c9bde44f4e5"
},
"thermometer_face": {
"category": "people",
"moji": "🤒",
"description": "face with thermometer",
"unicodeVersion": "8.0",
- "digest": "ac2b5caddd128563711a9dcc7f690cf210f684d5e8b64b09c0431d6902437126"
+ "digest": "8300d80af44461b1da2aeed90203901753705ec3418a288646a00dc59da70c93"
},
"thinking": {
"category": "people",
"moji": "🤔",
"description": "thinking face",
"unicodeVersion": "8.0",
- "digest": "4f0b84e5ab8a650cafb166e93688f0e9b31b9ade22a91035261ac90490edb9d3"
+ "digest": "2b2d2b844f147e1be7f4c9019c54ce1b96561b4a8e5bd0af9c8d955b3ceabefa"
},
"third_place": {
"category": "activity",
"moji": "🥉",
"description": "third place medal",
"unicodeVersion": "9.0",
- "digest": "27c9bcba44ad95bee30882cc0722e8b0a798206306655dd648e884447ed26808"
+ "digest": "0afe5ea1a8963329439e0a5ed4922939cc4ab733f5fb50f40edcc2e4fafa12ed"
},
"thought_balloon": {
"category": "symbols",
"moji": "💭",
"description": "thought balloon",
"unicodeVersion": "6.0",
- "digest": "bf59624560c333561d636aedf2c8827089e275895cf434974daaabb3d5cea46e"
+ "digest": "d6a36d105964c8184aa889193b812be4307508c10a9bf99d6eb199565be2c5cc"
},
"three": {
"category": "symbols",
"moji": "3ï¸âƒ£",
"description": "keycap digit three",
"unicodeVersion": "3.0",
- "digest": "d3f85828787799c769655c38a519cad0743ab799ab276c7606e6e6894cc442e6"
+ "digest": "e66cfca0c1871d16283fcdddc7b170ad67c0a52f21d54985e4789daa1c61ee63"
},
"thumbsdown": {
"category": "people",
"moji": "👎",
"description": "thumbs down sign",
"unicodeVersion": "6.0",
- "digest": "5954334e2dae5357312b3d629f10a496c728029e02216f8c8b887f9b51561c61"
+ "digest": "e5e3594f30f8b3c59f22963c3a903ec69569e9735690cbce1c96da981cea5f91"
},
"thumbsdown_tone1": {
"category": "people",
"moji": "👎ðŸ»",
"description": "thumbs down sign tone 1",
"unicodeVersion": "8.0",
- "digest": "3c2853491473fd7ae2d1b5415a425cc390d26a8754446f8736c1360e4cb18ba3"
+ "digest": "e360d25bc6fc05243ec5ea6489fdc80702899783faa83c88686c9b73c9e8684c"
},
"thumbsdown_tone2": {
"category": "people",
"moji": "👎ðŸ¼",
"description": "thumbs down sign tone 2",
"unicodeVersion": "8.0",
- "digest": "4e0f8f86a06b69e423df8d93f41ec393f12800633acc82c4cb6dff64ca0d8507"
+ "digest": "bf0ad5d01e7ac0ab4d2be9db76615ff303bd01d2b4915b2b846a494aa36878fd"
},
"thumbsdown_tone3": {
"category": "people",
"moji": "👎ðŸ½",
"description": "thumbs down sign tone 3",
"unicodeVersion": "8.0",
- "digest": "e08fa35575f59978612d4330bbc35313eca9c4dfa04f4212626abc700819effe"
+ "digest": "e3d907396c17971a6d533900dd857ad273c1b0ff1af520c6fda780a54616b3c8"
},
"thumbsdown_tone4": {
"category": "people",
"moji": "👎ðŸ¾",
"description": "thumbs down sign tone 4",
"unicodeVersion": "8.0",
- "digest": "7c6d118d20d5add8ca003e4a53e42685a1f9436b872ed10d79f67ad418fb2a44"
+ "digest": "31a952ef8b0fe9c0a9b04e46033e052d8104539929509010f7ab74a09b72d396"
},
"thumbsdown_tone5": {
"category": "people",
"moji": "👎ðŸ¿",
"description": "thumbs down sign tone 5",
"unicodeVersion": "8.0",
- "digest": "8697c4a4ee4d6669dc2d47aa97699c42012ca59b80818ad6845878b37b4a9c58"
+ "digest": "afe38eb9c879ba04556cb4bf211ef0dae63b51957389256e5af93dc7e7e94cef"
},
"thumbsup": {
"category": "people",
"moji": "ðŸ‘",
"description": "thumbs up sign",
"unicodeVersion": "6.0",
- "digest": "59ec2457ab33e8897261d01a495f6cf5c668d0004807dc541c3b1be5294b1e61"
+ "digest": "38755ce0360171dd24005d6f4d6b06c2df337adb0cfd590e2e381cf44a9c24ec"
},
"thumbsup_tone1": {
"category": "people",
"moji": "ðŸ‘ðŸ»",
"description": "thumbs up sign tone 1",
"unicodeVersion": "8.0",
- "digest": "f57e6c525e8830779ea5026590eec3ca10869dc438a0c779734b617d04f28d21"
+ "digest": "15492d43b5bafa46473154505b431ed81e365b6ebce507c97f509a00333420f3"
},
"thumbsup_tone2": {
"category": "people",
"moji": "ðŸ‘ðŸ¼",
"description": "thumbs up sign tone 2",
"unicodeVersion": "8.0",
- "digest": "980eeeb1d8f5d79dae35c7ff81a576e980aa13a440d07b10e32e98ed34cbf7f1"
+ "digest": "87f9941a2d3afba4ff5737a113cf070dcfbc3a2292ad15cb5b07459692cb0fdd"
},
"thumbsup_tone3": {
"category": "people",
"moji": "ðŸ‘ðŸ½",
"description": "thumbs up sign tone 3",
"unicodeVersion": "8.0",
- "digest": "b3881060569e56e1dd75ca7960feab0e58ae51f440458781948d65d461116b4e"
+ "digest": "f09364411db2331284b3deb85c6107049cbb41d2e5edfb50f61fc5907641a7a0"
},
"thumbsup_tone4": {
"category": "people",
"moji": "ðŸ‘ðŸ¾",
"description": "thumbs up sign tone 4",
"unicodeVersion": "8.0",
- "digest": "86fbe2c95414bce5e38fb5c33da31305d7942fca2c9c79168dcffdbd895e9ad6"
+ "digest": "8c1322a624b0ebcab1f08d7675df39383eac8b1d4b627889d3393b0d3cdc946d"
},
"thumbsup_tone5": {
"category": "people",
"moji": "ðŸ‘ðŸ¿",
"description": "thumbs up sign tone 5",
"unicodeVersion": "8.0",
- "digest": "49fa63ff725c746a18649df16c8fab69bad88bbb564884df79d1d15f553b7343"
+ "digest": "6dec547ee282457cbbcb7e3dffcf804188aed47960a70069df81a547a8f40df9"
},
"thunder_cloud_rain": {
"category": "nature",
"moji": "⛈",
"description": "thunder cloud and rain",
"unicodeVersion": "5.2",
- "digest": "dacc20b4f6b68e5834aa1b8391afa5e83b5e6eb28e2d2174d3a68186a770506d"
+ "digest": "c1d9417ce640885540743b4fdb7df6efcccb6a04a31a1c62780b4c952c9f11d4"
},
"ticket": {
"category": "activity",
"moji": "🎫",
"description": "ticket",
"unicodeVersion": "6.0",
- "digest": "b4326fe7761940216e6c76ee2928110a6b37bf913da9d694e96557e7c7c10420"
+ "digest": "0575c271a22acdc294505b2aae0f288e67b0d78d9b60af97420806ac893e4ea9"
},
"tickets": {
"category": "activity",
"moji": "🎟",
"description": "admission tickets",
"unicodeVersion": "7.0",
- "digest": "fb73358c3697c04fcfde6a1e705b1c3b47635b93b9cadfe31d5657566c7d190a"
+ "digest": "f70e7c3f2a059c85b36587941a861dc9e41c8db0475ddbe2d5dd50ad440dd579"
},
"tiger": {
"category": "nature",
"moji": "ðŸ¯",
"description": "tiger face",
"unicodeVersion": "6.0",
- "digest": "e139531e6c930bc46242dc0ed274661229de026b5419d8ea8f99fdb0f8a719ab"
+ "digest": "0ea11ea4b71adee37b67019634153f09ca6d5b762d4c9507a3d3f7b47ff59274"
},
"tiger2": {
"category": "nature",
"moji": "ðŸ…",
"description": "tiger",
"unicodeVersion": "6.0",
- "digest": "f930cc8714198310d9b0edca6baff243ac5a3320f75fadb56fa5acc6fe34ff24"
+ "digest": "84d80ae536dfad345dd878970c339451d4189f73f0d786cafcaa2421dab9fe97"
},
"timer": {
"category": "objects",
"moji": "â²",
"description": "timer clock",
"unicodeVersion": "6.0",
- "digest": "69b33f219523d89d81cbbc070ad7e528711e4b34e124a50acb12a0280a34d0b0"
+ "digest": "b94e3cdd84834063f72e333339b27f5aeaa2e8b3082eff51a871d706f0038349"
},
"tired_face": {
"category": "people",
"moji": "😫",
"description": "tired face",
"unicodeVersion": "6.0",
- "digest": "775739bc9324517e614878ca0960d793df97775feeb62b14dbfb311a42a21802"
+ "digest": "60d0656f21c7937c3f2e9c5a90d1dfd2deee068804fb17d813e8b6e9c9f994d5"
},
"tm": {
"category": "symbols",
- "moji": "â„¢",
+ "moji": "â„¢ï¸",
"description": "trade mark sign",
"unicodeVersion": "1.1",
- "digest": "7d9fafdb72d91860478fc185719f289f359eab2c368a132cb936a269e2ab6a24"
+ "digest": "aaa0898628f473e4e8df05d707b2d49a854ce3fbb78b8ca37ac0560b329fd8ea"
},
"toilet": {
"category": "objects",
"moji": "🚽",
"description": "toilet",
"unicodeVersion": "6.0",
- "digest": "0d1b0dd0078f51104e8632a0726e1b3f075561a1ffa8a2546602de15798415d0"
+ "digest": "ae590884c0bf0b5f5d721b4d7791ea3878a9514642f6a57ad4784b2ca7ce6fbd"
},
"tokyo_tower": {
"category": "travel",
"moji": "🗼",
"description": "tokyo tower",
"unicodeVersion": "6.0",
- "digest": "73eaf6fd59d16396673afef620c6d928857d5cf616e95a40eaf2861686e0956a"
+ "digest": "e012cdbb4648219ccee443cc09fa2946b99dadb483aeca5a3fdee39270dd3061"
},
"tomato": {
"category": "food",
"moji": "ðŸ…",
"description": "tomato",
"unicodeVersion": "6.0",
- "digest": "d092d8ad381d542e59b6a82b4f1ef0d10fc1ed48460952375c6c5c6258cea111"
+ "digest": "9fc42d1837bf67d7845f2a00c83c6b8001f96b6bb350f009063d211b20e96c16"
},
"tone1": {
"category": "modifier",
"moji": "ðŸ»",
"description": "emoji modifier Fitzpatrick type-1-2",
"unicodeVersion": "8.0",
- "digest": "5c62003a098b774c068be45d658db3c0dd38483c0871f7c8ae293bc1222c4f0c"
+ "digest": "545d866024aa7d4de2e2254420a9d8cca667534672d9e7122bd3e67cf81b694b"
},
"tone2": {
"category": "modifier",
"moji": "ðŸ¼",
"description": "emoji modifier Fitzpatrick type-3",
"unicodeVersion": "8.0",
- "digest": "3c636ecbc4e58c7a360f2338daaf44e7da598fd07e0ba1514bb5c0f83fc8819f"
+ "digest": "c2f93946364e79ed130e3c355416ada791c09d9b3d1bbfa44d03324bfabd642e"
},
"tone3": {
"category": "modifier",
"moji": "ðŸ½",
"description": "emoji modifier Fitzpatrick type-4",
"unicodeVersion": "8.0",
- "digest": "398a1e5441b64c9c2d033bbc01d7a8d90b4db30ea9f30e28f0a9120c72a48df8"
+ "digest": "ea55f80c25ec5df8232d509913b8f5e3260ecc98a2db0f5de333d7e3c9f05bb2"
},
"tone4": {
"category": "modifier",
"moji": "ðŸ¾",
"description": "emoji modifier Fitzpatrick type-5",
"unicodeVersion": "8.0",
- "digest": "ff4a12195aeb7494c785b81266efad8cd60c8022c407a0fc032a02e8b83216b3"
+ "digest": "676bd7f45026066bb72a6b5344e288c6b42ce9524eb0065d50d3354cc716cc6a"
},
"tone5": {
"category": "modifier",
"moji": "ðŸ¿",
"description": "emoji modifier Fitzpatrick type-6",
"unicodeVersion": "8.0",
- "digest": "9e9f0125b5d57011b7456c84719e6be6cf71d06c1b198081d0937c0979164a81"
+ "digest": "b9ab9e2f6307e2e5b8e0560d6b3048f2d0cd58e11c90b03d90688b91fdb4b5f8"
},
"tongue": {
"category": "people",
"moji": "👅",
"description": "tongue",
"unicodeVersion": "6.0",
- "digest": "286e9d2583c371431d6fc979dd4ab48981676da26baada51a846657a3654c19b"
+ "digest": "da75f4b8859b698b941cd091e1d3bf4be3c4e86bb72b2407b9d7b9abe063ed84"
},
"tools": {
"category": "objects",
"moji": "🛠",
"description": "hammer and wrench",
"unicodeVersion": "7.0",
- "digest": "bf08d60dedc06de73d04dab05703bb8ad81989c72b5035d1a07821e51096f158"
+ "digest": "f74b73f7a143d6e5a4efe0b293d998d7dfb681b23f0d6764137c6d9373a28374"
},
"top": {
"category": "symbols",
"moji": "ðŸ”",
"description": "top with upwards arrow above",
"unicodeVersion": "6.0",
- "digest": "c9a9f25b17db014e76b6be54aa07ef89bb18f8adb41b3199d180a559ff1d9ea5"
+ "digest": "69250cda059411b279e6503ff1afac1188b2507d861db7efc956d7758468aa01"
},
"tophat": {
"category": "people",
"moji": "🎩",
"description": "top hat",
"unicodeVersion": "6.0",
- "digest": "43a45dfb5d6b57a63a0491f4e3ec780774c0301b53ed39a303a0bd803d16ed71"
+ "digest": "dff54bdac5a4d1df8e406a5dfa517c5ea60f9ebb6952f27b2780878478c4c8dc"
},
"track_next": {
"category": "symbols",
"moji": "â­",
"description": "black right-pointing double triangle with vertical bar",
"unicodeVersion": "6.0",
- "digest": "88592ef6c720a32aeb752322fb4c794bf5110a72408e21e898630452115c731c"
+ "digest": "adc496351d784f266e6addac74e29d328d24f3e6d3f4a2f1270e88de00f48116"
},
"track_previous": {
"category": "symbols",
"moji": "â®",
"description": "black left-pointing double triangle with vertical bar",
"unicodeVersion": "6.0",
- "digest": "98c1b3d643768d94857fb762f6d26cfb87282b449a67792242e8b7068643ac87"
+ "digest": "aaa9c3c003a2839067dde8aab59c2887532b8f00d00726baa33c995b21b06dcc"
},
"trackball": {
"category": "objects",
"moji": "🖲",
"description": "trackball",
"unicodeVersion": "7.0",
- "digest": "32a819a3129429f797ad434d0c40e263dc236808e34878c599ed2304b43702f5"
+ "digest": "80003d0b886adf81afc07427b73b6ba462032c9fad318d1dcc142eae6e943238"
},
"tractor": {
"category": "travel",
"moji": "🚜",
"description": "tractor",
"unicodeVersion": "6.0",
- "digest": "5e4686290f1a4c9953ae208340b7d276f25b3b2197a43e52469aeb6450e93997"
+ "digest": "0bec7945ef52027a634bfbe75b71902e31c03a8d91814f3c37c2d1dbfa21de10"
},
"traffic_light": {
"category": "travel",
"moji": "🚥",
"description": "horizontal traffic light",
"unicodeVersion": "6.0",
- "digest": "d96aacade33d1ad3e0414f8a920513010f36eb7e5889774251c1d91148917ead"
+ "digest": "7ba4ce5e0bab82e8a78afb05e7705c1dfcaebba6bce6eec0dae63fd62896cd38"
},
"train": {
"category": "travel",
"moji": "🚋",
"description": "Tram Car",
"unicodeVersion": "6.0",
- "digest": "7423d17e131df7aadaa350b5d39dcbce3b28de331ff8b6703a3b2d0093963f4b"
+ "digest": "2b991f1b04ea9a364de103d751d4e3ca7d263b29e169517cf0b6bc098c0544fd"
},
"train2": {
"category": "travel",
"moji": "🚆",
"description": "train",
"unicodeVersion": "6.0",
- "digest": "06e65d549e771632f3c64287a38ba67236f9800ccb6a23c3b592bc010e24e122"
+ "digest": "4809681fd588ad64f82483ecb825bb16ff387e31f45e5fc5637f0c2547acd42f"
},
"tram": {
"category": "travel",
"moji": "🚊",
"description": "tram",
"unicodeVersion": "6.0",
- "digest": "21a7699f1a94f06dcb4d1e896448b98a4205f8efe902a8ac169a5005d11ab100"
+ "digest": "ab9d03c841a0ef60218aae50fe2b2e0ee045052b8b8f73c001c4203199209ba0"
},
"triangular_flag_on_post": {
"category": "objects",
"moji": "🚩",
"description": "triangular flag on post",
"unicodeVersion": "6.0",
- "digest": "1f5ce3828a42f5b1717bac1521d0502cf7081ad9f15e8ed292c1a65f0d1386da"
+ "digest": "135c571161ba6bd55d4940366202164a6c4c325064a7ebc76fbdb3f92428fd73"
},
"triangular_ruler": {
"category": "objects",
"moji": "ðŸ“",
"description": "triangular ruler",
"unicodeVersion": "6.0",
- "digest": "a0367dcf663ec934f1fc7c88bfaccc02b229a896f60930a66bb02241c933e501"
+ "digest": "8db7d5546f2c1403a5dbcd87216d15c9ded1c137def938f6cff3e14282b3b659"
},
"trident": {
"category": "symbols",
"moji": "🔱",
"description": "trident emblem",
"unicodeVersion": "6.0",
- "digest": "ee45920845d3b35c2e45b934cf30ce97bfe2f24c5d72ef1ac6e0842e52b50fc1"
+ "digest": "c9fcbc5e98ed51cd228a1b0eedde2851624c3a7fc354abab9efd96eaa52dcb52"
},
"triumph": {
"category": "people",
"moji": "😤",
"description": "face with look of triumph",
"unicodeVersion": "6.0",
- "digest": "4aa44b8e1682c1269624a359f4b0bf613553683b883d947561ab169d7f85da0f"
+ "digest": "b258f96aa69a0c5bbe672097bb58d0b7bd6c1dfcc93e66f73d632c2a42c9ecc4"
},
"trolleybus": {
"category": "travel",
"moji": "🚎",
"description": "trolleybus",
"unicodeVersion": "6.0",
- "digest": "f610b4fd1123f06778a8e3bb8f738d5b0079aeb0b0926b6a63268c0dd0ee03ed"
+ "digest": "587261051e9e8a6c1354406c62830d8895eaa83b1d9dc6df7516a835788805ec"
},
"trophy": {
"category": "activity",
"moji": "ðŸ†",
"description": "trophy",
"unicodeVersion": "6.0",
- "digest": "50cfbedac18bf0fa5dec727643e15ec47f64068944b536e97518ee3be4f08006"
+ "digest": "33ba0ae0619cb3c2cfa350a36e535601d327b7a0cb7371f2686790336559f912"
},
"tropical_drink": {
"category": "food",
"moji": "ðŸ¹",
"description": "tropical drink",
"unicodeVersion": "6.0",
- "digest": "54144fce60d650f426b1edf09e47c70b2762222398c1fe40231881f074603a69"
+ "digest": "085a51de7c6df9e8734450b0b7b30577c3afaed56cf02f6a481808c2d90a0c13"
},
"tropical_fish": {
"category": "nature",
"moji": "ðŸ ",
"description": "tropical fish",
"unicodeVersion": "6.0",
- "digest": "fd92100aaa9328da35e6090388824921b9726b474d1432a926d2cf9c45ad6528"
+ "digest": "26974903529bbda281c4f1302d8ced6eeca6f3d316ef0bd4ab6617062bd10ca9"
},
"truck": {
"category": "travel",
"moji": "🚚",
"description": "delivery truck",
"unicodeVersion": "6.0",
- "digest": "0d1571e58e900abc453df0ff683fe7acb5906ecbdd52ab35b7101074359faf18"
+ "digest": "c58cdc9790438031e3acd58bd224b83428a6e89be5cec3af01233d257d7b54a6"
},
"trumpet": {
"category": "activity",
"moji": "🎺",
"description": "trumpet",
"unicodeVersion": "6.0",
- "digest": "cea3614c309f5573f328f4603120dbe930016a35f0dfa400b0d968fe9fff2d55"
+ "digest": "21803bcdcfd7681ce77b8fdd30b115a4f67fb8f2cb91908ac9eb02613c413719"
},
"tulip": {
"category": "nature",
"moji": "🌷",
"description": "tulip",
"unicodeVersion": "6.0",
- "digest": "e744e8dbbdc6b126bd5b15aad56b524191de5a604189f4ab6d96730dfef4d086"
+ "digest": "78b7615137fedb534bb1a760b1c7bfdd09b60e1c770ba21ee9f5a3799aa7c93b"
},
"tumbler_glass": {
"category": "food",
"moji": "🥃",
"description": "tumbler glass",
"unicodeVersion": "9.0",
- "digest": "7a38658274b9ff28836725a1dbfad49b8fa3af5ec8385e629db6bfdc7d93907a"
+ "digest": "41ca844a7ae31e28bac5320298ff16c2adf9124b9a649ce5112e47ddce42ab06"
},
"turkey": {
"category": "nature",
"moji": "🦃",
"description": "turkey",
"unicodeVersion": "8.0",
- "digest": "bf5daef15716b66636a5fdb6d059420521443c0603e2d56bd7c99c791a7285f4"
+ "digest": "2b141b75a1df1c8e347fe96a5193060d6feb230e4ced5976e3a22ab4a145887b"
},
"turtle": {
"category": "nature",
"moji": "ðŸ¢",
"description": "turtle",
"unicodeVersion": "6.0",
- "digest": "588c35fb42c9502a908e9805517d4cc8c4ba4e74c9beed4035779fea1efe14f8"
+ "digest": "cb9ebbbd5c861943b8e52ad447959cb489edcb64c93a878a2db00060220e56da"
},
"tv": {
"category": "objects",
"moji": "📺",
"description": "television",
"unicodeVersion": "6.0",
- "digest": "1279f3f3955a58dbbf74e248fc914b0bdba9c4c6b6a5176e9d12bf2750ecfeb4"
+ "digest": "86ab2eef07bed93f56e29e20ef67d566ec7b4b1e96463ba3f9614a1db28aec11"
},
"twisted_rightwards_arrows": {
"category": "symbols",
"moji": "🔀",
"description": "twisted rightwards arrows",
"unicodeVersion": "6.0",
- "digest": "fed07eebc2cf0d977ca0826bbd80defafbbcf118508444148f47b58949ebe27c"
+ "digest": "f559a51e80d26d7bb196ea380936ff60c4a281c3943cf6e86aaebeacce8d957f"
},
"two": {
"category": "symbols",
"moji": "2ï¸âƒ£",
"description": "keycap digit two",
"unicodeVersion": "3.0",
- "digest": "b346f51f6523b02ebcbd753256804e2f9cc1574c96aa634362bf9401dac2c661"
+ "digest": "d091a45f6754587ac8602259955a5d2d1e41d090a1da1c81e46f286ab3de1385"
},
"two_hearts": {
"category": "symbols",
"moji": "💕",
"description": "two hearts",
"unicodeVersion": "6.0",
- "digest": "6ded120a59aed790b441ec8fbbdea6f5cbfb4fa48e9e4b224cc29c9fde2d2e4c"
+ "digest": "52fba958d8153422ae667827dd2dd44a58bf36ac3f7d3d9433527b6a92b7e6e7"
},
"two_men_holding_hands": {
"category": "people",
"moji": "👬",
"description": "two men holding hands",
"unicodeVersion": "6.0",
- "digest": "bfcf9e20a67d00262cdf6e85f1acd545dda91f2e370d68bfd41ce02f232a2987"
+ "digest": "8953ff520ff541f4ee8001ef4dfc22462b6ebf15f2e1adf9ba46d0c6384a0091"
},
"two_women_holding_hands": {
"category": "people",
"moji": "👭",
"description": "two women holding hands",
"unicodeVersion": "6.0",
- "digest": "9d9d2b37a7f8e16fde1468dd8b5645003ea81ae4bf8bcf68471e2381845dd0dd"
+ "digest": "4a6dc2a4b900084faa7b934300b1f07717e41971a9eb9d7830cec83a78c14e46"
},
"u5272": {
"category": "symbols",
"moji": "🈹",
"description": "squared cjk unified ideograph-5272",
"unicodeVersion": "6.0",
- "digest": "01e6cb8f74ea3c19fdade59c2d13d158b90dc6b4b293421b2014b7478bf20870"
+ "digest": "146800348d2954ab707184573fd7a5be20971d6df655f37829f88a8678d4f54b"
},
"u5408": {
"category": "symbols",
"moji": "🈴",
"description": "squared cjk unified ideograph-5408",
"unicodeVersion": "6.0",
- "digest": "084cdbd5436670ea4dc22010e269c1ab7b0432897b8675301e69120374bcdd14"
+ "digest": "c65c6b24648ec959bb497872003adf9f29db19f3bc3ffc5f3c6d03ec36f7e7ed"
},
"u55b6": {
"category": "symbols",
"moji": "🈺",
"description": "squared cjk unified ideograph-55b6",
"unicodeVersion": "6.0",
- "digest": "c1017023d20d4aae78d59342dd3bfc5282716ea0601d9a8c2476335cbf7a2e12"
+ "digest": "0c441fbe4e8527c04c44a297150b2c3dab5f5ba51acffd1adc3109057ec20522"
},
"u6307": {
"category": "symbols",
"moji": "🈯",
"description": "squared cjk unified ideograph-6307",
"unicodeVersion": "5.2",
- "digest": "f459b092b974f459db1fb9cc13617a448b2e4f2b4dc46cc316d8c46af6e7d8bd"
+ "digest": "6ecd33c04af54469548189adc89a12ea3677b7d76af6349221bab3ac17c51011"
},
"u6708": {
"category": "symbols",
"moji": "🈷",
"description": "squared cjk unified ideograph-6708",
"unicodeVersion": "6.0",
- "digest": "928815abf5b30f92efe5168de0c7e6cf8c17899a03e358ab42f42667e0a4a04c"
+ "digest": "de0a0568e1a0de7653dac4dd093ee95027087b301d914752bafbda4648724847"
},
"u6709": {
"category": "symbols",
"moji": "🈶",
"description": "squared cjk unified ideograph-6709",
"unicodeVersion": "6.0",
- "digest": "f63a48ee06c892d24acec8b5634c021658d2ebde67a42d8faa86f27804a9f26d"
+ "digest": "5370fc51eed9c35a7a695881cdb3218b2fda9d70b1a887a5f2dcd7bdd0f5f3bc"
},
"u6e80": {
"category": "symbols",
"moji": "🈵",
"description": "squared cjk unified ideograph-6e80",
"unicodeVersion": "6.0",
- "digest": "489181d90a5e43068459530673a153e4af04fdad8514ec341ff7afbcfd366c3b"
+ "digest": "cc9fbe7d7a29f3d309e0c7dedacf3b19afb4f0689aebcb0ffbdf06febd961842"
},
"u7121": {
"category": "symbols",
"moji": "🈚",
"description": "squared cjk unified ideograph-7121",
"unicodeVersion": "5.2",
- "digest": "9c50fd2ba14221affd2dcd3746322c2137dd75458493f4d385b544eb5bd8d6cd"
+ "digest": "3df28fb3345962cc97b32391bcb9dfd1df82bfadf1dc3567122fd086aff59cb3"
},
"u7533": {
"category": "symbols",
"moji": "🈸",
"description": "squared cjk unified ideograph-7533",
"unicodeVersion": "6.0",
- "digest": "2b05819b380a2ea47cc5fde8fcce3d53922fd223d6f5bd83d696d44175b69f18"
+ "digest": "014087496357083b2fa0f6372f3c768c9d0cde6f290460c8b4ecfa322955a065"
},
"u7981": {
"category": "symbols",
"moji": "🈲",
"description": "squared cjk unified ideograph-7981",
"unicodeVersion": "6.0",
- "digest": "adbe12601b22972003ddebcb0bd1532b979aa9c78bfdc147511854b5014eabc0"
+ "digest": "e61e1ed43e0aa5747ad99050d48550ac23a8c6bfa7de7114b03a17eb0366872a"
},
"u7a7a": {
"category": "symbols",
"moji": "🈳",
"description": "squared cjk unified ideograph-7a7a",
"unicodeVersion": "6.0",
- "digest": "b9ee0ec7bb0b86c3eb73d4dbbb91848c427bf356ae30a263b9b44bd9bd784482"
+ "digest": "d306d00de7a978823adf885d3beb23c41359a2bb804425b8652f59f5ceadd40d"
},
"umbrella": {
"category": "nature",
"moji": "☔",
"description": "umbrella with rain drops",
"unicodeVersion": "4.0",
- "digest": "0328a2f48b7df47905e2655460e524c0794ef12d3d7c32a049a10892d5662f77"
+ "digest": "99c2f2a4331ff3f17192394ce766808e725e0701cf903cea606efb5f1d4b3f4a"
},
"umbrella2": {
"category": "nature",
"moji": "☂",
"description": "umbrella",
"unicodeVersion": "1.1",
- "digest": "2f6a58110dc590480a822a3ffa2b5bc86f295e0c994a4a632837d25d4cf9fc58"
+ "digest": "c8e5f34916627bd8053727b3ae40c5fb1df6bad76049e925696140825b413af4"
},
"unamused": {
"category": "people",
"moji": "😒",
"description": "unamused face",
"unicodeVersion": "6.0",
- "digest": "0d597088e3e7880918d0166e5c69243b18fe64afa31685c39bfdbc71494aa132"
+ "digest": "68eaad1164a9cfdcfb28e6e247ab733d0698a4ddd8f9c72add082d28d3a74445"
},
"underage": {
"category": "symbols",
"moji": "🔞",
"description": "no one under eighteen symbol",
"unicodeVersion": "6.0",
- "digest": "b6b194614ca714ac2b1c2c17b75fe5922c7fdadb3d1157ba89ab2a5d03494a67"
+ "digest": "afdd3883748acb01bb18bfe034c39b4510957c7bfbdb9cec33b4e6b4a0068089"
},
"unicorn": {
"category": "nature",
"moji": "🦄",
"description": "unicorn face",
"unicodeVersion": "8.0",
- "digest": "f71bb485a7c208e999dd45f2b36d7b7d517898c0627947926b05aa28603804ca"
+ "digest": "00d784632f584c953340b1f1474be2a1ab6f065625e69e2d06dabd38ab45531c"
},
"unlock": {
"category": "objects",
"moji": "🔓",
"description": "open lock",
"unicodeVersion": "6.0",
- "digest": "9554ef3a6a315938b873e77970d9b0212e61f13c6cc36e4f17f87acc930a9a53"
+ "digest": "129328bd903055394ded6f0427d24c8f4ffc1a8ccb0cc831d1343b5c6c8d4416"
},
"up": {
"category": "symbols",
"moji": "🆙",
"description": "squared up with exclamation mark",
"unicodeVersion": "6.0",
- "digest": "ff2554ccf08c7208b38794c5fa3d9a93a46ff191a49401195d8f740846121906"
+ "digest": "807046ea55d94a542e355a6cf9c6bab5fe8523513669211ab1c13765348ff41a"
},
"upside_down": {
"category": "people",
"moji": "🙃",
"description": "upside-down face",
"unicodeVersion": "8.0",
- "digest": "5129121f0a28f5b334268c28565de26a5907559568deca11de6ec620b097dfe1"
+ "digest": "3211b742f7fefdca6b0e817fb45070d6a306e3d31debcfd11d006ea24ba08983"
},
"urn": {
"category": "objects",
"moji": "âš±",
"description": "funeral urn",
"unicodeVersion": "4.1",
- "digest": "9bebf589eed8dd361f6a03cd1b325078f2cd0e82270ef63a7dd1b6aee08cd1e6"
+ "digest": "0730518fad9fab0d5070432a6e771d6526349fb075ed9e42b046b88464b0f13c"
},
"v": {
"category": "people",
"moji": "✌",
"description": "victory hand",
"unicodeVersion": "1.1",
- "digest": "9825bf440df289a8edf8ede494e8c778dc63c95f967f4d7bbea3245cf4f558ec"
+ "digest": "cf0a1553b56d27c678ee71819933807339d0134eb71119aecc0c185bcd922996"
},
"v_tone1": {
"category": "people",
"moji": "✌ðŸ»",
"description": "victory hand tone 1",
"unicodeVersion": "8.0",
- "digest": "76e358250d9ca519b60b8d7b6a32900700d784433dcc609e9442254a410f6e37"
+ "digest": "1d4b156f48968318917284d695cf72f56f2ad8d2ed318f3886fa1eca5a27439f"
},
"v_tone2": {
"category": "people",
"moji": "✌ðŸ¼",
"description": "victory hand tone 2",
"unicodeVersion": "8.0",
- "digest": "4081b674be8416136022523fa9f29ec70a0f7e3aa05ca13152606609f3fd003c"
+ "digest": "6d842f89c4fe8d344d7748b4de74733a7b680566589556e542f808b28de8c12a"
},
"v_tone3": {
"category": "people",
"moji": "✌ðŸ½",
"description": "victory hand tone 3",
"unicodeVersion": "8.0",
- "digest": "b6afb3a4c78384280610b953592d378241c75597a82aa6d16c86a993f8d8f3b0"
+ "digest": "0125d0d20a51b11716399dcb0e0b81220a1fe755ea7a2e2fed22c5688516ae52"
},
"v_tone4": {
"category": "people",
"moji": "✌ðŸ¾",
"description": "victory hand tone 4",
"unicodeVersion": "8.0",
- "digest": "7ddc3cdd0138da2c8d7f6d8257ffdb8801496043e8a2395f93b0663447ac7fce"
+ "digest": "10502f0b7ce2aaaf9e9823f74f7cbe88503ec5bd614218b75c8f277b8a280328"
},
"v_tone5": {
"category": "people",
"moji": "✌ðŸ¿",
"description": "victory hand tone 5",
"unicodeVersion": "8.0",
- "digest": "a85dc5c589f0d1cf32f8bfa5c82e5c11c40b35439636914686a2f06f7359f539"
+ "digest": "1ea229068485d71074f7b6c782c6d275d7ff0a039f8c4ace5ba2700ee94315c4"
},
"vertical_traffic_light": {
"category": "travel",
"moji": "🚦",
"description": "vertical traffic light",
"unicodeVersion": "6.0",
- "digest": "8cfd49a8f96b15a8313ef855f2e234ea3fa58332e68896dea34760740de9f020"
+ "digest": "ff094eb787c114159f19f263994531db073cd9b3bd98c55fe4913bfa9bda53ec"
},
"vhs": {
"category": "objects",
"moji": "📼",
"description": "videocassette",
"unicodeVersion": "6.0",
- "digest": "3fb1acaf25805cf86f8d40ee2c17cf25da587b7ca93b931167ab43fce041eee8"
+ "digest": "7fbd915d2b660e32fc5720179a113deea2997601f8dc0f7dcf4ec754f4d8d17b"
},
"vibration_mode": {
"category": "symbols",
"moji": "📳",
"description": "vibration mode",
"unicodeVersion": "6.0",
- "digest": "c9a8899222f46fe51dd8cee3e59f77c48268f0b7cfae2bcb34a791213acb1755"
+ "digest": "15ef296e1ef2747dfc47d8999ff7bbcca42a2ea682d57e224064335d9fa1c84e"
},
"video_camera": {
"category": "objects",
"moji": "📹",
"description": "video camera",
"unicodeVersion": "6.0",
- "digest": "62e56f26c286a7964ef1021f0f23fcb4b38cdcfb5b5af569b472340c412c619a"
+ "digest": "b297b7675c9e69638a29f5332a4024fd68675101d03a059d90f151534de1a3b5"
},
"video_game": {
"category": "activity",
"moji": "🎮",
"description": "video game",
"unicodeVersion": "6.0",
- "digest": "2787e302aa9e6fd7e9dc382c9bc7f5fbf244ef4940e08a4f9e80d33324f3032e"
+ "digest": "95a218fcb12095024a77ee4826d0574190b5ebb8878d0fba7a640dcbeb3b78ba"
},
"violin": {
"category": "activity",
"moji": "🎻",
"description": "violin",
"unicodeVersion": "6.0",
- "digest": "1e69d531ce2b5d5bf1dd9470187dbbe76f479d14428834b6a9e2bf5296dc0ec9"
+ "digest": "3adf18cfe5778c508be936827ff1812503e02b8ebaf3db45053f0fab962cca39"
},
"virgo": {
"category": "symbols",
"moji": "â™",
"description": "virgo",
"unicodeVersion": "1.1",
- "digest": "0f75e9c228bc467fd0cec0f93f0e087c943bc5fb1d945fb0d4de53d07718388e"
+ "digest": "2cae076c31fe134ca69caef07db75283f72c99f8fd746b1c1fff6a897f613655"
},
"volcano": {
"category": "travel",
"moji": "🌋",
"description": "volcano",
"unicodeVersion": "6.0",
- "digest": "41c92ef88ca533df342a0ebe59d2b676873bfa944c3988495b8a96060a9b8e16"
+ "digest": "75b53e25406d31b630fd1bb75c363044129f481f24f7d225a6d30eef5257f92c"
},
"volleyball": {
"category": "activity",
"moji": "ðŸ",
"description": "volleyball",
"unicodeVersion": "8.0",
- "digest": "774a83357f7aee890b4d4383236f0a90946dbd7c86aaabadc5753dcc9b4c9d69"
+ "digest": "a9dc3a3516d1e22aededc7198fdf3a4f304b7c2f7fa528806c2e0bdfe320d007"
},
"vs": {
"category": "symbols",
"moji": "🆚",
"description": "squared vs",
"unicodeVersion": "6.0",
- "digest": "ac943e4c737459c2e1adbac8b71d3fdaebb704dbaf5713012e7a77beb09db1ef"
+ "digest": "1e67a891ce028db2e6fb8506879d3c0edbf024012a75a5073e89aa834c6f314e"
},
"vulcan": {
"category": "people",
"moji": "🖖",
"description": "raised hand with part between middle and ring fingers",
"unicodeVersion": "7.0",
- "digest": "b4d409a0b019e7b06333cefd15ea46cb54aef5132d86e8ba361c1c3b911fe265"
+ "digest": "829687cca319f7293457db7d49b7eb236c681def71b96711556534c6d9123279"
},
"vulcan_tone1": {
"category": "people",
"moji": "🖖ðŸ»",
"description": "raised hand with part between middle and ring fingers tone 1",
"unicodeVersion": "8.0",
- "digest": "cc6072c85031b5081995f98a57f09ab177168318f69a51f3acc63251760499a4"
+ "digest": "993550c5e6d01f173ce710e8d721474f21359f706cff863f913db3e31212ab56"
},
"vulcan_tone2": {
"category": "people",
"moji": "🖖ðŸ¼",
"description": "raised hand with part between middle and ring fingers tone 2",
"unicodeVersion": "8.0",
- "digest": "858bd5a1ac91dc4d7735f57ba4dd69d39138aa6dac1c80cfc05de30a59a5bc33"
+ "digest": "fad2b5ba5fef661214bee2d43a93d2cedb9024d1ba6d1f0369e76e8167926156"
},
"vulcan_tone3": {
"category": "people",
"moji": "🖖ðŸ½",
"description": "raised hand with part between middle and ring fingers tone 3",
"unicodeVersion": "8.0",
- "digest": "2f74b6f3eab2a75063591b66f1c7350af0d23153e1427af91de20c48a5f4a54a"
+ "digest": "344f09198268734de3a4f300b410a65c6a35d2ff958e7b675329e5ddffd1dd3f"
},
"vulcan_tone4": {
"category": "people",
"moji": "🖖ðŸ¾",
"description": "raised hand with part between middle and ring fingers tone 4",
"unicodeVersion": "8.0",
- "digest": "87cf8b87d3610f742857a9704b658462df32b4924d8f1ddba26f761e738c4e11"
+ "digest": "92f84231b71044b20d6132617fd1d2553472d3402175d85a42e24a3e5b40316d"
},
"vulcan_tone5": {
"category": "people",
"moji": "🖖ðŸ¿",
"description": "raised hand with part between middle and ring fingers tone 5",
"unicodeVersion": "8.0",
- "digest": "11e9ff62f2385edeb477dbf66c63734536531def5771daf80b66a3425ac71493"
+ "digest": "ab3aec60fd46b425d0ff4bed7e96f25007b6943e6e46b1754e695ef5e289c7a5"
},
"walking": {
"category": "people",
"moji": "🚶",
"description": "pedestrian",
"unicodeVersion": "6.0",
- "digest": "ae77471fe1e8a734d11711cdb589f64347c35d6ee2fc10f6db16ac550c0557fa"
+ "digest": "595b89b7ed1359e120f4aeeaccc8dbce01fc96358ce6b9501b6f4ab6559428f4"
},
"walking_tone1": {
"category": "people",
"moji": "🚶ðŸ»",
"description": "pedestrian tone 1",
"unicodeVersion": "8.0",
- "digest": "3de871c234e1340ccf95338df7babd94d175cfcb17a57b5a74d950e0a31f03b1"
+ "digest": "794562b94ed8c825c4facad1b3d8fca0c90f49582209cc0f0923e33d2d5a083d"
},
"walking_tone2": {
"category": "people",
"moji": "🚶ðŸ¼",
"description": "pedestrian tone 2",
"unicodeVersion": "8.0",
- "digest": "620eb7bfb753a331a5822b02bdaf08d8dde7b573efd210287a3d3dfdd84a40b9"
+ "digest": "3fc7452b3b324a3a9f7a34faa82175865681248094f13ea7977ee1eb64e6e201"
},
"walking_tone3": {
"category": "people",
"moji": "🚶ðŸ½",
"description": "pedestrian tone 3",
"unicodeVersion": "8.0",
- "digest": "ff39545acc2256006128f8c186433c28052b8c9aaec46fe06f25cff02c71f6b8"
+ "digest": "b9200fae09036c6919e8a348b51a2fe09e2e2909120077000dcba0fd62fb9fa5"
},
"walking_tone4": {
"category": "people",
"moji": "🚶ðŸ¾",
"description": "pedestrian tone 4",
"unicodeVersion": "8.0",
- "digest": "a9499d142392977a9b9e54fb957952359e9bdffce7ec2f1e8320523d185fb066"
+ "digest": "c1dbd3327bed96613834dd05dbf43bd233f5d4ab96b1c6f42684ecc690d62fa7"
},
"walking_tone5": {
"category": "people",
"moji": "🚶ðŸ¿",
"description": "pedestrian tone 5",
"unicodeVersion": "8.0",
- "digest": "b47a4c48ce40298f842f454fc1abccae70f69725d73ee2c80e4018f4c4065d7d"
+ "digest": "60e0ceb95d5c555835dda6b1fa368938f50e2ee6ccbda723f2ad9c511fd9d16b"
},
"waning_crescent_moon": {
"category": "nature",
"moji": "🌘",
"description": "waning crescent moon symbol",
"unicodeVersion": "6.0",
- "digest": "2ec7896eefcf821e0ea013556a17af59e997503662c07f080d0a84ab13ef4cf1"
+ "digest": "5790b3f1f581dd7e5480978f31a8c2ed67bca238a2f26eb6f415a2dc3b6ff7c5"
},
"waning_gibbous_moon": {
"category": "nature",
"moji": "🌖",
"description": "waning gibbous moon symbol",
"unicodeVersion": "6.0",
- "digest": "ce2f5aca8fccdacaaf174d10da4e493e853e4608cc4d159aa3081d108a8b58d5"
+ "digest": "bba224edaa61c1f00f4ea0679ebb96e15090c2948463bc7414734fd13307a3cc"
},
"warning": {
"category": "symbols",
"moji": "âš ",
"description": "warning sign",
"unicodeVersion": "4.0",
- "digest": "745f1d203958f42bf37ecb5909cd0819934e300308ba0ff20964c8c203092f90"
+ "digest": "1d6cf2ec8990304aaca53a2eecd878c17e4eb8685c48d3be59c8f0a1cfb66202"
},
"wastebasket": {
"category": "objects",
"moji": "🗑",
"description": "wastebasket",
"unicodeVersion": "7.0",
- "digest": "221a1b6d9975051038d9d97e18a16556cdf4254a6bca4c29bf1c51f306c79f2a"
+ "digest": "2a099e1431b96a2de10f79ddb319a1bcdc74d5bd7d05dee9a27b67274e4d86b0"
},
"watch": {
"category": "objects",
"moji": "⌚",
"description": "watch",
"unicodeVersion": "1.1",
- "digest": "acc0c96751404a789b3085f10425cf34f942185215df459515d2439cde3efc6b"
+ "digest": "1e540e8c6856ebfab897c71132525d2f3a1a51513d86423b862116515489f55b"
},
"water_buffalo": {
"category": "nature",
"moji": "ðŸƒ",
"description": "water buffalo",
"unicodeVersion": "6.0",
- "digest": "ba6a840d4f57f8f9f3e9f29b8a030faf02a3a3d912e3e31b067616b2ac48a3d1"
+ "digest": "dd9f6609e0ea97f610ab30e34c6564fe1504a54e2bd258fa64601cdbc91de177"
},
"water_polo": {
"category": "activity",
"moji": "🤽",
"description": "water polo",
"unicodeVersion": "9.0",
- "digest": "fc77e1d2a84a9f4cf0cf19c1ea10cf137cf0940b9103a523121eda87677ad148"
+ "digest": "b1ddaec4c4a506a89462a8d72173e44e0766c27e936e41d894de7ffc3da48236"
},
"water_polo_tone1": {
"category": "activity",
"moji": "🤽ðŸ»",
"description": "water polo tone 1",
"unicodeVersion": "9.0",
- "digest": "3be28384edd29ada8109f07720d601a9d5866ed63e6234efe9ee1a194ed5d0c5"
+ "digest": "a86b73dac5b378283ca59e0985b98524c813aa34bc08e0c3bb5e0279a572adbf"
},
"water_polo_tone2": {
"category": "activity",
"moji": "🤽ðŸ¼",
"description": "water polo tone 2",
"unicodeVersion": "9.0",
- "digest": "afcd3f28c6719f869ca79a6fd1ccade2ea976ade844fbc1081fc72865bcb652f"
+ "digest": "080f98b0afbc5a6a087ca9774c817717f8bae0bb2ff7d2968eecebeb7ef8fee6"
},
"water_polo_tone3": {
"category": "activity",
"moji": "🤽ðŸ½",
"description": "water polo tone 3",
"unicodeVersion": "9.0",
- "digest": "d19481c9b82d9413e99c2652e020fd763f2b54408dedaffec8dfe80973ded407"
+ "digest": "08a235850af9851f27148f53bd3e6f29668ce5d37afaaab0226a59195139e41c"
},
"water_polo_tone4": {
"category": "activity",
"moji": "🤽ðŸ¾",
"description": "water polo tone 4",
"unicodeVersion": "9.0",
- "digest": "375972d882b627e8d525e632e58b30346fc3e01858d7d08d62a9d3bf8132bbc7"
+ "digest": "7e69265f86e139af75bc1d1bea03c21b7f2cc445e4b7a767b0515ffa7be1a99c"
},
"water_polo_tone5": {
"category": "activity",
"moji": "🤽ðŸ¿",
"description": "water polo tone 5",
"unicodeVersion": "9.0",
- "digest": "a8e1ced1c5382a8147a1d1801a133cada9a0e52e41de6272e56c3c1f426f6048"
+ "digest": "db363a1e0a5f9b9d807258799d12e0a9010c99c383a4382f0f9a99feff2fd683"
},
"watermelon": {
"category": "food",
"moji": "ðŸ‰",
"description": "watermelon",
"unicodeVersion": "6.0",
- "digest": "42a3821d2e4dd595c93f5db7a5c70b7af486b8f0ddd3b9d26bc4e743a88e699a"
+ "digest": "8a18d12c6fb648b5cadc8d3ff390b9e24f5505a649055a2d4c840df7eb6bad78"
},
"wave": {
"category": "people",
"moji": "👋",
"description": "waving hand sign",
"unicodeVersion": "6.0",
- "digest": "cddbd764d471604446cbaca91f77f6c4119d1cfc2c856732ca0eaac4593cb736"
+ "digest": "5b877d50f49e858c453871fc380f0449633870118d487217c0a1f7f9cab02a06"
},
"wave_tone1": {
"category": "people",
"moji": "👋ðŸ»",
"description": "waving hand sign tone 1",
"unicodeVersion": "8.0",
- "digest": "cf40797437ddf68ec0275f337e6aac4bed81e28da7636d56c9f817ddf8e2b30a"
+ "digest": "d27aa7181be2fab9d0281889496ab100a6a9473d7b1b4b0b4bcaa7523a311706"
},
"wave_tone2": {
"category": "people",
"moji": "👋ðŸ¼",
"description": "waving hand sign tone 2",
"unicodeVersion": "8.0",
- "digest": "12c8a3e82c03ee35a734c642be482ba2d9d5948dacf91ec1fda243316dd4a0d0"
+ "digest": "7656b85268eb3318a0e8f954d334ca585c780da567a9a57ffdf24ecc3758e123"
},
"wave_tone3": {
"category": "people",
"moji": "👋ðŸ½",
"description": "waving hand sign tone 3",
"unicodeVersion": "8.0",
- "digest": "ebcaef43e21b475f76de811d4f4d1a67d9393973b57b03876e02164345a2ba4a"
+ "digest": "002912d69d16d423253db2e90d04164b2a861847dd6eff31f9a28f32e8720c9b"
},
"wave_tone4": {
"category": "people",
"moji": "👋ðŸ¾",
"description": "waving hand sign tone 4",
"unicodeVersion": "8.0",
- "digest": "7df7b70cf76766836ba146c3d91b6104930c384450cf2688426e60c1c06a1fc8"
+ "digest": "8e91cbf4b2eb22caa7c06e816d4083a861882b38cced8c59b5f19f7371114044"
},
"wave_tone5": {
"category": "people",
"moji": "👋ðŸ¿",
"description": "waving hand sign tone 5",
"unicodeVersion": "8.0",
- "digest": "8dfdba6aeff5d7dfd807467d431a137547726b34d021f1a5a0b74e155d270ea7"
+ "digest": "40f696691a3ee439029d7914abe0ccb5efe66bab0ed2c057080991fc878eb0f4"
},
"wavy_dash": {
"category": "symbols",
"moji": "〰",
"description": "wavy dash",
"unicodeVersion": "1.1",
- "digest": "7b1968474f01d12fd09a1f2572282927138d9e9d6a3642de4bf68af80a8c3738"
+ "digest": "d7bcb62068abe4e1c168ba0445c1d3d1b1e76373bbe6f2d84f4d78b38be524c7"
},
"waxing_crescent_moon": {
"category": "nature",
"moji": "🌒",
"description": "waxing crescent moon symbol",
"unicodeVersion": "6.0",
- "digest": "852d7e55a19074d061fa3aa80d6b1e7e87a9280bdf44d94bbdbbe6d59178b1be"
+ "digest": "a3534c77cf0a8da83fc2cef14481983bafc745e35da96231259dc926cd15937d"
},
"waxing_gibbous_moon": {
"category": "nature",
"moji": "🌔",
"description": "waxing gibbous moon symbol",
"unicodeVersion": "6.0",
- "digest": "a3a1c7cc72521a3f74929789a90e1c35d81ac86e21225c9f844d718d8940e3b3"
+ "digest": "46fc534be196723eabfe1a8be62217c1cff70e2ea806ff5bc15e9e09c116d9c1"
},
"wc": {
"category": "symbols",
"moji": "🚾",
"description": "water closet",
"unicodeVersion": "6.0",
- "digest": "4b95d54e0b53e4b705277917653503b32d6a143c2eaf6c547bc8e01c2dc23659"
+ "digest": "a1576f1731a68646c9de74c135674955eee3df8f740437ab9ef04a45a49b282c"
},
"weary": {
"category": "people",
"moji": "😩",
"description": "weary face",
"unicodeVersion": "6.0",
- "digest": "3528f85540996cd5b562efe5421c495fc1bb414dc797bc20062783ae1b730847"
+ "digest": "44fd697167f1403eaf6bc6778a394dee514f900a964bb9e7b6a45aac86a5d985"
},
"wedding": {
"category": "travel",
"moji": "💒",
"description": "wedding",
"unicodeVersion": "6.0",
- "digest": "980f3522cc4c19c3096e668032ea2cd19e7900cdc4b73bbb1c9b4c4d28dc78af"
+ "digest": "bdc97890b2ccd38285d4d9832e700c0cb99cf740305b37eac5cee1bf03137a92"
},
"whale": {
"category": "nature",
"moji": "ðŸ³",
"description": "spouting whale",
"unicodeVersion": "6.0",
- "digest": "6368fe4bc4a7f68aa2bd5386686a5f1b159feacbec16d59515f2b6e5d01adfbd"
+ "digest": "6a5de13dec0e0bbb05c9b3222ce04c16c079367124e59a49d015bbbee7a174a7"
},
"whale2": {
"category": "nature",
"moji": "ðŸ‹",
"description": "whale",
"unicodeVersion": "6.0",
- "digest": "ccd3edf88167965f2abc18631ffb80e2532f728da35bc0c11144376685da18e8"
+ "digest": "939087b5e3b24f0cc27978a8777eec9c38f6e8bafc98200ff2606c3648fa589e"
},
"wheel_of_dharma": {
"category": "symbols",
"moji": "☸",
"description": "wheel of dharma",
"unicodeVersion": "1.1",
- "digest": "4a0a13fcd507b9621686c8090bf340aa8770c064e0e3eb576fbae1229000d6da"
+ "digest": "bdc92990dc2dcde7de136ed934e9f2476dc011257ffbeeb5dc45e1f86e26a067"
},
"wheelchair": {
"category": "symbols",
"moji": "♿",
"description": "wheelchair symbol",
"unicodeVersion": "4.1",
- "digest": "f5250f2b4b5b4ffe6a6f77d30865c3f5d7173fc91aee547869589b2a96da91c8"
+ "digest": "805e8f94922c2214849af36b2de79cb812472cf6c3cf7c55dbf7fe9e11f0380b"
},
"white_check_mark": {
"category": "symbols",
"moji": "✅",
"description": "white heavy check mark",
"unicodeVersion": "6.0",
- "digest": "45eb17bde6e503f22c8579d6e4d507ad6557a15f9eaad14aa716ec9ba1540876"
+ "digest": "6f37f4b2dd017d42bb070d2544dce135a1c11203c5cb537c760b3c90d17bc0c3"
},
"white_circle": {
"category": "symbols",
"moji": "⚪",
"description": "medium white circle",
"unicodeVersion": "4.1",
- "digest": "2e7323fa4d1e3929e529d49210a0b82a043eae4f7c95128ec86b98c46fdb0e7c"
+ "digest": "386429066322ba83e4790d7e930c167a6789f978f65e2131f0534230f196d40a"
},
"white_flower": {
"category": "symbols",
"moji": "💮",
"description": "white flower",
"unicodeVersion": "6.0",
- "digest": "ace093b310eeefdecf4a4bdaf4fbcbb568457b0191ac80778a466ac5f3f4025a"
+ "digest": "30a1761e5672133bf4172bfecad661e951488c89e22ceee88d04fd3bcbd7e6d1"
},
"white_large_square": {
"category": "symbols",
"moji": "⬜",
"description": "white large square",
"unicodeVersion": "5.1",
- "digest": "0db6957ee9ff7325b534b730fc05345a63d4ed9060f0f816807d0dcf004baa3e"
+ "digest": "a56e16d3a7778cfec18b031b9f0f04aa008d3b81a2dc4642366f7d92adc1d862"
},
"white_medium_small_square": {
"category": "symbols",
"moji": "â—½",
"description": "white medium small square",
"unicodeVersion": "3.2",
- "digest": "d79689981a7b38211c60a025a81e44fd39ac6ea4062e227cae3aab8f51572cd4"
+ "digest": "9950d2efd6bca2b2583f670c389f839b5346b9e608eb9b00628b196f9d6b37a3"
},
"white_medium_square": {
"category": "symbols",
"moji": "â—»",
"description": "white medium square",
"unicodeVersion": "3.2",
- "digest": "6c4ce26d3f69667219f29ea18b04f3e79373024426275f25936e09a683e9a4fc"
+ "digest": "0328185858eb63e113136674509fb89f43ab5306449345e2e65d1ee2d616a54d"
},
"white_small_square": {
"category": "symbols",
"moji": "â–«",
"description": "white small square",
"unicodeVersion": "1.1",
- "digest": "ae0d35a6bbba4592b89b2f0f1f2d183efb2f93cf2a2136c0c195aab72f0bb1c8"
+ "digest": "a805e7c1edcf6668a6bdc8324e9ec78da8aa4a79f789f55ce6828337b2f8e43c"
},
"white_square_button": {
"category": "symbols",
"moji": "🔳",
"description": "white square button",
"unicodeVersion": "6.0",
- "digest": "797f3d9e44e88e940ffc118e52d0f709eec2ef14b13bdf873ad4b0c96cc0b042"
+ "digest": "bc65aefa55ddee130c006624bcd381313eba7261c99f8b273a938d273b84570a"
},
"white_sun_cloud": {
"category": "nature",
"moji": "🌥",
"description": "white sun behind cloud",
"unicodeVersion": "7.0",
- "digest": "0e714038bb0a5b091dd4ad8829c5c72dece493e09da6d56ceadcd0b68e1c0fd5"
+ "digest": "78c9ade346888e8758e56107bed5bd0a16b4da60ef591cb71e1c68625feec8c8"
},
"white_sun_rain_cloud": {
"category": "nature",
"moji": "🌦",
"description": "white sun behind cloud with rain",
"unicodeVersion": "7.0",
- "digest": "82fb2a91d43c7c511afed216e12f98e32aef4475e7f3c7ccc0f39732d2f7d5e5"
+ "digest": "7d95f929a5679e52f4c9f93d2fe87d33524e38ab08115cd9a20aa481611f83ab"
},
"white_sun_small_cloud": {
"category": "nature",
"moji": "🌤",
"description": "white sun with small cloud",
"unicodeVersion": "7.0",
- "digest": "0a6164cdadf2413555b7ef47b95f823f5a010f36d2dacfb1a38335a0f59e9601"
+ "digest": "7f6a12cec242c9fd4ece3a014eb12f771b4d5195280783ad771b5110c444c028"
},
"wilted_rose": {
"category": "nature",
"moji": "🥀",
"description": "wilted flower",
"unicodeVersion": "9.0",
- "digest": "2c9e01ab9a61d057c71478b09ba7d82ae08f4a5a1c2212b7ad562b74f616677f"
+ "digest": "401fb35a8c6d26db708b2756c0bb55e0c62490a8cbdd51a21d6634881a62d32c"
},
"wind_blowing_face": {
"category": "nature",
"moji": "🌬",
"description": "wind blowing face",
"unicodeVersion": "7.0",
- "digest": "e4f63149cbc8829118571f6a93487b96d26665fc15d17d578cca4e5c752cd54f"
+ "digest": "acb691375579ce301ce94a0c9f23bebcac90139e2c3cea8aa8c6cb3b581e8ae3"
},
"wind_chime": {
"category": "objects",
"moji": "ðŸŽ",
"description": "wind chime",
"unicodeVersion": "6.0",
- "digest": "1b1b212fbd74a9edc62aee7ffab9bcf91d3a9f69bffb2be4b7fd527914c14ced"
+ "digest": "57b721fd94e359f9a8dcd9fc702a3c9f82b06f4347d5b6e33c9d42117dd26e8a"
},
"wine_glass": {
"category": "food",
"moji": "ðŸ·",
"description": "wine glass",
"unicodeVersion": "6.0",
- "digest": "d99107d6809386bc5e219aa58ee4930d27b7c3a6d2b10deb9f523df369f766d1"
+ "digest": "d7551c39ea933566603e8ccd18c9c116e8d4dd2dca14697f5d6f6c0dc481e05c"
},
"wink": {
"category": "people",
"moji": "😉",
"description": "winking face",
"unicodeVersion": "6.0",
- "digest": "56e29994a47335a901d0c98fa141d26faae8f647a860517bd3615fa980921885"
+ "digest": "a9746d44d7fd9f51c0b0329aeb9eaa438e4690162d6c82c482ec3f4bc2def8b9"
},
"wolf": {
"category": "nature",
"moji": "ðŸº",
"description": "wolf face",
"unicodeVersion": "6.0",
- "digest": "4a983f5ec8ec0872fcde7890e17605b1229064e5e194b6fca1c4259068d1caed"
+ "digest": "f961f617f4b6af5a0b1683132476ce765cb3ce74c3c5c32083593622ff8c10e7"
},
"woman": {
"category": "people",
"moji": "👩",
"description": "woman",
"unicodeVersion": "6.0",
- "digest": "a06a22a48eeb3aeb885321358fe234e97797ed33be17f52d232ce2830cfbcd97"
+ "digest": "7f06a5df2103c959228c15f44a76d39f87f792bef6aaadf7e4f47fe31a0e85fa"
},
"woman_tone1": {
"category": "people",
"moji": "👩ðŸ»",
"description": "woman tone 1",
"unicodeVersion": "8.0",
- "digest": "c2e4b135c1dac6a0b002569a6ccd9d098f6cb18481c68b5d9115e11241a0978d"
+ "digest": "e1e1bc0d9e6c06fc37e54251c9d492c83852016baeb16acfedd7242a0f4a289e"
},
"woman_tone2": {
"category": "people",
"moji": "👩ðŸ¼",
"description": "woman tone 2",
"unicodeVersion": "8.0",
- "digest": "4848e650051214a53c4cd9f6d3d94158f77f65ecb34f891789de34ee0a713006"
+ "digest": "f3e0dd2ee081ca179d8c70e3c5a77254f98880f732cabdf601d54b64ae8702cd"
},
"woman_tone3": {
"category": "people",
"moji": "👩ðŸ½",
"description": "woman tone 3",
"unicodeVersion": "8.0",
- "digest": "b6f751ad47da019cdfb9d6d78f9610adb92120abf204c30df79a9150b57dbdee"
+ "digest": "1ad974a8aad0dc2cb62d22e7c6c155bd07030222c3f115e62c153ce5cb6b240d"
},
"woman_tone4": {
"category": "people",
"moji": "👩ðŸ¾",
"description": "woman tone 4",
"unicodeVersion": "8.0",
- "digest": "fd27d3a669dc34313fbfe518df7dc2ded3ade5dde695f8d773afe87bf8a8b0d4"
+ "digest": "c11d39ec49db3d36256f372521461b9d668726cab6d63166ef23c9c99e3a9c55"
},
"woman_tone5": {
"category": "people",
"moji": "👩ðŸ¿",
"description": "woman tone 5",
"unicodeVersion": "8.0",
- "digest": "9ae9b14dfff40fa60a565d89479727feeba4fd6ffea9acb353a81b14aba751d4"
+ "digest": "7220ffd6a38cf1587f1c45e3461c38f65162b604fb4261318c342bb6f1a4d95f"
},
"womans_clothes": {
"category": "people",
"moji": "👚",
"description": "womans clothes",
"unicodeVersion": "6.0",
- "digest": "d12a27810780fe5cd8118ed4587e0c4e70dbe9bcd014c6866fe6a8c9c7c55698"
+ "digest": "4b47a76b3fa144213583b47c2284eee1e4148b9b4cd578f1d02ddb474c78a3ae"
},
"womans_hat": {
"category": "people",
"moji": "👒",
"description": "womans hat",
"unicodeVersion": "6.0",
- "digest": "52a0255b3483085bd125d39b74516ab6a81003964f44995c2fac821e7ff93086"
+ "digest": "7feded8ca13ddee2d9fd71e97a0e7f719d85f85190a69d6fde985d69e20bc422"
},
"womens": {
"category": "symbols",
"moji": "🚺",
"description": "womens symbol",
"unicodeVersion": "6.0",
- "digest": "7e38964006f8b28dfa2b3e9b2b16553bb50c18a63455f556b0bff35ee172137e"
+ "digest": "d0dd248ac8f17c5eb5c24f636f2d6387f1e4126d2227834ffb89057e9428a19f"
},
"worried": {
"category": "people",
"moji": "😟",
"description": "worried face",
"unicodeVersion": "6.1",
- "digest": "5a073985e1344bc34201ef94a491f7f2b946f5828c9fdbc57eeb2dcd87ac3a6b"
+ "digest": "66814ad2b00574ed539af543224116a3564b162b57e9d02d58f19513cb2c80f2"
},
"wrench": {
"category": "objects",
"moji": "🔧",
"description": "wrench",
"unicodeVersion": "6.0",
- "digest": "81aae53bc892035b905bf3ec5b442a8ecc95027c5fa9eb51b7c3e7d8fad3f3f4"
+ "digest": "8478c1b8b0565f87fe6e4f429975f16919d80622a3cdbcc2e83f17fd6978a1d7"
},
"wrestlers": {
"category": "activity",
"moji": "🤼",
"description": "wrestlers",
"unicodeVersion": "9.0",
- "digest": "9be983f3f9438f3ab8f6b643a958371d1e710c6d78e728f3465141811f05c2d5"
+ "digest": "919cf0ff49517c62a0abc8a6067e196fa6a1d5f73fa5902537879775ee9fad13"
},
"wrestlers_tone1": {
"category": "activity",
"moji": "🤼ðŸ»",
"description": "wrestlers tone 1",
"unicodeVersion": "9.0",
- "digest": "60461f83bfc93ce59dd027eab4782b7f206a7b142719fa72f301e047dc83a5d9"
+ "digest": "9611c3dfb8a18b8332135642d0fac74bd6557054909066141a81c9684bbc7207"
},
"wrestlers_tone2": {
"category": "activity",
"moji": "🤼ðŸ¼",
"description": "wrestlers tone 2",
"unicodeVersion": "9.0",
- "digest": "67ad93c86e6c58d552c18e7a0105cc81fd9bb0474da51f788eba2e4c14b4a636"
+ "digest": "17c529119acb4aafd8c834874d6285e41d2d9694243cce9eb51c87f67d22a3be"
},
"wrestlers_tone3": {
"category": "activity",
"moji": "🤼ðŸ½",
"description": "wrestlers tone 3",
"unicodeVersion": "9.0",
- "digest": "6bfd06c4435cabf2def153912040e05bf8db424fa383148ddda6d0ce8a8a3349"
+ "digest": "0f98afb56ecc165b4b8193c86565eaf0ded90456d6370b9d9f2e61eef572642e"
},
"wrestlers_tone4": {
"category": "activity",
"moji": "🤼ðŸ¾",
"description": "wrestlers tone 4",
"unicodeVersion": "9.0",
- "digest": "597312678834c4d288c238482879856d5eba4620deb1eaef495f428e2ba5f2a5"
+ "digest": "595507c7163ed2349d6f5cd3afeb3cb961a889bda1091bb5b03bf97c743ddd83"
},
"wrestlers_tone5": {
"category": "activity",
"moji": "🤼ðŸ¿",
"description": "wrestlers tone 5",
"unicodeVersion": "9.0",
- "digest": "d6aebdf1e44fd825b9a5b3716aefbc53f4b4dbb73cb2a628c0f2994ebfd34614"
+ "digest": "9a844250d5dbce6369a7923154fd3e7192e9bbc8773044ede577e587c86a6481"
},
"writing_hand": {
"category": "people",
"moji": "âœ",
"description": "writing hand",
"unicodeVersion": "1.1",
- "digest": "110517ae4da5587e8b0662881658e27da4120bfacec54734fd6657831d4d782f"
+ "digest": "efe3bfa1c36098242e2c4cb2d66e8d76fd3c0bba57335059dd1ad25748752c41"
},
"writing_hand_tone1": {
"category": "people",
"moji": "âœðŸ»",
"description": "writing hand tone 1",
"unicodeVersion": "8.0",
- "digest": "2c7e2108e1990490b681343c1b01b4183d4f18fbdef792f113b2f87595e0dad0"
+ "digest": "13e6782eea27e216721c4d1aeaa049f9ae3d93c9052f131cc17618102d16e4f6"
},
"writing_hand_tone2": {
"category": "people",
"moji": "âœðŸ¼",
"description": "writing hand tone 2",
"unicodeVersion": "8.0",
- "digest": "87ec8d44f472d301adbcbd50d8c852b609e46584057f59cc1527401db363c1bf"
+ "digest": "6ec5eeef36ef27fae05f2d3ac9bd97460d75b08fa52e01e239cbbe4101eb8ad8"
},
"writing_hand_tone3": {
"category": "people",
"moji": "âœðŸ½",
"description": "writing hand tone 3",
"unicodeVersion": "8.0",
- "digest": "4a48ddef91f7264e8fa9cca223554db22b3a2e3153e94b88d146644ea6dd661e"
+ "digest": "e3d68b62cbda6579641f49b45581deca7653e6322df43413ee6b80967861e315"
},
"writing_hand_tone4": {
"category": "people",
"moji": "âœðŸ¾",
"description": "writing hand tone 4",
"unicodeVersion": "8.0",
- "digest": "e5254564a1f91e42ee59f359d8cd26f52abdc04dca8f3b37cb2f140cb7f71390"
+ "digest": "52b7652348605b384761de53c28ffc3dc84b1b34210f795b40bb3e6235b8a959"
},
"writing_hand_tone5": {
"category": "people",
"moji": "âœðŸ¿",
"description": "writing hand tone 5",
"unicodeVersion": "8.0",
- "digest": "61299bf86d83d323ca3e6052c535ae66c6f7b3d9866a37db0464223b8bc28523"
+ "digest": "ce22c8e6c71ca3a07d32fb0c336301d015b81975a1019f20760ee908349c76dd"
},
"x": {
"category": "symbols",
"moji": "âŒ",
"description": "cross mark",
"unicodeVersion": "6.0",
- "digest": "3e5a7918e31ddefdf1ce73972365e2f0bfd2917d6a450c1a278c108349c9425d"
+ "digest": "d07158957d15f5b6c6fc56a9658a82ee1fa58f7b8b19d121a1713c9bf38cbdfc"
},
"yellow_heart": {
"category": "symbols",
"moji": "💛",
"description": "yellow heart",
"unicodeVersion": "6.0",
- "digest": "a1098f2f04c29754cc9974324508386787d4d803b57cf691d42de414cb2679d6"
+ "digest": "1785103b3aab8606869692986a2ff5e320dae4b6d58f7dca33beed221aff8f42"
},
"yen": {
"category": "objects",
"moji": "💴",
"description": "banknote with yen sign",
"unicodeVersion": "6.0",
- "digest": "944daaeb3f6369c807c0e63b106cee1360040f7800a70c0d942a992f25a55da7"
+ "digest": "b12182adf55be97d7d5e52176bb149c16f57d0645f508dcb97efbeab4607d439"
},
"yin_yang": {
"category": "symbols",
"moji": "☯",
"description": "yin yang",
"unicodeVersion": "1.1",
- "digest": "5ee8d13dacf41306a09237bfcff6abeef110331b40eb7d6e80600628c1327545"
+ "digest": "2d97f8a9eca001163c5895ff25ca66aad5dfabe5e2e00bda102fb6b9a27fc02b"
},
"yum": {
"category": "people",
"moji": "😋",
"description": "face savouring delicious food",
"unicodeVersion": "6.0",
- "digest": "31a89088c21bd7a74a3a26d731a907d1bc49436300a9f9c55248703cf7ef44c7"
+ "digest": "796badd831c75797cd4acb88694d3bf19b2727678b3c2e63e465e4d8125e4ad4"
},
"zap": {
"category": "nature",
"moji": "âš¡",
"description": "high voltage sign",
"unicodeVersion": "4.0",
- "digest": "9f8144ae6f866129aea41bbf694b0c858ef9352a139969e57cd8db73385f52c3"
+ "digest": "fbbfbda066d067a5b92ca815c784b577354de3e6c7a3dfa9a1656c29dc804f0c"
},
"zero": {
"category": "symbols",
"moji": "0ï¸âƒ£",
"description": "keycap digit zero",
"unicodeVersion": "3.0",
- "digest": "1b27b5c904defadbdd28ace67a6be5c277ff043297db7cd9f672bbf84e37fa1a"
+ "digest": "ef62df7416e51b02ff22787a981235053baabbb872247605e97834d9a7caff49"
},
"zipper_mouth": {
"category": "people",
"moji": "ðŸ¤",
"description": "zipper-mouth face",
"unicodeVersion": "8.0",
- "digest": "81bee5aa1202dfd5a4c7badb71ec0e44b8f75c2cbef94e6fd35c593d8770ae43"
+ "digest": "dfeeb9947458d1bb04805e46211d4f29aa89210239c475425ac04a1cef340701"
},
"zzz": {
"category": "people",
"moji": "💤",
"description": "sleeping symbol",
"unicodeVersion": "6.0",
- "digest": "b3313d0c44a59fa9d4ce9f7eb4d07ff71dfc8bb01798154250f27cdcf3c693b5"
+ "digest": "6b19746f5be6ee5f10dcb0969557eb9b02972d4429052237facf8d4b4f768546"
}
} \ No newline at end of file
diff --git a/fixtures/emojis/emoji-unicode-version-map.json b/fixtures/emojis/emoji-unicode-version-map.json
deleted file mode 100644
index 5164fe39426..00000000000
--- a/fixtures/emojis/emoji-unicode-version-map.json
+++ /dev/null
@@ -1,2377 +0,0 @@
-{
- "100": "6.0",
- "1234": "6.0",
- "grinning": "6.1",
- "grin": "6.0",
- "joy": "6.0",
- "rofl": "9.0",
- "rolling_on_the_floor_laughing": "9.0",
- "smiley": "6.0",
- "smile": "6.0",
- "sweat_smile": "6.0",
- "laughing": "6.0",
- "satisfied": "6.0",
- "wink": "6.0",
- "blush": "6.0",
- "yum": "6.0",
- "sunglasses": "6.0",
- "heart_eyes": "6.0",
- "kissing_heart": "6.0",
- "kissing": "6.1",
- "kissing_smiling_eyes": "6.1",
- "kissing_closed_eyes": "6.0",
- "relaxed": "1.1",
- "slight_smile": "7.0",
- "slightly_smiling_face": "7.0",
- "hugging": "8.0",
- "hugging_face": "8.0",
- "thinking": "8.0",
- "thinking_face": "8.0",
- "neutral_face": "6.0",
- "expressionless": "6.1",
- "no_mouth": "6.0",
- "rolling_eyes": "8.0",
- "face_with_rolling_eyes": "8.0",
- "smirk": "6.0",
- "persevere": "6.0",
- "disappointed_relieved": "6.0",
- "open_mouth": "6.1",
- "zipper_mouth": "8.0",
- "zipper_mouth_face": "8.0",
- "hushed": "6.1",
- "sleepy": "6.0",
- "tired_face": "6.0",
- "sleeping": "6.1",
- "relieved": "6.0",
- "nerd": "8.0",
- "nerd_face": "8.0",
- "stuck_out_tongue": "6.1",
- "stuck_out_tongue_winking_eye": "6.0",
- "stuck_out_tongue_closed_eyes": "6.0",
- "drooling_face": "9.0",
- "drool": "9.0",
- "unamused": "6.0",
- "sweat": "6.0",
- "pensive": "6.0",
- "confused": "6.1",
- "upside_down": "8.0",
- "upside_down_face": "8.0",
- "money_mouth": "8.0",
- "money_mouth_face": "8.0",
- "astonished": "6.0",
- "frowning2": "1.1",
- "white_frowning_face": "1.1",
- "slight_frown": "7.0",
- "slightly_frowning_face": "7.0",
- "confounded": "6.0",
- "disappointed": "6.0",
- "worried": "6.1",
- "triumph": "6.0",
- "cry": "6.0",
- "sob": "6.0",
- "frowning": "6.1",
- "anguished": "6.1",
- "fearful": "6.0",
- "weary": "6.0",
- "grimacing": "6.1",
- "cold_sweat": "6.0",
- "scream": "6.0",
- "flushed": "6.0",
- "dizzy_face": "6.0",
- "rage": "6.0",
- "angry": "6.0",
- "innocent": "6.0",
- "cowboy": "9.0",
- "face_with_cowboy_hat": "9.0",
- "clown": "9.0",
- "clown_face": "9.0",
- "lying_face": "9.0",
- "liar": "9.0",
- "mask": "6.0",
- "thermometer_face": "8.0",
- "face_with_thermometer": "8.0",
- "head_bandage": "8.0",
- "face_with_head_bandage": "8.0",
- "nauseated_face": "9.0",
- "sick": "9.0",
- "sneezing_face": "9.0",
- "sneeze": "9.0",
- "smiling_imp": "6.0",
- "imp": "6.0",
- "japanese_ogre": "6.0",
- "japanese_goblin": "6.0",
- "skull": "6.0",
- "skeleton": "6.0",
- "skull_crossbones": "1.1",
- "skull_and_crossbones": "1.1",
- "ghost": "6.0",
- "alien": "6.0",
- "space_invader": "6.0",
- "robot": "8.0",
- "robot_face": "8.0",
- "poop": "6.0",
- "shit": "6.0",
- "hankey": "6.0",
- "poo": "6.0",
- "smiley_cat": "6.0",
- "smile_cat": "6.0",
- "joy_cat": "6.0",
- "heart_eyes_cat": "6.0",
- "smirk_cat": "6.0",
- "kissing_cat": "6.0",
- "scream_cat": "6.0",
- "crying_cat_face": "6.0",
- "pouting_cat": "6.0",
- "see_no_evil": "6.0",
- "hear_no_evil": "6.0",
- "speak_no_evil": "6.0",
- "boy": "6.0",
- "boy_tone1": "8.0",
- "boy_tone2": "8.0",
- "boy_tone3": "8.0",
- "boy_tone4": "8.0",
- "boy_tone5": "8.0",
- "girl": "6.0",
- "girl_tone1": "8.0",
- "girl_tone2": "8.0",
- "girl_tone3": "8.0",
- "girl_tone4": "8.0",
- "girl_tone5": "8.0",
- "man": "6.0",
- "man_tone1": "8.0",
- "man_tone2": "8.0",
- "man_tone3": "8.0",
- "man_tone4": "8.0",
- "man_tone5": "8.0",
- "woman": "6.0",
- "woman_tone1": "8.0",
- "woman_tone2": "8.0",
- "woman_tone3": "8.0",
- "woman_tone4": "8.0",
- "woman_tone5": "8.0",
- "older_man": "6.0",
- "older_man_tone1": "8.0",
- "older_man_tone2": "8.0",
- "older_man_tone3": "8.0",
- "older_man_tone4": "8.0",
- "older_man_tone5": "8.0",
- "older_woman": "6.0",
- "grandma": "6.0",
- "older_woman_tone1": "8.0",
- "grandma_tone1": "8.0",
- "older_woman_tone2": "8.0",
- "grandma_tone2": "8.0",
- "older_woman_tone3": "8.0",
- "grandma_tone3": "8.0",
- "older_woman_tone4": "8.0",
- "grandma_tone4": "8.0",
- "older_woman_tone5": "8.0",
- "grandma_tone5": "8.0",
- "baby": "6.0",
- "baby_tone1": "8.0",
- "baby_tone2": "8.0",
- "baby_tone3": "8.0",
- "baby_tone4": "8.0",
- "baby_tone5": "8.0",
- "angel": "6.0",
- "angel_tone1": "8.0",
- "angel_tone2": "8.0",
- "angel_tone3": "8.0",
- "angel_tone4": "8.0",
- "angel_tone5": "8.0",
- "cop": "6.0",
- "cop_tone1": "8.0",
- "cop_tone2": "8.0",
- "cop_tone3": "8.0",
- "cop_tone4": "8.0",
- "cop_tone5": "8.0",
- "spy": "7.0",
- "sleuth_or_spy": "7.0",
- "spy_tone1": "8.0",
- "sleuth_or_spy_tone1": "8.0",
- "spy_tone2": "8.0",
- "sleuth_or_spy_tone2": "8.0",
- "spy_tone3": "8.0",
- "sleuth_or_spy_tone3": "8.0",
- "spy_tone4": "8.0",
- "sleuth_or_spy_tone4": "8.0",
- "spy_tone5": "8.0",
- "sleuth_or_spy_tone5": "8.0",
- "guardsman": "6.0",
- "guardsman_tone1": "8.0",
- "guardsman_tone2": "8.0",
- "guardsman_tone3": "8.0",
- "guardsman_tone4": "8.0",
- "guardsman_tone5": "8.0",
- "construction_worker": "6.0",
- "construction_worker_tone1": "8.0",
- "construction_worker_tone2": "8.0",
- "construction_worker_tone3": "8.0",
- "construction_worker_tone4": "8.0",
- "construction_worker_tone5": "8.0",
- "man_with_turban": "6.0",
- "man_with_turban_tone1": "8.0",
- "man_with_turban_tone2": "8.0",
- "man_with_turban_tone3": "8.0",
- "man_with_turban_tone4": "8.0",
- "man_with_turban_tone5": "8.0",
- "person_with_blond_hair": "6.0",
- "person_with_blond_hair_tone1": "8.0",
- "person_with_blond_hair_tone2": "8.0",
- "person_with_blond_hair_tone3": "8.0",
- "person_with_blond_hair_tone4": "8.0",
- "person_with_blond_hair_tone5": "8.0",
- "santa": "6.0",
- "santa_tone1": "8.0",
- "santa_tone2": "8.0",
- "santa_tone3": "8.0",
- "santa_tone4": "8.0",
- "santa_tone5": "8.0",
- "mrs_claus": "9.0",
- "mother_christmas": "9.0",
- "mrs_claus_tone1": "9.0",
- "mother_christmas_tone1": "9.0",
- "mrs_claus_tone2": "9.0",
- "mother_christmas_tone2": "9.0",
- "mrs_claus_tone3": "9.0",
- "mother_christmas_tone3": "9.0",
- "mrs_claus_tone4": "9.0",
- "mother_christmas_tone4": "9.0",
- "mrs_claus_tone5": "9.0",
- "mother_christmas_tone5": "9.0",
- "princess": "6.0",
- "princess_tone1": "8.0",
- "princess_tone2": "8.0",
- "princess_tone3": "8.0",
- "princess_tone4": "8.0",
- "princess_tone5": "8.0",
- "prince": "9.0",
- "prince_tone1": "9.0",
- "prince_tone2": "9.0",
- "prince_tone3": "9.0",
- "prince_tone4": "9.0",
- "prince_tone5": "9.0",
- "bride_with_veil": "6.0",
- "bride_with_veil_tone1": "8.0",
- "bride_with_veil_tone2": "8.0",
- "bride_with_veil_tone3": "8.0",
- "bride_with_veil_tone4": "8.0",
- "bride_with_veil_tone5": "8.0",
- "man_in_tuxedo": "9.0",
- "man_in_tuxedo_tone1": "9.0",
- "tuxedo_tone1": "9.0",
- "man_in_tuxedo_tone2": "9.0",
- "tuxedo_tone2": "9.0",
- "man_in_tuxedo_tone3": "9.0",
- "tuxedo_tone3": "9.0",
- "man_in_tuxedo_tone4": "9.0",
- "tuxedo_tone4": "9.0",
- "man_in_tuxedo_tone5": "9.0",
- "tuxedo_tone5": "9.0",
- "pregnant_woman": "9.0",
- "expecting_woman": "9.0",
- "pregnant_woman_tone1": "9.0",
- "expecting_woman_tone1": "9.0",
- "pregnant_woman_tone2": "9.0",
- "expecting_woman_tone2": "9.0",
- "pregnant_woman_tone3": "9.0",
- "expecting_woman_tone3": "9.0",
- "pregnant_woman_tone4": "9.0",
- "expecting_woman_tone4": "9.0",
- "pregnant_woman_tone5": "9.0",
- "expecting_woman_tone5": "9.0",
- "man_with_gua_pi_mao": "6.0",
- "man_with_gua_pi_mao_tone1": "8.0",
- "man_with_gua_pi_mao_tone2": "8.0",
- "man_with_gua_pi_mao_tone3": "8.0",
- "man_with_gua_pi_mao_tone4": "8.0",
- "man_with_gua_pi_mao_tone5": "8.0",
- "person_frowning": "6.0",
- "person_frowning_tone1": "8.0",
- "person_frowning_tone2": "8.0",
- "person_frowning_tone3": "8.0",
- "person_frowning_tone4": "8.0",
- "person_frowning_tone5": "8.0",
- "person_with_pouting_face": "6.0",
- "person_with_pouting_face_tone1": "8.0",
- "person_with_pouting_face_tone2": "8.0",
- "person_with_pouting_face_tone3": "8.0",
- "person_with_pouting_face_tone4": "8.0",
- "person_with_pouting_face_tone5": "8.0",
- "no_good": "6.0",
- "no_good_tone1": "8.0",
- "no_good_tone2": "8.0",
- "no_good_tone3": "8.0",
- "no_good_tone4": "8.0",
- "no_good_tone5": "8.0",
- "ok_woman": "6.0",
- "ok_woman_tone1": "8.0",
- "ok_woman_tone2": "8.0",
- "ok_woman_tone3": "8.0",
- "ok_woman_tone4": "8.0",
- "ok_woman_tone5": "8.0",
- "information_desk_person": "6.0",
- "information_desk_person_tone1": "8.0",
- "information_desk_person_tone2": "8.0",
- "information_desk_person_tone3": "8.0",
- "information_desk_person_tone4": "8.0",
- "information_desk_person_tone5": "8.0",
- "raising_hand": "6.0",
- "raising_hand_tone1": "8.0",
- "raising_hand_tone2": "8.0",
- "raising_hand_tone3": "8.0",
- "raising_hand_tone4": "8.0",
- "raising_hand_tone5": "8.0",
- "bow": "6.0",
- "bow_tone1": "8.0",
- "bow_tone2": "8.0",
- "bow_tone3": "8.0",
- "bow_tone4": "8.0",
- "bow_tone5": "8.0",
- "face_palm": "9.0",
- "facepalm": "9.0",
- "face_palm_tone1": "9.0",
- "facepalm_tone1": "9.0",
- "face_palm_tone2": "9.0",
- "facepalm_tone2": "9.0",
- "face_palm_tone3": "9.0",
- "facepalm_tone3": "9.0",
- "face_palm_tone4": "9.0",
- "facepalm_tone4": "9.0",
- "face_palm_tone5": "9.0",
- "facepalm_tone5": "9.0",
- "shrug": "9.0",
- "shrug_tone1": "9.0",
- "shrug_tone2": "9.0",
- "shrug_tone3": "9.0",
- "shrug_tone4": "9.0",
- "shrug_tone5": "9.0",
- "massage": "6.0",
- "massage_tone1": "8.0",
- "massage_tone2": "8.0",
- "massage_tone3": "8.0",
- "massage_tone4": "8.0",
- "massage_tone5": "8.0",
- "haircut": "6.0",
- "haircut_tone1": "8.0",
- "haircut_tone2": "8.0",
- "haircut_tone3": "8.0",
- "haircut_tone4": "8.0",
- "haircut_tone5": "8.0",
- "walking": "6.0",
- "walking_tone1": "8.0",
- "walking_tone2": "8.0",
- "walking_tone3": "8.0",
- "walking_tone4": "8.0",
- "walking_tone5": "8.0",
- "runner": "6.0",
- "runner_tone1": "8.0",
- "runner_tone2": "8.0",
- "runner_tone3": "8.0",
- "runner_tone4": "8.0",
- "runner_tone5": "8.0",
- "dancer": "6.0",
- "dancer_tone1": "8.0",
- "dancer_tone2": "8.0",
- "dancer_tone3": "8.0",
- "dancer_tone4": "8.0",
- "dancer_tone5": "8.0",
- "man_dancing": "9.0",
- "male_dancer": "9.0",
- "man_dancing_tone1": "9.0",
- "male_dancer_tone1": "9.0",
- "man_dancing_tone2": "9.0",
- "male_dancer_tone2": "9.0",
- "man_dancing_tone3": "9.0",
- "male_dancer_tone3": "9.0",
- "man_dancing_tone4": "9.0",
- "male_dancer_tone4": "9.0",
- "man_dancing_tone5": "9.0",
- "male_dancer_tone5": "9.0",
- "dancers": "6.0",
- "levitate": "7.0",
- "man_in_business_suit_levitating": "7.0",
- "speaking_head": "7.0",
- "speaking_head_in_silhouette": "7.0",
- "bust_in_silhouette": "6.0",
- "busts_in_silhouette": "6.0",
- "fencer": "9.0",
- "fencing": "9.0",
- "horse_racing": "6.0",
- "horse_racing_tone1": "8.0",
- "horse_racing_tone2": "8.0",
- "horse_racing_tone3": "8.0",
- "horse_racing_tone4": "8.0",
- "horse_racing_tone5": "8.0",
- "skier": "5.2",
- "snowboarder": "6.0",
- "golfer": "7.0",
- "surfer": "6.0",
- "surfer_tone1": "8.0",
- "surfer_tone2": "8.0",
- "surfer_tone3": "8.0",
- "surfer_tone4": "8.0",
- "surfer_tone5": "8.0",
- "rowboat": "6.0",
- "rowboat_tone1": "8.0",
- "rowboat_tone2": "8.0",
- "rowboat_tone3": "8.0",
- "rowboat_tone4": "8.0",
- "rowboat_tone5": "8.0",
- "swimmer": "6.0",
- "swimmer_tone1": "8.0",
- "swimmer_tone2": "8.0",
- "swimmer_tone3": "8.0",
- "swimmer_tone4": "8.0",
- "swimmer_tone5": "8.0",
- "basketball_player": "5.2",
- "person_with_ball": "5.2",
- "basketball_player_tone1": "8.0",
- "person_with_ball_tone1": "8.0",
- "basketball_player_tone2": "8.0",
- "person_with_ball_tone2": "8.0",
- "basketball_player_tone3": "8.0",
- "person_with_ball_tone3": "8.0",
- "basketball_player_tone4": "8.0",
- "person_with_ball_tone4": "8.0",
- "basketball_player_tone5": "8.0",
- "person_with_ball_tone5": "8.0",
- "lifter": "7.0",
- "weight_lifter": "7.0",
- "lifter_tone1": "8.0",
- "weight_lifter_tone1": "8.0",
- "lifter_tone2": "8.0",
- "weight_lifter_tone2": "8.0",
- "lifter_tone3": "8.0",
- "weight_lifter_tone3": "8.0",
- "lifter_tone4": "8.0",
- "weight_lifter_tone4": "8.0",
- "lifter_tone5": "8.0",
- "weight_lifter_tone5": "8.0",
- "bicyclist": "6.0",
- "bicyclist_tone1": "8.0",
- "bicyclist_tone2": "8.0",
- "bicyclist_tone3": "8.0",
- "bicyclist_tone4": "8.0",
- "bicyclist_tone5": "8.0",
- "mountain_bicyclist": "6.0",
- "mountain_bicyclist_tone1": "8.0",
- "mountain_bicyclist_tone2": "8.0",
- "mountain_bicyclist_tone3": "8.0",
- "mountain_bicyclist_tone4": "8.0",
- "mountain_bicyclist_tone5": "8.0",
- "race_car": "7.0",
- "racing_car": "7.0",
- "motorcycle": "7.0",
- "racing_motorcycle": "7.0",
- "cartwheel": "9.0",
- "person_doing_cartwheel": "9.0",
- "cartwheel_tone1": "9.0",
- "person_doing_cartwheel_tone1": "9.0",
- "cartwheel_tone2": "9.0",
- "person_doing_cartwheel_tone2": "9.0",
- "cartwheel_tone3": "9.0",
- "person_doing_cartwheel_tone3": "9.0",
- "cartwheel_tone4": "9.0",
- "person_doing_cartwheel_tone4": "9.0",
- "cartwheel_tone5": "9.0",
- "person_doing_cartwheel_tone5": "9.0",
- "wrestlers": "9.0",
- "wrestling": "9.0",
- "wrestlers_tone1": "9.0",
- "wrestling_tone1": "9.0",
- "wrestlers_tone2": "9.0",
- "wrestling_tone2": "9.0",
- "wrestlers_tone3": "9.0",
- "wrestling_tone3": "9.0",
- "wrestlers_tone4": "9.0",
- "wrestling_tone4": "9.0",
- "wrestlers_tone5": "9.0",
- "wrestling_tone5": "9.0",
- "water_polo": "9.0",
- "water_polo_tone1": "9.0",
- "water_polo_tone2": "9.0",
- "water_polo_tone3": "9.0",
- "water_polo_tone4": "9.0",
- "water_polo_tone5": "9.0",
- "handball": "9.0",
- "handball_tone1": "9.0",
- "handball_tone2": "9.0",
- "handball_tone3": "9.0",
- "handball_tone4": "9.0",
- "handball_tone5": "9.0",
- "juggling": "9.0",
- "juggler": "9.0",
- "juggling_tone1": "9.0",
- "juggler_tone1": "9.0",
- "juggling_tone2": "9.0",
- "juggler_tone2": "9.0",
- "juggling_tone3": "9.0",
- "juggler_tone3": "9.0",
- "juggling_tone4": "9.0",
- "juggler_tone4": "9.0",
- "juggling_tone5": "9.0",
- "juggler_tone5": "9.0",
- "couple": "6.0",
- "two_men_holding_hands": "6.0",
- "two_women_holding_hands": "6.0",
- "couplekiss": "6.0",
- "kiss_mm": "6.0",
- "couplekiss_mm": "6.0",
- "kiss_ww": "6.0",
- "couplekiss_ww": "6.0",
- "couple_with_heart": "6.0",
- "couple_mm": "6.0",
- "couple_with_heart_mm": "6.0",
- "couple_ww": "6.0",
- "couple_with_heart_ww": "6.0",
- "family": "6.0",
- "family_mwg": "6.0",
- "family_mwgb": "6.0",
- "family_mwbb": "6.0",
- "family_mwgg": "6.0",
- "family_mmb": "6.0",
- "family_mmg": "6.0",
- "family_mmgb": "6.0",
- "family_mmbb": "6.0",
- "family_mmgg": "6.0",
- "family_wwb": "6.0",
- "family_wwg": "6.0",
- "family_wwgb": "6.0",
- "family_wwbb": "6.0",
- "family_wwgg": "6.0",
- "tone1": "8.0",
- "tone2": "8.0",
- "tone3": "8.0",
- "tone4": "8.0",
- "tone5": "8.0",
- "muscle": "6.0",
- "muscle_tone1": "8.0",
- "muscle_tone2": "8.0",
- "muscle_tone3": "8.0",
- "muscle_tone4": "8.0",
- "muscle_tone5": "8.0",
- "selfie": "9.0",
- "selfie_tone1": "9.0",
- "selfie_tone2": "9.0",
- "selfie_tone3": "9.0",
- "selfie_tone4": "9.0",
- "selfie_tone5": "9.0",
- "point_left": "6.0",
- "point_left_tone1": "8.0",
- "point_left_tone2": "8.0",
- "point_left_tone3": "8.0",
- "point_left_tone4": "8.0",
- "point_left_tone5": "8.0",
- "point_right": "6.0",
- "point_right_tone1": "8.0",
- "point_right_tone2": "8.0",
- "point_right_tone3": "8.0",
- "point_right_tone4": "8.0",
- "point_right_tone5": "8.0",
- "point_up": "1.1",
- "point_up_tone1": "8.0",
- "point_up_tone2": "8.0",
- "point_up_tone3": "8.0",
- "point_up_tone4": "8.0",
- "point_up_tone5": "8.0",
- "point_up_2": "6.0",
- "point_up_2_tone1": "8.0",
- "point_up_2_tone2": "8.0",
- "point_up_2_tone3": "8.0",
- "point_up_2_tone4": "8.0",
- "point_up_2_tone5": "8.0",
- "middle_finger": "7.0",
- "reversed_hand_with_middle_finger_extended": "7.0",
- "middle_finger_tone1": "8.0",
- "reversed_hand_with_middle_finger_extended_tone1": "8.0",
- "middle_finger_tone2": "8.0",
- "reversed_hand_with_middle_finger_extended_tone2": "8.0",
- "middle_finger_tone3": "8.0",
- "reversed_hand_with_middle_finger_extended_tone3": "8.0",
- "middle_finger_tone4": "8.0",
- "reversed_hand_with_middle_finger_extended_tone4": "8.0",
- "middle_finger_tone5": "8.0",
- "reversed_hand_with_middle_finger_extended_tone5": "8.0",
- "point_down": "6.0",
- "point_down_tone1": "8.0",
- "point_down_tone2": "8.0",
- "point_down_tone3": "8.0",
- "point_down_tone4": "8.0",
- "point_down_tone5": "8.0",
- "v": "1.1",
- "v_tone1": "8.0",
- "v_tone2": "8.0",
- "v_tone3": "8.0",
- "v_tone4": "8.0",
- "v_tone5": "8.0",
- "fingers_crossed": "9.0",
- "hand_with_index_and_middle_finger_crossed": "9.0",
- "fingers_crossed_tone1": "9.0",
- "hand_with_index_and_middle_fingers_crossed_tone1": "9.0",
- "fingers_crossed_tone2": "9.0",
- "hand_with_index_and_middle_fingers_crossed_tone2": "9.0",
- "fingers_crossed_tone3": "9.0",
- "hand_with_index_and_middle_fingers_crossed_tone3": "9.0",
- "fingers_crossed_tone4": "9.0",
- "hand_with_index_and_middle_fingers_crossed_tone4": "9.0",
- "fingers_crossed_tone5": "9.0",
- "hand_with_index_and_middle_fingers_crossed_tone5": "9.0",
- "vulcan": "7.0",
- "raised_hand_with_part_between_middle_and_ring_fingers": "7.0",
- "vulcan_tone1": "8.0",
- "raised_hand_with_part_between_middle_and_ring_fingers_tone1": "8.0",
- "vulcan_tone2": "8.0",
- "raised_hand_with_part_between_middle_and_ring_fingers_tone2": "8.0",
- "vulcan_tone3": "8.0",
- "raised_hand_with_part_between_middle_and_ring_fingers_tone3": "8.0",
- "vulcan_tone4": "8.0",
- "raised_hand_with_part_between_middle_and_ring_fingers_tone4": "8.0",
- "vulcan_tone5": "8.0",
- "raised_hand_with_part_between_middle_and_ring_fingers_tone5": "8.0",
- "metal": "8.0",
- "sign_of_the_horns": "8.0",
- "metal_tone1": "8.0",
- "sign_of_the_horns_tone1": "8.0",
- "metal_tone2": "8.0",
- "sign_of_the_horns_tone2": "8.0",
- "metal_tone3": "8.0",
- "sign_of_the_horns_tone3": "8.0",
- "metal_tone4": "8.0",
- "sign_of_the_horns_tone4": "8.0",
- "metal_tone5": "8.0",
- "sign_of_the_horns_tone5": "8.0",
- "call_me": "9.0",
- "call_me_hand": "9.0",
- "call_me_tone1": "9.0",
- "call_me_hand_tone1": "9.0",
- "call_me_tone2": "9.0",
- "call_me_hand_tone2": "9.0",
- "call_me_tone3": "9.0",
- "call_me_hand_tone3": "9.0",
- "call_me_tone4": "9.0",
- "call_me_hand_tone4": "9.0",
- "call_me_tone5": "9.0",
- "call_me_hand_tone5": "9.0",
- "hand_splayed": "7.0",
- "raised_hand_with_fingers_splayed": "7.0",
- "hand_splayed_tone1": "8.0",
- "raised_hand_with_fingers_splayed_tone1": "8.0",
- "hand_splayed_tone2": "8.0",
- "raised_hand_with_fingers_splayed_tone2": "8.0",
- "hand_splayed_tone3": "8.0",
- "raised_hand_with_fingers_splayed_tone3": "8.0",
- "hand_splayed_tone4": "8.0",
- "raised_hand_with_fingers_splayed_tone4": "8.0",
- "hand_splayed_tone5": "8.0",
- "raised_hand_with_fingers_splayed_tone5": "8.0",
- "raised_hand": "6.0",
- "raised_hand_tone1": "8.0",
- "raised_hand_tone2": "8.0",
- "raised_hand_tone3": "8.0",
- "raised_hand_tone4": "8.0",
- "raised_hand_tone5": "8.0",
- "ok_hand": "6.0",
- "ok_hand_tone1": "8.0",
- "ok_hand_tone2": "8.0",
- "ok_hand_tone3": "8.0",
- "ok_hand_tone4": "8.0",
- "ok_hand_tone5": "8.0",
- "thumbsup": "6.0",
- "+1": "6.0",
- "thumbup": "6.0",
- "thumbsup_tone1": "8.0",
- "+1_tone1": "8.0",
- "thumbup_tone1": "8.0",
- "thumbsup_tone2": "8.0",
- "+1_tone2": "8.0",
- "thumbup_tone2": "8.0",
- "thumbsup_tone3": "8.0",
- "+1_tone3": "8.0",
- "thumbup_tone3": "8.0",
- "thumbsup_tone4": "8.0",
- "+1_tone4": "8.0",
- "thumbup_tone4": "8.0",
- "thumbsup_tone5": "8.0",
- "+1_tone5": "8.0",
- "thumbup_tone5": "8.0",
- "thumbsdown": "6.0",
- "-1": "6.0",
- "thumbdown": "6.0",
- "thumbsdown_tone1": "8.0",
- "-1_tone1": "8.0",
- "thumbdown_tone1": "8.0",
- "thumbsdown_tone2": "8.0",
- "-1_tone2": "8.0",
- "thumbdown_tone2": "8.0",
- "thumbsdown_tone3": "8.0",
- "-1_tone3": "8.0",
- "thumbdown_tone3": "8.0",
- "thumbsdown_tone4": "8.0",
- "-1_tone4": "8.0",
- "thumbdown_tone4": "8.0",
- "thumbsdown_tone5": "8.0",
- "-1_tone5": "8.0",
- "thumbdown_tone5": "8.0",
- "fist": "6.0",
- "fist_tone1": "8.0",
- "fist_tone2": "8.0",
- "fist_tone3": "8.0",
- "fist_tone4": "8.0",
- "fist_tone5": "8.0",
- "punch": "6.0",
- "punch_tone1": "8.0",
- "punch_tone2": "8.0",
- "punch_tone3": "8.0",
- "punch_tone4": "8.0",
- "punch_tone5": "8.0",
- "left_facing_fist": "9.0",
- "left_fist": "9.0",
- "left_facing_fist_tone1": "9.0",
- "left_fist_tone1": "9.0",
- "left_facing_fist_tone2": "9.0",
- "left_fist_tone2": "9.0",
- "left_facing_fist_tone3": "9.0",
- "left_fist_tone3": "9.0",
- "left_facing_fist_tone4": "9.0",
- "left_fist_tone4": "9.0",
- "left_facing_fist_tone5": "9.0",
- "left_fist_tone5": "9.0",
- "right_facing_fist": "9.0",
- "right_fist": "9.0",
- "right_facing_fist_tone1": "9.0",
- "right_fist_tone1": "9.0",
- "right_facing_fist_tone2": "9.0",
- "right_fist_tone2": "9.0",
- "right_facing_fist_tone3": "9.0",
- "right_fist_tone3": "9.0",
- "right_facing_fist_tone4": "9.0",
- "right_fist_tone4": "9.0",
- "right_facing_fist_tone5": "9.0",
- "right_fist_tone5": "9.0",
- "raised_back_of_hand": "9.0",
- "back_of_hand": "9.0",
- "raised_back_of_hand_tone1": "9.0",
- "back_of_hand_tone1": "9.0",
- "raised_back_of_hand_tone2": "9.0",
- "back_of_hand_tone2": "9.0",
- "raised_back_of_hand_tone3": "9.0",
- "back_of_hand_tone3": "9.0",
- "raised_back_of_hand_tone4": "9.0",
- "back_of_hand_tone4": "9.0",
- "raised_back_of_hand_tone5": "9.0",
- "back_of_hand_tone5": "9.0",
- "wave": "6.0",
- "wave_tone1": "8.0",
- "wave_tone2": "8.0",
- "wave_tone3": "8.0",
- "wave_tone4": "8.0",
- "wave_tone5": "8.0",
- "clap": "6.0",
- "clap_tone1": "8.0",
- "clap_tone2": "8.0",
- "clap_tone3": "8.0",
- "clap_tone4": "8.0",
- "clap_tone5": "8.0",
- "writing_hand": "1.1",
- "writing_hand_tone1": "8.0",
- "writing_hand_tone2": "8.0",
- "writing_hand_tone3": "8.0",
- "writing_hand_tone4": "8.0",
- "writing_hand_tone5": "8.0",
- "open_hands": "6.0",
- "open_hands_tone1": "8.0",
- "open_hands_tone2": "8.0",
- "open_hands_tone3": "8.0",
- "open_hands_tone4": "8.0",
- "open_hands_tone5": "8.0",
- "raised_hands": "6.0",
- "raised_hands_tone1": "8.0",
- "raised_hands_tone2": "8.0",
- "raised_hands_tone3": "8.0",
- "raised_hands_tone4": "8.0",
- "raised_hands_tone5": "8.0",
- "pray": "6.0",
- "pray_tone1": "8.0",
- "pray_tone2": "8.0",
- "pray_tone3": "8.0",
- "pray_tone4": "8.0",
- "pray_tone5": "8.0",
- "handshake": "9.0",
- "shaking_hands": "9.0",
- "handshake_tone1": "9.0",
- "shaking_hands_tone1": "9.0",
- "handshake_tone2": "9.0",
- "shaking_hands_tone2": "9.0",
- "handshake_tone3": "9.0",
- "shaking_hands_tone3": "9.0",
- "handshake_tone4": "9.0",
- "shaking_hands_tone4": "9.0",
- "handshake_tone5": "9.0",
- "shaking_hands_tone5": "9.0",
- "nail_care": "6.0",
- "nail_care_tone1": "8.0",
- "nail_care_tone2": "8.0",
- "nail_care_tone3": "8.0",
- "nail_care_tone4": "8.0",
- "nail_care_tone5": "8.0",
- "ear": "6.0",
- "ear_tone1": "8.0",
- "ear_tone2": "8.0",
- "ear_tone3": "8.0",
- "ear_tone4": "8.0",
- "ear_tone5": "8.0",
- "nose": "6.0",
- "nose_tone1": "8.0",
- "nose_tone2": "8.0",
- "nose_tone3": "8.0",
- "nose_tone4": "8.0",
- "nose_tone5": "8.0",
- "footprints": "6.0",
- "eyes": "6.0",
- "eye": "7.0",
- "eye_in_speech_bubble": "7.0",
- "tongue": "6.0",
- "lips": "6.0",
- "kiss": "6.0",
- "cupid": "6.0",
- "heart": "1.1",
- "heartbeat": "6.0",
- "broken_heart": "6.0",
- "two_hearts": "6.0",
- "sparkling_heart": "6.0",
- "heartpulse": "6.0",
- "blue_heart": "6.0",
- "green_heart": "6.0",
- "yellow_heart": "6.0",
- "purple_heart": "6.0",
- "black_heart": "9.0",
- "gift_heart": "6.0",
- "revolving_hearts": "6.0",
- "heart_decoration": "6.0",
- "heart_exclamation": "1.1",
- "heavy_heart_exclamation_mark_ornament": "1.1",
- "love_letter": "6.0",
- "zzz": "6.0",
- "anger": "6.0",
- "bomb": "6.0",
- "boom": "6.0",
- "sweat_drops": "6.0",
- "dash": "6.0",
- "dizzy": "6.0",
- "speech_balloon": "6.0",
- "speech_left": "7.0",
- "left_speech_bubble": "7.0",
- "anger_right": "7.0",
- "right_anger_bubble": "7.0",
- "thought_balloon": "6.0",
- "hole": "7.0",
- "eyeglasses": "6.0",
- "dark_sunglasses": "7.0",
- "necktie": "6.0",
- "shirt": "6.0",
- "jeans": "6.0",
- "dress": "6.0",
- "kimono": "6.0",
- "bikini": "6.0",
- "womans_clothes": "6.0",
- "purse": "6.0",
- "handbag": "6.0",
- "pouch": "6.0",
- "shopping_bags": "7.0",
- "school_satchel": "6.0",
- "mans_shoe": "6.0",
- "athletic_shoe": "6.0",
- "high_heel": "6.0",
- "sandal": "6.0",
- "boot": "6.0",
- "crown": "6.0",
- "womans_hat": "6.0",
- "tophat": "6.0",
- "mortar_board": "6.0",
- "helmet_with_cross": "5.2",
- "helmet_with_white_cross": "5.2",
- "prayer_beads": "8.0",
- "lipstick": "6.0",
- "ring": "6.0",
- "gem": "6.0",
- "monkey_face": "6.0",
- "monkey": "6.0",
- "gorilla": "9.0",
- "dog": "6.0",
- "dog2": "6.0",
- "poodle": "6.0",
- "wolf": "6.0",
- "fox": "9.0",
- "fox_face": "9.0",
- "cat": "6.0",
- "cat2": "6.0",
- "lion_face": "8.0",
- "lion": "8.0",
- "tiger": "6.0",
- "tiger2": "6.0",
- "leopard": "6.0",
- "horse": "6.0",
- "racehorse": "6.0",
- "deer": "9.0",
- "unicorn": "8.0",
- "unicorn_face": "8.0",
- "cow": "6.0",
- "ox": "6.0",
- "water_buffalo": "6.0",
- "cow2": "6.0",
- "pig": "6.0",
- "pig2": "6.0",
- "boar": "6.0",
- "pig_nose": "6.0",
- "ram": "6.0",
- "sheep": "6.0",
- "goat": "6.0",
- "dromedary_camel": "6.0",
- "camel": "6.0",
- "elephant": "6.0",
- "rhino": "9.0",
- "rhinoceros": "9.0",
- "mouse": "6.0",
- "mouse2": "6.0",
- "rat": "6.0",
- "hamster": "6.0",
- "rabbit": "6.0",
- "rabbit2": "6.0",
- "chipmunk": "7.0",
- "bat": "9.0",
- "bear": "6.0",
- "koala": "6.0",
- "panda_face": "6.0",
- "feet": "6.0",
- "paw_prints": "6.0",
- "turkey": "8.0",
- "chicken": "6.0",
- "rooster": "6.0",
- "hatching_chick": "6.0",
- "baby_chick": "6.0",
- "hatched_chick": "6.0",
- "bird": "6.0",
- "penguin": "6.0",
- "dove": "7.0",
- "dove_of_peace": "7.0",
- "eagle": "9.0",
- "duck": "9.0",
- "owl": "9.0",
- "frog": "6.0",
- "crocodile": "6.0",
- "turtle": "6.0",
- "lizard": "9.0",
- "snake": "6.0",
- "dragon_face": "6.0",
- "dragon": "6.0",
- "whale": "6.0",
- "whale2": "6.0",
- "dolphin": "6.0",
- "fish": "6.0",
- "tropical_fish": "6.0",
- "blowfish": "6.0",
- "shark": "9.0",
- "octopus": "6.0",
- "shell": "6.0",
- "crab": "8.0",
- "shrimp": "9.0",
- "squid": "9.0",
- "butterfly": "9.0",
- "snail": "6.0",
- "bug": "6.0",
- "ant": "6.0",
- "bee": "6.0",
- "beetle": "6.0",
- "spider": "7.0",
- "spider_web": "7.0",
- "scorpion": "8.0",
- "bouquet": "6.0",
- "cherry_blossom": "6.0",
- "white_flower": "6.0",
- "rosette": "7.0",
- "rose": "6.0",
- "wilted_rose": "9.0",
- "wilted_flower": "9.0",
- "hibiscus": "6.0",
- "sunflower": "6.0",
- "blossom": "6.0",
- "tulip": "6.0",
- "seedling": "6.0",
- "evergreen_tree": "6.0",
- "deciduous_tree": "6.0",
- "palm_tree": "6.0",
- "cactus": "6.0",
- "ear_of_rice": "6.0",
- "herb": "6.0",
- "shamrock": "4.1",
- "four_leaf_clover": "6.0",
- "maple_leaf": "6.0",
- "fallen_leaf": "6.0",
- "leaves": "6.0",
- "grapes": "6.0",
- "melon": "6.0",
- "watermelon": "6.0",
- "tangerine": "6.0",
- "lemon": "6.0",
- "banana": "6.0",
- "pineapple": "6.0",
- "apple": "6.0",
- "green_apple": "6.0",
- "pear": "6.0",
- "peach": "6.0",
- "cherries": "6.0",
- "strawberry": "6.0",
- "kiwi": "9.0",
- "kiwifruit": "9.0",
- "tomato": "6.0",
- "avocado": "9.0",
- "eggplant": "6.0",
- "potato": "9.0",
- "carrot": "9.0",
- "corn": "6.0",
- "hot_pepper": "7.0",
- "cucumber": "9.0",
- "mushroom": "6.0",
- "peanuts": "9.0",
- "shelled_peanut": "9.0",
- "chestnut": "6.0",
- "bread": "6.0",
- "croissant": "9.0",
- "french_bread": "9.0",
- "baguette_bread": "9.0",
- "pancakes": "9.0",
- "cheese": "8.0",
- "cheese_wedge": "8.0",
- "meat_on_bone": "6.0",
- "poultry_leg": "6.0",
- "bacon": "9.0",
- "hamburger": "6.0",
- "fries": "6.0",
- "pizza": "6.0",
- "hotdog": "8.0",
- "hot_dog": "8.0",
- "taco": "8.0",
- "burrito": "8.0",
- "stuffed_flatbread": "9.0",
- "stuffed_pita": "9.0",
- "egg": "9.0",
- "cooking": "6.0",
- "shallow_pan_of_food": "9.0",
- "paella": "9.0",
- "stew": "6.0",
- "salad": "9.0",
- "green_salad": "9.0",
- "popcorn": "8.0",
- "bento": "6.0",
- "rice_cracker": "6.0",
- "rice_ball": "6.0",
- "rice": "6.0",
- "curry": "6.0",
- "ramen": "6.0",
- "spaghetti": "6.0",
- "sweet_potato": "6.0",
- "oden": "6.0",
- "sushi": "6.0",
- "fried_shrimp": "6.0",
- "fish_cake": "6.0",
- "dango": "6.0",
- "icecream": "6.0",
- "shaved_ice": "6.0",
- "ice_cream": "6.0",
- "doughnut": "6.0",
- "cookie": "6.0",
- "birthday": "6.0",
- "cake": "6.0",
- "chocolate_bar": "6.0",
- "candy": "6.0",
- "lollipop": "6.0",
- "custard": "6.0",
- "pudding": "6.0",
- "flan": "6.0",
- "honey_pot": "6.0",
- "baby_bottle": "6.0",
- "milk": "9.0",
- "glass_of_milk": "9.0",
- "coffee": "4.0",
- "tea": "6.0",
- "sake": "6.0",
- "champagne": "8.0",
- "bottle_with_popping_cork": "8.0",
- "wine_glass": "6.0",
- "cocktail": "6.0",
- "tropical_drink": "6.0",
- "beer": "6.0",
- "beers": "6.0",
- "champagne_glass": "9.0",
- "clinking_glass": "9.0",
- "tumbler_glass": "9.0",
- "whisky": "9.0",
- "fork_knife_plate": "7.0",
- "fork_and_knife_with_plate": "7.0",
- "fork_and_knife": "6.0",
- "spoon": "9.0",
- "knife": "6.0",
- "amphora": "8.0",
- "earth_africa": "6.0",
- "earth_americas": "6.0",
- "earth_asia": "6.0",
- "globe_with_meridians": "6.0",
- "map": "7.0",
- "world_map": "7.0",
- "japan": "6.0",
- "mountain_snow": "7.0",
- "snow_capped_mountain": "7.0",
- "mountain": "5.2",
- "volcano": "6.0",
- "mount_fuji": "6.0",
- "camping": "7.0",
- "beach": "7.0",
- "beach_with_umbrella": "7.0",
- "desert": "7.0",
- "island": "7.0",
- "desert_island": "7.0",
- "park": "7.0",
- "national_park": "7.0",
- "stadium": "7.0",
- "classical_building": "7.0",
- "construction_site": "7.0",
- "building_construction": "7.0",
- "homes": "7.0",
- "house_buildings": "7.0",
- "cityscape": "7.0",
- "house_abandoned": "7.0",
- "derelict_house_building": "7.0",
- "house": "6.0",
- "house_with_garden": "6.0",
- "office": "6.0",
- "post_office": "6.0",
- "european_post_office": "6.0",
- "hospital": "6.0",
- "bank": "6.0",
- "hotel": "6.0",
- "love_hotel": "6.0",
- "convenience_store": "6.0",
- "school": "6.0",
- "department_store": "6.0",
- "factory": "6.0",
- "japanese_castle": "6.0",
- "european_castle": "6.0",
- "wedding": "6.0",
- "tokyo_tower": "6.0",
- "statue_of_liberty": "6.0",
- "church": "5.2",
- "mosque": "8.0",
- "synagogue": "8.0",
- "shinto_shrine": "5.2",
- "kaaba": "8.0",
- "fountain": "5.2",
- "tent": "5.2",
- "foggy": "6.0",
- "night_with_stars": "6.0",
- "sunrise_over_mountains": "6.0",
- "sunrise": "6.0",
- "city_dusk": "6.0",
- "city_sunset": "6.0",
- "city_sunrise": "6.0",
- "bridge_at_night": "6.0",
- "hotsprings": "1.1",
- "milky_way": "6.0",
- "carousel_horse": "6.0",
- "ferris_wheel": "6.0",
- "roller_coaster": "6.0",
- "barber": "6.0",
- "circus_tent": "6.0",
- "performing_arts": "6.0",
- "frame_photo": "7.0",
- "frame_with_picture": "7.0",
- "art": "6.0",
- "slot_machine": "6.0",
- "steam_locomotive": "6.0",
- "railway_car": "6.0",
- "bullettrain_side": "6.0",
- "bullettrain_front": "6.0",
- "train2": "6.0",
- "metro": "6.0",
- "light_rail": "6.0",
- "station": "6.0",
- "tram": "6.0",
- "monorail": "6.0",
- "mountain_railway": "6.0",
- "train": "6.0",
- "bus": "6.0",
- "oncoming_bus": "6.0",
- "trolleybus": "6.0",
- "minibus": "6.0",
- "ambulance": "6.0",
- "fire_engine": "6.0",
- "police_car": "6.0",
- "oncoming_police_car": "6.0",
- "taxi": "6.0",
- "oncoming_taxi": "6.0",
- "red_car": "6.0",
- "oncoming_automobile": "6.0",
- "blue_car": "6.0",
- "truck": "6.0",
- "articulated_lorry": "6.0",
- "tractor": "6.0",
- "bike": "6.0",
- "scooter": "9.0",
- "motor_scooter": "9.0",
- "motorbike": "9.0",
- "busstop": "6.0",
- "motorway": "7.0",
- "railway_track": "7.0",
- "railroad_track": "7.0",
- "fuelpump": "5.2",
- "rotating_light": "6.0",
- "traffic_light": "6.0",
- "vertical_traffic_light": "6.0",
- "construction": "6.0",
- "octagonal_sign": "9.0",
- "stop_sign": "9.0",
- "anchor": "4.1",
- "sailboat": "5.2",
- "canoe": "9.0",
- "kayak": "9.0",
- "speedboat": "6.0",
- "cruise_ship": "7.0",
- "passenger_ship": "7.0",
- "ferry": "5.2",
- "motorboat": "7.0",
- "ship": "6.0",
- "airplane": "1.1",
- "airplane_small": "7.0",
- "small_airplane": "7.0",
- "airplane_departure": "7.0",
- "airplane_arriving": "7.0",
- "seat": "6.0",
- "helicopter": "6.0",
- "suspension_railway": "6.0",
- "mountain_cableway": "6.0",
- "aerial_tramway": "6.0",
- "rocket": "6.0",
- "satellite_orbital": "7.0",
- "bellhop": "7.0",
- "bellhop_bell": "7.0",
- "door": "6.0",
- "sleeping_accommodation": "7.0",
- "bed": "7.0",
- "couch": "7.0",
- "couch_and_lamp": "7.0",
- "toilet": "6.0",
- "shower": "6.0",
- "bath": "6.0",
- "bath_tone1": "8.0",
- "bath_tone2": "8.0",
- "bath_tone3": "8.0",
- "bath_tone4": "8.0",
- "bath_tone5": "8.0",
- "bathtub": "6.0",
- "hourglass": "1.1",
- "hourglass_flowing_sand": "6.0",
- "watch": "1.1",
- "alarm_clock": "6.0",
- "stopwatch": "6.0",
- "timer": "6.0",
- "timer_clock": "6.0",
- "clock": "7.0",
- "mantlepiece_clock": "7.0",
- "clock12": "6.0",
- "clock1230": "6.0",
- "clock1": "6.0",
- "clock130": "6.0",
- "clock2": "6.0",
- "clock230": "6.0",
- "clock3": "6.0",
- "clock330": "6.0",
- "clock4": "6.0",
- "clock430": "6.0",
- "clock5": "6.0",
- "clock530": "6.0",
- "clock6": "6.0",
- "clock630": "6.0",
- "clock7": "6.0",
- "clock730": "6.0",
- "clock8": "6.0",
- "clock830": "6.0",
- "clock9": "6.0",
- "clock930": "6.0",
- "clock10": "6.0",
- "clock1030": "6.0",
- "clock11": "6.0",
- "clock1130": "6.0",
- "new_moon": "6.0",
- "waxing_crescent_moon": "6.0",
- "first_quarter_moon": "6.0",
- "waxing_gibbous_moon": "6.0",
- "full_moon": "6.0",
- "waning_gibbous_moon": "6.0",
- "last_quarter_moon": "6.0",
- "waning_crescent_moon": "6.0",
- "crescent_moon": "6.0",
- "new_moon_with_face": "6.0",
- "first_quarter_moon_with_face": "6.0",
- "last_quarter_moon_with_face": "6.0",
- "thermometer": "7.0",
- "sunny": "1.1",
- "full_moon_with_face": "6.0",
- "sun_with_face": "6.0",
- "star": "5.1",
- "star2": "6.0",
- "stars": "6.0",
- "cloud": "1.1",
- "partly_sunny": "5.2",
- "thunder_cloud_rain": "5.2",
- "thunder_cloud_and_rain": "5.2",
- "white_sun_small_cloud": "7.0",
- "white_sun_with_small_cloud": "7.0",
- "white_sun_cloud": "7.0",
- "white_sun_behind_cloud": "7.0",
- "white_sun_rain_cloud": "7.0",
- "white_sun_behind_cloud_with_rain": "7.0",
- "cloud_rain": "7.0",
- "cloud_with_rain": "7.0",
- "cloud_snow": "7.0",
- "cloud_with_snow": "7.0",
- "cloud_lightning": "7.0",
- "cloud_with_lightning": "7.0",
- "cloud_tornado": "7.0",
- "cloud_with_tornado": "7.0",
- "fog": "7.0",
- "wind_blowing_face": "7.0",
- "cyclone": "6.0",
- "rainbow": "6.0",
- "closed_umbrella": "6.0",
- "umbrella2": "1.1",
- "umbrella": "4.0",
- "beach_umbrella": "5.2",
- "umbrella_on_ground": "5.2",
- "zap": "4.0",
- "snowflake": "1.1",
- "snowman2": "1.1",
- "snowman": "5.2",
- "comet": "1.1",
- "fire": "6.0",
- "flame": "6.0",
- "droplet": "6.0",
- "ocean": "6.0",
- "jack_o_lantern": "6.0",
- "christmas_tree": "6.0",
- "fireworks": "6.0",
- "sparkler": "6.0",
- "sparkles": "6.0",
- "balloon": "6.0",
- "tada": "6.0",
- "confetti_ball": "6.0",
- "tanabata_tree": "6.0",
- "bamboo": "6.0",
- "dolls": "6.0",
- "flags": "6.0",
- "wind_chime": "6.0",
- "rice_scene": "6.0",
- "ribbon": "6.0",
- "gift": "6.0",
- "reminder_ribbon": "7.0",
- "tickets": "7.0",
- "admission_tickets": "7.0",
- "ticket": "6.0",
- "military_medal": "7.0",
- "trophy": "6.0",
- "medal": "7.0",
- "sports_medal": "7.0",
- "first_place": "9.0",
- "first_place_medal": "9.0",
- "second_place": "9.0",
- "second_place_medal": "9.0",
- "third_place": "9.0",
- "third_place_medal": "9.0",
- "soccer": "5.2",
- "baseball": "5.2",
- "basketball": "6.0",
- "volleyball": "8.0",
- "football": "6.0",
- "rugby_football": "6.0",
- "tennis": "6.0",
- "8ball": "6.0",
- "bowling": "6.0",
- "cricket": "8.0",
- "cricket_bat_ball": "8.0",
- "field_hockey": "8.0",
- "hockey": "8.0",
- "ping_pong": "8.0",
- "table_tennis": "8.0",
- "badminton": "8.0",
- "boxing_glove": "9.0",
- "boxing_gloves": "9.0",
- "martial_arts_uniform": "9.0",
- "karate_uniform": "9.0",
- "goal": "9.0",
- "goal_net": "9.0",
- "dart": "6.0",
- "golf": "5.2",
- "ice_skate": "5.2",
- "fishing_pole_and_fish": "6.0",
- "running_shirt_with_sash": "6.0",
- "ski": "6.0",
- "video_game": "6.0",
- "joystick": "7.0",
- "game_die": "6.0",
- "spades": "1.1",
- "hearts": "1.1",
- "diamonds": "1.1",
- "clubs": "1.1",
- "black_joker": "6.0",
- "mahjong": "5.1",
- "flower_playing_cards": "6.0",
- "mute": "6.0",
- "speaker": "6.0",
- "sound": "6.0",
- "loud_sound": "6.0",
- "loudspeaker": "6.0",
- "mega": "6.0",
- "postal_horn": "6.0",
- "bell": "6.0",
- "no_bell": "6.0",
- "musical_score": "6.0",
- "musical_note": "6.0",
- "notes": "6.0",
- "microphone2": "7.0",
- "studio_microphone": "7.0",
- "level_slider": "7.0",
- "control_knobs": "7.0",
- "microphone": "6.0",
- "headphones": "6.0",
- "radio": "6.0",
- "saxophone": "6.0",
- "guitar": "6.0",
- "musical_keyboard": "6.0",
- "trumpet": "6.0",
- "violin": "6.0",
- "drum": "9.0",
- "drum_with_drumsticks": "9.0",
- "iphone": "6.0",
- "calling": "6.0",
- "telephone": "1.1",
- "telephone_receiver": "6.0",
- "pager": "6.0",
- "fax": "6.0",
- "battery": "6.0",
- "electric_plug": "6.0",
- "computer": "6.0",
- "desktop": "7.0",
- "desktop_computer": "7.0",
- "printer": "7.0",
- "keyboard": "1.1",
- "mouse_three_button": "7.0",
- "three_button_mouse": "7.0",
- "trackball": "7.0",
- "minidisc": "6.0",
- "floppy_disk": "6.0",
- "cd": "6.0",
- "dvd": "6.0",
- "movie_camera": "6.0",
- "film_frames": "7.0",
- "projector": "7.0",
- "film_projector": "7.0",
- "clapper": "6.0",
- "tv": "6.0",
- "camera": "6.0",
- "camera_with_flash": "7.0",
- "video_camera": "6.0",
- "vhs": "6.0",
- "mag": "6.0",
- "mag_right": "6.0",
- "microscope": "6.0",
- "telescope": "6.0",
- "satellite": "6.0",
- "candle": "7.0",
- "bulb": "6.0",
- "flashlight": "6.0",
- "izakaya_lantern": "6.0",
- "notebook_with_decorative_cover": "6.0",
- "closed_book": "6.0",
- "book": "6.0",
- "green_book": "6.0",
- "blue_book": "6.0",
- "orange_book": "6.0",
- "books": "6.0",
- "notebook": "6.0",
- "ledger": "6.0",
- "page_with_curl": "6.0",
- "scroll": "6.0",
- "page_facing_up": "6.0",
- "newspaper": "6.0",
- "newspaper2": "7.0",
- "rolled_up_newspaper": "7.0",
- "bookmark_tabs": "6.0",
- "bookmark": "6.0",
- "label": "7.0",
- "moneybag": "6.0",
- "yen": "6.0",
- "dollar": "6.0",
- "euro": "6.0",
- "pound": "6.0",
- "money_with_wings": "6.0",
- "credit_card": "6.0",
- "chart": "6.0",
- "currency_exchange": "6.0",
- "heavy_dollar_sign": "6.0",
- "envelope": "1.1",
- "e-mail": "6.0",
- "email": "6.0",
- "incoming_envelope": "6.0",
- "envelope_with_arrow": "6.0",
- "outbox_tray": "6.0",
- "inbox_tray": "6.0",
- "package": "6.0",
- "mailbox": "6.0",
- "mailbox_closed": "6.0",
- "mailbox_with_mail": "6.0",
- "mailbox_with_no_mail": "6.0",
- "postbox": "6.0",
- "ballot_box": "7.0",
- "ballot_box_with_ballot": "7.0",
- "pencil2": "1.1",
- "black_nib": "1.1",
- "pen_fountain": "7.0",
- "lower_left_fountain_pen": "7.0",
- "pen_ballpoint": "7.0",
- "lower_left_ballpoint_pen": "7.0",
- "paintbrush": "7.0",
- "lower_left_paintbrush": "7.0",
- "crayon": "7.0",
- "lower_left_crayon": "7.0",
- "pencil": "6.0",
- "briefcase": "6.0",
- "file_folder": "6.0",
- "open_file_folder": "6.0",
- "dividers": "7.0",
- "card_index_dividers": "7.0",
- "date": "6.0",
- "calendar": "6.0",
- "notepad_spiral": "7.0",
- "spiral_note_pad": "7.0",
- "calendar_spiral": "7.0",
- "spiral_calendar_pad": "7.0",
- "card_index": "6.0",
- "chart_with_upwards_trend": "6.0",
- "chart_with_downwards_trend": "6.0",
- "bar_chart": "6.0",
- "clipboard": "6.0",
- "pushpin": "6.0",
- "round_pushpin": "6.0",
- "paperclip": "6.0",
- "paperclips": "7.0",
- "linked_paperclips": "7.0",
- "straight_ruler": "6.0",
- "triangular_ruler": "6.0",
- "scissors": "1.1",
- "card_box": "7.0",
- "card_file_box": "7.0",
- "file_cabinet": "7.0",
- "wastebasket": "7.0",
- "lock": "6.0",
- "unlock": "6.0",
- "lock_with_ink_pen": "6.0",
- "closed_lock_with_key": "6.0",
- "key": "6.0",
- "key2": "7.0",
- "old_key": "7.0",
- "hammer": "6.0",
- "pick": "5.2",
- "hammer_pick": "4.1",
- "hammer_and_pick": "4.1",
- "tools": "7.0",
- "hammer_and_wrench": "7.0",
- "dagger": "7.0",
- "dagger_knife": "7.0",
- "crossed_swords": "4.1",
- "gun": "6.0",
- "bow_and_arrow": "8.0",
- "archery": "8.0",
- "shield": "7.0",
- "wrench": "6.0",
- "nut_and_bolt": "6.0",
- "gear": "4.1",
- "compression": "7.0",
- "alembic": "4.1",
- "scales": "4.1",
- "link": "6.0",
- "chains": "5.2",
- "syringe": "6.0",
- "pill": "6.0",
- "smoking": "6.0",
- "coffin": "4.1",
- "urn": "4.1",
- "funeral_urn": "4.1",
- "moyai": "6.0",
- "oil": "7.0",
- "oil_drum": "7.0",
- "crystal_ball": "6.0",
- "shopping_cart": "9.0",
- "shopping_trolley": "9.0",
- "atm": "6.0",
- "put_litter_in_its_place": "6.0",
- "potable_water": "6.0",
- "wheelchair": "4.1",
- "mens": "6.0",
- "womens": "6.0",
- "restroom": "6.0",
- "baby_symbol": "6.0",
- "wc": "6.0",
- "passport_control": "6.0",
- "customs": "6.0",
- "baggage_claim": "6.0",
- "left_luggage": "6.0",
- "warning": "4.0",
- "children_crossing": "6.0",
- "no_entry": "5.2",
- "no_entry_sign": "6.0",
- "no_bicycles": "6.0",
- "no_smoking": "6.0",
- "do_not_litter": "6.0",
- "non-potable_water": "6.0",
- "no_pedestrians": "6.0",
- "no_mobile_phones": "6.0",
- "underage": "6.0",
- "radioactive": "1.1",
- "radioactive_sign": "1.1",
- "biohazard": "1.1",
- "biohazard_sign": "1.1",
- "arrow_up": "4.0",
- "arrow_upper_right": "1.1",
- "arrow_right": "1.1",
- "arrow_lower_right": "1.1",
- "arrow_down": "4.0",
- "arrow_lower_left": "1.1",
- "arrow_left": "4.0",
- "arrow_upper_left": "1.1",
- "arrow_up_down": "1.1",
- "left_right_arrow": "1.1",
- "leftwards_arrow_with_hook": "1.1",
- "arrow_right_hook": "1.1",
- "arrow_heading_up": "3.2",
- "arrow_heading_down": "3.2",
- "arrows_clockwise": "6.0",
- "arrows_counterclockwise": "6.0",
- "back": "6.0",
- "end": "6.0",
- "on": "6.0",
- "soon": "6.0",
- "top": "6.0",
- "place_of_worship": "8.0",
- "worship_symbol": "8.0",
- "atom": "4.1",
- "atom_symbol": "4.1",
- "om_symbol": "7.0",
- "star_of_david": "1.1",
- "wheel_of_dharma": "1.1",
- "yin_yang": "1.1",
- "cross": "1.1",
- "latin_cross": "1.1",
- "orthodox_cross": "1.1",
- "star_and_crescent": "1.1",
- "peace": "1.1",
- "peace_symbol": "1.1",
- "menorah": "8.0",
- "six_pointed_star": "6.0",
- "aries": "1.1",
- "taurus": "1.1",
- "gemini": "1.1",
- "cancer": "1.1",
- "leo": "1.1",
- "virgo": "1.1",
- "libra": "1.1",
- "scorpius": "1.1",
- "sagittarius": "1.1",
- "capricorn": "1.1",
- "aquarius": "1.1",
- "pisces": "1.1",
- "ophiuchus": "6.0",
- "twisted_rightwards_arrows": "6.0",
- "repeat": "6.0",
- "repeat_one": "6.0",
- "arrow_forward": "1.1",
- "fast_forward": "6.0",
- "track_next": "6.0",
- "next_track": "6.0",
- "play_pause": "6.0",
- "arrow_backward": "1.1",
- "rewind": "6.0",
- "track_previous": "6.0",
- "previous_track": "6.0",
- "arrow_up_small": "6.0",
- "arrow_double_up": "6.0",
- "arrow_down_small": "6.0",
- "arrow_double_down": "6.0",
- "pause_button": "7.0",
- "double_vertical_bar": "7.0",
- "stop_button": "7.0",
- "record_button": "7.0",
- "eject": "4.0",
- "eject_symbol": "4.0",
- "cinema": "6.0",
- "low_brightness": "6.0",
- "high_brightness": "6.0",
- "signal_strength": "6.0",
- "vibration_mode": "6.0",
- "mobile_phone_off": "6.0",
- "recycle": "3.2",
- "name_badge": "6.0",
- "fleur-de-lis": "4.1",
- "beginner": "6.0",
- "trident": "6.0",
- "o": "5.2",
- "white_check_mark": "6.0",
- "ballot_box_with_check": "1.1",
- "heavy_check_mark": "1.1",
- "heavy_multiplication_x": "1.1",
- "x": "6.0",
- "negative_squared_cross_mark": "6.0",
- "heavy_plus_sign": "6.0",
- "heavy_minus_sign": "6.0",
- "heavy_division_sign": "6.0",
- "curly_loop": "6.0",
- "loop": "6.0",
- "part_alternation_mark": "3.2",
- "eight_spoked_asterisk": "1.1",
- "eight_pointed_black_star": "1.1",
- "sparkle": "1.1",
- "bangbang": "1.1",
- "interrobang": "3.0",
- "question": "6.0",
- "grey_question": "6.0",
- "grey_exclamation": "6.0",
- "exclamation": "5.2",
- "wavy_dash": "1.1",
- "copyright": "1.1",
- "registered": "1.1",
- "tm": "1.1",
- "hash": "3.0",
- "asterisk": "3.0",
- "keycap_asterisk": "3.0",
- "zero": "3.0",
- "one": "3.0",
- "two": "3.0",
- "three": "3.0",
- "four": "3.0",
- "five": "3.0",
- "six": "3.0",
- "seven": "3.0",
- "eight": "3.0",
- "nine": "3.0",
- "keycap_ten": "6.0",
- "capital_abcd": "6.0",
- "abcd": "6.0",
- "symbols": "6.0",
- "abc": "6.0",
- "a": "6.0",
- "ab": "6.0",
- "b": "6.0",
- "cl": "6.0",
- "cool": "6.0",
- "free": "6.0",
- "information_source": "3.0",
- "id": "6.0",
- "m": "1.1",
- "new": "6.0",
- "ng": "6.0",
- "o2": "6.0",
- "ok": "6.0",
- "parking": "5.2",
- "sos": "6.0",
- "up": "6.0",
- "vs": "6.0",
- "koko": "6.0",
- "sa": "6.0",
- "u6708": "6.0",
- "u6709": "6.0",
- "u6307": "5.2",
- "ideograph_advantage": "6.0",
- "u5272": "6.0",
- "u7121": "5.2",
- "u7981": "6.0",
- "accept": "6.0",
- "u7533": "6.0",
- "u5408": "6.0",
- "u7a7a": "6.0",
- "congratulations": "1.1",
- "secret": "1.1",
- "u55b6": "6.0",
- "u6e80": "6.0",
- "black_small_square": "1.1",
- "white_small_square": "1.1",
- "white_medium_square": "3.2",
- "black_medium_square": "3.2",
- "white_medium_small_square": "3.2",
- "black_medium_small_square": "3.2",
- "black_large_square": "5.1",
- "white_large_square": "5.1",
- "large_orange_diamond": "6.0",
- "large_blue_diamond": "6.0",
- "small_orange_diamond": "6.0",
- "small_blue_diamond": "6.0",
- "small_red_triangle": "6.0",
- "small_red_triangle_down": "6.0",
- "diamond_shape_with_a_dot_inside": "6.0",
- "radio_button": "6.0",
- "black_square_button": "6.0",
- "white_square_button": "6.0",
- "white_circle": "4.1",
- "black_circle": "4.1",
- "red_circle": "6.0",
- "blue_circle": "6.0",
- "checkered_flag": "6.0",
- "triangular_flag_on_post": "6.0",
- "crossed_flags": "6.0",
- "flag_black": "6.0",
- "waving_black_flag": "6.0",
- "flag_white": "6.0",
- "waving_white_flag": "6.0",
- "rainbow_flag": "6.0",
- "gay_pride_flag": "6.0",
- "flag_ac": "6.0",
- "ac": "6.0",
- "flag_ad": "6.0",
- "ad": "6.0",
- "flag_ae": "6.0",
- "ae": "6.0",
- "flag_af": "6.0",
- "af": "6.0",
- "flag_ag": "6.0",
- "ag": "6.0",
- "flag_ai": "6.0",
- "ai": "6.0",
- "flag_al": "6.0",
- "al": "6.0",
- "flag_am": "6.0",
- "am": "6.0",
- "flag_ao": "6.0",
- "ao": "6.0",
- "flag_aq": "6.0",
- "aq": "6.0",
- "flag_ar": "6.0",
- "ar": "6.0",
- "flag_as": "6.0",
- "as": "6.0",
- "flag_at": "6.0",
- "at": "6.0",
- "flag_au": "6.0",
- "au": "6.0",
- "flag_aw": "6.0",
- "aw": "6.0",
- "flag_ax": "6.0",
- "ax": "6.0",
- "flag_az": "6.0",
- "az": "6.0",
- "flag_ba": "6.0",
- "ba": "6.0",
- "flag_bb": "6.0",
- "bb": "6.0",
- "flag_bd": "6.0",
- "bd": "6.0",
- "flag_be": "6.0",
- "be": "6.0",
- "flag_bf": "6.0",
- "bf": "6.0",
- "flag_bg": "6.0",
- "bg": "6.0",
- "flag_bh": "6.0",
- "bh": "6.0",
- "flag_bi": "6.0",
- "bi": "6.0",
- "flag_bj": "6.0",
- "bj": "6.0",
- "flag_bl": "6.0",
- "bl": "6.0",
- "flag_bm": "6.0",
- "bm": "6.0",
- "flag_bn": "6.0",
- "bn": "6.0",
- "flag_bo": "6.0",
- "bo": "6.0",
- "flag_bq": "6.0",
- "bq": "6.0",
- "flag_br": "6.0",
- "br": "6.0",
- "flag_bs": "6.0",
- "bs": "6.0",
- "flag_bt": "6.0",
- "bt": "6.0",
- "flag_bv": "6.0",
- "bv": "6.0",
- "flag_bw": "6.0",
- "bw": "6.0",
- "flag_by": "6.0",
- "by": "6.0",
- "flag_bz": "6.0",
- "bz": "6.0",
- "flag_ca": "6.0",
- "ca": "6.0",
- "flag_cc": "6.0",
- "cc": "6.0",
- "flag_cd": "6.0",
- "congo": "6.0",
- "flag_cf": "6.0",
- "cf": "6.0",
- "flag_cg": "6.0",
- "cg": "6.0",
- "flag_ch": "6.0",
- "ch": "6.0",
- "flag_ci": "6.0",
- "ci": "6.0",
- "flag_ck": "6.0",
- "ck": "6.0",
- "flag_cl": "6.0",
- "chile": "6.0",
- "flag_cm": "6.0",
- "cm": "6.0",
- "flag_cn": "6.0",
- "cn": "6.0",
- "flag_co": "6.0",
- "co": "6.0",
- "flag_cp": "6.0",
- "cp": "6.0",
- "flag_cr": "6.0",
- "cr": "6.0",
- "flag_cu": "6.0",
- "cu": "6.0",
- "flag_cv": "6.0",
- "cv": "6.0",
- "flag_cw": "6.0",
- "cw": "6.0",
- "flag_cx": "6.0",
- "cx": "6.0",
- "flag_cy": "6.0",
- "cy": "6.0",
- "flag_cz": "6.0",
- "cz": "6.0",
- "flag_de": "6.0",
- "de": "6.0",
- "flag_dg": "6.0",
- "dg": "6.0",
- "flag_dj": "6.0",
- "dj": "6.0",
- "flag_dk": "6.0",
- "dk": "6.0",
- "flag_dm": "6.0",
- "dm": "6.0",
- "flag_do": "6.0",
- "do": "6.0",
- "flag_dz": "6.0",
- "dz": "6.0",
- "flag_ea": "6.0",
- "ea": "6.0",
- "flag_ec": "6.0",
- "ec": "6.0",
- "flag_ee": "6.0",
- "ee": "6.0",
- "flag_eg": "6.0",
- "eg": "6.0",
- "flag_eh": "6.0",
- "eh": "6.0",
- "flag_er": "6.0",
- "er": "6.0",
- "flag_es": "6.0",
- "es": "6.0",
- "flag_et": "6.0",
- "et": "6.0",
- "flag_eu": "6.0",
- "eu": "6.0",
- "flag_fi": "6.0",
- "fi": "6.0",
- "flag_fj": "6.0",
- "fj": "6.0",
- "flag_fk": "6.0",
- "fk": "6.0",
- "flag_fm": "6.0",
- "fm": "6.0",
- "flag_fo": "6.0",
- "fo": "6.0",
- "flag_fr": "6.0",
- "fr": "6.0",
- "flag_ga": "6.0",
- "ga": "6.0",
- "flag_gb": "6.0",
- "gb": "6.0",
- "flag_gd": "6.0",
- "gd": "6.0",
- "flag_ge": "6.0",
- "ge": "6.0",
- "flag_gf": "6.0",
- "gf": "6.0",
- "flag_gg": "6.0",
- "gg": "6.0",
- "flag_gh": "6.0",
- "gh": "6.0",
- "flag_gi": "6.0",
- "gi": "6.0",
- "flag_gl": "6.0",
- "gl": "6.0",
- "flag_gm": "6.0",
- "gm": "6.0",
- "flag_gn": "6.0",
- "gn": "6.0",
- "flag_gp": "6.0",
- "gp": "6.0",
- "flag_gq": "6.0",
- "gq": "6.0",
- "flag_gr": "6.0",
- "gr": "6.0",
- "flag_gs": "6.0",
- "gs": "6.0",
- "flag_gt": "6.0",
- "gt": "6.0",
- "flag_gu": "6.0",
- "gu": "6.0",
- "flag_gw": "6.0",
- "gw": "6.0",
- "flag_gy": "6.0",
- "gy": "6.0",
- "flag_hk": "6.0",
- "hk": "6.0",
- "flag_hm": "6.0",
- "hm": "6.0",
- "flag_hn": "6.0",
- "hn": "6.0",
- "flag_hr": "6.0",
- "hr": "6.0",
- "flag_ht": "6.0",
- "ht": "6.0",
- "flag_hu": "6.0",
- "hu": "6.0",
- "flag_ic": "6.0",
- "ic": "6.0",
- "flag_id": "6.0",
- "indonesia": "6.0",
- "flag_ie": "6.0",
- "ie": "6.0",
- "flag_il": "6.0",
- "il": "6.0",
- "flag_im": "6.0",
- "im": "6.0",
- "flag_in": "6.0",
- "in": "6.0",
- "flag_io": "6.0",
- "io": "6.0",
- "flag_iq": "6.0",
- "iq": "6.0",
- "flag_ir": "6.0",
- "ir": "6.0",
- "flag_is": "6.0",
- "is": "6.0",
- "flag_it": "6.0",
- "it": "6.0",
- "flag_je": "6.0",
- "je": "6.0",
- "flag_jm": "6.0",
- "jm": "6.0",
- "flag_jo": "6.0",
- "jo": "6.0",
- "flag_jp": "6.0",
- "jp": "6.0",
- "flag_ke": "6.0",
- "ke": "6.0",
- "flag_kg": "6.0",
- "kg": "6.0",
- "flag_kh": "6.0",
- "kh": "6.0",
- "flag_ki": "6.0",
- "ki": "6.0",
- "flag_km": "6.0",
- "km": "6.0",
- "flag_kn": "6.0",
- "kn": "6.0",
- "flag_kp": "6.0",
- "kp": "6.0",
- "flag_kr": "6.0",
- "kr": "6.0",
- "flag_kw": "6.0",
- "kw": "6.0",
- "flag_ky": "6.0",
- "ky": "6.0",
- "flag_kz": "6.0",
- "kz": "6.0",
- "flag_la": "6.0",
- "la": "6.0",
- "flag_lb": "6.0",
- "lb": "6.0",
- "flag_lc": "6.0",
- "lc": "6.0",
- "flag_li": "6.0",
- "li": "6.0",
- "flag_lk": "6.0",
- "lk": "6.0",
- "flag_lr": "6.0",
- "lr": "6.0",
- "flag_ls": "6.0",
- "ls": "6.0",
- "flag_lt": "6.0",
- "lt": "6.0",
- "flag_lu": "6.0",
- "lu": "6.0",
- "flag_lv": "6.0",
- "lv": "6.0",
- "flag_ly": "6.0",
- "ly": "6.0",
- "flag_ma": "6.0",
- "ma": "6.0",
- "flag_mc": "6.0",
- "mc": "6.0",
- "flag_md": "6.0",
- "md": "6.0",
- "flag_me": "6.0",
- "me": "6.0",
- "flag_mf": "6.0",
- "mf": "6.0",
- "flag_mg": "6.0",
- "mg": "6.0",
- "flag_mh": "6.0",
- "mh": "6.0",
- "flag_mk": "6.0",
- "mk": "6.0",
- "flag_ml": "6.0",
- "ml": "6.0",
- "flag_mm": "6.0",
- "mm": "6.0",
- "flag_mn": "6.0",
- "mn": "6.0",
- "flag_mo": "6.0",
- "mo": "6.0",
- "flag_mp": "6.0",
- "mp": "6.0",
- "flag_mq": "6.0",
- "mq": "6.0",
- "flag_mr": "6.0",
- "mr": "6.0",
- "flag_ms": "6.0",
- "ms": "6.0",
- "flag_mt": "6.0",
- "mt": "6.0",
- "flag_mu": "6.0",
- "mu": "6.0",
- "flag_mv": "6.0",
- "mv": "6.0",
- "flag_mw": "6.0",
- "mw": "6.0",
- "flag_mx": "6.0",
- "mx": "6.0",
- "flag_my": "6.0",
- "my": "6.0",
- "flag_mz": "6.0",
- "mz": "6.0",
- "flag_na": "6.0",
- "na": "6.0",
- "flag_nc": "6.0",
- "nc": "6.0",
- "flag_ne": "6.0",
- "ne": "6.0",
- "flag_nf": "6.0",
- "nf": "6.0",
- "flag_ng": "6.0",
- "nigeria": "6.0",
- "flag_ni": "6.0",
- "ni": "6.0",
- "flag_nl": "6.0",
- "nl": "6.0",
- "flag_no": "6.0",
- "no": "6.0",
- "flag_np": "6.0",
- "np": "6.0",
- "flag_nr": "6.0",
- "nr": "6.0",
- "flag_nu": "6.0",
- "nu": "6.0",
- "flag_nz": "6.0",
- "nz": "6.0",
- "flag_om": "6.0",
- "om": "6.0",
- "flag_pa": "6.0",
- "pa": "6.0",
- "flag_pe": "6.0",
- "pe": "6.0",
- "flag_pf": "6.0",
- "pf": "6.0",
- "flag_pg": "6.0",
- "pg": "6.0",
- "flag_ph": "6.0",
- "ph": "6.0",
- "flag_pk": "6.0",
- "pk": "6.0",
- "flag_pl": "6.0",
- "pl": "6.0",
- "flag_pm": "6.0",
- "pm": "6.0",
- "flag_pn": "6.0",
- "pn": "6.0",
- "flag_pr": "6.0",
- "pr": "6.0",
- "flag_ps": "6.0",
- "ps": "6.0",
- "flag_pt": "6.0",
- "pt": "6.0",
- "flag_pw": "6.0",
- "pw": "6.0",
- "flag_py": "6.0",
- "py": "6.0",
- "flag_qa": "6.0",
- "qa": "6.0",
- "flag_re": "6.0",
- "re": "6.0",
- "flag_ro": "6.0",
- "ro": "6.0",
- "flag_rs": "6.0",
- "rs": "6.0",
- "flag_ru": "6.0",
- "ru": "6.0",
- "flag_rw": "6.0",
- "rw": "6.0",
- "flag_sa": "6.0",
- "saudiarabia": "6.0",
- "saudi": "6.0",
- "flag_sb": "6.0",
- "sb": "6.0",
- "flag_sc": "6.0",
- "sc": "6.0",
- "flag_sd": "6.0",
- "sd": "6.0",
- "flag_se": "6.0",
- "se": "6.0",
- "flag_sg": "6.0",
- "sg": "6.0",
- "flag_sh": "6.0",
- "sh": "6.0",
- "flag_si": "6.0",
- "si": "6.0",
- "flag_sj": "6.0",
- "sj": "6.0",
- "flag_sk": "6.0",
- "sk": "6.0",
- "flag_sl": "6.0",
- "sl": "6.0",
- "flag_sm": "6.0",
- "sm": "6.0",
- "flag_sn": "6.0",
- "sn": "6.0",
- "flag_so": "6.0",
- "so": "6.0",
- "flag_sr": "6.0",
- "sr": "6.0",
- "flag_ss": "6.0",
- "ss": "6.0",
- "flag_st": "6.0",
- "st": "6.0",
- "flag_sv": "6.0",
- "sv": "6.0",
- "flag_sx": "6.0",
- "sx": "6.0",
- "flag_sy": "6.0",
- "sy": "6.0",
- "flag_sz": "6.0",
- "sz": "6.0",
- "flag_ta": "6.0",
- "ta": "6.0",
- "flag_tc": "6.0",
- "tc": "6.0",
- "flag_td": "6.0",
- "td": "6.0",
- "flag_tf": "6.0",
- "tf": "6.0",
- "flag_tg": "6.0",
- "tg": "6.0",
- "flag_th": "6.0",
- "th": "6.0",
- "flag_tj": "6.0",
- "tj": "6.0",
- "flag_tk": "6.0",
- "tk": "6.0",
- "flag_tl": "6.0",
- "tl": "6.0",
- "flag_tm": "6.0",
- "turkmenistan": "6.0",
- "flag_tn": "6.0",
- "tn": "6.0",
- "flag_to": "6.0",
- "to": "6.0",
- "flag_tr": "6.0",
- "tr": "6.0",
- "flag_tt": "6.0",
- "tt": "6.0",
- "flag_tv": "6.0",
- "tuvalu": "6.0",
- "flag_tw": "6.0",
- "tw": "6.0",
- "flag_tz": "6.0",
- "tz": "6.0",
- "flag_ua": "6.0",
- "ua": "6.0",
- "flag_ug": "6.0",
- "ug": "6.0",
- "flag_um": "6.0",
- "um": "6.0",
- "flag_us": "6.0",
- "us": "6.0",
- "flag_uy": "6.0",
- "uy": "6.0",
- "flag_uz": "6.0",
- "uz": "6.0",
- "flag_va": "6.0",
- "va": "6.0",
- "flag_vc": "6.0",
- "vc": "6.0",
- "flag_ve": "6.0",
- "ve": "6.0",
- "flag_vg": "6.0",
- "vg": "6.0",
- "flag_vi": "6.0",
- "vi": "6.0",
- "flag_vn": "6.0",
- "vn": "6.0",
- "flag_vu": "6.0",
- "vu": "6.0",
- "flag_wf": "6.0",
- "wf": "6.0",
- "flag_ws": "6.0",
- "ws": "6.0",
- "flag_xk": "6.0",
- "xk": "6.0",
- "flag_ye": "6.0",
- "ye": "6.0",
- "flag_yt": "6.0",
- "yt": "6.0",
- "flag_za": "6.0",
- "za": "6.0",
- "flag_zm": "6.0",
- "zm": "6.0",
- "flag_zw": "6.0",
- "zw": "6.0",
- "regional_indicator_z": "6.0",
- "regional_indicator_y": "6.0",
- "regional_indicator_x": "6.0",
- "regional_indicator_w": "6.0",
- "regional_indicator_v": "6.0",
- "regional_indicator_u": "6.0",
- "regional_indicator_t": "6.0",
- "regional_indicator_s": "6.0",
- "regional_indicator_r": "6.0",
- "regional_indicator_q": "6.0",
- "regional_indicator_p": "6.0",
- "regional_indicator_o": "6.0",
- "regional_indicator_n": "6.0",
- "regional_indicator_m": "6.0",
- "regional_indicator_l": "6.0",
- "regional_indicator_k": "6.0",
- "regional_indicator_j": "6.0",
- "regional_indicator_i": "6.0",
- "regional_indicator_h": "6.0",
- "regional_indicator_g": "6.0",
- "regional_indicator_f": "6.0",
- "regional_indicator_e": "6.0",
- "regional_indicator_d": "6.0",
- "regional_indicator_c": "6.0",
- "regional_indicator_b": "6.0",
- "regional_indicator_a": "6.0",
- "large_blue_circle": "6.0",
- "ten": "6.0"
-} \ No newline at end of file
diff --git a/generator_templates/usage_metric_definition/metric_definition.yml b/generator_templates/usage_metric_definition/metric_definition.yml
index 9ce03bdb7b4..c094d6d3d88 100644
--- a/generator_templates/usage_metric_definition/metric_definition.yml
+++ b/generator_templates/usage_metric_definition/metric_definition.yml
@@ -1,5 +1,5 @@
---
-key_path: <%= key_path %><%= metric_name_suggestion %>
+key_path: <%= args.second %><%= metric_name_suggestion(args.second) %>
description:
product_section:
product_stage:
diff --git a/jest.config.base.js b/jest.config.base.js
index 7cf1136a073..d1478987fb8 100644
--- a/jest.config.base.js
+++ b/jest.config.base.js
@@ -54,6 +54,7 @@ module.exports = (path, options = {}) => {
'^helpers(/.*)$': '<rootDir>/spec/frontend/__helpers__$1',
'^vendor(/.*)$': '<rootDir>/vendor/assets/javascripts$1',
[TEST_FIXTURES_PATTERN]: '<rootDir>/tmp/tests/frontend/fixtures$1',
+ '^test_fixtures_static(/.*)$': '<rootDir>/spec/frontend/fixtures/static$1',
'\\.(jpg|jpeg|png|svg|css)$': '<rootDir>/spec/frontend/__mocks__/file_mock.js',
'emojis(/.*).json': '<rootDir>/fixtures/emojis$1.json',
'^spec/test_constants$': '<rootDir>/spec/frontend/__helpers__/test_constants',
diff --git a/jest.config.integration.js b/jest.config.integration.js
index da8e813a2cb..184f88779c8 100644
--- a/jest.config.integration.js
+++ b/jest.config.integration.js
@@ -3,6 +3,13 @@ const baseConfig = require('./jest.config.base');
checkEnvironment();
+console.log(`
+PSA: Running into unexpected and/or strange frontend integration test errors?
+Please help improve our error logging by following the instructions on this issue:
+
+ https://gitlab.com/gitlab-org/gitlab/-/issues/345513
+`);
+
module.exports = {
...baseConfig('spec/frontend_integration', {
moduleNameMapper: {
diff --git a/jest.config.js b/jest.config.js
index 4d9e19abbaf..96a62b18d8f 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -1,5 +1,14 @@
+const fs = require('fs');
+const IS_JH = require('./config/helpers/is_jh_env');
const baseConfig = require('./jest.config.base');
-module.exports = {
- ...baseConfig('spec/frontend'),
-};
+// TODO: Remove existsSync once jh has added jest.config.js
+if (IS_JH && fs.existsSync('./jh/jest.config.js')) {
+ // We can't be explicit with eslint-disable rules because in JH it'll pass import/no-unresolved
+ // eslint-disable-next-line
+ module.exports = require('./jh/jest.config');
+} else {
+ module.exports = {
+ ...baseConfig('spec/frontend'),
+ };
+}
diff --git a/lefthook.yml b/lefthook.yml
index 55027f6bf59..c5c51b53fb3 100644
--- a/lefthook.yml
+++ b/lefthook.yml
@@ -33,6 +33,11 @@ pre-push:
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
glob: '*.rb'
run: REVEAL_RUBOCOP_TODO=0 bundle exec rubocop --parallel --force-exclusion {files}
+ graphql_docs:
+ tags: documentation
+ files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
+ glob: '{app/graphql/**/*.rb,ee/app/graphql/**/*.rb}'
+ run: bundle exec rake gitlab:graphql:check_docs
vale: # Requires Vale: https://docs.gitlab.com/ee/development/documentation/#install-linters
tags: documentation style
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
diff --git a/lib/after_commit_queue.rb b/lib/after_commit_queue.rb
index 2698d7adbd7..cbeaea97951 100644
--- a/lib/after_commit_queue.rb
+++ b/lib/after_commit_queue.rb
@@ -15,7 +15,7 @@ module AfterCommitQueue
end
def run_after_commit_or_now(&block)
- if Gitlab::Database.main.inside_transaction?
+ if ApplicationRecord.inside_transaction?
if ActiveRecord::Base.connection.current_transaction.records&.include?(self)
run_after_commit(&block)
else
diff --git a/lib/api/api.rb b/lib/api/api.rb
index a4d42c735cb..dcecaeae558 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -27,7 +27,8 @@ module API
Gitlab::GrapeLogging::Loggers::PerfLogger.new,
Gitlab::GrapeLogging::Loggers::CorrelationIdLogger.new,
Gitlab::GrapeLogging::Loggers::ContextLogger.new,
- Gitlab::GrapeLogging::Loggers::ContentLogger.new
+ Gitlab::GrapeLogging::Loggers::ContentLogger.new,
+ Gitlab::GrapeLogging::Loggers::UrgencyLogger.new
]
allow_access_with_scope :api
@@ -283,6 +284,7 @@ module API
mount ::API::Tags
mount ::API::Templates
mount ::API::Todos
+ mount ::API::Topics
mount ::API::Unleash
mount ::API::UsageData
mount ::API::UsageDataQueries
diff --git a/lib/api/boards.rb b/lib/api/boards.rb
index 9e829dd5e05..56633c07774 100644
--- a/lib/api/boards.rb
+++ b/lib/api/boards.rb
@@ -7,7 +7,7 @@ module API
prepend_mod_with('API::BoardsResponses') # rubocop: disable Cop/InjectEnterpriseEditionModule
- feature_category :boards
+ feature_category :team_planning
before { authenticate! }
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 0db5bb82296..462c4a3de4c 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -41,7 +41,7 @@ module API
optional :page_token, type: String, desc: 'Name of branch to start the paginaition from'
end
- get ':id/repository/branches' do
+ get ':id/repository/branches', urgency: :low do
ff_enabled = Feature.enabled?(:api_caching_rate_limit_branches, user_project, default_enabled: :yaml)
cache_action_if(ff_enabled, [user_project, :branches, current_user, declared_params], expires_in: 30.seconds) do
@@ -86,7 +86,7 @@ module API
head do
user_project.repository.branch_exists?(params[:branch]) ? no_content! : not_found!
end
- get do
+ get '/', urgency: :low do
branch = find_branch!(params[:branch])
present branch, with: Entities::Branch, current_user: current_user, project: user_project
diff --git a/lib/api/ci/jobs.rb b/lib/api/ci/jobs.rb
index eea1637c32a..30ce1454419 100644
--- a/lib/api/ci/jobs.rb
+++ b/lib/api/ci/jobs.rb
@@ -177,6 +177,39 @@ module API
present current_authenticated_job, with: Entities::Ci::Job
end
+
+ desc 'Get current agents' do
+ detail 'Retrieves a list of agents for the given job token'
+ end
+ route_setting :authentication, job_token_allowed: true
+ get '/allowed_agents', feature_category: :kubernetes_management do
+ validate_current_authenticated_job
+
+ status 200
+
+ pipeline = current_authenticated_job.pipeline
+ project = current_authenticated_job.project
+ agent_authorizations = Clusters::AgentAuthorizationsFinder.new(project).execute
+ project_groups = project.group&.self_and_ancestor_ids&.map { |id| { id: id } } || []
+ user_access_level = project.team.max_member_access(current_user.id)
+ roles_in_project = Gitlab::Access.sym_options_with_owner
+ .select { |_role, role_access_level| role_access_level <= user_access_level }
+ .map(&:first)
+
+ environment = if environment_slug = current_authenticated_job.deployment&.environment&.slug
+ { slug: environment_slug }
+ end
+
+ # See https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/kubernetes_ci_access.md#apiv4joballowed_agents-api
+ {
+ allowed_agents: Entities::Clusters::AgentAuthorization.represent(agent_authorizations),
+ job: { id: current_authenticated_job.id },
+ pipeline: { id: pipeline.id },
+ project: { id: project.id, groups: project_groups },
+ user: { id: current_user.id, username: current_user.username, roles_in_project: roles_in_project },
+ environment: environment
+ }.compact
+ end
end
helpers do
@@ -202,5 +235,3 @@ module API
end
end
end
-
-API::Ci::Jobs.prepend_mod_with('API::Ci::Jobs')
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index 10dc51556b9..8b8d8192524 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -27,7 +27,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS, urgency: :low do
desc 'Get a project repository commits' do
success Entities::Commit
end
@@ -43,7 +43,7 @@ module API
optional :trailers, type: Boolean, desc: 'Parse and include Git trailers for every commit', default: false
use :pagination
end
- get ':id/repository/commits' do
+ get ':id/repository/commits', urgency: :low do
path = params[:path]
before = params[:until]
after = params[:since]
@@ -169,7 +169,7 @@ module API
requires :sha, type: String, desc: 'A commit sha, or the name of a branch or tag'
use :pagination
end
- get ':id/repository/commits/:sha/diff', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
+ get ':id/repository/commits/:sha/diff', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS, urgency: :low do
commit = user_project.commit(params[:sha])
not_found! 'Commit' unless commit
@@ -295,7 +295,7 @@ module API
optional :type, type: String, values: %w[branch tag all], default: 'all', desc: 'Scope'
use :pagination
end
- get ':id/repository/commits/:sha/refs', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
+ get ':id/repository/commits/:sha/refs', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS, urgency: :low do
commit = user_project.commit(params[:sha])
not_found!('Commit') unless commit
@@ -363,7 +363,7 @@ module API
requires :sha, type: String, desc: 'A commit sha, or the name of a branch or tag on which to find Merge Requests'
use :pagination
end
- get ':id/repository/commits/:sha/merge_requests', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
+ get ':id/repository/commits/:sha/merge_requests', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS, urgency: :low do
authorize! :read_merge_request, user_project
commit = user_project.commit(params[:sha])
diff --git a/lib/api/concerns/packages/debian_distribution_endpoints.rb b/lib/api/concerns/packages/debian_distribution_endpoints.rb
index 798e583b87a..ddc83d0f747 100644
--- a/lib/api/concerns/packages/debian_distribution_endpoints.rb
+++ b/lib/api/concerns/packages/debian_distribution_endpoints.rb
@@ -15,6 +15,12 @@ module API
helpers ::API::Helpers::Packages::BasicAuthHelpers
include ::API::Helpers::Authentication
+ helpers do
+ def distribution
+ ::Packages::Debian::DistributionsFinder.new(project_or_group, codename: params[:codename]).execute.last || not_found!('Distribution')
+ end
+ end
+
namespace 'debian_distributions' do
helpers do
params :optional_distribution_params do
@@ -36,9 +42,18 @@ module API
end
end
+ rescue_from ArgumentError do |e|
+ render_api_error!(e.message, 400)
+ end
+
+ rescue_from ActiveRecord::RecordInvalid do |e|
+ render_api_error!(e.message, 400)
+ end
+
authenticate_with do |accept|
- accept.token_types(:personal_access_token, :deploy_token, :job_token)
- .sent_through(:http_basic_auth)
+ accept.token_types(:personal_access_token).sent_through(:http_private_token_header)
+ accept.token_types(:deploy_token).sent_through(:http_deploy_token_header)
+ accept.token_types(:job_token).sent_through(:http_job_token_header)
end
content_type :json, 'application/json'
@@ -59,12 +74,12 @@ module API
distribution_params = declared_params(include_missing: false)
result = ::Packages::Debian::CreateDistributionService.new(project_or_group, current_user, distribution_params).execute
- distribution = result.payload[:distribution]
+ created_distribution = result.payload[:distribution]
if result.success?
- present distribution, with: ::API::Entities::Packages::Debian::Distribution
+ present created_distribution, with: ::API::Entities::Packages::Debian::Distribution
else
- render_validation_error!(distribution)
+ render_validation_error!(created_distribution)
end
end
@@ -100,11 +115,28 @@ module API
get '/:codename' do
authorize_read_package!(project_or_group)
- distribution = ::Packages::Debian::DistributionsFinder.new(project_or_group, codename: params[:codename]).execute.last!
-
present distribution, with: ::API::Entities::Packages::Debian::Distribution
end
+ # GET {projects|groups}/:id/debian_distributions/:codename/key
+ desc 'Get a Debian Distribution Key' do
+ detail 'This feature was introduced in 14.4'
+ success ::API::Entities::Packages::Debian::Distribution
+ end
+
+ params do
+ requires :codename, type: String, regexp: Gitlab::Regex.debian_distribution_regex, desc: 'The Debian Codename'
+ end
+ get '/:codename/key.asc' do
+ authorize_read_package!(project_or_group)
+
+ content_type 'text/plain'
+ env['api.format'] = :binary
+ header 'Content-Disposition', "attachment; filename*=UTF-8''#{CGI.escape(params[:codename])}.asc"
+
+ distribution.key&.public_key || not_found!('Distribution key')
+ end
+
# PUT {projects|groups}/:id/debian_distributions/:codename
desc 'Update a Debian Distribution' do
detail 'This feature was introduced in 14.0'
@@ -118,15 +150,14 @@ module API
put '/:codename' do
authorize_create_package!(project_or_group)
- distribution = ::Packages::Debian::DistributionsFinder.new(project_or_group, codename: params[:codename]).execute.last!
distribution_params = declared_params(include_missing: false).except(:codename)
result = ::Packages::Debian::UpdateDistributionService.new(distribution, distribution_params).execute
- distribution = result.payload[:distribution]
+ updated_distribution = result.payload[:distribution]
if result.success?
- present distribution, with: ::API::Entities::Packages::Debian::Distribution
+ present updated_distribution, with: ::API::Entities::Packages::Debian::Distribution
else
- render_validation_error!(distribution)
+ render_validation_error!(updated_distribution)
end
end
@@ -142,8 +173,6 @@ module API
delete '/:codename' do
authorize_destroy_package!(project_or_group)
- distribution = ::Packages::Debian::DistributionsFinder.new(project_or_group, codename: params[:codename]).execute.last!
-
accepted! if distribution.destroy
render_api_error!('Failed to delete distribution', 400)
diff --git a/lib/api/concerns/packages/debian_package_endpoints.rb b/lib/api/concerns/packages/debian_package_endpoints.rb
index 0acc015f366..d083643f3d0 100644
--- a/lib/api/concerns/packages/debian_package_endpoints.rb
+++ b/lib/api/concerns/packages/debian_package_endpoints.rb
@@ -43,11 +43,6 @@ module API
end
end
- authenticate_with do |accept|
- accept.token_types(:personal_access_token, :deploy_token, :job_token)
- .sent_through(:http_basic_auth)
- end
-
rescue_from ArgumentError do |e|
render_api_error!(e.message, 400)
end
@@ -56,6 +51,11 @@ module API
render_api_error!(e.message, 400)
end
+ authenticate_with do |accept|
+ accept.token_types(:personal_access_token, :deploy_token, :job_token)
+ .sent_through(:http_basic_auth)
+ end
+
format :txt
content_type :txt, 'text/plain'
diff --git a/lib/api/concerns/packages/npm_endpoints.rb b/lib/api/concerns/packages/npm_endpoints.rb
index d6e006df976..7a657be5bf3 100644
--- a/lib/api/concerns/packages/npm_endpoints.rb
+++ b/lib/api/concerns/packages/npm_endpoints.rb
@@ -121,7 +121,9 @@ module API
not_found!('Packages') if packages.empty?
- present ::Packages::Npm::PackagePresenter.new(package_name, packages),
+ include_metadata = Feature.enabled?(:packages_npm_abbreviated_metadata, project, default_enabled: :yaml)
+
+ present ::Packages::Npm::PackagePresenter.new(package_name, packages, include_metadata: include_metadata),
with: ::API::Entities::NpmPackage
end
end
diff --git a/lib/api/debian_group_packages.rb b/lib/api/debian_group_packages.rb
index 29f5047230a..1f640cc17d0 100644
--- a/lib/api/debian_group_packages.rb
+++ b/lib/api/debian_group_packages.rb
@@ -32,7 +32,7 @@ module API
namespace ':id/-/packages/debian' do
include ::API::Concerns::Packages::DebianPackageEndpoints
- # GET groups/:id/packages/debian/pool/:distribution/:project_id/:letter/:package_name/:package_version/:file_name
+ # GET groups/:id/-/packages/debian/pool/:distribution/:project_id/:letter/:package_name/:package_version/:file_name
params do
requires :project_id, type: Integer, desc: 'The Project Id'
use :shared_package_file_params
diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb
index 9f0f569b711..0ab9fe6644c 100644
--- a/lib/api/deploy_keys.rb
+++ b/lib/api/deploy_keys.rb
@@ -23,11 +23,14 @@ module API
desc 'Return all deploy keys'
params do
use :pagination
+ optional :public, type: Boolean, default: false, desc: "Only return deploy keys that are public"
end
get "deploy_keys" do
authenticated_as_admin!
- present paginate(DeployKey.all), with: Entities::DeployKey
+ deploy_keys = params[:public] ? DeployKey.are_public : DeployKey.all
+
+ present paginate(deploy_keys.including_projects_with_write_access), with: Entities::DeployKey, include_projects_with_write_access: true
end
params do
diff --git a/lib/api/discussions.rb b/lib/api/discussions.rb
index 580d546b360..cf4b2348458 100644
--- a/lib/api/discussions.rb
+++ b/lib/api/discussions.rb
@@ -239,7 +239,7 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def readable_discussion_notes(noteable, discussion_ids)
notes = noteable.notes
- .where(discussion_id: discussion_ids)
+ .with_discussion_ids(discussion_ids)
.inc_relations_for_view
.includes(:noteable)
.fresh
diff --git a/lib/api/entities/alert_management/alert.rb b/lib/api/entities/alert_management/alert.rb
new file mode 100644
index 00000000000..664cd53293e
--- /dev/null
+++ b/lib/api/entities/alert_management/alert.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module AlertManagement
+ class Alert < Grape::Entity
+ expose :iid
+ expose :title
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/ci/job_request/service.rb b/lib/api/entities/ci/job_request/service.rb
index f89b95c1d5c..0dae5d5a933 100644
--- a/lib/api/entities/ci/job_request/service.rb
+++ b/lib/api/entities/ci/job_request/service.rb
@@ -6,6 +6,7 @@ module API
module JobRequest
class Service < Entities::Ci::JobRequest::Image
expose :alias, :command
+ expose :variables
end
end
end
diff --git a/lib/api/entities/ci/lint/result.rb b/lib/api/entities/ci/lint/result.rb
index 0e4aa238ba2..39039868bba 100644
--- a/lib/api/entities/ci/lint/result.rb
+++ b/lib/api/entities/ci/lint/result.rb
@@ -9,6 +9,7 @@ module API
expose :errors
expose :warnings
expose :merged_yaml
+ expose :jobs, if: -> (result, options) { options[:include_jobs] }
end
end
end
diff --git a/lib/api/entities/ci/runner.rb b/lib/api/entities/ci/runner.rb
index ede698696de..60193fe1df4 100644
--- a/lib/api/entities/ci/runner.rb
+++ b/lib/api/entities/ci/runner.rb
@@ -12,7 +12,9 @@ module API
expose :runner_type
expose :name
expose :online?, as: :online
- expose :status
+ # DEPRECATED
+ # TODO Remove in %15.0 in favor of `status` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/344648
+ expose :status, as: :deprecated_rest_status
end
end
end
diff --git a/lib/api/entities/ci/runner_details.rb b/lib/api/entities/ci/runner_details.rb
index 9d44da7e5b3..6ded1296f2a 100644
--- a/lib/api/entities/ci/runner_details.rb
+++ b/lib/api/entities/ci/runner_details.rb
@@ -15,18 +15,18 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
expose :projects, with: Entities::BasicProjectDetails do |runner, options|
if options[:current_user].admin? # rubocop: disable Cop/UserAdmin
- runner.projects
+ runner.projects.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
else
- options[:current_user].authorized_projects.where(id: runner.projects)
+ options[:current_user].authorized_projects.where(id: runner.projects).allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
end
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
expose :groups, with: Entities::BasicGroupDetails do |runner, options|
if options[:current_user].admin? # rubocop: disable Cop/UserAdmin
- runner.groups
+ runner.groups.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
else
- options[:current_user].authorized_groups.where(id: runner.groups)
+ options[:current_user].authorized_groups.where(id: runner.groups).allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338659')
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/api/entities/deploy_key.rb b/lib/api/entities/deploy_key.rb
index ed922c24eda..e8537c4c677 100644
--- a/lib/api/entities/deploy_key.rb
+++ b/lib/api/entities/deploy_key.rb
@@ -4,6 +4,9 @@ module API
module Entities
class DeployKey < Entities::SSHKey
expose :key
+ expose :fingerprint
+
+ expose :projects_with_write_access, using: Entities::ProjectIdentity, if: -> (_, options) { options[:include_projects_with_write_access] }
end
end
end
diff --git a/lib/api/entities/group.rb b/lib/api/entities/group.rb
index 048b7a3c15a..246fb819890 100644
--- a/lib/api/entities/group.rb
+++ b/lib/api/entities/group.rb
@@ -31,7 +31,10 @@ module API
expose :wiki_size
expose :lfs_objects_size
expose :build_artifacts_size, as: :job_artifacts_size
+ expose :pipeline_artifacts_size
+ expose :packages_size
expose :snippets_size
+ expose :uploads_size
end
end
end
diff --git a/lib/api/entities/project.rb b/lib/api/entities/project.rb
index 41320d184f9..e3f1e90b80f 100644
--- a/lib/api/entities/project.rb
+++ b/lib/api/entities/project.rb
@@ -114,6 +114,7 @@ module API
expose :merge_method
expose :squash_option
expose :suggestion_commit_message
+ expose :merge_commit_template
expose :statistics, using: 'API::Entities::ProjectStatistics', if: -> (project, options) {
options[:statistics] && Ability.allowed?(options[:current_user], :read_statistics, project)
}
diff --git a/lib/api/entities/project_statistics.rb b/lib/api/entities/project_statistics.rb
index 70980e670b0..6544e8bc8ff 100644
--- a/lib/api/entities/project_statistics.rb
+++ b/lib/api/entities/project_statistics.rb
@@ -9,8 +9,10 @@ module API
expose :wiki_size
expose :lfs_objects_size
expose :build_artifacts_size, as: :job_artifacts_size
- expose :snippets_size
+ expose :pipeline_artifacts_size
expose :packages_size
+ expose :snippets_size
+ expose :uploads_size
end
end
end
diff --git a/lib/api/entities/projects/topic.rb b/lib/api/entities/projects/topic.rb
new file mode 100644
index 00000000000..d3d1cbec81c
--- /dev/null
+++ b/lib/api/entities/projects/topic.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Projects
+ class Topic < Grape::Entity
+ expose :id
+ expose :name
+ expose :description
+ expose :total_projects_count
+ expose :avatar_url do |topic, options|
+ topic.avatar_url(only_path: false)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/todo.rb b/lib/api/entities/todo.rb
index 8d222db488a..5bbbb59f565 100644
--- a/lib/api/entities/todo.rb
+++ b/lib/api/entities/todo.rb
@@ -33,7 +33,7 @@ module API
def todo_target_url(todo)
return design_todo_target_url(todo) if todo.for_design?
- target_type = todo.target_type.underscore
+ target_type = todo.target_type.gsub('::', '_').underscore
target_url = "#{todo.resource_parent.class.to_s.underscore}_#{target_type}_url"
Gitlab::Routing
diff --git a/lib/api/error_tracking/collector.rb b/lib/api/error_tracking/collector.rb
index 22fbd3a1118..13fda356257 100644
--- a/lib/api/error_tracking/collector.rb
+++ b/lib/api/error_tracking/collector.rb
@@ -12,6 +12,10 @@ module API
content_type :txt, 'text/plain'
default_format :envelope
+ rescue_from ActiveRecord::RecordInvalid do |e|
+ render_api_error!(e.message, 400)
+ end
+
before do
not_found!('Project') unless project
not_found! unless feature_enabled?
@@ -50,6 +54,12 @@ module API
bad_request!('Failed to parse sentry request')
end
end
+
+ def validate_payload(payload)
+ unless ::ErrorTracking::Collector::PayloadValidator.new.valid?(payload)
+ bad_request!('Unsupported sentry payload')
+ end
+ end
end
desc 'Submit error tracking event to the project as envelope' do
@@ -88,6 +98,8 @@ module API
# We don't have use for transaction request yet,
# so we record only event one.
if type == 'event'
+ validate_payload(parsed_request[:event])
+
::ErrorTracking::CollectErrorService
.new(project, nil, event: parsed_request[:event])
.execute
@@ -96,7 +108,10 @@ module API
# Collector should never return any information back.
# Because DSN and public key are designed for public use,
# it is safe only for submission of new events.
- no_content!
+ #
+ # Some clients sdk require status 200 OK to work correctly.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/343531.
+ status 200
end
desc 'Submit error tracking event to the project' do
@@ -122,6 +137,8 @@ module API
bad_request!('Failed to parse sentry request')
end
+ validate_payload(parsed_body)
+
::ErrorTracking::CollectErrorService
.new(project, nil, event: parsed_body)
.execute
@@ -129,7 +146,10 @@ module API
# Collector should never return any information back.
# Because DSN and public key are designed for public use,
# it is safe only for submission of new events.
- no_content!
+ #
+ # Some clients sdk require status 200 OK to work correctly.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/343531.
+ status 200
end
end
end
diff --git a/lib/api/features.rb b/lib/api/features.rb
index 2ce2f7c518f..398e57794c8 100644
--- a/lib/api/features.rb
+++ b/lib/api/features.rb
@@ -14,7 +14,12 @@ module API
when '0', 'false'
false
else
- params[:value].to_i
+ # https://github.com/jnunemaker/flipper/blob/master/lib/flipper/typecast.rb#L47
+ if params[:value].to_s.include?('.')
+ params[:value].to_f
+ else
+ params[:value].to_i
+ end
end
end
@@ -59,7 +64,7 @@ module API
success Entities::Feature
end
params do
- requires :value, type: String, desc: '`true` or `false` to enable/disable, an integer for percentage of time'
+ requires :value, type: String, desc: '`true` or `false` to enable/disable, a float for percentage of time'
optional :key, type: String, desc: '`percentage_of_actors` or the default `percentage_of_time`'
optional :feature_group, type: String, desc: 'A Feature group name'
optional :user, type: String, desc: 'A GitLab username'
diff --git a/lib/api/files.rb b/lib/api/files.rb
index 9d2b7cce837..39b3904ec90 100644
--- a/lib/api/files.rb
+++ b/lib/api/files.rb
@@ -122,7 +122,7 @@ module API
requires :file_path, type: String, file_path: true, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
optional :ref, type: String, desc: 'The name of branch, tag or commit', allow_blank: false
end
- head ":id/repository/files/:file_path/raw", requirements: FILE_ENDPOINT_REQUIREMENTS do
+ head ":id/repository/files/:file_path/raw", requirements: FILE_ENDPOINT_REQUIREMENTS, urgency: :low do
assign_file_vars!
set_http_headers(blob_data)
@@ -133,7 +133,7 @@ module API
requires :file_path, type: String, file_path: true, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
optional :ref, type: String, desc: 'The name of branch, tag or commit', allow_blank: false
end
- get ":id/repository/files/:file_path/raw", requirements: FILE_ENDPOINT_REQUIREMENTS do
+ get ":id/repository/files/:file_path/raw", requirements: FILE_ENDPOINT_REQUIREMENTS, urgency: :low do
assign_file_vars!
no_cache_headers
@@ -147,7 +147,7 @@ module API
requires :file_path, type: String, file_path: true, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
requires :ref, type: String, desc: 'The name of branch, tag or commit', allow_blank: false
end
- head ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS do
+ head ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS, urgency: :low do
assign_file_vars!
set_http_headers(blob_data)
@@ -174,7 +174,7 @@ module API
params do
use :extended_file_params
end
- post ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS do
+ post ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS, urgency: :low do
authorize! :push_code, user_project
file_params = declared_params(include_missing: false)
@@ -192,7 +192,7 @@ module API
params do
use :extended_file_params
end
- put ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS do
+ put ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS, urgency: :low do
authorize! :push_code, user_project
file_params = declared_params(include_missing: false)
diff --git a/lib/api/generic_packages.rb b/lib/api/generic_packages.rb
index 5e184d35255..8cca3378eec 100644
--- a/lib/api/generic_packages.rb
+++ b/lib/api/generic_packages.rb
@@ -54,6 +54,7 @@ module API
requires :file_name, type: String, desc: 'Package file name', regexp: Gitlab::Regex.generic_package_file_name_regex, file_path: true
optional :status, type: String, values: ALLOWED_STATUSES, desc: 'Package status'
requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)'
+ optional :select, type: String, values: %w[package_file]
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
@@ -65,11 +66,15 @@ module API
track_package_event('push_package', :generic, project: project, user: current_user, namespace: project.namespace)
create_package_file_params = declared_params.merge(build: current_authenticated_job)
- ::Packages::Generic::CreatePackageFileService
+ package_file = ::Packages::Generic::CreatePackageFileService
.new(project, current_user, create_package_file_params)
.execute
- created!
+ if params[:select] == 'package_file'
+ present package_file
+ else
+ created!
+ end
rescue ObjectStorage::RemoteStoreError => e
Gitlab::ErrorTracking.track_exception(e, extra: { file_name: params[:file_name], project_id: project.id })
diff --git a/lib/api/github/entities.rb b/lib/api/github/entities.rb
index fe228c9a2d2..125985f0e23 100644
--- a/lib/api/github/entities.rb
+++ b/lib/api/github/entities.rb
@@ -59,8 +59,8 @@ module API
expose :parents do |commit|
commit.parent_ids.map { |id| { sha: id } }
end
- expose :files do |commit|
- commit.diffs.diff_files.flat_map do |diff|
+ expose :files do |_commit, options|
+ options[:diff_files].flat_map do |diff|
additions = diff.added_lines
deletions = diff.removed_lines
diff --git a/lib/api/group_boards.rb b/lib/api/group_boards.rb
index 92869f8fbba..e9350da555c 100644
--- a/lib/api/group_boards.rb
+++ b/lib/api/group_boards.rb
@@ -7,7 +7,7 @@ module API
prepend_mod_with('API::BoardsResponses') # rubocop: disable Cop/InjectEnterpriseEditionModule
- feature_category :boards
+ feature_category :team_planning
before { authenticate! }
diff --git a/lib/api/group_debian_distributions.rb b/lib/api/group_debian_distributions.rb
index 01a8774bd97..f0376fe2c9c 100644
--- a/lib/api/group_debian_distributions.rb
+++ b/lib/api/group_debian_distributions.rb
@@ -7,14 +7,6 @@ module API
end
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- rescue_from ArgumentError do |e|
- render_api_error!(e.message, 400)
- end
-
- rescue_from ActiveRecord::RecordInvalid do |e|
- render_api_error!(e.message, 400)
- end
-
after_validation do
require_packages_enabled!
diff --git a/lib/api/group_labels.rb b/lib/api/group_labels.rb
index bea538441ee..7c1f23be828 100644
--- a/lib/api/group_labels.rb
+++ b/lib/api/group_labels.rb
@@ -7,7 +7,7 @@ module API
before { authenticate! }
- feature_category :issue_tracking
+ feature_category :team_planning
params do
requires :id, type: String, desc: 'The ID of a group'
diff --git a/lib/api/group_milestones.rb b/lib/api/group_milestones.rb
index 061d0410a9c..b097022e9c1 100644
--- a/lib/api/group_milestones.rb
+++ b/lib/api/group_milestones.rb
@@ -7,7 +7,7 @@ module API
before { authenticate! }
- feature_category :issue_tracking
+ feature_category :team_planning
params do
requires :id, type: String, desc: 'The ID of a group'
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index f9ba5ba8186..76840091112 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -174,9 +174,9 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def find_namespace(id)
if id.to_s =~ /^\d+$/
- Namespace.find_by(id: id)
+ Namespace.without_project_namespaces.find_by(id: id)
else
- Namespace.find_by_full_path(id)
+ find_namespace_by_path(id)
end
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -186,7 +186,7 @@ module API
end
def find_namespace_by_path(path)
- Namespace.find_by_full_path(path)
+ Namespace.without_project_namespaces.find_by_full_path(path)
end
def find_namespace_by_path!(path)
@@ -488,7 +488,7 @@ module API
def handle_api_exception(exception)
if report_exception?(exception)
define_params_for_grape_middleware
- Gitlab::ApplicationContext.push(user: current_user)
+ Gitlab::ApplicationContext.push(user: current_user, remote_ip: request.ip)
Gitlab::ErrorTracking.track_exception(exception)
end
@@ -681,20 +681,27 @@ module API
def send_git_blob(repository, blob)
env['api.format'] = :txt
content_type 'text/plain'
+
header['Content-Disposition'] = ActionDispatch::Http::ContentDisposition.format(disposition: 'inline', filename: blob.name)
# Let Workhorse examine the content and determine the better content disposition
header[Gitlab::Workhorse::DETECT_HEADER] = "true"
header(*Gitlab::Workhorse.send_git_blob(repository, blob))
+
+ body ''
end
def send_git_archive(repository, **kwargs)
header(*Gitlab::Workhorse.send_git_archive(repository, **kwargs))
+
+ body ''
end
def send_artifacts_entry(file, entry)
header(*Gitlab::Workhorse.send_artifacts_entry(file, entry))
+
+ body ''
end
# The Grape Error Middleware only has access to `env` but not `params` nor
diff --git a/lib/api/helpers/award_emoji.rb b/lib/api/helpers/award_emoji.rb
index 5b659c4dde7..3ea35381c97 100644
--- a/lib/api/helpers/award_emoji.rb
+++ b/lib/api/helpers/award_emoji.rb
@@ -5,7 +5,7 @@ module API
module AwardEmoji
def self.awardables
[
- { type: 'issue', resource: :projects, find_by: :iid, feature_category: :issue_tracking },
+ { type: 'issue', resource: :projects, find_by: :iid, feature_category: :team_planning },
{ type: 'merge_request', resource: :projects, find_by: :iid, feature_category: :code_review },
{ type: 'snippet', resource: :projects, find_by: :id, feature_category: :snippets }
]
diff --git a/lib/api/helpers/discussions_helpers.rb b/lib/api/helpers/discussions_helpers.rb
index cb2feeda1e1..c94199b17bc 100644
--- a/lib/api/helpers/discussions_helpers.rb
+++ b/lib/api/helpers/discussions_helpers.rb
@@ -7,7 +7,7 @@ module API
# This is a method instead of a constant, allowing EE to more easily
# extend it.
{
- Issue => :issue_tracking,
+ Issue => :team_planning,
Snippet => :snippets,
MergeRequest => :code_review,
Commit => :code_review
diff --git a/lib/api/helpers/file_upload_helpers.rb b/lib/api/helpers/file_upload_helpers.rb
index dd551ec2976..751972b44f0 100644
--- a/lib/api/helpers/file_upload_helpers.rb
+++ b/lib/api/helpers/file_upload_helpers.rb
@@ -5,7 +5,7 @@ module API
module FileUploadHelpers
def file_is_valid?
filename = params[:file]&.original_filename
- filename && ImportExportUploader::EXTENSION_WHITELIST.include?(File.extname(filename).delete('.'))
+ filename && ImportExportUploader::EXTENSION_ALLOWLIST.include?(File.extname(filename).delete('.'))
end
def validate_file!
diff --git a/lib/api/helpers/integrations_helpers.rb b/lib/api/helpers/integrations_helpers.rb
index e0ef9099104..e7fdb6645a5 100644
--- a/lib/api/helpers/integrations_helpers.rb
+++ b/lib/api/helpers/integrations_helpers.rb
@@ -254,7 +254,7 @@ module API
type: Boolean,
desc: 'DEPRECATED: This parameter has no effect since SSL verification will always be enabled'
}
- ],
+ ],
'campfire' => [
{
required: true,
@@ -530,6 +530,14 @@ module API
desc: 'The Mattermost token'
}
],
+ 'shimo' => [
+ {
+ required: true,
+ name: :external_wiki_url,
+ type: String,
+ desc: 'Shimo workspace URL'
+ }
+ ],
'slack-slash-commands' => [
{
required: true,
@@ -768,7 +776,33 @@ module API
desc: 'The Webex Teams webhook. For example, https://api.ciscospark.com/v1/webhooks/incoming/...'
},
chat_notification_events
- ].flatten
+ ].flatten,
+ 'zentao' => [
+ {
+ required: true,
+ name: :url,
+ type: String,
+ desc: 'The base URL to the ZenTao instance web interface which is being linked to this GitLab project. For example, https://www.zentao.net'
+ },
+ {
+ required: false,
+ name: :api_url,
+ type: String,
+ desc: 'The base URL to the ZenTao instance API. Web URL value will be used if not set. For example, https://www.zentao.net'
+ },
+ {
+ required: true,
+ name: :api_token,
+ type: String,
+ desc: 'The API token created from ZenTao dashboard'
+ },
+ {
+ required: true,
+ name: :zentao_product_xid,
+ type: String,
+ desc: 'The product ID of ZenTao project'
+ }
+ ]
}
end
@@ -805,7 +839,8 @@ module API
::Integrations::Slack,
::Integrations::SlackSlashCommands,
::Integrations::Teamcity,
- ::Integrations::Youtrack
+ ::Integrations::Youtrack,
+ ::Integrations::Zentao
]
end
diff --git a/lib/api/helpers/notes_helpers.rb b/lib/api/helpers/notes_helpers.rb
index 356e4a98c97..45671b09be9 100644
--- a/lib/api/helpers/notes_helpers.rb
+++ b/lib/api/helpers/notes_helpers.rb
@@ -7,7 +7,7 @@ module API
def self.feature_category_per_noteable_type
{
- Issue => :issue_tracking,
+ Issue => :team_planning,
MergeRequest => :code_review,
Snippet => :snippets
}
diff --git a/lib/api/helpers/project_snapshots_helpers.rb b/lib/api/helpers/project_snapshots_helpers.rb
index 0b10641571a..4b48661eeca 100644
--- a/lib/api/helpers/project_snapshots_helpers.rb
+++ b/lib/api/helpers/project_snapshots_helpers.rb
@@ -11,6 +11,8 @@ module API
def send_git_snapshot(repository)
header(*Gitlab::Workhorse.send_git_snapshot(repository))
+
+ body ''
end
def snapshot_project
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index 30edbe91125..42d1c40dd11 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -61,6 +61,7 @@ module API
optional :printing_merge_request_link_enabled, type: Boolean, desc: 'Show link to create/view merge request when pushing from the command line'
optional :merge_method, type: String, values: %w(ff rebase_merge merge), desc: 'The merge method used when merging merge requests'
optional :suggestion_commit_message, type: String, desc: 'The commit message used to apply merge request suggestions'
+ optional :merge_commit_template, type: String, desc: 'Template used to create merge commit message'
optional :initialize_with_readme, type: Boolean, desc: "Initialize a project with a README.md"
optional :ci_default_git_depth, type: Integer, desc: 'Default number of revisions for shallow cloning'
optional :auto_devops_enabled, type: Boolean, desc: 'Flag indication if Auto DevOps is enabled'
@@ -160,6 +161,7 @@ module API
:wiki_access_level,
:avatar,
:suggestion_commit_message,
+ :merge_commit_template,
:repository_storage,
:compliance_framework_setting,
:packages_enabled,
@@ -178,6 +180,17 @@ module API
def filter_attributes_using_license!(attrs)
end
+
+ def validate_git_import_url!(import_url, import_enabled: true)
+ return if import_url.blank?
+ return unless import_enabled
+
+ result = Import::ValidateRemoteGitEndpointService.new(url: import_url).execute # network call
+
+ if result.error?
+ render_api_error!(result.message, 422)
+ end
+ end
end
end
end
diff --git a/lib/api/helpers/resource_label_events_helpers.rb b/lib/api/helpers/resource_label_events_helpers.rb
index 7e641130062..eeb68362c1d 100644
--- a/lib/api/helpers/resource_label_events_helpers.rb
+++ b/lib/api/helpers/resource_label_events_helpers.rb
@@ -7,7 +7,7 @@ module API
# This is a method instead of a constant, allowing EE to more easily
# extend it.
{
- Issue => :issue_tracking,
+ Issue => :team_planning,
MergeRequest => :code_review
}
end
diff --git a/lib/api/integrations.rb b/lib/api/integrations.rb
index 926cde340a0..bab8e556a73 100644
--- a/lib/api/integrations.rb
+++ b/lib/api/integrations.rb
@@ -153,7 +153,7 @@ module API
requires setting[:name], type: setting[:type], desc: setting[:desc]
end
end
- post "#{path}/#{integration_slug.underscore}/trigger" do
+ post "#{path}/#{integration_slug.underscore}/trigger", urgency: :low do
project = find_project(params[:id])
# This is not accurate, but done to prevent leakage of the project names
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
index dc9257ebd62..d8e39d089e4 100644
--- a/lib/api/internal/base.rb
+++ b/lib/api/internal/base.rb
@@ -145,7 +145,7 @@ module API
check_allowed(params)
end
- post "/lfs_authenticate", feature_category: :source_code_management do
+ post "/lfs_authenticate", feature_category: :source_code_management, urgency: :high do
not_found! unless container&.lfs_enabled?
status 200
diff --git a/lib/api/internal/lfs.rb b/lib/api/internal/lfs.rb
index 66baa4f1034..e94da8d34e0 100644
--- a/lib/api/internal/lfs.rb
+++ b/lib/api/internal/lfs.rb
@@ -24,7 +24,7 @@ module API
requires :oid, type: String, desc: 'The object ID to query'
requires :gl_repository, type: String, desc: "Project identifier (e.g. project-1)"
end
- get "/" do
+ get "/", urgency: :high do
lfs_object = find_lfs_object(params[:oid])
not_found! unless lfs_object
diff --git a/lib/api/invitations.rb b/lib/api/invitations.rb
index 5cade301d81..f7f5af07378 100644
--- a/lib/api/invitations.rb
+++ b/lib/api/invitations.rb
@@ -25,6 +25,8 @@ module API
optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
optional :invite_source, type: String, desc: 'Source that triggered the member creation process', default: 'invitations-api'
optional :areas_of_focus, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Areas the inviter wants the member to focus upon'
+ optional :tasks_to_be_done, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Tasks the inviter wants the member to do'
+ optional :tasks_project_id, type: Integer, desc: 'The project ID in which to create the task issues'
end
post ":id/invitations" do
params[:source] = find_source(source_type, params[:id])
diff --git a/lib/api/issue_links.rb b/lib/api/issue_links.rb
index 0b4f4e06d0b..98451afb12d 100644
--- a/lib/api/issue_links.rb
+++ b/lib/api/issue_links.rb
@@ -6,7 +6,7 @@ module API
before { authenticate! }
- feature_category :issue_tracking
+ feature_category :team_planning
params do
requires :id, type: String, desc: 'The ID of a project'
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 43e83bd58fe..9958526fa7f 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -7,7 +7,7 @@ module API
before { authenticate_non_get! }
- feature_category :issue_tracking
+ feature_category :team_planning
helpers do
params :negatable_issue_filter_params do
diff --git a/lib/api/labels.rb b/lib/api/labels.rb
index aa3746dae42..e3253d15c15 100644
--- a/lib/api/labels.rb
+++ b/lib/api/labels.rb
@@ -7,7 +7,7 @@ module API
before { authenticate! }
- feature_category :issue_tracking
+ feature_category :team_planning
LABEL_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(
name: API::NO_SLASH_URL_PART_REGEX,
diff --git a/lib/api/lint.rb b/lib/api/lint.rb
index fa871b4bc57..f1e19e9c3c5 100644
--- a/lib/api/lint.rb
+++ b/lib/api/lint.rb
@@ -9,6 +9,7 @@ module API
params do
requires :content, type: String, desc: 'Content of .gitlab-ci.yml'
optional :include_merged_yaml, type: Boolean, desc: 'Whether or not to include merged CI config yaml in the response'
+ optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response'
end
post '/lint' do
unauthorized! if (Gitlab::CurrentSettings.signup_disabled? || Gitlab::CurrentSettings.signup_limited?) && current_user.nil?
@@ -17,7 +18,7 @@ module API
.validate(params[:content], dry_run: false)
status 200
- Entities::Ci::Lint::Result.represent(result, current_user: current_user).serializable_hash.tap do |presented_result|
+ Entities::Ci::Lint::Result.represent(result, current_user: current_user, include_jobs: params[:include_jobs]).serializable_hash.tap do |presented_result|
presented_result[:status] = presented_result[:valid] ? 'valid' : 'invalid'
presented_result.delete(:merged_yaml) unless params[:include_merged_yaml]
end
@@ -30,6 +31,7 @@ module API
end
params do
optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
+ optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response'
end
get ':id/ci/lint' do
authorize! :download_code, user_project
@@ -39,7 +41,7 @@ module API
.new(project: user_project, current_user: current_user)
.validate(content, dry_run: params[:dry_run])
- present result, with: Entities::Ci::Lint::Result, current_user: current_user
+ present result, with: Entities::Ci::Lint::Result, current_user: current_user, include_jobs: params[:include_jobs]
end
end
@@ -50,6 +52,7 @@ module API
params do
requires :content, type: String, desc: 'Content of .gitlab-ci.yml'
optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
+ optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response'
end
post ':id/ci/lint' do
authorize! :create_pipeline, user_project
@@ -59,7 +62,7 @@ module API
.validate(params[:content], dry_run: params[:dry_run])
status 200
- present result, with: Entities::Ci::Lint::Result, current_user: current_user
+ present result, with: Entities::Ci::Lint::Result, current_user: current_user, include_jobs: params[:include_jobs]
end
end
end
diff --git a/lib/api/members.rb b/lib/api/members.rb
index 332520ccd26..f488c8c26fc 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -95,6 +95,8 @@ module API
optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
optional :invite_source, type: String, desc: 'Source that triggered the member creation process', default: 'members-api'
optional :areas_of_focus, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Areas the inviter wants the member to focus upon'
+ optional :tasks_to_be_done, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Tasks the inviter wants the member to do'
+ optional :tasks_project_id, type: Integer, desc: 'The project ID in which to create the task issues'
end
post ":id/members" do
diff --git a/lib/api/merge_request_approvals.rb b/lib/api/merge_request_approvals.rb
index 83150bb51ca..dd49624c74f 100644
--- a/lib/api/merge_request_approvals.rb
+++ b/lib/api/merge_request_approvals.rb
@@ -25,7 +25,7 @@ module API
# Examples:
# GET /projects/:id/merge_requests/:merge_request_iid/approvals
desc 'List approvals for merge request'
- get 'approvals' do
+ get 'approvals', urgency: :low do
not_found!("Merge Request") unless can?(current_user, :read_merge_request, user_project)
merge_request = find_merge_request_with_access(params[:merge_request_iid])
@@ -47,7 +47,7 @@ module API
use :ee_approval_params
end
- post 'approve' do
+ post 'approve', urgency: :low do
merge_request = find_merge_request_with_access(params[:merge_request_iid], :approve_merge_request)
check_sha_param!(params, merge_request)
@@ -63,7 +63,7 @@ module API
end
desc 'Remove an approval from a merge request'
- post 'unapprove' do
+ post 'unapprove', urgency: :low do
merge_request = find_merge_request_with_access(params[:merge_request_iid], :approve_merge_request)
success = ::MergeRequests::RemoveApprovalService
diff --git a/lib/api/namespaces.rb b/lib/api/namespaces.rb
index c2d839571a6..d2468fb1c2e 100644
--- a/lib/api/namespaces.rb
+++ b/lib/api/namespaces.rb
@@ -37,7 +37,7 @@ module API
namespaces = current_user.admin ? Namespace.all : current_user.namespaces(owned_only: owned_only)
- namespaces = namespaces.include_route
+ namespaces = namespaces.without_project_namespaces.include_route
namespaces = namespaces.include_gitlab_subscription_with_hosted_plan if Gitlab.ee?
@@ -70,7 +70,7 @@ module API
get ':namespace/exists', requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
namespace_path = params[:namespace]
- exists = Namespace.by_parent(params[:parent_id]).filter_by_path(namespace_path).exists?
+ exists = Namespace.without_project_namespaces.by_parent(params[:parent_id]).filter_by_path(namespace_path).exists?
suggestions = exists ? [Namespace.clean_path(namespace_path)] : []
present :exists, exists
diff --git a/lib/api/package_files.rb b/lib/api/package_files.rb
index 6d0c1f44a36..79ebf18ff27 100644
--- a/lib/api/package_files.rb
+++ b/lib/api/package_files.rb
@@ -28,7 +28,10 @@ module API
package = ::Packages::PackageFinder
.new(user_project, params[:package_id]).execute
- present paginate(package.package_files), with: ::API::Entities::PackageFile
+ files = package.package_files
+ .preload_pipelines
+
+ present paginate(files), with: ::API::Entities::PackageFile
end
desc 'Remove a package file' do
diff --git a/lib/api/project_debian_distributions.rb b/lib/api/project_debian_distributions.rb
index f057251fb6b..2ba1ff85adb 100644
--- a/lib/api/project_debian_distributions.rb
+++ b/lib/api/project_debian_distributions.rb
@@ -7,14 +7,6 @@ module API
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- rescue_from ArgumentError do |e|
- render_api_error!(e.message, 400)
- end
-
- rescue_from ActiveRecord::RecordInvalid do |e|
- render_api_error!(e.message, 400)
- end
-
after_validation do
require_packages_enabled!
diff --git a/lib/api/project_milestones.rb b/lib/api/project_milestones.rb
index 107311ea446..435e4bed776 100644
--- a/lib/api/project_milestones.rb
+++ b/lib/api/project_milestones.rb
@@ -7,7 +7,7 @@ module API
before { authenticate! }
- feature_category :issue_tracking
+ feature_category :team_planning
params do
requires :id, type: String, desc: 'The ID of a project'
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index bb74849a98a..9f0077d23d8 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -91,7 +91,7 @@ module API
end
def check_import_by_url_is_enabled
- forbidden! unless Gitlab::CurrentSettings.import_sources&.include?('git')
+ Gitlab::CurrentSettings.import_sources&.include?('git') || forbidden!
end
end
@@ -269,7 +269,9 @@ module API
attrs = declared_params(include_missing: false)
attrs = translate_params_for_compatibility(attrs)
filter_attributes_using_license!(attrs)
- check_import_by_url_is_enabled if params[:import_url].present?
+
+ validate_git_import_url!(params[:import_url], import_enabled: check_import_by_url_is_enabled)
+
project = ::Projects::CreateService.new(current_user, attrs).execute
if project.saved?
@@ -307,6 +309,8 @@ module API
attrs = declared_params(include_missing: false)
attrs = translate_params_for_compatibility(attrs)
filter_attributes_using_license!(attrs)
+ validate_git_import_url!(params[:import_url])
+
project = ::Projects::CreateService.new(user, attrs).execute
if project.saved?
@@ -400,7 +404,7 @@ module API
use :collection_params
use :with_custom_attributes
end
- get ':id/forks', feature_category: :source_code_management do
+ get ':id/forks', feature_category: :source_code_management, urgency: :low do
forks = ForkProjectsFinder.new(user_project, params: project_finder_params, current_user: current_user).execute
present_projects forks, request_scope: user_project
@@ -510,7 +514,7 @@ module API
end
desc 'Get languages in project repository'
- get ':id/languages', feature_category: :source_code_management do
+ get ':id/languages', feature_category: :source_code_management, urgency: :medium do
::Projects::RepositoryLanguagesService
.new(user_project, current_user)
.execute.to_h { |lang| [lang.name, lang.share] }
diff --git a/lib/api/protected_branches.rb b/lib/api/protected_branches.rb
index 3cebc308f51..a4f5dfefae6 100644
--- a/lib/api/protected_branches.rb
+++ b/lib/api/protected_branches.rb
@@ -91,7 +91,7 @@ module API
requires :name, type: String, desc: 'The name of the protected branch'
end
# rubocop: disable CodeReuse/ActiveRecord
- delete ':id/protected_branches/:name', requirements: BRANCH_ENDPOINT_REQUIREMENTS do
+ delete ':id/protected_branches/:name', requirements: BRANCH_ENDPOINT_REQUIREMENTS, urgency: :low do
protected_branch = user_project.protected_branches.find_by!(name: params[:name])
destroy_conditionally!(protected_branch) do
diff --git a/lib/api/releases.rb b/lib/api/releases.rb
index 3b7e2b4bd27..7b89a177fd9 100644
--- a/lib/api/releases.rb
+++ b/lib/api/releases.rb
@@ -32,6 +32,7 @@ module API
optional :include_html_description, type: Boolean,
desc: 'If `true`, a response includes HTML rendered markdown of the release description.'
end
+ route_setting :authentication, job_token_allowed: true
get ':id/releases' do
releases = ::ReleasesFinder.new(user_project, current_user, declared_params.slice(:order_by, :sort)).execute
@@ -59,6 +60,7 @@ module API
optional :include_html_description, type: Boolean,
desc: 'If `true`, a response includes HTML rendered markdown of the release description.'
end
+ route_setting :authentication, job_token_allowed: true
get ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
authorize_download_code!
@@ -117,6 +119,7 @@ module API
optional :released_at, type: DateTime, desc: 'The date when the release will be/was ready.'
optional :milestones, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The titles of the related milestones'
end
+ route_setting :authentication, job_token_allowed: true
put ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
authorize_update_release!
@@ -142,6 +145,7 @@ module API
params do
requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
end
+ route_setting :authentication, job_token_allowed: true
delete ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
authorize_destroy_release!
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 1aa76906b3d..2dd0e40afba 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -42,6 +42,26 @@ module API
not_found! 'Blob' unless @blob
end
+
+ def fetch_target_project(current_user, user_project, params)
+ return user_project unless params[:from_project_id].present?
+
+ MergeRequestTargetProjectFinder
+ .new(current_user: current_user, source_project: user_project, project_feature: :repository)
+ .execute(include_routes: true).find_by_id(params[:from_project_id])
+ end
+
+ def compare_cache_key(current_user, user_project, target_project, params)
+ [
+ user_project,
+ target_project,
+ current_user,
+ :repository_compare,
+ target_project.repository.commit(params[:from]),
+ user_project.repository.commit(params[:to]),
+ params
+ ]
+ end
end
desc 'Get a project repository tree' do
@@ -59,7 +79,7 @@ module API
optional :page_token, type: String, desc: 'Record from which to start the keyset pagination'
end
end
- get ':id/repository/tree' do
+ get ':id/repository/tree', urgency: :low do
tree_finder = ::Repositories::TreeFinder.new(user_project, declared_params(include_missing: false))
not_found!("Tree") unless tree_finder.commit_exists?
@@ -124,22 +144,17 @@ module API
optional :from_project_id, type: String, desc: 'The project to compare from'
optional :straight, type: Boolean, desc: 'Comparison method, `true` for direct comparison between `from` and `to` (`from`..`to`), `false` to compare using merge base (`from`...`to`)', default: false
end
- get ':id/repository/compare' do
+ get ':id/repository/compare', urgency: :low do
ff_enabled = Feature.enabled?(:api_caching_rate_limit_repository_compare, user_project, default_enabled: :yaml)
+ target_project = fetch_target_project(current_user, user_project, params)
- cache_action_if(ff_enabled, [user_project, :repository_compare, current_user, declared_params], expires_in: 1.minute) do
- if params[:from_project_id].present?
- target_project = MergeRequestTargetProjectFinder
- .new(current_user: current_user, source_project: user_project, project_feature: :repository)
- .execute(include_routes: true).find_by_id(params[:from_project_id])
+ if target_project.blank?
+ render_api_error!("Target project id:#{params[:from_project_id]} is not a fork of project id:#{params[:id]}", 400)
+ end
- if target_project.blank?
- render_api_error!("Target project id:#{params[:from_project_id]} is not a fork of project id:#{params[:id]}", 400)
- end
- else
- target_project = user_project
- end
+ cache_key = compare_cache_key(current_user, user_project, target_project, declared_params)
+ cache_action_if(ff_enabled, cache_key, expires_in: 1.minute) do
compare = CompareService.new(user_project, params[:to]).execute(target_project, params[:from], straight: params[:straight])
if compare
diff --git a/lib/api/resource_milestone_events.rb b/lib/api/resource_milestone_events.rb
index aeedd7ad109..c0483ca59c2 100644
--- a/lib/api/resource_milestone_events.rb
+++ b/lib/api/resource_milestone_events.rb
@@ -8,7 +8,7 @@ module API
before { authenticate! }
{
- Issue => :issue_tracking,
+ Issue => :team_planning,
MergeRequest => :code_review
}.each do |eventable_type, feature_category|
parent_type = eventable_type.parent_class.to_s.underscore
diff --git a/lib/api/resource_state_events.rb b/lib/api/resource_state_events.rb
index 3460aa2c00e..9b6f6a954b4 100644
--- a/lib/api/resource_state_events.rb
+++ b/lib/api/resource_state_events.rb
@@ -8,7 +8,7 @@ module API
before { authenticate! }
{
- Issue => :issue_tracking,
+ Issue => :team_planning,
MergeRequest => :code_review
}.each do |eventable_class, feature_category|
eventable_name = eventable_class.to_s.underscore
diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb
index f1ec1024492..c4b17a62b59 100644
--- a/lib/api/snippets.rb
+++ b/lib/api/snippets.rb
@@ -43,7 +43,7 @@ module API
params do
use :pagination
end
- get 'public' do
+ get 'public', urgency: :low do
authenticate!
present paginate(public_snippets), with: Entities::PersonalSnippet, current_user: current_user
diff --git a/lib/api/subscriptions.rb b/lib/api/subscriptions.rb
index 87dc1358a51..cda30dc957f 100644
--- a/lib/api/subscriptions.rb
+++ b/lib/api/subscriptions.rb
@@ -22,21 +22,21 @@ module API
entity: Entities::Issue,
source: Project,
finder: ->(id) { find_project_issue(id) },
- feature_category: :issue_tracking
+ feature_category: :team_planning
},
{
type: 'labels',
entity: Entities::ProjectLabel,
source: Project,
finder: ->(id) { find_label(user_project, id) },
- feature_category: :issue_tracking
+ feature_category: :team_planning
},
{
type: 'labels',
entity: Entities::GroupLabel,
source: Group,
finder: ->(id) { find_label(user_group, id) },
- feature_category: :issue_tracking
+ feature_category: :team_planning
}
]
diff --git a/lib/api/tags.rb b/lib/api/tags.rb
index f018b421edd..1b37d38ef06 100644
--- a/lib/api/tags.rb
+++ b/lib/api/tags.rb
@@ -21,20 +21,28 @@ module API
optional :order_by, type: String, values: %w[name updated], default: 'updated',
desc: 'Return tags ordered by `name` or `updated` fields.'
optional :search, type: String, desc: 'Return list of tags matching the search criteria'
+ optional :page_token, type: String, desc: 'Name of tag to start the paginaition from'
use :pagination
end
- get ':id/repository/tags', feature_category: :source_code_management do
- tags, _ = ::TagsFinder.new(user_project.repository,
+ get ':id/repository/tags', feature_category: :source_code_management, urgency: :low do
+ tags_finder = ::TagsFinder.new(user_project.repository,
sort: "#{params[:order_by]}_#{params[:sort]}",
- search: params[:search]).execute
+ search: params[:search],
+ page_token: params[:page_token],
+ per_page: params[:per_page])
- paginated_tags = paginate(::Kaminari.paginate_array(tags))
+ paginated_tags = Gitlab::Pagination::GitalyKeysetPager.new(self, user_project).paginate(tags_finder)
if Feature.enabled?(:api_caching_tags, user_project, type: :development)
present_cached paginated_tags, with: Entities::Tag, project: user_project, cache_context: -> (_tag) { user_project.cache_key }
else
present paginated_tags, with: Entities::Tag, project: user_project
end
+
+ rescue Gitlab::Git::InvalidPageToken => e
+ unprocessable_entity!(e.message)
+ rescue Gitlab::Git::CommandError
+ service_unavailable!
end
desc 'Get a single repository tag' do
diff --git a/lib/api/terraform/modules/v1/packages.rb b/lib/api/terraform/modules/v1/packages.rb
index aa59b6a4fee..ad5a4ae7ea6 100644
--- a/lib/api/terraform/modules/v1/packages.rb
+++ b/lib/api/terraform/modules/v1/packages.rb
@@ -46,7 +46,8 @@ module API
def finder_params
{
package_type: :terraform_module,
- package_name: "#{params[:module_name]}/#{params[:module_system]}"
+ package_name: "#{params[:module_name]}/#{params[:module_system]}",
+ exact_name: true
}.tap do |finder_params|
finder_params[:package_version] = params[:module_version] if params.has_key?(:module_version)
end
diff --git a/lib/api/todos.rb b/lib/api/todos.rb
index e0e5ca615ac..57a6ee0bebb 100644
--- a/lib/api/todos.rb
+++ b/lib/api/todos.rb
@@ -6,7 +6,7 @@ module API
before { authenticate! }
- feature_category :issue_tracking
+ feature_category :team_planning
ISSUABLE_TYPES = {
'merge_requests' => ->(iid) { find_merge_request_with_access(iid) },
diff --git a/lib/api/topics.rb b/lib/api/topics.rb
new file mode 100644
index 00000000000..bd28ebe58a9
--- /dev/null
+++ b/lib/api/topics.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module API
+ class Topics < ::API::Base
+ include PaginationParams
+
+ feature_category :projects
+
+ desc 'Get topics' do
+ detail 'This feature was introduced in GitLab 14.5.'
+ success Entities::Projects::Topic
+ end
+ params do
+ optional :search, type: String, desc: 'Return list of topics matching the search criteria'
+ use :pagination
+ end
+ get 'topics' do
+ topics = ::Projects::TopicsFinder.new(params: declared_params(include_missing: false)).execute
+
+ present paginate(topics), with: Entities::Projects::Topic
+ end
+
+ desc 'Get topic' do
+ detail 'This feature was introduced in GitLab 14.5.'
+ success Entities::Projects::Topic
+ end
+ params do
+ requires :id, type: Integer, desc: 'ID of project topic'
+ end
+ get 'topics/:id' do
+ topic = ::Projects::Topic.find(params[:id])
+
+ present topic, with: Entities::Projects::Topic
+ end
+
+ desc 'Create a topic' do
+ detail 'This feature was introduced in GitLab 14.5.'
+ success Entities::Projects::Topic
+ end
+ params do
+ requires :name, type: String, desc: 'Name'
+ optional :description, type: String, desc: 'Description'
+ optional :avatar, type: ::API::Validations::Types::WorkhorseFile, desc: 'Avatar image for topic'
+ end
+ post 'topics' do
+ authenticated_as_admin!
+
+ topic = ::Projects::Topic.new(declared_params(include_missing: false))
+
+ if topic.save
+ present topic, with: Entities::Projects::Topic
+ else
+ render_validation_error!(topic)
+ end
+ end
+
+ desc 'Update a topic' do
+ detail 'This feature was introduced in GitLab 14.5.'
+ success Entities::Projects::Topic
+ end
+ params do
+ requires :id, type: Integer, desc: 'ID of project topic'
+ optional :name, type: String, desc: 'Name'
+ optional :description, type: String, desc: 'Description'
+ optional :avatar, type: ::API::Validations::Types::WorkhorseFile, desc: 'Avatar image for topic'
+ end
+ put 'topics/:id' do
+ authenticated_as_admin!
+
+ topic = ::Projects::Topic.find(params[:id])
+
+ if topic.update(declared_params(include_missing: false))
+ present topic, with: Entities::Projects::Topic
+ else
+ render_validation_error!(topic)
+ end
+ end
+ end
+end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index f16e1148618..ce0a0e9b502 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -1062,6 +1062,7 @@ module API
requires :credit_card_expiration_year, type: Integer, desc: 'The year the credit card expires'
requires :credit_card_holder_name, type: String, desc: 'The credit card holder name'
requires :credit_card_mask_number, type: String, desc: 'The last 4 digits of credit card number'
+ requires :credit_card_type, type: String, desc: 'The credit card network name'
end
put ":user_id/credit_card_validation", feature_category: :users do
authenticated_as_admin!
diff --git a/lib/api/v3/github.rb b/lib/api/v3/github.rb
index 310054c298a..677d0840208 100644
--- a/lib/api/v3/github.rb
+++ b/lib/api/v3/github.rb
@@ -20,6 +20,9 @@ module API
# Jira Server user agent format: Jira DVCS Connector/version
JIRA_DVCS_CLOUD_USER_AGENT = 'Jira DVCS Connector Vertigo'
+ GITALY_TIMEOUT_CACHE_KEY = 'api:v3:Gitaly-timeout-cache-key'
+ GITALY_TIMEOUT_CACHE_EXPIRY = 1.day
+
include PaginationParams
feature_category :integrations
@@ -93,6 +96,32 @@ module API
notes.select { |n| n.readable_by?(current_user) }
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ # Returns an empty Array instead of the Commit diff files for a period
+ # of time after a Gitaly timeout, to mitigate frequent Gitaly timeouts
+ # for some Commit diffs.
+ def diff_files(commit)
+ return commit.diffs.diff_files unless Feature.enabled?(:api_v3_commits_skip_diff_files, commit.project, default_enabled: :yaml)
+
+ cache_key = [
+ GITALY_TIMEOUT_CACHE_KEY,
+ commit.project.id,
+ commit.cache_key
+ ].join(':')
+
+ return [] if Rails.cache.read(cache_key).present?
+
+ begin
+ commit.diffs.diff_files
+ rescue GRPC::DeadlineExceeded => error
+ # Gitaly fails to load diffs consistently for some commits. The other information
+ # is still valuable for Jira. So we skip the loading and respond with a 200 excluding diffs
+ # Remove this when https://gitlab.com/gitlab-org/gitaly/-/issues/3741 is fixed.
+ Rails.cache.write(cache_key, 1, expires_in: GITALY_TIMEOUT_CACHE_EXPIRY)
+ Gitlab::ErrorTracking.track_exception(error)
+ []
+ end
+ end
end
resource :orgs do
@@ -228,10 +257,9 @@ module API
user_project = find_project_with_access(params)
commit = user_project.commit(params[:sha])
-
not_found! 'Commit' unless commit
- present commit, with: ::API::Github::Entities::RepoCommit
+ present commit, with: ::API::Github::Entities::RepoCommit, diff_files: diff_files(commit)
end
end
end
diff --git a/lib/api/wikis.rb b/lib/api/wikis.rb
index 8441aeb10ab..fdce3c5ce18 100644
--- a/lib/api/wikis.rb
+++ b/lib/api/wikis.rb
@@ -32,7 +32,7 @@ module API
params do
optional :with_content, type: Boolean, default: false, desc: "Include pages' content"
end
- get ':id/wikis' do
+ get ':id/wikis', urgency: :low do
authorize! :read_wiki, container
entity = params[:with_content] ? Entities::WikiPage : Entities::WikiPageBasic
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 6c5350082e8..1bdc4965e5d 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -99,9 +99,10 @@ module Backup
# - 1495527122_gitlab_backup.tar
# - 1495527068_2017_05_23_gitlab_backup.tar
# - 1495527097_2017_05_23_9.3.0-pre_gitlab_backup.tar
- next unless file =~ /^(\d{10})(?:_\d{4}_\d{2}_\d{2}(_\d+\.\d+\.\d+((-|\.)(pre|rc\d))?(-ee)?)?)?_gitlab_backup\.tar$/
+ matched = backup_file?(file)
+ next unless matched
- timestamp = Regexp.last_match(1).to_i
+ timestamp = matched[1].to_i
if Time.at(timestamp) < (Time.now - keep_time)
begin
@@ -192,6 +193,10 @@ module Backup
private
+ def backup_file?(file)
+ file.match(/^(\d{10})(?:_\d{4}_\d{2}_\d{2}(_\d+\.\d+\.\d+((-|\.)(pre|rc\d))?(-ee)?)?)?_gitlab_backup\.tar$/)
+ end
+
def non_tarred_backup?
File.exist?(File.join(backup_path, 'backup_information.yml'))
end
@@ -210,9 +215,7 @@ module Backup
def object_storage_config
@object_storage_config ||= begin
- config = ObjectStorage::Config.new(Gitlab.config.backup.upload)
- config.load_provider
- config
+ ObjectStorage::Config.new(Gitlab.config.backup.upload)
end
end
@@ -316,3 +319,5 @@ module Backup
end
end
end
+
+Backup::Manager.prepend_mod
diff --git a/lib/banzai/filter/emoji_filter.rb b/lib/banzai/filter/emoji_filter.rb
index 9d24bf028b6..d8c9fd0a7f0 100644
--- a/lib/banzai/filter/emoji_filter.rb
+++ b/lib/banzai/filter/emoji_filter.rb
@@ -8,7 +8,6 @@ module Banzai
# Based on HTML::Pipeline::EmojiFilter
class EmojiFilter < HTML::Pipeline::Filter
IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set
- IGNORE_UNICODE_EMOJIS = %w(™ © ®).freeze
def call
doc.xpath('descendant-or-self::text()').each do |node|
@@ -35,7 +34,8 @@ module Banzai
def emoji_name_element_unicode_filter(text)
text.gsub(emoji_pattern) do |match|
name = Regexp.last_match(1)
- Gitlab::Emoji.gl_emoji_tag(name)
+ emoji = TanukiEmoji.find_by_alpha_code(name)
+ Gitlab::Emoji.gl_emoji_tag(emoji)
end
end
@@ -46,26 +46,19 @@ module Banzai
# Returns a String with unicode emoji replaced with gl-emoji unicode.
def emoji_unicode_element_unicode_filter(text)
text.gsub(emoji_unicode_pattern) do |moji|
- emoji_info = Gitlab::Emoji.emojis_by_moji[moji]
- Gitlab::Emoji.gl_emoji_tag(emoji_info['name'])
+ emoji = TanukiEmoji.find_by_codepoints(moji)
+ Gitlab::Emoji.gl_emoji_tag(emoji)
end
end
# Build a regexp that matches all valid :emoji: names.
def self.emoji_pattern
- @emoji_pattern ||=
- %r{(?<=[^[:alnum:]:]|\n|^)
- :(#{Gitlab::Emoji.emojis_names.map { |name| Regexp.escape(name) }.join('|')}):
- (?=[^[:alnum:]:]|$)}x
+ @emoji_pattern ||= TanukiEmoji.index.alpha_code_pattern
end
# Build a regexp that matches all valid unicode emojis names.
def self.emoji_unicode_pattern
- @emoji_unicode_pattern ||=
- begin
- filtered_emojis = Gitlab::Emoji.emojis_unicodes - IGNORE_UNICODE_EMOJIS
- /(#{filtered_emojis.map { |moji| Regexp.escape(moji) }.join('|')})/
- end
+ @emoji_unicode_pattern ||= TanukiEmoji.index.codepoints_pattern
end
private
diff --git a/lib/banzai/filter/footnote_filter.rb b/lib/banzai/filter/footnote_filter.rb
index 0f856dc0eb9..39c42ceaf9b 100644
--- a/lib/banzai/filter/footnote_filter.rb
+++ b/lib/banzai/filter/footnote_filter.rb
@@ -16,37 +16,60 @@ module Banzai
# can be used for a single render). So you get `id=fn1-4335` and `id=fn2-4335`.
#
class FootnoteFilter < HTML::Pipeline::Filter
- INTEGER_PATTERN = /\A\d+\z/.freeze
- FOOTNOTE_ID_PREFIX = 'fn'
- FOOTNOTE_LINK_ID_PREFIX = 'fnref'
- FOOTNOTE_LI_REFERENCE_PATTERN = /\A#{FOOTNOTE_ID_PREFIX}\d+\z/.freeze
- FOOTNOTE_LINK_REFERENCE_PATTERN = /\A#{FOOTNOTE_LINK_ID_PREFIX}\d+\z/.freeze
- FOOTNOTE_START_NUMBER = 1
-
- CSS_SECTION = "ol > li[id=#{FOOTNOTE_ID_PREFIX}#{FOOTNOTE_START_NUMBER}]"
+ FOOTNOTE_ID_PREFIX = 'fn-'
+ FOOTNOTE_LINK_ID_PREFIX = 'fnref-'
+ FOOTNOTE_LI_REFERENCE_PATTERN = /\A#{FOOTNOTE_ID_PREFIX}.+\z/.freeze
+ FOOTNOTE_LINK_REFERENCE_PATTERN = /\A#{FOOTNOTE_LINK_ID_PREFIX}.+\z/.freeze
+
+ CSS_SECTION = "ol > li a[href^=\"\##{FOOTNOTE_LINK_ID_PREFIX}\"]"
XPATH_SECTION = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_SECTION).freeze
CSS_FOOTNOTE = 'sup > a[id]'
XPATH_FOOTNOTE = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_FOOTNOTE).freeze
+ # only needed when feature flag use_cmark_renderer is turned off
+ INTEGER_PATTERN = /\A\d+\z/.freeze
+ FOOTNOTE_ID_PREFIX_OLD = 'fn'
+ FOOTNOTE_LINK_ID_PREFIX_OLD = 'fnref'
+ FOOTNOTE_LI_REFERENCE_PATTERN_OLD = /\A#{FOOTNOTE_ID_PREFIX_OLD}\d+\z/.freeze
+ FOOTNOTE_LINK_REFERENCE_PATTERN_OLD = /\A#{FOOTNOTE_LINK_ID_PREFIX_OLD}\d+\z/.freeze
+ FOOTNOTE_START_NUMBER = 1
+ CSS_SECTION_OLD = "ol > li[id=#{FOOTNOTE_ID_PREFIX_OLD}#{FOOTNOTE_START_NUMBER}]"
+ XPATH_SECTION_OLD = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_SECTION_OLD).freeze
+
def call
- return doc unless first_footnote = doc.at_xpath(XPATH_SECTION)
+ xpath_section = Feature.enabled?(:use_cmark_renderer) ? XPATH_SECTION : XPATH_SECTION_OLD
+ return doc unless first_footnote = doc.at_xpath(xpath_section)
# Sanitization stripped off the section wrapper - add it back in
- first_footnote.parent.wrap('<section class="footnotes">')
+ if Feature.enabled?(:use_cmark_renderer)
+ first_footnote.parent.parent.parent.wrap('<section class="footnotes" data-footnotes>')
+ else
+ first_footnote.parent.wrap('<section class="footnotes">')
+ end
+
rand_suffix = "-#{random_number}"
modified_footnotes = {}
doc.xpath(XPATH_FOOTNOTE).each do |link_node|
- ref_num = link_node[:id].delete_prefix(FOOTNOTE_LINK_ID_PREFIX)
- node_xpath = Gitlab::Utils::Nokogiri.css_to_xpath("li[id=#{fn_id(ref_num)}]")
+ if Feature.enabled?(:use_cmark_renderer)
+ ref_num = link_node[:id].delete_prefix(FOOTNOTE_LINK_ID_PREFIX)
+ ref_num.gsub!(/[[:punct:]]/, '\\\\\&')
+ else
+ ref_num = link_node[:id].delete_prefix(FOOTNOTE_LINK_ID_PREFIX_OLD)
+ end
+
+ node_xpath = Gitlab::Utils::Nokogiri.css_to_xpath("li[id=#{fn_id(ref_num)}]")
footnote_node = doc.at_xpath(node_xpath)
- if INTEGER_PATTERN.match?(ref_num) && (footnote_node || modified_footnotes[ref_num])
+ if footnote_node || modified_footnotes[ref_num]
+ next if Feature.disabled?(:use_cmark_renderer) && !INTEGER_PATTERN.match?(ref_num)
+
link_node[:href] += rand_suffix
link_node[:id] += rand_suffix
# Sanitization stripped off class - add it back in
link_node.parent.append_class('footnote-ref')
+ link_node['data-footnote-ref'] = nil if Feature.enabled?(:use_cmark_renderer)
unless modified_footnotes[ref_num]
footnote_node[:id] += rand_suffix
@@ -55,6 +78,7 @@ module Banzai
if backref_node
backref_node[:href] += rand_suffix
backref_node.append_class('footnote-backref')
+ backref_node['data-footnote-backref'] = nil if Feature.enabled?(:use_cmark_renderer)
end
modified_footnotes[ref_num] = true
@@ -72,11 +96,13 @@ module Banzai
end
def fn_id(num)
- "#{FOOTNOTE_ID_PREFIX}#{num}"
+ prefix = Feature.enabled?(:use_cmark_renderer) ? FOOTNOTE_ID_PREFIX : FOOTNOTE_ID_PREFIX_OLD
+ "#{prefix}#{num}"
end
def fnref_id(num)
- "#{FOOTNOTE_LINK_ID_PREFIX}#{num}"
+ prefix = Feature.enabled?(:use_cmark_renderer) ? FOOTNOTE_LINK_ID_PREFIX : FOOTNOTE_LINK_ID_PREFIX_OLD
+ "#{prefix}#{num}"
end
end
end
diff --git a/lib/banzai/filter/markdown_engines/common_mark.rb b/lib/banzai/filter/markdown_engines/common_mark.rb
index 7be52fc497f..a25ebedf029 100644
--- a/lib/banzai/filter/markdown_engines/common_mark.rb
+++ b/lib/banzai/filter/markdown_engines/common_mark.rb
@@ -13,8 +13,7 @@ module Banzai
EXTENSIONS = [
:autolink, # provides support for automatically converting URLs to anchor tags.
:strikethrough, # provides support for strikethroughs.
- :table, # provides support for tables.
- :tagfilter # strips out several "unsafe" HTML tags from being used: https://github.github.com/gfm/#disallowed-raw-html-extension-
+ :table # provides support for tables.
].freeze
PARSE_OPTIONS = [
@@ -23,36 +22,63 @@ module Banzai
:VALIDATE_UTF8 # replace illegal sequences with the replacement character U+FFFD.
].freeze
+ RENDER_OPTIONS_C = [
+ :GITHUB_PRE_LANG, # use GitHub-style <pre lang> for fenced code blocks.
+ :FOOTNOTES, # render footnotes.
+ :FULL_INFO_STRING, # include full info strings of code blocks in separate attribute.
+ :UNSAFE # allow raw/custom HTML and unsafe links.
+ ].freeze
+
# The `:GITHUB_PRE_LANG` option is not used intentionally because
# it renders a fence block with language as `<pre lang="LANG"><code>some code\n</code></pre>`
# while GitLab's syntax is `<pre><code lang="LANG">some code\n</code></pre>`.
# If in the future the syntax is about to be made GitHub-compatible, please, add `:GITHUB_PRE_LANG` render option below
# and remove `code_block` method from `lib/banzai/renderer/common_mark/html.rb`.
- RENDER_OPTIONS = [
+ RENDER_OPTIONS_RUBY = [
# as of commonmarker 0.18.0, we need to use :UNSAFE to get the same as the original :DEFAULT
# https://github.com/gjtorikian/commonmarker/pull/81
- :UNSAFE
- ].freeze
-
- RENDER_OPTIONS_SOURCEPOS = RENDER_OPTIONS + [
- :SOURCEPOS # enable embedding of source position information
+ :UNSAFE # allow raw/custom HTML and unsafe links.
].freeze
def initialize(context)
- @context = context
- @renderer = Banzai::Renderer::CommonMark::HTML.new(options: render_options)
+ @context = context
+ @renderer = Banzai::Renderer::CommonMark::HTML.new(options: render_options) if Feature.disabled?(:use_cmark_renderer)
end
def render(text)
- doc = CommonMarker.render_doc(text, PARSE_OPTIONS, EXTENSIONS)
+ if Feature.enabled?(:use_cmark_renderer)
+ CommonMarker.render_html(text, render_options, extensions)
+ else
+ doc = CommonMarker.render_doc(text, PARSE_OPTIONS, extensions)
- @renderer.render(doc)
+ @renderer.render(doc)
+ end
end
private
+ def extensions
+ if Feature.enabled?(:use_cmark_renderer)
+ EXTENSIONS
+ else
+ EXTENSIONS + [
+ :tagfilter # strips out several "unsafe" HTML tags from being used: https://github.github.com/gfm/#disallowed-raw-html-extension-
+ ].freeze
+ end
+ end
+
def render_options
- @context[:no_sourcepos] ? RENDER_OPTIONS : RENDER_OPTIONS_SOURCEPOS
+ @context[:no_sourcepos] ? render_options_no_sourcepos : render_options_sourcepos
+ end
+
+ def render_options_no_sourcepos
+ Feature.enabled?(:use_cmark_renderer) ? RENDER_OPTIONS_C : RENDER_OPTIONS_RUBY
+ end
+
+ def render_options_sourcepos
+ render_options_no_sourcepos + [
+ :SOURCEPOS # enable embedding of source position information
+ ].freeze
end
end
end
diff --git a/lib/banzai/filter/markdown_post_escape_filter.rb b/lib/banzai/filter/markdown_post_escape_filter.rb
index b69afdcfebe..ccffe1bfbb1 100644
--- a/lib/banzai/filter/markdown_post_escape_filter.rb
+++ b/lib/banzai/filter/markdown_post_escape_filter.rb
@@ -8,10 +8,8 @@ module Banzai
NOT_LITERAL_REGEX = %r{#{LITERAL_KEYWORD}-((%5C|\\).+?)-#{LITERAL_KEYWORD}}.freeze
SPAN_REGEX = %r{<span>(.*?)</span>}.freeze
- CSS_A = 'a'
- XPATH_A = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_A).freeze
- CSS_CODE = 'code'
- XPATH_CODE = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_CODE).freeze
+ CSS_A = 'a'
+ XPATH_A = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_A).freeze
def call
return doc unless result[:escaped_literals]
@@ -34,12 +32,22 @@ module Banzai
node.attributes['title'].value = node.attributes['title'].value.gsub(SPAN_REGEX, '\1') if node.attributes['title']
end
- doc.xpath(XPATH_CODE).each do |node|
+ doc.xpath(lang_tag).each do |node|
node.attributes['lang'].value = node.attributes['lang'].value.gsub(SPAN_REGEX, '\1') if node.attributes['lang']
end
doc
end
+
+ private
+
+ def lang_tag
+ if Feature.enabled?(:use_cmark_renderer)
+ Gitlab::Utils::Nokogiri.css_to_xpath('pre')
+ else
+ Gitlab::Utils::Nokogiri.css_to_xpath('code')
+ end
+ end
end
end
end
diff --git a/lib/banzai/filter/plantuml_filter.rb b/lib/banzai/filter/plantuml_filter.rb
index 93370178a61..e67cdc7df12 100644
--- a/lib/banzai/filter/plantuml_filter.rb
+++ b/lib/banzai/filter/plantuml_filter.rb
@@ -5,18 +5,15 @@ require "asciidoctor_plantuml/plantuml"
module Banzai
module Filter
- # HTML that replaces all `code plantuml` tags with PlantUML img tags.
+ # HTML that replaces all `lang plantuml` tags with PlantUML img tags.
#
class PlantumlFilter < HTML::Pipeline::Filter
- CSS = 'pre > code[lang="plantuml"]'
- XPATH = Gitlab::Utils::Nokogiri.css_to_xpath(CSS).freeze
-
def call
- return doc unless settings.plantuml_enabled? && doc.at_xpath(XPATH)
+ return doc unless settings.plantuml_enabled? && doc.at_xpath(lang_tag)
plantuml_setup
- doc.xpath(XPATH).each do |node|
+ doc.xpath(lang_tag).each do |node|
img_tag = Nokogiri::HTML::DocumentFragment.parse(
Asciidoctor::PlantUml::Processor.plantuml_content(node.content, {}))
node.parent.replace(img_tag)
@@ -27,6 +24,15 @@ module Banzai
private
+ def lang_tag
+ @lang_tag ||=
+ if Feature.enabled?(:use_cmark_renderer)
+ Gitlab::Utils::Nokogiri.css_to_xpath('pre[lang="plantuml"] > code').freeze
+ else
+ Gitlab::Utils::Nokogiri.css_to_xpath('pre > code[lang="plantuml"]').freeze
+ end
+ end
+
def settings
Gitlab::CurrentSettings.current_application_settings
end
diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb
index 1e84e7e8af3..7afbc1a1c9c 100644
--- a/lib/banzai/filter/sanitization_filter.rb
+++ b/lib/banzai/filter/sanitization_filter.rb
@@ -54,8 +54,13 @@ module Banzai
return unless node.name == 'a' || node.name == 'li'
return unless node.has_attribute?('id')
- return if node.name == 'a' && node['id'] =~ Banzai::Filter::FootnoteFilter::FOOTNOTE_LINK_REFERENCE_PATTERN
- return if node.name == 'li' && node['id'] =~ Banzai::Filter::FootnoteFilter::FOOTNOTE_LI_REFERENCE_PATTERN
+ if Feature.enabled?(:use_cmark_renderer)
+ return if node.name == 'a' && node['id'] =~ Banzai::Filter::FootnoteFilter::FOOTNOTE_LINK_REFERENCE_PATTERN
+ return if node.name == 'li' && node['id'] =~ Banzai::Filter::FootnoteFilter::FOOTNOTE_LI_REFERENCE_PATTERN
+ else
+ return if node.name == 'a' && node['id'] =~ Banzai::Filter::FootnoteFilter::FOOTNOTE_LINK_REFERENCE_PATTERN_OLD
+ return if node.name == 'li' && node['id'] =~ Banzai::Filter::FootnoteFilter::FOOTNOTE_LI_REFERENCE_PATTERN_OLD
+ end
node.remove_attribute('id')
end
diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb
index 8d869cd63d3..66bd86c5bb4 100644
--- a/lib/banzai/filter/syntax_highlight_filter.rb
+++ b/lib/banzai/filter/syntax_highlight_filter.rb
@@ -11,7 +11,7 @@ module Banzai
class SyntaxHighlightFilter < HTML::Pipeline::Filter
include OutputSafety
- PARAMS_DELIMITER = ':'
+ LANG_PARAMS_DELIMITER = ':'
LANG_PARAMS_ATTR = 'data-lang-params'
CSS = 'pre:not([data-math-style]):not([data-mermaid-style]):not([data-kroki-style]) > code'
@@ -27,7 +27,7 @@ module Banzai
def highlight_node(node)
css_classes = +'code highlight js-syntax-highlight'
- lang, lang_params = parse_lang_params(node.attr('lang'))
+ lang, lang_params = parse_lang_params(node)
sourcepos = node.parent.attr('data-sourcepos')
retried = false
@@ -56,7 +56,7 @@ module Banzai
retry
end
- sourcepos_attr = sourcepos ? "data-sourcepos=\"#{sourcepos}\"" : ""
+ sourcepos_attr = sourcepos ? "data-sourcepos=\"#{sourcepos}\"" : ''
highlighted = %(<pre #{sourcepos_attr} class="#{css_classes}"
lang="#{language}"
@@ -69,13 +69,36 @@ module Banzai
private
- def parse_lang_params(language)
+ def parse_lang_params(node)
+ node = node.parent if Feature.enabled?(:use_cmark_renderer)
+
+ # Commonmarker's FULL_INFO_STRING render option works with the space delimiter.
+ # But the current behavior of GitLab's markdown renderer is different - it grabs everything as the single
+ # line, including language and its options. To keep backward compatability, we have to parse the old format and
+ # merge with the new one.
+ #
+ # Behaviors before separating language and its parameters:
+ # Old ones:
+ # "```ruby with options```" -> '<pre><code lang="ruby with options">'.
+ # "```ruby:with:options```" -> '<pre><code lang="ruby:with:options">'.
+ #
+ # New ones:
+ # "```ruby with options```" -> '<pre><code lang="ruby" data-meta="with options">'.
+ # "```ruby:with:options```" -> '<pre><code lang="ruby:with:options">'.
+
+ language = node.attr('lang')
+
return unless language
- lang, params = language.split(PARAMS_DELIMITER, 2)
- formatted_params = %(#{LANG_PARAMS_ATTR}="#{escape_once(params)}") if params
+ language, language_params = language.split(LANG_PARAMS_DELIMITER, 2)
+
+ if Feature.enabled?(:use_cmark_renderer)
+ language_params = [node.attr('data-meta'), language_params].compact.join(' ')
+ end
+
+ formatted_language_params = format_language_params(language_params)
- [lang, formatted_params]
+ [language, formatted_language_params]
end
# Separate method so it can be instrumented.
@@ -95,6 +118,12 @@ module Banzai
def use_rouge?(language)
(%w(math suggestion) + ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES).exclude?(language)
end
+
+ def format_language_params(language_params)
+ return if language_params.blank?
+
+ %(#{LANG_PARAMS_ATTR}="#{escape_once(language_params)}")
+ end
end
end
end
diff --git a/lib/banzai/renderer.rb b/lib/banzai/renderer.rb
index fbbd6135959..b16af78841a 100644
--- a/lib/banzai/renderer.rb
+++ b/lib/banzai/renderer.rb
@@ -160,16 +160,40 @@ module Banzai
def self.cacheless_render(text, context = {})
return text.to_s unless text.present?
- Gitlab::Metrics.measure(:banzai_cacheless_render) do
- result = render_result(text, context)
+ real_start = Gitlab::Metrics::System.monotonic_time
+ cpu_start = Gitlab::Metrics::System.cpu_time
- output = result[:output]
- if output.respond_to?(:to_html)
- output.to_html
- else
- output.to_s
- end
- end
+ result = render_result(text, context)
+
+ output = result[:output]
+ rendered = if output.respond_to?(:to_html)
+ output.to_html
+ else
+ output.to_s
+ end
+
+ cpu_duration_histogram.observe({}, Gitlab::Metrics::System.cpu_time - cpu_start)
+ real_duration_histogram.observe({}, Gitlab::Metrics::System.monotonic_time - real_start)
+
+ rendered
+ end
+
+ def self.real_duration_histogram
+ Gitlab::Metrics.histogram(
+ :gitlab_banzai_cacheless_render_real_duration_seconds,
+ 'Duration of Banzai pipeline rendering in real time',
+ {},
+ [0.01, 0.01, 0.05, 0.1, 0.5, 1, 2, 5, 10.0, 50, 100]
+ )
+ end
+
+ def self.cpu_duration_histogram
+ Gitlab::Metrics.histogram(
+ :gitlab_banzai_cacheless_render_cpu_duration_seconds,
+ 'Duration of Banzai pipeline rendering in cpu time',
+ {},
+ Gitlab::Metrics::EXECUTION_MEASUREMENT_BUCKETS
+ )
end
def self.full_cache_key(cache_key, pipeline_name)
diff --git a/lib/banzai/renderer/common_mark/html.rb b/lib/banzai/renderer/common_mark/html.rb
index 837665451a1..d9a2d9a9564 100644
--- a/lib/banzai/renderer/common_mark/html.rb
+++ b/lib/banzai/renderer/common_mark/html.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+# Remove this entire file when removing `use_cmark_renderer` feature flag and switching to the CMARK html renderer.
+# https://gitlab.com/gitlab-org/gitlab/-/issues/345744
module Banzai
module Renderer
module CommonMark
diff --git a/lib/bulk_imports/common/extractors/ndjson_extractor.rb b/lib/bulk_imports/common/extractors/ndjson_extractor.rb
index 6b4acd45ea9..ecd7c08bd25 100644
--- a/lib/bulk_imports/common/extractors/ndjson_extractor.rb
+++ b/lib/bulk_imports/common/extractors/ndjson_extractor.rb
@@ -7,10 +7,6 @@ module BulkImports
include Gitlab::ImportExport::CommandLineUtil
include Gitlab::Utils::StrongMemoize
- FILE_SIZE_LIMIT = 5.gigabytes
- ALLOWED_CONTENT_TYPES = %w(application/gzip application/octet-stream).freeze
- EXPORT_DOWNLOAD_URL_PATH = "/%{resource}/%{full_path}/export_relations/download?relation=%{relation}"
-
def initialize(relation:)
@relation = relation
@tmp_dir = Dir.mktmpdir
@@ -39,33 +35,19 @@ module BulkImports
def download_service(tmp_dir, context)
@download_service ||= BulkImports::FileDownloadService.new(
configuration: context.configuration,
- relative_url: relative_resource_url(context),
+ relative_url: context.entity.relation_download_url_path(relation),
dir: tmp_dir,
- filename: filename,
- file_size_limit: FILE_SIZE_LIMIT,
- allowed_content_types: ALLOWED_CONTENT_TYPES
+ filename: filename
)
end
def decompression_service(tmp_dir)
- @decompression_service ||= BulkImports::FileDecompressionService.new(
- dir: tmp_dir,
- filename: filename
- )
+ @decompression_service ||= BulkImports::FileDecompressionService.new(dir: tmp_dir, filename: filename)
end
def ndjson_reader(tmp_dir)
@ndjson_reader ||= Gitlab::ImportExport::Json::NdjsonReader.new(tmp_dir)
end
-
- def relative_resource_url(context)
- strong_memoize(:relative_resource_url) do
- resource = context.entity.pluralized_name
- encoded_full_path = context.entity.encoded_source_full_path
-
- EXPORT_DOWNLOAD_URL_PATH % { resource: resource, full_path: encoded_full_path, relation: relation }
- end
- end
end
end
end
diff --git a/lib/bulk_imports/common/pipelines/milestones_pipeline.rb b/lib/bulk_imports/common/pipelines/milestones_pipeline.rb
new file mode 100644
index 00000000000..aea2a04c1c7
--- /dev/null
+++ b/lib/bulk_imports/common/pipelines/milestones_pipeline.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Pipelines
+ class MilestonesPipeline
+ include NdjsonPipeline
+
+ relation_name 'milestones'
+
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/common/pipelines/uploads_pipeline.rb b/lib/bulk_imports/common/pipelines/uploads_pipeline.rb
new file mode 100644
index 00000000000..15e126e1646
--- /dev/null
+++ b/lib/bulk_imports/common/pipelines/uploads_pipeline.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Pipelines
+ class UploadsPipeline
+ include Pipeline
+ include Gitlab::ImportExport::CommandLineUtil
+
+ FILENAME = 'uploads.tar.gz'
+
+ def extract(context)
+ download_service(tmp_dir, context).execute
+ untar_zxf(archive: File.join(tmp_dir, FILENAME), dir: tmp_dir)
+ upload_file_paths = Dir.glob(File.join(tmp_dir, '**', '*'))
+
+ BulkImports::Pipeline::ExtractedData.new(data: upload_file_paths)
+ end
+
+ def load(context, file_path)
+ dynamic_path = FileUploader.extract_dynamic_path(file_path)
+
+ return unless dynamic_path
+ return if File.directory?(file_path)
+
+ named_captures = dynamic_path.named_captures.symbolize_keys
+
+ UploadService.new(context.portable, File.open(file_path, 'r'), FileUploader, **named_captures).execute
+ end
+
+ def after_run(_)
+ FileUtils.remove_entry(tmp_dir)
+ end
+
+ private
+
+ def download_service(tmp_dir, context)
+ BulkImports::FileDownloadService.new(
+ configuration: context.configuration,
+ relative_url: context.entity.relation_download_url_path('uploads'),
+ dir: tmp_dir,
+ filename: FILENAME
+ )
+ end
+
+ def tmp_dir
+ @tmp_dir ||= Dir.mktmpdir('bulk_imports')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/common/pipelines/wiki_pipeline.rb b/lib/bulk_imports/common/pipelines/wiki_pipeline.rb
new file mode 100644
index 00000000000..ccab0b979b2
--- /dev/null
+++ b/lib/bulk_imports/common/pipelines/wiki_pipeline.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Pipelines
+ class WikiPipeline
+ include Pipeline
+
+ def extract(*)
+ BulkImports::Pipeline::ExtractedData.new(data: { url: url_from_parent_path(context.entity.source_full_path) })
+ end
+
+ def transform(_, data)
+ data&.slice(:url)
+ end
+
+ def load(context, data)
+ return unless context.portable.wiki
+
+ url = data[:url].sub("://", "://oauth2:#{context.configuration.access_token}@")
+
+ Gitlab::UrlBlocker.validate!(url, allow_local_network: allow_local_requests?, allow_localhost: allow_local_requests?)
+
+ context.portable.wiki.ensure_repository
+ context.portable.wiki.repository.fetch_as_mirror(url)
+ end
+
+ private
+
+ def url_from_parent_path(parent_path)
+ wiki_path = parent_path + ".wiki.git"
+ root = context.configuration.url
+ Gitlab::Utils.append_path(root, wiki_path)
+ end
+
+ def allow_local_requests?
+ Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services?
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/graphql/get_milestones_query.rb b/lib/bulk_imports/groups/graphql/get_milestones_query.rb
deleted file mode 100644
index 5dd5b31cf0e..00000000000
--- a/lib/bulk_imports/groups/graphql/get_milestones_query.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-module BulkImports
- module Groups
- module Graphql
- module GetMilestonesQuery
- extend self
-
- def to_s
- <<-'GRAPHQL'
- query ($full_path: ID!, $cursor: String, $per_page: Int) {
- group(fullPath: $full_path) {
- milestones(first: $per_page, after: $cursor, includeDescendants: false) {
- page_info: pageInfo {
- next_page: endCursor
- has_next_page: hasNextPage
- }
- nodes {
- iid
- title
- description
- state
- start_date: startDate
- due_date: dueDate
- created_at: createdAt
- updated_at: updatedAt
- }
- }
- }
- }
- GRAPHQL
- end
-
- def variables(context)
- {
- full_path: context.entity.source_full_path,
- cursor: context.tracker.next_page,
- per_page: ::BulkImports::Tracker::DEFAULT_PAGE_SIZE
- }
- end
-
- def base_path
- %w[data group milestones]
- end
-
- def data_path
- base_path << 'nodes'
- end
-
- def page_info_path
- base_path << 'page_info'
- end
- end
- end
- end
-end
diff --git a/lib/bulk_imports/groups/loaders/group_loader.rb b/lib/bulk_imports/groups/loaders/group_loader.rb
index a631685c2ad..5f5307123a5 100644
--- a/lib/bulk_imports/groups/loaders/group_loader.rb
+++ b/lib/bulk_imports/groups/loaders/group_loader.rb
@@ -4,10 +4,21 @@ module BulkImports
module Groups
module Loaders
class GroupLoader
+ GroupCreationError = Class.new(StandardError)
+
def load(context, data)
- return unless user_can_create_group?(context.current_user, data)
+ path = data['path']
+ current_user = context.current_user
+ destination_namespace = context.entity.destination_namespace
+
+ raise(GroupCreationError, 'Path is missing') unless path.present?
+ raise(GroupCreationError, 'Destination is not a group') if user_namespace_destination?(destination_namespace)
+ raise(GroupCreationError, 'User not allowed to create group') unless user_can_create_group?(current_user, data)
+ raise(GroupCreationError, 'Group exists') if group_exists?(destination_namespace, path)
+
+ group = ::Groups::CreateService.new(current_user, data).execute
- group = ::Groups::CreateService.new(context.current_user, data).execute
+ raise(GroupCreationError, group.errors.full_messages.to_sentence) if group.errors.any?
context.entity.update!(group: group)
@@ -25,6 +36,18 @@ module BulkImports
Ability.allowed?(current_user, :create_group)
end
end
+
+ def group_exists?(destination_namespace, path)
+ full_path = destination_namespace.present? ? File.join(destination_namespace, path) : path
+
+ Group.find_by_full_path(full_path).present?
+ end
+
+ def user_namespace_destination?(destination_namespace)
+ return false unless destination_namespace.present?
+
+ Namespace.find_by_full_path(destination_namespace)&.user_namespace?
+ end
end
end
end
diff --git a/lib/bulk_imports/groups/pipelines/milestones_pipeline.rb b/lib/bulk_imports/groups/pipelines/milestones_pipeline.rb
deleted file mode 100644
index b2bd14952e7..00000000000
--- a/lib/bulk_imports/groups/pipelines/milestones_pipeline.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module BulkImports
- module Groups
- module Pipelines
- class MilestonesPipeline
- include NdjsonPipeline
-
- relation_name 'milestones'
-
- extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
- end
- end
- end
-end
diff --git a/lib/bulk_imports/groups/stage.rb b/lib/bulk_imports/groups/stage.rb
index a1869b4cb0e..241dd428dd5 100644
--- a/lib/bulk_imports/groups/stage.rb
+++ b/lib/bulk_imports/groups/stage.rb
@@ -28,7 +28,7 @@ module BulkImports
stage: 1
},
milestones: {
- pipeline: BulkImports::Groups::Pipelines::MilestonesPipeline,
+ pipeline: BulkImports::Common::Pipelines::MilestonesPipeline,
stage: 1
},
badges: {
diff --git a/lib/bulk_imports/ndjson_pipeline.rb b/lib/bulk_imports/ndjson_pipeline.rb
index f01ce22a46d..6cc29d63919 100644
--- a/lib/bulk_imports/ndjson_pipeline.rb
+++ b/lib/bulk_imports/ndjson_pipeline.rb
@@ -13,7 +13,7 @@ module BulkImports
relation_hash, relation_index = data
relation_definition = import_export_config.top_relation_tree(relation)
- deep_transform_relation!(relation_hash, relation, relation_definition) do |key, hash|
+ relation_object = deep_transform_relation!(relation_hash, relation, relation_definition) do |key, hash|
relation_factory.create(
relation_index: relation_index,
relation_sym: key.to_sym,
@@ -25,6 +25,9 @@ module BulkImports
excluded_keys: import_export_config.relation_excluded_keys(key)
)
end
+
+ relation_object.assign_attributes(portable_class_sym => portable)
+ relation_object
end
def load(_, object)
@@ -94,6 +97,10 @@ module BulkImports
def members_mapper
@members_mapper ||= BulkImports::UsersMapper.new(context: context)
end
+
+ def portable_class_sym
+ portable.class.to_s.downcase.to_sym
+ end
end
end
end
diff --git a/lib/bulk_imports/projects/pipelines/external_pull_requests_pipeline.rb b/lib/bulk_imports/projects/pipelines/external_pull_requests_pipeline.rb
new file mode 100644
index 00000000000..1f720596c8f
--- /dev/null
+++ b/lib/bulk_imports/projects/pipelines/external_pull_requests_pipeline.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Pipelines
+ class ExternalPullRequestsPipeline
+ include NdjsonPipeline
+
+ relation_name 'external_pull_requests'
+
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/pipelines/merge_requests_pipeline.rb b/lib/bulk_imports/projects/pipelines/merge_requests_pipeline.rb
new file mode 100644
index 00000000000..264bda6e654
--- /dev/null
+++ b/lib/bulk_imports/projects/pipelines/merge_requests_pipeline.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Pipelines
+ class MergeRequestsPipeline
+ include NdjsonPipeline
+
+ relation_name 'merge_requests'
+
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
+
+ def after_run(_)
+ context.portable.merge_requests.set_latest_merge_request_diff_ids!
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/pipelines/protected_branches_pipeline.rb b/lib/bulk_imports/projects/pipelines/protected_branches_pipeline.rb
new file mode 100644
index 00000000000..a570143227d
--- /dev/null
+++ b/lib/bulk_imports/projects/pipelines/protected_branches_pipeline.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Pipelines
+ class ProtectedBranchesPipeline
+ include NdjsonPipeline
+
+ relation_name 'protected_branches'
+
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/pipelines/repository_pipeline.rb b/lib/bulk_imports/projects/pipelines/repository_pipeline.rb
index 86e696f87a4..6bbd4d0688b 100644
--- a/lib/bulk_imports/projects/pipelines/repository_pipeline.rb
+++ b/lib/bulk_imports/projects/pipelines/repository_pipeline.rb
@@ -17,10 +17,18 @@ module BulkImports
def load(context, data)
url = data['httpUrlToRepo']
url = url.sub("://", "://oauth2:#{context.configuration.access_token}@")
+ project = context.portable
Gitlab::UrlBlocker.validate!(url, allow_local_network: allow_local_requests?, allow_localhost: allow_local_requests?)
- context.portable.repository.import_repository(url)
+ project.ensure_repository
+ project.repository.fetch_as_mirror(url)
+ end
+
+ # The initial fetch can bring in lots of loose refs and objects.
+ # Running a `git gc` will make importing merge requests faster.
+ def after_run(_)
+ ::Repositories::HousekeepingService.new(context.portable, :gc).execute
end
private
diff --git a/lib/bulk_imports/projects/stage.rb b/lib/bulk_imports/projects/stage.rb
index 3ada0f406ca..9ccc9efff1d 100644
--- a/lib/bulk_imports/projects/stage.rb
+++ b/lib/bulk_imports/projects/stage.rb
@@ -19,6 +19,10 @@ module BulkImports
pipeline: BulkImports::Common::Pipelines::LabelsPipeline,
stage: 2
},
+ milestones: {
+ pipeline: BulkImports::Common::Pipelines::MilestonesPipeline,
+ stage: 2
+ },
issues: {
pipeline: BulkImports::Projects::Pipelines::IssuesPipeline,
stage: 3
@@ -27,9 +31,29 @@ module BulkImports
pipeline: BulkImports::Common::Pipelines::BoardsPipeline,
stage: 4
},
+ merge_requests: {
+ pipeline: BulkImports::Projects::Pipelines::MergeRequestsPipeline,
+ stage: 4
+ },
+ external_pull_requests: {
+ pipeline: BulkImports::Projects::Pipelines::ExternalPullRequestsPipeline,
+ stage: 4
+ },
+ protected_branches: {
+ pipeline: BulkImports::Projects::Pipelines::ProtectedBranchesPipeline,
+ stage: 4
+ },
+ wiki: {
+ pipeline: BulkImports::Common::Pipelines::WikiPipeline,
+ stage: 5
+ },
+ uploads: {
+ pipeline: BulkImports::Common::Pipelines::UploadsPipeline,
+ stage: 5
+ },
finisher: {
pipeline: BulkImports::Common::Pipelines::EntityFinisher,
- stage: 5
+ stage: 6
}
}
end
diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb
index 46399224a5d..c2ad9e6ae89 100644
--- a/lib/container_registry/client.rb
+++ b/lib/container_registry/client.rb
@@ -90,7 +90,7 @@ module ContainerRegistry
def repository_tag_digest(name, reference)
response = faraday.head("/v2/#{name}/manifests/#{reference}")
- response.headers['docker-content-digest'] if response.success?
+ response.headers[DependencyProxy::Manifest::DIGEST_HEADER] if response.success?
end
def delete_repository_tag_by_digest(name, reference)
@@ -171,7 +171,7 @@ module ContainerRegistry
req.body = Gitlab::Json.pretty_generate(manifest)
end
- response.headers['docker-content-digest'] if response.success?
+ response.headers[DependencyProxy::Manifest::DIGEST_HEADER] if response.success?
end
private
diff --git a/lib/declarative_enum.rb b/lib/declarative_enum.rb
index 8dea9d6130b..7875e0ba4f3 100644
--- a/lib/declarative_enum.rb
+++ b/lib/declarative_enum.rb
@@ -15,9 +15,9 @@
# TEXT
#
# define do
-# acceptable_risk value: 0, description: 'The vulnerability is known but is considered to be an acceptable business risk.'
-# false_positive value: 1, description: 'An error in reporting the presence of a vulnerability in a system when the vulnerability is not present.'
-# used_in_tests value: 2, description: 'The finding is not a vulnerability because it is part of a test or is test data.'
+# acceptable_risk value: 0, description: N_('The vulnerability is known but is considered to be an acceptable business risk.')
+# false_positive value: 1, description: N_('An error in reporting the presence of a vulnerability in a system when the vulnerability is not present.')
+# used_in_tests value: 2, description: N_('The finding is not a vulnerability because it is part of a test or is test data.')
# end
#
# Then we can use this module to register enums for our Active Record models like so,
@@ -63,6 +63,19 @@ module DeclarativeEnum
@description
end
+ def values
+ definition.transform_values { |definition| definition[:value] }
+ end
+
+ # Return list of dynamically translated descriptions.
+ #
+ # It is required to define descriptions with `N_(...)`.
+ #
+ # See https://github.com/grosser/fast_gettext#n_-and-nn_-make-dynamic-translations-available-to-the-parser
+ def translated_descriptions
+ definition.transform_values { |definition| _(definition[:description]) }
+ end
+
def define(&block)
raise LocalJumpError, 'No block given' unless block
diff --git a/lib/error_tracking/collector/payload_validator.rb b/lib/error_tracking/collector/payload_validator.rb
new file mode 100644
index 00000000000..aae19a3635a
--- /dev/null
+++ b/lib/error_tracking/collector/payload_validator.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module ErrorTracking
+ module Collector
+ class PayloadValidator
+ PAYLOAD_SCHEMA_PATH = Rails.root.join('app', 'validators', 'json_schemas', 'error_tracking_event_payload.json').to_s
+
+ def valid?(payload)
+ JSONSchemer.schema(Pathname.new(PAYLOAD_SCHEMA_PATH)).valid?(payload)
+ end
+ end
+ end
+end
diff --git a/lib/error_tracking/collector/sentry_request_parser.rb b/lib/error_tracking/collector/sentry_request_parser.rb
index 29e4cc8976f..ae632ebd518 100644
--- a/lib/error_tracking/collector/sentry_request_parser.rb
+++ b/lib/error_tracking/collector/sentry_request_parser.rb
@@ -4,15 +4,7 @@ module ErrorTracking
module Collector
class SentryRequestParser
def self.parse(request)
- # Request body can be "" or "gzip".
- # If later then body was compressed with Zlib.gzip
- encoding = request.headers['Content-Encoding']
-
- body = if encoding == 'gzip'
- Zlib.gunzip(request.body.read)
- else
- request.body.read
- end
+ body = request.body.read
# Request body contains 3 json objects merged together in one StringIO.
# We need to separate and parse them into array of hash objects.
diff --git a/lib/feature.rb b/lib/feature.rb
index f8d34e9c386..8186fbc40fa 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -6,6 +6,8 @@ require 'flipper/adapters/active_support_cache_store'
class Feature
# Classes to override flipper table names
class FlipperFeature < Flipper::Adapters::ActiveRecord::Feature
+ include DatabaseReflection
+
# Using `self.table_name` won't work. ActiveRecord bug?
superclass.table_name = 'features'
@@ -36,7 +38,7 @@ class Feature
end
def persisted_names
- return [] unless Gitlab::Database.main.exists?
+ return [] unless ApplicationRecord.database.exists?
# This loads names of all stored feature flags
# and returns a stable Set in the following order:
@@ -73,7 +75,7 @@ class Feature
# During setup the database does not exist yet. So we haven't stored a value
# for the feature yet and return the default.
- return default_enabled unless Gitlab::Database.main.exists?
+ return default_enabled unless ApplicationRecord.database.exists?
feature = get(key)
@@ -155,13 +157,13 @@ class Feature
def flipper
if Gitlab::SafeRequestStore.active?
- Gitlab::SafeRequestStore[:flipper] ||= build_flipper_instance
+ Gitlab::SafeRequestStore[:flipper] ||= build_flipper_instance(memoize: true)
else
@flipper ||= build_flipper_instance
end
end
- def build_flipper_instance
+ def build_flipper_instance(memoize: false)
active_record_adapter = Flipper::Adapters::ActiveRecord.new(
feature_class: FlipperFeature,
gate_class: FlipperGate)
@@ -182,7 +184,7 @@ class Feature
expires_in: 1.minute)
Flipper.new(flipper_adapter).tap do |flip|
- flip.memoize = true
+ flip.memoize = memoize
end
end
diff --git a/lib/feature/gitaly.rb b/lib/feature/gitaly.rb
index a061a83e79c..a1f7dc0ee39 100644
--- a/lib/feature/gitaly.rb
+++ b/lib/feature/gitaly.rb
@@ -15,7 +15,7 @@ class Feature
def server_feature_flags(project = nil)
# We need to check that both the DB connection and table exists
- return {} unless ::Gitlab::Database.main.cached_table_exists?(FlipperFeature.table_name)
+ return {} unless FlipperFeature.database.cached_table_exists?
Feature.persisted_names
.select { |f| f.start_with?(PREFIX) }
diff --git a/lib/generators/gitlab/usage_metric_definition_generator.rb b/lib/generators/gitlab/usage_metric_definition_generator.rb
index 2d65363bf7b..bd34ab0a16f 100644
--- a/lib/generators/gitlab/usage_metric_definition_generator.rb
+++ b/lib/generators/gitlab/usage_metric_definition_generator.rb
@@ -30,18 +30,20 @@ module Gitlab
source_root File.expand_path('../../../generator_templates/usage_metric_definition', __dir__)
- desc 'Generates a metric definition yml file'
+ desc 'Generates metric definitions yml files'
class_option :ee, type: :boolean, optional: true, default: false, desc: 'Indicates if metric is for ee'
class_option :dir,
type: :string, desc: "Indicates the metric location. It must be one of: #{VALID_INPUT_DIRS.join(', ')}"
- argument :key_path, type: :string, desc: 'Unique JSON key path for the metric'
+ argument :key_paths, type: :array, desc: 'Unique JSON key paths for the metrics'
def create_metric_file
validate!
- template "metric_definition.yml", file_path
+ key_paths.each do |key_path|
+ template "metric_definition.yml", file_path(key_path), key_path
+ end
end
def time_frame
@@ -66,12 +68,12 @@ module Gitlab
private
- def metric_name_suggestion
+ def metric_name_suggestion(key_path)
"\nname: \"#{Usage::Metrics::NamesSuggestions::Generator.generate(key_path)}\""
end
- def file_path
- path = File.join(TOP_LEVEL_DIR, 'metrics', directory&.name, "#{file_name}.yml")
+ def file_path(key_path)
+ path = File.join(TOP_LEVEL_DIR, 'metrics', directory&.name, "#{file_name(key_path)}.yml")
path = File.join(TOP_LEVEL_DIR_EE, path) if ee?
path
end
@@ -79,7 +81,10 @@ module Gitlab
def validate!
raise "--dir option is required" unless input_dir.present?
raise "Invalid dir #{input_dir}, allowed options are #{VALID_INPUT_DIRS.join(', ')}" unless directory.present?
- raise "Metric definition with key path '#{key_path}' already exists" if metric_definition_exists?
+
+ key_paths.each do |key_path|
+ raise "Metric definition with key path '#{key_path}' already exists" if metric_definition_exists?(key_path)
+ end
end
def ee?
@@ -93,15 +98,15 @@ module Gitlab
# Example of file name
#
# 20210201124931_g_project_management_issue_title_changed_weekly.yml
- def file_name
- "#{Time.now.utc.strftime("%Y%m%d%H%M%S")}_#{metric_name}"
+ def file_name(key_path)
+ "#{Time.now.utc.strftime("%Y%m%d%H%M%S")}_#{metric_name(key_path)}"
end
def directory
@directory ||= TIME_FRAME_DIRS.find { |d| d.match?(input_dir) }
end
- def metric_name
+ def metric_name(key_path)
key_path.split('.').last
end
@@ -109,7 +114,7 @@ module Gitlab
@definitions ||= Gitlab::Usage::MetricDefinition.definitions(skip_validation: true)
end
- def metric_definition_exists?
+ def metric_definition_exists?(key_path)
metric_definitions[key_path].present?
end
end
diff --git a/lib/generators/post_deployment_migration/post_deployment_migration_generator.rb b/lib/generators/post_deployment_migration/post_deployment_migration_generator.rb
index 66ee0e2440f..792c49a820d 100644
--- a/lib/generators/post_deployment_migration/post_deployment_migration_generator.rb
+++ b/lib/generators/post_deployment_migration/post_deployment_migration_generator.rb
@@ -1,17 +1,13 @@
# frozen_string_literal: true
require 'rails/generators'
+require 'rails/generators/active_record'
+require 'rails/generators/active_record/migration/migration_generator'
module PostDeploymentMigration
- class PostDeploymentMigrationGenerator < Rails::Generators::NamedBase
- def create_migration_file
- timestamp = Time.now.utc.strftime('%Y%m%d%H%M%S')
-
- template "migration.rb", "db/post_migrate/#{timestamp}_#{file_name}.rb"
- end
-
- def migration_class_name
- file_name.camelize
+ class PostDeploymentMigrationGenerator < ActiveRecord::Generators::MigrationGenerator
+ def db_migrate_path
+ super.sub("migrate", "post_migrate")
end
end
end
diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb
index d3c96a0f934..3e09d488bc3 100644
--- a/lib/gitlab/access.rb
+++ b/lib/gitlab/access.rb
@@ -74,16 +74,32 @@ module Gitlab
end
def protection_options
- {
- "Not protected: Both developers and maintainers can push new commits and force push." => PROTECTION_NONE,
- "Protected against pushes: Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch." => PROTECTION_DEV_CAN_MERGE,
- "Partially protected: Both developers and maintainers can push new commits, but cannot force push." => PROTECTION_DEV_CAN_PUSH,
- "Fully protected: Developers cannot push new commits, but maintainers can. No one can force push." => PROTECTION_FULL
- }
+ [
+ {
+ label: s_('DefaultBranchProtection|Not protected'),
+ help_text: s_('DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch.'),
+ value: PROTECTION_NONE
+ },
+ {
+ label: s_('DefaultBranchProtection|Protected against pushes'),
+ help_text: s_('DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch.'),
+ value: PROTECTION_DEV_CAN_MERGE
+ },
+ {
+ label: s_('DefaultBranchProtection|Partially protected'),
+ help_text: s_('DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push.'),
+ value: PROTECTION_DEV_CAN_PUSH
+ },
+ {
+ label: s_('DefaultBranchProtection|Fully protected'),
+ help_text: s_('DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push.'),
+ value: PROTECTION_FULL
+ }
+ ]
end
def protection_values
- protection_options.values
+ protection_options.map { |option| option[:value] }
end
def human_access(access)
diff --git a/lib/gitlab/action_cable/config.rb b/lib/gitlab/action_cable/config.rb
index 38e870353eb..77d4ec0733d 100644
--- a/lib/gitlab/action_cable/config.rb
+++ b/lib/gitlab/action_cable/config.rb
@@ -4,10 +4,6 @@ module Gitlab
module ActionCable
class Config
class << self
- def in_app?
- Gitlab::Utils.to_boolean(ENV.fetch('ACTION_CABLE_IN_APP', false))
- end
-
def worker_pool_size
ENV.fetch('ACTION_CABLE_WORKER_POOL_SIZE', 4).to_i
end
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb
new file mode 100644
index 00000000000..1e50c980a3a
--- /dev/null
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Analytics
+ module CycleAnalytics
+ module Aggregated
+ # rubocop: disable CodeReuse/ActiveRecord
+ class BaseQueryBuilder
+ include StageQueryHelpers
+
+ MODEL_CLASSES = {
+ MergeRequest.to_s => ::Analytics::CycleAnalytics::MergeRequestStageEvent,
+ Issue.to_s => ::Analytics::CycleAnalytics::IssueStageEvent
+ }.freeze
+
+ # Allowed params:
+ # * from - stage end date filter start date
+ # * to - stage end date filter to date
+ # * author_username
+ # * milestone_title
+ # * label_name (array)
+ # * assignee_username (array)
+ # * project_ids (array)
+ def initialize(stage:, params: {})
+ @stage = stage
+ @params = params
+ @root_ancestor = stage.parent.root_ancestor
+ @stage_event_model = MODEL_CLASSES.fetch(stage.subject_class.to_s)
+ end
+
+ def build
+ query = base_query
+ query = filter_by_stage_parent(query)
+ query = filter_author(query)
+ query = filter_milestone_ids(query)
+ query = filter_label_names(query)
+ filter_assignees(query)
+ end
+
+ def filter_author(query)
+ return query if params[:author_username].blank?
+
+ user = User.by_username(params[:author_username]).first
+
+ return query.none if user.blank?
+
+ query.authored(user)
+ end
+
+ def filter_milestone_ids(query)
+ return query if params[:milestone_title].blank?
+
+ milestone = MilestonesFinder
+ .new(group_ids: root_ancestor.self_and_descendant_ids, project_ids: root_ancestor.all_projects.select(:id), title: params[:milestone_title])
+ .execute
+ .first
+
+ return query.none if milestone.blank?
+
+ query.with_milestone_id(milestone.id)
+ end
+
+ def filter_label_names(query)
+ return query if params[:label_name].blank?
+
+ LabelFilter.new(
+ stage: stage,
+ params: params,
+ project: nil,
+ group: root_ancestor
+ ).filter(query)
+ end
+
+ def filter_assignees(query)
+ return query if params[:assignee_username].blank?
+
+ Issuables::AssigneeFilter
+ .new(params: { assignee_username: params[:assignee_username] })
+ .filter(query)
+ end
+
+ def filter_by_stage_parent(query)
+ query.by_project_id(stage.parent_id)
+ end
+
+ def base_query
+ query = stage_event_model
+ .by_stage_event_hash_id(stage.stage_event_hash_id)
+
+ from = params[:from] || 30.days.ago
+ if in_progress?
+ query = query
+ .end_event_is_not_happened_yet
+ .opened_state
+ .start_event_timestamp_after(from)
+ query = query.start_event_timestamp_before(params[:to]) if params[:to]
+ else
+ query = query.end_event_timestamp_after(from)
+ query = query.end_event_timestamp_before(params[:to]) if params[:to]
+ end
+
+ query
+ end
+
+ private
+
+ attr_reader :stage, :params, :root_ancestor, :stage_event_model
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+ end
+end
+Gitlab::Analytics::CycleAnalytics::Aggregated::BaseQueryBuilder.prepend_mod_with('Gitlab::Analytics::CycleAnalytics::Aggregated::BaseQueryBuilder')
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb
new file mode 100644
index 00000000000..c8b11ecb4a8
--- /dev/null
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Analytics
+ module CycleAnalytics
+ module Aggregated
+ # Arguments:
+ # stage - an instance of CycleAnalytics::ProjectStage or CycleAnalytics::GroupStage
+ # params:
+ # current_user: an instance of User
+ # from: DateTime
+ # to: DateTime
+ class DataCollector
+ include Gitlab::Utils::StrongMemoize
+
+ MAX_COUNT = 10001
+
+ delegate :serialized_records, to: :records_fetcher
+
+ def initialize(stage:, params: {})
+ @stage = stage
+ @params = params
+ end
+
+ def median
+ strong_memoize(:median) { Median.new(stage: stage, query: query, params: params) }
+ end
+
+ def count
+ strong_memoize(:count) { limit_count }
+ end
+
+ def records_fetcher
+ strong_memoize(:records_fetcher) do
+ RecordsFetcher.new(stage: stage, query: query, params: params)
+ end
+ end
+
+ private
+
+ attr_reader :stage, :params
+
+ def query
+ BaseQueryBuilder.new(stage: stage, params: params).build
+ end
+
+ def limit_count
+ query.limit(MAX_COUNT).count
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/label_filter.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/label_filter.rb
new file mode 100644
index 00000000000..6d87ae91a9c
--- /dev/null
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/label_filter.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Analytics
+ module CycleAnalytics
+ module Aggregated
+ # This class makes it possible to add label filters to stage event tables
+ class LabelFilter < Issuables::LabelFilter
+ extend ::Gitlab::Utils::Override
+
+ def initialize(stage:, project:, group:, **kwargs)
+ @stage = stage
+
+ super(project: project, group: group, **kwargs)
+ end
+
+ private
+
+ attr_reader :stage
+
+ override :label_link_query
+ def label_link_query(target_model, label_ids: nil)
+ join_column = target_model.arel_table[target_model.issuable_id_column]
+
+ LabelLink.by_target_for_exists_query(stage.subject_class.name, join_column, label_ids)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/median.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/median.rb
new file mode 100644
index 00000000000..181ee20948b
--- /dev/null
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/median.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Analytics
+ module CycleAnalytics
+ module Aggregated
+ class Median
+ include StageQueryHelpers
+
+ def initialize(stage:, query:, params:)
+ @stage = stage
+ @query = query
+ @params = params
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def seconds
+ @query = @query.select(median_duration_in_seconds.as('median')).reorder(nil)
+ result = @query.take || {}
+
+ result['median'] || nil
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def days
+ seconds ? seconds.fdiv(1.day) : nil
+ end
+
+ private
+
+ attr_reader :stage, :query, :params
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb
new file mode 100644
index 00000000000..7dce757cdc8
--- /dev/null
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb
@@ -0,0 +1,116 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Analytics
+ module CycleAnalytics
+ module Aggregated
+ class RecordsFetcher
+ include Gitlab::Utils::StrongMemoize
+ include StageQueryHelpers
+
+ MAX_RECORDS = 20
+
+ MAPPINGS = {
+ Issue => {
+ serializer_class: AnalyticsIssueSerializer,
+ includes_for_query: { project: { namespace: [:route] }, author: [] },
+ columns_for_select: %I[title iid id created_at author_id project_id]
+ },
+ MergeRequest => {
+ serializer_class: AnalyticsMergeRequestSerializer,
+ includes_for_query: { target_project: [:namespace], author: [] },
+ columns_for_select: %I[title iid id created_at author_id state_id target_project_id]
+ }
+ }.freeze
+
+ def initialize(stage:, query:, params: {})
+ @stage = stage
+ @query = query
+ @params = params
+ @sort = params[:sort] || :end_event
+ @direction = params[:direction] || :desc
+ @page = params[:page] || 1
+ @per_page = MAX_RECORDS
+ @stage_event_model = query.model
+ end
+
+ def serialized_records
+ strong_memoize(:serialized_records) do
+ records = ordered_and_limited_query.select(stage_event_model.arel_table[Arel.star], duration.as('total_time'))
+
+ yield records if block_given?
+ issuables_and_records = load_issuables(records)
+
+ preload_associations(issuables_and_records.map(&:first))
+
+ issuables_and_records.map do |issuable, record|
+ project = issuable.project
+ attributes = issuable.attributes.merge({
+ project_path: project.path,
+ namespace_path: project.namespace.route.path,
+ author: issuable.author,
+ total_time: record.total_time
+ })
+ serializer.represent(attributes)
+ end
+ end
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def ordered_and_limited_query
+ sorting_options = {
+ end_event: {
+ asc: -> { query.order(end_event_timestamp: :asc) },
+ desc: -> { query.order(end_event_timestamp: :desc) }
+ },
+ duration: {
+ asc: -> { query.order(duration.asc) },
+ desc: -> { query.order(duration.desc) }
+ }
+ }
+
+ sort_lambda = sorting_options.dig(sort, direction) || sorting_options.dig(:end_event, :desc)
+
+ sort_lambda.call
+ .page(page)
+ .per(per_page)
+ .without_count
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ private
+
+ attr_reader :stage, :query, :sort, :direction, :params, :page, :per_page, :stage_event_model
+
+ delegate :subject_class, to: :stage
+
+ def load_issuables(stage_event_records)
+ stage_event_records_by_issuable_id = stage_event_records.index_by(&:issuable_id)
+
+ issuable_model = stage_event_model.issuable_model
+ issuables_by_id = issuable_model.id_in(stage_event_records_by_issuable_id.keys).index_by(&:id)
+
+ stage_event_records_by_issuable_id.map do |issuable_id, record|
+ [issuables_by_id[issuable_id], record] if issuables_by_id[issuable_id]
+ end.compact
+ end
+
+ def serializer
+ MAPPINGS.fetch(subject_class).fetch(:serializer_class).new
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def preload_associations(records)
+ ActiveRecord::Associations::Preloader.new.preload(
+ records,
+ MAPPINGS.fetch(subject_class).fetch(:includes_for_query)
+ )
+
+ records
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/stage_query_helpers.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/stage_query_helpers.rb
new file mode 100644
index 00000000000..f23d1832df9
--- /dev/null
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/stage_query_helpers.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Analytics
+ module CycleAnalytics
+ module Aggregated
+ module StageQueryHelpers
+ def percentile_cont
+ percentile_cont_ordering = Arel::Nodes::UnaryOperation.new(Arel::Nodes::SqlLiteral.new('ORDER BY'), duration)
+ Arel::Nodes::NamedFunction.new(
+ 'percentile_cont(0.5) WITHIN GROUP',
+ [percentile_cont_ordering]
+ )
+ end
+
+ def duration
+ if in_progress?
+ Arel::Nodes::Subtraction.new(
+ Arel::Nodes::NamedFunction.new('TO_TIMESTAMP', [Time.current.to_i]),
+ query.model.arel_table[:start_event_timestamp]
+ )
+ else
+ Arel::Nodes::Subtraction.new(
+ query.model.arel_table[:end_event_timestamp],
+ query.model.arel_table[:start_event_timestamp]
+ )
+ end
+ end
+
+ def median_duration_in_seconds
+ Arel::Nodes::Extract.new(percentile_cont, :epoch)
+ end
+
+ def in_progress?
+ params[:end_event_filter] == :in_progress
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/analytics/cycle_analytics/data_collector.rb b/lib/gitlab/analytics/cycle_analytics/data_collector.rb
index 56179533ffb..a20481dd39e 100644
--- a/lib/gitlab/analytics/cycle_analytics/data_collector.rb
+++ b/lib/gitlab/analytics/cycle_analytics/data_collector.rb
@@ -23,13 +23,21 @@ module Gitlab
def records_fetcher
strong_memoize(:records_fetcher) do
- RecordsFetcher.new(stage: stage, query: query, params: params)
+ if use_aggregated_data_collector?
+ aggregated_data_collector.records_fetcher
+ else
+ RecordsFetcher.new(stage: stage, query: query, params: params)
+ end
end
end
def median
strong_memoize(:median) do
- Median.new(stage: stage, query: query, params: params)
+ if use_aggregated_data_collector?
+ aggregated_data_collector.median
+ else
+ Median.new(stage: stage, query: query, params: params)
+ end
end
end
@@ -41,7 +49,11 @@ module Gitlab
def count
strong_memoize(:count) do
- limit_count
+ if use_aggregated_data_collector?
+ aggregated_data_collector.count
+ else
+ limit_count
+ end
end
end
@@ -59,6 +71,14 @@ module Gitlab
def limit_count
query.limit(MAX_COUNT).count
end
+
+ def aggregated_data_collector
+ @aggregated_data_collector ||= Aggregated::DataCollector.new(stage: stage, params: params)
+ end
+
+ def use_aggregated_data_collector?
+ params.fetch(:use_aggregated_data_collector, false)
+ end
end
end
end
diff --git a/lib/gitlab/analytics/cycle_analytics/records_fetcher.rb b/lib/gitlab/analytics/cycle_analytics/records_fetcher.rb
index f94696e3186..140c4a300ca 100644
--- a/lib/gitlab/analytics/cycle_analytics/records_fetcher.rb
+++ b/lib/gitlab/analytics/cycle_analytics/records_fetcher.rb
@@ -8,23 +8,11 @@ module Gitlab
include StageQueryHelpers
include Gitlab::CycleAnalytics::MetricsTables
- MAX_RECORDS = 20
-
- MAPPINGS = {
- Issue => {
- serializer_class: AnalyticsIssueSerializer,
- includes_for_query: { project: { namespace: [:route] }, author: [] },
- columns_for_select: %I[title iid id created_at author_id project_id]
- },
- MergeRequest => {
- serializer_class: AnalyticsMergeRequestSerializer,
- includes_for_query: { target_project: [:namespace], author: [] },
- columns_for_select: %I[title iid id created_at author_id state_id target_project_id]
- }
- }.freeze
-
delegate :subject_class, to: :stage
+ MAX_RECORDS = Gitlab::Analytics::CycleAnalytics::Aggregated::RecordsFetcher::MAX_RECORDS
+ MAPPINGS = Gitlab::Analytics::CycleAnalytics::Aggregated::RecordsFetcher::MAPPINGS
+
def initialize(stage:, query:, params: {})
@stage = stage
@query = query
diff --git a/lib/gitlab/analytics/cycle_analytics/request_params.rb b/lib/gitlab/analytics/cycle_analytics/request_params.rb
index 94e20762368..bc9d94ef09c 100644
--- a/lib/gitlab/analytics/cycle_analytics/request_params.rb
+++ b/lib/gitlab/analytics/cycle_analytics/request_params.rb
@@ -79,7 +79,8 @@ module Gitlab
sort: sort&.to_sym,
direction: direction&.to_sym,
page: page,
- end_event_filter: end_event_filter.to_sym
+ end_event_filter: end_event_filter.to_sym,
+ use_aggregated_data_collector: Feature.enabled?(:use_vsa_aggregated_tables, group || project, default_enabled: :yaml)
}.merge(attributes.symbolize_keys.slice(*FINDER_PARAM_NAMES))
end
diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb
index 7c37f67b766..3db2f1295f9 100644
--- a/lib/gitlab/application_rate_limiter.rb
+++ b/lib/gitlab/application_rate_limiter.rb
@@ -11,6 +11,8 @@ module Gitlab
# redirect_to(edit_project_path(@project), status: :too_many_requests)
# end
class ApplicationRateLimiter
+ InvalidKeyError = Class.new(StandardError)
+
def initialize(key, **options)
@key = key
@options = options
@@ -64,39 +66,43 @@ module Gitlab
# @param key [Symbol] Key attribute registered in `.rate_limits`
# @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
# @option threshold [Integer] Optional threshold value to override default one registered in `.rate_limits`
- # @option interval [Integer] Optional interval value to override default one registered in `.rate_limits`
# @option users_allowlist [Array<String>] Optional list of usernames to exclude from the limit. This param will only be functional if Scope includes a current user.
#
# @return [Boolean] Whether or not a request should be throttled
def throttled?(key, **options)
- return unless rate_limits[key]
+ raise InvalidKeyError unless rate_limits[key]
return if scoped_user_in_allowlist?(options)
threshold_value = options[:threshold] || threshold(key)
threshold_value > 0 &&
- increment(key, options[:scope], options[:interval]) > threshold_value
+ increment(key, options[:scope]) > threshold_value
end
- # Increments the given cache key and increments the value by 1 with the
- # expiration interval defined in `.rate_limits`.
+ # Increments a cache key that is based on the current time and interval.
+ # So that when time passes to the next interval, the key changes and the count starts again from 0.
+ #
+ # Based on https://github.com/rack/rack-attack/blob/886ba3a18d13c6484cd511a4dc9b76c0d14e5e96/lib/rack/attack/cache.rb#L63-L68
#
# @param key [Symbol] Key attribute registered in `.rate_limits`
# @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
- # @option interval [Integer] Optional interval value to override default one registered in `.rate_limits`
#
# @return [Integer] incremented value
- def increment(key, scope, interval = nil)
- value = 0
- interval_value = interval || interval(key)
+ def increment(key, scope)
+ interval_value = interval(key)
+
+ period_key, time_elapsed_in_period = Time.now.to_i.divmod(interval_value)
+
+ cache_key = "#{action_key(key, scope)}:#{period_key}"
+ # We add a 1 second buffer to avoid timing issues when we're at the end of a period
+ expiry = interval_value - time_elapsed_in_period + 1
::Gitlab::Redis::RateLimiting.with do |redis|
- cache_key = action_key(key, scope)
- value = redis.incr(cache_key)
- redis.expire(cache_key, interval_value) if value == 1
+ redis.pipelined do
+ redis.incr(cache_key)
+ redis.expire(cache_key, expiry)
+ end.first
end
-
- value
end
# Logs request using provided logger
diff --git a/lib/gitlab/asciidoc/syntax_highlighter/html_pipeline_adapter.rb b/lib/gitlab/asciidoc/syntax_highlighter/html_pipeline_adapter.rb
index 5fc3323f0fd..6dbe6f691f6 100644
--- a/lib/gitlab/asciidoc/syntax_highlighter/html_pipeline_adapter.rb
+++ b/lib/gitlab/asciidoc/syntax_highlighter/html_pipeline_adapter.rb
@@ -7,7 +7,11 @@ module Gitlab
register_for 'gitlab-html-pipeline'
def format(node, lang, opts)
- %(<pre><code #{lang ? %[ lang="#{lang}"] : ''}>#{node.content}</code></pre>)
+ if Feature.enabled?(:use_cmark_renderer)
+ %(<pre #{lang ? %[lang="#{lang}"] : ''}><code>#{node.content}</code></pre>)
+ else
+ %(<pre><code #{lang ? %[ lang="#{lang}"] : ''}>#{node.content}</code></pre>)
+ end
end
end
end
diff --git a/lib/gitlab/auth/o_auth/provider.rb b/lib/gitlab/auth/o_auth/provider.rb
index ab6ac815601..41a8739b0b6 100644
--- a/lib/gitlab/auth/o_auth/provider.rb
+++ b/lib/gitlab/auth/o_auth/provider.rb
@@ -5,6 +5,7 @@ module Gitlab
module OAuth
class Provider
LABELS = {
+ "dingtalk" => "DingTalk",
"github" => "GitHub",
"gitlab" => "GitLab.com",
"google_oauth2" => "Google",
diff --git a/lib/gitlab/background_migration.rb b/lib/gitlab/background_migration.rb
index 0826887dd0a..22b4b685f81 100644
--- a/lib/gitlab/background_migration.rb
+++ b/lib/gitlab/background_migration.rb
@@ -2,8 +2,12 @@
module Gitlab
module BackgroundMigration
- def self.queue
- @queue ||= BackgroundMigrationWorker.sidekiq_options['queue']
+ def self.coordinator_for_database(database)
+ JobCoordinator.for_database(database)
+ end
+
+ def self.queue(database: :main)
+ coordinator_for_database(database).queue
end
# Begins stealing jobs from the background migrations queue, blocking the
@@ -16,35 +20,10 @@ module Gitlab
# re-raises the exception.
#
# steal_class - The name of the class for which to steal jobs.
- def self.steal(steal_class, retry_dead_jobs: false)
- queues = [
- Sidekiq::ScheduledSet.new,
- Sidekiq::Queue.new(self.queue)
- ]
-
- if retry_dead_jobs
- queues << Sidekiq::RetrySet.new
- queues << Sidekiq::DeadSet.new
- end
-
- queues.each do |queue|
- queue.each do |job|
- migration_class, migration_args = job.args
-
- next unless job.klass == 'BackgroundMigrationWorker'
- next unless migration_class == steal_class
- next if block_given? && !(yield job)
-
- begin
- perform(migration_class, migration_args) if job.delete
- rescue Exception # rubocop:disable Lint/RescueException
- BackgroundMigrationWorker # enqueue this migration again
- .perform_async(migration_class, migration_args)
-
- raise
- end
- end
- end
+ # retry_dead_jobs - Flag to control whether jobs in Sidekiq::RetrySet or Sidekiq::DeadSet are retried.
+ # database - tracking database this migration executes against
+ def self.steal(steal_class, retry_dead_jobs: false, database: :main, &block)
+ coordinator_for_database(database).steal(steal_class, retry_dead_jobs: retry_dead_jobs, &block)
end
##
@@ -55,64 +34,17 @@ module Gitlab
#
# arguments - The arguments to pass to the background migration's "perform"
# method.
- def self.perform(class_name, arguments)
- migration_class_for(class_name).new.perform(*arguments)
- end
-
- def self.remaining
- enqueued = Sidekiq::Queue.new(self.queue)
- scheduled = Sidekiq::ScheduledSet.new
-
- [enqueued, scheduled].sum do |set|
- set.count do |job|
- job.klass == 'BackgroundMigrationWorker'
- end
- end
- end
-
- def self.exists?(migration_class, additional_queues = [])
- enqueued = Sidekiq::Queue.new(self.queue)
- scheduled = Sidekiq::ScheduledSet.new
-
- enqueued_job?([enqueued, scheduled], migration_class)
- end
-
- def self.dead_jobs?(migration_class)
- dead_set = Sidekiq::DeadSet.new
-
- enqueued_job?([dead_set], migration_class)
+ # database - tracking database this migration executes against
+ def self.perform(class_name, arguments, database: :main)
+ coordinator_for_database(database).perform(class_name, arguments)
end
- def self.retrying_jobs?(migration_class)
- retry_set = Sidekiq::RetrySet.new
-
- enqueued_job?([retry_set], migration_class)
- end
-
- def self.migration_class_for(class_name)
- # We don't pass class name with Gitlab::BackgroundMigration:: prefix anymore
- # but some jobs could be already spawned so we need to have some backward compatibility period.
- # Can be removed since 13.x
- full_class_name_prefix_regexp = /\A(::)?Gitlab::BackgroundMigration::/
-
- if class_name.match(full_class_name_prefix_regexp)
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(
- StandardError.new("Full class name is used"),
- class_name: class_name
- )
-
- class_name = class_name.sub(full_class_name_prefix_regexp, '')
- end
-
- const_get(class_name, false)
+ def self.exists?(migration_class, additional_queues = [], database: :main)
+ coordinator_for_database(database).exists?(migration_class, additional_queues) # rubocop:disable CodeReuse/ActiveRecord
end
- def self.enqueued_job?(queues, migration_class)
- queues.any? do |queue|
- queue.any? do |job|
- job.klass == 'BackgroundMigrationWorker' && job.args.first == migration_class
- end
- end
+ def self.remaining(database: :main)
+ coordinator_for_database(database).remaining
end
end
end
diff --git a/lib/gitlab/background_migration/add_primary_email_to_emails_if_user_confirmed.rb b/lib/gitlab/background_migration/add_primary_email_to_emails_if_user_confirmed.rb
new file mode 100644
index 00000000000..b39c0953fb1
--- /dev/null
+++ b/lib/gitlab/background_migration/add_primary_email_to_emails_if_user_confirmed.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Add user primary email to emails table if confirmed
+ class AddPrimaryEmailToEmailsIfUserConfirmed
+ INNER_BATCH_SIZE = 1_000
+
+ # Stubbed class to access the User table
+ class User < ActiveRecord::Base
+ include ::EachBatch
+
+ self.table_name = 'users'
+ self.inheritance_column = :_type_disabled
+
+ scope :confirmed, -> { where.not(confirmed_at: nil) }
+
+ has_many :emails
+ end
+
+ # Stubbed class to access the Emails table
+ class Email < ActiveRecord::Base
+ self.table_name = 'emails'
+ self.inheritance_column = :_type_disabled
+
+ belongs_to :user
+ end
+
+ def perform(start_id, end_id)
+ User.confirmed.where(id: start_id..end_id).select(:id, :email, :confirmed_at).each_batch(of: INNER_BATCH_SIZE) do |users|
+ current_time = Time.now.utc
+
+ attributes = users.map do |user|
+ {
+ user_id: user.id,
+ email: user.email,
+ confirmed_at: user.confirmed_at,
+ created_at: current_time,
+ updated_at: current_time
+ }
+ end
+
+ Email.insert_all(attributes)
+ end
+ mark_job_as_succeeded(start_id, end_id)
+ end
+
+ private
+
+ def mark_job_as_succeeded(*arguments)
+ Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
+ 'AddPrimaryEmailToEmailsIfUserConfirmed',
+ arguments
+ )
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/backfill_design_internal_ids.rb b/lib/gitlab/background_migration/backfill_design_internal_ids.rb
deleted file mode 100644
index 236c6b6eb9a..00000000000
--- a/lib/gitlab/background_migration/backfill_design_internal_ids.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Backfill design.iid for a range of projects
- class BackfillDesignInternalIds
- # See app/models/internal_id
- # This is a direct copy of the application code with the following changes:
- # - usage enum is hard-coded to the value for design_management_designs
- # - init is not passed around, but ignored
- class InternalId < ActiveRecord::Base
- def self.track_greatest(subject, scope, new_value)
- InternalIdGenerator.new(subject, scope).track_greatest(new_value)
- end
-
- # Increments #last_value with new_value if it is greater than the current,
- # and saves the record
- #
- # The operation locks the record and gathers a `ROW SHARE` lock (in PostgreSQL).
- # As such, the increment is atomic and safe to be called concurrently.
- def track_greatest_and_save!(new_value)
- update_and_save { self.last_value = [last_value || 0, new_value].max }
- end
-
- private
-
- def update_and_save(&block)
- lock!
- yield
- # update_and_save_counter.increment(usage: usage, changed: last_value_changed?)
- save!
- last_value
- end
- end
-
- # See app/models/internal_id
- class InternalIdGenerator
- attr_reader :subject, :scope, :scope_attrs
-
- def initialize(subject, scope)
- @subject = subject
- @scope = scope
-
- raise ArgumentError, 'Scope is not well-defined, need at least one column for scope (given: 0)' if scope.empty?
- end
-
- # Create a record in internal_ids if one does not yet exist
- # and set its new_value if it is higher than the current last_value
- #
- # Note this will acquire a ROW SHARE lock on the InternalId record
- def track_greatest(new_value)
- subject.transaction do
- record.track_greatest_and_save!(new_value)
- end
- end
-
- def record
- @record ||= (lookup || create_record)
- end
-
- def lookup
- InternalId.find_by(**scope, usage: usage_value)
- end
-
- def usage_value
- 10 # see Enums::InternalId - this is the value for design_management_designs
- end
-
- # Create InternalId record for (scope, usage) combination, if it doesn't exist
- #
- # We blindly insert without synchronization. If another process
- # was faster in doing this, we'll realize once we hit the unique key constraint
- # violation. We can safely roll-back the nested transaction and perform
- # a lookup instead to retrieve the record.
- def create_record
- subject.transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
- InternalId.create!(
- **scope,
- usage: usage_value,
- last_value: 0
- )
- end
- rescue ActiveRecord::RecordNotUnique
- lookup
- end
- end
-
- attr_reader :design_class
-
- def initialize(design_class)
- @design_class = design_class
- end
-
- def perform(relation)
- start_id, end_id = relation.pluck("min(project_id), max(project_id)").flatten
- table = 'design_management_designs'
-
- ActiveRecord::Base.connection.execute <<~SQL
- WITH
- starting_iids(project_id, iid) as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported}(
- SELECT project_id, MAX(COALESCE(iid, 0))
- FROM #{table}
- WHERE project_id BETWEEN #{start_id} AND #{end_id}
- GROUP BY project_id
- ),
- with_calculated_iid(id, iid) as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported}(
- SELECT design.id,
- init.iid + ROW_NUMBER() OVER (PARTITION BY design.project_id ORDER BY design.id ASC)
- FROM #{table} as design, starting_iids as init
- WHERE design.project_id BETWEEN #{start_id} AND #{end_id}
- AND design.iid IS NULL
- AND init.project_id = design.project_id
- )
-
- UPDATE #{table}
- SET iid = with_calculated_iid.iid
- FROM with_calculated_iid
- WHERE #{table}.id = with_calculated_iid.id
- SQL
-
- # track the new greatest IID value
- relation.each do |design|
- current_max = design_class.where(project_id: design.project_id).maximum(:iid)
- scope = { project_id: design.project_id }
- InternalId.track_greatest(design, scope, current_max)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_project_repositories.rb b/lib/gitlab/background_migration/backfill_project_repositories.rb
index a9eaeb0562d..05e2ed72fb3 100644
--- a/lib/gitlab/background_migration/backfill_project_repositories.rb
+++ b/lib/gitlab/background_migration/backfill_project_repositories.rb
@@ -189,7 +189,7 @@ module Gitlab
end
def perform(start_id, stop_id)
- Gitlab::Database.main.bulk_insert(:project_repositories, project_repositories(start_id, stop_id)) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(:project_repositories, project_repositories(start_id, stop_id)) # rubocop:disable Gitlab/BulkInsert
end
private
diff --git a/lib/gitlab/background_migration/backfill_user_namespace.rb b/lib/gitlab/background_migration/backfill_user_namespace.rb
new file mode 100644
index 00000000000..f55eaa3b14e
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_user_namespace.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Backfills the `namespaces.type` column, replacing any
+ # instances of `NULL` with `User`
+ class BackfillUserNamespace
+ include Gitlab::Database::DynamicModelHelpers
+
+ def perform(start_id, end_id, batch_table, batch_column, sub_batch_size, pause_ms)
+ parent_batch_relation = relation_scoped_to_range(batch_table, batch_column, start_id, end_id)
+ parent_batch_relation.each_batch(column: batch_column, of: sub_batch_size, order_hint: :type) do |sub_batch|
+ batch_metrics.time_operation(:update_all) do
+ sub_batch.update_all(type: 'User')
+ end
+ pause_ms = 0 if pause_ms < 0
+ sleep(pause_ms * 0.001)
+ end
+ end
+
+ def batch_metrics
+ @batch_metrics ||= Gitlab::Database::BackgroundMigration::BatchMetrics.new
+ end
+
+ private
+
+ def connection
+ ActiveRecord::Base.connection
+ end
+
+ def relation_scoped_to_range(source_table, source_key_column, start_id, stop_id)
+ define_batchable_model(source_table)
+ .where(source_key_column => start_id..stop_id)
+ .where(type: nil)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb b/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb
deleted file mode 100644
index 691bdb457d7..00000000000
--- a/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class CopyMergeRequestTargetProjectToMergeRequestMetrics
- extend ::Gitlab::Utils::Override
-
- def perform(start_id, stop_id)
- ActiveRecord::Base.connection.execute <<~SQL
- WITH merge_requests_batch AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- SELECT id, target_project_id
- FROM merge_requests WHERE id BETWEEN #{Integer(start_id)} AND #{Integer(stop_id)}
- )
- UPDATE
- merge_request_metrics
- SET
- target_project_id = merge_requests_batch.target_project_id
- FROM merge_requests_batch
- WHERE merge_request_metrics.merge_request_id=merge_requests_batch.id
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/fix_merge_request_diff_commit_users.rb b/lib/gitlab/background_migration/fix_merge_request_diff_commit_users.rb
new file mode 100644
index 00000000000..ea3e56cb14a
--- /dev/null
+++ b/lib/gitlab/background_migration/fix_merge_request_diff_commit_users.rb
@@ -0,0 +1,156 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Background migration for fixing merge_request_diff_commit rows that don't
+ # have committer/author details due to
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/344080.
+ #
+ # This migration acts on a single project and corrects its data. Because
+ # this process needs Git/Gitaly access, and duplicating all that code is far
+ # too much, this migration relies on global models such as Project,
+ # MergeRequest, etc.
+ # rubocop: disable Metrics/ClassLength
+ class FixMergeRequestDiffCommitUsers
+ BATCH_SIZE = 100
+
+ def initialize
+ @commits = {}
+ @users = {}
+ end
+
+ def perform(project_id)
+ if (project = ::Project.find_by_id(project_id))
+ process(project)
+ end
+
+ ::Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
+ 'FixMergeRequestDiffCommitUsers',
+ [project_id]
+ )
+
+ schedule_next_job
+ end
+
+ def process(project)
+ # Loading everything using one big query may result in timeouts (e.g.
+ # for projects the size of gitlab-org/gitlab). So instead we query
+ # data on a per merge request basis.
+ project.merge_requests.each_batch(column: :iid) do |mrs|
+ mrs.ids.each do |mr_id|
+ each_row_to_check(mr_id) do |commit|
+ update_commit(project, commit)
+ end
+ end
+ end
+ end
+
+ def each_row_to_check(merge_request_id, &block)
+ columns = %w[merge_request_diff_id relative_order].map do |col|
+ Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: col,
+ order_expression: MergeRequestDiffCommit.arel_table[col.to_sym].asc,
+ nullable: :not_nullable,
+ distinct: false
+ )
+ end
+
+ order = Pagination::Keyset::Order.build(columns)
+ scope = MergeRequestDiffCommit
+ .joins(:merge_request_diff)
+ .where(merge_request_diffs: { merge_request_id: merge_request_id })
+ .where('commit_author_id IS NULL OR committer_id IS NULL')
+ .order(order)
+
+ Pagination::Keyset::Iterator
+ .new(scope: scope, use_union_optimization: true)
+ .each_batch(of: BATCH_SIZE) do |rows|
+ rows
+ .select([
+ :merge_request_diff_id,
+ :relative_order,
+ :sha,
+ :committer_id,
+ :commit_author_id
+ ])
+ .each(&block)
+ end
+ end
+
+ # rubocop: disable Metrics/AbcSize
+ def update_commit(project, row)
+ commit = find_commit(project, row.sha)
+ updates = []
+
+ unless row.commit_author_id
+ author_id = find_or_create_user(commit, :author_name, :author_email)
+
+ updates << [arel_table[:commit_author_id], author_id] if author_id
+ end
+
+ unless row.committer_id
+ committer_id =
+ find_or_create_user(commit, :committer_name, :committer_email)
+
+ updates << [arel_table[:committer_id], committer_id] if committer_id
+ end
+
+ return if updates.empty?
+
+ update = Arel::UpdateManager
+ .new
+ .table(MergeRequestDiffCommit.arel_table)
+ .where(matches_row(row))
+ .set(updates)
+ .to_sql
+
+ MergeRequestDiffCommit.connection.execute(update)
+ end
+ # rubocop: enable Metrics/AbcSize
+
+ def schedule_next_job
+ job = Database::BackgroundMigrationJob
+ .for_migration_class('FixMergeRequestDiffCommitUsers')
+ .pending
+ .first
+
+ return unless job
+
+ BackgroundMigrationWorker.perform_in(
+ 2.minutes,
+ 'FixMergeRequestDiffCommitUsers',
+ job.arguments
+ )
+ end
+
+ def find_commit(project, sha)
+ @commits[sha] ||= (project.commit(sha)&.to_hash || {})
+ end
+
+ def find_or_create_user(commit, name_field, email_field)
+ name = commit[name_field]
+ email = commit[email_field]
+
+ return unless name && email
+
+ @users[[name, email]] ||=
+ MergeRequest::DiffCommitUser.find_or_create(name, email).id
+ end
+
+ def matches_row(row)
+ primary_key = Arel::Nodes::Grouping
+ .new([arel_table[:merge_request_diff_id], arel_table[:relative_order]])
+
+ primary_val = Arel::Nodes::Grouping
+ .new([row.merge_request_diff_id, row.relative_order])
+
+ primary_key.eq(primary_val)
+ end
+
+ def arel_table
+ MergeRequestDiffCommit.arel_table
+ end
+ end
+ # rubocop: enable Metrics/ClassLength
+ end
+end
diff --git a/lib/gitlab/background_migration/fix_orphan_promoted_issues.rb b/lib/gitlab/background_migration/fix_orphan_promoted_issues.rb
deleted file mode 100644
index c50bf430d92..00000000000
--- a/lib/gitlab/background_migration/fix_orphan_promoted_issues.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # No OP for CE
- class FixOrphanPromotedIssues
- def perform(note_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::FixOrphanPromotedIssues.prepend_mod_with('Gitlab::BackgroundMigration::FixOrphanPromotedIssues')
diff --git a/lib/gitlab/background_migration/fix_ruby_object_in_audit_events.rb b/lib/gitlab/background_migration/fix_ruby_object_in_audit_events.rb
deleted file mode 100644
index 47a68c61fcc..00000000000
--- a/lib/gitlab/background_migration/fix_ruby_object_in_audit_events.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Remove serialized Ruby object in audit_events
- class FixRubyObjectInAuditEvents
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::FixRubyObjectInAuditEvents.prepend_mod_with('Gitlab::BackgroundMigration::FixRubyObjectInAuditEvents')
diff --git a/lib/gitlab/background_migration/job_coordinator.rb b/lib/gitlab/background_migration/job_coordinator.rb
new file mode 100644
index 00000000000..1c8819eaa62
--- /dev/null
+++ b/lib/gitlab/background_migration/job_coordinator.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Class responsible for executing background migrations based on the given database.
+ #
+ # Chooses the correct worker class when selecting jobs from the queue based on the
+ # convention of how the queues and worker classes are setup for each database.
+ #
+ # Also provides a database connection to the correct tracking database.
+ class JobCoordinator
+ VALID_DATABASES = %i[main].freeze
+ WORKER_CLASS_NAME = 'BackgroundMigrationWorker'
+
+ def self.for_database(database)
+ database = database.to_sym
+
+ unless VALID_DATABASES.include?(database)
+ raise ArgumentError, "database must be one of [#{VALID_DATABASES.join(', ')}], got '#{database}'"
+ end
+
+ namespace = database.to_s.capitalize unless database == :main
+ namespaced_worker_class = [namespace, WORKER_CLASS_NAME].compact.join('::')
+
+ new(database, "::#{namespaced_worker_class}".constantize)
+ end
+
+ attr_reader :database, :worker_class
+
+ def queue
+ @queue ||= worker_class.sidekiq_options['queue']
+ end
+
+ def with_shared_connection(&block)
+ Gitlab::Database::SharedModel.using_connection(connection, &block)
+ end
+
+ def steal(steal_class, retry_dead_jobs: false)
+ with_shared_connection do
+ queues = [
+ Sidekiq::ScheduledSet.new,
+ Sidekiq::Queue.new(self.queue)
+ ]
+
+ if retry_dead_jobs
+ queues << Sidekiq::RetrySet.new
+ queues << Sidekiq::DeadSet.new
+ end
+
+ queues.each do |queue|
+ queue.each do |job|
+ migration_class, migration_args = job.args
+
+ next unless job.klass == worker_class.name
+ next unless migration_class == steal_class
+ next if block_given? && !(yield job)
+
+ begin
+ perform(migration_class, migration_args) if job.delete
+ rescue Exception # rubocop:disable Lint/RescueException
+ worker_class # enqueue this migration again
+ .perform_async(migration_class, migration_args)
+
+ raise
+ end
+ end
+ end
+ end
+ end
+
+ def perform(class_name, arguments)
+ with_shared_connection do
+ migration_class_for(class_name).new.perform(*arguments)
+ end
+ end
+
+ def remaining
+ enqueued = Sidekiq::Queue.new(self.queue)
+ scheduled = Sidekiq::ScheduledSet.new
+
+ [enqueued, scheduled].sum do |set|
+ set.count do |job|
+ job.klass == worker_class.name
+ end
+ end
+ end
+
+ def exists?(migration_class, additional_queues = [])
+ enqueued = Sidekiq::Queue.new(self.queue)
+ scheduled = Sidekiq::ScheduledSet.new
+
+ enqueued_job?([enqueued, scheduled], migration_class)
+ end
+
+ def dead_jobs?(migration_class)
+ dead_set = Sidekiq::DeadSet.new
+
+ enqueued_job?([dead_set], migration_class)
+ end
+
+ def retrying_jobs?(migration_class)
+ retry_set = Sidekiq::RetrySet.new
+
+ enqueued_job?([retry_set], migration_class)
+ end
+
+ def migration_class_for(class_name)
+ Gitlab::BackgroundMigration.const_get(class_name, false)
+ end
+
+ def enqueued_job?(queues, migration_class)
+ queues.any? do |queue|
+ queue.any? do |job|
+ job.klass == worker_class.name && job.args.first == migration_class
+ end
+ end
+ end
+
+ private
+
+ def initialize(database, worker_class)
+ @database = database
+ @worker_class = worker_class
+ end
+
+ def connection
+ @connection ||= Gitlab::Database
+ .database_base_models
+ .fetch(database, Gitlab::Database::PRIMARY_DATABASE_NAME)
+ .connection
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys.rb b/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys.rb
index 1c60473750d..36a339c6b80 100644
--- a/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys.rb
+++ b/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys.rb
@@ -34,7 +34,7 @@ module Gitlab
end
end
- Gitlab::Database.main.bulk_insert(TEMP_TABLE, fingerprints) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(TEMP_TABLE, fingerprints) # rubocop:disable Gitlab/BulkInsert
execute("ANALYZE #{TEMP_TABLE}")
diff --git a/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data.rb b/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data.rb
deleted file mode 100644
index 14c72bb4a72..00000000000
--- a/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data.rb
+++ /dev/null
@@ -1,146 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This migration takes all issue trackers
- # and move data from properties to data field tables (jira_tracker_data and issue_tracker_data)
- class MigrateIssueTrackersSensitiveData
- delegate :select_all, :execute, :quote_string, to: :connection
-
- # we need to define this class and set fields encryption
- class IssueTrackerData < ApplicationRecord
- self.table_name = 'issue_tracker_data'
-
- def self.encryption_options
- {
- key: Settings.attr_encrypted_db_key_base_32,
- encode: true,
- mode: :per_attribute_iv,
- algorithm: 'aes-256-gcm'
- }
- end
-
- attr_encrypted :project_url, encryption_options
- attr_encrypted :issues_url, encryption_options
- attr_encrypted :new_issue_url, encryption_options
- end
-
- # we need to define this class and set fields encryption
- class JiraTrackerData < ApplicationRecord
- self.table_name = 'jira_tracker_data'
-
- def self.encryption_options
- {
- key: Settings.attr_encrypted_db_key_base_32,
- encode: true,
- mode: :per_attribute_iv,
- algorithm: 'aes-256-gcm'
- }
- end
-
- attr_encrypted :url, encryption_options
- attr_encrypted :api_url, encryption_options
- attr_encrypted :username, encryption_options
- attr_encrypted :password, encryption_options
- end
-
- def perform(start_id, stop_id)
- columns = 'id, properties, title, description, type'
- batch_condition = "id >= #{start_id} AND id <= #{stop_id} AND category = 'issue_tracker' \
- AND properties IS NOT NULL AND properties != '{}' AND properties != ''"
-
- data_subselect = "SELECT 1 \
- FROM jira_tracker_data \
- WHERE jira_tracker_data.service_id = services.id \
- UNION SELECT 1 \
- FROM issue_tracker_data \
- WHERE issue_tracker_data.service_id = services.id"
-
- query = "SELECT #{columns} FROM services WHERE #{batch_condition} AND NOT EXISTS (#{data_subselect})"
-
- migrated_ids = []
- data_to_insert(query).each do |table, data|
- service_ids = data.map { |s| s['service_id'] }
-
- next if service_ids.empty?
-
- migrated_ids += service_ids
- Gitlab::Database.main.bulk_insert(table, data) # rubocop:disable Gitlab/BulkInsert
- end
-
- return if migrated_ids.empty?
-
- move_title_description(migrated_ids)
- end
-
- private
-
- def data_to_insert(query)
- data = { 'jira_tracker_data' => [], 'issue_tracker_data' => [] }
- select_all(query).each do |service|
- begin
- properties = Gitlab::Json.parse(service['properties'])
- rescue JSON::ParserError
- logger.warn(
- message: 'Properties data not parsed - invalid json',
- service_id: service['id'],
- properties: service['properties']
- )
- next
- end
-
- if service['type'] == 'JiraService'
- row = data_row(JiraTrackerData, jira_mapping(properties), service)
- key = 'jira_tracker_data'
- else
- row = data_row(IssueTrackerData, issue_tracker_mapping(properties), service)
- key = 'issue_tracker_data'
- end
-
- data[key] << row if row
- end
-
- data
- end
-
- def data_row(klass, mapping, service)
- base_params = { service_id: service['id'], created_at: Time.current, updated_at: Time.current }
- klass.new(mapping).slice(*klass.column_names).compact.merge(base_params)
- end
-
- def move_title_description(service_ids)
- query = "UPDATE services SET \
- title = cast(properties as json)->>'title', \
- description = cast(properties as json)->>'description' \
- WHERE id IN (#{service_ids.join(',')}) AND title IS NULL AND description IS NULL"
-
- execute(query)
- end
-
- def jira_mapping(properties)
- {
- url: properties['url'],
- api_url: properties['api_url'],
- username: properties['username'],
- password: properties['password']
- }
- end
-
- def issue_tracker_mapping(properties)
- {
- project_url: properties['project_url'],
- issues_url: properties['issues_url'],
- new_issue_url: properties['new_issue_url']
- }
- end
-
- def connection
- @connection ||= ActiveRecord::Base.connection
- end
-
- def logger
- @logger ||= Gitlab::BackgroundMigration::Logger.build
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/migrate_requirements_to_work_items.rb b/lib/gitlab/background_migration/migrate_requirements_to_work_items.rb
new file mode 100644
index 00000000000..017791f197c
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_requirements_to_work_items.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # No op on CE
+ class MigrateRequirementsToWorkItems
+ def perform(start_id, end_id)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::MigrateRequirementsToWorkItems.prepend_mod_with('Gitlab::BackgroundMigration::MigrateRequirementsToWorkItems')
diff --git a/lib/gitlab/background_migration/migrate_users_bio_to_user_details.rb b/lib/gitlab/background_migration/migrate_users_bio_to_user_details.rb
deleted file mode 100644
index bbe2164ae4e..00000000000
--- a/lib/gitlab/background_migration/migrate_users_bio_to_user_details.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class MigrateUsersBioToUserDetails
- class User < ActiveRecord::Base
- self.table_name = 'users'
- end
-
- class UserDetails < ActiveRecord::Base
- self.table_name = 'user_details'
- end
-
- def perform(start_id, stop_id)
- relation = User
- .select("id AS user_id", "substring(COALESCE(bio, '') from 1 for 255) AS bio")
- .where("(COALESCE(bio, '') IS DISTINCT FROM '')")
- .where(id: (start_id..stop_id))
-
- ActiveRecord::Base.connection.execute <<-EOF.strip_heredoc
- INSERT INTO user_details
- (user_id, bio)
- #{relation.to_sql}
- ON CONFLICT (user_id)
- DO UPDATE SET
- "bio" = EXCLUDED."bio";
- EOF
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_issue_email_participants.rb b/lib/gitlab/background_migration/populate_issue_email_participants.rb
index 0a56ac1dae8..2b959b81f45 100644
--- a/lib/gitlab/background_migration/populate_issue_email_participants.rb
+++ b/lib/gitlab/background_migration/populate_issue_email_participants.rb
@@ -21,7 +21,7 @@ module Gitlab
}
end
- Gitlab::Database.main.bulk_insert(:issue_email_participants, rows, on_conflict: :do_nothing) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(:issue_email_participants, rows, on_conflict: :do_nothing) # rubocop:disable Gitlab/BulkInsert
end
end
end
diff --git a/lib/gitlab/background_migration/populate_user_highest_roles_table.rb b/lib/gitlab/background_migration/populate_user_highest_roles_table.rb
deleted file mode 100644
index 16386ebf9c3..00000000000
--- a/lib/gitlab/background_migration/populate_user_highest_roles_table.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This background migration creates records on user_highest_roles according to
- # the given user IDs range. IDs will load users with a left outer joins to
- # have a record for users without a Group or Project. One INSERT per ID is
- # issued.
- class PopulateUserHighestRolesTable
- BATCH_SIZE = 100
-
- # rubocop:disable Style/Documentation
- class User < ActiveRecord::Base
- self.table_name = 'users'
-
- scope :active, -> {
- where(state: 'active', user_type: nil, bot_type: nil)
- .where('ghost IS NOT TRUE')
- }
- end
-
- def perform(from_id, to_id)
- return unless User.column_names.include?('bot_type')
-
- (from_id..to_id).each_slice(BATCH_SIZE) do |ids|
- execute(
- <<-EOF
- INSERT INTO user_highest_roles (updated_at, user_id, highest_access_level)
- #{select_sql(from_id, to_id)}
- ON CONFLICT (user_id) DO
- UPDATE SET highest_access_level = EXCLUDED.highest_access_level
- EOF
- )
- end
- end
-
- private
-
- def select_sql(from_id, to_id)
- User
- .select('NOW() as updated_at, users.id, MAX(access_level) AS highest_access_level')
- .joins('LEFT OUTER JOIN members ON members.user_id = users.id AND members.requested_at IS NULL')
- .where(users: { id: active_user_ids(from_id, to_id) })
- .group('users.id')
- .to_sql
- end
-
- def active_user_ids(from_id, to_id)
- User.active.where(users: { id: from_id..to_id }).pluck(:id)
- end
-
- def execute(sql)
- @connection ||= ActiveRecord::Base.connection
- @connection.execute(sql)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb b/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb
new file mode 100644
index 00000000000..8e94c16369e
--- /dev/null
+++ b/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb
@@ -0,0 +1,151 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module ProjectNamespaces
+ # Back-fill project namespaces for projects that do not yet have a namespace.
+ #
+ # TODO: remove this comment when an actuall backfill migration is added.
+ #
+ # This is first being added without an actual migration as we need to initially test
+ # if backfilling project namespaces affects performance in any significant way.
+ # rubocop: disable Metrics/ClassLength
+ class BackfillProjectNamespaces
+ BATCH_SIZE = 100
+ DELETE_BATCH_SIZE = 10
+ PROJECT_NAMESPACE_STI_NAME = 'Project'
+
+ IsolatedModels = ::Gitlab::BackgroundMigration::ProjectNamespaces::Models
+
+ def perform(start_id, end_id, namespace_id, migration_type = 'up')
+ load_project_ids(start_id, end_id, namespace_id)
+
+ case migration_type
+ when 'up'
+ backfill_project_namespaces(namespace_id)
+ mark_job_as_succeeded(start_id, end_id, namespace_id, 'up')
+ when 'down'
+ cleanup_backfilled_project_namespaces(namespace_id)
+ mark_job_as_succeeded(start_id, end_id, namespace_id, 'down')
+ else
+ raise "Unknown migration type"
+ end
+ end
+
+ private
+
+ attr_accessor :project_ids
+
+ def backfill_project_namespaces(namespace_id)
+ project_ids.each_slice(BATCH_SIZE) do |project_ids|
+ # We need to lock these project records for the period when we create project namespaces
+ # and link them to projects so that if a project is modified in the time between creating
+ # project namespaces `batch_insert_namespaces` and linking them to projects `batch_update_projects`
+ # we do not get them out of sync.
+ #
+ # see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72527#note_730679469
+ Project.transaction do
+ Project.where(id: project_ids).select(:id).lock!('FOR UPDATE')
+
+ batch_insert_namespaces(project_ids)
+ batch_update_projects(project_ids)
+ end
+
+ batch_update_project_namespaces_traversal_ids(project_ids)
+ end
+ end
+
+ def cleanup_backfilled_project_namespaces(namespace_id)
+ project_ids.each_slice(BATCH_SIZE) do |project_ids|
+ # IMPORTANT: first nullify project_namespace_id in projects table to avoid removing projects when records
+ # from namespaces are deleted due to FK/triggers
+ nullify_project_namespaces_in_projects(project_ids)
+ delete_project_namespace_records(project_ids)
+ end
+ end
+
+ def batch_insert_namespaces(project_ids)
+ projects = IsolatedModels::Project.where(id: project_ids)
+ .select("projects.id, projects.name, projects.path, projects.namespace_id, projects.visibility_level, shared_runners_enabled, '#{PROJECT_NAMESPACE_STI_NAME}', now(), now()")
+
+ ActiveRecord::Base.connection.execute <<~SQL
+ INSERT INTO namespaces (tmp_project_id, name, path, parent_id, visibility_level, shared_runners_enabled, type, created_at, updated_at)
+ #{projects.to_sql}
+ ON CONFLICT DO NOTHING;
+ SQL
+ end
+
+ def batch_update_projects(project_ids)
+ projects = IsolatedModels::Project.where(id: project_ids)
+ .joins("INNER JOIN namespaces ON projects.id = namespaces.tmp_project_id")
+ .select("namespaces.id, namespaces.tmp_project_id")
+
+ ActiveRecord::Base.connection.execute <<~SQL
+ WITH cte(project_namespace_id, project_id) AS #{::Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
+ #{projects.to_sql}
+ )
+ UPDATE projects
+ SET project_namespace_id = cte.project_namespace_id
+ FROM cte
+ WHERE id = cte.project_id AND projects.project_namespace_id IS DISTINCT FROM cte.project_namespace_id
+ SQL
+ end
+
+ def batch_update_project_namespaces_traversal_ids(project_ids)
+ namespaces = Namespace.where(tmp_project_id: project_ids)
+ .joins("INNER JOIN namespaces n2 ON namespaces.parent_id = n2.id")
+ .select("namespaces.id as project_namespace_id, n2.traversal_ids")
+
+ ActiveRecord::Base.connection.execute <<~SQL
+ UPDATE namespaces
+ SET traversal_ids = array_append(project_namespaces.traversal_ids, project_namespaces.project_namespace_id)
+ FROM (#{namespaces.to_sql}) as project_namespaces(project_namespace_id, traversal_ids)
+ WHERE id = project_namespaces.project_namespace_id
+ SQL
+ end
+
+ def nullify_project_namespaces_in_projects(project_ids)
+ IsolatedModels::Project.where(id: project_ids).update_all(project_namespace_id: nil)
+ end
+
+ def delete_project_namespace_records(project_ids)
+ project_ids.each_slice(DELETE_BATCH_SIZE) do |p_ids|
+ IsolatedModels::Namespace.where(type: PROJECT_NAMESPACE_STI_NAME).where(tmp_project_id: p_ids).delete_all
+ end
+ end
+
+ def load_project_ids(start_id, end_id, namespace_id)
+ projects = IsolatedModels::Project.arel_table
+ relation = IsolatedModels::Project.where(projects[:id].between(start_id..end_id))
+ relation = relation.where(projects[:namespace_id].in(Arel::Nodes::SqlLiteral.new(hierarchy_cte(namespace_id)))) if namespace_id
+
+ @project_ids = relation.pluck(:id)
+ end
+
+ def mark_job_as_succeeded(*arguments)
+ ::Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded('BackfillProjectNamespaces', arguments)
+ end
+
+ def hierarchy_cte(root_namespace_id)
+ <<-SQL
+ WITH RECURSIVE "base_and_descendants" AS (
+ (
+ SELECT "namespaces"."id"
+ FROM "namespaces"
+ WHERE "namespaces"."type" = 'Group' AND "namespaces"."id" = #{root_namespace_id.to_i}
+ )
+ UNION
+ (
+ SELECT "namespaces"."id"
+ FROM "namespaces", "base_and_descendants"
+ WHERE "namespaces"."type" = 'Group' AND "namespaces"."parent_id" = "base_and_descendants"."id"
+ )
+ )
+ SELECT "id" FROM "base_and_descendants" AS "namespaces"
+ SQL
+ end
+ end
+ # rubocop: enable Metrics/ClassLength
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/project_namespaces/models/namespace.rb b/lib/gitlab/background_migration/project_namespaces/models/namespace.rb
new file mode 100644
index 00000000000..5576c34cf65
--- /dev/null
+++ b/lib/gitlab/background_migration/project_namespaces/models/namespace.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module ProjectNamespaces
+ module Models
+ # isolated Namespace model
+ class Namespace < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'namespaces'
+ self.inheritance_column = :_type_disabled
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/project_namespaces/models/project.rb b/lib/gitlab/background_migration/project_namespaces/models/project.rb
new file mode 100644
index 00000000000..4a6a309e289
--- /dev/null
+++ b/lib/gitlab/background_migration/project_namespaces/models/project.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module ProjectNamespaces
+ module Models
+ # isolated Project model
+ class Project < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'projects'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb b/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb
index ca61118a06c..15799659b55 100644
--- a/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb
+++ b/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb
@@ -2,7 +2,7 @@
# rubocop: disable Style/Documentation
class Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindings
- DELETE_BATCH_SIZE = 100
+ DELETE_BATCH_SIZE = 50
# rubocop:disable Gitlab/NamespacedClass
class VulnerabilitiesFinding < ActiveRecord::Base
@@ -10,6 +10,12 @@ class Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindings
end
# rubocop:enable Gitlab/NamespacedClass
+ # rubocop:disable Gitlab/NamespacedClass
+ class Vulnerability < ActiveRecord::Base
+ self.table_name = "vulnerabilities"
+ end
+ # rubocop:enable Gitlab/NamespacedClass
+
def perform(start_id, end_id)
batch = VulnerabilitiesFinding.where(id: start_id..end_id)
@@ -40,11 +46,19 @@ class Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindings
ids_to_delete.concat(duplicate_ids)
if ids_to_delete.size == DELETE_BATCH_SIZE
- VulnerabilitiesFinding.where(id: ids_to_delete).delete_all
+ delete_findings_and_vulnerabilities(ids_to_delete)
ids_to_delete.clear
end
end
- VulnerabilitiesFinding.where(id: ids_to_delete).delete_all if ids_to_delete.any?
+ delete_findings_and_vulnerabilities(ids_to_delete) if ids_to_delete.any?
+ end
+
+ private
+
+ def delete_findings_and_vulnerabilities(ids)
+ vulnerability_ids = VulnerabilitiesFinding.where(id: ids).pluck(:vulnerability_id).compact
+ VulnerabilitiesFinding.where(id: ids).delete_all
+ Vulnerability.where(id: vulnerability_ids).delete_all
end
end
diff --git a/lib/gitlab/background_migration/remove_undefined_occurrence_confidence_level.rb b/lib/gitlab/background_migration/remove_undefined_occurrence_confidence_level.rb
deleted file mode 100644
index 540ffc6f548..00000000000
--- a/lib/gitlab/background_migration/remove_undefined_occurrence_confidence_level.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class RemoveUndefinedOccurrenceConfidenceLevel
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::RemoveUndefinedOccurrenceConfidenceLevel.prepend_mod_with('Gitlab::BackgroundMigration::RemoveUndefinedOccurrenceConfidenceLevel')
diff --git a/lib/gitlab/background_migration/remove_undefined_occurrence_severity_level.rb b/lib/gitlab/background_migration/remove_undefined_occurrence_severity_level.rb
deleted file mode 100644
index cecb385afa0..00000000000
--- a/lib/gitlab/background_migration/remove_undefined_occurrence_severity_level.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class RemoveUndefinedOccurrenceSeverityLevel
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::RemoveUndefinedOccurrenceSeverityLevel.prepend_mod_with('Gitlab::BackgroundMigration::RemoveUndefinedOccurrenceSeverityLevel')
diff --git a/lib/gitlab/background_migration/remove_undefined_vulnerability_severity_level.rb b/lib/gitlab/background_migration/remove_undefined_vulnerability_severity_level.rb
deleted file mode 100644
index 1ea483f929f..00000000000
--- a/lib/gitlab/background_migration/remove_undefined_vulnerability_severity_level.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class RemoveUndefinedVulnerabilitySeverityLevel
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::RemoveUndefinedVulnerabilitySeverityLevel.prepend_mod_with('Gitlab::BackgroundMigration::RemoveUndefinedVulnerabilitySeverityLevel')
diff --git a/lib/gitlab/background_migration/set_default_iteration_cadences.rb b/lib/gitlab/background_migration/set_default_iteration_cadences.rb
deleted file mode 100644
index 42f9d33ab71..00000000000
--- a/lib/gitlab/background_migration/set_default_iteration_cadences.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop:disable Style/Documentation
- class SetDefaultIterationCadences
- class Iteration < ApplicationRecord
- self.table_name = 'sprints'
- end
-
- class IterationCadence < ApplicationRecord
- self.table_name = 'iterations_cadences'
-
- include BulkInsertSafe
- end
-
- class Group < ApplicationRecord
- self.table_name = 'namespaces'
-
- self.inheritance_column = :_type_disabled
- end
-
- def perform(*group_ids)
- create_iterations_cadences(group_ids)
- assign_iterations_cadences(group_ids)
- end
-
- private
-
- def create_iterations_cadences(group_ids)
- groups_with_cadence = IterationCadence.select(:group_id)
-
- new_cadences = Group.where(id: group_ids).where.not(id: groups_with_cadence).map do |group|
- last_iteration = Iteration.where(group_id: group.id).order(:start_date)&.last
-
- next unless last_iteration
-
- time = Time.now
- IterationCadence.new(
- group_id: group.id,
- title: "#{group.name} Iterations",
- start_date: last_iteration.start_date,
- last_run_date: last_iteration.start_date,
- automatic: false,
- created_at: time,
- updated_at: time
- )
- end
-
- IterationCadence.bulk_insert!(new_cadences.compact, skip_duplicates: true)
- end
-
- def assign_iterations_cadences(group_ids)
- IterationCadence.where(group_id: group_ids).each do |cadence|
- Iteration.where(iterations_cadence_id: nil).where(group_id: cadence.group_id).update_all(iterations_cadence_id: cadence.id)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/set_null_external_diff_store_to_local_value.rb b/lib/gitlab/background_migration/set_null_external_diff_store_to_local_value.rb
deleted file mode 100644
index 71f3483987e..00000000000
--- a/lib/gitlab/background_migration/set_null_external_diff_store_to_local_value.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class is responsible for migrating a range of merge request diffs
- # with external_diff_store == NULL to 1.
- #
- # The index `index_merge_request_diffs_external_diff_store_is_null` is
- # expected to be used to find the rows here and in the migration scheduling
- # the jobs that run this class.
- class SetNullExternalDiffStoreToLocalValue
- LOCAL_STORE = 1 # equal to ObjectStorage::Store::LOCAL
-
- # Temporary AR class for merge request diffs
- class MergeRequestDiff < ActiveRecord::Base
- self.table_name = 'merge_request_diffs'
- end
-
- def perform(start_id, stop_id)
- MergeRequestDiff.where(external_diff_store: nil, id: start_id..stop_id).update_all(external_diff_store: LOCAL_STORE)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb b/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb
deleted file mode 100644
index c485c23f3be..00000000000
--- a/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class is responsible for migrating a range of package files
- # with file_store == NULL to 1.
- #
- # The index `index_packages_package_files_file_store_is_null` is
- # expected to be used to find the rows here and in the migration scheduling
- # the jobs that run this class.
- class SetNullPackageFilesFileStoreToLocalValue
- LOCAL_STORE = 1 # equal to ObjectStorage::Store::LOCAL
-
- module Packages
- # Temporary AR class for package files
- class PackageFile < ActiveRecord::Base
- self.table_name = 'packages_package_files'
- end
- end
-
- def perform(start_id, stop_id)
- Packages::PackageFile.where(file_store: nil, id: start_id..stop_id).update_all(file_store: LOCAL_STORE)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/update_vulnerabilities_to_dismissed.rb b/lib/gitlab/background_migration/update_vulnerabilities_to_dismissed.rb
deleted file mode 100644
index 60adb6b7e3e..00000000000
--- a/lib/gitlab/background_migration/update_vulnerabilities_to_dismissed.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop: disable Style/Documentation
- class UpdateVulnerabilitiesToDismissed
- def perform(project_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::UpdateVulnerabilitiesToDismissed.prepend_mod_with('Gitlab::BackgroundMigration::UpdateVulnerabilitiesToDismissed')
diff --git a/lib/gitlab/background_migration/update_vulnerability_confidence.rb b/lib/gitlab/background_migration/update_vulnerability_confidence.rb
deleted file mode 100644
index 40d29978dd4..00000000000
--- a/lib/gitlab/background_migration/update_vulnerability_confidence.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop: disable Style/Documentation
- class UpdateVulnerabilityConfidence
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::UpdateVulnerabilityConfidence.prepend_mod_with('Gitlab::BackgroundMigration::UpdateVulnerabilityConfidence')
diff --git a/lib/gitlab/background_migration/update_vulnerability_occurrences_location.rb b/lib/gitlab/background_migration/update_vulnerability_occurrences_location.rb
new file mode 100644
index 00000000000..458e0537f1c
--- /dev/null
+++ b/lib/gitlab/background_migration/update_vulnerability_occurrences_location.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class UpdateVulnerabilityOccurrencesLocation
+ def perform(start_id, stop_id)
+ end
+ end
+ # rubocop: enable Style/Documentation
+ end
+end
+
+Gitlab::BackgroundMigration::UpdateVulnerabilityOccurrencesLocation.prepend_mod_with('Gitlab::BackgroundMigration::UpdateVulnerabilityOccurrencesLocation')
diff --git a/lib/gitlab/bitbucket_server_import/importer.rb b/lib/gitlab/bitbucket_server_import/importer.rb
index e0eee64dc58..899e2e6c1c5 100644
--- a/lib/gitlab/bitbucket_server_import/importer.rb
+++ b/lib/gitlab/bitbucket_server_import/importer.rb
@@ -461,10 +461,14 @@ module Gitlab
end
def uid(rep_object)
- find_user_id(by: :email, value: rep_object.author_email) unless Feature.enabled?(:bitbucket_server_user_mapping_by_username)
-
- find_user_id(by: :username, value: rep_object.author_username) ||
+ # We want this explicit to only be username on the FF
+ # Otherwise, match email.
+ # There should be no default fall-through on username. Fall-through to import user
+ if Feature.enabled?(:bitbucket_server_user_mapping_by_username)
+ find_user_id(by: :username, value: rep_object.author_username)
+ else
find_user_id(by: :email, value: rep_object.author_email)
+ end
end
end
end
diff --git a/lib/gitlab/blob_helper.rb b/lib/gitlab/blob_helper.rb
index c5b183d113d..9e4ea934edb 100644
--- a/lib/gitlab/blob_helper.rb
+++ b/lib/gitlab/blob_helper.rb
@@ -47,7 +47,7 @@ module Gitlab
end
def image?
- ['.png', '.jpg', '.jpeg', '.gif', '.svg'].include?(extname.downcase)
+ ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp'].include?(extname.downcase)
end
# Internal: Lookup mime type for extension.
diff --git a/lib/gitlab/ci/artifact_file_reader.rb b/lib/gitlab/ci/artifact_file_reader.rb
index 3cfed8e5e2c..b0fad026ec5 100644
--- a/lib/gitlab/ci/artifact_file_reader.rb
+++ b/lib/gitlab/ci/artifact_file_reader.rb
@@ -45,14 +45,6 @@ module Gitlab
end
def read_zip_file!(file_path)
- if ::Feature.enabled?(:ci_new_artifact_file_reader, job.project, default_enabled: :yaml)
- read_with_new_artifact_file_reader(file_path)
- else
- read_with_legacy_artifact_file_reader(file_path)
- end
- end
-
- def read_with_new_artifact_file_reader(file_path)
job.artifacts_file.use_open_file do |file|
zip_file = Zip::File.new(file, false, true)
entry = zip_file.find_entry(file_path)
@@ -69,25 +61,6 @@ module Gitlab
end
end
- def read_with_legacy_artifact_file_reader(file_path)
- job.artifacts_file.use_file do |archive_path|
- Zip::File.open(archive_path) do |zip_file|
- entry = zip_file.find_entry(file_path)
- unless entry
- raise Error, "Path `#{file_path}` does not exist inside the `#{job.name}` artifacts archive!"
- end
-
- if entry.name_is_directory?
- raise Error, "Path `#{file_path}` was expected to be a file but it was a directory!"
- end
-
- zip_file.get_input_stream(entry) do |is|
- is.read
- end
- end
- end
- end
-
def max_archive_size_in_mb
ActiveSupport::NumberHelper.number_to_human_size(MAX_ARCHIVE_SIZE)
end
diff --git a/lib/gitlab/ci/artifacts/metrics.rb b/lib/gitlab/ci/artifacts/metrics.rb
index 656f4d2cc13..03459c4bf36 100644
--- a/lib/gitlab/ci/artifacts/metrics.rb
+++ b/lib/gitlab/ci/artifacts/metrics.rb
@@ -6,10 +6,14 @@ module Gitlab
class Metrics
include Gitlab::Utils::StrongMemoize
- def increment_destroyed_artifacts(size)
+ def increment_destroyed_artifacts_count(size)
destroyed_artifacts_counter.increment({}, size.to_i)
end
+ def increment_destroyed_artifacts_bytes(bytes)
+ destroyed_artifacts_bytes_counter.increment({}, bytes)
+ end
+
private
def destroyed_artifacts_counter
@@ -20,6 +24,15 @@ module Gitlab
::Gitlab::Metrics.counter(name, comment)
end
end
+
+ def destroyed_artifacts_bytes_counter
+ strong_memoize(:destroyed_artifacts_bytes_counter) do
+ name = :destroyed_job_artifacts_bytes_total
+ comment = 'Counter of bytes of destroyed expired job artifacts'
+
+ ::Gitlab::Metrics.counter(name, comment)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/ci/build/auto_retry.rb b/lib/gitlab/ci/build/auto_retry.rb
index 6ab567dff7c..4950a7616c8 100644
--- a/lib/gitlab/ci/build/auto_retry.rb
+++ b/lib/gitlab/ci/build/auto_retry.rb
@@ -10,7 +10,9 @@ class Gitlab::Ci::Build::AutoRetry
RETRY_OVERRIDES = {
ci_quota_exceeded: 0,
no_matching_runner: 0,
- missing_dependency_failure: 0
+ missing_dependency_failure: 0,
+ forward_deployment_failure: 0,
+ environment_creation_failure: 0
}.freeze
def initialize(build)
diff --git a/lib/gitlab/ci/build/context/base.rb b/lib/gitlab/ci/build/context/base.rb
index 02b97ea76e9..c7ea7c78e2f 100644
--- a/lib/gitlab/ci/build/context/base.rb
+++ b/lib/gitlab/ci/build/context/base.rb
@@ -5,6 +5,8 @@ module Gitlab
module Build
module Context
class Base
+ include Gitlab::Utils::StrongMemoize
+
attr_reader :pipeline
def initialize(pipeline)
@@ -15,6 +17,26 @@ module Gitlab
raise NotImplementedError
end
+ def project
+ pipeline.project
+ end
+
+ def sha
+ pipeline.sha
+ end
+
+ def top_level_worktree_paths
+ strong_memoize(:top_level_worktree_paths) do
+ project.repository.tree(sha).blobs.map(&:path)
+ end
+ end
+
+ def all_worktree_paths
+ strong_memoize(:all_worktree_paths) do
+ project.repository.ls_files(sha)
+ end
+ end
+
protected
def pipeline_attributes
diff --git a/lib/gitlab/ci/build/image.rb b/lib/gitlab/ci/build/image.rb
index 1d7bfba75cd..8ddcf1d523e 100644
--- a/lib/gitlab/ci/build/image.rb
+++ b/lib/gitlab/ci/build/image.rb
@@ -4,7 +4,7 @@ module Gitlab
module Ci
module Build
class Image
- attr_reader :alias, :command, :entrypoint, :name, :ports
+ attr_reader :alias, :command, :entrypoint, :name, :ports, :variables
class << self
def from_image(job)
@@ -33,6 +33,7 @@ module Gitlab
@entrypoint = image[:entrypoint]
@name = image[:name]
@ports = build_ports(image).select(&:valid?)
+ @variables = build_variables(image)
end
end
@@ -45,6 +46,12 @@ module Gitlab
def build_ports(image)
image[:ports].to_a.map { |port| ::Gitlab::Ci::Build::Port.new(port) }
end
+
+ def build_variables(image)
+ image[:variables].to_a.map do |key, value|
+ { key: key, value: value.to_s }
+ end
+ end
end
end
end
diff --git a/lib/gitlab/ci/build/rules/rule/clause/exists.rb b/lib/gitlab/ci/build/rules/rule/clause/exists.rb
index 85e77438f51..e2b54797dc8 100644
--- a/lib/gitlab/ci/build/rules/rule/clause/exists.rb
+++ b/lib/gitlab/ci/build/rules/rule/clause/exists.rb
@@ -15,19 +15,21 @@ module Gitlab
@exact_globs, @pattern_globs = globs.partition(&method(:exact_glob?))
end
- def satisfied_by?(pipeline, context)
- paths = worktree_paths(pipeline)
+ def satisfied_by?(_pipeline, context)
+ paths = worktree_paths(context)
exact_matches?(paths) || pattern_matches?(paths)
end
private
- def worktree_paths(pipeline)
+ def worktree_paths(context)
+ return unless context.project
+
if @top_level_only
- pipeline.top_level_worktree_paths
+ context.top_level_worktree_paths
else
- pipeline.all_worktree_paths
+ context.all_worktree_paths
end
end
diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb
index aceaf012f7e..6f149385969 100644
--- a/lib/gitlab/ci/config.rb
+++ b/lib/gitlab/ci/config.rb
@@ -19,11 +19,12 @@ module Gitlab
attr_reader :root, :context, :source_ref_path, :source
- def initialize(config, project: nil, sha: nil, user: nil, parent_pipeline: nil, source_ref_path: nil, source: nil)
- @context = build_context(project: project, sha: sha, user: user, parent_pipeline: parent_pipeline, ref: source_ref_path)
+ def initialize(config, project: nil, pipeline: nil, sha: nil, user: nil, parent_pipeline: nil, source: nil)
+ @source_ref_path = pipeline&.source_ref_path
+
+ @context = build_context(project: project, pipeline: pipeline, sha: sha, user: user, parent_pipeline: parent_pipeline)
@context.set_deadline(TIMEOUT_SECONDS)
- @source_ref_path = source_ref_path
@source = source
@config = expand_config(config)
@@ -108,16 +109,16 @@ module Gitlab
end
end
- def build_context(project:, sha:, user:, parent_pipeline:, ref:)
+ def build_context(project:, pipeline:, sha:, user:, parent_pipeline:)
Config::External::Context.new(
project: project,
sha: sha || find_sha(project),
user: user,
parent_pipeline: parent_pipeline,
- variables: build_variables(project: project, ref: ref))
+ variables: build_variables(project: project, pipeline: pipeline))
end
- def build_variables(project:, ref:)
+ def build_variables(project:, pipeline:)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
break variables unless project
@@ -126,18 +127,12 @@ module Gitlab
#
# See more detail in the docs: https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
variables.concat(project.predefined_variables)
- variables.concat(pipeline_predefined_variables(ref: ref))
- variables.concat(project.ci_instance_variables_for(ref: ref))
- variables.concat(project.group.ci_variables_for(ref, project)) if project.group
- variables.concat(project.ci_variables_for(ref: ref))
- end
- end
-
- # https://gitlab.com/gitlab-org/gitlab/-/issues/337633 aims to add all predefined variables
- # to this list, but only CI_COMMIT_REF_NAME is available right now to support compliance pipelines.
- def pipeline_predefined_variables(ref:)
- Gitlab::Ci::Variables::Collection.new.tap do |v|
- v.append(key: 'CI_COMMIT_REF_NAME', value: ref)
+ variables.concat(pipeline.predefined_variables) if pipeline
+ variables.concat(project.ci_instance_variables_for(ref: source_ref_path))
+ variables.concat(project.group.ci_variables_for(source_ref_path, project)) if project.group
+ variables.concat(project.ci_variables_for(ref: source_ref_path))
+ variables.concat(pipeline.variables) if pipeline
+ variables.concat(pipeline.pipeline_schedule.job_variables) if pipeline&.pipeline_schedule
end
end
diff --git a/lib/gitlab/ci/config/entry/include/rules/rule.rb b/lib/gitlab/ci/config/entry/include/rules/rule.rb
index d3d0f098814..fa99a7204d6 100644
--- a/lib/gitlab/ci/config/entry/include/rules/rule.rb
+++ b/lib/gitlab/ci/config/entry/include/rules/rule.rb
@@ -9,9 +9,9 @@ module Gitlab
include ::Gitlab::Config::Entry::Validatable
include ::Gitlab::Config::Entry::Attributable
- ALLOWED_KEYS = %i[if].freeze
+ ALLOWED_KEYS = %i[if exists].freeze
- attributes :if
+ attributes :if, :exists
validations do
validates :config, presence: true
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index f867189d521..75bbe2ccb1b 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -14,10 +14,10 @@ module Gitlab
ALLOWED_KEYS = %i[tags script type image services start_in artifacts
cache dependencies before_script after_script
environment coverage retry parallel interruptible timeout
- release dast_configuration secrets].freeze
+ release].freeze
validations do
- validates :config, allowed_keys: ALLOWED_KEYS + PROCESSABLE_ALLOWED_KEYS
+ validates :config, allowed_keys: Gitlab::Ci::Config::Entry::Job.allowed_keys + PROCESSABLE_ALLOWED_KEYS
validates :script, presence: true
with_options allow_nil: true do
@@ -178,6 +178,10 @@ module Gitlab
allow_failure_defined? ? static_allow_failure : manual_action?
end
+ def self.allowed_keys
+ ALLOWED_KEYS
+ end
+
private
def allow_failure_criteria
diff --git a/lib/gitlab/ci/config/entry/processable.rb b/lib/gitlab/ci/config/entry/processable.rb
index 2549c35ebd6..520b1ce6119 100644
--- a/lib/gitlab/ci/config/entry/processable.rb
+++ b/lib/gitlab/ci/config/entry/processable.rb
@@ -23,6 +23,7 @@ module Gitlab
validates :config, presence: true
validates :name, presence: true
validates :name, type: Symbol
+ validates :name, length: { maximum: 255 }, if: -> { ::Feature.enabled?(:ci_validate_job_length, default_enabled: :yaml) }
validates :config, disallowed_keys: {
in: %i[only except when start_in],
diff --git a/lib/gitlab/ci/config/entry/service.rb b/lib/gitlab/ci/config/entry/service.rb
index 247bf930d3b..f27dca4986e 100644
--- a/lib/gitlab/ci/config/entry/service.rb
+++ b/lib/gitlab/ci/config/entry/service.rb
@@ -15,7 +15,7 @@ module Gitlab
include ::Gitlab::Config::Entry::Attributable
include ::Gitlab::Config::Entry::Configurable
- ALLOWED_KEYS = %i[name entrypoint command alias ports].freeze
+ ALLOWED_KEYS = %i[name entrypoint command alias ports variables].freeze
validations do
validates :config, hash_or_string: true
@@ -32,6 +32,10 @@ module Gitlab
entry :ports, Entry::Ports,
description: 'Ports used to expose the service'
+ entry :variables, ::Gitlab::Ci::Config::Entry::Variables,
+ description: 'Environment variables available for this service.',
+ inherit: false
+
attributes :ports
def alias
diff --git a/lib/gitlab/ci/config/external/context.rb b/lib/gitlab/ci/config/external/context.rb
index e0adb1b19c2..51624dc30ea 100644
--- a/lib/gitlab/ci/config/external/context.rb
+++ b/lib/gitlab/ci/config/external/context.rb
@@ -5,6 +5,8 @@ module Gitlab
class Config
module External
class Context
+ include Gitlab::Utils::StrongMemoize
+
TimeoutError = Class.new(StandardError)
attr_reader :project, :sha, :user, :parent_pipeline, :variables
@@ -22,6 +24,18 @@ module Gitlab
yield self if block_given?
end
+ def top_level_worktree_paths
+ strong_memoize(:top_level_worktree_paths) do
+ project.repository.tree(sha).blobs.map(&:path)
+ end
+ end
+
+ def all_worktree_paths
+ strong_memoize(:all_worktree_paths) do
+ project.repository.ls_files(sha)
+ end
+ end
+
def mutate(attrs = {})
self.class.new(**attrs) do |ctx|
ctx.expandset = expandset
diff --git a/lib/gitlab/ci/parsers/security/common.rb b/lib/gitlab/ci/parsers/security/common.rb
index 1cf4f252ab9..0c969daf7fd 100644
--- a/lib/gitlab/ci/parsers/security/common.rb
+++ b/lib/gitlab/ci/parsers/security/common.rb
@@ -33,8 +33,7 @@ module Gitlab
report_data
rescue JSON::ParserError
raise SecurityReportParserError, 'JSON parsing failed'
- rescue StandardError => e
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
+ rescue StandardError
raise SecurityReportParserError, "#{report.type} security report parsing failed"
end
@@ -115,7 +114,7 @@ module Gitlab
flags: flags,
links: links,
remediations: remediations,
- raw_metadata: data.to_json,
+ original_data: data,
metadata_version: report_version,
details: data['details'] || {},
signatures: signatures,
diff --git a/lib/gitlab/ci/parsers/security/validators/schema_validator.rb b/lib/gitlab/ci/parsers/security/validators/schema_validator.rb
index 143b930c669..73cfa02ce4b 100644
--- a/lib/gitlab/ci/parsers/security/validators/schema_validator.rb
+++ b/lib/gitlab/ci/parsers/security/validators/schema_validator.rb
@@ -34,7 +34,7 @@ module Gitlab
end
def file_name
- "#{report_type}.json"
+ "#{report_type.to_s.dasherize}-report-format.json"
end
end
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/sast.json b/lib/gitlab/ci/parsers/security/validators/schemas/sast-report-format.json
index a7159be0190..a7159be0190 100644
--- a/lib/gitlab/ci/parsers/security/validators/schemas/sast.json
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/sast-report-format.json
diff --git a/lib/gitlab/ci/parsers/security/validators/schemas/secret_detection.json b/lib/gitlab/ci/parsers/security/validators/schemas/secret-detection-report-format.json
index 462e23a151c..462e23a151c 100644
--- a/lib/gitlab/ci/parsers/security/validators/schemas/secret_detection.json
+++ b/lib/gitlab/ci/parsers/security/validators/schemas/secret-detection-report-format.json
diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb
index c9bc4ec411d..beb8801096b 100644
--- a/lib/gitlab/ci/pipeline/chain/command.rb
+++ b/lib/gitlab/ci/pipeline/chain/command.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
@@ -144,3 +145,5 @@ module Gitlab
end
end
end
+
+# rubocop:enable Naming/FileName
diff --git a/lib/gitlab/ci/pipeline/chain/config/process.rb b/lib/gitlab/ci/pipeline/chain/config/process.rb
index 5251dd3d40a..f3c937ddd28 100644
--- a/lib/gitlab/ci/pipeline/chain/config/process.rb
+++ b/lib/gitlab/ci/pipeline/chain/config/process.rb
@@ -14,7 +14,7 @@ module Gitlab
result = ::Gitlab::Ci::YamlProcessor.new(
@command.config_content, {
project: project,
- source_ref_path: @pipeline.source_ref_path,
+ pipeline: @pipeline,
sha: @pipeline.sha,
source: @pipeline.source,
user: current_user,
diff --git a/lib/gitlab/ci/pipeline/chain/create_cross_database_associations.rb b/lib/gitlab/ci/pipeline/chain/create_cross_database_associations.rb
new file mode 100644
index 00000000000..bb5b4e722b7
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/create_cross_database_associations.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ class CreateCrossDatabaseAssociations < Chain::Base
+ def perform!
+ # to be overridden in EE
+ end
+
+ def break?
+ false # to be overridden in EE
+ end
+ end
+ end
+ end
+ end
+end
+
+Gitlab::Ci::Pipeline::Chain::CreateCrossDatabaseAssociations.prepend_mod_with('Gitlab::Ci::Pipeline::Chain::CreateCrossDatabaseAssociations')
diff --git a/lib/gitlab/ci/pipeline/metrics.rb b/lib/gitlab/ci/pipeline/metrics.rb
index 321efa7854f..b5e48f210ad 100644
--- a/lib/gitlab/ci/pipeline/metrics.rb
+++ b/lib/gitlab/ci/pipeline/metrics.rb
@@ -51,6 +51,15 @@ module Gitlab
::Gitlab::Metrics.histogram(name, comment, labels, buckets)
end
+ def self.pipeline_builder_scoped_variables_histogram
+ name = :gitlab_ci_pipeline_builder_scoped_variables_duration
+ comment = 'Pipeline variables builder scoped_variables duration'
+ labels = {}
+ buckets = [0.01, 0.05, 0.1, 0.3, 0.5, 1, 2, 5, 10, 30, 60, 120]
+
+ ::Gitlab::Metrics.histogram(name, comment, labels, buckets)
+ end
+
def self.pipeline_processing_events_counter
name = :gitlab_ci_pipeline_processing_events_total
comment = 'Total amount of pipeline processing events'
diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb
index 9ad5d6538b7..72837b8ec22 100644
--- a/lib/gitlab/ci/pipeline/seed/build.rb
+++ b/lib/gitlab/ci/pipeline/seed/build.rb
@@ -11,11 +11,11 @@ module Gitlab
delegate :dig, to: :@seed_attributes
- def initialize(context, attributes, previous_stages, current_stage)
+ def initialize(context, attributes, stages_for_needs_lookup = [])
@context = context
@pipeline = context.pipeline
@seed_attributes = attributes
- @stages_for_needs_lookup = (previous_stages + [current_stage]).compact
+ @stages_for_needs_lookup = stages_for_needs_lookup.compact
@needs_attributes = dig(:needs_attributes)
@resource_group_key = attributes.delete(:resource_group_key)
@job_variables = @seed_attributes.delete(:job_variables)
@@ -90,7 +90,7 @@ module Gitlab
::Ci::Bridge.new(attributes)
else
::Ci::Build.new(attributes).tap do |build|
- build.assign_attributes(self.class.environment_attributes_for(build))
+ build.assign_attributes(self.class.deployment_attributes_for(build))
end
end
end
@@ -101,10 +101,10 @@ module Gitlab
.to_resource
end
- def self.environment_attributes_for(build)
+ def self.deployment_attributes_for(build, environment = nil)
return {} unless build.has_environment?
- environment = Seed::Environment.new(build).to_resource
+ environment = Seed::Environment.new(build).to_resource if environment.nil?
unless environment.persisted?
if Feature.enabled?(:surface_environment_creation_failure, build.project, default_enabled: :yaml) &&
@@ -173,7 +173,7 @@ module Gitlab
end
def variable_expansion_errors
- expanded_collection = evaluate_context.variables.sort_and_expand_all(@pipeline.project)
+ expanded_collection = evaluate_context.variables.sort_and_expand_all
errors = expanded_collection.errors
["#{name}: #{errors}"] if errors
end
@@ -244,5 +244,3 @@ module Gitlab
end
end
end
-
-Gitlab::Ci::Pipeline::Seed::Build.prepend_mod_with('Gitlab::Ci::Pipeline::Seed::Build')
diff --git a/lib/gitlab/ci/pipeline/seed/stage.rb b/lib/gitlab/ci/pipeline/seed/stage.rb
index 018fb260986..bc56fe9bef9 100644
--- a/lib/gitlab/ci/pipeline/seed/stage.rb
+++ b/lib/gitlab/ci/pipeline/seed/stage.rb
@@ -17,7 +17,7 @@ module Gitlab
@previous_stages = previous_stages
@builds = attributes.fetch(:builds).map do |attributes|
- Seed::Build.new(context, attributes, previous_stages, self)
+ Seed::Build.new(context, attributes, previous_stages + [self])
end
end
diff --git a/lib/gitlab/ci/reports/security/finding.rb b/lib/gitlab/ci/reports/security/finding.rb
index 39531e12f69..47ec82ac86c 100644
--- a/lib/gitlab/ci/reports/security/finding.rb
+++ b/lib/gitlab/ci/reports/security/finding.rb
@@ -17,7 +17,6 @@ module Gitlab
attr_reader :name
attr_reader :old_location
attr_reader :project_fingerprint
- attr_reader :raw_metadata
attr_reader :report_type
attr_reader :scanner
attr_reader :scan
@@ -28,10 +27,13 @@ module Gitlab
attr_reader :details
attr_reader :signatures
attr_reader :project_id
+ attr_reader :original_data
delegate :file_path, :start_line, :end_line, to: :location
- def initialize(compare_key:, identifiers:, flags: [], links: [], remediations: [], location:, metadata_version:, name:, raw_metadata:, report_type:, scanner:, scan:, uuid:, confidence: nil, severity: nil, details: {}, signatures: [], project_id: nil, vulnerability_finding_signatures_enabled: false) # rubocop:disable Metrics/ParameterLists
+ alias_method :cve, :compare_key
+
+ def initialize(compare_key:, identifiers:, flags: [], links: [], remediations: [], location:, metadata_version:, name:, original_data:, report_type:, scanner:, scan:, uuid:, confidence: nil, severity: nil, details: {}, signatures: [], project_id: nil, vulnerability_finding_signatures_enabled: false) # rubocop:disable Metrics/ParameterLists
@compare_key = compare_key
@confidence = confidence
@identifiers = identifiers
@@ -40,7 +42,7 @@ module Gitlab
@location = location
@metadata_version = metadata_version
@name = name
- @raw_metadata = raw_metadata
+ @original_data = original_data
@report_type = report_type
@scanner = scanner
@scan = scan
@@ -74,6 +76,10 @@ module Gitlab
uuid
details
signatures
+ description
+ message
+ cve
+ solution
].each_with_object({}) do |key, hash|
hash[key] = public_send(key) # rubocop:disable GitlabSecurity/PublicSend
end
@@ -88,8 +94,8 @@ module Gitlab
@location = new_location
end
- def unsafe?(severity_levels)
- severity.in?(severity_levels)
+ def unsafe?(severity_levels, report_types)
+ severity.to_s.in?(severity_levels) && (report_types.blank? || report_type.to_s.in?(report_types) )
end
def eql?(other)
@@ -141,6 +147,30 @@ module Gitlab
scanner <=> other.scanner
end
+ def has_signatures?
+ signatures.present?
+ end
+
+ def raw_metadata
+ @raw_metadata ||= original_data.to_json
+ end
+
+ def description
+ original_data['description']
+ end
+
+ def message
+ original_data['message']
+ end
+
+ def solution
+ original_data['solution']
+ end
+
+ def location_data
+ original_data['location']
+ end
+
private
def generate_project_fingerprint
diff --git a/lib/gitlab/ci/reports/security/report.rb b/lib/gitlab/ci/reports/security/report.rb
index 1ba2d909d99..417319cb5be 100644
--- a/lib/gitlab/ci/reports/security/report.rb
+++ b/lib/gitlab/ci/reports/security/report.rb
@@ -69,6 +69,10 @@ module Gitlab
primary_scanner <=> other.primary_scanner
end
+
+ def has_signatures?
+ findings.any?(&:has_signatures?)
+ end
end
end
end
diff --git a/lib/gitlab/ci/reports/security/reports.rb b/lib/gitlab/ci/reports/security/reports.rb
index b7a5e36b108..b6372349f68 100644
--- a/lib/gitlab/ci/reports/security/reports.rb
+++ b/lib/gitlab/ci/reports/security/reports.rb
@@ -22,21 +22,24 @@ module Gitlab
reports.values.flat_map(&:findings)
end
- def violates_default_policy_against?(target_reports, vulnerabilities_allowed, severity_levels)
- unsafe_findings_count(target_reports, severity_levels) > vulnerabilities_allowed
+ def violates_default_policy_against?(target_reports, vulnerabilities_allowed, severity_levels, vulnerability_states, report_types = [])
+ unsafe_findings_count(target_reports, severity_levels, vulnerability_states, report_types) > vulnerabilities_allowed
end
- private
-
- def findings_diff(target_reports)
- findings - target_reports&.findings.to_a
+ def unsafe_findings_uuids(severity_levels, report_types)
+ findings.select { |finding| finding.unsafe?(severity_levels, report_types) }.map(&:uuid)
end
- def unsafe_findings_count(target_reports, severity_levels)
- findings_diff(target_reports).count {|finding| finding.unsafe?(severity_levels)}
+ private
+
+ def unsafe_findings_count(target_reports, severity_levels, vulnerability_states, report_types)
+ new_uuids = unsafe_findings_uuids(severity_levels, report_types) - target_reports&.unsafe_findings_uuids(severity_levels, report_types).to_a
+ new_uuids.count
end
end
end
end
end
end
+
+Gitlab::Ci::Reports::Security::Reports.prepend_mod_with('Gitlab::Ci::Reports::Security::Reports')
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index adb5d430d46..89fd59d98f4 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -179,3 +179,11 @@ include:
- template: Security/License-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
- template: Security/SAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
+
+# The latest build job generates a dotenv report artifact with a CI_APPLICATION_TAG
+# that also includes the image digest. This configures Auto Deploy to receive
+# this artifact and use the updated CI_APPLICATION_TAG for deployments.
+.auto-deploy:
+ dependencies: [build]
+dast_environment_deploy:
+ dependencies: [build]
diff --git a/lib/gitlab/ci/templates/Django.gitlab-ci.yml b/lib/gitlab/ci/templates/Django.gitlab-ci.yml
index f147ad9332d..426076c84a1 100644
--- a/lib/gitlab/ci/templates/Django.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Django.gitlab-ci.yml
@@ -1,54 +1,76 @@
-# To contribute improvements to CI/CD templates, please follow the Development guide at:
-# https://docs.gitlab.com/ee/development/cicd/templates.html
-# This specific template is located at:
-# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Django.gitlab-ci.yml
-
-# Official framework image. Look for the different tagged releases at:
-# https://hub.docker.com/r/library/python
-image: python:latest
-
-# Pick zero or more services to be used on all builds.
-# Only needed when using a docker container to run your tests in.
-# Check out: http://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service
-services:
- - mysql:latest
- - postgres:latest
+# This example is for testing Django with MySQL.
+#
+# The test CI/CD variables MYSQL_DB, MYSQL_USER and MYSQL_PASS can be set in the project settings at:
+# Settings --> CI/CD --> Variables
+#
+# The Django settings in settings.py, used in tests, might look similar to:
+#
+# DATABASES = {
+# 'default': {
+# 'ENGINE': 'django.db.backends.mysql',
+# 'NAME': os.environ.get('MYSQL_DATABASE'),
+# 'USER': os.environ.get('MYSQL_USER'),
+# 'PASSWORD': os.environ.get('MYSQL_PASSWORD'),
+# 'HOST': 'mysql',
+# 'PORT': '3306',
+# 'CONN_MAX_AGE':60,
+# },
+# }
+#
+# It is possible to use '--settings' to specify a custom settings file on the command line below or use an environment
+# variable to trigger an include on the bottom of your settings.py:
+# if os.environ.get('DJANGO_CONFIG')=='test':
+# from .settings_test import *
+#
+# It is also possible to hardcode the database name and credentials in the settings.py file and in the .gitlab-ci.yml file.
+#
+# The mysql service needs some variables too. See https://hub.docker.com/_/mysql for possible mysql env variables
+# Note that when using a service in GitLab CI/CD that needs environment variables to run, only variables defined in
+# .gitlab-ci.yml are passed to the service and variables defined in the GitLab UI are not.
+# https://gitlab.com/gitlab-org/gitlab/-/issues/30178
variables:
- POSTGRES_DB: database_name
+ # DJANGO_CONFIG: "test"
+ MYSQL_DATABASE: $MYSQL_DB
+ MYSQL_ROOT_PASSWORD: $MYSQL_PASS
+ MYSQL_USER: $MYSQL_USER
+ MYSQL_PASSWORD: $MYSQL_PASS
-# This folder is cached between builds
-# https://docs.gitlab.com/ee/ci/yaml/index.html#cache
-cache:
- paths:
- - ~/.cache/pip/
+default:
+ image: ubuntu:20.04
+ #
+ # Pick zero or more services to be used on all builds.
+ # Only needed when using a docker container to run your tests in.
+ # Check out: http://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service
+ services:
+ - mysql:8.0
+ #
+ # This folder is cached between builds
+ # http://docs.gitlab.com/ee/ci/yaml/README.html#cache
+ cache:
+ paths:
+ - ~/.cache/pip/
+ before_script:
+ - apt -y update
+ - apt -y install apt-utils
+ - apt -y install net-tools python3.8 python3-pip mysql-client libmysqlclient-dev
+ - apt -y upgrade
+ - pip3 install -r requirements.txt
-# This is a basic example for a gem or script which doesn't use
-# services such as redis or postgres
-before_script:
- - python -V # Print out python version for debugging
- # Uncomment next line if your Django app needs a JS runtime:
- # - apt-get update -q && apt-get install nodejs -yqq
- - pip install -r requirements.txt
-# To get Django tests to work you may need to create a settings file using
-# the following DATABASES:
-#
-# DATABASES = {
-# 'default': {
-# 'ENGINE': 'django.db.backends.postgresql_psycopg2',
-# 'NAME': 'ci',
-# 'USER': 'postgres',
-# 'PASSWORD': 'postgres',
-# 'HOST': 'postgres',
-# 'PORT': '5432',
-# },
-# }
-#
-# and then adding `--settings app.settings.ci` (or similar) to the test command
+migrations:
+ stage: build
+ script:
+ - python3 manage.py makemigrations
+ # - python3 manage.py makemigrations myapp
+ - python3 manage.py migrate
+ - python3 manage.py check
+
-test:
- variables:
- DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB"
+django-tests:
+ stage: test
script:
- - python manage.py test
+ # The MYSQL user only gets permissions for MYSQL_DB, so Django can't create a test database.
+ - echo "GRANT ALL on *.* to '${MYSQL_USER}';"| mysql -u root --password="${MYSQL_ROOT_PASSWORD}" -h mysql
+ # use python3 explicitly. see https://wiki.ubuntu.com/Python/3
+ - python3 manage.py test
diff --git a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
index 56899614cc6..99fd9870b1d 100644
--- a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
@@ -70,7 +70,7 @@ browser_performance:
reports:
browser_performance: browser-performance.json
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$BROWSER_PERFORMANCE_DISABLED'
when: never
diff --git a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml
index 56899614cc6..99fd9870b1d 100644
--- a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.latest.gitlab-ci.yml
@@ -70,7 +70,7 @@ browser_performance:
reports:
browser_performance: browser-performance.json
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$BROWSER_PERFORMANCE_DISABLED'
when: never
diff --git a/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml
index 6a3b0cfa9e7..211adc9bd5b 100644
--- a/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml
@@ -3,7 +3,7 @@
# This template is scheduled for removal when testing is complete: https://gitlab.com/gitlab-org/gitlab/-/issues/337987
variables:
- AUTO_BUILD_IMAGE_VERSION: 'v1.3.1'
+ AUTO_BUILD_IMAGE_VERSION: 'v1.5.0'
build:
stage: build
@@ -23,6 +23,9 @@ build:
export CI_APPLICATION_TAG=${CI_APPLICATION_TAG:-$CI_COMMIT_TAG}
fi
- /build/build.sh
+ artifacts:
+ reports:
+ dotenv: gl-auto-build-variables.env
rules:
- if: '$BUILD_DISABLED'
when: never
diff --git a/lib/gitlab/ci/templates/Jobs/CF-Provision.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/CF-Provision.gitlab-ci.yml
index 31ca68c57d7..11f8376f0b4 100644
--- a/lib/gitlab/ci/templates/Jobs/CF-Provision.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/CF-Provision.gitlab-ci.yml
@@ -9,6 +9,6 @@ cloud_formation:
rules:
- if: '($AUTO_DEVOPS_PLATFORM_TARGET != "EC2") || ($AUTO_DEVOPS_PLATFORM_TARGET != "ECS")'
when: never
- - if: '$CI_KUBERNETES_ACTIVE'
+ - if: '$CI_KUBERNETES_ACTIVE || $KUBECONFIG'
when: never
- if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
diff --git a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
index 65a58130962..28ac627f103 100644
--- a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.14.0'
+ DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.17.0'
.dast-auto-deploy:
image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:${DAST_AUTO_DEPLOY_IMAGE_VERSION}"
@@ -10,6 +10,7 @@ dast_environment_deploy:
script:
- auto-deploy check_kube_domain
- auto-deploy download_chart
+ - auto-deploy use_kube_context || true
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
@@ -29,7 +30,7 @@ dast_environment_deploy:
- if: $DAST_WEBSITE # we don't need to create a review app if a URL is already given
when: never
- if: $CI_COMMIT_BRANCH &&
- $CI_KUBERNETES_ACTIVE &&
+ ($CI_KUBERNETES_ACTIVE || $KUBECONFIG) &&
$GITLAB_FEATURES =~ /\bdast\b/
stop_dast_environment:
@@ -38,6 +39,7 @@ stop_dast_environment:
variables:
GIT_STRATEGY: none
script:
+ - auto-deploy use_kube_context || true
- auto-deploy initialize_tiller
- auto-deploy delete
environment:
@@ -52,6 +54,6 @@ stop_dast_environment:
- if: $DAST_WEBSITE # we don't need to create a review app if a URL is already given
when: never
- if: $CI_COMMIT_BRANCH &&
- $CI_KUBERNETES_ACTIVE &&
+ ($CI_KUBERNETES_ACTIVE || $KUBECONFIG) &&
$GITLAB_FEATURES =~ /\bdast\b/
when: always
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
index 58f13746a1f..973db26bf2d 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
variables:
- AUTO_DEPLOY_IMAGE_VERSION: 'v2.14.0'
+ AUTO_DEPLOY_IMAGE_VERSION: 'v2.17.0'
.auto-deploy:
image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
@@ -11,6 +11,7 @@ review:
script:
- auto-deploy check_kube_domain
- auto-deploy download_chart
+ - auto-deploy use_kube_context || true
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
@@ -24,7 +25,7 @@ review:
paths: [environment_url.txt, tiller.log]
when: always
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: never
@@ -38,6 +39,7 @@ stop_review:
variables:
GIT_STRATEGY: none
script:
+ - auto-deploy use_kube_context || true
- auto-deploy initialize_tiller
- auto-deploy delete
environment:
@@ -45,7 +47,7 @@ stop_review:
action: stop
allow_failure: true
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: never
@@ -66,6 +68,7 @@ staging:
script:
- auto-deploy check_kube_domain
- auto-deploy download_chart
+ - auto-deploy use_kube_context || true
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
@@ -74,7 +77,7 @@ staging:
name: staging
url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_INGRESS_BASE_DOMAIN
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
when: never
@@ -91,6 +94,7 @@ canary:
script:
- auto-deploy check_kube_domain
- auto-deploy download_chart
+ - auto-deploy use_kube_context || true
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
@@ -101,7 +105,7 @@ canary:
rules:
- if: '$CI_DEPLOY_FREEZE != null'
when: never
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
when: never
@@ -114,6 +118,7 @@ canary:
script:
- auto-deploy check_kube_domain
- auto-deploy download_chart
+ - auto-deploy use_kube_context || true
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
@@ -132,7 +137,7 @@ production:
rules:
- if: '$CI_DEPLOY_FREEZE != null'
when: never
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$STAGING_ENABLED'
when: never
@@ -150,7 +155,7 @@ production_manual:
rules:
- if: '$CI_DEPLOY_FREEZE != null'
when: never
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$INCREMENTAL_ROLLOUT_ENABLED'
when: never
@@ -168,6 +173,7 @@ production_manual:
script:
- auto-deploy check_kube_domain
- auto-deploy download_chart
+ - auto-deploy use_kube_context || true
- auto-deploy ensure_namespace
- auto-deploy initialize_tiller
- auto-deploy create_secret
@@ -188,7 +194,7 @@ production_manual:
rules:
- if: '$CI_DEPLOY_FREEZE != null'
when: never
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$INCREMENTAL_ROLLOUT_MODE == "timed"'
when: never
@@ -203,7 +209,7 @@ production_manual:
rules:
- if: '$CI_DEPLOY_FREEZE != null'
when: never
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$INCREMENTAL_ROLLOUT_MODE == "manual"'
when: never
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
index 530ab1d0f99..248040b8b18 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
@@ -21,7 +21,7 @@ review:
paths: [environment_url.txt, tiller.log]
when: always
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: never
@@ -42,7 +42,7 @@ stop_review:
action: stop
allow_failure: true
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: never
@@ -71,7 +71,7 @@ staging:
name: staging
url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_INGRESS_BASE_DOMAIN
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
when: never
@@ -96,7 +96,7 @@ canary:
name: production
url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
when: never
@@ -125,7 +125,7 @@ canary:
production:
<<: *production_template
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$STAGING_ENABLED'
when: never
@@ -141,7 +141,7 @@ production_manual:
<<: *production_template
allow_failure: false
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$INCREMENTAL_ROLLOUT_ENABLED'
when: never
@@ -177,7 +177,7 @@ production_manual:
resource_group: production
allow_failure: true
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$INCREMENTAL_ROLLOUT_MODE == "timed"'
when: never
@@ -190,7 +190,7 @@ production_manual:
.timed_rollout_template: &timed_rollout_template
<<: *rollout_template
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$INCREMENTAL_ROLLOUT_MODE == "manual"'
when: never
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy/EC2.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy/EC2.gitlab-ci.yml
index 7efbcab221b..ab3bc511cba 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy/EC2.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy/EC2.gitlab-ci.yml
@@ -16,7 +16,7 @@ review_ec2:
rules:
- if: '$AUTO_DEVOPS_PLATFORM_TARGET != "EC2"'
when: never
- - if: '$CI_KUBERNETES_ACTIVE'
+ - if: '$CI_KUBERNETES_ACTIVE || $KUBECONFIG'
when: never
- if: '$REVIEW_DISABLED'
when: never
@@ -32,7 +32,7 @@ production_ec2:
rules:
- if: '$AUTO_DEVOPS_PLATFORM_TARGET != "EC2"'
when: never
- - if: '$CI_KUBERNETES_ACTIVE'
+ - if: '$CI_KUBERNETES_ACTIVE || $KUBECONFIG'
when: never
- if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
when: never
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml
index 332c58c8695..9bb2ba69d84 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml
@@ -42,7 +42,7 @@ review_ecs:
rules:
- if: '$AUTO_DEVOPS_PLATFORM_TARGET != "ECS"'
when: never
- - if: '$CI_KUBERNETES_ACTIVE'
+ - if: '$CI_KUBERNETES_ACTIVE || $KUBECONFIG'
when: never
- if: '$REVIEW_DISABLED'
when: never
@@ -58,7 +58,7 @@ stop_review_ecs:
rules:
- if: '$AUTO_DEVOPS_PLATFORM_TARGET != "ECS"'
when: never
- - if: '$CI_KUBERNETES_ACTIVE'
+ - if: '$CI_KUBERNETES_ACTIVE || $KUBECONFIG'
when: never
- if: '$REVIEW_DISABLED'
when: never
@@ -77,7 +77,7 @@ review_fargate:
rules:
- if: '$AUTO_DEVOPS_PLATFORM_TARGET != "FARGATE"'
when: never
- - if: '$CI_KUBERNETES_ACTIVE'
+ - if: '$CI_KUBERNETES_ACTIVE || $KUBECONFIG'
when: never
- if: '$REVIEW_DISABLED'
when: never
@@ -93,7 +93,7 @@ stop_review_fargate:
rules:
- if: '$AUTO_DEVOPS_PLATFORM_TARGET != "FARGATE"'
when: never
- - if: '$CI_KUBERNETES_ACTIVE'
+ - if: '$CI_KUBERNETES_ACTIVE || $KUBECONFIG'
when: never
- if: '$REVIEW_DISABLED'
when: never
@@ -107,7 +107,7 @@ production_ecs:
rules:
- if: '$AUTO_DEVOPS_PLATFORM_TARGET != "ECS"'
when: never
- - if: '$CI_KUBERNETES_ACTIVE'
+ - if: '$CI_KUBERNETES_ACTIVE || $KUBECONFIG'
when: never
- if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
when: never
@@ -118,7 +118,7 @@ production_fargate:
rules:
- if: '$AUTO_DEVOPS_PLATFORM_TARGET != "FARGATE"'
when: never
- - if: '$CI_KUBERNETES_ACTIVE'
+ - if: '$CI_KUBERNETES_ACTIVE || $KUBECONFIG'
when: never
- if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
when: never
diff --git a/lib/gitlab/ci/templates/Jobs/Helm-2to3.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Helm-2to3.gitlab-ci.yml
index 1ec1aa60d88..d55c126eeb7 100644
--- a/lib/gitlab/ci/templates/Jobs/Helm-2to3.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Helm-2to3.gitlab-ci.yml
@@ -72,7 +72,7 @@
rules:
- if: '$MIGRATE_HELM_2TO3 != "true"'
when: never
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: never
@@ -89,7 +89,7 @@ review:helm-2to3:cleanup:
rules:
- if: '$MIGRATE_HELM_2TO3 != "true" && $CLEANUP_HELM_2TO3 == null'
when: never
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: never
@@ -104,7 +104,7 @@ review:helm-2to3:cleanup:
rules:
- if: '$MIGRATE_HELM_2TO3 != "true"'
when: never
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
when: never
@@ -119,7 +119,7 @@ staging:helm-2to3:cleanup:
rules:
- if: '$MIGRATE_HELM_2TO3 != "true" && $CLEANUP_HELM_2TO3 == null'
when: never
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
when: never
@@ -132,7 +132,7 @@ staging:helm-2to3:cleanup:
rules:
- if: '$MIGRATE_HELM_2TO3 != "true"'
when: never
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: manual
@@ -145,7 +145,7 @@ production:helm-2to3:cleanup:
rules:
- if: '$MIGRATE_HELM_2TO3 != "true" && $CLEANUP_HELM_2TO3 == null'
when: never
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: manual
diff --git a/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml
index 9a7c513c25f..8e34388893a 100644
--- a/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml
@@ -23,7 +23,7 @@ load_performance:
reports:
load_performance: load-performance.json
rules:
- - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ - if: '($CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == "") && ($KUBECONFIG == null || $KUBECONFIG == "")'
when: never
- if: '$LOAD_PERFORMANCE_DISABLED'
when: never
diff --git a/lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml
new file mode 100644
index 00000000000..b763705857e
--- /dev/null
+++ b/lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml
@@ -0,0 +1,34 @@
+variables:
+ # Setting this variable will affect all Security templates
+ # (SAST, Dependency Scanning, ...)
+ SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
+ SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
+
+iac-sast:
+ stage: test
+ artifacts:
+ reports:
+ sast: gl-sast-report.json
+ rules:
+ - when: never
+ # `rules` must be overridden explicitly by each child job
+ # see https://gitlab.com/gitlab-org/gitlab/-/issues/218444
+ variables:
+ SEARCH_MAX_DEPTH: 4
+ allow_failure: true
+ script:
+ - /analyzer run
+
+kics-iac-sast:
+ extends: iac-sast
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE_TAG: 0
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/kics:$SAST_ANALYZER_IMAGE_TAG"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /kics/
+ when: never
+ - if: $CI_COMMIT_BRANCH
diff --git a/lib/gitlab/ci/templates/Kaniko.gitlab-ci.yml b/lib/gitlab/ci/templates/Kaniko.gitlab-ci.yml
new file mode 100644
index 00000000000..f1b1c20b4e0
--- /dev/null
+++ b/lib/gitlab/ci/templates/Kaniko.gitlab-ci.yml
@@ -0,0 +1,47 @@
+# To contribute improvements to CI/CD templates, please follow the Development guide at:
+# https://docs.gitlab.com/ee/development/cicd/templates.html
+# This specific template is located at:
+# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Kaniko.gitlab-ci.yml
+
+# Build and publish a tag/branch to Gitlab Docker Registry using Kaniko and Gitlab Docker executor.
+# Kaniko can build Docker images without using Docker-In-Docker and it's permission
+# drawbacks. No additional configuration required.
+kaniko-build:
+ variables:
+ # Additional options for Kaniko executor.
+ # For more details see https://github.com/GoogleContainerTools/kaniko/blob/master/README.md#additional-flags
+ KANIKO_ARGS: ""
+ stage: build
+ image:
+ # For latest releases see https://github.com/GoogleContainerTools/kaniko/releases
+ # Only debug/*-debug versions of the Kaniko image are known to work within Gitlab CI
+ name: gcr.io/kaniko-project/executor:debug
+ entrypoint: [""]
+ script:
+ # Compose docker tag name
+ # Git Branch/Tag to Docker Image Tag Mapping
+ # * Default Branch: main -> latest
+ # * Branch: feature/my-feature -> branch-feature-my-feature
+ # * Tag: v1.0.0/beta2 -> v1.0.0-beta2
+ - |
+ if [ "$CI_COMMIT_REF_NAME" = $CI_DEFAULT_BRANCH ]; then
+ VERSION="latest"
+ elif [ -n "$CI_COMMIT_TAG" ];then
+ NOSLASH=$(echo "$CI_COMMIT_TAG" | tr -s / - )
+ SANITIZED="${NOSLASH//[^a-zA-Z0-9\-\.]/}"
+ VERSION="$SANITIZED"
+ else \
+ NOSLASH=$(echo "$CI_COMMIT_REF_NAME" | tr -s / - )
+ SANITIZED="${NOSLASH//[^a-zA-Z0-9\-]/}"
+ VERSION="branch-$SANITIZED"
+ fi
+ - echo $VERSION
+ - mkdir -p /kaniko/.docker
+ # Write credentials to access Gitlab Container Registry within the runner/ci
+ - echo "{\"auths\":{\"$CI_REGISTRY\":{\"auth\":\"$(echo -n ${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD} | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
+ # Build and push the container. To disable push add --no-push
+ - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$VERSION $KANIKO_ARGS
+ # Run this job in a branch/tag where a Dockerfile exists
+ rules:
+ - exists:
+ - Dockerfile
diff --git a/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml
index ceeefa8aea6..544774d3b06 100644
--- a/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml
@@ -1,7 +1,7 @@
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
-# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.lastest.gitlab-ci.yml
+# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/
#
diff --git a/lib/gitlab/ci/templates/Security/Cluster-Image-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Cluster-Image-Scanning.gitlab-ci.yml
index ed4876c2bcc..6b861510eef 100644
--- a/lib/gitlab/ci/templates/Security/Cluster-Image-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Cluster-Image-Scanning.gitlab-ci.yml
@@ -12,7 +12,7 @@
# List of available variables: https://docs.gitlab.com/ee/user/application_security/cluster_image_scanning/#available-variables
variables:
- CIS_ANALYZER_IMAGE: registry.gitlab.com/gitlab-org/security-products/analyzers/cluster-image-scanning:0
+ CIS_ANALYZER_IMAGE: registry.gitlab.com/security-products/cluster-image-scanning:0
cluster_image_scanning:
image: "$CIS_ANALYZER_IMAGE"
diff --git a/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
index 0802868d67f..0ecbe5e14b8 100644
--- a/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
@@ -51,7 +51,7 @@ dast:
$REVIEW_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
- $CI_KUBERNETES_ACTIVE &&
+ ($CI_KUBERNETES_ACTIVE || $KUBECONFIG) &&
$GITLAB_FEATURES =~ /\bdast\b/
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bdast\b/
diff --git a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
index ac7d87a4cda..3d07674c377 100644
--- a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
@@ -1,7 +1,7 @@
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
-# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST.lastest.gitlab-ci.yml
+# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
# To use this template, add the following to your .gitlab-ci.yml file:
#
@@ -52,7 +52,7 @@ dast:
$DAST_API_SPECIFICATION == null
when: never
- if: $CI_COMMIT_BRANCH &&
- $CI_KUBERNETES_ACTIVE &&
+ ($CI_KUBERNETES_ACTIVE || $KUBECONFIG) &&
$GITLAB_FEATURES =~ /\bdast\b/
- if: $CI_COMMIT_BRANCH &&
$DAST_WEBSITE
diff --git a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
index aa7b394a13c..197ce2438e6 100644
--- a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
@@ -74,6 +74,9 @@ gemnasium-maven-dependency_scanning:
# override the analyzer image with a custom value. This may be subject to change or
# breakage across GitLab releases.
DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gemnasium-maven:$DS_MAJOR_VERSION"
+ # Stop reporting Gradle as "maven".
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/338252
+ DS_REPORT_PACKAGE_MANAGER_MAVEN_WHEN_JAVA: "false"
rules:
- if: $DEPENDENCY_SCANNING_DISABLED
when: never
@@ -97,6 +100,9 @@ gemnasium-python-dependency_scanning:
# override the analyzer image with a custom value. This may be subject to change or
# breakage across GitLab releases.
DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gemnasium-python:$DS_MAJOR_VERSION"
+ # Stop reporting Pipenv and Setuptools as "pip".
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/338252
+ DS_REPORT_PACKAGE_MANAGER_PIP_WHEN_PYTHON: "false"
rules:
- if: $DEPENDENCY_SCANNING_DISABLED
when: never
diff --git a/lib/gitlab/ci/templates/Security/SAST-IaC.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST-IaC.latest.gitlab-ci.yml
new file mode 100644
index 00000000000..8c0d72ff282
--- /dev/null
+++ b/lib/gitlab/ci/templates/Security/SAST-IaC.latest.gitlab-ci.yml
@@ -0,0 +1,2 @@
+include:
+ template: Jobs/SAST-IaC.latest.gitlab-ci.yml
diff --git a/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml
index 081a3a6cc78..e554742735c 100644
--- a/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml
@@ -7,20 +7,17 @@ include:
- template: Terraform/Base.latest.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
stages:
- - init
- validate
- build
- deploy
- - cleanup
-
-init:
- extends: .terraform:init
fmt:
extends: .terraform:fmt
+ needs: []
validate:
extends: .terraform:validate
+ needs: []
build:
extends: .terraform:build
diff --git a/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
index 3a70e6bc4b8..a0ec07e61e1 100644
--- a/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
@@ -21,18 +21,11 @@ cache:
paths:
- ${TF_ROOT}/.terraform/
-.terraform:init: &terraform_init
- stage: init
- script:
- - cd ${TF_ROOT}
- - gitlab-terraform init
-
.terraform:fmt: &terraform_fmt
stage: validate
- needs: []
script:
- cd ${TF_ROOT}
- - gitlab-terraform fmt -check -recursive
+ - gitlab-terraform fmt
allow_failure: true
.terraform:validate: &terraform_validate
@@ -60,10 +53,9 @@ cache:
- cd ${TF_ROOT}
- gitlab-terraform apply
resource_group: ${TF_STATE_NAME}
- when: manual
- only:
- variables:
- - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ when: manual
.terraform:destroy: &terraform_destroy
stage: cleanup
diff --git a/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml b/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml
index 22c40d8a8b8..4f63ff93d4d 100644
--- a/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml
@@ -13,7 +13,7 @@ stages:
a11y:
stage: accessibility
- image: registry.gitlab.com/gitlab-org/ci-cd/accessibility:5.3.0-gitlab.3
+ image: registry.gitlab.com/gitlab-org/ci-cd/accessibility:6.0.1
script: /gitlab-accessibility.sh $a11y_urls
allow_failure: true
artifacts:
diff --git a/lib/gitlab/ci/trace.rb b/lib/gitlab/ci/trace.rb
index 25075cc8f90..7d08f0230fc 100644
--- a/lib/gitlab/ci/trace.rb
+++ b/lib/gitlab/ci/trace.rb
@@ -78,7 +78,7 @@ module Gitlab
end
def archived_trace_exist?
- trace_artifact&.exists?
+ archived?
end
def live_trace_exist?
@@ -156,7 +156,7 @@ module Gitlab
def read_stream
stream = Gitlab::Ci::Trace::Stream.new do
- if trace_artifact
+ if archived?
trace_artifact.open
elsif job.trace_chunks.any?
Gitlab::Ci::Trace::ChunkedIO.new(job)
@@ -174,7 +174,7 @@ module Gitlab
def unsafe_write!(mode, &blk)
stream = Gitlab::Ci::Trace::Stream.new do
- if trace_artifact
+ if archived?
raise AlreadyArchivedError, 'Could not write to the archived trace'
elsif current_path
File.open(current_path, mode)
@@ -195,7 +195,7 @@ module Gitlab
def unsafe_archive!
raise ArchiveError, 'Job is not finished yet' unless job.complete?
- already_archived?.tap do |archived|
+ archived?.tap do |archived|
destroy_any_orphan_trace_data!
raise AlreadyArchivedError, 'Could not archive again' if archived
end
@@ -218,7 +218,7 @@ module Gitlab
end
end
- def already_archived?
+ def archived?
# TODO check checksum to ensure archive completed successfully
# See https://gitlab.com/gitlab-org/gitlab/-/issues/259619
trace_artifact&.archived_trace_exists?
@@ -227,11 +227,12 @@ module Gitlab
def destroy_any_orphan_trace_data!
return unless trace_artifact
- if already_archived?
- # An archive already exists, so make sure to remove the trace chunks
+ if archived?
+ # An archive file exists, so remove the trace chunks
erase_trace_chunks!
else
- # An archive already exists, but its associated file does not, so remove it
+ # A trace artifact record exists with no archive file
+ # but an archive was attempted, so cleanup the associated record
trace_artifact.destroy!
end
end
diff --git a/lib/gitlab/ci/trace/archive.rb b/lib/gitlab/ci/trace/archive.rb
index 5047cf04562..d4a451ca526 100644
--- a/lib/gitlab/ci/trace/archive.rb
+++ b/lib/gitlab/ci/trace/archive.rb
@@ -62,7 +62,7 @@ module Gitlab
trace_metadata.update!(remote_checksum: remote_checksum)
unless trace_metadata.remote_checksum_valid?
- metrics.increment_error_counter(type: :archive_invalid_checksum)
+ metrics.increment_error_counter(error_reason: :archive_invalid_checksum)
end
end
diff --git a/lib/gitlab/ci/trace/metrics.rb b/lib/gitlab/ci/trace/metrics.rb
index 174a5f184ff..f3ded3cda4a 100644
--- a/lib/gitlab/ci/trace/metrics.rb
+++ b/lib/gitlab/ci/trace/metrics.rb
@@ -21,7 +21,7 @@ module Gitlab
:corrupted # malformed trace found after comparing CRC32 and size
].freeze
- TRACE_ERROR_TYPES = [
+ TRACE_ERROR_REASONS = [
:chunks_invalid_size, # used to be :corrupted
:chunks_invalid_checksum, # used to be :invalid
:archive_invalid_checksum # malformed trace found into object store after comparing MD5
@@ -39,12 +39,12 @@ module Gitlab
self.class.trace_bytes.increment({}, size.to_i)
end
- def increment_error_counter(type: :unknown)
- unless TRACE_ERROR_TYPES.include?(type)
- raise ArgumentError, "unknown error type: #{type}"
+ def increment_error_counter(error_reason: :unknown)
+ unless TRACE_ERROR_REASONS.include?(error_reason)
+ raise ArgumentError, "unknown error reason: #{error_reason}"
end
- self.class.trace_errors_counter.increment(type: type)
+ self.class.trace_errors_counter.increment(error_reason: error_reason)
end
def observe_migration_duration(seconds)
diff --git a/lib/gitlab/ci/variables/builder.rb b/lib/gitlab/ci/variables/builder.rb
new file mode 100644
index 00000000000..f4c5a06af97
--- /dev/null
+++ b/lib/gitlab/ci/variables/builder.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Variables
+ class Builder
+ include ::Gitlab::Utils::StrongMemoize
+
+ def initialize(pipeline)
+ @pipeline = pipeline
+ end
+
+ def scoped_variables(job, environment:, dependencies:)
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ variables.concat(predefined_variables(job)) if pipeline.predefined_vars_in_builder_enabled?
+ end
+ end
+
+ private
+
+ attr_reader :pipeline
+
+ def predefined_variables(job)
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ variables.append(key: 'CI_JOB_NAME', value: job.name)
+ variables.append(key: 'CI_JOB_STAGE', value: job.stage)
+ variables.append(key: 'CI_JOB_MANUAL', value: 'true') if job.action?
+ variables.append(key: 'CI_PIPELINE_TRIGGERED', value: 'true') if job.trigger_request
+
+ variables.append(key: 'CI_NODE_INDEX', value: job.options[:instance].to_s) if job.options&.include?(:instance)
+ variables.append(key: 'CI_NODE_TOTAL', value: ci_node_total_value(job).to_s)
+
+ # legacy variables
+ variables.append(key: 'CI_BUILD_NAME', value: job.name)
+ variables.append(key: 'CI_BUILD_STAGE', value: job.stage)
+ variables.append(key: 'CI_BUILD_TRIGGERED', value: 'true') if job.trigger_request
+ variables.append(key: 'CI_BUILD_MANUAL', value: 'true') if job.action?
+ end
+ end
+
+ def ci_node_total_value(job)
+ parallel = job.options&.dig(:parallel)
+ parallel = parallel.dig(:total) if parallel.is_a?(Hash)
+ parallel || 1
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/variables/collection.rb b/lib/gitlab/ci/variables/collection.rb
index 09c75a2b3f1..a00c1da97ea 100644
--- a/lib/gitlab/ci/variables/collection.rb
+++ b/lib/gitlab/ci/variables/collection.rb
@@ -89,9 +89,7 @@ module Gitlab
end
end
- def sort_and_expand_all(project, keep_undefined: false)
- return self if Feature.disabled?(:variable_inside_variable, project, default_enabled: :yaml)
-
+ def sort_and_expand_all(keep_undefined: false)
sorted = Sort.new(self)
return self.class.new(self, sorted.errors) unless sorted.valid?
diff --git a/lib/gitlab/ci/yaml_processor/result.rb b/lib/gitlab/ci/yaml_processor/result.rb
index a97c7050fbb..6215ba40ebe 100644
--- a/lib/gitlab/ci/yaml_processor/result.rb
+++ b/lib/gitlab/ci/yaml_processor/result.rb
@@ -80,7 +80,6 @@ module Gitlab
cache: job[:cache],
resource_group_key: job[:resource_group],
scheduling_type: job[:scheduling_type],
- secrets: job[:secrets],
options: {
image: job[:image],
services: job[:services],
diff --git a/lib/gitlab/config_checker/external_database_checker.rb b/lib/gitlab/config_checker/external_database_checker.rb
index a56f2413615..54320b7ff9a 100644
--- a/lib/gitlab/config_checker/external_database_checker.rb
+++ b/lib/gitlab/config_checker/external_database_checker.rb
@@ -6,7 +6,7 @@ module Gitlab
extend self
def check
- return [] if Gitlab::Database.main.postgresql_minimum_supported_version?
+ return [] if ApplicationRecord.database.postgresql_minimum_supported_version?
[
{
@@ -15,7 +15,7 @@ module Gitlab
'%{pg_version_minimum} is required for this version of GitLab. ' \
'Please upgrade your environment to a supported PostgreSQL version, ' \
'see %{pg_requirements_url} for details.') % {
- pg_version_current: Gitlab::Database.main.version,
+ pg_version_current: ApplicationRecord.database.version,
pg_version_minimum: Gitlab::Database::MINIMUM_POSTGRES_VERSION,
pg_requirements_url: '<a href="https://docs.gitlab.com/ee/install/requirements.html#database">database requirements</a>'
}
diff --git a/lib/gitlab/container_repository/tags/cache.rb b/lib/gitlab/container_repository/tags/cache.rb
new file mode 100644
index 00000000000..ff457fb9219
--- /dev/null
+++ b/lib/gitlab/container_repository/tags/cache.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ContainerRepository
+ module Tags
+ class Cache
+ def initialize(container_repository)
+ @container_repository = container_repository
+ @cached_tag_names = Set.new
+ end
+
+ def populate(tags)
+ return if tags.empty?
+
+ # This will load all tags in one Redis roundtrip
+ # the maximum number of tags is configurable and is set to 200 by default.
+ # https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/packages/container_registry/index.md#set-cleanup-limits-to-conserve-resources
+ keys = tags.map(&method(:cache_key))
+ cached_tags_count = 0
+
+ ::Gitlab::Redis::Cache.with do |redis|
+ tags.zip(redis.mget(keys)).each do |tag, created_at|
+ next unless created_at
+
+ tag.created_at = DateTime.rfc3339(created_at)
+ @cached_tag_names << tag.name
+ cached_tags_count += 1
+ end
+ end
+
+ cached_tags_count
+ end
+
+ def insert(tags, max_ttl_in_seconds)
+ return unless max_ttl_in_seconds
+ return if tags.empty?
+
+ # tags with nil created_at are not cacheable
+ # tags already cached don't need to be cached again
+ cacheable_tags = tags.select do |tag|
+ tag.created_at.present? && !tag.name.in?(@cached_tag_names)
+ end
+
+ return if cacheable_tags.empty?
+
+ now = Time.zone.now
+
+ ::Gitlab::Redis::Cache.with do |redis|
+ # we use a pipeline instead of a MSET because each tag has
+ # a specific ttl
+ redis.pipelined do
+ cacheable_tags.each do |tag|
+ created_at = tag.created_at
+ # ttl is the max_ttl_in_seconds reduced by the number
+ # of seconds that the tag has already existed
+ ttl = max_ttl_in_seconds - (now - created_at).seconds
+ ttl = ttl.to_i
+ redis.set(cache_key(tag), created_at.rfc3339, ex: ttl) if ttl > 0
+ end
+ end
+ end
+ end
+
+ private
+
+ def cache_key(tag)
+ "container_repository:{#{@container_repository.id}}:tag:#{tag.name}:created_at"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/content_security_policy/config_loader.rb b/lib/gitlab/content_security_policy/config_loader.rb
index 0e3fa8b8d87..bdae59e7e3c 100644
--- a/lib/gitlab/content_security_policy/config_loader.rb
+++ b/lib/gitlab/content_security_policy/config_loader.rb
@@ -19,30 +19,42 @@ module Gitlab
'font_src' => "'self'",
'form_action' => "'self' https: http:",
'frame_ancestors' => "'self'",
- 'frame_src' => "'self' https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://content.googleapis.com https://content-compute.googleapis.com https://content-cloudbilling.googleapis.com https://content-cloudresourcemanager.googleapis.com",
+ 'frame_src' => ContentSecurityPolicy::Directives.frame_src,
'img_src' => "'self' data: blob: http: https:",
'manifest_src' => "'self'",
'media_src' => "'self'",
- 'script_src' => "'strict-dynamic' 'self' 'unsafe-inline' 'unsafe-eval' https://www.google.com/recaptcha/ https://www.recaptcha.net https://apis.google.com",
+ 'script_src' => ContentSecurityPolicy::Directives.script_src,
'style_src' => "'self' 'unsafe-inline'",
- 'worker_src' => "'self' blob: data:",
+ 'worker_src' => "#{Gitlab::Utils.append_path(Gitlab.config.gitlab.url, 'assets/')} blob: data:",
'object_src' => "'none'",
'report_uri' => nil
}
- # frame-src was deprecated in CSP level 2 in favor of child-src
- # CSP level 3 "undeprecated" frame-src and browsers fall back on child-src if it's missing
- # However Safari seems to read child-src first so we'll just keep both equal
- directives['child_src'] = directives['frame_src']
-
# connect_src with 'self' includes https/wss variations of the origin,
# however, safari hasn't covered this yet and we need to explicitly add
# support for websocket origins until Safari catches up with the specs
+ if Rails.env.development?
+ allow_webpack_dev_server(directives)
+ allow_letter_opener(directives)
+ allow_customersdot(directives) if ENV['CUSTOMER_PORTAL_URL'].present?
+ end
+
allow_websocket_connections(directives)
- allow_webpack_dev_server(directives) if Rails.env.development?
allow_cdn(directives, Settings.gitlab.cdn_host) if Settings.gitlab.cdn_host.present?
- allow_customersdot(directives) if Rails.env.development? && ENV['CUSTOMER_PORTAL_URL'].present?
allow_sentry(directives) if Gitlab.config.sentry&.enabled && Gitlab.config.sentry&.clientside_dsn
+ allow_framed_gitlab_paths(directives)
+
+ # The follow section contains workarounds to patch Safari's lack of support for CSP Level 3
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/343579
+ # frame-src was deprecated in CSP level 2 in favor of child-src
+ # CSP level 3 "undeprecated" frame-src and browsers fall back on child-src if it's missing
+ # However Safari seems to read child-src first so we'll just keep both equal
+ append_to_directive(directives, 'child_src', directives['frame_src'])
+
+ # Safari also doesn't support worker-src and only checks child-src
+ # So for compatibility until it catches up to other browsers we need to
+ # append worker-src's content to child-src
+ append_to_directive(directives, 'child_src', directives['worker_src'])
directives
end
@@ -100,6 +112,8 @@ module Gitlab
append_to_directive(directives, 'script_src', cdn_host)
append_to_directive(directives, 'style_src', cdn_host)
append_to_directive(directives, 'font_src', cdn_host)
+ append_to_directive(directives, 'worker_src', cdn_host)
+ append_to_directive(directives, 'frame_src', cdn_host)
end
def self.append_to_directive(directives, directive, text)
@@ -119,6 +133,21 @@ module Gitlab
append_to_directive(directives, 'connect_src', sentry_uri.to_s)
end
+
+ def self.allow_letter_opener(directives)
+ append_to_directive(directives, 'frame_src', Gitlab::Utils.append_path(Gitlab.config.gitlab.url, '/rails/letter_opener/'))
+ end
+
+ # Using 'self' in the CSP introduces several CSP bypass opportunities
+ # for this reason we list the URLs where GitLab frames itself instead
+ def self.allow_framed_gitlab_paths(directives)
+ # We need the version without trailing / for the sidekiq page itself
+ # and we also need the version with trailing / for "deeper" pages
+ # like /admin/sidekiq/busy
+ ['/admin/sidekiq', '/admin/sidekiq/', '/-/speedscope/index.html'].map do |path|
+ append_to_directive(directives, 'frame_src', Gitlab::Utils.append_path(Gitlab.config.gitlab.url, path))
+ end
+ end
end
end
end
diff --git a/lib/gitlab/content_security_policy/directives.rb b/lib/gitlab/content_security_policy/directives.rb
new file mode 100644
index 00000000000..30f3c16247d
--- /dev/null
+++ b/lib/gitlab/content_security_policy/directives.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# This module is used to return various SaaS related
+# ContentSecurityPolicy Directives src which may be
+# overridden in other variants of GitLab
+
+module Gitlab
+ module ContentSecurityPolicy
+ module Directives
+ def self.frame_src
+ "https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://content.googleapis.com https://content-compute.googleapis.com https://content-cloudbilling.googleapis.com https://content-cloudresourcemanager.googleapis.com"
+ end
+
+ def self.script_src
+ "'strict-dynamic' 'self' 'unsafe-inline' 'unsafe-eval' https://www.google.com/recaptcha/ https://www.recaptcha.net https://apis.google.com"
+ end
+ end
+ end
+end
+
+Gitlab::ContentSecurityPolicy::Directives.prepend_mod
diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb
index 7d7c604d86a..deaaab953aa 100644
--- a/lib/gitlab/contributions_calendar.rb
+++ b/lib/gitlab/contributions_calendar.rb
@@ -2,12 +2,15 @@
module Gitlab
class ContributionsCalendar
+ include TimeZoneHelper
+
attr_reader :contributor
attr_reader :current_user
attr_reader :projects
def initialize(contributor, current_user = nil)
@contributor = contributor
+ @contributor_time_instance = local_time_instance(contributor.timezone)
@current_user = current_user
@projects = if @contributor.include_private_contributions?
ContributedProjectsFinder.new(@contributor).execute(@contributor)
@@ -22,7 +25,7 @@ module Gitlab
# Can't use Event.contributions here because we need to check 3 different
# project_features for the (currently) 3 different contribution types
- date_from = 1.year.ago
+ date_from = @contributor_time_instance.now.years_ago(1)
repo_events = event_counts(date_from, :repository)
.having(action: :pushed)
issue_events = event_counts(date_from, :issues)
@@ -47,19 +50,21 @@ module Gitlab
def events_by_date(date)
return Event.none unless can_read_cross_project?
+ date_in_time_zone = date.in_time_zone(@contributor_time_instance)
+
Event.contributions.where(author_id: contributor.id)
- .where(created_at: date.beginning_of_day..date.end_of_day)
+ .where(created_at: date_in_time_zone.beginning_of_day..date_in_time_zone.end_of_day)
.where(project_id: projects)
.with_associations
end
# rubocop: enable CodeReuse/ActiveRecord
def starting_year
- 1.year.ago.year
+ @contributor_time_instance.now.years_ago(1).year
end
def starting_month
- Date.current.month
+ @contributor_time_instance.today.month
end
private
@@ -82,10 +87,10 @@ module Gitlab
.select(:id)
conditions = t[:created_at].gteq(date_from.beginning_of_day)
- .and(t[:created_at].lteq(Date.current.end_of_day))
+ .and(t[:created_at].lteq(@contributor_time_instance.today.end_of_day))
.and(t[:author_id].eq(contributor.id))
- date_interval = "INTERVAL '#{Time.zone.now.utc_offset} seconds'"
+ date_interval = "INTERVAL '#{@contributor_time_instance.now.utc_offset} seconds'"
Event.reorder(nil)
.select(t[:project_id], t[:target_type], t[:action], "date(created_at + #{date_interval}) AS date", 'count(id) as total_amount')
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index bfe3f06a56b..b9034cff447 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -85,7 +85,7 @@ module Gitlab
active_db_connection = ActiveRecord::Base.connection.active? rescue false
active_db_connection &&
- Gitlab::Database.main.cached_table_exists?('application_settings')
+ ApplicationSetting.database.cached_table_exists?
rescue ActiveRecord::NoDatabaseError
false
end
diff --git a/lib/gitlab/cycle_analytics/stage_summary.rb b/lib/gitlab/cycle_analytics/stage_summary.rb
index b309802f296..fdbf068303f 100644
--- a/lib/gitlab/cycle_analytics/stage_summary.rb
+++ b/lib/gitlab/cycle_analytics/stage_summary.rb
@@ -38,7 +38,8 @@ module Gitlab
serialize(
Summary::DeploymentFrequency.new(
deployments: deployments_summary.value.raw_value,
- options: @options),
+ options: @options,
+ project: @project),
with_unit: true
)
end
diff --git a/lib/gitlab/cycle_analytics/summary/base.rb b/lib/gitlab/cycle_analytics/summary/base.rb
index e30e526f017..f2ff86a40a2 100644
--- a/lib/gitlab/cycle_analytics/summary/base.rb
+++ b/lib/gitlab/cycle_analytics/summary/base.rb
@@ -17,6 +17,10 @@ module Gitlab
raise NotImplementedError, "Expected #{self.name} to implement value"
end
+ def links
+ []
+ end
+
private
attr_reader :project, :options
diff --git a/lib/gitlab/cycle_analytics/summary/deployment_frequency.rb b/lib/gitlab/cycle_analytics/summary/deployment_frequency.rb
index 1947866d772..2b1529bdc1a 100644
--- a/lib/gitlab/cycle_analytics/summary/deployment_frequency.rb
+++ b/lib/gitlab/cycle_analytics/summary/deployment_frequency.rb
@@ -6,7 +6,7 @@ module Gitlab
class DeploymentFrequency < Base
include SummaryHelper
- def initialize(deployments:, options:, project: nil)
+ def initialize(deployments:, options:, project:)
@deployments = deployments
super(project: project, options: options)
@@ -23,6 +23,13 @@ module Gitlab
def unit
_('per day')
end
+
+ def links
+ [
+ { "name" => _('Deployment frequency'), "url" => Gitlab::Routing.url_helpers.charts_project_pipelines_path(project, chart: 'deployment-frequency'), "label" => s_('ValueStreamAnalytics|Dashboard') },
+ { "name" => _('Deployment frequency'), "url" => Gitlab::Routing.url_helpers.help_page_path('user/analytics/index', anchor: 'definitions'), "docs_link" => true, "label" => s_('ValueStreamAnalytics|Go to docs') }
+ ]
+ end
end
end
end
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index b560d4cbca8..9c74e5d2ca8 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -59,19 +59,8 @@ module Gitlab
# that inher from ActiveRecord::Base; not just our own models that
# inherit from ApplicationRecord.
main: ::ActiveRecord::Base,
- ci: ::Ci::CiDatabaseRecord.connection_class? ? ::Ci::CiDatabaseRecord : nil
- }.compact.freeze
- end
-
- def self.databases
- @databases ||= database_base_models
- .transform_values { |connection_class| Connection.new(connection_class) }
- .with_indifferent_access
- .freeze
- end
-
- def self.main
- databases[PRIMARY_DATABASE_NAME]
+ ci: ::Ci::ApplicationRecord.connection_class? ? ::Ci::ApplicationRecord : nil
+ }.compact.with_indifferent_access.freeze
end
# We configure the database connection pool size automatically based on the
@@ -110,8 +99,10 @@ module Gitlab
def self.check_postgres_version_and_print_warning
return if Gitlab::Runtime.rails_runner?
- databases.each do |name, connection|
- next if connection.postgresql_minimum_supported_version?
+ database_base_models.each do |name, model|
+ database = Gitlab::Database::Reflection.new(model)
+
+ next if database.postgresql_minimum_supported_version?
Kernel.warn ERB.new(Rainbow.new.wrap(<<~EOS).red).result
@@ -122,7 +113,7 @@ module Gitlab
â€â–ˆâ–ˆâ–ˆâ€â–ˆâ–ˆâ–ˆâ€â€â–ˆâ–ˆâ€ ██â€â–ˆâ–ˆâ€ ██â€â–ˆâ–ˆâ€ â€â–ˆâ–ˆâ–ˆâ–ˆâ€â–ˆâ–ˆâ€â–ˆâ–ˆâ€ â€â–ˆâ–ˆâ–ˆâ–ˆâ€â€â–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ€â€
******************************************************************************
- You are using PostgreSQL #{connection.version} for the #{name} database, but PostgreSQL >= <%= Gitlab::Database::MINIMUM_POSTGRES_VERSION %>
+ You are using PostgreSQL #{database.version} for the #{name} database, but PostgreSQL >= <%= Gitlab::Database::MINIMUM_POSTGRES_VERSION %>
is required for this version of GitLab.
<% if Rails.env.development? || Rails.env.test? %>
If using gitlab-development-kit, please find the relevant steps here:
@@ -177,18 +168,6 @@ module Gitlab
yield
end
- # This method will allow cross database modifications within the block
- # Example:
- #
- # allow_cross_database_modification_within_transaction(url: 'url-to-an-issue') do
- # create(:build) # inserts ci_build and project record in one transaction
- # end
- def self.allow_cross_database_modification_within_transaction(url:)
- # this method will be overridden in:
- # spec/support/database/cross_database_modification_check.rb
- yield
- end
-
def self.add_post_migrate_path_to_rails(force: false)
return if ENV['SKIP_POST_DEPLOYMENT_MIGRATIONS'] && !force
@@ -263,14 +242,28 @@ module Gitlab
# A patch over ActiveRecord::Base.transaction that provides
# observability into transactional methods.
def transaction(**options, &block)
- if options[:requires_new] && connection.transaction_open?
- ::Gitlab::Database::Metrics.subtransactions_increment(self.name)
- end
+ transaction_type = get_transaction_type(connection.transaction_open?, options[:requires_new])
+
+ ::Gitlab::Database::Metrics.subtransactions_increment(self.name) if transaction_type == :sub_transaction
+
+ payload = { connection: connection, transaction_type: transaction_type }
- ActiveSupport::Notifications.instrument('transaction.active_record', { connection: connection }) do
+ ActiveSupport::Notifications.instrument('transaction.active_record', payload) do
super(**options, &block)
end
end
+
+ private
+
+ def get_transaction_type(transaction_open, requires_new_flag)
+ if transaction_open
+ return :sub_transaction if requires_new_flag
+
+ return :fake_transaction
+ end
+
+ :real_transaction
+ end
end
end
diff --git a/lib/gitlab/database/as_with_materialized.rb b/lib/gitlab/database/as_with_materialized.rb
index 07809c5b592..a04ea97117d 100644
--- a/lib/gitlab/database/as_with_materialized.rb
+++ b/lib/gitlab/database/as_with_materialized.rb
@@ -19,7 +19,7 @@ module Gitlab
# Note: to be deleted after the minimum PG version is set to 12.0
def self.materialized_supported?
strong_memoize(:materialized_supported) do
- Gitlab::Database.main.version.match?(/^1[2-9]\./) # version 12.x and above
+ ApplicationRecord.database.version.match?(/^1[2-9]\./) # version 12.x and above
end
end
diff --git a/lib/gitlab/database/async_indexes/index_creator.rb b/lib/gitlab/database/async_indexes/index_creator.rb
index 00de79ec970..994a1deba57 100644
--- a/lib/gitlab/database/async_indexes/index_creator.rb
+++ b/lib/gitlab/database/async_indexes/index_creator.rb
@@ -40,7 +40,7 @@ module Gitlab
end
def connection
- @connection ||= ApplicationRecord.connection
+ @connection ||= async_index.connection
end
def lease_timeout
diff --git a/lib/gitlab/database/async_indexes/postgres_async_index.rb b/lib/gitlab/database/async_indexes/postgres_async_index.rb
index 236459e6216..6cb40729061 100644
--- a/lib/gitlab/database/async_indexes/postgres_async_index.rb
+++ b/lib/gitlab/database/async_indexes/postgres_async_index.rb
@@ -3,7 +3,7 @@
module Gitlab
module Database
module AsyncIndexes
- class PostgresAsyncIndex < ApplicationRecord
+ class PostgresAsyncIndex < SharedModel
self.table_name = 'postgres_async_indexes'
MAX_IDENTIFIER_LENGTH = Gitlab::Database::MigrationHelpers::MAX_IDENTIFIER_NAME_LENGTH
diff --git a/lib/gitlab/database/background_migration_job.rb b/lib/gitlab/database/background_migration_job.rb
index 1121793917b..c046571a111 100644
--- a/lib/gitlab/database/background_migration_job.rb
+++ b/lib/gitlab/database/background_migration_job.rb
@@ -4,6 +4,7 @@ module Gitlab
module Database
class BackgroundMigrationJob < ActiveRecord::Base # rubocop:disable Rails/ApplicationRecord
include EachBatch
+ include BulkInsertSafe
self.table_name = :background_migration_jobs
diff --git a/lib/gitlab/database/batch_counter.rb b/lib/gitlab/database/batch_counter.rb
index 7efa5b46ecb..6c0ce9e481a 100644
--- a/lib/gitlab/database/batch_counter.rb
+++ b/lib/gitlab/database/batch_counter.rb
@@ -31,7 +31,7 @@ module Gitlab
end
def count(batch_size: nil, mode: :itself, start: nil, finish: nil)
- raise 'BatchCount can not be run inside a transaction' if @relation.connection.transaction_open?
+ raise 'BatchCount can not be run inside a transaction' if transaction_open?
check_mode!(mode)
@@ -87,6 +87,10 @@ module Gitlab
results
end
+ def transaction_open?
+ @relation.connection.transaction_open?
+ end
+
def merge_results(results, object)
return object unless results
diff --git a/lib/gitlab/database/connection.rb b/lib/gitlab/database/connection.rb
deleted file mode 100644
index cda6220ee6c..00000000000
--- a/lib/gitlab/database/connection.rb
+++ /dev/null
@@ -1,260 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Database
- # Configuration settings and methods for interacting with a PostgreSQL
- # database, with support for multiple databases.
- class Connection
- attr_reader :scope
-
- # Initializes a new `Database`.
- #
- # The `scope` argument must be an object (such as `ActiveRecord::Base`)
- # that supports retrieving connections and connection pools.
- def initialize(scope = ActiveRecord::Base)
- @config = nil
- @scope = scope
- @version = nil
- @open_transactions_baseline = 0
- end
-
- def config
- # The result of this method must not be cached, as other methods may use
- # it after making configuration changes and expect those changes to be
- # present. For example, `disable_prepared_statements` expects the
- # configuration settings to always be up to date.
- #
- # See the following for more information:
- #
- # - https://gitlab.com/gitlab-org/release/retrospectives/-/issues/39
- # - https://gitlab.com/gitlab-com/gl-infra/production/-/issues/5238
- scope.connection_db_config.configuration_hash.with_indifferent_access
- end
-
- def pool_size
- config[:pool] || Database.default_pool_size
- end
-
- def username
- config[:username] || ENV['USER']
- end
-
- def database_name
- config[:database]
- end
-
- def adapter_name
- config[:adapter]
- end
-
- def human_adapter_name
- if postgresql?
- 'PostgreSQL'
- else
- 'Unknown'
- end
- end
-
- def postgresql?
- adapter_name.casecmp('postgresql') == 0
- end
-
- def db_config_with_default_pool_size
- db_config_object = scope.connection_db_config
- config = db_config_object
- .configuration_hash
- .merge(pool: Database.default_pool_size)
-
- ActiveRecord::DatabaseConfigurations::HashConfig.new(
- db_config_object.env_name,
- db_config_object.name,
- config
- )
- end
-
- # Disables prepared statements for the current database connection.
- def disable_prepared_statements
- db_config_object = scope.connection_db_config
- config = db_config_object.configuration_hash.merge(prepared_statements: false)
-
- hash_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(
- db_config_object.env_name,
- db_config_object.name,
- config
- )
-
- scope.establish_connection(hash_config)
- end
-
- # Check whether the underlying database is in read-only mode
- def db_read_only?
- pg_is_in_recovery =
- scope
- .connection
- .execute('SELECT pg_is_in_recovery()')
- .first
- .fetch('pg_is_in_recovery')
-
- Gitlab::Utils.to_boolean(pg_is_in_recovery)
- end
-
- def db_read_write?
- !db_read_only?
- end
-
- def version
- @version ||= database_version.match(/\A(?:PostgreSQL |)([^\s]+).*\z/)[1]
- end
-
- def database_version
- connection.execute("SELECT VERSION()").first['version']
- end
-
- def postgresql_minimum_supported_version?
- version.to_f >= MINIMUM_POSTGRES_VERSION
- end
-
- # Bulk inserts a number of rows into a table, optionally returning their
- # IDs.
- #
- # table - The name of the table to insert the rows into.
- # rows - An Array of Hash instances, each mapping the columns to their
- # values.
- # return_ids - When set to true the return value will be an Array of IDs of
- # the inserted rows
- # disable_quote - A key or an Array of keys to exclude from quoting (You
- # become responsible for protection from SQL injection for
- # these keys!)
- # on_conflict - Defines an upsert. Values can be: :disabled (default) or
- # :do_nothing
- def bulk_insert(table, rows, return_ids: false, disable_quote: [], on_conflict: nil)
- return if rows.empty?
-
- keys = rows.first.keys
- columns = keys.map { |key| connection.quote_column_name(key) }
-
- disable_quote = Array(disable_quote).to_set
- tuples = rows.map do |row|
- keys.map do |k|
- disable_quote.include?(k) ? row[k] : connection.quote(row[k])
- end
- end
-
- sql = <<-EOF
- INSERT INTO #{table} (#{columns.join(', ')})
- VALUES #{tuples.map { |tuple| "(#{tuple.join(', ')})" }.join(', ')}
- EOF
-
- sql = "#{sql} ON CONFLICT DO NOTHING" if on_conflict == :do_nothing
-
- sql = "#{sql} RETURNING id" if return_ids
-
- result = connection.execute(sql)
-
- if return_ids
- result.values.map { |tuple| tuple[0].to_i }
- else
- []
- end
- end
-
- def cached_column_exists?(table_name, column_name)
- connection
- .schema_cache.columns_hash(table_name)
- .has_key?(column_name.to_s)
- end
-
- def cached_table_exists?(table_name)
- exists? && connection.schema_cache.data_source_exists?(table_name)
- end
-
- def exists?
- # We can't _just_ check if `connection` raises an error, as it will
- # point to a `ConnectionProxy`, and obtaining those doesn't involve any
- # database queries. So instead we obtain the database version, which is
- # cached after the first call.
- connection.schema_cache.database_version
- true
- rescue StandardError
- false
- end
-
- def system_id
- row = connection
- .execute('SELECT system_identifier FROM pg_control_system()')
- .first
-
- row['system_identifier']
- end
-
- def pg_wal_lsn_diff(location1, location2)
- lsn1 = connection.quote(location1)
- lsn2 = connection.quote(location2)
-
- query = <<-SQL.squish
- SELECT pg_wal_lsn_diff(#{lsn1}, #{lsn2})
- AS result
- SQL
-
- row = connection.select_all(query).first
- row['result'] if row
- end
-
- # @param [ActiveRecord::Connection] ar_connection
- # @return [String]
- def get_write_location(ar_connection)
- use_new_load_balancer_query = Gitlab::Utils
- .to_boolean(ENV['USE_NEW_LOAD_BALANCER_QUERY'], default: true)
-
- sql =
- if use_new_load_balancer_query
- <<~NEWSQL
- SELECT CASE
- WHEN pg_is_in_recovery() = true AND EXISTS (SELECT 1 FROM pg_stat_get_wal_senders())
- THEN pg_last_wal_replay_lsn()::text
- WHEN pg_is_in_recovery() = false
- THEN pg_current_wal_insert_lsn()::text
- ELSE NULL
- END AS location;
- NEWSQL
- else
- <<~SQL
- SELECT pg_current_wal_insert_lsn()::text AS location
- SQL
- end
-
- row = ar_connection.select_all(sql).first
- row['location'] if row
- end
-
- # inside_transaction? will return true if the caller is running within a
- # transaction. Handles special cases when running inside a test
- # environment, where tests may be wrapped in transactions
- def inside_transaction?
- base = Rails.env.test? ? @open_transactions_baseline : 0
-
- scope.connection.open_transactions > base
- end
-
- # These methods that access @open_transactions_baseline are not
- # thread-safe. These are fine though because we only call these in
- # RSpec's main thread. If we decide to run specs multi-threaded, we would
- # need to use something like ThreadGroup to keep track of this value
- def set_open_transactions_baseline
- @open_transactions_baseline = scope.connection.open_transactions
- end
-
- def reset_open_transactions_baseline
- @open_transactions_baseline = 0
- end
-
- private
-
- def connection
- scope.connection
- end
- end
- end
-end
-
-Gitlab::Database::Connection.prepend_mod_with('Gitlab::Database::Connection')
diff --git a/lib/gitlab/database/each_database.rb b/lib/gitlab/database/each_database.rb
new file mode 100644
index 00000000000..7c9e65e6691
--- /dev/null
+++ b/lib/gitlab/database/each_database.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module EachDatabase
+ class << self
+ def each_database_connection
+ Gitlab::Database.database_base_models.each_pair do |connection_name, model|
+ connection = model.connection
+
+ with_shared_connection(connection, connection_name) do
+ yield connection, connection_name
+ end
+ end
+ end
+
+ def each_model_connection(models)
+ models.each do |model|
+ connection_name = model.connection.pool.db_config.name
+
+ with_shared_connection(model.connection, connection_name) do
+ yield model, connection_name
+ end
+ end
+ end
+
+ private
+
+ def with_shared_connection(connection, connection_name)
+ Gitlab::Database::SharedModel.using_connection(connection) do
+ Gitlab::AppLogger.debug(message: 'Switched database connection', connection_name: connection_name)
+
+ yield
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/gitlab_schema.rb b/lib/gitlab/database/gitlab_schema.rb
new file mode 100644
index 00000000000..14807494a79
--- /dev/null
+++ b/lib/gitlab/database/gitlab_schema.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+# This module gathers information about table to schema mapping
+# to understand table affinity
+#
+# Each table / view needs to have assigned gitlab_schema. Names supported today:
+#
+# - gitlab_shared - defines a set of tables that are found on all databases (data accessed is dependent on connection)
+# - gitlab_main / gitlab_ci - defines a set of tables that can only exist on a given database
+#
+# Tables for the purpose of tests should be prefixed with `_test_my_table_name`
+
+module Gitlab
+ module Database
+ module GitlabSchema
+ # These tables are deleted/renamed, but still referenced by migrations.
+ # This is needed for now, but should be removed in the future
+ DELETED_TABLES = {
+ # main tables
+ 'alerts_service_data' => :gitlab_main,
+ 'analytics_devops_adoption_segment_selections' => :gitlab_main,
+ 'analytics_repository_file_commits' => :gitlab_main,
+ 'analytics_repository_file_edits' => :gitlab_main,
+ 'analytics_repository_files' => :gitlab_main,
+ 'audit_events_archived' => :gitlab_main,
+ 'backup_labels' => :gitlab_main,
+ 'clusters_applications_fluentd' => :gitlab_main,
+ 'forked_project_links' => :gitlab_main,
+ 'issue_milestones' => :gitlab_main,
+ 'merge_request_milestones' => :gitlab_main,
+ 'namespace_onboarding_actions' => :gitlab_main,
+ 'services' => :gitlab_main,
+ 'terraform_state_registry' => :gitlab_main,
+ 'tmp_fingerprint_sha256_migration' => :gitlab_main, # used by lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys.rb
+ 'web_hook_logs_archived' => :gitlab_main,
+ 'vulnerability_export_registry' => :gitlab_main,
+ 'vulnerability_finding_fingerprints' => :gitlab_main,
+ 'vulnerability_export_verification_status' => :gitlab_main,
+
+ # CI tables
+ 'ci_build_trace_sections' => :gitlab_ci,
+ 'ci_build_trace_section_names' => :gitlab_ci,
+ 'ci_daily_report_results' => :gitlab_ci,
+ 'ci_test_cases' => :gitlab_ci,
+ 'ci_test_case_failures' => :gitlab_ci,
+
+ # leftovers from early implementation of partitioning
+ 'audit_events_part_5fc467ac26' => :gitlab_main,
+ 'web_hook_logs_part_0c5294f417' => :gitlab_main
+ }.freeze
+
+ def self.table_schemas(tables)
+ tables.map { |table| table_schema(table) }.to_set
+ end
+
+ def self.table_schema(name)
+ schema_name, table_name = name.split('.', 2) # Strip schema name like: `public.`
+
+ # Most of names do not have schemas, ensure that this is table
+ unless table_name
+ table_name = schema_name
+ schema_name = nil
+ end
+
+ # strip partition number of a form `loose_foreign_keys_deleted_records_1`
+ table_name.gsub!(/_[0-9]+$/, '')
+
+ # Tables that are properly mapped
+ if gitlab_schema = tables_to_schema[table_name]
+ return gitlab_schema
+ end
+
+ # Tables that are deleted, but we still need to reference them
+ if gitlab_schema = DELETED_TABLES[table_name]
+ return gitlab_schema
+ end
+
+ # All tables from `information_schema.` are `:gitlab_shared`
+ return :gitlab_shared if schema_name == 'information_schema'
+
+ # All tables that start with `_test_` are shared and ignored
+ return :gitlab_shared if table_name.start_with?('_test_')
+
+ # All `pg_` tables are marked as `shared`
+ return :gitlab_shared if table_name.start_with?('pg_')
+
+ # When undefined it's best to return a unique name so that we don't incorrectly assume that 2 undefined schemas belong on the same database
+ :"undefined_#{table_name}"
+ end
+
+ def self.tables_to_schema
+ @tables_to_schema ||= YAML.load_file(Rails.root.join('lib/gitlab/database/gitlab_schemas.yml'))
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/gitlab_schemas.yml b/lib/gitlab/database/gitlab_schemas.yml
new file mode 100644
index 00000000000..66157e998a0
--- /dev/null
+++ b/lib/gitlab/database/gitlab_schemas.yml
@@ -0,0 +1,543 @@
+abuse_reports: :gitlab_main
+agent_group_authorizations: :gitlab_main
+agent_project_authorizations: :gitlab_main
+alert_management_alert_assignees: :gitlab_main
+alert_management_alerts: :gitlab_main
+alert_management_alert_user_mentions: :gitlab_main
+alert_management_http_integrations: :gitlab_main
+allowed_email_domains: :gitlab_main
+analytics_cycle_analytics_group_stages: :gitlab_main
+analytics_cycle_analytics_group_value_streams: :gitlab_main
+analytics_cycle_analytics_issue_stage_events: :gitlab_main
+analytics_cycle_analytics_merge_request_stage_events: :gitlab_main
+analytics_cycle_analytics_project_stages: :gitlab_main
+analytics_cycle_analytics_project_value_streams: :gitlab_main
+analytics_cycle_analytics_stage_event_hashes: :gitlab_main
+analytics_devops_adoption_segments: :gitlab_main
+analytics_devops_adoption_snapshots: :gitlab_main
+analytics_language_trend_repository_languages: :gitlab_main
+analytics_usage_trends_measurements: :gitlab_main
+appearances: :gitlab_main
+application_settings: :gitlab_main
+application_setting_terms: :gitlab_main
+approval_merge_request_rules_approved_approvers: :gitlab_main
+approval_merge_request_rules: :gitlab_main
+approval_merge_request_rules_groups: :gitlab_main
+approval_merge_request_rule_sources: :gitlab_main
+approval_merge_request_rules_users: :gitlab_main
+approval_project_rules: :gitlab_main
+approval_project_rules_groups: :gitlab_main
+approval_project_rules_protected_branches: :gitlab_main
+approval_project_rules_users: :gitlab_main
+approvals: :gitlab_main
+approver_groups: :gitlab_main
+approvers: :gitlab_main
+ar_internal_metadata: :gitlab_shared
+atlassian_identities: :gitlab_main
+audit_events_external_audit_event_destinations: :gitlab_main
+audit_events: :gitlab_main
+authentication_events: :gitlab_main
+award_emoji: :gitlab_main
+aws_roles: :gitlab_main
+background_migration_jobs: :gitlab_main
+badges: :gitlab_main
+banned_users: :gitlab_main
+batched_background_migration_jobs: :gitlab_main
+batched_background_migrations: :gitlab_main
+board_assignees: :gitlab_main
+board_group_recent_visits: :gitlab_main
+board_labels: :gitlab_main
+board_project_recent_visits: :gitlab_main
+boards_epic_board_labels: :gitlab_main
+boards_epic_board_positions: :gitlab_main
+boards_epic_board_recent_visits: :gitlab_main
+boards_epic_boards: :gitlab_main
+boards_epic_lists: :gitlab_main
+boards_epic_list_user_preferences: :gitlab_main
+boards_epic_user_preferences: :gitlab_main
+boards: :gitlab_main
+board_user_preferences: :gitlab_main
+broadcast_messages: :gitlab_main
+bulk_import_configurations: :gitlab_main
+bulk_import_entities: :gitlab_main
+bulk_import_exports: :gitlab_main
+bulk_import_export_uploads: :gitlab_main
+bulk_import_failures: :gitlab_main
+bulk_imports: :gitlab_main
+bulk_import_trackers: :gitlab_main
+chat_names: :gitlab_main
+chat_teams: :gitlab_main
+ci_build_needs: :gitlab_ci
+ci_build_pending_states: :gitlab_ci
+ci_build_report_results: :gitlab_ci
+ci_builds: :gitlab_ci
+ci_builds_metadata: :gitlab_ci
+ci_builds_runner_session: :gitlab_ci
+ci_build_trace_chunks: :gitlab_ci
+ci_build_trace_metadata: :gitlab_ci
+ci_daily_build_group_report_results: :gitlab_ci
+ci_deleted_objects: :gitlab_ci
+ci_freeze_periods: :gitlab_ci
+ci_group_variables: :gitlab_ci
+ci_instance_variables: :gitlab_ci
+ci_job_artifacts: :gitlab_ci
+ci_job_token_project_scope_links: :gitlab_ci
+ci_job_variables: :gitlab_ci
+ci_minutes_additional_packs: :gitlab_ci
+ci_namespace_monthly_usages: :gitlab_ci
+ci_pending_builds: :gitlab_ci
+ci_pipeline_artifacts: :gitlab_ci
+ci_pipeline_chat_data: :gitlab_ci
+ci_pipeline_messages: :gitlab_ci
+ci_pipeline_schedules: :gitlab_ci
+ci_pipeline_schedule_variables: :gitlab_ci
+ci_pipelines_config: :gitlab_ci
+ci_pipelines: :gitlab_ci
+ci_pipeline_variables: :gitlab_ci
+ci_platform_metrics: :gitlab_ci
+ci_project_monthly_usages: :gitlab_ci
+ci_refs: :gitlab_ci
+ci_resource_groups: :gitlab_ci
+ci_resources: :gitlab_ci
+ci_runner_namespaces: :gitlab_ci
+ci_runner_projects: :gitlab_ci
+ci_runners: :gitlab_ci
+ci_running_builds: :gitlab_ci
+ci_sources_pipelines: :gitlab_ci
+ci_sources_projects: :gitlab_ci
+ci_stages: :gitlab_ci
+ci_subscriptions_projects: :gitlab_ci
+ci_trigger_requests: :gitlab_ci
+ci_triggers: :gitlab_ci
+ci_unit_test_failures: :gitlab_ci
+ci_unit_tests: :gitlab_ci
+ci_variables: :gitlab_ci
+cluster_agents: :gitlab_main
+cluster_agent_tokens: :gitlab_main
+cluster_groups: :gitlab_main
+cluster_platforms_kubernetes: :gitlab_main
+cluster_projects: :gitlab_main
+cluster_providers_aws: :gitlab_main
+cluster_providers_gcp: :gitlab_main
+clusters_applications_cert_managers: :gitlab_main
+clusters_applications_cilium: :gitlab_main
+clusters_applications_crossplane: :gitlab_main
+clusters_applications_elastic_stacks: :gitlab_main
+clusters_applications_helm: :gitlab_main
+clusters_applications_ingress: :gitlab_main
+clusters_applications_jupyter: :gitlab_main
+clusters_applications_knative: :gitlab_main
+clusters_applications_prometheus: :gitlab_main
+clusters_applications_runners: :gitlab_main
+clusters: :gitlab_main
+clusters_integration_elasticstack: :gitlab_main
+clusters_integration_prometheus: :gitlab_main
+clusters_kubernetes_namespaces: :gitlab_main
+commit_user_mentions: :gitlab_main
+compliance_management_frameworks: :gitlab_main
+container_expiration_policies: :gitlab_main
+container_repositories: :gitlab_main
+content_blocked_states: :gitlab_main
+conversational_development_index_metrics: :gitlab_main
+coverage_fuzzing_corpuses: :gitlab_main
+csv_issue_imports: :gitlab_main
+custom_emoji: :gitlab_main
+customer_relations_contacts: :gitlab_main
+customer_relations_organizations: :gitlab_main
+dast_profile_schedules: :gitlab_main
+dast_profiles: :gitlab_main
+dast_profiles_pipelines: :gitlab_main
+dast_scanner_profiles_builds: :gitlab_main
+dast_scanner_profiles: :gitlab_main
+dast_site_profiles_builds: :gitlab_main
+dast_site_profile_secret_variables: :gitlab_main
+dast_site_profiles: :gitlab_main
+dast_site_profiles_pipelines: :gitlab_main
+dast_sites: :gitlab_main
+dast_site_tokens: :gitlab_main
+dast_site_validations: :gitlab_main
+dependency_proxy_blobs: :gitlab_main
+dependency_proxy_group_settings: :gitlab_main
+dependency_proxy_image_ttl_group_policies: :gitlab_main
+dependency_proxy_manifests: :gitlab_main
+deploy_keys_projects: :gitlab_main
+deployment_clusters: :gitlab_main
+deployment_merge_requests: :gitlab_main
+deployments: :gitlab_main
+deploy_tokens: :gitlab_main
+description_versions: :gitlab_main
+design_management_designs: :gitlab_main
+design_management_designs_versions: :gitlab_main
+design_management_versions: :gitlab_main
+design_user_mentions: :gitlab_main
+detached_partitions: :gitlab_shared
+diff_note_positions: :gitlab_main
+dora_daily_metrics: :gitlab_main
+draft_notes: :gitlab_main
+elastic_index_settings: :gitlab_main
+elastic_reindexing_slices: :gitlab_main
+elastic_reindexing_subtasks: :gitlab_main
+elastic_reindexing_tasks: :gitlab_main
+elasticsearch_indexed_namespaces: :gitlab_main
+elasticsearch_indexed_projects: :gitlab_main
+emails: :gitlab_main
+environments: :gitlab_main
+epic_issues: :gitlab_main
+epic_metrics: :gitlab_main
+epics: :gitlab_main
+epic_user_mentions: :gitlab_main
+error_tracking_client_keys: :gitlab_main
+error_tracking_error_events: :gitlab_main
+error_tracking_errors: :gitlab_main
+events: :gitlab_main
+evidences: :gitlab_main
+experiments: :gitlab_main
+experiment_subjects: :gitlab_main
+experiment_users: :gitlab_main
+external_approval_rules: :gitlab_main
+external_approval_rules_protected_branches: :gitlab_main
+external_pull_requests: :gitlab_main
+external_status_checks: :gitlab_main
+external_status_checks_protected_branches: :gitlab_main
+feature_gates: :gitlab_main
+features: :gitlab_main
+fork_network_members: :gitlab_main
+fork_networks: :gitlab_main
+geo_cache_invalidation_events: :gitlab_main
+geo_container_repository_updated_events: :gitlab_main
+geo_event_log: :gitlab_main
+geo_events: :gitlab_main
+geo_hashed_storage_attachments_events: :gitlab_main
+geo_hashed_storage_migrated_events: :gitlab_main
+geo_job_artifact_deleted_events: :gitlab_main
+geo_lfs_object_deleted_events: :gitlab_main
+geo_node_namespace_links: :gitlab_main
+geo_nodes: :gitlab_main
+geo_node_statuses: :gitlab_main
+geo_repositories_changed_events: :gitlab_main
+geo_repository_created_events: :gitlab_main
+geo_repository_deleted_events: :gitlab_main
+geo_repository_renamed_events: :gitlab_main
+geo_repository_updated_events: :gitlab_main
+geo_reset_checksum_events: :gitlab_main
+gitlab_subscription_histories: :gitlab_main
+gitlab_subscriptions: :gitlab_main
+gpg_keys: :gitlab_main
+gpg_key_subkeys: :gitlab_main
+gpg_signatures: :gitlab_main
+grafana_integrations: :gitlab_main
+group_custom_attributes: :gitlab_main
+group_deletion_schedules: :gitlab_main
+group_deploy_keys: :gitlab_main
+group_deploy_keys_groups: :gitlab_main
+group_deploy_tokens: :gitlab_main
+group_group_links: :gitlab_main
+group_import_states: :gitlab_main
+group_merge_request_approval_settings: :gitlab_main
+group_repository_storage_moves: :gitlab_main
+group_wiki_repositories: :gitlab_main
+historical_data: :gitlab_main
+identities: :gitlab_main
+import_export_uploads: :gitlab_main
+import_failures: :gitlab_main
+incident_management_escalation_policies: :gitlab_main
+incident_management_escalation_rules: :gitlab_main
+incident_management_issuable_escalation_statuses: :gitlab_main
+incident_management_oncall_participants: :gitlab_main
+incident_management_oncall_rotations: :gitlab_main
+incident_management_oncall_schedules: :gitlab_main
+incident_management_oncall_shifts: :gitlab_main
+incident_management_pending_alert_escalations: :gitlab_main
+incident_management_pending_issue_escalations: :gitlab_main
+index_statuses: :gitlab_main
+in_product_marketing_emails: :gitlab_main
+insights: :gitlab_main
+integrations: :gitlab_main
+internal_ids: :gitlab_main
+ip_restrictions: :gitlab_main
+issuable_metric_images: :gitlab_main
+issuable_severities: :gitlab_main
+issuable_slas: :gitlab_main
+issue_assignees: :gitlab_main
+issue_customer_relations_contacts: :gitlab_main
+issue_email_participants: :gitlab_main
+issue_links: :gitlab_main
+issue_metrics: :gitlab_main
+issues: :gitlab_main
+issues_prometheus_alert_events: :gitlab_main
+issues_self_managed_prometheus_alert_events: :gitlab_main
+issue_tracker_data: :gitlab_main
+issue_user_mentions: :gitlab_main
+iterations_cadences: :gitlab_main
+jira_connect_installations: :gitlab_main
+jira_connect_subscriptions: :gitlab_main
+jira_imports: :gitlab_main
+jira_tracker_data: :gitlab_main
+keys: :gitlab_main
+label_links: :gitlab_main
+label_priorities: :gitlab_main
+labels: :gitlab_main
+ldap_group_links: :gitlab_main
+lfs_file_locks: :gitlab_main
+lfs_objects: :gitlab_main
+lfs_objects_projects: :gitlab_main
+licenses: :gitlab_main
+lists: :gitlab_main
+list_user_preferences: :gitlab_main
+loose_foreign_keys_deleted_records: :gitlab_shared
+member_tasks: :gitlab_main
+members: :gitlab_main
+merge_request_assignees: :gitlab_main
+merge_request_blocks: :gitlab_main
+merge_request_cleanup_schedules: :gitlab_main
+merge_request_context_commit_diff_files: :gitlab_main
+merge_request_context_commits: :gitlab_main
+merge_request_diff_commits: :gitlab_main
+merge_request_diff_commit_users: :gitlab_main
+merge_request_diff_details: :gitlab_main
+merge_request_diff_files: :gitlab_main
+merge_request_diffs: :gitlab_main
+merge_request_metrics: :gitlab_main
+merge_request_reviewers: :gitlab_main
+merge_requests_closing_issues: :gitlab_main
+merge_requests: :gitlab_main
+merge_request_user_mentions: :gitlab_main
+merge_trains: :gitlab_main
+metrics_dashboard_annotations: :gitlab_main
+metrics_users_starred_dashboards: :gitlab_main
+milestone_releases: :gitlab_main
+milestones: :gitlab_main
+namespace_admin_notes: :gitlab_main
+namespace_aggregation_schedules: :gitlab_main
+namespace_limits: :gitlab_main
+namespace_package_settings: :gitlab_main
+namespace_root_storage_statistics: :gitlab_main
+namespace_settings: :gitlab_main
+namespaces: :gitlab_main
+namespace_statistics: :gitlab_main
+note_diff_files: :gitlab_main
+notes: :gitlab_main
+notification_settings: :gitlab_main
+oauth_access_grants: :gitlab_main
+oauth_access_tokens: :gitlab_main
+oauth_applications: :gitlab_main
+oauth_openid_requests: :gitlab_main
+onboarding_progresses: :gitlab_main
+operations_feature_flags_clients: :gitlab_main
+operations_feature_flag_scopes: :gitlab_main
+operations_feature_flags: :gitlab_main
+operations_feature_flags_issues: :gitlab_main
+operations_scopes: :gitlab_main
+operations_strategies: :gitlab_main
+operations_strategies_user_lists: :gitlab_main
+operations_user_lists: :gitlab_main
+packages_build_infos: :gitlab_main
+packages_composer_cache_files: :gitlab_main
+packages_composer_metadata: :gitlab_main
+packages_conan_file_metadata: :gitlab_main
+packages_conan_metadata: :gitlab_main
+packages_debian_file_metadata: :gitlab_main
+packages_debian_group_architectures: :gitlab_main
+packages_debian_group_component_files: :gitlab_main
+packages_debian_group_components: :gitlab_main
+packages_debian_group_distribution_keys: :gitlab_main
+packages_debian_group_distributions: :gitlab_main
+packages_debian_project_architectures: :gitlab_main
+packages_debian_project_component_files: :gitlab_main
+packages_debian_project_components: :gitlab_main
+packages_debian_project_distribution_keys: :gitlab_main
+packages_debian_project_distributions: :gitlab_main
+packages_debian_publications: :gitlab_main
+packages_dependencies: :gitlab_main
+packages_dependency_links: :gitlab_main
+packages_events: :gitlab_main
+packages_helm_file_metadata: :gitlab_main
+packages_maven_metadata: :gitlab_main
+packages_npm_metadata: :gitlab_main
+packages_nuget_dependency_link_metadata: :gitlab_main
+packages_nuget_metadata: :gitlab_main
+packages_package_file_build_infos: :gitlab_main
+packages_package_files: :gitlab_main
+packages_packages: :gitlab_main
+packages_pypi_metadata: :gitlab_main
+packages_rubygems_metadata: :gitlab_main
+packages_tags: :gitlab_main
+pages_deployments: :gitlab_main
+pages_domain_acme_orders: :gitlab_main
+pages_domains: :gitlab_main
+partitioned_foreign_keys: :gitlab_main
+path_locks: :gitlab_main
+personal_access_tokens: :gitlab_main
+plan_limits: :gitlab_main
+plans: :gitlab_main
+pool_repositories: :gitlab_main
+postgres_async_indexes: :gitlab_shared
+postgres_foreign_keys: :gitlab_shared
+postgres_index_bloat_estimates: :gitlab_shared
+postgres_indexes: :gitlab_shared
+postgres_partitioned_tables: :gitlab_shared
+postgres_partitions: :gitlab_shared
+postgres_reindex_actions: :gitlab_shared
+postgres_reindex_queued_actions: :gitlab_main
+product_analytics_events_experimental: :gitlab_main
+programming_languages: :gitlab_main
+project_access_tokens: :gitlab_main
+project_alerting_settings: :gitlab_main
+project_aliases: :gitlab_main
+project_authorizations: :gitlab_main
+project_auto_devops: :gitlab_main
+project_ci_cd_settings: :gitlab_main
+project_ci_feature_usages: :gitlab_main
+project_compliance_framework_settings: :gitlab_main
+project_custom_attributes: :gitlab_main
+project_daily_statistics: :gitlab_main
+project_deploy_tokens: :gitlab_main
+project_error_tracking_settings: :gitlab_main
+project_export_jobs: :gitlab_main
+project_features: :gitlab_main
+project_feature_usages: :gitlab_main
+project_group_links: :gitlab_main
+project_import_data: :gitlab_main
+project_incident_management_settings: :gitlab_main
+project_metrics_settings: :gitlab_main
+project_mirror_data: :gitlab_main
+project_pages_metadata: :gitlab_main
+project_repositories: :gitlab_main
+project_repository_states: :gitlab_main
+project_repository_storage_moves: :gitlab_main
+project_security_settings: :gitlab_main
+project_settings: :gitlab_main
+projects: :gitlab_main
+project_statistics: :gitlab_main
+project_topics: :gitlab_main
+project_tracing_settings: :gitlab_main
+prometheus_alert_events: :gitlab_main
+prometheus_alerts: :gitlab_main
+prometheus_metrics: :gitlab_main
+protected_branches: :gitlab_main
+protected_branch_merge_access_levels: :gitlab_main
+protected_branch_push_access_levels: :gitlab_main
+protected_branch_unprotect_access_levels: :gitlab_main
+protected_environment_deploy_access_levels: :gitlab_main
+protected_environments: :gitlab_main
+protected_tag_create_access_levels: :gitlab_main
+protected_tags: :gitlab_main
+push_event_payloads: :gitlab_main
+push_rules: :gitlab_main
+raw_usage_data: :gitlab_main
+redirect_routes: :gitlab_main
+release_links: :gitlab_main
+releases: :gitlab_main
+remote_mirrors: :gitlab_main
+repository_languages: :gitlab_main
+required_code_owners_sections: :gitlab_main
+requirements: :gitlab_main
+requirements_management_test_reports: :gitlab_main
+resource_iteration_events: :gitlab_main
+resource_label_events: :gitlab_main
+resource_milestone_events: :gitlab_main
+resource_state_events: :gitlab_main
+resource_weight_events: :gitlab_main
+reviews: :gitlab_main
+routes: :gitlab_main
+saml_group_links: :gitlab_main
+saml_providers: :gitlab_main
+schema_migrations: :gitlab_shared
+scim_identities: :gitlab_main
+scim_oauth_access_tokens: :gitlab_main
+security_findings: :gitlab_main
+security_orchestration_policy_configurations: :gitlab_main
+security_orchestration_policy_rule_schedules: :gitlab_main
+security_scans: :gitlab_main
+self_managed_prometheus_alert_events: :gitlab_main
+sent_notifications: :gitlab_main
+sentry_issues: :gitlab_main
+serverless_domain_cluster: :gitlab_main
+service_desk_settings: :gitlab_main
+shards: :gitlab_main
+slack_integrations: :gitlab_main
+smartcard_identities: :gitlab_main
+snippet_repositories: :gitlab_main
+snippet_repository_storage_moves: :gitlab_main
+snippets: :gitlab_main
+snippet_statistics: :gitlab_main
+snippet_user_mentions: :gitlab_main
+software_license_policies: :gitlab_main
+software_licenses: :gitlab_main
+spam_logs: :gitlab_main
+sprints: :gitlab_main
+status_check_responses: :gitlab_main
+status_page_published_incidents: :gitlab_main
+status_page_settings: :gitlab_main
+subscriptions: :gitlab_main
+suggestions: :gitlab_main
+system_note_metadata: :gitlab_main
+taggings: :gitlab_ci
+tags: :gitlab_ci
+term_agreements: :gitlab_main
+terraform_states: :gitlab_main
+terraform_state_versions: :gitlab_main
+timelogs: :gitlab_main
+todos: :gitlab_main
+token_with_ivs: :gitlab_main
+topics: :gitlab_main
+trending_projects: :gitlab_main
+u2f_registrations: :gitlab_main
+upcoming_reconciliations: :gitlab_main
+uploads: :gitlab_main
+user_agent_details: :gitlab_main
+user_callouts: :gitlab_main
+user_canonical_emails: :gitlab_main
+user_credit_card_validations: :gitlab_main
+user_custom_attributes: :gitlab_main
+user_details: :gitlab_main
+user_follow_users: :gitlab_main
+user_group_callouts: :gitlab_main
+user_highest_roles: :gitlab_main
+user_interacted_projects: :gitlab_main
+user_permission_export_uploads: :gitlab_main
+user_preferences: :gitlab_main
+users: :gitlab_main
+users_ops_dashboard_projects: :gitlab_main
+users_security_dashboard_projects: :gitlab_main
+users_star_projects: :gitlab_main
+users_statistics: :gitlab_main
+user_statuses: :gitlab_main
+user_synced_attributes_metadata: :gitlab_main
+verification_codes: :gitlab_main
+vulnerabilities: :gitlab_main
+vulnerability_exports: :gitlab_main
+vulnerability_external_issue_links: :gitlab_main
+vulnerability_feedback: :gitlab_main
+vulnerability_finding_evidence_assets: :gitlab_main
+vulnerability_finding_evidence_headers: :gitlab_main
+vulnerability_finding_evidence_requests: :gitlab_main
+vulnerability_finding_evidence_responses: :gitlab_main
+vulnerability_finding_evidences: :gitlab_main
+vulnerability_finding_evidence_sources: :gitlab_main
+vulnerability_finding_evidence_supporting_messages: :gitlab_main
+vulnerability_finding_links: :gitlab_main
+vulnerability_finding_signatures: :gitlab_main
+vulnerability_findings_remediations: :gitlab_main
+vulnerability_flags: :gitlab_main
+vulnerability_historical_statistics: :gitlab_main
+vulnerability_identifiers: :gitlab_main
+vulnerability_issue_links: :gitlab_main
+vulnerability_occurrence_identifiers: :gitlab_main
+vulnerability_occurrence_pipelines: :gitlab_main
+vulnerability_occurrences: :gitlab_main
+vulnerability_remediations: :gitlab_main
+vulnerability_scanners: :gitlab_main
+vulnerability_statistics: :gitlab_main
+vulnerability_user_mentions: :gitlab_main
+webauthn_registrations: :gitlab_main
+web_hook_logs: :gitlab_main
+web_hooks: :gitlab_main
+wiki_page_meta: :gitlab_main
+wiki_page_slugs: :gitlab_main
+work_item_types: :gitlab_main
+x509_certificates: :gitlab_main
+x509_commit_signatures: :gitlab_main
+x509_issuers: :gitlab_main
+zentao_tracker_data: :gitlab_main
+zoom_meetings: :gitlab_main
diff --git a/lib/gitlab/database/load_balancing.rb b/lib/gitlab/database/load_balancing.rb
index 3e322e752b7..52eb0764ae3 100644
--- a/lib/gitlab/database/load_balancing.rb
+++ b/lib/gitlab/database/load_balancing.rb
@@ -26,7 +26,7 @@ module Gitlab
return to_enum(__method__) unless block_given?
base_models.each do |model|
- yield model.connection.load_balancer
+ yield model.load_balancer
end
end
diff --git a/lib/gitlab/database/load_balancing/configuration.rb b/lib/gitlab/database/load_balancing/configuration.rb
index 6156515bd73..da313361073 100644
--- a/lib/gitlab/database/load_balancing/configuration.rb
+++ b/lib/gitlab/database/load_balancing/configuration.rb
@@ -7,7 +7,7 @@ module Gitlab
class Configuration
attr_accessor :hosts, :max_replication_difference,
:max_replication_lag_time, :replica_check_interval,
- :service_discovery, :model
+ :service_discovery
# Creates a configuration object for the given ActiveRecord model.
def self.for_model(model)
@@ -41,6 +41,8 @@ module Gitlab
end
end
+ config.reuse_primary_connection!
+
config
end
@@ -59,6 +61,28 @@ module Gitlab
disconnect_timeout: 120,
use_tcp: false
}
+
+ # Temporary model for GITLAB_LOAD_BALANCING_REUSE_PRIMARY_
+ # To be removed with FF
+ @primary_model = nil
+ end
+
+ def db_config_name
+ @model.connection_db_config.name.to_sym
+ end
+
+ # With connection re-use the primary connection can be overwritten
+ # to be used from different model
+ def primary_connection_specification_name
+ (@primary_model || @model).connection_specification_name
+ end
+
+ def primary_db_config
+ (@primary_model || @model).connection_db_config
+ end
+
+ def replica_db_config
+ @model.connection_db_config
end
def pool_size
@@ -86,6 +110,30 @@ module Gitlab
def service_discovery_enabled?
service_discovery[:record].present?
end
+
+ # TODO: This is temporary code to allow re-use of primary connection
+ # if the two connections are pointing to the same host. This is needed
+ # to properly support transaction visibility.
+ #
+ # This behavior is required to support [Phase 3](https://gitlab.com/groups/gitlab-org/-/epics/6160#progress).
+ # This method is meant to be removed as soon as it is finished.
+ #
+ # The remapping is done as-is:
+ # export GITLAB_LOAD_BALANCING_REUSE_PRIMARY_<name-of-connection>=<new-name-of-connection>
+ #
+ # Ex.:
+ # export GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci=main
+ #
+ def reuse_primary_connection!
+ new_connection = ENV["GITLAB_LOAD_BALANCING_REUSE_PRIMARY_#{db_config_name}"]
+ return unless new_connection.present?
+
+ @primary_model = Gitlab::Database.database_base_models[new_connection.to_sym]
+
+ unless @primary_model
+ raise "Invalid value for 'GITLAB_LOAD_BALANCING_REUSE_PRIMARY_#{db_config_name}=#{new_connection}'"
+ end
+ end
end
end
end
diff --git a/lib/gitlab/database/load_balancing/connection_proxy.rb b/lib/gitlab/database/load_balancing/connection_proxy.rb
index 1be63da8896..a91df2eccdd 100644
--- a/lib/gitlab/database/load_balancing/connection_proxy.rb
+++ b/lib/gitlab/database/load_balancing/connection_proxy.rb
@@ -13,6 +13,13 @@ module Gitlab
WriteInsideReadOnlyTransactionError = Class.new(StandardError)
READ_ONLY_TRANSACTION_KEY = :load_balacing_read_only_transaction
+ # The load balancer returned by connection might be different
+ # between `model.connection.load_balancer` vs `model.load_balancer`
+ #
+ # The used `model.connection` is dependent on `use_model_load_balancing`.
+ # See more in: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73949.
+ #
+ # Always use `model.load_balancer` or `model.sticking`.
attr_reader :load_balancer
# These methods perform writes after which we need to stick to the
diff --git a/lib/gitlab/database/load_balancing/load_balancer.rb b/lib/gitlab/database/load_balancing/load_balancer.rb
index 2be7f0baa60..1e27bcfc55d 100644
--- a/lib/gitlab/database/load_balancing/load_balancer.rb
+++ b/lib/gitlab/database/load_balancing/load_balancer.rb
@@ -12,7 +12,7 @@ module Gitlab
REPLICA_SUFFIX = '_replica'
- attr_reader :name, :host_list, :configuration
+ attr_reader :host_list, :configuration
# configuration - An instance of `LoadBalancing::Configuration` that
# contains the configuration details (such as the hosts)
@@ -26,8 +26,10 @@ module Gitlab
else
HostList.new(configuration.hosts.map { |addr| Host.new(addr, self) })
end
+ end
- @name = @configuration.model.connection_db_config.name.to_sym
+ def name
+ @configuration.db_config_name
end
def primary_only?
@@ -64,7 +66,7 @@ module Gitlab
# times before using the primary instead.
will_retry = conflict_retried < @host_list.length * 3
- LoadBalancing::Logger.warn(
+ ::Gitlab::Database::LoadBalancing::Logger.warn(
event: :host_query_conflict,
message: 'Query conflict on host',
conflict_retried: conflict_retried,
@@ -89,7 +91,7 @@ module Gitlab
end
end
- LoadBalancing::Logger.warn(
+ ::Gitlab::Database::LoadBalancing::Logger.warn(
event: :no_secondaries_available,
message: 'No secondaries were available, using primary instead',
conflict_retried: conflict_retried,
@@ -136,7 +138,7 @@ module Gitlab
# Returns the transaction write location of the primary.
def primary_write_location
location = read_write do |connection|
- ::Gitlab::Database.main.get_write_location(connection)
+ get_write_location(connection)
end
return location if location
@@ -230,7 +232,7 @@ module Gitlab
# host - An optional host name to use instead of the default one.
# port - An optional port to connect to.
def create_replica_connection_pool(pool_size, host = nil, port = nil)
- db_config = pool.db_config
+ db_config = @configuration.replica_db_config
env_config = db_config.configuration_hash.dup
env_config[:pool] = pool_size
@@ -255,22 +257,67 @@ module Gitlab
# leverage that.
def pool
ActiveRecord::Base.connection_handler.retrieve_connection_pool(
- @configuration.model.connection_specification_name,
+ @configuration.primary_connection_specification_name,
role: ActiveRecord::Base.writing_role,
shard: ActiveRecord::Base.default_shard
) || raise(::ActiveRecord::ConnectionNotEstablished)
end
+ def wal_diff(location1, location2)
+ read_write do |connection|
+ lsn1 = connection.quote(location1)
+ lsn2 = connection.quote(location2)
+
+ query = <<-SQL.squish
+ SELECT pg_wal_lsn_diff(#{lsn1}, #{lsn2})
+ AS result
+ SQL
+
+ row = connection.select_all(query).first
+ row['result'] if row
+ end
+ end
+
private
def ensure_caching!
- host.enable_query_cache! unless host.query_cache_enabled
+ return unless Rails.application.executor.active?
+ return if host.query_cache_enabled
+
+ host.enable_query_cache!
end
def request_cache
base = SafeRequestStore[:gitlab_load_balancer] ||= {}
base[self] ||= {}
end
+
+ # @param [ActiveRecord::Connection] ar_connection
+ # @return [String]
+ def get_write_location(ar_connection)
+ use_new_load_balancer_query = Gitlab::Utils
+ .to_boolean(ENV['USE_NEW_LOAD_BALANCER_QUERY'], default: true)
+
+ sql =
+ if use_new_load_balancer_query
+ <<~NEWSQL
+ SELECT CASE
+ WHEN pg_is_in_recovery() = true AND EXISTS (SELECT 1 FROM pg_stat_get_wal_senders())
+ THEN pg_last_wal_replay_lsn()::text
+ WHEN pg_is_in_recovery() = false
+ THEN pg_current_wal_insert_lsn()::text
+ ELSE NULL
+ END AS location;
+ NEWSQL
+ else
+ <<~SQL
+ SELECT pg_current_wal_insert_lsn()::text AS location
+ SQL
+ end
+
+ row = ar_connection.select_all(sql).first
+ row['location'] if row
+ end
end
end
end
diff --git a/lib/gitlab/database/load_balancing/primary_host.rb b/lib/gitlab/database/load_balancing/primary_host.rb
index 7070cc54d4b..fb52b384ddb 100644
--- a/lib/gitlab/database/load_balancing/primary_host.rb
+++ b/lib/gitlab/database/load_balancing/primary_host.rb
@@ -49,6 +49,11 @@ module Gitlab
end
def offline!
+ ::Gitlab::Database::LoadBalancing::Logger.warn(
+ event: :host_offline,
+ message: 'Marking primary host as offline'
+ )
+
nil
end
diff --git a/lib/gitlab/database/load_balancing/rack_middleware.rb b/lib/gitlab/database/load_balancing/rack_middleware.rb
index 7ce7649cc22..99b1c31b04b 100644
--- a/lib/gitlab/database/load_balancing/rack_middleware.rb
+++ b/lib/gitlab/database/load_balancing/rack_middleware.rb
@@ -38,8 +38,8 @@ module Gitlab
def unstick_or_continue_sticking(env)
namespaces_and_ids = sticking_namespaces(env)
- namespaces_and_ids.each do |(model, namespace, id)|
- model.sticking.unstick_or_continue_sticking(namespace, id)
+ namespaces_and_ids.each do |(sticking, namespace, id)|
+ sticking.unstick_or_continue_sticking(namespace, id)
end
end
@@ -47,8 +47,8 @@ module Gitlab
def stick_if_necessary(env)
namespaces_and_ids = sticking_namespaces(env)
- namespaces_and_ids.each do |model, namespace, id|
- model.sticking.stick_if_necessary(namespace, id)
+ namespaces_and_ids.each do |sticking, namespace, id|
+ sticking.stick_if_necessary(namespace, id)
end
end
@@ -74,7 +74,7 @@ module Gitlab
# models that support load balancing. In the future (if we
# determined this to be OK) we may be able to relax this.
::Gitlab::Database::LoadBalancing.base_models.map do |model|
- [model, :user, warden.user.id]
+ [model.sticking, :user, warden.user.id]
end
elsif env[STICK_OBJECT].present?
env[STICK_OBJECT].to_a
diff --git a/lib/gitlab/database/load_balancing/setup.rb b/lib/gitlab/database/load_balancing/setup.rb
index 3cce839a960..ef38f42f50b 100644
--- a/lib/gitlab/database/load_balancing/setup.rb
+++ b/lib/gitlab/database/load_balancing/setup.rb
@@ -5,7 +5,7 @@ module Gitlab
module LoadBalancing
# Class for setting up load balancing of a specific model.
class Setup
- attr_reader :configuration
+ attr_reader :model, :configuration
def initialize(model, start_service_discovery: false)
@model = model
@@ -14,47 +14,102 @@ module Gitlab
end
def setup
- disable_prepared_statements
- setup_load_balancer
+ configure_connection
+ setup_connection_proxy
setup_service_discovery
+ setup_feature_flag_to_model_load_balancing
end
- def disable_prepared_statements
+ def configure_connection
db_config_object = @model.connection_db_config
- config =
- db_config_object.configuration_hash.merge(prepared_statements: false)
+
+ hash = db_config_object.configuration_hash.merge(
+ prepared_statements: false,
+ pool: Gitlab::Database.default_pool_size
+ )
hash_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(
db_config_object.env_name,
db_config_object.name,
- config
+ hash
)
@model.establish_connection(hash_config)
end
- def setup_load_balancer
- lb = LoadBalancer.new(configuration)
-
+ def setup_connection_proxy
# We just use a simple `class_attribute` here so we don't need to
# inject any modules and/or expose unnecessary methods.
- @model.class_attribute(:connection)
- @model.class_attribute(:sticking)
+ setup_class_attribute(:load_balancer, load_balancer)
+ setup_class_attribute(:connection, ConnectionProxy.new(load_balancer))
+ setup_class_attribute(:sticking, Sticking.new(load_balancer))
+ end
+
+ # TODO: This is temporary code to gradually redirect traffic to use
+ # a dedicated DB replicas, or DB primaries (depending on configuration)
+ # This implements a sticky behavior for the current request if enabled.
+ #
+ # This is needed for Phase 3 and Phase 4 of application rollout
+ # https://gitlab.com/groups/gitlab-org/-/epics/6160#progress
+ #
+ # If `GITLAB_USE_MODEL_LOAD_BALANCING` is set, its value is preferred
+ # Otherwise, a `use_model_load_balancing` FF value is used
+ def setup_feature_flag_to_model_load_balancing
+ return if active_record_base?
- @model.connection = ConnectionProxy.new(lb)
- @model.sticking = Sticking.new(lb)
+ @model.singleton_class.prepend(ModelLoadBalancingFeatureFlagMixin)
end
def setup_service_discovery
return unless configuration.service_discovery_enabled?
- lb = @model.connection.load_balancer
- sv = ServiceDiscovery.new(lb, **configuration.service_discovery)
+ sv = ServiceDiscovery.new(load_balancer, **configuration.service_discovery)
sv.perform_service_discovery
sv.start if @start_service_discovery
end
+
+ def load_balancer
+ @load_balancer ||= LoadBalancer.new(configuration)
+ end
+
+ private
+
+ def setup_class_attribute(attribute, value)
+ @model.class_attribute(attribute)
+ @model.public_send("#{attribute}=", value) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def active_record_base?
+ @model == ActiveRecord::Base
+ end
+
+ module ModelLoadBalancingFeatureFlagMixin
+ extend ActiveSupport::Concern
+
+ def use_model_load_balancing?
+ # Cache environment variable and return env variable first if defined
+ use_model_load_balancing_env = Gitlab::Utils.to_boolean(ENV["GITLAB_USE_MODEL_LOAD_BALANCING"])
+
+ unless use_model_load_balancing_env.nil?
+ return use_model_load_balancing_env
+ end
+
+ # Check a feature flag using RequestStore (if active)
+ return false unless Gitlab::SafeRequestStore.active?
+
+ Gitlab::SafeRequestStore.fetch(:use_model_load_balancing) do
+ Feature.enabled?(:use_model_load_balancing, default_enabled: :yaml)
+ end
+ end
+
+ # rubocop:disable Database/MultipleDatabases
+ def connection
+ use_model_load_balancing? ? super : ActiveRecord::Base.connection
+ end
+ # rubocop:enable Database/MultipleDatabases
+ end
end
end
end
diff --git a/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb b/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb
index f0c7016032b..b9acc36b4cc 100644
--- a/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb
+++ b/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb
@@ -13,7 +13,7 @@ module Gitlab
job['load_balancing_strategy'] = strategy.to_s
if use_primary?(strategy)
- Session.current.use_primary!
+ ::Gitlab::Database::LoadBalancing::Session.current.use_primary!
elsif strategy == :retry
raise JobReplicaNotUpToDate, "Sidekiq job #{worker_class} JID-#{job['jid']} couldn't use the replica."\
" Replica was not up to date."
@@ -29,8 +29,8 @@ module Gitlab
private
def clear
- LoadBalancing.release_hosts
- Session.clear_session
+ ::Gitlab::Database::LoadBalancing.release_hosts
+ ::Gitlab::Database::LoadBalancing::Session.clear_session
end
def use_primary?(strategy)
@@ -66,7 +66,7 @@ module Gitlab
def legacy_wal_location(job)
wal_location = job['database_write_location'] || job['database_replica_location']
- { Gitlab::Database::MAIN_DATABASE_NAME.to_sym => wal_location } if wal_location
+ { ::Gitlab::Database::MAIN_DATABASE_NAME.to_sym => wal_location } if wal_location
end
def load_balancing_available?(worker_class)
@@ -90,7 +90,7 @@ module Gitlab
end
def databases_in_sync?(wal_locations)
- LoadBalancing.each_load_balancer.all? do |lb|
+ ::Gitlab::Database::LoadBalancing.each_load_balancer.all? do |lb|
if (location = wal_locations[lb.name])
lb.select_up_to_date_host(location)
else
diff --git a/lib/gitlab/database/load_balancing/sticking.rb b/lib/gitlab/database/load_balancing/sticking.rb
index df4ad18581f..834e9c6d3c6 100644
--- a/lib/gitlab/database/load_balancing/sticking.rb
+++ b/lib/gitlab/database/load_balancing/sticking.rb
@@ -12,7 +12,6 @@ module Gitlab
def initialize(load_balancer)
@load_balancer = load_balancer
- @model = load_balancer.configuration.model
end
# Unsticks or continues sticking the current request.
@@ -27,8 +26,8 @@ module Gitlab
def stick_or_unstick_request(env, namespace, id)
unstick_or_continue_sticking(namespace, id)
- env[RackMiddleware::STICK_OBJECT] ||= Set.new
- env[RackMiddleware::STICK_OBJECT] << [@model, namespace, id]
+ env[::Gitlab::Database::LoadBalancing::RackMiddleware::STICK_OBJECT] ||= Set.new
+ env[::Gitlab::Database::LoadBalancing::RackMiddleware::STICK_OBJECT] << [self, namespace, id]
end
# Sticks to the primary if a write was performed.
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 9968096b1f6..7dce4fa0ce2 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -10,8 +10,6 @@ module Gitlab
# https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
MAX_IDENTIFIER_NAME_LENGTH = 63
-
- PERMITTED_TIMESTAMP_COLUMNS = %i[created_at updated_at deleted_at].to_set.freeze
DEFAULT_TIMESTAMP_COLUMNS = %i[created_at updated_at].freeze
# Adds `created_at` and `updated_at` columns with timezone information.
@@ -28,33 +26,23 @@ module Gitlab
# :default - The default value for the column.
# :null - When set to `true` the column will allow NULL values.
# The default is to not allow NULL values.
- # :columns - the column names to create. Must be one
- # of `Gitlab::Database::MigrationHelpers::PERMITTED_TIMESTAMP_COLUMNS`.
+ # :columns - the column names to create. Must end with `_at`.
# Default value: `DEFAULT_TIMESTAMP_COLUMNS`
#
# All options are optional.
def add_timestamps_with_timezone(table_name, options = {})
- options[:null] = false if options[:null].nil?
columns = options.fetch(:columns, DEFAULT_TIMESTAMP_COLUMNS)
- default_value = options[:default]
-
- validate_not_in_transaction!(:add_timestamps_with_timezone, 'with default value') if default_value
columns.each do |column_name|
validate_timestamp_column_name!(column_name)
- # If default value is presented, use `add_column_with_default` method instead.
- if default_value
- add_column_with_default(
- table_name,
- column_name,
- :datetime_with_timezone,
- default: default_value,
- allow_null: options[:null]
- )
- else
- add_column(table_name, column_name, :datetime_with_timezone, **options)
- end
+ add_column(
+ table_name,
+ column_name,
+ :datetime_with_timezone,
+ default: options[:default],
+ null: options[:null] || false
+ )
end
end
@@ -147,8 +135,18 @@ module Gitlab
options = options.merge({ algorithm: :concurrently })
if index_exists?(table_name, column_name, **options)
- Gitlab::AppLogger.warn "Index not created because it already exists (this may be due to an aborted migration or similar): table_name: #{table_name}, column_name: #{column_name}"
- return
+ name = options[:name] || index_name(table_name, column_name)
+ _, schema = table_name.to_s.split('.').reverse
+
+ if index_invalid?(name, schema: schema)
+ say "Index being recreated because the existing version was INVALID: table_name: #{table_name}, column_name: #{column_name}"
+
+ remove_concurrent_index_by_name(table_name, name)
+ else
+ say "Index not created because it already exists (this may be due to an aborted migration or similar): table_name: #{table_name}, column_name: #{column_name}"
+
+ return
+ end
end
disable_statement_timeout do
@@ -159,6 +157,23 @@ module Gitlab
unprepare_async_index(table_name, column_name, **options)
end
+ def index_invalid?(index_name, schema: nil)
+ index_name = connection.quote(index_name)
+ schema = connection.quote(schema) if schema
+ schema ||= 'current_schema()'
+
+ connection.select_value(<<~SQL)
+ select not i.indisvalid
+ from pg_class c
+ inner join pg_index i
+ on c.oid = i.indexrelid
+ inner join pg_namespace n
+ on n.oid = c.relnamespace
+ where n.nspname = #{schema}
+ and c.relname = #{index_name}
+ SQL
+ end
+
# Removes an existed index, concurrently
#
# Example:
@@ -1245,8 +1260,8 @@ module Gitlab
def check_trigger_permissions!(table)
unless Grant.create_and_execute_trigger?(table)
- dbname = Database.main.database_name
- user = Database.main.username
+ dbname = ApplicationRecord.database.database_name
+ user = ApplicationRecord.database.username
raise <<-EOF
Your database user is not allowed to create, drop, or execute triggers on the
@@ -1568,8 +1583,8 @@ into similar problems in the future (e.g. when new tables are created).
def create_extension(extension)
execute('CREATE EXTENSION IF NOT EXISTS %s' % extension)
rescue ActiveRecord::StatementInvalid => e
- dbname = Database.main.database_name
- user = Database.main.username
+ dbname = ApplicationRecord.database.database_name
+ user = ApplicationRecord.database.username
warn(<<~MSG) if e.to_s =~ /permission denied/
GitLab requires the PostgreSQL extension '#{extension}' installed in database '#{dbname}', but
@@ -1596,8 +1611,8 @@ into similar problems in the future (e.g. when new tables are created).
def drop_extension(extension)
execute('DROP EXTENSION IF EXISTS %s' % extension)
rescue ActiveRecord::StatementInvalid => e
- dbname = Database.main.database_name
- user = Database.main.username
+ dbname = ApplicationRecord.database.database_name
+ user = ApplicationRecord.database.username
warn(<<~MSG) if e.to_s =~ /permission denied/
This migration attempts to drop the PostgreSQL extension '#{extension}'
@@ -1791,11 +1806,11 @@ into similar problems in the future (e.g. when new tables are created).
end
def validate_timestamp_column_name!(column_name)
- return if PERMITTED_TIMESTAMP_COLUMNS.member?(column_name)
+ return if column_name.to_s.end_with?('_at')
raise <<~MESSAGE
Illegal timestamp column name! Got #{column_name}.
- Must be one of: #{PERMITTED_TIMESTAMP_COLUMNS.to_a}
+ Must end with `_at`}
MESSAGE
end
diff --git a/lib/gitlab/database/migration_helpers/cascading_namespace_settings.rb b/lib/gitlab/database/migration_helpers/cascading_namespace_settings.rb
index d9ef5ab462e..8a37e619285 100644
--- a/lib/gitlab/database/migration_helpers/cascading_namespace_settings.rb
+++ b/lib/gitlab/database/migration_helpers/cascading_namespace_settings.rb
@@ -31,10 +31,10 @@ module Gitlab
namespace_options = options.merge(null: true, default: nil)
- add_column(:namespace_settings, setting_name, type, namespace_options)
+ add_column(:namespace_settings, setting_name, type, **namespace_options)
add_column(:namespace_settings, lock_column_name, :boolean, default: false, null: false)
- add_column(:application_settings, setting_name, type, options)
+ add_column(:application_settings, setting_name, type, **options)
add_column(:application_settings, lock_column_name, :boolean, default: false, null: false)
end
diff --git a/lib/gitlab/database/migrations/observation.rb b/lib/gitlab/database/migrations/observation.rb
index 54eedec3c7b..a494c357950 100644
--- a/lib/gitlab/database/migrations/observation.rb
+++ b/lib/gitlab/database/migrations/observation.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
@@ -14,3 +15,5 @@ module Gitlab
end
end
end
+
+# rubocop:enable Naming/FileName
diff --git a/lib/gitlab/database/migrations/observers.rb b/lib/gitlab/database/migrations/observers.rb
index 140b3feed64..b890e62c2d0 100644
--- a/lib/gitlab/database/migrations/observers.rb
+++ b/lib/gitlab/database/migrations/observers.rb
@@ -9,7 +9,8 @@ module Gitlab
TotalDatabaseSizeChange,
QueryStatistics,
QueryLog,
- QueryDetails
+ QueryDetails,
+ TransactionDuration
]
end
end
diff --git a/lib/gitlab/database/migrations/observers/transaction_duration.rb b/lib/gitlab/database/migrations/observers/transaction_duration.rb
new file mode 100644
index 00000000000..a96b94334cf
--- /dev/null
+++ b/lib/gitlab/database/migrations/observers/transaction_duration.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Migrations
+ module Observers
+ class TransactionDuration < MigrationObserver
+ def before
+ file_path = File.join(output_dir, "#{observation.version}_#{observation.name}-transaction-duration.json")
+ @file = File.open(file_path, 'wb')
+ @writer = Oj::StreamWriter.new(@file, {})
+ @writer.push_array
+ @subscriber = ActiveSupport::Notifications.subscribe('transaction.active_record') do |*args|
+ record_sql_event(*args)
+ end
+ end
+
+ def after
+ ActiveSupport::Notifications.unsubscribe(@subscriber)
+ @writer.pop_all
+ @writer.flush
+ @file.close
+ end
+
+ def record
+ # no-op
+ end
+
+ def record_sql_event(_name, started, finished, _unique_id, payload)
+ return if payload[:transaction_type] == :fake_transaction
+
+ @writer.push_value({
+ start_time: started.iso8601(6),
+ end_time: finished.iso8601(6),
+ transaction_type: payload[:transaction_type]
+ })
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/partitioning.rb b/lib/gitlab/database/partitioning.rb
index 71fb995577a..1343354715a 100644
--- a/lib/gitlab/database/partitioning.rb
+++ b/lib/gitlab/database/partitioning.rb
@@ -3,20 +3,83 @@
module Gitlab
module Database
module Partitioning
- def self.register_models(models)
- registered_models.merge(models)
- end
+ class TableWithoutModel
+ include PartitionedTable::ClassMethods
- def self.registered_models
- @registered_models ||= Set.new
- end
+ attr_reader :table_name
+
+ def initialize(table_name:, partitioned_column:, strategy:)
+ @table_name = table_name
+ partitioned_by(partitioned_column, strategy: strategy)
+ end
- def self.sync_partitions(models_to_sync = registered_models)
- MultiDatabasePartitionManager.new(models_to_sync).sync_partitions
+ def connection
+ Gitlab::Database::SharedModel.connection
+ end
end
- def self.drop_detached_partitions
- MultiDatabasePartitionDropper.new.drop_detached_partitions
+ class << self
+ def register_models(models)
+ models.each do |model|
+ raise "#{model} should have partitioning strategy defined" unless model.respond_to?(:partitioning_strategy)
+
+ registered_models << model
+ end
+ end
+
+ def register_tables(tables)
+ registered_tables.merge(tables)
+ end
+
+ def sync_partitions_ignore_db_error
+ sync_partitions unless ENV['DISABLE_POSTGRES_PARTITION_CREATION_ON_STARTUP']
+ rescue ActiveRecord::ActiveRecordError, PG::Error
+ # ignore - happens when Rake tasks yet have to create a database, e.g. for testing
+ end
+
+ def sync_partitions(models_to_sync = registered_for_sync)
+ Gitlab::AppLogger.info(message: 'Syncing dynamic postgres partitions')
+
+ Gitlab::Database::EachDatabase.each_model_connection(models_to_sync) do |model|
+ PartitionManager.new(model).sync_partitions
+ end
+
+ Gitlab::AppLogger.info(message: 'Finished sync of dynamic postgres partitions')
+ end
+
+ def report_metrics(models_to_monitor = registered_models)
+ partition_monitoring = PartitionMonitoring.new
+
+ Gitlab::Database::EachDatabase.each_model_connection(models_to_monitor) do |model|
+ partition_monitoring.report_metrics_for_model(model)
+ end
+ end
+
+ def drop_detached_partitions
+ Gitlab::AppLogger.info(message: 'Dropping detached postgres partitions')
+
+ Gitlab::Database::EachDatabase.each_database_connection do
+ DetachedPartitionDropper.new.perform
+ end
+
+ Gitlab::AppLogger.info(message: 'Finished dropping detached postgres partitions')
+ end
+
+ def registered_models
+ @registered_models ||= Set.new
+ end
+
+ def registered_tables
+ @registered_tables ||= Set.new
+ end
+
+ private
+
+ def registered_for_sync
+ registered_models + registered_tables.map do |table|
+ TableWithoutModel.new(**table)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/database/partitioning/detached_partition_dropper.rb b/lib/gitlab/database/partitioning/detached_partition_dropper.rb
index 3e7ddece20b..593824384b5 100644
--- a/lib/gitlab/database/partitioning/detached_partition_dropper.rb
+++ b/lib/gitlab/database/partitioning/detached_partition_dropper.rb
@@ -9,13 +9,10 @@ module Gitlab
Gitlab::AppLogger.info(message: "Checking for previously detached partitions to drop")
Postgresql::DetachedPartition.ready_to_drop.find_each do |detached_partition|
- connection.transaction do
- # Another process may have already dropped the table and deleted this entry
- next unless (detached_partition = Postgresql::DetachedPartition.lock.find_by(id: detached_partition.id))
-
- drop_detached_partition(detached_partition.table_name)
-
- detached_partition.destroy!
+ if partition_attached?(qualify_partition_name(detached_partition.table_name))
+ unmark_partition(detached_partition)
+ else
+ drop_partition(detached_partition)
end
rescue StandardError => e
Gitlab::AppLogger.error(message: "Failed to drop previously detached partition",
@@ -27,31 +24,100 @@ module Gitlab
private
+ def unmark_partition(detached_partition)
+ connection.transaction do
+ # Another process may have already encountered this case and deleted this entry
+ next unless try_lock_detached_partition(detached_partition.id)
+
+ # The current partition was scheduled for deletion incorrectly
+ # Dropping it now could delete in-use data and take locks that interrupt other database activity
+ Gitlab::AppLogger.error(message: "Prevented an attempt to drop an attached database partition", partition_name: detached_partition.table_name)
+ detached_partition.destroy!
+ end
+ end
+
+ def drop_partition(detached_partition)
+ remove_foreign_keys(detached_partition)
+
+ connection.transaction do
+ # Another process may have already dropped the table and deleted this entry
+ next unless try_lock_detached_partition(detached_partition.id)
+
+ drop_detached_partition(detached_partition.table_name)
+
+ detached_partition.destroy!
+ end
+ end
+
+ def remove_foreign_keys(detached_partition)
+ partition_identifier = qualify_partition_name(detached_partition.table_name)
+
+ # We want to load all of these into memory at once to get a consistent view to loop over,
+ # since we'll be deleting from this list as we go
+ fks_to_drop = PostgresForeignKey.by_constrained_table_identifier(partition_identifier).to_a
+ fks_to_drop.each do |foreign_key|
+ drop_foreign_key_if_present(detached_partition, foreign_key)
+ end
+ end
+
+ # Drops the given foreign key for the given detached partition, but only if another process has not already
+ # detached the partition first. This method must be safe to call even if the associated partition table has already
+ # been detached, as it could be called by multiple processes at once.
+ def drop_foreign_key_if_present(detached_partition, foreign_key)
+ # It is important to only drop one foreign key per transaction.
+ # Dropping a foreign key takes an ACCESS EXCLUSIVE lock on both tables participating in the foreign key.
+
+ partition_identifier = qualify_partition_name(detached_partition.table_name)
+ with_lock_retries do
+ connection.transaction(requires_new: false) do
+ next unless try_lock_detached_partition(detached_partition.id)
+
+ # Another process may have already dropped this foreign key
+ next unless PostgresForeignKey.by_constrained_table_identifier(partition_identifier).where(name: foreign_key.name).exists?
+
+ connection.execute("ALTER TABLE #{connection.quote_table_name(partition_identifier)} DROP CONSTRAINT #{connection.quote_table_name(foreign_key.name)}")
+
+ Gitlab::AppLogger.info(message: "Dropped foreign key for previously detached partition",
+ partition_name: detached_partition.table_name,
+ referenced_table_name: foreign_key.referenced_table_identifier,
+ foreign_key_name: foreign_key.name)
+ end
+ end
+ end
+
def drop_detached_partition(partition_name)
partition_identifier = qualify_partition_name(partition_name)
- if partition_detached?(partition_identifier)
- connection.drop_table(partition_identifier, if_exists: true)
+ connection.drop_table(partition_identifier, if_exists: true)
- Gitlab::AppLogger.info(message: "Dropped previously detached partition", partition_name: partition_name)
- else
- Gitlab::AppLogger.error(message: "Attempt to drop attached database partition", partition_name: partition_name)
- end
+ Gitlab::AppLogger.info(message: "Dropped previously detached partition", partition_name: partition_name)
end
def qualify_partition_name(table_name)
"#{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.#{table_name}"
end
- def partition_detached?(partition_identifier)
+ def partition_attached?(partition_identifier)
# PostgresPartition checks the pg_inherits view, so our partition will only show here if it's still attached
# and thus should not be dropped
- !Gitlab::Database::PostgresPartition.for_identifier(partition_identifier).exists?
+ Gitlab::Database::PostgresPartition.for_identifier(partition_identifier).exists?
+ end
+
+ def try_lock_detached_partition(id)
+ Postgresql::DetachedPartition.lock.find_by(id: id).present?
end
def connection
Postgresql::DetachedPartition.connection
end
+
+ def with_lock_retries(&block)
+ Gitlab::Database::WithLockRetries.new(
+ klass: self.class,
+ logger: Gitlab::AppLogger,
+ connection: connection
+ ).run(raise_on_exhaustion: true, &block)
+ end
end
end
end
diff --git a/lib/gitlab/database/partitioning/monthly_strategy.rb b/lib/gitlab/database/partitioning/monthly_strategy.rb
index 4cdde5bf2f1..c93e775d7ed 100644
--- a/lib/gitlab/database/partitioning/monthly_strategy.rb
+++ b/lib/gitlab/database/partitioning/monthly_strategy.rb
@@ -96,10 +96,6 @@ module Gitlab
def oldest_active_date
(Date.today - retain_for).beginning_of_month
end
-
- def connection
- ActiveRecord::Base.connection
- end
end
end
end
diff --git a/lib/gitlab/database/partitioning/multi_database_partition_dropper.rb b/lib/gitlab/database/partitioning/multi_database_partition_dropper.rb
deleted file mode 100644
index 769b658bae4..00000000000
--- a/lib/gitlab/database/partitioning/multi_database_partition_dropper.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Database
- module Partitioning
- class MultiDatabasePartitionDropper
- def drop_detached_partitions
- Gitlab::AppLogger.info(message: "Dropping detached postgres partitions")
-
- each_database_connection do |name, connection|
- Gitlab::Database::SharedModel.using_connection(connection) do
- Gitlab::AppLogger.debug(message: "Switched database connection", connection_name: name)
-
- DetachedPartitionDropper.new.perform
- end
- end
-
- Gitlab::AppLogger.info(message: "Finished dropping detached postgres partitions")
- end
-
- private
-
- def each_database_connection
- databases.each_pair do |name, connection_wrapper|
- yield name, connection_wrapper.scope.connection
- end
- end
-
- def databases
- Gitlab::Database.databases
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/database/partitioning/multi_database_partition_manager.rb b/lib/gitlab/database/partitioning/multi_database_partition_manager.rb
deleted file mode 100644
index 5a93e3fb1fb..00000000000
--- a/lib/gitlab/database/partitioning/multi_database_partition_manager.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Database
- module Partitioning
- class MultiDatabasePartitionManager
- def initialize(models)
- @models = models
- end
-
- def sync_partitions
- Gitlab::AppLogger.info(message: "Syncing dynamic postgres partitions")
-
- models.each do |model|
- Gitlab::Database::SharedModel.using_connection(model.connection) do
- Gitlab::AppLogger.debug(message: "Switched database connection",
- connection_name: connection_name,
- table_name: model.table_name)
-
- PartitionManager.new(model).sync_partitions
- end
- end
-
- Gitlab::AppLogger.info(message: "Finished sync of dynamic postgres partitions")
- end
-
- private
-
- attr_reader :models
-
- def connection_name
- Gitlab::Database::SharedModel.connection.pool.db_config.name
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/database/partitioning/partition_monitoring.rb b/lib/gitlab/database/partitioning/partition_monitoring.rb
index e5b561fc447..1a23f58285d 100644
--- a/lib/gitlab/database/partitioning/partition_monitoring.rb
+++ b/lib/gitlab/database/partitioning/partition_monitoring.rb
@@ -4,20 +4,12 @@ module Gitlab
module Database
module Partitioning
class PartitionMonitoring
- attr_reader :models
+ def report_metrics_for_model(model)
+ strategy = model.partitioning_strategy
- def initialize(models = Gitlab::Database::Partitioning.registered_models)
- @models = models
- end
-
- def report_metrics
- models.each do |model|
- strategy = model.partitioning_strategy
-
- gauge_present.set({ table: model.table_name }, strategy.current_partitions.size)
- gauge_missing.set({ table: model.table_name }, strategy.missing_partitions.size)
- gauge_extra.set({ table: model.table_name }, strategy.extra_partitions.size)
- end
+ gauge_present.set({ table: model.table_name }, strategy.current_partitions.size)
+ gauge_missing.set({ table: model.table_name }, strategy.missing_partitions.size)
+ gauge_extra.set({ table: model.table_name }, strategy.extra_partitions.size)
end
private
diff --git a/lib/gitlab/database/partitioning/replace_table.rb b/lib/gitlab/database/partitioning/replace_table.rb
index 6f6af223fa2..a7686e97553 100644
--- a/lib/gitlab/database/partitioning/replace_table.rb
+++ b/lib/gitlab/database/partitioning/replace_table.rb
@@ -9,7 +9,8 @@ module Gitlab
attr_reader :original_table, :replacement_table, :replaced_table, :primary_key_column,
:sequence, :original_primary_key, :replacement_primary_key, :replaced_primary_key
- def initialize(original_table, replacement_table, replaced_table, primary_key_column)
+ def initialize(connection, original_table, replacement_table, replaced_table, primary_key_column)
+ @connection = connection
@original_table = original_table
@replacement_table = replacement_table
@replaced_table = replaced_table
@@ -29,10 +30,8 @@ module Gitlab
private
+ attr_reader :connection
delegate :execute, :quote_table_name, :quote_column_name, to: :connection
- def connection
- @connection ||= ActiveRecord::Base.connection
- end
def default_sequence(table, column)
"#{table}_#{column}_seq"
diff --git a/lib/gitlab/database/partitioning/time_partition.rb b/lib/gitlab/database/partitioning/time_partition.rb
index e09ca483549..649687bdd12 100644
--- a/lib/gitlab/database/partitioning/time_partition.rb
+++ b/lib/gitlab/database/partitioning/time_partition.rb
@@ -87,7 +87,7 @@ module Gitlab
end
def conn
- @conn ||= ActiveRecord::Base.connection
+ @conn ||= Gitlab::Database::SharedModel.connection
end
end
end
diff --git a/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb b/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
index 0dc9f92e4c8..c382d2f0715 100644
--- a/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
@@ -428,8 +428,8 @@ module Gitlab
end
def replace_table(original_table_name, replacement_table_name, replaced_table_name, primary_key_name)
- replace_table = Gitlab::Database::Partitioning::ReplaceTable.new(original_table_name.to_s,
- replacement_table_name, replaced_table_name, primary_key_name)
+ replace_table = Gitlab::Database::Partitioning::ReplaceTable.new(connection,
+ original_table_name.to_s, replacement_table_name, replaced_table_name, primary_key_name)
transaction do
drop_sync_trigger(original_table_name)
diff --git a/lib/gitlab/database/postgres_foreign_key.rb b/lib/gitlab/database/postgres_foreign_key.rb
index 72640f8785d..241b6f009f7 100644
--- a/lib/gitlab/database/postgres_foreign_key.rb
+++ b/lib/gitlab/database/postgres_foreign_key.rb
@@ -10,6 +10,12 @@ module Gitlab
where(referenced_table_identifier: identifier)
end
+
+ scope :by_constrained_table_identifier, ->(identifier) do
+ raise ArgumentError, "Constrained table name is not fully qualified with a schema: #{identifier}" unless identifier =~ /^\w+\.\w+$/
+
+ where(constrained_table_identifier: identifier)
+ end
end
end
end
diff --git a/lib/gitlab/database/postgres_hll/batch_distinct_counter.rb b/lib/gitlab/database/postgres_hll/batch_distinct_counter.rb
index 2e3f674cf82..4e973efebca 100644
--- a/lib/gitlab/database/postgres_hll/batch_distinct_counter.rb
+++ b/lib/gitlab/database/postgres_hll/batch_distinct_counter.rb
@@ -57,7 +57,7 @@ module Gitlab
# @param finish final pkey range
# @return [Gitlab::Database::PostgresHll::Buckets] HyperLogLog data structure instance that can estimate number of unique elements
def execute(batch_size: nil, start: nil, finish: nil)
- raise 'BatchCount can not be run inside a transaction' if ActiveRecord::Base.connection.transaction_open? # rubocop: disable Database/MultipleDatabases
+ raise 'BatchCount can not be run inside a transaction' if transaction_open?
batch_size ||= DEFAULT_BATCH_SIZE
start = actual_start(start)
@@ -79,6 +79,10 @@ module Gitlab
private
+ def transaction_open?
+ @relation.connection.transaction_open?
+ end
+
def unwanted_configuration?(start, finish, batch_size)
batch_size <= MIN_REQUIRED_BATCH_SIZE ||
(finish - start) >= MAX_DATA_VOLUME ||
diff --git a/lib/gitlab/database/postgres_index.rb b/lib/gitlab/database/postgres_index.rb
index 1079bfdeda3..4a9d8728c83 100644
--- a/lib/gitlab/database/postgres_index.rb
+++ b/lib/gitlab/database/postgres_index.rb
@@ -2,7 +2,7 @@
module Gitlab
module Database
- class PostgresIndex < ActiveRecord::Base
+ class PostgresIndex < SharedModel
include Gitlab::Utils::StrongMemoize
self.table_name = 'postgres_indexes'
@@ -11,6 +11,7 @@ module Gitlab
has_one :bloat_estimate, class_name: 'Gitlab::Database::PostgresIndexBloatEstimate', foreign_key: :identifier
has_many :reindexing_actions, class_name: 'Gitlab::Database::Reindexing::ReindexAction', foreign_key: :index_identifier
+ has_many :queued_reindexing_actions, class_name: 'Gitlab::Database::Reindexing::QueuedAction', foreign_key: :index_identifier
scope :by_identifier, ->(identifier) do
raise ArgumentError, "Index name is not fully qualified with a schema: #{identifier}" unless identifier =~ /^\w+\.\w+$/
diff --git a/lib/gitlab/database/postgres_index_bloat_estimate.rb b/lib/gitlab/database/postgres_index_bloat_estimate.rb
index 379227bf87c..5c9b5777b74 100644
--- a/lib/gitlab/database/postgres_index_bloat_estimate.rb
+++ b/lib/gitlab/database/postgres_index_bloat_estimate.rb
@@ -6,7 +6,7 @@ module Gitlab
# for all indexes can be expensive in a large database.
#
# Best used on a per-index basis.
- class PostgresIndexBloatEstimate < ActiveRecord::Base
+ class PostgresIndexBloatEstimate < SharedModel
self.table_name = 'postgres_index_bloat_estimates'
self.primary_key = 'identifier'
diff --git a/lib/gitlab/database/query_analyzer.rb b/lib/gitlab/database/query_analyzer.rb
new file mode 100644
index 00000000000..0f285688876
--- /dev/null
+++ b/lib/gitlab/database/query_analyzer.rb
@@ -0,0 +1,129 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ # The purpose of this class is to implement a various query analyzers based on `pg_query`
+ # And process them all via `Gitlab::Database::QueryAnalyzers::*`
+ #
+ # Sometimes this might cause errors in specs.
+ # This is best to be disable with `describe '...', query_analyzers: false do`
+ class QueryAnalyzer
+ include ::Singleton
+
+ Parsed = Struct.new(
+ :sql, :connection, :pg
+ )
+
+ attr_reader :all_analyzers
+
+ def initialize
+ @all_analyzers = []
+ end
+
+ def hook!
+ @subscriber = ActiveSupport::Notifications.subscribe('sql.active_record') do |event|
+ # In some cases analyzer code might trigger another SQL call
+ # to avoid stack too deep this detects recursive call of subscriber
+ with_ignored_recursive_calls do
+ process_sql(event.payload[:sql], event.payload[:connection])
+ end
+ end
+ end
+
+ def within
+ # Due to singleton nature of analyzers
+ # only an outer invocation of the `.within`
+ # is allowed to initialize them
+ return yield if already_within?
+
+ begin!
+
+ begin
+ yield
+ ensure
+ end!
+ end
+ end
+
+ def already_within?
+ # If analyzers are set they are already configured
+ !enabled_analyzers.nil?
+ end
+
+ def process_sql(sql, connection)
+ analyzers = enabled_analyzers
+ return unless analyzers&.any?
+
+ parsed = parse(sql, connection)
+ return unless parsed
+
+ analyzers.each do |analyzer|
+ next if analyzer.suppressed?
+
+ analyzer.analyze(parsed)
+ rescue StandardError => e
+ # We catch all standard errors to prevent validation errors to introduce fatal errors in production
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
+ end
+ end
+
+ private
+
+ # Enable query analyzers
+ def begin!
+ analyzers = all_analyzers.select do |analyzer|
+ if analyzer.enabled?
+ analyzer.begin!
+
+ true
+ end
+ rescue StandardError => e
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
+
+ false
+ end
+
+ Thread.current[:query_analyzer_enabled_analyzers] = analyzers
+ end
+
+ # Disable enabled query analyzers
+ def end!
+ enabled_analyzers.select do |analyzer|
+ analyzer.end!
+ rescue StandardError => e
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
+ end
+
+ Thread.current[:query_analyzer_enabled_analyzers] = nil
+ end
+
+ def enabled_analyzers
+ Thread.current[:query_analyzer_enabled_analyzers]
+ end
+
+ def parse(sql, connection)
+ parsed = PgQuery.parse(sql)
+ return unless parsed
+
+ normalized = PgQuery.normalize(sql)
+ Parsed.new(normalized, connection, parsed)
+ rescue PgQuery::ParseError => e
+ # Ignore PgQuery parse errors (due to depth limit or other reasons)
+ Gitlab::ErrorTracking.track_exception(e)
+
+ nil
+ end
+
+ def with_ignored_recursive_calls
+ return if Thread.current[:query_analyzer_recursive]
+
+ begin
+ Thread.current[:query_analyzer_recursive] = true
+ yield
+ ensure
+ Thread.current[:query_analyzer_recursive] = nil
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/query_analyzers/base.rb b/lib/gitlab/database/query_analyzers/base.rb
new file mode 100644
index 00000000000..e8066f7a706
--- /dev/null
+++ b/lib/gitlab/database/query_analyzers/base.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module QueryAnalyzers
+ class Base
+ def self.suppressed?
+ Thread.current[self.suppress_key]
+ end
+
+ def self.suppress=(value)
+ Thread.current[self.suppress_key] = value
+ end
+
+ def self.with_suppressed(value = true, &blk)
+ previous = self.suppressed?
+ self.suppress = value
+ yield
+ ensure
+ self.suppress = previous
+ end
+
+ def self.begin!
+ Thread.current[self.context_key] = {}
+ end
+
+ def self.end!
+ Thread.current[self.context_key] = nil
+ end
+
+ def self.context
+ Thread.current[self.context_key]
+ end
+
+ def self.enabled?
+ raise NotImplementedError
+ end
+
+ def self.analyze(parsed)
+ raise NotImplementedError
+ end
+
+ def self.context_key
+ "#{self.class.name}_context"
+ end
+
+ def self.suppress_key
+ "#{self.class.name}_suppressed"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics.rb b/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics.rb
new file mode 100644
index 00000000000..06e2b114c91
--- /dev/null
+++ b/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module QueryAnalyzers
+ # The purpose of this analyzer is to observe via prometheus metrics
+ # all unique schemas observed on a given connection
+ #
+ # This effectively allows to do sample 1% or 0.01% of queries hitting
+ # system and observe if on a given connection we observe queries that
+ # are misaligned (`ci_replica` sees queries doing accessing only `gitlab_main`)
+ #
+ class GitlabSchemasMetrics < Base
+ class << self
+ def enabled?
+ ::Feature::FlipperFeature.table_exists? &&
+ Feature.enabled?(:query_analyzer_gitlab_schema_metrics)
+ end
+
+ def analyze(parsed)
+ db_config_name = ::Gitlab::Database.db_config_name(parsed.connection)
+ return unless db_config_name
+
+ gitlab_schemas = ::Gitlab::Database::GitlabSchema.table_schemas(parsed.pg.tables)
+ return if gitlab_schemas.empty?
+
+ # to reduce amount of labels sort schemas used
+ gitlab_schemas = gitlab_schemas.to_a.sort.join(",")
+
+ schemas_metrics.increment({
+ gitlab_schemas: gitlab_schemas,
+ db_config_name: db_config_name
+ })
+ end
+
+ def schemas_metrics
+ @schemas_metrics ||= ::Gitlab::Metrics.counter(
+ :gitlab_database_decomposition_gitlab_schemas_used,
+ 'The number of observed schemas dependent on connection'
+ )
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb b/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb
new file mode 100644
index 00000000000..2233f3c4646
--- /dev/null
+++ b/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb
@@ -0,0 +1,119 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module QueryAnalyzers
+ class PreventCrossDatabaseModification < Database::QueryAnalyzers::Base
+ CrossDatabaseModificationAcrossUnsupportedTablesError = Class.new(StandardError)
+
+ # This method will allow cross database modifications within the block
+ # Example:
+ #
+ # allow_cross_database_modification_within_transaction(url: 'url-to-an-issue') do
+ # create(:build) # inserts ci_build and project record in one transaction
+ # end
+ def self.allow_cross_database_modification_within_transaction(url:, &blk)
+ self.with_suppressed(true, &blk)
+ end
+
+ # This method will prevent cross database modifications within the block
+ # if it was allowed previously
+ def self.with_cross_database_modification_prevented(&blk)
+ self.with_suppressed(false, &blk)
+ end
+
+ def self.begin!
+ super
+
+ context.merge!({
+ transaction_depth_by_db: Hash.new { |h, k| h[k] = 0 },
+ modified_tables_by_db: Hash.new { |h, k| h[k] = Set.new }
+ })
+ end
+
+ def self.enabled?
+ ::Feature::FlipperFeature.table_exists? &&
+ Feature.enabled?(:detect_cross_database_modification, default_enabled: :yaml)
+ end
+
+ # rubocop:disable Metrics/AbcSize
+ def self.analyze(parsed)
+ return if in_factory_bot_create?
+
+ database = ::Gitlab::Database.db_config_name(parsed.connection)
+ sql = parsed.sql
+
+ # We ignore BEGIN in tests as this is the outer transaction for
+ # DatabaseCleaner
+ if sql.start_with?('SAVEPOINT') || (!Rails.env.test? && sql.start_with?('BEGIN'))
+ context[:transaction_depth_by_db][database] += 1
+
+ return
+ elsif sql.start_with?('RELEASE SAVEPOINT', 'ROLLBACK TO SAVEPOINT') || (!Rails.env.test? && sql.start_with?('ROLLBACK', 'COMMIT'))
+ context[:transaction_depth_by_db][database] -= 1
+ if context[:transaction_depth_by_db][database] <= 0
+ context[:modified_tables_by_db][database].clear
+ end
+
+ return
+ end
+
+ return if context[:transaction_depth_by_db].values.all?(&:zero?)
+
+ # PgQuery might fail in some cases due to limited nesting:
+ # https://github.com/pganalyze/pg_query/issues/209
+ tables = sql.downcase.include?(' for update') ? parsed.pg.tables : parsed.pg.dml_tables
+
+ # We have some code where plans and gitlab_subscriptions are lazily
+ # created and this causes lots of spec failures
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/343394
+ tables -= %w[plans gitlab_subscriptions]
+
+ return if tables.empty?
+
+ # All migrations will write to schema_migrations in the same transaction.
+ # It's safe to ignore this since schema_migrations exists in all
+ # databases
+ return if tables == ['schema_migrations']
+
+ context[:modified_tables_by_db][database].merge(tables)
+ all_tables = context[:modified_tables_by_db].values.map(&:to_a).flatten
+ schemas = ::Gitlab::Database::GitlabSchema.table_schemas(all_tables)
+
+ if schemas.many?
+ message = "Cross-database data modification of '#{schemas.to_a.join(", ")}' were detected within " \
+ "a transaction modifying the '#{all_tables.to_a.join(", ")}' tables." \
+ "Please refer to https://docs.gitlab.com/ee/development/database/multiple_databases.html#removing-cross-database-transactions for details on how to resolve this exception."
+
+ if schemas.any? { |s| s.to_s.start_with?("undefined") }
+ message += " The gitlab_schema was undefined for one or more of the tables in this transaction. Any new tables must be added to lib/gitlab/database/gitlab_schemas.yml ."
+ end
+
+ raise CrossDatabaseModificationAcrossUnsupportedTablesError, message
+ end
+ rescue CrossDatabaseModificationAcrossUnsupportedTablesError => e
+ ::Gitlab::ErrorTracking.track_exception(e, { gitlab_schemas: schemas, tables: all_tables, query: parsed.sql })
+ raise if raise_exception?
+ end
+ # rubocop:enable Metrics/AbcSize
+
+ # We only raise in tests for now otherwise some features will be broken
+ # in development. For now we've mostly only added allowlist based on
+ # spec names. Until we have allowed all the violations inline we don't
+ # want to raise in development.
+ def self.raise_exception?
+ Rails.env.test?
+ end
+
+ # We ignore execution in the #create method from FactoryBot
+ # because it is not representative of real code we run in
+ # production. There are far too many false positives caused
+ # by instantiating objects in different `gitlab_schema` in a
+ # FactoryBot `create`.
+ def self.in_factory_bot_create?
+ Rails.env.test? && caller_locations.any? { |l| l.path.end_with?('lib/factory_bot/evaluation.rb') && l.label == 'create' }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/reflection.rb b/lib/gitlab/database/reflection.rb
new file mode 100644
index 00000000000..48a4de28541
--- /dev/null
+++ b/lib/gitlab/database/reflection.rb
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ # A class for reflecting upon a database and its settings, such as the
+ # adapter name, PostgreSQL version, and the presence of tables or columns.
+ class Reflection
+ attr_reader :model
+
+ def initialize(model)
+ @model = model
+ @version = nil
+ end
+
+ def config
+ # The result of this method must not be cached, as other methods may use
+ # it after making configuration changes and expect those changes to be
+ # present. For example, `disable_prepared_statements` expects the
+ # configuration settings to always be up to date.
+ #
+ # See the following for more information:
+ #
+ # - https://gitlab.com/gitlab-org/release/retrospectives/-/issues/39
+ # - https://gitlab.com/gitlab-com/gl-infra/production/-/issues/5238
+ model.connection_db_config.configuration_hash.with_indifferent_access
+ end
+
+ def username
+ config[:username] || ENV['USER']
+ end
+
+ def database_name
+ config[:database]
+ end
+
+ def adapter_name
+ config[:adapter]
+ end
+
+ def human_adapter_name
+ if postgresql?
+ 'PostgreSQL'
+ else
+ 'Unknown'
+ end
+ end
+
+ def postgresql?
+ adapter_name.casecmp('postgresql') == 0
+ end
+
+ # Check whether the underlying database is in read-only mode
+ def db_read_only?
+ pg_is_in_recovery =
+ connection
+ .execute('SELECT pg_is_in_recovery()')
+ .first
+ .fetch('pg_is_in_recovery')
+
+ Gitlab::Utils.to_boolean(pg_is_in_recovery)
+ end
+
+ def db_read_write?
+ !db_read_only?
+ end
+
+ def version
+ @version ||= database_version.match(/\A(?:PostgreSQL |)([^\s]+).*\z/)[1]
+ end
+
+ def database_version
+ connection.execute("SELECT VERSION()").first['version']
+ end
+
+ def postgresql_minimum_supported_version?
+ version.to_f >= MINIMUM_POSTGRES_VERSION
+ end
+
+ def cached_column_exists?(column_name)
+ connection
+ .schema_cache.columns_hash(model.table_name)
+ .has_key?(column_name.to_s)
+ end
+
+ def cached_table_exists?
+ exists? && connection.schema_cache.data_source_exists?(model.table_name)
+ end
+
+ def exists?
+ # We can't _just_ check if `connection` raises an error, as it will
+ # point to a `ConnectionProxy`, and obtaining those doesn't involve any
+ # database queries. So instead we obtain the database version, which is
+ # cached after the first call.
+ connection.schema_cache.database_version
+ true
+ rescue StandardError
+ false
+ end
+
+ def system_id
+ row = connection
+ .execute('SELECT system_identifier FROM pg_control_system()')
+ .first
+
+ row['system_identifier']
+ end
+
+ private
+
+ def connection
+ model.connection
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/reindexing.rb b/lib/gitlab/database/reindexing.rb
index 04b409a9306..7a22e324bdb 100644
--- a/lib/gitlab/database/reindexing.rb
+++ b/lib/gitlab/database/reindexing.rb
@@ -15,25 +15,58 @@ module Gitlab
# on e.g. vacuum.
REMOVE_INDEX_RETRY_CONFIG = [[1.minute, 9.minutes]] * 30
- # candidate_indexes: Array of Gitlab::Database::PostgresIndex
- def self.perform(candidate_indexes, how_many: DEFAULT_INDEXES_PER_INVOCATION)
- IndexSelection.new(candidate_indexes).take(how_many).each do |index|
+ # Performs automatic reindexing for a limited number of indexes per call
+ # 1. Consume from the explicit reindexing queue
+ # 2. Apply bloat heuristic to find most bloated indexes and reindex those
+ def self.automatic_reindexing(maximum_records: DEFAULT_INDEXES_PER_INVOCATION)
+ # Cleanup leftover temporary indexes from previous, possibly aborted runs (if any)
+ cleanup_leftovers!
+
+ # Consume from the explicit reindexing queue first
+ done_counter = perform_from_queue(maximum_records: maximum_records)
+
+ return if done_counter >= maximum_records
+
+ # Execute reindexing based on bloat heuristic
+ perform_with_heuristic(maximum_records: maximum_records - done_counter)
+ end
+
+ # Reindex based on bloat heuristic for a limited number of indexes per call
+ #
+ # We use a bloat heuristic to estimate the index bloat and pick the
+ # most bloated indexes for reindexing.
+ def self.perform_with_heuristic(candidate_indexes = Gitlab::Database::PostgresIndex.reindexing_support, maximum_records: DEFAULT_INDEXES_PER_INVOCATION)
+ IndexSelection.new(candidate_indexes).take(maximum_records).each do |index|
Coordinator.new(index).perform
end
end
+ # Reindex indexes that have been explicitly enqueued (for a limited number of indexes per call)
+ def self.perform_from_queue(maximum_records: DEFAULT_INDEXES_PER_INVOCATION)
+ QueuedAction.in_queue_order.limit(maximum_records).each do |queued_entry|
+ Coordinator.new(queued_entry.index).perform
+
+ queued_entry.done!
+ rescue StandardError => e
+ queued_entry.failed!
+
+ Gitlab::AppLogger.error("Failed to perform reindexing action on queued entry #{queued_entry}: #{e}")
+ end.size
+ end
+
def self.cleanup_leftovers!
PostgresIndex.reindexing_leftovers.each do |index|
Gitlab::AppLogger.info("Removing index #{index.identifier} which is a leftover, temporary index from previous reindexing activity")
retries = Gitlab::Database::WithLockRetriesOutsideTransaction.new(
+ connection: index.connection,
timing_configuration: REMOVE_INDEX_RETRY_CONFIG,
klass: self.class,
logger: Gitlab::AppLogger
)
retries.run(raise_on_exhaustion: false) do
- ApplicationRecord.connection.tap do |conn|
+ index.connection.tap do |conn|
conn.execute("DROP INDEX CONCURRENTLY IF EXISTS #{conn.quote_table_name(index.schema)}.#{conn.quote_table_name(index.name)}")
end
end
diff --git a/lib/gitlab/database/reindexing/index_selection.rb b/lib/gitlab/database/reindexing/index_selection.rb
index 2186384e7d7..2d384f2f9e2 100644
--- a/lib/gitlab/database/reindexing/index_selection.rb
+++ b/lib/gitlab/database/reindexing/index_selection.rb
@@ -9,8 +9,8 @@ module Gitlab
# Only reindex indexes with a relative bloat level (bloat estimate / size) higher than this
MINIMUM_RELATIVE_BLOAT = 0.2
- # Only consider indexes with a total ondisk size in this range (before reindexing)
- INDEX_SIZE_RANGE = (1.gigabyte..100.gigabyte).freeze
+ # Only consider indexes beyond this size (before reindexing)
+ INDEX_SIZE_MINIMUM = 1.gigabyte
delegate :each, to: :indexes
@@ -32,7 +32,7 @@ module Gitlab
@indexes ||= candidates
.not_recently_reindexed
- .where(ondisk_size_bytes: INDEX_SIZE_RANGE)
+ .where('ondisk_size_bytes >= ?', INDEX_SIZE_MINIMUM)
.sort_by(&:relative_bloat_level) # forced N+1
.reverse
.select { |candidate| candidate.relative_bloat_level >= MINIMUM_RELATIVE_BLOAT }
diff --git a/lib/gitlab/database/reindexing/queued_action.rb b/lib/gitlab/database/reindexing/queued_action.rb
new file mode 100644
index 00000000000..c2039a289da
--- /dev/null
+++ b/lib/gitlab/database/reindexing/queued_action.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Reindexing
+ class QueuedAction < SharedModel
+ self.table_name = 'postgres_reindex_queued_actions'
+
+ enum state: { queued: 0, done: 1, failed: 2 }
+
+ belongs_to :index, foreign_key: :index_identifier, class_name: 'Gitlab::Database::PostgresIndex'
+
+ scope :in_queue_order, -> { queued.order(:created_at) }
+
+ def to_s
+ "queued action [ id = #{id}, index: #{index_identifier} ]"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/reindexing/reindex_action.rb b/lib/gitlab/database/reindexing/reindex_action.rb
index ff465fffb74..73424a76cfe 100644
--- a/lib/gitlab/database/reindexing/reindex_action.rb
+++ b/lib/gitlab/database/reindexing/reindex_action.rb
@@ -3,7 +3,7 @@
module Gitlab
module Database
module Reindexing
- class ReindexAction < ActiveRecord::Base
+ class ReindexAction < SharedModel
self.table_name = 'postgres_reindex_actions'
belongs_to :index, foreign_key: :index_identifier, class_name: 'Gitlab::Database::PostgresIndex'
diff --git a/lib/gitlab/database/reindexing/reindex_concurrently.rb b/lib/gitlab/database/reindexing/reindex_concurrently.rb
index 7a720f7c539..152935bd734 100644
--- a/lib/gitlab/database/reindexing/reindex_concurrently.rb
+++ b/lib/gitlab/database/reindexing/reindex_concurrently.rb
@@ -8,7 +8,7 @@ module Gitlab
ReindexError = Class.new(StandardError)
TEMPORARY_INDEX_PATTERN = '\_ccnew[0-9]*'
- STATEMENT_TIMEOUT = 9.hours
+ STATEMENT_TIMEOUT = 24.hours
PG_MAX_INDEX_NAME_LENGTH = 63
attr_reader :index, :logger
@@ -99,6 +99,7 @@ module Gitlab
logger.info("Removing dangling index #{index.identifier}")
retries = Gitlab::Database::WithLockRetriesOutsideTransaction.new(
+ connection: connection,
timing_configuration: REMOVE_INDEX_RETRY_CONFIG,
klass: self.class,
logger: logger
@@ -109,11 +110,6 @@ module Gitlab
end
end
- def with_lock_retries(&block)
- arguments = { klass: self.class, logger: logger }
- Gitlab::Database::WithLockRetries.new(**arguments).run(raise_on_exhaustion: true, &block)
- end
-
def set_statement_timeout
execute("SET statement_timeout TO '%ds'" % STATEMENT_TIMEOUT)
yield
@@ -123,7 +119,7 @@ module Gitlab
delegate :execute, :quote_table_name, to: :connection
def connection
- @connection ||= ActiveRecord::Base.connection
+ @connection ||= index.connection
end
end
end
diff --git a/lib/gitlab/database/shared_model.rb b/lib/gitlab/database/shared_model.rb
index f304c32d731..f31dbc01907 100644
--- a/lib/gitlab/database/shared_model.rb
+++ b/lib/gitlab/database/shared_model.rb
@@ -8,13 +8,17 @@ module Gitlab
class << self
def using_connection(connection)
- raise 'cannot nest connection overrides for shared models' unless overriding_connection.nil?
+ previous_connection = self.overriding_connection
+
+ unless previous_connection.nil? || previous_connection.equal?(connection)
+ raise 'cannot nest connection overrides for shared models with different connections'
+ end
self.overriding_connection = connection
yield
ensure
- self.overriding_connection = nil
+ self.overriding_connection = nil unless previous_connection.equal?(self.overriding_connection)
end
def connection
diff --git a/lib/gitlab/database/unidirectional_copy_trigger.rb b/lib/gitlab/database/unidirectional_copy_trigger.rb
index 029c894a5ff..146b5cacd9e 100644
--- a/lib/gitlab/database/unidirectional_copy_trigger.rb
+++ b/lib/gitlab/database/unidirectional_copy_trigger.rb
@@ -3,7 +3,7 @@
module Gitlab
module Database
class UnidirectionalCopyTrigger
- def self.on_table(table_name, connection: ActiveRecord::Base.connection)
+ def self.on_table(table_name, connection:)
new(table_name, connection)
end
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index 1e6d80e1100..83f242ff902 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -43,6 +43,8 @@ module Gitlab
# Ensure items are collected in the the batch
new_blob_lazy
old_blob_lazy
+
+ preprocess_before_diff(diff) if Feature.enabled?(:jupyter_clean_diffs, repository.project, default_enabled: true)
end
def position(position_marker, position_type: :text)
@@ -448,6 +450,33 @@ module Gitlab
find_renderable_viewer_class(classes)
end
+ def preprocess_before_diff(diff)
+ return unless diff.new_path.ends_with? '.ipynb'
+
+ from = old_blob_lazy&.data
+ to = new_blob_lazy&.data
+
+ transformed_diff = IpynbDiff.diff(from, to,
+ diff_opts: { context: 5, include_diff_info: true },
+ transform_options: { cell_decorator: :percent },
+ raise_if_invalid_notebook: true)
+ new_diff = strip_diff_frontmatter(transformed_diff)
+
+ if new_diff
+ diff.diff = new_diff
+ new_blob_lazy.transformed_for_diff = true if new_blob_lazy
+ old_blob_lazy.transformed_for_diff = true if old_blob_lazy
+ end
+
+ Gitlab::AppLogger.info({ message: new_diff ? 'IPYNB_DIFF_GENERATED' : 'IPYNB_DIFF_NIL' })
+ rescue IpynbDiff::InvalidNotebookError => e
+ Gitlab::ErrorTracking.log_exception(e)
+ end
+
+ def strip_diff_frontmatter(diff_content)
+ diff_content.scan(/.*\n/)[2..-1]&.join('') if diff_content.present?
+ end
+
def alternate_viewer_class
return unless viewer.instance_of?(DiffViewer::Renamed)
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
index 32ce35110f8..aedcfe3cb40 100644
--- a/lib/gitlab/diff/highlight.rb
+++ b/lib/gitlab/diff/highlight.rb
@@ -152,6 +152,9 @@ module Gitlab
return [] unless blob
blob.load_all_data!
+
+ return blob.present.highlight_transformed.lines if Feature.enabled?(:jupyter_clean_diffs, @project, default_enabled: true)
+
blob.present.highlight.lines
end
diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb
index 075027ebdc8..12ed11b0140 100644
--- a/lib/gitlab/diff/highlight_cache.rb
+++ b/lib/gitlab/diff/highlight_cache.rb
@@ -213,7 +213,7 @@ module Gitlab
end
def current_transaction
- ::Gitlab::Metrics::Transaction.current
+ ::Gitlab::Metrics::WebTransaction.current
end
end
end
diff --git a/lib/gitlab/diff/position_tracer/line_strategy.rb b/lib/gitlab/diff/position_tracer/line_strategy.rb
index 8bacc781f61..0f0b8f0c4f3 100644
--- a/lib/gitlab/diff/position_tracer/line_strategy.rb
+++ b/lib/gitlab/diff/position_tracer/line_strategy.rb
@@ -104,7 +104,7 @@ module Gitlab
# the current state on the CD diff, so we treat it as outdated.
ac_diff = ac_diffs.diff_file_with_new_path(c_path, c_mode)
- { position: new_position(ac_diff, nil, c_line), outdated: true }
+ { position: new_position(ac_diff, nil, c_line, position.line_range), outdated: true }
end
else
# If the line is still in D and not in C, it is still added.
@@ -112,7 +112,7 @@ module Gitlab
end
else
# If the line is no longer in D, it has been removed from the MR.
- { position: new_position(bd_diff, b_line, nil), outdated: true }
+ { position: new_position(bd_diff, b_line, nil, position.line_range), outdated: true }
end
end
@@ -140,14 +140,14 @@ module Gitlab
# removed line into an unchanged one.
bd_diff = bd_diffs.diff_file_with_new_path(d_path, d_mode)
- { position: new_position(bd_diff, nil, d_line), outdated: true }
+ { position: new_position(bd_diff, nil, d_line, position.line_range), outdated: true }
else
# If the line is still in C and not in D, it is still removed.
{ position: new_position(cd_diff, c_line, nil, position.line_range), outdated: false }
end
else
# If the line is no longer in C, it has been removed outside of the MR.
- { position: new_position(ac_diff, a_line, nil), outdated: true }
+ { position: new_position(ac_diff, a_line, nil, position.line_range), outdated: true }
end
end
diff --git a/lib/gitlab/email/handler/service_desk_handler.rb b/lib/gitlab/email/handler/service_desk_handler.rb
index 74c8d0a1fd7..8d73aa842be 100644
--- a/lib/gitlab/email/handler/service_desk_handler.rb
+++ b/lib/gitlab/email/handler/service_desk_handler.rb
@@ -15,16 +15,14 @@ module Gitlab
PROJECT_KEY_PATTERN = /\A(?<slug>.+)-(?<key>[a-z0-9_]+)\z/.freeze
def initialize(mail, mail_key, service_desk_key: nil)
- super(mail, mail_key)
-
- if service_desk_key.present?
+ if service_desk_key
+ mail_key ||= service_desk_key
@service_desk_key = service_desk_key
- elsif !mail_key&.include?('/') && (matched = HANDLER_REGEX.match(mail_key.to_s))
- @project_slug = matched[:project_slug]
- @project_id = matched[:project_id]&.to_i
- elsif matched = HANDLER_REGEX_LEGACY.match(mail_key.to_s)
- @project_path = matched[:project_path]
end
+
+ super(mail, mail_key)
+
+ match_project_slug || match_legacy_project_slug
end
def can_handle?
@@ -42,15 +40,29 @@ module Gitlab
end
end
+ def match_project_slug
+ return if mail_key&.include?('/')
+ return unless matched = HANDLER_REGEX.match(mail_key.to_s)
+
+ @project_slug = matched[:project_slug]
+ @project_id = matched[:project_id]&.to_i
+ end
+
+ def match_legacy_project_slug
+ return unless matched = HANDLER_REGEX_LEGACY.match(mail_key.to_s)
+
+ @project_path = matched[:project_path]
+ end
+
def metrics_event
:receive_email_service_desk
end
def project
strong_memoize(:project) do
- @project = service_desk_key ? project_from_key : super
- @project = nil unless @project&.service_desk_enabled?
- @project
+ project_record = super
+ project_record ||= project_from_key if service_desk_key
+ project_record&.service_desk_enabled? ? project_record : nil
end
end
@@ -96,7 +108,7 @@ module Gitlab
end
def message_including_template
- description = message_including_reply
+ description = process_message(trim_reply: false, allow_only_quotes: true)
template_content = service_desk_setting&.issue_template_content
if template_content.present?
diff --git a/lib/gitlab/email/message/in_product_marketing.rb b/lib/gitlab/email/message/in_product_marketing.rb
index fb4315e74b2..ac9585bcd1a 100644
--- a/lib/gitlab/email/message/in_product_marketing.rb
+++ b/lib/gitlab/email/message/in_product_marketing.rb
@@ -7,7 +7,8 @@ module Gitlab
UnknownTrackError = Class.new(StandardError)
def self.for(track)
- raise UnknownTrackError unless Namespaces::InProductMarketingEmailsService::TRACKS.key?(track)
+ valid_tracks = [Namespaces::InviteTeamEmailService::TRACK, Namespaces::InProductMarketingEmailsService::TRACKS.keys].flatten
+ raise UnknownTrackError unless valid_tracks.include?(track)
"Gitlab::Email::Message::InProductMarketing::#{track.to_s.classify}".constantize
end
diff --git a/lib/gitlab/email/message/in_product_marketing/admin_verify.rb b/lib/gitlab/email/message/in_product_marketing/admin_verify.rb
index 234b93594b5..19d9cf99cdb 100644
--- a/lib/gitlab/email/message/in_product_marketing/admin_verify.rb
+++ b/lib/gitlab/email/message/in_product_marketing/admin_verify.rb
@@ -36,6 +36,10 @@ module Gitlab
def progress
super(track_name: 'Admin')
end
+
+ def invite_members?
+ invite_members_for_task_experiment_enabled?
+ end
end
end
end
diff --git a/lib/gitlab/email/message/in_product_marketing/base.rb b/lib/gitlab/email/message/in_product_marketing/base.rb
index c4895d35a14..7cd54390b9f 100644
--- a/lib/gitlab/email/message/in_product_marketing/base.rb
+++ b/lib/gitlab/email/message/in_product_marketing/base.rb
@@ -7,16 +7,17 @@ module Gitlab
class Base
include Gitlab::Email::Message::InProductMarketing::Helper
include Gitlab::Routing
+ include Gitlab::Experiment::Dsl
attr_accessor :format
def initialize(group:, user:, series:, format: :html)
- raise ArgumentError, "Only #{total_series} series available for this track." unless series.between?(0, total_series - 1)
-
+ @series = series
@group = group
@user = user
- @series = series
@format = format
+
+ validate_series!
end
def subject_line
@@ -56,6 +57,18 @@ module Gitlab
end
end
+ def invite_members?
+ false
+ end
+
+ def invite_text
+ s_('InProductMarketing|Do you have a teammate who would be perfect for this task?')
+ end
+
+ def invite_link
+ action_link(s_('InProductMarketing|Invite them to help out.'), group_url(group, open_modal: 'invite_members_for_task'))
+ end
+
def unsubscribe
parts = Gitlab.com? ? unsubscribe_com : unsubscribe_self_managed(track, series)
@@ -102,6 +115,10 @@ module Gitlab
["mailers/in_product_marketing", "#{track}-#{series}.png"].join('/')
end
+ def series?
+ total_series > 0
+ end
+
protected
attr_reader :group, :user, :series
@@ -148,6 +165,20 @@ module Gitlab
link(s_('InProductMarketing|update your preferences'), preference_link)
end
+
+ def invite_members_for_task_experiment_enabled?
+ return unless user.can?(:admin_group_member, group)
+
+ experiment(:invite_members_for_task, namespace: group) do |e|
+ e.candidate { true }
+ e.record!
+ e.run
+ end
+ end
+
+ def validate_series!
+ raise ArgumentError, "Only #{total_series} series available for this track." unless @series.between?(0, total_series - 1)
+ end
end
end
end
diff --git a/lib/gitlab/email/message/in_product_marketing/create.rb b/lib/gitlab/email/message/in_product_marketing/create.rb
index 4b0c4af4911..2c396775374 100644
--- a/lib/gitlab/email/message/in_product_marketing/create.rb
+++ b/lib/gitlab/email/message/in_product_marketing/create.rb
@@ -61,6 +61,10 @@ module Gitlab
][series]
end
+ def invite_members?
+ invite_members_for_task_experiment_enabled?
+ end
+
private
def project_link
diff --git a/lib/gitlab/email/message/in_product_marketing/experience.rb b/lib/gitlab/email/message/in_product_marketing/experience.rb
index 4156a737517..7520de6d2a3 100644
--- a/lib/gitlab/email/message/in_product_marketing/experience.rb
+++ b/lib/gitlab/email/message/in_product_marketing/experience.rb
@@ -43,7 +43,9 @@ module Gitlab
survey_id: EASE_SCORE_SURVEY_ID
}
- "#{Gitlab::Saas.com_url}/-/survey_responses?#{params.to_query}"
+ params[:show_incentive] = true if show_incentive?
+
+ "#{gitlab_com_root_url}/-/survey_responses?#{params.to_query}"
end
def feedback_ratings(rating)
@@ -70,9 +72,19 @@ module Gitlab
def show_invite_link
strong_memoize(:show_invite_link) do
- group.member_count > 1 && group.max_member_access_for_user(user) >= GroupMember::DEVELOPER && user.preferred_language == 'en'
+ group.max_member_access_for_user(user) >= GroupMember::DEVELOPER && user.preferred_language == 'en'
end
end
+
+ def show_incentive?
+ show_invite_link && group.member_count > 1
+ end
+
+ def gitlab_com_root_url
+ return root_url.chomp('/') if Rails.env.development?
+
+ Gitlab::Saas.com_url
+ end
end
end
end
diff --git a/lib/gitlab/email/message/in_product_marketing/helper.rb b/lib/gitlab/email/message/in_product_marketing/helper.rb
index cec0aad44a6..bffa90ed4ec 100644
--- a/lib/gitlab/email/message/in_product_marketing/helper.rb
+++ b/lib/gitlab/email/message/in_product_marketing/helper.rb
@@ -36,6 +36,15 @@ module Gitlab
"#{text} (#{link})"
end
end
+
+ def action_link(text, link)
+ case format
+ when :html
+ ActionController::Base.helpers.link_to text, link, target: '_blank', rel: 'noopener noreferrer'
+ else
+ [text, link].join(' >> ')
+ end
+ end
end
end
end
diff --git a/lib/gitlab/email/message/in_product_marketing/invite_team.rb b/lib/gitlab/email/message/in_product_marketing/invite_team.rb
new file mode 100644
index 00000000000..e9334b687f4
--- /dev/null
+++ b/lib/gitlab/email/message/in_product_marketing/invite_team.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Email
+ module Message
+ module InProductMarketing
+ class InviteTeam < Base
+ def subject_line
+ s_('InProductMarketing|Invite your teammates to GitLab')
+ end
+
+ def tagline
+ ''
+ end
+
+ def title
+ s_('InProductMarketing|GitLab is better with teammates to help out!')
+ end
+
+ def subtitle
+ ''
+ end
+
+ def body_line1
+ s_('InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running.')
+ end
+
+ def body_line2
+ ''
+ end
+
+ def cta_text
+ s_('InProductMarketing|Invite your teammates to help')
+ end
+
+ def logo_path
+ 'mailers/in_product_marketing/team-0.png'
+ end
+
+ def series?
+ false
+ end
+
+ private
+
+ def validate_series!
+ raise ArgumentError, "Only one email is sent for this track. Value of `series` should be 0." unless @series == 0
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/email/message/in_product_marketing/verify.rb b/lib/gitlab/email/message/in_product_marketing/verify.rb
index e731c65121e..daf0c969f2b 100644
--- a/lib/gitlab/email/message/in_product_marketing/verify.rb
+++ b/lib/gitlab/email/message/in_product_marketing/verify.rb
@@ -65,6 +65,10 @@ module Gitlab
][series]
end
+ def invite_members?
+ invite_members_for_task_experiment_enabled?
+ end
+
private
def ci_link
diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb
index 242def826be..526f1188065 100644
--- a/lib/gitlab/email/receiver.rb
+++ b/lib/gitlab/email/receiver.rb
@@ -44,6 +44,10 @@ module Gitlab
}
end
+ def mail
+ strong_memoize(:mail) { build_mail }
+ end
+
private
def handler
@@ -54,10 +58,6 @@ module Gitlab
Handler.for(mail, mail_key)
end
- def mail
- strong_memoize(:mail) { build_mail }
- end
-
def build_mail
Mail::Message.new(@raw)
rescue Encoding::UndefinedConversionError,
diff --git a/lib/gitlab/email/reply_parser.rb b/lib/gitlab/email/reply_parser.rb
index 0f0f4800062..d39fa139abb 100644
--- a/lib/gitlab/email/reply_parser.rb
+++ b/lib/gitlab/email/reply_parser.rb
@@ -4,12 +4,13 @@
module Gitlab
module Email
class ReplyParser
- attr_accessor :message
+ attr_accessor :message, :allow_only_quotes
- def initialize(message, trim_reply: true, append_reply: false)
+ def initialize(message, trim_reply: true, append_reply: false, allow_only_quotes: false)
@message = message
@trim_reply = trim_reply
@append_reply = append_reply
+ @allow_only_quotes = allow_only_quotes
end
def execute
@@ -25,7 +26,12 @@ module Gitlab
# NOTE: We currently don't support empty quotes.
# EmailReplyTrimmer allows this as a special case,
# so we detect it manually here.
- return "" if body.lines.all? { |l| l.strip.empty? || l.start_with?('>') }
+ #
+ # If allow_only_quotes is true a message where all lines starts with ">" is allowed.
+ # This could happen if an email has an empty quote, forwarded without any new content.
+ return "" if body.lines.all? do |l|
+ l.strip.empty? || (!allow_only_quotes && l.start_with?('>'))
+ end
encoded_body = body.force_encoding(encoding).encode("UTF-8")
return encoded_body unless @append_reply
diff --git a/lib/gitlab/emoji.rb b/lib/gitlab/emoji.rb
index 2b5f465d3c5..519b1d94bf5 100644
--- a/lib/gitlab/emoji.rb
+++ b/lib/gitlab/emoji.rb
@@ -4,40 +4,15 @@ module Gitlab
module Emoji
extend self
- def emojis
- Gemojione.index.instance_variable_get(:@emoji_by_name)
- end
-
- def emojis_by_moji
- Gemojione.index.instance_variable_get(:@emoji_by_moji)
- end
-
- def emojis_unicodes
- emojis_by_moji.keys
- end
-
- def emojis_names
- emojis.keys
- end
-
- def emojis_aliases
- @emoji_aliases ||= Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'aliases.json')))
- end
-
- def emoji_filename(name)
- emojis[name]["unicode"]
- end
-
- def emoji_unicode_filename(moji)
- emojis_by_moji[moji]["unicode"]
- end
-
- def emoji_unicode_version(name)
- emoji_unicode_versions_by_name[name]
- end
+ # When updating emoji assets increase the version below
+ # and update the version number in `app/assets/javascripts/emoji/index.js`
+ EMOJI_VERSION = 1
- def normalize_emoji_name(name)
- emojis_aliases[name] || name
+ # Return a Pathname to emoji's current versioned folder
+ #
+ # @return [Pathname] Absolute Path to versioned emojis folder in `public`
+ def emoji_public_absolute_path
+ Rails.root.join("public/-/emojis/#{EMOJI_VERSION}")
end
def emoji_image_tag(name, src)
@@ -54,23 +29,19 @@ module Gitlab
ActionController::Base.helpers.tag(:img, image_options)
end
- def emoji_exists?(name)
- emojis.has_key?(name)
- end
-
# CSS sprite fallback takes precedence over image fallback
- def gl_emoji_tag(name, options = {})
- emoji_name = emojis_aliases[name] || name
- emoji_info = emojis[emoji_name]
- return unless emoji_info
+ # @param [TanukiEmoji::Character] emoji
+ # @param [Hash] options
+ def gl_emoji_tag(emoji, options = {})
+ return unless emoji
data = {
- name: emoji_name,
- unicode_version: emoji_unicode_version(emoji_name)
+ name: emoji.name,
+ unicode_version: emoji.unicode_version
}
- options = { title: emoji_info['description'], data: data }.merge(options)
+ options = { title: emoji.description, data: data }.merge(options)
- ActionController::Base.helpers.content_tag('gl-emoji', emoji_info['moji'], options)
+ ActionController::Base.helpers.content_tag('gl-emoji', emoji.codepoints, options)
end
def custom_emoji_tag(name, image_source)
@@ -82,12 +53,5 @@ module Gitlab
emoji_image_tag(name, image_source).html_safe
end
end
-
- private
-
- def emoji_unicode_versions_by_name
- @emoji_unicode_versions_by_name ||=
- Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'emoji-unicode-version-map.json')))
- end
end
end
diff --git a/lib/gitlab/etag_caching/router/restful.rb b/lib/gitlab/etag_caching/router/restful.rb
index 408a901f69d..176676bd6ba 100644
--- a/lib/gitlab/etag_caching/router/restful.rb
+++ b/lib/gitlab/etag_caching/router/restful.rb
@@ -23,7 +23,7 @@ module Gitlab
[
%r(#{RESERVED_WORDS_PREFIX}/noteable/issue/\d+/notes\z),
'issue_notes',
- 'issue_tracking'
+ 'team_planning'
],
[
%r(#{RESERVED_WORDS_PREFIX}/noteable/merge_request/\d+/notes\z),
@@ -33,7 +33,7 @@ module Gitlab
[
%r(#{RESERVED_WORDS_PREFIX}/issues/\d+/realtime_changes\z),
'issue_title',
- 'issue_tracking'
+ 'team_planning'
],
[
%r(#{RESERVED_WORDS_PREFIX}/commit/\S+/pipelines\.json\z),
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index a1855132b0c..2da30b88d55 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -17,6 +17,7 @@ module Gitlab
OSError = Class.new(BaseError)
UnknownRef = Class.new(BaseError)
CommandTimedOut = Class.new(CommandError)
+ InvalidPageToken = Class.new(BaseError)
class << self
include Gitlab::EncodingHelper
diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb
index f72217dedde..b0d194f309a 100644
--- a/lib/gitlab/git/blob.rb
+++ b/lib/gitlab/git/blob.rb
@@ -24,7 +24,7 @@ module Gitlab
LFS_POINTER_MIN_SIZE = 120.bytes
LFS_POINTER_MAX_SIZE = 200.bytes
- attr_accessor :size, :mode, :id, :commit_id, :loaded_size, :binary
+ attr_accessor :size, :mode, :id, :commit_id, :loaded_size, :binary, :transformed_for_diff
attr_writer :name, :path, :data
def self.gitlab_blob_truncated_true
@@ -127,6 +127,7 @@ module Gitlab
# Retain the actual size before it is encoded
@loaded_size = @data.bytesize if @data
@loaded_all_data = @loaded_size == size
+ @transformed_for_diff = false
record_metric_blob_size
record_metric_truncated(truncated?)
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index 6605e896ef1..267107e04e6 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -315,10 +315,18 @@ module Gitlab
#
def ref_names(repo)
refs(repo).map do |ref|
- ref.sub(%r{^refs/(heads|remotes|tags)/}, "")
+ strip_ref_prefix(ref)
end
end
+ def first_ref_by_oid(repo)
+ ref = repo.refs_by_oid(oid: id, limit: 1)&.first
+
+ return unless ref
+
+ strip_ref_prefix(ref)
+ end
+
def message
encode! @message
end
@@ -466,6 +474,10 @@ module Gitlab
commit_id.match?(/\s/)
)
end
+
+ def strip_ref_prefix(ref)
+ ref.sub(%r{^refs/(heads|remotes|tags)/}, "")
+ end
end
end
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 473bc04661c..5afdcc0bd4c 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -20,6 +20,7 @@ module Gitlab
EMPTY_REPOSITORY_CHECKSUM = '0000000000000000000000000000000000000000'
NoRepository = Class.new(::Gitlab::Git::BaseError)
+ RepositoryExists = Class.new(::Gitlab::Git::BaseError)
InvalidRepository = Class.new(::Gitlab::Git::BaseError)
InvalidBlobName = Class.new(::Gitlab::Git::BaseError)
InvalidRef = Class.new(::Gitlab::Git::BaseError)
@@ -101,6 +102,8 @@ module Gitlab
def create_repository
wrapped_gitaly_errors do
gitaly_repository_client.create_repository
+ rescue GRPC::AlreadyExists => e
+ raise RepositoryExists, e.message
end
end
@@ -198,9 +201,9 @@ module Gitlab
# Returns an Array of Tags
#
- def tags(sort_by: nil)
+ def tags(sort_by: nil, pagination_params: nil)
wrapped_gitaly_errors do
- gitaly_ref_client.tags(sort_by: sort_by)
+ gitaly_ref_client.tags(sort_by: sort_by, pagination_params: pagination_params)
end
end
@@ -519,6 +522,17 @@ module Gitlab
@refs_hash
end
+ # Returns matching refs for OID
+ #
+ # Limit of 0 means there is no limit.
+ def refs_by_oid(oid:, limit: 0)
+ wrapped_gitaly_errors do
+ gitaly_ref_client.find_refs_by_oid(oid: oid, limit: limit)
+ end
+ rescue CommandError, TypeError, NoRepository
+ nil
+ end
+
# Returns url for submodule
#
# Ex.
@@ -784,6 +798,12 @@ module Gitlab
end
end
+ def list_refs
+ wrapped_gitaly_errors do
+ gitaly_ref_client.list_refs
+ end
+ end
+
# Refactoring aid; allows us to copy code from app/models/repository.rb
def commit(ref = 'HEAD')
Gitlab::Git::Commit.find(self, ref)
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index 2c26da037da..cc3f20ab774 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -24,7 +24,6 @@ module Gitlab
end
end
- PEM_REGEX = /\-+BEGIN CERTIFICATE\-+.+?\-+END CERTIFICATE\-+/m.freeze
SERVER_VERSION_FILE = 'GITALY_SERVER_VERSION'
MAXIMUM_GITALY_CALLS = 30
CLIENT_NAME = (Gitlab::Runtime.sidekiq? ? 'gitlab-sidekiq' : 'gitlab-web').freeze
@@ -57,33 +56,15 @@ module Gitlab
# https://gitlab.com/gitlab-org/gitaly/-/blob/bf9f52bc/client/dial.go#L78
{
'grpc.keepalive_time_ms': 20000,
- 'grpc.keepalive_permit_without_calls': 1
+ 'grpc.keepalive_permit_without_calls': 1,
+ 'grpc.http2.max_pings_without_data': 0
}
end
private_class_method :channel_args
- def self.stub_cert_paths
- cert_paths = Dir["#{OpenSSL::X509::DEFAULT_CERT_DIR}/*"]
- cert_paths << OpenSSL::X509::DEFAULT_CERT_FILE if File.exist? OpenSSL::X509::DEFAULT_CERT_FILE
- cert_paths
- end
-
- def self.stub_certs
- return @certs if @certs
-
- @certs = stub_cert_paths.flat_map do |cert_file|
- File.read(cert_file).scan(PEM_REGEX).map do |cert|
- OpenSSL::X509::Certificate.new(cert).to_pem
- rescue OpenSSL::OpenSSLError => e
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, cert_file: cert_file)
- nil
- end.compact
- end.uniq.join("\n")
- end
-
def self.stub_creds(storage)
if URI(address(storage)).scheme == 'tls'
- GRPC::Core::ChannelCredentials.new stub_certs
+ GRPC::Core::ChannelCredentials.new ::Gitlab::X509::Certificate.ca_certs_bundle
else
:this_channel_is_insecure
end
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 75588ad980c..7c688044e9c 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -205,6 +205,8 @@ module Gitlab
end
def between(from, to)
+ return list_commits(["^" + from, to], reverse: true) if Feature.enabled?(:between_commits_via_list_commits)
+
request = Gitaly::CommitsBetweenRequest.new(
repository: @gitaly_repo,
from: from,
diff --git a/lib/gitlab/gitaly_client/ref_service.rb b/lib/gitlab/gitaly_client/ref_service.rb
index 235eef4575e..c064811b1e7 100644
--- a/lib/gitlab/gitaly_client/ref_service.rb
+++ b/lib/gitlab/gitaly_client/ref_service.rb
@@ -77,8 +77,8 @@ module Gitlab
consume_find_local_branches_response(response)
end
- def tags(sort_by: nil)
- request = Gitaly::FindAllTagsRequest.new(repository: @gitaly_repo)
+ def tags(sort_by: nil, pagination_params: nil)
+ request = Gitaly::FindAllTagsRequest.new(repository: @gitaly_repo, pagination_params: pagination_params)
request.sort_by = sort_tags_by_param(sort_by) if sort_by
response = GitalyClient.call(@storage, :ref_service, :find_all_tags, request, timeout: GitalyClient.medium_timeout)
@@ -194,18 +194,39 @@ module Gitlab
raise ArgumentError, ex
end
+ def list_refs(patterns = [Gitlab::Git::BRANCH_REF_PREFIX])
+ request = Gitaly::ListRefsRequest.new(
+ repository: @gitaly_repo,
+ patterns: patterns
+ )
+
+ response = GitalyClient.call(@storage, :ref_service, :list_refs, request, timeout: GitalyClient.fast_timeout)
+ consume_list_refs_response(response)
+ end
+
def pack_refs
request = Gitaly::PackRefsRequest.new(repository: @gitaly_repo)
GitalyClient.call(@storage, :ref_service, :pack_refs, request, timeout: GitalyClient.long_timeout)
end
+ def find_refs_by_oid(oid:, limit:)
+ request = Gitaly::FindRefsByOIDRequest.new(repository: @gitaly_repo, sort_field: :refname, oid: oid, limit: limit)
+
+ response = GitalyClient.call(@storage, :ref_service, :find_refs_by_oid, request, timeout: GitalyClient.medium_timeout)
+ response&.refs&.to_a
+ end
+
private
def consume_refs_response(response)
response.flat_map { |message| message.names.map { |name| yield(name) } }
end
+ def consume_list_refs_response(response)
+ response.flat_map(&:references)
+ end
+
def sort_local_branches_by_param(sort_by)
sort_by = 'name' if sort_by == 'name_asc'
diff --git a/lib/gitlab/github_import/bulk_importing.rb b/lib/gitlab/github_import/bulk_importing.rb
index 80f8f8bfbe2..28a39128ec9 100644
--- a/lib/gitlab/github_import/bulk_importing.rb
+++ b/lib/gitlab/github_import/bulk_importing.rb
@@ -30,7 +30,7 @@ module Gitlab
# Bulk inserts the given rows into the database.
def bulk_insert(model, rows, batch_size: 100)
rows.each_slice(batch_size) do |slice|
- Gitlab::Database.main.bulk_insert(model.table_name, slice) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(model.table_name, slice) # rubocop:disable Gitlab/BulkInsert
log_and_increment_counter(slice.size, :imported)
end
diff --git a/lib/gitlab/github_import/importer/diff_note_importer.rb b/lib/gitlab/github_import/importer/diff_note_importer.rb
index 4cfc920e2e3..0aa0896aa57 100644
--- a/lib/gitlab/github_import/importer/diff_note_importer.rb
+++ b/lib/gitlab/github_import/importer/diff_note_importer.rb
@@ -4,41 +4,64 @@ module Gitlab
module GithubImport
module Importer
class DiffNoteImporter
- attr_reader :note, :project, :client, :user_finder
-
- # note - An instance of `Gitlab::GithubImport::Representation::DiffNote`.
- # project - An instance of `Project`.
- # client - An instance of `Gitlab::GithubImport::Client`.
+ # note - An instance of `Gitlab::GithubImport::Representation::DiffNote`
+ # project - An instance of `Project`
+ # client - An instance of `Gitlab::GithubImport::Client`
def initialize(note, project, client)
@note = note
@project = project
@client = client
- @user_finder = GithubImport::UserFinder.new(project, client)
end
def execute
- return unless (mr_id = find_merge_request_id)
+ return if merge_request_id.blank?
- author_id, author_found = user_finder.author_id_for(note)
+ note.project = project
+ note.merge_request = merge_request
- note_body = MarkdownText.format(note.note, note.author, author_found)
+ build_author_attributes
- attributes = {
- discussion_id: Discussion.discussion_id(note),
- noteable_type: 'MergeRequest',
- noteable_id: mr_id,
- project_id: project.id,
- author_id: author_id,
- note: note_body,
- system: false,
- commit_id: note.original_commit_id,
- line_code: note.line_code,
- type: 'LegacyDiffNote',
- created_at: note.created_at,
- updated_at: note.updated_at,
- st_diff: note.diff_hash.to_yaml
- }
+ # Diff notes with suggestions are imported with DiffNote, which is
+ # slower to import than LegacyDiffNote. Importing DiffNote is slower
+ # because it cannot use the BulkImporting strategy, which skips
+ # callbacks and validations. For this reason, notes that don't have
+ # suggestions are still imported with LegacyDiffNote
+ if import_with_diff_note?
+ import_with_diff_note
+ else
+ import_with_legacy_diff_note
+ end
+ rescue ActiveRecord::InvalidForeignKey => e
+ # It's possible the project and the issue have been deleted since
+ # scheduling this job. In this case we'll just skip creating the note
+ Logger.info(
+ message: e.message,
+ github_identifiers: note.github_identifiers
+ )
+ end
+ private
+
+ attr_reader :note, :project, :client, :author_id, :author_found
+
+ def import_with_diff_note?
+ note.contains_suggestion? && use_diff_note_with_suggestions_enabled?
+ end
+
+ def use_diff_note_with_suggestions_enabled?
+ Feature.enabled?(
+ :github_importer_use_diff_note_with_suggestions,
+ default_enabled: :yaml
+ )
+ end
+
+ def build_author_attributes
+ @author_id, @author_found = user_finder.author_id_for(note)
+ end
+
+ # rubocop:disable Gitlab/BulkInsert
+ def import_with_legacy_diff_note
+ log_diff_note_creation('LegacyDiffNote')
# It's possible that during an import we'll insert tens of thousands
# of diff notes. If we were to use the Note/LegacyDiffNote model here
# we'd also have to run additional queries for both validations and
@@ -47,15 +70,70 @@ module Gitlab
# To work around this we're using bulk_insert with a single row. This
# allows us to efficiently insert data (even if it's just 1 row)
# without having to use all sorts of hacks to disable callbacks.
- Gitlab::Database.main.bulk_insert(LegacyDiffNote.table_name, [attributes]) # rubocop:disable Gitlab/BulkInsert
- rescue ActiveRecord::InvalidForeignKey
- # It's possible the project and the issue have been deleted since
- # scheduling this job. In this case we'll just skip creating the note.
+ ApplicationRecord.legacy_bulk_insert(LegacyDiffNote.table_name, [{
+ noteable_type: note.noteable_type,
+ system: false,
+ type: 'LegacyDiffNote',
+ discussion_id: note.discussion_id,
+ noteable_id: merge_request_id,
+ project_id: project.id,
+ author_id: author_id,
+ note: note_body,
+ commit_id: note.original_commit_id,
+ line_code: note.line_code,
+ created_at: note.created_at,
+ updated_at: note.updated_at,
+ st_diff: note.diff_hash.to_yaml
+ }])
+ end
+ # rubocop:enabled Gitlab/BulkInsert
+
+ def import_with_diff_note
+ log_diff_note_creation('DiffNote')
+
+ ::Import::Github::Notes::CreateService.new(project, author, {
+ noteable_type: note.noteable_type,
+ system: false,
+ type: 'DiffNote',
+ noteable_id: merge_request_id,
+ project_id: project.id,
+ note: note_body,
+ discussion_id: note.discussion_id,
+ commit_id: note.original_commit_id,
+ created_at: note.created_at,
+ updated_at: note.updated_at,
+ position: note.diff_position
+ }).execute
+ end
+
+ def note_body
+ @note_body ||= MarkdownText.format(note.note, note.author, author_found)
+ end
+
+ def author
+ @author ||= User.find(author_id)
+ end
+
+ def merge_request
+ @merge_request ||= MergeRequest.find(merge_request_id)
end
# Returns the ID of the merge request this note belongs to.
- def find_merge_request_id
- GithubImport::IssuableFinder.new(project, note).database_id
+ def merge_request_id
+ @merge_request_id ||= GithubImport::IssuableFinder.new(project, note).database_id
+ end
+
+ def user_finder
+ @user_finder ||= GithubImport::UserFinder.new(project, client)
+ end
+
+ def log_diff_note_creation(model)
+ Logger.info(
+ project_id: project.id,
+ importer: self.class.name,
+ github_identifiers: note.github_identifiers,
+ model: model
+ )
end
end
end
diff --git a/lib/gitlab/github_import/importer/issue_importer.rb b/lib/gitlab/github_import/importer/issue_importer.rb
index f8665676ccf..7f46615f17e 100644
--- a/lib/gitlab/github_import/importer/issue_importer.rb
+++ b/lib/gitlab/github_import/importer/issue_importer.rb
@@ -75,7 +75,7 @@ module Gitlab
end
end
- Gitlab::Database.main.bulk_insert(IssueAssignee.table_name, assignees) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(IssueAssignee.table_name, assignees) # rubocop:disable Gitlab/BulkInsert
end
end
end
diff --git a/lib/gitlab/github_import/importer/label_links_importer.rb b/lib/gitlab/github_import/importer/label_links_importer.rb
index b608bb48e38..5e248c7cfc5 100644
--- a/lib/gitlab/github_import/importer/label_links_importer.rb
+++ b/lib/gitlab/github_import/importer/label_links_importer.rb
@@ -40,7 +40,7 @@ module Gitlab
}
end
- Gitlab::Database.main.bulk_insert(LabelLink.table_name, rows) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(LabelLink.table_name, rows) # rubocop:disable Gitlab/BulkInsert
end
def find_target_id
diff --git a/lib/gitlab/github_import/importer/note_importer.rb b/lib/gitlab/github_import/importer/note_importer.rb
index 1fd42a69fac..2cc3a82dd9b 100644
--- a/lib/gitlab/github_import/importer/note_importer.rb
+++ b/lib/gitlab/github_import/importer/note_importer.rb
@@ -37,7 +37,7 @@ module Gitlab
# We're using bulk_insert here so we can bypass any validations and
# callbacks. Running these would result in a lot of unnecessary SQL
# queries being executed when importing large projects.
- Gitlab::Database.main.bulk_insert(Note.table_name, [attributes]) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(Note.table_name, [attributes]) # rubocop:disable Gitlab/BulkInsert
rescue ActiveRecord::InvalidForeignKey
# It's possible the project and the issue have been deleted since
# scheduling this job. In this case we'll just skip creating the note.
diff --git a/lib/gitlab/github_import/importer/pull_requests_merged_by_importer.rb b/lib/gitlab/github_import/importer/pull_requests_merged_by_importer.rb
index 287e0ea7f7f..c56b391cbec 100644
--- a/lib/gitlab/github_import/importer/pull_requests_merged_by_importer.rb
+++ b/lib/gitlab/github_import/importer/pull_requests_merged_by_importer.rb
@@ -31,9 +31,7 @@ module Gitlab
end
def each_object_to_import
- project.merge_requests.with_state(:merged).find_each do |merge_request|
- next if already_imported?(merge_request)
-
+ merge_requests_to_import.find_each do |merge_request|
Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched)
pull_request = client.pull_request(project.import_source, merge_request.iid)
@@ -42,6 +40,17 @@ module Gitlab
mark_as_imported(merge_request)
end
end
+
+ private
+
+ # Returns only the merge requests that still have merged_by to be imported.
+ def merge_requests_to_import
+ project.merge_requests.id_not_in(already_imported_objects).with_state(:merged)
+ end
+
+ def already_imported_objects
+ Gitlab::Cache::Import::Caching.values_from_set(already_imported_cache_key)
+ end
end
end
end
diff --git a/lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb b/lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb
index bd65eb5899c..5e55d09fe3d 100644
--- a/lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb
+++ b/lib/gitlab/github_import/importer/pull_requests_reviews_importer.rb
@@ -86,7 +86,7 @@ module Gitlab
# Returns only the merge requests that still have reviews to be imported.
def merge_requests_to_import
- project.merge_requests.where.not(id: already_imported_merge_requests) # rubocop: disable CodeReuse/ActiveRecord
+ project.merge_requests.id_not_in(already_imported_merge_requests)
end
def already_imported_merge_requests
diff --git a/lib/gitlab/github_import/representation/diff_note.rb b/lib/gitlab/github_import/representation/diff_note.rb
index a3dcd2e380c..fecff0644c2 100644
--- a/lib/gitlab/github_import/representation/diff_note.rb
+++ b/lib/gitlab/github_import/representation/diff_note.rb
@@ -7,13 +7,14 @@ module Gitlab
include ToHash
include ExposeAttribute
- attr_reader :attributes
-
- expose_attribute :noteable_type, :noteable_id, :commit_id, :file_path,
- :diff_hunk, :author, :note, :created_at, :updated_at,
- :original_commit_id, :note_id
-
+ NOTEABLE_TYPE = 'MergeRequest'
NOTEABLE_ID_REGEX = %r{/pull/(?<iid>\d+)}i.freeze
+ DISCUSSION_CACHE_KEY = 'github-importer/discussion-id-map/%{project_id}/%{noteable_id}/%{original_note_id}'
+
+ expose_attribute :noteable_id, :commit_id, :file_path,
+ :diff_hunk, :author, :created_at, :updated_at,
+ :original_commit_id, :note_id, :end_line, :start_line,
+ :side, :in_reply_to_id
# Builds a diff note from a GitHub API response.
#
@@ -30,7 +31,6 @@ module Gitlab
user = Representation::User.from_api_response(note.user) if note.user
hash = {
- noteable_type: 'MergeRequest',
noteable_id: matches[:iid].to_i,
file_path: note.path,
commit_id: note.commit_id,
@@ -42,7 +42,9 @@ module Gitlab
updated_at: note.updated_at,
note_id: note.id,
end_line: note.line,
- start_line: note.start_line
+ start_line: note.start_line,
+ side: note.side,
+ in_reply_to_id: note.in_reply_to_id
}
new(hash)
@@ -56,21 +58,41 @@ module Gitlab
new(hash)
end
+ attr_accessor :merge_request, :project
+
# attributes - A Hash containing the raw note details. The keys of this
# Hash must be Symbols.
def initialize(attributes)
@attributes = attributes
+
+ @note_formatter = DiffNotes::SuggestionFormatter.new(
+ note: attributes[:note],
+ start_line: attributes[:start_line],
+ end_line: attributes[:end_line]
+ )
+ end
+
+ def noteable_type
+ NOTEABLE_TYPE
+ end
+
+ def contains_suggestion?
+ @note_formatter.contains_suggestion?
+ end
+
+ def note
+ @note_formatter.formatted_note
end
def line_code
diff_line = Gitlab::Diff::Parser.new.parse(diff_hunk.lines).to_a.last
- Gitlab::Git
- .diff_line_code(file_path, diff_line.new_pos, diff_line.old_pos)
+ Gitlab::Git.diff_line_code(file_path, diff_line.new_pos, diff_line.old_pos)
end
# Returns a Hash that can be used to populate `notes.st_diff`, removing
# the need for requesting Git data for every diff note.
+ # Used when importing with LegacyDiffNote
def diff_hash
{
diff: diff_hunk,
@@ -85,12 +107,15 @@ module Gitlab
}
end
- def note
- @note ||= DiffNotes::SuggestionFormatter.formatted_note_for(
- note: attributes[:note],
- start_line: attributes[:start_line],
- end_line: attributes[:end_line]
- )
+ # Used when importing with DiffNote
+ def diff_position
+ position_params = {
+ diff_refs: merge_request.diff_refs,
+ old_path: file_path,
+ new_path: file_path
+ }
+
+ Gitlab::Diff::Position.new(position_params.merge(diff_line_params))
end
def github_identifiers
@@ -100,6 +125,53 @@ module Gitlab
noteable_type: noteable_type
}
end
+
+ def discussion_id
+ if in_reply_to_id.present?
+ current_discussion_id
+ else
+ Discussion.discussion_id(
+ Struct
+ .new(:noteable_id, :noteable_type)
+ .new(merge_request.id, NOTEABLE_TYPE)
+ ).tap do |discussion_id|
+ cache_discussion_id(discussion_id)
+ end
+ end
+ end
+
+ private
+
+ # Required by ExposeAttribute
+ attr_reader :attributes
+
+ def diff_line_params
+ if addition?
+ { new_line: end_line, old_line: nil }
+ else
+ { new_line: nil, old_line: end_line }
+ end
+ end
+
+ def addition?
+ side == 'RIGHT'
+ end
+
+ def cache_discussion_id(discussion_id)
+ Gitlab::Cache::Import::Caching.write(discussion_id_cache_key(note_id), discussion_id)
+ end
+
+ def current_discussion_id
+ Gitlab::Cache::Import::Caching.read(discussion_id_cache_key(in_reply_to_id))
+ end
+
+ def discussion_id_cache_key(id)
+ DISCUSSION_CACHE_KEY % {
+ project_id: project.id,
+ noteable_id: merge_request.id,
+ original_note_id: id
+ }
+ end
end
end
end
diff --git a/lib/gitlab/github_import/representation/diff_notes/suggestion_formatter.rb b/lib/gitlab/github_import/representation/diff_notes/suggestion_formatter.rb
index 4e5855ee4cd..38b15c4b5bb 100644
--- a/lib/gitlab/github_import/representation/diff_notes/suggestion_formatter.rb
+++ b/lib/gitlab/github_import/representation/diff_notes/suggestion_formatter.rb
@@ -10,30 +10,38 @@ module Gitlab
module Representation
module DiffNotes
class SuggestionFormatter
+ include Gitlab::Utils::StrongMemoize
+
# A github suggestion:
# - the ```suggestion tag must be the first text of the line
# - it might have up to 3 spaces before the ```suggestion tag
# - extra text on the ```suggestion tag line will be ignored
GITHUB_SUGGESTION = /^\ {,3}(?<suggestion>```suggestion\b).*(?<eol>\R)/.freeze
- def self.formatted_note_for(...)
- new(...).formatted_note
- end
-
def initialize(note:, start_line: nil, end_line: nil)
@note = note
@start_line = start_line
@end_line = end_line
end
+ # Returns a tuple with:
+ # - a boolean indicating if the note has suggestions
+ # - the note with the suggestion formatted for Gitlab
def formatted_note
- if contains_suggestion?
- note.gsub(
- GITHUB_SUGGESTION,
- "\\k<suggestion>:#{suggestion_range}\\k<eol>"
- )
- else
- note
+ @formatted_note ||=
+ if contains_suggestion?
+ note.gsub(
+ GITHUB_SUGGESTION,
+ "\\k<suggestion>:#{suggestion_range}\\k<eol>"
+ )
+ else
+ note
+ end
+ end
+
+ def contains_suggestion?
+ strong_memoize(:contain_suggestion) do
+ note.to_s.match?(GITHUB_SUGGESTION)
end
end
@@ -41,10 +49,6 @@ module Gitlab
attr_reader :note, :start_line, :end_line
- def contains_suggestion?
- note.to_s.match?(GITHUB_SUGGESTION)
- end
-
# Github always saves the comment on the _last_ line of the range.
# Therefore, the diff hunk will always be related to lines before
# the comment itself.
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index 9f628a10771..9ad902efb3a 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -39,6 +39,7 @@ module Gitlab
gon.ee = Gitlab.ee?
gon.jh = Gitlab.jh?
gon.dot_com = Gitlab.com?
+ gon.dev_env_or_com = Gitlab.dev_env_or_com?
if current_user
gon.current_user_id = current_user.id
@@ -55,7 +56,8 @@ module Gitlab
push_frontend_feature_flag(:security_auto_fix, default_enabled: false)
push_frontend_feature_flag(:improved_emoji_picker, default_enabled: :yaml)
push_frontend_feature_flag(:new_header_search, default_enabled: :yaml)
- push_frontend_feature_flag(:suppress_apollo_errors_during_navigation, current_user, default_enabled: :yaml)
+ push_frontend_feature_flag(:configure_iac_scanning_via_mr, current_user, default_enabled: :yaml)
+ push_frontend_feature_flag(:bootstrap_confirmation_modals, default_enabled: :yaml)
end
# Exposes the state of a feature flag to the frontend code.
diff --git a/lib/gitlab/gpg/commit.rb b/lib/gitlab/gpg/commit.rb
index 1abbd6dc45b..9a6317e2b76 100644
--- a/lib/gitlab/gpg/commit.rb
+++ b/lib/gitlab/gpg/commit.rb
@@ -48,7 +48,7 @@ module Gitlab
if gpg_key
Gitlab::Gpg::CurrentKeyChain.add(gpg_key.key)
- clear_memoization(:verified_signature)
+ clear_memoization(:gpg_signatures)
end
yield gpg_key
@@ -56,16 +56,7 @@ module Gitlab
end
def verified_signature
- strong_memoize(:verified_signature) { gpgme_signature }
- end
-
- def gpgme_signature
- GPGME::Crypto.new.verify(signature_text, signed_text: signed_text) do |verified_signature|
- # Return the first signature for now: https://gitlab.com/gitlab-org/gitlab-foss/issues/54932
- break verified_signature
- end
- rescue GPGME::Error
- nil
+ gpg_signatures.first
end
def create_cached_signature!
@@ -77,6 +68,24 @@ module Gitlab
end
end
+ def gpg_signatures
+ strong_memoize(:gpg_signatures) do
+ signatures = []
+
+ GPGME::Crypto.new.verify(signature_text, signed_text: signed_text) do |verified_signature|
+ signatures << verified_signature
+ end
+
+ signatures
+ rescue GPGME::Error
+ []
+ end
+ end
+
+ def multiple_signatures?
+ gpg_signatures.size > 1
+ end
+
def attributes(gpg_key)
user_infos = user_infos(gpg_key)
verification_status = verification_status(gpg_key)
@@ -93,6 +102,7 @@ module Gitlab
end
def verification_status(gpg_key)
+ return :multiple_signatures if multiple_signatures? && Feature.enabled?(:multiple_gpg_signatures, @commit.project, default_enabled: :yaml)
return :unknown_key unless gpg_key
return :unverified_key unless gpg_key.verified?
return :unverified unless verified_signature&.valid?
diff --git a/lib/gitlab/grape_logging/loggers/urgency_logger.rb b/lib/gitlab/grape_logging/loggers/urgency_logger.rb
new file mode 100644
index 00000000000..0a503086d05
--- /dev/null
+++ b/lib/gitlab/grape_logging/loggers/urgency_logger.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GrapeLogging
+ module Loggers
+ class UrgencyLogger < ::GrapeLogging::Loggers::Base
+ def parameters(request, _)
+ endpoint = request.env['api.endpoint']
+ return {} unless endpoint
+
+ urgency = endpoint.options[:for].try(:urgency_for_app, endpoint)
+ return {} unless urgency
+
+ { request_urgency: urgency.name, target_duration_s: urgency.duration }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/known_operations.rb b/lib/gitlab/graphql/known_operations.rb
new file mode 100644
index 00000000000..ead52935945
--- /dev/null
+++ b/lib/gitlab/graphql/known_operations.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ class KnownOperations
+ Operation = Struct.new(:name) do
+ def to_caller_id
+ "graphql:#{name}"
+ end
+
+ def query_urgency
+ # We'll be able to actually correlate query_urgency with https://gitlab.com/gitlab-org/gitlab/-/issues/345141
+ ::Gitlab::EndpointAttributes::DEFAULT_URGENCY
+ end
+ end
+
+ ANONYMOUS = Operation.new("anonymous").freeze
+ UNKNOWN = Operation.new("unknown").freeze
+
+ def self.default
+ @default ||= self.new(Gitlab::Webpack::GraphqlKnownOperations.load)
+ end
+
+ def initialize(operation_names)
+ @operation_hash = operation_names
+ .map { |name| Operation.new(name).freeze }
+ .concat([ANONYMOUS, UNKNOWN])
+ .index_by(&:name)
+ end
+
+ # Returns the known operation from the given ::GraphQL::Query object
+ def from_query(query)
+ operation_name = query.selected_operation_name
+
+ return ANONYMOUS unless operation_name
+
+ @operation_hash[operation_name] || UNKNOWN
+ end
+
+ def operations
+ @operation_hash.values
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/loaders/full_path_model_loader.rb b/lib/gitlab/graphql/loaders/full_path_model_loader.rb
index 7f9013c6e4c..2ea3fa71d5e 100644
--- a/lib/gitlab/graphql/loaders/full_path_model_loader.rb
+++ b/lib/gitlab/graphql/loaders/full_path_model_loader.rb
@@ -16,8 +16,11 @@ module Gitlab
def find
BatchLoader::GraphQL.for(full_path).batch(key: model_class) do |full_paths, loader, args|
+ scope = args[:key]
+ # this logic cannot be placed in the NamespaceResolver due to N+1
+ scope = scope.without_project_namespaces if scope == Namespace
# `with_route` avoids an N+1 calculating full_path
- args[:key].where_full_path_in(full_paths).with_route.each do |model_instance|
+ scope.where_full_path_in(full_paths).with_route.each do |model_instance|
loader.call(model_instance.full_path.downcase, model_instance)
end
end
diff --git a/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb b/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb
index 5a9d21e7469..15f95edd318 100644
--- a/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb
+++ b/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb
@@ -76,7 +76,7 @@ module Gitlab
def items
original_items = super
- return original_items if Gitlab::Pagination::Keyset::Order.keyset_aware?(original_items) || Feature.disabled?(:new_graphql_keyset_pagination)
+ return original_items if Feature.disabled?(:new_graphql_keyset_pagination, default_enabled: :yaml) || Gitlab::Pagination::Keyset::Order.keyset_aware?(original_items)
strong_memoize(:generic_keyset_pagination_items) do
rebuilt_items_with_keyset_order, success = Gitlab::Pagination::Keyset::SimpleOrderBuilder.build(original_items)
diff --git a/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb b/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb
index b8d2f5b0f29..207324e73bd 100644
--- a/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb
+++ b/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb
@@ -10,15 +10,10 @@ module Gitlab
ALL_ANALYZERS = [COMPLEXITY_ANALYZER, DEPTH_ANALYZER, FIELD_USAGE_ANALYZER].freeze
def initial_value(query)
- variables = process_variables(query.provided_variables)
- default_initial_values(query).merge({
- operation_name: query.operation_name,
- query_string: query.query_string,
- variables: variables
- })
- rescue StandardError => e
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
- default_initial_values(query)
+ {
+ time_started: Gitlab::Metrics::System.monotonic_time,
+ query: query
+ }
end
def call(memo, *)
@@ -28,25 +23,42 @@ module Gitlab
def final_value(memo)
return if memo.nil?
- complexity, depth, field_usages = GraphQL::Analysis.analyze_query(memo[:query], ALL_ANALYZERS)
+ query = memo[:query]
+ complexity, depth, field_usages = GraphQL::Analysis.analyze_query(query, ALL_ANALYZERS)
memo[:depth] = depth
memo[:complexity] = complexity
# This duration is not the execution time of the
# query but the execution time of the analyzer.
- memo[:duration_s] = duration(memo[:time_started]).round(1)
+ memo[:duration_s] = duration(memo[:time_started])
memo[:used_fields] = field_usages.first
memo[:used_deprecated_fields] = field_usages.second
- RequestStore.store[:graphql_logs] ||= []
- RequestStore.store[:graphql_logs] << memo
- GraphqlLogger.info(memo.except!(:time_started, :query))
+ push_to_request_store(memo)
+
+ # This gl_analysis is included in the tracer log
+ query.context[:gl_analysis] = memo.except!(:time_started, :query)
rescue StandardError => e
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
end
private
+ def push_to_request_store(memo)
+ query = memo[:query]
+
+ # TODO: This RequestStore management is used to handle setting request wide metadata
+ # to improve preexisting logging. We should handle this either with ApplicationContext
+ # or in a separate tracer.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/343802
+
+ RequestStore.store[:graphql_logs] ||= []
+ RequestStore.store[:graphql_logs] << memo.except(:time_started, :duration_s, :query).merge({
+ variables: process_variables(query.provided_variables),
+ operation_name: query.operation_name
+ })
+ end
+
def process_variables(variables)
filtered_variables = filter_sensitive_variables(variables)
@@ -66,16 +78,6 @@ module Gitlab
def duration(time_started)
Gitlab::Metrics::System.monotonic_time - time_started
end
-
- def default_initial_values(query)
- {
- time_started: Gitlab::Metrics::System.monotonic_time,
- query_string: nil,
- query: query,
- variables: nil,
- duration_s: nil
- }
- end
end
end
end
diff --git a/lib/gitlab/graphql/tracers/application_context_tracer.rb b/lib/gitlab/graphql/tracers/application_context_tracer.rb
new file mode 100644
index 00000000000..4193c46e321
--- /dev/null
+++ b/lib/gitlab/graphql/tracers/application_context_tracer.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Tracers
+ # This graphql-ruby tracer sets up `ApplicationContext` for certain operations.
+ class ApplicationContextTracer
+ def self.use(schema)
+ schema.tracer(self.new)
+ end
+
+ # See docs on expected interface for trace
+ # https://graphql-ruby.org/api-doc/1.12.17/GraphQL/Tracing
+ def trace(key, data)
+ case key
+ when "execute_query"
+ operation = known_operation(data)
+
+ ::Gitlab::ApplicationContext.with_context(caller_id: operation.to_caller_id) do
+ yield
+ end
+ else
+ yield
+ end
+ end
+
+ private
+
+ def known_operation(data)
+ # The library guarantees that we should have :query for execute_query, but we're being defensive here
+ query = data.fetch(:query, nil)
+
+ return ::Gitlab::Graphql::KnownOperations.UNKNOWN unless query
+
+ ::Gitlab::Graphql::KnownOperations.default.from_query(query)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/tracers/logger_tracer.rb b/lib/gitlab/graphql/tracers/logger_tracer.rb
new file mode 100644
index 00000000000..c7ba56824db
--- /dev/null
+++ b/lib/gitlab/graphql/tracers/logger_tracer.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Tracers
+ # This tracer writes logs for certain trace events.
+ # It reads duration metadata written by TimerTracer.
+ class LoggerTracer
+ def self.use(schema)
+ schema.tracer(self.new)
+ end
+
+ def trace(key, data)
+ result = yield
+
+ case key
+ when "execute_query"
+ log_execute_query(**data)
+ end
+
+ result
+ end
+
+ private
+
+ def log_execute_query(query: nil, duration_s: 0)
+ # execute_query should always have :query, but we're just being defensive
+ return unless query
+
+ analysis_info = query.context[:gl_analysis]&.transform_keys { |key| "query_analysis.#{key}" }
+ info = {
+ trace_type: 'execute_query',
+ query_fingerprint: query.fingerprint,
+ duration_s: duration_s,
+ operation_name: query.operation_name,
+ operation_fingerprint: query.operation_fingerprint,
+ is_mutation: query.mutation?,
+ variables: clean_variables(query.provided_variables),
+ query_string: query.query_string
+ }
+
+ info.merge!(::Gitlab::ApplicationContext.current)
+ info.merge!(analysis_info) if analysis_info
+
+ ::Gitlab::GraphqlLogger.info(info)
+ end
+
+ def clean_variables(variables)
+ filtered = ActiveSupport::ParameterFilter
+ .new(::Rails.application.config.filter_parameters)
+ .filter(variables)
+
+ filtered&.to_s
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/tracers/metrics_tracer.rb b/lib/gitlab/graphql/tracers/metrics_tracer.rb
new file mode 100644
index 00000000000..9fc001c0a6d
--- /dev/null
+++ b/lib/gitlab/graphql/tracers/metrics_tracer.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Tracers
+ class MetricsTracer
+ def self.use(schema)
+ schema.tracer(self.new)
+ end
+
+ # See https://graphql-ruby.org/api-doc/1.12.16/GraphQL/Tracing for full list of events
+ def trace(key, data)
+ result = yield
+
+ case key
+ when "execute_query"
+ increment_query_sli(data)
+ end
+
+ result
+ end
+
+ private
+
+ def increment_query_sli(data)
+ duration_s = data.fetch(:duration_s, nil)
+ query = data.fetch(:query, nil)
+
+ # We're just being defensive here...
+ # duration_s comes from TimerTracer and we should be pretty much guaranteed it exists
+ return unless duration_s && query
+
+ operation = ::Gitlab::Graphql::KnownOperations.default.from_query(query)
+ query_urgency = operation.query_urgency
+
+ Gitlab::Metrics::RailsSlis.graphql_query_apdex.increment(
+ labels: {
+ endpoint_id: ::Gitlab::ApplicationContext.current_context_attribute(:caller_id),
+ feature_category: ::Gitlab::ApplicationContext.current_context_attribute(:feature_category),
+ query_urgency: query_urgency.name
+ },
+ success: duration_s <= query_urgency.duration
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/tracers/timer_tracer.rb b/lib/gitlab/graphql/tracers/timer_tracer.rb
new file mode 100644
index 00000000000..326620a22bc
--- /dev/null
+++ b/lib/gitlab/graphql/tracers/timer_tracer.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Tracers
+ # This graphql-ruby tracer records duration for trace events and merges
+ # the duration into the trace event's metadata. This way, separate tracers
+ # can all use the same duration information.
+ #
+ # NOTE: TimerTracer should be applied last **after** other tracers, so
+ # that it runs first (similar to function composition)
+ class TimerTracer
+ def self.use(schema)
+ schema.tracer(self.new)
+ end
+
+ def trace(key, data)
+ start_time = Gitlab::Metrics::System.monotonic_time
+
+ result = yield
+
+ duration_s = Gitlab::Metrics::System.monotonic_time - start_time
+
+ data[:duration_s] = duration_s
+
+ result
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/variables.rb b/lib/gitlab/graphql/variables.rb
index e17ca56d022..102a269dd5b 100644
--- a/lib/gitlab/graphql/variables.rb
+++ b/lib/gitlab/graphql/variables.rb
@@ -24,8 +24,13 @@ module Gitlab
else
{}
end
- when Hash, ActionController::Parameters
+ when Hash
ambiguous_param
+ when ActionController::Parameters
+ # We can and have to trust the "Parameters" because `graphql-ruby` handles this hash safely
+ # Also, `graphql-ruby` uses hash-specific methods, for example `size`:
+ # https://sourcegraph.com/github.com/rmosolgo/graphql-ruby@61232b03412df6685406fc46c414e11d3f447817/-/blob/lib/graphql/query.rb?L304
+ ambiguous_param.to_unsafe_h
when nil
{}
else
diff --git a/lib/gitlab/health_checks/metric.rb b/lib/gitlab/health_checks/metric.rb
index b697cb0d027..c1e437831d7 100644
--- a/lib/gitlab/health_checks/metric.rb
+++ b/lib/gitlab/health_checks/metric.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
@@ -5,3 +6,5 @@ module Gitlab
Metric = Struct.new(:name, :value, :labels)
end
end
+
+# rubocop:enable Naming/FileName
diff --git a/lib/gitlab/health_checks/probes/status.rb b/lib/gitlab/health_checks/probes/status.rb
index 192e9366001..1c59f18ff7d 100644
--- a/lib/gitlab/health_checks/probes/status.rb
+++ b/lib/gitlab/health_checks/probes/status.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
@@ -12,3 +13,5 @@ module Gitlab
end
end
end
+
+# rubocop:enable Naming/FileName
diff --git a/lib/gitlab/health_checks/redis/cache_check.rb b/lib/gitlab/health_checks/redis/cache_check.rb
index 0c8fe83893b..bd843bdaac4 100644
--- a/lib/gitlab/health_checks/redis/cache_check.rb
+++ b/lib/gitlab/health_checks/redis/cache_check.rb
@@ -4,31 +4,7 @@ module Gitlab
module HealthChecks
module Redis
class CacheCheck
- extend SimpleAbstractCheck
-
- class << self
- def check_up
- check
- end
-
- private
-
- def metric_prefix
- 'redis_cache_ping'
- end
-
- def successful?(result)
- result == 'PONG'
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def check
- catch_timeout 10.seconds do
- Gitlab::Redis::Cache.with(&:ping)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
- end
+ extend RedisAbstractCheck
end
end
end
diff --git a/lib/gitlab/health_checks/redis/queues_check.rb b/lib/gitlab/health_checks/redis/queues_check.rb
index b1e33b9f459..fb92db937dc 100644
--- a/lib/gitlab/health_checks/redis/queues_check.rb
+++ b/lib/gitlab/health_checks/redis/queues_check.rb
@@ -4,31 +4,7 @@ module Gitlab
module HealthChecks
module Redis
class QueuesCheck
- extend SimpleAbstractCheck
-
- class << self
- def check_up
- check
- end
-
- private
-
- def metric_prefix
- 'redis_queues_ping'
- end
-
- def successful?(result)
- result == 'PONG'
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def check
- catch_timeout 10.seconds do
- Gitlab::Redis::Queues.with(&:ping)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
- end
+ extend RedisAbstractCheck
end
end
end
diff --git a/lib/gitlab/health_checks/redis/rate_limiting_check.rb b/lib/gitlab/health_checks/redis/rate_limiting_check.rb
index 67c14e26361..0e9d94f7dff 100644
--- a/lib/gitlab/health_checks/redis/rate_limiting_check.rb
+++ b/lib/gitlab/health_checks/redis/rate_limiting_check.rb
@@ -4,31 +4,7 @@ module Gitlab
module HealthChecks
module Redis
class RateLimitingCheck
- extend SimpleAbstractCheck
-
- class << self
- def check_up
- check
- end
-
- private
-
- def metric_prefix
- 'redis_rate_limiting_ping'
- end
-
- def successful?(result)
- result == 'PONG'
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def check
- catch_timeout 10.seconds do
- Gitlab::Redis::RateLimiting.with(&:ping)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
- end
+ extend RedisAbstractCheck
end
end
end
diff --git a/lib/gitlab/health_checks/redis/redis_abstract_check.rb b/lib/gitlab/health_checks/redis/redis_abstract_check.rb
new file mode 100644
index 00000000000..ecad4b06ea9
--- /dev/null
+++ b/lib/gitlab/health_checks/redis/redis_abstract_check.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module HealthChecks
+ module Redis
+ module RedisAbstractCheck
+ include SimpleAbstractCheck
+
+ def check_up
+ successful?(check)
+ end
+
+ private
+
+ def redis_instance_class_name
+ Gitlab::Redis.const_get(redis_instance_name.camelize, false)
+ end
+
+ def metric_prefix
+ "redis_#{redis_instance_name}_ping"
+ end
+
+ def redis_instance_name
+ name.sub(/_check$/, '')
+ end
+
+ def successful?(result)
+ result == 'PONG'
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def check
+ catch_timeout 10.seconds do
+ redis_instance_class_name.with(&:ping)
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/health_checks/redis/redis_check.rb b/lib/gitlab/health_checks/redis/redis_check.rb
index 25879c18f84..c793a939abd 100644
--- a/lib/gitlab/health_checks/redis/redis_check.rb
+++ b/lib/gitlab/health_checks/redis/redis_check.rb
@@ -14,16 +14,22 @@ module Gitlab
end
def successful?(result)
- result == 'PONG'
+ result == true
end
def check
- ::Gitlab::HealthChecks::Redis::CacheCheck.check_up &&
- ::Gitlab::HealthChecks::Redis::QueuesCheck.check_up &&
- ::Gitlab::HealthChecks::Redis::SharedStateCheck.check_up &&
- ::Gitlab::HealthChecks::Redis::TraceChunksCheck.check_up &&
- ::Gitlab::HealthChecks::Redis::RateLimitingCheck.check_up &&
- ::Gitlab::HealthChecks::Redis::SessionsCheck.check_up
+ redis_health_checks.all?(&:check_up)
+ end
+
+ def redis_health_checks
+ [
+ Gitlab::HealthChecks::Redis::CacheCheck,
+ Gitlab::HealthChecks::Redis::QueuesCheck,
+ Gitlab::HealthChecks::Redis::SharedStateCheck,
+ Gitlab::HealthChecks::Redis::TraceChunksCheck,
+ Gitlab::HealthChecks::Redis::RateLimitingCheck,
+ Gitlab::HealthChecks::Redis::SessionsCheck
+ ]
end
end
end
diff --git a/lib/gitlab/health_checks/redis/sessions_check.rb b/lib/gitlab/health_checks/redis/sessions_check.rb
index a0c5e177b4e..90a4c868f40 100644
--- a/lib/gitlab/health_checks/redis/sessions_check.rb
+++ b/lib/gitlab/health_checks/redis/sessions_check.rb
@@ -4,31 +4,7 @@ module Gitlab
module HealthChecks
module Redis
class SessionsCheck
- extend SimpleAbstractCheck
-
- class << self
- def check_up
- check
- end
-
- private
-
- def metric_prefix
- 'redis_sessions_ping'
- end
-
- def successful?(result)
- result == 'PONG'
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def check
- catch_timeout 10.seconds do
- Gitlab::Redis::Sessions.with(&:ping)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
- end
+ extend RedisAbstractCheck
end
end
end
diff --git a/lib/gitlab/health_checks/redis/shared_state_check.rb b/lib/gitlab/health_checks/redis/shared_state_check.rb
index 285ac271929..80f91784b8c 100644
--- a/lib/gitlab/health_checks/redis/shared_state_check.rb
+++ b/lib/gitlab/health_checks/redis/shared_state_check.rb
@@ -4,31 +4,7 @@ module Gitlab
module HealthChecks
module Redis
class SharedStateCheck
- extend SimpleAbstractCheck
-
- class << self
- def check_up
- check
- end
-
- private
-
- def metric_prefix
- 'redis_shared_state_ping'
- end
-
- def successful?(result)
- result == 'PONG'
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def check
- catch_timeout 10.seconds do
- Gitlab::Redis::SharedState.with(&:ping)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
- end
+ extend RedisAbstractCheck
end
end
end
diff --git a/lib/gitlab/health_checks/redis/trace_chunks_check.rb b/lib/gitlab/health_checks/redis/trace_chunks_check.rb
index cf9fa700b0a..9a89a1ce51d 100644
--- a/lib/gitlab/health_checks/redis/trace_chunks_check.rb
+++ b/lib/gitlab/health_checks/redis/trace_chunks_check.rb
@@ -4,31 +4,7 @@ module Gitlab
module HealthChecks
module Redis
class TraceChunksCheck
- extend SimpleAbstractCheck
-
- class << self
- def check_up
- check
- end
-
- private
-
- def metric_prefix
- 'redis_trace_chunks_ping'
- end
-
- def successful?(result)
- result == 'PONG'
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def check
- catch_timeout 10.seconds do
- Gitlab::Redis::TraceChunks.with(&:ping)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
- end
+ extend RedisAbstractCheck
end
end
end
diff --git a/lib/gitlab/health_checks/result.rb b/lib/gitlab/health_checks/result.rb
index 38a36100ec7..cbb847d2af2 100644
--- a/lib/gitlab/health_checks/result.rb
+++ b/lib/gitlab/health_checks/result.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
@@ -13,3 +14,5 @@ module Gitlab
end
end
end
+
+# rubocop:enable Naming/FileName
diff --git a/lib/gitlab/http.rb b/lib/gitlab/http.rb
index 8a19f208adf..1b860001ac0 100644
--- a/lib/gitlab/http.rb
+++ b/lib/gitlab/http.rb
@@ -15,7 +15,7 @@ module Gitlab
].freeze
HTTP_ERRORS = HTTP_TIMEOUT_ERRORS + [
EOFError, SocketError, OpenSSL::SSL::SSLError, OpenSSL::OpenSSLError,
- Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH,
+ Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH,
Gitlab::HTTP::BlockedUrlError, Gitlab::HTTP::RedirectionTooDeep
].freeze
diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb
index b090d05de19..251bc34d462 100644
--- a/lib/gitlab/i18n.rb
+++ b/lib/gitlab/i18n.rb
@@ -44,26 +44,26 @@ module Gitlab
'bg' => 0,
'cs_CZ' => 0,
'da_DK' => 52,
- 'de' => 16,
+ 'de' => 15,
'en' => 100,
'eo' => 0,
- 'es' => 41,
+ 'es' => 40,
'fil_PH' => 0,
'fr' => 11,
'gl_ES' => 0,
'id_ID' => 0,
'it' => 2,
- 'ja' => 37,
+ 'ja' => 36,
'ko' => 11,
- 'nb_NO' => 35,
+ 'nb_NO' => 34,
'nl_NL' => 0,
'pl_PL' => 5,
- 'pt_BR' => 45,
+ 'pt_BR' => 49,
'ro_RO' => 24,
- 'ru' => 27,
- 'tr_TR' => 16,
- 'uk' => 40,
- 'zh_CN' => 95,
+ 'ru' => 26,
+ 'tr_TR' => 15,
+ 'uk' => 39,
+ 'zh_CN' => 97,
'zh_HK' => 2,
'zh_TW' => 3
}.freeze
diff --git a/lib/gitlab/import/database_helpers.rb b/lib/gitlab/import/database_helpers.rb
index e73c3afe9bd..96490db0c07 100644
--- a/lib/gitlab/import/database_helpers.rb
+++ b/lib/gitlab/import/database_helpers.rb
@@ -11,8 +11,8 @@ module Gitlab
# We use bulk_insert here so we can bypass any queries executed by
# callbacks or validation rules, as doing this wouldn't scale when
# importing very large projects.
- result = Gitlab::Database.main # rubocop:disable Gitlab/BulkInsert
- .bulk_insert(relation.table_name, [attributes], return_ids: true)
+ result = ApplicationRecord # rubocop:disable Gitlab/BulkInsert
+ .legacy_bulk_insert(relation.table_name, [attributes], return_ids: true)
result.first
end
diff --git a/lib/gitlab/import/metrics.rb b/lib/gitlab/import/metrics.rb
index 5f27d0ab965..7a0cf1682a6 100644
--- a/lib/gitlab/import/metrics.rb
+++ b/lib/gitlab/import/metrics.rb
@@ -69,11 +69,7 @@ module Gitlab
end
def observe_histogram
- if project.github_import?
- duration_histogram.observe({ project: project.full_path }, duration)
- else
- duration_histogram.observe({ importer: importer }, duration)
- end
+ duration_histogram.observe({ importer: importer }, duration)
end
def track_finish_metric
diff --git a/lib/gitlab/import_export/attributes_permitter.rb b/lib/gitlab/import_export/attributes_permitter.rb
index 2d8e25a9f70..f6f65f85599 100644
--- a/lib/gitlab/import_export/attributes_permitter.rb
+++ b/lib/gitlab/import_export/attributes_permitter.rb
@@ -44,7 +44,7 @@ module Gitlab
# We want to use AttributesCleaner for these relations instead, in the future this should be removed to make sure
# we are using AttributesPermitter for every imported relation.
- DISABLED_RELATION_NAMES = %i[user author issuable_sla].freeze
+ DISABLED_RELATION_NAMES = %i[author issuable_sla].freeze
def initialize(config: ImportExport::Config.new.to_h)
@config = config
diff --git a/lib/gitlab/import_export/base/object_builder.rb b/lib/gitlab/import_export/base/object_builder.rb
index 48836729ff6..5e9c8292c1e 100644
--- a/lib/gitlab/import_export/base/object_builder.rb
+++ b/lib/gitlab/import_export/base/object_builder.rb
@@ -47,15 +47,15 @@ module Gitlab
attributes
end
- private
+ def find_with_cache(key = cache_key)
+ return yield unless lru_cache && key
- attr_reader :klass, :attributes, :lru_cache, :cache_key
+ lru_cache[key] ||= yield
+ end
- def find_with_cache
- return yield unless lru_cache && cache_key
+ private
- lru_cache[cache_key] ||= yield
- end
+ attr_reader :klass, :attributes, :lru_cache, :cache_key
def cache_from_request_store
Gitlab::SafeRequestStore[:lru_cache] ||= LruRedux::Cache.new(LRU_CACHE_SIZE)
diff --git a/lib/gitlab/import_export/decompressed_archive_size_validator.rb b/lib/gitlab/import_export/decompressed_archive_size_validator.rb
index febfe00af0b..61b37256964 100644
--- a/lib/gitlab/import_export/decompressed_archive_size_validator.rb
+++ b/lib/gitlab/import_export/decompressed_archive_size_validator.rb
@@ -6,7 +6,7 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
DEFAULT_MAX_BYTES = 10.gigabytes.freeze
- TIMEOUT_LIMIT = 60.seconds
+ TIMEOUT_LIMIT = 210.seconds
def initialize(archive_path:, max_bytes: self.class.max_bytes)
@archive_path = archive_path
diff --git a/lib/gitlab/import_export/group/relation_tree_restorer.rb b/lib/gitlab/import_export/group/relation_tree_restorer.rb
new file mode 100644
index 00000000000..f3c392b8c20
--- /dev/null
+++ b/lib/gitlab/import_export/group/relation_tree_restorer.rb
@@ -0,0 +1,274 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ImportExport
+ module Group
+ class RelationTreeRestorer
+ def initialize( # rubocop:disable Metrics/ParameterLists
+ user:,
+ shared:,
+ relation_reader:,
+ members_mapper:,
+ object_builder:,
+ relation_factory:,
+ reader:,
+ importable:,
+ importable_attributes:,
+ importable_path:
+ )
+ @user = user
+ @shared = shared
+ @importable = importable
+ @relation_reader = relation_reader
+ @members_mapper = members_mapper
+ @object_builder = object_builder
+ @relation_factory = relation_factory
+ @reader = reader
+ @importable_attributes = importable_attributes
+ @importable_path = importable_path
+ end
+
+ def restore
+ ActiveRecord::Base.uncached do
+ ActiveRecord::Base.no_touching do
+ update_params!
+
+ BulkInsertableAssociations.with_bulk_insert(enabled: bulk_insert_enabled) do
+ fix_ci_pipelines_not_sorted_on_legacy_project_json!
+ create_relations!
+ end
+ end
+ end
+
+ # ensure that we have latest version of the restore
+ @importable.reload # rubocop:disable Cop/ActiveRecordAssociationReload
+
+ true
+ rescue StandardError => e
+ @shared.error(e)
+ false
+ end
+
+ private
+
+ def bulk_insert_enabled
+ false
+ end
+
+ # Loops through the tree of models defined in import_export.yml and
+ # finds them in the imported JSON so they can be instantiated and saved
+ # in the DB. The structure and relationships between models are guessed from
+ # the configuration yaml file too.
+ # Finally, it updates each attribute in the newly imported project/group.
+ def create_relations!
+ relations.each do |relation_key, relation_definition|
+ process_relation!(relation_key, relation_definition)
+ end
+ end
+
+ def process_relation!(relation_key, relation_definition)
+ @relation_reader.consume_relation(@importable_path, relation_key).each do |data_hash, relation_index|
+ process_relation_item!(relation_key, relation_definition, relation_index, data_hash)
+ end
+ end
+
+ def process_relation_item!(relation_key, relation_definition, relation_index, data_hash)
+ relation_object = build_relation(relation_key, relation_definition, relation_index, data_hash)
+ return unless relation_object
+ return if relation_invalid_for_importable?(relation_object)
+
+ relation_object.assign_attributes(importable_class_sym => @importable)
+
+ import_failure_service.with_retry(action: 'relation_object.save!', relation_key: relation_key, relation_index: relation_index) do
+ relation_object.save!
+ log_relation_creation(@importable, relation_key, relation_object)
+ end
+ rescue StandardError => e
+ import_failure_service.log_import_failure(
+ source: 'process_relation_item!',
+ relation_key: relation_key,
+ relation_index: relation_index,
+ exception: e)
+ end
+
+ def import_failure_service
+ @import_failure_service ||= ImportFailureService.new(@importable)
+ end
+
+ def relations
+ @relations ||=
+ @reader
+ .attributes_finder
+ .find_relations_tree(importable_class_sym)
+ .deep_stringify_keys
+ end
+
+ def update_params!
+ params = @importable_attributes.except(*relations.keys.map(&:to_s))
+ params = params.merge(present_override_params)
+
+ # Cleaning all imported and overridden params
+ params = Gitlab::ImportExport::AttributeCleaner.clean(
+ relation_hash: params,
+ relation_class: importable_class,
+ excluded_keys: excluded_keys_for_relation(importable_class_sym))
+
+ @importable.assign_attributes(params)
+
+ modify_attributes
+
+ Gitlab::Timeless.timeless(@importable) do
+ @importable.save!
+ end
+ end
+
+ def present_override_params
+ # we filter out the empty strings from the overrides
+ # keeping the default values configured
+ override_params&.transform_values do |value|
+ value.is_a?(String) ? value.presence : value
+ end&.compact
+ end
+
+ def override_params
+ @importable_override_params ||= importable_override_params
+ end
+
+ def importable_override_params
+ if @importable.respond_to?(:import_data)
+ @importable.import_data&.data&.fetch('override_params', nil) || {}
+ else
+ {}
+ end
+ end
+
+ def modify_attributes
+ # no-op to be overridden on inheritance
+ end
+
+ def build_relations(relation_key, relation_definition, relation_index, data_hashes)
+ data_hashes
+ .map { |data_hash| build_relation(relation_key, relation_definition, relation_index, data_hash) }
+ .tap { |entries| entries.compact! }
+ end
+
+ def build_relation(relation_key, relation_definition, relation_index, data_hash)
+ # TODO: This is hack to not create relation for the author
+ # Rather make `RelationFactory#set_note_author` to take care of that
+ return data_hash if relation_key == 'author' || already_restored?(data_hash)
+
+ # create relation objects recursively for all sub-objects
+ relation_definition.each do |sub_relation_key, sub_relation_definition|
+ transform_sub_relations!(data_hash, sub_relation_key, sub_relation_definition, relation_index)
+ end
+
+ relation = @relation_factory.create(**relation_factory_params(relation_key, relation_index, data_hash))
+
+ if relation && !relation.valid?
+ @shared.logger.warn(
+ message: "[Project/Group Import] Invalid object relation built",
+ relation_key: relation_key,
+ relation_index: relation_index,
+ relation_class: relation.class.name,
+ error_messages: relation.errors.full_messages.join(". ")
+ )
+ end
+
+ relation
+ end
+
+ # Since we update the data hash in place as we restore relation items,
+ # and since we also de-duplicate items, we might encounter items that
+ # have already been restored in a previous iteration.
+ def already_restored?(relation_item)
+ !relation_item.is_a?(Hash)
+ end
+
+ def transform_sub_relations!(data_hash, sub_relation_key, sub_relation_definition, relation_index)
+ sub_data_hash = data_hash[sub_relation_key]
+ return unless sub_data_hash
+
+ # if object is a hash we can create simple object
+ # as it means that this is 1-to-1 vs 1-to-many
+ current_item =
+ if sub_data_hash.is_a?(Array)
+ build_relations(
+ sub_relation_key,
+ sub_relation_definition,
+ relation_index,
+ sub_data_hash).presence
+ else
+ build_relation(
+ sub_relation_key,
+ sub_relation_definition,
+ relation_index,
+ sub_data_hash)
+ end
+
+ if current_item
+ data_hash[sub_relation_key] = current_item
+ else
+ data_hash.delete(sub_relation_key)
+ end
+ end
+
+ def relation_invalid_for_importable?(_relation_object)
+ false
+ end
+
+ def excluded_keys_for_relation(relation)
+ @reader.attributes_finder.find_excluded_keys(relation)
+ end
+
+ def importable_class
+ @importable.class
+ end
+
+ def importable_class_sym
+ importable_class.to_s.downcase.to_sym
+ end
+
+ def relation_factory_params(relation_key, relation_index, data_hash)
+ {
+ relation_index: relation_index,
+ relation_sym: relation_key.to_sym,
+ relation_hash: data_hash,
+ importable: @importable,
+ members_mapper: @members_mapper,
+ object_builder: @object_builder,
+ user: @user,
+ excluded_keys: excluded_keys_for_relation(relation_key)
+ }
+ end
+
+ # Temporary fix for https://gitlab.com/gitlab-org/gitlab/-/issues/27883 when import from legacy project.json
+ # This should be removed once legacy JSON format is deprecated.
+ # Ndjson export file will fix the order during project export.
+ def fix_ci_pipelines_not_sorted_on_legacy_project_json!
+ return unless @relation_reader.legacy?
+
+ @relation_reader.sort_ci_pipelines_by_id
+ end
+
+ # Enable logging of each top-level relation creation when Importing
+ # into a Group if feature flag is enabled
+ def log_relation_creation(importable, relation_key, relation_object)
+ root_ancestor_group = importable.try(:root_ancestor)
+
+ return unless root_ancestor_group
+ return unless root_ancestor_group.instance_of?(::Group)
+ return unless Feature.enabled?(:log_import_export_relation_creation, root_ancestor_group)
+
+ @shared.logger.info(
+ importable_type: importable.class.to_s,
+ importable_id: importable.id,
+ relation_key: relation_key,
+ relation_id: relation_object.id,
+ author_id: relation_object.try(:author_id),
+ message: '[Project/Group Import] Created new object relation'
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml
index 618ef9a4f43..d815dd284ba 100644
--- a/lib/gitlab/import_export/project/import_export.yml
+++ b/lib/gitlab/import_export/project/import_export.yml
@@ -178,17 +178,7 @@ included_attributes:
- :project_id
- :key
- :value
- label:
- - :title
- - :color
- - :project_id
- - :group_id
- - :created_at
- - :updated_at
- - :template
- - :description
- - :priority
- labels:
+ label: &label_definition
- :title
- :color
- :project_id
@@ -198,23 +188,13 @@ included_attributes:
- :template
- :description
- :priority
+ labels: *label_definition
priorities:
- :project_id
- :priority
- :created_at
- :updated_at
- milestone:
- - :iid
- - :title
- - :project_id
- - :group_id
- - :description
- - :due_date
- - :created_at
- - :updated_at
- - :start_date
- - :state
- milestones:
+ milestone: &milestone_definition
- :iid
- :title
- :project_id
@@ -225,6 +205,7 @@ included_attributes:
- :updated_at
- :start_date
- :state
+ milestones: *milestone_definition
protected_branches:
- :project_id
- :name
@@ -272,6 +253,385 @@ included_attributes:
- :updated_at
- :filepath
- :link_type
+ container_expiration_policy:
+ - :created_at
+ - :updated_at
+ - :next_run_at
+ - :project_id
+ - :name_regex
+ - :cadence
+ - :older_than
+ - :keep_n
+ - :enabled
+ - :name_regex_keep
+ project_feature:
+ - :project_id
+ - :merge_requests_access_level
+ - :issues_access_level
+ - :wiki_access_level
+ - :snippets_access_level
+ - :builds_access_level
+ - :created_at
+ - :updated_at
+ - :repository_access_level
+ - :pages_access_level
+ - :forking_access_level
+ - :metrics_dashboard_access_level
+ - :operations_access_level
+ - :analytics_access_level
+ - :security_and_compliance_access_level
+ - :container_registry_access_level
+ prometheus_metrics:
+ - :created_at
+ - :updated_at
+ - :project_id
+ - :y_label
+ - :unit
+ - :legend
+ - :title
+ - :query
+ - :group
+ - :dashboard_path
+ service_desk_setting:
+ - :project_id
+ - :issue_template_key
+ - :project_key
+ snippets:
+ - :title
+ - :content
+ - :author_id
+ - :project_id
+ - :created_at
+ - :updated_at
+ - :file_name
+ - :visibility_level
+ - :description
+ project_members:
+ - :access_level
+ - :source_type
+ - :user_id
+ - :notification_level
+ - :created_at
+ - :updated_at
+ - :created_by_id
+ - :invite_email
+ - :invite_accepted_at
+ - :requested_at
+ - :expires_at
+ - :ldap
+ - :override
+ merge_request: &merge_request_definition
+ - :target_branch
+ - :source_branch
+ - :source_project_id
+ - :author_id
+ - :assignee_id
+ - :title
+ - :created_at
+ - :updated_at
+ - :state
+ - :merge_status
+ - :target_project_id
+ - :iid
+ - :description
+ - :updated_by_id
+ - :merge_error
+ - :merge_params
+ - :merge_when_pipeline_succeeds
+ - :merge_user_id
+ - :merge_commit_sha
+ - :squash_commit_sha
+ - :in_progress_merge_commit_sha
+ - :lock_version
+ - :approvals_before_merge
+ - :rebase_commit_sha
+ - :time_estimate
+ - :squash
+ - :last_edited_at
+ - :last_edited_by_id
+ - :discussion_locked
+ - :allow_maintainer_to_push
+ - :merge_ref_sha
+ - :draft
+ - :diff_head_sha
+ - :source_branch_sha
+ - :target_branch_sha
+ merge_requests: *merge_request_definition
+ award_emoji:
+ - :user_id
+ - :name
+ - :awardable_type
+ - :created_at
+ - :updated_at
+ commit_author:
+ - :name
+ - :email
+ committer:
+ - :name
+ - :email
+ events:
+ - :target_type
+ - :action
+ - :author_id
+ - :fingerprint
+ - :created_at
+ - :updated_at
+ label_links:
+ - :target_type
+ - :created_at
+ - :updated_at
+ merge_request_diff:
+ - :state
+ - :created_at
+ - :updated_at
+ - :base_commit_sha
+ - :real_size
+ - :head_commit_sha
+ - :start_commit_sha
+ - :commits_count
+ - :files_count
+ - :sorted
+ - :diff_type
+ merge_request_diff_commits:
+ - :author_name
+ - :author_email
+ - :committer_name
+ - :committer_email
+ - :relative_order
+ - :sha
+ - :authored_date
+ - :committed_date
+ - :message
+ - :trailers
+ merge_request_diff_files:
+ - :relative_order
+ - :new_file
+ - :renamed_file
+ - :deleted_file
+ - :new_path
+ - :old_path
+ - :a_mode
+ - :b_mode
+ - :too_large
+ - :binary
+ - :diff
+ metrics:
+ - :created_at
+ - :updated_at
+ - :latest_closed_by_id
+ - :latest_closed_at
+ - :merged_by_id
+ - :merged_at
+ - :latest_build_started_at
+ - :latest_build_finished_at
+ - :first_deployed_to_production_at
+ - :first_comment_at
+ - :first_commit_at
+ - :last_commit_at
+ - :diff_size
+ - :modified_paths_size
+ - :commits_count
+ - :first_approved_at
+ - :first_reassigned_at
+ - :added_lines
+ - :target_project_id
+ - :removed_lines
+ notes:
+ - :note
+ - :noteable_type
+ - :author_id
+ - :created_at
+ - :updated_at
+ - :project_id
+ - :attachment
+ - :line_code
+ - :commit_id
+ - :system
+ - :st_diff
+ - :updated_by_id
+ - :type
+ - :position
+ - :original_position
+ - :change_position
+ - :resolved_at
+ - :resolved_by_id
+ - :resolved_by_push
+ - :discussion_id
+ - :confidential
+ - :last_edited_at
+ push_event_payload:
+ - :commit_count
+ - :action
+ - :ref_type
+ - :commit_from
+ - :commit_to
+ - :ref
+ - :commit_title
+ - :ref_count
+ resource_label_events:
+ - :action
+ - :user_id
+ - :created_at
+ suggestions:
+ - :relative_order
+ - :applied
+ - :commit_id
+ - :from_content
+ - :to_content
+ - :outdated
+ - :lines_above
+ - :lines_below
+ system_note_metadata:
+ - :commit_count
+ - :action
+ - :created_at
+ - :updated_at
+ timelogs:
+ - :time_spent
+ - :user_id
+ - :project_id
+ - :spent_at
+ - :created_at
+ - :updated_at
+ - :summary
+ external_pull_request: &external_pull_request_definition
+ - :created_at
+ - :updated_at
+ - :project_id
+ - :pull_request_iid
+ - :status
+ - :source_branch
+ - :target_branch
+ - :source_repository
+ - :target_repository
+ - :source_sha
+ - :target_sha
+ external_pull_requests: *external_pull_request_definition
+ statuses:
+ - :project_id
+ - :status
+ - :finished_at
+ - :created_at
+ - :updated_at
+ - :started_at
+ - :coverage
+ - :commit_id
+ - :name
+ - :options
+ - :allow_failure
+ - :stage
+ - :stage_idx
+ - :tag
+ - :ref
+ - :user_id
+ - :type
+ - :target_url
+ - :description
+ - :erased_at
+ - :artifacts_expire_at
+ - :environment
+ - :yaml_variables
+ - :queued_at
+ - :lock_version
+ - :coverage_regex
+ - :retried
+ - :protected
+ - :failure_reason
+ - :scheduled_at
+ - :scheduling_type
+ ci_pipelines:
+ - :ref
+ - :sha
+ - :before_sha
+ - :created_at
+ - :updated_at
+ - :tag
+ - :yaml_errors
+ - :committed_at
+ - :project_id
+ - :status
+ - :started_at
+ - :finished_at
+ - :duration
+ - :user_id
+ - :lock_version
+ - :source
+ - :protected
+ - :config_source
+ - :failure_reason
+ - :iid
+ - :source_sha
+ - :target_sha
+ stages:
+ - :name
+ - :status
+ - :position
+ - :lock_version
+ - :project_id
+ - :created_at
+ - :updated_at
+ actions:
+ - :event
+ - :image_v432x230
+ design: &design_definition
+ - :iid
+ - :project_id
+ - :filename
+ - :relative_position
+ designs: *design_definition
+ design_versions:
+ - :created_at
+ - :sha
+ - :author_id
+ issue_assignees:
+ - :user_id
+ sentry_issue:
+ - :sentry_issue_identifier
+ zoom_meetings:
+ - :project_id
+ - :issue_status
+ - :url
+ - :created_at
+ - :updated_at
+ issues:
+ - :title
+ - :author_id
+ - :project_id
+ - :created_at
+ - :updated_at
+ - :description
+ - :state
+ - :iid
+ - :updated_by_id
+ - :confidential
+ - :closed_at
+ - :closed_by_id
+ - :due_date
+ - :lock_version
+ - :weight
+ - :time_estimate
+ - :relative_position
+ - :external_author
+ - :last_edited_at
+ - :last_edited_by_id
+ - :discussion_locked
+ - :health_status
+ - :external_key
+ - :issue_type
+ group_members:
+ - :access_level
+ - :source_type
+ - :user_id
+ - :notification_level
+ - :created_at
+ - :updated_at
+ - :created_by_id
+ - :invite_email
+ - :invite_accepted_at
+ - :requested_at
+ - :expires_at
+ - :ldap
+ - :override
# Do not include the following attributes for the models specified.
excluded_attributes:
@@ -387,16 +747,7 @@ excluded_attributes:
- :service_desk_reply_to
- :upvotes_count
- :work_item_type_id
- merge_request:
- - :milestone_id
- - :sprint_id
- - :ref_fetched
- - :merge_jid
- - :rebase_jid
- - :latest_merge_request_diff_id
- - :head_pipeline_id
- - :state_id
- merge_requests:
+ merge_request: &merge_request_excluded_definition
- :milestone_id
- :sprint_id
- :ref_fetched
@@ -405,6 +756,7 @@ excluded_attributes:
- :latest_merge_request_diff_id
- :head_pipeline_id
- :state_id
+ merge_requests: *merge_request_excluded_definition
award_emoji:
- :awardable_id
statuses:
@@ -473,10 +825,9 @@ excluded_attributes:
- :issue_id
zoom_meetings:
- :issue_id
- design:
- - :issue_id
- designs:
+ design: &design_excluded_definition
- :issue_id
+ designs: *design_excluded_definition
design_versions:
- :issue_id
actions:
@@ -660,4 +1011,13 @@ ee:
- :name
- :created_at
- :updated_at
-
+ project_feature:
+ - :requirements_access_level
+ security_setting:
+ - :project_id
+ - :created_at
+ - :updated_at
+ - :auto_fix_container_scanning
+ - :auto_fix_dast
+ - :auto_fix_dependency_scanning
+ - :auto_fix_sast
diff --git a/lib/gitlab/import_export/project/object_builder.rb b/lib/gitlab/import_export/project/object_builder.rb
index b03dceba303..f7598ba1337 100644
--- a/lib/gitlab/import_export/project/object_builder.rb
+++ b/lib/gitlab/import_export/project/object_builder.rb
@@ -29,6 +29,7 @@ module Gitlab
def find
return if epic? && group.nil?
return find_diff_commit_user if diff_commit_user?
+ return find_diff_commit if diff_commit?
super
end
@@ -83,9 +84,38 @@ module Gitlab
end
def find_diff_commit_user
- find_with_cache do
- MergeRequest::DiffCommitUser
- .find_or_create(@attributes['name'], @attributes['email'])
+ find_or_create_diff_commit_user(@attributes['name'], @attributes['email'])
+ end
+
+ def find_diff_commit
+ row = @attributes.dup
+
+ # Diff commits come in two formats:
+ #
+ # 1. The old format where author/committer details are separate fields
+ # 2. The new format where author/committer details are nested objects,
+ # and pre-processed by `find_diff_commit_user`.
+ #
+ # The code here ensures we support both the old and new format.
+ aname = row.delete('author_name')
+ amail = row.delete('author_email')
+ cname = row.delete('committer_name')
+ cmail = row.delete('committer_email')
+ author = row.delete('commit_author')
+ committer = row.delete('committer')
+
+ row['commit_author'] = author ||
+ find_or_create_diff_commit_user(aname, amail)
+
+ row['committer'] = committer ||
+ find_or_create_diff_commit_user(cname, cmail)
+
+ MergeRequestDiffCommit.new(row)
+ end
+
+ def find_or_create_diff_commit_user(name, email)
+ find_with_cache([MergeRequest::DiffCommitUser, name, email]) do
+ MergeRequest::DiffCommitUser.find_or_create(name, email)
end
end
@@ -113,6 +143,10 @@ module Gitlab
klass == MergeRequest::DiffCommitUser
end
+ def diff_commit?
+ klass == MergeRequestDiffCommit
+ end
+
# If an existing group milestone used the IID
# claim the IID back and set the group milestone to use one available
# This is necessary to fix situations like the following:
diff --git a/lib/gitlab/import_export/project/relation_factory.rb b/lib/gitlab/import_export/project/relation_factory.rb
index 888a5a10f2c..d84db92fe69 100644
--- a/lib/gitlab/import_export/project/relation_factory.rb
+++ b/lib/gitlab/import_export/project/relation_factory.rb
@@ -33,7 +33,8 @@ module Gitlab
links: 'Releases::Link',
metrics_setting: 'ProjectMetricsSetting',
commit_author: 'MergeRequest::DiffCommitUser',
- committer: 'MergeRequest::DiffCommitUser' }.freeze
+ committer: 'MergeRequest::DiffCommitUser',
+ merge_request_diff_commits: 'MergeRequestDiffCommit' }.freeze
BUILD_MODELS = %i[Ci::Build commit_status].freeze
@@ -59,6 +60,7 @@ module Gitlab
external_pull_requests
DesignManagement::Design
MergeRequest::DiffCommitUser
+ MergeRequestDiffCommit
].freeze
def create
diff --git a/lib/gitlab/import_export/project/relation_tree_restorer.rb b/lib/gitlab/import_export/project/relation_tree_restorer.rb
new file mode 100644
index 00000000000..6e9548f393a
--- /dev/null
+++ b/lib/gitlab/import_export/project/relation_tree_restorer.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ImportExport
+ module Project
+ class RelationTreeRestorer < ImportExport::Group::RelationTreeRestorer
+ # Relations which cannot be saved at project level (and have a group assigned)
+ GROUP_MODELS = [GroupLabel, Milestone, Epic].freeze
+
+ private
+
+ def bulk_insert_enabled
+ true
+ end
+
+ def modify_attributes
+ @importable.reconcile_shared_runners_setting!
+ @importable.drop_visibility_level!
+ end
+
+ def relation_invalid_for_importable?(relation_object)
+ GROUP_MODELS.include?(relation_object.class) && relation_object.group_id
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/project/sample/relation_tree_restorer.rb b/lib/gitlab/import_export/project/sample/relation_tree_restorer.rb
index 4db92b12968..034122a9f14 100644
--- a/lib/gitlab/import_export/project/sample/relation_tree_restorer.rb
+++ b/lib/gitlab/import_export/project/sample/relation_tree_restorer.rb
@@ -4,7 +4,7 @@ module Gitlab
module ImportExport
module Project
module Sample
- class RelationTreeRestorer < ImportExport::RelationTreeRestorer
+ class RelationTreeRestorer < ImportExport::Project::RelationTreeRestorer
def initialize(...)
super(...)
@@ -18,10 +18,10 @@ module Gitlab
end
def dates
- return [] if relation_reader.legacy?
+ return [] if @relation_reader.legacy?
RelationFactory::DATE_MODELS.flat_map do |tag|
- relation_reader.consume_relation(@importable_path, tag, mark_as_consumed: false).map do |model|
+ @relation_reader.consume_relation(@importable_path, tag, mark_as_consumed: false).map do |model|
model.first['due_date']
end
end
diff --git a/lib/gitlab/import_export/project/tree_saver.rb b/lib/gitlab/import_export/project/tree_saver.rb
index 1f0fa249390..aafed850afa 100644
--- a/lib/gitlab/import_export/project/tree_saver.rb
+++ b/lib/gitlab/import_export/project/tree_saver.rb
@@ -6,20 +6,16 @@ module Gitlab
class TreeSaver
attr_reader :full_path
- def initialize(project:, current_user:, shared:, params: {})
+ def initialize(project:, current_user:, shared:, params: {}, logger: Gitlab::Import::Logger)
@params = params
@project = project
@current_user = current_user
@shared = shared
+ @logger = logger
end
def save
- ImportExport::Json::StreamingSerializer.new(
- exportable,
- reader.project_tree,
- json_writer,
- exportable_path: "project"
- ).execute
+ stream_export
true
rescue StandardError => e
@@ -31,6 +27,32 @@ module Gitlab
private
+ def stream_export
+ on_retry = proc do |exception, try, elapsed_time, next_interval|
+ @logger.info(
+ message: "Project export retry triggered from streaming",
+ 'error.class': exception.class,
+ 'error.message': exception.message,
+ try_count: try,
+ elapsed_time_s: elapsed_time,
+ wait_to_retry_s: next_interval,
+ project_name: @project.name,
+ project_id: @project.id
+ )
+ end
+
+ serializer = ImportExport::Json::StreamingSerializer.new(
+ exportable,
+ reader.project_tree,
+ json_writer,
+ exportable_path: "project"
+ )
+
+ Retriable.retriable(on: Net::OpenTimeout, on_retry: on_retry) do
+ serializer.execute
+ end
+ end
+
def reader
@reader ||= Gitlab::ImportExport::Reader.new(shared: @shared)
end
diff --git a/lib/gitlab/import_export/relation_tree_restorer.rb b/lib/gitlab/import_export/relation_tree_restorer.rb
deleted file mode 100644
index 1eeacafef53..00000000000
--- a/lib/gitlab/import_export/relation_tree_restorer.rb
+++ /dev/null
@@ -1,280 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module ImportExport
- class RelationTreeRestorer
- # Relations which cannot be saved at project level (and have a group assigned)
- GROUP_MODELS = [GroupLabel, Milestone, Epic].freeze
-
- attr_reader :user
- attr_reader :shared
- attr_reader :importable
- attr_reader :relation_reader
-
- def initialize( # rubocop:disable Metrics/ParameterLists
- user:, shared:, relation_reader:,
- members_mapper:, object_builder:,
- relation_factory:,
- reader:,
- importable:,
- importable_attributes:,
- importable_path:
- )
- @user = user
- @shared = shared
- @importable = importable
- @relation_reader = relation_reader
- @members_mapper = members_mapper
- @object_builder = object_builder
- @relation_factory = relation_factory
- @reader = reader
- @importable_attributes = importable_attributes
- @importable_path = importable_path
- end
-
- def restore
- ActiveRecord::Base.uncached do
- ActiveRecord::Base.no_touching do
- update_params!
-
- BulkInsertableAssociations.with_bulk_insert(enabled: project?) do
- fix_ci_pipelines_not_sorted_on_legacy_project_json!
- create_relations!
- end
- end
- end
-
- # ensure that we have latest version of the restore
- @importable.reload # rubocop:disable Cop/ActiveRecordAssociationReload
-
- true
- rescue StandardError => e
- @shared.error(e)
- false
- end
-
- private
-
- def project?
- @importable.instance_of?(::Project)
- end
-
- # Loops through the tree of models defined in import_export.yml and
- # finds them in the imported JSON so they can be instantiated and saved
- # in the DB. The structure and relationships between models are guessed from
- # the configuration yaml file too.
- # Finally, it updates each attribute in the newly imported project/group.
- def create_relations!
- relations.each do |relation_key, relation_definition|
- process_relation!(relation_key, relation_definition)
- end
- end
-
- def process_relation!(relation_key, relation_definition)
- @relation_reader.consume_relation(@importable_path, relation_key).each do |data_hash, relation_index|
- process_relation_item!(relation_key, relation_definition, relation_index, data_hash)
- end
- end
-
- def process_relation_item!(relation_key, relation_definition, relation_index, data_hash)
- relation_object = build_relation(relation_key, relation_definition, relation_index, data_hash)
- return unless relation_object
- return if project? && group_model?(relation_object)
-
- relation_object.assign_attributes(importable_class_sym => @importable)
-
- import_failure_service.with_retry(action: 'relation_object.save!', relation_key: relation_key, relation_index: relation_index) do
- relation_object.save!
- log_relation_creation(@importable, relation_key, relation_object)
- end
- rescue StandardError => e
- import_failure_service.log_import_failure(
- source: 'process_relation_item!',
- relation_key: relation_key,
- relation_index: relation_index,
- exception: e)
- end
-
- def import_failure_service
- @import_failure_service ||= ImportFailureService.new(@importable)
- end
-
- def relations
- @relations ||=
- @reader
- .attributes_finder
- .find_relations_tree(importable_class_sym)
- .deep_stringify_keys
- end
-
- def update_params!
- params = @importable_attributes.except(*relations.keys.map(&:to_s))
- params = params.merge(present_override_params)
-
- # Cleaning all imported and overridden params
- params = Gitlab::ImportExport::AttributeCleaner.clean(
- relation_hash: params,
- relation_class: importable_class,
- excluded_keys: excluded_keys_for_relation(importable_class_sym))
-
- @importable.assign_attributes(params)
-
- modify_attributes
-
- Gitlab::Timeless.timeless(@importable) do
- @importable.save!
- end
- end
-
- def present_override_params
- # we filter out the empty strings from the overrides
- # keeping the default values configured
- override_params&.transform_values do |value|
- value.is_a?(String) ? value.presence : value
- end&.compact
- end
-
- def override_params
- @importable_override_params ||= importable_override_params
- end
-
- def importable_override_params
- if @importable.respond_to?(:import_data)
- @importable.import_data&.data&.fetch('override_params', nil) || {}
- else
- {}
- end
- end
-
- def modify_attributes
- return unless project?
-
- @importable.reconcile_shared_runners_setting!
- @importable.drop_visibility_level!
- end
-
- def build_relations(relation_key, relation_definition, relation_index, data_hashes)
- data_hashes
- .map { |data_hash| build_relation(relation_key, relation_definition, relation_index, data_hash) }
- .tap { |entries| entries.compact! }
- end
-
- def build_relation(relation_key, relation_definition, relation_index, data_hash)
- # TODO: This is hack to not create relation for the author
- # Rather make `RelationFactory#set_note_author` to take care of that
- return data_hash if relation_key == 'author' || already_restored?(data_hash)
-
- # create relation objects recursively for all sub-objects
- relation_definition.each do |sub_relation_key, sub_relation_definition|
- transform_sub_relations!(data_hash, sub_relation_key, sub_relation_definition, relation_index)
- end
-
- relation = @relation_factory.create(**relation_factory_params(relation_key, relation_index, data_hash))
-
- if relation && !relation.valid?
- @shared.logger.warn(
- message: "[Project/Group Import] Invalid object relation built",
- relation_key: relation_key,
- relation_index: relation_index,
- relation_class: relation.class.name,
- error_messages: relation.errors.full_messages.join(". ")
- )
- end
-
- relation
- end
-
- # Since we update the data hash in place as we restore relation items,
- # and since we also de-duplicate items, we might encounter items that
- # have already been restored in a previous iteration.
- def already_restored?(relation_item)
- !relation_item.is_a?(Hash)
- end
-
- def transform_sub_relations!(data_hash, sub_relation_key, sub_relation_definition, relation_index)
- sub_data_hash = data_hash[sub_relation_key]
- return unless sub_data_hash
-
- # if object is a hash we can create simple object
- # as it means that this is 1-to-1 vs 1-to-many
- current_item =
- if sub_data_hash.is_a?(Array)
- build_relations(
- sub_relation_key,
- sub_relation_definition,
- relation_index,
- sub_data_hash).presence
- else
- build_relation(
- sub_relation_key,
- sub_relation_definition,
- relation_index,
- sub_data_hash)
- end
-
- if current_item
- data_hash[sub_relation_key] = current_item
- else
- data_hash.delete(sub_relation_key)
- end
- end
-
- def group_model?(relation_object)
- GROUP_MODELS.include?(relation_object.class) && relation_object.group_id
- end
-
- def excluded_keys_for_relation(relation)
- @reader.attributes_finder.find_excluded_keys(relation)
- end
-
- def importable_class
- @importable.class
- end
-
- def importable_class_sym
- importable_class.to_s.downcase.to_sym
- end
-
- def relation_factory_params(relation_key, relation_index, data_hash)
- {
- relation_index: relation_index,
- relation_sym: relation_key.to_sym,
- relation_hash: data_hash,
- importable: @importable,
- members_mapper: @members_mapper,
- object_builder: @object_builder,
- user: @user,
- excluded_keys: excluded_keys_for_relation(relation_key)
- }
- end
-
- # Temporary fix for https://gitlab.com/gitlab-org/gitlab/-/issues/27883 when import from legacy project.json
- # This should be removed once legacy JSON format is deprecated.
- # Ndjson export file will fix the order during project export.
- def fix_ci_pipelines_not_sorted_on_legacy_project_json!
- return unless relation_reader.legacy?
-
- relation_reader.sort_ci_pipelines_by_id
- end
-
- # Enable logging of each top-level relation creation when Importing
- # into a Group if feature flag is enabled
- def log_relation_creation(importable, relation_key, relation_object)
- root_ancestor_group = importable.try(:root_ancestor)
-
- return unless root_ancestor_group
- return unless root_ancestor_group.instance_of?(::Group)
- return unless Feature.enabled?(:log_import_export_relation_creation, root_ancestor_group)
-
- @shared.logger.info(
- importable_type: importable.class.to_s,
- importable_id: importable.id,
- relation_key: relation_key,
- relation_id: relation_object.id,
- author_id: relation_object.try(:author_id),
- message: '[Project/Group Import] Created new object relation'
- )
- end
- end
- end
-end
diff --git a/lib/gitlab/instrumentation/redis_interceptor.rb b/lib/gitlab/instrumentation/redis_interceptor.rb
index ba25e54ac9f..14474693ddf 100644
--- a/lib/gitlab/instrumentation/redis_interceptor.rb
+++ b/lib/gitlab/instrumentation/redis_interceptor.rb
@@ -5,10 +5,6 @@ module Gitlab
module RedisInterceptor
APDEX_EXCLUDE = %w[brpop blpop brpoplpush bzpopmin bzpopmax xread xreadgroup].freeze
- # These are temporary to help with investigating
- # https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1183
- DURATION_ERROR_THRESHOLD = 1.25.seconds
-
class MysteryRedisDurationError < StandardError
attr_reader :backtrace
@@ -19,7 +15,6 @@ module Gitlab
def call(*args, &block)
start = Gitlab::Metrics::System.monotonic_time # must come first so that 'start' is always defined
- start_real_time = Time.now
instrumentation_class.instance_count_request
instrumentation_class.redis_cluster_validate!(args.first)
@@ -40,16 +35,6 @@ module Gitlab
instrumentation_class.add_duration(duration)
instrumentation_class.add_call_details(duration, args)
end
-
- if duration > DURATION_ERROR_THRESHOLD &&
- instrumentation_class == ::Gitlab::Instrumentation::Redis::SharedState &&
- Feature.enabled?(:report_on_long_redis_durations, default_enabled: :yaml)
-
- Gitlab::ErrorTracking.track_exception(MysteryRedisDurationError.new(caller),
- command: command_from_args(args),
- duration: duration,
- timestamp: start_real_time.iso8601(5))
- end
end
def write(command)
diff --git a/lib/gitlab/instrumentation/uploads.rb b/lib/gitlab/instrumentation/uploads.rb
new file mode 100644
index 00000000000..02e457453cd
--- /dev/null
+++ b/lib/gitlab/instrumentation/uploads.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Instrumentation
+ class Uploads
+ UPLOAD_DURATION = :uploaded_file_upload_duration_s
+ UPLOADED_FILE_SIZE = :uploaded_file_size_bytes
+
+ def self.track(uploaded_file)
+ if ::Gitlab::SafeRequestStore.active?
+ ::Gitlab::SafeRequestStore[UPLOAD_DURATION] = uploaded_file.upload_duration
+ ::Gitlab::SafeRequestStore[UPLOADED_FILE_SIZE] = uploaded_file.size
+ end
+ end
+
+ def self.get_upload_duration
+ ::Gitlab::SafeRequestStore[UPLOAD_DURATION]
+ end
+
+ def self.get_uploaded_file_size
+ ::Gitlab::SafeRequestStore[UPLOADED_FILE_SIZE]
+ end
+
+ def self.payload
+ {
+ UPLOAD_DURATION => get_upload_duration,
+ UPLOADED_FILE_SIZE => get_uploaded_file_size
+ }.compact
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/instrumentation_helper.rb b/lib/gitlab/instrumentation_helper.rb
index 26e44d7822e..155e365d04c 100644
--- a/lib/gitlab/instrumentation_helper.rb
+++ b/lib/gitlab/instrumentation_helper.rb
@@ -31,6 +31,7 @@ module Gitlab
instrument_thread_memory_allocations(payload)
instrument_load_balancing(payload)
instrument_pid(payload)
+ instrument_uploads(payload)
end
def instrument_gitaly(payload)
@@ -116,6 +117,10 @@ module Gitlab
payload.merge!(load_balancing_payload)
end
+ def instrument_uploads(payload)
+ payload.merge! ::Gitlab::Instrumentation::Uploads.payload
+ end
+
# Returns the queuing duration for a Sidekiq job in seconds, as a float, if the
# `enqueued_at` field or `created_at` field is available.
#
diff --git a/lib/gitlab/integrations/sti_type.rb b/lib/gitlab/integrations/sti_type.rb
index 91797a7b99b..1350d75b216 100644
--- a/lib/gitlab/integrations/sti_type.rb
+++ b/lib/gitlab/integrations/sti_type.rb
@@ -7,7 +7,7 @@ module Gitlab
Asana Assembla Bamboo Bugzilla Buildkite Campfire Confluence CustomIssueTracker Datadog
Discord DroneCi EmailsOnPush Ewm ExternalWiki Flowdock HangoutsChat Irker Jenkins Jira Mattermost
MattermostSlashCommands MicrosoftTeams MockCi MockMonitoring Packagist PipelinesEmail Pivotaltracker
- Prometheus Pushover Redmine Slack SlackSlashCommands Teamcity UnifyCircuit WebexTeams Youtrack Zentao
+ Prometheus Pushover Redmine Shimo Slack SlackSlashCommands Teamcity UnifyCircuit WebexTeams Youtrack Zentao
)).freeze
def self.namespaced_integrations
diff --git a/lib/gitlab/issues/rebalancing/state.rb b/lib/gitlab/issues/rebalancing/state.rb
index dce165a3489..3d3fd9419b2 100644
--- a/lib/gitlab/issues/rebalancing/state.rb
+++ b/lib/gitlab/issues/rebalancing/state.rb
@@ -4,6 +4,10 @@ module Gitlab
module Issues
module Rebalancing
class State
+ REDIS_KEY_PREFIX = "gitlab:issues-position-rebalances"
+ CONCURRENT_RUNNING_REBALANCES_KEY = "#{REDIS_KEY_PREFIX}:running_rebalances"
+ RECENTLY_FINISHED_REBALANCE_PREFIX = "#{REDIS_KEY_PREFIX}:recently_finished"
+
REDIS_EXPIRY_TIME = 10.days
MAX_NUMBER_OF_CONCURRENT_REBALANCES = 5
NAMESPACE = 1
@@ -21,25 +25,23 @@ module Gitlab
redis.multi do |multi|
# we trigger re-balance for namespaces(groups) or specific user project
value = "#{rebalanced_container_type}/#{rebalanced_container_id}"
- multi.sadd(concurrent_running_rebalances_key, value)
- multi.expire(concurrent_running_rebalances_key, REDIS_EXPIRY_TIME)
+ multi.sadd(CONCURRENT_RUNNING_REBALANCES_KEY, value)
+ multi.expire(CONCURRENT_RUNNING_REBALANCES_KEY, REDIS_EXPIRY_TIME)
end
end
end
def concurrent_running_rebalances_count
- with_redis { |redis| redis.scard(concurrent_running_rebalances_key).to_i }
+ with_redis { |redis| redis.scard(CONCURRENT_RUNNING_REBALANCES_KEY).to_i }
end
def rebalance_in_progress?
- all_rebalanced_containers = with_redis { |redis| redis.smembers(concurrent_running_rebalances_key) }
-
is_running = case rebalanced_container_type
when NAMESPACE
- namespace_ids = all_rebalanced_containers.map {|string| string.split("#{NAMESPACE}/").second.to_i }.compact
+ namespace_ids = self.class.current_rebalancing_containers.map {|string| string.split("#{NAMESPACE}/").second.to_i }.compact
namespace_ids.include?(root_namespace.id)
when PROJECT
- project_ids = all_rebalanced_containers.map {|string| string.split("#{PROJECT}/").second.to_i }.compact
+ project_ids = self.class.current_rebalancing_containers.map {|string| string.split("#{PROJECT}/").second.to_i }.compact
project_ids.include?(projects.take.id) # rubocop:disable CodeReuse/ActiveRecord
else
false
@@ -101,36 +103,63 @@ module Gitlab
multi.expire(issue_ids_key, REDIS_EXPIRY_TIME)
multi.expire(current_index_key, REDIS_EXPIRY_TIME)
multi.expire(current_project_key, REDIS_EXPIRY_TIME)
- multi.expire(concurrent_running_rebalances_key, REDIS_EXPIRY_TIME)
+ multi.expire(CONCURRENT_RUNNING_REBALANCES_KEY, REDIS_EXPIRY_TIME)
end
end
end
def cleanup_cache
+ value = "#{rebalanced_container_type}/#{rebalanced_container_id}"
+
with_redis do |redis|
redis.multi do |multi|
multi.del(issue_ids_key)
multi.del(current_index_key)
multi.del(current_project_key)
- multi.srem(concurrent_running_rebalances_key, "#{rebalanced_container_type}/#{rebalanced_container_id}")
+ multi.srem(CONCURRENT_RUNNING_REBALANCES_KEY, value)
+ multi.set(self.class.recently_finished_key(rebalanced_container_type, rebalanced_container_id), true, ex: 1.hour)
end
end
end
+ def self.rebalance_recently_finished?(project_id, namespace_id)
+ container_id = project_id || namespace_id
+ container_type = project_id.present? ? PROJECT : NAMESPACE
+
+ Gitlab::Redis::SharedState.with { |redis| redis.get(recently_finished_key(container_type, container_id)) }
+ end
+
+ def self.fetch_rebalancing_groups_and_projects
+ namespace_ids = []
+ project_ids = []
+
+ current_rebalancing_containers.each do |string|
+ container_type, container_id = string.split('/', 2).map(&:to_i)
+
+ if container_type == NAMESPACE
+ namespace_ids << container_id
+ elsif container_type == PROJECT
+ project_ids << container_id
+ end
+ end
+
+ [namespace_ids, project_ids]
+ end
+
private
+ def self.current_rebalancing_containers
+ Gitlab::Redis::SharedState.with { |redis| redis.smembers(CONCURRENT_RUNNING_REBALANCES_KEY) }
+ end
+
attr_accessor :root_namespace, :projects, :rebalanced_container_type, :rebalanced_container_id
def too_many_rebalances_running?
concurrent_running_rebalances_count <= MAX_NUMBER_OF_CONCURRENT_REBALANCES
end
- def redis_key_prefix
- "gitlab:issues-position-rebalances"
- end
-
def issue_ids_key
- "#{redis_key_prefix}:#{root_namespace.id}"
+ "#{REDIS_KEY_PREFIX}:#{root_namespace.id}"
end
def current_index_key
@@ -141,8 +170,8 @@ module Gitlab
"#{issue_ids_key}:current_project_id"
end
- def concurrent_running_rebalances_key
- "#{redis_key_prefix}:running_rebalances"
+ def self.recently_finished_key(container_type, container_id)
+ "#{RECENTLY_FINISHED_REBALANCE_PREFIX}:#{container_type}:#{container_id}"
end
def with_redis(&blk)
diff --git a/lib/gitlab/jira/http_client.rb b/lib/gitlab/jira/http_client.rb
index 13d3bb2b8dc..7abfe8e38e8 100644
--- a/lib/gitlab/jira/http_client.rb
+++ b/lib/gitlab/jira/http_client.rb
@@ -32,7 +32,6 @@ module Gitlab
request_params = { headers: headers }
request_params[:body] = body if body.present?
request_params[:headers][:Cookie] = get_cookies if options[:use_cookies]
- request_params[:timeout] = options[:read_timeout] if options[:read_timeout]
request_params[:base_uri] = uri.to_s
request_params.merge!(auth_params)
diff --git a/lib/gitlab/language_detection.rb b/lib/gitlab/language_detection.rb
index fc9fb5caa09..6f7fa9fe03b 100644
--- a/lib/gitlab/language_detection.rb
+++ b/lib/gitlab/language_detection.rb
@@ -18,7 +18,7 @@ module Gitlab
end
# Newly detected languages, returned in a structure accepted by
- # Gitlab::Database.main.bulk_insert
+ # ApplicationRecord.legacy_bulk_insert
def insertions(programming_languages)
lang_to_id = programming_languages.to_h { |p| [p.name, p.id] }
diff --git a/lib/gitlab/lfs_token.rb b/lib/gitlab/lfs_token.rb
index 2e8564b6e00..03655eb7237 100644
--- a/lib/gitlab/lfs_token.rb
+++ b/lib/gitlab/lfs_token.rb
@@ -96,24 +96,15 @@ module Gitlab
attr_reader :actor
def secret
- salt + key
- end
-
- def salt
case actor
when DeployKey, Key
- actor.fingerprint.delete(':').first(16)
+ # Since fingerprint is based on the public key, let's take more bytes from attr_encrypted_db_key_base
+ actor.fingerprint.delete(':').first(16) + Settings.attr_encrypted_db_key_base_32
when User
# Take the last 16 characters as they're more unique than the first 16
- actor.id.to_s + actor.encrypted_password.last(16)
+ actor.id.to_s + actor.encrypted_password.last(16) + Settings.attr_encrypted_db_key_base.first(16)
end
end
-
- def key
- # Take 16 characters of attr_encrypted_db_key_base, as that's what the
- # cipher needs exactly
- Settings.attr_encrypted_db_key_base.first(16)
- end
end
end
end
diff --git a/lib/gitlab/lograge/custom_options.rb b/lib/gitlab/lograge/custom_options.rb
index 83fd74310d0..e6c9ba0773c 100644
--- a/lib/gitlab/lograge/custom_options.rb
+++ b/lib/gitlab/lograge/custom_options.rb
@@ -7,6 +7,8 @@ module Gitlab
LIMITED_ARRAY_SENTINEL = { key: 'truncated', value: '...' }.freeze
IGNORE_PARAMS = Set.new(%w(controller action format)).freeze
+ KNOWN_PAYLOAD_PARAMS = [:remote_ip, :user_id, :username, :ua, :queue_duration_s,
+ :etag_route, :request_urgency, :target_duration_s] + CLOUDFLARE_CUSTOM_HEADERS.values
def self.call(event)
params = event
@@ -14,24 +16,17 @@ module Gitlab
.each_with_object([]) { |(k, v), array| array << { key: k, value: v } unless IGNORE_PARAMS.include?(k) }
payload = {
time: Time.now.utc.iso8601(3),
- params: Gitlab::Utils::LogLimitedArray.log_limited_array(params, sentinel: LIMITED_ARRAY_SENTINEL),
- remote_ip: event.payload[:remote_ip],
- user_id: event.payload[:user_id],
- username: event.payload[:username],
- ua: event.payload[:ua]
+ params: Gitlab::Utils::LogLimitedArray.log_limited_array(params, sentinel: LIMITED_ARRAY_SENTINEL)
}
+
payload.merge!(event.payload[:metadata]) if event.payload[:metadata]
+ optional_payload_params = event.payload.slice(*KNOWN_PAYLOAD_PARAMS).compact
+ payload.merge!(optional_payload_params)
::Gitlab::InstrumentationHelper.add_instrumentation_data(payload)
- payload[:queue_duration_s] = event.payload[:queue_duration_s] if event.payload[:queue_duration_s]
- payload[:etag_route] = event.payload[:etag_route] if event.payload[:etag_route]
payload[Labkit::Correlation::CorrelationId::LOG_KEY] = event.payload[Labkit::Correlation::CorrelationId::LOG_KEY] || Labkit::Correlation::CorrelationId.current_id
- CLOUDFLARE_CUSTOM_HEADERS.each do |_, value|
- payload[value] = event.payload[value] if event.payload[value]
- end
-
# https://github.com/roidrage/lograge#logging-errors--exceptions
exception = event.payload[:exception_object]
diff --git a/lib/gitlab/merge_requests/merge_commit_message.rb b/lib/gitlab/merge_requests/merge_commit_message.rb
new file mode 100644
index 00000000000..2a6a7859b33
--- /dev/null
+++ b/lib/gitlab/merge_requests/merge_commit_message.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+module Gitlab
+ module MergeRequests
+ class MergeCommitMessage
+ def initialize(merge_request:)
+ @merge_request = merge_request
+ end
+
+ def message
+ return unless @merge_request.target_project.merge_commit_template.present?
+
+ message = @merge_request.target_project.merge_commit_template
+ message = message.delete("\r")
+
+ # Remove placeholders that correspond to empty values and are the last word in the line
+ # along with all whitespace characters preceding them.
+ # This allows us to recreate previous default merge commit message behaviour - we skipped new line character
+ # before empty description and before closed issues when none were present.
+ PLACEHOLDERS.each do |key, value|
+ unless value.call(merge_request).present?
+ message = message.gsub(BLANK_PLACEHOLDERS_REGEXES[key], '')
+ end
+ end
+
+ Gitlab::StringPlaceholderReplacer
+ .replace_string_placeholders(message, PLACEHOLDERS_REGEX) do |key|
+ PLACEHOLDERS[key].call(merge_request)
+ end
+ end
+
+ private
+
+ attr_reader :merge_request
+
+ PLACEHOLDERS = {
+ 'source_branch' => ->(merge_request) { merge_request.source_branch.to_s },
+ 'target_branch' => ->(merge_request) { merge_request.target_branch.to_s },
+ 'title' => ->(merge_request) { merge_request.title },
+ 'issues' => ->(merge_request) do
+ return "" if merge_request.visible_closing_issues_for.blank?
+
+ closes_issues_references = merge_request.visible_closing_issues_for.map do |issue|
+ issue.to_reference(merge_request.target_project)
+ end
+ "Closes #{closes_issues_references.to_sentence}"
+ end,
+ 'description' => ->(merge_request) { merge_request.description.presence || '' },
+ 'reference' => ->(merge_request) { merge_request.to_reference(full: true) }
+ }.freeze
+
+ PLACEHOLDERS_REGEX = Regexp.union(PLACEHOLDERS.keys.map do |key|
+ Regexp.new(Regexp.escape(key))
+ end).freeze
+
+ BLANK_PLACEHOLDERS_REGEXES = (PLACEHOLDERS.map do |key, value|
+ [key, Regexp.new("[\n\r]+%{#{Regexp.escape(key)}}$")]
+ end).to_h.freeze
+ end
+ end
+end
diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb
index 4c4942c12d5..6d7ecb53ec3 100644
--- a/lib/gitlab/metrics.rb
+++ b/lib/gitlab/metrics.rb
@@ -29,7 +29,7 @@ module Gitlab
# Allow access from other metrics related middlewares
def self.current_transaction
- Transaction.current
+ WebTransaction.current || BackgroundTransaction.current
end
# Returns the prefix to use for the name of a series.
diff --git a/lib/gitlab/metrics/background_transaction.rb b/lib/gitlab/metrics/background_transaction.rb
index a1fabe75a97..54095461dd4 100644
--- a/lib/gitlab/metrics/background_transaction.rb
+++ b/lib/gitlab/metrics/background_transaction.rb
@@ -2,14 +2,17 @@
module Gitlab
module Metrics
+ # Exclusive transaction-type metrics for background jobs (Sidekiq). One
+ # instance of this class is created for each job going through the Sidekiq
+ # metric middleware. Any metrics dispatched with this instance include
+ # metadata such as endpoint_id, queue, and feature category.
class BackgroundTransaction < Transaction
- # Separate web transaction instance and background transaction instance
- BACKGROUND_THREAD_KEY = :_gitlab_metrics_background_transaction
- BACKGROUND_BASE_LABEL_KEYS = %i(endpoint_id feature_category).freeze
+ THREAD_KEY = :_gitlab_metrics_background_transaction
+ BASE_LABEL_KEYS = %i(queue endpoint_id feature_category).freeze
class << self
def current
- Thread.current[BACKGROUND_THREAD_KEY]
+ Thread.current[THREAD_KEY]
end
def prometheus_metric(name, type, &block)
@@ -19,17 +22,17 @@ module Gitlab
evaluate(&block)
# always filter sensitive labels and merge with base ones
- label_keys BACKGROUND_BASE_LABEL_KEYS | (label_keys - ::Gitlab::Metrics::Transaction::FILTERED_LABEL_KEYS)
+ label_keys BASE_LABEL_KEYS | (label_keys - ::Gitlab::Metrics::Transaction::FILTERED_LABEL_KEYS)
end
end
end
def run
- Thread.current[BACKGROUND_THREAD_KEY] = self
+ Thread.current[THREAD_KEY] = self
yield
ensure
- Thread.current[BACKGROUND_THREAD_KEY] = nil
+ Thread.current[THREAD_KEY] = nil
end
def labels
diff --git a/lib/gitlab/metrics/methods.rb b/lib/gitlab/metrics/methods.rb
index 8ddd76ad7ae..dc9a7ed1312 100644
--- a/lib/gitlab/metrics/methods.rb
+++ b/lib/gitlab/metrics/methods.rb
@@ -13,8 +13,12 @@ module Gitlab
end
class_methods do
- def reload_metric!(name)
- @@_metrics_provider_cache.delete(name)
+ def reload_metric!(name = nil)
+ if name.nil?
+ @@_metrics_provider_cache = {}
+ else
+ @@_metrics_provider_cache.delete(name)
+ end
end
private
diff --git a/lib/gitlab/metrics/rails_slis.rb b/lib/gitlab/metrics/rails_slis.rb
index 69e0c1e9fde..8c40c0ad441 100644
--- a/lib/gitlab/metrics/rails_slis.rb
+++ b/lib/gitlab/metrics/rails_slis.rb
@@ -4,23 +4,32 @@ module Gitlab
module Metrics
module RailsSlis
class << self
- def request_apdex_counters_enabled?
- Feature.enabled?(:request_apdex_counters)
- end
-
def initialize_request_slis_if_needed!
- return unless request_apdex_counters_enabled?
- return if Gitlab::Metrics::Sli.initialized?(:rails_request_apdex)
-
- Gitlab::Metrics::Sli.initialize_sli(:rails_request_apdex, possible_request_labels)
+ Gitlab::Metrics::Sli.initialize_sli(:rails_request_apdex, possible_request_labels) unless Gitlab::Metrics::Sli.initialized?(:rails_request_apdex)
+ Gitlab::Metrics::Sli.initialize_sli(:graphql_query_apdex, possible_graphql_query_labels) unless Gitlab::Metrics::Sli.initialized?(:graphql_query_apdex)
end
def request_apdex
Gitlab::Metrics::Sli[:rails_request_apdex]
end
+ def graphql_query_apdex
+ Gitlab::Metrics::Sli[:graphql_query_apdex]
+ end
+
private
+ def possible_graphql_query_labels
+ ::Gitlab::Graphql::KnownOperations.default.operations.map do |op|
+ {
+ endpoint_id: op.to_caller_id,
+ # We'll be able to correlate feature_category with https://gitlab.com/gitlab-org/gitlab/-/issues/328535
+ feature_category: nil,
+ query_urgency: op.query_urgency.name
+ }
+ end
+ end
+
def possible_request_labels
possible_controller_labels + possible_api_labels
end
@@ -30,10 +39,12 @@ module Gitlab
endpoint_id = API::Base.endpoint_id_for_route(route)
route_class = route.app.options[:for]
feature_category = route_class.feature_category_for_app(route.app)
+ request_urgency = route_class.urgency_for_app(route.app)
{
endpoint_id: endpoint_id,
- feature_category: feature_category
+ feature_category: feature_category,
+ request_urgency: request_urgency.name
}
end
end
@@ -42,7 +53,8 @@ module Gitlab
Gitlab::RequestEndpoints.all_controller_actions.map do |controller, action|
{
endpoint_id: controller.endpoint_id_for_action(action),
- feature_category: controller.feature_category_for_action(action)
+ feature_category: controller.feature_category_for_action(action),
+ request_urgency: controller.urgency_for_action(action).name
}
end
end
diff --git a/lib/gitlab/metrics/requests_rack_middleware.rb b/lib/gitlab/metrics/requests_rack_middleware.rb
index 3a0e34d5615..c143a7f5a1b 100644
--- a/lib/gitlab/metrics/requests_rack_middleware.rb
+++ b/lib/gitlab/metrics/requests_rack_middleware.rb
@@ -79,7 +79,7 @@ module Gitlab
if !health_endpoint && ::Gitlab::Metrics.record_duration_for_status?(status)
self.class.http_request_duration_seconds.observe({ method: method }, elapsed)
- record_apdex_if_needed(env, elapsed)
+ record_apdex(env, elapsed)
end
[status, headers, body]
@@ -113,12 +113,12 @@ module Gitlab
::Gitlab::ApplicationContext.current_context_attribute(:caller_id)
end
- def record_apdex_if_needed(env, elapsed)
- return unless Gitlab::Metrics::RailsSlis.request_apdex_counters_enabled?
+ def record_apdex(env, elapsed)
+ urgency = urgency_for_env(env)
Gitlab::Metrics::RailsSlis.request_apdex.increment(
- labels: labels_from_context,
- success: satisfactory?(env, elapsed)
+ labels: labels_from_context.merge(request_urgency: urgency.name),
+ success: elapsed < urgency.duration
)
end
@@ -129,17 +129,15 @@ module Gitlab
}
end
- def satisfactory?(env, elapsed)
- target =
+ def urgency_for_env(env)
+ endpoint_urgency =
if env['api.endpoint'].present?
env['api.endpoint'].options[:for].try(:urgency_for_app, env['api.endpoint'])
elsif env['action_controller.instance'].present? && env['action_controller.instance'].respond_to?(:urgency)
env['action_controller.instance'].urgency
end
- target ||= Gitlab::EndpointAttributes::DEFAULT_URGENCY
-
- elapsed < target.duration
+ endpoint_urgency || Gitlab::EndpointAttributes::DEFAULT_URGENCY
end
end
end
diff --git a/lib/gitlab/metrics/samplers/action_cable_sampler.rb b/lib/gitlab/metrics/samplers/action_cable_sampler.rb
index 043d2ae84cc..adce3030d0d 100644
--- a/lib/gitlab/metrics/samplers/action_cable_sampler.rb
+++ b/lib/gitlab/metrics/samplers/action_cable_sampler.rb
@@ -39,23 +39,14 @@ module Gitlab
def sample
pool = @action_cable.worker_pool.executor
- labels = {
- server_mode: server_mode
- }
-
- metrics[:active_connections].set(labels, @action_cable.connections.size)
- metrics[:pool_min_size].set(labels, pool.min_length)
- metrics[:pool_max_size].set(labels, pool.max_length)
- metrics[:pool_current_size].set(labels, pool.length)
- metrics[:pool_largest_size].set(labels, pool.largest_length)
- metrics[:pool_completed_tasks].set(labels, pool.completed_task_count)
- metrics[:pool_pending_tasks].set(labels, pool.queue_length)
- end
-
- private
- def server_mode
- Gitlab::ActionCable::Config.in_app? ? 'in-app' : 'standalone'
+ metrics[:active_connections].set({}, @action_cable.connections.size)
+ metrics[:pool_min_size].set({}, pool.min_length)
+ metrics[:pool_max_size].set({}, pool.max_length)
+ metrics[:pool_current_size].set({}, pool.length)
+ metrics[:pool_largest_size].set({}, pool.largest_length)
+ metrics[:pool_completed_tasks].set({}, pool.completed_task_count)
+ metrics[:pool_pending_tasks].set({}, pool.queue_length)
end
end
end
diff --git a/lib/gitlab/metrics/subscribers/action_view.rb b/lib/gitlab/metrics/subscribers/action_view.rb
index fa129025bfe..bc9032a6942 100644
--- a/lib/gitlab/metrics/subscribers/action_view.rb
+++ b/lib/gitlab/metrics/subscribers/action_view.rb
@@ -40,7 +40,7 @@ module Gitlab
end
def current_transaction
- ::Gitlab::Metrics::Transaction.current
+ ::Gitlab::Metrics::WebTransaction.current
end
end
end
diff --git a/lib/gitlab/metrics/subscribers/external_http.rb b/lib/gitlab/metrics/subscribers/external_http.rb
index 60a1b084345..ff8654a2cec 100644
--- a/lib/gitlab/metrics/subscribers/external_http.rb
+++ b/lib/gitlab/metrics/subscribers/external_http.rb
@@ -43,7 +43,7 @@ module Gitlab
private
def current_transaction
- ::Gitlab::Metrics::Transaction.current
+ ::Gitlab::Metrics::WebTransaction.current || ::Gitlab::Metrics::BackgroundTransaction.current
end
def add_to_detail_store(start, payload)
diff --git a/lib/gitlab/metrics/subscribers/rails_cache.rb b/lib/gitlab/metrics/subscribers/rails_cache.rb
index 45344e79796..b5e087d107b 100644
--- a/lib/gitlab/metrics/subscribers/rails_cache.rb
+++ b/lib/gitlab/metrics/subscribers/rails_cache.rb
@@ -65,7 +65,7 @@ module Gitlab
private
def current_transaction
- ::Gitlab::Metrics::Transaction.current
+ ::Gitlab::Metrics::WebTransaction.current
end
def metric_cache_operation_duration_seconds
diff --git a/lib/gitlab/metrics/transaction.rb b/lib/gitlab/metrics/transaction.rb
index 97cc8bed564..56a310548a7 100644
--- a/lib/gitlab/metrics/transaction.rb
+++ b/lib/gitlab/metrics/transaction.rb
@@ -6,35 +6,14 @@ module Gitlab
class Transaction
include Gitlab::Metrics::Methods
- # base label keys shared among all transactions
- BASE_LABEL_KEYS = %i(controller action feature_category).freeze
# labels that potentially contain sensitive information and will be filtered
FILTERED_LABEL_KEYS = %i(branch path).freeze
- THREAD_KEY = :_gitlab_metrics_transaction
-
# The series to store events (e.g. Git pushes) in.
EVENT_SERIES = 'events'
attr_reader :method
- class << self
- def current
- Thread.current[THREAD_KEY]
- end
-
- def prometheus_metric(name, type, &block)
- fetch_metric(type, name) do
- # set default metric options
- docstring "#{name.to_s.humanize} #{type}"
-
- evaluate(&block)
- # always filter sensitive labels and merge with base ones
- label_keys BASE_LABEL_KEYS | (label_keys - FILTERED_LABEL_KEYS)
- end
- end
- end
-
def initialize
@methods = {}
end
@@ -126,10 +105,6 @@ module Gitlab
histogram.observe(filter_labels(labels), value)
end
- def labels
- BASE_LABEL_KEYS.product([nil]).to_h
- end
-
def filter_labels(labels)
labels.empty? ? self.labels : labels.without(*FILTERED_LABEL_KEYS).merge(self.labels)
end
diff --git a/lib/gitlab/metrics/web_transaction.rb b/lib/gitlab/metrics/web_transaction.rb
index 544c142f7bb..fcfa86734e8 100644
--- a/lib/gitlab/metrics/web_transaction.rb
+++ b/lib/gitlab/metrics/web_transaction.rb
@@ -2,12 +2,37 @@
module Gitlab
module Metrics
+ # Exclusive transaction-type metrics for web servers (including Web/Api/Git
+ # fleet). One instance of this class is created for each request going
+ # through the Rack metric middleware. Any metrics dispatched with this
+ # instance include metadata such as controller, action, feature category,
+ # etc.
class WebTransaction < Transaction
+ THREAD_KEY = :_gitlab_metrics_transaction
+ BASE_LABEL_KEYS = %i(controller action feature_category).freeze
+
CONTROLLER_KEY = 'action_controller.instance'
ENDPOINT_KEY = 'api.endpoint'
ALLOWED_SUFFIXES = Set.new(%w[json js atom rss xml zip])
SMALL_BUCKETS = [0.1, 0.25, 0.5, 1.0, 2.5, 5.0].freeze
+ class << self
+ def current
+ Thread.current[THREAD_KEY]
+ end
+
+ def prometheus_metric(name, type, &block)
+ fetch_metric(type, name) do
+ # set default metric options
+ docstring "#{name.to_s.humanize} #{type}"
+
+ evaluate(&block)
+ # always filter sensitive labels and merge with base ones
+ label_keys BASE_LABEL_KEYS | (label_keys - ::Gitlab::Metrics::Transaction::FILTERED_LABEL_KEYS)
+ end
+ end
+ end
+
def initialize(env)
super()
@env = env
diff --git a/lib/gitlab/middleware/compressed_json.rb b/lib/gitlab/middleware/compressed_json.rb
new file mode 100644
index 00000000000..ef6e0db5673
--- /dev/null
+++ b/lib/gitlab/middleware/compressed_json.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Middleware
+ class CompressedJson
+ COLLECTOR_PATH = '/api/v4/error_tracking/collector'
+ MAXIMUM_BODY_SIZE = 200.kilobytes.to_i
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ if compressed_et_request?(env)
+ input = extract(env['rack.input'])
+
+ if input.length > MAXIMUM_BODY_SIZE
+ return too_large
+ end
+
+ env.delete('HTTP_CONTENT_ENCODING')
+ env['CONTENT_LENGTH'] = input.length
+ env['rack.input'] = StringIO.new(input)
+ end
+
+ @app.call(env)
+ end
+
+ def compressed_et_request?(env)
+ post_request?(env) &&
+ gzip_encoding?(env) &&
+ match_content_type?(env) &&
+ match_path?(env)
+ end
+
+ def too_large
+ [413, { 'Content-Type' => 'text/plain' }, ['Payload Too Large']]
+ end
+
+ def relative_url
+ File.join('', Gitlab.config.gitlab.relative_url_root).chomp('/')
+ end
+
+ def extract(input)
+ Zlib::GzipReader.new(input).read(MAXIMUM_BODY_SIZE + 1)
+ end
+
+ def post_request?(env)
+ env['REQUEST_METHOD'] == 'POST'
+ end
+
+ def gzip_encoding?(env)
+ env['HTTP_CONTENT_ENCODING'] == 'gzip'
+ end
+
+ def match_content_type?(env)
+ env['CONTENT_TYPE'] == 'application/json' ||
+ env['CONTENT_TYPE'] == 'application/x-sentry-envelope'
+ end
+
+ def match_path?(env)
+ env['PATH_INFO'].start_with?((File.join(relative_url, COLLECTOR_PATH)))
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/middleware/go.rb b/lib/gitlab/middleware/go.rb
index a1a0356ff58..bfa4e4cf5f8 100644
--- a/lib/gitlab/middleware/go.rb
+++ b/lib/gitlab/middleware/go.rb
@@ -27,6 +27,8 @@ module Gitlab
path: request.fullpath
)
Rack::Response.new('', 403).finish
+ rescue Gitlab::Auth::MissingPersonalAccessTokenError
+ Rack::Response.new('', 401).finish
end
private
diff --git a/lib/gitlab/middleware/query_analyzer.rb b/lib/gitlab/middleware/query_analyzer.rb
new file mode 100644
index 00000000000..8d63c644a69
--- /dev/null
+++ b/lib/gitlab/middleware/query_analyzer.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Middleware
+ class QueryAnalyzer
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ ::Gitlab::Database::QueryAnalyzer.instance.within { @app.call(env) }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/middleware/release_env.rb b/lib/gitlab/middleware/release_env.rb
index 0719fb2e8c6..2439e873e0b 100644
--- a/lib/gitlab/middleware/release_env.rb
+++ b/lib/gitlab/middleware/release_env.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
@@ -14,3 +15,5 @@ module Gitlab
end
end
end
+
+# rubocop:enable Naming/FileName
diff --git a/lib/gitlab/pagination/gitaly_keyset_pager.rb b/lib/gitlab/pagination/gitaly_keyset_pager.rb
index a16bf7a379c..99a3145104a 100644
--- a/lib/gitlab/pagination/gitaly_keyset_pager.rb
+++ b/lib/gitlab/pagination/gitaly_keyset_pager.rb
@@ -30,6 +30,8 @@ module Gitlab
if finder.is_a?(BranchesFinder)
Feature.enabled?(:branch_list_keyset_pagination, project, default_enabled: :yaml)
+ elsif finder.is_a?(TagsFinder)
+ Feature.enabled?(:tag_list_keyset_pagination, project, default_enabled: :yaml)
elsif finder.is_a?(::Repositories::TreeFinder)
Feature.enabled?(:repository_tree_gitaly_pagination, project, default_enabled: :yaml)
else
@@ -42,6 +44,8 @@ module Gitlab
if finder.is_a?(BranchesFinder)
Feature.enabled?(:branch_list_keyset_pagination, project, default_enabled: :yaml)
+ elsif finder.is_a?(TagsFinder)
+ Feature.enabled?(:tag_list_keyset_pagination, project, default_enabled: :yaml)
elsif finder.is_a?(::Repositories::TreeFinder)
Feature.enabled?(:repository_tree_gitaly_pagination, project, default_enabled: :yaml)
else
diff --git a/lib/gitlab/patch/sidekiq_client.rb b/lib/gitlab/patch/sidekiq_client.rb
new file mode 100644
index 00000000000..2de13560cce
--- /dev/null
+++ b/lib/gitlab/patch/sidekiq_client.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Patch
+ module SidekiqClient
+ private
+
+ # This is a copy of https://github.com/mperham/sidekiq/blob/v6.2.2/lib/sidekiq/client.rb#L187-L194
+ # but using `conn.pipelined` instead of `conn.multi`. The multi call isn't needed here because in
+ # the case of scheduled jobs, only one Redis call is made. For other jobs, we don't really need
+ # the commands to be atomic.
+ def raw_push(payloads)
+ @redis_pool.with do |conn| # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ conn.pipelined do
+ atomic_push(conn, payloads)
+ end
+ end
+ true
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/patch/sidekiq_cron_poller.rb b/lib/gitlab/patch/sidekiq_cron_poller.rb
new file mode 100644
index 00000000000..56ca24c68f5
--- /dev/null
+++ b/lib/gitlab/patch/sidekiq_cron_poller.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Patch
+ module SidekiqCronPoller
+ def enqueue
+ Rails.application.reloader.wrap do
+ ::Gitlab::WithRequestStore.with_request_store do
+ super
+ ensure
+ ::Gitlab::Database::LoadBalancing.release_hosts
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/project_template.rb b/lib/gitlab/project_template.rb
index 8875e6320c7..d53b11fe98c 100644
--- a/lib/gitlab/project_template.rb
+++ b/lib/gitlab/project_template.rb
@@ -66,6 +66,7 @@ module Gitlab
ProjectTemplate.new('nfhexo', 'Netlify/Hexo', _('A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features'), 'https://gitlab.com/pages/nfhexo', 'illustrations/logos/netlify.svg'),
ProjectTemplate.new('salesforcedx', 'SalesforceDX', _('A project boilerplate for Salesforce App development with Salesforce Developer tools'), 'https://gitlab.com/gitlab-org/project-templates/salesforcedx'),
ProjectTemplate.new('serverless_framework', 'Serverless Framework/JS', _('A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages'), 'https://gitlab.com/gitlab-org/project-templates/serverless-framework', 'illustrations/logos/serverless_framework.svg'),
+ ProjectTemplate.new('tencent_serverless_framework', 'Tencent Serverless Framework/NextjsSSR', _('A project boilerplate for Tencent Serverless Framework that uses Next.js SSR'), 'https://gitlab.com/gitlab-org/project-templates/nextjsssr_demo', 'illustrations/logos/tencent_serverless_framework.svg'),
ProjectTemplate.new('jsonnet', 'Jsonnet for Dynamic Child Pipelines', _('An example showing how to use Jsonnet with GitLab dynamic child pipelines'), 'https://gitlab.com/gitlab-org/project-templates/jsonnet'),
ProjectTemplate.new('cluster_management', 'GitLab Cluster Management', _('An example project for managing Kubernetes clusters integrated with GitLab'), 'https://gitlab.com/gitlab-org/project-templates/cluster-management'),
ProjectTemplate.new('kotlin_native_linux', 'Kotlin Native Linux', _('A basic template for developing Linux programs using Kotlin Native'), 'https://gitlab.com/gitlab-org/project-templates/kotlin-native-linux')
diff --git a/lib/gitlab/prometheus/queries/validate_query.rb b/lib/gitlab/prometheus/queries/validate_query.rb
index 1f55f3e9768..160db7d44bc 100644
--- a/lib/gitlab/prometheus/queries/validate_query.rb
+++ b/lib/gitlab/prometheus/queries/validate_query.rb
@@ -7,7 +7,7 @@ module Gitlab
def query(query)
client_query(query)
{ valid: true }
- rescue Gitlab::PrometheusClient::QueryError, Gitlab::HTTP::BlockedUrlError => ex
+ rescue Gitlab::PrometheusClient::QueryError, Gitlab::PrometheusClient::ConnectionError => ex
{ valid: false, error: ex.message }
end
diff --git a/lib/gitlab/prometheus_client.rb b/lib/gitlab/prometheus_client.rb
index 8182dbad4f8..dda28ffdf90 100644
--- a/lib/gitlab/prometheus_client.rb
+++ b/lib/gitlab/prometheus_client.rb
@@ -151,12 +151,8 @@ module Gitlab
def get(path, args)
Gitlab::HTTP.get(path, { query: args }.merge(http_options) )
- rescue SocketError
- raise PrometheusClient::ConnectionError, "Can't connect to #{api_url}"
- rescue OpenSSL::SSL::SSLError
- raise PrometheusClient::ConnectionError, "#{api_url} contains invalid SSL data"
- rescue Errno::ECONNREFUSED
- raise PrometheusClient::ConnectionError, 'Connection refused'
+ rescue *Gitlab::HTTP::HTTP_ERRORS => e
+ raise PrometheusClient::ConnectionError, e.message
end
def handle_management_api_response(response)
diff --git a/lib/gitlab/quick_actions/issuable_actions.rb b/lib/gitlab/quick_actions/issuable_actions.rb
index cf5c9296d8c..4bac0643a91 100644
--- a/lib/gitlab/quick_actions/issuable_actions.rb
+++ b/lib/gitlab/quick_actions/issuable_actions.rb
@@ -84,8 +84,7 @@ module Gitlab
params '~label1 ~"label 2"'
types Issuable
condition do
- parent &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", parent) &&
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target) &&
find_labels.any?
end
command :label do |labels_param|
@@ -107,7 +106,7 @@ module Gitlab
condition do
quick_action_target.persisted? &&
quick_action_target.labels.any? &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", parent)
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target)
end
command :unlabel, :remove_label do |labels_param = nil|
if labels_param.present?
@@ -139,7 +138,7 @@ module Gitlab
condition do
quick_action_target.persisted? &&
quick_action_target.labels.any? &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", parent)
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target)
end
command :relabel do |labels_param|
run_label_command(labels: find_labels(labels_param), command: :relabel, updates_key: :label_ids)
diff --git a/lib/gitlab/quick_actions/issue_actions.rb b/lib/gitlab/quick_actions/issue_actions.rb
index c5cf3262039..a55ead519e2 100644
--- a/lib/gitlab/quick_actions/issue_actions.rb
+++ b/lib/gitlab/quick_actions/issue_actions.rb
@@ -19,7 +19,7 @@ module Gitlab
types Issue
condition do
quick_action_target.respond_to?(:due_date) &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target)
end
parse_params do |due_date_param|
Chronic.parse(due_date_param).try(:to_date)
@@ -40,7 +40,7 @@ module Gitlab
quick_action_target.persisted? &&
quick_action_target.respond_to?(:due_date) &&
quick_action_target.due_date? &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target)
end
command :remove_due_date do
@updates[:due_date] = nil
@@ -54,7 +54,7 @@ module Gitlab
params '~"Target column"'
types Issue
condition do
- current_user.can?(:"update_#{quick_action_target.to_ability_name}", quick_action_target) &&
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target) &&
quick_action_target.project.boards.count == 1
end
command :board_move do |target_list_name|
@@ -86,7 +86,7 @@ module Gitlab
types Issue
condition do
quick_action_target.persisted? &&
- current_user.can?(:"update_#{quick_action_target.to_ability_name}", quick_action_target)
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target)
end
command :duplicate do |duplicate_param|
canonical_issue = extract_references(duplicate_param, :issue).first
@@ -172,7 +172,7 @@ module Gitlab
condition do
quick_action_target.issue_type_supports?(:confidentiality) &&
!quick_action_target.confidential? &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", quick_action_target)
+ current_user.can?(:set_confidentiality, quick_action_target)
end
command :confidential do
@updates[:confidential] = true
@@ -264,6 +264,27 @@ module Gitlab
end
end
+ desc _('Promote issue to incident')
+ explanation _('Promotes issue to incident')
+ types Issue
+ condition do
+ quick_action_target.persisted? &&
+ !quick_action_target.incident? &&
+ current_user.can?(:update_issue, quick_action_target)
+ end
+ command :promote_to_incident do
+ issue = ::Issues::UpdateService
+ .new(project: quick_action_target.project, current_user: current_user, params: { issue_type: 'incident' })
+ .execute(quick_action_target)
+
+ @execution_message[:promote_to_incident] =
+ if issue.incident?
+ _('Issue has been promoted to incident')
+ else
+ _('Failed to promote issue to incident')
+ end
+ end
+
private
def zoom_link_service
diff --git a/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb b/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
index b53fdd60606..4a75fa0a571 100644
--- a/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
@@ -26,7 +26,7 @@ module Gitlab
end
types Issue, MergeRequest
condition do
- quick_action_target.supports_assignee? && current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
+ quick_action_target.supports_assignee? && current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target)
end
parse_params do |assignee_param|
extract_users(assignee_param)
@@ -66,7 +66,7 @@ module Gitlab
condition do
quick_action_target.persisted? &&
quick_action_target.assignees.any? &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target)
end
parse_params do |unassign_param|
# When multiple users are assigned, all will be unassigned if multiple assignees are no longer allowed
@@ -92,7 +92,7 @@ module Gitlab
types Issue, MergeRequest
condition do
quick_action_target.supports_milestone? &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project) &&
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target) &&
find_milestones(project, state: 'active').any?
end
parse_params do |milestone_param|
@@ -115,7 +115,7 @@ module Gitlab
quick_action_target.persisted? &&
quick_action_target.milestone_id? &&
quick_action_target.supports_milestone? &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target)
end
command :remove_milestone do
@updates[:milestone_id] = nil
@@ -128,7 +128,7 @@ module Gitlab
params '#issue | !merge_request'
types Issue, MergeRequest
condition do
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", quick_action_target)
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target)
end
parse_params do |issuable_param|
extract_references(issuable_param, :issue).first ||
@@ -225,7 +225,7 @@ module Gitlab
condition do
quick_action_target.persisted? &&
!quick_action_target.discussion_locked? &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", quick_action_target)
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target)
end
command :lock do
@updates[:discussion_locked] = true
@@ -238,7 +238,7 @@ module Gitlab
condition do
quick_action_target.persisted? &&
quick_action_target.discussion_locked? &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", quick_action_target)
+ current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target)
end
command :unlock do
@updates[:discussion_locked] = false
diff --git a/lib/gitlab/redis/hll.rb b/lib/gitlab/redis/hll.rb
index 0d04545688b..4d1855e4637 100644
--- a/lib/gitlab/redis/hll.rb
+++ b/lib/gitlab/redis/hll.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
@@ -51,3 +52,5 @@ module Gitlab
end
end
end
+
+# rubocop:enable Naming/FileName
diff --git a/lib/gitlab/redis/multi_store.rb b/lib/gitlab/redis/multi_store.rb
new file mode 100644
index 00000000000..f930a0040bc
--- /dev/null
+++ b/lib/gitlab/redis/multi_store.rb
@@ -0,0 +1,215 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Redis
+ class MultiStore
+ include Gitlab::Utils::StrongMemoize
+
+ class ReadFromPrimaryError < StandardError
+ def message
+ 'Value not found on the redis primary store. Read from the redis secondary store successful.'
+ end
+ end
+ class MethodMissingError < StandardError
+ def message
+ 'Method missing. Falling back to execute method on the redis secondary store.'
+ end
+ end
+
+ attr_reader :primary_store, :secondary_store, :instance_name
+
+ FAILED_TO_READ_ERROR_MESSAGE = 'Failed to read from the redis primary_store.'
+ FAILED_TO_WRITE_ERROR_MESSAGE = 'Failed to write to the redis primary_store.'
+
+ READ_COMMANDS = %i(
+ get
+ mget
+ smembers
+ scard
+ ).freeze
+
+ WRITE_COMMANDS = %i(
+ set
+ setnx
+ setex
+ sadd
+ srem
+ del
+ pipelined
+ flushdb
+ ).freeze
+
+ def initialize(primary_store, secondary_store, instance_name = nil)
+ @primary_store = primary_store
+ @secondary_store = secondary_store
+ @instance_name = instance_name
+
+ validate_stores!
+ end
+
+ READ_COMMANDS.each do |name|
+ define_method(name) do |*args, &block|
+ if multi_store_enabled?
+ read_command(name, *args, &block)
+ else
+ secondary_store.send(name, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+ end
+
+ WRITE_COMMANDS.each do |name|
+ define_method(name) do |*args, &block|
+ if multi_store_enabled?
+ write_command(name, *args, &block)
+ else
+ secondary_store.send(name, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+ end
+
+ def method_missing(...)
+ return @instance.send(...) if @instance # rubocop:disable GitlabSecurity/PublicSend
+
+ log_method_missing(...)
+
+ secondary_store.send(...) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def respond_to_missing?(command_name, include_private = false)
+ true
+ end
+
+ # This is needed because of Redis::Rack::Connection is requiring Redis::Store
+ # https://github.com/redis-store/redis-rack/blob/a833086ba494083b6a384a1a4e58b36573a9165d/lib/redis/rack/connection.rb#L15
+ # Done similarly in https://github.com/lsegal/yard/blob/main/lib/yard/templates/template.rb#L122
+ def is_a?(klass)
+ return true if klass == secondary_store.class
+
+ super(klass)
+ end
+ alias_method :kind_of?, :is_a?
+
+ def to_s
+ if multi_store_enabled?
+ primary_store.to_s
+ else
+ secondary_store.to_s
+ end
+ end
+
+ private
+
+ def log_method_missing(command_name, *_args)
+ log_error(MethodMissingError.new, command_name)
+ increment_method_missing_count(command_name)
+ end
+
+ def read_command(command_name, *args, &block)
+ if @instance
+ send_command(@instance, command_name, *args, &block)
+ else
+ read_one_with_fallback(command_name, *args, &block)
+ end
+ end
+
+ def write_command(command_name, *args, &block)
+ if @instance
+ send_command(@instance, command_name, *args, &block)
+ else
+ write_both(command_name, *args, &block)
+ end
+ end
+
+ def read_one_with_fallback(command_name, *args, &block)
+ begin
+ value = send_command(primary_store, command_name, *args, &block)
+ rescue StandardError => e
+ log_error(e, command_name,
+ multi_store_error_message: FAILED_TO_READ_ERROR_MESSAGE)
+ end
+
+ value ||= fallback_read(command_name, *args, &block)
+
+ value
+ end
+
+ def fallback_read(command_name, *args, &block)
+ value = send_command(secondary_store, command_name, *args, &block)
+
+ if value
+ log_error(ReadFromPrimaryError.new, command_name)
+ increment_read_fallback_count(command_name)
+ end
+
+ value
+ end
+
+ def write_both(command_name, *args, &block)
+ begin
+ send_command(primary_store, command_name, *args, &block)
+ rescue StandardError => e
+ log_error(e, command_name,
+ multi_store_error_message: FAILED_TO_WRITE_ERROR_MESSAGE)
+ end
+
+ send_command(secondary_store, command_name, *args, &block)
+ end
+
+ def multi_store_enabled?
+ Feature.enabled?(:use_multi_store, default_enabled: :yaml) && !same_redis_store?
+ end
+
+ def same_redis_store?
+ strong_memoize(:same_redis_store) do
+ # <Redis client v4.4.0 for redis:///path_to/redis/redis.socket/5>"
+ primary_store.inspect == secondary_store.inspect
+ end
+ end
+
+ # rubocop:disable GitlabSecurity/PublicSend
+ def send_command(redis_instance, command_name, *args, &block)
+ if block_given?
+ # Make sure that block is wrapped and executed only on the redis instance that is executing the block
+ redis_instance.send(command_name, *args) do |*params|
+ with_instance(redis_instance, *params, &block)
+ end
+ else
+ redis_instance.send(command_name, *args)
+ end
+ end
+ # rubocop:enable GitlabSecurity/PublicSend
+
+ def with_instance(instance, *params)
+ @instance = instance
+
+ yield(*params)
+ ensure
+ @instance = nil
+ end
+
+ def increment_read_fallback_count(command_name)
+ @read_fallback_counter ||= Gitlab::Metrics.counter(:gitlab_redis_multi_store_read_fallback_total, 'Client side Redis MultiStore reading fallback')
+ @read_fallback_counter.increment(command: command_name, instance_name: instance_name)
+ end
+
+ def increment_method_missing_count(command_name)
+ @method_missing_counter ||= Gitlab::Metrics.counter(:gitlab_redis_multi_store_method_missing_total, 'Client side Redis MultiStore method missing')
+ @method_missing_counter.increment(command: command_name, innamece_name: instance_name)
+ end
+
+ def validate_stores!
+ raise ArgumentError, 'primary_store is required' unless primary_store
+ raise ArgumentError, 'secondary_store is required' unless secondary_store
+ raise ArgumentError, 'invalid primary_store' unless primary_store.is_a?(::Redis)
+ raise ArgumentError, 'invalid secondary_store' unless secondary_store.is_a?(::Redis)
+ end
+
+ def log_error(exception, command_name, extra = {})
+ Gitlab::ErrorTracking.log_exception(
+ exception,
+ command_name: command_name,
+ extra: extra.merge(instance_name: instance_name))
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/redis/wrapper.rb b/lib/gitlab/redis/wrapper.rb
index 7b804038146..985c8dc619c 100644
--- a/lib/gitlab/redis/wrapper.rb
+++ b/lib/gitlab/redis/wrapper.rb
@@ -17,7 +17,7 @@ module Gitlab
module Redis
class Wrapper
class << self
- delegate :params, :url, to: :new
+ delegate :params, :url, :store, to: :new
def with
pool.with { |redis| yield redis }
@@ -126,6 +126,10 @@ module Gitlab
sentinels && !sentinels.empty?
end
+ def store(extras = {})
+ ::Redis::Store::Factory.create(redis_store_options.merge(extras))
+ end
+
private
def redis_store_options
diff --git a/lib/gitlab/runtime.rb b/lib/gitlab/runtime.rb
index f60cac0aff0..5fbbfd90be1 100644
--- a/lib/gitlab/runtime.rb
+++ b/lib/gitlab/runtime.rb
@@ -63,12 +63,8 @@ module Gitlab
puma?
end
- def action_cable?
- web_server? && (!!defined?(ACTION_CABLE_SERVER) || Gitlab::ActionCable::Config.in_app?)
- end
-
def multi_threaded?
- puma? || sidekiq? || action_cable?
+ puma? || sidekiq?
end
def puma_in_clustered_mode?
@@ -84,12 +80,15 @@ module Gitlab
if puma? && Puma.respond_to?(:cli_config)
threads += Puma.cli_config.options[:max_threads]
elsif sidekiq?
- # An extra thread for the poller in Sidekiq Cron:
+ # 2 extra threads for the pollers in Sidekiq and Sidekiq Cron:
# https://github.com/ondrejbartas/sidekiq-cron#under-the-hood
- threads += Sidekiq.options[:concurrency] + 1
+ #
+ # These threads execute Sidekiq client middleware when jobs
+ # are enqueued and those can access DB / Redis.
+ threads += Sidekiq.options[:concurrency] + 2
end
- if action_cable?
+ if web_server?
threads += Gitlab::ActionCable::Config.worker_pool_size
end
diff --git a/lib/gitlab/saas.rb b/lib/gitlab/saas.rb
index 9220ad1be6c..1e00bd4cbfc 100644
--- a/lib/gitlab/saas.rb
+++ b/lib/gitlab/saas.rb
@@ -38,11 +38,11 @@ module Gitlab
end
def self.about_pricing_url
- "https://about.gitlab.com/pricing"
+ "https://about.gitlab.com/pricing/"
end
def self.about_pricing_faq_url
- "https://about.gitlab.com/gitlab-com/#faq"
+ "https://about.gitlab.com/pricing#faq"
end
end
end
diff --git a/lib/gitlab/search_results.rb b/lib/gitlab/search_results.rb
index 217a48e740d..37414f9e2b1 100644
--- a/lib/gitlab/search_results.rb
+++ b/lib/gitlab/search_results.rb
@@ -115,6 +115,11 @@ module Gitlab
{}
end
+ # aggregations are only performed by Elasticsearch backed results
+ def aggregations(scope)
+ []
+ end
+
private
def collection_for(scope)
diff --git a/lib/gitlab/setup_helper.rb b/lib/gitlab/setup_helper.rb
index 751405f1045..3a31f651714 100644
--- a/lib/gitlab/setup_helper.rb
+++ b/lib/gitlab/setup_helper.rb
@@ -104,9 +104,6 @@ module Gitlab
socket_filename = options[:gitaly_socket] || "gitaly.socket"
prometheus_listen_addr = options[:prometheus_listen_addr]
- git_bin_path = File.expand_path('../gitaly/_build/deps/git/install/bin/git')
- git_bin_path = nil unless File.exist?(git_bin_path)
-
config = {
# Override the set gitaly_address since Praefect is in the loop
socket_path: File.join(gitaly_dir, socket_filename),
@@ -116,8 +113,8 @@ module Gitlab
# sidekiq jobs, and concurrency will be low anyway in test.
git: {
catfile_cache_size: 5,
- bin_path: git_bin_path
- }.compact,
+ bin_path: File.expand_path(File.join(gitaly_dir, '_build', 'deps', 'git', 'install', 'bin', 'git'))
+ },
prometheus_listen_addr: prometheus_listen_addr
}.compact
diff --git a/lib/gitlab/sidekiq_cluster.rb b/lib/gitlab/sidekiq_cluster.rb
deleted file mode 100644
index cc1bd282da8..00000000000
--- a/lib/gitlab/sidekiq_cluster.rb
+++ /dev/null
@@ -1,171 +0,0 @@
-# frozen_string_literal: true
-
-require 'shellwords'
-
-module Gitlab
- module SidekiqCluster
- # The signals that should terminate both the master and workers.
- TERMINATE_SIGNALS = %i(INT TERM).freeze
-
- # The signals that should simply be forwarded to the workers.
- FORWARD_SIGNALS = %i(TTIN USR1 USR2 HUP).freeze
-
- # Traps the given signals and yields the block whenever these signals are
- # received.
- #
- # The block is passed the name of the signal.
- #
- # Example:
- #
- # trap_signals(%i(HUP TERM)) do |signal|
- # ...
- # end
- def self.trap_signals(signals)
- signals.each do |signal|
- trap(signal) do
- yield signal
- end
- end
- end
-
- def self.trap_terminate(&block)
- trap_signals(TERMINATE_SIGNALS, &block)
- end
-
- def self.trap_forward(&block)
- trap_signals(FORWARD_SIGNALS, &block)
- end
-
- def self.signal(pid, signal)
- Process.kill(signal, pid)
- true
- rescue Errno::ESRCH
- false
- end
-
- def self.signal_processes(pids, signal)
- pids.each { |pid| signal(pid, signal) }
- end
-
- # Starts Sidekiq workers for the pairs of processes.
- #
- # Example:
- #
- # start([ ['foo'], ['bar', 'baz'] ], :production)
- #
- # This would start two Sidekiq processes: one processing "foo", and one
- # processing "bar" and "baz". Each one is placed in its own process group.
- #
- # queues - An Array containing Arrays. Each sub Array should specify the
- # queues to use for a single process.
- #
- # directory - The directory of the Rails application.
- #
- # Returns an Array containing the PIDs of the started processes.
- def self.start(queues, env: :development, directory: Dir.pwd, max_concurrency: 50, min_concurrency: 0, timeout: CLI::DEFAULT_SOFT_TIMEOUT_SECONDS, dryrun: false)
- queues.map.with_index do |pair, index|
- start_sidekiq(pair, env: env,
- directory: directory,
- max_concurrency: max_concurrency,
- min_concurrency: min_concurrency,
- worker_id: index,
- timeout: timeout,
- dryrun: dryrun)
- end
- end
-
- # Starts a Sidekiq process that processes _only_ the given queues.
- #
- # Returns the PID of the started process.
- def self.start_sidekiq(queues, env:, directory:, max_concurrency:, min_concurrency:, worker_id:, timeout:, dryrun:)
- counts = count_by_queue(queues)
-
- cmd = %w[bundle exec sidekiq]
- cmd << "-c#{self.concurrency(queues, min_concurrency, max_concurrency)}"
- cmd << "-e#{env}"
- cmd << "-t#{timeout}"
- cmd << "-gqueues:#{proc_details(counts)}"
- cmd << "-r#{directory}"
-
- counts.each do |queue, count|
- cmd << "-q#{queue},#{count}"
- end
-
- if dryrun
- puts Shellwords.join(cmd) # rubocop:disable Rails/Output
- return
- end
-
- pid = Process.spawn(
- { 'ENABLE_SIDEKIQ_CLUSTER' => '1',
- 'SIDEKIQ_WORKER_ID' => worker_id.to_s },
- *cmd,
- pgroup: true,
- err: $stderr,
- out: $stdout
- )
-
- wait_async(pid)
-
- pid
- end
-
- def self.count_by_queue(queues)
- queues.tally
- end
-
- def self.proc_details(counts)
- counts.map do |queue, count|
- if count == 1
- queue
- else
- "#{queue} (#{count})"
- end
- end.join(',')
- end
-
- def self.concurrency(queues, min_concurrency, max_concurrency)
- concurrency_from_queues = queues.length + 1
- max = max_concurrency > 0 ? max_concurrency : concurrency_from_queues
- min = [min_concurrency, max].min
-
- concurrency_from_queues.clamp(min, max)
- end
-
- # Waits for the given process to complete using a separate thread.
- def self.wait_async(pid)
- Thread.new do
- Process.wait(pid) rescue Errno::ECHILD
- end
- end
-
- # Returns true if all the processes are alive.
- def self.all_alive?(pids)
- pids.each do |pid|
- return false unless process_alive?(pid)
- end
-
- true
- end
-
- def self.any_alive?(pids)
- pids_alive(pids).any?
- end
-
- def self.pids_alive(pids)
- pids.select { |pid| process_alive?(pid) }
- end
-
- def self.process_alive?(pid)
- # Signal 0 tests whether the process exists and we have access to send signals
- # but is otherwise a noop (doesn't actually send a signal to the process)
- signal(pid, 0)
- end
-
- def self.write_pid(path)
- File.open(path, 'w') do |handle|
- handle.write(Process.pid.to_s)
- end
- end
- end
-end
diff --git a/lib/gitlab/sidekiq_cluster/cli.rb b/lib/gitlab/sidekiq_cluster/cli.rb
deleted file mode 100644
index 3dee257229d..00000000000
--- a/lib/gitlab/sidekiq_cluster/cli.rb
+++ /dev/null
@@ -1,230 +0,0 @@
-# frozen_string_literal: true
-
-require 'optparse'
-require 'logger'
-require 'time'
-
-module Gitlab
- module SidekiqCluster
- class CLI
- CHECK_TERMINATE_INTERVAL_SECONDS = 1
-
- # How long to wait when asking for a clean termination.
- # It maps the Sidekiq default timeout:
- # https://github.com/mperham/sidekiq/wiki/Signals#term
- #
- # This value is passed to Sidekiq's `-t` if none
- # is given through arguments.
- DEFAULT_SOFT_TIMEOUT_SECONDS = 25
-
- # After surpassing the soft timeout.
- DEFAULT_HARD_TIMEOUT_SECONDS = 5
-
- CommandError = Class.new(StandardError)
-
- def initialize(log_output = $stderr)
- require_relative '../../../lib/gitlab/sidekiq_logging/json_formatter'
-
- # As recommended by https://github.com/mperham/sidekiq/wiki/Advanced-Options#concurrency
- @max_concurrency = 50
- @min_concurrency = 0
- @environment = ENV['RAILS_ENV'] || 'development'
- @pid = nil
- @interval = 5
- @alive = true
- @processes = []
- @logger = Logger.new(log_output)
- @logger.formatter = ::Gitlab::SidekiqLogging::JSONFormatter.new
- @rails_path = Dir.pwd
- @dryrun = false
- @list_queues = false
- end
-
- def run(argv = ARGV)
- if argv.empty?
- raise CommandError,
- 'You must specify at least one queue to start a worker for'
- end
-
- option_parser.parse!(argv)
-
- if @dryrun && @list_queues
- raise CommandError,
- 'The --dryrun and --list-queues options are mutually exclusive'
- end
-
- worker_metadatas = SidekiqConfig::CliMethods.worker_metadatas(@rails_path)
- worker_queues = SidekiqConfig::CliMethods.worker_queues(@rails_path)
-
- queue_groups = argv.map do |queues_or_query_string|
- if queues_or_query_string =~ /[\r\n]/
- raise CommandError,
- 'The queue arguments cannot contain newlines'
- end
-
- next worker_queues if queues_or_query_string == SidekiqConfig::WorkerMatcher::WILDCARD_MATCH
-
- # When using the queue query syntax, we treat each queue group
- # as a worker attribute query, and resolve the queues for the
- # queue group using this query.
-
- if @queue_selector
- SidekiqConfig::CliMethods.query_queues(queues_or_query_string, worker_metadatas)
- else
- SidekiqConfig::CliMethods.expand_queues(queues_or_query_string.split(','), worker_queues)
- end
- end
-
- if @negate_queues
- queue_groups.map! { |queues| worker_queues - queues }
- end
-
- if queue_groups.all?(&:empty?)
- raise CommandError,
- 'No queues found, you must select at least one queue'
- end
-
- if @list_queues
- puts queue_groups.map(&:sort) # rubocop:disable Rails/Output
-
- return
- end
-
- unless @dryrun
- @logger.info("Starting cluster with #{queue_groups.length} processes")
- end
-
- @processes = SidekiqCluster.start(
- queue_groups,
- env: @environment,
- directory: @rails_path,
- max_concurrency: @max_concurrency,
- min_concurrency: @min_concurrency,
- dryrun: @dryrun,
- timeout: soft_timeout_seconds
- )
-
- return if @dryrun
-
- write_pid
- trap_signals
- start_loop
- end
-
- def write_pid
- SidekiqCluster.write_pid(@pid) if @pid
- end
-
- def soft_timeout_seconds
- @soft_timeout_seconds || DEFAULT_SOFT_TIMEOUT_SECONDS
- end
-
- # The amount of time it'll wait for killing the alive Sidekiq processes.
- def hard_timeout_seconds
- soft_timeout_seconds + DEFAULT_HARD_TIMEOUT_SECONDS
- end
-
- def monotonic_time
- Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second)
- end
-
- def continue_waiting?(deadline)
- SidekiqCluster.any_alive?(@processes) && monotonic_time < deadline
- end
-
- def hard_stop_stuck_pids
- SidekiqCluster.signal_processes(SidekiqCluster.pids_alive(@processes), "-KILL")
- end
-
- def wait_for_termination
- deadline = monotonic_time + hard_timeout_seconds
- sleep(CHECK_TERMINATE_INTERVAL_SECONDS) while continue_waiting?(deadline)
-
- hard_stop_stuck_pids
- end
-
- def trap_signals
- SidekiqCluster.trap_terminate do |signal|
- @alive = false
- SidekiqCluster.signal_processes(@processes, signal)
- wait_for_termination
- end
-
- SidekiqCluster.trap_forward do |signal|
- SidekiqCluster.signal_processes(@processes, signal)
- end
- end
-
- def start_loop
- while @alive
- sleep(@interval)
-
- unless SidekiqCluster.all_alive?(@processes)
- # If a child process died we'll just terminate the whole cluster. It's up to
- # runit and such to then restart the cluster.
- @logger.info('A worker terminated, shutting down the cluster')
-
- SidekiqCluster.signal_processes(@processes, :TERM)
- break
- end
- end
- end
-
- def option_parser
- OptionParser.new do |opt|
- opt.banner = "#{File.basename(__FILE__)} [QUEUE,QUEUE] [QUEUE] ... [OPTIONS]"
-
- opt.separator "\nOptions:\n"
-
- opt.on('-h', '--help', 'Shows this help message') do
- abort opt.to_s
- end
-
- opt.on('-m', '--max-concurrency INT', 'Maximum threads to use with Sidekiq (default: 50, 0 to disable)') do |int|
- @max_concurrency = int.to_i
- end
-
- opt.on('--min-concurrency INT', 'Minimum threads to use with Sidekiq (default: 0)') do |int|
- @min_concurrency = int.to_i
- end
-
- opt.on('-e', '--environment ENV', 'The application environment') do |env|
- @environment = env
- end
-
- opt.on('-P', '--pidfile PATH', 'Path to the PID file') do |pid|
- @pid = pid
- end
-
- opt.on('-r', '--require PATH', 'Location of the Rails application') do |path|
- @rails_path = path
- end
-
- opt.on('--queue-selector', 'Run workers based on the provided selector') do |queue_selector|
- @queue_selector = queue_selector
- end
-
- opt.on('-n', '--negate', 'Run workers for all queues in sidekiq_queues.yml except the given ones') do
- @negate_queues = true
- end
-
- opt.on('-i', '--interval INT', 'The number of seconds to wait between worker checks') do |int|
- @interval = int.to_i
- end
-
- opt.on('-t', '--timeout INT', 'Graceful timeout for all running processes') do |timeout|
- @soft_timeout_seconds = timeout.to_i
- end
-
- opt.on('-d', '--dryrun', 'Print commands that would be run without this flag, and quit') do |int|
- @dryrun = true
- end
-
- opt.on('--list-queues', 'List matching queues, and quit') do |int|
- @list_queues = true
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/sidekiq_config.rb b/lib/gitlab/sidekiq_config.rb
index 5663c51bb7a..07ddac209f8 100644
--- a/lib/gitlab/sidekiq_config.rb
+++ b/lib/gitlab/sidekiq_config.rb
@@ -6,11 +6,13 @@ module Gitlab
module SidekiqConfig
FOSS_QUEUE_CONFIG_PATH = 'app/workers/all_queues.yml'
EE_QUEUE_CONFIG_PATH = 'ee/app/workers/all_queues.yml'
+ JH_QUEUE_CONFIG_PATH = 'jh/app/workers/all_queues.yml'
SIDEKIQ_QUEUES_PATH = 'config/sidekiq_queues.yml'
QUEUE_CONFIG_PATHS = [
FOSS_QUEUE_CONFIG_PATH,
- (EE_QUEUE_CONFIG_PATH if Gitlab.ee?)
+ (EE_QUEUE_CONFIG_PATH if Gitlab.ee?),
+ (JH_QUEUE_CONFIG_PATH if Gitlab.jh?)
].compact.freeze
# This maps workers not in our application code to queues. We need
@@ -33,7 +35,7 @@ module Gitlab
weight: 2,
tags: []
)
- }.transform_values { |worker| Gitlab::SidekiqConfig::Worker.new(worker, ee: false) }.freeze
+ }.transform_values { |worker| Gitlab::SidekiqConfig::Worker.new(worker, ee: false, jh: false) }.freeze
class << self
include Gitlab::SidekiqConfig::CliMethods
@@ -58,10 +60,14 @@ module Gitlab
@workers ||= begin
result = []
result.concat(DEFAULT_WORKERS.values)
- result.concat(find_workers(Rails.root.join('app', 'workers'), ee: false))
+ result.concat(find_workers(Rails.root.join('app', 'workers'), ee: false, jh: false))
if Gitlab.ee?
- result.concat(find_workers(Rails.root.join('ee', 'app', 'workers'), ee: true))
+ result.concat(find_workers(Rails.root.join('ee', 'app', 'workers'), ee: true, jh: false))
+ end
+
+ if Gitlab.jh?
+ result.concat(find_workers(Rails.root.join('jh', 'app', 'workers'), ee: false, jh: true))
end
result
@@ -69,16 +75,26 @@ module Gitlab
end
def workers_for_all_queues_yml
- workers.partition(&:ee?).reverse.map(&:sort)
+ workers.each_with_object([[], [], []]) do |worker, array|
+ if worker.jh?
+ array[2].push(worker)
+ elsif worker.ee?
+ array[1].push(worker)
+ else
+ array[0].push(worker)
+ end
+ end.map(&:sort)
end
# YAML.load_file is OK here as we control the file contents
def all_queues_yml_outdated?
- foss_workers, ee_workers = workers_for_all_queues_yml
+ foss_workers, ee_workers, jh_workers = workers_for_all_queues_yml
return true if foss_workers != YAML.load_file(FOSS_QUEUE_CONFIG_PATH)
- Gitlab.ee? && ee_workers != YAML.load_file(EE_QUEUE_CONFIG_PATH)
+ return true if Gitlab.ee? && ee_workers != YAML.load_file(EE_QUEUE_CONFIG_PATH)
+
+ Gitlab.jh? && File.exist?(JH_QUEUE_CONFIG_PATH) && jh_workers != YAML.load_file(JH_QUEUE_CONFIG_PATH)
end
def queues_for_sidekiq_queues_yml
@@ -120,14 +136,14 @@ module Gitlab
private
- def find_workers(root, ee:)
+ def find_workers(root, ee:, jh:)
concerns = root.join('concerns').to_s
Dir[root.join('**', '*.rb')]
.reject { |path| path.start_with?(concerns) }
.map { |path| worker_from_path(path, root) }
.select { |worker| worker < Sidekiq::Worker }
- .map { |worker| Gitlab::SidekiqConfig::Worker.new(worker, ee: ee) }
+ .map { |worker| Gitlab::SidekiqConfig::Worker.new(worker, ee: ee, jh: jh) }
end
def worker_from_path(path, root)
diff --git a/lib/gitlab/sidekiq_config/cli_methods.rb b/lib/gitlab/sidekiq_config/cli_methods.rb
index 8eef15f9ccb..70798f8c3e8 100644
--- a/lib/gitlab/sidekiq_config/cli_methods.rb
+++ b/lib/gitlab/sidekiq_config/cli_methods.rb
@@ -18,6 +18,7 @@ module Gitlab
QUEUE_CONFIG_PATHS = begin
result = %w[app/workers/all_queues.yml]
result << 'ee/app/workers/all_queues.yml' if Gitlab.ee?
+ result << 'jh/app/workers/all_queues.yml' if Gitlab.jh?
result
end.freeze
diff --git a/lib/gitlab/sidekiq_config/worker.rb b/lib/gitlab/sidekiq_config/worker.rb
index a343573440f..1e3fb675ca7 100644
--- a/lib/gitlab/sidekiq_config/worker.rb
+++ b/lib/gitlab/sidekiq_config/worker.rb
@@ -13,15 +13,20 @@ module Gitlab
:worker_has_external_dependencies?,
to: :klass
- def initialize(klass, ee:)
+ def initialize(klass, ee:, jh: false)
@klass = klass
@ee = ee
+ @jh = jh
end
def ee?
@ee
end
+ def jh?
+ @jh
+ end
+
def ==(other)
to_yaml == case other
when self.class
diff --git a/lib/gitlab/sidekiq_enq.rb b/lib/gitlab/sidekiq_enq.rb
index d8a01ac8ef4..de0c00fe561 100644
--- a/lib/gitlab/sidekiq_enq.rb
+++ b/lib/gitlab/sidekiq_enq.rb
@@ -1,16 +1,44 @@
# frozen_string_literal: true
-# This is a copy of https://github.com/mperham/sidekiq/blob/32c55e31659a1e6bd42f98334cca5eef2863de8d/lib/sidekiq/scheduled.rb#L11-L34
-#
-# It effectively reverts
-# https://github.com/mperham/sidekiq/commit/9b75467b33759888753191413eddbc15c37a219e
-# because we observe that the extra ZREMs caused by this change can lead to high
-# CPU usage on Redis at peak times:
-# https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1179
-#
module Gitlab
class SidekiqEnq
+ LUA_ZPOPBYSCORE = <<~EOS
+ local key, now = KEYS[1], ARGV[1]
+ local jobs = redis.call("zrangebyscore", key, "-inf", now, "limit", 0, 1)
+ if jobs[1] then
+ redis.call("zrem", key, jobs[1])
+ return jobs[1]
+ end
+ EOS
+
+ LUA_ZPOPBYSCORE_SHA = Digest::SHA1.hexdigest(LUA_ZPOPBYSCORE)
+
def enqueue_jobs(now = Time.now.to_f.to_s, sorted_sets = Sidekiq::Scheduled::SETS)
+ Rails.application.reloader.wrap do
+ ::Gitlab::WithRequestStore.with_request_store do
+ if Feature.enabled?(:atomic_sidekiq_scheduler, default_enabled: :yaml)
+ atomic_find_jobs_and_enqueue(now, sorted_sets)
+ else
+ find_jobs_and_enqueue(now, sorted_sets)
+ end
+
+ ensure
+ ::Gitlab::Database::LoadBalancing.release_hosts
+ end
+ end
+ end
+
+ private
+
+ # This is a copy of https://github.com/mperham/sidekiq/blob/32c55e31659a1e6bd42f98334cca5eef2863de8d/lib/sidekiq/scheduled.rb#L11-L34
+ #
+ # It effectively reverts
+ # https://github.com/mperham/sidekiq/commit/9b75467b33759888753191413eddbc15c37a219e
+ # because we observe that the extra ZREMs caused by this change can lead to high
+ # CPU usage on Redis at peak times:
+ # https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1179
+ #
+ def find_jobs_and_enqueue(now, sorted_sets)
# A job's "score" in Redis is the time at which it should be processed.
# Just check Redis for the set of jobs with a timestamp before now.
Sidekiq.redis do |conn|
@@ -24,8 +52,7 @@ module Gitlab
# We need to go through the list one at a time to reduce the risk of something
# going wrong between the time jobs are popped from the scheduled queue and when
# they are pushed onto a work queue and losing the jobs.
- while (job = conn.zrangebyscore(sorted_set, "-inf", now, limit: [0, 1]).first)
-
+ while job = conn.zrangebyscore(sorted_set, "-inf", now, limit: [0, 1]).first
# Pop item off the queue and add it to the work queue. If the job can't be popped from
# the queue, it's because another process already popped it so we can move on to the
# next one.
@@ -47,5 +74,38 @@ module Gitlab
end
end
end
+
+ def atomic_find_jobs_and_enqueue(now, sorted_sets)
+ Sidekiq.redis do |conn|
+ sorted_sets.each do |sorted_set|
+ start_time = ::Gitlab::Metrics::System.monotonic_time
+ jobs = 0
+
+ Sidekiq.logger.info(message: 'Atomically enqueuing scheduled jobs', status: 'start', sorted_set: sorted_set)
+
+ while job = redis_eval_lua(conn, LUA_ZPOPBYSCORE, LUA_ZPOPBYSCORE_SHA, keys: [sorted_set], argv: [now])
+ jobs += 1
+ Sidekiq::Client.push(Sidekiq.load_json(job))
+ end
+
+ end_time = ::Gitlab::Metrics::System.monotonic_time
+ Sidekiq.logger.info(message: 'Atomically enqueuing scheduled jobs',
+ status: 'done',
+ sorted_set: sorted_set,
+ jobs_count: jobs,
+ duration_s: end_time - start_time)
+ end
+ end
+ end
+
+ def redis_eval_lua(conn, script, sha, keys: nil, argv: nil)
+ conn.evalsha(sha, keys: keys, argv: argv)
+ rescue ::Redis::CommandError => e
+ if e.message.start_with?('NOSCRIPT')
+ conn.eval(script, keys: keys, argv: argv)
+ else
+ raise
+ end
+ end
end
end
diff --git a/lib/gitlab/sidekiq_logging/deduplication_logger.rb b/lib/gitlab/sidekiq_logging/deduplication_logger.rb
index c5654819ffb..f4f6cb2a306 100644
--- a/lib/gitlab/sidekiq_logging/deduplication_logger.rb
+++ b/lib/gitlab/sidekiq_logging/deduplication_logger.rb
@@ -6,7 +6,7 @@ module Gitlab
include Singleton
include LogsJobs
- def log(job, deduplication_type, deduplication_options = {})
+ def deduplicated_log(job, deduplication_type, deduplication_options = {})
payload = parse_job(job)
payload['job_status'] = 'deduplicated'
payload['message'] = "#{base_message(payload)}: deduplicated: #{deduplication_type}"
@@ -17,6 +17,14 @@ module Gitlab
Sidekiq.logger.info payload
end
+
+ def rescheduled_log(job)
+ payload = parse_job(job)
+ payload['job_status'] = 'rescheduled'
+ payload['message'] = "#{base_message(payload)}: rescheduled"
+
+ Sidekiq.logger.info payload
+ end
end
end
end
diff --git a/lib/gitlab/sidekiq_logging/json_formatter.rb b/lib/gitlab/sidekiq_logging/json_formatter.rb
index 8894b48417c..a6281bbdf26 100644
--- a/lib/gitlab/sidekiq_logging/json_formatter.rb
+++ b/lib/gitlab/sidekiq_logging/json_formatter.rb
@@ -6,7 +6,7 @@ require 'json'
module Gitlab
module SidekiqLogging
class JSONFormatter
- TIMESTAMP_FIELDS = %w[created_at enqueued_at started_at retried_at failed_at completed_at].freeze
+ TIMESTAMP_FIELDS = %w[created_at scheduled_at enqueued_at started_at retried_at failed_at completed_at].freeze
def call(severity, timestamp, progname, data)
output = {
diff --git a/lib/gitlab/sidekiq_middleware.rb b/lib/gitlab/sidekiq_middleware.rb
index c97b1632bf8..69802fd6217 100644
--- a/lib/gitlab/sidekiq_middleware.rb
+++ b/lib/gitlab/sidekiq_middleware.rb
@@ -33,6 +33,7 @@ module Gitlab
chain.add ::Gitlab::SidekiqMiddleware::BatchLoader
chain.add ::Gitlab::SidekiqMiddleware::InstrumentationLogger
chain.add ::Gitlab::SidekiqMiddleware::AdminMode::Server
+ chain.add ::Gitlab::SidekiqMiddleware::QueryAnalyzer if Gitlab.dev_or_test_env? || Gitlab::Utils.to_boolean(ENV['GITLAB_ENABLE_QUERY_ANALYZERS'], default: false)
chain.add ::Gitlab::SidekiqVersioning::Middleware
chain.add ::Gitlab::SidekiqStatus::ServerMiddleware
chain.add ::Gitlab::SidekiqMiddleware::WorkerContext::Server
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
index e63164efc94..f31262bfcc9 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
@@ -19,11 +19,12 @@ module Gitlab
class DuplicateJob
include Gitlab::Utils::StrongMemoize
- DUPLICATE_KEY_TTL = 6.hours
+ DEFAULT_DUPLICATE_KEY_TTL = 6.hours
WAL_LOCATION_TTL = 60.seconds
MAX_REDIS_RETRIES = 5
DEFAULT_STRATEGY = :until_executing
STRATEGY_NONE = :none
+ DEDUPLICATED_FLAG_VALUE = 1
LUA_SET_WAL_SCRIPT = <<~EOS
local key, wal, offset, ttl = KEYS[1], ARGV[1], tonumber(ARGV[2]), ARGV[3]
@@ -58,7 +59,7 @@ module Gitlab
end
# This method will return the jid that was set in redis
- def check!(expiry = DUPLICATE_KEY_TTL)
+ def check!(expiry = duplicate_key_ttl)
read_jid = nil
read_wal_locations = {}
@@ -83,7 +84,11 @@ module Gitlab
Sidekiq.redis do |redis|
redis.multi do |multi|
job_wal_locations.each do |connection_name, location|
- multi.eval(LUA_SET_WAL_SCRIPT, keys: [wal_location_key(connection_name)], argv: [location, pg_wal_lsn_diff(connection_name).to_i, WAL_LOCATION_TTL])
+ multi.eval(
+ LUA_SET_WAL_SCRIPT,
+ keys: [wal_location_key(connection_name)],
+ argv: [location, pg_wal_lsn_diff(connection_name).to_i, WAL_LOCATION_TTL]
+ )
end
end
end
@@ -110,12 +115,18 @@ module Gitlab
def delete!
Sidekiq.redis do |redis|
redis.multi do |multi|
- multi.del(idempotency_key)
+ multi.del(idempotency_key, deduplicated_flag_key)
delete_wal_locations!(multi)
end
end
end
+ def reschedule
+ Gitlab::SidekiqLogging::DeduplicationLogger.instance.rescheduled_log(job)
+
+ worker_klass.perform_async(*arguments)
+ end
+
def scheduled?
scheduled_at.present?
end
@@ -126,6 +137,22 @@ module Gitlab
jid != existing_jid
end
+ def set_deduplicated_flag!(expiry = duplicate_key_ttl)
+ return unless reschedulable?
+
+ Sidekiq.redis do |redis|
+ redis.set(deduplicated_flag_key, DEDUPLICATED_FLAG_VALUE, ex: expiry, nx: true)
+ end
+ end
+
+ def should_reschedule?
+ return false unless reschedulable?
+
+ Sidekiq.redis do |redis|
+ redis.get(deduplicated_flag_key).present?
+ end
+ end
+
def scheduled_at
job['at']
end
@@ -145,6 +172,10 @@ module Gitlab
worker_klass.idempotent?
end
+ def duplicate_key_ttl
+ options[:ttl] || DEFAULT_DUPLICATE_KEY_TTL
+ end
+
private
attr_writer :existing_wal_locations
@@ -181,7 +212,12 @@ module Gitlab
end
def pg_wal_lsn_diff(connection_name)
- Gitlab::Database.databases[connection_name].pg_wal_lsn_diff(job_wal_locations[connection_name], existing_wal_locations[connection_name])
+ model = Gitlab::Database.database_base_models[connection_name]
+
+ model.connection.load_balancer.wal_diff(
+ job_wal_locations[connection_name],
+ existing_wal_locations[connection_name]
+ )
end
def strategy
@@ -216,6 +252,10 @@ module Gitlab
@idempotency_key ||= job['idempotency_key'] || "#{namespace}:#{idempotency_hash}"
end
+ def deduplicated_flag_key
+ "#{idempotency_key}:deduplicate_flag"
+ end
+
def idempotency_hash
Digest::SHA256.hexdigest(idempotency_string)
end
@@ -235,6 +275,10 @@ module Gitlab
def preserve_wal_location?
Feature.enabled?(:preserve_latest_wal_locations_for_idempotent_jobs, default_enabled: :yaml)
end
+
+ def reschedulable?
+ !scheduled? && options[:if_deduplicated] == :reschedule_once
+ end
end
end
end
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/server.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/server.rb
index a35edc5774e..6d5d41902ea 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/server.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/server.rb
@@ -5,7 +5,7 @@ module Gitlab
module DuplicateJobs
class Server
def call(worker, job, queue, &block)
- DuplicateJob.new(job, queue).perform(&block)
+ ::Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob.new(job, queue).perform(&block)
end
end
end
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/base.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/base.rb
index df5df590281..9b3066bae6c 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/base.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/base.rb
@@ -26,8 +26,8 @@ module Gitlab
end
def check!
- # The default expiry time is the DuplicateJob::DUPLICATE_KEY_TTL already
- # Only the strategies de-duplicating when scheduling
+ # The default expiry time is the worker class'
+ # configured deduplication TTL or DuplicateJob::DEFAULT_DUPLICATE_KEY_TTL.
duplicate_job.check!
end
end
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/deduplicates_when_scheduling.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/deduplicates_when_scheduling.rb
index b0da85b74a6..0fc95534e2a 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/deduplicates_when_scheduling.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/deduplicates_when_scheduling.rb
@@ -6,6 +6,7 @@ module Gitlab
module Strategies
class DeduplicatesWhenScheduling < Base
extend ::Gitlab::Utils::Override
+ include ::Gitlab::Utils::StrongMemoize
override :initialize
def initialize(duplicate_job)
@@ -19,8 +20,9 @@ module Gitlab
if duplicate_job.idempotent?
duplicate_job.update_latest_wal_location!
+ duplicate_job.set_deduplicated_flag!(expiry)
- Gitlab::SidekiqLogging::DeduplicationLogger.instance.log(
+ Gitlab::SidekiqLogging::DeduplicationLogger.instance.deduplicated_log(
job, "dropped #{strategy_name}", duplicate_job.options)
return false
end
@@ -49,11 +51,16 @@ module Gitlab
end
def expiry
- return DuplicateJob::DUPLICATE_KEY_TTL unless duplicate_job.scheduled?
+ strong_memoize(:expiry) do
+ next duplicate_job.duplicate_key_ttl unless duplicate_job.scheduled?
- time_diff = duplicate_job.scheduled_at.to_i - Time.now.to_i
+ time_diff = [
+ duplicate_job.scheduled_at.to_i - Time.now.to_i,
+ 0
+ ].max
- time_diff > 0 ? time_diff : DuplicateJob::DUPLICATE_KEY_TTL
+ time_diff + duplicate_job.duplicate_key_ttl
+ end
end
end
end
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed.rb
index 25f1b8b7c51..8c7e15364f8 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed.rb
@@ -14,7 +14,10 @@ module Gitlab
yield
+ should_reschedule = duplicate_job.should_reschedule?
+ # Deleting before rescheduling to make sure we don't deduplicate again.
duplicate_job.delete!
+ duplicate_job.reschedule if should_reschedule
end
end
end
diff --git a/lib/gitlab/sidekiq_middleware/query_analyzer.rb b/lib/gitlab/sidekiq_middleware/query_analyzer.rb
new file mode 100644
index 00000000000..4478fcd3594
--- /dev/null
+++ b/lib/gitlab/sidekiq_middleware/query_analyzer.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SidekiqMiddleware
+ class QueryAnalyzer
+ def call(worker, job, queue)
+ ::Gitlab::Database::QueryAnalyzer.instance.within { yield }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sidekiq_middleware/size_limiter/validator.rb b/lib/gitlab/sidekiq_middleware/size_limiter/validator.rb
index 71316bbd243..6186c9ad1f4 100644
--- a/lib/gitlab/sidekiq_middleware/size_limiter/validator.rb
+++ b/lib/gitlab/sidekiq_middleware/size_limiter/validator.rb
@@ -55,18 +55,15 @@ module Gitlab
attr_reader :mode, :size_limit, :compression_threshold
- def initialize(
- worker_class, job,
- mode: Gitlab::CurrentSettings.sidekiq_job_limiter_mode,
- compression_threshold: Gitlab::CurrentSettings.sidekiq_job_limiter_compression_threshold_bytes,
- size_limit: Gitlab::CurrentSettings.sidekiq_job_limiter_limit_bytes
- )
+ def initialize(worker_class, job)
@worker_class = worker_class
@job = job
- set_mode(mode)
- set_compression_threshold(compression_threshold)
- set_size_limit(size_limit)
+ current_settings = Gitlab::CurrentSettings.current_application_settings
+
+ @mode = current_settings.sidekiq_job_limiter_mode
+ @compression_threshold = current_settings.sidekiq_job_limiter_compression_threshold_bytes
+ @size_limit = current_settings.sidekiq_job_limiter_limit_bytes
end
def validate!
@@ -90,30 +87,6 @@ module Gitlab
private
- def set_mode(mode)
- @mode = (mode || TRACK_MODE).to_s.strip
- unless MODES.include?(@mode)
- ::Sidekiq.logger.warn "Invalid Sidekiq size limiter mode: #{@mode}. Fallback to #{TRACK_MODE} mode."
- @mode = TRACK_MODE
- end
- end
-
- def set_compression_threshold(compression_threshold)
- @compression_threshold = (compression_threshold || DEFAULT_COMPRESSION_THRESHOLD_BYTES).to_i
- if @compression_threshold <= 0
- ::Sidekiq.logger.warn "Invalid Sidekiq size limiter compression threshold: #{@compression_threshold}"
- @compression_threshold = DEFAULT_COMPRESSION_THRESHOLD_BYTES
- end
- end
-
- def set_size_limit(size_limit)
- @size_limit = (size_limit || DEFAULT_SIZE_LIMIT).to_i
- if @size_limit < 0
- ::Sidekiq.logger.warn "Invalid Sidekiq size limiter limit: #{@size_limit}"
- @size_limit = DEFAULT_SIZE_LIMIT
- end
- end
-
def exceed_limit_error(job_args)
ExceedLimitError.new(@worker_class, job_args.bytesize, @size_limit).tap do |exception|
# This should belong to Gitlab::ErrorTracking. We'll remove this
diff --git a/lib/gitlab/sidekiq_status.rb b/lib/gitlab/sidekiq_status.rb
index 623fdd89456..fbf2718d718 100644
--- a/lib/gitlab/sidekiq_status.rb
+++ b/lib/gitlab/sidekiq_status.rb
@@ -7,12 +7,16 @@ module Gitlab
# To check if a job has been completed, simply pass the job ID to the
# `completed?` method:
#
- # job_id = SomeWorker.perform_async(...)
+ # job_id = SomeWorker.with_status.perform_async(...)
#
# if Gitlab::SidekiqStatus.completed?(job_id)
# ...
# end
#
+ # If you do not use `with_status`, and the worker class does not declare
+ # `status_expiration` in its `sidekiq_options`, then this status will not be
+ # stored.
+ #
# For each job ID registered a separate key is stored in Redis, making lookups
# much faster than using Sidekiq's built-in job finding/status API. These keys
# expire after a certain period of time to prevent storing too many keys in
diff --git a/lib/gitlab/slash_commands/result.rb b/lib/gitlab/slash_commands/result.rb
index a66a2e0726b..d488606120f 100644
--- a/lib/gitlab/slash_commands/result.rb
+++ b/lib/gitlab/slash_commands/result.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
@@ -5,3 +6,5 @@ module Gitlab
Result = Struct.new(:type, :message)
end
end
+
+# rubocop:enable Naming/FileName
diff --git a/lib/gitlab/spamcheck/client.rb b/lib/gitlab/spamcheck/client.rb
index df6d3eb7d0a..925ca44dfc9 100644
--- a/lib/gitlab/spamcheck/client.rb
+++ b/lib/gitlab/spamcheck/client.rb
@@ -5,6 +5,7 @@ module Gitlab
module Spamcheck
class Client
include ::Spam::SpamConstants
+
DEFAULT_TIMEOUT_SECS = 2
VERDICT_MAPPING = {
@@ -27,12 +28,7 @@ module Gitlab
# connect with Spamcheck
@endpoint_url = @endpoint_url.gsub(%r(^grpc:\/\/), '')
- @creds =
- if Rails.env.development? || Rails.env.test?
- :this_channel_is_insecure
- else
- GRPC::Core::ChannelCredentials.new
- end
+ @creds = stub_creds
end
def issue_spam?(spam_issue:, user:, context: {})
@@ -73,6 +69,8 @@ module Gitlab
user_pb.emails << build_email(user.email, user.confirmed?)
user.emails.each do |email|
+ next if email.user_primary_email?
+
user_pb.emails << build_email(email.email, email.confirmed?)
end
@@ -98,6 +96,14 @@ module Gitlab
nanos: ar_timestamp.to_time.nsec)
end
+ def stub_creds
+ if Rails.env.development? || Rails.env.test?
+ :this_channel_is_insecure
+ else
+ GRPC::Core::ChannelCredentials.new ::Gitlab::X509::Certificate.ca_certs_bundle
+ end
+ end
+
def grpc_client
@grpc_client ||= ::Spamcheck::SpamcheckService::Stub.new(@endpoint_url, @creds,
interceptors: interceptors,
diff --git a/lib/gitlab/subscription_portal.rb b/lib/gitlab/subscription_portal.rb
index 9b6bae12057..4f6d25097e2 100644
--- a/lib/gitlab/subscription_portal.rb
+++ b/lib/gitlab/subscription_portal.rb
@@ -4,11 +4,7 @@ module Gitlab
module SubscriptionPortal
def self.default_subscriptions_url
if ::Gitlab.dev_or_test_env?
- if Feature.enabled?(:new_customersdot_staging_url, default_enabled: :yaml)
- 'https://customers.staging.gitlab.com'
- else
- 'https://customers.stg.gitlab.com'
- end
+ 'https://customers.staging.gitlab.com'
else
'https://customers.gitlab.com'
end
@@ -43,7 +39,7 @@ module Gitlab
end
def self.subscriptions_plans_url
- "#{self.subscriptions_url}/plans"
+ Gitlab::Saas.about_pricing_url
end
def self.subscriptions_gitlab_plans_url
diff --git a/lib/gitlab/template_parser/ast.rb b/lib/gitlab/template_parser/ast.rb
index 89318ee0d68..c6a5f66c377 100644
--- a/lib/gitlab/template_parser/ast.rb
+++ b/lib/gitlab/template_parser/ast.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
@@ -155,3 +156,5 @@ module Gitlab
end
end
end
+
+# rubocop:enable Naming/FileName
diff --git a/lib/gitlab/testing/request_inspector_middleware.rb b/lib/gitlab/testing/request_inspector_middleware.rb
index 36cdfebcc28..3cbe97cd84c 100644
--- a/lib/gitlab/testing/request_inspector_middleware.rb
+++ b/lib/gitlab/testing/request_inspector_middleware.rb
@@ -9,6 +9,8 @@ module Gitlab
@@logged_requests = Concurrent::Array.new
@@inject_headers = Concurrent::Hash.new
+ Request = Struct.new(:url, :status_code, :request_headers, :response_headers, :body, keyword_init: true)
+
# Resets the current request log and starts logging requests
def self.log_requests!(headers = {})
@@inject_headers.replace(headers)
@@ -40,7 +42,7 @@ module Gitlab
full_body = +''
body.each { |b| full_body << b }
- request = OpenStruct.new(
+ request = Request.new(
url: url,
status_code: status,
request_headers: request_headers,
diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
index f4fbea50515..ec032cf2d3c 100644
--- a/lib/gitlab/tracking.rb
+++ b/lib/gitlab/tracking.rb
@@ -6,38 +6,37 @@ module Gitlab
class << self
def enabled?
- Gitlab::CurrentSettings.snowplow_enabled?
+ snowplow_micro_enabled? || Gitlab::CurrentSettings.snowplow_enabled?
end
def event(category, action, label: nil, property: nil, value: nil, context: [], project: nil, user: nil, namespace: nil, **extra) # rubocop:disable Metrics/ParameterLists
contexts = [Tracking::StandardContext.new(project: project, user: user, namespace: namespace, **extra).to_context, *context]
snowplow.event(category, action, label: label, property: property, value: value, context: contexts)
- product_analytics.event(category, action, label: label, property: property, value: value, context: contexts)
rescue StandardError => error
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error, snowplow_category: category, snowplow_action: action)
end
def options(group)
- additional_features = Feature.enabled?(:additional_snowplow_tracking, group)
- {
- namespace: SNOWPLOW_NAMESPACE,
- hostname: Gitlab::CurrentSettings.snowplow_collector_hostname,
- cookie_domain: Gitlab::CurrentSettings.snowplow_cookie_domain,
- app_id: Gitlab::CurrentSettings.snowplow_app_id,
- form_tracking: additional_features,
- link_click_tracking: additional_features
- }.transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
+ snowplow.options(group)
+ end
+
+ def collector_hostname
+ snowplow.hostname
end
private
def snowplow
- @snowplow ||= Gitlab::Tracking::Destinations::Snowplow.new
+ @snowplow ||= if snowplow_micro_enabled?
+ Gitlab::Tracking::Destinations::SnowplowMicro.new
+ else
+ Gitlab::Tracking::Destinations::Snowplow.new
+ end
end
- def product_analytics
- @product_analytics ||= Gitlab::Tracking::Destinations::ProductAnalytics.new
+ def snowplow_micro_enabled?
+ Rails.env.development? && Gitlab::Utils.to_boolean(ENV['SNOWPLOW_MICRO_ENABLE'])
end
end
end
diff --git a/lib/gitlab/tracking/destinations/product_analytics.rb b/lib/gitlab/tracking/destinations/product_analytics.rb
deleted file mode 100644
index cacedbc5b83..00000000000
--- a/lib/gitlab/tracking/destinations/product_analytics.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Tracking
- module Destinations
- class ProductAnalytics < Base
- extend ::Gitlab::Utils::Override
- include ::Gitlab::Utils::StrongMemoize
-
- override :event
- def event(category, action, label: nil, property: nil, value: nil, context: nil)
- return unless event_allowed?(category, action)
- return unless enabled?
-
- tracker.track_struct_event(category, action, label, property, value, context, (Time.now.to_f * 1000).to_i)
- end
-
- private
-
- def event_allowed?(category, action)
- category == 'epics' && action == 'promote'
- end
-
- def enabled?
- Feature.enabled?(:product_analytics_tracking, type: :ops) &&
- Gitlab::CurrentSettings.usage_ping_enabled? &&
- Gitlab::CurrentSettings.self_monitoring_project_id.present?
- end
-
- def tracker
- @tracker ||= SnowplowTracker::Tracker.new(
- SnowplowTracker::AsyncEmitter.new(::ProductAnalytics::Tracker::COLLECTOR_URL, protocol: Gitlab.config.gitlab.protocol),
- SnowplowTracker::Subject.new,
- Gitlab::Tracking::SNOWPLOW_NAMESPACE,
- Gitlab::CurrentSettings.self_monitoring_project_id.to_s
- )
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/tracking/destinations/snowplow.rb b/lib/gitlab/tracking/destinations/snowplow.rb
index 07a53b0892b..5596e9acd30 100644
--- a/lib/gitlab/tracking/destinations/snowplow.rb
+++ b/lib/gitlab/tracking/destinations/snowplow.rb
@@ -16,25 +16,53 @@ module Gitlab
increment_total_events_counter
end
+ def options(group)
+ additional_features = Feature.enabled?(:additional_snowplow_tracking, group, type: :ops)
+ {
+ namespace: Gitlab::Tracking::SNOWPLOW_NAMESPACE,
+ hostname: hostname,
+ cookie_domain: cookie_domain,
+ app_id: app_id,
+ form_tracking: additional_features,
+ link_click_tracking: additional_features
+ }.transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
+ end
+
+ def hostname
+ Gitlab::CurrentSettings.snowplow_collector_hostname
+ end
+
private
def enabled?
Gitlab::Tracking.enabled?
end
+ def app_id
+ Gitlab::CurrentSettings.snowplow_app_id
+ end
+
+ def protocol
+ 'https'
+ end
+
+ def cookie_domain
+ Gitlab::CurrentSettings.snowplow_cookie_domain
+ end
+
def tracker
@tracker ||= SnowplowTracker::Tracker.new(
emitter,
SnowplowTracker::Subject.new,
Gitlab::Tracking::SNOWPLOW_NAMESPACE,
- Gitlab::CurrentSettings.snowplow_app_id
+ app_id
)
end
def emitter
SnowplowTracker::AsyncEmitter.new(
- Gitlab::CurrentSettings.snowplow_collector_hostname,
- protocol: 'https',
+ hostname,
+ protocol: protocol,
on_success: method(:increment_successful_events_emissions),
on_failure: method(:failure_callback)
)
@@ -68,8 +96,6 @@ module Gitlab
end
def log_failures(failures)
- hostname = Gitlab::CurrentSettings.snowplow_collector_hostname
-
failures.each do |failure|
Gitlab::AppLogger.error("#{failure["se_ca"]} #{failure["se_ac"]} failed to be reported to collector at #{hostname}")
end
diff --git a/lib/gitlab/tracking/destinations/snowplow_micro.rb b/lib/gitlab/tracking/destinations/snowplow_micro.rb
new file mode 100644
index 00000000000..b818d349a6d
--- /dev/null
+++ b/lib/gitlab/tracking/destinations/snowplow_micro.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+#
+module Gitlab
+ module Tracking
+ module Destinations
+ class SnowplowMicro < Snowplow
+ include ::Gitlab::Utils::StrongMemoize
+ extend ::Gitlab::Utils::Override
+
+ DEFAULT_URI = 'http://localhost:9090'
+
+ override :options
+ def options(group)
+ super.update(
+ protocol: uri.scheme,
+ port: uri.port,
+ force_secure_tracker: false
+ )
+ end
+
+ override :hostname
+ def hostname
+ "#{uri.host}:#{uri.port}"
+ end
+
+ private
+
+ def uri
+ strong_memoize(:snowplow_uri) do
+ uri = URI(ENV['SNOWPLOW_MICRO_URI'] || DEFAULT_URI)
+ uri = URI("http://#{ENV['SNOWPLOW_MICRO_URI']}") unless %w[http https].include?(uri.scheme)
+ uri
+ end
+ end
+
+ override :cookie_domain
+ def cookie_domain
+ '.gitlab.com'
+ end
+
+ override :protocol
+ def protocol
+ uri.scheme
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracking/standard_context.rb b/lib/gitlab/tracking/standard_context.rb
index df62e8bbbe6..837390b91fb 100644
--- a/lib/gitlab/tracking/standard_context.rb
+++ b/lib/gitlab/tracking/standard_context.rb
@@ -43,15 +43,8 @@ module Gitlab
environment: environment,
source: source,
plan: plan,
- extra: extra
- }.merge(project_and_namespace)
- .merge(user_data)
- end
-
- def project_and_namespace
- return {} unless ::Feature.enabled?(:add_namespace_and_project_to_snowplow_tracking, default_enabled: :yaml)
-
- {
+ extra: extra,
+ user_id: user&.id,
namespace_id: namespace&.id,
project_id: project_id
}
@@ -60,10 +53,6 @@ module Gitlab
def project_id
project.is_a?(Integer) ? project : project&.id
end
-
- def user_data
- ::Feature.enabled?(:add_actor_based_user_to_snowplow_tracking, user) ? { user_id: user&.id } : {}
- end
end
end
end
diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb
index 10822f943b6..2c5d76ba41d 100644
--- a/lib/gitlab/url_blocker.rb
+++ b/lib/gitlab/url_blocker.rb
@@ -164,15 +164,21 @@ module Gitlab
end
def parse_url(url)
- raise Addressable::URI::InvalidURIError if multiline?(url)
-
- Addressable::URI.parse(url)
+ Addressable::URI.parse(url).tap do |parsed_url|
+ raise Addressable::URI::InvalidURIError if multiline_blocked?(parsed_url)
+ end
rescue Addressable::URI::InvalidURIError, URI::InvalidURIError
raise BlockedUrlError, 'URI is invalid'
end
- def multiline?(url)
- CGI.unescape(url.to_s) =~ /\n|\r/
+ def multiline_blocked?(parsed_url)
+ url = parsed_url.to_s
+
+ return true if url =~ /\n|\r/
+ # Google Cloud Storage uses a multi-line, encoded Signature query string
+ return false if %w(http https).include?(parsed_url.scheme&.downcase)
+
+ CGI.unescape(url) =~ /\n|\r/
end
def validate_port(port, ports)
diff --git a/lib/gitlab/usage/metric.rb b/lib/gitlab/usage/metric.rb
index 5b1ac189c13..24e044c5740 100644
--- a/lib/gitlab/usage/metric.rb
+++ b/lib/gitlab/usage/metric.rb
@@ -25,6 +25,10 @@ module Gitlab
unflatten_key_path(intrumentation_object.instrumentation)
end
+ def with_suggested_name
+ unflatten_key_path(intrumentation_object.suggested_name)
+ end
+
private
def unflatten_key_path(value)
diff --git a/lib/gitlab/usage/metrics/names_suggestions/generator.rb b/lib/gitlab/usage/metrics/names_suggestions/generator.rb
index b47dc5689d4..6dcbe5f5fe5 100644
--- a/lib/gitlab/usage/metrics/names_suggestions/generator.rb
+++ b/lib/gitlab/usage/metrics/names_suggestions/generator.rb
@@ -10,14 +10,18 @@ module Gitlab
uncached_data.deep_stringify_keys.dig(*key_path.split('.'))
end
- def add_metric(metric, time_frame: 'none')
+ def add_metric(metric, time_frame: 'none', options: {})
metric_class = "Gitlab::Usage::Metrics::Instrumentations::#{metric}".constantize
- metric_class.new(time_frame: time_frame).suggested_name
+ metric_class.new(time_frame: time_frame, options: options).suggested_name
end
private
+ def instrumentation_metrics
+ ::Gitlab::UsageDataMetrics.suggested_names
+ end
+
def count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
Gitlab::Usage::Metrics::NameSuggestion.for(:count, column: column, relation: relation)
end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index dd66f9133bb..20e526aeefa 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -45,23 +45,10 @@ module Gitlab
clear_memoized
with_finished_at(:recording_ce_finished_at) do
- license_usage_data
- .merge(system_usage_data_license)
- .merge(system_usage_data_settings)
- .merge(system_usage_data)
- .merge(system_usage_data_monthly)
- .merge(system_usage_data_weekly)
- .merge(features_usage_data)
- .merge(components_usage_data)
- .merge(object_store_usage_data)
- .merge(topology_usage_data)
- .merge(usage_activity_by_stage)
- .merge(usage_activity_by_stage(:usage_activity_by_stage_monthly, monthly_time_range_db_params))
- .merge(analytics_unique_visits_data)
- .merge(compliance_unique_visits_data)
- .merge(search_unique_visits_data)
- .merge(redis_hll_counters)
- .deep_merge(aggregated_metrics_data)
+ usage_data = usage_data_metrics
+ usage_data = usage_data.with_indifferent_access.deep_merge(instrumentation_metrics.with_indifferent_access) if Feature.enabled?(:usage_data_instrumentation)
+
+ usage_data
end
end
@@ -309,9 +296,11 @@ module Gitlab
version: alt_usage_data(fallback: nil) { Gitlab::CurrentSettings.container_registry_version }
},
database: {
- adapter: alt_usage_data { Gitlab::Database.main.adapter_name },
- version: alt_usage_data { Gitlab::Database.main.version },
- pg_system_id: alt_usage_data { Gitlab::Database.main.system_id }
+ # rubocop: disable UsageData/LargeTable
+ adapter: alt_usage_data { ApplicationRecord.database.adapter_name },
+ version: alt_usage_data { ApplicationRecord.database.version },
+ pg_system_id: alt_usage_data { ApplicationRecord.database.system_id }
+ # rubocop: enable UsageData/LargeTable
},
mail: {
smtp_server: alt_usage_data { ActionMailer::Base.smtp_settings[:address] }
@@ -549,7 +538,8 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def usage_activity_by_stage_manage(time_period)
{
- events: distinct_count(::Event.where(time_period), :author_id),
+ # rubocop: disable UsageData/LargeTable
+ events: stage_manage_events(time_period),
groups: distinct_count(::GroupMember.where(time_period), :user_id),
users_created: count(::User.where(time_period), start: minimum_id(User), finish: maximum_id(User)),
omniauth_providers: filtered_omniauth_provider_names.reject { |name| name == 'group_saml' },
@@ -628,9 +618,9 @@ module Gitlab
todos: distinct_count(::Todo.where(time_period), :author_id),
service_desk_enabled_projects: distinct_count_service_desk_enabled_projects(time_period),
service_desk_issues: count(::Issue.service_desk.where(time_period)),
- projects_jira_active: distinct_count(::Project.with_active_integration(::Integrations::Jira) .where(time_period), :creator_id),
- projects_jira_dvcs_cloud_active: distinct_count(::Project.with_active_integration(::Integrations::Jira) .with_jira_dvcs_cloud.where(time_period), :creator_id),
- projects_jira_dvcs_server_active: distinct_count(::Project.with_active_integration(::Integrations::Jira) .with_jira_dvcs_server.where(time_period), :creator_id)
+ projects_jira_active: distinct_count(::Project.with_active_integration(::Integrations::Jira).where(time_period), :creator_id),
+ projects_jira_dvcs_cloud_active: distinct_count(::Project.with_active_integration(::Integrations::Jira).with_jira_dvcs_cloud.where(time_period), :creator_id),
+ projects_jira_dvcs_server_active: distinct_count(::Project.with_active_integration(::Integrations::Jira).with_jira_dvcs_server.where(time_period), :creator_id)
}
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -729,6 +719,44 @@ module Gitlab
private
+ def stage_manage_events(time_period)
+ if time_period.empty?
+ Gitlab::Utils::UsageData::FALLBACK
+ else
+ # rubocop: disable CodeReuse/ActiveRecord
+ # rubocop: disable UsageData/LargeTable
+ start = ::Event.where(time_period).select(:id).order(created_at: :asc).first&.id
+ finish = ::Event.where(time_period).select(:id).order(created_at: :asc).first&.id
+ estimate_batch_distinct_count(::Event.where(time_period), :author_id, start: start, finish: finish)
+ # rubocop: enable UsageData/LargeTable
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+
+ def usage_data_metrics
+ license_usage_data
+ .merge(system_usage_data_license)
+ .merge(system_usage_data_settings)
+ .merge(system_usage_data)
+ .merge(system_usage_data_monthly)
+ .merge(system_usage_data_weekly)
+ .merge(features_usage_data)
+ .merge(components_usage_data)
+ .merge(object_store_usage_data)
+ .merge(topology_usage_data)
+ .merge(usage_activity_by_stage)
+ .merge(usage_activity_by_stage(:usage_activity_by_stage_monthly, monthly_time_range_db_params))
+ .merge(analytics_unique_visits_data)
+ .merge(compliance_unique_visits_data)
+ .merge(search_unique_visits_data)
+ .merge(redis_hll_counters)
+ .deep_merge(aggregated_metrics_data)
+ end
+
+ def instrumentation_metrics
+ Gitlab::UsageDataMetrics.uncached_data # rubocop:disable UsageData/LargeTable
+ end
+
def metric_time_period(time_period)
time_period.present? ? '28d' : 'none'
end
@@ -805,7 +833,13 @@ module Gitlab
Users::InProductMarketingEmail.tracks.keys.each_with_object({}) do |track, result|
# rubocop: enable UsageData/LargeTable:
- series_amount = Namespaces::InProductMarketingEmailsService::TRACKS[track.to_sym][:interval_days].count
+ series_amount =
+ if track.to_sym == Namespaces::InviteTeamEmailService::TRACK
+ 0
+ else
+ Namespaces::InProductMarketingEmailsService::TRACKS[track.to_sym][:interval_days].count
+ end
+
0.upto(series_amount - 1).map do |series|
# When there is an error with the query and it's not the Hash we expect, we return what we got from `count`.
sent_count = sent_emails.is_a?(Hash) ? sent_emails.fetch([track, series], 0) : sent_emails
@@ -881,7 +915,30 @@ module Gitlab
end
def projects_imported_count(from, time_period)
- count(::Project.imported_from(from).where(time_period).where.not(import_type: nil)) # rubocop: disable CodeReuse/ActiveRecord
+ # rubocop:disable CodeReuse/ActiveRecord
+ relation = ::Project.imported_from(from).where.not(import_type: nil) # rubocop:disable UsageData/LargeTable
+ if time_period.empty?
+ count(relation)
+ else
+ @project_import_id ||= {}
+ start = time_period[:created_at].first
+ finish = time_period[:created_at].last
+
+ # can be nil values here if no records are in our range and it is possible the same instance
+ # is called with different time periods since it is passed in as a variable
+ unless @project_import_id.key?(start)
+ @project_import_id[start] = ::Project.select(:id).where(Project.arel_table[:created_at].gteq(start)) # rubocop:disable UsageData/LargeTable
+ .order(created_at: :asc).limit(1).first&.id
+ end
+
+ unless @project_import_id.key?(finish)
+ @project_import_id[finish] = ::Project.select(:id).where(Project.arel_table[:created_at].lteq(finish)) # rubocop:disable UsageData/LargeTable
+ .order(created_at: :desc).limit(1).first&.id
+ end
+
+ count(relation, start: @project_import_id[start], finish: @project_import_id[finish])
+ end
+ # rubocop:enable CodeReuse/ActiveRecord
end
def issue_imports(time_period)
diff --git a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
index 99bdd3ca9e9..40922433635 100644
--- a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
+++ b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
@@ -83,6 +83,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_security_sast_iac_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_security_dast_runner_validation
category: ci_templates
redis_slot: ci_templates
@@ -267,6 +271,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_jobs_sast_iac_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_jobs_secret_detection
category: ci_templates
redis_slot: ci_templates
@@ -447,6 +455,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_implicit_jobs_sast_iac_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_implicit_jobs_secret_detection
category: ci_templates
redis_slot: ci_templates
@@ -503,6 +515,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_implicit_security_sast_iac_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_implicit_security_dast_runner_validation
category: ci_templates
redis_slot: ci_templates
@@ -559,3 +575,7 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_kaniko
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
diff --git a/lib/gitlab/usage_data_counters/known_events/code_review_events.yml b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
index d4a818f8fe0..d4bc060abf9 100644
--- a/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
+++ b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
@@ -249,3 +249,27 @@
redis_slot: code_review
category: code_review
aggregation: weekly
+- name: i_code_review_widget_nothing_merge_click_new_file
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_post_merge_delete_branch
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_post_merge_click_revert
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_post_merge_click_cherry_pick
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_post_merge_submit_revert_modal
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_post_merge_submit_cherry_pick_modal
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
diff --git a/lib/gitlab/usage_data_counters/known_events/quickactions.yml b/lib/gitlab/usage_data_counters/known_events/quickactions.yml
index 7f77fa8ee02..dff2c4f8d03 100644
--- a/lib/gitlab/usage_data_counters/known_events/quickactions.yml
+++ b/lib/gitlab/usage_data_counters/known_events/quickactions.yml
@@ -119,6 +119,10 @@
category: quickactions
redis_slot: quickactions
aggregation: weekly
+- name: i_quickactions_promote_to_incident
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
- name: i_quickactions_publish
category: quickactions
redis_slot: quickactions
diff --git a/lib/gitlab/usage_data_counters/vs_code_extension_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/vscode_extension_activity_unique_counter.rb
index 703c4885b04..703c4885b04 100644
--- a/lib/gitlab/usage_data_counters/vs_code_extension_activity_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/vscode_extension_activity_unique_counter.rb
diff --git a/lib/gitlab/usage_data_metrics.rb b/lib/gitlab/usage_data_metrics.rb
index 1ef201121d9..48f695d5db1 100644
--- a/lib/gitlab/usage_data_metrics.rb
+++ b/lib/gitlab/usage_data_metrics.rb
@@ -5,7 +5,17 @@ module Gitlab
class << self
# Build the Usage Ping JSON payload from metrics YAML definitions which have instrumentation class set
def uncached_data
- ::Gitlab::Usage::Metric.all.map(&:with_value).reduce({}, :deep_merge)
+ build_payload(:with_value)
+ end
+
+ def suggested_names
+ build_payload(:with_suggested_name)
+ end
+
+ private
+
+ def build_payload(method_symbol)
+ ::Gitlab::Usage::Metric.all.map(&method_symbol).reduce({}, :deep_merge)
end
end
end
diff --git a/lib/gitlab/usage_data_non_sql_metrics.rb b/lib/gitlab/usage_data_non_sql_metrics.rb
index 1ff4588d091..be5a571fb82 100644
--- a/lib/gitlab/usage_data_non_sql_metrics.rb
+++ b/lib/gitlab/usage_data_non_sql_metrics.rb
@@ -6,13 +6,16 @@ module Gitlab
class << self
def uncached_data
- super.with_indifferent_access.deep_merge(instrumentation_metrics_queries.with_indifferent_access)
+ # instrumentation_metrics is already included with feature flag enabled
+ return super if Feature.enabled?(:usage_data_instrumentation)
+
+ super.with_indifferent_access.deep_merge(instrumentation_metrics.with_indifferent_access)
end
- def add_metric(metric, time_frame: 'none')
+ def add_metric(metric, time_frame: 'none', options: {})
metric_class = "Gitlab::Usage::Metrics::Instrumentations::#{metric}".constantize
- metric_class.new(time_frame: time_frame).instrumentation
+ metric_class.new(time_frame: time_frame, options: options).instrumentation
end
def count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
@@ -50,7 +53,7 @@ module Gitlab
private
- def instrumentation_metrics_queries
+ def instrumentation_metrics
::Gitlab::Usage::Metric.all.map(&:with_instrumentation).reduce({}, :deep_merge)
end
end
diff --git a/lib/gitlab/usage_data_queries.rb b/lib/gitlab/usage_data_queries.rb
index f64da2fbf13..f543b29e43f 100644
--- a/lib/gitlab/usage_data_queries.rb
+++ b/lib/gitlab/usage_data_queries.rb
@@ -6,13 +6,16 @@ module Gitlab
class UsageDataQueries < UsageData
class << self
def uncached_data
- super.with_indifferent_access.deep_merge(instrumentation_metrics_queries.with_indifferent_access)
+ # instrumentation_metrics is already included with feature flag enabled
+ return super if Feature.enabled?(:usage_data_instrumentation)
+
+ super.with_indifferent_access.deep_merge(instrumentation_metrics.with_indifferent_access)
end
- def add_metric(metric, time_frame: 'none')
+ def add_metric(metric, time_frame: 'none', options: {})
metric_class = "Gitlab::Usage::Metrics::Instrumentations::#{metric}".constantize
- metric_class.new(time_frame: time_frame).instrumentation
+ metric_class.new(time_frame: time_frame, options: options).instrumentation
end
def count(relation, column = nil, *args, **kwargs)
@@ -71,7 +74,7 @@ module Gitlab
private
- def instrumentation_metrics_queries
+ def instrumentation_metrics
::Gitlab::Usage::Metric.all.map(&:with_instrumentation).reduce({}, :deep_merge)
end
end
diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb
index d46210f6efe..77f04929661 100644
--- a/lib/gitlab/utils/usage_data.rb
+++ b/lib/gitlab/utils/usage_data.rb
@@ -43,11 +43,16 @@ module Gitlab
HISTOGRAM_FALLBACK = { '-1' => -1 }.freeze
DISTRIBUTED_HLL_FALLBACK = -2
MAX_BUCKET_SIZE = 100
+ INSTRUMENTATION_CLASS_FALLBACK = -100
+
+ def add_metric(metric, time_frame: 'none', options: {})
+ # Results of this method should be overwritten by instrumentation class values
+ # -100 indicates the metric was not properly merged.
+ return INSTRUMENTATION_CLASS_FALLBACK if Feature.enabled?(:usage_data_instrumentation)
- def add_metric(metric, time_frame: 'none')
metric_class = "Gitlab::Usage::Metrics::Instrumentations::#{metric}".constantize
- metric_class.new(time_frame: time_frame).value
+ metric_class.new(time_frame: time_frame, options: options).value
end
def count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
diff --git a/lib/gitlab/webpack/file_loader.rb b/lib/gitlab/webpack/file_loader.rb
new file mode 100644
index 00000000000..35ecb1eb4ed
--- /dev/null
+++ b/lib/gitlab/webpack/file_loader.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'net/http'
+require 'uri'
+
+module Gitlab
+ module Webpack
+ class FileLoader
+ class BaseError < StandardError
+ attr_reader :original_error, :uri
+
+ def initialize(uri, orig)
+ super orig.message
+ @uri = uri.to_s
+ @original_error = orig
+ end
+ end
+
+ StaticLoadError = Class.new(BaseError)
+ DevServerLoadError = Class.new(BaseError)
+ DevServerSSLError = Class.new(BaseError)
+
+ def self.load(path)
+ if Gitlab.config.webpack.dev_server.enabled
+ self.load_from_dev_server(path)
+ else
+ self.load_from_static(path)
+ end
+ end
+
+ def self.load_from_dev_server(path)
+ host = Gitlab.config.webpack.dev_server.host
+ port = Gitlab.config.webpack.dev_server.port
+ scheme = Gitlab.config.webpack.dev_server.https ? 'https' : 'http'
+ uri = Addressable::URI.new(scheme: scheme, host: host, port: port, path: self.dev_server_path(path))
+
+ # localhost could be blocked via Gitlab::HTTP
+ response = HTTParty.get(uri.to_s, verify: false) # rubocop:disable Gitlab/HTTParty
+
+ return response.body if response.code == 200
+
+ raise "HTTP error #{response.code}"
+ rescue OpenSSL::SSL::SSLError, EOFError => e
+ raise DevServerSSLError.new(uri, e)
+ rescue StandardError => e
+ raise DevServerLoadError.new(uri, e)
+ end
+
+ def self.load_from_static(path)
+ file_uri = ::Rails.root.join(
+ Gitlab.config.webpack.output_dir,
+ path
+ )
+
+ File.read(file_uri)
+ rescue StandardError => e
+ raise StaticLoadError.new(file_uri, e)
+ end
+
+ def self.dev_server_path(path)
+ "/#{Gitlab.config.webpack.public_path}/#{path}"
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/webpack/graphql_known_operations.rb b/lib/gitlab/webpack/graphql_known_operations.rb
new file mode 100644
index 00000000000..7945513667c
--- /dev/null
+++ b/lib/gitlab/webpack/graphql_known_operations.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Webpack
+ class GraphqlKnownOperations
+ class << self
+ include Gitlab::Utils::StrongMemoize
+
+ def clear_memoization!
+ clear_memoization(:graphql_known_operations)
+ end
+
+ def load
+ strong_memoize(:graphql_known_operations) do
+ data = ::Gitlab::Webpack::FileLoader.load("graphql_known_operations.yml")
+
+ YAML.safe_load(data)
+ rescue StandardError
+ []
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/webpack/manifest.rb b/lib/gitlab/webpack/manifest.rb
index b73c2ebb578..06cddc23134 100644
--- a/lib/gitlab/webpack/manifest.rb
+++ b/lib/gitlab/webpack/manifest.rb
@@ -1,8 +1,5 @@
# frozen_string_literal: true
-require 'net/http'
-require 'uri'
-
module Gitlab
module Webpack
class Manifest
@@ -78,49 +75,16 @@ module Gitlab
end
def load_manifest
- data = if Gitlab.config.webpack.dev_server.enabled
- load_dev_server_manifest
- else
- load_static_manifest
- end
+ data = Gitlab::Webpack::FileLoader.load(Gitlab.config.webpack.manifest_filename)
Gitlab::Json.parse(data)
- end
-
- def load_dev_server_manifest
- host = Gitlab.config.webpack.dev_server.host
- port = Gitlab.config.webpack.dev_server.port
- scheme = Gitlab.config.webpack.dev_server.https ? 'https' : 'http'
- uri = Addressable::URI.new(scheme: scheme, host: host, port: port, path: dev_server_path)
-
- # localhost could be blocked via Gitlab::HTTP
- response = HTTParty.get(uri.to_s, verify: false) # rubocop:disable Gitlab/HTTParty
-
- return response.body if response.code == 200
-
- raise "HTTP error #{response.code}"
- rescue OpenSSL::SSL::SSLError, EOFError => e
+ rescue Gitlab::Webpack::FileLoader::StaticLoadError => e
+ raise ManifestLoadError.new("Could not load compiled manifest from #{e.uri}.\n\nHave you run `rake gitlab:assets:compile`?", e.original_error)
+ rescue Gitlab::Webpack::FileLoader::DevServerSSLError => e
ssl_status = Gitlab.config.webpack.dev_server.https ? ' over SSL' : ''
- raise ManifestLoadError.new("Could not connect to webpack-dev-server at #{uri}#{ssl_status}.\n\nIs SSL enabled? Check that settings in `gitlab.yml` and webpack-dev-server match.", e)
- rescue StandardError => e
- raise ManifestLoadError.new("Could not load manifest from webpack-dev-server at #{uri}.\n\nIs webpack-dev-server running? Try running `gdk status webpack` or `gdk tail webpack`.", e)
- end
-
- def load_static_manifest
- File.read(static_manifest_path)
- rescue StandardError => e
- raise ManifestLoadError.new("Could not load compiled manifest from #{static_manifest_path}.\n\nHave you run `rake gitlab:assets:compile`?", e)
- end
-
- def static_manifest_path
- ::Rails.root.join(
- Gitlab.config.webpack.output_dir,
- Gitlab.config.webpack.manifest_filename
- )
- end
-
- def dev_server_path
- "/#{Gitlab.config.webpack.public_path}/#{Gitlab.config.webpack.manifest_filename}"
+ raise ManifestLoadError.new("Could not connect to webpack-dev-server at #{e.uri}#{ssl_status}.\n\nIs SSL enabled? Check that settings in `gitlab.yml` and webpack-dev-server match.", e.original_error)
+ rescue Gitlab::Webpack::FileLoader::DevServerLoadError => e
+ raise ManifestLoadError.new("Could not load manifest from webpack-dev-server at #{e.uri}.\n\nIs webpack-dev-server running? Try running `gdk status webpack` or `gdk tail webpack`.", e.original_error)
end
end
end
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index c40aa2273aa..3a905a2e1c5 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -8,6 +8,7 @@ require 'uri'
module Gitlab
class Workhorse
SEND_DATA_HEADER = 'Gitlab-Workhorse-Send-Data'
+ SEND_DEPENDENCY_CONTENT_TYPE_HEADER = 'Workhorse-Proxy-Content-Type'
VERSION_FILE = 'GITLAB_WORKHORSE_VERSION'
INTERNAL_API_CONTENT_TYPE = 'application/vnd.gitlab-workhorse+json'
INTERNAL_API_REQUEST_HEADER = 'Gitlab-Workhorse-Api-Request'
@@ -170,9 +171,9 @@ module Gitlab
]
end
- def send_dependency(token, url)
+ def send_dependency(headers, url)
params = {
- 'Header' => { Authorization: ["Bearer #{token}"] },
+ 'Header' => headers,
'Url' => url
}
diff --git a/lib/gitlab/x509/certificate.rb b/lib/gitlab/x509/certificate.rb
index c7289a51b49..752f3c6b004 100644
--- a/lib/gitlab/x509/certificate.rb
+++ b/lib/gitlab/x509/certificate.rb
@@ -19,6 +19,10 @@ module Gitlab
ca_certs.map(&:to_pem).join('\n') unless ca_certs.blank?
end
+ class << self
+ include ::Gitlab::Utils::StrongMemoize
+ end
+
def self.from_strings(key_string, cert_string, ca_certs_string = nil)
key = OpenSSL::PKey::RSA.new(key_string)
cert = OpenSSL::X509::Certificate.new(cert_string)
@@ -33,6 +37,30 @@ module Gitlab
from_strings(File.read(key_path), File.read(cert_path), ca_certs_string)
end
+ # Returns all top-level, readable files in the default CA cert directory
+ def self.ca_certs_paths
+ cert_paths = Dir["#{OpenSSL::X509::DEFAULT_CERT_DIR}/*"].select do |path|
+ !File.directory?(path) && File.readable?(path)
+ end
+ cert_paths << OpenSSL::X509::DEFAULT_CERT_FILE if File.exist? OpenSSL::X509::DEFAULT_CERT_FILE
+ cert_paths
+ end
+
+ # Returns a concatenated array of Strings, each being a PEM-coded CA certificate.
+ def self.ca_certs_bundle
+ strong_memoize(:ca_certs_bundle) do
+ ca_certs_paths.flat_map do |cert_file|
+ load_ca_certs_bundle(File.read(cert_file))
+ rescue OpenSSL::OpenSSLError => e
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, cert_file: cert_file)
+ end.uniq.join("\n")
+ end
+ end
+
+ def self.reset_ca_certs_bundle
+ clear_memoization(:ca_certs_bundle)
+ end
+
# Returns an array of OpenSSL::X509::Certificate objects, empty array if none found
#
# Ruby OpenSSL::X509::Certificate.new will only load the first
diff --git a/lib/gitlab/zentao/client.rb b/lib/gitlab/zentao/client.rb
index bdfa4b3a308..8acfb4913f3 100644
--- a/lib/gitlab/zentao/client.rb
+++ b/lib/gitlab/zentao/client.rb
@@ -15,10 +15,8 @@ module Gitlab
end
def ping
- response = fetch_product(zentao_product_xid)
-
- active = response.fetch('deleted') == '0' rescue false
-
+ response = fetch_product(zentao_product_xid) rescue {}
+ active = response['deleted'] == '0'
if active
{ success: true }
else
@@ -31,25 +29,30 @@ module Gitlab
end
def fetch_issues(params = {})
- get("products/#{zentao_product_xid}/issues",
- params.reverse_merge(page: 1, limit: 20))
+ get("products/#{zentao_product_xid}/issues", params)
end
def fetch_issue(issue_id)
+ raise Gitlab::Zentao::Client::Error, 'invalid issue id' unless issue_id_pattern.match(issue_id)
+
get("issues/#{issue_id}")
end
private
+ def issue_id_pattern
+ /\A\S+-\d+\z/
+ end
+
def get(path, params = {})
options = { headers: headers, query: params }
response = Gitlab::HTTP.get(url(path), options)
- return {} unless response.success?
+ raise Gitlab::Zentao::Client::Error, 'request error' unless response.success?
Gitlab::Json.parse(response.body)
rescue JSON::ParserError
- {}
+ raise Gitlab::Zentao::Client::Error, 'invalid response format'
end
def url(path)
diff --git a/lib/gitlab/zentao/query.rb b/lib/gitlab/zentao/query.rb
new file mode 100644
index 00000000000..d40ee80939a
--- /dev/null
+++ b/lib/gitlab/zentao/query.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Zentao
+ class Query
+ STATUSES = %w[all opened closed].freeze
+ ISSUES_DEFAULT_LIMIT = 20
+ ISSUES_MAX_LIMIT = 50
+
+ def initialize(integration, params)
+ @client = Client.new(integration)
+ @params = params
+ end
+
+ def issues
+ issues_response = client.fetch_issues(query_options)
+ return [] if issues_response.blank?
+
+ Kaminari.paginate_array(
+ issues_response['issues'],
+ limit: issues_response['limit'],
+ total_count: issues_response['total']
+ )
+ end
+
+ def issue
+ issue_response = client.fetch_issue(params[:id])
+ issue_response['issue']
+ end
+
+ private
+
+ attr_reader :client, :params
+
+ def query_options
+ {
+ order: query_order,
+ status: query_status,
+ labels: query_labels,
+ page: query_page,
+ limit: query_limit,
+ search: query_search
+ }
+ end
+
+ def query_page
+ params[:page].presence || 1
+ end
+
+ def query_limit
+ limit = params[:limit].presence || ISSUES_DEFAULT_LIMIT
+ [limit.to_i, ISSUES_MAX_LIMIT].min
+ end
+
+ def query_search
+ params[:search] || ''
+ end
+
+ def query_order
+ key, order = params['sort'].to_s.split('_', 2)
+ zentao_key = (key == 'created' ? 'openedDate' : 'lastEditedDate')
+ zentao_order = (order == 'asc' ? 'asc' : 'desc')
+
+ "#{zentao_key}_#{zentao_order}"
+ end
+
+ def query_status
+ return params[:state] if params[:state].present? && params[:state].in?(STATUSES)
+
+ 'opened'
+ end
+
+ def query_labels
+ (params[:labels].presence || []).join(',')
+ end
+ end
+ end
+end
diff --git a/lib/object_storage/config.rb b/lib/object_storage/config.rb
index 82d9fc07043..056e22278dd 100644
--- a/lib/object_storage/config.rb
+++ b/lib/object_storage/config.rb
@@ -12,16 +12,6 @@ module ObjectStorage
@options = options.to_hash.deep_symbolize_keys
end
- def load_provider
- if aws?
- require 'fog/aws'
- elsif google?
- require 'fog/google'
- elsif azure?
- require 'fog/azurerm'
- end
- end
-
def credentials
@credentials ||= options[:connection] || {}
end
diff --git a/lib/security/ci_configuration/sast_iac_build_action.rb b/lib/security/ci_configuration/sast_iac_build_action.rb
new file mode 100644
index 00000000000..ddc7db282ef
--- /dev/null
+++ b/lib/security/ci_configuration/sast_iac_build_action.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Security
+ module CiConfiguration
+ class SastIacBuildAction < BaseBuildAction
+ private
+
+ def update_existing_content!
+ @existing_gitlab_ci_content['include'] = generate_includes
+ end
+
+ def template
+ return 'Auto-DevOps.gitlab-ci.yml' if @auto_devops_enabled
+
+ 'Security/SAST-IaC.latest.gitlab-ci.yml'
+ end
+ end
+ end
+end
diff --git a/lib/sidebars/groups/menus/customer_relations_menu.rb b/lib/sidebars/groups/menus/customer_relations_menu.rb
new file mode 100644
index 00000000000..fdbbd662ad6
--- /dev/null
+++ b/lib/sidebars/groups/menus/customer_relations_menu.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Groups
+ module Menus
+ class CustomerRelationsMenu < ::Sidebars::Menu
+ override :configure_menu_items
+ def configure_menu_items
+ add_item(contacts_menu_item) if can_read_contact?
+ add_item(organizations_menu_item) if can_read_organization?
+
+ true
+ end
+
+ override :title
+ def title
+ _('Customer relations')
+ end
+
+ override :sprite_icon
+ def sprite_icon
+ 'users'
+ end
+
+ override :render?
+ def render?
+ can_read_contact? || can_read_organization?
+ end
+
+ private
+
+ def contacts_menu_item
+ ::Sidebars::MenuItem.new(
+ title: _('Contacts'),
+ link: contacts_group_crm_index_path(context.group),
+ active_routes: { path: 'groups/crm#contacts' },
+ item_id: :crm_contacts
+ )
+ end
+
+ def organizations_menu_item
+ ::Sidebars::MenuItem.new(
+ title: _('Organizations'),
+ link: organizations_group_crm_index_path(context.group),
+ active_routes: { path: 'groups/crm#organizations' },
+ item_id: :crm_organizations
+ )
+ end
+
+ def can_read_contact?
+ can?(context.current_user, :read_crm_contact, context.group)
+ end
+
+ def can_read_organization?
+ can?(context.current_user, :read_crm_organization, context.group)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/sidebars/groups/menus/invite_team_members_menu.rb b/lib/sidebars/groups/menus/invite_team_members_menu.rb
new file mode 100644
index 00000000000..0779b696061
--- /dev/null
+++ b/lib/sidebars/groups/menus/invite_team_members_menu.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Groups
+ module Menus
+ class InviteTeamMembersMenu < ::Sidebars::Menu
+ override :title
+ def title
+ s_('InviteMember|Invite members')
+ end
+
+ override :render?
+ def render?
+ can?(context.current_user, :admin_group_member, context.group) && all_valid_members.size <= 1
+ end
+
+ override :menu_partial
+ def menu_partial
+ 'groups/invite_members_side_nav_link'
+ end
+
+ override :menu_partial_options
+ def menu_partial_options
+ {
+ group: context.group,
+ title: title,
+ sidebar_menu: self
+ }
+ end
+
+ override :extra_nav_link_html_options
+ def extra_nav_link_html_options
+ {
+ 'data-test-id': 'side-nav-invite-members'
+ }
+ end
+
+ private
+
+ def all_valid_members
+ GroupMembersFinder.new(context.group, context.current_user).execute
+ end
+ end
+ end
+ end
+end
diff --git a/lib/sidebars/groups/menus/packages_registries_menu.rb b/lib/sidebars/groups/menus/packages_registries_menu.rb
index e81e9355e7e..46fcec9f7b8 100644
--- a/lib/sidebars/groups/menus/packages_registries_menu.rb
+++ b/lib/sidebars/groups/menus/packages_registries_menu.rb
@@ -52,7 +52,7 @@ module Sidebars
end
def dependency_proxy_menu_item
- unless context.group.dependency_proxy_feature_available?
+ unless can?(context.current_user, :read_dependency_proxy, context.group)
return ::Sidebars::NilMenuItem.new(item_id: :dependency_proxy)
end
diff --git a/lib/sidebars/groups/panel.rb b/lib/sidebars/groups/panel.rb
index 6efe89d496a..463c2571b14 100644
--- a/lib/sidebars/groups/panel.rb
+++ b/lib/sidebars/groups/panel.rb
@@ -13,13 +13,24 @@ module Sidebars
add_menu(Sidebars::Groups::Menus::CiCdMenu.new(context))
add_menu(Sidebars::Groups::Menus::KubernetesMenu.new(context))
add_menu(Sidebars::Groups::Menus::PackagesRegistriesMenu.new(context))
+ add_menu(Sidebars::Groups::Menus::CustomerRelationsMenu.new(context))
add_menu(Sidebars::Groups::Menus::SettingsMenu.new(context))
+ add_invite_members_menu
end
override :aria_label
def aria_label
context.group.subgroup? ? _('Subgroup navigation') : _('Group navigation')
end
+
+ private
+
+ def add_invite_members_menu
+ experiment(:invite_members_in_side_nav, group: context.group) do |e|
+ e.control {}
+ e.candidate { add_menu(Sidebars::Groups::Menus::InviteTeamMembersMenu.new(context)) }
+ end
+ end
end
end
end
diff --git a/lib/sidebars/panel.rb b/lib/sidebars/panel.rb
index 75b3ba65729..e8c02a2d707 100644
--- a/lib/sidebars/panel.rb
+++ b/lib/sidebars/panel.rb
@@ -4,6 +4,7 @@ module Sidebars
class Panel
extend ::Gitlab::Utils::Override
include ::Sidebars::Concerns::PositionableList
+ include Gitlab::Experiment::Dsl
attr_reader :context, :scope_menu, :hidden_menu
diff --git a/lib/sidebars/projects/menus/confluence_menu.rb b/lib/sidebars/projects/menus/confluence_menu.rb
index 0d83238fa82..0fd42a57da3 100644
--- a/lib/sidebars/projects/menus/confluence_menu.rb
+++ b/lib/sidebars/projects/menus/confluence_menu.rb
@@ -37,6 +37,11 @@ module Sidebars
def render?
context.project.has_confluence?
end
+
+ override :active_routes
+ def active_routes
+ { controller: :confluences }
+ end
end
end
end
diff --git a/lib/sidebars/projects/menus/infrastructure_menu.rb b/lib/sidebars/projects/menus/infrastructure_menu.rb
index 92e9cbb7040..ccc4787601a 100644
--- a/lib/sidebars/projects/menus/infrastructure_menu.rb
+++ b/lib/sidebars/projects/menus/infrastructure_menu.rb
@@ -91,7 +91,7 @@ module Sidebars
def google_cloud_menu_item
feature_is_enabled = Feature.enabled?(:incubation_5mp_google_cloud)
- user_has_permissions = can?(context.current_user, :manage_project_google_cloud, context.project)
+ user_has_permissions = can?(context.current_user, :admin_project_google_cloud, context.project)
unless feature_is_enabled && user_has_permissions
return ::Sidebars::NilMenuItem.new(item_id: :incubation_5mp_google_cloud)
@@ -100,7 +100,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Google Cloud'),
link: project_google_cloud_index_path(context.project),
- active_routes: {},
+ active_routes: { controller: :google_cloud },
item_id: :google_cloud
)
end
diff --git a/lib/sidebars/projects/menus/invite_team_members_menu.rb b/lib/sidebars/projects/menus/invite_team_members_menu.rb
new file mode 100644
index 00000000000..0db49f1e12a
--- /dev/null
+++ b/lib/sidebars/projects/menus/invite_team_members_menu.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Projects
+ module Menus
+ class InviteTeamMembersMenu < ::Sidebars::Menu
+ override :title
+ def title
+ s_('InviteMember|Invite members')
+ end
+
+ override :render?
+ def render?
+ can?(context.current_user, :admin_project_member, context.project) && all_valid_members.size <= 1
+ end
+
+ override :menu_partial
+ def menu_partial
+ 'projects/invite_members_side_nav_link'
+ end
+
+ override :menu_partial_options
+ def menu_partial_options
+ {
+ project: context.project,
+ title: title,
+ sidebar_menu: self
+ }
+ end
+
+ override :extra_nav_link_html_options
+ def extra_nav_link_html_options
+ {
+ 'data-test-id': 'side-nav-invite-members'
+ }
+ end
+
+ private
+
+ def all_valid_members
+ MembersFinder.new(context.project, context.current_user)
+ .execute(include_relations: [:inherited, :direct, :invited_groups])
+ end
+ end
+ end
+ end
+end
diff --git a/lib/sidebars/projects/menus/settings_menu.rb b/lib/sidebars/projects/menus/settings_menu.rb
index 6439c97d0bc..2411ca8263a 100644
--- a/lib/sidebars/projects/menus/settings_menu.rb
+++ b/lib/sidebars/projects/menus/settings_menu.rb
@@ -144,10 +144,6 @@ module Sidebars
end
def usage_quotas_menu_item
- unless Feature.enabled?(:project_storage_ui, context.project&.group, default_enabled: :yaml)
- return ::Sidebars::NilMenuItem.new(item_id: :usage_quotas)
- end
-
::Sidebars::MenuItem.new(
title: s_('UsageQuota|Usage Quotas'),
link: project_usage_quotas_path(context.project),
diff --git a/lib/sidebars/projects/menus/zentao_menu.rb b/lib/sidebars/projects/menus/zentao_menu.rb
new file mode 100644
index 00000000000..db9e60326a4
--- /dev/null
+++ b/lib/sidebars/projects/menus/zentao_menu.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Projects
+ module Menus
+ class ZentaoMenu < ::Sidebars::Menu
+ override :configure_menu_items
+ def configure_menu_items
+ render?.tap { |render| add_items if render }
+ end
+
+ override :link
+ def link
+ zentao_integration.url
+ end
+
+ override :title
+ def title
+ s_('ZentaoIntegration|ZenTao issues')
+ end
+
+ override :title_html_options
+ def title_html_options
+ {
+ id: 'js-onboarding-settings-link'
+ }
+ end
+
+ override :image_path
+ def image_path
+ 'logos/zentao.svg'
+ end
+
+ # Hardcode sizes so image doesn't flash before CSS loads https://gitlab.com/gitlab-org/gitlab/-/issues/321022
+ override :image_html_options
+ def image_html_options
+ {
+ size: 16
+ }
+ end
+
+ override :render?
+ def render?
+ return false if zentao_integration.blank?
+
+ zentao_integration.active?
+ end
+
+ def add_items
+ add_item(open_zentao_menu_item)
+ end
+
+ private
+
+ def zentao_integration
+ @zentao_integration ||= context.project.zentao_integration
+ end
+
+ def open_zentao_menu_item
+ ::Sidebars::MenuItem.new(
+ title: s_('ZentaoIntegration|Open ZenTao'),
+ link: zentao_integration.url,
+ active_routes: {},
+ item_id: :open_zentao,
+ sprite_icon: 'external-link',
+ container_html_options: {
+ target: '_blank',
+ rel: 'noopener noreferrer'
+ }
+ )
+ end
+ end
+ end
+ end
+end
+
+::Sidebars::Projects::Menus::ZentaoMenu.prepend_mod
diff --git a/lib/sidebars/projects/panel.rb b/lib/sidebars/projects/panel.rb
index d5311c0a0c1..8fbd71c1543 100644
--- a/lib/sidebars/projects/panel.rb
+++ b/lib/sidebars/projects/panel.rb
@@ -23,6 +23,7 @@ module Sidebars
add_menu(Sidebars::Projects::Menus::RepositoryMenu.new(context))
add_menu(Sidebars::Projects::Menus::IssuesMenu.new(context))
add_menu(Sidebars::Projects::Menus::ExternalIssueTrackerMenu.new(context))
+ add_menu(Sidebars::Projects::Menus::ZentaoMenu.new(context))
add_menu(Sidebars::Projects::Menus::MergeRequestsMenu.new(context))
add_menu(Sidebars::Projects::Menus::CiCdMenu.new(context))
add_menu(Sidebars::Projects::Menus::SecurityComplianceMenu.new(context))
@@ -35,6 +36,14 @@ module Sidebars
add_menu(Sidebars::Projects::Menus::ExternalWikiMenu.new(context))
add_menu(Sidebars::Projects::Menus::SnippetsMenu.new(context))
add_menu(Sidebars::Projects::Menus::SettingsMenu.new(context))
+ add_invite_members_menu
+ end
+
+ def add_invite_members_menu
+ experiment(:invite_members_in_side_nav, group: context.project.group) do |e|
+ e.control {}
+ e.candidate { add_menu(Sidebars::Projects::Menus::InviteTeamMembersMenu.new(context)) }
+ end
end
def confluence_or_wiki_menu
diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index 96e3a015115..1ad89fdc364 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -291,7 +291,9 @@ start_gitlab() {
if [ "$sidekiq_status" = "0" ]; then
echo "The Sidekiq job dispatcher is already running with pid $spid, not restarting"
else
- RAILS_ENV=$RAILS_ENV SIDEKIQ_WORKERS=$SIDEKIQ_WORKERS bin/background_jobs start &
+ # bin/background_jobs writes to log/sidekiq.log and stdout by
+ # default, so we just need to suppress the latter here.
+ RAILS_ENV=$RAILS_ENV SIDEKIQ_WORKERS=$SIDEKIQ_WORKERS bin/background_jobs start > /dev/null &
fi
if [ "$gitlab_workhorse_status" = "0" ]; then
@@ -454,7 +456,9 @@ reload_gitlab(){
echo "Done."
echo "Restarting GitLab Sidekiq since it isn't capable of reloading its config..."
- RAILS_ENV=$RAILS_ENV SIDEKIQ_WORKERS=$SIDEKIQ_WORKERS bin/background_jobs restart
+ # bin/background_jobs writes to log/sidekiq.log and stdout by default,
+ # so we just need to suppress the latter here.
+ RAILS_ENV=$RAILS_ENV SIDEKIQ_WORKERS=$SIDEKIQ_WORKERS bin/background_jobs restart > /dev/null &
if [ "$mail_room_enabled" != true ]; then
echo "Restarting GitLab MailRoom since it isn't capable of reloading its config..."
diff --git a/lib/support/systemd/gitlab-gitaly.service b/lib/support/systemd/gitlab-gitaly.service
new file mode 100644
index 00000000000..49f04563292
--- /dev/null
+++ b/lib/support/systemd/gitlab-gitaly.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=GitLab Gitaly
+ReloadPropagatedFrom=gitlab.target
+PartOf=gitlab.target
+After=network.target
+
+[Service]
+Type=simple
+User=git
+WorkingDirectory=/home/git/gitlab
+ExecStart=/home/git/gitaly/_build/bin/gitaly /home/git/gitaly/config.toml
+Restart=on-failure
+SyslogIdentifier=gitlab-gitaly
+Slice=gitlab.slice
+
+[Install]
+WantedBy=gitlab.target
diff --git a/lib/support/systemd/gitlab-mailroom.service b/lib/support/systemd/gitlab-mailroom.service
new file mode 100644
index 00000000000..4186126c128
--- /dev/null
+++ b/lib/support/systemd/gitlab-mailroom.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=GitLab Mailroom
+PartOf=gitlab.target
+After=network.target
+StartLimitIntervalSec=100s
+
+[Service]
+Type=simple
+User=git
+WorkingDirectory=/home/git/gitlab
+Environment=RAILS_ENV=production
+ExecStart=/usr/local/bin/bundle exec mail_room --log-exit-as json --quiet --config /home/git/gitlab/config/mail_room.yml
+Restart=on-failure
+RestartSec=1
+SyslogIdentifier=gitlab-mailroom
+Slice=gitlab.slice
+
+[Install]
+WantedBy=gitlab.target
diff --git a/lib/support/systemd/gitlab-pages.service b/lib/support/systemd/gitlab-pages.service
new file mode 100644
index 00000000000..2060f01be01
--- /dev/null
+++ b/lib/support/systemd/gitlab-pages.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=GitLab Pages
+ReloadPropagatedFrom=gitlab.target
+PartOf=gitlab.target
+After=network.target gitlab-puma.service
+Wants=gitlab-puma.service
+
+[Service]
+Type=simple
+User=git
+WorkingDirectory=/home/git/gitlab
+ExecStart=/home/git/gitlab-pages/gitlab-pages -config /home/git/gitlab-pages/gitlab-pages.conf
+Restart=on-failure
+RestartSec=1
+SyslogIdentifier=gitlab-pages
+Slice=gitlab.slice
+
+[Install]
+WantedBy=gitlab.target
diff --git a/lib/support/systemd/gitlab-puma.service b/lib/support/systemd/gitlab-puma.service
new file mode 100644
index 00000000000..c0affa92ddf
--- /dev/null
+++ b/lib/support/systemd/gitlab-puma.service
@@ -0,0 +1,26 @@
+[Unit]
+Description=GitLab
+Conflicts=gitlab.service
+ReloadPropagatedFrom=gitlab.target
+PartOf=gitlab.target
+After=network.target
+StartLimitIntervalSec=100s
+
+[Service]
+Type=notify
+User=git
+WorkingDirectory=/home/git/gitlab
+Environment=RAILS_ENV=production
+ExecStart=/usr/local/bin/bundle exec puma --config /home/git/gitlab/config/puma.rb --environment production --pidfile /home/git/gitlab/tmp/pids/puma.pid
+ExecReload=/usr/bin/kill -USR2 $MAINPID
+PIDFile=/home/git/gitlab/tmp/pids/puma.pid
+# puma can be slow to start
+TimeoutStartSec=120
+WatchdogSec=10
+Restart=on-failure
+RestartSec=1
+SyslogIdentifier=gitlab-puma
+Slice=gitlab.slice
+
+[Install]
+WantedBy=gitlab.target
diff --git a/lib/support/systemd/gitlab-sidekiq.service b/lib/support/systemd/gitlab-sidekiq.service
new file mode 100644
index 00000000000..81046f5348a
--- /dev/null
+++ b/lib/support/systemd/gitlab-sidekiq.service
@@ -0,0 +1,22 @@
+[Unit]
+Description=GitLab Sidekiq
+ReloadPropagatedFrom=gitlab.target
+PartOf=gitlab.target
+After=network.target
+JoinsNamespaceOf=gitlab-puma.service
+
+[Service]
+Type=simple
+User=git
+WorkingDirectory=/home/git/gitlab
+Environment=RAILS_ENV=production
+ExecStart=/usr/local/bin/bundle exec sidekiq --config /home/git/gitlab/config/sidekiq_queues.yml --environment production
+ExecStop=/usr/local/bin/bundle exec sidekiqctl stop /run/gitlab/sidekiq.pid
+PIDFile=/home/git/gitlab/tmp/pids/sidekiq.pid
+Restart=on-failure
+RestartSec=1
+SyslogIdentifier=gitlab-sidekiq
+Slice=gitlab.slice
+
+[Install]
+WantedBy=gitlab.target
diff --git a/lib/support/systemd/gitlab-workhorse.service b/lib/support/systemd/gitlab-workhorse.service
new file mode 100644
index 00000000000..3e9a72d3cb2
--- /dev/null
+++ b/lib/support/systemd/gitlab-workhorse.service
@@ -0,0 +1,21 @@
+[Unit]
+Description=GitLab Workhorse
+ReloadPropagatedFrom=gitlab.target
+PartOf=gitlab.target
+After=network.target gitlab-puma.service
+Wants=gitlab-puma.service
+
+[Service]
+Type=simple
+User=git
+WorkingDirectory=/home/git/gitlab
+Environment=PATH=/home/git/gitlab-workhorse:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+ExecStart=/home/git/gitlab-workhorse/gitlab-workhorse -listenUmask 0 -listenNetwork unix -listenAddr /home/git/gitlab/tmp/sockets/gitlab-workhorse.socket -authBackend http://127.0.0.1:8080 -authSocket /home/git/gitlab/tmp/sockets/gitlab.socket -documentRoot /home/git/gitlab/public -secretPath /home/git/gitlab/.gitlab_workhorse_secret
+ExecReload=/usr/bin/kill -USR2 $MAINPID
+Restart=on-failure
+RestartSec=1
+SyslogIdentifier=gitlab-workhorse
+Slice=gitlab.slice
+
+[Install]
+WantedBy=gitlab.target
diff --git a/lib/support/systemd/gitlab.slice b/lib/support/systemd/gitlab.slice
new file mode 100644
index 00000000000..2c447f6224a
--- /dev/null
+++ b/lib/support/systemd/gitlab.slice
@@ -0,0 +1,8 @@
+[Unit]
+Description=Slice to bundle all GitLab services
+Before=slices.target
+
+[Slice]
+MemoryAccounting=true
+IOAccounting=true
+CPUAccounting=true
diff --git a/lib/support/systemd/gitlab.target b/lib/support/systemd/gitlab.target
new file mode 100644
index 00000000000..e0538c3ff81
--- /dev/null
+++ b/lib/support/systemd/gitlab.target
@@ -0,0 +1,6 @@
+[Unit]
+Description=GitLab
+Wants=gitlab-gitaly.service gitlab-puma.service gitlab-sidekiq.service gitlab-workhorse.service
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/system_check/app/init_script_exists_check.rb b/lib/system_check/app/init_script_exists_check.rb
deleted file mode 100644
index 7be92acdc37..00000000000
--- a/lib/system_check/app/init_script_exists_check.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module SystemCheck
- module App
- class InitScriptExistsCheck < SystemCheck::BaseCheck
- set_name 'Init script exists?'
- set_skip_reason 'skipped (omnibus-gitlab has no init script)'
-
- def skip?
- omnibus_gitlab?
- end
-
- def check?
- script_path = '/etc/init.d/gitlab'
- File.exist?(script_path)
- end
-
- def show_error
- try_fixing_it(
- 'Install the init script'
- )
- for_more_information(
- see_installation_guide_section('Install Init Script')
- )
- fix_and_rerun
- end
- end
- end
-end
diff --git a/lib/system_check/app/init_script_up_to_date_check.rb b/lib/system_check/app/init_script_up_to_date_check.rb
deleted file mode 100644
index cf841d5e659..00000000000
--- a/lib/system_check/app/init_script_up_to_date_check.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-module SystemCheck
- module App
- class InitScriptUpToDateCheck < SystemCheck::BaseCheck
- SCRIPT_PATH = '/etc/init.d/gitlab'
-
- set_name 'Init script up-to-date?'
- set_skip_reason 'skipped (omnibus-gitlab has no init script)'
-
- def skip?
- return true if omnibus_gitlab?
-
- unless init_file_exists?
- self.skip_reason = "can't check because of previous errors"
-
- true
- end
- end
-
- def check?
- recipe_path = Rails.root.join('lib/support/init.d/', 'gitlab')
-
- recipe_content = File.read(recipe_path)
- script_content = File.read(SCRIPT_PATH)
-
- recipe_content == script_content
- end
-
- def show_error
- try_fixing_it(
- 'Re-download the init script'
- )
- for_more_information(
- see_installation_guide_section('Install Init Script')
- )
- fix_and_rerun
- end
-
- private
-
- def init_file_exists?
- File.exist?(SCRIPT_PATH)
- end
- end
- end
-end
diff --git a/lib/system_check/app/systemd_unit_files_or_init_script_exist_check.rb b/lib/system_check/app/systemd_unit_files_or_init_script_exist_check.rb
new file mode 100644
index 00000000000..b2f059d212b
--- /dev/null
+++ b/lib/system_check/app/systemd_unit_files_or_init_script_exist_check.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module SystemCheck
+ module App
+ class SystemdUnitFilesOrInitScriptExistCheck < SystemCheck::BaseCheck
+ set_name 'Systemd unit files or init script exist?'
+ set_skip_reason 'skipped (omnibus-gitlab has neither init script nor systemd units)'
+
+ def skip?
+ omnibus_gitlab?
+ end
+
+ def check?
+ unit_paths = [
+ '/usr/local/lib/systemd/system/gitlab-gitaly.service',
+ '/usr/local/lib/systemd/system/gitlab-mailroom.service',
+ '/usr/local/lib/systemd/system/gitlab-puma.service',
+ '/usr/local/lib/systemd/system/gitlab-sidekiq.service',
+ '/usr/local/lib/systemd/system/gitlab.slice',
+ '/usr/local/lib/systemd/system/gitlab.target',
+ '/usr/local/lib/systemd/system/gitlab-workhorse.service'
+ ]
+ script_path = '/etc/init.d/gitlab'
+
+ unit_paths.all? { |s| File.exist?(s) } || File.exist?(script_path)
+ end
+
+ def show_error
+ try_fixing_it(
+ 'Install the Service'
+ )
+ for_more_information(
+ see_installation_guide_section('Install the Service')
+ )
+ fix_and_rerun
+ end
+ end
+ end
+end
diff --git a/lib/system_check/app/systemd_unit_files_or_init_script_up_to_date_check.rb b/lib/system_check/app/systemd_unit_files_or_init_script_up_to_date_check.rb
new file mode 100644
index 00000000000..10bc772a83c
--- /dev/null
+++ b/lib/system_check/app/systemd_unit_files_or_init_script_up_to_date_check.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+module SystemCheck
+ module App
+ class SystemdUnitFilesOrInitScriptUpToDateCheck < SystemCheck::BaseCheck
+ SCRIPT_PATH = '/etc/init.d/gitlab'
+ UNIT_PATHS = [
+ '/usr/local/lib/systemd/system/gitlab-gitaly.service',
+ '/usr/local/lib/systemd/system/gitlab-mailroom.service',
+ '/usr/local/lib/systemd/system/gitlab-puma.service',
+ '/usr/local/lib/systemd/system/gitlab-sidekiq.service',
+ '/usr/local/lib/systemd/system/gitlab.slice',
+ '/usr/local/lib/systemd/system/gitlab.target',
+ '/usr/local/lib/systemd/system/gitlab-workhorse.service'
+ ].freeze
+
+ set_name 'Systemd unit files or init script up-to-date?'
+ set_skip_reason 'skipped (omnibus-gitlab has neither init script nor systemd units)'
+
+ def skip?
+ return true if omnibus_gitlab?
+
+ unless unit_files_exist? || init_file_exists?
+ self.skip_reason = "can't check because of previous errors"
+
+ true
+ end
+ end
+
+ def check?
+ if unit_files_exist?
+ return unit_files_up_to_date?
+ end
+
+ init_file_up_to_date?
+ end
+
+ def show_error
+ try_fixing_it(
+ 'Install the Service'
+ )
+ for_more_information(
+ see_installation_guide_section('Install the Service')
+ )
+ fix_and_rerun
+ end
+
+ private
+
+ def init_file_exists?
+ File.exist?(SCRIPT_PATH)
+ end
+
+ def unit_files_exist?
+ UNIT_PATHS.all? { |s| File.exist?(s) }
+ end
+
+ def init_file_up_to_date?
+ recipe_path = Rails.root.join('lib/support/init.d/', 'gitlab')
+
+ recipe_content = File.read(recipe_path)
+ script_content = File.read(SCRIPT_PATH)
+
+ recipe_content == script_content
+ end
+
+ def unit_files_up_to_date?
+ UNIT_PATHS.all? do |unit|
+ unit_name = File.basename(unit)
+ recipe_path = Rails.root.join('lib/support/systemd/', unit_name)
+
+ recipe_content = File.read(recipe_path)
+ unit_content = File.read(unit)
+
+ recipe_content == unit_content
+ end
+ end
+ end
+ end
+end
diff --git a/lib/system_check/incoming_email/initd_configured_check.rb b/lib/system_check/incoming_email/initd_configured_check.rb
deleted file mode 100644
index acb4b5a9e74..00000000000
--- a/lib/system_check/incoming_email/initd_configured_check.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-module SystemCheck
- module IncomingEmail
- class InitdConfiguredCheck < SystemCheck::BaseCheck
- set_name 'Init.d configured correctly?'
-
- def skip?
- omnibus_gitlab?
- end
-
- def check?
- mail_room_configured?
- end
-
- def show_error
- try_fixing_it(
- 'Enable mail_room in the init.d configuration.'
- )
- for_more_information(
- 'doc/administration/reply_by_email.md'
- )
- fix_and_rerun
- end
-
- private
-
- def mail_room_configured?
- path = '/etc/default/gitlab'
- File.exist?(path) && File.read(path).include?('mail_room_enabled=true')
- end
- end
- end
-end
diff --git a/lib/system_check/incoming_email/mail_room_enabled_check.rb b/lib/system_check/incoming_email/mail_room_enabled_check.rb
new file mode 100644
index 00000000000..8e725aabd03
--- /dev/null
+++ b/lib/system_check/incoming_email/mail_room_enabled_check.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module SystemCheck
+ module IncomingEmail
+ class MailRoomEnabledCheck < SystemCheck::BaseCheck
+ include ::SystemCheck::InitHelpers
+ set_name 'Mailroom enabled?'
+
+ def skip?
+ omnibus_gitlab?
+ end
+
+ def check?
+ mail_room_enabled? || mail_room_configured?
+ end
+
+ def show_error
+ try_fixing_it(
+ 'Enable mail_room'
+ )
+ for_more_information(
+ 'doc/administration/reply_by_email.md'
+ )
+ fix_and_rerun
+ end
+
+ private
+
+ def mail_room_enabled?
+ target = '/usr/local/lib/systemd/system/gitlab.target'
+ service = '/usr/local/lib/systemd/system/gitlab-mailroom.service'
+
+ File.exist?(target) && File.exist?(service) && systemd_get_wants('gitlab.target').include?("gitlab-mailroom.service")
+ end
+
+ def mail_room_configured?
+ path = '/etc/default/gitlab'
+ File.exist?(path) && File.read(path).include?('mail_room_enabled=true')
+ end
+ end
+ end
+end
diff --git a/lib/system_check/incoming_email/mail_room_running_check.rb b/lib/system_check/incoming_email/mail_room_running_check.rb
index b7aead4624e..38bb1e46364 100644
--- a/lib/system_check/incoming_email/mail_room_running_check.rb
+++ b/lib/system_check/incoming_email/mail_room_running_check.rb
@@ -3,12 +3,13 @@
module SystemCheck
module IncomingEmail
class MailRoomRunningCheck < SystemCheck::BaseCheck
+ include ::SystemCheck::InitHelpers
set_name 'MailRoom running?'
def skip?
return true if omnibus_gitlab?
- unless mail_room_configured?
+ unless mail_room_enabled? || mail_room_configured?
self.skip_reason = "can't check because of previous errors"
true
end
@@ -20,10 +21,10 @@ module SystemCheck
def show_error
try_fixing_it(
- sudo_gitlab('RAILS_ENV=production bin/mail_room start')
+ 'Start mail_room'
)
for_more_information(
- see_installation_guide_section('Install Init Script'),
+ 'doc/administration/incoming_email.md',
'see log/mail_room.log for possible errors'
)
fix_and_rerun
@@ -31,6 +32,13 @@ module SystemCheck
private
+ def mail_room_enabled?
+ target = '/usr/local/lib/systemd/system/gitlab.target'
+ service = '/usr/local/lib/systemd/system/gitlab-mailroom.service'
+
+ File.exist?(target) && File.exist?(service) && systemd_get_wants('gitlab.target').include?("gitlab-mailroom.service")
+ end
+
def mail_room_configured?
path = '/etc/default/gitlab'
File.exist?(path) && File.read(path).include?('mail_room_enabled=true')
diff --git a/lib/system_check/incoming_email_check.rb b/lib/system_check/incoming_email_check.rb
index 84033ada710..3cae9450b94 100644
--- a/lib/system_check/incoming_email_check.rb
+++ b/lib/system_check/incoming_email_check.rb
@@ -14,7 +14,7 @@ module SystemCheck
end
if Rails.env.production?
- checks << SystemCheck::IncomingEmail::InitdConfiguredCheck
+ checks << SystemCheck::IncomingEmail::MailRoomEnabledCheck
checks << SystemCheck::IncomingEmail::MailRoomRunningCheck
end
diff --git a/lib/system_check/init_helpers.rb b/lib/system_check/init_helpers.rb
new file mode 100644
index 00000000000..2573f06b716
--- /dev/null
+++ b/lib/system_check/init_helpers.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'open3'
+
+module SystemCheck
+ module InitHelpers
+ # Return the Wants= of a unit, empty if the unit doesn't exist
+ def systemd_get_wants(unitname)
+ stdout, _stderr, status = Open3.capture3("systemctl", "--no-pager", "show", unitname)
+
+ unless status
+ return []
+ end
+
+ wantsline = stdout.lines.find { |line| line.start_with?("Wants=") }
+
+ unless wantsline
+ return []
+ end
+
+ wantsline.delete_prefix("Wants=").strip.split
+ end
+ end
+end
diff --git a/lib/system_check/rake_task/app_task.rb b/lib/system_check/rake_task/app_task.rb
index f7d2bf86c78..892417d67ec 100644
--- a/lib/system_check/rake_task/app_task.rb
+++ b/lib/system_check/rake_task/app_task.rb
@@ -23,8 +23,8 @@ module SystemCheck
SystemCheck::App::UploadsDirectoryExistsCheck,
SystemCheck::App::UploadsPathPermissionCheck,
SystemCheck::App::UploadsPathTmpPermissionCheck,
- SystemCheck::App::InitScriptExistsCheck,
- SystemCheck::App::InitScriptUpToDateCheck,
+ SystemCheck::App::SystemdUnitFilesOrInitScriptExistCheck,
+ SystemCheck::App::SystemdUnitFilesOrInitScriptUpToDateCheck,
SystemCheck::App::ProjectsHaveNamespaceCheck,
SystemCheck::App::RedisVersionCheck,
SystemCheck::App::RubyVersionCheck,
diff --git a/lib/system_check/sidekiq_check.rb b/lib/system_check/sidekiq_check.rb
index 7ac1bd58ede..ab048433b37 100644
--- a/lib/system_check/sidekiq_check.rb
+++ b/lib/system_check/sidekiq_check.rb
@@ -39,6 +39,12 @@ module SystemCheck
if (cluster_count == 1 && worker_count > 0) || (cluster_count == 0 && worker_count == 1)
$stdout.puts "#{cluster_count}/#{worker_count}".color(:green)
+ elsif File.symlink?('/run/systemd/units/invocation:gitlab-sidekiq.service')
+ $stdout.puts "#{cluster_count}/#{worker_count}".color(:red)
+ try_fixing_it(
+ 'sudo systemctl restart gitlab-sidekiq.service'
+ )
+ fix_and_rerun
else
$stdout.puts "#{cluster_count}/#{worker_count}".color(:red)
try_fixing_it(
diff --git a/lib/tasks/gemojione.rake b/lib/tasks/gemojione.rake
deleted file mode 100644
index a4600a0ed16..00000000000
--- a/lib/tasks/gemojione.rake
+++ /dev/null
@@ -1,245 +0,0 @@
-# frozen_string_literal: true
-
-namespace :gemojione do
- desc 'Generates Emoji SHA256 digests'
-
- task aliases: ['yarn:check', 'environment'] do
- require 'json'
-
- aliases = {}
-
- index_file = File.join(Rails.root, 'fixtures', 'emojis', 'index.json')
- index = Gitlab::Json.parse(File.read(index_file))
-
- index.each_pair do |key, data|
- data['aliases'].each do |a|
- a.tr!(':', '')
-
- aliases[a] = key
- end
- end
-
- out = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json')
- File.open(out, 'w') do |handle|
- handle.write(Gitlab::Json.pretty_generate(aliases, indent: ' ', space: '', space_before: ''))
- end
- end
-
- task digests: ['yarn:check', 'environment'] do
- require 'digest/sha2'
- require 'json'
-
- # We don't have `node_modules` available in built versions of GitLab
- FileUtils.cp_r(Rails.root.join('node_modules', 'emoji-unicode-version', 'emoji-unicode-version-map.json'), File.join(Rails.root, 'fixtures', 'emojis'))
-
- dir = Gemojione.images_path
- resultant_emoji_map = {}
- resultant_emoji_map_new = {}
-
- Gitlab::Emoji.emojis.each do |name, emoji_hash|
- # Ignore aliases
- unless Gitlab::Emoji.emojis_aliases.key?(name)
- fpath = File.join(dir, "#{emoji_hash['unicode']}.png")
- hash_digest = Digest::SHA256.file(fpath).hexdigest
-
- category = emoji_hash['category']
- if name == 'gay_pride_flag'
- category = 'flags'
- end
-
- entry = {
- category: category,
- moji: emoji_hash['moji'],
- description: emoji_hash['description'],
- unicodeVersion: Gitlab::Emoji.emoji_unicode_version(name),
- digest: hash_digest
- }
-
- resultant_emoji_map[name] = entry
-
- # Our new map is only characters to make the json substantially smaller
- new_entry = {
- c: category,
- e: emoji_hash['moji'],
- d: emoji_hash['description'],
- u: Gitlab::Emoji.emoji_unicode_version(name)
- }
-
- resultant_emoji_map_new[name] = new_entry
- end
- end
-
- out = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json')
- File.open(out, 'w') do |handle|
- handle.write(Gitlab::Json.pretty_generate(resultant_emoji_map))
- end
-
- out_new = File.join(Rails.root, 'public', '-', 'emojis', '1', 'emojis.json')
- File.open(out_new, 'w') do |handle|
- handle.write(Gitlab::Json.pretty_generate(resultant_emoji_map_new))
- end
- end
-
- # This task will generate a standard and Retina sprite of all of the current
- # Gemojione Emojis, with the accompanying SCSS map.
- #
- # It will not appear in `rake -T` output, and the dependent gems are not
- # included in the Gemfile by default, because this task will only be needed
- # occasionally, such as when new Emojis are added to Gemojione.
- task sprite: :environment do
- begin
- require 'sprite_factory'
- require 'rmagick'
- rescue LoadError
- # noop
- end
-
- check_requirements!
-
- SIZE = 20
- RETINA = SIZE * 2
-
- # Update these values to the width and height of the spritesheet when
- # new emoji are added.
- SPRITESHEET_WIDTH = 860
- SPRITESHEET_HEIGHT = 840
-
- # Set up a map to rename image files
- emoji_unicode_string_to_name_map = {}
- Gitlab::Emoji.emojis.each do |name, emoji_hash|
- # Ignore aliases
- unless Gitlab::Emoji.emojis_aliases.key?(name)
- emoji_unicode_string_to_name_map[emoji_hash['unicode']] = name
- end
- end
-
- # Copy the Gemojione assets to the temporary folder for renaming
- emoji_dir = "app/assets/images/emoji"
- FileUtils.rm_rf(emoji_dir)
- FileUtils.mkdir_p(emoji_dir, mode: 0700)
- FileUtils.cp_r(File.join(Gemojione.images_path, '.'), emoji_dir)
- Dir[File.join(emoji_dir, "**/*.png")].each do |png|
- image_path = png
- rename_to_named_emoji_image!(emoji_unicode_string_to_name_map, image_path)
- end
-
- Dir.mktmpdir do |tmpdir|
- FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
-
- Dir.chdir(tmpdir) do
- Dir["**/*.png"].each do |png|
- tmp_image_path = File.join(tmpdir, png)
- resize!(tmp_image_path, SIZE)
- end
- end
-
- style_path = Rails.root.join(*%w(app assets stylesheets framework emoji_sprites.scss))
-
- # Combine the resized assets into a packed sprite and re-generate the SCSS
- SpriteFactory.cssurl = "image-url('$IMAGE')"
- SpriteFactory.run!(tmpdir, {
- output_style: style_path,
- output_image: "app/assets/images/emoji.png",
- selector: '.emoji-',
- style: :scss,
- nocomments: true,
- pngcrush: true,
- layout: :packed
- })
-
- # SpriteFactory's SCSS is a bit too verbose for our purposes here, so
- # let's simplify it
- system(%Q(sed -i '' "s/width: #{SIZE}px; height: #{SIZE}px; background: image-url('emoji.png')/background-position:/" #{style_path}))
- system(%Q(sed -i '' "s/ no-repeat//" #{style_path}))
- system(%Q(sed -i '' "s/ 0px/ 0/g" #{style_path}))
-
- # Append a generic rule that applies to all Emojis
- File.open(style_path, 'a') do |f|
- f.puts
- f.puts <<-CSS.strip_heredoc
- .emoji-icon {
- background-image: image-url('emoji.png');
- background-repeat: no-repeat;
- color: transparent;
- text-indent: -99em;
- height: #{SIZE}px;
- width: #{SIZE}px;
-
- @media only screen and (-webkit-min-device-pixel-ratio: 2),
- only screen and (min--moz-device-pixel-ratio: 2),
- only screen and (-o-min-device-pixel-ratio: 2/1),
- only screen and (min-device-pixel-ratio: 2),
- only screen and (min-resolution: 192dpi),
- only screen and (min-resolution: 2dppx) {
- background-image: image-url('emoji@2x.png');
- background-size: #{SPRITESHEET_WIDTH}px #{SPRITESHEET_HEIGHT}px;
- }
- }
- CSS
- end
- end
-
- # Now do it again but for Retina
- Dir.mktmpdir do |tmpdir|
- # Copy the Gemojione assets to the temporary folder for resizing
- FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
-
- Dir.chdir(tmpdir) do
- Dir["**/*.png"].each do |png|
- tmp_image_path = File.join(tmpdir, png)
- resize!(tmp_image_path, RETINA)
- end
- end
-
- # Combine the resized assets into a packed sprite and re-generate the SCSS
- SpriteFactory.run!(tmpdir, {
- output_image: "app/assets/images/emoji@2x.png",
- style: false,
- nocomments: true,
- pngcrush: true,
- layout: :packed
- })
- end
- end
-
- def check_requirements!
- return if defined?(SpriteFactory) && defined?(Magick)
-
- puts <<-MSG.strip_heredoc
- This task is disabled by default and should only be run when the Gemojione
- gem is updated with new Emojis.
-
- To enable this task, *temporarily* add the following lines to Gemfile and
- re-bundle:
-
- gem 'sprite-factory'
- gem 'rmagick'
- MSG
-
- exit 1
- end
-
- def resize!(image_path, size)
- # Resize the image in-place, save it, and free the object
- image = Magick::Image.read(image_path).first
- image.resize!(size, size)
- image.write(image_path) { self.quality = 100 }
- image.destroy!
- end
-
- EMOJI_IMAGE_PATH_RE = /(.*?)(([0-9a-f]-?)+)\.png$/i.freeze
- def rename_to_named_emoji_image!(emoji_unicode_string_to_name_map, image_path)
- # Rename file from unicode to emoji name
- matches = EMOJI_IMAGE_PATH_RE.match(image_path)
- preceding_path = matches[1]
- unicode_string = matches[2]
- name = emoji_unicode_string_to_name_map[unicode_string]
- if name
- new_png_path = File.join(preceding_path, "#{name}.png")
- FileUtils.mv(image_path, new_png_path)
- new_png_path
- else
- puts "Warning: emoji_unicode_string_to_name_map missing entry for #{unicode_string}. Full path: #{image_path}"
- end
- end
-end
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index e2647021914..e83c4cbdb39 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -160,35 +160,44 @@ namespace :gitlab do
Rake::Task['gitlab:db:create_dynamic_partitions'].invoke
end
- desc 'reindex a regular index without downtime to eliminate bloat'
- task :reindex, [:index_name] => :environment do |_, args|
- unless Feature.enabled?(:database_reindexing, type: :ops)
+ desc 'execute reindexing without downtime to eliminate bloat'
+ task reindex: :environment do
+ unless Feature.enabled?(:database_reindexing, type: :ops, default_enabled: :yaml)
puts "This feature (database_reindexing) is currently disabled.".color(:yellow)
exit
end
- indexes = Gitlab::Database::PostgresIndex.reindexing_support
+ Gitlab::Database::EachDatabase.each_database_connection do |connection, connection_name|
+ Gitlab::Database::SharedModel.logger = Logger.new($stdout) if Gitlab::Utils.to_boolean(ENV['LOG_QUERIES_TO_CONSOLE'], default: false)
- if identifier = args[:index_name]
- raise ArgumentError, "Index name is not fully qualified with a schema: #{identifier}" unless identifier =~ /^\w+\.\w+$/
+ # Hack: Before we do actual reindexing work, create async indexes
+ Gitlab::Database::AsyncIndexes.create_pending_indexes! if Feature.enabled?(:database_async_index_creation, type: :ops)
- indexes = indexes.where(identifier: identifier)
-
- raise "Index not found or not supported: #{args[:index_name]}" if indexes.empty?
+ Gitlab::Database::Reindexing.automatic_reindexing
end
+ rescue StandardError => e
+ Gitlab::AppLogger.error(e)
+ raise
+ end
- ActiveRecord::Base.logger = Logger.new($stdout) if Gitlab::Utils.to_boolean(ENV['LOG_QUERIES_TO_CONSOLE'], default: false)
+ desc 'Enqueue an index for reindexing'
+ task :enqueue_reindexing_action, [:index_name, :database] => :environment do |_, args|
+ model = Gitlab::Database.database_base_models[args.fetch(:database, Gitlab::Database::PRIMARY_DATABASE_NAME)]
- # Cleanup leftover temporary indexes from previous, possibly aborted runs (if any)
- Gitlab::Database::Reindexing.cleanup_leftovers!
+ Gitlab::Database::SharedModel.using_connection(model.connection) do
+ queued_action = Gitlab::Database::PostgresIndex.find(args[:index_name]).queued_reindexing_actions.create!
- # Hack: Before we do actual reindexing work, create async indexes
- Gitlab::Database::AsyncIndexes.create_pending_indexes! if Feature.enabled?(:database_async_index_creation, type: :ops)
+ puts "Queued reindexing action: #{queued_action}"
+ puts "There are #{Gitlab::Database::Reindexing::QueuedAction.queued.size} queued actions in total."
+ end
- Gitlab::Database::Reindexing.perform(indexes)
- rescue StandardError => e
- Gitlab::AppLogger.error(e)
- raise
+ unless Feature.enabled?(:database_reindexing, type: :ops, default_enabled: :yaml)
+ puts <<~NOTE.color(:yellow)
+ Note: database_reindexing feature is currently disabled.
+
+ Enable with: Feature.enable(:database_reindexing)
+ NOTE
+ end
end
desc 'Check if there have been user additions to the database'
diff --git a/lib/tasks/gitlab/docs/compile_deprecations.rake b/lib/tasks/gitlab/docs/compile_deprecations.rake
index 0fd43775015..dc9788cb0b2 100644
--- a/lib/tasks/gitlab/docs/compile_deprecations.rake
+++ b/lib/tasks/gitlab/docs/compile_deprecations.rake
@@ -21,7 +21,7 @@ namespace :gitlab do
if doc == contents
puts "Deprecations doc is up to date."
else
- format_output('Deprecations doc is outdated! Please update it by running `bundle exec rake gitlab:docs:compile_deprecations`.')
+ format_output('Deprecations doc is outdated! You (or your technical writer) can update it by running `bin/rake gitlab:docs:compile_deprecations`.')
abort
end
end
diff --git a/lib/tasks/gitlab/gitaly.rake b/lib/tasks/gitlab/gitaly.rake
index ef58c9339f1..eabbb8652f1 100644
--- a/lib/tasks/gitlab/gitaly.rake
+++ b/lib/tasks/gitlab/gitaly.rake
@@ -67,7 +67,8 @@ Usage: rake "gitlab:gitaly:install[/installation/dir,/storage/path]")
env["BUNDLE_DEPLOYMENT"] = 'false'
end
- Gitlab::Popen.popen([make_cmd], nil, env)
+ output, status = Gitlab::Popen.popen([make_cmd, 'all', 'git'], nil, env)
+ raise "Gitaly failed to compile: #{output}" unless status&.zero?
end
end
end
diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake
index 68395d10d24..02764b5d46f 100644
--- a/lib/tasks/gitlab/info.rake
+++ b/lib/tasks/gitlab/info.rake
@@ -68,8 +68,8 @@ namespace :gitlab do
puts "Version:\t#{Gitlab::VERSION}"
puts "Revision:\t#{Gitlab.revision}"
puts "Directory:\t#{Rails.root}"
- puts "DB Adapter:\t#{Gitlab::Database.main.human_adapter_name}"
- puts "DB Version:\t#{Gitlab::Database.main.version}"
+ puts "DB Adapter:\t#{ApplicationRecord.database.human_adapter_name}"
+ puts "DB Version:\t#{ApplicationRecord.database.version}"
puts "URL:\t\t#{Gitlab.config.gitlab.url}"
puts "HTTP Clone URL:\t#{http_clone_url}"
puts "SSH Clone URL:\t#{ssh_clone_url}"
diff --git a/lib/tasks/gitlab/sidekiq.rake b/lib/tasks/gitlab/sidekiq.rake
index 90ed91221ae..2e383065b64 100644
--- a/lib/tasks/gitlab/sidekiq.rake
+++ b/lib/tasks/gitlab/sidekiq.rake
@@ -36,13 +36,17 @@ namespace :gitlab do
# Do not edit it manually!
BANNER
- foss_workers, ee_workers = Gitlab::SidekiqConfig.workers_for_all_queues_yml
+ foss_workers, ee_workers, jh_workers = Gitlab::SidekiqConfig.workers_for_all_queues_yml
write_yaml(Gitlab::SidekiqConfig::FOSS_QUEUE_CONFIG_PATH, banner, foss_workers)
if Gitlab.ee?
write_yaml(Gitlab::SidekiqConfig::EE_QUEUE_CONFIG_PATH, banner, ee_workers)
end
+
+ if Gitlab.jh?
+ write_yaml(Gitlab::SidekiqConfig::JH_QUEUE_CONFIG_PATH, banner, jh_workers)
+ end
end
desc 'GitLab | Sidekiq | Validate that all_queues.yml matches worker definitions'
@@ -57,6 +61,7 @@ namespace :gitlab do
- #{Gitlab::SidekiqConfig::FOSS_QUEUE_CONFIG_PATH}
- #{Gitlab::SidekiqConfig::EE_QUEUE_CONFIG_PATH}
+ #{"- " + Gitlab::SidekiqConfig::JH_QUEUE_CONFIG_PATH if Gitlab.jh?}
MSG
end
diff --git a/lib/tasks/gitlab/storage.rake b/lib/tasks/gitlab/storage.rake
index fb9f9b9fe67..eb5eeed531f 100644
--- a/lib/tasks/gitlab/storage.rake
+++ b/lib/tasks/gitlab/storage.rake
@@ -170,7 +170,7 @@ namespace :gitlab do
inverval = (ENV['MAX_DATABASE_CONNECTION_CHECK_INTERVAL'] || 10).to_f
attempts.to_i.times do
- unless Gitlab::Database.main.exists?
+ unless ApplicationRecord.database.exists?
puts "Waiting until database is ready before continuing...".color(:yellow)
sleep inverval
end
diff --git a/lib/tasks/haml-lint.rake b/lib/tasks/haml-lint.rake
index 270793359e1..71e84d3795f 100644
--- a/lib/tasks/haml-lint.rake
+++ b/lib/tasks/haml-lint.rake
@@ -4,16 +4,5 @@ unless Rails.env.production?
require 'haml_lint/rake_task'
require Rails.root.join('haml_lint/inline_javascript')
- # Workaround for warnings from parser/current
- # Keep it even if it no longer emits any warnings,
- # because we'll still see warnings in console/server anyway,
- # and we don't need to break static-analysis for this.
- task :haml_lint do
- require 'parser'
- def Parser.warn(*args)
- puts(*args) # static-analysis ignores stdout if status is 0
- end
- end
-
HamlLint::RakeTask.new
end
diff --git a/lib/tasks/tanuki_emoji.rake b/lib/tasks/tanuki_emoji.rake
new file mode 100644
index 00000000000..98d3920c07f
--- /dev/null
+++ b/lib/tasks/tanuki_emoji.rake
@@ -0,0 +1,260 @@
+# frozen_string_literal: true
+
+namespace :tanuki_emoji do
+ desc 'Generates Emoji aliases fixtures'
+ task aliases: :environment do
+ aliases = {}
+
+ TanukiEmoji.index.all.each do |emoji|
+ emoji.aliases.each do |emoji_alias|
+ aliases[TanukiEmoji::Character.format_name(emoji_alias)] = emoji.name
+ end
+ end
+
+ aliases_json_file = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json')
+ File.open(aliases_json_file, 'w') do |handle|
+ handle.write(Gitlab::Json.pretty_generate(aliases, indent: ' ', space: '', space_before: ''))
+ end
+ end
+
+ desc 'Generates Emoji SHA256 digests'
+ task digests: :environment do
+ require 'digest/sha2'
+
+ digest_emoji_map = {}
+ emojis_map = {}
+
+ TanukiEmoji.index.all.each do |emoji|
+ emoji_path = Gitlab::Emoji.emoji_public_absolute_path.join("#{emoji.name}.png")
+
+ digest_entry = {
+ category: emoji.category,
+ moji: emoji.codepoints,
+ description: emoji.description,
+ unicodeVersion: emoji.unicode_version,
+ digest: Digest::SHA256.file(emoji_path).hexdigest
+ }
+
+ digest_emoji_map[emoji.name] = digest_entry
+
+ # Our new map is only characters to make the json substantially smaller
+ emoji_entry = {
+ c: emoji.category,
+ e: emoji.codepoints,
+ d: emoji.description,
+ u: emoji.unicode_version
+ }
+
+ emojis_map[emoji.name] = emoji_entry
+ end
+
+ digests_json = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json')
+ File.open(digests_json, 'w') do |handle|
+ handle.write(Gitlab::Json.pretty_generate(digest_emoji_map))
+ end
+
+ emojis_json = Gitlab::Emoji.emoji_public_absolute_path.join('emojis.json')
+ File.open(emojis_json, 'w') do |handle|
+ handle.write(Gitlab::Json.pretty_generate(emojis_map))
+ end
+ end
+
+ desc 'Import emoji assets from TanukiEmoji to versioned folder'
+ task import: :environment do
+ require 'mini_magick'
+
+ # Setting to the same size as previous gemojione images
+ EMOJI_SIZE = 64
+
+ emoji_dir = Gitlab::Emoji.emoji_public_absolute_path
+
+ puts "Importing emojis into: #{emoji_dir} ..."
+
+ # Re-create the assets folder and copy emojis renaming them to use name instead of unicode hex
+ FileUtils.rm_rf(emoji_dir) if Dir.exist?(emoji_dir)
+ FileUtils.mkdir_p(emoji_dir, mode: 0700)
+
+ TanukiEmoji.index.all.each do |emoji|
+ source = File.join(TanukiEmoji.images_path, emoji.image_name)
+ destination = File.join(emoji_dir, "#{emoji.name}.png")
+
+ FileUtils.cp(source, destination)
+ resize!(destination, EMOJI_SIZE)
+ print emoji.codepoints
+ end
+
+ puts
+ puts 'Done!'
+ end
+
+ # This task will generate a standard and Retina sprite of all of the current
+ # TanukiEmoji Emojis, with the accompanying SCSS map.
+ #
+ # It will not appear in `rake -T` output, and the dependent gems are not
+ # included in the Gemfile by default, because this task will only be needed
+ # occasionally, such as when new Emojis are added to TanukiEmoji.
+ task sprite: :environment do
+ begin
+ require 'sprite_factory'
+ # Sprite-Factory still requires rmagick, but maybe could be migrated to support minimagick
+ # Upstream issue: https://github.com/jakesgordon/sprite-factory/issues/47#issuecomment-929302890
+ require 'rmagick'
+ rescue LoadError
+ # noop
+ end
+
+ check_requirements!
+
+ SIZE = 20
+ RETINA = SIZE * 2
+
+ # Update these values to the width and height of the spritesheet when
+ # new emoji are added.
+ SPRITESHEET_WIDTH = 860
+ SPRITESHEET_HEIGHT = 840
+
+ emoji_dir = Gitlab::Emoji.emoji_public_absolute_path
+
+ puts "Preparing sprites for regular size: #{SIZE}px..."
+
+ Dir.mktmpdir do |tmpdir|
+ FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
+
+ Dir.chdir(tmpdir) do
+ Dir["**/*.png"].each do |png|
+ tmp_image_path = File.join(tmpdir, png)
+ resize!(tmp_image_path, SIZE)
+ print '.'
+ end
+ end
+ puts ' Done!'
+
+ puts "\n"
+
+ style_path = Rails.root.join(*%w(app assets stylesheets emoji_sprites.scss))
+
+ print 'Compiling sprites regular sprites... '
+
+ # Combine the resized assets into a packed sprite and re-generate the SCSS
+ SpriteFactory.cssurl = "image-url('$IMAGE')"
+ SpriteFactory.run!(tmpdir, {
+ output_style: style_path,
+ output_image: "app/assets/images/emoji.png",
+ selector: '.emoji-',
+ style: :scss,
+ nocomments: true,
+ pngcrush: true,
+ layout: :packed
+ })
+
+ # SpriteFactory's SCSS is a bit too verbose for our purposes here, so
+ # let's simplify it
+ system(%Q(sed -i '' "s/width: #{SIZE}px; height: #{SIZE}px; background: image-url('emoji.png')/background-position:/" #{style_path}))
+ system(%Q(sed -i '' "s/ no-repeat//" #{style_path}))
+ system(%Q(sed -i '' "s/ 0px/ 0/g" #{style_path}))
+
+ # Append a generic rule that applies to all Emojis
+ File.open(style_path, 'a') do |f|
+ f.puts
+ f.puts <<-CSS.strip_heredoc
+ .emoji-icon {
+ background-image: image-url('emoji.png');
+ background-repeat: no-repeat;
+ color: transparent;
+ text-indent: -99em;
+ height: #{SIZE}px;
+ width: #{SIZE}px;
+
+ /* stylelint-disable media-feature-name-no-vendor-prefix */
+ @media only screen and (-webkit-min-device-pixel-ratio: 2),
+ only screen and (min--moz-device-pixel-ratio: 2),
+ only screen and (-o-min-device-pixel-ratio: 2/1),
+ only screen and (min-device-pixel-ratio: 2),
+ only screen and (min-resolution: 192dpi),
+ only screen and (min-resolution: 2dppx) {
+ background-image: image-url('emoji@2x.png');
+ background-size: #{SPRITESHEET_WIDTH}px #{SPRITESHEET_HEIGHT}px;
+ }
+ /* stylelint-enable media-feature-name-no-vendor-prefix */
+ }
+ CSS
+ end
+ end
+ puts 'Done!'
+
+ puts "\n"
+
+ puts "Preparing sprites for HiDPI size: #{RETINA}px..."
+
+ # Now do it again but for Retina
+ Dir.mktmpdir do |tmpdir|
+ # Copy the TanukiEmoji assets to the temporary folder for resizing
+ FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
+
+ Dir.chdir(tmpdir) do
+ Dir["**/*.png"].each do |png|
+ tmp_image_path = File.join(tmpdir, png)
+ resize!(tmp_image_path, RETINA)
+ print '.'
+ end
+ end
+ puts ' Done!'
+
+ puts "\n"
+
+ print 'Compiling HiDPI sprites...'
+
+ # Combine the resized assets into a packed sprite and re-generate the SCSS
+ SpriteFactory.run!(tmpdir, {
+ output_image: "app/assets/images/emoji@2x.png",
+ style: false,
+ nocomments: true,
+ pngcrush: true,
+ layout: :packed
+ })
+ end
+
+ puts ' Done!'
+ end
+
+ def check_requirements!
+ unless defined?(Magick)
+ puts <<~MSG
+ This task is disabled by default and should only be run when the TanukiEmoji
+ gem is updated with new Emojis.
+
+ To enable this task, *temporarily* add the following lines to Gemfile and
+ re-bundle:
+
+ gem 'rmagick', '~> 3.2'
+
+ It depends on ImageMagick 6, which can be installed via HomeBrew with:
+
+ brew unlink imagemagick
+ brew install imagemagick@6 && brew link imagemagick@6 --force
+ MSG
+
+ exit 1
+ end
+
+ return if Dir.exist? Gitlab::Emoji.emoji_public_absolute_path
+
+ puts <<~MSG
+ You first need to import the assets for Emoji version: #{Gitlab::Emoji::EMOJI_VERSION}
+
+ Run the following task:
+
+ rake tanuki_emoji:import
+ MSG
+
+ exit 1
+ end
+
+ def resize!(image_path, size)
+ # Resize the image in-place, save it, and free the object
+ image = MiniMagick::Image.open(image_path)
+ image.quality(100)
+ image.resize("#{size}x#{size}")
+ image.write(image_path)
+ end
+end
diff --git a/lib/uploaded_file.rb b/lib/uploaded_file.rb
index 79920968603..36baf4a3cf8 100644
--- a/lib/uploaded_file.rb
+++ b/lib/uploaded_file.rb
@@ -20,8 +20,9 @@ class UploadedFile
attr_reader :remote_id
attr_reader :sha256
attr_reader :size
+ attr_reader :upload_duration
- def initialize(path, filename: nil, content_type: "application/octet-stream", sha256: nil, remote_id: nil, size: nil)
+ def initialize(path, filename: nil, content_type: "application/octet-stream", sha256: nil, remote_id: nil, size: nil, upload_duration: nil)
if path.present?
raise InvalidPathError, "#{path} file does not exist" unless ::File.exist?(path)
@@ -35,6 +36,12 @@ class UploadedFile
end
end
+ begin
+ @upload_duration = Float(upload_duration)
+ rescue ArgumentError, TypeError
+ @upload_duration = 0
+ end
+
@content_type = content_type
@original_filename = sanitize_filename(filename || path || '')
@content_type = content_type
@@ -64,8 +71,11 @@ class UploadedFile
content_type: params['type'] || 'application/octet-stream',
sha256: params['sha256'],
remote_id: remote_id,
- size: params['size']
- )
+ size: params['size'],
+ upload_duration: params['upload_duration']
+ ).tap do |uploaded_file|
+ ::Gitlab::Instrumentation::Uploads.track(uploaded_file)
+ end
end
def self.allowed_path?(file_path, paths)
diff --git a/locale/am_ET/gitlab.po b/locale/am_ET/gitlab.po
index 8314b02104d..402d584f1c9 100644
--- a/locale/am_ET/gitlab.po
+++ b/locale/am_ET/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: am\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr " ይህንን ከ %{grace_period_deadline} በáŠá‰µ ማድረጠያስáˆáˆáŒá‹Žá‰³áˆ á¡á¡"
-msgid " and"
-msgstr " እና"
-
msgid " and "
msgstr " እና "
msgid " and %{sliced}"
msgstr " እና %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " በ %d áŠáŒ¥á‰¥ ላይ á‹á‰… ተደርጓáˆ"
-msgstr[1] " በ %d áŠáŒ¥á‰¦á‰½ ላይ á‹á‰… ተደርጓáˆ"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " በ %d áŠáŒ¥á‰¥ ላይ ተሻሽáˆáˆ"
-msgstr[1] " በ %d áŠáŒ¥á‰¦á‰½ ላይ ተሻሽáˆáˆ"
-
msgid " or "
msgstr " ወይሠ"
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] "%d commit á¥"
msgstr[1] "%d commits á¥"
-msgid "%d commits"
-msgstr "%d commits"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 1007a55f046..0bffd45bf35 100644
--- a/locale/ar_SA/gitlab.po
+++ b/locale/ar_SA/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ar\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,33 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid " or "
msgstr ""
@@ -94,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -286,9 +268,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1399,6 +1378,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1486,9 +1468,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1549,6 +1537,9 @@ msgstr[5] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1891,9 +1882,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1927,7 +1915,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1954,6 +1942,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -2302,6 +2293,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -2383,9 +2377,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2464,9 +2455,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2560,6 +2548,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -3016,7 +3007,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -3031,6 +3022,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -3166,7 +3163,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3781,7 +3778,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3799,6 +3796,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3814,7 +3814,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -4054,13 +4054,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -4264,6 +4267,15 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -4327,9 +4339,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4690,12 +4699,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4708,12 +4723,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4726,6 +4750,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4741,6 +4774,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4750,6 +4786,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -5026,12 +5065,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -5275,6 +5308,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5911,6 +5947,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -6160,7 +6199,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -6271,6 +6310,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6478,9 +6520,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6769,9 +6808,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6829,6 +6865,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -7165,6 +7207,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -7198,6 +7243,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -7312,6 +7360,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -7354,15 +7405,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -8005,7 +8050,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8446,6 +8491,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8455,6 +8503,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8464,9 +8515,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8479,6 +8545,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8629,30 +8698,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8791,12 +8836,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8917,6 +8956,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8998,13 +9040,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -9013,16 +9055,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -9031,6 +9079,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -9043,31 +9097,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -9139,15 +9193,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -9292,6 +9340,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9424,10 +9475,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9628,7 +9679,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9652,9 +9703,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9775,9 +9823,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9847,9 +9892,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9934,9 +9976,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -10042,6 +10081,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -10060,6 +10102,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -10072,9 +10117,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -10090,6 +10132,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -10225,6 +10270,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -10342,7 +10390,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10465,10 +10513,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10525,6 +10570,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10579,6 +10627,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10738,6 +10795,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10813,6 +10873,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -11311,6 +11374,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -11377,6 +11443,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11416,16 +11485,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
msgstr ""
-msgid "Define approval rules."
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11500,9 +11587,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11530,9 +11614,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11560,6 +11641,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11734,13 +11818,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11749,7 +11833,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -12083,7 +12179,13 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -12187,6 +12289,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -12202,15 +12310,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -12262,6 +12367,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -12340,6 +12448,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -12385,6 +12496,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12583,12 +12697,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12685,18 +12793,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12727,9 +12823,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12955,6 +13048,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -13279,10 +13375,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -13408,7 +13501,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13463,7 +13559,13 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13564,7 +13666,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13864,6 +13966,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -14041,6 +14146,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -14341,9 +14449,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -14425,6 +14530,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -14440,6 +14548,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14467,9 +14578,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14482,6 +14590,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14566,6 +14680,15 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14800,9 +14923,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14998,6 +15118,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -15253,6 +15376,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15484,6 +15610,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15544,6 +15673,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -16120,6 +16252,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -16159,6 +16294,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -16174,9 +16312,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -16246,10 +16381,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -16297,6 +16432,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16606,6 +16744,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16774,12 +16915,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -17008,7 +17143,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -17071,9 +17206,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -17176,7 +17317,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -17305,6 +17446,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -17389,7 +17533,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17458,9 +17602,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17482,6 +17623,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17506,6 +17650,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17518,6 +17665,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -18100,6 +18250,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -18160,6 +18313,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -18214,6 +18370,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -18232,6 +18391,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18745,6 +18913,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18850,6 +19021,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18889,6 +19063,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -19072,6 +19249,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -19147,9 +19327,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -19249,6 +19426,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -19267,6 +19450,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -19282,6 +19468,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -19315,6 +19504,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19840,6 +20032,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19933,19 +20128,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -20287,6 +20482,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20545,12 +20746,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20719,6 +20926,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -21370,6 +21580,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21499,6 +21712,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21586,9 +21802,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21712,6 +21925,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21721,6 +21937,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21982,6 +22201,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -22027,6 +22249,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -22099,6 +22324,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -22255,34 +22489,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -22309,6 +22537,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -22405,9 +22639,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22543,9 +22774,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22996,6 +23224,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -23116,6 +23347,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -23182,9 +23416,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -23497,6 +23728,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23611,7 +23845,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23626,6 +23860,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23821,6 +24058,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23881,9 +24121,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -24133,18 +24370,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -24196,9 +24430,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -24400,6 +24631,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -24412,6 +24646,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -24424,6 +24664,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -24439,6 +24682,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24556,15 +24802,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24613,9 +24859,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24643,6 +24886,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24652,6 +24898,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24721,6 +24970,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24796,9 +25075,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24979,14 +25255,20 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -25030,9 +25312,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -25291,6 +25570,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -25312,6 +25594,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25819,6 +26104,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25939,6 +26227,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -26056,6 +26347,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -26158,9 +26452,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -26305,6 +26605,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26581,12 +26884,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26596,9 +26905,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26626,6 +26932,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26917,6 +27226,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -27217,6 +27529,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -27232,6 +27547,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -27415,6 +27733,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27427,6 +27748,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27604,6 +27928,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27694,6 +28021,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27775,6 +28105,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27802,6 +28135,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27817,6 +28153,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27832,54 +28171,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -28183,9 +28477,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -28201,6 +28492,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -28339,6 +28633,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -28351,6 +28648,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28537,9 +28837,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28573,6 +28870,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28660,15 +28960,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -29158,6 +29458,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -29506,6 +29809,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -29515,9 +29821,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29596,8 +29899,8 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29605,8 +29908,8 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29965,9 +30268,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29992,6 +30292,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -30001,6 +30310,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -30052,6 +30364,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -30073,6 +30388,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30112,6 +30445,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -30175,6 +30511,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -30205,15 +30544,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -30310,9 +30640,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30685,6 +31012,9 @@ msgstr[5] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30910,16 +31240,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30970,6 +31303,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30988,6 +31324,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31057,6 +31396,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -31078,9 +31420,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -31114,6 +31453,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -31123,6 +31471,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -31153,6 +31504,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -31276,6 +31630,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -31315,10 +31672,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -31336,15 +31693,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31603,9 +31954,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31705,9 +32053,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31762,9 +32107,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31855,9 +32197,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31891,10 +32230,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31960,6 +32299,15 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -32311,9 +32659,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -32380,6 +32725,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -32404,6 +32752,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -32413,6 +32764,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -32437,9 +32791,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -33034,12 +33385,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -33079,6 +33424,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -33577,7 +33925,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33676,18 +34024,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33709,9 +34051,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33724,12 +34063,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33745,30 +34078,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33796,9 +34114,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33811,9 +34126,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33856,6 +34168,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -34042,6 +34357,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -34066,6 +34384,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -34078,6 +34405,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -34471,6 +34801,9 @@ msgstr[5] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -34540,6 +34873,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -34570,9 +34906,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34645,6 +34978,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34729,6 +35065,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34834,9 +35173,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34870,9 +35206,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -35032,6 +35365,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -35116,6 +35452,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -35302,9 +35641,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -35527,7 +35863,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35830,6 +36166,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35968,6 +36310,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -36307,7 +36652,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -36343,7 +36688,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -36529,6 +36874,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36622,7 +36982,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36994,6 +37354,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -37078,6 +37441,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -37411,6 +37777,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -37429,10 +37798,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -37444,6 +37813,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -37489,9 +37861,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -37531,10 +37900,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37684,6 +38053,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37714,6 +38086,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37780,6 +38155,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -38131,6 +38512,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -38140,6 +38524,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -38185,10 +38578,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38860,6 +39265,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -39055,6 +39463,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -39064,9 +39475,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39079,6 +39487,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -39091,9 +39502,6 @@ msgstr[5] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -39400,10 +39808,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -39445,9 +39853,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -39514,6 +39919,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39670,9 +40078,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39772,9 +40177,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39862,6 +40264,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39871,9 +40276,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -40330,28 +40732,55 @@ msgstr[5] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao API token"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -40363,6 +40792,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -40375,9 +40807,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -40492,12 +40921,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -40525,6 +40960,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -40540,9 +40978,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40573,6 +41008,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -40609,9 +41047,24 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -40621,7 +41074,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40687,6 +41146,21 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40720,10 +41194,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40846,6 +41320,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40906,9 +41386,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40921,6 +41398,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40939,6 +41422,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40975,6 +41461,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -41185,6 +41674,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -41347,6 +41842,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -41380,6 +41878,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -41446,6 +41950,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -41482,9 +41989,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -41599,12 +42103,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -41620,6 +42118,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41668,6 +42169,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41743,6 +42250,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/as_IN/gitlab.po b/locale/as_IN/gitlab.po
index 56aab7f64da..1a1bf0ff4a9 100644
--- a/locale/as_IN/gitlab.po
+++ b/locale/as_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: as\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/az_AZ/gitlab.po b/locale/az_AZ/gitlab.po
index 6062ed7b4b1..2500abdbb6b 100644
--- a/locale/az_AZ/gitlab.po
+++ b/locale/az_AZ/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: az\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/ba_RU/gitlab.po b/locale/ba_RU/gitlab.po
index ffb21ba1f3f..2613419ddde 100644
--- a/locale/ba_RU/gitlab.po
+++ b/locale/ba_RU/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ba\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,23 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-
msgid " or "
msgstr ""
@@ -84,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -171,9 +163,6 @@ msgid "%d commit,"
msgid_plural "%d commits,"
msgstr[0] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -969,6 +958,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1051,9 +1043,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1104,6 +1102,9 @@ msgstr[0] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1326,9 +1327,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1362,7 +1360,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1389,6 +1387,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1737,6 +1738,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1818,9 +1822,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -1899,9 +1900,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -1995,6 +1993,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2451,7 +2452,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2466,6 +2467,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2601,7 +2608,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3216,7 +3223,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3234,6 +3241,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3249,7 +3259,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3489,13 +3499,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3699,6 +3712,10 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3762,9 +3779,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4090,12 +4104,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4108,12 +4128,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4126,6 +4155,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4141,6 +4179,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4150,6 +4191,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4421,12 +4465,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4660,6 +4698,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5291,6 +5332,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5530,7 +5574,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5641,6 +5685,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5848,9 +5895,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6134,9 +6178,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6194,6 +6235,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6520,6 +6567,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6553,6 +6603,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6667,6 +6720,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6709,15 +6765,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7360,7 +7410,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7801,6 +7851,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7810,6 +7863,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7819,9 +7875,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7834,6 +7905,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -7984,30 +8058,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8146,12 +8196,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8267,6 +8311,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8348,13 +8395,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8363,16 +8410,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8381,6 +8434,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8393,31 +8452,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8489,15 +8548,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8642,6 +8695,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8764,10 +8820,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -8963,7 +9019,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -8987,9 +9043,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9110,9 +9163,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9182,9 +9232,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9269,9 +9316,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9377,6 +9421,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9395,6 +9442,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9407,9 +9457,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9425,6 +9472,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9560,6 +9610,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9677,7 +9730,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9800,10 +9853,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9860,6 +9910,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -9914,6 +9967,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10073,6 +10135,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10138,6 +10203,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10631,6 +10699,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10697,6 +10768,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10736,16 +10810,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10820,9 +10912,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10850,9 +10939,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -10880,6 +10966,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11039,13 +11128,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11054,7 +11143,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11368,7 +11469,8 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11472,6 +11574,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11487,15 +11595,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11547,6 +11652,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11625,6 +11733,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11670,6 +11781,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11853,12 +11967,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -11950,18 +12058,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -11992,9 +12088,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12220,6 +12313,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12544,10 +12640,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12673,7 +12766,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12728,7 +12824,8 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12829,7 +12926,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13129,6 +13226,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13306,6 +13406,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13601,9 +13704,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13685,6 +13785,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13700,6 +13803,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13727,9 +13833,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13742,6 +13845,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13826,6 +13935,10 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14060,9 +14173,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14253,6 +14363,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14503,6 +14616,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14734,6 +14850,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14794,6 +14913,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15370,6 +15492,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15409,6 +15534,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15424,9 +15552,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15496,10 +15621,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15547,6 +15672,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -15856,6 +15984,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16024,12 +16155,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16258,7 +16383,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16321,9 +16446,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16426,7 +16557,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16555,6 +16686,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16639,7 +16773,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16698,9 +16832,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16722,6 +16853,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16746,6 +16880,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16758,6 +16895,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17325,6 +17465,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17385,6 +17528,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17439,6 +17585,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17457,6 +17606,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -17970,6 +18128,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18070,6 +18231,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18109,6 +18273,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18292,6 +18459,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18367,9 +18537,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18469,6 +18636,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18487,6 +18660,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18502,6 +18678,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18535,6 +18714,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19060,6 +19242,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19153,19 +19338,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19507,6 +19692,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19760,12 +19951,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -19934,6 +20131,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20550,6 +20750,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20679,6 +20882,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20766,9 +20972,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -20892,6 +21095,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -20901,6 +21107,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21162,6 +21371,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21207,6 +21419,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21279,6 +21494,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21435,34 +21659,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21489,6 +21707,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21580,9 +21804,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21718,9 +21939,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22166,6 +22384,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22281,6 +22502,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22347,9 +22571,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22657,6 +22878,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22771,7 +22995,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22786,6 +23010,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -22981,6 +23208,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23036,9 +23266,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23268,18 +23495,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23331,9 +23555,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23535,6 +23756,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23547,6 +23771,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23559,6 +23789,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23574,6 +23807,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23686,15 +23922,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23743,9 +23979,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23773,6 +24006,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23782,6 +24018,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -23851,6 +24090,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -23926,9 +24195,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24109,14 +24375,15 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24160,9 +24427,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24421,6 +24685,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24442,6 +24709,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -24949,6 +25219,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25069,6 +25342,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25186,6 +25462,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25288,9 +25567,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25435,6 +25720,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25711,12 +25999,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25726,9 +26020,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25756,6 +26047,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26047,6 +26341,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26347,6 +26644,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26362,6 +26662,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26545,6 +26848,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26557,6 +26863,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26734,6 +27043,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26824,6 +27136,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -26905,6 +27220,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26932,6 +27250,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -26947,6 +27268,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -26962,54 +27286,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27313,9 +27592,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27331,6 +27607,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27469,6 +27748,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27481,6 +27763,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27667,9 +27952,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27703,6 +27985,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27790,15 +28075,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28278,6 +28563,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28606,6 +28894,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28615,9 +28906,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28696,12 +28984,12 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgid "Requires values to meet regular expression requirements."
@@ -29045,9 +29333,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29072,6 +29357,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29081,6 +29375,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29132,6 +29429,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29153,6 +29453,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29192,6 +29510,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29255,6 +29576,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29285,15 +29609,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29390,9 +29705,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29710,6 +30022,9 @@ msgstr[0] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -29935,16 +30250,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -29995,6 +30313,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30013,6 +30334,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30082,6 +30406,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30103,9 +30430,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30139,6 +30463,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30148,6 +30481,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30178,6 +30514,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30301,6 +30640,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30340,10 +30682,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30361,15 +30703,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30628,9 +30964,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30730,9 +31063,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30787,9 +31117,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -30880,9 +31207,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -30916,10 +31240,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -30985,6 +31309,10 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31326,9 +31654,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31395,6 +31720,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31419,6 +31747,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31428,6 +31759,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31452,9 +31786,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32049,12 +32380,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32094,6 +32419,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32592,7 +32920,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32691,18 +33019,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32724,9 +33046,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32739,12 +33058,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32760,30 +33073,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -32811,9 +33109,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -32826,9 +33121,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -32871,6 +33163,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33057,6 +33352,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33081,6 +33379,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33093,6 +33400,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33461,6 +33771,9 @@ msgstr[0] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33530,6 +33843,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33560,9 +33876,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33630,6 +33943,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33714,6 +34030,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -33819,9 +34138,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -33855,9 +34171,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34017,6 +34330,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34101,6 +34417,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34287,9 +34606,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34512,7 +34828,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -34815,6 +35131,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -34953,6 +35275,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35282,7 +35607,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35318,7 +35643,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35504,6 +35829,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35597,7 +35937,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -35964,6 +36304,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36048,6 +36391,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36381,6 +36727,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36399,10 +36748,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36414,6 +36763,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36459,9 +36811,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36501,10 +36850,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36654,6 +37003,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36684,6 +37036,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36750,6 +37105,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37101,6 +37462,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37110,6 +37474,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37155,10 +37528,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -37815,6 +38200,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38010,6 +38398,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38019,9 +38410,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38034,6 +38422,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38041,9 +38432,6 @@ msgstr[0] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38350,10 +38738,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38395,9 +38783,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38464,6 +38849,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38620,9 +39008,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38722,9 +39107,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -38812,6 +39194,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -38821,9 +39206,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39275,28 +39657,55 @@ msgstr[0] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39308,6 +39717,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39320,9 +39732,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39427,12 +39836,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39460,6 +39875,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39475,9 +39893,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39508,6 +39923,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39544,9 +39962,19 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39556,7 +39984,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39622,6 +40056,16 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39655,10 +40099,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39776,6 +40220,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -39831,9 +40281,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -39846,6 +40293,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -39859,6 +40312,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -39895,6 +40351,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40090,6 +40549,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40247,6 +40712,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40280,6 +40748,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40341,6 +40815,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40372,9 +40849,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40489,12 +40963,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40510,6 +40978,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40558,6 +41029,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40633,6 +41110,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index 18dfcc1b501..f35090abf69 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bg\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Ðктивно"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Сравнение"
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Създаване на нова папка"
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,18 +10945,36 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "Задайте потребителÑки шаблон, използвайки ÑинтакÑиÑа на „Cron“"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr "Задайте потребителÑки шаблон, използвайки ÑинтакÑиÑа на „Cron“"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "ПоÑледна Ñхема"
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr "Ðов етикет"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr "Опции"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr "СобÑтвеник"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "ЗаÑвка за доÑтъп"
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr "Задайте парола на акаунта Ñи, за да може
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "зададете парола"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index 0fb483b3596..8c71e5e67a9 100644
--- a/locale/bn_BD/gitlab.po
+++ b/locale/bn_BD/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:18\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index ebdb5e26e68..2d7d353a038 100644
--- a/locale/bn_IN/gitlab.po
+++ b/locale/bn_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bn-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/br_FR/gitlab.po b/locale/br_FR/gitlab.po
index d4a66813efa..4ee94da0b8e 100644
--- a/locale/br_FR/gitlab.po
+++ b/locale/br_FR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: br-FR\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,31 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-
msgid " or "
msgstr ""
@@ -92,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -263,9 +247,6 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1313,6 +1294,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1399,9 +1383,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1460,6 +1450,9 @@ msgstr[4] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1778,9 +1771,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1814,7 +1804,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1841,6 +1831,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -2189,6 +2182,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -2270,9 +2266,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2351,9 +2344,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2447,6 +2437,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2903,7 +2896,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2918,6 +2911,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -3053,7 +3052,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3668,7 +3667,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3686,6 +3685,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3701,7 +3703,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3941,13 +3943,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -4151,6 +4156,14 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -4214,9 +4227,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4570,12 +4580,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4588,12 +4604,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4606,6 +4631,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4621,6 +4655,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4630,6 +4667,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4905,12 +4945,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -5152,6 +5186,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5787,6 +5824,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -6034,7 +6074,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -6145,6 +6185,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6352,9 +6395,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6642,9 +6682,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6702,6 +6739,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -7036,6 +7079,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -7069,6 +7115,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -7183,6 +7232,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -7225,15 +7277,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7876,7 +7922,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8317,6 +8363,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8326,6 +8375,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8335,9 +8387,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8350,6 +8417,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8500,30 +8570,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8662,12 +8708,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8787,6 +8827,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8868,13 +8911,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8883,16 +8926,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8901,6 +8950,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8913,31 +8968,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -9009,15 +9064,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -9162,6 +9211,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9292,10 +9344,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9495,7 +9547,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9519,9 +9571,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9642,9 +9691,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9714,9 +9760,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9801,9 +9844,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9909,6 +9949,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9927,6 +9970,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9939,9 +9985,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9957,6 +10000,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -10092,6 +10138,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -10209,7 +10258,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10332,10 +10381,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10392,6 +10438,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10446,6 +10495,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10605,6 +10663,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10678,6 +10739,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -11175,6 +11239,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -11241,6 +11308,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11280,16 +11350,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11364,9 +11452,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11394,9 +11479,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11424,6 +11506,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11595,13 +11680,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11610,7 +11695,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11940,7 +12037,12 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -12044,6 +12146,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -12059,15 +12167,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -12119,6 +12224,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -12197,6 +12305,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -12242,6 +12353,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12437,12 +12551,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12538,18 +12646,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12580,9 +12676,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12808,6 +12901,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -13132,10 +13228,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -13261,7 +13354,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13316,7 +13412,12 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13417,7 +13518,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13717,6 +13818,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13894,6 +13998,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -14193,9 +14300,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -14277,6 +14381,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -14292,6 +14399,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14319,9 +14429,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14334,6 +14441,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14418,6 +14531,14 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14652,9 +14773,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14849,6 +14967,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -15103,6 +15224,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15334,6 +15458,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15394,6 +15521,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15970,6 +16100,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -16009,6 +16142,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -16024,9 +16160,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -16096,10 +16229,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -16147,6 +16280,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16456,6 +16592,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16624,12 +16763,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16858,7 +16991,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16921,9 +17054,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -17026,7 +17165,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -17155,6 +17294,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -17239,7 +17381,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17306,9 +17448,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17330,6 +17469,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17354,6 +17496,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17366,6 +17511,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17945,6 +18093,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -18005,6 +18156,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -18059,6 +18213,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -18077,6 +18234,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18590,6 +18756,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18694,6 +18863,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18733,6 +18905,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18916,6 +19091,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18991,9 +19169,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -19093,6 +19268,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -19111,6 +19292,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -19126,6 +19310,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -19159,6 +19346,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19684,6 +19874,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19777,19 +19970,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -20131,6 +20324,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20388,12 +20587,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20562,6 +20767,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -21206,6 +21414,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21335,6 +21546,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21422,9 +21636,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21548,6 +21759,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21557,6 +21771,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21818,6 +22035,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21863,6 +22083,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21935,6 +22158,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -22091,34 +22323,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -22145,6 +22371,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -22240,9 +22472,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22378,9 +22607,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22830,6 +23056,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22949,6 +23178,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -23015,9 +23247,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -23329,6 +23558,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23443,7 +23675,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23458,6 +23690,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23653,6 +23888,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23712,9 +23950,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23960,18 +24195,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -24023,9 +24255,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -24227,6 +24456,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -24239,6 +24471,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -24251,6 +24489,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -24266,6 +24507,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24382,15 +24626,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24439,9 +24683,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24469,6 +24710,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24478,6 +24722,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24547,6 +24794,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24622,9 +24899,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24805,14 +25079,19 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24856,9 +25135,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -25117,6 +25393,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -25138,6 +25417,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25645,6 +25927,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25765,6 +26050,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25882,6 +26170,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25984,9 +26275,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -26131,6 +26428,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26407,12 +26707,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26422,9 +26728,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26452,6 +26755,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26743,6 +27049,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -27043,6 +27352,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -27058,6 +27370,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -27241,6 +27556,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27253,6 +27571,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27430,6 +27751,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27520,6 +27844,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27601,6 +27928,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27628,6 +27958,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27643,6 +27976,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27658,54 +27994,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -28009,9 +28300,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -28027,6 +28315,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -28165,6 +28456,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -28177,6 +28471,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28363,9 +28660,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28399,6 +28693,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28486,15 +28783,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28982,6 +29279,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -29326,6 +29626,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -29335,9 +29638,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29416,16 +29716,16 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29781,9 +30081,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29808,6 +30105,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29817,6 +30123,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29868,6 +30177,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29889,6 +30201,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29928,6 +30258,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29991,6 +30324,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -30021,15 +30357,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -30126,9 +30453,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30490,6 +30814,9 @@ msgstr[4] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30715,16 +31042,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30775,6 +31105,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30793,6 +31126,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30862,6 +31198,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30883,9 +31222,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30919,6 +31255,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30928,6 +31273,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30958,6 +31306,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -31081,6 +31432,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -31120,10 +31474,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -31141,15 +31495,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31408,9 +31756,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31510,9 +31855,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31567,9 +31909,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31660,9 +31999,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31696,10 +32032,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31765,6 +32101,14 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -32114,9 +32458,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -32183,6 +32524,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -32207,6 +32551,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -32216,6 +32563,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -32240,9 +32590,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32837,12 +33184,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32882,6 +33223,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -33380,7 +33724,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33479,18 +33823,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33512,9 +33850,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33527,12 +33862,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33548,30 +33877,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33599,9 +33913,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33614,9 +33925,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33659,6 +33967,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33845,6 +34156,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33869,6 +34183,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33881,6 +34204,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -34269,6 +34595,9 @@ msgstr[4] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -34338,6 +34667,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -34368,9 +34700,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34442,6 +34771,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34526,6 +34858,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34631,9 +34966,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34667,9 +34999,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34829,6 +35158,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34913,6 +35245,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -35099,9 +35434,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -35324,7 +35656,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35627,6 +35959,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35765,6 +36103,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -36102,7 +36443,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -36138,7 +36479,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -36324,6 +36665,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36417,7 +36773,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36788,6 +37144,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36872,6 +37231,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -37205,6 +37567,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -37223,10 +37588,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -37238,6 +37603,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -37283,9 +37651,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -37325,10 +37690,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37478,6 +37843,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37508,6 +37876,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37574,6 +37945,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37925,6 +38302,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37934,6 +38314,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37979,10 +38368,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38651,6 +39052,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38846,6 +39250,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38855,9 +39262,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38870,6 +39274,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38881,9 +39288,6 @@ msgstr[4] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -39190,10 +39594,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -39235,9 +39639,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -39304,6 +39705,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39460,9 +39864,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39562,9 +39963,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39652,6 +40050,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39661,9 +40062,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -40119,28 +40517,55 @@ msgstr[4] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao API token"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -40152,6 +40577,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -40164,9 +40592,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -40279,12 +40704,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -40312,6 +40743,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -40327,9 +40761,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40360,6 +40791,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -40396,9 +40830,23 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -40408,7 +40856,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40474,6 +40928,20 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40507,10 +40975,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40632,6 +41100,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40691,9 +41165,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40706,6 +41177,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40723,6 +41200,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40759,6 +41239,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40966,6 +41449,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -41127,6 +41616,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -41160,6 +41652,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -41225,6 +41723,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -41260,9 +41761,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -41377,12 +41875,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -41398,6 +41890,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41446,6 +41941,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41521,6 +42022,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/bs_BA/gitlab.po b/locale/bs_BA/gitlab.po
index 5082627699d..344727ff128 100644
--- a/locale/bs_BA/gitlab.po
+++ b/locale/bs_BA/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,27 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr " i"
-
msgid " and "
msgstr " i "
msgid " and %{sliced}"
msgstr " i %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid " or "
msgstr " ili "
@@ -88,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -217,9 +205,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1141,6 +1126,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1225,9 +1213,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1282,6 +1276,9 @@ msgstr[2] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1552,9 +1549,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1588,7 +1582,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1615,6 +1609,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1963,6 +1960,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -2044,9 +2044,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2125,9 +2122,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2221,6 +2215,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2677,7 +2674,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2692,6 +2689,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2827,7 +2830,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3442,7 +3445,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3460,6 +3463,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3475,7 +3481,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3715,13 +3721,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3925,6 +3934,12 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3988,9 +4003,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4330,12 +4342,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4348,12 +4366,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4366,6 +4393,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4381,6 +4417,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4390,6 +4429,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4663,12 +4705,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4906,6 +4942,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5539,6 +5578,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5782,7 +5824,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5893,6 +5935,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6100,9 +6145,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6388,9 +6430,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6448,6 +6487,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6778,6 +6823,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6811,6 +6859,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6925,6 +6976,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6967,15 +7021,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7618,7 +7666,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8059,6 +8107,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8068,6 +8119,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8077,9 +8131,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8092,6 +8161,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8242,30 +8314,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8404,12 +8452,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8527,6 +8569,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8608,13 +8653,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8623,16 +8668,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8641,6 +8692,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8653,31 +8710,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8749,15 +8806,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8902,6 +8953,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9028,10 +9082,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9229,7 +9283,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9253,9 +9307,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9376,9 +9427,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9448,9 +9496,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9535,9 +9580,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9643,6 +9685,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9661,6 +9706,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9673,9 +9721,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9691,6 +9736,9 @@ msgstr ""
msgid "Create a new issue"
msgstr "Kreiraj novi zadatak"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9826,6 +9874,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9943,7 +9994,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10066,10 +10117,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10126,6 +10174,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10180,6 +10231,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10339,6 +10399,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10408,6 +10471,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10903,6 +10969,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10969,6 +11038,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11008,16 +11080,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11092,9 +11182,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11122,9 +11209,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11152,6 +11236,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11317,13 +11404,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11332,7 +11419,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11654,7 +11753,10 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11758,6 +11860,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11773,15 +11881,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11833,6 +11938,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11911,6 +12019,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11956,6 +12067,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12145,12 +12259,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12244,18 +12352,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12286,9 +12382,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12514,6 +12607,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12838,10 +12934,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12967,7 +13060,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13022,7 +13118,10 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13123,7 +13222,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13423,6 +13522,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13600,6 +13702,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13897,9 +14002,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13981,6 +14083,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13996,6 +14101,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14023,9 +14131,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14038,6 +14143,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14122,6 +14233,12 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14356,9 +14473,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14551,6 +14665,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14803,6 +14920,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15034,6 +15154,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15094,6 +15217,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15670,6 +15796,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15709,6 +15838,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15724,9 +15856,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15796,10 +15925,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15847,6 +15976,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16156,6 +16288,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16324,12 +16459,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16558,7 +16687,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16621,9 +16750,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16726,7 +16861,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16855,6 +16990,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16939,7 +17077,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17002,9 +17140,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17026,6 +17161,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17050,6 +17188,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17062,6 +17203,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17635,6 +17779,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17695,6 +17842,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17749,6 +17899,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17767,6 +17920,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18280,6 +18442,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18382,6 +18547,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18421,6 +18589,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18604,6 +18775,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18679,9 +18853,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18781,6 +18952,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18799,6 +18976,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18814,6 +18994,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18847,6 +19030,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19372,6 +19558,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19465,19 +19654,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19819,6 +20008,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20074,12 +20269,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20248,6 +20449,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20878,6 +21082,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr "OznaÄava ovaj zadatak kao povjerljiv."
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21007,6 +21214,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21094,9 +21304,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21220,6 +21427,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21229,6 +21439,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21490,6 +21703,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21535,6 +21751,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21607,6 +21826,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21763,34 +21991,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21817,6 +22039,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21910,9 +22138,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22048,9 +22273,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22498,6 +22720,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22615,6 +22840,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22681,9 +22909,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22993,6 +23218,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23107,7 +23335,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23122,6 +23350,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23317,6 +23548,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23374,9 +23608,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23614,18 +23845,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23677,9 +23905,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23881,6 +24106,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23893,6 +24121,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23905,6 +24139,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23920,6 +24157,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24034,15 +24274,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24091,9 +24331,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24121,6 +24358,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24130,6 +24370,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24199,6 +24442,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24274,9 +24547,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24457,14 +24727,17 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24508,9 +24781,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24769,6 +25039,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24790,6 +25063,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25297,6 +25573,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25417,6 +25696,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25534,6 +25816,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25636,9 +25921,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25783,6 +26074,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26059,12 +26353,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26074,9 +26374,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26104,6 +26401,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26395,6 +26695,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26695,6 +26998,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26710,6 +27016,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26893,6 +27202,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26905,6 +27217,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27082,6 +27397,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27172,6 +27490,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27253,6 +27574,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27280,6 +27604,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27295,6 +27622,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27310,54 +27640,9 @@ msgstr ""
msgid "Prometheus"
msgstr "Prometheus"
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27661,9 +27946,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27679,6 +27961,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27817,6 +28102,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27829,6 +28117,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28015,9 +28306,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28051,6 +28339,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28138,15 +28429,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28630,6 +28921,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28966,6 +29260,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28975,9 +29272,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29056,14 +29350,14 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29413,9 +29707,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29440,6 +29731,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29449,6 +29749,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29500,6 +29803,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29521,6 +29827,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29560,6 +29884,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29623,6 +29950,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29653,15 +29983,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29758,9 +30079,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30100,6 +30418,9 @@ msgstr[2] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30325,16 +30646,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30385,6 +30709,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30403,6 +30730,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30472,6 +30802,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30493,9 +30826,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30529,6 +30859,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30538,6 +30877,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30568,6 +30910,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30691,6 +31036,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30730,10 +31078,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30751,15 +31099,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31018,9 +31360,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31120,9 +31459,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31177,9 +31513,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31270,9 +31603,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31306,10 +31636,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31375,6 +31705,12 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31720,9 +32056,6 @@ msgstr "SliÄni zadaci"
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31789,6 +32122,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31813,6 +32149,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31822,6 +32161,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31846,9 +32188,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32443,12 +32782,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32488,6 +32821,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32986,7 +33322,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33085,18 +33421,12 @@ msgstr ""
msgid "Sunday"
msgstr "Nedjelja"
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33118,9 +33448,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33133,12 +33460,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33154,30 +33475,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33205,9 +33511,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33220,9 +33523,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33265,6 +33565,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33451,6 +33754,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33475,6 +33781,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33487,6 +33802,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33865,6 +34183,9 @@ msgstr[2] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33934,6 +34255,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33964,9 +34288,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34036,6 +34357,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34120,6 +34444,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34225,9 +34552,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34261,9 +34585,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34423,6 +34744,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34507,6 +34831,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34693,9 +35020,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34918,7 +35242,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35221,6 +35545,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35359,6 +35689,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35692,7 +36025,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35728,7 +36061,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35914,6 +36247,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36007,7 +36355,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36376,6 +36724,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36460,6 +36811,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36793,6 +37147,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36811,10 +37168,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36826,6 +37183,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36871,9 +37231,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36913,10 +37270,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37066,6 +37423,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37096,6 +37456,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37162,6 +37525,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37513,6 +37882,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37522,6 +37894,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37567,10 +37948,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38233,6 +38626,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38428,6 +38824,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38437,9 +38836,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38452,6 +38848,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38461,9 +38860,6 @@ msgstr[2] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38770,10 +39166,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38815,9 +39211,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38884,6 +39277,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39040,9 +39436,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39142,9 +39535,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39232,6 +39622,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39241,9 +39634,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39697,28 +40087,55 @@ msgstr[2] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39730,6 +40147,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39742,9 +40162,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39853,12 +40270,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39886,6 +40309,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39901,9 +40327,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39934,6 +40357,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39970,9 +40396,21 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39982,7 +40420,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40048,6 +40492,18 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40081,10 +40537,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40204,6 +40660,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40261,9 +40723,6 @@ msgstr "postavi"
msgid "design"
msgstr "dizajn"
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40276,6 +40735,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40291,6 +40756,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40327,6 +40795,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40528,6 +40999,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40687,6 +41164,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40720,6 +41200,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40783,6 +41269,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40816,9 +41305,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40933,12 +41419,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40954,6 +41434,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41002,6 +41485,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41077,6 +41566,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index e5283111839..c18db984108 100644
--- a/locale/ca_ES/gitlab.po
+++ b/locale/ca_ES/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ca\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr " Des de %{start} fins %{end}"
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Cal que ho feu abans de %{grace_period_deadline}."
-msgid " and"
-msgstr " i"
-
msgid " and "
msgstr " i "
msgid " and %{sliced}"
msgstr " i %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " degradat en %d punts"
-msgstr[1] " degradat en %d punts"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " millorat en %d punt"
-msgstr[1] " millorat en %d punts"
-
msgid " or "
msgstr " o "
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Actiu"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr "Afegeix a l'arbre"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr "agost"
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr "Totes"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr "Trieu una plantilla..."
msgid "Choose a type..."
msgstr "Trieu un tipus..."
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr "Trieu un color."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Compara"
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "Registre de contenidors"
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr "Selector de data"
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
msgstr ""
-msgid "Define approval rules."
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr "Domini"
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr "Historial"
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr "Xarxa"
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index aaf21b8a80a..71a54d483cf 100644
--- a/locale/cs_CZ/gitlab.po
+++ b/locale/cs_CZ/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: cs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,29 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr " a"
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid " or "
msgstr ""
@@ -90,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -240,9 +226,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1227,6 +1210,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1312,9 +1298,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1371,6 +1363,9 @@ msgstr[3] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1665,9 +1660,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1701,7 +1693,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1728,6 +1720,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -2076,6 +2071,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -2157,9 +2155,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2238,9 +2233,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2334,6 +2326,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2790,7 +2785,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2805,6 +2800,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2940,7 +2941,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3555,7 +3556,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3573,6 +3574,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3588,7 +3592,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3828,13 +3832,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -4038,6 +4045,13 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -4101,9 +4115,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4450,12 +4461,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4468,12 +4485,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4486,6 +4512,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4501,6 +4536,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4510,6 +4548,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4784,12 +4825,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -5029,6 +5064,9 @@ msgstr "Srpen"
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5663,6 +5701,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5908,7 +5949,7 @@ msgstr "VÅ¡echny"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -6019,6 +6060,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6226,9 +6270,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6515,9 +6556,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6575,6 +6613,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6907,6 +6951,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6940,6 +6987,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -7054,6 +7104,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -7096,15 +7149,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7747,7 +7794,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8188,6 +8235,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8197,6 +8247,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8206,9 +8259,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8221,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8371,30 +8442,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8533,12 +8580,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8657,6 +8698,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8738,13 +8782,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8753,16 +8797,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8771,6 +8821,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8783,31 +8839,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8879,15 +8935,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -9032,6 +9082,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9160,10 +9213,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9362,7 +9415,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9386,9 +9439,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9509,9 +9559,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9581,9 +9628,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9668,9 +9712,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9776,6 +9817,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9794,6 +9838,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9806,9 +9853,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9824,6 +9868,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9959,6 +10006,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -10076,7 +10126,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10199,10 +10249,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10259,6 +10306,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10313,6 +10363,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10472,6 +10531,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10543,6 +10605,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -11039,6 +11104,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -11105,6 +11173,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11144,16 +11215,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11228,9 +11317,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11258,9 +11344,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11288,6 +11371,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11456,13 +11542,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11471,7 +11557,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11797,7 +11895,11 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11901,6 +12003,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11916,15 +12024,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11976,6 +12081,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -12054,6 +12162,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -12099,6 +12210,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12291,12 +12405,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12391,18 +12499,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12433,9 +12529,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12661,6 +12754,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12985,10 +13081,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -13114,7 +13207,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13169,7 +13265,11 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13270,7 +13370,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13570,6 +13670,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13747,6 +13850,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -14045,9 +14151,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -14129,6 +14232,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -14144,6 +14250,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14171,9 +14280,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14186,6 +14292,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14270,6 +14382,13 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14504,9 +14623,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14700,6 +14816,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14953,6 +15072,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15184,6 +15306,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15244,6 +15369,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15820,6 +15948,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15859,6 +15990,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15874,9 +16008,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15946,10 +16077,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15997,6 +16128,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16306,6 +16440,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16474,12 +16611,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16708,7 +16839,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16771,9 +16902,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16876,7 +17013,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -17005,6 +17142,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -17089,7 +17229,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17154,9 +17294,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17178,6 +17315,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17202,6 +17342,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17214,6 +17357,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17790,6 +17936,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17850,6 +17999,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17904,6 +18056,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17922,6 +18077,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18435,6 +18599,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18538,6 +18705,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18577,6 +18747,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18760,6 +18933,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18835,9 +19011,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18937,6 +19110,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18955,6 +19134,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18970,6 +19152,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -19003,6 +19188,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19528,6 +19716,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19621,19 +19812,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19975,6 +20166,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20231,12 +20428,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20405,6 +20608,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -21042,6 +21248,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21171,6 +21380,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21258,9 +21470,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21384,6 +21593,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21393,6 +21605,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21654,6 +21869,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21699,6 +21917,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21771,6 +21992,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21927,34 +22157,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21981,6 +22205,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -22075,9 +22305,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22213,9 +22440,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22664,6 +22888,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22782,6 +23009,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22848,9 +23078,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -23161,6 +23388,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23275,7 +23505,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23290,6 +23520,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23485,6 +23718,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23543,9 +23779,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23787,18 +24020,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23850,9 +24080,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -24054,6 +24281,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -24066,6 +24296,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -24078,6 +24314,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -24093,6 +24332,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24208,15 +24450,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24265,9 +24507,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24295,6 +24534,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24304,6 +24546,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24373,6 +24618,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24448,9 +24723,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24631,14 +24903,18 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24682,9 +24958,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24943,6 +25216,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24964,6 +25240,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25471,6 +25750,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25591,6 +25873,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25708,6 +25993,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25810,9 +26098,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25957,6 +26251,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26233,12 +26530,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26248,9 +26551,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26278,6 +26578,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26569,6 +26872,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26869,6 +27175,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26884,6 +27193,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -27067,6 +27379,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27079,6 +27394,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27256,6 +27574,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27346,6 +27667,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27427,6 +27751,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27454,6 +27781,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27469,6 +27799,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27484,54 +27817,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27835,9 +28123,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27853,6 +28138,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27991,6 +28279,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -28003,6 +28294,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28189,9 +28483,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28225,6 +28516,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28312,15 +28606,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28806,6 +29100,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -29146,6 +29443,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -29155,9 +29455,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29236,15 +29533,15 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29597,9 +29894,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29624,6 +29918,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29633,6 +29936,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29684,6 +29990,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29705,6 +30014,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29744,6 +30071,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29807,6 +30137,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29837,15 +30170,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29942,9 +30266,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30295,6 +30616,9 @@ msgstr[3] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30520,16 +30844,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30580,6 +30907,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30598,6 +30928,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30667,6 +31000,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30688,9 +31024,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30724,6 +31057,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30733,6 +31075,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30763,6 +31108,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30886,6 +31234,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30925,10 +31276,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30946,15 +31297,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31213,9 +31558,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31315,9 +31657,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31372,9 +31711,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31465,9 +31801,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31501,10 +31834,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31570,6 +31903,13 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31917,9 +32257,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31986,6 +32323,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -32010,6 +32350,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -32019,6 +32362,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -32043,9 +32389,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32640,12 +32983,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32685,6 +33022,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -33183,7 +33523,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33282,18 +33622,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33315,9 +33649,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33330,12 +33661,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33351,30 +33676,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33402,9 +33712,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33417,9 +33724,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33462,6 +33766,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33648,6 +33955,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33672,6 +33982,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33684,6 +34003,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -34067,6 +34389,9 @@ msgstr[3] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -34136,6 +34461,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -34166,9 +34494,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34239,6 +34564,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34323,6 +34651,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34428,9 +34759,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34464,9 +34792,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34626,6 +34951,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34710,6 +35038,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34896,9 +35227,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -35121,7 +35449,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35424,6 +35752,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35562,6 +35896,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35897,7 +36234,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35933,7 +36270,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -36119,6 +36456,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36212,7 +36564,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36582,6 +36934,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36666,6 +37021,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36999,6 +37357,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -37017,10 +37378,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -37032,6 +37393,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -37077,9 +37441,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -37119,10 +37480,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37272,6 +37633,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37302,6 +37666,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37368,6 +37735,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37719,6 +38092,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37728,6 +38104,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37773,10 +38158,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38442,6 +38839,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38637,6 +39037,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38646,9 +39049,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38661,6 +39061,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38671,9 +39074,6 @@ msgstr[3] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38980,10 +39380,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -39025,9 +39425,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -39094,6 +39491,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39250,9 +39650,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39352,9 +39749,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39442,6 +39836,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39451,9 +39848,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39908,28 +40302,55 @@ msgstr[3] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39941,6 +40362,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39953,9 +40377,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -40066,12 +40487,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -40099,6 +40526,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -40114,9 +40544,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40147,6 +40574,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -40183,9 +40613,22 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -40195,7 +40638,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40261,6 +40710,19 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40294,10 +40756,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40418,6 +40880,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40476,9 +40944,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40491,6 +40956,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40507,6 +40978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40543,6 +41017,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40747,6 +41224,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40907,6 +41390,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40940,6 +41426,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -41004,6 +41496,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -41038,9 +41533,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -41155,12 +41647,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -41176,6 +41662,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41224,6 +41713,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41299,6 +41794,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index 8f874ae1255..584689472f0 100644
--- a/locale/cy_GB/gitlab.po
+++ b/locale/cy_GB/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: cy\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:18\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr " %{start} i %{end}"
@@ -40,33 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Mae angen i chi wneud hyn cyn %{grace_period_deadline}."
-msgid " and"
-msgstr " a"
-
msgid " and "
msgstr " a "
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " wedi'i wella ar %d pwyntiau"
-msgstr[1] " wedi'i wella ar %d pwynt"
-msgstr[2] " wedi'i wella ar %d bwynt"
-msgstr[3] " wedi'i wella ar %d pwynt"
-msgstr[4] " wedi'i wella ar %d phwynt"
-msgstr[5] " wedi'i wella ar %d pwynt"
-
msgid " or "
msgstr " neu "
@@ -94,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -286,9 +268,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1399,6 +1378,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1486,9 +1468,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1549,6 +1537,9 @@ msgstr[5] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1891,9 +1882,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1927,7 +1915,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1954,6 +1942,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -2302,6 +2293,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -2383,9 +2377,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2464,9 +2455,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2560,6 +2548,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -3016,7 +3007,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -3031,6 +3022,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -3166,7 +3163,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3781,7 +3778,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3799,6 +3796,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3814,7 +3814,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -4054,13 +4054,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -4264,6 +4267,15 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -4327,9 +4339,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4690,12 +4699,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4708,12 +4723,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4726,6 +4750,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4741,6 +4774,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4750,6 +4786,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -5026,12 +5065,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -5275,6 +5308,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5911,6 +5947,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -6160,7 +6199,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -6271,6 +6310,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6478,9 +6520,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6769,9 +6808,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6829,6 +6865,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -7165,6 +7207,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -7198,6 +7243,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -7312,6 +7360,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -7354,15 +7405,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -8005,7 +8050,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8446,6 +8491,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8455,6 +8503,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8464,9 +8515,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8479,6 +8545,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8629,30 +8698,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8791,12 +8836,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8917,6 +8956,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8998,13 +9040,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -9013,16 +9055,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -9031,6 +9079,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -9043,31 +9097,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -9139,15 +9193,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -9292,6 +9340,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9424,10 +9475,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9628,7 +9679,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9652,9 +9703,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9775,9 +9823,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9847,9 +9892,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9934,9 +9976,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -10042,6 +10081,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -10060,6 +10102,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -10072,9 +10117,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -10090,6 +10132,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -10225,6 +10270,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -10342,7 +10390,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10465,10 +10513,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10525,6 +10570,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10579,6 +10627,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10738,6 +10795,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10813,6 +10873,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -11311,6 +11374,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -11377,6 +11443,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11416,16 +11485,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Fully protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11500,9 +11587,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11530,9 +11614,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11560,6 +11641,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11734,13 +11818,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11749,7 +11833,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -12083,7 +12179,13 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -12187,6 +12289,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -12202,15 +12310,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -12262,6 +12367,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -12340,6 +12448,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -12385,6 +12496,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12583,12 +12697,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12685,18 +12793,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12727,9 +12823,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12955,6 +13048,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -13279,10 +13375,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -13408,7 +13501,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13463,7 +13559,13 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13564,7 +13666,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13864,6 +13966,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -14041,6 +14146,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -14341,9 +14449,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -14425,6 +14530,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -14440,6 +14548,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14467,9 +14578,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14482,6 +14590,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14566,6 +14680,15 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14800,9 +14923,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14998,6 +15118,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -15253,6 +15376,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15484,6 +15610,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15544,6 +15673,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -16120,6 +16252,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -16159,6 +16294,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -16174,9 +16312,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -16246,10 +16381,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -16297,6 +16432,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16606,6 +16744,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16774,12 +16915,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -17008,7 +17143,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -17071,9 +17206,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -17176,7 +17317,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -17305,6 +17446,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -17389,7 +17533,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17458,9 +17602,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17482,6 +17623,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17506,6 +17650,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17518,6 +17665,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -18100,6 +18250,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -18160,6 +18313,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -18214,6 +18370,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -18232,6 +18391,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18745,6 +18913,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18850,6 +19021,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18889,6 +19063,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -19072,6 +19249,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -19147,9 +19327,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -19249,6 +19426,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -19267,6 +19450,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -19282,6 +19468,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -19315,6 +19504,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19840,6 +20032,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19933,19 +20128,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -20287,6 +20482,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20545,12 +20746,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20719,6 +20926,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -21370,6 +21580,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21499,6 +21712,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21586,9 +21802,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21712,6 +21925,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21721,6 +21937,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21982,6 +22201,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -22027,6 +22249,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -22099,6 +22324,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -22255,34 +22489,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -22309,6 +22537,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -22405,9 +22639,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22543,9 +22774,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22996,6 +23224,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -23116,6 +23347,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -23182,9 +23416,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -23497,6 +23728,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23611,7 +23845,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23626,6 +23860,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23821,6 +24058,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23881,9 +24121,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -24133,18 +24370,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -24196,9 +24430,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -24400,6 +24631,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -24412,6 +24646,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -24424,6 +24664,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -24439,6 +24682,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24556,15 +24802,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24613,9 +24859,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24643,6 +24886,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24652,6 +24898,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24721,6 +24970,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24796,9 +25075,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24979,14 +25255,20 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -25030,9 +25312,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -25291,6 +25570,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -25312,6 +25594,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25819,6 +26104,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25939,6 +26227,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -26056,6 +26347,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -26158,9 +26452,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -26305,6 +26605,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26581,12 +26884,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26596,9 +26905,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26626,6 +26932,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26917,6 +27226,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -27217,6 +27529,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -27232,6 +27547,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -27415,6 +27733,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27427,6 +27748,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27604,6 +27928,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27694,6 +28021,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27775,6 +28105,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27802,6 +28135,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27817,6 +28153,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27832,54 +28171,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -28183,9 +28477,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -28201,6 +28492,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -28339,6 +28633,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -28351,6 +28648,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28537,9 +28837,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28573,6 +28870,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28660,15 +28960,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -29158,6 +29458,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -29506,6 +29809,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -29515,9 +29821,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29596,8 +29899,8 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29605,8 +29908,8 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29965,9 +30268,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29992,6 +30292,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -30001,6 +30310,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -30052,6 +30364,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -30073,6 +30388,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -30112,6 +30445,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -30175,6 +30511,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -30205,15 +30544,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -30310,9 +30640,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30685,6 +31012,9 @@ msgstr[5] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30910,16 +31240,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30970,6 +31303,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30988,6 +31324,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -31057,6 +31396,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -31078,9 +31420,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -31114,6 +31453,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -31123,6 +31471,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -31153,6 +31504,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -31276,6 +31630,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -31315,10 +31672,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -31336,15 +31693,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31603,9 +31954,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31705,9 +32053,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31762,9 +32107,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31855,9 +32197,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31891,10 +32230,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31960,6 +32299,15 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -32311,9 +32659,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -32380,6 +32725,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -32404,6 +32752,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -32413,6 +32764,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -32437,9 +32791,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -33034,12 +33385,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -33079,6 +33424,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -33577,7 +33925,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33676,18 +34024,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33709,9 +34051,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33724,12 +34063,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33745,30 +34078,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33796,9 +34114,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33811,9 +34126,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33856,6 +34168,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -34042,6 +34357,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -34066,6 +34384,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -34078,6 +34405,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -34471,6 +34801,9 @@ msgstr[5] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -34540,6 +34873,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -34570,9 +34906,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34645,6 +34978,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34729,6 +35065,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34834,9 +35173,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34870,9 +35206,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -35032,6 +35365,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -35116,6 +35452,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -35302,9 +35641,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -35527,7 +35863,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35830,6 +36166,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35968,6 +36310,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -36307,7 +36652,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -36343,7 +36688,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -36529,6 +36874,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36622,7 +36982,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36994,6 +37354,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -37078,6 +37441,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -37411,6 +37777,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -37429,10 +37798,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -37444,6 +37813,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -37489,9 +37861,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -37531,10 +37900,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37684,6 +38053,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37714,6 +38086,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37780,6 +38155,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -38131,6 +38512,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -38140,6 +38524,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -38185,10 +38578,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38860,6 +39265,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -39055,6 +39463,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -39064,9 +39475,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39079,6 +39487,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -39091,9 +39502,6 @@ msgstr[5] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -39400,10 +39808,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -39445,9 +39853,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -39514,6 +39919,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39670,9 +40078,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39772,9 +40177,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39862,6 +40264,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39871,9 +40276,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -40330,28 +40732,55 @@ msgstr[5] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -40363,6 +40792,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -40375,9 +40807,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -40492,12 +40921,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -40525,6 +40960,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -40540,9 +40978,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40573,6 +41008,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -40609,9 +41047,24 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -40621,7 +41074,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40687,6 +41146,21 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40720,10 +41194,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40846,6 +41320,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40906,9 +41386,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40921,6 +41398,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40939,6 +41422,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40975,6 +41461,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -41185,6 +41674,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -41347,6 +41842,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -41380,6 +41878,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -41446,6 +41950,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -41482,9 +41989,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -41599,12 +42103,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -41620,6 +42118,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41668,6 +42169,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41743,6 +42250,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index 3c39d640884..9c4eafc6597 100644
--- a/locale/da_DK/gitlab.po
+++ b/locale/da_DK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr " %{start} til %{end}"
@@ -40,25 +40,12 @@ msgstr " Type"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Du skal gøre det inden %{grace_period_deadline}."
-msgid " and"
-msgstr " og"
-
msgid " and "
msgstr " og "
msgid " and %{sliced}"
msgstr " og %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " forringet på %d punkt"
-msgstr[1] " forringet på %d punkter"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " forbedret på %d punkt"
-msgstr[1] " forbedret på %d punkter"
-
msgid " or "
msgstr " eller "
@@ -86,18 +73,21 @@ msgstr "Størrelsen på \"%{repository_name}\" (%{repository_size}) er større e
msgid "\"el\" parameter is required for createInstance()"
msgstr "Parameteren \"el\" kræves til createInstance()"
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr "#generelt, #udvikling"
msgid "%d Alert"
msgid_plural "%d Alerts"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d alertbesked"
+msgstr[1] "%d alertbeskeder"
msgid "%d Alert:"
msgid_plural "%d Alerts:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d alertbesked:"
+msgstr[1] "%d alertbeskeder:"
msgid "%d Approval"
msgid_plural "%d Approvals"
@@ -186,17 +176,14 @@ msgstr[1] "%d commit-forfattere"
msgid "%d commit behind"
msgid_plural "%d commits behind"
-msgstr[0] "%d commit bagud"
-msgstr[1] "%d commits bagud"
+msgstr[0] "%d commit bagefter"
+msgstr[1] "%d commits bagefter"
msgid "%d commit,"
msgid_plural "%d commits,"
msgstr[0] "%d commit,"
msgstr[1] "%d commits,"
-msgid "%d commits"
-msgstr "%d commits"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] "%d fuldført problemstilling"
@@ -463,10 +450,10 @@ msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or
msgstr "%{code_open}Beskyttede:%{code_close} vises kun for beskyttede grene eller mærkater."
msgid "%{commit_author_link} authored %{commit_authored_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} forfattede %{commit_authored_timeago}"
msgid "%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} forfattede %{commit_authored_timeago} og %{commit_committer_avatar} %{commit_committer_link} committede %{commit_committer_timeago}"
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} fuldført vægt"
@@ -560,13 +547,13 @@ msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
msgstr "%{doc_link_start}Avanceret søgning%{doc_link_end} er aktiveret."
msgid "%{docs_link_start}Learn about visibility levels.%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Lær om synlighedsniveauer%{docs_link_end}."
msgid "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Hvad er Large File Storage?%{docs_link_end}"
msgid "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Hvad er totrinsgodkendelse?%{docs_link_end}"
msgid "%{due_date} (Past due)"
msgstr "%{due_date} (overskredet)"
@@ -698,10 +685,10 @@ msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} utilgængelig"
msgid "%{learn_more_link}."
-msgstr ""
+msgstr "%{learn_more_link}."
msgid "%{lessThan} 1 hour"
-msgstr ""
+msgstr "%{lessThan} 1 time"
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} er en gratis automatiserede open source certifikatmyndighed (CA) som udsteder digitale certifikater for at gøre det muligt at bruge HTTPS (SSL/TLS) på websteder."
@@ -722,7 +709,7 @@ msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent
msgstr "%{link_start}Start titlen med %{draft_snippet}%{link_end} for at forhindre en sammenlægningsanmodning der er under udarbejdelse i at blive sammenlagt før den er klar."
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
-msgstr ""
+msgstr "%{link_start}Hvilke informationer indsamler GitLab Inc.?%{link_end}"
msgid "%{listToShow}, and %{awardsListLength} more"
msgstr "%{listToShow} og %{awardsListLength} mere"
@@ -877,7 +864,7 @@ msgstr[0] "%{securityScanner} resultat er ikke tilgængeligt fordi en pipeline i
msgstr[1] "%{securityScanner} resultater er ikke tilgængelige fordi en pipeline ikke er blevet kørt siden de blev aktiverede. %{linkStart}Kør en pipeline%{linkEnd}"
msgid "%{service_ping_link_start}What information is shared with GitLab Inc.?%{service_ping_link_end}"
-msgstr ""
+msgstr "%{service_ping_link_start}Hvilke informationer deles med GitLab Inc.?%{service_ping_link_end}"
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -913,7 +900,7 @@ msgid "%{state} epics"
msgstr "%{state} epics"
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
-msgstr ""
+msgstr "%{strongOpen}Advarsel:%{strongClose} SAML-gruppelinks kan få GitLab til automatisk at fjerne medlemmer fra grupper."
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr "%{strongStart}Tip:%{strongEnd} Du kan også checkout sammenlægningsanmodninger lokalt ved at %{linkStart}følge retningslinjerne%{linkEnd}"
@@ -930,13 +917,13 @@ msgstr[1] "%{strong_start}%{commit_count}%{strong_end} commits"
msgid "%{strong_start}%{count} approval rule%{strong_end} requires eligible members to approve before merging."
msgid_plural "%{strong_start}%{count} approval rules%{strong_end} require eligible members to approve before merging."
-msgstr[0] "%{strong_start}%{count} godkendelsesregel%{strong_end} kræver godkendelse fra berettigede medlemmer inden sammenlægning."
-msgstr[1] "%{strong_start}%{count} godkendelsesregler%{strong_end} kræver godkendelse fra berettigede medlemmer inden sammenlægning."
+msgstr[0] "%{strong_start}%{count} godkendelsesregel%{strong_end} kræver godkendelse fra kvalificerede medlemmer inden sammenlægning."
+msgstr[1] "%{strong_start}%{count} godkendelsesregler%{strong_end} kræver godkendelse fra kvalificerede medlemmer inden sammenlægning."
msgid "%{strong_start}%{count} eligible member%{strong_end} must approve to merge."
msgid_plural "%{strong_start}%{count} eligible members%{strong_end} must approve to merge."
-msgstr[0] "%{strong_start}%{count} berettigede medlem%{strong_end} skal godkende for at sammenlægge."
-msgstr[1] "%{strong_start}%{count} berettigede medlemmer%{strong_end} skal godkende for at sammenlægge."
+msgstr[0] "%{strong_start}%{count} kvalificeret medlem%{strong_end} skal godkende for at sammenlægge."
+msgstr[1] "%{strong_start}%{count} kvalificerede medlemmer%{strong_end} skal godkende for at sammenlægge."
msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
@@ -1055,6 +1042,9 @@ msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} gør det muligt for dig
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} gør det muligt for dig at sende underretninger til webprogrammer som svar til begivenheder i en gruppe eller et projekt. Vi anbefaler at bruge en %{integrations_link_start}integrering%{link_end} i stedet for en webhook."
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr "%{wildcards_link_start}Jokertegn%{wildcards_link_end} såsom %{code_tag_start}v*%{code_tag_end} eller %{code_tag_start}*-release%{code_tag_end} understøttes."
@@ -1138,9 +1128,15 @@ msgstr "(fjernet)"
msgid "(revoked)"
msgstr "(tilbagekaldt)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr "(vi har brug for din nuværende adgangskode for at bekræfte dine ændringer)"
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} mere"
@@ -1193,6 +1189,9 @@ msgstr[1] "- Begivenheder"
msgid "- Not available to run jobs."
msgstr "- Ikke tilgængelig til at køre jobs."
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- Bruger"
@@ -1208,7 +1207,7 @@ msgid "."
msgstr "."
msgid "/"
-msgstr ""
+msgstr "/"
msgid "0 bytes"
msgstr "0 byte"
@@ -1341,7 +1340,7 @@ msgid "1000+"
msgstr "1000+"
msgid "192.168.0.0/24"
-msgstr ""
+msgstr "192.168.0.0/24"
msgid "1st contribution!"
msgstr "Første bidrag!"
@@ -1350,7 +1349,7 @@ msgid "20-29 contributions"
msgstr "20-29 bidrag"
msgid "2FA"
-msgstr "2TG"
+msgstr "2FA"
msgid "2FADevice|Registered On"
msgstr "Registreret"
@@ -1439,9 +1438,6 @@ msgstr "En standardgren kan ikke vælges til et tomt projekt."
msgid "A deleted user"
msgstr "En slettet bruger"
-msgid "A description is required"
-msgstr "En beskrivelse kræves"
-
msgid "A different reason"
msgstr "En anden årsag"
@@ -1475,8 +1471,8 @@ msgstr "Et medlem af misbrugsteamet gennemgår din rapport hurtigt muligt."
msgid "A merge request hasn't yet been merged"
msgstr "En sammenlægningsanmodning er endnu ikke blevet sammenlagt"
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
-msgstr "En ny Auto DevOps-pipeline er blevet oprettet. GÃ¥ til %{pipelines_link_start}Pipelines-siden%{pipelines_link_end} for detaljer"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
+msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
msgstr "En ny udgivelse %{tag} for %{name} blev udgivet. Besøg %{release_link_start}Udgivelser-siden%{release_link_end} for at læse mere om det."
@@ -1502,6 +1498,9 @@ msgstr "En platformværdi kan være web, mob eller app."
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1728,7 +1727,7 @@ msgid "Access granted"
msgstr "Adgang givet"
msgid "Access key ID"
-msgstr ""
+msgstr "Adgangsnøgle-id"
msgid "Access requests"
msgstr "Adgangsanmodninger"
@@ -1791,7 +1790,7 @@ msgid "AccessTokens|Static object token"
msgstr "Statisk objekttoken"
msgid "AccessTokens|They are the only accepted password when you have Two-Factor Authentication (2FA) enabled."
-msgstr "De er de eneste adgangskoder som accepteres når du har totrinsgodkendelse (2TG) aktiveret."
+msgstr "De er de eneste adgangskoder som accepteres når du har totrinsgodkendelse (2FA) aktiveret."
msgid "AccessTokens|You can also use personal access tokens to authenticate against Git over HTTP."
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr "Handlinger"
msgid "Activate Service Desk"
msgstr "Aktivér serviceskranke"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Aktive"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Tilføj en generel kommentar til denne %{noteableDisplayName}."
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "Tilføj en generel kommentar til %{noteable_name}."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Tilføj en startside til din wiki med information om dit projekt, så viser GitLab den her i stedet for denne meddelelse."
@@ -2012,9 +2011,6 @@ msgstr "Tilføj udsendelsesfrysning"
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr "Tilføj udsendelsesnøgler for at give læse-/skriveadgang til depotet. %{link_start}Hvad er udsendelsesnøgler?%{link_end}"
-msgid "Add domain"
-msgstr "Tilføj domæne"
-
msgid "Add email address"
msgstr "Tilføj e-mailadresse"
@@ -2052,7 +2048,7 @@ msgid "Add new directory"
msgstr "Tilføj ny mappe"
msgid "Add new service account"
-msgstr ""
+msgstr "Tilføj ny tjenestekonto"
msgid "Add or remove previously merged commits"
msgstr "Tilføj eller fjern commits, som tidligere er blevet sammenlagt"
@@ -2108,6 +2104,9 @@ msgstr "Tilføj til kontrol"
msgid "Add to tree"
msgstr "Tilføj til træ"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr "Tilføj udløser"
@@ -2331,13 +2330,13 @@ msgid "AdminArea|Projects"
msgstr "Projekter"
msgid "AdminArea|Reporter"
-msgstr ""
+msgstr "Rapportør"
msgid "AdminArea|Sign up for the GitLab Security Newsletter to get notified for security updates."
-msgstr ""
+msgstr "Tilmeld GitLab-sikkerhedsnyhedsbrevet for at blive underrettet om sikkerhedsopdateringer."
msgid "AdminArea|Sign up for the GitLab newsletter"
-msgstr ""
+msgstr "Tilmeld GitLab-nyhedsbrevet"
msgid "AdminArea|Stop all jobs"
msgstr "Stop alle job"
@@ -2436,7 +2435,7 @@ msgid "AdminSettings|Let's Encrypt email"
msgstr "E-mail for Let's Encrypt"
msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
-msgstr "Maksimale varighed på en session for Git-handlinger når 2TG er aktiveret."
+msgstr "Maksimale varighed på en session for Git-handlinger når 2FA er aktiveret."
msgid "AdminSettings|New CI/CD variables in projects and groups default to protected."
msgstr "Nye CI-/CD-variabler i projekter og grupper indstilles som standard til beskyttet."
@@ -2463,7 +2462,7 @@ msgid "AdminSettings|Select to disable public access for Pages sites, which requ
msgstr ""
msgid "AdminSettings|Session duration for Git operations when 2FA is enabled (minutes)"
-msgstr "Sessionsvarighed for Git-handlinger når 2TG er aktiveret (minutter)"
+msgstr "Sessionsvarighed for Git-handlinger når 2FA er aktiveret (minutter)"
msgid "AdminSettings|Set a CI/CD template as the required pipeline configuration for all projects in the instance. Project CI/CD configuration merges into the required pipeline configuration when the pipeline runs. %{link_start}What is a required pipeline configuration?%{link_end}"
msgstr ""
@@ -2511,7 +2510,7 @@ msgid "AdminStatistics|SSH Keys"
msgstr "SSH-nøgler"
msgid "AdminStatistics|Snippets"
-msgstr "Snippets"
+msgstr "Udklip"
msgid "AdminUsers|(Admin)"
msgstr "(administrator)"
@@ -2532,10 +2531,10 @@ msgid "AdminUsers|(Pending approval)"
msgstr "(afventer godkendelse)"
msgid "AdminUsers|2FA Disabled"
-msgstr "2TG deaktiveret"
+msgstr "2FA deaktiveret"
msgid "AdminUsers|2FA Enabled"
-msgstr "2TG aktiveret"
+msgstr "2FA aktiveret"
msgid "AdminUsers|A user can validate themselves by inputting a credit/debit card, or an admin can manually validate a user."
msgstr "En bruger kan validere sig selv ved at indtaste et kredit-/debetkort eller en administrator kan validere en bruger manuelt."
@@ -2564,8 +2563,8 @@ msgstr "Juster indstillingen brugerloft på din instans"
msgid "AdminUsers|Admin"
msgstr "Administrator"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
-msgstr "Administratorer har adgang til alle grupper, projekter og brugere, og kan håndtere alle funktioner i installationen"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgstr ""
msgid "AdminUsers|Admins"
msgstr "Administratorer"
@@ -2579,6 +2578,12 @@ msgstr "Godkend brugeren %{username}?"
msgid "AdminUsers|Approved users can:"
msgstr "Godkendte brugere kan:"
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr "Automatisk mærket som standard intern bruger"
@@ -2714,8 +2719,8 @@ msgstr "Genaktivering af en bruger vil:"
msgid "AdminUsers|Regular"
msgstr "Almindelige"
-msgid "AdminUsers|Regular users have access to their groups and projects"
-msgstr "Almindelige brugere har adgang til deres grupper og projekter"
+msgid "AdminUsers|Regular users have access to their groups and projects."
+msgstr ""
msgid "AdminUsers|Reject"
msgstr "Afvis"
@@ -2913,10 +2918,10 @@ msgid "Advanced export options"
msgstr ""
msgid "After a successful password update you will be redirected to login screen."
-msgstr "Efter en adgangskodeopdatering vil du blive omdirigeret til indlogningsskærmen."
+msgstr "Efter adgangskoden er blevet opdateret vil du blive omdirigeret til indlogningsskærmen."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
-msgstr "Efter en adgangskodeopdatering vil du blive omdirigeret til indlogningsskærmen hvor du kan logge ind med din nye adgangskode."
+msgstr "Efter adgangskoden er blevet opdateret vil du blive omdirigeret til indlogningsskærmen hvor du kan logge ind med din nye adgangskode."
msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
msgstr "Herefter vil du ikke være i stand til at bruge sammenlægningsgodkendelser eller kodekvalitet samt mange andre funktioner."
@@ -2931,7 +2936,7 @@ msgid "After you've reviewed these contribution guidelines, you'll be all set to
msgstr ""
msgid "Akismet"
-msgstr ""
+msgstr "Akismet"
msgid "Akismet API Key"
msgstr "Akismet API-nøgle"
@@ -3294,7 +3299,7 @@ msgid "All (default)"
msgstr "Alle (standard)"
msgid "All GitLab"
-msgstr ""
+msgstr "Hele GitLab"
msgid "All Members"
msgstr "Alle medlemmer"
@@ -3329,7 +3334,7 @@ msgstr "Alle sammenlægningskonflikter blev løst. Sammenlægningsanmodningen ka
msgid "All merge request dependencies have been merged"
msgstr "Alle sammenlægningsanmodningsafhængigheder er blevet sammenlagt"
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr "Alle brugere skal acceptere vilkår for tjeneste og privatlivspolitik fo
msgid "All users must have a name."
msgstr "Alle brugere skal have et navn."
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Tillad \"%{group_name}\" at logge dig ind"
@@ -3362,8 +3370,8 @@ msgstr "Tillad commits fra medlemmer, som kan sammenlægge til målgrenen."
msgid "Allow group owners to manage LDAP-related settings"
msgstr "Tillad gruppeejere at håndtere LDAP-relaterede indstillinger"
-msgid "Allow non-administrators to access to the performance bar"
-msgstr "Tillad ikke-administratorer at få adgang til ydelseslinjen"
+msgid "Allow non-administrators access to the performance bar"
+msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Tillad kun at de valgte protokoller bruges til Git-adgang."
@@ -3405,13 +3413,13 @@ msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr "Tillad undergrupper at indstille deres egne regler for totrinsgodkendelse"
msgid "Allow this key to push to this repository"
-msgstr ""
+msgstr "Tillad nøglen at bruge push til depotet"
msgid "Allow this secondary node to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
-msgstr ""
+msgstr "Tillad brug af licenserede EE-funktioner"
msgid "Allow users to dismiss the broadcast message"
msgstr "Tillad brugere at afskedig broadcastmeddelelsen"
@@ -3597,19 +3605,22 @@ msgid "An error occurred while enabling Service Desk."
msgstr "Der opstod en fejl under aktivering af serviceskranke."
msgid "An error occurred while fetching Markdown preview"
-msgstr ""
+msgstr "Der opstod en fejl under hentning af Markdown-forhåndsvisning"
msgid "An error occurred while fetching ancestors"
msgstr "Der opstod en fejl under hentning af forfædre"
-msgid "An error occurred while fetching branches. Retry the search."
-msgstr "Der opstod en fejl under hentning af grene. Prøv søgningen igen."
+msgid "An error occurred while fetching branches. Retry the search."
+msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr "Der opstod en fejl under hentning af kodekvalitets mr diff-rapporter."
-msgid "An error occurred while fetching commits. Retry the search."
-msgstr "Der opstod en fejl under hentning af commits. Prøv søgningen igen."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
+msgstr ""
msgid "An error occurred while fetching coverage reports."
msgstr "Der opstod en fejl under hentning af dækningsrapporter."
@@ -3720,7 +3731,7 @@ msgid "An error occurred while loading merge requests."
msgstr "Der opstod en fejl under indlæsning af sammenlægningsanmodninger."
msgid "An error occurred while loading projects."
-msgstr ""
+msgstr "Der opstod en fejl under indlæsning af projekter."
msgid "An error occurred while loading the Needs tab."
msgstr "Der opstod en fejl under indlæsning af fanebladet Behov."
@@ -3812,6 +3823,11 @@ msgstr "Der opstod en fejl under indhentning af projekter."
msgid "An error occurred while saving changes: %{error}"
msgstr "Der opstod en fejl under gemning af ændringer: %{error}"
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "Der opstod en fejl under abonnering på underretninger."
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr "Et serverfrit domæne på instansniveau findes allerede."
-
msgid "An issue already exists"
msgstr "Der findes allerede en problemstilling"
@@ -4127,8 +4140,8 @@ msgstr "Anvend"
msgid "Apply %d suggestion"
msgid_plural "Apply %d suggestions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Anvend %d forslag"
+msgstr[1] "Anvend %d forslag"
msgid "Apply a label"
msgstr "Anvend en etiket"
@@ -4210,12 +4223,18 @@ msgstr "Alle skannere"
msgid "ApprovalRule|All severity levels"
msgstr "Alle alvorlighedsniveauer"
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr "Anvend godkendelsesreglen til kun at overveje de valgte sikkerhedsskannere."
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr "Anvend godkendelsesreglen til kun at overveje de valgte alvorlighedsniveauer."
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr "Godkendelsesregler"
@@ -4228,12 +4247,21 @@ msgstr "Godkendertype"
msgid "ApprovalRule|Approvers"
msgstr "Godkendere"
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr "Eksempler: kvalitetssikring, sikkerhed."
msgid "ApprovalRule|Name"
msgstr "Navn"
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr "Antal sårbarheder som er tilladt før godkendelsesreglen udløses."
@@ -4246,6 +4274,15 @@ msgstr "Vælg venligst mindst én sikkerhedsskanner"
msgid "ApprovalRule|Please select at least one severity level"
msgstr "Vælg venligst mindst ét sikkerhedsniveau"
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr "Regelnavn"
@@ -4261,6 +4298,9 @@ msgstr "Vælg skannere"
msgid "ApprovalRule|Select severity levels"
msgstr "Vælg alvorlighedsniveauer"
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr "Alvorlighedsniveauer"
@@ -4270,6 +4310,9 @@ msgstr "MÃ¥lgren"
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr "SÃ¥rbarheder tilladt"
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "Godkendelsesindstillinger for sammenlægningsanmodning er blevet opdateret."
@@ -4542,12 +4585,6 @@ msgstr "Er du sikker? Fjernelse af GPG-nøglen påvirker ikke commits som allere
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr "Er du sikker? Enheden vil blive logget ud af GitLab og alle husk mig-tokens tilbagekaldt."
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr "Er du sikker? Det vil invalidere dine registrerede programmer og U2F-/WebAuthn-enheder."
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr "Er du sikker? Det vil invalidere dine registrerede programmer og U2F-enheder."
-
msgid "Arrange charts"
msgstr "Opstil diagrammer"
@@ -4783,6 +4820,9 @@ msgstr "August"
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -4868,16 +4908,16 @@ msgid "Authorize"
msgstr "Godkend"
msgid "Authorize %{link_to_client} to use your account?"
-msgstr ""
+msgstr "Giv %{link_to_client} tilladelse til at bruge din konto?"
msgid "Authorize %{user} to use your account?"
-msgstr ""
+msgstr "Giv %{user} tilladelse til at bruge din konto?"
msgid "Authorized %{new_chat_name}"
-msgstr ""
+msgstr "Giv %{new_chat_name} tilladelse"
msgid "Authorized At"
-msgstr ""
+msgstr "Tilladelse givet kl."
msgid "Authorized applications (%{size})"
msgstr "Godkendte programmer (%{size})"
@@ -5132,7 +5172,7 @@ msgid "BambooService|Atlassian Bamboo"
msgstr ""
msgid "BambooService|Bamboo URL"
-msgstr ""
+msgstr "URL for Bamboo"
msgid "BambooService|Bamboo build plan key."
msgstr ""
@@ -5294,7 +5334,7 @@ msgid "Billings|Reactivate trial"
msgstr "Genaktivér prøveperiode"
msgid "Billings|Shared runners cannot be enabled until a valid credit card is on file."
-msgstr "Delte runnere kan ikke aktiveres indtil en gyldigt kreditkort er blevet registreret."
+msgstr "Delte runnere kan ikke aktiveres indtil et gyldigt kreditkort er blevet registreret."
msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -5410,28 +5450,31 @@ msgid "Blocking issues"
msgstr "Blokerende problemstillinger"
msgid "Blocks"
-msgstr "Blokeringer"
+msgstr "Blokerer"
msgid "Blog"
msgstr "Blog"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
msgid "BoardNewEpic|Groups"
-msgstr ""
+msgstr "Grupper"
msgid "BoardNewEpic|Loading groups"
-msgstr ""
+msgstr "Indlæser grupper"
msgid "BoardNewEpic|No matching results"
-msgstr ""
+msgstr "Ingen matchende resultater"
msgid "BoardNewEpic|Search groups"
-msgstr ""
+msgstr "Søg efter grupper"
msgid "BoardNewEpic|Select a group"
-msgstr ""
+msgstr "Vælg en gruppe"
msgid "BoardNewIssue|No matching results"
msgstr ""
@@ -5479,7 +5522,7 @@ msgid "BoardScope|Select milestone"
msgstr "Vælg milepæl"
msgid "BoardScope|Select weight"
-msgstr ""
+msgstr "Vælg vægt"
msgid "BoardScope|Started"
msgstr "Startet"
@@ -5488,7 +5531,7 @@ msgid "BoardScope|Upcoming"
msgstr "Kommende"
msgid "BoardScope|Weight"
-msgstr ""
+msgstr "Vægt"
msgid "Boards"
msgstr "Tavler"
@@ -5656,8 +5699,8 @@ msgstr "Alle"
msgid "Branches|Cancel, keep branch"
msgstr "Annuller, behold gren"
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "Kan ikke finde HEAD-commit til grenen"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "Sammenlign"
@@ -5767,6 +5810,9 @@ msgstr "Skriv %{branch_name_confirmation} for at bekræfte:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "For at forkaste de lokale ændringer og overskrive grenen med upstream-versionen skal du slette den her og vælge 'Opdater nu' ovenover."
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr "Ja, slet gren"
@@ -5858,7 +5904,7 @@ msgid "BulkImport|From source group"
msgstr "Fra kildegruppe"
msgid "BulkImport|Group import history"
-msgstr ""
+msgstr "Historik for gruppeimport"
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5867,19 +5913,19 @@ msgid "BulkImport|Import groups from GitLab"
msgstr "Importér grupper fra GitLab"
msgid "BulkImport|Import selected"
-msgstr ""
+msgstr "Importér valgte"
msgid "BulkImport|Importing the group failed"
msgstr "Importering af gruppen mislykkedes"
msgid "BulkImport|Last imported to %{link}"
-msgstr ""
+msgstr "Sidst importeret til %{link}"
msgid "BulkImport|Name already exists."
msgstr "Navnet findes allerede."
msgid "BulkImport|New group"
-msgstr ""
+msgstr "Ny gruppe"
msgid "BulkImport|No history is available"
msgstr ""
@@ -5897,7 +5943,7 @@ msgid "BulkImport|Showing %{start}-%{end} of %{total} matching filter \"%{filter
msgstr ""
msgid "BulkImport|Source group"
-msgstr ""
+msgstr "Kildegruppe"
msgid "BulkImport|To new group"
msgstr "Til ny gruppe"
@@ -5960,7 +6006,7 @@ msgid "By authenticating with an account tied to an Enterprise e-mail address, i
msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
-msgstr ""
+msgstr "Som standard vil alle projekter og grupper bruge den globale underretningsindstilling."
msgid "ByAuthor|by"
msgstr "af"
@@ -5974,9 +6020,6 @@ msgstr "CI Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr "CI-minutter"
-
msgid "CI settings"
msgstr "CI-indstillinger"
@@ -6121,7 +6164,7 @@ msgid "CVE|Request CVE ID"
msgstr ""
msgid "CVE|Why Request a CVE ID?"
-msgstr ""
+msgstr "Hvorfor anmode om et CVE-id?"
msgid "Cadence is not automated"
msgstr "Kadence er ikke automatiseret"
@@ -6261,9 +6304,6 @@ msgstr "Annullerer forhåndsvisning"
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr "Kan ikke tildeles til andre projekter."
-
msgid "Cannot be merged automatically"
msgstr "Kan ikke sammenlægges automatisk"
@@ -6321,6 +6361,12 @@ msgstr "Kan ikke springe opsætning af totrinsgodkendelse over"
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6606,7 +6652,7 @@ msgid "Checkout|%{cardType} ending in %{lastFourDigits}"
msgstr "%{cardType} slutter med %{lastFourDigits}"
msgid "Checkout|%{name}'s CI minutes"
-msgstr ""
+msgstr "%{name}s CI-minutter"
msgid "Checkout|%{name}'s GitLab subscription"
msgstr "%{name}s GitLab-abonnement"
@@ -6615,7 +6661,7 @@ msgid "Checkout|%{name}'s storage subscription"
msgstr ""
msgid "Checkout|%{quantity} GB of storage"
-msgstr ""
+msgstr "%{quantity} GB lager"
msgid "Checkout|%{quantity} storage pack"
msgid_plural "Checkout|%{quantity} storage packs"
@@ -6649,6 +6695,9 @@ msgstr "CI-minutpakke"
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr "Rediger"
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6704,7 +6756,7 @@ msgid "Checkout|Failed to register credit card. Please try again."
msgstr "Kunne ikke registrere kreditkort. Prøv venligst igen."
msgid "Checkout|GB"
-msgstr ""
+msgstr "GB"
msgid "Checkout|GitLab group"
msgstr "GitLab-gruppe"
@@ -6767,7 +6819,7 @@ msgid "Checkout|Total minutes: %{quantity}"
msgstr "Minutter i alt: %{quantity}"
msgid "Checkout|Total storage: %{quantity} GB"
-msgstr ""
+msgstr "Lager i alt: %{quantity} GB"
msgid "Checkout|Users"
msgstr "Brugere"
@@ -6794,6 +6846,9 @@ msgid "Checkout|company or team"
msgstr "virksomhed eller team"
msgid "Checkout|minutes"
+msgstr "minutter"
+
+msgid "Checkout|x %{quantity} %{units} per pack"
msgstr ""
msgid "Checkout|x %{quantity} %{units} per pack ="
@@ -6838,15 +6893,9 @@ msgstr "Vælg en skabelon ..."
msgid "Choose a type..."
msgstr "Vælg en type ..."
-msgid "Choose any color"
-msgstr "Vælg en farve"
-
msgid "Choose any color."
msgstr "Vælg en farve."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr "Vælg en farve. Eller du kan vælge en de forslåede farver nedenunder"
-
msgid "Choose file…"
msgstr "Vælg fil …"
@@ -7265,7 +7314,7 @@ msgid "ClusterAgents|Connected"
msgstr ""
msgid "ClusterAgents|Connection status"
-msgstr ""
+msgstr "Forbindelsesstatus"
msgid "ClusterAgents|Copy token"
msgstr "Kopiér token"
@@ -7307,7 +7356,7 @@ msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
msgid "ClusterAgents|Last contact"
-msgstr ""
+msgstr "Sidste kontakt"
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr "Lær at oprette en agentadgangstoken"
@@ -7489,7 +7538,7 @@ msgstr "Tjek din klyngestatus"
msgid "ClusterIntegration|Check your token"
msgstr "Tjek din token"
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7823,7 +7872,7 @@ msgid "ClusterIntegration|No subnet found"
msgstr ""
msgid "ClusterIntegration|No subnetworks found"
-msgstr ""
+msgstr "Ingen undernetværk fundet"
msgid "ClusterIntegration|No zones matched your search"
msgstr "Ingen zoner passede til din søgning"
@@ -7930,6 +7979,9 @@ msgstr "Sikkerhedsgruppe"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Se og rediger detaljerne til din Kubernetes-klynge"
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr "Vælg en VPC for at vælge en sikkerhedsgruppe"
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "Vælg et netværk for at vælge et undernetværk"
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "Vælg maskintype"
@@ -7963,6 +8033,9 @@ msgstr "Vælg projekt og zone for at vælge maskintype"
msgid "ClusterIntegration|Select project to choose zone"
msgstr "Vælg projekt for at vælge zone"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8021,7 +8094,7 @@ msgid "ClusterIntegration|There was an HTTP error when connecting to your cluste
msgstr ""
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
-msgstr "Kontoen skal have tilladelser til at oprette en Kubernetes-klynge i %{link_to_container_project} angivet nedenfor"
+msgstr "Kontoen skal have tilladelser til at oprette en Kubernetes-klynge i %{link_to_container_project} angivet nedenunder"
msgid "ClusterIntegration|This is necessary if your integration has become out of sync. The cache is repopulated during the next CI job that requires namespace and service accounts."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr "opfylder kravene"
msgid "ClusterIntegration|sign up"
msgstr "tilmeld"
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr "Vælg et netværk"
-
-msgid "ClusterIntergation|Select a security group"
-msgstr "Vælg en sikkerhedsgruppe"
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr "Vælg et undernetværk"
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr "Vælg en instanstype"
-
-msgid "ClusterIntergation|Select key pair"
-msgstr "Vælg et nøglepar"
-
-msgid "ClusterIntergation|Select service role"
-msgstr "Vælg tjenesterolle"
-
msgid "Clusters|An error occurred while loading clusters"
msgstr "Der opstod en fejl under indlæsning af klynger"
@@ -8234,7 +8283,7 @@ msgid "Collapse replies"
msgstr "Sammenfold svar"
msgid "Collapse settings section"
-msgstr ""
+msgstr "Sammenfold indstillingsafsnit"
msgid "Collapse sidebar"
msgstr "Sammenfold sidebjælke"
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr "Kommentér"
-msgid "Comment & close %{noteable_name}"
-msgstr "Kommentér og luk %{noteable_name}"
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr "Kommentér og genåbn %{noteable_name}"
-
msgid "Comment & resolve thread"
msgstr "Kommentér og løs tråd"
@@ -8397,6 +8440,9 @@ msgstr "Fællesskabsforum"
msgid "Company"
msgstr "Virksomhed"
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Sammenlign"
@@ -8478,32 +8524,38 @@ msgstr "Fuldført"
msgid "Completed"
msgstr "Fuldført"
-msgid "Compliance"
-msgstr "Overholdelse"
-
-msgid "Compliance Dashboard"
-msgstr "Overholdelsesbetjeningspanel"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
+msgstr ""
msgid "Compliance framework"
msgstr "Overholdelsesframework"
+msgid "Compliance report"
+msgstr ""
+
msgid "ComplianceDashboard|created by:"
msgstr "oprettet af:"
msgid "ComplianceFrameworks|Add framework"
msgstr "Tilføj framework"
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr "Overholdelsesframework slettet"
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
-msgstr "Kunne ikke finde konfigurationsplaceringen. Prøv venligst en anden placering"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
+msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
msgstr "Slet overholdelsesframeworket %{framework}"
@@ -8511,6 +8563,12 @@ msgstr "Slet overholdelsesframeworket %{framework}"
msgid "ComplianceFrameworks|Delete framework"
msgstr "Slet framework"
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr "Rediger framework"
@@ -8523,32 +8581,32 @@ msgstr "Fejl ved hentning af overholdelsesframeworkdata. Opdater venligst siden"
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr "Fejl ved hentning af overholdelsesframeworkdata. Opdater venligst siden eller prøv et andet framework"
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
-msgstr "Ugyldigt format: det skal følge formatet [STI].y(a)ml@[GRUPPE]/[PROJEKT]"
+msgid "ComplianceFrameworks|Invalid format"
+msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
-msgstr "Når et overholdelsesframework er tilføjet, så vises det her."
+msgid "ComplianceFrameworks|Name"
+msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
-msgstr "Der er ikke opsat nogle overholdelsesframeworks endnu"
+msgid "ComplianceFrameworks|Name is required"
+msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
-msgstr "Kan ikke gemme overholdelsesframeworket. Prøv venligst igen"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
+msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr "Kan ikke gemme overholdelsesframeworket. Prøv venligst igen"
+
msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
-msgstr "Rediger overholdelsesframework"
-
-msgid "ComplianceFramework|New Compliance Framework"
-msgstr "Nyt overholdelsesframework"
+msgid "ComplianceFramework|New compliance framework"
+msgstr ""
msgid "Component"
msgstr "Komponent"
@@ -8617,17 +8675,11 @@ msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeSt
msgstr "Konfigurer en %{codeStart}.gitlab-webide.yml%{codeEnd}-fil i mappen %{codeStart}.gitlab%{codeEnd} for at komme i gang med webterminal. %{helpStart}Lær mere%{helpEnd}."
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
-msgstr ""
-
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
+msgstr "Konfigurer avancerede tilladelser, Large File Storage og totrinsgodkendelsesindstillinger."
msgid "Configure existing installation"
msgstr "Konfigurer eksisterende installation"
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr "Kontakt support"
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "Beholderregister"
@@ -8888,7 +8943,7 @@ msgid "ContainerRegistry|Copy login command"
msgstr ""
msgid "ContainerRegistry|Copy push command"
-msgstr ""
+msgstr "Kopiér push-kommando"
msgid "ContainerRegistry|Delete image repository?"
msgstr "Slet aftryksdepot?"
@@ -8896,10 +8951,10 @@ msgstr "Slet aftryksdepot?"
msgid "ContainerRegistry|Delete selected tags"
msgstr "Slet valgte mærkater"
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -8975,7 +9030,7 @@ msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at
msgstr "Udgivet til aftryksdepotet %{repositoryPath} kl. %{time} %{date}"
msgid "ContainerRegistry|Push an image"
-msgstr ""
+msgstr "Push et billede"
msgid "ContainerRegistry|Remember to run %{docLinkStart}garbage collection%{docLinkEnd} to remove the stale data from storage."
msgstr ""
@@ -9067,7 +9122,7 @@ msgid "ContainerRegistry|The requested image repository does not exist or has be
msgstr "Det anmodede aftryksdepot findes ikke eller er blevet slettet. Hvis du tror det er en fejl, så prøv at opdatere siden."
msgid "ContainerRegistry|The value of this input should be less than 256 characters"
-msgstr "Værdien af inputtet skal skal være mindre end 256 tegn"
+msgstr "Værdien af inputtet skal være mindre end 256 tegn"
msgid "ContainerRegistry|There are no container images available in this group"
msgstr "Der er ingen beholderaftryk tilgængelige i gruppen"
@@ -9096,7 +9151,7 @@ msgstr "Dit projekts oprydningsregelsæt for mærkater er ikke aktiveret."
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,14 +9175,11 @@ msgstr "Du er ved at fjerne depotet %{title}. Når du bekræfter, så vil depote
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr "Du kan tilføje et aftryk til registeret med følgende kommandoer:"
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
msgid "ContentEditor|Table of Contents"
-msgstr ""
+msgstr "Indholdsfortegnelse"
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr "Kopiér %{name}"
msgid "Copy %{protocol} clone URL"
msgstr "Kopiér klonings-URL for %{protocol}"
-msgid "Copy %{proxy_url}"
-msgstr "Kopiér %{proxy_url}"
-
msgid "Copy %{type}"
msgstr "Kopiér %{type}"
@@ -9315,9 +9364,6 @@ msgstr "Kopiér link"
msgid "Copy link to chart"
msgstr "Kopiér link til diagram"
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr "Kopiér reference"
@@ -9402,9 +9448,6 @@ msgstr "Kunne ikke tilføje administratorer som medlemmer"
msgid "Could not apply %{name} command."
msgstr "Kunne ikke anvende kommandoen %{name}."
-msgid "Could not archive %{design}. Please try again."
-msgstr "Kunne ikke arkivere %{design}. Prøv venligst igen."
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr "Kunne ikke uploade dine designs da en eller flere af de uploadede filer
msgid "Couldn't assign policy to project"
msgstr "Kunne ikke tildele regelsæt til projekt"
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr "Dækning"
@@ -9528,6 +9574,9 @@ msgstr "Opret %{humanized_resource_name}"
msgid "Create %{type}"
msgstr "Opret %{type}"
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Opret ny mappe"
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr "Opret et Mattermost-team til gruppen"
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr "Opret en sammenlægningsanmodning"
@@ -9558,11 +9604,14 @@ msgstr ""
msgid "Create a new issue"
msgstr "Opret en ny problemstilling"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr "Opret et nyt depot"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
-msgstr ""
+msgstr "Opret en personlig adgangstoken på din konto for at bruge pull eller push via %{protocol}."
msgid "Create an account using:"
msgstr "Opret en konto med:"
@@ -9616,7 +9665,7 @@ msgid "Create issue"
msgstr "Opret problemstilling"
msgid "Create issue to resolve all threads"
-msgstr ""
+msgstr "Opret problemstilling for at løse alle tråde"
msgid "Create iteration"
msgstr "Opret gennemløb"
@@ -9673,7 +9722,7 @@ msgid "Create new..."
msgstr "Opret ny(t) ..."
msgid "Create or import your first project"
-msgstr ""
+msgstr "Opret eller importér dit første projekt"
msgid "Create project"
msgstr "Opret projekt"
@@ -9693,6 +9742,9 @@ msgstr "Opret udklip"
msgid "Create tag %{tagName}"
msgstr "Opret mærkatet %{tagName}"
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr "Opret bruger"
@@ -9810,11 +9862,11 @@ msgstr "Gendan standarder"
msgid "CreateValueStreamForm|Restore stage"
msgstr "Gendannelsesstadie"
-msgid "CreateValueStreamForm|Save Value Stream"
-msgstr "Gem Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
+msgstr ""
msgid "CreateValueStreamForm|Select end event"
-msgstr ""
+msgstr "Vælg slutbegivenhed"
msgid "CreateValueStreamForm|Select start event"
msgstr ""
@@ -9933,10 +9985,7 @@ msgstr "Personlige adgangstokens"
msgid "CredentialsInventory|SSH Keys"
msgstr "SSH-nøgler"
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr "Nuværende indlognings-IP:"
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10033,7 +10085,7 @@ msgid "Custom notification events"
msgstr "Tilpassede underretningsbegivenheder"
msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notificationLinkStart}notification emails%{notificationLinkEnd}."
-msgstr ""
+msgstr "Tilpassede underretningsniveauer er det samme som deltagelsesniveauer. Med tilpassede underretningsniveauer vil du også modtage underretninger om udvalgte begivenheder. Find ud af mere ved at tjekke %{notificationLinkStart}underretnings e-mails%{notificationLinkEnd}."
msgid "Custom project templates"
msgstr "Tilpassede projektskabeloner"
@@ -10047,6 +10099,15 @@ msgstr "Tilpasset område"
msgid "Custom range (UTC)"
msgstr "Tilpasset område (UTC)"
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr "Kan tilpasses af en administrator."
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr "Vis diagramfiltre"
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr "Ingen stadier valgt"
@@ -10273,6 +10337,9 @@ msgstr "DAST-konfiguration"
msgid "DAST Scans"
msgstr "DAST-skanninger"
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10547,7 +10614,7 @@ msgid "DastProfiles|Scanner name"
msgstr ""
msgid "DastProfiles|Schedule"
-msgstr ""
+msgstr "Planlæg"
msgid "DastProfiles|Select branch"
msgstr "Vælg gren"
@@ -10729,7 +10796,7 @@ msgid "DatadogIntegration|(Advanced) The full URL for your Datadog site."
msgstr ""
msgid "DatadogIntegration|API URL"
-msgstr ""
+msgstr "API URL"
msgid "DatadogIntegration|Environment"
msgstr "Miljø"
@@ -10767,6 +10834,9 @@ msgstr "Datovælger"
msgid "Date range"
msgstr "Datoområde"
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr "Standardgren"
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10843,7 +10916,7 @@ msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
-msgstr ""
+msgstr "Standardbeskrivelsesskabelon for problemstillinger"
msgid "Default description template for merge requests"
msgstr "Standardbeskrivelsesskabelon til sammenlægningsanmodninger"
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Fully protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10909,7 +11000,7 @@ msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This jo
msgstr ""
msgid "DelayedJobs|Run the delayed job now?"
-msgstr ""
+msgstr "Kør det forsinkede job nu?"
msgid "DelayedJobs|Start now"
msgstr "Start nu"
@@ -10956,9 +11047,6 @@ msgstr "Slet kommentar"
msgid "Delete corpus"
msgstr "Slet korpus"
-msgid "Delete domain"
-msgstr "Slet domæne"
-
msgid "Delete file"
msgstr "Slet fil"
@@ -10986,9 +11074,6 @@ msgstr "Slet række"
msgid "Delete self monitoring project"
msgstr "Slet selvovervågningsprojekt"
-msgid "Delete serverless domain?"
-msgstr "Slet serverfrit domæne?"
-
msgid "Delete snippet"
msgstr "Slet udklip"
@@ -11016,6 +11101,9 @@ msgstr "Slet brugerliste"
msgid "Delete variable"
msgstr "Slet variabel"
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "Kunne ikke fjerne projektdepot. Prøv venligst igen eller kontakt administrator."
@@ -11178,22 +11266,34 @@ msgstr "Afhængighedsproxy"
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
-msgstr "Afhængighedsproxy"
+msgid "DependencyProxy|Cached %{time}"
+msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
msgstr ""
msgid "DependencyProxy|Dependency Proxy"
+msgstr "Afhængighedsproxy"
+
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11245,7 +11345,7 @@ msgid "DeployFreeze|Delete deploy freeze?"
msgstr "Slet udsendelsesfrysning?"
msgid "DeployFreeze|Delete freeze period"
-msgstr ""
+msgstr "Slet frysningsperiode"
msgid "DeployFreeze|Deploy freeze from %{start} to %{end} in %{timezone} will be removed. Are you sure?"
msgstr "Udsendelsesfrysning fra %{start} til %{end} i %{timezone} vil blive fjernet. Er du sikker?"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr "%{current_design} af %{designs_count}"
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr "Gem kommentar"
msgid "DesignManagement|Select all"
msgstr "Vælg alle"
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr "Det maksimale antal designs som kan uploades er %{upload_limit}. Prøv venligst igen."
@@ -11630,15 +11738,12 @@ msgstr "Genåbn løst tråd"
msgid "DesignManagement|Upload designs"
msgstr "Upload designs"
-msgid "DesignManagement|Upload skipped."
-msgstr "Upload sprunget over."
+msgid "DesignManagement|Upload skipped. %{reason}"
+msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr "Dine designs er ved at blive kopieret og er på vej … opdater venligst."
-msgid "DesignManagement|and %{moreCount} more."
-msgstr "og %{moreCount} mere."
-
msgid "Designs"
msgstr "Designs"
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr "Der opstod en fejl under fjernelse af gruppen. Prøv venligst igen."
@@ -11768,6 +11876,9 @@ msgstr "Sammenlægningsanmodninger"
msgid "DevopsAdoption|No results…"
msgstr "Ingen resultater …"
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr "Der opstod en fejl ved hentning af grupper. Opdater venligst siden."
msgid "DevopsAdoption|This group has no subgroups"
msgstr "Gruppen har ingen undergrupper"
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11850,10 +11964,10 @@ msgid "Didn't receive a confirmation email?"
msgstr "Modtog du ikke en bekræftelses e-mail?"
msgid "Didn't receive confirmation instructions?"
-msgstr ""
+msgstr "Har du ikke modtaget bekræftelsesinstruktioner?"
msgid "Didn't receive unlock instructions?"
-msgstr ""
+msgstr "Har du ikke modtaget oplåsningsinstruktioner?"
msgid "Diff files surpassing this limit will be presented as 'too large' and won't be expandable."
msgstr ""
@@ -11872,13 +11986,13 @@ msgstr ""
msgid "Diffs|%d addition"
msgid_plural "Diffs|%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d tilføjelse"
+msgstr[1] "%d tilføjelser"
msgid "Diffs|%d deletion"
msgid_plural "Diffs|%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d sletning"
+msgstr[1] "%d sletninger"
msgid "Diffs|No file name available"
msgstr ""
@@ -11898,7 +12012,7 @@ msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "Noget gik galt under hentning af diff-linjer."
msgid "Diffs|with %{additions} and %{deletions}"
-msgstr ""
+msgstr "med %{additions} og %{deletions}"
msgid "Direct member"
msgstr "Direkte medlem"
@@ -11999,12 +12113,6 @@ msgstr "Start en gratis prøveperiode"
msgid "Discover|Upgrade now"
msgstr "Opgrader nu"
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr "Debatér et bestemt forslag eller spørgsmål som har brug for at blive løst."
@@ -12074,7 +12182,7 @@ msgid "Do you want to remove this deploy key?"
msgstr "Vil du fjerne udsendelsesnøglen?"
msgid "Dockerfile"
-msgstr ""
+msgstr "Dockerfile"
msgid "Documentation"
msgstr "Dokumentation"
@@ -12083,7 +12191,7 @@ msgid "Documentation for popular identity providers"
msgstr ""
msgid "Documentation pages URL"
-msgstr ""
+msgstr "URL for dokumentationssider"
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr "Dokumenter genindekseret: %{processed_documents} (%{percentage} %%)"
@@ -12097,18 +12205,6 @@ msgstr "Domæne"
msgid "Domain Name"
msgstr "Domænenavn"
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr "Domænet blev oprettet."
-
-msgid "Domain was successfully deleted."
-msgstr "Domænet blev slettet."
-
-msgid "Domain was successfully updated."
-msgstr "Domænet blev opdateret."
-
msgid "Don't have an account yet?"
msgstr "Har du endnu ikke en konto?"
@@ -12139,9 +12235,6 @@ msgstr "Download %{format}"
msgid "Download %{format}:"
msgstr "Download %{format}:"
-msgid "Download %{name} artifact"
-msgstr "Download artefaktet %{name}"
-
msgid "Download (%{fileSizeReadable})"
msgstr "Download (%{fileSizeReadable})"
@@ -12323,7 +12416,7 @@ msgid "Edit files in the editor and commit changes here"
msgstr "Rediger filer i editoren og commit ændringer her"
msgid "Edit fork in Web IDE"
-msgstr "Rediger forgrening i Web IDE"
+msgstr "Rediger forgrening i web-IDE"
msgid "Edit group application"
msgstr "Rediger gruppeprogram"
@@ -12335,7 +12428,7 @@ msgid "Edit identity for %{user_name}"
msgstr ""
msgid "Edit in Web IDE"
-msgstr "Rediger i Web IDE"
+msgstr "Rediger i web-IDE"
msgid "Edit in single-file editor"
msgstr "Rediger i editor med én fil"
@@ -12347,7 +12440,7 @@ msgid "Edit issues"
msgstr "Rediger problemstillinger"
msgid "Edit merge requests"
-msgstr ""
+msgstr "Rediger sammenlægningsanmodninger"
msgid "Edit public deploy key"
msgstr "Rediger offentlig udsendelsesnøgle"
@@ -12367,6 +12460,9 @@ msgstr "Rediger udgivelsen"
msgid "Edit title and description"
msgstr "Rediger titel og beskrivelse"
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr "Rediger bruger: %{user_name}"
@@ -12425,7 +12521,7 @@ msgid "Elastic|None. Select projects to index."
msgstr ""
msgid "Eligible users"
-msgstr ""
+msgstr "Kvalificerede brugere"
msgid "Email"
msgstr "E-mail"
@@ -12527,7 +12623,7 @@ msgid "EmailsOnPushService|Email the commits and diff of each push to a list of
msgstr ""
msgid "EmailsOnPushService|Emails on push"
-msgstr ""
+msgstr "E-mails ved push"
msgid "EmailsOnPushService|Emails separated by whitespace."
msgstr ""
@@ -12593,7 +12689,7 @@ msgid "Enable SSL verification"
msgstr "Aktivér SSL-verificering"
msgid "Enable Service Ping"
-msgstr ""
+msgstr "Aktivér tjenesteping"
msgid "Enable Snowplow tracking"
msgstr ""
@@ -12611,7 +12707,7 @@ msgid "Enable a Prometheus endpoint that exposes health and performance statisti
msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
-msgstr ""
+msgstr "Aktivér adgang til ydelseslinjen for ikke-administratorer i en given gruppe."
msgid "Enable admin mode"
msgstr "Aktivér administratortilstand"
@@ -12691,17 +12787,14 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
-msgid "Enable proxy"
-msgstr "Aktivér proxy"
-
msgid "Enable reCAPTCHA"
msgstr "Aktivér reCAPTCHA"
msgid "Enable reCAPTCHA for login."
-msgstr ""
+msgstr "Aktivér reCAPTCHA for indlogning."
msgid "Enable repository checks"
msgstr ""
@@ -12731,7 +12824,7 @@ msgid "Enable unauthenticated web request rate limit"
msgstr ""
msgid "Enable user deactivation emails"
-msgstr ""
+msgstr "Aktivér brugerdeaktiverings e-mails"
msgid "Enable version check"
msgstr ""
@@ -12770,7 +12863,7 @@ msgid "Encountered an error while rendering: %{err}"
msgstr "Stødte på en fejl under gengivelse: %{err}"
msgid "End Time"
-msgstr "Sluttid"
+msgstr "Sluttidspunkt"
msgid "Ends"
msgstr "Slutter"
@@ -12820,8 +12913,11 @@ msgstr "Indtast et tal"
msgid "Enter an integer number between 0 and 100"
msgstr "Indtast et heltal fra 0 til 100"
-msgid "Enter an integer number number between 0 and 100"
-msgstr "Indtast et heltal fra 0 til 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
+msgstr ""
msgid "Enter at least three characters to search"
msgstr "Indtast mindst tre tegn for at søge"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr "Miljø"
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,8 +13074,8 @@ msgstr "Der opstod en fejl under stop af miljøet. Prøv venligst igen"
msgid "Environments|Are you sure you want to stop this environment?"
msgstr "Er du sikker på, at du vil stoppe miljøet?"
-msgid "Environments|Auto stop in"
-msgstr "Automatisk stop om"
+msgid "Environments|Auto stop"
+msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
msgstr "Stopper automatisk %{autoStopAt}"
@@ -12995,7 +13093,7 @@ msgid "Environments|Delete"
msgstr "Slet"
msgid "Environments|Delete '%{environmentName}'?"
-msgstr ""
+msgstr "Slet '%{environmentName}'?"
msgid "Environments|Delete environment"
msgstr "Slet miljø"
@@ -13061,7 +13159,7 @@ msgid "Environments|Note that this action will stop the environment, but it will
msgstr ""
msgid "Environments|Open"
-msgstr ""
+msgstr "Ã…bne"
msgid "Environments|Open live environment"
msgstr ""
@@ -13276,6 +13374,9 @@ msgstr "Fejl ved oprettelse af epic"
msgid "Error creating label."
msgstr "Fejl ved oprettelse af etiket."
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr "Fejl ved oprettelse af nyt gennemløb"
@@ -13406,7 +13507,7 @@ msgid "Error parsing CSV file. Please make sure it has"
msgstr "Fejl ved fortolkning af CSV-fil. Sørg venligst for at den har"
msgid "Error rendering Markdown preview"
-msgstr ""
+msgstr "Fejl ved gengivelse af Markdown-forhåndsvisning"
msgid "Error saving label update."
msgstr "Fejl ved gemning af etiketopdatering."
@@ -13453,6 +13554,9 @@ msgstr "Fejl med Akismet. Tjek venligst loggene for mere information."
msgid "Error: %{error_message}"
msgstr "Fejl: %{error_message}"
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13658,13 +13762,13 @@ msgid "Every %{action} attempt has failed: %{job_error_message}. Please try agai
msgstr "Alle forsøg på %{action} mislykkedes: %{job_error_message}. Prøv venligst igen."
msgid "Every 3 months"
-msgstr ""
+msgstr "Hver 3. måned"
msgid "Every 3 months on the %{day} at %{time} %{timezone}"
msgstr ""
msgid "Every 6 months"
-msgstr ""
+msgstr "Hver 6. måned"
msgid "Every 6 months on the %{day} at %{time} %{timezone}"
msgstr ""
@@ -13676,7 +13780,7 @@ msgid "Every day (at %{time})"
msgstr "Hver dag (kl. %{time})"
msgid "Every day at %{time} %{timezone}"
-msgstr ""
+msgstr "Hver dag kl. %{time} %{timezone}"
msgid "Every month"
msgstr "Hver måned"
@@ -13705,7 +13809,7 @@ msgid "Every week on %{day} at %{time} %{timezone}"
msgstr ""
msgid "Every year"
-msgstr ""
+msgstr "Hvert år"
msgid "Every year on %{day} at %{time} %{timezone}"
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr "Præcist én af %{attributes} kræves"
msgid "Example: @sub\\.company\\.com$"
msgstr "Eksempel: @sub\\.company\\.com$"
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr "Udløbsdato"
msgid "Expiration date (optional)"
msgstr "Udløbsdato (valgfrit)"
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr "Udløbet"
@@ -13848,6 +13952,9 @@ msgstr "Udløber"
msgid "Expires in %{expires_at}"
msgstr "Udløber om %{expires_at}"
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr "Udløber:"
@@ -13875,11 +13982,8 @@ msgstr "Udforsk offentlige grupper"
msgid "Export"
msgstr "Eksportér"
-msgid "Export %{name}"
-msgstr "Eksportér %{name}"
-
msgid "Export %{requirementsCount} requirements?"
-msgstr ""
+msgstr "Eksportér %{requirementsCount} krav?"
msgid "Export as CSV"
msgstr "Eksportér som CSV"
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr "Eksportér gruppe"
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "Eksportér projekt"
@@ -13930,7 +14040,7 @@ msgid "External authorization request timeout"
msgstr ""
msgid "External storage URL"
-msgstr ""
+msgstr "URL for eksternt lager"
msgid "External storage authentication token"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr "Kunne ikke tilføje et Zoom-møde"
msgid "Failed to apply commands."
msgstr "Kunne ikke anvende kommandoer."
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr "Kunne ikke tildele en kontrollant fordi der ikke blev fundet nogen bruger."
@@ -14208,9 +14323,6 @@ msgstr "Kunne ikke opgradere."
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr "Kunne ikke verificere domæneejerskab"
-
msgid "Failure"
msgstr "Mislykket"
@@ -14268,7 +14380,7 @@ msgid "FeatureFlags|* (All Environments)"
msgstr "* (alle miljøer)"
msgid "FeatureFlags|API URL"
-msgstr ""
+msgstr "URL for API"
msgid "FeatureFlags|Active"
msgstr "Aktiv"
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr "Fjern"
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr "Færdige"
msgid "Finished at"
msgstr "Færdig kl."
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr "Først set"
@@ -14884,6 +15002,9 @@ msgstr "Fandt fejl i din .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr "Framework slettet"
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr "Gratis prøveperiode af GitLab.com Ultimate"
@@ -14906,7 +15027,7 @@ msgid "From"
msgstr "Fra"
msgid "From %{code_open}%{source_title}%{code_close} into"
-msgstr ""
+msgstr "Fra %{code_open}%{source_title}%{code_close} ind i"
msgid "From %{providerTitle}"
msgstr "Fra %{providerTitle}"
@@ -14944,6 +15065,9 @@ msgstr "Generelle indstillinger"
msgid "General pipelines"
msgstr "Generelle pipelines"
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15083,7 +15207,7 @@ msgid "Geo|Discover GitLab Geo"
msgstr ""
msgid "Geo|Does not match the primary storage configuration"
-msgstr ""
+msgstr "Matcher ikke den primære lagerkonfiguration"
msgid "Geo|Failed"
msgstr "Mislykket"
@@ -15104,16 +15228,16 @@ msgid "Geo|Geo sites are paused using a command run on the site"
msgstr ""
msgid "Geo|Geo supports replication of many data types."
-msgstr ""
+msgstr "Geo understøtter replikering af mange datatyper."
msgid "Geo|Go to the primary site"
-msgstr ""
+msgstr "Gå til det primære websted"
msgid "Geo|Healthy"
msgstr "Sund"
msgid "Geo|If you want to make changes, you must visit the primary site."
-msgstr ""
+msgstr "Hvis du vil foretage ændringer, så skal du besøge det primære websted."
msgid "Geo|In progress"
msgstr "I gang"
@@ -15125,19 +15249,19 @@ msgid "Geo|Internal URL"
msgstr "Intern URL"
msgid "Geo|Last event ID from primary"
-msgstr ""
+msgstr "Sidste begivenheds-id fra primære"
msgid "Geo|Last event ID processed by cursor"
-msgstr ""
+msgstr "Sidste begivenheds-id behandlet af markør"
msgid "Geo|Last repository check run"
-msgstr ""
+msgstr "Sidste kørsel af depottjek"
msgid "Geo|Last successful sync"
msgstr "Sidste synkronisering som lykkedes"
msgid "Geo|Last sync attempt"
-msgstr ""
+msgstr "Sidste synkroniseringsforsøg"
msgid "Geo|Last time verified"
msgstr ""
@@ -15146,7 +15270,7 @@ msgid "Geo|Learn more about Geo"
msgstr "Lær mere om Geo"
msgid "Geo|Learn more about Geo site statuses"
-msgstr ""
+msgstr "Lær mere om Geo-webstedsstatusser"
msgid "Geo|Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
@@ -15161,10 +15285,10 @@ msgid "Geo|No available replication slots"
msgstr "Ingen tilgængelige replikationspladser"
msgid "Geo|Node name can't be blank"
-msgstr ""
+msgstr "Knudepunktsnavn må ikke være tomt"
msgid "Geo|Node name should be between 1 and 255 characters"
-msgstr ""
+msgstr "Knudepunktsnavn skal være fra 1 til 255 tegn"
msgid "Geo|Not synced yet"
msgstr "Ikke synkroniseret endnu"
@@ -15191,7 +15315,7 @@ msgid "Geo|Primary node"
msgstr "Primære knudepunkt"
msgid "Geo|Primary site"
-msgstr ""
+msgstr "Primære websted"
msgid "Geo|Project"
msgstr "Projekt"
@@ -15200,7 +15324,7 @@ msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is sa
msgstr ""
msgid "Geo|Projects in certain groups"
-msgstr ""
+msgstr "Projekter i bestemte grupper"
msgid "Geo|Projects in certain storage shards"
msgstr ""
@@ -15284,7 +15408,7 @@ msgid "Geo|Secondary site"
msgstr "Sekundært websted"
msgid "Geo|Selective (%{syncLabel})"
-msgstr ""
+msgstr "Selektiv (%{syncLabel})"
msgid "Geo|Site's status was updated %{timeAgo}."
msgstr ""
@@ -15299,7 +15423,7 @@ msgid "Geo|Synced"
msgstr "Synkroniseret"
msgid "Geo|Synced at"
-msgstr ""
+msgstr "Synkroniseret kl."
msgid "Geo|Synchronization"
msgstr "Synkronisering"
@@ -15308,19 +15432,19 @@ msgid "Geo|Synchronization failed - %{error}"
msgstr "Synkronisering mislykkedes - %{error}"
msgid "Geo|Synchronization settings"
-msgstr ""
+msgstr "Synkroniseringsindstillinger"
msgid "Geo|Synchronization status"
-msgstr ""
+msgstr "Synkroniseringsstatus"
msgid "Geo|The database is currently %{db_lag} behind the primary site."
-msgstr ""
+msgstr "Databasen er i øjeblikket %{db_lag} bagefter det primære websted."
msgid "Geo|The site is currently %{minutes_behind} behind the primary site."
-msgstr "Webstedet er i øjeblikket %{minutes_behind} bag det primære websted."
+msgstr "Webstedet er i øjeblikket %{minutes_behind} bagefter det primære websted."
msgid "Geo|There are no %{replicable_type} to show"
-msgstr ""
+msgstr "Der er ingen %{replicable_type} at vise"
msgid "Geo|There was an error deleting the Geo Node"
msgstr "Der opstod en fejl under sletning af Geo-knudepunktet"
@@ -15383,7 +15507,7 @@ msgid "Geo|Verified"
msgstr "Verificeret"
msgid "Geo|Waiting for scheduler"
-msgstr ""
+msgstr "Venter på planlægger"
msgid "Geo|With GitLab Geo, you can install a special read-only and replicated instance anywhere. %{linkStart}Learn more%{linkEnd}"
msgstr ""
@@ -15404,7 +15528,7 @@ msgid "Geo|secondary"
msgstr "sekundær"
msgid "Get a free instance review"
-msgstr ""
+msgstr "FÃ¥ en gratis instanskontrol"
msgid "Get a support subscription"
msgstr "FÃ¥ et abonnement med support"
@@ -15449,7 +15573,7 @@ msgid "Git global setup"
msgstr ""
msgid "Git repository URL"
-msgstr ""
+msgstr "URL for Git-depot"
msgid "Git revision"
msgstr "Git-revision"
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr "GitLab-eksport"
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr "GitLab-projekteksport"
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr "GitLab bruger %{linkStart}Sidekiq%{linkEnd} til at behandle baggrundsjob
msgid "GitLab version"
msgstr "GitLab-version"
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -15646,10 +15773,10 @@ msgstr "Gem ændringer"
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr "Noget fik galt under indhentning af Let's Encrypt-certifikatet til %{domain}. Besøg dine %{link_start}domænedetaljer%{link_end} for at prøve igen."
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15689,7 +15816,7 @@ msgid "Gitaly|Address"
msgstr "Adresse"
msgid "Gitea Host URL"
-msgstr ""
+msgstr "URL for Gitea-vært"
msgid "Gitea Import"
msgstr "Gitea-import"
@@ -15697,9 +15824,12 @@ msgstr "Gitea-import"
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
-msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgid "GithubIntegration|Enable static status check names"
msgstr ""
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr "Indhent statusser for commits og pull-anmodninger."
+
msgid "GithubIntegration|Repository URL"
msgstr ""
@@ -15890,7 +16020,7 @@ msgid "Goal of the changes and what reviewers should be aware of"
msgstr "Målet for ændringerne og hvad kontrollanter skal være opmærksomme på"
msgid "Google Cloud"
-msgstr ""
+msgstr "Google Cloud"
msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr "Gruppeavatar"
msgid "Group by"
msgstr "Gruppér efter"
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr "Gruppebeskrivelse (valgfrit)"
@@ -16154,16 +16287,16 @@ msgid "GroupImport|Unable to process group import file"
msgstr ""
msgid "GroupPage|Copy group ID"
-msgstr ""
+msgstr "Kopiér gruppe-id"
msgid "GroupPage|Group ID: %{group_id}"
-msgstr ""
+msgstr "Gruppe-id: %{group_id}"
msgid "GroupRoadmap|%{dateWord} – No end date"
msgstr "%{dateWord} – ingen slutdato"
msgid "GroupRoadmap|%{startDateInWords} – %{endDateInWords}"
-msgstr ""
+msgstr "%{startDateInWords} – %{endDateInWords}"
msgid "GroupRoadmap|Loading epics"
msgstr "Indlæser epics"
@@ -16174,12 +16307,6 @@ msgstr "Ingen start- eller slutdato"
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr "Ingen startdato – %{dateWord}"
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "Noget gik galt under hentning af epics"
@@ -16373,7 +16500,7 @@ msgid "GroupSelect|No matching results"
msgstr ""
msgid "GroupSelect|Search groups"
-msgstr ""
+msgstr "Søg efter grupper"
msgid "GroupSelect|Select a group"
msgstr "Vælg en gruppe"
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr "Overholdelsesframeworks"
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16463,7 +16590,7 @@ msgid "GroupSettings|Prevent sharing a project within %{group} with other groups
msgstr "Forhindr deling af et projekt i %{group} med andre grupper"
msgid "GroupSettings|Prevents group members from being notified if the group is mentioned."
-msgstr ""
+msgstr "Forhindrer gruppemedlemmer i at blive underrettet hvis gruppen nævnes."
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. Inherited by subgroups."
msgstr ""
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr "Vælg en undergruppe som skal bruges som kilden til tilpassede projektskabeloner i gruppen."
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr "Ingen grupper fundet"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr "Headermeddelelse"
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr "Overskrift 1"
@@ -16769,7 +16905,7 @@ msgid "HelloMessage|Does this page need fixes or improvements? Open an issue or
msgstr ""
msgid "HelloMessage|Welcome to GitLab!"
-msgstr ""
+msgstr "Velkommen til GitLab!"
msgid "Help"
msgstr "Hjælp"
@@ -16781,7 +16917,7 @@ msgid "Helps prevent bots from creating accounts."
msgstr "Hjælper med at forhindre botter i at oprette kontoer."
msgid "Helps prevent bots from creating issues."
-msgstr ""
+msgstr "Hjælper med at forhindre botter i at oprette problemstillinger."
msgid "Helps prevent malicious users hide their activity."
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr "Skjul værdier"
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr "Højeste rolle:"
@@ -16860,7 +16993,7 @@ msgid "HighlightBar|Alert events:"
msgstr ""
msgid "HighlightBar|Alert start time:"
-msgstr ""
+msgstr "Starttidspunkt for alertbesked:"
msgid "HighlightBar|Original alert:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr "Historik"
msgid "History of authentications"
msgstr "Historik for godkendelser"
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr "URL for startside"
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr "Time (UTC)"
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr "Husarbejde"
@@ -16908,10 +17047,13 @@ msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "Husarbejde, eksport, sti, overfør, fjern, arkivér."
msgid "How do I configure Akismet?"
+msgstr "Hvordan konfigurerer jeg Akismet?"
+
+msgid "How do I configure authentication using the GitLab database?"
msgstr ""
msgid "How do I configure it?"
-msgstr ""
+msgstr "Hvordan konfigurerer jeg den?"
msgid "How do I configure runners?"
msgstr "Hvordan konfigurerer jeg runnere?"
@@ -16920,7 +17062,7 @@ msgid "How do I configure this integration?"
msgstr "Hvordan konfigurerer jeg integreringen?"
msgid "How do I generate it?"
-msgstr ""
+msgstr "Hvordan genererer jeg den?"
msgid "How do I mirror repositories?"
msgstr ""
@@ -16935,10 +17077,10 @@ msgid "How do I set up this service?"
msgstr "Hvordan opsætter jeg tjenesten?"
msgid "How do I use a web terminal?"
-msgstr ""
+msgstr "Hvordan bruger jeg er webterminal?"
msgid "How do I use file templates?"
-msgstr ""
+msgstr "Hvordan bruger jeg filskabeloner?"
msgid "How it works"
msgstr ""
@@ -17043,7 +17185,7 @@ msgid "IP address restrictions"
msgstr ""
msgid "IP addresses per user"
-msgstr ""
+msgstr "IP-adresser pr. bruger"
msgid "IP subnet restriction only allowed for top-level groups"
msgstr ""
@@ -17224,7 +17366,7 @@ msgid "Import from Jira"
msgstr "Importér fra Jira"
msgid "Import group"
-msgstr ""
+msgstr "Importér gruppe"
msgid "Import group from file"
msgstr "Importér gruppe fra fil"
@@ -17233,7 +17375,7 @@ msgid "Import groups"
msgstr "Importér grupper"
msgid "Import history"
-msgstr ""
+msgstr "Importér historik"
msgid "Import in progress"
msgstr "Import i gang"
@@ -17299,7 +17441,7 @@ msgid "Import timed out. Import took longer than %{import_jobs_expiration} secon
msgstr "Importen fik timeout. Importen tog længere end %{import_jobs_expiration} sekunder"
msgid "ImportAProjectModal|Import from a project"
-msgstr ""
+msgstr "Importér fra et projekt"
msgid "ImportAProjectModal|Import members from another project"
msgstr ""
@@ -17478,6 +17620,9 @@ msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
msgid "InProductMarketing|Do you have a minute?"
+msgstr "Har du et øjeblik?"
+
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
msgstr ""
msgid "InProductMarketing|Easy"
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr "Øg driftseffektivitet"
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr "Inviter dine kollegaer og begynd at sende kode hurtigere afsted."
@@ -17612,6 +17763,15 @@ msgstr "Inviter dit team nu"
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -17619,7 +17779,7 @@ msgid "InProductMarketing|It's also possible to simply %{external_repo_link} in
msgstr ""
msgid "InProductMarketing|Launch GitLab CI/CD in 20 minutes or less"
-msgstr ""
+msgstr "Start GitLab CI/CD på 20 minutter eller mindre"
msgid "InProductMarketing|Making the switch? It's easier than you think to import your projects into GitLab. Move %{github_link}, or import something %{bitbucket_link}."
msgstr ""
@@ -17634,7 +17794,7 @@ msgid "InProductMarketing|Multiple owners, confusing workstreams? We've got you
msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
-msgstr ""
+msgstr "Har du brug for et alternativ til at importere?"
msgid "InProductMarketing|Neutral"
msgstr ""
@@ -17844,10 +18004,10 @@ msgid "Incident template (optional)."
msgstr ""
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
-msgstr ""
+msgstr "%{hours} timer, %{minutes} minutter tilbage"
msgid "IncidentManagement|%{minutes} minutes remaining"
-msgstr ""
+msgstr "%{minutes} minutter tilbage"
msgid "IncidentManagement|Achieved SLA"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr "Nedarvet:"
msgid "Inline"
msgstr "Indlejret"
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr "Indtast værtsnøgler manuelt"
@@ -18226,6 +18389,9 @@ msgstr "Instansoversigt"
msgid "Insufficient permissions"
msgstr "Utilstrækkelige tilladelser"
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr "Integrering"
@@ -18265,6 +18431,9 @@ msgstr "Alle projekter som nedarver indstillingerne nulstilles også."
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr "Der opstod en fejl under indlæsning af projekter med tilpassede indstillinger."
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr "Browserbegrænsninger"
@@ -18380,7 +18549,7 @@ msgid "Integrations|Search Jira issues"
msgstr "Søg efter Jira-problemstillinger"
msgid "Integrations|Search ZenTao issues"
-msgstr ""
+msgstr "Søg efter ZenTao-problemstillinger"
msgid "Integrations|Send notifications about project events to Unify Circuit."
msgstr "Send underretninger om projektbegivenheder til Unify Circuit."
@@ -18448,6 +18617,9 @@ msgstr "Interne - projektet kan tilgås af brugere som er logget ind, undtagen e
msgid "Internal URL (optional)"
msgstr "Intern URL (valgfrit)"
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr "Interne brugere"
@@ -18523,9 +18695,6 @@ msgstr "Ugyldig pod_name"
msgid "Invalid policy type"
msgstr "Ugyldig regelsættype"
-msgid "Invalid query"
-msgstr "Ugyldig forespørgsel"
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18539,7 +18708,7 @@ msgid "Invalid server response"
msgstr "Ugyldigt serversvar"
msgid "Invalid start or end time format"
-msgstr ""
+msgstr "Ugyldigt format for start- og sluttidspunkt"
msgid "Invalid status"
msgstr "Ugyldig status"
@@ -18554,7 +18723,7 @@ msgid "Investigate vulnerability: %{title}"
msgstr ""
msgid "Invisible Captcha"
-msgstr ""
+msgstr "Usynlig Captcha"
msgid "Invisible Captcha helps prevent the creation of spam accounts. It adds a honeypot field and time-sensitive form submission to the account signup form."
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr "Du inviteres til at deltage i %{strong_start}%{project_or_group_name}%{s
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr "Du er blevet inviteret til at deltage i %{project_or_group_name} %{project_or_group} som en %{role}"
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr "Annuller"
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18677,7 +18858,7 @@ msgid "InviteMembersModal|Other"
msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
-msgstr ""
+msgstr "Søg efter en grupper som skal inviteres"
msgid "InviteMembersModal|Select a group to invite"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr "Vælg medlemmer eller skriv e-mailadresser"
msgid "InviteMembersModal|Something went wrong"
msgstr "Noget gik galt"
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr "Hvad vil du have nye medlemmer til at fokusere på? (valgfrit)"
@@ -18962,7 +19146,7 @@ msgid "IssueTracker|Issue URL"
msgstr "Problemstillings-URL"
msgid "IssueTracker|New issue URL"
-msgstr ""
+msgstr "URL for ny problemstilling"
msgid "IssueTracker|The URL to create an issue in the external issue tracker."
msgstr "URL'en til at oprette en problemstilling i den eksterne problemstillingsporing."
@@ -19013,7 +19197,7 @@ msgid "Issues"
msgstr "Problemstillinger"
msgid "Issues I've created"
-msgstr ""
+msgstr "Problemstillinger jeg har oprettet"
msgid "Issues Rate Limits"
msgstr ""
@@ -19022,7 +19206,7 @@ msgid "Issues and merge requests"
msgstr "Problemstillinger og sammenlægningsanmodninger"
msgid "Issues assigned to me"
-msgstr ""
+msgstr "Problemstillinger tildelt til mig"
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr ""
@@ -19136,7 +19320,7 @@ msgid "Iterations|Create cadence"
msgstr "Opret kadence"
msgid "Iterations|Create iteration"
-msgstr ""
+msgstr "Opret gennemløb"
msgid "Iterations|Delete cadence"
msgstr "Slet kadence"
@@ -19145,7 +19329,7 @@ msgid "Iterations|Delete iteration cadence?"
msgstr "Slet gennemløbskadence?"
msgid "Iterations|Delete iteration?"
-msgstr ""
+msgstr "Slet gennemløb?"
msgid "Iterations|Duration"
msgstr "Varighed"
@@ -19181,7 +19365,7 @@ msgid "Iterations|New iteration cadence"
msgstr "Ny gennemløbskadence"
msgid "Iterations|No closed iterations."
-msgstr ""
+msgstr "Ingen lukkede gennemløb."
msgid "Iterations|No iteration cadences to show."
msgstr "Ingen gennemløbskadencer at vise."
@@ -19190,7 +19374,7 @@ msgid "Iterations|No iterations in cadence."
msgstr "Ingen gennemløb i kadence."
msgid "Iterations|No open iterations."
-msgstr ""
+msgstr "Ingen åbne gennemløb."
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr "Startdato"
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr "Varigheden af hvert gennemløb (i uger)"
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
-msgstr "Der opstod en fejl under anmodning af data fra Jira. Tjek din konfiguration af Jira-integrering og prøv igen."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
+msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
-msgstr "Der opstod en fejl under anmodning af data fra Jira: %{messages}. Tjek din konfiguration af Jira-integrering og prøv igen."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
+msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19403,7 +19590,7 @@ msgid "JiraService|Issues created from vulnerabilities in this project will be J
msgstr ""
msgid "JiraService|Jira API URL"
-msgstr ""
+msgstr "URL for Jira API"
msgid "JiraService|Jira Issues"
msgstr "Jira-problemstillinger"
@@ -19508,7 +19695,7 @@ msgid "Job"
msgstr "Job"
msgid "Job %{jobName}"
-msgstr ""
+msgstr "Job %{jobName}"
msgid "Job Failed #%{build_id}"
msgstr ""
@@ -19663,6 +19850,12 @@ msgstr "med"
msgid "Join Zoom meeting"
msgstr "Deltag i Zoom-møde"
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr "Tilmeldt %{time_ago}"
@@ -19917,12 +20110,18 @@ msgstr "Sidst tilgået"
msgid "Last Activity"
msgstr "Sidste aktivitet"
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "Sidste pipeline"
msgid "Last Seen"
msgstr "Sidst set"
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr "Sidst brugt"
@@ -20017,7 +20216,7 @@ msgid "LastPushEvent|You pushed to"
msgstr ""
msgid "LastPushEvent|at"
-msgstr "kl."
+msgstr "hos"
msgid "Latest changes"
msgstr "Seneste ændringer"
@@ -20091,6 +20290,9 @@ msgstr "Lær mere om udsendelse til en klynge"
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr "Lær mere om shards og replikaer i dokumentationen %{configuration_link_start}konfiguration af avanceret søgning%{configuration_link_end}. Ændringerne ske ikke før indekset %{recreated_link_start}genoprettes%{recreated_link_end}."
@@ -20260,7 +20462,7 @@ msgid "LicenseCompliance|Add license and related policy"
msgstr ""
msgid "LicenseCompliance|Add license policy"
-msgstr ""
+msgstr "Tilføj licensregelsæt"
msgid "LicenseCompliance|Allow"
msgstr "Tillad"
@@ -20682,7 +20884,7 @@ msgid "MRDiff|Show changes only"
msgstr "Vis kun ændringer"
msgid "MRDiff|Show full file"
-msgstr ""
+msgstr "Vis hele filen"
msgid "Made this issue confidential."
msgstr "Gjorde problemstillingen fortrolig."
@@ -20714,8 +20916,11 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr "Gør problemstillingen fortrolig."
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
-msgstr "HÃ¥ndter Web IDE-funktioner."
+msgstr "HÃ¥ndter web-IDE-funktioner."
msgid "Manage access"
msgstr "HÃ¥ndter adgang"
@@ -20843,6 +21048,9 @@ msgstr "Tilføj kursiv tekst (%{modifier_key}I)"
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,11 +21138,8 @@ msgstr "Maks. rolle"
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr "MaxBuilds"
-
msgid "Maximum 20 characters"
-msgstr ""
+msgstr "Højest 20 tegn"
msgid "Maximum Conan package file size in bytes"
msgstr "Maksimale filstørrelse for Conan-pakke i byte"
@@ -21056,6 +21261,9 @@ msgstr "Maksimale filstørrelse for npm-pakke i byte"
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21090,7 +21301,7 @@ msgid "Maximum push size (MB)"
msgstr "Maksimale størrelse på push (MB)"
msgid "Maximum requests per minute"
-msgstr ""
+msgstr "Højeste anmodninger pr. minut"
msgid "Maximum running slices"
msgstr ""
@@ -21177,13 +21388,13 @@ msgid "Members of %{group} can also merge into this branch: %{branch}"
msgstr "Medlemmer af %{group} kan også sammenlægge i grenen: %{branch}"
msgid "Members of %{group} can also push to this branch: %{branch}"
-msgstr ""
+msgstr "Medlemmer af %{group} kan også bruge push til grenen: %{branch}"
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
msgid "Membership"
-msgstr ""
+msgstr "Medlemskab"
msgid "Members|%{time} by %{user}"
msgstr "%{time} af %{user}"
@@ -21192,7 +21403,7 @@ msgid "Members|%{userName} is currently an LDAP user. Editing their permissions
msgstr ""
msgid "Members|2FA"
-msgstr "2TG"
+msgstr "2FA"
msgid "Members|An error occurred while trying to enable LDAP override, please try again."
msgstr "Der opstod en fejl under forsøg på at aktivere LDAP-tilsidesættelse. Prøv venligst igen."
@@ -21276,7 +21487,7 @@ msgid "Members|Role updated successfully."
msgstr ""
msgid "Members|Search groups"
-msgstr ""
+msgstr "Søg efter grupper"
msgid "Members|Search invited"
msgstr ""
@@ -21326,9 +21537,12 @@ msgstr "Sammenlæg automatisk (%{strategy})"
msgid "Merge blocked: new changes were just added."
msgstr "Sammenlægning blokeret: nye ændringer blev netop tilføjet."
-msgid "Merge blocked: the source branch must be rebased onto the target branch."
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
msgstr ""
+msgid "Merge blocked: the source branch must be rebased onto the target branch."
+msgstr "Sammenlægning blokeret: kildegrenen skal rebases på målgrenen."
+
msgid "Merge commit SHA"
msgstr "Sammenlægningscommit-SHA"
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21378,7 +21595,7 @@ msgid "Merge requests"
msgstr "Sammenlægningsanmodninger"
msgid "Merge requests I've created"
-msgstr ""
+msgstr "Sammenlægningsanmodninger jeg har oprettet"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -21387,10 +21604,10 @@ msgid "Merge requests are read-only in a secondary Geo node"
msgstr ""
msgid "Merge requests assigned to me"
-msgstr ""
+msgstr "Sammenlægningsanmodninger tildelt til mig"
msgid "Merge requests that I'm a reviewer"
-msgstr ""
+msgstr "Sammenlægningsanmodninger hvor jeg er en kontrollant"
msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr "Pipelines"
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21453,7 +21679,7 @@ msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr "Der opstod en fejl under gemning af kladdekommentaren."
msgid "MergeRequests|Create issue to resolve thread"
-msgstr ""
+msgstr "Opret problemstilling for at løse alle tråde"
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr "Kunne ikke squash. Skal gøres manuelt."
@@ -21599,34 +21825,28 @@ msgstr "YAML-definition for målingsbetjeningspanel er gyldig."
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr "Annotering må ikke både tilhøre en klynge og et miljø på samme tid"
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr "Annotering er ikke blevet slettet"
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
-msgstr "Annotering skal tilhøre en klynge eller et miljø"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
-msgstr "Kan ikke finde betjeningspanel med anmodningssti"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
-msgstr "Du har ikke tilladelse til at oprette annotering for den valgte klynge"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
-msgstr "Du har ikke tilladelse til at oprette annotering for det valgte miljø"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
-msgstr "Du har ikke tilladelse til at slette annoteringen"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr "må ikke være før starting_at-tiden"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
+msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr "Kan ikke finde betjeningspanel med anmodningssti"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
+msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr "UTC (Coordinated Universal Time)"
msgid "MetricsSettings|User's local timezone"
msgstr "Brugerens lokale tidszone"
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr "Udfold panel"
msgid "Metrics|For grouping similar metrics"
msgstr "Til gruppering af lignende målinger"
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21812,7 +22035,7 @@ msgid "Metrics|Select a value"
msgstr "Vælg en værdi"
msgid "Metrics|Set refresh rate"
-msgstr ""
+msgstr "Indstil opdateringshastighed"
msgid "Metrics|Star dashboard"
msgstr "Stjernemarkér betjeningspanel"
@@ -21883,9 +22106,6 @@ msgstr "Vis dokumentation"
msgid "Metrics|View logs"
msgstr "Vis logge"
-msgid "Metrics|View runbook - %{label}"
-msgstr "Vis runbook - %{label}"
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -21908,7 +22128,7 @@ msgid "Metrics|e.g. Throughput"
msgstr ""
msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
+msgstr "f.eks. rate(http_requests_total[5m])"
msgid "Metrics|e.g. req/sec"
msgstr ""
@@ -21967,7 +22187,7 @@ msgid "MilestoneCombobox|Select milestone"
msgstr "Vælg milepæl"
msgid "MilestoneSidebar|Closed:"
-msgstr ""
+msgstr "Lukket:"
msgid "MilestoneSidebar|Copy reference"
msgstr ""
@@ -22276,7 +22496,7 @@ msgid "Moved issue to %{label} column in the board."
msgstr ""
msgid "Moved this issue to %{path_to_project}."
-msgstr ""
+msgstr "Flyttede problemstillingen til %{path_to_project}."
msgid "Moves issue to %{label} column in the board."
msgstr "Flytter problemstilling til kolonnen %{label} i tavlen."
@@ -22297,7 +22517,7 @@ msgid "Multi-project"
msgstr "Multiprojekt"
msgid "Multi-project Runners cannot be removed"
-msgstr ""
+msgstr "Multiprojekt-runnere kan ikke fjernes"
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr "Min fantastiske gruppe"
msgid "My company or team"
msgstr "Min virksomhed eller team"
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr "Min-reaktion"
@@ -22448,6 +22671,9 @@ msgstr "Behøver opmærksomhed"
msgid "Network"
msgstr "Netværk"
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22476,7 +22702,7 @@ msgid "NetworkPolicies|.yaml mode"
msgstr ".yaml-tilstand"
msgid "NetworkPolicies|Add alert"
-msgstr ""
+msgstr "Tilføj alertbesked"
msgid "NetworkPolicies|Alerts are intended to be selectively used for a limited number of events that are potentially concerning and warrant a manual review. Alerts should not be used as a substitute for a SIEM or a logging tool. High volume alerts are likely to be dropped so as to preserve the stability of GitLab's integration with Kubernetes."
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr "Afvis al trafik"
msgid "NetworkPolicies|Edit policy"
msgstr "Rediger regelsæt"
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22745,7 +22968,7 @@ msgid "New group URL"
msgstr "URL for ny gruppe"
msgid "New group name"
-msgstr "Navn for ny gruppe"
+msgstr "Nyt gruppenavn"
msgid "New health check access token has been generated!"
msgstr ""
@@ -22757,7 +22980,7 @@ msgid "New issue"
msgstr "Ny problemstilling"
msgid "New issue in %{project}"
-msgstr ""
+msgstr "Ny problemstilling i %{project}"
msgid "New issue title"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr "Nyt mærkat"
msgid "New test case"
msgstr "Ny testsag"
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,8 +23165,8 @@ msgstr "Ingen overholdelsesframeworks er i brug."
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
-msgstr "Ikke modtaget nogle bekræftelses e-mail? Tjek venligst din spammappe eller"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
+msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Der kunne ikke oprettes forbindelse til a Gitaly-server. Tjek venligst dine logge!"
@@ -22954,6 +23180,9 @@ msgstr "Ingen bidrag"
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr "Ingen sårbarheder tilstede"
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr "Ingen webhooks fundet, tilføj en i formularen ovenover."
@@ -23173,7 +23405,7 @@ msgid "Nodes"
msgstr "Knudepunkter"
msgid "Non-admin users are restricted to read-only access, in both GitLab UI and API."
-msgstr ""
+msgstr "Brugere som ikke er administratorer er begrænset til skrivebeskyttet adgang i både GitLab-brugerflade og -API."
msgid "None"
msgstr "Ingen"
@@ -23205,9 +23437,6 @@ msgstr "Ikke tilgængelig for private projekter"
msgid "Not available for protected branches"
msgstr "Ikke tilgængelig for beskyttede grene"
-msgid "Not available to run jobs."
-msgstr "Ikke tilgængelig til at køre job."
-
msgid "Not confidential"
msgstr "Ikke fortrolig"
@@ -23364,7 +23593,7 @@ msgid "NotificationEvent|New release"
msgstr "Ny udgivelse"
msgid "NotificationEvent|Push to merge request"
-msgstr ""
+msgstr "Push for at sammenlægge anmodning"
msgid "NotificationEvent|Reassign issue"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr "Antal LOC'er pr. commit"
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr "Antal commits"
msgid "Number of commits per MR"
msgstr "Antal commits pr. sammenlægningsanmodning"
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr "Antal begivenheder"
@@ -23504,9 +23730,6 @@ msgstr "Ældste først"
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr "Til"
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr "Skannerprofil"
@@ -23745,6 +23980,9 @@ msgid "OnDemandScans|Site profile"
msgstr ""
msgid "OnDemandScans|Start time"
+msgstr "Starttidspunkt"
+
+msgid "OnDemandScans|Target"
msgstr ""
msgid "OnDemandScans|Use existing scanner profile"
@@ -23837,7 +24075,7 @@ msgid "Only projects created under a Ultimate license are available in Security
msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
-msgstr ""
+msgstr "Kun reCAPTCHA v2 understøttes:"
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr "Ã…bn markering"
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr "Ã…bne epics"
msgid "Open errors"
msgstr "Ã…bne fejl"
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr "Ã…bn i filvisning"
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr "Valgfrit"
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr "Valgmuligheder"
msgid "Or you can choose one of the suggested colors below"
msgstr "Eller du kan vælge en af de foreslåede farver nedenunder"
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr "Forælderløst medlem"
@@ -24025,6 +24266,36 @@ msgstr "Ejet af:"
msgid "Owner"
msgstr "Ejer"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr "Pakkeregister"
@@ -24100,9 +24371,6 @@ msgstr "Tilføj composer-register"
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr "Der opstod en fejl under gemning af indstillingerne"
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24182,7 +24450,7 @@ msgid "PackageRegistry|Copy require package include"
msgstr ""
msgid "PackageRegistry|Copy target SHA"
-msgstr ""
+msgstr "Kopiér mål-SHA"
msgid "PackageRegistry|Copy yarn command"
msgstr "Kopiér yarn-kommando"
@@ -24251,7 +24519,7 @@ msgid "PackageRegistry|Install package version"
msgstr "Installer pakkeversion"
msgid "PackageRegistry|Instance-level"
-msgstr ""
+msgstr "Instansniveau"
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr "NuGet-kommando"
msgid "PackageRegistry|Package Registry"
msgstr "Pakkeregister"
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr "Pakke har %{number} arkiverede opdateringer"
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr "Indstillinger for generiske pakker"
msgid "PackageRegistry|Settings for Maven packages"
msgstr "Indstillinger for Maven-pakker"
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr "Vis Composer-kommandoer"
@@ -24368,7 +24635,7 @@ msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
msgid "PackageRegistry|Target SHA: %{sha}"
-msgstr ""
+msgstr "MÃ¥l-SHA: %{sha}"
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -24527,7 +24794,7 @@ msgid "Password (optional)"
msgstr "Adgangskode (valgfrit)"
msgid "Password authentication is unavailable."
-msgstr ""
+msgstr "Adgangskodegodkendelse er utilgængelig."
msgid "Password confirmation"
msgstr "Bekræftelse af adgangskode"
@@ -24539,19 +24806,19 @@ msgid "Password was successfully updated. Please sign in again."
msgstr "Adgangskode blev opdateret. Log venligst ind igen."
msgid "PasswordPrompt|Confirm password"
-msgstr ""
+msgstr "Bekræft adgangskode"
msgid "PasswordPrompt|Confirm password to continue"
msgstr ""
msgid "PasswordPrompt|Password is required"
-msgstr ""
+msgstr "Adgangskode kræves"
msgid "PasswordPrompt|Please enter your password to confirm"
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
-msgstr ""
+msgstr "Adgangskoder skal være unikke og ikke være brugt på andre websteder eller tjenester."
msgid "Past due"
msgstr "Overskredet"
@@ -24595,6 +24862,9 @@ msgstr "Sti:"
msgid "Paths can contain wildcards, like */welcome"
msgstr "Stier kan indeholde jokertegn såsom */velkommen"
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr "Pause"
@@ -24616,6 +24886,9 @@ msgstr "Afventende"
msgid "Pending comments"
msgstr "Afventende kommentarer"
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr "Afventer synkronisering …"
@@ -24701,13 +24974,13 @@ msgid "PerformanceBar|Trace"
msgstr "Trace"
msgid "PerformanceBar|cpu"
-msgstr ""
+msgstr "cpu"
msgid "PerformanceBar|object"
-msgstr ""
+msgstr "objekt"
msgid "PerformanceBar|wall"
-msgstr ""
+msgstr "væg"
msgid "Period in seconds"
msgstr "Periode i sekunder"
@@ -24749,7 +25022,7 @@ msgid "Phabricator Server Import"
msgstr ""
msgid "Phabricator Server URL"
-msgstr ""
+msgstr "URL for Phabricator-server"
msgid "Phabricator Tasks"
msgstr "Phabricator-opgaver"
@@ -24938,19 +25211,19 @@ msgid "PipelineSchedules|Variables"
msgstr "Variabler"
msgid "PipelineSource|API"
-msgstr ""
+msgstr "API"
msgid "PipelineSource|Chat"
-msgstr ""
+msgstr "Chat"
msgid "PipelineSource|External"
-msgstr ""
+msgstr "Ekstern"
msgid "PipelineSource|External Pull Request"
-msgstr ""
+msgstr "Ekstern pull-anmodning"
msgid "PipelineSource|Merge Request"
-msgstr ""
+msgstr "Sammenlægningsanmodning"
msgid "PipelineSource|On-Demand DAST Scan"
msgstr ""
@@ -24962,22 +25235,22 @@ msgid "PipelineSource|Parent Pipeline"
msgstr ""
msgid "PipelineSource|Pipeline"
-msgstr ""
+msgstr "Pipeline"
msgid "PipelineSource|Push"
-msgstr ""
+msgstr "Push"
msgid "PipelineSource|Schedule"
-msgstr ""
+msgstr "Planlægning"
msgid "PipelineSource|Trigger"
-msgstr ""
+msgstr "Udløser"
msgid "PipelineSource|Web"
-msgstr ""
+msgstr "Web"
msgid "PipelineSource|Web IDE"
-msgstr ""
+msgstr "Web-IDE"
msgid "PipelineStatusTooltip|Pipeline: %{ciStatus}"
msgstr "Pipeline: %{ciStatus}"
@@ -25123,6 +25396,9 @@ msgstr "Der er i øjeblikket ingen færdige pipelines."
msgid "Pipelines|There are currently no pipelines."
msgstr "Der er i øjeblikket ingen pipelines."
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "Der opstod en fejl under hentning af pipelinesne. Prøv igen om lidt eller kontakt dit supportteam."
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25280,7 +25559,7 @@ msgid "Pipeline|Source"
msgstr "Kilde"
msgid "Pipeline|Source|Security Policy"
-msgstr ""
+msgstr "Sikkerhedsregelsæt"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default."
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr "Ren diff"
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr "Plan:"
@@ -25367,7 +25649,7 @@ msgid "PlantUML"
msgstr "PlantUML"
msgid "PlantUML URL"
-msgstr ""
+msgstr "URL for PlantUML"
msgid "Play"
msgstr "Afspil"
@@ -25462,9 +25744,15 @@ msgstr "Indtast venligst et gyldigt tal"
msgid "Please enter or upload a valid license."
msgstr "Indtast eller upload venligst en gyldig licens."
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Udfyld venligst med et beskrivende navn på dit gruppe."
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr "Udfyld venligst feltet."
@@ -25609,6 +25897,9 @@ msgstr "Postman-samling"
msgid "Postman collection file path or URL"
msgstr "Filsti eller URL for Postman-samling"
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25679,7 +25970,7 @@ msgid "Preferences|Project overview content"
msgstr "Indhold for projektoversigt"
msgid "Preferences|Render whitespace characters in the Web IDE"
-msgstr "Gengiv blanktegn i Web IDE"
+msgstr "Gengiv blanktegn i web-IDE"
msgid "Preferences|Show one file at a time on merge request's Changes tab"
msgstr "Vis én fil ad gangen i sammenlægningsanmodningens Ændringer-faneblad"
@@ -25724,13 +26015,13 @@ msgid "Prevent adding new members to project membership within this group"
msgstr ""
msgid "Prevent auto-stopping"
-msgstr ""
+msgstr "Forhindr automatisk stop"
msgid "Prevent editing approval rules in projects and merge requests."
msgstr "Forhindr redigering af godkendelsesregler i projekter og sammenlægningsanmodninger."
msgid "Prevent environment from auto-stopping"
-msgstr "Forhindr miljø i at stoppe automatisk"
+msgstr "Forhindr automatisk stop af miljø"
msgid "Prevent project forking outside current group"
msgstr ""
@@ -25885,24 +26176,27 @@ msgstr "Profil"
msgid "Profile Settings"
msgstr "Profilindstillinger"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr "Profilside:"
-msgid "ProfileSession|on"
+msgid "Profile parameter missing"
msgstr ""
+msgid "ProfileSession|on"
+msgstr "på"
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr " Du er ved at slette %{yourAccount} og alle de problemstillinger, sammenlægningsanmodninger og grupper som er linket til din konto permanent. Når du har bekræftet %{deleteAccount}, så kan det ikke fortrydes eller gendannes."
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr " Du er ved at ændre brugernavnet %{currentUsernameBold} til %{newUsernameBold}. Profil og projekter vil blive omdirigeret til navnerummet %{newUsername} men omdirigeringen udløber når navnerummet %{currentUsername} registreres af en anden bruger eller gruppe. Opdater venligst dit Git-depotremotes så snart som muligt."
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr "\"Optaget\" vises ved siden af dit navn"
-
msgid "Profiles|%{provider} Active"
msgstr "%{provider} aktiv"
@@ -25930,6 +26224,9 @@ msgstr "Tilføj statusemoji"
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr "Der opstod en fejl under opdatering af dit brugernavn. Prøv venligst igen."
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr "Beskæring af avatar"
@@ -25961,7 +26258,7 @@ msgid "Profiles|Clear status"
msgstr "Ryd status"
msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr "Klik på ikonet for at aktivere indlogning med en af følgende tjenester"
+msgstr "Klik på et ikon for at aktivere indlogning med en af følgende tjenester"
msgid "Profiles|Commit email"
msgstr ""
@@ -26051,7 +26348,7 @@ msgid "Profiles|Incoming email token was successfully reset"
msgstr ""
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
-msgstr "Forbedr sikkerheden på din konto ved at aktivere totrinsgodkendelse (2TG)"
+msgstr "Forbedr sikkerheden på din konto ved at aktivere totrinsgodkendelse (2FA)"
msgid "Profiles|Invalid key."
msgstr "Ugyldig nøgle."
@@ -26221,6 +26518,9 @@ msgstr "Du kan uploade din avatar her eller ændre den på %{gravatar_link}"
msgid "Profiles|You don't have access to delete this user."
msgstr "Du har ikke adgang til at slette brugeren."
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26249,7 +26549,7 @@ msgid "Profiles|e.g. My MacBook key"
msgstr "f.eks. Min MacBook-nøgle"
msgid "Profiles|https://website.com"
-msgstr ""
+msgstr "https://website.com"
msgid "Profiles|username"
msgstr "brugernavn"
@@ -26495,7 +26795,7 @@ msgid "ProjectSelect| or group"
msgstr " eller gruppe"
msgid "ProjectSelect|No matching results"
-msgstr ""
+msgstr "Ingen matchende resultater"
msgid "ProjectSelect|Search for project"
msgstr "Søg efter projekt"
@@ -26504,7 +26804,7 @@ msgid "ProjectSelect|Search projects"
msgstr ""
msgid "ProjectSelect|Select a project"
-msgstr ""
+msgstr "Vælg et projekt"
msgid "ProjectSelect|There was an error fetching the projects. Please try again."
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr "Indtast ny adgangskode"
msgid "ProjectService|Enter new password."
msgstr "Indtast ny adgangskode."
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr "Git Large File Storage (LFS)"
msgid "ProjectSettings|Global"
msgstr "Globalt"
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "Internt"
@@ -26731,6 +27040,9 @@ msgstr "Problemstillinger"
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr "LFS-objekter fra depotet er tilgængelige til forgreninger. %{linkStart}Hvordan fjerner jeg dem?%{linkEnd}"
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26831,7 +27143,7 @@ msgid "ProjectSettings|Skipped pipelines are considered successful"
msgstr ""
msgid "ProjectSettings|Snippets"
-msgstr "Snippets"
+msgstr "Udklip"
msgid "ProjectSettings|Squash commits when merging"
msgstr "Squash commits når der sammenlægges"
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr "Visualiser projektets ydelsesmålinger."
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr "Hvad er badges?"
@@ -26998,6 +27313,9 @@ msgstr "Spring"
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr "Editor til statisk websted/Middleman"
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
@@ -27014,7 +27332,7 @@ msgid "Projects are graded based on the highest severity vulnerability present"
msgstr ""
msgid "Projects are organized into groups"
-msgstr ""
+msgstr "Projekter organiseres i grupper"
msgid "Projects contributed to"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr "Opret nyt projekt"
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr "Importér"
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "Projektbeskrivelse %{tag_start}(valgfrit)%{tag_end}"
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr "Prometheus"
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr "%{count} alertbeskeder anvendt"
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr "Tilføj alertbesked"
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr "Rediger alertbesked"
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr "Fejl ved oprettelse af alertbesked"
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr "Fejl ved sletning af alertbesked"
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr "Fejl ved hentning af alertbesked"
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr "Fejl ved gemning af alertbesked"
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr "Runbook-URL (valgfrit)"
-
-msgid "PrometheusAlerts|Select query"
-msgstr "Vælg forespørgsel"
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr "https://gitlab.com/gitlab-com/runbooks"
-
msgid "PrometheusAlerts|is equal to"
msgstr "er lig med"
@@ -27487,9 +27769,6 @@ msgstr "Beskyttede grene"
msgid "Protected Environment"
msgstr "Beskyttet miljø"
-msgid "Protected Paths"
-msgstr "Beskyttede stier"
-
msgid "Protected Paths: requests"
msgstr "Beskyttede stier: anmodninger"
@@ -27505,6 +27784,9 @@ msgstr "Beskyttede grene"
msgid "Protected environments"
msgstr "Beskyttede miljøer"
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr "%{wildcards_link_start}Jokertegn%{wildcards_link_end} såsom %{code_tag_start}*-stable%{code_tag_end} eller %{code_tag_start}production/*%{code_tag_end} understøttes."
@@ -27581,7 +27863,7 @@ msgid "ProtectedBranch|Toggle code owner approval"
msgstr "Kodeejergodkendelse til/fra"
msgid "ProtectedBranch|What are protected branches?"
-msgstr ""
+msgstr "Hvad er beskyttede grene?"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} vil være skrivbar for udviklere. Er du sikker?"
@@ -27643,6 +27925,9 @@ msgstr "Hvad er beskyttede mærkater?"
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr "Protip: %{linkStart}Auto DevOps%{linkEnd} bruger Kubernetes-klynger til at udsende din kode!"
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr "Udbyder"
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27692,10 +27980,10 @@ msgid "Publishes this issue to the associated status page."
msgstr "Udgiver problemstillingen til den tilknyttede statusside."
msgid "Pull"
-msgstr ""
+msgstr "Pull"
msgid "Pull requests from fork are not supported"
-msgstr ""
+msgstr "Pull-anmodninger fra forgrening understøttes ikke"
msgid "Puma is running with a thread count above 1 and the Rugged service is enabled. This may decrease performance in some environments. See our %{link_start}documentation%{link_end} for details of this issue."
msgstr ""
@@ -27710,22 +27998,22 @@ msgid "PurchaseStep|An error occured in the purchase step. If the problem persis
msgstr ""
msgid "Push"
-msgstr ""
+msgstr "Push"
msgid "Push Rule updated successfully."
-msgstr ""
+msgstr "Push-regel opdateret."
msgid "Push Rules"
-msgstr ""
+msgstr "Push-regler"
msgid "Push Rules updated successfully."
-msgstr ""
+msgstr "Push-regler opdateret."
msgid "Push an existing Git repository"
-msgstr ""
+msgstr "Push et eksisterende Git-depot"
msgid "Push an existing folder"
-msgstr ""
+msgstr "Push en eksisterende mappe"
msgid "Push commits to the source branch or add previously merged commits to review them."
msgstr ""
@@ -27734,13 +28022,13 @@ msgid "Push events"
msgstr "Push-begivenheder"
msgid "Push project from command line"
-msgstr ""
+msgstr "Push projekt fra kommandolinje"
msgid "Push the result of the merge to GitLab"
msgstr ""
msgid "Push to create a project"
-msgstr ""
+msgstr "Push for at oprette et projekt"
msgid "PushRules|All branch names must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any branch name is allowed."
msgstr ""
@@ -27773,16 +28061,16 @@ msgid "PushRules|Restrict push operations for this project."
msgstr ""
msgid "PushRules|Save push rules"
-msgstr ""
+msgstr "Gem push-regler"
msgid "PushRules|Select push rules"
-msgstr ""
+msgstr "Vælg push-regler"
msgid "PushRules|Users can still delete tags through the GitLab UI."
msgstr ""
msgid "PushRule|Push rules"
-msgstr ""
+msgstr "Push-regler"
msgid "PushRule|Reject unverified users"
msgstr ""
@@ -27794,7 +28082,7 @@ msgid "Pushes"
msgstr ""
msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
-msgstr ""
+msgstr "%{user_name} slettede grenen \"%{ref}\"."
msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr "Forespørgsel"
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr "Forespørgslen er ugyldig"
-
msgid "Queued"
msgstr "Sat i kø"
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27893,7 +28181,7 @@ msgid "Re-authentication required"
msgstr ""
msgid "Re-import"
-msgstr ""
+msgstr "Genimportér"
msgid "Re-request review"
msgstr ""
@@ -27917,7 +28205,7 @@ msgid "Read more about related issues"
msgstr "Læs mere om relaterede problemstillinger"
msgid "Read their documentation."
-msgstr ""
+msgstr "Læs deres dokumentation."
msgid "Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project."
msgstr "Klar til at komme i gang med GitLab? Følg trinnene for at opsætte dit arbejdsområde, planlægge og committe ændringer, og udsende dit projekt."
@@ -27938,13 +28226,13 @@ msgid "Rebase in progress"
msgstr "Rebase i gang"
msgid "Rebase source branch"
-msgstr ""
+msgstr "Rebase kildegren"
msgid "Rebase source branch on the target branch."
msgstr "Rebase kildegren på målgrenen."
msgid "Recaptcha verified?"
-msgstr ""
+msgstr "Recaptcha verificeret?"
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -27956,7 +28244,7 @@ msgid "Receive notification of abuse reports by email."
msgstr ""
msgid "Receive notifications about your own activity"
-msgstr ""
+msgstr "Modtag underretninger om din egen aktivitet"
msgid "Receive product marketing emails"
msgstr "Modtag e-mails om markedsføring af produkter"
@@ -27964,15 +28252,15 @@ msgstr "Modtag e-mails om markedsføring af produkter"
msgid "Recent"
msgstr "Seneste"
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28057,7 +28345,7 @@ msgid "Register / Sign In"
msgstr "Tilmeld/log ind"
msgid "Register Two-Factor Authenticator"
-msgstr ""
+msgstr "Tilmeld totrinsgodkendelse"
msgid "Register Universal Two-Factor (U2F) Device"
msgstr "Tilmeld U2F-enhed (Universal Two-Factor)"
@@ -28194,7 +28482,7 @@ msgid "Release|Something went wrong while saving the release details."
msgstr "Noget gik galt under gemning af udgivelsesdetaljerne."
msgid "Reload page"
-msgstr ""
+msgstr "Genindlæs side"
msgid "Remediations"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr "Forny abonnement"
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr "Genåbn"
@@ -28479,7 +28770,7 @@ msgid "Reopens this %{quick_action_target}."
msgstr "Genåbner denne %{quick_action_target}."
msgid "Repeats"
-msgstr ""
+msgstr "Gentager"
msgid "Replace"
msgstr "Erstat"
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "Anmod om adgang"
@@ -28795,9 +29089,6 @@ msgstr "Anmod om en ny"
msgid "Request details"
msgstr "Anmodningsdetaljer"
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr "Anmodningsparameteren %{param} mangler."
@@ -28876,13 +29167,13 @@ msgstr "Krav"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -28920,7 +29211,7 @@ msgid "Reset authorization key"
msgstr ""
msgid "Reset authorization key?"
-msgstr ""
+msgstr "Nulstil godkendelsesnøgle?"
msgid "Reset filters"
msgstr "Nulstil filtre"
@@ -29010,7 +29301,7 @@ msgid "Response text"
msgstr "Svartekst"
msgid "Restart GitLab to apply changes."
-msgstr ""
+msgstr "Genstart GitLab for at anvende ændringer."
msgid "Restart Terminal"
msgstr "Genstart terminal"
@@ -29090,7 +29381,7 @@ msgid "Review App|View latest app"
msgstr ""
msgid "Review changes"
-msgstr ""
+msgstr "Kontrollér ændringer"
msgid "Review requested from %{name}"
msgstr ""
@@ -29128,10 +29419,10 @@ msgid "Reviewers"
msgstr "Kontrollanter"
msgid "Reviewing"
-msgstr "Kontrollerer"
+msgstr "Kontrollering"
msgid "Reviewing (merge request !%{mergeRequestId})"
-msgstr "Kontrollerer (sammenlægningsanmodning !%{mergeRequestId})"
+msgstr "Kontrollering (sammenlægningsanmodning !%{mergeRequestId})"
msgid "Revoke"
msgstr "Tilbagekald"
@@ -29229,9 +29520,6 @@ msgstr "Runnere"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr "Arkitektur"
msgid "Runners|Are you sure you want to delete this runner?"
msgstr "Er du sikker på, at du vil slette runneren?"
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr "Udsend GitLab Runner i AWS"
@@ -29316,6 +29616,9 @@ msgstr "Ny registreringstoken genereret!"
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr "Egenskabsnavn"
msgid "Runners|Protected"
msgstr "Beskyttet"
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr "Revision"
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr "Noget gik galt under hentning af runnerdata."
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr "Du kan opsat en bestemt runner til at blive brugt af flere projekter men du kan ikke gøre den til en delt runner."
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr "Kører"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "Kører nogle husarbejdeopgaver i det nuværende depot såsom komprimering af filrevisioner og fjernelse af objekter som ikke kan nås."
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr "Kører job fra alle utildelte projekter."
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr "SAML"
@@ -29557,7 +29875,7 @@ msgid "SastEntryPoints|How do I set up SAST?"
msgstr "Hvordan opsætter jeg SAST?"
msgid "SastEntryPoints|Learn more"
-msgstr ""
+msgstr "Lær mere"
msgid "Satisfied"
msgstr "Opfyldt"
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr "Gem ændringer"
-msgid "Save Value Stream"
-msgstr "Gem Value Stream"
-
msgid "Save application"
msgstr "Gem program"
@@ -29773,7 +30088,7 @@ msgid "Search or filter results…"
msgstr "Søg efter eller filtrér resultater …"
msgid "Search or jump to..."
-msgstr ""
+msgstr "Søg eller hop til ..."
msgid "Search project"
msgstr "Søg efter projekt"
@@ -29833,7 +30148,7 @@ msgid "SearchAutocomplete|in project %{projectName}"
msgstr "i projektet %{projectName}"
msgid "SearchCodeResults|of %{link_to_project}"
-msgstr ""
+msgstr "af %{link_to_project}"
msgid "SearchResults|Showing %{count} %{scope} for %{term_element}"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] "wikiresultater"
msgid "Searching by both author and message is currently not supported."
msgstr "Søgning efter både forfatter og meddelelse understøttes ikke i øjeblikket."
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -29927,7 +30245,7 @@ msgid "Secret Detection"
msgstr ""
msgid "Secret access key"
-msgstr ""
+msgstr "Hemmelig adgangsnøgle"
msgid "Secret token"
msgstr "Hemmelig token"
@@ -30014,7 +30332,7 @@ msgid "SecurityConfiguration|Compliance"
msgstr ""
msgid "SecurityConfiguration|Configuration guide"
-msgstr ""
+msgstr "Konfigurationsvejledning"
msgid "SecurityConfiguration|Configuration history"
msgstr "Konfigurationshistorik"
@@ -30116,30 +30434,33 @@ msgid "SecurityOrchestration|Action"
msgstr ""
msgid "SecurityOrchestration|Actions"
-msgstr ""
+msgstr "Handlinger"
msgid "SecurityOrchestration|Add rule"
-msgstr ""
+msgstr "Tilføj regel"
msgid "SecurityOrchestration|All policies"
-msgstr ""
+msgstr "Alle regelsæt"
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
msgid "SecurityOrchestration|Description"
+msgstr "Beskrivelse"
+
+msgid "SecurityOrchestration|Disabled"
msgstr ""
msgid "SecurityOrchestration|Edit policy"
-msgstr ""
+msgstr "Rediger regelsæt"
msgid "SecurityOrchestration|Edit policy project"
-msgstr ""
+msgstr "Rediger regelsætprojekt"
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30149,40 +30470,40 @@ msgid "SecurityOrchestration|If you are using Auto DevOps, your %{monospacedStar
msgstr ""
msgid "SecurityOrchestration|Latest scan"
-msgstr ""
+msgstr "Seneste skanning"
msgid "SecurityOrchestration|Network"
-msgstr ""
+msgstr "Netværk"
msgid "SecurityOrchestration|New policy"
-msgstr ""
+msgstr "Nyt regelsæt"
msgid "SecurityOrchestration|Only owners can update Security Policy Project"
msgstr "Kun ejere kan opdatere sikkerhedsregelsætprojekt"
msgid "SecurityOrchestration|Policies"
-msgstr ""
+msgstr "Regelsæt"
msgid "SecurityOrchestration|Policy description"
-msgstr ""
+msgstr "Regelsætbeskrivelse"
msgid "SecurityOrchestration|Policy editor"
-msgstr ""
+msgstr "Regelsæteditor"
msgid "SecurityOrchestration|Policy preview"
msgstr ""
msgid "SecurityOrchestration|Policy status"
-msgstr ""
+msgstr "Regelsætstatus"
msgid "SecurityOrchestration|Policy type"
msgstr "Regelsættype"
msgid "SecurityOrchestration|Rule"
-msgstr ""
+msgstr "Regel"
msgid "SecurityOrchestration|Rules"
-msgstr ""
+msgstr "Regler"
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr "Skanning som skal udføres hvert %{cadence} på %{branches}"
@@ -30208,6 +30532,9 @@ msgstr "Vælg sikkerhedsprojekt"
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr "Beklager, dit filter gav ingen resultater."
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30221,7 +30548,7 @@ msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
msgid "SecurityOrchestration|view results"
-msgstr ""
+msgstr "vis resultater"
msgid "SecurityOrhestration|No rules defined - policy will not run."
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr "Opret Jira-problemstilling"
msgid "SecurityReports|Create issue"
msgstr "Opret problemstilling"
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr "Download resultater"
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr "Download skannede ressourcer"
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr "Lær mere om at opsætte dit betjeningspanel"
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr "Overvåg sårbarheder i alle dine projekter"
@@ -30373,6 +30712,9 @@ msgstr "Ingen sårbarheder fundet for pipelinen"
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr "Projekt"
@@ -30458,7 +30800,7 @@ msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
msgid "SecurityReports|Tool"
-msgstr ""
+msgstr "Værktøj"
msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr "Din feedback er vigtig for os! Vi spørger igen om en uge."
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,12 +30880,12 @@ msgstr "Vælg side"
msgid "Select a branch"
msgstr "Vælg en gren"
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "Vælg en fil i den venstre sidebjælke for at begynde redigering. Herefter vil du være i stand til at committe dine ændringer."
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
-msgstr ""
-
msgid "Select a group to invite"
msgstr "Vælg en gruppe som skal inviteres"
@@ -30556,15 +30901,9 @@ msgstr "Vælg et nyt navnerum"
msgid "Select a project"
msgstr "Vælg et projekt"
-msgid "Select a project to read Insights configuration file"
-msgstr "Vælg et projekt for at læse Insights-konfigurationsfilen"
-
msgid "Select a reason"
msgstr "Vælg en årsag"
-msgid "Select a repository"
-msgstr "Vælg et depot"
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30695,7 +31034,7 @@ msgid "Selected commits"
msgstr "Valgte commits"
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
-msgstr ""
+msgstr "Valgte niveauer kan ikke bruges af brugere som ikke er administratorer for grupper, projekter og udklip. Hvis det offentlige niveau er begrænset, så er brugerprofiler kun synlige for brugere som er logget ind."
msgid "Selected projects"
msgstr "Valgte projekter"
@@ -30788,10 +31127,10 @@ msgid "Send service data"
msgstr "Send tjenestedata"
msgid "Sentry"
-msgstr ""
+msgstr "Sentry"
msgid "Sentry API URL"
-msgstr ""
+msgstr "URL for Sentry API"
msgid "Sentry event"
msgstr "Sentry-begivenhed"
@@ -30823,9 +31162,6 @@ msgstr "Serverversion"
msgid "Serverless"
msgstr "Serverfri"
-msgid "Serverless domain"
-msgstr "Serverfrit domæne"
-
msgid "Serverless platform"
msgstr "Serverfri platform"
@@ -30925,9 +31261,6 @@ msgstr "Aktivér serviceskranke"
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr "Kontakt venligst en administrator for at få hjælp med at opsætning serviceskranken til din instans."
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr "Problemstillinger som er oprettet med e-mails fra serviceskranken vises her. Hver kommentar bliver en del af e-mail-samtalen."
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr "Problemstillinger som er oprettet med e-mails fra serviceskranken vises her. Hver kommentar bliver en del af e-mail-samtalen."
@@ -30982,9 +31315,6 @@ msgstr "Indstil en adgangskode på din konto for at bruge pull eller push via %{
msgid "Set access permissions for this token."
msgstr "Indstil adgangstilladelser for tokenen."
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr "Opsæt Jira-integrering"
msgid "Set up a %{type} Runner for a project"
msgstr "Opsæt en %{type}-runner til et projekt"
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,12 +31438,12 @@ msgstr "Indstil hvad der skal replikeres af det sekundære websted."
msgid "SetPasswordToCloneLink|set a password"
msgstr "indstil en adgangskode"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
-msgstr "En optaget-indikator vises ved siden af dit navn og avatar."
-
msgid "SetStatusModal|Add status emoji"
msgstr "Tilføj statusemoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "SetStatusModal|Busy"
msgstr "Optaget"
@@ -31180,6 +31507,11 @@ msgstr "Indstilling"
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31259,7 +31591,7 @@ msgid "Show Pipeline IID"
msgstr "Vis pipeline-iid"
msgid "Show all %{issuable_type}."
-msgstr ""
+msgstr "Vis alle %{issuable_type}."
msgid "Show all activity"
msgstr "Vis al aktivitet"
@@ -31325,10 +31657,10 @@ msgid "Show parent subgroups"
msgstr "Vis forælderundergrupper"
msgid "Show the Closed list"
-msgstr "Vis den lukkede liste"
+msgstr "Vis listen lukket"
msgid "Show the Open list"
-msgstr "Vis den åbne liste"
+msgstr "Vis listen åbne"
msgid "Show whitespace changes"
msgstr ""
@@ -31434,7 +31766,7 @@ msgid "Sign in using smart card"
msgstr "Log ind med smartcard"
msgid "Sign in via 2FA code"
-msgstr "Log ind via 2TG-kode"
+msgstr "Log ind via 2FA-kode"
msgid "Sign in with"
msgstr "Log ind med"
@@ -31476,7 +31808,7 @@ msgid "Sign-in text"
msgstr "Indlogningstekst"
msgid "Sign-out page URL"
-msgstr ""
+msgstr "URL for udlogningsside"
msgid "Sign-up restrictions"
msgstr "Begrænsninger for tilmelding"
@@ -31523,9 +31855,6 @@ msgstr "Lignende problemstillinger"
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31533,7 +31862,7 @@ msgid "Site profile not found for given parameters"
msgstr ""
msgid "Sites"
-msgstr ""
+msgstr "Websteder"
msgid "Size"
msgstr "Størrelse"
@@ -31592,8 +31921,11 @@ msgstr "Smartcard"
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
-msgstr "Snippets"
+msgstr "Udklip"
msgid "Snippets with non-text files can only be edited via Git."
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr "Gem, del og indlejr små stykker kode og tekst."
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "Der er ingen udklip at vise."
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr "Tilføj endnu en fil %{num}/%{total}"
@@ -31625,6 +31960,9 @@ msgstr "Slet fil"
msgid "Snippets|Description (optional)"
msgstr "Beskrivelse (valgfrit)"
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr "Filer"
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr "Nogen redigerede problemstillingen på samme tid som dig. Tjek venligst %{linkStart}problemstillingen%{linkEnd} og sørg for at dine ændringer ikke utilsigtet fjerner deres."
@@ -31902,7 +32237,7 @@ msgid "SortOptions|Due date"
msgstr "Forfaldsdato"
msgid "SortOptions|Due later"
-msgstr ""
+msgstr "Forfalder senere"
msgid "SortOptions|Due soon"
msgstr "Forfalder snart"
@@ -31950,7 +32285,7 @@ msgid "SortOptions|Milestone due date"
msgstr "Forfaldsdato for milepæl"
msgid "SortOptions|Milestone due later"
-msgstr ""
+msgstr "Milepæl forfalder senere"
msgid "SortOptions|Milestone due soon"
msgstr ""
@@ -32058,7 +32393,7 @@ msgid "Source branch"
msgstr "Kildegren"
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
-msgstr ""
+msgstr "Kildegren: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgid "Source code (%{fileExtension})"
msgstr "Kildekode (%{fileExtension})"
@@ -32115,10 +32450,10 @@ msgid "SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{li
msgstr "Bruger en tilpasset %{linkStart}Sourcegraph-instans%{linkEnd}."
msgid "Spam Check"
-msgstr ""
+msgstr "Spamtjek"
msgid "Spam Check API key"
-msgstr ""
+msgstr "API-nøgle for spamtjek"
msgid "Spam Logs"
msgstr "Spamlogge"
@@ -32205,7 +32540,7 @@ msgid "Start Web Terminal"
msgstr "Start webterminal"
msgid "Start a %{new_merge_request} with these changes"
-msgstr "Start en %{new_merge_request} med disse ændringer"
+msgstr "Start en %{new_merge_request} med ændringerne"
msgid "Start a Free Ultimate Trial"
msgstr "Start en gratis Ultimate-prøveperiode"
@@ -32246,12 +32581,6 @@ msgstr "Start søgning"
msgid "Start thread"
msgstr "Start tråd"
-msgid "Start thread & close %{noteable_name}"
-msgstr "Start tråd og luk %{noteable_name}"
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr "Start tråd og genåbn %{noteable_name}"
-
msgid "Start your Free Ultimate Trial"
msgstr "Start din gratis Ultimate-prøveperiode"
@@ -32291,6 +32620,9 @@ msgstr "Starter: %{startsAt}"
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr "Static Application Security Testing (SAST)"
@@ -32403,7 +32735,7 @@ msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
msgid "StatusCheck|Failed to load status checks."
-msgstr ""
+msgstr "Kunne ikke indlæse statustjek."
msgid "StatusCheck|Invoke an external API as part of the pipeline process."
msgstr ""
@@ -32466,7 +32798,7 @@ msgid "StatusPage|Status page"
msgstr "Statusside"
msgid "StatusPage|Status page URL"
-msgstr ""
+msgstr "URL for statusside"
msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
@@ -32691,10 +33023,10 @@ msgid "SubscriptionTable|Something went wrong trying to refresh seats"
msgstr "Noget gik galt under forsøg på at opdatere sæder"
msgid "SubscriptionTable|Subscription end date"
-msgstr ""
+msgstr "Slutdato for abonnement"
msgid "SubscriptionTable|Subscription start date"
-msgstr ""
+msgstr "Startdato for abonnement"
msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
msgstr ""
@@ -32721,7 +33053,7 @@ msgid "SubscriptionTable|Upgrade"
msgstr "Opgrader"
msgid "SubscriptionTable|Usage"
-msgstr ""
+msgstr "Forbrug"
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr "Opdateret %{last_updated_timeago}."
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr "Opsummering/bemærkning"
msgid "Sunday"
msgstr "Søndag"
-msgid "SuperSonics|Activate"
-msgstr "Aktivér"
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr "Aktivér abonnement"
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr "Aktiveringskode"
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr "Udløber"
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr "Id"
-
-msgid "SuperSonics|Last Sync"
-msgstr "Sidste synkronisering"
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr "Lær at %{linkStart}aktivere dit abonnement%{linkEnd}."
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr "Indsæt din aktiveringskode"
-msgid "SuperSonics|Plan"
-msgstr "Plan"
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr "Fornyer"
-
-msgid "SuperSonics|Seats"
-msgstr "Sæder"
-
msgid "SuperSonics|Start free trial"
msgstr "Start gratis prøveperiode"
-msgid "SuperSonics|Started"
-msgstr "Startet"
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr "Abonnementsdetaljer"
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr "Type"
-
msgid "SuperSonics|Upload a license file"
msgstr "Upload en licensfil"
@@ -33023,9 +33322,6 @@ msgstr "Brugere over abonnement"
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr "Gyldig fra"
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr "URL for supportside"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr "Skift gren"
@@ -33254,6 +33553,9 @@ msgstr "Mærkater gør det muligt at mærke bestemte punkter i historik som vær
msgid "TagsPage|This tag has no release notes."
msgstr "Mærkatet har ingen udgivelsesnoter."
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr "MÃ¥lgren"
msgid "Task ID: %{elastic_task}"
msgstr "Opgave-id: %{elastic_task}"
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "Team"
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33551,7 +33865,7 @@ msgid "TestHooks|Ensure the project has merge requests."
msgstr "Sørg for at projektet har sammenlægningsanmodninger."
msgid "TestHooks|Ensure the project has notes."
-msgstr ""
+msgstr "Sørg for at projektet har noter."
msgid "TestHooks|Ensure the project has releases."
msgstr "Sørg for at projektet har udgivelser."
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr "Mappen er blevet oprettet."
@@ -33833,11 +34150,14 @@ msgstr "Formularen indeholder følgende fejl:"
msgid "The form contains the following warning:"
msgstr "Formularen indeholder følgende advarsel:"
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr "De globale indstillinger kræver at du aktiverer totrinsgodkendelse for din konto."
msgid "The group and any internal projects can be viewed by any logged in user except external users."
-msgstr ""
+msgstr "Gruppen og alle interne projekter kan vises af alle brugere som er logget ind undtagen eksterne brugere."
msgid "The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -33888,7 +34208,7 @@ msgid "The invitation has already been accepted."
msgstr "Invitationen er allerede blevet accepteret."
msgid "The invitation was successfully resent."
-msgstr ""
+msgstr "Invitationen blev sendt igen."
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
msgstr "Problemstillingen blev forfremmet til en epic. Omdirigerer til epic ..."
@@ -33915,6 +34235,9 @@ msgid "The license was successfully uploaded and is now active. You can see the
msgstr "Licensen blev uploadet og er nu aktiv. Du kan se detaljerne nedenunder."
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
+msgstr "Licensen er blevet uploadet og vil være aktiv fra %{starts_at}. Du kan se detaljerne nedenunder."
+
+msgid "The list creation wizard is already open"
msgstr ""
msgid "The maximum file size allowed is %{size}."
@@ -33996,10 +34319,10 @@ msgid "The private key to use when a client certificate is provided. This value
msgstr ""
msgid "The project can be accessed by any logged in user except external users."
-msgstr ""
+msgstr "Projektet kan tilgås af alle brugere som er logget ind undtagen eksterne brugere."
msgid "The project can be accessed by any user who is logged in."
-msgstr ""
+msgstr "Projektet kan tilgås af alle brugere som er logget ind."
msgid "The project can be accessed by anyone, regardless of authentication."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr "Projektet blev forgrenet."
msgid "The project was successfully imported."
msgstr "Projektet blev importeret."
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34035,19 +34355,19 @@ msgid "The remote mirror took to long to complete."
msgstr ""
msgid "The remote repository is being updated..."
-msgstr ""
+msgstr "Fjerndepotet er ved at blive opdateret ..."
msgid "The repository can be committed to, and issues, comments and other entities can be created."
msgstr ""
msgid "The repository for this project does not exist."
-msgstr ""
+msgstr "Depotet for projektet findes ikke."
msgid "The repository for this project is empty"
msgstr "Depotet for projektet er tomt"
msgid "The repository is being updated..."
-msgstr ""
+msgstr "Depotet er ved at blive opdateret ..."
msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close} or %{code_open}git://%{code_close}."
msgstr "Depotet skal kunne tilgås over %{code_open}http://%{code_close}, %{code_open}https://%{code_close} eller %{code_open}git://%{code_close}."
@@ -34058,20 +34378,17 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr "Planlægningstiden skal være i fremtiden!"
-
msgid "The snippet can be accessed without any authentication."
-msgstr ""
+msgstr "Udklippet kan ikke tilgås uden godkendelse."
msgid "The snippet is visible only to me."
-msgstr "Snippeten er kun synlig for mig."
+msgstr "Udklippet er kun synligt for mig."
msgid "The snippet is visible only to project members."
msgstr "Udklippet er kun synligt for projektmedlemmer."
msgid "The snippet is visible to any logged in user except external users."
-msgstr ""
+msgstr "Udklippet er synligt for alle brugere som er logget ind undtagen eksterne brugere."
msgid "The source branch will be deleted"
msgstr "Kildegrenen vil blive slettet"
@@ -34197,7 +34514,7 @@ msgid "There are no labels yet"
msgstr "Der er endnu ingen etiketter"
msgid "There are no matching files"
-msgstr ""
+msgstr "Der er ingen matchende filer"
msgid "There are no open epics"
msgstr "Der er ingen åbne epics"
@@ -34218,6 +34535,9 @@ msgid "There are no packages yet"
msgstr "Der er endnu ingen pakker"
msgid "There are no projects shared with this group yet"
+msgstr "Der er ingen projekter som er delt med gruppen endnu"
+
+msgid "There are no topics to show."
msgstr ""
msgid "There are no variables yet."
@@ -34304,6 +34624,9 @@ msgstr "Der var problemer med at hente seneste grupper."
msgid "There was a problem fetching recent projects."
msgstr "Der var problemer med at hente seneste projekter."
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr "Stierne er beskyttet for POST-anmodninger."
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34515,7 +34835,7 @@ msgid "Third-party offers"
msgstr "Tilbud fra tredjepart"
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
-msgstr ""
+msgstr "%{issuableDisplayName} er låst. Kun projektmedlemmer kan kommentere."
msgid "This %{issuableType} is confidential"
msgstr "Denne %{issuableType} er fortrolig"
@@ -34557,7 +34877,7 @@ msgid "This action cannot be undone, and will permanently delete the %{key} SSH
msgstr ""
msgid "This action has been performed too many times. Try again later."
-msgstr ""
+msgstr "Handlingen er blevet udført for mange gange. Prøv igen senere."
msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues and merge requests."
msgstr ""
@@ -34569,7 +34889,7 @@ msgid "This action will %{strongOpen}permanently remove%{strongClose} %{codeOpen
msgstr "Handlingen vil %{strongOpen}straks fjerne%{strongClose} %{codeOpen}%{group}%{codeClose} %{strongOpen}permanent%{strongClose}."
msgid "This also resolves all related threads"
-msgstr ""
+msgstr "Det løser også alle relaterede tråde"
msgid "This also resolves this thread"
msgstr "Det løser også tråden"
@@ -34715,8 +35035,8 @@ msgstr "Gruppen er linket til et abonnement"
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
-msgstr "Gruppen, dens undergrupper og projekter vil blive fjernet %{date} da dens forældergruppe '%{parent_group_name}'' er blevet planlagt til sletning."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
+msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -34728,13 +35048,13 @@ msgid "This is a Jira user."
msgstr "Det er en Jira-bruger."
msgid "This is a confidential %{noteableTypeText}."
-msgstr ""
+msgstr "Det er en fortrolig %{noteableTypeText}."
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
-msgstr ""
+msgstr "Dette er en liste over enheder som har logget ind på din konto. Tilbagekald sessioner som du ikke genkender."
msgid "This is a merge train pipeline"
msgstr ""
@@ -34743,7 +35063,7 @@ msgid "This is a private email address %{helpIcon} generated just for you. Anyon
msgstr ""
msgid "This is a security log of important events involving your account."
-msgstr ""
+msgstr "Dette er en sikkerhedslog over vigtige begivenheder der involverer din konto."
msgid "This is a self-managed instance of GitLab."
msgstr "Dette er en selvhåndterede instans af GitLab."
@@ -34869,7 +35189,7 @@ msgid "This means you can not push code until you create an empty repository or
msgstr ""
msgid "This merge request cannot be rebased while there are conflicts."
-msgstr ""
+msgstr "Sammenlægningsanmodningen kan ikke rebases mens der er konflikter."
msgid "This merge request does not have accessibility reports"
msgstr "Sammenlægningsanmodningen har ikke tilgængelighedsrapporter"
@@ -34938,16 +35258,16 @@ msgid "This project has no active access tokens."
msgstr "Projektet har ingen aktive adgangstokens."
msgid "This project is archived and cannot be commented on."
-msgstr ""
+msgstr "Projektet er arkiveret og kan ikke kommenteres på."
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
-msgstr ""
+msgstr "Projektet er licenseret under %{strong_start}%{license_name}%{strong_end}."
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
msgstr "Projektet håndterer sine afhængigheder med %{strong_start}%{manager_name}%{strong_end}"
msgid "This project path either does not exist or you do not have access."
-msgstr ""
+msgstr "Enten findes projektstien ikke eller også har du ikke adgang."
msgid "This project will be deleted on %{date}"
msgstr "Projektet slettes %{date}"
@@ -34980,7 +35300,7 @@ msgid "This service allows users to perform common operations on this project by
msgstr ""
msgid "This setting can be overridden in each project."
-msgstr ""
+msgstr "Indstillingen kan tilsidesættes i hvert projekt."
msgid "This subscription is for"
msgstr "Abonnementet er til"
@@ -35004,7 +35324,7 @@ msgid "This user has no identities"
msgstr "Brugeren har ingen identiteter"
msgid "This user has no personal projects."
-msgstr ""
+msgstr "Brugeren har ingen personlige projekter."
msgid "This user has previously committed to the %{name} project."
msgstr ""
@@ -35013,9 +35333,15 @@ msgid "This user has the %{access} role in the %{name} project."
msgstr "Brugeren har rollen %{access} i projektet %{name}."
msgid "This user is the author of this %{noteable}."
-msgstr ""
+msgstr "Brugeren er forfatteren af denne %{noteable}."
msgid "This variable can not be masked."
+msgstr "Variablen kan ikke maskeres."
+
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
msgstr ""
msgid "This will redirect you to an external sign in page."
@@ -35031,13 +35357,13 @@ msgid "Thread to reply to cannot be found"
msgstr "Kan ikke finde tråden som skal besvares"
msgid "Threat Monitoring"
-msgstr ""
+msgstr "Trådovervågning"
msgid "ThreatMonitoring|Alert Details"
-msgstr ""
+msgstr "Alertbeskeddetaljer"
msgid "ThreatMonitoring|Alerts"
-msgstr ""
+msgstr "Alertbeskeder"
msgid "ThreatMonitoring|All Environments"
msgstr "Alle miljøer"
@@ -35073,7 +35399,7 @@ msgid "ThreatMonitoring|Failed to create incident, please try again."
msgstr "Kunne ikke oprette hændelse. Prøv venligst igen."
msgid "ThreatMonitoring|Hide dismissed alerts"
-msgstr ""
+msgstr "Skjul afskedigede alertbeskeder"
msgid "ThreatMonitoring|In review"
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,8 +35852,8 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr "Opret en ny sammenlægningsanmodning for at holde projektet i gang"
-msgid "To learn more about this project, read %{link_to_wiki}."
-msgstr "Læs %{link_to_wiki} for at lære mere om projektet."
+msgid "To learn more about this project, read %{link_to_wiki}"
+msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
@@ -35578,7 +35907,7 @@ msgid "To set up this integration:"
msgstr ""
msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
-msgstr ""
+msgstr "For at angive underretningsniveauet pr. projekt i en gruppe du tilhører, så skal du besøge projektsiden og ændre underretningsniveauet der."
msgid "To start using GitLab Enterprise Edition, upload the %{codeOpen}.gitlab-license%{codeClose} file or enter the license key you have received from GitLab Inc."
msgstr ""
@@ -35709,6 +36038,21 @@ msgstr "For mange projekter aktiveret. Du skal håndtere dem via konsollen eller
msgid "TopNav|Go back"
msgstr "GÃ¥ tilbage"
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr "Emner (valgfrit)"
@@ -35802,8 +36146,8 @@ msgstr "Gruppen er allerede en rodmappe."
msgid "TransferGroup|Group is already associated to the parent group."
msgstr "Gruppe er allerede tilknyttet til forældergruppen."
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
-msgstr "Forældergruppen har allerede en undergruppe med den samme sti."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
+msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
msgstr ""
@@ -36084,7 +36428,7 @@ msgid "URL"
msgstr "URL"
msgid "URL cannot be blank"
-msgstr ""
+msgstr "URL'en må ikke være tom"
msgid "URL is invalid"
msgstr "URL'en er ugyldig"
@@ -36170,6 +36514,9 @@ msgstr "Kan ikke hente grenliste for projektet."
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr "Fortryd"
@@ -36587,17 +36937,20 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr "Køb yderligere minutter"
msgid "UsageQuota|CI minutes usage by month"
-msgstr ""
+msgstr "Forbrug af CI-minutter pr. måned"
msgid "UsageQuota|CI minutes usage by project"
-msgstr ""
+msgstr "Forbrug af CI-minutter efter projekt"
msgid "UsageQuota|Code packages and container images."
-msgstr ""
+msgstr "Kodepakker og beholderaftryk."
msgid "UsageQuota|Current period usage"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr "LFS-objekter"
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36630,7 +36986,7 @@ msgid "UsageQuota|Packages"
msgstr "Pakker"
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
-msgstr ""
+msgstr "Pipelineartefakter og jobartefakter, oprettet med CI/CD."
msgid "UsageQuota|Pipelines"
msgstr ""
@@ -36651,22 +37007,19 @@ msgid "UsageQuota|Seats"
msgstr "Sæder"
msgid "UsageQuota|Shared bits of code and text."
-msgstr ""
+msgstr "Delte stykker med kode og tekst."
msgid "UsageQuota|Snippets"
-msgstr "Snippets"
+msgstr "Udklip"
msgid "UsageQuota|Something went wrong while fetching project storage statistics"
-msgstr "Noget fik galt under hentning af af projektlagerstatistik"
+msgstr "Noget fik galt under hentning af projektlagerstatistik"
msgid "UsageQuota|Storage"
msgstr "Lager"
msgid "UsageQuota|Storage type"
-msgstr ""
-
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
+msgstr "Lagertype"
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,12 +37060,12 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr "Forbrug"
-msgid "UsageQuota|Usage Breakdown"
-msgstr ""
-
msgid "UsageQuota|Usage Quotas"
msgstr "Forbrugskvoter"
+msgid "UsageQuota|Usage breakdown"
+msgstr ""
+
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
msgstr ""
@@ -36720,13 +37073,13 @@ msgid "UsageQuota|Usage of project resources across the %{strong_start}%{project
msgstr ""
msgid "UsageQuota|Usage of resources across your projects"
-msgstr ""
+msgstr "Forbrug af ressourcer på tværs af dine projekter"
msgid "UsageQuota|Usage quotas help link"
msgstr ""
msgid "UsageQuota|Usage since"
-msgstr ""
+msgstr "Forbrug siden"
msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
msgstr ""
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr "Brug en AWS CloudFormation Template (CFT) til at installere og konfigurere GitLab Runner i AWS."
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr "Brug cURL"
@@ -36890,6 +37246,9 @@ msgstr "Brug skråstregskommandoer."
msgid "Use template"
msgstr "Brug skabelon"
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr "Brug linket nedenunder for at bekræfte din e-mailadresse (%{email})"
@@ -36956,17 +37315,23 @@ msgstr "Brugerindstillinger"
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
msgid "User identity was successfully created."
-msgstr ""
+msgstr "Brugeridentiteten blev oprettet."
msgid "User identity was successfully removed."
-msgstr ""
+msgstr "Brugeridentiteten blev fjernet."
msgid "User identity was successfully updated."
-msgstr ""
+msgstr "Brugeridentiteten blev opdateret."
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -37155,7 +37520,7 @@ msgid "UserProfile|Retry"
msgstr "Prøv igen"
msgid "UserProfile|Snippets"
-msgstr "Snippets"
+msgstr "Udklip"
msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
msgstr "Udklip i GitLab kan enten være private, interne eller offentlige."
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr "Valider"
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -37490,7 +37879,7 @@ msgid "View documentation"
msgstr "Vis dokumentation"
msgid "View eligible approvers"
-msgstr "Vis berettigede godkendere"
+msgstr "Vis kvalificerede godkendere"
msgid "View epics list"
msgstr "Vis epicliste"
@@ -37507,10 +37896,10 @@ msgid "View file @ %{commitSha}"
msgstr "Vis fil @ %{commitSha}"
msgid "View full dashboard"
-msgstr ""
+msgstr "Vis hele betjeningspanelet"
msgid "View full log"
-msgstr ""
+msgstr "Vis hele loggen"
msgid "View group in admin area"
msgstr "Vis gruppe i administratorområde"
@@ -37968,7 +38357,7 @@ msgid "We've found no vulnerabilities"
msgstr "Vi fandt ingen sårbarheder"
msgid "Web IDE"
-msgstr "Web IDE"
+msgstr "Web-IDE"
msgid "Web Terminal"
msgstr "Webterminal"
@@ -38024,6 +38413,9 @@ msgstr "Webhook-logge"
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr "Webhook:"
@@ -38214,11 +38606,14 @@ msgid "What is your job title? (optional)"
msgstr "Hvad er din jobtitel? (valgfrit)"
msgid "What templates can I create?"
-msgstr ""
+msgstr "Hvilke skabeloner kan jeg oprette?"
msgid "What will you use this group for?"
msgstr "Hvad vil du bruge gruppen til?"
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr "Nyheder"
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr "Når en begivenhed i GitLab udløser en webhook, så kan du bruge anmodningsdetaljerne til at finde ud af om noget gik galt."
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "Når sammenlægningsanmodningen accepteres"
@@ -38251,14 +38646,11 @@ msgstr[1] "Når sammenlægningsanmodningerne accepteres"
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr "Når protokollerne %{code_open}http://%{code_close} eller %{code_open}https://%{code_close} bruges, så angiv venligst den præcise URL til depotet. HTTP-omdirigeringer følges ikke."
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr "Når protokollerne %{code_open}http://%{code_close} eller %{code_open}https://%{code_close} bruges, så angiv den præcise URL til depotet. HTTP-omdirigeringer følges ikke."
-
msgid "When:"
msgstr "NÃ¥r:"
msgid "Which API requests are affected?"
-msgstr ""
+msgstr "Hvilke API-anmodninger påvirkes?"
msgid "While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
msgstr ""
@@ -38560,11 +38952,11 @@ msgstr "Skriv en kommentar …"
msgid "Write a description or drag your files here…"
msgstr "Skriv en beskrivelse eller træk dine filer hertil …"
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
-msgstr "Skriv til \"authorized_keys\"-fil"
+msgid "Write milestone description..."
+msgstr ""
msgid "Write your release notes or drag your files here…"
msgstr "Skriv dine udgivelsesnoter eller træk dine filer hertil …"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr "Du er ved at tilføje %{usersTag} personer til debatten. De vil alle modtage en underretning."
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr "Du er ved at slette %{domain} fra din instans. Domænet vil ikke længere være tilgængeligt for nogle Knative-programmer."
-
msgid "You are about to permanently delete this project"
msgstr "Du er ved at slette projektet permanent"
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38723,7 +39115,7 @@ msgid "You can also use project access tokens with Git to authenticate over HTTP
msgstr ""
msgid "You can always change your URL later"
-msgstr ""
+msgstr "Du kan altid ændre din URL senere"
msgid "You can always edit this later"
msgstr "Du kan altid ændre det senere"
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr "Du kan gendanne projektet indtil %{date}"
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38843,7 +39232,7 @@ msgid "You can set up jobs to only use runners with specific tags. Separate tags
msgstr ""
msgid "You can specify notification level per group or per project."
-msgstr ""
+msgstr "Du kan angive underretningsniveau pr. gruppe eller pr. projekt."
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -38906,7 +39295,7 @@ msgid "You do not have permissions to run the import."
msgstr "Du har ikke tilladelser til at køre importen."
msgid "You don't have any U2F devices registered yet."
-msgstr "Du har endnu ikke registreret nogle U2F-enheder."
+msgstr "Du har endnu ikke tilmeldt nogle U2F-enheder."
msgid "You don't have any WebAuthn devices registered yet."
msgstr "Du har endnu ikke tilmeldt nogle WebAuthn-enheder."
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr "Du har ingen seneste søgninger"
-msgid "You don't have any webhooks deliveries"
-msgstr "Du har ikke nogle webhooksleveringer"
-
msgid "You don't have sufficient permission to perform this action."
msgstr "Du har ikke tilstrækkelig tilladelse til at udføre handlingen."
@@ -39014,7 +39400,7 @@ msgid "You have reached your project limit"
msgstr "Du har nået din projektgrænse"
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
-msgstr "Du har opsat 2TG til din konto! Hvis du mister adgang til din 2TG-enhed, så kan du bruge dine gendannelseskoder til at få adgang til din konto. Ellers kan du, hvis du uploader en SSH-nøgle, %{anchorOpen}bruge nøglen til at generere yderligere gendannelseskoder%{anchorClose}."
+msgstr "Du har opsat 2FA til din konto! Hvis du mister adgang til din 2FA-enhed, så kan du bruge dine gendannelseskoder til at få adgang til din konto. Ellers kan du, hvis du uploader en SSH-nøgle, %{anchorOpen}bruge nøglen til at generere yderligere gendannelseskoder%{anchorClose}."
msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr "Du forlod \"%{membershipable_human_name}\" %{source_type}."
@@ -39031,9 +39420,6 @@ msgstr "Du kan nu lukke milepælen."
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39053,10 +39439,10 @@ msgid "You must provide your current password in order to change it."
msgstr "Du skal angive din nuværende adgangskode for at ændre den."
msgid "You must sign in to search for specific projects."
-msgstr ""
+msgstr "Du skal logge ind for at søge efter bestemte projekter."
msgid "You must sign in to search for specific terms."
-msgstr ""
+msgstr "Du skal logge ind for at søge efter bestemte udtryk."
msgid "You must solve the CAPTCHA in order to submit"
msgstr "Du skal løse CAPTCHA'en for at indsende"
@@ -39086,7 +39472,7 @@ msgid "You need to upload a GitLab project export archive (ending in .gz)."
msgstr "Du skal uploade et GitLab-projekteksportarkiv (slutter med .gz)."
msgid "You need to verify your primary email first before enabling Two-Factor Authentication."
-msgstr ""
+msgstr "Du skal bekræfte din primære e-mail inden aktivering af totrinsgodkendelse."
msgid "You successfully declined the invitation"
msgstr "Du har afvist invitationen"
@@ -39335,7 +39721,7 @@ msgid "Your commit email is used for web based operations, such as edits and mer
msgstr ""
msgid "Your current password is required to register a two-factor authenticator app."
-msgstr ""
+msgstr "Din nuværende adgangskode kræves for at tilmelde et totrinsgodkendelsesprogram."
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr ""
@@ -39443,7 +39829,7 @@ msgid "Your projects"
msgstr "Dine projekter"
msgid "Your public email will be displayed on your public profile."
-msgstr ""
+msgstr "Din offentlige e-mail vil blive vist på din offentlige profil."
msgid "Your request for access could not be processed: %{error_meesage}"
msgstr ""
@@ -39473,42 +39859,69 @@ msgid "Your search timed out"
msgstr "Din søgning fik timeout"
msgid "Your sign-in page is %{url}."
-msgstr ""
+msgstr "Din indlogningsside er %{url}."
msgid "Your subscription expired!"
msgstr "Dit abonnement udløb!"
msgid "Your subscription will expire in %{remaining_days} day."
msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Dit abonnement vil udløbe om %{remaining_days} dag."
+msgstr[1] "Dit abonnement vil udløbe om %{remaining_days} dage."
msgid "Your username is %{username}."
msgstr "Dit brugernavn er %{username}."
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
-msgstr "Grund-URL på Zentao-instansen."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
-msgid "ZentaoIntegration|Enter API token"
-msgstr "Indtast API-token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
+msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
-msgstr "Brug Zentao som projektets problemstillingssporing."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
+msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
-msgstr "URL for Zentao-API (valgfrit)"
+msgid "ZentaoIntegration|ZenTao API token"
+msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
-msgstr "API-token for Zentao"
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
-msgstr "Produkt-id for Zentao"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
-msgstr "Web-URL for Zentao"
+msgid "ZentaoIntegration|ZenTao issues"
+msgstr ""
msgid "Zoom meeting added"
msgstr "Zoom-møde tilføjet"
@@ -39519,6 +39932,9 @@ msgstr "Zoom-møde fjernet"
msgid "[No reason]"
msgstr "[ingen årsag]"
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr "`start_time` skal være før `end_time`"
msgid "a deleted user"
msgstr "en slettet bruger"
-msgid "a design"
-msgstr "et design"
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] "cirka 1 time"
@@ -39640,12 +40053,18 @@ msgstr "kan kun ændres af en gruppeadministrator."
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr "kan ikke være det samme som kildeprojektet"
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39668,11 +40087,14 @@ msgid "cannot be enabled unless all domains have TLS certificates"
msgstr "kan ikke aktiveres medmindre alle domæner har TLS-certifikater"
msgid "cannot be enabled until a valid credit card is on file"
-msgstr ""
+msgstr "kan ikke aktiveres indtil et gyldigt kreditkort er blevet registreret"
msgid "cannot be modified"
msgstr "kan ikke ændres"
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr "må ikke blokere andre"
@@ -39688,9 +40110,6 @@ msgstr "må ikke selv blokeres"
msgid "cannot merge"
msgstr "kan ikke sammenlægge"
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "%{remainingPackagesCount} mere"
@@ -39757,9 +40179,20 @@ msgstr "Anvend automatisk patchen i en ny gren"
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,8 +40202,14 @@ msgstr "Tjekker"
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
-msgstr "Kodekvalitet"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
msgid "ciReport|Container Scanning"
msgstr "Beholderskanning"
@@ -39835,6 +40274,17 @@ msgstr "Fandt %{issuesWithCount}"
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr "SAST"
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39916,7 +40366,7 @@ msgstr[0] "Brugt af %{packagesString}"
msgstr[1] "Brugt af %{packagesString} og %{lastPackage}"
msgid "ciReport|View full report"
-msgstr ""
+msgstr "Vis hele rapporten"
msgid "ciReport|is loading"
msgstr "indlæser"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr "container_name må ikke være længere end %{max_length} tegn"
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr "bidrag til projektet."
@@ -40015,7 +40471,7 @@ msgid "created %{timeAgo}"
msgstr "oprettet %{timeAgo}"
msgid "created %{timeAgo} by %{author}"
-msgstr ""
+msgstr "oprettet %{timeAgo} af %{author}"
msgid "created by"
msgstr "oprettet af"
@@ -40046,9 +40502,6 @@ msgstr "udsend"
msgid "design"
msgstr "design"
-msgid "designs"
-msgstr "designs"
-
msgid "detached"
msgstr "løsrevet"
@@ -40061,6 +40514,12 @@ msgstr "findes ikke"
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr "download den"
@@ -40075,6 +40534,9 @@ msgstr "f.eks. %{token}"
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40085,7 +40547,7 @@ msgid "encrypted: needs to be a :required, :optional or :migrating!"
msgstr ""
msgid "ending with a reserved file extension is not allowed."
-msgstr ""
+msgstr "det er ikke tilladt at slutte med en reserveret filendelse."
msgid "entries cannot be larger than 255 characters"
msgstr "indslag må ikke være længere end 255 tegn"
@@ -40109,6 +40571,9 @@ msgid "estimateCommand|%{slash_command} overwrites the total estimated time."
msgstr "%{slash_command} overskriver den samlede estimerede tid."
msgid "example.com"
+msgstr "example.com"
+
+msgid "exceeds the %{max_value_length} character limit"
msgstr ""
msgid "exceeds the limit of %{bytes} bytes"
@@ -40170,7 +40635,7 @@ msgstr[0] "fra %d job"
msgstr[1] "fra %d job"
msgid "frontmatter"
-msgstr ""
+msgstr "frontmatter"
msgid "group"
msgstr "gruppe"
@@ -40239,16 +40704,16 @@ msgid "in Infrastructure :: Kubernetes clusters"
msgstr ""
msgid "in all GitLab"
-msgstr ""
+msgstr "i hele GitLab"
msgid "in group"
-msgstr ""
+msgstr "i gruppe"
msgid "in group %{link_to_group}"
msgstr "i gruppen %{link_to_group}"
msgid "in project"
-msgstr ""
+msgstr "i projekt"
msgid "in project %{link_to_project}"
msgstr "i projektet %{link_to_project}"
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr "er ikke gyldig. Gennemløbsgruppen skal matche gennmløbskadencegruppen."
@@ -40397,7 +40868,7 @@ msgid "log in"
msgstr "log ind"
msgid "managed"
-msgstr ""
+msgstr "håndteret"
msgid "manual"
msgstr "manuelt"
@@ -40467,6 +40938,9 @@ msgstr "%{metricsLinkStart} Hukommelsesforbrug %{metricsLinkEnd} er %{emphasisSt
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr "Godkend yderligere"
msgid "mrWidget|Approved by"
msgstr "Godkendt af"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40507,7 +40987,7 @@ msgid "mrWidget|Cancel auto-merge"
msgstr "Annuller automatisk sammenlægning"
msgid "mrWidget|Check out branch"
-msgstr ""
+msgstr "Check out gren"
msgid "mrWidget|Checking if merge request can be merged…"
msgstr "Tjekker om sammenlægningsanmodning kan sammenlægges …"
@@ -40530,7 +41010,7 @@ msgstr[0] "Lukker problemstilling"
msgstr[1] "Lukker problemstillinger"
msgid "mrWidget|Create issue to resolve all threads"
-msgstr ""
+msgstr "Opret problemstilling for at løse alle tråde"
msgid "mrWidget|Delete source branch"
msgstr "Slet kildegren"
@@ -40542,7 +41022,7 @@ msgid "mrWidget|Did not close"
msgstr "Lukkede ikke"
msgid "mrWidget|Dismiss"
-msgstr ""
+msgstr "Afskedig"
msgid "mrWidget|Email patches"
msgstr "E-mail-patches"
@@ -40551,17 +41031,20 @@ msgid "mrWidget|Failed to load deployment statistics"
msgstr "Kunne ikke indlæse udsendelsesstatistik"
msgid "mrWidget|Hide %{widget} details"
-msgstr ""
+msgstr "Skjul %{widget}-detaljer"
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Hvis grenen %{missingBranchName} findes i dit lokale depot, så kan du sammenlægge sammenlægningsanmodningen manuelt med kommandolinjen"
msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
-msgstr ""
+msgstr "Hvis den sidste pipeline kørte i forgreningsprojektet, så kan den være upræcis. Inden sammenlægning anbefaler vi at køre en pipeline i projektet."
msgid "mrWidget|Jump to first unresolved thread"
msgstr "Hop til første uløste tråd"
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr "Indlæser udsendelsesstatistik"
@@ -40573,8 +41056,8 @@ msgstr "Medlemmer som kan sammenlægge har ikke tilladelse til at tilføje commi
msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Nævner problemstilling"
+msgstr[1] "Nævner problemstillinger"
msgid "mrWidget|Merge"
msgstr "Sammenlæg"
@@ -40594,9 +41077,6 @@ msgstr "Sammenlægning mislykkedes."
msgid "mrWidget|Merge locally"
msgstr "Sammenlæg lokalt"
-msgid "mrWidget|Merge request approved."
-msgstr "Sammenlægningsanmodning godkendt."
-
msgid "mrWidget|Merged by"
msgstr "Sammenlagt af"
@@ -40604,19 +41084,19 @@ msgid "mrWidget|Merging! Changes are being shipped…"
msgstr "Sammenlægger! Ændringer er ved at blive sendt afsted …"
msgid "mrWidget|Merging! Changes will land soon…"
-msgstr ""
+msgstr "Sammenlægger! Ændringerne kommer snart …"
msgid "mrWidget|Merging! Drum roll, please…"
msgstr "Sammenlægger! Trommehvirvel, tak …"
msgid "mrWidget|Merging! Everything's good…"
-msgstr ""
+msgstr "Sammenlægger! Det ser altsammen godt ud …"
msgid "mrWidget|Merging! This is going to be great…"
-msgstr ""
+msgstr "Sammenlægger! Det skal nok blive godt …"
msgid "mrWidget|Merging! We're almost there…"
-msgstr ""
+msgstr "Sammenlægger! Vi er der næsten …"
msgid "mrWidget|More information"
msgstr "Mere information"
@@ -40625,7 +41105,7 @@ msgid "mrWidget|Open in Gitpod"
msgstr "Ã…bn i Gitpod"
msgid "mrWidget|Open in Web IDE"
-msgstr "Ã…bn i Web IDE"
+msgstr "Ã…bn i web-IDE"
msgid "mrWidget|Plain diff"
msgstr "Ren diff"
@@ -40646,7 +41126,7 @@ msgid "mrWidget|Remove from merge train"
msgstr "Fjern fra sammenlægningstog"
msgid "mrWidget|Request to merge"
-msgstr "Anmod om at sammenlægge"
+msgstr "Anmodning om at sammenlægge"
msgid "mrWidget|Resolve conflicts"
msgstr "Løs konflikter"
@@ -40676,7 +41156,7 @@ msgid "mrWidget|Set by %{merge_author} to start a merge train when the pipeline
msgstr "Indstillet af %{merge_author} til at starte et sammenlægningstog når pipelinen lykkes"
msgid "mrWidget|Show %{widget} details"
-msgstr ""
+msgstr "Vis %{widget}-detaljer"
msgid "mrWidget|The changes were merged into"
msgstr "Ændringerne blev sammenlagt i"
@@ -40697,7 +41177,7 @@ msgid "mrWidget|The source branch has been deleted"
msgstr "Kildegrenen er blevet slettet"
msgid "mrWidget|The source branch is %{link} the target branch"
-msgstr ""
+msgstr "Kildegrenen er %{link} målgrenen"
msgid "mrWidget|The source branch is being deleted"
msgstr "Kildegrenen er ved at blive slettet"
@@ -40711,12 +41191,6 @@ msgstr "Kildegrenen vil ikke blive slettet"
msgid "mrWidget|There are merge conflicts"
msgstr "Der er sammenlægningskonflikter"
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr "Handlingen vil starte et sammenlægningstog når pipelinen %{pipelineLink} lykkes."
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Sammenlægningsanmodningen kunne ikke sammenlægges automatisk"
@@ -40732,11 +41206,14 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
+msgstr "Du kan kun sammenlægge når sammenlægningsanmodningen er godkendt."
msgid "mrWidget|Your password"
msgstr "Din adgangskode"
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr "min-fantastiske-gruppe"
@@ -40855,6 +41338,9 @@ msgstr "eller"
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "ud af %d test i alt"
@@ -40897,8 +41383,8 @@ msgstr "pod_name må ikke være længere end %{max_length} tegn"
msgid "point"
msgid_plural "points"
-msgstr[0] "point"
-msgstr[1] "point"
+msgstr[0] "punkt"
+msgstr[1] "punkter"
msgid "previously merged commits"
msgstr ""
@@ -40948,7 +41434,7 @@ msgid "quick actions"
msgstr "hurtighandlinger"
msgid "reCAPTCHA"
-msgstr ""
+msgstr "reCAPTCHA"
msgid "reCAPTCHA helps prevent credential stuffing."
msgstr ""
@@ -41196,10 +41682,10 @@ msgid "v%{version} published %{timeAgo}"
msgstr "v%{version} udgivet %{timeAgo}"
msgid "value for '%{storage}' must be an integer"
-msgstr ""
+msgstr "værdi for '%{storage}' skal være et heltal"
msgid "value for '%{storage}' must be between 0 and 100"
-msgstr ""
+msgstr "værdi for '%{storage}' skal være fra 0 til 100"
msgid "verify ownership"
msgstr "bekræft ejerskab"
@@ -41211,10 +41697,10 @@ msgid "via %{closed_via}"
msgstr "via %{closed_via}"
msgid "via merge request %{link}"
-msgstr ""
+msgstr "via sammenlægningsanmodningen %{link}"
msgid "view it on GitLab"
-msgstr "vis på GitLab"
+msgstr "vis den på GitLab"
msgid "view the blob"
msgstr "vis blob'en"
@@ -41279,8 +41765,8 @@ msgid "your settings"
msgstr "dine indstillinger"
msgid "{group}"
-msgstr ""
+msgstr "{gruppe}"
msgid "{project}"
-msgstr ""
+msgstr "{projekt}"
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index c844162709d..7fa90704966 100644
--- a/locale/de/gitlab.po
+++ b/locale/de/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr " %{start} bis %{end}"
@@ -40,25 +40,12 @@ msgstr " Typ"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Das musst du vor %{grace_period_deadline} tun."
-msgid " and"
-msgstr " und"
-
msgid " and "
msgstr " und "
msgid " and %{sliced}"
msgstr " und %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " um %d Punkt verschlechtert"
-msgstr[1] " um %d Punkte verschlechtert"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " um %d Punkt verbessert"
-msgstr[1] " um %d Punkte verbessert"
-
msgid " or "
msgstr " oder "
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr "\"el\" Parameter wird für createInstance() benötigt"
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr "#allgemein, #entwicklung"
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] "%d Commit,"
msgstr[1] "%d Commits,"
-msgid "%d commits"
-msgstr "%d Commits"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] "%d erledigtes Ticket"
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr "(entfernt)"
msgid "(revoked)"
msgstr "(widerrufen)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} weitere"
@@ -1193,6 +1189,9 @@ msgstr[1] "- Ereignisse"
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr "Ein Default-Branch kann nicht für ein leeres Projekt ausgewählt werden
msgid "A deleted user"
msgstr "Ein(e) gelöschte(r) Benutzer(in)"
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr "Deinen Bericht wird so schnell wie möglich von einer zuständigen Perso
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr "Ein Projekt, das Tickets für jede Prüfanfrage im HIPAA-Prüfprotokoll enthält, das vom US-Gesundheitsministerium veröffentlicht wurde"
@@ -1850,6 +1849,9 @@ msgstr "Aktionen"
msgid "Activate Service Desk"
msgstr "Service-Desk aktivieren"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Aktiv"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Füge einen allgemeinen Kommentar zu %{noteableDisplayName} hinzu."
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "Trage einen allgemeinen Kommentar zu diesem %{noteable_name} bei."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Füge zu deinem Wiki eine Startseite mit Informationen zu deinem GitLab-Project hinzu und GitLab wird sie hier anstatt dieser Meldung anzeigen."
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr "Domain hinzufügen"
-
msgid "Add email address"
msgstr "E-Mail-Adresse hinzufügen"
@@ -2108,6 +2104,9 @@ msgstr "Zum Review hinzufügen"
msgid "Add to tree"
msgstr "Zur Verzeichnisbaum hinzufügen"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "Admin"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr "Benutzer(in) zu reaktivieren, wird:"
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,8 +3334,8 @@ msgstr "Alle Merge-Konflikte wurden gelöst. Der Merge-Request kann nun gemerged
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
-msgstr "Alle Pfade sind relativ zur GitLab-URL. Füge keine %{relative_url_link_start}relativen URLs%{relative_url_link_end} hinzu."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
+msgstr ""
msgid "All projects"
msgstr "Alle Projekte"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr "Alle Benutzer(innen) benötigen einen Namen."
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Erlaube \"%{group_name}\" dich anzumelden"
@@ -3362,7 +3370,7 @@ msgstr "Erlaube Commits von Mitgliedern die zum Zielbranch mergen können."
msgid "Allow group owners to manage LDAP-related settings"
msgstr "Gruppenbesitzer erlauben, LDAP-bezogene Einstellungen zu verwalten"
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "Beim Abonnieren von Benachrichtigungen ist ein Fehler aufgetreten."
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Genehmigungsberechtigte(r)"
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr "Name"
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr "Regelname"
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr "Bist du sicher? Dadurch werden deine registrierten Anwendungen und U2F-Geräte ungültig."
-
msgid "Arrange charts"
msgstr "Diagramme anordnen"
@@ -4783,6 +4820,9 @@ msgstr "August"
msgid "Authenticate"
msgstr "Authentifizieren"
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr "Mit GitHub authentifizieren"
@@ -5415,6 +5455,9 @@ msgstr "Blöcke"
msgid "Blog"
msgstr "Blog"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "Der Board-Bereich beeinflusst, welche Themen für jeden angezeigt werden, der dieses Board besucht"
@@ -5656,8 +5699,8 @@ msgstr "Alle"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "HEAD-Commit kann für diesen Branch nicht gefunden werden"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "Vergleichen"
@@ -5767,6 +5810,9 @@ msgstr "Gib zur Bestätigung %{branch_name_confirmation} ein:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Um die lokalen Änderungen zu verwerfen und den Branch mit der Upstream-Version zu überschreiben, lösche ihn hier und wähle oben \"Jetzt aktualisieren\"."
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr "CI Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr "Schließe Vorschau"
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr "Kann nicht automatisch zusammengeführt werden"
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr "Kapazitätsschwelle"
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr "Vorlage auswählen ..."
msgid "Choose a type..."
msgstr "Typ auswählen..."
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr "Wähle eine Farbe."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr "Datei auswählen…"
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Betrachte und ändere die Details deines Kubernetes-Clusters"
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "Wähle ein Netzwerk aus, um das Subnetzwerk auszuwählen"
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr "Wähle eine Zone aus, um das Netzwerk auszuwählen"
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "Wähle den Maschinentyp aus"
@@ -7963,6 +8033,9 @@ msgstr "Wähle ein Projekt und ein Zone, um den Maschinentyp auszuwählen"
msgid "ClusterIntegration|Select project to choose zone"
msgstr "Wähle ein Projekt aus, um die Zone auszuwählen"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr "erfüllt die Anforderungen"
msgid "ClusterIntegration|sign up"
msgstr "Registrierung"
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr "Wähle ein Netzwerk"
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr "Wähle ein Subnetzwerk"
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr "Befehle wurden nicht angewendet"
msgid "Comment"
msgstr "Kommentieren"
-msgid "Comment & close %{noteable_name}"
-msgstr "%{noteable_name} kommentieren und schließen"
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr "%{noteable_name} kommentieren und erneut öffnen"
-
msgid "Comment & resolve thread"
msgstr "Kommentiere & beende Diskussion"
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Vergleichen"
@@ -8478,13 +8524,13 @@ msgstr "Abgeschlossen"
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr "Vorhandene Installation konfigurieren"
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "Container-Registry"
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr "Kopiere %{protocol} clone-URL"
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr "Link kopieren"
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr "Konnte Admins nicht als Mitglieder hinzufügen"
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr "Abdeckung"
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Erstelle neues Verzeichnis"
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr "Merge-Request erzeugen"
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr "Neues Ticket erstellen"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr "Snippet erstellen"
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr "Diagrammfilter anzeigen"
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10767,6 +10834,9 @@ msgstr "Datumsauswahl"
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr "Standard-Branch"
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr "Standardklassifikationslabel"
@@ -10872,18 +10945,36 @@ msgstr "Standard: Ordne eine FogBugz-Konto-ID einem vollständigen Namen zu"
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "Erstelle ein benutzerdefiniertes Muster mittels Cron-Syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr "Erstelle ein benutzerdefiniertes Muster mittels Cron-Syntax"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -10956,9 +11047,6 @@ msgstr "Kommentar entfernen"
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr "Codeausschnitt löschen"
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr "Abhängigkeitsproxy"
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
-msgstr "Abhängigkeitsproxy"
+msgid "DependencyProxy|Cached %{time}"
+msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr "Designs"
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr "Spezifische(n) Vorschlag oder Frage diskutieren"
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr "Spezifische(n) Vorschlag oder Frage diskutieren, um eine Lösung zu finden"
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr "Diskutiere einen speziellen Vorschlag oder eine Frage, die gelöst werden muss."
@@ -12097,18 +12205,6 @@ msgstr "Domäne"
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr "Kann Domain nicht löschen, solange sie mit Cluster(n) verknüpft ist."
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr "Dieses Release bearbeiten"
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr "Aktiviere oder deaktiviere die Pseudonymizer-Datensammlung."
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr "Umgebung hat keine Bereitstellungen"
@@ -12976,7 +13074,7 @@ msgstr "Beim Anhalten der Umgebung ist ein Fehler aufgetreten. Bitte versuche es
msgid "Environments|Are you sure you want to stop this environment?"
msgstr "Bist du sicher, dass du diese Umgebung stoppen möchtest?"
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr "Fehler beim Erstellen des Epics"
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr "Ablaufdatum"
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr "Erkunde öffentliche Gruppen"
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr "Gruppe exportieren"
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr "Domain-Besitz konnte nicht überprüft werden."
-
msgid "Failure"
msgstr "Fehlschlag"
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr "Fertiggestellt"
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr "Erstmals gesehen"
@@ -14884,6 +15002,9 @@ msgstr "Fehler in deiner .gitlab-ci.yml gefunden:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr "Allgemeine Pipelines"
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr "Generiere einen Standardsatz von Labels"
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr "GitLab-Projekt exportieren"
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "GitLab wird einen Hintergrundjob ausführen, der pseudonymisierte CSVs der GitLab-Datenbank erzeugt, die in dein konfiguriertes Objektspeicherverzeichnis hochgeladen werden."
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr "Gitea-Import"
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr "Gruppenavatar"
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr "Gruppenbeschreibung (optional)"
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "Beim Abfragen der Epics ist etwas schief gelaufen"
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr "Keine Gruppen gefunden"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Du kannst die Berechtigungen deiner Gruppenmitglieder und den Zugriff auf jedes Projekt in der Gruppe verwalten."
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr "Kopfzeilennachricht"
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr "Verlauf"
msgid "History of authentications"
msgstr "Verlauf der Authentifizierungen"
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr "Inline"
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr "Gib die Host-Schlüssel manuell ein"
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr "Interne Benutzer(innen)"
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr "Letzter Zugriff am"
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "Letzte Pipeline"
msgid "Last Seen"
msgstr "Zuletzt gesehen"
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr "Maximalzahl an %{name}s (%{count}) überschritten"
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr "Metriken und Profiling"
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr "Panel erweitern"
msgid "Metrics|For grouping similar metrics"
msgstr "Zum Gruppieren ähnlicher Metriken"
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr "Y-Achsen-Bezeichnung"
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr "Meine Firma oder Team"
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr "Netzwerk"
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr "Neuer Tag"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr "Keine Beiträge gefunden"
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr "Keine Kreditkarte erforderlich."
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr "Nicht verfügbar für private Projekte"
msgid "Not available for protected branches"
msgstr "Für geschützte Branches nicht verfügbar"
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr "Nicht vertraulich"
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr "Vorgänge"
-
msgid "Operations Dashboard"
msgstr "Operations Dashboard"
@@ -23947,6 +24182,9 @@ msgstr "Optional"
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "Optional kannst du %{link_to_customize}, wie FogBugz E-Mail-Adressen und Benutzernamen in GitLab importiert werden."
@@ -23956,6 +24194,9 @@ msgstr "Optionen"
msgid "Or you can choose one of the suggested colors below"
msgstr "Oder du wählst eine der unten vorgeschlagenen Farben"
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr "Besitzer(in)"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr "Pfad:"
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr "Pausieren"
@@ -24616,6 +24886,9 @@ msgstr "In Arbeit"
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "Derzeit gibt es keine Pipelines."
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "Beim Abrufen der Pipelines ist ein Fehler aufgetreten. Versuche es in einigen Augenblicken noch einmal oder wende dich an dein Support-Team."
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr "Unformatierter Diff"
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Bitte gib einen beschreibenden Namen für deine Gruppe ein."
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr "Profil"
msgid "Profile Settings"
msgstr "Profileinstellungen"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr "Du bist dabei, %{yourAccount} permanent zu löschen, inklusive aller Tic
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr "Du bist dabei, deinen Benutzernamen von %{currentUsernameBold} in %{newUsernameBold} zu ändern. Profile und Projekte werden auf den neuen %{newUsername}-Namensraum umgeleitet, aber diese Umleitung wird auslaufen, sobald der %{currentUsername}-Namensraum von einem anderen Benutzer oder einer anderen Gruppe registriert wird. Bitte aktualisiere deine Git-Repository-Remotes so bald wie möglich."
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr "Füge Status-Emoji hinzu"
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr "Avatar zuschneiden"
@@ -26221,6 +26518,9 @@ msgstr "Du kannst deinen Avatar hier hochladen oder bei %{gravatar_link} ändern
msgid "Profiles|You don't have access to delete this user."
msgstr "Du hast keine Berechtigung, um diese(n) Benutzer(in) zu löschen."
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr "Dieses Feature erfordert einen Browser, der LocalStorage unterstützt"
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr "%{count} Alarme angewendet"
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr "Alarm hinzufügen"
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr "Alarm bearbeiten"
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr "Fehler beim erstellen des Alarms"
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr "Fehler beim Löschen des Alarms"
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr "Fehler beim Abrufen des Alarms"
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr "Fehler beim Speichern des Alarm"
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr "Operator"
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr "Grenzwert"
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr "Provider"
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr "Pseudonymizer-Datensammlung"
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr "Wieder öffnen"
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr "Auswählen"
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "Anfrage auf Zugriff"
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr "Anforderungen"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] "Benötigt die Zustimmung von %{names}."
-msgstr[1] "Benötigt noch %{count} Zustimmungen von %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
+msgstr[0] ""
+msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr "Runners"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr "Runner derzeit online: %{active_runners_count}"
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr "Wird ausgeführt"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr "Anwendung speichern"
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr "Grund auswählen"
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr "Serverversion"
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr "Lege ein Passwort für dein Konto fest, um mittels %{protocol} zu übert
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,12 +31438,12 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "ein Passwort festlegst"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr "Statusemoji hinzufügen"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "SetStatusModal|Busy"
msgstr ""
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr "Smartcard"
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "Smartcard-Authentifizierung fehlgeschlagen: Client-Zertifikat-Header fehlt."
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "Codeausschnitte"
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr "Suche starten"
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "Gib deine Nachricht an, um sie zu aktivieren"
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr "Sonntag"
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr "Tags erlauben es, bestimmte Punkte in der git-Historie als wichtig zu ma
msgid "TagsPage|This tag has no release notes."
msgstr "Dieses Tag enthält keine Versionshinweise."
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "Verwende den Befehl git tag, um einen neuen Tag hinzuzufügen:"
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "Team"
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Die Verbindung wird nach %{timeout} beendet. Verwende eine Clone/Push-Kombination für Repositorys, die länger brauchen."
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "Die Bereitstellung dieses Jobs auf %{environmentLink} war nicht erfolgreich."
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "Die Pseudonymizer-Datensammlung ist deaktiviert. Wenn sie aktiv ist, führt GitLab einen Hintergrundjob aus, der pseudonymisierte CSVs der GitLab-Datenbank erzeugt, die in dein konfiguriertes Objektspeicherverzeichnis hochgeladen werden."
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr "Es gibt noch keine geteilten Projekte mit dieser Gruppe"
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr "Zu viele Projekte aktviert. Sie müssen sie über die Konsole oder die A
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr "Rückgängig machen"
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr "Template verwenden"
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr "Benutzereinstellungen"
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Wenn ein Runner gesperrt ist, kann er keinem anderen Projekt zugewiesen werden"
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr "Wenn die URL leer gelassen wird, können Klassifizierungslabels weiterhi
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "Du kannst den Merge-Konflikt lösen, indem du entweder den interaktiven Modus verwendest, indem du die Schaltflächen %{use_ours} oder %{use_theirs} wählst, oder indem du die Dateien direkt bearbeitest. Übernimm diese Änderungen mittels Commit in %{branch_name}"
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr "ein(e) gelöschte(r) Benutzer(in)"
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] "etwa 1 Stunde"
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "%{remainingPackagesCount} mehr"
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,8 +40202,14 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
-msgstr "Code-Qualität"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
msgid "ciReport|Container Scanning"
msgstr ""
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr "SAST"
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr "%{metricsLinkStart} Speicherauslastung %{metricsLinkEnd} ist %{emphasisS
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr "Genehmigt von"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr "Lade Bereitstellungsstatistiken"
@@ -40594,9 +41077,6 @@ msgstr "Merge fehlgeschlagen."
msgid "mrWidget|Merge locally"
msgstr "Lokal mergen"
-msgid "mrWidget|Merge request approved."
-msgstr "Merge-Request genehmigt."
-
msgid "mrWidget|Merged by"
msgstr "Merged von"
@@ -40711,12 +41191,6 @@ msgstr "Der Quellbranch wird nicht gelöscht"
msgid "mrWidget|There are merge conflicts"
msgstr "Es gibt Merge-Konflikte"
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Dieser Merge-Request konnte nicht automatisch gemerged werden"
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr "oder"
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "von insgesamt %d Test"
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index 703c60acc61..686b5a891fa 100644
--- a/locale/el_GR/gitlab.po
+++ b/locale/el_GR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: el\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index dd03557924a..840e9c164c2 100644
--- a/locale/eo/gitlab.po
+++ b/locale/eo/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: eo\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Aktiva"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Kompari"
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Krei novan dosierujon"
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,18 +10945,36 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "Difini propran Åablonon, uzante la sintakson de Cron"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr "Difini propran Åablonon, uzante la sintakson de Cron"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "Lasta ĉenstablo"
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr "Nova etikedo"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr "Opcioj"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr "Posedanto"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "Peti atingeblon"
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr "Kreu pasvorton por via konto por ebligi al vi eltiri kaj alpuÅi per %{p
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "kreos pasvorton"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index 202ce89bff5..7efd0433a6d 100644
--- a/locale/es/gitlab.po
+++ b/locale/es/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr " %{start} hasta %{end}"
@@ -40,25 +40,12 @@ msgstr " Tipo"
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr " y"
-
msgid " and "
msgstr " y "
msgid " and %{sliced}"
msgstr " y %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " degradado en %d punto"
-msgstr[1] " degradado en %d puntos"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " mejorado en %d punto"
-msgstr[1] " mejorado en %d puntos"
-
msgid " or "
msgstr " o "
@@ -86,6 +73,9 @@ msgstr "El tamaño de \"%{repository_name}(%{repository_size}) es mayor que el l
msgid "\"el\" parameter is required for createInstance()"
msgstr "El parámetro \"el\" es necesario para createInstance()"
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr "#general, #desarrollo"
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] "%d commit,"
msgstr[1] "%d commits,"
-msgid "%d commits"
-msgstr "%d commits"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] "%d incidencia completada"
@@ -1055,6 +1042,9 @@ msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} le permiten enviar noti
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} le permiten enviar notificaciones a aplicaciones web en respuesta a eventos en un grupo o proyecto. Recomendamos utilizar una %{integrations_link_start}integración%{link_end} en lugar de un webhook."
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr "(eliminado)"
msgid "(revoked)"
msgstr "(revocado)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr "(Necesitamos su contraseña actual para confirmar sus cambios)"
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} más"
@@ -1193,6 +1189,9 @@ msgstr[1] "- Eventos"
msgid "- Not available to run jobs."
msgstr "- No disponible para ejecutar trabajos."
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- Usuario"
@@ -1439,9 +1438,6 @@ msgstr "No se puede elegir una rama por defecto para un proyecto vacío."
msgid "A deleted user"
msgstr "Un usuario eliminado"
-msgid "A description is required"
-msgstr "Es necesaria una descripción"
-
msgid "A different reason"
msgstr "Una motivo diferente"
@@ -1475,8 +1471,8 @@ msgstr "Un miembro del equipo revisará su informe tan pronto como sea posible."
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
-msgstr "Se ha creado un nuevo pipeline de Auto DevOps, vaya a la página de pipelines %{pipelines_link_start}%{pipelines_link_end} para más detalles"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
+msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
msgstr "Se publicó una nueva versión %{tag} para %{name}. Visite la página de %{release_link_start}versiones%{release_link_end} para obtener más información al respecto."
@@ -1502,6 +1498,9 @@ msgstr "Un valor de plataforma puede ser web, mob o aplicación."
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr "Acciones"
msgid "Activate Service Desk"
msgstr "Activar Service Desk"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Activo"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Añadir un comentario general a este %{noteableDisplayName}."
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "Añadir un comentario general a este %{noteable_name}."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Añada una página de inicio a su wiki que contenga información sobre su proyecto y GitLab la mostrará aquí en lugar de este mensaje."
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr "Añadir dominio"
-
msgid "Add email address"
msgstr "Añadir dirección de correo electrónico"
@@ -2108,6 +2104,9 @@ msgstr "Añadir a revisión"
msgid "Add to tree"
msgstr "Agregar al árbol"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr "Añadir disparador"
@@ -2564,8 +2563,8 @@ msgstr "Ajuste la configuración del límite de usuarios en tu instancia"
msgid "AdminUsers|Admin"
msgstr "Admin"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
-msgstr "Los administradores tienen acceso a todos los grupos, proyectos y usuarios y pueden administrar todas las funcionalidades en esta instalación"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgstr ""
msgid "AdminUsers|Admins"
msgstr "Administradores"
@@ -2579,6 +2578,12 @@ msgstr "¿Aprobar al usuario %{username}?"
msgid "AdminUsers|Approved users can:"
msgstr "Los usuarios aprobados pueden:"
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr "Marcado automáticamente como usuario interno por defecto"
@@ -2714,8 +2719,8 @@ msgstr "Al reactivar un usuario:"
msgid "AdminUsers|Regular"
msgstr "Habituales"
-msgid "AdminUsers|Regular users have access to their groups and projects"
-msgstr "Los usuarios habituales tienen acceso a sus grupos y proyectos"
+msgid "AdminUsers|Regular users have access to their groups and projects."
+msgstr ""
msgid "AdminUsers|Reject"
msgstr "Rechazar"
@@ -3329,8 +3334,8 @@ msgstr "Se han solucionado todos los conflictos del merge. Puede realizar el mer
msgid "All merge request dependencies have been merged"
msgstr "Todas las dependencias de las peticiones de fusión han sido fusionadas"
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
-msgstr "Todas las rutas son relativas a la URL de GitLab. Por favor, no incluya la %{relative_url_link_start}URL relativa%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
+msgstr ""
msgid "All projects"
msgstr "Todos los proyectos"
@@ -3347,6 +3352,9 @@ msgstr "Todos los usuarios deben aceptar los términos de servicio y la polític
msgid "All users must have a name."
msgstr "Todos los usuarios deben tener un nombre."
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Permitir al grupo %{group_name} iniciar sesión"
@@ -3362,8 +3370,8 @@ msgstr "Permitir commits de los miembros que pueden hacer merge con la rama de d
msgid "Allow group owners to manage LDAP-related settings"
msgstr "Permitir a los propietarios de los grupos administrar configuraciones relacionadas con LDAP"
-msgid "Allow non-administrators to access to the performance bar"
-msgstr "Permitir a los usuarios no administradores acceder a la barra de rendimiento"
+msgid "Allow non-administrators access to the performance bar"
+msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Permitir que sólo los protocolos seleccionados tengan acceso a Git."
@@ -3602,14 +3610,17 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr "Se ha producido un error al obtener los ancestros"
-msgid "An error occurred while fetching branches. Retry the search."
-msgstr "Se ha producido un error al recuperar las ramas. Por favor, vuelva a intentar la búsqueda."
+msgid "An error occurred while fetching branches. Retry the search."
+msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
-msgstr "Se ha producido un error al obtener los commits. Por favor, vuelva a intentar la búsqueda."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
+msgstr ""
msgid "An error occurred while fetching coverage reports."
msgstr "Se ha producido un error al recuperar los informes de cobertura."
@@ -3812,6 +3823,11 @@ msgstr "Se ha producido un error al obtener los proyectos."
msgid "An error occurred while saving changes: %{error}"
msgstr "Se ha producido un error al guardar los cambios: %{error}"
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "Se ha producido un error al suscribirse a las notificaciones."
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr "Ya existe un dominio serverless a nivel de instancia."
-
msgid "An issue already exists"
msgstr "Ya existe una incidencia"
@@ -4210,12 +4223,18 @@ msgstr "Todos los escáneres"
msgid "ApprovalRule|All severity levels"
msgstr "Todos los niveles de gravedad"
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr "Reglas de aprobación"
@@ -4228,12 +4247,21 @@ msgstr "Tipo de aprobador"
msgid "ApprovalRule|Approvers"
msgstr "Aprobadores"
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr "Ejemplos: QA, Seguridad."
msgid "ApprovalRule|Name"
msgstr "Nombre"
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr "Por favor, seleccione al menos un escáner de seguridad"
msgid "ApprovalRule|Please select at least one severity level"
msgstr "Por favor seleccione al menos un nivel de gravedad"
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr "Nombre de la regla"
@@ -4261,6 +4298,9 @@ msgstr "Seleccionar escáneres"
msgid "ApprovalRule|Select severity levels"
msgstr "Seleccione los niveles de gravedad"
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr "Niveles de gravedad"
@@ -4270,6 +4310,9 @@ msgstr "Branch de destino"
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr "Vulnerabilidades permitidas"
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr "¿Está seguro? Eliminar esta clave GPG no afecta a los commits ya firma
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr "¿Está seguro de que desea continuar? Se cerrará la sesión en el dispositivo y todos los tokens serán revocados."
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr "¿Está seguro de que desea continuar? Al hacer esto se invalidarán sus aplicaciones registradas y sus dispositivos U2F."
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr "¿Está seguro?. Al hacer esto invalidará sus aplicaciones registradas y sus dispositivos U2F."
-
msgid "Arrange charts"
msgstr "Organizar gráficas"
@@ -4783,6 +4820,9 @@ msgstr "Agosto"
msgid "Authenticate"
msgstr "Autenticar"
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr "Autenticar con GitHub"
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr "Blog"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "El alcance del panel de control afecta qué problemas se muestran para cualquiera persona que visite este panel"
@@ -5656,8 +5699,8 @@ msgstr "Todas"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "No puedo encontrar el commit HEAD para esta rama"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "Comparar"
@@ -5767,6 +5810,9 @@ msgstr "Para confirmar, teclee %{branch_name_confirmation}:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Para descartar los cambios locales y sobreescribir la rama actual en el servidor, elimínela aquí y seleccione 'Actualizar ahora' en el enlace situado la parte superior."
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr "Cl Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr "Minutos de CI"
-
msgid "CI settings"
msgstr "Configuración de CI"
@@ -6261,9 +6304,6 @@ msgstr "Cancelando la vista previa"
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr "No se puede asignar a otros proyectos."
-
msgid "Cannot be merged automatically"
msgstr "No se puede hacer merge automáticamente"
@@ -6321,6 +6361,12 @@ msgstr "No se puede omitir la configuración de autenticación de dos factores"
msgid "Capacity threshold"
msgstr "Límite de capacidad"
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr "Forzar para todos los subgrupos"
@@ -6649,6 +6695,9 @@ msgstr "Paquete de minutos CI"
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr "Editar"
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr "empresa o equipo"
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr "Elegir una plantilla..."
msgid "Choose a type..."
msgstr "Elegir un tipo..."
-msgid "Choose any color"
-msgstr "Seleccione cualquier color"
-
msgid "Choose any color."
msgstr "Elegir cualquier color."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr "Seleccione cualquier color. O puede seleccionar alguno de los qcolores sugeridos a continuación"
-
msgid "Choose file…"
msgstr "Seleccione un archivo…"
@@ -7489,7 +7538,7 @@ msgstr "Verifique el estado de su clúster"
msgid "ClusterIntegration|Check your token"
msgstr "Verifique su token"
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr "Grupo de seguridad"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Consulte y edite los detalles de su clúster de Kubernetes"
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr "Seleccione una VPC para elegir un grupo de seguridad"
@@ -7939,6 +7991,9 @@ msgstr "Seleccione una VPC para elegir una subred"
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "Seleccione una red para elegir una subred"
@@ -7948,9 +8003,24 @@ msgstr "Seleccione una región para elegir un par de claves"
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr "Seleccione una región para elegir una VPC"
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr "Seleccione una zona para elegir una red"
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "Seleccione el tipo de máquina"
@@ -7963,6 +8033,9 @@ msgstr "Seleccione el proyecto y la zona para elegir el tipo de máquina"
msgid "ClusterIntegration|Select project to choose zone"
msgstr "Seleccione un proyecto para elegir la zona"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr "cumple con los requisitos"
msgid "ClusterIntegration|sign up"
msgstr "regístrese"
-msgid "ClusterIntergation|Select a VPC"
-msgstr "Seleccione una VPC"
-
-msgid "ClusterIntergation|Select a network"
-msgstr "Seleccione una red"
-
-msgid "ClusterIntergation|Select a security group"
-msgstr "Seleccione un grupo de seguridad"
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr "Seleccione una subred"
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr "Seleccione una subred"
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr "Seleccione un tipo de instancia"
-
-msgid "ClusterIntergation|Select key pair"
-msgstr "Seleccione el par de claves"
-
-msgid "ClusterIntergation|Select service role"
-msgstr "Seleccione el rol de servicio"
-
msgid "Clusters|An error occurred while loading clusters"
msgstr "Se ha producido un error al cargar los clústeres"
@@ -8275,12 +8324,6 @@ msgstr "No se aplicaron los comandos"
msgid "Comment"
msgstr "Comentar"
-msgid "Comment & close %{noteable_name}"
-msgstr "Comentar y cerrar %{noteable_name}"
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr "Comentar y volver a abrir %{noteable_name}"
-
msgid "Comment & resolve thread"
msgstr "Comentar y resolver hilo"
@@ -8397,6 +8440,9 @@ msgstr "Foro de la comunidad"
msgid "Company"
msgstr "Empresa"
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Comparar"
@@ -8478,31 +8524,37 @@ msgstr "Completado"
msgid "Completed"
msgstr "Completado"
-msgid "Compliance"
-msgstr "Cumplimiento"
-
-msgid "Compliance Dashboard"
-msgstr "Panel de cumplimiento"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
+msgstr ""
msgid "Compliance framework"
msgstr "Framework de cumplimiento"
+msgid "Compliance report"
+msgstr ""
+
msgid "ComplianceDashboard|created by:"
msgstr "Creado por:"
msgid "ComplianceFrameworks|Add framework"
msgstr "Añadir framework"
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr "Eliminar framework"
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr "Editar framework"
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr "Configurar la instalación existente"
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr "Configurar las réplicas del repositorio."
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr "Contactar con soporte"
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "Registro de contenedores"
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr "Está a punto de eliminar el repositorio %{title}. Una vez que confirme
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr "Puede añadir una imagen a este registro utilizando los siguientes comandos:"
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr "Contiene %{count} archivos de imágenes de tipo blob con un tamaño de (%{size})"
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr "Copiar %{name}"
msgid "Copy %{protocol} clone URL"
msgstr "Copiar la URL de clonado del protocolo %{protocol}"
-msgid "Copy %{proxy_url}"
-msgstr "Copiar %{proxy_url}"
-
msgid "Copy %{type}"
msgstr "Copiar %{type}"
@@ -9315,9 +9364,6 @@ msgstr "Copiar enlace"
msgid "Copy link to chart"
msgstr "Copiar enlace al gráfico"
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr "Copiar la referencia"
@@ -9402,9 +9448,6 @@ msgstr "No se puede agregar administradores como miembros"
msgid "Could not apply %{name} command."
msgstr "No se pudo aplicar el comando %{name}."
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr "No se puede autorizar el nick del chat. Por favor, inténtelo de nuevo"
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr "Cobertura"
@@ -9528,6 +9574,9 @@ msgstr "Crear %{humanized_resource_name}"
msgid "Create %{type}"
msgstr "Crear %{type}"
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Crear Nuevo Directorio"
@@ -9540,9 +9589,6 @@ msgstr "Cree primero una cuenta de GitLab y luego conéctela a su cuenta %{label
msgid "Create a Mattermost team for this group"
msgstr "Crear un equipo de Mattermost para este grupo"
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr "Cree un proxy local para almacenar las imágenes usadas frecuentemente con anterioridad. %{link_start}Obtenga más%{link_end} información sobre los proxies de dependencias."
-
msgid "Create a merge request"
msgstr "Crear un merge request"
@@ -9558,6 +9604,9 @@ msgstr "Cree un nuevo archivo ya todavía no hay archivos. Posteriormente, podrÃ
msgid "Create a new issue"
msgstr "Crear una nueva incidencia"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr "Crear un nuevo repositorio"
@@ -9693,6 +9742,9 @@ msgstr "Crear fragmento de código"
msgid "Create tag %{tagName}"
msgstr "Crear etiqueta %{tagName}"
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr "Crear usuario"
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,11 +9985,8 @@ msgstr "Tokens de acceso personal"
msgid "CredentialsInventory|SSH Keys"
msgstr "Claves SSH"
-msgid "Credit card validated at:"
-msgstr "Tarjeta de crédito validada el:"
-
-msgid "Credit card validated:"
-msgstr "Tarjeta de crédito validada:"
+msgid "Credit card:"
+msgstr ""
msgid "Critical vulnerabilities present"
msgstr "Vulnerabilidades críticas presentes"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr "Contador de vulnerabilidades"
@@ -10047,6 +10099,15 @@ msgstr "Rango personalizado"
msgid "Custom range (UTC)"
msgstr "Rango personalizado (UTC)"
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr "Personalizable por un administrador."
@@ -10206,6 +10267,9 @@ msgstr "Días hasta completar"
msgid "CycleAnalytics|Display chart filters"
msgstr "Mostrar filtros de gráficos"
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr "Ninguna etapa seleccionada"
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10767,6 +10834,9 @@ msgstr "Selector de fecha"
msgid "Date range"
msgstr "Rango de fechas"
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr "Rama por defecto"
msgid "Default branch and protected branches"
msgstr "Ramas por defecto y ramas protegidas"
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr "Etiqueta de clasificación por defecto"
@@ -10872,18 +10945,36 @@ msgstr "Por defecto: Asignar un ID de cuenta de FogBugz a un nombre completo"
msgid "DefaultBranchLabel|default"
msgstr "Por defecto"
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "Definir un patrón personalizado con la sintaxis de cron"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
+msgid "Define a custom pattern with cron syntax"
+msgstr "Definir un patrón personalizado con la sintaxis de cron"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -10956,9 +11047,6 @@ msgstr "Eliminar comentario"
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr "Eliminar dominio"
-
msgid "Delete file"
msgstr "Eliminar el archivo"
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr "Eliminar fragmento de código"
@@ -11016,6 +11101,9 @@ msgstr "Eliminar la lista de usuarios"
msgid "Delete variable"
msgstr "Eliminar variable"
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "Se ha producido un error al eliminar el repositorio del proyecto. Por favor, inténtelo de nuevo o póngase en contacto con el administrador."
@@ -11178,13 +11266,13 @@ msgstr "Proxy de dependencias"
msgid "Dependency Scanning"
msgstr "Escaneo de dependencias"
-msgid "Dependency proxy"
-msgstr "Proxy de dependencias"
+msgid "DependencyProxy|Cached %{time}"
+msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
-msgstr "La funcionalidad del proxy de dependencias está limitada, por ahora, únicamente a grupos públicos."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
+msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,8 +11281,20 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
-msgstr "Cambiar el proxy de dependencias"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
+msgstr ""
msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr "%{current_design} de %{designs_count}"
msgid "DesignManagement|%{filename} did not change."
-msgstr "%{filename} no ha cambiado."
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "Agregar un diseño con el mismo nombre de archivo reemplaza el archivo en una nueva versión."
@@ -11615,6 +11717,12 @@ msgstr "Guardar comentario"
msgid "DesignManagement|Select all"
msgstr "Seleccionar todo"
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr "El número máximo de diseños permitidos que se pueden cargar es %{upload_limit}. Por favor, inténtalo de nuevo."
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr "Subir diseños"
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr "y %{moreCount} más."
-
msgid "Designs"
msgstr "Diseños"
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr "MRs"
msgid "DevopsAdoption|No results…"
msgstr "Sin resultados…"
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr "No adoptado"
@@ -11813,6 +11924,9 @@ msgstr "Se ha producido un error al recuperar los grupos. Por favor, actualice l
msgid "DevopsAdoption|This group has no subgroups"
msgstr "Este grupo no tiene subgrupos"
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr "Iniciar una prueba gratuita"
msgid "Discover|Upgrade now"
msgstr "Actualizar ahora"
-msgid "Discuss a specific suggestion or question"
-msgstr "Discuta una sugerencia específica o una pregunta"
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr "Discuta una propuesta específica o una pregunta que necesita ser resuelta"
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr "Discutir una propuesta específica o una pregunta que necesita ser resuelta."
@@ -12097,18 +12205,6 @@ msgstr "Dominio"
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr "El dominio se ha creado correctamente."
-
-msgid "Domain was successfully deleted."
-msgstr "El dominio se ha eliminado correctamente."
-
-msgid "Domain was successfully updated."
-msgstr "El dominio se ha actualizado correctamente."
-
msgid "Don't have an account yet?"
msgstr "¿Todavía no tiene una cuenta?"
@@ -12139,9 +12235,6 @@ msgstr "Descargar %{format}"
msgid "Download %{format}:"
msgstr "Descargar %{format}:"
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr "Editar esta versión"
msgid "Edit title and description"
msgstr "Editar título y descripción"
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,12 +12787,9 @@ msgstr "Habilitar o deshabilitar la recolección de datos con Pseudonymizer."
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
-msgid "Enable proxy"
-msgstr "Habilitar el proxy"
-
msgid "Enable reCAPTCHA"
msgstr "Habilitar reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr "Introduzca un número"
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr "Empresa"
msgid "Environment"
-msgstr "Entorno"
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr "Ocurrió un error al detener el entorno, por favor inténtelo de nuevo"
msgid "Environments|Are you sure you want to stop this environment?"
msgstr "¿Está seguro de que desea detener este entorno?"
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr "Error al crear la tarea épica"
msgid "Error creating label."
msgstr "Se ha producido un error al crear la etiqueta."
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr "Error con Akismet. Por favor, compruebe los registros de error para obte
msgid "Error: %{error_message}"
msgstr "Error: %{error_message}"
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr "Exactamente uno de los %{attributes} es necesario"
msgid "Example: @sub\\.company\\.com$"
msgstr "Ejemplo: @sub\\.empresa\\.com$"
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr "Ejemplo: Uso = consulta simple. (Solicitado)/(Capacidad) = Varias consultas combinadas en una sola fórmula."
-
msgid "Except policy:"
msgstr "Extracto de la política:"
@@ -13833,6 +13934,9 @@ msgstr "Fecha de vencimiento"
msgid "Expiration date (optional)"
msgstr "Fecha de vencimiento (opcional)"
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr "Caducó"
@@ -13848,6 +13952,9 @@ msgstr "Caduca"
msgid "Expires in %{expires_at}"
msgstr "Caduca en %{expires_at}"
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr "Caduca:"
@@ -13875,9 +13982,6 @@ msgstr "Explorar grupos públicos"
msgid "Export"
msgstr "Exportar"
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr "Exportar grupo"
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "Exportar proyecto"
@@ -13974,6 +14084,11 @@ msgstr "Se ha producido un error al agregar una reunión de Zoom"
msgid "Failed to apply commands."
msgstr "Se ha producido un error al aplicar los comandos."
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr "Se ha producido un error al actualizar."
msgid "Failed to upload object map file"
msgstr "Se ha producido un error al cargar el archivo de mapa de objetos"
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr "Error"
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr "Eliminar"
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr "Finalizado"
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr "Visto por primera vez"
@@ -14884,6 +15002,9 @@ msgstr "Se han encontrado errores en su fichero .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr "Configuración general"
msgid "General pipelines"
msgstr "Pipelines"
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr "Generar un conjunto predeterminado de etiquetas"
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr "GitLab commit"
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr "URL de metadatos de GitLab"
msgid "GitLab project export"
msgstr "Exportar proyecto desde GitLab"
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "Gitlab ejecutará un trabajo como tarea de fondo que producirá un archivo CSV seudonimizado de la base de datos de Gitlab y que se cargará a su directorio de almacenamiento de objetos que tenga configurado."
-
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
-msgstr "El soporte para dominios y certificados está deshabilitado. Solicite al administrador de su sistema que lo habilite."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr "Importar desde Gitea"
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr "Avatar del grupo"
msgid "Group by"
msgstr "Agrupar por"
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr "Descripción del grupo (opcional)"
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr "No se encuentran grupos"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Puede administrar los permisos y el acceso de cada miembro del grupo a cada proyecto del grupo."
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr "Encabezado del mensaje"
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,8 +16925,8 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
-msgstr "Ayuda a reducir el volumen de solicitudes para rutas protegidas"
+msgid "Helps reduce request volume for protected paths."
+msgstr ""
msgid "Here you will find recent merge request activity"
msgstr ""
@@ -16850,9 +16986,6 @@ msgstr "Ocultar valores"
msgid "High or unknown vulnerabilities present"
msgstr "Hay vulnerabilidades altas o desconocidas presentes"
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr "Mayor número de solicitudes por minuto para cada ruta sin procesar, por defecto, 300. Para deshabilitar esta limitación, establezca en 0."
-
msgid "Highest role:"
msgstr "Rol más alto:"
@@ -16874,6 +17007,9 @@ msgstr "Historial"
msgid "History of authentications"
msgstr "Historial de autentificación"
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr "Hora (UTC)"
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr "Mantenimiento"
@@ -16910,6 +17049,9 @@ msgstr "Tareas de mantenimiento, exportación, ruta, transferencia, eliminación
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr "Heredado:"
msgid "Inline"
msgstr "En línea"
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr "Introducir las claves del host manualmente"
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr "Integración"
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr "Limitaciones del navegador"
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr "URL interna (opcional)"
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr "Usuarios internos"
@@ -18523,9 +18695,6 @@ msgstr "Pod_name no válido"
msgid "Invalid policy type"
msgstr "Tipo de política no válido"
-msgid "Invalid query"
-msgstr "Consulta no válida"
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr "Cancelar"
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr "Fecha de inicio"
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr "con"
msgid "Join Zoom meeting"
msgstr "Unirse a la reunión de Zoom"
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr "Último acceso el"
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "Último Pipeline"
msgid "Last Seen"
msgstr "Visto por última vez"
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr "Obtenga más información sobre los despliegues en un clúster"
msgid "Learn more about group-level project templates"
msgstr "Obtenga más información sobre las plantillas de proyectos a nivel de grupo"
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr "Asegúrese de guardarlo, no podrá volver a acceder a él."
msgid "Makes this issue confidential."
msgstr "Convierte la incidencia en confidencial."
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr "Añadir texto en cursiva (%{modifier_key}I)"
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr "Número máximo de %{name} (%{count}) excedido"
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr "Número máximo de comentarios excedido"
@@ -21065,6 +21273,9 @@ msgstr "Número máximo de réplicas que se pueden sincronizar al mismo tiempo."
msgid "Maximum number of projects."
msgstr "Número máximo de proyectos."
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr "Métricas e informes"
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr "Expandir el panel"
msgid "Metrics|For grouping similar metrics"
msgstr "Para agrupar métricas similares"
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr "Rango de tiempo inválido, por favor verifíquelo."
@@ -21883,9 +22106,6 @@ msgstr "Ver la documentación"
msgid "Metrics|View logs"
msgstr "Ver registros"
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr "Etiqueta del eje Y"
@@ -22332,6 +22552,9 @@ msgstr "Mi increíble grupo"
msgid "My company or team"
msgstr "Mi empresa o equipo"
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr "Mi reacción"
@@ -22448,6 +22671,9 @@ msgstr "Necesita atención"
msgid "Network"
msgstr "Red"
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr "Nueva etiqueta"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr "Nuevos usuarios configurados como externos"
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr "Sin contribuciones"
msgid "No contributions were found"
msgstr "No se encontraron contribuciones"
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr "No se necesita tarjeta de crédito."
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr "No se han encontrado vulnerabilidades"
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr "No está disponible para proyectos privados"
msgid "Not available for protected branches"
msgstr "No está disponible para ramas protegidas"
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr "No es confidencial"
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr "Número de LOCs por commit"
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr "Número de cambios (ramas o etiquetas) en un solo push para determinar si se activarán o no los webhooks y servicios. Los webhooks y servicios no se enviarán si sobrepasa ese valor."
-
msgid "Number of commits"
msgstr "Número de commits"
msgid "Number of commits per MR"
msgstr "Número de commits por MR"
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr "Más antiguo primero"
msgid "OmniAuth"
msgstr "OmniAuth"
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr "Escaneos bajo demanda"
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr "Abrir la selección"
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr "Errores abiertos"
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr "Operación no permitida"
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr "Se ha agotado el tiempo de la operación. Por favor, compruebe los registros del pod para %{pod_name} para obtener más información."
-msgid "Operations"
-msgstr "Operaciones"
-
msgid "Operations Dashboard"
msgstr "Panel de control de operaciones"
@@ -23947,6 +24182,9 @@ msgstr "Opcional"
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "Opcionalmente, puede %{link_to_customize} cómo se importan en Gitlab las direcciones de correo y los nombres de usuario de FogBugz."
@@ -23956,6 +24194,9 @@ msgstr "Opciones"
msgid "Or you can choose one of the suggested colors below"
msgstr "O puede seleccionar alguno de los colores sugeridos a continuación"
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr "Propietario"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr "Registro de paquetes"
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr "Comando NuGet"
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr "Ruta:"
msgid "Paths can contain wildcards, like */welcome"
msgstr "Las rutas pueden contener comodines, como por ejemplo */welcome"
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr "Pausar"
@@ -24616,6 +24886,9 @@ msgstr "Pendiente"
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "Actualmente no hay pipelines."
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "Se ha producido un error al obtener los pipelines. Por favor, inténtelo de nuevo en unos momentos o contacte con su equipo de soporte."
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr "Dif simple"
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr "Plan:"
@@ -25462,9 +25744,15 @@ msgstr "Por favor, introduzca un número válido"
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Por favor ingrese un nombre descriptivo para su grupo."
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr "Perfil"
msgid "Profile Settings"
msgstr "Configuración del perfil"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr "Página del perfil:"
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr "Encendido"
@@ -25900,9 +26197,6 @@ msgstr "Está a punto de eliminar permanentemente %{yourAccount}, y todas las in
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr "Está a punto de renombrar el usuario %{currentUsernameBold} a %{newUsernameBold}. El perfil del usuario y los proyectos serán redirigidos al espacio de nombres %{newUsername} pero este redireccionamiento caducará una vez que otro usuario o grupo registre el %{currentUsername}. Por favor, actualice los remotos de su repositorio Git tan pronto como sea posible."
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr "Agregar emoji de estado"
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr "Redimensionador de avatar"
@@ -26221,6 +26518,9 @@ msgstr "Puede subir directamente su avatar aquí o modificarlo en %{gravatar_lin
msgid "Profiles|You don't have access to delete this user."
msgstr "No tienes acceso para eliminar este usuario."
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "Interno"
@@ -26731,6 +27040,9 @@ msgstr "Incidencias"
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr "Spring"
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr "IOS (Swift)"
@@ -27079,6 +27397,9 @@ msgstr "Esta función requiere que el navegador permita la utilización de almac
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr "Le permite que pueda clonar inmediatamente el repositorio de este proyecto. Puede omitir este paso si planea hacer push a un repositorio existente."
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr "Formato de la descripción"
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr "Importar"
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr "No hay opciones de importación disponibles"
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "Descripción del proyecto %{tag_start}(opcional)%{tag_end}"
@@ -27136,54 +27463,9 @@ msgstr "¿Desea alojar varios proyectos independientes bajo el mismo espacio de
msgid "Prometheus"
msgstr "Prometheus"
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr "%{count} alertas aplicadas"
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr "Añadir alerta"
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr "Editar alerta"
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr "Se ha producido un error al crear la alerta"
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr "Se ha producido un error al eliminar la alerta"
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr "Se ha producido un error al recuperar la alerta"
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr "Se ha producido un error al guardar la alerta"
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr "Operador"
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr "Seleccionar consulta"
-
-msgid "PrometheusAlerts|Threshold"
-msgstr "Umbral"
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr "Entorno protegido"
-msgid "Protected Paths"
-msgstr "Rutas protegidas"
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr "Ramas protegidas"
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr "Proveedor"
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr "Pseudonymizer data collection"
@@ -27841,9 +28129,6 @@ msgstr "Consulta"
msgid "Query cannot be processed"
msgstr "Se ha producido un error al procesar la consulta"
-msgid "Query is valid"
-msgstr "La consulta es válida"
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr "Reciente"
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr "Actividad reciente del proyecto"
msgid "Recent Searches Service is unavailable"
msgstr "El servicio de búsquedas recientes no está disponible"
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr "Volver a abrir"
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr "Seleccionar"
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "Solicitar acceso"
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,15 +29167,15 @@ msgstr "Requisitos"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] "Requiere aprobación de %{names}."
-msgstr[1] "Requiere %{count} aprobaciones más de %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
+msgstr[0] ""
+msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
-msgstr[0] "Requiere aprobación."
-msgstr[1] "Requiere %d aprobaciones más."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
+msgstr[0] ""
+msgstr[1] ""
msgid "Requires values to meet regular expression requirements."
msgstr ""
@@ -29229,9 +29520,6 @@ msgstr "Runners"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr "Ejecutores actualmente en línea: %{active_runners_count}"
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "Ha utilizado %{quotaUsed} de %{quotaLimit} de sus minutos de ejecución de pipelines con Runners compartidos."
@@ -29469,15 +29796,6 @@ msgstr "En ejecución"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "Ejecuta una serie de tareas de mantenimiento dentro del repositorio actual, como comprimir las revisiones de los archivos y eliminar objetos no disponibles."
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr "SAML"
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr "Guardar cambios"
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr "Guardar aplicación"
@@ -29905,6 +30220,9 @@ msgstr[1] "Resultados de la wiki"
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr "Crear incidencia"
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr "No se encontraron vulnerabilidades para este pipeline"
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr "Oops, algo parece que no está correcto."
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr "Proyecto"
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,12 +30880,12 @@ msgstr "Seleccionar página"
msgid "Select a branch"
msgstr ""
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "Seleccione un archivo en la barra lateral izquierda para comenzar la edición. Posteriormente, podrá hacer commit de sus cambios."
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
-msgstr ""
-
msgid "Select a group to invite"
msgstr "Seleccione un grupo a invitar"
@@ -30556,15 +30901,9 @@ msgstr "Seleccione un nuevo espacio de nombres"
msgid "Select a project"
msgstr "Seleccione un proyecto"
-msgid "Select a project to read Insights configuration file"
-msgstr "Seleccione un proyecto para leer el archivo de configuración de Insights"
-
msgid "Select a reason"
msgstr "Seleccione una razón"
-msgid "Select a repository"
-msgstr "Seleccione un repositorio"
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr "Versión del servidor"
msgid "Serverless"
msgstr "Serverless"
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr "Establezca una contraseña en su cuenta para hacer pull o push vía %{pr
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr "Configurar la integración con Jira"
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,12 +31438,12 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "establecer una contraseña"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr "Añadir emoji de estado"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "SetStatusModal|Busy"
msgstr ""
@@ -31180,6 +31507,11 @@ msgstr "Configuración"
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr "Incidencias similares"
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr "Consultas simples o combinadas"
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr "Tarjeta inteligente"
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "Falló la autenticación de la tarjeta inteligente: falta la cabecera del certificado del cliente."
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "Fragmentos de código"
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "No hay fragmentos de código que mostrar."
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr "Descripción (opcional)"
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr "Alguien editó esta incidencia al mismo tiempo que usted. Por favor revise %{linkStart} esta incidencia%{linkEnd} y asegúrese de que los cambios que ha realizado no eliminen sin querer los cambios realizados por la otra persona."
@@ -32246,12 +32581,6 @@ msgstr "Iniciar una búsqueda"
msgid "Start thread"
msgstr "Iniciar un hilo"
-msgid "Start thread & close %{noteable_name}"
-msgstr "Iniciar el hilo y cerrar %{noteable_name}"
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr "Iniciar el hilo y volver a abrir %{noteable_name}"
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "Indique su mensaje para activar"
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr "Desbloqueado con éxito"
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr "Domingo"
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr "URL de la página de soporte"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr "Los tags de git le permiten marcar puntos importantes y específicos en
msgid "TagsPage|This tag has no release notes."
msgstr "Esta etiqueta no tiene notas de la versión."
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "Utilice el comando git tag para agregar una nueva:"
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "Equipo"
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] "El %{type} contiene los siguientes errores:"
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "La conexión terminará después de %{timeout}. Para los repositorios que tarden más tiempo, utilice una combinación de git clone y git push."
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr "El contenido de esta página no está codificado en UTF-8. Las ediciones sobre este contenido, solo se pueden realizar a través del repositorio Git."
@@ -33762,9 +34082,6 @@ msgstr "La lista de dependencias detalla la información sobre los componentes u
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "El despliegue de este trabajo en %{environmentLink} no tuvo éxito."
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr "El directorio se ha creado correctamente."
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr "La configuración global requiere que habilite la autenticación de dos factores para su cuenta."
@@ -33917,6 +34237,9 @@ msgstr "La licencia se ha subido correctamente y está activada. Puede ver los d
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr "El tamaño máximo de archivo permitido es de %{size}."
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr "El proyecto se ha importado correctamente."
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr "¡El horario programado debe ser en el futuro!"
-
msgid "The snippet can be accessed without any authentication."
msgstr "Se puede acceder al fragmento de código sin necesidad ningún tipo de autenticación."
@@ -34220,6 +34537,9 @@ msgstr "Todavía no hay paquetes"
msgid "There are no projects shared with this group yet"
msgstr "Aún no hay proyectos compartidos con este grupo"
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr "Todavía no hay variables."
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr "Estas incidencias tienen un título similar al de la incidencia que está creando. Sería mejor hacer un comentario en alguna de estas en vez de crear otra incidencia similar."
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr "Esta variable no se puede enmascarar."
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr "Esto le redirigirá a una página de inicio de sesión externa."
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr "Para mantener este proyecto en marcha, crea una nueva incidencia"
msgid "To keep this project going, create a new merge request"
msgstr "Para mantener este proyecto en marcha, cree un nuevo merge request"
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr "Demasiados proyectos habilitados. Necesitará administrarlos a través d
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr "Temas (opcional)"
@@ -35802,8 +36146,8 @@ msgstr "El grupo ya es un grupo raíz."
msgid "TransferGroup|Group is already associated to the parent group."
msgstr "El grupo ya está asociado al grupo principal."
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
-msgstr "El grupo principal ya tiene un subgrupo definido con la misma ruta."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
+msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
msgstr "Transferencia fallida: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr "No se pueden obtener los proyectos vulnerables"
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr "Deshacer"
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr "Comprar minutos adicionales"
@@ -36605,10 +36958,10 @@ msgstr "Periodo actual de uso"
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr "Objetos LFS"
msgid "UsageQuota|LFS Storage"
msgstr "Almacenamiento LFS"
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr "Almacenamiento"
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,12 +37060,12 @@ msgstr "Subidas"
msgid "UsageQuota|Usage"
msgstr "Uso"
-msgid "UsageQuota|Usage Breakdown"
-msgstr ""
-
msgid "UsageQuota|Usage Quotas"
msgstr "Cuotas de uso"
+msgid "UsageQuota|Usage breakdown"
+msgstr ""
+
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
msgstr "Uso de los recursos del grupo a través de los proyectos en el grupo %{strong_start}%{group_name}%{strong_end}"
@@ -36860,6 +37213,9 @@ msgstr "Utilice un autenticador de contraseña de un solo uso en su dispositivo
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr "Utilice cURL"
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr "Utilizar plantilla"
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr "Ajustes de usuario"
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr "Utilizar la estrategia de cifrado requerida cuando falta el campo cifrad
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr "Validar"
@@ -37316,6 +37684,15 @@ msgstr "Valide su configuración de GitLab CI"
msgid "Validate your GitLab CI configuration file"
msgstr "Valide su archivo de configuración de GitLab CI"
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr "La validación ha fallado."
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr "¿Qué hay de nuevo?"
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Cuando un ejecutor está bloqueado, no se puede asignar a otros proyectos"
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr "Al dejar la URL en blanco, aún se pueden especificar las etiquetas de c
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "Cuando el merge request sea aceptado"
@@ -38251,9 +38646,6 @@ msgstr[1] "Cuando los merge request sean aceptados"
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr "Cuando:"
@@ -38560,12 +38952,12 @@ msgstr "Escriba un comentario…"
msgid "Write a description or drag your files here…"
msgstr "Escriba una descripción o arrastre sus archivos aquí.."
+msgid "Write a description…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Escriba la descripción del hito..."
-msgid "Write to \"authorized_keys\" file"
-msgstr ""
-
msgid "Write your release notes or drag your files here…"
msgstr "Escribe sus notas de la versión o arrastrar sus archivos aquí…"
@@ -38605,9 +38997,6 @@ msgstr "Ya tiene una tarea pendiente para esta alerta"
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr "Está a punto de añadir %{usersTag} personas a la discusión. Todas ellas recibirán una notificación."
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr "Está a punto de eliminar %{domain} de su instancia. Este dominio ya no estará disponible para ninguna aplicación Knative."
-
msgid "You are about to permanently delete this project"
msgstr "Está a punto de eliminar definitivamente este proyecto"
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr "No tiene permiso para realizar esta acción"
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "Puede resolver el conflicto del merge request utilizando el modo Interactivo, utilizando los botones %{use_ours} o %{use_theirs}, o editando los archivos directamente. Confirme estos cambios en %{branch_name}"
@@ -38932,9 +39321,6 @@ msgstr "No tiene ningún proyecto disponible."
msgid "You don't have any recent searches"
msgstr "No tiene ninguna búsquedas reciente"
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr "No tiene permisos suficientes para realizar esta acción."
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr "Dejó el \"%{membershipable_human_name}\" %{source_type}."
@@ -39031,9 +39420,6 @@ msgstr "Puede cerrar el hito ahora."
msgid "You must be logged in to search across all of GitLab"
msgstr "Debe estar conectado para buscar en todo GitLab"
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr "Su nombre de usuario es %{username}."
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao API token"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr "Se ha eliminado la reunión de Zoom"
msgid "[No reason]"
msgstr "[No hay razón]"
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr "un usuario eliminado"
-msgid "a design"
-msgstr "un diseño"
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] "alrededor de 1 hora"
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr "no se puede modificar"
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr "no puede bloquear a otros"
@@ -39688,9 +40110,6 @@ msgstr "no se puede bloquer"
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "%{remainingPackagesCount} más"
@@ -39757,9 +40179,20 @@ msgstr "Aplicar automáticamente el parche en una nueva rama"
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,8 +40202,14 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
-msgstr "Calidad del código"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
msgid "ciReport|Container Scanning"
msgstr "Análisis de contenedores"
@@ -39835,6 +40274,17 @@ msgstr "Encontrado %{issuesWithCount}"
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "Investigue esta vulnerabilidad creando una incidencia"
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr "SAST"
msgid "ciReport|Secret Detection"
msgstr "Detección de secretos"
-msgid "ciReport|Secret scanning"
-msgstr "Escaneo de secretos"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
+msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr "el nombre contenedor no puede ser mayor que %{max_length} caracteres"
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr "desplegar"
msgid "design"
msgstr "diseño"
-msgid "designs"
-msgstr "diseños"
-
msgid "detached"
msgstr "Desvinculado"
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr "no tiene una extensión compatible. Sólo %{extension_list} son compatibles"
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr "descargarlo"
@@ -40075,6 +40534,9 @@ msgstr "por ejemplo %{token}"
msgid "element is not a hierarchy"
msgstr "el elemento no es una jerarquía"
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr "%{metricsLinkStart} El uso de la memoria %{metricsLinkEnd} es %{emphasis
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr "Aprobar adicionalmente"
msgid "mrWidget|Approved by"
msgstr "Aprobado por"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr "Cargando las estadísticas de los despliegues"
@@ -40594,9 +41077,6 @@ msgstr "Merge fallido."
msgid "mrWidget|Merge locally"
msgstr "Merge local"
-msgid "mrWidget|Merge request approved."
-msgstr "merge request aprobado."
-
msgid "mrWidget|Merged by"
msgstr "Merge realizado por"
@@ -40711,12 +41191,6 @@ msgstr "El branch de origen no será eliminado"
msgid "mrWidget|There are merge conflicts"
msgstr "Hay conflictos de merge"
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Esta merge request no se realizó automáticamente"
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr "mi-asombroso-grupo"
@@ -40855,6 +41338,9 @@ msgstr "o"
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "total de %d prueba"
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index a9fb75e771b..1f70904cfa7 100644
--- a/locale/et_EE/gitlab.po
+++ b/locale/et_EE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: et\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/fa_IR/gitlab.po b/locale/fa_IR/gitlab.po
index dcf558fd9a6..64a0c1a0489 100644
--- a/locale/fa_IR/gitlab.po
+++ b/locale/fa_IR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fa\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:18\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/fi_FI/gitlab.po b/locale/fi_FI/gitlab.po
index 816b7fa6b1d..9fa4d8d90b3 100644
--- a/locale/fi_FI/gitlab.po
+++ b/locale/fi_FI/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index 5ddc2beb665..9ef0c7b8489 100644
--- a/locale/fil_PH/gitlab.po
+++ b/locale/fil_PH/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fil\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index 8220aaa1aca..4973e9a71ce 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr " %{start} à %{end}"
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Vous devez faire cela avant %{grace_period_deadline}."
-msgid " and"
-msgstr " et"
-
msgid " and "
msgstr " et "
msgid " and %{sliced}"
msgstr " et %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " dégradé sur %d point"
-msgstr[1] " dégradé sur %d points"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " amélioré sur %d point"
-msgstr[1] " amélioré sur %d points"
-
msgid " or "
msgstr " ou "
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] "%d commit,"
msgstr[1] "%d commits,"
-msgid "%d commits"
-msgstr "%d commits"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr "Une branche par défaut ne peut pas être choisie pour un projet vide."
msgid "A deleted user"
msgstr "Un utilisateur supprimé"
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Actif"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "Ajoutez un commentaire général à %{noteable_name}."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Ajoutez une page d’accueil à votre wiki contenant des informations sur votre projet. GitLab l’affichera ici à la place de ce message."
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr "Ajouter à la revue de code"
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr "Autoriser les commits des membres qui peuvent fusionner dans la branche
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "Une erreur est survenue lors de l’abonnement aux notifications."
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr "août"
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr "Blog"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,8 +5699,8 @@ msgstr "Toutes"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "Impossible de trouver le commit HEAD pour cette branche"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "Comparer"
@@ -5767,6 +5810,9 @@ msgstr "Pour confirmer, veuillez saisir %{branch_name_confirmation} :"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Pour rejeter les changements locaux et écraser la branche avec la version du dépôt en amont, veuillez la supprimer ici et cliquer sur « Mettre à jour maintenant » ciâ€dessus."
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr "Ne peut être fusionnée automatiquement"
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr "Choisir un modèle…"
msgid "Choose a type..."
msgstr "Choisir un type…"
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr "Choisissez n’importe quelle couleur."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Voir et modifier les détails de votre grappe de serveurs Kubernetes"
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "Sélectionnez le type de machine"
@@ -7963,6 +8033,9 @@ msgstr "Sélectionnez le projet et la zone afin de choisir le type de machine"
msgid "ClusterIntegration|Select project to choose zone"
msgstr "Sélectionnez le projet afin de choisir la zone"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr "répond aux exigences"
msgid "ClusterIntegration|sign up"
msgstr "s’inscrire"
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr "Commenter"
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Comparer"
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "Registre de conteneur"
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr "Copier l’URL %{protocol} de clonage"
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr "Copier le lien"
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Créer un nouveau dossier"
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr "Créer un nouveau ticket"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr "Sélecteur de date"
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr "Étiquette de classement par défaut"
@@ -10872,18 +10945,36 @@ msgstr "Par défaut : associer un identifiant de compte FogBugz à un nom compl
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "Définir un schéma personnalisé avec une syntaxe Cron"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Fully protected"
msgstr ""
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr "Définir un schéma personnalisé avec une syntaxe Cron"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -10956,9 +11047,6 @@ msgstr "Supprimer le commentaire"
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr "Domaine"
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr "Activer ou désactiver la collecte de données Pseudonymizer."
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr "Une erreur s’est produite lors de l’arrêt de l’environnement. Veu
msgid "Environments|Are you sure you want to stop this environment?"
msgstr "Êtesâ€vous sûr(e) de vouloir arrêter cet environnement ?"
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr "Erreur lors de la création de l’épopée"
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr "Date d’expiration"
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr "Explorer les groupes publics"
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr "Échec"
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr "Terminé"
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr "Erreurs trouvées dans votre fichier .gitlab-ci.yml :"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr "Pipelines généraux"
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr "Générer un jeu d’étiquettes par défaut"
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr "Exportation de projet GitLab"
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "GitLab va exécuter une tâche en arrièreâ€plan qui permettra de produire des fichiers CSV contenant des pseudonymes de la base de données GitLab qui seront téléversés dans le répertoire de stockage d’objets que vous avez configuré."
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr "Importation depuis Gitea"
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr "Avatar de groupe"
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr "Description du groupe (optionnel)"
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "Une erreur s’est produite lors de la récupération des épopées"
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr "Aucun groupe trouvé"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Vous pouvez gérer les autorisations des membres de votre groupe et accéder à chacun de ses projets."
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr "Message d’enâ€tête"
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr "Historique"
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr "En ligne"
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr "Entrer les clefs d’hôte manuellement"
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr "Utilisateurs internes"
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "Dernier pipeline"
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr "Statistiques et rapports"
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr "Pour regrouper des métriques similaires"
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr "Libellé de l’axe Y"
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr "Réseau"
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr "Nouvelle étiquette"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr "Aucune contribution n’a été trouvée"
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr "Aucune carte de crédit n’est nécessaire."
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr "Non disponible pour les projets privés"
msgid "Not available for protected branches"
msgstr "Non disponible pour les branches protégées"
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr "Opérations"
-
msgid "Operations Dashboard"
msgstr "Tableau de bord des opérations"
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "Vous pouvez éventuellement %{link_to_customize} la manière dont les adresses de courriel et les noms d’utilisateur issus de FogBugz sont importés dans GitLab."
@@ -23956,6 +24194,9 @@ msgstr "Options"
msgid "Or you can choose one of the suggested colors below"
msgstr "Ou vous pouvez choisir l’une des couleurs suggérées ciâ€dessous"
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr "Propriétaire"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr "Chemin d’accès :"
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr "Pause"
@@ -24616,6 +24886,9 @@ msgstr "En attente"
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "Il n’y a actuellement aucun pipeline."
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "Une erreur est survenue lors de la récupération des pipelines. Réessayez dans quelques instants ou contactez votre équipe d’assistance."
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr "Diff brut"
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Veuillez saisir un nom descriptif pour votre groupe."
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr "Profil"
msgid "Profile Settings"
msgstr "Paramètres du profil"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr "Vous êtes sur le point de supprimer définitivement %{yourAccount}, ain
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr "Vous êtes sur le point de changer le nom d’utilisateur %{currentUsernameBold} en %{newUsernameBold}. Le profil et les projets seront redirigés vers l’espace de noms %{newUsername}, mais cette redirection expire si un nouvel utilisateur ou un nouveau groupe est créé avec l’ancien nom %{currentUsername}. Veuillez mettre à jour vos dépôts Git dès que possible."
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr "Ajouter un émoji de statut"
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr "Rogneur d’avatar"
@@ -26221,6 +26518,9 @@ msgstr "Vous pouvez téléverser votre avatar ici ou le changer en %{gravatar_li
msgid "Profiles|You don't have access to delete this user."
msgstr "Vous n’avez pas les autorisations suffisantes pour supprimer cet utilisateur ou cette utilisatrice."
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr "Cette fonctionnalité nécessite un navigateur prenant en charge localSt
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr "Ajouter une alerte"
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr "Modifier l’alerte"
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr "Erreur lors de la création de l’alerte"
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr "Erreur lors de la suppression de l’alerte"
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr "Erreur lors de la récupération de l’alerte"
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr "Erreur lors de l’enregistrement de l’alerte"
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr "Opérateur"
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr "Seuil"
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr "Fournisseur"
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr "Collecte de données Pseudonymizer"
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr "Sélectionner"
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "Demander l’accès"
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr "Exécuteurs"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr "Exécuteurs actuellement en ligne : %{active_runners_count}"
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr "En cours d’exécution"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr "Enregistrer l’application"
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr "Version du serveur"
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr "Définissez un mot de passe pour votre compte afin de pouvoir récupére
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,12 +31438,12 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "définir un mot de passe"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr "Ajouter un émoji d’état"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "SetStatusModal|Busy"
msgstr ""
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr "Carte à puce"
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "L’authentification par carte à puce a échoué : un enâ€tête de certificat client est manquant."
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "Extraits de code"
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "Énoncez votre message à activer"
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr "Les étiquettes permettent de marquer des moments spécifiques de l’hi
msgid "TagsPage|This tag has no release notes."
msgstr "Cette étiquette n’a pas de notes de version."
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "Utilisez la commande « git tag » pour en rajouter :"
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "Équipe"
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "La connexion expirera après %{timeout}. Pour les dépôts qui nécessitent plus de temps, utilisez une combinaison de clone et push."
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "Le déploiement de cette tâche sur %{environmentLink} a échoué."
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "La collecte de données du pseudonymiseur est désactivée. Lorsque cette option est activée, GitLab exécute un travail en tâche de fond produisant des fichiers CSV pseudonymisés à partir de la base de données GitLab qui seront téléchargés dans le répertoire de stockage d’objets que vous avez configuré."
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr "Il n’y a pas encore de projets partagés avec ce groupe"
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr "Annuler"
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr "Utiliser ce modèle"
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr "Paramètres de l’utilisateur"
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Lorsqu’un exécuteur est verrouillé, il ne peut pas être affecté à d’autres projets"
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr "Lorsque vous laissez l’URL vide, des étiquettes de classification peu
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "Vous pouvez résoudre le conflit de fusion Git soit en mode interactif, en cliquant sur les boutons « %{use_ours} » ou « %{use_theirs} », soit en modifiant directement les fichiers. Valider ces modifications dans la branche « %{branch_name} »"
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr "un utilisateur supprimé"
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "%{remainingPackagesCount} restant(s)"
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,8 +40202,14 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
-msgstr "Qualité du code"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
msgid "ciReport|Container Scanning"
msgstr ""
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr "SAST"
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr "%{metricsLinkStart}L’usage mémoire%{metricsLinkEnd} %{emphasisStart}e
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr "Approuvée par"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr "Chargement des statistiques de déploiement"
@@ -40594,9 +41077,6 @@ msgstr "La fusion a échoué."
msgid "mrWidget|Merge locally"
msgstr "Fusionner localement"
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr "Fusionnée par"
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "Il y a des conflits de fusion"
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Cette demande de fusion n’a pas pu être fusionnée automatiquement"
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "sur un total de %d test"
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 56e7413c530..f87833e829d 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -818,6 +830,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -896,9 +911,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1128,12 +1140,23 @@ msgstr ""
msgid "(revoked)"
msgstr ""
-msgid "(target)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(this user)"
msgstr ""
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1468,7 +1491,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1495,6 +1518,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1564,9 +1590,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1843,6 +1866,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -2038,9 +2064,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2110,6 +2133,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2155,9 +2181,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2305,6 +2328,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2371,7 +2397,7 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
-msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2908,19 +2934,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3325,7 +3360,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3361,7 +3396,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3511,9 +3546,6 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr ""
@@ -3601,7 +3633,7 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
@@ -3610,7 +3642,7 @@ msgstr ""
msgid "An error occurred while fetching commit data."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3921,6 +3953,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3963,9 +3998,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3978,9 +4010,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4037,6 +4066,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4045,6 +4077,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|By making this change, you will automatically approve all users in pending approval status."
+msgstr ""
+
msgid "ApplicationSettings|Denied domains for sign-ups"
msgstr ""
@@ -4214,12 +4249,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4232,12 +4273,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4250,6 +4300,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4265,6 +4324,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4274,6 +4336,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4546,12 +4611,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -5422,6 +5481,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5455,6 +5517,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5464,12 +5529,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5482,6 +5556,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5573,6 +5650,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5585,6 +5665,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5663,7 +5746,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5876,10 +5959,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5888,6 +5974,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6133,6 +6222,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6325,6 +6417,9 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
msgid "Card number:"
msgstr ""
@@ -6478,9 +6573,6 @@ msgstr ""
msgid "Changes are shown as if the %{b_open}source%{b_close} revision was being merged into the %{b_open}target%{b_close} revision."
msgstr ""
-msgid "Changes are still tracked. Useful for cluster/index migrations."
-msgstr ""
-
msgid "Changes saved."
msgstr ""
@@ -6493,6 +6585,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6556,10 +6651,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
msgstr ""
-msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -7136,6 +7231,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7220,12 +7318,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7247,15 +7339,30 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} Agent based integrations"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} Certificate based integrations"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
+msgid "ClusterAgents|All"
+msgstr ""
+
msgid "ClusterAgents|Alternative installation methods"
msgstr ""
@@ -7268,9 +7375,24 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate based"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with certificate"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7280,6 +7402,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7295,31 +7420,34 @@ msgstr ""
msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|GitLab Agents"
+msgstr ""
+
+msgid "ClusterAgents|GitLab Agents provide an increased level of security when integrating with clusters. %{linkStart}Learn more about the GitLab Kubernetes Agent.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Go to the repository"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|If you are setting up multiple clusters and are using Auto DevOps, %{linkStart}read about using multiple Kubernetes clusters first.%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Install new Agent"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Last contact"
msgstr ""
-msgid "ClusterAgents|Last connected %{timeAgo}."
+msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
-msgid "ClusterAgents|Last contact"
+msgid "ClusterAgents|Learn how to troubleshoot"
msgstr ""
-msgid "ClusterAgents|Learn how to create an agent access token"
+msgid "ClusterAgents|Learn more about the GitLab Kubernetes Agent."
msgstr ""
msgid "ClusterAgents|Make sure you are using a valid token."
@@ -7334,21 +7462,36 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No Agent based integrations"
+msgstr ""
+
+msgid "ClusterAgents|No Certificate based integrations"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
msgid "ClusterAgents|Read more about getting started"
msgstr ""
+msgid "ClusterAgents|Recommended"
+msgstr ""
+
msgid "ClusterAgents|Recommended installation method"
msgstr ""
+msgid "ClusterAgents|Register Agent"
+msgstr ""
+
msgid "ClusterAgents|Registering Agent"
msgstr ""
msgid "ClusterAgents|Registration token"
msgstr ""
+msgid "ClusterAgents|Security"
+msgstr ""
+
msgid "ClusterAgents|Select an Agent"
msgstr ""
@@ -7361,12 +7504,6 @@ msgstr ""
msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
-msgstr ""
-
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
-
msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
msgstr ""
@@ -7385,6 +7522,15 @@ msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|Use GitLab Agents to more securely integrate with your clusters to deploy your applications, run your pipelines, use review apps and much more."
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} Agent based integrations"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} Certificate based integrations"
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
@@ -7499,7 +7645,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7529,15 +7675,15 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
-msgid "ClusterIntegration|Clusters connected with a certificate"
-msgstr ""
-
msgid "ClusterIntegration|Connect cluster with certificate"
msgstr ""
msgid "ClusterIntegration|Connect existing cluster"
msgstr ""
+msgid "ClusterIntegration|Connect with a certificate"
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7664,9 +7810,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7700,6 +7843,9 @@ msgstr ""
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{linkStart}read about using multiple Kubernetes clusters first.%{linkEnd}"
+msgstr ""
+
msgid "ClusterIntegration|If you do not wish to delete all associated GitLab resources, you can simply remove the integration."
msgstr ""
@@ -7712,12 +7858,6 @@ msgstr ""
msgid "ClusterIntegration|Instance type"
msgstr ""
-msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
-msgstr ""
-
-msgid "ClusterIntegration|Integrate with a cluster certificate"
-msgstr ""
-
msgid "ClusterIntegration|Integration disabled"
msgstr ""
@@ -7739,9 +7879,6 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created."
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr ""
-
msgid "ClusterIntegration|Kubernetes version"
msgstr ""
@@ -7763,6 +7900,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about the GitLab managed clusters"
+msgstr ""
+
msgid "ClusterIntegration|Loading IAM Roles"
msgstr ""
@@ -8096,6 +8236,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use certificates to integrate with your clusters to deploy your applications, run your pipelines, use review apps and much more in an easy way."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8153,9 +8296,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8485,6 +8625,9 @@ msgstr ""
msgid "Completed"
msgstr ""
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
+msgstr ""
+
msgid "Compliance framework"
msgstr ""
@@ -8614,6 +8757,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
msgstr ""
@@ -8626,6 +8775,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8635,15 +8787,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8671,9 +8817,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -8788,6 +8931,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9136,9 +9282,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9328,9 +9471,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9571,6 +9711,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9700,6 +9843,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9733,9 +9879,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9826,7 +9969,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9955,6 +10098,12 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10063,6 +10212,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10222,6 +10380,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10289,6 +10450,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10328,6 +10492,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -10783,6 +10950,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10849,6 +11019,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10888,16 +11061,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
msgstr ""
-msgid "Define approval rules."
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11071,6 +11262,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11185,16 +11382,16 @@ msgstr ""
msgid "Dependency Proxy"
msgstr ""
-msgid "Dependency Proxy disabled. To enable it, contact the group owner."
+msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency Proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency Proxy image prefix"
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency Scanning"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11203,9 +11400,24 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
msgid "DependencyProxy|Enable Proxy"
msgstr ""
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
@@ -11443,9 +11655,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11675,7 +11884,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -11942,6 +12151,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12109,6 +12321,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12313,9 +12528,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12409,6 +12630,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12424,6 +12648,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12544,9 +12771,6 @@ msgstr ""
msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain matches the domain used by your GitLab instance (such as %{domains})."
msgstr ""
-msgid "EmailsOnPushService|can't exceed %{recipients_limit}"
-msgstr ""
-
msgid "EmailsOnPushService|tanuki@example.com gitlab@example.com"
msgstr ""
@@ -12598,6 +12822,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12697,7 +12924,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12865,6 +13092,12 @@ msgstr ""
msgid "Enter the number of seconds, or other human-readable input, like \"1 hour\". This timeout takes precedence over lower timeouts set for the project."
msgstr ""
+msgid "Enter the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -12881,7 +13114,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12946,16 +13181,13 @@ msgstr ""
msgid "EnvironmentsDashboard|More actions"
msgstr ""
-msgid "EnvironmentsDashboard|More information"
-msgstr ""
-
msgid "EnvironmentsDashboard|Remove"
msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13462,6 +13694,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13582,7 +13817,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13758,18 +13993,12 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13860,6 +14089,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13884,6 +14116,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -13959,6 +14197,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14141,6 +14385,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14778,6 +15025,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15096,9 +15346,6 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
-msgid "Geo|Could not remove tracking entry for an existing upload."
-msgstr ""
-
msgid "Geo|Data replication lag"
msgstr ""
@@ -15372,9 +15619,6 @@ msgstr ""
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr ""
-msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
-msgstr ""
-
msgid "Geo|URL can't be blank"
msgstr ""
@@ -15591,6 +15835,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15606,9 +15853,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15678,10 +15922,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15729,6 +15973,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -15924,7 +16171,7 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -15981,6 +16228,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16209,12 +16459,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16617,7 +16861,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16728,6 +16972,12 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
+msgstr ""
+
msgid "Header cannot be associated with both a request and a response"
msgstr ""
@@ -16746,6 +16996,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16830,7 +17083,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16939,6 +17192,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17101,7 +17357,7 @@ msgstr ""
msgid "Identities"
msgstr ""
-msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17140,6 +17396,9 @@ msgstr ""
msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
msgstr ""
+msgid "If there isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -17524,6 +17783,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17584,6 +17846,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17638,6 +17903,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17656,6 +17924,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -17899,7 +18176,10 @@ msgstr ""
msgid "IncidentManagement|All"
msgstr ""
-msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18064,9 +18344,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18130,6 +18407,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18273,6 +18553,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18312,6 +18595,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18339,12 +18625,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18462,6 +18754,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18477,6 +18772,9 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18495,6 +18793,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18504,7 +18805,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18561,7 +18865,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18570,9 +18874,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18672,6 +18973,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18690,6 +18997,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18702,12 +19012,24 @@ msgstr ""
msgid "InviteMembersModal|Configure security features"
msgstr ""
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
+msgstr ""
+
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
+msgid "InviteMembersModal|GitLab is better with colleagues!"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
+msgstr ""
+
msgid "InviteMembersModal|Invite"
msgstr ""
@@ -18738,6 +19060,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -18927,6 +19252,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19068,6 +19396,9 @@ msgstr ""
msgid "Issues and merge requests"
msgstr ""
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
+msgstr ""
+
msgid "Issues assigned to me"
msgstr ""
@@ -19077,9 +19408,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19173,6 +19501,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19182,6 +19513,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19278,9 +19612,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19359,19 +19699,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19416,18 +19756,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19476,12 +19807,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-msgstr ""
-
-msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
-msgstr ""
-
msgid "JiraService|Open Jira"
msgstr ""
@@ -19512,9 +19837,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19713,6 +20035,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19976,6 +20304,9 @@ msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20147,7 +20478,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20435,9 +20766,6 @@ msgstr ""
msgid "Licenses|Detected licenses that are out-of-compliance with the project's assigned policies"
msgstr ""
-msgid "Licenses|Disallow Merge request if detected and will instruct the developer to remove"
-msgstr ""
-
msgid "Licenses|Displays licenses detected in the project, based on the %{linkStart}latest successful%{linkEnd} scan"
msgstr ""
@@ -20465,13 +20793,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20489,6 +20817,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20992,9 +21323,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21394,6 +21722,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21403,6 +21734,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21514,6 +21848,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21816,9 +22159,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21954,9 +22294,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22217,6 +22554,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|You won't be able to pull or push repositories via SSH until you add an SSH key to your profile"
msgstr ""
@@ -22468,9 +22808,6 @@ msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
-msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines. To learn more about reducing storage capacity please visit our docs."
-msgstr ""
-
msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22522,6 +22859,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22588,9 +22928,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22851,6 +23188,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23082,6 +23422,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23133,6 +23476,9 @@ msgstr ""
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23196,6 +23542,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23291,6 +23640,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23506,7 +23858,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23581,9 +23933,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23665,7 +24014,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23749,7 +24098,7 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
-msgid "OnDemandScans|%{learnMoreLinkStart}Lean more about on-demand scans%{learnMoreLinkEnd}."
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
msgstr ""
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
@@ -23821,6 +24170,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23836,13 +24188,7 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
-msgid "OnDemandScans|There are no finished scans."
-msgstr ""
-
-msgid "OnDemandScans|There are no running scans."
-msgstr ""
-
-msgid "OnDemandScans|There are no scheduled scans."
+msgid "OnDemandScans|Target"
msgstr ""
msgid "OnDemandScans|Use existing scanner profile"
@@ -23854,12 +24200,6 @@ msgstr ""
msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
-msgstr ""
-
-msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues and merge requests."
-msgstr ""
-
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
@@ -23916,6 +24256,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -23937,6 +24280,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24054,6 +24400,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24192,6 +24541,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24408,6 +24760,9 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
@@ -24545,6 +24900,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24641,9 +24999,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -24716,6 +25071,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24893,6 +25251,9 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25208,9 +25569,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25247,6 +25605,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25337,6 +25698,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25352,9 +25716,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25367,6 +25728,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25442,10 +25806,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25484,6 +25848,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25586,6 +25953,9 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -25607,9 +25977,6 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
-msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
-msgstr ""
-
msgid "Please provide a name"
msgstr ""
@@ -26015,12 +26382,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26030,9 +26403,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26060,6 +26430,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26654,6 +27027,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26669,6 +27045,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26867,15 +27246,24 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -26945,6 +27333,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -26990,6 +27381,9 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27137,6 +27531,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27191,6 +27588,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27284,54 +27684,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27443,6 +27798,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27461,6 +27819,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
@@ -27635,9 +27996,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27653,6 +28011,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27791,6 +28152,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27803,6 +28167,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27818,6 +28185,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -27980,6 +28350,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -27989,9 +28362,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28025,6 +28395,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28094,6 +28467,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28195,9 +28574,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28392,6 +28768,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28518,15 +28897,15 @@ msgstr ""
msgid "Removed %{reviewer_text} %{reviewer_references}."
msgstr ""
-msgid "Removed %{type} with id %{id}"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
+msgid "Removed attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28542,6 +28921,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28602,6 +28984,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28811,6 +29196,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28832,6 +29220,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28850,6 +29241,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -28928,18 +29322,27 @@ msgstr ""
msgid "Repository update events"
msgstr ""
-msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -28961,6 +29364,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29000,6 +29406,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29383,6 +29792,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29416,6 +29828,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29434,6 +29849,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29446,6 +29864,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29467,6 +29888,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29485,12 +29909,33 @@ msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29500,6 +29945,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29509,6 +29957,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29530,18 +29981,27 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29602,16 +30062,19 @@ msgstr ""
msgid "Runners|group"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|locked"
msgstr ""
-msgid "Runners|locked"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29722,9 +30185,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30053,6 +30513,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30155,7 +30618,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
msgstr ""
-msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
+msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the merge request."
msgstr ""
msgid "SecurityConfiguration|Compliance"
@@ -30182,7 +30645,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+msgid "SecurityConfiguration|Create merge request"
msgstr ""
msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
@@ -30278,16 +30741,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30338,6 +30804,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30356,6 +30825,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30425,6 +30897,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30446,9 +30921,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30482,6 +30954,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30491,6 +30972,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30572,7 +31056,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30647,6 +31131,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30944,9 +31431,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31046,7 +31530,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31067,9 +31560,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31106,6 +31596,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31187,6 +31680,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31214,9 +31710,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31247,13 +31740,10 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31324,9 +31814,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31393,6 +31880,15 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{boldStart}will%{boldEnd} lose access to your account."
msgstr ""
@@ -31408,6 +31904,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31456,18 +31955,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -31667,9 +32157,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -32198,9 +32685,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32219,6 +32703,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32540,7 +33051,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -33035,18 +33546,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33068,9 +33573,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33083,12 +33585,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33104,30 +33600,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33155,9 +33636,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33170,9 +33648,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33215,6 +33690,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33428,6 +33906,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33852,7 +34339,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
msgstr ""
-msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
msgstr ""
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
@@ -33888,6 +34375,12 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -34091,9 +34584,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-msgstr ""
-
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
@@ -34181,9 +34671,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34217,9 +34704,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34232,9 +34716,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34289,6 +34770,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34385,9 +34869,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34400,9 +34881,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34466,6 +34944,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34652,9 +35133,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34778,6 +35256,9 @@ msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
+msgid "This commit was signed with %{strong_open}multiple%{strong_close} signatures."
+msgstr ""
+
msgid "This commit was signed with a %{strong_open}verified%{strong_close} signature and the committer email is verified to belong to the same user."
msgstr ""
@@ -34850,6 +35331,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -34877,7 +35364,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -34904,12 +35391,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35099,6 +35589,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35180,6 +35673,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35652,7 +36151,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35688,7 +36187,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35760,6 +36259,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -35865,10 +36367,10 @@ msgstr ""
msgid "Too many changes to show."
msgstr ""
-msgid "Too many namespaces enabled. You will need to manage them via the console or the API."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -35889,9 +36391,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -35982,7 +36481,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36122,7 +36621,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36179,6 +36678,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36350,6 +36855,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36374,9 +36882,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36434,6 +36939,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36674,6 +37182,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36725,9 +37236,6 @@ msgstr ""
msgid "Uploading changes to terminal"
msgstr ""
-msgid "Uploads"
-msgstr ""
-
msgid "Upon performing this action, the contents of this group, its subgroup and projects will be permanently deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36767,6 +37275,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36785,10 +37296,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36800,12 +37311,18 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -36845,9 +37362,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36860,18 +37374,6 @@ msgstr ""
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
-msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
-msgstr ""
-
-msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
-msgstr ""
-
-msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
-msgstr ""
-
-msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
-msgstr ""
-
msgid "UsageQuota|Total excess storage used"
msgstr ""
@@ -36887,10 +37389,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37112,9 +37614,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37142,6 +37641,9 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
msgid "User created at"
msgstr ""
@@ -37415,9 +37917,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37496,6 +37995,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37559,6 +38061,18 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
@@ -37871,9 +38385,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -37889,6 +38400,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -37901,6 +38415,12 @@ msgstr ""
msgid "VulnerabilityManagement|Detected"
msgstr ""
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
+msgstr ""
+
msgid "VulnerabilityManagement|Needs triage"
msgstr ""
@@ -38126,7 +38646,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
msgstr ""
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
@@ -38420,6 +38940,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38441,6 +38964,12 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
+msgstr ""
+
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38449,9 +38978,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38869,6 +39395,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39085,6 +39614,9 @@ msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39211,6 +39743,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39316,9 +39851,6 @@ msgstr ""
msgid "You won't be able to create new projects because you have reached your project limit."
msgstr ""
-msgid "You won't be able to pull or push repositories via %{protocol} until you %{set_password_link} on your account"
-msgstr ""
-
msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
@@ -39403,7 +39935,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39469,6 +40001,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39661,6 +40199,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39675,40 +40216,49 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This is a ZenTao user."
+msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZenTaoIntegration|ZenTao user"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39746,9 +40296,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -39841,12 +40388,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39874,6 +40427,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39889,9 +40445,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40044,6 +40597,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40053,6 +40609,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40076,6 +40635,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40112,6 +40674,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40222,6 +40787,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40290,6 +40861,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40343,6 +40920,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40467,9 +41047,6 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
msgid "in all GitLab"
msgstr ""
@@ -40541,6 +41118,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40628,9 +41211,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40660,13 +41240,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40678,6 +41258,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40696,9 +41279,6 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
-msgstr ""
-
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40735,7 +41315,10 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
msgstr ""
msgid "mrWidget|Cancel auto-merge"
@@ -40770,6 +41353,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -40779,12 +41365,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -40832,10 +41424,10 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
+msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merged by"
+msgid "mrWidget|Merges changes into"
msgstr ""
msgid "mrWidget|Merging! Changes are being shipped…"
@@ -40922,9 +41514,6 @@ msgstr ""
msgid "mrWidget|The changes were not merged into"
msgstr ""
-msgid "mrWidget|The changes will be merged into"
-msgstr ""
-
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
@@ -40940,12 +41529,6 @@ msgstr ""
msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be deleted"
-msgstr ""
-
-msgid "mrWidget|The source branch will not be deleted"
-msgstr ""
-
msgid "mrWidget|There are merge conflicts"
msgstr ""
@@ -40958,10 +41541,10 @@ msgstr ""
msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
msgstr ""
msgid "mrWidget|What is a merge train?"
@@ -41015,6 +41598,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41127,6 +41716,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41334,6 +41935,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index de57c0423bf..74cd14a55fd 100644
--- a/locale/gl_ES/gitlab.po
+++ b/locale/gl_ES/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: gl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:18\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr " %{start} a %{end}"
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Debe facelo antes do %{grace_period_deadline}."
-msgid " and"
-msgstr " e"
-
msgid " and "
msgstr " e "
msgid " and %{sliced}"
msgstr " e %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " rebaixado en %d puntos"
-msgstr[1] " rebaixado en %d puntos"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " mellorado en %d puntos"
-msgstr[1] " mellorado en %d punto"
-
msgid " or "
msgstr " ou "
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
msgstr ""
-msgid "Define approval rules."
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index 820581c103e..5b1e201dbd6 100644
--- a/locale/he_IL/gitlab.po
+++ b/locale/he_IL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: he\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,29 +40,12 @@ msgstr " סוג"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " עליך לעשות ×–×ת לפני %{grace_period_deadline}."
-msgid " and"
-msgstr " וג×"
-
msgid " and "
msgstr " ×•×’× "
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid " or "
msgstr " ×ו "
@@ -90,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -240,9 +226,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1227,6 +1210,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1312,9 +1298,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1371,6 +1363,9 @@ msgstr[3] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1665,9 +1660,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1701,7 +1693,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1728,6 +1720,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -2076,6 +2071,9 @@ msgstr "פעולות"
msgid "Activate Service Desk"
msgstr "הפעלת דלפק שירות"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "פעיל"
@@ -2157,9 +2155,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2238,9 +2233,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr "הוספת ×©× ×ª×—×•×"
-
msgid "Add email address"
msgstr "הוספת כתובת דו×״ל"
@@ -2334,6 +2326,9 @@ msgstr "הוספה לסקירה"
msgid "Add to tree"
msgstr "הוספה לעץ"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2790,7 +2785,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2805,6 +2800,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2940,7 +2941,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3555,7 +3556,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3573,6 +3574,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3588,7 +3592,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3828,13 +3832,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -4038,6 +4045,13 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -4101,9 +4115,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4450,12 +4461,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4468,12 +4485,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4486,6 +4512,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4501,6 +4536,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4510,6 +4548,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4784,12 +4825,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -5029,6 +5064,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5663,6 +5701,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5908,7 +5949,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -6019,6 +6060,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6226,9 +6270,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6515,9 +6556,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6575,6 +6613,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6907,6 +6951,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6940,6 +6987,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -7054,6 +7104,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -7096,15 +7149,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7747,7 +7794,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8188,6 +8235,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8197,6 +8247,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8206,9 +8259,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8221,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8371,30 +8442,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8533,12 +8580,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8657,6 +8698,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8738,13 +8782,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8753,16 +8797,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8771,6 +8821,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8783,31 +8839,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8879,15 +8935,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -9032,6 +9082,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9160,10 +9213,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9362,7 +9415,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9386,9 +9439,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9509,9 +9559,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9581,9 +9628,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9668,9 +9712,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9776,6 +9817,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9794,6 +9838,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9806,9 +9853,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9824,6 +9868,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9959,6 +10006,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -10076,7 +10126,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10199,10 +10249,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10259,6 +10306,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10313,6 +10363,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10472,6 +10531,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10543,6 +10605,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -11039,6 +11104,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -11105,6 +11173,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11144,16 +11215,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11228,9 +11317,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11258,9 +11344,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11288,6 +11371,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11456,13 +11542,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11471,7 +11557,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11797,7 +11895,11 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11901,6 +12003,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11916,15 +12024,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11976,6 +12081,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -12054,6 +12162,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -12099,6 +12210,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12291,12 +12405,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12391,18 +12499,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12433,9 +12529,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12661,6 +12754,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12985,10 +13081,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -13114,7 +13207,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13169,7 +13265,11 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13270,7 +13370,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13570,6 +13670,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13747,6 +13850,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -14045,9 +14151,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -14129,6 +14232,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -14144,6 +14250,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14171,9 +14280,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14186,6 +14292,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14270,6 +14382,13 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14504,9 +14623,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14700,6 +14816,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14953,6 +15072,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15184,6 +15306,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15244,6 +15369,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15820,6 +15948,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15859,6 +15990,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15874,9 +16008,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15946,10 +16077,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15997,6 +16128,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16306,6 +16440,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16474,12 +16611,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16708,7 +16839,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16771,9 +16902,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16876,7 +17013,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -17005,6 +17142,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -17089,7 +17229,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17154,9 +17294,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17178,6 +17315,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17202,6 +17342,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17214,6 +17357,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17790,6 +17936,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17850,6 +17999,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17904,6 +18056,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17922,6 +18077,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18435,6 +18599,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18538,6 +18705,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18577,6 +18747,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18760,6 +18933,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18835,9 +19011,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18937,6 +19110,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18955,6 +19134,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18970,6 +19152,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -19003,6 +19188,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19528,6 +19716,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19621,19 +19812,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19975,6 +20166,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20231,12 +20428,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20405,6 +20608,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -21042,6 +21248,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21171,6 +21380,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21258,9 +21470,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21384,6 +21593,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21393,6 +21605,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21654,6 +21869,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21699,6 +21917,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21771,6 +21992,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21927,34 +22157,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21981,6 +22205,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -22075,9 +22305,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22213,9 +22440,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22664,6 +22888,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22782,6 +23009,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22848,9 +23078,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -23161,6 +23388,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23275,7 +23505,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23290,6 +23520,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23485,6 +23718,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23543,9 +23779,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23787,18 +24020,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23850,9 +24080,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -24054,6 +24281,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -24066,6 +24296,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -24078,6 +24314,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -24093,6 +24332,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24208,15 +24450,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24265,9 +24507,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24295,6 +24534,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24304,6 +24546,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24373,6 +24618,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24448,9 +24723,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24631,14 +24903,18 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24682,9 +24958,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24943,6 +25216,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24964,6 +25240,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25471,6 +25750,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25591,6 +25873,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25708,6 +25993,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25810,9 +26098,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25957,6 +26251,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26233,12 +26530,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26248,9 +26551,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26278,6 +26578,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26569,6 +26872,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26869,6 +27175,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26884,6 +27193,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -27067,6 +27379,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27079,6 +27394,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27256,6 +27574,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27346,6 +27667,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27427,6 +27751,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27454,6 +27781,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27469,6 +27799,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27484,54 +27817,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27835,9 +28123,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27853,6 +28138,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27991,6 +28279,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -28003,6 +28294,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28189,9 +28483,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28225,6 +28516,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28312,15 +28606,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28806,6 +29100,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -29146,6 +29443,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -29155,9 +29455,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29236,15 +29533,15 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29597,9 +29894,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29624,6 +29918,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29633,6 +29936,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29684,6 +29990,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29705,6 +30014,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29744,6 +30071,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29807,6 +30137,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29837,15 +30170,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29942,9 +30266,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30295,6 +30616,9 @@ msgstr[3] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30520,16 +30844,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30580,6 +30907,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30598,6 +30928,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30667,6 +31000,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30688,9 +31024,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30724,6 +31057,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30733,6 +31075,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30763,6 +31108,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30886,6 +31234,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30925,10 +31276,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30946,15 +31297,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31213,9 +31558,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31315,9 +31657,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31372,9 +31711,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31465,9 +31801,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31501,10 +31834,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31570,6 +31903,13 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31917,9 +32257,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31986,6 +32323,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -32010,6 +32350,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -32019,6 +32362,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -32043,9 +32389,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32640,12 +32983,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32685,6 +33022,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -33183,7 +33523,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33282,18 +33622,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33315,9 +33649,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33330,12 +33661,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33351,30 +33676,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33402,9 +33712,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33417,9 +33724,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33462,6 +33766,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33648,6 +33955,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33672,6 +33982,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33684,6 +34003,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -34067,6 +34389,9 @@ msgstr[3] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -34136,6 +34461,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -34166,9 +34494,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34239,6 +34564,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34323,6 +34651,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34428,9 +34759,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34464,9 +34792,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34626,6 +34951,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34710,6 +35038,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34896,9 +35227,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -35121,7 +35449,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35424,6 +35752,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35562,6 +35896,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35897,7 +36234,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35933,7 +36270,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -36119,6 +36456,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36212,7 +36564,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36582,6 +36934,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36666,6 +37021,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36999,6 +37357,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -37017,10 +37378,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -37032,6 +37393,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -37077,9 +37441,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -37119,10 +37480,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37272,6 +37633,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37302,6 +37666,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37368,6 +37735,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37719,6 +38092,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37728,6 +38104,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37773,10 +38158,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38442,6 +38839,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38637,6 +39037,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38646,9 +39049,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38661,6 +39061,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38671,9 +39074,6 @@ msgstr[3] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38980,10 +39380,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -39025,9 +39425,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -39094,6 +39491,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39250,9 +39650,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39352,9 +39749,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39442,6 +39836,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39451,9 +39848,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39908,28 +40302,55 @@ msgstr[3] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39941,6 +40362,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39953,9 +40377,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -40066,12 +40487,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -40099,6 +40526,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -40114,9 +40544,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40147,6 +40574,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -40183,9 +40613,22 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -40195,7 +40638,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40261,6 +40710,19 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40294,10 +40756,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40418,6 +40880,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40476,9 +40944,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40491,6 +40956,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40507,6 +40978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40543,6 +41017,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40747,6 +41224,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40907,6 +41390,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40940,6 +41426,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -41004,6 +41496,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -41038,9 +41533,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -41155,12 +41647,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -41176,6 +41662,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41224,6 +41713,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41299,6 +41794,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index 68470d14033..ad5764bfa99 100644
--- a/locale/hi_IN/gitlab.po
+++ b/locale/hi_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index 510343664e1..53d09604d6c 100644
--- a/locale/hr_HR/gitlab.po
+++ b/locale/hr_HR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:18\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,27 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid " or "
msgstr ""
@@ -88,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -217,9 +205,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1141,6 +1126,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1225,9 +1213,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1282,6 +1276,9 @@ msgstr[2] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1552,9 +1549,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1588,7 +1582,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1615,6 +1609,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1963,6 +1960,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -2044,9 +2044,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2125,9 +2122,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2221,6 +2215,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2677,7 +2674,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2692,6 +2689,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2827,7 +2830,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3442,7 +3445,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3460,6 +3463,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3475,7 +3481,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3715,13 +3721,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3925,6 +3934,12 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3988,9 +4003,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4330,12 +4342,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4348,12 +4366,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4366,6 +4393,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4381,6 +4417,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4390,6 +4429,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4663,12 +4705,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4906,6 +4942,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5539,6 +5578,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5782,7 +5824,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5893,6 +5935,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6100,9 +6145,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6388,9 +6430,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6448,6 +6487,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6778,6 +6823,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6811,6 +6859,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6925,6 +6976,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6967,15 +7021,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7618,7 +7666,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8059,6 +8107,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8068,6 +8119,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8077,9 +8131,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8092,6 +8161,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8242,30 +8314,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8404,12 +8452,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8527,6 +8569,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8608,13 +8653,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8623,16 +8668,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8641,6 +8692,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8653,31 +8710,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8749,15 +8806,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8902,6 +8953,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9028,10 +9082,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9229,7 +9283,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9253,9 +9307,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9376,9 +9427,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9448,9 +9496,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9535,9 +9580,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9643,6 +9685,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9661,6 +9706,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9673,9 +9721,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9691,6 +9736,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9826,6 +9874,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9943,7 +9994,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10066,10 +10117,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10126,6 +10174,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10180,6 +10231,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10339,6 +10399,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10408,6 +10471,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10903,6 +10969,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10969,6 +11038,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11008,16 +11080,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11092,9 +11182,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11122,9 +11209,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11152,6 +11236,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11317,13 +11404,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11332,7 +11419,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11654,7 +11753,10 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11758,6 +11860,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11773,15 +11881,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11833,6 +11938,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11911,6 +12019,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11956,6 +12067,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12145,12 +12259,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12244,18 +12352,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12286,9 +12382,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12514,6 +12607,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12838,10 +12934,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12967,7 +13060,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13022,7 +13118,10 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13123,7 +13222,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13423,6 +13522,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13600,6 +13702,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13897,9 +14002,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13981,6 +14083,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13996,6 +14101,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14023,9 +14131,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14038,6 +14143,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14122,6 +14233,12 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14356,9 +14473,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14551,6 +14665,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14803,6 +14920,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15034,6 +15154,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15094,6 +15217,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15670,6 +15796,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15709,6 +15838,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15724,9 +15856,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15796,10 +15925,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15847,6 +15976,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16156,6 +16288,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16324,12 +16459,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16558,7 +16687,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16621,9 +16750,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16726,7 +16861,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16855,6 +16990,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16939,7 +17077,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17002,9 +17140,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17026,6 +17161,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17050,6 +17188,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17062,6 +17203,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17635,6 +17779,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17695,6 +17842,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17749,6 +17899,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17767,6 +17920,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18280,6 +18442,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18382,6 +18547,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18421,6 +18589,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18604,6 +18775,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18679,9 +18853,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18781,6 +18952,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18799,6 +18976,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18814,6 +18994,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18847,6 +19030,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19372,6 +19558,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19465,19 +19654,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19819,6 +20008,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20074,12 +20269,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20248,6 +20449,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20878,6 +21082,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21007,6 +21214,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21094,9 +21304,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21220,6 +21427,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21229,6 +21439,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21490,6 +21703,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21535,6 +21751,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21607,6 +21826,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21763,34 +21991,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21817,6 +22039,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21910,9 +22138,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22048,9 +22273,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22498,6 +22720,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22615,6 +22840,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22681,9 +22909,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22993,6 +23218,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23107,7 +23335,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23122,6 +23350,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23317,6 +23548,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23374,9 +23608,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23614,18 +23845,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23677,9 +23905,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23881,6 +24106,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23893,6 +24121,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23905,6 +24139,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23920,6 +24157,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24034,15 +24274,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24091,9 +24331,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24121,6 +24358,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24130,6 +24370,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24199,6 +24442,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24274,9 +24547,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24457,14 +24727,17 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24508,9 +24781,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24769,6 +25039,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24790,6 +25063,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25297,6 +25573,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25417,6 +25696,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25534,6 +25816,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25636,9 +25921,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25783,6 +26074,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26059,12 +26353,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26074,9 +26374,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26104,6 +26401,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26395,6 +26695,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26695,6 +26998,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26710,6 +27016,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26893,6 +27202,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26905,6 +27217,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27082,6 +27397,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27172,6 +27490,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27253,6 +27574,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27280,6 +27604,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27295,6 +27622,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27310,54 +27640,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27661,9 +27946,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27679,6 +27961,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27817,6 +28102,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27829,6 +28117,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28015,9 +28306,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28051,6 +28339,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28138,15 +28429,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28630,6 +28921,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28966,6 +29260,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28975,9 +29272,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29056,14 +29350,14 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29413,9 +29707,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29440,6 +29731,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29449,6 +29749,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29500,6 +29803,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29521,6 +29827,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29560,6 +29884,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29623,6 +29950,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29653,15 +29983,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29758,9 +30079,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30100,6 +30418,9 @@ msgstr[2] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30325,16 +30646,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30385,6 +30709,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30403,6 +30730,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30472,6 +30802,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30493,9 +30826,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30529,6 +30859,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30538,6 +30877,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30568,6 +30910,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30691,6 +31036,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30730,10 +31078,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30751,15 +31099,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31018,9 +31360,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31120,9 +31459,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31177,9 +31513,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31270,9 +31603,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31306,10 +31636,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31375,6 +31705,12 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31720,9 +32056,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31789,6 +32122,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31813,6 +32149,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31822,6 +32161,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31846,9 +32188,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32443,12 +32782,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32488,6 +32821,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32986,7 +33322,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33085,18 +33421,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33118,9 +33448,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33133,12 +33460,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33154,30 +33475,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33205,9 +33511,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33220,9 +33523,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33265,6 +33565,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33451,6 +33754,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33475,6 +33781,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33487,6 +33802,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33865,6 +34183,9 @@ msgstr[2] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33934,6 +34255,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33964,9 +34288,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34036,6 +34357,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34120,6 +34444,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34225,9 +34552,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34261,9 +34585,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34423,6 +34744,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34507,6 +34831,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34693,9 +35020,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34918,7 +35242,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35221,6 +35545,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35359,6 +35689,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35692,7 +36025,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35728,7 +36061,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35914,6 +36247,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36007,7 +36355,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36376,6 +36724,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36460,6 +36811,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36793,6 +37147,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36811,10 +37168,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36826,6 +37183,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36871,9 +37231,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36913,10 +37270,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37066,6 +37423,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37096,6 +37456,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37162,6 +37525,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37513,6 +37882,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37522,6 +37894,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37567,10 +37948,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38233,6 +38626,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38428,6 +38824,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38437,9 +38836,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38452,6 +38848,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38461,9 +38860,6 @@ msgstr[2] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38770,10 +39166,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38815,9 +39211,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38884,6 +39277,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39040,9 +39436,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39142,9 +39535,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39232,6 +39622,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39241,9 +39634,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39697,28 +40087,55 @@ msgstr[2] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39730,6 +40147,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39742,9 +40162,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] "približno 1 sat"
@@ -39853,12 +40270,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39886,6 +40309,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39901,9 +40327,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39934,6 +40357,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39970,9 +40396,21 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39982,7 +40420,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40048,6 +40492,18 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40081,10 +40537,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40204,6 +40660,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40261,9 +40723,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40276,6 +40735,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40291,6 +40756,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40327,6 +40795,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40528,6 +40999,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40687,6 +41164,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40720,6 +41200,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40783,6 +41269,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40816,9 +41305,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40933,12 +41419,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40954,6 +41434,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41002,6 +41485,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41077,6 +41566,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index c7c5e387754..c987b9f5b3b 100644
--- a/locale/hu_HU/gitlab.po
+++ b/locale/hu_HU/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hu\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/hy_AM/gitlab.po b/locale/hy_AM/gitlab.po
index 5219d91bbfe..e841e7a470a 100644
--- a/locale/hy_AM/gitlab.po
+++ b/locale/hy_AM/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hy-AM\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index 7555a705a95..c9adcdd242b 100644
--- a/locale/id_ID/gitlab.po
+++ b/locale/id_ID/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: id\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:18\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,23 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-
msgid " or "
msgstr ""
@@ -84,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -171,9 +163,6 @@ msgid "%d commit,"
msgid_plural "%d commits,"
msgstr[0] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -969,6 +958,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1051,9 +1043,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1104,6 +1102,9 @@ msgstr[0] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1326,9 +1327,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1362,7 +1360,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1389,6 +1387,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1737,6 +1738,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1818,9 +1822,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -1899,9 +1900,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -1995,6 +1993,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2451,7 +2452,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2466,6 +2467,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2601,7 +2608,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3216,7 +3223,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3234,6 +3241,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3249,7 +3259,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3489,13 +3499,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3699,6 +3712,10 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3762,9 +3779,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4090,12 +4104,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4108,12 +4128,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4126,6 +4155,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4141,6 +4179,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4150,6 +4191,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4421,12 +4465,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4660,6 +4698,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5291,6 +5332,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5530,7 +5574,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5641,6 +5685,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5848,9 +5895,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6134,9 +6178,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6194,6 +6235,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6520,6 +6567,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6553,6 +6603,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6667,6 +6720,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6709,15 +6765,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7360,7 +7410,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7801,6 +7851,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7810,6 +7863,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7819,9 +7875,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7834,6 +7905,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -7984,30 +8058,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8146,12 +8196,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8267,6 +8311,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8348,13 +8395,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8363,16 +8410,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8381,6 +8434,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8393,31 +8452,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8489,15 +8548,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8642,6 +8695,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8764,10 +8820,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -8963,7 +9019,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -8987,9 +9043,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9110,9 +9163,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9182,9 +9232,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9269,9 +9316,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9377,6 +9421,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9395,6 +9442,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9407,9 +9457,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9425,6 +9472,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9560,6 +9610,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9677,7 +9730,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9800,10 +9853,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9860,6 +9910,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -9914,6 +9967,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10073,6 +10135,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10138,6 +10203,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10631,6 +10699,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10697,6 +10768,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10736,16 +10810,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10820,9 +10912,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10850,9 +10939,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -10880,6 +10966,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11039,13 +11128,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11054,7 +11143,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11368,7 +11469,8 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11472,6 +11574,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11487,15 +11595,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11547,6 +11652,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11625,6 +11733,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11670,6 +11781,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11853,12 +11967,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -11950,18 +12058,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -11992,9 +12088,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12220,6 +12313,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12544,10 +12640,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12673,7 +12766,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12728,7 +12824,8 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12829,7 +12926,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13129,6 +13226,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13306,6 +13406,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13601,9 +13704,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13685,6 +13785,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13700,6 +13803,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13727,9 +13833,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13742,6 +13845,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13826,6 +13935,10 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14060,9 +14173,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14253,6 +14363,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14503,6 +14616,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14734,6 +14850,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14794,6 +14913,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15370,6 +15492,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15409,6 +15534,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15424,9 +15552,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15496,10 +15621,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15547,6 +15672,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -15856,6 +15984,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16024,12 +16155,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16258,7 +16383,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16321,9 +16446,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16426,7 +16557,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16555,6 +16686,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16639,7 +16773,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16698,9 +16832,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16722,6 +16853,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16746,6 +16880,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16758,6 +16895,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17325,6 +17465,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17385,6 +17528,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17439,6 +17585,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17457,6 +17606,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -17970,6 +18128,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18070,6 +18231,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18109,6 +18273,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18292,6 +18459,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18367,9 +18537,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18469,6 +18636,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18487,6 +18660,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18502,6 +18678,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18535,6 +18714,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19060,6 +19242,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19153,19 +19338,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19507,6 +19692,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19760,12 +19951,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -19934,6 +20131,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20550,6 +20750,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20679,6 +20882,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20766,9 +20972,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -20892,6 +21095,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -20901,6 +21107,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21162,6 +21371,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21207,6 +21419,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21279,6 +21494,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21435,34 +21659,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21489,6 +21707,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21580,9 +21804,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21718,9 +21939,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22166,6 +22384,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22281,6 +22502,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22347,9 +22571,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22657,6 +22878,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22771,7 +22995,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22786,6 +23010,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -22981,6 +23208,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23036,9 +23266,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23268,18 +23495,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23331,9 +23555,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23535,6 +23756,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23547,6 +23771,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23559,6 +23789,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23574,6 +23807,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23686,15 +23922,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23743,9 +23979,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23773,6 +24006,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23782,6 +24018,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -23851,6 +24090,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -23926,9 +24195,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24109,14 +24375,15 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24160,9 +24427,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24421,6 +24685,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24442,6 +24709,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -24949,6 +25219,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25069,6 +25342,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25186,6 +25462,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25288,9 +25567,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25435,6 +25720,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25711,12 +25999,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25726,9 +26020,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25756,6 +26047,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26047,6 +26341,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26347,6 +26644,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26362,6 +26662,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26545,6 +26848,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26557,6 +26863,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26734,6 +27043,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26824,6 +27136,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -26905,6 +27220,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26932,6 +27250,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -26947,6 +27268,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -26962,54 +27286,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27313,9 +27592,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27331,6 +27607,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27469,6 +27748,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27481,6 +27763,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27667,9 +27952,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27703,6 +27985,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27790,15 +28075,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28278,6 +28563,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28606,6 +28894,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28615,9 +28906,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28696,12 +28984,12 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgid "Requires values to meet regular expression requirements."
@@ -29045,9 +29333,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29072,6 +29357,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29081,6 +29375,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29132,6 +29429,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29153,6 +29453,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29192,6 +29510,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29255,6 +29576,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29285,15 +29609,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29390,9 +29705,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29710,6 +30022,9 @@ msgstr[0] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -29935,16 +30250,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -29995,6 +30313,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30013,6 +30334,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30082,6 +30406,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30103,9 +30430,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30139,6 +30463,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30148,6 +30481,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30178,6 +30514,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30301,6 +30640,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30340,10 +30682,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30361,15 +30703,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30628,9 +30964,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30730,9 +31063,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30787,9 +31117,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -30880,9 +31207,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -30916,10 +31240,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -30985,6 +31309,10 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31326,9 +31654,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31395,6 +31720,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31419,6 +31747,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31428,6 +31759,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31452,9 +31786,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32049,12 +32380,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32094,6 +32419,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32592,7 +32920,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32691,18 +33019,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32724,9 +33046,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32739,12 +33058,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32760,30 +33073,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -32811,9 +33109,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -32826,9 +33121,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -32871,6 +33163,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33057,6 +33352,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33081,6 +33379,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33093,6 +33400,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33461,6 +33771,9 @@ msgstr[0] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33530,6 +33843,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33560,9 +33876,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33630,6 +33943,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33714,6 +34030,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -33819,9 +34138,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -33855,9 +34171,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34017,6 +34330,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34101,6 +34417,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34287,9 +34606,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34512,7 +34828,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -34815,6 +35131,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -34953,6 +35275,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35282,7 +35607,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35318,7 +35643,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35504,6 +35829,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35597,7 +35937,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -35964,6 +36304,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36048,6 +36391,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36381,6 +36727,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36399,10 +36748,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36414,6 +36763,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36459,9 +36811,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36501,10 +36850,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36654,6 +37003,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36684,6 +37036,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36750,6 +37105,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37101,6 +37462,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37110,6 +37474,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37155,10 +37528,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -37815,6 +38200,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38010,6 +38398,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38019,9 +38410,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38034,6 +38422,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38041,9 +38432,6 @@ msgstr[0] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38350,10 +38738,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38395,9 +38783,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38464,6 +38849,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38620,9 +39008,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38722,9 +39107,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -38812,6 +39194,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -38821,9 +39206,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39275,28 +39657,55 @@ msgstr[0] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39308,6 +39717,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39320,9 +39732,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39427,12 +39836,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39460,6 +39875,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39475,9 +39893,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39508,6 +39923,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39544,9 +39962,19 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39556,7 +39984,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39622,6 +40056,16 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39655,10 +40099,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39776,6 +40220,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -39831,9 +40281,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -39846,6 +40293,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -39859,6 +40312,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -39895,6 +40351,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40090,6 +40549,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40247,6 +40712,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40280,6 +40748,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40341,6 +40815,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40372,9 +40849,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40489,12 +40963,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40510,6 +40978,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40558,6 +41029,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40633,6 +41110,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/ig_NG/gitlab.po b/locale/ig_NG/gitlab.po
index dca470ff8a7..3a890d99d72 100644
--- a/locale/ig_NG/gitlab.po
+++ b/locale/ig_NG/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ig\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,23 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-
msgid " or "
msgstr ""
@@ -84,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -171,9 +163,6 @@ msgid "%d commit,"
msgid_plural "%d commits,"
msgstr[0] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -969,6 +958,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1051,9 +1043,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1104,6 +1102,9 @@ msgstr[0] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1326,9 +1327,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1362,7 +1360,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1389,6 +1387,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1737,6 +1738,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1818,9 +1822,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -1899,9 +1900,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -1995,6 +1993,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2451,7 +2452,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2466,6 +2467,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2601,7 +2608,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3216,7 +3223,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3234,6 +3241,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3249,7 +3259,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3489,13 +3499,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3699,6 +3712,10 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3762,9 +3779,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4090,12 +4104,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4108,12 +4128,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4126,6 +4155,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4141,6 +4179,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4150,6 +4191,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4421,12 +4465,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4660,6 +4698,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5291,6 +5332,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5530,7 +5574,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5641,6 +5685,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5848,9 +5895,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6134,9 +6178,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6194,6 +6235,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6520,6 +6567,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6553,6 +6603,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6667,6 +6720,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6709,15 +6765,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7360,7 +7410,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7801,6 +7851,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7810,6 +7863,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7819,9 +7875,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7834,6 +7905,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -7984,30 +8058,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8146,12 +8196,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8267,6 +8311,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8348,13 +8395,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8363,16 +8410,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8381,6 +8434,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8393,31 +8452,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8489,15 +8548,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8642,6 +8695,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8764,10 +8820,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -8963,7 +9019,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -8987,9 +9043,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9110,9 +9163,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9182,9 +9232,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9269,9 +9316,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9377,6 +9421,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9395,6 +9442,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9407,9 +9457,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9425,6 +9472,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9560,6 +9610,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9677,7 +9730,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9800,10 +9853,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9860,6 +9910,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -9914,6 +9967,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10073,6 +10135,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10138,6 +10203,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10631,6 +10699,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10697,6 +10768,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10736,16 +10810,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10820,9 +10912,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10850,9 +10939,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -10880,6 +10966,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11039,13 +11128,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11054,7 +11143,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11368,7 +11469,8 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11472,6 +11574,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11487,15 +11595,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11547,6 +11652,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11625,6 +11733,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11670,6 +11781,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11853,12 +11967,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -11950,18 +12058,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -11992,9 +12088,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12220,6 +12313,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12544,10 +12640,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12673,7 +12766,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12728,7 +12824,8 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12829,7 +12926,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13129,6 +13226,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13306,6 +13406,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13601,9 +13704,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13685,6 +13785,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13700,6 +13803,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13727,9 +13833,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13742,6 +13845,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13826,6 +13935,10 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14060,9 +14173,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14253,6 +14363,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14503,6 +14616,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14734,6 +14850,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14794,6 +14913,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15370,6 +15492,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15409,6 +15534,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15424,9 +15552,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15496,10 +15621,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15547,6 +15672,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -15856,6 +15984,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16024,12 +16155,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16258,7 +16383,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16321,9 +16446,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16426,7 +16557,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16555,6 +16686,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16639,7 +16773,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16698,9 +16832,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16722,6 +16853,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16746,6 +16880,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16758,6 +16895,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17325,6 +17465,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17385,6 +17528,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17439,6 +17585,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17457,6 +17606,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -17970,6 +18128,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18070,6 +18231,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18109,6 +18273,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18292,6 +18459,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18367,9 +18537,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18469,6 +18636,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18487,6 +18660,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18502,6 +18678,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18535,6 +18714,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19060,6 +19242,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19153,19 +19338,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19507,6 +19692,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19760,12 +19951,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -19934,6 +20131,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20550,6 +20750,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20679,6 +20882,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20766,9 +20972,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -20892,6 +21095,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -20901,6 +21107,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21162,6 +21371,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21207,6 +21419,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21279,6 +21494,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21435,34 +21659,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21489,6 +21707,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21580,9 +21804,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21718,9 +21939,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22166,6 +22384,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22281,6 +22502,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22347,9 +22571,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22657,6 +22878,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22771,7 +22995,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22786,6 +23010,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -22981,6 +23208,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23036,9 +23266,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23268,18 +23495,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23331,9 +23555,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23535,6 +23756,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23547,6 +23771,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23559,6 +23789,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23574,6 +23807,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23686,15 +23922,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23743,9 +23979,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23773,6 +24006,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23782,6 +24018,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -23851,6 +24090,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -23926,9 +24195,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24109,14 +24375,15 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24160,9 +24427,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24421,6 +24685,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24442,6 +24709,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -24949,6 +25219,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25069,6 +25342,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25186,6 +25462,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25288,9 +25567,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25435,6 +25720,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25711,12 +25999,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25726,9 +26020,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25756,6 +26047,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26047,6 +26341,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26347,6 +26644,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26362,6 +26662,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26545,6 +26848,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26557,6 +26863,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26734,6 +27043,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26824,6 +27136,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -26905,6 +27220,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26932,6 +27250,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -26947,6 +27268,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -26962,54 +27286,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27313,9 +27592,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27331,6 +27607,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27469,6 +27748,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27481,6 +27763,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27667,9 +27952,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27703,6 +27985,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27790,15 +28075,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28278,6 +28563,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28606,6 +28894,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28615,9 +28906,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28696,12 +28984,12 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgid "Requires values to meet regular expression requirements."
@@ -29045,9 +29333,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29072,6 +29357,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29081,6 +29375,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29132,6 +29429,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29153,6 +29453,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29192,6 +29510,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29255,6 +29576,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29285,15 +29609,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29390,9 +29705,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29710,6 +30022,9 @@ msgstr[0] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -29935,16 +30250,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -29995,6 +30313,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30013,6 +30334,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30082,6 +30406,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30103,9 +30430,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30139,6 +30463,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30148,6 +30481,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30178,6 +30514,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30301,6 +30640,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30340,10 +30682,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30361,15 +30703,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30628,9 +30964,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30730,9 +31063,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30787,9 +31117,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -30880,9 +31207,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -30916,10 +31240,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -30985,6 +31309,10 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31326,9 +31654,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31395,6 +31720,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31419,6 +31747,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31428,6 +31759,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31452,9 +31786,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32049,12 +32380,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32094,6 +32419,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32592,7 +32920,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32691,18 +33019,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32724,9 +33046,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32739,12 +33058,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32760,30 +33073,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -32811,9 +33109,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -32826,9 +33121,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -32871,6 +33163,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33057,6 +33352,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33081,6 +33379,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33093,6 +33400,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33461,6 +33771,9 @@ msgstr[0] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33530,6 +33843,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33560,9 +33876,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33630,6 +33943,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33714,6 +34030,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -33819,9 +34138,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -33855,9 +34171,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34017,6 +34330,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34101,6 +34417,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34287,9 +34606,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34512,7 +34828,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -34815,6 +35131,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -34953,6 +35275,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35282,7 +35607,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35318,7 +35643,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35504,6 +35829,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35597,7 +35937,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -35964,6 +36304,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36048,6 +36391,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36381,6 +36727,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36399,10 +36748,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36414,6 +36763,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36459,9 +36811,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36501,10 +36850,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36654,6 +37003,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36684,6 +37036,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36750,6 +37105,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37101,6 +37462,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37110,6 +37474,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37155,10 +37528,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -37815,6 +38200,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38010,6 +38398,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38019,9 +38410,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38034,6 +38422,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38041,9 +38432,6 @@ msgstr[0] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38350,10 +38738,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38395,9 +38783,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38464,6 +38849,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38620,9 +39008,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38722,9 +39107,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -38812,6 +39194,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -38821,9 +39206,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39275,28 +39657,55 @@ msgstr[0] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39308,6 +39717,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39320,9 +39732,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39427,12 +39836,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39460,6 +39875,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39475,9 +39893,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39508,6 +39923,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39544,9 +39962,19 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39556,7 +39984,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39622,6 +40056,16 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39655,10 +40099,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39776,6 +40220,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -39831,9 +40281,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -39846,6 +40293,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -39859,6 +40312,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -39895,6 +40351,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40090,6 +40549,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40247,6 +40712,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40280,6 +40748,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40341,6 +40815,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40372,9 +40849,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40489,12 +40963,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40510,6 +40978,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40558,6 +41029,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40633,6 +41110,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/is_IS/gitlab.po b/locale/is_IS/gitlab.po
index d35fb042464..dfe2b282cbd 100644
--- a/locale/is_IS/gitlab.po
+++ b/locale/is_IS/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: is\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:18\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index 2193c3d525a..d6749d72572 100644
--- a/locale/it/gitlab.po
+++ b/locale/it/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: it\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Devi farlo prima di %{grace_period_deadline}."
-msgid " and"
-msgstr " e"
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " degradato di %d punto"
-msgstr[1] " degradato di %d punti"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " migliorato di %d punto"
-msgstr[1] " migliorato di %d punti"
-
msgid " or "
msgstr " o "
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] "%d commit,"
msgstr[1] "%d commit,"
-msgid "%d commits"
-msgstr "%d commit"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr "Un ramo predefinito non può essere scelto per un progetto vuoto."
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Attivo"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr "Agosto"
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,8 +5699,8 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "Impossibile trovare l'HEAD commit per questa branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "Confronta"
@@ -5767,6 +5810,9 @@ msgstr "Per confermare, scrivi %{branch_name_confirmation}:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Confronta"
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Crea una nuova cartella"
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,18 +10945,36 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "Definisci un patter personalizzato mediante la sintassi cron"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Fully protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr "Definisci un patter personalizzato mediante la sintassi cron"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr "Esplora gruppi pubblici"
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr "Cronologia"
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "Ultima Pipeline"
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr "Nuovo tag"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr "Opzioni"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr "Proprietario"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr "Profilo"
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr "Non hai i permessi per eliminare questo utente."
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "Richiedi accesso"
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr "Establezca una contraseña en su cuenta para actualizar o enviar a travÃ
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "imposta una password"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "Snippet"
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index e417900b458..4ed672c3b99 100644
--- a/locale/ja/gitlab.po
+++ b/locale/ja/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ja\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr " %{start} ã‹ã‚‰ %{end} ã¾ã§"
@@ -40,23 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr " %{grace_period_deadline} ã®å‰ã«ã“れを行ã†å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-msgid " and"
-msgstr " ã¨"
-
msgid " and "
msgstr " 㨠"
msgid " and %{sliced}"
msgstr " 㨠%{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " %dãƒã‚¤ãƒ³ãƒˆæ‚ªåŒ–"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " %dãƒã‚¤ãƒ³ãƒˆã§æ”¹å–„"
-
msgid " or "
msgstr " ã¾ãŸã¯ "
@@ -84,6 +73,9 @@ msgstr "\"%{repository_name}\" ã®ã‚µã‚¤ã‚º (%{repository_size}) ãŒåˆ¶é™ã® %{
msgid "\"el\" parameter is required for createInstance()"
msgstr "createInstance() ã«ã¯ \"el\" パラメータãŒå¿…è¦ã§ã™"
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -171,9 +163,6 @@ msgid "%d commit,"
msgid_plural "%d commits,"
msgstr[0] "%d個ã®ã‚³ãƒŸãƒƒãƒˆ,"
-msgid "%d commits"
-msgstr "%d個ã®ã‚³ãƒŸãƒƒãƒˆ"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] "%d件ã®å®Œäº†ã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼"
@@ -969,6 +958,9 @@ msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} を使ã†ã¨ã€ã‚°ãƒ«ãƒ
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1051,9 +1043,15 @@ msgstr "(除去ã—ã¾ã—ãŸ)"
msgid "(revoked)"
msgstr "(失効)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} 件以上"
@@ -1104,6 +1102,9 @@ msgstr[0] "- イベント"
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- ユーザー"
@@ -1326,9 +1327,6 @@ msgstr "プロジェクトãŒç©ºã®å ´åˆã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ–ランãƒã‚’é¸
msgid "A deleted user"
msgstr "削除ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
-msgid "A description is required"
-msgstr "説明ã¯å¿…須項目ã§ã™ã€‚"
-
msgid "A different reason"
msgstr ""
@@ -1362,8 +1360,8 @@ msgstr "ãŸã ã¡ã«ä¸æ­£åˆ©ç”¨å¯¾å¿œãƒãƒ¼ãƒ ãƒ¡ãƒ³ãƒãƒ¼ã§ã„ãŸã ã„ãŸãƒ¬
msgid "A merge request hasn't yet been merged"
msgstr "マージリクエストã¯ã¾ã ãƒžãƒ¼ã‚¸ã•ã‚Œã¦ã„ã¾ã›ã‚“"
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
-msgstr "æ–°ã—ã„Auto DevOps パイプラインãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚詳細ã«ã¤ã„ã¦ã¯ã€ %{pipelines_link_start}パイプラインページ%{pipelines_link_end} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
+msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
msgstr "%{name} ã®æ–°ã—ã„リリース %{tag} ãŒå…¬é–‹ã•ã‚Œã¾ã—ãŸã€‚ 詳細ã«ã¤ã„ã¦ã¯ã€ %{release_link_start} リリースページ %{release_link_end} ã‚’ã”覧ãã ã•ã„。"
@@ -1389,6 +1387,9 @@ msgstr "プラットフォームã®å€¤ã¯ã€ã‚¦ã‚§ãƒ–ã€ãƒ¢ãƒã‚¤ãƒ«ã€ã¾ãŸã¯
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr "アメリカåˆè¡†å›½ä¿å¥ç¦ç¥‰çœãŒç™ºè¡Œã—ãŸHIPAA監査プロトコルã®å„監査照会ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’å«ã‚€ãƒ—ロジェクト"
@@ -1737,6 +1738,9 @@ msgstr "アクション"
msgid "Activate Service Desk"
msgstr "サービスデスクを有効ã«ã™ã‚‹"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "有効"
@@ -1818,9 +1822,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "ã“ã® %{noteableDisplayName} ã¸ä¸€èˆ¬çš„ãªã‚³ãƒ¡ãƒ³ãƒˆã‚’追加。"
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "ã“ã® %{noteable_name} ã«ã¤ã„ã¦å¤§ã¾ã‹ãªã‚³ãƒ¡ãƒ³ãƒˆã‚’追加"
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "ã‚ãªãŸã® Wiki ã«ãƒ—ロジェクトã«é–¢ã™ã‚‹æƒ…報をå«ã‚€ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’追加ã™ã‚‹ã¨ã€GitLab ã¯ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®ä»£ã‚ã‚Šã«ãれをã“ã“ã«è¡¨ç¤ºã—ã¾ã™ã€‚"
@@ -1899,9 +1900,6 @@ msgstr "デプロイフリーズを追加"
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr "ドメインを追加"
-
msgid "Add email address"
msgstr "メールアドレス追加"
@@ -1995,6 +1993,9 @@ msgstr "レビュー追加"
msgid "Add to tree"
msgstr "ツリーã«è¿½åŠ "
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2451,8 +2452,8 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "管ç†è€…"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
-msgstr "管ç†è€…ã¯ã™ã¹ã¦ã®ã‚°ãƒ«ãƒ¼ãƒ—ã€ãƒ—ロジェクトã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚ã¾ãŸã“ã® GitLab ã®ã™ã¹ã¦ã®æ©Ÿèƒ½ã‚’管ç†ã§ãã¾ã™"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgstr ""
msgid "AdminUsers|Admins"
msgstr "管ç†è€…"
@@ -2466,6 +2467,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr "承èªã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯æ¬¡ã®ã“ã¨ãŒã§ãã¾ã™:"
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr "自動的ã«ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®å†…部ユーザーã¨ã—ã¦ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸã€‚"
@@ -2601,8 +2608,8 @@ msgstr "ユーザーã®å†æœ‰åŠ¹åŒ–:"
msgid "AdminUsers|Regular"
msgstr "標準"
-msgid "AdminUsers|Regular users have access to their groups and projects"
-msgstr "標準ユーザーã¯ã‚°ãƒ«ãƒ¼ãƒ—やプロジェクトã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™"
+msgid "AdminUsers|Regular users have access to their groups and projects."
+msgstr ""
msgid "AdminUsers|Reject"
msgstr "æ‹’å¦"
@@ -3216,8 +3223,8 @@ msgstr "ã™ã¹ã¦ã®ç«¶åˆãŒè§£æ±ºã•ã‚Œã¾ã—ãŸã€‚マージリクエストを
msgid "All merge request dependencies have been merged"
msgstr "ä¾å­˜ã™ã‚‹ã™ã¹ã¦ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã—ãŸ"
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
-msgstr "ã™ã¹ã¦ã®ãƒ‘スã¯GitLab URL㮠相対パスã§ã™ã€‚ %{relative_url_link_start}相対URL%{relative_url_link_end}ã‚’å«ã‚ãªã„ã§ãã ã•ã„。"
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
+msgstr ""
msgid "All projects"
msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクト"
@@ -3234,6 +3241,9 @@ msgstr ""
msgid "All users must have a name."
msgstr "ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«åå‰ãŒå¿…è¦ã§ã™ã€‚"
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "%{group_name} ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã‚’許å¯"
@@ -3249,7 +3259,7 @@ msgstr "ターゲットブランãƒã«ãƒžãƒ¼ã‚¸ã§ãるメンãƒãƒ¼ã‹ã‚‰ã®ã‚³
msgid "Allow group owners to manage LDAP-related settings"
msgstr "グループオーナー㌠LDAP 関連ã®è¨­å®šã‚’管ç†ã§ãるよã†ã«ã™ã‚‹"
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3489,13 +3499,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
-msgstr "ブランãƒã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚検索をå†è©¦è¡Œã—ã¦ãã ã•ã„。"
+msgid "An error occurred while fetching branches. Retry the search."
+msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3699,6 +3712,10 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "通知ã®è³¼èª­ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -3762,9 +3779,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr "インスタンスレベル㮠serverless ドメインã¯ã™ã§ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚"
-
msgid "An issue already exists"
msgstr ""
@@ -4090,12 +4104,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4108,12 +4128,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "承èªè€…"
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr "åå‰"
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4126,6 +4155,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr "ルールå"
@@ -4141,6 +4179,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4150,6 +4191,9 @@ msgstr "ターゲットブランãƒ"
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4421,12 +4465,6 @@ msgstr "本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿã“ã®GPGキーを削除ã—ã¦ã‚‚ã€ã™
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr "本当ã«å®Ÿè¡Œã—ã¾ã™ã‹? ã“ã‚Œã¯ç™»éŒ²ã•ã‚ŒãŸã‚¢ãƒ—リケーション㨠U2Fデãƒã‚¤ã‚¹ã‚’無効ã«ã—ã¾ã™ã€‚"
-
msgid "Arrange charts"
msgstr "ãƒãƒ£ãƒ¼ãƒˆã®ã‚¢ãƒ¬ãƒ³ã‚¸"
@@ -4660,6 +4698,9 @@ msgstr "8月"
msgid "Authenticate"
msgstr "èªè¨¼"
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr "GitHub ã§èªè¨¼ã—ã¾ã™"
@@ -5291,6 +5332,9 @@ msgstr "ブロック"
msgid "Blog"
msgstr "ブログ"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "ボードã®ç¯„囲ã¯ã€ã“ã®ãƒœãƒ¼ãƒ‰ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ãŸä»»æ„ã®äººã«è¡¨ç¤ºã•ã‚Œã‚‹ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã«å½±éŸ¿ã—ã¾ã™"
@@ -5530,8 +5574,8 @@ msgstr "ã™ã¹ã¦"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "ã“ã®ãƒ–ランãƒã«ã¯HEADコミットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "比較"
@@ -5641,6 +5685,9 @@ msgstr "確èªã®ãŸã‚ã€%{branch_name_confirmation} を入力ã—ã¦ãã ã•ã
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "ローカルã®å¤‰æ›´å†…容を破棄ã—ã¦ã€ã‚¢ãƒƒãƒ—ストリームã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ãƒ–ランãƒã‚’上書ãã™ã‚‹ã«ã¯ã€ã“ã“ã§ãれらを削除ã—ã€ä¸Šã®ã€Œä»Šã™ãæ›´æ–°ã€ã‚’クリックã—ã¦ãã ã•ã„。"
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5848,9 +5895,6 @@ msgstr "CI Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6134,9 +6178,6 @@ msgstr "プレビューをキャンセル"
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr "自動的ã«ãƒžãƒ¼ã‚¸ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“"
@@ -6194,6 +6235,12 @@ msgstr "2è¦ç´ èªè¨¼ã®è¨­å®šã‚’スキップã§ãã¾ã›ã‚“"
msgid "Capacity threshold"
msgstr "キャパシティ判定ã®ã—ãã„値"
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6520,6 +6567,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr "ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ"
@@ -6553,6 +6603,9 @@ msgstr "クレジットカードã®ãƒ•ã‚©ãƒ¼ãƒ èª­ã¿è¾¼ã¿å¤±æ•—ã—ã¾ã—ãŸã€‚
msgid "Checkout|Edit"
msgstr "編集"
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6667,6 +6720,9 @@ msgstr "会社ã¾ãŸã¯ãƒãƒ¼ãƒ "
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6709,15 +6765,9 @@ msgstr "テンプレートをé¸æŠžã—ã¦ãã ã•ã„..."
msgid "Choose a type..."
msgstr "タイプをé¸æŠžã—ã¦ãã ã•ã„..."
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr "カラーをé¸æŠžã—ã¦ãã ã•ã„。"
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr "ファイルをé¸æŠž..."
@@ -7360,7 +7410,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7801,6 +7851,9 @@ msgstr "セキュリティグループ"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Kubernetes クラスターã®è©³ç´°ã‚’閲覧ã€ç·¨é›†ã™ã‚‹"
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr "VPC ã‚’é¸æŠžã—ã¦ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠž"
@@ -7810,6 +7863,9 @@ msgstr "VPC ã‚’é¸æŠžã—ã¦ã‚µãƒ–ãƒãƒƒãƒˆã‚’é¸æŠž"
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’é¸æŠžã—ã¦ã‚µãƒ–ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’é¸æŠž"
@@ -7819,9 +7875,24 @@ msgstr "リージョンをé¸æŠžã—ã¦ã‚­ãƒ¼ãƒšã‚¢ã‚’é¸æŠž"
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr "リージョンをé¸æŠžã—ã¦VPCã‚’é¸æŠž"
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr "ゾーンをé¸æŠžã—ã¦ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’é¸æŠž"
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "マシンタイプをé¸æŠž"
@@ -7834,6 +7905,9 @@ msgstr "プロジェクトã¨ã‚¾ãƒ¼ãƒ³ã‚’é¸æŠžã—ã¦ãƒžã‚·ãƒ³ã‚¿ã‚¤ãƒ—ã‚’é¸æŠž
msgid "ClusterIntegration|Select project to choose zone"
msgstr "プロジェクトをé¸æŠžã—ã¦ã‚¾ãƒ¼ãƒ³ã‚’é¸æŠž"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -7984,30 +8058,6 @@ msgstr "å¿…è¦æ¡ä»¶"
msgid "ClusterIntegration|sign up"
msgstr "æ–°è¦ç™»éŒ²"
-msgid "ClusterIntergation|Select a VPC"
-msgstr "VPCã‚’é¸æŠž"
-
-msgid "ClusterIntergation|Select a network"
-msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’é¸æŠž"
-
-msgid "ClusterIntergation|Select a security group"
-msgstr "セキュリティグループをé¸æŠž"
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr "サブãƒãƒƒãƒˆã‚’é¸æŠž"
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr "サブãƒãƒƒãƒˆã‚’é¸æŠž"
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr "インスタンスタイプをé¸æŠž"
-
-msgid "ClusterIntergation|Select key pair"
-msgstr "キーペアをé¸æŠž"
-
-msgid "ClusterIntergation|Select service role"
-msgstr "サービスロールをé¸æŠž"
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8146,12 +8196,6 @@ msgstr "コマンドã¯é©ç”¨ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
msgid "Comment"
msgstr "コメント"
-msgid "Comment & close %{noteable_name}"
-msgstr "コメントã—ã¦é–‰ã˜ã‚‹ %{noteable_name}"
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr "コメントã—ã¦å†é–‹ %{noteable_name}"
-
msgid "Comment & resolve thread"
msgstr "コメントã—ã¦ã€ã‚¹ãƒ¬ãƒƒãƒ‰ã‚’解決ã™ã‚‹"
@@ -8267,6 +8311,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "比較"
@@ -8348,31 +8395,37 @@ msgstr "完了"
msgid "Completed"
msgstr ""
-msgid "Compliance"
-msgstr "コンプライアンス"
-
-msgid "Compliance Dashboard"
-msgstr "コンプライアンスダッシュボード"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
+msgstr ""
msgid "Compliance framework"
msgstr ""
+msgid "Compliance report"
+msgstr ""
+
msgid "ComplianceDashboard|created by:"
msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8381,6 +8434,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8393,31 +8452,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8489,15 +8548,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr "既存ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’設定ã™ã‚‹"
-msgid "Configure paths to be protected by Rack Attack."
-msgstr "Rack 攻撃を防御ã™ã‚‹ãƒ‘スを設定ã—ã¾ã™ã€‚"
-
msgid "Configure repository mirroring."
msgstr "リãƒã‚¸ãƒˆãƒªã®ãƒŸãƒ©ãƒ¼ãƒªãƒ³ã‚°ã‚’設定ã—ã¾ã™ã€‚"
@@ -8642,6 +8695,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "コンテナレジストリ"
@@ -8764,10 +8820,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -8963,7 +9019,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -8987,9 +9043,6 @@ msgstr "ã‚ãªãŸã¯ %{title} リãƒã‚¸ãƒˆãƒªã‚’削除ã—よã†ã¨ã—ã¦ã„ã¾ã
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr "次ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã—ã¦ã€ã“ã®ãƒ¬ã‚¸ã‚¹ãƒˆãƒªã«ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’追加ã§ãã¾ã™ï¼š"
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr "%{count} 個ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ãŒå«ã¾ã‚Œã¦ã„ã¾ã™(%{size})"
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9110,9 +9163,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr "%{protocol} クローン URL をコピー"
-msgid "Copy %{proxy_url}"
-msgstr "%{proxy_url} をコピー"
-
msgid "Copy %{type}"
msgstr ""
@@ -9182,9 +9232,6 @@ msgstr "リンクをコピー"
msgid "Copy link to chart"
msgstr "ãƒãƒ£ãƒ¼ãƒˆã¸ã®ãƒªãƒ³ã‚¯ã‚’コピー"
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr "å‚ç…§ã®ã‚³ãƒ”ー"
@@ -9269,9 +9316,6 @@ msgstr "管ç†è€…ã¯ãƒ¡ãƒ³ãƒãƒ¼ã¨ã—ã¦è¿½åŠ ã§ãã¾ã›ã‚“。"
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr "ãƒãƒ£ãƒƒãƒˆã®ãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ ã‚’承èªã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -9377,6 +9421,9 @@ msgstr "デザインをアップロードã§ãã¾ã›ã‚“ã§ã—ãŸã€‚アップロ
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr "ã‚«ãƒãƒ¬ãƒƒã‚¸"
@@ -9395,6 +9442,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’作æˆ"
@@ -9407,9 +9457,6 @@ msgstr "ã¯ã˜ã‚ã«GitLabアカウントを作æˆã—ã€ãã®å¾Œ %{label} ã®ã‚
msgid "Create a Mattermost team for this group"
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã® Mattermost ãƒãƒ¼ãƒ ã‚’作æˆã—ã¾ã™"
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr "é »ç¹ã«ä½¿ç”¨ã™ã‚‹ã‚¢ãƒƒãƒ—ストリームイメージをä¿å­˜ã™ã‚‹ãŸã‚ã€ãƒ­ãƒ¼ã‚«ãƒ«ãƒ—ロキシを作æˆã—ã¾ã™ã€‚ %{link_start}ä¾å­˜é–¢ä¿‚プロキシã«ã¤ã„ã¦ã¯ã“ã¡ã‚‰ã‚’å‚ç…§ã—ã¦ãã ã•ã„%{link_end}。"
-
msgid "Create a merge request"
msgstr "マージリクエストを作æˆ"
@@ -9425,6 +9472,9 @@ msgstr "ã¾ã ãƒ•ã‚¡ã‚¤ãƒ«ãŒãªã„ãŸã‚ã€æ–°ã—ã„ファイルを作æˆã—ã¾
msgid "Create a new issue"
msgstr "イシューã®æ–°è¦ä½œæˆ"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr "æ–°ã—ã„リãƒã‚¸ãƒˆãƒªã‚’作æˆ"
@@ -9560,6 +9610,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9677,7 +9730,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr "ステージを復元"
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9800,10 +9853,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr "SSH éµ"
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9860,6 +9910,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr "ç¾åœ¨ã®è„†å¼±æ€§ã‚«ã‚¦ãƒ³ãƒˆ"
@@ -9914,6 +9967,15 @@ msgstr "カスタム範囲"
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10073,6 +10135,9 @@ msgstr "完了ã¾ã§ã®æ—¥æ•°"
msgid "CycleAnalytics|Display chart filters"
msgstr "ãƒãƒ£ãƒ¼ãƒˆãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã®è¡¨ç¤º"
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr "ステージã¯é¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“"
@@ -10138,6 +10203,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10631,6 +10699,9 @@ msgstr "日付é¸æŠž"
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10697,6 +10768,9 @@ msgstr "デフォルトブランãƒ"
msgid "Default branch and protected branches"
msgstr "デフォルトブランãƒã¨ä¿è­·ãƒ–ランãƒ"
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr "デフォルト分類ラベル"
@@ -10736,18 +10810,36 @@ msgstr "デフォルト:FogBugz ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆIDをフルãƒãƒ¼ãƒ ã«ãƒžãƒ
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "Cron 構文ã§ã‚«ã‚¹ã‚¿ãƒ ãªãƒ‘ターンを指定ã™ã‚‹"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
+msgid "Define a custom pattern with cron syntax"
+msgstr "Cron 構文ã§ã‚«ã‚¹ã‚¿ãƒ ãªãƒ‘ターンを指定ã™ã‚‹"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -10820,9 +10912,6 @@ msgstr "コメントを削除"
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10850,9 +10939,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr "スニペットã®å‰Šé™¤"
@@ -10880,6 +10966,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "プロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã™ã‹ã€ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
@@ -11039,13 +11128,13 @@ msgstr "ä¾å­˜é–¢ä¿‚プロキシ"
msgid "Dependency Scanning"
msgstr "ä¾å­˜é–¢ä¿‚スキャン"
-msgid "Dependency proxy"
-msgstr "ä¾å­˜é–¢ä¿‚プロキシ"
+msgid "DependencyProxy|Cached %{time}"
+msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
-msgstr "ä¾å­˜é–¢ä¿‚プロキシ機能ã¯ã€ç¾åœ¨å…¬é–‹ã‚°ãƒ«ãƒ¼ãƒ—ã«åˆ¶é™ã•ã‚Œã¦ã„ã¾ã™ã€‚"
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
+msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11054,8 +11143,20 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
-msgstr "ä¾å­˜é–¢ä¿‚プロキシã®åˆ‡ã‚Šæ›¿ãˆ"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
+msgstr ""
msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
@@ -11368,7 +11469,8 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr "%{designs_count} / %{current_design}"
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "åŒã˜ãƒ•ã‚¡ã‚¤ãƒ«åã§è¨­è¨ˆã™ã‚‹ã¨ã€æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ç½®ãæ›ãˆã‚‰ã‚Œã¾ã™ã€‚"
@@ -11472,6 +11574,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr "å…¨é¸æŠž"
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr "デザインã¯æœ€å¤§ã§ %{upload_limit} ã¾ã§ã‚¢ãƒƒãƒ—ロードã§ãã¾ã™ã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -11487,13 +11595,10 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
-msgstr "アップロードãŒã‚¹ã‚­ãƒƒãƒ—ã•ã‚Œã¾ã—ãŸã€‚"
-
-msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
+msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
msgid "Designs"
@@ -11547,6 +11652,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11625,6 +11733,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11670,6 +11781,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11853,12 +11967,6 @@ msgstr "無料トライアルを始ã‚ã‚‹"
msgid "Discover|Upgrade now"
msgstr "今ã™ãアップグレード"
-msgid "Discuss a specific suggestion or question"
-msgstr "具体的ãªæ案や質å•ã«ã¤ã„ã¦è­°è«–ã—ã¾ã™ã€‚"
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr "解決ãŒå¿…è¦ãªã€å…·ä½“çš„ãªæ案や質å•ã«ã¤ã„ã¦è­°è«–ã™ã‚‹ã€‚"
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr "解決ãŒå¿…è¦ãªã€å…·ä½“çš„ãªæ案や質å•ã«ã¤ã„ã¦è­°è«–ã™ã‚‹ã€‚"
@@ -11950,18 +12058,6 @@ msgstr "ドメイン"
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr "ドメインã¯æ­£å¸¸ã«ä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
-
-msgid "Domain was successfully deleted."
-msgstr "ドメインã¯æ­£å¸¸ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
-
-msgid "Domain was successfully updated."
-msgstr "ドメインã¯æ­£å¸¸ã«æ›´æ–°ã§ãã¾ã—ãŸã€‚"
-
msgid "Don't have an account yet?"
msgstr "ã¾ã ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ãŠæŒã¡ã§ãªã„ã§ã™ã‹ï¼Ÿ"
@@ -11992,9 +12088,6 @@ msgstr "%{format} をダウンロード"
msgid "Download %{format}:"
msgstr "%{format} をダウンロード:"
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12220,6 +12313,9 @@ msgstr "ã“ã®ãƒªãƒªãƒ¼ã‚¹ã‚’編集ã—ã¾ã™ã€‚"
msgid "Edit title and description"
msgstr "タイトルã¨èª¬æ˜Žã‚’編集"
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12544,11 +12640,8 @@ msgstr "匿å化データコレクション機能ã®æœ‰åŠ¹åŒ–ã¾ãŸã¯ç„¡åŠ¹åŒ–
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr "ä¿è­·ã•ã‚ŒãŸãƒ‘スã®ãƒ¬ãƒ¼ãƒˆåˆ¶é™ã‚’有効ã«ã™ã‚‹"
-
-msgid "Enable proxy"
-msgstr "プロキシを有効ã«ã™ã‚‹"
+msgid "Enable rate limiting for POST requests to the specified paths"
+msgstr ""
msgid "Enable reCAPTCHA"
msgstr ""
@@ -12673,7 +12766,10 @@ msgstr "数値ã®å…¥åŠ›"
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12728,7 +12824,8 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr "環境"
+msgid_plural "Environments"
+msgstr[0] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12829,7 +12926,7 @@ msgstr "環境ã®åœæ­¢ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦
msgid "Environments|Are you sure you want to stop this environment?"
msgstr "ã“ã®ç’°å¢ƒã‚’åœæ­¢ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13129,6 +13226,9 @@ msgstr "エピックã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼"
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr "æ–°ã—ã„イテレーションã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -13306,6 +13406,9 @@ msgstr "Akismet ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚詳細ã«ã¤ã„ã¦ã¯ãƒ­ã‚°ã
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13601,9 +13704,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr "例: @sub\\.company\\.com$"
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr "例: Usage = å˜ä¸€ã‚¯ã‚¨ãƒªã€‚ (Requested) / (Capacity) = å¼ã‚’構æˆã™ã‚‹è¤‡æ•°ã‚¯ã‚¨ãƒªã€‚"
-
msgid "Except policy:"
msgstr "除外ãƒãƒªã‚·ãƒ¼:"
@@ -13685,6 +13785,9 @@ msgstr "有効期é™"
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr "有効期é™åˆ‡ã‚Œ"
@@ -13700,6 +13803,9 @@ msgstr "有効期é™"
msgid "Expires in %{expires_at}"
msgstr "%{expires_at} ã§æœŸé™åˆ‡ã‚Œ"
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr "有効期é™:"
@@ -13727,9 +13833,6 @@ msgstr "公開グループを検索"
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13742,6 +13845,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ"
@@ -13826,6 +13935,10 @@ msgstr "Zoom ミーティングã®è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "Failed to apply commands."
msgstr "コマンドã®é©ç”¨ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr "ユーザãŒè¦‹ã¤ã‹ã‚‰ãªã„ãŸã‚ã€ãƒ¬ãƒ“ュアーを割り当ã¦ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -14060,9 +14173,6 @@ msgstr "アップグレードã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
msgid "Failed to upload object map file"
msgstr "オブジェクトマップファイルをアップロードã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr "失敗"
@@ -14253,6 +14363,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr "削除"
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14503,6 +14616,9 @@ msgstr "完了"
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr "最åˆã«è¦‹ãŸ"
@@ -14734,6 +14850,9 @@ msgstr ".gitlab-ci.yml ã«ã‚¨ãƒ©ãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14794,6 +14913,9 @@ msgstr "全般設定"
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr "åˆæœŸè¨­å®šãƒ©ãƒ™ãƒ«ã‚»ãƒƒãƒˆã‚’生æˆã™ã‚‹"
@@ -15370,6 +15492,9 @@ msgstr ""
msgid "GitLab commit"
msgstr "GitLab ã®ã‚³ãƒŸãƒƒãƒˆ"
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15409,6 +15534,9 @@ msgstr "GitLab メタデータ URL"
msgid "GitLab project export"
msgstr "GitLab プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ"
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15424,9 +15552,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "Gitlabã¯ã€ã‚ãªãŸãŒè¨­å®šã—ãŸã‚ªãƒ–ジェクトストレージディレクトリã«ã‚¢ãƒƒãƒ—ロードã™ã‚‹ Gitlabデータベースã®åŒ¿å化ã—ãŸCSVを生æˆã™ã‚‹ã‚¸ãƒ§ãƒ–ã‚’ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§å®Ÿè¡Œã—ã¾ã™ã€‚"
-
msgid "GitLab.com"
msgstr ""
@@ -15496,11 +15621,11 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr "%{domain} ã® Let's Encrypt 証明書をå–å¾—ã™ã‚‹éš›ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†è©¦è¡Œã™ã‚‹ã«ã¯ã€ %{link_start} ドメインã®è©³ç´° %{link_end} ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ãã ã•ã„。"
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
-msgstr "ドメインã¨è¨¼æ˜Žæ›¸ã®ã‚µãƒãƒ¼ãƒˆãŒç„¡åŠ¹ã§ã™ã€‚有効ã«ã™ã‚‹ã«ã¯ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。"
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
-msgstr "デプロイã—ãŸé™çš„コンテンツã®å…¨ã‚µã‚¤ã‚ºã¯ã“ã®ã‚µã‚¤ã‚ºä»¥ä¸‹ã«åˆ¶é™ã•ã‚Œã¾ã™ã€‚無制é™ã®å ´åˆã¯0を指定ã—ã¦ãã ã•ã„。グローãƒãƒ«å€¤ã‚’継承ã™ã‚‹å ´åˆã¯ç©ºã®ã¾ã¾ã«ã—ã¾ã™ã€‚"
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgstr ""
msgid "GitLabPages|Unverified"
msgstr "未確èª"
@@ -15547,6 +15672,9 @@ msgstr "Gitea インãƒãƒ¼ãƒˆ"
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -15856,6 +15984,9 @@ msgstr "グループアãƒã‚¿ãƒ¼"
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr "グループã®èª¬æ˜Ž(ä»»æ„)"
@@ -16024,12 +16155,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "エピックã®èª­ã¿è¾¼ã¿ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -16258,7 +16383,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16321,9 +16446,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16426,7 +16557,7 @@ msgstr "グループã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "グループメンãƒãƒ¼ã®æ¨©é™ç®¡ç†ã€ãŠã‚ˆã³ã‚°ãƒ«ãƒ¼ãƒ—内ã®å„プロジェクトã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©é™ã‚’管ç†ã§ãã¾ã™ã€‚"
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16555,6 +16686,9 @@ msgstr "ヘッダーメッセージ"
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16639,8 +16773,8 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
-msgstr "ä¿è­·ã•ã‚ŒãŸãƒ‘スã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆé‡ã‚’減らã™ã®ã«å½¹ç«‹ã¡ã¾ã™"
+msgid "Helps reduce request volume for protected paths."
+msgstr ""
msgid "Here you will find recent merge request activity"
msgstr ""
@@ -16698,9 +16832,6 @@ msgstr "éžè¡¨ç¤º"
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr "å„rawパスã®1分ã‚ãŸã‚Šã®æœ€å¤§ãƒªã‚¯ã‚¨ã‚¹ãƒˆæ•°ã€‚デフォルトã¯300ã§ã™ã€‚スロットルを無効ã«ã™ã‚‹ã«ã¯0ã«è¨­å®šã—ã¾ã™ã€‚"
-
msgid "Highest role:"
msgstr "最高ä½:"
@@ -16722,6 +16853,9 @@ msgstr "履歴"
msgid "History of authentications"
msgstr "èªè¨¼å±¥æ­´"
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16746,6 +16880,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ング"
@@ -16758,6 +16895,9 @@ msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã€ãƒ‘スã€è»¢é€ã€å‰Šé™¤
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17325,6 +17465,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17385,6 +17528,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17439,6 +17585,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17457,6 +17606,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -17970,6 +18128,9 @@ msgstr "継承ã•ã‚Œã¾ã—ãŸï¼š"
msgid "Inline"
msgstr "インライン"
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr "ホストキーã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«å…¥åŠ›"
@@ -18070,6 +18231,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18109,6 +18273,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18292,6 +18459,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr "内部URL(オプション)"
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr "内部ユーザー"
@@ -18367,9 +18537,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr "無効ãªã‚¯ã‚¨ãƒªãƒ¼"
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18469,6 +18636,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18487,6 +18660,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18502,6 +18678,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18535,6 +18714,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19060,6 +19242,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19153,19 +19338,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19507,6 +19692,12 @@ msgstr "ソースブランãƒ:"
msgid "Join Zoom meeting"
msgstr "Zoom ミーティングã«å‚加ã™ã‚‹"
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19760,12 +19951,18 @@ msgstr "最終アクセス"
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "最新パイプライン"
msgid "Last Seen"
msgstr "最終閲覧"
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -19934,6 +20131,9 @@ msgstr "クラスターã¸ã®ãƒ‡ãƒ—ロイã®è©³ç´°ã«ã¤ã„ã¦"
msgid "Learn more about group-level project templates"
msgstr "グループレベルプロジェクトテンプレートã®è©³ç´°"
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20550,6 +20750,9 @@ msgstr "ã“ã‚Œã¯å¿…ãšä¿å­˜ã—ã¦ãã ã•ã„。二度ã¨ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾
msgid "Makes this issue confidential."
msgstr "イシューをéžå…¬é–‹ã«ã™ã‚‹ã€‚"
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20679,6 +20882,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20766,9 +20972,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -20892,6 +21095,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr "%{name} ã®ä¸Šé™(%{count})を超ãˆã¾ã—ãŸ"
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr "コメント数ãŒä¸Šé™ã«é”ã—ã¾ã—ãŸã€‚"
@@ -20901,6 +21107,9 @@ msgstr "åŒæ™‚ã«åŒæœŸã§ãるミラーã®æœ€å¤§æ•°ã€‚"
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21162,6 +21371,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21207,6 +21419,9 @@ msgstr "マージリクエストã®ä¾å­˜é–¢ä¿‚"
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21279,6 +21494,15 @@ msgstr "パイプライン"
msgid "MergeRequestAnalytics|Time to merge"
msgstr "マージã¾ã§ã®æ™‚é–“"
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr "%{selectStart} ã‹ã‚‰ %{selectEnd} ã¾ã§ %{end} ã®è¡Œã¸ã®ã‚³ãƒ¡ãƒ³ãƒˆ"
@@ -21435,34 +21659,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr "メトリクスã¨ãƒ—ロファイリング"
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr "アノテーションã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ã¨ç’°å¢ƒã®ä¸¡æ–¹ã§åŒæ™‚ã«æ‰€å±žã§ãã¾ã›ã‚“"
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr "アノテーションãŒå‰Šé™¤ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
-msgstr "アノテーションã¯ã€ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ã¨ç’°å¢ƒã®ã©ã¡ã‚‰ã‹ã«æ‰€å±žã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
-msgstr "è¦æ±‚ã•ã‚ŒãŸãƒ‘スをæŒã¤ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
-msgstr "é¸æŠžã—ãŸã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ã®ãŸã‚ã®ã‚¢ãƒŽãƒ†ãƒ¼ã‚·ãƒ§ãƒ³ã‚’作æˆã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
-msgstr "é¸æŠžã—ãŸç’°å¢ƒã®ã‚¢ãƒŽãƒ†ãƒ¼ã‚·ãƒ§ãƒ³ã‚’作æˆã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
-msgstr "ã“ã®ã‚¢ãƒŽãƒ†ãƒ¼ã‚·ãƒ§ãƒ³ã‚’削除ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21489,6 +21707,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21580,9 +21804,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr "é¡žä¼¼ã®ãƒ¡ãƒˆãƒªã‚¯ã‚¹ã‚’グループ化"
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21718,9 +21939,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr "Y軸ラベル"
@@ -22166,6 +22384,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr "自分ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³"
@@ -22281,6 +22502,9 @@ msgstr ""
msgid "Network"
msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯"
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22347,9 +22571,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22657,6 +22878,9 @@ msgstr "æ–°è¦ã‚¿ã‚°"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr "æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’外部ユーザーã«è¨­å®š"
@@ -22771,7 +22995,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22786,6 +23010,9 @@ msgstr "貢献ãªã—"
msgid "No contributions were found"
msgstr "貢献ãŒã¿ã¤ã‹ã‚Šã¾ã›ã‚“。"
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr "クレジット カードã¯å¿…è¦ã‚ã‚Šã¾ã›ã‚“"
@@ -22981,6 +23208,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr "脆弱性ã¯ç™ºè¦‹ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚"
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr "ウェブフックãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚上記ã®ãƒ•ã‚©ãƒ¼ãƒ ã«ã‚¦ã‚§ãƒ–フックを追加ã—ã¦ãã ã•ã„。"
@@ -23036,9 +23266,6 @@ msgstr "プライベートプロジェクトã§ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“"
msgid "Not available for protected branches"
msgstr "ä¿è­·ãƒ–ランãƒã§ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr "機密ã§ã¯ãªã„"
@@ -23268,18 +23495,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr "コミットã”ã¨ã®LOCæ•°"
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr "1回ã®ãƒ—ッシュã§ã®å¤‰æ›´ï¼ˆãƒ–ランãƒã¾ãŸã¯ã‚¿ã‚°ï¼‰ã®æ•°ã€‚å˜ä¸€ã®ãƒ—ッシュイベントã¾ãŸã¯ãƒãƒ«ã‚¯ãƒ—ッシュイベントã®ã©ã¡ã‚‰ã‚’作æˆã™ã‚‹ã‹ã‚’決定ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã—ã¾ã™ã€‚ã“ã®å€¤ã‚’超ãˆã‚‹ã¨ãƒãƒ«ã‚¯ãƒ—ッシュイベントを作æˆã—ã¾ã™ã€‚"
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr "1回ã®ãƒ—ッシュã§ã®å¤‰æ›´ï¼ˆãƒ–ランãƒã¾ãŸã¯ã‚¿ã‚°ï¼‰ã®æ•°ã€‚Webhook ãŠã‚ˆã³ã‚µãƒ¼ãƒ“スãŒèµ·å‹•ã•ã‚Œã‚‹ã‹ã©ã†ã‹ã‚’決定ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã—ã¾ã™ã€‚ ã“ã®å€¤ã‚’超ãˆã‚‹ã¨ Webhook やサービスã«é€ä¿¡ã•ã‚Œã¾ã›ã‚“。"
-
msgid "Number of commits"
msgstr "コミット数"
msgid "Number of commits per MR"
msgstr "MRã‚ãŸã‚Šã®ã‚³ãƒŸãƒƒãƒˆæ•°"
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23331,9 +23555,6 @@ msgstr "å¤ã„é †"
msgid "OmniAuth"
msgstr "OmniAuth"
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23535,6 +23756,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr "æ–°è¦ã‚ªãƒ³ãƒ‡ãƒžãƒ³ãƒ‰DASTスキャン"
@@ -23547,6 +23771,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr "オンデマンドスキャン"
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr "オンデマンドスキャン㯠DevOps ã®ã‚µã‚¤ã‚¯ãƒ«å¤–ã§å®Ÿè¡Œã•ã‚Œã€ãƒ—ロジェクトã®è„†å¼±æ€§ã‚’見ã¤ã‘ã¾ã™ã€‚%{learnMoreLinkStart}詳細を表示%{learnMoreLinkEnd}"
@@ -23559,6 +23789,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23574,6 +23807,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23686,15 +23922,15 @@ msgstr "é¸æŠžæ¸ˆã¿ã®ã‚‚ã®ã‚’é–‹ã"
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr "コメントタイプドロップダウンを開ã"
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr "エラーを開ã"
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23743,9 +23979,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr "æ“作ãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸã€‚ pod log ã® %{pod_name} ã§è©³ç´°ã‚’確èªã—ã¦ãã ã•ã„。"
-msgid "Operations"
-msgstr "オペレーション"
-
msgid "Operations Dashboard"
msgstr "オペレーションダッシュボード"
@@ -23773,6 +24006,9 @@ msgstr "オプション"
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "オプションã¨ã—ã¦ã€ã‚ãªãŸã¯ã€%{link_to_customize} 㧠FogBugz ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼åã‚’ GitLab ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ãã¾ã™ã€‚"
@@ -23782,6 +24018,9 @@ msgstr "オプション"
msgid "Or you can choose one of the suggested colors below"
msgstr "ã¾ãŸã¯ã€ä¸‹è¨˜ã®ã„ãšã‚Œã‹ã®è‰²ã‚’é¸æŠžã§ãã¾ã™"
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -23851,6 +24090,36 @@ msgstr ""
msgid "Owner"
msgstr "オーナー"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr "パッケージレジストリ"
@@ -23926,9 +24195,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24109,14 +24375,15 @@ msgstr "NuGet コマンド"
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24160,9 +24427,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24421,6 +24685,9 @@ msgstr "パス:"
msgid "Paths can contain wildcards, like */welcome"
msgstr "パスã«ã¯ã€*/welcomeã®ã‚ˆã†ãªãƒ¯ã‚¤ãƒ«ãƒ‰ã‚«ãƒ¼ãƒ‰ã‚’å«ã‚ã‚‹ã“ã¨ãŒã§ãã¾ã™"
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr "åœæ­¢"
@@ -24442,6 +24709,9 @@ msgstr "ä¿ç•™ä¸­"
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -24949,6 +25219,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "パイプラインã¯ç¾åœ¨ã‚ã‚Šã¾ã›ã‚“。"
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "パイプラインをフェッãƒã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã—ã°ã‚‰ãã—ã¦ã‹ã‚‰ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ã„ãŸã ãã‹ã€ã‚µãƒãƒ¼ãƒˆãƒãƒ¼ãƒ ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。"
@@ -25069,6 +25342,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr "マージçµæžœãƒ‘イプライン"
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25186,6 +25462,9 @@ msgstr "テキスト差分"
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25288,9 +25567,15 @@ msgstr "有効ãªæ•°å€¤ã‚’入力ã—ã¦ãã ã•ã„"
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚ã‹ã‚Šã‚„ã™ã„åå‰ã‚’記入ã—ã¦ãã ã•ã„。"
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25435,6 +25720,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25711,12 +25999,18 @@ msgstr "プロフィール"
msgid "Profile Settings"
msgstr "プロファイルã®è¨­å®š"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr "オン"
@@ -25726,9 +26020,6 @@ msgstr "ã‚ãªãŸã¯ %{yourAccount} ã¨ã€ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ãƒªãƒ³ã‚
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr "ユーザåã‚’ %{currentUsernameBold} ã‹ã‚‰ %{newUsernameBold} ã«å¤‰æ›´ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚プロファイルã¨ãƒ—ロジェクト㯠%{newUsername} åå‰ç©ºé–“ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã•ã‚Œã¾ã™ã€‚ã—ã‹ã—〠%{currentUsername} åå‰ç©ºé–“ãŒåˆ¥ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚ˆã£ã¦ç™»éŒ²ã•ã‚Œã‚‹ã¨ã€ã“ã®ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã¯æœŸé™åˆ‡ã‚Œã«ãªã‚Šã¾ã™ã€‚ Gitリãƒã‚¸ãƒˆãƒªã®ãƒªãƒ¢ãƒ¼ãƒˆã‚’ã§ãã‚‹ã ã‘æ—©ãæ›´æ–°ã—ã¦ãã ã•ã„。"
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25756,6 +26047,9 @@ msgstr "ステータス絵文字を追加"
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚¯ãƒ­ãƒƒãƒ‘ー"
@@ -26047,6 +26341,9 @@ msgstr "ã“ã“ã«ã‚ãªãŸã®ã‚¢ãƒã‚¿ãƒ¼ã‚’アップロードã™ã‚‹ã‹ã€ %{gra
msgid "Profiles|You don't have access to delete this user."
msgstr "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’削除ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26347,6 +26644,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26362,6 +26662,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26545,6 +26848,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "内部"
@@ -26557,6 +26863,9 @@ msgstr "イシュー"
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26734,6 +27043,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26824,6 +27136,9 @@ msgstr "Spring"
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
@@ -26905,6 +27220,9 @@ msgstr "ã“ã®æ©Ÿèƒ½ã«ã¯ãƒ–ラウザー㫠localStorage サãƒãƒ¼ãƒˆãŒå¿…è¦ã
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr "ã“ã®ãƒ—ロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã®ã‚¯ãƒ­ãƒ¼ãƒ³ã‚’ã™ãã«ä½œæˆã§ãã¾ã™ã€‚既存ã®ãƒªãƒã‚¸ãƒˆãƒªã‚’プッシュã™ã‚‹å ´åˆã¯ã€ã“れをスキップã—ã¦ãã ã•ã„。"
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26932,6 +27250,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr "説明フォーマット"
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr "インãƒãƒ¼ãƒˆ"
@@ -26947,6 +27268,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr "利用å¯èƒ½ãªã‚¤ãƒ³ãƒãƒ¼ãƒˆã‚ªãƒ—ションã¯ã‚ã‚Šã¾ã›ã‚“"
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "プロジェクトã®èª¬æ˜Ž%{tag_start}(オプション)%{tag_end}"
@@ -26962,54 +27286,9 @@ msgstr "åŒã˜åå‰ç©ºé–“ã®ä¸‹ã«ã„ãã¤ã‹ã®ä¾å­˜ãƒ—ロジェクトをåŽ
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr "%{count} 件ã®ã‚¢ãƒ©ãƒ¼ãƒˆãŒé©ç”¨ã•ã‚Œã¾ã—ãŸ"
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr "アラートを追加"
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr "アラートã®ç·¨é›†"
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr "アラート作æˆã®ã‚¨ãƒ©ãƒ¼"
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr "アラートã®å‰Šé™¤ã®ã‚¨ãƒ©ãƒ¼"
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr "アラートå–å¾—ã®ã‚¨ãƒ©ãƒ¼"
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr "アラートä¿å­˜ã®ã‚¨ãƒ©ãƒ¼"
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr "オペレータ"
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr "クエリをé¸æŠž"
-
-msgid "PrometheusAlerts|Threshold"
-msgstr "ã—ãã„値"
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27313,9 +27592,6 @@ msgstr "ä¿è­·ãƒ–ランãƒ"
msgid "Protected Environment"
msgstr "ä¿è­·ç’°å¢ƒ"
-msgid "Protected Paths"
-msgstr "ä¿è­·æ¸ˆã¿ã®ãƒ‘ス"
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27331,6 +27607,9 @@ msgstr "ä¿è­·ãƒ–ランãƒ"
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27469,6 +27748,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr "プロãƒã‚¤ãƒ€ãƒ¼"
@@ -27481,6 +27763,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr "匿å化データã®åŽé›†"
@@ -27667,9 +27952,6 @@ msgstr "クエリ"
msgid "Query cannot be processed"
msgstr "クエリーを処ç†ã§ãã¾ã›ã‚“"
-msgid "Query is valid"
-msgstr "クエリーã¯æœ‰åŠ¹ã§ã™"
-
msgid "Queued"
msgstr "キュー済"
@@ -27703,6 +27985,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27790,15 +28075,15 @@ msgstr ""
msgid "Recent"
msgstr "最近"
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr "最近ã®ãƒ—ロジェクトアクティビティ"
msgid "Recent Searches Service is unavailable"
msgstr "最近ã®æ¤œç´¢ã‚µãƒ¼ãƒ“スã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28278,6 +28563,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28606,6 +28894,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr "é¸æŠž"
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "アクセス権é™ã‚’リクエストã™ã‚‹"
@@ -28615,9 +28906,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr "必須パラメーター %{param} ãŒã‚ã‚Šã¾ã›ã‚“。"
@@ -28696,13 +28984,13 @@ msgstr "è¦æ±‚事項"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] "%{names} ã‹ã‚‰ã® %{count} 件以上ã®æ‰¿èªãŒå¿…è¦ã§ã™ã€‚"
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
+msgstr[0] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
-msgstr[0] "もㆠ%d 件ã®æ‰¿èªãŒå¿…è¦ã§ã™ã€‚"
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
+msgstr[0] ""
msgid "Requires values to meet regular expression requirements."
msgstr "æ­£è¦è¡¨ç¾ã®æ¡ä»¶ã‚’満ãŸã™å€¤ãŒå¿…è¦ã§ã™ã€‚"
@@ -29045,9 +29333,6 @@ msgstr "Runner"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr "ç¾åœ¨ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã®Runner: %{active_runners_count}"
@@ -29072,6 +29357,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29081,6 +29375,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29132,6 +29429,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29153,6 +29453,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29192,6 +29510,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29255,6 +29576,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "共有ランナーパイプラインã®%{quotaLimit} ã®ã†ã¡%{quotaUsed} を使用ã—ã¾ã—ãŸã€‚"
@@ -29285,15 +29609,6 @@ msgstr "稼åƒä¸­"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "ç¾åœ¨ã®ãƒªãƒã‚¸ãƒˆãƒªå†…ã§ã€ãƒ•ã‚¡ã‚¤ãƒ«ãƒªãƒ“ジョンã®åœ§ç¸®ã‚„アクセスä¸å¯èƒ½ãªã‚ªãƒ–ジェクトã®é™¤åŽ»ã¨ã„ã£ãŸã€ã„ãã¤ã‹ã®ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングを実行ã—ã¾ã™ã€‚"
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29390,9 +29705,6 @@ msgstr ""
msgid "Save Changes"
msgstr "変更をä¿å­˜"
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr "アプリケーションã®ä¿å­˜"
@@ -29710,6 +30022,9 @@ msgstr[0] "Wikiã®çµæžœ"
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -29935,16 +30250,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -29995,6 +30313,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30013,6 +30334,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30082,6 +30406,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr "イシューを作æˆã™ã‚‹"
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30103,9 +30430,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30139,6 +30463,15 @@ msgstr "ダッシュボードã®è¨­å®šã®è©³ç´°"
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30148,6 +30481,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30178,6 +30514,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30301,6 +30640,9 @@ msgstr "ã“ã®ãƒ¬ãƒãƒ¼ãƒˆã‚’表示ã™ã‚‹ã«ã¯ã€æ‰¿èªã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30340,12 +30682,12 @@ msgstr "ページを変更"
msgid "Select a branch"
msgstr ""
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "å·¦å´ã®ã‚µã‚¤ãƒ‰ãƒãƒ¼ã‹ã‚‰ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ç·¨é›†ã‚’開始ã—ã¾ã™ã€‚ãã®å¾Œã€å¤‰æ›´ã‚’コミットã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
-msgstr ""
-
msgid "Select a group to invite"
msgstr "招待ã™ã‚‹ãŸã‚ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠžã™ã‚‹"
@@ -30361,15 +30703,9 @@ msgstr "æ–°ã—ã„åå‰ç©ºé–“ã‚’é¸æŠž"
msgid "Select a project"
msgstr "プロジェクトã®é¸æŠž"
-msgid "Select a project to read Insights configuration file"
-msgstr "インサイト設定ファイルを読むプロジェクトをé¸æŠžã—ã¦ãã ã•ã„"
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr "リãƒã‚¸ãƒˆãƒªã‚’é¸æŠž"
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30628,9 +30964,6 @@ msgstr "サーãƒãƒ¼ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³"
msgid "Serverless"
msgstr "Serverless"
-msgid "Serverless domain"
-msgstr "Severlessドメイン"
-
msgid "Serverless platform"
msgstr ""
@@ -30730,9 +31063,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30787,9 +31117,6 @@ msgstr "%{protocol} プロコトル経由ã§ãƒ—ルã€ãƒ—ッシュã™ã‚‹ãŸã‚ã«
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -30880,9 +31207,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -30916,12 +31240,12 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "パスワードを設定"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr "ステータス絵文字ã®è¿½åŠ "
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "SetStatusModal|Busy"
msgstr ""
@@ -30985,6 +31309,10 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31326,9 +31654,6 @@ msgstr "é¡žä¼¼ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr "å˜ä¸€ã¾ãŸã¯è¤‡åˆã®ã‚¯ã‚¨ãƒªãƒ¼"
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31395,6 +31720,9 @@ msgstr "スマートカード"
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "スマートカードèªè¨¼ã«å¤±æ•—:クライアント証明書ヘッダーãŒã‚ã‚Šã¾ã›ã‚“。"
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "スニペット"
@@ -31419,6 +31747,9 @@ msgstr "コードスニペットã¨ãƒ†ã‚­ã‚¹ãƒˆã‚’ä¿å­˜ã€å…±æœ‰ã€åŸ‹ã‚è¾¼ã¿
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "表示ã™ã‚‹ã‚¹ãƒ‹ãƒšãƒƒãƒˆã¯ã‚ã‚Šã¾ã›ã‚“。"
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31428,6 +31759,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr "説明(オプション)"
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31452,9 +31786,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr "誰ã‹ãŒåŒæ™‚ã«ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’編集ã—ã¾ã—ãŸã€‚%{linkStart} イシュー %{linkEnd} を確èªã—ã¦ã€å¤‰æ›´ç‚¹ãŒæ„図ã›ãšå‰Šé™¤ã•ã‚Œãªã„よã†ã«æ°—ã‚’ã¤ã‘ã¦ãã ã•ã„。"
@@ -32049,12 +32380,6 @@ msgstr "検索開始"
msgid "Start thread"
msgstr "スレッドを開始ã—ã¾ã™ã€‚"
-msgid "Start thread & close %{noteable_name}"
-msgstr "スレッドã®é–‹å§‹ã¨ã‚¯ãƒ­ãƒ¼ã‚º %{noteable_name}"
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr "スレッドã®é–‹å§‹ã¨ %{noteable_name} ã®å†é–‹"
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32094,6 +32419,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "メッセージを有効ã«ã™ã‚‹"
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr "é™çš„アプリケーションセキュリティテスト (SAST)"
@@ -32592,7 +32920,7 @@ msgstr "正常ã«ãƒ­ãƒƒã‚¯ãŒè§£é™¤ã•ã‚Œã¾ã—ãŸ"
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32691,18 +33019,12 @@ msgstr ""
msgid "Sunday"
msgstr "日曜日"
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32724,9 +33046,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32739,12 +33058,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32760,30 +33073,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -32811,9 +33109,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -32826,9 +33121,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -32871,6 +33163,9 @@ msgstr "サãƒãƒ¼ãƒˆãƒšãƒ¼ã‚¸URL"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33057,6 +33352,9 @@ msgstr "ã‚¿ã‚°ã¯ã€å±¥æ­´ã®ç‰¹å®šã®ä½ç½®ã‚’é‡è¦ãªã‚‚ã®ã¨ã—ã¦ãƒžãƒ¼ã‚¯
msgid "TagsPage|This tag has no release notes."
msgstr "ã“ã®ã‚¿ã‚°ã«ã¯ãƒªãƒªãƒ¼ã‚¹ãƒŽãƒ¼ãƒˆãŒã‚ã‚Šã¾ã›ã‚“。"
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "æ–°ã—ã„タグを追加ã™ã‚‹ã«ã¯ git tag コマンドを使用ã—ã¾ã™:"
@@ -33081,6 +33379,15 @@ msgstr "ターゲットブランãƒ"
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "ãƒãƒ¼ãƒ "
@@ -33093,6 +33400,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33461,6 +33771,9 @@ msgstr[0] "%{type} ã«æ¬¡ã®ã‚¨ãƒ©ãƒ¼ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚"
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33530,6 +33843,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "コãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ %{timeout} ã§ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã™ã€‚タイムアウトã™ã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ã¯ã€clone/push を組ã¿åˆã‚ã›ã¦ä½¿ç”¨ã—ã¦ãã ã•ã„。"
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã¯UTF-8ã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚Œã¦ã„ã¾ã›ã‚“。編集ã¯Gitリãƒã‚¸ãƒˆãƒªã‚’介ã—ã¦è¡Œã£ã¦ãã ã•ã„。"
@@ -33560,9 +33876,6 @@ msgstr "ä¾å­˜é–¢ä¿‚リストã«ã¯ãƒ—ロジェクト内ã§ä½¿ç”¨ã•ã‚Œã¦ã„ã‚‹
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "ã“ã®ã‚¸ãƒ§ãƒ–ã® %{environmentLink} ã¸ã®ãƒ‡ãƒ—ロイã¯æˆåŠŸã—ã¾ã›ã‚“ã§ã—ãŸã€‚"
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr "ディレクトリã®ä½œæˆã«æˆåŠŸã—ã¾ã—ãŸ"
@@ -33630,6 +33943,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr "グローãƒãƒ«è¨­å®šã§ã¯ã€è‡ªåˆ†ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«å¯¾ã—ã¦2è¦ç´ èªè¨¼ã‚’有効ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -33714,6 +34030,9 @@ msgstr "ライセンスã¯æ­£å¸¸ã«ã‚¢ãƒƒãƒ—ロードã•ã‚Œã€ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã«
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr "許å¯ã•ã‚Œã‚‹æœ€å¤§ãƒ•ã‚¡ã‚¤ãƒ«ã‚µã‚¤ã‚ºã¯ %{size} ã§ã™ã€‚"
@@ -33819,9 +34138,6 @@ msgstr "プロジェクトã¯æ­£å¸¸ã«ãƒ•ã‚©ãƒ¼ã‚¯ã•ã‚Œã¾ã—ãŸã€‚"
msgid "The project was successfully imported."
msgstr "プロジェクトを正常ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ãã¾ã—ãŸã€‚"
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "匿å化データコレクションã¯ç„¡åŠ¹ã§ã™ã€‚有効ã«ã—ãŸã¨ãã€GitLab ã¯ã€ã‚ãªãŸãŒè¨­å®šã—ãŸã‚ªãƒ–ジェクトストレージディレクトリã«ã‚¢ãƒƒãƒ—ロードã™ã‚‹ GitLab データベースã®åŒ¿å化ã—㟠CSV を生æˆã™ã‚‹ã‚¸ãƒ§ãƒ–ã‚’ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§å®Ÿè¡Œã—ã¾ã™ã€‚"
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -33855,9 +34171,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr "スケジュールã®æ™‚é–“ã¯ç¾åœ¨ä»¥é™ã®æ—¥æ™‚ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“"
-
msgid "The snippet can be accessed without any authentication."
msgstr "ã“ã®ã‚¹ãƒ‹ãƒšãƒƒãƒˆã¯èªè¨¼ç„¡ã—ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™"
@@ -34017,6 +34330,9 @@ msgstr "ã¾ã ãƒ‘ッケージãŒã‚ã‚Šã¾ã›ã‚“。"
msgid "There are no projects shared with this group yet"
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¨å…±æœ‰ã—ã¦ã„るプロジェクトã¯ã‚ã‚Šã¾ã›ã‚“"
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34101,6 +34417,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34287,9 +34606,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr "既存ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã«åŒæ§˜ã®ã‚¿ã‚¤ãƒˆãƒ«ãŒã‚ã‚Šã¾ã™ã€‚別ã®ä¼¼ãŸã‚ˆã†ãªã‚¤ã‚·ãƒ¥ãƒ¼ã‚’作æˆã™ã‚‹ã‚ˆã‚Šã€ãã“ã«ã‚³ãƒ¡ãƒ³ãƒˆã™ã‚‹æ–¹ãŒè‰¯ã„ã§ã™ã€‚"
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34512,7 +34828,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -34815,6 +35131,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr "ã“ã®å¤‰æ•°ã¯ãƒžã‚¹ã‚¯ã§ãã¾ã›ã‚“."
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr "外部ã®ã‚µã‚¤ãƒ³ã‚¤ãƒ³ãƒšãƒ¼ã‚¸ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã—ã¾ã™ã€‚"
@@ -34953,6 +35275,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35282,7 +35607,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35318,7 +35643,7 @@ msgstr "ã“ã®ãƒ—ロジェクトを継続ã™ã‚‹ãŸã‚ã«ã€æ–°ã—ã„イシュー
msgid "To keep this project going, create a new merge request"
msgstr "ã“ã®ãƒ—ロジェクトを継続ã™ã‚‹ã«ã¯ã€æ–°ã—ã„マージリクエストを作æˆã—ã¦ãã ã•ã„"
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35504,6 +35829,21 @@ msgstr "有効ã«ãªã£ã¦ã„るプロジェクトãŒå¤šã™ãŽã¾ã™ã€‚コンソ
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr "トピック (ä»»æ„)"
@@ -35597,8 +35937,8 @@ msgstr "グループã¯ã™ã§ã«ãƒ«ãƒ¼ãƒˆã‚°ãƒ«ãƒ¼ãƒ—ã§ã™ã€‚"
msgid "TransferGroup|Group is already associated to the parent group."
msgstr "Groupã¯ã™ã§ã«è¦ªã‚°ãƒ«ãƒ¼ãƒ—ã«é–¢é€£ä»˜ã‘ã§ãã¦ã„ã¾ã™ã€‚"
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
-msgstr "親グループã«ã¯ã€ã™ã§ã«åŒã˜ãƒ‘スをæŒã¤ã‚µãƒ–グループãŒã‚ã‚Šã¾ã™ã€‚"
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
+msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
msgstr "転é€ã«å¤±æ•—: %{error_message}"
@@ -35964,6 +36304,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr "脆弱ãªãƒ—ロジェクトã¯å–å¾—ã§ãã¾ã›ã‚“"
@@ -36048,6 +36391,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr "å…ƒã«æˆ»ã™"
@@ -36381,6 +36727,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr "追加分ã®è³¼å…¥"
@@ -36399,10 +36748,10 @@ msgstr "ç¾åœ¨ã®ä½¿ç”¨çŠ¶æ³"
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36414,6 +36763,9 @@ msgstr "LFSオブジェクト"
msgid "UsageQuota|LFS Storage"
msgstr "LFSストレージ"
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36459,9 +36811,6 @@ msgstr "ストレージ"
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36501,12 +36850,12 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr "使用率"
-msgid "UsageQuota|Usage Breakdown"
-msgstr ""
-
msgid "UsageQuota|Usage Quotas"
msgstr "割当使用率"
+msgid "UsageQuota|Usage breakdown"
+msgstr ""
+
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
msgstr "%{strong_start}%{group_name}%{strong_end} グループã®ãƒ—ロジェクト全体ã§ã®ã‚°ãƒ«ãƒ¼ãƒ—リソースã®ä½¿ç”¨çŽ‡"
@@ -36654,6 +37003,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36684,6 +37036,9 @@ msgstr ""
msgid "Use template"
msgstr "テンプレートを使用"
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36750,6 +37105,12 @@ msgstr "ユーザー設定"
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37101,6 +37462,9 @@ msgstr "æš—å·åŒ–フィールドãŒãªã„å ´åˆã€å¿…è¦ãªæš—å·åŒ–戦略を使
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr "検証"
@@ -37110,6 +37474,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr "GitLab CI構æˆãƒ•ã‚¡ã‚¤ãƒ«ã‚’検証"
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr "検証ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
@@ -37155,10 +37528,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr "イシューã®ä½œæˆã‹ã‚‰ã‚¯ãƒ­ãƒ¼ã‚ºã¾ã§ã®æ™‚é–“ã®ä¸­å¤®å€¤ã€‚"
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -37815,6 +38200,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38010,6 +38398,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr "What's new"
@@ -38019,9 +38410,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Runner ãŒãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹å ´åˆã€ä»–ã®ãƒ—ロジェクトã«å‰²ã‚Šå½“ã¦ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“"
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38034,6 +38422,9 @@ msgstr "URL を空白ã®ã¾ã¾ã«ã™ã‚‹ã¨ã€ãƒ—ロジェクト間ã®æ©Ÿèƒ½ã‚’ç„
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "マージリクエストãŒæ‰¿èªã•ã‚ŒãŸã¨ã"
@@ -38041,9 +38432,6 @@ msgstr[0] "マージリクエストãŒæ‰¿èªã•ã‚ŒãŸã¨ã"
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr "日付"
@@ -38350,12 +38738,12 @@ msgstr "コメントを書ã..."
msgid "Write a description or drag your files here…"
msgstr ""
+msgid "Write a description…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "マイルストーンã®èª¬æ˜Žã‚’書ã..."
-msgid "Write to \"authorized_keys\" file"
-msgstr ""
-
msgid "Write your release notes or drag your files here…"
msgstr "リリースノートを書ãã‹ã€ã“ã“ã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ドラッグ"
@@ -38395,9 +38783,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38464,6 +38849,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr "ã“ã®æ“作を実行ã™ã‚‹æ¨©é™ã‚’ã‚‚ã£ã¦ã„ã¾ã›ã‚“。"
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38620,9 +39008,6 @@ msgstr "既存ã®ãƒ‡ã‚¶ã‚¤ãƒ³ã«ç ´æ£„ã—ãŸã¨ãã«ã‚¢ãƒƒãƒ—ロードã§ãã‚‹
msgid "You can recover this project until %{date}"
msgstr "%{date} ã¾ã§ã“ã®ãƒ—ロジェクトを復元ã§ãã¾ã™"
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "対話モードã§ã¯ã€%{use_ours} ボタンã¾ãŸã¯%{use_theirs} ボタンã§ã®é¸æŠžã¨ã€ãã®ä»–ファイルã®ç›´æŽ¥ç·¨é›†ã§ç«¶åˆã‚’解決ã§ãã¾ã™ã€‚ãã‚Œã‹ã‚‰ã“れらã®å¤‰æ›´ã‚’ %{branch_name} ã«ã‚³ãƒŸãƒƒãƒˆã—ã¾ã™ã€‚"
@@ -38722,9 +39107,6 @@ msgstr "利用å¯èƒ½ãªãƒ—ロジェクトã¯ã¾ã ã‚ã‚Šã¾ã›ã‚“"
msgid "You don't have any recent searches"
msgstr "最近ã®æ¤œç´¢ãŒã‚ã‚Šã¾ã›ã‚“。"
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr "ã“ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã‚’実行ã™ã‚‹ãŸã‚ã®å分ãªæ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“"
@@ -38812,6 +39194,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr "ã‚ãªãŸã¯ \"%{membershipable_human_name}\"%{source_type} を残ã—ã¾ã—ãŸã€‚"
@@ -38821,9 +39206,6 @@ msgstr "マイルストーンを終了ã§ãã¾ã™ã€‚"
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39275,28 +39657,55 @@ msgstr[0] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao API token"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39308,6 +39717,9 @@ msgstr "Zoom ミーティングを削除ã—ã¾ã—ãŸ"
msgid "[No reason]"
msgstr "[ç†ç”±ã¯ã‚ã‚Šã¾ã›ã‚“]"
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39320,9 +39732,6 @@ msgstr ""
msgid "a deleted user"
msgstr "削除ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
-msgid "a design"
-msgstr "デザイン"
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] "約 %d 時間"
@@ -39427,12 +39836,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39460,6 +39875,9 @@ msgstr ""
msgid "cannot be modified"
msgstr "変更ã§ãã¾ã›ã‚“"
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr "他をブロックã§ãã¾ã›ã‚“"
@@ -39475,9 +39893,6 @@ msgstr "ãれ自体をブロックã§ãã¾ã›ã‚“"
msgid "cannot merge"
msgstr "マージã§ãã¾ã›ã‚“"
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39508,6 +39923,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "他 %{remainingPackagesCount} 件"
@@ -39544,9 +39962,19 @@ msgstr "自動的ã«æ–°ã—ã„ブランãƒã«ã“ã®ãƒ‘ッãƒã‚’é©ç”¨ã™ã‚‹"
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr "ベースパイプラインã®ã‚³ãƒ¼ãƒ‰å“質アーティファクトãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39556,8 +39984,14 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
-msgstr "コードã®å“質"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
msgid "ciReport|Container Scanning"
msgstr "コンテナースキャン"
@@ -39622,6 +40056,16 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "イシューを作æˆã—ã¦ã€ã“ã®è„†å¼±æ€§ã‚’調査ã—ã¾ã™"
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39655,11 +40099,11 @@ msgstr "SAST"
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
-msgstr "シークレットスキャン"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
+msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
-msgstr "シークレットスキャンã¯ã€ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã®ç§˜å¯†ã¨èªè¨¼æƒ…å ±ã®è„†å¼±æ€§ã‚’検出ã—ã¾ã™ã€‚"
+msgid "ciReport|Secret detection"
+msgstr ""
msgid "ciReport|Security scanning"
msgstr "セキュリティスキャン"
@@ -39776,6 +40220,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr "container_name ã« %{max_length} 以上ã®æ–‡å­—列を付与ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -39831,9 +40281,6 @@ msgstr "デプロイ"
msgid "design"
msgstr "デザイン"
-msgid "designs"
-msgstr "デザイン"
-
msgid "detached"
msgstr "デタッãƒ"
@@ -39846,6 +40293,12 @@ msgstr "存在ã—ã¾ã›ã‚“"
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr "サãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã‚‹æ‹¡å¼µå­ã§ã¯ã‚ã‚Šã¾ã›ã‚“。 %{extension_list} ã®æ‹¡å¼µå­ã ã‘ãŒã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã™"
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr "ダウンロードã™ã‚‹"
@@ -39859,6 +40312,9 @@ msgstr "例 %{token}"
msgid "element is not a hierarchy"
msgstr "è¦ç´ ã¯éšŽå±¤ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr "メール '%{email}'ã¯æ¤œè¨¼æ¸ˆã¿ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
@@ -39895,6 +40351,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr "ãƒã‚¤ãƒˆæ•°ã®åˆ¶é™ (%{bytes}) を超ãˆã¦ã„ã¾ã™"
@@ -40090,6 +40549,12 @@ msgstr "ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。ç¾åœ¨ã€ãƒ—ロジェクトレベルã®
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40247,6 +40712,9 @@ msgstr "%{metricsLinkStart} メモリ %{metricsLinkEnd} 使用率㯠%{memoryFro
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40280,6 +40748,12 @@ msgstr "追加ã§æ‰¿èªã™ã‚‹"
msgid "mrWidget|Approved by"
msgstr "承èªè€…"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr "技術的ãªè² å‚µã‚„脆弱性を追加ã—ã¦ã„ã¾ã™ã‹ï¼Ÿ"
@@ -40341,6 +40815,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr "デプロイ統計を読ã¿è¾¼ã¿ä¸­"
@@ -40372,9 +40849,6 @@ msgstr "マージã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
msgid "mrWidget|Merge locally"
msgstr "ローカルã§ãƒžãƒ¼ã‚¸"
-msgid "mrWidget|Merge request approved."
-msgstr "マージリクエストãŒæ‰¿èªã•ã‚Œã¾ã—ãŸ."
-
msgid "mrWidget|Merged by"
msgstr "マージ作業者"
@@ -40489,12 +40963,6 @@ msgstr "ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¯å‰Šé™¤ã•ã‚Œã¾ã›ã‚“"
msgid "mrWidget|There are merge conflicts"
msgstr "マージã®ç«¶åˆãŒã‚ã‚Šã¾ã™"
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯è‡ªå‹•çš„ã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
@@ -40510,6 +40978,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40558,6 +41029,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40633,6 +41110,9 @@ msgstr "ã¾ãŸã¯"
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "テスト全件数 %d ã®ã†ã¡"
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index 9a175d2ea23..37572cf9c28 100644
--- a/locale/ka_GE/gitlab.po
+++ b/locale/ka_GE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ka\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/kab/gitlab.po b/locale/kab/gitlab.po
index a6908028541..b5a059f367f 100644
--- a/locale/kab/gitlab.po
+++ b/locale/kab/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: kab\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:24\n"
+"PO-Revision-Date: 2021-11-02 00:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index b190b36fa05..6d3a4f179e5 100644
--- a/locale/ko/gitlab.po
+++ b/locale/ko/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ko\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr " %{start}부터 %{end}까지"
@@ -40,23 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr " %{grace_period_deadline} ì´ì „ì— ì´ ìž‘ì—…ì„ ìˆ˜í–‰ 하셔야 합니다."
-msgid " and"
-msgstr " 그리고"
-
msgid " and "
msgstr " 그리고 "
msgid " and %{sliced}"
msgstr " 그리고 %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " %d í¬ì¸íŠ¸ 저하"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " %d í¬ì¸íŠ¸ í–¥ìƒ"
-
msgid " or "
msgstr " ë˜ëŠ” "
@@ -84,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -171,9 +163,6 @@ msgid "%d commit,"
msgid_plural "%d commits,"
msgstr[0] "%dê°œì˜ ì»¤ë°‹,"
-msgid "%d commits"
-msgstr "%dê°œì˜ ì»¤ë°‹"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -969,6 +958,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end}ì„ ì‚¬ìš©í•˜ë©´ 그룹 ë˜ëŠ” 프로ì íŠ¸ì˜ ì´ë²¤íŠ¸ì— 대한 ì‘답으로 웹 애플리케ì´ì…˜ì— ì•Œë¦¼ì„ ë³´ë‚¼ 수 있습니다. Webhook보다 %{integrations_link_start}통합%{link_end}ì„ ì‚¬ìš©í•˜ëŠ” ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤."
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1051,9 +1043,15 @@ msgstr "(ì‚­ì œë¨)"
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount}ê°œ ë” ìžˆìŒ"
@@ -1104,6 +1102,9 @@ msgstr[0] "- ì´ë²¤íŠ¸"
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- 사용ìž"
@@ -1326,9 +1327,6 @@ msgstr "빈 프로ì íŠ¸ì—서는 기본 브랜치를 ì„ íƒí•  수 없습니다
msgid "A deleted user"
msgstr "ì‚­ì œëœ ì‚¬ìš©ìž"
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1362,8 +1360,8 @@ msgstr "사ì´ë²„ í­ë ¥ ë°©ì§€íŒ€ì´ ìµœëŒ€í•œ 빨리 ê·€í•˜ì˜ ë¦¬í¬íŠ¸ë¥¼ ê²
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
-msgstr "새로운 Auto DevOps 파ì´í”„ë¼ì¸ì´ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤. %{pipelines_link_start}파ì´í”„ë¼ì¸ 페ì´ì§€%{pipelines_link_end}ë¡œ ì´ë™í•˜ì—¬ ìžì„¸ížˆ 알아보세요."
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
+msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
msgstr "새 릴리즈 %{tag}ê°€ %{name}으로 공개ë˜ì—ˆìŠµë‹ˆë‹¤. %{release_link_start}릴리즈 페ì´ì§€%{release_link_end}를 방문하여 ë” ìžì„¸ížˆ 알아보세요."
@@ -1389,6 +1387,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1737,6 +1738,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr "서비스 ë°ìŠ¤í¬ 활성화"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "활성"
@@ -1818,9 +1822,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "ì´ %{noteableDisplayName} ì— ì¼ë°˜ì ì¸ 코멘트를 추가 합니다."
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "ì´ %{noteable_name} ì— ì¼ë°˜ì ì¸ 코멘트를 추가 합니다."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "프로ì íŠ¸ì— 관한 ì •ë³´ê°€ 담긴 홈페ì´ì§€ë¥¼ wikiì— ì¶”ê°€í•˜ë©´ GitLabì´ ë©”ì‹œì§€ 대신 ì—¬ê¸°ì— í‘œì‹œ 합니다."
@@ -1899,9 +1900,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr "ì´ë©”ì¼ ì£¼ì†Œ 추가"
@@ -1995,6 +1993,9 @@ msgstr "리뷰 추가"
msgid "Add to tree"
msgstr "íŠ¸ë¦¬ì— ì¶”ê°€"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2451,7 +2452,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "관리ìž"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2466,6 +2467,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2601,7 +2608,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3216,7 +3223,7 @@ msgstr "모든 병합 충ëŒì´ í•´ê²°ë˜ì—ˆìŠµë‹ˆë‹¤. ì´ì œ 병합 ìš”ì²­ì„ ë
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3234,6 +3241,9 @@ msgstr ""
msgid "All users must have a name."
msgstr "모든 사용ìžëŠ” ì´ë¦„ì´ ìžˆì–´ì•¼í•©ë‹ˆë‹¤."
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "\"%{group_name}\"ì„ ìž…ë ¥í•˜ë©´ ë¡œê·¸ì¸ í•  수 있습니다."
@@ -3249,7 +3259,7 @@ msgstr "ëŒ€ìƒ ë¸Œëžœì¹˜ì— ë¨¸ì§€í•  수 있는 ë©¤ë²„ì˜ ì»¤ë°‹ì„ í—ˆìš©í•©ë‹
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3489,13 +3499,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3699,6 +3712,10 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "ì•Œë¦¼ì„ êµ¬ë…하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -3762,9 +3779,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4090,12 +4104,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4108,12 +4128,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4126,6 +4155,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4141,6 +4179,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4150,6 +4191,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4421,12 +4465,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr "차트 정렬"
@@ -4660,6 +4698,9 @@ msgstr "8ì›”"
msgid "Authenticate"
msgstr "ì¸ì¦"
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr "GitHubë¡œ ì¸ì¦"
@@ -5291,6 +5332,9 @@ msgstr ""
msgid "Blog"
msgstr "블로그"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5530,8 +5574,8 @@ msgstr "모ë‘"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "ì´ ë¸Œëžœì¹˜ì—ì„œ HEAD ì»¤ë°‹ì„ ì°¾ì„ ìˆ˜ ì—†ìŒ"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "비êµ"
@@ -5641,6 +5685,9 @@ msgstr "확ì¸í•˜ë ¤ë©´, %{branch_name_confirmation} 를 ìž…ë ¥ 합니다."
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "로컬 ë³€ê²½ì‚¬í•­ì„ ì·¨ì†Œí•˜ê³  업스트림 버전으로 브랜치를 ë®ì–´ì“°ë ¤ë©´ 여기서 삭제하고 '지금 ì—…ë°ì´íŠ¸'를 ì„ íƒí•˜ì„¸ìš”."
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5848,9 +5895,6 @@ msgstr "CI 린트"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6134,9 +6178,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr "ìžë™ìœ¼ë¡œ 머지할 수 없습니다."
@@ -6194,6 +6235,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6520,6 +6567,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6553,6 +6603,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6667,6 +6720,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6709,15 +6765,9 @@ msgstr "템플릿 ì„ íƒ..."
msgid "Choose a type..."
msgstr "ìœ í˜•ì„ ì„ íƒ..."
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr "아무 색ìƒì„ ì„ íƒí•´ 주세요."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr "íŒŒì¼ ì„ íƒâ€¦"
@@ -7360,7 +7410,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7801,6 +7851,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ì˜ 세부 ì •ë³´ 보기 ë° ìˆ˜ì •"
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7810,6 +7863,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7819,9 +7875,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "시스템 유형 ì„ íƒ"
@@ -7834,6 +7905,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -7984,30 +8058,6 @@ msgstr "요구 ì‚¬í•­ì„ ì¶©ì¡±"
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8146,12 +8196,6 @@ msgstr ""
msgid "Comment"
msgstr "코멘트"
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8267,6 +8311,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "비êµ"
@@ -8348,13 +8395,13 @@ msgstr "완료"
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8363,16 +8410,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8381,6 +8434,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8393,31 +8452,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8489,15 +8548,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8642,6 +8695,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "컨테ì´ë„ˆ 레지스트리"
@@ -8764,10 +8820,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -8963,7 +9019,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -8987,9 +9043,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9110,9 +9163,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr "%{protocol} í´ë¡  URL 복사"
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9182,9 +9232,6 @@ msgstr "ë§í¬ 복사"
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9269,9 +9316,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr "채팅 ë‹‰ë„¤ìž„ì„ ì¸ì¦í•˜ì§€ 못했습니다. 다시 ì‹œë„하세요!"
@@ -9377,6 +9421,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9395,6 +9442,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "새 디렉토리 만들기"
@@ -9407,9 +9457,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9425,6 +9472,9 @@ msgstr ""
msgid "Create a new issue"
msgstr "새 ì´ìŠˆ 만들기"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr "새 저장소 만들기"
@@ -9560,6 +9610,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9677,7 +9730,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9800,10 +9853,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9860,6 +9910,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -9914,6 +9967,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10073,6 +10135,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10138,6 +10203,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10631,6 +10699,9 @@ msgstr "날짜 ì„ íƒ"
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10697,6 +10768,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr "기본 분류 ë¼ë²¨"
@@ -10736,18 +10810,36 @@ msgstr "기본: FogBugz 계정 ID를 풀네임으로 매핑"
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "cron êµ¬ë¬¸ì„ ì‚¬ìš©í•˜ì—¬ ì‚¬ìš©ìž ì •ì˜ íŒ¨í„´ ì •ì˜"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Protected against pushes"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
+msgid "Define a custom pattern with cron syntax"
+msgstr "cron êµ¬ë¬¸ì„ ì‚¬ìš©í•˜ì—¬ ì‚¬ìš©ìž ì •ì˜ íŒ¨í„´ ì •ì˜"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -10820,9 +10912,6 @@ msgstr "댓글 삭제"
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10850,9 +10939,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -10880,6 +10966,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11039,13 +11128,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11054,7 +11143,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11368,7 +11469,8 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11472,6 +11574,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11487,15 +11595,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr "ë””ìžì¸"
@@ -11547,6 +11652,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11625,6 +11733,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11670,6 +11781,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11853,12 +11967,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -11950,18 +12058,6 @@ msgstr "ë„ë©”ì¸"
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -11992,9 +12088,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12220,6 +12313,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12544,10 +12640,7 @@ msgstr "Pseudonymizer ë°ì´í„° ìˆ˜ì§‘ì„ ì‚¬ìš©í•˜ê±°ë‚˜ 중지합니다."
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12673,7 +12766,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12728,7 +12824,8 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12829,7 +12926,7 @@ msgstr "í™˜ê²½ì„ ì¤‘ì§€í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„í•
msgid "Environments|Are you sure you want to stop this environment?"
msgstr "ì´ í™˜ê²½ì„ ì¤‘ë‹¨í• ê¹Œìš”?"
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13129,6 +13226,9 @@ msgstr "ì—í”½ì„ ë§Œë“œëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13306,6 +13406,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13601,9 +13704,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13685,6 +13785,9 @@ msgstr "만료ì¼"
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr "만료ë¨"
@@ -13700,6 +13803,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13727,9 +13833,6 @@ msgstr "공개 그룹 íƒìƒ‰"
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13742,6 +13845,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13826,6 +13935,10 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14060,9 +14173,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr "실패"
@@ -14253,6 +14363,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14503,6 +14616,9 @@ msgstr "완료"
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14734,6 +14850,9 @@ msgstr ".gitlab-ci.ymlì—ì„œ 오류를 발견했습니다:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14794,6 +14913,9 @@ msgstr "ì¼ë°˜ 설정"
msgid "General pipelines"
msgstr "ì¼ë°˜ 파ì´í”„ë¼ì¸"
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15370,6 +15492,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15409,6 +15534,9 @@ msgstr ""
msgid "GitLab project export"
msgstr "GitLab 프로ì íŠ¸ 내보내기"
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15424,9 +15552,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15496,10 +15621,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15547,6 +15672,9 @@ msgstr "Gitea 가져오기"
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -15856,6 +15984,9 @@ msgstr "그룹 아바타"
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr "그룹 설명 (ì„ íƒ ì‚¬í•­)"
@@ -16024,12 +16155,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16258,7 +16383,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16321,9 +16446,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16426,7 +16557,7 @@ msgstr "ê·¸ë£¹ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "그룹 구성ì›ì˜ 사용 ê¶Œí•œì„ ê´€ë¦¬í•˜ê³  ê·¸ë£¹ì˜ ê° í”„ë¡œì íŠ¸ì— ì ‘ê·¼ í•  수 있습니다."
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16555,6 +16686,9 @@ msgstr "머릿글 메시지"
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16639,7 +16773,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16698,9 +16832,6 @@ msgstr "값 숨기기"
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16722,6 +16853,9 @@ msgstr "ì´ë ¥"
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16746,6 +16880,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr "정리"
@@ -16758,6 +16895,9 @@ msgstr "정리, 내보내기, 경로, 전송, 삭제, 보관"
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17325,6 +17465,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17385,6 +17528,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17439,6 +17585,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17457,6 +17606,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -17970,6 +18128,9 @@ msgstr ""
msgid "Inline"
msgstr "ì¸ë¼ì¸"
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr "호스트 키를 수ë™ìœ¼ë¡œ ìž…ë ¥"
@@ -18070,6 +18231,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18109,6 +18273,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18292,6 +18459,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr "내부 사용ìž"
@@ -18367,9 +18537,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18469,6 +18636,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18487,6 +18660,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18502,6 +18678,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18535,6 +18714,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19060,6 +19242,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19153,19 +19338,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19507,6 +19692,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19760,12 +19951,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "최근 파ì´í”„ë¼ì¸"
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -19934,6 +20131,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20550,6 +20750,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20679,6 +20882,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20766,9 +20972,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -20892,6 +21095,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -20901,6 +21107,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21162,6 +21371,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21207,6 +21419,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21279,6 +21494,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21435,34 +21659,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21489,6 +21707,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21580,9 +21804,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21718,9 +21939,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22166,6 +22384,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22281,6 +22502,9 @@ msgstr ""
msgid "Network"
msgstr "네트워í¬"
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22347,9 +22571,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22657,6 +22878,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22771,7 +22995,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22786,6 +23010,9 @@ msgstr ""
msgid "No contributions were found"
msgstr "기여를 ì°¾ì„ ìˆ˜ 없습니다."
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr "신용 카드가 필요하지 않습니다."
@@ -22981,6 +23208,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23036,9 +23266,6 @@ msgstr "프ë¼ì´ë¹— 프로ì íŠ¸ì—는 사용할 수 없습니다."
msgid "Not available for protected branches"
msgstr "프로í…íŠ¸ëœ ë¸Œëžœì¹˜ì—는 사용할 수 없습니다."
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr "비밀 아님"
@@ -23268,18 +23495,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23331,9 +23555,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23535,6 +23756,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23547,6 +23771,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23559,6 +23789,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23574,6 +23807,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23686,15 +23922,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23743,9 +23979,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr "ìš´ì˜ìž"
-
msgid "Operations Dashboard"
msgstr "작업 대시보드"
@@ -23773,6 +24006,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23782,6 +24018,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -23851,6 +24090,36 @@ msgstr ""
msgid "Owner"
msgstr "소유ìž"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -23926,9 +24195,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24109,14 +24375,15 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24160,9 +24427,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24421,6 +24685,9 @@ msgstr "경로:"
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr "중지"
@@ -24442,6 +24709,9 @@ msgstr "대기중"
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -24949,6 +25219,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "현재 ì‹¤í–‰ì¤‘ì¸ íŒŒì´í”„ë¼ì¸ì´ 없습니다."
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25069,6 +25342,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25186,6 +25462,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25288,9 +25567,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25435,6 +25720,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25711,12 +25999,18 @@ msgstr "프로필"
msgid "Profile Settings"
msgstr "프로필 설정"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25726,9 +26020,6 @@ msgstr "%{yourAccount}를 ì˜êµ¬ì ìœ¼ë¡œ 삭제하려고 합니다. ì´ìŠˆ, 머
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr "ì‚¬ìš©ìž ì´ë¦„ì„ %{currentUsernameBold}ì—ì„œ %{newUsernameBold}으로 변경하려고 합니다. 기존 프로필과 프로ì íŠ¸ë“¤ì€ %{newUsername}으로 리디렉션ë˜ì§€ë§Œ, %{currentUsername}ê°€ 다른 유저나 ê·¸ë£¹ì— ì˜í•´ 등ë¡ë˜ë©´ ë” ì´ìƒ 리디렉션ë˜ì§€ 않습니다. ì‚¬ìš©ìž ì´ë¦„ì„ ë³€ê²½í•œ ë’¤ git ì €ìž¥ì†Œì˜ ë¦¬ëª¨íŠ¸ë¥¼ 변경하세요."
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25756,6 +26047,9 @@ msgstr "ìƒíƒœ ì´ëª¨í‹°ì½˜ 추가"
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr "아바타 ìžë¥´ê¸°"
@@ -26047,6 +26341,9 @@ msgstr "ì´ê³³ì— 아바타를 업로드하거나 %{gravatar_link}ì—ì„œ 변경í
msgid "Profiles|You don't have access to delete this user."
msgstr "ì´ ì‚¬ìš©ìžë¥¼ 삭제할 ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26347,6 +26644,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26362,6 +26662,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26545,6 +26848,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26557,6 +26863,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26734,6 +27043,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26824,6 +27136,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -26905,6 +27220,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26932,6 +27250,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -26947,6 +27268,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -26962,54 +27286,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr "알림 추가"
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr "알림 수정"
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27313,9 +27592,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27331,6 +27607,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27469,6 +27748,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr "공급ìž"
@@ -27481,6 +27763,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27667,9 +27952,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27703,6 +27985,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27790,15 +28075,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28278,6 +28563,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28606,6 +28894,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "액세스 요청"
@@ -28615,9 +28906,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28696,12 +28984,12 @@ msgstr "요구 사항"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgid "Requires values to meet regular expression requirements."
@@ -29045,9 +29333,6 @@ msgstr "Runners"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29072,6 +29357,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29081,6 +29375,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29132,6 +29429,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29153,6 +29453,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29192,6 +29510,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29255,6 +29576,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29285,15 +29609,6 @@ msgstr "실행중"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "현재 저장소ì—ì„œ íŒŒì¼ ê¸°ë¡ì„ 압축하거나, ë„달할 수 없는 ê°ì²´ë¥¼ 제거하여 정리를 실행합니다."
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29390,9 +29705,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr "애플리케ì´ì…˜ 저장"
@@ -29710,6 +30022,9 @@ msgstr[0] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -29935,16 +30250,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -29995,6 +30313,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30013,6 +30334,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30082,6 +30406,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30103,9 +30430,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30139,6 +30463,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30148,6 +30481,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30178,6 +30514,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30301,6 +30640,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30340,10 +30682,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30361,15 +30703,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30628,9 +30964,6 @@ msgstr "서버 버전"
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30730,9 +31063,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30787,9 +31117,6 @@ msgstr "%{protocol} í”„ë¡œí† ì½œì„ í†µí•´ Pull 하거나 Push하려면 계정ì—
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -30880,9 +31207,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -30916,12 +31240,12 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "패스워드 설정"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr "ìƒíƒœ ì´ëª¨ì§€ 추가"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "SetStatusModal|Busy"
msgstr ""
@@ -30985,6 +31309,10 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31326,9 +31654,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31395,6 +31720,9 @@ msgstr "스마트카드"
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "스마트카드 ì¸ì¦ 실패: í´ë¼ì´ì–¸íŠ¸ ì¸ì¦ì„œ í—¤ë”ê°€ 잘못ë˜ì—ˆìŠµë‹ˆë‹¤."
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "스니펫"
@@ -31419,6 +31747,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31428,6 +31759,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31452,9 +31786,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32049,12 +32380,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32094,6 +32419,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32592,7 +32920,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32691,18 +33019,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32724,9 +33046,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32739,12 +33058,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32760,30 +33073,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -32811,9 +33109,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -32826,9 +33121,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -32871,6 +33163,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33057,6 +33352,9 @@ msgstr "태그는 특정 지ì ì„ 중요하다고 표시하는 기능입니다.
msgid "TagsPage|This tag has no release notes."
msgstr "ì´ íƒœê·¸ëŠ” 릴리즈 노트가 없습니다."
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "git tag ëª…ë ¹ì„ ì‚¬ìš©í•˜ì—¬ 새 태그를 추가하십시오:"
@@ -33081,6 +33379,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "팀"
@@ -33093,6 +33400,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33461,6 +33771,9 @@ msgstr[0] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33530,6 +33843,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33560,9 +33876,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33630,6 +33943,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33714,6 +34030,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -33819,9 +34138,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -33855,9 +34171,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34017,6 +34330,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34101,6 +34417,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34287,9 +34606,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34512,7 +34828,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -34815,6 +35131,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -34953,6 +35275,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35282,7 +35607,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35318,7 +35643,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35504,6 +35829,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35597,7 +35937,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -35964,6 +36304,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36048,6 +36391,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr "실행 취소"
@@ -36381,6 +36727,9 @@ msgstr "아티팩트는 빌드와 파ì´í”„ë¼ì¸ ì•„í‹°íŒ©íŠ¸ì˜ í•©ê³„ìž…ë‹ˆë‹
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr "추가 시간 구매"
@@ -36399,10 +36748,10 @@ msgstr "ì´ë²ˆ ê²°ì œ 주기 사용량"
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36414,6 +36763,9 @@ msgstr "LFS ê°ì²´"
msgid "UsageQuota|LFS Storage"
msgstr "LFS 저장소"
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36459,9 +36811,6 @@ msgstr "저장 공간"
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr "ì´ ë„¤ìž„ìŠ¤íŽ˜ì´ìŠ¤ì˜ 프로ì íŠ¸ì—ì„œ ì´ ì‚¬ìš©ì¤‘ì¸ ì €ìž¥ 공간입니다."
@@ -36501,12 +36850,12 @@ msgstr "업로드"
msgid "UsageQuota|Usage"
msgstr "사용량"
-msgid "UsageQuota|Usage Breakdown"
-msgstr ""
-
msgid "UsageQuota|Usage Quotas"
msgstr "사용량 제한"
+msgid "UsageQuota|Usage breakdown"
+msgstr ""
+
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
msgstr ""
@@ -36654,6 +37003,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36684,6 +37036,9 @@ msgstr ""
msgid "Use template"
msgstr "템플릿 사용"
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36750,6 +37105,12 @@ msgstr "ì‚¬ìš©ìž ì„¤ì •"
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37101,6 +37462,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37110,6 +37474,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37155,10 +37528,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -37815,6 +38200,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38010,6 +38398,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38019,9 +38410,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Runnerê°€ 잠겨 있으면 다른 프로ì íŠ¸ì— 할당 í•  수 없습니다"
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38034,6 +38422,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "ì´ ë¨¸ì§€ 리퀘스트(MR)ê°€ 승ì¸ëì„ ë•Œ"
@@ -38041,9 +38432,6 @@ msgstr[0] "ì´ ë¨¸ì§€ 리퀘스트(MR)ê°€ 승ì¸ëì„ ë•Œ"
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38350,10 +38738,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38395,9 +38783,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38464,6 +38849,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38620,9 +39008,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38722,9 +39107,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -38812,6 +39194,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -38821,9 +39206,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39275,28 +39657,55 @@ msgstr[0] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39308,6 +39717,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39320,9 +39732,6 @@ msgstr ""
msgid "a deleted user"
msgstr "ì‚­ì œëœ ì‚¬ìš©ìž"
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39427,12 +39836,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39460,6 +39875,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39475,9 +39893,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39508,6 +39923,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39544,9 +39962,19 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39556,7 +39984,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39622,6 +40056,16 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39655,10 +40099,10 @@ msgstr "SAST"
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39776,6 +40220,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -39831,9 +40281,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -39846,6 +40293,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -39859,6 +40312,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -39895,6 +40351,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40090,6 +40549,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40247,6 +40712,9 @@ msgstr "%{metricsLinkStart} 메모리 사용률 %{metricsLinkEnd} ì´ %{memoryFr
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40280,6 +40748,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr "ë‹¤ìŒ ì‚¬ìš©ìžì— ì˜í•´ 승ì¸ë¨: "
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40341,6 +40815,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr "ë°°í¬ í†µê³„ 로딩중"
@@ -40372,9 +40849,6 @@ msgstr "머지 실패."
msgid "mrWidget|Merge locally"
msgstr "로컬ì—ì„œ 머지"
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr "머지:"
@@ -40489,12 +40963,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "머지 충ëŒì´ 있습니다."
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 ìžë™ìœ¼ë¡œ ë¨¸ì§€í•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -40510,6 +40978,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40558,6 +41029,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40633,6 +41110,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "전체 테스트 중 %d"
diff --git a/locale/ku_TR/gitlab.po b/locale/ku_TR/gitlab.po
index 97d6d47753c..b40cb1bcc5f 100644
--- a/locale/ku_TR/gitlab.po
+++ b/locale/ku_TR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ku\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/ky_KG/gitlab.po b/locale/ky_KG/gitlab.po
index ce2506cb85b..8aba098537d 100644
--- a/locale/ky_KG/gitlab.po
+++ b/locale/ky_KG/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ky\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/lt_LT/gitlab.po b/locale/lt_LT/gitlab.po
index 7549eb15a1d..3cb2a8d88fc 100644
--- a/locale/lt_LT/gitlab.po
+++ b/locale/lt_LT/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: lt\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,29 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid " or "
msgstr ""
@@ -90,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -240,9 +226,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1227,6 +1210,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1312,9 +1298,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1371,6 +1363,9 @@ msgstr[3] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1665,9 +1660,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1701,7 +1693,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1728,6 +1720,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -2076,6 +2071,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -2157,9 +2155,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2238,9 +2233,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2334,6 +2326,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2790,7 +2785,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2805,6 +2800,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2940,7 +2941,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3555,7 +3556,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3573,6 +3574,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3588,7 +3592,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3828,13 +3832,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -4038,6 +4045,13 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -4101,9 +4115,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4450,12 +4461,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4468,12 +4485,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4486,6 +4512,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4501,6 +4536,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4510,6 +4548,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4784,12 +4825,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -5029,6 +5064,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5663,6 +5701,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5908,7 +5949,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -6019,6 +6060,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6226,9 +6270,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6515,9 +6556,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6575,6 +6613,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6907,6 +6951,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6940,6 +6987,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -7054,6 +7104,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -7096,15 +7149,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7747,7 +7794,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8188,6 +8235,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8197,6 +8247,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8206,9 +8259,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8221,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8371,30 +8442,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8533,12 +8580,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8657,6 +8698,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8738,13 +8782,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8753,16 +8797,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8771,6 +8821,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8783,31 +8839,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8879,15 +8935,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -9032,6 +9082,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9160,10 +9213,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9362,7 +9415,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9386,9 +9439,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9509,9 +9559,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9581,9 +9628,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9668,9 +9712,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9776,6 +9817,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9794,6 +9838,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9806,9 +9853,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9824,6 +9868,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9959,6 +10006,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -10076,7 +10126,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10199,10 +10249,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10259,6 +10306,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10313,6 +10363,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10472,6 +10531,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10543,6 +10605,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -11039,6 +11104,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -11105,6 +11173,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11144,16 +11215,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11228,9 +11317,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11258,9 +11344,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11288,6 +11371,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11456,13 +11542,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11471,7 +11557,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11797,7 +11895,11 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11901,6 +12003,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11916,15 +12024,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11976,6 +12081,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -12054,6 +12162,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -12099,6 +12210,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12291,12 +12405,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12391,18 +12499,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12433,9 +12529,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12661,6 +12754,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12985,10 +13081,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -13114,7 +13207,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13169,7 +13265,11 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13270,7 +13370,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13570,6 +13670,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13747,6 +13850,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -14045,9 +14151,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -14129,6 +14232,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -14144,6 +14250,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14171,9 +14280,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14186,6 +14292,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14270,6 +14382,13 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14504,9 +14623,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14700,6 +14816,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14953,6 +15072,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15184,6 +15306,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15244,6 +15369,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15820,6 +15948,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15859,6 +15990,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15874,9 +16008,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15946,10 +16077,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15997,6 +16128,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16306,6 +16440,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16474,12 +16611,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16708,7 +16839,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16771,9 +16902,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16876,7 +17013,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -17005,6 +17142,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -17089,7 +17229,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17154,9 +17294,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17178,6 +17315,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17202,6 +17342,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17214,6 +17357,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17790,6 +17936,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17850,6 +17999,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17904,6 +18056,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17922,6 +18077,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18435,6 +18599,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18538,6 +18705,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18577,6 +18747,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18760,6 +18933,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18835,9 +19011,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18937,6 +19110,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18955,6 +19134,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18970,6 +19152,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -19003,6 +19188,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19528,6 +19716,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19621,19 +19812,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19975,6 +20166,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20231,12 +20428,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20405,6 +20608,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -21042,6 +21248,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21171,6 +21380,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21258,9 +21470,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21384,6 +21593,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21393,6 +21605,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21654,6 +21869,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21699,6 +21917,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21771,6 +21992,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21927,34 +22157,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21981,6 +22205,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -22075,9 +22305,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22213,9 +22440,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22664,6 +22888,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22782,6 +23009,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22848,9 +23078,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -23161,6 +23388,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23275,7 +23505,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23290,6 +23520,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23485,6 +23718,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23543,9 +23779,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23787,18 +24020,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23850,9 +24080,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -24054,6 +24281,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -24066,6 +24296,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -24078,6 +24314,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -24093,6 +24332,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24208,15 +24450,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24265,9 +24507,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24295,6 +24534,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24304,6 +24546,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24373,6 +24618,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24448,9 +24723,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24631,14 +24903,18 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24682,9 +24958,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24943,6 +25216,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24964,6 +25240,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25471,6 +25750,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25591,6 +25873,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25708,6 +25993,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25810,9 +26098,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25957,6 +26251,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26233,12 +26530,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26248,9 +26551,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26278,6 +26578,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26569,6 +26872,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26869,6 +27175,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26884,6 +27193,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -27067,6 +27379,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27079,6 +27394,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27256,6 +27574,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27346,6 +27667,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27427,6 +27751,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27454,6 +27781,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27469,6 +27799,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27484,54 +27817,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27835,9 +28123,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27853,6 +28138,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27991,6 +28279,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -28003,6 +28294,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28189,9 +28483,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28225,6 +28516,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28312,15 +28606,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28806,6 +29100,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -29146,6 +29443,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -29155,9 +29455,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29236,15 +29533,15 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29597,9 +29894,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29624,6 +29918,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29633,6 +29936,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29684,6 +29990,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29705,6 +30014,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29744,6 +30071,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29807,6 +30137,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29837,15 +30170,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29942,9 +30266,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30295,6 +30616,9 @@ msgstr[3] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30520,16 +30844,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30580,6 +30907,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30598,6 +30928,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30667,6 +31000,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30688,9 +31024,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30724,6 +31057,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30733,6 +31075,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30763,6 +31108,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30886,6 +31234,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30925,10 +31276,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30946,15 +31297,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31213,9 +31558,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31315,9 +31657,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31372,9 +31711,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31465,9 +31801,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31501,10 +31834,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31570,6 +31903,13 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31917,9 +32257,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31986,6 +32323,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -32010,6 +32350,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -32019,6 +32362,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -32043,9 +32389,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32640,12 +32983,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32685,6 +33022,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -33183,7 +33523,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33282,18 +33622,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33315,9 +33649,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33330,12 +33661,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33351,30 +33676,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33402,9 +33712,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33417,9 +33724,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33462,6 +33766,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33648,6 +33955,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33672,6 +33982,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33684,6 +34003,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -34067,6 +34389,9 @@ msgstr[3] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -34136,6 +34461,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -34166,9 +34494,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34239,6 +34564,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34323,6 +34651,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34428,9 +34759,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34464,9 +34792,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34626,6 +34951,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34710,6 +35038,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34896,9 +35227,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -35121,7 +35449,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35424,6 +35752,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35562,6 +35896,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35897,7 +36234,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35933,7 +36270,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -36119,6 +36456,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36212,7 +36564,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36582,6 +36934,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36666,6 +37021,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36999,6 +37357,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -37017,10 +37378,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -37032,6 +37393,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -37077,9 +37441,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -37119,10 +37480,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37272,6 +37633,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37302,6 +37666,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37368,6 +37735,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37719,6 +38092,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37728,6 +38104,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37773,10 +38158,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38442,6 +38839,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38637,6 +39037,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38646,9 +39049,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38661,6 +39061,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38671,9 +39074,6 @@ msgstr[3] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38980,10 +39380,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -39025,9 +39425,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -39094,6 +39491,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39250,9 +39650,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39352,9 +39749,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39442,6 +39836,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39451,9 +39848,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39908,28 +40302,55 @@ msgstr[3] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39941,6 +40362,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39953,9 +40377,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -40066,12 +40487,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -40099,6 +40526,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -40114,9 +40544,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40147,6 +40574,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -40183,9 +40613,22 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -40195,7 +40638,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40261,6 +40710,19 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40294,10 +40756,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40418,6 +40880,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40476,9 +40944,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40491,6 +40956,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40507,6 +40978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40543,6 +41017,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40747,6 +41224,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40907,6 +41390,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40940,6 +41426,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -41004,6 +41496,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -41038,9 +41533,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -41155,12 +41647,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -41176,6 +41662,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41224,6 +41713,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41299,6 +41794,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/mk_MK/gitlab.po b/locale/mk_MK/gitlab.po
index d541dd58609..88152fe74f4 100644
--- a/locale/mk_MK/gitlab.po
+++ b/locale/mk_MK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: mk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index b5f9808df25..45e6c1dbca7 100644
--- a/locale/mn_MN/gitlab.po
+++ b/locale/mn_MN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: mn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index 68b4f1f109b..d1a1d649bc6 100644
--- a/locale/nb_NO/gitlab.po
+++ b/locale/nb_NO/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: nb\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 21:03\n"
+"PO-Revision-Date: 2021-11-02 00:42\n"
msgid " %{start} to %{end}"
msgstr " %{start} til %{end}"
@@ -40,25 +40,12 @@ msgstr " Type"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Du er nødt til å gjøre dette før %{grace_period_deadline}."
-msgid " and"
-msgstr " og"
-
msgid " and "
msgstr " og "
msgid " and %{sliced}"
msgstr " og %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " dårligere på %d punkt"
-msgstr[1] " dårligere på %d punkter"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " forbedret på %d punkt"
-msgstr[1] " forbedret på %d punkter"
-
msgid " or "
msgstr " eller "
@@ -86,6 +73,9 @@ msgstr "«%{repository_name}» sin størrelse (%{repository_size}) er større en
msgid "\"el\" parameter is required for createInstance()"
msgstr "\"el\"-parameteret er påkrevd for createInstance()"
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] "%d commit,"
msgstr[1] "%d commits,"
-msgid "%d commits"
-msgstr "%d commits"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] "%d fullført sak"
@@ -1055,9 +1042,12 @@ msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} lar deg sende varsler t
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} lar deg sende varsler til nettapplikasjoner som svar på hendelser i en gruppe eller et prosjekt. Vi anbefaler at du bruker en %{integrations_link_start}integrasjon%{link_end} som det foretrukne fremfor en webhook."
-msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
+msgid "%{widget} options"
msgstr ""
+msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
+msgstr "%{wildcards_link_start}Jokertegn%{wildcards_link_end} slik som %{code_tag_start}v*%{code_tag_end} eller %{code_tag_start}*-release%{code_tag_end} er støttet."
+
msgid "'%{data}' at %{location} does not match format: %{format}"
msgstr "'%{data}' ved %{location} samsvarer ikke med formatet: %{format}"
@@ -1138,9 +1128,15 @@ msgstr "(fjernet)"
msgid "(revoked)"
msgstr "(tilbakekalt)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} til"
@@ -1193,6 +1189,9 @@ msgstr[1] "- Hendelser"
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- Bruker"
@@ -1439,9 +1438,6 @@ msgstr "En standardgren kan ikke velges for et tomt prosjekt."
msgid "A deleted user"
msgstr "En slettet bruker"
-msgid "A description is required"
-msgstr "En beskrivelse er påkrevd"
-
msgid "A different reason"
msgstr "En annen årsak"
@@ -1475,7 +1471,7 @@ msgstr "Et medlem av misbruksteamet vil vurdere rapporten din så snart som muli
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr "En plattformverdi kan være web, mob, eller app."
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr "Handlinger"
msgid "Activate Service Desk"
msgstr "Skru på tjenestedesken"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Aktiv"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Legg til en generell kommentar til denne %{noteableDisplayName}."
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "Legg til en generell kommentar til denne %{noteable_name}."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Legg til en hjemmeside på din wiki som inneholder informasjon om prosjektet ditt og GitLab vil vise det her i stedet for denne meldingen."
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr "Legg til domene"
-
msgid "Add email address"
msgstr "Legg til E-postadresse"
@@ -2108,6 +2104,9 @@ msgstr "Legg til vurdering"
msgid "Add to tree"
msgstr "Legg til i treet"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,8 +2563,8 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "Admin"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
-msgstr "Administratorer har tilgang til alle grupper, prosjekter og brukere og kan administrere alle funksjonene i denne installasjonen"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgstr ""
msgid "AdminUsers|Admins"
msgstr "Administratorer"
@@ -2579,6 +2578,12 @@ msgstr "Vil du godkjenne brukeren %{username}?"
msgid "AdminUsers|Approved users can:"
msgstr "Godkjente brukere kan:"
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,8 +2719,8 @@ msgstr "Ã… reaktivere en bruker vil:"
msgid "AdminUsers|Regular"
msgstr "Vanlig"
-msgid "AdminUsers|Regular users have access to their groups and projects"
-msgstr "Vanlige brukere har tilgang til deres grupper og prosjekter"
+msgid "AdminUsers|Regular users have access to their groups and projects."
+msgstr ""
msgid "AdminUsers|Reject"
msgstr "Avvis"
@@ -3329,7 +3334,7 @@ msgstr "Alle flettekonflikter ble oppklart. Fletteforespørselen kan nå bli inn
msgid "All merge request dependencies have been merged"
msgstr "Alle fletteforespørselsavhengigheter har blitt innflettet"
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr "Alle brukere må ha et navn."
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Tillat \"%{group_name}\" å logge deg på"
@@ -3362,7 +3370,7 @@ msgstr "Tillat commits fra medlemmer som kan flette inn til målgrenen."
msgid "Allow group owners to manage LDAP-related settings"
msgstr "Tillat gruppeeiere å behandle LDAP-relaterte innstillinger"
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,14 +3610,17 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
-msgstr "Det oppstod en feil under innhenting av grener. Prøv søket på nytt."
+msgid "An error occurred while fetching branches. Retry the search."
+msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
-msgstr "Det oppstod en feil under innhenting av commiter. Prøv søket på nytt."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
+msgstr ""
msgid "An error occurred while fetching coverage reports."
msgstr "Det oppstod en feil under innhenting av dekningsrapporter."
@@ -3812,6 +3823,11 @@ msgstr "Det oppstod en feil under innhenting av prosjekter."
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "En feil oppstod under abonnering på varsler."
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr "En sak finnes allerede"
@@ -4210,12 +4223,18 @@ msgstr "Alle skannere"
msgid "ApprovalRule|All severity levels"
msgstr "Alle alvorlighetsgrader"
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr "Godkjenningsregler"
@@ -4228,12 +4247,21 @@ msgstr "Godkjennertype"
msgid "ApprovalRule|Approvers"
msgstr "Godkjennere"
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr "Navn"
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr "Regelnavn"
@@ -4261,6 +4298,9 @@ msgstr "Velg skannere"
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr "Alvorlighetsgrader"
@@ -4270,6 +4310,9 @@ msgstr "MÃ¥lgren"
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr "Er du sikker? Å fjerne denne GPG-nøkkelen påvirker ikke commits som a
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr "Still opp diagrammer"
@@ -4783,6 +4820,9 @@ msgstr "August"
msgid "Authenticate"
msgstr "Autentisere"
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr "Autentiser med GitHub"
@@ -5216,7 +5256,7 @@ msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_li
msgstr ""
msgid "BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}"
-msgstr "Er du ute etter å kjøpe eller behandle et abonnement til gruppen din? Gå til %{groups_link} din og gå til %{strong_open}Innstillinger → Fakturering.%{strong_close}"
+msgstr "Er du ute etter å kjøpe eller behandle et abonnement til gruppen din? Gå til %{groups_link}n din og gå til %{strong_open}Innstillinger → Fakturering.%{strong_close}"
msgid "BillingPlans|Manage plan"
msgstr "Behandle planen"
@@ -5415,11 +5455,14 @@ msgstr "Blokk"
msgid "Blog"
msgstr "Blogg"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "Bord-omfang påvirker hvilke saker som vises for alle som besøker dette bordet"
msgid "BoardNewEpic|Groups"
-msgstr ""
+msgstr "Grupper"
msgid "BoardNewEpic|Loading groups"
msgstr ""
@@ -5656,8 +5699,8 @@ msgstr "Alle"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "Kan ikke finne HEAD-commit for denne grenen"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "Sammenlign"
@@ -5767,6 +5810,9 @@ msgstr "For å bekrefte tast inn %{branch_name_confirmation}:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr "Ja, slett grenen"
@@ -5974,9 +6020,6 @@ msgstr "CI Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr "CI-minutter"
-
msgid "CI settings"
msgstr "CI-innstillinger"
@@ -6261,9 +6304,6 @@ msgstr "Avbryter forhåndsvisningen"
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr "Kan ikke flettes automatisk"
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr "Kapasitetsterskel"
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr "CI-minuttpakke"
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr "Kasse"
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr "Rediger"
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6794,6 +6846,9 @@ msgid "Checkout|company or team"
msgstr "firma eller team"
msgid "Checkout|minutes"
+msgstr "minutter"
+
+msgid "Checkout|x %{quantity} %{units} per pack"
msgstr ""
msgid "Checkout|x %{quantity} %{units} per pack ="
@@ -6838,15 +6893,9 @@ msgstr "Velg en mal …"
msgid "Choose a type..."
msgstr "Velg en type …"
-msgid "Choose any color"
-msgstr "Velg enhver farge"
-
msgid "Choose any color."
msgstr "Velg hvilken som helst farge."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr "Velg fil …"
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr "Sikkerhetsgruppe"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr "Velg en VPC for å velge en sikkerhetsgruppe"
@@ -7939,6 +7991,9 @@ msgstr "Velg en VPC for å velge et undernett"
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "Velg et nettverk for å velge et undernettverk"
@@ -7948,9 +8003,24 @@ msgstr "Velg en region for å velge et nøkkelpar"
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr "Velg en region for å velge et VPC"
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr "Velg en sone for å velge et nettverk"
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "Velg maskintype"
@@ -7963,6 +8033,9 @@ msgstr "Velg prosjekt og sone for å velge maskintype"
msgid "ClusterIntegration|Select project to choose zone"
msgstr "Velg prosjekt for å velge sone"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr "oppfyller kravene"
msgid "ClusterIntegration|sign up"
msgstr "registrer"
-msgid "ClusterIntergation|Select a VPC"
-msgstr "Velg en VPC"
-
-msgid "ClusterIntergation|Select a network"
-msgstr "Velg et nettverk"
-
-msgid "ClusterIntergation|Select a security group"
-msgstr "Velg en sikkerhetsgruppe"
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr "Velg et undernett"
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr "Velg et undernettverk"
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr "Velg en instanstype"
-
-msgid "ClusterIntergation|Select key pair"
-msgstr "Velg nøkkelpar"
-
-msgid "ClusterIntergation|Select service role"
-msgstr "Velg tjenesterolle"
-
msgid "Clusters|An error occurred while loading clusters"
msgstr "En feil oppstod under innlasting av klynger"
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr "Kommentar"
-msgid "Comment & close %{noteable_name}"
-msgstr "Kommenter og lukk %{noteable_name}"
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr "Kommenter og oppklar tråden"
@@ -8397,6 +8440,9 @@ msgstr "Samfunnsforum"
msgid "Company"
msgstr "Firma"
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Sammenlign"
@@ -8478,31 +8524,37 @@ msgstr "Fullført"
msgid "Completed"
msgstr "Fullført"
-msgid "Compliance"
-msgstr "Overholdelse"
-
-msgid "Compliance Dashboard"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
msgid "Compliance framework"
msgstr ""
+msgid "Compliance report"
+msgstr ""
+
msgid "ComplianceDashboard|created by:"
msgstr "opprettet av:"
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr "Konfigurer en %{codeStart}.gitlab-webide.yml%{codeEnd}-fil i %{codeStart
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr "Sett opp eksisterende installasjon"
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr "Sett opp kodelagerspeiling."
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr "Kontakt kundestøtte"
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "Container-register"
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr "Slett valgte tagger"
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr "For å utvide søket, endre eller fjerne filtrene ovenfor."
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr "Kopier %{name}"
msgid "Copy %{protocol} clone URL"
msgstr "Kopier %{protocol}-klone-URL"
-msgid "Copy %{proxy_url}"
-msgstr "Kopier %{proxy_url}"
-
msgid "Copy %{type}"
msgstr "Kopier %{type}"
@@ -9315,9 +9364,6 @@ msgstr "Kopier lenke"
msgid "Copy link to chart"
msgstr "Kopier lenke til diagram"
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr "Kopier referanse"
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr "Klarte ikke å arkivere %{design}. Vennligst prøv igjen."
-
msgid "Could not authorize chat nickname. Try again!"
msgstr "Klarte ikke å autorisere chat-kallenavnet. Prøv igjen!"
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr "Dekning"
@@ -9528,6 +9574,9 @@ msgstr "Opprett %{humanized_resource_name}"
msgid "Create %{type}"
msgstr "Opprett %{type}"
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Opprett ny katalog"
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr "Opprett et Mattermost-team for denne gruppen"
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr "Opprett en fletteforespørsel"
@@ -9558,6 +9604,9 @@ msgstr "Opprett en ny fil siden det ikke er noen filer ennå. Etterpå vil du ku
msgid "Create a new issue"
msgstr "Opprett et nytt sak"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr "Opprett et nytt kodelager"
@@ -9640,7 +9689,7 @@ msgid "Create new"
msgstr "Opprett ny"
msgid "Create new %{name} by email"
-msgstr ""
+msgstr "Opprett ny %{name} via E-post"
msgid "Create new CI/CD pipeline"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr "Opprett utdrag"
msgid "Create tag %{tagName}"
msgstr "Opprett etiketten %{tagName}"
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr "Opprett bruker"
@@ -9810,7 +9862,7 @@ msgstr "Gjenopprett standardinnstillinger"
msgid "CreateValueStreamForm|Restore stage"
msgstr "Gjenopprett trinn"
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,11 +9985,8 @@ msgstr "Personlige tilgangssjetonger"
msgid "CredentialsInventory|SSH Keys"
msgstr "SSH-nøkler"
-msgid "Credit card validated at:"
-msgstr "Bankkort godkjent den:"
-
-msgid "Credit card validated:"
-msgstr "Bankkort godkjent:"
+msgid "Credit card:"
+msgstr ""
msgid "Critical vulnerabilities present"
msgstr "Kritiske sårbarheter til stede"
@@ -9993,6 +10042,9 @@ msgstr "Nåværende påloggings-IP:"
msgid "Current sign-in at:"
msgstr "Nåværende pålogging hos:"
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr "Egendefinert tidsrom"
msgid "Custom range (UTC)"
msgstr "Tilpasset område (UTC)"
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr "Justerbar av en administrator."
@@ -10206,6 +10267,9 @@ msgstr "Dager igjen til fullføring"
msgid "CycleAnalytics|Display chart filters"
msgstr "Vis diagramfiltre"
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr "Ingen trinn er valgt"
@@ -10273,6 +10337,9 @@ msgstr "DAST-oppsett"
msgid "DAST Scans"
msgstr "DAST-skanninger"
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10767,6 +10834,9 @@ msgstr "Datovelger"
msgid "Date range"
msgstr "Datointervall"
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr "Standardgren"
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr "standard"
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr "Slett kommentar"
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr "Slett domene"
-
msgid "Delete file"
msgstr "Slett fil"
@@ -10986,9 +11074,6 @@ msgstr "Slett rad"
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr "Slett utdraget"
@@ -11016,6 +11101,9 @@ msgstr "Slett brukerliste"
msgid "Delete variable"
msgstr "Slett variabel"
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr "Avhengighetsmellomtjener"
msgid "Dependency Scanning"
msgstr "Avhengighetsskanning"
-msgid "Dependency proxy"
-msgstr "Avhengighetsmellomtjener"
+msgid "DependencyProxy|Cached %{time}"
+msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr "%{current_design} av %{designs_count}"
msgid "DesignManagement|%{filename} did not change."
-msgstr "%{filename} forble det samme."
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr "Lagre kommentar"
msgid "DesignManagement|Select all"
msgstr "Velg alle"
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr "Uoppklar tråden"
msgid "DesignManagement|Upload designs"
msgstr "Last opp design"
-msgid "DesignManagement|Upload skipped."
-msgstr "Opplasting hoppet over."
+msgid "DesignManagement|Upload skipped. %{reason}"
+msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr "og %{moreCount} til."
-
msgid "Designs"
msgstr "Design"
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr "FF-er"
msgid "DevopsAdoption|No results…"
msgstr "Ingen resultater …"
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr "Begynn en gratis prøveperiode"
msgid "Discover|Upgrade now"
msgstr "Oppgrader nå"
-msgid "Discuss a specific suggestion or question"
-msgstr "Diskuter et spesifikt forslag eller løsning"
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr "Domene"
msgid "Domain Name"
msgstr "Domenenavn"
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr "Domenet ble vellykket opprettet."
-
-msgid "Domain was successfully deleted."
-msgstr "Domenet ble vellykket slettet."
-
-msgid "Domain was successfully updated."
-msgstr "Domenet ble vellykket oppdatert."
-
msgid "Don't have an account yet?"
msgstr "Har du ikke en konto ennå?"
@@ -12139,9 +12235,6 @@ msgstr "Last ned %{format}"
msgid "Download %{format}:"
msgstr "Last ned %{format}:"
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr "Last ned (%{fileSizeReadable})"
@@ -12367,6 +12460,9 @@ msgstr "Rediger denne utgivelsen"
msgid "Edit title and description"
msgstr "Rediger tittel og beskrivelse"
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr "Rediger bruker: %{user_name}"
@@ -12437,7 +12533,7 @@ msgid "Email Notification"
msgstr "E-postvarsling"
msgid "Email a new %{name} to this project"
-msgstr ""
+msgstr "Send inn en ny %{name} til dette prosjektet via E-post"
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12691,12 +12787,9 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
-msgid "Enable proxy"
-msgstr "Skru på mellomtjener"
-
msgid "Enable reCAPTCHA"
msgstr "Skru på reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr "Skriv inn et nummer"
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12869,13 +12965,15 @@ msgid "Enter your Packagist username."
msgstr ""
msgid "Enter your password to approve"
-msgstr ""
+msgstr "Skriv inn passordet ditt for å godkjenne"
msgid "Enterprise"
msgstr "Bedrift"
msgid "Environment"
-msgstr "Miljø"
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,8 +13074,8 @@ msgstr "Det oppstod en feil ved stopping av miljøet, vennligst prøv igjen"
msgid "Environments|Are you sure you want to stop this environment?"
msgstr "Er du sikker på at du vil stoppe dette miljøet?"
-msgid "Environments|Auto stop in"
-msgstr "Autostopp om"
+msgid "Environments|Auto stop"
+msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
msgstr ""
@@ -13061,7 +13159,7 @@ msgid "Environments|Note that this action will stop the environment, but it will
msgstr "Merk at denne handlingen vil stoppe miljøet, men det vil %{emphasisStart}ikke%{emphasisEnd} ha en effekt på noen eksisterende distribusjoner fordi ingen «Stopp miljøhandling» er definert i %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd}-filen."
msgid "Environments|Open"
-msgstr ""
+msgstr "Ã…pne"
msgid "Environments|Open live environment"
msgstr ""
@@ -13276,6 +13374,9 @@ msgstr "Feil under oppretting av epos"
msgid "Error creating label."
msgstr "Feil ved oppretting av stempel."
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr "Feil under opprettelse av ny iterasjon"
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr "Feil: %{error_message}"
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr "Eksempel: @sub\\.firma\\.com$"
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr "Utløpsdato"
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr "Utløpt"
@@ -13848,6 +13952,9 @@ msgstr "Utløper"
msgid "Expires in %{expires_at}"
msgstr "Utløper om %{expires_at}"
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr "Utløper:"
@@ -13875,9 +13982,6 @@ msgstr "Utforsk offentlige grupper"
msgid "Export"
msgstr "Eksporter"
-msgid "Export %{name}"
-msgstr "Eksporter %{name}"
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr "Eksporter gruppe"
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "Eksporter prosjekt"
@@ -13974,6 +14084,11 @@ msgstr "Mislyktes i å legge til et Zoom-møte"
msgid "Failed to apply commands."
msgstr "Mislyktes i å benytte kommandoer."
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr "Mislyktes i å upgrade."
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr "Mislyktes i å verifisere domeneeierskapet"
-
msgid "Failure"
msgstr "Feil"
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr "Fjern"
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr "Sett Unleash-klientapplikasjonsnavnet til navnet på miljøet som applikasjonen kjører i. Denne verdien brukes til å samsvare med miljøomfang. Se %{linkStart}eksempelklientoppsettet%{linkEnd}."
@@ -14653,6 +14768,9 @@ msgstr "Fullført"
msgid "Finished at"
msgstr "Fullført den"
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr "Først sett"
@@ -14884,6 +15002,9 @@ msgstr "Fant feil i din .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr "Generelle innstillinger"
msgid "General pipelines"
msgstr "Generelle rørledninger"
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr "Generer et standardsett med stempler"
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr "GitLab-commit"
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr "GitLab-eksport"
@@ -15559,6 +15686,9 @@ msgstr "GitLab-metadata-URL"
msgid "GitLab project export"
msgstr "GitLab-prosjekteksportering"
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr "GitLab-versjon"
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "GitLab vil kjøre en bakgrunnsjobb som vil opprette pseudonymiserte CSV filer av GitLab-databasen. Disse vil bli lastet opp til den konfigurerte objektlagringskatalogen."
-
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -15646,10 +15773,10 @@ msgstr "Lagre endringer"
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr "Noe gikk galt under innhenting av Let's Encrypt-sertifikatet for %{domain}. Gå til dine %{link_start}domenedetaljer%{link_end} for å prøve på nytt."
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
-msgstr "Støtte for domener og sertifikater er deaktivert. Be systemadministratoren din om å aktivere det."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr "Gitea-importering"
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr "Gruppeavatar"
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr "Gruppebeskrivelse (valgfritt)"
@@ -16174,12 +16307,6 @@ msgstr "Ingen start- eller sluttdato"
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr "Ingen startdato – %{dateWord}"
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr "Endring av gruppe-URL-en kan ha utilsiktede bivirkninger."
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr "Ingen grupper ble funnet"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr "Overskrift 1"
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr "Skjul verdier"
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr "Høyeste rolle:"
@@ -16874,6 +17007,9 @@ msgstr "Historie"
msgid "History of authentications"
msgstr "Historikk over autentiseringer"
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr "Hjemmeside-URL"
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr "Time (UTC)"
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr "Renhold"
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr "Har du et minutt?"
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr "Enkelt"
@@ -17540,6 +17685,9 @@ msgstr "Grunnleggende om Git"
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr "Inviter teamet ditt nå"
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr "Arvet:"
msgid "Inline"
msgstr "Integrert"
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr "Instansoversikt"
msgid "Insufficient permissions"
msgstr "Utilstrekkelige tillatelser"
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr "Integrasjon"
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr "Nettleserbegrensninger"
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr "Intern URL (valgfritt)"
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr "Interne brukere"
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr "Ugyldig spørring"
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr "Samarbeid med teamet ditt"
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr "Avbryt"
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr "Noe gikk galt"
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr "Startdato"
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr "Varigheten til hver iterasjon (i uker)"
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr "Startdatoen til din første iterasjon"
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,11 +19850,17 @@ msgstr "med"
msgid "Join Zoom meeting"
msgstr "Bli med på Zoom-møte"
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr "Ble med %{time_ago}"
msgid "Joined %{user_created_time}"
-msgstr ""
+msgstr "Ble med %{user_created_time}"
msgid "Joined projects (%{projects_count})"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr "Nyeste aktivitet"
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "Nyeste rørledning"
msgid "Last Seen"
msgstr "Sist sett"
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr "Sist brukt"
@@ -20091,6 +20290,9 @@ msgstr "Lær mer om utstasjonering til en klynge"
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr "Gjør denne saken konfidensiell."
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr "Legg til kursiv tekst (%{modifier_key}I)"
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr "Maks økttid"
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr "Maks antall %{name} (%{count}) har blitt overskredet"
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr "Maks antall kommentarer har blitt overskredet"
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr "Maks antall prosjekter."
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr "Fletteforespørselshendelser"
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr "Rørledninger"
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr "UTC (Coordinated Universal Time)"
msgid "MetricsSettings|User's local timezone"
msgstr "Brukerens lokale tidssone"
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr "Utvid panel"
msgid "Metrics|For grouping similar metrics"
msgstr "For gruppering av lignende metrikker"
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr "Vis dokumentasjon"
msgid "Metrics|View logs"
msgstr "Vis loggføringer"
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22309,7 +22529,7 @@ msgid "Multiple Prometheus integrations are not supported"
msgstr ""
msgid "Multiple domains are supported."
-msgstr ""
+msgstr "Flere domener støttes."
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr "Mitt firma eller team"
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr "Trenger oppmerksomhet"
msgid "Network"
msgstr "Nettverk"
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr "%{ifLabelStart}hvis%{ifLabelEnd} %{ruleType} %{isLabelStart}er%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}og er innkommende fra en%{directionLabelEnd} %{rule} %{portsLabelStart}på%{portsLabelEnd} %{ports}"
@@ -22514,9 +22740,6 @@ msgstr "Avvis all trafikk"
msgid "NetworkPolicies|Edit policy"
msgstr "Rediger retningslinje"
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr "Ny etikett"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr "Ingen bidrag"
msgid "No contributions were found"
msgstr "Ingen bidrag ble funnet"
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr "Ingen kredittkort nødvendig."
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr "Ingen sårbarheter er til stede"
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr "Ikke tilgjengelig for private prosjekter"
msgid "Not available for protected branches"
msgstr "Ikke tilgjengelig for beskyttede grener"
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr "Ikke konfidensiell"
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr "Antall LOC per commit"
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr "Antall endringer (grener eller etiketter) i én enkelt push for å bestemme om individuelle pushhendelser eller bunke-pushhendelser skal opprettes. Bunke-pushhendelser vil bli opprettet hvis den overstiger denne verdien."
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr "Antall commiter"
msgid "Number of commits per MR"
msgstr "Antall commiter per FF"
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr "Antall hendelser"
@@ -23504,9 +23730,6 @@ msgstr "Eldste øverst"
msgid "OmniAuth"
msgstr "OmniAuth"
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr "Omnibus Protected Paths-pedalen er aktiv, og prioriterer disse innstillingene. Fra 12.4, avvikles Omnibus-pedalen og vil bli fjernet i en fremtidig utgivelse. Les dokumentasjonen for %{relative_url_link_start}Migrering av beskyttede filbaner%{relative_url_link_end}."
-
msgid "On"
msgstr "Den"
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr "Lagre skanning"
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr "Skannerprofil"
@@ -23747,6 +23982,9 @@ msgstr "Nettstedsprofil"
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr "Ã…pne eposer"
msgid "Open errors"
msgstr "Ã…pne feil"
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr "Ã…pne i filvisning"
@@ -23917,9 +24155,6 @@ msgstr "Handlingen er ikke tillatt"
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr "Handlinger"
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr "Valgfritt"
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "Eventuelt kan du %{link_to_customize} hvordan FogBugz-e-postadresser og brukernavn importeres til GitLab."
@@ -23956,6 +24194,9 @@ msgstr "Innstillinger"
msgid "Or you can choose one of the suggested colors below"
msgstr "Eller så kan du velge en av de foreslåtte fargene nedenfor"
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr "Eid av:"
msgid "Owner"
msgstr "Eier"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr "Pakkeregister"
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr "Tillat duplikater"
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr "Appgruppe: %{group}"
@@ -24283,14 +24551,16 @@ msgstr "NuGet-kommando"
msgid "PackageRegistry|Package Registry"
msgstr "Pakkeregister"
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr "Filbane:"
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr "Pause"
@@ -24616,6 +24886,9 @@ msgstr "I kø"
msgid "Pending comments"
msgstr "Avventende kommentarer"
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr "Venter på synkronisering …"
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "Det er ingen rørledninger for øyeblikket."
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr "Bestått"
@@ -25360,6 +25639,9 @@ msgstr "RÃ¥ diff"
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr "Plan:"
@@ -25462,9 +25744,15 @@ msgstr "Vennligst skriv inn et gyldig nummer"
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Vennligst skriv inn et beskrivende navn på gruppen din."
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr "Profil"
msgid "Profile Settings"
msgstr "Profilinnstillinger"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr "Profilside:"
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr "den"
@@ -25900,9 +26197,6 @@ msgstr "Du er i ferd med å slette %{yourAccount} permanent, og alle sakene, fle
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr "Du er i ferd med å endre brukernavnet %{currentUsernameBold} til %{newUsernameBold}. Profilen og prosjektene blir omdirigert til %{newUsername}-navnefeltet, men denne viderekoblingen utløper når %{currentUsername}-navnene har blitt registrert av en annen bruker eller gruppe. Oppdater Git-kodelagerfjernkontrollene dine så snart som mulig."
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr "«Opptatt» vil bli vist ved siden av navnet ditt"
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr "Legg til status emoji"
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr "Avatarbeskjærer"
@@ -25961,7 +26258,7 @@ msgid "Profiles|Clear status"
msgstr "Tøm status"
msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
+msgstr "Klikk på ikonene for å aktivere pålogging med en av følgende tjenester"
msgid "Profiles|Commit email"
msgstr "Commit-E-post"
@@ -26015,7 +26312,7 @@ msgid "Profiles|Enter your password to confirm the email change"
msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
-msgstr ""
+msgstr "Skriv inn pronomenene dine for å la folk vite hvordan de skal referere til deg"
msgid "Profiles|Expired key is not valid."
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr "Du kan laste opp avataren din her eller endre den på %{gravatar_link}"
msgid "Profiles|You don't have access to delete this user."
msgstr "Du har ikke tilgang til å slette denne brukeren."
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26228,7 +26528,7 @@ msgid "Profiles|You must transfer ownership or delete these groups before you ca
msgstr "Du må overføre eierskapet eller slette disse gruppene før du kan slette kontoen din."
msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
-msgstr "Ditt LinkedIn-profilnavn fra linkedin.com/in/profilename"
+msgstr "Ditt LinkedIn-profilnavn fra linkedin.com/in/profilnavn"
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Din konto er for øyeblikket eier i disse gruppene:"
@@ -26521,6 +26821,9 @@ msgstr "Oppgi nytt passord"
msgid "ProjectService|Enter new password."
msgstr "Skriv inn nytt passord."
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr "Sakens URL"
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr "Universelt"
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "Internt"
@@ -26731,6 +27040,9 @@ msgstr "Saker"
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr "Opprett nytt prosjekt"
msgid "ProjectsNew|Description format"
msgstr "Beskrivelsesformat"
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr "Importer"
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr "Ingen importalternativer er tilgjengelige"
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "Prosjektbeskrivelse %{tag_start}(valgfritt)%{tag_end}"
@@ -27136,54 +27463,9 @@ msgstr "Vil du huse flere prosjekter som er avhengig av hverandre i det samme na
msgid "Prometheus"
msgstr "Prometheus"
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr "Legg til alarm"
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr "Rediger alarm"
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr "Feil under oppretting av alarm"
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr "Feil under sletting av alarm"
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr "Feil under innhenting av alarm"
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr "Feil under lagring av alarm"
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr "Operatør"
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr "Velg forespørsel"
-
-msgid "PrometheusAlerts|Threshold"
-msgstr "Terskel"
-
msgid "PrometheusAlerts|exceeded"
msgstr "overskredet"
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr "https://gitlab.com/gitlab-com/runbooks"
-
msgid "PrometheusAlerts|is equal to"
msgstr "er det samme som"
@@ -27487,9 +27769,6 @@ msgstr "Beskyttede grener"
msgid "Protected Environment"
msgstr "Beskyttet miljø"
-msgid "Protected Paths"
-msgstr "Beskyttede stier"
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,9 +27784,12 @@ msgstr "Beskyttede grener"
msgid "Protected environments"
msgstr ""
-msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
+msgid "Protected paths"
msgstr ""
+msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
+msgstr "%{wildcards_link_start}Jokertegn%{wildcards_link_end} slik som %{code_tag_start}*-stable%{code_tag_end} eller %{code_tag_start}production/*%{code_tag_end} er støttet."
+
msgid "ProtectedBranch|Allow all users with push access to %{tag_start}force push%{tag_end}."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr "Leverandør"
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr "Spørring"
msgid "Query cannot be processed"
msgstr "Spørringen kan ikke behandles"
-msgid "Query is valid"
-msgstr "Spørringen er gyldig"
-
msgid "Queued"
msgstr "Satt i kø"
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr "Nylig"
-msgid "Recent Deliveries"
-msgstr "Nylige leveranser"
-
msgid "Recent Project Activity"
msgstr "Nylig prosjektaktivitet"
msgid "Recent Searches Service is unavailable"
msgstr "Tjeneste for nylige søk er ikke tilgjengelig"
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr "Forny abonnement"
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr "Åpne på nytt"
@@ -28786,6 +29077,9 @@ msgstr "Kodelager: %{counter_repositories} / Wikier: %{counter_wikis} / Byggarti
msgid "RepositorySettingsAccessLevel|Select"
msgstr "Velg"
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "Be om tilgang"
@@ -28795,9 +29089,6 @@ msgstr "Be om en ny en"
msgid "Request details"
msgstr "Be om detaljer"
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,15 +29167,15 @@ msgstr "Krav"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] "Krever godkjenning fra %{names}."
-msgstr[1] "Krever %{count} flere godkjenninger fra %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
+msgstr[0] ""
+msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
-msgstr[0] "Krever godkjennelse."
-msgstr[1] "Krever %d godkjenninger til."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
+msgstr[0] ""
+msgstr[1] ""
msgid "Requires values to meet regular expression requirements."
msgstr ""
@@ -29229,9 +29520,6 @@ msgstr "Løpere"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr "Arkitektur"
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr "Ikke tilkoblet"
@@ -29337,6 +29640,24 @@ msgstr "Egenskapsnavn"
msgid "Runners|Protected"
msgstr "Beskyttet"
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr "Revisjon"
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr "Kjører"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr "SAML"
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr "Lagre endringene"
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr "Lagre applikasjon"
@@ -29905,6 +30220,9 @@ msgstr[1] "wiki-resultater"
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr "Beskrivelse"
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr "Opprett saker"
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr "Last ned resultater"
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr "Enten har du ikke tillatelse til å se dette kontrollpanelet, eller så har kontrollpanelet ikke blitt konfigurert. Kontroller tillatelsesinnstillingene dine med administratoren din, eller sjekk kontrollpanelkonfigurasjonene sine for å fortsette."
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr "Behandle og spor sårbarheter som har blitt identifisert i prosjekter innenfor gruppen din. Sårbarheter i prosjekter vises her når sikkerhetstesting er satt opp."
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr "Behandle og spor sårbarheter som har blitt identifisert i prosjektet ditt. Sårbarheter vises her når sikkerhetstesting er satt opp."
@@ -30343,6 +30679,9 @@ msgstr "Behandle og spor sårbarheter som har blitt identifisert i dine valgte p
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr "Hold øye med sårbarheter i alle dine prosjekter"
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr "Oi sann, noe ser ikke riktig ut."
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr "Prosjekt"
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr "Velg side"
msgid "Select a branch"
msgstr "Velg en gren"
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr "Velg et nytt navnefelt"
msgid "Select a project"
msgstr "Velg et prosjekt"
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr "Velg en årsak"
-msgid "Select a repository"
-msgstr "Velg et kodelager"
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr "Serverversjon"
msgid "Serverless"
msgstr "Serverless"
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr "Sett opp Jira-integrering"
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,12 +31438,12 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "bestem et passord"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
-msgstr "En «opptatt»-indikator vises ved siden av navnet og avataren din."
-
msgid "SetStatusModal|Add status emoji"
msgstr "Legg til status-emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "SetStatusModal|Busy"
msgstr "Opptatt"
@@ -31180,6 +31507,11 @@ msgstr "Innstilling"
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr "Lignende saker"
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr "Smartkort"
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "Tekstblokker"
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr "Legg til en annen fil %{num}/%{total}"
@@ -31625,6 +31960,9 @@ msgstr "Slett fil"
msgid "Snippets|Description (optional)"
msgstr "Beskrivelse (valgfritt)"
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr "Filer"
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -31947,7 +32282,7 @@ msgid "SortOptions|Merged recently"
msgstr "Nylig sammenslått"
msgid "SortOptions|Milestone due date"
-msgstr ""
+msgstr "Milepælforfallsdato"
msgid "SortOptions|Milestone due later"
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr "Start søk"
msgid "Start thread"
msgstr "Start tråd"
-msgid "Start thread & close %{noteable_name}"
-msgstr "Start tråd og lukk %{noteable_name}"
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr "Starter: %{startsAt}"
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr "Opplåsingen var vellykket"
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr "Oppsummering / Notat"
msgid "Sunday"
msgstr "Søndag"
-msgid "SuperSonics|Activate"
-msgstr "Aktiver"
-
msgid "SuperSonics|Activate cloud license"
msgstr "Aktiver skylisens"
msgid "SuperSonics|Activate subscription"
msgstr "Aktiver abonnement"
-msgid "SuperSonics|Activated on"
-msgstr "Aktivert den"
-
msgid "SuperSonics|Activation code"
msgstr "Aktiveringskode"
@@ -32921,9 +33247,6 @@ msgstr "Skylisensiering"
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr "Utløper den"
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr "ID"
-
-msgid "SuperSonics|Last Sync"
-msgstr "Nyligste synkronisering"
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr "Maks antall brukere"
msgid "SuperSonics|Paste your activation code"
msgstr "Lim inn aktiveringskoden din"
-msgid "SuperSonics|Plan"
-msgstr "Plan"
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr "Fornyer"
-
-msgid "SuperSonics|Seats"
-msgstr "Seter"
-
msgid "SuperSonics|Start free trial"
msgstr "Begynn gratis prøveperiode"
-msgid "SuperSonics|Started"
-msgstr "Startet"
-
-msgid "SuperSonics|Subscription"
-msgstr "Abonnement"
-
msgid "SuperSonics|Subscription details"
msgstr "Abonnementsdetaljer"
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr "Type"
-
msgid "SuperSonics|Upload a license file"
msgstr "Last opp en lisensfil"
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr "Gyldig fra"
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr "Støtteside-URL"
msgid "Survey Response"
msgstr "Undersøkelsessvar"
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr "Bytt gren"
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr "Denne etiketten har ingen utgivelsesbeskrivelser."
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr "MÃ¥lgren"
msgid "Task ID: %{elastic_task}"
msgstr "Oppgave-ID: %{elastic_task}"
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "Team"
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] "%{type} inneholder følgende feil:"
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr "Mappen har blitt vellykket opprettet."
@@ -33833,6 +34150,9 @@ msgstr "Skjemaet inneholder følgende feilmeldinger:"
msgid "The form contains the following warning:"
msgstr "Skjemaet inneholder følgende advarsel:"
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr "Den maks tillatte filstørrelsen er %{size}."
@@ -34022,9 +34345,6 @@ msgstr "Prosjektet ble vellykket utgreinet."
msgid "The project was successfully imported."
msgstr "Prosjektet ble vellykket importert."
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "Pseudonymisert datainnsamling er deaktivert. Når den er aktivert, vil GitLab kjøre en bakgrunnsjobb som vil opprette pseudonymiserte CSV-filer av GitLab-databasen. Disse vil bli lastet opp til den konfigurerte objektlagringskatalogen."
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr "Kodelageret må være tilgjengelig over %{code_open}http://%{code_close}
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr "Planleggingstiden må være i fremtiden!"
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr "Det er ingen pakker ennå"
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr "Det er ingen variabler enda."
@@ -34304,6 +34624,9 @@ msgstr "En feil oppstod under innhenting av nylige grupper."
msgid "There was a problem fetching recent projects."
msgstr "En feil oppstod under innhenting av nylige prosjekter."
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr "Denne gruppen er knyttet til et abonnement"
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr "Denne brukeren er forfatteren av denne %{noteable}."
msgid "This variable can not be masked."
msgstr "Denne variabelen kan ikke maskeres."
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr "Gjennomstrømming"
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,8 +35852,8 @@ msgstr "For å holde dette prosjektet gående, opprett en ny sak"
msgid "To keep this project going, create a new merge request"
msgstr "For å holde dette prosjektet gående, opprett en ny fletteforespørsel"
-msgid "To learn more about this project, read %{link_to_wiki}."
-msgstr "For å lære mer om dette prosjektet, les %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
+msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr "GÃ¥ tilbake"
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr "Emner (valgfritt)"
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr "Klarte ikke å innhente sårbare prosjekter"
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr "Angre"
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr "Kjøp ekstra minutter"
@@ -36605,10 +36958,10 @@ msgstr "Bruk i nåværende periode"
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr "LFS-objekter"
msgid "UsageQuota|LFS Storage"
msgstr "LFS-lagring"
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr "Lær mer om overflødig lagringsbenyttelse"
@@ -36665,9 +37021,6 @@ msgstr "Lagring"
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,12 +37060,12 @@ msgstr "Opplastinger"
msgid "UsageQuota|Usage"
msgstr "Benyttelse"
-msgid "UsageQuota|Usage Breakdown"
-msgstr ""
-
msgid "UsageQuota|Usage Quotas"
msgstr "Brukskvoter"
+msgid "UsageQuota|Usage breakdown"
+msgstr ""
+
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
msgstr ""
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr "Bruk cURL"
@@ -36890,6 +37246,9 @@ msgstr "Bruk skråstrekkommandoer."
msgid "Use template"
msgstr "Bruk mal"
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr "Brukerinnstillinger"
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr "Valider"
@@ -37316,6 +37684,15 @@ msgstr "Valider GitLab CI-konfigurasjonen din"
msgid "Validate your GitLab CI configuration file"
msgstr "Valider GitLab CI-konfigurasjonensfilen din"
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr "Valideringer mislyktes."
@@ -37361,10 +37738,22 @@ msgstr "&lt;1m"
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr "Webhook-loggføringer"
msgid "Webhook Settings"
msgstr "Webhook-innstillinger"
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr "Hva er nytt"
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "Når denne fletteforespørselen godtas"
@@ -38251,9 +38646,6 @@ msgstr[1] "Når disse fletteforespørslene godtas"
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr "Når du bruker %{code_open}http: //%{code_close} eller %{code_open}https: //%{code_close} protokollene, vennligst oppgi den nøyaktige URL-en til kodelageret. HTTP-viderekoblinger blir ikke fulgt."
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr "NÃ¥r:"
@@ -38558,14 +38950,14 @@ msgid "Write a comment…"
msgstr "Skriv en kommentar …"
msgid "Write a description or drag your files here…"
+msgstr "Skriv en beskrivelse og/eller slipp filene dine hit …"
+
+msgid "Write a description…"
msgstr ""
msgid "Write milestone description..."
msgstr "Skriv en milepælbeskrivelse …"
-msgid "Write to \"authorized_keys\" file"
-msgstr ""
-
msgid "Write your release notes or drag your files here…"
msgstr ""
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr "Du kan gjenopprette dette prosjektet frem til %{date}"
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr "Du har ikke noen prosjekter tilgjengelig."
msgid "You don't have any recent searches"
msgstr "Du har ingen nylige søk"
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr "Du har ikke tilstrekkelig tillatelse til å utføre denne handlingen."
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr "Du har vellykket kjøpt et abonnement på %{plan}-plan for %{seats}. Du mottar en kvittering via e-post."
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr "Du forlot «%{membershipable_human_name}»-%{source_type}."
@@ -39031,9 +39420,6 @@ msgstr "Du kan lukke milepælen nå."
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
-msgstr "Skriv inn API-sjetong"
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
+msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr "Zoom-møte fjernet"
msgid "[No reason]"
msgstr "[Ingen grunn]"
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr "en slettet bruker"
-msgid "a design"
-msgstr "et design"
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] "omkring 1 time"
@@ -39546,7 +39959,7 @@ msgid "added"
msgstr "lagt til"
msgid "added %{created_at_timeago}"
-msgstr ""
+msgstr "lagt til %{created_at_timeago}"
msgid "added %{emails}"
msgstr "la til %{emails}"
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr "kan ikke modifiseres"
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr "kan ikke selv bli blokkert"
msgid "cannot merge"
msgstr "kan ikke flette"
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr "%{degradedNum} degradert"
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "%{remainingPackagesCount} til"
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,8 +40202,14 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
-msgstr "Kodekvalitet"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
msgid "ciReport|Container Scanning"
msgstr "Containerskanning"
@@ -39835,6 +40274,17 @@ msgstr "Fant %{issuesWithCount}"
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "Undersøk dette sikkerhetsproblemet ved å opprette en sak"
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr "SAST"
msgid "ciReport|Secret Detection"
msgstr "Hemmelig oppdaging"
-msgid "ciReport|Secret scanning"
-msgstr "Hemmelig skanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
+msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40015,7 +40471,7 @@ msgid "created %{timeAgo}"
msgstr "opprettet %{timeAgo}"
msgid "created %{timeAgo} by %{author}"
-msgstr ""
+msgstr "opprettet for %{timeAgo} av %{author}"
msgid "created by"
msgstr "laget av"
@@ -40046,9 +40502,6 @@ msgstr "distribuering"
msgid "design"
msgstr "design"
-msgid "designs"
-msgstr "design"
-
msgid "detached"
msgstr "frakoblet"
@@ -40061,6 +40514,12 @@ msgstr "eksisterer ikke"
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr "last den ned"
@@ -40075,6 +40534,9 @@ msgstr "f.eks. %{token}"
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr "overgår grensen på %{bytes} bytes"
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr "Godkjenn i tillegg"
msgid "mrWidget|Approved by"
msgstr "Godkjent av"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr "Fletting mislyktes."
msgid "mrWidget|Merge locally"
msgstr "Flett lokalt"
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr "Flettet av"
@@ -40711,12 +41191,6 @@ msgstr "Kildegrenen vil ikke bli slettet"
msgid "mrWidget|There are merge conflicts"
msgstr "Det er flette konflikter"
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Denne fletteforespørsel ble ikke flettet automatisk"
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr "Bruk %{linkStart}CI-rørledninger til å teste koden%{linkEnd} ved å legge til en GitLab CI-konfigurasjonsfil i prosjektet ditt. Det tar bare et minutt å gjøre koden din mer sikker og robust."
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr "min-kule-gruppe"
@@ -40855,6 +41338,9 @@ msgstr "eller"
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index c52dc26a8f6..7dd2b54118a 100644
--- a/locale/nl_NL/gitlab.po
+++ b/locale/nl_NL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: nl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:22\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr " en"
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " gedegradeerd op %d punt"
-msgstr[1] " gedegradeerd op %d punten"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " verbeterd op %d punt"
-msgstr[1] " verbeterd op %d punten"
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Actief"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Vergelijk"
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
msgstr ""
-msgid "Define approval rules."
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index 5743595767b..3a95cf988e9 100644
--- a/locale/pa_IN/gitlab.po
+++ b/locale/pa_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pa-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:22\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index df085f1178c..215c0dca0ed 100644
--- a/locale/pl_PL/gitlab.po
+++ b/locale/pl_PL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:22\n"
+"PO-Revision-Date: 2021-11-02 00:40\n"
msgid " %{start} to %{end}"
msgstr " %{start} do %{end}"
@@ -40,29 +40,12 @@ msgstr " Typ"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Musisz to zrobić przed %{grace_period_deadline}."
-msgid " and"
-msgstr " i"
-
msgid " and "
msgstr " i "
msgid " and %{sliced}"
msgstr " i %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " polepszono o %d punkt"
-msgstr[1] " polepszono o %d punkty"
-msgstr[2] " polepszono o %d punktów"
-msgstr[3] " polepszono o %d punkta"
-
msgid " or "
msgstr " lub "
@@ -90,6 +73,9 @@ msgstr "Rozmiar (%{repository_size}) w „%{repository_name}†jest większy ni
msgid "\"el\" parameter is required for createInstance()"
msgstr "Parametr „el†jest wymagany dla createInstance()"
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr "#ogólne, #rozwój"
@@ -240,9 +226,6 @@ msgstr[1] "%d commity,"
msgstr[2] "%d commitów,"
msgstr[3] "%d commitu,"
-msgid "%d commits"
-msgstr "%d commitów"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] "%d zakończone zgłoszenie"
@@ -1227,6 +1210,9 @@ msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} umożliwia wysyłanie p
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr "%{webhooks_link_start} %{webhook_type} %{link_end} umożliwia wysyłanie powiadomień do aplikacji sieci web w odpowiedzi na zdarzenia w grupie lub projekcie. Zalecamy użycie %{integrations_link_start}integracji%{link_end} zamiast elementu webhook."
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr "%{wildcards_link_start}Symbole wieloznaczne%{wildcards_link_end} takie jak %{code_tag_start}v*%{code_tag_end} lub %{code_tag_start}*-release%{code_tag_end} są obsługiwane."
@@ -1312,9 +1298,15 @@ msgstr "(usunięto)"
msgid "(revoked)"
msgstr "(unieważnione)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr "(potrzebujemy Twojego aktualnego hasła, aby potwierdzić zmiany)"
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} więcej"
@@ -1371,6 +1363,9 @@ msgstr[3] ""
msgid "- Not available to run jobs."
msgstr "- Niedostępne do uruchomienia zadań."
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- Użytkownik"
@@ -1665,9 +1660,6 @@ msgstr "Domyślny branch nie może być wybrany dla pustego projektu."
msgid "A deleted user"
msgstr "Usunięty użytkownik"
-msgid "A description is required"
-msgstr "Wymagany jest opis"
-
msgid "A different reason"
msgstr "Inny powód"
@@ -1701,7 +1693,7 @@ msgstr "Członek zespołu ds. nadużyć zweryfikuje Twoje zgłoszenie tak szybko
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1728,6 +1720,9 @@ msgstr "Wartością platformy może być internet, mob lub aplikacja."
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr "Projekt standardowy dla rozwoju aplikacji Salesforce z narzędziami Salesforce Developer"
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr "Projekt zawierający kwestie dotyczące każdego audytu w protokole kontroli HIPAA opublikowanym przez Departament Zdrowia i Usług Stanów Zjednoczonych"
@@ -2076,6 +2071,9 @@ msgstr "Akcje"
msgid "Activate Service Desk"
msgstr "Aktywuj Service Desk"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Aktywne"
@@ -2157,9 +2155,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Dodaj ogólny komentarz do tego %{noteableDisplayName}."
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "Dodaj ogólny komentarz do tego %{noteable_name}."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Dodaj do swojej wiki stronę główną z informacjami o Twoim projekcie, a GitLab wyświetli ją zamiast tej wiadomości."
@@ -2238,9 +2233,6 @@ msgstr "Dodaj zamrożenie wdrożenia"
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr "Dodaj klucze wdrażania, aby udzielić dostępu do odczytu/zapisu do tego repozytorium. %{link_start} Co to są klucze wdrażania? %{link_end}"
-msgid "Add domain"
-msgstr "Dodaj domenÄ™"
-
msgid "Add email address"
msgstr "Dodaj adres e-mail"
@@ -2334,6 +2326,9 @@ msgstr "Dodaj do recenzji"
msgid "Add to tree"
msgstr "Dodaj do drzewa"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr "Dodaj wyzwalacz"
@@ -2790,8 +2785,8 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
-msgstr "Administratorzy mają dostęp do wszystkich grup, projektów i użytkowników i mogą zarządzać wszystkimi funkcjami w tej instalacji"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgstr ""
msgid "AdminUsers|Admins"
msgstr ""
@@ -2805,6 +2800,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr "Zatwierdzeni użytkownicy mogą:"
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2940,8 +2941,8 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr "Zwykły"
-msgid "AdminUsers|Regular users have access to their groups and projects"
-msgstr "Zwykli użytkownicy mają dostęp do swoich grup i projektów"
+msgid "AdminUsers|Regular users have access to their groups and projects."
+msgstr ""
msgid "AdminUsers|Reject"
msgstr "Odrzuć"
@@ -3555,8 +3556,8 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
-msgstr "Wszystkie ścieżki są względne w stosunku do adresu URL GitLab. Nie dołączaj %{relative_url_link_start}względnego adresu URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
+msgstr ""
msgid "All projects"
msgstr "Wszystkie projekty"
@@ -3573,6 +3574,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3588,7 +3592,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr "Pozwól właścicielom grupy na zarządzanie ustawieniami związanymi z LDAP"
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3828,13 +3832,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -4038,6 +4045,13 @@ msgstr "Wystąpił błąd podczas pobierania projektów."
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "Wystąpił błąd podczas subskrybowania powiadomień."
@@ -4101,9 +4115,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4450,12 +4461,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4468,12 +4485,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4486,6 +4512,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4501,6 +4536,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4510,6 +4548,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4784,12 +4825,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -5029,6 +5064,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5663,6 +5701,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5908,7 +5949,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -6019,6 +6060,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6226,9 +6270,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6515,9 +6556,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6575,6 +6613,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6907,6 +6951,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6940,6 +6987,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -7054,6 +7104,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -7096,15 +7149,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7747,7 +7794,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8188,6 +8235,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8197,6 +8247,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8206,9 +8259,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8221,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8371,30 +8442,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8533,12 +8580,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8657,6 +8698,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8738,13 +8782,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8753,16 +8797,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8771,6 +8821,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8783,31 +8839,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8879,15 +8935,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -9032,6 +9082,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9160,10 +9213,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9362,7 +9415,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9386,9 +9439,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9509,9 +9559,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9581,9 +9628,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9668,9 +9712,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9776,6 +9817,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9794,6 +9838,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9806,9 +9853,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9824,6 +9868,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9959,6 +10006,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -10076,7 +10126,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10199,10 +10249,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10259,6 +10306,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10313,6 +10363,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10472,6 +10531,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10543,6 +10605,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -11039,6 +11104,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -11105,6 +11173,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11144,16 +11215,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11228,9 +11317,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11258,9 +11344,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11288,6 +11371,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11456,13 +11542,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11471,7 +11557,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11797,7 +11895,11 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11901,6 +12003,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11916,15 +12024,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11976,6 +12081,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -12054,6 +12162,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -12099,6 +12210,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12291,12 +12405,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12391,18 +12499,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12433,9 +12529,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12661,6 +12754,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12985,10 +13081,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -13114,7 +13207,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13169,7 +13265,11 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13270,7 +13370,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13570,6 +13670,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13747,6 +13850,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -14045,9 +14151,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -14129,6 +14232,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -14144,6 +14250,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14171,9 +14280,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14186,6 +14292,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14270,6 +14382,13 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14504,9 +14623,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14700,6 +14816,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14953,6 +15072,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15184,6 +15306,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15244,6 +15369,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15820,6 +15948,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15859,6 +15990,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15874,9 +16008,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15946,10 +16077,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15997,6 +16128,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16306,6 +16440,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16474,12 +16611,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16708,7 +16839,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16771,9 +16902,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16876,7 +17013,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -17005,6 +17142,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -17089,7 +17229,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17154,9 +17294,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17178,6 +17315,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17202,6 +17342,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17214,6 +17357,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17790,6 +17936,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17850,6 +17999,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17904,6 +18056,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17922,6 +18077,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18435,6 +18599,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18538,6 +18705,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18577,6 +18747,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18760,6 +18933,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18835,9 +19011,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18937,6 +19110,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18955,6 +19134,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18970,6 +19152,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -19003,6 +19188,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19528,6 +19716,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19621,19 +19812,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19975,6 +20166,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20231,12 +20428,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20405,6 +20608,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -21042,6 +21248,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21171,6 +21380,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21258,9 +21470,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21384,6 +21593,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21393,6 +21605,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21654,6 +21869,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21699,6 +21917,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21771,6 +21992,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21927,34 +22157,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21981,6 +22205,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -22075,9 +22305,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22213,9 +22440,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22664,6 +22888,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22782,6 +23009,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22848,9 +23078,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -23161,6 +23388,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23275,7 +23505,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23290,6 +23520,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23485,6 +23718,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23543,9 +23779,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23787,18 +24020,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23850,9 +24080,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -24054,6 +24281,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -24066,6 +24296,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -24078,6 +24314,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -24093,6 +24332,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24208,15 +24450,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24265,9 +24507,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24295,6 +24534,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24304,6 +24546,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24373,6 +24618,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24448,9 +24723,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24631,14 +24903,18 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24682,9 +24958,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24943,6 +25216,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24964,6 +25240,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25471,6 +25750,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25591,6 +25873,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25708,6 +25993,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25810,9 +26098,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25957,6 +26251,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26233,12 +26530,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26248,9 +26551,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26278,6 +26578,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26569,6 +26872,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26869,6 +27175,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26884,6 +27193,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -27067,6 +27379,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27079,6 +27394,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27256,6 +27574,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27346,6 +27667,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27427,6 +27751,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27454,6 +27781,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27469,6 +27799,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27484,54 +27817,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27835,9 +28123,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27853,6 +28138,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27991,6 +28279,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -28003,6 +28294,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28189,9 +28483,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28225,6 +28516,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28312,15 +28606,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28806,6 +29100,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -29146,6 +29443,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr "Wybierz"
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -29155,9 +29455,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29236,15 +29533,15 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29597,9 +29894,6 @@ msgstr "Robotnicy"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr "Liczba Robotników online: %{active_runners_count}"
@@ -29624,6 +29918,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29633,6 +29936,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29684,6 +29990,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29705,6 +30014,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29744,6 +30071,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29807,6 +30137,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29837,15 +30170,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29942,9 +30266,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30295,6 +30616,9 @@ msgstr[3] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30520,16 +30844,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30580,6 +30907,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30598,6 +30928,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30667,6 +31000,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30688,9 +31024,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30724,6 +31057,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30733,6 +31075,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30763,6 +31108,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30886,6 +31234,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30925,10 +31276,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30946,15 +31297,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31213,9 +31558,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31315,9 +31657,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31372,9 +31711,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31465,9 +31801,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31501,10 +31834,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31570,6 +31903,13 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31917,9 +32257,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31986,6 +32323,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "Uwierzytelnianie karty inteligentnej nie powiodło się: brakuje nagłówka certyfikatu klienta."
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -32010,6 +32350,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -32019,6 +32362,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -32043,9 +32389,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32640,12 +32983,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32685,6 +33022,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "Określ swoją wiadomość, aby aktywować"
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -33183,7 +33523,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33282,18 +33622,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33315,9 +33649,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33330,12 +33661,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33351,30 +33676,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33402,9 +33712,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33417,9 +33724,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33462,6 +33766,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33648,6 +33955,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33672,6 +33982,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33684,6 +34003,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -34067,6 +34389,9 @@ msgstr[3] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -34136,6 +34461,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Połączenie upłynie po %{timeout}. W przypadku repozytoriów, którym zajmuje to dłużej, użyj kombinacji klonuj/pchnij."
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -34166,9 +34494,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "Wdrożenie tego zadania do %{environmentLink} nie powiodło się."
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34239,6 +34564,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34323,6 +34651,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34428,9 +34759,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "Zbiór danych pseudonimizera jest wyłączony. Po włączeniu GitLab uruchomi zadanie w tle, które będzie wytwarzać pseudonimiczne pliki CSV bazy danych GitLab, które zostaną przesłane do skonfigurowanego katalogu przechowywania obiektów."
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34464,9 +34792,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34626,6 +34951,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr "Nie ma jeszcze projektów udostępnionych w tej grupie"
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34710,6 +35038,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34896,9 +35227,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -35121,7 +35449,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35424,6 +35752,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35562,6 +35896,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35897,7 +36234,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35933,7 +36270,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -36119,6 +36456,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36212,7 +36564,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36582,6 +36934,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36666,6 +37021,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36999,6 +37357,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -37017,10 +37378,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -37032,6 +37393,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -37077,9 +37441,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -37119,10 +37480,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37272,6 +37633,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37302,6 +37666,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37368,6 +37735,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37719,6 +38092,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37728,6 +38104,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37773,10 +38158,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38442,6 +38839,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38637,6 +39037,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38646,9 +39049,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38661,6 +39061,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38671,9 +39074,6 @@ msgstr[3] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38980,10 +39380,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -39025,9 +39425,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -39094,6 +39491,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39250,9 +39650,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39352,9 +39749,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39442,6 +39836,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39451,9 +39848,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39908,28 +40302,55 @@ msgstr[3] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39941,6 +40362,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39953,9 +40377,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -40066,12 +40487,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -40099,6 +40526,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -40114,9 +40544,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40147,6 +40574,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -40183,9 +40613,22 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -40195,7 +40638,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40261,6 +40710,19 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40294,10 +40756,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40418,6 +40880,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40476,9 +40944,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40491,6 +40956,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40507,6 +40978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40543,6 +41017,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40747,6 +41224,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40907,6 +41390,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40940,6 +41426,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -41004,6 +41496,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -41038,9 +41533,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -41155,12 +41647,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -41176,6 +41662,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41224,6 +41713,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41299,6 +41794,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index dcdbeb00544..5ce2caf06e0 100644
--- a/locale/pt_BR/gitlab.po
+++ b/locale/pt_BR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pt-BR\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:18\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr " %{start} até %{end}"
@@ -40,25 +40,12 @@ msgstr " Tipo"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Você precisa fazer isso antes de %{grace_period_deadline}."
-msgid " and"
-msgstr " e"
-
msgid " and "
msgstr " e "
msgid " and %{sliced}"
msgstr " e %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " piorado em %d ponto"
-msgstr[1] " piorado em %d pontos"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " melhorado em %d ponto"
-msgstr[1] " melhorado em %d pontos"
-
msgid " or "
msgstr " ou "
@@ -86,18 +73,21 @@ msgstr "\"%{repository_name}\" tamanho (%{repository_size}) é maior que o limit
msgid "\"el\" parameter is required for createInstance()"
msgstr "O parâmetro \"el\" é necessário para createInstance()"
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr "#geral, #desenvolvimento"
msgid "%d Alert"
msgid_plural "%d Alerts"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Alerta"
+msgstr[1] "%d Alertas"
msgid "%d Alert:"
msgid_plural "%d Alerts:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Alerta:"
+msgstr[1] "%d Alertas:"
msgid "%d Approval"
msgid_plural "%d Approvals"
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] "%d commit,"
msgstr[1] "%d commits,"
-msgid "%d commits"
-msgstr "%d commits"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] "%d problema concluído"
@@ -463,10 +450,10 @@ msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or
msgstr "%{code_open}Protegido:%{code_close} Somente exposto a ramificações ou tags protegidas."
msgid "%{commit_author_link} authored %{commit_authored_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} criou %{commit_authored_timeago}"
msgid "%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} criou %{commit_authored_timeago} e %{commit_committer_avatar} %{commit_committer_link} criou o commit %{commit_committer_timeago}"
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} peso concluído"
@@ -563,10 +550,10 @@ msgid "%{docs_link_start}Learn about visibility levels.%{docs_link_end}"
msgstr ""
msgid "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}O que é armazenamento de arquivos grandes?%{docs_link_end}"
msgid "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}O que é autenticação de dois fatores?%{docs_link_end}"
msgid "%{due_date} (Past due)"
msgstr "%{due_date} (vencido)"
@@ -698,10 +685,10 @@ msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} indisponível"
msgid "%{learn_more_link}."
-msgstr ""
+msgstr "%{learn_more_link}."
msgid "%{lessThan} 1 hour"
-msgstr ""
+msgstr "%{lessThan} 1 hora"
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} é uma autoridade certificadora (CA) gratuita, automatizada e aberta, que emite certificados digitais para habilitar o HTTPS (SSL/TLS) para sites."
@@ -1055,6 +1042,9 @@ msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} permitem que você envi
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} permitem que você envie notificações para aplicativos da web em resposta a eventos de um grupo ou projeto. Recomendamos usar uma %{integrations_link_start}integração%{link_end} em vez de um webhook."
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr "%{wildcards_link_start}Caracteres curinga%{wildcards_link_end} como %{code_tag_start}v*%{code_tag_end} ou %{code_tag_start}*release%{code_tag_end} são suportados."
@@ -1138,9 +1128,15 @@ msgstr "(removido)"
msgid "(revoked)"
msgstr "(revogado)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr "(precisamos da sua senha atual para confirmar as alterações)"
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} mais"
@@ -1193,6 +1189,9 @@ msgstr[1] "- Eventos"
msgid "- Not available to run jobs."
msgstr "- Não disponível para executar tarefas."
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- Usuário"
@@ -1208,7 +1207,7 @@ msgid "."
msgstr "."
msgid "/"
-msgstr ""
+msgstr "/"
msgid "0 bytes"
msgstr "0 bytes"
@@ -1341,7 +1340,7 @@ msgid "1000+"
msgstr "1000+"
msgid "192.168.0.0/24"
-msgstr ""
+msgstr "192.168.0.0/24"
msgid "1st contribution!"
msgstr "1ª contribuição!"
@@ -1439,9 +1438,6 @@ msgstr "Um branch padrão não pode ser escolhido para um projeto vazio."
msgid "A deleted user"
msgstr "Um usuário excluído"
-msgid "A description is required"
-msgstr "é necessária uma descrição"
-
msgid "A different reason"
msgstr "Um motivo diferente"
@@ -1473,10 +1469,10 @@ msgid "A member of the abuse team will review your report as soon as possible."
msgstr "Um membro da equipe de abusos irá rever a sua avaliação assim que possível."
msgid "A merge request hasn't yet been merged"
-msgstr ""
+msgstr "Uma solicitação de mesclagem ainda não foi mesclada"
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
-msgstr "Um novo pipeline de Auto DevOps foi criado, vá para a página de Pipelines %{pipelines_link_start}%{pipelines_link_end} para obter detalhes"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
+msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
msgstr ""
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1530,7 +1529,7 @@ msgid "A user with write access to the source branch selected this option"
msgstr "Um usuário com permissão de escrita no branch de origem selecionou esta opção"
msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
-msgstr ""
+msgstr "AÇÃO NECESSÃRIA: Ocorreu um erro ao obter o certificado Let's Encrypt para o domínio de GitLab Pages \"%{domain}\""
msgid "API"
msgstr "API"
@@ -1728,7 +1727,7 @@ msgid "Access granted"
msgstr "Acesso concedido"
msgid "Access key ID"
-msgstr ""
+msgstr "Chave ID de acesso"
msgid "Access requests"
msgstr "Solicitação de acesso"
@@ -1737,7 +1736,7 @@ msgid "Access to '%{classification_label}' not allowed"
msgstr "Acesso a '%{classification_label}' não permitido"
msgid "Access tokens expire after 2 hours. A refresh token may be used at any time to generate a new access token. Non-expiring access tokens are deprecated. Clear this setting to enable backward compatibility."
-msgstr ""
+msgstr "Os tokens de acesso expiram após 2 horas. Um token de atualização deve ser usado a qualquer momento para gerar um novo token de acesso. Tokens de acesso sem expiração foram descontinuados. Desmarque esta opção para habilitar compatibilidade com versões anteriores."
msgid "AccessDropdown|Deploy Keys"
msgstr "Implementar chaves"
@@ -1850,6 +1849,9 @@ msgstr "Ações"
msgid "Activate Service Desk"
msgstr "Ativar Central de Serviços"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Ativo"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Adicionar um comentário geral para este %{noteableDisplayName}."
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "Adicionar um comentário geral para este %{noteable_name}."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Adicione uma homepage ao seu wiki que contenha informações sobre o seu projeto e o GitLab irá exibi-lo aqui ao invés desta mensagem."
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr "Adicionar chaves de implantação para conceder acesso de leitura/gravação a este repositório. %{link_start}O que são chaves de implantação?%{link_end}"
-msgid "Add domain"
-msgstr "Adicionar domínio"
-
msgid "Add email address"
msgstr "Adicionar endereço de e-mail"
@@ -2052,7 +2048,7 @@ msgid "Add new directory"
msgstr "Adicionar novo diretório"
msgid "Add new service account"
-msgstr ""
+msgstr "Adicionar nova conta de serviço"
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr "Adicionar à revisão"
msgid "Add to tree"
msgstr "Adicionar à árvore"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr "Adicionar gatilho"
@@ -2139,10 +2138,10 @@ msgid "AddMember|Invite email is invalid"
msgstr "E-mail de Convite é inválido"
msgid "AddMember|Invite limit of %{daily_invites} per day exceeded"
-msgstr ""
+msgstr "Excedido o limite de convite de %{daily_invites} por dia"
msgid "AddMember|No invite source provided."
-msgstr ""
+msgstr "Nenhuma fonte de convite fornecida."
msgid "AddMember|No users specified."
msgstr "Não há usuários especificados."
@@ -2292,7 +2291,7 @@ msgid "AdminArea|Features"
msgstr "Recursos"
msgid "AdminArea|Get security updates from GitLab and stay up to date"
-msgstr ""
+msgstr "Obtenha atualizações de segurança do GitLab e mantenha-se atualizado"
msgid "AdminArea|Groups"
msgstr "Grupos"
@@ -2334,10 +2333,10 @@ msgid "AdminArea|Reporter"
msgstr "Relatante"
msgid "AdminArea|Sign up for the GitLab Security Newsletter to get notified for security updates."
-msgstr ""
+msgstr "Inscreva-se no boletim informativo de segurança do GitLab para ser notificado sobre atualizações de segurança."
msgid "AdminArea|Sign up for the GitLab newsletter"
-msgstr ""
+msgstr "Inscreva-se no boletim informativo do GitLab"
msgid "AdminArea|Stop all jobs"
msgstr "Parar todas as tarefas"
@@ -2409,13 +2408,13 @@ msgid "AdminSettings|Disable public access to Pages sites"
msgstr "Desativar o acesso público ao Gitlab Pages"
msgid "AdminSettings|Display a banner on merge requests in projects with no pipelines to initiate steps to add a .gitlab-ci.yml file."
-msgstr ""
+msgstr "Mostre um banner em solicitações de mesclagem em projetos sem pipelines para iniciar etapas para adicionar um arquivo .gitlab-ci.yml."
msgid "AdminSettings|Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled. %{link_start}Learn more.%{link_end}"
msgstr "A verificação de domínio é uma medida de segurança essencial para sites GitLab públicos. Os usuários devem demonstrar que controlam um domínio antes de habilitá-lo. %{link_start}Saiba mais.%{link_end}"
msgid "AdminSettings|Enable pipeline suggestion banner"
-msgstr ""
+msgstr "Ativar banner de sugestão de pipeline"
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "Ativar executores compartilhados para novos projetos"
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "Administrador"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr "Aprovar usuário %{username}?"
msgid "AdminUsers|Approved users can:"
msgstr "Usuários aprovados podem:"
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,8 +2719,8 @@ msgstr "Reativar um usuário irá:"
msgid "AdminUsers|Regular"
msgstr "Regular"
-msgid "AdminUsers|Regular users have access to their groups and projects"
-msgstr "Os usuários regulares têm acesso a seus grupos e projetos"
+msgid "AdminUsers|Regular users have access to their groups and projects."
+msgstr ""
msgid "AdminUsers|Reject"
msgstr "Rejeitar"
@@ -2889,10 +2894,10 @@ msgid "Admin|Quarterly reconciliation will occur on %{qrtlyDate}"
msgstr "A reconciliação trimestral ocorrerá em %{qrtlyDate}"
msgid "Admin|The number of max seats in your namespace exceeds the number of seats in your subscription. On %{qrtlyDate}, quarterly reconciliation occurs and you are automatically billed a prorated amount for the overage. No action is needed from you. If you have a credit card on file, it will be charged. Otherwise, you will receive an invoice. For more information about the timing of the invoicing process, view the documentation."
-msgstr ""
+msgstr "O número máximo de licenças no seu espaço de nome excede o número de licenças da sua assinatura. Em %{qrtlyDate}, a reconciliação trimestral ocorrerá e você será cobrado automaticamente um valor rateado do excedente. Nenhuma ação sua é necessária. Se você possui um cartão de crédito registrado, haverá a cobrança. Caso contrário, você receberá uma fatura. Para mais informações do tempo do processo do faturamento, consulte a documentação."
msgid "Admin|The number of max users in your instance exceeds the number of users in your license. On %{qrtlyDate}, quarterly reconciliation occurs and you are automatically billed a prorated amount for the overage. No action is needed from you. If you have a credit card on file, it will be charged. Otherwise, you will receive an invoice. For more information about the timing of the invoicing process, view the documentation."
-msgstr ""
+msgstr "O número máximo de usuários na sua instância excede o número de usuários da sua licença. Em %{qrtlyDate}, a reconciliação trimestral ocorrerá e você será automaticamente cobrado por um valor rateado do excedente. Nenhuma ação sua é necessária. Se você possui cartão de crédito registrado, haverá a cobrança. Caso contrário, você receberá uma fatura. Para mais informações sobre o tempo do processo de faturamento, consulte a documentação."
msgid "Admin|View pending user approvals"
msgstr "Ver aprovações de usuários pendentes"
@@ -2931,7 +2936,7 @@ msgid "After you've reviewed these contribution guidelines, you'll be all set to
msgstr ""
msgid "Akismet"
-msgstr ""
+msgstr "Akismet"
msgid "Akismet API Key"
msgstr "Clave de API de Akismet"
@@ -3210,7 +3215,7 @@ msgid "AlertSettings|To create a custom mapping, enter an example payload from y
msgstr ""
msgid "AlertSettings|URL cannot be blank and must start with http: or https:."
-msgstr ""
+msgstr "URL não pode ficar em branco e deve começar com http: ou https :."
msgid "AlertSettings|Use the URL and authorization key below to configure how Prometheus sends alerts to GitLab. Review the %{linkStart}GitLab documentation%{linkEnd} to learn how to configure your endpoint."
msgstr ""
@@ -3294,7 +3299,7 @@ msgid "All (default)"
msgstr "Todos (padrão)"
msgid "All GitLab"
-msgstr ""
+msgstr "Todo o GitLab"
msgid "All Members"
msgstr "Todos os membros"
@@ -3329,7 +3334,7 @@ msgstr "Todos os conflitos de merge foram resolvidos. A merge request pode agora
msgid "All merge request dependencies have been merged"
msgstr "Todas as dependências da solicitação de mesclagem tiveram foram mescladas"
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr "Todos os usuários devem aceitar os termos de serviço e a política de
msgid "All users must have a name."
msgstr "Todos os usuários devem ter um nome."
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Permitir que \"%{group_name}\" adicione você"
@@ -3362,8 +3370,8 @@ msgstr "Permitir commits de membros que podem mesclar na ramificação de destin
msgid "Allow group owners to manage LDAP-related settings"
msgstr "Permitir que proprietários de grupos gerenciem configurações relacionadas ao LDAP"
-msgid "Allow non-administrators to access to the performance bar"
-msgstr "Permitir que não administradores de acessar a barra de desempenho"
+msgid "Allow non-administrators access to the performance bar"
+msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Permitir que apenas os protocolos selecionados sejam usados para acesso ao Git."
@@ -3411,7 +3419,7 @@ msgid "Allow this secondary node to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
-msgstr ""
+msgstr "Permitir o uso de funcionalidades da licença EE"
msgid "Allow users to dismiss the broadcast message"
msgstr ""
@@ -3429,7 +3437,7 @@ msgid "Allowed Geo IP"
msgstr "Geo IP permitido"
msgid "Allowed characters: +, 0-9, -, and spaces."
-msgstr ""
+msgstr "Caracteres permitidos: +, 0-9, - e espaços."
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
@@ -3597,19 +3605,22 @@ msgid "An error occurred while enabling Service Desk."
msgstr "Um erro ocorreu ao habilitar a Central de serviços."
msgid "An error occurred while fetching Markdown preview"
-msgstr ""
+msgstr "Um erro ocorreu ao obter a pré-visualização em Markdown"
msgid "An error occurred while fetching ancestors"
msgstr "Ocorreu um erro ao obter antepassados"
-msgid "An error occurred while fetching branches. Retry the search."
-msgstr "Ocorreu um erro ao obter as ramificações. Tente novamente a pesquisa."
+msgid "An error occurred while fetching branches. Retry the search."
+msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
-msgstr "Ocorreu um erro ao obter os commits. Tente novamente a pesquisa."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
+msgstr ""
msgid "An error occurred while fetching coverage reports."
msgstr "Ocorreu um erro ao obter relatórios de cobertura."
@@ -3720,7 +3731,7 @@ msgid "An error occurred while loading merge requests."
msgstr "Ocorreu um erro ao carregar as solicitações de mesclagem"
msgid "An error occurred while loading projects."
-msgstr ""
+msgstr "Um erro ocorreu durante o carregamento de projetos."
msgid "An error occurred while loading the Needs tab."
msgstr ""
@@ -3812,6 +3823,11 @@ msgstr "Ocorreu um erro ao recuperar projetos."
msgid "An error occurred while saving changes: %{error}"
msgstr "Ocorreu um erro ao salvar as alterações: %{error}"
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "Ocorreu um erro ao inscrever às notificações."
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr "Um domínio serverless a nível de instância já existe."
-
msgid "An issue already exists"
msgstr "Uma issue já existe"
@@ -4127,8 +4140,8 @@ msgstr "Aplicar"
msgid "Apply %d suggestion"
msgid_plural "Apply %d suggestions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Aplicar %d sugestão"
+msgstr[1] "Aplicar %d sugestões"
msgid "Apply a label"
msgstr "Aplicar uma etiqueta"
@@ -4210,12 +4223,18 @@ msgstr "Todas as verificações"
msgid "ApprovalRule|All severity levels"
msgstr "Todos os níveis de severidade"
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr "Aplique esta regra de aprovação para considerar apenas os níveis de severidade selecionados."
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr "Regras de aprovação"
@@ -4228,12 +4247,21 @@ msgstr "Tipo de aprovador"
msgid "ApprovalRule|Approvers"
msgstr "Aprovadores"
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr "Nome"
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr "Por favor, selecione pelo menos uma verificação de segurança"
msgid "ApprovalRule|Please select at least one severity level"
msgstr "Selecione pelo menos um nível de severidade"
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr "Nome da regra"
@@ -4261,6 +4298,9 @@ msgstr "Selecionar verificação"
msgid "ApprovalRule|Select severity levels"
msgstr "Selecione os níveis de severidade"
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr "Níveis de severidade"
@@ -4270,6 +4310,9 @@ msgstr "Ramificação de destino"
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr "Vulnerabilidades permitidas"
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "As configurações de solicitação de mesclagem foram atualizadas"
@@ -4301,7 +4344,7 @@ msgid "ApprovalSettings|This setting is configured at the instance level and can
msgstr "Esta configuração está caracterizada no nível de instância e pode ser somente alterada por um administrador."
msgid "ApprovalSettings|This setting is configured in %{groupName} and can only be changed by an administrator or group owner."
-msgstr ""
+msgstr "Essa configuração está configurada em %{groupName} e só pode ser alterada por um administrador ou proprietário do grupo."
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr "Você tem certeza? A remoção dessa chave GPG não afeta commits já as
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr "Tem certeza? O dispositivo será desconectado do GitLab e todas os tokens de lembrar-me revogados."
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr "Você tem certeza? Isso invalidará seus aplicativos registrados e dispositivos U2F / WebAuthn."
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr "Você tem certeza? Isso invalidará seus aplicativos registrados e dispositivos U2F."
-
msgid "Arrange charts"
msgstr "Organizar gráficos"
@@ -4630,7 +4667,7 @@ msgid "Assign to"
msgstr "Atribuir à"
msgid "Assign to commenting user"
-msgstr ""
+msgstr "Atribuir ao usuário que comentou"
msgid "Assign yourself to these issues"
msgstr "Atribuir-se a essas issues"
@@ -4783,6 +4820,9 @@ msgstr "Agosto"
msgid "Authenticate"
msgstr "Autenticar"
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr "Autenticar com GitHub"
@@ -4799,7 +4839,7 @@ msgid "Authenticated Git LFS request rate limit"
msgstr ""
msgid "Authenticated Git LFS requests"
-msgstr ""
+msgstr "Requisições de autenticação de Git LFS"
msgid "Authenticated web rate limit period in seconds"
msgstr ""
@@ -4901,7 +4941,7 @@ msgid "Auto-close referenced issues on default branch"
msgstr "Fechar automaticamente as issues referenciadas na ramificação padrão"
msgid "AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}"
-msgstr ""
+msgstr "%{auto_devops_start}Automatiza a construção, testes e implantação de%{auto_devops_end} seus aplicativos com base na sua integração contínua e configuração de entrega. %{quickstart_start}Como eu começo?%{quickstart_end}"
msgid "AutoDevOps|Auto DevOps"
msgstr "Auto DevOps"
@@ -4949,7 +4989,7 @@ msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered
msgstr "As reversões automáticas começam quando um alerta crítico é acionado. Se a última implantação bem-sucedida falhar em reverter automaticamente, ainda pode ser feito manualmente."
msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
-msgstr ""
+msgstr "Automaticamente retrocede para a última implementação bem-sucedida quando um problema crítico é detectado."
msgid "AutoRollback|Enable automatic rollbacks"
msgstr "Ativar reversões automáticas"
@@ -5210,7 +5250,7 @@ msgid "BillingPlans|If you would like to downgrade your plan please contact %{su
msgstr "Se você gostaria de diminuir o seu plano, por favor entre em contato com o %{support_link_start}Suporte ao Cliente%{support_link_end}."
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Ultimate."
-msgstr ""
+msgstr "Aprenda mais sobre cada plano lendo nossos %{faq_link}ou inicie uma avaliação gratuita de 30 dias do GitLab.com Ultimate."
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "Saiba mais sobre cada plano visitando nossa %{pricing_page_link}."
@@ -5240,7 +5280,7 @@ msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you
msgstr ""
msgid "BillingPlans|Your GitLab.com %{plan} trial will %{strong_open}expire after %{expiration_date}%{strong_close}. You can retain access to the %{plan} features by upgrading below."
-msgstr ""
+msgstr "Sua avaliação do GitLab.com %{plan} vai %{strong_open}expirar após %{expiration_date}%{strong_close}. Você pode manter o acesso aos recursos do %{plan} atualizando abaixo."
msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. You can restore access to the features at any time by upgrading below."
msgstr "Sua versão de avaliação do GitLab.com expirou em %{expiration_date}. Você pode restaurar o acesso a recursos a qualquer momento atualizando abaixo."
@@ -5415,23 +5455,26 @@ msgstr ""
msgid "Blog"
msgstr "Blog"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "O escopo do painel afeta quais issues são exibidas para qualquer um que visite este painel"
msgid "BoardNewEpic|Groups"
-msgstr ""
+msgstr "Grupos"
msgid "BoardNewEpic|Loading groups"
-msgstr ""
+msgstr "Carregando grupos"
msgid "BoardNewEpic|No matching results"
-msgstr ""
+msgstr "Nenhum resultado correspondente"
msgid "BoardNewEpic|Search groups"
-msgstr ""
+msgstr "Pesquisar grupos"
msgid "BoardNewEpic|Select a group"
-msgstr ""
+msgstr "Selecione um grupo"
msgid "BoardNewIssue|No matching results"
msgstr "Nenhum resultado correspondente"
@@ -5656,8 +5699,8 @@ msgstr "Todos"
msgid "Branches|Cancel, keep branch"
msgstr "Cancelar, manter ramificação"
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "Não foi possível encontrar o commit HEAD para essa branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "Comparar"
@@ -5767,6 +5810,9 @@ msgstr "Para confirmar, digite %{branch_name_confirmation}:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Para descartar as alterações locais e sobrescrever o branch com a versão upstream, exclua-o aqui e escolhe 'Atualize agora' acima."
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr "Sim, apagar o branch"
@@ -5858,7 +5904,7 @@ msgid "BulkImport|From source group"
msgstr "Do grupo de origem"
msgid "BulkImport|Group import history"
-msgstr ""
+msgstr "Histórico de importação de grupo"
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
@@ -5873,16 +5919,16 @@ msgid "BulkImport|Importing the group failed"
msgstr ""
msgid "BulkImport|Last imported to %{link}"
-msgstr ""
+msgstr "Última importação para %{link}"
msgid "BulkImport|Name already exists."
msgstr ""
msgid "BulkImport|New group"
-msgstr ""
+msgstr "Novo grupo"
msgid "BulkImport|No history is available"
-msgstr ""
+msgstr "Nenhum histórico disponível"
msgid "BulkImport|No parent"
msgstr ""
@@ -5897,7 +5943,7 @@ msgid "BulkImport|Showing %{start}-%{end} of %{total} matching filter \"%{filter
msgstr ""
msgid "BulkImport|Source group"
-msgstr ""
+msgstr "Grupo de fonte"
msgid "BulkImport|To new group"
msgstr "Para um novo grupo"
@@ -5909,7 +5955,7 @@ msgid "BulkImport|You have no groups to import"
msgstr "Você não tem grupos para importar"
msgid "BulkImport|Your imported groups will appear here."
-msgstr ""
+msgstr "Seus grupos importados aparecerão aqui."
msgid "BulkImport|expected an associated Group but has an associated Project"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr "Checar syntaxe de CI"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr "Configuração de CI validada, incluindo todas as configurações adicionadas com a palavra-chave %{codeStart}includes%{codeEnd}. %{link}"
-msgid "CI minutes"
-msgstr "Minutos de CI"
-
msgid "CI settings"
msgstr "Configurações de CI"
@@ -6034,10 +6077,10 @@ msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
-msgstr ""
+msgstr "Adicione um %{base_domain_link_start}domínio base%{link_end} para o seu %{kubernetes_cluster_link_start}cluster Kubernetes%{link_end} para que a sua estratégia de deploy funcione."
msgid "CICD|Add a %{kubernetes_cluster_link_start}Kubernetes cluster integration%{link_end} with a domain, or create an AUTO_DEVOPS_PLATFORM_TARGET CI variable."
-msgstr ""
+msgstr "Adicione uma %{kubernetes_cluster_link_start}integração de cluster Kubernetes%{link_end} com um domínio ou crie uma variável CI AUTO_DEVOPS_PLATFORM_TARGET."
msgid "CICD|Add an existing project to the scope"
msgstr "Adicionar um projeto existente ao escopo"
@@ -6049,10 +6092,10 @@ msgid "CICD|Automatic deployment to staging, manual deployment to production"
msgstr "Deploy automático para staging, deploy manual para produção"
msgid "CICD|Continuous deployment to production"
-msgstr "Deploy contínuo para produção"
+msgstr "Implantação contínua para produção"
msgid "CICD|Continuous deployment to production using timed incremental rollout"
-msgstr "Entrega contínua para a produção usando deploy incremental cronometrado"
+msgstr "Entrega contínua para a produção usando implantação incremental cronometrado"
msgid "CICD|Default to Auto DevOps pipeline"
msgstr "Padrão para o pipeline Auto DevOps"
@@ -6067,13 +6110,13 @@ msgid "CICD|Jobs"
msgstr "Tarefas"
msgid "CICD|Limit CI_JOB_TOKEN access"
-msgstr ""
+msgstr "Limite de acesso de CI_JOB_TOKEN"
msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
-msgstr ""
+msgstr "Selecione projetos que podem ser acessados por solicitações de API autenticadas com a variável CI_JOB_TOKEN deste projeto."
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file."
-msgstr ""
+msgstr "O pipeline Auto DevOps é executado por padrão em todos os projetos sem arquivo de configuração CI/CD."
msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr "O pipeline de Auto DevOps será executado se nenhum arquivo de configuração de CI alternativo for encontrado."
@@ -6154,7 +6197,7 @@ msgid "Can be manually deployed to"
msgstr "Pode ser implantado manualmente para"
msgid "Can be overridden in each project."
-msgstr ""
+msgstr "Pode ser substituído em cada projeto."
msgid "Can create groups:"
msgstr "Pode criar grupos:"
@@ -6261,9 +6304,6 @@ msgstr "Cancelando pré-visualização"
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr "Não pode ser atribuído a outros projetos."
-
msgid "Cannot be merged automatically"
msgstr "Não pode ser mesclado automaticamente"
@@ -6321,9 +6361,15 @@ msgstr "Não é possível ignorar a configuração de autenticação de dois fat
msgid "Capacity threshold"
msgstr "Limite de capacidade"
-msgid "CascadingSettings|Enforce for all subgroups"
+msgid "Card holder name"
msgstr ""
+msgid "Card number:"
+msgstr ""
+
+msgid "CascadingSettings|Enforce for all subgroups"
+msgstr "Aplicar para todos os subgrupos"
+
msgid "CascadingSettings|Setting enforced"
msgstr ""
@@ -6343,7 +6389,7 @@ msgid "CascadingSettings|cannot be nil when locking the attribute"
msgstr ""
msgid "Certain user content will be moved to a system-wide \"Ghost User\" in order to maintain content for posterity. For further information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
-msgstr ""
+msgstr "Certos conteúdos do usuário serão movidos para um \"Usuário fantasma\" de todo o sistema a fim de manter o conteúdo para a posteridade. Para mais informações, consulte a %{link_start}documentação de exclusão de conta do usuário.%{link_end}"
msgid "Certificate"
msgstr "Certificado"
@@ -6487,7 +6533,7 @@ msgid "Changes to the title have not been saved"
msgstr ""
msgid "Changing group URL can have unintended side effects."
-msgstr ""
+msgstr "Alterar a URL do grupo pode ter efeitos colaterais indesejados."
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -6523,7 +6569,7 @@ msgid "ChatMessage|Tag"
msgstr "Tag"
msgid "ChatMessage|and [%{count} more](%{pipeline_failed_jobs_url})"
-msgstr ""
+msgstr "e [%{count} mais](%{pipeline_failed_jobs_url})"
msgid "ChatMessage|has failed"
msgstr ""
@@ -6556,7 +6602,7 @@ msgid "Check the elasticsearch.log file to debug why the migration was halted an
msgstr ""
msgid "Check with your administrator."
-msgstr ""
+msgstr "Verifique com o seu administrador."
msgid "Check your Docker images for known vulnerabilities."
msgstr "Verifique suas imagens do Docker quanto a vulnerabilidades conhecidas."
@@ -6589,7 +6635,7 @@ msgid "Checkout"
msgstr ""
msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage per pack"
-msgstr ""
+msgstr "$%{selectedPlanPrice} por 10 GB de armazenamento por pacote"
msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
msgstr ""
@@ -6612,15 +6658,15 @@ msgid "Checkout|%{name}'s GitLab subscription"
msgstr "Assinatura do GitLab de %{name}"
msgid "Checkout|%{name}'s storage subscription"
-msgstr ""
+msgstr "Assinatura de armazenamento de %{name}"
msgid "Checkout|%{quantity} GB of storage"
-msgstr ""
+msgstr "%{quantity} GB de armazenamento"
msgid "Checkout|%{quantity} storage pack"
msgid_plural "Checkout|%{quantity} storage packs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{quantity} de pacote de armazenamento"
+msgstr[1] "%{quantity} de pacotes de armazenamento"
msgid "Checkout|%{selectedPlanText} plan"
msgstr "plano %{selectedPlanText}"
@@ -6649,6 +6695,9 @@ msgstr "Pacote de minutos de CI"
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr "Checkout"
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr "Editar"
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr "Expira em: %{expirationMonth}/%{expirationYear}"
@@ -6704,7 +6756,7 @@ msgid "Checkout|Failed to register credit card. Please try again."
msgstr ""
msgid "Checkout|GB"
-msgstr ""
+msgstr "GB"
msgid "Checkout|GitLab group"
msgstr "Grupo no GitLab"
@@ -6743,7 +6795,7 @@ msgid "Checkout|State"
msgstr "Estado"
msgid "Checkout|Storage packs"
-msgstr ""
+msgstr "Pacotes de armazenamento"
msgid "Checkout|Street address"
msgstr "Endereço da rua"
@@ -6767,7 +6819,7 @@ msgid "Checkout|Total minutes: %{quantity}"
msgstr "Minutos totais: %{quantity}"
msgid "Checkout|Total storage: %{quantity} GB"
-msgstr ""
+msgstr "Total de armazenamento: %{quantity} GB"
msgid "Checkout|Users"
msgstr "Usuários"
@@ -6788,16 +6840,19 @@ msgid "Checkout|Zip code"
msgstr "Código postal"
msgid "Checkout|a storage subscription"
-msgstr ""
+msgstr "uma assinatura de armazenamento"
msgid "Checkout|company or team"
msgstr "empresa ou equipe"
msgid "Checkout|minutes"
+msgstr "minutos"
+
+msgid "Checkout|x %{quantity} %{units} per pack"
msgstr ""
msgid "Checkout|x %{quantity} %{units} per pack ="
-msgstr ""
+msgstr "x %{quantity} %{units} por pacote="
msgid "Cherry-pick this commit"
msgstr "Cherry-pick esse commit"
@@ -6838,15 +6893,9 @@ msgstr "Escolha um modelo..."
msgid "Choose a type..."
msgstr "Escolha um tipo..."
-msgid "Choose any color"
-msgstr "Escolha qualquer cor"
-
msgid "Choose any color."
msgstr "Escolha qualquer cor."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr "Escolher arquivo…"
@@ -7154,7 +7203,7 @@ msgid "CloneIssue|Cannot clone issue to target project as it is pending deletion
msgstr ""
msgid "CloneIssue|Cannot clone issues of '%{issue_type}' type."
-msgstr ""
+msgstr "Não é possível clonar as issues do tipo '%{issue_type}"
msgid "Cloned this issue to %{path_to_project}."
msgstr "Clonou esta issue para %{path_to_project}."
@@ -7262,10 +7311,10 @@ msgid "ClusterAgents|Configuration"
msgstr "Configuração"
msgid "ClusterAgents|Connected"
-msgstr ""
+msgstr "Conectado"
msgid "ClusterAgents|Connection status"
-msgstr ""
+msgstr "Status da conexão"
msgid "ClusterAgents|Copy token"
msgstr "Copiar token"
@@ -7304,16 +7353,16 @@ msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr "Integrar com o GitLab Agent"
msgid "ClusterAgents|Last connected %{timeAgo}."
-msgstr ""
+msgstr "Última conexão %{timeAgo}."
msgid "ClusterAgents|Last contact"
-msgstr ""
+msgstr "Última conexão"
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr "Aprenda a criar um token de acesso do agente"
msgid "ClusterAgents|Make sure you are using a valid token."
-msgstr ""
+msgstr "Certifique-se de estar usando um token válido."
msgid "ClusterAgents|Name"
msgstr "Nome"
@@ -7322,10 +7371,10 @@ msgid "ClusterAgents|Never"
msgstr "Nunca"
msgid "ClusterAgents|Never connected"
-msgstr ""
+msgstr "Nunca conectado"
msgid "ClusterAgents|Not connected"
-msgstr ""
+msgstr "Não conectado"
msgid "ClusterAgents|Read more about getting started"
msgstr "Leia mais sobre como começar"
@@ -7436,7 +7485,7 @@ msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cl
msgstr ""
msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
-msgstr ""
+msgstr "Permitir ao GitLab consultar um Prometheus especificamente configurado no cluster para obter métricas."
msgid "ClusterIntegration|Amazon EKS"
msgstr "Amazon EKS"
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr "Verifique seu token"
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7694,7 +7743,7 @@ msgid "ClusterIntegration|If you do not wish to delete all associated GitLab res
msgstr "Se você não deseja excluir todos os recursos do GitLab associados, pode simplesmente remover a integração."
msgid "ClusterIntegration|In order to view the health of your cluster, you must first enable Prometheus in the Integrations tab."
-msgstr ""
+msgstr "Para visualizar a saúde do seu cluster, deve-se primeiro ative Prometheus na aba de Integrações."
msgid "ClusterIntegration|Instance cluster"
msgstr "Cluster de instância"
@@ -7930,6 +7979,9 @@ msgstr "Grupo de segurança"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Veja e edite os detalhes de seus cluster Kubernetes"
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr "Selecione um VPC para escolher um grupo de segurança"
@@ -7939,6 +7991,9 @@ msgstr "Selecione um VPC para escolher uma sub-rede"
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "Selecione uma rede para escolher uma sub-rede"
@@ -7948,9 +8003,24 @@ msgstr "Selecione uma região para escolher um par de chaves"
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr "Selecione uma região para escolher um VPC"
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr "Selecione uma zona para escolher uma rede"
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "Selecionar tipo de máquina"
@@ -7963,6 +8033,9 @@ msgstr "Selecione projeto e zona para escolher o tipo de máquina"
msgid "ClusterIntegration|Select project to choose zone"
msgstr "Selecione o projeto para escolher a zona"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8000,7 +8073,7 @@ msgid "ClusterIntegration|Subnets"
msgstr "Sub-redes"
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provisioned role, first create one on %{awsLinkStart}Amazon Web Services %{awsLinkEnd} using the above account and external IDs. %{moreInfoStart}More information%{moreInfoEnd}"
-msgstr ""
+msgstr "O Amazon Resource Name (ARN) associado com seu cargo. Se você não tem um cargo provisionado, primeiro crie um em %{awsLinkStart}Amazon Web Services %{awsLinkEnd} usando a conta acima e IDs externos. %{moreInfoStart}Mais informações%{moreInfoEnd}"
msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr "O certificado do Kubernetes usado para autenticar no cluster."
@@ -8113,30 +8186,6 @@ msgstr "atende aos requisitos"
msgid "ClusterIntegration|sign up"
msgstr "cadastrar"
-msgid "ClusterIntergation|Select a VPC"
-msgstr "Selecione um VPC"
-
-msgid "ClusterIntergation|Select a network"
-msgstr "Selecione uma rede"
-
-msgid "ClusterIntergation|Select a security group"
-msgstr "Selecione um grupo de segurança"
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr "Selecione uma sub-redes"
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr "Selecione uma sub-rede"
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr "Selecione um tipo de instância"
-
-msgid "ClusterIntergation|Select key pair"
-msgstr "Selecione o par de chaves"
-
-msgid "ClusterIntergation|Select service role"
-msgstr "Selecione a função de serviço"
-
msgid "Clusters|An error occurred while loading clusters"
msgstr "Ocorreu um erro ao carregar os clusters"
@@ -8234,7 +8283,7 @@ msgid "Collapse replies"
msgstr "Ocultar respostas"
msgid "Collapse settings section"
-msgstr ""
+msgstr "Fechar seção de configurações"
msgid "Collapse sidebar"
msgstr "Minimizar barra lateral"
@@ -8275,12 +8324,6 @@ msgstr "Comandos não foram aplicados"
msgid "Comment"
msgstr "Comentar"
-msgid "Comment & close %{noteable_name}"
-msgstr "Comentar e fechar %{noteable_name}"
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr "Comentar e reabrir %{noteable_name}"
-
msgid "Comment & resolve thread"
msgstr "Comentar e resolver discussão"
@@ -8397,6 +8440,9 @@ msgstr "Fórum da comunidade"
msgid "Company"
msgstr "Empresa"
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Comparar"
@@ -8478,31 +8524,37 @@ msgstr "Completo"
msgid "Completed"
msgstr "Completo"
-msgid "Compliance"
-msgstr "Conformidade"
-
-msgid "Compliance Dashboard"
-msgstr "Painel de conformidade"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
+msgstr ""
msgid "Compliance framework"
msgstr "Framework de conformidade"
+msgid "Compliance report"
+msgstr ""
+
msgid "ComplianceDashboard|created by:"
msgstr "Criado por"
msgid "ComplianceFrameworks|Add framework"
msgstr "Adicionar framework"
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr "Excluir framework de conformidade %{framework}"
msgid "ComplianceFrameworks|Delete framework"
msgstr "Excluir framework"
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr "Editar framework"
@@ -8523,32 +8581,32 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
-msgstr "Editar framework de conformidade"
+msgid "ComplianceFramework|Edit compliance framework"
+msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
-msgstr "Novo framework de conformidade"
+msgid "ComplianceFramework|New compliance framework"
+msgstr ""
msgid "Component"
msgstr "Componente"
@@ -8617,17 +8675,11 @@ msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeSt
msgstr "Configure um arquivo %{codeStart}.gitlab-webide.yml%{codeEnd} no %{codeStart}.gitLab%{codeEnd} para começar a usar o Terminal Web. %{helpStart}Saiba mais.%{helpEnd}"
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
-msgstr ""
-
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
+msgstr "Configure permissões avançadas, armazenamento de arquivos grandes e configurações de autenticação de dois fatores."
msgid "Configure existing installation"
msgstr "Configurar instalação existente"
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr "Configurar espelhamento de repositório."
@@ -8638,7 +8690,7 @@ msgid "Configure settings for Advanced Search with Elasticsearch."
msgstr ""
msgid "Configure specific limits for Files API requests that supersede the general user and IP rate limits."
-msgstr ""
+msgstr "Configure limites específicos para solicitações de API de arquivos que substituem o usuário geral e os limites de taxa de IP."
msgid "Configure specific limits for Git LFS requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8656,7 +8708,7 @@ msgid "Configure the way a user creates a new account."
msgstr "Configurar a forma como o usuário cria uma nova conta."
msgid "Configure via Merge Request"
-msgstr ""
+msgstr "Configurar via solicitação de mesclagem"
msgid "Configure which lists are shown for anyone who visits this board"
msgstr "Configure quais listas são mostradas para qualquer pessoa que visita este painel"
@@ -8728,7 +8780,7 @@ msgid "ConfluenceService|Your GitLab wiki is still available at %{wiki_link}. To
msgstr ""
msgid "Congratulations, your free trial is activated."
-msgstr ""
+msgstr "Parabéns, sua avaliação gratuita foi ativada."
msgid "Connect"
msgstr "Conectar"
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr "Contatar suporte"
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "Registro de contêiner"
@@ -8896,11 +8951,11 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr "Excluir tags selecionadas"
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
-msgstr "Exclusão desabilitada devido à falta de permissões ou insuficientes."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
msgstr ""
@@ -9096,7 +9151,7 @@ msgstr "A política de limpeza deste projeto para tags não está ativada."
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,14 +9175,11 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr "Você pode adicionar uma imagem a este registro com os seguintes comandos:"
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
-msgstr ""
+msgstr "Conteúdo analisado com %{link}."
msgid "ContentEditor|Table of Contents"
-msgstr ""
+msgstr "Ãndice"
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr "Copiar %{name}"
msgid "Copy %{protocol} clone URL"
msgstr "Copiar URL de Clone do %{protocol}"
-msgid "Copy %{proxy_url}"
-msgstr "Copiar %{proxy_url}"
-
msgid "Copy %{type}"
msgstr "Copiar %{type}"
@@ -9315,9 +9364,6 @@ msgstr "Copiar link"
msgid "Copy link to chart"
msgstr "Copiar link para o gráfico"
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr "Copiar referência"
@@ -9349,19 +9395,19 @@ msgid "Copy value"
msgstr "Copiar valor"
msgid "Corpus Management"
-msgstr ""
+msgstr "Gerenciamento de corpus"
msgid "Corpus Management|Are you sure you want to delete the corpus?"
-msgstr ""
+msgstr "Tem certeza de que deseja excluir o corpus?"
msgid "CorpusManagement|Actions"
msgstr "Ações"
msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
-msgstr ""
+msgstr "Corpus são usados em testes de fuzz como fonte de mutação para melhorar testes futuros."
msgid "CorpusManagement|Corpus name"
-msgstr ""
+msgstr "Nome do corpus"
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
@@ -9376,16 +9422,16 @@ msgid "CorpusManagement|Latest Job:"
msgstr "Última tarefa:"
msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
-msgstr ""
+msgstr "Corpus precisa ser um upload no formato *.zip. Máximo de 10GB"
msgid "CorpusManagement|New upload"
msgstr "Novo envio"
msgid "CorpusManagement|Not Set"
-msgstr ""
+msgstr "Não definido"
msgid "CorpusManagement|Target"
-msgstr ""
+msgstr "Alvo"
msgid "CorpusManagement|To use this corpus, edit the corresponding YAML file"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr "Não foi possível adicionar administradores como membros"
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr "Não foi possível autorizar o apelido do bate-papo. Tente novamente!"
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr "Cobertura"
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr "Criar %{type}"
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Criar Novo Diretório"
@@ -9540,9 +9589,6 @@ msgstr "Crie uma conta do GitLab primeiro e em seguida conecte-a à sua conta %{
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr "Criar um merge request"
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr "Criar uma nova issue"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr "Criar um novo repositório"
@@ -9580,7 +9629,7 @@ msgid "Create commit"
msgstr "Criar commit"
msgid "Create common files more quickly, and standardize their format."
-msgstr ""
+msgstr "Crie arquivos comuns mais rapidamente e padronize seu formato."
msgid "Create confidential merge request"
msgstr "Criar merge request confidencial"
@@ -9616,7 +9665,7 @@ msgid "Create issue"
msgstr "Criar issue"
msgid "Create issue to resolve all threads"
-msgstr ""
+msgstr "Crie uma issue para resolver todos os tópicos"
msgid "Create iteration"
msgstr "Criar interação"
@@ -9673,7 +9722,7 @@ msgid "Create new..."
msgstr "Criar novo..."
msgid "Create or import your first project"
-msgstr ""
+msgstr "Criar ou importar seu primeiro projeto"
msgid "Create project"
msgstr "Criar projeto"
@@ -9693,6 +9742,9 @@ msgstr "Criar snippet"
msgid "Create tag %{tagName}"
msgstr "Criar tag %{tagName}"
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr "Criar usuário"
@@ -9796,10 +9848,10 @@ msgid "CreateValueStreamForm|Plan stage start"
msgstr ""
msgid "CreateValueStreamForm|Please select a start event first"
-msgstr ""
+msgstr "Por favor, selecionar antes um evento de início"
msgid "CreateValueStreamForm|Please select an end event"
-msgstr ""
+msgstr "Por favor, selecionar um evento de término"
msgid "CreateValueStreamForm|Recover hidden stage"
msgstr "Recuperar estágio oculto"
@@ -9810,23 +9862,23 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr "Restaurar estágio"
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
-msgstr ""
+msgstr "Selecionar evento de término"
msgid "CreateValueStreamForm|Select start event"
-msgstr ""
+msgstr "Selecionar evento de início"
msgid "CreateValueStreamForm|Stage %{index}"
msgstr "Estágio %{index}"
msgid "CreateValueStreamForm|Stage name already exists"
-msgstr ""
+msgstr "Este nome de estágio já existe"
msgid "CreateValueStreamForm|Stage name is required"
-msgstr ""
+msgstr "O nome do estágio é obrigatório"
msgid "CreateValueStreamForm|Start event"
msgstr "Início do evento"
@@ -9844,7 +9896,7 @@ msgid "CreateValueStreamForm|Update stage"
msgstr "Estágio de atualização"
msgid "CreateValueStreamForm|Value Stream name"
-msgstr ""
+msgstr "Nome do fluxo de valor"
msgid "Created"
msgstr "Criado"
@@ -9933,11 +9985,8 @@ msgstr "Tokens de acesso pessoal"
msgid "CredentialsInventory|SSH Keys"
msgstr "Chaves SSH"
-msgid "Credit card validated at:"
-msgstr "Cartão de crédito validado em:"
-
-msgid "Credit card validated:"
-msgstr "Cartão de crédito validado:"
+msgid "Credit card:"
+msgstr ""
msgid "Critical vulnerabilities present"
msgstr "Vulnerabilidades críticas presentes"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr "Contador de vulnerabilidades"
@@ -10033,7 +10085,7 @@ msgid "Custom notification events"
msgstr "Eventos de notificação personalizados"
msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notificationLinkStart}notification emails%{notificationLinkEnd}."
-msgstr ""
+msgstr "Os níveis personalizados para as notificações são os mesmos dos níveis de participação. Através dos níveis personalizados de notificação você também receberá notificações para os eventos selecionados. Para mais informações, confira %{notificationLinkStart}e-mails de notificação%{notificationLinkEnd}."
msgid "Custom project templates"
msgstr "Modelos de projetos personalizados"
@@ -10047,6 +10099,15 @@ msgstr "Intervalo personalizado"
msgid "Custom range (UTC)"
msgstr "Intervalo personalizado (UTC)"
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr "Personalizado por um administrador"
@@ -10206,6 +10267,9 @@ msgstr "Dias para completar"
msgid "CycleAnalytics|Display chart filters"
msgstr "Mostrar filtros de gráficos"
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr "Nenhum estágios selecionados"
@@ -10232,10 +10296,10 @@ msgstr[0] "Mostrando %{subjectFilterText} e %{selectedLabelsCount} etiqueta"
msgstr[1] "Mostrando %{subjectFilterText} e %{selectedLabelsCount} etiquetas"
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
-msgstr ""
+msgstr "Mostrando dados para o grupo '%{groupName}' e %{selectedProjectCount} projetos de %{createdAfter} para %{createdBefore}"
msgid "CycleAnalytics|Showing data for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
-msgstr ""
+msgstr "Mostrando dados para o grupo '%{groupName}' de %{createdAfter} a %{createdBefore}"
msgid "CycleAnalytics|Stages"
msgstr "Estágios"
@@ -10273,6 +10337,9 @@ msgstr "Cconfiguração de DAST"
msgid "DAST Scans"
msgstr "Verificações de DAST"
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10358,7 +10425,7 @@ msgid "DastProfiles|Active"
msgstr "Ativo"
msgid "DastProfiles|Additional request headers (Optional)"
-msgstr ""
+msgstr "Cabeçalhos adicionais de requisição (Opcional)"
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
@@ -10442,10 +10509,10 @@ msgid "DastProfiles|Enable Authentication"
msgstr "Ativar autenticação"
msgid "DastProfiles|Enter URLs in a comma-separated list."
-msgstr ""
+msgstr "Insira as URLs em uma lista separada por vírgulas."
msgid "DastProfiles|Enter headers in a comma-separated list."
-msgstr ""
+msgstr "Insira os cabeçalhos em uma lista separada por vírgulas."
msgid "DastProfiles|Error Details"
msgstr "Detalhes do erro"
@@ -10469,7 +10536,7 @@ msgid "DastProfiles|Manage profiles"
msgstr "Gerenciar perfis"
msgid "DastProfiles|Manage site profiles"
-msgstr ""
+msgstr "Gerenciar perfis de site"
msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
msgstr ""
@@ -10547,7 +10614,7 @@ msgid "DastProfiles|Scanner name"
msgstr "Nome da verificação"
msgid "DastProfiles|Schedule"
-msgstr ""
+msgstr "Agendamento"
msgid "DastProfiles|Select branch"
msgstr "Selecionar branch"
@@ -10767,6 +10834,9 @@ msgstr "Seletor de data"
msgid "Date range"
msgstr "Intervalo de datas"
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10792,7 +10862,7 @@ msgid "Days to merge"
msgstr "Dias para mesclar"
msgid "Deactivate dormant users after 90 days of inactivity"
-msgstr ""
+msgstr "Desativar usuários inativos após 90 dias de inatividade"
msgid "Dear Administrator,"
msgstr "Caro Administrador,"
@@ -10833,14 +10903,17 @@ msgstr "Ramificação padrão"
msgid "Default branch and protected branches"
msgstr "Branch padrão e branches protegidos"
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr "Etiqueta de classificação padrão"
msgid "Default delayed project deletion"
-msgstr ""
+msgstr "Atraso padrão para exclusão de projeto"
msgid "Default deletion delay"
-msgstr ""
+msgstr "Atraso padrão para exclusão"
msgid "Default description template for issues"
msgstr "Modelo de descrição padrão para issues"
@@ -10855,13 +10928,13 @@ msgid "Default first day of the week in calendars and date pickers."
msgstr "Primeiro dia da semana padrão em calendários e selecionadores de data."
msgid "Default initial branch name"
-msgstr ""
+msgstr "Nome padrão da ramificação inicial"
msgid "Default project deletion protection"
msgstr ""
msgid "Default projects limit"
-msgstr ""
+msgstr "Limite padrão de projetos"
msgid "Default timeout"
msgstr "Tempo limite padrão"
@@ -10872,26 +10945,44 @@ msgstr "Padrão: Mapeie uma ID de conta do FogBugz para um nome completo"
msgid "DefaultBranchLabel|default"
msgstr "padrão"
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "Defina um padrão personalizado utilizando a sintaxe do cron"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr "Defina um padrão personalizado utilizando a sintaxe do cron"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
msgid "Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here."
-msgstr ""
+msgstr "Defina os ambientes na(s) fase(s) de implantação em %{code_open}.gitlab-ci.yml%{code_close} para acompanhar as implantações aqui."
msgid "Define how approval rules are applied to merge requests."
-msgstr ""
+msgstr "Defina como as regras de aprovação são aplicadas às solicitações de mesclagem."
msgid "Definition"
msgstr "Definição"
@@ -10936,7 +11027,7 @@ msgid "Delete Key"
msgstr "Excluir chave"
msgid "Delete Value Stream"
-msgstr ""
+msgstr "Excluir fluxo de valor"
msgid "Delete account"
msgstr "Excluir conta"
@@ -10956,9 +11047,6 @@ msgstr "Excluir comentário"
msgid "Delete corpus"
msgstr "Excluir corpus"
-msgid "Delete domain"
-msgstr "Excluir domínio"
-
msgid "Delete file"
msgstr "Excluir arquivo"
@@ -10986,9 +11074,6 @@ msgstr "Excluir linha"
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr "Excluir snippet"
@@ -11008,7 +11093,7 @@ msgid "Delete this attachment"
msgstr "Excluir este anexo"
msgid "Delete this epic and all descendants?"
-msgstr ""
+msgstr "Excluir este épico e todos os descendentes?"
msgid "Delete user list"
msgstr "Excluir lista de usuário"
@@ -11016,6 +11101,9 @@ msgstr "Excluir lista de usuário"
msgid "Delete variable"
msgstr "Excluir a variável"
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "Falha ao remover o repositório do projeto. Por favor, tente novamente ou entre em contato com o administrador."
@@ -11065,10 +11153,10 @@ msgid "Deleting"
msgstr "Excluíndo"
msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "Excluir um projeto o coloca em um estado de somente leitura até %{date}, nesse ponto o projeto será permanentemente excluído. Você tem certeza ABSOULTA?"
msgid "Deleting the project will delete its repository and all related resources, including issues and merge requests."
-msgstr ""
+msgstr "Apagar o projeto irá apagar o repositório e todos os itens relacionados, como issues e solicitações de mesclagem."
msgid "Deletion pending. This project will be deleted on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -11170,7 +11258,7 @@ msgid "Dependency List"
msgstr "Lista de dependências"
msgid "Dependency List has no entries"
-msgstr ""
+msgstr "A lista de dependências não tem entradas."
msgid "Dependency Proxy"
msgstr "Proxy de dependências"
@@ -11178,23 +11266,35 @@ msgstr "Proxy de dependências"
msgid "Dependency Scanning"
msgstr "Verificação de dependência"
-msgid "Dependency proxy"
-msgstr "Proxy de dependências"
+msgid "DependencyProxy|Cached %{time}"
+msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
-msgstr "A funcionalidade de proxy de dependências está limitada a grupos públicos por hora."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
+msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
msgstr ""
msgid "DependencyProxy|Dependency Proxy"
+msgstr "Proxy de dependências"
+
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
-msgstr "Alternar proxy de dependências"
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
+msgstr ""
msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr "%{current_design} de %{designs_count}"
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "Adicionar um design com o mesmo nome de arquivo substitui o arquivo por uma nova versão."
@@ -11615,6 +11717,12 @@ msgstr "Salvar comentário"
msgid "DesignManagement|Select all"
msgstr "Selecionar tudo"
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr "Enviar designs"
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr "Designs"
@@ -11690,6 +11795,9 @@ msgstr "Adoção por grupo"
msgid "DevopsAdoption|Adoption by subgroup"
msgstr "Adoção por subgrupo"
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr "Ocorreu um erro ao remover o grupo. Por favor, tente novamente."
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr "Sem resultados…"
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr "Não adotado"
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr "O grupo não tem subgrupos"
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11872,13 +11986,13 @@ msgstr "(base)"
msgid "Diffs|%d addition"
msgid_plural "Diffs|%d additions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d adição"
+msgstr[1] "%d adições"
msgid "Diffs|%d deletion"
msgid_plural "Diffs|%d deletions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d exclusão"
+msgstr[1] "%d exclusões"
msgid "Diffs|No file name available"
msgstr "Nenhum nome de arquivo disponível"
@@ -11891,14 +12005,14 @@ msgstr "Mostrar todas as linhas sem alterações"
msgid "Diffs|Showing %{dropdownStart}%{count} changed file%{dropdownEnd}"
msgid_plural "Diffs|Showing %{dropdownStart}%{count} changed files%{dropdownEnd}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Mostrando %{dropdownStart}%{count} arquivo alterado%{dropdownEnd}"
+msgstr[1] "Mostrando %{dropdownStart}%{count} arquivos alterados%{dropdownEnd}"
msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "Algo errado aconteceu ao buscar linhas de comparação."
msgid "Diffs|with %{additions} and %{deletions}"
-msgstr ""
+msgstr "com %{additions} e %{deletions}"
msgid "Direct member"
msgstr "Membro direto"
@@ -11999,12 +12113,6 @@ msgstr "Iniciar um teste grátis"
msgid "Discover|Upgrade now"
msgstr "Atualizar agora"
-msgid "Discuss a specific suggestion or question"
-msgstr "Discuta uma sugestão ou pergunta específica"
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr "Discuta uma sugestão ou pergunta específica que precisa ser resolvida"
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr "Discutir uma sugestão ou pergunta específica que precisa ser resolvida."
@@ -12097,18 +12205,6 @@ msgstr "Domínio"
msgid "Domain Name"
msgstr "Nome do domínio"
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr "Domínio foi criado com sucesso"
-
-msgid "Domain was successfully deleted."
-msgstr "Domínio foi excluído com sucesso"
-
-msgid "Domain was successfully updated."
-msgstr "Domínio foi atualizando com sucesso"
-
msgid "Don't have an account yet?"
msgstr "Ainda não possui uma conta?"
@@ -12139,9 +12235,6 @@ msgstr "Baixar %{format}"
msgid "Download %{format}:"
msgstr "Baixar %{format}:"
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr "Baixar (%{fileSizeReadable})"
@@ -12203,16 +12296,16 @@ msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr "Arraste seus projetos aqui ou %{linkStart}clique para enviar%{linkEnd}."
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
-msgstr ""
+msgstr "Solte ou %{linkStart}envie%{linkEnd} um arquivo para ser anexado"
msgid "Drop or %{linkStart}upload%{linkEnd} files to attach"
-msgstr ""
+msgstr "Solte ou %{linkStart}envie%{linkEnd} arquivos para serem anexados"
msgid "Drop your designs to start your upload."
msgstr ""
msgid "Drop your files to start your upload."
-msgstr ""
+msgstr "Solte os arquivos para começar o envio."
msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
msgstr ""
@@ -12341,13 +12434,13 @@ msgid "Edit in single-file editor"
msgstr ""
msgid "Edit inline"
-msgstr ""
+msgstr "Editar inline"
msgid "Edit issues"
msgstr "Editar issues"
msgid "Edit merge requests"
-msgstr ""
+msgstr "Editar solicitação de mesclagem"
msgid "Edit public deploy key"
msgstr "Editar chave de implantação pública"
@@ -12367,6 +12460,9 @@ msgstr "Editar essa versão"
msgid "Edit title and description"
msgstr "Editar título e descrição"
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr "Editar usuário: %{user_name}"
@@ -12425,7 +12521,7 @@ msgid "Elastic|None. Select projects to index."
msgstr "Nenhum. Selecione projetos para indexar."
msgid "Eligible users"
-msgstr ""
+msgstr "Usuários elegíveis"
msgid "Email"
msgstr "E-mail"
@@ -12437,7 +12533,7 @@ msgid "Email Notification"
msgstr "Notificação por e-mail"
msgid "Email a new %{name} to this project"
-msgstr ""
+msgstr "Enviar um novo %{name} para este projeto"
msgid "Email address to use for Support Desk"
msgstr "Endereço de e-mail para usar na central de serviços"
@@ -12557,7 +12653,7 @@ msgid "Enable"
msgstr "Ativar"
msgid "Enable Amazon EKS integration"
-msgstr ""
+msgstr "Ativar integração da Amazon EKS"
msgid "Enable Auto DevOps"
msgstr "Ativar Auto DevOps"
@@ -12593,7 +12689,7 @@ msgid "Enable SSL verification"
msgstr "Ativar verificação SSL"
msgid "Enable Service Ping"
-msgstr ""
+msgstr "Ativar o serviço de ping"
msgid "Enable Snowplow tracking"
msgstr ""
@@ -12626,7 +12722,7 @@ msgid "Enable authenticated Git LFS request rate limit"
msgstr ""
msgid "Enable authenticated web request rate limit"
-msgstr ""
+msgstr "Ativar o limite da taxa de solicitação das requisições web autenticada"
msgid "Enable authentication"
msgstr "Ativar autenticação"
@@ -12641,7 +12737,7 @@ msgid "Enable container expiration and retention policies for projects created e
msgstr ""
msgid "Enable delayed project deletion by default for newly-created groups."
-msgstr ""
+msgstr "Ativar a exclusão atrasada do projeto por padrão para grupos recém-criados."
msgid "Enable email notification"
msgstr "Ativar notificações por e-mail"
@@ -12689,19 +12785,16 @@ msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Ative ou desative a coleção de dados Pseudonymizer"
msgid "Enable or disable version check and Service Ping."
-msgstr ""
+msgstr "Ativar ou desativar a verificação de versão e o serviço de ping."
-msgid "Enable protected paths rate limit"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
-msgid "Enable proxy"
-msgstr "Habilitar proxy"
-
msgid "Enable reCAPTCHA"
msgstr "Ativar reCAPTCHA"
msgid "Enable reCAPTCHA for login."
-msgstr ""
+msgstr "Ativar reCAPTCHA para login."
msgid "Enable repository checks"
msgstr "Ativar as verificações de repositório"
@@ -12728,10 +12821,10 @@ msgid "Enable unauthenticated API request rate limit"
msgstr ""
msgid "Enable unauthenticated web request rate limit"
-msgstr ""
+msgstr "Ativar o limite da taxa de solicitação das requisições web não autenticadas"
msgid "Enable user deactivation emails"
-msgstr ""
+msgstr "Ativar e-mails de desativação do usuário"
msgid "Enable version check"
msgstr "Ativar verificação de versão"
@@ -12820,8 +12913,11 @@ msgstr "Digite um número"
msgid "Enter an integer number between 0 and 100"
msgstr "Digite um número inteiro entre 0 e 100"
-msgid "Enter an integer number number between 0 and 100"
-msgstr "Digite um número inteiro entre 0 e 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
+msgstr ""
msgid "Enter at least three characters to search"
msgstr "Digite pelo menos três caracteres para pesquisar"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr "Empresa"
msgid "Environment"
-msgstr "Ambiente"
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12887,7 +12985,7 @@ msgid "Environment is required for Stages::VariableEndpointInserter"
msgstr ""
msgid "Environment scope"
-msgstr ""
+msgstr "Escopo de ambiente"
msgid "Environment variable %{code_start}%{environment_variable}%{code_end} does not exist or is not pointing to a valid directory."
msgstr ""
@@ -12976,8 +13074,8 @@ msgstr "Ocorreu um erro ao parar o ambiente, por favor, tente novamente"
msgid "Environments|Are you sure you want to stop this environment?"
msgstr "Você tem certeza de que deseja parar este ambiente?"
-msgid "Environments|Auto stop in"
-msgstr "Parada automática"
+msgid "Environments|Auto stop"
+msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
msgstr ""
@@ -13001,7 +13099,7 @@ msgid "Environments|Delete environment"
msgstr "Excluir ambiente"
msgid "Environments|Deleting the '%{environmentName}' environment cannot be undone. Do you want to delete it anyway?"
-msgstr ""
+msgstr "A exclusão do '%{environmentName}' não pode ser desfeita. Você deseja excluí-lo mesmo assim?"
msgid "Environments|Deploy to..."
msgstr "Implantar para..."
@@ -13061,7 +13159,7 @@ msgid "Environments|Note that this action will stop the environment, but it will
msgstr "Observe que esta ação irá parar o ambiente mas %{emphasisStart}não%{emphasisEnd} terá efeito sobre qualquer deploy existente devido a \"ação de parar ambiente\" sendo definida no arquivo %{ciConfigLinkEnd}.gitlab-ci.yml%{ciConfigLinkStart}."
msgid "Environments|Open"
-msgstr ""
+msgstr "Abrir"
msgid "Environments|Open live environment"
msgstr "Abrir ambiente ao vivo"
@@ -13100,7 +13198,7 @@ msgid "Environments|Stop environment"
msgstr "Parar ambiente"
msgid "Environments|Stopping %{environmentName}"
-msgstr ""
+msgstr "Parar %{environmentName}"
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
@@ -13276,6 +13374,9 @@ msgstr "Erro ao criar epic"
msgid "Error creating label."
msgstr "Erro ao criar etiqueta."
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr "Erro ao criar uma nova iteração"
@@ -13406,7 +13507,7 @@ msgid "Error parsing CSV file. Please make sure it has"
msgstr ""
msgid "Error rendering Markdown preview"
-msgstr ""
+msgstr "Erro ao renderizar a pré-visualização do Markdown"
msgid "Error saving label update."
msgstr "Erro ao salvar alteração de etiqueta."
@@ -13453,6 +13554,9 @@ msgstr "Ocorreu um erro com Akismet. Por favor, verifique os logs para mais info
msgid "Error: %{error_message}"
msgstr "Erro: %{error_message}"
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13601,7 +13705,7 @@ msgid "EscalationPolicies|Select schedule"
msgstr "Selecionar agendamento"
msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
-msgstr ""
+msgstr "Configure as políticas de escalação para definir quem é paginado e quando, no caso de os primeiros usuários paginados não responderem."
msgid "EscalationPolicies|THEN %{doAction} %{scheduleOrUser}"
msgstr "ENTÃO %{doAction} %{scheduleOrUser}"
@@ -13658,13 +13762,13 @@ msgid "Every %{action} attempt has failed: %{job_error_message}. Please try agai
msgstr "Cada tentativa de %{action} falhou: %{job_error_message}. Por favor, tente novamente."
msgid "Every 3 months"
-msgstr ""
+msgstr "A cada 3 meses"
msgid "Every 3 months on the %{day} at %{time} %{timezone}"
msgstr ""
msgid "Every 6 months"
-msgstr ""
+msgstr "A cada 6 meses"
msgid "Every 6 months on the %{day} at %{time} %{timezone}"
msgstr ""
@@ -13705,10 +13809,10 @@ msgid "Every week on %{day} at %{time} %{timezone}"
msgstr ""
msgid "Every year"
-msgstr ""
+msgstr "Todos os anos"
msgid "Every year on %{day} at %{time} %{timezone}"
-msgstr ""
+msgstr "Todos os anos em %{day} às %{time} %{timezone}"
msgid "Everyone"
msgstr "Todos"
@@ -13749,14 +13853,11 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr "Exemplo: @sub\\.company\\.com$"
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr "Exemplo: Uso = consulta única. (Solicitada) / (Capacidade) = múltiplas consultas combinadas em uma fórmula."
-
msgid "Except policy:"
msgstr "Exceto da política:"
msgid "Exceptions"
-msgstr ""
+msgstr "Exceções"
msgid "Excess storage"
msgstr "Armazenamento em excesso"
@@ -13771,7 +13872,7 @@ msgid "Execution time"
msgstr "Tempo de execução"
msgid "Existing branch name, tag, or commit SHA"
-msgstr ""
+msgstr "Nome de ramificação, tag ou SHA do commit existente"
msgid "Existing projects may be moved into a group"
msgstr ""
@@ -13813,7 +13914,7 @@ msgid "Expand pipeline"
msgstr "Expandir pipeline"
msgid "Expand settings section"
-msgstr ""
+msgstr "Expandir seção de configurações"
msgid "Expand sidebar"
msgstr "Expandir barra lateral"
@@ -13833,6 +13934,9 @@ msgstr "Data de validade"
msgid "Expiration date (optional)"
msgstr "Data de expiração (opcional)"
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr "Expirado"
@@ -13848,6 +13952,9 @@ msgstr "Expira"
msgid "Expires in %{expires_at}"
msgstr "Expira em %{expires_at}"
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr "Expira:"
@@ -13875,9 +13982,6 @@ msgstr "Explorar grupos públicos"
msgid "Export"
msgstr "Exportar"
-msgid "Export %{name}"
-msgstr "Exportar %{name}"
-
msgid "Export %{requirementsCount} requirements?"
msgstr "Exportar %{requirementsCount} requisitos?"
@@ -13885,11 +13989,17 @@ msgid "Export as CSV"
msgstr "Exportar como CSV"
msgid "Export commit custody report"
-msgstr ""
+msgstr "Exportar relatório de custódia de commits"
msgid "Export group"
msgstr "Exportar grupo"
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "Exportar projeto"
@@ -13974,6 +14084,11 @@ msgstr "Falha ao adicionar uma reunião do Zoom"
msgid "Failed to apply commands."
msgstr "Falha ao aplicar comandos."
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr "Falha ao atribuir um revisor porque nenhum usuário foi encontrado."
@@ -14107,7 +14222,7 @@ msgid "Failed to load stacktrace."
msgstr "Falha ao carregar a stacktrace."
msgid "Failed to make repository read-only. %{reason}"
-msgstr ""
+msgstr "Falha ao tornar este repositório apenas leitura. %{reason}"
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
msgstr "Falha ao marcar esta issue como duplicada porque a issue referenciada não foi encontrada."
@@ -14208,9 +14323,6 @@ msgstr "Falha ao atualizar."
msgid "Failed to upload object map file"
msgstr "Falha ao enviar o arquivo de mapeamento de objeto"
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr "Falha"
@@ -14239,7 +14351,7 @@ msgid "Feature Flags"
msgstr "Feature flag"
msgid "Feature flag status"
-msgstr ""
+msgstr "Status de feature flag"
msgid "Feature flag was not removed."
msgstr "O Feature flag não foi removido."
@@ -14262,7 +14374,7 @@ msgid "FeatureFlags|%{percent} by user ID"
msgstr "%{percent} por ID do usuário"
msgid "FeatureFlags|%{percent} randomly"
-msgstr ""
+msgstr "%{percent} aleatoriamente"
msgid "FeatureFlags|* (All Environments)"
msgstr "* (Todos os Ambientes)"
@@ -14292,7 +14404,7 @@ msgid "FeatureFlags|Configure feature flags"
msgstr "Configurar feature flag"
msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
-msgstr ""
+msgstr "Considere usar a estratégia de \"rolagem percentual\" mais flexível."
msgid "FeatureFlags|Create feature flag"
msgstr "Criar feature flag"
@@ -14313,7 +14425,7 @@ msgid "FeatureFlags|Edit User List"
msgstr "Editar lista de usuários"
msgid "FeatureFlags|Enable features for specific users and environments by configuring feature flag strategies."
-msgstr ""
+msgstr "Ative funcionalidades para usuários e ambientes específicos configurando estratégias de feature flag."
msgid "FeatureFlags|Environment Specs"
msgstr "Especificações do Ambiente"
@@ -14322,16 +14434,16 @@ msgid "FeatureFlags|Feature Flag"
msgstr "Feature flag"
msgid "FeatureFlags|Feature Flag User List Details"
-msgstr ""
+msgstr "Detalhes da lista de usuários de feature flag"
msgid "FeatureFlags|Feature Flag User Lists"
-msgstr ""
+msgstr "Listas de usuários de feature flag"
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr "O comportamento de Feature flag é feito ao criar uma série de regras para definir o status de ambientes alvo. Um regra padrão de curinga %{codeStart}*%{codeEnd} para %{boldStart}Todos os Ambientes%{boldEnd} e você poderá adicionar quantas regras você precisar, escolhendo as especificações de ambiente abaixo. Você pode alternar o comportamento para cada uma de suas regras para configurá-los como %{boldStart}Ativo%{boldEnd} ou %{boldStart}Inativo%{boldEnd}."
msgid "FeatureFlags|Feature Flag has no strategies"
-msgstr ""
+msgstr "Feature Flag não tem estratégias"
msgid "FeatureFlags|Feature Flags"
msgstr "Feature flags"
@@ -14343,7 +14455,7 @@ msgid "FeatureFlags|Feature flags allow you to configure your code into differen
msgstr "Feature flags permitem que você configure o seu código em diferentes versões alterando dinamicamente determinada funcionalidade."
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
-msgstr ""
+msgstr "Limite de feature flags atingido (%{featureFlagsLimit}). Remova uma ou mais feature flags antes de adicionar novas."
msgid "FeatureFlags|Get started with feature flags"
msgstr "Começar a usar feature flags"
@@ -14382,7 +14494,7 @@ msgid "FeatureFlags|New Feature Flag"
msgstr "Nova feature flag"
msgid "FeatureFlags|New User List"
-msgstr ""
+msgstr "Nova lista de usuários"
msgid "FeatureFlags|New feature flag"
msgstr "Nova feature flag"
@@ -14391,7 +14503,7 @@ msgid "FeatureFlags|No user list selected"
msgstr "Nenhuma lista de usuários selecionada"
msgid "FeatureFlags|Percent of users"
-msgstr ""
+msgstr "Percentual de usuários"
msgid "FeatureFlags|Percent rollout"
msgstr ""
@@ -14402,9 +14514,12 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr "Remover"
-msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
+msgid "FeatureFlags|Search code references"
msgstr ""
+msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
+msgstr "Definir o nome do cliente de aplicação Unleash para o nome do ambiente onde sua aplicação é executada. Este valor é utilizado para corresponder os escopos do ambiente. Veja a %{linkStart}configuração exemplo do cliente%{linkEnd}."
+
msgid "FeatureFlags|Status"
msgstr "Status"
@@ -14439,10 +14554,10 @@ msgid "FeatureFlag|Select a user list"
msgstr "Selecionar uma lista de usuários"
msgid "FeatureFlag|Select the environment scope for this feature flag"
-msgstr ""
+msgstr "Selecione o escopo do ambiente para este feature flag"
msgid "FeatureFlag|There are no configured user lists"
-msgstr ""
+msgstr "Não há listas de usuários configuradas"
msgid "FeatureFlag|Type"
msgstr "Tipo"
@@ -14651,6 +14766,9 @@ msgid "Finished"
msgstr "Finalizado"
msgid "Finished at"
+msgstr "Finalizado em"
+
+msgid "First Name"
msgstr ""
msgid "First Seen"
@@ -14663,7 +14781,7 @@ msgid "First name"
msgstr "Primeiro nome"
msgid "First seen"
-msgstr ""
+msgstr "Visto a primeira vez"
msgid "Fixed burndown chart"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr "Erros encontrados em seu .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14918,7 +15039,7 @@ msgid "From merge request merge until deploy to production"
msgstr "Da solicitação de mesclagem até a implantação em produção"
msgid "Full"
-msgstr ""
+msgstr "Cheio"
msgid "Full name"
msgstr "Nome completo"
@@ -14944,6 +15065,9 @@ msgstr "Configurações gerais"
msgid "General pipelines"
msgstr "Pipelines gerais"
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr "Gerar etiquetas padrão"
@@ -14969,10 +15093,10 @@ msgid "Generic package file size in bytes"
msgstr ""
msgid "GenericReport|After"
-msgstr ""
+msgstr "Após"
msgid "GenericReport|Before"
-msgstr ""
+msgstr "Antes"
msgid "GenericReport|Diff"
msgstr ""
@@ -15350,7 +15474,7 @@ msgid "Geo|URL can't be blank"
msgstr ""
msgid "Geo|URL must be a valid url (ex: https://gitlab.com)"
-msgstr ""
+msgstr "O URL deve ser um URL válido (por exemplo: https://gitlab.com)"
msgid "Geo|Undefined"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr "Solicitação de conta do GitLab rejeitada"
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15533,10 +15660,10 @@ msgid "GitLab informs you if a new version is available."
msgstr ""
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
-msgstr ""
+msgstr "GitLab é uma plataforma completa de DevOps, entregue como uma única aplicação, mudando fundamentalmente o caminho de desenvolvimento, segurança e equipes de Ops colaboram"
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
-msgstr ""
+msgstr "GitLab é uma plataforma completa de DevOps, entregue como uma única aplicação, mudando fundamentalmente o caminho de%{br_tag}desenvolvimento, segurança e equipes de Ops colaboram"
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr "URL de metadados do GitLab"
msgid "GitLab project export"
msgstr "Exportação do projeto GitLab"
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr "Versão do GitLab"
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "O GitLab executará um trabalho em segundo plano que produzirá CSVs com pseudônimos do banco de dados do GitLab que serão carregados no diretório de armazenamento de objetos configurado."
-
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -15644,12 +15771,12 @@ msgid "GitLabPages|Save changes"
msgstr "Salvar alterações"
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
-msgstr ""
+msgstr "Ocorreu um erro ao obter o certificado Let's Encrypt para %{domain}. Para tentar novamente, visite os seus %{link_start}detalhes de domínio%{link_end}."
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
-msgstr "O suporte a domínios e certificados está desativado. Peça ao administrador do seu sistema para ativá-lo."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15671,7 +15798,7 @@ msgid "GitLabPages|Your Pages site is not configured yet. See the %{docs_link_st
msgstr ""
msgid "GitLabPages|Your pages are served under:"
-msgstr ""
+msgstr "Suas páginas são servidas sob:"
msgid "Gitaly Servers"
msgstr "Servidores Gitaly"
@@ -15697,6 +15824,9 @@ msgstr "Importação do Gitea"
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr "Obtenha o status para commits e pull requests."
@@ -15890,7 +16020,7 @@ msgid "Goal of the changes and what reviewers should be aware of"
msgstr ""
msgid "Google Cloud"
-msgstr ""
+msgstr "Google Cloud"
msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr "Avatar do grupo"
msgid "Group by"
msgstr "Agrupar por"
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr "Descrição do grupo (opcional)"
@@ -16103,7 +16236,7 @@ msgid "Group runners can be managed with the %{link}."
msgstr ""
msgid "Group sharing provides access to all group members (including members who inherited group membership from a parent group)."
-msgstr ""
+msgstr "O compartilhamento de grupo fornece acesso a todos os membros do grupo (incluindo membros que herdaram a associação ao grupo de um grupo pai)."
msgid "Group variables (inherited)"
msgstr "Variáveis de grupo (herdados)"
@@ -16154,10 +16287,10 @@ msgid "GroupImport|Unable to process group import file"
msgstr ""
msgid "GroupPage|Copy group ID"
-msgstr ""
+msgstr "Copiar ID do grupo"
msgid "GroupPage|Group ID: %{group_id}"
-msgstr ""
+msgstr "Id do grupo: %{group_id}"
msgid "GroupRoadmap|%{dateWord} – No end date"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "Alguma coisa deu errada ao recuperar epics"
@@ -16247,13 +16374,13 @@ msgid "GroupSAML|Default membership role"
msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group"
-msgstr ""
+msgstr "Ativar autenticação SAML para esse grupo"
msgid "GroupSAML|Enforce SSO-only authentication for Git and Dependency Proxy activity for this group"
msgstr ""
msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group"
-msgstr ""
+msgstr "Reforçar autenticação somente via SSO para atividades web deste grupo"
msgid "GroupSAML|Enforce users to have dedicated group-managed accounts for this group"
msgstr ""
@@ -16400,15 +16527,15 @@ msgid "GroupSettings|Cannot update the path because there are projects under thi
msgstr ""
msgid "GroupSettings|Change group URL"
-msgstr ""
+msgstr "Alterar URL do grupo"
msgid "GroupSettings|Changing group URL can have unintended side effects."
-msgstr ""
+msgstr "Alterar a URL do grupo pode ter efeitos colaterais indesejados."
msgid "GroupSettings|Compliance frameworks"
msgstr "Frameworks de conformidade"
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16421,13 +16548,13 @@ msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within thi
msgstr "Padrão para pipeline de Auto DevOps para todos os projetos dentro deste grupo"
msgid "GroupSettings|Disable email notifications"
-msgstr ""
+msgstr "Desativar notificações por e-mail"
msgid "GroupSettings|Disable group mentions"
-msgstr ""
+msgstr "Desabilitar menções de grupo"
msgid "GroupSettings|Enable delayed project deletion"
-msgstr ""
+msgstr "Ativar exclusão atrasada do projeto"
msgid "GroupSettings|Export group"
msgstr "Exportar grupo"
@@ -16451,7 +16578,7 @@ msgid "GroupSettings|Please choose a group URL with no special characters or spa
msgstr ""
msgid "GroupSettings|Prevent forking outside of the group"
-msgstr ""
+msgstr "Impedir fork fora do grupo"
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
@@ -16463,7 +16590,7 @@ msgid "GroupSettings|Prevent sharing a project within %{group} with other groups
msgstr "Bloquear compartilhamento de projetos do grupo %{group} com outros grupos"
msgid "GroupSettings|Prevents group members from being notified if the group is mentioned."
-msgstr ""
+msgstr "Impede que os membros do grupo sejam notificados se o grupo for mencionado."
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. Inherited by subgroups."
msgstr ""
@@ -16471,7 +16598,13 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
+msgstr "Selecione um subgrupo para usar como fonte para modelos de projeto personalizados para este grupo."
+
+msgid "GroupSettings|Select the project that contains your custom Insights file."
msgstr ""
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
@@ -16484,7 +16617,7 @@ msgid "GroupSettings|The default name for the initial branch of new repositories
msgstr ""
msgid "GroupSettings|The projects in this subgroup can be selected as templates for new projects created in the group. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Os projetos neste subgrupo podem ser selecionados como modelos para novos projetos criados no grupo. %{link_start}Saiba mais.%{link_end}"
msgid "GroupSettings|There was a problem updating Auto DevOps pipeline: %{error_messages}."
msgstr "Houve um problema ao atualizar o pipeline de Auto DevOps: %{error_messages}."
@@ -16508,7 +16641,7 @@ msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_e
msgstr ""
msgid "GroupSettings|What are badges?"
-msgstr ""
+msgstr "O que são selos?"
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16576,11 +16709,11 @@ msgstr "Nenhum grupo encontrado"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Você pode gerenciar permissões de membros e acesso do seu grupo para cada projeto no grupo."
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
-msgstr ""
+msgstr "Reúne projetos relacionados e concede aos membros acesso a vários projetos ao mesmo tempo."
msgid "GroupsNew|Connect instance"
msgstr "Conectar instância"
@@ -16705,6 +16838,9 @@ msgstr "Mensagem de cabeçalho"
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr "Título 1"
@@ -16721,7 +16857,7 @@ msgid "Headings"
msgstr "Títulos"
msgid "Health"
-msgstr ""
+msgstr "Saúde"
msgid "Health Check"
msgstr "Status de saúde"
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16837,7 +16973,7 @@ msgid "Hide shared projects"
msgstr "Ocultar projetos compartilhados"
msgid "Hide tooltips or popovers"
-msgstr ""
+msgstr "Ocultar dicas de ferramentas ou popovers"
msgid "Hide value"
msgid_plural "Hide values"
@@ -16848,25 +16984,22 @@ msgid "Hide values"
msgstr "Ocultar valores"
msgid "High or unknown vulnerabilities present"
-msgstr ""
-
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
+msgstr "Vulnerabilidades altas ou desconhecidas encontradas"
msgid "Highest role:"
msgstr "Função mais alta:"
msgid "HighlightBar|Alert events:"
-msgstr ""
+msgstr "Eventos de Alerta:"
msgid "HighlightBar|Alert start time:"
-msgstr ""
+msgstr "Tempo de início do alerta:"
msgid "HighlightBar|Original alert:"
-msgstr ""
+msgstr "Alerta original:"
msgid "HighlightBar|Time to SLA:"
-msgstr ""
+msgstr "Tempo para SLA:"
msgid "History"
msgstr "Histórico"
@@ -16874,9 +17007,12 @@ msgstr "Histórico"
msgid "History of authentications"
msgstr "Histórico de autenticações"
-msgid "Home page URL"
+msgid "Holder name:"
msgstr ""
+msgid "Home page URL"
+msgstr "URL da página inicial"
+
msgid "Homepage"
msgstr "Página inicial"
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr "Hora (UTC)"
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr "Manutenção"
@@ -16908,6 +17047,9 @@ msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "Manutenção, exportação, caminho, transferência, remoção e arquivamento."
msgid "How do I configure Akismet?"
+msgstr "Como eu configuro o Akismet?"
+
+msgid "How do I configure authentication using the GitLab database?"
msgstr ""
msgid "How do I configure it?"
@@ -17037,13 +17179,13 @@ msgid "IP Address"
msgstr "Endereço IP"
msgid "IP address expiration time"
-msgstr ""
+msgstr "Tempo de expiração do endereço de IP"
msgid "IP address restrictions"
-msgstr ""
+msgstr "Restrições de endereço de IP"
msgid "IP addresses per user"
-msgstr ""
+msgstr "Endereços de IP por usuário"
msgid "IP subnet restriction only allowed for top-level groups"
msgstr ""
@@ -17121,7 +17263,7 @@ msgid "If you did not initiate this change, please contact your administrator im
msgstr ""
msgid "If you did not perform this request, you can safely ignore this email."
-msgstr ""
+msgstr "Se você não realizou essa solicitação, pode ignorar este e-mail com segurança."
msgid "If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
msgstr ""
@@ -17224,7 +17366,7 @@ msgid "Import from Jira"
msgstr "Importar do Jira"
msgid "Import group"
-msgstr ""
+msgstr "Importar grupo"
msgid "Import group from file"
msgstr "Importar grupo de arquivo"
@@ -17233,7 +17375,7 @@ msgid "Import groups"
msgstr "Importar grupos"
msgid "Import history"
-msgstr ""
+msgstr "Importar histórico"
msgid "Import in progress"
msgstr "Importação em andamento"
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr "Você tem um minuto?"
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr "Fácil"
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17601,7 +17752,7 @@ msgid "InProductMarketing|Invite your colleagues to join in less than one minute
msgstr ""
msgid "InProductMarketing|Invite your colleagues today"
-msgstr ""
+msgstr "Convide seus colegas hoje mesmo"
msgid "InProductMarketing|Invite your team in less than 60 seconds"
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -17667,7 +17827,7 @@ msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit ca
msgstr ""
msgid "InProductMarketing|Start a trial"
-msgstr ""
+msgstr "Inicie uma avaliação"
msgid "InProductMarketing|Start by %{performance_link}"
msgstr ""
@@ -17682,7 +17842,7 @@ msgid "InProductMarketing|Start your trial now!"
msgstr ""
msgid "InProductMarketing|Start your trial today to experience single application success and discover all the features of GitLab Ultimate for free!"
-msgstr ""
+msgstr "Comece sua avaliação hoje para experimentar o sucesso de um único aplicativo e descubra todos os recursos do GitLab Ultimate gratuitamente!"
msgid "InProductMarketing|Stop wondering and use GitLab to answer questions like:"
msgstr ""
@@ -17856,7 +18016,7 @@ msgid "IncidentManagement|All"
msgstr ""
msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
-msgstr ""
+msgstr "Todos os alertas promovidos para incidentes serão exibidos automaticamente na lista. Você também pode criar um novo incidente usando o botão abaixo."
msgid "IncidentManagement|Assignees"
msgstr "Responsáveis"
@@ -17955,7 +18115,7 @@ msgid "IncidentSettings|Time limit must be a multiple of 15 minutes."
msgstr "O limite de tempo deve ser um múltiplo de 15 minutos."
msgid "IncidentSettings|Time limit must be a valid number."
-msgstr ""
+msgstr "O limite de tempo deve ser um número válido."
msgid "IncidentSettings|Time limit must be greater than 0."
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr "Herdado:"
msgid "Inline"
msgstr "Em linha"
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr "Insira as chaves do host manualmente"
@@ -18138,13 +18301,13 @@ msgid "Insert a %{rows}x%{cols} table."
msgstr "Inserir uma tabela %{rows}x%{cols}."
msgid "Insert a code block"
-msgstr ""
+msgstr "Inserir um bloco de código-fonte"
msgid "Insert a quote"
msgstr "Inserir uma citação"
msgid "Insert a video"
-msgstr ""
+msgstr "Inserir um vídeo"
msgid "Insert an image"
msgstr "Inserir uma imagem"
@@ -18162,7 +18325,7 @@ msgid "Insert image"
msgstr "Inserir imagem"
msgid "Insert inline code"
-msgstr ""
+msgstr "Inserir código-fonte embutido"
msgid "Insert link"
msgstr "Inserir link"
@@ -18177,7 +18340,7 @@ msgid "Insert suggestion"
msgstr "Inserir sugestão"
msgid "Insert video"
-msgstr ""
+msgstr "Inserir vídeo"
msgid "Insights"
msgstr "Insights"
@@ -18203,7 +18366,7 @@ msgstr[0] "Instância"
msgstr[1] "Instâncias"
msgid "Instance Configuration"
-msgstr ""
+msgstr "Configuração de Instância"
msgid "Instance access request"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr "Visão geral da instância"
msgid "Insufficient permissions"
msgstr "Permissões insuficientes"
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr "Integração"
@@ -18242,7 +18408,7 @@ msgid "Integrations|%{integration} settings saved and active."
msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
-msgstr ""
+msgstr "configurações salvas de %{integration}, mas não ativas."
msgid "Integrations|Active integrations"
msgstr "Integrações ativas"
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr "Ocorreu um erro ao carregar projetos usando configurações personalizadas."
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr "Limitações do navegador"
@@ -18284,7 +18453,7 @@ msgid "Integrations|Create new issue in Jira"
msgstr "Criar novo problema no Jira"
msgid "Integrations|Create new issue in ZenTao"
-msgstr ""
+msgstr "Criar nova issue no ZenTao"
msgid "Integrations|Default settings are inherited from the group level."
msgstr ""
@@ -18380,7 +18549,7 @@ msgid "Integrations|Search Jira issues"
msgstr "Pesquisar issues do Jira"
msgid "Integrations|Search ZenTao issues"
-msgstr ""
+msgstr "Pesquisar issues do ZenTao"
msgid "Integrations|Send notifications about project events to Unify Circuit."
msgstr "Envie notificações sobre eventos de projeto para Unify Circuit."
@@ -18448,6 +18617,9 @@ msgstr "Interno - O projeto pode ser acessado por qualquer usuário entrado, exc
msgid "Internal URL (optional)"
msgstr "URL interno (opcional)"
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr "Usuários internos"
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr "Tipo de política inválido"
-msgid "Invalid query"
-msgstr "Consulta inválida"
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18554,7 +18723,7 @@ msgid "Investigate vulnerability: %{title}"
msgstr ""
msgid "Invisible Captcha"
-msgstr ""
+msgstr "Captcha Invisível"
msgid "Invisible Captcha helps prevent the creation of spam accounts. It adds a honeypot field and time-sensitive form submission to the account signup form."
msgstr ""
@@ -18593,19 +18762,19 @@ msgid "Invite members"
msgstr "Convidar membros"
msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
-msgstr ""
+msgstr "%{inviter} convidou você para participar em %{project_or_group_name} %{project_or_group} como %{role}"
msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
-msgstr ""
+msgstr "%{inviter} convidou você para participar em %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} como %{role}"
msgid "InviteEmail|%{project_or_group} details"
-msgstr ""
+msgstr "Detalhes de %{project_or_group}"
msgid "InviteEmail|Groups assemble related projects together and grant members access to several projects at once."
-msgstr ""
+msgstr "Grupos reúnem projetos relacionados e concedem aos membros acesso a vários projetos ao mesmo tempo."
msgid "InviteEmail|Join now"
-msgstr "Juntar agora"
+msgstr "Participar agora"
msgid "InviteEmail|Join your team on GitLab! %{inviter} invited you to %{project_or_group_name}"
msgstr ""
@@ -18617,32 +18786,41 @@ msgid "InviteEmail|Projects are used to host and collaborate on code, track issu
msgstr ""
msgid "InviteEmail|What's it about?"
-msgstr ""
+msgstr "Sobre o que é?"
msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr "Você foi convidado para se juntar-se a %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} como %{role}"
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr "Você foi convidado a participar em %{project_or_group_name} %{project_or_group} como %{role}"
+
+msgid "InviteEmail|You were assigned the following tasks:"
msgstr ""
-msgid "InviteMembersBanner|Collaborate with your team"
+msgid "InviteEmail|and has assigned you the following tasks:"
msgstr ""
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr "Colabore com sua equipe"
+
msgid "InviteMembersBanner|Invite your colleagues"
-msgstr ""
+msgstr "Convide seus colegas"
msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
-msgstr ""
+msgstr "Percebemos que você não convidou ninguém para este grupo. Convide seus colegas para que você possa discutir problemas, colaborar em solicitações de mesclagem e compartilhar seu conhecimento."
msgid "InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions"
-msgstr ""
+msgstr "%{linkStart}Leia mais%{linkEnd} sobre as permissões de cargos"
msgid "InviteMembersModal|Access expiration date (optional)"
-msgstr ""
+msgstr "Data de expiração do acesso (opcional)"
msgid "InviteMembersModal|Cancel"
msgstr "Cancelar"
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr "Configurar funcionalidades de segurança"
msgid "InviteMembersModal|Contribute to the codebase"
msgstr "Contribua com a base de código"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr "Membro do GitLab ou endereço de e-mail"
@@ -18691,6 +18872,9 @@ msgstr "Selecione membros ou digite o endereço de e-mail"
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -18722,7 +18906,7 @@ msgid "InviteMember|Invite Members (optional)"
msgstr "Convidar membros (opcional)"
msgid "InviteMember|Invite another member"
-msgstr ""
+msgstr "Convidar outro membro"
msgid "InviteMember|Invite members"
msgstr ""
@@ -18821,13 +19005,13 @@ msgid "Is blocked by"
msgstr "Está bloqueado por"
msgid "Is this GitLab trial for your company?"
-msgstr ""
+msgstr "Este é uma avaliação do GitLab para sua empresa?"
msgid "Is using license seat:"
msgstr "Está usando o assento de licença:"
msgid "Is using seat"
-msgstr ""
+msgstr "Está usando licença"
msgid "IssuableStatus|Closed"
msgstr "Fechada"
@@ -19013,7 +19197,7 @@ msgid "Issues"
msgstr "Issues"
msgid "Issues I've created"
-msgstr ""
+msgstr "Issues que eu criei"
msgid "Issues Rate Limits"
msgstr ""
@@ -19022,7 +19206,7 @@ msgid "Issues and merge requests"
msgstr "Issues e solicitações de mesclagem"
msgid "Issues assigned to me"
-msgstr ""
+msgstr "Issues atribuídas a mim"
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr "Issues podem ser bugs, tarefas ou ideias a serem discutidas. Além disso, issues são pesquisáveis e filtráveis."
@@ -19136,7 +19320,7 @@ msgid "Iterations|Create cadence"
msgstr ""
msgid "Iterations|Create iteration"
-msgstr ""
+msgstr "Criar iteração"
msgid "Iterations|Delete cadence"
msgstr ""
@@ -19145,7 +19329,7 @@ msgid "Iterations|Delete iteration cadence?"
msgstr ""
msgid "Iterations|Delete iteration?"
-msgstr ""
+msgstr "Excluir iteração?"
msgid "Iterations|Duration"
msgstr "Duração"
@@ -19181,7 +19365,7 @@ msgid "Iterations|New iteration cadence"
msgstr "Nova cadência de iteração"
msgid "Iterations|No closed iterations."
-msgstr ""
+msgstr "Sem iterações fechadas."
msgid "Iterations|No iteration cadences to show."
msgstr "Sem cadências de iteração para mostrar."
@@ -19190,7 +19374,7 @@ msgid "Iterations|No iterations in cadence."
msgstr "Nenhuma integrações em cadência"
msgid "Iterations|No open iterations."
-msgstr ""
+msgstr "Sem iterações abertas."
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr "Data de início"
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19223,7 +19410,7 @@ msgid "Iterations|This will delete the cadence as well as all of the iterations
msgstr ""
msgid "Iterations|This will remove the iteration from any issues that are assigned to it."
-msgstr ""
+msgstr "Isso removerá a iteração de quaisquer issues atribuídos a ela."
msgid "Iterations|Title"
msgstr "Título"
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19625,7 +19812,7 @@ msgid "Job|The artifacts will be removed"
msgstr "Os artefatos serão removidos"
msgid "Job|These artifacts are the latest. They will not be deleted (even if expired) until newer artifacts are available."
-msgstr ""
+msgstr "Esses artefatos são os mais recentes. Eles não serão excluídos (mesmo se expirados) até que os artefatos mais novos estejam disponíveis."
msgid "Job|This job failed because the necessary resources were not successfully created."
msgstr "Esta tarefa falhou porque os recursos necessários não foram criados com sucesso."
@@ -19663,6 +19850,12 @@ msgstr "com"
msgid "Join Zoom meeting"
msgstr "Participe da reunião com Zoom"
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr "Acessado pela última vez em"
msgid "Last Activity"
msgstr "Última atividade"
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "Último Pipeline"
msgid "Last Seen"
msgstr "Visto pela última vez"
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr "Último uso"
@@ -20091,6 +20290,9 @@ msgstr "Saiba mais sobre como fazer deploy para um cluster"
msgid "Learn more about group-level project templates"
msgstr "Saiba mais sobre os modelos de projeto de nível de grupo"
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20140,7 +20342,7 @@ msgid "LearnGitLab|GitLab works best as a team. Invite your colleague to enjoy a
msgstr ""
msgid "LearnGitLab|Invite your colleagues"
-msgstr ""
+msgstr "Convide seus colegas"
msgid "LearnGitLab|Learn GitLab"
msgstr ""
@@ -20179,7 +20381,7 @@ msgid "LearnGitLab|Set-up CI/CD"
msgstr ""
msgid "LearnGitLab|Start a free Ultimate trial"
-msgstr ""
+msgstr "Comece uma avaliação gratuita do Ultimate"
msgid "LearnGitLab|Submit a merge request"
msgstr ""
@@ -20260,7 +20462,7 @@ msgid "LicenseCompliance|Add license and related policy"
msgstr ""
msgid "LicenseCompliance|Add license policy"
-msgstr ""
+msgstr "Adicionar política de licença"
msgid "LicenseCompliance|Allow"
msgstr "Permitir"
@@ -20442,7 +20644,7 @@ msgstr[0] "Limitado a mostrar %d evento, no máximo"
msgstr[1] "Limitado a mostrar %d eventos, no máximo"
msgid "Limiting mode"
-msgstr ""
+msgstr "Modo de limitação"
msgid "Line changes"
msgstr "Alterações de linha"
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr "Torna esta issue confidencial."
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr "Gerenciar recursos do IDE Web."
@@ -20843,6 +21048,9 @@ msgstr "Adicionar texto em itálico (%{modifier_key}I)"
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,11 +21138,8 @@ msgstr "Cargo max"
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr "MaxBuilds"
-
msgid "Maximum 20 characters"
-msgstr ""
+msgstr "Máximo de 20 caracteres"
msgid "Maximum Conan package file size in bytes"
msgstr ""
@@ -20982,7 +21187,7 @@ msgid "Maximum capacity"
msgstr "Capacidade máxima"
msgid "Maximum character limit - %{limit}"
-msgstr ""
+msgstr "Limite máximo de caracteres - %{limit}"
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr "Tamanho máximo de arquivo para pacote npm em bytes"
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21063,6 +21271,9 @@ msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr "Número máximo de espelhos que podem estar sincronizando ao mesmo tempo."
msgid "Maximum number of projects."
+msgstr "Número máximo de projetos."
+
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
msgstr ""
msgid "Maximum number of unique IP addresses per user."
@@ -21090,7 +21301,7 @@ msgid "Maximum push size (MB)"
msgstr "Tamanho máximo de push (MB)"
msgid "Maximum requests per minute"
-msgstr ""
+msgstr "Requisições máximas por minuto"
msgid "Maximum running slices"
msgstr ""
@@ -21156,7 +21367,7 @@ msgid "Member since:"
msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
-msgstr ""
+msgstr "%{member_name} convidou você para participar do GitLab"
msgid "MemberInviteEmail|I've invited you to join me in GitLab"
msgstr ""
@@ -21303,13 +21514,13 @@ msgid "Merge Conflicts"
msgstr "Conflitos de mesclagem"
msgid "Merge Request"
-msgstr "Solicitações de mesclagem"
+msgstr "Solicitação de mesclagem"
msgid "Merge Request Analytics"
msgstr ""
msgid "Merge Requests"
-msgstr "Solicitações de merge"
+msgstr "Solicitações de mesclagem"
msgid "Merge Requests created"
msgstr "Solicitações de mesclagem criadas"
@@ -21326,6 +21537,9 @@ msgstr "Mesclar automaticamente (%{strategy})"
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr "Pipelines"
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr "Métricas e perfis"
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr "UTC (Tempo Universal Coordenado)"
msgid "MetricsSettings|User's local timezone"
msgstr "Fuso horário local do usuário"
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr "Expandir painel"
msgid "Metrics|For grouping similar metrics"
msgstr "Para agrupar métricas similares"
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr "Ver documentação"
msgid "Metrics|View logs"
msgstr "Ver registros"
-msgid "Metrics|View runbook - %{label}"
-msgstr "Ver runbook - %{label}"
-
msgid "Metrics|Y-axis label"
msgstr "Rótulo do eixo Y"
@@ -21917,7 +22137,7 @@ msgid "Mi"
msgstr "Mi"
msgid "Middleman project with Static Site Editor support"
-msgstr ""
+msgstr "Projeto intermediário com suporte ao editor de sites estáticos"
msgid "Migrated %{success_count}/%{total_count} files."
msgstr "Migrado %{success_count}/%{total_count} arquivos."
@@ -22117,7 +22337,7 @@ msgid "Mirroring settings were successfully updated. The project is being update
msgstr ""
msgid "Mirroring was successfully disabled."
-msgstr ""
+msgstr "O espelhamento foi desativado com sucesso."
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr "Espelhamento só estará disponível se a funcionalidade estiver incluída no plano do grupo ou usuário selecionado."
@@ -22332,6 +22552,9 @@ msgstr "Meu grupo incrível"
msgid "My company or team"
msgstr "Minha empresa ou equipe"
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,119 +22671,119 @@ msgstr "Necessita de atenção"
msgid "Network"
msgstr "Rede"
-msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgid "Network:"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr "%{ifLabelStart}se%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and está entrando de um%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
-msgstr ""
+msgstr "%{ifLabelStart}se%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}e é saída para um%{directionLabelEnd} %{rule} %{portsLabelStart}em%{portsLabelEnd} %{ports}"
msgid "NetworkPolicies|%{labelStart}And%{labelEnd} %{spanStart}send an Alert to GitLab.%{spanEnd}"
-msgstr ""
+msgstr "%{labelStart}E%{labelEnd} %{spanStart}enviar um alerta para Gitlab.%{spanEnd}"
msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
-msgstr ""
+msgstr "%{labelStart}Então%{labelEnd} %{action} %{spanStart}o tráfego da rede.%{spanEnd}"
msgid "NetworkPolicies|%{number} selected"
-msgstr ""
+msgstr "%{number} selecionado(s)"
msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
-msgstr ""
+msgstr "%{strongOpen}todos%{strongClose} pods"
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
-msgstr ""
+msgstr "%{strongOpen}qualquer%{strongClose} port"
msgid "NetworkPolicies|.yaml"
-msgstr ""
+msgstr ".yaml"
msgid "NetworkPolicies|.yaml mode"
-msgstr ""
+msgstr "Modo .yaml"
msgid "NetworkPolicies|Add alert"
-msgstr ""
+msgstr "Adicionar alerta"
msgid "NetworkPolicies|Alerts are intended to be selectively used for a limited number of events that are potentially concerning and warrant a manual review. Alerts should not be used as a substitute for a SIEM or a logging tool. High volume alerts are likely to be dropped so as to preserve the stability of GitLab's integration with Kubernetes."
msgstr ""
msgid "NetworkPolicies|All selected"
-msgstr ""
+msgstr "Todos selecionados"
msgid "NetworkPolicies|Allow"
msgstr "Permitir"
msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
-msgstr ""
+msgstr "Permite todo o tráfego de entrada para %{selector} de %{ruleSelector} em %{ports}"
msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
-msgstr ""
+msgstr "Permite todo o tráfego de saída de %{selector} para %{ruleSelector} em %{ports}"
msgid "NetworkPolicies|Are you sure you want to delete this policy? This action cannot be undone."
msgstr ""
msgid "NetworkPolicies|Create policy"
-msgstr ""
+msgstr "Criar política"
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
msgid "NetworkPolicies|Delete policy"
-msgstr ""
+msgstr "Excluir política"
msgid "NetworkPolicies|Delete policy: %{policy}"
-msgstr ""
+msgstr "Excluir política: %{policy}"
msgid "NetworkPolicies|Deny all traffic"
-msgstr ""
+msgstr "Negar todo o tráfego"
msgid "NetworkPolicies|Edit policy"
msgstr "Editar política"
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
-msgstr ""
+msgstr "O ambiente não possui plataforma de implantação"
msgid "NetworkPolicies|IP/subnet"
-msgstr ""
+msgstr "IP/sub-redes"
msgid "NetworkPolicies|Invalid or empty policy"
-msgstr ""
+msgstr "Política inválida ou vazia"
msgid "NetworkPolicies|Invalid or unsupported policy kind"
msgstr ""
msgid "NetworkPolicies|Kubernetes error: %{error}"
-msgstr ""
+msgstr "Erro de Kubernetes: %{error}"
msgid "NetworkPolicies|Network"
-msgstr ""
+msgstr "Rede"
msgid "NetworkPolicies|Network Policies can be used to limit which network traffic is allowed between containers inside the cluster."
-msgstr ""
+msgstr "Políticas de rede podem ser usadas para limitar o tráfego de rede permitido entre os contêineres dentro do cluster."
msgid "NetworkPolicies|Network policy can be created after the environment is loaded successfully."
msgstr ""
msgid "NetworkPolicies|Network traffic"
-msgstr ""
+msgstr "Tráfego de rede"
msgid "NetworkPolicies|None selected"
-msgstr ""
+msgstr "Nenhum selecionado"
msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
-msgstr ""
+msgstr "Por favor %{installLinkStart}instale%{installLinkEnd} e %{configureLinkStart}Configure um agente Kubernetes para este projeto%{configureLinkEnd} para ativar alertas."
msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
msgstr ""
msgid "NetworkPolicies|Policy definition"
-msgstr ""
+msgstr "Definição de política"
msgid "NetworkPolicies|Rule"
-msgstr ""
+msgstr "Regra"
msgid "NetworkPolicies|Rule mode"
-msgstr ""
+msgstr "Modo de regra"
msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
msgstr ""
@@ -22575,16 +22798,16 @@ msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
-msgstr ""
+msgstr "O tráfego que não corresponder a nenhuma regra será bloqueado."
msgid "NetworkPolicies|all DNS names"
-msgstr ""
+msgstr "todos os nomes de DNS"
msgid "NetworkPolicies|all IP addresses"
msgstr "todos os endereços de IP"
msgid "NetworkPolicies|any pod"
-msgstr ""
+msgstr "qualquer pod"
msgid "NetworkPolicies|any port"
msgstr "qualquer porta"
@@ -22593,31 +22816,31 @@ msgid "NetworkPolicies|domain name"
msgstr "nome de domínio"
msgid "NetworkPolicies|entity"
-msgstr ""
+msgstr "entidade"
msgid "NetworkPolicies|inbound to"
-msgstr ""
+msgstr "entrada para"
msgid "NetworkPolicies|nowhere"
msgstr ""
msgid "NetworkPolicies|outbound from"
-msgstr ""
+msgstr "saída para"
msgid "NetworkPolicies|pod with labels"
msgstr "pod com etiquetas"
msgid "NetworkPolicies|pods %{pods}"
-msgstr ""
+msgstr "pods %{pods}"
msgid "NetworkPolicies|pods with labels"
msgstr "pods com etiquetas"
msgid "NetworkPolicies|ports %{ports}"
-msgstr ""
+msgstr "portas %{ports}"
msgid "NetworkPolicies|ports/protocols"
-msgstr ""
+msgstr "portas/protocolos"
msgid "NetworkPolicy|Policy"
msgstr "Política"
@@ -22659,7 +22882,7 @@ msgid "New Group"
msgstr "Novo Grupo"
msgid "New Group Name"
-msgstr "Novo nobre do grupo"
+msgstr "Nome do novo grupo"
msgid "New Identity"
msgstr "Nova identidade"
@@ -22757,7 +22980,7 @@ msgid "New issue"
msgstr "Nova issue"
msgid "New issue in %{project}"
-msgstr ""
+msgstr "Nova issue em %{project}"
msgid "New issue title"
msgstr "Titulo da nova issue"
@@ -22825,6 +23048,9 @@ msgstr "Nova tag"
msgid "New test case"
msgstr "Novo caso de teste"
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr "Novos usuários definidos para uso externo"
@@ -22939,7 +23165,7 @@ msgstr "Nenhum frameworks de conformidade em uso"
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr "Nenhum frameworks de conformidade em uso. Crie um na seção %{link} em Configurações de grupo."
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr "Nenhum contribuidor"
msgid "No contributions were found"
msgstr "Nenhuma contribuição foi encontrada"
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr "Não é necessário cartão de crédito."
@@ -23102,7 +23331,7 @@ msgid "No ref selected"
msgstr ""
msgid "No related merge requests found."
-msgstr ""
+msgstr "Nenhuma solicitação de mesclagem relacionada foi encontrada."
msgid "No repository"
msgstr "Nenhum repositório"
@@ -23149,6 +23378,9 @@ msgstr "Nenhum gatilho existe ainda. Use o formulário acima para criar um."
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr "Nenhum webhooks encontrados, adicione um no formulário acima."
@@ -23205,9 +23437,6 @@ msgstr "Não disponível para projetos privados"
msgid "Not available for protected branches"
msgstr "Não disponível para ramificações protegidas"
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr "Não confidencial"
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr "Número de LOCs por commit"
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr "Número de commits"
msgid "Number of commits per MR"
msgstr "Número de commits por MR"
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr "Mais antigo primeiro"
msgid "OmniAuth"
msgstr "OmniAuth"
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23694,7 +23917,7 @@ msgid "OnDemandScans|Edit on-demand DAST scan"
msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
-msgstr ""
+msgstr "Por exemplo: testa a página de login para injeções de SQL"
msgid "OnDemandScans|Manage DAST scans"
msgstr "Gerenciar verificações de DAST"
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,23 +23946,32 @@ msgstr "Não há nenhum perfil ainda. Para criar uma nova verificação, você p
msgid "OnDemandScans|On-demand Scans"
msgstr "Verificação sob demanda"
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
msgid "OnDemandScans|Save and run scan"
-msgstr ""
+msgstr "Salvar verificação e executar"
msgid "OnDemandScans|Save scan"
-msgstr ""
+msgstr "Salvar verificação"
msgid "OnDemandScans|Scan name"
msgstr "Nome da verificação"
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr "Perfil de verificação"
msgid "OnDemandScans|Schedule scan"
-msgstr ""
+msgstr "Verificação agendada"
msgid "OnDemandScans|Select one of the existing profiles"
msgstr ""
@@ -23745,6 +23980,9 @@ msgid "OnDemandScans|Site profile"
msgstr "Perfil de site"
msgid "OnDemandScans|Start time"
+msgstr "Hora de início"
+
+msgid "OnDemandScans|Target"
msgstr ""
msgid "OnDemandScans|Use existing scanner profile"
@@ -23860,15 +24098,15 @@ msgstr "Abrir seleção"
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr "Abrir erros"
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr "Abrir na visualização de arquivos"
@@ -23917,9 +24155,6 @@ msgstr "Operação não permitida"
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr "A operação expirou. Verifique os registros do pod para %{pod_name} para mais detalhes."
-msgid "Operations"
-msgstr "Operações"
-
msgid "Operations Dashboard"
msgstr "Painel de operações"
@@ -23947,6 +24182,9 @@ msgstr "Opcional"
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "Opcionalmente, você pode %{link_to_customize} como os endereços de e-mail e nomes de usuários do FogBugz são importados para o GitLab."
@@ -23956,6 +24194,9 @@ msgstr "Opções"
msgid "Or you can choose one of the suggested colors below"
msgstr "Ou você pode escolher uma das cores sugeridas abaixo"
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -23978,7 +24219,7 @@ msgid "Other visibility settings have been disabled by the administrator."
msgstr "Outras configurações de visibilidade foram desabilitadas pelo administrador."
msgid "Otherwise, click the link below to complete the process."
-msgstr ""
+msgstr "Caso contrário, clique no link abaixo para concluir o processo."
msgid "Otherwise, click the link below to complete the process:"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr "Propriedade de:"
msgid "Owner"
msgstr "Proprietário"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr "Registro de pacote"
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24182,7 +24450,7 @@ msgid "PackageRegistry|Copy require package include"
msgstr ""
msgid "PackageRegistry|Copy target SHA"
-msgstr ""
+msgstr "Copiar SHA de destino"
msgid "PackageRegistry|Copy yarn command"
msgstr "Copiar comando yarn"
@@ -24251,7 +24519,7 @@ msgid "PackageRegistry|Install package version"
msgstr ""
msgid "PackageRegistry|Instance-level"
-msgstr ""
+msgstr "Nível de instância"
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr "Comando NuGet"
msgid "PackageRegistry|Package Registry"
msgstr "Registro de pacote"
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24299,7 +24569,7 @@ msgid "PackageRegistry|Pip Command"
msgstr ""
msgid "PackageRegistry|Project-level"
-msgstr ""
+msgstr "Nível do projeto"
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
msgstr "Publique e compartilhe pacotes para uma variedade de gerenciadores de pacotes comuns. %{docLinkStart}Mais informações%{docLinkEnd}"
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24368,7 +24635,7 @@ msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
msgid "PackageRegistry|Target SHA: %{sha}"
-msgstr ""
+msgstr "SHA de destino: %{sha}"
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -24539,16 +24806,16 @@ msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "PasswordPrompt|Confirm password"
-msgstr ""
+msgstr "Confirmar senha"
msgid "PasswordPrompt|Confirm password to continue"
-msgstr ""
+msgstr "Confirmar senha para continuar"
msgid "PasswordPrompt|Password is required"
-msgstr ""
+msgstr "A senha é necessária"
msgid "PasswordPrompt|Please enter your password to confirm"
-msgstr ""
+msgstr "Por favor, digite sua senha para confirmar"
msgid "Passwords should be unique and not used for any other sites or services."
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr "Caminho:"
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr "Pausar"
@@ -24616,6 +24886,9 @@ msgstr "Pendente"
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -24632,7 +24905,7 @@ msgid "Percentage"
msgstr ""
msgid "Perform advanced options such as changing path, transferring, exporting, or removing the group."
-msgstr ""
+msgstr "Execute opções avançadas, como alterar o caminho, transferir, exportar ou remover o grupo."
msgid "Perform code reviews and enhance collaboration with merge requests."
msgstr ""
@@ -24665,7 +24938,7 @@ msgid "PerformanceBar|First Contentful Paint"
msgstr ""
msgid "PerformanceBar|Flamegraph with mode:"
-msgstr ""
+msgstr "Flamegraph com modo:"
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -24701,13 +24974,13 @@ msgid "PerformanceBar|Trace"
msgstr ""
msgid "PerformanceBar|cpu"
-msgstr ""
+msgstr "cpu"
msgid "PerformanceBar|object"
-msgstr ""
+msgstr "objeto"
msgid "PerformanceBar|wall"
-msgstr ""
+msgstr "parede"
msgid "Period in seconds"
msgstr "Período em segundos"
@@ -24800,7 +25073,7 @@ msgid "Pipeline status emails"
msgstr "E-mails de status do pipeline"
msgid "Pipeline subscriptions"
-msgstr ""
+msgstr "Assinaturas de pipeline"
msgid "Pipeline subscriptions trigger a new pipeline on the default branch of this project when a pipeline successfully completes for a new tag on the %{default_branch_docs} of the subscribed project."
msgstr ""
@@ -24938,31 +25211,31 @@ msgid "PipelineSchedules|Variables"
msgstr "Variáveis"
msgid "PipelineSource|API"
-msgstr ""
+msgstr "API"
msgid "PipelineSource|Chat"
-msgstr ""
+msgstr "Bate-papo"
msgid "PipelineSource|External"
-msgstr ""
+msgstr "Externo"
msgid "PipelineSource|External Pull Request"
-msgstr ""
+msgstr "requisição de pull externa"
msgid "PipelineSource|Merge Request"
-msgstr ""
+msgstr "Solicitação de mesclagem"
msgid "PipelineSource|On-Demand DAST Scan"
-msgstr ""
+msgstr "Verificação sob demanda de DAST"
msgid "PipelineSource|On-Demand DAST Validation"
-msgstr ""
+msgstr "Verificação DAST sob demanda"
msgid "PipelineSource|Parent Pipeline"
-msgstr ""
+msgstr "Pipeline pai"
msgid "PipelineSource|Pipeline"
-msgstr ""
+msgstr "Pipeline"
msgid "PipelineSource|Push"
msgstr ""
@@ -24971,13 +25244,13 @@ msgid "PipelineSource|Schedule"
msgstr ""
msgid "PipelineSource|Trigger"
-msgstr ""
+msgstr "Gatilho"
msgid "PipelineSource|Web"
-msgstr ""
+msgstr "Web"
msgid "PipelineSource|Web IDE"
-msgstr ""
+msgstr "IDE Web"
msgid "PipelineStatusTooltip|Pipeline: %{ciStatus}"
msgstr "Pipeline: %{ciStatus}"
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "Atualmente não há pipelines."
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "Ocorreu um erro ao buscar os pipelines. Tente novamente daqui a pouco ou entre em contato com sua equipe de suporte."
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr "Pipeline de resultado mesclado"
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr "Passou"
@@ -25280,7 +25559,7 @@ msgid "Pipeline|Source"
msgstr "Fonte"
msgid "Pipeline|Source|Security Policy"
-msgstr ""
+msgstr "Política de segurança"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default."
msgstr ""
@@ -25331,7 +25610,7 @@ msgid "Pipeline|We are currently unable to fetch pipeline data"
msgstr ""
msgid "Pipeline|You’re about to stop pipeline #%{pipelineId}."
-msgstr ""
+msgstr "Você está prestes a interromper o pipeline #%{pipelineId}."
msgid "Pipeline|for"
msgstr "para"
@@ -25360,6 +25639,9 @@ msgstr "Diff simples"
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr "Digite um número válido"
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Por favor, preencha um nome descritivo para o seu grupo."
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr "Por favor, preencha este campo."
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25724,16 +26015,16 @@ msgid "Prevent adding new members to project membership within this group"
msgstr "Impede a adição de novos membros ao projeto pertencentes a este grupo"
msgid "Prevent auto-stopping"
-msgstr ""
+msgstr "Evitar a parada automática"
msgid "Prevent editing approval rules in projects and merge requests."
msgstr "Evitar a edição de regras de aprovação em projetos e solicitações de mesclagem."
msgid "Prevent environment from auto-stopping"
-msgstr ""
+msgstr "Impedir que o ambiente pare automaticamente"
msgid "Prevent project forking outside current group"
-msgstr ""
+msgstr "Impedir o fork do projeto fora do grupo atual"
msgid "Prevent users from changing their profile name"
msgstr ""
@@ -25799,7 +26090,7 @@ msgid "Private"
msgstr "Privado"
msgid "Private - Guest users are not allowed to view detailed release information like title and source code."
-msgstr ""
+msgstr "Privado - Usuários convidados não têm permissão para ver informações detalhadas do lançamento como título e código-fonte."
msgid "Private - Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group."
msgstr "Privado - O acesso ao projeto deve ser concedido explicitamente para cada usuário. Se esse projeto é parte de um grupo, o acesso será concedido para os membros do grupo,"
@@ -25885,12 +26176,18 @@ msgstr "Perfil"
msgid "Profile Settings"
msgstr "Configurações do perfil"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr "Diretriz de imagem de perfil"
msgid "Profile page:"
msgstr "Página de perfil:"
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr "Você está prestes a excluir permanentemente a %{yourAccount}, e todas
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr "Você vai alterar o nome de usuário %{currentUsernameBold} para %{newUsernameBold}. O perfil e os projetos serão redirecionados para %{newUsername} mas esse redirecionamento expirará quando %{currentUsername} for registrado por outro usuário ou grupo. Por favor, atualize seus repositórios remotos Git o mais rápido possível."
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr "\"Ocupado\" será mostrado próximo do seu nome"
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr "Adicionar emoji de status"
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr "Recortar Avatar"
@@ -26012,7 +26309,7 @@ msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr "Digite seu nome, então as pessoas que você conhece podem reconhecê-lo"
msgid "Profiles|Enter your password to confirm the email change"
-msgstr ""
+msgstr "Digite sua senha para confirmar a alteração do e-mail"
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr "Digite seu pronome para que as pessoas sabiam como preferir a você"
@@ -26221,6 +26518,9 @@ msgstr "Você pode enviar o seu avatar aqui ou alterá-lo em %{gravatar_link}"
msgid "Profiles|You don't have access to delete this user."
msgstr "Você não tem permissão para apagar esse usuário."
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26249,7 +26549,7 @@ msgid "Profiles|e.g. My MacBook key"
msgstr "por exemplo, Chave do meu MacBook"
msgid "Profiles|https://website.com"
-msgstr ""
+msgstr "https://website.com"
msgid "Profiles|username"
msgstr "nome de usuário"
@@ -26495,16 +26795,16 @@ msgid "ProjectSelect| or group"
msgstr " ou grupo"
msgid "ProjectSelect|No matching results"
-msgstr ""
+msgstr "Nenhum resultado correspondente"
msgid "ProjectSelect|Search for project"
msgstr "Pesquisar por projeto"
msgid "ProjectSelect|Search projects"
-msgstr ""
+msgstr "Pesquisar projetos"
msgid "ProjectSelect|Select a project"
-msgstr ""
+msgstr "Selecionar um projeto"
msgid "ProjectSelect|There was an error fetching the projects. Please try again."
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr "Global"
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "Interno"
@@ -26731,6 +27040,9 @@ msgstr "Issues"
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr "Gerencia arquivos grandes, como arquivos de áudio, vídeo e gráficos."
@@ -26894,7 +27206,7 @@ msgid "ProjectSettings|Users can request access"
msgstr "Usuários podem solicitar acesso"
msgid "ProjectSettings|View and edit files in this project."
-msgstr ""
+msgstr "Visualize e edite arquivos neste projeto."
msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
msgstr "Veja e edite arquivos nesse projeto. Não membros do projeto terão apenas acesso a leitura."
@@ -26908,9 +27220,12 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr "Visualize as métricas de desempenho do projeto."
-msgid "ProjectSettings|What are badges?"
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
msgstr ""
+msgid "ProjectSettings|What are badges?"
+msgstr "O que são selos?"
+
msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr "Spring"
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr "Editor de site estático/Middleman"
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
@@ -27014,7 +27332,7 @@ msgid "Projects are graded based on the highest severity vulnerability present"
msgstr ""
msgid "Projects are organized into groups"
-msgstr ""
+msgstr "Os projetos são organizados em grupos"
msgid "Projects contributed to"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr "Esta funcionalidade necessita de suporte à localStorage do navegador"
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr "Permite que você clone imediatamente o repositório deste projeto. Pule esta etapa se você planeja fazer o push de um repositório existente."
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr "Conecte seu repositório externo para o GitLab CI/CD"
@@ -27106,6 +27427,9 @@ msgstr "Criar novo projeto"
msgid "ProjectsNew|Description format"
msgstr "Formato de descrição"
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr "Importar"
@@ -27121,6 +27445,9 @@ msgstr "Migre seus dados de uma fonte externa como GitHub, Bitbucket, ou outra i
msgid "ProjectsNew|No import options available"
msgstr "Nenhuma opção de importação disponível"
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "Descrição do projeto %{tag_start}(opcional)%{tag_end}"
@@ -27136,54 +27463,9 @@ msgstr "Quer abrigar vários projetos dependentes no mesmo espaço de nome? %{li
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr "Adicionar alerta"
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr "Editar alerta"
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr "Erro ao criar alerta"
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr "Erro ao excluir alerta"
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr "Erro ao buscar alerta"
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr "Erro ao salvar alerta"
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr "Operador"
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr "Selecionar consulta"
-
-msgid "PrometheusAlerts|Threshold"
-msgstr "Tolerância"
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27206,7 +27488,7 @@ msgid "PrometheusService|Common metrics are automatically monitored based on a l
msgstr "Métricas comuns são monitoradas automaticamente com base em uma biblioteca de métricas de exportadores populares."
msgid "PrometheusService|Configure GitLab to query a Prometheus installed in one of your clusters."
-msgstr ""
+msgstr "Configure o GitLab para consultar um Prometheus instalado em um de seus clusters."
msgid "PrometheusService|Custom metrics"
msgstr "Métricas personalizadas"
@@ -27254,10 +27536,10 @@ msgid "PrometheusService|No custom metrics have been created. Create one using t
msgstr "Nenhuma métrica personalizada foi criada. Crie uma usando o botão acima"
msgid "PrometheusService|Prometheus cluster integration"
-msgstr ""
+msgstr "Integração de cluster do Prometheus"
msgid "PrometheusService|Select this checkbox to override the auto configuration settings with your own settings."
-msgstr ""
+msgstr "Selecione esta caixa de seleção para substituir as configurações automáticas pelas suas próprias configurações."
msgid "PrometheusService|The ID of the IAP-secured resource."
msgstr ""
@@ -27266,7 +27548,7 @@ msgid "PrometheusService|The Prometheus API base URL."
msgstr ""
msgid "PrometheusService|The contents of the credentials.json file of your service account."
-msgstr ""
+msgstr "O conteúdo do arquivo credentials.json da sua conta de serviço."
msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
msgstr "Essas métricas serão monitoradas após sua primeira implantação para um ambiente"
@@ -27281,7 +27563,7 @@ msgid "PrometheusService|You can now manage your Prometheus settings on the %{op
msgstr ""
msgid "PrometheusService|You have a cluster with the Prometheus integration enabled."
-msgstr ""
+msgstr "Você tem um cluster com a integração do Prometheus ativada."
msgid "PrometheusService|https://prometheus.example.com/"
msgstr ""
@@ -27317,7 +27599,7 @@ msgid "Promotion is not supported."
msgstr ""
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
-msgstr ""
+msgstr "Adicione webhooks de grupo e GitLab Enterprise Edition."
msgid "Promotions|Better Protected Branches"
msgstr "Ramificações protegidas com a melhor proteção"
@@ -27341,7 +27623,7 @@ msgid "Promotions|Contact your Administrator to upgrade your license."
msgstr "Entre em contato com seu administrador para aprimorar sua licença."
msgid "Promotions|Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
-msgstr ""
+msgstr "Modelos de descrição permitem que você defina modelos de contextos específicos para issue e descrição de merge requests para seu projeto."
msgid "Promotions|Dismiss burndown charts promotion"
msgstr ""
@@ -27398,7 +27680,7 @@ msgid "Promotions|See the other features in the %{subscription_link_start}Premiu
msgstr "Veja outras funcionalidade do %{subscription_link_start}plano Premium%{subscription_link_end}"
msgid "Promotions|Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
-msgstr ""
+msgstr "Definir o número de aprovações necessárias e definir uma lista de aprovadores necessários para cada solicitação de mesclagem em um projeto."
msgid "Promotions|Start GitLab Ultimate trial"
msgstr "Iniciar avaliação do GitLab Ultimate"
@@ -27461,7 +27743,7 @@ msgid "Promotions|description templates"
msgstr "modelos de descrição"
msgid "Promotions|to help your contributors communicate effectively!"
-msgstr ""
+msgstr "para ajudar seus contribuintes à se comunicar de maneira eficaz!"
msgid "Prompt users to upload SSH keys"
msgstr "Solicitar que os usuários adicionem chaves SSH"
@@ -27487,9 +27769,6 @@ msgstr "Ramificações protegidas"
msgid "Protected Environment"
msgstr "Ambiente protegido"
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr "Ramificações protegidas"
msgid "Protected environments"
msgstr "Ambientes protegidos"
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr "O que são tags protegidas?"
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr "Provedor"
@@ -27655,6 +27940,9 @@ msgstr "Provisionado por:"
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr "Coleção de dados Pseudonymizer"
@@ -27841,9 +28129,6 @@ msgstr "Consulta"
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr "A consulta é válida"
-
msgid "Queued"
msgstr "Na fila"
@@ -27877,6 +28162,9 @@ msgstr "Limites de taxa"
msgid "Rate limit"
msgstr "Taxa limite"
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr "Receber e-mails de marketing de produtos"
msgid "Recent"
msgstr "Recente"
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr "Atividade recente do projeto"
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr "Tarefas recentes servidos por este executor"
@@ -28194,7 +28482,7 @@ msgid "Release|Something went wrong while saving the release details."
msgstr ""
msgid "Reload page"
-msgstr ""
+msgstr "Atualizar a página"
msgid "Remediations"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr "Reabrir"
@@ -28479,7 +28770,7 @@ msgid "Reopens this %{quick_action_target}."
msgstr "Reabre este %{quick_action_target}."
msgid "Repeats"
-msgstr ""
+msgstr "Repetir"
msgid "Replace"
msgstr "Substituir"
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr "Selecionar"
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "Solicitar acesso"
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28844,7 +29135,7 @@ msgid "Require additional authentication for administrative tasks."
msgstr ""
msgid "Require all users in this group to set up two-factor authentication"
-msgstr ""
+msgstr "Exigir que todos os usuários neste grupo configurem a autenticação de dois fatores"
msgid "Required approvals (%{approvals_given} given)"
msgstr ""
@@ -28876,15 +29167,15 @@ msgstr "Requisitos"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] "Requer aprovação de %{names}."
-msgstr[1] "Requer mais %{count} aprovações de %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
+msgstr[0] ""
+msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
-msgstr[0] "Requer aprovação."
-msgstr[1] "Requer mais %d aprovações."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
+msgstr[0] ""
+msgstr[1] ""
msgid "Requires values to meet regular expression requirements."
msgstr ""
@@ -28911,7 +29202,7 @@ msgid "Resend it"
msgstr "Reenviar"
msgid "Resend unlock instructions"
-msgstr ""
+msgstr "Reenviar instruções de desbloqueio"
msgid "Reset"
msgstr ""
@@ -29229,9 +29520,6 @@ msgstr "Executores"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr "Executores são processos que selecionam e executam Tarefas de CI /CD para o GitLab."
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr "Executores online no momento: %{active_runners_count}"
@@ -29256,6 +29544,15 @@ msgstr "Arquitetura"
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr "Comando para registrar o executor"
msgid "Runners|Copy instructions"
msgstr "Copiar instruções"
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr "Novo token de registro gerado!"
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr "Não conectado"
@@ -29337,6 +29640,24 @@ msgstr "Nome da propriedade"
msgid "Runners|Protected"
msgstr "Protegido"
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr "Revisão"
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr "Mostrar instruções de instalação do executor"
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "Você usou %{quotaUsed} dos seus %{quotaLimit} minutos dos executores compartilhados."
@@ -29469,15 +29796,6 @@ msgstr "Executando"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "Executa várias tarefas de manutenção dentro do repositório atual, como compactar revisões de arquivos e remover objetos inacessíveis."
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr "Salvar alterações"
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr "Salvar aplicativo"
@@ -29905,6 +30220,9 @@ msgstr[1] "resultados em wiki"
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -29927,7 +30245,7 @@ msgid "Secret Detection"
msgstr "Detecção de secreto"
msgid "Secret access key"
-msgstr ""
+msgstr "Chave de acesso secreta"
msgid "Secret token"
msgstr "Token secreto"
@@ -29966,7 +30284,7 @@ msgid "SecurityApprovals|A merge request approval is required when test coverage
msgstr ""
msgid "SecurityApprovals|A merge request approval is required when the license compliance report contains a denied license."
-msgstr ""
+msgstr "É necessária uma aprovação da solicitação de mesclagem quando o relatório de conformidade da licença contenha uma licença negada."
msgid "SecurityApprovals|Coverage-Check"
msgstr "Verificação de cobertura"
@@ -29987,7 +30305,7 @@ msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More
msgstr ""
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "Requer aprovação para reduções de cobertura de teste. %{linkStart}Saiba mais%{linkEnd}"
msgid "SecurityApprovals|Requires approval for vulnerabilities. %{linkStart}Learn more.%{linkEnd}"
msgstr "Requer aprovação para vulnerabilidades. %{linkStart}Saiba mais.%{linkEnd}"
@@ -30056,7 +30374,7 @@ msgid "SecurityConfiguration|Immediately begin risk analysis and remediation wit
msgstr ""
msgid "SecurityConfiguration|Manage corpus"
-msgstr ""
+msgstr "Gerenciar corpus"
msgid "SecurityConfiguration|Manage corpus files used as mutation sources in coverage fuzzing."
msgstr ""
@@ -30077,7 +30395,7 @@ msgid "SecurityConfiguration|Once you've enabled a scan for the default branch,
msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
-msgstr ""
+msgstr "Ative rapidamente todos os testes contínuos e ferramentas de conformidade ativando %{linkStart}Auto DevOps%{linkEnd}"
msgid "SecurityConfiguration|Runtime security metrics for application environments"
msgstr ""
@@ -30116,10 +30434,10 @@ msgid "SecurityOrchestration|Action"
msgstr "Ação"
msgid "SecurityOrchestration|Actions"
-msgstr ""
+msgstr "Ações"
msgid "SecurityOrchestration|Add rule"
-msgstr ""
+msgstr "Adicionar regra"
msgid "SecurityOrchestration|All policies"
msgstr "Todas as políticas"
@@ -30130,18 +30448,21 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr "Descrição"
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr "Editar política"
msgid "SecurityOrchestration|Edit policy project"
msgstr "Editar projeto de política"
+msgid "SecurityOrchestration|Enabled"
+msgstr ""
+
msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr "Aplicar segurança para este projeto. %{linkStart}Mais informações.%{linkEnd}"
-msgid "SecurityOrchestration|Enforcement Status"
-msgstr ""
-
msgid "SecurityOrchestration|Executes a %{scanType} scan"
msgstr "Executa uma verificação %{scanType}"
@@ -30170,7 +30491,7 @@ msgid "SecurityOrchestration|Policy editor"
msgstr "Editor de política"
msgid "SecurityOrchestration|Policy preview"
-msgstr ""
+msgstr "Pré-visualizar política"
msgid "SecurityOrchestration|Policy status"
msgstr "Status da política"
@@ -30182,7 +30503,7 @@ msgid "SecurityOrchestration|Rule"
msgstr "Regra"
msgid "SecurityOrchestration|Rules"
-msgstr ""
+msgstr "Regras"
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,11 +30532,14 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
msgid "SecurityOrchestration|This project does not contain any security policies."
-msgstr ""
+msgstr "Este projeto não contém nenhuma política de segurança."
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
@@ -30277,9 +30604,12 @@ msgstr "Criar uma Jira do Jira"
msgid "SecurityReports|Create issue"
msgstr "Criar issue"
-msgid "SecurityReports|Development vulnerabilities"
+msgid "SecurityReports|Create policy"
msgstr ""
+msgid "SecurityReports|Development vulnerabilities"
+msgstr "Vulnerabilidades de desenvolvimento"
+
msgid "SecurityReports|Dismiss vulnerability"
msgstr "Dispensar vulnerabilidade"
@@ -30298,9 +30628,6 @@ msgstr "Baixar os resultados"
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30332,6 +30659,15 @@ msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
+msgstr "Gerenciar e acompanhe vulnerabilidades identificadas em projetos dentro de seu grupo. Vulnerabilidades em projetos são mostradas aqui quando o teste de segurança é configurado."
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
@@ -30343,11 +30679,14 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr "Monitore vulnerabilidades em todos os seus projetos"
msgid "SecurityReports|Monitor vulnerabilities in your group"
-msgstr ""
+msgstr "Monitore vulnerabilidades em seu grupo"
msgid "SecurityReports|Monitor vulnerabilities in your project"
msgstr "Monitore vulnerabilidades em seu projeto"
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr "Projeto"
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,12 +30880,12 @@ msgstr "Selecionar Página"
msgid "Select a branch"
msgstr "Selecionar uma ramificação"
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "Selecione um arquivo da barra lateral na esquerda para começar a editar. Depois, você poderá fazer commit das suas alterações."
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
-msgstr "Selecionar um framework que se aplique a esse projeto. %{linkStart}Como são adicionados?%{linkEnd}"
-
msgid "Select a group to invite"
msgstr "Selecione um grupo para convidar"
@@ -30556,17 +30901,11 @@ msgstr "Selecione um novo espaço de nome"
msgid "Select a project"
msgstr "Selecione um projeto"
-msgid "Select a project to read Insights configuration file"
-msgstr "Selecione um projeto para ler o arquivo de configuração de Insight"
-
msgid "Select a reason"
msgstr "Selecione um motivo"
-msgid "Select a repository"
-msgstr "Selecione um repositório"
-
msgid "Select a repository containing templates for common files."
-msgstr ""
+msgstr "Selecione um repositório contendo modelos para arquivos comuns."
msgid "Select a role"
msgstr "Selecione um cargo"
@@ -30788,7 +31127,7 @@ msgid "Send service data"
msgstr ""
msgid "Sentry"
-msgstr ""
+msgstr "Sentry"
msgid "Sentry API URL"
msgstr "URL da API do Sentry"
@@ -30823,9 +31162,6 @@ msgstr "Versão do servidor"
msgid "Serverless"
msgstr "Serverless"
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr "Plataforma sem servidor"
@@ -30925,9 +31261,6 @@ msgstr "Ativar central de Serviços"
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr "issues criadas a partir da central de serviços aparecem aqui. Cada comentário torna-se da conversa por e-mail"
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr "issues criadas a partir da central de serviços aparecerão aqui. Cada comentário torna-se da conversa por e-mail"
@@ -30982,9 +31315,6 @@ msgstr "Defina uma senha para sua conta para aceitar ou entregar código via %{p
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr "Configurar integração do Jira"
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr "Definir um dispositivo de hardware como o segundo fator para entrar."
@@ -31111,12 +31438,12 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "defina uma senha"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
-msgstr "Um indicador de ocupado é mostrado próximo do seu nome e avatar."
-
msgid "SetStatusModal|Add status emoji"
msgstr "Adicionar emoji de status"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "SetStatusModal|Busy"
msgstr ""
@@ -31180,6 +31507,11 @@ msgstr "Configuração"
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr "Issues semelhantes"
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr "Consultas simples ou combinadas"
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr "Cartão inteligente"
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "A autenticação do cartão inteligente falhou: o cabeçalho do certificado do cliente está faltando."
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "Snippets"
@@ -31616,6 +31948,9 @@ msgstr "Armazene, compartilhe e incorpore pequenas partes de código e texto"
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "Não há snippets para mostrar."
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr "Adicionar outro arquivo %{num}/%{total}"
@@ -31625,14 +31960,17 @@ msgstr "Excluir arquivo"
msgid "Snippets|Description (optional)"
msgstr "Descrição (opcional)"
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr "Arquivos"
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
-msgstr ""
+msgstr "Dê ao seu arquivo um nome para adicionar destaque de código, por exemplo, example.rb para Ruby"
msgid "Snippets|Optionally add a description about what your snippet does or how to use it…"
-msgstr ""
+msgstr "Opcionalmente, adicione uma descrição sobre o que seu snippet faz ou como usá-lo…"
msgid "Snowplow"
msgstr "Snowplow"
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr "Alguém editou a issue ao mesmo tempo que você. Por favor, verifique %{linkStart}a issue%{linkEnd} e tenha certeza de que suas alterações não irão intencionalmente remover as alterações da outra pessoa."
@@ -31665,7 +32000,7 @@ msgid "Someone edited this test case at the same time you did. The description h
msgstr ""
msgid "Someone, hopefully you, has requested to reset the password for your GitLab account on %{link_to_gitlab}."
-msgstr ""
+msgstr "Alguém, esperamos que você, solicitou a redefinição da senha da sua conta do GitLab em %{link_to_gitlab}."
msgid "Something went wrong"
msgstr "Alguma coisa deu errado"
@@ -31785,7 +32120,7 @@ msgid "Something went wrong while merging this merge request. Please try again."
msgstr ""
msgid "Something went wrong while obtaining the Let's Encrypt certificate."
-msgstr ""
+msgstr "Ocorreu um erro ao obter o certificado Let's Encrypt."
msgid "Something went wrong while promoting the issue to an epic. Please try again."
msgstr ""
@@ -31821,7 +32156,7 @@ msgid "Something went wrong while setting %{issuableType} weight."
msgstr ""
msgid "Something went wrong while stopping this environment. Please try again."
-msgstr ""
+msgstr "Algo deu errado ao parar este ambiente. Por favor, tente novamente."
msgid "Something went wrong while updating a requirement."
msgstr ""
@@ -32199,7 +32534,7 @@ msgid "Start Date"
msgstr ""
msgid "Start Time"
-msgstr ""
+msgstr "Hora de início"
msgid "Start Web Terminal"
msgstr "Iniciar Terminal Web"
@@ -32246,14 +32581,8 @@ msgstr "Iniciar pesquisa"
msgid "Start thread"
msgstr "Iniciar tópico"
-msgid "Start thread & close %{noteable_name}"
-msgstr "Iniciar tópico e fechar %{noteable_name}"
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr "Iniciar tópico e reabrir %{noteable_name}"
-
msgid "Start your Free Ultimate Trial"
-msgstr ""
+msgstr "Comece sua avaliação Ultimate gratuita"
msgid "Start your free trial"
msgstr "Inicie o seu teste gratuito"
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "Regitre sua mensagem para ativar"
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr "Teste de segurança de aplicativo estático (SAST)"
@@ -32789,7 +33121,7 @@ msgstr "Desbloqueado com sucesso"
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr "Resumo / Nota"
msgid "Sunday"
msgstr "Domingo"
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr "Código de ativação"
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr "Expira em"
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr "ID"
-
-msgid "SuperSonics|Last Sync"
-msgstr "Última sincronização"
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr "Plan"
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr "Iniciar a avaliação gratuita"
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr "Assinatura"
-
msgid "SuperSonics|Subscription details"
msgstr "Detalhes da assinatura"
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr "Type"
-
msgid "SuperSonics|Upload a license file"
msgstr "Enviar um arquivo de licença"
@@ -33021,10 +33320,7 @@ msgid "SuperSonics|Users over subscription"
msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "SuperSonics|Valid From"
-msgstr ""
+msgstr "Os usuários com um cargo de convidado ou aqueles que não pertencem a um projeto ou grupo não usarão uma licença de sua licença."
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr "URL da página de suporte"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr "Trocar ramificação"
@@ -33254,6 +33553,9 @@ msgstr "Tags dão capacidade de marcar pontos específicos na história como sen
msgid "TagsPage|This tag has no release notes."
msgstr "Essa tag não tem release notes."
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "Use o comando \"git tag\" para adiciona uma nova tag:"
@@ -33278,6 +33580,15 @@ msgstr "Ramificação de destino"
msgid "Task ID: %{elastic_task}"
msgstr "ID da tarefa: %{elastic_task}"
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "Equipe"
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr "Conte-nos as suas experiências com o novo editor Markdown %{linkStart}nessa issue%{linkEnd}."
@@ -33488,7 +33802,7 @@ msgstr[0] "Cobertura de teste: %d acerto"
msgstr[1] "Cobertura de teste: %d acertos"
msgid "Test settings"
-msgstr ""
+msgstr "Testar configurações"
msgid "TestCases|Move test case"
msgstr "Mover caso de teste"
@@ -33578,7 +33892,7 @@ msgid "TestReports|Jobs"
msgstr "Tarefas"
msgid "TestReports|Learn how to upload pipeline test reports"
-msgstr ""
+msgstr "Saiba como fazer upload de relatórios de teste de pipeline"
msgid "TestReports|Learn more about pipeline test reports"
msgstr ""
@@ -33593,7 +33907,7 @@ msgid "TestReports|There are no test cases to display."
msgstr ""
msgid "TestReports|There are no test reports for this pipeline"
-msgstr ""
+msgstr "Não há relatórios de teste para este pipeline"
msgid "TestReports|There are no test suites to show."
msgstr ""
@@ -33608,7 +33922,7 @@ msgid "TestReports|There was an error fetching the test suite."
msgstr ""
msgid "TestReports|You can configure your job to use unit test reports, and GitLab displays a report here and in the related merge request."
-msgstr ""
+msgstr "Você pode configurar sua tarefa para usar relatórios de teste de unidade, e o GitLab exibe um relatório aqui e na solicitação de mesclagem relacionada."
msgid "Tests"
msgstr "Testes"
@@ -33663,6 +33977,9 @@ msgstr[1] "O %{type} contém os seguintes erros:"
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33727,11 +34044,14 @@ msgid "The comparison view may be inaccurate due to merge conflicts."
msgstr ""
msgid "The compliance report captures merged changes that violate compliance best practices."
-msgstr ""
+msgstr "O relatório de conformidade captura mudanças mescladas que violam as melhores práticas de conformidade."
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "A conexão expirará após %{timeout}. Para repositórios que demoram mais tempo, use a combinação clone/push."
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr "O conteúdo desta página não está codificado em UTF-8. Edições só podem ser feitas através do repositório Git."
@@ -33762,9 +34082,6 @@ msgstr "A lista de dependências detalha informações sobre os componentes usad
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "A implantação desta tarefa para o ambiente %{environmentLink} foi mal sucedida."
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr "O diretório foi criado com sucesso."
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr "As configurações globais exigem que você habilite a autenticação de dois fatores para sua conta."
@@ -33917,6 +34237,9 @@ msgstr "A licença foi carregada com sucesso e agora está ativa. Você pode ver
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr "O tamanho máximo do arquivo é %{size}."
@@ -34011,7 +34334,7 @@ msgid "The project has already been added to your dashboard."
msgstr ""
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
-msgstr ""
+msgstr "O projeto é acessível apenas por membros do projeto. O acesso deve ser concedido explicitamente para cada usuário(a)."
msgid "The project is still being deleted. Please try again later."
msgstr "O projeto ainda está sendo excluído. Por favor, tente mais tarde."
@@ -34022,9 +34345,6 @@ msgstr "Fork do projeto realizado com sucesso."
msgid "The project was successfully imported."
msgstr "O projeto foi importado com sucesso."
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "A coleção de dados pseudonymizer está desativada. Quando ativada, o GitLab executará uma tarefa em segundo plano que produzirá CSVs com pseudônimos do banco de dados do GitLab que serão carregados no diretório de armazenamento de objetos configurado."
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr "O repositório deve ser acessível em %{code_open}http://%{code_close},
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr "O horário do agendamento deve ser no futuro!"
-
msgid "The snippet can be accessed without any authentication."
msgstr "O snippet pode ser acessado sem nenhuma autenticação."
@@ -34220,6 +34537,9 @@ msgstr "Não há pacotes ainda"
msgid "There are no projects shared with this group yet"
msgstr "Não há projetos compartilhados com esse grupo ainda"
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr "Ainda não existem variáveis."
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr "Esses exemplos mostram como acionar o pipeline deste projeto para uma ra
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr "Esses executores são compartilhados entre projetos neste grupo."
@@ -34689,7 +35009,7 @@ msgid "This field is required."
msgstr "Este campo é obrigatório."
msgid "This form is disabled in preview"
-msgstr ""
+msgstr "Este formulário está desativado na pré-visualização"
msgid "This group"
msgstr "Esse grupo"
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -34920,7 +35240,7 @@ msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{
msgstr "Este pipeline faz uso de uma configuração de CI/CD predefinida habilitada por %{strongStart}Auto DevOps.%{strongEnd}"
msgid "This pipeline was triggered by a schedule."
-msgstr ""
+msgstr "Este pipeline foi disparando por um agendamento."
msgid "This project"
msgstr "Este projeto"
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35166,7 +35495,7 @@ msgid "Time"
msgstr "Hora"
msgid "Time (in hours) that users are allowed to skip forced configuration of two-factor authentication."
-msgstr ""
+msgstr "Tempo (em horas) que os usuários têm permissão para ignorar a configuração forçada da autenticação de dois fatores."
msgid "Time Spent"
msgstr "Tempo gasto"
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr "Para manter este projeto em andamento, crie uma nova issue"
msgid "To keep this project going, create a new merge request"
msgstr "Para manter este projeto em andamento, crie uma nova solicitação de mesclagem"
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr "Muitos projetos ativos. Você precisará gerenciá-los através do conso
msgid "TopNav|Go back"
msgstr "Voltar"
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr "Tópicos (opcional)"
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -35850,34 +36194,34 @@ msgid "Trials|Compare all plans"
msgstr "Comparar todos os planos"
msgid "Trials|Create a new group to start your GitLab Ultimate trial."
-msgstr ""
+msgstr "Crie um novo grupo para iniciar sua avaliação do GitLab Ultimate."
msgid "Trials|Go back to GitLab"
msgstr "Voltar para o GitLab"
msgid "Trials|Hey there"
-msgstr ""
+msgstr "Olá"
msgid "Trials|Skip Trial"
-msgstr ""
+msgstr "Pular avaliação"
msgid "Trials|Upgrade %{groupName} to %{planName}"
-msgstr ""
+msgstr "Atualizar %{groupName} para %{planName}"
msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
-msgstr ""
+msgstr "Você sempre pode retomar este processo selecionando seu avatar e escolhendo 'Iniciar uma avaliação do Ultimate'"
msgid "Trials|You can apply your trial to a new group or an existing group."
-msgstr ""
+msgstr "Você pode aplicar sua avaliação a um novo grupo ou a um grupo existente."
msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
-msgstr ""
+msgstr "Você não obterá uma avaliação gratuita agora, mas pode sempre retomar esse processo selecionando seu avatar e escolhendo 'Iniciar uma avaliação do Ultimate'"
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
-msgstr ""
+msgstr "Nome da empresa"
msgid "Trial|Continue"
msgstr "Continuar"
@@ -35886,16 +36230,16 @@ msgid "Trial|Continue using the basic features of GitLab for free."
msgstr ""
msgid "Trial|Country"
-msgstr ""
+msgstr "País"
msgid "Trial|Dismiss"
-msgstr ""
+msgstr "Dispensar"
msgid "Trial|First name"
msgstr "Nome"
msgid "Trial|GitLab Ultimate trial (optional)"
-msgstr ""
+msgstr "Avaliação do GitLab Ultimate (opcional)"
msgid "Trial|Hi%{salutation}, your GitLab Ultimate trial lasts for 30 days, but you can keep your free GitLab account forever. We just need some additional information about %{company} to activate your trial."
msgstr ""
@@ -35904,13 +36248,13 @@ msgid "Trial|How many employees will use Gitlab?"
msgstr ""
msgid "Trial|How many users will be evaluating the trial?"
-msgstr ""
+msgstr "Quantos usuários estarão avaliando o teste?"
msgid "Trial|Last name"
msgstr "Sobrenome"
msgid "Trial|Number of employees"
-msgstr ""
+msgstr "Número de funcionários"
msgid "Trial|Please select a country"
msgstr "Por favor selecione um país"
@@ -35919,7 +36263,7 @@ msgid "Trial|Successful trial activation image"
msgstr ""
msgid "Trial|Telephone number"
-msgstr ""
+msgstr "Número de telefone"
msgid "Trial|Upgrade to Ultimate to keep using GitLab with advanced features."
msgstr ""
@@ -36096,7 +36440,7 @@ msgid "URL is triggered for each branch updated to the repository"
msgstr ""
msgid "URL is triggered when a merge request is created, updated, or merged"
-msgstr ""
+msgstr "O URL é acionado quando uma solicitação de mesclagem é criada, atualizada ou mesclada"
msgid "URL is triggered when a new tag is pushed to the repository"
msgstr ""
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36225,10 +36572,10 @@ msgid "Unable to update this issue at this time."
msgstr "Não é possível atualizar esta issue neste momento."
msgid "Unapprove a merge request"
-msgstr ""
+msgstr "Desaprovar uma solicitação de mesclagem"
msgid "Unapprove the current merge request."
-msgstr ""
+msgstr "Desaprovar a solicitação de mesclagem atual."
msgid "Unapproved the current merge request."
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr "Solicitações não autenticadas"
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr "Desfazer"
@@ -36573,7 +36923,7 @@ msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled,
msgstr "%{help_link_start}Executores compartilhados%{help_link_end} estão desativados, então não há limites definidos no uso de pipeline"
msgid "UsageQuota|%{linkTitle} help link"
-msgstr ""
+msgstr "link de ajuda %{linkTitle}"
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr "%{percentageLeft} de armazenamento comprado está disponível"
@@ -36585,6 +36935,9 @@ msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr "Artefatos é uma soma de artefatos de construção e pipeline."
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
+msgstr "Amostras de áudio, vídeos, conjuntos de dados e gráficos."
+
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -36597,18 +36950,18 @@ msgid "UsageQuota|CI minutes usage by project"
msgstr "Uso de minutos de CI por projeto"
msgid "UsageQuota|Code packages and container images."
-msgstr ""
+msgstr "Pacotes de código e imagens de contêiner."
msgid "UsageQuota|Current period usage"
msgstr "Uso do período atual"
msgid "UsageQuota|File attachments and smaller design graphics."
-msgstr ""
+msgstr "Anexos de arquivo e gráficos de design menores."
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr "Objetos LFS"
msgid "UsageQuota|LFS Storage"
msgstr "Armazenamento LFS"
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr "Saiba mais sobre o armazenamento em excesso"
@@ -36630,7 +36986,7 @@ msgid "UsageQuota|Packages"
msgstr "Pacotes"
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
-msgstr ""
+msgstr "Artefatos de pipeline e artefatos de tarefa, criados com CI/CD."
msgid "UsageQuota|Pipelines"
msgstr "Pipelines"
@@ -36651,7 +37007,7 @@ msgid "UsageQuota|Seats"
msgstr "Assentos"
msgid "UsageQuota|Shared bits of code and text."
-msgstr ""
+msgstr "Bits compartilhados de código e texto."
msgid "UsageQuota|Snippets"
msgstr "Snippets"
@@ -36663,10 +37019,7 @@ msgid "UsageQuota|Storage"
msgstr "Armazenamento"
msgid "UsageQuota|Storage type"
-msgstr ""
-
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
+msgstr "Tipo de armazenamento"
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,12 +37060,12 @@ msgstr "Envios"
msgid "UsageQuota|Usage"
msgstr "Uso"
-msgid "UsageQuota|Usage Breakdown"
-msgstr ""
-
msgid "UsageQuota|Usage Quotas"
msgstr "Cotas de uso"
+msgid "UsageQuota|Usage breakdown"
+msgstr ""
+
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
msgstr "Uso de recursos de grupo entre os projetos no grupo %{strong_start}%{group_name}%{strong_end}"
@@ -36735,7 +37088,7 @@ msgid "UsageQuota|Wiki"
msgstr "Wiki"
msgid "UsageQuota|Wiki content."
-msgstr ""
+msgstr "Conteúdo da wiki."
msgid "UsageQuota|Wikis"
msgstr "Wikis"
@@ -36860,6 +37213,9 @@ msgstr "Use um autenticador de senha única no seu dispositivo móvel ou computa
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr "Usar cURL"
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr "Utilizar modelo"
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36954,11 +37313,17 @@ msgid "User Settings"
msgstr "Configurações do usuário"
msgid "User and IP rate limits"
+msgstr "Limite de taxa do usuário e IP"
+
+msgid "User cap"
msgstr ""
-msgid "User does not have a pending request"
+msgid "User created at"
msgstr ""
+msgid "User does not have a pending request"
+msgstr "Usuário não tem uma solicitação pendente"
+
msgid "User identity was successfully created."
msgstr "A identidade do usuário foi criada com sucesso."
@@ -37278,7 +37643,7 @@ msgid "Users were successfully added."
msgstr "Usuário adicionado com sucesso"
msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
+msgstr "Os usuários com um cargo de convidado ou aqueles que não pertencem a um projeto ou grupo não usarão uma licença de sua licença."
msgid "UsersSelect|%{name} + %{length} more"
msgstr "%{name} + %{length} mais"
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr "Validar"
@@ -37316,6 +37684,15 @@ msgstr "Valide sua configuração do GitLab CI"
msgid "Validate your GitLab CI configuration file"
msgstr "Valide seu arquivo de configuração de GitLab CI"
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr "Falha na verificação"
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -37962,7 +38351,7 @@ msgid "We'll continuously validate your pipeline configuration. The validation r
msgstr ""
msgid "We'll use this to help surface the right features and information to you."
-msgstr ""
+msgstr "Vamos usar isso para ajudar a supervisionar os recursos e informações certos para você."
msgid "We've found no vulnerabilities"
msgstr "Nenhuma vulnerabilidade encontrada"
@@ -38024,6 +38413,9 @@ msgstr "Registros de webhook"
msgid "Webhook Settings"
msgstr "Configurações de webhook"
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr "Webhook:"
@@ -38070,7 +38462,7 @@ msgid "Webhooks|Push events"
msgstr "Eventos de push"
msgid "Webhooks|Releases events"
-msgstr ""
+msgstr "Eventos de versões"
msgid "Webhooks|SSL verification"
msgstr "Verificação SSL"
@@ -38094,46 +38486,46 @@ msgid "Webhooks|URL is triggered by a push to the repository"
msgstr "URL é acionado por push para o repositório"
msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened"
-msgstr ""
+msgstr "O URL é acionado quando uma issue confidencial é criada, atualizada, fechada ou reaberta"
msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
-msgstr ""
+msgstr "URL é acionado quando uma implantação começa, termina, falha ou é cancelada"
msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
-msgstr ""
+msgstr "O URL é acionado quando um feature flag é ativado ou desativado"
msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
-msgstr ""
+msgstr "O URL é acionado quando um membro do grupo é criado, atualizado ou removido"
msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
-msgstr ""
+msgstr "O URL é acionado quando uma solicitação de mesclagem é criada, atualizada ou mesclada"
msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
-msgstr ""
+msgstr "O URL é acionado quando uma nova tag é enviada para o repositório"
msgid "Webhooks|URL is triggered when a release is created or updated"
-msgstr ""
+msgstr "O URL é acionado quando uma versão é criada ou atualizada"
msgid "Webhooks|URL is triggered when a subgroup is created or removed"
-msgstr ""
+msgstr "O URL é acionado quando um subgrupo é criado ou removido"
msgid "Webhooks|URL is triggered when a wiki page is created or updated"
-msgstr ""
+msgstr "URL é acionado quando uma página wiki é criada ou atualizada"
msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened"
-msgstr ""
+msgstr "O URL é acionado quando uma issue é criada, atualizada, fechada ou reaberta"
msgid "Webhooks|URL is triggered when someone adds a comment"
-msgstr ""
+msgstr "O URL é acionado quando alguém adiciona um comentário"
msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
-msgstr ""
+msgstr "O URL é acionado quando alguém adiciona um comentário sobre uma issue confidencial confidencial"
msgid "Webhooks|URL is triggered when the job status changes"
-msgstr ""
+msgstr "O URL é acionado quando o status da tarefa muda"
msgid "Webhooks|URL is triggered when the pipeline status changes"
-msgstr ""
+msgstr "O URL é acionado quando o status do pipeline muda"
msgid "Webhooks|URL must be percent-encoded if neccessary."
msgstr "O URL deve ser codificado em porcentagem, se necessário."
@@ -38163,7 +38555,7 @@ msgid "Weight %{weight}"
msgstr "Peso %{weight}"
msgid "Welcome back! Your account had been deactivated due to inactivity but is now reactivated."
-msgstr ""
+msgstr "Bem-vindo novamente! Sua conta foi desativada devido a inatividade, mas agora foi reativada."
msgid "Welcome to GitLab"
msgstr "Bem-vindo ao GitLab"
@@ -38172,13 +38564,13 @@ msgid "Welcome to GitLab, %{first_name}!"
msgstr "Bem-vindo ao GitLab, %{first_name}!"
msgid "Welcome to GitLab,%{br_tag}%{name}!"
-msgstr ""
+msgstr "Bem-vindo ao GitLab,%{br_tag}%{name}!"
msgid "Welcome, %{name}!"
-msgstr ""
+msgstr "Bem-vindo, %{name}!"
msgid "What are group audit events?"
-msgstr ""
+msgstr "O que são eventos de auditoria em grupo?"
msgid "What are instance audit events?"
msgstr "O que são eventos de auditoria de instância?"
@@ -38187,7 +38579,7 @@ msgid "What are project audit events?"
msgstr "O que são eventos de auditoria de projetos?"
msgid "What are shared runner pipeline minutes?"
-msgstr ""
+msgstr "O que são os minutos de pipeline do executor compartilhado?"
msgid "What are you searching for?"
msgstr "O que você esta pesquisando?"
@@ -38202,10 +38594,10 @@ msgid "What is Markdown?"
msgstr "O que é Markdown?"
msgid "What is repository mirroring?"
-msgstr ""
+msgstr "O que é o espelhamento de repositório?"
msgid "What is squashing?"
-msgstr ""
+msgstr "O que é o esmagamento?"
msgid "What is time tracking?"
msgstr "O que é o acompanhamento do tempo?"
@@ -38214,11 +38606,14 @@ msgid "What is your job title? (optional)"
msgstr "Qual é o título do seu trabalho? (opcional)"
msgid "What templates can I create?"
-msgstr ""
+msgstr "Quais modelos posso criar?"
msgid "What will you use this group for?"
msgstr "Para que você usará este grupo?"
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr "Novidades"
@@ -38228,9 +38623,6 @@ msgstr "Quando uma tarefa de implantação é bem-sucedida, pule as tarefas de i
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Quando um executor está bloqueado, não pode ser atribuído a outros projetos"
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr "Ao deixar o URL em branco, a classificação das etiquetas ainda podem s
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr "Quando as solicitações de mesclagem e commits na ramificação padrão são fechadas, todas as issues aos quais eles fazem referência também são encerrados."
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr "Quando usar os protocolos %{code_open}http://%{code_close} ou %{code_open}https://%{code_close}, por favor forneça o URL exato do repositório. Redirecionamentos HTTP não serão seguidos."
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr "Quando usar os protocolos %{code_open}http://%{code_close} ou %{code_open}https://%{code_close}, forneça o URL exato do repositório. Redirecionamentos HTTP não serão seguidos."
-
msgid "When:"
msgstr "Quando:"
@@ -38273,31 +38665,31 @@ msgid "Who will be able to see this group?"
msgstr "Quem poderá ver esse grupo?"
msgid "Who will be using GitLab?"
-msgstr ""
+msgstr "Quem vai usar o GitLab?"
msgid "Who will be using this GitLab subscription?"
-msgstr ""
+msgstr "Quem usará esta assinatura do GitLab?"
msgid "Who will be using this GitLab trial?"
-msgstr ""
+msgstr "Quem vai usar essa avaliação do GitLab?"
msgid "Who will be using this group?"
msgstr "Quem usará esse grupo?"
msgid "Why are you signing up? (Optional)"
-msgstr ""
+msgstr "Por que você está se inscrevendo? (Opcional)"
msgid "Wiki"
msgstr "Wiki"
msgid "Wiki page was successfully created."
-msgstr ""
+msgstr "Página Wiki criada com sucesso."
msgid "Wiki page was successfully deleted."
-msgstr ""
+msgstr "Página wiki excluída com sucesso."
msgid "Wiki page was successfully updated."
-msgstr ""
+msgstr "Página Wiki atualizada com sucesso."
msgid "WikiClone|Clone your wiki"
msgstr "Clonar sua wiki"
@@ -38318,7 +38710,7 @@ msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
msgstr "Sugira uma melhoria na wiki"
msgid "WikiEmptyIssueMessage|You must be a group member in order to add wiki pages. If you have suggestions for how to improve the wiki for this group, consider opening an issue in the %{issues_link}."
-msgstr ""
+msgstr "Você deve ser um membro de grupo para adicionar páginas wiki. Se você tem sugestões de como melhorar a wiki desse grupo, considere abrir uma issue no %{issues_link}."
msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
msgstr "Você deve ser um membro do projeto para adicionar páginas na wiki. Se você tiver sugestões de como melhorar o wiki para este projeto, considere a possibilidade de abrir uma issue no %{issues_link}."
@@ -38327,7 +38719,7 @@ msgid "WikiEmptyIssueMessage|issue tracker"
msgstr "issue tracker"
msgid "WikiEmpty| Have a Confluence wiki already? Use that instead."
-msgstr ""
+msgstr "Já tem uma wiki de Confluence? Use-a em vez disso."
msgid "WikiEmpty|A wiki is where you can store all the details about your group. This can include why you've created it, its principles, how to use it, and so on."
msgstr ""
@@ -38560,12 +38952,12 @@ msgstr "Escreva um comentário…"
msgid "Write a description or drag your files here…"
msgstr "Escreva uma descrição ou arraste seus arquivos para aqui…"
+msgid "Write a description…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Escreva a descrição do marco..."
-msgid "Write to \"authorized_keys\" file"
-msgstr ""
-
msgid "Write your release notes or drag your files here…"
msgstr ""
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr "Você está prestes a excluir permanentemente este projeto"
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "Você pode resolver o conflito de mesclagem usando o modo Interativo, escolhendo os botões %{use_ours} ou %{use_theirs} ou editando os arquivos diretamente. Confirme essas alterações em %{branch_name}"
@@ -38870,7 +39259,7 @@ msgid "You cannot play this scheduled pipeline at the moment. Please wait a minu
msgstr ""
msgid "You cannot rename an environment after it's created."
-msgstr ""
+msgstr "Você não pode renomear um ambiente após sua criação."
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr "Você não pode escrever numa instância secundária de somente leitura do GitLab Geo. Por favor use %{link_to_primary_node} em vez disso."
@@ -38921,7 +39310,7 @@ msgid "You don't have any authorized applications"
msgstr "Você não tem nenhum aplicativo autorizado"
msgid "You don't have any deployments right now."
-msgstr ""
+msgstr "Você não tem implantações nesse momento."
msgid "You don't have any open merge requests"
msgstr "Você não tem nenhuma solicitação de mesclagem em aberto"
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr "Você não tem nenhuma pesquisa recente"
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr "Você deve estar conectado para pesquisar em todo o GitLab"
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,29 +39872,56 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr "Seu nome de usuário é %{username}."
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
-msgstr "Insira o token de API"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
+msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr "Se for diferente do URL da web."
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
-msgstr "Use Zentao como o rastreador de issues deste projeto."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
-msgstr "URL do API do Zentao (Opcional)"
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
-msgstr "Token de API do Zentao"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
-msgstr "ID de produto do Zentao"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
+msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
-msgstr "URL do Zentao Web"
+msgid "ZentaoIntegration|ZenTao API token"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
+msgstr ""
msgid "Zoom meeting added"
msgstr "Reunião do Zoom adicionada"
@@ -39519,6 +39932,9 @@ msgstr "Reunião do Zoom removida"
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr "[Redacted]"
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr "um usuário excluído"
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] "cerca de 1 hora"
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr "não foi possível bloquear outros"
@@ -39688,9 +40110,6 @@ msgstr "não é possível bloquear a si próprio"
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "mais %{remainingPackagesCount}"
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,8 +40202,14 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
-msgstr "Qualidade do código"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
msgid "ciReport|Container Scanning"
msgstr "Verificação de container"
@@ -39835,6 +40274,17 @@ msgstr "Encontrado %{issuesWithCount}"
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr "SAST"
msgid "ciReport|Secret Detection"
msgstr "Detecção de secreto"
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40015,7 +40471,7 @@ msgid "created %{timeAgo}"
msgstr "criado em %{timeAgo}"
msgid "created %{timeAgo} by %{author}"
-msgstr ""
+msgstr "criado %{timeAgo} por %{author}"
msgid "created by"
msgstr "criado por"
@@ -40046,9 +40502,6 @@ msgstr "implantar"
msgid "design"
msgstr "design"
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr "baixá-lo"
@@ -40075,6 +40534,9 @@ msgstr "por exemplo %{token}"
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40109,6 +40571,9 @@ msgid "estimateCommand|%{slash_command} overwrites the total estimated time."
msgstr "%{slash_command} substitui o tempo total estimado."
msgid "example.com"
+msgstr "example.com"
+
+msgid "exceeds the %{max_value_length} character limit"
msgstr ""
msgid "exceeds the limit of %{bytes} bytes"
@@ -40239,16 +40704,16 @@ msgid "in Infrastructure :: Kubernetes clusters"
msgstr ""
msgid "in all GitLab"
-msgstr ""
+msgstr "em todo o GitLab"
msgid "in group"
-msgstr ""
+msgstr "no grupo"
msgid "in group %{link_to_group}"
msgstr "no grupo %{link_to_group}"
msgid "in project"
-msgstr ""
+msgstr "no projeto"
msgid "in project %{link_to_project}"
msgstr "no projeto %{link_to_project}"
@@ -40295,10 +40760,10 @@ msgid "is not allowed for sign-up."
msgstr ""
msgid "is not allowed for this group."
-msgstr ""
+msgstr "não é permitido para este grupo."
msgid "is not allowed for this project."
-msgstr ""
+msgstr "não é permitido para este projeto."
msgid "is not allowed since the group is not top-level group."
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40397,7 +40868,7 @@ msgid "log in"
msgstr ""
msgid "managed"
-msgstr ""
+msgstr "gerenciado"
msgid "manual"
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr "%{metricsLinkStart} Memória %{metricsLinkEnd} uso é %{emphasisStart} i
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr "Aprovar adicionalmente"
msgid "mrWidget|Approved by"
msgstr "Aprovado por"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40530,7 +41010,7 @@ msgstr[0] "Issue fechada"
msgstr[1] "Issues fechadas"
msgid "mrWidget|Create issue to resolve all threads"
-msgstr ""
+msgstr "Criar uma issue para resolver todos os tópicos"
msgid "mrWidget|Delete source branch"
msgstr "Excluir branch de origem"
@@ -40542,7 +41022,7 @@ msgid "mrWidget|Did not close"
msgstr "Não foi possível fechar"
msgid "mrWidget|Dismiss"
-msgstr ""
+msgstr "Dispensar"
msgid "mrWidget|Email patches"
msgstr "Email patches"
@@ -40562,6 +41042,9 @@ msgstr "Se o ultimo pipeline foi executado no fork do projeto, pode ser imprecis
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr "Carregando estatísticas de implantação"
@@ -40594,9 +41077,6 @@ msgstr "Falha ao mesclar."
msgid "mrWidget|Merge locally"
msgstr "Mesclar localmente"
-msgid "mrWidget|Merge request approved."
-msgstr "Solicitação de mesclagem aprovada."
-
msgid "mrWidget|Merged by"
msgstr "Mesclado por"
@@ -40711,12 +41191,6 @@ msgstr "A ramificação de origem não será excluída"
msgid "mrWidget|There are merge conflicts"
msgstr "Existem conflitos de merge"
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Falha ao realizar merge automaticamente"
@@ -40732,11 +41206,14 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr "Você pode mesclar após remover as licenças negadas"
msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
+msgstr "Você só pode mesclar quando essa solicitação de mesclagem for aprovada."
msgid "mrWidget|Your password"
msgstr "Sua senha"
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr "meu-grupo-incrível"
@@ -40855,6 +41338,9 @@ msgstr "ou"
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "de um total de %d teste"
@@ -40948,16 +41434,16 @@ msgid "quick actions"
msgstr "ações rápidas"
msgid "reCAPTCHA"
-msgstr ""
+msgstr "reCAPTCHA"
msgid "reCAPTCHA helps prevent credential stuffing."
msgstr ""
msgid "reCAPTCHA private key"
-msgstr ""
+msgstr "Chave privada de reCAPTCHA"
msgid "reCAPTCHA site key"
-msgstr ""
+msgstr "Chave de reCAPTCHA do site"
msgid "recent activity"
msgstr "atividade recente"
@@ -41279,8 +41765,8 @@ msgid "your settings"
msgstr ""
msgid "{group}"
-msgstr ""
+msgstr "{group}"
msgid "{project}"
-msgstr ""
+msgstr "{project}"
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index 725dd521ecc..1c2dc219c8c 100644
--- a/locale/pt_PT/gitlab.po
+++ b/locale/pt_PT/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pt-PT\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:22\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Tens de fazer isto antes de %{grace_period_deadline}."
-msgid " and"
-msgstr " e"
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " melhorado em %d ponto"
-msgstr[1] " melhorado em %d pontos"
-
msgid " or "
msgstr " ou "
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] "%d envio"
msgstr[1] "%d envios"
-msgid "%d commits"
-msgstr "%d envios"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr "Um ramo padrão não pode ser escolhido para um projeto vazio."
msgid "A deleted user"
msgstr "Um utilizador apagado"
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr "Um membro da equipa de abuso irá, rever a tua denúncia assim que possÃ
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr "Ativar Central de Serviços"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Ativo"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "Adicionar um comentário geral para este %{noteable_name}."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Adiciona uma página inicial à tua wiki que confoi informações sobre o teu projeto e o GitLab irá exibi-lo aqui, ao invés desta mensagem."
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr "Adicionar endereço de email"
@@ -2108,6 +2104,9 @@ msgstr "Adicionar à revisão"
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "Administrador"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr "Todos os conflitos de mesclagem foram resolvidos. O pedido de mesclagem
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr "Todos os utilizadores devem ter um nome."
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Permitir que \"%{group_name}\" adicione-te"
@@ -3362,7 +3370,7 @@ msgstr "Permitir envios de membros que podem mesclar ao ramo de destino."
msgid "Allow group owners to manage LDAP-related settings"
msgstr "Permitir que proprietários de grupos gerenciem as definições relacionadas ao LDAP"
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "Ocorreu um erro ao assinar as notificações."
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr "Nome"
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr "Tens a certeza? Remover esta chave GPG não afeta as confirmações já
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr "Tens a certeza? Isto invalidará as tuas aplicações registadas e dispositivos U2F."
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr "agosto"
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr "Blogue"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,8 +5699,8 @@ msgstr "Todos"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "Não foi possível encontrar o envio do HEAD para este ramo"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "Comparar"
@@ -5767,6 +5810,9 @@ msgstr "Para confirmar, digita %{branch_name_confirmation}:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Para rejeitar as alterações locais e sobrescrever a ramificação com a versão upstream, apaga-o aqui e escolhe \"Atualizar Agora\" em cima."
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr "CI Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr "Não pode ser mesclado automaticamente"
@@ -6321,6 +6361,12 @@ msgstr "Não é possível ignorar a configuração de autenticação de dois fat
msgid "Capacity threshold"
msgstr "Limite de capacidade"
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr "Escolhe um modelo..."
msgid "Choose a type..."
msgstr "Escolhe um tipo..."
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr "Escolhe qualquer cor."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr "Escolher um ficheiro…"
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Vê e edita os detalhes do teu cluster Kubernetes"
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "Selecionar tipo de máquina"
@@ -7963,6 +8033,9 @@ msgstr "Selecionar projeto e zona para escolher o tipo de máquina"
msgid "ClusterIntegration|Select project to choose zone"
msgstr "Selecionar projeto para escolher a zona"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr "Configurar instalação existente"
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
msgstr ""
-msgid "Define approval rules."
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr "Falha ao enviar o ficheiro de mapeamento de objeto"
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr "Definições Gerais"
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "O GitLab executará um trabalho em segundo plano que produzirá CSVs com pseudónimos da base de dados do GitLab que serão enviados no diretório de armazenamento de objetos configurados."
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr "Histórico de autenticações"
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr "Podes enviar o teu avatar aqui ou alterá-lo em %{gravatar_link}"
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr "Página URL de suporte"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "A coleta de dados do pseudomizador está desativada. Quando ativado, o GitLab executará um trabalho em segundo produzir que produzirá CSVs com pseudónimo da base de dados do GitLab que serão enviados no diretório de armazenamento de objetos configurados."
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,12 +38952,12 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
+msgid "Write a description…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Escreve a descrição do objetivo..."
-msgid "Write to \"authorized_keys\" file"
-msgstr ""
-
msgid "Write your release notes or drag your files here…"
msgstr ""
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr "um utilizador apagado"
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index cfd2ea26fac..d1f6df211ae 100644
--- a/locale/ro_RO/gitlab.po
+++ b/locale/ro_RO/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ro\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:18\n"
+"PO-Revision-Date: 2021-11-02 00:38\n"
msgid " %{start} to %{end}"
msgstr " de la %{start} până la %{end}"
@@ -40,27 +40,12 @@ msgstr " Tip"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Trebuie să faceți asta înainte de %{grace_period_deadline}."
-msgid " and"
-msgstr " și"
-
msgid " and "
msgstr " și "
msgid " and %{sliced}"
msgstr " și %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " degradat la %d punct"
-msgstr[1] " degradat la %d puncte"
-msgstr[2] " degradat la %d de puncte"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " îmbunătățit în %d punct"
-msgstr[1] " îmbunătățit în %d puncte"
-msgstr[2] " îmbunătățit în %d de puncte"
-
msgid " or "
msgstr " sau "
@@ -88,20 +73,23 @@ msgstr "\"%{repository_name}\" dimensiunea (%{repository_size}) este mai mare de
msgid "\"el\" parameter is required for createInstance()"
msgstr "Parametrul \"el\" este necesar pentru createInstance()"
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr "#general, #development"
msgid "%d Alert"
msgid_plural "%d Alerts"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d Alertă"
+msgstr[1] "%d Alerte"
+msgstr[2] "%d Alerte"
msgid "%d Alert:"
msgid_plural "%d Alerts:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d Alertă:"
+msgstr[1] "%d Alerte:"
+msgstr[2] "%d Alerte:"
msgid "%d Approval"
msgid_plural "%d Approvals"
@@ -217,9 +205,6 @@ msgstr[0] "%d commit,"
msgstr[1] "%d commit-uri,"
msgstr[2] "%d de commit-uri,"
-msgid "%d commits"
-msgstr "%d (de) commit-uri"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] "%d problemă completată"
@@ -635,13 +620,13 @@ msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
msgstr "%{doc_link_start}Căutarea avansată%{doc_link_end} este activată."
msgid "%{docs_link_start}Learn about visibility levels.%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Aflați mai multe despre nivelurile de vizibilitate.%{docs_link_end}"
msgid "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Ce este Large File Storage?%{docs_link_end}"
msgid "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Ce este autentificarea cu doi factori?%{docs_link_end}"
msgid "%{due_date} (Past due)"
msgstr "%{due_date} (Cu scadență depășită)"
@@ -773,10 +758,10 @@ msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} indisponibil"
msgid "%{learn_more_link}."
-msgstr ""
+msgstr "%{learn_more_link}"
msgid "%{lessThan} 1 hour"
-msgstr ""
+msgstr "%{lessThan} 1 oră"
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} este o autoritate de certificare gratuită, automată și deschisă (CA) care emite certificate digitale pentru a activa HTTPS (SSL/TLS) pentru site-uri."
@@ -797,7 +782,7 @@ msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent
msgstr "%{link_start}Începeți titlul cu %{draft_snippet}%{link_end} pentru a preveni merge request-ul care este o lucrare în curs de a fi îmbinat înainte de a fi gata."
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
-msgstr ""
+msgstr "%{link_start}Ce informații colectează GitLab Inc.?%{link_end}"
msgid "%{listToShow}, and %{awardsListLength} more"
msgstr "%{listToShow}, și încă %{awardsListLength} mai multe"
@@ -956,7 +941,7 @@ msgstr[1] "Rezultatele %{securityScanner} nu sunt disponibile deoarece nu a fost
msgstr[2] "Rezultatele %{securityScanner} nu sunt disponibile deoarece nu a fost rulată o conductă de când a fost activată. %{linkStart}Executați o conductă%{linkEnd}"
msgid "%{service_ping_link_start}What information is shared with GitLab Inc.?%{service_ping_link_end}"
-msgstr ""
+msgstr "%{service_ping_link_start}Ce informații sunt partajate cu GitLab Inc.?%{service_ping_link_end}"
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -1141,6 +1126,9 @@ msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} vă permit să trimiteÈ
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} vă permit să trimiteți notificări aplicațiilor web ca răspuns la evenimente dintr-un grup sau proiect. Vă recomandăm să utilizați o %{integrations_link_start}integrație%{link_end} de preferință față de un webhook."
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr "%{wildcards_link_start}Jokerii%{wildcards_link_end} cum ar fi %{code_tag_start}v*%{code_tag_end} sau %{code_tag_start}*-lansare%{code_tag_end} sunt acceptați."
@@ -1225,9 +1213,15 @@ msgstr "(eliminat)"
msgid "(revoked)"
msgstr "(revocat)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr "(avem nevoie de parola curentă pentru a confirma modificările)"
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} mai mult"
@@ -1282,6 +1276,9 @@ msgstr[2] "- Evenimente"
msgid "- Not available to run jobs."
msgstr "- Nedisponibil pentru a executa joburi."
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- Utilizator"
@@ -1298,7 +1295,7 @@ msgid "."
msgstr "."
msgid "/"
-msgstr ""
+msgstr "/"
msgid "0 bytes"
msgstr "0 octeți"
@@ -1454,7 +1451,7 @@ msgid "1000+"
msgstr "1000+"
msgid "192.168.0.0/24"
-msgstr ""
+msgstr "192.168.0.0/24"
msgid "1st contribution!"
msgstr "Prima contribuție!"
@@ -1552,9 +1549,6 @@ msgstr "O ramură implicită nu poate fi aleasă pentru un proiect gol."
msgid "A deleted user"
msgstr "Un utilizator șters"
-msgid "A description is required"
-msgstr "Descrierea este necesară"
-
msgid "A different reason"
msgstr "Un motiv diferit"
@@ -1588,8 +1582,8 @@ msgstr "Un membru al echipei de combatere a abuzurilor va analiza raportul dumne
msgid "A merge request hasn't yet been merged"
msgstr "O cerere de îmbinare nu a fost încă îmbinată"
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
-msgstr "O nouă conductă Auto DevOps a fost creată, mergeți pe %{pipelines_link_start}pagina Conducte%{pipelines_link_end} pentru detalii."
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
+msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
msgstr "A fost publicată o nouă versiune %{tag} pentru %{name}. Vizitați pagina %{release_link_start}pagina Lansări%{release_link_end} pentru a citi mai multe despre aceasta."
@@ -1615,6 +1609,9 @@ msgstr "O valoare a platformei poate fi web, mob sau aplicație."
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr "Un cazan proiect pentru o dezvoltarea unei aplicații Salesforce cu unelte de dezvoltatori Salesforce"
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr "Un proiect care să conțină aspecte pentru fiecare anchetă de audit din Protocolul de audit HIPAA publicat de Departamentul de Sănătate și Servicii Umane al SUA."
@@ -1963,6 +1960,9 @@ msgstr "Acțiuni"
msgid "Activate Service Desk"
msgstr "Activați Biroul de Servicii"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Activ"
@@ -2044,9 +2044,6 @@ msgstr "Adăugați un mesaj personalizat cu detalii despre rulourile partajate a
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Adăugați un comentariu general la acest %{noteableDisplayName}."
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "Adăugați un comentariu general la acest %{noteable_name}."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Adăugați o pagină de pornire în wiki-ul dvs care conține informații despre proiectul dvs, iar GitLab îl va afișa aici în locul acestui mesaj."
@@ -2125,9 +2122,6 @@ msgstr "Adăugați înghețarea implementării"
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr "Adăugați chei de implementare pentru a acorda acces de citire/scriere la acest repozitoriu. %{link_start}Ce sunt cheile de implementare?%{link_end}"
-msgid "Add domain"
-msgstr "Adăugați domeniu"
-
msgid "Add email address"
msgstr "Adăugați adresă e-mail"
@@ -2221,6 +2215,9 @@ msgstr "Adăugați pentru revizuire"
msgid "Add to tree"
msgstr "Adăugare la arbore"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr "Adăugare declanșator"
@@ -2677,8 +2674,8 @@ msgstr "Ajustați setarea plafonului de utilizatori pe instanța dvs."
msgid "AdminUsers|Admin"
msgstr "Administrator"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
-msgstr "Administratorii au acces la toate grupurile, proiectele și utilizatorii și pot gestiona toate funcțiile din această instalație."
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgstr ""
msgid "AdminUsers|Admins"
msgstr "Administratori"
@@ -2692,6 +2689,12 @@ msgstr "Aprobați utilizatorul %{username}?"
msgid "AdminUsers|Approved users can:"
msgstr "Utilizatorii aprobați pot:"
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr "Marcat automat ca utilizator intern implicit"
@@ -2827,8 +2830,8 @@ msgstr "Reactivarea unui utilizator va:"
msgid "AdminUsers|Regular"
msgstr "Regular"
-msgid "AdminUsers|Regular users have access to their groups and projects"
-msgstr "Utilizatorii obișnuiți au acces la grupurile și proiectele lor"
+msgid "AdminUsers|Regular users have access to their groups and projects."
+msgstr ""
msgid "AdminUsers|Reject"
msgstr "Respingere"
@@ -3044,7 +3047,7 @@ msgid "After you've reviewed these contribution guidelines, you'll be all set to
msgstr "După ce ați examinat aceste reguli privind contribuțiile, veți fi gata să"
msgid "Akismet"
-msgstr ""
+msgstr "Akismet"
msgid "Akismet API Key"
msgstr "Cheia API Akismet"
@@ -3442,8 +3445,8 @@ msgstr "Toate conflictele merge au fost rezolvate. Merge request-ul poate fi acu
msgid "All merge request dependencies have been merged"
msgstr "Toate dependențele din merge request au fost îmbinate."
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
-msgstr "Toate căile de acces sunt relative la URL-ul GitLab. Nu includeți %{relative_url_link_start}URL relativ%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
+msgstr ""
msgid "All projects"
msgstr "Toate proiectele"
@@ -3460,6 +3463,9 @@ msgstr "Toți utilizatorii trebuie să accepte Termenii și condițiile și Poli
msgid "All users must have a name."
msgstr "Toți utilizatorii trebuie să aibă un nume."
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Permiteți \"%{group_name}\" să vă conecteze"
@@ -3475,8 +3481,8 @@ msgstr "Permiteți commit-uri de la membri care pot îmbina la ramura țintă."
msgid "Allow group owners to manage LDAP-related settings"
msgstr "Permiteți proprietarilor de grup să gestioneze setările legate de LDAP"
-msgid "Allow non-administrators to access to the performance bar"
-msgstr "Permiteți non-administratorilor accesul la bara de performanță"
+msgid "Allow non-administrators access to the performance bar"
+msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Permiteți utilizarea numai protocoalelor selectate pentru accesul Git."
@@ -3715,14 +3721,17 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr "A apărut o eroare în timpul obținerii predecesorilor"
-msgid "An error occurred while fetching branches. Retry the search."
-msgstr "S-a produs o eroare în timpul preluării ramurilor. Reîncercați căutarea."
+msgid "An error occurred while fetching branches. Retry the search."
+msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr "A apărut o eroare în timpul preluării rapoartelor codequality diff cerere de îmbinare."
-msgid "An error occurred while fetching commits. Retry the search."
-msgstr "A apărut o eroare în timpul preluării comiterilor. Reîncercați căutarea."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
+msgstr ""
msgid "An error occurred while fetching coverage reports."
msgstr "S-a produs o eroare în timpul obținerii rapoartelor de acoperire."
@@ -3925,6 +3934,12 @@ msgstr "A apărut o eroare în timpul recuperării proiectelor."
msgid "An error occurred while saving changes: %{error}"
msgstr "A apărut o eroare în timpul salvării modificărilor: %{error}"
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "A apărut o eroare la abonarea la notificări."
@@ -3988,9 +4003,6 @@ msgstr "Un proiect de exemplu care prezintă cele mai bune practici pentru confi
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr "Un exemplu care arată cum să utilizați Jsonnet cu conducte dinamice copii ale GitLab"
-msgid "An instance-level serverless domain already exists."
-msgstr "Există deja un domeniu fără server la nivel de instanță."
-
msgid "An issue already exists"
msgstr "Există deja o problemă"
@@ -4242,9 +4254,9 @@ msgstr "Aplică"
msgid "Apply %d suggestion"
msgid_plural "Apply %d suggestions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "Aplicați %d sugestia"
+msgstr[1] "Aplicați %d sugestiile"
+msgstr[2] "Aplicați %d sugestiile"
msgid "Apply a label"
msgstr "Aplicați o etichetă"
@@ -4330,12 +4342,18 @@ msgstr "Toate scanerele"
msgid "ApprovalRule|All severity levels"
msgstr "Toate nivelele de severitate"
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr "Aplicați această regulă de aprobare pentru a lua în considerare doar scanerele de securitate selectate."
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr "Aplicați această regulă de aprobare pentru a considera doar nivelele de severitate selectate."
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr "Reguli de aprobare"
@@ -4348,12 +4366,21 @@ msgstr "Tip aprobator"
msgid "ApprovalRule|Approvers"
msgstr "Aprobatori"
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr "Exemple: QA, Securitate."
msgid "ApprovalRule|Name"
msgstr "Nume"
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr "Numărul de vulnerabilități permise înainte de declanșarea regulii de aprobare."
@@ -4366,6 +4393,15 @@ msgstr "Vă rugăm să selectați cel puțin un scaner de securitate"
msgid "ApprovalRule|Please select at least one severity level"
msgstr "Vă rugăm selectați măcar un nivel de severitate"
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr "Numele regulii"
@@ -4381,6 +4417,9 @@ msgstr "Selectați scanerele"
msgid "ApprovalRule|Select severity levels"
msgstr "Selectați nivele de severitate"
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr "Nivele severitate"
@@ -4390,6 +4429,9 @@ msgstr "Ramura țintă"
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr "Vulnerabilități permise"
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "Setările de aprobare a cererilor de îmbinare au fost actualizate."
@@ -4663,12 +4705,6 @@ msgstr "Sunteți sigur? Eliminarea acestei chei GPG nu afectează commit-urile d
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr "Sunteți sigur? Dispozitivul va fi deconectat de la GitLab și toate token-urile de tip \"remember me\" vor fi revocate."
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr "Ești sigur? Acest lucru va invalida aplicațiile înregistrate și dispozitivele U2F / WebAuthn."
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr "Sunteți sigur? Acest lucru va invalida aplicațiile și dispozitivele U2F înregistrate."
-
msgid "Arrange charts"
msgstr "Aranjați diagramele"
@@ -4906,6 +4942,9 @@ msgstr "August"
msgid "Authenticate"
msgstr "Autentificare"
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr "Autentificare cu GitHub"
@@ -5539,11 +5578,14 @@ msgstr "Blocuri"
msgid "Blog"
msgstr "Blog"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
msgid "BoardNewEpic|Groups"
-msgstr ""
+msgstr "Grupuri"
msgid "BoardNewEpic|Loading groups"
msgstr ""
@@ -5782,8 +5824,8 @@ msgstr "Toate"
msgid "Branches|Cancel, keep branch"
msgstr "Anulați, păstrați ramura"
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "Nu se poate găsi commit-ul HEAD pentru această ramură"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "Comparați"
@@ -5893,6 +5935,9 @@ msgstr "Pentru a confirma, tastați %{branch_name_confirmation}:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr "Da, ștergeți ramura"
@@ -6100,9 +6145,6 @@ msgstr "CI Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr "Minute CI"
-
msgid "CI settings"
msgstr "Setări CI"
@@ -6281,7 +6323,7 @@ msgid "Can be manually deployed to"
msgstr "Poate fi implementat manual la"
msgid "Can be overridden in each project."
-msgstr ""
+msgstr "Poate fi suprascris în fiecare proiect."
msgid "Can create groups:"
msgstr ""
@@ -6388,9 +6430,6 @@ msgstr "Previzualizare anulare"
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6448,6 +6487,12 @@ msgstr "Nu se poate sări peste configurarea autentificării în doi pași"
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6778,6 +6823,9 @@ msgstr "Pachet minute CI"
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr "Pachete minute CI sunt folosite numai după ce v-ați utilizat cota lunară a abonamentului dvs. Minutele suplimentare se vor roti din lună-n-lună și sunt valide pentru un an."
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6811,6 +6859,9 @@ msgstr " Formularul cardului de credit nu s-a încărcat: %{message}"
msgid "Checkout|Edit"
msgstr "Editați"
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr "Exp %{expirationMonth}/%{expirationYear}"
@@ -6833,7 +6884,7 @@ msgid "Checkout|Failed to register credit card. Please try again."
msgstr ""
msgid "Checkout|GB"
-msgstr ""
+msgstr "GB"
msgid "Checkout|GitLab group"
msgstr "Grup GitLab"
@@ -6923,10 +6974,13 @@ msgid "Checkout|company or team"
msgstr "companie sau echipă"
msgid "Checkout|minutes"
+msgstr "minute"
+
+msgid "Checkout|x %{quantity} %{units} per pack"
msgstr ""
msgid "Checkout|x %{quantity} %{units} per pack ="
-msgstr ""
+msgstr "x %{quantity}%{units} per pachet ="
msgid "Cherry-pick this commit"
msgstr "Cherry-pick acest commit"
@@ -6967,15 +7021,9 @@ msgstr "Alegeți un șablon…"
msgid "Choose a type..."
msgstr "Alegeți un tip…"
-msgid "Choose any color"
-msgstr "Alegeți orice culoare"
-
msgid "Choose any color."
msgstr "Alegeți orice culoare."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr "Alegeți orice culoare. Sau puteți alege una dintre culorile sugerate mai jos"
-
msgid "Choose file…"
msgstr "Alegeți fișierul…"
@@ -7391,7 +7439,7 @@ msgid "ClusterAgents|Configuration"
msgstr ""
msgid "ClusterAgents|Connected"
-msgstr ""
+msgstr "Conectat"
msgid "ClusterAgents|Connection status"
msgstr ""
@@ -7618,7 +7666,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8059,6 +8107,9 @@ msgstr " Grup de securitate"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Vizualizați și editați detaliile pentru clusterul dvs. Kubernetes"
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr " Selectați un VPC pentru a alege un grup de securitate"
@@ -8068,6 +8119,9 @@ msgstr " Selectați un VPC pentru a alege o subrețea"
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr "Selectați un VPC care să fie utilizat pentru resursele Clusterului EKS. Pentru a utiliza un VPC nou, creați mai întâi unul pe %{linkStart}Amazon Web Services %{linkEnd}."
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr " Selectați o rețea pentru a alege o subrețea"
@@ -8077,9 +8131,24 @@ msgstr "Selectați o regiune pentru a alege o pereche de chei"
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr "Selectați o regiune pentru a alege un VPC"
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr " Selectați o zonă pentru a alege o rețea"
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "Selectați tipul mașinii"
@@ -8092,6 +8161,9 @@ msgstr "Selectați proiectul și zona pentru a alege tipul mașinii"
msgid "ClusterIntegration|Select project to choose zone"
msgstr "Selectați proiectul pentru a alege zona"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr "Selectați numele perechii de chei care va fi utilizată pentru a crea noduri EC2. Pentru a utiliza un nou nume de pereche de chei, creați mai întâi unul pe %{linkStart}Amazon Web Services%{linkEnd}."
@@ -8242,30 +8314,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8404,12 +8452,6 @@ msgstr ""
msgid "Comment"
msgstr "Comentariu"
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8527,6 +8569,9 @@ msgstr "Forumul comunității"
msgid "Company"
msgstr "Companie"
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8608,31 +8653,37 @@ msgstr "Complet"
msgid "Completed"
msgstr ""
-msgid "Compliance"
-msgstr "Conformitate"
-
-msgid "Compliance Dashboard"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
msgid "Compliance framework"
msgstr ""
+msgid "Compliance report"
+msgstr ""
+
msgid "ComplianceDashboard|created by:"
msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8641,6 +8692,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8653,31 +8710,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8749,15 +8806,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8902,6 +8953,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9028,12 +9082,12 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
+msgid "ContainerRegistry|Delete tag"
+msgstr ""
+
msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr "Ștergerea depozitului de imagine va șterge toate imaginile și etichetele din interior. Această acțiune nu poate fi anulată. Introduceți următoarele pentru a confirma: %{code}"
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
-msgstr ""
-
msgid "ContainerRegistry|Digest: %{imageId}"
msgstr ""
@@ -9229,7 +9283,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9253,9 +9307,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9376,9 +9427,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9448,9 +9496,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9535,9 +9580,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9643,6 +9685,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9661,6 +9706,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9673,9 +9721,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9691,6 +9736,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9826,6 +9874,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9943,7 +9994,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10066,10 +10117,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10126,6 +10174,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10180,6 +10231,15 @@ msgstr "Interval personalizat"
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10339,6 +10399,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10408,6 +10471,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10903,6 +10969,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10969,6 +11038,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11008,16 +11080,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11092,9 +11182,6 @@ msgstr ""
msgid "Delete corpus"
msgstr "Eliminare corpus"
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11122,9 +11209,6 @@ msgstr "Eliminare rând"
msgid "Delete self monitoring project"
msgstr "Ștergeți proiectul de auto-monitorizare"
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11152,6 +11236,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11317,14 +11404,14 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
-msgstr "Prefix imagine proxy dependență"
+msgid "DependencyProxy|Copy prefix"
+msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
msgstr ""
@@ -11332,7 +11419,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11654,7 +11753,10 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11758,6 +11860,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11773,15 +11881,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11833,6 +11938,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11911,6 +12019,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11956,6 +12067,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr "Acest grup nu are subgrupuri"
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12145,12 +12259,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12244,18 +12352,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12286,9 +12382,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr "Descărcați (%{fileSizeReadable})"
@@ -12514,6 +12607,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12838,10 +12934,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12967,8 +13060,11 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
-msgstr "Introduceți un număr întreg între 0 și 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
+msgstr ""
msgid "Enter at least three characters to search"
msgstr ""
@@ -13022,7 +13118,10 @@ msgid "Enterprise"
msgstr "ÃŽntreprindere"
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13123,7 +13222,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13423,6 +13522,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13600,6 +13702,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr "Eroare: %{error_message}"
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13897,9 +14002,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr "Cu excepția politicii:"
@@ -13981,6 +14083,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr "Data expirării (opțional)"
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13996,6 +14101,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14023,9 +14131,6 @@ msgstr "Explorați grupurile publice"
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14038,6 +14143,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14122,6 +14233,12 @@ msgstr "Adăugarea unei întâlniri Zoom a eșuat"
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14356,9 +14473,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14551,6 +14665,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14803,6 +14920,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15034,6 +15154,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15094,6 +15217,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15670,6 +15796,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15709,6 +15838,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15724,9 +15856,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15796,10 +15925,10 @@ msgstr "Salvați modificările"
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15847,6 +15976,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16156,6 +16288,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16324,12 +16459,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16558,7 +16687,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16621,9 +16750,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr "Selectați un subgrup de utilizat ca sursă pentru șabloane de proiect personalizate pentru acest grup."
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr "Setați mărimea maximă a Pagini GitLab pentru acest grup. %{link_start}Aflați mai multe.%{link_end}"
@@ -16726,7 +16861,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16855,6 +16990,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16939,7 +17077,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17002,9 +17140,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17026,6 +17161,9 @@ msgstr "Istoric"
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17050,6 +17188,9 @@ msgstr "Hostname utilizat în e-mailuri comitere private. %{learn_more}"
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17062,6 +17203,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17635,6 +17779,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr "Aveți un minut?"
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr "Ușor"
@@ -17695,6 +17842,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17749,6 +17899,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr "Sporiți Eficiența Operațională"
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17767,6 +17920,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr "Invitați-vă echipa astăzi pentru a construi cod mai bun (și procese) împreună"
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18280,6 +18442,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18382,6 +18547,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18421,6 +18589,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18604,6 +18775,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18679,9 +18853,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr "Tip politică invalid"
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18781,6 +18952,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18799,6 +18976,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18814,6 +18994,9 @@ msgstr "Configurați funcțiile de securitate"
msgid "InviteMembersModal|Contribute to the codebase"
msgstr "Contribuiți la baza de cod"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18847,6 +19030,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr "Ceva nu a mers bine"
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr "Pe ce ați vrea să se concentreze membri noi? (opțional)"
@@ -19372,6 +19558,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19465,19 +19654,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
-msgstr "A apărut o eroare în timp ce se solicitau date de la Jira. Verificați configurația integrației Jira și încercați din nou."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
+msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
-msgstr "A apărut o eroare în timp ce se solicitau date de la Jira: %{messages}. Verificați configurația integrației Jira și încercați din nou."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
+msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr "URL-ul API Jira pentru conectarea la Jira nu este valid. Verificați-vă URL-ul API Integrație Jira și încercați din nou."
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
-msgstr "Acreditările pentru accesarea Jira nu au permisiunea de a accesa datele. Verificați-vă acreditările integrației Jira și încercați din nou."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
+msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19819,6 +20008,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20074,12 +20269,18 @@ msgstr ""
msgid "Last Activity"
msgstr "Ultima activitate"
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20248,6 +20449,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20878,6 +21082,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21007,6 +21214,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21094,9 +21304,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21220,6 +21427,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr "Numărul maxim de %{name} (%{count}) a fost depășit"
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21229,6 +21439,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21490,6 +21703,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr "Îmbinare blocată: tocmai au fost adăugate modificări noi."
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr "Îmbinare blocată: ramura sursă trebuie să fie rebazată pe ramura țintă."
@@ -21535,6 +21751,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21607,6 +21826,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21763,34 +21991,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr "Anotația nu poate aparține atât unui cluster, cât și unui mediu în același timp"
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr "Anotația nu a fost ștearsă"
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
-msgstr "Anotația trebuie să aparțină unui cluster sau unui mediu"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
-msgstr "Tabloul de bord cu calea solicitată nu poate fi găsit"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
-msgstr "Nu sunteți autorizat să creați anotații pentru clusterul selectat"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
-msgstr "Nu sunteți autorizat să creați anotații pentru mediul selectat"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
-msgstr "Nu sunteți autorizat să ștergeți această anotație"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr "nu poate fi înainte de a începe_la ora"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
+msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21817,6 +22039,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21910,9 +22138,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22048,9 +22273,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22498,6 +22720,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22615,6 +22840,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22681,9 +22909,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22993,6 +23218,9 @@ msgstr "Etichetă nouă"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23107,7 +23335,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23122,6 +23350,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23317,6 +23548,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23374,9 +23608,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23614,18 +23845,15 @@ msgstr "Numărul de împingeri Git după ce un %{code_start}git repack%{code_end
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23677,9 +23905,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23881,6 +24106,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23893,6 +24121,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23905,6 +24139,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23920,6 +24157,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24034,15 +24274,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24091,9 +24331,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24121,6 +24358,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24130,6 +24370,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24199,6 +24442,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24274,9 +24547,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24457,14 +24727,17 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24497,7 +24770,7 @@ msgid "PackageRegistry|Remove package"
msgstr ""
msgid "PackageRegistry|Required Python: %{pythonVersion}"
-msgstr ""
+msgstr "Python necesar: %{pythonVersion}"
msgid "PackageRegistry|RubyGems"
msgstr ""
@@ -24508,9 +24781,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24713,16 +24983,16 @@ msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "PasswordPrompt|Confirm password"
-msgstr ""
+msgstr "Confirmați parola"
msgid "PasswordPrompt|Confirm password to continue"
-msgstr ""
+msgstr "Confirmați parola pentru a continua"
msgid "PasswordPrompt|Password is required"
-msgstr ""
+msgstr "Parola este necesară"
msgid "PasswordPrompt|Please enter your password to confirm"
-msgstr ""
+msgstr "Vă rugăm să introduceți parola pentru a confirma"
msgid "Passwords should be unique and not used for any other sites or services."
msgstr ""
@@ -24752,7 +25022,7 @@ msgid "Paste project path (i.e. gitlab-org/gitlab)"
msgstr "Inserați traiectoria proiectului (i.e. gitlab-org/gitlab)"
msgid "Paste this DSN into your Sentry SDK"
-msgstr ""
+msgstr "Lipiți acest DSN în SDK-ul dvs. Sentry"
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
msgstr ""
@@ -24769,6 +25039,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24790,6 +25063,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -24839,7 +25115,7 @@ msgid "PerformanceBar|First Contentful Paint"
msgstr ""
msgid "PerformanceBar|Flamegraph with mode:"
-msgstr ""
+msgstr "Flamegraph cu modul:"
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -24875,13 +25151,13 @@ msgid "PerformanceBar|Trace"
msgstr ""
msgid "PerformanceBar|cpu"
-msgstr ""
+msgstr "cpu"
msgid "PerformanceBar|object"
-msgstr ""
+msgstr "obiect"
msgid "PerformanceBar|wall"
-msgstr ""
+msgstr "perete"
msgid "Period in seconds"
msgstr "Perioadă în secunde"
@@ -25112,46 +25388,46 @@ msgid "PipelineSchedules|Variables"
msgstr ""
msgid "PipelineSource|API"
-msgstr ""
+msgstr "API"
msgid "PipelineSource|Chat"
-msgstr ""
+msgstr "Chat"
msgid "PipelineSource|External"
msgstr ""
msgid "PipelineSource|External Pull Request"
-msgstr ""
+msgstr "Pull Request Extern"
msgid "PipelineSource|Merge Request"
-msgstr ""
+msgstr "Merge Request"
msgid "PipelineSource|On-Demand DAST Scan"
-msgstr ""
+msgstr "Scanare DAST la cerere"
msgid "PipelineSource|On-Demand DAST Validation"
-msgstr ""
+msgstr "Validare DAST la cerere"
msgid "PipelineSource|Parent Pipeline"
-msgstr ""
+msgstr "Pipeline Părinte"
msgid "PipelineSource|Pipeline"
-msgstr ""
+msgstr "Pipeline"
msgid "PipelineSource|Push"
-msgstr ""
+msgstr "Push"
msgid "PipelineSource|Schedule"
-msgstr ""
+msgstr "Program"
msgid "PipelineSource|Trigger"
msgstr ""
msgid "PipelineSource|Web"
-msgstr ""
+msgstr "Web"
msgid "PipelineSource|Web IDE"
-msgstr ""
+msgstr "IDE Web"
msgid "PipelineStatusTooltip|Pipeline: %{ciStatus}"
msgstr ""
@@ -25297,6 +25573,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25417,6 +25696,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25454,7 +25736,7 @@ msgid "Pipeline|Source"
msgstr "Sursa"
msgid "Pipeline|Source|Security Policy"
-msgstr ""
+msgstr "Politică de securitate"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default."
msgstr ""
@@ -25505,7 +25787,7 @@ msgid "Pipeline|We are currently unable to fetch pipeline data"
msgstr ""
msgid "Pipeline|You’re about to stop pipeline #%{pipelineId}."
-msgstr ""
+msgstr "Sunteți pe cale să opriți pipeline-ul #%{pipelineId}."
msgid "Pipeline|for"
msgstr ""
@@ -25534,6 +25816,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25636,9 +25921,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25783,6 +26074,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25898,7 +26192,7 @@ msgid "Prevent adding new members to project membership within this group"
msgstr ""
msgid "Prevent auto-stopping"
-msgstr ""
+msgstr "Preveniți oprirea automată"
msgid "Prevent editing approval rules in projects and merge requests."
msgstr ""
@@ -25913,7 +26207,7 @@ msgid "Prevent users from changing their profile name"
msgstr ""
msgid "Prevent users from performing write operations while GitLab maintenance is in progress."
-msgstr ""
+msgstr "Împiedicați utilizatorii să efectueze operațiuni de scriere în timp ce întreținerea GitLab este în curs de desfășurare."
msgid "Preview"
msgstr ""
@@ -26059,12 +26353,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26074,9 +26374,6 @@ msgstr "Sunteți pe cale să ștergeți definitiv %{yourAccount} și toate probl
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26104,6 +26401,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26186,7 +26486,7 @@ msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
msgid "Profiles|Enter your password to confirm the email change"
-msgstr ""
+msgstr "Introduceți parola pentru a confirma modificarea e-mail-ului"
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
@@ -26395,6 +26695,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26423,7 +26726,7 @@ msgid "Profiles|e.g. My MacBook key"
msgstr ""
msgid "Profiles|https://website.com"
-msgstr ""
+msgstr "https://website.com"
msgid "Profiles|username"
msgstr ""
@@ -26678,10 +26981,10 @@ msgid "ProjectSelect|Search projects"
msgstr ""
msgid "ProjectSelect|Select a project"
-msgstr ""
+msgstr "Selectați un proiect"
msgid "ProjectSelect|There was an error fetching the projects. Please try again."
-msgstr ""
+msgstr "A existat o eroare la preluarea proiectelor. Vă rugăm să încercați din nou."
msgid "ProjectService|Drone server URL"
msgstr ""
@@ -26695,6 +26998,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26710,6 +27016,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26893,6 +27202,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26905,6 +27217,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27082,6 +27397,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27172,6 +27490,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27188,7 +27509,7 @@ msgid "Projects are graded based on the highest severity vulnerability present"
msgstr ""
msgid "Projects are organized into groups"
-msgstr ""
+msgstr "Proiectele sunt organizate în grupuri"
msgid "Projects contributed to"
msgstr ""
@@ -27253,6 +27574,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27280,6 +27604,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27295,6 +27622,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27310,54 +27640,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27661,9 +27946,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr "Traiectorii protejate: cereri"
@@ -27679,6 +27961,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27817,6 +28102,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27829,6 +28117,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28015,9 +28306,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr "În așteptare"
@@ -28051,6 +28339,9 @@ msgstr "Limite frecvență"
msgid "Rate limit"
msgstr "Limită frecvență"
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28127,7 +28418,7 @@ msgid "Receive any notifications from GitLab."
msgstr "Primiți orice notificare de la GitLab."
msgid "Receive notification of abuse reports by email."
-msgstr ""
+msgstr "Primiți notificări cu privire la rapoartele de abuz prin e-mail."
msgid "Receive notifications about your own activity"
msgstr ""
@@ -28138,15 +28429,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28370,7 +28661,7 @@ msgid "Release|Something went wrong while saving the release details."
msgstr ""
msgid "Reload page"
-msgstr ""
+msgstr "Reîncărcați pagina"
msgid "Remediations"
msgstr ""
@@ -28630,6 +28921,9 @@ msgstr "Redați diagrame în documentele dvs. utilizând PlantUML."
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28966,6 +29260,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28975,9 +29272,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29056,14 +29350,14 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29413,9 +29707,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29440,6 +29731,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29449,6 +29749,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29500,6 +29803,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29521,6 +29827,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29560,6 +29884,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr "Ceva nu a mers bine în timpul preluării datelor executorilor."
@@ -29623,6 +29950,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29653,15 +29983,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29758,9 +30079,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30100,6 +30418,9 @@ msgstr[2] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30325,16 +30646,19 @@ msgstr "A apărut o eroare la desemnarea proiectului dvs. al politicii de securi
msgid "SecurityOrchestration|Description"
msgstr "Descriere"
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr "Editați politica"
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30385,6 +30709,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30403,6 +30730,9 @@ msgstr "Selectați proiect de securitate"
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr "Ne pare rău, filtrul dvs. nu a produs rezultate"
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30472,6 +30802,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30493,9 +30826,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30529,6 +30859,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30538,6 +30877,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr "Limita maximă de proiecte selectate a fost atinsă"
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30568,6 +30910,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30691,6 +31036,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30730,11 +31078,11 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
-msgstr "Selectați un cadru care se aplică acestui proiect. %{linkStart}Cum se adaugă acestea?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
msgid "Select a group to invite"
msgstr ""
@@ -30751,15 +31099,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31018,9 +31360,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31120,9 +31459,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31177,9 +31513,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31270,9 +31603,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31306,10 +31636,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31375,6 +31705,12 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31720,9 +32056,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31789,6 +32122,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31813,6 +32149,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31822,6 +32161,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31846,9 +32188,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32443,12 +32782,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32488,6 +32821,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32986,7 +33322,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33085,18 +33421,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33118,9 +33448,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33133,12 +33460,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33154,30 +33475,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33205,9 +33511,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33220,9 +33523,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33265,6 +33565,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33451,6 +33754,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33475,6 +33781,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33487,6 +33802,9 @@ msgstr "Declanșați TeamCity CI după ce un merge request a fost creat sau actu
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33865,6 +34183,9 @@ msgstr[2] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33934,6 +34255,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33964,9 +34288,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34036,6 +34357,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34120,6 +34444,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34225,9 +34552,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34261,9 +34585,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34423,6 +34744,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34507,6 +34831,9 @@ msgstr "A apărut o problemă în timpul preluării grupurilor recente."
msgid "There was a problem fetching recent projects."
msgstr "A apărut o problemă în timpul preluării proiectelor recente."
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr "A apărut o problemă în timpul preluării valorii domeniului de aplicare al tokenului jobului"
@@ -34693,9 +35020,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34918,7 +35242,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35221,6 +35545,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35359,6 +35689,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35692,7 +36025,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35728,7 +36061,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35914,6 +36247,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36007,7 +36355,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36376,6 +36724,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36460,6 +36811,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36793,6 +37147,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36811,10 +37168,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36826,6 +37183,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36871,9 +37231,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36913,10 +37270,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37066,6 +37423,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37096,6 +37456,9 @@ msgstr "Utilizați comenzi slash."
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37162,6 +37525,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37513,6 +37882,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37522,6 +37894,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37567,11 +37948,23 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
-msgstr "Timpul mediu de la primul merge request creat până la închiderea problemei."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
+msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
msgstr ""
@@ -38233,6 +38626,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38428,6 +38824,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr "Pentru ce veți folosi acest grup?"
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38437,9 +38836,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38452,6 +38848,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "Când acest merge request este acceptat"
@@ -38461,9 +38860,6 @@ msgstr[2] "Când aceste merge request-uri sunt acceptate"
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38770,10 +39166,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38815,9 +39211,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38884,6 +39277,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39040,9 +39436,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39142,9 +39535,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39232,6 +39622,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39241,9 +39634,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39275,10 +39665,10 @@ msgid "You must upload a file with the same file name when dropping onto an exis
msgstr ""
msgid "You need a different license to enable FileLocks feature"
-msgstr ""
+msgstr "Aveți nevoie de o licență diferită pentru a activa caracteristica FileLocks"
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
-msgstr ""
+msgstr "Aveți nevoie de versiunea git-lfs %{min_git_lfs_version} (sau mai mare) pentru a continua. Vizitați https://git-lfs.github.com"
msgid "You need permission."
msgstr ""
@@ -39392,13 +39782,13 @@ msgid "You've already enabled two-factor authentication using one time password
msgstr ""
msgid "You've rejected %{user}"
-msgstr ""
+msgstr "Ați respins %{user}"
msgid "YouTube"
-msgstr ""
+msgstr "YouTube"
msgid "YouTube URL or ID"
-msgstr ""
+msgstr "Adresa URL sau ID-ul YouTube"
msgid "Your %{group} membership will now expire in %{days}."
msgstr "Abonamentul dvs. %{group} va expira acum în %{days}."
@@ -39697,28 +40087,55 @@ msgstr[2] ""
msgid "Your username is %{username}."
msgstr "Numele dvs. de utilizator este %{username}."
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
-msgstr "Adresa URL de bază a instanței Zentao."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
-msgid "ZentaoIntegration|Enter API token"
-msgstr "Introduceți token-ul API"
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
+msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr "Dacă este diferit de URL-ul web."
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
-msgstr "Folosiți Zentao ca instrument de urmărire a problemelor din acest proiect."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
+msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
-msgstr "Token API Zentao"
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39730,6 +40147,9 @@ msgstr ""
msgid "[No reason]"
msgstr "[Fără motiv]"
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr "[Redacted]"
@@ -39742,9 +40162,6 @@ msgstr "`start_time` ar trebui să preceadă `end_time`"
msgid "a deleted user"
msgstr "un utilizator șters"
-msgid "a design"
-msgstr "un design"
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] "cam 1 oră"
@@ -39853,12 +40270,18 @@ msgstr "poate fi schimbat doar de un administrator de grup."
msgid "can only have one escalation policy"
msgstr "poate avea doar o singură politică de escaladare"
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr "nu poate include: %{invalid_storages}"
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr "nu poate fi o dată în trecut"
@@ -39886,6 +40309,9 @@ msgstr ""
msgid "cannot be modified"
msgstr "nu poate fi modificat"
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr "nu poate bloca pe alții"
@@ -39901,9 +40327,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr "%{degradedNum} degradat"
@@ -39934,6 +40357,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "%{remainingPackagesCount} mai mult"
@@ -39970,9 +40396,21 @@ msgstr "Aplică automat patch-ul într-o ramură nouă"
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39982,8 +40420,14 @@ msgstr "Verificări"
msgid "ciReport|Cluster Image Scanning"
msgstr "Scanare Imagini Cluster"
-msgid "ciReport|Code quality"
-msgstr "Calitatea codului"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
msgid "ciReport|Container Scanning"
msgstr "Scanare container"
@@ -40048,6 +40492,18 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40081,11 +40537,11 @@ msgstr "SAST"
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
-msgstr "Scanare secretă"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
+msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
-msgstr "Scanarea secretă detectează secretele și vulnerabilitățile credențialelor din codul dvs. sursă."
+msgid "ciReport|Secret detection"
+msgstr ""
msgid "ciReport|Security scanning"
msgstr "Scanare de securitate"
@@ -40142,7 +40598,7 @@ msgid "closed"
msgstr "închis"
msgid "closed issue"
-msgstr ""
+msgstr "problemă închisă"
msgid "codeQualityWalkthrough|A code quality job will now run every time you or your team members commit changes to your project. You can view the results of the code quality job in the job logs."
msgstr ""
@@ -40204,6 +40660,12 @@ msgstr "container_name poate conține numai litere mici, cifre, '-' și '.' și
msgid "container_name cannot be larger than %{max_length} chars"
msgstr "container_name nu poate fi mai mare de %{max_length} caractere"
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr "contribuie la acest proiect."
@@ -40261,9 +40723,6 @@ msgstr ""
msgid "design"
msgstr "design"
-msgid "designs"
-msgstr "design-uri"
-
msgid "detached"
msgstr "detașat"
@@ -40276,6 +40735,12 @@ msgstr "nu există"
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr "nu are o extensie acceptată. Doar %{extension_list} sunt acceptate"
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr "descărcați-l"
@@ -40291,6 +40756,9 @@ msgstr "ex. %{token}"
msgid "element is not a hierarchy"
msgstr "elementul nu este o ierarhie"
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr "e-mail-ul '%{email}' nu este un e-mail verificat."
@@ -40325,6 +40793,9 @@ msgid "estimateCommand|%{slash_command} overwrites the total estimated time."
msgstr "%{slash_command}suprascrie timpul total estimat."
msgid "example.com"
+msgstr "example.com"
+
+msgid "exceeds the %{max_value_length} character limit"
msgstr ""
msgid "exceeds the limit of %{bytes} bytes"
@@ -40454,19 +40925,19 @@ msgid "in"
msgstr "în"
msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
+msgstr "în Infrastructură: Clustere Kubernetes"
msgid "in all GitLab"
msgstr ""
msgid "in group"
-msgstr ""
+msgstr "în grup"
msgid "in group %{link_to_group}"
msgstr "în grupul %{link_to_group}"
msgid "in project"
-msgstr ""
+msgstr "în proiect"
msgid "in project %{link_to_project}"
msgstr "în proiectul %{link_to_project}"
@@ -40514,10 +40985,10 @@ msgid "is not allowed for sign-up."
msgstr ""
msgid "is not allowed for this group."
-msgstr ""
+msgstr "nu este permis pentru acest grup."
msgid "is not allowed for this project."
-msgstr ""
+msgstr "nu este permis pentru acest proiect."
msgid "is not allowed since the group is not top-level group."
msgstr "nu este permis, deoarece grupul nu este un grup de nivel superior."
@@ -40528,6 +40999,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40616,7 +41093,7 @@ msgid "log in"
msgstr "autentificare"
msgid "managed"
-msgstr ""
+msgstr "gestionat"
msgid "manual"
msgstr "manual"
@@ -40687,6 +41164,9 @@ msgstr "%{metricsLinkStart} Memoria %{metricsLinkEnd} utilizată este %{emphasis
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr "%{prefixToLinkStart}Fără pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Adaugați fișierul .gitlab-ci.yml%{addPipelineLinkEnd} pentru a crea unul."
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr "Un nou merge train a început și acest merge request este primul în coada de așteptare."
@@ -40720,6 +41200,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr "Aprobat de"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40783,6 +41269,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr "Salt la primul subiect nerezolvat"
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40816,9 +41305,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr "Merge request aprobat."
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40933,12 +41419,6 @@ msgstr "Ramura sursă nu va fi ștearsă"
msgid "mrWidget|There are merge conflicts"
msgstr "Există conflicte de îmbinare"
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr "Această acțiune va adăuga merge request-ul la merge train când pipeline-ul %{pipelineLink} reușește."
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr "Această acțiune va începe un merge train când pipeline-ul %{pipelineLink} reușește."
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Acest merge request nu a reușit să fie îmbinat automat"
@@ -40954,6 +41434,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr "Folosiți %{linkStart}pipeline-uri CI în codul dvs.%{linkEnd} prin simpla adăugare a fișierului de configurare GitLab CI la proiectul dvs. Este nevoie doar de un minut pentru a face codul dvs. mai sigur și mai robust."
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41002,6 +41485,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr "grupul-meu-minunat"
@@ -41077,6 +41566,9 @@ msgstr "sau"
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "din %d test total"
@@ -41174,13 +41666,13 @@ msgid "quick actions"
msgstr "acțiuni rapide"
msgid "reCAPTCHA"
-msgstr ""
+msgstr "reCAPTCHA"
msgid "reCAPTCHA helps prevent credential stuffing."
msgstr ""
msgid "reCAPTCHA private key"
-msgstr ""
+msgstr "cheie privată reCAPTCHA"
msgid "reCAPTCHA site key"
msgstr ""
@@ -41507,8 +41999,8 @@ msgid "your settings"
msgstr "setările dvs."
msgid "{group}"
-msgstr ""
+msgstr "{group}"
msgid "{project}"
-msgstr ""
+msgstr "{project}"
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index 37ea3766125..354070b4675 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ru\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:22\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr " %{start} по %{end}"
@@ -40,29 +40,12 @@ msgstr " Тип"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Вам нужно Ñделать Ñто до %{grace_period_deadline}."
-msgid " and"
-msgstr " и"
-
msgid " and "
msgstr " и "
msgid " and %{sliced}"
msgstr " и %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " ухудшилоÑÑŒ на %d пункт"
-msgstr[1] " ухудшилоÑÑŒ на %d пунктов"
-msgstr[2] " ухудшилоÑÑŒ на %d пунктов"
-msgstr[3] " ухудшилоÑÑŒ на %d пунктов"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " улучшилоÑÑŒ на %d пункт"
-msgstr[1] " улучшилоÑÑŒ на %d пункта"
-msgstr[2] " улучшилоÑÑŒ на %d пунктов"
-msgstr[3] " улучшилоÑÑŒ на %d пунктов"
-
msgid " or "
msgstr " или "
@@ -90,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr "Параметр \"el\" необходим Ð´Ð»Ñ createInstance()"
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -240,9 +226,6 @@ msgstr[1] "%d коммита,"
msgstr[2] "%d коммитов,"
msgstr[3] "%d коммитов,"
-msgid "%d commits"
-msgstr "%d коммитов"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] "%d закрытое обÑуждение"
@@ -1227,6 +1210,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1312,9 +1298,15 @@ msgstr "(удалено)"
msgid "(revoked)"
msgstr "(отозван)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+%{amount} ещё"
@@ -1371,6 +1363,9 @@ msgstr[3] "- СобытиÑ"
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- Пользователь"
@@ -1385,7 +1380,7 @@ msgid "- show less"
msgstr "- Ñвернуть"
msgid "."
-msgstr ""
+msgstr "."
msgid "/"
msgstr ""
@@ -1394,7 +1389,7 @@ msgid "0 bytes"
msgstr "0 байт"
msgid "0t1DgySidms"
-msgstr ""
+msgstr "0t1DgySidms"
msgid "1 Day"
msgid_plural "%d Days"
@@ -1440,10 +1435,10 @@ msgstr[3] ""
msgid "1 day selected"
msgid_plural "%d days selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "1 день выбран"
+msgstr[1] "%d Ð´Ð½Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð¾"
+msgstr[2] "%d дней выбрано"
+msgstr[3] "%d дней выбрано"
msgid "1 deploy key"
msgid_plural "%d deploy keys"
@@ -1665,9 +1660,6 @@ msgstr "Ð”Ð»Ñ Ð¿ÑƒÑтого проекта Ð½ÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð±Ñ€Ð°Ñ‚ÑŒ ветÐ
msgid "A deleted user"
msgstr "Удаленный пользователь"
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1701,8 +1693,8 @@ msgstr "УчаÑтник команды по борьбе Ñ Ð½Ð°Ñ€ÑƒÑˆÐµÐ½Ð¸ÑÐ
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
-msgstr "ÐÐ¾Ð²Ð°Ñ ÑÐ±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ Auto DevOps Ñоздана, обратитеÑÑŒ к %{pipelines_link_start}Ñтранице, поÑвÑщенной Сборочным линиÑм%{pipelines_link_end} за подробноÑÑ‚Ñми"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
+msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
msgstr "Ðовый релиз %{tag} Ð´Ð»Ñ %{name} опубликован. ПоÑетите Ñтраницу %{release_link_start}Релизов%{release_link_end}, чтобы узнать больше."
@@ -1728,6 +1720,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -2076,6 +2071,9 @@ msgstr "ДейÑтвиÑ"
msgid "Activate Service Desk"
msgstr "Ðктивировать Ñлужбу поддержки"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Ðктивный"
@@ -2157,9 +2155,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Добавить общий комментарий Ð´Ð»Ñ Ñтого %{noteableDisplayName}."
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "Добавить общий комментарий к Ñтому %{noteable_name}."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Добавьте домашнюю Ñтраницу в Ñвою Wiki, в которой ÑодержитÑÑ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ вашем проекте, и GitLab отобразит ее здеÑÑŒ вмеÑто Ñтого ÑообщениÑ."
@@ -2238,9 +2233,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr "Добавить домен"
-
msgid "Add email address"
msgstr "Добавить Ð°Ð´Ñ€ÐµÑ Ñлектронной почты"
@@ -2334,6 +2326,9 @@ msgstr "Добавить к рецензированию"
msgid "Add to tree"
msgstr "Добавить к дереву"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2790,7 +2785,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "ÐдминиÑтратор"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2805,6 +2800,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2940,7 +2941,7 @@ msgstr "ÐŸÐ¾Ð²Ñ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð±ÑƒÐ´ÐµÑ
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3555,8 +3556,8 @@ msgstr "Ð’Ñе конфликты ÑлиÑÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ разрешены. Т
msgid "All merge request dependencies have been merged"
msgstr "Ð’Ñе завиÑимоÑти запроÑа на ÑлиÑние были объединены"
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
-msgstr "Ð’Ñе пути должны быть указаны отноÑительно URL GitLab. Ðе указывайте Ñам %{relative_url_link_start}отноÑительный URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
+msgstr ""
msgid "All projects"
msgstr "Ð’Ñе проекты"
@@ -3573,6 +3574,9 @@ msgstr ""
msgid "All users must have a name."
msgstr "У вÑех пользователей должно быть имÑ."
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Разрешить %{group_name} Ð²Ð°Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñать"
@@ -3588,7 +3592,7 @@ msgstr "Разрешить коммиты от учаÑтников, которÑ
msgid "Allow group owners to manage LDAP-related settings"
msgstr "Разрешить владельцам групп управлÑÑ‚ÑŒ наÑтройками, ÑвÑзанными Ñ LDAP"
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3828,13 +3832,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -4038,6 +4045,13 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "При подпиÑке на ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð¾ÑˆÐ»Ð° ошибка."
@@ -4101,9 +4115,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr "Пример, показывающий, как иÑпользовать Jsonnet Ñ Ð´Ð¸Ð½Ð°Ð¼Ð¸Ñ‡ÐµÑкими дочерними Ñборочными линиÑми GitLab"
-msgid "An instance-level serverless domain already exists."
-msgstr "Домен Serverless ÑƒÑ€Ð¾Ð²Ð½Ñ ÑкземплÑра уже ÑущеÑтвует."
-
msgid "An issue already exists"
msgstr "ОбÑуждение уже ÑущеÑтвует"
@@ -4450,12 +4461,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4468,12 +4485,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Утверждающие"
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr "ИмÑ"
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4486,6 +4512,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr "Ðазвание правила"
@@ -4501,6 +4536,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4510,6 +4548,9 @@ msgstr "Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð²ÐµÑ‚ÐºÐ°"
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4784,12 +4825,6 @@ msgstr "Ð’Ñ‹ уверены? Удаление Ñтого ключа GPG не пÐ
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr "Ð’Ñ‹ уверены? Это аннулирует ваши зарегиÑтрированные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸ U2F уÑтройÑтва."
-
msgid "Arrange charts"
msgstr "УпорÑдочить диаграммы"
@@ -5029,6 +5064,9 @@ msgstr "ÐвгуÑÑ‚"
msgid "Authenticate"
msgstr "ÐутентификациÑ"
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr "ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ GitHub"
@@ -5663,6 +5701,9 @@ msgstr "Блокирует"
msgid "Blog"
msgstr "Блог"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "ОблаÑÑ‚ÑŒ дейÑÑ‚Ð²Ð¸Ñ Ð´Ð¾Ñки влиÑет на то, какие задачи отображаютÑÑ Ð´Ð»Ñ Ð²Ñех, кто поÑещает Ñту доÑку"
@@ -5908,8 +5949,8 @@ msgstr "Ð’Ñе"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "Ðевозможно найти HEAD-коммит Ñтой ветки"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "Сравнить"
@@ -6019,6 +6060,9 @@ msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ, введите %{branch_name_confirma
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Чтобы отменить локальные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸ перезапиÑать ветку верÑией из родительÑкого репозиториÑ, удалите её здеÑÑŒ и выберите \"Обновить ÑейчаÑ\" выше."
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6226,9 +6270,6 @@ msgstr "CI Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr "ÐаÑтройки CI"
@@ -6515,9 +6556,6 @@ msgstr "Отмена предварительного проÑмотра"
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr "Ðет возможноÑти объединить автоматичеÑки"
@@ -6575,6 +6613,12 @@ msgstr "Ðевозможно пропуÑтить наÑтройку двухфÐ
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6907,6 +6951,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6940,6 +6987,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -7054,6 +7104,9 @@ msgstr "ÐºÐ¾Ð¼Ð¿Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ команда"
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -7096,15 +7149,9 @@ msgstr "Выберите шаблон..."
msgid "Choose a type..."
msgstr "Выберите тип..."
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr "Выберите любой цвет."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr "Выберите файл…"
@@ -7747,7 +7794,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8188,6 +8235,9 @@ msgstr "Группа безопаÑноÑи"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "ПроÑмотр и редактирование информации о вашем клаÑтере Kubernetes"
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr "Ð”Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° группы безопаÑноÑти необходимо выбрать VPC"
@@ -8197,6 +8247,9 @@ msgstr "Ð”Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° подÑети необходимо выбрать V
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "Ð”Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° подÑети нужно выбрать Ñеть"
@@ -8206,9 +8259,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "Выберите тип машины"
@@ -8221,6 +8289,9 @@ msgstr "Выберите проект и зону, чтобы выбрать Ñ‚Ð
msgid "ClusterIntegration|Select project to choose zone"
msgstr "Выберите проект, чтобы выбрать зону"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8371,30 +8442,6 @@ msgstr "отвечает требованиÑм"
msgid "ClusterIntegration|sign up"
msgstr "зарегиÑтрироватьÑÑ"
-msgid "ClusterIntergation|Select a VPC"
-msgstr "Выберите VPC"
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr "Выберите группу безопаÑноÑти"
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr "Выберите подÑеть"
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr "Выберите подÑеть"
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr "Выберите пару ключей"
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8533,12 +8580,6 @@ msgstr ""
msgid "Comment"
msgstr "Комментарий"
-msgid "Comment & close %{noteable_name}"
-msgstr "Комментировать и закрыть %{noteable_name}"
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr "Комментировать и переоткрыть %{noteable_name}"
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8657,6 +8698,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Сравнение"
@@ -8738,31 +8782,37 @@ msgstr "Завершено"
msgid "Completed"
msgstr ""
-msgid "Compliance"
-msgstr "КомплаенÑ"
-
-msgid "Compliance Dashboard"
-msgstr "Панель ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñлужбы комплаенÑа"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
+msgstr ""
msgid "Compliance framework"
msgstr ""
+msgid "Compliance report"
+msgstr ""
+
msgid "ComplianceDashboard|created by:"
msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8771,6 +8821,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8783,31 +8839,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8879,15 +8935,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr "ÐаÑтроить ÑущеÑтвующую уÑтановку"
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -9032,6 +9082,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "РееÑÑ‚Ñ€ контейнеров"
@@ -9160,10 +9213,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9362,7 +9415,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9386,9 +9439,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr "Ð’Ñ‹ можете добавить образ в Ñтот рееÑÑ‚Ñ€ контвейнеров при помощи данных команд:"
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr "Содержит %{count} изображений (%{size})"
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9509,9 +9559,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr "Копировать %{proxy_url}"
-
msgid "Copy %{type}"
msgstr ""
@@ -9581,9 +9628,6 @@ msgstr "Копировать ÑÑылку"
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9668,9 +9712,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr "Ðе удалоÑÑŒ авторизовать никнейм чата. Попробуйте еще раз!"
@@ -9776,6 +9817,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr "Покрытие"
@@ -9794,6 +9838,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Создать Ðовый каталог"
@@ -9806,9 +9853,6 @@ msgstr "Сначала Ñоздайте учетную запиÑÑŒ GitLab, а Ð
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr "Создать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
@@ -9824,6 +9868,9 @@ msgstr "Создайте новый файл, поÑкольку еще нет Ñ
msgid "Create a new issue"
msgstr "Создать новое обÑуждение"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr "Создать новый репозиторий"
@@ -9959,6 +10006,9 @@ msgstr "Создать Ñниппет"
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -10076,7 +10126,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10199,10 +10249,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr "Ключи SSH"
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10259,6 +10306,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10313,6 +10363,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10472,6 +10531,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr "Этапы не выбраны"
@@ -10543,6 +10605,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -11039,6 +11104,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -11105,6 +11173,9 @@ msgstr "Ветвь по умолчанию"
msgid "Default branch and protected branches"
msgstr "Ветвь по умолчанию и защищенные ветки"
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11144,18 +11215,36 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "Определить наÑтраиваемый шаблон Ñ ÑинтакÑиÑом cron"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr "Определить наÑтраиваемый шаблон Ñ ÑинтакÑиÑом cron"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -11228,9 +11317,6 @@ msgstr "Удалить комментарий"
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11258,9 +11344,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr "Удалить Ñниппет"
@@ -11288,6 +11371,9 @@ msgstr ""
msgid "Delete variable"
msgstr "Удалить переменную"
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11456,13 +11542,13 @@ msgstr "ПрокÑи завиÑимоÑтей"
msgid "Dependency Scanning"
msgstr "Сканирование ЗавиÑимоÑтей"
-msgid "Dependency proxy"
-msgstr "ПрокÑи завиÑимоÑтей"
+msgid "DependencyProxy|Cached %{time}"
+msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
-msgstr "Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¿Ñ€Ð¾ÐºÑи-завиÑимоÑтей на данный момент ограничиваетÑÑ Ð¿ÑƒÐ±Ð»Ð¸Ñ‡Ð½Ñ‹Ð¼Ð¸ группами."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
+msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11471,8 +11557,20 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
-msgstr "Переключить прокÑи-завиÑимоÑÑ‚ÑŒ"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
+msgstr ""
msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
@@ -11797,7 +11895,11 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr "%{current_design} из %{designs_count}"
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "Добавление Ñтруктуры Ñ Ñ‚ÐµÐ¼ же именем файла заменÑет файл в новой верÑии."
@@ -11901,6 +12003,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11916,15 +12024,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr "и ещё %{moreCount}."
-
msgid "Designs"
msgstr "Дизайны"
@@ -11976,6 +12081,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -12054,6 +12162,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -12099,6 +12210,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12291,12 +12405,6 @@ msgstr "Ðачать беÑплатный пробный период"
msgid "Discover|Upgrade now"
msgstr "Улучшить ÑейчаÑ"
-msgid "Discuss a specific suggestion or question"
-msgstr "ОбÑудить конкретное предложение или вопроÑ"
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr "ОбÑудить конкретное предложение или вопроÑ, который необходимо решить"
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr "ОбÑудить конкретное предложение или вопроÑ, который необходимо решить."
@@ -12391,18 +12499,6 @@ msgstr "Домен"
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12433,9 +12529,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12661,6 +12754,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12985,12 +13081,9 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
-msgid "Enable proxy"
-msgstr "Включить прокÑи"
-
msgid "Enable reCAPTCHA"
msgstr ""
@@ -13114,7 +13207,10 @@ msgstr "Введите номер"
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13169,7 +13265,11 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr "Окружение"
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Environment does not have deployments"
msgstr "Окружение не имеет развёртываний"
@@ -13270,7 +13370,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr "Ð’Ñ‹ уверены, что хотите оÑтановить Ñто окружение?"
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13570,6 +13670,9 @@ msgstr "Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ†ÐµÐ»Ð¸"
msgid "Error creating label."
msgstr "Ошибка при Ñоздании метки."
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr "Ошибка при Ñоздании новой итерации"
@@ -13747,6 +13850,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -14045,9 +14151,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr "За иÑключением политики:"
@@ -14129,6 +14232,9 @@ msgstr "Срок дейÑтвиÑ"
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -14144,6 +14250,9 @@ msgstr "ИÑтекает"
msgid "Expires in %{expires_at}"
msgstr "ИÑтекает в %{expires_at}"
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr "ИÑтекает:"
@@ -14171,9 +14280,6 @@ msgstr "Обзор публичных групп"
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14186,6 +14292,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "ЭкÑпорт проекта"
@@ -14270,6 +14382,13 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14504,9 +14623,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr "Ðе удалоÑÑŒ загрузить файл карты объектов"
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14700,6 +14816,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr "Удалить"
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14953,6 +15072,9 @@ msgstr "Завершено"
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15184,6 +15306,9 @@ msgstr "Ðайдены ошибки в вашем .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15244,6 +15369,9 @@ msgstr "ОÑновные ÐаÑтройки"
msgid "General pipelines"
msgstr "Сборочные линии"
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr "Создать Ñтандартный набор меток"
@@ -15820,6 +15948,9 @@ msgstr ""
msgid "GitLab commit"
msgstr "Коммит GitLab"
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15859,6 +15990,9 @@ msgstr ""
msgid "GitLab project export"
msgstr "ЭкÑпорт проекта GitLab"
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15874,9 +16008,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15946,10 +16077,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15997,6 +16128,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16306,6 +16440,9 @@ msgstr "Ðватар группы"
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr "ОпиÑание группы (необÑзательно)"
@@ -16474,12 +16611,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr "Без начальной даты – %{dateWord}"
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "Что-то пошло не так при извлечении целей"
@@ -16708,7 +16839,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16771,9 +16902,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16876,7 +17013,7 @@ msgstr "Группы не найдены"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Ð’Ñ‹ можете управлÑÑ‚ÑŒ правами и доÑтупом учаÑтников вашей группы к каждому проекту в группе."
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -17005,6 +17142,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -17089,7 +17229,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17154,9 +17294,6 @@ msgstr "Скрыть значениÑ"
msgid "High or unknown vulnerabilities present"
msgstr "ПриÑутÑтвуют уÑзвимоÑти выÑокого или неизвеÑтного уровнÑ"
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr "ÐÐ°Ð¸Ð±Ð¾Ð»ÑŒÑˆÐ°Ñ Ñ€Ð¾Ð»ÑŒ:"
@@ -17178,6 +17315,9 @@ msgstr "ИÑториÑ"
msgid "History of authentications"
msgstr "ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¹"
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17202,6 +17342,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr "Ð§Ð°Ñ (UTC)"
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr "ОчиÑтка"
@@ -17214,6 +17357,9 @@ msgstr "ОчиÑтка, ÑкÑпорт, путь, перемещение, уда
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17790,6 +17936,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17850,6 +17999,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17904,6 +18056,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17922,6 +18077,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18435,6 +18599,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18538,6 +18705,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr "ИнтеграциÑ"
@@ -18577,6 +18747,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18760,6 +18933,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr "Внутренний URL (необÑзательно)"
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr "Внутренние пользователи"
@@ -18835,9 +19011,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18937,6 +19110,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr "Работайте вмеÑте Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¾Ð¹"
@@ -18955,6 +19134,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18970,6 +19152,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -19003,6 +19188,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19528,6 +19716,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19621,19 +19812,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19975,6 +20166,12 @@ msgstr "Ñ"
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20231,12 +20428,18 @@ msgstr "ПоÑледнее обращение"
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "ПоÑледнÑÑ Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð›Ð¸Ð½Ð¸Ñ"
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20405,6 +20608,9 @@ msgstr "Узнайте больше о развертывании в клаÑÑ‚Ð
msgid "Learn more about group-level project templates"
msgstr "Узнать больше о шаблонах проекта группового уровнÑ"
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -21042,6 +21248,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21171,6 +21380,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21258,9 +21470,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21384,6 +21593,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr "Превышено макÑимальное количеÑтво комментариев"
@@ -21393,6 +21605,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21654,6 +21869,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21699,6 +21917,9 @@ msgstr "ЗавиÑимоÑти запроÑа на ÑлиÑние"
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21771,6 +21992,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21927,34 +22157,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr "Метрики и профилирование"
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr "ÐÐ½Ð½Ð¾Ñ‚Ð°Ñ†Ð¸Ñ Ð½Ðµ может принадлежать одновременно клаÑтеру и окружению"
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr "ÐÐ½Ð½Ð¾Ñ‚Ð°Ñ†Ð¸Ñ Ð½Ðµ была удалена"
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
-msgstr "ÐÐ½Ð½Ð¾Ñ‚Ð°Ñ†Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° принадлежать клаÑтеру или окружению"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
-msgstr "Ðевозможно найти Панель Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ‹Ð¼ путём"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
-msgstr "Ð’Ñ‹ не уполномочены Ñоздавать аннотации Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ клаÑтера"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
-msgstr "Ð’Ñ‹ не уполномочены Ñоздавать аннотации Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ окружениÑ"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
-msgstr "У Ð²Ð°Ñ Ð½ÐµÑ‚ права на удаление Ñтой аннотации"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21981,6 +22205,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -22075,9 +22305,6 @@ msgstr "Развернуть панель"
msgid "Metrics|For grouping similar metrics"
msgstr "Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð¸Ñ€Ð¾Ð²ÐºÐ¸ похожих метрик"
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr "ÐедопуÑтимый промежуток времени, пожалуйÑта, проверьте его."
@@ -22213,9 +22440,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr "ПроÑмотр журналов"
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr "ПодпиÑÑŒ оÑи Y"
@@ -22664,6 +22888,9 @@ msgstr ""
msgid "My company or team"
msgstr "ÐœÐ¾Ñ ÐºÐ¾Ð¼Ð¿Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ команда"
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr "ÐœÐ¾Ñ Ñ€ÐµÐ°ÐºÑ†Ð¸Ñ"
@@ -22782,6 +23009,9 @@ msgstr ""
msgid "Network"
msgstr "Сеть"
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22848,9 +23078,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -23161,6 +23388,9 @@ msgstr "Ðовый тег"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23275,7 +23505,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23290,6 +23520,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23485,6 +23718,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr "Веб-обработчики не найдены, добавьте один в форме выше."
@@ -23543,9 +23779,6 @@ msgstr "ÐедоÑтупно Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ñ‹Ñ… проектов"
msgid "Not available for protected branches"
msgstr "ÐедоÑтупно Ð´Ð»Ñ Ð·Ð°Ñ‰Ð¸Ñ‰ÐµÐ½Ð½Ñ‹Ñ… веток"
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr "Ðе конфиденциально"
@@ -23787,18 +24020,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr "КоличеÑтво Ñтрок кода (LOC) на коммит"
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr "КоличеÑтво изменений (веток или тегов) в одной отправке, которое определÑет, будут ли запущены веб-обработчики и Ñлужбы. Веб-обработчики и Ñлужбы не будут выполнÑÑ‚ÑŒÑÑ, еÑли Ñто значение будет превышено."
-
msgid "Number of commits"
msgstr "КоличеÑтво коммитов"
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23850,9 +24080,6 @@ msgstr "Сначала Ñтарые"
msgid "OmniAuth"
msgstr "OmniAuth"
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -24054,6 +24281,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -24066,6 +24296,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -24078,6 +24314,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -24093,6 +24332,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24208,15 +24450,15 @@ msgstr "Открыть выбранное"
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24265,9 +24507,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¸ иÑтекло. Проверьте журналы пода %{pod_name} Ð´Ð»Ñ Ð±Ð¾Ð»ÐµÐµ подробной информации."
-msgid "Operations"
-msgstr "Операции"
-
msgid "Operations Dashboard"
msgstr ""
@@ -24295,6 +24534,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24304,6 +24546,9 @@ msgstr "ÐаÑтройки"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24373,6 +24618,36 @@ msgstr ""
msgid "Owner"
msgstr "Владелец"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr "РееÑÑ‚Ñ€ пакетов"
@@ -24448,9 +24723,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24631,14 +24903,18 @@ msgstr "Команда NuGet"
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24682,9 +24958,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24943,6 +25216,9 @@ msgstr "Путь:"
msgid "Paths can contain wildcards, like */welcome"
msgstr "Путь необÑзательно должен быть абÑолютным, а может ÑвлÑÑ‚ÑŒÑÑ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð¾Ð¼, например */your_group"
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr "ПриоÑтановить"
@@ -24964,6 +25240,9 @@ msgstr "В ожидании"
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25471,6 +25750,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÑ‚ Ñборочных линий."
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25591,6 +25873,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25708,6 +25993,9 @@ msgstr "ПроÑтое отличие"
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr "План:"
@@ -25810,9 +26098,15 @@ msgstr "ПожалуйÑта введите правильное чиÑло"
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr "ПожалуйÑта, заполните Ñто поле."
@@ -25957,6 +26251,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26233,12 +26530,18 @@ msgstr "Профиль"
msgid "Profile Settings"
msgstr "ÐаÑтройки профилÑ"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr "на"
@@ -26248,9 +26551,6 @@ msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ навÑегда удалить %{yourAccoun
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ изменить Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{currentUsernameBold} на %{newUsernameBold}. Профиль и проекты будут перенаправлены в проÑтранÑтво имен %{newUsername}, но Ñто перенаправление переÑтанет дейÑтвовать, как только проÑтранÑтво имён %{currentUsername} будет зарегиÑтрировано другим пользователем или группой. ПожалуйÑта, как можно Ñкорее, обновите указатели на Ñвои удаленные репозитории Git."
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26278,6 +26578,9 @@ msgstr "Добавить Ñмайл к ÑтатуÑу"
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr "Обрезать аватар"
@@ -26569,6 +26872,9 @@ msgstr "Ð’Ñ‹ можете загрузить Ñвой аватар здеÑÑŒ и
msgid "Profiles|You don't have access to delete this user."
msgstr "У Ð²Ð°Ñ Ð½ÐµÑ‚ прав на удаление Ñтого пользователÑ."
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26869,6 +27175,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26884,6 +27193,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -27067,6 +27379,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "ВнутреннÑÑ"
@@ -27079,6 +27394,9 @@ msgstr "ОбÑуждениÑ"
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27256,6 +27574,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27346,6 +27667,9 @@ msgstr "Spring"
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
@@ -27427,6 +27751,9 @@ msgstr "Эта функциональноÑÑ‚ÑŒ требует поддержкÐ
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr "ПозволÑет вам Ñразу клонировать репозиторий. ПропуÑтите Ñтот пункт, еÑли вы планируете загрузить ÑущеÑтвующий репозиторий."
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27454,6 +27781,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr "Ðапишите неÑколько Ñлов про проект"
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr "Импорт"
@@ -27469,6 +27799,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr "Ðет доÑтупных опций импорта"
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "ОпиÑание проекта %{tag_start}(необÑзательно)%{tag_end}"
@@ -27484,54 +27817,9 @@ msgstr "Хотите размеÑтить неÑколько взаимоÑвÑÐ
msgid "Prometheus"
msgstr "Prometheus"
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr "%{count} оповещений применено"
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr "%{firingCount} горÑщих"
-
-msgid "PrometheusAlerts|Add alert"
-msgstr "Добавить оповещение"
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr "Редактировать оповещение"
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr "Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ"
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr "Ошибка ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ"
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr "Ошибка Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ"
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr "Ошибка ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ"
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr "ГорÑщие: %{alerts}"
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr "ГорÑщее: %{alert}"
-
-msgid "PrometheusAlerts|Operator"
-msgstr "Оператор"
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr "Выберите запроÑ"
-
-msgid "PrometheusAlerts|Threshold"
-msgstr "Порог ÑрабатываниÑ"
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27835,9 +28123,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27853,6 +28138,9 @@ msgstr "Защищённые ветви"
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27991,6 +28279,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr "Провайдер"
@@ -28003,6 +28294,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28189,9 +28483,6 @@ msgstr "ЗапроÑ"
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð²ÐµÑ€ÐµÐ½"
-
msgid "Queued"
msgstr ""
@@ -28225,6 +28516,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28312,15 +28606,15 @@ msgstr ""
msgid "Recent"
msgstr "ПоÑледние"
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr "Ðедавние дейÑÑ‚Ð²Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°"
msgid "Recent Searches Service is unavailable"
msgstr "ÐÐ¾Ð²Ð°Ñ Ñлужба поиÑка недоÑтупна"
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28806,6 +29100,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr "Открыть заново"
@@ -29146,6 +29443,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð¾Ñтупа"
@@ -29155,9 +29455,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29236,19 +29533,19 @@ msgstr "ТребованиÑ"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] "Ðеобходимо подтверждений от %{names}."
-msgstr[1] "Ðеобходимо %{count} подтверждений от %{names}."
-msgstr[2] "Ðеобходимо %{count} подтверждений от %{names}."
-msgstr[3] "Ðеобходимо %{count} подтверждений от %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
-msgstr[0] "Требует подтверждениÑ."
-msgstr[1] "Ðеобходимо %d подтверждений."
-msgstr[2] "Ðеобходимо %d подтверждений."
-msgstr[3] "Ðеобходимо %d подтверждений."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Requires values to meet regular expression requirements."
msgstr "Требует, чтобы Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ ÑоответÑтвовали регулÑрному выражению."
@@ -29597,9 +29894,6 @@ msgstr "Runner'Ñ‹"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29624,6 +29918,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29633,6 +29936,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29684,6 +29990,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29705,6 +30014,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29744,6 +30071,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29807,6 +30137,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "Ð’Ñ‹ иÑпользовали %{quotaUsed} из %{quotaLimit} ваших минут Ñборки на общих Runner'ах."
@@ -29837,15 +30170,6 @@ msgstr "ВыполнÑетÑÑ"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "ЗапуÑкает Ñ€Ñд Ñлужебных задач в текущем репозитории, таких как Ñжатие верÑий файлов и удаление недоÑтупных объектов."
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29942,9 +30266,6 @@ msgstr ""
msgid "Save Changes"
msgstr "Сохранить изменениÑ"
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr "Сохранить приложение"
@@ -30295,6 +30616,9 @@ msgstr[3] "Результат Wiki"
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30520,16 +30844,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30580,6 +30907,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30598,6 +30928,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30667,6 +31000,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30688,9 +31024,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30724,6 +31057,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30733,6 +31075,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30763,6 +31108,9 @@ msgstr "Ð”Ð»Ñ Ñтой Ñборочной линии не найдено ник
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30886,6 +31234,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30925,12 +31276,12 @@ msgstr ""
msgid "Select a branch"
msgstr ""
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "Выберите файл на левой боковой панели, чтобы начать редактирование. ПоÑле Ñтого вы Ñможете зафикÑировать Ñвои изменениÑ."
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
-msgstr ""
-
msgid "Select a group to invite"
msgstr "Выберите группу"
@@ -30946,15 +31297,9 @@ msgstr "Выберите новое проÑтранÑтво имен"
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr "Выберите проект Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° конфигурации Insights"
-
msgid "Select a reason"
msgstr "Выберите причину"
-msgid "Select a repository"
-msgstr "Выберите репозиторий"
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31213,9 +31558,6 @@ msgstr "ВерÑÐ¸Ñ Ñервера"
msgid "Serverless"
msgstr "Serverless"
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31315,9 +31657,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31372,9 +31711,6 @@ msgstr "УÑтановите пароль в Ñвоем аккаунте, что
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31465,9 +31801,6 @@ msgstr "ÐаÑтроить интеграцию Ñ Jira"
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31501,12 +31834,12 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "уÑтановите пароль"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr "Добавить Ñмайл"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "SetStatusModal|Busy"
msgstr ""
@@ -31570,6 +31903,13 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31917,9 +32257,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr "Одиночные или комбинированные запроÑÑ‹"
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31986,6 +32323,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "Сниппеты"
@@ -32010,6 +32350,9 @@ msgstr "СохранÑйте, раÑпроÑтранÑйте и вÑтраива
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "Ðет Ñниппетов Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ."
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr "Добавить ещё файл %{num}/%{total}"
@@ -32019,6 +32362,9 @@ msgstr "Удалить файл"
msgid "Snippets|Description (optional)"
msgstr "ОпиÑание (необÑзательно)"
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr "Файлы"
@@ -32043,9 +32389,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr "Кто-то отредактировал обÑуждение одновременно Ñ Ð²Ð°Ð¼Ð¸. ПожалуйÑта, проверьте %{linkStart}обÑуждение%{linkEnd} и убедитеÑÑŒ, что внеÑённые Вами Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñлучайно не затёрли чужие."
@@ -32640,12 +32983,6 @@ msgstr "Ðачать поиÑк"
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32685,6 +33022,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -33183,7 +33523,7 @@ msgstr "УÑпешно разблокировано"
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33282,18 +33622,12 @@ msgstr ""
msgid "Sunday"
msgstr "ВоÑкреÑенье"
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33315,9 +33649,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33330,12 +33661,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33351,30 +33676,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33402,9 +33712,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33417,9 +33724,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33462,6 +33766,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33648,6 +33955,9 @@ msgstr "Теги дают возможноÑÑ‚ÑŒ отмечать определ
msgid "TagsPage|This tag has no release notes."
msgstr "Этот тег не Ñодержит заметок к релизу."
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "ИÑпользуйте команду git tag, чтобы добавить новый тег:"
@@ -33672,6 +33982,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "Команда"
@@ -33684,6 +34003,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -34067,6 +34389,9 @@ msgstr[3] "%{type} Ñодержат Ñледующие ошибки:"
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -34136,6 +34461,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Соединение будет отключено через %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸ÐµÐ², требующих больше времени, иÑпользуйте комбинацию clone/push."
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr "Содержание Ñтой Ñтраницы не закодировано в UTF-8. Редактировать можно только через Git репозиторий."
@@ -34166,9 +34494,6 @@ msgstr "СпиÑок завиÑимоÑтей Ñодержит подробнуÑ
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "Задание Ñ€Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð½Ð° %{environmentLink} не удалоÑÑŒ."
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr "Каталог уÑпешно Ñоздан."
@@ -34239,6 +34564,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr "Глобальные наÑтройки требуют, чтобы вы включили двухфакторную аутентификацию Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ¹ учетной запиÑи."
@@ -34323,6 +34651,9 @@ msgstr "Ð›Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ Ð±Ñ‹Ð»Ð° уÑпешно загружена и тепеÑ
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr "МакÑимальный размер файла - %{size}."
@@ -34428,9 +34759,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr "Проект был уÑпешно импортирован."
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34464,9 +34792,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr "Ð’Ñ€ÐµÐ¼Ñ Ñ€Ð°ÑпиÑÐ°Ð½Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ быть в будущем!"
-
msgid "The snippet can be accessed without any authentication."
msgstr "ДоÑтуп к Ñниппету можно получить без какой-либо аутентификации."
@@ -34626,6 +34951,9 @@ msgstr "Пакетов пока нет"
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34710,6 +35038,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34896,9 +35227,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -35121,7 +35449,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35424,6 +35752,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35562,6 +35896,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35897,7 +36234,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35933,7 +36270,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -36119,6 +36456,21 @@ msgstr "Слишком много проектов включено. Ð”Ð»Ñ ÑƒÐ¿
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr "Темы (необÑзательно)"
@@ -36212,8 +36564,8 @@ msgstr "Группа уже ÑвлÑетÑÑ ÐºÐ¾Ñ€Ð½ÐµÐ²Ð¾Ð¹."
msgid "TransferGroup|Group is already associated to the parent group."
msgstr "Группа уже ÑвÑзана Ñ Ñ€Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÑкой группой."
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
-msgstr "У родительÑкой группы уже еÑÑ‚ÑŒ подгруппа Ñ Ñ‚ÐµÐ¼ же путем."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
+msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
msgstr "Ошибка переноÑа: %{error_message}"
@@ -36582,6 +36934,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36666,6 +37021,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr "Отменить"
@@ -36999,6 +37357,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr "Купить дополнительные минуты"
@@ -37017,10 +37378,10 @@ msgstr "Текущий период иÑпользованиÑ"
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -37032,6 +37393,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr "Хранилище LFS"
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -37077,9 +37441,6 @@ msgstr "Хранилище"
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -37119,12 +37480,12 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr "ИÑпользование"
-msgid "UsageQuota|Usage Breakdown"
-msgstr ""
-
msgid "UsageQuota|Usage Quotas"
msgstr "Квоты иÑпользованиÑ"
+msgid "UsageQuota|Usage breakdown"
+msgstr ""
+
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
msgstr "ИÑпользование групповых реÑурÑов по проектам в группе %{strong_start}%{group_name}%{strong_end}"
@@ -37272,6 +37633,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37302,6 +37666,9 @@ msgstr ""
msgid "Use template"
msgstr "ИÑпользовать шаблон"
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37368,6 +37735,12 @@ msgstr "ÐаÑтройки пользователÑ"
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37719,6 +38092,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37728,6 +38104,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37773,10 +38158,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr "Медианное Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð´Ð¾ его закрытиÑ."
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38442,6 +38839,9 @@ msgstr "Журналы веб-обработчика"
msgid "Webhook Settings"
msgstr "ÐаÑтройки веб-обработчика"
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38637,6 +39037,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38646,9 +39049,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Когда Runner закреплён, он не может быть назначен другим проектам"
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38661,6 +39061,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38671,9 +39074,6 @@ msgstr[3] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr "Когда:"
@@ -38980,12 +39380,12 @@ msgstr "Ðапишите комментарий…"
msgid "Write a description or drag your files here…"
msgstr ""
+msgid "Write a description…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Ðапишите опиÑание Ñтапа..."
-msgid "Write to \"authorized_keys\" file"
-msgstr ""
-
msgid "Write your release notes or drag your files here…"
msgstr "Ðапишите Ñвои заметки к релизу или перетащите ваши файлы Ñюда…"
@@ -39025,9 +39425,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -39094,6 +39491,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39250,9 +39650,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "Ð’Ñ‹ можете разрешить конфликт ÑлиÑниÑ, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð»Ð¸Ð±Ð¾ интерактивный режим, выбрав кнопки %{use_ours} или %{use_theirs}, либо отредактировав файлы напрÑмую. Примите Ñти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² %{branch_name}"
@@ -39352,9 +39749,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ´Ð¾Ñтаточно прав Ð´Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñтого дейÑтвиÑ."
@@ -39442,6 +39836,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr "Ð’Ñ‹ уÑпешно приобрели подпиÑку на план %{plan} на %{seats} меÑÑ‚. Ð’Ñ‹ получите чек по Ñлектронной почте."
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39451,9 +39848,6 @@ msgstr "Теперь вы можете закрыть Ñтап."
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39908,28 +40302,55 @@ msgstr[3] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39941,6 +40362,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39953,9 +40377,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] "примерно чаÑ"
@@ -40066,12 +40487,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -40099,6 +40526,9 @@ msgstr ""
msgid "cannot be modified"
msgstr "не может быть изменено"
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr "невозможно заблокировать других"
@@ -40114,9 +40544,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40147,6 +40574,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -40183,9 +40613,22 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -40195,7 +40638,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40261,6 +40710,19 @@ msgstr "Ðайдено %{issuesWithCount}"
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "РаÑÑледуйте Ñту уÑзвимоÑÑ‚ÑŒ, вынеÑÑ Ð½Ð° обÑуждение"
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40294,10 +40756,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40418,6 +40880,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr "поле container_name не может быть больше, чем %{max_length} Ñимволов"
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40476,9 +40944,6 @@ msgstr "развернуть"
msgid "design"
msgstr "дизайн"
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40491,6 +40956,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40507,6 +40978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr "Ñлемент не ÑвлÑетÑÑ Ð¸ÐµÑ€Ð°Ñ€Ñ…Ð¸ÐµÐ¹"
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40543,6 +41017,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40747,6 +41224,12 @@ msgstr "невозможно. Ðа данный момент мы не поддÐ
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40907,6 +41390,9 @@ msgstr "Потребление %{metricsLinkStart} памÑти %{metricsLinkEnd
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40940,6 +41426,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr "Одобрено"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -41004,6 +41496,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr "Загрузка ÑтатиÑтики развертываниÑ"
@@ -41038,9 +41533,6 @@ msgstr "СлиÑние не удалоÑÑŒ."
msgid "mrWidget|Merge locally"
msgstr "Слить локально"
-msgid "mrWidget|Merge request approved."
-msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние одобрен."
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -41155,12 +41647,6 @@ msgstr "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð²ÐµÑ‚ÐºÐ° не будет удалена"
msgid "mrWidget|There are merge conflicts"
msgstr "ЕÑÑ‚ÑŒ конфликты ÑлиÑниÑ"
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Этот Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние не может быть выполнен автоматичеÑки"
@@ -41176,6 +41662,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41224,6 +41713,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41299,6 +41794,9 @@ msgstr "или"
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/si_LK/gitlab.po b/locale/si_LK/gitlab.po
index 3b636f46c73..c149bc804db 100644
--- a/locale/si_LK/gitlab.po
+++ b/locale/si_LK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: si-LK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index edc498b5231..8257cdf7cf9 100644
--- a/locale/sk_SK/gitlab.po
+++ b/locale/sk_SK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:22\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,29 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid " or "
msgstr ""
@@ -90,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -240,9 +226,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1227,6 +1210,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1312,9 +1298,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1371,6 +1363,9 @@ msgstr[3] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1665,9 +1660,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1701,7 +1693,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1728,6 +1720,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -2076,6 +2071,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -2157,9 +2155,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2238,9 +2233,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2334,6 +2326,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2790,7 +2785,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2805,6 +2800,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2940,7 +2941,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3555,7 +3556,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3573,6 +3574,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3588,7 +3592,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3828,13 +3832,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -4038,6 +4045,13 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -4101,9 +4115,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4450,12 +4461,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4468,12 +4485,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4486,6 +4512,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4501,6 +4536,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4510,6 +4548,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4784,12 +4825,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -5029,6 +5064,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5663,6 +5701,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5908,7 +5949,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -6019,6 +6060,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6226,9 +6270,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6515,9 +6556,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6575,6 +6613,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6907,6 +6951,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6940,6 +6987,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -7054,6 +7104,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -7096,15 +7149,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7747,7 +7794,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8188,6 +8235,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8197,6 +8247,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8206,9 +8259,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8221,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8371,30 +8442,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8533,12 +8580,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8657,6 +8698,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8738,13 +8782,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8753,16 +8797,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8771,6 +8821,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8783,31 +8839,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8879,15 +8935,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -9032,6 +9082,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9160,10 +9213,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9362,7 +9415,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9386,9 +9439,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9509,9 +9559,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9581,9 +9628,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9668,9 +9712,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9776,6 +9817,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9794,6 +9838,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9806,9 +9853,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9824,6 +9868,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9959,6 +10006,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -10076,7 +10126,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10199,10 +10249,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10259,6 +10306,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10313,6 +10363,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10472,6 +10531,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10543,6 +10605,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -11039,6 +11104,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -11105,6 +11173,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11144,16 +11215,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11228,9 +11317,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11258,9 +11344,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11288,6 +11371,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11456,13 +11542,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11471,7 +11557,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11797,7 +11895,11 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11901,6 +12003,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11916,15 +12024,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11976,6 +12081,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -12054,6 +12162,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -12099,6 +12210,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12291,12 +12405,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12391,18 +12499,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12433,9 +12529,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12661,6 +12754,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12985,10 +13081,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -13114,7 +13207,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13169,7 +13265,11 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13270,7 +13370,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13570,6 +13670,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13747,6 +13850,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -14045,9 +14151,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -14129,6 +14232,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -14144,6 +14250,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14171,9 +14280,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14186,6 +14292,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14270,6 +14382,13 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14504,9 +14623,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14700,6 +14816,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14953,6 +15072,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15184,6 +15306,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15244,6 +15369,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15820,6 +15948,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15859,6 +15990,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15874,9 +16008,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15946,10 +16077,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15997,6 +16128,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16306,6 +16440,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16474,12 +16611,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16708,7 +16839,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16771,9 +16902,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16876,7 +17013,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -17005,6 +17142,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -17089,7 +17229,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17154,9 +17294,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17178,6 +17315,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17202,6 +17342,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17214,6 +17357,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17790,6 +17936,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17850,6 +17999,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17904,6 +18056,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17922,6 +18077,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18435,6 +18599,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18538,6 +18705,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18577,6 +18747,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18760,6 +18933,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18835,9 +19011,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18937,6 +19110,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18955,6 +19134,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18970,6 +19152,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -19003,6 +19188,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19528,6 +19716,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19621,19 +19812,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19975,6 +20166,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20231,12 +20428,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20405,6 +20608,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -21042,6 +21248,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21171,6 +21380,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21258,9 +21470,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21384,6 +21593,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21393,6 +21605,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21654,6 +21869,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21699,6 +21917,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21771,6 +21992,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21927,34 +22157,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21981,6 +22205,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -22075,9 +22305,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22213,9 +22440,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22664,6 +22888,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22782,6 +23009,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22848,9 +23078,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -23161,6 +23388,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23275,7 +23505,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23290,6 +23520,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23485,6 +23718,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23543,9 +23779,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23787,18 +24020,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23850,9 +24080,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -24054,6 +24281,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -24066,6 +24296,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -24078,6 +24314,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -24093,6 +24332,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24208,15 +24450,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24265,9 +24507,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24295,6 +24534,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24304,6 +24546,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24373,6 +24618,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24448,9 +24723,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24631,14 +24903,18 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24682,9 +24958,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24943,6 +25216,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24964,6 +25240,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25471,6 +25750,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25591,6 +25873,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25708,6 +25993,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25810,9 +26098,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25957,6 +26251,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26233,12 +26530,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26248,9 +26551,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26278,6 +26578,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26569,6 +26872,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26869,6 +27175,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26884,6 +27193,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -27067,6 +27379,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27079,6 +27394,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27256,6 +27574,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27346,6 +27667,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27427,6 +27751,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27454,6 +27781,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27469,6 +27799,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27484,54 +27817,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27835,9 +28123,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27853,6 +28138,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27991,6 +28279,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -28003,6 +28294,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28189,9 +28483,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28225,6 +28516,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28312,15 +28606,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28806,6 +29100,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -29146,6 +29443,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -29155,9 +29455,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29236,15 +29533,15 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29597,9 +29894,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29624,6 +29918,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29633,6 +29936,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29684,6 +29990,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29705,6 +30014,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29744,6 +30071,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29807,6 +30137,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29837,15 +30170,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29942,9 +30266,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30295,6 +30616,9 @@ msgstr[3] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30520,16 +30844,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30580,6 +30907,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30598,6 +30928,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30667,6 +31000,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30688,9 +31024,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30724,6 +31057,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30733,6 +31075,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30763,6 +31108,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30886,6 +31234,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30925,10 +31276,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30946,15 +31297,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31213,9 +31558,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31315,9 +31657,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31372,9 +31711,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31465,9 +31801,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31501,10 +31834,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31570,6 +31903,13 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31917,9 +32257,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31986,6 +32323,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -32010,6 +32350,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -32019,6 +32362,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -32043,9 +32389,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32640,12 +32983,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32685,6 +33022,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -33183,7 +33523,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33282,18 +33622,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33315,9 +33649,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33330,12 +33661,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33351,30 +33676,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33402,9 +33712,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33417,9 +33724,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33462,6 +33766,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33648,6 +33955,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33672,6 +33982,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33684,6 +34003,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -34067,6 +34389,9 @@ msgstr[3] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -34136,6 +34461,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -34166,9 +34494,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34239,6 +34564,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34323,6 +34651,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34428,9 +34759,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34464,9 +34792,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34626,6 +34951,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34710,6 +35038,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34896,9 +35227,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -35121,7 +35449,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35424,6 +35752,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35562,6 +35896,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35897,7 +36234,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35933,7 +36270,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -36119,6 +36456,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36212,7 +36564,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36582,6 +36934,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36666,6 +37021,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36999,6 +37357,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -37017,10 +37378,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -37032,6 +37393,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -37077,9 +37441,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -37119,10 +37480,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37272,6 +37633,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37302,6 +37666,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37368,6 +37735,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37719,6 +38092,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37728,6 +38104,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37773,10 +38158,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38442,6 +38839,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38637,6 +39037,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38646,9 +39049,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38661,6 +39061,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38671,9 +39074,6 @@ msgstr[3] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38980,10 +39380,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -39025,9 +39425,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -39094,6 +39491,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39250,9 +39650,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39352,9 +39749,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39442,6 +39836,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39451,9 +39848,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39908,28 +40302,55 @@ msgstr[3] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39941,6 +40362,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39953,9 +40377,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -40066,12 +40487,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -40099,6 +40526,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -40114,9 +40544,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40147,6 +40574,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -40183,9 +40613,22 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -40195,7 +40638,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40261,6 +40710,19 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40294,10 +40756,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40418,6 +40880,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40476,9 +40944,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40491,6 +40956,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40507,6 +40978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40543,6 +41017,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40747,6 +41224,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40907,6 +41390,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40940,6 +41426,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -41004,6 +41496,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -41038,9 +41533,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -41155,12 +41647,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -41176,6 +41662,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41224,6 +41713,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41299,6 +41794,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/sl_SI/gitlab.po b/locale/sl_SI/gitlab.po
index 23307046d0e..3a549c0956b 100644
--- a/locale/sl_SI/gitlab.po
+++ b/locale/sl_SI/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:24\n"
+"PO-Revision-Date: 2021-11-02 00:38\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,29 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid " or "
msgstr ""
@@ -90,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -240,9 +226,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1227,6 +1210,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1312,9 +1298,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1371,6 +1363,9 @@ msgstr[3] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1665,9 +1660,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1701,7 +1693,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1728,6 +1720,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -2076,6 +2071,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -2157,9 +2155,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2238,9 +2233,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2334,6 +2326,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2790,7 +2785,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2805,6 +2800,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2940,7 +2941,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3555,7 +3556,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3573,6 +3574,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3588,7 +3592,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3828,13 +3832,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -4038,6 +4045,13 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -4101,9 +4115,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4450,12 +4461,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4468,12 +4485,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4486,6 +4512,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4501,6 +4536,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4510,6 +4548,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4784,12 +4825,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -5029,6 +5064,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5663,6 +5701,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5908,7 +5949,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -6019,6 +6060,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6226,9 +6270,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6515,9 +6556,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6575,6 +6613,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6907,6 +6951,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6940,6 +6987,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -7054,6 +7104,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -7096,15 +7149,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7747,7 +7794,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8188,6 +8235,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8197,6 +8247,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8206,9 +8259,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8221,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8371,30 +8442,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8533,12 +8580,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8657,6 +8698,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8738,13 +8782,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8753,16 +8797,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8771,6 +8821,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8783,31 +8839,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8879,15 +8935,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -9032,6 +9082,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9160,10 +9213,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9362,7 +9415,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9386,9 +9439,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9509,9 +9559,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9581,9 +9628,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9668,9 +9712,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9776,6 +9817,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9794,6 +9838,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9806,9 +9853,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9824,6 +9868,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9959,6 +10006,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -10076,7 +10126,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10199,10 +10249,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10259,6 +10306,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10313,6 +10363,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10472,6 +10531,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10543,6 +10605,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -11039,6 +11104,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -11105,6 +11173,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11144,16 +11215,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11228,9 +11317,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11258,9 +11344,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11288,6 +11371,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11456,13 +11542,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11471,7 +11557,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11797,7 +11895,11 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11901,6 +12003,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11916,15 +12024,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11976,6 +12081,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -12054,6 +12162,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -12099,6 +12210,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12291,12 +12405,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12391,18 +12499,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12433,9 +12529,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12661,6 +12754,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12985,10 +13081,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -13114,7 +13207,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13169,7 +13265,11 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13270,7 +13370,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13570,6 +13670,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13747,6 +13850,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -14045,9 +14151,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -14129,6 +14232,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -14144,6 +14250,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14171,9 +14280,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14186,6 +14292,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14270,6 +14382,13 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14504,9 +14623,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14700,6 +14816,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14953,6 +15072,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15184,6 +15306,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15244,6 +15369,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15820,6 +15948,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15859,6 +15990,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15874,9 +16008,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15946,10 +16077,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15997,6 +16128,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16306,6 +16440,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16474,12 +16611,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16708,7 +16839,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16771,9 +16902,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16876,7 +17013,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -17005,6 +17142,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -17089,7 +17229,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17154,9 +17294,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17178,6 +17315,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17202,6 +17342,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17214,6 +17357,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17790,6 +17936,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17850,6 +17999,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17904,6 +18056,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17922,6 +18077,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18435,6 +18599,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18538,6 +18705,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18577,6 +18747,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18760,6 +18933,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18835,9 +19011,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18937,6 +19110,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18955,6 +19134,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18970,6 +19152,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -19003,6 +19188,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19528,6 +19716,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19621,19 +19812,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19975,6 +20166,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20231,12 +20428,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20405,6 +20608,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -21042,6 +21248,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21171,6 +21380,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21258,9 +21470,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21384,6 +21593,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21393,6 +21605,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21654,6 +21869,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21699,6 +21917,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21771,6 +21992,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21927,34 +22157,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21981,6 +22205,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -22075,9 +22305,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22213,9 +22440,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22664,6 +22888,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22782,6 +23009,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22848,9 +23078,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -23161,6 +23388,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23275,7 +23505,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23290,6 +23520,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23485,6 +23718,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23543,9 +23779,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23787,18 +24020,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23850,9 +24080,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -24054,6 +24281,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -24066,6 +24296,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -24078,6 +24314,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -24093,6 +24332,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24208,15 +24450,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24265,9 +24507,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24295,6 +24534,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24304,6 +24546,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24373,6 +24618,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24448,9 +24723,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24631,14 +24903,18 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24682,9 +24958,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24943,6 +25216,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24964,6 +25240,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25471,6 +25750,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25591,6 +25873,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25708,6 +25993,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25810,9 +26098,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25957,6 +26251,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26233,12 +26530,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26248,9 +26551,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26278,6 +26578,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26569,6 +26872,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26869,6 +27175,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26884,6 +27193,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -27067,6 +27379,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -27079,6 +27394,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27256,6 +27574,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27346,6 +27667,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27427,6 +27751,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27454,6 +27781,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27469,6 +27799,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27484,54 +27817,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27835,9 +28123,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27853,6 +28138,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27991,6 +28279,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -28003,6 +28294,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28189,9 +28483,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28225,6 +28516,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28312,15 +28606,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28806,6 +29100,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -29146,6 +29443,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -29155,9 +29455,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29236,15 +29533,15 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29597,9 +29894,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29624,6 +29918,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29633,6 +29936,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29684,6 +29990,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29705,6 +30014,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29744,6 +30071,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29807,6 +30137,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29837,15 +30170,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29942,9 +30266,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30295,6 +30616,9 @@ msgstr[3] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30520,16 +30844,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30580,6 +30907,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30598,6 +30928,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30667,6 +31000,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30688,9 +31024,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30724,6 +31057,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30733,6 +31075,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30763,6 +31108,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30886,6 +31234,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30925,10 +31276,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30946,15 +31297,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31213,9 +31558,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31315,9 +31657,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31372,9 +31711,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31465,9 +31801,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31501,10 +31834,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31570,6 +31903,13 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31917,9 +32257,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31986,6 +32323,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -32010,6 +32350,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -32019,6 +32362,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -32043,9 +32389,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32640,12 +32983,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32685,6 +33022,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -33183,7 +33523,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33282,18 +33622,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33315,9 +33649,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33330,12 +33661,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33351,30 +33676,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33402,9 +33712,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33417,9 +33724,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33462,6 +33766,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33648,6 +33955,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33672,6 +33982,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33684,6 +34003,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -34067,6 +34389,9 @@ msgstr[3] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -34136,6 +34461,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -34166,9 +34494,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34239,6 +34564,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34323,6 +34651,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34428,9 +34759,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34464,9 +34792,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34626,6 +34951,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34710,6 +35038,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34896,9 +35227,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -35121,7 +35449,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35424,6 +35752,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35562,6 +35896,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35897,7 +36234,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35933,7 +36270,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -36119,6 +36456,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36212,7 +36564,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36582,6 +36934,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36666,6 +37021,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36999,6 +37357,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -37017,10 +37378,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -37032,6 +37393,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -37077,9 +37441,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -37119,10 +37480,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37272,6 +37633,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37302,6 +37666,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37368,6 +37735,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37719,6 +38092,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37728,6 +38104,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37773,10 +38158,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38442,6 +38839,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38637,6 +39037,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38646,9 +39049,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38661,6 +39061,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38671,9 +39074,6 @@ msgstr[3] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38980,10 +39380,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -39025,9 +39425,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -39094,6 +39491,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39250,9 +39650,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39352,9 +39749,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39442,6 +39836,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39451,9 +39848,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39908,28 +40302,55 @@ msgstr[3] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39941,6 +40362,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39953,9 +40377,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -40066,12 +40487,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -40099,6 +40526,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -40114,9 +40544,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40147,6 +40574,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -40183,9 +40613,22 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -40195,7 +40638,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40261,6 +40710,19 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40294,10 +40756,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40418,6 +40880,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40476,9 +40944,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40491,6 +40956,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40507,6 +40978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40543,6 +41017,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40747,6 +41224,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40907,6 +41390,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40940,6 +41426,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -41004,6 +41496,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -41038,9 +41533,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -41155,12 +41647,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -41176,6 +41662,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41224,6 +41713,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41299,6 +41794,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index 465eec3eb61..a49a729c2f1 100644
--- a/locale/sq_AL/gitlab.po
+++ b/locale/sq_AL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sq\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:24\n"
+"PO-Revision-Date: 2021-11-02 00:38\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index b8850c10d36..493438287e7 100644
--- a/locale/sr_CS/gitlab.po
+++ b/locale/sr_CS/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sr-CS\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,27 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid " or "
msgstr ""
@@ -88,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -217,9 +205,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1141,6 +1126,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1225,9 +1213,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1282,6 +1276,9 @@ msgstr[2] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1552,9 +1549,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1588,7 +1582,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1615,6 +1609,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1963,6 +1960,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -2044,9 +2044,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2125,9 +2122,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2221,6 +2215,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2677,7 +2674,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2692,6 +2689,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2827,7 +2830,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3442,7 +3445,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3460,6 +3463,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3475,7 +3481,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3715,13 +3721,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3925,6 +3934,12 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3988,9 +4003,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4330,12 +4342,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4348,12 +4366,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4366,6 +4393,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4381,6 +4417,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4390,6 +4429,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4663,12 +4705,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4906,6 +4942,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5539,6 +5578,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5782,7 +5824,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5893,6 +5935,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6100,9 +6145,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6388,9 +6430,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6448,6 +6487,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6778,6 +6823,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6811,6 +6859,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6925,6 +6976,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6967,15 +7021,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7618,7 +7666,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8059,6 +8107,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8068,6 +8119,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8077,9 +8131,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8092,6 +8161,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8242,30 +8314,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8404,12 +8452,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8527,6 +8569,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8608,13 +8653,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8623,16 +8668,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8641,6 +8692,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8653,31 +8710,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8749,15 +8806,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8902,6 +8953,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9028,10 +9082,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9229,7 +9283,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9253,9 +9307,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9376,9 +9427,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9448,9 +9496,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9535,9 +9580,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9643,6 +9685,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9661,6 +9706,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9673,9 +9721,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9691,6 +9736,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9826,6 +9874,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9943,7 +9994,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10066,10 +10117,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10126,6 +10174,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10180,6 +10231,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10339,6 +10399,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10408,6 +10471,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10903,6 +10969,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10969,6 +11038,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11008,16 +11080,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11092,9 +11182,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11122,9 +11209,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11152,6 +11236,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11317,13 +11404,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11332,7 +11419,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11654,7 +11753,10 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11758,6 +11860,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11773,15 +11881,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11833,6 +11938,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11911,6 +12019,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11956,6 +12067,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12145,12 +12259,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12244,18 +12352,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12286,9 +12382,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12514,6 +12607,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12838,10 +12934,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12967,7 +13060,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13022,7 +13118,10 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13123,7 +13222,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13423,6 +13522,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13600,6 +13702,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13897,9 +14002,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13981,6 +14083,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13996,6 +14101,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14023,9 +14131,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14038,6 +14143,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14122,6 +14233,12 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14356,9 +14473,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14551,6 +14665,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14803,6 +14920,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15034,6 +15154,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15094,6 +15217,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15670,6 +15796,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15709,6 +15838,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15724,9 +15856,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15796,10 +15925,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15847,6 +15976,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16156,6 +16288,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16324,12 +16459,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16558,7 +16687,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16621,9 +16750,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16726,7 +16861,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16855,6 +16990,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16939,7 +17077,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17002,9 +17140,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17026,6 +17161,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17050,6 +17188,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17062,6 +17203,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17635,6 +17779,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17695,6 +17842,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17749,6 +17899,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17767,6 +17920,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18280,6 +18442,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18382,6 +18547,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18421,6 +18589,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18604,6 +18775,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18679,9 +18853,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18781,6 +18952,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18799,6 +18976,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18814,6 +18994,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18847,6 +19030,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19372,6 +19558,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19465,19 +19654,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19819,6 +20008,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20074,12 +20269,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20248,6 +20449,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20878,6 +21082,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21007,6 +21214,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21094,9 +21304,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21220,6 +21427,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21229,6 +21439,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21490,6 +21703,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21535,6 +21751,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21607,6 +21826,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21763,34 +21991,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21817,6 +22039,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21910,9 +22138,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22048,9 +22273,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22498,6 +22720,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22615,6 +22840,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22681,9 +22909,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22993,6 +23218,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23107,7 +23335,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23122,6 +23350,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23317,6 +23548,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23374,9 +23608,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23614,18 +23845,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23677,9 +23905,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23881,6 +24106,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23893,6 +24121,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23905,6 +24139,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23920,6 +24157,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24034,15 +24274,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24091,9 +24331,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24121,6 +24358,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24130,6 +24370,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24199,6 +24442,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24274,9 +24547,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24457,14 +24727,17 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24508,9 +24781,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24769,6 +25039,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24790,6 +25063,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25297,6 +25573,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25417,6 +25696,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25534,6 +25816,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25636,9 +25921,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25783,6 +26074,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26059,12 +26353,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26074,9 +26374,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26104,6 +26401,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26395,6 +26695,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26695,6 +26998,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26710,6 +27016,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26893,6 +27202,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26905,6 +27217,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27082,6 +27397,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27172,6 +27490,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27253,6 +27574,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27280,6 +27604,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27295,6 +27622,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27310,54 +27640,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27661,9 +27946,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27679,6 +27961,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27817,6 +28102,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27829,6 +28117,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28015,9 +28306,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28051,6 +28339,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28138,15 +28429,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28630,6 +28921,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28966,6 +29260,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28975,9 +29272,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29056,14 +29350,14 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29413,9 +29707,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29440,6 +29731,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29449,6 +29749,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29500,6 +29803,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29521,6 +29827,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29560,6 +29884,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29623,6 +29950,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29653,15 +29983,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29758,9 +30079,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30100,6 +30418,9 @@ msgstr[2] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30325,16 +30646,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30385,6 +30709,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30403,6 +30730,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30472,6 +30802,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30493,9 +30826,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30529,6 +30859,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30538,6 +30877,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30568,6 +30910,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30691,6 +31036,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30730,10 +31078,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30751,15 +31099,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31018,9 +31360,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31120,9 +31459,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31177,9 +31513,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31270,9 +31603,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31306,10 +31636,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31375,6 +31705,12 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31720,9 +32056,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31789,6 +32122,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31813,6 +32149,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31822,6 +32161,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31846,9 +32188,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32443,12 +32782,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32488,6 +32821,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32986,7 +33322,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33085,18 +33421,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33118,9 +33448,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33133,12 +33460,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33154,30 +33475,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33205,9 +33511,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33220,9 +33523,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33265,6 +33565,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33451,6 +33754,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33475,6 +33781,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33487,6 +33802,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33865,6 +34183,9 @@ msgstr[2] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33934,6 +34255,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33964,9 +34288,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34036,6 +34357,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34120,6 +34444,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34225,9 +34552,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34261,9 +34585,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34423,6 +34744,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34507,6 +34831,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34693,9 +35020,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34918,7 +35242,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35221,6 +35545,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35359,6 +35689,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35692,7 +36025,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35728,7 +36061,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35914,6 +36247,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36007,7 +36355,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36376,6 +36724,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36460,6 +36811,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36793,6 +37147,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36811,10 +37168,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36826,6 +37183,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36871,9 +37231,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36913,10 +37270,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37066,6 +37423,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37096,6 +37456,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37162,6 +37525,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37513,6 +37882,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37522,6 +37894,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37567,10 +37948,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38233,6 +38626,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38428,6 +38824,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38437,9 +38836,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38452,6 +38848,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38461,9 +38860,6 @@ msgstr[2] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38770,10 +39166,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38815,9 +39211,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38884,6 +39277,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39040,9 +39436,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39142,9 +39535,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39232,6 +39622,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39241,9 +39634,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39697,28 +40087,55 @@ msgstr[2] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39730,6 +40147,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39742,9 +40162,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39853,12 +40270,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39886,6 +40309,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39901,9 +40327,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39934,6 +40357,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39970,9 +40396,21 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39982,7 +40420,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40048,6 +40492,18 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40081,10 +40537,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40204,6 +40660,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40261,9 +40723,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40276,6 +40735,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40291,6 +40756,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40327,6 +40795,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40528,6 +40999,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40687,6 +41164,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40720,6 +41200,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40783,6 +41269,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40816,9 +41305,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40933,12 +41419,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40954,6 +41434,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41002,6 +41485,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41077,6 +41566,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index 10ffb180094..57c46b68756 100644
--- a/locale/sr_SP/gitlab.po
+++ b/locale/sr_SP/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:24\n"
+"PO-Revision-Date: 2021-11-02 00:38\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,27 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid " or "
msgstr ""
@@ -88,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -217,9 +205,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1141,6 +1126,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1225,9 +1213,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1282,6 +1276,9 @@ msgstr[2] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1552,9 +1549,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1588,7 +1582,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1615,6 +1609,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1963,6 +1960,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -2044,9 +2044,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2125,9 +2122,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2221,6 +2215,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2677,7 +2674,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2692,6 +2689,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2827,7 +2830,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3442,7 +3445,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3460,6 +3463,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3475,7 +3481,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3715,13 +3721,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3925,6 +3934,12 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3988,9 +4003,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4330,12 +4342,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4348,12 +4366,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4366,6 +4393,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4381,6 +4417,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4390,6 +4429,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4663,12 +4705,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4906,6 +4942,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5539,6 +5578,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5782,7 +5824,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5893,6 +5935,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -6100,9 +6145,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6388,9 +6430,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6448,6 +6487,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6778,6 +6823,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6811,6 +6859,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6925,6 +6976,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6967,15 +7021,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7618,7 +7666,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8059,6 +8107,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -8068,6 +8119,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -8077,9 +8131,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -8092,6 +8161,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8242,30 +8314,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8404,12 +8452,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8527,6 +8569,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8608,13 +8653,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8623,16 +8668,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8641,6 +8692,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8653,31 +8710,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8749,15 +8806,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8902,6 +8953,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -9028,10 +9082,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9229,7 +9283,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9253,9 +9307,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9376,9 +9427,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9448,9 +9496,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9535,9 +9580,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9643,6 +9685,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9661,6 +9706,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9673,9 +9721,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9691,6 +9736,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9826,6 +9874,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9943,7 +9994,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10066,10 +10117,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10126,6 +10174,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10180,6 +10231,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10339,6 +10399,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10408,6 +10471,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10903,6 +10969,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10969,6 +11038,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -11008,16 +11080,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -11092,9 +11182,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -11122,9 +11209,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11152,6 +11236,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11317,13 +11404,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11332,7 +11419,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11654,7 +11753,10 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11758,6 +11860,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11773,15 +11881,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11833,6 +11938,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11911,6 +12019,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11956,6 +12067,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12145,12 +12259,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12244,18 +12352,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12286,9 +12382,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12514,6 +12607,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12838,10 +12934,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12967,7 +13060,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13022,7 +13118,10 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -13123,7 +13222,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13423,6 +13522,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13600,6 +13702,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13897,9 +14002,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13981,6 +14083,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13996,6 +14101,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -14023,9 +14131,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14038,6 +14143,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -14122,6 +14233,12 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14356,9 +14473,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14551,6 +14665,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14803,6 +14920,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -15034,6 +15154,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15094,6 +15217,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15670,6 +15796,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15709,6 +15838,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15724,9 +15856,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15796,10 +15925,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15847,6 +15976,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16156,6 +16288,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16324,12 +16459,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16558,7 +16687,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16621,9 +16750,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16726,7 +16861,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16855,6 +16990,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16939,7 +17077,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -17002,9 +17140,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -17026,6 +17161,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17050,6 +17188,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -17062,6 +17203,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17635,6 +17779,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17695,6 +17842,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17749,6 +17899,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17767,6 +17920,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18280,6 +18442,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18382,6 +18547,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18421,6 +18589,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18604,6 +18775,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18679,9 +18853,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18781,6 +18952,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18799,6 +18976,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18814,6 +18994,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18847,6 +19030,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19372,6 +19558,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19465,19 +19654,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19819,6 +20008,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20074,12 +20269,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20248,6 +20449,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20878,6 +21082,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21007,6 +21214,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21094,9 +21304,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21220,6 +21427,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21229,6 +21439,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21490,6 +21703,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21535,6 +21751,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21607,6 +21826,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21763,34 +21991,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21817,6 +22039,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21910,9 +22138,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22048,9 +22273,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22498,6 +22720,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22615,6 +22840,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22681,9 +22909,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22993,6 +23218,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -23107,7 +23335,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23122,6 +23350,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23317,6 +23548,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23374,9 +23608,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23614,18 +23845,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23677,9 +23905,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23881,6 +24106,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23893,6 +24121,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23905,6 +24139,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23920,6 +24157,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24034,15 +24274,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -24091,9 +24331,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -24121,6 +24358,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -24130,6 +24370,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24199,6 +24442,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24274,9 +24547,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24457,14 +24727,17 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24508,9 +24781,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24769,6 +25039,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24790,6 +25063,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25297,6 +25573,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25417,6 +25696,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25534,6 +25816,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25636,9 +25921,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25783,6 +26074,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26059,12 +26353,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -26074,9 +26374,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26104,6 +26401,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26395,6 +26695,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26695,6 +26998,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26710,6 +27016,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26893,6 +27202,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26905,6 +27217,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27082,6 +27397,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27172,6 +27490,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27253,6 +27574,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27280,6 +27604,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27295,6 +27622,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27310,54 +27640,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27661,9 +27946,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27679,6 +27961,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27817,6 +28102,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27829,6 +28117,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -28015,9 +28306,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -28051,6 +28339,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28138,15 +28429,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28630,6 +28921,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28966,6 +29260,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28975,9 +29272,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -29056,14 +29350,14 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -29413,9 +29707,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29440,6 +29731,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29449,6 +29749,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29500,6 +29803,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29521,6 +29827,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29560,6 +29884,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29623,6 +29950,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29653,15 +29983,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29758,9 +30079,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -30100,6 +30418,9 @@ msgstr[2] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30325,16 +30646,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30385,6 +30709,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30403,6 +30730,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30472,6 +30802,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30493,9 +30826,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30529,6 +30859,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30538,6 +30877,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30568,6 +30910,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30691,6 +31036,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30730,10 +31078,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30751,15 +31099,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31018,9 +31360,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31120,9 +31459,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31177,9 +31513,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31270,9 +31603,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31306,10 +31636,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31375,6 +31705,12 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31720,9 +32056,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31789,6 +32122,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31813,6 +32149,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31822,6 +32161,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31846,9 +32188,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32443,12 +32782,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32488,6 +32821,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32986,7 +33322,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33085,18 +33421,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33118,9 +33448,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33133,12 +33460,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33154,30 +33475,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33205,9 +33511,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33220,9 +33523,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33265,6 +33565,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33451,6 +33754,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33475,6 +33781,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33487,6 +33802,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33865,6 +34183,9 @@ msgstr[2] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33934,6 +34255,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33964,9 +34288,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -34036,6 +34357,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -34120,6 +34444,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34225,9 +34552,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34261,9 +34585,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34423,6 +34744,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34507,6 +34831,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34693,9 +35020,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34918,7 +35242,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35221,6 +35545,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35359,6 +35689,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35692,7 +36025,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35728,7 +36061,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35914,6 +36247,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -36007,7 +36355,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36376,6 +36724,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36460,6 +36811,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36793,6 +37147,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36811,10 +37168,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36826,6 +37183,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36871,9 +37231,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36913,10 +37270,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -37066,6 +37423,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37096,6 +37456,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37162,6 +37525,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37513,6 +37882,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37522,6 +37894,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37567,10 +37948,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38233,6 +38626,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38428,6 +38824,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38437,9 +38836,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38452,6 +38848,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38461,9 +38860,6 @@ msgstr[2] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38770,10 +39166,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38815,9 +39211,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38884,6 +39277,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39040,9 +39436,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -39142,9 +39535,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39232,6 +39622,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39241,9 +39634,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39697,28 +40087,55 @@ msgstr[2] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39730,6 +40147,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39742,9 +40162,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39853,12 +40270,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39886,6 +40309,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39901,9 +40327,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39934,6 +40357,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39970,9 +40396,21 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39982,7 +40420,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -40048,6 +40492,18 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40081,10 +40537,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40204,6 +40660,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40261,9 +40723,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40276,6 +40735,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40291,6 +40756,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40327,6 +40795,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40528,6 +40999,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40687,6 +41164,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40720,6 +41200,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40783,6 +41269,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40816,9 +41305,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40933,12 +41419,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40954,6 +41434,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41002,6 +41485,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41077,6 +41566,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index f4d93bf0a8e..f327550b24d 100644
--- a/locale/sv_SE/gitlab.po
+++ b/locale/sv_SE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sv-SE\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:24\n"
+"PO-Revision-Date: 2021-11-02 00:38\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr " Typ"
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr " och"
-
msgid " and "
msgstr " och "
msgid " and %{sliced}"
msgstr " och %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " försämrad på %d punkt"
-msgstr[1] " försämrad på %d punkter"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " förbättrad på %d punkt"
-msgstr[1] " förbättrad på %d punkter"
-
msgid " or "
msgstr " eller "
@@ -86,6 +73,9 @@ msgstr "\"%{repository_name}\" storlek (%{repository_size}) är större än grä
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] "%d commit,"
msgstr[1] "%d commits,"
-msgid "%d commits"
-msgstr "%d commits"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] "%d slutfört ärende"
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr "(borttagen)"
msgid "(revoked)"
msgstr "(Ã¥terkallad)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr "En raderad användare"
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Skapa ny katalog"
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr "Gruppavatar"
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index 356772fb66d..4a91803a7cb 100644
--- a/locale/sw_KE/gitlab.po
+++ b/locale/sw_KE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sw\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:41\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/ta_IN/gitlab.po b/locale/ta_IN/gitlab.po
index 9bce689c49c..0413763bcef 100644
--- a/locale/ta_IN/gitlab.po
+++ b/locale/ta_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ta\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:18\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index 154381c7065..a13ef43fe50 100644
--- a/locale/tr_TR/gitlab.po
+++ b/locale/tr_TR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: tr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:21\n"
+"PO-Revision-Date: 2021-11-02 00:38\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr " Tür"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Bunu %{grace_period_deadline} önce yapmanız gerekiyor."
-msgid " and"
-msgstr " ve"
-
msgid " and "
msgstr " ve "
msgid " and %{sliced}"
msgstr " ve %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " %d noktasında bozuldu"
-msgstr[1] " %d noktasında bozuldu"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " %d noktasında geliştirildi"
-msgstr[1] " %d noktasında geliştirildi"
-
msgid " or "
msgstr " veya "
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr "#genel, #geliÅŸtirme"
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] "%d iÅŸlem"
msgstr[1] "%d iÅŸlem"
-msgid "%d commits"
-msgstr "%d iÅŸlem"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] "%d tamamlanmış konu"
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr "(silindi)"
msgid "(revoked)"
msgstr "(iptal edildi)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "%{amount} tane daha"
@@ -1193,6 +1189,9 @@ msgstr[1] "- Olaylar"
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- Kullanıcı"
@@ -1439,9 +1438,6 @@ msgstr "Boş bir proje için bir varsayılan dal seçilemez."
msgid "A deleted user"
msgstr "Silinmiş kullanıcı"
-msgid "A description is required"
-msgstr "Bir açıklama gerekli"
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr "Bir platform deÄŸeri web, mobil veya uygulama olabilir."
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr "Eylemler"
msgid "Activate Service Desk"
msgstr "Servis Masasını Etkinleştir"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Etkin"
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Bu %{noteableDisplayName} için genel bir yorum ekle."
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "Buna %{noteable_name} genel bir yorum ekle."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Wiki'nize projeniz hakkında bilgi içeren bir ana sayfa ekleyin. GitLab bu mesaj yerine onu burada görüntüleyecektir."
@@ -2012,9 +2011,6 @@ msgstr "Dağıtım durdurma ekle"
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr "Etki alanı ekle"
-
msgid "Add email address"
msgstr "E-posta adresi ekle"
@@ -2108,6 +2104,9 @@ msgstr "Ä°ncelemeye ekle"
msgid "Add to tree"
msgstr "AÄŸaca ekle"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr "Tetikleyici ekle"
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "Yönetici"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr "Tüm birleştirme isteği bağımlılıkları birleştirildi"
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr "Tüm kullanıcıların bir adı olmalıdır."
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "\"%{group_name}\" grubunun oturum açmasına izin ver"
@@ -3362,7 +3370,7 @@ msgstr "Hedef dala bağlanabilecek üyelerin işlemlerine izin verin."
msgid "Allow group owners to manage LDAP-related settings"
msgstr "Grup sahiplerinin LDAP ile ilgili ayarları yönetmesine izin ver"
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "Bildirimlere abone olunurken bir hata oluÅŸtu."
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr "Bir sorun zaten var"
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Onaylayanlar"
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr "Ä°sim"
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr "Kural adı"
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr "Hedef dal"
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr "Emin misiniz? Bu, kayıtlı uygulamalarınızı ve U2F cihazlarınızı geçersiz kılar."
-
msgid "Arrange charts"
msgstr "Grafikleri düzenle"
@@ -4783,6 +4820,9 @@ msgstr "AÄŸustos"
msgid "Authenticate"
msgstr "Kimlik doÄŸrulama"
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr "GitHub ile Kimlik Doğrulaması"
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr "Blog"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "Pano kapsamı, bu panoyu ziyaret eden kişilere hangi sorunların gösterileceğini belirler"
@@ -5656,8 +5699,8 @@ msgstr "Tümü"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "Bu dal için HEAD işlemi bulunamadı"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "Karşılaştır"
@@ -5767,6 +5810,9 @@ msgstr "Kabul etmek için %{branch_name_confirmation} yazın:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Yerel değişikliklerden vazgeçip akış sürümüyle dalın üzerine yazmak için, buradan silin ve yukarıdan 'Şimdi Güncelle'yi seçin."
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr "CI Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr "CI ayarları"
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr "Otomatik olarak birleÅŸtirilemez"
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr "Kapasite eÅŸiÄŸi"
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr "Ödeme"
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr "Düzenle"
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr "Son Erme %{expirationMonth}/%{expirationYear}"
@@ -6796,6 +6848,9 @@ msgstr "ÅŸirket veya ekip"
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr "Bir şablon seç..."
msgid "Choose a type..."
msgstr "Bir tür seç..."
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr "Herhangi bir renk seçin."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr "Dosya seçin…"
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr "Güvenlik grubu"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "Makine türlerini seç"
@@ -7963,6 +8033,9 @@ msgstr "Makine türü seçimine göre alan ve proje seç"
msgid "ClusterIntegration|Select project to choose zone"
msgstr "Seçili alan için proje seç"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr "kaydol"
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr "Bir güvenlik grubu seçin"
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr "Bir alt ağ seçin"
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr "Bir örnek türü seçin"
-
-msgid "ClusterIntergation|Select key pair"
-msgstr "Anahtar çifti seçin"
-
-msgid "ClusterIntergation|Select service role"
-msgstr "Bir hizmet rolü seçin"
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr "Komutlar uygulanmadı"
msgid "Comment"
msgstr "Yorum"
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr "Topluluk forumu"
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "Karşılaştır"
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr "Destek ile iletişime geçin"
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "Kapsayıcı Kaydı"
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr "%{protocol} klon URL'sini kopyala"
-msgid "Copy %{proxy_url}"
-msgstr "%{proxy_url} kopyala"
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr "Bağlantıyı kopyala"
msgid "Copy link to chart"
msgstr "Bağlantıyı grafiğe kopyala"
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr "Referansı kopyala"
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr "Bu sohbet takma adı yetkilendirilemedi. Tekrar deneyin!"
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr "Kapsam"
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Yeni Dizin OluÅŸtur"
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr "BirleÅŸtirme isteÄŸi oluÅŸtur"
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr "Yeni bir sorun oluÅŸtur"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr "Yeni bir depo oluÅŸtur"
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr "Özel aralık"
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10767,6 +10834,9 @@ msgstr "Tarih seçici"
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr "Varsayılan dal"
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr "Varsayılan sınıflandırma etiketi"
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr "Yorumu sil"
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr "Etki alanını sil"
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr "Kod parçacığını sil"
@@ -11016,6 +11101,9 @@ msgstr "Kullanıcı listesini sil"
msgid "Delete variable"
msgstr "DeÄŸiÅŸkeni sil"
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,8 +11281,20 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
-msgstr "Bağımlılık vekil sunucusunu aç/kapat"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
+msgstr ""
msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr "%{filename} deÄŸiÅŸmedi"
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr "Yorumu kaydet"
msgid "DesignManagement|Select all"
msgstr "Tümünü seç"
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr "Tasarımlar"
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr "Ücretsiz deneme sürümü başlatın"
msgid "Discover|Upgrade now"
msgstr "Şimdi yükselt"
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr "Bir veya daha fazla kümeyle ilişkilendirilirken etki alanı silinemez."
-
-msgid "Domain was successfully created."
-msgstr "Etki alanı başarıyla oluşturuldu."
-
-msgid "Domain was successfully deleted."
-msgstr "Etki alanı başarıyla silindi."
-
-msgid "Domain was successfully updated."
-msgstr "Etki alanı başarıyla güncellendi."
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr "%{format} olarak indir"
msgid "Download %{format}:"
msgstr "%{format} indir:"
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr "Bu sürümü düzenle"
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr "Korunan yolların sıklık limitini etkinleştir"
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr "Ortam durdurulurken bir hata oluştu, lütfen tekrar deneyin"
msgid "Environments|Are you sure you want to stop this environment?"
msgstr "Bu ortamı durdurmak istediğinizden emin misiniz?"
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr "Epik oluÅŸtururken hata oluÅŸtu"
msgid "Error creating label."
msgstr "Etiket ayarlanırken hata oluştu"
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr "BitiÅŸ tarihi:"
@@ -13875,9 +13982,6 @@ msgstr "Genel grupları keşfedin"
msgid "Export"
msgstr "Dışa aktar"
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "Projeyi dışa aktar"
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr "Kaldır"
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr "İlk Görülme"
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr "Genel Ayarlar"
msgid "General pipelines"
msgstr "Genel iş hatları"
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr "Varsayılan etiket kümesi oluştur"
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr "GitLab proje dışa aktarımı"
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr "Gitea içe aktarma"
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr "Grup profil resmi"
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr "Grup açıklaması (isteğe bağlı)"
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "Epikler alınırken bir şeyler ters gitti"
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr "Grup bulunamadı"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr "DeÄŸerleri gizle"
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr "En yüksek rol:"
@@ -16874,6 +17007,9 @@ msgstr "Geçmiş"
msgid "History of authentications"
msgstr "Kimlik doğrulama geçmişi"
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr "Saat (UTC)"
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr "Temizlik hizmeti"
@@ -16910,6 +17049,9 @@ msgstr "Temizlik hizmeti, dışa aktarma, yol, transfer, kaldırma, arşivleme."
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr "%{time_ago} katıldı"
@@ -19917,12 +20110,18 @@ msgstr "Son EriÅŸim Tarihi"
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "Son İş Hattı"
msgid "Last Seen"
msgstr "Son Görülme"
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr "Bir kümeyi dağıtma hakkında daha fazla bilgi edinin"
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr "Birleştirme zamanı"
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr "Y ekseni etiketi"
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr "Yeni etiket"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr "Yeni kullanıcılar harici olarak ayarlandı"
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr "Hiçbir katkı bulunamadı"
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr "Kredi kartı gerektirmez."
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr "Gizli deÄŸil"
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr "Önce en eski"
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr "Seçimi Aç"
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr "Yorum türü açılır penceresini aç"
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr "Açık hatalar"
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr "Operasyonlar"
-
msgid "Operations Dashboard"
msgstr "Ä°ÅŸlemler Panosu"
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr "Seçenekler"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr "Sahibi"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr "Yol:"
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr "Profil"
msgid "Profile Settings"
msgstr "Profil Ayarları"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr "-"
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr "Adınızın yanında \"Meşgul\" gösterilecek"
-
msgid "Profiles|%{provider} Active"
msgstr "%{provider} Aktif"
@@ -25930,6 +26224,9 @@ msgstr "Durum ifadesi ekle"
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr "Kullanıcı adınız güncellenirken bir hata oluştu, lütfen tekrar deneyin."
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr "Profil resmi kırpıcı"
@@ -26221,6 +26518,9 @@ msgstr "Profil resminizi buraya yükleyebilir veya %{gravatar_link} adresinden d
msgid "Profiles|You don't have access to delete this user."
msgstr "Bu kullanıcıyı silme yetkiniz yok."
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr "Sorunlar"
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr "Yeni proje oluÅŸtur"
msgid "ProjectsNew|Description format"
msgstr "Açıklama formatı"
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr "İçe aktar"
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "Proje açıklaması %{tag_start}(isteğe bağlı)%{tag_end}"
@@ -27136,54 +27463,9 @@ msgstr "Aynı isim alanı altında birkaç bağımlı projeye ev sahipliği yapm
msgid "Prometheus"
msgstr "Prometheus"
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr "Korunan Yollar"
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr "Korunan dallar"
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr "Ürün pazarlama e-postalarını al"
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr "Son Proje EtkinliÄŸi"
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "EriÅŸim Talebi"
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr "Gereksinimler"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr "Çalışıyor"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "Geçerli depoda, dosya düzeltmelerini sıkıştırma ve erişilemeyen nesneleri kaldırma gibi bir dizi temizlik görevi yürütür."
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr "DeÄŸiÅŸiklikleri Kaydet"
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr "Uygulamayı kaydet"
@@ -29905,6 +30220,9 @@ msgstr[1] "viki sonucu"
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr "Sorun oluÅŸtur"
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr "Proje"
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr "Sayfa Seç"
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr "Yeni bir isim alanı seçin"
msgid "Select a project"
msgstr "Bir proje seç"
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr "Sunucu sürümü"
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,12 +31438,12 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "ÅŸifre ayarla"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr "Durum ifadesi ekle"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "SetStatusModal|Busy"
msgstr ""
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr "Benzer sorunlar"
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "Parçacıklar"
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "Gösterilecek parçacık yok."
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr "Aramayı başlat"
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr "Başarıyla kilit kaldırıldı"
msgid "Successfully updated %{last_updated_timeago}."
msgstr "%{last_updated_timeago} başarıyla güncellendi."
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr "Pazar"
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr "Destek sayfası URL'si"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr "Bu etiketin sürüm notu yok."
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "Ekip"
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr "Henüz bu grupla paylaşılan proje yok."
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr "Bu projenin devam etmesini sağlamak için yeni bir fikir verin"
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr "Ek dakika satın al"
@@ -36605,10 +36958,10 @@ msgstr "Mevcut dönem kullanımı"
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr "LFS Depolama"
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr "Depolama"
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,12 +37060,12 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr "Kullanım"
-msgid "UsageQuota|Usage Breakdown"
-msgstr ""
-
msgid "UsageQuota|Usage Quotas"
msgstr "Kullanım Kotaları"
+msgid "UsageQuota|Usage breakdown"
+msgstr ""
+
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
msgstr "Grup kaynaklarının gruptaki projeler arasında %{strong_start}%{group_name}%{strong_end} kullanılması"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr "Åžablonu kullan"
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr "Kullanıcı Ayarları"
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr "Yenilikler"
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,12 +38952,12 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
+msgid "Write a description…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Dönüm noktası açıklaması yazın..."
-msgid "Write to \"authorized_keys\" file"
-msgstr ""
-
msgid "Write your release notes or drag your files here…"
msgstr ""
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr "[Sebep yok]"
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr "silinmiş bir kullanıcı"
-msgid "a design"
-msgstr "bir tasarım"
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr "birleÅŸtirilemez"
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,8 +40202,14 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
-msgstr "Kod kalitesi"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
msgid "ciReport|Container Scanning"
msgstr ""
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr "SAST"
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr "dağıt"
msgid "design"
msgstr ""
-msgid "designs"
-msgstr "tasarımlar"
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr "Ek olarak onayla"
msgid "mrWidget|Approved by"
msgstr "Onaylayan:"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr "Dağıtım istatistikleri yükleniyor"
@@ -40594,9 +41077,6 @@ msgstr "Birleştirme başarısız."
msgid "mrWidget|Merge locally"
msgstr "Yerel olarak birleÅŸtir"
-msgid "mrWidget|Merge request approved."
-msgstr "Birleştirme talebi onaylandı."
-
msgid "mrWidget|Merged by"
msgstr "BirleÅŸtiren:"
@@ -40711,12 +41191,6 @@ msgstr "Kaynak dal silinmeyecek"
msgid "mrWidget|There are merge conflicts"
msgstr "Birleştirme çakışmaları var"
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr "veya"
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index d6f1419d28e..dc989ee54da 100644
--- a/locale/uk/gitlab.po
+++ b/locale/uk/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: uk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:38\n"
msgid " %{start} to %{end}"
msgstr " %{start} до %{end}"
@@ -40,29 +40,12 @@ msgstr " Тип"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Ви повинні зробити це до %{grace_period_deadline}."
-msgid " and"
-msgstr " Ñ–"
-
msgid " and "
msgstr " Ñ– "
msgid " and %{sliced}"
msgstr " Ñ– %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " погіршилоÑÑ Ð½Ð° %d одиницю"
-msgstr[1] " погіршилоÑÑ Ð½Ð° %d одиниць"
-msgstr[2] " погіршилоÑÑ Ð½Ð° %d одиниць"
-msgstr[3] " погіршилоÑÑ Ð½Ð° %d одиниць"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " покращилоÑÑ Ð½Ð° %d одиницю"
-msgstr[1] " покращилоÑÑ Ð½Ð° %d одиниць"
-msgstr[2] " покращилоÑÑ Ð½Ð° %d одиниць"
-msgstr[3] " покращилоÑÑ Ð½Ð° %d одиниць"
-
msgid " or "
msgstr " або "
@@ -90,9 +73,12 @@ msgstr "Розмір \"%{repository_name}\" (%{repository_size}) перевищÑ
msgid "\"el\" parameter is required for createInstance()"
msgstr "Параметр \"el\" необхідний Ð´Ð»Ñ createInstance()"
-msgid "#general, #development"
+msgid "#%{issueIid} (closed)"
msgstr ""
+msgid "#general, #development"
+msgstr "#загальне, #розробка"
+
msgid "%d Alert"
msgid_plural "%d Alerts"
msgstr[0] ""
@@ -221,10 +207,10 @@ msgstr[3] "%d комітів"
msgid "%d commit author"
msgid_plural "%d commit authors"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d автор коміту"
+msgstr[1] "%d автори коміту"
+msgstr[2] "%d авторів коміту"
+msgstr[3] "%d авторів коміту"
msgid "%d commit behind"
msgid_plural "%d commits behind"
@@ -240,9 +226,6 @@ msgstr[1] "%d коміта,"
msgstr[2] "%d комітів,"
msgstr[3] "%d комітів,"
-msgid "%d commits"
-msgstr "%d комітів"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -603,10 +586,10 @@ msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or
msgstr "%{code_open}Захищений:%{code_close} Відкритий лише захищеними гілками або тегами."
msgid "%{commit_author_link} authored %{commit_authored_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} автор%{commit_authored_timeago}"
msgid "%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} автор %{commit_authored_timeago} та %{commit_committer_avatar} %{commit_committer_link} коміт %{commit_committer_timeago}"
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} заповнена вага"
@@ -710,13 +693,13 @@ msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
msgstr "%{doc_link_start}Розширений пошук%{doc_link_end} увімкнено."
msgid "%{docs_link_start}Learn about visibility levels.%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}ДовідайтеÑÑŒ про рівні видимоÑÑ‚Ñ–.%{docs_link_end}"
msgid "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Що таке Ñховище великих файлів?%{docs_link_end}"
msgid "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start} Що таке Двофакторна автентифікаціÑ?%{docs_link_end}"
msgid "%{due_date} (Past due)"
msgstr "%{due_date} (з проÑтроченнÑм)"
@@ -794,7 +777,7 @@ msgid "%{issuesSize} with a limit of %{maxIssueCount}"
msgstr "%{issuesSize} з обмеженнÑм %{maxIssueCount}"
msgid "%{italic_start}What's new%{italic_end} is inactive and cannot be viewed."
-msgstr ""
+msgstr "%{italic_start}Що нового %{italic_end} неактивний Ñ– не може бути розглÑнутим"
msgid "%{itemsCount} issues with a limit of %{maxIssueCount}"
msgstr "%{itemsCount} задач з обмеженнÑм %{maxIssueCount}"
@@ -848,13 +831,13 @@ msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} недоÑтупний"
msgid "%{learn_more_link}."
-msgstr ""
+msgstr "%{learn_more_link}."
msgid "%{lessThan} 1 hour"
-msgstr ""
+msgstr "%{lessThan} 1 година"
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
-msgstr ""
+msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} – це безкоштовний, автоматизований Ñ– відкритий центр Ñертифікації (CA), Ñкий видає цифрові Ñертифікати, щоб увімкнути HTTPS (SSL/TLS) Ð´Ð»Ñ Ñайтів."
msgid "%{level_name} is not allowed in a %{group_level_name} group."
msgstr "%{level_name} не дозволено в %{group_level_name} групі."
@@ -863,7 +846,7 @@ msgid "%{level_name} is not allowed since the fork source project has lower visi
msgstr "%{level_name} не допуÑкаєтьÑÑ, оÑкільки проєкт-джерело цього форку має нижчу видиміÑÑ‚ÑŒ."
msgid "%{link_start}Learn more%{link_end} about roles."
-msgstr ""
+msgstr "%{link_start}ДовідайтеÑÑŒ більше%{link_end} про ролі."
msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr "%{link_start}Видаліть %{draft_snippet} префікÑ%{link_end} з назви , щоб зробити можливим Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту, коли він буде готовий."
@@ -872,10 +855,10 @@ msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
-msgstr ""
+msgstr "%{link_start}Яку інформацію збирає ÐºÐ¾Ð¼Ð¿Ð°Ð½Ñ–Ñ GitLab Inc.?%{link_end}"
msgid "%{listToShow}, and %{awardsListLength} more"
-msgstr ""
+msgstr "%{listToShow}та %{awardsListLength} ще"
msgid "%{location} is missing required keys: %{keys}"
msgstr "%{location} відÑутні необхідні ключі: %{keys}"
@@ -908,7 +891,7 @@ msgid "%{name_with_link} namespace has %{percent} or less Shared Runner Pipeline
msgstr ""
msgid "%{name_with_link} namespace has run out of Shared Runner Pipeline minutes. No new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "%{name_with_link} у проÑторі імен вичерпано хвилин загальних Runner'ів конвеєра. Ðових завдань у проєктах не буде."
msgid "%{name} (Busy)"
msgstr "%{name} (зайнÑто)"
@@ -1015,7 +998,7 @@ msgid "%{rotation} has been recalculated with the remaining participants. Please
msgstr ""
msgid "%{scope} results for term '%{term}'"
-msgstr ""
+msgstr "%{scope} результати Ð´Ð»Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ \"%{term}\""
msgid "%{seconds}s"
msgstr "%{seconds}Ñ"
@@ -1035,7 +1018,7 @@ msgstr[2] ""
msgstr[3] ""
msgid "%{service_ping_link_start}What information is shared with GitLab Inc.?%{service_ping_link_end}"
-msgstr ""
+msgstr "%{service_ping_link_start}Яку інформацію надає GitLab Inc.?%{service_ping_link_end}"
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -1071,10 +1054,10 @@ msgid "%{state} epics"
msgstr "%{state} епіки"
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
-msgstr ""
+msgstr "%{strongOpen}ПопередженнÑ:%{strongClose} поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¸ SAML може Ñпричинити автоматичне Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ ÑƒÑ‡Ð°Ñників із груп."
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
-msgstr ""
+msgstr "%{strongStart}Порада:%{strongEnd}Ви також можете перевірити запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾, %{linkStart}дотримуючиÑÑŒ цих вказівок%{linkEnd}"
msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
@@ -1180,7 +1163,7 @@ msgid "%{total} open issue weight"
msgstr "%{total} загальна вага відкритих задач"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
-msgstr ""
+msgstr "%{total}знайдено Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ : показано перше%{warningsDisplayed}"
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (не може виконувати злиттÑ)"
@@ -1189,16 +1172,16 @@ msgid "%{userName}'s avatar"
msgstr "%{userName} аватар"
msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
-msgstr ""
+msgstr "%{user_name} (%{user_username}) було видалено з %{rotation} в %{schedule} в %{project}. "
msgid "%{user_name} profile page"
msgstr "%{user_name} Ñторінка профілю"
msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr ""
+msgstr "%{username} змінив ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ‡ÐµÑ€Ð½ÐµÑ‚ÐºÐ¸ запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %{mr_link}"
msgid "%{username} has asked for a GitLab account on your instance %{host}:"
-msgstr ""
+msgstr "%{username} попроÑив Ñтворити обліковий Ð·Ð°Ð¿Ð¸Ñ GitLab у вашому випадку%{host}:"
msgid "%{username}'s avatar"
msgstr "%{username} аватар"
@@ -1227,6 +1210,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1237,7 +1223,7 @@ msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
msgstr "'%{data}' в %{location} не відповідає шаблону: %{pattern}"
msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
-msgstr ""
+msgstr "'%{data}' на %{location} - не відповідає типу: %{type}"
msgid "'%{data}' at %{location} is not of type: %{type}"
msgstr "'%{data}' на %{location} - не відповідає типу: %{type}"
@@ -1312,7 +1298,13 @@ msgstr "(видалено)"
msgid "(revoked)"
msgstr "(відкликано)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
+msgstr "(нам потрібен ваш поточний пароль Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… змін)"
+
+msgid "* All times are in UTC unless specified"
msgstr ""
msgid "+ %{amount} more"
@@ -1335,7 +1327,7 @@ msgstr[2] "+%d додатково"
msgstr[3] "+%d додатково"
msgid "+%{approvers} more approvers"
-msgstr ""
+msgstr "+ ще%{approvers} більше затверджуючих оÑіб"
msgid "+%{extra} more"
msgstr "+%{extra} більше"
@@ -1371,6 +1363,9 @@ msgstr[3] "- Подій"
msgid "- Not available to run jobs."
msgstr "- ÐедоÑтупний Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку завдань."
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- КориÑтувач"
@@ -1388,7 +1383,7 @@ msgid "."
msgstr "."
msgid "/"
-msgstr ""
+msgstr "/"
msgid "0 bytes"
msgstr "0 байт"
@@ -1454,10 +1449,10 @@ msgstr[3] ""
msgid "1 follower"
msgid_plural "%{count} followers"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "1 підпиÑник"
+msgstr[1] "%{count} підпиÑника"
+msgstr[2] "%{count} підпиÑників"
+msgstr[3] "%{count} підпиÑників"
msgid "1 group"
msgid_plural "%d groups"
@@ -1482,10 +1477,10 @@ msgstr[3] "Вибрано %d задач"
msgid "1 merge request selected"
msgid_plural "%d merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "вибрано 1 запит на злиттÑ"
+msgstr[1] "вибрано %d запити на злиттÑ"
+msgstr[2] "вибрано %d запитів на злиттÑ"
+msgstr[3] "вибрано %d запитів на злиттÑ"
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
@@ -1567,7 +1562,7 @@ msgid "1000+"
msgstr "1000+"
msgid "192.168.0.0/24"
-msgstr ""
+msgstr "192.168.0.0/24"
msgid "1st contribution!"
msgstr "Перший внеÑок!"
@@ -1621,7 +1616,7 @@ msgid ":%{startLine} to %{endLine}"
msgstr ":%{startLine} до %{endLine}"
msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
-msgstr ""
+msgstr "%{incident_docs_start}змінено задачу %{incident_docs_end} Ð´Ð»Ñ ÐºÐµÑ€Ñ–Ð²Ð½Ð¸Ñ†Ñ‚Ð²Ð° вирішеннÑм інцидентів."
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr "Шаблон конÑольного заÑтоÑунку .NET Core, Ñкий налаштовуєтьÑÑ Ð´Ð»Ñ Ð±ÑƒÐ´ÑŒ-Ñкого проєкту .NET Core"
@@ -1665,9 +1660,6 @@ msgstr "Ðе можна обирати уÑтавну гілку Ð´Ð»Ñ Ð¿Ð¾Ñ€Ð¾
msgid "A deleted user"
msgstr "Видалений кориÑтувач"
-msgid "A description is required"
-msgstr "Потрібен опиÑ"
-
msgid "A different reason"
msgstr "Інша причина"
@@ -1701,8 +1693,8 @@ msgstr "УчаÑник команди по боротьбі з порушеннÑ
msgid "A merge request hasn't yet been merged"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‰Ðµ не злито"
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
-msgstr "Створено новий конвеєр Auto DevOps, детальну інформацію можна знайти на Ñторінці %{pipelines_link_start}Конвеєри%{pipelines_link_end}"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
+msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
msgstr "Опубліковано новий Реліз %{tag} Ð´Ð»Ñ %{name}. ПереглÑньте %{release_link_start}Сторінку Релізів%{release_link_end} щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ."
@@ -1726,6 +1718,9 @@ msgid "A platform value can be web, mob or app."
msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
+msgstr "Проєкт boilerplate Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±ÐºÐ¸ заÑтоÑунку Salesforce з інÑтрументами розробника Salesforce"
+
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
msgstr ""
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
@@ -1780,13 +1775,13 @@ msgid "API?"
msgstr "API?"
msgid "APIFuzzing|$VARIABLE_WITH_PASSWORD"
-msgstr ""
+msgstr "$VARIABLE_WITH_PASSWORD"
msgid "APIFuzzing|$VARIABLE_WITH_USERNAME"
-msgstr ""
+msgstr "$VARIABLE_WITH_USERNAME"
msgid "APIFuzzing|API Fuzzing Configuration"
-msgstr ""
+msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ API Fuzsing"
msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr "Базова URL-адреÑа цілі теÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ API. Ðаприклад, http://www.example.com."
@@ -1798,7 +1793,7 @@ msgid "APIFuzzing|Choose a profile"
msgstr "Виберіть профіль"
msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
+msgstr "Сніпет не вдалоÑÑ Ñтворити. Спробуйте ще раз пізніше."
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ñновних значень автентифікації HTTP. ПідтримуютьÑÑ Ñ–Ð½ÑˆÑ– методи автентифікації. %{linkStart}Докладніше%{linkEnd}."
@@ -1810,34 +1805,34 @@ msgid "APIFuzzing|Enable authentication"
msgstr "Увімкнути автентифікацію"
msgid "APIFuzzing|Enter the name of the CI variable containing the password. For example, $VARIABLE_WITH_PASSWORD."
-msgstr ""
+msgstr "Введіть ім'Ñ Ð·Ð¼Ñ–Ð½Ð½Ð¾Ñ—, що міÑтить пароль. Ðаприклад, $VARIABLE_WITH_PASSWORD."
msgid "APIFuzzing|Enter the name of the CI variable containing the username. For example, $VARIABLE_WITH_USERNAME."
-msgstr ""
+msgstr "Введіть ім'Ñ Ð·Ð¼Ñ–Ð½Ð½Ð¾Ñ—, що міÑтить ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. Ðаприклад, $VARIABLE_WITH_USERNAME."
msgid "APIFuzzing|File path or URL to APIs to be tested. For example, folder/example_fuzz.har. HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
-msgstr ""
+msgstr "ДоÑтуп до файлу або URL -адреÑа Ð´Ð»Ñ Ñпецифікації OpenAPI. Ðаприклад, папка/openapi.json або http://www.example.com/openapi.json."
msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
-msgstr ""
+msgstr "ШлÑÑ… до файлу або URL -адреÑа запитів Ð´Ð»Ñ Ñ‚ÐµÑтуваннÑ. Ðаприклад, папка/example.postman_collection.json."
msgid "APIFuzzing|Generate code snippet"
msgstr "Створити Ñніпет коду"
msgid "APIFuzzing|Make sure your credentials are secured"
-msgstr ""
+msgstr "ПереконайтеÑÑ, що ваші облікові дані захищені"
msgid "APIFuzzing|Password for basic authentication"
-msgstr ""
+msgstr "Пароль Ð´Ð»Ñ Ð±Ð°Ð·Ð¾Ð²Ð¾Ñ— автентифікації"
msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
-msgstr ""
+msgstr "Режим ÑкануваннÑ"
msgid "APIFuzzing|Scan profile"
msgstr ""
@@ -1846,10 +1841,10 @@ msgid "APIFuzzing|Show code snippet for the profile"
msgstr ""
msgid "APIFuzzing|Target URL"
-msgstr ""
+msgstr "Цільова URL -адреÑа"
msgid "APIFuzzing|There are three ways to perform scans."
-msgstr ""
+msgstr "ІÑнує три ÑпоÑоби Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÑкануваннÑ."
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
msgstr ""
@@ -1867,10 +1862,10 @@ msgid "APIFuzzing|To prevent a security leak, authentication info must be added
msgstr ""
msgid "APIFuzzing|Username for basic authentication"
-msgstr ""
+msgstr "Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ð´Ð»Ñ Ð±Ð°Ð·Ð¾Ð²Ð¾Ñ— аутентифікації"
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
-msgstr ""
+msgstr "Вам може знадобитиÑÑ Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð° учаÑника команди проєкту Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñту ваших облікових даних."
msgid "APIFuzzing|folder/example.postman_collection.json"
msgstr ""
@@ -1954,7 +1949,7 @@ msgid "Access granted"
msgstr "ДоÑтуп дозволено"
msgid "Access key ID"
-msgstr ""
+msgstr "Ідентифікатор ключа доÑтупу"
msgid "Access requests"
msgstr "Запити на доÑтуп"
@@ -2076,6 +2071,9 @@ msgstr "Дії"
msgid "Activate Service Desk"
msgstr "Ðктивувати Службу підтримки"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "Ðктивний"
@@ -2157,9 +2155,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Додайте загальний коментар до цього %{noteableDisplayName}."
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "Додайте загальний коментар до цього %{noteable_name}."
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Додати домашню Ñторінку в вікі, Ñка міÑтить інформацію про ваш проєкт, Ñ– GitLab відображатиме його тут заміÑÑ‚ÑŒ цього повідомленнÑ."
@@ -2215,7 +2210,7 @@ msgid "Add bold text"
msgstr "Додати жирний текÑÑ‚"
msgid "Add broadcast message"
-msgstr ""
+msgstr "Додати широкомовне повідомленнÑ"
msgid "Add child epic to an epic"
msgstr "Додати дочірній епік до епіка"
@@ -2230,7 +2225,7 @@ msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
msgstr "Додати коментар до завдань Asana. %{docs_link}"
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
-msgstr ""
+msgstr "Додати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñк коментарі до Ñ–Ñторій Pivotal Tracker. %{docs_link}"
msgid "Add deploy freeze"
msgstr "Додати Ð·Ð°Ð¼Ð¾Ñ€Ð¾Ð¶ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
@@ -2238,9 +2233,6 @@ msgstr "Додати Ð·Ð°Ð¼Ð¾Ñ€Ð¾Ð¶ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr "Додайте ключі розгортаннÑ, щоб надати доÑтуп до читаннÑ/запиÑу цього репозиторію. %{link_start}Що таке ключі розгортаннÑ?%{link_end}"
-msgid "Add domain"
-msgstr "Додати домен"
-
msgid "Add email address"
msgstr "Додати адреÑу електронної пошти"
@@ -2278,7 +2270,7 @@ msgid "Add new directory"
msgstr "Додати новий каталог"
msgid "Add new service account"
-msgstr ""
+msgstr "Додати новий обліковий запиÑ"
msgid "Add or remove previously merged commits"
msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ€Ð°Ð½Ñ–ÑˆÐµ злитих комітів"
@@ -2334,6 +2326,9 @@ msgstr "Додати до перевірки"
msgid "Add to tree"
msgstr "Додати до дерева"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr "Додати тригер"
@@ -2359,16 +2354,16 @@ msgid "AddContextCommits|Add/remove"
msgstr "Додати/видалити"
msgid "AddMember|Emails cannot be blank"
-msgstr ""
+msgstr "ÐдреÑа електронної пошти не може бути порожньою"
msgid "AddMember|Invite email is invalid"
-msgstr ""
+msgstr "ÐдреÑа електронної пошти Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð½ÐµÐ´Ñ–Ð¹Ñна"
msgid "AddMember|Invite limit of %{daily_invites} per day exceeded"
msgstr "Перевищено ліміт запрошень: %{daily_invites} на день"
msgid "AddMember|No invite source provided."
-msgstr ""
+msgstr "ВідÑутнє джерело запрошеннÑ."
msgid "AddMember|No users specified."
msgstr "Жодного кориÑтувача не вказано."
@@ -2452,7 +2447,7 @@ msgid "Adjust how frequently the GitLab UI polls for updates."
msgstr ""
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
-msgstr ""
+msgstr "Ðалаштуйте фільтри / умови пошуку, наведені вище. Якщо ви думаєте, що це помилка, переглÑньте документацію на Ñторінці %{linkStart}Geo Troubleshooting%{linkEnd}, щоб отримати додаткову інформацію."
msgid "Admin"
msgstr "ÐдмініÑтратор"
@@ -2674,7 +2669,7 @@ msgid "AdminSettings|Protect CI/CD variables by default"
msgstr "ЗахиÑтити змінні CI/CD за замовчуваннÑм"
msgid "AdminSettings|Require users to prove ownership of custom domains"
-msgstr ""
+msgstr "Вимагати від кориÑтувачів Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð°Ð²Ð° влаÑноÑÑ‚Ñ– на влаÑні домени"
msgid "AdminSettings|Required pipeline configuration"
msgstr "Ðеобхідна ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñƒ"
@@ -2790,7 +2785,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "ÐдмініÑтратор"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2800,9 +2795,15 @@ msgid "AdminUsers|Approve"
msgstr "Затвердити"
msgid "AdminUsers|Approve user %{username}?"
-msgstr ""
+msgstr "Затвердити кориÑтувача %{username}?"
msgid "AdminUsers|Approved users can:"
+msgstr "Затверджені кориÑтувачі можуть:"
+
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
msgstr ""
msgid "AdminUsers|Automatically marked as default internal user"
@@ -2940,8 +2941,8 @@ msgstr "Повторна Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ ÐºÐ¾Ñ€Ð¸Ñтувача зробитÑ
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
-msgstr "Звичайні кориÑтувачі мають доÑтуп до Ñвоїх груп та проєктів"
+msgid "AdminUsers|Regular users have access to their groups and projects."
+msgstr ""
msgid "AdminUsers|Reject"
msgstr "Відхилити"
@@ -3145,10 +3146,10 @@ msgid "After a successful password update, you will be redirected to the login p
msgstr "ПіÑÐ»Ñ ÑƒÑпішного Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ ви будете перенаправлені на Ñторінку входу, де ви зможете увійти з новим паролем."
msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
-msgstr ""
+msgstr "ПіÑÐ»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ ви не зможете викориÑтовувати Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½Ð° Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð°Ð±Ð¾ ÑкіÑÑ‚ÑŒ коду, а також багато інших функцій."
msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
-msgstr ""
+msgstr "ПіÑÐ»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ ви не зможете викориÑтовувати Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð°Ð±Ð¾ епіки, а також багато інших функцій."
msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
msgstr ""
@@ -3555,8 +3556,8 @@ msgstr "УÑÑ– конфлікти Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ð¸Ñ€Ñ–ÑˆÐµÐ½Ð¾. Тепер за
msgid "All merge request dependencies have been merged"
msgstr "Ð’ÑÑ– залежноÑÑ‚Ñ– запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÑƒÐ»Ð¸ злиті"
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
-msgstr "Ð’ÑÑ– шлÑхи Ñ” відноÑними до URL-адреÑи GitLab. Ðе включайте %{relative_url_link_start}відноÑну URL-адреÑу%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
+msgstr ""
msgid "All projects"
msgstr "Ð’ÑÑ– проєкти"
@@ -3573,6 +3574,9 @@ msgstr "УÑÑ– кориÑтувачі мають прийнÑти умови нÐ
msgid "All users must have a name."
msgstr "Ð’ÑÑ– кориÑтувачі повинні мати імена."
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Дозволити вхід через \"%{group_name}\""
@@ -3588,8 +3592,8 @@ msgstr "Дозволити коміти від учаÑників, Ñкі мож
msgid "Allow group owners to manage LDAP-related settings"
msgstr "Дозволити влаÑникам груп керувати налаштуваннÑми LDAP"
-msgid "Allow non-administrators to access to the performance bar"
-msgstr "Дозволити кориÑтувачам без прав адмініÑтратора доÑтуп до панелі продуктивноÑÑ‚Ñ–"
+msgid "Allow non-administrators access to the performance bar"
+msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Дозволити викориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ вибраних протоколів Ð´Ð»Ñ Ð´Ð¾Ñтупу до Git."
@@ -3828,13 +3832,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -4038,6 +4045,13 @@ msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñ–Ð² ÑталаÑÑ Ð¿Ð¾Ð¼Ð
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "Помилка при підпиÑці на ÑповіщеннÑ."
@@ -4101,9 +4115,6 @@ msgstr "Приклад проєкту, Ñкий показує найкращиÐ
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr "Ð¦Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° вже Ñ–Ñнує"
@@ -4450,12 +4461,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr "Правила затвердженнÑ"
@@ -4468,12 +4485,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Затверджуючі оÑоби"
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr "Ім'Ñ"
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4486,6 +4512,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr "Ð†Ð¼â€™Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð°"
@@ -4501,6 +4536,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4510,6 +4548,9 @@ msgstr "Цільова гілка"
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4553,7 +4594,7 @@ msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
msgstr ""
msgid "Approvals are optional."
-msgstr ""
+msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½ÐµÐ¾Ð±Ð¾Ð²'Ñзкові."
msgid "Approvals|Section: %section"
msgstr ""
@@ -4784,12 +4825,6 @@ msgstr "Ви впевнені? Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ GPG ключа не
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr "Ви впевнені? Це призведе до Ð°Ð½ÑƒÐ»ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ñ€ÐµÑ”Ñтрованих заÑтоÑунків та U2F приÑтроїв."
-
msgid "Arrange charts"
msgstr "ВпорÑдкувати графіки"
@@ -5029,6 +5064,9 @@ msgstr "Ñерпень"
msgid "Authenticate"
msgstr "Ðвтентифікувати"
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr "Ðвтентифікувати за допомогою GitHub"
@@ -5663,11 +5701,14 @@ msgstr "Блокує"
msgid "Blog"
msgstr "Блог"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "ОблаÑÑ‚ÑŒ видимоÑÑ‚Ñ– дошки впливає на те, Ñкі задачі відображаютьÑÑ Ð´Ð»Ñ Ñ‚Ð¸Ñ…, хто Ñ—Ñ— переглÑдає"
msgid "BoardNewEpic|Groups"
-msgstr ""
+msgstr "Групи"
msgid "BoardNewEpic|Loading groups"
msgstr ""
@@ -5676,10 +5717,10 @@ msgid "BoardNewEpic|No matching results"
msgstr ""
msgid "BoardNewEpic|Search groups"
-msgstr ""
+msgstr "Пошук груп"
msgid "BoardNewEpic|Select a group"
-msgstr ""
+msgstr "Виберіть групу"
msgid "BoardNewIssue|No matching results"
msgstr ""
@@ -5700,7 +5741,7 @@ msgid "BoardScope|An error occurred while searching for users, please try again.
msgstr ""
msgid "BoardScope|Any Milestone"
-msgstr ""
+msgstr "Будь-Ñкий етап"
msgid "BoardScope|Any assignee"
msgstr ""
@@ -5718,13 +5759,13 @@ msgid "BoardScope|No milestone"
msgstr "Етап відÑутній"
msgid "BoardScope|Search milestones"
-msgstr ""
+msgstr "Пошук етапів"
msgid "BoardScope|Select assignee"
msgstr ""
msgid "BoardScope|Select milestone"
-msgstr ""
+msgstr "Вибрати етап"
msgid "BoardScope|Select weight"
msgstr ""
@@ -5908,8 +5949,8 @@ msgstr "Ð’ÑÑ–"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "Ðе можу знайти HEAD-коміт Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— гілки"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "ПорівнÑти"
@@ -6019,6 +6060,9 @@ msgstr "Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ, введіть %{branch_name_confirma
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "Щоб відхилити локальні зміни Ñ– перезапиÑати гілку верÑією з upstream, видаліть Ñ—Ñ— тут Ñ– виберіть \"Оновити зараз\" вище."
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr "Так, видалити гілку"
@@ -6131,7 +6175,7 @@ msgid "BulkImport|Name already exists."
msgstr "Ім'Ñ Ð²Ð¶Ðµ Ñ–Ñнує."
msgid "BulkImport|New group"
-msgstr ""
+msgstr "Ðова група"
msgid "BulkImport|No history is available"
msgstr ""
@@ -6226,9 +6270,6 @@ msgstr "Перевірка CI конфігурації"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI"
@@ -6327,10 +6368,10 @@ msgid "CICD|Select projects that can be accessed by API requests authenticated w
msgstr ""
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file."
-msgstr ""
+msgstr "Конвеєр Auto DevOps запуÑкаєтьÑÑ Ð·Ð° замовчуваннÑм у вÑÑ–Ñ… проєктах без конфігурації CI/CD."
msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
-msgstr ""
+msgstr "Конвеєр Auto DevOps запуÑкаєтьÑÑ, Ñкщо не знайдено альтернативного файлу конфігурації CI."
msgid "CICD|group enabled"
msgstr "група увімкнена"
@@ -6515,9 +6556,6 @@ msgstr "СкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду"
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr "Ðеможливо злити автоматично"
@@ -6575,6 +6613,12 @@ msgstr "Ðеможливо пропуÑтити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð²Ð¾Ñ
msgid "Capacity threshold"
msgstr "Поріг пропуÑкної здатноÑÑ‚Ñ–"
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6690,7 +6734,7 @@ msgid "ChangeTypeAction|Revert in branch"
msgstr ""
msgid "ChangeTypeAction|Search branches"
-msgstr ""
+msgstr "Пошук гілок"
msgid "ChangeTypeAction|Search projects"
msgstr "Пошук проєктів"
@@ -6907,6 +6951,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr "ÐžÑ„Ð¾Ñ€Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ"
@@ -6940,6 +6987,9 @@ msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ форму кредитної
msgid "Checkout|Edit"
msgstr "Редагувати"
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -7052,6 +7102,9 @@ msgid "Checkout|company or team"
msgstr "ÐºÐ¾Ð¼Ð¿Ð°Ð½Ñ–Ñ Ð°Ð±Ð¾ команда"
msgid "Checkout|minutes"
+msgstr "хвилини"
+
+msgid "Checkout|x %{quantity} %{units} per pack"
msgstr ""
msgid "Checkout|x %{quantity} %{units} per pack ="
@@ -7096,15 +7149,9 @@ msgstr "Виберіть тему-шаблон..."
msgid "Choose a type..."
msgstr "Виберіть тип..."
-msgid "Choose any color"
-msgstr "Вибрати будь-Ñкий колір"
-
msgid "Choose any color."
msgstr "Вибрати будь-Ñкий колір."
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr "Виберіть файл…"
@@ -7121,7 +7168,7 @@ msgid "Choose the top-level group for your repository imports."
msgstr "Оберіть групу найвищого Ñ€Ñ–Ð²Ð½Ñ Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ репозиторіїв."
msgid "Choose visibility level, enable/disable project features and their permissions, disable email notifications, and show default award emoji."
-msgstr ""
+msgstr "Виберіть рівень видимоÑÑ‚Ñ–, увімкніть/вимкніть функції проєкту та Ñ—Ñ… дозволи, вимкніть ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою та показувати емодзі."
msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
@@ -7520,7 +7567,7 @@ msgid "ClusterAgents|Configuration"
msgstr "КонфігураціÑ"
msgid "ClusterAgents|Connected"
-msgstr ""
+msgstr "Підключено"
msgid "ClusterAgents|Connection status"
msgstr ""
@@ -7747,7 +7794,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -8188,6 +8235,9 @@ msgstr "Група безпеки"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "ПереглÑнути та редагувати параметри вашого Kubernetes-клаÑтера"
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr "Виберіть VPC Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ групи безпеки"
@@ -8197,6 +8247,9 @@ msgstr "Виберіть VPC Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ підмережі"
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "Виберіть мережу Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ підмережі"
@@ -8206,9 +8259,24 @@ msgstr "Виберіть регіон Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ пари ключів"
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr "Виберіть регіон Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ VPC"
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr "Виберіть зону Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ мережі"
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "Вибрати тип машин"
@@ -8221,6 +8289,9 @@ msgstr "Виберіть проєкт та зону Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, що виб
msgid "ClusterIntegration|Select project to choose zone"
msgstr "Виберіть проєкт, щоб вибрати зону"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8371,30 +8442,6 @@ msgstr "задовольнÑÑ” вимогам"
msgid "ClusterIntegration|sign up"
msgstr "реєÑтрації"
-msgid "ClusterIntergation|Select a VPC"
-msgstr "Вибрати VPC"
-
-msgid "ClusterIntergation|Select a network"
-msgstr "Вибрати мережу"
-
-msgid "ClusterIntergation|Select a security group"
-msgstr "Вибрати групу безпеки"
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr "Вибрати підмережу"
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr "Вибрати підмережу"
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr "Вибрати тип інÑтанÑу"
-
-msgid "ClusterIntergation|Select key pair"
-msgstr "Вибрати пару ключів"
-
-msgid "ClusterIntergation|Select service role"
-msgstr "Вибрати Ñлужбову роль"
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8477,7 +8524,7 @@ msgid "Collapse"
msgstr "Згорнути"
msgid "Collapse all threads"
-msgstr ""
+msgstr "Згорнути вÑÑ– теми"
msgid "Collapse approvers"
msgstr "Згорнути ÑпиÑок затверджуючих оÑіб"
@@ -8533,12 +8580,6 @@ msgstr "Команди не заÑтоÑовано"
msgid "Comment"
msgstr "Коментар"
-msgid "Comment & close %{noteable_name}"
-msgstr "Коментувати та закрити %{noteable_name}"
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr "Коментувати та повторно відкрити %{noteable_name}"
-
msgid "Comment & resolve thread"
msgstr "Коментувати та закрити обговореннÑ"
@@ -8657,6 +8698,9 @@ msgstr ""
msgid "Company"
msgstr "КомпаніÑ"
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "ПорівнÑти"
@@ -8738,31 +8782,37 @@ msgstr "Завершено"
msgid "Completed"
msgstr "Завершено"
-msgid "Compliance"
-msgstr "ВідповідніÑÑ‚ÑŒ"
-
-msgid "Compliance Dashboard"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
msgid "Compliance framework"
msgstr ""
+msgid "Compliance report"
+msgstr ""
+
msgid "ComplianceDashboard|created by:"
msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8771,6 +8821,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8783,31 +8839,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
-msgstr "Ðаприклад include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8879,15 +8935,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr "Ðалаштувати Ñ–Ñнуючу інÑталÑцію"
-msgid "Configure paths to be protected by Rack Attack."
-msgstr "Ðалаштуйте шлÑхи Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñту від атак Rack Attack."
-
msgid "Configure repository mirroring."
msgstr "Ðалаштувати Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð²."
@@ -9032,6 +9082,9 @@ msgstr ""
msgid "Contact support"
msgstr "ЗвернутиÑÑ Ð´Ð¾ Ñлужби підтримки"
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "РеєÑÑ‚Ñ€ Контейнерів"
@@ -9160,10 +9213,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9362,7 +9415,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9386,9 +9439,6 @@ msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ репозиторій %{titl
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr "Ви можете додати образ до цього реєÑтру за допомогою наÑтупних команд:"
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr "МіÑтить %{count} бінарних даних зображень (%{size})"
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9509,9 +9559,6 @@ msgstr "Скопіювати %{name}"
msgid "Copy %{protocol} clone URL"
msgstr "Скопіювати URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %{protocol}"
-msgid "Copy %{proxy_url}"
-msgstr "Скопіювати %{proxy_url}"
-
msgid "Copy %{type}"
msgstr "Скопіювати %{type}"
@@ -9581,9 +9628,6 @@ msgstr "Скопіювати поÑиланнÑ"
msgid "Copy link to chart"
msgstr "Копіювати поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° графік"
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr "Скопіювати поÑиланнÑ"
@@ -9668,9 +9712,6 @@ msgstr "Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ адмініÑтраторів Ñк уÑ
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr "Ðе вдалоÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·ÑƒÐ²Ð°Ñ‚Ð¸ пÑевдонім Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ. Спробуйте ще раз!"
@@ -9776,6 +9817,9 @@ msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ваші дизайни, оÑ
msgid "Couldn't assign policy to project"
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð·Ð½Ð°Ñ‡Ð¸Ñ‚Ð¸ політику Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ"
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr "ПокриттÑ"
@@ -9794,6 +9838,9 @@ msgstr ""
msgid "Create %{type}"
msgstr "Створити %{type}"
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Створити новий каталог"
@@ -9806,9 +9853,6 @@ msgstr "Спочатку Ñтворіть обліковий Ð·Ð°Ð¿Ð¸Ñ GitLab,
msgid "Create a Mattermost team for this group"
msgstr "Створити команду в Mattermost Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи"
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr "Створити локальний прокÑÑ– залежноÑтей Ð´Ð»Ñ Ñ‡Ð°Ñто викориÑтовуваних образів. %{link_start}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ%{link_end} про прокÑÑ– залежноÑтей."
-
msgid "Create a merge request"
msgstr "Створити запит на злиттÑ"
@@ -9824,6 +9868,9 @@ msgstr "Створіть новий файл, тому що наразі немÐ
msgid "Create a new issue"
msgstr "Створити нову задачу"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr "Створити новий репозиторій"
@@ -9959,6 +10006,9 @@ msgstr "Створити Ñніпет"
msgid "Create tag %{tagName}"
msgstr "Створити тег %{tagName}"
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr "Створити кориÑтувача"
@@ -10076,7 +10126,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -10199,10 +10249,7 @@ msgstr "ОÑобиÑÑ‚Ñ– токени доÑтупу"
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -10259,6 +10306,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr "Поточна кількіÑÑ‚ÑŒ вразливоÑтей"
@@ -10313,6 +10363,15 @@ msgstr "КориÑтувацький діапазон"
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10472,6 +10531,9 @@ msgstr "Днів до завершеннÑ"
msgid "CycleAnalytics|Display chart filters"
msgstr "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ñ–Ð»ÑŒÑ‚Ñ€Ñ–Ð² графіків"
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr "Жодної Ñтадії не вибрано"
@@ -10543,6 +10605,9 @@ msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ DAST"
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -11039,6 +11104,9 @@ msgstr "Вибір дати"
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -11105,6 +11173,9 @@ msgstr "Гілка за замовчуваннÑм"
msgid "Default branch and protected branches"
msgstr "Гілка за замовчуваннÑм Ñ– захищені гілки"
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr "Мітка клаÑифікації за замовчуваннÑм"
@@ -11144,18 +11215,36 @@ msgstr "По замовчуванню: викориÑтовувати ідент
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "Визначте влаÑний шаблон за допомогою ÑинтакÑиÑу cron"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr "Визначте влаÑний шаблон за допомогою ÑинтакÑиÑу cron"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -11228,9 +11317,6 @@ msgstr "Видалити коментар"
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr "Видалити домен"
-
msgid "Delete file"
msgstr ""
@@ -11258,9 +11344,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr "Видалити Ñніпет"
@@ -11288,6 +11371,9 @@ msgstr "Видалити ÑпиÑок кориÑтувачів"
msgid "Delete variable"
msgstr "Видалити змінну"
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "Помилка при видаленні репозиторію проєкту. Будь лаÑка, Ñпробуйте знову, або зв'ÑжітьÑÑ Ñ–Ð· адмініÑтратором."
@@ -11456,23 +11542,35 @@ msgstr "ПрокÑÑ– залежноÑтей"
msgid "Dependency Scanning"
msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей"
-msgid "Dependency proxy"
-msgstr "ПрокÑÑ– залежноÑтей"
+msgid "DependencyProxy|Cached %{time}"
+msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
-msgstr "Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ Ð¿Ñ€Ð¾ÐºÑÑ– залежноÑтей наразі доÑтупна тільки Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… груп."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
+msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
msgstr ""
msgid "DependencyProxy|Dependency Proxy"
+msgstr "ПрокÑÑ– залежноÑтей"
+
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
-msgstr "Увімкнути/вимкнути прокÑÑ– залежноÑтей"
+msgid "DependencyProxy|Manifest list"
+msgstr ""
msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
@@ -11797,7 +11895,11 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr "%{current_design} з %{designs_count}"
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð¸Ð·Ð°Ð¹Ð½Ñƒ із тим же ім’Ñм файлу замінює цей файл новою верÑією."
@@ -11901,6 +12003,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr "Виділити уÑÑ–"
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr "МакÑимальна кількіÑÑ‚ÑŒ дизайнів, Ñкі можна завантажити — %{upload_limit}. Будь лаÑка, Ñпробуйте знову."
@@ -11916,15 +12024,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr "Дизайни"
@@ -11976,11 +12081,14 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
-msgstr ""
+msgstr "ЗатвердженнÑ"
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
@@ -11998,7 +12106,7 @@ msgid "DevopsAdoption|At least one merge request opened"
msgstr ""
msgid "DevopsAdoption|At least one pipeline successfully run"
-msgstr ""
+msgstr "Щонайменше один конвеєр уÑпішно запущено"
msgid "DevopsAdoption|Code owners"
msgstr ""
@@ -12054,6 +12162,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -12099,6 +12210,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -12291,12 +12405,6 @@ msgstr "Розпочати безкоштовну пробну верÑÑ–ÑŽ"
msgid "Discover|Upgrade now"
msgstr "Оновити зараз"
-msgid "Discuss a specific suggestion or question"
-msgstr "Обговорити конкретну пропозицію чи питаннÑ"
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr "Обговорити конкретну пропозицію або питаннÑ, що необхідно вирішити"
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr "Обговорити конкретну пропозицію або питаннÑ, що необхідно вирішити."
@@ -12391,18 +12499,6 @@ msgstr "Домен"
msgid "Domain Name"
msgstr "Доменне ім'Ñ"
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr "Домен уÑпішно Ñтворено."
-
-msgid "Domain was successfully deleted."
-msgstr "Домен уÑпішно видалено."
-
-msgid "Domain was successfully updated."
-msgstr "Домен уÑпішно оновлено."
-
msgid "Don't have an account yet?"
msgstr "Ще не зареєÑтровані?"
@@ -12433,9 +12529,6 @@ msgstr "Завантажити %{format}"
msgid "Download %{format}:"
msgstr "Завантажити %{format}:"
-msgid "Download %{name} artifact"
-msgstr "Завантажити %{name} артефакт"
-
msgid "Download (%{fileSizeReadable})"
msgstr "Завантажити (%{fileSizeReadable})"
@@ -12661,6 +12754,9 @@ msgstr "Редагувати цей реліз"
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr "Редагувати кориÑтувача: %{user_name}"
@@ -12758,7 +12854,7 @@ msgid "Email sent"
msgstr "ЛиÑта відправлено"
msgid "Email the pipeline status to a list of recipients."
-msgstr ""
+msgstr "ВідправлÑти ÑÑ‚Ð°Ñ‚ÑƒÑ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð° по електронній пошті ÑпиÑок одержувачів."
msgid "Email updates (optional)"
msgstr ""
@@ -12985,11 +13081,8 @@ msgstr "Увімкнути чи вимкнути збір даних Ð´Ð»Ñ Pseu
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr "Увімкнути Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñ‰ÐµÐ½Ð¸Ñ… шлÑхів"
-
-msgid "Enable proxy"
-msgstr "ЗадіÑти прокÑÑ–-Ñервер"
+msgid "Enable rate limiting for POST requests to the specified paths"
+msgstr ""
msgid "Enable reCAPTCHA"
msgstr "Увімкнути reCAPTCHA"
@@ -13114,7 +13207,10 @@ msgstr "Введіть номер"
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -13169,7 +13265,11 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr "Середовище"
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Environment does not have deployments"
msgstr "Середовище не має розгортань"
@@ -13270,7 +13370,7 @@ msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·ÑƒÐ¿Ð¸Ð½ÐºÐ¸ ÑередоÐ
msgid "Environments|Are you sure you want to stop this environment?"
msgstr "Ви впевнені що хочете зупинити це Ñередовище?"
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13499,7 +13599,7 @@ msgid "Epics|Remove issue"
msgstr "Видалити задачу"
msgid "Epics|Search epics"
-msgstr ""
+msgstr "Пошук епіків"
msgid "Epics|Select epic"
msgstr ""
@@ -13570,6 +13670,9 @@ msgstr "Помилка при Ñтворенні епіку"
msgid "Error creating label."
msgstr "Помилка при Ñтворенні мітки."
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr "Помилка при Ñтворенні нової ітерації"
@@ -13747,6 +13850,9 @@ msgstr "Помилка з Akismet. Будь лаÑка, перевірте жуÑ
msgid "Error: %{error_message}"
msgstr "Помилка: %{error_message}"
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13889,7 +13995,7 @@ msgid "EscalationPolicies|Remove escalation rule"
msgstr ""
msgid "EscalationPolicies|Search for user"
-msgstr ""
+msgstr "Пошук кориÑтувача"
msgid "EscalationPolicies|Select schedule"
msgstr ""
@@ -13952,13 +14058,13 @@ msgid "Every %{action} attempt has failed: %{job_error_message}. Please try agai
msgstr "УÑÑ– Ñпроби %{action} закінчилиÑÑ Ð½ÐµÐ²Ð´Ð°Ñ‡ÐµÑŽ: %{job_error_message}. Будь лаÑка, Ñпробуйте знову."
msgid "Every 3 months"
-msgstr ""
+msgstr "Кожні 3 міÑÑцÑ"
msgid "Every 3 months on the %{day} at %{time} %{timezone}"
msgstr ""
msgid "Every 6 months"
-msgstr ""
+msgstr "Кожні 6 міÑÑцÑ"
msgid "Every 6 months on the %{day} at %{time} %{timezone}"
msgstr ""
@@ -14001,7 +14107,7 @@ msgid "Every week on %{day} at %{time} %{timezone}"
msgstr ""
msgid "Every year"
-msgstr ""
+msgstr "Щороку"
msgid "Every year on %{day} at %{time} %{timezone}"
msgstr ""
@@ -14045,9 +14151,6 @@ msgstr "Потрібен лише один з %{attributes}"
msgid "Example: @sub\\.company\\.com$"
msgstr "Приклад: @sub\\.company\\.com$"
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr "Ðаприклад: Usage = одиночний запит. (Requested) / (Capacity) = кілька запитів, пов’Ñзаних у формулу."
-
msgid "Except policy:"
msgstr "Політика виключеннÑ:"
@@ -14129,6 +14232,9 @@ msgstr "Термін дії"
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr "Термін дії закінчивÑÑ"
@@ -14144,6 +14250,9 @@ msgstr "ЗакінчуєтьÑÑ"
msgid "Expires in %{expires_at}"
msgstr "ЗакінчуєтьÑÑ %{expires_at}"
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr "ЗакінчуєтьÑÑ:"
@@ -14171,9 +14280,6 @@ msgstr "ПереглÑнути публічні групи"
msgid "Export"
msgstr "ЕкÑпорт"
-msgid "Export %{name}"
-msgstr "ЕкÑпорт %{name}"
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -14186,6 +14292,12 @@ msgstr ""
msgid "Export group"
msgstr "ЕкÑпортувати групу"
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "ЕкÑпорт проєкту"
@@ -14270,6 +14382,13 @@ msgstr "Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ Zoom-зуÑтріч"
msgid "Failed to apply commands."
msgstr "Ðе вдалоÑÑ Ð·Ð°ÑтоÑувати команди."
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14504,9 +14623,6 @@ msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸."
msgid "Failed to upload object map file"
msgstr "Ðе вдалоÑÑ Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ файл відповідноÑÑ‚Ñ– об’єктів"
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr "Помилка"
@@ -14700,6 +14816,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr "Видалити"
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14953,6 +15072,9 @@ msgstr "Завершено"
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr "Перший раз помічено"
@@ -15184,6 +15306,9 @@ msgstr "Знайдено помилки у вашому .gitlab-ci.yml:"
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15244,6 +15369,9 @@ msgstr "Загальні налаштуваннÑ"
msgid "General pipelines"
msgstr "Загальні конвеєри"
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr "Створити Ñтандартний набір міток"
@@ -15761,7 +15889,7 @@ msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
-msgstr ""
+msgstr "Триває перенеÑÐµÐ½Ð½Ñ Git"
msgid "Git version"
msgstr "Git-верÑÑ–Ñ"
@@ -15820,6 +15948,9 @@ msgstr ""
msgid "GitLab commit"
msgstr "GitLab коміт"
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr "ЕкÑпорт GitLab"
@@ -15859,6 +15990,9 @@ msgstr "URL-адреÑа метаданних GitLab"
msgid "GitLab project export"
msgstr "ЕкÑпорт проєкту GitLab"
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15874,9 +16008,6 @@ msgstr ""
msgid "GitLab version"
msgstr "ВерÑÑ–Ñ GitLab"
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "GitLab запуÑтить фонове завданнÑ, Ñке буде оброблÑти пÑевдонімізовані CSV-файли бази даних GitLab, Ñкі будуть надіÑлані до вашого налаштованого Ñховища об'єктів."
-
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -15946,10 +16077,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr "ЩоÑÑŒ пішло не так при отриманні Ñертифікату Let's Encrypt Ð´Ð»Ñ %{domain}. Перевірте %{link_start}деталі домену%{link_end}, щоб повторити Ñпробу."
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
-msgstr "Підтримку доменів та Ñертифікатів вимкнено. ЗвернітьÑÑ Ð´Ð¾ адмініÑтратора Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб Ñ—Ñ… увімкнути."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15997,6 +16128,9 @@ msgstr "Імпорт з Gitea"
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16190,13 +16324,13 @@ msgid "Goal of the changes and what reviewers should be aware of"
msgstr ""
msgid "Google Cloud"
-msgstr ""
+msgstr "Google Cloud"
msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
-msgstr ""
+msgstr "ÐÐ²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Google не %{link_start}налаштована належним чином%{link_end}. ЗвернітьÑÑ Ð´Ð¾ вашого адмініÑтратора GitLab Ñкщо хочете викориÑтовувати цю Ñлужбу."
msgid "Got it"
msgstr "Зрозуміло"
@@ -16306,6 +16440,9 @@ msgstr "Ðватар групи"
msgid "Group by"
msgstr "Групувати за"
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr "ÐžÐ¿Ð¸Ñ Ð³Ñ€ÑƒÐ¿Ð¸ (необов'Ñзково)"
@@ -16474,12 +16611,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "Проблема при завантаженні епіків"
@@ -16673,7 +16804,7 @@ msgid "GroupSelect|No matching results"
msgstr ""
msgid "GroupSelect|Search groups"
-msgstr ""
+msgstr "Пошук груп"
msgid "GroupSelect|Select a group"
msgstr "Вибрати групу"
@@ -16708,7 +16839,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16771,9 +16902,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16876,7 +17013,7 @@ msgstr "Групи не знайдені"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Ви можете керувати правами доÑтупу членів групи мати доÑтуп до кожного проєкту в ній."
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -17005,6 +17142,9 @@ msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ°"
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr "Заголовок 1"
@@ -17089,8 +17229,8 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
-msgstr "Допомагає зменшити об’єм запитів Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñ‰ÐµÐ½Ð¸Ñ… шлÑхів"
+msgid "Helps reduce request volume for protected paths."
+msgstr ""
msgid "Here you will find recent merge request activity"
msgstr "Тут ви знайдете нещодавню активніÑÑ‚ÑŒ в запитах на злиттÑ"
@@ -17154,9 +17294,6 @@ msgstr "Сховати значеннÑ"
msgid "High or unknown vulnerabilities present"
msgstr "ПриÑутні вразливоÑÑ‚Ñ– виÑокого або невідомого рівнÑ"
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr "Ðайвища кількіÑÑ‚ÑŒ запитів за хвилину Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ необробленого шлÑÑ…, за замовчуваннÑм Ñкладає 300. Ð”Ð»Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð²Ñтановіть в 0."
-
msgid "Highest role:"
msgstr "Ðайвища роль:"
@@ -17178,6 +17315,9 @@ msgstr "ІÑторіÑ"
msgid "History of authentications"
msgstr "ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ð¹"
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -17202,6 +17342,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr "Година (UTC)"
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr "ОчищеннÑ"
@@ -17214,6 +17357,9 @@ msgstr "ОчищеннÑ, екÑпорт, шлÑÑ…, перенеÑеннÑ, ви
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17532,7 +17678,7 @@ msgid "Import from Jira"
msgstr "Імпортувати з Jira"
msgid "Import group"
-msgstr ""
+msgstr "Імпортувати групу"
msgid "Import group from file"
msgstr ""
@@ -17790,6 +17936,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17850,6 +17999,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17904,6 +18056,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17922,6 +18077,15 @@ msgstr "ЗапроÑити Ñвою команду зараз"
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18382,7 +18546,7 @@ msgid "Index all projects"
msgstr "ІндекÑувати вÑÑ– проєкти"
msgid "Index deletion is canceled"
-msgstr ""
+msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ–Ð½Ð´ÐµÐºÑу ÑкаÑовуєтьÑÑ"
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "Вказує на те, чи може даний runner виконувати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÐµÐ· тегів"
@@ -18435,6 +18599,9 @@ msgstr "УÑпадковано:"
msgid "Inline"
msgstr "Вбудований"
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr "Введіть ключі хоÑта вручну"
@@ -18538,6 +18705,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr "ІнтеграціÑ"
@@ -18577,6 +18747,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18760,6 +18933,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr "Внутрішні кориÑтувачі"
@@ -18835,9 +19011,6 @@ msgstr "Ðекоректна назва pod_name"
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr "Ðеправильний запит"
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18937,6 +19110,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18955,6 +19134,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr "СкаÑувати"
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18965,16 +19147,19 @@ msgid "InviteMembersModal|Configure CI/CD"
msgstr "Ðалаштувати CI/CD"
msgid "InviteMembersModal|Configure security features"
-msgstr ""
+msgstr "Ðалаштувати функції безпеки"
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
-msgstr ""
+msgstr "ЗапроÑити"
msgid "InviteMembersModal|Invite a group"
msgstr "ЗапроÑити групу"
@@ -18986,7 +19171,7 @@ msgid "InviteMembersModal|Members were successfully added"
msgstr ""
msgid "InviteMembersModal|Other"
-msgstr ""
+msgstr "Інші"
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19003,6 +19188,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19528,6 +19716,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19621,19 +19812,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19820,7 +20011,7 @@ msgid "Job"
msgstr "ЗавданнÑ"
msgid "Job %{jobName}"
-msgstr ""
+msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ %{jobName}"
msgid "Job Failed #%{build_id}"
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð½ÐµÐ²Ð´Ð°Ð»Ðµ #%{build_id}"
@@ -19975,6 +20166,12 @@ msgstr "з"
msgid "Join Zoom meeting"
msgstr "ПриєднатиÑÑ Ð´Ð¾ зуÑтрічі в Zoom"
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -20231,12 +20428,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "ОÑтанній Конвеєр"
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr "ОÑтаннє викориÑтаннÑ"
@@ -20405,6 +20608,9 @@ msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð² клÐ
msgid "Learn more about group-level project templates"
msgstr "Докладніше про шаблони проєктів на рівні групи"
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -21042,6 +21248,9 @@ msgstr "ПереконайтеÑÑ, що ви його зберегли, бо в
msgid "Makes this issue confidential."
msgstr "Робить цю задачу конфіденційною."
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -21171,6 +21380,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -21258,9 +21470,6 @@ msgstr "МакÑимальна роль"
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21384,6 +21593,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr "Перевищено макÑимальну кількіÑÑ‚ÑŒ коментарів"
@@ -21393,6 +21605,9 @@ msgstr "МакÑимальна кількіÑÑ‚ÑŒ дзеркал, що можуÑ
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21654,6 +21869,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21699,6 +21917,9 @@ msgstr "ЗалежноÑÑ‚Ñ– запиту на злиттÑ"
msgid "Merge request events"
msgstr "Події запиту на злиттÑ"
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21771,6 +21992,15 @@ msgstr "Конвеєри"
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21927,34 +22157,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr "Метрики та профілюваннÑ"
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21981,6 +22205,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -22006,10 +22236,10 @@ msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Перевірте документацію CI/CD щодо Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð² Ñередовищі"
msgid "Metrics|Collapse panel"
-msgstr ""
+msgstr "Згорнути панель"
msgid "Metrics|Collapse panel (Esc)"
-msgstr ""
+msgstr "Згорнути панель (Esc)"
msgid "Metrics|Copy YAML"
msgstr "Копіювати YAML"
@@ -22075,9 +22305,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr "Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð´Ñ–Ð±Ð½Ð¸Ñ… метрик"
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -22213,9 +22440,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr "Ðазва оÑÑ– Y"
@@ -22269,7 +22493,7 @@ msgstr[2] "Етапів"
msgstr[3] "Етапів"
msgid "Milestone due date"
-msgstr ""
+msgstr "Дата Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ ÐµÑ‚Ð°Ð¿Ñƒ"
msgid "Milestone lists not available with your current license"
msgstr "СпиÑки етапів не доÑтупні з вашою поточною ліцензією"
@@ -22305,7 +22529,7 @@ msgid "MilestoneSidebar|Copy reference"
msgstr "Копіювати поÑиланнÑ"
msgid "MilestoneSidebar|Due date"
-msgstr ""
+msgstr "Дата завершеннÑ"
msgid "MilestoneSidebar|Edit"
msgstr "Редагувати"
@@ -22329,10 +22553,10 @@ msgid "MilestoneSidebar|New issue"
msgstr "Ðова задача"
msgid "MilestoneSidebar|No due date"
-msgstr ""
+msgstr "Ðемає дати завершеннÑ"
msgid "MilestoneSidebar|No start date"
-msgstr ""
+msgstr "Ðемає дати початку"
msgid "MilestoneSidebar|None"
msgstr "Ðемає"
@@ -22344,7 +22568,7 @@ msgid "MilestoneSidebar|Reference:"
msgstr ""
msgid "MilestoneSidebar|Start date"
-msgstr ""
+msgstr "Дата початку"
msgid "MilestoneSidebar|Toggle sidebar"
msgstr ""
@@ -22365,10 +22589,10 @@ msgid "Milestones| You’re about to permanently delete the milestone %{mileston
msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити етап %{milestoneTitle}. Ðаразі цей етап не викориÑтовуєтьÑÑ Ð² жодних задачах або запитах на злиттÑ."
msgid "Milestones|Close Milestone"
-msgstr ""
+msgstr "Закрити етап"
msgid "Milestones|Completed Issues (closed)"
-msgstr ""
+msgstr "Виконані задачі (закриті)"
msgid "Milestones|Delete milestone"
msgstr "Видалити етап"
@@ -22404,7 +22628,7 @@ msgid "Milestones|Promoting %{milestoneTitle} will make it available for all pro
msgstr "ПеренеÑÐµÐ½Ð½Ñ %{milestoneTitle} на рівень групи зробить його доÑтупним Ð´Ð»Ñ Ð²ÑÑ–Ñ… проєктів в групі %{groupName}. ІÑнуючі проєктні етапи з такими ж заголовками будуть об'єднані."
msgid "Milestones|Reopen Milestone"
-msgstr ""
+msgstr "Повторно відкрити етап"
msgid "Milestones|This action cannot be reversed."
msgstr "Цю дію не можна ÑкаÑувати."
@@ -22664,6 +22888,9 @@ msgstr "ÐœÐ¾Ñ Ð´Ð¸Ð²Ð¾Ð²Ð¸Ð¶Ð½Ð° група"
msgid "My company or team"
msgstr "ÐœÐ¾Ñ ÐºÐ¾Ð¼Ð¿Ð°Ð½Ñ–Ñ Ð°Ð±Ð¾ команда"
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22782,6 +23009,9 @@ msgstr "Потребує уваги"
msgid "Network"
msgstr "Мережа"
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22848,9 +23078,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr "Редагувати політику"
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -23126,7 +23353,7 @@ msgid "New project page"
msgstr ""
msgid "New project pages"
-msgstr ""
+msgstr "Ðові Ñторінки проєкту"
msgid "New project/repository"
msgstr "Ðовий проєкт/репозиторій"
@@ -23161,6 +23388,9 @@ msgstr "Ðовий тег"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr "Ðові кориÑтувачі Ñ” \"зовнішні по замовчанню\""
@@ -23213,7 +23443,7 @@ msgid "No Matching Results"
msgstr "Ðемає відповідних результатів"
msgid "No Milestone"
-msgstr ""
+msgstr "Етап відÑутній"
msgid "No Scopes"
msgstr ""
@@ -23275,7 +23505,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -23290,6 +23520,9 @@ msgstr "Ðемає внеÑків"
msgid "No contributions were found"
msgstr "ВнеÑки не знайдено"
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr "Ðе потрібна кредитна картка."
@@ -23485,6 +23718,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr "ВразливоÑÑ‚Ñ– відÑутні"
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr "Ðе знайдено жодного вебхука, додайте його у формі вище."
@@ -23543,9 +23779,6 @@ msgstr "ÐедоÑтупно Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¸Ñ… проєктів"
msgid "Not available for protected branches"
msgstr "ÐедоÑтупно Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñ‰ÐµÐ½Ð¸Ñ… гілок"
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr "Ðе конфіденційно"
@@ -23787,18 +24020,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr "КількіÑÑ‚ÑŒ Ñ€Ñдків коду (LOC) на коміт"
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr "КількіÑÑ‚ÑŒ змін (гілок чи тегів) у одному відправленні Ñка впливає на те будуть ÑтворюватиÑÑ Ñ–Ð½Ð´Ð¸Ð²Ñ–Ð´ÑƒÐ°Ð»ÑŒÐ½Ñ– події відправки чи одна групова. Групова Ð¿Ð¾Ð´Ñ–Ñ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²ÐºÐ¸ буде Ñтворена Ñкщо Ñ†Ñ ÐºÑ–Ð»ÑŒÐºÑ–ÑÑ‚ÑŒ перевищує вÑтановлене чиÑло."
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr "КількіÑÑ‚ÑŒ змін (гілок чи тегів) у одному відправленні Ñка впливає на те чи будуть викликані веб-хуки та ÑервіÑи. Вони не будуть викликатиÑÑ Ñкщо Ñ†Ñ ÐºÑ–Ð»ÑŒÐºÑ–ÑÑ‚ÑŒ перевищує вÑтановленне чиÑло."
-
msgid "Number of commits"
msgstr "КількіÑÑ‚ÑŒ комітів"
msgid "Number of commits per MR"
msgstr "КількіÑÑ‚ÑŒ комітів на запит на злиттÑ"
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr "КількіÑÑ‚ÑŒ подій"
@@ -23850,9 +24080,6 @@ msgstr "Спочатку Ñтарі"
msgid "OmniAuth"
msgstr "OmniAuth"
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -24054,6 +24281,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -24066,6 +24296,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -24078,6 +24314,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -24093,6 +24332,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -24170,7 +24412,7 @@ msgid "Only include features new to your current subscription tier."
msgstr ""
msgid "Only policy:"
-msgstr "Политика включеннÑ:"
+msgstr "Політика включеннÑ:"
msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr "Продовжуйте тільки Ñкщо ви довірÑєте %{idp_url} контроль над входом до вашого облікового запиÑу GitLab."
@@ -24208,15 +24450,15 @@ msgstr "Відкрити виділеннÑ"
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr "Випадаючий ÑпиÑок типу коментарів"
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr "Відкрити помилки"
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr "Відкрити файл Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду"
@@ -24265,9 +24507,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr "ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð¿ÐµÑ€ÐµÐ²Ð¸Ñ‰Ð¸Ð»Ð° ліміт очікуваннÑ. Перевірте журнал pod'а %{pod_name} Ð´Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆ детальної інформації."
-msgid "Operations"
-msgstr "Операції"
-
msgid "Operations Dashboard"
msgstr "Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñми"
@@ -24295,6 +24534,9 @@ msgstr "Ðеобов'Ñзково"
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "За необхідноÑÑ‚Ñ– ви можете %{link_to_customize} Ñк адреÑи електронної почти та імена кориÑтувачів FobBugz будуть імпортовані у GitLab."
@@ -24304,6 +24546,9 @@ msgstr "Параметри"
msgid "Or you can choose one of the suggested colors below"
msgstr "Ðбо ви можете вибрати один із запропонованих нижче кольорів"
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24373,6 +24618,36 @@ msgstr "ВлаÑник:"
msgid "Owner"
msgstr "ВлаÑник"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr "РеєÑÑ‚Ñ€ пакетів"
@@ -24448,9 +24723,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24631,14 +24903,18 @@ msgstr "Команда NNGet"
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24682,9 +24958,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24943,6 +25216,9 @@ msgstr "ШлÑÑ…:"
msgid "Paths can contain wildcards, like */welcome"
msgstr "ШлÑхи можуть міÑтити шаблони, наприклад */welcome"
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr "Призупинити"
@@ -24964,6 +25240,9 @@ msgstr "В очікуванні"
msgid "Pending comments"
msgstr "Коментарі в очікуванні"
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25286,19 +25565,19 @@ msgid "PipelineSchedules|Variables"
msgstr "Змінні"
msgid "PipelineSource|API"
-msgstr ""
+msgstr "API"
msgid "PipelineSource|Chat"
-msgstr ""
+msgstr "Чат"
msgid "PipelineSource|External"
-msgstr ""
+msgstr "Зовнішній"
msgid "PipelineSource|External Pull Request"
msgstr ""
msgid "PipelineSource|Merge Request"
-msgstr ""
+msgstr "Запит на злиттÑ"
msgid "PipelineSource|On-Demand DAST Scan"
msgstr ""
@@ -25307,25 +25586,25 @@ msgid "PipelineSource|On-Demand DAST Validation"
msgstr ""
msgid "PipelineSource|Parent Pipeline"
-msgstr ""
+msgstr "БатьківÑький конвеєр"
msgid "PipelineSource|Pipeline"
-msgstr ""
+msgstr "Конвеєр"
msgid "PipelineSource|Push"
msgstr ""
msgid "PipelineSource|Schedule"
-msgstr ""
+msgstr "Розклад"
msgid "PipelineSource|Trigger"
-msgstr ""
+msgstr "Тригер"
msgid "PipelineSource|Web"
-msgstr ""
+msgstr "Веб"
msgid "PipelineSource|Web IDE"
-msgstr ""
+msgstr "Веб-IDE"
msgid "PipelineStatusTooltip|Pipeline: %{ciStatus}"
msgstr "Конвеєр: %{ciStatus}"
@@ -25433,7 +25712,7 @@ msgid "Pipelines|More Information"
msgstr "Більше інформації"
msgid "Pipelines|No artifacts available"
-msgstr ""
+msgstr "Ðемає доÑтупних артефактів"
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25471,6 +25750,9 @@ msgstr "Ð’ даний Ñ‡Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” завершених конвеєрів.
msgid "Pipelines|There are currently no pipelines."
msgstr "Ð’ даний Ñ‡Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” конвеєрів."
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "Помилка при отриманні конвеєрів. Спробуйте знову через декілька хвилин, або звернітьÑÑ Ð´Ð¾ Ñлужби підтримки."
@@ -25591,6 +25873,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr "Конвеєр результату злиттÑ"
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr "Виконано"
@@ -25604,7 +25889,7 @@ msgid "Pipeline|Pipeline %{idStart}#%{idEnd} %{statusStart}%{statusEnd} for %{co
msgstr ""
msgid "Pipeline|Pipeline cannot be run."
-msgstr ""
+msgstr "Конвеєр не може бути запущений."
msgid "Pipeline|Pipelines"
msgstr "Конвеєр"
@@ -25628,7 +25913,7 @@ msgid "Pipeline|Source"
msgstr "Джерело"
msgid "Pipeline|Source|Security Policy"
-msgstr ""
+msgstr "Політика безпеки"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default."
msgstr ""
@@ -25679,7 +25964,7 @@ msgid "Pipeline|We are currently unable to fetch pipeline data"
msgstr ""
msgid "Pipeline|You’re about to stop pipeline #%{pipelineId}."
-msgstr ""
+msgstr "Зараз ви зупинете конвеєр #%{pipelineId}."
msgid "Pipeline|for"
msgstr "ДлÑ"
@@ -25708,6 +25993,9 @@ msgstr "ПроÑте порівнÑннÑ"
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr "План:"
@@ -25810,9 +26098,15 @@ msgstr "Будь лаÑка, введіть дійÑний номер"
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Введіть опиÑове ім'Ñ Ð³Ñ€ÑƒÐ¿Ð¸."
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25957,6 +26251,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -26030,7 +26327,7 @@ msgid "Preferences|Render whitespace characters in the Web IDE"
msgstr "Візуалізувати пробіли в веб-IDE"
msgid "Preferences|Show one file at a time on merge request's Changes tab"
-msgstr ""
+msgstr "Показати лише один файл на вкладці зміни запиту на злиттÑ"
msgid "Preferences|Show whitespace changes in diffs"
msgstr "Показувати зміни пробілів у відмінноÑÑ‚ÑÑ…"
@@ -26233,12 +26530,18 @@ msgstr "Профіль"
msgid "Profile Settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽ"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr "о"
@@ -26248,9 +26551,6 @@ msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити %{yourAcco
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr "Ви збираєтеÑÑ Ð·Ð¼Ñ–Ð½Ð¸Ñ‚Ð¸ ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача %{currentUsernameBold} на %{newUsernameBold}. Профіль та проєкти будуть перенаправлÑтиÑÑ Ð½Ð° проÑÑ‚Ñ–Ñ€ імен %{newUsername}, але таке Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡Ð¸Ñ‚ÑŒÑÑ, коли проÑÑ‚Ñ–Ñ€ імен %{currentUsername} буде зареєÑтровано на іншого кориÑтувача або групу. Будь лаÑка, оновіть віддалені адреÑи в репозиторіÑÑ… Git Ñкомога швидше."
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -26278,6 +26578,9 @@ msgstr "Додати Ñмайлик-ÑтатуÑ"
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr "Обрізка аватарів"
@@ -26569,6 +26872,9 @@ msgstr "Тут ви можете завантажити Ñвій аватар а
msgid "Profiles|You don't have access to delete this user."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” доÑтупу Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ кориÑтувача."
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26852,7 +27158,7 @@ msgid "ProjectSelect|Search projects"
msgstr ""
msgid "ProjectSelect|Select a project"
-msgstr ""
+msgstr "Виберіть проєкт"
msgid "ProjectSelect|There was an error fetching the projects. Please try again."
msgstr ""
@@ -26869,6 +27175,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26884,6 +27193,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26990,7 +27302,7 @@ msgid "ProjectSettings|Checkbox is visible and unselected by default."
msgstr ""
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
-msgstr ""
+msgstr "Виберіть метод злиттÑ, Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° пропозиції щодо злиттÑ."
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
msgstr ""
@@ -27005,7 +27317,7 @@ msgid "ProjectSettings|Container registry"
msgstr "РеєÑÑ‚Ñ€ контейнерів"
msgid "ProjectSettings|Customize this project's badges."
-msgstr ""
+msgstr "Ðалаштувати значки цього проєкту."
msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
msgstr ""
@@ -27056,7 +27368,7 @@ msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Flexible tool to collaboratively develop ideas and plan work in this project."
-msgstr ""
+msgstr "Гнучкий інÑтрумент Ð´Ð»Ñ Ñпільної розробки ідей та Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ в цьому проєкті."
msgid "ProjectSettings|Forks"
msgstr "Форки"
@@ -27067,6 +27379,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr "Глобальні"
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "Внутрішні"
@@ -27079,6 +27394,9 @@ msgstr "Задачі"
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -27256,6 +27574,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -27346,6 +27667,9 @@ msgstr "Spring"
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
@@ -27427,6 +27751,9 @@ msgstr "Ð¦Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±ÑƒÑ” підтримки localStorage вÐ
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr "ДозволÑÑ” негайно зклонувати репозиторій цього проєкту. ПропуÑÑ‚Ñ–Ñ‚ÑŒ, Ñкщо ви плануєте розміÑтити тут вже Ñ–Ñнуючий репозиторій."
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr "Підключіть Ñвій зовнішній репозиторій до GitLab CI/CD."
@@ -27454,6 +27781,9 @@ msgstr "Створити новий проєкт"
msgid "ProjectsNew|Description format"
msgstr "Формат опиÑу"
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr "Імпорт"
@@ -27469,6 +27799,9 @@ msgstr "Мігрувати Ñвої дані із зовнішнього джеÑ
msgid "ProjectsNew|No import options available"
msgstr "Варіанти імпорту не доÑтупні"
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "ÐžÐ¿Ð¸Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ %{tag_start}(необов’Ñзково)%{tag_end}"
@@ -27484,54 +27817,9 @@ msgstr "Хочете розміÑтити декілька залежних пр
msgid "Prometheus"
msgstr "Prometheus"
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr "%{count} попереджень заÑтоÑовано"
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr "Додати попередженнÑ"
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr "Редагувати попередженнÑ"
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr "Помилка ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ"
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr "Помилка Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ"
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr "Помилка Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ"
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr "Помилка Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ"
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr "Оператор"
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr "Вибрати запит"
-
-msgid "PrometheusAlerts|Threshold"
-msgstr "Поріг"
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27835,9 +28123,6 @@ msgstr "Захищені гілки"
msgid "Protected Environment"
msgstr "Захищене Ñередовище"
-msgid "Protected Paths"
-msgstr "Захищені шлÑхи"
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27853,6 +28138,9 @@ msgstr "Захищені гілки"
msgid "Protected environments"
msgstr "Захищені Ñередовища"
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27991,6 +28279,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr "ПоÑтачальник"
@@ -28003,6 +28294,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr "Збір даних Pseudonymizer"
@@ -28189,9 +28483,6 @@ msgstr "Запит"
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr "Запит є правильним"
-
msgid "Queued"
msgstr "У черзі"
@@ -28225,6 +28516,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -28312,15 +28606,15 @@ msgstr ""
msgid "Recent"
msgstr "ОÑтанні"
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ð½Ð° активніÑÑ‚ÑŒ"
msgid "Recent Searches Service is unavailable"
msgstr "Ð¡ÐµÑ€Ð²Ñ–Ñ Ð¾Ñтанніх пошуків недоÑтупний"
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28806,6 +29100,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr "Повторне відкриттÑ"
@@ -29146,6 +29443,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr "Вибрати"
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "Запит доÑтупу"
@@ -29155,9 +29455,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr "Параметр запиту %{param} відÑутній."
@@ -29236,19 +29533,19 @@ msgstr "Вимоги"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr "Вимоги можуть базуватиÑÑ Ð½Ð° кориÑтувачах, зацікавлених Ñторонах, ÑиÑтемах, програмному забезпеченні чи будь-Ñкому іншому, що ви вважаєте важливим."
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] "Ðеобхідно Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ %{names}."
-msgstr[1] "Ðеобхідно ще %{count} Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ %{names}."
-msgstr[2] "Ðеобхідно ще %{count} затверджень від %{names}."
-msgstr[3] "Ðеобхідно ще %{count} затверджень від %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
-msgstr[0] "Ðеобхідно затвердженнÑ."
-msgstr[1] "Ðеобхідно ще %d затвердженнÑ."
-msgstr[2] "Ðеобхідно ще %d затверджень."
-msgstr[3] "Ðеобхідно ще %d затверджень."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Requires values to meet regular expression requirements."
msgstr ""
@@ -29597,9 +29894,6 @@ msgstr "Runner'и"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr "ДоÑтупні Runner'и: %{active_runners_count}"
@@ -29624,6 +29918,15 @@ msgstr "Ðрхітектура"
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29633,6 +29936,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29684,6 +29990,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29705,6 +30014,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr "Захищені"
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr "ВерÑÑ–Ñ"
@@ -29744,6 +30071,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29807,6 +30137,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "Ви викориÑтали %{quotaUsed} із ваших %{quotaLimit} хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² загальних runner'ів."
@@ -29837,15 +30170,6 @@ msgstr "ВиконуєтьÑÑ"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "Виконує Ñ€Ñд задач по очищенню поточного репозиторію, таких Ñк ÑтиÑÐ½ÐµÐ½Ð½Ñ Ñ€ÐµÐ´Ð°ÐºÑ†Ñ–Ð¹ файлів та Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð½ÐµÐ´Ð¾ÑÑжних об'єктів."
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr "SAML"
@@ -29925,7 +30249,7 @@ msgid "SastEntryPoints|How do I set up SAST?"
msgstr ""
msgid "SastEntryPoints|Learn more"
-msgstr ""
+msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
msgid "Satisfied"
msgstr ""
@@ -29942,9 +30266,6 @@ msgstr ""
msgid "Save Changes"
msgstr "Зберегти зміни"
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr "Зберегти заÑтоÑунок"
@@ -30054,7 +30375,7 @@ msgid "Search"
msgstr "Пошук"
msgid "Search GitLab"
-msgstr ""
+msgstr "Пошук в GitLab"
msgid "Search Jira issues"
msgstr "Пошук задач Jira"
@@ -30066,7 +30387,7 @@ msgid "Search an environment spec"
msgstr "Пошук Ñпецифікації Ñередовища"
msgid "Search assignees"
-msgstr ""
+msgstr "Пошук виконавців"
msgid "Search authors"
msgstr "Пошук авторів"
@@ -30078,16 +30399,16 @@ msgid "Search branches and tags"
msgstr "Пошук гілок та тегів"
msgid "Search branches, tags, and commits"
-msgstr ""
+msgstr "Пошук гілок, тегів та комітів"
msgid "Search by Git revision"
msgstr "Пошук за верÑією Git"
msgid "Search by author"
-msgstr ""
+msgstr "Пошук за автором"
msgid "Search by commit title or SHA"
-msgstr ""
+msgstr "Шукати за назвою коміту або SHA"
msgid "Search by message"
msgstr "Шукати за повідомленнÑм"
@@ -30099,7 +30420,7 @@ msgid "Search files"
msgstr "Пошук файлів"
msgid "Search for Namespace"
-msgstr ""
+msgstr "Пошук проÑтору імен"
msgid "Search for a LDAP group"
msgstr "Пошук LDAP-групи"
@@ -30141,7 +30462,7 @@ msgid "Search or filter results…"
msgstr "Шукати чи фільтрувати результати…"
msgid "Search or jump to..."
-msgstr ""
+msgstr "Шукати чи перейти до..."
msgid "Search project"
msgstr "Пошук в проєкті"
@@ -30295,6 +30616,9 @@ msgstr[3] "результатів у вікі"
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30506,10 +30830,10 @@ msgid "SecurityOrchestration|Action"
msgstr ""
msgid "SecurityOrchestration|Actions"
-msgstr ""
+msgstr "Дії"
msgid "SecurityOrchestration|Add rule"
-msgstr ""
+msgstr "Додати правило"
msgid "SecurityOrchestration|All policies"
msgstr ""
@@ -30520,16 +30844,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30572,7 +30899,7 @@ msgid "SecurityOrchestration|Rule"
msgstr ""
msgid "SecurityOrchestration|Rules"
-msgstr ""
+msgstr "Правила"
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
@@ -30580,6 +30907,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30598,6 +30928,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30667,6 +31000,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr "Створити задачу"
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30688,9 +31024,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30724,6 +31057,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30733,6 +31075,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30763,6 +31108,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr "Проєкт"
@@ -30886,6 +31234,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30925,12 +31276,12 @@ msgstr "Вибрати Ñторінку"
msgid "Select a branch"
msgstr ""
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ виберіть його в лівій бічній панелі. Пізніше ви будете мати можливіÑÑ‚ÑŒ закомітити Ñвої зміни."
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
-msgstr ""
-
msgid "Select a group to invite"
msgstr "Виберіть групу Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ"
@@ -30938,7 +31289,7 @@ msgid "Select a label"
msgstr "Вибрати мітку"
msgid "Select a milestone"
-msgstr ""
+msgstr "Вибрати етап"
msgid "Select a new namespace"
msgstr "Вибрати новий проÑÑ‚Ñ–Ñ€ імен"
@@ -30946,15 +31297,9 @@ msgstr "Вибрати новий проÑÑ‚Ñ–Ñ€ імен"
msgid "Select a project"
msgstr "Вибрати проєкт"
-msgid "Select a project to read Insights configuration file"
-msgstr "Вибрати проєкт, щоб прочитати файл конфігурації ÑтатиÑтики (Insights)"
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr "Виберіть репозиторій"
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -31213,9 +31558,6 @@ msgstr "ВерÑÑ–Ñ Ñервера"
msgid "Serverless"
msgstr "Serverless"
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -31315,9 +31657,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -31372,9 +31711,6 @@ msgstr "Ð’Ñтановіть пароль Ð´Ð»Ñ Ñвого облікового
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31465,9 +31801,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31501,12 +31834,12 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "вÑтановити пароль"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr "Додати Ñмайлик-ÑтатуÑ"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "SetStatusModal|Busy"
msgstr "ЗайнÑтий"
@@ -31570,6 +31903,13 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31917,9 +32257,6 @@ msgstr "Подібні задачі"
msgid "Simulate a pipeline created for the default branch"
msgstr "Імітуйте конвеєр Ñтворений Ð´Ð»Ñ Ð³Ñ–Ð»ÐºÐ¸ за замовчуваннÑм"
-msgid "Single or combined queries"
-msgstr "Одиночні або комбіновані запити"
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31986,6 +32323,9 @@ msgstr "Смарт-карта"
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "Ðе вдалоÑÑ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸ Ñмарт-карту: відÑутній заголовок в Ñертифікаті клієнта."
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "Сніпети"
@@ -32010,6 +32350,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "Ðемає Ñніпетів Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ."
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -32019,6 +32362,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr "Файли"
@@ -32043,9 +32389,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr "ХтоÑÑŒ редагував цю задачу в одночаÑно із вами. Будь лаÑка, ознайомтеÑÑ Ñ–Ð· %{linkStart}нею%{linkEnd} Ñ– переконайтеÑÑ, ваші зміни не затруть зміни інших."
@@ -32640,12 +32983,6 @@ msgstr "Розпочати пошук"
msgid "Start thread"
msgstr "Розпочати обговореннÑ"
-msgid "Start thread & close %{noteable_name}"
-msgstr "Розпочати Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° закрити %{noteable_name}"
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr "Розпочати Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° повторно відкрити %{noteable_name}"
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32685,6 +33022,9 @@ msgstr ""
msgid "State your message to activate"
msgstr "Залиште Ñвоє Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ—"
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -33183,7 +33523,7 @@ msgstr "УÑпішно розблоковано"
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -33282,18 +33622,12 @@ msgstr ""
msgid "Sunday"
msgstr "ÐеділÑ"
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -33315,9 +33649,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -33330,12 +33661,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -33351,30 +33676,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33402,9 +33712,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33417,9 +33724,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33462,6 +33766,9 @@ msgstr "URL-адреÑа Ñторінки підтримки"
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33648,6 +33955,9 @@ msgstr "Теги дають можливіÑÑ‚ÑŒ позначати певні Ð
msgid "TagsPage|This tag has no release notes."
msgstr "Цей тег не міÑтить опиÑу релізу."
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "ВикориÑтовуйте команду git tag, щоб додати новий тег:"
@@ -33672,6 +33982,15 @@ msgstr "Цільова гілка"
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "Команда"
@@ -33684,6 +34003,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -34067,6 +34389,9 @@ msgstr[3] "%{type} міÑтить наÑтупні помилки:"
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -34136,6 +34461,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Ð—â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ припинено піÑÐ»Ñ %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð², Ñким потрібно більше чаÑу, викориÑтовуйте комбінацію clone/push."
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr "ВміÑÑ‚ цієї Ñторінки не закодований в UTF-8. Зміни можна вноÑити лише через репозиторій Git."
@@ -34166,9 +34494,6 @@ msgstr "СпиÑок залежноÑтей міÑтить детальну ін
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "Ð Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð½Ð° %{environmentLink} не уÑпішне."
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr "Каталог уÑпішно Ñтворено."
@@ -34239,6 +34564,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr "Глобальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼Ð°Ð³Ð°ÑŽÑ‚ÑŒ, щоб ви увімкнули двофакторну автентифікацію Ð´Ð»Ñ Ñвого облікового запиÑу."
@@ -34323,6 +34651,9 @@ msgstr "Ліцензію уÑпішно завантажено Ñ– вона акÑ
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr "МакÑимальний розмір файлу — %{size}."
@@ -34428,9 +34759,6 @@ msgstr "УÑпішно Ñтворено форк проєкту."
msgid "The project was successfully imported."
msgstr "Проект уÑпішно імпортовано."
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "Збір даних пÑевдонімізованих данних вимкнено. Коли його буде увімкнено GitLab запуÑтить фонове завданнÑ, Ñке буде Ñтворювати пÑевдонімізовані CSV-файли бази даних GitLab, Ñкі будуть надÑилатиÑÑ Ð´Ð¾ вашого налаштованого Ñховища об'єктів."
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34464,9 +34792,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr "Запланований Ñ‡Ð°Ñ Ð¼Ð°Ñ” бути в майбутньому!"
-
msgid "The snippet can be accessed without any authentication."
msgstr "ДоÑтуп до Ñніпета можливий без будь-Ñкої автентифікації."
@@ -34626,6 +34951,9 @@ msgstr "Ðаразі пакети відÑутні"
msgid "There are no projects shared with this group yet"
msgstr "Ще немає Ñпільних проєктів з цією групою"
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34710,6 +35038,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34896,9 +35227,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr "Ці Ñ–Ñнуючі проблеми мають подібні заголовки. Можливо, краще додати коментар до однієї з них заміÑÑ‚ÑŒ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ñ—."
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -35121,7 +35449,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35424,6 +35752,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr "Цю змінну не можна замаÑкувати."
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr "Це перенаправить Ð²Ð°Ñ Ð½Ð° зовнішню Ñторінку входу."
@@ -35562,6 +35896,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35897,7 +36234,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35933,7 +36270,7 @@ msgstr "Ð”Ð»Ñ Ñ€Ð¾Ð·Ð²Ð¸Ñ‚ÐºÑƒ цього проєкту Ñтворіть ноÐ
msgid "To keep this project going, create a new merge request"
msgstr "Ð”Ð»Ñ Ñ€Ð¾Ð·Ð²Ð¸Ñ‚ÐºÑƒ цього проєкту Ñтворіть новий запит на злиттÑ"
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -36119,6 +36456,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr "Теми (додатково)"
@@ -36212,8 +36564,8 @@ msgstr "Група вже є кореневою."
msgid "TransferGroup|Group is already associated to the parent group."
msgstr "Група вже пов'Ñзана із батьківÑькою групою."
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
-msgstr "Ð¦Ñ Ð±Ð°Ñ‚ÑŒÐºÑ–Ð²Ñька група уже міÑтить підгрупу з тим же шлÑхом."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
+msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
msgstr "ПеренеÑÐµÐ½Ð½Ñ Ð½ÐµÐ²Ð´Ð°Ð»Ðµ: %{error_message}"
@@ -36582,6 +36934,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ вразливі проєкти"
@@ -36666,6 +37021,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr "СкаÑувати"
@@ -36856,7 +37214,7 @@ msgid "Update iteration"
msgstr "Оновити ітерацію"
msgid "Update milestone"
-msgstr ""
+msgstr "Оновити етап"
msgid "Update now"
msgstr "Оновити зараз"
@@ -36999,6 +37357,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr "Купити додаткові хвилини"
@@ -37017,10 +37378,10 @@ msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð·Ð° поточний період"
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -37032,6 +37393,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr "Сховище LFS"
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -37077,9 +37441,6 @@ msgstr "Сховище"
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -37119,12 +37480,12 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr "ВикориÑтаннÑ"
-msgid "UsageQuota|Usage Breakdown"
-msgstr ""
-
msgid "UsageQuota|Usage Quotas"
msgstr "Квоти на викориÑтаннÑ"
+msgid "UsageQuota|Usage breakdown"
+msgstr ""
+
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¾Ð²Ð¸Ñ… реÑурÑів у проєктах групи %{strong_start}%{group_name}%{strong_end}"
@@ -37207,10 +37568,10 @@ msgid "UsageTrends|Pipelines failed"
msgstr ""
msgid "UsageTrends|Pipelines skipped"
-msgstr ""
+msgstr "Конвеєри пропущені"
msgid "UsageTrends|Pipelines succeeded"
-msgstr ""
+msgstr "Конвеєри уÑпішні"
msgid "UsageTrends|Pipelines total"
msgstr "Ð’Ñього конвеєрів"
@@ -37272,6 +37633,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -37302,6 +37666,9 @@ msgstr ""
msgid "Use template"
msgstr "ВикориÑтовувати шаблон"
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -37368,6 +37735,12 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37423,7 +37796,7 @@ msgid "User-based escalation rules must have a user with access to the project"
msgstr ""
msgid "UserAvailability|%{author} %{spanStart}(Busy)%{spanEnd}"
-msgstr ""
+msgstr "%{author} %{spanStart}(ЗайнÑтий)%{spanEnd}"
msgid "UserAvailability|%{author} (Busy)"
msgstr "%{author} (ЗайнÑтий)"
@@ -37719,6 +38092,9 @@ msgstr "ВикориÑтовуєтьÑÑ Ð¾Ð±Ð¾Ð²â€™Ñзкова ÑтратегÑ
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr "Перевірити"
@@ -37728,6 +38104,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr "Перевірити ваш файл конфігурації Gitlab CI"
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr "Перевірки не пройшли уÑпішно."
@@ -37773,10 +38158,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38442,6 +38839,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38637,6 +39037,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr "Що нового"
@@ -38646,9 +39049,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Коли runner закріплений (за проєктами), його не можна викориÑтовувати в інших проєктах"
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38661,6 +39061,9 @@ msgstr "Якщо залишити URL порожнім, можна вÑтаноÐ
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "Коли цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¸Ð¹Ð½Ñто"
@@ -38671,9 +39074,6 @@ msgstr[3] "Коли ці запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¸Ð¹Ð½Ñто"
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr "Коли:"
@@ -38980,12 +39380,12 @@ msgstr "ÐапиÑати коментар…"
msgid "Write a description or drag your files here…"
msgstr ""
+msgid "Write a description…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Створити Ð¾Ð¿Ð¸Ñ ÐµÑ‚Ð°Ð¿Ñƒ..."
-msgid "Write to \"authorized_keys\" file"
-msgstr ""
-
msgid "Write your release notes or drag your files here…"
msgstr "Створіть Ð¾Ð¿Ð¸Ñ Ñ€ÐµÐ»Ñ–Ð·Ñƒ або перетÑгніть файли Ñюди…"
@@ -39025,9 +39425,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr "Ви збираєтеÑÑŒ оÑтаточно видалити цей проєкт"
@@ -39094,6 +39491,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” повноважень на Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¾Ñ— дії"
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39250,9 +39650,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "Ви можете розв’Ñзати цей конфлікт Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð° допомогою інтерактивного режиму (викориÑтовуючи кнопки %{use_ours} та %{use_theirs}), або безпоÑередньо редагуючи файли. Закомітити зміни у %{branch_name}"
@@ -39352,9 +39749,6 @@ msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” жодних доÑтупних проєктів."
msgid "You don't have any recent searches"
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” недавніх пошуків"
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ´Ð¾Ñтатньо прав, щоб виконати цю дію."
@@ -39442,6 +39836,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr "Ви уÑпішно придбали підпиÑку на план %{plan} на %{seats}. Ви отримаєте чек електронною поштою."
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr "Ви залишили \"%{membershipable_human_name}\" %{source_type}."
@@ -39451,9 +39848,6 @@ msgstr "Зараз ви можете закрити цей етап."
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39908,28 +40302,55 @@ msgstr[3] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao API token"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39941,6 +40362,9 @@ msgstr "Zoom-зуÑтріч видалено"
msgid "[No reason]"
msgstr "[Без причини]"
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr "[Redacted]"
@@ -39953,9 +40377,6 @@ msgstr ""
msgid "a deleted user"
msgstr "видалений кориÑтувач"
-msgid "a design"
-msgstr "дизайн"
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] "близько 1 години"
@@ -40066,12 +40487,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -40099,6 +40526,9 @@ msgstr ""
msgid "cannot be modified"
msgstr "не може бути змінено"
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr "не може блокувати інших"
@@ -40114,9 +40544,6 @@ msgstr "не може блокувати Ñам Ñебе"
msgid "cannot merge"
msgstr "не може виконувати злиттÑ"
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40147,6 +40574,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr "%{linkStartTag}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про звіти про ÑкіÑÑ‚ÑŒ коду %{linkEndTag}"
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "%{remainingPackagesCount} більше"
@@ -40183,9 +40613,22 @@ msgstr "Ðвтоматично заÑтоÑувати патч у новій гÑ
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -40195,8 +40638,14 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
-msgstr "ЯкіÑÑ‚ÑŒ коду"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
msgid "ciReport|Container Scanning"
msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ð°"
@@ -40261,6 +40710,19 @@ msgstr "Знайдено %{issuesWithCount}"
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "ДоÑлідити цю вразливіÑÑ‚ÑŒ, Ñтворивши задачу"
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -40294,10 +40756,10 @@ msgstr "SAST"
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -40418,6 +40880,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr "container_name не може бути довше %{max_length} Ñимволів"
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40476,9 +40944,6 @@ msgstr "розгортаннÑ"
msgid "design"
msgstr "дизайн"
-msgid "designs"
-msgstr "дизайни"
-
msgid "detached"
msgstr "відділена"
@@ -40491,6 +40956,12 @@ msgstr "не Ñ–Ñнує"
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr "не підтримує розширеннÑ. ПідтримуютьÑÑ Ð»Ð¸ÑˆÐµ %{extension_list}"
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr "завантажити це"
@@ -40507,6 +40978,9 @@ msgstr "напр. %{token}"
msgid "element is not a hierarchy"
msgstr "елемент відÑутній в ієрархії"
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40543,6 +41017,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40678,7 +41155,7 @@ msgid "in all GitLab"
msgstr ""
msgid "in group"
-msgstr ""
+msgstr "в групі"
msgid "in group %{link_to_group}"
msgstr "в групі %{link_to_group}"
@@ -40747,6 +41224,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40907,6 +41390,9 @@ msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ %{metricsLinkStart} пам’ÑÑ‚Ñ– %{metricsLi
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40926,7 +41412,7 @@ msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Помилка при обробці вашого затвердженнÑ."
msgid "mrWidget|Approval is optional"
-msgstr ""
+msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½ÐµÐ¾Ð±Ð¾Ð²â€™Ñзкове"
msgid "mrWidget|Approval password is invalid."
msgstr "Пароль Ð´Ð»Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ” недійÑним."
@@ -40940,11 +41426,17 @@ msgstr "Затвердити додатково"
msgid "mrWidget|Approved by"
msgstr "Затверджено"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
msgid "mrWidget|Cancel auto-merge"
-msgstr ""
+msgstr "СкаÑувати автоматичне злиттÑ"
msgid "mrWidget|Check out branch"
msgstr "Перейти в гілку"
@@ -41004,6 +41496,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÑтатиÑтики розгортаннÑ"
@@ -41038,9 +41533,6 @@ msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¾Ð¹ÑˆÐ»Ð¾ невдало."
msgid "mrWidget|Merge locally"
msgstr "Злити локально"
-msgid "mrWidget|Merge request approved."
-msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð¾."
-
msgid "mrWidget|Merged by"
msgstr "Злито"
@@ -41114,7 +41606,7 @@ msgid "mrWidget|Set by %{merge_author} to be added to the merge train when the p
msgstr ""
msgid "mrWidget|Set by %{merge_author} to be merged automatically when the pipeline succeeds"
-msgstr ""
+msgstr "Ðвтоматичне Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ–Ð´ %{merge_author} буде злито, коли конвеєр пройде уÑпішно"
msgid "mrWidget|Set by %{merge_author} to start a merge train when the pipeline succeeds"
msgstr ""
@@ -41155,12 +41647,6 @@ msgstr "Гілку-джерело не буде видалено"
msgid "mrWidget|There are merge conflicts"
msgstr "Ñ–Ñнують конфлікти при злитті"
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "ВідбулаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при автоматичному злитті цього запиту"
@@ -41176,6 +41662,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -41224,6 +41713,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -41299,6 +41794,9 @@ msgstr "або"
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "із %d теÑту"
@@ -41335,7 +41833,7 @@ msgid "pipeline"
msgstr "конвеєр"
msgid "pipeline schedules documentation"
-msgstr ""
+msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ñ€Ð¾Ð·ÐºÐ»Ð°Ð´Ñ–Ð² Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41735,8 +42233,8 @@ msgid "your settings"
msgstr "ваші налаштуваннÑ"
msgid "{group}"
-msgstr ""
+msgstr "{group}"
msgid "{project}"
-msgstr ""
+msgstr "{project}"
diff --git a/locale/unfound_translations.rb b/locale/unfound_translations.rb
index 3923c62466a..ace9149599c 100644
--- a/locale/unfound_translations.rb
+++ b/locale/unfound_translations.rb
@@ -1,3 +1,4 @@
+# rubocop:disable Naming/FileName
# frozen_string_literal: true
# Dynamic translations which needs to be marked by `N_` so they can be found by `rake gettext:find`, see:
@@ -22,3 +23,5 @@ N_('NotificationEvent|Failed pipeline')
N_('NotificationEvent|Fixed pipeline')
N_('NotificationEvent|Moved project')
N_('NotificationEvent|Merge when pipeline succeeds')
+
+# rubocop:enable Naming/FileName
diff --git a/locale/ur_PK/gitlab.po b/locale/ur_PK/gitlab.po
index 9973e95818b..5949f4d3c63 100644
--- a/locale/ur_PK/gitlab.po
+++ b/locale/ur_PK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ur-PK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:18\n"
+"PO-Revision-Date: 2021-11-02 00:39\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/uz_UZ/gitlab.po b/locale/uz_UZ/gitlab.po
index 8691840795f..f1480ed6118 100644
--- a/locale/uz_UZ/gitlab.po
+++ b/locale/uz_UZ/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: uz\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
-
msgid " or "
msgstr ""
@@ -86,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -194,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -1055,6 +1042,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1138,9 +1128,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1193,6 +1189,9 @@ msgstr[1] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1439,9 +1438,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1475,7 +1471,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1502,6 +1498,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1850,6 +1849,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1931,9 +1933,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -2012,9 +2011,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -2108,6 +2104,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2564,7 +2563,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2579,6 +2578,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2714,7 +2719,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3329,7 +3334,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3347,6 +3352,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3362,7 +3370,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3602,13 +3610,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3812,6 +3823,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3875,9 +3891,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4210,12 +4223,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4228,12 +4247,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4246,6 +4274,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4261,6 +4298,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4270,6 +4310,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4542,12 +4585,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4783,6 +4820,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5415,6 +5455,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5656,7 +5699,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5767,6 +5810,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5974,9 +6020,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6261,9 +6304,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6321,6 +6361,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6649,6 +6695,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6682,6 +6731,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6796,6 +6848,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6838,15 +6893,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7489,7 +7538,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7930,6 +7979,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7939,6 +7991,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7948,9 +8003,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7963,6 +8033,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -8113,30 +8186,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8275,12 +8324,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8397,6 +8440,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8478,13 +8524,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8493,16 +8539,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8511,6 +8563,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8523,31 +8581,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8619,15 +8677,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8772,6 +8824,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8896,10 +8951,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -9096,7 +9151,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -9120,9 +9175,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9243,9 +9295,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9315,9 +9364,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9402,9 +9448,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9510,6 +9553,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9528,6 +9574,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9540,9 +9589,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9558,6 +9604,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9693,6 +9742,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9810,7 +9862,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9933,10 +9985,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9993,6 +10042,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -10047,6 +10099,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10206,6 +10267,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10273,6 +10337,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10767,6 +10834,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10833,6 +10903,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10872,16 +10945,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10956,9 +11047,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10986,9 +11074,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -11016,6 +11101,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11178,13 +11266,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11193,7 +11281,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11511,7 +11611,9 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
+msgstr[1] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11615,6 +11717,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11630,15 +11738,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11690,6 +11795,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11768,6 +11876,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11813,6 +11924,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11999,12 +12113,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -12097,18 +12205,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -12139,9 +12235,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12367,6 +12460,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12691,10 +12787,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12820,7 +12913,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12875,7 +12971,9 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
+msgstr[1] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12976,7 +13074,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13276,6 +13374,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13453,6 +13554,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13749,9 +13853,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13833,6 +13934,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13848,6 +13952,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13875,9 +13982,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13890,6 +13994,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13974,6 +14084,11 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14208,9 +14323,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14402,6 +14514,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14653,6 +14768,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14884,6 +15002,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14944,6 +15065,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15520,6 +15644,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15559,6 +15686,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15574,9 +15704,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15646,10 +15773,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15697,6 +15824,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -16006,6 +16136,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16174,12 +16307,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16408,7 +16535,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16471,9 +16598,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16576,7 +16709,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16705,6 +16838,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16789,7 +16925,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16850,9 +16986,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16874,6 +17007,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16898,6 +17034,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16910,6 +17049,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17480,6 +17622,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17540,6 +17685,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17594,6 +17742,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17612,6 +17763,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -18125,6 +18285,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18226,6 +18389,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18265,6 +18431,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18448,6 +18617,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18523,9 +18695,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18625,6 +18794,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18643,6 +18818,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18658,6 +18836,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18691,6 +18872,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19216,6 +19400,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19309,19 +19496,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19663,6 +19850,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19917,12 +20110,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -20091,6 +20290,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20714,6 +20916,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20843,6 +21048,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20930,9 +21138,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -21056,6 +21261,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -21065,6 +21273,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21326,6 +21537,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21371,6 +21585,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21443,6 +21660,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21599,34 +21825,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21653,6 +21873,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21745,9 +21971,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21883,9 +22106,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22332,6 +22552,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22448,6 +22671,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22514,9 +22740,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22825,6 +23048,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22939,7 +23165,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22954,6 +23180,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -23149,6 +23378,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23205,9 +23437,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23441,18 +23670,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23504,9 +23730,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23708,6 +23931,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23720,6 +23946,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23732,6 +23964,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23747,6 +23982,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23860,15 +24098,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23917,9 +24155,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23947,6 +24182,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23956,6 +24194,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -24025,6 +24266,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -24100,9 +24371,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24283,14 +24551,16 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
+msgstr[1] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24334,9 +24604,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24595,6 +24862,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24616,6 +24886,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -25123,6 +25396,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25243,6 +25519,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25360,6 +25639,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25462,9 +25744,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25609,6 +25897,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25885,12 +26176,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25900,9 +26197,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25930,6 +26224,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26221,6 +26518,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26521,6 +26821,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26536,6 +26839,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26719,6 +27025,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26731,6 +27040,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26908,6 +27220,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26998,6 +27313,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -27079,6 +27397,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -27106,6 +27427,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -27121,6 +27445,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -27136,54 +27463,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27487,9 +27769,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27505,6 +27784,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27643,6 +27925,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27655,6 +27940,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27841,9 +28129,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27877,6 +28162,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27964,15 +28252,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28454,6 +28742,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28786,6 +29077,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28795,9 +29089,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28876,13 +29167,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
msgstr[1] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgstr[1] ""
@@ -29229,9 +29520,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29256,6 +29544,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29265,6 +29562,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29316,6 +29616,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29337,6 +29640,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29376,6 +29697,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29439,6 +29763,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29469,15 +29796,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29574,9 +29892,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29905,6 +30220,9 @@ msgstr[1] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30130,16 +30448,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -30190,6 +30511,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30208,6 +30532,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30277,6 +30604,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30298,9 +30628,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30334,6 +30661,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30343,6 +30679,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30373,6 +30712,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30496,6 +30838,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30535,10 +30880,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30556,15 +30901,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30823,9 +31162,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30925,9 +31261,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30982,9 +31315,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -31075,9 +31405,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -31111,10 +31438,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -31180,6 +31507,11 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31523,9 +31855,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31592,6 +31921,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31616,6 +31948,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31625,6 +31960,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31649,9 +31987,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32246,12 +32581,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32291,6 +32620,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32789,7 +33121,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32888,18 +33220,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32921,9 +33247,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32936,12 +33259,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32957,30 +33274,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -33008,9 +33310,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -33023,9 +33322,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -33068,6 +33364,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33254,6 +33553,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33278,6 +33580,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33290,6 +33601,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33663,6 +33977,9 @@ msgstr[1] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33732,6 +34049,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33762,9 +34082,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33833,6 +34150,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33917,6 +34237,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -34022,9 +34345,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -34058,9 +34378,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34220,6 +34537,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34304,6 +34624,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34490,9 +34813,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34715,7 +35035,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -35018,6 +35338,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -35156,6 +35482,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35487,7 +35816,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35523,7 +35852,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35709,6 +36038,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35802,7 +36146,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -36170,6 +36514,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36254,6 +36601,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36587,6 +36937,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36605,10 +36958,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36620,6 +36973,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36665,9 +37021,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36707,10 +37060,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36860,6 +37213,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36890,6 +37246,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36956,6 +37315,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37307,6 +37672,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37316,6 +37684,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37361,10 +37738,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -38024,6 +38413,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38219,6 +38611,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38228,9 +38623,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38243,6 +38635,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38251,9 +38646,6 @@ msgstr[1] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38560,10 +38952,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38605,9 +38997,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38674,6 +39063,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38830,9 +39222,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38932,9 +39321,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -39022,6 +39408,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39031,9 +39420,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39486,28 +39872,55 @@ msgstr[1] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao Product ID"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39519,6 +39932,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39531,9 +39947,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39640,12 +40053,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39673,6 +40092,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39688,9 +40110,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39721,6 +40140,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39757,9 +40179,20 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39769,7 +40202,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39835,6 +40274,17 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39868,10 +40318,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39990,6 +40440,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -40046,9 +40502,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -40061,6 +40514,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -40075,6 +40534,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40111,6 +40573,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40309,6 +40774,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40467,6 +40938,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40500,6 +40974,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40562,6 +41042,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40594,9 +41077,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40711,12 +41191,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40732,6 +41206,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40780,6 +41257,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40855,6 +41338,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/vi_VN/gitlab.po b/locale/vi_VN/gitlab.po
index 52ecf819c77..0c6c7c722eb 100644
--- a/locale/vi_VN/gitlab.po
+++ b/locale/vi_VN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: vi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:18\n"
+"PO-Revision-Date: 2021-11-02 00:38\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,23 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
-msgid " and"
-msgstr ""
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] ""
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] ""
-
msgid " or "
msgstr ""
@@ -84,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -171,9 +163,6 @@ msgid "%d commit,"
msgid_plural "%d commits,"
msgstr[0] ""
-msgid "%d commits"
-msgstr ""
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -969,6 +958,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1051,9 +1043,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1104,6 +1102,9 @@ msgstr[0] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1326,9 +1327,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1362,7 +1360,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1389,6 +1387,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1737,6 +1738,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1818,9 +1822,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -1899,9 +1900,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -1995,6 +1993,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2451,7 +2452,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr ""
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2466,6 +2467,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2601,7 +2608,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3216,7 +3223,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3234,6 +3241,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3249,7 +3259,7 @@ msgstr ""
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3489,13 +3499,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3699,6 +3712,10 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -3762,9 +3779,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4090,12 +4104,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4108,12 +4128,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4126,6 +4155,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4141,6 +4179,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4150,6 +4191,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4421,12 +4465,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4660,6 +4698,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5291,6 +5332,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5530,7 +5574,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5641,6 +5685,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5848,9 +5895,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6134,9 +6178,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6194,6 +6235,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6520,6 +6567,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6553,6 +6603,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6667,6 +6720,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6709,15 +6765,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7360,7 +7410,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7801,6 +7851,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7810,6 +7863,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7819,9 +7875,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7834,6 +7905,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -7984,30 +8058,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8146,12 +8196,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8267,6 +8311,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8348,13 +8395,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8363,16 +8410,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8381,6 +8434,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8393,31 +8452,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8489,15 +8548,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8642,6 +8695,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8764,10 +8820,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -8963,7 +9019,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -8987,9 +9043,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9110,9 +9163,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9182,9 +9232,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9269,9 +9316,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9377,6 +9421,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9395,6 +9442,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9407,9 +9457,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9425,6 +9472,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9560,6 +9610,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9677,7 +9730,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9800,10 +9853,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9860,6 +9910,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -9914,6 +9967,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10073,6 +10135,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10138,6 +10203,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10631,6 +10699,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10697,6 +10768,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10736,16 +10810,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Protected against pushes"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10820,9 +10912,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10850,9 +10939,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -10880,6 +10966,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11039,13 +11128,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11054,7 +11143,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11368,7 +11469,8 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11472,6 +11574,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11487,15 +11595,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11547,6 +11652,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11625,6 +11733,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11670,6 +11781,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11853,12 +11967,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -11950,18 +12058,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -11992,9 +12088,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12220,6 +12313,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12544,10 +12640,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12673,7 +12766,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12728,7 +12824,8 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12829,7 +12926,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13129,6 +13226,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13306,6 +13406,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13601,9 +13704,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13685,6 +13785,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13700,6 +13803,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13727,9 +13833,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13742,6 +13845,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13826,6 +13935,10 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14060,9 +14173,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14253,6 +14363,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14503,6 +14616,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14734,6 +14850,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14794,6 +14913,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15370,6 +15492,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15409,6 +15534,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15424,9 +15552,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15496,10 +15621,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15547,6 +15672,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -15856,6 +15984,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16024,12 +16155,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16258,7 +16383,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16321,9 +16446,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16426,7 +16557,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16555,6 +16686,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16639,7 +16773,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16698,9 +16832,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16722,6 +16853,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16746,6 +16880,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16758,6 +16895,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17325,6 +17465,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17385,6 +17528,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17439,6 +17585,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17457,6 +17606,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -17970,6 +18128,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18070,6 +18231,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18109,6 +18273,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18292,6 +18459,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18367,9 +18537,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18469,6 +18636,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18487,6 +18660,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18502,6 +18678,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18535,6 +18714,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19060,6 +19242,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19153,19 +19338,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19507,6 +19692,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19760,12 +19951,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -19934,6 +20131,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20550,6 +20750,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20679,6 +20882,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20766,9 +20972,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -20892,6 +21095,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -20901,6 +21107,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21162,6 +21371,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21207,6 +21419,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21279,6 +21494,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21435,34 +21659,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21489,6 +21707,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21580,9 +21804,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21718,9 +21939,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22166,6 +22384,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22281,6 +22502,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22347,9 +22571,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22657,6 +22878,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22771,7 +22995,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22786,6 +23010,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -22981,6 +23208,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23036,9 +23266,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23268,18 +23495,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23331,9 +23555,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23535,6 +23756,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23547,6 +23771,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23559,6 +23789,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23574,6 +23807,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23686,15 +23922,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23743,9 +23979,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23773,6 +24006,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23782,6 +24018,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -23851,6 +24090,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -23926,9 +24195,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24109,14 +24375,15 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24160,9 +24427,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24421,6 +24685,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24442,6 +24709,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -24949,6 +25219,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25069,6 +25342,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25186,6 +25462,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25288,9 +25567,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25435,6 +25720,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25711,12 +25999,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25726,9 +26020,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25756,6 +26047,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26047,6 +26341,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26347,6 +26644,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26362,6 +26662,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26545,6 +26848,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26557,6 +26863,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26734,6 +27043,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26824,6 +27136,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -26905,6 +27220,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26932,6 +27250,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -26947,6 +27268,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -26962,54 +27286,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27313,9 +27592,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27331,6 +27607,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27469,6 +27748,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27481,6 +27763,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27667,9 +27952,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27703,6 +27985,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27790,15 +28075,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28278,6 +28563,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28606,6 +28894,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28615,9 +28906,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28696,12 +28984,12 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgid "Requires values to meet regular expression requirements."
@@ -29045,9 +29333,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29072,6 +29357,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29081,6 +29375,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29132,6 +29429,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29153,6 +29453,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29192,6 +29510,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29255,6 +29576,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29285,15 +29609,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29390,9 +29705,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29710,6 +30022,9 @@ msgstr[0] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -29935,16 +30250,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -29995,6 +30313,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30013,6 +30334,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30082,6 +30406,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30103,9 +30430,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30139,6 +30463,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30148,6 +30481,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30178,6 +30514,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30301,6 +30640,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30340,10 +30682,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30361,15 +30703,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30628,9 +30964,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30730,9 +31063,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30787,9 +31117,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -30880,9 +31207,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -30916,10 +31240,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -30985,6 +31309,10 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31326,9 +31654,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31395,6 +31720,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31419,6 +31747,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31428,6 +31759,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31452,9 +31786,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32049,12 +32380,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32094,6 +32419,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32592,7 +32920,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32691,18 +33019,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32724,9 +33046,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32739,12 +33058,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32760,30 +33073,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -32811,9 +33109,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -32826,9 +33121,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -32871,6 +33163,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33057,6 +33352,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33081,6 +33379,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr ""
@@ -33093,6 +33400,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33461,6 +33771,9 @@ msgstr[0] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33530,6 +33843,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33560,9 +33876,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33630,6 +33943,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33714,6 +34030,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -33819,9 +34138,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -33855,9 +34171,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34017,6 +34330,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34101,6 +34417,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34287,9 +34606,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34512,7 +34828,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -34815,6 +35131,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -34953,6 +35275,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35282,7 +35607,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35318,7 +35643,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35504,6 +35829,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35597,7 +35937,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -35964,6 +36304,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36048,6 +36391,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36381,6 +36727,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36399,10 +36748,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36414,6 +36763,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36459,9 +36811,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36501,10 +36850,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36654,6 +37003,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36684,6 +37036,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36750,6 +37105,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37101,6 +37462,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37110,6 +37474,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37155,10 +37528,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -37815,6 +38200,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38010,6 +38398,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38019,9 +38410,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38034,6 +38422,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38041,9 +38432,6 @@ msgstr[0] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38350,10 +38738,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38395,9 +38783,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38464,6 +38849,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38620,9 +39008,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38722,9 +39107,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -38812,6 +39194,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -38821,9 +39206,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39275,28 +39657,55 @@ msgstr[0] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39308,6 +39717,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39320,9 +39732,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39427,12 +39836,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39460,6 +39875,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39475,9 +39893,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39508,6 +39923,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39544,9 +39962,19 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39556,7 +39984,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39622,6 +40056,16 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39655,10 +40099,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39776,6 +40220,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -39831,9 +40281,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -39846,6 +40293,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -39859,6 +40312,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -39895,6 +40351,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40090,6 +40549,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40247,6 +40712,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40280,6 +40748,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40341,6 +40815,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40372,9 +40849,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40489,12 +40963,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40510,6 +40978,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40558,6 +41029,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40633,6 +41110,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index 7bdd455e3a1..7e97d937ced 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:38\n"
msgid " %{start} to %{end}"
msgstr "从%{start}到%{end}"
@@ -40,23 +40,12 @@ msgstr " 类型"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " 您需è¦åœ¨ %{grace_period_deadline} 之å‰æ‰§è¡Œæ­¤æ“作。"
-msgid " and"
-msgstr "和"
-
msgid " and "
msgstr "和"
msgid " and %{sliced}"
msgstr "和%{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] "于%d处有下é™"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] "于%d处有æ高"
-
msgid " or "
msgstr " 或 "
@@ -84,16 +73,19 @@ msgstr "“%{repository_name}†的大å°ï¼ˆ%{repository_size})大于%{limit}
msgid "\"el\" parameter is required for createInstance()"
msgstr "createInstance()必需“elâ€å‚æ•°"
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr "#一般, #å¼€å‘"
msgid "%d Alert"
msgid_plural "%d Alerts"
-msgstr[0] ""
+msgstr[0] "%d 个警报"
msgid "%d Alert:"
msgid_plural "%d Alerts:"
-msgstr[0] ""
+msgstr[0] "%d 个警报:"
msgid "%d Approval"
msgid_plural "%d Approvals"
@@ -171,9 +163,6 @@ msgid "%d commit,"
msgid_plural "%d commits,"
msgstr[0] "%d 次æ交,"
-msgid "%d commits"
-msgstr "%d 次æ交"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] "%d个已完æˆçš„议题"
@@ -393,10 +382,10 @@ msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or
msgstr "%{code_open}å—ä¿æŠ¤ï¼š%{code_close} 仅暴露于å—ä¿æŠ¤çš„分支或标签。"
msgid "%{commit_author_link} authored %{commit_authored_timeago}"
-msgstr ""
+msgstr "由 %{commit_author_link} 创作于 %{commit_authored_timeago}"
msgid "%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} 创作于 %{commit_authored_timeago} ,%{commit_committer_avatar}%{commit_committer_link} æ交于 %{commit_committer_timeago}"
msgid "%{completedCount} completed weight"
msgstr "%{completedCount}已完æˆæƒé‡"
@@ -485,13 +474,13 @@ msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
msgstr "%{doc_link_start}高级æœç´¢%{doc_link_end} å·²å¯ç”¨ã€‚"
msgid "%{docs_link_start}Learn about visibility levels.%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}了解å¯è§æ€§çº§åˆ«ã€‚%{docs_link_end}"
msgid "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}什么是大文件存储?%{docs_link_end}"
msgid "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}什么是åŒé‡èº«ä»½éªŒè¯ï¼Ÿ%{docs_link_end}"
msgid "%{due_date} (Past due)"
msgstr "%{due_date} (已过期)"
@@ -623,10 +612,10 @@ msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message}ä¸å¯ç”¨"
msgid "%{learn_more_link}."
-msgstr ""
+msgstr "%{learn_more_link}。"
msgid "%{lessThan} 1 hour"
-msgstr ""
+msgstr "%{lessThan} 1å°æ—¶"
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} 是一个å…费的ã€è‡ªåŠ¨åŒ–çš„ã€å¼€æ”¾çš„è¯ä¹¦é¢å‘机构(CA),æ供数字è¯ä¹¦ï¼Œä»¥ä¾¿ä¸ºç½‘ç«™å¯ç”¨ HTTPS(SSL / TLS)。"
@@ -647,7 +636,7 @@ msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent
msgstr "%{link_start}以%{draft_snippet}作为标题的开头%{link_end} ,以防止正在工作进程中的åˆå¹¶è¯·æ±‚在准备就绪之å‰è¢«åˆå¹¶ã€‚"
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
-msgstr ""
+msgstr "%{link_start}GitLab Inc. 收集哪些信æ¯ï¼Ÿ%{link_end}"
msgid "%{listToShow}, and %{awardsListLength} more"
msgstr "%{listToShow},还有 %{awardsListLength} 个。"
@@ -798,7 +787,7 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] "%{securityScanner}无结果,因为自å¯ç”¨ä»¥æ¥å°šæœªè¿è¡Œæµæ°´çº¿ã€‚%{linkStart}è¿è¡Œæµæ°´çº¿%{linkEnd}"
msgid "%{service_ping_link_start}What information is shared with GitLab Inc.?%{service_ping_link_end}"
-msgstr ""
+msgstr "%{service_ping_link_start}与 GitLab Inc. 共享哪些信æ¯ï¼Ÿ%{service_ping_link_end}"
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -834,7 +823,7 @@ msgid "%{state} epics"
msgstr "%{state}å²è¯—"
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
-msgstr ""
+msgstr "%{strongOpen}警告:%{strongClose} SAML 群组链接会导致 GitLab 自动从群组中移除æˆå‘˜ã€‚"
msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
msgstr "%{strongStart}æ示:%{strongEnd}您å¯ä»¥%{linkStart}通过以下命令%{linkEnd}å°†åˆå¹¶è¯·æ±‚检出到本地。"
@@ -969,6 +958,9 @@ msgstr "%{webhooks_link_start}%{webhook_type}%{link_end}å…许您针对æŸä¸ªç¾¤
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end}å…许您针对æŸä¸ªç¾¤ç»„或项目中的事件å‘é€é€šçŸ¥åˆ°web应用程åºã€‚ 如需使用webhook, 我们推è优先使用已有%{integrations_link_start}集æˆ%{link_end}。"
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr "支æŒ%{wildcards_link_start}通é…符%{wildcards_link_end} ,例如 %{code_tag_start}v *%{code_tag_end} 或 %{code_tag_start}* -release%{code_tag_end}。"
@@ -1051,9 +1043,15 @@ msgstr "(已删除)"
msgid "(revoked)"
msgstr "(已撤销)"
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr "(我们需è¦æ‚¨å½“å‰çš„密ç æ¥ç¡®è®¤æ‚¨çš„更改)"
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ 其余 %{amount} 项"
@@ -1104,6 +1102,9 @@ msgstr[0] "- 事件"
msgid "- Not available to run jobs."
msgstr "- ä¸å¯ç”¨äºŽè¿è¡Œä½œä¸šã€‚"
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- 用户"
@@ -1118,7 +1119,7 @@ msgid "."
msgstr "."
msgid "/"
-msgstr ""
+msgstr "/"
msgid "0 bytes"
msgstr "0 字节"
@@ -1228,7 +1229,7 @@ msgid "1000+"
msgstr "1000+"
msgid "192.168.0.0/24"
-msgstr ""
+msgstr "192.168.0.0/24"
msgid "1st contribution!"
msgstr "最高贡献"
@@ -1326,9 +1327,6 @@ msgstr "无法为空项目选择默认分支。"
msgid "A deleted user"
msgstr "已删除的用户"
-msgid "A description is required"
-msgstr "需è¦æè¿°"
-
msgid "A different reason"
msgstr "一个ä¸åŒçš„原因"
@@ -1362,8 +1360,8 @@ msgstr "GitLab滥用审查团队æˆå‘˜å°†ä¼šå°½å¿«æŸ¥çœ‹æ‚¨çš„报告。"
msgid "A merge request hasn't yet been merged"
msgstr "åˆå¹¶è¯·æ±‚尚未åˆå¹¶"
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
-msgstr "已创建新的Auto DevOpsæµæ°´çº¿ï¼Œè¯·è½¬åˆ° %{pipelines_link_start}æµæ°´çº¿é¡µé¢%{pipelines_link_end}查看详细信æ¯ã€‚"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
+msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
msgstr "%{name}的新的版本%{tag}å·²å‘布。请访问 %{release_link_start}å‘布页é¢%{release_link_end}了解更多信æ¯ã€‚"
@@ -1389,6 +1387,9 @@ msgstr "å¹³å°å€¼å¯ä»¥æ˜¯web, mob或app。"
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr "使用 Salesforce Developer å·¥å…·å¼€å‘ Salesforce App 的项目样æ¿"
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr "项目包å«ç¾Žå›½å«ç”Ÿä¸Žå…¬å…±æœåŠ¡éƒ¨å‘布的HIPAA审计å议中æ¯ä¸ªå®¡è®¡æŸ¥è¯¢çš„议题"
@@ -1465,7 +1466,7 @@ msgid "APIFuzzing|Configure HTTP basic authentication values. Other authenticati
msgstr "é…ç½®HTTP基本身份验è¯å€¼ã€‚支æŒå…¶å®ƒèº«ä»½éªŒè¯æ–¹æ³•ã€‚ %{linkStart}了解更多%{linkEnd}。"
msgid "APIFuzzing|Customize your project's API fuzzing configuration options and copy the code snippet to your .gitlab-ci.yml file to apply any changes. Note that this tool does not reflect or update your .gitlab-ci.yml file automatically. For details of more advanced configuration options, see the %{docsLinkStart}GitLab API Fuzzing documentation%{docsLinkEnd}."
-msgstr ""
+msgstr "自定义您的项目的 API fuzzing é…置选项,并将代ç ç‰‡æ®µå¤åˆ¶åˆ° .gitlab-ci.yml 文件以应用任何更改。请注æ„,此工具ä¸ä¼šè‡ªåŠ¨å映或更新您的 .gitlab-ci.yml 文件。有关更高级é…置选项的详细信æ¯ï¼Œè¯·å‚阅 %{docsLinkStart}GitLab API Fuzzing 文档%{docsLinkEnd}。"
msgid "APIFuzzing|Enable authentication"
msgstr "å¯ç”¨èº«ä»½éªŒè¯"
@@ -1615,7 +1616,7 @@ msgid "Access granted"
msgstr "已授予访问"
msgid "Access key ID"
-msgstr ""
+msgstr "访问密钥 ID"
msgid "Access requests"
msgstr "访问请求"
@@ -1624,7 +1625,7 @@ msgid "Access to '%{classification_label}' not allowed"
msgstr "ä¸å…许访问%{classification_label}"
msgid "Access tokens expire after 2 hours. A refresh token may be used at any time to generate a new access token. Non-expiring access tokens are deprecated. Clear this setting to enable backward compatibility."
-msgstr ""
+msgstr "访问令牌在 2 å°æ—¶åŽè¿‡æœŸã€‚å¯ä»¥éšæ—¶ä½¿ç”¨åˆ·æ–°ä»¤ç‰Œæ¥ç”Ÿæˆæ–°çš„访问令牌。未到期的访问令牌被废弃。清除此设置以å¯ç”¨å‘åŽå…¼å®¹æ€§ã€‚"
msgid "AccessDropdown|Deploy Keys"
msgstr "部署密钥"
@@ -1711,7 +1712,7 @@ msgid "AccessibilityReport|The accessibility scanning found an error of the foll
msgstr "æ— éšœç¢æ€§æ‰«æå‘现以下类型的错误: %{code}"
msgid "Account"
-msgstr "å¸å·"
+msgstr "å¸æˆ·"
msgid "Account ID"
msgstr "å¸æˆ·ID"
@@ -1737,6 +1738,9 @@ msgstr "æ“作"
msgid "Activate Service Desk"
msgstr "å¯ç”¨æœåŠ¡å°"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "å¯ç”¨"
@@ -1818,9 +1822,6 @@ msgstr "添加一个自定义消æ¯ï¼ŒåŒ…å«å®žä¾‹å…±äº«Runner的详细信æ¯ã€‚
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "添加一般评论 %{noteableDisplayName}。"
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "添加一般评论 %{noteable_name}。"
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "在wiki中添加一个主页,其中包å«æœ‰å…³é¡¹ç›®çš„ä¿¡æ¯ï¼ŒGitLab将在此处显示该主页,而ä¸æ˜¯æ­¤æ¶ˆæ¯ã€‚"
@@ -1899,9 +1900,6 @@ msgstr "添加部署冻结"
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr "添加部署密钥以授予对此存储库的读/写访问æƒé™ã€‚ %{link_start}什么是部署密钥?%{link_end}"
-msgid "Add domain"
-msgstr "添加域å"
-
msgid "Add email address"
msgstr "添加电å­é‚®ä»¶åœ°å€"
@@ -1939,7 +1937,7 @@ msgid "Add new directory"
msgstr "添加目录"
msgid "Add new service account"
-msgstr ""
+msgstr "添加新的æœåŠ¡å¸å·"
msgid "Add or remove previously merged commits"
msgstr "添加或删除先å‰åˆå¹¶çš„æ交"
@@ -1995,6 +1993,9 @@ msgstr "添加到评审"
msgid "Add to tree"
msgstr "添加到树"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr "添加触å‘器"
@@ -2179,7 +2180,7 @@ msgid "AdminArea|Features"
msgstr "功能"
msgid "AdminArea|Get security updates from GitLab and stay up to date"
-msgstr ""
+msgstr "从 GitLab 获å–安全更新并ä¿æŒæ›´æ–°"
msgid "AdminArea|Groups"
msgstr "群组"
@@ -2221,10 +2222,10 @@ msgid "AdminArea|Reporter"
msgstr "报告者"
msgid "AdminArea|Sign up for the GitLab Security Newsletter to get notified for security updates."
-msgstr ""
+msgstr "注册 GitLab Security Newsletter 以获得安全更新通知。"
msgid "AdminArea|Sign up for the GitLab newsletter"
-msgstr ""
+msgstr "注册 GitLab 通讯"
msgid "AdminArea|Stop all jobs"
msgstr "åœæ­¢æ‰€æœ‰ä½œä¸š"
@@ -2296,13 +2297,13 @@ msgid "AdminSettings|Disable public access to Pages sites"
msgstr "ç¦æ­¢å…¬å¼€è®¿é—® Pages 站点"
msgid "AdminSettings|Display a banner on merge requests in projects with no pipelines to initiate steps to add a .gitlab-ci.yml file."
-msgstr ""
+msgstr "在没有æµæ°´çº¿çš„项目中,在åˆå¹¶è¯·æ±‚上显示æ示,开始添加.gitlab-ci.yml文件的步骤。"
msgid "AdminSettings|Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled. %{link_start}Learn more.%{link_end}"
msgstr "域å验è¯æ˜¯å…¬å…± GitLab 站点的基本安全措施。用户需è¦è¯æ˜Žä»–们在å¯ç”¨åŸŸå之å‰æ‹¥æœ‰åŸŸå的所有æƒã€‚%{link_start}了解更多。%{link_end}"
msgid "AdminSettings|Enable pipeline suggestion banner"
-msgstr ""
+msgstr "å¯ç”¨æµæ°´çº¿å»ºè®®æ示"
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "为新项目å¯ç”¨å…±äº«Runner"
@@ -2451,8 +2452,8 @@ msgstr "在您的实例上调整用户上é™è®¾ç½®"
msgid "AdminUsers|Admin"
msgstr "管ç†å‘˜"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
-msgstr "管ç†å‘˜å¯ä»¥è®¿é—®æ‰€æœ‰ç¾¤ç»„ã€é¡¹ç›®å’Œç”¨æˆ·ï¼Œå¹¶å¯ä»¥ç®¡ç†æ­¤å®‰è£…中的所有功能"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
+msgstr ""
msgid "AdminUsers|Admins"
msgstr "管ç†å‘˜"
@@ -2466,6 +2467,12 @@ msgstr "批准用户 %{username} å—?"
msgid "AdminUsers|Approved users can:"
msgstr "已获批准的用户å¯ä»¥ï¼š"
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr "自动标记为默认内部用户"
@@ -2601,8 +2608,8 @@ msgstr "é‡æ–°æ¿€æ´»ç”¨æˆ·å°†ä¼šï¼š"
msgid "AdminUsers|Regular"
msgstr "普通"
-msgid "AdminUsers|Regular users have access to their groups and projects"
-msgstr "普通用户å¯ä»¥è®¿é—®ä»–们的群组和项目"
+msgid "AdminUsers|Regular users have access to their groups and projects."
+msgstr ""
msgid "AdminUsers|Reject"
msgstr "æ‹’ç»"
@@ -2776,10 +2783,10 @@ msgid "Admin|Quarterly reconciliation will occur on %{qrtlyDate}"
msgstr "季度对账将在 %{qrtlyDate}"
msgid "Admin|The number of max seats in your namespace exceeds the number of seats in your subscription. On %{qrtlyDate}, quarterly reconciliation occurs and you are automatically billed a prorated amount for the overage. No action is needed from you. If you have a credit card on file, it will be charged. Otherwise, you will receive an invoice. For more information about the timing of the invoicing process, view the documentation."
-msgstr ""
+msgstr "您的命å空间中的最大席ä½æ•°è¶…过了您订阅中的席ä½æ•°ã€‚在 %{qrtlyDate},进行季度对å¸ï¼Œæ‚¨å°†è‡ªåŠ¨æŒ‰æ¯”例支付超é¢è´¹ç”¨ã€‚您无需采å–任何行动。如果您有信用å¡å­˜æ¡£ï¼Œåˆ™ä¼šè¢«æ”¶å–费用。å¦åˆ™ï¼Œæ‚¨å°†æ”¶åˆ°è´¦å•ã€‚有关账å•æµç¨‹æ—¶é—´çš„更多信æ¯ï¼Œè¯·æŸ¥çœ‹æ–‡æ¡£ã€‚"
msgid "Admin|The number of max users in your instance exceeds the number of users in your license. On %{qrtlyDate}, quarterly reconciliation occurs and you are automatically billed a prorated amount for the overage. No action is needed from you. If you have a credit card on file, it will be charged. Otherwise, you will receive an invoice. For more information about the timing of the invoicing process, view the documentation."
-msgstr ""
+msgstr "您实例中的最大用户数超过了您的许å¯è¯ä¸­çš„用户数。在 %{qrtlyDate},进行季度对å¸ï¼Œæ‚¨å°†è‡ªåŠ¨æŒ‰æ¯”例支付超é¢è´¹ç”¨ã€‚您无需采å–任何行动。如果您有信用å¡å­˜æ¡£ï¼Œåˆ™ä¼šè¢«æ”¶å–费用。å¦åˆ™ï¼Œæ‚¨å°†æ”¶åˆ°è´¦å•ã€‚有关账å•æµç¨‹æ—¶é—´çš„更多信æ¯ï¼Œè¯·æŸ¥çœ‹æ–‡æ¡£ã€‚"
msgid "Admin|View pending user approvals"
msgstr "查看等待中的用户批准"
@@ -2818,13 +2825,13 @@ msgid "After you've reviewed these contribution guidelines, you'll be all set to
msgstr "在阅读这些贡献指å—åŽï¼Œæ‚¨å°†å‡†å¤‡å¥½"
msgid "Akismet"
-msgstr ""
+msgstr "Akismet"
msgid "Akismet API Key"
msgstr "Akismet API 密钥"
msgid "Akismet helps prevent the creation of spam issues in public projects."
-msgstr ""
+msgstr "Akismet有助于防止在公共项目中产生垃圾信æ¯ã€‚"
msgid "AlertManagement|Acknowledged"
msgstr "已确认"
@@ -3181,7 +3188,7 @@ msgid "All (default)"
msgstr "全部(默认)"
msgid "All GitLab"
-msgstr ""
+msgstr "整个GitLab"
msgid "All Members"
msgstr "所有æˆå‘˜"
@@ -3216,8 +3223,8 @@ msgstr "所有åˆå¹¶å†²çªéƒ½å·²è§£å†³ã€‚æ­¤åˆå¹¶è¯·æ±‚现在å¯ä»¥åˆå¹¶ã€‚"
msgid "All merge request dependencies have been merged"
msgstr "所有åˆå¹¶è¯·æ±‚ä¾èµ–项å‡å·²åˆå¹¶"
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
-msgstr "所有路径都相对于GitLab URL。请ä¸è¦åŒ…å«%{relative_url_link_start}相对的URL%{relative_url_link_end}。"
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
+msgstr ""
msgid "All projects"
msgstr "所有项目"
@@ -3234,6 +3241,9 @@ msgstr "所有用户必须接å—æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–æ‰èƒ½è®¿é—® GitLab"
msgid "All users must have a name."
msgstr "所有的用户都必须具有å称。"
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "å…许“%{group_name}â€ä»¥æ‚¨çš„身份登录"
@@ -3249,8 +3259,8 @@ msgstr "å…许具有åˆå¹¶åˆ°ç›®æ ‡åˆ†æ”¯æƒé™çš„æˆå‘˜æ交"
msgid "Allow group owners to manage LDAP-related settings"
msgstr "å…许群组所有者管ç†LDAP相关的设置"
-msgid "Allow non-administrators to access to the performance bar"
-msgstr "å…许éžç®¡ç†å‘˜è®¿é—®æ€§èƒ½æ "
+msgid "Allow non-administrators access to the performance bar"
+msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr "ä»…å…许所选å议用于 Git 访问。"
@@ -3298,7 +3308,7 @@ msgid "Allow this secondary node to replicate content on Object Storage"
msgstr "å…许此次è¦èŠ‚点在对象存储上å¤åˆ¶å†…容"
msgid "Allow use of licensed EE features"
-msgstr ""
+msgstr "å…许使用许å¯çš„EE功能"
msgid "Allow users to dismiss the broadcast message"
msgstr "å…许用户关闭广播消æ¯"
@@ -3484,19 +3494,22 @@ msgid "An error occurred while enabling Service Desk."
msgstr "å¯ç”¨æœåŠ¡å°æ—¶å‘生错误。"
msgid "An error occurred while fetching Markdown preview"
-msgstr ""
+msgstr "èŽ·å– Markdown 预览时出错"
msgid "An error occurred while fetching ancestors"
msgstr "获å–上级时å‘生错误"
-msgid "An error occurred while fetching branches. Retry the search."
-msgstr "获å–分支时å‘生错误,请é‡è¯•æœç´¢ã€‚"
+msgid "An error occurred while fetching branches. Retry the search."
+msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr "获å–代ç è´¨é‡åˆå¹¶è¯·æ±‚差异报告时å‘生错误。"
-msgid "An error occurred while fetching commits. Retry the search."
-msgstr "获å–æ交时å‘生错误,请é‡è¯•æœç´¢ã€‚"
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
+msgstr ""
msgid "An error occurred while fetching coverage reports."
msgstr "获å–覆盖度报告时出错。"
@@ -3607,7 +3620,7 @@ msgid "An error occurred while loading merge requests."
msgstr "加载åˆå¹¶è¯·æ±‚æ—¶å‘生错误。"
msgid "An error occurred while loading projects."
-msgstr ""
+msgstr "加载项目时出错。"
msgid "An error occurred while loading the Needs tab."
msgstr "加载Needs选项å¡æ—¶å‡ºé”™ã€‚"
@@ -3699,6 +3712,10 @@ msgstr "获å–项目时å‘生错误。"
msgid "An error occurred while saving changes: %{error}"
msgstr "ä¿å­˜æ›´æ”¹æ—¶å‘生错误:%{error}"
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "订阅通知时å‘生错误。"
@@ -3762,9 +3779,6 @@ msgstr "一个示例项目,展示了为你自己的组织设置GitLab的最佳
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr "显示如何在GitLab动æ€å­æµæ°´çº¿ä¸­ä½¿ç”¨Jsonnet的示例"
-msgid "An instance-level serverless domain already exists."
-msgstr "一个实例级无æœåŠ¡å™¨åŸŸå·²ç»å­˜åœ¨ã€‚"
-
msgid "An issue already exists"
msgstr "议题已ç»å­˜åœ¨"
@@ -3862,7 +3876,7 @@ msgid "Any namespace"
msgstr "任何命å空间"
msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
+msgstr "App Engineæ述和适åˆæ­¤éƒ¨ç½²ç›®æ ‡çš„ App"
msgid "App ID"
msgstr "应用ID"
@@ -4012,7 +4026,7 @@ msgstr "应用"
msgid "Apply %d suggestion"
msgid_plural "Apply %d suggestions"
-msgstr[0] ""
+msgstr[0] "应用 %d 个建议"
msgid "Apply a label"
msgstr "应用标记"
@@ -4027,7 +4041,7 @@ msgid "Apply template"
msgstr "应用模æ¿"
msgid "Apply this approval rule to all branches or a specific protected branch."
-msgstr ""
+msgstr "将此批准规则应用于所有分支或特定的å—ä¿æŠ¤åˆ†æ”¯ã€‚"
msgid "Applying"
msgstr "应用中"
@@ -4090,12 +4104,18 @@ msgstr "所有扫æ工具"
msgid "ApprovalRule|All severity levels"
msgstr "所有严é‡çº§åˆ«"
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr "应用此审批规则åªè€ƒè™‘选定的安全扫æ工具。"
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr "应用此审批规则åªè€ƒè™‘选定的严é‡çº§åˆ«ã€‚"
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr "核准规则"
@@ -4108,12 +4128,21 @@ msgstr "核准人类型"
msgid "ApprovalRule|Approvers"
msgstr "核准人"
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr "示例:QAã€å®‰å…¨ã€‚"
msgid "ApprovalRule|Name"
msgstr "å称"
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr "在触å‘批准规则之å‰å…许的æ¼æ´žæ•°é‡ã€‚"
@@ -4126,6 +4155,15 @@ msgstr "请选择至少一个安全扫æ工具"
msgid "ApprovalRule|Please select at least one severity level"
msgstr "请选择至少一个严é‡çº§åˆ«"
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr "规则å称"
@@ -4141,6 +4179,9 @@ msgstr "选择扫æ工具"
msgid "ApprovalRule|Select severity levels"
msgstr "选择严é‡çº§åˆ«"
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr "严é‡çº§åˆ«"
@@ -4150,8 +4191,11 @@ msgstr "目标分支"
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr "å…许的æ¼æ´ž"
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
-msgstr "åˆå¹¶è¯·æ±‚核准设置已更新。"
+msgstr "åˆå¹¶è¯·æ±‚审批设置已更新。"
msgid "ApprovalSettings|Prevent approval by author."
msgstr "ç¦æ­¢ä½œè€…审批。"
@@ -4160,16 +4204,16 @@ msgid "ApprovalSettings|Prevent approvals by users who add commits."
msgstr "ç¦æ­¢æ·»åŠ æ交的用户审批。"
msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
-msgstr "ç¦æ­¢åœ¨åˆå¹¶è¯·æ±‚中编辑审批规则。"
+msgstr "ç¦æ­¢åœ¨åˆå¹¶è¯·æ±‚中编辑批准规则。"
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
-msgstr "ç¦æ­¢åœ¨é¡¹ç›®å’Œåˆå¹¶è¯·æ±‚中编辑审批规则。"
+msgstr "ç¦æ­¢åœ¨é¡¹ç›®å’Œåˆå¹¶è¯·æ±‚中编辑批准规则。"
msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
-msgstr "当æ交被添加到æºåˆ†æ”¯æ—¶ï¼Œåˆ é™¤æ‰€æœ‰å®¡æ‰¹ã€‚"
+msgstr "当æ交被添加到æºåˆ†æ”¯æ—¶åˆ é™¤æ‰€æœ‰å®¡æ‰¹ã€‚"
msgid "ApprovalSettings|Require user password to approve."
-msgstr "需è¦ç”¨æˆ·å¯†ç æ‰èƒ½å®¡æ‰¹ã€‚"
+msgstr "需è¦ç”¨æˆ·å¯†ç æ‰èƒ½æ‰¹å‡†ã€‚"
msgid "ApprovalSettings|There was an error loading merge request approval settings."
msgstr "加载åˆå¹¶è¯·æ±‚批准设置时出错。"
@@ -4181,7 +4225,7 @@ msgid "ApprovalSettings|This setting is configured at the instance level and can
msgstr "此设置在实例级别é…置,åªèƒ½ç”±ç®¡ç†å‘˜æ›´æ”¹ã€‚"
msgid "ApprovalSettings|This setting is configured in %{groupName} and can only be changed by an administrator or group owner."
-msgstr ""
+msgstr "此设置在 %{groupName} 中é…置,åªèƒ½ç”±ç®¡ç†å‘˜æˆ–群组所有者更改。"
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr "éµå®ˆèŒè´£åˆ†ç¦»"
@@ -4421,12 +4465,6 @@ msgstr "您确认è¦åˆ é™¤GPG密钥么?删除此GPG密钥ä¸ä¼šå½±å“å·²ç»ç­¾
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr "您确定å—?该设备将从GitLab中注销,所有“记ä½æˆ‘â€çš„令牌å‡è¢«æ’¤é”€ã€‚"
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr "你确定å—?这会使您注册的应用程åºå’ŒU2F / WebAuthn设备无效。"
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr "你确定å—?这将使您的已注册应用和U2F设备失效。"
-
msgid "Arrange charts"
msgstr "排列图表"
@@ -4660,6 +4698,9 @@ msgstr "8 月"
msgid "Authenticate"
msgstr "验è¯"
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr "使用GitHub身份验è¯"
@@ -4676,7 +4717,7 @@ msgid "Authenticated Git LFS request rate limit"
msgstr "认è¯çš„ Git LFS 请求速率é™åˆ¶"
msgid "Authenticated Git LFS requests"
-msgstr ""
+msgstr "ç»è¿‡èº«ä»½éªŒè¯çš„ Git LFS 请求"
msgid "Authenticated web rate limit period in seconds"
msgstr "认è¯çš„网页速率é™åˆ¶æ—¶é—´ï¼ˆç§’)"
@@ -5291,23 +5332,26 @@ msgstr "阻止"
msgid "Blog"
msgstr "åšå®¢"
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "看æ¿èŒƒå›´ä¼šå½±å“访问此看æ¿çš„人å¯ä»¥æ˜¾ç¤ºå“ªäº›è®®é¢˜"
msgid "BoardNewEpic|Groups"
-msgstr ""
+msgstr "群组"
msgid "BoardNewEpic|Loading groups"
-msgstr ""
+msgstr "加载群组"
msgid "BoardNewEpic|No matching results"
-msgstr ""
+msgstr "没有匹é…结果"
msgid "BoardNewEpic|Search groups"
-msgstr ""
+msgstr "æœç´¢ç¾¤ç»„"
msgid "BoardNewEpic|Select a group"
-msgstr ""
+msgstr "选择一个群组"
msgid "BoardNewIssue|No matching results"
msgstr "没有匹é…结果"
@@ -5386,7 +5430,7 @@ msgid "Boards|An error occurred while creating the list. Please try again."
msgstr "创建列表时å‘生错误。请å†è¯•ä¸€é。"
msgid "Boards|An error occurred while fetching child groups. Please try again."
-msgstr ""
+msgstr "获å–å­ç¾¤ç»„æ—¶å‘生错误,请é‡è¯•ã€‚"
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr "获å–群组项目时å‘生错误。请é‡è¯•ã€‚"
@@ -5530,8 +5574,8 @@ msgstr "全部"
msgid "Branches|Cancel, keep branch"
msgstr "å–消,ä¿ç•™åˆ†æ”¯"
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "ä¸èƒ½æ‰¾åˆ°è¿™ä¸ªåˆ†æ”¯çš„ HEAD æ交"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "比较"
@@ -5641,6 +5685,9 @@ msgstr "请输入 %{branch_name_confirmation} æ¥ç¡®è®¤ï¼š"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr "è¦æ”¾å¼ƒæœ¬åœ°æ›´æ”¹å¹¶è¦†ç›–上游版本的分支,请在此处将其删除,然åŽé€‰æ‹©ä¸Šé¢çš„“立å³æ›´æ–°â€ã€‚"
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr "是的,删除分支"
@@ -5720,7 +5767,7 @@ msgid "Bulk update"
msgstr "批é‡æ›´æ–°"
msgid "BulkImports|Re-import creates a new group. It does not sync with the existing group."
-msgstr ""
+msgstr "é‡æ–°å¯¼å…¥æ–°ç¾¤ç»„。它ä¸ä¼šä¸ŽçŽ°æœ‰ç¾¤ç»„åŒæ­¥ã€‚"
msgid "BulkImport|Existing groups"
msgstr "现有群组"
@@ -5732,7 +5779,7 @@ msgid "BulkImport|From source group"
msgstr "从æºç¾¤ç»„"
msgid "BulkImport|Group import history"
-msgstr ""
+msgstr "群组导入历å²"
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr "导入失败:目标ä¸èƒ½æ˜¯æºç»„çš„å­ç»„。更改目标,然åŽé‡è¯•ã€‚"
@@ -5747,16 +5794,16 @@ msgid "BulkImport|Importing the group failed"
msgstr "导入群组失败"
msgid "BulkImport|Last imported to %{link}"
-msgstr ""
+msgstr "上次导入到 %{link}"
msgid "BulkImport|Name already exists."
msgstr "å称已存在。"
msgid "BulkImport|New group"
-msgstr ""
+msgstr "新建群组"
msgid "BulkImport|No history is available"
-msgstr ""
+msgstr "没有历å²è®°å½•"
msgid "BulkImport|No parent"
msgstr "没有父级"
@@ -5771,7 +5818,7 @@ msgid "BulkImport|Showing %{start}-%{end} of %{total} matching filter \"%{filter
msgstr "显示从%{link}中匹é…筛选器“%{filter}†的 %{start}-%{end} / %{total}"
msgid "BulkImport|Source group"
-msgstr ""
+msgstr "æºç¾¤ç»„"
msgid "BulkImport|To new group"
msgstr "到新群组"
@@ -5783,7 +5830,7 @@ msgid "BulkImport|You have no groups to import"
msgstr "您没有è¦å¯¼å…¥çš„群组"
msgid "BulkImport|Your imported groups will appear here."
-msgstr ""
+msgstr "您导入的群组将出现在这里。"
msgid "BulkImport|expected an associated Group but has an associated Project"
msgstr "需与群组关è”但是当å‰ä¸Žé¡¹ç›®å…³è”"
@@ -5848,9 +5895,6 @@ msgstr "CI Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr "CIé…置已验è¯ï¼ŒåŒ…括所有通过%{codeStart}include%{codeEnd}关键字引入的é…置。%{link}"
-msgid "CI minutes"
-msgstr "CI 分钟"
-
msgid "CI settings"
msgstr "CI设置"
@@ -6027,7 +6071,7 @@ msgid "Can be manually deployed to"
msgstr "å¯ä»¥æ‰‹åŠ¨éƒ¨ç½²åˆ°"
msgid "Can be overridden in each project."
-msgstr ""
+msgstr "å¯ä»¥åœ¨æ¯ä¸ªé¡¹ç›®ä¸­è¦†ç›–。"
msgid "Can create groups:"
msgstr "å¯ä»¥åˆ›å»ºç¾¤ç»„:"
@@ -6132,10 +6176,7 @@ msgid "Cancelling Preview"
msgstr "å–消预览"
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
-msgstr ""
-
-msgid "Cannot be assigned to other projects."
-msgstr "无法分é…给其他项目。"
+msgstr "无法将机密å²è¯—分é…ç»™éžæœºå¯†è®®é¢˜ã€‚请将此议题设置机密并é‡è¯•"
msgid "Cannot be merged automatically"
msgstr "无法自动åˆå¹¶"
@@ -6194,6 +6235,12 @@ msgstr "无法跳过åŒé‡è®¤è¯è®¾ç½®"
msgid "Capacity threshold"
msgstr "容é‡é˜ˆå€¼"
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr "强制所有å­ç¾¤ç»„"
@@ -6429,7 +6476,7 @@ msgid "Check the elasticsearch.log file to debug why the migration was halted an
msgstr "检查elasticsearch.log文件以调试为什么åœæ­¢è¿ç§»ï¼Œåœ¨é‡æ–°å°è¯•è¿ç§»ä¹‹å‰è¿›è¡Œä»»ä½•æ›´æ”¹ã€‚解决故障原因åŽï¼Œè¯·å•å‡»â€œé‡è¯•è¿ç§»â€ï¼ŒåŽå°ä¼šè®¡åˆ’é‡è¯•è¿ç§»ã€‚"
msgid "Check with your administrator."
-msgstr ""
+msgstr "请è”系您的管ç†å‘˜ã€‚"
msgid "Check your Docker images for known vulnerabilities."
msgstr "检查您的Dockeré•œåƒæ˜¯å¦å­˜åœ¨å·²çŸ¥æ¼æ´ž."
@@ -6462,7 +6509,7 @@ msgid "Checkout"
msgstr "支付"
msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage per pack"
-msgstr ""
+msgstr "æ¯ä¸ªåŒ…æ¯10 GB存储 %{selectedPlanPrice} 美元"
msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
msgstr "$%{selectedPlanPrice} æ¯åŒ… 1,000 分钟"
@@ -6484,14 +6531,14 @@ msgid "Checkout|%{name}'s GitLab subscription"
msgstr "%{name}的GitLab订阅"
msgid "Checkout|%{name}'s storage subscription"
-msgstr ""
+msgstr "%{name}的存储订阅"
msgid "Checkout|%{quantity} GB of storage"
-msgstr ""
+msgstr "%{quantity} GB 存储"
msgid "Checkout|%{quantity} storage pack"
msgid_plural "Checkout|%{quantity} storage packs"
-msgstr[0] ""
+msgstr[0] "%{quantity} 个存储包"
msgid "Checkout|%{selectedPlanText} plan"
msgstr "%{selectedPlanText}计划"
@@ -6520,6 +6567,9 @@ msgstr "CI 分钟包"
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr "CI 分钟包仅在您使用完订阅的æ¯æœˆé…é¢åŽä½¿ç”¨ã€‚é¢å¤–的分钟数将é€æœˆæ»šåŠ¨ï¼Œæœ‰æ•ˆæœŸä¸ºä¸€å¹´ã€‚"
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr " 支付"
@@ -6553,6 +6603,9 @@ msgstr "信用å¡è¡¨å•åŠ è½½å¤±è´¥ï¼š %{message}"
msgid "Checkout|Edit"
msgstr "编辑"
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr "有效期至%{expirationMonth}/%{expirationYear}"
@@ -6575,7 +6628,7 @@ msgid "Checkout|Failed to register credit card. Please try again."
msgstr "注册信用å¡å¤±è´¥ã€‚请å†è¯•ä¸€æ¬¡ã€‚"
msgid "Checkout|GB"
-msgstr ""
+msgstr "GB"
msgid "Checkout|GitLab group"
msgstr "GitLab群组"
@@ -6614,7 +6667,7 @@ msgid "Checkout|State"
msgstr "å·ž"
msgid "Checkout|Storage packs"
-msgstr ""
+msgstr "存储包"
msgid "Checkout|Street address"
msgstr "è¡—é“地å€"
@@ -6638,7 +6691,7 @@ msgid "Checkout|Total minutes: %{quantity}"
msgstr "总分钟数:%{quantity}"
msgid "Checkout|Total storage: %{quantity} GB"
-msgstr ""
+msgstr "总存储é‡: %{quantity} GB"
msgid "Checkout|Users"
msgstr "用户"
@@ -6650,7 +6703,7 @@ msgid "Checkout|Your organization"
msgstr "您的组织"
msgid "Checkout|Your storage subscription has the same term as your main subscription, and the price is prorated accordingly."
-msgstr ""
+msgstr "您的存储订阅与您的主è¦è®¢é˜…具有相åŒçš„期é™ï¼Œå¹¶ä¸”价格会相应地按比例分é…。"
msgid "Checkout|Your subscription will be applied to this group"
msgstr "您的订阅将应用于该群组"
@@ -6659,16 +6712,19 @@ msgid "Checkout|Zip code"
msgstr "邮政编ç "
msgid "Checkout|a storage subscription"
-msgstr ""
+msgstr "存储订阅"
msgid "Checkout|company or team"
msgstr "å…¬å¸æˆ–团队"
msgid "Checkout|minutes"
+msgstr "分钟"
+
+msgid "Checkout|x %{quantity} %{units} per pack"
msgstr ""
msgid "Checkout|x %{quantity} %{units} per pack ="
-msgstr ""
+msgstr "x %{quantity} %{units} æ¯åŒ… ="
msgid "Cherry-pick this commit"
msgstr "拣选此æ交"
@@ -6709,15 +6765,9 @@ msgstr "选择模æ¿..."
msgid "Choose a type..."
msgstr "选择类型..."
-msgid "Choose any color"
-msgstr "选择任何颜色"
-
msgid "Choose any color."
msgstr "选择任何颜色。"
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr "选择任何颜色。或者您å¯ä»¥é€‰æ‹©ä»¥ä¸‹å»ºè®®çš„颜色之一"
-
msgid "Choose file…"
msgstr "选择文件…"
@@ -7025,7 +7075,7 @@ msgid "CloneIssue|Cannot clone issue to target project as it is pending deletion
msgstr "无法克隆议题到目标项目,因为它正在等待删除。"
msgid "CloneIssue|Cannot clone issues of '%{issue_type}' type."
-msgstr ""
+msgstr "无法å¤åˆ¶ \"%{issue_type}\" 类型的议题。"
msgid "Cloned this issue to %{path_to_project}."
msgstr "将此议题克隆到%{path_to_project}。"
@@ -7082,10 +7132,10 @@ msgid "Closes this %{quick_action_target}."
msgstr "关闭此%{quick_action_target}."
msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
+msgstr "适用于此部署目标的 Cloud Functions æ述和应用程åº"
msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
+msgstr "适用于此部署目标的 Cloud Run æ述和应用"
msgid "Cluster"
msgstr "集群"
@@ -7112,10 +7162,10 @@ msgid "ClusterAgents|Access tokens"
msgstr "访问令牌"
msgid "ClusterAgents|Agent might not be connected to GitLab"
-msgstr ""
+msgstr "代ç†å¯èƒ½æ— æ³•è¿žæŽ¥åˆ° GitLab"
msgid "ClusterAgents|Agent never connected to GitLab"
-msgstr ""
+msgstr "代ç†ä»Žæœªè¿žæŽ¥åˆ° GitLab"
msgid "ClusterAgents|Alternative installation methods"
msgstr "其他安装方法"
@@ -7133,10 +7183,10 @@ msgid "ClusterAgents|Configuration"
msgstr "é…ç½®"
msgid "ClusterAgents|Connected"
-msgstr ""
+msgstr "已连接"
msgid "ClusterAgents|Connection status"
-msgstr ""
+msgstr "连接状æ€"
msgid "ClusterAgents|Copy token"
msgstr "å¤åˆ¶ä»¤ç‰Œ"
@@ -7157,7 +7207,7 @@ msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the
msgstr "关于替代安装方法,%{linkStart}转到文档%{linkEnd}。"
msgid "ClusterAgents|For more troubleshooting information go to"
-msgstr ""
+msgstr "有关更多故障排查信æ¯ï¼Œè¯·è®¿é—®"
msgid "ClusterAgents|Go to the repository"
msgstr "转到仓库"
@@ -7175,16 +7225,16 @@ msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr "与GitLab Agent集æˆ"
msgid "ClusterAgents|Last connected %{timeAgo}."
-msgstr ""
+msgstr "上次连接在 %{timeAgo}。"
msgid "ClusterAgents|Last contact"
-msgstr ""
+msgstr "最åŽä¸€æ¬¡è”ç³»"
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr "了解如何创建一个 agent 访问令牌"
msgid "ClusterAgents|Make sure you are using a valid token."
-msgstr ""
+msgstr "请确ä¿æ‚¨æ­£åœ¨ä½¿ç”¨ä¸€ä¸ªæœ‰æ•ˆçš„令牌。"
msgid "ClusterAgents|Name"
msgstr "å称"
@@ -7193,10 +7243,10 @@ msgid "ClusterAgents|Never"
msgstr "从ä¸"
msgid "ClusterAgents|Never connected"
-msgstr ""
+msgstr "从未连接"
msgid "ClusterAgents|Not connected"
-msgstr ""
+msgstr "未连接"
msgid "ClusterAgents|Read more about getting started"
msgstr "阅读有关入门的更多信æ¯"
@@ -7220,7 +7270,7 @@ msgid "ClusterAgents|Select which Agent you want to install"
msgstr "选择您想è¦å®‰è£…的代ç†"
msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
-msgstr ""
+msgstr "代ç†å¾ˆä¹…未连接。å¯èƒ½å­˜åœ¨è¿žæŽ¥é—®é¢˜ã€‚最åŽä¸€æ¬¡è”系是在 %{timeAgo}。"
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr "GitLab Agent也需è¦%{linkStart}å¯ç”¨ä»£ç†æœåŠ¡å™¨%{linkEnd}"
@@ -7360,8 +7410,8 @@ msgstr "检查您的群集状æ€"
msgid "ClusterIntegration|Check your token"
msgstr "检查您的令牌"
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
-msgstr "选择应用于在工作节点å­ç½‘中创建并由EKS管ç†çš„弹性网络接å£çš„%{linkStart}安全组%{linkEnd}。"
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
msgstr "在VPC中选择è¿è¡Œå·¥ä½œèŠ‚点的%{linkStart}å­ç½‘%{linkEnd}。"
@@ -7801,6 +7851,9 @@ msgstr "安全组"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "查看并编辑Kubernetes集群的详细信æ¯"
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr "请先选择一个区域然åŽé€‰æ‹©å®‰å…¨ç»„"
@@ -7810,6 +7863,9 @@ msgstr "请先选择一个区域然åŽé€‰æ‹©å­ç½‘"
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr "请选择EKS集群的VPC。如需使用新的VPC, 请先在%{linkStart}Amazon Web Services%{linkEnd}上创建一个。"
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "选择一个网络以选择å­ç½‘"
@@ -7819,9 +7875,24 @@ msgstr "请先选择一个区域然åŽé€‰æ‹©ä¸€ä¸ªå¯†é’¥å¯¹"
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr "请先选择一个区域然åŽé€‰æ‹©VPC"
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr "选择区域以选择网络"
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr "选择实例类型"
@@ -7834,6 +7905,9 @@ msgstr "按项目和地域选择实例类型"
msgid "ClusterIntegration|Select project to choose zone"
msgstr "按项目选择地域"
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr "选择将用于创建EC2节点的密钥对å称。如需è¦ä½¿ç”¨æ–°çš„密钥对å称,请先在%{linkStart}Amazon Web Services%{linkEnd}上创建一个。"
@@ -7871,7 +7945,7 @@ msgid "ClusterIntegration|Subnets"
msgstr "å­ç½‘"
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provisioned role, first create one on %{awsLinkStart}Amazon Web Services %{awsLinkEnd} using the above account and external IDs. %{moreInfoStart}More information%{moreInfoEnd}"
-msgstr ""
+msgstr "与您角色相关è”的亚马逊资æºå称 (ARN)。 如果您没有预设的角色,首先在 %{awsLinkStart}Amazon Web Services %{awsLinkEnd} 上使用上述账å·å’Œå¤–部ID创建一个。%{moreInfoStart}更多信æ¯%{moreInfoEnd}"
msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr "用于对群集进行身份验è¯çš„ Kubernetes è¯ä¹¦ã€‚"
@@ -7984,30 +8058,6 @@ msgstr "符åˆç›¸å…³è¦æ±‚"
msgid "ClusterIntegration|sign up"
msgstr "注册"
-msgid "ClusterIntergation|Select a VPC"
-msgstr "选择VPC"
-
-msgid "ClusterIntergation|Select a network"
-msgstr "选择网络"
-
-msgid "ClusterIntergation|Select a security group"
-msgstr "选择一个安全组"
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr "选择å­ç½‘"
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr "选择å­ç½‘"
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr "选择实例类型"
-
-msgid "ClusterIntergation|Select key pair"
-msgstr "选择密钥对"
-
-msgid "ClusterIntergation|Select service role"
-msgstr "选择æœåŠ¡è§’色"
-
msgid "Clusters|An error occurred while loading clusters"
msgstr "加载集群时å‘生了错误"
@@ -8105,7 +8155,7 @@ msgid "Collapse replies"
msgstr "收起回å¤"
msgid "Collapse settings section"
-msgstr ""
+msgstr "折å è®¾ç½®éƒ¨åˆ†"
msgid "Collapse sidebar"
msgstr "收起侧边æ "
@@ -8126,7 +8176,7 @@ msgid "Comma-separated list of email addresses."
msgstr "逗å·åˆ†éš”的电å­é‚®ä»¶åœ°å€åˆ—表。"
msgid "Comma-separated list of users allowed to exceed the rate limit."
-msgstr ""
+msgstr "å…许超过速率é™åˆ¶çš„以逗å·åˆ†éš”的用户列表。"
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
msgstr "以逗å·åˆ†éš”,例如 '1.1.1, 2.2.2.0/24'"
@@ -8146,12 +8196,6 @@ msgstr "命令未使用"
msgid "Comment"
msgstr "添加评论"
-msgid "Comment & close %{noteable_name}"
-msgstr "评论并关闭 %{noteable_name}"
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr "评论并é‡æ–°å¼€å¯ %{noteable_name}"
-
msgid "Comment & resolve thread"
msgstr "评论并解决主题"
@@ -8267,6 +8311,9 @@ msgstr "社区论å›"
msgid "Company"
msgstr "å…¬å¸"
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "比较"
@@ -8348,32 +8395,38 @@ msgstr "完æˆ"
msgid "Completed"
msgstr "已完æˆ"
-msgid "Compliance"
-msgstr "åˆè§„"
-
-msgid "Compliance Dashboard"
-msgstr "åˆè§„仪表æ¿"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
+msgstr ""
msgid "Compliance framework"
msgstr "åˆè§„框架"
+msgid "Compliance report"
+msgstr ""
+
msgid "ComplianceDashboard|created by:"
msgstr "创建人:"
msgid "ComplianceFrameworks|Add framework"
msgstr "添加框架"
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
-msgstr "è¿è¡Œæ—¶ä¸ŽCIé…置组åˆã€‚"
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
+msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr "åˆè§„框架已æˆåŠŸåˆ é™¤"
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
-msgstr "åˆè§„æµæ°´çº¿é…ç½®ä½ç½®ï¼ˆå¯é€‰ï¼‰"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
-msgstr "找ä¸åˆ°æ­¤é…ç½®ä½ç½®ï¼Œè¯·å°è¯•å…¶å®ƒä½ç½®"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
+msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
msgstr "删除åˆè§„框架%{framework}"
@@ -8381,6 +8434,12 @@ msgstr "删除åˆè§„框架%{framework}"
msgid "ComplianceFrameworks|Delete framework"
msgstr "删除框架"
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr "编辑框架"
@@ -8393,32 +8452,32 @@ msgstr "获å–åˆè§„框架数æ®æ—¶å‡ºé”™ã€‚请刷新页é¢"
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr "获å–åˆè§„框架数æ®æ—¶å‡ºé”™ã€‚请刷新页é¢æˆ–å°è¯•å…¶å®ƒçš„框架"
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
-msgstr "无效格å¼ï¼šåº”éµå¾ªæ ¼å¼[PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
+msgstr ""
+
+msgid "ComplianceFrameworks|Name"
+msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
-msgstr "添加åˆè§„框架åŽï¼Œå®ƒå°†å‡ºçŽ°åœ¨è¿™é‡Œã€‚"
+msgid "ComplianceFrameworks|Name is required"
+msgstr ""
+
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
+msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
-msgstr "尚未设置åˆè§„框架"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr "无法ä¿å­˜æ­¤åˆè§„性框架。请é‡è¯•"
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
-msgstr "使用%{codeStart}::%{codeEnd}创建一个%{linkStart}范围集%{linkEnd} (例如 %{codeStart}SOX::AWS%{codeEnd})"
-
msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr "您å³å°†ä»Žæ‰€æœ‰å½“å‰åº”用的项目中永久删除åˆè§„框架 %{framework} ,这å¯èƒ½ä¼šåˆ é™¤å…¶å®ƒåŠŸèƒ½ã€‚æ­¤æ“作无法撤消。"
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
-msgstr "例如include-gitlab.ci.yml@group-name/project-name"
-
-msgid "ComplianceFramework|Edit Compliance Framework"
-msgstr "编辑åˆè§„框架"
+msgid "ComplianceFramework|Edit compliance framework"
+msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
-msgstr "新建åˆè§„框架"
+msgid "ComplianceFramework|New compliance framework"
+msgstr ""
msgid "Component"
msgstr "组件"
@@ -8448,7 +8507,7 @@ msgid "Configure %{repository_checks_link_start}repository checks%{link_end} and
msgstr "在仓库上é…ç½® %{repository_checks_link_start}仓库检查%{link_end} å’Œ %{housekeeping_link_start}例行维护%{link_end}。"
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
-msgstr ""
+msgstr "é…ç½® CAPTCHAã€IP 地å€é™åˆ¶å’Œå…¶ä»–å垃圾邮件措施。"
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
msgstr "使用 GitLab 托管模æ¿åœ¨ `.gitlab-ci.yml` 中é…ç½®ä¾èµ–扫æ。您å¯ä»¥[添加å˜é‡è¦†ç›–](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) æ¥è‡ªå®šä¹‰ä¾èµ–项扫æ设置。"
@@ -8487,17 +8546,11 @@ msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeSt
msgstr "在%{codeStart}.gitlab%{codeEnd}目录中é…ç½®%{codeStart}gitlab-webide.yml%{codeEnd}文件以开始使用Web终端。 %{helpStart}了解更多。%{helpEnd}"
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
-msgstr ""
-
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
+msgstr "é…置高级æƒé™ã€å¤§æ–‡ä»¶å­˜å‚¨å’ŒåŒé‡èº«ä»½éªŒè¯è®¾ç½®ã€‚"
msgid "Configure existing installation"
msgstr "é…置现有安装"
-msgid "Configure paths to be protected by Rack Attack."
-msgstr "é…ç½®è¦ä¿æŠ¤æœºæž¶æ”»å‡»çš„路径。"
-
msgid "Configure repository mirroring."
msgstr "é…置仓库镜åƒã€‚"
@@ -8508,13 +8561,13 @@ msgid "Configure settings for Advanced Search with Elasticsearch."
msgstr "使用 Elasticsearch é…置高级æœç´¢çš„设置。"
msgid "Configure specific limits for Files API requests that supersede the general user and IP rate limits."
-msgstr ""
+msgstr "为 Files API 请求é…置特定é™åˆ¶ä»¥å–代一般用户和 IP 速率é™åˆ¶ã€‚"
msgid "Configure specific limits for Git LFS requests that supersede the general user and IP rate limits."
msgstr "é…ç½®å–代一般用户和 IP 率é™åˆ¶çš„ Git LFS 请求的特定é™åˆ¶ã€‚"
msgid "Configure specific limits for deprecated API requests that supersede the general user and IP rate limits."
-msgstr ""
+msgstr "为已废弃的 API 请求é…置特定é™åˆ¶ä»¥å–代一般用户和 IP 速率é™åˆ¶ã€‚"
msgid "Configure the %{link} integration."
msgstr "é…ç½® %{link} 集æˆã€‚"
@@ -8526,7 +8579,7 @@ msgid "Configure the way a user creates a new account."
msgstr "é…置用户创建新å¸æˆ·çš„æ–¹å¼ã€‚"
msgid "Configure via Merge Request"
-msgstr ""
+msgstr "通过åˆå¹¶è¯·æ±‚é…ç½®"
msgid "Configure which lists are shown for anyone who visits this board"
msgstr "é…置显示给任何访问此看æ¿çš„人的列表"
@@ -8642,6 +8695,9 @@ msgstr "一致性ä¿éšœæ–¹æ³•"
msgid "Contact support"
msgstr "è”系支æŒ"
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr "容器镜åƒåº“"
@@ -8764,12 +8820,12 @@ msgstr "删除镜åƒä»“库?"
msgid "ContainerRegistry|Delete selected tags"
msgstr "删除选中的标签"
+msgid "ContainerRegistry|Delete tag"
+msgstr ""
+
msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr "删除镜åƒä»“库会删除里é¢çš„所有镜åƒå’Œæ ‡ç­¾ã€‚æ­¤æ“作无法撤消。请输入以下内容进行确认: %{code}"
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
-msgstr "由于缺少æƒé™æˆ–æƒé™ä¸è¶³ï¼Œåˆ é™¤åŠŸèƒ½å·²ç¦ç”¨ã€‚"
-
msgid "ContainerRegistry|Digest: %{imageId}"
msgstr "摘è¦: %{imageId}"
@@ -8963,8 +9019,8 @@ msgstr "此项目的标签清ç†ç­–略未å¯ç”¨ã€‚"
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„筛选器。"
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
-msgstr "当å‰æ— æ³•è¿žæŽ¥åˆ°é•œåƒåº“,原因å¯èƒ½æ˜¯é¡¹ç›®å称或路径的问题。%{docLinkStart}更多信æ¯%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
+msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr "在容器镜åƒåº“中,æ¯ä¸ªé¡¹ç›®éƒ½æœ‰è‡ªå·±çš„空间æ¥å­˜å‚¨å®¹å™¨é•œåƒã€‚ %{docLinkStart}更多信æ¯%{docLinkEnd}"
@@ -8987,14 +9043,11 @@ msgstr "您将è¦åˆ é™¤ä»“库%{title}。确认åŽï¼Œæ­¤ä»“库将被永久删除ã
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr "您å¯ä»¥é€šè¿‡ä»¥ä¸‹å‘½ä»¤å°†é•œåƒæ·»åŠ åˆ°å®¹å™¨é•œåƒåº“:"
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr "包å«é•œåƒ(%{size})çš„%{count}个blob"
-
msgid "Content parsed with %{link}."
msgstr "%{link}解æžçš„内容。"
msgid "ContentEditor|Table of Contents"
-msgstr ""
+msgstr "目录列表"
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr "您必须æä¾›renderMarkdown 函数或自定义åºåˆ—化程åº"
@@ -9110,9 +9163,6 @@ msgstr "å¤åˆ¶ %{name}"
msgid "Copy %{protocol} clone URL"
msgstr "å¤åˆ¶ %{protocol} 克隆URL"
-msgid "Copy %{proxy_url}"
-msgstr "å¤åˆ¶%{proxy_url}"
-
msgid "Copy %{type}"
msgstr "å¤åˆ¶%{type}"
@@ -9182,9 +9232,6 @@ msgstr "å¤åˆ¶é“¾æŽ¥"
msgid "Copy link to chart"
msgstr "å¤åˆ¶å›¾è¡¨çš„链接"
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr "å¤åˆ¶å‚ç…§"
@@ -9216,7 +9263,7 @@ msgid "Copy value"
msgstr "å¤åˆ¶å€¼"
msgid "Corpus Management"
-msgstr ""
+msgstr "语料库管ç†"
msgid "Corpus Management|Are you sure you want to delete the corpus?"
msgstr "确定è¦åˆ é™¤è¯­æ–™åº“å—?"
@@ -9269,9 +9316,6 @@ msgstr "无法将管ç†å‘˜æ·»åŠ ä¸ºæˆå‘˜"
msgid "Could not apply %{name} command."
msgstr "无法应用 %{name} 命令。"
-msgid "Could not archive %{design}. Please try again."
-msgstr "无法归档%{design}。请é‡è¯•ã€‚"
-
msgid "Could not authorize chat nickname. Try again!"
msgstr "无法授æƒèŠå¤©æ˜µç§°ã€‚å†è¯•ä¸€æ¬¡ï¼"
@@ -9377,6 +9421,9 @@ msgstr "无法上传您的设计,因为ä¸æ”¯æŒå·²ä¸Šä¼ ä¸€ä¸ªæˆ–多个的文
msgid "Couldn't assign policy to project"
msgstr "无法将策略分é…给项目"
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr "覆盖率"
@@ -9395,6 +9442,9 @@ msgstr "创建%{humanized_resource_name}"
msgid "Create %{type}"
msgstr "创建%{type}"
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "创建新目录"
@@ -9407,9 +9457,6 @@ msgstr "请先创建一个GitLabå¸æˆ·ï¼Œç„¶åŽå°†å…¶è¿žæŽ¥åˆ°æ‚¨çš„ %{label} å¸
msgid "Create a Mattermost team for this group"
msgstr "为这个群组创建一个Mattermost团队"
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr "创建本地代ç†ï¼Œç”¨äºŽå­˜å‚¨å¸¸ç”¨çš„上游镜åƒã€‚%{link_start}了解更多%{link_end}关于ä¾èµ–项代ç†çš„内容。"
-
msgid "Create a merge request"
msgstr "创建一个åˆå¹¶ç”³è¯·"
@@ -9425,6 +9472,9 @@ msgstr "当å‰æ— æ–‡ä»¶ã€‚请先创建一个新文件。然åŽæ‚¨å°†èƒ½å¤Ÿæ交
msgid "Create a new issue"
msgstr "创建新议题"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr "创建一个新仓库"
@@ -9447,7 +9497,7 @@ msgid "Create commit"
msgstr "创建æ交"
msgid "Create common files more quickly, and standardize their format."
-msgstr ""
+msgstr "更快地创建共åŒæ–‡ä»¶å¹¶ä½¿å…¶æ ¼å¼æ ‡å‡†åŒ–。"
msgid "Create confidential merge request"
msgstr "创建ç§å¯†åˆå¹¶è¯·æ±‚"
@@ -9483,7 +9533,7 @@ msgid "Create issue"
msgstr "创建议题"
msgid "Create issue to resolve all threads"
-msgstr ""
+msgstr "创建议题æ¥è§£å†³æ‰€æœ‰ä¸»é¢˜"
msgid "Create iteration"
msgstr "创建迭代"
@@ -9540,7 +9590,7 @@ msgid "Create new..."
msgstr "创建..."
msgid "Create or import your first project"
-msgstr ""
+msgstr "创建或导入您的第一个项目"
msgid "Create project"
msgstr "新建项目"
@@ -9560,6 +9610,9 @@ msgstr "创建代ç ç‰‡æ–­"
msgid "Create tag %{tagName}"
msgstr "创建标签 %{tagName}"
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr "创建用户"
@@ -9677,8 +9730,8 @@ msgstr "æ¢å¤é»˜è®¤å€¼"
msgid "CreateValueStreamForm|Restore stage"
msgstr "æ¢å¤é˜¶æ®µ"
-msgid "CreateValueStreamForm|Save Value Stream"
-msgstr "ä¿å­˜ä»·å€¼æµ"
+msgid "CreateValueStreamForm|Save value stream"
+msgstr ""
msgid "CreateValueStreamForm|Select end event"
msgstr "选择结æŸäº‹ä»¶"
@@ -9800,11 +9853,8 @@ msgstr "个人访问令牌"
msgid "CredentialsInventory|SSH Keys"
msgstr "SSH密钥"
-msgid "Credit card validated at:"
-msgstr "信用å¡æœ‰æ•ˆæœŸï¼š"
-
-msgid "Credit card validated:"
-msgstr "信用å¡å·²éªŒè¯ï¼š"
+msgid "Credit card:"
+msgstr ""
msgid "Critical vulnerabilities present"
msgstr "存在严é‡æ¼æ´ž"
@@ -9860,6 +9910,9 @@ msgstr "当å‰ç™»å½•IP:"
msgid "Current sign-in at:"
msgstr "当å‰ç™»å½•äºŽï¼š"
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr "当å‰æ¼æ´žæ•°é‡"
@@ -9900,7 +9953,7 @@ msgid "Custom notification events"
msgstr "自定义通知事件"
msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notificationLinkStart}notification emails%{notificationLinkEnd}."
-msgstr ""
+msgstr "自定义通知级别与å‚与级别相åŒã€‚使用自定义通知级别,您还将收到选定事件的通知。è¦äº†è§£æ›´å¤šä¿¡æ¯ï¼Œè¯·æŸ¥çœ‹ %{notificationLinkStart}通知电å­é‚®ä»¶%{notificationLinkEnd}。"
msgid "Custom project templates"
msgstr "自定义项目模æ¿"
@@ -9914,6 +9967,15 @@ msgstr "自定义范围"
msgid "Custom range (UTC)"
msgstr "自定义范围 (UTC)"
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr "å¯ç”±ç®¡ç†å‘˜è‡ªå®šä¹‰ã€‚"
@@ -10073,6 +10135,9 @@ msgstr "完æˆæ‰€éœ€å¤©æ•°"
msgid "CycleAnalytics|Display chart filters"
msgstr "显示图表筛选器"
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr "未选择阶段"
@@ -10097,10 +10162,10 @@ msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCo
msgstr[0] "显示 %{subjectFilterText} 和 %{selectedLabelsCount} 标记"
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
-msgstr ""
+msgstr "显示群组“%{groupName}â€å’Œ%{selectedProjectCount}个项目从%{createdAfter}到%{createdBefore}çš„æ•°æ®"
msgid "CycleAnalytics|Showing data for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
-msgstr ""
+msgstr "显示群组“%{groupName}â€ä»Ž%{createdAfter}到%{createdBefore}çš„æ•°æ®"
msgid "CycleAnalytics|Stages"
msgstr "阶段"
@@ -10138,6 +10203,9 @@ msgstr "DAST é…ç½®"
msgid "DAST Scans"
msgstr "DAST 扫æ"
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10334,7 +10402,7 @@ msgid "DastProfiles|Manage profiles"
msgstr "管ç†é…ç½®"
msgid "DastProfiles|Manage site profiles"
-msgstr ""
+msgstr "管ç†ç«™ç‚¹é…置文件"
msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
msgstr "æœ€å° = 0 (无超时),最大 = 2880 分钟"
@@ -10412,7 +10480,7 @@ msgid "DastProfiles|Scanner name"
msgstr "扫æ工具å称"
msgid "DastProfiles|Schedule"
-msgstr ""
+msgstr "计划"
msgid "DastProfiles|Select branch"
msgstr "选择分支"
@@ -10484,7 +10552,7 @@ msgid "DastProfiles|Website"
msgstr "网站"
msgid "DastProfiles|You can either choose a passive scan or validate the target site from the site profile management page. %{docsLinkStart}Learn more about site validation.%{docsLinkEnd}"
-msgstr ""
+msgstr "您å¯ä»¥é€‰æ‹©è¢«åŠ¨æ‰«æ或从站点é…置文件管ç†é¡µé¢éªŒè¯ç›®æ ‡ç«™ç‚¹ã€‚ %{docsLinkStart}了解有关站点验è¯çš„更多信æ¯ã€‚%{docsLinkEnd}"
msgid "DastProfiles|You cannot run an active scan against an unvalidated site."
msgstr "ä¸èƒ½å¯¹æœªç»éªŒè¯çš„站点è¿è¡Œä¸»åŠ¨æ‰«æ。"
@@ -10631,6 +10699,9 @@ msgstr "日期选择器"
msgid "Date range"
msgstr "日期范围"
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr "日期范围必须å°äºŽ %{max_range} 天。"
@@ -10656,7 +10727,7 @@ msgid "Days to merge"
msgstr "åˆå¹¶æ‰€éœ€å¤©æ•°"
msgid "Deactivate dormant users after 90 days of inactivity"
-msgstr ""
+msgstr "闲置 90 天åŽåœç”¨ä¼‘眠用户"
msgid "Dear Administrator,"
msgstr "亲爱的管ç†å‘˜ï¼Œ"
@@ -10697,6 +10768,9 @@ msgstr "默认分支"
msgid "Default branch and protected branches"
msgstr "默认分支和å—ä¿æŠ¤çš„分支"
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr "默认分类标记"
@@ -10736,18 +10810,36 @@ msgstr "默认:将FogBugzå¸æˆ·ID映射为全å"
msgid "DefaultBranchLabel|default"
msgstr "default"
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
-msgstr "使用%{cronSyntaxStart}cron语法%{cronSyntaxEnd}定义自定义部署冻结模å¼"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
+msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "使用 Cron 语法定义自定义模å¼"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
msgstr ""
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr "使用%{cronSyntaxStart}cron语法%{cronSyntaxEnd}定义自定义部署冻结模å¼"
+
+msgid "Define a custom pattern with cron syntax"
+msgstr "使用 Cron 语法定义自定义模å¼"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr "定义独立于Akismet的垃圾邮件自定义规则"
@@ -10755,7 +10847,7 @@ msgid "Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%
msgstr "在%{code_open}.githab-ci.yml%{code_close}的部署阶段中定义环境æ¥è·Ÿè¸ªéƒ¨ç½²ã€‚"
msgid "Define how approval rules are applied to merge requests."
-msgstr ""
+msgstr "定义审核规则如何应用于åˆå¹¶è¯·æ±‚。"
msgid "Definition"
msgstr "定义"
@@ -10770,10 +10862,10 @@ msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This jo
msgstr "您确定è¦ç«‹å³è¿è¡Œ %{job_name} å—?该作业将在计时结æŸåŽè‡ªåŠ¨è¿è¡Œã€‚"
msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after its timer finishes."
-msgstr ""
+msgstr "您确定è¦ç«‹å³è¿è¡Œ %{job_name} å—?该作业将在计时器结æŸåŽè‡ªåŠ¨è¿è¡Œã€‚"
msgid "DelayedJobs|Run the delayed job now?"
-msgstr ""
+msgstr "现在è¿è¡Œå»¶è¿Ÿä½œä¸šå—?"
msgid "DelayedJobs|Start now"
msgstr "ç«‹å³å¼€å§‹"
@@ -10820,9 +10912,6 @@ msgstr "删除评论"
msgid "Delete corpus"
msgstr "删除语料库"
-msgid "Delete domain"
-msgstr "删除域"
-
msgid "Delete file"
msgstr "删除文件"
@@ -10850,9 +10939,6 @@ msgstr "删除行"
msgid "Delete self monitoring project"
msgstr "删除自监控项目"
-msgid "Delete serverless domain?"
-msgstr "删除无æœåŠ¡å™¨çš„域å?"
-
msgid "Delete snippet"
msgstr "删除代ç ç‰‡æ®µ"
@@ -10880,6 +10966,9 @@ msgstr "删除用户列表"
msgid "Delete variable"
msgstr "删除å˜é‡"
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "删除项目仓库失败。请é‡è¯•æˆ–è”系管ç†å‘˜ã€‚"
@@ -11039,23 +11128,35 @@ msgstr "ä¾èµ–项代ç†"
msgid "Dependency Scanning"
msgstr "ä¾èµ–项扫æ"
-msgid "Dependency proxy"
-msgstr "ä¾èµ–项代ç†"
+msgid "DependencyProxy|Cached %{time}"
+msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
-msgstr "ä¾èµ–项代ç†åŠŸèƒ½ç›®å‰ä»…é™äºŽå…¬å¼€ç¾¤ç»„。"
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
+msgstr ""
-msgid "Dependency proxy image prefix"
-msgstr "ä¾èµ–代ç†é•œåƒå‰ç¼€"
+msgid "DependencyProxy|Copy prefix"
+msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
-msgstr ""
+msgstr "创建一个本地代ç†ï¼Œç”¨äºŽå­˜å‚¨é¢‘ç¹ä½¿ç”¨çš„上游镜åƒã€‚ %{docLinkStart}了解更多%{docLinkEnd} 关于ä¾èµ–代ç†çš„内容。"
msgid "DependencyProxy|Dependency Proxy"
+msgstr "ä¾èµ–代ç†"
+
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
-msgstr " 开关ä¾èµ–项代ç†"
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
+msgstr ""
msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
@@ -11292,7 +11393,7 @@ msgid "Deployments"
msgstr "部署"
msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
+msgstr "Google Kubernetes Engine 的部署å¯ä»¥æ˜¯ "
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
@@ -11323,7 +11424,7 @@ msgid "Deployment|success"
msgstr "æˆåŠŸ"
msgid "Deprecated API rate limits"
-msgstr ""
+msgstr "已弃用的 API 速率é™åˆ¶"
msgid "Deprioritize label"
msgstr "å–消优先标记"
@@ -11368,7 +11469,8 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr "%{current_design}/%{designs_count}"
msgid "DesignManagement|%{filename} did not change."
-msgstr "%{filename}æ— å˜åŒ–。"
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "添加具有相åŒæ–‡ä»¶å的设计会替æ¢ä¸ºæ–°ç‰ˆæœ¬çš„文件。"
@@ -11472,6 +11574,12 @@ msgstr "ä¿å­˜è¯„论"
msgid "DesignManagement|Select all"
msgstr "选择全部"
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr "å…许上传的设计最大数é‡ä¸º %{upload_limit}。请å†è¯•ä¸€æ¬¡ã€‚"
@@ -11487,15 +11595,12 @@ msgstr "将主题置为未解决"
msgid "DesignManagement|Upload designs"
msgstr "上传设计"
-msgid "DesignManagement|Upload skipped."
-msgstr "上传已跳过。"
+msgid "DesignManagement|Upload skipped. %{reason}"
+msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr "您的设计正在å¤åˆ¶è¿‡ç¨‹ä¸­â€¦ 请刷新以获得更新。"
-msgid "DesignManagement|and %{moreCount} more."
-msgstr "以åŠå…¶ä½™%{moreCount}项。"
-
msgid "Designs"
msgstr "设计"
@@ -11547,6 +11652,9 @@ msgstr "按群组采用"
msgid "DevopsAdoption|Adoption by subgroup"
msgstr "按å­ç»„采用"
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr "删除群组时出错,请é‡è¯•ã€‚"
@@ -11625,6 +11733,9 @@ msgstr "åˆå¹¶è¯·æ±‚"
msgid "DevopsAdoption|No results…"
msgstr "没有结果…"
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr "未采用"
@@ -11670,6 +11781,9 @@ msgstr "获å–群组时å‘生错误,请刷新页é¢ã€‚"
msgid "DevopsAdoption|This group has no subgroups"
msgstr "此群组没有å­ç¾¤ç»„"
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr "您ä¸èƒ½åˆ é™¤æ‚¨å½“å‰æ‰€åœ¨çš„群组。"
@@ -11729,11 +11843,11 @@ msgstr "(æº)"
msgid "Diffs|%d addition"
msgid_plural "Diffs|%d additions"
-msgstr[0] ""
+msgstr[0] "%d 个添加"
msgid "Diffs|%d deletion"
msgid_plural "Diffs|%d deletions"
-msgstr[0] ""
+msgstr[0] "%d 个删除"
msgid "Diffs|No file name available"
msgstr "æ— å¯ç”¨çš„文件å"
@@ -11746,13 +11860,13 @@ msgstr "显示所有未改å˜çš„è¡Œ"
msgid "Diffs|Showing %{dropdownStart}%{count} changed file%{dropdownEnd}"
msgid_plural "Diffs|Showing %{dropdownStart}%{count} changed files%{dropdownEnd}"
-msgstr[0] ""
+msgstr[0] "显示 %{dropdownStart}%{count} 个更改的文件%{dropdownEnd}"
msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "获å–差异线时å‘生错误。"
msgid "Diffs|with %{additions} and %{deletions}"
-msgstr ""
+msgstr "有 %{additions} 和 %{deletions}"
msgid "Direct member"
msgstr "直接æˆå‘˜"
@@ -11853,12 +11967,6 @@ msgstr "开始å…费试用"
msgid "Discover|Upgrade now"
msgstr "ç«‹å³å‡çº§"
-msgid "Discuss a specific suggestion or question"
-msgstr "讨论具体的建议或议题"
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr "讨论需è¦è§£å†³çš„具体建议或议题"
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr "讨论需è¦è§£å†³çš„具体建议或问题。"
@@ -11882,7 +11990,7 @@ msgid "Dismiss merge request promotion"
msgstr "关闭åˆå¹¶è¯·æ±‚推è"
msgid "Dismiss selected"
-msgstr "å–消选择"
+msgstr "忽略选å–项目"
msgid "Dismiss trial promotion"
msgstr "关闭试用推è"
@@ -11950,18 +12058,6 @@ msgstr "域å"
msgid "Domain Name"
msgstr "域å"
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr "如已关è”到一个或多个集群,则域ä¸èƒ½åˆ é™¤ã€‚"
-
-msgid "Domain was successfully created."
-msgstr "域å已创建æˆåŠŸã€‚"
-
-msgid "Domain was successfully deleted."
-msgstr "域åå·²æˆåŠŸåˆ é™¤ã€‚"
-
-msgid "Domain was successfully updated."
-msgstr "域åå·²æˆåŠŸæ›´æ–°ã€‚"
-
msgid "Don't have an account yet?"
msgstr "还没有账户?"
@@ -11992,9 +12088,6 @@ msgstr "下载%{format}"
msgid "Download %{format}:"
msgstr "下载%{format}:"
-msgid "Download %{name} artifact"
-msgstr "下载%{name}产物"
-
msgid "Download (%{fileSizeReadable})"
msgstr "下载(%{fileSizeReadable})"
@@ -12200,7 +12293,7 @@ msgid "Edit issues"
msgstr "编辑议题"
msgid "Edit merge requests"
-msgstr ""
+msgstr "编辑åˆå¹¶è¯·æ±‚"
msgid "Edit public deploy key"
msgstr "编辑公共部署密钥"
@@ -12220,6 +12313,9 @@ msgstr "编辑此å‘布"
msgid "Edit title and description"
msgstr "编辑标题和æè¿°"
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr "编辑用户:%{user_name}"
@@ -12278,7 +12374,7 @@ msgid "Elastic|None. Select projects to index."
msgstr "无。请选择è¦å»ºç«‹ç´¢å¼•çš„项目。"
msgid "Eligible users"
-msgstr ""
+msgstr "符åˆæ¡ä»¶çš„用户"
msgid "Email"
msgstr "电å­é‚®ä»¶"
@@ -12410,7 +12506,7 @@ msgid "Enable"
msgstr "å¯ç”¨"
msgid "Enable Amazon EKS integration"
-msgstr ""
+msgstr "å¯ç”¨ Amazon EKS 集æˆ"
msgid "Enable Auto DevOps"
msgstr "å¯ç”¨Auto DevOps"
@@ -12446,7 +12542,7 @@ msgid "Enable SSL verification"
msgstr "å¯ç”¨ SSL 验è¯"
msgid "Enable Service Ping"
-msgstr ""
+msgstr "å¯ç”¨æœåŠ¡Ping"
msgid "Enable Snowplow tracking"
msgstr "å¯ç”¨Snowplow跟踪"
@@ -12479,7 +12575,7 @@ msgid "Enable authenticated Git LFS request rate limit"
msgstr "å¯ç”¨è®¤è¯çš„ Git LFS 请求速率é™åˆ¶"
msgid "Enable authenticated web request rate limit"
-msgstr ""
+msgstr "å¯ç”¨ç»è¿‡èº«ä»½éªŒè¯çš„ Web 请求速率é™åˆ¶"
msgid "Enable authentication"
msgstr "å¯ç”¨èº«ä»½éªŒè¯"
@@ -12542,19 +12638,16 @@ msgid "Enable or disable the Pseudonymizer data collection."
msgstr "å¯ç”¨æˆ–ç¦ç”¨åŒ¿å化数æ®æ”¶é›†."
msgid "Enable or disable version check and Service Ping."
-msgstr ""
+msgstr "å¯ç”¨æˆ–ç¦ç”¨ç‰ˆæœ¬æ£€æŸ¥å’ŒæœåŠ¡Ping。"
-msgid "Enable protected paths rate limit"
-msgstr "å¯ç”¨ä¿æŠ¤è·¯å¾„速率é™åˆ¶"
-
-msgid "Enable proxy"
-msgstr "å¯ç”¨ä»£ç†"
+msgid "Enable rate limiting for POST requests to the specified paths"
+msgstr ""
msgid "Enable reCAPTCHA"
msgstr "å¯ç”¨ reCAPTCHA"
msgid "Enable reCAPTCHA for login."
-msgstr ""
+msgstr "å¯ç”¨ reCAPTCHA 进行登录。"
msgid "Enable repository checks"
msgstr "å¯ç”¨ä»“库检查"
@@ -12581,10 +12674,10 @@ msgid "Enable unauthenticated API request rate limit"
msgstr "å¯ç”¨æœªç»èº«ä»½éªŒè¯çš„ API 请求速率é™åˆ¶"
msgid "Enable unauthenticated web request rate limit"
-msgstr ""
+msgstr "å¯ç”¨æœªç»èº«ä»½éªŒè¯çš„ Web 请求速率é™åˆ¶"
msgid "Enable user deactivation emails"
-msgstr ""
+msgstr "å¯ç”¨ç”¨æˆ·åœç”¨ç”µå­é‚®ä»¶"
msgid "Enable version check"
msgstr "å¯ç”¨ç‰ˆæœ¬æ£€æŸ¥"
@@ -12673,8 +12766,11 @@ msgstr "输入数字"
msgid "Enter an integer number between 0 and 100"
msgstr "输入介于0到100之间的整数"
-msgid "Enter an integer number number between 0 and 100"
-msgstr "输入一个介于0到100之间的整数"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
+msgstr ""
msgid "Enter at least three characters to search"
msgstr "请至少输入三个字符æ‰å¯æœç´¢"
@@ -12728,7 +12824,8 @@ msgid "Enterprise"
msgstr "ä¼ä¸š"
msgid "Environment"
-msgstr "环境"
+msgid_plural "Environments"
+msgstr[0] ""
msgid "Environment does not have deployments"
msgstr "环境没有部署"
@@ -12829,8 +12926,8 @@ msgstr "终止环境时å‘生错误,请ç¨åŽé‡è¯•"
msgid "Environments|Are you sure you want to stop this environment?"
msgstr "是å¦ç¡®å®šç»ˆæ­¢å½“å‰çŽ¯å¢ƒï¼Ÿ"
-msgid "Environments|Auto stop in"
-msgstr "自动终止于"
+msgid "Environments|Auto stop"
+msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
msgstr "自动åœæ­¢äºŽ %{autoStopAt}"
@@ -12914,7 +13011,7 @@ msgid "Environments|Note that this action will stop the environment, but it will
msgstr "注æ„:继续æ“作将终止当å‰çŽ¯å¢ƒï¼ç”±äºŽæœªåœ¨%{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd}文件中定义“终止环境æ“作â€ï¼Œå› æ­¤%{emphasisStart}ä¸ä¼š%{emphasisEnd}å½±å“å·²ç»å­˜åœ¨çš„部署。"
msgid "Environments|Open"
-msgstr ""
+msgstr "打开"
msgid "Environments|Open live environment"
msgstr "打开è¿è¡Œä¸­çš„环境"
@@ -13129,6 +13226,9 @@ msgstr "创建 å²è¯— 时出错"
msgid "Error creating label."
msgstr "创建标记时出错。"
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr "创建新迭代时出错"
@@ -13259,7 +13359,7 @@ msgid "Error parsing CSV file. Please make sure it has"
msgstr "解æžCSV文件时出错。请确认它是å¦åŒ…å«"
msgid "Error rendering Markdown preview"
-msgstr ""
+msgstr "渲染Markdown预览出错"
msgid "Error saving label update."
msgstr "ä¿å­˜æ ‡è®°æ›´æ–°æ—¶å‡ºé”™ã€‚"
@@ -13306,9 +13406,12 @@ msgstr "Akismet 错误。请检查日志以获å–更多信æ¯ã€‚"
msgid "Error: %{error_message}"
msgstr "错误: %{error_message}"
-msgid "Error: Couldn't load some or all of the changes."
+msgid "Error: %{error}"
msgstr ""
+msgid "Error: Couldn't load some or all of the changes."
+msgstr "错误:无法加载部分或全部更改。"
+
msgid "Error: No AWS credentials were supplied"
msgstr "错误:未æ供任何AWS凭æ®"
@@ -13343,7 +13446,7 @@ msgid "ErrorTracking|Enable error tracking"
msgstr "å¯ç”¨é”™è¯¯è·Ÿè¸ª"
msgid "ErrorTracking|Error tracking backend"
-msgstr ""
+msgstr "错误跟踪åŽç«¯"
msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr "如果您自托管 Sentry,请输入您的 Sentry 实例的完整 URL。如果您使用 Sentry 的托管解决方案,请输入 https://sentry.io"
@@ -13379,10 +13482,10 @@ msgid "Escalation policies must have at least one rule"
msgstr "å‡çº§ç­–略必须至少有一个规则"
msgid "EscalationPolicies|%{clockIcon} IF alert is not %{alertStatus} in %{minutes}"
-msgstr ""
+msgstr "%{clockIcon}如果警报在%{minutes}分钟内ä¸æ˜¯%{alertStatus}"
msgid "EscalationPolicies|%{notificationIcon} THEN %{doAction} %{forScheduleOrUser}"
-msgstr ""
+msgstr "%{notificationIcon} 那么 %{doAction} %{forScheduleOrUser}"
msgid "EscalationPolicies|+ Add an additional rule"
msgstr "+ 添加附加规则"
@@ -13427,7 +13530,7 @@ msgid "EscalationPolicies|Escalation policies"
msgstr "å‡çº§ç­–ç•¥"
msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
-msgstr ""
+msgstr "项目 %{project} çš„å‡çº§ç­–ç•¥ %{obstacle}"
msgid "EscalationPolicies|Escalation rules"
msgstr "å‡çº§è§„则"
@@ -13511,16 +13614,16 @@ msgid "Every %{action} attempt has failed: %{job_error_message}. Please try agai
msgstr "所有 %{action} å°è¯•éƒ½å·²å¤±è´¥ï¼š %{job_error_message}。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "Every 3 months"
-msgstr ""
+msgstr "æ¯ 3 个月"
msgid "Every 3 months on the %{day} at %{time} %{timezone}"
-msgstr ""
+msgstr "æ¯ä¸‰ä¸ªæœˆåœ¨ %{day} çš„ %{time} %{timezone}"
msgid "Every 6 months"
-msgstr ""
+msgstr "æ¯ 6 个月"
msgid "Every 6 months on the %{day} at %{time} %{timezone}"
-msgstr ""
+msgstr "æ¯ 6 个月在 %{day} 在 %{time} %{timezone}"
msgid "Every day"
msgstr "æ¯å¤©"
@@ -13529,7 +13632,7 @@ msgid "Every day (at %{time})"
msgstr "æ¯å¤©(%{time})"
msgid "Every day at %{time} %{timezone}"
-msgstr ""
+msgstr "æ¯å¤©åœ¨ %{time} %{timezone}"
msgid "Every month"
msgstr "æ¯æœˆ"
@@ -13538,7 +13641,7 @@ msgid "Every month (Day %{day} at %{time})"
msgstr "æ¯æœˆ(%{day}日的%{time})"
msgid "Every month on the %{day} at %{time} %{timezone}"
-msgstr ""
+msgstr "æ¯æœˆåœ¨ %{day} çš„ %{time} %{timezone}"
msgid "Every three months"
msgstr "æ¯ä¸‰ä¸ªæœˆ"
@@ -13554,13 +13657,13 @@ msgid "Every week (%{weekday} at %{time})"
msgstr "æ¯å‘¨(%{weekday}çš„%{time})"
msgid "Every week on %{day} at %{time} %{timezone}"
-msgstr ""
+msgstr "æ¯ä¸ªæ˜ŸæœŸåœ¨ %{day} çš„ %{time} %{timezone}"
msgid "Every year"
-msgstr ""
+msgstr "æ¯å¹´"
msgid "Every year on %{day} at %{time} %{timezone}"
-msgstr ""
+msgstr "æ¯å¹´åœ¨ %{day} çš„ %{time} %{timezone}"
msgid "Everyone"
msgstr "所有人"
@@ -13601,9 +13704,6 @@ msgstr "其中的一个%{attributes}是必需的"
msgid "Example: @sub\\.company\\.com$"
msgstr "示例: @sub\\.company\\.com$"
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr "示例:使用é‡=å•ä¸€æŸ¥è¯¢ã€‚(请求)/(容é‡)=å½¢æˆå…¬å¼çš„多é‡æŸ¥è¯¢ã€‚"
-
msgid "Except policy:"
msgstr "除外(Except)æ¡ä»¶ï¼š"
@@ -13665,7 +13765,7 @@ msgid "Expand pipeline"
msgstr "展开æµæ°´çº¿"
msgid "Expand settings section"
-msgstr ""
+msgstr "展开设置部分"
msgid "Expand sidebar"
msgstr "展开侧边æ "
@@ -13685,6 +13785,9 @@ msgstr "到期时间"
msgid "Expiration date (optional)"
msgstr "过期日期 (å¯é€‰)"
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr "已过期"
@@ -13700,6 +13803,9 @@ msgstr "到期"
msgid "Expires in %{expires_at}"
msgstr "在 %{expires_at} 过期"
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr "到期时间:"
@@ -13727,9 +13833,6 @@ msgstr "æµè§ˆå…¬å¼€ç¾¤ç»„"
msgid "Export"
msgstr "导出"
-msgid "Export %{name}"
-msgstr "导出 %{name}"
-
msgid "Export %{requirementsCount} requirements?"
msgstr "导出 %{requirementsCount} 个需求?"
@@ -13742,6 +13845,12 @@ msgstr "导出æ交监管报告"
msgid "Export group"
msgstr "导出群组"
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr "导出项目"
@@ -13826,6 +13935,10 @@ msgstr "无法添加Zoom会议"
msgid "Failed to apply commands."
msgstr "应用命令失败。"
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr "由于未找到用户,因此无法指派审核者。"
@@ -14060,9 +14173,6 @@ msgstr "å‡çº§å¤±è´¥ã€‚"
msgid "Failed to upload object map file"
msgstr "上传对象映射文件失败"
-msgid "Failed to verify domain ownership"
-msgstr "验è¯åŸŸå所有æƒå¤±è´¥"
-
msgid "Failure"
msgstr "失败"
@@ -14253,6 +14363,9 @@ msgstr "百分比上线必须是0-100之间的整数"
msgid "FeatureFlags|Remove"
msgstr "删除"
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr "设置Unleash客户端应用å称为应用程åºè¿è¡Œçš„环境å称。 此值将用于匹é…环境范围。查看 %{linkStart}客户端é…置示例%{linkEnd}。"
@@ -14378,7 +14491,7 @@ msgid "Files"
msgstr "文件"
msgid "Files API Rate Limits"
-msgstr ""
+msgstr "文件 API 速率é™åˆ¶"
msgid "Files breadcrumb"
msgstr "文件导航"
@@ -14503,6 +14616,9 @@ msgstr "已完æˆ"
msgid "Finished at"
msgstr "完æˆäºŽ"
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr "首次出现"
@@ -14734,6 +14850,9 @@ msgstr "在.gitlab-ci.yml中å‘现错误:"
msgid "Framework successfully deleted"
msgstr "框架删除æˆåŠŸ"
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr "å…费试用"
@@ -14794,6 +14913,9 @@ msgstr "常规设置"
msgid "General pipelines"
msgstr "æµæ°´çº¿é€šç”¨è®¾ç½®"
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr "生æˆä¸€ç»„默认的标记"
@@ -15370,6 +15492,9 @@ msgstr "GitLabå¸æˆ·è¯·æ±‚被拒ç»"
msgid "GitLab commit"
msgstr "GitLabæ交"
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr "GitLab导出"
@@ -15380,7 +15505,7 @@ msgid "GitLab group: %{source_link}"
msgstr "GitLab 群组:%{source_link}"
msgid "GitLab informs you if a new version is available."
-msgstr ""
+msgstr "GitLab 会通知您是å¦æœ‰æ–°ç‰ˆæœ¬å¯ç”¨ã€‚"
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr "GitLab是一个完整的DevOpså¹³å°ï¼Œä½œä¸ºå•ä¸ªåº”用程åºå‘ˆçŽ°ï¼Œä»Žæ ¹æœ¬ä¸Šæ”¹å˜äº†å¼€å‘,安全和è¿ç»´å›¢é˜Ÿçš„å作方å¼"
@@ -15398,7 +15523,7 @@ msgid "GitLab is open source software to collaborate on code."
msgstr "GitLab 是用于代ç å作的开æºè½¯ä»¶ã€‚"
msgid "GitLab is undergoing maintenance and is operating in read-only mode."
-msgstr ""
+msgstr "GitLab 正在进行维护并以åªè¯»æ¨¡å¼è¿è¡Œã€‚"
msgid "GitLab member or Email address"
msgstr "GitLabæˆå‘˜æˆ–电å­é‚®ä»¶åœ°å€"
@@ -15409,6 +15534,9 @@ msgstr "GitLab å…ƒæ•°æ® URL"
msgid "GitLab project export"
msgstr "GitLab项目导出"
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr "GitLabå•ç‚¹ç™»å½•ç½‘å€"
@@ -15424,9 +15552,6 @@ msgstr "GitLab 使用 %{linkStart}Sidekiq%{linkEnd} 处ç†åŽå°ä½œä¸š"
msgid "GitLab version"
msgstr "GitLab 版本"
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "GitLabå°†è¿è¡ŒåŽå°ä»»åŠ¡ï¼Œç”Ÿæˆæ•°æ®åº“的匿å化CSV,并上传到预先设定的对象存储目录。"
-
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -15496,11 +15621,11 @@ msgstr "ä¿å­˜æ›´æ”¹"
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr "在获å–域å%{domain}çš„Let's Encryptè¯ä¹¦æ—¶å‡ºé”™ã€‚如需é‡è¯•ï¼Œè¯·è®¿é—®æ‚¨çš„%{link_start}域详细信æ¯%{link_end}。"
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
-msgstr "域åå’Œè¯ä¹¦æ”¯æŒå·²è¢«ç¦ç”¨ã€‚请系统管ç†å‘˜å¯ç”¨ã€‚"
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
-msgstr "部署的é™æ€å†…容的总大å°å°†é™åˆ¶åœ¨æ­¤å¤§å°ã€‚0为无é™ã€‚留空则继承全局设置。"
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgstr ""
msgid "GitLabPages|Unverified"
msgstr "未验è¯"
@@ -15547,6 +15672,9 @@ msgstr "从Gitea导入"
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr "创建一个具有%{status_html}访问æƒé™çš„%{token_link_start}个人访问令牌%{token_link_end},并将其粘贴到此处。"
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr "获å–æ交和拉å–请求的状æ€ã€‚"
@@ -15689,19 +15817,19 @@ msgid "Go to snippets"
msgstr "转到代ç ç‰‡æ®µ"
msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check 'Allowed domains for sign-ups'."
-msgstr ""
+msgstr "转到“管ç†ä¸­å¿ƒ &gt; 注册é™åˆ¶â€ï¼Œç„¶åŽé€‰ä¸­â€œå…许注册的域â€ã€‚"
msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check 'Email restrictions for sign-ups'."
-msgstr ""
+msgstr "转到“管ç†ä¸­å¿ƒ &gt; 注册é™åˆ¶â€ï¼Œç„¶åŽé€‰ä¸­â€œç¦æ­¢ä»¥ä¸‹é‚®ç®±æ³¨å†Œâ€ã€‚"
msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check the 'Domain denylist'."
-msgstr ""
+msgstr "转到“管ç†ä¸­å¿ƒ &gt; 注册é™åˆ¶â€ï¼Œç„¶åŽé€‰ä¸­â€œåŸŸå黑åå•â€ã€‚"
msgid "Go to the activity feed"
msgstr "转到动æ€æº"
msgid "Go to the group’s 'Settings &gt; General' page, and check 'Restrict membership by email domain'."
-msgstr ""
+msgstr "转到组的“设置 &gt; 通用â€é¡µé¢ï¼Œç„¶åŽé€‰ä¸­â€œé€šè¿‡ç”µå­é‚®ä»¶åŸŸé™åˆ¶æˆå‘˜èµ„æ ¼â€ã€‚"
msgid "Go to the milestone list"
msgstr "转到里程碑列表"
@@ -15740,10 +15868,10 @@ msgid "Goal of the changes and what reviewers should be aware of"
msgstr "å˜æ›´çš„目的以åŠè¯„审人员应注æ„的事项。"
msgid "Google Cloud"
-msgstr ""
+msgstr "Google Cloud"
msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
-msgstr ""
+msgstr "Google Cloud æ供了多个部署目标,选择一个最适åˆæ‚¨çš„项目。"
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
msgstr "谷歌的身份验è¯æœª%{link_start}正确é…ç½®%{link_end}。如需使用这项æœåŠ¡ï¼Œè¯·è”ç³»GitLab管ç†å‘˜ã€‚"
@@ -15856,6 +15984,9 @@ msgstr "群组头åƒ"
msgid "Group by"
msgstr "分组方å¼"
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr "群组æ述(å¯é€‰ï¼‰"
@@ -16004,10 +16135,10 @@ msgid "GroupImport|Unable to process group import file"
msgstr "无法处ç†ç¾¤ç»„导入文件"
msgid "GroupPage|Copy group ID"
-msgstr ""
+msgstr "å¤åˆ¶ç¾¤ç»„ ID"
msgid "GroupPage|Group ID: %{group_id}"
-msgstr ""
+msgstr "群组 ID: %{group_id}"
msgid "GroupRoadmap|%{dateWord} – No end date"
msgstr "%{dateWord} - 无结æŸæ—¥æœŸ"
@@ -16024,12 +16155,6 @@ msgstr "无开始和结æŸæ—¥æœŸ"
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr "无开始日期 - %{dateWord}"
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr "路线图最多å¯ä»¥æ˜¾ç¤º1,000个å²è¯—。这些按您选择的排åºé¡ºåºæ˜¾ç¤ºã€‚"
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr "您的一些å²è¯—å¯èƒ½ä¸å¯è§"
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "è¯»å– å²è¯— 时出错"
@@ -16064,7 +16189,7 @@ msgid "GroupRoadmap|Within 3 years"
msgstr "3年内"
msgid "GroupSAML|\"persistent\" recommended"
-msgstr ""
+msgstr "推è“æŒä¹…化â€"
msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
msgstr "%{strongOpen}警告%{strongClose} - å¯ç”¨ %{linkStart}SSO 执行%{linkEnd} å¯ä»¥é™ä½Žå®‰å…¨é£Žé™©ã€‚"
@@ -16199,7 +16324,7 @@ msgid "GroupSAML|To be able to prohibit outer forks, you first need to enforce d
msgstr "如需ç¦æ­¢å¤–部派生,您首先需è¦å¼ºåˆ¶æ‰§è¡ŒæŒ‡å®šç¾¤ç»„托管账户。"
msgid "GroupSAML|Use SAML group links to manage group membership using SAML."
-msgstr ""
+msgstr "使用 SAML 群组链接æ¥ç®¡ç†ä½¿ç”¨ SAML 的群组æˆå‘˜èµ„格。"
msgid "GroupSAML|Valid SAML Response"
msgstr "有效的SAMLå“应"
@@ -16214,10 +16339,10 @@ msgid "GroupSAML|as %{access_level}"
msgstr "以%{access_level}身份"
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" to identify user and allow sign in"
-msgstr ""
+msgstr "必须匹é…存储的“%{extern_uid}â€çš„ NameID 以识别用户并å…许登录"
msgid "GroupSAML|recommend persistent ID instead of email"
-msgstr ""
+msgstr "建议使用æŒä¹…性 ID 而ä¸æ˜¯ç”µå­é‚®ä»¶"
msgid "GroupSelect|No matching results"
msgstr "没有匹é…的结果"
@@ -16232,13 +16357,13 @@ msgid "GroupSettings|Allow project access token creation"
msgstr "å…许创建项目访问令牌"
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
-msgstr ""
+msgstr "应用到所有å­ç¾¤ç»„,除éžè¢«ç¾¤ç»„所有者覆盖。已添加到项目的群组将失去访问æƒé™ã€‚"
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr "已为群组更新 Auto DevOps æµæ°´çº¿"
msgid "GroupSettings|Available only on the top-level group. Applies to all subgroups. Groups already shared with a group outside %{group} are still shared unless removed manually."
-msgstr ""
+msgstr "仅在顶级群组中å¯ç”¨ã€‚适用于所有å­ç»„。除éžæ‰‹åŠ¨åˆ é™¤ï¼Œå¦åˆ™ %{group} 以外的群组所共享的群组ä»ä¼šå…±äº«ã€‚"
msgid "GroupSettings|Badges"
msgstr "徽章"
@@ -16258,8 +16383,8 @@ msgstr "更改群组URLå¯èƒ½ä¼šæœ‰éžé¢„期的副作用。"
msgid "GroupSettings|Compliance frameworks"
msgstr "åˆè§„框架"
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
-msgstr "é…置框架以将å¯æ‰§è¡Œè§„则应用于项目。"
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
msgid "GroupSettings|Custom project templates"
msgstr "自定义项目模æ¿"
@@ -16292,7 +16417,7 @@ msgid "GroupSettings|New runners registration token has been generated!"
msgstr "已生æˆæ–°çš„Runner注册令牌ï¼"
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
-msgstr ""
+msgstr "覆盖群组ã€å­ç»„和项目所有æˆå‘˜çš„用户通知å好设置。"
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr "群组æµæ°´çº¿è®¾ç½®å·²æ›´æ–°"
@@ -16307,13 +16432,13 @@ msgid "GroupSettings|Prevent forking setting was not saved"
msgstr "阻止派生设置未ä¿å­˜"
msgid "GroupSettings|Prevent members from sending invitations to groups outside of %{group} and its subgroups"
-msgstr ""
+msgstr "ç¦æ­¢æˆå‘˜å‘é€é‚€è¯·åˆ° %{group} åŠå…¶å­ç¾¤ç»„。"
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "ç¦æ­¢ä¸Žå…¶ä»–群组共享 %{group} 中的项目"
msgid "GroupSettings|Prevents group members from being notified if the group is mentioned."
-msgstr ""
+msgstr "阻止群组æˆå‘˜åœ¨æåŠç¾¤ç»„时得到通知。"
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. Inherited by subgroups."
msgstr "项目将在 %{waiting_period}天延迟åŽæ°¸ä¹…删除,由å­ç»„继承。"
@@ -16321,9 +16446,15 @@ msgstr "项目将在 %{waiting_period}天延迟åŽæ°¸ä¹…删除,由å­ç»„继承
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr "项目将在%{waiting_period}天延迟åŽæ°¸ä¹…删除,此延迟在实例设置中%{link_start}å¯ä»¥ç”±ç®¡ç†å‘˜å®šä¹‰%{link_end} ,由å­ç¾¤ç»„继承。"
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr "选择一个å­ç»„用作该组的自定义项目模æ¿çš„æºã€‚"
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr "为该群组设置GitLab Pages的最大大å°ã€‚ %{link_start}了解更多。%{link_end}"
@@ -16426,8 +16557,8 @@ msgstr "找ä¸åˆ°ç¾¤ç»„"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "您å¯ä»¥ç®¡ç†ç¾¤ç»„æˆå‘˜çš„æƒé™å¹¶è®¿é—®ç¾¤ç»„中的æ¯ä¸ªé¡¹ç›®ã€‚"
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
-msgstr "%{linkStart}群组%{linkEnd}å…许您在多个项目之间进行管ç†ä¸Žå作。群组的æˆå‘˜æ‹¥æœ‰è®¿é—®å…¶ä¸­æ‰€æœ‰é¡¹ç›®çš„æƒé™ã€‚群组也å¯ä»¥é€šè¿‡åˆ›å»ºå­ç¾¤ç»„æ¥è¿›è¡ŒåµŒå¥—。"
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr "将相关项目组åˆåœ¨ä¸€èµ·å¹¶ä¸€æ¬¡æŽˆäºˆæˆå‘˜è®¿é—®å¤šä¸ªé¡¹ç›®çš„æƒé™ã€‚"
@@ -16469,7 +16600,7 @@ msgid "GroupsNew|No import options available"
msgstr "æ— å¯ç”¨çš„导入选项"
msgid "GroupsNew|Not all related objects are migrated. %{docs_link_start}More info%{docs_link_end}."
-msgstr ""
+msgstr "并éžæ‰€æœ‰ç›¸å…³å¯¹è±¡éƒ½å·²è¿ç§»ã€‚%{docs_link_start}更多信æ¯%{docs_link_end}。"
msgid "GroupsNew|Personal access token"
msgstr "个人访问令牌"
@@ -16555,6 +16686,9 @@ msgstr "页头消æ¯"
msgid "Header must be associated with a request or response"
msgstr "Header必须与请求或å“应相关è”"
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr "标题 1"
@@ -16607,19 +16741,19 @@ msgid "Hello, %{username}!"
msgstr "%{username},您好!"
msgid "HelloMessage|%{handshake_emoji} Contribute to GitLab: %{contribute_link}"
-msgstr ""
+msgstr "%{handshake_emoji} 贡献 GitLab:%{contribute_link}"
msgid "HelloMessage|%{magnifier_emoji} Create a new GitLab issue: %{new_issue_link}"
-msgstr ""
+msgstr "%{magnifier_emoji} 创建一个新的议题:%{new_issue_link}"
msgid "HelloMessage|%{rocket_emoji} We like your curiosity! Help us improve GitLab by joining the team: %{jobs_page_link}"
-msgstr ""
+msgstr "%{rocket_emoji} 我们喜欢您的好奇心ï¼é€šè¿‡åŠ å…¥å›¢é˜Ÿæ¥å¸®åŠ©æˆ‘们改进:%{jobs_page_link}"
msgid "HelloMessage|Does this page need fixes or improvements? Open an issue or contribute a merge request to help make GitLab more lovable. At GitLab, everyone can contribute!"
-msgstr ""
+msgstr "此页é¢éœ€è¦ä¿®å¤æˆ–改进å—?打开一个议题或贡献一个åˆå¹¶è¯·æ±‚,æ¯ä¸ªäººéƒ½å¯ä»¥åšå‡ºè´¡çŒ®ï¼"
msgid "HelloMessage|Welcome to GitLab!"
-msgstr ""
+msgstr "欢迎使用 GitLabï¼"
msgid "Help"
msgstr "帮助"
@@ -16631,16 +16765,16 @@ msgid "Helps prevent bots from creating accounts."
msgstr "有助于防止机器人程åºåˆ›å»ºè´¦æˆ·ã€‚"
msgid "Helps prevent bots from creating issues."
-msgstr ""
+msgstr "有助于防止机器人创建议题。"
msgid "Helps prevent malicious users hide their activity."
-msgstr ""
+msgstr "有助于防止æ¶æ„用户éšè—他们的活动。"
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr "帮助å‡å°‘请求é‡ï¼ˆä¾‹å¦‚æ¥è‡ªçˆ¬è™«æˆ–滥用机器人的请求)"
-msgid "Helps reduce request volume for protected paths"
-msgstr "有助于帮助å‡å°‘å—ä¿æŠ¤è·¯å¾„的请求é‡"
+msgid "Helps reduce request volume for protected paths."
+msgstr ""
msgid "Here you will find recent merge request activity"
msgstr "您将在这里找到最近的åˆå¹¶è¯·æ±‚活动"
@@ -16698,9 +16832,6 @@ msgstr "éšè—值"
msgid "High or unknown vulnerabilities present"
msgstr "存在高å±æˆ–未知æ¼æ´ž"
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr "æ¯ä¸ªåŽŸå§‹è·¯å¾„æ¯åˆ†é’Ÿçš„最大请求数,默认为300. 如è¦ç¦ç”¨åˆ™è®¾ç½®ä¸º0。"
-
msgid "Highest role:"
msgstr "顶级角色:"
@@ -16722,6 +16853,9 @@ msgstr "历å²"
msgid "History of authentications"
msgstr "身份验è¯çš„历å²"
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr "首页URL"
@@ -16746,6 +16880,9 @@ msgstr "ç§äººæ交电å­é‚®ä»¶ä¸­ä½¿ç”¨çš„主机å。 %{learn_more}"
msgid "Hour (UTC)"
msgstr "å°æ—¶(UTC)"
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr "例行维护"
@@ -16756,10 +16893,13 @@ msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "管家,导出,路径,转移,删除,存档。"
msgid "How do I configure Akismet?"
+msgstr "如何é…ç½® Akismet ?"
+
+msgid "How do I configure authentication using the GitLab database?"
msgstr ""
msgid "How do I configure it?"
-msgstr ""
+msgstr "我如何é…置它?"
msgid "How do I configure runners?"
msgstr "如何é…ç½® Runner?"
@@ -16783,10 +16923,10 @@ msgid "How do I set up this service?"
msgstr "如何设置此æœåŠ¡ï¼Ÿ"
msgid "How do I use a web terminal?"
-msgstr ""
+msgstr "如何使用 web 终端?"
msgid "How do I use file templates?"
-msgstr ""
+msgstr "如何使用文件模æ¿ï¼Ÿ"
msgid "How it works"
msgstr "工作原ç†"
@@ -16795,10 +16935,10 @@ msgid "How many days need to pass between marking entity for deletion and actual
msgstr "对象标记被删除和实际被删除之间的天数。"
msgid "How many seconds an IP counts toward the IP address limit."
-msgstr ""
+msgstr "IP 计入 IP 地å€é™åˆ¶çš„秒数。"
msgid "How the job limiter handles jobs exceeding the thresholds specified below. The 'track' mode only logs the jobs. The 'compress' mode compresses the jobs and raises an exception if the compressed size exceeds the limit."
-msgstr ""
+msgstr "作业é™åˆ¶å™¨å¦‚何处ç†è¶…出以下指定阈值的作业。 “trackâ€æ¨¡å¼åªè®°å½•ä½œä¸šã€‚“compressâ€æ¨¡å¼åŽ‹ç¼©ä½œä¸šå¹¶åœ¨åŽ‹ç¼©å¤§å°è¶…过é™åˆ¶æ—¶å¼•å‘异常。"
msgid "I accept the %{terms_link}"
msgstr "æˆ‘æŽ¥å— %{terms_link}"
@@ -16885,13 +17025,13 @@ msgid "IP Address"
msgstr "IP地å€"
msgid "IP address expiration time"
-msgstr ""
+msgstr "IP地å€åˆ°æœŸæ—¶é—´"
msgid "IP address restrictions"
-msgstr ""
+msgstr "IP 地å€é™åˆ¶"
msgid "IP addresses per user"
-msgstr ""
+msgstr "æ¯ä¸ªç”¨æˆ·çš„ IP 地å€"
msgid "IP subnet restriction only allowed for top-level groups"
msgstr "åªå…许在最顶层群组设置IPå­ç½‘é™åˆ¶"
@@ -16909,7 +17049,7 @@ msgid "If any indexed field exceeds this limit it will be truncated to this numb
msgstr "如果任何索引字段超过此é™åˆ¶ï¼Œå®ƒå°†è¢«æˆªæ–­ä¸ºè¯¥å­—符数,其余部分将无法索引或ä¸å¯æœç´¢ã€‚此设置ä¸é€‚用于仓库和Wiki索引。将此设置为0表示它是无é™çš„。"
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
-msgstr ""
+msgstr "如果为空,默认为 %{code_open}ç¨åŽé‡è¯•%{code_close}。"
msgid "If blank, set allowable lifetime to %{instance_level_policy_in_words}, as defined by the instance admin. Once set, existing tokens for users in this group may be revoked."
msgstr "如果为空,则将å…许寿命设置为 %{instance_level_policy_in_words},如实例管ç†å‘˜æ‰€å®šä¹‰ã€‚设置åŽï¼Œè¯¥ç¾¤ç»„中的用户现有令牌å¯èƒ½ä¼šè¢«æ’¤é”€ã€‚"
@@ -16963,7 +17103,7 @@ msgid "If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be
msgstr "如果将%{codeStart}needs%{codeEnd}加到æµæ°´çº¿çš„作业里é¢ï¼Œæ‚¨å°†å¯ä»¥åœ¨%{linkStart}有å‘无环图 (DAG)%{linkEnd}页é¢çœ‹åˆ°ä½œä¸šä¹‹é—´çš„%{codeStart}needs%{codeEnd}关系。"
msgid "If you did not initiate these sign-in attempts, please reach out to your administrator or enable two-factor authentication (2FA) on your account."
-msgstr ""
+msgstr "如果您没有å‘起这些登录å°è¯•ï¼Œè¯·è”系您的管ç†å‘˜æˆ–在您的å¸æˆ·ä¸Šå¯ç”¨åŒé‡èº«ä»½éªŒè¯ï¼ˆ2FA)。"
msgid "If you did not initiate this change, please contact your administrator immediately."
msgstr "如果您没有å‘起此更改,请立å³è”系您的管ç†å‘˜ã€‚"
@@ -17058,7 +17198,7 @@ msgid "Import an exported GitLab project"
msgstr "导入一个从GitLab导出的项目"
msgid "Import and export rate limits"
-msgstr ""
+msgstr "导入/导出速率é™åˆ¶"
msgid "Import failed due to a GitHub error: %{original}"
msgstr "由于GitHub错误,导入失败: %{original}"
@@ -17070,7 +17210,7 @@ msgid "Import from Jira"
msgstr "从Jira导入"
msgid "Import group"
-msgstr ""
+msgstr "导入群组"
msgid "Import group from file"
msgstr "从文件导入群组"
@@ -17079,7 +17219,7 @@ msgid "Import groups"
msgstr "导入群组"
msgid "Import history"
-msgstr ""
+msgstr "导入历å²"
msgid "Import in progress"
msgstr "正在导入"
@@ -17145,25 +17285,25 @@ msgid "Import timed out. Import took longer than %{import_jobs_expiration} secon
msgstr "导入超时。耗时已超过 %{import_jobs_expiration} 秒"
msgid "ImportAProjectModal|Import from a project"
-msgstr ""
+msgstr "从一个项目导入"
msgid "ImportAProjectModal|Import members from another project"
-msgstr ""
+msgstr "从å¦ä¸€ä¸ªé¡¹ç›®å¯¼å…¥æˆå‘˜"
msgid "ImportAProjectModal|Import project members"
-msgstr ""
+msgstr "导入项目æˆå‘˜"
msgid "ImportAProjectModal|Only project members (not group members) are imported, and they get the same permissions as the project you import from."
-msgstr ""
+msgstr "仅导入项目æˆå‘˜ï¼ˆè€Œéžç¾¤ç»„æˆå‘˜ï¼‰ï¼Œå¹¶ä¸”他们获得与您从中导入的项目相åŒçš„æƒé™ã€‚"
msgid "ImportAProjectModal|Successfully imported"
-msgstr ""
+msgstr "导入æˆåŠŸ"
msgid "ImportAProjectModal|Unable to import project members"
-msgstr ""
+msgstr "无法导入项目æˆå‘˜"
msgid "ImportAProjectModal|You're importing members to the %{strongStart}%{name}%{strongEnd} project."
-msgstr ""
+msgstr "您正在邀请æˆå‘˜åŠ å…¥ %{strongStart}%{name}%{strongEnd} 群组。"
msgid "ImportButtons|Connect repositories from"
msgstr "用以下方å¼è¿žæŽ¥å‚¨å­˜åº“"
@@ -17215,7 +17355,7 @@ msgid "Importing..."
msgstr "导入中..."
msgid "Import|There is not a valid Git repository at this URL. If your HTTP repository is not publicly accessible, verify your credentials."
-msgstr ""
+msgstr "在此 URL 上没有有效的 Git 仓库。如果您的 HTTP 仓库ä¸èƒ½å…¬å¼€è®¿é—®ï¼Œè¯·éªŒè¯æ‚¨çš„凭æ®ã€‚"
msgid "Improve customer support with Service Desk"
msgstr "通过æœåŠ¡å°æ”¹å–„客户支æŒ"
@@ -17325,6 +17465,9 @@ msgstr "深入并创建一个项目和仓库"
msgid "InProductMarketing|Do you have a minute?"
msgstr "有空å—?"
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr "简å•"
@@ -17385,6 +17528,9 @@ msgstr "Git 基础知识"
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr "GitHub ä¼ä¸šé¡¹ç›®åˆ° GitLab"
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr "GitLab æä¾›é™æ€åº”用程åºå®‰å…¨æµ‹è¯•ï¼ˆSAST)ã€åŠ¨æ€åº”用程åºå®‰å…¨æµ‹è¯•ï¼ˆDAST)ã€å®¹å™¨æ‰«æå’Œä¾èµ–扫æ以帮助您æ供安全的应用程åºä»¥åŠéµå®ˆè®¸å¯å议。"
@@ -17439,6 +17585,9 @@ msgstr "æ高代ç è´¨é‡å¹¶ç®€åŒ–审查"
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr "æ高è¿è¥æ•ˆçŽ‡"
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr "邀请您的åŒäº‹å¹¶å¼€å§‹æ›´å¿«åœ°å‘é€ä»£ç ã€‚"
@@ -17457,6 +17606,15 @@ msgstr "ç«‹å³é‚€è¯·æ‚¨çš„团队"
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr "ç«‹å³é‚€è¯·æ‚¨çš„团队一起构建更好的代ç ï¼ˆå’Œæµç¨‹ï¼‰"
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr "一切尽在统计中"
@@ -17509,7 +17667,7 @@ msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one m
msgstr "ç«‹å³åœ¨ä¸åˆ°ä¸€åˆ†é’Ÿçš„时间内开始 GitLab Ultimate 试用,无需信用å¡ã€‚"
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
-msgstr ""
+msgstr "开始å…费试用旗舰版 - 无需信用å¡"
msgid "InProductMarketing|Start a trial"
msgstr "开始试用"
@@ -17548,7 +17706,7 @@ msgid "InProductMarketing|Team up in GitLab for greater efficiency"
msgstr "在 GitLab 中组队以æ高效率"
msgid "InProductMarketing|Team work makes the dream work"
-msgstr ""
+msgstr "团队åˆä½œæˆå°±æ¢¦æƒ³"
msgid "InProductMarketing|Test, create, deploy"
msgstr "测试,创建,部署"
@@ -17970,6 +18128,9 @@ msgstr "继承:"
msgid "Inline"
msgstr "内è”"
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr "手动输入主机密钥"
@@ -18070,6 +18231,9 @@ msgstr "实例概览"
msgid "Insufficient permissions"
msgstr "æƒé™ä¸è¶³"
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr "集æˆ"
@@ -18109,6 +18273,9 @@ msgstr "继承这些设置的所有项目也将被é‡ç½®ã€‚"
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr "使用自定义设置加载项目时å‘生错误。"
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr "æµè§ˆå™¨é™åˆ¶"
@@ -18128,7 +18295,7 @@ msgid "Integrations|Create new issue in Jira"
msgstr "在Jira中创建新议题"
msgid "Integrations|Create new issue in ZenTao"
-msgstr ""
+msgstr "在禅é“中创建新议题"
msgid "Integrations|Default settings are inherited from the group level."
msgstr "默认设置继承自群组级别。"
@@ -18224,13 +18391,13 @@ msgid "Integrations|Search Jira issues"
msgstr "æœç´¢Jira议题"
msgid "Integrations|Search ZenTao issues"
-msgstr ""
+msgstr "æœç´¢ç¦…é“议题"
msgid "Integrations|Send notifications about project events to Unify Circuit."
msgstr "将有关项目事件的通知å‘é€åˆ° Unify Circuit。"
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
-msgstr ""
+msgstr "将有关项目事件的通知å‘é€åˆ° Unify Circuit 对è¯ã€‚ %{docs_link}"
msgid "Integrations|Sign in to add namespaces"
msgstr "登录以添加命å空间"
@@ -18272,7 +18439,7 @@ msgid "Integrations|You've activated every integration 🎉"
msgstr "æ‚¨å·²æ¿€æ´»æ‰€æœ‰é›†æˆ ðŸŽ‰"
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
-msgstr ""
+msgstr "当您在禅é“中创建项目的议题时,禅é“议题会显示在此处。"
msgid "Interactive mode"
msgstr "交互模å¼"
@@ -18292,6 +18459,9 @@ msgstr "除外部用户外,任何登录用户å‡å¯è®¿é—®è¯¥é¡¹ç›®ã€‚"
msgid "Internal URL (optional)"
msgstr "内部URL(å¯é€‰)"
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr "内部用户"
@@ -18367,9 +18537,6 @@ msgstr "无效的pod_name"
msgid "Invalid policy type"
msgstr "无效的策略类型"
-msgid "Invalid query"
-msgstr "无效的查询"
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr "针对代ç ç‰‡æ®µ%{snippet_id}的无效仓库包"
@@ -18398,10 +18565,10 @@ msgid "Investigate vulnerability: %{title}"
msgstr "调查æ¼æ´ž: %{title}"
msgid "Invisible Captcha"
-msgstr ""
+msgstr "éšå½¢éªŒè¯ç "
msgid "Invisible Captcha helps prevent the creation of spam accounts. It adds a honeypot field and time-sensitive form submission to the account signup form."
-msgstr ""
+msgstr "éšå½¢éªŒè¯ç æœ‰åŠ©äºŽé˜²æ­¢åˆ›å»ºåžƒåœ¾é‚®ä»¶å¸æˆ·ã€‚它在å¸æˆ·æ³¨å†Œè¡¨å•ä¸­æ·»åŠ äº†ä¸€ä¸ªèœœç½å­—段和时间æ•æ„Ÿçš„表å•æ交。"
msgid "Invitation"
msgstr "邀请"
@@ -18469,6 +18636,12 @@ msgstr "您被邀请以%{role}身份加入%{strong_start}%{project_or_group_name
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr "您被邀请以%{role}身份加入%{project_or_group_name}%{project_or_group}"
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr "与您的团队å作"
@@ -18487,6 +18660,9 @@ msgstr "访问到期日期(å¯é€‰)"
msgid "InviteMembersModal|Cancel"
msgstr "å–消"
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr "关闭邀请团队æˆå‘˜"
@@ -18502,6 +18678,9 @@ msgstr "é…置安全功能"
msgid "InviteMembersModal|Contribute to the codebase"
msgstr "为代ç åº“贡献"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr "GitLab用户或电å­é‚®ä»¶åœ°å€"
@@ -18535,6 +18714,9 @@ msgstr "选择æˆå‘˜æˆ–输入电å­é‚®ä»¶åœ°å€"
msgid "InviteMembersModal|Something went wrong"
msgstr "出现错误"
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr "您希望新æˆå‘˜å…³æ³¨ä»€ä¹ˆï¼Ÿï¼ˆå¯é€‰ï¼‰"
@@ -18857,7 +19039,7 @@ msgid "Issues"
msgstr "议题"
msgid "Issues I've created"
-msgstr ""
+msgstr "我创建的议题"
msgid "Issues Rate Limits"
msgstr "议题速率é™åˆ¶"
@@ -18866,7 +19048,7 @@ msgid "Issues and merge requests"
msgstr "议题和åˆå¹¶è¯·æ±‚"
msgid "Issues assigned to me"
-msgstr ""
+msgstr "已分é…给我的议题"
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr "议题å¯ä»¥æ˜¯ç¼ºé™·ï¼Œä»»åŠ¡æˆ–è¦è®¨è®ºçš„想法。此外,å¯ä»¥é€šè¿‡æœç´¢å’Œç­›é€‰æ¥æŸ¥æ‰¾è®®é¢˜ã€‚"
@@ -18980,7 +19162,7 @@ msgid "Iterations|Create cadence"
msgstr "创建周期"
msgid "Iterations|Create iteration"
-msgstr ""
+msgstr "创建迭代"
msgid "Iterations|Delete cadence"
msgstr "删除周期"
@@ -18989,7 +19171,7 @@ msgid "Iterations|Delete iteration cadence?"
msgstr "删除迭代周期?"
msgid "Iterations|Delete iteration?"
-msgstr ""
+msgstr "删除迭代?"
msgid "Iterations|Duration"
msgstr "时长"
@@ -19025,7 +19207,7 @@ msgid "Iterations|New iteration cadence"
msgstr "新建迭代周期"
msgid "Iterations|No closed iterations."
-msgstr ""
+msgstr "没有已关闭的迭代。"
msgid "Iterations|No iteration cadences to show."
msgstr "没有è¦æ˜¾ç¤ºçš„迭代周期。"
@@ -19034,7 +19216,7 @@ msgid "Iterations|No iterations in cadence."
msgstr "周期中没有迭代。"
msgid "Iterations|No open iterations."
-msgstr ""
+msgstr "没有开放的迭代。"
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr "您希望安排的未æ¥è¿­ä»£æ¬¡æ•°"
@@ -19060,6 +19242,9 @@ msgstr "开始日期"
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr "æ¯æ¬¡è¿­ä»£çš„æŒç»­æ—¶é—´ï¼ˆä»¥å‘¨ä¸ºå•ä½ï¼‰"
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr "第一次迭代的开始日期"
@@ -19067,7 +19252,7 @@ msgid "Iterations|This will delete the cadence as well as all of the iterations
msgstr "这将删除周期以åŠå…¶ä¸­çš„所有迭代。"
msgid "Iterations|This will remove the iteration from any issues that are assigned to it."
-msgstr ""
+msgstr "这将从分é…给它的任何议题中删除迭代。"
msgid "Iterations|Title"
msgstr "标题"
@@ -19153,20 +19338,20 @@ msgstr "连接到 Jira æ—¶å‘生超时错误。请您å†æ¬¡å°è¯•è¯·æ±‚。"
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr "连接到 Jira æ—¶å‘生 SSL 错误: %{message}。å†æ¬¡å°è¯•æ‚¨çš„请求。"
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
-msgstr "从 Jira 请求数æ®æ—¶å‡ºé”™ã€‚检查您的 Jira 集æˆé…置并é‡è¯•ã€‚"
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
+msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
-msgstr "从 Jira 请求数æ®æ—¶å‡ºé”™ï¼š%{messages}。检查您的 Jira 集æˆé…置并é‡è¯•ã€‚"
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
+msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr "用于连接到 Jira çš„ Jira API URL 无效。检查您的 Jira é›†æˆ API URL,然åŽé‡è¯•ã€‚"
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
-msgstr "访问Jira的凭æ®ä¸å…许访问数æ®ã€‚检查您的Jira集æˆå‡­æ®ï¼Œç„¶åŽé‡è¯•ã€‚"
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
+msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
-msgstr "访问Jira的凭æ®æ— æ•ˆã€‚检查您的Jira集æˆå‡­æ®ï¼Œç„¶åŽé‡è¯•ã€‚"
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
+msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr "于分支%{branch_link}"
@@ -19352,7 +19537,7 @@ msgid "Job"
msgstr "作业"
msgid "Job %{jobName}"
-msgstr ""
+msgstr "作业 %{jobName}"
msgid "Job Failed #%{build_id}"
msgstr "作业 #%{build_id} 已失败 "
@@ -19507,6 +19692,12 @@ msgstr "ç”±"
msgid "Join Zoom meeting"
msgstr "加入Zoom会议"
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr "加入于%{time_ago}"
@@ -19760,12 +19951,18 @@ msgstr "最åŽè®¿é—®äºŽ"
msgid "Last Activity"
msgstr "最近活动"
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "最新æµæ°´çº¿"
msgid "Last Seen"
msgstr "最åŽå‡ºçŽ°"
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr "最近使用"
@@ -19934,6 +20131,9 @@ msgstr "了解有关部署到群集的详细信æ¯"
msgid "Learn more about group-level project templates"
msgstr "了解更多关于群组级项目模æ¿"
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr "%{configuration_link_start}高级æœç´¢é…ç½®%{configuration_link_end} 文档中了解有关分片和副本的更多信æ¯ã€‚直到索引%{recreated_link_start}é‡æ–°åˆ›å»º%{recreated_link_end}æ‰ä¼šå‘生更改。"
@@ -20103,7 +20303,7 @@ msgid "LicenseCompliance|Add license and related policy"
msgstr "添加许å¯è¯å’Œç›¸å…³æ”¿ç­–"
msgid "LicenseCompliance|Add license policy"
-msgstr ""
+msgstr "添加许å¯è¯ç­–ç•¥"
msgid "LicenseCompliance|Allow"
msgstr "å…许"
@@ -20187,7 +20387,7 @@ msgid "LicenseManagement|Uncategorized"
msgstr "未分类"
msgid "Licensed Enterprise Edition features can be used if the project namespace's plan includes the feature, or if the project is public."
-msgstr ""
+msgstr "如果项目命å空间的计划包å«è¯¥åŠŸèƒ½ï¼Œæˆ–者该项目是公开的,则å¯ä»¥ä½¿ç”¨è®¸å¯çš„功能。"
msgid "Licensed Features"
msgstr "需è¦è®¸å¯çš„功能"
@@ -20256,10 +20456,10 @@ msgid "Limit namespaces and projects that can be indexed"
msgstr "é™åˆ¶å¯ç´¢å¼•å‘½å空间和项目"
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "在全局ã€ç¾¤ç»„和项目级别é™åˆ¶é¡¹ç›®å¤§å°ã€‚ %{link_start}了解更多%{link_end}。"
msgid "Limit sign in from multiple IP addresses"
-msgstr ""
+msgstr "é™åˆ¶ä»Žå¤šä¸ªIP地å€ç™»å½•"
msgid "Limit the number of concurrent operations this secondary site can run in the background."
msgstr "é™åˆ¶æ­¤æ¬¡è¦èŠ‚点在åŽå°è¿è¡Œçš„并行æ“作数é‡ã€‚"
@@ -20271,14 +20471,14 @@ msgid "Limit the number of issues and epics per minute a user can create through
msgstr "é™åˆ¶ç”¨æˆ·æ¯åˆ†é’Ÿå¯ä»¥é€šè¿‡ Web å’Œ API 请求创建的议题和å²è¯—çš„æ•°é‡ã€‚"
msgid "Limit the size of Sidekiq jobs stored in Redis."
-msgstr ""
+msgstr "é™åˆ¶å­˜å‚¨åœ¨Redis中的Sidekiq作业的大å°ã€‚"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] "最多显示 %d 个事件"
msgid "Limiting mode"
-msgstr ""
+msgstr "é™åˆ¶æ¨¡å¼"
msgid "Line changes"
msgstr "è¡Œå˜æ›´"
@@ -20550,6 +20750,9 @@ msgstr "请确ä¿å¦¥å–„ä¿å­˜å®ƒ - 您无法å†æ¬¡è®¿é—®å®ƒçš„内容。"
msgid "Makes this issue confidential."
msgstr "将此议题设置为ç§å¯†."
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr "ç®¡ç† Web IDE 功能。"
@@ -20679,9 +20882,12 @@ msgstr "添加斜体文本(%{modifier_key}I)"
msgid "Marked For Deletion At - %{deletion_time}"
msgstr "标记删除于 - %{deletion_time}"
-msgid "Marked as ready. Merging is now allowed."
+msgid "Marked as draft. Can only be merged when marked as ready."
msgstr ""
+msgid "Marked as ready. Merging is now allowed."
+msgstr "标记为已准备好。现在å…许åˆå¹¶ã€‚"
+
msgid "Marked this %{noun} as a draft."
msgstr "已标记此%{noun}为è‰ç¨¿ã€‚"
@@ -20766,11 +20972,8 @@ msgstr "最大角色"
msgid "Max session time"
msgstr "最大会è¯æ—¶é—´"
-msgid "MaxBuilds"
-msgstr "MaxBuilds"
-
msgid "Maximum 20 characters"
-msgstr ""
+msgstr "最多 20 个字符"
msgid "Maximum Conan package file size in bytes"
msgstr "最大Conan文件包大å°ï¼ˆå­—节)"
@@ -20806,10 +21009,10 @@ msgid "Maximum attachment size (MB)"
msgstr "æœ€å¤§é™„ä»¶å¤§å° (MB)"
msgid "Maximum authenticated API requests per rate limit period per user"
-msgstr ""
+msgstr "æ¯ä¸ªç”¨æˆ·æ¯ä¸ªé€ŸçŽ‡é™åˆ¶æœŸçš„æœ€å¤§å·²éªŒè¯ API 请求数"
msgid "Maximum authenticated web requests per rate limit period per user"
-msgstr ""
+msgstr "æ¯ä¸ªç”¨æˆ·æ¯ä¸ªé€ŸçŽ‡é™åˆ¶æœŸé—´çš„æœ€å¤§å·²éªŒè¯ Web 请求数"
msgid "Maximum bulk request size (MiB)"
msgstr "最大批é‡è¯·æ±‚大å°(MiB)"
@@ -20857,13 +21060,13 @@ msgid "Maximum files in a diff"
msgstr "差异中的最大文件数"
msgid "Maximum group export download requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é’Ÿæœ€å¤§ç¾¤ç»„导出下载请求"
msgid "Maximum group export requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é’Ÿæœ€å¤§ç¾¤ç»„导出请求"
msgid "Maximum group import requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é’Ÿæœ€å¤§ç¾¤ç»„导入请求"
msgid "Maximum import size"
msgstr "最大导入大å°"
@@ -20892,6 +21095,9 @@ msgstr "最大 npm 包文件大å°ï¼ˆä»¥å­—节为å•ä½ï¼‰"
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr "超过%{name}的最大数é‡(%{count})"
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr "超出最大评论数"
@@ -20901,9 +21107,12 @@ msgstr "å¯ä»¥åŒæ—¶åŒæ­¥çš„最大镜åƒæ•°ã€‚"
msgid "Maximum number of projects."
msgstr "最大项目数é‡ã€‚"
-msgid "Maximum number of unique IP addresses per user."
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
msgstr ""
+msgid "Maximum number of unique IP addresses per user."
+msgstr "æ¯ä¸ªç”¨æˆ·çš„最大唯一 IP 地å€æ•°ã€‚"
+
msgid "Maximum page reached"
msgstr "已达到最大页é¢"
@@ -20911,13 +21120,13 @@ msgid "Maximum page size"
msgstr "最大页é¢å¤§å°"
msgid "Maximum project export download requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é’Ÿæœ€å¤§é¡¹ç›®å¯¼å‡ºä¸‹è½½è¯·æ±‚"
msgid "Maximum project export requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é’Ÿæœ€å¤§é¡¹ç›®å¯¼å‡ºè¯·æ±‚"
msgid "Maximum project import requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é’Ÿæœ€å¤§é¡¹ç›®å¯¼å…¥è¯·æ±‚"
msgid "Maximum push size"
msgstr "最大推é€å¤§å°"
@@ -20926,7 +21135,7 @@ msgid "Maximum push size (MB)"
msgstr "最大推é€å¤§å° (MB)"
msgid "Maximum requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é’Ÿæœ€å¤§è¯·æ±‚æ•°"
msgid "Maximum running slices"
msgstr "最大è¿è¡Œåˆ‡ç‰‡"
@@ -20959,13 +21168,13 @@ msgid "Maximum time that users are allowed to skip the setup of two-factor authe
msgstr "å…许用户跳过åŒé‡èº«ä»½éªŒè¯çš„最长时间(以å°æ—¶ä¸ºå•ä½ï¼‰ã€‚设置为 0(零)以在下次登录时强制执行。"
msgid "Maximum time, in seconds, for a web terminal websocket connection. 0 for unlimited."
-msgstr ""
+msgstr "Web 终端 websocket 连接的最长时间,以秒为å•ä½ï¼Œ0 表示无é™åˆ¶ã€‚"
msgid "Maximum unauthenticated API requests per rate limit period per IP"
-msgstr ""
+msgstr "æ¯ä¸ª IP æ¯ä¸ªé€ŸçŽ‡é™åˆ¶æœŸé—´çš„最大未ç»èº«ä»½éªŒè¯çš„ API 请求数"
msgid "Maximum unauthenticated web requests per rate limit period per IP"
-msgstr ""
+msgstr "æ¯ä¸ª IP æ¯ä¸ªé€ŸçŽ‡é™åˆ¶æœŸé—´çš„最大未ç»èº«ä»½éªŒè¯çš„ Web 请求"
msgid "May"
msgstr "5月"
@@ -21019,7 +21228,7 @@ msgid "Members of a group may only view projects they have permission to access"
msgstr "群组æˆå‘˜åªèƒ½æŸ¥çœ‹ä»–们有æƒè®¿é—®çš„项目"
msgid "Membership"
-msgstr ""
+msgstr "æˆå‘˜èµ„æ ¼"
msgid "Members|%{time} by %{user}"
msgstr "于%{time}由%{user}"
@@ -21162,6 +21371,9 @@ msgstr "自动åˆå¹¶(%{strategy})"
msgid "Merge blocked: new changes were just added."
msgstr "åˆå¹¶è¢«é˜»æ­¢ï¼šåˆšåˆšæ·»åŠ äº†æ–°çš„更改。"
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr "åˆå¹¶å—阻:æºåˆ†æ”¯å¿…é¡»å˜åŸºï¼ˆrebase)到目标分支。"
@@ -21207,6 +21419,9 @@ msgstr "åˆå¹¶è¯·æ±‚ä¾èµ–"
msgid "Merge request events"
msgstr "åˆå¹¶è¯·æ±‚事件"
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr "åˆå¹¶è¯·æ±‚已安排在æµæ°´çº¿æˆåŠŸåŽåˆå¹¶"
@@ -21214,7 +21429,7 @@ msgid "Merge requests"
msgstr "åˆå¹¶è¯·æ±‚"
msgid "Merge requests I've created"
-msgstr ""
+msgstr "我创建的åˆå¹¶è¯·æ±‚"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "åˆå¹¶è¯·æ±‚用于æ出对项目的更改并与他人进行讨论"
@@ -21223,10 +21438,10 @@ msgid "Merge requests are read-only in a secondary Geo node"
msgstr "åˆå¹¶è¯·æ±‚在Geo次è¦èŠ‚点中为åªè¯»"
msgid "Merge requests assigned to me"
-msgstr ""
+msgstr "指派给我的åˆå¹¶è¯·æ±‚"
msgid "Merge requests that I'm a reviewer"
-msgstr ""
+msgstr "我作为审核者的åˆå¹¶è¯·æ±‚"
msgid "Merge the branch and fix any conflicts that come up"
msgstr "åˆå¹¶åˆ†æ”¯å¹¶è§£å†³å‡ºçŽ°çš„任何冲çª"
@@ -21279,6 +21494,15 @@ msgstr "æµæ°´çº¿"
msgid "MergeRequestAnalytics|Time to merge"
msgstr "åˆå¹¶æ—¶é—´"
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr "对%{selectStart}开始于%{selectEnd}到%{end}è¡Œå‘表评论"
@@ -21289,7 +21513,7 @@ msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr "ä¿å­˜è¯„论è‰ç¨¿æ—¶å‘生错误。"
msgid "MergeRequests|Create issue to resolve thread"
-msgstr ""
+msgstr "创建议题以解决主题"
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr "无法压缩(Squash)。应该手动完æˆã€‚"
@@ -21435,35 +21659,29 @@ msgstr "指标仪表æ¿YAML定义有效。"
msgid "Metrics and profiling"
msgstr "指标与分æž"
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr "标注ä¸èƒ½åŒæ—¶å±žäºŽä¸€ä¸ªé›†ç¾¤å’Œä¸€ä¸ªçŽ¯å¢ƒ"
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr "标注未被删除"
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
-msgstr "标注必须属于一个集群或一个环境"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
-msgstr "找ä¸åˆ°è¯·æ±‚路径的仪表æ¿"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
-msgstr "您无æƒä¸ºæ‰€é€‰é›†ç¾¤åˆ›å»ºæ ‡æ³¨"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
-msgstr "您无æƒä¸ºæ‰€é€‰çŽ¯å¢ƒåˆ›å»ºæ ‡æ³¨"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
-msgstr "您无æƒåˆ é™¤æ­¤æ ‡æ³¨"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
+msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
-msgstr "ä¸èƒ½ä¸ºå¯åŠ¨å‰çš„时间"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
+msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr "找ä¸åˆ°è¯·æ±‚路径的仪表æ¿"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
+msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
-msgstr "您无æƒæ·»åŠ æ˜Ÿæ ‡åˆ°æ­¤ä»ªè¡¨æ¿"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
+msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
msgstr "å‘指标仪表æ¿æ·»åŠ ä¸€ä¸ªæŒ‰é’®ï¼Œç›´æŽ¥é“¾æŽ¥åˆ°æ‚¨çš„现有外部仪表æ¿ã€‚"
@@ -21489,6 +21707,12 @@ msgstr "UTC(世界标准时间)"
msgid "MetricsSettings|User's local timezone"
msgstr "用户本地时区"
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr "1. 定义和预览é¢æ¿"
@@ -21580,9 +21804,6 @@ msgstr "展开é¢æ¿"
msgid "Metrics|For grouping similar metrics"
msgstr "用于分组类似指标"
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr "GitLab 管ç†çš„ Prometheus 已弃用, %{linkStart}计划删除%{linkEnd}。移除åŽï¼Œæ‚¨çŽ°æœ‰çš„警报将继续作为新集群集æˆçš„一部分å‘挥作用。但是,您将无法å†ä»ŽæŒ‡æ ‡ä»ªè¡¨æ¿æ·»åŠ æ–°è­¦æŠ¥æˆ–编辑现有警报。"
-
msgid "Metrics|Invalid time range, please verify."
msgstr "无效的时间范围,请验è¯ã€‚"
@@ -21718,9 +21939,6 @@ msgstr "查看文档"
msgid "Metrics|View logs"
msgstr "查看日志"
-msgid "Metrics|View runbook - %{label}"
-msgstr "查看Runbook - %{label}"
-
msgid "Metrics|Y-axis label"
msgstr "Y轴标签"
@@ -22104,7 +22322,7 @@ msgid "MoveIssue|Cannot move issue to project it originates from!"
msgstr "无法将议题移动到æºé¡¹ç›®ä¸­!"
msgid "MoveIssue|Cannot move issues of '%{issue_type}' type."
-msgstr ""
+msgstr "无法移动“%{issue_type}â€ç±»åž‹çš„议题。"
msgid "Moved issue to %{label} column in the board."
msgstr "将议题移动到看æ¿ä¸­çš„%{label}列。"
@@ -22166,6 +22384,9 @@ msgstr "My Awesome Group"
msgid "My company or team"
msgstr "我的公å¸æˆ–团队"
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr "我的å应"
@@ -22231,13 +22452,13 @@ msgid "NamespaceStorageSize|push to your repository, create pipelines, create is
msgstr "推é€åˆ°æ‚¨çš„仓库ã€åˆ›å»ºæµæ°´çº¿ã€åˆ›å»ºè®®é¢˜æˆ–添加评论。è¦å‡å°‘存储容é‡ï¼Œè¯·åˆ é™¤æœªä½¿ç”¨çš„仓库ã€äº§ç‰©ã€wikiã€è®®é¢˜å’Œæµæ°´çº¿ã€‚è¦äº†è§£æœ‰å…³å‡å°‘存储容é‡çš„更多信æ¯ï¼Œè¯·è®¿é—®æˆ‘们的文档。"
msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
-msgstr ""
+msgstr "待定用户必须ç»è¿‡ç¾¤ç»„所有者的审查和批准。了解有关 %{user_caps_link_start}用户上é™%{link_end} å’Œ %{users_pending_approval_link_start}用户等待批准%{link_end}。"
msgid "NamespaceUserCap|View pending user approvals"
-msgstr ""
+msgstr "查看待处ç†çš„用户批准"
msgid "NamespaceUserCap|Your group has reached its billable member limit"
-msgstr ""
+msgstr "您的群组已达到å¯è®¡è´¹æˆå‘˜ä¸Šé™"
msgid "Namespaces"
msgstr "命å空间"
@@ -22281,6 +22502,9 @@ msgstr "需è¦å…³æ³¨"
msgid "Network"
msgstr "网络"
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr "%{ifLabelStart}如果%{ifLabelEnd}%{ruleType}%{isLabelStart}为%{isLabelEnd}%{ruleDirection}%{ruleSelector}%{directionLabelStart}且由%{directionLabelEnd}%{rule}%{portsLabelStart}在%{portsLabelEnd} %{ports}传入。"
@@ -22309,7 +22533,7 @@ msgid "NetworkPolicies|.yaml mode"
msgstr ".yaml模å¼"
msgid "NetworkPolicies|Add alert"
-msgstr ""
+msgstr "添加警报"
msgid "NetworkPolicies|Alerts are intended to be selectively used for a limited number of events that are potentially concerning and warrant a manual review. Alerts should not be used as a substitute for a SIEM or a logging tool. High volume alerts are likely to be dropped so as to preserve the stability of GitLab's integration with Kubernetes."
msgstr "警报是为了有选择地用于少数å¯èƒ½æ¶‰åŠå¹¶éœ€è¦äººå·¥å®¡æŸ¥çš„事件。ä¸åº”将警报用作 SIEM 或记录工具的替代å“。为了ä¿æŒGitLab与Kubernetes一体化的稳定性,å¯èƒ½ä¼šæ”¾å¼ƒå¤§é‡è­¦æŠ¥ã€‚"
@@ -22347,9 +22571,6 @@ msgstr "æ‹’ç»æ‰€æœ‰æµé‡"
msgid "NetworkPolicies|Edit policy"
msgstr "编辑策略"
-msgid "NetworkPolicies|Enforcement status"
-msgstr "强制执行状æ€"
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr "环境没有部署平å°"
@@ -22369,10 +22590,10 @@ msgid "NetworkPolicies|Network"
msgstr "网络"
msgid "NetworkPolicies|Network Policies can be used to limit which network traffic is allowed between containers inside the cluster."
-msgstr ""
+msgstr "网络策略å¯ä»¥ç”¨äºŽé™åˆ¶é›†ç¾¤å†…容器之间的网络æµé‡ã€‚"
msgid "NetworkPolicies|Network policy can be created after the environment is loaded successfully."
-msgstr ""
+msgstr "环境加载æˆåŠŸåŽå¯ä»¥åˆ›å»ºç½‘络策略。"
msgid "NetworkPolicies|Network traffic"
msgstr "网络æµé‡"
@@ -22589,7 +22810,7 @@ msgid "New issue"
msgstr "新建议题"
msgid "New issue in %{project}"
-msgstr ""
+msgstr "在 %{project} 中新建议题"
msgid "New issue title"
msgstr "新议题标题"
@@ -22657,6 +22878,9 @@ msgstr "新建标签"
msgid "New test case"
msgstr "新测试用例"
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr "新用户设置为外部"
@@ -22670,7 +22894,7 @@ msgid "Newest first"
msgstr "最新在å‰"
msgid "Newly-registered users are external by default"
-msgstr ""
+msgstr "新注册的用户默认是外部用户"
msgid "Next"
msgstr "Next"
@@ -22771,8 +22995,8 @@ msgstr "没有使用中的åˆè§„框架。"
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr "没有使用中的åˆè§„框架。从群组设置中的 %{link} 部分创建一个。"
-msgid "No confirmation email received? Please check your spam folder or"
-msgstr "没有收到确认邮件?请检查您的垃圾邮件文件夹或"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
+msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "无法连接到GitalyæœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥ç›¸å…³æ—¥å¿—ï¼"
@@ -22786,6 +23010,9 @@ msgstr "无贡献"
msgid "No contributions were found"
msgstr "未找到任何贡献者"
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr "无需信用å¡ã€‚"
@@ -22981,12 +23208,15 @@ msgstr "尚无触å‘器。使用上é¢çš„表å•åˆ›å»ºä¸€ä¸ªã€‚"
msgid "No vulnerabilities present"
msgstr "æ— æ¼æ´ž"
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr "没有找到Webhook,请通过上é¢è¡¨å•æ·»åŠ ã€‚"
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
msgid_plural "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} days to renew your subscription."
-msgstr[0] ""
+msgstr[0] "ä¸ç”¨æ‹…心,您现在ä»ç„¶å¯ä»¥ä½¿ç”¨æ‰€æœ‰ %{strong}%{plan_name}%{strong_close} 功能。您有 %{remaining_days} 天æ¥ç»­è®¢æ‚¨çš„订阅。"
msgid "No. of commits"
msgstr "æ交次数"
@@ -23004,7 +23234,7 @@ msgid "Nodes"
msgstr "节点"
msgid "Non-admin users are restricted to read-only access, in both GitLab UI and API."
-msgstr ""
+msgstr "在 UI å’Œ API 中,éžç®¡ç†å‘˜ç”¨æˆ·ä»…é™åªè¯»è®¿é—®ã€‚"
msgid "None"
msgstr "æ— "
@@ -23036,9 +23266,6 @@ msgstr "对ç§æœ‰é¡¹ç›®ä¸å¯ç”¨"
msgid "Not available for protected branches"
msgstr "对å—ä¿æŠ¤çš„分支ä¸å¯ç”¨"
-msgid "Not available to run jobs."
-msgstr "无法è¿è¡Œä½œä¸šã€‚"
-
msgid "Not confidential"
msgstr "éžç§å¯†"
@@ -23085,7 +23312,7 @@ msgid "NoteForm|Note"
msgstr "注æ„"
msgid "Notes rate limit"
-msgstr ""
+msgstr "Notes 速率é™åˆ¶"
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "确定è¦å–消此评论å—?"
@@ -23268,18 +23495,15 @@ msgstr "增é‡%{code_start}git repack%{code_end} 之åŽçš„ Git 推é€æ¬¡æ•°ã€‚"
msgid "Number of LOCs per commit"
msgstr "æ¯æ¬¡æ交的代ç è¡Œæ•°"
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr "å•ä¸ªæŽ¨é€ä¸­çš„å˜æ›´æ•°é‡(分支或标签),将决定创建多个å•ä¸€æŽ¨é€äº‹ä»¶è¿˜æ˜¯ä¸€ä¸ªæ‰¹é‡æŽ¨é€äº‹ä»¶ã€‚如果超过该值,将会创建批é‡æŽ¨é€äº‹ä»¶ã€‚"
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr "å•ä¸ªæŽ¨é€ä¸­çš„å˜æ›´æ•°é‡(分支或标签),将决定webhook或æœåŠ¡æ˜¯å¦ä¼šè§¦å‘。如果超过该值,webhookå’ŒæœåŠ¡å°†ä¸ä¼šæ交。"
-
msgid "Number of commits"
msgstr "æ交次数"
msgid "Number of commits per MR"
msgstr "æ¯ä¸ªMR包å«çš„æ交数é‡"
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr "事件数é‡"
@@ -23331,9 +23555,6 @@ msgstr "最早在å‰"
msgid "OmniAuth"
msgstr "OmniAuth"
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr "Omnibusä¿æŠ¤è·¯å¾„阈值已å¯ç”¨ï¼Œä¸”优先级高于这些设置。从12.4èµ·Omnibus阈值已弃用,并将在未æ¥ç‰ˆæœ¬ä¸­ç§»é™¤ã€‚请å‚阅%{relative_url_link_start}è¿ç§»ä¿æŠ¤è·¯å¾„文档%{relative_url_link_end}。"
-
msgid "On"
msgstr "于"
@@ -23416,7 +23637,7 @@ msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr "对于这个循环,待命计划将是:"
msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
-msgstr ""
+msgstr "项目 %{project} 的 On-call 计划 %{obstacle}"
msgid "OnCallSchedules|On-call schedules"
msgstr "待命计划"
@@ -23535,6 +23756,9 @@ msgstr "管ç†ç«™ç‚¹é…置文件"
msgid "OnDemandScans|My daily scan"
msgstr "我的æ¯æ—¥æ‰«æ"
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr "新建按需扫æDAST"
@@ -23547,6 +23771,12 @@ msgstr "å°šæ— é…置文件。如需创建新扫æ,需è¦è‡³å°‘有一个完整
msgid "OnDemandScans|On-demand Scans"
msgstr "按需扫æ"
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr "按需扫æ在DevOps周期之外è¿è¡Œï¼Œå¹¶åœ¨æ‚¨çš„项目中å‘现æ¼æ´žã€‚%{learnMoreLinkStart}了解更多%{learnMoreLinkEnd}"
@@ -23559,11 +23789,14 @@ msgstr "ä¿å­˜æ‰«æ"
msgid "OnDemandScans|Scan name"
msgstr "扫æå称"
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr "扫æ工具é…ç½®"
msgid "OnDemandScans|Schedule scan"
-msgstr ""
+msgstr "计划扫æ"
msgid "OnDemandScans|Select one of the existing profiles"
msgstr "选择一个现有的é…置文件"
@@ -23572,6 +23805,9 @@ msgid "OnDemandScans|Site profile"
msgstr "站点é…ç½®"
msgid "OnDemandScans|Start time"
+msgstr "开始时间"
+
+msgid "OnDemandScans|Target"
msgstr ""
msgid "OnDemandScans|Use existing scanner profile"
@@ -23642,7 +23878,7 @@ msgid "Only admins can delete project"
msgstr "åªæœ‰ç®¡ç†å‘˜å¯ä»¥åˆ é™¤é¡¹ç›®"
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
-msgstr ""
+msgstr "仅在å¯ç”¨è¿œç¨‹å­˜å‚¨æ—¶æœ‰æ•ˆã€‚设置为 0 表示没有大å°é™åˆ¶ã€‚"
msgid "Only include features new to your current subscription tier."
msgstr "仅包括您当å‰è®¢é˜…级别的新功能。"
@@ -23663,10 +23899,10 @@ msgid "Only projects created under a Ultimate license are available in Security
msgstr "åªæœ‰åœ¨æ——舰版许å¯ä¸‹åˆ›å»ºçš„项目æ‰èƒ½åœ¨å®‰å…¨ä»ªè¡¨æ¿ä¸­ä½¿ç”¨ã€‚"
msgid "Only reCAPTCHA v2 is supported:"
-msgstr ""
+msgstr "仅支æŒreCAPTCHA v2:"
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
-msgstr ""
+msgstr "åªæœ‰æ¥è‡ªæŒ‡å®š IP 地å€èŒƒå›´çš„用户æ‰èƒ½è®¿é—®æ­¤ç¾¤ç»„,包括所有å­ç»„ã€é¡¹ç›®å’Œ Git 仓库。"
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr "åªæœ‰å…·æœ‰è¿™äº›åŸŸå电å­é‚®ä»¶åœ°å€çš„已验è¯ç”¨æˆ·æ‰èƒ½æ·»åŠ åˆ°ç¾¤ç»„。"
@@ -23686,15 +23922,15 @@ msgstr "打开所选项"
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr "打开 CLI 并连接到您想è¦å®‰è£…代ç†çš„集群。使用此安装方法æ¥æœ€å°åŒ–任何手动步骤。令牌已ç»åŒ…å«åœ¨å‘½ä»¤ä¸­ã€‚"
-msgid "Open comment type dropdown"
-msgstr "打开评论类型下拉列表"
-
msgid "Open epics"
msgstr "打开å²è¯—"
msgid "Open errors"
msgstr "打开错误"
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr "在文件视图中打开"
@@ -23743,9 +23979,6 @@ msgstr "ä¸å…许此æ“作"
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr "æ“作超时。请检查 Pod 日志 %{pod_name} 了解更多信æ¯ã€‚"
-msgid "Operations"
-msgstr "è¿ç»´"
-
msgid "Operations Dashboard"
msgstr "è¿ç»´ä»ªè¡¨æ¿"
@@ -23773,6 +24006,9 @@ msgstr "å¯é€‰"
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr "å¯é€‰å‚数“variablesâ€å¿…须是哈希。例如:variables[key1]=value1"
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "您å¯ä»¥é€‰æ‹© %{link_to_customize} FogBugz的电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å如何被导入到GitLab。"
@@ -23782,6 +24018,9 @@ msgstr "æ“作"
msgid "Or you can choose one of the suggested colors below"
msgstr "或者您å¯ä»¥é€‰æ‹©ä¸‹é¢çš„建议颜色之一"
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr "孤儿æˆå‘˜"
@@ -23851,6 +24090,36 @@ msgstr "拥有者:"
msgid "Owner"
msgstr "所有者"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr "软件包注册表"
@@ -23873,7 +24142,7 @@ msgid "Package recipe already exists"
msgstr "软件包构æˆå·²å­˜åœ¨"
msgid "Package registry rate limits"
-msgstr ""
+msgstr "软件包仓库速率é™åˆ¶"
msgid "Package type"
msgstr "包类型"
@@ -23926,9 +24195,6 @@ msgstr "添加composer注册表"
msgid "PackageRegistry|Allow duplicates"
msgstr "å…许é‡å¤"
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr "ä¿å­˜è®¾ç½®æ—¶å‡ºé”™"
-
msgid "PackageRegistry|App group: %{group}"
msgstr "应用分组: %{group}"
@@ -23942,7 +24208,7 @@ msgid "PackageRegistry|Composer"
msgstr "Composer"
msgid "PackageRegistry|Composer.json with license: %{license} and version: %{version}"
-msgstr ""
+msgstr "Composer.json 许å¯è¯ï¼š%{license} 和版本:%{version}"
msgid "PackageRegistry|Conan"
msgstr "Conan"
@@ -24008,7 +24274,7 @@ msgid "PackageRegistry|Copy require package include"
msgstr "å¤åˆ¶æ‰€éœ€çš„软件包并包å«"
msgid "PackageRegistry|Copy target SHA"
-msgstr ""
+msgstr "å¤åˆ¶ç›®æ ‡ SHA"
msgid "PackageRegistry|Copy yarn command"
msgstr "å¤åˆ¶yarn命令"
@@ -24077,7 +24343,7 @@ msgid "PackageRegistry|Install package version"
msgstr "安装软件包版本"
msgid "PackageRegistry|Instance-level"
-msgstr ""
+msgstr "实例级别"
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
msgstr "无效的软件包:元数æ®æå–失败"
@@ -24109,14 +24375,15 @@ msgstr "NuGet命令"
msgid "PackageRegistry|Package Registry"
msgstr "软件包注册表"
+msgid "PackageRegistry|Package deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package file deleted successfully"
msgstr "æˆåŠŸåˆ é™¤è½¯ä»¶åŒ…文件"
-msgid "PackageRegistry|Package has %{number} archived update"
-msgstr "软件包有%{number}个存档更新"
-
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr "软件包有%{number}个存档更新"
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr "软件包由分支%{branch}上的%{link}æ交所更新,由æµæ°´çº¿%{pipeline}构建并于%{datetime}å‘布到库"
@@ -24125,7 +24392,7 @@ msgid "PackageRegistry|Pip Command"
msgstr "Pip命令"
msgid "PackageRegistry|Project-level"
-msgstr ""
+msgstr "项目级别"
msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
msgstr "å‘布和分享å„ç§å¸¸è§çš„软件包管ç†å·¥å…·æ”¯æŒçš„软件包。 %{docLinkStart}更多信æ¯%{docLinkEnd}"
@@ -24149,7 +24416,7 @@ msgid "PackageRegistry|Remove package"
msgstr "删除软件包"
msgid "PackageRegistry|Required Python: %{pythonVersion}"
-msgstr ""
+msgstr "éœ€è¦ Python: %{pythonVersion}"
msgid "PackageRegistry|RubyGems"
msgstr "RubyGems"
@@ -24160,9 +24427,6 @@ msgstr "通用包设置"
msgid "PackageRegistry|Settings for Maven packages"
msgstr "Maven 包的设置"
-msgid "PackageRegistry|Settings saved successfully"
-msgstr "设置ä¿å­˜æˆåŠŸ"
-
msgid "PackageRegistry|Show Composer commands"
msgstr "显示 Composer 命令"
@@ -24194,7 +24458,7 @@ msgid "PackageRegistry|Source project located at %{link}"
msgstr "æºé¡¹ç›®ä½äºŽ%{link}"
msgid "PackageRegistry|Target SHA: %{sha}"
-msgstr ""
+msgstr "目标 SHA:%{sha}"
msgid "PackageRegistry|There are no other versions of this package."
msgstr "此软件包没有其他版本。"
@@ -24365,16 +24629,16 @@ msgid "Password was successfully updated. Please sign in again."
msgstr "密ç æ›´æ–°æˆåŠŸã€‚请é‡æ–°ç™»å½•ã€‚"
msgid "PasswordPrompt|Confirm password"
-msgstr ""
+msgstr "确认密ç "
msgid "PasswordPrompt|Confirm password to continue"
-msgstr ""
+msgstr "确认密ç ä»¥ç»§ç»­"
msgid "PasswordPrompt|Password is required"
-msgstr ""
+msgstr "密ç æ˜¯å¿…需的"
msgid "PasswordPrompt|Please enter your password to confirm"
-msgstr ""
+msgstr "请输入您的密ç ä»¥ç¡®è®¤"
msgid "Passwords should be unique and not used for any other sites or services."
msgstr "密ç åº”唯一并未用于任何其他网站或æœåŠ¡ã€‚"
@@ -24404,7 +24668,7 @@ msgid "Paste project path (i.e. gitlab-org/gitlab)"
msgstr "粘贴项目路径(å³gitlab-org/gitlab)"
msgid "Paste this DSN into your Sentry SDK"
-msgstr ""
+msgstr "将此DSN粘贴到您的Sentry SDK"
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
msgstr "粘贴您的SSH 公钥,通常包å«åœ¨æ–‡ä»¶ '~/.ssh/id_ed25519.pub' 或 '~/.ssh/id_rsa.pub' 中,并以“ssh-ed25519â€æˆ–“ssh-rsaâ€å¼€å¤´ã€‚ä¸è¦ç²˜è´´æ‚¨çš„SSHç§é’¥ï¼Œå› ä¸ºè¿™ä¼šæ³„露您的身份信æ¯ã€‚"
@@ -24421,6 +24685,9 @@ msgstr "路径:"
msgid "Paths can contain wildcards, like */welcome"
msgstr "路径å¯ä»¥åŒ…å«é€šé…符,如*/welcome"
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr "æš‚åœ"
@@ -24442,6 +24709,9 @@ msgstr "等待中"
msgid "Pending comments"
msgstr "待处ç†çš„评论"
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr "等待åŒæ­¥â€¦"
@@ -24491,7 +24761,7 @@ msgid "PerformanceBar|First Contentful Paint"
msgstr "第一次内容绘制"
msgid "PerformanceBar|Flamegraph with mode:"
-msgstr ""
+msgstr "ç«ç„°å›¾æ¨¡å¼ï¼š"
msgid "PerformanceBar|Frontend resources"
msgstr "å‰ç«¯èµ„æº"
@@ -24527,13 +24797,13 @@ msgid "PerformanceBar|Trace"
msgstr "跟踪"
msgid "PerformanceBar|cpu"
-msgstr ""
+msgstr "cpu"
msgid "PerformanceBar|object"
-msgstr ""
+msgstr "对象"
msgid "PerformanceBar|wall"
-msgstr ""
+msgstr "墙"
msgid "Period in seconds"
msgstr "周期(秒)"
@@ -24764,46 +25034,46 @@ msgid "PipelineSchedules|Variables"
msgstr "å˜é‡"
msgid "PipelineSource|API"
-msgstr ""
+msgstr "API"
msgid "PipelineSource|Chat"
-msgstr ""
+msgstr "Chat"
msgid "PipelineSource|External"
-msgstr ""
+msgstr "外部"
msgid "PipelineSource|External Pull Request"
-msgstr ""
+msgstr "外部拉å–请求"
msgid "PipelineSource|Merge Request"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚"
msgid "PipelineSource|On-Demand DAST Scan"
-msgstr ""
+msgstr "按需 DAST 扫æ"
msgid "PipelineSource|On-Demand DAST Validation"
-msgstr ""
+msgstr "按需 DAST 验è¯"
msgid "PipelineSource|Parent Pipeline"
-msgstr ""
+msgstr "上级æµæ°´çº¿"
msgid "PipelineSource|Pipeline"
-msgstr ""
+msgstr "æµæ°´çº¿"
msgid "PipelineSource|Push"
-msgstr ""
+msgstr "推é€"
msgid "PipelineSource|Schedule"
-msgstr ""
+msgstr "计划"
msgid "PipelineSource|Trigger"
-msgstr ""
+msgstr "触å‘器"
msgid "PipelineSource|Web"
-msgstr ""
+msgstr "Web"
msgid "PipelineSource|Web IDE"
-msgstr ""
+msgstr "Web IDE"
msgid "PipelineStatusTooltip|Pipeline: %{ciStatus}"
msgstr "æµæ°´çº¿ï¼š%{ciStatus}"
@@ -24949,6 +25219,9 @@ msgstr "ç›®å‰æ²¡æœ‰å·²å®Œæˆçš„æµæ°´çº¿ã€‚"
msgid "Pipelines|There are currently no pipelines."
msgstr "当å‰æ— æµæ°´çº¿ã€‚"
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "获å–æµæ°´çº¿æ—¶å‡ºé”™ã€‚请ç¨åŽé‡è¯•æˆ–è”系支æŒå›¢é˜Ÿã€‚"
@@ -25069,6 +25342,9 @@ msgstr "åˆå¹¶é˜Ÿåˆ—æµæ°´çº¿ä½œä¸šæ— æ³•é‡è¯•"
msgid "Pipeline|Merged result pipeline"
msgstr "åˆå¹¶ç»“æžœæµæ°´çº¿"
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr "已通过"
@@ -25106,7 +25382,7 @@ msgid "Pipeline|Source"
msgstr "æ¥æº"
msgid "Pipeline|Source|Security Policy"
-msgstr ""
+msgstr "安全策略"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default."
msgstr "指定è¦åœ¨æ­¤æ¬¡è¿è¡Œä¸­ä½¿ç”¨çš„å˜é‡å€¼ã€‚%{linkStart}CI/CD设置%{linkEnd}中指定的值将用作默认值."
@@ -25157,7 +25433,7 @@ msgid "Pipeline|We are currently unable to fetch pipeline data"
msgstr "我们目å‰æ— æ³•èŽ·å–æµæ°´çº¿æ•°æ®"
msgid "Pipeline|You’re about to stop pipeline #%{pipelineId}."
-msgstr ""
+msgstr "您将è¦åœæ­¢æµæ°´çº¿ #%{pipelineId}。"
msgid "Pipeline|for"
msgstr "使用æ交"
@@ -25184,6 +25460,9 @@ msgid "Plain diff"
msgstr "文本差异"
msgid "Plain-text response to send to clients that hit a rate limit"
+msgstr "å‘达到速率é™åˆ¶çš„客户å‘é€çš„纯文本å“应。"
+
+msgid "Plan"
msgstr ""
msgid "Plan:"
@@ -25288,9 +25567,15 @@ msgstr "请输入有效的数字"
msgid "Please enter or upload a valid license."
msgstr "请输入或上传有效的许å¯è¯ã€‚"
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "请为您的群组填写æ述性å称。"
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr "请填写此字段。"
@@ -25435,6 +25720,9 @@ msgstr "Postman 集åˆ"
msgid "Postman collection file path or URL"
msgstr "Postman 集åˆæ–‡ä»¶è·¯å¾„或 URL"
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr "预定义的推é€è§„则。"
@@ -25550,10 +25838,10 @@ msgid "Prevent adding new members to project membership within this group"
msgstr "ç¦æ­¢å‘当å‰ç¾¤ç»„中的项目添加新æˆå‘˜"
msgid "Prevent auto-stopping"
-msgstr ""
+msgstr "防止自动åœæ­¢"
msgid "Prevent editing approval rules in projects and merge requests."
-msgstr "ç¦æ­¢åœ¨é¡¹ç›®å’Œåˆå¹¶è¯·æ±‚中编辑审批规则。"
+msgstr "ç¦æ­¢åœ¨é¡¹ç›®å’Œåˆå¹¶è¯·æ±‚中编辑批准规则。"
msgid "Prevent environment from auto-stopping"
msgstr "防止环境自动终止"
@@ -25565,7 +25853,7 @@ msgid "Prevent users from changing their profile name"
msgstr "ç¦æ­¢ç”¨æˆ·æ›´æ”¹é…置文件å称"
msgid "Prevent users from performing write operations while GitLab maintenance is in progress."
-msgstr ""
+msgstr "防止用户在维护期间执行写æ“作。"
msgid "Preview"
msgstr "预览"
@@ -25711,12 +25999,18 @@ msgstr "用户资料"
msgid "Profile Settings"
msgstr "个人资料设置"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr "个人资料图片指å—"
msgid "Profile page:"
msgstr "个人资料页:"
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr "于"
@@ -25726,9 +26020,6 @@ msgstr "您å³å°†æ°¸ä¹…删除 %{yourAccount},以åŠä¸Žæ‚¨çš„å¸æˆ·å…³è”的所
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr "您将更改用户å %{currentUsernameBold} 为 %{newUsernameBold}。é…置文件和项目将é‡å®šå‘到 %{newUsername} 命å空间,但是一旦 %{currentUsername} 命å空间被å¦ä¸€ä¸ªç”¨æˆ·æˆ–组注册,此é‡å®šå‘将过期。请尽快更新您的远端Git仓库。"
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr "\"忙碌\"将显示在您的åå­—æ—边。"
-
msgid "Profiles|%{provider} Active"
msgstr "%{provider}有效"
@@ -25756,6 +26047,9 @@ msgstr "在状æ€ä¸­æ·»åŠ è¡¨æƒ…符å·"
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr "更新您的用户å时出错,请é‡è¯•ã€‚"
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr "头åƒè£å‰ª"
@@ -25838,10 +26132,10 @@ msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr "输入您的姓å,以便大家认识您"
msgid "Profiles|Enter your password to confirm the email change"
-msgstr ""
+msgstr "输入您的密ç ä»¥ç¡®è®¤ç”µå­é‚®ä»¶æ›´æ”¹"
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
-msgstr "输入您的昵称,让人们知é“如何称呼您"
+msgstr "输入您的代è¯ï¼Œè®©äººä»¬çŸ¥é“如何称呼您"
msgid "Profiles|Expired key is not valid."
msgstr "过期的密钥无效。"
@@ -26047,6 +26341,9 @@ msgstr "å¯ä»¥åœ¨è¿™é‡Œä¸Šä¼ æ‚¨çš„头åƒæˆ–者从 %{gravatar_link} 修改头åƒ
msgid "Profiles|You don't have access to delete this user."
msgstr "您无æƒåˆ é™¤æ­¤ç”¨æˆ·ã€‚"
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr "您必须转移所有æƒæˆ–删除这些群组,然åŽæ‰èƒ½åˆ é™¤æ‚¨çš„å¸æˆ·ã€‚"
@@ -26075,7 +26372,7 @@ msgid "Profiles|e.g. My MacBook key"
msgstr "例如: My MacBook Key"
msgid "Profiles|https://website.com"
-msgstr ""
+msgstr "https://website.com"
msgid "Profiles|username"
msgstr "用户å"
@@ -26321,19 +26618,19 @@ msgid "ProjectSelect| or group"
msgstr "或群组"
msgid "ProjectSelect|No matching results"
-msgstr ""
+msgstr "没有匹é…的结果"
msgid "ProjectSelect|Search for project"
msgstr "æœç´¢é¡¹ç›®"
msgid "ProjectSelect|Search projects"
-msgstr ""
+msgstr "æœç´¢é¡¹ç›®"
msgid "ProjectSelect|Select a project"
-msgstr ""
+msgstr "选择一个项目"
msgid "ProjectSelect|There was an error fetching the projects. Please try again."
-msgstr ""
+msgstr "获å–项目时出错。请é‡è¯•ã€‚"
msgid "ProjectService|Drone server URL"
msgstr "Drone æœåŠ¡å™¨URL"
@@ -26347,6 +26644,9 @@ msgstr "输入新密ç "
msgid "ProjectService|Enter new password."
msgstr "输入新密ç ã€‚"
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr "议题 URL"
@@ -26362,6 +26662,9 @@ msgstr "留空时,使用您当å‰çš„密ç "
msgid "ProjectService|Leave blank to use your current password."
msgstr "留空时,使用您当å‰çš„密ç ã€‚"
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr "模拟æœåŠ¡URL"
@@ -26423,7 +26726,7 @@ msgid "ProjectService|Trigger event when a new, unique alert is recorded."
msgstr "在记录新的ã€å”¯ä¸€çš„警报时触å‘事件。"
msgid "ProjectService|Trigger event when a new, unique vulnerability is recorded. (Note: This feature requires an Ultimate plan.)"
-msgstr ""
+msgstr "在记录新的独特æ¼æ´žæ—¶è§¦å‘事件。(注æ„:此功能需è¦æ——舰版方案。)"
msgid "ProjectService|Trigger event when a pipeline status changes."
msgstr "æµæ°´çº¿çŠ¶æ€æ›´æ”¹æ—¶è§¦å‘事件。"
@@ -26545,6 +26848,9 @@ msgstr "Git大文件存储 (LFS)"
msgid "ProjectSettings|Global"
msgstr "全局"
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr "内部"
@@ -26557,6 +26863,9 @@ msgstr "议题"
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr "此仓库中的 LFS 对象å¯ä¾›æ´¾ç”Ÿã€‚ %{linkStart}我如何移除它们?%{linkEnd}"
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr "管ç†å¤§åž‹æ–‡ä»¶ï¼Œä¾‹å¦‚音频ã€è§†é¢‘和图形文件。"
@@ -26734,6 +27043,9 @@ msgstr "此派生的å¯è§æ€§é€‰é¡¹å—æºé¡¹ç›®å½“å‰å¯è§æ€§çš„é™åˆ¶ã€‚"
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr "å¯è§†åŒ–项目的性能指标。"
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr "什么是徽章?"
@@ -26824,6 +27136,9 @@ msgstr "Spring"
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr "é™æ€ç«™ç‚¹ç¼–辑器/Middleman"
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
@@ -26840,13 +27155,13 @@ msgid "Projects are graded based on the highest severity vulnerability present"
msgstr "按项目所包å«æœ€é«˜å±é™©ç¨‹åº¦å®‰å…¨æ¼æ´žåˆ†çº§"
msgid "Projects are organized into groups"
-msgstr ""
+msgstr "项目被组织æˆç¾¤ç»„"
msgid "Projects contributed to"
msgstr "贡献的项目"
msgid "Projects help you organize your work. They contain your file repository, issues, merge requests, and so much more."
-msgstr ""
+msgstr "项目å¯å¸®åŠ©æ‚¨ç»„织工作。它们包å«æ‚¨çš„文件仓库ã€è®®é¢˜ã€åˆå¹¶è¯·æ±‚等等。"
msgid "Projects shared with %{group_name}"
msgstr "与 %{group_name} 共享的项目"
@@ -26905,6 +27220,9 @@ msgstr "此功能需è¦æµè§ˆå™¨æ”¯æŒæœ¬åœ°å­˜å‚¨"
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr "å…许您立å³å…‹éš†è¿™ä¸ªé¡¹ç›®çš„仓库。如果您计划推é€ä¸€ä¸ªçŽ°æœ‰çš„仓库,请跳过这个步骤。"
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr "将外部仓库连接到GitLab CI/CD"
@@ -26932,6 +27250,9 @@ msgstr "创建新项目"
msgid "ProjectsNew|Description format"
msgstr "æè¿°æ ¼å¼"
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr "导入"
@@ -26947,6 +27268,9 @@ msgstr "从外部æºï¼ˆå¦‚ GitHubã€Bitbucket 或 GitLab 的其他实例)è¿ç§
msgid "ProjectsNew|No import options available"
msgstr "没有å¯ç”¨çš„导入选项"
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "项目æè¿°%{tag_start}(å¯é€‰)%{tag_end}"
@@ -26962,54 +27286,9 @@ msgstr "想è¦åœ¨åŒä¸€å‘½å空间下存放几个ä¾èµ–项目?请%{link_start
msgid "Prometheus"
msgstr "Prometheus"
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr "%{count}项警报已应用"
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr "%{firingCount}次触å‘"
-
-msgid "PrometheusAlerts|Add alert"
-msgstr "添加警报"
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr "编辑警报"
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr "创建警报时出错"
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr "删除警报时出错"
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr "获å–警报时出错"
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr "ä¿å­˜è­¦æŠ¥æ—¶å‡ºé”™"
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr "触å‘: %{alerts}"
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr "触å‘: %{alert}"
-
-msgid "PrometheusAlerts|Operator"
-msgstr "æ“作符"
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr "Runbook URL (å¯é€‰)"
-
-msgid "PrometheusAlerts|Select query"
-msgstr "选择查询"
-
-msgid "PrometheusAlerts|Threshold"
-msgstr "阈值"
-
msgid "PrometheusAlerts|exceeded"
msgstr "超过"
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr "https://gitlab.com/gitlab-com/runbooks"
-
msgid "PrometheusAlerts|is equal to"
msgstr "等于"
@@ -27086,7 +27365,7 @@ msgid "PrometheusService|Select this checkbox to override the auto configuration
msgstr "选中此å¤é€‰æ¡†å¯ä½¿ç”¨æ‚¨è‡ªå·±çš„设置覆盖自动é…置设置。"
msgid "PrometheusService|The ID of the IAP-secured resource."
-msgstr ""
+msgstr "IAP 安全资æºçš„ ID。"
msgid "PrometheusService|The Prometheus API base URL."
msgstr "Prometheus API 基本 URL。"
@@ -27313,9 +27592,6 @@ msgstr "ä¿æŠ¤åˆ†æ”¯"
msgid "Protected Environment"
msgstr "å—ä¿æŠ¤çš„环境"
-msgid "Protected Paths"
-msgstr "å—ä¿æŠ¤çš„路径"
-
msgid "Protected Paths: requests"
msgstr "å—ä¿æŠ¤çš„路径:请求"
@@ -27331,6 +27607,9 @@ msgstr "å—ä¿æŠ¤çš„分支"
msgid "Protected environments"
msgstr "å—ä¿æŠ¤çš„环境"
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr "支æŒä¾‹å¦‚%{code_tag_start}*-stable%{code_tag_end}或%{code_tag_start}production/*%{code_tag_end} çš„%{wildcards_link_start}通é…符%{wildcards_link_end}。"
@@ -27469,6 +27748,9 @@ msgstr "什么是å—ä¿æŠ¤çš„标签?"
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr "æ示:%{linkStart}Auto DevOps%{linkEnd} 使用 Kubernetes 集群æ¥éƒ¨ç½²æ‚¨çš„代ç ï¼"
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr "æ供者"
@@ -27481,6 +27763,9 @@ msgstr "æ供者:"
msgid "Proxy support for this API is not available currently"
msgstr "æ­¤APIç›®å‰ä¸æ”¯æŒä½¿ç”¨ä»£ç†"
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr "匿å化数æ®æ”¶é›†"
@@ -27667,9 +27952,6 @@ msgstr "查询"
msgid "Query cannot be processed"
msgstr "查询无法处ç†"
-msgid "Query is valid"
-msgstr "查询有效"
-
msgid "Queued"
msgstr "队列中"
@@ -27703,9 +27985,12 @@ msgstr "速率é™åˆ¶"
msgid "Rate limit"
msgstr "速率é™åˆ¶"
-msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
+msgid "Rate limit access to specified paths."
msgstr ""
+msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
+msgstr "速率é™åˆ¶æœ‰åŠ©äºŽå‡å°‘请求é‡ï¼ˆä¾‹å¦‚æ¥è‡ªçˆ¬è™«æˆ–滥用机器人的请求)。"
+
msgid "Raw blob request rate limit per minute"
msgstr "æ¯åˆ†é’ŸåŽŸå§‹Blob请求速率é™åˆ¶"
@@ -27719,7 +28004,7 @@ msgid "Re-authentication required"
msgstr "需è¦é‡æ–°è®¤è¯"
msgid "Re-import"
-msgstr ""
+msgstr "é‡æ–°å¯¼å…¥"
msgid "Re-request review"
msgstr "é‡æ–°è¯·æ±‚审核"
@@ -27743,7 +28028,7 @@ msgid "Read more about related issues"
msgstr "了解更多关于相关议题的信æ¯"
msgid "Read their documentation."
-msgstr ""
+msgstr "阅读他们的文档。"
msgid "Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project."
msgstr "准备好开始使用 GitLab 了å—?按照以下步骤设置您的工作区ã€è®¡åˆ’å’Œæ交更改以åŠéƒ¨ç½²æ‚¨çš„项目。"
@@ -27779,7 +28064,7 @@ msgid "Receive any notifications from GitLab."
msgstr "接收æ¥è‡ª GitLab 的任何通知。"
msgid "Receive notification of abuse reports by email."
-msgstr ""
+msgstr "通过电å­é‚®ä»¶æŽ¥æ”¶æ»¥ç”¨æŠ¥å‘Šé€šçŸ¥ã€‚"
msgid "Receive notifications about your own activity"
msgstr "接收关于您自己活动的通知"
@@ -27790,15 +28075,15 @@ msgstr "接收产å“è¥é”€ç”µå­é‚®ä»¶"
msgid "Recent"
msgstr "最近"
-msgid "Recent Deliveries"
-msgstr "最近传é€"
-
msgid "Recent Project Activity"
msgstr "最近的项目动æ€"
msgid "Recent Searches Service is unavailable"
msgstr "最近æœç´¢æœåŠ¡ä¸å¯ç”¨"
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr "此Runner最近执行的作业"
@@ -28018,7 +28303,7 @@ msgid "Release|Something went wrong while saving the release details."
msgstr "ä¿å­˜å‘布详细信æ¯æ—¶å‡ºé”™ã€‚"
msgid "Reload page"
-msgstr ""
+msgstr "é‡æ–°åŠ è½½é¡µé¢"
msgid "Remediations"
msgstr "ä¿®å¤æŽªæ–½"
@@ -28278,6 +28563,9 @@ msgstr "使用 PlantUML 在您的文档中渲染图表。"
msgid "Renew subscription"
msgstr "续订"
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr "é‡æ–°æ‰“å¼€"
@@ -28303,7 +28591,7 @@ msgid "Reopens this %{quick_action_target}."
msgstr "é‡æ–°æ‰“å¼€%{quick_action_target}。"
msgid "Repeats"
-msgstr ""
+msgstr "é‡å¤"
msgid "Replace"
msgstr "替æ¢"
@@ -28606,6 +28894,9 @@ msgstr "仓库: %{counter_repositories} /Wikis: %{counter_wikis} /构建产物:
msgid "RepositorySettingsAccessLevel|Select"
msgstr "选择"
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "申请æƒé™"
@@ -28615,9 +28906,6 @@ msgstr "请求一个新的"
msgid "Request details"
msgstr "请求详情"
-msgid "Request new confirmation email"
-msgstr "请求新的确认电å­é‚®ä»¶"
-
msgid "Request parameter %{param} is missing."
msgstr "请求å‚æ•°%{param}缺失。"
@@ -28664,7 +28952,7 @@ msgid "Require additional authentication for administrative tasks."
msgstr "需è¦å¯¹ç®¡ç†ä»»åŠ¡è¿›è¡Œé¢å¤–的身份验è¯ã€‚"
msgid "Require all users in this group to set up two-factor authentication"
-msgstr ""
+msgstr "è¦æ±‚此群组中的所有用户都设置åŒé‡è®¤è¯"
msgid "Required approvals (%{approvals_given} given)"
msgstr "必需的核准(%{approvals_given}已完æˆ)"
@@ -28696,19 +28984,19 @@ msgstr "需求"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr "需求å¯ä»¥åŸºäºŽç”¨æˆ·ã€åˆ©ç›Šç›¸å…³è€…ã€ç³»ç»Ÿã€è½¯ä»¶æˆ–您认为é‡è¦çš„其他任何东西。"
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] "éœ€è¦ %{count}个%{names} 的核准"
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
+msgstr[0] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
-msgstr[0] "éœ€è¦ %d 个核准"
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
+msgstr[0] ""
msgid "Requires values to meet regular expression requirements."
msgstr "需è¦å€¼åŒ¹é…正则表达å¼ã€‚"
msgid "Requires you to deploy or set up cloud-hosted Sentry."
-msgstr ""
+msgstr "需è¦æ‚¨éƒ¨ç½²æˆ–设置云托管的 Sentry。"
msgid "Requires your primary GitLab email address."
msgstr "需è¦æ‚¨çš„主GitLab电å­é‚®ä»¶åœ°å€ã€‚"
@@ -28828,7 +29116,7 @@ msgid "Response text"
msgstr "å“应文本"
msgid "Restart GitLab to apply changes."
-msgstr ""
+msgstr "é‡å¯ GitLab 以应用更改。"
msgid "Restart Terminal"
msgstr "é‡å¯ç»ˆç«¯"
@@ -28849,7 +29137,7 @@ msgid "Restoring the project will prevent the project from being removed on this
msgstr "æ¢å¤è¯¥é¡¹ç›®å°†é˜²æ­¢é¡¹ç›®åœ¨æ­¤æ—¥æœŸè¢«åˆ é™¤å¹¶æ¢å¤ç”¨æˆ·å¯¹å…¶è¿›è¡Œæ›´æ”¹çš„能力。"
msgid "Restrict group access by IP address. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "通过 IP 地å€é™åˆ¶ç¾¤ç»„访问。%{link_start}了解更多%{link_end}。"
msgid "Restrict membership by email domain"
msgstr "通过电å­é‚®ä»¶åŸŸé™åˆ¶æˆå‘˜èµ„æ ¼"
@@ -29045,9 +29333,6 @@ msgstr "Runner"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr "Runner用于接收和执行GitLab的CI/CD作业的进程。"
-msgid "Runners can be:"
-msgstr "Runnerå¯ä»¥æ˜¯ï¼š"
-
msgid "Runners currently online: %{active_runners_count}"
msgstr "当å‰åœ¨çº¿Runner: %{active_runners_count}"
@@ -29072,6 +29357,15 @@ msgstr "架构"
msgid "Runners|Are you sure you want to delete this runner?"
msgstr "确定è¦åˆ é™¤æ­¤runnerå—?"
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr "å¯ä»¥è¿è¡Œæœªæ ‡è®°çš„作业"
@@ -29081,6 +29375,9 @@ msgstr "注册runner的命令"
msgid "Runners|Copy instructions"
msgstr "å¤åˆ¶è¯´æ˜Ž"
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr "在 AWS 中部署 GitLab Runner"
@@ -29132,6 +29429,9 @@ msgstr "已生æˆæ–°çš„注册令牌ï¼"
msgid "Runners|New runner, has not connected yet"
msgstr "新的Runner,尚未连接"
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr "未连接"
@@ -29153,6 +29453,24 @@ msgstr "属性å称"
msgid "Runners|Protected"
msgstr "å—ä¿æŠ¤"
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr "版本"
@@ -29163,7 +29481,7 @@ msgid "Runners|Runner #%{runner_id}"
msgstr "Runner #%{runner_id}"
msgid "Runners|Runner assigned to project."
-msgstr ""
+msgstr "分é…给项目的runner"
msgid "Runners|Runner is offline, last contact was %{runner_contact} ago"
msgstr "Runner 处于离线状æ€ï¼Œæœ€åŽè¿žæŽ¥æ˜¯åœ¨%{runner_contact}å‰"
@@ -29178,7 +29496,7 @@ msgid "Runners|Runner registration"
msgstr "Runner 注册"
msgid "Runners|Runner unassigned from project."
-msgstr ""
+msgstr "å–消分é…到项目的runner。"
msgid "Runners|Runners"
msgstr "Runner"
@@ -29192,6 +29510,9 @@ msgstr "共享Runnerå¯ç”¨äºŽ GitLab 实例中的æ¯ä¸ªé¡¹ç›®ã€‚如果您希望R
msgid "Runners|Show Runner installation instructions"
msgstr "显示Runner安装说明"
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr "获å–Runneræ•°æ®æ—¶å‡ºé”™ã€‚"
@@ -29255,6 +29576,9 @@ msgstr "您将è¦å°†æ­¤å®žä¾‹çš„runner更改为项目runner,此æ“作ä¸å¯é€†
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr "您å¯ä»¥è®¾ç½®ä¸€ä¸ªç‰¹å®šçš„Runner供多个项目使用,但是您ä¸èƒ½è®©å®ƒæˆä¸ºä¸€ä¸ªå…±äº«çš„Runner。"
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "您已使用了%{quotaUsed},超出了共享æµæ°´çº¿æ—¶é—´é…é¢é™åˆ¶ï¼ˆ%{quotaLimit} )。"
@@ -29285,15 +29609,6 @@ msgstr "è¿è¡Œä¸­"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "在当å‰ä»“库中è¿è¡Œä¸€äº›ä¾‹è¡Œç»´æŠ¤ä»»åŠ¡ï¼Œä¾‹å¦‚压缩文件修订和删除无法访问的对象。"
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr "从所在群组的所有未分é…项目中执行任务。"
-
-msgid "Runs jobs from all unassigned projects."
-msgstr "从所有未分é…项目中执行任务。"
-
-msgid "Runs jobs from assigned projects."
-msgstr "è¿è¡ŒæŒ‡å®šé¡¹ç›®çš„作业。"
-
msgid "SAML"
msgstr "SAML"
@@ -29373,7 +29688,7 @@ msgid "SastEntryPoints|How do I set up SAST?"
msgstr "如何设置 SAST?"
msgid "SastEntryPoints|Learn more"
-msgstr ""
+msgstr "了解更多"
msgid "Satisfied"
msgstr "满足"
@@ -29390,9 +29705,6 @@ msgstr "ä¿å­˜%{name}大å°é™åˆ¶"
msgid "Save Changes"
msgstr "ä¿å­˜ä¿®æ”¹"
-msgid "Save Value Stream"
-msgstr "ä¿å­˜ä»·å€¼æµ"
-
msgid "Save application"
msgstr "ä¿å­˜åº”用"
@@ -29415,7 +29727,7 @@ msgid "Save pipeline schedule"
msgstr "ä¿å­˜æµæ°´çº¿è®¡åˆ’"
msgid "Save storage space by automatically deleting tags from the container registry and keeping the ones you want. %{linkStart}How does cleanup work?%{linkEnd}"
-msgstr ""
+msgstr "通过自动从容器镜åƒåº“中删除标签并ä¿ç•™æ‚¨æƒ³è¦çš„标签æ¥èŠ‚çœå­˜å‚¨ç©ºé—´ã€‚%{linkStart}清ç†å¦‚何工作?%{linkEnd}"
msgid "Saving"
msgstr "ä¿å­˜ä¸­"
@@ -29589,7 +29901,7 @@ msgid "Search or filter results…"
msgstr "æœç´¢æˆ–筛选结果…"
msgid "Search or jump to..."
-msgstr ""
+msgstr "æœç´¢æˆ–跳转到..."
msgid "Search project"
msgstr "æœç´¢é¡¹ç›®"
@@ -29652,16 +29964,16 @@ msgid "SearchCodeResults|of %{link_to_project}"
msgstr "于%{link_to_project}项目中"
msgid "SearchResults|Showing %{count} %{scope} for %{term_element}"
-msgstr ""
+msgstr "显示包å«%{term_element}中%{count}项的%{scope}"
msgid "SearchResults|Showing %{count} %{scope} for %{term_element} in your personal and project snippets"
-msgstr ""
+msgstr "在个人和项目代ç ç‰‡æ®µä¸­æ˜¾ç¤ºæœç´¢%{term_element}结果的%{count}项%{scope}"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for %{term_element}"
-msgstr ""
+msgstr "显示%{term_element}的 %{from} - %{to}/ %{count} %{scope}"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for %{term_element} in your personal and project snippets"
-msgstr ""
+msgstr "在个人和项目代ç ç‰‡æ®µä¸­æ˜¾ç¤ºæœç´¢%{term_element}结果的%{count}项%{scope}里的第%{from}项 - 第%{to}项"
msgid "SearchResults|code result"
msgid_plural "SearchResults|code results"
@@ -29710,6 +30022,9 @@ msgstr[0] "wiki结果"
msgid "Searching by both author and message is currently not supported."
msgstr "ç›®å‰ä¸æ”¯æŒä½œè€…和消æ¯åŒæ—¶æœç´¢ã€‚"
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr "席ä½ä½¿ç”¨æƒ…况数æ®ï¼Œæˆªè‡³ %{last_enqueue_time} (æ¯å¤©æ›´æ–°ï¼‰"
@@ -29732,7 +30047,7 @@ msgid "Secret Detection"
msgstr "密ç æ£€æµ‹"
msgid "Secret access key"
-msgstr ""
+msgstr "Secret 访问密钥"
msgid "Secret token"
msgstr "Secret令牌"
@@ -29792,7 +30107,7 @@ msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More
msgstr "当结果中包å«æ‹’ç»çš„许å¯è¯æ—¶æ ¸å‡†ä¸ºå¿…须。%{linkStart}更多信æ¯%{linkEnd}"
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "需è¦æ‰¹å‡†æ‰èƒ½é™ä½Žæµ‹è¯•è¦†ç›–率。%{linkStart}了解更多。%{linkEnd}"
msgid "SecurityApprovals|Requires approval for vulnerabilities. %{linkStart}Learn more.%{linkEnd}"
msgstr "需è¦å¯¹æ¼æ´žè¿›è¡Œå®¡æ‰¹ã€‚ %{linkStart}了解更多。%{linkEnd}"
@@ -29861,10 +30176,10 @@ msgid "SecurityConfiguration|Immediately begin risk analysis and remediation wit
msgstr "使用应用程åºå®‰å…¨åŠŸèƒ½ç«‹å³å¼€å§‹é£Žé™©åˆ†æžå’Œè¡¥æ•‘。从 SAST å’Œ Secret 检测开始,适用于所有计划。å‡çº§åˆ° Ultimate 以获得所有功能,包括:"
msgid "SecurityConfiguration|Manage corpus"
-msgstr ""
+msgstr "管ç†è¯­æ–™åº“"
msgid "SecurityConfiguration|Manage corpus files used as mutation sources in coverage fuzzing."
-msgstr ""
+msgstr "管ç†åœ¨è¦†ç›–模糊测试中用作å˜å¼‚æºçš„语料库文件。"
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
msgstr "管ç†ä¾› DAST 扫æ使用的é…置文件。"
@@ -29921,10 +30236,10 @@ msgid "SecurityOrchestration|Action"
msgstr "行动"
msgid "SecurityOrchestration|Actions"
-msgstr ""
+msgstr "行动"
msgid "SecurityOrchestration|Add rule"
-msgstr ""
+msgstr "添加规则"
msgid "SecurityOrchestration|All policies"
msgstr "所有策略"
@@ -29935,18 +30250,21 @@ msgstr "分é…您的安全策略项目时出错"
msgid "SecurityOrchestration|Description"
msgstr "æè¿°"
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr "编辑策略"
msgid "SecurityOrchestration|Edit policy project"
msgstr "编辑策略项目"
+msgid "SecurityOrchestration|Enabled"
+msgstr ""
+
msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr "强制此项目的安全性。 %{linkStart}更多信æ¯ã€‚%{linkEnd}"
-msgid "SecurityOrchestration|Enforcement Status"
-msgstr "执行状æ€"
-
msgid "SecurityOrchestration|Executes a %{scanType} scan"
msgstr "执行 %{scanType} 扫æ"
@@ -29975,7 +30293,7 @@ msgid "SecurityOrchestration|Policy editor"
msgstr "策略编辑器"
msgid "SecurityOrchestration|Policy preview"
-msgstr ""
+msgstr "策略预览"
msgid "SecurityOrchestration|Policy status"
msgstr "策略状æ€"
@@ -29987,7 +30305,7 @@ msgid "SecurityOrchestration|Rule"
msgstr "规则"
msgid "SecurityOrchestration|Rules"
-msgstr ""
+msgstr "规则"
msgid "SecurityOrchestration|Scan Execution"
msgstr "扫æ执行"
@@ -29995,6 +30313,9 @@ msgstr "扫æ执行"
msgid "SecurityOrchestration|Scan execution"
msgstr "扫æ执行"
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr "在 %{branches} 上扫ææ¯ä¸€ä¸ª %{cadence}"
@@ -30013,6 +30334,9 @@ msgstr "选择安全项目"
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr "对ä¸èµ·ï¼Œæ‚¨çš„过滤器没有产生任何结果。"
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr "创建新的安全策略时出现问题"
@@ -30082,9 +30406,12 @@ msgstr "创建 Jira 议题"
msgid "SecurityReports|Create issue"
msgstr "创建议题"
-msgid "SecurityReports|Development vulnerabilities"
+msgid "SecurityReports|Create policy"
msgstr ""
+msgid "SecurityReports|Development vulnerabilities"
+msgstr "å¼€å‘æ¼æ´ž"
+
msgid "SecurityReports|Dismiss vulnerability"
msgstr "忽略æ¼æ´ž"
@@ -30101,10 +30428,7 @@ msgid "SecurityReports|Download results"
msgstr "下载结果"
msgid "SecurityReports|Download scanned URLs"
-msgstr ""
-
-msgid "SecurityReports|Download scanned resources"
-msgstr "下载扫æ资æº"
+msgstr "下载扫æçš„ URL"
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr "您无æƒæŸ¥çœ‹æ­¤ä»ªè¡¨æ¿æˆ–尚未设置仪表æ¿ã€‚请å‘管ç†å‘˜æŸ¥è¯¢æ‚¨çš„æƒé™è®¾ç½®ï¼Œæˆ–检查仪表æ¿é…置以继续。"
@@ -30139,6 +30463,15 @@ msgstr "了解更多关于仪表æ¿åˆ›å»ºçš„ä¿¡æ¯"
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr "管ç†å’Œè·Ÿè¸ªæ‚¨ç»„内项目中å‘现的æ¼æ´žã€‚é…置安全测试时,此处显示项目中的æ¼æ´žã€‚"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr "管ç†å’Œè·Ÿè¸ªæ‚¨çš„项目中å‘现的æ¼æ´žã€‚é…置安全测试时,此处会显示æ¼æ´žã€‚"
@@ -30148,6 +30481,9 @@ msgstr "管ç†å’Œè·Ÿè¸ªåœ¨æ‚¨é€‰æ‹©çš„项目中å‘现的æ¼æ´žã€‚此处显示了
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr "已达到最大选定项目é™åˆ¶"
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr "监控您所有项目中的æ¼æ´ž"
@@ -30178,6 +30514,9 @@ msgstr "æ­¤æµæ°´çº¿ä¸­æœªå‘现æ¼æ´ž"
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr "哎呀,看起æ¥ä¸æ­£ç¡®ã€‚"
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr "项目"
@@ -30227,7 +30566,7 @@ msgid "SecurityReports|Take survey"
msgstr "å‚加调查"
msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "æ¼æ´žæŠ¥å‘Šæ˜¾ç¤ºé¡¹ç›®é»˜è®¤åˆ†æ”¯ä¸Šæœ€æ–°æˆåŠŸæµæ°´çº¿çš„结果,以åŠæœ€æ–°å®¹å™¨æ‰«æçš„æ¼æ´žã€‚%{linkStart}了解更多。%{linkEnd}"
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
msgstr "下é¢çš„安全报告包å«ä¸€ä¸ªæˆ–多个无法解æžä¸”未记录的æ¼æ´žå‘现。下载作业输出中的产物以进行调查。确ä¿åˆ›å»ºçš„任何安全报告都符åˆç›¸å…³çš„ %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}。"
@@ -30301,6 +30640,9 @@ msgstr "您必须以授æƒç”¨æˆ·èº«ä»½ç™»å½•æ‰èƒ½æŸ¥çœ‹æ­¤æŠ¥å‘Š"
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr "您的å馈对我们很é‡è¦ï¼æˆ‘们将在一周内å†æ¬¡è¯¢é—®ã€‚"
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr "请å‚阅我们文档中的示例 DevOps Score 页é¢ã€‚"
@@ -30340,12 +30682,12 @@ msgstr "选择页é¢"
msgid "Select a branch"
msgstr "选择分支"
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "请先从左侧边æ é€‰æ‹©ä¸€ä¸ªæ–‡ä»¶å¼€å§‹ç¼–辑,然åŽå°±å¯ä»¥æ交您的更改了。"
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
-msgstr "选择适用于该项目的框架。 %{linkStart}这些是如何添加的?%{linkEnd}"
-
msgid "Select a group to invite"
msgstr "选择è¦é‚€è¯·çš„组"
@@ -30361,17 +30703,11 @@ msgstr "选择一个新的命å空间"
msgid "Select a project"
msgstr "选择一个项目"
-msgid "Select a project to read Insights configuration file"
-msgstr "选择è¦è¯»å– Insights é…置文件的项目"
-
msgid "Select a reason"
msgstr "选择原因"
-msgid "Select a repository"
-msgstr "选择一个仓库"
-
msgid "Select a repository containing templates for common files."
-msgstr ""
+msgstr "选择一个包å«å¸¸è§æ–‡ä»¶æ¨¡æ¿çš„仓库。"
msgid "Select a role"
msgstr "选择一个角色"
@@ -30452,7 +30788,7 @@ msgid "Select project to choose zone"
msgstr "按项目选择地域"
msgid "Select project to create issue"
-msgstr ""
+msgstr "选择è¦åˆ›å»ºè®®é¢˜çš„项目"
msgid "Select projects"
msgstr "选择项目"
@@ -30572,7 +30908,7 @@ msgid "Send emails to help guide new users through the onboarding process."
msgstr "å‘é€ç”µå­é‚®ä»¶ä»¥å¸®åŠ©æŒ‡å¯¼æ–°ç”¨æˆ·å®Œæˆæ–°äººæµç¨‹ã€‚"
msgid "Send emails to users upon account deactivation."
-msgstr ""
+msgstr "å¸æˆ·åœç”¨åŽå‘用户å‘é€ç”µå­é‚®ä»¶ã€‚"
msgid "Send message"
msgstr "å‘é€ä¿¡æ¯â€‹â€‹â€‹â€‹â€‹â€‹â€‹â€‹"
@@ -30593,7 +30929,7 @@ msgid "Send service data"
msgstr "å‘é€æœåŠ¡æ•°æ®"
msgid "Sentry"
-msgstr ""
+msgstr "Sentry"
msgid "Sentry API URL"
msgstr "Sentry API URL"
@@ -30628,9 +30964,6 @@ msgstr "æœåŠ¡å™¨ç‰ˆæœ¬"
msgid "Serverless"
msgstr "Serverless"
-msgid "Serverless domain"
-msgstr "æ— æœåŠ¡å™¨åŸŸ"
-
msgid "Serverless platform"
msgstr "æ— æœåŠ¡å™¨å¹³å°"
@@ -30710,7 +31043,7 @@ msgid "Service"
msgstr "æœåŠ¡"
msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
-msgstr ""
+msgstr "éœ€è¦ Service Accounts 密钥æ‰èƒ½æŽˆæƒ GitLab 部署您的 Google Cloud 项目。"
msgid "Service Desk"
msgstr "æœåŠ¡å°"
@@ -30730,9 +31063,6 @@ msgstr "å¯ç”¨æœåŠ¡å°"
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr "有关为您的实例设置æœåŠ¡å°çš„帮助,请è”系管ç†å‘˜ã€‚"
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr "从æœåŠ¡å°ç”µå­é‚®ä»¶åˆ›å»ºçš„议题显示在此处,æ¯æ¡è¯„论都æˆä¸ºç”µå­é‚®ä»¶å¯¹è¯çš„一部分。"
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr "从æœåŠ¡å°ç”µå­é‚®ä»¶åˆ›å»ºçš„议题将显示在此处,æ¯æ¡è¯„论都æˆä¸ºç”µå­é‚®ä»¶å¯¹è¯çš„一部分。"
@@ -30787,11 +31117,8 @@ msgstr "为账å·åˆ›å»ºä¸€ä¸ªç”¨äºŽæŽ¨é€æˆ–拉å–çš„ %{protocol} 密ç ã€‚"
msgid "Set access permissions for this token."
msgstr "设置此令牌的访问æƒé™ã€‚"
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr "设置实例级别的域,å¯ç”¨äºŽæ‰€æœ‰é›†ç¾¤å®‰è£…Knative。"
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
-msgstr ""
+msgstr "将任何速率é™åˆ¶è®¾ç½®ä¸º %{code_open}0%{code_close} 以ç¦ç”¨è¯¥é™åˆ¶ã€‚"
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "设定缺çœåŠå—é™å¯è§æ€§çº§åˆ«ã€‚é…置导入æ¥æºåŠgit访问å议。"
@@ -30806,7 +31133,7 @@ msgid "Set limit to 0 to allow any file size."
msgstr "设置é™åˆ¶ä¸º 0 以å…许任何文件大å°ã€‚"
msgid "Set limits for web and API requests."
-msgstr ""
+msgstr "为 Web å’Œ API 请求设置é™åˆ¶ã€‚"
msgid "Set milestone"
msgstr "设置里程碑"
@@ -30818,13 +31145,13 @@ msgid "Set parent epic to an epic"
msgstr "为å²è¯—设置上级å²è¯—"
msgid "Set per-user rate limits for imports and exports of projects and groups."
-msgstr ""
+msgstr "为项目和群组的导入和导出设置æ¯ä¸ªç”¨æˆ·çš„速率é™åˆ¶ã€‚"
msgid "Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan."
msgstr "设置项目和最大空间é™åˆ¶ã€ä¼šè¯æŒç»­æ—¶é—´ã€ç”¨æˆ·é€‰é¡¹ï¼Œå¹¶æ£€æŸ¥å‘½å空间计划的功能å¯ç”¨æ€§ã€‚"
msgid "Set rate limits for package registry API requests that supersede the general user and IP rate limits."
-msgstr ""
+msgstr "为 Packages registry API 请求é…置速率é™åˆ¶ä»¥å–代一般用户和 IP 速率é™åˆ¶ã€‚"
msgid "Set severity"
msgstr "设置严é‡æ€§"
@@ -30845,7 +31172,7 @@ msgid "Set the default branch for this project. All merge requests and commits a
msgstr "设置此项目的默认分支。除éžæ‚¨æŒ‡å®šä¸åŒçš„分支,å¦åˆ™æ‰€æœ‰åˆå¹¶è¯·æ±‚å’Œæ交都是针对此分支进行的。"
msgid "Set the default expiration time for job artifacts in all projects. Set to %{code_open}0%{code_close} to never expire artifacts by default. If no unit is written, it defaults to seconds. For example, these are all equivalent: %{code_open}3600%{code_close}, %{code_open}60 minutes%{code_close}, or %{code_open}one hour%{code_close}."
-msgstr ""
+msgstr "为所有项目中的作业产物设置默认到期时间。默认情况下设置为 %{code_open}0%{code_close} 表示永ä¸è¿‡æœŸã€‚如果没有写入å•ä½ï¼Œåˆ™é»˜è®¤ä¸ºç§’。例如,以下都是等价的: %{code_open}3600%{code_close}〠%{code_open}60 minutes%{code_close}或 %{code_open}one hour%{code_close}。"
msgid "Set the due date to %{due_date}."
msgstr "设置到期日期为%{due_date}。"
@@ -30854,13 +31181,13 @@ msgid "Set the iteration to %{iteration_reference}."
msgstr "将迭代设置为%{iteration_reference}。"
msgid "Set the maximum session time for a web terminal."
-msgstr ""
+msgstr "设置 Web 终端的最长会è¯æ—¶é—´ã€‚"
msgid "Set the milestone to %{milestone_reference}."
msgstr "将里程碑设置为%{milestone_reference}。"
msgid "Set the per-user rate limit for notes created by web or API requests."
-msgstr ""
+msgstr "为由 Web 或 API 请求创建的 notes 设置æ¯ä¸ªç”¨æˆ·çš„速率é™åˆ¶ã€‚"
msgid "Set the timeout in seconds to send a secondary site status to the primary and IPs allowed for the secondary sites."
msgstr "以秒为å•ä½è®¾ç½®è¶…时,以将次è¦ç«™ç‚¹çŠ¶æ€å‘é€åˆ°ä¸»ç«™ç‚¹å’Œæ¬¡è¦ç«™ç‚¹å…许的 IP。"
@@ -30880,9 +31207,6 @@ msgstr "设置Jira集æˆ"
msgid "Set up a %{type} Runner for a project"
msgstr "为项目设置一个 %{type}的Runner"
-msgid "Set up a %{type} runner manually"
-msgstr "手动设置一个%{type}的Runner"
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr "设置一个硬件设备作为登录的第二个因素。"
@@ -30916,12 +31240,12 @@ msgstr "设置此次è¦èŠ‚点应该å¤åˆ¶çš„内容。"
msgid "SetPasswordToCloneLink|set a password"
msgstr "设置密ç "
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
-msgstr "您的å字和头åƒæ—边显示ç¹å¿™çš„标识。"
-
msgid "SetStatusModal|Add status emoji"
msgstr "添加状æ€è¡¨æƒ…"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "SetStatusModal|Busy"
msgstr "忙碌"
@@ -30929,7 +31253,7 @@ msgid "SetStatusModal|Clear status"
msgstr "清除状æ€"
msgid "SetStatusModal|Clear status after"
-msgstr "清除状æ€æ åŽçš„状æ€"
+msgstr "清除状æ€"
msgid "SetStatusModal|Edit status"
msgstr "编辑状æ€"
@@ -30985,6 +31309,10 @@ msgstr "设置"
msgid "Setting enforced"
msgstr "强制设置"
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr "设置为 0 æ„味ç€ä½¿ç”¨ç³»ç»Ÿé»˜è®¤è¶…时值。"
@@ -31064,7 +31392,7 @@ msgid "Show Pipeline IID"
msgstr "显示æµæ°´çº¿IID"
msgid "Show all %{issuable_type}."
-msgstr ""
+msgstr "显示所有 %{issuable_type}。"
msgid "Show all activity"
msgstr "显示所有活动"
@@ -31165,7 +31493,7 @@ msgid "Showing all issues"
msgstr "显示所有议题"
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
-msgstr ""
+msgstr "显示群组 “%{group_name}†从 2019 å¹´ 11 月 1 日到 2019 å¹´ 12 月 31 日的数æ®"
msgid "Showing data for workflow items created in this date range. Date range cannot exceed %{maxDateRange} days."
msgstr "显示在此日期范围内创建的工作æµé¡¹ç›®çš„æ•°æ®ã€‚日期范围ä¸èƒ½è¶…过 %{maxDateRange} 天。"
@@ -31207,13 +31535,13 @@ msgid "Sidebar|Weight"
msgstr "æƒé‡"
msgid "Sidekiq job compression threshold (bytes)"
-msgstr ""
+msgstr "Sidekiq 作业压缩阈值(字节)"
msgid "Sidekiq job size limit (bytes)"
-msgstr ""
+msgstr "Sidekiq作业大å°é™åˆ¶ (字节)"
msgid "Sidekiq job size limits"
-msgstr ""
+msgstr "Sidekiq作业大å°é™åˆ¶"
msgid "Sign in"
msgstr "登录"
@@ -31326,9 +31654,6 @@ msgstr "相似议题"
msgid "Simulate a pipeline created for the default branch"
msgstr "模拟为默认分支创建的æµæ°´çº¿"
-msgid "Single or combined queries"
-msgstr "å•ä¸ªæˆ–组åˆæŸ¥è¯¢"
-
msgid "Site profile failed to delete"
msgstr "网站é…置文件删除失败"
@@ -31336,7 +31661,7 @@ msgid "Site profile not found for given parameters"
msgstr "找ä¸åˆ°ç»™å®šå‚数的站点é…置文件"
msgid "Sites"
-msgstr ""
+msgstr "站点"
msgid "Size"
msgstr "大å°"
@@ -31369,22 +31694,22 @@ msgid "SlackIntegration|Sends notifications about project events to Slack channe
msgstr "å‘ Slack 频é“å‘é€æœ‰å…³é¡¹ç›®äº‹ä»¶çš„通知。"
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
-msgstr ""
+msgstr "1. %{slash_command_link_start}在您的Slack团队中使用此信æ¯æ·»åŠ ä¸€ä¸ªæ–œæ å‘½ä»¤%{slash_command_link_end}:"
msgid "SlackService|2. Paste the token from Slack in the %{strong_open}Token%{strong_close} field below."
-msgstr ""
+msgstr "2. 在下é¢çš„ %{strong_open}令牌%{strong_close} 字段粘贴æ¥è‡ªSlack的令牌。"
msgid "SlackService|3. Select the %{strong_open}Active%{strong_close} checkbox, select %{strong_open}Save changes%{strong_close}, and start using slash commands in Slack!"
-msgstr ""
+msgstr "3. 选择 %{strong_open}激活%{strong_close} å¤é€‰æ¡†ï¼Œé€‰æ‹© %{strong_open}ä¿å­˜æ›´æ”¹%{strong_close},然åŽå¼€å§‹ä½¿ç”¨Slackçš„æ–œæ å‘½ä»¤ï¼"
msgid "SlackService|After setup, get a list of available Slack slash commands by entering"
-msgstr ""
+msgstr "设置åŽï¼Œé€šè¿‡è¾“入获å–å¯ç”¨Slackæ–œæ å‘½ä»¤çš„列表"
msgid "SlackService|Fill in the word that works best for your team."
msgstr "填写最适åˆä½ çš„团队的文字。"
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
-msgstr ""
+msgstr "通过在Slack中输入斜æ å‘½ä»¤æ¥æ‰§è¡Œè¿™ä¸ªé¡¹ç›®ä¸­çš„常用æ“作。"
msgid "Slice multiplier"
msgstr "切片å€æ•°"
@@ -31395,6 +31720,9 @@ msgstr "智能å¡"
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "智能å¡èº«ä»½éªŒè¯å¤±è´¥ï¼šç¼ºå°‘客户端è¯ä¹¦æŠ¥å¤´ã€‚"
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "代ç ç‰‡æ®µ"
@@ -31419,6 +31747,9 @@ msgstr "存储〠分享和嵌入å°æ®µä»£ç å’Œæ–‡æœ¬ã€‚"
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "没有è¦æ˜¾ç¤ºçš„代ç ç‰‡æ®µã€‚"
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr "添加å¦ä¸€ä¸ªæ–‡ä»¶%{num}/%{total}"
@@ -31428,6 +31759,9 @@ msgstr "删除文件"
msgid "Snippets|Description (optional)"
msgstr "æè¿° (å¯é€‰)"
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr "文件"
@@ -31450,10 +31784,7 @@ msgid "Some child epics may be hidden due to applied filters"
msgstr "æŸäº›å­å²è¯—å¯èƒ½ç”±äºŽåº”用筛选器而被éšè—"
msgid "Some common domains are not allowed. %{learn_more_link}."
-msgstr ""
-
-msgid "Some of the designs you tried uploading did not change:"
-msgstr "您å°è¯•ä¸Šä¼ çš„部分设计没有改å˜ã€‚"
+msgstr "æŸäº›å¸¸è§åŸŸåä¸è¢«å…许。%{learn_more_link}"
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr "其他用户åŒæ—¶ç¼–辑了这个议题。请检查%{linkStart}议题%{linkEnd}并确ä¿æ‚¨çš„更改ä¸ä¼šæ— æ„中移除他们的更改。"
@@ -31918,10 +32249,10 @@ msgid "SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{li
msgstr "使用自定义的%{linkStart}Sourcegraph实例%{linkEnd}。"
msgid "Spam Check"
-msgstr ""
+msgstr "垃圾邮件检查"
msgid "Spam Check API key"
-msgstr ""
+msgstr "垃圾邮件检查 API 密钥"
msgid "Spam Logs"
msgstr "垃圾信æ¯æ—¥å¿—"
@@ -31939,7 +32270,7 @@ msgid "Specified URL cannot be used: \"%{reason}\""
msgstr "无法使用指定的URL:“%{reason}â€"
msgid "Specify an email address regex pattern to identify default internal users."
-msgstr ""
+msgstr "指定电å­é‚®ä»¶åœ°å€æ­£åˆ™è¡¨è¾¾å¼æ¨¡å¼ä»¥æ ‡è¯†é»˜è®¤å†…部用户。"
msgid "Speed up your pipelines with Needs relationships"
msgstr "通过Needs关系加速您的æµæ°´çº¿"
@@ -32049,12 +32380,6 @@ msgstr "开始æœç´¢"
msgid "Start thread"
msgstr "å¼€å¯ä¸»é¢˜"
-msgid "Start thread & close %{noteable_name}"
-msgstr "开始主题并关闭%{noteable_name}"
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr "å¼€å¯ä¸»é¢˜å¹¶é‡æ–°æ‰“å¼€%{noteable_name}"
-
msgid "Start your Free Ultimate Trial"
msgstr "开始您的å…费试用"
@@ -32094,6 +32419,9 @@ msgstr "开始于: %{startsAt}"
msgid "State your message to activate"
msgstr "输入消æ¯ä»¥å¯ç”¨"
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr "é™æ€åº”用程åºå®‰å…¨æµ‹è¯•(SAST)"
@@ -32194,7 +32522,7 @@ msgid "StatusCheck|An error occurred fetching the status checks."
msgstr "获å–状æ€æ£€æŸ¥æ—¶å‡ºé”™ã€‚"
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
-msgstr ""
+msgstr "将此状æ€æ£€æŸ¥åº”用于所有分支或特定的å—ä¿æŠ¤åˆ†æ”¯ã€‚"
msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr "检查åˆå¹¶è¯·æ±‚中的状æ€å“应,失败ä¸ä¼šé˜»æ­¢åˆå¹¶ã€‚ %{link_start}了解更多%{link_end}."
@@ -32533,7 +32861,7 @@ msgid "Subscriptions"
msgstr "订阅"
msgid "Subscription|Your subscription for %{strong}%{namespace_name}%{strong_close} has expired and you are now on %{pricing_link_start}the GitLab Free tier%{pricing_link_end}. Don't worry, your data is safe. Get in touch with our support team (%{support_email}). They'll gladly help with your subscription renewal."
-msgstr ""
+msgstr "您对 %{strong}%{namespace_name}%{strong_close} 的订阅已过期,您现在在 %{pricing_link_start}标准版%{pricing_link_end}了。别担心,您的数æ®æ˜¯å®‰å…¨çš„。请è”系我们的支æŒå›¢é˜Ÿï¼ˆ%{support_email})。他们将ä¹æ„帮助您更新订阅。"
msgid "Subtracted"
msgstr "å‡åŽ»"
@@ -32592,8 +32920,8 @@ msgstr "æˆåŠŸè§£é™¤ç¦ç”¨"
msgid "Successfully updated %{last_updated_timeago}."
msgstr "æˆåŠŸæ›´æ–° %{last_updated_timeago}."
-msgid "Successfully verified domain ownership"
-msgstr "æˆåŠŸéªŒè¯åŸŸæ‰€æœ‰æƒ"
+msgid "Successfully updated the environment."
+msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
msgstr "å¯ä»¥ä¸€é”®åº”用的建议代ç æ›´æ”¹åŠŸèƒ½ã€‚试试看ï¼"
@@ -32691,18 +33019,12 @@ msgstr "摘è¦/注释"
msgid "Sunday"
msgstr "星期日"
-msgid "SuperSonics|Activate"
-msgstr "激活"
-
msgid "SuperSonics|Activate cloud license"
msgstr "激活云端许å¯è¯"
msgid "SuperSonics|Activate subscription"
msgstr "激活订阅"
-msgid "SuperSonics|Activated on"
-msgstr "激活于"
-
msgid "SuperSonics|Activation code"
msgstr "激活ç "
@@ -32724,9 +33046,6 @@ msgstr "云授æƒ"
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr "Cloud 许å¯çŽ°å·²æŽ¨å‡ºã€‚这是激活实例和管ç†è®¢é˜…的更简å•æ–¹æ³•ã€‚阅读 %{blogPostLinkStart}åšå®¢æ–‡ç« %{blogPostLinkEnd}中的更多相关信æ¯ã€‚激活ç åœ¨ %{portalLinkStart}客户门户%{portalLinkEnd}中å¯ç”¨ã€‚"
-msgid "SuperSonics|Expires on"
-msgstr "到期"
-
msgid "SuperSonics|Export license usage file"
msgstr "导出许å¯è¯ä½¿ç”¨æ–‡ä»¶"
@@ -32739,12 +33058,6 @@ msgstr "通过 %{linkStart}激活ç æ•…障排查%{linkEnd},获å–最常è§çš„è
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr "我åŒæ„我对GitLab 软件的使用必须éµå®ˆä½äºŽ %{linkStart}æœåŠ¡æ¡æ¬¾%{linkEnd}的订阅å议, 除éžä¸ŽGitLabå¦æœ‰ä¹¦é¢å议。"
-msgid "SuperSonics|ID"
-msgstr "ID"
-
-msgid "SuperSonics|Last Sync"
-msgstr "上次åŒæ­¥"
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr "了解如何 %{linkStart}激活您的订阅%{linkEnd}。"
@@ -32760,30 +33073,15 @@ msgstr "最大用户数"
msgid "SuperSonics|Paste your activation code"
msgstr "粘贴您的激活ç "
-msgid "SuperSonics|Plan"
-msgstr "方案"
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
-msgstr ""
+msgstr "请åŒæ„订阅åè®®"
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr "准备好开始了å—? GitLab 方案éžå¸¸é€‚åˆæ‰©å±•ç»„织和多团队使用。"
-msgid "SuperSonics|Renews"
-msgstr "续订"
-
-msgid "SuperSonics|Seats"
-msgstr "席ä½"
-
msgid "SuperSonics|Start free trial"
msgstr "开始å…费试用"
-msgid "SuperSonics|Started"
-msgstr "å·²å¯åŠ¨"
-
-msgid "SuperSonics|Subscription"
-msgstr "订阅"
-
msgid "SuperSonics|Subscription details"
msgstr "订阅详情"
@@ -32797,7 +33095,7 @@ msgid "SuperSonics|The activation code is not valid. Please make sure to copy it
msgstr "激活ç æ— æ•ˆã€‚请确ä¿ä»Žå®¢æˆ·ç«¯é—¨æˆ·æˆ–确认电å­é‚®ä»¶å¤åˆ¶å®ƒã€‚ 了解更多关于 %{linkStart}激活您的订阅%{linkEnd}。"
msgid "SuperSonics|The activation code should be a 24-character alphanumeric string"
-msgstr ""
+msgstr "激活ç åº”该是一个24个字符的字æ¯æ•°å­—字符串"
msgid "SuperSonics|There is a connectivity issue."
msgstr "存在连接问题。"
@@ -32811,9 +33109,6 @@ msgstr "这是 %{billableUsersLinkStart}计费用户%{billableUsersLinkEnd} çš„æ
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr "è¦æ¿€æ´»æ‚¨çš„订阅,请通过 %{linkStart}Cloud Licensing%{linkEnd} æœåŠ¡è¿žæŽ¥åˆ° GitLab æœåŠ¡å™¨ï¼Œè¿™æ˜¯ä¸€ç§è½»æ¾ç®¡ç†è®¢é˜…çš„æ–¹å¼ã€‚"
-msgid "SuperSonics|Type"
-msgstr "类型"
-
msgid "SuperSonics|Upload a license file"
msgstr "上传许å¯æ–‡ä»¶"
@@ -32826,9 +33121,6 @@ msgstr "超过订阅的用户"
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr "具有访客角色的用户或ä¸å±žäºŽé¡¹ç›®æˆ–组的用户将ä¸ä¼šä½¿ç”¨æ‚¨çš„许å¯è¯ä¸­çš„席ä½ã€‚"
-msgid "SuperSonics|Valid From"
-msgstr "有效期自"
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr "您å¯ä»¥äº†è§£æ›´å¤šå…³äºŽ %{activationLinkStart}激活您的订阅%{activationLinkEnd}。如果您需è¦è¿›ä¸€æ­¥çš„帮助,请 %{supportLinkStart}è”系技术支æŒ%{supportLinkEnd}。"
@@ -32842,13 +33134,13 @@ msgid "SuperSonics|You do not have an active subscription"
msgstr "您没有有效订阅"
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
-msgstr ""
+msgstr "您已æˆåŠŸæ·»åŠ åœ¨ %{date} 激活的许å¯è¯ã€‚有关更多详细信æ¯ï¼Œè¯·å‚阅下é¢çš„订阅历å²è¡¨ã€‚"
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr "æ ¹æ®æ‚¨çš„åè®®æ¡æ¬¾ï¼Œæ‚¨å°†æŒ‰å­£åº¦æˆ–æ¯å¹´ä¸º %{trueUpLinkStart}超过许å¯è¯çš„用户%{trueUpLinkEnd}付费。"
msgid "SuperSonics|Your future dated license was successfully added"
-msgstr ""
+msgstr "您的未æ¥æ—¥æœŸè®¸å¯è¯å·²æˆåŠŸæ·»åŠ "
msgid "SuperSonics|Your subscription"
msgstr "您的订阅"
@@ -32871,6 +33163,9 @@ msgstr "支æŒé¡µé¢ç½‘å€"
msgid "Survey Response"
msgstr "é—®å·è°ƒæŸ¥ç­”å¤"
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr "切æ¢åˆ†æ”¯"
@@ -33057,6 +33352,9 @@ msgstr "使用标签,å¯ä»¥æ ‡è®°æ交历å²ä¸Šçš„特定点为é‡è¦æ交"
msgid "TagsPage|This tag has no release notes."
msgstr "此标签无å‘行说明。"
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "使用git tag命令添加一个:"
@@ -33081,6 +33379,15 @@ msgstr "目标分支"
msgid "Task ID: %{elastic_task}"
msgstr "任务ID: %{elastic_task}"
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "团队"
@@ -33093,6 +33400,9 @@ msgstr "在创建或更新åˆå¹¶è¯·æ±‚åŽè§¦å‘ TeamCity CI"
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr "æ¯æ¬¡æŽ¨é€åˆ°å­˜å‚¨åº“åŽè§¦å‘ TeamCity CI,分支删除除外"
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr "%{linkStart}在此å馈议题中%{linkEnd},告诉我们您对新 Markdown 编辑器的体验。"
@@ -33103,7 +33413,7 @@ msgid "Template to append to all Service Desk issues"
msgstr "附加到所有æœåŠ¡å°ç”Ÿæˆè®®é¢˜çš„模æ¿"
msgid "TemplateRepository|Create common files more quickly, and standardize their format."
-msgstr ""
+msgstr "更快地创建共åŒæ–‡ä»¶å¹¶ä½¿å…¶æ ¼å¼æ ‡å‡†åŒ–。"
msgid "Templates"
msgstr "模æ¿"
@@ -33305,7 +33615,7 @@ msgid "TestCases|Search test cases"
msgstr "æœç´¢æµ‹è¯•ç”¨ä¾‹"
msgid "TestCases|Something went wrong while adding test case to a to-do item."
-msgstr ""
+msgstr "å‘待办事项添加测试案例时出错。"
msgid "TestCases|Something went wrong while creating a test case."
msgstr "创建新测试用例时出现错误."
@@ -33317,7 +33627,7 @@ msgid "TestCases|Something went wrong while fetching test cases list."
msgstr "获å–测试用例列表时出错。"
msgid "TestCases|Something went wrong while marking test case to-do item as done."
-msgstr ""
+msgstr "将测试案例待办事项标记为完æˆæ—¶å‡ºé”™ã€‚"
msgid "TestCases|Something went wrong while moving test case."
msgstr "移动测试用例时出错。"
@@ -33437,7 +33747,7 @@ msgid "Thanks for your purchase!"
msgstr "感谢购买ï¼"
msgid "That's OK, I don't want to renew"
-msgstr ""
+msgstr "好的,我ä¸å¸Œæœ›ç»­çº¦"
msgid "That's it, well done!"
msgstr "就是这样,åšå¾—好ï¼"
@@ -33459,6 +33769,9 @@ msgid_plural "The %{type} contains the following errors:"
msgstr[0] "%{type} 包å«ä»¥ä¸‹é”™è¯¯ï¼š"
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
+msgstr "用于访问垃圾邮件检查æœåŠ¡ç«¯ç‚¹çš„ API 密钥."
+
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
msgstr ""
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
@@ -33530,6 +33843,9 @@ msgstr "åˆè§„报告æ•èŽ·è¿ååˆè§„最佳实践的åˆå¹¶æ›´æ”¹ã€‚"
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "该连接将在 %{timeout}åŽè¶…时。如仓库导入耗时超过该时间,请使用克隆/推é€ç»„åˆã€‚"
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr "此页é¢çš„内容未以UTF-8ç¼–ç ã€‚编辑åªèƒ½é€šè¿‡Git仓库进行。"
@@ -33560,9 +33876,6 @@ msgstr "ä¾èµ–项列表详细说明了项目中使用组件的信æ¯ã€‚"
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "将此作业部署为 %{environmentLink} 并未æˆåŠŸã€‚"
-msgid "The designs you tried uploading did not change."
-msgstr "您å°è¯•ä¸Šä¼ çš„设计没有改å˜ã€‚"
-
msgid "The directory has been successfully created."
msgstr "目录已æˆåŠŸåˆ›å»ºã€‚"
@@ -33630,6 +33943,9 @@ msgstr "表å•åŒ…å«ä»¥ä¸‹é”™è¯¯ï¼š"
msgid "The form contains the following warning:"
msgstr "该表格包å«ä»¥ä¸‹è­¦å‘Šï¼š"
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr "系统设置è¦æ±‚您为å¸æˆ·å¯ç”¨åŒé‡è®¤è¯ã€‚"
@@ -33714,6 +34030,9 @@ msgstr "许å¯è¯å·²æˆåŠŸä¸Šä¼ ï¼Œå¹¶å·²æ¿€æ´»ã€‚详细信æ¯å¦‚下。"
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr "许å¯è¯å·²æˆåŠŸä¸Šä¼ ï¼Œå°†äºŽ%{starts_at}激活。您å¯ä»¥åœ¨ä¸‹é¢çœ‹åˆ°è¯¦ç»†ä¿¡æ¯ã€‚"
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr "å…许的最大文件大å°ä¸º %{size}。"
@@ -33819,9 +34138,6 @@ msgstr "该项目æˆåŠŸæ´¾ç”Ÿã€‚"
msgid "The project was successfully imported."
msgstr "该项目已æˆåŠŸå¯¼å…¥ã€‚"
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr "匿å化数æ®æœé›†å·²ç¦ç”¨ã€‚该功能å¯ç”¨æ—¶ï¼ŒGitLab会è¿è¡ŒåŽå°ä»»åŠ¡ï¼Œç”Ÿæˆæ•°æ®åº“的匿å化CSV,并上传到预先设定的对象存储目录。"
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr "用于在作业日志中查找测试覆盖率输出的正则表达å¼ã€‚例如,对 Simplecov (Ruby) 使用%{regex}。留空以ç¦ç”¨ã€‚"
@@ -33855,9 +34171,6 @@ msgstr "仓库必须能够通过%{code_open}http://%{code_close}, %{code_open}ht
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr "åŒä¸€ä¸ªå…±äº«runnerå¯æ‰§è¡Œå¤šä¸ªé¡¹ç›®çš„代ç ï¼Œé™¤éžæ‚¨é…置了自动伸缩,将%{link}设置为1 (GitLab.com 上的设置)。"
-msgid "The schedule time must be in the future!"
-msgstr "计划è¿è¡Œæ—¶é—´å¿…须在将æ¥ï¼"
-
msgid "The snippet can be accessed without any authentication."
msgstr "无需任何身份验è¯å³å¯è®¿é—®è¯¥ä»£ç ç‰‡æ®µã€‚"
@@ -34017,6 +34330,9 @@ msgstr "还没有包"
msgid "There are no projects shared with this group yet"
msgstr "当å‰å°šæ— åˆ†äº«ç»™è¯¥ç¾¤ç»„的项目"
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr "还没有å˜é‡ã€‚"
@@ -34101,6 +34417,9 @@ msgstr "获å–最近的群组时出现问题。"
msgid "There was a problem fetching recent projects."
msgstr "获å–最近的项目时出现问题。"
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr "获å–作业令牌范围值时出现问题"
@@ -34120,7 +34439,7 @@ msgid "There was a problem updating the keep latest artifacts setting."
msgstr "æ›´æ–°ä¿æŒæœ€æ–°äº§ç‰©è®¾ç½®æ—¶å‡ºçŽ°é—®é¢˜ã€‚"
msgid "There was an error %{message} to-do item."
-msgstr ""
+msgstr "待办事项å‘生错误%{message}"
msgid "There was an error adding a To Do."
msgstr "添加待办事项时出现错误"
@@ -34159,7 +34478,7 @@ msgid "There was an error fetching projects"
msgstr "获å–项目时出错"
msgid "There was an error fetching search autocomplete suggestions"
-msgstr ""
+msgstr "获å–æœç´¢è‡ªåŠ¨å®Œæˆå»ºè®®æ—¶å‡ºé”™"
msgid "There was an error fetching stage total counts"
msgstr "获å–阶段总计数时出错"
@@ -34287,9 +34606,6 @@ msgstr "这些示例显示了如何为分支或标记触å‘此项目的æµæ°´çº¿
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr "这些现有的议题具有类似的标题。在那里评论å¯èƒ½æ›´å¥½ï¼Œè€Œä¸æ˜¯åˆ›å»ºå¦ä¸€ä¸ªç±»ä¼¼çš„问题。"
-msgid "These paths are protected for POST requests."
-msgstr "这些路径å—POST请求ä¿æŠ¤ã€‚"
-
msgid "These runners are shared across projects in this group."
msgstr "这些Runner在该群组中的项目之间共享。"
@@ -34486,7 +34802,7 @@ msgid "This field is required."
msgstr "该字段是必填字段。"
msgid "This form is disabled in preview"
-msgstr ""
+msgstr "此表å•åœ¨é¢„览中被ç¦ç”¨"
msgid "This group"
msgstr "当å‰ç¾¤ç»„"
@@ -34512,8 +34828,8 @@ msgstr "此群组已链接到订阅"
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr "此群组ã€å…¶å­ç¾¤ç»„和项目已安排在%{date}移除。"
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
-msgstr "此群组ã€å…¶å­ç¾¤ç»„和项目将于%{date}被删除,因为其父群组'%{parent_group_name}‘已被安排移除。"
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
+msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr "此邀请已å‘é€è‡³ %{mail_to_invite_email},但您以 %{link_to_current_user} 身份使用电å­é‚®ä»¶ %{mail_to_current_user}登录。"
@@ -34815,6 +35131,12 @@ msgstr "该用户是%{noteable}的作者。"
msgid "This variable can not be masked."
msgstr "æ­¤å˜é‡æ— æ³•è¢«éšè—。"
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr "这会将您é‡å®šå‘到外部登录页é¢ã€‚"
@@ -34948,9 +35270,12 @@ msgid "ThreatMonitoring|View documentation"
msgstr "查看文档"
msgid "Threshold in bytes at which to compress Sidekiq job arguments."
-msgstr ""
+msgstr "压缩 Sidekiq 作业å‚数的阈值(以字节为å•ä½ï¼‰ã€‚"
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
+msgstr "æ‹’ç» Sidekiq 作业的阈值(以字节为å•ä½ï¼‰ã€‚如果您ä¸æƒ³é™åˆ¶ Sidekiq 作业,请将其设置为 0。"
+
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
msgstr ""
msgid "Throughput"
@@ -34963,7 +35288,7 @@ msgid "Time"
msgstr "时间"
msgid "Time (in hours) that users are allowed to skip forced configuration of two-factor authentication."
-msgstr ""
+msgstr "å…许用户跳过强制é…ç½®åŒé‡è®¤è¯çš„时间(以å°æ—¶ä¸ºå•ä½ï¼‰"
msgid "Time Spent"
msgstr "耗时"
@@ -35032,7 +35357,7 @@ msgid "TimeTrackingEstimated|Est"
msgstr "预计"
msgid "TimeTracking|%{spentStart}Spent: %{spentEnd}"
-msgstr ""
+msgstr "%{spentStart}花费:%{spentEnd}"
msgid "TimeTracking|Estimated:"
msgstr "预计:"
@@ -35244,7 +35569,7 @@ msgid "To access this domain create a new DNS record"
msgstr "è¦è®¿é—®æ­¤åŸŸï¼Œè¯·åˆ›å»ºæ–°çš„DNS记录"
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "è¦æ·»åŠ è‡ªå®šä¹‰åŽç¼€ï¼Œè¯·è®¾ç½®æœåŠ¡å°ç”µå­é‚®ä»¶åœ°å€ã€‚%{linkStart}了解更多。%{linkEnd}"
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "è¦æ·»åŠ ä¸€ä¸ªSSH密钥, 您需è¦%{generate_link_start}生æˆä¸€ä¸ª%{link_end}或使用一个%{existing_link_start}现有的密钥%{link_end}。"
@@ -35268,7 +35593,7 @@ msgid "To connect an SVN repository, check out %{svn_link}."
msgstr "如è¦è¿žæŽ¥SVN仓库,请查看 %{svn_link}。"
msgid "To continue using GitLab Enterprise Edition, upload the %{codeOpen}.gitlab-license%{codeClose} file or enter the license key you have received from GitLab Inc."
-msgstr ""
+msgstr "è¦ç»§ç»­ä½¿ç”¨ GitLab ä¼ä¸šç‰ˆï¼Œè¯·ä¸Šä¼  %{codeOpen}.gitlab-license%{codeClose} 文件或输入您从 GitLab Inc 收到的许å¯è¯å¯†é’¥ã€‚"
msgid "To continue, you need to select the link in the confirmation email we sent to verify your email address. If you didn't get our email, select %{strongStart}Resend confirmation email.%{strongEnd}"
msgstr "è¦ç»§ç»­ï¼Œæ‚¨éœ€è¦é€‰æ‹©æˆ‘们å‘é€çš„确认电å­é‚®ä»¶ä¸­çš„链接以验è¯æ‚¨çš„电å­é‚®ä»¶åœ°å€ã€‚如果您没有收到我们的电å­é‚®ä»¶ï¼Œè¯·é€‰æ‹© %{strongStart}é‡æ–°å‘é€ç¡®è®¤ç”µå­é‚®ä»¶ã€‚%{strongEnd}"
@@ -35277,13 +35602,13 @@ msgid "To define internal users, first enable new users set to external"
msgstr "è¦å®šä¹‰å†…部用户,请首先å¯ç”¨è®¾ç½®ä¸ºå¤–部的新用户"
msgid "To enable Registration Features, first enable Service Ping."
-msgstr ""
+msgstr "è¦å¯ç”¨æ³¨å†ŒåŠŸèƒ½ï¼Œè¯·å…ˆå¯ç”¨Service Ping。"
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr "为ä¿è¯ä¸ªäººå†…容ä¸ä¸¢å¤±ï¼Œæœ¬è´¦å·ä»…用于与 %{group_name}相关的事项。"
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
-msgstr "è¦åœ¨ä»»ä½•è¿™äº›ç‰ˆæœ¬ä¸­æŸ¥æ‰¾æ­¤é¡¹ç›®å­˜å‚¨åº“的状æ€ï¼Œè¯·æ£€æŸ¥ %{link_start}标签%{link_end}。"
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
+msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr "为了进一步ä¿æŠ¤æ‚¨çš„å¸æˆ·ï¼Œè¯·è€ƒè™‘é…置一个%{mfa_link_start}åŒé‡èº«ä»½éªŒè¯%{mfa_link_end}方法。"
@@ -35304,7 +35629,7 @@ msgid "To get started, use the link below to confirm your account."
msgstr "首先,请使用以下链接确认您的å¸æˆ·ã€‚"
msgid "To help improve GitLab and its user experience, GitLab periodically collects usage information."
-msgstr ""
+msgstr "为了帮助改进GitLabåŠæå‡ç”¨æˆ·ä½“验, GitLab将定期收集使用信æ¯ã€‚"
msgid "To help improve GitLab, we would like to periodically %{docs_link}. This can be changed at any time in %{settings_link}."
msgstr "为了帮助改进GitLab,我们会定期%{docs_link}。您å¯ä»¥éšæ—¶é€šè¿‡%{settings_link}更改设置。"
@@ -35318,8 +35643,8 @@ msgstr "为了ä¿æŒè¿™ä¸ªé¡¹ç›®çš„进行,请创建一个新的议题"
msgid "To keep this project going, create a new merge request"
msgstr "为了ä¿æŒè¿™ä¸ªé¡¹ç›®çš„进行,请创建一个新的åˆå¹¶è¯·æ±‚"
-msgid "To learn more about this project, read %{link_to_wiki}."
-msgstr "è¦äº†è§£æœ‰å…³æ­¤é¡¹ç›®çš„更多信æ¯ï¼Œè¯·é˜…读 %{link_to_wiki}。"
+msgid "To learn more about this project, read %{link_to_wiki}"
+msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr "如需将整个GitLab项目从å¦ä¸€ä¸ªGitLabæœåŠ¡å™¨ç§»åŠ¨æˆ–å¤åˆ¶åˆ°æ­¤æœåŠ¡å™¨ï¼Œè¯·è®¿é—®åŽŸé¡¹ç›®çš„设置页é¢ï¼Œç”Ÿæˆå¯¼å‡ºæ–‡ä»¶ï¼Œç„¶åŽåœ¨æ­¤å¤„上载。"
@@ -35337,7 +35662,7 @@ msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size
msgstr "为了ä¿è¯æ€§èƒ½ï¼Œä»…显示文件中的总计%{strong_open}%{real_size}中的%{display_size}%{strong_close}。"
msgid "To protect this issue's confidentiality, %{linkStart}fork this project%{linkEnd} and set the fork's visibility to private."
-msgstr ""
+msgstr "为了ä¿æŠ¤æ­¤è®®é¢˜çš„机密性, %{linkStart}派生此项目%{linkEnd}并将å¯è§æ€§è®¾ç½®ä¸ºç§æœ‰é¡¹ç›®ã€‚"
msgid "To protect this issue's confidentiality, a private fork of this project was selected."
msgstr "为了ä¿è¯æ­¤è®®é¢˜çš„ç§å¯†æ€§ï¼Œé€‰æ‹©äº†è¯¥é¡¹ç›®çš„ç§æœ‰æ´¾ç”Ÿã€‚"
@@ -35370,13 +35695,13 @@ msgid "To set up SAML authentication for your group through an identity provider
msgstr "通过Azure,Okta,Onelogin,Ping Identity或自定义SAML 2.0等身份验è¯ç¨‹åºä¸ºæ‚¨çš„群组设置SAML身份验è¯ï¼š"
msgid "To set up this integration:"
-msgstr ""
+msgstr "è¦å»ºç«‹æ­¤é›†æˆï¼š"
msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
msgstr "è‹¥è¦æŒ‡å®šæ‚¨æ‰€å±žçš„群组的æ¯ä¸ªé¡¹ç›®çš„通知级别,您需è¦è®¿é—®é¡¹ç›®é¡µé¢ï¼Œæ›´æ”¹é€šçŸ¥çº§åˆ«ã€‚"
msgid "To start using GitLab Enterprise Edition, upload the %{codeOpen}.gitlab-license%{codeClose} file or enter the license key you have received from GitLab Inc."
-msgstr ""
+msgstr "è¦å¼€å§‹ä½¿ç”¨ GitLab ä¼ä¸šç‰ˆï¼Œè¯·ä¸Šä¼  %{codeOpen}.gitlab-license%{codeClose} 文件或输入您从 GitLab Inc 收到的许å¯è¯å¯†é’¥ã€‚"
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr "è‹¥è¦é€€è®¢æ­¤é—®é¢˜ï¼Œè¯·å°†ä»¥ä¸‹é“¾æŽ¥ç²˜è´´åˆ°æ‚¨çš„æµè§ˆå™¨ï¼š"
@@ -35504,6 +35829,21 @@ msgstr "å¯ç”¨äº†å¤ªå¤šçš„项目。您需è¦é€šè¿‡æŽ§åˆ¶å°æˆ–APIæ¥ç®¡ç†å®ƒä»¬
msgid "TopNav|Go back"
msgstr "返回"
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr "主题(å¯é€‰)"
@@ -35597,8 +35937,8 @@ msgstr "群组已ç»æ˜¯ä¸€ä¸ªæ ¹ç¾¤ç»„。"
msgid "TransferGroup|Group is already associated to the parent group."
msgstr "群组已与父群组关è”。"
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
-msgstr "父群组已ç»æœ‰ä¸€ä¸ªå…·æœ‰ç›¸åŒè·¯å¾„çš„å­ç¾¤ç»„。"
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
+msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
msgstr "转移失败: %{error_message}"
@@ -35964,6 +36304,9 @@ msgstr "无法获å–此项目的分支列表。"
msgid "Unable to fetch branches list, please close the form and try again"
msgstr "无法获å–分支列表,请关闭表å•å¹¶é‡è¯•"
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr "无法获å–å¯èƒ½å­˜åœ¨æ¼æ´žçš„项目"
@@ -36019,13 +36362,13 @@ msgid "Unable to update this issue at this time."
msgstr "当å‰æ— æ³•æ›´æ–°è¿™ä¸ªè®®é¢˜ã€‚"
msgid "Unapprove a merge request"
-msgstr ""
+msgstr "å–消批准åˆå¹¶è¯·æ±‚"
msgid "Unapprove the current merge request."
-msgstr ""
+msgstr "å–消批准当å‰åˆå¹¶è¯·æ±‚。"
msgid "Unapproved the current merge request."
-msgstr ""
+msgstr "å·²å–消批准当å‰åˆå¹¶è¯·æ±‚。"
msgid "Unarchive project"
msgstr "å–消归档项目"
@@ -36040,12 +36383,15 @@ msgid "Unassigned"
msgstr "未分é…"
msgid "Unauthenticated API rate limit period in seconds"
-msgstr ""
+msgstr "未ç»èº«ä»½éªŒè¯çš„ API 速率é™åˆ¶æœŸï¼ˆä»¥ç§’为å•ä½ï¼‰"
msgid "Unauthenticated requests"
msgstr "未认è¯çš„请求"
msgid "Unauthenticated web rate limit period in seconds"
+msgstr "未ç»èº«ä»½éªŒè¯çš„ Web 速率é™åˆ¶æœŸï¼ˆä»¥ç§’为å•ä½ï¼‰"
+
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
msgstr ""
msgid "Undo"
@@ -36367,7 +36713,7 @@ msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled,
msgstr "%{help_link_start}共享Runner%{help_link_end}å·²ç¦ç”¨ï¼Œæ‰€ä»¥æµæ°´çº¿ä½¿ç”¨æ²¡æœ‰è®¾ç½®é™åˆ¶"
msgid "UsageQuota|%{linkTitle} help link"
-msgstr ""
+msgstr "%{linkTitle} 帮助链接"
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr "%{percentageLeft}购买的存储空间å¯ç”¨"
@@ -36379,6 +36725,9 @@ msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr "产物是构建产物和æµæ°´çº¿äº§ç‰©çš„总和。"
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
+msgstr "音频样本ã€è§†é¢‘ã€æ•°æ®é›†å’Œå›¾å½¢ã€‚"
+
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
msgstr ""
msgid "UsageQuota|Buy additional minutes"
@@ -36391,18 +36740,18 @@ msgid "UsageQuota|CI minutes usage by project"
msgstr "CI 分钟使用é‡ï¼ˆæŒ‰é¡¹ç›®ï¼‰"
msgid "UsageQuota|Code packages and container images."
-msgstr ""
+msgstr "代ç åŒ…和容器镜åƒã€‚"
msgid "UsageQuota|Current period usage"
msgstr "当å‰å‘¨æœŸä½¿ç”¨é‡"
msgid "UsageQuota|File attachments and smaller design graphics."
-msgstr ""
+msgstr "文件附件和较å°çš„设计图表。"
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36414,6 +36763,9 @@ msgstr "LFS对象"
msgid "UsageQuota|LFS Storage"
msgstr "LFS存储"
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr "了解有关超é¢å­˜å‚¨ä½¿ç”¨é‡çš„更多信æ¯"
@@ -36424,7 +36776,7 @@ msgid "UsageQuota|Packages"
msgstr "软件包"
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
-msgstr ""
+msgstr "用 CI/CD 创建的æµæ°´çº¿åˆ¶å“和作业制å“。"
msgid "UsageQuota|Pipelines"
msgstr "æµæ°´çº¿"
@@ -36445,7 +36797,7 @@ msgid "UsageQuota|Seats"
msgstr "席ä½"
msgid "UsageQuota|Shared bits of code and text."
-msgstr ""
+msgstr "代ç å’Œæ–‡æœ¬çš„共享bits。"
msgid "UsageQuota|Snippets"
msgstr "代ç ç‰‡æ®µ"
@@ -36457,10 +36809,7 @@ msgid "UsageQuota|Storage"
msgstr "存储"
msgid "UsageQuota|Storage type"
-msgstr ""
-
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
+msgstr "存储类型"
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr "这是此å称空间中所有项目使用的存储空间总和。"
@@ -36501,12 +36850,12 @@ msgstr "上传"
msgid "UsageQuota|Usage"
msgstr "使用é‡"
-msgid "UsageQuota|Usage Breakdown"
-msgstr ""
-
msgid "UsageQuota|Usage Quotas"
msgstr "使用é‡é…é¢"
+msgid "UsageQuota|Usage breakdown"
+msgstr ""
+
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
msgstr "%{strong_start}%{group_name}%{strong_end}群组中的项目使用群组资æºçŠ¶å†µ"
@@ -36529,7 +36878,7 @@ msgid "UsageQuota|Wiki"
msgstr "Wiki"
msgid "UsageQuota|Wiki content."
-msgstr ""
+msgstr "Wiki 内容。"
msgid "UsageQuota|Wikis"
msgstr "Wiki"
@@ -36654,6 +37003,9 @@ msgstr "在您的移动设备或计算机上使用一次性密ç éªŒè¯å™¨æ¥å¯
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr "使用 AWS CloudFormation æ¨¡æ¿ (CFT) 在 AWS 中安装和é…ç½® GitLab Runner。"
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr "使用 cURL"
@@ -36684,6 +37036,9 @@ msgstr "使用斜线命令。"
msgid "Use template"
msgstr "使用模æ¿"
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr "使用以下链接确认您的电å­é‚®ä»¶åœ°å€ (%{email})"
@@ -36748,11 +37103,17 @@ msgid "User Settings"
msgstr "用户设置"
msgid "User and IP rate limits"
+msgstr "用户和 IP 速率é™åˆ¶"
+
+msgid "User cap"
msgstr ""
-msgid "User does not have a pending request"
+msgid "User created at"
msgstr ""
+msgid "User does not have a pending request"
+msgstr "用户没有待处ç†è¯·æ±‚"
+
msgid "User identity was successfully created."
msgstr "å·²æˆåŠŸåˆ›å»ºç”¨æˆ·æ ‡è¯†ã€‚"
@@ -37048,7 +37409,7 @@ msgid "Users can launch a development environment from a GitLab browser tab when
msgstr "%{linkStart}Gitpod%{linkEnd} 集æˆåŽï¼Œç”¨æˆ·å¯ä»¥ä»Ž GitLab æµè§ˆå™¨é€‰é¡¹å¡å¯åŠ¨å¼€å‘环境。"
msgid "Users can reactivate their account by signing in."
-msgstr ""
+msgstr "用户å¯ä»¥é€šè¿‡ç™»å½•é‡æ–°æ¿€æ´»ä»–们的å¸æˆ·ã€‚"
msgid "Users can render diagrams in AsciiDoc, Markdown, reStructuredText, and Textile documents using Kroki."
msgstr "用户å¯ä»¥ä½¿ç”¨ Kroki 在 AsciiDocã€Markdownã€reStructuredText å’Œ Textile 文档中渲染图表。"
@@ -37066,7 +37427,7 @@ msgid "Users requesting access to"
msgstr "请求访问的用户"
msgid "Users to exclude from the rate limit"
-msgstr ""
+msgstr "从速率é™åˆ¶ä¸­æŽ’除的用户"
msgid "Users were successfully added."
msgstr "å·²æˆåŠŸæ·»åŠ ç”¨æˆ·ã€‚"
@@ -37090,7 +37451,7 @@ msgid "UsersSelect|Unassigned"
msgstr "未分é…"
msgid "Uses GitLab as a lightweight alternative to Sentry."
-msgstr ""
+msgstr "使用 GitLab 作为 Sentry çš„è½»é‡çº§æ›¿ä»£å“。"
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr "使用 %{code_start}::%{code_end} 表示 %{link_start}范围标签集%{link_end}"
@@ -37101,6 +37462,9 @@ msgstr "当缺少加密字段时,使用必è¦çš„加密策略ï¼"
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr "使用%{codeStart}needs%{codeEnd}关键字会使作业比其所在阶段更早è¿è¡Œã€‚åªè¦å®ƒä»¬çš„%{codeStart}needs%{codeEnd}关系得到满足,作业将尽快执行,从而实现æµæ°´çº¿åŠ é€Ÿã€‚"
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr "验è¯"
@@ -37110,6 +37474,15 @@ msgstr "验è¯æ‚¨çš„GitLab CIé…ç½®"
msgid "Validate your GitLab CI configuration file"
msgstr "验è¯æ‚¨çš„GitLab CIé…置文件"
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr "验è¯å¤±è´¥ã€‚"
@@ -37123,7 +37496,7 @@ msgid "Value Stream Analytics can help you determine your team’s velocity"
msgstr "价值æµåˆ†æžå¯ä»¥å¸®åŠ©æ‚¨äº†è§£å›¢é˜Ÿçš„效率"
msgid "Value might contain a variable reference"
-msgstr ""
+msgstr "值å¯èƒ½åŒ…å«å˜é‡å¼•ç”¨"
msgid "Value stream"
msgstr "价值æµ"
@@ -37155,11 +37528,23 @@ msgstr "&lt;1m"
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr "æ¯å¤©ç”Ÿäº§çŽ¯å¢ƒéƒ¨ç½²çš„å¹³å‡æ•°ã€‚"
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr "从议题创建到关闭的中ä½æ•°æ—¶é—´ã€‚"
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
-msgstr "从议题的第一个åˆå¹¶è¯·æ±‚创建到议题关闭的中ä½æ—¶é—´ã€‚"
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
+msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
msgstr "推é€åˆ°é»˜è®¤åˆ†æ”¯çš„æ交数é‡"
@@ -37189,7 +37574,7 @@ msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr "默认价值æµä¸å¯åˆ é™¤"
msgid "Values that contain the %{codeStart}$%{codeEnd} character can be considered a variable reference and expanded. %{docsLinkStart}Learn more.%{docsLinkEnd}"
-msgstr ""
+msgstr "åŒ…å« %{codeStart}$%{codeEnd} 字符的值å¯ä»¥è¢«è§†ä¸ºå˜é‡å¼•ç”¨å¹¶è¿›è¡Œæ‰©å±•ã€‚%{docsLinkStart}了解更多。%{docsLinkEnd}"
msgid "Variable"
msgstr "å˜é‡"
@@ -37594,7 +37979,7 @@ msgid "Vulnerability|Evidence"
msgstr "è¯æ®"
msgid "Vulnerability|False positive detected"
-msgstr ""
+msgstr "检测到误报"
msgid "Vulnerability|File"
msgstr "文件"
@@ -37639,7 +38024,7 @@ msgid "Vulnerability|Status"
msgstr "状æ€"
msgid "Vulnerability|The scanner determined this vulnerability to be a false positive. Verify the evaluation before changing its status. %{linkStart}Learn more about false positive detection.%{linkEnd}"
-msgstr ""
+msgstr "扫æ器确定此æ¼æ´žä¸ºè¯¯æŠ¥ã€‚在更改其状æ€ä¹‹å‰éªŒè¯è¯„估。 %{linkStart}了解有关误报检测的更多信æ¯ã€‚%{linkEnd}"
msgid "Vulnerability|The unmodified response is the original response that had no mutations done to the request"
msgstr "未修改的å“应是原始å“应没有对请求进行çªå˜çš„å“应"
@@ -37815,6 +38200,9 @@ msgstr "Webhook日志"
msgid "Webhook Settings"
msgstr "Webhook设置"
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr "Webhook:"
@@ -38005,11 +38393,14 @@ msgid "What is your job title? (optional)"
msgstr "您的工作èŒä½æ˜¯ä»€ä¹ˆï¼Ÿ(å¯é€‰)"
msgid "What templates can I create?"
-msgstr ""
+msgstr "我å¯ä»¥åˆ›å»ºä»€ä¹ˆæ ·çš„模æ¿ï¼Ÿ"
msgid "What will you use this group for?"
msgstr "你会用这个群组åšä»€ä¹ˆï¼Ÿ"
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr "新增功能"
@@ -38019,11 +38410,8 @@ msgstr "部署作业æˆåŠŸæ—¶ï¼Œè·³è¿‡å°šæœªå®Œæˆçš„旧部署任务。"
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "当Runner被é”定时,ä¸èƒ½å°†å…¶åˆ†é…给其他项目"
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr "å½“äº‹ä»¶è§¦å‘ webhook 时,您å¯ä»¥ä½¿ç”¨è¯·æ±‚详细信æ¯æ¥ç¡®å®šæ˜¯å¦å‡ºçŽ°é—®é¢˜ã€‚"
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
-msgstr ""
+msgstr "å¯ç”¨åŽï¼ŒçŽ°æœ‰çš„个人访问令牌å¯èƒ½ä¼šè¢«æ’¤é”€ã€‚留空表示没有é™åˆ¶ã€‚"
msgid "When inactive, an external authentication provider must be used."
msgstr "当未激活时,必须使用外部身份验è¯æ供程åºã€‚"
@@ -38034,6 +38422,9 @@ msgstr "å°†URLä¿ç•™ä¸ºç©ºç™½æ—¶ï¼Œä»å¯æŒ‡å®šåˆ†ç±»æ ‡ç­¾ï¼Œè€Œæ— éœ€ç¦ç”¨è·¨
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr "当默认分支中的åˆå¹¶è¯·æ±‚å’Œæ交关闭时,它们引用的任何议题也会关闭。"
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "当åˆå¹¶è¯·æ±‚被接å—æ—¶"
@@ -38041,14 +38432,11 @@ msgstr[0] "当åˆå¹¶è¯·æ±‚被接å—æ—¶"
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr "使用%{code_open}http://%{code_close}或%{code_open}https://%{code_close}å议时,请æ供仓库的实际地å€ã€‚ä¸æ”¯æŒHTTPé‡å®šå‘。"
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr "使用 %{code_open}http://%{code_close} 或 %{code_open}https://%{code_close} å议时,请æ供仓库的确切 URL。将ä¸ä¼šéµå¾ª HTTP é‡å®šå‘。"
-
msgid "When:"
msgstr "当:"
msgid "Which API requests are affected?"
-msgstr ""
+msgstr "哪些API请求å—到影å“?"
msgid "While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
msgstr "虽然没有å‘现æ¼æ´žï¼Œè¿™ç§çŽ°è±¡å¾ˆç½•è§ï¼Œä½†ä¹Ÿæ˜¯æœ‰å¯èƒ½çš„。无论如何,建议您仔细检查设置以确ä¿ä»ªè¡¨æ¿çš„é…置正确。"
@@ -38330,7 +38718,7 @@ msgid "Work in progress Limit"
msgstr "“进行中â€é™åˆ¶"
msgid "WorkItem|Work Items"
-msgstr ""
+msgstr "工作事项"
msgid "Would you like to create a new branch?"
msgstr "您è¦åˆ›å»ºä¸€ä¸ªæ–°åˆ†æ”¯å—?"
@@ -38350,12 +38738,12 @@ msgstr "å‘表评论..."
msgid "Write a description or drag your files here…"
msgstr "写下æ述或将您的文件拖到此处…"
+msgid "Write a description…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "写入里程碑æè¿°..."
-msgid "Write to \"authorized_keys\" file"
-msgstr "写入“authorized_keysâ€æ–‡ä»¶"
-
msgid "Write your release notes or drag your files here…"
msgstr "编写å‘行说明(Release Notes) 或将文件拖动到此处..."
@@ -38395,9 +38783,6 @@ msgstr "您已有针对此警报的待处ç†çš„待办事项"
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr "å³å°†æŠŠ%{usersTag}相关人员添加到讨论中。他们都会收到通知。"
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr "å³å°†ä»Žæ‚¨çš„实例中删除 %{domain}。此域å将无法å†ç”¨äºŽä»»ä½•Knorigin应用程åºã€‚"
-
msgid "You are about to permanently delete this project"
msgstr "您将永久删除此项目"
@@ -38408,7 +38793,7 @@ msgid "You are already a member of this %{member_source}."
msgstr "您已ç»æ˜¯%{member_source}çš„æˆå‘˜ã€‚"
msgid "You are already impersonating another user"
-msgstr ""
+msgstr "您已ç»åœ¨æ¨¡æ‹Ÿå¦ä¸€ä¸ªç”¨æˆ·"
msgid "You are an admin, which means granting access to %{client_name} will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "您是管ç†å‘˜ï¼Œè¿™æ„味ç€èµ‹äºˆ%{client_name}æƒé™å°†å…许他们作为管ç†å‘˜æ¥å¯¹GitLab进行æ“作。请谨慎行事。"
@@ -38464,6 +38849,9 @@ msgstr "您无æƒåˆ é™¤æ­¤ç«™ç‚¹é…置文件"
msgid "You are not authorized to perform this action"
msgstr "您无æƒæ‰§è¡Œæ­¤æ“作"
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr "您无æƒæ›´æ–°æ­¤æ‰«æ工具é…置文件"
@@ -38513,7 +38901,7 @@ msgid "You can also use project access tokens with Git to authenticate over HTTP
msgstr "您还å¯ä»¥å°†é¡¹ç›®è®¿é—®ä»¤ç‰Œä¸Ž Git 结åˆä½¿ç”¨ä»¥é€šè¿‡ HTTP(S) 进行身份验è¯ã€‚ %{link_start}了解更多。%{link_end}"
msgid "You can always change your URL later"
-msgstr ""
+msgstr "您å¯ä»¥ç¨åŽæ›´æ”¹æ‚¨çš„ URL"
msgid "You can always edit this later"
msgstr "您也å¯ä»¥ç¨åŽç¼–辑此选项。"
@@ -38620,9 +39008,6 @@ msgstr "通过拖放到现有设计的方å¼ï¼Œæ‚¨æ¯æ¬¡åªèƒ½ä¸Šä¼ ä¸€ä¸ªè®¾è®¡
msgid "You can recover this project until %{date}"
msgstr "您å¯ä»¥åœ¨%{date}之å‰æ¢å¤æ­¤é¡¹ç›®"
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr "您å¯ä»¥ä¸ºå•ä¸ªç”¨æˆ·ï¼Œå•ä¸ªæœåŠ¡å™¨ä»¥åŠæ‚¨çš„本地机器注册Runner。注册Runnerçš„æ•°é‡ä¸å—é™åˆ¶ã€‚"
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "您å¯ä»¥ä½¿ç”¨äº¤äº’模å¼ï¼Œé€šè¿‡é€‰æ‹© %{use_ours} 或 %{use_theirs} 按钮æ¥è§£å†³åˆå¹¶å†²çªã€‚也å¯ä»¥é€šè¿‡ç›´æŽ¥ç¼–辑文件æ¥è§£å†³åˆå¹¶å†²çªã€‚然åŽå°†è¿™äº›æ›´æ”¹æ交到 %{branch_name}"
@@ -38672,7 +39057,7 @@ msgid "You can’t %{tag_start}edit%{tag_end} files directly in this project. Fo
msgstr "您ä¸èƒ½åœ¨æ­¤é¡¹ç›®ä¸­ç›´æŽ¥ %{tag_start}编辑%{tag_end},派生(fork)这个项目并æ交一个包å«æ‚¨çš„更改的åˆå¹¶è¯·æ±‚。"
msgid "You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
-msgstr ""
+msgstr "您ä¸èƒ½åœ¨è¿™ä¸ªé¡¹ç›®ä¸­ç›´æŽ¥ç¼–辑文件,请派生(Fork)这个项目并æ交包å«æ‚¨çš„更改的åˆå¹¶è¯·æ±‚。"
msgid "You could not create a new trigger."
msgstr "您无法创建新的触å‘器。"
@@ -38722,9 +39107,6 @@ msgstr "您没有任何å¯ç”¨çš„项目。"
msgid "You don't have any recent searches"
msgstr "您没有任何近期的æœç´¢"
-msgid "You don't have any webhooks deliveries"
-msgstr "您没有任何Webhook交付"
-
msgid "You don't have sufficient permission to perform this action."
msgstr "你没有足够的æƒé™æ¥æ‰§è¡Œæ­¤æ“作。"
@@ -38812,6 +39194,9 @@ msgstr "您已æˆåŠŸè´­ä¹° %{product}。您将通过邮件收到收æ®ã€‚"
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr "您已æˆåŠŸè´­ä¹°äº†%{seats}用户的%{plan}计划订阅。收æ®å°†é€šè¿‡ç”µå­é‚®ä»¶å‘é€ç»™æ‚¨ã€‚"
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr "ä½ å·²ç»ä»Žâ€œ%{membershipable_human_name}†%{source_type}退出。"
@@ -38821,9 +39206,6 @@ msgstr "你现在å¯ä»¥å…³é—­è¿™ä¸ªé‡Œç¨‹ç¢‘。"
msgid "You must be logged in to search across all of GitLab"
msgstr "您必须登录æ‰èƒ½åœ¨æ•´ä¸ªGitLab中进行æœç´¢"
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr "删除å‰æ‚¨å¿…须将%{domain}从所有相关的集群中解除关è”。"
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr "å¯ç”¨è°ƒè¯•è·Ÿè¸ªæ—¶ï¼Œæ‚¨å¿…须在关è”项目中拥有开å‘人员或更高æƒé™æ‰èƒ½æŸ¥çœ‹ä½œä¸šæ—¥å¿—。è¦ç¦ç”¨è°ƒè¯•è·Ÿè¸ªï¼Œè¯·åœ¨æµæ°´çº¿é…置或 CI/CD 设置中将“CI_DEBUG_TRACEâ€å˜é‡è®¾ç½®ä¸ºâ€œfalseâ€ã€‚如果您需è¦æŸ¥çœ‹æ­¤ä½œä¸šæ—¥å¿—,项目维护者必须将您添加到具有开å‘人员æƒé™æˆ–更高æƒé™çš„项目中。"
@@ -38843,10 +39225,10 @@ msgid "You must provide your current password in order to change it."
msgstr "您必须æ供当å‰å¯†ç æ‰èƒ½è¿›è¡Œæ›´æ”¹ã€‚"
msgid "You must sign in to search for specific projects."
-msgstr ""
+msgstr "您必须登录æ‰èƒ½æœç´¢ç‰¹å®šé¡¹ç›®ã€‚"
msgid "You must sign in to search for specific terms."
-msgstr ""
+msgstr "您必须登录æ‰èƒ½æœç´¢ç‰¹å®šäº‹é¡¹ã€‚"
msgid "You must solve the CAPTCHA in order to submit"
msgstr "您必须解决验è¯ç æ‰èƒ½æ交"
@@ -38876,7 +39258,7 @@ msgid "You need to upload a GitLab project export archive (ending in .gz)."
msgstr "您需è¦ä¸Šä¼ GitLab项目导出文件(以.gz结尾)."
msgid "You need to verify your primary email first before enabling Two-Factor Authentication."
-msgstr ""
+msgstr "您需è¦å…ˆéªŒè¯æ‚¨çš„主è¦ç”µå­é‚®ä»¶ï¼Œç„¶åŽæ‰èƒ½å¯ç”¨åŒé‡èº«ä»½éªŒè¯ã€‚"
msgid "You successfully declined the invitation"
msgstr "您æˆåŠŸæ‹’ç»äº†é‚€è¯·"
@@ -38987,7 +39369,7 @@ msgid "Your %{host} account was signed in to from a new location"
msgstr "您在%{host}上的å¸æˆ·å·²ä»Žä¸€ä¸ªæ–°çš„ä½ç½®ç™»å½•"
msgid "Your %{strong}%{plan_name}%{strong_close} subscription expires on %{strong}%{expires_on}%{strong_close}. After that date, you cannot create issues or merge requests, or use many other features."
-msgstr ""
+msgstr "您的%{strong}%{plan_name}%{strong_close}订阅将于%{strong}%{expires_on}%{strong_close}到期。此åŽï¼Œæ‚¨å°†æ— æ³•åˆ›å»ºè®®é¢˜æˆ–åˆå¹¶è¯·æ±‚,åŒæ—¶ä¹Ÿæ— æ³•è®¿é—®å…¶ä»–众多功能。"
msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
msgstr "您为%{strong}%{namespace_name}%{strong_close}的%{strong}%{plan_name}%{strong_close}订阅将于%{strong}%{expires_on}%{strong_close}到期。"
@@ -39014,7 +39396,7 @@ msgid "Your GPG keys (%{count})"
msgstr "您的GPG密钥 (%{count})"
msgid "Your GitLab account has been locked due to an excessive number of unsuccessful sign in attempts. You can wait for your account to automatically unlock in %{duration} or you can click the link below to unlock now."
-msgstr ""
+msgstr "由于大é‡ä¸æˆåŠŸçš„登录å°è¯•ï¼Œæ‚¨çš„ GitLab å¸æˆ·å·²è¢«é”定。您的å¸æˆ·å°†åœ¨ %{duration} 自动解é”,或者您å¯ä»¥å•å‡»ä¸‹é¢çš„链接立å³è§£é”。"
msgid "Your GitLab account request has been approved!"
msgstr "您的GitLabå¸æˆ·åˆ›å»ºè¯·æ±‚已被批准ï¼"
@@ -39125,7 +39507,7 @@ msgid "Your commit email is used for web based operations, such as edits and mer
msgstr "您的æ交电å­é‚®ä»¶ç”¨äºŽåŸºäºŽ web çš„æ“作,例如编辑和åˆå¹¶ã€‚"
msgid "Your current password is required to register a two-factor authenticator app."
-msgstr ""
+msgstr "需è¦æ‚¨å½“å‰çš„密ç æ¥æ³¨å†ŒåŒé‡èº«ä»½éªŒè¯ç¨‹åºã€‚"
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
msgstr "仪表æ¿å·²ç»è¢«å¤åˆ¶ã€‚ ä½ å¯ä»¥%{web_ide_link_start}在这里进行编辑%{web_ide_link_end}。"
@@ -39227,7 +39609,7 @@ msgid "Your project limit is %{limit} projects! Please contact your administrato
msgstr "您的被é™åˆ¶ä¸ºæœ€å¤§ %{limit} 个项目ï¼è¯·ä¸Žæ‚¨çš„管ç†å‘˜è”系以增加它"
msgid "Your project will be created at:"
-msgstr ""
+msgstr "您的项目将创建于:"
msgid "Your projects"
msgstr "您的项目"
@@ -39270,34 +39652,61 @@ msgstr "您的订阅已过期ï¼"
msgid "Your subscription will expire in %{remaining_days} day."
msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
+msgstr[0] "您的订阅将在 %{remaining_days} 天åŽåˆ°æœŸã€‚"
msgid "Your username is %{username}."
msgstr "您的用户å是%{username}。"
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
-msgstr "禅é“实例的基础URL。"
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
-msgid "ZentaoIntegration|Enter API token"
-msgstr "输入 API 令牌"
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
+msgstr ""
+
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
+msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr "如果与 Web URL ä¸åŒã€‚"
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
-msgstr "使用禅é“作为此项目的议题跟踪器。"
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
+msgstr ""
+
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
+msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
-msgstr "ç¦…é“ API URL(å¯é€‰ï¼‰"
+msgid "ZentaoIntegration|ZenTao API token"
+msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
-msgstr "ç¦…é“ API 令牌"
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
-msgstr "ç¦…é“ Product ID"
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
-msgstr "ç¦…é“ Web URL"
+msgid "ZentaoIntegration|ZenTao issues"
+msgstr ""
msgid "Zoom meeting added"
msgstr "已添加Zoom会议"
@@ -39308,6 +39717,9 @@ msgstr "已删除Zoom会议"
msgid "[No reason]"
msgstr "[无原因]"
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr "[Redacted]"
@@ -39320,9 +39732,6 @@ msgstr "`start_time` 应该在 `end_time` 之å‰"
msgid "a deleted user"
msgstr "已删除的用户"
-msgid "a design"
-msgstr "一个设计"
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] "约%då°æ—¶"
@@ -39427,12 +39836,18 @@ msgstr "åªèƒ½ç”±ç¾¤ç»„管ç†å‘˜æ›´æ”¹ã€‚"
msgid "can only have one escalation policy"
msgstr "åªèƒ½æœ‰ä¸€ä¸ªå‡çº§ç­–ç•¥"
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr "ä¸èƒ½å’Œæºé¡¹ç›®ç›¸åŒ"
msgid "can't include: %{invalid_storages}"
msgstr "ä¸èƒ½åŒ…括: %{invalid_storages}"
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr "ä¸èƒ½æ˜¯è¿‡åŽ»çš„日期"
@@ -39460,6 +39875,9 @@ msgstr "在有效的信用å¡å­˜æ¡£ä¹‹å‰æ— æ³•å¯ç”¨"
msgid "cannot be modified"
msgstr "无法修改"
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr "ä¸ä¼šé˜»å¡žå…¶ä»–"
@@ -39475,9 +39893,6 @@ msgstr "本身ä¸èƒ½è¢«é˜»å¡ž"
msgid "cannot merge"
msgstr "无法åˆå¹¶"
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr "å·²é™ä½Ž%{degradedNum}"
@@ -39508,6 +39923,9 @@ msgstr "%{linkStartTag}了解更多关于密ç æ£€æµ‹çš„ä¿¡æ¯%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr "%{linkStartTag}了解有关代ç è´¨é‡æŠ¥å‘Šçš„更多信æ¯%{linkEndTag}"
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "还有%{remainingPackagesCount} 个"
@@ -39544,9 +39962,19 @@ msgstr "在新分支中自动应用补ä¸"
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr "找ä¸åˆ°åŸºå‡†æµæ°´çº¿ä»£ç è´¨é‡äº§ç‰©"
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr "æµè§ˆå™¨æ€§èƒ½æµ‹è¯•æŒ‡æ ‡: "
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr "æµè§ˆå™¨æ€§èƒ½æµ‹è¯•æŒ‡æ ‡ï¼šæ— å˜åŒ–"
@@ -39556,8 +39984,14 @@ msgstr "检查"
msgid "ciReport|Cluster Image Scanning"
msgstr "集群镜åƒæ‰«æ"
-msgid "ciReport|Code quality"
-msgstr "代ç è´¨é‡"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
+msgstr ""
msgid "ciReport|Container Scanning"
msgstr "容器扫æ"
@@ -39622,6 +40056,16 @@ msgstr "找到%{issuesWithCount}"
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "通过创建议题æ¥è°ƒæŸ¥æ­¤æ¼æ´ž"
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr "负载性能测试指标:"
@@ -39655,11 +40099,11 @@ msgstr "SAST"
msgid "ciReport|Secret Detection"
msgstr "密ç æ£€æµ‹"
-msgid "ciReport|Secret scanning"
-msgstr "密ç æ‰«æ"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
+msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
-msgstr "密ç æ‰«æ检测æºä»£ç ä¸­çš„密ç å’Œå‡­æ®æ¼æ´žã€‚"
+msgid "ciReport|Secret detection"
+msgstr ""
msgid "ciReport|Security scanning"
msgstr "安全扫æ"
@@ -39776,6 +40220,12 @@ msgstr "container_nameåªèƒ½åŒ…å«å°å†™å­—æ¯ï¼Œæ•°å­—,'-'å’Œ'.',并且必é
msgid "container_name cannot be larger than %{max_length} chars"
msgstr "container_nameä¸èƒ½è¶…过%{max_length}个字符"
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr "为此项目åšå‡ºè´¡çŒ®ã€‚"
@@ -39801,7 +40251,7 @@ msgid "created %{timeAgo}"
msgstr "创建于%{timeAgo}"
msgid "created %{timeAgo} by %{author}"
-msgstr ""
+msgstr "ç”± %{author} 在 %{timeAgo} 之å‰åˆ›å»º"
msgid "created by"
msgstr "创建人:"
@@ -39831,9 +40281,6 @@ msgstr "部署"
msgid "design"
msgstr "设计"
-msgid "designs"
-msgstr "设计"
-
msgid "detached"
msgstr "已游离"
@@ -39846,6 +40293,12 @@ msgstr "ä¸å­˜åœ¨"
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr "当å‰æ‰©å±•åä¸æ”¯æŒã€‚åªæ”¯æŒ%{extension_list}"
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr "下载"
@@ -39859,6 +40312,9 @@ msgstr "例如, %{token}"
msgid "element is not a hierarchy"
msgstr "此元素并éžç¾¤ç»„层级"
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr "邮箱“%{email}â€è¿˜æœªè¢«éªŒè¯ã€‚"
@@ -39869,7 +40325,7 @@ msgid "encrypted: needs to be a :required, :optional or :migrating!"
msgstr "加密:必须是 :requiredã€:optional 或 :migrating 之一"
msgid "ending with a reserved file extension is not allowed."
-msgstr ""
+msgstr "ä¸å…许以ä¿ç•™çš„文件扩展å结尾。"
msgid "entries cannot be larger than 255 characters"
msgstr "æ¡ç›®ä¸èƒ½è¶…过255个字符"
@@ -39893,6 +40349,9 @@ msgid "estimateCommand|%{slash_command} overwrites the total estimated time."
msgstr "%{slash_command} 覆盖总估计时间。"
msgid "example.com"
+msgstr "example.com"
+
+msgid "exceeds the %{max_value_length} character limit"
msgstr ""
msgid "exceeds the limit of %{bytes} bytes"
@@ -39952,7 +40411,7 @@ msgid_plural "from %d jobs"
msgstr[0] "æ¥è‡ª%d个作业"
msgid "frontmatter"
-msgstr ""
+msgstr "frontmatter"
msgid "group"
msgstr "群组"
@@ -39982,7 +40441,7 @@ msgid "has been completed."
msgstr "已完æˆã€‚"
msgid "has too deep level of nesting"
-msgstr ""
+msgstr "有太深的嵌套级别"
msgid "help"
msgstr "帮助"
@@ -40018,19 +40477,19 @@ msgid "in"
msgstr "于"
msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
+msgstr "在 Infrastructure :: Kubernetes clusters"
msgid "in all GitLab"
-msgstr ""
+msgstr "在此GitLab实例中ä¸è¢«å…许。"
msgid "in group"
-msgstr ""
+msgstr "在群组中"
msgid "in group %{link_to_group}"
msgstr "在 %{link_to_group} 群组"
msgid "in project"
-msgstr ""
+msgstr "在项目中"
msgid "in project %{link_to_project}"
msgstr "在 %{link_to_project} 项目"
@@ -40073,13 +40532,13 @@ msgid "is not a valid X509 certificate."
msgstr "ä¸æ˜¯æœ‰æ•ˆçš„X509è¯ä¹¦ã€‚"
msgid "is not allowed for sign-up."
-msgstr ""
+msgstr "ä¸å…许注册。"
msgid "is not allowed for this group."
-msgstr ""
+msgstr "在此群组中ä¸è¢«å…许。"
msgid "is not allowed for this project."
-msgstr ""
+msgstr "在此项目中ä¸è¢«å…许。"
msgid "is not allowed since the group is not top-level group."
msgstr "ä¸å…许,因为该群组ä¸æ˜¯é¡¶çº§ç¾¤ç»„。"
@@ -40090,6 +40549,12 @@ msgstr "ä¸è¢«å…许。我们目å‰ä¸æ”¯æŒé¡¹ç›®çº§è¿­ä»£"
msgid "is not in the group enforcing Group Managed Account"
msgstr "ä¸åœ¨å¼ºåˆ¶æ‰§è¡Œç¾¤ç»„托管账户的群组"
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr "无效。迭代群组必须与迭代周期组匹é…。"
@@ -40178,7 +40643,7 @@ msgid "log in"
msgstr "登录"
msgid "managed"
-msgstr ""
+msgstr "托管的"
msgid "manual"
msgstr "手动"
@@ -40227,7 +40692,7 @@ msgid "mrWidget| Please restore it or use a different %{missingBranchName} branc
msgstr "请æ¢å¤æ­¤åˆ†æ”¯æˆ–使用其他的 %{missingBranchName} 分支"
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
-msgstr ""
+msgstr "mrWidget|%{linkStart}现在设置%{linkEnd} æ¥åˆ†æžæ‚¨çš„æºä»£ç ä¸­å·²çŸ¥çš„安全æ¼æ´žã€‚"
msgid "mrWidget|%{mergeError}."
msgstr "%{mergeError}。"
@@ -40247,6 +40712,9 @@ msgstr "%{metricsLinkStart} 内存 %{metricsLinkEnd} å ç”¨ %{emphasisStart} æ— 
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr "当å‰%{prefixToLinkStart}æ— æµæ°´çº¿%{prefixToLinkEnd},å¯é€šè¿‡%{addPipelineLinkStart}添加.gitlab-ci.yml æ–‡%{addPipelineLinkEnd}æ¥åˆ›å»ºä¸€ä¸ªã€‚"
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr "æ–°åˆå¹¶åˆ—车已ç»å¯åŠ¨ï¼Œæ­¤åˆå¹¶è¯·æ±‚ä½äºŽåˆå¹¶é˜Ÿåˆ—中的第一ä½ã€‚"
@@ -40280,6 +40748,12 @@ msgstr "é¢å¤–核准"
msgid "mrWidget|Approved by"
msgstr "核准人:"
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr "您会增加技术债务或引入代ç æ¼æ´žå—?"
@@ -40309,7 +40783,7 @@ msgid_plural "mrWidget|Closes issues"
msgstr[0] "关闭议题"
msgid "mrWidget|Create issue to resolve all threads"
-msgstr ""
+msgstr "创建议题æ¥è§£å†³æ‰€æœ‰ä¸»é¢˜"
msgid "mrWidget|Delete source branch"
msgstr "删除æºåˆ†æ”¯"
@@ -40321,7 +40795,7 @@ msgid "mrWidget|Did not close"
msgstr "未关闭"
msgid "mrWidget|Dismiss"
-msgstr ""
+msgstr "关闭"
msgid "mrWidget|Email patches"
msgstr "通过电å­é‚®ä»¶å‘出补ä¸"
@@ -40330,7 +40804,7 @@ msgid "mrWidget|Failed to load deployment statistics"
msgstr "无法加载部署统计信æ¯"
msgid "mrWidget|Hide %{widget} details"
-msgstr ""
+msgstr "éšè— %{widget} 的详细信æ¯"
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "如果 %{missingBranchName} 分支存在于本地仓库中,则å¯ä»¥é€šè¿‡ä»¥ä¸‹å‘½ä»¤è¡Œæ‰‹åŠ¨åˆå¹¶è¯¥åˆå¹¶è¯·æ±‚。"
@@ -40341,6 +40815,9 @@ msgstr "如果最åŽä¸€ä¸ªæµæ°´çº¿è¿è¡Œåœ¨æ´¾ç”Ÿé¡¹ç›®ä¸­ï¼Œå®ƒå¯èƒ½ä¸å‡†ç¡®
msgid "mrWidget|Jump to first unresolved thread"
msgstr "跳转到第一个未解决的主题"
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr "加载部署统计信æ¯ä¸­"
@@ -40372,9 +40849,6 @@ msgstr "åˆå¹¶å¤±è´¥ã€‚"
msgid "mrWidget|Merge locally"
msgstr "本地åˆå¹¶"
-msgid "mrWidget|Merge request approved."
-msgstr "åˆå¹¶è¯·æ±‚已核准。"
-
msgid "mrWidget|Merged by"
msgstr "åˆå¹¶è€…:"
@@ -40442,7 +40916,7 @@ msgid "mrWidget|Revoke approval"
msgstr "撤销核准"
msgid "mrWidget|SAST and Secret Detection is not enabled."
-msgstr ""
+msgstr "SASTå’ŒSecret检测未å¯ç”¨ã€‚"
msgid "mrWidget|Set by %{merge_author} to be added to the merge train when the pipeline succeeds"
msgstr "ç”±%{merge_author}设置为在æµæ°´çº¿æˆåŠŸæ—¶æ·»åŠ åˆ°åˆå¹¶é˜Ÿåˆ—中"
@@ -40454,7 +40928,7 @@ msgid "mrWidget|Set by %{merge_author} to start a merge train when the pipeline
msgstr "ç”±%{merge_author}设置为在æµæ°´çº¿æˆåŠŸæ—¶å¯åŠ¨åˆå¹¶é˜Ÿåˆ—"
msgid "mrWidget|Show %{widget} details"
-msgstr ""
+msgstr "显示 %{widget} 详情"
msgid "mrWidget|The changes were merged into"
msgstr "更改已åˆå¹¶åˆ°"
@@ -40469,7 +40943,7 @@ msgid "mrWidget|The pipeline for this merge request did not complete. Push a new
msgstr "æ­¤åˆå¹¶è¯·æ±‚çš„æµæ°´çº¿æœªå®Œæˆã€‚推é€æ–°çš„æ交以修å¤å¤±è´¥ï¼Œæˆ–检查 %{linkStart}故障排查文档%{linkEnd} 以查看其它å¯èƒ½çš„æ“作。"
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
-msgstr ""
+msgstr "æ­¤åˆå¹¶è¯·æ±‚çš„æµæ°´çº¿æœªå®Œæˆã€‚推é€æ–°çš„æ交以修å¤å¤±è´¥ã€‚"
msgid "mrWidget|The source branch has been deleted"
msgstr "æºåˆ†æ”¯å·²åˆ é™¤"
@@ -40489,12 +40963,6 @@ msgstr "æºåˆ†æ”¯å°†ä¸ä¼šè¢«åˆ é™¤"
msgid "mrWidget|There are merge conflicts"
msgstr "存在åˆå¹¶å†²çª"
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr "æ­¤æ“作将在æµæ°´çº¿%{pipelineLink}æˆåŠŸæ—¶å°†åˆå¹¶è¯·æ±‚加入åˆå¹¶åˆ—车。"
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr "æ­¤æ“作将在æµæ°´çº¿%{pipelineLink}æˆåŠŸæ—¶å¯åŠ¨åˆå¹¶åˆ—车。"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "该åˆå¹¶è¯·æ±‚未能自动åˆå¹¶"
@@ -40510,11 +40978,14 @@ msgstr "è¦åˆå¹¶ï¼Œå¿…须在标题或æ述中æ到Jira议题的key。"
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr "使用%{linkStart}CIæµæ°´çº¿æµ‹è¯•ä½ çš„代ç %{linkEnd},åªéœ€ç®€å•åœ°å‘项目添加一个GitLab CIé…置文件。åªéœ€è¦ä¸€åˆ†é’Ÿï¼Œå°±å¯ä»¥ä½¿ä½ çš„代ç çš„更加安全å¯é ã€‚"
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr "您å¯ä»¥åœ¨åˆ é™¤æ‹’ç»çš„许å¯è¯åŽåˆå¹¶"
msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
+msgstr "您åªèƒ½åœ¨è¿™ä¸ªåˆå¹¶è¯·æ±‚获得批准åŽè¿›è¡Œåˆå¹¶ã€‚"
msgid "mrWidget|Your password"
msgstr "您的密ç "
@@ -40553,11 +41024,17 @@ msgid "must be less than the limit of %{tag_limit} tags"
msgstr "å¿…é¡»å°äºŽ %{tag_limit} 个标签的数é‡é™åˆ¶"
msgid "must be set for a project namespace"
-msgstr ""
+msgstr "必须为项目命å空间设置"
msgid "must be unique by status and elapsed time within a policy"
msgstr "必须在策略中的状æ€å’Œç»è¿‡æ—¶é—´ä¸Šæ˜¯å”¯ä¸€çš„"
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr "my-awesome-group"
@@ -40633,6 +41110,9 @@ msgstr "或"
msgid "originating vulnerability"
msgstr "åˆå§‹æ¼æ´ž"
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] "于总计%d个测试中"
@@ -40663,7 +41143,7 @@ msgid "pipeline"
msgstr "æµæ°´çº¿"
msgid "pipeline schedules documentation"
-msgstr ""
+msgstr "æµæ°´çº¿è®¡åˆ’文件"
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr "pod_nameåªèƒ½åŒ…å«å°å†™å­—æ¯ï¼Œæ•°å­—,'-'å’Œ'.',并且必须以字æ¯å’Œæ•°å­—字符开头和结尾"
@@ -40713,7 +41193,7 @@ msgid "project name"
msgstr "项目å称"
msgid "project namespace cannot be the parent of another namespace"
-msgstr ""
+msgstr "项目命å空间ä¸èƒ½æ˜¯å¦ä¸€ä¸ªå‘½å空间的父级"
msgid "projects"
msgstr "项目"
@@ -40722,16 +41202,16 @@ msgid "quick actions"
msgstr "å¿«æ·æ“作"
msgid "reCAPTCHA"
-msgstr ""
+msgstr "reCAPTCHA"
msgid "reCAPTCHA helps prevent credential stuffing."
-msgstr ""
+msgstr "reCAPTCHA有助于防止凭æ®å †ç Œã€‚"
msgid "reCAPTCHA private key"
-msgstr ""
+msgstr "reCAPTCHA ç§é’¥"
msgid "reCAPTCHA site key"
-msgstr ""
+msgstr "reCAPTCHA 公钥"
msgid "recent activity"
msgstr "最近活动"
@@ -40957,7 +41437,7 @@ msgid "user avatar"
msgstr "用户头åƒ"
msgid "user namespace cannot be the parent of another namespace"
-msgstr ""
+msgstr "用户命å空间ä¸èƒ½æ˜¯å¦ä¸€ä¸ªå‘½å空间的父级"
msgid "user preferences"
msgstr "用户首选项"
@@ -41051,8 +41531,8 @@ msgid "your settings"
msgstr "您的设置"
msgid "{group}"
-msgstr ""
+msgstr "{group}"
msgid "{project}"
-msgstr ""
+msgstr "{project}"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 61c83c95abe..23e48f08c27 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-HK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:19\n"
+"PO-Revision-Date: 2021-11-02 00:42\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,23 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr " 您需è¦åœ¨ %{grace_period_deadline} 之å‰åŸ·è¡Œæ­¤æ“作。"
-msgid " and"
-msgstr " 和"
-
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " é™ä½Ž %d 點"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " æ高 %d 分"
-
msgid " or "
msgstr "或"
@@ -84,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -171,9 +163,6 @@ msgid "%d commit,"
msgid_plural "%d commits,"
msgstr[0] ""
-msgid "%d commits"
-msgstr "%d 個æ交"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -969,6 +958,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1051,9 +1043,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1104,6 +1102,9 @@ msgstr[0] ""
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] ""
@@ -1326,9 +1327,6 @@ msgstr ""
msgid "A deleted user"
msgstr ""
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1362,7 +1360,7 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
@@ -1389,6 +1387,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1737,6 +1738,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "啟用"
@@ -1818,9 +1822,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "å° %{noteable_name} 新增一般留言。"
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
@@ -1899,9 +1900,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr ""
@@ -1995,6 +1993,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2451,7 +2452,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "管ç†å“¡"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2466,6 +2467,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2601,7 +2608,7 @@ msgstr ""
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3216,7 +3223,7 @@ msgstr ""
msgid "All merge request dependencies have been merged"
msgstr ""
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
msgstr ""
msgid "All projects"
@@ -3234,6 +3241,9 @@ msgstr ""
msgid "All users must have a name."
msgstr ""
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -3249,7 +3259,7 @@ msgstr "容許授權開發者å‘å…±åŒå”作分支æ交"
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3489,13 +3499,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3699,6 +3712,10 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "訂閱通知時出錯"
@@ -3762,9 +3779,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4090,12 +4104,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4108,12 +4128,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4126,6 +4155,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4141,6 +4179,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4150,6 +4191,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4421,12 +4465,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4660,6 +4698,9 @@ msgstr "八月"
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5291,6 +5332,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5530,8 +5574,8 @@ msgstr "全部"
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
-msgstr "找ä¸åˆ°æ­¤åˆ†æ”¯çš„ HEAD 更動。"
+msgid "Branches|Can’t find HEAD commit for this branch"
+msgstr ""
msgid "Branches|Compare"
msgstr "比較"
@@ -5641,6 +5685,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5848,9 +5895,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6134,9 +6178,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6194,6 +6235,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6520,6 +6567,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6553,6 +6603,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6667,6 +6720,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6709,15 +6765,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7360,7 +7410,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7801,6 +7851,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7810,6 +7863,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7819,9 +7875,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7834,6 +7905,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -7984,30 +8058,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8146,12 +8196,6 @@ msgstr ""
msgid "Comment"
msgstr "留言"
-msgid "Comment & close %{noteable_name}"
-msgstr "留言並關閉 %{noteable_name}"
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr "留言並é‡æ–°é–‹å•Ÿ %{noteable_name}"
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8267,6 +8311,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr "比較"
@@ -8348,13 +8395,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8363,16 +8410,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configuration not found"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8381,6 +8434,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8393,31 +8452,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8489,15 +8548,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8642,6 +8695,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8764,10 +8820,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -8963,7 +9019,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -8987,9 +9043,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9110,9 +9163,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9182,9 +9232,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9269,9 +9316,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9377,6 +9421,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9395,6 +9442,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr "創建新目錄"
@@ -9407,9 +9457,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9425,6 +9472,9 @@ msgstr ""
msgid "Create a new issue"
msgstr "建立新議題"
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9560,6 +9610,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9677,7 +9730,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9800,10 +9853,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9860,6 +9910,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -9914,6 +9967,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10073,6 +10135,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10138,6 +10203,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -10631,6 +10699,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10697,6 +10768,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10736,18 +10810,36 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
-msgstr "使用 Cron 語法定義自定義模å¼"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "DefaultBranchProtection|Protected against pushes"
msgstr ""
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr "使用 Cron 語法定義自定義模å¼"
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -10820,9 +10912,6 @@ msgstr "刪除留言"
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10850,9 +10939,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -10880,6 +10966,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11039,13 +11128,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11054,7 +11143,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11368,7 +11469,8 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11472,6 +11574,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11487,15 +11595,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11547,6 +11652,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11625,6 +11733,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11670,6 +11781,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11853,12 +11967,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -11950,18 +12058,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -11992,9 +12088,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12220,6 +12313,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12544,10 +12640,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12673,7 +12766,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12728,7 +12824,8 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12829,7 +12926,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13129,6 +13226,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13306,6 +13406,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13601,9 +13704,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13685,6 +13785,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13700,6 +13803,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13727,9 +13833,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13742,6 +13845,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13826,6 +13935,10 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14060,9 +14173,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14253,6 +14363,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14503,6 +14616,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14734,6 +14850,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14794,6 +14913,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr "產生é è¨­çš„標籤"
@@ -15370,6 +15492,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15409,6 +15534,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15424,9 +15552,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15496,10 +15621,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15547,6 +15672,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -15856,6 +15984,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16024,12 +16155,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16258,7 +16383,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16321,9 +16446,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16426,7 +16557,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16555,6 +16686,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16639,7 +16773,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16698,9 +16832,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16722,6 +16853,9 @@ msgstr "æ­·å²ç´€éŒ„"
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16746,6 +16880,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16758,6 +16895,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17325,6 +17465,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17385,6 +17528,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17439,6 +17585,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17457,6 +17606,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -17970,6 +18128,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18070,6 +18231,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18109,6 +18273,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18292,6 +18459,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18367,9 +18537,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18469,6 +18636,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18487,6 +18660,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18502,6 +18678,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18535,6 +18714,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19060,6 +19242,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19153,19 +19338,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19507,6 +19692,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19760,12 +19951,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr "最新æµæ°´ç·š"
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -19934,6 +20131,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20550,6 +20750,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20679,6 +20882,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20766,9 +20972,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -20892,6 +21095,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -20901,6 +21107,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21162,6 +21371,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21207,6 +21419,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21279,6 +21494,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21435,34 +21659,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21489,6 +21707,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21580,9 +21804,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21718,9 +21939,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22166,6 +22384,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22281,6 +22502,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22347,9 +22571,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22657,6 +22878,9 @@ msgstr "新增標籤"
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22771,7 +22995,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22786,6 +23010,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -22981,6 +23208,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23036,9 +23266,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr "éžéš±å¯†"
@@ -23268,18 +23495,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23331,9 +23555,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23535,6 +23756,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23547,6 +23771,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23559,6 +23789,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23574,6 +23807,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23686,15 +23922,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23743,9 +23979,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23773,6 +24006,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23782,6 +24018,9 @@ msgstr "æ“作"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -23851,6 +24090,36 @@ msgstr ""
msgid "Owner"
msgstr "所有者"
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -23926,9 +24195,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24109,14 +24375,15 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24160,9 +24427,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24421,6 +24685,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24442,6 +24709,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -24949,6 +25219,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25069,6 +25342,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25186,6 +25462,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25288,9 +25567,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25435,6 +25720,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25711,12 +25999,18 @@ msgstr "個人資料"
msgid "Profile Settings"
msgstr "個人資料設定"
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25726,9 +26020,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25756,6 +26047,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26047,6 +26341,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26347,6 +26644,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26362,6 +26662,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26545,6 +26848,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26557,6 +26863,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26734,6 +27043,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26824,6 +27136,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -26905,6 +27220,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26932,6 +27250,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -26947,6 +27268,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -26962,54 +27286,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27313,9 +27592,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27331,6 +27607,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27469,6 +27748,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27481,6 +27763,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27667,9 +27952,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27703,6 +27985,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27790,15 +28075,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28278,6 +28563,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28606,6 +28894,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr "申請權é™"
@@ -28615,9 +28906,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28696,13 +28984,13 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] "從 %{names} éœ€è¦ %{count} 批准。"
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
+msgstr[0] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
-msgstr[0] "éœ€è¦ %d 個批准。"
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
+msgstr[0] ""
msgid "Requires values to meet regular expression requirements."
msgstr ""
@@ -29045,9 +29333,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29072,6 +29357,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29081,6 +29375,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29132,6 +29429,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29153,6 +29453,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29192,6 +29510,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29255,6 +29576,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29285,15 +29609,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29390,9 +29705,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29710,6 +30022,9 @@ msgstr[0] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -29935,16 +30250,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -29995,6 +30313,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30013,6 +30334,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30082,6 +30406,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30103,9 +30430,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30139,6 +30463,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30148,6 +30481,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30178,6 +30514,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30301,6 +30640,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30340,10 +30682,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30361,15 +30703,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30628,9 +30964,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30730,9 +31063,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30787,9 +31117,6 @@ msgstr "為賬號添加壹個用於推é€æˆ–拉å–çš„ %{protocol} 密碼。"
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -30880,9 +31207,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -30916,10 +31240,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "設置密碼"
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -30985,6 +31309,10 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31326,9 +31654,6 @@ msgstr "相似議題"
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31395,6 +31720,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr "程å¼ç¢¼ç‰‡æ®µ"
@@ -31419,6 +31747,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31428,6 +31759,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31452,9 +31786,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32049,12 +32380,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32094,6 +32419,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32592,7 +32920,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32691,18 +33019,12 @@ msgstr ""
msgid "Sunday"
msgstr "星期日"
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32724,9 +33046,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32739,12 +33058,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32760,30 +33073,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -32811,9 +33109,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -32826,9 +33121,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -32871,6 +33163,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33057,6 +33352,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33081,6 +33379,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "團隊"
@@ -33093,6 +33400,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33461,6 +33771,9 @@ msgstr[0] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33530,6 +33843,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33560,9 +33876,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33630,6 +33943,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33714,6 +34030,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -33819,9 +34138,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -33855,9 +34171,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34017,6 +34330,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34101,6 +34417,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34287,9 +34606,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34512,7 +34828,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -34815,6 +35131,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -34953,6 +35275,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35282,7 +35607,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35318,7 +35643,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35504,6 +35829,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35597,7 +35937,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -35964,6 +36304,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36048,6 +36391,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36381,6 +36727,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36399,10 +36748,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36414,6 +36763,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36459,9 +36811,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36501,10 +36850,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36654,6 +37003,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36684,6 +37036,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36750,6 +37105,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37101,6 +37462,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37110,6 +37474,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37155,10 +37528,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -37815,6 +38200,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38010,6 +38398,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38019,9 +38410,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38034,6 +38422,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38041,9 +38432,6 @@ msgstr[0] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38350,10 +38738,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38395,9 +38783,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38464,6 +38849,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38620,9 +39008,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38722,9 +39107,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -38812,6 +39194,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -38821,9 +39206,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39275,28 +39657,55 @@ msgstr[0] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39308,6 +39717,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39320,9 +39732,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39427,12 +39836,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39460,6 +39875,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39475,9 +39893,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39508,6 +39923,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39544,9 +39962,19 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39556,7 +39984,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39622,6 +40056,16 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39655,10 +40099,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39776,6 +40220,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -39831,9 +40281,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -39846,6 +40293,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -39859,6 +40312,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -39895,6 +40351,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40090,6 +40549,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40247,6 +40712,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40280,6 +40748,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40341,6 +40815,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40372,9 +40849,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40489,12 +40963,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40510,6 +40978,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40558,6 +41029,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40633,6 +41110,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 6f45fa86aa7..f6346a983e9 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-TW\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-10-04 20:20\n"
+"PO-Revision-Date: 2021-11-02 00:38\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -40,23 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr " 您需è¦åœ¨ %{grace_period_deadline} 之å‰åŸ·è¡Œæ­¤å‹•ä½œã€‚"
-msgid " and"
-msgstr "和"
-
msgid " and "
msgstr "和"
msgid " and %{sliced}"
msgstr " 和 %{sliced}"
-msgid " degraded on %d point"
-msgid_plural " degraded on %d points"
-msgstr[0] " æ–¼ %d 處有下é™"
-
-msgid " improved on %d point"
-msgid_plural " improved on %d points"
-msgstr[0] " æ–¼ %d 處有æå‡"
-
msgid " or "
msgstr " 或 "
@@ -84,6 +73,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#%{issueIid} (closed)"
+msgstr ""
+
msgid "#general, #development"
msgstr ""
@@ -171,9 +163,6 @@ msgid "%d commit,"
msgid_plural "%d commits,"
msgstr[0] "%d 次æ交,"
-msgid "%d commits"
-msgstr "%d 次æ交"
-
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@@ -969,6 +958,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
+msgid "%{widget} options"
+msgstr ""
+
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@@ -1051,9 +1043,15 @@ msgstr "(已刪除)"
msgid "(revoked)"
msgstr ""
+msgid "(this user)"
+msgstr ""
+
msgid "(we need your current password to confirm your changes)"
msgstr ""
+msgid "* All times are in UTC unless specified"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ 其餘 %{amount} 項"
@@ -1104,6 +1102,9 @@ msgstr[0] "- 事件"
msgid "- Not available to run jobs."
msgstr ""
+msgid "- Select -"
+msgstr ""
+
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- 使用者"
@@ -1326,9 +1327,6 @@ msgstr "無法設定空專案的é è¨­åˆ†æ”¯ã€‚"
msgid "A deleted user"
msgstr "已刪除的使用者"
-msgid "A description is required"
-msgstr ""
-
msgid "A different reason"
msgstr ""
@@ -1362,8 +1360,8 @@ msgstr "濫用審查團隊æˆå“¡å°‡æœƒå„˜å¿«æª¢é–±æ‚¨çš„報告。"
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
-msgstr "已建立新的自動 DevOps æµæ°´ç·šï¼Œè«‹å‰å¾€ %{pipelines_link_start}æµæ°´ç·šé é¢%{pipelines_link_end} 檢視詳細訊æ¯ã€‚"
+msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
+msgstr ""
msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
msgstr "%{name} 的新版本 %{tag} å·²ç¶“ç™¼å¸ƒã€‚è«‹å­˜å– %{release_link_start}發布版é é¢%{release_link_end} 了解更多資訊。"
@@ -1389,6 +1387,9 @@ msgstr ""
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr ""
+msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
+msgstr ""
+
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr ""
@@ -1737,6 +1738,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr "啟用æœå‹™å°"
+msgid "Activated on"
+msgstr ""
+
msgid "Active"
msgstr "使用中"
@@ -1818,9 +1822,6 @@ msgstr ""
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "加入一般留言至 %{noteableDisplayName}。"
-msgid "Add a general comment to this %{noteable_name}."
-msgstr "加入一般留言至 %{noteable_name}。"
-
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "在 wiki 中加入首é ï¼Œå…¶ä¸­åŒ…å«æœ‰é—œå°ˆæ¡ˆçš„資訊,GitLab 將在這裡顯示該首é ï¼Œè€Œä¸æ˜¯æ­¤è¨Šæ¯ã€‚"
@@ -1899,9 +1900,6 @@ msgstr ""
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
msgstr ""
-msgid "Add domain"
-msgstr ""
-
msgid "Add email address"
msgstr "加入電å­éƒµä»¶åœ°å€"
@@ -1995,6 +1993,9 @@ msgstr "加入待審閱"
msgid "Add to tree"
msgstr "加入到樹"
+msgid "Add topics to projects to help users find them."
+msgstr ""
+
msgid "Add trigger"
msgstr ""
@@ -2451,7 +2452,7 @@ msgstr ""
msgid "AdminUsers|Admin"
msgstr "管ç†å“¡"
-msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
msgstr ""
msgid "AdminUsers|Admins"
@@ -2466,6 +2467,12 @@ msgstr ""
msgid "AdminUsers|Approved users can:"
msgstr ""
+msgid "AdminUsers|Auditor"
+msgstr ""
+
+msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
+msgstr ""
+
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2601,7 +2608,7 @@ msgstr "å–消å‡çµä½¿ç”¨è€…將會:"
msgid "AdminUsers|Regular"
msgstr ""
-msgid "AdminUsers|Regular users have access to their groups and projects"
+msgid "AdminUsers|Regular users have access to their groups and projects."
msgstr ""
msgid "AdminUsers|Reject"
@@ -3216,8 +3223,8 @@ msgstr "所有åˆä½µè¡çªå‡å·²è§£æ±ºã€‚æ­¤åˆä½µè«‹æ±‚ç¾åœ¨å¯ä»¥åˆä½µã€‚"
msgid "All merge request dependencies have been merged"
msgstr "所有åˆä½µè«‹æ±‚ä¾è³´é—œä¿‚å‡å·²åˆä½µ"
-msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
-msgstr "所有路徑都相å°æ–¼ GitLab 網å€ã€‚è«‹ä¸è¦åŒ…å«%{relative_url_link_start}相å°ç¶²å€%{relative_url_link_end}。"
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
+msgstr ""
msgid "All projects"
msgstr "所有專案"
@@ -3234,6 +3241,9 @@ msgstr ""
msgid "All users must have a name."
msgstr "所有的使用者都必須具有å稱。"
+msgid "All users with matching cards"
+msgstr ""
+
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "å…許「%{group_name}ã€ä»¥æ‚¨çš„身份登入"
@@ -3249,7 +3259,7 @@ msgstr "å…許具有åˆä½µåˆ°ç›®æ¨™åˆ†æ”¯æ¬Šé™çš„æˆå“¡æ交"
msgid "Allow group owners to manage LDAP-related settings"
msgstr "å…è¨±ç¾¤çµ„æ‰€æœ‰è€…ç®¡ç† LDAP 相關的設定"
-msgid "Allow non-administrators to access to the performance bar"
+msgid "Allow non-administrators access to the performance bar"
msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
@@ -3489,13 +3499,16 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches. Retry the search."
+msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
-msgid "An error occurred while fetching commits. Retry the search."
+msgid "An error occurred while fetching commit data."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
msgstr ""
msgid "An error occurred while fetching coverage reports."
@@ -3699,6 +3712,10 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}"
msgstr ""
+msgid "An error occurred while saving the setting"
+msgid_plural "An error occurred while saving the settings"
+msgstr[0] ""
+
msgid "An error occurred while subscribing to notifications."
msgstr "訂閱通知時發生錯誤。"
@@ -3762,9 +3779,6 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
-msgid "An instance-level serverless domain already exists."
-msgstr ""
-
msgid "An issue already exists"
msgstr ""
@@ -4090,12 +4104,18 @@ msgstr ""
msgid "ApprovalRule|All severity levels"
msgstr ""
+msgid "ApprovalRule|All vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
msgstr ""
+msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4108,12 +4128,21 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Confirmed"
+msgstr ""
+
+msgid "ApprovalRule|Dismissed"
+msgstr ""
+
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
msgid "ApprovalRule|Name"
msgstr ""
+msgid "ApprovalRule|Newly detected"
+msgstr ""
+
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4126,6 +4155,15 @@ msgstr ""
msgid "ApprovalRule|Please select at least one severity level"
msgstr ""
+msgid "ApprovalRule|Please select at least one vulnerability state"
+msgstr ""
+
+msgid "ApprovalRule|Previously detected"
+msgstr ""
+
+msgid "ApprovalRule|Resolved"
+msgstr ""
+
msgid "ApprovalRule|Rule name"
msgstr ""
@@ -4141,6 +4179,9 @@ msgstr ""
msgid "ApprovalRule|Select severity levels"
msgstr ""
+msgid "ApprovalRule|Select vulnerability states"
+msgstr ""
+
msgid "ApprovalRule|Severity levels"
msgstr ""
@@ -4150,6 +4191,9 @@ msgstr ""
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
+msgid "ApprovalRule|Vulnerability states"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4421,12 +4465,6 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
-msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
-
-msgid "Are you sure? This will invalidate your registered applications and U2F devices."
-msgstr ""
-
msgid "Arrange charts"
msgstr ""
@@ -4660,6 +4698,9 @@ msgstr ""
msgid "Authenticate"
msgstr ""
+msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
+msgstr ""
+
msgid "Authenticate with GitHub"
msgstr ""
@@ -5291,6 +5332,9 @@ msgstr ""
msgid "Blog"
msgstr ""
+msgid "Board scope affects which epics are displayed for anyone who visits this board"
+msgstr ""
+
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr ""
@@ -5530,7 +5574,7 @@ msgstr ""
msgid "Branches|Cancel, keep branch"
msgstr ""
-msgid "Branches|Cant find HEAD commit for this branch"
+msgid "Branches|Can’t find HEAD commit for this branch"
msgstr ""
msgid "Branches|Compare"
@@ -5641,6 +5685,9 @@ msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
+msgid "Branches|Unable to load branches"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -5848,9 +5895,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
-msgid "CI minutes"
-msgstr ""
-
msgid "CI settings"
msgstr ""
@@ -6134,9 +6178,6 @@ msgstr ""
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
msgstr ""
-msgid "Cannot be assigned to other projects."
-msgstr ""
-
msgid "Cannot be merged automatically"
msgstr ""
@@ -6194,6 +6235,12 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "Card holder name"
+msgstr ""
+
+msgid "Card number:"
+msgstr ""
+
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6520,6 +6567,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
+msgid "Checkout|CI minutes"
+msgstr ""
+
msgid "Checkout|Checkout"
msgstr ""
@@ -6553,6 +6603,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
+msgid "Checkout|Enter a number greater than 0"
+msgstr ""
+
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -6667,6 +6720,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
+msgid "Checkout|x %{quantity} %{units} per pack"
+msgstr ""
+
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
@@ -6709,15 +6765,9 @@ msgstr ""
msgid "Choose a type..."
msgstr ""
-msgid "Choose any color"
-msgstr ""
-
msgid "Choose any color."
msgstr ""
-msgid "Choose any color. Or you can choose one of the suggested colors below"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -7360,7 +7410,7 @@ msgstr ""
msgid "ClusterIntegration|Check your token"
msgstr ""
-msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
@@ -7801,6 +7851,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Select a VPC"
+msgstr ""
+
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
@@ -7810,6 +7863,9 @@ msgstr ""
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Select a network"
+msgstr ""
+
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr ""
@@ -7819,9 +7875,24 @@ msgstr ""
msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
+msgid "ClusterIntegration|Select a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a subnetwork"
+msgstr ""
+
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr ""
+msgid "ClusterIntegration|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Select key pair"
+msgstr ""
+
msgid "ClusterIntegration|Select machine type"
msgstr ""
@@ -7834,6 +7905,9 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
+msgid "ClusterIntegration|Select service role"
+msgstr ""
+
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
msgstr ""
@@ -7984,30 +8058,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select a VPC"
-msgstr ""
-
-msgid "ClusterIntergation|Select a network"
-msgstr ""
-
-msgid "ClusterIntergation|Select a security group"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnet"
-msgstr ""
-
-msgid "ClusterIntergation|Select a subnetwork"
-msgstr ""
-
-msgid "ClusterIntergation|Select an instance type"
-msgstr ""
-
-msgid "ClusterIntergation|Select key pair"
-msgstr ""
-
-msgid "ClusterIntergation|Select service role"
-msgstr ""
-
msgid "Clusters|An error occurred while loading clusters"
msgstr ""
@@ -8146,12 +8196,6 @@ msgstr ""
msgid "Comment"
msgstr ""
-msgid "Comment & close %{noteable_name}"
-msgstr ""
-
-msgid "Comment & reopen %{noteable_name}"
-msgstr ""
-
msgid "Comment & resolve thread"
msgstr ""
@@ -8267,6 +8311,9 @@ msgstr ""
msgid "Company"
msgstr ""
+msgid "Company Name"
+msgstr ""
+
msgid "Compare"
msgstr ""
@@ -8348,13 +8395,13 @@ msgstr ""
msgid "Completed"
msgstr ""
-msgid "Compliance"
+msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
-msgid "Compliance Dashboard"
+msgid "Compliance framework"
msgstr ""
-msgid "Compliance framework"
+msgid "Compliance report"
msgstr ""
msgid "ComplianceDashboard|created by:"
@@ -8363,16 +8410,22 @@ msgstr ""
msgid "ComplianceFrameworks|Add framework"
msgstr ""
-msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgid "ComplianceFrameworks|Background color"
+msgstr ""
+
+msgid "ComplianceFrameworks|Cancel"
msgstr ""
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
-msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Configuration not found"
msgstr ""
-msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
@@ -8381,6 +8434,12 @@ msgstr ""
msgid "ComplianceFrameworks|Delete framework"
msgstr ""
+msgid "ComplianceFrameworks|Description"
+msgstr ""
+
+msgid "ComplianceFrameworks|Description is required"
+msgstr ""
+
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8393,31 +8452,31 @@ msgstr ""
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
msgstr ""
-msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgid "ComplianceFrameworks|Invalid format"
msgstr ""
-msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
+msgid "ComplianceFrameworks|Name"
msgstr ""
-msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgid "ComplianceFrameworks|Name is required"
msgstr ""
-msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
-msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
-msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
msgstr ""
-msgid "ComplianceFramework|Edit Compliance Framework"
+msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
-msgid "ComplianceFramework|New Compliance Framework"
+msgid "ComplianceFramework|New compliance framework"
msgstr ""
msgid "Component"
@@ -8489,15 +8548,9 @@ msgstr ""
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
-msgid "Configure approvals by authors and committers on all projects."
-msgstr ""
-
msgid "Configure existing installation"
msgstr ""
-msgid "Configure paths to be protected by Rack Attack."
-msgstr ""
-
msgid "Configure repository mirroring."
msgstr ""
@@ -8642,6 +8695,9 @@ msgstr ""
msgid "Contact support"
msgstr ""
+msgid "Contacts"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -8764,10 +8820,10 @@ msgstr ""
msgid "ContainerRegistry|Delete selected tags"
msgstr ""
-msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
+msgid "ContainerRegistry|Delete tag"
msgstr ""
-msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
msgid "ContainerRegistry|Digest: %{imageId}"
@@ -8963,7 +9019,7 @@ msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr ""
-msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
msgstr ""
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
@@ -8987,9 +9043,6 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
-msgid "Contains %{count} blobs of images (%{size})"
-msgstr ""
-
msgid "Content parsed with %{link}."
msgstr ""
@@ -9110,9 +9163,6 @@ msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
-msgid "Copy %{proxy_url}"
-msgstr ""
-
msgid "Copy %{type}"
msgstr ""
@@ -9182,9 +9232,6 @@ msgstr ""
msgid "Copy link to chart"
msgstr ""
-msgid "Copy prefix"
-msgstr ""
-
msgid "Copy reference"
msgstr ""
@@ -9269,9 +9316,6 @@ msgstr ""
msgid "Could not apply %{name} command."
msgstr ""
-msgid "Could not archive %{design}. Please try again."
-msgstr ""
-
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -9377,6 +9421,9 @@ msgstr ""
msgid "Couldn't assign policy to project"
msgstr ""
+msgid "Country"
+msgstr ""
+
msgid "Coverage"
msgstr ""
@@ -9395,6 +9442,9 @@ msgstr ""
msgid "Create %{type}"
msgstr ""
+msgid "Create %{workspace} label"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9407,9 +9457,6 @@ msgstr ""
msgid "Create a Mattermost team for this group"
msgstr ""
-msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr ""
-
msgid "Create a merge request"
msgstr ""
@@ -9425,6 +9472,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
+msgid "Create a new project"
+msgstr ""
+
msgid "Create a new repository"
msgstr ""
@@ -9560,6 +9610,9 @@ msgstr ""
msgid "Create tag %{tagName}"
msgstr ""
+msgid "Create topic"
+msgstr ""
+
msgid "Create user"
msgstr ""
@@ -9677,7 +9730,7 @@ msgstr ""
msgid "CreateValueStreamForm|Restore stage"
msgstr ""
-msgid "CreateValueStreamForm|Save Value Stream"
+msgid "CreateValueStreamForm|Save value stream"
msgstr ""
msgid "CreateValueStreamForm|Select end event"
@@ -9800,10 +9853,7 @@ msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
-msgid "Credit card validated at:"
-msgstr ""
-
-msgid "Credit card validated:"
+msgid "Credit card:"
msgstr ""
msgid "Critical vulnerabilities present"
@@ -9860,6 +9910,9 @@ msgstr ""
msgid "Current sign-in at:"
msgstr ""
+msgid "Current sign-in ip"
+msgstr ""
+
msgid "Current vulnerabilities count"
msgstr ""
@@ -9914,6 +9967,15 @@ msgstr ""
msgid "Custom range (UTC)"
msgstr ""
+msgid "Customer Relations Contacts"
+msgstr ""
+
+msgid "Customer Relations Organizations"
+msgstr ""
+
+msgid "Customer relations"
+msgstr ""
+
msgid "Customizable by an administrator."
msgstr ""
@@ -10073,6 +10135,9 @@ msgstr ""
msgid "CycleAnalytics|Display chart filters"
msgstr ""
+msgid "CycleAnalytics|Lead Time for Changes"
+msgstr ""
+
msgid "CycleAnalytics|No stages selected"
msgstr ""
@@ -10138,6 +10203,9 @@ msgstr ""
msgid "DAST Scans"
msgstr ""
+msgid "DAST profile not found: %{name}"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -10631,6 +10699,9 @@ msgstr ""
msgid "Date range"
msgstr ""
+msgid "Date range limited to %{number} days"
+msgstr ""
+
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
@@ -10697,6 +10768,9 @@ msgstr ""
msgid "Default branch and protected branches"
msgstr ""
+msgid "Default branch protection"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -10736,16 +10810,34 @@ msgstr ""
msgid "DefaultBranchLabel|default"
msgstr ""
-msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
-msgid "Define a custom pattern with cron syntax"
+msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
+msgstr ""
+
+msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
+msgstr ""
+
+msgid "DefaultBranchProtection|Fully protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Not protected"
+msgstr ""
+
+msgid "DefaultBranchProtection|Partially protected"
msgstr ""
-msgid "Define approval rules."
+msgid "DefaultBranchProtection|Protected against pushes"
msgstr ""
-msgid "Define approval rules. %{linkStart}Learn more.%{linkEnd}"
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
msgstr ""
msgid "Define custom rules for what constitutes spam, independent of Akismet"
@@ -10820,9 +10912,6 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
-msgid "Delete domain"
-msgstr ""
-
msgid "Delete file"
msgstr ""
@@ -10850,9 +10939,6 @@ msgstr ""
msgid "Delete self monitoring project"
msgstr ""
-msgid "Delete serverless domain?"
-msgstr ""
-
msgid "Delete snippet"
msgstr ""
@@ -10880,6 +10966,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11039,13 +11128,13 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
-msgid "Dependency proxy"
+msgid "DependencyProxy|Cached %{time}"
msgstr ""
-msgid "Dependency proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
-msgid "Dependency proxy image prefix"
+msgid "DependencyProxy|Copy prefix"
msgstr ""
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
@@ -11054,7 +11143,19 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Toggle Dependency Proxy"
+msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr ""
+
+msgid "DependencyProxy|Enable Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Manifest list"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11368,7 +11469,8 @@ msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|%{filename} did not change."
-msgstr ""
+msgid_plural "DesignManagement|The designs you tried uploading did not change."
+msgstr[0] ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
@@ -11472,6 +11574,12 @@ msgstr ""
msgid "DesignManagement|Select all"
msgstr ""
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
+msgstr ""
+
+msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
+msgstr ""
+
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
@@ -11487,15 +11595,12 @@ msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
-msgid "DesignManagement|Upload skipped."
+msgid "DesignManagement|Upload skipped. %{reason}"
msgstr ""
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr ""
-msgid "DesignManagement|and %{moreCount} more."
-msgstr ""
-
msgid "Designs"
msgstr ""
@@ -11547,6 +11652,9 @@ msgstr ""
msgid "DevopsAdoption|Adoption by subgroup"
msgstr ""
+msgid "DevopsAdoption|Adoption over time"
+msgstr ""
+
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
@@ -11625,6 +11733,9 @@ msgstr ""
msgid "DevopsAdoption|No results…"
msgstr ""
+msgid "DevopsAdoption|No tracked features"
+msgstr ""
+
msgid "DevopsAdoption|Not adopted"
msgstr ""
@@ -11670,6 +11781,9 @@ msgstr ""
msgid "DevopsAdoption|This group has no subgroups"
msgstr ""
+msgid "DevopsAdoption|Total number of features adopted"
+msgstr ""
+
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
@@ -11853,12 +11967,6 @@ msgstr ""
msgid "Discover|Upgrade now"
msgstr ""
-msgid "Discuss a specific suggestion or question"
-msgstr ""
-
-msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
-
msgid "Discuss a specific suggestion or question that needs to be resolved."
msgstr ""
@@ -11950,18 +12058,6 @@ msgstr ""
msgid "Domain Name"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
-msgstr ""
-
-msgid "Domain was successfully created."
-msgstr ""
-
-msgid "Domain was successfully deleted."
-msgstr ""
-
-msgid "Domain was successfully updated."
-msgstr ""
-
msgid "Don't have an account yet?"
msgstr ""
@@ -11992,9 +12088,6 @@ msgstr ""
msgid "Download %{format}:"
msgstr ""
-msgid "Download %{name} artifact"
-msgstr ""
-
msgid "Download (%{fileSizeReadable})"
msgstr ""
@@ -12220,6 +12313,9 @@ msgstr ""
msgid "Edit title and description"
msgstr ""
+msgid "Edit topic: %{topic_name}"
+msgstr ""
+
msgid "Edit user: %{user_name}"
msgstr ""
@@ -12544,10 +12640,7 @@ msgstr ""
msgid "Enable or disable version check and Service Ping."
msgstr ""
-msgid "Enable protected paths rate limit"
-msgstr ""
-
-msgid "Enable proxy"
+msgid "Enable rate limiting for POST requests to the specified paths"
msgstr ""
msgid "Enable reCAPTCHA"
@@ -12673,7 +12766,10 @@ msgstr ""
msgid "Enter an integer number between 0 and 100"
msgstr ""
-msgid "Enter an integer number number between 0 and 100"
+msgid "Enter any color or choose one of the suggested colors below."
+msgstr ""
+
+msgid "Enter any color."
msgstr ""
msgid "Enter at least three characters to search"
@@ -12728,7 +12824,8 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgid_plural "Environments"
+msgstr[0] ""
msgid "Environment does not have deployments"
msgstr ""
@@ -12829,7 +12926,7 @@ msgstr ""
msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
-msgid "Environments|Auto stop in"
+msgid "Environments|Auto stop"
msgstr ""
msgid "Environments|Auto stops %{autoStopAt}"
@@ -13129,6 +13226,9 @@ msgstr ""
msgid "Error creating label."
msgstr ""
+msgid "Error creating new directory. Please try again."
+msgstr ""
+
msgid "Error creating new iteration"
msgstr ""
@@ -13306,6 +13406,9 @@ msgstr ""
msgid "Error: %{error_message}"
msgstr ""
+msgid "Error: %{error}"
+msgstr ""
+
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13601,9 +13704,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
-msgstr ""
-
msgid "Except policy:"
msgstr ""
@@ -13685,6 +13785,9 @@ msgstr ""
msgid "Expiration date (optional)"
msgstr ""
+msgid "Expiration date:"
+msgstr ""
+
msgid "Expired"
msgstr ""
@@ -13700,6 +13803,9 @@ msgstr ""
msgid "Expires in %{expires_at}"
msgstr ""
+msgid "Expires on"
+msgstr ""
+
msgid "Expires:"
msgstr ""
@@ -13727,9 +13833,6 @@ msgstr ""
msgid "Export"
msgstr ""
-msgid "Export %{name}"
-msgstr ""
-
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -13742,6 +13845,12 @@ msgstr ""
msgid "Export group"
msgstr ""
+msgid "Export issues"
+msgstr ""
+
+msgid "Export merge requests"
+msgstr ""
+
msgid "Export project"
msgstr ""
@@ -13826,6 +13935,10 @@ msgstr ""
msgid "Failed to apply commands."
msgstr ""
+msgid "Failed to archive a design. Please try again."
+msgid_plural "Failed to archive designs. Please try again."
+msgstr[0] ""
+
msgid "Failed to assign a reviewer because no user was found."
msgstr ""
@@ -14060,9 +14173,6 @@ msgstr ""
msgid "Failed to upload object map file"
msgstr ""
-msgid "Failed to verify domain ownership"
-msgstr ""
-
msgid "Failure"
msgstr ""
@@ -14253,6 +14363,9 @@ msgstr ""
msgid "FeatureFlags|Remove"
msgstr ""
+msgid "FeatureFlags|Search code references"
+msgstr ""
+
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr ""
@@ -14503,6 +14616,9 @@ msgstr ""
msgid "Finished at"
msgstr ""
+msgid "First Name"
+msgstr ""
+
msgid "First Seen"
msgstr ""
@@ -14734,6 +14850,9 @@ msgstr ""
msgid "Framework successfully deleted"
msgstr ""
+msgid "Free"
+msgstr ""
+
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -14794,6 +14913,9 @@ msgstr ""
msgid "General pipelines"
msgstr ""
+msgid "General settings"
+msgstr ""
+
msgid "Generate a default set of labels"
msgstr ""
@@ -15370,6 +15492,9 @@ msgstr ""
msgid "GitLab commit"
msgstr ""
+msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
+msgstr ""
+
msgid "GitLab export"
msgstr ""
@@ -15409,6 +15534,9 @@ msgstr ""
msgid "GitLab project export"
msgstr ""
+msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "GitLab single sign-on URL"
msgstr ""
@@ -15424,9 +15552,6 @@ msgstr ""
msgid "GitLab version"
msgstr ""
-msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "GitLab.com"
msgstr ""
@@ -15496,10 +15621,10 @@ msgstr ""
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
-msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
-msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
msgstr ""
msgid "GitLabPages|Unverified"
@@ -15547,6 +15672,9 @@ msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
+msgid "GithubIntegration|Enable static status check names"
+msgstr ""
+
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
@@ -15856,6 +15984,9 @@ msgstr ""
msgid "Group by"
msgstr ""
+msgid "Group description"
+msgstr ""
+
msgid "Group description (optional)"
msgstr ""
@@ -16024,12 +16155,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
-msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
-msgstr ""
-
-msgid "GroupRoadmap|Some of your epics might not be visible"
-msgstr ""
-
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
@@ -16258,7 +16383,7 @@ msgstr ""
msgid "GroupSettings|Compliance frameworks"
msgstr ""
-msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "GroupSettings|Custom project templates"
@@ -16321,9 +16446,15 @@ msgstr ""
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
+msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
+msgstr ""
+
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select the project that contains your custom Insights file."
+msgstr ""
+
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16426,7 +16557,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups."
+msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@@ -16555,6 +16686,9 @@ msgstr ""
msgid "Header must be associated with a request or response"
msgstr ""
+msgid "Headers"
+msgstr ""
+
msgid "Heading 1"
msgstr ""
@@ -16639,7 +16773,7 @@ msgstr ""
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr ""
-msgid "Helps reduce request volume for protected paths"
+msgid "Helps reduce request volume for protected paths."
msgstr ""
msgid "Here you will find recent merge request activity"
@@ -16698,9 +16832,6 @@ msgstr ""
msgid "High or unknown vulnerabilities present"
msgstr ""
-msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
-msgstr ""
-
msgid "Highest role:"
msgstr ""
@@ -16722,6 +16853,9 @@ msgstr ""
msgid "History of authentications"
msgstr ""
+msgid "Holder name:"
+msgstr ""
+
msgid "Home page URL"
msgstr ""
@@ -16746,6 +16880,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
+msgid "House your files, plan your work, collaborate on code, and more."
+msgstr ""
+
msgid "Housekeeping"
msgstr ""
@@ -16758,6 +16895,9 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
+msgid "How do I configure authentication using the GitLab database?"
+msgstr ""
+
msgid "How do I configure it?"
msgstr ""
@@ -17325,6 +17465,9 @@ msgstr ""
msgid "InProductMarketing|Do you have a minute?"
msgstr ""
+msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
+msgstr ""
+
msgid "InProductMarketing|Easy"
msgstr ""
@@ -17385,6 +17528,9 @@ msgstr ""
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr ""
+msgid "InProductMarketing|GitLab is better with teammates to help out!"
+msgstr ""
+
msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
msgstr ""
@@ -17439,6 +17585,9 @@ msgstr ""
msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr ""
+msgid "InProductMarketing|Invite them to help out."
+msgstr ""
+
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr ""
@@ -17457,6 +17606,15 @@ msgstr ""
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
msgstr ""
+msgid "InProductMarketing|Invite your teammates to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates to help"
+msgstr ""
+
+msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
+msgstr ""
+
msgid "InProductMarketing|It's all in the stats"
msgstr ""
@@ -17970,6 +18128,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Inline math"
+msgstr ""
+
msgid "Input host keys manually"
msgstr ""
@@ -18070,6 +18231,9 @@ msgstr ""
msgid "Insufficient permissions"
msgstr ""
+msgid "Insufficient permissions for dast_configuration keyword"
+msgstr ""
+
msgid "Integration"
msgstr ""
@@ -18109,6 +18273,9 @@ msgstr ""
msgid "Integrations|An error occurred while loading projects using custom settings."
msgstr ""
+msgid "Integrations|Branches for which notifications are to be sent"
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -18292,6 +18459,9 @@ msgstr ""
msgid "Internal URL (optional)"
msgstr ""
+msgid "Internal error occured while delivering this webhook."
+msgstr ""
+
msgid "Internal users"
msgstr ""
@@ -18367,9 +18537,6 @@ msgstr ""
msgid "Invalid policy type"
msgstr ""
-msgid "Invalid query"
-msgstr ""
-
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
msgstr ""
@@ -18469,6 +18636,12 @@ msgstr ""
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|You were assigned the following tasks:"
+msgstr ""
+
+msgid "InviteEmail|and has assigned you the following tasks:"
+msgstr ""
+
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
@@ -18487,6 +18660,9 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
+msgid "InviteMembersModal|Choose a project for the issues"
+msgstr ""
+
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -18502,6 +18678,9 @@ msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
@@ -18535,6 +18714,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
+msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
+msgstr ""
+
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
@@ -19060,6 +19242,9 @@ msgstr ""
msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
+msgid "Iterations|The iteration has been deleted."
+msgstr ""
+
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19153,19 +19338,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again."
+msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
-msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again."
+msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr ""
msgid "JiraService| on branch %{branch_link}"
@@ -19507,6 +19692,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Join a project"
+msgstr ""
+
+msgid "Join your team on GitLab and contribute to an existing project"
+msgstr ""
+
msgid "Joined %{time_ago}"
msgstr ""
@@ -19760,12 +19951,18 @@ msgstr ""
msgid "Last Activity"
msgstr ""
+msgid "Last Name"
+msgstr ""
+
msgid "Last Pipeline"
msgstr ""
msgid "Last Seen"
msgstr ""
+msgid "Last Sync"
+msgstr ""
+
msgid "Last Used"
msgstr ""
@@ -19934,6 +20131,9 @@ msgstr ""
msgid "Learn more about group-level project templates"
msgstr ""
+msgid "Learn more about groups."
+msgstr ""
+
msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
msgstr ""
@@ -20550,6 +20750,9 @@ msgstr ""
msgid "Makes this issue confidential."
msgstr ""
+msgid "Manage %{workspace} labels"
+msgstr ""
+
msgid "Manage Web IDE features."
msgstr ""
@@ -20679,6 +20882,9 @@ msgstr ""
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
+msgid "Marked as draft. Can only be merged when marked as ready."
+msgstr ""
+
msgid "Marked as ready. Merging is now allowed."
msgstr ""
@@ -20766,9 +20972,6 @@ msgstr ""
msgid "Max session time"
msgstr ""
-msgid "MaxBuilds"
-msgstr ""
-
msgid "Maximum 20 characters"
msgstr ""
@@ -20892,6 +21095,9 @@ msgstr ""
msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr ""
+msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
+msgstr ""
+
msgid "Maximum number of comments exceeded"
msgstr ""
@@ -20901,6 +21107,9 @@ msgstr ""
msgid "Maximum number of projects."
msgstr ""
+msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
+msgstr ""
+
msgid "Maximum number of unique IP addresses per user."
msgstr ""
@@ -21162,6 +21371,9 @@ msgstr ""
msgid "Merge blocked: new changes were just added."
msgstr ""
+msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
+msgstr ""
+
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -21207,6 +21419,9 @@ msgstr ""
msgid "Merge request events"
msgstr ""
+msgid "Merge request reports"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21279,6 +21494,15 @@ msgstr ""
msgid "MergeRequestAnalytics|Time to merge"
msgstr ""
+msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
+msgstr ""
+
+msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -21435,34 +21659,28 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
-
-msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
msgstr ""
-msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
msgstr ""
-msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
-
-msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgid "MetricsDashboardAnnotation|can't be before starting_at time"
msgstr ""
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
@@ -21489,6 +21707,12 @@ msgstr ""
msgid "MetricsSettings|User's local timezone"
msgstr ""
+msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
msgid "Metrics|1. Define and preview panel"
msgstr ""
@@ -21580,9 +21804,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|GitLab-managed Prometheus is deprecated and %{linkStart}scheduled for removal%{linkEnd}. Following this removal, your existing alerts will continue to function as part of the new cluster integration. However, you will no longer be able to add new alerts or edit existing alerts from the metrics dashboard."
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -21718,9 +21939,6 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
-msgid "Metrics|View runbook - %{label}"
-msgstr ""
-
msgid "Metrics|Y-axis label"
msgstr ""
@@ -22166,6 +22384,9 @@ msgstr ""
msgid "My company or team"
msgstr ""
+msgid "My topic"
+msgstr ""
+
msgid "My-Reaction"
msgstr ""
@@ -22281,6 +22502,9 @@ msgstr ""
msgid "Network"
msgstr ""
+msgid "Network:"
+msgstr ""
+
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22347,9 +22571,6 @@ msgstr ""
msgid "NetworkPolicies|Edit policy"
msgstr ""
-msgid "NetworkPolicies|Enforcement status"
-msgstr ""
-
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
@@ -22657,6 +22878,9 @@ msgstr ""
msgid "New test case"
msgstr ""
+msgid "New topic"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -22771,7 +22995,7 @@ msgstr ""
msgid "No compliance frameworks are in use. Create one from the %{link} section in Group Settings."
msgstr ""
-msgid "No confirmation email received? Please check your spam folder or"
+msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
msgstr ""
msgid "No connection could be made to a Gitaly Server, please check your logs!"
@@ -22786,6 +23010,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No credit card data for matching"
+msgstr ""
+
msgid "No credit card required."
msgstr ""
@@ -22981,6 +23208,9 @@ msgstr ""
msgid "No vulnerabilities present"
msgstr ""
+msgid "No webhook events"
+msgstr ""
+
msgid "No webhooks found, add one in the form above."
msgstr ""
@@ -23036,9 +23266,6 @@ msgstr ""
msgid "Not available for protected branches"
msgstr ""
-msgid "Not available to run jobs."
-msgstr ""
-
msgid "Not confidential"
msgstr ""
@@ -23268,18 +23495,15 @@ msgstr ""
msgid "Number of LOCs per commit"
msgstr ""
-msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
-msgstr ""
-
-msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
-msgstr ""
-
msgid "Number of commits"
msgstr ""
msgid "Number of commits per MR"
msgstr ""
+msgid "Number of employees"
+msgstr ""
+
msgid "Number of events"
msgstr ""
@@ -23331,9 +23555,6 @@ msgstr ""
msgid "OmniAuth"
msgstr ""
-msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
-msgstr ""
-
msgid "On"
msgstr ""
@@ -23535,6 +23756,9 @@ msgstr ""
msgid "OnDemandScans|My daily scan"
msgstr ""
+msgid "OnDemandScans|New DAST scan"
+msgstr ""
+
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23547,6 +23771,12 @@ msgstr ""
msgid "OnDemandScans|On-demand Scans"
msgstr ""
+msgid "OnDemandScans|On-demand scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
@@ -23559,6 +23789,9 @@ msgstr ""
msgid "OnDemandScans|Scan name"
msgstr ""
+msgid "OnDemandScans|Scan type"
+msgstr ""
+
msgid "OnDemandScans|Scanner profile"
msgstr ""
@@ -23574,6 +23807,9 @@ msgstr ""
msgid "OnDemandScans|Start time"
msgstr ""
+msgid "OnDemandScans|Target"
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23686,15 +23922,15 @@ msgstr ""
msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
-msgid "Open comment type dropdown"
-msgstr ""
-
msgid "Open epics"
msgstr ""
msgid "Open errors"
msgstr ""
+msgid "Open in Web IDE"
+msgstr ""
+
msgid "Open in file view"
msgstr ""
@@ -23743,9 +23979,6 @@ msgstr ""
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
msgstr ""
-msgid "Operations"
-msgstr ""
-
msgid "Operations Dashboard"
msgstr ""
@@ -23773,6 +24006,9 @@ msgstr ""
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
msgstr ""
+msgid "Optional."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -23782,6 +24018,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Organizations"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -23851,6 +24090,36 @@ msgstr ""
msgid "Owner"
msgstr ""
+msgid "PQL|An error occurred while sending hand raise lead."
+msgstr ""
+
+msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
+msgstr ""
+
+msgid "PQL|Cancel"
+msgstr ""
+
+msgid "PQL|Contact our Sales team"
+msgstr ""
+
+msgid "PQL|Contact sales"
+msgstr ""
+
+msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
+msgstr ""
+
+msgid "PQL|Message for the Sales team (optional)"
+msgstr ""
+
+msgid "PQL|Please select a city or state"
+msgstr ""
+
+msgid "PQL|Submit information"
+msgstr ""
+
+msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
+msgstr ""
+
msgid "Package Registry"
msgstr ""
@@ -23926,9 +24195,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates"
msgstr ""
-msgid "PackageRegistry|An error occurred while saving the settings"
-msgstr ""
-
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -24109,14 +24375,15 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
-msgid "PackageRegistry|Package file deleted successfully"
+msgid "PackageRegistry|Package deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived update"
+msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
-msgid "PackageRegistry|Package has %{number} archived updates"
-msgstr ""
+msgid "PackageRegistry|Package has %{updatesCount} archived update"
+msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
+msgstr[0] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
@@ -24160,9 +24427,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Settings saved successfully"
-msgstr ""
-
msgid "PackageRegistry|Show Composer commands"
msgstr ""
@@ -24421,6 +24685,9 @@ msgstr ""
msgid "Paths can contain wildcards, like */welcome"
msgstr ""
+msgid "Paths to protect with rate limiting"
+msgstr ""
+
msgid "Pause"
msgstr ""
@@ -24442,6 +24709,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending owner approval"
+msgstr ""
+
msgid "Pending sync…"
msgstr ""
@@ -24949,6 +25219,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There was a problem with loading the pipeline data."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -25069,6 +25342,9 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
@@ -25186,6 +25462,9 @@ msgstr ""
msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
+msgid "Plan"
+msgstr ""
+
msgid "Plan:"
msgstr ""
@@ -25288,9 +25567,15 @@ msgstr ""
msgid "Please enter or upload a valid license."
msgstr ""
+msgid "Please enter your current password."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
+msgid "Please fill in a name for your topic."
+msgstr ""
+
msgid "Please fill out this field."
msgstr ""
@@ -25435,6 +25720,9 @@ msgstr ""
msgid "Postman collection file path or URL"
msgstr ""
+msgid "Potentially unwanted character detected: Unicode BiDi Control"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -25711,12 +25999,18 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "Profile failed to delete"
+msgstr ""
+
msgid "Profile image guideline"
msgstr ""
msgid "Profile page:"
msgstr ""
+msgid "Profile parameter missing"
+msgstr ""
+
msgid "ProfileSession|on"
msgstr ""
@@ -25726,9 +26020,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|\"Busy\" will be shown next to your name"
-msgstr ""
-
msgid "Profiles|%{provider} Active"
msgstr ""
@@ -25756,6 +26047,9 @@ msgstr ""
msgid "Profiles|An error occurred while updating your username, please try again."
msgstr ""
+msgid "Profiles|An indicator appears next to your name and avatar"
+msgstr ""
+
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -26047,6 +26341,9 @@ msgstr ""
msgid "Profiles|You don't have access to delete this user."
msgstr ""
+msgid "Profiles|You must accept the Terms of Service in order to perform this action."
+msgstr ""
+
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr ""
@@ -26347,6 +26644,9 @@ msgstr ""
msgid "ProjectService|Enter new password."
msgstr ""
+msgid "ProjectService|Enter new token"
+msgstr ""
+
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26362,6 +26662,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current password."
msgstr ""
+msgid "ProjectService|Leave blank to use your current token."
+msgstr ""
+
msgid "ProjectService|Mock service URL"
msgstr ""
@@ -26545,6 +26848,9 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
+msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
+msgstr ""
+
msgid "ProjectSettings|Internal"
msgstr ""
@@ -26557,6 +26863,9 @@ msgstr ""
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
+msgid "ProjectSettings|Manage who can see the project in the public access directory."
+msgstr ""
+
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
@@ -26734,6 +27043,9 @@ msgstr ""
msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
+msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
+msgstr ""
+
msgid "ProjectSettings|What are badges?"
msgstr ""
@@ -26824,6 +27136,9 @@ msgstr ""
msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr ""
+msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
+msgstr ""
+
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
@@ -26905,6 +27220,9 @@ msgstr ""
msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
msgstr ""
+msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
+msgstr ""
+
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr ""
@@ -26932,6 +27250,9 @@ msgstr ""
msgid "ProjectsNew|Description format"
msgstr ""
+msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
+msgstr ""
+
msgid "ProjectsNew|Import"
msgstr ""
@@ -26947,6 +27268,9 @@ msgstr ""
msgid "ProjectsNew|No import options available"
msgstr ""
+msgid "ProjectsNew|Project Configuration"
+msgstr ""
+
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr ""
@@ -26962,54 +27286,9 @@ msgstr ""
msgid "Prometheus"
msgstr ""
-msgid "PrometheusAlerts|%{count} alerts applied"
-msgstr ""
-
-msgid "PrometheusAlerts|%{firingCount} firing"
-msgstr ""
-
-msgid "PrometheusAlerts|Add alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Edit alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alerts}"
-msgstr ""
-
-msgid "PrometheusAlerts|Firing: %{alert}"
-msgstr ""
-
-msgid "PrometheusAlerts|Operator"
-msgstr ""
-
-msgid "PrometheusAlerts|Runbook URL (optional)"
-msgstr ""
-
-msgid "PrometheusAlerts|Select query"
-msgstr ""
-
-msgid "PrometheusAlerts|Threshold"
-msgstr ""
-
msgid "PrometheusAlerts|exceeded"
msgstr ""
-msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
-msgstr ""
-
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -27313,9 +27592,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Paths"
-msgstr ""
-
msgid "Protected Paths: requests"
msgstr ""
@@ -27331,6 +27607,9 @@ msgstr ""
msgid "Protected environments"
msgstr ""
+msgid "Protected paths"
+msgstr ""
+
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
@@ -27469,6 +27748,9 @@ msgstr ""
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
+msgid "Provide a number our sales team can use to call you."
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -27481,6 +27763,9 @@ msgstr ""
msgid "Proxy support for this API is not available currently"
msgstr ""
+msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
+msgstr ""
+
msgid "Pseudonymizer data collection"
msgstr ""
@@ -27667,9 +27952,6 @@ msgstr ""
msgid "Query cannot be processed"
msgstr ""
-msgid "Query is valid"
-msgstr ""
-
msgid "Queued"
msgstr ""
@@ -27703,6 +27985,9 @@ msgstr ""
msgid "Rate limit"
msgstr ""
+msgid "Rate limit access to specified paths."
+msgstr ""
+
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr ""
@@ -27790,15 +28075,15 @@ msgstr ""
msgid "Recent"
msgstr ""
-msgid "Recent Deliveries"
-msgstr ""
-
msgid "Recent Project Activity"
msgstr ""
msgid "Recent Searches Service is unavailable"
msgstr ""
+msgid "Recent events"
+msgstr ""
+
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28278,6 +28563,9 @@ msgstr ""
msgid "Renew subscription"
msgstr ""
+msgid "Renews"
+msgstr ""
+
msgid "Reopen"
msgstr ""
@@ -28606,6 +28894,9 @@ msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
+msgid "Request"
+msgstr ""
+
msgid "Request Access"
msgstr ""
@@ -28615,9 +28906,6 @@ msgstr ""
msgid "Request details"
msgstr ""
-msgid "Request new confirmation email"
-msgstr ""
-
msgid "Request parameter %{param} is missing."
msgstr ""
@@ -28696,12 +28984,12 @@ msgstr ""
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
-msgid "Requires approval from %{names}."
-msgid_plural "Requires %{count} more approvals from %{names}."
+msgid "Requires %d approval from eligible users."
+msgid_plural "Requires %d approvals from eligible users."
msgstr[0] ""
-msgid "Requires approval."
-msgid_plural "Requires %d more approvals."
+msgid "Requires %{count} approval from %{names}."
+msgid_plural "Requires %{count} approvals from %{names}."
msgstr[0] ""
msgid "Requires values to meet regular expression requirements."
@@ -29045,9 +29333,6 @@ msgstr ""
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners can be:"
-msgstr ""
-
msgid "Runners currently online: %{active_runners_count}"
msgstr ""
@@ -29072,6 +29357,15 @@ msgstr ""
msgid "Runners|Are you sure you want to delete this runner?"
msgstr ""
+msgid "Runners|Associated with one or more projects"
+msgstr ""
+
+msgid "Runners|Available to all projects"
+msgstr ""
+
+msgid "Runners|Available to all projects and subgroups in the group"
+msgstr ""
+
msgid "Runners|Can run untagged jobs"
msgstr ""
@@ -29081,6 +29375,9 @@ msgstr ""
msgid "Runners|Copy instructions"
msgstr ""
+msgid "Runners|Copy registration token"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29132,6 +29429,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr ""
+
msgid "Runners|Not connected"
msgstr ""
@@ -29153,6 +29453,24 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register a group runner"
+msgstr ""
+
+msgid "Runners|Register a project runner"
+msgstr ""
+
+msgid "Runners|Register a runner"
+msgstr ""
+
+msgid "Runners|Register an instance runner"
+msgstr ""
+
+msgid "Runners|Registration token"
+msgstr ""
+
+msgid "Runners|Registration token copied!"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
@@ -29192,6 +29510,9 @@ msgstr ""
msgid "Runners|Show Runner installation instructions"
msgstr ""
+msgid "Runners|Show runner installation and registration instructions"
+msgstr ""
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr ""
@@ -29255,6 +29576,9 @@ msgstr ""
msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
msgstr ""
+msgid "Runners|You cannot assign to other projects"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -29285,15 +29609,6 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
-msgid "Runs jobs from all unassigned projects in its group."
-msgstr ""
-
-msgid "Runs jobs from all unassigned projects."
-msgstr ""
-
-msgid "Runs jobs from assigned projects."
-msgstr ""
-
msgid "SAML"
msgstr ""
@@ -29390,9 +29705,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Value Stream"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -29710,6 +30022,9 @@ msgstr[0] ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
+msgid "Seats"
+msgstr ""
+
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -29935,16 +30250,19 @@ msgstr ""
msgid "SecurityOrchestration|Description"
msgstr ""
+msgid "SecurityOrchestration|Disabled"
+msgstr ""
+
msgid "SecurityOrchestration|Edit policy"
msgstr ""
msgid "SecurityOrchestration|Edit policy project"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforcement Status"
+msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Executes a %{scanType} scan"
@@ -29995,6 +30313,9 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
+msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr ""
+
msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
msgstr ""
@@ -30013,6 +30334,9 @@ msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
+msgid "SecurityOrchestration|Status"
+msgstr ""
+
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30082,6 +30406,9 @@ msgstr ""
msgid "SecurityReports|Create issue"
msgstr ""
+msgid "SecurityReports|Create policy"
+msgstr ""
+
msgid "SecurityReports|Development vulnerabilities"
msgstr ""
@@ -30103,9 +30430,6 @@ msgstr ""
msgid "SecurityReports|Download scanned URLs"
msgstr ""
-msgid "SecurityReports|Download scanned resources"
-msgstr ""
-
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr ""
@@ -30139,6 +30463,15 @@ msgstr ""
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
+msgstr ""
+
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
@@ -30148,6 +30481,9 @@ msgstr ""
msgid "SecurityReports|Maximum selected projects limit reached"
msgstr ""
+msgid "SecurityReports|Monitor vulnerabilities across clusters"
+msgstr ""
+
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
@@ -30178,6 +30514,9 @@ msgstr ""
msgid "SecurityReports|Oops, something doesn't seem right."
msgstr ""
+msgid "SecurityReports|Operational vulnerabilities"
+msgstr ""
+
msgid "SecurityReports|Project"
msgstr ""
@@ -30301,6 +30640,9 @@ msgstr ""
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
+msgid "SecurityReports|scanned resources"
+msgstr ""
+
msgid "See example DevOps Score page in our documentation."
msgstr ""
@@ -30340,10 +30682,10 @@ msgstr ""
msgid "Select a branch"
msgstr ""
-msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "Select a framework that applies to this project. %{linkStart}How are these added?%{linkEnd}"
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
msgid "Select a group to invite"
@@ -30361,15 +30703,9 @@ msgstr ""
msgid "Select a project"
msgstr ""
-msgid "Select a project to read Insights configuration file"
-msgstr ""
-
msgid "Select a reason"
msgstr ""
-msgid "Select a repository"
-msgstr ""
-
msgid "Select a repository containing templates for common files."
msgstr ""
@@ -30628,9 +30964,6 @@ msgstr ""
msgid "Serverless"
msgstr ""
-msgid "Serverless domain"
-msgstr ""
-
msgid "Serverless platform"
msgstr ""
@@ -30730,9 +31063,6 @@ msgstr ""
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
-msgstr ""
-
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
@@ -30787,9 +31117,6 @@ msgstr ""
msgid "Set access permissions for this token."
msgstr ""
-msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -30880,9 +31207,6 @@ msgstr ""
msgid "Set up a %{type} Runner for a project"
msgstr ""
-msgid "Set up a %{type} runner manually"
-msgstr ""
-
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -30916,10 +31240,10 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "SetStatusModal|Add status emoji"
+msgid "SetStatusModal|An indicator appears next to your name and avatar"
msgstr ""
msgid "SetStatusModal|Busy"
@@ -30985,6 +31309,10 @@ msgstr ""
msgid "Setting enforced"
msgstr ""
+msgid "Setting saved successfully"
+msgid_plural "Settings saved successfully"
+msgstr[0] ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -31326,9 +31654,6 @@ msgstr ""
msgid "Simulate a pipeline created for the default branch"
msgstr ""
-msgid "Single or combined queries"
-msgstr ""
-
msgid "Site profile failed to delete"
msgstr ""
@@ -31395,6 +31720,9 @@ msgstr ""
msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippet"
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -31419,6 +31747,9 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
@@ -31428,6 +31759,9 @@ msgstr ""
msgid "Snippets|Description (optional)"
msgstr ""
+msgid "Snippets|Error with Akismet. Please check the logs for more info."
+msgstr ""
+
msgid "Snippets|Files"
msgstr ""
@@ -31452,9 +31786,6 @@ msgstr ""
msgid "Some common domains are not allowed. %{learn_more_link}."
msgstr ""
-msgid "Some of the designs you tried uploading did not change:"
-msgstr ""
-
msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
@@ -32049,12 +32380,6 @@ msgstr ""
msgid "Start thread"
msgstr ""
-msgid "Start thread & close %{noteable_name}"
-msgstr ""
-
-msgid "Start thread & reopen %{noteable_name}"
-msgstr ""
-
msgid "Start your Free Ultimate Trial"
msgstr ""
@@ -32094,6 +32419,9 @@ msgstr ""
msgid "State your message to activate"
msgstr ""
+msgid "State/Province/City"
+msgstr ""
+
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -32592,7 +32920,7 @@ msgstr ""
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
-msgid "Successfully verified domain ownership"
+msgid "Successfully updated the environment."
msgstr ""
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
@@ -32691,18 +33019,12 @@ msgstr ""
msgid "Sunday"
msgstr ""
-msgid "SuperSonics|Activate"
-msgstr ""
-
msgid "SuperSonics|Activate cloud license"
msgstr ""
msgid "SuperSonics|Activate subscription"
msgstr ""
-msgid "SuperSonics|Activated on"
-msgstr ""
-
msgid "SuperSonics|Activation code"
msgstr ""
@@ -32724,9 +33046,6 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
-msgid "SuperSonics|Expires on"
-msgstr ""
-
msgid "SuperSonics|Export license usage file"
msgstr ""
@@ -32739,12 +33058,6 @@ msgstr ""
msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
-msgid "SuperSonics|ID"
-msgstr ""
-
-msgid "SuperSonics|Last Sync"
-msgstr ""
-
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
@@ -32760,30 +33073,15 @@ msgstr ""
msgid "SuperSonics|Paste your activation code"
msgstr ""
-msgid "SuperSonics|Plan"
-msgstr ""
-
msgid "SuperSonics|Please agree to the Subscription Agreement"
msgstr ""
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
-msgid "SuperSonics|Renews"
-msgstr ""
-
-msgid "SuperSonics|Seats"
-msgstr ""
-
msgid "SuperSonics|Start free trial"
msgstr ""
-msgid "SuperSonics|Started"
-msgstr ""
-
-msgid "SuperSonics|Subscription"
-msgstr ""
-
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -32811,9 +33109,6 @@ msgstr ""
msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
msgstr ""
-msgid "SuperSonics|Type"
-msgstr ""
-
msgid "SuperSonics|Upload a license file"
msgstr ""
@@ -32826,9 +33121,6 @@ msgstr ""
msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
-msgid "SuperSonics|Valid From"
-msgstr ""
-
msgid "SuperSonics|You can learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, please %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
msgstr ""
@@ -32871,6 +33163,9 @@ msgstr ""
msgid "Survey Response"
msgstr ""
+msgid "Switch Branches"
+msgstr ""
+
msgid "Switch branch"
msgstr ""
@@ -33057,6 +33352,9 @@ msgstr ""
msgid "TagsPage|This tag has no release notes."
msgstr ""
+msgid "TagsPage|Unable to load tags"
+msgstr ""
+
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
@@ -33081,6 +33379,15 @@ msgstr ""
msgid "Task ID: %{elastic_task}"
msgstr ""
+msgid "TasksToBeDone|Create/import code into a project (repository)"
+msgstr ""
+
+msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
+msgstr ""
+
+msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
+msgstr ""
+
msgid "Team"
msgstr "團隊"
@@ -33093,6 +33400,9 @@ msgstr ""
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
msgstr ""
+msgid "Telephone number"
+msgstr ""
+
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -33461,6 +33771,9 @@ msgstr[0] ""
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
msgstr ""
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
+msgstr ""
+
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr ""
@@ -33530,6 +33843,9 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The contact does not belong to the same group as the issue."
+msgstr ""
+
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
@@ -33560,9 +33876,6 @@ msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
-msgid "The designs you tried uploading did not change."
-msgstr ""
-
msgid "The directory has been successfully created."
msgstr ""
@@ -33630,6 +33943,9 @@ msgstr ""
msgid "The form contains the following warning:"
msgstr ""
+msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -33714,6 +34030,9 @@ msgstr ""
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
msgstr ""
+msgid "The list creation wizard is already open"
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -33819,9 +34138,6 @@ msgstr ""
msgid "The project was successfully imported."
msgstr ""
-msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
-
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
@@ -33855,9 +34171,6 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr ""
-msgid "The schedule time must be in the future!"
-msgstr ""
-
msgid "The snippet can be accessed without any authentication."
msgstr ""
@@ -34017,6 +34330,9 @@ msgstr ""
msgid "There are no projects shared with this group yet"
msgstr ""
+msgid "There are no topics to show."
+msgstr ""
+
msgid "There are no variables yet."
msgstr ""
@@ -34101,6 +34417,9 @@ msgstr ""
msgid "There was a problem fetching recent projects."
msgstr ""
+msgid "There was a problem fetching releases."
+msgstr ""
+
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -34287,9 +34606,6 @@ msgstr ""
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr ""
-msgid "These paths are protected for POST requests."
-msgstr ""
-
msgid "These runners are shared across projects in this group."
msgstr ""
@@ -34512,7 +34828,7 @@ msgstr ""
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr ""
-msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
msgstr ""
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
@@ -34815,6 +35131,12 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -34953,6 +35275,9 @@ msgstr ""
msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if you don't want to limit Sidekiq jobs."
msgstr ""
+msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
+msgstr ""
+
msgid "Throughput"
msgstr ""
@@ -35282,7 +35607,7 @@ msgstr ""
msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
-msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}."
+msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -35318,7 +35643,7 @@ msgstr ""
msgid "To keep this project going, create a new merge request"
msgstr ""
-msgid "To learn more about this project, read %{link_to_wiki}."
+msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
@@ -35504,6 +35829,21 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{topic_name} was successfully created."
+msgstr ""
+
+msgid "Topic avatar"
+msgstr ""
+
+msgid "Topic name"
+msgstr ""
+
+msgid "Topic was successfully updated."
+msgstr ""
+
+msgid "Topics"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -35597,7 +35937,7 @@ msgstr ""
msgid "TransferGroup|Group is already associated to the parent group."
msgstr ""
-msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
msgstr ""
msgid "TransferGroup|Transfer failed: %{error_message}"
@@ -35964,6 +36304,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again"
msgstr ""
+msgid "Unable to fetch upstream and downstream pipelines."
+msgstr ""
+
msgid "Unable to fetch vulnerable projects"
msgstr ""
@@ -36048,6 +36391,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
+msgstr ""
+
msgid "Undo"
msgstr ""
@@ -36381,6 +36727,9 @@ msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
+msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
+msgstr ""
+
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -36399,10 +36748,10 @@ msgstr ""
msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
-msgid "UsageQuota|Git repository, managed by the Gitaly service."
+msgid "UsageQuota|Git repository."
msgstr ""
-msgid "UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items."
+msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
@@ -36414,6 +36763,9 @@ msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
+msgid "UsageQuota|LFS storage"
+msgstr ""
+
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -36459,9 +36811,6 @@ msgstr ""
msgid "UsageQuota|Storage type"
msgstr ""
-msgid "UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
-
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
msgstr ""
@@ -36501,10 +36850,10 @@ msgstr ""
msgid "UsageQuota|Usage"
msgstr ""
-msgid "UsageQuota|Usage Breakdown"
+msgid "UsageQuota|Usage Quotas"
msgstr ""
-msgid "UsageQuota|Usage Quotas"
+msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
@@ -36654,6 +37003,9 @@ msgstr ""
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
msgstr ""
+msgid "Use authorized_keys file to authenticate SSH keys"
+msgstr ""
+
msgid "Use cURL"
msgstr ""
@@ -36684,6 +37036,9 @@ msgstr ""
msgid "Use template"
msgstr ""
+msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
+msgstr ""
+
msgid "Use the link below to confirm your email address (%{email})"
msgstr ""
@@ -36750,6 +37105,12 @@ msgstr ""
msgid "User and IP rate limits"
msgstr ""
+msgid "User cap"
+msgstr ""
+
+msgid "User created at"
+msgstr ""
+
msgid "User does not have a pending request"
msgstr ""
@@ -37101,6 +37462,9 @@ msgstr ""
msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
msgstr ""
+msgid "Valid From"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -37110,6 +37474,15 @@ msgstr ""
msgid "Validate your GitLab CI configuration file"
msgstr ""
+msgid "Validated at"
+msgstr ""
+
+msgid "Validated at:"
+msgstr ""
+
+msgid "Validated:"
+msgstr ""
+
msgid "Validations failed."
msgstr ""
@@ -37155,10 +37528,22 @@ msgstr ""
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
msgstr ""
+msgid "ValueStreamAnalytics|Dashboard"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Go to docs"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
+msgstr ""
+
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
-msgid "ValueStreamAnalytics|Median time from issue first merge request created to issue closed."
+msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
msgstr ""
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
@@ -37815,6 +38200,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook events will be displayed here."
+msgstr ""
+
msgid "Webhook:"
msgstr ""
@@ -38010,6 +38398,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
+msgid "What would you like to do?"
+msgstr ""
+
msgid "What's new"
msgstr ""
@@ -38019,9 +38410,6 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
-msgstr ""
-
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38034,6 +38422,9 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
+msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -38041,9 +38432,6 @@ msgstr[0] ""
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
msgstr ""
-msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
-
msgid "When:"
msgstr ""
@@ -38350,10 +38738,10 @@ msgstr ""
msgid "Write a description or drag your files here…"
msgstr ""
-msgid "Write milestone description..."
+msgid "Write a description…"
msgstr ""
-msgid "Write to \"authorized_keys\" file"
+msgid "Write milestone description..."
msgstr ""
msgid "Write your release notes or drag your files here…"
@@ -38395,9 +38783,6 @@ msgstr ""
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
-msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
-msgstr ""
-
msgid "You are about to permanently delete this project"
msgstr ""
@@ -38464,6 +38849,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this profile"
+msgstr ""
+
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -38620,9 +39008,6 @@ msgstr ""
msgid "You can recover this project until %{date}"
msgstr ""
-msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -38722,9 +39107,6 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
-msgid "You don't have any webhooks deliveries"
-msgstr ""
-
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -38812,6 +39194,9 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
+msgid "You have unsaved changes"
+msgstr ""
+
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -38821,9 +39206,6 @@ msgstr ""
msgid "You must be logged in to search across all of GitLab"
msgstr ""
-msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
-msgstr ""
-
msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
msgstr ""
@@ -39275,28 +39657,55 @@ msgstr[0] ""
msgid "Your username is %{username}."
msgstr ""
-msgid "ZentaoIntegration|Base URL of the Zentao instance."
+msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
+msgstr ""
+
+msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
+msgstr ""
+
+msgid "ZenTaoIntegration|This is a ZenTao user."
+msgstr ""
+
+msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
+msgstr ""
+
+msgid "ZenTaoIntegration|ZenTao user"
+msgstr ""
+
+msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
msgstr ""
-msgid "ZentaoIntegration|Enter API token"
+msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr ""
+
+msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
msgid "ZentaoIntegration|If different from Web URL."
msgstr ""
-msgid "ZentaoIntegration|Use Zentao as this project's issue tracker."
+msgid "ZentaoIntegration|Issue list"
+msgstr ""
+
+msgid "ZentaoIntegration|Open ZenTao"
msgstr ""
-msgid "ZentaoIntegration|Zentao API URL (optional)"
+msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
msgstr ""
-msgid "ZentaoIntegration|Zentao API token"
+msgid "ZentaoIntegration|ZenTao API URL (optional)"
msgstr ""
-msgid "ZentaoIntegration|Zentao Product ID"
+msgid "ZentaoIntegration|ZenTao API token"
msgstr ""
-msgid "ZentaoIntegration|Zentao Web URL"
+msgid "ZentaoIntegration|ZenTao Product ID"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao Web URL"
+msgstr ""
+
+msgid "ZentaoIntegration|ZenTao issues"
msgstr ""
msgid "Zoom meeting added"
@@ -39308,6 +39717,9 @@ msgstr ""
msgid "[No reason]"
msgstr ""
+msgid "[REDACTED]"
+msgstr ""
+
msgid "[Redacted]"
msgstr ""
@@ -39320,9 +39732,6 @@ msgstr ""
msgid "a deleted user"
msgstr ""
-msgid "a design"
-msgstr ""
-
msgid "about 1 hour"
msgid_plural "about %d hours"
msgstr[0] ""
@@ -39427,12 +39836,18 @@ msgstr ""
msgid "can only have one escalation policy"
msgstr ""
+msgid "can't be nil"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
+msgid "can't reference a branch that does not exist"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -39460,6 +39875,9 @@ msgstr ""
msgid "cannot be modified"
msgstr ""
+msgid "cannot be used for user namespace"
+msgstr ""
+
msgid "cannot block others"
msgstr ""
@@ -39475,9 +39893,6 @@ msgstr ""
msgid "cannot merge"
msgstr ""
-msgid "cannot not be used for user namespace"
-msgstr ""
-
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -39508,6 +39923,9 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
+msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgstr ""
+
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
@@ -39544,9 +39962,19 @@ msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
msgstr ""
+msgid "ciReport|Browser Performance"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Browser performance test metrics: "
msgstr ""
+msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
@@ -39556,7 +39984,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|Code quality degraded"
+msgstr ""
+
+msgid "ciReport|Code quality improved"
+msgstr ""
+
+msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"
@@ -39622,6 +40056,16 @@ msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
+msgid "ciReport|Load Performance"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgstr[0] ""
+
+msgid "ciReport|Load performance test metrics results are being parsed"
+msgstr ""
+
msgid "ciReport|Load performance test metrics: "
msgstr ""
@@ -39655,10 +40099,10 @@ msgstr ""
msgid "ciReport|Secret Detection"
msgstr ""
-msgid "ciReport|Secret scanning"
+msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
msgstr ""
-msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgid "ciReport|Secret detection"
msgstr ""
msgid "ciReport|Security scanning"
@@ -39776,6 +40220,12 @@ msgstr ""
msgid "container_name cannot be larger than %{max_length} chars"
msgstr ""
+msgid "contains URLs that exceed the 1024 character limit (%{urls})"
+msgstr ""
+
+msgid "contains invalid URLs (%{urls})"
+msgstr ""
+
msgid "contribute to this project."
msgstr ""
@@ -39831,9 +40281,6 @@ msgstr ""
msgid "design"
msgstr ""
-msgid "designs"
-msgstr ""
-
msgid "detached"
msgstr ""
@@ -39846,6 +40293,12 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr ""
+msgid "does not match dast_site.project"
+msgstr ""
+
+msgid "does not match dast_site_validation.project"
+msgstr ""
+
msgid "download it"
msgstr ""
@@ -39859,6 +40312,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
+msgid "eligible users"
+msgstr ""
+
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -39895,6 +40351,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds the %{max_value_length} character limit"
+msgstr ""
+
msgid "exceeds the limit of %{bytes} bytes"
msgstr ""
@@ -40090,6 +40549,12 @@ msgstr ""
msgid "is not in the group enforcing Group Managed Account"
msgstr ""
+msgid "is not in the member group"
+msgstr ""
+
+msgid "is not the member project"
+msgstr ""
+
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40247,6 +40712,9 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
+msgstr ""
+
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr ""
@@ -40280,6 +40748,12 @@ msgstr ""
msgid "mrWidget|Approved by"
msgstr ""
+msgid "mrWidget|Approved by you"
+msgstr ""
+
+msgid "mrWidget|Approved by you and others"
+msgstr ""
+
msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr ""
@@ -40341,6 +40815,9 @@ msgstr ""
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
+msgid "mrWidget|Learn more"
+msgstr ""
+
msgid "mrWidget|Loading deployment statistics"
msgstr ""
@@ -40372,9 +40849,6 @@ msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
-msgid "mrWidget|Merge request approved."
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -40489,12 +40963,6 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
-msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -40510,6 +40978,9 @@ msgstr ""
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
msgstr ""
+msgid "mrWidget|What is a merge train?"
+msgstr ""
+
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
@@ -40558,6 +41029,12 @@ msgstr ""
msgid "must be unique by status and elapsed time within a policy"
msgstr ""
+msgid "must have a repository"
+msgstr ""
+
+msgid "must match %{association}.project_id"
+msgstr ""
+
msgid "my-awesome-group"
msgstr ""
@@ -40633,6 +41110,9 @@ msgstr ""
msgid "originating vulnerability"
msgstr ""
+msgid "other card matches"
+msgstr ""
+
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/package.json b/package.json
index b8ad3a5e84b..943a176ce75 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
"dev-server": "NODE_OPTIONS=\"--max-old-space-size=3584\" node scripts/frontend/webpack_dev_server.js",
"file-coverage": "scripts/frontend/file_test_coverage.js",
"lint-docs": "scripts/lint-doc.sh",
- "internal:eslint": "eslint --cache --max-warnings 0 --report-unused-disable-directives --ext .js,.vue",
+ "internal:eslint": "eslint --cache --max-warnings 0 --report-unused-disable-directives --ext .js,.vue,.graphql",
"internal:stylelint": "stylelint -q '{ee/,}app/assets/stylesheets/**/*.{css,scss}'",
"prejest": "yarn check-dependencies",
"jest": "jest --config jest.config.js",
@@ -55,44 +55,44 @@
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
- "@gitlab/svgs": "1.218.0",
+ "@gitlab/svgs": "1.220.0",
"@gitlab/tributejs": "1.0.0",
- "@gitlab/ui": "32.19.1",
+ "@gitlab/ui": "32.36.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "6.1.4-1",
"@rails/ujs": "6.1.4-1",
"@sentry/browser": "5.30.0",
"@sourcegraph/code-host-integration": "0.0.60",
- "@tiptap/core": "^2.0.0-beta.118",
- "@tiptap/extension-blockquote": "^2.0.0-beta.15",
- "@tiptap/extension-bold": "^2.0.0-beta.15",
- "@tiptap/extension-bullet-list": "^2.0.0-beta.15",
- "@tiptap/extension-code": "^2.0.0-beta.16",
- "@tiptap/extension-code-block-lowlight": "2.0.0-beta.41",
+ "@tiptap/core": "^2.0.0-beta.125",
+ "@tiptap/extension-blockquote": "^2.0.0-beta.19",
+ "@tiptap/extension-bold": "^2.0.0-beta.19",
+ "@tiptap/extension-bullet-list": "^2.0.0-beta.18",
+ "@tiptap/extension-code": "^2.0.0-beta.20",
+ "@tiptap/extension-code-block-lowlight": "2.0.0-beta.47",
"@tiptap/extension-document": "^2.0.0-beta.13",
"@tiptap/extension-dropcursor": "^2.0.0-beta.19",
- "@tiptap/extension-gapcursor": "^2.0.0-beta.24",
- "@tiptap/extension-hard-break": "^2.0.0-beta.21",
- "@tiptap/extension-heading": "^2.0.0-beta.15",
+ "@tiptap/extension-gapcursor": "^2.0.0-beta.27",
+ "@tiptap/extension-hard-break": "^2.0.0-beta.24",
+ "@tiptap/extension-heading": "^2.0.0-beta.18",
"@tiptap/extension-history": "^2.0.0-beta.16",
- "@tiptap/extension-horizontal-rule": "^2.0.0-beta.21",
- "@tiptap/extension-image": "^2.0.0-beta.15",
- "@tiptap/extension-italic": "^2.0.0-beta.15",
- "@tiptap/extension-link": "^2.0.0-beta.20",
+ "@tiptap/extension-horizontal-rule": "^2.0.0-beta.24",
+ "@tiptap/extension-image": "^2.0.0-beta.19",
+ "@tiptap/extension-italic": "^2.0.0-beta.19",
+ "@tiptap/extension-link": "^2.0.0-beta.23",
"@tiptap/extension-list-item": "^2.0.0-beta.14",
- "@tiptap/extension-ordered-list": "^2.0.0-beta.16",
+ "@tiptap/extension-ordered-list": "^2.0.0-beta.19",
"@tiptap/extension-paragraph": "^2.0.0-beta.17",
- "@tiptap/extension-strike": "^2.0.0-beta.17",
+ "@tiptap/extension-strike": "^2.0.0-beta.21",
"@tiptap/extension-subscript": "^2.0.0-beta.4",
"@tiptap/extension-superscript": "^2.0.0-beta.4",
- "@tiptap/extension-table": "^2.0.0-beta.31",
+ "@tiptap/extension-table": "^2.0.0-beta.34",
"@tiptap/extension-table-cell": "^2.0.0-beta.15",
"@tiptap/extension-table-header": "^2.0.0-beta.17",
"@tiptap/extension-table-row": "^2.0.0-beta.14",
- "@tiptap/extension-task-item": "^2.0.0-beta.18",
- "@tiptap/extension-task-list": "^2.0.0-beta.17",
+ "@tiptap/extension-task-item": "^2.0.0-beta.21",
+ "@tiptap/extension-task-list": "^2.0.0-beta.18",
"@tiptap/extension-text": "^2.0.0-beta.13",
- "@tiptap/vue-2": "^2.0.0-beta.57",
+ "@tiptap/vue-2": "^2.0.0-beta.60",
"@toast-ui/editor": "^2.5.2",
"@toast-ui/vue-editor": "^2.5.2",
"apollo-cache-inmemory": "^1.6.6",
@@ -102,13 +102,14 @@
"apollo-link-error": "^1.1.13",
"apollo-link-http": "^1.5.17",
"apollo-upload-client": "^13.0.0",
- "autosize": "^4.0.2",
+ "autosize": "^5.0.1",
"aws-sdk": "^2.637.0",
- "axios": "^0.20.0",
+ "axios": "^0.24.0",
"babel-loader": "^8.2.2",
"babel-plugin-lodash": "^3.3.4",
"bootstrap": "4.5.3",
"cache-loader": "^4.1.0",
+ "canvas-confetti": "^1.4.0",
"clipboard": "^1.7.1",
"codemirror": "^5.48.4",
"codesandbox-api": "0.0.23",
@@ -128,7 +129,6 @@
"dropzone": "^4.2.0",
"editorconfig": "^0.15.3",
"emoji-regex": "^7.0.3",
- "emoji-unicode-version": "^0.2.1",
"fast-mersenne-twister": "1.0.2",
"file-loader": "^6.2.0",
"fuzzaldrin-plus": "^0.6.0",
@@ -160,12 +160,11 @@
"popper.js": "^1.16.1",
"portal-vue": "^2.1.7",
"prismjs": "^1.21.0",
- "prosemirror-inputrules": "^1.1.3",
"prosemirror-markdown": "^1.6.0",
"prosemirror-model": "^1.14.3",
"prosemirror-state": "^1.3.4",
"prosemirror-tables": "^1.1.1",
- "prosemirror-view": "^1.20.2",
+ "prosemirror-view": "^1.20.3",
"raphael": "^2.2.7",
"raw-loader": "^4.0.2",
"scrollparent": "^2.0.1",
@@ -201,12 +200,14 @@
"webpack-cli": "^3.3.12",
"webpack-stats-plugin": "^0.3.1",
"worker-loader": "^2.0.0",
- "xterm": "3.14.5"
+ "xterm": "3.14.5",
+ "yaml": "^2.0.0-8"
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
- "@gitlab/eslint-plugin": "9.4.0",
- "@gitlab/stylelint-config": "2.3.0",
+ "@gitlab/eslint-plugin": "10.0.0",
+ "@gitlab/stylelint-config": "2.6.0",
+ "@graphql-eslint/eslint-plugin": "2.3.0",
"@testing-library/dom": "^7.16.2",
"@vue/test-utils": "1.2.0",
"acorn": "^6.3.0",
@@ -221,8 +222,8 @@
"docdash": "^1.0.2",
"eslint": "7.32.0",
"eslint-import-resolver-jest": "3.0.2",
- "eslint-import-resolver-webpack": "0.13.1",
- "eslint-plugin-no-jquery": "2.6.0",
+ "eslint-import-resolver-webpack": "0.13.2",
+ "eslint-plugin-no-jquery": "2.7.0",
"gettext-extractor": "^3.5.3",
"gettext-extractor-vue": "^5.0.0",
"glob": "^7.1.6",
@@ -247,7 +248,7 @@
"prettier": "2.2.1",
"prosemirror-schema-basic": "^1.1.2",
"prosemirror-schema-list": "^1.1.6",
- "prosemirror-test-builder": "^1.0.4",
+ "prosemirror-test-builder": "^1.0.5",
"purgecss": "^4.0.3",
"purgecss-from-html": "^4.0.3",
"readdir-enhanced": "^2.2.4",
@@ -263,7 +264,8 @@
"bootstrap-vue": "https://docs.gitlab.com/ee/development/fe_guide/dependencies.html#bootstrapvue"
},
"resolutions": {
- "chokidar": "^3.4.0"
+ "chokidar": "^3.4.0",
+ "@types/node": "14.17.5"
},
"engines": {
"node": ">=12.22.1",
diff --git a/public/-/emojis/1/emojis.json b/public/-/emojis/1/emojis.json
index 20a564720d1..8cc7cd7479a 100644
--- a/public/-/emojis/1/emojis.json
+++ b/public/-/emojis/1/emojis.json
@@ -10757,4 +10757,4 @@
"d": "sleeping symbol",
"u": "6.0"
}
-} \ No newline at end of file
+}
diff --git a/public/-/emojis/2/100.png b/public/-/emojis/2/100.png
new file mode 100644
index 00000000000..3501136c22d
--- /dev/null
+++ b/public/-/emojis/2/100.png
Binary files differ
diff --git a/public/-/emojis/2/1234.png b/public/-/emojis/2/1234.png
new file mode 100644
index 00000000000..8ce28681ebc
--- /dev/null
+++ b/public/-/emojis/2/1234.png
Binary files differ
diff --git a/public/-/emojis/2/8ball.png b/public/-/emojis/2/8ball.png
new file mode 100644
index 00000000000..48207741211
--- /dev/null
+++ b/public/-/emojis/2/8ball.png
Binary files differ
diff --git a/public/-/emojis/2/a.png b/public/-/emojis/2/a.png
new file mode 100644
index 00000000000..6c4875bce2f
--- /dev/null
+++ b/public/-/emojis/2/a.png
Binary files differ
diff --git a/public/-/emojis/2/ab.png b/public/-/emojis/2/ab.png
new file mode 100644
index 00000000000..40c566e63eb
--- /dev/null
+++ b/public/-/emojis/2/ab.png
Binary files differ
diff --git a/public/-/emojis/2/abc.png b/public/-/emojis/2/abc.png
new file mode 100644
index 00000000000..c9a0764b9d6
--- /dev/null
+++ b/public/-/emojis/2/abc.png
Binary files differ
diff --git a/public/-/emojis/2/abcd.png b/public/-/emojis/2/abcd.png
new file mode 100644
index 00000000000..e22fcb79e5a
--- /dev/null
+++ b/public/-/emojis/2/abcd.png
Binary files differ
diff --git a/public/-/emojis/2/accept.png b/public/-/emojis/2/accept.png
new file mode 100644
index 00000000000..0348dded3d8
--- /dev/null
+++ b/public/-/emojis/2/accept.png
Binary files differ
diff --git a/public/-/emojis/2/aerial_tramway.png b/public/-/emojis/2/aerial_tramway.png
new file mode 100644
index 00000000000..ec1cf64f019
--- /dev/null
+++ b/public/-/emojis/2/aerial_tramway.png
Binary files differ
diff --git a/public/-/emojis/2/airplane.png b/public/-/emojis/2/airplane.png
new file mode 100644
index 00000000000..ba6dda4fae3
--- /dev/null
+++ b/public/-/emojis/2/airplane.png
Binary files differ
diff --git a/public/-/emojis/2/airplane_arriving.png b/public/-/emojis/2/airplane_arriving.png
new file mode 100644
index 00000000000..cc83ea662d3
--- /dev/null
+++ b/public/-/emojis/2/airplane_arriving.png
Binary files differ
diff --git a/public/-/emojis/2/airplane_departure.png b/public/-/emojis/2/airplane_departure.png
new file mode 100644
index 00000000000..d72e051c383
--- /dev/null
+++ b/public/-/emojis/2/airplane_departure.png
Binary files differ
diff --git a/public/-/emojis/2/airplane_small.png b/public/-/emojis/2/airplane_small.png
new file mode 100644
index 00000000000..1dc72e20096
--- /dev/null
+++ b/public/-/emojis/2/airplane_small.png
Binary files differ
diff --git a/public/-/emojis/2/alarm_clock.png b/public/-/emojis/2/alarm_clock.png
new file mode 100644
index 00000000000..0509bb4226c
--- /dev/null
+++ b/public/-/emojis/2/alarm_clock.png
Binary files differ
diff --git a/public/-/emojis/2/alembic.png b/public/-/emojis/2/alembic.png
new file mode 100644
index 00000000000..56801316030
--- /dev/null
+++ b/public/-/emojis/2/alembic.png
Binary files differ
diff --git a/public/-/emojis/2/alien.png b/public/-/emojis/2/alien.png
new file mode 100644
index 00000000000..f22de392f55
--- /dev/null
+++ b/public/-/emojis/2/alien.png
Binary files differ
diff --git a/public/-/emojis/2/ambulance.png b/public/-/emojis/2/ambulance.png
new file mode 100644
index 00000000000..fa27a6298b9
--- /dev/null
+++ b/public/-/emojis/2/ambulance.png
Binary files differ
diff --git a/public/-/emojis/2/amphora.png b/public/-/emojis/2/amphora.png
new file mode 100644
index 00000000000..fb0c91f90b3
--- /dev/null
+++ b/public/-/emojis/2/amphora.png
Binary files differ
diff --git a/public/-/emojis/2/anchor.png b/public/-/emojis/2/anchor.png
new file mode 100644
index 00000000000..87123bfda86
--- /dev/null
+++ b/public/-/emojis/2/anchor.png
Binary files differ
diff --git a/public/-/emojis/2/angel.png b/public/-/emojis/2/angel.png
new file mode 100644
index 00000000000..172bab3a431
--- /dev/null
+++ b/public/-/emojis/2/angel.png
Binary files differ
diff --git a/public/-/emojis/2/angel_tone1.png b/public/-/emojis/2/angel_tone1.png
new file mode 100644
index 00000000000..e158cf2577d
--- /dev/null
+++ b/public/-/emojis/2/angel_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/angel_tone2.png b/public/-/emojis/2/angel_tone2.png
new file mode 100644
index 00000000000..4f034d25d47
--- /dev/null
+++ b/public/-/emojis/2/angel_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/angel_tone3.png b/public/-/emojis/2/angel_tone3.png
new file mode 100644
index 00000000000..a5cc52bd6cc
--- /dev/null
+++ b/public/-/emojis/2/angel_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/angel_tone4.png b/public/-/emojis/2/angel_tone4.png
new file mode 100644
index 00000000000..fe7f467844e
--- /dev/null
+++ b/public/-/emojis/2/angel_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/angel_tone5.png b/public/-/emojis/2/angel_tone5.png
new file mode 100644
index 00000000000..8b3c0affb91
--- /dev/null
+++ b/public/-/emojis/2/angel_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/anger.png b/public/-/emojis/2/anger.png
new file mode 100644
index 00000000000..b0466432996
--- /dev/null
+++ b/public/-/emojis/2/anger.png
Binary files differ
diff --git a/public/-/emojis/2/anger_right.png b/public/-/emojis/2/anger_right.png
new file mode 100644
index 00000000000..f79728df54d
--- /dev/null
+++ b/public/-/emojis/2/anger_right.png
Binary files differ
diff --git a/public/-/emojis/2/angry.png b/public/-/emojis/2/angry.png
new file mode 100644
index 00000000000..6004c26ecaf
--- /dev/null
+++ b/public/-/emojis/2/angry.png
Binary files differ
diff --git a/public/-/emojis/2/anguished.png b/public/-/emojis/2/anguished.png
new file mode 100644
index 00000000000..a19ec81e6e5
--- /dev/null
+++ b/public/-/emojis/2/anguished.png
Binary files differ
diff --git a/public/-/emojis/2/ant.png b/public/-/emojis/2/ant.png
new file mode 100644
index 00000000000..74dc0dc8464
--- /dev/null
+++ b/public/-/emojis/2/ant.png
Binary files differ
diff --git a/public/-/emojis/2/apple.png b/public/-/emojis/2/apple.png
new file mode 100644
index 00000000000..4b985bde351
--- /dev/null
+++ b/public/-/emojis/2/apple.png
Binary files differ
diff --git a/public/-/emojis/2/aquarius.png b/public/-/emojis/2/aquarius.png
new file mode 100644
index 00000000000..ea054a8a9e7
--- /dev/null
+++ b/public/-/emojis/2/aquarius.png
Binary files differ
diff --git a/public/-/emojis/2/aries.png b/public/-/emojis/2/aries.png
new file mode 100644
index 00000000000..8b6c08a7552
--- /dev/null
+++ b/public/-/emojis/2/aries.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_backward.png b/public/-/emojis/2/arrow_backward.png
new file mode 100644
index 00000000000..6843100777b
--- /dev/null
+++ b/public/-/emojis/2/arrow_backward.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_double_down.png b/public/-/emojis/2/arrow_double_down.png
new file mode 100644
index 00000000000..d9d05a7bbc7
--- /dev/null
+++ b/public/-/emojis/2/arrow_double_down.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_double_up.png b/public/-/emojis/2/arrow_double_up.png
new file mode 100644
index 00000000000..c351d36485d
--- /dev/null
+++ b/public/-/emojis/2/arrow_double_up.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_down.png b/public/-/emojis/2/arrow_down.png
new file mode 100644
index 00000000000..68a4aea4def
--- /dev/null
+++ b/public/-/emojis/2/arrow_down.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_down_small.png b/public/-/emojis/2/arrow_down_small.png
new file mode 100644
index 00000000000..2c0cf94e73d
--- /dev/null
+++ b/public/-/emojis/2/arrow_down_small.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_forward.png b/public/-/emojis/2/arrow_forward.png
new file mode 100644
index 00000000000..fa4e5e37673
--- /dev/null
+++ b/public/-/emojis/2/arrow_forward.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_heading_down.png b/public/-/emojis/2/arrow_heading_down.png
new file mode 100644
index 00000000000..59717864566
--- /dev/null
+++ b/public/-/emojis/2/arrow_heading_down.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_heading_up.png b/public/-/emojis/2/arrow_heading_up.png
new file mode 100644
index 00000000000..6961a4b3f9c
--- /dev/null
+++ b/public/-/emojis/2/arrow_heading_up.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_left.png b/public/-/emojis/2/arrow_left.png
new file mode 100644
index 00000000000..4fab1e0a87c
--- /dev/null
+++ b/public/-/emojis/2/arrow_left.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_lower_left.png b/public/-/emojis/2/arrow_lower_left.png
new file mode 100644
index 00000000000..7ac710061c7
--- /dev/null
+++ b/public/-/emojis/2/arrow_lower_left.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_lower_right.png b/public/-/emojis/2/arrow_lower_right.png
new file mode 100644
index 00000000000..61dae63f729
--- /dev/null
+++ b/public/-/emojis/2/arrow_lower_right.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_right.png b/public/-/emojis/2/arrow_right.png
new file mode 100644
index 00000000000..778a3575616
--- /dev/null
+++ b/public/-/emojis/2/arrow_right.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_right_hook.png b/public/-/emojis/2/arrow_right_hook.png
new file mode 100644
index 00000000000..bd34a4f5d0f
--- /dev/null
+++ b/public/-/emojis/2/arrow_right_hook.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_up.png b/public/-/emojis/2/arrow_up.png
new file mode 100644
index 00000000000..699e54e296d
--- /dev/null
+++ b/public/-/emojis/2/arrow_up.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_up_down.png b/public/-/emojis/2/arrow_up_down.png
new file mode 100644
index 00000000000..cf355615344
--- /dev/null
+++ b/public/-/emojis/2/arrow_up_down.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_up_small.png b/public/-/emojis/2/arrow_up_small.png
new file mode 100644
index 00000000000..1f0d4e2ee1b
--- /dev/null
+++ b/public/-/emojis/2/arrow_up_small.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_upper_left.png b/public/-/emojis/2/arrow_upper_left.png
new file mode 100644
index 00000000000..4fefca9d4ff
--- /dev/null
+++ b/public/-/emojis/2/arrow_upper_left.png
Binary files differ
diff --git a/public/-/emojis/2/arrow_upper_right.png b/public/-/emojis/2/arrow_upper_right.png
new file mode 100644
index 00000000000..c1439f52943
--- /dev/null
+++ b/public/-/emojis/2/arrow_upper_right.png
Binary files differ
diff --git a/public/-/emojis/2/arrows_clockwise.png b/public/-/emojis/2/arrows_clockwise.png
new file mode 100644
index 00000000000..12bc8184d65
--- /dev/null
+++ b/public/-/emojis/2/arrows_clockwise.png
Binary files differ
diff --git a/public/-/emojis/2/arrows_counterclockwise.png b/public/-/emojis/2/arrows_counterclockwise.png
new file mode 100644
index 00000000000..2a65f636b2b
--- /dev/null
+++ b/public/-/emojis/2/arrows_counterclockwise.png
Binary files differ
diff --git a/public/-/emojis/2/art.png b/public/-/emojis/2/art.png
new file mode 100644
index 00000000000..170e1b2ff97
--- /dev/null
+++ b/public/-/emojis/2/art.png
Binary files differ
diff --git a/public/-/emojis/2/articulated_lorry.png b/public/-/emojis/2/articulated_lorry.png
new file mode 100644
index 00000000000..3a0f4daa029
--- /dev/null
+++ b/public/-/emojis/2/articulated_lorry.png
Binary files differ
diff --git a/public/-/emojis/2/asterisk.png b/public/-/emojis/2/asterisk.png
new file mode 100644
index 00000000000..2f379e50373
--- /dev/null
+++ b/public/-/emojis/2/asterisk.png
Binary files differ
diff --git a/public/-/emojis/2/astonished.png b/public/-/emojis/2/astonished.png
new file mode 100644
index 00000000000..1755a8e51b1
--- /dev/null
+++ b/public/-/emojis/2/astonished.png
Binary files differ
diff --git a/public/-/emojis/2/athletic_shoe.png b/public/-/emojis/2/athletic_shoe.png
new file mode 100644
index 00000000000..3fd62e6d275
--- /dev/null
+++ b/public/-/emojis/2/athletic_shoe.png
Binary files differ
diff --git a/public/-/emojis/2/atm.png b/public/-/emojis/2/atm.png
new file mode 100644
index 00000000000..241d8d13e89
--- /dev/null
+++ b/public/-/emojis/2/atm.png
Binary files differ
diff --git a/public/-/emojis/2/atom.png b/public/-/emojis/2/atom.png
new file mode 100644
index 00000000000..5905490208f
--- /dev/null
+++ b/public/-/emojis/2/atom.png
Binary files differ
diff --git a/public/-/emojis/2/avocado.png b/public/-/emojis/2/avocado.png
new file mode 100644
index 00000000000..9649361f901
--- /dev/null
+++ b/public/-/emojis/2/avocado.png
Binary files differ
diff --git a/public/-/emojis/2/b.png b/public/-/emojis/2/b.png
new file mode 100644
index 00000000000..d72ba8aecf8
--- /dev/null
+++ b/public/-/emojis/2/b.png
Binary files differ
diff --git a/public/-/emojis/2/baby.png b/public/-/emojis/2/baby.png
new file mode 100644
index 00000000000..65ec5c9e920
--- /dev/null
+++ b/public/-/emojis/2/baby.png
Binary files differ
diff --git a/public/-/emojis/2/baby_bottle.png b/public/-/emojis/2/baby_bottle.png
new file mode 100644
index 00000000000..71fa119f5bb
--- /dev/null
+++ b/public/-/emojis/2/baby_bottle.png
Binary files differ
diff --git a/public/-/emojis/2/baby_chick.png b/public/-/emojis/2/baby_chick.png
new file mode 100644
index 00000000000..6a59d81132d
--- /dev/null
+++ b/public/-/emojis/2/baby_chick.png
Binary files differ
diff --git a/public/-/emojis/2/baby_symbol.png b/public/-/emojis/2/baby_symbol.png
new file mode 100644
index 00000000000..e031a83c006
--- /dev/null
+++ b/public/-/emojis/2/baby_symbol.png
Binary files differ
diff --git a/public/-/emojis/2/baby_tone1.png b/public/-/emojis/2/baby_tone1.png
new file mode 100644
index 00000000000..b1b44d162a2
--- /dev/null
+++ b/public/-/emojis/2/baby_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/baby_tone2.png b/public/-/emojis/2/baby_tone2.png
new file mode 100644
index 00000000000..f886dfdd55b
--- /dev/null
+++ b/public/-/emojis/2/baby_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/baby_tone3.png b/public/-/emojis/2/baby_tone3.png
new file mode 100644
index 00000000000..dceede5f0b2
--- /dev/null
+++ b/public/-/emojis/2/baby_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/baby_tone4.png b/public/-/emojis/2/baby_tone4.png
new file mode 100644
index 00000000000..76855978285
--- /dev/null
+++ b/public/-/emojis/2/baby_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/baby_tone5.png b/public/-/emojis/2/baby_tone5.png
new file mode 100644
index 00000000000..9b7a8f3bc04
--- /dev/null
+++ b/public/-/emojis/2/baby_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/back.png b/public/-/emojis/2/back.png
new file mode 100644
index 00000000000..b284d7d9d21
--- /dev/null
+++ b/public/-/emojis/2/back.png
Binary files differ
diff --git a/public/-/emojis/2/bacon.png b/public/-/emojis/2/bacon.png
new file mode 100644
index 00000000000..c3fc3f71ec9
--- /dev/null
+++ b/public/-/emojis/2/bacon.png
Binary files differ
diff --git a/public/-/emojis/2/badminton.png b/public/-/emojis/2/badminton.png
new file mode 100644
index 00000000000..60cdd61a0b0
--- /dev/null
+++ b/public/-/emojis/2/badminton.png
Binary files differ
diff --git a/public/-/emojis/2/baggage_claim.png b/public/-/emojis/2/baggage_claim.png
new file mode 100644
index 00000000000..86138e53281
--- /dev/null
+++ b/public/-/emojis/2/baggage_claim.png
Binary files differ
diff --git a/public/-/emojis/2/balloon.png b/public/-/emojis/2/balloon.png
new file mode 100644
index 00000000000..6baaa25d595
--- /dev/null
+++ b/public/-/emojis/2/balloon.png
Binary files differ
diff --git a/public/-/emojis/2/ballot_box.png b/public/-/emojis/2/ballot_box.png
new file mode 100644
index 00000000000..296a69bea76
--- /dev/null
+++ b/public/-/emojis/2/ballot_box.png
Binary files differ
diff --git a/public/-/emojis/2/ballot_box_with_check.png b/public/-/emojis/2/ballot_box_with_check.png
new file mode 100644
index 00000000000..cd2cfc0c3bf
--- /dev/null
+++ b/public/-/emojis/2/ballot_box_with_check.png
Binary files differ
diff --git a/public/-/emojis/2/bamboo.png b/public/-/emojis/2/bamboo.png
new file mode 100644
index 00000000000..0a49e68d188
--- /dev/null
+++ b/public/-/emojis/2/bamboo.png
Binary files differ
diff --git a/public/-/emojis/2/banana.png b/public/-/emojis/2/banana.png
new file mode 100644
index 00000000000..1ba957e89b6
--- /dev/null
+++ b/public/-/emojis/2/banana.png
Binary files differ
diff --git a/public/-/emojis/2/bangbang.png b/public/-/emojis/2/bangbang.png
new file mode 100644
index 00000000000..005e832fd16
--- /dev/null
+++ b/public/-/emojis/2/bangbang.png
Binary files differ
diff --git a/public/-/emojis/2/bank.png b/public/-/emojis/2/bank.png
new file mode 100644
index 00000000000..9e056f23ca6
--- /dev/null
+++ b/public/-/emojis/2/bank.png
Binary files differ
diff --git a/public/-/emojis/2/bar_chart.png b/public/-/emojis/2/bar_chart.png
new file mode 100644
index 00000000000..9f2638751f0
--- /dev/null
+++ b/public/-/emojis/2/bar_chart.png
Binary files differ
diff --git a/public/-/emojis/2/barber.png b/public/-/emojis/2/barber.png
new file mode 100644
index 00000000000..2bbc3511668
--- /dev/null
+++ b/public/-/emojis/2/barber.png
Binary files differ
diff --git a/public/-/emojis/2/baseball.png b/public/-/emojis/2/baseball.png
new file mode 100644
index 00000000000..a5c0d615728
--- /dev/null
+++ b/public/-/emojis/2/baseball.png
Binary files differ
diff --git a/public/-/emojis/2/basketball.png b/public/-/emojis/2/basketball.png
new file mode 100644
index 00000000000..b91e88f87d4
--- /dev/null
+++ b/public/-/emojis/2/basketball.png
Binary files differ
diff --git a/public/-/emojis/2/basketball_player.png b/public/-/emojis/2/basketball_player.png
new file mode 100644
index 00000000000..8fabefd1d22
--- /dev/null
+++ b/public/-/emojis/2/basketball_player.png
Binary files differ
diff --git a/public/-/emojis/2/basketball_player_tone1.png b/public/-/emojis/2/basketball_player_tone1.png
new file mode 100644
index 00000000000..870f251e92d
--- /dev/null
+++ b/public/-/emojis/2/basketball_player_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/basketball_player_tone2.png b/public/-/emojis/2/basketball_player_tone2.png
new file mode 100644
index 00000000000..644cb8ce6f2
--- /dev/null
+++ b/public/-/emojis/2/basketball_player_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/basketball_player_tone3.png b/public/-/emojis/2/basketball_player_tone3.png
new file mode 100644
index 00000000000..913e7089c7a
--- /dev/null
+++ b/public/-/emojis/2/basketball_player_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/basketball_player_tone4.png b/public/-/emojis/2/basketball_player_tone4.png
new file mode 100644
index 00000000000..330790f88ea
--- /dev/null
+++ b/public/-/emojis/2/basketball_player_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/basketball_player_tone5.png b/public/-/emojis/2/basketball_player_tone5.png
new file mode 100644
index 00000000000..ff79e0bd2e6
--- /dev/null
+++ b/public/-/emojis/2/basketball_player_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/bat.png b/public/-/emojis/2/bat.png
new file mode 100644
index 00000000000..e63cc1cac1f
--- /dev/null
+++ b/public/-/emojis/2/bat.png
Binary files differ
diff --git a/public/-/emojis/2/bath.png b/public/-/emojis/2/bath.png
new file mode 100644
index 00000000000..a3bfe7f1cf9
--- /dev/null
+++ b/public/-/emojis/2/bath.png
Binary files differ
diff --git a/public/-/emojis/2/bath_tone1.png b/public/-/emojis/2/bath_tone1.png
new file mode 100644
index 00000000000..595211ac853
--- /dev/null
+++ b/public/-/emojis/2/bath_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/bath_tone2.png b/public/-/emojis/2/bath_tone2.png
new file mode 100644
index 00000000000..f9441853388
--- /dev/null
+++ b/public/-/emojis/2/bath_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/bath_tone3.png b/public/-/emojis/2/bath_tone3.png
new file mode 100644
index 00000000000..eb70bfc776d
--- /dev/null
+++ b/public/-/emojis/2/bath_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/bath_tone4.png b/public/-/emojis/2/bath_tone4.png
new file mode 100644
index 00000000000..09f6deccbca
--- /dev/null
+++ b/public/-/emojis/2/bath_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/bath_tone5.png b/public/-/emojis/2/bath_tone5.png
new file mode 100644
index 00000000000..60b16f61659
--- /dev/null
+++ b/public/-/emojis/2/bath_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/bathtub.png b/public/-/emojis/2/bathtub.png
new file mode 100644
index 00000000000..501ccae15a7
--- /dev/null
+++ b/public/-/emojis/2/bathtub.png
Binary files differ
diff --git a/public/-/emojis/2/battery.png b/public/-/emojis/2/battery.png
new file mode 100644
index 00000000000..12843f1c95e
--- /dev/null
+++ b/public/-/emojis/2/battery.png
Binary files differ
diff --git a/public/-/emojis/2/beach.png b/public/-/emojis/2/beach.png
new file mode 100644
index 00000000000..a9226e600d3
--- /dev/null
+++ b/public/-/emojis/2/beach.png
Binary files differ
diff --git a/public/-/emojis/2/beach_umbrella.png b/public/-/emojis/2/beach_umbrella.png
new file mode 100644
index 00000000000..5e624c39828
--- /dev/null
+++ b/public/-/emojis/2/beach_umbrella.png
Binary files differ
diff --git a/public/-/emojis/2/bear.png b/public/-/emojis/2/bear.png
new file mode 100644
index 00000000000..acc09b24874
--- /dev/null
+++ b/public/-/emojis/2/bear.png
Binary files differ
diff --git a/public/-/emojis/2/bed.png b/public/-/emojis/2/bed.png
new file mode 100644
index 00000000000..26ced7e343e
--- /dev/null
+++ b/public/-/emojis/2/bed.png
Binary files differ
diff --git a/public/-/emojis/2/bee.png b/public/-/emojis/2/bee.png
new file mode 100644
index 00000000000..969e84a62d8
--- /dev/null
+++ b/public/-/emojis/2/bee.png
Binary files differ
diff --git a/public/-/emojis/2/beer.png b/public/-/emojis/2/beer.png
new file mode 100644
index 00000000000..84b9b596b07
--- /dev/null
+++ b/public/-/emojis/2/beer.png
Binary files differ
diff --git a/public/-/emojis/2/beers.png b/public/-/emojis/2/beers.png
new file mode 100644
index 00000000000..b9f281aa043
--- /dev/null
+++ b/public/-/emojis/2/beers.png
Binary files differ
diff --git a/public/-/emojis/2/beetle.png b/public/-/emojis/2/beetle.png
new file mode 100644
index 00000000000..48a4be009f8
--- /dev/null
+++ b/public/-/emojis/2/beetle.png
Binary files differ
diff --git a/public/-/emojis/2/beginner.png b/public/-/emojis/2/beginner.png
new file mode 100644
index 00000000000..f96db16b96a
--- /dev/null
+++ b/public/-/emojis/2/beginner.png
Binary files differ
diff --git a/public/-/emojis/2/bell.png b/public/-/emojis/2/bell.png
new file mode 100644
index 00000000000..b46ebdb6288
--- /dev/null
+++ b/public/-/emojis/2/bell.png
Binary files differ
diff --git a/public/-/emojis/2/bellhop.png b/public/-/emojis/2/bellhop.png
new file mode 100644
index 00000000000..dbe77931480
--- /dev/null
+++ b/public/-/emojis/2/bellhop.png
Binary files differ
diff --git a/public/-/emojis/2/bento.png b/public/-/emojis/2/bento.png
new file mode 100644
index 00000000000..f68dcb2ea68
--- /dev/null
+++ b/public/-/emojis/2/bento.png
Binary files differ
diff --git a/public/-/emojis/2/bicyclist.png b/public/-/emojis/2/bicyclist.png
new file mode 100644
index 00000000000..b17c6711cda
--- /dev/null
+++ b/public/-/emojis/2/bicyclist.png
Binary files differ
diff --git a/public/-/emojis/2/bicyclist_tone1.png b/public/-/emojis/2/bicyclist_tone1.png
new file mode 100644
index 00000000000..843080335ce
--- /dev/null
+++ b/public/-/emojis/2/bicyclist_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/bicyclist_tone2.png b/public/-/emojis/2/bicyclist_tone2.png
new file mode 100644
index 00000000000..a51965af04f
--- /dev/null
+++ b/public/-/emojis/2/bicyclist_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/bicyclist_tone3.png b/public/-/emojis/2/bicyclist_tone3.png
new file mode 100644
index 00000000000..3a168648f36
--- /dev/null
+++ b/public/-/emojis/2/bicyclist_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/bicyclist_tone4.png b/public/-/emojis/2/bicyclist_tone4.png
new file mode 100644
index 00000000000..cccf1d9daf0
--- /dev/null
+++ b/public/-/emojis/2/bicyclist_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/bicyclist_tone5.png b/public/-/emojis/2/bicyclist_tone5.png
new file mode 100644
index 00000000000..b4ace73d9c5
--- /dev/null
+++ b/public/-/emojis/2/bicyclist_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/bike.png b/public/-/emojis/2/bike.png
new file mode 100644
index 00000000000..93f96307aca
--- /dev/null
+++ b/public/-/emojis/2/bike.png
Binary files differ
diff --git a/public/-/emojis/2/bikini.png b/public/-/emojis/2/bikini.png
new file mode 100644
index 00000000000..e3ec48ceccd
--- /dev/null
+++ b/public/-/emojis/2/bikini.png
Binary files differ
diff --git a/public/-/emojis/2/biohazard.png b/public/-/emojis/2/biohazard.png
new file mode 100644
index 00000000000..38efca6e9be
--- /dev/null
+++ b/public/-/emojis/2/biohazard.png
Binary files differ
diff --git a/public/-/emojis/2/bird.png b/public/-/emojis/2/bird.png
new file mode 100644
index 00000000000..3c24adad7e9
--- /dev/null
+++ b/public/-/emojis/2/bird.png
Binary files differ
diff --git a/public/-/emojis/2/birthday.png b/public/-/emojis/2/birthday.png
new file mode 100644
index 00000000000..079f6b4f6a6
--- /dev/null
+++ b/public/-/emojis/2/birthday.png
Binary files differ
diff --git a/public/-/emojis/2/black_circle.png b/public/-/emojis/2/black_circle.png
new file mode 100644
index 00000000000..aeb256fad50
--- /dev/null
+++ b/public/-/emojis/2/black_circle.png
Binary files differ
diff --git a/public/-/emojis/2/black_heart.png b/public/-/emojis/2/black_heart.png
new file mode 100644
index 00000000000..e03590a7e1b
--- /dev/null
+++ b/public/-/emojis/2/black_heart.png
Binary files differ
diff --git a/public/-/emojis/2/black_joker.png b/public/-/emojis/2/black_joker.png
new file mode 100644
index 00000000000..198f3bf92d4
--- /dev/null
+++ b/public/-/emojis/2/black_joker.png
Binary files differ
diff --git a/public/-/emojis/2/black_large_square.png b/public/-/emojis/2/black_large_square.png
new file mode 100644
index 00000000000..59885c1decf
--- /dev/null
+++ b/public/-/emojis/2/black_large_square.png
Binary files differ
diff --git a/public/-/emojis/2/black_medium_small_square.png b/public/-/emojis/2/black_medium_small_square.png
new file mode 100644
index 00000000000..de0e9a53fd7
--- /dev/null
+++ b/public/-/emojis/2/black_medium_small_square.png
Binary files differ
diff --git a/public/-/emojis/2/black_medium_square.png b/public/-/emojis/2/black_medium_square.png
new file mode 100644
index 00000000000..41e0821fd2c
--- /dev/null
+++ b/public/-/emojis/2/black_medium_square.png
Binary files differ
diff --git a/public/-/emojis/2/black_nib.png b/public/-/emojis/2/black_nib.png
new file mode 100644
index 00000000000..b7142a9af5b
--- /dev/null
+++ b/public/-/emojis/2/black_nib.png
Binary files differ
diff --git a/public/-/emojis/2/black_small_square.png b/public/-/emojis/2/black_small_square.png
new file mode 100644
index 00000000000..f812d0b647f
--- /dev/null
+++ b/public/-/emojis/2/black_small_square.png
Binary files differ
diff --git a/public/-/emojis/2/black_square_button.png b/public/-/emojis/2/black_square_button.png
new file mode 100644
index 00000000000..633c32431cf
--- /dev/null
+++ b/public/-/emojis/2/black_square_button.png
Binary files differ
diff --git a/public/-/emojis/2/blossom.png b/public/-/emojis/2/blossom.png
new file mode 100644
index 00000000000..251f15cb23b
--- /dev/null
+++ b/public/-/emojis/2/blossom.png
Binary files differ
diff --git a/public/-/emojis/2/blowfish.png b/public/-/emojis/2/blowfish.png
new file mode 100644
index 00000000000..4cab2fc8fc6
--- /dev/null
+++ b/public/-/emojis/2/blowfish.png
Binary files differ
diff --git a/public/-/emojis/2/blue_book.png b/public/-/emojis/2/blue_book.png
new file mode 100644
index 00000000000..ca10b2dbf6c
--- /dev/null
+++ b/public/-/emojis/2/blue_book.png
Binary files differ
diff --git a/public/-/emojis/2/blue_car.png b/public/-/emojis/2/blue_car.png
new file mode 100644
index 00000000000..eb63d4d2853
--- /dev/null
+++ b/public/-/emojis/2/blue_car.png
Binary files differ
diff --git a/public/-/emojis/2/blue_heart.png b/public/-/emojis/2/blue_heart.png
new file mode 100644
index 00000000000..9ed47aa4206
--- /dev/null
+++ b/public/-/emojis/2/blue_heart.png
Binary files differ
diff --git a/public/-/emojis/2/blush.png b/public/-/emojis/2/blush.png
new file mode 100644
index 00000000000..2ef1e69832e
--- /dev/null
+++ b/public/-/emojis/2/blush.png
Binary files differ
diff --git a/public/-/emojis/2/boar.png b/public/-/emojis/2/boar.png
new file mode 100644
index 00000000000..584788c3a83
--- /dev/null
+++ b/public/-/emojis/2/boar.png
Binary files differ
diff --git a/public/-/emojis/2/bomb.png b/public/-/emojis/2/bomb.png
new file mode 100644
index 00000000000..c1658f35bd9
--- /dev/null
+++ b/public/-/emojis/2/bomb.png
Binary files differ
diff --git a/public/-/emojis/2/book.png b/public/-/emojis/2/book.png
new file mode 100644
index 00000000000..2ee15e7db43
--- /dev/null
+++ b/public/-/emojis/2/book.png
Binary files differ
diff --git a/public/-/emojis/2/bookmark.png b/public/-/emojis/2/bookmark.png
new file mode 100644
index 00000000000..c80383f64ce
--- /dev/null
+++ b/public/-/emojis/2/bookmark.png
Binary files differ
diff --git a/public/-/emojis/2/bookmark_tabs.png b/public/-/emojis/2/bookmark_tabs.png
new file mode 100644
index 00000000000..fe19b388148
--- /dev/null
+++ b/public/-/emojis/2/bookmark_tabs.png
Binary files differ
diff --git a/public/-/emojis/2/books.png b/public/-/emojis/2/books.png
new file mode 100644
index 00000000000..374a30cfdc6
--- /dev/null
+++ b/public/-/emojis/2/books.png
Binary files differ
diff --git a/public/-/emojis/2/boom.png b/public/-/emojis/2/boom.png
new file mode 100644
index 00000000000..e900ada8694
--- /dev/null
+++ b/public/-/emojis/2/boom.png
Binary files differ
diff --git a/public/-/emojis/2/boot.png b/public/-/emojis/2/boot.png
new file mode 100644
index 00000000000..53ef9c9bf6e
--- /dev/null
+++ b/public/-/emojis/2/boot.png
Binary files differ
diff --git a/public/-/emojis/2/bouquet.png b/public/-/emojis/2/bouquet.png
new file mode 100644
index 00000000000..363c3e4d5b9
--- /dev/null
+++ b/public/-/emojis/2/bouquet.png
Binary files differ
diff --git a/public/-/emojis/2/bow.png b/public/-/emojis/2/bow.png
new file mode 100644
index 00000000000..668e9f32996
--- /dev/null
+++ b/public/-/emojis/2/bow.png
Binary files differ
diff --git a/public/-/emojis/2/bow_and_arrow.png b/public/-/emojis/2/bow_and_arrow.png
new file mode 100644
index 00000000000..9219625875f
--- /dev/null
+++ b/public/-/emojis/2/bow_and_arrow.png
Binary files differ
diff --git a/public/-/emojis/2/bow_tone1.png b/public/-/emojis/2/bow_tone1.png
new file mode 100644
index 00000000000..53d7d5c5ba3
--- /dev/null
+++ b/public/-/emojis/2/bow_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/bow_tone2.png b/public/-/emojis/2/bow_tone2.png
new file mode 100644
index 00000000000..0af738819ae
--- /dev/null
+++ b/public/-/emojis/2/bow_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/bow_tone3.png b/public/-/emojis/2/bow_tone3.png
new file mode 100644
index 00000000000..fbccdadd4b2
--- /dev/null
+++ b/public/-/emojis/2/bow_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/bow_tone4.png b/public/-/emojis/2/bow_tone4.png
new file mode 100644
index 00000000000..18dc42597e4
--- /dev/null
+++ b/public/-/emojis/2/bow_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/bow_tone5.png b/public/-/emojis/2/bow_tone5.png
new file mode 100644
index 00000000000..61c7f3d3771
--- /dev/null
+++ b/public/-/emojis/2/bow_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/bowling.png b/public/-/emojis/2/bowling.png
new file mode 100644
index 00000000000..a0bff897502
--- /dev/null
+++ b/public/-/emojis/2/bowling.png
Binary files differ
diff --git a/public/-/emojis/2/boxing_glove.png b/public/-/emojis/2/boxing_glove.png
new file mode 100644
index 00000000000..cf7ddc9b5d8
--- /dev/null
+++ b/public/-/emojis/2/boxing_glove.png
Binary files differ
diff --git a/public/-/emojis/2/boy.png b/public/-/emojis/2/boy.png
new file mode 100644
index 00000000000..28175e3d73f
--- /dev/null
+++ b/public/-/emojis/2/boy.png
Binary files differ
diff --git a/public/-/emojis/2/boy_tone1.png b/public/-/emojis/2/boy_tone1.png
new file mode 100644
index 00000000000..aa38328d79c
--- /dev/null
+++ b/public/-/emojis/2/boy_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/boy_tone2.png b/public/-/emojis/2/boy_tone2.png
new file mode 100644
index 00000000000..a2f1487c5d4
--- /dev/null
+++ b/public/-/emojis/2/boy_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/boy_tone3.png b/public/-/emojis/2/boy_tone3.png
new file mode 100644
index 00000000000..b69d9ae87dc
--- /dev/null
+++ b/public/-/emojis/2/boy_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/boy_tone4.png b/public/-/emojis/2/boy_tone4.png
new file mode 100644
index 00000000000..ed000edbe8d
--- /dev/null
+++ b/public/-/emojis/2/boy_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/boy_tone5.png b/public/-/emojis/2/boy_tone5.png
new file mode 100644
index 00000000000..664e31af90b
--- /dev/null
+++ b/public/-/emojis/2/boy_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/bread.png b/public/-/emojis/2/bread.png
new file mode 100644
index 00000000000..38b1d37af13
--- /dev/null
+++ b/public/-/emojis/2/bread.png
Binary files differ
diff --git a/public/-/emojis/2/bride_with_veil.png b/public/-/emojis/2/bride_with_veil.png
new file mode 100644
index 00000000000..89048717a9d
--- /dev/null
+++ b/public/-/emojis/2/bride_with_veil.png
Binary files differ
diff --git a/public/-/emojis/2/bride_with_veil_tone1.png b/public/-/emojis/2/bride_with_veil_tone1.png
new file mode 100644
index 00000000000..da3c67c8db1
--- /dev/null
+++ b/public/-/emojis/2/bride_with_veil_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/bride_with_veil_tone2.png b/public/-/emojis/2/bride_with_veil_tone2.png
new file mode 100644
index 00000000000..6b2582a50a5
--- /dev/null
+++ b/public/-/emojis/2/bride_with_veil_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/bride_with_veil_tone3.png b/public/-/emojis/2/bride_with_veil_tone3.png
new file mode 100644
index 00000000000..8162fdb3704
--- /dev/null
+++ b/public/-/emojis/2/bride_with_veil_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/bride_with_veil_tone4.png b/public/-/emojis/2/bride_with_veil_tone4.png
new file mode 100644
index 00000000000..50dfe4f2d8e
--- /dev/null
+++ b/public/-/emojis/2/bride_with_veil_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/bride_with_veil_tone5.png b/public/-/emojis/2/bride_with_veil_tone5.png
new file mode 100644
index 00000000000..5010deb0e7b
--- /dev/null
+++ b/public/-/emojis/2/bride_with_veil_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/bridge_at_night.png b/public/-/emojis/2/bridge_at_night.png
new file mode 100644
index 00000000000..a01e15a9124
--- /dev/null
+++ b/public/-/emojis/2/bridge_at_night.png
Binary files differ
diff --git a/public/-/emojis/2/briefcase.png b/public/-/emojis/2/briefcase.png
new file mode 100644
index 00000000000..9a74a2e42aa
--- /dev/null
+++ b/public/-/emojis/2/briefcase.png
Binary files differ
diff --git a/public/-/emojis/2/broken_heart.png b/public/-/emojis/2/broken_heart.png
new file mode 100644
index 00000000000..b64559dc2e3
--- /dev/null
+++ b/public/-/emojis/2/broken_heart.png
Binary files differ
diff --git a/public/-/emojis/2/bug.png b/public/-/emojis/2/bug.png
new file mode 100644
index 00000000000..921525fa773
--- /dev/null
+++ b/public/-/emojis/2/bug.png
Binary files differ
diff --git a/public/-/emojis/2/bulb.png b/public/-/emojis/2/bulb.png
new file mode 100644
index 00000000000..8581f5fe1ac
--- /dev/null
+++ b/public/-/emojis/2/bulb.png
Binary files differ
diff --git a/public/-/emojis/2/bullettrain_front.png b/public/-/emojis/2/bullettrain_front.png
new file mode 100644
index 00000000000..0367a8331ab
--- /dev/null
+++ b/public/-/emojis/2/bullettrain_front.png
Binary files differ
diff --git a/public/-/emojis/2/bullettrain_side.png b/public/-/emojis/2/bullettrain_side.png
new file mode 100644
index 00000000000..84893313804
--- /dev/null
+++ b/public/-/emojis/2/bullettrain_side.png
Binary files differ
diff --git a/public/-/emojis/2/burrito.png b/public/-/emojis/2/burrito.png
new file mode 100644
index 00000000000..7da1b837e6f
--- /dev/null
+++ b/public/-/emojis/2/burrito.png
Binary files differ
diff --git a/public/-/emojis/2/bus.png b/public/-/emojis/2/bus.png
new file mode 100644
index 00000000000..f0ac86d53c6
--- /dev/null
+++ b/public/-/emojis/2/bus.png
Binary files differ
diff --git a/public/-/emojis/2/busstop.png b/public/-/emojis/2/busstop.png
new file mode 100644
index 00000000000..c92076b7360
--- /dev/null
+++ b/public/-/emojis/2/busstop.png
Binary files differ
diff --git a/public/-/emojis/2/bust_in_silhouette.png b/public/-/emojis/2/bust_in_silhouette.png
new file mode 100644
index 00000000000..da9befccb0f
--- /dev/null
+++ b/public/-/emojis/2/bust_in_silhouette.png
Binary files differ
diff --git a/public/-/emojis/2/busts_in_silhouette.png b/public/-/emojis/2/busts_in_silhouette.png
new file mode 100644
index 00000000000..4e7041a45d4
--- /dev/null
+++ b/public/-/emojis/2/busts_in_silhouette.png
Binary files differ
diff --git a/public/-/emojis/2/butterfly.png b/public/-/emojis/2/butterfly.png
new file mode 100644
index 00000000000..3bc61589ef0
--- /dev/null
+++ b/public/-/emojis/2/butterfly.png
Binary files differ
diff --git a/public/-/emojis/2/cactus.png b/public/-/emojis/2/cactus.png
new file mode 100644
index 00000000000..991fcbf4353
--- /dev/null
+++ b/public/-/emojis/2/cactus.png
Binary files differ
diff --git a/public/-/emojis/2/cake.png b/public/-/emojis/2/cake.png
new file mode 100644
index 00000000000..0301bdea583
--- /dev/null
+++ b/public/-/emojis/2/cake.png
Binary files differ
diff --git a/public/-/emojis/2/calendar.png b/public/-/emojis/2/calendar.png
new file mode 100644
index 00000000000..7627d5c1fca
--- /dev/null
+++ b/public/-/emojis/2/calendar.png
Binary files differ
diff --git a/public/-/emojis/2/calendar_spiral.png b/public/-/emojis/2/calendar_spiral.png
new file mode 100644
index 00000000000..a13a4a5c9d9
--- /dev/null
+++ b/public/-/emojis/2/calendar_spiral.png
Binary files differ
diff --git a/public/-/emojis/2/call_me.png b/public/-/emojis/2/call_me.png
new file mode 100644
index 00000000000..f4feced19fd
--- /dev/null
+++ b/public/-/emojis/2/call_me.png
Binary files differ
diff --git a/public/-/emojis/2/call_me_tone1.png b/public/-/emojis/2/call_me_tone1.png
new file mode 100644
index 00000000000..cbb9b56e70a
--- /dev/null
+++ b/public/-/emojis/2/call_me_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/call_me_tone2.png b/public/-/emojis/2/call_me_tone2.png
new file mode 100644
index 00000000000..da166ecb517
--- /dev/null
+++ b/public/-/emojis/2/call_me_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/call_me_tone3.png b/public/-/emojis/2/call_me_tone3.png
new file mode 100644
index 00000000000..093361f982d
--- /dev/null
+++ b/public/-/emojis/2/call_me_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/call_me_tone4.png b/public/-/emojis/2/call_me_tone4.png
new file mode 100644
index 00000000000..9df57caccf8
--- /dev/null
+++ b/public/-/emojis/2/call_me_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/call_me_tone5.png b/public/-/emojis/2/call_me_tone5.png
new file mode 100644
index 00000000000..acbf2664558
--- /dev/null
+++ b/public/-/emojis/2/call_me_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/calling.png b/public/-/emojis/2/calling.png
new file mode 100644
index 00000000000..d0359eb84da
--- /dev/null
+++ b/public/-/emojis/2/calling.png
Binary files differ
diff --git a/public/-/emojis/2/camel.png b/public/-/emojis/2/camel.png
new file mode 100644
index 00000000000..27169a82dec
--- /dev/null
+++ b/public/-/emojis/2/camel.png
Binary files differ
diff --git a/public/-/emojis/2/camera.png b/public/-/emojis/2/camera.png
new file mode 100644
index 00000000000..8730993c939
--- /dev/null
+++ b/public/-/emojis/2/camera.png
Binary files differ
diff --git a/public/-/emojis/2/camera_with_flash.png b/public/-/emojis/2/camera_with_flash.png
new file mode 100644
index 00000000000..0faf75e29be
--- /dev/null
+++ b/public/-/emojis/2/camera_with_flash.png
Binary files differ
diff --git a/public/-/emojis/2/camping.png b/public/-/emojis/2/camping.png
new file mode 100644
index 00000000000..d69f19211fe
--- /dev/null
+++ b/public/-/emojis/2/camping.png
Binary files differ
diff --git a/public/-/emojis/2/cancer.png b/public/-/emojis/2/cancer.png
new file mode 100644
index 00000000000..77e14405cbe
--- /dev/null
+++ b/public/-/emojis/2/cancer.png
Binary files differ
diff --git a/public/-/emojis/2/candle.png b/public/-/emojis/2/candle.png
new file mode 100644
index 00000000000..b70c3ef6a89
--- /dev/null
+++ b/public/-/emojis/2/candle.png
Binary files differ
diff --git a/public/-/emojis/2/candy.png b/public/-/emojis/2/candy.png
new file mode 100644
index 00000000000..6e7ed35a242
--- /dev/null
+++ b/public/-/emojis/2/candy.png
Binary files differ
diff --git a/public/-/emojis/2/canoe.png b/public/-/emojis/2/canoe.png
new file mode 100644
index 00000000000..848d3575b68
--- /dev/null
+++ b/public/-/emojis/2/canoe.png
Binary files differ
diff --git a/public/-/emojis/2/capital_abcd.png b/public/-/emojis/2/capital_abcd.png
new file mode 100644
index 00000000000..13dc90f6873
--- /dev/null
+++ b/public/-/emojis/2/capital_abcd.png
Binary files differ
diff --git a/public/-/emojis/2/capricorn.png b/public/-/emojis/2/capricorn.png
new file mode 100644
index 00000000000..7f6317677da
--- /dev/null
+++ b/public/-/emojis/2/capricorn.png
Binary files differ
diff --git a/public/-/emojis/2/card_box.png b/public/-/emojis/2/card_box.png
new file mode 100644
index 00000000000..722d7429b6d
--- /dev/null
+++ b/public/-/emojis/2/card_box.png
Binary files differ
diff --git a/public/-/emojis/2/card_index.png b/public/-/emojis/2/card_index.png
new file mode 100644
index 00000000000..c160c49cf02
--- /dev/null
+++ b/public/-/emojis/2/card_index.png
Binary files differ
diff --git a/public/-/emojis/2/carousel_horse.png b/public/-/emojis/2/carousel_horse.png
new file mode 100644
index 00000000000..86d2eeba49b
--- /dev/null
+++ b/public/-/emojis/2/carousel_horse.png
Binary files differ
diff --git a/public/-/emojis/2/carrot.png b/public/-/emojis/2/carrot.png
new file mode 100644
index 00000000000..752f4bbcd1c
--- /dev/null
+++ b/public/-/emojis/2/carrot.png
Binary files differ
diff --git a/public/-/emojis/2/cartwheel.png b/public/-/emojis/2/cartwheel.png
new file mode 100644
index 00000000000..3fbaf1e9ca2
--- /dev/null
+++ b/public/-/emojis/2/cartwheel.png
Binary files differ
diff --git a/public/-/emojis/2/cartwheel_tone1.png b/public/-/emojis/2/cartwheel_tone1.png
new file mode 100644
index 00000000000..297c90ea301
--- /dev/null
+++ b/public/-/emojis/2/cartwheel_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/cartwheel_tone2.png b/public/-/emojis/2/cartwheel_tone2.png
new file mode 100644
index 00000000000..6350424f699
--- /dev/null
+++ b/public/-/emojis/2/cartwheel_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/cartwheel_tone3.png b/public/-/emojis/2/cartwheel_tone3.png
new file mode 100644
index 00000000000..ebb273532f6
--- /dev/null
+++ b/public/-/emojis/2/cartwheel_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/cartwheel_tone4.png b/public/-/emojis/2/cartwheel_tone4.png
new file mode 100644
index 00000000000..57775ff5268
--- /dev/null
+++ b/public/-/emojis/2/cartwheel_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/cartwheel_tone5.png b/public/-/emojis/2/cartwheel_tone5.png
new file mode 100644
index 00000000000..4b0a0ba5a0d
--- /dev/null
+++ b/public/-/emojis/2/cartwheel_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/cat.png b/public/-/emojis/2/cat.png
new file mode 100644
index 00000000000..d0a60fec3db
--- /dev/null
+++ b/public/-/emojis/2/cat.png
Binary files differ
diff --git a/public/-/emojis/2/cat2.png b/public/-/emojis/2/cat2.png
new file mode 100644
index 00000000000..610076eccd7
--- /dev/null
+++ b/public/-/emojis/2/cat2.png
Binary files differ
diff --git a/public/-/emojis/2/cd.png b/public/-/emojis/2/cd.png
new file mode 100644
index 00000000000..db14c01a3c5
--- /dev/null
+++ b/public/-/emojis/2/cd.png
Binary files differ
diff --git a/public/-/emojis/2/chains.png b/public/-/emojis/2/chains.png
new file mode 100644
index 00000000000..8f14d9bebaf
--- /dev/null
+++ b/public/-/emojis/2/chains.png
Binary files differ
diff --git a/public/-/emojis/2/champagne.png b/public/-/emojis/2/champagne.png
new file mode 100644
index 00000000000..fd57382281a
--- /dev/null
+++ b/public/-/emojis/2/champagne.png
Binary files differ
diff --git a/public/-/emojis/2/champagne_glass.png b/public/-/emojis/2/champagne_glass.png
new file mode 100644
index 00000000000..ba9e60d75eb
--- /dev/null
+++ b/public/-/emojis/2/champagne_glass.png
Binary files differ
diff --git a/public/-/emojis/2/chart.png b/public/-/emojis/2/chart.png
new file mode 100644
index 00000000000..c6085e85433
--- /dev/null
+++ b/public/-/emojis/2/chart.png
Binary files differ
diff --git a/public/-/emojis/2/chart_with_downwards_trend.png b/public/-/emojis/2/chart_with_downwards_trend.png
new file mode 100644
index 00000000000..6670585553d
--- /dev/null
+++ b/public/-/emojis/2/chart_with_downwards_trend.png
Binary files differ
diff --git a/public/-/emojis/2/chart_with_upwards_trend.png b/public/-/emojis/2/chart_with_upwards_trend.png
new file mode 100644
index 00000000000..4dd69a0b9e6
--- /dev/null
+++ b/public/-/emojis/2/chart_with_upwards_trend.png
Binary files differ
diff --git a/public/-/emojis/2/checkered_flag.png b/public/-/emojis/2/checkered_flag.png
new file mode 100644
index 00000000000..59f2594ddc5
--- /dev/null
+++ b/public/-/emojis/2/checkered_flag.png
Binary files differ
diff --git a/public/-/emojis/2/cheese.png b/public/-/emojis/2/cheese.png
new file mode 100644
index 00000000000..f5d6b3a7c4c
--- /dev/null
+++ b/public/-/emojis/2/cheese.png
Binary files differ
diff --git a/public/-/emojis/2/cherries.png b/public/-/emojis/2/cherries.png
new file mode 100644
index 00000000000..db09bb5e4b9
--- /dev/null
+++ b/public/-/emojis/2/cherries.png
Binary files differ
diff --git a/public/-/emojis/2/cherry_blossom.png b/public/-/emojis/2/cherry_blossom.png
new file mode 100644
index 00000000000..7f89052791b
--- /dev/null
+++ b/public/-/emojis/2/cherry_blossom.png
Binary files differ
diff --git a/public/-/emojis/2/chestnut.png b/public/-/emojis/2/chestnut.png
new file mode 100644
index 00000000000..04aa25a86c3
--- /dev/null
+++ b/public/-/emojis/2/chestnut.png
Binary files differ
diff --git a/public/-/emojis/2/chicken.png b/public/-/emojis/2/chicken.png
new file mode 100644
index 00000000000..f9aa50248c1
--- /dev/null
+++ b/public/-/emojis/2/chicken.png
Binary files differ
diff --git a/public/-/emojis/2/children_crossing.png b/public/-/emojis/2/children_crossing.png
new file mode 100644
index 00000000000..8549b6ddaad
--- /dev/null
+++ b/public/-/emojis/2/children_crossing.png
Binary files differ
diff --git a/public/-/emojis/2/chipmunk.png b/public/-/emojis/2/chipmunk.png
new file mode 100644
index 00000000000..308550d9e96
--- /dev/null
+++ b/public/-/emojis/2/chipmunk.png
Binary files differ
diff --git a/public/-/emojis/2/chocolate_bar.png b/public/-/emojis/2/chocolate_bar.png
new file mode 100644
index 00000000000..37aac73574b
--- /dev/null
+++ b/public/-/emojis/2/chocolate_bar.png
Binary files differ
diff --git a/public/-/emojis/2/christmas_tree.png b/public/-/emojis/2/christmas_tree.png
new file mode 100644
index 00000000000..3cf4ca07d41
--- /dev/null
+++ b/public/-/emojis/2/christmas_tree.png
Binary files differ
diff --git a/public/-/emojis/2/church.png b/public/-/emojis/2/church.png
new file mode 100644
index 00000000000..a12aabbd66f
--- /dev/null
+++ b/public/-/emojis/2/church.png
Binary files differ
diff --git a/public/-/emojis/2/cinema.png b/public/-/emojis/2/cinema.png
new file mode 100644
index 00000000000..59934f466df
--- /dev/null
+++ b/public/-/emojis/2/cinema.png
Binary files differ
diff --git a/public/-/emojis/2/circus_tent.png b/public/-/emojis/2/circus_tent.png
new file mode 100644
index 00000000000..6c9d9a219e7
--- /dev/null
+++ b/public/-/emojis/2/circus_tent.png
Binary files differ
diff --git a/public/-/emojis/2/city_dusk.png b/public/-/emojis/2/city_dusk.png
new file mode 100644
index 00000000000..8fe2f6e5bca
--- /dev/null
+++ b/public/-/emojis/2/city_dusk.png
Binary files differ
diff --git a/public/-/emojis/2/city_sunset.png b/public/-/emojis/2/city_sunset.png
new file mode 100644
index 00000000000..fcbc2854169
--- /dev/null
+++ b/public/-/emojis/2/city_sunset.png
Binary files differ
diff --git a/public/-/emojis/2/cityscape.png b/public/-/emojis/2/cityscape.png
new file mode 100644
index 00000000000..e9029b2eb2c
--- /dev/null
+++ b/public/-/emojis/2/cityscape.png
Binary files differ
diff --git a/public/-/emojis/2/cl.png b/public/-/emojis/2/cl.png
new file mode 100644
index 00000000000..915f8de08fd
--- /dev/null
+++ b/public/-/emojis/2/cl.png
Binary files differ
diff --git a/public/-/emojis/2/clap.png b/public/-/emojis/2/clap.png
new file mode 100644
index 00000000000..9833ca8f2c6
--- /dev/null
+++ b/public/-/emojis/2/clap.png
Binary files differ
diff --git a/public/-/emojis/2/clap_tone1.png b/public/-/emojis/2/clap_tone1.png
new file mode 100644
index 00000000000..0be85e1c20e
--- /dev/null
+++ b/public/-/emojis/2/clap_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/clap_tone2.png b/public/-/emojis/2/clap_tone2.png
new file mode 100644
index 00000000000..46c31a511a1
--- /dev/null
+++ b/public/-/emojis/2/clap_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/clap_tone3.png b/public/-/emojis/2/clap_tone3.png
new file mode 100644
index 00000000000..1a30dc96fce
--- /dev/null
+++ b/public/-/emojis/2/clap_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/clap_tone4.png b/public/-/emojis/2/clap_tone4.png
new file mode 100644
index 00000000000..de6406e8938
--- /dev/null
+++ b/public/-/emojis/2/clap_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/clap_tone5.png b/public/-/emojis/2/clap_tone5.png
new file mode 100644
index 00000000000..25dd231d55a
--- /dev/null
+++ b/public/-/emojis/2/clap_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/clapper.png b/public/-/emojis/2/clapper.png
new file mode 100644
index 00000000000..09d06f708a7
--- /dev/null
+++ b/public/-/emojis/2/clapper.png
Binary files differ
diff --git a/public/-/emojis/2/classical_building.png b/public/-/emojis/2/classical_building.png
new file mode 100644
index 00000000000..0e6c9bd6e83
--- /dev/null
+++ b/public/-/emojis/2/classical_building.png
Binary files differ
diff --git a/public/-/emojis/2/clipboard.png b/public/-/emojis/2/clipboard.png
new file mode 100644
index 00000000000..e622014de0d
--- /dev/null
+++ b/public/-/emojis/2/clipboard.png
Binary files differ
diff --git a/public/-/emojis/2/clock.png b/public/-/emojis/2/clock.png
new file mode 100644
index 00000000000..a4df2685212
--- /dev/null
+++ b/public/-/emojis/2/clock.png
Binary files differ
diff --git a/public/-/emojis/2/clock1.png b/public/-/emojis/2/clock1.png
new file mode 100644
index 00000000000..b91e15f8816
--- /dev/null
+++ b/public/-/emojis/2/clock1.png
Binary files differ
diff --git a/public/-/emojis/2/clock10.png b/public/-/emojis/2/clock10.png
new file mode 100644
index 00000000000..388f7ba7057
--- /dev/null
+++ b/public/-/emojis/2/clock10.png
Binary files differ
diff --git a/public/-/emojis/2/clock1030.png b/public/-/emojis/2/clock1030.png
new file mode 100644
index 00000000000..f8fd18dd956
--- /dev/null
+++ b/public/-/emojis/2/clock1030.png
Binary files differ
diff --git a/public/-/emojis/2/clock11.png b/public/-/emojis/2/clock11.png
new file mode 100644
index 00000000000..6f468e2a3ce
--- /dev/null
+++ b/public/-/emojis/2/clock11.png
Binary files differ
diff --git a/public/-/emojis/2/clock1130.png b/public/-/emojis/2/clock1130.png
new file mode 100644
index 00000000000..5b02c922ab1
--- /dev/null
+++ b/public/-/emojis/2/clock1130.png
Binary files differ
diff --git a/public/-/emojis/2/clock12.png b/public/-/emojis/2/clock12.png
new file mode 100644
index 00000000000..7580b0e8c33
--- /dev/null
+++ b/public/-/emojis/2/clock12.png
Binary files differ
diff --git a/public/-/emojis/2/clock1230.png b/public/-/emojis/2/clock1230.png
new file mode 100644
index 00000000000..72c8fbeca23
--- /dev/null
+++ b/public/-/emojis/2/clock1230.png
Binary files differ
diff --git a/public/-/emojis/2/clock130.png b/public/-/emojis/2/clock130.png
new file mode 100644
index 00000000000..bf581dfeae6
--- /dev/null
+++ b/public/-/emojis/2/clock130.png
Binary files differ
diff --git a/public/-/emojis/2/clock2.png b/public/-/emojis/2/clock2.png
new file mode 100644
index 00000000000..47dd28d2b00
--- /dev/null
+++ b/public/-/emojis/2/clock2.png
Binary files differ
diff --git a/public/-/emojis/2/clock230.png b/public/-/emojis/2/clock230.png
new file mode 100644
index 00000000000..46f53970329
--- /dev/null
+++ b/public/-/emojis/2/clock230.png
Binary files differ
diff --git a/public/-/emojis/2/clock3.png b/public/-/emojis/2/clock3.png
new file mode 100644
index 00000000000..5ef2bdcd3d2
--- /dev/null
+++ b/public/-/emojis/2/clock3.png
Binary files differ
diff --git a/public/-/emojis/2/clock330.png b/public/-/emojis/2/clock330.png
new file mode 100644
index 00000000000..e2d04b8867d
--- /dev/null
+++ b/public/-/emojis/2/clock330.png
Binary files differ
diff --git a/public/-/emojis/2/clock4.png b/public/-/emojis/2/clock4.png
new file mode 100644
index 00000000000..492b7387c6c
--- /dev/null
+++ b/public/-/emojis/2/clock4.png
Binary files differ
diff --git a/public/-/emojis/2/clock430.png b/public/-/emojis/2/clock430.png
new file mode 100644
index 00000000000..d133e54e43d
--- /dev/null
+++ b/public/-/emojis/2/clock430.png
Binary files differ
diff --git a/public/-/emojis/2/clock5.png b/public/-/emojis/2/clock5.png
new file mode 100644
index 00000000000..56ef3041df2
--- /dev/null
+++ b/public/-/emojis/2/clock5.png
Binary files differ
diff --git a/public/-/emojis/2/clock530.png b/public/-/emojis/2/clock530.png
new file mode 100644
index 00000000000..dc53cc1c261
--- /dev/null
+++ b/public/-/emojis/2/clock530.png
Binary files differ
diff --git a/public/-/emojis/2/clock6.png b/public/-/emojis/2/clock6.png
new file mode 100644
index 00000000000..49641e97294
--- /dev/null
+++ b/public/-/emojis/2/clock6.png
Binary files differ
diff --git a/public/-/emojis/2/clock630.png b/public/-/emojis/2/clock630.png
new file mode 100644
index 00000000000..0f4fd735880
--- /dev/null
+++ b/public/-/emojis/2/clock630.png
Binary files differ
diff --git a/public/-/emojis/2/clock7.png b/public/-/emojis/2/clock7.png
new file mode 100644
index 00000000000..65b554c7b28
--- /dev/null
+++ b/public/-/emojis/2/clock7.png
Binary files differ
diff --git a/public/-/emojis/2/clock730.png b/public/-/emojis/2/clock730.png
new file mode 100644
index 00000000000..ce46b94451f
--- /dev/null
+++ b/public/-/emojis/2/clock730.png
Binary files differ
diff --git a/public/-/emojis/2/clock8.png b/public/-/emojis/2/clock8.png
new file mode 100644
index 00000000000..a838ef2f034
--- /dev/null
+++ b/public/-/emojis/2/clock8.png
Binary files differ
diff --git a/public/-/emojis/2/clock830.png b/public/-/emojis/2/clock830.png
new file mode 100644
index 00000000000..790d19a639f
--- /dev/null
+++ b/public/-/emojis/2/clock830.png
Binary files differ
diff --git a/public/-/emojis/2/clock9.png b/public/-/emojis/2/clock9.png
new file mode 100644
index 00000000000..5b08c8dbd95
--- /dev/null
+++ b/public/-/emojis/2/clock9.png
Binary files differ
diff --git a/public/-/emojis/2/clock930.png b/public/-/emojis/2/clock930.png
new file mode 100644
index 00000000000..ededcf92cba
--- /dev/null
+++ b/public/-/emojis/2/clock930.png
Binary files differ
diff --git a/public/-/emojis/2/closed_book.png b/public/-/emojis/2/closed_book.png
new file mode 100644
index 00000000000..30e95d2d52d
--- /dev/null
+++ b/public/-/emojis/2/closed_book.png
Binary files differ
diff --git a/public/-/emojis/2/closed_lock_with_key.png b/public/-/emojis/2/closed_lock_with_key.png
new file mode 100644
index 00000000000..3a034974455
--- /dev/null
+++ b/public/-/emojis/2/closed_lock_with_key.png
Binary files differ
diff --git a/public/-/emojis/2/closed_umbrella.png b/public/-/emojis/2/closed_umbrella.png
new file mode 100644
index 00000000000..4ae00f07df9
--- /dev/null
+++ b/public/-/emojis/2/closed_umbrella.png
Binary files differ
diff --git a/public/-/emojis/2/cloud.png b/public/-/emojis/2/cloud.png
new file mode 100644
index 00000000000..7f63fa4bf10
--- /dev/null
+++ b/public/-/emojis/2/cloud.png
Binary files differ
diff --git a/public/-/emojis/2/cloud_lightning.png b/public/-/emojis/2/cloud_lightning.png
new file mode 100644
index 00000000000..739d7491473
--- /dev/null
+++ b/public/-/emojis/2/cloud_lightning.png
Binary files differ
diff --git a/public/-/emojis/2/cloud_rain.png b/public/-/emojis/2/cloud_rain.png
new file mode 100644
index 00000000000..ce4aaad1522
--- /dev/null
+++ b/public/-/emojis/2/cloud_rain.png
Binary files differ
diff --git a/public/-/emojis/2/cloud_snow.png b/public/-/emojis/2/cloud_snow.png
new file mode 100644
index 00000000000..6af161f3c5f
--- /dev/null
+++ b/public/-/emojis/2/cloud_snow.png
Binary files differ
diff --git a/public/-/emojis/2/cloud_tornado.png b/public/-/emojis/2/cloud_tornado.png
new file mode 100644
index 00000000000..1480b092e2e
--- /dev/null
+++ b/public/-/emojis/2/cloud_tornado.png
Binary files differ
diff --git a/public/-/emojis/2/clown.png b/public/-/emojis/2/clown.png
new file mode 100644
index 00000000000..311febd6a6b
--- /dev/null
+++ b/public/-/emojis/2/clown.png
Binary files differ
diff --git a/public/-/emojis/2/clubs.png b/public/-/emojis/2/clubs.png
new file mode 100644
index 00000000000..7860b5c6356
--- /dev/null
+++ b/public/-/emojis/2/clubs.png
Binary files differ
diff --git a/public/-/emojis/2/cocktail.png b/public/-/emojis/2/cocktail.png
new file mode 100644
index 00000000000..02680697988
--- /dev/null
+++ b/public/-/emojis/2/cocktail.png
Binary files differ
diff --git a/public/-/emojis/2/coffee.png b/public/-/emojis/2/coffee.png
new file mode 100644
index 00000000000..9117f8a03a5
--- /dev/null
+++ b/public/-/emojis/2/coffee.png
Binary files differ
diff --git a/public/-/emojis/2/coffin.png b/public/-/emojis/2/coffin.png
new file mode 100644
index 00000000000..83f74b23081
--- /dev/null
+++ b/public/-/emojis/2/coffin.png
Binary files differ
diff --git a/public/-/emojis/2/cold_sweat.png b/public/-/emojis/2/cold_sweat.png
new file mode 100644
index 00000000000..81aaf65d30f
--- /dev/null
+++ b/public/-/emojis/2/cold_sweat.png
Binary files differ
diff --git a/public/-/emojis/2/comet.png b/public/-/emojis/2/comet.png
new file mode 100644
index 00000000000..69ec4ecd43a
--- /dev/null
+++ b/public/-/emojis/2/comet.png
Binary files differ
diff --git a/public/-/emojis/2/compression.png b/public/-/emojis/2/compression.png
new file mode 100644
index 00000000000..697af61af91
--- /dev/null
+++ b/public/-/emojis/2/compression.png
Binary files differ
diff --git a/public/-/emojis/2/computer.png b/public/-/emojis/2/computer.png
new file mode 100644
index 00000000000..7f475f39726
--- /dev/null
+++ b/public/-/emojis/2/computer.png
Binary files differ
diff --git a/public/-/emojis/2/confetti_ball.png b/public/-/emojis/2/confetti_ball.png
new file mode 100644
index 00000000000..2bf3de8938a
--- /dev/null
+++ b/public/-/emojis/2/confetti_ball.png
Binary files differ
diff --git a/public/-/emojis/2/confounded.png b/public/-/emojis/2/confounded.png
new file mode 100644
index 00000000000..9410a26ea24
--- /dev/null
+++ b/public/-/emojis/2/confounded.png
Binary files differ
diff --git a/public/-/emojis/2/confused.png b/public/-/emojis/2/confused.png
new file mode 100644
index 00000000000..4dedc86f13d
--- /dev/null
+++ b/public/-/emojis/2/confused.png
Binary files differ
diff --git a/public/-/emojis/2/congratulations.png b/public/-/emojis/2/congratulations.png
new file mode 100644
index 00000000000..6a15c4bc107
--- /dev/null
+++ b/public/-/emojis/2/congratulations.png
Binary files differ
diff --git a/public/-/emojis/2/construction.png b/public/-/emojis/2/construction.png
new file mode 100644
index 00000000000..8b15db797a2
--- /dev/null
+++ b/public/-/emojis/2/construction.png
Binary files differ
diff --git a/public/-/emojis/2/construction_site.png b/public/-/emojis/2/construction_site.png
new file mode 100644
index 00000000000..5d2a18d9f86
--- /dev/null
+++ b/public/-/emojis/2/construction_site.png
Binary files differ
diff --git a/public/-/emojis/2/construction_worker.png b/public/-/emojis/2/construction_worker.png
new file mode 100644
index 00000000000..4ae3426de3a
--- /dev/null
+++ b/public/-/emojis/2/construction_worker.png
Binary files differ
diff --git a/public/-/emojis/2/construction_worker_tone1.png b/public/-/emojis/2/construction_worker_tone1.png
new file mode 100644
index 00000000000..b248134628b
--- /dev/null
+++ b/public/-/emojis/2/construction_worker_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/construction_worker_tone2.png b/public/-/emojis/2/construction_worker_tone2.png
new file mode 100644
index 00000000000..00ea3920275
--- /dev/null
+++ b/public/-/emojis/2/construction_worker_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/construction_worker_tone3.png b/public/-/emojis/2/construction_worker_tone3.png
new file mode 100644
index 00000000000..2dda18a3726
--- /dev/null
+++ b/public/-/emojis/2/construction_worker_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/construction_worker_tone4.png b/public/-/emojis/2/construction_worker_tone4.png
new file mode 100644
index 00000000000..c1eaf70a9f1
--- /dev/null
+++ b/public/-/emojis/2/construction_worker_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/construction_worker_tone5.png b/public/-/emojis/2/construction_worker_tone5.png
new file mode 100644
index 00000000000..9109d5cc838
--- /dev/null
+++ b/public/-/emojis/2/construction_worker_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/control_knobs.png b/public/-/emojis/2/control_knobs.png
new file mode 100644
index 00000000000..fc77d837cfd
--- /dev/null
+++ b/public/-/emojis/2/control_knobs.png
Binary files differ
diff --git a/public/-/emojis/2/convenience_store.png b/public/-/emojis/2/convenience_store.png
new file mode 100644
index 00000000000..687cebbc56d
--- /dev/null
+++ b/public/-/emojis/2/convenience_store.png
Binary files differ
diff --git a/public/-/emojis/2/cookie.png b/public/-/emojis/2/cookie.png
new file mode 100644
index 00000000000..5c562e3d8c3
--- /dev/null
+++ b/public/-/emojis/2/cookie.png
Binary files differ
diff --git a/public/-/emojis/2/cooking.png b/public/-/emojis/2/cooking.png
new file mode 100644
index 00000000000..062ebf83853
--- /dev/null
+++ b/public/-/emojis/2/cooking.png
Binary files differ
diff --git a/public/-/emojis/2/cool.png b/public/-/emojis/2/cool.png
new file mode 100644
index 00000000000..0942e466588
--- /dev/null
+++ b/public/-/emojis/2/cool.png
Binary files differ
diff --git a/public/-/emojis/2/cop.png b/public/-/emojis/2/cop.png
new file mode 100644
index 00000000000..ed4250c9045
--- /dev/null
+++ b/public/-/emojis/2/cop.png
Binary files differ
diff --git a/public/-/emojis/2/cop_tone1.png b/public/-/emojis/2/cop_tone1.png
new file mode 100644
index 00000000000..fd73888b037
--- /dev/null
+++ b/public/-/emojis/2/cop_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/cop_tone2.png b/public/-/emojis/2/cop_tone2.png
new file mode 100644
index 00000000000..e8f401197ef
--- /dev/null
+++ b/public/-/emojis/2/cop_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/cop_tone3.png b/public/-/emojis/2/cop_tone3.png
new file mode 100644
index 00000000000..7f1c923ec1b
--- /dev/null
+++ b/public/-/emojis/2/cop_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/cop_tone4.png b/public/-/emojis/2/cop_tone4.png
new file mode 100644
index 00000000000..f4ca694083d
--- /dev/null
+++ b/public/-/emojis/2/cop_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/cop_tone5.png b/public/-/emojis/2/cop_tone5.png
new file mode 100644
index 00000000000..f9be2181d40
--- /dev/null
+++ b/public/-/emojis/2/cop_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/copyright.png b/public/-/emojis/2/copyright.png
new file mode 100644
index 00000000000..1533c4c61eb
--- /dev/null
+++ b/public/-/emojis/2/copyright.png
Binary files differ
diff --git a/public/-/emojis/2/corn.png b/public/-/emojis/2/corn.png
new file mode 100644
index 00000000000..a2c5befc508
--- /dev/null
+++ b/public/-/emojis/2/corn.png
Binary files differ
diff --git a/public/-/emojis/2/couch.png b/public/-/emojis/2/couch.png
new file mode 100644
index 00000000000..e5f64c537d2
--- /dev/null
+++ b/public/-/emojis/2/couch.png
Binary files differ
diff --git a/public/-/emojis/2/couple.png b/public/-/emojis/2/couple.png
new file mode 100644
index 00000000000..2ed7eb3262a
--- /dev/null
+++ b/public/-/emojis/2/couple.png
Binary files differ
diff --git a/public/-/emojis/2/couple_mm.png b/public/-/emojis/2/couple_mm.png
new file mode 100644
index 00000000000..1adebaa7ff9
--- /dev/null
+++ b/public/-/emojis/2/couple_mm.png
Binary files differ
diff --git a/public/-/emojis/2/couple_with_heart.png b/public/-/emojis/2/couple_with_heart.png
new file mode 100644
index 00000000000..338ffadef7a
--- /dev/null
+++ b/public/-/emojis/2/couple_with_heart.png
Binary files differ
diff --git a/public/-/emojis/2/couple_ww.png b/public/-/emojis/2/couple_ww.png
new file mode 100644
index 00000000000..2bcc1aa527b
--- /dev/null
+++ b/public/-/emojis/2/couple_ww.png
Binary files differ
diff --git a/public/-/emojis/2/couplekiss.png b/public/-/emojis/2/couplekiss.png
new file mode 100644
index 00000000000..1fa3de69028
--- /dev/null
+++ b/public/-/emojis/2/couplekiss.png
Binary files differ
diff --git a/public/-/emojis/2/cow.png b/public/-/emojis/2/cow.png
new file mode 100644
index 00000000000..bb41c5b8327
--- /dev/null
+++ b/public/-/emojis/2/cow.png
Binary files differ
diff --git a/public/-/emojis/2/cow2.png b/public/-/emojis/2/cow2.png
new file mode 100644
index 00000000000..7b22fbf57a2
--- /dev/null
+++ b/public/-/emojis/2/cow2.png
Binary files differ
diff --git a/public/-/emojis/2/cowboy.png b/public/-/emojis/2/cowboy.png
new file mode 100644
index 00000000000..77a8a8f91bc
--- /dev/null
+++ b/public/-/emojis/2/cowboy.png
Binary files differ
diff --git a/public/-/emojis/2/crab.png b/public/-/emojis/2/crab.png
new file mode 100644
index 00000000000..4006a1fac1b
--- /dev/null
+++ b/public/-/emojis/2/crab.png
Binary files differ
diff --git a/public/-/emojis/2/crayon.png b/public/-/emojis/2/crayon.png
new file mode 100644
index 00000000000..a708705dc38
--- /dev/null
+++ b/public/-/emojis/2/crayon.png
Binary files differ
diff --git a/public/-/emojis/2/credit_card.png b/public/-/emojis/2/credit_card.png
new file mode 100644
index 00000000000..a30cf4cea3b
--- /dev/null
+++ b/public/-/emojis/2/credit_card.png
Binary files differ
diff --git a/public/-/emojis/2/crescent_moon.png b/public/-/emojis/2/crescent_moon.png
new file mode 100644
index 00000000000..c53b11e2bfb
--- /dev/null
+++ b/public/-/emojis/2/crescent_moon.png
Binary files differ
diff --git a/public/-/emojis/2/cricket.png b/public/-/emojis/2/cricket.png
new file mode 100644
index 00000000000..e83078dd6f7
--- /dev/null
+++ b/public/-/emojis/2/cricket.png
Binary files differ
diff --git a/public/-/emojis/2/crocodile.png b/public/-/emojis/2/crocodile.png
new file mode 100644
index 00000000000..45eae24995f
--- /dev/null
+++ b/public/-/emojis/2/crocodile.png
Binary files differ
diff --git a/public/-/emojis/2/croissant.png b/public/-/emojis/2/croissant.png
new file mode 100644
index 00000000000..cac52a57ec6
--- /dev/null
+++ b/public/-/emojis/2/croissant.png
Binary files differ
diff --git a/public/-/emojis/2/cross.png b/public/-/emojis/2/cross.png
new file mode 100644
index 00000000000..dcaf713d86a
--- /dev/null
+++ b/public/-/emojis/2/cross.png
Binary files differ
diff --git a/public/-/emojis/2/crossed_flags.png b/public/-/emojis/2/crossed_flags.png
new file mode 100644
index 00000000000..5f8a42cf7ae
--- /dev/null
+++ b/public/-/emojis/2/crossed_flags.png
Binary files differ
diff --git a/public/-/emojis/2/crossed_swords.png b/public/-/emojis/2/crossed_swords.png
new file mode 100644
index 00000000000..849a32fc979
--- /dev/null
+++ b/public/-/emojis/2/crossed_swords.png
Binary files differ
diff --git a/public/-/emojis/2/crown.png b/public/-/emojis/2/crown.png
new file mode 100644
index 00000000000..805b0b48603
--- /dev/null
+++ b/public/-/emojis/2/crown.png
Binary files differ
diff --git a/public/-/emojis/2/cruise_ship.png b/public/-/emojis/2/cruise_ship.png
new file mode 100644
index 00000000000..7c393baf077
--- /dev/null
+++ b/public/-/emojis/2/cruise_ship.png
Binary files differ
diff --git a/public/-/emojis/2/cry.png b/public/-/emojis/2/cry.png
new file mode 100644
index 00000000000..8fcecb30d34
--- /dev/null
+++ b/public/-/emojis/2/cry.png
Binary files differ
diff --git a/public/-/emojis/2/crying_cat_face.png b/public/-/emojis/2/crying_cat_face.png
new file mode 100644
index 00000000000..4ad78aa8ed7
--- /dev/null
+++ b/public/-/emojis/2/crying_cat_face.png
Binary files differ
diff --git a/public/-/emojis/2/crystal_ball.png b/public/-/emojis/2/crystal_ball.png
new file mode 100644
index 00000000000..cf68dfb6704
--- /dev/null
+++ b/public/-/emojis/2/crystal_ball.png
Binary files differ
diff --git a/public/-/emojis/2/cucumber.png b/public/-/emojis/2/cucumber.png
new file mode 100644
index 00000000000..c4f95a74ecb
--- /dev/null
+++ b/public/-/emojis/2/cucumber.png
Binary files differ
diff --git a/public/-/emojis/2/cupid.png b/public/-/emojis/2/cupid.png
new file mode 100644
index 00000000000..a46c194c899
--- /dev/null
+++ b/public/-/emojis/2/cupid.png
Binary files differ
diff --git a/public/-/emojis/2/curly_loop.png b/public/-/emojis/2/curly_loop.png
new file mode 100644
index 00000000000..3d71b69637c
--- /dev/null
+++ b/public/-/emojis/2/curly_loop.png
Binary files differ
diff --git a/public/-/emojis/2/currency_exchange.png b/public/-/emojis/2/currency_exchange.png
new file mode 100644
index 00000000000..bf63ee89a62
--- /dev/null
+++ b/public/-/emojis/2/currency_exchange.png
Binary files differ
diff --git a/public/-/emojis/2/curry.png b/public/-/emojis/2/curry.png
new file mode 100644
index 00000000000..94cb3cea86a
--- /dev/null
+++ b/public/-/emojis/2/curry.png
Binary files differ
diff --git a/public/-/emojis/2/custard.png b/public/-/emojis/2/custard.png
new file mode 100644
index 00000000000..07fc9250fe5
--- /dev/null
+++ b/public/-/emojis/2/custard.png
Binary files differ
diff --git a/public/-/emojis/2/customs.png b/public/-/emojis/2/customs.png
new file mode 100644
index 00000000000..de8b8525889
--- /dev/null
+++ b/public/-/emojis/2/customs.png
Binary files differ
diff --git a/public/-/emojis/2/cyclone.png b/public/-/emojis/2/cyclone.png
new file mode 100644
index 00000000000..10a1ee67512
--- /dev/null
+++ b/public/-/emojis/2/cyclone.png
Binary files differ
diff --git a/public/-/emojis/2/dagger.png b/public/-/emojis/2/dagger.png
new file mode 100644
index 00000000000..7a65ce095d2
--- /dev/null
+++ b/public/-/emojis/2/dagger.png
Binary files differ
diff --git a/public/-/emojis/2/dancer.png b/public/-/emojis/2/dancer.png
new file mode 100644
index 00000000000..701d5dc6a83
--- /dev/null
+++ b/public/-/emojis/2/dancer.png
Binary files differ
diff --git a/public/-/emojis/2/dancer_tone1.png b/public/-/emojis/2/dancer_tone1.png
new file mode 100644
index 00000000000..ad63b590f06
--- /dev/null
+++ b/public/-/emojis/2/dancer_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/dancer_tone2.png b/public/-/emojis/2/dancer_tone2.png
new file mode 100644
index 00000000000..1a28580ead5
--- /dev/null
+++ b/public/-/emojis/2/dancer_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/dancer_tone3.png b/public/-/emojis/2/dancer_tone3.png
new file mode 100644
index 00000000000..e3c35797fef
--- /dev/null
+++ b/public/-/emojis/2/dancer_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/dancer_tone4.png b/public/-/emojis/2/dancer_tone4.png
new file mode 100644
index 00000000000..053a498d4cd
--- /dev/null
+++ b/public/-/emojis/2/dancer_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/dancer_tone5.png b/public/-/emojis/2/dancer_tone5.png
new file mode 100644
index 00000000000..af4758d40c4
--- /dev/null
+++ b/public/-/emojis/2/dancer_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/dancers.png b/public/-/emojis/2/dancers.png
new file mode 100644
index 00000000000..e68ca59ed70
--- /dev/null
+++ b/public/-/emojis/2/dancers.png
Binary files differ
diff --git a/public/-/emojis/2/dango.png b/public/-/emojis/2/dango.png
new file mode 100644
index 00000000000..6a5ed27f7f7
--- /dev/null
+++ b/public/-/emojis/2/dango.png
Binary files differ
diff --git a/public/-/emojis/2/dark_sunglasses.png b/public/-/emojis/2/dark_sunglasses.png
new file mode 100644
index 00000000000..b3c3cbf16fb
--- /dev/null
+++ b/public/-/emojis/2/dark_sunglasses.png
Binary files differ
diff --git a/public/-/emojis/2/dart.png b/public/-/emojis/2/dart.png
new file mode 100644
index 00000000000..297c50e37e6
--- /dev/null
+++ b/public/-/emojis/2/dart.png
Binary files differ
diff --git a/public/-/emojis/2/dash.png b/public/-/emojis/2/dash.png
new file mode 100644
index 00000000000..da03bbdac9d
--- /dev/null
+++ b/public/-/emojis/2/dash.png
Binary files differ
diff --git a/public/-/emojis/2/date.png b/public/-/emojis/2/date.png
new file mode 100644
index 00000000000..9cd8e92e497
--- /dev/null
+++ b/public/-/emojis/2/date.png
Binary files differ
diff --git a/public/-/emojis/2/deciduous_tree.png b/public/-/emojis/2/deciduous_tree.png
new file mode 100644
index 00000000000..c61ab068531
--- /dev/null
+++ b/public/-/emojis/2/deciduous_tree.png
Binary files differ
diff --git a/public/-/emojis/2/deer.png b/public/-/emojis/2/deer.png
new file mode 100644
index 00000000000..8c7cd98546f
--- /dev/null
+++ b/public/-/emojis/2/deer.png
Binary files differ
diff --git a/public/-/emojis/2/department_store.png b/public/-/emojis/2/department_store.png
new file mode 100644
index 00000000000..548cba49523
--- /dev/null
+++ b/public/-/emojis/2/department_store.png
Binary files differ
diff --git a/public/-/emojis/2/desert.png b/public/-/emojis/2/desert.png
new file mode 100644
index 00000000000..35f2adbafb4
--- /dev/null
+++ b/public/-/emojis/2/desert.png
Binary files differ
diff --git a/public/-/emojis/2/desktop.png b/public/-/emojis/2/desktop.png
new file mode 100644
index 00000000000..8de01a76ecb
--- /dev/null
+++ b/public/-/emojis/2/desktop.png
Binary files differ
diff --git a/public/-/emojis/2/diamond_shape_with_a_dot_inside.png b/public/-/emojis/2/diamond_shape_with_a_dot_inside.png
new file mode 100644
index 00000000000..33616cd496d
--- /dev/null
+++ b/public/-/emojis/2/diamond_shape_with_a_dot_inside.png
Binary files differ
diff --git a/public/-/emojis/2/diamonds.png b/public/-/emojis/2/diamonds.png
new file mode 100644
index 00000000000..9c1d0fb2551
--- /dev/null
+++ b/public/-/emojis/2/diamonds.png
Binary files differ
diff --git a/public/-/emojis/2/disappointed.png b/public/-/emojis/2/disappointed.png
new file mode 100644
index 00000000000..58f85314d73
--- /dev/null
+++ b/public/-/emojis/2/disappointed.png
Binary files differ
diff --git a/public/-/emojis/2/disappointed_relieved.png b/public/-/emojis/2/disappointed_relieved.png
new file mode 100644
index 00000000000..eec72338eef
--- /dev/null
+++ b/public/-/emojis/2/disappointed_relieved.png
Binary files differ
diff --git a/public/-/emojis/2/dividers.png b/public/-/emojis/2/dividers.png
new file mode 100644
index 00000000000..a90c2fd8ff6
--- /dev/null
+++ b/public/-/emojis/2/dividers.png
Binary files differ
diff --git a/public/-/emojis/2/dizzy.png b/public/-/emojis/2/dizzy.png
new file mode 100644
index 00000000000..6bdcd9e5584
--- /dev/null
+++ b/public/-/emojis/2/dizzy.png
Binary files differ
diff --git a/public/-/emojis/2/dizzy_face.png b/public/-/emojis/2/dizzy_face.png
new file mode 100644
index 00000000000..8a8836963da
--- /dev/null
+++ b/public/-/emojis/2/dizzy_face.png
Binary files differ
diff --git a/public/-/emojis/2/do_not_litter.png b/public/-/emojis/2/do_not_litter.png
new file mode 100644
index 00000000000..1582c789df8
--- /dev/null
+++ b/public/-/emojis/2/do_not_litter.png
Binary files differ
diff --git a/public/-/emojis/2/dog.png b/public/-/emojis/2/dog.png
new file mode 100644
index 00000000000..261ee82429d
--- /dev/null
+++ b/public/-/emojis/2/dog.png
Binary files differ
diff --git a/public/-/emojis/2/dog2.png b/public/-/emojis/2/dog2.png
new file mode 100644
index 00000000000..c1c9bd911a3
--- /dev/null
+++ b/public/-/emojis/2/dog2.png
Binary files differ
diff --git a/public/-/emojis/2/dollar.png b/public/-/emojis/2/dollar.png
new file mode 100644
index 00000000000..dc0ffc7580e
--- /dev/null
+++ b/public/-/emojis/2/dollar.png
Binary files differ
diff --git a/public/-/emojis/2/dolls.png b/public/-/emojis/2/dolls.png
new file mode 100644
index 00000000000..7e0ac5e0ff5
--- /dev/null
+++ b/public/-/emojis/2/dolls.png
Binary files differ
diff --git a/public/-/emojis/2/dolphin.png b/public/-/emojis/2/dolphin.png
new file mode 100644
index 00000000000..135c1ff635f
--- /dev/null
+++ b/public/-/emojis/2/dolphin.png
Binary files differ
diff --git a/public/-/emojis/2/door.png b/public/-/emojis/2/door.png
new file mode 100644
index 00000000000..9f97e75007f
--- /dev/null
+++ b/public/-/emojis/2/door.png
Binary files differ
diff --git a/public/-/emojis/2/doughnut.png b/public/-/emojis/2/doughnut.png
new file mode 100644
index 00000000000..12fff3c0d52
--- /dev/null
+++ b/public/-/emojis/2/doughnut.png
Binary files differ
diff --git a/public/-/emojis/2/dove.png b/public/-/emojis/2/dove.png
new file mode 100644
index 00000000000..2a4392ec711
--- /dev/null
+++ b/public/-/emojis/2/dove.png
Binary files differ
diff --git a/public/-/emojis/2/dragon.png b/public/-/emojis/2/dragon.png
new file mode 100644
index 00000000000..0373699122e
--- /dev/null
+++ b/public/-/emojis/2/dragon.png
Binary files differ
diff --git a/public/-/emojis/2/dragon_face.png b/public/-/emojis/2/dragon_face.png
new file mode 100644
index 00000000000..1184d6f1a10
--- /dev/null
+++ b/public/-/emojis/2/dragon_face.png
Binary files differ
diff --git a/public/-/emojis/2/dress.png b/public/-/emojis/2/dress.png
new file mode 100644
index 00000000000..b8eacb7d177
--- /dev/null
+++ b/public/-/emojis/2/dress.png
Binary files differ
diff --git a/public/-/emojis/2/dromedary_camel.png b/public/-/emojis/2/dromedary_camel.png
new file mode 100644
index 00000000000..bad07051604
--- /dev/null
+++ b/public/-/emojis/2/dromedary_camel.png
Binary files differ
diff --git a/public/-/emojis/2/drooling_face.png b/public/-/emojis/2/drooling_face.png
new file mode 100644
index 00000000000..ad883534d30
--- /dev/null
+++ b/public/-/emojis/2/drooling_face.png
Binary files differ
diff --git a/public/-/emojis/2/droplet.png b/public/-/emojis/2/droplet.png
new file mode 100644
index 00000000000..5cfce842955
--- /dev/null
+++ b/public/-/emojis/2/droplet.png
Binary files differ
diff --git a/public/-/emojis/2/drum.png b/public/-/emojis/2/drum.png
new file mode 100644
index 00000000000..43a3b0cb1ce
--- /dev/null
+++ b/public/-/emojis/2/drum.png
Binary files differ
diff --git a/public/-/emojis/2/duck.png b/public/-/emojis/2/duck.png
new file mode 100644
index 00000000000..1126d456cb0
--- /dev/null
+++ b/public/-/emojis/2/duck.png
Binary files differ
diff --git a/public/-/emojis/2/dvd.png b/public/-/emojis/2/dvd.png
new file mode 100644
index 00000000000..b3b00ecfdcf
--- /dev/null
+++ b/public/-/emojis/2/dvd.png
Binary files differ
diff --git a/public/-/emojis/2/e-mail.png b/public/-/emojis/2/e-mail.png
new file mode 100644
index 00000000000..ce99dd7a163
--- /dev/null
+++ b/public/-/emojis/2/e-mail.png
Binary files differ
diff --git a/public/-/emojis/2/eagle.png b/public/-/emojis/2/eagle.png
new file mode 100644
index 00000000000..9e799f596a5
--- /dev/null
+++ b/public/-/emojis/2/eagle.png
Binary files differ
diff --git a/public/-/emojis/2/ear.png b/public/-/emojis/2/ear.png
new file mode 100644
index 00000000000..29aaf9ea164
--- /dev/null
+++ b/public/-/emojis/2/ear.png
Binary files differ
diff --git a/public/-/emojis/2/ear_of_rice.png b/public/-/emojis/2/ear_of_rice.png
new file mode 100644
index 00000000000..5424d157bc3
--- /dev/null
+++ b/public/-/emojis/2/ear_of_rice.png
Binary files differ
diff --git a/public/-/emojis/2/ear_tone1.png b/public/-/emojis/2/ear_tone1.png
new file mode 100644
index 00000000000..dee81b5f6ce
--- /dev/null
+++ b/public/-/emojis/2/ear_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/ear_tone2.png b/public/-/emojis/2/ear_tone2.png
new file mode 100644
index 00000000000..06b9835ea65
--- /dev/null
+++ b/public/-/emojis/2/ear_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/ear_tone3.png b/public/-/emojis/2/ear_tone3.png
new file mode 100644
index 00000000000..3e0ac0befd3
--- /dev/null
+++ b/public/-/emojis/2/ear_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/ear_tone4.png b/public/-/emojis/2/ear_tone4.png
new file mode 100644
index 00000000000..42398620022
--- /dev/null
+++ b/public/-/emojis/2/ear_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/ear_tone5.png b/public/-/emojis/2/ear_tone5.png
new file mode 100644
index 00000000000..de97241e30c
--- /dev/null
+++ b/public/-/emojis/2/ear_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/earth_africa.png b/public/-/emojis/2/earth_africa.png
new file mode 100644
index 00000000000..11b57568561
--- /dev/null
+++ b/public/-/emojis/2/earth_africa.png
Binary files differ
diff --git a/public/-/emojis/2/earth_americas.png b/public/-/emojis/2/earth_americas.png
new file mode 100644
index 00000000000..9f80abddcf7
--- /dev/null
+++ b/public/-/emojis/2/earth_americas.png
Binary files differ
diff --git a/public/-/emojis/2/earth_asia.png b/public/-/emojis/2/earth_asia.png
new file mode 100644
index 00000000000..199705875b0
--- /dev/null
+++ b/public/-/emojis/2/earth_asia.png
Binary files differ
diff --git a/public/-/emojis/2/egg.png b/public/-/emojis/2/egg.png
new file mode 100644
index 00000000000..201929d6119
--- /dev/null
+++ b/public/-/emojis/2/egg.png
Binary files differ
diff --git a/public/-/emojis/2/eggplant.png b/public/-/emojis/2/eggplant.png
new file mode 100644
index 00000000000..bb21a8e6f2e
--- /dev/null
+++ b/public/-/emojis/2/eggplant.png
Binary files differ
diff --git a/public/-/emojis/2/eight.png b/public/-/emojis/2/eight.png
new file mode 100644
index 00000000000..d220764a928
--- /dev/null
+++ b/public/-/emojis/2/eight.png
Binary files differ
diff --git a/public/-/emojis/2/eight_pointed_black_star.png b/public/-/emojis/2/eight_pointed_black_star.png
new file mode 100644
index 00000000000..78ad05b8bed
--- /dev/null
+++ b/public/-/emojis/2/eight_pointed_black_star.png
Binary files differ
diff --git a/public/-/emojis/2/eight_spoked_asterisk.png b/public/-/emojis/2/eight_spoked_asterisk.png
new file mode 100644
index 00000000000..fd95e20ba88
--- /dev/null
+++ b/public/-/emojis/2/eight_spoked_asterisk.png
Binary files differ
diff --git a/public/-/emojis/2/eject.png b/public/-/emojis/2/eject.png
new file mode 100644
index 00000000000..9037b30f5fd
--- /dev/null
+++ b/public/-/emojis/2/eject.png
Binary files differ
diff --git a/public/-/emojis/2/electric_plug.png b/public/-/emojis/2/electric_plug.png
new file mode 100644
index 00000000000..8942ea456ea
--- /dev/null
+++ b/public/-/emojis/2/electric_plug.png
Binary files differ
diff --git a/public/-/emojis/2/elephant.png b/public/-/emojis/2/elephant.png
new file mode 100644
index 00000000000..d25e5e96fb5
--- /dev/null
+++ b/public/-/emojis/2/elephant.png
Binary files differ
diff --git a/public/-/emojis/2/emojis.json b/public/-/emojis/2/emojis.json
new file mode 100644
index 00000000000..4ba559b5a77
--- /dev/null
+++ b/public/-/emojis/2/emojis.json
@@ -0,0 +1,10766 @@
+{
+ "100": {
+ "c": "symbols",
+ "e": "💯",
+ "d": "hundred points symbol",
+ "u": "6.0"
+ },
+ "1234": {
+ "c": "symbols",
+ "e": "🔢",
+ "d": "input symbol for numbers",
+ "u": "6.0"
+ },
+ "8ball": {
+ "c": "activity",
+ "e": "🎱",
+ "d": "billiards",
+ "u": "6.0"
+ },
+ "a": {
+ "c": "symbols",
+ "e": "🅰",
+ "d": "negative squared latin capital letter a",
+ "u": "6.0"
+ },
+ "ab": {
+ "c": "symbols",
+ "e": "🆎",
+ "d": "negative squared ab",
+ "u": "6.0"
+ },
+ "abc": {
+ "c": "symbols",
+ "e": "🔤",
+ "d": "input symbol for latin letters",
+ "u": "6.0"
+ },
+ "abcd": {
+ "c": "symbols",
+ "e": "🔡",
+ "d": "input symbol for latin small letters",
+ "u": "6.0"
+ },
+ "accept": {
+ "c": "symbols",
+ "e": "🉑",
+ "d": "circled ideograph accept",
+ "u": "6.0"
+ },
+ "aerial_tramway": {
+ "c": "travel",
+ "e": "🚡",
+ "d": "aerial tramway",
+ "u": "6.0"
+ },
+ "airplane": {
+ "c": "travel",
+ "e": "✈",
+ "d": "airplane",
+ "u": "1.1"
+ },
+ "airplane_arriving": {
+ "c": "travel",
+ "e": "🛬",
+ "d": "airplane arriving",
+ "u": "7.0"
+ },
+ "airplane_departure": {
+ "c": "travel",
+ "e": "🛫",
+ "d": "airplane departure",
+ "u": "7.0"
+ },
+ "airplane_small": {
+ "c": "travel",
+ "e": "🛩",
+ "d": "small airplane",
+ "u": "7.0"
+ },
+ "alarm_clock": {
+ "c": "objects",
+ "e": "â°",
+ "d": "alarm clock",
+ "u": "6.0"
+ },
+ "alembic": {
+ "c": "objects",
+ "e": "âš—",
+ "d": "alembic",
+ "u": "4.1"
+ },
+ "alien": {
+ "c": "people",
+ "e": "👽",
+ "d": "extraterrestrial alien",
+ "u": "6.0"
+ },
+ "ambulance": {
+ "c": "travel",
+ "e": "🚑",
+ "d": "ambulance",
+ "u": "6.0"
+ },
+ "amphora": {
+ "c": "objects",
+ "e": "ðŸº",
+ "d": "amphora",
+ "u": "8.0"
+ },
+ "anchor": {
+ "c": "travel",
+ "e": "âš“",
+ "d": "anchor",
+ "u": "4.1"
+ },
+ "angel": {
+ "c": "people",
+ "e": "👼",
+ "d": "baby angel",
+ "u": "6.0"
+ },
+ "angel_tone1": {
+ "c": "people",
+ "e": "👼ðŸ»",
+ "d": "baby angel tone 1",
+ "u": "8.0"
+ },
+ "angel_tone2": {
+ "c": "people",
+ "e": "👼ðŸ¼",
+ "d": "baby angel tone 2",
+ "u": "8.0"
+ },
+ "angel_tone3": {
+ "c": "people",
+ "e": "👼ðŸ½",
+ "d": "baby angel tone 3",
+ "u": "8.0"
+ },
+ "angel_tone4": {
+ "c": "people",
+ "e": "👼ðŸ¾",
+ "d": "baby angel tone 4",
+ "u": "8.0"
+ },
+ "angel_tone5": {
+ "c": "people",
+ "e": "👼ðŸ¿",
+ "d": "baby angel tone 5",
+ "u": "8.0"
+ },
+ "anger": {
+ "c": "symbols",
+ "e": "💢",
+ "d": "anger symbol",
+ "u": "6.0"
+ },
+ "anger_right": {
+ "c": "symbols",
+ "e": "🗯",
+ "d": "right anger bubble",
+ "u": "7.0"
+ },
+ "angry": {
+ "c": "people",
+ "e": "😠",
+ "d": "angry face",
+ "u": "6.0"
+ },
+ "anguished": {
+ "c": "people",
+ "e": "😧",
+ "d": "anguished face",
+ "u": "6.1"
+ },
+ "ant": {
+ "c": "nature",
+ "e": "ðŸœ",
+ "d": "ant",
+ "u": "6.0"
+ },
+ "apple": {
+ "c": "food",
+ "e": "ðŸŽ",
+ "d": "red apple",
+ "u": "6.0"
+ },
+ "aquarius": {
+ "c": "symbols",
+ "e": "â™’",
+ "d": "aquarius",
+ "u": "1.1"
+ },
+ "aries": {
+ "c": "symbols",
+ "e": "♈",
+ "d": "aries",
+ "u": "1.1"
+ },
+ "arrow_backward": {
+ "c": "symbols",
+ "e": "â—€",
+ "d": "black left-pointing triangle",
+ "u": "1.1"
+ },
+ "arrow_double_down": {
+ "c": "symbols",
+ "e": "â¬",
+ "d": "black down-pointing double triangle",
+ "u": "6.0"
+ },
+ "arrow_double_up": {
+ "c": "symbols",
+ "e": "â«",
+ "d": "black up-pointing double triangle",
+ "u": "6.0"
+ },
+ "arrow_down": {
+ "c": "symbols",
+ "e": "⬇",
+ "d": "downwards black arrow",
+ "u": "4.0"
+ },
+ "arrow_down_small": {
+ "c": "symbols",
+ "e": "🔽",
+ "d": "down-pointing small red triangle",
+ "u": "6.0"
+ },
+ "arrow_forward": {
+ "c": "symbols",
+ "e": "â–¶",
+ "d": "black right-pointing triangle",
+ "u": "1.1"
+ },
+ "arrow_heading_down": {
+ "c": "symbols",
+ "e": "⤵",
+ "d": "arrow pointing rightwards then curving downwards",
+ "u": "3.2"
+ },
+ "arrow_heading_up": {
+ "c": "symbols",
+ "e": "⤴",
+ "d": "arrow pointing rightwards then curving upwards",
+ "u": "3.2"
+ },
+ "arrow_left": {
+ "c": "symbols",
+ "e": "⬅",
+ "d": "leftwards black arrow",
+ "u": "4.0"
+ },
+ "arrow_lower_left": {
+ "c": "symbols",
+ "e": "↙",
+ "d": "south west arrow",
+ "u": "1.1"
+ },
+ "arrow_lower_right": {
+ "c": "symbols",
+ "e": "↘",
+ "d": "south east arrow",
+ "u": "1.1"
+ },
+ "arrow_right": {
+ "c": "symbols",
+ "e": "âž¡",
+ "d": "black rightwards arrow",
+ "u": "1.1"
+ },
+ "arrow_right_hook": {
+ "c": "symbols",
+ "e": "↪",
+ "d": "rightwards arrow with hook",
+ "u": "1.1"
+ },
+ "arrow_up": {
+ "c": "symbols",
+ "e": "⬆",
+ "d": "upwards black arrow",
+ "u": "4.0"
+ },
+ "arrow_up_down": {
+ "c": "symbols",
+ "e": "↕",
+ "d": "up down arrow",
+ "u": "1.1"
+ },
+ "arrow_up_small": {
+ "c": "symbols",
+ "e": "🔼",
+ "d": "up-pointing small red triangle",
+ "u": "6.0"
+ },
+ "arrow_upper_left": {
+ "c": "symbols",
+ "e": "↖",
+ "d": "north west arrow",
+ "u": "1.1"
+ },
+ "arrow_upper_right": {
+ "c": "symbols",
+ "e": "↗",
+ "d": "north east arrow",
+ "u": "1.1"
+ },
+ "arrows_clockwise": {
+ "c": "symbols",
+ "e": "🔃",
+ "d": "clockwise downwards and upwards open circle arrows",
+ "u": "6.0"
+ },
+ "arrows_counterclockwise": {
+ "c": "symbols",
+ "e": "🔄",
+ "d": "anticlockwise downwards and upwards open circle ar",
+ "u": "6.0"
+ },
+ "art": {
+ "c": "activity",
+ "e": "🎨",
+ "d": "artist palette",
+ "u": "6.0"
+ },
+ "articulated_lorry": {
+ "c": "travel",
+ "e": "🚛",
+ "d": "articulated lorry",
+ "u": "6.0"
+ },
+ "asterisk": {
+ "c": "symbols",
+ "e": "*⃣",
+ "d": "keycap asterisk",
+ "u": "3.0"
+ },
+ "astonished": {
+ "c": "people",
+ "e": "😲",
+ "d": "astonished face",
+ "u": "6.0"
+ },
+ "athletic_shoe": {
+ "c": "people",
+ "e": "👟",
+ "d": "athletic shoe",
+ "u": "6.0"
+ },
+ "atm": {
+ "c": "symbols",
+ "e": "ðŸ§",
+ "d": "automated teller machine",
+ "u": "6.0"
+ },
+ "atom": {
+ "c": "symbols",
+ "e": "âš›",
+ "d": "atom symbol",
+ "u": "4.1"
+ },
+ "avocado": {
+ "c": "food",
+ "e": "🥑",
+ "d": "avocado",
+ "u": "9.0"
+ },
+ "b": {
+ "c": "symbols",
+ "e": "🅱",
+ "d": "negative squared latin capital letter b",
+ "u": "6.0"
+ },
+ "baby": {
+ "c": "people",
+ "e": "👶",
+ "d": "baby",
+ "u": "6.0"
+ },
+ "baby_bottle": {
+ "c": "food",
+ "e": "ðŸ¼",
+ "d": "baby bottle",
+ "u": "6.0"
+ },
+ "baby_chick": {
+ "c": "nature",
+ "e": "ðŸ¤",
+ "d": "baby chick",
+ "u": "6.0"
+ },
+ "baby_symbol": {
+ "c": "symbols",
+ "e": "🚼",
+ "d": "baby symbol",
+ "u": "6.0"
+ },
+ "baby_tone1": {
+ "c": "people",
+ "e": "👶ðŸ»",
+ "d": "baby tone 1",
+ "u": "8.0"
+ },
+ "baby_tone2": {
+ "c": "people",
+ "e": "👶ðŸ¼",
+ "d": "baby tone 2",
+ "u": "8.0"
+ },
+ "baby_tone3": {
+ "c": "people",
+ "e": "👶ðŸ½",
+ "d": "baby tone 3",
+ "u": "8.0"
+ },
+ "baby_tone4": {
+ "c": "people",
+ "e": "👶ðŸ¾",
+ "d": "baby tone 4",
+ "u": "8.0"
+ },
+ "baby_tone5": {
+ "c": "people",
+ "e": "👶ðŸ¿",
+ "d": "baby tone 5",
+ "u": "8.0"
+ },
+ "back": {
+ "c": "symbols",
+ "e": "🔙",
+ "d": "back with leftwards arrow above",
+ "u": "6.0"
+ },
+ "bacon": {
+ "c": "food",
+ "e": "🥓",
+ "d": "bacon",
+ "u": "9.0"
+ },
+ "badminton": {
+ "c": "activity",
+ "e": "ðŸ¸",
+ "d": "badminton racquet",
+ "u": "8.0"
+ },
+ "baggage_claim": {
+ "c": "symbols",
+ "e": "🛄",
+ "d": "baggage claim",
+ "u": "6.0"
+ },
+ "balloon": {
+ "c": "objects",
+ "e": "🎈",
+ "d": "balloon",
+ "u": "6.0"
+ },
+ "ballot_box": {
+ "c": "objects",
+ "e": "🗳",
+ "d": "ballot box with ballot",
+ "u": "7.0"
+ },
+ "ballot_box_with_check": {
+ "c": "symbols",
+ "e": "☑",
+ "d": "ballot box with check",
+ "u": "1.1"
+ },
+ "bamboo": {
+ "c": "nature",
+ "e": "ðŸŽ",
+ "d": "pine decoration",
+ "u": "6.0"
+ },
+ "banana": {
+ "c": "food",
+ "e": "ðŸŒ",
+ "d": "banana",
+ "u": "6.0"
+ },
+ "bangbang": {
+ "c": "symbols",
+ "e": "‼",
+ "d": "double exclamation mark",
+ "u": "1.1"
+ },
+ "bank": {
+ "c": "travel",
+ "e": "ðŸ¦",
+ "d": "bank",
+ "u": "6.0"
+ },
+ "bar_chart": {
+ "c": "objects",
+ "e": "📊",
+ "d": "bar chart",
+ "u": "6.0"
+ },
+ "barber": {
+ "c": "objects",
+ "e": "💈",
+ "d": "barber pole",
+ "u": "6.0"
+ },
+ "baseball": {
+ "c": "activity",
+ "e": "âš¾",
+ "d": "baseball",
+ "u": "5.2"
+ },
+ "basketball": {
+ "c": "activity",
+ "e": "ðŸ€",
+ "d": "basketball and hoop",
+ "u": "6.0"
+ },
+ "basketball_player": {
+ "c": "activity",
+ "e": "⛹",
+ "d": "person with ball",
+ "u": "5.2"
+ },
+ "basketball_player_tone1": {
+ "c": "activity",
+ "e": "⛹ðŸ»",
+ "d": "person with ball tone 1",
+ "u": "8.0"
+ },
+ "basketball_player_tone2": {
+ "c": "activity",
+ "e": "⛹ðŸ¼",
+ "d": "person with ball tone 2",
+ "u": "8.0"
+ },
+ "basketball_player_tone3": {
+ "c": "activity",
+ "e": "⛹ðŸ½",
+ "d": "person with ball tone 3",
+ "u": "8.0"
+ },
+ "basketball_player_tone4": {
+ "c": "activity",
+ "e": "⛹ðŸ¾",
+ "d": "person with ball tone 4",
+ "u": "8.0"
+ },
+ "basketball_player_tone5": {
+ "c": "activity",
+ "e": "⛹ðŸ¿",
+ "d": "person with ball tone 5",
+ "u": "8.0"
+ },
+ "bat": {
+ "c": "nature",
+ "e": "🦇",
+ "d": "bat",
+ "u": "9.0"
+ },
+ "bath": {
+ "c": "activity",
+ "e": "🛀",
+ "d": "bath",
+ "u": "6.0"
+ },
+ "bath_tone1": {
+ "c": "activity",
+ "e": "🛀ðŸ»",
+ "d": "bath tone 1",
+ "u": "8.0"
+ },
+ "bath_tone2": {
+ "c": "activity",
+ "e": "🛀ðŸ¼",
+ "d": "bath tone 2",
+ "u": "8.0"
+ },
+ "bath_tone3": {
+ "c": "activity",
+ "e": "🛀ðŸ½",
+ "d": "bath tone 3",
+ "u": "8.0"
+ },
+ "bath_tone4": {
+ "c": "activity",
+ "e": "🛀ðŸ¾",
+ "d": "bath tone 4",
+ "u": "8.0"
+ },
+ "bath_tone5": {
+ "c": "activity",
+ "e": "🛀ðŸ¿",
+ "d": "bath tone 5",
+ "u": "8.0"
+ },
+ "bathtub": {
+ "c": "objects",
+ "e": "ðŸ›",
+ "d": "bathtub",
+ "u": "6.0"
+ },
+ "battery": {
+ "c": "objects",
+ "e": "🔋",
+ "d": "battery",
+ "u": "6.0"
+ },
+ "beach": {
+ "c": "travel",
+ "e": "ðŸ–",
+ "d": "beach with umbrella",
+ "u": "7.0"
+ },
+ "beach_umbrella": {
+ "c": "objects",
+ "e": "â›±",
+ "d": "umbrella on ground",
+ "u": "5.2"
+ },
+ "bear": {
+ "c": "nature",
+ "e": "ðŸ»",
+ "d": "bear face",
+ "u": "6.0"
+ },
+ "bed": {
+ "c": "objects",
+ "e": "ðŸ›",
+ "d": "bed",
+ "u": "7.0"
+ },
+ "bee": {
+ "c": "nature",
+ "e": "ðŸ",
+ "d": "honeybee",
+ "u": "6.0"
+ },
+ "beer": {
+ "c": "food",
+ "e": "ðŸº",
+ "d": "beer mug",
+ "u": "6.0"
+ },
+ "beers": {
+ "c": "food",
+ "e": "ðŸ»",
+ "d": "clinking beer mugs",
+ "u": "6.0"
+ },
+ "beetle": {
+ "c": "nature",
+ "e": "ðŸž",
+ "d": "lady beetle",
+ "u": "6.0"
+ },
+ "beginner": {
+ "c": "symbols",
+ "e": "🔰",
+ "d": "japanese symbol for beginner",
+ "u": "6.0"
+ },
+ "bell": {
+ "c": "symbols",
+ "e": "🔔",
+ "d": "bell",
+ "u": "6.0"
+ },
+ "bellhop": {
+ "c": "objects",
+ "e": "🛎",
+ "d": "bellhop bell",
+ "u": "7.0"
+ },
+ "bento": {
+ "c": "food",
+ "e": "ðŸ±",
+ "d": "bento box",
+ "u": "6.0"
+ },
+ "bicyclist": {
+ "c": "activity",
+ "e": "🚴",
+ "d": "bicyclist",
+ "u": "6.0"
+ },
+ "bicyclist_tone1": {
+ "c": "activity",
+ "e": "🚴ðŸ»",
+ "d": "bicyclist tone 1",
+ "u": "8.0"
+ },
+ "bicyclist_tone2": {
+ "c": "activity",
+ "e": "🚴ðŸ¼",
+ "d": "bicyclist tone 2",
+ "u": "8.0"
+ },
+ "bicyclist_tone3": {
+ "c": "activity",
+ "e": "🚴ðŸ½",
+ "d": "bicyclist tone 3",
+ "u": "8.0"
+ },
+ "bicyclist_tone4": {
+ "c": "activity",
+ "e": "🚴ðŸ¾",
+ "d": "bicyclist tone 4",
+ "u": "8.0"
+ },
+ "bicyclist_tone5": {
+ "c": "activity",
+ "e": "🚴ðŸ¿",
+ "d": "bicyclist tone 5",
+ "u": "8.0"
+ },
+ "bike": {
+ "c": "travel",
+ "e": "🚲",
+ "d": "bicycle",
+ "u": "6.0"
+ },
+ "bikini": {
+ "c": "people",
+ "e": "👙",
+ "d": "bikini",
+ "u": "6.0"
+ },
+ "biohazard": {
+ "c": "symbols",
+ "e": "☣",
+ "d": "biohazard sign",
+ "u": "1.1"
+ },
+ "bird": {
+ "c": "nature",
+ "e": "ðŸ¦",
+ "d": "bird",
+ "u": "6.0"
+ },
+ "birthday": {
+ "c": "food",
+ "e": "🎂",
+ "d": "birthday cake",
+ "u": "6.0"
+ },
+ "black_circle": {
+ "c": "symbols",
+ "e": "âš«",
+ "d": "medium black circle",
+ "u": "4.1"
+ },
+ "black_heart": {
+ "c": "symbols",
+ "e": "🖤",
+ "d": "black heart",
+ "u": "9.0"
+ },
+ "black_joker": {
+ "c": "symbols",
+ "e": "ðŸƒ",
+ "d": "playing card black joker",
+ "u": "6.0"
+ },
+ "black_large_square": {
+ "c": "symbols",
+ "e": "⬛",
+ "d": "black large square",
+ "u": "5.1"
+ },
+ "black_medium_small_square": {
+ "c": "symbols",
+ "e": "â—¾",
+ "d": "black medium small square",
+ "u": "3.2"
+ },
+ "black_medium_square": {
+ "c": "symbols",
+ "e": "â—¼",
+ "d": "black medium square",
+ "u": "3.2"
+ },
+ "black_nib": {
+ "c": "objects",
+ "e": "✒",
+ "d": "black nib",
+ "u": "1.1"
+ },
+ "black_small_square": {
+ "c": "symbols",
+ "e": "â–ª",
+ "d": "black small square",
+ "u": "1.1"
+ },
+ "black_square_button": {
+ "c": "symbols",
+ "e": "🔲",
+ "d": "black square button",
+ "u": "6.0"
+ },
+ "blossom": {
+ "c": "nature",
+ "e": "🌼",
+ "d": "blossom",
+ "u": "6.0"
+ },
+ "blowfish": {
+ "c": "nature",
+ "e": "ðŸ¡",
+ "d": "blowfish",
+ "u": "6.0"
+ },
+ "blue_book": {
+ "c": "objects",
+ "e": "📘",
+ "d": "blue book",
+ "u": "6.0"
+ },
+ "blue_car": {
+ "c": "travel",
+ "e": "🚙",
+ "d": "recreational vehicle",
+ "u": "6.0"
+ },
+ "blue_heart": {
+ "c": "symbols",
+ "e": "💙",
+ "d": "blue heart",
+ "u": "6.0"
+ },
+ "blush": {
+ "c": "people",
+ "e": "😊",
+ "d": "smiling face with smiling eyes",
+ "u": "6.0"
+ },
+ "boar": {
+ "c": "nature",
+ "e": "ðŸ—",
+ "d": "boar",
+ "u": "6.0"
+ },
+ "bomb": {
+ "c": "objects",
+ "e": "💣",
+ "d": "bomb",
+ "u": "6.0"
+ },
+ "book": {
+ "c": "objects",
+ "e": "📖",
+ "d": "open book",
+ "u": "6.0"
+ },
+ "bookmark": {
+ "c": "objects",
+ "e": "🔖",
+ "d": "bookmark",
+ "u": "6.0"
+ },
+ "bookmark_tabs": {
+ "c": "objects",
+ "e": "📑",
+ "d": "bookmark tabs",
+ "u": "6.0"
+ },
+ "books": {
+ "c": "objects",
+ "e": "📚",
+ "d": "books",
+ "u": "6.0"
+ },
+ "boom": {
+ "c": "nature",
+ "e": "💥",
+ "d": "collision symbol",
+ "u": "6.0"
+ },
+ "boot": {
+ "c": "people",
+ "e": "👢",
+ "d": "womans boots",
+ "u": "6.0"
+ },
+ "bouquet": {
+ "c": "nature",
+ "e": "ðŸ’",
+ "d": "bouquet",
+ "u": "6.0"
+ },
+ "bow": {
+ "c": "people",
+ "e": "🙇",
+ "d": "person bowing deeply",
+ "u": "6.0"
+ },
+ "bow_and_arrow": {
+ "c": "activity",
+ "e": "ðŸ¹",
+ "d": "bow and arrow",
+ "u": "8.0"
+ },
+ "bow_tone1": {
+ "c": "people",
+ "e": "🙇ðŸ»",
+ "d": "person bowing deeply tone 1",
+ "u": "8.0"
+ },
+ "bow_tone2": {
+ "c": "people",
+ "e": "🙇ðŸ¼",
+ "d": "person bowing deeply tone 2",
+ "u": "8.0"
+ },
+ "bow_tone3": {
+ "c": "people",
+ "e": "🙇ðŸ½",
+ "d": "person bowing deeply tone 3",
+ "u": "8.0"
+ },
+ "bow_tone4": {
+ "c": "people",
+ "e": "🙇ðŸ¾",
+ "d": "person bowing deeply tone 4",
+ "u": "8.0"
+ },
+ "bow_tone5": {
+ "c": "people",
+ "e": "🙇ðŸ¿",
+ "d": "person bowing deeply tone 5",
+ "u": "8.0"
+ },
+ "bowling": {
+ "c": "activity",
+ "e": "🎳",
+ "d": "bowling",
+ "u": "6.0"
+ },
+ "boxing_glove": {
+ "c": "activity",
+ "e": "🥊",
+ "d": "boxing glove",
+ "u": "9.0"
+ },
+ "boy": {
+ "c": "people",
+ "e": "👦",
+ "d": "boy",
+ "u": "6.0"
+ },
+ "boy_tone1": {
+ "c": "people",
+ "e": "👦ðŸ»",
+ "d": "boy tone 1",
+ "u": "8.0"
+ },
+ "boy_tone2": {
+ "c": "people",
+ "e": "👦ðŸ¼",
+ "d": "boy tone 2",
+ "u": "8.0"
+ },
+ "boy_tone3": {
+ "c": "people",
+ "e": "👦ðŸ½",
+ "d": "boy tone 3",
+ "u": "8.0"
+ },
+ "boy_tone4": {
+ "c": "people",
+ "e": "👦ðŸ¾",
+ "d": "boy tone 4",
+ "u": "8.0"
+ },
+ "boy_tone5": {
+ "c": "people",
+ "e": "👦ðŸ¿",
+ "d": "boy tone 5",
+ "u": "8.0"
+ },
+ "bread": {
+ "c": "food",
+ "e": "ðŸž",
+ "d": "bread",
+ "u": "6.0"
+ },
+ "bride_with_veil": {
+ "c": "people",
+ "e": "👰",
+ "d": "bride with veil",
+ "u": "6.0"
+ },
+ "bride_with_veil_tone1": {
+ "c": "people",
+ "e": "👰ðŸ»",
+ "d": "bride with veil tone 1",
+ "u": "8.0"
+ },
+ "bride_with_veil_tone2": {
+ "c": "people",
+ "e": "👰ðŸ¼",
+ "d": "bride with veil tone 2",
+ "u": "8.0"
+ },
+ "bride_with_veil_tone3": {
+ "c": "people",
+ "e": "👰ðŸ½",
+ "d": "bride with veil tone 3",
+ "u": "8.0"
+ },
+ "bride_with_veil_tone4": {
+ "c": "people",
+ "e": "👰ðŸ¾",
+ "d": "bride with veil tone 4",
+ "u": "8.0"
+ },
+ "bride_with_veil_tone5": {
+ "c": "people",
+ "e": "👰ðŸ¿",
+ "d": "bride with veil tone 5",
+ "u": "8.0"
+ },
+ "bridge_at_night": {
+ "c": "travel",
+ "e": "🌉",
+ "d": "bridge at night",
+ "u": "6.0"
+ },
+ "briefcase": {
+ "c": "people",
+ "e": "💼",
+ "d": "briefcase",
+ "u": "6.0"
+ },
+ "broken_heart": {
+ "c": "symbols",
+ "e": "💔",
+ "d": "broken heart",
+ "u": "6.0"
+ },
+ "bug": {
+ "c": "nature",
+ "e": "ðŸ›",
+ "d": "bug",
+ "u": "6.0"
+ },
+ "bulb": {
+ "c": "objects",
+ "e": "💡",
+ "d": "electric light bulb",
+ "u": "6.0"
+ },
+ "bullettrain_front": {
+ "c": "travel",
+ "e": "🚅",
+ "d": "high-speed train with bullet nose",
+ "u": "6.0"
+ },
+ "bullettrain_side": {
+ "c": "travel",
+ "e": "🚄",
+ "d": "high-speed train",
+ "u": "6.0"
+ },
+ "burrito": {
+ "c": "food",
+ "e": "🌯",
+ "d": "burrito",
+ "u": "8.0"
+ },
+ "bus": {
+ "c": "travel",
+ "e": "🚌",
+ "d": "bus",
+ "u": "6.0"
+ },
+ "busstop": {
+ "c": "travel",
+ "e": "ðŸš",
+ "d": "bus stop",
+ "u": "6.0"
+ },
+ "bust_in_silhouette": {
+ "c": "people",
+ "e": "👤",
+ "d": "bust in silhouette",
+ "u": "6.0"
+ },
+ "busts_in_silhouette": {
+ "c": "people",
+ "e": "👥",
+ "d": "busts in silhouette",
+ "u": "6.0"
+ },
+ "butterfly": {
+ "c": "nature",
+ "e": "🦋",
+ "d": "butterfly",
+ "u": "9.0"
+ },
+ "cactus": {
+ "c": "nature",
+ "e": "🌵",
+ "d": "cactus",
+ "u": "6.0"
+ },
+ "cake": {
+ "c": "food",
+ "e": "ðŸ°",
+ "d": "shortcake",
+ "u": "6.0"
+ },
+ "calendar": {
+ "c": "objects",
+ "e": "📆",
+ "d": "tear-off calendar",
+ "u": "6.0"
+ },
+ "calendar_spiral": {
+ "c": "objects",
+ "e": "🗓",
+ "d": "spiral calendar pad",
+ "u": "7.0"
+ },
+ "call_me": {
+ "c": "people",
+ "e": "🤙",
+ "d": "call me hand",
+ "u": "9.0"
+ },
+ "call_me_tone1": {
+ "c": "people",
+ "e": "🤙ðŸ»",
+ "d": "call me hand tone 1",
+ "u": "9.0"
+ },
+ "call_me_tone2": {
+ "c": "people",
+ "e": "🤙ðŸ¼",
+ "d": "call me hand tone 2",
+ "u": "9.0"
+ },
+ "call_me_tone3": {
+ "c": "people",
+ "e": "🤙ðŸ½",
+ "d": "call me hand tone 3",
+ "u": "9.0"
+ },
+ "call_me_tone4": {
+ "c": "people",
+ "e": "🤙ðŸ¾",
+ "d": "call me hand tone 4",
+ "u": "9.0"
+ },
+ "call_me_tone5": {
+ "c": "people",
+ "e": "🤙ðŸ¿",
+ "d": "call me hand tone 5",
+ "u": "9.0"
+ },
+ "calling": {
+ "c": "objects",
+ "e": "📲",
+ "d": "mobile phone with rightwards arrow at left",
+ "u": "6.0"
+ },
+ "camel": {
+ "c": "nature",
+ "e": "ðŸ«",
+ "d": "bactrian camel",
+ "u": "6.0"
+ },
+ "camera": {
+ "c": "objects",
+ "e": "📷",
+ "d": "camera",
+ "u": "6.0"
+ },
+ "camera_with_flash": {
+ "c": "objects",
+ "e": "📸",
+ "d": "camera with flash",
+ "u": "7.0"
+ },
+ "camping": {
+ "c": "travel",
+ "e": "ðŸ•",
+ "d": "camping",
+ "u": "7.0"
+ },
+ "cancer": {
+ "c": "symbols",
+ "e": "♋",
+ "d": "cancer",
+ "u": "1.1"
+ },
+ "candle": {
+ "c": "objects",
+ "e": "🕯",
+ "d": "candle",
+ "u": "7.0"
+ },
+ "candy": {
+ "c": "food",
+ "e": "ðŸ¬",
+ "d": "candy",
+ "u": "6.0"
+ },
+ "canoe": {
+ "c": "travel",
+ "e": "🛶",
+ "d": "canoe",
+ "u": "9.0"
+ },
+ "capital_abcd": {
+ "c": "symbols",
+ "e": "🔠",
+ "d": "input symbol for latin capital letters",
+ "u": "6.0"
+ },
+ "capricorn": {
+ "c": "symbols",
+ "e": "♑",
+ "d": "capricorn",
+ "u": "1.1"
+ },
+ "card_box": {
+ "c": "objects",
+ "e": "🗃",
+ "d": "card file box",
+ "u": "7.0"
+ },
+ "card_index": {
+ "c": "objects",
+ "e": "📇",
+ "d": "card index",
+ "u": "6.0"
+ },
+ "carousel_horse": {
+ "c": "travel",
+ "e": "🎠",
+ "d": "carousel horse",
+ "u": "6.0"
+ },
+ "carrot": {
+ "c": "food",
+ "e": "🥕",
+ "d": "carrot",
+ "u": "9.0"
+ },
+ "cartwheel": {
+ "c": "activity",
+ "e": "🤸",
+ "d": "person doing cartwheel",
+ "u": "9.0"
+ },
+ "cartwheel_tone1": {
+ "c": "activity",
+ "e": "🤸ðŸ»",
+ "d": "person doing cartwheel tone 1",
+ "u": "9.0"
+ },
+ "cartwheel_tone2": {
+ "c": "activity",
+ "e": "🤸ðŸ¼",
+ "d": "person doing cartwheel tone 2",
+ "u": "9.0"
+ },
+ "cartwheel_tone3": {
+ "c": "activity",
+ "e": "🤸ðŸ½",
+ "d": "person doing cartwheel tone 3",
+ "u": "9.0"
+ },
+ "cartwheel_tone4": {
+ "c": "activity",
+ "e": "🤸ðŸ¾",
+ "d": "person doing cartwheel tone 4",
+ "u": "9.0"
+ },
+ "cartwheel_tone5": {
+ "c": "activity",
+ "e": "🤸ðŸ¿",
+ "d": "person doing cartwheel tone 5",
+ "u": "9.0"
+ },
+ "cat": {
+ "c": "nature",
+ "e": "ðŸ±",
+ "d": "cat face",
+ "u": "6.0"
+ },
+ "cat2": {
+ "c": "nature",
+ "e": "ðŸˆ",
+ "d": "cat",
+ "u": "6.0"
+ },
+ "cd": {
+ "c": "objects",
+ "e": "💿",
+ "d": "optical disc",
+ "u": "6.0"
+ },
+ "chains": {
+ "c": "objects",
+ "e": "⛓",
+ "d": "chains",
+ "u": "5.2"
+ },
+ "champagne": {
+ "c": "food",
+ "e": "ðŸ¾",
+ "d": "bottle with popping cork",
+ "u": "8.0"
+ },
+ "champagne_glass": {
+ "c": "food",
+ "e": "🥂",
+ "d": "clinking glasses",
+ "u": "9.0"
+ },
+ "chart": {
+ "c": "symbols",
+ "e": "💹",
+ "d": "chart with upwards trend and yen sign",
+ "u": "6.0"
+ },
+ "chart_with_downwards_trend": {
+ "c": "objects",
+ "e": "📉",
+ "d": "chart with downwards trend",
+ "u": "6.0"
+ },
+ "chart_with_upwards_trend": {
+ "c": "objects",
+ "e": "📈",
+ "d": "chart with upwards trend",
+ "u": "6.0"
+ },
+ "checkered_flag": {
+ "c": "travel",
+ "e": "ðŸ",
+ "d": "chequered flag",
+ "u": "6.0"
+ },
+ "cheese": {
+ "c": "food",
+ "e": "🧀",
+ "d": "cheese wedge",
+ "u": "8.0"
+ },
+ "cherries": {
+ "c": "food",
+ "e": "ðŸ’",
+ "d": "cherries",
+ "u": "6.0"
+ },
+ "cherry_blossom": {
+ "c": "nature",
+ "e": "🌸",
+ "d": "cherry blossom",
+ "u": "6.0"
+ },
+ "chestnut": {
+ "c": "nature",
+ "e": "🌰",
+ "d": "chestnut",
+ "u": "6.0"
+ },
+ "chicken": {
+ "c": "nature",
+ "e": "ðŸ”",
+ "d": "chicken",
+ "u": "6.0"
+ },
+ "children_crossing": {
+ "c": "symbols",
+ "e": "🚸",
+ "d": "children crossing",
+ "u": "6.0"
+ },
+ "chipmunk": {
+ "c": "nature",
+ "e": "ðŸ¿",
+ "d": "chipmunk",
+ "u": "7.0"
+ },
+ "chocolate_bar": {
+ "c": "food",
+ "e": "ðŸ«",
+ "d": "chocolate bar",
+ "u": "6.0"
+ },
+ "christmas_tree": {
+ "c": "nature",
+ "e": "🎄",
+ "d": "christmas tree",
+ "u": "6.0"
+ },
+ "church": {
+ "c": "travel",
+ "e": "⛪",
+ "d": "church",
+ "u": "5.2"
+ },
+ "cinema": {
+ "c": "symbols",
+ "e": "🎦",
+ "d": "cinema",
+ "u": "6.0"
+ },
+ "circus_tent": {
+ "c": "activity",
+ "e": "🎪",
+ "d": "circus tent",
+ "u": "6.0"
+ },
+ "city_dusk": {
+ "c": "travel",
+ "e": "🌆",
+ "d": "cityscape at dusk",
+ "u": "6.0"
+ },
+ "city_sunset": {
+ "c": "travel",
+ "e": "🌇",
+ "d": "sunset over buildings",
+ "u": "6.0"
+ },
+ "cityscape": {
+ "c": "travel",
+ "e": "ðŸ™",
+ "d": "cityscape",
+ "u": "7.0"
+ },
+ "cl": {
+ "c": "symbols",
+ "e": "🆑",
+ "d": "squared cl",
+ "u": "6.0"
+ },
+ "clap": {
+ "c": "people",
+ "e": "ðŸ‘",
+ "d": "clapping hands sign",
+ "u": "6.0"
+ },
+ "clap_tone1": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ»",
+ "d": "clapping hands sign tone 1",
+ "u": "8.0"
+ },
+ "clap_tone2": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¼",
+ "d": "clapping hands sign tone 2",
+ "u": "8.0"
+ },
+ "clap_tone3": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ½",
+ "d": "clapping hands sign tone 3",
+ "u": "8.0"
+ },
+ "clap_tone4": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¾",
+ "d": "clapping hands sign tone 4",
+ "u": "8.0"
+ },
+ "clap_tone5": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¿",
+ "d": "clapping hands sign tone 5",
+ "u": "8.0"
+ },
+ "clapper": {
+ "c": "activity",
+ "e": "🎬",
+ "d": "clapper board",
+ "u": "6.0"
+ },
+ "classical_building": {
+ "c": "travel",
+ "e": "ðŸ›",
+ "d": "classical building",
+ "u": "7.0"
+ },
+ "clipboard": {
+ "c": "objects",
+ "e": "📋",
+ "d": "clipboard",
+ "u": "6.0"
+ },
+ "clock": {
+ "c": "objects",
+ "e": "🕰",
+ "d": "mantlepiece clock",
+ "u": "7.0"
+ },
+ "clock1": {
+ "c": "symbols",
+ "e": "ðŸ•",
+ "d": "clock face one oclock",
+ "u": "6.0"
+ },
+ "clock10": {
+ "c": "symbols",
+ "e": "🕙",
+ "d": "clock face ten oclock",
+ "u": "6.0"
+ },
+ "clock1030": {
+ "c": "symbols",
+ "e": "🕥",
+ "d": "clock face ten-thirty",
+ "u": "6.0"
+ },
+ "clock11": {
+ "c": "symbols",
+ "e": "🕚",
+ "d": "clock face eleven oclock",
+ "u": "6.0"
+ },
+ "clock1130": {
+ "c": "symbols",
+ "e": "🕦",
+ "d": "clock face eleven-thirty",
+ "u": "6.0"
+ },
+ "clock12": {
+ "c": "symbols",
+ "e": "🕛",
+ "d": "clock face twelve oclock",
+ "u": "6.0"
+ },
+ "clock1230": {
+ "c": "symbols",
+ "e": "🕧",
+ "d": "clock face twelve-thirty",
+ "u": "6.0"
+ },
+ "clock130": {
+ "c": "symbols",
+ "e": "🕜",
+ "d": "clock face one-thirty",
+ "u": "6.0"
+ },
+ "clock2": {
+ "c": "symbols",
+ "e": "🕑",
+ "d": "clock face two oclock",
+ "u": "6.0"
+ },
+ "clock230": {
+ "c": "symbols",
+ "e": "ðŸ•",
+ "d": "clock face two-thirty",
+ "u": "6.0"
+ },
+ "clock3": {
+ "c": "symbols",
+ "e": "🕒",
+ "d": "clock face three oclock",
+ "u": "6.0"
+ },
+ "clock330": {
+ "c": "symbols",
+ "e": "🕞",
+ "d": "clock face three-thirty",
+ "u": "6.0"
+ },
+ "clock4": {
+ "c": "symbols",
+ "e": "🕓",
+ "d": "clock face four oclock",
+ "u": "6.0"
+ },
+ "clock430": {
+ "c": "symbols",
+ "e": "🕟",
+ "d": "clock face four-thirty",
+ "u": "6.0"
+ },
+ "clock5": {
+ "c": "symbols",
+ "e": "🕔",
+ "d": "clock face five oclock",
+ "u": "6.0"
+ },
+ "clock530": {
+ "c": "symbols",
+ "e": "🕠",
+ "d": "clock face five-thirty",
+ "u": "6.0"
+ },
+ "clock6": {
+ "c": "symbols",
+ "e": "🕕",
+ "d": "clock face six oclock",
+ "u": "6.0"
+ },
+ "clock630": {
+ "c": "symbols",
+ "e": "🕡",
+ "d": "clock face six-thirty",
+ "u": "6.0"
+ },
+ "clock7": {
+ "c": "symbols",
+ "e": "🕖",
+ "d": "clock face seven oclock",
+ "u": "6.0"
+ },
+ "clock730": {
+ "c": "symbols",
+ "e": "🕢",
+ "d": "clock face seven-thirty",
+ "u": "6.0"
+ },
+ "clock8": {
+ "c": "symbols",
+ "e": "🕗",
+ "d": "clock face eight oclock",
+ "u": "6.0"
+ },
+ "clock830": {
+ "c": "symbols",
+ "e": "🕣",
+ "d": "clock face eight-thirty",
+ "u": "6.0"
+ },
+ "clock9": {
+ "c": "symbols",
+ "e": "🕘",
+ "d": "clock face nine oclock",
+ "u": "6.0"
+ },
+ "clock930": {
+ "c": "symbols",
+ "e": "🕤",
+ "d": "clock face nine-thirty",
+ "u": "6.0"
+ },
+ "closed_book": {
+ "c": "objects",
+ "e": "📕",
+ "d": "closed book",
+ "u": "6.0"
+ },
+ "closed_lock_with_key": {
+ "c": "objects",
+ "e": "ðŸ”",
+ "d": "closed lock with key",
+ "u": "6.0"
+ },
+ "closed_umbrella": {
+ "c": "people",
+ "e": "🌂",
+ "d": "closed umbrella",
+ "u": "6.0"
+ },
+ "cloud": {
+ "c": "nature",
+ "e": "â˜",
+ "d": "cloud",
+ "u": "1.1"
+ },
+ "cloud_lightning": {
+ "c": "nature",
+ "e": "🌩",
+ "d": "cloud with lightning",
+ "u": "7.0"
+ },
+ "cloud_rain": {
+ "c": "nature",
+ "e": "🌧",
+ "d": "cloud with rain",
+ "u": "7.0"
+ },
+ "cloud_snow": {
+ "c": "nature",
+ "e": "🌨",
+ "d": "cloud with snow",
+ "u": "7.0"
+ },
+ "cloud_tornado": {
+ "c": "nature",
+ "e": "🌪",
+ "d": "cloud with tornado",
+ "u": "7.0"
+ },
+ "clown": {
+ "c": "people",
+ "e": "🤡",
+ "d": "clown face",
+ "u": "9.0"
+ },
+ "clubs": {
+ "c": "symbols",
+ "e": "♣",
+ "d": "black club suit",
+ "u": "1.1"
+ },
+ "cocktail": {
+ "c": "food",
+ "e": "ðŸ¸",
+ "d": "cocktail glass",
+ "u": "6.0"
+ },
+ "coffee": {
+ "c": "food",
+ "e": "☕",
+ "d": "hot beverage",
+ "u": "4.0"
+ },
+ "coffin": {
+ "c": "objects",
+ "e": "âš°",
+ "d": "coffin",
+ "u": "4.1"
+ },
+ "cold_sweat": {
+ "c": "people",
+ "e": "😰",
+ "d": "face with open mouth and cold sweat",
+ "u": "6.0"
+ },
+ "comet": {
+ "c": "nature",
+ "e": "☄",
+ "d": "comet",
+ "u": "1.1"
+ },
+ "compression": {
+ "c": "objects",
+ "e": "🗜",
+ "d": "compression",
+ "u": "7.0"
+ },
+ "computer": {
+ "c": "objects",
+ "e": "💻",
+ "d": "personal computer",
+ "u": "6.0"
+ },
+ "confetti_ball": {
+ "c": "objects",
+ "e": "🎊",
+ "d": "confetti ball",
+ "u": "6.0"
+ },
+ "confounded": {
+ "c": "people",
+ "e": "😖",
+ "d": "confounded face",
+ "u": "6.0"
+ },
+ "confused": {
+ "c": "people",
+ "e": "😕",
+ "d": "confused face",
+ "u": "6.1"
+ },
+ "congratulations": {
+ "c": "symbols",
+ "e": "㊗",
+ "d": "circled ideograph congratulation",
+ "u": "1.1"
+ },
+ "construction": {
+ "c": "travel",
+ "e": "🚧",
+ "d": "construction sign",
+ "u": "6.0"
+ },
+ "construction_site": {
+ "c": "travel",
+ "e": "ðŸ—",
+ "d": "building construction",
+ "u": "7.0"
+ },
+ "construction_worker": {
+ "c": "people",
+ "e": "👷",
+ "d": "construction worker",
+ "u": "6.0"
+ },
+ "construction_worker_tone1": {
+ "c": "people",
+ "e": "👷ðŸ»",
+ "d": "construction worker tone 1",
+ "u": "8.0"
+ },
+ "construction_worker_tone2": {
+ "c": "people",
+ "e": "👷ðŸ¼",
+ "d": "construction worker tone 2",
+ "u": "8.0"
+ },
+ "construction_worker_tone3": {
+ "c": "people",
+ "e": "👷ðŸ½",
+ "d": "construction worker tone 3",
+ "u": "8.0"
+ },
+ "construction_worker_tone4": {
+ "c": "people",
+ "e": "👷ðŸ¾",
+ "d": "construction worker tone 4",
+ "u": "8.0"
+ },
+ "construction_worker_tone5": {
+ "c": "people",
+ "e": "👷ðŸ¿",
+ "d": "construction worker tone 5",
+ "u": "8.0"
+ },
+ "control_knobs": {
+ "c": "objects",
+ "e": "🎛",
+ "d": "control knobs",
+ "u": "7.0"
+ },
+ "convenience_store": {
+ "c": "travel",
+ "e": "ðŸª",
+ "d": "convenience store",
+ "u": "6.0"
+ },
+ "cookie": {
+ "c": "food",
+ "e": "ðŸª",
+ "d": "cookie",
+ "u": "6.0"
+ },
+ "cooking": {
+ "c": "food",
+ "e": "ðŸ³",
+ "d": "cooking",
+ "u": "6.0"
+ },
+ "cool": {
+ "c": "symbols",
+ "e": "🆒",
+ "d": "squared cool",
+ "u": "6.0"
+ },
+ "cop": {
+ "c": "people",
+ "e": "👮",
+ "d": "police officer",
+ "u": "6.0"
+ },
+ "cop_tone1": {
+ "c": "people",
+ "e": "👮ðŸ»",
+ "d": "police officer tone 1",
+ "u": "8.0"
+ },
+ "cop_tone2": {
+ "c": "people",
+ "e": "👮ðŸ¼",
+ "d": "police officer tone 2",
+ "u": "8.0"
+ },
+ "cop_tone3": {
+ "c": "people",
+ "e": "👮ðŸ½",
+ "d": "police officer tone 3",
+ "u": "8.0"
+ },
+ "cop_tone4": {
+ "c": "people",
+ "e": "👮ðŸ¾",
+ "d": "police officer tone 4",
+ "u": "8.0"
+ },
+ "cop_tone5": {
+ "c": "people",
+ "e": "👮ðŸ¿",
+ "d": "police officer tone 5",
+ "u": "8.0"
+ },
+ "copyright": {
+ "c": "symbols",
+ "e": "©ï¸",
+ "d": "copyright sign",
+ "u": "1.1"
+ },
+ "corn": {
+ "c": "food",
+ "e": "🌽",
+ "d": "ear of maize",
+ "u": "6.0"
+ },
+ "couch": {
+ "c": "objects",
+ "e": "🛋",
+ "d": "couch and lamp",
+ "u": "7.0"
+ },
+ "couple": {
+ "c": "people",
+ "e": "👫",
+ "d": "man and woman holding hands",
+ "u": "6.0"
+ },
+ "couple_mm": {
+ "c": "people",
+ "e": "👨â€â¤ï¸â€ðŸ‘¨",
+ "d": "couple (man,man)",
+ "u": "6.0"
+ },
+ "couple_with_heart": {
+ "c": "people",
+ "e": "💑",
+ "d": "couple with heart",
+ "u": "6.0"
+ },
+ "couple_ww": {
+ "c": "people",
+ "e": "👩â€â¤ï¸â€ðŸ‘©",
+ "d": "couple (woman,woman)",
+ "u": "6.0"
+ },
+ "couplekiss": {
+ "c": "people",
+ "e": "ðŸ’",
+ "d": "kiss",
+ "u": "6.0"
+ },
+ "cow": {
+ "c": "nature",
+ "e": "ðŸ®",
+ "d": "cow face",
+ "u": "6.0"
+ },
+ "cow2": {
+ "c": "nature",
+ "e": "ðŸ„",
+ "d": "cow",
+ "u": "6.0"
+ },
+ "cowboy": {
+ "c": "people",
+ "e": "🤠",
+ "d": "face with cowboy hat",
+ "u": "9.0"
+ },
+ "crab": {
+ "c": "nature",
+ "e": "🦀",
+ "d": "crab",
+ "u": "8.0"
+ },
+ "crayon": {
+ "c": "objects",
+ "e": "ðŸ–",
+ "d": "lower left crayon",
+ "u": "7.0"
+ },
+ "credit_card": {
+ "c": "objects",
+ "e": "💳",
+ "d": "credit card",
+ "u": "6.0"
+ },
+ "crescent_moon": {
+ "c": "nature",
+ "e": "🌙",
+ "d": "crescent moon",
+ "u": "6.0"
+ },
+ "cricket": {
+ "c": "activity",
+ "e": "ðŸ",
+ "d": "cricket bat and ball",
+ "u": "10.0"
+ },
+ "crocodile": {
+ "c": "nature",
+ "e": "ðŸŠ",
+ "d": "crocodile",
+ "u": "6.0"
+ },
+ "croissant": {
+ "c": "food",
+ "e": "ðŸ¥",
+ "d": "croissant",
+ "u": "9.0"
+ },
+ "cross": {
+ "c": "symbols",
+ "e": "âœ",
+ "d": "latin cross",
+ "u": "1.1"
+ },
+ "crossed_flags": {
+ "c": "objects",
+ "e": "🎌",
+ "d": "crossed flags",
+ "u": "6.0"
+ },
+ "crossed_swords": {
+ "c": "objects",
+ "e": "âš”",
+ "d": "crossed swords",
+ "u": "4.1"
+ },
+ "crown": {
+ "c": "people",
+ "e": "👑",
+ "d": "crown",
+ "u": "6.0"
+ },
+ "cruise_ship": {
+ "c": "travel",
+ "e": "🛳",
+ "d": "passenger ship",
+ "u": "7.0"
+ },
+ "cry": {
+ "c": "people",
+ "e": "😢",
+ "d": "crying face",
+ "u": "6.0"
+ },
+ "crying_cat_face": {
+ "c": "people",
+ "e": "😿",
+ "d": "crying cat face",
+ "u": "6.0"
+ },
+ "crystal_ball": {
+ "c": "objects",
+ "e": "🔮",
+ "d": "crystal ball",
+ "u": "6.0"
+ },
+ "cucumber": {
+ "c": "food",
+ "e": "🥒",
+ "d": "cucumber",
+ "u": "9.0"
+ },
+ "cupid": {
+ "c": "symbols",
+ "e": "💘",
+ "d": "heart with arrow",
+ "u": "6.0"
+ },
+ "curly_loop": {
+ "c": "symbols",
+ "e": "âž°",
+ "d": "curly loop",
+ "u": "6.0"
+ },
+ "currency_exchange": {
+ "c": "symbols",
+ "e": "💱",
+ "d": "currency exchange",
+ "u": "6.0"
+ },
+ "curry": {
+ "c": "food",
+ "e": "ðŸ›",
+ "d": "curry and rice",
+ "u": "6.0"
+ },
+ "custard": {
+ "c": "food",
+ "e": "ðŸ®",
+ "d": "custard",
+ "u": "6.0"
+ },
+ "customs": {
+ "c": "symbols",
+ "e": "🛃",
+ "d": "customs",
+ "u": "6.0"
+ },
+ "cyclone": {
+ "c": "symbols",
+ "e": "🌀",
+ "d": "cyclone",
+ "u": "6.0"
+ },
+ "dagger": {
+ "c": "objects",
+ "e": "🗡",
+ "d": "dagger knife",
+ "u": "7.0"
+ },
+ "dancer": {
+ "c": "people",
+ "e": "💃",
+ "d": "dancer",
+ "u": "6.0"
+ },
+ "dancer_tone1": {
+ "c": "people",
+ "e": "💃ðŸ»",
+ "d": "dancer tone 1",
+ "u": "8.0"
+ },
+ "dancer_tone2": {
+ "c": "people",
+ "e": "💃ðŸ¼",
+ "d": "dancer tone 2",
+ "u": "8.0"
+ },
+ "dancer_tone3": {
+ "c": "people",
+ "e": "💃ðŸ½",
+ "d": "dancer tone 3",
+ "u": "8.0"
+ },
+ "dancer_tone4": {
+ "c": "people",
+ "e": "💃ðŸ¾",
+ "d": "dancer tone 4",
+ "u": "8.0"
+ },
+ "dancer_tone5": {
+ "c": "people",
+ "e": "💃ðŸ¿",
+ "d": "dancer tone 5",
+ "u": "8.0"
+ },
+ "dancers": {
+ "c": "people",
+ "e": "👯",
+ "d": "woman with bunny ears",
+ "u": "6.0"
+ },
+ "dango": {
+ "c": "food",
+ "e": "ðŸ¡",
+ "d": "dango",
+ "u": "6.0"
+ },
+ "dark_sunglasses": {
+ "c": "people",
+ "e": "🕶",
+ "d": "dark sunglasses",
+ "u": "7.0"
+ },
+ "dart": {
+ "c": "activity",
+ "e": "🎯",
+ "d": "direct hit",
+ "u": "6.0"
+ },
+ "dash": {
+ "c": "nature",
+ "e": "💨",
+ "d": "dash symbol",
+ "u": "6.0"
+ },
+ "date": {
+ "c": "objects",
+ "e": "📅",
+ "d": "calendar",
+ "u": "6.0"
+ },
+ "deciduous_tree": {
+ "c": "nature",
+ "e": "🌳",
+ "d": "deciduous tree",
+ "u": "6.0"
+ },
+ "deer": {
+ "c": "nature",
+ "e": "🦌",
+ "d": "deer",
+ "u": "9.0"
+ },
+ "department_store": {
+ "c": "travel",
+ "e": "ðŸ¬",
+ "d": "department store",
+ "u": "6.0"
+ },
+ "desert": {
+ "c": "travel",
+ "e": "ðŸœ",
+ "d": "desert",
+ "u": "7.0"
+ },
+ "desktop": {
+ "c": "objects",
+ "e": "🖥",
+ "d": "desktop computer",
+ "u": "7.0"
+ },
+ "diamond_shape_with_a_dot_inside": {
+ "c": "symbols",
+ "e": "💠",
+ "d": "diamond shape with a dot inside",
+ "u": "6.0"
+ },
+ "diamonds": {
+ "c": "symbols",
+ "e": "♦",
+ "d": "black diamond suit",
+ "u": "1.1"
+ },
+ "disappointed": {
+ "c": "people",
+ "e": "😞",
+ "d": "disappointed face",
+ "u": "6.0"
+ },
+ "disappointed_relieved": {
+ "c": "people",
+ "e": "😥",
+ "d": "disappointed but relieved face",
+ "u": "6.0"
+ },
+ "dividers": {
+ "c": "objects",
+ "e": "🗂",
+ "d": "card index dividers",
+ "u": "7.0"
+ },
+ "dizzy": {
+ "c": "nature",
+ "e": "💫",
+ "d": "dizzy symbol",
+ "u": "6.0"
+ },
+ "dizzy_face": {
+ "c": "people",
+ "e": "😵",
+ "d": "dizzy face",
+ "u": "6.0"
+ },
+ "do_not_litter": {
+ "c": "symbols",
+ "e": "🚯",
+ "d": "do not litter symbol",
+ "u": "6.0"
+ },
+ "dog": {
+ "c": "nature",
+ "e": "ðŸ¶",
+ "d": "dog face",
+ "u": "6.0"
+ },
+ "dog2": {
+ "c": "nature",
+ "e": "ðŸ•",
+ "d": "dog",
+ "u": "6.0"
+ },
+ "dollar": {
+ "c": "objects",
+ "e": "💵",
+ "d": "banknote with dollar sign",
+ "u": "6.0"
+ },
+ "dolls": {
+ "c": "objects",
+ "e": "🎎",
+ "d": "japanese dolls",
+ "u": "6.0"
+ },
+ "dolphin": {
+ "c": "nature",
+ "e": "ðŸ¬",
+ "d": "dolphin",
+ "u": "6.0"
+ },
+ "door": {
+ "c": "objects",
+ "e": "🚪",
+ "d": "door",
+ "u": "6.0"
+ },
+ "doughnut": {
+ "c": "food",
+ "e": "ðŸ©",
+ "d": "doughnut",
+ "u": "6.0"
+ },
+ "dove": {
+ "c": "nature",
+ "e": "🕊",
+ "d": "dove of peace",
+ "u": "7.0"
+ },
+ "dragon": {
+ "c": "nature",
+ "e": "ðŸ‰",
+ "d": "dragon",
+ "u": "6.0"
+ },
+ "dragon_face": {
+ "c": "nature",
+ "e": "ðŸ²",
+ "d": "dragon face",
+ "u": "6.0"
+ },
+ "dress": {
+ "c": "people",
+ "e": "👗",
+ "d": "dress",
+ "u": "6.0"
+ },
+ "dromedary_camel": {
+ "c": "nature",
+ "e": "ðŸª",
+ "d": "dromedary camel",
+ "u": "6.0"
+ },
+ "drooling_face": {
+ "c": "people",
+ "e": "🤤",
+ "d": "drooling face",
+ "u": "9.0"
+ },
+ "droplet": {
+ "c": "nature",
+ "e": "💧",
+ "d": "droplet",
+ "u": "6.0"
+ },
+ "drum": {
+ "c": "activity",
+ "e": "ðŸ¥",
+ "d": "drum with drumsticks",
+ "u": "9.0"
+ },
+ "duck": {
+ "c": "nature",
+ "e": "🦆",
+ "d": "duck",
+ "u": "9.0"
+ },
+ "dvd": {
+ "c": "objects",
+ "e": "📀",
+ "d": "dvd",
+ "u": "6.0"
+ },
+ "e-mail": {
+ "c": "objects",
+ "e": "📧",
+ "d": "e-mail symbol",
+ "u": "6.0"
+ },
+ "eagle": {
+ "c": "nature",
+ "e": "🦅",
+ "d": "eagle",
+ "u": "9.0"
+ },
+ "ear": {
+ "c": "people",
+ "e": "👂",
+ "d": "ear",
+ "u": "6.0"
+ },
+ "ear_of_rice": {
+ "c": "nature",
+ "e": "🌾",
+ "d": "ear of rice",
+ "u": "6.0"
+ },
+ "ear_tone1": {
+ "c": "people",
+ "e": "👂ðŸ»",
+ "d": "ear tone 1",
+ "u": "8.0"
+ },
+ "ear_tone2": {
+ "c": "people",
+ "e": "👂ðŸ¼",
+ "d": "ear tone 2",
+ "u": "8.0"
+ },
+ "ear_tone3": {
+ "c": "people",
+ "e": "👂ðŸ½",
+ "d": "ear tone 3",
+ "u": "8.0"
+ },
+ "ear_tone4": {
+ "c": "people",
+ "e": "👂ðŸ¾",
+ "d": "ear tone 4",
+ "u": "8.0"
+ },
+ "ear_tone5": {
+ "c": "people",
+ "e": "👂ðŸ¿",
+ "d": "ear tone 5",
+ "u": "8.0"
+ },
+ "earth_africa": {
+ "c": "nature",
+ "e": "ðŸŒ",
+ "d": "earth globe europe-africa",
+ "u": "6.0"
+ },
+ "earth_americas": {
+ "c": "nature",
+ "e": "🌎",
+ "d": "earth globe americas",
+ "u": "6.0"
+ },
+ "earth_asia": {
+ "c": "nature",
+ "e": "ðŸŒ",
+ "d": "earth globe asia-australia",
+ "u": "6.0"
+ },
+ "egg": {
+ "c": "food",
+ "e": "🥚",
+ "d": "egg",
+ "u": "9.0"
+ },
+ "eggplant": {
+ "c": "food",
+ "e": "ðŸ†",
+ "d": "aubergine",
+ "u": "6.0"
+ },
+ "eight": {
+ "c": "symbols",
+ "e": "8ï¸âƒ£",
+ "d": "keycap digit eight",
+ "u": "3.0"
+ },
+ "eight_pointed_black_star": {
+ "c": "symbols",
+ "e": "✴",
+ "d": "eight pointed black star",
+ "u": "1.1"
+ },
+ "eight_spoked_asterisk": {
+ "c": "symbols",
+ "e": "✳",
+ "d": "eight spoked asterisk",
+ "u": "1.1"
+ },
+ "eject": {
+ "c": "symbols",
+ "e": "â",
+ "d": "eject symbol",
+ "u": "4.0"
+ },
+ "electric_plug": {
+ "c": "objects",
+ "e": "🔌",
+ "d": "electric plug",
+ "u": "6.0"
+ },
+ "elephant": {
+ "c": "nature",
+ "e": "ðŸ˜",
+ "d": "elephant",
+ "u": "6.0"
+ },
+ "end": {
+ "c": "symbols",
+ "e": "🔚",
+ "d": "end with leftwards arrow above",
+ "u": "6.0"
+ },
+ "envelope": {
+ "c": "objects",
+ "e": "✉",
+ "d": "envelope",
+ "u": "1.1"
+ },
+ "envelope_with_arrow": {
+ "c": "objects",
+ "e": "📩",
+ "d": "envelope with downwards arrow above",
+ "u": "6.0"
+ },
+ "euro": {
+ "c": "objects",
+ "e": "💶",
+ "d": "banknote with euro sign",
+ "u": "6.0"
+ },
+ "european_castle": {
+ "c": "travel",
+ "e": "ðŸ°",
+ "d": "european castle",
+ "u": "6.0"
+ },
+ "european_post_office": {
+ "c": "travel",
+ "e": "ðŸ¤",
+ "d": "european post office",
+ "u": "6.0"
+ },
+ "evergreen_tree": {
+ "c": "nature",
+ "e": "🌲",
+ "d": "evergreen tree",
+ "u": "6.0"
+ },
+ "exclamation": {
+ "c": "symbols",
+ "e": "â—",
+ "d": "heavy exclamation mark symbol",
+ "u": "5.2"
+ },
+ "expressionless": {
+ "c": "people",
+ "e": "😑",
+ "d": "expressionless face",
+ "u": "6.1"
+ },
+ "eye": {
+ "c": "people",
+ "e": "ðŸ‘",
+ "d": "eye",
+ "u": "7.0"
+ },
+ "eye_in_speech_bubble": {
+ "c": "symbols",
+ "e": "ðŸ‘â€ðŸ—¨",
+ "d": "eye in speech bubble",
+ "u": "7.0"
+ },
+ "eyeglasses": {
+ "c": "people",
+ "e": "👓",
+ "d": "eyeglasses",
+ "u": "6.0"
+ },
+ "eyes": {
+ "c": "people",
+ "e": "👀",
+ "d": "eyes",
+ "u": "6.0"
+ },
+ "face_palm": {
+ "c": "people",
+ "e": "🤦",
+ "d": "face palm",
+ "u": "9.0"
+ },
+ "face_palm_tone1": {
+ "c": "people",
+ "e": "🤦ðŸ»",
+ "d": "face palm tone 1",
+ "u": "9.0"
+ },
+ "face_palm_tone2": {
+ "c": "people",
+ "e": "🤦ðŸ¼",
+ "d": "face palm tone 2",
+ "u": "9.0"
+ },
+ "face_palm_tone3": {
+ "c": "people",
+ "e": "🤦ðŸ½",
+ "d": "face palm tone 3",
+ "u": "9.0"
+ },
+ "face_palm_tone4": {
+ "c": "people",
+ "e": "🤦ðŸ¾",
+ "d": "face palm tone 4",
+ "u": "9.0"
+ },
+ "face_palm_tone5": {
+ "c": "people",
+ "e": "🤦ðŸ¿",
+ "d": "face palm tone 5",
+ "u": "9.0"
+ },
+ "factory": {
+ "c": "travel",
+ "e": "ðŸ­",
+ "d": "factory",
+ "u": "6.0"
+ },
+ "fallen_leaf": {
+ "c": "nature",
+ "e": "ðŸ‚",
+ "d": "fallen leaf",
+ "u": "6.0"
+ },
+ "family": {
+ "c": "people",
+ "e": "👪",
+ "d": "family",
+ "u": "6.0"
+ },
+ "family_mmb": {
+ "c": "people",
+ "e": "👨â€ðŸ‘¨â€ðŸ‘¦",
+ "d": "family (man,man,boy)",
+ "u": "6.0"
+ },
+ "family_mmbb": {
+ "c": "people",
+ "e": "👨â€ðŸ‘¨â€ðŸ‘¦â€ðŸ‘¦",
+ "d": "family (man,man,boy,boy)",
+ "u": "6.0"
+ },
+ "family_mmg": {
+ "c": "people",
+ "e": "👨â€ðŸ‘¨â€ðŸ‘§",
+ "d": "family (man,man,girl)",
+ "u": "6.0"
+ },
+ "family_mmgb": {
+ "c": "people",
+ "e": "👨â€ðŸ‘¨â€ðŸ‘§â€ðŸ‘¦",
+ "d": "family (man,man,girl,boy)",
+ "u": "6.0"
+ },
+ "family_mmgg": {
+ "c": "people",
+ "e": "👨â€ðŸ‘¨â€ðŸ‘§â€ðŸ‘§",
+ "d": "family (man,man,girl,girl)",
+ "u": "6.0"
+ },
+ "family_mwbb": {
+ "c": "people",
+ "e": "👨â€ðŸ‘©â€ðŸ‘¦â€ðŸ‘¦",
+ "d": "family (man,woman,boy,boy)",
+ "u": "6.0"
+ },
+ "family_mwg": {
+ "c": "people",
+ "e": "👨â€ðŸ‘©â€ðŸ‘§",
+ "d": "family (man,woman,girl)",
+ "u": "6.0"
+ },
+ "family_mwgb": {
+ "c": "people",
+ "e": "👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦",
+ "d": "family (man,woman,girl,boy)",
+ "u": "6.0"
+ },
+ "family_mwgg": {
+ "c": "people",
+ "e": "👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘§",
+ "d": "family (man,woman,girl,girl)",
+ "u": "6.0"
+ },
+ "family_wwb": {
+ "c": "people",
+ "e": "👩â€ðŸ‘©â€ðŸ‘¦",
+ "d": "family (woman,woman,boy)",
+ "u": "6.0"
+ },
+ "family_wwbb": {
+ "c": "people",
+ "e": "👩â€ðŸ‘©â€ðŸ‘¦â€ðŸ‘¦",
+ "d": "family (woman,woman,boy,boy)",
+ "u": "6.0"
+ },
+ "family_wwg": {
+ "c": "people",
+ "e": "👩â€ðŸ‘©â€ðŸ‘§",
+ "d": "family (woman,woman,girl)",
+ "u": "6.0"
+ },
+ "family_wwgb": {
+ "c": "people",
+ "e": "👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦",
+ "d": "family (woman,woman,girl,boy)",
+ "u": "6.0"
+ },
+ "family_wwgg": {
+ "c": "people",
+ "e": "👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘§",
+ "d": "family (woman,woman,girl,girl)",
+ "u": "6.0"
+ },
+ "fast_forward": {
+ "c": "symbols",
+ "e": "â©",
+ "d": "black right-pointing double triangle",
+ "u": "6.0"
+ },
+ "fax": {
+ "c": "objects",
+ "e": "📠",
+ "d": "fax machine",
+ "u": "6.0"
+ },
+ "fearful": {
+ "c": "people",
+ "e": "😨",
+ "d": "fearful face",
+ "u": "6.0"
+ },
+ "feet": {
+ "c": "nature",
+ "e": "ðŸ¾",
+ "d": "paw prints",
+ "u": "6.0"
+ },
+ "fencer": {
+ "c": "activity",
+ "e": "🤺",
+ "d": "fencer",
+ "u": "9.0"
+ },
+ "ferris_wheel": {
+ "c": "travel",
+ "e": "🎡",
+ "d": "ferris wheel",
+ "u": "6.0"
+ },
+ "ferry": {
+ "c": "travel",
+ "e": "â›´",
+ "d": "ferry",
+ "u": "5.2"
+ },
+ "field_hockey": {
+ "c": "activity",
+ "e": "ðŸ‘",
+ "d": "field hockey stick and ball",
+ "u": "8.0"
+ },
+ "file_cabinet": {
+ "c": "objects",
+ "e": "🗄",
+ "d": "file cabinet",
+ "u": "7.0"
+ },
+ "file_folder": {
+ "c": "objects",
+ "e": "ðŸ“",
+ "d": "file folder",
+ "u": "6.0"
+ },
+ "film_frames": {
+ "c": "objects",
+ "e": "🎞",
+ "d": "film frames",
+ "u": "7.0"
+ },
+ "fingers_crossed": {
+ "c": "people",
+ "e": "🤞",
+ "d": "hand with first and index finger crossed",
+ "u": "9.0"
+ },
+ "fingers_crossed_tone1": {
+ "c": "people",
+ "e": "🤞ðŸ»",
+ "d": "hand with index and middle fingers crossed tone 1",
+ "u": "9.0"
+ },
+ "fingers_crossed_tone2": {
+ "c": "people",
+ "e": "🤞ðŸ¼",
+ "d": "hand with index and middle fingers crossed tone 2",
+ "u": "9.0"
+ },
+ "fingers_crossed_tone3": {
+ "c": "people",
+ "e": "🤞ðŸ½",
+ "d": "hand with index and middle fingers crossed tone 3",
+ "u": "9.0"
+ },
+ "fingers_crossed_tone4": {
+ "c": "people",
+ "e": "🤞ðŸ¾",
+ "d": "hand with index and middle fingers crossed tone 4",
+ "u": "9.0"
+ },
+ "fingers_crossed_tone5": {
+ "c": "people",
+ "e": "🤞ðŸ¿",
+ "d": "hand with index and middle fingers crossed tone 5",
+ "u": "9.0"
+ },
+ "fire": {
+ "c": "nature",
+ "e": "🔥",
+ "d": "fire",
+ "u": "6.0"
+ },
+ "fire_engine": {
+ "c": "travel",
+ "e": "🚒",
+ "d": "fire engine",
+ "u": "6.0"
+ },
+ "fireworks": {
+ "c": "travel",
+ "e": "🎆",
+ "d": "fireworks",
+ "u": "6.0"
+ },
+ "first_place": {
+ "c": "activity",
+ "e": "🥇",
+ "d": "first place medal",
+ "u": "9.0"
+ },
+ "first_quarter_moon": {
+ "c": "nature",
+ "e": "🌓",
+ "d": "first quarter moon symbol",
+ "u": "6.0"
+ },
+ "first_quarter_moon_with_face": {
+ "c": "nature",
+ "e": "🌛",
+ "d": "first quarter moon with face",
+ "u": "6.0"
+ },
+ "fish": {
+ "c": "nature",
+ "e": "ðŸŸ",
+ "d": "fish",
+ "u": "6.0"
+ },
+ "fish_cake": {
+ "c": "food",
+ "e": "ðŸ¥",
+ "d": "fish cake with swirl design",
+ "u": "6.0"
+ },
+ "fishing_pole_and_fish": {
+ "c": "activity",
+ "e": "🎣",
+ "d": "fishing pole and fish",
+ "u": "6.0"
+ },
+ "fist": {
+ "c": "people",
+ "e": "✊",
+ "d": "raised fist",
+ "u": "6.0"
+ },
+ "fist_tone1": {
+ "c": "people",
+ "e": "✊ðŸ»",
+ "d": "raised fist tone 1",
+ "u": "8.0"
+ },
+ "fist_tone2": {
+ "c": "people",
+ "e": "✊ðŸ¼",
+ "d": "raised fist tone 2",
+ "u": "8.0"
+ },
+ "fist_tone3": {
+ "c": "people",
+ "e": "✊ðŸ½",
+ "d": "raised fist tone 3",
+ "u": "8.0"
+ },
+ "fist_tone4": {
+ "c": "people",
+ "e": "✊ðŸ¾",
+ "d": "raised fist tone 4",
+ "u": "8.0"
+ },
+ "fist_tone5": {
+ "c": "people",
+ "e": "✊ðŸ¿",
+ "d": "raised fist tone 5",
+ "u": "8.0"
+ },
+ "five": {
+ "c": "symbols",
+ "e": "5ï¸âƒ£",
+ "d": "keycap digit five",
+ "u": "3.0"
+ },
+ "flag_ac": {
+ "c": "flags",
+ "e": "🇦🇨",
+ "d": "ascension",
+ "u": "6.0"
+ },
+ "flag_ad": {
+ "c": "flags",
+ "e": "🇦🇩",
+ "d": "andorra",
+ "u": "6.0"
+ },
+ "flag_ae": {
+ "c": "flags",
+ "e": "🇦🇪",
+ "d": "the united arab emirates",
+ "u": "6.0"
+ },
+ "flag_af": {
+ "c": "flags",
+ "e": "🇦🇫",
+ "d": "afghanistan",
+ "u": "6.0"
+ },
+ "flag_ag": {
+ "c": "flags",
+ "e": "🇦🇬",
+ "d": "antigua and barbuda",
+ "u": "6.0"
+ },
+ "flag_ai": {
+ "c": "flags",
+ "e": "🇦🇮",
+ "d": "anguilla",
+ "u": "6.0"
+ },
+ "flag_al": {
+ "c": "flags",
+ "e": "🇦🇱",
+ "d": "albania",
+ "u": "6.0"
+ },
+ "flag_am": {
+ "c": "flags",
+ "e": "🇦🇲",
+ "d": "armenia",
+ "u": "6.0"
+ },
+ "flag_ao": {
+ "c": "flags",
+ "e": "🇦🇴",
+ "d": "angola",
+ "u": "6.0"
+ },
+ "flag_aq": {
+ "c": "flags",
+ "e": "🇦🇶",
+ "d": "antarctica",
+ "u": "6.0"
+ },
+ "flag_ar": {
+ "c": "flags",
+ "e": "🇦🇷",
+ "d": "argentina",
+ "u": "6.0"
+ },
+ "flag_as": {
+ "c": "flags",
+ "e": "🇦🇸",
+ "d": "american samoa",
+ "u": "6.0"
+ },
+ "flag_at": {
+ "c": "flags",
+ "e": "🇦🇹",
+ "d": "austria",
+ "u": "6.0"
+ },
+ "flag_au": {
+ "c": "flags",
+ "e": "🇦🇺",
+ "d": "australia",
+ "u": "6.0"
+ },
+ "flag_aw": {
+ "c": "flags",
+ "e": "🇦🇼",
+ "d": "aruba",
+ "u": "6.0"
+ },
+ "flag_ax": {
+ "c": "flags",
+ "e": "🇦🇽",
+ "d": "Ã¥land islands",
+ "u": "6.0"
+ },
+ "flag_az": {
+ "c": "flags",
+ "e": "🇦🇿",
+ "d": "azerbaijan",
+ "u": "6.0"
+ },
+ "flag_ba": {
+ "c": "flags",
+ "e": "🇧🇦",
+ "d": "bosnia and herzegovina",
+ "u": "6.0"
+ },
+ "flag_bb": {
+ "c": "flags",
+ "e": "🇧🇧",
+ "d": "barbados",
+ "u": "6.0"
+ },
+ "flag_bd": {
+ "c": "flags",
+ "e": "🇧🇩",
+ "d": "bangladesh",
+ "u": "6.0"
+ },
+ "flag_be": {
+ "c": "flags",
+ "e": "🇧🇪",
+ "d": "belgium",
+ "u": "6.0"
+ },
+ "flag_bf": {
+ "c": "flags",
+ "e": "🇧🇫",
+ "d": "burkina faso",
+ "u": "6.0"
+ },
+ "flag_bg": {
+ "c": "flags",
+ "e": "🇧🇬",
+ "d": "bulgaria",
+ "u": "6.0"
+ },
+ "flag_bh": {
+ "c": "flags",
+ "e": "🇧🇭",
+ "d": "bahrain",
+ "u": "6.0"
+ },
+ "flag_bi": {
+ "c": "flags",
+ "e": "🇧🇮",
+ "d": "burundi",
+ "u": "6.0"
+ },
+ "flag_bj": {
+ "c": "flags",
+ "e": "🇧🇯",
+ "d": "benin",
+ "u": "6.0"
+ },
+ "flag_bl": {
+ "c": "flags",
+ "e": "🇧🇱",
+ "d": "saint barthélemy",
+ "u": "6.0"
+ },
+ "flag_black": {
+ "c": "objects",
+ "e": "ðŸ´",
+ "d": "waving black flag",
+ "u": "7.0"
+ },
+ "flag_bm": {
+ "c": "flags",
+ "e": "🇧🇲",
+ "d": "bermuda",
+ "u": "6.0"
+ },
+ "flag_bn": {
+ "c": "flags",
+ "e": "🇧🇳",
+ "d": "brunei",
+ "u": "6.0"
+ },
+ "flag_bo": {
+ "c": "flags",
+ "e": "🇧🇴",
+ "d": "bolivia",
+ "u": "6.0"
+ },
+ "flag_bq": {
+ "c": "flags",
+ "e": "🇧🇶",
+ "d": "caribbean netherlands",
+ "u": "6.0"
+ },
+ "flag_br": {
+ "c": "flags",
+ "e": "🇧🇷",
+ "d": "brazil",
+ "u": "6.0"
+ },
+ "flag_bs": {
+ "c": "flags",
+ "e": "🇧🇸",
+ "d": "the bahamas",
+ "u": "6.0"
+ },
+ "flag_bt": {
+ "c": "flags",
+ "e": "🇧🇹",
+ "d": "bhutan",
+ "u": "6.0"
+ },
+ "flag_bv": {
+ "c": "flags",
+ "e": "🇧🇻",
+ "d": "bouvet island",
+ "u": "6.0"
+ },
+ "flag_bw": {
+ "c": "flags",
+ "e": "🇧🇼",
+ "d": "botswana",
+ "u": "6.0"
+ },
+ "flag_by": {
+ "c": "flags",
+ "e": "🇧🇾",
+ "d": "belarus",
+ "u": "6.0"
+ },
+ "flag_bz": {
+ "c": "flags",
+ "e": "🇧🇿",
+ "d": "belize",
+ "u": "6.0"
+ },
+ "flag_ca": {
+ "c": "flags",
+ "e": "🇨🇦",
+ "d": "canada",
+ "u": "6.0"
+ },
+ "flag_cc": {
+ "c": "flags",
+ "e": "🇨🇨",
+ "d": "cocos (keeling) islands",
+ "u": "6.0"
+ },
+ "flag_cd": {
+ "c": "flags",
+ "e": "🇨🇩",
+ "d": "the democratic republic of the congo",
+ "u": "6.0"
+ },
+ "flag_cf": {
+ "c": "flags",
+ "e": "🇨🇫",
+ "d": "central african republic",
+ "u": "6.0"
+ },
+ "flag_cg": {
+ "c": "flags",
+ "e": "🇨🇬",
+ "d": "the republic of the congo",
+ "u": "6.0"
+ },
+ "flag_ch": {
+ "c": "flags",
+ "e": "🇨🇭",
+ "d": "switzerland",
+ "u": "6.0"
+ },
+ "flag_ci": {
+ "c": "flags",
+ "e": "🇨🇮",
+ "d": "cote d'ivoire",
+ "u": "6.0"
+ },
+ "flag_ck": {
+ "c": "flags",
+ "e": "🇨🇰",
+ "d": "cook islands",
+ "u": "6.0"
+ },
+ "flag_cl": {
+ "c": "flags",
+ "e": "🇨🇱",
+ "d": "chile",
+ "u": "6.0"
+ },
+ "flag_cm": {
+ "c": "flags",
+ "e": "🇨🇲",
+ "d": "cameroon",
+ "u": "6.0"
+ },
+ "flag_cn": {
+ "c": "flags",
+ "e": "🇨🇳",
+ "d": "china",
+ "u": "6.0"
+ },
+ "flag_co": {
+ "c": "flags",
+ "e": "🇨🇴",
+ "d": "colombia",
+ "u": "6.0"
+ },
+ "flag_cp": {
+ "c": "flags",
+ "e": "🇨🇵",
+ "d": "clipperton island",
+ "u": "6.0"
+ },
+ "flag_cr": {
+ "c": "flags",
+ "e": "🇨🇷",
+ "d": "costa rica",
+ "u": "6.0"
+ },
+ "flag_cu": {
+ "c": "flags",
+ "e": "🇨🇺",
+ "d": "cuba",
+ "u": "6.0"
+ },
+ "flag_cv": {
+ "c": "flags",
+ "e": "🇨🇻",
+ "d": "cape verde",
+ "u": "6.0"
+ },
+ "flag_cw": {
+ "c": "flags",
+ "e": "🇨🇼",
+ "d": "curaçao",
+ "u": "6.0"
+ },
+ "flag_cx": {
+ "c": "flags",
+ "e": "🇨🇽",
+ "d": "christmas island",
+ "u": "6.0"
+ },
+ "flag_cy": {
+ "c": "flags",
+ "e": "🇨🇾",
+ "d": "cyprus",
+ "u": "6.0"
+ },
+ "flag_cz": {
+ "c": "flags",
+ "e": "🇨🇿",
+ "d": "the czech republic",
+ "u": "6.0"
+ },
+ "flag_de": {
+ "c": "flags",
+ "e": "🇩🇪",
+ "d": "germany",
+ "u": "6.0"
+ },
+ "flag_dg": {
+ "c": "flags",
+ "e": "🇩🇬",
+ "d": "diego garcia",
+ "u": "6.0"
+ },
+ "flag_dj": {
+ "c": "flags",
+ "e": "🇩🇯",
+ "d": "djibouti",
+ "u": "6.0"
+ },
+ "flag_dk": {
+ "c": "flags",
+ "e": "🇩🇰",
+ "d": "denmark",
+ "u": "6.0"
+ },
+ "flag_dm": {
+ "c": "flags",
+ "e": "🇩🇲",
+ "d": "dominica",
+ "u": "6.0"
+ },
+ "flag_do": {
+ "c": "flags",
+ "e": "🇩🇴",
+ "d": "the dominican republic",
+ "u": "6.0"
+ },
+ "flag_dz": {
+ "c": "flags",
+ "e": "🇩🇿",
+ "d": "algeria",
+ "u": "6.0"
+ },
+ "flag_ea": {
+ "c": "flags",
+ "e": "🇪🇦",
+ "d": "ceuta, melilla",
+ "u": "6.0"
+ },
+ "flag_ec": {
+ "c": "flags",
+ "e": "🇪🇨",
+ "d": "ecuador",
+ "u": "6.0"
+ },
+ "flag_ee": {
+ "c": "flags",
+ "e": "🇪🇪",
+ "d": "estonia",
+ "u": "6.0"
+ },
+ "flag_eg": {
+ "c": "flags",
+ "e": "🇪🇬",
+ "d": "egypt",
+ "u": "6.0"
+ },
+ "flag_eh": {
+ "c": "flags",
+ "e": "🇪🇭",
+ "d": "western sahara",
+ "u": "6.0"
+ },
+ "flag_er": {
+ "c": "flags",
+ "e": "🇪🇷",
+ "d": "eritrea",
+ "u": "6.0"
+ },
+ "flag_es": {
+ "c": "flags",
+ "e": "🇪🇸",
+ "d": "spain",
+ "u": "6.0"
+ },
+ "flag_et": {
+ "c": "flags",
+ "e": "🇪🇹",
+ "d": "ethiopia",
+ "u": "6.0"
+ },
+ "flag_eu": {
+ "c": "flags",
+ "e": "🇪🇺",
+ "d": "european union",
+ "u": "6.0"
+ },
+ "flag_fi": {
+ "c": "flags",
+ "e": "🇫🇮",
+ "d": "finland",
+ "u": "6.0"
+ },
+ "flag_fj": {
+ "c": "flags",
+ "e": "🇫🇯",
+ "d": "fiji",
+ "u": "6.0"
+ },
+ "flag_fk": {
+ "c": "flags",
+ "e": "🇫🇰",
+ "d": "falkland islands",
+ "u": "6.0"
+ },
+ "flag_fm": {
+ "c": "flags",
+ "e": "🇫🇲",
+ "d": "micronesia",
+ "u": "6.0"
+ },
+ "flag_fo": {
+ "c": "flags",
+ "e": "🇫🇴",
+ "d": "faroe islands",
+ "u": "6.0"
+ },
+ "flag_fr": {
+ "c": "flags",
+ "e": "🇫🇷",
+ "d": "france",
+ "u": "6.0"
+ },
+ "flag_ga": {
+ "c": "flags",
+ "e": "🇬🇦",
+ "d": "gabon",
+ "u": "6.0"
+ },
+ "flag_gb": {
+ "c": "flags",
+ "e": "🇬🇧",
+ "d": "great britain",
+ "u": "6.0"
+ },
+ "flag_gd": {
+ "c": "flags",
+ "e": "🇬🇩",
+ "d": "grenada",
+ "u": "6.0"
+ },
+ "flag_ge": {
+ "c": "flags",
+ "e": "🇬🇪",
+ "d": "georgia",
+ "u": "6.0"
+ },
+ "flag_gf": {
+ "c": "flags",
+ "e": "🇬🇫",
+ "d": "french guiana",
+ "u": "6.0"
+ },
+ "flag_gg": {
+ "c": "flags",
+ "e": "🇬🇬",
+ "d": "guernsey",
+ "u": "6.0"
+ },
+ "flag_gh": {
+ "c": "flags",
+ "e": "🇬🇭",
+ "d": "ghana",
+ "u": "6.0"
+ },
+ "flag_gi": {
+ "c": "flags",
+ "e": "🇬🇮",
+ "d": "gibraltar",
+ "u": "6.0"
+ },
+ "flag_gl": {
+ "c": "flags",
+ "e": "🇬🇱",
+ "d": "greenland",
+ "u": "6.0"
+ },
+ "flag_gm": {
+ "c": "flags",
+ "e": "🇬🇲",
+ "d": "the gambia",
+ "u": "6.0"
+ },
+ "flag_gn": {
+ "c": "flags",
+ "e": "🇬🇳",
+ "d": "guinea",
+ "u": "6.0"
+ },
+ "flag_gp": {
+ "c": "flags",
+ "e": "🇬🇵",
+ "d": "guadeloupe",
+ "u": "6.0"
+ },
+ "flag_gq": {
+ "c": "flags",
+ "e": "🇬🇶",
+ "d": "equatorial guinea",
+ "u": "6.0"
+ },
+ "flag_gr": {
+ "c": "flags",
+ "e": "🇬🇷",
+ "d": "greece",
+ "u": "6.0"
+ },
+ "flag_gs": {
+ "c": "flags",
+ "e": "🇬🇸",
+ "d": "south georgia",
+ "u": "6.0"
+ },
+ "flag_gt": {
+ "c": "flags",
+ "e": "🇬🇹",
+ "d": "guatemala",
+ "u": "6.0"
+ },
+ "flag_gu": {
+ "c": "flags",
+ "e": "🇬🇺",
+ "d": "guam",
+ "u": "6.0"
+ },
+ "flag_gw": {
+ "c": "flags",
+ "e": "🇬🇼",
+ "d": "guinea-bissau",
+ "u": "6.0"
+ },
+ "flag_gy": {
+ "c": "flags",
+ "e": "🇬🇾",
+ "d": "guyana",
+ "u": "6.0"
+ },
+ "flag_hk": {
+ "c": "flags",
+ "e": "🇭🇰",
+ "d": "hong kong",
+ "u": "6.0"
+ },
+ "flag_hm": {
+ "c": "flags",
+ "e": "🇭🇲",
+ "d": "heard island and mcdonald islands",
+ "u": "6.0"
+ },
+ "flag_hn": {
+ "c": "flags",
+ "e": "🇭🇳",
+ "d": "honduras",
+ "u": "6.0"
+ },
+ "flag_hr": {
+ "c": "flags",
+ "e": "🇭🇷",
+ "d": "croatia",
+ "u": "6.0"
+ },
+ "flag_ht": {
+ "c": "flags",
+ "e": "🇭🇹",
+ "d": "haiti",
+ "u": "6.0"
+ },
+ "flag_hu": {
+ "c": "flags",
+ "e": "🇭🇺",
+ "d": "hungary",
+ "u": "6.0"
+ },
+ "flag_ic": {
+ "c": "flags",
+ "e": "🇮🇨",
+ "d": "canary islands",
+ "u": "6.0"
+ },
+ "flag_id": {
+ "c": "flags",
+ "e": "🇮🇩",
+ "d": "indonesia",
+ "u": "6.0"
+ },
+ "flag_ie": {
+ "c": "flags",
+ "e": "🇮🇪",
+ "d": "ireland",
+ "u": "6.0"
+ },
+ "flag_il": {
+ "c": "flags",
+ "e": "🇮🇱",
+ "d": "israel",
+ "u": "6.0"
+ },
+ "flag_im": {
+ "c": "flags",
+ "e": "🇮🇲",
+ "d": "isle of man",
+ "u": "6.0"
+ },
+ "flag_in": {
+ "c": "flags",
+ "e": "🇮🇳",
+ "d": "india",
+ "u": "6.0"
+ },
+ "flag_io": {
+ "c": "flags",
+ "e": "🇮🇴",
+ "d": "british indian ocean territory",
+ "u": "6.0"
+ },
+ "flag_iq": {
+ "c": "flags",
+ "e": "🇮🇶",
+ "d": "iraq",
+ "u": "6.0"
+ },
+ "flag_ir": {
+ "c": "flags",
+ "e": "🇮🇷",
+ "d": "iran",
+ "u": "6.0"
+ },
+ "flag_is": {
+ "c": "flags",
+ "e": "🇮🇸",
+ "d": "iceland",
+ "u": "6.0"
+ },
+ "flag_it": {
+ "c": "flags",
+ "e": "🇮🇹",
+ "d": "italy",
+ "u": "6.0"
+ },
+ "flag_je": {
+ "c": "flags",
+ "e": "🇯🇪",
+ "d": "jersey",
+ "u": "6.0"
+ },
+ "flag_jm": {
+ "c": "flags",
+ "e": "🇯🇲",
+ "d": "jamaica",
+ "u": "6.0"
+ },
+ "flag_jo": {
+ "c": "flags",
+ "e": "🇯🇴",
+ "d": "jordan",
+ "u": "6.0"
+ },
+ "flag_jp": {
+ "c": "flags",
+ "e": "🇯🇵",
+ "d": "japan",
+ "u": "6.0"
+ },
+ "flag_ke": {
+ "c": "flags",
+ "e": "🇰🇪",
+ "d": "kenya",
+ "u": "6.0"
+ },
+ "flag_kg": {
+ "c": "flags",
+ "e": "🇰🇬",
+ "d": "kyrgyzstan",
+ "u": "6.0"
+ },
+ "flag_kh": {
+ "c": "flags",
+ "e": "🇰🇭",
+ "d": "cambodia",
+ "u": "6.0"
+ },
+ "flag_ki": {
+ "c": "flags",
+ "e": "🇰🇮",
+ "d": "kiribati",
+ "u": "6.0"
+ },
+ "flag_km": {
+ "c": "flags",
+ "e": "🇰🇲",
+ "d": "the comoros",
+ "u": "6.0"
+ },
+ "flag_kn": {
+ "c": "flags",
+ "e": "🇰🇳",
+ "d": "saint kitts and nevis",
+ "u": "6.0"
+ },
+ "flag_kp": {
+ "c": "flags",
+ "e": "🇰🇵",
+ "d": "north korea",
+ "u": "6.0"
+ },
+ "flag_kr": {
+ "c": "flags",
+ "e": "🇰🇷",
+ "d": "korea",
+ "u": "6.0"
+ },
+ "flag_kw": {
+ "c": "flags",
+ "e": "🇰🇼",
+ "d": "kuwait",
+ "u": "6.0"
+ },
+ "flag_ky": {
+ "c": "flags",
+ "e": "🇰🇾",
+ "d": "cayman islands",
+ "u": "6.0"
+ },
+ "flag_kz": {
+ "c": "flags",
+ "e": "🇰🇿",
+ "d": "kazakhstan",
+ "u": "6.0"
+ },
+ "flag_la": {
+ "c": "flags",
+ "e": "🇱🇦",
+ "d": "laos",
+ "u": "6.0"
+ },
+ "flag_lb": {
+ "c": "flags",
+ "e": "🇱🇧",
+ "d": "lebanon",
+ "u": "6.0"
+ },
+ "flag_lc": {
+ "c": "flags",
+ "e": "🇱🇨",
+ "d": "saint lucia",
+ "u": "6.0"
+ },
+ "flag_li": {
+ "c": "flags",
+ "e": "🇱🇮",
+ "d": "liechtenstein",
+ "u": "6.0"
+ },
+ "flag_lk": {
+ "c": "flags",
+ "e": "🇱🇰",
+ "d": "sri lanka",
+ "u": "6.0"
+ },
+ "flag_lr": {
+ "c": "flags",
+ "e": "🇱🇷",
+ "d": "liberia",
+ "u": "6.0"
+ },
+ "flag_ls": {
+ "c": "flags",
+ "e": "🇱🇸",
+ "d": "lesotho",
+ "u": "6.0"
+ },
+ "flag_lt": {
+ "c": "flags",
+ "e": "🇱🇹",
+ "d": "lithuania",
+ "u": "6.0"
+ },
+ "flag_lu": {
+ "c": "flags",
+ "e": "🇱🇺",
+ "d": "luxembourg",
+ "u": "6.0"
+ },
+ "flag_lv": {
+ "c": "flags",
+ "e": "🇱🇻",
+ "d": "latvia",
+ "u": "6.0"
+ },
+ "flag_ly": {
+ "c": "flags",
+ "e": "🇱🇾",
+ "d": "libya",
+ "u": "6.0"
+ },
+ "flag_ma": {
+ "c": "flags",
+ "e": "🇲🇦",
+ "d": "morocco",
+ "u": "6.0"
+ },
+ "flag_mc": {
+ "c": "flags",
+ "e": "🇲🇨",
+ "d": "monaco",
+ "u": "6.0"
+ },
+ "flag_md": {
+ "c": "flags",
+ "e": "🇲🇩",
+ "d": "moldova",
+ "u": "6.0"
+ },
+ "flag_me": {
+ "c": "flags",
+ "e": "🇲🇪",
+ "d": "montenegro",
+ "u": "6.0"
+ },
+ "flag_mf": {
+ "c": "flags",
+ "e": "🇲🇫",
+ "d": "saint martin",
+ "u": "6.0"
+ },
+ "flag_mg": {
+ "c": "flags",
+ "e": "🇲🇬",
+ "d": "madagascar",
+ "u": "6.0"
+ },
+ "flag_mh": {
+ "c": "flags",
+ "e": "🇲🇭",
+ "d": "the marshall islands",
+ "u": "6.0"
+ },
+ "flag_mk": {
+ "c": "flags",
+ "e": "🇲🇰",
+ "d": "macedonia",
+ "u": "6.0"
+ },
+ "flag_ml": {
+ "c": "flags",
+ "e": "🇲🇱",
+ "d": "mali",
+ "u": "6.0"
+ },
+ "flag_mm": {
+ "c": "flags",
+ "e": "🇲🇲",
+ "d": "myanmar",
+ "u": "6.0"
+ },
+ "flag_mn": {
+ "c": "flags",
+ "e": "🇲🇳",
+ "d": "mongolia",
+ "u": "6.0"
+ },
+ "flag_mo": {
+ "c": "flags",
+ "e": "🇲🇴",
+ "d": "macau",
+ "u": "6.0"
+ },
+ "flag_mp": {
+ "c": "flags",
+ "e": "🇲🇵",
+ "d": "northern mariana islands",
+ "u": "6.0"
+ },
+ "flag_mq": {
+ "c": "flags",
+ "e": "🇲🇶",
+ "d": "martinique",
+ "u": "6.0"
+ },
+ "flag_mr": {
+ "c": "flags",
+ "e": "🇲🇷",
+ "d": "mauritania",
+ "u": "6.0"
+ },
+ "flag_ms": {
+ "c": "flags",
+ "e": "🇲🇸",
+ "d": "montserrat",
+ "u": "6.0"
+ },
+ "flag_mt": {
+ "c": "flags",
+ "e": "🇲🇹",
+ "d": "malta",
+ "u": "6.0"
+ },
+ "flag_mu": {
+ "c": "flags",
+ "e": "🇲🇺",
+ "d": "mauritius",
+ "u": "6.0"
+ },
+ "flag_mv": {
+ "c": "flags",
+ "e": "🇲🇻",
+ "d": "maldives",
+ "u": "6.0"
+ },
+ "flag_mw": {
+ "c": "flags",
+ "e": "🇲🇼",
+ "d": "malawi",
+ "u": "6.0"
+ },
+ "flag_mx": {
+ "c": "flags",
+ "e": "🇲🇽",
+ "d": "mexico",
+ "u": "6.0"
+ },
+ "flag_my": {
+ "c": "flags",
+ "e": "🇲🇾",
+ "d": "malaysia",
+ "u": "6.0"
+ },
+ "flag_mz": {
+ "c": "flags",
+ "e": "🇲🇿",
+ "d": "mozambique",
+ "u": "6.0"
+ },
+ "flag_na": {
+ "c": "flags",
+ "e": "🇳🇦",
+ "d": "namibia",
+ "u": "6.0"
+ },
+ "flag_nc": {
+ "c": "flags",
+ "e": "🇳🇨",
+ "d": "new caledonia",
+ "u": "6.0"
+ },
+ "flag_ne": {
+ "c": "flags",
+ "e": "🇳🇪",
+ "d": "niger",
+ "u": "6.0"
+ },
+ "flag_nf": {
+ "c": "flags",
+ "e": "🇳🇫",
+ "d": "norfolk island",
+ "u": "6.0"
+ },
+ "flag_ng": {
+ "c": "flags",
+ "e": "🇳🇬",
+ "d": "nigeria",
+ "u": "6.0"
+ },
+ "flag_ni": {
+ "c": "flags",
+ "e": "🇳🇮",
+ "d": "nicaragua",
+ "u": "6.0"
+ },
+ "flag_nl": {
+ "c": "flags",
+ "e": "🇳🇱",
+ "d": "the netherlands",
+ "u": "6.0"
+ },
+ "flag_no": {
+ "c": "flags",
+ "e": "🇳🇴",
+ "d": "norway",
+ "u": "6.0"
+ },
+ "flag_np": {
+ "c": "flags",
+ "e": "🇳🇵",
+ "d": "nepal",
+ "u": "6.0"
+ },
+ "flag_nr": {
+ "c": "flags",
+ "e": "🇳🇷",
+ "d": "nauru",
+ "u": "6.0"
+ },
+ "flag_nu": {
+ "c": "flags",
+ "e": "🇳🇺",
+ "d": "niue",
+ "u": "6.0"
+ },
+ "flag_nz": {
+ "c": "flags",
+ "e": "🇳🇿",
+ "d": "new zealand",
+ "u": "6.0"
+ },
+ "flag_om": {
+ "c": "flags",
+ "e": "🇴🇲",
+ "d": "oman",
+ "u": "6.0"
+ },
+ "flag_pa": {
+ "c": "flags",
+ "e": "🇵🇦",
+ "d": "panama",
+ "u": "6.0"
+ },
+ "flag_pe": {
+ "c": "flags",
+ "e": "🇵🇪",
+ "d": "peru",
+ "u": "6.0"
+ },
+ "flag_pf": {
+ "c": "flags",
+ "e": "🇵🇫",
+ "d": "french polynesia",
+ "u": "6.0"
+ },
+ "flag_pg": {
+ "c": "flags",
+ "e": "🇵🇬",
+ "d": "papua new guinea",
+ "u": "6.0"
+ },
+ "flag_ph": {
+ "c": "flags",
+ "e": "🇵🇭",
+ "d": "the philippines",
+ "u": "6.0"
+ },
+ "flag_pk": {
+ "c": "flags",
+ "e": "🇵🇰",
+ "d": "pakistan",
+ "u": "6.0"
+ },
+ "flag_pl": {
+ "c": "flags",
+ "e": "🇵🇱",
+ "d": "poland",
+ "u": "6.0"
+ },
+ "flag_pm": {
+ "c": "flags",
+ "e": "🇵🇲",
+ "d": "saint pierre and miquelon",
+ "u": "6.0"
+ },
+ "flag_pn": {
+ "c": "flags",
+ "e": "🇵🇳",
+ "d": "pitcairn",
+ "u": "6.0"
+ },
+ "flag_pr": {
+ "c": "flags",
+ "e": "🇵🇷",
+ "d": "puerto rico",
+ "u": "6.0"
+ },
+ "flag_ps": {
+ "c": "flags",
+ "e": "🇵🇸",
+ "d": "palestinian authority",
+ "u": "6.0"
+ },
+ "flag_pt": {
+ "c": "flags",
+ "e": "🇵🇹",
+ "d": "portugal",
+ "u": "6.0"
+ },
+ "flag_pw": {
+ "c": "flags",
+ "e": "🇵🇼",
+ "d": "palau",
+ "u": "6.0"
+ },
+ "flag_py": {
+ "c": "flags",
+ "e": "🇵🇾",
+ "d": "paraguay",
+ "u": "6.0"
+ },
+ "flag_qa": {
+ "c": "flags",
+ "e": "🇶🇦",
+ "d": "qatar",
+ "u": "6.0"
+ },
+ "flag_re": {
+ "c": "flags",
+ "e": "🇷🇪",
+ "d": "réunion",
+ "u": "6.0"
+ },
+ "flag_ro": {
+ "c": "flags",
+ "e": "🇷🇴",
+ "d": "romania",
+ "u": "6.0"
+ },
+ "flag_rs": {
+ "c": "flags",
+ "e": "🇷🇸",
+ "d": "serbia",
+ "u": "6.0"
+ },
+ "flag_ru": {
+ "c": "flags",
+ "e": "🇷🇺",
+ "d": "russia",
+ "u": "6.0"
+ },
+ "flag_rw": {
+ "c": "flags",
+ "e": "🇷🇼",
+ "d": "rwanda",
+ "u": "6.0"
+ },
+ "flag_sa": {
+ "c": "flags",
+ "e": "🇸🇦",
+ "d": "saudi arabia",
+ "u": "6.0"
+ },
+ "flag_sb": {
+ "c": "flags",
+ "e": "🇸🇧",
+ "d": "the solomon islands",
+ "u": "6.0"
+ },
+ "flag_sc": {
+ "c": "flags",
+ "e": "🇸🇨",
+ "d": "the seychelles",
+ "u": "6.0"
+ },
+ "flag_sd": {
+ "c": "flags",
+ "e": "🇸🇩",
+ "d": "sudan",
+ "u": "6.0"
+ },
+ "flag_se": {
+ "c": "flags",
+ "e": "🇸🇪",
+ "d": "sweden",
+ "u": "6.0"
+ },
+ "flag_sg": {
+ "c": "flags",
+ "e": "🇸🇬",
+ "d": "singapore",
+ "u": "6.0"
+ },
+ "flag_sh": {
+ "c": "flags",
+ "e": "🇸🇭",
+ "d": "saint helena",
+ "u": "6.0"
+ },
+ "flag_si": {
+ "c": "flags",
+ "e": "🇸🇮",
+ "d": "slovenia",
+ "u": "6.0"
+ },
+ "flag_sj": {
+ "c": "flags",
+ "e": "🇸🇯",
+ "d": "svalbard and jan mayen",
+ "u": "6.0"
+ },
+ "flag_sk": {
+ "c": "flags",
+ "e": "🇸🇰",
+ "d": "slovakia",
+ "u": "6.0"
+ },
+ "flag_sl": {
+ "c": "flags",
+ "e": "🇸🇱",
+ "d": "sierra leone",
+ "u": "6.0"
+ },
+ "flag_sm": {
+ "c": "flags",
+ "e": "🇸🇲",
+ "d": "san marino",
+ "u": "6.0"
+ },
+ "flag_sn": {
+ "c": "flags",
+ "e": "🇸🇳",
+ "d": "senegal",
+ "u": "6.0"
+ },
+ "flag_so": {
+ "c": "flags",
+ "e": "🇸🇴",
+ "d": "somalia",
+ "u": "6.0"
+ },
+ "flag_sr": {
+ "c": "flags",
+ "e": "🇸🇷",
+ "d": "suriname",
+ "u": "6.0"
+ },
+ "flag_ss": {
+ "c": "flags",
+ "e": "🇸🇸",
+ "d": "south sudan",
+ "u": "6.0"
+ },
+ "flag_st": {
+ "c": "flags",
+ "e": "🇸🇹",
+ "d": "sao tome and principe",
+ "u": "6.0"
+ },
+ "flag_sv": {
+ "c": "flags",
+ "e": "🇸🇻",
+ "d": "el salvador",
+ "u": "6.0"
+ },
+ "flag_sx": {
+ "c": "flags",
+ "e": "🇸🇽",
+ "d": "sint maarten",
+ "u": "6.0"
+ },
+ "flag_sy": {
+ "c": "flags",
+ "e": "🇸🇾",
+ "d": "syria",
+ "u": "6.0"
+ },
+ "flag_sz": {
+ "c": "flags",
+ "e": "🇸🇿",
+ "d": "swaziland",
+ "u": "6.0"
+ },
+ "flag_ta": {
+ "c": "flags",
+ "e": "🇹🇦",
+ "d": "tristan da cunha",
+ "u": "6.0"
+ },
+ "flag_tc": {
+ "c": "flags",
+ "e": "🇹🇨",
+ "d": "turks and caicos islands",
+ "u": "6.0"
+ },
+ "flag_td": {
+ "c": "flags",
+ "e": "🇹🇩",
+ "d": "chad",
+ "u": "6.0"
+ },
+ "flag_tf": {
+ "c": "flags",
+ "e": "🇹🇫",
+ "d": "french southern territories",
+ "u": "6.0"
+ },
+ "flag_tg": {
+ "c": "flags",
+ "e": "🇹🇬",
+ "d": "togo",
+ "u": "6.0"
+ },
+ "flag_th": {
+ "c": "flags",
+ "e": "🇹🇭",
+ "d": "thailand",
+ "u": "6.0"
+ },
+ "flag_tj": {
+ "c": "flags",
+ "e": "🇹🇯",
+ "d": "tajikistan",
+ "u": "6.0"
+ },
+ "flag_tk": {
+ "c": "flags",
+ "e": "🇹🇰",
+ "d": "tokelau",
+ "u": "6.0"
+ },
+ "flag_tl": {
+ "c": "flags",
+ "e": "🇹🇱",
+ "d": "east timor",
+ "u": "6.0"
+ },
+ "flag_tm": {
+ "c": "flags",
+ "e": "🇹🇲",
+ "d": "turkmenistan",
+ "u": "6.0"
+ },
+ "flag_tn": {
+ "c": "flags",
+ "e": "🇹🇳",
+ "d": "tunisia",
+ "u": "6.0"
+ },
+ "flag_to": {
+ "c": "flags",
+ "e": "🇹🇴",
+ "d": "tonga",
+ "u": "6.0"
+ },
+ "flag_tr": {
+ "c": "flags",
+ "e": "🇹🇷",
+ "d": "turkey",
+ "u": "6.0"
+ },
+ "flag_tt": {
+ "c": "flags",
+ "e": "🇹🇹",
+ "d": "trinidad and tobago",
+ "u": "6.0"
+ },
+ "flag_tv": {
+ "c": "flags",
+ "e": "🇹🇻",
+ "d": "tuvalu",
+ "u": "6.0"
+ },
+ "flag_tw": {
+ "c": "flags",
+ "e": "🇹🇼",
+ "d": "the republic of china",
+ "u": "6.0"
+ },
+ "flag_tz": {
+ "c": "flags",
+ "e": "🇹🇿",
+ "d": "tanzania",
+ "u": "6.0"
+ },
+ "flag_ua": {
+ "c": "flags",
+ "e": "🇺🇦",
+ "d": "ukraine",
+ "u": "6.0"
+ },
+ "flag_ug": {
+ "c": "flags",
+ "e": "🇺🇬",
+ "d": "uganda",
+ "u": "6.0"
+ },
+ "flag_um": {
+ "c": "flags",
+ "e": "🇺🇲",
+ "d": "united states minor outlying islands",
+ "u": "6.0"
+ },
+ "flag_us": {
+ "c": "flags",
+ "e": "🇺🇸",
+ "d": "united states",
+ "u": "6.0"
+ },
+ "flag_uy": {
+ "c": "flags",
+ "e": "🇺🇾",
+ "d": "uruguay",
+ "u": "6.0"
+ },
+ "flag_uz": {
+ "c": "flags",
+ "e": "🇺🇿",
+ "d": "uzbekistan",
+ "u": "6.0"
+ },
+ "flag_va": {
+ "c": "flags",
+ "e": "🇻🇦",
+ "d": "the vatican city",
+ "u": "6.0"
+ },
+ "flag_vc": {
+ "c": "flags",
+ "e": "🇻🇨",
+ "d": "saint vincent and the grenadines",
+ "u": "6.0"
+ },
+ "flag_ve": {
+ "c": "flags",
+ "e": "🇻🇪",
+ "d": "venezuela",
+ "u": "6.0"
+ },
+ "flag_vg": {
+ "c": "flags",
+ "e": "🇻🇬",
+ "d": "british virgin islands",
+ "u": "6.0"
+ },
+ "flag_vi": {
+ "c": "flags",
+ "e": "🇻🇮",
+ "d": "u.s. virgin islands",
+ "u": "6.0"
+ },
+ "flag_vn": {
+ "c": "flags",
+ "e": "🇻🇳",
+ "d": "vietnam",
+ "u": "6.0"
+ },
+ "flag_vu": {
+ "c": "flags",
+ "e": "🇻🇺",
+ "d": "vanuatu",
+ "u": "6.0"
+ },
+ "flag_wf": {
+ "c": "flags",
+ "e": "🇼🇫",
+ "d": "wallis and futuna",
+ "u": "6.0"
+ },
+ "flag_white": {
+ "c": "objects",
+ "e": "ðŸ³",
+ "d": "waving white flag",
+ "u": "7.0"
+ },
+ "flag_ws": {
+ "c": "flags",
+ "e": "🇼🇸",
+ "d": "samoa",
+ "u": "6.0"
+ },
+ "flag_xk": {
+ "c": "flags",
+ "e": "🇽🇰",
+ "d": "kosovo",
+ "u": "6.0"
+ },
+ "flag_ye": {
+ "c": "flags",
+ "e": "🇾🇪",
+ "d": "yemen",
+ "u": "6.0"
+ },
+ "flag_yt": {
+ "c": "flags",
+ "e": "🇾🇹",
+ "d": "mayotte",
+ "u": "6.0"
+ },
+ "flag_za": {
+ "c": "flags",
+ "e": "🇿🇦",
+ "d": "south africa",
+ "u": "6.0"
+ },
+ "flag_zm": {
+ "c": "flags",
+ "e": "🇿🇲",
+ "d": "zambia",
+ "u": "6.0"
+ },
+ "flag_zw": {
+ "c": "flags",
+ "e": "🇿🇼",
+ "d": "zimbabwe",
+ "u": "6.0"
+ },
+ "flags": {
+ "c": "objects",
+ "e": "ðŸŽ",
+ "d": "carp streamer",
+ "u": "6.0"
+ },
+ "flashlight": {
+ "c": "objects",
+ "e": "🔦",
+ "d": "electric torch",
+ "u": "6.0"
+ },
+ "fleur-de-lis": {
+ "c": "symbols",
+ "e": "⚜",
+ "d": "fleur-de-lis",
+ "u": "4.1"
+ },
+ "floppy_disk": {
+ "c": "objects",
+ "e": "💾",
+ "d": "floppy disk",
+ "u": "6.0"
+ },
+ "flower_playing_cards": {
+ "c": "symbols",
+ "e": "🎴",
+ "d": "flower playing cards",
+ "u": "6.0"
+ },
+ "flushed": {
+ "c": "people",
+ "e": "😳",
+ "d": "flushed face",
+ "u": "6.0"
+ },
+ "fog": {
+ "c": "nature",
+ "e": "🌫",
+ "d": "fog",
+ "u": "7.0"
+ },
+ "foggy": {
+ "c": "travel",
+ "e": "ðŸŒ",
+ "d": "foggy",
+ "u": "6.0"
+ },
+ "football": {
+ "c": "activity",
+ "e": "ðŸˆ",
+ "d": "american football",
+ "u": "6.0"
+ },
+ "footprints": {
+ "c": "people",
+ "e": "👣",
+ "d": "footprints",
+ "u": "6.0"
+ },
+ "fork_and_knife": {
+ "c": "food",
+ "e": "ðŸ´",
+ "d": "fork and knife",
+ "u": "6.0"
+ },
+ "fork_knife_plate": {
+ "c": "food",
+ "e": "ðŸ½",
+ "d": "fork and knife with plate",
+ "u": "7.0"
+ },
+ "fountain": {
+ "c": "travel",
+ "e": "⛲",
+ "d": "fountain",
+ "u": "5.2"
+ },
+ "four": {
+ "c": "symbols",
+ "e": "4ï¸âƒ£",
+ "d": "keycap digit four",
+ "u": "3.0"
+ },
+ "four_leaf_clover": {
+ "c": "nature",
+ "e": "ðŸ€",
+ "d": "four leaf clover",
+ "u": "6.0"
+ },
+ "fox": {
+ "c": "nature",
+ "e": "🦊",
+ "d": "fox face",
+ "u": "9.0"
+ },
+ "frame_photo": {
+ "c": "objects",
+ "e": "🖼",
+ "d": "frame with picture",
+ "u": "7.0"
+ },
+ "free": {
+ "c": "symbols",
+ "e": "🆓",
+ "d": "squared free",
+ "u": "6.0"
+ },
+ "french_bread": {
+ "c": "food",
+ "e": "🥖",
+ "d": "baguette bread",
+ "u": "9.0"
+ },
+ "fried_shrimp": {
+ "c": "food",
+ "e": "ðŸ¤",
+ "d": "fried shrimp",
+ "u": "6.0"
+ },
+ "fries": {
+ "c": "food",
+ "e": "ðŸŸ",
+ "d": "french fries",
+ "u": "6.0"
+ },
+ "frog": {
+ "c": "nature",
+ "e": "ðŸ¸",
+ "d": "frog face",
+ "u": "6.0"
+ },
+ "frowning": {
+ "c": "people",
+ "e": "😦",
+ "d": "frowning face with open mouth",
+ "u": "6.1"
+ },
+ "frowning2": {
+ "c": "people",
+ "e": "☹",
+ "d": "white frowning face",
+ "u": "1.1"
+ },
+ "fuelpump": {
+ "c": "travel",
+ "e": "⛽",
+ "d": "fuel pump",
+ "u": "5.2"
+ },
+ "full_moon": {
+ "c": "nature",
+ "e": "🌕",
+ "d": "full moon symbol",
+ "u": "6.0"
+ },
+ "full_moon_with_face": {
+ "c": "nature",
+ "e": "ðŸŒ",
+ "d": "full moon with face",
+ "u": "6.0"
+ },
+ "game_die": {
+ "c": "activity",
+ "e": "🎲",
+ "d": "game die",
+ "u": "6.0"
+ },
+ "gear": {
+ "c": "objects",
+ "e": "âš™",
+ "d": "gear",
+ "u": "4.1"
+ },
+ "gem": {
+ "c": "objects",
+ "e": "💎",
+ "d": "gem stone",
+ "u": "6.0"
+ },
+ "gay_pride_flag": {
+ "c": "flags",
+ "e": "ðŸ³ï¸â€ðŸŒˆ",
+ "d": "gay_pride_flag",
+ "u": "7.0"
+ },
+ "gemini": {
+ "c": "symbols",
+ "e": "♊",
+ "d": "gemini",
+ "u": "1.1"
+ },
+ "ghost": {
+ "c": "people",
+ "e": "👻",
+ "d": "ghost",
+ "u": "6.0"
+ },
+ "gift": {
+ "c": "objects",
+ "e": "ðŸŽ",
+ "d": "wrapped present",
+ "u": "6.0"
+ },
+ "gift_heart": {
+ "c": "symbols",
+ "e": "ðŸ’",
+ "d": "heart with ribbon",
+ "u": "6.0"
+ },
+ "girl": {
+ "c": "people",
+ "e": "👧",
+ "d": "girl",
+ "u": "6.0"
+ },
+ "girl_tone1": {
+ "c": "people",
+ "e": "👧ðŸ»",
+ "d": "girl tone 1",
+ "u": "8.0"
+ },
+ "girl_tone2": {
+ "c": "people",
+ "e": "👧ðŸ¼",
+ "d": "girl tone 2",
+ "u": "8.0"
+ },
+ "girl_tone3": {
+ "c": "people",
+ "e": "👧ðŸ½",
+ "d": "girl tone 3",
+ "u": "8.0"
+ },
+ "girl_tone4": {
+ "c": "people",
+ "e": "👧ðŸ¾",
+ "d": "girl tone 4",
+ "u": "8.0"
+ },
+ "girl_tone5": {
+ "c": "people",
+ "e": "👧ðŸ¿",
+ "d": "girl tone 5",
+ "u": "8.0"
+ },
+ "globe_with_meridians": {
+ "c": "symbols",
+ "e": "ðŸŒ",
+ "d": "globe with meridians",
+ "u": "6.0"
+ },
+ "goal": {
+ "c": "activity",
+ "e": "🥅",
+ "d": "goal net",
+ "u": "9.0"
+ },
+ "goat": {
+ "c": "nature",
+ "e": "ðŸ",
+ "d": "goat",
+ "u": "6.0"
+ },
+ "golf": {
+ "c": "activity",
+ "e": "⛳",
+ "d": "flag in hole",
+ "u": "5.2"
+ },
+ "golfer": {
+ "c": "activity",
+ "e": "ðŸŒ",
+ "d": "golfer",
+ "u": "7.0"
+ },
+ "gorilla": {
+ "c": "nature",
+ "e": "ðŸ¦",
+ "d": "gorilla",
+ "u": "9.0"
+ },
+ "grapes": {
+ "c": "food",
+ "e": "ðŸ‡",
+ "d": "grapes",
+ "u": "6.0"
+ },
+ "green_apple": {
+ "c": "food",
+ "e": "ðŸ",
+ "d": "green apple",
+ "u": "6.0"
+ },
+ "green_book": {
+ "c": "objects",
+ "e": "📗",
+ "d": "green book",
+ "u": "6.0"
+ },
+ "green_heart": {
+ "c": "symbols",
+ "e": "💚",
+ "d": "green heart",
+ "u": "6.0"
+ },
+ "grey_exclamation": {
+ "c": "symbols",
+ "e": "â•",
+ "d": "white exclamation mark ornament",
+ "u": "6.0"
+ },
+ "grey_question": {
+ "c": "symbols",
+ "e": "â”",
+ "d": "white question mark ornament",
+ "u": "6.0"
+ },
+ "grimacing": {
+ "c": "people",
+ "e": "😬",
+ "d": "grimacing face",
+ "u": "6.1"
+ },
+ "grin": {
+ "c": "people",
+ "e": "ðŸ˜",
+ "d": "grinning face with smiling eyes",
+ "u": "6.0"
+ },
+ "grinning": {
+ "c": "people",
+ "e": "😀",
+ "d": "grinning face",
+ "u": "6.1"
+ },
+ "guardsman": {
+ "c": "people",
+ "e": "💂",
+ "d": "guardsman",
+ "u": "6.0"
+ },
+ "guardsman_tone1": {
+ "c": "people",
+ "e": "💂ðŸ»",
+ "d": "guardsman tone 1",
+ "u": "8.0"
+ },
+ "guardsman_tone2": {
+ "c": "people",
+ "e": "💂ðŸ¼",
+ "d": "guardsman tone 2",
+ "u": "8.0"
+ },
+ "guardsman_tone3": {
+ "c": "people",
+ "e": "💂ðŸ½",
+ "d": "guardsman tone 3",
+ "u": "8.0"
+ },
+ "guardsman_tone4": {
+ "c": "people",
+ "e": "💂ðŸ¾",
+ "d": "guardsman tone 4",
+ "u": "8.0"
+ },
+ "guardsman_tone5": {
+ "c": "people",
+ "e": "💂ðŸ¿",
+ "d": "guardsman tone 5",
+ "u": "8.0"
+ },
+ "guitar": {
+ "c": "activity",
+ "e": "🎸",
+ "d": "guitar",
+ "u": "6.0"
+ },
+ "gun": {
+ "c": "objects",
+ "e": "🔫",
+ "d": "pistol",
+ "u": "6.0"
+ },
+ "haircut": {
+ "c": "people",
+ "e": "💇",
+ "d": "haircut",
+ "u": "6.0"
+ },
+ "haircut_tone1": {
+ "c": "people",
+ "e": "💇ðŸ»",
+ "d": "haircut tone 1",
+ "u": "8.0"
+ },
+ "haircut_tone2": {
+ "c": "people",
+ "e": "💇ðŸ¼",
+ "d": "haircut tone 2",
+ "u": "8.0"
+ },
+ "haircut_tone3": {
+ "c": "people",
+ "e": "💇ðŸ½",
+ "d": "haircut tone 3",
+ "u": "8.0"
+ },
+ "haircut_tone4": {
+ "c": "people",
+ "e": "💇ðŸ¾",
+ "d": "haircut tone 4",
+ "u": "8.0"
+ },
+ "haircut_tone5": {
+ "c": "people",
+ "e": "💇ðŸ¿",
+ "d": "haircut tone 5",
+ "u": "8.0"
+ },
+ "hamburger": {
+ "c": "food",
+ "e": "ðŸ”",
+ "d": "hamburger",
+ "u": "6.0"
+ },
+ "hammer": {
+ "c": "objects",
+ "e": "🔨",
+ "d": "hammer",
+ "u": "6.0"
+ },
+ "hammer_pick": {
+ "c": "objects",
+ "e": "âš’",
+ "d": "hammer and pick",
+ "u": "4.1"
+ },
+ "hamster": {
+ "c": "nature",
+ "e": "ðŸ¹",
+ "d": "hamster face",
+ "u": "6.0"
+ },
+ "hand_splayed": {
+ "c": "people",
+ "e": "ðŸ–",
+ "d": "raised hand with fingers splayed",
+ "u": "7.0"
+ },
+ "hand_splayed_tone1": {
+ "c": "people",
+ "e": "ðŸ–ðŸ»",
+ "d": "raised hand with fingers splayed tone 1",
+ "u": "8.0"
+ },
+ "hand_splayed_tone2": {
+ "c": "people",
+ "e": "ðŸ–ðŸ¼",
+ "d": "raised hand with fingers splayed tone 2",
+ "u": "8.0"
+ },
+ "hand_splayed_tone3": {
+ "c": "people",
+ "e": "ðŸ–ðŸ½",
+ "d": "raised hand with fingers splayed tone 3",
+ "u": "8.0"
+ },
+ "hand_splayed_tone4": {
+ "c": "people",
+ "e": "ðŸ–ðŸ¾",
+ "d": "raised hand with fingers splayed tone 4",
+ "u": "8.0"
+ },
+ "hand_splayed_tone5": {
+ "c": "people",
+ "e": "ðŸ–ðŸ¿",
+ "d": "raised hand with fingers splayed tone 5",
+ "u": "8.0"
+ },
+ "handbag": {
+ "c": "people",
+ "e": "👜",
+ "d": "handbag",
+ "u": "6.0"
+ },
+ "handball": {
+ "c": "activity",
+ "e": "🤾",
+ "d": "handball",
+ "u": "9.0"
+ },
+ "handball_tone1": {
+ "c": "activity",
+ "e": "🤾ðŸ»",
+ "d": "handball tone 1",
+ "u": "9.0"
+ },
+ "handball_tone2": {
+ "c": "activity",
+ "e": "🤾ðŸ¼",
+ "d": "handball tone 2",
+ "u": "9.0"
+ },
+ "handball_tone3": {
+ "c": "activity",
+ "e": "🤾ðŸ½",
+ "d": "handball tone 3",
+ "u": "9.0"
+ },
+ "handball_tone4": {
+ "c": "activity",
+ "e": "🤾ðŸ¾",
+ "d": "handball tone 4",
+ "u": "9.0"
+ },
+ "handball_tone5": {
+ "c": "activity",
+ "e": "🤾ðŸ¿",
+ "d": "handball tone 5",
+ "u": "9.0"
+ },
+ "handshake": {
+ "c": "people",
+ "e": "ðŸ¤",
+ "d": "handshake",
+ "u": "9.0"
+ },
+ "handshake_tone1": {
+ "c": "people",
+ "e": "ðŸ¤ðŸ»",
+ "d": "handshake tone 1",
+ "u": "9.0"
+ },
+ "handshake_tone2": {
+ "c": "people",
+ "e": "ðŸ¤ðŸ¼",
+ "d": "handshake tone 2",
+ "u": "9.0"
+ },
+ "handshake_tone3": {
+ "c": "people",
+ "e": "ðŸ¤ðŸ½",
+ "d": "handshake tone 3",
+ "u": "9.0"
+ },
+ "handshake_tone4": {
+ "c": "people",
+ "e": "ðŸ¤ðŸ¾",
+ "d": "handshake tone 4",
+ "u": "9.0"
+ },
+ "handshake_tone5": {
+ "c": "people",
+ "e": "ðŸ¤ðŸ¿",
+ "d": "handshake tone 5",
+ "u": "9.0"
+ },
+ "hash": {
+ "c": "symbols",
+ "e": "#⃣",
+ "d": "number sign",
+ "u": "3.0"
+ },
+ "hatched_chick": {
+ "c": "nature",
+ "e": "ðŸ¥",
+ "d": "front-facing baby chick",
+ "u": "6.0"
+ },
+ "hatching_chick": {
+ "c": "nature",
+ "e": "ðŸ£",
+ "d": "hatching chick",
+ "u": "6.0"
+ },
+ "head_bandage": {
+ "c": "people",
+ "e": "🤕",
+ "d": "face with head-bandage",
+ "u": "8.0"
+ },
+ "headphones": {
+ "c": "activity",
+ "e": "🎧",
+ "d": "headphone",
+ "u": "6.0"
+ },
+ "hear_no_evil": {
+ "c": "nature",
+ "e": "🙉",
+ "d": "hear-no-evil monkey",
+ "u": "6.0"
+ },
+ "heart": {
+ "c": "symbols",
+ "e": "â¤",
+ "d": "heavy black heart",
+ "u": "1.1"
+ },
+ "heart_decoration": {
+ "c": "symbols",
+ "e": "💟",
+ "d": "heart decoration",
+ "u": "6.0"
+ },
+ "heart_exclamation": {
+ "c": "symbols",
+ "e": "â£",
+ "d": "heavy heart exclamation mark ornament",
+ "u": "1.1"
+ },
+ "heart_eyes": {
+ "c": "people",
+ "e": "ðŸ˜",
+ "d": "smiling face with heart-shaped eyes",
+ "u": "6.0"
+ },
+ "heart_eyes_cat": {
+ "c": "people",
+ "e": "😻",
+ "d": "smiling cat face with heart-shaped eyes",
+ "u": "6.0"
+ },
+ "heartbeat": {
+ "c": "symbols",
+ "e": "💓",
+ "d": "beating heart",
+ "u": "6.0"
+ },
+ "heartpulse": {
+ "c": "symbols",
+ "e": "💗",
+ "d": "growing heart",
+ "u": "6.0"
+ },
+ "hearts": {
+ "c": "symbols",
+ "e": "♥",
+ "d": "black heart suit",
+ "u": "1.1"
+ },
+ "heavy_check_mark": {
+ "c": "symbols",
+ "e": "✔",
+ "d": "heavy check mark",
+ "u": "1.1"
+ },
+ "heavy_division_sign": {
+ "c": "symbols",
+ "e": "âž—",
+ "d": "heavy division sign",
+ "u": "6.0"
+ },
+ "heavy_dollar_sign": {
+ "c": "symbols",
+ "e": "💲",
+ "d": "heavy dollar sign",
+ "u": "6.0"
+ },
+ "heavy_minus_sign": {
+ "c": "symbols",
+ "e": "âž–",
+ "d": "heavy minus sign",
+ "u": "6.0"
+ },
+ "heavy_multiplication_x": {
+ "c": "symbols",
+ "e": "✖",
+ "d": "heavy multiplication x",
+ "u": "1.1"
+ },
+ "heavy_plus_sign": {
+ "c": "symbols",
+ "e": "âž•",
+ "d": "heavy plus sign",
+ "u": "6.0"
+ },
+ "helicopter": {
+ "c": "travel",
+ "e": "ðŸš",
+ "d": "helicopter",
+ "u": "6.0"
+ },
+ "helmet_with_cross": {
+ "c": "people",
+ "e": "⛑",
+ "d": "helmet with white cross",
+ "u": "5.2"
+ },
+ "herb": {
+ "c": "nature",
+ "e": "🌿",
+ "d": "herb",
+ "u": "6.0"
+ },
+ "hibiscus": {
+ "c": "nature",
+ "e": "🌺",
+ "d": "hibiscus",
+ "u": "6.0"
+ },
+ "high_brightness": {
+ "c": "symbols",
+ "e": "🔆",
+ "d": "high brightness symbol",
+ "u": "6.0"
+ },
+ "high_heel": {
+ "c": "people",
+ "e": "👠",
+ "d": "high-heeled shoe",
+ "u": "6.0"
+ },
+ "hockey": {
+ "c": "activity",
+ "e": "ðŸ’",
+ "d": "ice hockey stick and puck",
+ "u": "8.0"
+ },
+ "hole": {
+ "c": "objects",
+ "e": "🕳",
+ "d": "hole",
+ "u": "7.0"
+ },
+ "homes": {
+ "c": "travel",
+ "e": "ðŸ˜",
+ "d": "house buildings",
+ "u": "7.0"
+ },
+ "honey_pot": {
+ "c": "food",
+ "e": "ðŸ¯",
+ "d": "honey pot",
+ "u": "6.0"
+ },
+ "horse": {
+ "c": "nature",
+ "e": "ðŸ´",
+ "d": "horse face",
+ "u": "6.0"
+ },
+ "horse_racing": {
+ "c": "activity",
+ "e": "ðŸ‡",
+ "d": "horse racing",
+ "u": "6.0"
+ },
+ "horse_racing_tone1": {
+ "c": "activity",
+ "e": "ðŸ‡ðŸ»",
+ "d": "horse racing tone 1",
+ "u": "8.0"
+ },
+ "horse_racing_tone2": {
+ "c": "activity",
+ "e": "ðŸ‡ðŸ¼",
+ "d": "horse racing tone 2",
+ "u": "8.0"
+ },
+ "horse_racing_tone3": {
+ "c": "activity",
+ "e": "ðŸ‡ðŸ½",
+ "d": "horse racing tone 3",
+ "u": "8.0"
+ },
+ "horse_racing_tone4": {
+ "c": "activity",
+ "e": "ðŸ‡ðŸ¾",
+ "d": "horse racing tone 4",
+ "u": "8.0"
+ },
+ "horse_racing_tone5": {
+ "c": "activity",
+ "e": "ðŸ‡ðŸ¿",
+ "d": "horse racing tone 5",
+ "u": "8.0"
+ },
+ "hospital": {
+ "c": "travel",
+ "e": "ðŸ¥",
+ "d": "hospital",
+ "u": "6.0"
+ },
+ "hot_pepper": {
+ "c": "food",
+ "e": "🌶",
+ "d": "hot pepper",
+ "u": "7.0"
+ },
+ "hotdog": {
+ "c": "food",
+ "e": "🌭",
+ "d": "hot dog",
+ "u": "8.0"
+ },
+ "hotel": {
+ "c": "travel",
+ "e": "ðŸ¨",
+ "d": "hotel",
+ "u": "6.0"
+ },
+ "hotsprings": {
+ "c": "symbols",
+ "e": "♨",
+ "d": "hot springs",
+ "u": "1.1"
+ },
+ "hourglass": {
+ "c": "objects",
+ "e": "⌛",
+ "d": "hourglass",
+ "u": "1.1"
+ },
+ "hourglass_flowing_sand": {
+ "c": "objects",
+ "e": "â³",
+ "d": "hourglass with flowing sand",
+ "u": "6.0"
+ },
+ "house": {
+ "c": "travel",
+ "e": "ðŸ ",
+ "d": "house building",
+ "u": "6.0"
+ },
+ "house_abandoned": {
+ "c": "travel",
+ "e": "ðŸš",
+ "d": "derelict house building",
+ "u": "7.0"
+ },
+ "house_with_garden": {
+ "c": "travel",
+ "e": "ðŸ¡",
+ "d": "house with garden",
+ "u": "6.0"
+ },
+ "hugging": {
+ "c": "people",
+ "e": "🤗",
+ "d": "hugging face",
+ "u": "8.0"
+ },
+ "hushed": {
+ "c": "people",
+ "e": "😯",
+ "d": "hushed face",
+ "u": "6.1"
+ },
+ "ice_cream": {
+ "c": "food",
+ "e": "ðŸ¨",
+ "d": "ice cream",
+ "u": "6.0"
+ },
+ "ice_skate": {
+ "c": "activity",
+ "e": "⛸",
+ "d": "ice skate",
+ "u": "5.2"
+ },
+ "icecream": {
+ "c": "food",
+ "e": "ðŸ¦",
+ "d": "soft ice cream",
+ "u": "6.0"
+ },
+ "id": {
+ "c": "symbols",
+ "e": "🆔",
+ "d": "squared id",
+ "u": "6.0"
+ },
+ "ideograph_advantage": {
+ "c": "symbols",
+ "e": "ðŸ‰",
+ "d": "circled ideograph advantage",
+ "u": "6.0"
+ },
+ "imp": {
+ "c": "people",
+ "e": "👿",
+ "d": "imp",
+ "u": "6.0"
+ },
+ "inbox_tray": {
+ "c": "objects",
+ "e": "📥",
+ "d": "inbox tray",
+ "u": "6.0"
+ },
+ "incoming_envelope": {
+ "c": "objects",
+ "e": "📨",
+ "d": "incoming envelope",
+ "u": "6.0"
+ },
+ "information_desk_person": {
+ "c": "people",
+ "e": "ðŸ’",
+ "d": "information desk person",
+ "u": "6.0"
+ },
+ "information_desk_person_tone1": {
+ "c": "people",
+ "e": "ðŸ’ðŸ»",
+ "d": "information desk person tone 1",
+ "u": "8.0"
+ },
+ "information_desk_person_tone2": {
+ "c": "people",
+ "e": "ðŸ’ðŸ¼",
+ "d": "information desk person tone 2",
+ "u": "8.0"
+ },
+ "information_desk_person_tone3": {
+ "c": "people",
+ "e": "ðŸ’ðŸ½",
+ "d": "information desk person tone 3",
+ "u": "8.0"
+ },
+ "information_desk_person_tone4": {
+ "c": "people",
+ "e": "ðŸ’ðŸ¾",
+ "d": "information desk person tone 4",
+ "u": "8.0"
+ },
+ "information_desk_person_tone5": {
+ "c": "people",
+ "e": "ðŸ’ðŸ¿",
+ "d": "information desk person tone 5",
+ "u": "8.0"
+ },
+ "information_source": {
+ "c": "symbols",
+ "e": "ℹ",
+ "d": "information source",
+ "u": "3.0"
+ },
+ "innocent": {
+ "c": "people",
+ "e": "😇",
+ "d": "smiling face with halo",
+ "u": "6.0"
+ },
+ "interrobang": {
+ "c": "symbols",
+ "e": "â‰",
+ "d": "exclamation question mark",
+ "u": "3.0"
+ },
+ "iphone": {
+ "c": "objects",
+ "e": "📱",
+ "d": "mobile phone",
+ "u": "6.0"
+ },
+ "island": {
+ "c": "travel",
+ "e": "ðŸ",
+ "d": "desert island",
+ "u": "7.0"
+ },
+ "izakaya_lantern": {
+ "c": "objects",
+ "e": "ðŸ®",
+ "d": "izakaya lantern",
+ "u": "6.0"
+ },
+ "jack_o_lantern": {
+ "c": "nature",
+ "e": "🎃",
+ "d": "jack-o-lantern",
+ "u": "6.0"
+ },
+ "japan": {
+ "c": "travel",
+ "e": "🗾",
+ "d": "silhouette of japan",
+ "u": "6.0"
+ },
+ "japanese_castle": {
+ "c": "travel",
+ "e": "ðŸ¯",
+ "d": "japanese castle",
+ "u": "6.0"
+ },
+ "japanese_goblin": {
+ "c": "people",
+ "e": "👺",
+ "d": "japanese goblin",
+ "u": "6.0"
+ },
+ "japanese_ogre": {
+ "c": "people",
+ "e": "👹",
+ "d": "japanese ogre",
+ "u": "6.0"
+ },
+ "jeans": {
+ "c": "people",
+ "e": "👖",
+ "d": "jeans",
+ "u": "6.0"
+ },
+ "joy": {
+ "c": "people",
+ "e": "😂",
+ "d": "face with tears of joy",
+ "u": "6.0"
+ },
+ "joy_cat": {
+ "c": "people",
+ "e": "😹",
+ "d": "cat face with tears of joy",
+ "u": "6.0"
+ },
+ "joystick": {
+ "c": "objects",
+ "e": "🕹",
+ "d": "joystick",
+ "u": "7.0"
+ },
+ "juggling": {
+ "c": "activity",
+ "e": "🤹",
+ "d": "juggling",
+ "u": "9.0"
+ },
+ "juggling_tone1": {
+ "c": "activity",
+ "e": "🤹ðŸ»",
+ "d": "juggling tone 1",
+ "u": "9.0"
+ },
+ "juggling_tone2": {
+ "c": "activity",
+ "e": "🤹ðŸ¼",
+ "d": "juggling tone 2",
+ "u": "9.0"
+ },
+ "juggling_tone3": {
+ "c": "activity",
+ "e": "🤹ðŸ½",
+ "d": "juggling tone 3",
+ "u": "9.0"
+ },
+ "juggling_tone4": {
+ "c": "activity",
+ "e": "🤹ðŸ¾",
+ "d": "juggling tone 4",
+ "u": "9.0"
+ },
+ "juggling_tone5": {
+ "c": "activity",
+ "e": "🤹ðŸ¿",
+ "d": "juggling tone 5",
+ "u": "9.0"
+ },
+ "kaaba": {
+ "c": "travel",
+ "e": "🕋",
+ "d": "kaaba",
+ "u": "8.0"
+ },
+ "key": {
+ "c": "objects",
+ "e": "🔑",
+ "d": "key",
+ "u": "6.0"
+ },
+ "key2": {
+ "c": "objects",
+ "e": "ðŸ—",
+ "d": "old key",
+ "u": "7.0"
+ },
+ "keyboard": {
+ "c": "objects",
+ "e": "⌨",
+ "d": "keyboard",
+ "u": "1.1"
+ },
+ "kimono": {
+ "c": "people",
+ "e": "👘",
+ "d": "kimono",
+ "u": "6.0"
+ },
+ "kiss": {
+ "c": "people",
+ "e": "💋",
+ "d": "kiss mark",
+ "u": "6.0"
+ },
+ "kiss_mm": {
+ "c": "people",
+ "e": "👨â€â¤ï¸â€ðŸ’‹â€ðŸ‘¨",
+ "d": "kiss (man,man)",
+ "u": "6.0"
+ },
+ "kiss_ww": {
+ "c": "people",
+ "e": "👩â€â¤ï¸â€ðŸ’‹â€ðŸ‘©",
+ "d": "kiss (woman,woman)",
+ "u": "6.0"
+ },
+ "kissing": {
+ "c": "people",
+ "e": "😗",
+ "d": "kissing face",
+ "u": "6.1"
+ },
+ "kissing_cat": {
+ "c": "people",
+ "e": "😽",
+ "d": "kissing cat face with closed eyes",
+ "u": "6.0"
+ },
+ "kissing_closed_eyes": {
+ "c": "people",
+ "e": "😚",
+ "d": "kissing face with closed eyes",
+ "u": "6.0"
+ },
+ "kissing_heart": {
+ "c": "people",
+ "e": "😘",
+ "d": "face throwing a kiss",
+ "u": "6.0"
+ },
+ "kissing_smiling_eyes": {
+ "c": "people",
+ "e": "😙",
+ "d": "kissing face with smiling eyes",
+ "u": "6.1"
+ },
+ "kiwi": {
+ "c": "food",
+ "e": "ðŸ¥",
+ "d": "kiwifruit",
+ "u": "9.0"
+ },
+ "knife": {
+ "c": "objects",
+ "e": "🔪",
+ "d": "hocho",
+ "u": "6.0"
+ },
+ "koala": {
+ "c": "nature",
+ "e": "ðŸ¨",
+ "d": "koala",
+ "u": "6.0"
+ },
+ "koko": {
+ "c": "symbols",
+ "e": "ðŸˆ",
+ "d": "squared katakana koko",
+ "u": "6.0"
+ },
+ "label": {
+ "c": "objects",
+ "e": "ðŸ·",
+ "d": "label",
+ "u": "7.0"
+ },
+ "large_blue_circle": {
+ "c": "symbols",
+ "e": "🔵",
+ "d": "large blue circle",
+ "u": "6.0"
+ },
+ "large_blue_diamond": {
+ "c": "symbols",
+ "e": "🔷",
+ "d": "large blue diamond",
+ "u": "6.0"
+ },
+ "large_orange_diamond": {
+ "c": "symbols",
+ "e": "🔶",
+ "d": "large orange diamond",
+ "u": "6.0"
+ },
+ "last_quarter_moon": {
+ "c": "nature",
+ "e": "🌗",
+ "d": "last quarter moon symbol",
+ "u": "6.0"
+ },
+ "last_quarter_moon_with_face": {
+ "c": "nature",
+ "e": "🌜",
+ "d": "last quarter moon with face",
+ "u": "6.0"
+ },
+ "laughing": {
+ "c": "people",
+ "e": "😆",
+ "d": "smiling face with open mouth and tightly-closed ey",
+ "u": "6.0"
+ },
+ "leaves": {
+ "c": "nature",
+ "e": "ðŸƒ",
+ "d": "leaf fluttering in wind",
+ "u": "6.0"
+ },
+ "ledger": {
+ "c": "objects",
+ "e": "📒",
+ "d": "ledger",
+ "u": "6.0"
+ },
+ "left_facing_fist": {
+ "c": "people",
+ "e": "🤛",
+ "d": "left-facing fist",
+ "u": "9.0"
+ },
+ "left_facing_fist_tone1": {
+ "c": "people",
+ "e": "🤛ðŸ»",
+ "d": "left facing fist tone 1",
+ "u": "9.0"
+ },
+ "left_facing_fist_tone2": {
+ "c": "people",
+ "e": "🤛ðŸ¼",
+ "d": "left facing fist tone 2",
+ "u": "9.0"
+ },
+ "left_facing_fist_tone3": {
+ "c": "people",
+ "e": "🤛ðŸ½",
+ "d": "left facing fist tone 3",
+ "u": "9.0"
+ },
+ "left_facing_fist_tone4": {
+ "c": "people",
+ "e": "🤛ðŸ¾",
+ "d": "left facing fist tone 4",
+ "u": "9.0"
+ },
+ "left_facing_fist_tone5": {
+ "c": "people",
+ "e": "🤛ðŸ¿",
+ "d": "left facing fist tone 5",
+ "u": "9.0"
+ },
+ "left_luggage": {
+ "c": "symbols",
+ "e": "🛅",
+ "d": "left luggage",
+ "u": "6.0"
+ },
+ "left_right_arrow": {
+ "c": "symbols",
+ "e": "↔",
+ "d": "left right arrow",
+ "u": "1.1"
+ },
+ "leftwards_arrow_with_hook": {
+ "c": "symbols",
+ "e": "↩",
+ "d": "leftwards arrow with hook",
+ "u": "1.1"
+ },
+ "lemon": {
+ "c": "food",
+ "e": "ðŸ‹",
+ "d": "lemon",
+ "u": "6.0"
+ },
+ "leo": {
+ "c": "symbols",
+ "e": "♌",
+ "d": "leo",
+ "u": "1.1"
+ },
+ "leopard": {
+ "c": "nature",
+ "e": "ðŸ†",
+ "d": "leopard",
+ "u": "6.0"
+ },
+ "level_slider": {
+ "c": "objects",
+ "e": "🎚",
+ "d": "level slider",
+ "u": "7.0"
+ },
+ "levitate": {
+ "c": "activity",
+ "e": "🕴",
+ "d": "man in business suit levitating",
+ "u": "7.0"
+ },
+ "libra": {
+ "c": "symbols",
+ "e": "♎",
+ "d": "libra",
+ "u": "1.1"
+ },
+ "lifter": {
+ "c": "activity",
+ "e": "ðŸ‹",
+ "d": "weight lifter",
+ "u": "7.0"
+ },
+ "lifter_tone1": {
+ "c": "activity",
+ "e": "ðŸ‹ðŸ»",
+ "d": "weight lifter tone 1",
+ "u": "8.0"
+ },
+ "lifter_tone2": {
+ "c": "activity",
+ "e": "ðŸ‹ðŸ¼",
+ "d": "weight lifter tone 2",
+ "u": "8.0"
+ },
+ "lifter_tone3": {
+ "c": "activity",
+ "e": "ðŸ‹ðŸ½",
+ "d": "weight lifter tone 3",
+ "u": "8.0"
+ },
+ "lifter_tone4": {
+ "c": "activity",
+ "e": "ðŸ‹ðŸ¾",
+ "d": "weight lifter tone 4",
+ "u": "8.0"
+ },
+ "lifter_tone5": {
+ "c": "activity",
+ "e": "ðŸ‹ðŸ¿",
+ "d": "weight lifter tone 5",
+ "u": "8.0"
+ },
+ "light_rail": {
+ "c": "travel",
+ "e": "🚈",
+ "d": "light rail",
+ "u": "6.0"
+ },
+ "link": {
+ "c": "objects",
+ "e": "🔗",
+ "d": "link symbol",
+ "u": "6.0"
+ },
+ "lion_face": {
+ "c": "nature",
+ "e": "ðŸ¦",
+ "d": "lion face",
+ "u": "8.0"
+ },
+ "lips": {
+ "c": "people",
+ "e": "👄",
+ "d": "mouth",
+ "u": "6.0"
+ },
+ "lipstick": {
+ "c": "people",
+ "e": "💄",
+ "d": "lipstick",
+ "u": "6.0"
+ },
+ "lizard": {
+ "c": "nature",
+ "e": "🦎",
+ "d": "lizard",
+ "u": "9.0"
+ },
+ "lock": {
+ "c": "objects",
+ "e": "🔒",
+ "d": "lock",
+ "u": "6.0"
+ },
+ "lock_with_ink_pen": {
+ "c": "objects",
+ "e": "ðŸ”",
+ "d": "lock with ink pen",
+ "u": "6.0"
+ },
+ "lollipop": {
+ "c": "food",
+ "e": "ðŸ­",
+ "d": "lollipop",
+ "u": "6.0"
+ },
+ "loop": {
+ "c": "symbols",
+ "e": "âž¿",
+ "d": "double curly loop",
+ "u": "6.0"
+ },
+ "loud_sound": {
+ "c": "symbols",
+ "e": "🔊",
+ "d": "speaker with three sound waves",
+ "u": "6.0"
+ },
+ "loudspeaker": {
+ "c": "symbols",
+ "e": "📢",
+ "d": "public address loudspeaker",
+ "u": "6.0"
+ },
+ "love_hotel": {
+ "c": "travel",
+ "e": "ðŸ©",
+ "d": "love hotel",
+ "u": "6.0"
+ },
+ "love_letter": {
+ "c": "objects",
+ "e": "💌",
+ "d": "love letter",
+ "u": "6.0"
+ },
+ "low_brightness": {
+ "c": "symbols",
+ "e": "🔅",
+ "d": "low brightness symbol",
+ "u": "6.0"
+ },
+ "lying_face": {
+ "c": "people",
+ "e": "🤥",
+ "d": "lying face",
+ "u": "9.0"
+ },
+ "m": {
+ "c": "symbols",
+ "e": "â“‚",
+ "d": "circled latin capital letter m",
+ "u": "1.1"
+ },
+ "mag": {
+ "c": "objects",
+ "e": "ðŸ”",
+ "d": "left-pointing magnifying glass",
+ "u": "6.0"
+ },
+ "mag_right": {
+ "c": "objects",
+ "e": "🔎",
+ "d": "right-pointing magnifying glass",
+ "u": "6.0"
+ },
+ "mahjong": {
+ "c": "symbols",
+ "e": "🀄",
+ "d": "mahjong tile red dragon",
+ "u": "5.1"
+ },
+ "mailbox": {
+ "c": "objects",
+ "e": "📫",
+ "d": "closed mailbox with raised flag",
+ "u": "6.0"
+ },
+ "mailbox_closed": {
+ "c": "objects",
+ "e": "📪",
+ "d": "closed mailbox with lowered flag",
+ "u": "6.0"
+ },
+ "mailbox_with_mail": {
+ "c": "objects",
+ "e": "📬",
+ "d": "open mailbox with raised flag",
+ "u": "6.0"
+ },
+ "mailbox_with_no_mail": {
+ "c": "objects",
+ "e": "📭",
+ "d": "open mailbox with lowered flag",
+ "u": "6.0"
+ },
+ "man": {
+ "c": "people",
+ "e": "👨",
+ "d": "man",
+ "u": "6.0"
+ },
+ "man_dancing": {
+ "c": "people",
+ "e": "🕺",
+ "d": "man dancing",
+ "u": "9.0"
+ },
+ "man_dancing_tone1": {
+ "c": "activity",
+ "e": "🕺ðŸ»",
+ "d": "man dancing tone 1",
+ "u": "9.0"
+ },
+ "man_dancing_tone2": {
+ "c": "activity",
+ "e": "🕺ðŸ¼",
+ "d": "man dancing tone 2",
+ "u": "9.0"
+ },
+ "man_dancing_tone3": {
+ "c": "activity",
+ "e": "🕺ðŸ½",
+ "d": "man dancing tone 3",
+ "u": "9.0"
+ },
+ "man_dancing_tone4": {
+ "c": "activity",
+ "e": "🕺ðŸ¾",
+ "d": "man dancing tone 4",
+ "u": "9.0"
+ },
+ "man_dancing_tone5": {
+ "c": "activity",
+ "e": "🕺ðŸ¿",
+ "d": "man dancing tone 5",
+ "u": "9.0"
+ },
+ "man_in_tuxedo": {
+ "c": "people",
+ "e": "🤵",
+ "d": "man in tuxedo",
+ "u": "9.0"
+ },
+ "man_in_tuxedo_tone1": {
+ "c": "people",
+ "e": "🤵ðŸ»",
+ "d": "man in tuxedo tone 1",
+ "u": "9.0"
+ },
+ "man_in_tuxedo_tone2": {
+ "c": "people",
+ "e": "🤵ðŸ¼",
+ "d": "man in tuxedo tone 2",
+ "u": "9.0"
+ },
+ "man_in_tuxedo_tone3": {
+ "c": "people",
+ "e": "🤵ðŸ½",
+ "d": "man in tuxedo tone 3",
+ "u": "9.0"
+ },
+ "man_in_tuxedo_tone4": {
+ "c": "people",
+ "e": "🤵ðŸ¾",
+ "d": "man in tuxedo tone 4",
+ "u": "9.0"
+ },
+ "man_in_tuxedo_tone5": {
+ "c": "people",
+ "e": "🤵ðŸ¿",
+ "d": "man in tuxedo tone 5",
+ "u": "9.0"
+ },
+ "man_tone1": {
+ "c": "people",
+ "e": "👨ðŸ»",
+ "d": "man tone 1",
+ "u": "8.0"
+ },
+ "man_tone2": {
+ "c": "people",
+ "e": "👨ðŸ¼",
+ "d": "man tone 2",
+ "u": "8.0"
+ },
+ "man_tone3": {
+ "c": "people",
+ "e": "👨ðŸ½",
+ "d": "man tone 3",
+ "u": "8.0"
+ },
+ "man_tone4": {
+ "c": "people",
+ "e": "👨ðŸ¾",
+ "d": "man tone 4",
+ "u": "8.0"
+ },
+ "man_tone5": {
+ "c": "people",
+ "e": "👨ðŸ¿",
+ "d": "man tone 5",
+ "u": "8.0"
+ },
+ "man_with_gua_pi_mao": {
+ "c": "people",
+ "e": "👲",
+ "d": "man with gua pi mao",
+ "u": "6.0"
+ },
+ "man_with_gua_pi_mao_tone1": {
+ "c": "people",
+ "e": "👲ðŸ»",
+ "d": "man with gua pi mao tone 1",
+ "u": "8.0"
+ },
+ "man_with_gua_pi_mao_tone2": {
+ "c": "people",
+ "e": "👲ðŸ¼",
+ "d": "man with gua pi mao tone 2",
+ "u": "8.0"
+ },
+ "man_with_gua_pi_mao_tone3": {
+ "c": "people",
+ "e": "👲ðŸ½",
+ "d": "man with gua pi mao tone 3",
+ "u": "8.0"
+ },
+ "man_with_gua_pi_mao_tone4": {
+ "c": "people",
+ "e": "👲ðŸ¾",
+ "d": "man with gua pi mao tone 4",
+ "u": "8.0"
+ },
+ "man_with_gua_pi_mao_tone5": {
+ "c": "people",
+ "e": "👲ðŸ¿",
+ "d": "man with gua pi mao tone 5",
+ "u": "8.0"
+ },
+ "man_with_turban": {
+ "c": "people",
+ "e": "👳",
+ "d": "man with turban",
+ "u": "6.0"
+ },
+ "man_with_turban_tone1": {
+ "c": "people",
+ "e": "👳ðŸ»",
+ "d": "man with turban tone 1",
+ "u": "8.0"
+ },
+ "man_with_turban_tone2": {
+ "c": "people",
+ "e": "👳ðŸ¼",
+ "d": "man with turban tone 2",
+ "u": "8.0"
+ },
+ "man_with_turban_tone3": {
+ "c": "people",
+ "e": "👳ðŸ½",
+ "d": "man with turban tone 3",
+ "u": "8.0"
+ },
+ "man_with_turban_tone4": {
+ "c": "people",
+ "e": "👳ðŸ¾",
+ "d": "man with turban tone 4",
+ "u": "8.0"
+ },
+ "man_with_turban_tone5": {
+ "c": "people",
+ "e": "👳ðŸ¿",
+ "d": "man with turban tone 5",
+ "u": "8.0"
+ },
+ "mans_shoe": {
+ "c": "people",
+ "e": "👞",
+ "d": "mans shoe",
+ "u": "6.0"
+ },
+ "map": {
+ "c": "objects",
+ "e": "🗺",
+ "d": "world map",
+ "u": "7.0"
+ },
+ "maple_leaf": {
+ "c": "nature",
+ "e": "ðŸ",
+ "d": "maple leaf",
+ "u": "6.0"
+ },
+ "martial_arts_uniform": {
+ "c": "activity",
+ "e": "🥋",
+ "d": "martial arts uniform",
+ "u": "9.0"
+ },
+ "mask": {
+ "c": "people",
+ "e": "😷",
+ "d": "face with medical mask",
+ "u": "6.0"
+ },
+ "massage": {
+ "c": "people",
+ "e": "💆",
+ "d": "face massage",
+ "u": "6.0"
+ },
+ "massage_tone1": {
+ "c": "people",
+ "e": "💆ðŸ»",
+ "d": "face massage tone 1",
+ "u": "8.0"
+ },
+ "massage_tone2": {
+ "c": "people",
+ "e": "💆ðŸ¼",
+ "d": "face massage tone 2",
+ "u": "8.0"
+ },
+ "massage_tone3": {
+ "c": "people",
+ "e": "💆ðŸ½",
+ "d": "face massage tone 3",
+ "u": "8.0"
+ },
+ "massage_tone4": {
+ "c": "people",
+ "e": "💆ðŸ¾",
+ "d": "face massage tone 4",
+ "u": "8.0"
+ },
+ "massage_tone5": {
+ "c": "people",
+ "e": "💆ðŸ¿",
+ "d": "face massage tone 5",
+ "u": "8.0"
+ },
+ "meat_on_bone": {
+ "c": "food",
+ "e": "ðŸ–",
+ "d": "meat on bone",
+ "u": "6.0"
+ },
+ "medal": {
+ "c": "activity",
+ "e": "ðŸ…",
+ "d": "sports medal",
+ "u": "7.0"
+ },
+ "mega": {
+ "c": "symbols",
+ "e": "📣",
+ "d": "cheering megaphone",
+ "u": "6.0"
+ },
+ "melon": {
+ "c": "food",
+ "e": "ðŸˆ",
+ "d": "melon",
+ "u": "6.0"
+ },
+ "menorah": {
+ "c": "symbols",
+ "e": "🕎",
+ "d": "menorah with nine branches",
+ "u": "8.0"
+ },
+ "mens": {
+ "c": "symbols",
+ "e": "🚹",
+ "d": "mens symbol",
+ "u": "6.0"
+ },
+ "metal": {
+ "c": "people",
+ "e": "🤘",
+ "d": "sign of the horns",
+ "u": "8.0"
+ },
+ "metal_tone1": {
+ "c": "people",
+ "e": "🤘ðŸ»",
+ "d": "sign of the horns tone 1",
+ "u": "8.0"
+ },
+ "metal_tone2": {
+ "c": "people",
+ "e": "🤘ðŸ¼",
+ "d": "sign of the horns tone 2",
+ "u": "8.0"
+ },
+ "metal_tone3": {
+ "c": "people",
+ "e": "🤘ðŸ½",
+ "d": "sign of the horns tone 3",
+ "u": "8.0"
+ },
+ "metal_tone4": {
+ "c": "people",
+ "e": "🤘ðŸ¾",
+ "d": "sign of the horns tone 4",
+ "u": "8.0"
+ },
+ "metal_tone5": {
+ "c": "people",
+ "e": "🤘ðŸ¿",
+ "d": "sign of the horns tone 5",
+ "u": "8.0"
+ },
+ "metro": {
+ "c": "travel",
+ "e": "🚇",
+ "d": "metro",
+ "u": "6.0"
+ },
+ "microphone": {
+ "c": "activity",
+ "e": "🎤",
+ "d": "microphone",
+ "u": "6.0"
+ },
+ "microphone2": {
+ "c": "objects",
+ "e": "🎙",
+ "d": "studio microphone",
+ "u": "7.0"
+ },
+ "microscope": {
+ "c": "objects",
+ "e": "🔬",
+ "d": "microscope",
+ "u": "6.0"
+ },
+ "middle_finger": {
+ "c": "people",
+ "e": "🖕",
+ "d": "reversed hand with middle finger extended",
+ "u": "7.0"
+ },
+ "middle_finger_tone1": {
+ "c": "people",
+ "e": "🖕ðŸ»",
+ "d": "reversed hand with middle finger extended tone 1",
+ "u": "8.0"
+ },
+ "middle_finger_tone2": {
+ "c": "people",
+ "e": "🖕ðŸ¼",
+ "d": "reversed hand with middle finger extended tone 2",
+ "u": "8.0"
+ },
+ "middle_finger_tone3": {
+ "c": "people",
+ "e": "🖕ðŸ½",
+ "d": "reversed hand with middle finger extended tone 3",
+ "u": "8.0"
+ },
+ "middle_finger_tone4": {
+ "c": "people",
+ "e": "🖕ðŸ¾",
+ "d": "reversed hand with middle finger extended tone 4",
+ "u": "8.0"
+ },
+ "middle_finger_tone5": {
+ "c": "people",
+ "e": "🖕ðŸ¿",
+ "d": "reversed hand with middle finger extended tone 5",
+ "u": "8.0"
+ },
+ "military_medal": {
+ "c": "activity",
+ "e": "🎖",
+ "d": "military medal",
+ "u": "7.0"
+ },
+ "milk": {
+ "c": "food",
+ "e": "🥛",
+ "d": "glass of milk",
+ "u": "9.0"
+ },
+ "milky_way": {
+ "c": "travel",
+ "e": "🌌",
+ "d": "milky way",
+ "u": "6.0"
+ },
+ "minibus": {
+ "c": "travel",
+ "e": "ðŸš",
+ "d": "minibus",
+ "u": "6.0"
+ },
+ "minidisc": {
+ "c": "objects",
+ "e": "💽",
+ "d": "minidisc",
+ "u": "6.0"
+ },
+ "mobile_phone_off": {
+ "c": "symbols",
+ "e": "📴",
+ "d": "mobile phone off",
+ "u": "6.0"
+ },
+ "money_mouth": {
+ "c": "people",
+ "e": "🤑",
+ "d": "money-mouth face",
+ "u": "8.0"
+ },
+ "money_with_wings": {
+ "c": "objects",
+ "e": "💸",
+ "d": "money with wings",
+ "u": "6.0"
+ },
+ "moneybag": {
+ "c": "objects",
+ "e": "💰",
+ "d": "money bag",
+ "u": "6.0"
+ },
+ "monkey": {
+ "c": "nature",
+ "e": "ðŸ’",
+ "d": "monkey",
+ "u": "6.0"
+ },
+ "monkey_face": {
+ "c": "nature",
+ "e": "ðŸµ",
+ "d": "monkey face",
+ "u": "6.0"
+ },
+ "monorail": {
+ "c": "travel",
+ "e": "ðŸš",
+ "d": "monorail",
+ "u": "6.0"
+ },
+ "mortar_board": {
+ "c": "people",
+ "e": "🎓",
+ "d": "graduation cap",
+ "u": "6.0"
+ },
+ "mosque": {
+ "c": "travel",
+ "e": "🕌",
+ "d": "mosque",
+ "u": "8.0"
+ },
+ "motor_scooter": {
+ "c": "travel",
+ "e": "🛵",
+ "d": "motor scooter",
+ "u": "9.0"
+ },
+ "motorboat": {
+ "c": "travel",
+ "e": "🛥",
+ "d": "motorboat",
+ "u": "7.0"
+ },
+ "motorcycle": {
+ "c": "travel",
+ "e": "ðŸ",
+ "d": "racing motorcycle",
+ "u": "7.0"
+ },
+ "motorway": {
+ "c": "travel",
+ "e": "🛣",
+ "d": "motorway",
+ "u": "7.0"
+ },
+ "mount_fuji": {
+ "c": "travel",
+ "e": "🗻",
+ "d": "mount fuji",
+ "u": "6.0"
+ },
+ "mountain": {
+ "c": "travel",
+ "e": "â›°",
+ "d": "mountain",
+ "u": "5.2"
+ },
+ "mountain_bicyclist": {
+ "c": "activity",
+ "e": "🚵",
+ "d": "mountain bicyclist",
+ "u": "6.0"
+ },
+ "mountain_bicyclist_tone1": {
+ "c": "activity",
+ "e": "🚵ðŸ»",
+ "d": "mountain bicyclist tone 1",
+ "u": "8.0"
+ },
+ "mountain_bicyclist_tone2": {
+ "c": "activity",
+ "e": "🚵ðŸ¼",
+ "d": "mountain bicyclist tone 2",
+ "u": "8.0"
+ },
+ "mountain_bicyclist_tone3": {
+ "c": "activity",
+ "e": "🚵ðŸ½",
+ "d": "mountain bicyclist tone 3",
+ "u": "8.0"
+ },
+ "mountain_bicyclist_tone4": {
+ "c": "activity",
+ "e": "🚵ðŸ¾",
+ "d": "mountain bicyclist tone 4",
+ "u": "8.0"
+ },
+ "mountain_bicyclist_tone5": {
+ "c": "activity",
+ "e": "🚵ðŸ¿",
+ "d": "mountain bicyclist tone 5",
+ "u": "8.0"
+ },
+ "mountain_cableway": {
+ "c": "travel",
+ "e": "🚠",
+ "d": "mountain cableway",
+ "u": "6.0"
+ },
+ "mountain_railway": {
+ "c": "travel",
+ "e": "🚞",
+ "d": "mountain railway",
+ "u": "6.0"
+ },
+ "mountain_snow": {
+ "c": "travel",
+ "e": "ðŸ”",
+ "d": "snow capped mountain",
+ "u": "7.0"
+ },
+ "mouse": {
+ "c": "nature",
+ "e": "ðŸ­",
+ "d": "mouse face",
+ "u": "6.0"
+ },
+ "mouse2": {
+ "c": "nature",
+ "e": "ðŸ",
+ "d": "mouse",
+ "u": "6.0"
+ },
+ "mouse_three_button": {
+ "c": "objects",
+ "e": "🖱",
+ "d": "three button mouse",
+ "u": "7.0"
+ },
+ "movie_camera": {
+ "c": "objects",
+ "e": "🎥",
+ "d": "movie camera",
+ "u": "6.0"
+ },
+ "moyai": {
+ "c": "objects",
+ "e": "🗿",
+ "d": "moyai",
+ "u": "6.0"
+ },
+ "mrs_claus": {
+ "c": "people",
+ "e": "🤶",
+ "d": "mother christmas",
+ "u": "9.0"
+ },
+ "mrs_claus_tone1": {
+ "c": "people",
+ "e": "🤶ðŸ»",
+ "d": "mother christmas tone 1",
+ "u": "9.0"
+ },
+ "mrs_claus_tone2": {
+ "c": "people",
+ "e": "🤶ðŸ¼",
+ "d": "mother christmas tone 2",
+ "u": "9.0"
+ },
+ "mrs_claus_tone3": {
+ "c": "people",
+ "e": "🤶ðŸ½",
+ "d": "mother christmas tone 3",
+ "u": "9.0"
+ },
+ "mrs_claus_tone4": {
+ "c": "people",
+ "e": "🤶ðŸ¾",
+ "d": "mother christmas tone 4",
+ "u": "9.0"
+ },
+ "mrs_claus_tone5": {
+ "c": "people",
+ "e": "🤶ðŸ¿",
+ "d": "mother christmas tone 5",
+ "u": "9.0"
+ },
+ "muscle": {
+ "c": "people",
+ "e": "💪",
+ "d": "flexed biceps",
+ "u": "6.0"
+ },
+ "muscle_tone1": {
+ "c": "people",
+ "e": "💪ðŸ»",
+ "d": "flexed biceps tone 1",
+ "u": "8.0"
+ },
+ "muscle_tone2": {
+ "c": "people",
+ "e": "💪ðŸ¼",
+ "d": "flexed biceps tone 2",
+ "u": "8.0"
+ },
+ "muscle_tone3": {
+ "c": "people",
+ "e": "💪ðŸ½",
+ "d": "flexed biceps tone 3",
+ "u": "8.0"
+ },
+ "muscle_tone4": {
+ "c": "people",
+ "e": "💪ðŸ¾",
+ "d": "flexed biceps tone 4",
+ "u": "8.0"
+ },
+ "muscle_tone5": {
+ "c": "people",
+ "e": "💪ðŸ¿",
+ "d": "flexed biceps tone 5",
+ "u": "8.0"
+ },
+ "mushroom": {
+ "c": "nature",
+ "e": "ðŸ„",
+ "d": "mushroom",
+ "u": "6.0"
+ },
+ "musical_keyboard": {
+ "c": "activity",
+ "e": "🎹",
+ "d": "musical keyboard",
+ "u": "6.0"
+ },
+ "musical_note": {
+ "c": "symbols",
+ "e": "🎵",
+ "d": "musical note",
+ "u": "6.0"
+ },
+ "musical_score": {
+ "c": "activity",
+ "e": "🎼",
+ "d": "musical score",
+ "u": "6.0"
+ },
+ "mute": {
+ "c": "symbols",
+ "e": "🔇",
+ "d": "speaker with cancellation stroke",
+ "u": "6.0"
+ },
+ "nail_care": {
+ "c": "people",
+ "e": "💅",
+ "d": "nail polish",
+ "u": "6.0"
+ },
+ "nail_care_tone1": {
+ "c": "people",
+ "e": "💅ðŸ»",
+ "d": "nail polish tone 1",
+ "u": "8.0"
+ },
+ "nail_care_tone2": {
+ "c": "people",
+ "e": "💅ðŸ¼",
+ "d": "nail polish tone 2",
+ "u": "8.0"
+ },
+ "nail_care_tone3": {
+ "c": "people",
+ "e": "💅ðŸ½",
+ "d": "nail polish tone 3",
+ "u": "8.0"
+ },
+ "nail_care_tone4": {
+ "c": "people",
+ "e": "💅ðŸ¾",
+ "d": "nail polish tone 4",
+ "u": "8.0"
+ },
+ "nail_care_tone5": {
+ "c": "people",
+ "e": "💅ðŸ¿",
+ "d": "nail polish tone 5",
+ "u": "8.0"
+ },
+ "name_badge": {
+ "c": "symbols",
+ "e": "📛",
+ "d": "name badge",
+ "u": "6.0"
+ },
+ "nauseated_face": {
+ "c": "people",
+ "e": "🤢",
+ "d": "nauseated face",
+ "u": "9.0"
+ },
+ "necktie": {
+ "c": "people",
+ "e": "👔",
+ "d": "necktie",
+ "u": "6.0"
+ },
+ "negative_squared_cross_mark": {
+ "c": "symbols",
+ "e": "âŽ",
+ "d": "negative squared cross mark",
+ "u": "6.0"
+ },
+ "nerd": {
+ "c": "people",
+ "e": "🤓",
+ "d": "nerd face",
+ "u": "8.0"
+ },
+ "neutral_face": {
+ "c": "people",
+ "e": "ðŸ˜",
+ "d": "neutral face",
+ "u": "6.0"
+ },
+ "new": {
+ "c": "symbols",
+ "e": "🆕",
+ "d": "squared new",
+ "u": "6.0"
+ },
+ "new_moon": {
+ "c": "nature",
+ "e": "🌑",
+ "d": "new moon symbol",
+ "u": "6.0"
+ },
+ "new_moon_with_face": {
+ "c": "nature",
+ "e": "🌚",
+ "d": "new moon with face",
+ "u": "6.0"
+ },
+ "newspaper": {
+ "c": "objects",
+ "e": "📰",
+ "d": "newspaper",
+ "u": "6.0"
+ },
+ "newspaper2": {
+ "c": "objects",
+ "e": "🗞",
+ "d": "rolled-up newspaper",
+ "u": "7.0"
+ },
+ "ng": {
+ "c": "symbols",
+ "e": "🆖",
+ "d": "squared ng",
+ "u": "6.0"
+ },
+ "night_with_stars": {
+ "c": "travel",
+ "e": "🌃",
+ "d": "night with stars",
+ "u": "6.0"
+ },
+ "nine": {
+ "c": "symbols",
+ "e": "9ï¸âƒ£",
+ "d": "keycap digit nine",
+ "u": "3.0"
+ },
+ "no_bell": {
+ "c": "symbols",
+ "e": "🔕",
+ "d": "bell with cancellation stroke",
+ "u": "6.0"
+ },
+ "no_bicycles": {
+ "c": "symbols",
+ "e": "🚳",
+ "d": "no bicycles",
+ "u": "6.0"
+ },
+ "no_entry": {
+ "c": "symbols",
+ "e": "â›”",
+ "d": "no entry",
+ "u": "5.2"
+ },
+ "no_entry_sign": {
+ "c": "symbols",
+ "e": "🚫",
+ "d": "no entry sign",
+ "u": "6.0"
+ },
+ "no_good": {
+ "c": "people",
+ "e": "🙅",
+ "d": "face with no good gesture",
+ "u": "6.0"
+ },
+ "no_good_tone1": {
+ "c": "people",
+ "e": "🙅ðŸ»",
+ "d": "face with no good gesture tone 1",
+ "u": "8.0"
+ },
+ "no_good_tone2": {
+ "c": "people",
+ "e": "🙅ðŸ¼",
+ "d": "face with no good gesture tone 2",
+ "u": "8.0"
+ },
+ "no_good_tone3": {
+ "c": "people",
+ "e": "🙅ðŸ½",
+ "d": "face with no good gesture tone 3",
+ "u": "8.0"
+ },
+ "no_good_tone4": {
+ "c": "people",
+ "e": "🙅ðŸ¾",
+ "d": "face with no good gesture tone 4",
+ "u": "8.0"
+ },
+ "no_good_tone5": {
+ "c": "people",
+ "e": "🙅ðŸ¿",
+ "d": "face with no good gesture tone 5",
+ "u": "8.0"
+ },
+ "no_mobile_phones": {
+ "c": "symbols",
+ "e": "📵",
+ "d": "no mobile phones",
+ "u": "6.0"
+ },
+ "no_mouth": {
+ "c": "people",
+ "e": "😶",
+ "d": "face without mouth",
+ "u": "6.0"
+ },
+ "no_pedestrians": {
+ "c": "symbols",
+ "e": "🚷",
+ "d": "no pedestrians",
+ "u": "6.0"
+ },
+ "no_smoking": {
+ "c": "symbols",
+ "e": "🚭",
+ "d": "no smoking symbol",
+ "u": "6.0"
+ },
+ "non-potable_water": {
+ "c": "symbols",
+ "e": "🚱",
+ "d": "non-potable water symbol",
+ "u": "6.0"
+ },
+ "nose": {
+ "c": "people",
+ "e": "👃",
+ "d": "nose",
+ "u": "6.0"
+ },
+ "nose_tone1": {
+ "c": "people",
+ "e": "👃ðŸ»",
+ "d": "nose tone 1",
+ "u": "8.0"
+ },
+ "nose_tone2": {
+ "c": "people",
+ "e": "👃ðŸ¼",
+ "d": "nose tone 2",
+ "u": "8.0"
+ },
+ "nose_tone3": {
+ "c": "people",
+ "e": "👃ðŸ½",
+ "d": "nose tone 3",
+ "u": "8.0"
+ },
+ "nose_tone4": {
+ "c": "people",
+ "e": "👃ðŸ¾",
+ "d": "nose tone 4",
+ "u": "8.0"
+ },
+ "nose_tone5": {
+ "c": "people",
+ "e": "👃ðŸ¿",
+ "d": "nose tone 5",
+ "u": "8.0"
+ },
+ "notebook": {
+ "c": "objects",
+ "e": "📓",
+ "d": "notebook",
+ "u": "6.0"
+ },
+ "notebook_with_decorative_cover": {
+ "c": "objects",
+ "e": "📔",
+ "d": "notebook with decorative cover",
+ "u": "6.0"
+ },
+ "notepad_spiral": {
+ "c": "objects",
+ "e": "🗒",
+ "d": "spiral note pad",
+ "u": "7.0"
+ },
+ "notes": {
+ "c": "symbols",
+ "e": "🎶",
+ "d": "multiple musical notes",
+ "u": "6.0"
+ },
+ "nut_and_bolt": {
+ "c": "objects",
+ "e": "🔩",
+ "d": "nut and bolt",
+ "u": "6.0"
+ },
+ "o": {
+ "c": "symbols",
+ "e": "â­•",
+ "d": "heavy large circle",
+ "u": "5.2"
+ },
+ "o2": {
+ "c": "symbols",
+ "e": "🅾",
+ "d": "negative squared latin capital letter o",
+ "u": "6.0"
+ },
+ "ocean": {
+ "c": "nature",
+ "e": "🌊",
+ "d": "water wave",
+ "u": "6.0"
+ },
+ "octagonal_sign": {
+ "c": "symbols",
+ "e": "🛑",
+ "d": "octagonal sign",
+ "u": "9.0"
+ },
+ "octopus": {
+ "c": "nature",
+ "e": "ðŸ™",
+ "d": "octopus",
+ "u": "6.0"
+ },
+ "oden": {
+ "c": "food",
+ "e": "ðŸ¢",
+ "d": "oden",
+ "u": "6.0"
+ },
+ "office": {
+ "c": "travel",
+ "e": "ðŸ¢",
+ "d": "office building",
+ "u": "6.0"
+ },
+ "oil": {
+ "c": "objects",
+ "e": "🛢",
+ "d": "oil drum",
+ "u": "7.0"
+ },
+ "ok": {
+ "c": "symbols",
+ "e": "🆗",
+ "d": "squared ok",
+ "u": "6.0"
+ },
+ "ok_hand": {
+ "c": "people",
+ "e": "👌",
+ "d": "ok hand sign",
+ "u": "6.0"
+ },
+ "ok_hand_tone1": {
+ "c": "people",
+ "e": "👌ðŸ»",
+ "d": "ok hand sign tone 1",
+ "u": "8.0"
+ },
+ "ok_hand_tone2": {
+ "c": "people",
+ "e": "👌ðŸ¼",
+ "d": "ok hand sign tone 2",
+ "u": "8.0"
+ },
+ "ok_hand_tone3": {
+ "c": "people",
+ "e": "👌ðŸ½",
+ "d": "ok hand sign tone 3",
+ "u": "8.0"
+ },
+ "ok_hand_tone4": {
+ "c": "people",
+ "e": "👌ðŸ¾",
+ "d": "ok hand sign tone 4",
+ "u": "8.0"
+ },
+ "ok_hand_tone5": {
+ "c": "people",
+ "e": "👌ðŸ¿",
+ "d": "ok hand sign tone 5",
+ "u": "8.0"
+ },
+ "ok_woman": {
+ "c": "people",
+ "e": "🙆",
+ "d": "face with ok gesture",
+ "u": "6.0"
+ },
+ "ok_woman_tone1": {
+ "c": "people",
+ "e": "🙆ðŸ»",
+ "d": "face with ok gesture tone1",
+ "u": "8.0"
+ },
+ "ok_woman_tone2": {
+ "c": "people",
+ "e": "🙆ðŸ¼",
+ "d": "face with ok gesture tone2",
+ "u": "8.0"
+ },
+ "ok_woman_tone3": {
+ "c": "people",
+ "e": "🙆ðŸ½",
+ "d": "face with ok gesture tone3",
+ "u": "8.0"
+ },
+ "ok_woman_tone4": {
+ "c": "people",
+ "e": "🙆ðŸ¾",
+ "d": "face with ok gesture tone4",
+ "u": "8.0"
+ },
+ "ok_woman_tone5": {
+ "c": "people",
+ "e": "🙆ðŸ¿",
+ "d": "face with ok gesture tone5",
+ "u": "8.0"
+ },
+ "older_man": {
+ "c": "people",
+ "e": "👴",
+ "d": "older man",
+ "u": "6.0"
+ },
+ "older_man_tone1": {
+ "c": "people",
+ "e": "👴ðŸ»",
+ "d": "older man tone 1",
+ "u": "8.0"
+ },
+ "older_man_tone2": {
+ "c": "people",
+ "e": "👴ðŸ¼",
+ "d": "older man tone 2",
+ "u": "8.0"
+ },
+ "older_man_tone3": {
+ "c": "people",
+ "e": "👴ðŸ½",
+ "d": "older man tone 3",
+ "u": "8.0"
+ },
+ "older_man_tone4": {
+ "c": "people",
+ "e": "👴ðŸ¾",
+ "d": "older man tone 4",
+ "u": "8.0"
+ },
+ "older_man_tone5": {
+ "c": "people",
+ "e": "👴ðŸ¿",
+ "d": "older man tone 5",
+ "u": "8.0"
+ },
+ "older_woman": {
+ "c": "people",
+ "e": "👵",
+ "d": "older woman",
+ "u": "6.0"
+ },
+ "older_woman_tone1": {
+ "c": "people",
+ "e": "👵ðŸ»",
+ "d": "older woman tone 1",
+ "u": "8.0"
+ },
+ "older_woman_tone2": {
+ "c": "people",
+ "e": "👵ðŸ¼",
+ "d": "older woman tone 2",
+ "u": "8.0"
+ },
+ "older_woman_tone3": {
+ "c": "people",
+ "e": "👵ðŸ½",
+ "d": "older woman tone 3",
+ "u": "8.0"
+ },
+ "older_woman_tone4": {
+ "c": "people",
+ "e": "👵ðŸ¾",
+ "d": "older woman tone 4",
+ "u": "8.0"
+ },
+ "older_woman_tone5": {
+ "c": "people",
+ "e": "👵ðŸ¿",
+ "d": "older woman tone 5",
+ "u": "8.0"
+ },
+ "om_symbol": {
+ "c": "symbols",
+ "e": "🕉",
+ "d": "om symbol",
+ "u": "7.0"
+ },
+ "on": {
+ "c": "symbols",
+ "e": "🔛",
+ "d": "on with exclamation mark with left right arrow abo",
+ "u": "6.0"
+ },
+ "oncoming_automobile": {
+ "c": "travel",
+ "e": "🚘",
+ "d": "oncoming automobile",
+ "u": "6.0"
+ },
+ "oncoming_bus": {
+ "c": "travel",
+ "e": "ðŸš",
+ "d": "oncoming bus",
+ "u": "6.0"
+ },
+ "oncoming_police_car": {
+ "c": "travel",
+ "e": "🚔",
+ "d": "oncoming police car",
+ "u": "6.0"
+ },
+ "oncoming_taxi": {
+ "c": "travel",
+ "e": "🚖",
+ "d": "oncoming taxi",
+ "u": "6.0"
+ },
+ "one": {
+ "c": "symbols",
+ "e": "1ï¸âƒ£",
+ "d": "keycap digit one",
+ "u": "3.0"
+ },
+ "open_file_folder": {
+ "c": "objects",
+ "e": "📂",
+ "d": "open file folder",
+ "u": "6.0"
+ },
+ "open_hands": {
+ "c": "people",
+ "e": "ðŸ‘",
+ "d": "open hands sign",
+ "u": "6.0"
+ },
+ "open_hands_tone1": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ»",
+ "d": "open hands sign tone 1",
+ "u": "8.0"
+ },
+ "open_hands_tone2": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¼",
+ "d": "open hands sign tone 2",
+ "u": "8.0"
+ },
+ "open_hands_tone3": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ½",
+ "d": "open hands sign tone 3",
+ "u": "8.0"
+ },
+ "open_hands_tone4": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¾",
+ "d": "open hands sign tone 4",
+ "u": "8.0"
+ },
+ "open_hands_tone5": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¿",
+ "d": "open hands sign tone 5",
+ "u": "8.0"
+ },
+ "open_mouth": {
+ "c": "people",
+ "e": "😮",
+ "d": "face with open mouth",
+ "u": "6.1"
+ },
+ "ophiuchus": {
+ "c": "symbols",
+ "e": "⛎",
+ "d": "ophiuchus",
+ "u": "6.0"
+ },
+ "orange_book": {
+ "c": "objects",
+ "e": "📙",
+ "d": "orange book",
+ "u": "6.0"
+ },
+ "orthodox_cross": {
+ "c": "symbols",
+ "e": "☦",
+ "d": "orthodox cross",
+ "u": "1.1"
+ },
+ "outbox_tray": {
+ "c": "objects",
+ "e": "📤",
+ "d": "outbox tray",
+ "u": "6.0"
+ },
+ "owl": {
+ "c": "nature",
+ "e": "🦉",
+ "d": "owl",
+ "u": "9.0"
+ },
+ "ox": {
+ "c": "nature",
+ "e": "ðŸ‚",
+ "d": "ox",
+ "u": "6.0"
+ },
+ "package": {
+ "c": "objects",
+ "e": "📦",
+ "d": "package",
+ "u": "6.0"
+ },
+ "page_facing_up": {
+ "c": "objects",
+ "e": "📄",
+ "d": "page facing up",
+ "u": "6.0"
+ },
+ "page_with_curl": {
+ "c": "objects",
+ "e": "📃",
+ "d": "page with curl",
+ "u": "6.0"
+ },
+ "pager": {
+ "c": "objects",
+ "e": "📟",
+ "d": "pager",
+ "u": "6.0"
+ },
+ "paintbrush": {
+ "c": "objects",
+ "e": "🖌",
+ "d": "lower left paintbrush",
+ "u": "7.0"
+ },
+ "palm_tree": {
+ "c": "nature",
+ "e": "🌴",
+ "d": "palm tree",
+ "u": "6.0"
+ },
+ "pancakes": {
+ "c": "food",
+ "e": "🥞",
+ "d": "pancakes",
+ "u": "9.0"
+ },
+ "panda_face": {
+ "c": "nature",
+ "e": "ðŸ¼",
+ "d": "panda face",
+ "u": "6.0"
+ },
+ "paperclip": {
+ "c": "objects",
+ "e": "📎",
+ "d": "paperclip",
+ "u": "6.0"
+ },
+ "paperclips": {
+ "c": "objects",
+ "e": "🖇",
+ "d": "linked paperclips",
+ "u": "7.0"
+ },
+ "park": {
+ "c": "travel",
+ "e": "ðŸž",
+ "d": "national park",
+ "u": "7.0"
+ },
+ "parking": {
+ "c": "symbols",
+ "e": "🅿",
+ "d": "negative squared latin capital letter p",
+ "u": "5.2"
+ },
+ "part_alternation_mark": {
+ "c": "symbols",
+ "e": "〽",
+ "d": "part alternation mark",
+ "u": "3.2"
+ },
+ "partly_sunny": {
+ "c": "nature",
+ "e": "â›…",
+ "d": "sun behind cloud",
+ "u": "5.2"
+ },
+ "passport_control": {
+ "c": "symbols",
+ "e": "🛂",
+ "d": "passport control",
+ "u": "6.0"
+ },
+ "pause_button": {
+ "c": "symbols",
+ "e": "â¸",
+ "d": "double vertical bar",
+ "u": "7.0"
+ },
+ "peace": {
+ "c": "symbols",
+ "e": "☮",
+ "d": "peace symbol",
+ "u": "1.1"
+ },
+ "peach": {
+ "c": "food",
+ "e": "ðŸ‘",
+ "d": "peach",
+ "u": "6.0"
+ },
+ "peanuts": {
+ "c": "food",
+ "e": "🥜",
+ "d": "peanuts",
+ "u": "9.0"
+ },
+ "pear": {
+ "c": "food",
+ "e": "ðŸ",
+ "d": "pear",
+ "u": "6.0"
+ },
+ "pen_ballpoint": {
+ "c": "objects",
+ "e": "🖊",
+ "d": "lower left ballpoint pen",
+ "u": "7.0"
+ },
+ "pen_fountain": {
+ "c": "objects",
+ "e": "🖋",
+ "d": "lower left fountain pen",
+ "u": "7.0"
+ },
+ "pencil": {
+ "c": "objects",
+ "e": "ðŸ“",
+ "d": "memo",
+ "u": "6.0"
+ },
+ "pencil2": {
+ "c": "objects",
+ "e": "âœ",
+ "d": "pencil",
+ "u": "1.1"
+ },
+ "penguin": {
+ "c": "nature",
+ "e": "ðŸ§",
+ "d": "penguin",
+ "u": "6.0"
+ },
+ "pensive": {
+ "c": "people",
+ "e": "😔",
+ "d": "pensive face",
+ "u": "6.0"
+ },
+ "performing_arts": {
+ "c": "activity",
+ "e": "🎭",
+ "d": "performing arts",
+ "u": "6.0"
+ },
+ "persevere": {
+ "c": "people",
+ "e": "😣",
+ "d": "persevering face",
+ "u": "6.0"
+ },
+ "person_frowning": {
+ "c": "people",
+ "e": "ðŸ™",
+ "d": "person frowning",
+ "u": "6.0"
+ },
+ "person_frowning_tone1": {
+ "c": "people",
+ "e": "ðŸ™ðŸ»",
+ "d": "person frowning tone 1",
+ "u": "8.0"
+ },
+ "person_frowning_tone2": {
+ "c": "people",
+ "e": "ðŸ™ðŸ¼",
+ "d": "person frowning tone 2",
+ "u": "8.0"
+ },
+ "person_frowning_tone3": {
+ "c": "people",
+ "e": "ðŸ™ðŸ½",
+ "d": "person frowning tone 3",
+ "u": "8.0"
+ },
+ "person_frowning_tone4": {
+ "c": "people",
+ "e": "ðŸ™ðŸ¾",
+ "d": "person frowning tone 4",
+ "u": "8.0"
+ },
+ "person_frowning_tone5": {
+ "c": "people",
+ "e": "ðŸ™ðŸ¿",
+ "d": "person frowning tone 5",
+ "u": "8.0"
+ },
+ "person_with_blond_hair": {
+ "c": "people",
+ "e": "👱",
+ "d": "person with blond hair",
+ "u": "6.0"
+ },
+ "person_with_blond_hair_tone1": {
+ "c": "people",
+ "e": "👱ðŸ»",
+ "d": "person with blond hair tone 1",
+ "u": "8.0"
+ },
+ "person_with_blond_hair_tone2": {
+ "c": "people",
+ "e": "👱ðŸ¼",
+ "d": "person with blond hair tone 2",
+ "u": "8.0"
+ },
+ "person_with_blond_hair_tone3": {
+ "c": "people",
+ "e": "👱ðŸ½",
+ "d": "person with blond hair tone 3",
+ "u": "8.0"
+ },
+ "person_with_blond_hair_tone4": {
+ "c": "people",
+ "e": "👱ðŸ¾",
+ "d": "person with blond hair tone 4",
+ "u": "8.0"
+ },
+ "person_with_blond_hair_tone5": {
+ "c": "people",
+ "e": "👱ðŸ¿",
+ "d": "person with blond hair tone 5",
+ "u": "8.0"
+ },
+ "person_with_pouting_face": {
+ "c": "people",
+ "e": "🙎",
+ "d": "person with pouting face",
+ "u": "6.0"
+ },
+ "person_with_pouting_face_tone1": {
+ "c": "people",
+ "e": "🙎ðŸ»",
+ "d": "person with pouting face tone1",
+ "u": "8.0"
+ },
+ "person_with_pouting_face_tone2": {
+ "c": "people",
+ "e": "🙎ðŸ¼",
+ "d": "person with pouting face tone2",
+ "u": "8.0"
+ },
+ "person_with_pouting_face_tone3": {
+ "c": "people",
+ "e": "🙎ðŸ½",
+ "d": "person with pouting face tone3",
+ "u": "8.0"
+ },
+ "person_with_pouting_face_tone4": {
+ "c": "people",
+ "e": "🙎ðŸ¾",
+ "d": "person with pouting face tone4",
+ "u": "8.0"
+ },
+ "person_with_pouting_face_tone5": {
+ "c": "people",
+ "e": "🙎ðŸ¿",
+ "d": "person with pouting face tone5",
+ "u": "8.0"
+ },
+ "pick": {
+ "c": "objects",
+ "e": "â›",
+ "d": "pick",
+ "u": "5.2"
+ },
+ "pig": {
+ "c": "nature",
+ "e": "ðŸ·",
+ "d": "pig face",
+ "u": "6.0"
+ },
+ "pig2": {
+ "c": "nature",
+ "e": "ðŸ–",
+ "d": "pig",
+ "u": "6.0"
+ },
+ "pig_nose": {
+ "c": "nature",
+ "e": "ðŸ½",
+ "d": "pig nose",
+ "u": "6.0"
+ },
+ "pill": {
+ "c": "objects",
+ "e": "💊",
+ "d": "pill",
+ "u": "6.0"
+ },
+ "pineapple": {
+ "c": "food",
+ "e": "ðŸ",
+ "d": "pineapple",
+ "u": "6.0"
+ },
+ "ping_pong": {
+ "c": "activity",
+ "e": "ðŸ“",
+ "d": "table tennis paddle and ball",
+ "u": "8.0"
+ },
+ "pisces": {
+ "c": "symbols",
+ "e": "♓",
+ "d": "pisces",
+ "u": "1.1"
+ },
+ "pizza": {
+ "c": "food",
+ "e": "ðŸ•",
+ "d": "slice of pizza",
+ "u": "6.0"
+ },
+ "place_of_worship": {
+ "c": "symbols",
+ "e": "ðŸ›",
+ "d": "place of worship",
+ "u": "8.0"
+ },
+ "play_pause": {
+ "c": "symbols",
+ "e": "â¯",
+ "d": "black right-pointing double triangle with double vertical bar",
+ "u": "6.0"
+ },
+ "point_down": {
+ "c": "people",
+ "e": "👇",
+ "d": "white down pointing backhand index",
+ "u": "6.0"
+ },
+ "point_down_tone1": {
+ "c": "people",
+ "e": "👇ðŸ»",
+ "d": "white down pointing backhand index tone 1",
+ "u": "8.0"
+ },
+ "point_down_tone2": {
+ "c": "people",
+ "e": "👇ðŸ¼",
+ "d": "white down pointing backhand index tone 2",
+ "u": "8.0"
+ },
+ "point_down_tone3": {
+ "c": "people",
+ "e": "👇ðŸ½",
+ "d": "white down pointing backhand index tone 3",
+ "u": "8.0"
+ },
+ "point_down_tone4": {
+ "c": "people",
+ "e": "👇ðŸ¾",
+ "d": "white down pointing backhand index tone 4",
+ "u": "8.0"
+ },
+ "point_down_tone5": {
+ "c": "people",
+ "e": "👇ðŸ¿",
+ "d": "white down pointing backhand index tone 5",
+ "u": "8.0"
+ },
+ "point_left": {
+ "c": "people",
+ "e": "👈",
+ "d": "white left pointing backhand index",
+ "u": "6.0"
+ },
+ "point_left_tone1": {
+ "c": "people",
+ "e": "👈ðŸ»",
+ "d": "white left pointing backhand index tone 1",
+ "u": "8.0"
+ },
+ "point_left_tone2": {
+ "c": "people",
+ "e": "👈ðŸ¼",
+ "d": "white left pointing backhand index tone 2",
+ "u": "8.0"
+ },
+ "point_left_tone3": {
+ "c": "people",
+ "e": "👈ðŸ½",
+ "d": "white left pointing backhand index tone 3",
+ "u": "8.0"
+ },
+ "point_left_tone4": {
+ "c": "people",
+ "e": "👈ðŸ¾",
+ "d": "white left pointing backhand index tone 4",
+ "u": "8.0"
+ },
+ "point_left_tone5": {
+ "c": "people",
+ "e": "👈ðŸ¿",
+ "d": "white left pointing backhand index tone 5",
+ "u": "8.0"
+ },
+ "point_right": {
+ "c": "people",
+ "e": "👉",
+ "d": "white right pointing backhand index",
+ "u": "6.0"
+ },
+ "point_right_tone1": {
+ "c": "people",
+ "e": "👉ðŸ»",
+ "d": "white right pointing backhand index tone 1",
+ "u": "8.0"
+ },
+ "point_right_tone2": {
+ "c": "people",
+ "e": "👉ðŸ¼",
+ "d": "white right pointing backhand index tone 2",
+ "u": "8.0"
+ },
+ "point_right_tone3": {
+ "c": "people",
+ "e": "👉ðŸ½",
+ "d": "white right pointing backhand index tone 3",
+ "u": "8.0"
+ },
+ "point_right_tone4": {
+ "c": "people",
+ "e": "👉ðŸ¾",
+ "d": "white right pointing backhand index tone 4",
+ "u": "8.0"
+ },
+ "point_right_tone5": {
+ "c": "people",
+ "e": "👉ðŸ¿",
+ "d": "white right pointing backhand index tone 5",
+ "u": "8.0"
+ },
+ "point_up": {
+ "c": "people",
+ "e": "â˜",
+ "d": "white up pointing index",
+ "u": "1.1"
+ },
+ "point_up_2": {
+ "c": "people",
+ "e": "👆",
+ "d": "white up pointing backhand index",
+ "u": "6.0"
+ },
+ "point_up_2_tone1": {
+ "c": "people",
+ "e": "👆ðŸ»",
+ "d": "white up pointing backhand index tone 1",
+ "u": "8.0"
+ },
+ "point_up_2_tone2": {
+ "c": "people",
+ "e": "👆ðŸ¼",
+ "d": "white up pointing backhand index tone 2",
+ "u": "8.0"
+ },
+ "point_up_2_tone3": {
+ "c": "people",
+ "e": "👆ðŸ½",
+ "d": "white up pointing backhand index tone 3",
+ "u": "8.0"
+ },
+ "point_up_2_tone4": {
+ "c": "people",
+ "e": "👆ðŸ¾",
+ "d": "white up pointing backhand index tone 4",
+ "u": "8.0"
+ },
+ "point_up_2_tone5": {
+ "c": "people",
+ "e": "👆ðŸ¿",
+ "d": "white up pointing backhand index tone 5",
+ "u": "8.0"
+ },
+ "point_up_tone1": {
+ "c": "people",
+ "e": "â˜ðŸ»",
+ "d": "white up pointing index tone 1",
+ "u": "8.0"
+ },
+ "point_up_tone2": {
+ "c": "people",
+ "e": "â˜ðŸ¼",
+ "d": "white up pointing index tone 2",
+ "u": "8.0"
+ },
+ "point_up_tone3": {
+ "c": "people",
+ "e": "â˜ðŸ½",
+ "d": "white up pointing index tone 3",
+ "u": "8.0"
+ },
+ "point_up_tone4": {
+ "c": "people",
+ "e": "â˜ðŸ¾",
+ "d": "white up pointing index tone 4",
+ "u": "8.0"
+ },
+ "point_up_tone5": {
+ "c": "people",
+ "e": "â˜ðŸ¿",
+ "d": "white up pointing index tone 5",
+ "u": "8.0"
+ },
+ "police_car": {
+ "c": "travel",
+ "e": "🚓",
+ "d": "police car",
+ "u": "6.0"
+ },
+ "poodle": {
+ "c": "nature",
+ "e": "ðŸ©",
+ "d": "poodle",
+ "u": "6.0"
+ },
+ "poop": {
+ "c": "people",
+ "e": "💩",
+ "d": "pile of poo",
+ "u": "6.0"
+ },
+ "popcorn": {
+ "c": "food",
+ "e": "ðŸ¿",
+ "d": "popcorn",
+ "u": "8.0"
+ },
+ "post_office": {
+ "c": "travel",
+ "e": "ðŸ£",
+ "d": "japanese post office",
+ "u": "6.0"
+ },
+ "postal_horn": {
+ "c": "objects",
+ "e": "📯",
+ "d": "postal horn",
+ "u": "6.0"
+ },
+ "postbox": {
+ "c": "objects",
+ "e": "📮",
+ "d": "postbox",
+ "u": "6.0"
+ },
+ "potable_water": {
+ "c": "symbols",
+ "e": "🚰",
+ "d": "potable water symbol",
+ "u": "6.0"
+ },
+ "potato": {
+ "c": "food",
+ "e": "🥔",
+ "d": "potato",
+ "u": "9.0"
+ },
+ "pouch": {
+ "c": "people",
+ "e": "ðŸ‘",
+ "d": "pouch",
+ "u": "6.0"
+ },
+ "poultry_leg": {
+ "c": "food",
+ "e": "ðŸ—",
+ "d": "poultry leg",
+ "u": "6.0"
+ },
+ "pound": {
+ "c": "objects",
+ "e": "💷",
+ "d": "banknote with pound sign",
+ "u": "6.0"
+ },
+ "pouting_cat": {
+ "c": "people",
+ "e": "😾",
+ "d": "pouting cat face",
+ "u": "6.0"
+ },
+ "pray": {
+ "c": "people",
+ "e": "ðŸ™",
+ "d": "person with folded hands",
+ "u": "6.0"
+ },
+ "pray_tone1": {
+ "c": "people",
+ "e": "ðŸ™ðŸ»",
+ "d": "person with folded hands tone 1",
+ "u": "8.0"
+ },
+ "pray_tone2": {
+ "c": "people",
+ "e": "ðŸ™ðŸ¼",
+ "d": "person with folded hands tone 2",
+ "u": "8.0"
+ },
+ "pray_tone3": {
+ "c": "people",
+ "e": "ðŸ™ðŸ½",
+ "d": "person with folded hands tone 3",
+ "u": "8.0"
+ },
+ "pray_tone4": {
+ "c": "people",
+ "e": "ðŸ™ðŸ¾",
+ "d": "person with folded hands tone 4",
+ "u": "8.0"
+ },
+ "pray_tone5": {
+ "c": "people",
+ "e": "ðŸ™ðŸ¿",
+ "d": "person with folded hands tone 5",
+ "u": "8.0"
+ },
+ "prayer_beads": {
+ "c": "objects",
+ "e": "📿",
+ "d": "prayer beads",
+ "u": "8.0"
+ },
+ "pregnant_woman": {
+ "c": "people",
+ "e": "🤰",
+ "d": "pregnant woman",
+ "u": "9.0"
+ },
+ "pregnant_woman_tone1": {
+ "c": "people",
+ "e": "🤰ðŸ»",
+ "d": "pregnant woman tone 1",
+ "u": "9.0"
+ },
+ "pregnant_woman_tone2": {
+ "c": "people",
+ "e": "🤰ðŸ¼",
+ "d": "pregnant woman tone 2",
+ "u": "9.0"
+ },
+ "pregnant_woman_tone3": {
+ "c": "people",
+ "e": "🤰ðŸ½",
+ "d": "pregnant woman tone 3",
+ "u": "9.0"
+ },
+ "pregnant_woman_tone4": {
+ "c": "people",
+ "e": "🤰ðŸ¾",
+ "d": "pregnant woman tone 4",
+ "u": "9.0"
+ },
+ "pregnant_woman_tone5": {
+ "c": "people",
+ "e": "🤰ðŸ¿",
+ "d": "pregnant woman tone 5",
+ "u": "9.0"
+ },
+ "prince": {
+ "c": "people",
+ "e": "🤴",
+ "d": "prince",
+ "u": "9.0"
+ },
+ "prince_tone1": {
+ "c": "people",
+ "e": "🤴ðŸ»",
+ "d": "prince tone 1",
+ "u": "9.0"
+ },
+ "prince_tone2": {
+ "c": "people",
+ "e": "🤴ðŸ¼",
+ "d": "prince tone 2",
+ "u": "9.0"
+ },
+ "prince_tone3": {
+ "c": "people",
+ "e": "🤴ðŸ½",
+ "d": "prince tone 3",
+ "u": "9.0"
+ },
+ "prince_tone4": {
+ "c": "people",
+ "e": "🤴ðŸ¾",
+ "d": "prince tone 4",
+ "u": "9.0"
+ },
+ "prince_tone5": {
+ "c": "people",
+ "e": "🤴ðŸ¿",
+ "d": "prince tone 5",
+ "u": "9.0"
+ },
+ "princess": {
+ "c": "people",
+ "e": "👸",
+ "d": "princess",
+ "u": "6.0"
+ },
+ "princess_tone1": {
+ "c": "people",
+ "e": "👸ðŸ»",
+ "d": "princess tone 1",
+ "u": "8.0"
+ },
+ "princess_tone2": {
+ "c": "people",
+ "e": "👸ðŸ¼",
+ "d": "princess tone 2",
+ "u": "8.0"
+ },
+ "princess_tone3": {
+ "c": "people",
+ "e": "👸ðŸ½",
+ "d": "princess tone 3",
+ "u": "8.0"
+ },
+ "princess_tone4": {
+ "c": "people",
+ "e": "👸ðŸ¾",
+ "d": "princess tone 4",
+ "u": "8.0"
+ },
+ "princess_tone5": {
+ "c": "people",
+ "e": "👸ðŸ¿",
+ "d": "princess tone 5",
+ "u": "8.0"
+ },
+ "printer": {
+ "c": "objects",
+ "e": "🖨",
+ "d": "printer",
+ "u": "7.0"
+ },
+ "projector": {
+ "c": "objects",
+ "e": "📽",
+ "d": "film projector",
+ "u": "7.0"
+ },
+ "punch": {
+ "c": "people",
+ "e": "👊",
+ "d": "fisted hand sign",
+ "u": "6.0"
+ },
+ "punch_tone1": {
+ "c": "people",
+ "e": "👊ðŸ»",
+ "d": "fisted hand sign tone 1",
+ "u": "8.0"
+ },
+ "punch_tone2": {
+ "c": "people",
+ "e": "👊ðŸ¼",
+ "d": "fisted hand sign tone 2",
+ "u": "8.0"
+ },
+ "punch_tone3": {
+ "c": "people",
+ "e": "👊ðŸ½",
+ "d": "fisted hand sign tone 3",
+ "u": "8.0"
+ },
+ "punch_tone4": {
+ "c": "people",
+ "e": "👊ðŸ¾",
+ "d": "fisted hand sign tone 4",
+ "u": "8.0"
+ },
+ "punch_tone5": {
+ "c": "people",
+ "e": "👊ðŸ¿",
+ "d": "fisted hand sign tone 5",
+ "u": "8.0"
+ },
+ "purple_heart": {
+ "c": "symbols",
+ "e": "💜",
+ "d": "purple heart",
+ "u": "6.0"
+ },
+ "purse": {
+ "c": "people",
+ "e": "👛",
+ "d": "purse",
+ "u": "6.0"
+ },
+ "pushpin": {
+ "c": "objects",
+ "e": "📌",
+ "d": "pushpin",
+ "u": "6.0"
+ },
+ "put_litter_in_its_place": {
+ "c": "symbols",
+ "e": "🚮",
+ "d": "put litter in its place symbol",
+ "u": "6.0"
+ },
+ "question": {
+ "c": "symbols",
+ "e": "â“",
+ "d": "black question mark ornament",
+ "u": "6.0"
+ },
+ "rabbit": {
+ "c": "nature",
+ "e": "ðŸ°",
+ "d": "rabbit face",
+ "u": "6.0"
+ },
+ "rabbit2": {
+ "c": "nature",
+ "e": "ðŸ‡",
+ "d": "rabbit",
+ "u": "6.0"
+ },
+ "race_car": {
+ "c": "travel",
+ "e": "ðŸŽ",
+ "d": "racing car",
+ "u": "7.0"
+ },
+ "racehorse": {
+ "c": "nature",
+ "e": "ðŸŽ",
+ "d": "horse",
+ "u": "6.0"
+ },
+ "radio": {
+ "c": "objects",
+ "e": "📻",
+ "d": "radio",
+ "u": "6.0"
+ },
+ "radio_button": {
+ "c": "symbols",
+ "e": "🔘",
+ "d": "radio button",
+ "u": "6.0"
+ },
+ "radioactive": {
+ "c": "symbols",
+ "e": "☢",
+ "d": "radioactive sign",
+ "u": "1.1"
+ },
+ "rage": {
+ "c": "people",
+ "e": "😡",
+ "d": "pouting face",
+ "u": "6.0"
+ },
+ "railway_car": {
+ "c": "travel",
+ "e": "🚃",
+ "d": "railway car",
+ "u": "6.0"
+ },
+ "railway_track": {
+ "c": "travel",
+ "e": "🛤",
+ "d": "railway track",
+ "u": "7.0"
+ },
+ "rainbow": {
+ "c": "travel",
+ "e": "🌈",
+ "d": "rainbow",
+ "u": "6.0"
+ },
+ "raised_back_of_hand": {
+ "c": "people",
+ "e": "🤚",
+ "d": "raised back of hand",
+ "u": "9.0"
+ },
+ "raised_back_of_hand_tone1": {
+ "c": "people",
+ "e": "🤚ðŸ»",
+ "d": "raised back of hand tone 1",
+ "u": "9.0"
+ },
+ "raised_back_of_hand_tone2": {
+ "c": "people",
+ "e": "🤚ðŸ¼",
+ "d": "raised back of hand tone 2",
+ "u": "9.0"
+ },
+ "raised_back_of_hand_tone3": {
+ "c": "people",
+ "e": "🤚ðŸ½",
+ "d": "raised back of hand tone 3",
+ "u": "9.0"
+ },
+ "raised_back_of_hand_tone4": {
+ "c": "people",
+ "e": "🤚ðŸ¾",
+ "d": "raised back of hand tone 4",
+ "u": "9.0"
+ },
+ "raised_back_of_hand_tone5": {
+ "c": "people",
+ "e": "🤚ðŸ¿",
+ "d": "raised back of hand tone 5",
+ "u": "9.0"
+ },
+ "raised_hand": {
+ "c": "people",
+ "e": "✋",
+ "d": "raised hand",
+ "u": "6.0"
+ },
+ "raised_hand_tone1": {
+ "c": "people",
+ "e": "✋ðŸ»",
+ "d": "raised hand tone 1",
+ "u": "8.0"
+ },
+ "raised_hand_tone2": {
+ "c": "people",
+ "e": "✋ðŸ¼",
+ "d": "raised hand tone 2",
+ "u": "8.0"
+ },
+ "raised_hand_tone3": {
+ "c": "people",
+ "e": "✋ðŸ½",
+ "d": "raised hand tone 3",
+ "u": "8.0"
+ },
+ "raised_hand_tone4": {
+ "c": "people",
+ "e": "✋ðŸ¾",
+ "d": "raised hand tone 4",
+ "u": "8.0"
+ },
+ "raised_hand_tone5": {
+ "c": "people",
+ "e": "✋ðŸ¿",
+ "d": "raised hand tone 5",
+ "u": "8.0"
+ },
+ "raised_hands": {
+ "c": "people",
+ "e": "🙌",
+ "d": "person raising both hands in celebration",
+ "u": "6.0"
+ },
+ "raised_hands_tone1": {
+ "c": "people",
+ "e": "🙌ðŸ»",
+ "d": "person raising both hands in celebration tone 1",
+ "u": "8.0"
+ },
+ "raised_hands_tone2": {
+ "c": "people",
+ "e": "🙌ðŸ¼",
+ "d": "person raising both hands in celebration tone 2",
+ "u": "8.0"
+ },
+ "raised_hands_tone3": {
+ "c": "people",
+ "e": "🙌ðŸ½",
+ "d": "person raising both hands in celebration tone 3",
+ "u": "8.0"
+ },
+ "raised_hands_tone4": {
+ "c": "people",
+ "e": "🙌ðŸ¾",
+ "d": "person raising both hands in celebration tone 4",
+ "u": "8.0"
+ },
+ "raised_hands_tone5": {
+ "c": "people",
+ "e": "🙌ðŸ¿",
+ "d": "person raising both hands in celebration tone 5",
+ "u": "8.0"
+ },
+ "raising_hand": {
+ "c": "people",
+ "e": "🙋",
+ "d": "happy person raising one hand",
+ "u": "6.0"
+ },
+ "raising_hand_tone1": {
+ "c": "people",
+ "e": "🙋ðŸ»",
+ "d": "happy person raising one hand tone1",
+ "u": "8.0"
+ },
+ "raising_hand_tone2": {
+ "c": "people",
+ "e": "🙋ðŸ¼",
+ "d": "happy person raising one hand tone2",
+ "u": "8.0"
+ },
+ "raising_hand_tone3": {
+ "c": "people",
+ "e": "🙋ðŸ½",
+ "d": "happy person raising one hand tone3",
+ "u": "8.0"
+ },
+ "raising_hand_tone4": {
+ "c": "people",
+ "e": "🙋ðŸ¾",
+ "d": "happy person raising one hand tone4",
+ "u": "8.0"
+ },
+ "raising_hand_tone5": {
+ "c": "people",
+ "e": "🙋ðŸ¿",
+ "d": "happy person raising one hand tone5",
+ "u": "8.0"
+ },
+ "ram": {
+ "c": "nature",
+ "e": "ðŸ",
+ "d": "ram",
+ "u": "6.0"
+ },
+ "ramen": {
+ "c": "food",
+ "e": "ðŸœ",
+ "d": "steaming bowl",
+ "u": "6.0"
+ },
+ "rat": {
+ "c": "nature",
+ "e": "ðŸ€",
+ "d": "rat",
+ "u": "6.0"
+ },
+ "record_button": {
+ "c": "symbols",
+ "e": "âº",
+ "d": "black circle for record",
+ "u": "7.0"
+ },
+ "recycle": {
+ "c": "symbols",
+ "e": "â™»",
+ "d": "black universal recycling symbol",
+ "u": "3.2"
+ },
+ "red_car": {
+ "c": "travel",
+ "e": "🚗",
+ "d": "automobile",
+ "u": "6.0"
+ },
+ "red_circle": {
+ "c": "symbols",
+ "e": "🔴",
+ "d": "large red circle",
+ "u": "6.0"
+ },
+ "registered": {
+ "c": "symbols",
+ "e": "®ï¸",
+ "d": "registered sign",
+ "u": "1.1"
+ },
+ "relaxed": {
+ "c": "people",
+ "e": "☺",
+ "d": "white smiling face",
+ "u": "1.1"
+ },
+ "relieved": {
+ "c": "people",
+ "e": "😌",
+ "d": "relieved face",
+ "u": "6.0"
+ },
+ "reminder_ribbon": {
+ "c": "activity",
+ "e": "🎗",
+ "d": "reminder ribbon",
+ "u": "7.0"
+ },
+ "repeat": {
+ "c": "symbols",
+ "e": "ðŸ”",
+ "d": "clockwise rightwards and leftwards open circle arr",
+ "u": "6.0"
+ },
+ "repeat_one": {
+ "c": "symbols",
+ "e": "🔂",
+ "d": "clockwise rightwards and leftwards open circle arr",
+ "u": "6.0"
+ },
+ "restroom": {
+ "c": "symbols",
+ "e": "🚻",
+ "d": "restroom",
+ "u": "6.0"
+ },
+ "revolving_hearts": {
+ "c": "symbols",
+ "e": "💞",
+ "d": "revolving hearts",
+ "u": "6.0"
+ },
+ "rewind": {
+ "c": "symbols",
+ "e": "âª",
+ "d": "black left-pointing double triangle",
+ "u": "6.0"
+ },
+ "rhino": {
+ "c": "nature",
+ "e": "ðŸ¦",
+ "d": "rhinoceros",
+ "u": "9.0"
+ },
+ "ribbon": {
+ "c": "objects",
+ "e": "🎀",
+ "d": "ribbon",
+ "u": "6.0"
+ },
+ "rice": {
+ "c": "food",
+ "e": "ðŸš",
+ "d": "cooked rice",
+ "u": "6.0"
+ },
+ "rice_ball": {
+ "c": "food",
+ "e": "ðŸ™",
+ "d": "rice ball",
+ "u": "6.0"
+ },
+ "rice_cracker": {
+ "c": "food",
+ "e": "ðŸ˜",
+ "d": "rice cracker",
+ "u": "6.0"
+ },
+ "rice_scene": {
+ "c": "travel",
+ "e": "🎑",
+ "d": "moon viewing ceremony",
+ "u": "6.0"
+ },
+ "right_facing_fist": {
+ "c": "people",
+ "e": "🤜",
+ "d": "right-facing fist",
+ "u": "9.0"
+ },
+ "right_facing_fist_tone1": {
+ "c": "people",
+ "e": "🤜ðŸ»",
+ "d": "right facing fist tone 1",
+ "u": "9.0"
+ },
+ "right_facing_fist_tone2": {
+ "c": "people",
+ "e": "🤜ðŸ¼",
+ "d": "right facing fist tone 2",
+ "u": "9.0"
+ },
+ "right_facing_fist_tone3": {
+ "c": "people",
+ "e": "🤜ðŸ½",
+ "d": "right facing fist tone 3",
+ "u": "9.0"
+ },
+ "right_facing_fist_tone4": {
+ "c": "people",
+ "e": "🤜ðŸ¾",
+ "d": "right facing fist tone 4",
+ "u": "9.0"
+ },
+ "right_facing_fist_tone5": {
+ "c": "people",
+ "e": "🤜ðŸ¿",
+ "d": "right facing fist tone 5",
+ "u": "9.0"
+ },
+ "ring": {
+ "c": "people",
+ "e": "ðŸ’",
+ "d": "ring",
+ "u": "6.0"
+ },
+ "robot": {
+ "c": "people",
+ "e": "🤖",
+ "d": "robot face",
+ "u": "8.0"
+ },
+ "rocket": {
+ "c": "travel",
+ "e": "🚀",
+ "d": "rocket",
+ "u": "6.0"
+ },
+ "rofl": {
+ "c": "people",
+ "e": "🤣",
+ "d": "rolling on the floor laughing",
+ "u": "9.0"
+ },
+ "roller_coaster": {
+ "c": "travel",
+ "e": "🎢",
+ "d": "roller coaster",
+ "u": "6.0"
+ },
+ "rolling_eyes": {
+ "c": "people",
+ "e": "🙄",
+ "d": "face with rolling eyes",
+ "u": "8.0"
+ },
+ "rooster": {
+ "c": "nature",
+ "e": "ðŸ“",
+ "d": "rooster",
+ "u": "6.0"
+ },
+ "rose": {
+ "c": "nature",
+ "e": "🌹",
+ "d": "rose",
+ "u": "6.0"
+ },
+ "rosette": {
+ "c": "activity",
+ "e": "ðŸµ",
+ "d": "rosette",
+ "u": "7.0"
+ },
+ "rotating_light": {
+ "c": "travel",
+ "e": "🚨",
+ "d": "police cars revolving light",
+ "u": "6.0"
+ },
+ "round_pushpin": {
+ "c": "objects",
+ "e": "ðŸ“",
+ "d": "round pushpin",
+ "u": "6.0"
+ },
+ "rowboat": {
+ "c": "activity",
+ "e": "🚣",
+ "d": "rowboat",
+ "u": "6.0"
+ },
+ "rowboat_tone1": {
+ "c": "activity",
+ "e": "🚣ðŸ»",
+ "d": "rowboat tone 1",
+ "u": "8.0"
+ },
+ "rowboat_tone2": {
+ "c": "activity",
+ "e": "🚣ðŸ¼",
+ "d": "rowboat tone 2",
+ "u": "8.0"
+ },
+ "rowboat_tone3": {
+ "c": "activity",
+ "e": "🚣ðŸ½",
+ "d": "rowboat tone 3",
+ "u": "8.0"
+ },
+ "rowboat_tone4": {
+ "c": "activity",
+ "e": "🚣ðŸ¾",
+ "d": "rowboat tone 4",
+ "u": "8.0"
+ },
+ "rowboat_tone5": {
+ "c": "activity",
+ "e": "🚣ðŸ¿",
+ "d": "rowboat tone 5",
+ "u": "8.0"
+ },
+ "rugby_football": {
+ "c": "activity",
+ "e": "ðŸ‰",
+ "d": "rugby football",
+ "u": "6.0"
+ },
+ "runner": {
+ "c": "people",
+ "e": "ðŸƒ",
+ "d": "runner",
+ "u": "6.0"
+ },
+ "runner_tone1": {
+ "c": "people",
+ "e": "ðŸƒðŸ»",
+ "d": "runner tone 1",
+ "u": "8.0"
+ },
+ "runner_tone2": {
+ "c": "people",
+ "e": "ðŸƒðŸ¼",
+ "d": "runner tone 2",
+ "u": "8.0"
+ },
+ "runner_tone3": {
+ "c": "people",
+ "e": "ðŸƒðŸ½",
+ "d": "runner tone 3",
+ "u": "8.0"
+ },
+ "runner_tone4": {
+ "c": "people",
+ "e": "ðŸƒðŸ¾",
+ "d": "runner tone 4",
+ "u": "8.0"
+ },
+ "runner_tone5": {
+ "c": "people",
+ "e": "ðŸƒðŸ¿",
+ "d": "runner tone 5",
+ "u": "8.0"
+ },
+ "running_shirt_with_sash": {
+ "c": "activity",
+ "e": "🎽",
+ "d": "running shirt with sash",
+ "u": "6.0"
+ },
+ "sa": {
+ "c": "symbols",
+ "e": "🈂",
+ "d": "squared katakana sa",
+ "u": "6.0"
+ },
+ "sagittarius": {
+ "c": "symbols",
+ "e": "â™",
+ "d": "sagittarius",
+ "u": "1.1"
+ },
+ "sailboat": {
+ "c": "travel",
+ "e": "⛵",
+ "d": "sailboat",
+ "u": "5.2"
+ },
+ "sake": {
+ "c": "food",
+ "e": "ðŸ¶",
+ "d": "sake bottle and cup",
+ "u": "6.0"
+ },
+ "salad": {
+ "c": "food",
+ "e": "🥗",
+ "d": "green salad",
+ "u": "9.0"
+ },
+ "sandal": {
+ "c": "people",
+ "e": "👡",
+ "d": "womans sandal",
+ "u": "6.0"
+ },
+ "santa": {
+ "c": "people",
+ "e": "🎅",
+ "d": "father christmas",
+ "u": "6.0"
+ },
+ "santa_tone1": {
+ "c": "people",
+ "e": "🎅ðŸ»",
+ "d": "father christmas tone 1",
+ "u": "8.0"
+ },
+ "santa_tone2": {
+ "c": "people",
+ "e": "🎅ðŸ¼",
+ "d": "father christmas tone 2",
+ "u": "8.0"
+ },
+ "santa_tone3": {
+ "c": "people",
+ "e": "🎅ðŸ½",
+ "d": "father christmas tone 3",
+ "u": "8.0"
+ },
+ "santa_tone4": {
+ "c": "people",
+ "e": "🎅ðŸ¾",
+ "d": "father christmas tone 4",
+ "u": "8.0"
+ },
+ "santa_tone5": {
+ "c": "people",
+ "e": "🎅ðŸ¿",
+ "d": "father christmas tone 5",
+ "u": "8.0"
+ },
+ "satellite": {
+ "c": "objects",
+ "e": "📡",
+ "d": "satellite antenna",
+ "u": "6.0"
+ },
+ "satellite_orbital": {
+ "c": "travel",
+ "e": "🛰",
+ "d": "satellite",
+ "u": "7.0"
+ },
+ "saxophone": {
+ "c": "activity",
+ "e": "🎷",
+ "d": "saxophone",
+ "u": "6.0"
+ },
+ "scales": {
+ "c": "objects",
+ "e": "âš–",
+ "d": "scales",
+ "u": "4.1"
+ },
+ "school": {
+ "c": "travel",
+ "e": "ðŸ«",
+ "d": "school",
+ "u": "6.0"
+ },
+ "school_satchel": {
+ "c": "people",
+ "e": "🎒",
+ "d": "school satchel",
+ "u": "6.0"
+ },
+ "scissors": {
+ "c": "objects",
+ "e": "✂",
+ "d": "black scissors",
+ "u": "1.1"
+ },
+ "scooter": {
+ "c": "travel",
+ "e": "🛴",
+ "d": "scooter",
+ "u": "9.0"
+ },
+ "scorpion": {
+ "c": "nature",
+ "e": "🦂",
+ "d": "scorpion",
+ "u": "8.0"
+ },
+ "scorpius": {
+ "c": "symbols",
+ "e": "â™",
+ "d": "scorpius",
+ "u": "1.1"
+ },
+ "scream": {
+ "c": "people",
+ "e": "😱",
+ "d": "face screaming in fear",
+ "u": "6.0"
+ },
+ "scream_cat": {
+ "c": "people",
+ "e": "🙀",
+ "d": "weary cat face",
+ "u": "6.0"
+ },
+ "scroll": {
+ "c": "objects",
+ "e": "📜",
+ "d": "scroll",
+ "u": "6.0"
+ },
+ "seat": {
+ "c": "travel",
+ "e": "💺",
+ "d": "seat",
+ "u": "6.0"
+ },
+ "second_place": {
+ "c": "activity",
+ "e": "🥈",
+ "d": "second place medal",
+ "u": "9.0"
+ },
+ "secret": {
+ "c": "symbols",
+ "e": "㊙",
+ "d": "circled ideograph secret",
+ "u": "1.1"
+ },
+ "see_no_evil": {
+ "c": "nature",
+ "e": "🙈",
+ "d": "see-no-evil monkey",
+ "u": "6.0"
+ },
+ "seedling": {
+ "c": "nature",
+ "e": "🌱",
+ "d": "seedling",
+ "u": "6.0"
+ },
+ "selfie": {
+ "c": "people",
+ "e": "🤳",
+ "d": "selfie",
+ "u": "9.0"
+ },
+ "selfie_tone1": {
+ "c": "people",
+ "e": "🤳ðŸ»",
+ "d": "selfie tone 1",
+ "u": "9.0"
+ },
+ "selfie_tone2": {
+ "c": "people",
+ "e": "🤳ðŸ¼",
+ "d": "selfie tone 2",
+ "u": "9.0"
+ },
+ "selfie_tone3": {
+ "c": "people",
+ "e": "🤳ðŸ½",
+ "d": "selfie tone 3",
+ "u": "9.0"
+ },
+ "selfie_tone4": {
+ "c": "people",
+ "e": "🤳ðŸ¾",
+ "d": "selfie tone 4",
+ "u": "9.0"
+ },
+ "selfie_tone5": {
+ "c": "people",
+ "e": "🤳ðŸ¿",
+ "d": "selfie tone 5",
+ "u": "9.0"
+ },
+ "seven": {
+ "c": "symbols",
+ "e": "7ï¸âƒ£",
+ "d": "keycap digit seven",
+ "u": "3.0"
+ },
+ "shallow_pan_of_food": {
+ "c": "food",
+ "e": "🥘",
+ "d": "shallow pan of food",
+ "u": "9.0"
+ },
+ "shamrock": {
+ "c": "nature",
+ "e": "☘",
+ "d": "shamrock",
+ "u": "4.1"
+ },
+ "shark": {
+ "c": "nature",
+ "e": "🦈",
+ "d": "shark",
+ "u": "9.0"
+ },
+ "shaved_ice": {
+ "c": "food",
+ "e": "ðŸ§",
+ "d": "shaved ice",
+ "u": "6.0"
+ },
+ "sheep": {
+ "c": "nature",
+ "e": "ðŸ‘",
+ "d": "sheep",
+ "u": "6.0"
+ },
+ "shell": {
+ "c": "nature",
+ "e": "ðŸš",
+ "d": "spiral shell",
+ "u": "6.0"
+ },
+ "shield": {
+ "c": "objects",
+ "e": "🛡",
+ "d": "shield",
+ "u": "7.0"
+ },
+ "shinto_shrine": {
+ "c": "travel",
+ "e": "⛩",
+ "d": "shinto shrine",
+ "u": "5.2"
+ },
+ "ship": {
+ "c": "travel",
+ "e": "🚢",
+ "d": "ship",
+ "u": "6.0"
+ },
+ "shirt": {
+ "c": "people",
+ "e": "👕",
+ "d": "t-shirt",
+ "u": "6.0"
+ },
+ "shopping_bags": {
+ "c": "objects",
+ "e": "ðŸ›",
+ "d": "shopping bags",
+ "u": "7.0"
+ },
+ "shopping_cart": {
+ "c": "objects",
+ "e": "🛒",
+ "d": "shopping trolley",
+ "u": "9.0"
+ },
+ "shower": {
+ "c": "objects",
+ "e": "🚿",
+ "d": "shower",
+ "u": "6.0"
+ },
+ "shrimp": {
+ "c": "nature",
+ "e": "ðŸ¦",
+ "d": "shrimp",
+ "u": "9.0"
+ },
+ "shrug": {
+ "c": "people",
+ "e": "🤷",
+ "d": "shrug",
+ "u": "9.0"
+ },
+ "shrug_tone1": {
+ "c": "people",
+ "e": "🤷ðŸ»",
+ "d": "shrug tone 1",
+ "u": "9.0"
+ },
+ "shrug_tone2": {
+ "c": "people",
+ "e": "🤷ðŸ¼",
+ "d": "shrug tone 2",
+ "u": "9.0"
+ },
+ "shrug_tone3": {
+ "c": "people",
+ "e": "🤷ðŸ½",
+ "d": "shrug tone 3",
+ "u": "9.0"
+ },
+ "shrug_tone4": {
+ "c": "people",
+ "e": "🤷ðŸ¾",
+ "d": "shrug tone 4",
+ "u": "9.0"
+ },
+ "shrug_tone5": {
+ "c": "people",
+ "e": "🤷ðŸ¿",
+ "d": "shrug tone 5",
+ "u": "9.0"
+ },
+ "signal_strength": {
+ "c": "symbols",
+ "e": "📶",
+ "d": "antenna with bars",
+ "u": "6.0"
+ },
+ "six": {
+ "c": "symbols",
+ "e": "6ï¸âƒ£",
+ "d": "keycap digit six",
+ "u": "3.0"
+ },
+ "six_pointed_star": {
+ "c": "symbols",
+ "e": "🔯",
+ "d": "six pointed star with middle dot",
+ "u": "6.0"
+ },
+ "ski": {
+ "c": "activity",
+ "e": "🎿",
+ "d": "ski and ski boot",
+ "u": "6.0"
+ },
+ "skier": {
+ "c": "activity",
+ "e": "â›·",
+ "d": "skier",
+ "u": "5.2"
+ },
+ "skull": {
+ "c": "people",
+ "e": "💀",
+ "d": "skull",
+ "u": "6.0"
+ },
+ "skull_crossbones": {
+ "c": "objects",
+ "e": "☠",
+ "d": "skull and crossbones",
+ "u": "1.1"
+ },
+ "sleeping": {
+ "c": "people",
+ "e": "😴",
+ "d": "sleeping face",
+ "u": "6.1"
+ },
+ "sleeping_accommodation": {
+ "c": "objects",
+ "e": "🛌",
+ "d": "sleeping accommodation",
+ "u": "7.0"
+ },
+ "sleepy": {
+ "c": "people",
+ "e": "😪",
+ "d": "sleepy face",
+ "u": "6.0"
+ },
+ "slight_frown": {
+ "c": "people",
+ "e": "ðŸ™",
+ "d": "slightly frowning face",
+ "u": "7.0"
+ },
+ "slight_smile": {
+ "c": "people",
+ "e": "🙂",
+ "d": "slightly smiling face",
+ "u": "7.0"
+ },
+ "slot_machine": {
+ "c": "activity",
+ "e": "🎰",
+ "d": "slot machine",
+ "u": "6.0"
+ },
+ "small_blue_diamond": {
+ "c": "symbols",
+ "e": "🔹",
+ "d": "small blue diamond",
+ "u": "6.0"
+ },
+ "small_orange_diamond": {
+ "c": "symbols",
+ "e": "🔸",
+ "d": "small orange diamond",
+ "u": "6.0"
+ },
+ "small_red_triangle": {
+ "c": "symbols",
+ "e": "🔺",
+ "d": "up-pointing red triangle",
+ "u": "6.0"
+ },
+ "small_red_triangle_down": {
+ "c": "symbols",
+ "e": "🔻",
+ "d": "down-pointing red triangle",
+ "u": "6.0"
+ },
+ "smile": {
+ "c": "people",
+ "e": "😄",
+ "d": "smiling face with open mouth and smiling eyes",
+ "u": "6.0"
+ },
+ "smile_cat": {
+ "c": "people",
+ "e": "😸",
+ "d": "grinning cat face with smiling eyes",
+ "u": "6.0"
+ },
+ "smiley": {
+ "c": "people",
+ "e": "😃",
+ "d": "smiling face with open mouth",
+ "u": "6.0"
+ },
+ "smiley_cat": {
+ "c": "people",
+ "e": "😺",
+ "d": "smiling cat face with open mouth",
+ "u": "6.0"
+ },
+ "smiling_imp": {
+ "c": "people",
+ "e": "😈",
+ "d": "smiling face with horns",
+ "u": "6.0"
+ },
+ "smirk": {
+ "c": "people",
+ "e": "ðŸ˜",
+ "d": "smirking face",
+ "u": "6.0"
+ },
+ "smirk_cat": {
+ "c": "people",
+ "e": "😼",
+ "d": "cat face with wry smile",
+ "u": "6.0"
+ },
+ "smoking": {
+ "c": "objects",
+ "e": "🚬",
+ "d": "smoking symbol",
+ "u": "6.0"
+ },
+ "snail": {
+ "c": "nature",
+ "e": "ðŸŒ",
+ "d": "snail",
+ "u": "6.0"
+ },
+ "snake": {
+ "c": "nature",
+ "e": "ðŸ",
+ "d": "snake",
+ "u": "6.0"
+ },
+ "sneezing_face": {
+ "c": "people",
+ "e": "🤧",
+ "d": "sneezing face",
+ "u": "9.0"
+ },
+ "snowboarder": {
+ "c": "activity",
+ "e": "ðŸ‚",
+ "d": "snowboarder",
+ "u": "6.0"
+ },
+ "snowflake": {
+ "c": "nature",
+ "e": "â„",
+ "d": "snowflake",
+ "u": "1.1"
+ },
+ "snowman": {
+ "c": "nature",
+ "e": "⛄",
+ "d": "snowman without snow",
+ "u": "5.2"
+ },
+ "snowman2": {
+ "c": "nature",
+ "e": "☃",
+ "d": "snowman",
+ "u": "1.1"
+ },
+ "sob": {
+ "c": "people",
+ "e": "😭",
+ "d": "loudly crying face",
+ "u": "6.0"
+ },
+ "soccer": {
+ "c": "activity",
+ "e": "âš½",
+ "d": "soccer ball",
+ "u": "5.2"
+ },
+ "soon": {
+ "c": "symbols",
+ "e": "🔜",
+ "d": "soon with rightwards arrow above",
+ "u": "6.0"
+ },
+ "sos": {
+ "c": "symbols",
+ "e": "🆘",
+ "d": "squared sos",
+ "u": "6.0"
+ },
+ "sound": {
+ "c": "symbols",
+ "e": "🔉",
+ "d": "speaker with one sound wave",
+ "u": "6.0"
+ },
+ "space_invader": {
+ "c": "activity",
+ "e": "👾",
+ "d": "alien monster",
+ "u": "6.0"
+ },
+ "spades": {
+ "c": "symbols",
+ "e": "â™ ",
+ "d": "black spade suit",
+ "u": "1.1"
+ },
+ "spaghetti": {
+ "c": "food",
+ "e": "ðŸ",
+ "d": "spaghetti",
+ "u": "6.0"
+ },
+ "sparkle": {
+ "c": "symbols",
+ "e": "â‡",
+ "d": "sparkle",
+ "u": "1.1"
+ },
+ "sparkler": {
+ "c": "travel",
+ "e": "🎇",
+ "d": "firework sparkler",
+ "u": "6.0"
+ },
+ "sparkles": {
+ "c": "nature",
+ "e": "✨",
+ "d": "sparkles",
+ "u": "6.0"
+ },
+ "sparkling_heart": {
+ "c": "symbols",
+ "e": "💖",
+ "d": "sparkling heart",
+ "u": "6.0"
+ },
+ "speak_no_evil": {
+ "c": "nature",
+ "e": "🙊",
+ "d": "speak-no-evil monkey",
+ "u": "6.0"
+ },
+ "speaker": {
+ "c": "symbols",
+ "e": "🔈",
+ "d": "speaker",
+ "u": "6.0"
+ },
+ "speaking_head": {
+ "c": "people",
+ "e": "🗣",
+ "d": "speaking head in silhouette",
+ "u": "7.0"
+ },
+ "speech_balloon": {
+ "c": "symbols",
+ "e": "💬",
+ "d": "speech balloon",
+ "u": "6.0"
+ },
+ "speech_left": {
+ "c": "symbols",
+ "e": "🗨",
+ "d": "left speech bubble",
+ "u": "7.0"
+ },
+ "speedboat": {
+ "c": "travel",
+ "e": "🚤",
+ "d": "speedboat",
+ "u": "6.0"
+ },
+ "spider": {
+ "c": "nature",
+ "e": "🕷",
+ "d": "spider",
+ "u": "7.0"
+ },
+ "spider_web": {
+ "c": "nature",
+ "e": "🕸",
+ "d": "spider web",
+ "u": "7.0"
+ },
+ "spoon": {
+ "c": "food",
+ "e": "🥄",
+ "d": "spoon",
+ "u": "9.0"
+ },
+ "spy": {
+ "c": "people",
+ "e": "🕵",
+ "d": "sleuth or spy",
+ "u": "7.0"
+ },
+ "spy_tone1": {
+ "c": "people",
+ "e": "🕵ðŸ»",
+ "d": "sleuth or spy tone 1",
+ "u": "8.0"
+ },
+ "spy_tone2": {
+ "c": "people",
+ "e": "🕵ðŸ¼",
+ "d": "sleuth or spy tone 2",
+ "u": "8.0"
+ },
+ "spy_tone3": {
+ "c": "people",
+ "e": "🕵ðŸ½",
+ "d": "sleuth or spy tone 3",
+ "u": "8.0"
+ },
+ "spy_tone4": {
+ "c": "people",
+ "e": "🕵ðŸ¾",
+ "d": "sleuth or spy tone 4",
+ "u": "8.0"
+ },
+ "spy_tone5": {
+ "c": "people",
+ "e": "🕵ðŸ¿",
+ "d": "sleuth or spy tone 5",
+ "u": "8.0"
+ },
+ "squid": {
+ "c": "nature",
+ "e": "🦑",
+ "d": "squid",
+ "u": "9.0"
+ },
+ "stadium": {
+ "c": "travel",
+ "e": "ðŸŸ",
+ "d": "stadium",
+ "u": "7.0"
+ },
+ "star": {
+ "c": "nature",
+ "e": "â­",
+ "d": "white medium star",
+ "u": "5.1"
+ },
+ "star2": {
+ "c": "nature",
+ "e": "🌟",
+ "d": "glowing star",
+ "u": "6.0"
+ },
+ "star_and_crescent": {
+ "c": "symbols",
+ "e": "☪",
+ "d": "star and crescent",
+ "u": "1.1"
+ },
+ "star_of_david": {
+ "c": "symbols",
+ "e": "✡",
+ "d": "star of david",
+ "u": "1.1"
+ },
+ "stars": {
+ "c": "travel",
+ "e": "🌠",
+ "d": "shooting star",
+ "u": "6.0"
+ },
+ "station": {
+ "c": "travel",
+ "e": "🚉",
+ "d": "station",
+ "u": "6.0"
+ },
+ "statue_of_liberty": {
+ "c": "travel",
+ "e": "🗽",
+ "d": "statue of liberty",
+ "u": "6.0"
+ },
+ "steam_locomotive": {
+ "c": "travel",
+ "e": "🚂",
+ "d": "steam locomotive",
+ "u": "6.0"
+ },
+ "stew": {
+ "c": "food",
+ "e": "ðŸ²",
+ "d": "pot of food",
+ "u": "6.0"
+ },
+ "stop_button": {
+ "c": "symbols",
+ "e": "â¹",
+ "d": "black square for stop",
+ "u": "7.0"
+ },
+ "stopwatch": {
+ "c": "objects",
+ "e": "â±",
+ "d": "stopwatch",
+ "u": "6.0"
+ },
+ "straight_ruler": {
+ "c": "objects",
+ "e": "ðŸ“",
+ "d": "straight ruler",
+ "u": "6.0"
+ },
+ "strawberry": {
+ "c": "food",
+ "e": "ðŸ“",
+ "d": "strawberry",
+ "u": "6.0"
+ },
+ "stuck_out_tongue": {
+ "c": "people",
+ "e": "😛",
+ "d": "face with stuck-out tongue",
+ "u": "6.1"
+ },
+ "stuck_out_tongue_closed_eyes": {
+ "c": "people",
+ "e": "ðŸ˜",
+ "d": "face with stuck-out tongue and tightly-closed eyes",
+ "u": "6.0"
+ },
+ "stuck_out_tongue_winking_eye": {
+ "c": "people",
+ "e": "😜",
+ "d": "face with stuck-out tongue and winking eye",
+ "u": "6.0"
+ },
+ "stuffed_flatbread": {
+ "c": "food",
+ "e": "🥙",
+ "d": "stuffed flatbread",
+ "u": "9.0"
+ },
+ "sun_with_face": {
+ "c": "nature",
+ "e": "🌞",
+ "d": "sun with face",
+ "u": "6.0"
+ },
+ "sunflower": {
+ "c": "nature",
+ "e": "🌻",
+ "d": "sunflower",
+ "u": "6.0"
+ },
+ "sunglasses": {
+ "c": "people",
+ "e": "😎",
+ "d": "smiling face with sunglasses",
+ "u": "6.0"
+ },
+ "sunny": {
+ "c": "nature",
+ "e": "☀",
+ "d": "black sun with rays",
+ "u": "1.1"
+ },
+ "sunrise": {
+ "c": "travel",
+ "e": "🌅",
+ "d": "sunrise",
+ "u": "6.0"
+ },
+ "sunrise_over_mountains": {
+ "c": "travel",
+ "e": "🌄",
+ "d": "sunrise over mountains",
+ "u": "6.0"
+ },
+ "surfer": {
+ "c": "activity",
+ "e": "ðŸ„",
+ "d": "surfer",
+ "u": "6.0"
+ },
+ "surfer_tone1": {
+ "c": "activity",
+ "e": "ðŸ„ðŸ»",
+ "d": "surfer tone 1",
+ "u": "8.0"
+ },
+ "surfer_tone2": {
+ "c": "activity",
+ "e": "ðŸ„ðŸ¼",
+ "d": "surfer tone 2",
+ "u": "8.0"
+ },
+ "surfer_tone3": {
+ "c": "activity",
+ "e": "ðŸ„ðŸ½",
+ "d": "surfer tone 3",
+ "u": "8.0"
+ },
+ "surfer_tone4": {
+ "c": "activity",
+ "e": "ðŸ„ðŸ¾",
+ "d": "surfer tone 4",
+ "u": "8.0"
+ },
+ "surfer_tone5": {
+ "c": "activity",
+ "e": "ðŸ„ðŸ¿",
+ "d": "surfer tone 5",
+ "u": "8.0"
+ },
+ "sushi": {
+ "c": "food",
+ "e": "ðŸ£",
+ "d": "sushi",
+ "u": "6.0"
+ },
+ "suspension_railway": {
+ "c": "travel",
+ "e": "🚟",
+ "d": "suspension railway",
+ "u": "6.0"
+ },
+ "sweat": {
+ "c": "people",
+ "e": "😓",
+ "d": "face with cold sweat",
+ "u": "6.0"
+ },
+ "sweat_drops": {
+ "c": "nature",
+ "e": "💦",
+ "d": "splashing sweat symbol",
+ "u": "6.0"
+ },
+ "sweat_smile": {
+ "c": "people",
+ "e": "😅",
+ "d": "smiling face with open mouth and cold sweat",
+ "u": "6.0"
+ },
+ "sweet_potato": {
+ "c": "food",
+ "e": "ðŸ ",
+ "d": "roasted sweet potato",
+ "u": "6.0"
+ },
+ "swimmer": {
+ "c": "activity",
+ "e": "ðŸŠ",
+ "d": "swimmer",
+ "u": "6.0"
+ },
+ "swimmer_tone1": {
+ "c": "activity",
+ "e": "ðŸŠðŸ»",
+ "d": "swimmer tone 1",
+ "u": "8.0"
+ },
+ "swimmer_tone2": {
+ "c": "activity",
+ "e": "ðŸŠðŸ¼",
+ "d": "swimmer tone 2",
+ "u": "8.0"
+ },
+ "swimmer_tone3": {
+ "c": "activity",
+ "e": "ðŸŠðŸ½",
+ "d": "swimmer tone 3",
+ "u": "8.0"
+ },
+ "swimmer_tone4": {
+ "c": "activity",
+ "e": "ðŸŠðŸ¾",
+ "d": "swimmer tone 4",
+ "u": "8.0"
+ },
+ "swimmer_tone5": {
+ "c": "activity",
+ "e": "ðŸŠðŸ¿",
+ "d": "swimmer tone 5",
+ "u": "8.0"
+ },
+ "symbols": {
+ "c": "symbols",
+ "e": "🔣",
+ "d": "input symbol for symbols",
+ "u": "6.0"
+ },
+ "synagogue": {
+ "c": "travel",
+ "e": "ðŸ•",
+ "d": "synagogue",
+ "u": "8.0"
+ },
+ "syringe": {
+ "c": "objects",
+ "e": "💉",
+ "d": "syringe",
+ "u": "6.0"
+ },
+ "taco": {
+ "c": "food",
+ "e": "🌮",
+ "d": "taco",
+ "u": "8.0"
+ },
+ "tada": {
+ "c": "objects",
+ "e": "🎉",
+ "d": "party popper",
+ "u": "6.0"
+ },
+ "tanabata_tree": {
+ "c": "nature",
+ "e": "🎋",
+ "d": "tanabata tree",
+ "u": "6.0"
+ },
+ "tangerine": {
+ "c": "food",
+ "e": "ðŸŠ",
+ "d": "tangerine",
+ "u": "6.0"
+ },
+ "taurus": {
+ "c": "symbols",
+ "e": "♉",
+ "d": "taurus",
+ "u": "1.1"
+ },
+ "taxi": {
+ "c": "travel",
+ "e": "🚕",
+ "d": "taxi",
+ "u": "6.0"
+ },
+ "tea": {
+ "c": "food",
+ "e": "ðŸµ",
+ "d": "teacup without handle",
+ "u": "6.0"
+ },
+ "telephone": {
+ "c": "objects",
+ "e": "☎",
+ "d": "black telephone",
+ "u": "1.1"
+ },
+ "telephone_receiver": {
+ "c": "objects",
+ "e": "📞",
+ "d": "telephone receiver",
+ "u": "6.0"
+ },
+ "telescope": {
+ "c": "objects",
+ "e": "🔭",
+ "d": "telescope",
+ "u": "6.0"
+ },
+ "ten": {
+ "c": "symbols",
+ "e": "🔟",
+ "d": "keycap ten",
+ "u": "6.0"
+ },
+ "tennis": {
+ "c": "activity",
+ "e": "🎾",
+ "d": "tennis racquet and ball",
+ "u": "6.0"
+ },
+ "tent": {
+ "c": "travel",
+ "e": "⛺",
+ "d": "tent",
+ "u": "5.2"
+ },
+ "thermometer": {
+ "c": "objects",
+ "e": "🌡",
+ "d": "thermometer",
+ "u": "7.0"
+ },
+ "thermometer_face": {
+ "c": "people",
+ "e": "🤒",
+ "d": "face with thermometer",
+ "u": "8.0"
+ },
+ "thinking": {
+ "c": "people",
+ "e": "🤔",
+ "d": "thinking face",
+ "u": "8.0"
+ },
+ "third_place": {
+ "c": "activity",
+ "e": "🥉",
+ "d": "third place medal",
+ "u": "9.0"
+ },
+ "thought_balloon": {
+ "c": "symbols",
+ "e": "💭",
+ "d": "thought balloon",
+ "u": "6.0"
+ },
+ "three": {
+ "c": "symbols",
+ "e": "3ï¸âƒ£",
+ "d": "keycap digit three",
+ "u": "3.0"
+ },
+ "thumbsdown": {
+ "c": "people",
+ "e": "👎",
+ "d": "thumbs down sign",
+ "u": "6.0"
+ },
+ "thumbsdown_tone1": {
+ "c": "people",
+ "e": "👎ðŸ»",
+ "d": "thumbs down sign tone 1",
+ "u": "8.0"
+ },
+ "thumbsdown_tone2": {
+ "c": "people",
+ "e": "👎ðŸ¼",
+ "d": "thumbs down sign tone 2",
+ "u": "8.0"
+ },
+ "thumbsdown_tone3": {
+ "c": "people",
+ "e": "👎ðŸ½",
+ "d": "thumbs down sign tone 3",
+ "u": "8.0"
+ },
+ "thumbsdown_tone4": {
+ "c": "people",
+ "e": "👎ðŸ¾",
+ "d": "thumbs down sign tone 4",
+ "u": "8.0"
+ },
+ "thumbsdown_tone5": {
+ "c": "people",
+ "e": "👎ðŸ¿",
+ "d": "thumbs down sign tone 5",
+ "u": "8.0"
+ },
+ "thumbsup": {
+ "c": "people",
+ "e": "ðŸ‘",
+ "d": "thumbs up sign",
+ "u": "6.0"
+ },
+ "thumbsup_tone1": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ»",
+ "d": "thumbs up sign tone 1",
+ "u": "8.0"
+ },
+ "thumbsup_tone2": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¼",
+ "d": "thumbs up sign tone 2",
+ "u": "8.0"
+ },
+ "thumbsup_tone3": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ½",
+ "d": "thumbs up sign tone 3",
+ "u": "8.0"
+ },
+ "thumbsup_tone4": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¾",
+ "d": "thumbs up sign tone 4",
+ "u": "8.0"
+ },
+ "thumbsup_tone5": {
+ "c": "people",
+ "e": "ðŸ‘ðŸ¿",
+ "d": "thumbs up sign tone 5",
+ "u": "8.0"
+ },
+ "thunder_cloud_rain": {
+ "c": "nature",
+ "e": "⛈",
+ "d": "thunder cloud and rain",
+ "u": "5.2"
+ },
+ "ticket": {
+ "c": "activity",
+ "e": "🎫",
+ "d": "ticket",
+ "u": "6.0"
+ },
+ "tickets": {
+ "c": "activity",
+ "e": "🎟",
+ "d": "admission tickets",
+ "u": "7.0"
+ },
+ "tiger": {
+ "c": "nature",
+ "e": "ðŸ¯",
+ "d": "tiger face",
+ "u": "6.0"
+ },
+ "tiger2": {
+ "c": "nature",
+ "e": "ðŸ…",
+ "d": "tiger",
+ "u": "6.0"
+ },
+ "timer": {
+ "c": "objects",
+ "e": "â²",
+ "d": "timer clock",
+ "u": "6.0"
+ },
+ "tired_face": {
+ "c": "people",
+ "e": "😫",
+ "d": "tired face",
+ "u": "6.0"
+ },
+ "tm": {
+ "c": "symbols",
+ "e": "â„¢ï¸",
+ "d": "trade mark sign",
+ "u": "1.1"
+ },
+ "toilet": {
+ "c": "objects",
+ "e": "🚽",
+ "d": "toilet",
+ "u": "6.0"
+ },
+ "tokyo_tower": {
+ "c": "travel",
+ "e": "🗼",
+ "d": "tokyo tower",
+ "u": "6.0"
+ },
+ "tomato": {
+ "c": "food",
+ "e": "ðŸ…",
+ "d": "tomato",
+ "u": "6.0"
+ },
+ "tone1": {
+ "c": "modifier",
+ "e": "ðŸ»",
+ "d": "emoji modifier Fitzpatrick type-1-2",
+ "u": "8.0"
+ },
+ "tone2": {
+ "c": "modifier",
+ "e": "ðŸ¼",
+ "d": "emoji modifier Fitzpatrick type-3",
+ "u": "8.0"
+ },
+ "tone3": {
+ "c": "modifier",
+ "e": "ðŸ½",
+ "d": "emoji modifier Fitzpatrick type-4",
+ "u": "8.0"
+ },
+ "tone4": {
+ "c": "modifier",
+ "e": "ðŸ¾",
+ "d": "emoji modifier Fitzpatrick type-5",
+ "u": "8.0"
+ },
+ "tone5": {
+ "c": "modifier",
+ "e": "ðŸ¿",
+ "d": "emoji modifier Fitzpatrick type-6",
+ "u": "8.0"
+ },
+ "tongue": {
+ "c": "people",
+ "e": "👅",
+ "d": "tongue",
+ "u": "6.0"
+ },
+ "tools": {
+ "c": "objects",
+ "e": "🛠",
+ "d": "hammer and wrench",
+ "u": "7.0"
+ },
+ "top": {
+ "c": "symbols",
+ "e": "ðŸ”",
+ "d": "top with upwards arrow above",
+ "u": "6.0"
+ },
+ "tophat": {
+ "c": "people",
+ "e": "🎩",
+ "d": "top hat",
+ "u": "6.0"
+ },
+ "track_next": {
+ "c": "symbols",
+ "e": "â­",
+ "d": "black right-pointing double triangle with vertical bar",
+ "u": "6.0"
+ },
+ "track_previous": {
+ "c": "symbols",
+ "e": "â®",
+ "d": "black left-pointing double triangle with vertical bar",
+ "u": "6.0"
+ },
+ "trackball": {
+ "c": "objects",
+ "e": "🖲",
+ "d": "trackball",
+ "u": "7.0"
+ },
+ "tractor": {
+ "c": "travel",
+ "e": "🚜",
+ "d": "tractor",
+ "u": "6.0"
+ },
+ "traffic_light": {
+ "c": "travel",
+ "e": "🚥",
+ "d": "horizontal traffic light",
+ "u": "6.0"
+ },
+ "train": {
+ "c": "travel",
+ "e": "🚋",
+ "d": "Tram Car",
+ "u": "6.0"
+ },
+ "train2": {
+ "c": "travel",
+ "e": "🚆",
+ "d": "train",
+ "u": "6.0"
+ },
+ "tram": {
+ "c": "travel",
+ "e": "🚊",
+ "d": "tram",
+ "u": "6.0"
+ },
+ "triangular_flag_on_post": {
+ "c": "objects",
+ "e": "🚩",
+ "d": "triangular flag on post",
+ "u": "6.0"
+ },
+ "triangular_ruler": {
+ "c": "objects",
+ "e": "ðŸ“",
+ "d": "triangular ruler",
+ "u": "6.0"
+ },
+ "trident": {
+ "c": "symbols",
+ "e": "🔱",
+ "d": "trident emblem",
+ "u": "6.0"
+ },
+ "triumph": {
+ "c": "people",
+ "e": "😤",
+ "d": "face with look of triumph",
+ "u": "6.0"
+ },
+ "trolleybus": {
+ "c": "travel",
+ "e": "🚎",
+ "d": "trolleybus",
+ "u": "6.0"
+ },
+ "trophy": {
+ "c": "activity",
+ "e": "ðŸ†",
+ "d": "trophy",
+ "u": "6.0"
+ },
+ "tropical_drink": {
+ "c": "food",
+ "e": "ðŸ¹",
+ "d": "tropical drink",
+ "u": "6.0"
+ },
+ "tropical_fish": {
+ "c": "nature",
+ "e": "ðŸ ",
+ "d": "tropical fish",
+ "u": "6.0"
+ },
+ "truck": {
+ "c": "travel",
+ "e": "🚚",
+ "d": "delivery truck",
+ "u": "6.0"
+ },
+ "trumpet": {
+ "c": "activity",
+ "e": "🎺",
+ "d": "trumpet",
+ "u": "6.0"
+ },
+ "tulip": {
+ "c": "nature",
+ "e": "🌷",
+ "d": "tulip",
+ "u": "6.0"
+ },
+ "tumbler_glass": {
+ "c": "food",
+ "e": "🥃",
+ "d": "tumbler glass",
+ "u": "9.0"
+ },
+ "turkey": {
+ "c": "nature",
+ "e": "🦃",
+ "d": "turkey",
+ "u": "8.0"
+ },
+ "turtle": {
+ "c": "nature",
+ "e": "ðŸ¢",
+ "d": "turtle",
+ "u": "6.0"
+ },
+ "tv": {
+ "c": "objects",
+ "e": "📺",
+ "d": "television",
+ "u": "6.0"
+ },
+ "twisted_rightwards_arrows": {
+ "c": "symbols",
+ "e": "🔀",
+ "d": "twisted rightwards arrows",
+ "u": "6.0"
+ },
+ "two": {
+ "c": "symbols",
+ "e": "2ï¸âƒ£",
+ "d": "keycap digit two",
+ "u": "3.0"
+ },
+ "two_hearts": {
+ "c": "symbols",
+ "e": "💕",
+ "d": "two hearts",
+ "u": "6.0"
+ },
+ "two_men_holding_hands": {
+ "c": "people",
+ "e": "👬",
+ "d": "two men holding hands",
+ "u": "6.0"
+ },
+ "two_women_holding_hands": {
+ "c": "people",
+ "e": "👭",
+ "d": "two women holding hands",
+ "u": "6.0"
+ },
+ "u5272": {
+ "c": "symbols",
+ "e": "🈹",
+ "d": "squared cjk unified ideograph-5272",
+ "u": "6.0"
+ },
+ "u5408": {
+ "c": "symbols",
+ "e": "🈴",
+ "d": "squared cjk unified ideograph-5408",
+ "u": "6.0"
+ },
+ "u55b6": {
+ "c": "symbols",
+ "e": "🈺",
+ "d": "squared cjk unified ideograph-55b6",
+ "u": "6.0"
+ },
+ "u6307": {
+ "c": "symbols",
+ "e": "🈯",
+ "d": "squared cjk unified ideograph-6307",
+ "u": "5.2"
+ },
+ "u6708": {
+ "c": "symbols",
+ "e": "🈷",
+ "d": "squared cjk unified ideograph-6708",
+ "u": "6.0"
+ },
+ "u6709": {
+ "c": "symbols",
+ "e": "🈶",
+ "d": "squared cjk unified ideograph-6709",
+ "u": "6.0"
+ },
+ "u6e80": {
+ "c": "symbols",
+ "e": "🈵",
+ "d": "squared cjk unified ideograph-6e80",
+ "u": "6.0"
+ },
+ "u7121": {
+ "c": "symbols",
+ "e": "🈚",
+ "d": "squared cjk unified ideograph-7121",
+ "u": "5.2"
+ },
+ "u7533": {
+ "c": "symbols",
+ "e": "🈸",
+ "d": "squared cjk unified ideograph-7533",
+ "u": "6.0"
+ },
+ "u7981": {
+ "c": "symbols",
+ "e": "🈲",
+ "d": "squared cjk unified ideograph-7981",
+ "u": "6.0"
+ },
+ "u7a7a": {
+ "c": "symbols",
+ "e": "🈳",
+ "d": "squared cjk unified ideograph-7a7a",
+ "u": "6.0"
+ },
+ "umbrella": {
+ "c": "nature",
+ "e": "☔",
+ "d": "umbrella with rain drops",
+ "u": "4.0"
+ },
+ "umbrella2": {
+ "c": "nature",
+ "e": "☂",
+ "d": "umbrella",
+ "u": "1.1"
+ },
+ "unamused": {
+ "c": "people",
+ "e": "😒",
+ "d": "unamused face",
+ "u": "6.0"
+ },
+ "underage": {
+ "c": "symbols",
+ "e": "🔞",
+ "d": "no one under eighteen symbol",
+ "u": "6.0"
+ },
+ "unicorn": {
+ "c": "nature",
+ "e": "🦄",
+ "d": "unicorn face",
+ "u": "8.0"
+ },
+ "unlock": {
+ "c": "objects",
+ "e": "🔓",
+ "d": "open lock",
+ "u": "6.0"
+ },
+ "up": {
+ "c": "symbols",
+ "e": "🆙",
+ "d": "squared up with exclamation mark",
+ "u": "6.0"
+ },
+ "upside_down": {
+ "c": "people",
+ "e": "🙃",
+ "d": "upside-down face",
+ "u": "8.0"
+ },
+ "urn": {
+ "c": "objects",
+ "e": "âš±",
+ "d": "funeral urn",
+ "u": "4.1"
+ },
+ "v": {
+ "c": "people",
+ "e": "✌",
+ "d": "victory hand",
+ "u": "1.1"
+ },
+ "v_tone1": {
+ "c": "people",
+ "e": "✌ðŸ»",
+ "d": "victory hand tone 1",
+ "u": "8.0"
+ },
+ "v_tone2": {
+ "c": "people",
+ "e": "✌ðŸ¼",
+ "d": "victory hand tone 2",
+ "u": "8.0"
+ },
+ "v_tone3": {
+ "c": "people",
+ "e": "✌ðŸ½",
+ "d": "victory hand tone 3",
+ "u": "8.0"
+ },
+ "v_tone4": {
+ "c": "people",
+ "e": "✌ðŸ¾",
+ "d": "victory hand tone 4",
+ "u": "8.0"
+ },
+ "v_tone5": {
+ "c": "people",
+ "e": "✌ðŸ¿",
+ "d": "victory hand tone 5",
+ "u": "8.0"
+ },
+ "vertical_traffic_light": {
+ "c": "travel",
+ "e": "🚦",
+ "d": "vertical traffic light",
+ "u": "6.0"
+ },
+ "vhs": {
+ "c": "objects",
+ "e": "📼",
+ "d": "videocassette",
+ "u": "6.0"
+ },
+ "vibration_mode": {
+ "c": "symbols",
+ "e": "📳",
+ "d": "vibration mode",
+ "u": "6.0"
+ },
+ "video_camera": {
+ "c": "objects",
+ "e": "📹",
+ "d": "video camera",
+ "u": "6.0"
+ },
+ "video_game": {
+ "c": "activity",
+ "e": "🎮",
+ "d": "video game",
+ "u": "6.0"
+ },
+ "violin": {
+ "c": "activity",
+ "e": "🎻",
+ "d": "violin",
+ "u": "6.0"
+ },
+ "virgo": {
+ "c": "symbols",
+ "e": "â™",
+ "d": "virgo",
+ "u": "1.1"
+ },
+ "volcano": {
+ "c": "travel",
+ "e": "🌋",
+ "d": "volcano",
+ "u": "6.0"
+ },
+ "volleyball": {
+ "c": "activity",
+ "e": "ðŸ",
+ "d": "volleyball",
+ "u": "8.0"
+ },
+ "vs": {
+ "c": "symbols",
+ "e": "🆚",
+ "d": "squared vs",
+ "u": "6.0"
+ },
+ "vulcan": {
+ "c": "people",
+ "e": "🖖",
+ "d": "raised hand with part between middle and ring fingers",
+ "u": "7.0"
+ },
+ "vulcan_tone1": {
+ "c": "people",
+ "e": "🖖ðŸ»",
+ "d": "raised hand with part between middle and ring fingers tone 1",
+ "u": "8.0"
+ },
+ "vulcan_tone2": {
+ "c": "people",
+ "e": "🖖ðŸ¼",
+ "d": "raised hand with part between middle and ring fingers tone 2",
+ "u": "8.0"
+ },
+ "vulcan_tone3": {
+ "c": "people",
+ "e": "🖖ðŸ½",
+ "d": "raised hand with part between middle and ring fingers tone 3",
+ "u": "8.0"
+ },
+ "vulcan_tone4": {
+ "c": "people",
+ "e": "🖖ðŸ¾",
+ "d": "raised hand with part between middle and ring fingers tone 4",
+ "u": "8.0"
+ },
+ "vulcan_tone5": {
+ "c": "people",
+ "e": "🖖ðŸ¿",
+ "d": "raised hand with part between middle and ring fingers tone 5",
+ "u": "8.0"
+ },
+ "walking": {
+ "c": "people",
+ "e": "🚶",
+ "d": "pedestrian",
+ "u": "6.0"
+ },
+ "walking_tone1": {
+ "c": "people",
+ "e": "🚶ðŸ»",
+ "d": "pedestrian tone 1",
+ "u": "8.0"
+ },
+ "walking_tone2": {
+ "c": "people",
+ "e": "🚶ðŸ¼",
+ "d": "pedestrian tone 2",
+ "u": "8.0"
+ },
+ "walking_tone3": {
+ "c": "people",
+ "e": "🚶ðŸ½",
+ "d": "pedestrian tone 3",
+ "u": "8.0"
+ },
+ "walking_tone4": {
+ "c": "people",
+ "e": "🚶ðŸ¾",
+ "d": "pedestrian tone 4",
+ "u": "8.0"
+ },
+ "walking_tone5": {
+ "c": "people",
+ "e": "🚶ðŸ¿",
+ "d": "pedestrian tone 5",
+ "u": "8.0"
+ },
+ "waning_crescent_moon": {
+ "c": "nature",
+ "e": "🌘",
+ "d": "waning crescent moon symbol",
+ "u": "6.0"
+ },
+ "waning_gibbous_moon": {
+ "c": "nature",
+ "e": "🌖",
+ "d": "waning gibbous moon symbol",
+ "u": "6.0"
+ },
+ "warning": {
+ "c": "symbols",
+ "e": "âš ",
+ "d": "warning sign",
+ "u": "4.0"
+ },
+ "wastebasket": {
+ "c": "objects",
+ "e": "🗑",
+ "d": "wastebasket",
+ "u": "7.0"
+ },
+ "watch": {
+ "c": "objects",
+ "e": "⌚",
+ "d": "watch",
+ "u": "1.1"
+ },
+ "water_buffalo": {
+ "c": "nature",
+ "e": "ðŸƒ",
+ "d": "water buffalo",
+ "u": "6.0"
+ },
+ "water_polo": {
+ "c": "activity",
+ "e": "🤽",
+ "d": "water polo",
+ "u": "9.0"
+ },
+ "water_polo_tone1": {
+ "c": "activity",
+ "e": "🤽ðŸ»",
+ "d": "water polo tone 1",
+ "u": "9.0"
+ },
+ "water_polo_tone2": {
+ "c": "activity",
+ "e": "🤽ðŸ¼",
+ "d": "water polo tone 2",
+ "u": "9.0"
+ },
+ "water_polo_tone3": {
+ "c": "activity",
+ "e": "🤽ðŸ½",
+ "d": "water polo tone 3",
+ "u": "9.0"
+ },
+ "water_polo_tone4": {
+ "c": "activity",
+ "e": "🤽ðŸ¾",
+ "d": "water polo tone 4",
+ "u": "9.0"
+ },
+ "water_polo_tone5": {
+ "c": "activity",
+ "e": "🤽ðŸ¿",
+ "d": "water polo tone 5",
+ "u": "9.0"
+ },
+ "watermelon": {
+ "c": "food",
+ "e": "ðŸ‰",
+ "d": "watermelon",
+ "u": "6.0"
+ },
+ "wave": {
+ "c": "people",
+ "e": "👋",
+ "d": "waving hand sign",
+ "u": "6.0"
+ },
+ "wave_tone1": {
+ "c": "people",
+ "e": "👋ðŸ»",
+ "d": "waving hand sign tone 1",
+ "u": "8.0"
+ },
+ "wave_tone2": {
+ "c": "people",
+ "e": "👋ðŸ¼",
+ "d": "waving hand sign tone 2",
+ "u": "8.0"
+ },
+ "wave_tone3": {
+ "c": "people",
+ "e": "👋ðŸ½",
+ "d": "waving hand sign tone 3",
+ "u": "8.0"
+ },
+ "wave_tone4": {
+ "c": "people",
+ "e": "👋ðŸ¾",
+ "d": "waving hand sign tone 4",
+ "u": "8.0"
+ },
+ "wave_tone5": {
+ "c": "people",
+ "e": "👋ðŸ¿",
+ "d": "waving hand sign tone 5",
+ "u": "8.0"
+ },
+ "wavy_dash": {
+ "c": "symbols",
+ "e": "〰",
+ "d": "wavy dash",
+ "u": "1.1"
+ },
+ "waxing_crescent_moon": {
+ "c": "nature",
+ "e": "🌒",
+ "d": "waxing crescent moon symbol",
+ "u": "6.0"
+ },
+ "waxing_gibbous_moon": {
+ "c": "nature",
+ "e": "🌔",
+ "d": "waxing gibbous moon symbol",
+ "u": "6.0"
+ },
+ "wc": {
+ "c": "symbols",
+ "e": "🚾",
+ "d": "water closet",
+ "u": "6.0"
+ },
+ "weary": {
+ "c": "people",
+ "e": "😩",
+ "d": "weary face",
+ "u": "6.0"
+ },
+ "wedding": {
+ "c": "travel",
+ "e": "💒",
+ "d": "wedding",
+ "u": "6.0"
+ },
+ "whale": {
+ "c": "nature",
+ "e": "ðŸ³",
+ "d": "spouting whale",
+ "u": "6.0"
+ },
+ "whale2": {
+ "c": "nature",
+ "e": "ðŸ‹",
+ "d": "whale",
+ "u": "6.0"
+ },
+ "wheel_of_dharma": {
+ "c": "symbols",
+ "e": "☸",
+ "d": "wheel of dharma",
+ "u": "1.1"
+ },
+ "wheelchair": {
+ "c": "symbols",
+ "e": "♿",
+ "d": "wheelchair symbol",
+ "u": "4.1"
+ },
+ "white_check_mark": {
+ "c": "symbols",
+ "e": "✅",
+ "d": "white heavy check mark",
+ "u": "6.0"
+ },
+ "white_circle": {
+ "c": "symbols",
+ "e": "⚪",
+ "d": "medium white circle",
+ "u": "4.1"
+ },
+ "white_flower": {
+ "c": "symbols",
+ "e": "💮",
+ "d": "white flower",
+ "u": "6.0"
+ },
+ "white_large_square": {
+ "c": "symbols",
+ "e": "⬜",
+ "d": "white large square",
+ "u": "5.1"
+ },
+ "white_medium_small_square": {
+ "c": "symbols",
+ "e": "â—½",
+ "d": "white medium small square",
+ "u": "3.2"
+ },
+ "white_medium_square": {
+ "c": "symbols",
+ "e": "â—»",
+ "d": "white medium square",
+ "u": "3.2"
+ },
+ "white_small_square": {
+ "c": "symbols",
+ "e": "â–«",
+ "d": "white small square",
+ "u": "1.1"
+ },
+ "white_square_button": {
+ "c": "symbols",
+ "e": "🔳",
+ "d": "white square button",
+ "u": "6.0"
+ },
+ "white_sun_cloud": {
+ "c": "nature",
+ "e": "🌥",
+ "d": "white sun behind cloud",
+ "u": "7.0"
+ },
+ "white_sun_rain_cloud": {
+ "c": "nature",
+ "e": "🌦",
+ "d": "white sun behind cloud with rain",
+ "u": "7.0"
+ },
+ "white_sun_small_cloud": {
+ "c": "nature",
+ "e": "🌤",
+ "d": "white sun with small cloud",
+ "u": "7.0"
+ },
+ "wilted_rose": {
+ "c": "nature",
+ "e": "🥀",
+ "d": "wilted flower",
+ "u": "9.0"
+ },
+ "wind_blowing_face": {
+ "c": "nature",
+ "e": "🌬",
+ "d": "wind blowing face",
+ "u": "7.0"
+ },
+ "wind_chime": {
+ "c": "objects",
+ "e": "ðŸŽ",
+ "d": "wind chime",
+ "u": "6.0"
+ },
+ "wine_glass": {
+ "c": "food",
+ "e": "ðŸ·",
+ "d": "wine glass",
+ "u": "6.0"
+ },
+ "wink": {
+ "c": "people",
+ "e": "😉",
+ "d": "winking face",
+ "u": "6.0"
+ },
+ "wolf": {
+ "c": "nature",
+ "e": "ðŸº",
+ "d": "wolf face",
+ "u": "6.0"
+ },
+ "woman": {
+ "c": "people",
+ "e": "👩",
+ "d": "woman",
+ "u": "6.0"
+ },
+ "woman_tone1": {
+ "c": "people",
+ "e": "👩ðŸ»",
+ "d": "woman tone 1",
+ "u": "8.0"
+ },
+ "woman_tone2": {
+ "c": "people",
+ "e": "👩ðŸ¼",
+ "d": "woman tone 2",
+ "u": "8.0"
+ },
+ "woman_tone3": {
+ "c": "people",
+ "e": "👩ðŸ½",
+ "d": "woman tone 3",
+ "u": "8.0"
+ },
+ "woman_tone4": {
+ "c": "people",
+ "e": "👩ðŸ¾",
+ "d": "woman tone 4",
+ "u": "8.0"
+ },
+ "woman_tone5": {
+ "c": "people",
+ "e": "👩ðŸ¿",
+ "d": "woman tone 5",
+ "u": "8.0"
+ },
+ "womans_clothes": {
+ "c": "people",
+ "e": "👚",
+ "d": "womans clothes",
+ "u": "6.0"
+ },
+ "womans_hat": {
+ "c": "people",
+ "e": "👒",
+ "d": "womans hat",
+ "u": "6.0"
+ },
+ "womens": {
+ "c": "symbols",
+ "e": "🚺",
+ "d": "womens symbol",
+ "u": "6.0"
+ },
+ "worried": {
+ "c": "people",
+ "e": "😟",
+ "d": "worried face",
+ "u": "6.1"
+ },
+ "wrench": {
+ "c": "objects",
+ "e": "🔧",
+ "d": "wrench",
+ "u": "6.0"
+ },
+ "wrestlers": {
+ "c": "activity",
+ "e": "🤼",
+ "d": "wrestlers",
+ "u": "9.0"
+ },
+ "wrestlers_tone1": {
+ "c": "activity",
+ "e": "🤼ðŸ»",
+ "d": "wrestlers tone 1",
+ "u": "9.0"
+ },
+ "wrestlers_tone2": {
+ "c": "activity",
+ "e": "🤼ðŸ¼",
+ "d": "wrestlers tone 2",
+ "u": "9.0"
+ },
+ "wrestlers_tone3": {
+ "c": "activity",
+ "e": "🤼ðŸ½",
+ "d": "wrestlers tone 3",
+ "u": "9.0"
+ },
+ "wrestlers_tone4": {
+ "c": "activity",
+ "e": "🤼ðŸ¾",
+ "d": "wrestlers tone 4",
+ "u": "9.0"
+ },
+ "wrestlers_tone5": {
+ "c": "activity",
+ "e": "🤼ðŸ¿",
+ "d": "wrestlers tone 5",
+ "u": "9.0"
+ },
+ "writing_hand": {
+ "c": "people",
+ "e": "âœ",
+ "d": "writing hand",
+ "u": "1.1"
+ },
+ "writing_hand_tone1": {
+ "c": "people",
+ "e": "âœðŸ»",
+ "d": "writing hand tone 1",
+ "u": "8.0"
+ },
+ "writing_hand_tone2": {
+ "c": "people",
+ "e": "âœðŸ¼",
+ "d": "writing hand tone 2",
+ "u": "8.0"
+ },
+ "writing_hand_tone3": {
+ "c": "people",
+ "e": "âœðŸ½",
+ "d": "writing hand tone 3",
+ "u": "8.0"
+ },
+ "writing_hand_tone4": {
+ "c": "people",
+ "e": "âœðŸ¾",
+ "d": "writing hand tone 4",
+ "u": "8.0"
+ },
+ "writing_hand_tone5": {
+ "c": "people",
+ "e": "âœðŸ¿",
+ "d": "writing hand tone 5",
+ "u": "8.0"
+ },
+ "x": {
+ "c": "symbols",
+ "e": "âŒ",
+ "d": "cross mark",
+ "u": "6.0"
+ },
+ "yellow_heart": {
+ "c": "symbols",
+ "e": "💛",
+ "d": "yellow heart",
+ "u": "6.0"
+ },
+ "yen": {
+ "c": "objects",
+ "e": "💴",
+ "d": "banknote with yen sign",
+ "u": "6.0"
+ },
+ "yin_yang": {
+ "c": "symbols",
+ "e": "☯",
+ "d": "yin yang",
+ "u": "1.1"
+ },
+ "yum": {
+ "c": "people",
+ "e": "😋",
+ "d": "face savouring delicious food",
+ "u": "6.0"
+ },
+ "zap": {
+ "c": "nature",
+ "e": "âš¡",
+ "d": "high voltage sign",
+ "u": "4.0"
+ },
+ "zero": {
+ "c": "symbols",
+ "e": "0ï¸âƒ£",
+ "d": "keycap digit zero",
+ "u": "3.0"
+ },
+ "zipper_mouth": {
+ "c": "people",
+ "e": "ðŸ¤",
+ "d": "zipper-mouth face",
+ "u": "8.0"
+ },
+ "zzz": {
+ "c": "people",
+ "e": "💤",
+ "d": "sleeping symbol",
+ "u": "6.0"
+ }
+} \ No newline at end of file
diff --git a/public/-/emojis/2/end.png b/public/-/emojis/2/end.png
new file mode 100644
index 00000000000..17c319dc03d
--- /dev/null
+++ b/public/-/emojis/2/end.png
Binary files differ
diff --git a/public/-/emojis/2/envelope.png b/public/-/emojis/2/envelope.png
new file mode 100644
index 00000000000..aed381de949
--- /dev/null
+++ b/public/-/emojis/2/envelope.png
Binary files differ
diff --git a/public/-/emojis/2/envelope_with_arrow.png b/public/-/emojis/2/envelope_with_arrow.png
new file mode 100644
index 00000000000..54b89817587
--- /dev/null
+++ b/public/-/emojis/2/envelope_with_arrow.png
Binary files differ
diff --git a/public/-/emojis/2/euro.png b/public/-/emojis/2/euro.png
new file mode 100644
index 00000000000..2094ed7692f
--- /dev/null
+++ b/public/-/emojis/2/euro.png
Binary files differ
diff --git a/public/-/emojis/2/european_castle.png b/public/-/emojis/2/european_castle.png
new file mode 100644
index 00000000000..5da56216c1e
--- /dev/null
+++ b/public/-/emojis/2/european_castle.png
Binary files differ
diff --git a/public/-/emojis/2/european_post_office.png b/public/-/emojis/2/european_post_office.png
new file mode 100644
index 00000000000..05537ad7702
--- /dev/null
+++ b/public/-/emojis/2/european_post_office.png
Binary files differ
diff --git a/public/-/emojis/2/evergreen_tree.png b/public/-/emojis/2/evergreen_tree.png
new file mode 100644
index 00000000000..1004726d8a8
--- /dev/null
+++ b/public/-/emojis/2/evergreen_tree.png
Binary files differ
diff --git a/public/-/emojis/2/exclamation.png b/public/-/emojis/2/exclamation.png
new file mode 100644
index 00000000000..b5685afaf63
--- /dev/null
+++ b/public/-/emojis/2/exclamation.png
Binary files differ
diff --git a/public/-/emojis/2/expressionless.png b/public/-/emojis/2/expressionless.png
new file mode 100644
index 00000000000..9343ff25768
--- /dev/null
+++ b/public/-/emojis/2/expressionless.png
Binary files differ
diff --git a/public/-/emojis/2/eye.png b/public/-/emojis/2/eye.png
new file mode 100644
index 00000000000..3ed81334987
--- /dev/null
+++ b/public/-/emojis/2/eye.png
Binary files differ
diff --git a/public/-/emojis/2/eye_in_speech_bubble.png b/public/-/emojis/2/eye_in_speech_bubble.png
new file mode 100644
index 00000000000..17517147011
--- /dev/null
+++ b/public/-/emojis/2/eye_in_speech_bubble.png
Binary files differ
diff --git a/public/-/emojis/2/eyeglasses.png b/public/-/emojis/2/eyeglasses.png
new file mode 100644
index 00000000000..bb40227139e
--- /dev/null
+++ b/public/-/emojis/2/eyeglasses.png
Binary files differ
diff --git a/public/-/emojis/2/eyes.png b/public/-/emojis/2/eyes.png
new file mode 100644
index 00000000000..61359d39629
--- /dev/null
+++ b/public/-/emojis/2/eyes.png
Binary files differ
diff --git a/public/-/emojis/2/face_palm.png b/public/-/emojis/2/face_palm.png
new file mode 100644
index 00000000000..002c60b3622
--- /dev/null
+++ b/public/-/emojis/2/face_palm.png
Binary files differ
diff --git a/public/-/emojis/2/face_palm_tone1.png b/public/-/emojis/2/face_palm_tone1.png
new file mode 100644
index 00000000000..fb126e9e89f
--- /dev/null
+++ b/public/-/emojis/2/face_palm_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/face_palm_tone2.png b/public/-/emojis/2/face_palm_tone2.png
new file mode 100644
index 00000000000..84a0fba7993
--- /dev/null
+++ b/public/-/emojis/2/face_palm_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/face_palm_tone3.png b/public/-/emojis/2/face_palm_tone3.png
new file mode 100644
index 00000000000..fe5fe356641
--- /dev/null
+++ b/public/-/emojis/2/face_palm_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/face_palm_tone4.png b/public/-/emojis/2/face_palm_tone4.png
new file mode 100644
index 00000000000..6e9e22338cf
--- /dev/null
+++ b/public/-/emojis/2/face_palm_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/face_palm_tone5.png b/public/-/emojis/2/face_palm_tone5.png
new file mode 100644
index 00000000000..ddac1343cb2
--- /dev/null
+++ b/public/-/emojis/2/face_palm_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/factory.png b/public/-/emojis/2/factory.png
new file mode 100644
index 00000000000..cabe180b278
--- /dev/null
+++ b/public/-/emojis/2/factory.png
Binary files differ
diff --git a/public/-/emojis/2/fallen_leaf.png b/public/-/emojis/2/fallen_leaf.png
new file mode 100644
index 00000000000..931532c6603
--- /dev/null
+++ b/public/-/emojis/2/fallen_leaf.png
Binary files differ
diff --git a/public/-/emojis/2/family.png b/public/-/emojis/2/family.png
new file mode 100644
index 00000000000..4b0ba60c626
--- /dev/null
+++ b/public/-/emojis/2/family.png
Binary files differ
diff --git a/public/-/emojis/2/family_mmb.png b/public/-/emojis/2/family_mmb.png
new file mode 100644
index 00000000000..98d7c8ca41c
--- /dev/null
+++ b/public/-/emojis/2/family_mmb.png
Binary files differ
diff --git a/public/-/emojis/2/family_mmbb.png b/public/-/emojis/2/family_mmbb.png
new file mode 100644
index 00000000000..bc7f57d9ff1
--- /dev/null
+++ b/public/-/emojis/2/family_mmbb.png
Binary files differ
diff --git a/public/-/emojis/2/family_mmg.png b/public/-/emojis/2/family_mmg.png
new file mode 100644
index 00000000000..7c810606d79
--- /dev/null
+++ b/public/-/emojis/2/family_mmg.png
Binary files differ
diff --git a/public/-/emojis/2/family_mmgb.png b/public/-/emojis/2/family_mmgb.png
new file mode 100644
index 00000000000..7b41b66f57e
--- /dev/null
+++ b/public/-/emojis/2/family_mmgb.png
Binary files differ
diff --git a/public/-/emojis/2/family_mmgg.png b/public/-/emojis/2/family_mmgg.png
new file mode 100644
index 00000000000..ce89a085800
--- /dev/null
+++ b/public/-/emojis/2/family_mmgg.png
Binary files differ
diff --git a/public/-/emojis/2/family_mwbb.png b/public/-/emojis/2/family_mwbb.png
new file mode 100644
index 00000000000..b8679e572f2
--- /dev/null
+++ b/public/-/emojis/2/family_mwbb.png
Binary files differ
diff --git a/public/-/emojis/2/family_mwg.png b/public/-/emojis/2/family_mwg.png
new file mode 100644
index 00000000000..affc7206f23
--- /dev/null
+++ b/public/-/emojis/2/family_mwg.png
Binary files differ
diff --git a/public/-/emojis/2/family_mwgb.png b/public/-/emojis/2/family_mwgb.png
new file mode 100644
index 00000000000..5951cf11be3
--- /dev/null
+++ b/public/-/emojis/2/family_mwgb.png
Binary files differ
diff --git a/public/-/emojis/2/family_mwgg.png b/public/-/emojis/2/family_mwgg.png
new file mode 100644
index 00000000000..7aaec104e31
--- /dev/null
+++ b/public/-/emojis/2/family_mwgg.png
Binary files differ
diff --git a/public/-/emojis/2/family_wwb.png b/public/-/emojis/2/family_wwb.png
new file mode 100644
index 00000000000..fb40fefe84a
--- /dev/null
+++ b/public/-/emojis/2/family_wwb.png
Binary files differ
diff --git a/public/-/emojis/2/family_wwbb.png b/public/-/emojis/2/family_wwbb.png
new file mode 100644
index 00000000000..1b6f6ae2434
--- /dev/null
+++ b/public/-/emojis/2/family_wwbb.png
Binary files differ
diff --git a/public/-/emojis/2/family_wwg.png b/public/-/emojis/2/family_wwg.png
new file mode 100644
index 00000000000..6e17b1e8ed6
--- /dev/null
+++ b/public/-/emojis/2/family_wwg.png
Binary files differ
diff --git a/public/-/emojis/2/family_wwgb.png b/public/-/emojis/2/family_wwgb.png
new file mode 100644
index 00000000000..23eeaad269d
--- /dev/null
+++ b/public/-/emojis/2/family_wwgb.png
Binary files differ
diff --git a/public/-/emojis/2/family_wwgg.png b/public/-/emojis/2/family_wwgg.png
new file mode 100644
index 00000000000..c2c19736a96
--- /dev/null
+++ b/public/-/emojis/2/family_wwgg.png
Binary files differ
diff --git a/public/-/emojis/2/fast_forward.png b/public/-/emojis/2/fast_forward.png
new file mode 100644
index 00000000000..307199414d4
--- /dev/null
+++ b/public/-/emojis/2/fast_forward.png
Binary files differ
diff --git a/public/-/emojis/2/fax.png b/public/-/emojis/2/fax.png
new file mode 100644
index 00000000000..ff4ab54244e
--- /dev/null
+++ b/public/-/emojis/2/fax.png
Binary files differ
diff --git a/public/-/emojis/2/fearful.png b/public/-/emojis/2/fearful.png
new file mode 100644
index 00000000000..c6dc3d8f19a
--- /dev/null
+++ b/public/-/emojis/2/fearful.png
Binary files differ
diff --git a/public/-/emojis/2/feet.png b/public/-/emojis/2/feet.png
new file mode 100644
index 00000000000..622a3f4d7f5
--- /dev/null
+++ b/public/-/emojis/2/feet.png
Binary files differ
diff --git a/public/-/emojis/2/fencer.png b/public/-/emojis/2/fencer.png
new file mode 100644
index 00000000000..39ee19e1e3c
--- /dev/null
+++ b/public/-/emojis/2/fencer.png
Binary files differ
diff --git a/public/-/emojis/2/ferris_wheel.png b/public/-/emojis/2/ferris_wheel.png
new file mode 100644
index 00000000000..a2f6c2d9415
--- /dev/null
+++ b/public/-/emojis/2/ferris_wheel.png
Binary files differ
diff --git a/public/-/emojis/2/ferry.png b/public/-/emojis/2/ferry.png
new file mode 100644
index 00000000000..60e738626ea
--- /dev/null
+++ b/public/-/emojis/2/ferry.png
Binary files differ
diff --git a/public/-/emojis/2/field_hockey.png b/public/-/emojis/2/field_hockey.png
new file mode 100644
index 00000000000..758e09349a2
--- /dev/null
+++ b/public/-/emojis/2/field_hockey.png
Binary files differ
diff --git a/public/-/emojis/2/file_cabinet.png b/public/-/emojis/2/file_cabinet.png
new file mode 100644
index 00000000000..88531539f2e
--- /dev/null
+++ b/public/-/emojis/2/file_cabinet.png
Binary files differ
diff --git a/public/-/emojis/2/file_folder.png b/public/-/emojis/2/file_folder.png
new file mode 100644
index 00000000000..47a14a2836a
--- /dev/null
+++ b/public/-/emojis/2/file_folder.png
Binary files differ
diff --git a/public/-/emojis/2/film_frames.png b/public/-/emojis/2/film_frames.png
new file mode 100644
index 00000000000..528cf55a933
--- /dev/null
+++ b/public/-/emojis/2/film_frames.png
Binary files differ
diff --git a/public/-/emojis/2/fingers_crossed.png b/public/-/emojis/2/fingers_crossed.png
new file mode 100644
index 00000000000..2c065dcd557
--- /dev/null
+++ b/public/-/emojis/2/fingers_crossed.png
Binary files differ
diff --git a/public/-/emojis/2/fingers_crossed_tone1.png b/public/-/emojis/2/fingers_crossed_tone1.png
new file mode 100644
index 00000000000..c3864ac868f
--- /dev/null
+++ b/public/-/emojis/2/fingers_crossed_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/fingers_crossed_tone2.png b/public/-/emojis/2/fingers_crossed_tone2.png
new file mode 100644
index 00000000000..82f3b9ce4fe
--- /dev/null
+++ b/public/-/emojis/2/fingers_crossed_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/fingers_crossed_tone3.png b/public/-/emojis/2/fingers_crossed_tone3.png
new file mode 100644
index 00000000000..199fe0cf68d
--- /dev/null
+++ b/public/-/emojis/2/fingers_crossed_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/fingers_crossed_tone4.png b/public/-/emojis/2/fingers_crossed_tone4.png
new file mode 100644
index 00000000000..12d6b8d2963
--- /dev/null
+++ b/public/-/emojis/2/fingers_crossed_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/fingers_crossed_tone5.png b/public/-/emojis/2/fingers_crossed_tone5.png
new file mode 100644
index 00000000000..9a62704dd92
--- /dev/null
+++ b/public/-/emojis/2/fingers_crossed_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/fire.png b/public/-/emojis/2/fire.png
new file mode 100644
index 00000000000..83f34701807
--- /dev/null
+++ b/public/-/emojis/2/fire.png
Binary files differ
diff --git a/public/-/emojis/2/fire_engine.png b/public/-/emojis/2/fire_engine.png
new file mode 100644
index 00000000000..271141fd1b9
--- /dev/null
+++ b/public/-/emojis/2/fire_engine.png
Binary files differ
diff --git a/public/-/emojis/2/fireworks.png b/public/-/emojis/2/fireworks.png
new file mode 100644
index 00000000000..dcfff099ad3
--- /dev/null
+++ b/public/-/emojis/2/fireworks.png
Binary files differ
diff --git a/public/-/emojis/2/first_place.png b/public/-/emojis/2/first_place.png
new file mode 100644
index 00000000000..bf22f19b833
--- /dev/null
+++ b/public/-/emojis/2/first_place.png
Binary files differ
diff --git a/public/-/emojis/2/first_quarter_moon.png b/public/-/emojis/2/first_quarter_moon.png
new file mode 100644
index 00000000000..aeb729f4ce1
--- /dev/null
+++ b/public/-/emojis/2/first_quarter_moon.png
Binary files differ
diff --git a/public/-/emojis/2/first_quarter_moon_with_face.png b/public/-/emojis/2/first_quarter_moon_with_face.png
new file mode 100644
index 00000000000..8042d82544a
--- /dev/null
+++ b/public/-/emojis/2/first_quarter_moon_with_face.png
Binary files differ
diff --git a/public/-/emojis/2/fish.png b/public/-/emojis/2/fish.png
new file mode 100644
index 00000000000..945e72ce9f6
--- /dev/null
+++ b/public/-/emojis/2/fish.png
Binary files differ
diff --git a/public/-/emojis/2/fish_cake.png b/public/-/emojis/2/fish_cake.png
new file mode 100644
index 00000000000..31bb39b908b
--- /dev/null
+++ b/public/-/emojis/2/fish_cake.png
Binary files differ
diff --git a/public/-/emojis/2/fishing_pole_and_fish.png b/public/-/emojis/2/fishing_pole_and_fish.png
new file mode 100644
index 00000000000..5f0fd69a69c
--- /dev/null
+++ b/public/-/emojis/2/fishing_pole_and_fish.png
Binary files differ
diff --git a/public/-/emojis/2/fist.png b/public/-/emojis/2/fist.png
new file mode 100644
index 00000000000..0750351373d
--- /dev/null
+++ b/public/-/emojis/2/fist.png
Binary files differ
diff --git a/public/-/emojis/2/fist_tone1.png b/public/-/emojis/2/fist_tone1.png
new file mode 100644
index 00000000000..bdd0e44d659
--- /dev/null
+++ b/public/-/emojis/2/fist_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/fist_tone2.png b/public/-/emojis/2/fist_tone2.png
new file mode 100644
index 00000000000..7189dba83f2
--- /dev/null
+++ b/public/-/emojis/2/fist_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/fist_tone3.png b/public/-/emojis/2/fist_tone3.png
new file mode 100644
index 00000000000..e0d6ec2ffc3
--- /dev/null
+++ b/public/-/emojis/2/fist_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/fist_tone4.png b/public/-/emojis/2/fist_tone4.png
new file mode 100644
index 00000000000..3d2c974bc00
--- /dev/null
+++ b/public/-/emojis/2/fist_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/fist_tone5.png b/public/-/emojis/2/fist_tone5.png
new file mode 100644
index 00000000000..84d1f68bf4d
--- /dev/null
+++ b/public/-/emojis/2/fist_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/five.png b/public/-/emojis/2/five.png
new file mode 100644
index 00000000000..e7e387b889e
--- /dev/null
+++ b/public/-/emojis/2/five.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ac.png b/public/-/emojis/2/flag_ac.png
new file mode 100644
index 00000000000..e7e7bcaad81
--- /dev/null
+++ b/public/-/emojis/2/flag_ac.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ad.png b/public/-/emojis/2/flag_ad.png
new file mode 100644
index 00000000000..105439cc07e
--- /dev/null
+++ b/public/-/emojis/2/flag_ad.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ae.png b/public/-/emojis/2/flag_ae.png
new file mode 100644
index 00000000000..33b21809a0c
--- /dev/null
+++ b/public/-/emojis/2/flag_ae.png
Binary files differ
diff --git a/public/-/emojis/2/flag_af.png b/public/-/emojis/2/flag_af.png
new file mode 100644
index 00000000000..ab0fe0e4f74
--- /dev/null
+++ b/public/-/emojis/2/flag_af.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ag.png b/public/-/emojis/2/flag_ag.png
new file mode 100644
index 00000000000..2c73fdf1525
--- /dev/null
+++ b/public/-/emojis/2/flag_ag.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ai.png b/public/-/emojis/2/flag_ai.png
new file mode 100644
index 00000000000..065ab03e0ce
--- /dev/null
+++ b/public/-/emojis/2/flag_ai.png
Binary files differ
diff --git a/public/-/emojis/2/flag_al.png b/public/-/emojis/2/flag_al.png
new file mode 100644
index 00000000000..dc0a90eef32
--- /dev/null
+++ b/public/-/emojis/2/flag_al.png
Binary files differ
diff --git a/public/-/emojis/2/flag_am.png b/public/-/emojis/2/flag_am.png
new file mode 100644
index 00000000000..065d25b7153
--- /dev/null
+++ b/public/-/emojis/2/flag_am.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ao.png b/public/-/emojis/2/flag_ao.png
new file mode 100644
index 00000000000..dd957f9ef1d
--- /dev/null
+++ b/public/-/emojis/2/flag_ao.png
Binary files differ
diff --git a/public/-/emojis/2/flag_aq.png b/public/-/emojis/2/flag_aq.png
new file mode 100644
index 00000000000..930e8e3a726
--- /dev/null
+++ b/public/-/emojis/2/flag_aq.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ar.png b/public/-/emojis/2/flag_ar.png
new file mode 100644
index 00000000000..db8209c85c2
--- /dev/null
+++ b/public/-/emojis/2/flag_ar.png
Binary files differ
diff --git a/public/-/emojis/2/flag_as.png b/public/-/emojis/2/flag_as.png
new file mode 100644
index 00000000000..11213f5704a
--- /dev/null
+++ b/public/-/emojis/2/flag_as.png
Binary files differ
diff --git a/public/-/emojis/2/flag_at.png b/public/-/emojis/2/flag_at.png
new file mode 100644
index 00000000000..b33df6aa245
--- /dev/null
+++ b/public/-/emojis/2/flag_at.png
Binary files differ
diff --git a/public/-/emojis/2/flag_au.png b/public/-/emojis/2/flag_au.png
new file mode 100644
index 00000000000..411488897f8
--- /dev/null
+++ b/public/-/emojis/2/flag_au.png
Binary files differ
diff --git a/public/-/emojis/2/flag_aw.png b/public/-/emojis/2/flag_aw.png
new file mode 100644
index 00000000000..3973babb781
--- /dev/null
+++ b/public/-/emojis/2/flag_aw.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ax.png b/public/-/emojis/2/flag_ax.png
new file mode 100644
index 00000000000..11920409024
--- /dev/null
+++ b/public/-/emojis/2/flag_ax.png
Binary files differ
diff --git a/public/-/emojis/2/flag_az.png b/public/-/emojis/2/flag_az.png
new file mode 100644
index 00000000000..e59359684bc
--- /dev/null
+++ b/public/-/emojis/2/flag_az.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ba.png b/public/-/emojis/2/flag_ba.png
new file mode 100644
index 00000000000..d810071c62f
--- /dev/null
+++ b/public/-/emojis/2/flag_ba.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bb.png b/public/-/emojis/2/flag_bb.png
new file mode 100644
index 00000000000..0f8881e39b7
--- /dev/null
+++ b/public/-/emojis/2/flag_bb.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bd.png b/public/-/emojis/2/flag_bd.png
new file mode 100644
index 00000000000..17bcfe491ec
--- /dev/null
+++ b/public/-/emojis/2/flag_bd.png
Binary files differ
diff --git a/public/-/emojis/2/flag_be.png b/public/-/emojis/2/flag_be.png
new file mode 100644
index 00000000000..105dd2bfba7
--- /dev/null
+++ b/public/-/emojis/2/flag_be.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bf.png b/public/-/emojis/2/flag_bf.png
new file mode 100644
index 00000000000..ea075a3b880
--- /dev/null
+++ b/public/-/emojis/2/flag_bf.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bg.png b/public/-/emojis/2/flag_bg.png
new file mode 100644
index 00000000000..9210245917c
--- /dev/null
+++ b/public/-/emojis/2/flag_bg.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bh.png b/public/-/emojis/2/flag_bh.png
new file mode 100644
index 00000000000..2ed0ea1c7a0
--- /dev/null
+++ b/public/-/emojis/2/flag_bh.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bi.png b/public/-/emojis/2/flag_bi.png
new file mode 100644
index 00000000000..98839afcf3a
--- /dev/null
+++ b/public/-/emojis/2/flag_bi.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bj.png b/public/-/emojis/2/flag_bj.png
new file mode 100644
index 00000000000..dffe78e8e0e
--- /dev/null
+++ b/public/-/emojis/2/flag_bj.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bl.png b/public/-/emojis/2/flag_bl.png
new file mode 100644
index 00000000000..267a479dc37
--- /dev/null
+++ b/public/-/emojis/2/flag_bl.png
Binary files differ
diff --git a/public/-/emojis/2/flag_black.png b/public/-/emojis/2/flag_black.png
new file mode 100644
index 00000000000..60c40762a30
--- /dev/null
+++ b/public/-/emojis/2/flag_black.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bm.png b/public/-/emojis/2/flag_bm.png
new file mode 100644
index 00000000000..6c1c56313a2
--- /dev/null
+++ b/public/-/emojis/2/flag_bm.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bn.png b/public/-/emojis/2/flag_bn.png
new file mode 100644
index 00000000000..8e698042cd4
--- /dev/null
+++ b/public/-/emojis/2/flag_bn.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bo.png b/public/-/emojis/2/flag_bo.png
new file mode 100644
index 00000000000..45714cc5f96
--- /dev/null
+++ b/public/-/emojis/2/flag_bo.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bq.png b/public/-/emojis/2/flag_bq.png
new file mode 100644
index 00000000000..52bf03c5017
--- /dev/null
+++ b/public/-/emojis/2/flag_bq.png
Binary files differ
diff --git a/public/-/emojis/2/flag_br.png b/public/-/emojis/2/flag_br.png
new file mode 100644
index 00000000000..1d32b466587
--- /dev/null
+++ b/public/-/emojis/2/flag_br.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bs.png b/public/-/emojis/2/flag_bs.png
new file mode 100644
index 00000000000..3d7cadc9506
--- /dev/null
+++ b/public/-/emojis/2/flag_bs.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bt.png b/public/-/emojis/2/flag_bt.png
new file mode 100644
index 00000000000..bb7219420d3
--- /dev/null
+++ b/public/-/emojis/2/flag_bt.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bv.png b/public/-/emojis/2/flag_bv.png
new file mode 100644
index 00000000000..d94e9a72179
--- /dev/null
+++ b/public/-/emojis/2/flag_bv.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bw.png b/public/-/emojis/2/flag_bw.png
new file mode 100644
index 00000000000..9cbeaa67eea
--- /dev/null
+++ b/public/-/emojis/2/flag_bw.png
Binary files differ
diff --git a/public/-/emojis/2/flag_by.png b/public/-/emojis/2/flag_by.png
new file mode 100644
index 00000000000..8470eaf9b1e
--- /dev/null
+++ b/public/-/emojis/2/flag_by.png
Binary files differ
diff --git a/public/-/emojis/2/flag_bz.png b/public/-/emojis/2/flag_bz.png
new file mode 100644
index 00000000000..2e26a0d6ef8
--- /dev/null
+++ b/public/-/emojis/2/flag_bz.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ca.png b/public/-/emojis/2/flag_ca.png
new file mode 100644
index 00000000000..044edd36311
--- /dev/null
+++ b/public/-/emojis/2/flag_ca.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cc.png b/public/-/emojis/2/flag_cc.png
new file mode 100644
index 00000000000..54e4972ec1d
--- /dev/null
+++ b/public/-/emojis/2/flag_cc.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cd.png b/public/-/emojis/2/flag_cd.png
new file mode 100644
index 00000000000..53fbf77e757
--- /dev/null
+++ b/public/-/emojis/2/flag_cd.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cf.png b/public/-/emojis/2/flag_cf.png
new file mode 100644
index 00000000000..d1db72b656e
--- /dev/null
+++ b/public/-/emojis/2/flag_cf.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cg.png b/public/-/emojis/2/flag_cg.png
new file mode 100644
index 00000000000..c1145ed54b5
--- /dev/null
+++ b/public/-/emojis/2/flag_cg.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ch.png b/public/-/emojis/2/flag_ch.png
new file mode 100644
index 00000000000..700c7fde14d
--- /dev/null
+++ b/public/-/emojis/2/flag_ch.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ci.png b/public/-/emojis/2/flag_ci.png
new file mode 100644
index 00000000000..6629b379c97
--- /dev/null
+++ b/public/-/emojis/2/flag_ci.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ck.png b/public/-/emojis/2/flag_ck.png
new file mode 100644
index 00000000000..11be975c5b0
--- /dev/null
+++ b/public/-/emojis/2/flag_ck.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cl.png b/public/-/emojis/2/flag_cl.png
new file mode 100644
index 00000000000..3c23b255425
--- /dev/null
+++ b/public/-/emojis/2/flag_cl.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cm.png b/public/-/emojis/2/flag_cm.png
new file mode 100644
index 00000000000..6a0bd3cea0c
--- /dev/null
+++ b/public/-/emojis/2/flag_cm.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cn.png b/public/-/emojis/2/flag_cn.png
new file mode 100644
index 00000000000..327aa7dd7bf
--- /dev/null
+++ b/public/-/emojis/2/flag_cn.png
Binary files differ
diff --git a/public/-/emojis/2/flag_co.png b/public/-/emojis/2/flag_co.png
new file mode 100644
index 00000000000..3d8cd9e41f2
--- /dev/null
+++ b/public/-/emojis/2/flag_co.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cp.png b/public/-/emojis/2/flag_cp.png
new file mode 100644
index 00000000000..98039a24e6b
--- /dev/null
+++ b/public/-/emojis/2/flag_cp.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cr.png b/public/-/emojis/2/flag_cr.png
new file mode 100644
index 00000000000..78941a89143
--- /dev/null
+++ b/public/-/emojis/2/flag_cr.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cu.png b/public/-/emojis/2/flag_cu.png
new file mode 100644
index 00000000000..67faa51a5d2
--- /dev/null
+++ b/public/-/emojis/2/flag_cu.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cv.png b/public/-/emojis/2/flag_cv.png
new file mode 100644
index 00000000000..6f481eae77e
--- /dev/null
+++ b/public/-/emojis/2/flag_cv.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cw.png b/public/-/emojis/2/flag_cw.png
new file mode 100644
index 00000000000..afb10f14b60
--- /dev/null
+++ b/public/-/emojis/2/flag_cw.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cx.png b/public/-/emojis/2/flag_cx.png
new file mode 100644
index 00000000000..4fec7f6220f
--- /dev/null
+++ b/public/-/emojis/2/flag_cx.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cy.png b/public/-/emojis/2/flag_cy.png
new file mode 100644
index 00000000000..6d14cf405ff
--- /dev/null
+++ b/public/-/emojis/2/flag_cy.png
Binary files differ
diff --git a/public/-/emojis/2/flag_cz.png b/public/-/emojis/2/flag_cz.png
new file mode 100644
index 00000000000..0182b611410
--- /dev/null
+++ b/public/-/emojis/2/flag_cz.png
Binary files differ
diff --git a/public/-/emojis/2/flag_de.png b/public/-/emojis/2/flag_de.png
new file mode 100644
index 00000000000..3298cfccacd
--- /dev/null
+++ b/public/-/emojis/2/flag_de.png
Binary files differ
diff --git a/public/-/emojis/2/flag_dg.png b/public/-/emojis/2/flag_dg.png
new file mode 100644
index 00000000000..520adc653cc
--- /dev/null
+++ b/public/-/emojis/2/flag_dg.png
Binary files differ
diff --git a/public/-/emojis/2/flag_dj.png b/public/-/emojis/2/flag_dj.png
new file mode 100644
index 00000000000..eef897f1734
--- /dev/null
+++ b/public/-/emojis/2/flag_dj.png
Binary files differ
diff --git a/public/-/emojis/2/flag_dk.png b/public/-/emojis/2/flag_dk.png
new file mode 100644
index 00000000000..120a8fd7138
--- /dev/null
+++ b/public/-/emojis/2/flag_dk.png
Binary files differ
diff --git a/public/-/emojis/2/flag_dm.png b/public/-/emojis/2/flag_dm.png
new file mode 100644
index 00000000000..5c5999be098
--- /dev/null
+++ b/public/-/emojis/2/flag_dm.png
Binary files differ
diff --git a/public/-/emojis/2/flag_do.png b/public/-/emojis/2/flag_do.png
new file mode 100644
index 00000000000..d59ec7e54ef
--- /dev/null
+++ b/public/-/emojis/2/flag_do.png
Binary files differ
diff --git a/public/-/emojis/2/flag_dz.png b/public/-/emojis/2/flag_dz.png
new file mode 100644
index 00000000000..c7d8acc9c66
--- /dev/null
+++ b/public/-/emojis/2/flag_dz.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ea.png b/public/-/emojis/2/flag_ea.png
new file mode 100644
index 00000000000..d48640c85d8
--- /dev/null
+++ b/public/-/emojis/2/flag_ea.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ec.png b/public/-/emojis/2/flag_ec.png
new file mode 100644
index 00000000000..61dddf35f10
--- /dev/null
+++ b/public/-/emojis/2/flag_ec.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ee.png b/public/-/emojis/2/flag_ee.png
new file mode 100644
index 00000000000..620f80e4206
--- /dev/null
+++ b/public/-/emojis/2/flag_ee.png
Binary files differ
diff --git a/public/-/emojis/2/flag_eg.png b/public/-/emojis/2/flag_eg.png
new file mode 100644
index 00000000000..8799f624c2d
--- /dev/null
+++ b/public/-/emojis/2/flag_eg.png
Binary files differ
diff --git a/public/-/emojis/2/flag_eh.png b/public/-/emojis/2/flag_eh.png
new file mode 100644
index 00000000000..829595e4c2c
--- /dev/null
+++ b/public/-/emojis/2/flag_eh.png
Binary files differ
diff --git a/public/-/emojis/2/flag_er.png b/public/-/emojis/2/flag_er.png
new file mode 100644
index 00000000000..a29c0662463
--- /dev/null
+++ b/public/-/emojis/2/flag_er.png
Binary files differ
diff --git a/public/-/emojis/2/flag_es.png b/public/-/emojis/2/flag_es.png
new file mode 100644
index 00000000000..d48640c85d8
--- /dev/null
+++ b/public/-/emojis/2/flag_es.png
Binary files differ
diff --git a/public/-/emojis/2/flag_et.png b/public/-/emojis/2/flag_et.png
new file mode 100644
index 00000000000..a848b8cd19f
--- /dev/null
+++ b/public/-/emojis/2/flag_et.png
Binary files differ
diff --git a/public/-/emojis/2/flag_eu.png b/public/-/emojis/2/flag_eu.png
new file mode 100644
index 00000000000..940d25cbfa1
--- /dev/null
+++ b/public/-/emojis/2/flag_eu.png
Binary files differ
diff --git a/public/-/emojis/2/flag_fi.png b/public/-/emojis/2/flag_fi.png
new file mode 100644
index 00000000000..525b45b11ad
--- /dev/null
+++ b/public/-/emojis/2/flag_fi.png
Binary files differ
diff --git a/public/-/emojis/2/flag_fj.png b/public/-/emojis/2/flag_fj.png
new file mode 100644
index 00000000000..eff4c31d825
--- /dev/null
+++ b/public/-/emojis/2/flag_fj.png
Binary files differ
diff --git a/public/-/emojis/2/flag_fk.png b/public/-/emojis/2/flag_fk.png
new file mode 100644
index 00000000000..32d298878c0
--- /dev/null
+++ b/public/-/emojis/2/flag_fk.png
Binary files differ
diff --git a/public/-/emojis/2/flag_fm.png b/public/-/emojis/2/flag_fm.png
new file mode 100644
index 00000000000..e60b16cc45a
--- /dev/null
+++ b/public/-/emojis/2/flag_fm.png
Binary files differ
diff --git a/public/-/emojis/2/flag_fo.png b/public/-/emojis/2/flag_fo.png
new file mode 100644
index 00000000000..5a518772352
--- /dev/null
+++ b/public/-/emojis/2/flag_fo.png
Binary files differ
diff --git a/public/-/emojis/2/flag_fr.png b/public/-/emojis/2/flag_fr.png
new file mode 100644
index 00000000000..98039a24e6b
--- /dev/null
+++ b/public/-/emojis/2/flag_fr.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ga.png b/public/-/emojis/2/flag_ga.png
new file mode 100644
index 00000000000..28c24da1100
--- /dev/null
+++ b/public/-/emojis/2/flag_ga.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gb.png b/public/-/emojis/2/flag_gb.png
new file mode 100644
index 00000000000..0ca6ffbdf69
--- /dev/null
+++ b/public/-/emojis/2/flag_gb.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gd.png b/public/-/emojis/2/flag_gd.png
new file mode 100644
index 00000000000..d0d4abc000e
--- /dev/null
+++ b/public/-/emojis/2/flag_gd.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ge.png b/public/-/emojis/2/flag_ge.png
new file mode 100644
index 00000000000..f9fab204a42
--- /dev/null
+++ b/public/-/emojis/2/flag_ge.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gf.png b/public/-/emojis/2/flag_gf.png
new file mode 100644
index 00000000000..a762e4f4303
--- /dev/null
+++ b/public/-/emojis/2/flag_gf.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gg.png b/public/-/emojis/2/flag_gg.png
new file mode 100644
index 00000000000..d90a4d5fb95
--- /dev/null
+++ b/public/-/emojis/2/flag_gg.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gh.png b/public/-/emojis/2/flag_gh.png
new file mode 100644
index 00000000000..82a2f41e187
--- /dev/null
+++ b/public/-/emojis/2/flag_gh.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gi.png b/public/-/emojis/2/flag_gi.png
new file mode 100644
index 00000000000..c2d84ddcb38
--- /dev/null
+++ b/public/-/emojis/2/flag_gi.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gl.png b/public/-/emojis/2/flag_gl.png
new file mode 100644
index 00000000000..6f38711a78c
--- /dev/null
+++ b/public/-/emojis/2/flag_gl.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gm.png b/public/-/emojis/2/flag_gm.png
new file mode 100644
index 00000000000..9b5b726373d
--- /dev/null
+++ b/public/-/emojis/2/flag_gm.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gn.png b/public/-/emojis/2/flag_gn.png
new file mode 100644
index 00000000000..8821ec9bd42
--- /dev/null
+++ b/public/-/emojis/2/flag_gn.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gp.png b/public/-/emojis/2/flag_gp.png
new file mode 100644
index 00000000000..a647fced59b
--- /dev/null
+++ b/public/-/emojis/2/flag_gp.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gq.png b/public/-/emojis/2/flag_gq.png
new file mode 100644
index 00000000000..11cc7efcc09
--- /dev/null
+++ b/public/-/emojis/2/flag_gq.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gr.png b/public/-/emojis/2/flag_gr.png
new file mode 100644
index 00000000000..d21b9090c46
--- /dev/null
+++ b/public/-/emojis/2/flag_gr.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gs.png b/public/-/emojis/2/flag_gs.png
new file mode 100644
index 00000000000..6134e4d008a
--- /dev/null
+++ b/public/-/emojis/2/flag_gs.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gt.png b/public/-/emojis/2/flag_gt.png
new file mode 100644
index 00000000000..f6164936b1e
--- /dev/null
+++ b/public/-/emojis/2/flag_gt.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gu.png b/public/-/emojis/2/flag_gu.png
new file mode 100644
index 00000000000..a98170e8398
--- /dev/null
+++ b/public/-/emojis/2/flag_gu.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gw.png b/public/-/emojis/2/flag_gw.png
new file mode 100644
index 00000000000..e378bef4372
--- /dev/null
+++ b/public/-/emojis/2/flag_gw.png
Binary files differ
diff --git a/public/-/emojis/2/flag_gy.png b/public/-/emojis/2/flag_gy.png
new file mode 100644
index 00000000000..ecda480554c
--- /dev/null
+++ b/public/-/emojis/2/flag_gy.png
Binary files differ
diff --git a/public/-/emojis/2/flag_hk.png b/public/-/emojis/2/flag_hk.png
new file mode 100644
index 00000000000..a10bb088089
--- /dev/null
+++ b/public/-/emojis/2/flag_hk.png
Binary files differ
diff --git a/public/-/emojis/2/flag_hm.png b/public/-/emojis/2/flag_hm.png
new file mode 100644
index 00000000000..411488897f8
--- /dev/null
+++ b/public/-/emojis/2/flag_hm.png
Binary files differ
diff --git a/public/-/emojis/2/flag_hn.png b/public/-/emojis/2/flag_hn.png
new file mode 100644
index 00000000000..d0022feac8e
--- /dev/null
+++ b/public/-/emojis/2/flag_hn.png
Binary files differ
diff --git a/public/-/emojis/2/flag_hr.png b/public/-/emojis/2/flag_hr.png
new file mode 100644
index 00000000000..e802cb38946
--- /dev/null
+++ b/public/-/emojis/2/flag_hr.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ht.png b/public/-/emojis/2/flag_ht.png
new file mode 100644
index 00000000000..f82286d8814
--- /dev/null
+++ b/public/-/emojis/2/flag_ht.png
Binary files differ
diff --git a/public/-/emojis/2/flag_hu.png b/public/-/emojis/2/flag_hu.png
new file mode 100644
index 00000000000..e32ae6719f6
--- /dev/null
+++ b/public/-/emojis/2/flag_hu.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ic.png b/public/-/emojis/2/flag_ic.png
new file mode 100644
index 00000000000..e99d9d3f245
--- /dev/null
+++ b/public/-/emojis/2/flag_ic.png
Binary files differ
diff --git a/public/-/emojis/2/flag_id.png b/public/-/emojis/2/flag_id.png
new file mode 100644
index 00000000000..3cfc3fa45c8
--- /dev/null
+++ b/public/-/emojis/2/flag_id.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ie.png b/public/-/emojis/2/flag_ie.png
new file mode 100644
index 00000000000..0dd86179495
--- /dev/null
+++ b/public/-/emojis/2/flag_ie.png
Binary files differ
diff --git a/public/-/emojis/2/flag_il.png b/public/-/emojis/2/flag_il.png
new file mode 100644
index 00000000000..439ced78d3b
--- /dev/null
+++ b/public/-/emojis/2/flag_il.png
Binary files differ
diff --git a/public/-/emojis/2/flag_im.png b/public/-/emojis/2/flag_im.png
new file mode 100644
index 00000000000..69fc5a30ed9
--- /dev/null
+++ b/public/-/emojis/2/flag_im.png
Binary files differ
diff --git a/public/-/emojis/2/flag_in.png b/public/-/emojis/2/flag_in.png
new file mode 100644
index 00000000000..8ad7e9447d1
--- /dev/null
+++ b/public/-/emojis/2/flag_in.png
Binary files differ
diff --git a/public/-/emojis/2/flag_io.png b/public/-/emojis/2/flag_io.png
new file mode 100644
index 00000000000..520adc653cc
--- /dev/null
+++ b/public/-/emojis/2/flag_io.png
Binary files differ
diff --git a/public/-/emojis/2/flag_iq.png b/public/-/emojis/2/flag_iq.png
new file mode 100644
index 00000000000..3af377f252d
--- /dev/null
+++ b/public/-/emojis/2/flag_iq.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ir.png b/public/-/emojis/2/flag_ir.png
new file mode 100644
index 00000000000..66c91de1b35
--- /dev/null
+++ b/public/-/emojis/2/flag_ir.png
Binary files differ
diff --git a/public/-/emojis/2/flag_is.png b/public/-/emojis/2/flag_is.png
new file mode 100644
index 00000000000..0b0379b6993
--- /dev/null
+++ b/public/-/emojis/2/flag_is.png
Binary files differ
diff --git a/public/-/emojis/2/flag_it.png b/public/-/emojis/2/flag_it.png
new file mode 100644
index 00000000000..b18c50adea5
--- /dev/null
+++ b/public/-/emojis/2/flag_it.png
Binary files differ
diff --git a/public/-/emojis/2/flag_je.png b/public/-/emojis/2/flag_je.png
new file mode 100644
index 00000000000..c514594f15e
--- /dev/null
+++ b/public/-/emojis/2/flag_je.png
Binary files differ
diff --git a/public/-/emojis/2/flag_jm.png b/public/-/emojis/2/flag_jm.png
new file mode 100644
index 00000000000..96cba7996cb
--- /dev/null
+++ b/public/-/emojis/2/flag_jm.png
Binary files differ
diff --git a/public/-/emojis/2/flag_jo.png b/public/-/emojis/2/flag_jo.png
new file mode 100644
index 00000000000..3d96d761668
--- /dev/null
+++ b/public/-/emojis/2/flag_jo.png
Binary files differ
diff --git a/public/-/emojis/2/flag_jp.png b/public/-/emojis/2/flag_jp.png
new file mode 100644
index 00000000000..e5c1c471846
--- /dev/null
+++ b/public/-/emojis/2/flag_jp.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ke.png b/public/-/emojis/2/flag_ke.png
new file mode 100644
index 00000000000..bf3ee8acde3
--- /dev/null
+++ b/public/-/emojis/2/flag_ke.png
Binary files differ
diff --git a/public/-/emojis/2/flag_kg.png b/public/-/emojis/2/flag_kg.png
new file mode 100644
index 00000000000..683c1837886
--- /dev/null
+++ b/public/-/emojis/2/flag_kg.png
Binary files differ
diff --git a/public/-/emojis/2/flag_kh.png b/public/-/emojis/2/flag_kh.png
new file mode 100644
index 00000000000..c5ebaee91d5
--- /dev/null
+++ b/public/-/emojis/2/flag_kh.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ki.png b/public/-/emojis/2/flag_ki.png
new file mode 100644
index 00000000000..1e99c52b4c0
--- /dev/null
+++ b/public/-/emojis/2/flag_ki.png
Binary files differ
diff --git a/public/-/emojis/2/flag_km.png b/public/-/emojis/2/flag_km.png
new file mode 100644
index 00000000000..c394f1c75f5
--- /dev/null
+++ b/public/-/emojis/2/flag_km.png
Binary files differ
diff --git a/public/-/emojis/2/flag_kn.png b/public/-/emojis/2/flag_kn.png
new file mode 100644
index 00000000000..c8a4e42d97b
--- /dev/null
+++ b/public/-/emojis/2/flag_kn.png
Binary files differ
diff --git a/public/-/emojis/2/flag_kp.png b/public/-/emojis/2/flag_kp.png
new file mode 100644
index 00000000000..aa0ac4f6473
--- /dev/null
+++ b/public/-/emojis/2/flag_kp.png
Binary files differ
diff --git a/public/-/emojis/2/flag_kr.png b/public/-/emojis/2/flag_kr.png
new file mode 100644
index 00000000000..356d312e961
--- /dev/null
+++ b/public/-/emojis/2/flag_kr.png
Binary files differ
diff --git a/public/-/emojis/2/flag_kw.png b/public/-/emojis/2/flag_kw.png
new file mode 100644
index 00000000000..fc30e8ea8cb
--- /dev/null
+++ b/public/-/emojis/2/flag_kw.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ky.png b/public/-/emojis/2/flag_ky.png
new file mode 100644
index 00000000000..ec4b2a48d93
--- /dev/null
+++ b/public/-/emojis/2/flag_ky.png
Binary files differ
diff --git a/public/-/emojis/2/flag_kz.png b/public/-/emojis/2/flag_kz.png
new file mode 100644
index 00000000000..7f3c5e4eb70
--- /dev/null
+++ b/public/-/emojis/2/flag_kz.png
Binary files differ
diff --git a/public/-/emojis/2/flag_la.png b/public/-/emojis/2/flag_la.png
new file mode 100644
index 00000000000..f61309db084
--- /dev/null
+++ b/public/-/emojis/2/flag_la.png
Binary files differ
diff --git a/public/-/emojis/2/flag_lb.png b/public/-/emojis/2/flag_lb.png
new file mode 100644
index 00000000000..83bbd534f1d
--- /dev/null
+++ b/public/-/emojis/2/flag_lb.png
Binary files differ
diff --git a/public/-/emojis/2/flag_lc.png b/public/-/emojis/2/flag_lc.png
new file mode 100644
index 00000000000..42b49d2059c
--- /dev/null
+++ b/public/-/emojis/2/flag_lc.png
Binary files differ
diff --git a/public/-/emojis/2/flag_li.png b/public/-/emojis/2/flag_li.png
new file mode 100644
index 00000000000..851a5e23c7c
--- /dev/null
+++ b/public/-/emojis/2/flag_li.png
Binary files differ
diff --git a/public/-/emojis/2/flag_lk.png b/public/-/emojis/2/flag_lk.png
new file mode 100644
index 00000000000..94148a42a6f
--- /dev/null
+++ b/public/-/emojis/2/flag_lk.png
Binary files differ
diff --git a/public/-/emojis/2/flag_lr.png b/public/-/emojis/2/flag_lr.png
new file mode 100644
index 00000000000..316e623afe0
--- /dev/null
+++ b/public/-/emojis/2/flag_lr.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ls.png b/public/-/emojis/2/flag_ls.png
new file mode 100644
index 00000000000..0935837ec98
--- /dev/null
+++ b/public/-/emojis/2/flag_ls.png
Binary files differ
diff --git a/public/-/emojis/2/flag_lt.png b/public/-/emojis/2/flag_lt.png
new file mode 100644
index 00000000000..2b4bc32fd91
--- /dev/null
+++ b/public/-/emojis/2/flag_lt.png
Binary files differ
diff --git a/public/-/emojis/2/flag_lu.png b/public/-/emojis/2/flag_lu.png
new file mode 100644
index 00000000000..ebdcc7741fd
--- /dev/null
+++ b/public/-/emojis/2/flag_lu.png
Binary files differ
diff --git a/public/-/emojis/2/flag_lv.png b/public/-/emojis/2/flag_lv.png
new file mode 100644
index 00000000000..1c9eca324cd
--- /dev/null
+++ b/public/-/emojis/2/flag_lv.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ly.png b/public/-/emojis/2/flag_ly.png
new file mode 100644
index 00000000000..7a592633b01
--- /dev/null
+++ b/public/-/emojis/2/flag_ly.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ma.png b/public/-/emojis/2/flag_ma.png
new file mode 100644
index 00000000000..e10789036e4
--- /dev/null
+++ b/public/-/emojis/2/flag_ma.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mc.png b/public/-/emojis/2/flag_mc.png
new file mode 100644
index 00000000000..4ce51af1b03
--- /dev/null
+++ b/public/-/emojis/2/flag_mc.png
Binary files differ
diff --git a/public/-/emojis/2/flag_md.png b/public/-/emojis/2/flag_md.png
new file mode 100644
index 00000000000..f2397e452ae
--- /dev/null
+++ b/public/-/emojis/2/flag_md.png
Binary files differ
diff --git a/public/-/emojis/2/flag_me.png b/public/-/emojis/2/flag_me.png
new file mode 100644
index 00000000000..90d099d845f
--- /dev/null
+++ b/public/-/emojis/2/flag_me.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mf.png b/public/-/emojis/2/flag_mf.png
new file mode 100644
index 00000000000..98039a24e6b
--- /dev/null
+++ b/public/-/emojis/2/flag_mf.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mg.png b/public/-/emojis/2/flag_mg.png
new file mode 100644
index 00000000000..e4735ae04bc
--- /dev/null
+++ b/public/-/emojis/2/flag_mg.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mh.png b/public/-/emojis/2/flag_mh.png
new file mode 100644
index 00000000000..9c092055bd9
--- /dev/null
+++ b/public/-/emojis/2/flag_mh.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mk.png b/public/-/emojis/2/flag_mk.png
new file mode 100644
index 00000000000..a19baac59dd
--- /dev/null
+++ b/public/-/emojis/2/flag_mk.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ml.png b/public/-/emojis/2/flag_ml.png
new file mode 100644
index 00000000000..5ffff4573f0
--- /dev/null
+++ b/public/-/emojis/2/flag_ml.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mm.png b/public/-/emojis/2/flag_mm.png
new file mode 100644
index 00000000000..31e81f3eb82
--- /dev/null
+++ b/public/-/emojis/2/flag_mm.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mn.png b/public/-/emojis/2/flag_mn.png
new file mode 100644
index 00000000000..52e6d949f8b
--- /dev/null
+++ b/public/-/emojis/2/flag_mn.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mo.png b/public/-/emojis/2/flag_mo.png
new file mode 100644
index 00000000000..a46519c4452
--- /dev/null
+++ b/public/-/emojis/2/flag_mo.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mp.png b/public/-/emojis/2/flag_mp.png
new file mode 100644
index 00000000000..726df4037b9
--- /dev/null
+++ b/public/-/emojis/2/flag_mp.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mq.png b/public/-/emojis/2/flag_mq.png
new file mode 100644
index 00000000000..f88d5d97735
--- /dev/null
+++ b/public/-/emojis/2/flag_mq.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mr.png b/public/-/emojis/2/flag_mr.png
new file mode 100644
index 00000000000..b2b01eb272d
--- /dev/null
+++ b/public/-/emojis/2/flag_mr.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ms.png b/public/-/emojis/2/flag_ms.png
new file mode 100644
index 00000000000..5f202c492c3
--- /dev/null
+++ b/public/-/emojis/2/flag_ms.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mt.png b/public/-/emojis/2/flag_mt.png
new file mode 100644
index 00000000000..33eae3cab25
--- /dev/null
+++ b/public/-/emojis/2/flag_mt.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mu.png b/public/-/emojis/2/flag_mu.png
new file mode 100644
index 00000000000..6404dbf9a34
--- /dev/null
+++ b/public/-/emojis/2/flag_mu.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mv.png b/public/-/emojis/2/flag_mv.png
new file mode 100644
index 00000000000..2027b0e826c
--- /dev/null
+++ b/public/-/emojis/2/flag_mv.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mw.png b/public/-/emojis/2/flag_mw.png
new file mode 100644
index 00000000000..2dec6561580
--- /dev/null
+++ b/public/-/emojis/2/flag_mw.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mx.png b/public/-/emojis/2/flag_mx.png
new file mode 100644
index 00000000000..f24df18d199
--- /dev/null
+++ b/public/-/emojis/2/flag_mx.png
Binary files differ
diff --git a/public/-/emojis/2/flag_my.png b/public/-/emojis/2/flag_my.png
new file mode 100644
index 00000000000..4de9b8de086
--- /dev/null
+++ b/public/-/emojis/2/flag_my.png
Binary files differ
diff --git a/public/-/emojis/2/flag_mz.png b/public/-/emojis/2/flag_mz.png
new file mode 100644
index 00000000000..b7d7ca87a8e
--- /dev/null
+++ b/public/-/emojis/2/flag_mz.png
Binary files differ
diff --git a/public/-/emojis/2/flag_na.png b/public/-/emojis/2/flag_na.png
new file mode 100644
index 00000000000..04316824cc9
--- /dev/null
+++ b/public/-/emojis/2/flag_na.png
Binary files differ
diff --git a/public/-/emojis/2/flag_nc.png b/public/-/emojis/2/flag_nc.png
new file mode 100644
index 00000000000..52ee45e79d9
--- /dev/null
+++ b/public/-/emojis/2/flag_nc.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ne.png b/public/-/emojis/2/flag_ne.png
new file mode 100644
index 00000000000..f0a0c09a522
--- /dev/null
+++ b/public/-/emojis/2/flag_ne.png
Binary files differ
diff --git a/public/-/emojis/2/flag_nf.png b/public/-/emojis/2/flag_nf.png
new file mode 100644
index 00000000000..5819a858430
--- /dev/null
+++ b/public/-/emojis/2/flag_nf.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ng.png b/public/-/emojis/2/flag_ng.png
new file mode 100644
index 00000000000..944486f9691
--- /dev/null
+++ b/public/-/emojis/2/flag_ng.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ni.png b/public/-/emojis/2/flag_ni.png
new file mode 100644
index 00000000000..5ccdc5a94b1
--- /dev/null
+++ b/public/-/emojis/2/flag_ni.png
Binary files differ
diff --git a/public/-/emojis/2/flag_nl.png b/public/-/emojis/2/flag_nl.png
new file mode 100644
index 00000000000..3ea08f39858
--- /dev/null
+++ b/public/-/emojis/2/flag_nl.png
Binary files differ
diff --git a/public/-/emojis/2/flag_no.png b/public/-/emojis/2/flag_no.png
new file mode 100644
index 00000000000..d94e9a72179
--- /dev/null
+++ b/public/-/emojis/2/flag_no.png
Binary files differ
diff --git a/public/-/emojis/2/flag_np.png b/public/-/emojis/2/flag_np.png
new file mode 100644
index 00000000000..8105052636b
--- /dev/null
+++ b/public/-/emojis/2/flag_np.png
Binary files differ
diff --git a/public/-/emojis/2/flag_nr.png b/public/-/emojis/2/flag_nr.png
new file mode 100644
index 00000000000..15295d0df43
--- /dev/null
+++ b/public/-/emojis/2/flag_nr.png
Binary files differ
diff --git a/public/-/emojis/2/flag_nu.png b/public/-/emojis/2/flag_nu.png
new file mode 100644
index 00000000000..6b5afc0bca6
--- /dev/null
+++ b/public/-/emojis/2/flag_nu.png
Binary files differ
diff --git a/public/-/emojis/2/flag_nz.png b/public/-/emojis/2/flag_nz.png
new file mode 100644
index 00000000000..ea6f2368d20
--- /dev/null
+++ b/public/-/emojis/2/flag_nz.png
Binary files differ
diff --git a/public/-/emojis/2/flag_om.png b/public/-/emojis/2/flag_om.png
new file mode 100644
index 00000000000..57c88d19d01
--- /dev/null
+++ b/public/-/emojis/2/flag_om.png
Binary files differ
diff --git a/public/-/emojis/2/flag_pa.png b/public/-/emojis/2/flag_pa.png
new file mode 100644
index 00000000000..d9d880b5b87
--- /dev/null
+++ b/public/-/emojis/2/flag_pa.png
Binary files differ
diff --git a/public/-/emojis/2/flag_pe.png b/public/-/emojis/2/flag_pe.png
new file mode 100644
index 00000000000..7d41ec53fd3
--- /dev/null
+++ b/public/-/emojis/2/flag_pe.png
Binary files differ
diff --git a/public/-/emojis/2/flag_pf.png b/public/-/emojis/2/flag_pf.png
new file mode 100644
index 00000000000..2a14a5e1e4f
--- /dev/null
+++ b/public/-/emojis/2/flag_pf.png
Binary files differ
diff --git a/public/-/emojis/2/flag_pg.png b/public/-/emojis/2/flag_pg.png
new file mode 100644
index 00000000000..95acf5da44f
--- /dev/null
+++ b/public/-/emojis/2/flag_pg.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ph.png b/public/-/emojis/2/flag_ph.png
new file mode 100644
index 00000000000..e84f6d51761
--- /dev/null
+++ b/public/-/emojis/2/flag_ph.png
Binary files differ
diff --git a/public/-/emojis/2/flag_pk.png b/public/-/emojis/2/flag_pk.png
new file mode 100644
index 00000000000..d4ad31d7270
--- /dev/null
+++ b/public/-/emojis/2/flag_pk.png
Binary files differ
diff --git a/public/-/emojis/2/flag_pl.png b/public/-/emojis/2/flag_pl.png
new file mode 100644
index 00000000000..0f1839943b4
--- /dev/null
+++ b/public/-/emojis/2/flag_pl.png
Binary files differ
diff --git a/public/-/emojis/2/flag_pm.png b/public/-/emojis/2/flag_pm.png
new file mode 100644
index 00000000000..6034f084a6d
--- /dev/null
+++ b/public/-/emojis/2/flag_pm.png
Binary files differ
diff --git a/public/-/emojis/2/flag_pn.png b/public/-/emojis/2/flag_pn.png
new file mode 100644
index 00000000000..b7098d1c8fe
--- /dev/null
+++ b/public/-/emojis/2/flag_pn.png
Binary files differ
diff --git a/public/-/emojis/2/flag_pr.png b/public/-/emojis/2/flag_pr.png
new file mode 100644
index 00000000000..2fc5e5dc3cf
--- /dev/null
+++ b/public/-/emojis/2/flag_pr.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ps.png b/public/-/emojis/2/flag_ps.png
new file mode 100644
index 00000000000..f85277da227
--- /dev/null
+++ b/public/-/emojis/2/flag_ps.png
Binary files differ
diff --git a/public/-/emojis/2/flag_pt.png b/public/-/emojis/2/flag_pt.png
new file mode 100644
index 00000000000..db518e255d1
--- /dev/null
+++ b/public/-/emojis/2/flag_pt.png
Binary files differ
diff --git a/public/-/emojis/2/flag_pw.png b/public/-/emojis/2/flag_pw.png
new file mode 100644
index 00000000000..dc72d2877a1
--- /dev/null
+++ b/public/-/emojis/2/flag_pw.png
Binary files differ
diff --git a/public/-/emojis/2/flag_py.png b/public/-/emojis/2/flag_py.png
new file mode 100644
index 00000000000..32d09073d15
--- /dev/null
+++ b/public/-/emojis/2/flag_py.png
Binary files differ
diff --git a/public/-/emojis/2/flag_qa.png b/public/-/emojis/2/flag_qa.png
new file mode 100644
index 00000000000..02bebd76678
--- /dev/null
+++ b/public/-/emojis/2/flag_qa.png
Binary files differ
diff --git a/public/-/emojis/2/flag_re.png b/public/-/emojis/2/flag_re.png
new file mode 100644
index 00000000000..76ab2085f47
--- /dev/null
+++ b/public/-/emojis/2/flag_re.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ro.png b/public/-/emojis/2/flag_ro.png
new file mode 100644
index 00000000000..ed9cdd874be
--- /dev/null
+++ b/public/-/emojis/2/flag_ro.png
Binary files differ
diff --git a/public/-/emojis/2/flag_rs.png b/public/-/emojis/2/flag_rs.png
new file mode 100644
index 00000000000..767a22acb64
--- /dev/null
+++ b/public/-/emojis/2/flag_rs.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ru.png b/public/-/emojis/2/flag_ru.png
new file mode 100644
index 00000000000..4ef7edfa177
--- /dev/null
+++ b/public/-/emojis/2/flag_ru.png
Binary files differ
diff --git a/public/-/emojis/2/flag_rw.png b/public/-/emojis/2/flag_rw.png
new file mode 100644
index 00000000000..15c38302d80
--- /dev/null
+++ b/public/-/emojis/2/flag_rw.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sa.png b/public/-/emojis/2/flag_sa.png
new file mode 100644
index 00000000000..f9845634a24
--- /dev/null
+++ b/public/-/emojis/2/flag_sa.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sb.png b/public/-/emojis/2/flag_sb.png
new file mode 100644
index 00000000000..dda0b3cae0c
--- /dev/null
+++ b/public/-/emojis/2/flag_sb.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sc.png b/public/-/emojis/2/flag_sc.png
new file mode 100644
index 00000000000..097f3f8f851
--- /dev/null
+++ b/public/-/emojis/2/flag_sc.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sd.png b/public/-/emojis/2/flag_sd.png
new file mode 100644
index 00000000000..70a3a95a8ee
--- /dev/null
+++ b/public/-/emojis/2/flag_sd.png
Binary files differ
diff --git a/public/-/emojis/2/flag_se.png b/public/-/emojis/2/flag_se.png
new file mode 100644
index 00000000000..4904b2cba39
--- /dev/null
+++ b/public/-/emojis/2/flag_se.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sg.png b/public/-/emojis/2/flag_sg.png
new file mode 100644
index 00000000000..f4f9416c467
--- /dev/null
+++ b/public/-/emojis/2/flag_sg.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sh.png b/public/-/emojis/2/flag_sh.png
new file mode 100644
index 00000000000..a0122711407
--- /dev/null
+++ b/public/-/emojis/2/flag_sh.png
Binary files differ
diff --git a/public/-/emojis/2/flag_si.png b/public/-/emojis/2/flag_si.png
new file mode 100644
index 00000000000..36736281a49
--- /dev/null
+++ b/public/-/emojis/2/flag_si.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sj.png b/public/-/emojis/2/flag_sj.png
new file mode 100644
index 00000000000..d94e9a72179
--- /dev/null
+++ b/public/-/emojis/2/flag_sj.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sk.png b/public/-/emojis/2/flag_sk.png
new file mode 100644
index 00000000000..46e027dea8b
--- /dev/null
+++ b/public/-/emojis/2/flag_sk.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sl.png b/public/-/emojis/2/flag_sl.png
new file mode 100644
index 00000000000..3f2e4f191b0
--- /dev/null
+++ b/public/-/emojis/2/flag_sl.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sm.png b/public/-/emojis/2/flag_sm.png
new file mode 100644
index 00000000000..261b25e45f4
--- /dev/null
+++ b/public/-/emojis/2/flag_sm.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sn.png b/public/-/emojis/2/flag_sn.png
new file mode 100644
index 00000000000..97e2fbe745b
--- /dev/null
+++ b/public/-/emojis/2/flag_sn.png
Binary files differ
diff --git a/public/-/emojis/2/flag_so.png b/public/-/emojis/2/flag_so.png
new file mode 100644
index 00000000000..aaecb5fb5a0
--- /dev/null
+++ b/public/-/emojis/2/flag_so.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sr.png b/public/-/emojis/2/flag_sr.png
new file mode 100644
index 00000000000..b2c03cf5b3c
--- /dev/null
+++ b/public/-/emojis/2/flag_sr.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ss.png b/public/-/emojis/2/flag_ss.png
new file mode 100644
index 00000000000..65b217b70e3
--- /dev/null
+++ b/public/-/emojis/2/flag_ss.png
Binary files differ
diff --git a/public/-/emojis/2/flag_st.png b/public/-/emojis/2/flag_st.png
new file mode 100644
index 00000000000..9cb7c0287b7
--- /dev/null
+++ b/public/-/emojis/2/flag_st.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sv.png b/public/-/emojis/2/flag_sv.png
new file mode 100644
index 00000000000..006ac33d5a5
--- /dev/null
+++ b/public/-/emojis/2/flag_sv.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sx.png b/public/-/emojis/2/flag_sx.png
new file mode 100644
index 00000000000..52228e067ba
--- /dev/null
+++ b/public/-/emojis/2/flag_sx.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sy.png b/public/-/emojis/2/flag_sy.png
new file mode 100644
index 00000000000..314495da4b3
--- /dev/null
+++ b/public/-/emojis/2/flag_sy.png
Binary files differ
diff --git a/public/-/emojis/2/flag_sz.png b/public/-/emojis/2/flag_sz.png
new file mode 100644
index 00000000000..ef94dd551d0
--- /dev/null
+++ b/public/-/emojis/2/flag_sz.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ta.png b/public/-/emojis/2/flag_ta.png
new file mode 100644
index 00000000000..e1bbc026b65
--- /dev/null
+++ b/public/-/emojis/2/flag_ta.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tc.png b/public/-/emojis/2/flag_tc.png
new file mode 100644
index 00000000000..c244969df1f
--- /dev/null
+++ b/public/-/emojis/2/flag_tc.png
Binary files differ
diff --git a/public/-/emojis/2/flag_td.png b/public/-/emojis/2/flag_td.png
new file mode 100644
index 00000000000..ad7c61a2b4e
--- /dev/null
+++ b/public/-/emojis/2/flag_td.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tf.png b/public/-/emojis/2/flag_tf.png
new file mode 100644
index 00000000000..720ce002eb8
--- /dev/null
+++ b/public/-/emojis/2/flag_tf.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tg.png b/public/-/emojis/2/flag_tg.png
new file mode 100644
index 00000000000..42e20707c30
--- /dev/null
+++ b/public/-/emojis/2/flag_tg.png
Binary files differ
diff --git a/public/-/emojis/2/flag_th.png b/public/-/emojis/2/flag_th.png
new file mode 100644
index 00000000000..6022f2645f1
--- /dev/null
+++ b/public/-/emojis/2/flag_th.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tj.png b/public/-/emojis/2/flag_tj.png
new file mode 100644
index 00000000000..78a207210eb
--- /dev/null
+++ b/public/-/emojis/2/flag_tj.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tk.png b/public/-/emojis/2/flag_tk.png
new file mode 100644
index 00000000000..84bc1155fd3
--- /dev/null
+++ b/public/-/emojis/2/flag_tk.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tl.png b/public/-/emojis/2/flag_tl.png
new file mode 100644
index 00000000000..c6a53e5b5e7
--- /dev/null
+++ b/public/-/emojis/2/flag_tl.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tm.png b/public/-/emojis/2/flag_tm.png
new file mode 100644
index 00000000000..207ec41373a
--- /dev/null
+++ b/public/-/emojis/2/flag_tm.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tn.png b/public/-/emojis/2/flag_tn.png
new file mode 100644
index 00000000000..c196de6565c
--- /dev/null
+++ b/public/-/emojis/2/flag_tn.png
Binary files differ
diff --git a/public/-/emojis/2/flag_to.png b/public/-/emojis/2/flag_to.png
new file mode 100644
index 00000000000..1e334470bf6
--- /dev/null
+++ b/public/-/emojis/2/flag_to.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tr.png b/public/-/emojis/2/flag_tr.png
new file mode 100644
index 00000000000..c32816cc587
--- /dev/null
+++ b/public/-/emojis/2/flag_tr.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tt.png b/public/-/emojis/2/flag_tt.png
new file mode 100644
index 00000000000..7dc4f5b6654
--- /dev/null
+++ b/public/-/emojis/2/flag_tt.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tv.png b/public/-/emojis/2/flag_tv.png
new file mode 100644
index 00000000000..1b1fcbf4f46
--- /dev/null
+++ b/public/-/emojis/2/flag_tv.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tw.png b/public/-/emojis/2/flag_tw.png
new file mode 100644
index 00000000000..81f18e8aede
--- /dev/null
+++ b/public/-/emojis/2/flag_tw.png
Binary files differ
diff --git a/public/-/emojis/2/flag_tz.png b/public/-/emojis/2/flag_tz.png
new file mode 100644
index 00000000000..15953ebb6f5
--- /dev/null
+++ b/public/-/emojis/2/flag_tz.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ua.png b/public/-/emojis/2/flag_ua.png
new file mode 100644
index 00000000000..23deec9379c
--- /dev/null
+++ b/public/-/emojis/2/flag_ua.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ug.png b/public/-/emojis/2/flag_ug.png
new file mode 100644
index 00000000000..ee0ab96e776
--- /dev/null
+++ b/public/-/emojis/2/flag_ug.png
Binary files differ
diff --git a/public/-/emojis/2/flag_um.png b/public/-/emojis/2/flag_um.png
new file mode 100644
index 00000000000..ca311bd16fd
--- /dev/null
+++ b/public/-/emojis/2/flag_um.png
Binary files differ
diff --git a/public/-/emojis/2/flag_us.png b/public/-/emojis/2/flag_us.png
new file mode 100644
index 00000000000..ca311bd16fd
--- /dev/null
+++ b/public/-/emojis/2/flag_us.png
Binary files differ
diff --git a/public/-/emojis/2/flag_uy.png b/public/-/emojis/2/flag_uy.png
new file mode 100644
index 00000000000..f9c064087b5
--- /dev/null
+++ b/public/-/emojis/2/flag_uy.png
Binary files differ
diff --git a/public/-/emojis/2/flag_uz.png b/public/-/emojis/2/flag_uz.png
new file mode 100644
index 00000000000..aac61d58c4f
--- /dev/null
+++ b/public/-/emojis/2/flag_uz.png
Binary files differ
diff --git a/public/-/emojis/2/flag_va.png b/public/-/emojis/2/flag_va.png
new file mode 100644
index 00000000000..acfd70c51fa
--- /dev/null
+++ b/public/-/emojis/2/flag_va.png
Binary files differ
diff --git a/public/-/emojis/2/flag_vc.png b/public/-/emojis/2/flag_vc.png
new file mode 100644
index 00000000000..8863ec1ba37
--- /dev/null
+++ b/public/-/emojis/2/flag_vc.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ve.png b/public/-/emojis/2/flag_ve.png
new file mode 100644
index 00000000000..602657e337a
--- /dev/null
+++ b/public/-/emojis/2/flag_ve.png
Binary files differ
diff --git a/public/-/emojis/2/flag_vg.png b/public/-/emojis/2/flag_vg.png
new file mode 100644
index 00000000000..3fa10bf2fad
--- /dev/null
+++ b/public/-/emojis/2/flag_vg.png
Binary files differ
diff --git a/public/-/emojis/2/flag_vi.png b/public/-/emojis/2/flag_vi.png
new file mode 100644
index 00000000000..fcf5cbec7d8
--- /dev/null
+++ b/public/-/emojis/2/flag_vi.png
Binary files differ
diff --git a/public/-/emojis/2/flag_vn.png b/public/-/emojis/2/flag_vn.png
new file mode 100644
index 00000000000..9e603f6b167
--- /dev/null
+++ b/public/-/emojis/2/flag_vn.png
Binary files differ
diff --git a/public/-/emojis/2/flag_vu.png b/public/-/emojis/2/flag_vu.png
new file mode 100644
index 00000000000..0d066d309e8
--- /dev/null
+++ b/public/-/emojis/2/flag_vu.png
Binary files differ
diff --git a/public/-/emojis/2/flag_wf.png b/public/-/emojis/2/flag_wf.png
new file mode 100644
index 00000000000..5fa64fa8d0d
--- /dev/null
+++ b/public/-/emojis/2/flag_wf.png
Binary files differ
diff --git a/public/-/emojis/2/flag_white.png b/public/-/emojis/2/flag_white.png
new file mode 100644
index 00000000000..d61c3e954dd
--- /dev/null
+++ b/public/-/emojis/2/flag_white.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ws.png b/public/-/emojis/2/flag_ws.png
new file mode 100644
index 00000000000..243d1cc2e64
--- /dev/null
+++ b/public/-/emojis/2/flag_ws.png
Binary files differ
diff --git a/public/-/emojis/2/flag_xk.png b/public/-/emojis/2/flag_xk.png
new file mode 100644
index 00000000000..387fe660587
--- /dev/null
+++ b/public/-/emojis/2/flag_xk.png
Binary files differ
diff --git a/public/-/emojis/2/flag_ye.png b/public/-/emojis/2/flag_ye.png
new file mode 100644
index 00000000000..7506fb2de99
--- /dev/null
+++ b/public/-/emojis/2/flag_ye.png
Binary files differ
diff --git a/public/-/emojis/2/flag_yt.png b/public/-/emojis/2/flag_yt.png
new file mode 100644
index 00000000000..00adfaacda6
--- /dev/null
+++ b/public/-/emojis/2/flag_yt.png
Binary files differ
diff --git a/public/-/emojis/2/flag_za.png b/public/-/emojis/2/flag_za.png
new file mode 100644
index 00000000000..96236a0d34b
--- /dev/null
+++ b/public/-/emojis/2/flag_za.png
Binary files differ
diff --git a/public/-/emojis/2/flag_zm.png b/public/-/emojis/2/flag_zm.png
new file mode 100644
index 00000000000..71807f86941
--- /dev/null
+++ b/public/-/emojis/2/flag_zm.png
Binary files differ
diff --git a/public/-/emojis/2/flag_zw.png b/public/-/emojis/2/flag_zw.png
new file mode 100644
index 00000000000..cf2c5b5a930
--- /dev/null
+++ b/public/-/emojis/2/flag_zw.png
Binary files differ
diff --git a/public/-/emojis/2/flags.png b/public/-/emojis/2/flags.png
new file mode 100644
index 00000000000..b2d6ab4b89c
--- /dev/null
+++ b/public/-/emojis/2/flags.png
Binary files differ
diff --git a/public/-/emojis/2/flashlight.png b/public/-/emojis/2/flashlight.png
new file mode 100644
index 00000000000..bb6933f0095
--- /dev/null
+++ b/public/-/emojis/2/flashlight.png
Binary files differ
diff --git a/public/-/emojis/2/fleur-de-lis.png b/public/-/emojis/2/fleur-de-lis.png
new file mode 100644
index 00000000000..44130044b8a
--- /dev/null
+++ b/public/-/emojis/2/fleur-de-lis.png
Binary files differ
diff --git a/public/-/emojis/2/floppy_disk.png b/public/-/emojis/2/floppy_disk.png
new file mode 100644
index 00000000000..c94373d19f5
--- /dev/null
+++ b/public/-/emojis/2/floppy_disk.png
Binary files differ
diff --git a/public/-/emojis/2/flower_playing_cards.png b/public/-/emojis/2/flower_playing_cards.png
new file mode 100644
index 00000000000..988dd11cb22
--- /dev/null
+++ b/public/-/emojis/2/flower_playing_cards.png
Binary files differ
diff --git a/public/-/emojis/2/flushed.png b/public/-/emojis/2/flushed.png
new file mode 100644
index 00000000000..d0e141206d3
--- /dev/null
+++ b/public/-/emojis/2/flushed.png
Binary files differ
diff --git a/public/-/emojis/2/fog.png b/public/-/emojis/2/fog.png
new file mode 100644
index 00000000000..81d7c57aa16
--- /dev/null
+++ b/public/-/emojis/2/fog.png
Binary files differ
diff --git a/public/-/emojis/2/foggy.png b/public/-/emojis/2/foggy.png
new file mode 100644
index 00000000000..d616d716e6b
--- /dev/null
+++ b/public/-/emojis/2/foggy.png
Binary files differ
diff --git a/public/-/emojis/2/football.png b/public/-/emojis/2/football.png
new file mode 100644
index 00000000000..75bf17b1328
--- /dev/null
+++ b/public/-/emojis/2/football.png
Binary files differ
diff --git a/public/-/emojis/2/footprints.png b/public/-/emojis/2/footprints.png
new file mode 100644
index 00000000000..378c0aaa56d
--- /dev/null
+++ b/public/-/emojis/2/footprints.png
Binary files differ
diff --git a/public/-/emojis/2/fork_and_knife.png b/public/-/emojis/2/fork_and_knife.png
new file mode 100644
index 00000000000..d526471d29a
--- /dev/null
+++ b/public/-/emojis/2/fork_and_knife.png
Binary files differ
diff --git a/public/-/emojis/2/fork_knife_plate.png b/public/-/emojis/2/fork_knife_plate.png
new file mode 100644
index 00000000000..5ad662327b1
--- /dev/null
+++ b/public/-/emojis/2/fork_knife_plate.png
Binary files differ
diff --git a/public/-/emojis/2/fountain.png b/public/-/emojis/2/fountain.png
new file mode 100644
index 00000000000..96c1352516f
--- /dev/null
+++ b/public/-/emojis/2/fountain.png
Binary files differ
diff --git a/public/-/emojis/2/four.png b/public/-/emojis/2/four.png
new file mode 100644
index 00000000000..075389303ec
--- /dev/null
+++ b/public/-/emojis/2/four.png
Binary files differ
diff --git a/public/-/emojis/2/four_leaf_clover.png b/public/-/emojis/2/four_leaf_clover.png
new file mode 100644
index 00000000000..7c37aba7146
--- /dev/null
+++ b/public/-/emojis/2/four_leaf_clover.png
Binary files differ
diff --git a/public/-/emojis/2/fox.png b/public/-/emojis/2/fox.png
new file mode 100644
index 00000000000..9ae868c7d70
--- /dev/null
+++ b/public/-/emojis/2/fox.png
Binary files differ
diff --git a/public/-/emojis/2/frame_photo.png b/public/-/emojis/2/frame_photo.png
new file mode 100644
index 00000000000..87da6c848f3
--- /dev/null
+++ b/public/-/emojis/2/frame_photo.png
Binary files differ
diff --git a/public/-/emojis/2/free.png b/public/-/emojis/2/free.png
new file mode 100644
index 00000000000..c3f8ecb2188
--- /dev/null
+++ b/public/-/emojis/2/free.png
Binary files differ
diff --git a/public/-/emojis/2/french_bread.png b/public/-/emojis/2/french_bread.png
new file mode 100644
index 00000000000..1c71c123d5f
--- /dev/null
+++ b/public/-/emojis/2/french_bread.png
Binary files differ
diff --git a/public/-/emojis/2/fried_shrimp.png b/public/-/emojis/2/fried_shrimp.png
new file mode 100644
index 00000000000..56c72d63710
--- /dev/null
+++ b/public/-/emojis/2/fried_shrimp.png
Binary files differ
diff --git a/public/-/emojis/2/fries.png b/public/-/emojis/2/fries.png
new file mode 100644
index 00000000000..c48b1734dff
--- /dev/null
+++ b/public/-/emojis/2/fries.png
Binary files differ
diff --git a/public/-/emojis/2/frog.png b/public/-/emojis/2/frog.png
new file mode 100644
index 00000000000..5a2f4c668bf
--- /dev/null
+++ b/public/-/emojis/2/frog.png
Binary files differ
diff --git a/public/-/emojis/2/frowning.png b/public/-/emojis/2/frowning.png
new file mode 100644
index 00000000000..58e0c67a2bb
--- /dev/null
+++ b/public/-/emojis/2/frowning.png
Binary files differ
diff --git a/public/-/emojis/2/frowning2.png b/public/-/emojis/2/frowning2.png
new file mode 100644
index 00000000000..a30f4f36066
--- /dev/null
+++ b/public/-/emojis/2/frowning2.png
Binary files differ
diff --git a/public/-/emojis/2/fuelpump.png b/public/-/emojis/2/fuelpump.png
new file mode 100644
index 00000000000..941d5ec7433
--- /dev/null
+++ b/public/-/emojis/2/fuelpump.png
Binary files differ
diff --git a/public/-/emojis/2/full_moon.png b/public/-/emojis/2/full_moon.png
new file mode 100644
index 00000000000..8c73fc2ecf6
--- /dev/null
+++ b/public/-/emojis/2/full_moon.png
Binary files differ
diff --git a/public/-/emojis/2/full_moon_with_face.png b/public/-/emojis/2/full_moon_with_face.png
new file mode 100644
index 00000000000..a9aedae2395
--- /dev/null
+++ b/public/-/emojis/2/full_moon_with_face.png
Binary files differ
diff --git a/public/-/emojis/2/game_die.png b/public/-/emojis/2/game_die.png
new file mode 100644
index 00000000000..d3754f16ead
--- /dev/null
+++ b/public/-/emojis/2/game_die.png
Binary files differ
diff --git a/public/-/emojis/2/gay_pride_flag.png b/public/-/emojis/2/gay_pride_flag.png
new file mode 100644
index 00000000000..9a6d2add84d
--- /dev/null
+++ b/public/-/emojis/2/gay_pride_flag.png
Binary files differ
diff --git a/public/-/emojis/2/gear.png b/public/-/emojis/2/gear.png
new file mode 100644
index 00000000000..d75eb3bcb25
--- /dev/null
+++ b/public/-/emojis/2/gear.png
Binary files differ
diff --git a/public/-/emojis/2/gem.png b/public/-/emojis/2/gem.png
new file mode 100644
index 00000000000..bd5ddcc0cf2
--- /dev/null
+++ b/public/-/emojis/2/gem.png
Binary files differ
diff --git a/public/-/emojis/2/gemini.png b/public/-/emojis/2/gemini.png
new file mode 100644
index 00000000000..e06658b1aa3
--- /dev/null
+++ b/public/-/emojis/2/gemini.png
Binary files differ
diff --git a/public/-/emojis/2/ghost.png b/public/-/emojis/2/ghost.png
new file mode 100644
index 00000000000..a32f5c9c076
--- /dev/null
+++ b/public/-/emojis/2/ghost.png
Binary files differ
diff --git a/public/-/emojis/2/gift.png b/public/-/emojis/2/gift.png
new file mode 100644
index 00000000000..92d11ff1be9
--- /dev/null
+++ b/public/-/emojis/2/gift.png
Binary files differ
diff --git a/public/-/emojis/2/gift_heart.png b/public/-/emojis/2/gift_heart.png
new file mode 100644
index 00000000000..317073b749b
--- /dev/null
+++ b/public/-/emojis/2/gift_heart.png
Binary files differ
diff --git a/public/-/emojis/2/girl.png b/public/-/emojis/2/girl.png
new file mode 100644
index 00000000000..8a66d436ddb
--- /dev/null
+++ b/public/-/emojis/2/girl.png
Binary files differ
diff --git a/public/-/emojis/2/girl_tone1.png b/public/-/emojis/2/girl_tone1.png
new file mode 100644
index 00000000000..1a260068a96
--- /dev/null
+++ b/public/-/emojis/2/girl_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/girl_tone2.png b/public/-/emojis/2/girl_tone2.png
new file mode 100644
index 00000000000..43b91b8551c
--- /dev/null
+++ b/public/-/emojis/2/girl_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/girl_tone3.png b/public/-/emojis/2/girl_tone3.png
new file mode 100644
index 00000000000..bff227055c7
--- /dev/null
+++ b/public/-/emojis/2/girl_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/girl_tone4.png b/public/-/emojis/2/girl_tone4.png
new file mode 100644
index 00000000000..6b258a8edc9
--- /dev/null
+++ b/public/-/emojis/2/girl_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/girl_tone5.png b/public/-/emojis/2/girl_tone5.png
new file mode 100644
index 00000000000..efdec2df0f9
--- /dev/null
+++ b/public/-/emojis/2/girl_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/globe_with_meridians.png b/public/-/emojis/2/globe_with_meridians.png
new file mode 100644
index 00000000000..beca893eda6
--- /dev/null
+++ b/public/-/emojis/2/globe_with_meridians.png
Binary files differ
diff --git a/public/-/emojis/2/goal.png b/public/-/emojis/2/goal.png
new file mode 100644
index 00000000000..3b5b2c65250
--- /dev/null
+++ b/public/-/emojis/2/goal.png
Binary files differ
diff --git a/public/-/emojis/2/goat.png b/public/-/emojis/2/goat.png
new file mode 100644
index 00000000000..d88463d768d
--- /dev/null
+++ b/public/-/emojis/2/goat.png
Binary files differ
diff --git a/public/-/emojis/2/golf.png b/public/-/emojis/2/golf.png
new file mode 100644
index 00000000000..16910ca79fe
--- /dev/null
+++ b/public/-/emojis/2/golf.png
Binary files differ
diff --git a/public/-/emojis/2/golfer.png b/public/-/emojis/2/golfer.png
new file mode 100644
index 00000000000..554558e68e3
--- /dev/null
+++ b/public/-/emojis/2/golfer.png
Binary files differ
diff --git a/public/-/emojis/2/gorilla.png b/public/-/emojis/2/gorilla.png
new file mode 100644
index 00000000000..08c10f889a7
--- /dev/null
+++ b/public/-/emojis/2/gorilla.png
Binary files differ
diff --git a/public/-/emojis/2/grapes.png b/public/-/emojis/2/grapes.png
new file mode 100644
index 00000000000..dc1c8a42eca
--- /dev/null
+++ b/public/-/emojis/2/grapes.png
Binary files differ
diff --git a/public/-/emojis/2/green_apple.png b/public/-/emojis/2/green_apple.png
new file mode 100644
index 00000000000..df297a575f0
--- /dev/null
+++ b/public/-/emojis/2/green_apple.png
Binary files differ
diff --git a/public/-/emojis/2/green_book.png b/public/-/emojis/2/green_book.png
new file mode 100644
index 00000000000..da6ab19b789
--- /dev/null
+++ b/public/-/emojis/2/green_book.png
Binary files differ
diff --git a/public/-/emojis/2/green_heart.png b/public/-/emojis/2/green_heart.png
new file mode 100644
index 00000000000..3e9dde55a42
--- /dev/null
+++ b/public/-/emojis/2/green_heart.png
Binary files differ
diff --git a/public/-/emojis/2/grey_exclamation.png b/public/-/emojis/2/grey_exclamation.png
new file mode 100644
index 00000000000..b7cd2b00626
--- /dev/null
+++ b/public/-/emojis/2/grey_exclamation.png
Binary files differ
diff --git a/public/-/emojis/2/grey_question.png b/public/-/emojis/2/grey_question.png
new file mode 100644
index 00000000000..e43e9ef5b4b
--- /dev/null
+++ b/public/-/emojis/2/grey_question.png
Binary files differ
diff --git a/public/-/emojis/2/grimacing.png b/public/-/emojis/2/grimacing.png
new file mode 100644
index 00000000000..ab12d7edd9d
--- /dev/null
+++ b/public/-/emojis/2/grimacing.png
Binary files differ
diff --git a/public/-/emojis/2/grin.png b/public/-/emojis/2/grin.png
new file mode 100644
index 00000000000..fc82c6bd4ae
--- /dev/null
+++ b/public/-/emojis/2/grin.png
Binary files differ
diff --git a/public/-/emojis/2/grinning.png b/public/-/emojis/2/grinning.png
new file mode 100644
index 00000000000..d9d24fc834f
--- /dev/null
+++ b/public/-/emojis/2/grinning.png
Binary files differ
diff --git a/public/-/emojis/2/guardsman.png b/public/-/emojis/2/guardsman.png
new file mode 100644
index 00000000000..cb6ef760163
--- /dev/null
+++ b/public/-/emojis/2/guardsman.png
Binary files differ
diff --git a/public/-/emojis/2/guardsman_tone1.png b/public/-/emojis/2/guardsman_tone1.png
new file mode 100644
index 00000000000..485242cdf8a
--- /dev/null
+++ b/public/-/emojis/2/guardsman_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/guardsman_tone2.png b/public/-/emojis/2/guardsman_tone2.png
new file mode 100644
index 00000000000..cbba6179e67
--- /dev/null
+++ b/public/-/emojis/2/guardsman_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/guardsman_tone3.png b/public/-/emojis/2/guardsman_tone3.png
new file mode 100644
index 00000000000..94698df5ebd
--- /dev/null
+++ b/public/-/emojis/2/guardsman_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/guardsman_tone4.png b/public/-/emojis/2/guardsman_tone4.png
new file mode 100644
index 00000000000..df3593b97b7
--- /dev/null
+++ b/public/-/emojis/2/guardsman_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/guardsman_tone5.png b/public/-/emojis/2/guardsman_tone5.png
new file mode 100644
index 00000000000..fe449dd7326
--- /dev/null
+++ b/public/-/emojis/2/guardsman_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/guitar.png b/public/-/emojis/2/guitar.png
new file mode 100644
index 00000000000..afccf1c4170
--- /dev/null
+++ b/public/-/emojis/2/guitar.png
Binary files differ
diff --git a/public/-/emojis/2/gun.png b/public/-/emojis/2/gun.png
new file mode 100644
index 00000000000..fa713cca903
--- /dev/null
+++ b/public/-/emojis/2/gun.png
Binary files differ
diff --git a/public/-/emojis/2/haircut.png b/public/-/emojis/2/haircut.png
new file mode 100644
index 00000000000..6bc3eb96c84
--- /dev/null
+++ b/public/-/emojis/2/haircut.png
Binary files differ
diff --git a/public/-/emojis/2/haircut_tone1.png b/public/-/emojis/2/haircut_tone1.png
new file mode 100644
index 00000000000..b862983e467
--- /dev/null
+++ b/public/-/emojis/2/haircut_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/haircut_tone2.png b/public/-/emojis/2/haircut_tone2.png
new file mode 100644
index 00000000000..5f0588d23dd
--- /dev/null
+++ b/public/-/emojis/2/haircut_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/haircut_tone3.png b/public/-/emojis/2/haircut_tone3.png
new file mode 100644
index 00000000000..a820a84770f
--- /dev/null
+++ b/public/-/emojis/2/haircut_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/haircut_tone4.png b/public/-/emojis/2/haircut_tone4.png
new file mode 100644
index 00000000000..80c1fb49ce1
--- /dev/null
+++ b/public/-/emojis/2/haircut_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/haircut_tone5.png b/public/-/emojis/2/haircut_tone5.png
new file mode 100644
index 00000000000..85ef6faa508
--- /dev/null
+++ b/public/-/emojis/2/haircut_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/hamburger.png b/public/-/emojis/2/hamburger.png
new file mode 100644
index 00000000000..4f41f0e500b
--- /dev/null
+++ b/public/-/emojis/2/hamburger.png
Binary files differ
diff --git a/public/-/emojis/2/hammer.png b/public/-/emojis/2/hammer.png
new file mode 100644
index 00000000000..16709adc8e9
--- /dev/null
+++ b/public/-/emojis/2/hammer.png
Binary files differ
diff --git a/public/-/emojis/2/hammer_pick.png b/public/-/emojis/2/hammer_pick.png
new file mode 100644
index 00000000000..0a84f3da67e
--- /dev/null
+++ b/public/-/emojis/2/hammer_pick.png
Binary files differ
diff --git a/public/-/emojis/2/hamster.png b/public/-/emojis/2/hamster.png
new file mode 100644
index 00000000000..e6c8747fb6c
--- /dev/null
+++ b/public/-/emojis/2/hamster.png
Binary files differ
diff --git a/public/-/emojis/2/hand_splayed.png b/public/-/emojis/2/hand_splayed.png
new file mode 100644
index 00000000000..1ef0aeb3220
--- /dev/null
+++ b/public/-/emojis/2/hand_splayed.png
Binary files differ
diff --git a/public/-/emojis/2/hand_splayed_tone1.png b/public/-/emojis/2/hand_splayed_tone1.png
new file mode 100644
index 00000000000..acdf53b8c38
--- /dev/null
+++ b/public/-/emojis/2/hand_splayed_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/hand_splayed_tone2.png b/public/-/emojis/2/hand_splayed_tone2.png
new file mode 100644
index 00000000000..0849a7a9236
--- /dev/null
+++ b/public/-/emojis/2/hand_splayed_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/hand_splayed_tone3.png b/public/-/emojis/2/hand_splayed_tone3.png
new file mode 100644
index 00000000000..33050a2d739
--- /dev/null
+++ b/public/-/emojis/2/hand_splayed_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/hand_splayed_tone4.png b/public/-/emojis/2/hand_splayed_tone4.png
new file mode 100644
index 00000000000..6f3d80fc1f3
--- /dev/null
+++ b/public/-/emojis/2/hand_splayed_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/hand_splayed_tone5.png b/public/-/emojis/2/hand_splayed_tone5.png
new file mode 100644
index 00000000000..e6aee746215
--- /dev/null
+++ b/public/-/emojis/2/hand_splayed_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/handbag.png b/public/-/emojis/2/handbag.png
new file mode 100644
index 00000000000..bbc9b950acc
--- /dev/null
+++ b/public/-/emojis/2/handbag.png
Binary files differ
diff --git a/public/-/emojis/2/handball.png b/public/-/emojis/2/handball.png
new file mode 100644
index 00000000000..590339f8837
--- /dev/null
+++ b/public/-/emojis/2/handball.png
Binary files differ
diff --git a/public/-/emojis/2/handball_tone1.png b/public/-/emojis/2/handball_tone1.png
new file mode 100644
index 00000000000..3083c727c00
--- /dev/null
+++ b/public/-/emojis/2/handball_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/handball_tone2.png b/public/-/emojis/2/handball_tone2.png
new file mode 100644
index 00000000000..95387a56726
--- /dev/null
+++ b/public/-/emojis/2/handball_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/handball_tone3.png b/public/-/emojis/2/handball_tone3.png
new file mode 100644
index 00000000000..14e7ff24344
--- /dev/null
+++ b/public/-/emojis/2/handball_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/handball_tone4.png b/public/-/emojis/2/handball_tone4.png
new file mode 100644
index 00000000000..ee9becaa748
--- /dev/null
+++ b/public/-/emojis/2/handball_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/handball_tone5.png b/public/-/emojis/2/handball_tone5.png
new file mode 100644
index 00000000000..2826267bf2e
--- /dev/null
+++ b/public/-/emojis/2/handball_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/handshake.png b/public/-/emojis/2/handshake.png
new file mode 100644
index 00000000000..08274235735
--- /dev/null
+++ b/public/-/emojis/2/handshake.png
Binary files differ
diff --git a/public/-/emojis/2/handshake_tone1.png b/public/-/emojis/2/handshake_tone1.png
new file mode 100644
index 00000000000..b80629e7a75
--- /dev/null
+++ b/public/-/emojis/2/handshake_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/handshake_tone2.png b/public/-/emojis/2/handshake_tone2.png
new file mode 100644
index 00000000000..cb8864e27ae
--- /dev/null
+++ b/public/-/emojis/2/handshake_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/handshake_tone3.png b/public/-/emojis/2/handshake_tone3.png
new file mode 100644
index 00000000000..52817cb5f43
--- /dev/null
+++ b/public/-/emojis/2/handshake_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/handshake_tone4.png b/public/-/emojis/2/handshake_tone4.png
new file mode 100644
index 00000000000..7b0cc45d77b
--- /dev/null
+++ b/public/-/emojis/2/handshake_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/handshake_tone5.png b/public/-/emojis/2/handshake_tone5.png
new file mode 100644
index 00000000000..d9254fe6125
--- /dev/null
+++ b/public/-/emojis/2/handshake_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/hash.png b/public/-/emojis/2/hash.png
new file mode 100644
index 00000000000..ebd7b7047b3
--- /dev/null
+++ b/public/-/emojis/2/hash.png
Binary files differ
diff --git a/public/-/emojis/2/hatched_chick.png b/public/-/emojis/2/hatched_chick.png
new file mode 100644
index 00000000000..0867f68a397
--- /dev/null
+++ b/public/-/emojis/2/hatched_chick.png
Binary files differ
diff --git a/public/-/emojis/2/hatching_chick.png b/public/-/emojis/2/hatching_chick.png
new file mode 100644
index 00000000000..b7f68d7b6a5
--- /dev/null
+++ b/public/-/emojis/2/hatching_chick.png
Binary files differ
diff --git a/public/-/emojis/2/head_bandage.png b/public/-/emojis/2/head_bandage.png
new file mode 100644
index 00000000000..96a8b1511be
--- /dev/null
+++ b/public/-/emojis/2/head_bandage.png
Binary files differ
diff --git a/public/-/emojis/2/headphones.png b/public/-/emojis/2/headphones.png
new file mode 100644
index 00000000000..8dd7ef6e07e
--- /dev/null
+++ b/public/-/emojis/2/headphones.png
Binary files differ
diff --git a/public/-/emojis/2/hear_no_evil.png b/public/-/emojis/2/hear_no_evil.png
new file mode 100644
index 00000000000..489b210e41a
--- /dev/null
+++ b/public/-/emojis/2/hear_no_evil.png
Binary files differ
diff --git a/public/-/emojis/2/heart.png b/public/-/emojis/2/heart.png
new file mode 100644
index 00000000000..c462b4318ad
--- /dev/null
+++ b/public/-/emojis/2/heart.png
Binary files differ
diff --git a/public/-/emojis/2/heart_decoration.png b/public/-/emojis/2/heart_decoration.png
new file mode 100644
index 00000000000..f3db4864f40
--- /dev/null
+++ b/public/-/emojis/2/heart_decoration.png
Binary files differ
diff --git a/public/-/emojis/2/heart_exclamation.png b/public/-/emojis/2/heart_exclamation.png
new file mode 100644
index 00000000000..afe34a69a56
--- /dev/null
+++ b/public/-/emojis/2/heart_exclamation.png
Binary files differ
diff --git a/public/-/emojis/2/heart_eyes.png b/public/-/emojis/2/heart_eyes.png
new file mode 100644
index 00000000000..e3bb7806e12
--- /dev/null
+++ b/public/-/emojis/2/heart_eyes.png
Binary files differ
diff --git a/public/-/emojis/2/heart_eyes_cat.png b/public/-/emojis/2/heart_eyes_cat.png
new file mode 100644
index 00000000000..74b72d63f79
--- /dev/null
+++ b/public/-/emojis/2/heart_eyes_cat.png
Binary files differ
diff --git a/public/-/emojis/2/heartbeat.png b/public/-/emojis/2/heartbeat.png
new file mode 100644
index 00000000000..168dbdc2d36
--- /dev/null
+++ b/public/-/emojis/2/heartbeat.png
Binary files differ
diff --git a/public/-/emojis/2/heartpulse.png b/public/-/emojis/2/heartpulse.png
new file mode 100644
index 00000000000..79258086f4b
--- /dev/null
+++ b/public/-/emojis/2/heartpulse.png
Binary files differ
diff --git a/public/-/emojis/2/hearts.png b/public/-/emojis/2/hearts.png
new file mode 100644
index 00000000000..723226d77a4
--- /dev/null
+++ b/public/-/emojis/2/hearts.png
Binary files differ
diff --git a/public/-/emojis/2/heavy_check_mark.png b/public/-/emojis/2/heavy_check_mark.png
new file mode 100644
index 00000000000..9dfde579082
--- /dev/null
+++ b/public/-/emojis/2/heavy_check_mark.png
Binary files differ
diff --git a/public/-/emojis/2/heavy_division_sign.png b/public/-/emojis/2/heavy_division_sign.png
new file mode 100644
index 00000000000..a86eebd442b
--- /dev/null
+++ b/public/-/emojis/2/heavy_division_sign.png
Binary files differ
diff --git a/public/-/emojis/2/heavy_dollar_sign.png b/public/-/emojis/2/heavy_dollar_sign.png
new file mode 100644
index 00000000000..4e58e372cbd
--- /dev/null
+++ b/public/-/emojis/2/heavy_dollar_sign.png
Binary files differ
diff --git a/public/-/emojis/2/heavy_minus_sign.png b/public/-/emojis/2/heavy_minus_sign.png
new file mode 100644
index 00000000000..493523b02af
--- /dev/null
+++ b/public/-/emojis/2/heavy_minus_sign.png
Binary files differ
diff --git a/public/-/emojis/2/heavy_multiplication_x.png b/public/-/emojis/2/heavy_multiplication_x.png
new file mode 100644
index 00000000000..5a0e0198c61
--- /dev/null
+++ b/public/-/emojis/2/heavy_multiplication_x.png
Binary files differ
diff --git a/public/-/emojis/2/heavy_plus_sign.png b/public/-/emojis/2/heavy_plus_sign.png
new file mode 100644
index 00000000000..b3791a2c3fe
--- /dev/null
+++ b/public/-/emojis/2/heavy_plus_sign.png
Binary files differ
diff --git a/public/-/emojis/2/helicopter.png b/public/-/emojis/2/helicopter.png
new file mode 100644
index 00000000000..18843853ec4
--- /dev/null
+++ b/public/-/emojis/2/helicopter.png
Binary files differ
diff --git a/public/-/emojis/2/helmet_with_cross.png b/public/-/emojis/2/helmet_with_cross.png
new file mode 100644
index 00000000000..6119e2e6498
--- /dev/null
+++ b/public/-/emojis/2/helmet_with_cross.png
Binary files differ
diff --git a/public/-/emojis/2/herb.png b/public/-/emojis/2/herb.png
new file mode 100644
index 00000000000..7b1ff5815f0
--- /dev/null
+++ b/public/-/emojis/2/herb.png
Binary files differ
diff --git a/public/-/emojis/2/hibiscus.png b/public/-/emojis/2/hibiscus.png
new file mode 100644
index 00000000000..5400fdd7a9b
--- /dev/null
+++ b/public/-/emojis/2/hibiscus.png
Binary files differ
diff --git a/public/-/emojis/2/high_brightness.png b/public/-/emojis/2/high_brightness.png
new file mode 100644
index 00000000000..fde91f298a3
--- /dev/null
+++ b/public/-/emojis/2/high_brightness.png
Binary files differ
diff --git a/public/-/emojis/2/high_heel.png b/public/-/emojis/2/high_heel.png
new file mode 100644
index 00000000000..4a6e62180e9
--- /dev/null
+++ b/public/-/emojis/2/high_heel.png
Binary files differ
diff --git a/public/-/emojis/2/hockey.png b/public/-/emojis/2/hockey.png
new file mode 100644
index 00000000000..3353eb01657
--- /dev/null
+++ b/public/-/emojis/2/hockey.png
Binary files differ
diff --git a/public/-/emojis/2/hole.png b/public/-/emojis/2/hole.png
new file mode 100644
index 00000000000..bf1ad759bd6
--- /dev/null
+++ b/public/-/emojis/2/hole.png
Binary files differ
diff --git a/public/-/emojis/2/homes.png b/public/-/emojis/2/homes.png
new file mode 100644
index 00000000000..32b16a807d0
--- /dev/null
+++ b/public/-/emojis/2/homes.png
Binary files differ
diff --git a/public/-/emojis/2/honey_pot.png b/public/-/emojis/2/honey_pot.png
new file mode 100644
index 00000000000..85294a979fa
--- /dev/null
+++ b/public/-/emojis/2/honey_pot.png
Binary files differ
diff --git a/public/-/emojis/2/horse.png b/public/-/emojis/2/horse.png
new file mode 100644
index 00000000000..35112aca1ae
--- /dev/null
+++ b/public/-/emojis/2/horse.png
Binary files differ
diff --git a/public/-/emojis/2/horse_racing.png b/public/-/emojis/2/horse_racing.png
new file mode 100644
index 00000000000..84f92487654
--- /dev/null
+++ b/public/-/emojis/2/horse_racing.png
Binary files differ
diff --git a/public/-/emojis/2/horse_racing_tone1.png b/public/-/emojis/2/horse_racing_tone1.png
new file mode 100644
index 00000000000..7d2e8729e12
--- /dev/null
+++ b/public/-/emojis/2/horse_racing_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/horse_racing_tone2.png b/public/-/emojis/2/horse_racing_tone2.png
new file mode 100644
index 00000000000..ff29cd640de
--- /dev/null
+++ b/public/-/emojis/2/horse_racing_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/horse_racing_tone3.png b/public/-/emojis/2/horse_racing_tone3.png
new file mode 100644
index 00000000000..a72be537729
--- /dev/null
+++ b/public/-/emojis/2/horse_racing_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/horse_racing_tone4.png b/public/-/emojis/2/horse_racing_tone4.png
new file mode 100644
index 00000000000..169955f1d7e
--- /dev/null
+++ b/public/-/emojis/2/horse_racing_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/horse_racing_tone5.png b/public/-/emojis/2/horse_racing_tone5.png
new file mode 100644
index 00000000000..09aeeb940e1
--- /dev/null
+++ b/public/-/emojis/2/horse_racing_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/hospital.png b/public/-/emojis/2/hospital.png
new file mode 100644
index 00000000000..2251e567729
--- /dev/null
+++ b/public/-/emojis/2/hospital.png
Binary files differ
diff --git a/public/-/emojis/2/hot_pepper.png b/public/-/emojis/2/hot_pepper.png
new file mode 100644
index 00000000000..934bf6daf87
--- /dev/null
+++ b/public/-/emojis/2/hot_pepper.png
Binary files differ
diff --git a/public/-/emojis/2/hotdog.png b/public/-/emojis/2/hotdog.png
new file mode 100644
index 00000000000..a1738700e26
--- /dev/null
+++ b/public/-/emojis/2/hotdog.png
Binary files differ
diff --git a/public/-/emojis/2/hotel.png b/public/-/emojis/2/hotel.png
new file mode 100644
index 00000000000..2291ece74a2
--- /dev/null
+++ b/public/-/emojis/2/hotel.png
Binary files differ
diff --git a/public/-/emojis/2/hotsprings.png b/public/-/emojis/2/hotsprings.png
new file mode 100644
index 00000000000..a8e12e196de
--- /dev/null
+++ b/public/-/emojis/2/hotsprings.png
Binary files differ
diff --git a/public/-/emojis/2/hourglass.png b/public/-/emojis/2/hourglass.png
new file mode 100644
index 00000000000..ae55c33d237
--- /dev/null
+++ b/public/-/emojis/2/hourglass.png
Binary files differ
diff --git a/public/-/emojis/2/hourglass_flowing_sand.png b/public/-/emojis/2/hourglass_flowing_sand.png
new file mode 100644
index 00000000000..961f1769d32
--- /dev/null
+++ b/public/-/emojis/2/hourglass_flowing_sand.png
Binary files differ
diff --git a/public/-/emojis/2/house.png b/public/-/emojis/2/house.png
new file mode 100644
index 00000000000..a23121dad9e
--- /dev/null
+++ b/public/-/emojis/2/house.png
Binary files differ
diff --git a/public/-/emojis/2/house_abandoned.png b/public/-/emojis/2/house_abandoned.png
new file mode 100644
index 00000000000..147f8ddb361
--- /dev/null
+++ b/public/-/emojis/2/house_abandoned.png
Binary files differ
diff --git a/public/-/emojis/2/house_with_garden.png b/public/-/emojis/2/house_with_garden.png
new file mode 100644
index 00000000000..728d9791d33
--- /dev/null
+++ b/public/-/emojis/2/house_with_garden.png
Binary files differ
diff --git a/public/-/emojis/2/hugging.png b/public/-/emojis/2/hugging.png
new file mode 100644
index 00000000000..06afc6c7350
--- /dev/null
+++ b/public/-/emojis/2/hugging.png
Binary files differ
diff --git a/public/-/emojis/2/hushed.png b/public/-/emojis/2/hushed.png
new file mode 100644
index 00000000000..9d02a806052
--- /dev/null
+++ b/public/-/emojis/2/hushed.png
Binary files differ
diff --git a/public/-/emojis/2/ice_cream.png b/public/-/emojis/2/ice_cream.png
new file mode 100644
index 00000000000..15888c9e9d9
--- /dev/null
+++ b/public/-/emojis/2/ice_cream.png
Binary files differ
diff --git a/public/-/emojis/2/ice_skate.png b/public/-/emojis/2/ice_skate.png
new file mode 100644
index 00000000000..60b7dcba437
--- /dev/null
+++ b/public/-/emojis/2/ice_skate.png
Binary files differ
diff --git a/public/-/emojis/2/icecream.png b/public/-/emojis/2/icecream.png
new file mode 100644
index 00000000000..a63c4b900da
--- /dev/null
+++ b/public/-/emojis/2/icecream.png
Binary files differ
diff --git a/public/-/emojis/2/id.png b/public/-/emojis/2/id.png
new file mode 100644
index 00000000000..29d43ac5eb4
--- /dev/null
+++ b/public/-/emojis/2/id.png
Binary files differ
diff --git a/public/-/emojis/2/ideograph_advantage.png b/public/-/emojis/2/ideograph_advantage.png
new file mode 100644
index 00000000000..95c62036a17
--- /dev/null
+++ b/public/-/emojis/2/ideograph_advantage.png
Binary files differ
diff --git a/public/-/emojis/2/imp.png b/public/-/emojis/2/imp.png
new file mode 100644
index 00000000000..9d6c71af9b0
--- /dev/null
+++ b/public/-/emojis/2/imp.png
Binary files differ
diff --git a/public/-/emojis/2/inbox_tray.png b/public/-/emojis/2/inbox_tray.png
new file mode 100644
index 00000000000..2a34335455d
--- /dev/null
+++ b/public/-/emojis/2/inbox_tray.png
Binary files differ
diff --git a/public/-/emojis/2/incoming_envelope.png b/public/-/emojis/2/incoming_envelope.png
new file mode 100644
index 00000000000..7febff3bfe2
--- /dev/null
+++ b/public/-/emojis/2/incoming_envelope.png
Binary files differ
diff --git a/public/-/emojis/2/information_desk_person.png b/public/-/emojis/2/information_desk_person.png
new file mode 100644
index 00000000000..396f4f0a489
--- /dev/null
+++ b/public/-/emojis/2/information_desk_person.png
Binary files differ
diff --git a/public/-/emojis/2/information_desk_person_tone1.png b/public/-/emojis/2/information_desk_person_tone1.png
new file mode 100644
index 00000000000..fec768939e2
--- /dev/null
+++ b/public/-/emojis/2/information_desk_person_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/information_desk_person_tone2.png b/public/-/emojis/2/information_desk_person_tone2.png
new file mode 100644
index 00000000000..bd086a61d48
--- /dev/null
+++ b/public/-/emojis/2/information_desk_person_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/information_desk_person_tone3.png b/public/-/emojis/2/information_desk_person_tone3.png
new file mode 100644
index 00000000000..13557e8c32e
--- /dev/null
+++ b/public/-/emojis/2/information_desk_person_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/information_desk_person_tone4.png b/public/-/emojis/2/information_desk_person_tone4.png
new file mode 100644
index 00000000000..a91d0b5835e
--- /dev/null
+++ b/public/-/emojis/2/information_desk_person_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/information_desk_person_tone5.png b/public/-/emojis/2/information_desk_person_tone5.png
new file mode 100644
index 00000000000..4acb6992b4c
--- /dev/null
+++ b/public/-/emojis/2/information_desk_person_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/information_source.png b/public/-/emojis/2/information_source.png
new file mode 100644
index 00000000000..0b9dc75c950
--- /dev/null
+++ b/public/-/emojis/2/information_source.png
Binary files differ
diff --git a/public/-/emojis/2/innocent.png b/public/-/emojis/2/innocent.png
new file mode 100644
index 00000000000..297404a8b92
--- /dev/null
+++ b/public/-/emojis/2/innocent.png
Binary files differ
diff --git a/public/-/emojis/2/interrobang.png b/public/-/emojis/2/interrobang.png
new file mode 100644
index 00000000000..9b2875cea93
--- /dev/null
+++ b/public/-/emojis/2/interrobang.png
Binary files differ
diff --git a/public/-/emojis/2/iphone.png b/public/-/emojis/2/iphone.png
new file mode 100644
index 00000000000..2a333235c71
--- /dev/null
+++ b/public/-/emojis/2/iphone.png
Binary files differ
diff --git a/public/-/emojis/2/island.png b/public/-/emojis/2/island.png
new file mode 100644
index 00000000000..87d13274924
--- /dev/null
+++ b/public/-/emojis/2/island.png
Binary files differ
diff --git a/public/-/emojis/2/izakaya_lantern.png b/public/-/emojis/2/izakaya_lantern.png
new file mode 100644
index 00000000000..c180a2ff957
--- /dev/null
+++ b/public/-/emojis/2/izakaya_lantern.png
Binary files differ
diff --git a/public/-/emojis/2/jack_o_lantern.png b/public/-/emojis/2/jack_o_lantern.png
new file mode 100644
index 00000000000..6b4b5fd3360
--- /dev/null
+++ b/public/-/emojis/2/jack_o_lantern.png
Binary files differ
diff --git a/public/-/emojis/2/japan.png b/public/-/emojis/2/japan.png
new file mode 100644
index 00000000000..98dcb48b15d
--- /dev/null
+++ b/public/-/emojis/2/japan.png
Binary files differ
diff --git a/public/-/emojis/2/japanese_castle.png b/public/-/emojis/2/japanese_castle.png
new file mode 100644
index 00000000000..6b133365e3b
--- /dev/null
+++ b/public/-/emojis/2/japanese_castle.png
Binary files differ
diff --git a/public/-/emojis/2/japanese_goblin.png b/public/-/emojis/2/japanese_goblin.png
new file mode 100644
index 00000000000..1c0a10aa2fc
--- /dev/null
+++ b/public/-/emojis/2/japanese_goblin.png
Binary files differ
diff --git a/public/-/emojis/2/japanese_ogre.png b/public/-/emojis/2/japanese_ogre.png
new file mode 100644
index 00000000000..6d4f4aa7f45
--- /dev/null
+++ b/public/-/emojis/2/japanese_ogre.png
Binary files differ
diff --git a/public/-/emojis/2/jeans.png b/public/-/emojis/2/jeans.png
new file mode 100644
index 00000000000..2bd8122c90f
--- /dev/null
+++ b/public/-/emojis/2/jeans.png
Binary files differ
diff --git a/public/-/emojis/2/joy.png b/public/-/emojis/2/joy.png
new file mode 100644
index 00000000000..3a1103803c4
--- /dev/null
+++ b/public/-/emojis/2/joy.png
Binary files differ
diff --git a/public/-/emojis/2/joy_cat.png b/public/-/emojis/2/joy_cat.png
new file mode 100644
index 00000000000..0c3c1be3b6d
--- /dev/null
+++ b/public/-/emojis/2/joy_cat.png
Binary files differ
diff --git a/public/-/emojis/2/joystick.png b/public/-/emojis/2/joystick.png
new file mode 100644
index 00000000000..ace46cb751f
--- /dev/null
+++ b/public/-/emojis/2/joystick.png
Binary files differ
diff --git a/public/-/emojis/2/juggling.png b/public/-/emojis/2/juggling.png
new file mode 100644
index 00000000000..50f2275aac0
--- /dev/null
+++ b/public/-/emojis/2/juggling.png
Binary files differ
diff --git a/public/-/emojis/2/juggling_tone1.png b/public/-/emojis/2/juggling_tone1.png
new file mode 100644
index 00000000000..acb9056a2a4
--- /dev/null
+++ b/public/-/emojis/2/juggling_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/juggling_tone2.png b/public/-/emojis/2/juggling_tone2.png
new file mode 100644
index 00000000000..c2809447a80
--- /dev/null
+++ b/public/-/emojis/2/juggling_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/juggling_tone3.png b/public/-/emojis/2/juggling_tone3.png
new file mode 100644
index 00000000000..625e0d90506
--- /dev/null
+++ b/public/-/emojis/2/juggling_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/juggling_tone4.png b/public/-/emojis/2/juggling_tone4.png
new file mode 100644
index 00000000000..ceb628ff36e
--- /dev/null
+++ b/public/-/emojis/2/juggling_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/juggling_tone5.png b/public/-/emojis/2/juggling_tone5.png
new file mode 100644
index 00000000000..fc1ff36a024
--- /dev/null
+++ b/public/-/emojis/2/juggling_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/kaaba.png b/public/-/emojis/2/kaaba.png
new file mode 100644
index 00000000000..c49eb875d09
--- /dev/null
+++ b/public/-/emojis/2/kaaba.png
Binary files differ
diff --git a/public/-/emojis/2/key.png b/public/-/emojis/2/key.png
new file mode 100644
index 00000000000..26ef5c33cdf
--- /dev/null
+++ b/public/-/emojis/2/key.png
Binary files differ
diff --git a/public/-/emojis/2/key2.png b/public/-/emojis/2/key2.png
new file mode 100644
index 00000000000..abd66dbc688
--- /dev/null
+++ b/public/-/emojis/2/key2.png
Binary files differ
diff --git a/public/-/emojis/2/keyboard.png b/public/-/emojis/2/keyboard.png
new file mode 100644
index 00000000000..f1f9d350b39
--- /dev/null
+++ b/public/-/emojis/2/keyboard.png
Binary files differ
diff --git a/public/-/emojis/2/kimono.png b/public/-/emojis/2/kimono.png
new file mode 100644
index 00000000000..c04d88fc1ce
--- /dev/null
+++ b/public/-/emojis/2/kimono.png
Binary files differ
diff --git a/public/-/emojis/2/kiss.png b/public/-/emojis/2/kiss.png
new file mode 100644
index 00000000000..4d30dff10d9
--- /dev/null
+++ b/public/-/emojis/2/kiss.png
Binary files differ
diff --git a/public/-/emojis/2/kiss_mm.png b/public/-/emojis/2/kiss_mm.png
new file mode 100644
index 00000000000..9b49c4b409d
--- /dev/null
+++ b/public/-/emojis/2/kiss_mm.png
Binary files differ
diff --git a/public/-/emojis/2/kiss_ww.png b/public/-/emojis/2/kiss_ww.png
new file mode 100644
index 00000000000..678857c5109
--- /dev/null
+++ b/public/-/emojis/2/kiss_ww.png
Binary files differ
diff --git a/public/-/emojis/2/kissing.png b/public/-/emojis/2/kissing.png
new file mode 100644
index 00000000000..bb176638d8d
--- /dev/null
+++ b/public/-/emojis/2/kissing.png
Binary files differ
diff --git a/public/-/emojis/2/kissing_cat.png b/public/-/emojis/2/kissing_cat.png
new file mode 100644
index 00000000000..cc47ec15537
--- /dev/null
+++ b/public/-/emojis/2/kissing_cat.png
Binary files differ
diff --git a/public/-/emojis/2/kissing_closed_eyes.png b/public/-/emojis/2/kissing_closed_eyes.png
new file mode 100644
index 00000000000..3422c63253b
--- /dev/null
+++ b/public/-/emojis/2/kissing_closed_eyes.png
Binary files differ
diff --git a/public/-/emojis/2/kissing_heart.png b/public/-/emojis/2/kissing_heart.png
new file mode 100644
index 00000000000..0427b706194
--- /dev/null
+++ b/public/-/emojis/2/kissing_heart.png
Binary files differ
diff --git a/public/-/emojis/2/kissing_smiling_eyes.png b/public/-/emojis/2/kissing_smiling_eyes.png
new file mode 100644
index 00000000000..6b00b2fbe17
--- /dev/null
+++ b/public/-/emojis/2/kissing_smiling_eyes.png
Binary files differ
diff --git a/public/-/emojis/2/kiwi.png b/public/-/emojis/2/kiwi.png
new file mode 100644
index 00000000000..d9cabbf03fe
--- /dev/null
+++ b/public/-/emojis/2/kiwi.png
Binary files differ
diff --git a/public/-/emojis/2/knife.png b/public/-/emojis/2/knife.png
new file mode 100644
index 00000000000..86c5a80ea04
--- /dev/null
+++ b/public/-/emojis/2/knife.png
Binary files differ
diff --git a/public/-/emojis/2/koala.png b/public/-/emojis/2/koala.png
new file mode 100644
index 00000000000..88c4947e513
--- /dev/null
+++ b/public/-/emojis/2/koala.png
Binary files differ
diff --git a/public/-/emojis/2/koko.png b/public/-/emojis/2/koko.png
new file mode 100644
index 00000000000..835d1351c13
--- /dev/null
+++ b/public/-/emojis/2/koko.png
Binary files differ
diff --git a/public/-/emojis/2/label.png b/public/-/emojis/2/label.png
new file mode 100644
index 00000000000..ff9ebf30690
--- /dev/null
+++ b/public/-/emojis/2/label.png
Binary files differ
diff --git a/public/-/emojis/2/large_blue_circle.png b/public/-/emojis/2/large_blue_circle.png
new file mode 100644
index 00000000000..13aca4ff995
--- /dev/null
+++ b/public/-/emojis/2/large_blue_circle.png
Binary files differ
diff --git a/public/-/emojis/2/large_blue_diamond.png b/public/-/emojis/2/large_blue_diamond.png
new file mode 100644
index 00000000000..501b85dedc0
--- /dev/null
+++ b/public/-/emojis/2/large_blue_diamond.png
Binary files differ
diff --git a/public/-/emojis/2/large_orange_diamond.png b/public/-/emojis/2/large_orange_diamond.png
new file mode 100644
index 00000000000..929f9132687
--- /dev/null
+++ b/public/-/emojis/2/large_orange_diamond.png
Binary files differ
diff --git a/public/-/emojis/2/last_quarter_moon.png b/public/-/emojis/2/last_quarter_moon.png
new file mode 100644
index 00000000000..a5e5b7ff320
--- /dev/null
+++ b/public/-/emojis/2/last_quarter_moon.png
Binary files differ
diff --git a/public/-/emojis/2/last_quarter_moon_with_face.png b/public/-/emojis/2/last_quarter_moon_with_face.png
new file mode 100644
index 00000000000..2f2ed5fd8f5
--- /dev/null
+++ b/public/-/emojis/2/last_quarter_moon_with_face.png
Binary files differ
diff --git a/public/-/emojis/2/laughing.png b/public/-/emojis/2/laughing.png
new file mode 100644
index 00000000000..56ace6c7f8d
--- /dev/null
+++ b/public/-/emojis/2/laughing.png
Binary files differ
diff --git a/public/-/emojis/2/leaves.png b/public/-/emojis/2/leaves.png
new file mode 100644
index 00000000000..ed2dcc893ea
--- /dev/null
+++ b/public/-/emojis/2/leaves.png
Binary files differ
diff --git a/public/-/emojis/2/ledger.png b/public/-/emojis/2/ledger.png
new file mode 100644
index 00000000000..bf8f09fb37f
--- /dev/null
+++ b/public/-/emojis/2/ledger.png
Binary files differ
diff --git a/public/-/emojis/2/left_facing_fist.png b/public/-/emojis/2/left_facing_fist.png
new file mode 100644
index 00000000000..9c906df503b
--- /dev/null
+++ b/public/-/emojis/2/left_facing_fist.png
Binary files differ
diff --git a/public/-/emojis/2/left_facing_fist_tone1.png b/public/-/emojis/2/left_facing_fist_tone1.png
new file mode 100644
index 00000000000..1135adf2b05
--- /dev/null
+++ b/public/-/emojis/2/left_facing_fist_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/left_facing_fist_tone2.png b/public/-/emojis/2/left_facing_fist_tone2.png
new file mode 100644
index 00000000000..b1632483ce9
--- /dev/null
+++ b/public/-/emojis/2/left_facing_fist_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/left_facing_fist_tone3.png b/public/-/emojis/2/left_facing_fist_tone3.png
new file mode 100644
index 00000000000..2209797d48c
--- /dev/null
+++ b/public/-/emojis/2/left_facing_fist_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/left_facing_fist_tone4.png b/public/-/emojis/2/left_facing_fist_tone4.png
new file mode 100644
index 00000000000..a5e3c48f821
--- /dev/null
+++ b/public/-/emojis/2/left_facing_fist_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/left_facing_fist_tone5.png b/public/-/emojis/2/left_facing_fist_tone5.png
new file mode 100644
index 00000000000..f9d58061e6f
--- /dev/null
+++ b/public/-/emojis/2/left_facing_fist_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/left_luggage.png b/public/-/emojis/2/left_luggage.png
new file mode 100644
index 00000000000..5a4c8014113
--- /dev/null
+++ b/public/-/emojis/2/left_luggage.png
Binary files differ
diff --git a/public/-/emojis/2/left_right_arrow.png b/public/-/emojis/2/left_right_arrow.png
new file mode 100644
index 00000000000..900ff12cc99
--- /dev/null
+++ b/public/-/emojis/2/left_right_arrow.png
Binary files differ
diff --git a/public/-/emojis/2/leftwards_arrow_with_hook.png b/public/-/emojis/2/leftwards_arrow_with_hook.png
new file mode 100644
index 00000000000..22b51a690a9
--- /dev/null
+++ b/public/-/emojis/2/leftwards_arrow_with_hook.png
Binary files differ
diff --git a/public/-/emojis/2/lemon.png b/public/-/emojis/2/lemon.png
new file mode 100644
index 00000000000..e0bab2a069d
--- /dev/null
+++ b/public/-/emojis/2/lemon.png
Binary files differ
diff --git a/public/-/emojis/2/leo.png b/public/-/emojis/2/leo.png
new file mode 100644
index 00000000000..a42fe8e6aa3
--- /dev/null
+++ b/public/-/emojis/2/leo.png
Binary files differ
diff --git a/public/-/emojis/2/leopard.png b/public/-/emojis/2/leopard.png
new file mode 100644
index 00000000000..37ea6bb759b
--- /dev/null
+++ b/public/-/emojis/2/leopard.png
Binary files differ
diff --git a/public/-/emojis/2/level_slider.png b/public/-/emojis/2/level_slider.png
new file mode 100644
index 00000000000..84ccab6e7d6
--- /dev/null
+++ b/public/-/emojis/2/level_slider.png
Binary files differ
diff --git a/public/-/emojis/2/levitate.png b/public/-/emojis/2/levitate.png
new file mode 100644
index 00000000000..bbbd63ec40f
--- /dev/null
+++ b/public/-/emojis/2/levitate.png
Binary files differ
diff --git a/public/-/emojis/2/libra.png b/public/-/emojis/2/libra.png
new file mode 100644
index 00000000000..791d13f8a45
--- /dev/null
+++ b/public/-/emojis/2/libra.png
Binary files differ
diff --git a/public/-/emojis/2/lifter.png b/public/-/emojis/2/lifter.png
new file mode 100644
index 00000000000..de24a15a5d9
--- /dev/null
+++ b/public/-/emojis/2/lifter.png
Binary files differ
diff --git a/public/-/emojis/2/lifter_tone1.png b/public/-/emojis/2/lifter_tone1.png
new file mode 100644
index 00000000000..fb3f3233ad1
--- /dev/null
+++ b/public/-/emojis/2/lifter_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/lifter_tone2.png b/public/-/emojis/2/lifter_tone2.png
new file mode 100644
index 00000000000..0355652ba15
--- /dev/null
+++ b/public/-/emojis/2/lifter_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/lifter_tone3.png b/public/-/emojis/2/lifter_tone3.png
new file mode 100644
index 00000000000..a0d8c97ee19
--- /dev/null
+++ b/public/-/emojis/2/lifter_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/lifter_tone4.png b/public/-/emojis/2/lifter_tone4.png
new file mode 100644
index 00000000000..2f6cc33e461
--- /dev/null
+++ b/public/-/emojis/2/lifter_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/lifter_tone5.png b/public/-/emojis/2/lifter_tone5.png
new file mode 100644
index 00000000000..77888ef91d1
--- /dev/null
+++ b/public/-/emojis/2/lifter_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/light_rail.png b/public/-/emojis/2/light_rail.png
new file mode 100644
index 00000000000..ae337d7ce54
--- /dev/null
+++ b/public/-/emojis/2/light_rail.png
Binary files differ
diff --git a/public/-/emojis/2/link.png b/public/-/emojis/2/link.png
new file mode 100644
index 00000000000..f1a7c11e9f0
--- /dev/null
+++ b/public/-/emojis/2/link.png
Binary files differ
diff --git a/public/-/emojis/2/lion_face.png b/public/-/emojis/2/lion_face.png
new file mode 100644
index 00000000000..42eac6464b3
--- /dev/null
+++ b/public/-/emojis/2/lion_face.png
Binary files differ
diff --git a/public/-/emojis/2/lips.png b/public/-/emojis/2/lips.png
new file mode 100644
index 00000000000..542c12a5594
--- /dev/null
+++ b/public/-/emojis/2/lips.png
Binary files differ
diff --git a/public/-/emojis/2/lipstick.png b/public/-/emojis/2/lipstick.png
new file mode 100644
index 00000000000..a58667d0c70
--- /dev/null
+++ b/public/-/emojis/2/lipstick.png
Binary files differ
diff --git a/public/-/emojis/2/lizard.png b/public/-/emojis/2/lizard.png
new file mode 100644
index 00000000000..1712def5e90
--- /dev/null
+++ b/public/-/emojis/2/lizard.png
Binary files differ
diff --git a/public/-/emojis/2/lock.png b/public/-/emojis/2/lock.png
new file mode 100644
index 00000000000..1d63bc87919
--- /dev/null
+++ b/public/-/emojis/2/lock.png
Binary files differ
diff --git a/public/-/emojis/2/lock_with_ink_pen.png b/public/-/emojis/2/lock_with_ink_pen.png
new file mode 100644
index 00000000000..fa9cf62c0f1
--- /dev/null
+++ b/public/-/emojis/2/lock_with_ink_pen.png
Binary files differ
diff --git a/public/-/emojis/2/lollipop.png b/public/-/emojis/2/lollipop.png
new file mode 100644
index 00000000000..0948101801d
--- /dev/null
+++ b/public/-/emojis/2/lollipop.png
Binary files differ
diff --git a/public/-/emojis/2/loop.png b/public/-/emojis/2/loop.png
new file mode 100644
index 00000000000..353fce5994e
--- /dev/null
+++ b/public/-/emojis/2/loop.png
Binary files differ
diff --git a/public/-/emojis/2/loud_sound.png b/public/-/emojis/2/loud_sound.png
new file mode 100644
index 00000000000..8150c3ae6ab
--- /dev/null
+++ b/public/-/emojis/2/loud_sound.png
Binary files differ
diff --git a/public/-/emojis/2/loudspeaker.png b/public/-/emojis/2/loudspeaker.png
new file mode 100644
index 00000000000..b73054a5cb9
--- /dev/null
+++ b/public/-/emojis/2/loudspeaker.png
Binary files differ
diff --git a/public/-/emojis/2/love_hotel.png b/public/-/emojis/2/love_hotel.png
new file mode 100644
index 00000000000..b0bc9b9150c
--- /dev/null
+++ b/public/-/emojis/2/love_hotel.png
Binary files differ
diff --git a/public/-/emojis/2/love_letter.png b/public/-/emojis/2/love_letter.png
new file mode 100644
index 00000000000..135bcf05119
--- /dev/null
+++ b/public/-/emojis/2/love_letter.png
Binary files differ
diff --git a/public/-/emojis/2/low_brightness.png b/public/-/emojis/2/low_brightness.png
new file mode 100644
index 00000000000..f444013da6e
--- /dev/null
+++ b/public/-/emojis/2/low_brightness.png
Binary files differ
diff --git a/public/-/emojis/2/lying_face.png b/public/-/emojis/2/lying_face.png
new file mode 100644
index 00000000000..97432b50d57
--- /dev/null
+++ b/public/-/emojis/2/lying_face.png
Binary files differ
diff --git a/public/-/emojis/2/m.png b/public/-/emojis/2/m.png
new file mode 100644
index 00000000000..3ee9e9fbc9c
--- /dev/null
+++ b/public/-/emojis/2/m.png
Binary files differ
diff --git a/public/-/emojis/2/mag.png b/public/-/emojis/2/mag.png
new file mode 100644
index 00000000000..2363ea1bb02
--- /dev/null
+++ b/public/-/emojis/2/mag.png
Binary files differ
diff --git a/public/-/emojis/2/mag_right.png b/public/-/emojis/2/mag_right.png
new file mode 100644
index 00000000000..9284b384810
--- /dev/null
+++ b/public/-/emojis/2/mag_right.png
Binary files differ
diff --git a/public/-/emojis/2/mahjong.png b/public/-/emojis/2/mahjong.png
new file mode 100644
index 00000000000..6e86f916fc4
--- /dev/null
+++ b/public/-/emojis/2/mahjong.png
Binary files differ
diff --git a/public/-/emojis/2/mailbox.png b/public/-/emojis/2/mailbox.png
new file mode 100644
index 00000000000..e6a6f24ddfa
--- /dev/null
+++ b/public/-/emojis/2/mailbox.png
Binary files differ
diff --git a/public/-/emojis/2/mailbox_closed.png b/public/-/emojis/2/mailbox_closed.png
new file mode 100644
index 00000000000..712b644754c
--- /dev/null
+++ b/public/-/emojis/2/mailbox_closed.png
Binary files differ
diff --git a/public/-/emojis/2/mailbox_with_mail.png b/public/-/emojis/2/mailbox_with_mail.png
new file mode 100644
index 00000000000..5b3acde9ed3
--- /dev/null
+++ b/public/-/emojis/2/mailbox_with_mail.png
Binary files differ
diff --git a/public/-/emojis/2/mailbox_with_no_mail.png b/public/-/emojis/2/mailbox_with_no_mail.png
new file mode 100644
index 00000000000..e91113c5b7d
--- /dev/null
+++ b/public/-/emojis/2/mailbox_with_no_mail.png
Binary files differ
diff --git a/public/-/emojis/2/man.png b/public/-/emojis/2/man.png
new file mode 100644
index 00000000000..1471371a28d
--- /dev/null
+++ b/public/-/emojis/2/man.png
Binary files differ
diff --git a/public/-/emojis/2/man_dancing.png b/public/-/emojis/2/man_dancing.png
new file mode 100644
index 00000000000..506607c93f1
--- /dev/null
+++ b/public/-/emojis/2/man_dancing.png
Binary files differ
diff --git a/public/-/emojis/2/man_dancing_tone1.png b/public/-/emojis/2/man_dancing_tone1.png
new file mode 100644
index 00000000000..42f547529c2
--- /dev/null
+++ b/public/-/emojis/2/man_dancing_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/man_dancing_tone2.png b/public/-/emojis/2/man_dancing_tone2.png
new file mode 100644
index 00000000000..2c3daaa08e2
--- /dev/null
+++ b/public/-/emojis/2/man_dancing_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/man_dancing_tone3.png b/public/-/emojis/2/man_dancing_tone3.png
new file mode 100644
index 00000000000..85c5092a13a
--- /dev/null
+++ b/public/-/emojis/2/man_dancing_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/man_dancing_tone4.png b/public/-/emojis/2/man_dancing_tone4.png
new file mode 100644
index 00000000000..98897f3aa8c
--- /dev/null
+++ b/public/-/emojis/2/man_dancing_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/man_dancing_tone5.png b/public/-/emojis/2/man_dancing_tone5.png
new file mode 100644
index 00000000000..16da682d8e3
--- /dev/null
+++ b/public/-/emojis/2/man_dancing_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/man_in_tuxedo.png b/public/-/emojis/2/man_in_tuxedo.png
new file mode 100644
index 00000000000..15cfc08f5c2
--- /dev/null
+++ b/public/-/emojis/2/man_in_tuxedo.png
Binary files differ
diff --git a/public/-/emojis/2/man_in_tuxedo_tone1.png b/public/-/emojis/2/man_in_tuxedo_tone1.png
new file mode 100644
index 00000000000..18a24c9571f
--- /dev/null
+++ b/public/-/emojis/2/man_in_tuxedo_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/man_in_tuxedo_tone2.png b/public/-/emojis/2/man_in_tuxedo_tone2.png
new file mode 100644
index 00000000000..2de8e0a8aa2
--- /dev/null
+++ b/public/-/emojis/2/man_in_tuxedo_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/man_in_tuxedo_tone3.png b/public/-/emojis/2/man_in_tuxedo_tone3.png
new file mode 100644
index 00000000000..35b10680ac3
--- /dev/null
+++ b/public/-/emojis/2/man_in_tuxedo_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/man_in_tuxedo_tone4.png b/public/-/emojis/2/man_in_tuxedo_tone4.png
new file mode 100644
index 00000000000..569bf7c6928
--- /dev/null
+++ b/public/-/emojis/2/man_in_tuxedo_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/man_in_tuxedo_tone5.png b/public/-/emojis/2/man_in_tuxedo_tone5.png
new file mode 100644
index 00000000000..d3f0518b4b7
--- /dev/null
+++ b/public/-/emojis/2/man_in_tuxedo_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/man_tone1.png b/public/-/emojis/2/man_tone1.png
new file mode 100644
index 00000000000..d7b3233ccfd
--- /dev/null
+++ b/public/-/emojis/2/man_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/man_tone2.png b/public/-/emojis/2/man_tone2.png
new file mode 100644
index 00000000000..4713c4e89a7
--- /dev/null
+++ b/public/-/emojis/2/man_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/man_tone3.png b/public/-/emojis/2/man_tone3.png
new file mode 100644
index 00000000000..4c2b28426be
--- /dev/null
+++ b/public/-/emojis/2/man_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/man_tone4.png b/public/-/emojis/2/man_tone4.png
new file mode 100644
index 00000000000..91f19b75c5e
--- /dev/null
+++ b/public/-/emojis/2/man_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/man_tone5.png b/public/-/emojis/2/man_tone5.png
new file mode 100644
index 00000000000..5fe2741efb8
--- /dev/null
+++ b/public/-/emojis/2/man_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/man_with_gua_pi_mao.png b/public/-/emojis/2/man_with_gua_pi_mao.png
new file mode 100644
index 00000000000..986a82d38cb
--- /dev/null
+++ b/public/-/emojis/2/man_with_gua_pi_mao.png
Binary files differ
diff --git a/public/-/emojis/2/man_with_gua_pi_mao_tone1.png b/public/-/emojis/2/man_with_gua_pi_mao_tone1.png
new file mode 100644
index 00000000000..6657368cc73
--- /dev/null
+++ b/public/-/emojis/2/man_with_gua_pi_mao_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/man_with_gua_pi_mao_tone2.png b/public/-/emojis/2/man_with_gua_pi_mao_tone2.png
new file mode 100644
index 00000000000..822a6b18309
--- /dev/null
+++ b/public/-/emojis/2/man_with_gua_pi_mao_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/man_with_gua_pi_mao_tone3.png b/public/-/emojis/2/man_with_gua_pi_mao_tone3.png
new file mode 100644
index 00000000000..ec53dc12c14
--- /dev/null
+++ b/public/-/emojis/2/man_with_gua_pi_mao_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/man_with_gua_pi_mao_tone4.png b/public/-/emojis/2/man_with_gua_pi_mao_tone4.png
new file mode 100644
index 00000000000..e454dcbf25f
--- /dev/null
+++ b/public/-/emojis/2/man_with_gua_pi_mao_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/man_with_gua_pi_mao_tone5.png b/public/-/emojis/2/man_with_gua_pi_mao_tone5.png
new file mode 100644
index 00000000000..15e5d9238e8
--- /dev/null
+++ b/public/-/emojis/2/man_with_gua_pi_mao_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/man_with_turban.png b/public/-/emojis/2/man_with_turban.png
new file mode 100644
index 00000000000..4fdf66b58be
--- /dev/null
+++ b/public/-/emojis/2/man_with_turban.png
Binary files differ
diff --git a/public/-/emojis/2/man_with_turban_tone1.png b/public/-/emojis/2/man_with_turban_tone1.png
new file mode 100644
index 00000000000..e018f241027
--- /dev/null
+++ b/public/-/emojis/2/man_with_turban_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/man_with_turban_tone2.png b/public/-/emojis/2/man_with_turban_tone2.png
new file mode 100644
index 00000000000..84fdcdeeeef
--- /dev/null
+++ b/public/-/emojis/2/man_with_turban_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/man_with_turban_tone3.png b/public/-/emojis/2/man_with_turban_tone3.png
new file mode 100644
index 00000000000..f3bb33a49c3
--- /dev/null
+++ b/public/-/emojis/2/man_with_turban_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/man_with_turban_tone4.png b/public/-/emojis/2/man_with_turban_tone4.png
new file mode 100644
index 00000000000..e718321068f
--- /dev/null
+++ b/public/-/emojis/2/man_with_turban_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/man_with_turban_tone5.png b/public/-/emojis/2/man_with_turban_tone5.png
new file mode 100644
index 00000000000..0c7c9c80150
--- /dev/null
+++ b/public/-/emojis/2/man_with_turban_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/mans_shoe.png b/public/-/emojis/2/mans_shoe.png
new file mode 100644
index 00000000000..e8bc1d237c0
--- /dev/null
+++ b/public/-/emojis/2/mans_shoe.png
Binary files differ
diff --git a/public/-/emojis/2/map.png b/public/-/emojis/2/map.png
new file mode 100644
index 00000000000..609a7da92d5
--- /dev/null
+++ b/public/-/emojis/2/map.png
Binary files differ
diff --git a/public/-/emojis/2/maple_leaf.png b/public/-/emojis/2/maple_leaf.png
new file mode 100644
index 00000000000..b79b9d4b8f8
--- /dev/null
+++ b/public/-/emojis/2/maple_leaf.png
Binary files differ
diff --git a/public/-/emojis/2/martial_arts_uniform.png b/public/-/emojis/2/martial_arts_uniform.png
new file mode 100644
index 00000000000..813c890ec96
--- /dev/null
+++ b/public/-/emojis/2/martial_arts_uniform.png
Binary files differ
diff --git a/public/-/emojis/2/mask.png b/public/-/emojis/2/mask.png
new file mode 100644
index 00000000000..fa1ef6f7191
--- /dev/null
+++ b/public/-/emojis/2/mask.png
Binary files differ
diff --git a/public/-/emojis/2/massage.png b/public/-/emojis/2/massage.png
new file mode 100644
index 00000000000..e2592063d1e
--- /dev/null
+++ b/public/-/emojis/2/massage.png
Binary files differ
diff --git a/public/-/emojis/2/massage_tone1.png b/public/-/emojis/2/massage_tone1.png
new file mode 100644
index 00000000000..cc9dcfea166
--- /dev/null
+++ b/public/-/emojis/2/massage_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/massage_tone2.png b/public/-/emojis/2/massage_tone2.png
new file mode 100644
index 00000000000..108603a7f79
--- /dev/null
+++ b/public/-/emojis/2/massage_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/massage_tone3.png b/public/-/emojis/2/massage_tone3.png
new file mode 100644
index 00000000000..5c81192b6ee
--- /dev/null
+++ b/public/-/emojis/2/massage_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/massage_tone4.png b/public/-/emojis/2/massage_tone4.png
new file mode 100644
index 00000000000..64f3bbb8086
--- /dev/null
+++ b/public/-/emojis/2/massage_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/massage_tone5.png b/public/-/emojis/2/massage_tone5.png
new file mode 100644
index 00000000000..738fde080ab
--- /dev/null
+++ b/public/-/emojis/2/massage_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/meat_on_bone.png b/public/-/emojis/2/meat_on_bone.png
new file mode 100644
index 00000000000..38e9b730868
--- /dev/null
+++ b/public/-/emojis/2/meat_on_bone.png
Binary files differ
diff --git a/public/-/emojis/2/medal.png b/public/-/emojis/2/medal.png
new file mode 100644
index 00000000000..0b8a681f8a3
--- /dev/null
+++ b/public/-/emojis/2/medal.png
Binary files differ
diff --git a/public/-/emojis/2/mega.png b/public/-/emojis/2/mega.png
new file mode 100644
index 00000000000..729f1d6062e
--- /dev/null
+++ b/public/-/emojis/2/mega.png
Binary files differ
diff --git a/public/-/emojis/2/melon.png b/public/-/emojis/2/melon.png
new file mode 100644
index 00000000000..4bf92d03233
--- /dev/null
+++ b/public/-/emojis/2/melon.png
Binary files differ
diff --git a/public/-/emojis/2/menorah.png b/public/-/emojis/2/menorah.png
new file mode 100644
index 00000000000..6acfdd9dfdd
--- /dev/null
+++ b/public/-/emojis/2/menorah.png
Binary files differ
diff --git a/public/-/emojis/2/mens.png b/public/-/emojis/2/mens.png
new file mode 100644
index 00000000000..fcdeea081d2
--- /dev/null
+++ b/public/-/emojis/2/mens.png
Binary files differ
diff --git a/public/-/emojis/2/metal.png b/public/-/emojis/2/metal.png
new file mode 100644
index 00000000000..aa16a05280f
--- /dev/null
+++ b/public/-/emojis/2/metal.png
Binary files differ
diff --git a/public/-/emojis/2/metal_tone1.png b/public/-/emojis/2/metal_tone1.png
new file mode 100644
index 00000000000..e21cf74fb44
--- /dev/null
+++ b/public/-/emojis/2/metal_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/metal_tone2.png b/public/-/emojis/2/metal_tone2.png
new file mode 100644
index 00000000000..8f3e405c249
--- /dev/null
+++ b/public/-/emojis/2/metal_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/metal_tone3.png b/public/-/emojis/2/metal_tone3.png
new file mode 100644
index 00000000000..17c7e61b1a1
--- /dev/null
+++ b/public/-/emojis/2/metal_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/metal_tone4.png b/public/-/emojis/2/metal_tone4.png
new file mode 100644
index 00000000000..377ee61c6b7
--- /dev/null
+++ b/public/-/emojis/2/metal_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/metal_tone5.png b/public/-/emojis/2/metal_tone5.png
new file mode 100644
index 00000000000..3538e4a0634
--- /dev/null
+++ b/public/-/emojis/2/metal_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/metro.png b/public/-/emojis/2/metro.png
new file mode 100644
index 00000000000..5b46fff041c
--- /dev/null
+++ b/public/-/emojis/2/metro.png
Binary files differ
diff --git a/public/-/emojis/2/microphone.png b/public/-/emojis/2/microphone.png
new file mode 100644
index 00000000000..2fa4b55cce5
--- /dev/null
+++ b/public/-/emojis/2/microphone.png
Binary files differ
diff --git a/public/-/emojis/2/microphone2.png b/public/-/emojis/2/microphone2.png
new file mode 100644
index 00000000000..8de74839976
--- /dev/null
+++ b/public/-/emojis/2/microphone2.png
Binary files differ
diff --git a/public/-/emojis/2/microscope.png b/public/-/emojis/2/microscope.png
new file mode 100644
index 00000000000..a43f3f862c3
--- /dev/null
+++ b/public/-/emojis/2/microscope.png
Binary files differ
diff --git a/public/-/emojis/2/middle_finger.png b/public/-/emojis/2/middle_finger.png
new file mode 100644
index 00000000000..cadd7de4b1e
--- /dev/null
+++ b/public/-/emojis/2/middle_finger.png
Binary files differ
diff --git a/public/-/emojis/2/middle_finger_tone1.png b/public/-/emojis/2/middle_finger_tone1.png
new file mode 100644
index 00000000000..2c2b63095c7
--- /dev/null
+++ b/public/-/emojis/2/middle_finger_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/middle_finger_tone2.png b/public/-/emojis/2/middle_finger_tone2.png
new file mode 100644
index 00000000000..33a47b9bd7f
--- /dev/null
+++ b/public/-/emojis/2/middle_finger_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/middle_finger_tone3.png b/public/-/emojis/2/middle_finger_tone3.png
new file mode 100644
index 00000000000..209224ab4e4
--- /dev/null
+++ b/public/-/emojis/2/middle_finger_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/middle_finger_tone4.png b/public/-/emojis/2/middle_finger_tone4.png
new file mode 100644
index 00000000000..438793f2ee0
--- /dev/null
+++ b/public/-/emojis/2/middle_finger_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/middle_finger_tone5.png b/public/-/emojis/2/middle_finger_tone5.png
new file mode 100644
index 00000000000..91eb77d1857
--- /dev/null
+++ b/public/-/emojis/2/middle_finger_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/military_medal.png b/public/-/emojis/2/military_medal.png
new file mode 100644
index 00000000000..e78c6fa87e0
--- /dev/null
+++ b/public/-/emojis/2/military_medal.png
Binary files differ
diff --git a/public/-/emojis/2/milk.png b/public/-/emojis/2/milk.png
new file mode 100644
index 00000000000..ea6fae69ed7
--- /dev/null
+++ b/public/-/emojis/2/milk.png
Binary files differ
diff --git a/public/-/emojis/2/milky_way.png b/public/-/emojis/2/milky_way.png
new file mode 100644
index 00000000000..b769796a96c
--- /dev/null
+++ b/public/-/emojis/2/milky_way.png
Binary files differ
diff --git a/public/-/emojis/2/minibus.png b/public/-/emojis/2/minibus.png
new file mode 100644
index 00000000000..799a2eeac72
--- /dev/null
+++ b/public/-/emojis/2/minibus.png
Binary files differ
diff --git a/public/-/emojis/2/minidisc.png b/public/-/emojis/2/minidisc.png
new file mode 100644
index 00000000000..7ee33d5be5e
--- /dev/null
+++ b/public/-/emojis/2/minidisc.png
Binary files differ
diff --git a/public/-/emojis/2/mobile_phone_off.png b/public/-/emojis/2/mobile_phone_off.png
new file mode 100644
index 00000000000..9fe93dffcb9
--- /dev/null
+++ b/public/-/emojis/2/mobile_phone_off.png
Binary files differ
diff --git a/public/-/emojis/2/money_mouth.png b/public/-/emojis/2/money_mouth.png
new file mode 100644
index 00000000000..9ec050c9c62
--- /dev/null
+++ b/public/-/emojis/2/money_mouth.png
Binary files differ
diff --git a/public/-/emojis/2/money_with_wings.png b/public/-/emojis/2/money_with_wings.png
new file mode 100644
index 00000000000..245b84584b2
--- /dev/null
+++ b/public/-/emojis/2/money_with_wings.png
Binary files differ
diff --git a/public/-/emojis/2/moneybag.png b/public/-/emojis/2/moneybag.png
new file mode 100644
index 00000000000..1d7a8cd2a02
--- /dev/null
+++ b/public/-/emojis/2/moneybag.png
Binary files differ
diff --git a/public/-/emojis/2/monkey.png b/public/-/emojis/2/monkey.png
new file mode 100644
index 00000000000..f8b4d6a6ccf
--- /dev/null
+++ b/public/-/emojis/2/monkey.png
Binary files differ
diff --git a/public/-/emojis/2/monkey_face.png b/public/-/emojis/2/monkey_face.png
new file mode 100644
index 00000000000..cbab205225d
--- /dev/null
+++ b/public/-/emojis/2/monkey_face.png
Binary files differ
diff --git a/public/-/emojis/2/monorail.png b/public/-/emojis/2/monorail.png
new file mode 100644
index 00000000000..71b9947f085
--- /dev/null
+++ b/public/-/emojis/2/monorail.png
Binary files differ
diff --git a/public/-/emojis/2/mortar_board.png b/public/-/emojis/2/mortar_board.png
new file mode 100644
index 00000000000..150e02378a6
--- /dev/null
+++ b/public/-/emojis/2/mortar_board.png
Binary files differ
diff --git a/public/-/emojis/2/mosque.png b/public/-/emojis/2/mosque.png
new file mode 100644
index 00000000000..cd8e6fac4cd
--- /dev/null
+++ b/public/-/emojis/2/mosque.png
Binary files differ
diff --git a/public/-/emojis/2/motor_scooter.png b/public/-/emojis/2/motor_scooter.png
new file mode 100644
index 00000000000..831d6ea9800
--- /dev/null
+++ b/public/-/emojis/2/motor_scooter.png
Binary files differ
diff --git a/public/-/emojis/2/motorboat.png b/public/-/emojis/2/motorboat.png
new file mode 100644
index 00000000000..9e8a605b814
--- /dev/null
+++ b/public/-/emojis/2/motorboat.png
Binary files differ
diff --git a/public/-/emojis/2/motorcycle.png b/public/-/emojis/2/motorcycle.png
new file mode 100644
index 00000000000..669a050d5b4
--- /dev/null
+++ b/public/-/emojis/2/motorcycle.png
Binary files differ
diff --git a/public/-/emojis/2/motorway.png b/public/-/emojis/2/motorway.png
new file mode 100644
index 00000000000..abb88ad9418
--- /dev/null
+++ b/public/-/emojis/2/motorway.png
Binary files differ
diff --git a/public/-/emojis/2/mount_fuji.png b/public/-/emojis/2/mount_fuji.png
new file mode 100644
index 00000000000..696499ed762
--- /dev/null
+++ b/public/-/emojis/2/mount_fuji.png
Binary files differ
diff --git a/public/-/emojis/2/mountain.png b/public/-/emojis/2/mountain.png
new file mode 100644
index 00000000000..3156894f243
--- /dev/null
+++ b/public/-/emojis/2/mountain.png
Binary files differ
diff --git a/public/-/emojis/2/mountain_bicyclist.png b/public/-/emojis/2/mountain_bicyclist.png
new file mode 100644
index 00000000000..724f811a817
--- /dev/null
+++ b/public/-/emojis/2/mountain_bicyclist.png
Binary files differ
diff --git a/public/-/emojis/2/mountain_bicyclist_tone1.png b/public/-/emojis/2/mountain_bicyclist_tone1.png
new file mode 100644
index 00000000000..c36a951c8b3
--- /dev/null
+++ b/public/-/emojis/2/mountain_bicyclist_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/mountain_bicyclist_tone2.png b/public/-/emojis/2/mountain_bicyclist_tone2.png
new file mode 100644
index 00000000000..e60847a02f0
--- /dev/null
+++ b/public/-/emojis/2/mountain_bicyclist_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/mountain_bicyclist_tone3.png b/public/-/emojis/2/mountain_bicyclist_tone3.png
new file mode 100644
index 00000000000..1f4e071bc5a
--- /dev/null
+++ b/public/-/emojis/2/mountain_bicyclist_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/mountain_bicyclist_tone4.png b/public/-/emojis/2/mountain_bicyclist_tone4.png
new file mode 100644
index 00000000000..b9698a9e76b
--- /dev/null
+++ b/public/-/emojis/2/mountain_bicyclist_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/mountain_bicyclist_tone5.png b/public/-/emojis/2/mountain_bicyclist_tone5.png
new file mode 100644
index 00000000000..79fe186755c
--- /dev/null
+++ b/public/-/emojis/2/mountain_bicyclist_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/mountain_cableway.png b/public/-/emojis/2/mountain_cableway.png
new file mode 100644
index 00000000000..6a23c7d3903
--- /dev/null
+++ b/public/-/emojis/2/mountain_cableway.png
Binary files differ
diff --git a/public/-/emojis/2/mountain_railway.png b/public/-/emojis/2/mountain_railway.png
new file mode 100644
index 00000000000..369b2e347da
--- /dev/null
+++ b/public/-/emojis/2/mountain_railway.png
Binary files differ
diff --git a/public/-/emojis/2/mountain_snow.png b/public/-/emojis/2/mountain_snow.png
new file mode 100644
index 00000000000..93a2a5f4157
--- /dev/null
+++ b/public/-/emojis/2/mountain_snow.png
Binary files differ
diff --git a/public/-/emojis/2/mouse.png b/public/-/emojis/2/mouse.png
new file mode 100644
index 00000000000..9250e474b02
--- /dev/null
+++ b/public/-/emojis/2/mouse.png
Binary files differ
diff --git a/public/-/emojis/2/mouse2.png b/public/-/emojis/2/mouse2.png
new file mode 100644
index 00000000000..bea98407263
--- /dev/null
+++ b/public/-/emojis/2/mouse2.png
Binary files differ
diff --git a/public/-/emojis/2/mouse_three_button.png b/public/-/emojis/2/mouse_three_button.png
new file mode 100644
index 00000000000..fe51db1fb37
--- /dev/null
+++ b/public/-/emojis/2/mouse_three_button.png
Binary files differ
diff --git a/public/-/emojis/2/movie_camera.png b/public/-/emojis/2/movie_camera.png
new file mode 100644
index 00000000000..7dff4477ade
--- /dev/null
+++ b/public/-/emojis/2/movie_camera.png
Binary files differ
diff --git a/public/-/emojis/2/moyai.png b/public/-/emojis/2/moyai.png
new file mode 100644
index 00000000000..1ab5cec7a08
--- /dev/null
+++ b/public/-/emojis/2/moyai.png
Binary files differ
diff --git a/public/-/emojis/2/mrs_claus.png b/public/-/emojis/2/mrs_claus.png
new file mode 100644
index 00000000000..f1680c9fb33
--- /dev/null
+++ b/public/-/emojis/2/mrs_claus.png
Binary files differ
diff --git a/public/-/emojis/2/mrs_claus_tone1.png b/public/-/emojis/2/mrs_claus_tone1.png
new file mode 100644
index 00000000000..26c7f27e75f
--- /dev/null
+++ b/public/-/emojis/2/mrs_claus_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/mrs_claus_tone2.png b/public/-/emojis/2/mrs_claus_tone2.png
new file mode 100644
index 00000000000..e9e0908ca0a
--- /dev/null
+++ b/public/-/emojis/2/mrs_claus_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/mrs_claus_tone3.png b/public/-/emojis/2/mrs_claus_tone3.png
new file mode 100644
index 00000000000..b464380985c
--- /dev/null
+++ b/public/-/emojis/2/mrs_claus_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/mrs_claus_tone4.png b/public/-/emojis/2/mrs_claus_tone4.png
new file mode 100644
index 00000000000..ac8a014dbd3
--- /dev/null
+++ b/public/-/emojis/2/mrs_claus_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/mrs_claus_tone5.png b/public/-/emojis/2/mrs_claus_tone5.png
new file mode 100644
index 00000000000..2d998498375
--- /dev/null
+++ b/public/-/emojis/2/mrs_claus_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/muscle.png b/public/-/emojis/2/muscle.png
new file mode 100644
index 00000000000..b40eccccba6
--- /dev/null
+++ b/public/-/emojis/2/muscle.png
Binary files differ
diff --git a/public/-/emojis/2/muscle_tone1.png b/public/-/emojis/2/muscle_tone1.png
new file mode 100644
index 00000000000..d971d331bfc
--- /dev/null
+++ b/public/-/emojis/2/muscle_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/muscle_tone2.png b/public/-/emojis/2/muscle_tone2.png
new file mode 100644
index 00000000000..dfb2c9697d3
--- /dev/null
+++ b/public/-/emojis/2/muscle_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/muscle_tone3.png b/public/-/emojis/2/muscle_tone3.png
new file mode 100644
index 00000000000..a528d2a27c7
--- /dev/null
+++ b/public/-/emojis/2/muscle_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/muscle_tone4.png b/public/-/emojis/2/muscle_tone4.png
new file mode 100644
index 00000000000..b3b5cd54e8b
--- /dev/null
+++ b/public/-/emojis/2/muscle_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/muscle_tone5.png b/public/-/emojis/2/muscle_tone5.png
new file mode 100644
index 00000000000..b98fa1b2af3
--- /dev/null
+++ b/public/-/emojis/2/muscle_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/mushroom.png b/public/-/emojis/2/mushroom.png
new file mode 100644
index 00000000000..989372ef8ce
--- /dev/null
+++ b/public/-/emojis/2/mushroom.png
Binary files differ
diff --git a/public/-/emojis/2/musical_keyboard.png b/public/-/emojis/2/musical_keyboard.png
new file mode 100644
index 00000000000..3b5bb2f0af2
--- /dev/null
+++ b/public/-/emojis/2/musical_keyboard.png
Binary files differ
diff --git a/public/-/emojis/2/musical_note.png b/public/-/emojis/2/musical_note.png
new file mode 100644
index 00000000000..7316152de60
--- /dev/null
+++ b/public/-/emojis/2/musical_note.png
Binary files differ
diff --git a/public/-/emojis/2/musical_score.png b/public/-/emojis/2/musical_score.png
new file mode 100644
index 00000000000..d3ec8b4a9cb
--- /dev/null
+++ b/public/-/emojis/2/musical_score.png
Binary files differ
diff --git a/public/-/emojis/2/mute.png b/public/-/emojis/2/mute.png
new file mode 100644
index 00000000000..62b1ab9dbbb
--- /dev/null
+++ b/public/-/emojis/2/mute.png
Binary files differ
diff --git a/public/-/emojis/2/nail_care.png b/public/-/emojis/2/nail_care.png
new file mode 100644
index 00000000000..58af69b130e
--- /dev/null
+++ b/public/-/emojis/2/nail_care.png
Binary files differ
diff --git a/public/-/emojis/2/nail_care_tone1.png b/public/-/emojis/2/nail_care_tone1.png
new file mode 100644
index 00000000000..127e7311df1
--- /dev/null
+++ b/public/-/emojis/2/nail_care_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/nail_care_tone2.png b/public/-/emojis/2/nail_care_tone2.png
new file mode 100644
index 00000000000..7463b7f36f7
--- /dev/null
+++ b/public/-/emojis/2/nail_care_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/nail_care_tone3.png b/public/-/emojis/2/nail_care_tone3.png
new file mode 100644
index 00000000000..335c23402e1
--- /dev/null
+++ b/public/-/emojis/2/nail_care_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/nail_care_tone4.png b/public/-/emojis/2/nail_care_tone4.png
new file mode 100644
index 00000000000..516732c6e6c
--- /dev/null
+++ b/public/-/emojis/2/nail_care_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/nail_care_tone5.png b/public/-/emojis/2/nail_care_tone5.png
new file mode 100644
index 00000000000..40beb2c2bf5
--- /dev/null
+++ b/public/-/emojis/2/nail_care_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/name_badge.png b/public/-/emojis/2/name_badge.png
new file mode 100644
index 00000000000..7a6314f3470
--- /dev/null
+++ b/public/-/emojis/2/name_badge.png
Binary files differ
diff --git a/public/-/emojis/2/nauseated_face.png b/public/-/emojis/2/nauseated_face.png
new file mode 100644
index 00000000000..aff0287a9bf
--- /dev/null
+++ b/public/-/emojis/2/nauseated_face.png
Binary files differ
diff --git a/public/-/emojis/2/necktie.png b/public/-/emojis/2/necktie.png
new file mode 100644
index 00000000000..e2fcfe233a1
--- /dev/null
+++ b/public/-/emojis/2/necktie.png
Binary files differ
diff --git a/public/-/emojis/2/negative_squared_cross_mark.png b/public/-/emojis/2/negative_squared_cross_mark.png
new file mode 100644
index 00000000000..9165fb916e5
--- /dev/null
+++ b/public/-/emojis/2/negative_squared_cross_mark.png
Binary files differ
diff --git a/public/-/emojis/2/nerd.png b/public/-/emojis/2/nerd.png
new file mode 100644
index 00000000000..f0b8d4807a6
--- /dev/null
+++ b/public/-/emojis/2/nerd.png
Binary files differ
diff --git a/public/-/emojis/2/neutral_face.png b/public/-/emojis/2/neutral_face.png
new file mode 100644
index 00000000000..4dca04fdfc4
--- /dev/null
+++ b/public/-/emojis/2/neutral_face.png
Binary files differ
diff --git a/public/-/emojis/2/new.png b/public/-/emojis/2/new.png
new file mode 100644
index 00000000000..fc11fea7251
--- /dev/null
+++ b/public/-/emojis/2/new.png
Binary files differ
diff --git a/public/-/emojis/2/new_moon.png b/public/-/emojis/2/new_moon.png
new file mode 100644
index 00000000000..699e2283aaa
--- /dev/null
+++ b/public/-/emojis/2/new_moon.png
Binary files differ
diff --git a/public/-/emojis/2/new_moon_with_face.png b/public/-/emojis/2/new_moon_with_face.png
new file mode 100644
index 00000000000..5863644ce97
--- /dev/null
+++ b/public/-/emojis/2/new_moon_with_face.png
Binary files differ
diff --git a/public/-/emojis/2/newspaper.png b/public/-/emojis/2/newspaper.png
new file mode 100644
index 00000000000..1b72b5592a4
--- /dev/null
+++ b/public/-/emojis/2/newspaper.png
Binary files differ
diff --git a/public/-/emojis/2/newspaper2.png b/public/-/emojis/2/newspaper2.png
new file mode 100644
index 00000000000..13e9f54d42b
--- /dev/null
+++ b/public/-/emojis/2/newspaper2.png
Binary files differ
diff --git a/public/-/emojis/2/ng.png b/public/-/emojis/2/ng.png
new file mode 100644
index 00000000000..4ccf0e104c1
--- /dev/null
+++ b/public/-/emojis/2/ng.png
Binary files differ
diff --git a/public/-/emojis/2/night_with_stars.png b/public/-/emojis/2/night_with_stars.png
new file mode 100644
index 00000000000..3c44cb2308e
--- /dev/null
+++ b/public/-/emojis/2/night_with_stars.png
Binary files differ
diff --git a/public/-/emojis/2/nine.png b/public/-/emojis/2/nine.png
new file mode 100644
index 00000000000..178adebc883
--- /dev/null
+++ b/public/-/emojis/2/nine.png
Binary files differ
diff --git a/public/-/emojis/2/no_bell.png b/public/-/emojis/2/no_bell.png
new file mode 100644
index 00000000000..70800056224
--- /dev/null
+++ b/public/-/emojis/2/no_bell.png
Binary files differ
diff --git a/public/-/emojis/2/no_bicycles.png b/public/-/emojis/2/no_bicycles.png
new file mode 100644
index 00000000000..e77283eec67
--- /dev/null
+++ b/public/-/emojis/2/no_bicycles.png
Binary files differ
diff --git a/public/-/emojis/2/no_entry.png b/public/-/emojis/2/no_entry.png
new file mode 100644
index 00000000000..5fe52435ba3
--- /dev/null
+++ b/public/-/emojis/2/no_entry.png
Binary files differ
diff --git a/public/-/emojis/2/no_entry_sign.png b/public/-/emojis/2/no_entry_sign.png
new file mode 100644
index 00000000000..d36a461aaef
--- /dev/null
+++ b/public/-/emojis/2/no_entry_sign.png
Binary files differ
diff --git a/public/-/emojis/2/no_good.png b/public/-/emojis/2/no_good.png
new file mode 100644
index 00000000000..0e7a9ca57c5
--- /dev/null
+++ b/public/-/emojis/2/no_good.png
Binary files differ
diff --git a/public/-/emojis/2/no_good_tone1.png b/public/-/emojis/2/no_good_tone1.png
new file mode 100644
index 00000000000..054522577a9
--- /dev/null
+++ b/public/-/emojis/2/no_good_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/no_good_tone2.png b/public/-/emojis/2/no_good_tone2.png
new file mode 100644
index 00000000000..7b002ccddd9
--- /dev/null
+++ b/public/-/emojis/2/no_good_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/no_good_tone3.png b/public/-/emojis/2/no_good_tone3.png
new file mode 100644
index 00000000000..39bb63f75e4
--- /dev/null
+++ b/public/-/emojis/2/no_good_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/no_good_tone4.png b/public/-/emojis/2/no_good_tone4.png
new file mode 100644
index 00000000000..e0d16713730
--- /dev/null
+++ b/public/-/emojis/2/no_good_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/no_good_tone5.png b/public/-/emojis/2/no_good_tone5.png
new file mode 100644
index 00000000000..cc7c1829b96
--- /dev/null
+++ b/public/-/emojis/2/no_good_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/no_mobile_phones.png b/public/-/emojis/2/no_mobile_phones.png
new file mode 100644
index 00000000000..8e375d76df0
--- /dev/null
+++ b/public/-/emojis/2/no_mobile_phones.png
Binary files differ
diff --git a/public/-/emojis/2/no_mouth.png b/public/-/emojis/2/no_mouth.png
new file mode 100644
index 00000000000..1e67ba3e048
--- /dev/null
+++ b/public/-/emojis/2/no_mouth.png
Binary files differ
diff --git a/public/-/emojis/2/no_pedestrians.png b/public/-/emojis/2/no_pedestrians.png
new file mode 100644
index 00000000000..3673e73d99c
--- /dev/null
+++ b/public/-/emojis/2/no_pedestrians.png
Binary files differ
diff --git a/public/-/emojis/2/no_smoking.png b/public/-/emojis/2/no_smoking.png
new file mode 100644
index 00000000000..28df4476795
--- /dev/null
+++ b/public/-/emojis/2/no_smoking.png
Binary files differ
diff --git a/public/-/emojis/2/non-potable_water.png b/public/-/emojis/2/non-potable_water.png
new file mode 100644
index 00000000000..c3a838989df
--- /dev/null
+++ b/public/-/emojis/2/non-potable_water.png
Binary files differ
diff --git a/public/-/emojis/2/nose.png b/public/-/emojis/2/nose.png
new file mode 100644
index 00000000000..d554d8266de
--- /dev/null
+++ b/public/-/emojis/2/nose.png
Binary files differ
diff --git a/public/-/emojis/2/nose_tone1.png b/public/-/emojis/2/nose_tone1.png
new file mode 100644
index 00000000000..bb9b0e32c0e
--- /dev/null
+++ b/public/-/emojis/2/nose_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/nose_tone2.png b/public/-/emojis/2/nose_tone2.png
new file mode 100644
index 00000000000..ab33c2f7856
--- /dev/null
+++ b/public/-/emojis/2/nose_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/nose_tone3.png b/public/-/emojis/2/nose_tone3.png
new file mode 100644
index 00000000000..5e21cce930d
--- /dev/null
+++ b/public/-/emojis/2/nose_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/nose_tone4.png b/public/-/emojis/2/nose_tone4.png
new file mode 100644
index 00000000000..edff6c9b76f
--- /dev/null
+++ b/public/-/emojis/2/nose_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/nose_tone5.png b/public/-/emojis/2/nose_tone5.png
new file mode 100644
index 00000000000..be4fb9dd7aa
--- /dev/null
+++ b/public/-/emojis/2/nose_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/notebook.png b/public/-/emojis/2/notebook.png
new file mode 100644
index 00000000000..71ea5926049
--- /dev/null
+++ b/public/-/emojis/2/notebook.png
Binary files differ
diff --git a/public/-/emojis/2/notebook_with_decorative_cover.png b/public/-/emojis/2/notebook_with_decorative_cover.png
new file mode 100644
index 00000000000..9c19f162a5f
--- /dev/null
+++ b/public/-/emojis/2/notebook_with_decorative_cover.png
Binary files differ
diff --git a/public/-/emojis/2/notepad_spiral.png b/public/-/emojis/2/notepad_spiral.png
new file mode 100644
index 00000000000..cd157e1f075
--- /dev/null
+++ b/public/-/emojis/2/notepad_spiral.png
Binary files differ
diff --git a/public/-/emojis/2/notes.png b/public/-/emojis/2/notes.png
new file mode 100644
index 00000000000..b2ccdb4fdfe
--- /dev/null
+++ b/public/-/emojis/2/notes.png
Binary files differ
diff --git a/public/-/emojis/2/nut_and_bolt.png b/public/-/emojis/2/nut_and_bolt.png
new file mode 100644
index 00000000000..12f315b42dc
--- /dev/null
+++ b/public/-/emojis/2/nut_and_bolt.png
Binary files differ
diff --git a/public/-/emojis/2/o.png b/public/-/emojis/2/o.png
new file mode 100644
index 00000000000..60d3a67b7a1
--- /dev/null
+++ b/public/-/emojis/2/o.png
Binary files differ
diff --git a/public/-/emojis/2/o2.png b/public/-/emojis/2/o2.png
new file mode 100644
index 00000000000..396f10bc7a1
--- /dev/null
+++ b/public/-/emojis/2/o2.png
Binary files differ
diff --git a/public/-/emojis/2/ocean.png b/public/-/emojis/2/ocean.png
new file mode 100644
index 00000000000..326120f06ae
--- /dev/null
+++ b/public/-/emojis/2/ocean.png
Binary files differ
diff --git a/public/-/emojis/2/octagonal_sign.png b/public/-/emojis/2/octagonal_sign.png
new file mode 100644
index 00000000000..909917c79be
--- /dev/null
+++ b/public/-/emojis/2/octagonal_sign.png
Binary files differ
diff --git a/public/-/emojis/2/octopus.png b/public/-/emojis/2/octopus.png
new file mode 100644
index 00000000000..6e02be6bc65
--- /dev/null
+++ b/public/-/emojis/2/octopus.png
Binary files differ
diff --git a/public/-/emojis/2/oden.png b/public/-/emojis/2/oden.png
new file mode 100644
index 00000000000..8705452827f
--- /dev/null
+++ b/public/-/emojis/2/oden.png
Binary files differ
diff --git a/public/-/emojis/2/office.png b/public/-/emojis/2/office.png
new file mode 100644
index 00000000000..efc1b7fe17a
--- /dev/null
+++ b/public/-/emojis/2/office.png
Binary files differ
diff --git a/public/-/emojis/2/oil.png b/public/-/emojis/2/oil.png
new file mode 100644
index 00000000000..8141f0f4d77
--- /dev/null
+++ b/public/-/emojis/2/oil.png
Binary files differ
diff --git a/public/-/emojis/2/ok.png b/public/-/emojis/2/ok.png
new file mode 100644
index 00000000000..7ac40b38704
--- /dev/null
+++ b/public/-/emojis/2/ok.png
Binary files differ
diff --git a/public/-/emojis/2/ok_hand.png b/public/-/emojis/2/ok_hand.png
new file mode 100644
index 00000000000..cefc5583e4b
--- /dev/null
+++ b/public/-/emojis/2/ok_hand.png
Binary files differ
diff --git a/public/-/emojis/2/ok_hand_tone1.png b/public/-/emojis/2/ok_hand_tone1.png
new file mode 100644
index 00000000000..6ab2c4a0b30
--- /dev/null
+++ b/public/-/emojis/2/ok_hand_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/ok_hand_tone2.png b/public/-/emojis/2/ok_hand_tone2.png
new file mode 100644
index 00000000000..66d1f9e18a1
--- /dev/null
+++ b/public/-/emojis/2/ok_hand_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/ok_hand_tone3.png b/public/-/emojis/2/ok_hand_tone3.png
new file mode 100644
index 00000000000..d621900f510
--- /dev/null
+++ b/public/-/emojis/2/ok_hand_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/ok_hand_tone4.png b/public/-/emojis/2/ok_hand_tone4.png
new file mode 100644
index 00000000000..e5a04d44ff5
--- /dev/null
+++ b/public/-/emojis/2/ok_hand_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/ok_hand_tone5.png b/public/-/emojis/2/ok_hand_tone5.png
new file mode 100644
index 00000000000..2f8ee905c60
--- /dev/null
+++ b/public/-/emojis/2/ok_hand_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/ok_woman.png b/public/-/emojis/2/ok_woman.png
new file mode 100644
index 00000000000..13ba0e57483
--- /dev/null
+++ b/public/-/emojis/2/ok_woman.png
Binary files differ
diff --git a/public/-/emojis/2/ok_woman_tone1.png b/public/-/emojis/2/ok_woman_tone1.png
new file mode 100644
index 00000000000..5ed4b830368
--- /dev/null
+++ b/public/-/emojis/2/ok_woman_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/ok_woman_tone2.png b/public/-/emojis/2/ok_woman_tone2.png
new file mode 100644
index 00000000000..9ccd187d96f
--- /dev/null
+++ b/public/-/emojis/2/ok_woman_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/ok_woman_tone3.png b/public/-/emojis/2/ok_woman_tone3.png
new file mode 100644
index 00000000000..fa03cb6d59a
--- /dev/null
+++ b/public/-/emojis/2/ok_woman_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/ok_woman_tone4.png b/public/-/emojis/2/ok_woman_tone4.png
new file mode 100644
index 00000000000..d0dde591096
--- /dev/null
+++ b/public/-/emojis/2/ok_woman_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/ok_woman_tone5.png b/public/-/emojis/2/ok_woman_tone5.png
new file mode 100644
index 00000000000..7bba2590a87
--- /dev/null
+++ b/public/-/emojis/2/ok_woman_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/older_man.png b/public/-/emojis/2/older_man.png
new file mode 100644
index 00000000000..fdb37b455b0
--- /dev/null
+++ b/public/-/emojis/2/older_man.png
Binary files differ
diff --git a/public/-/emojis/2/older_man_tone1.png b/public/-/emojis/2/older_man_tone1.png
new file mode 100644
index 00000000000..282992bb73e
--- /dev/null
+++ b/public/-/emojis/2/older_man_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/older_man_tone2.png b/public/-/emojis/2/older_man_tone2.png
new file mode 100644
index 00000000000..28c013c40f8
--- /dev/null
+++ b/public/-/emojis/2/older_man_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/older_man_tone3.png b/public/-/emojis/2/older_man_tone3.png
new file mode 100644
index 00000000000..7af90cd6ea8
--- /dev/null
+++ b/public/-/emojis/2/older_man_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/older_man_tone4.png b/public/-/emojis/2/older_man_tone4.png
new file mode 100644
index 00000000000..c66b2711cf8
--- /dev/null
+++ b/public/-/emojis/2/older_man_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/older_man_tone5.png b/public/-/emojis/2/older_man_tone5.png
new file mode 100644
index 00000000000..86b09738a44
--- /dev/null
+++ b/public/-/emojis/2/older_man_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/older_woman.png b/public/-/emojis/2/older_woman.png
new file mode 100644
index 00000000000..f1d13148730
--- /dev/null
+++ b/public/-/emojis/2/older_woman.png
Binary files differ
diff --git a/public/-/emojis/2/older_woman_tone1.png b/public/-/emojis/2/older_woman_tone1.png
new file mode 100644
index 00000000000..bfb73101f61
--- /dev/null
+++ b/public/-/emojis/2/older_woman_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/older_woman_tone2.png b/public/-/emojis/2/older_woman_tone2.png
new file mode 100644
index 00000000000..c977015582d
--- /dev/null
+++ b/public/-/emojis/2/older_woman_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/older_woman_tone3.png b/public/-/emojis/2/older_woman_tone3.png
new file mode 100644
index 00000000000..cc7922077a4
--- /dev/null
+++ b/public/-/emojis/2/older_woman_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/older_woman_tone4.png b/public/-/emojis/2/older_woman_tone4.png
new file mode 100644
index 00000000000..77111bf20a6
--- /dev/null
+++ b/public/-/emojis/2/older_woman_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/older_woman_tone5.png b/public/-/emojis/2/older_woman_tone5.png
new file mode 100644
index 00000000000..26673b3df96
--- /dev/null
+++ b/public/-/emojis/2/older_woman_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/om_symbol.png b/public/-/emojis/2/om_symbol.png
new file mode 100644
index 00000000000..ce778fd4457
--- /dev/null
+++ b/public/-/emojis/2/om_symbol.png
Binary files differ
diff --git a/public/-/emojis/2/on.png b/public/-/emojis/2/on.png
new file mode 100644
index 00000000000..74fd6c584b8
--- /dev/null
+++ b/public/-/emojis/2/on.png
Binary files differ
diff --git a/public/-/emojis/2/oncoming_automobile.png b/public/-/emojis/2/oncoming_automobile.png
new file mode 100644
index 00000000000..8579ad86c3a
--- /dev/null
+++ b/public/-/emojis/2/oncoming_automobile.png
Binary files differ
diff --git a/public/-/emojis/2/oncoming_bus.png b/public/-/emojis/2/oncoming_bus.png
new file mode 100644
index 00000000000..0b9dc0544e8
--- /dev/null
+++ b/public/-/emojis/2/oncoming_bus.png
Binary files differ
diff --git a/public/-/emojis/2/oncoming_police_car.png b/public/-/emojis/2/oncoming_police_car.png
new file mode 100644
index 00000000000..b4e95c64bba
--- /dev/null
+++ b/public/-/emojis/2/oncoming_police_car.png
Binary files differ
diff --git a/public/-/emojis/2/oncoming_taxi.png b/public/-/emojis/2/oncoming_taxi.png
new file mode 100644
index 00000000000..9211b81d8d1
--- /dev/null
+++ b/public/-/emojis/2/oncoming_taxi.png
Binary files differ
diff --git a/public/-/emojis/2/one.png b/public/-/emojis/2/one.png
new file mode 100644
index 00000000000..2532afb6fcf
--- /dev/null
+++ b/public/-/emojis/2/one.png
Binary files differ
diff --git a/public/-/emojis/2/open_file_folder.png b/public/-/emojis/2/open_file_folder.png
new file mode 100644
index 00000000000..d33f2f40c9a
--- /dev/null
+++ b/public/-/emojis/2/open_file_folder.png
Binary files differ
diff --git a/public/-/emojis/2/open_hands.png b/public/-/emojis/2/open_hands.png
new file mode 100644
index 00000000000..d4bdccbe0b2
--- /dev/null
+++ b/public/-/emojis/2/open_hands.png
Binary files differ
diff --git a/public/-/emojis/2/open_hands_tone1.png b/public/-/emojis/2/open_hands_tone1.png
new file mode 100644
index 00000000000..1ba31eeb590
--- /dev/null
+++ b/public/-/emojis/2/open_hands_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/open_hands_tone2.png b/public/-/emojis/2/open_hands_tone2.png
new file mode 100644
index 00000000000..a74b5b4d5bf
--- /dev/null
+++ b/public/-/emojis/2/open_hands_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/open_hands_tone3.png b/public/-/emojis/2/open_hands_tone3.png
new file mode 100644
index 00000000000..5dc472da57e
--- /dev/null
+++ b/public/-/emojis/2/open_hands_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/open_hands_tone4.png b/public/-/emojis/2/open_hands_tone4.png
new file mode 100644
index 00000000000..435544a1f26
--- /dev/null
+++ b/public/-/emojis/2/open_hands_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/open_hands_tone5.png b/public/-/emojis/2/open_hands_tone5.png
new file mode 100644
index 00000000000..a5d516049ac
--- /dev/null
+++ b/public/-/emojis/2/open_hands_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/open_mouth.png b/public/-/emojis/2/open_mouth.png
new file mode 100644
index 00000000000..17fbef0c183
--- /dev/null
+++ b/public/-/emojis/2/open_mouth.png
Binary files differ
diff --git a/public/-/emojis/2/ophiuchus.png b/public/-/emojis/2/ophiuchus.png
new file mode 100644
index 00000000000..5e9a128b9af
--- /dev/null
+++ b/public/-/emojis/2/ophiuchus.png
Binary files differ
diff --git a/public/-/emojis/2/orange_book.png b/public/-/emojis/2/orange_book.png
new file mode 100644
index 00000000000..d673bc9aec5
--- /dev/null
+++ b/public/-/emojis/2/orange_book.png
Binary files differ
diff --git a/public/-/emojis/2/orthodox_cross.png b/public/-/emojis/2/orthodox_cross.png
new file mode 100644
index 00000000000..7ae9fcb33d1
--- /dev/null
+++ b/public/-/emojis/2/orthodox_cross.png
Binary files differ
diff --git a/public/-/emojis/2/outbox_tray.png b/public/-/emojis/2/outbox_tray.png
new file mode 100644
index 00000000000..0d0afbfeccb
--- /dev/null
+++ b/public/-/emojis/2/outbox_tray.png
Binary files differ
diff --git a/public/-/emojis/2/owl.png b/public/-/emojis/2/owl.png
new file mode 100644
index 00000000000..d559d46d75c
--- /dev/null
+++ b/public/-/emojis/2/owl.png
Binary files differ
diff --git a/public/-/emojis/2/ox.png b/public/-/emojis/2/ox.png
new file mode 100644
index 00000000000..539f49b8a2c
--- /dev/null
+++ b/public/-/emojis/2/ox.png
Binary files differ
diff --git a/public/-/emojis/2/package.png b/public/-/emojis/2/package.png
new file mode 100644
index 00000000000..cee076870bb
--- /dev/null
+++ b/public/-/emojis/2/package.png
Binary files differ
diff --git a/public/-/emojis/2/page_facing_up.png b/public/-/emojis/2/page_facing_up.png
new file mode 100644
index 00000000000..31e199da290
--- /dev/null
+++ b/public/-/emojis/2/page_facing_up.png
Binary files differ
diff --git a/public/-/emojis/2/page_with_curl.png b/public/-/emojis/2/page_with_curl.png
new file mode 100644
index 00000000000..b252e563dcf
--- /dev/null
+++ b/public/-/emojis/2/page_with_curl.png
Binary files differ
diff --git a/public/-/emojis/2/pager.png b/public/-/emojis/2/pager.png
new file mode 100644
index 00000000000..3fe3355c646
--- /dev/null
+++ b/public/-/emojis/2/pager.png
Binary files differ
diff --git a/public/-/emojis/2/paintbrush.png b/public/-/emojis/2/paintbrush.png
new file mode 100644
index 00000000000..b429269f18c
--- /dev/null
+++ b/public/-/emojis/2/paintbrush.png
Binary files differ
diff --git a/public/-/emojis/2/palm_tree.png b/public/-/emojis/2/palm_tree.png
new file mode 100644
index 00000000000..e26bc83032b
--- /dev/null
+++ b/public/-/emojis/2/palm_tree.png
Binary files differ
diff --git a/public/-/emojis/2/pancakes.png b/public/-/emojis/2/pancakes.png
new file mode 100644
index 00000000000..4906a19fcee
--- /dev/null
+++ b/public/-/emojis/2/pancakes.png
Binary files differ
diff --git a/public/-/emojis/2/panda_face.png b/public/-/emojis/2/panda_face.png
new file mode 100644
index 00000000000..edfc15d1db3
--- /dev/null
+++ b/public/-/emojis/2/panda_face.png
Binary files differ
diff --git a/public/-/emojis/2/paperclip.png b/public/-/emojis/2/paperclip.png
new file mode 100644
index 00000000000..a307e0efc87
--- /dev/null
+++ b/public/-/emojis/2/paperclip.png
Binary files differ
diff --git a/public/-/emojis/2/paperclips.png b/public/-/emojis/2/paperclips.png
new file mode 100644
index 00000000000..01010d13145
--- /dev/null
+++ b/public/-/emojis/2/paperclips.png
Binary files differ
diff --git a/public/-/emojis/2/park.png b/public/-/emojis/2/park.png
new file mode 100644
index 00000000000..d3fba154924
--- /dev/null
+++ b/public/-/emojis/2/park.png
Binary files differ
diff --git a/public/-/emojis/2/parking.png b/public/-/emojis/2/parking.png
new file mode 100644
index 00000000000..8b547b76816
--- /dev/null
+++ b/public/-/emojis/2/parking.png
Binary files differ
diff --git a/public/-/emojis/2/part_alternation_mark.png b/public/-/emojis/2/part_alternation_mark.png
new file mode 100644
index 00000000000..0432e380f23
--- /dev/null
+++ b/public/-/emojis/2/part_alternation_mark.png
Binary files differ
diff --git a/public/-/emojis/2/partly_sunny.png b/public/-/emojis/2/partly_sunny.png
new file mode 100644
index 00000000000..dcb0aa10133
--- /dev/null
+++ b/public/-/emojis/2/partly_sunny.png
Binary files differ
diff --git a/public/-/emojis/2/passport_control.png b/public/-/emojis/2/passport_control.png
new file mode 100644
index 00000000000..13d436b025c
--- /dev/null
+++ b/public/-/emojis/2/passport_control.png
Binary files differ
diff --git a/public/-/emojis/2/pause_button.png b/public/-/emojis/2/pause_button.png
new file mode 100644
index 00000000000..cf62af3cbf8
--- /dev/null
+++ b/public/-/emojis/2/pause_button.png
Binary files differ
diff --git a/public/-/emojis/2/peace.png b/public/-/emojis/2/peace.png
new file mode 100644
index 00000000000..331e82e5f4a
--- /dev/null
+++ b/public/-/emojis/2/peace.png
Binary files differ
diff --git a/public/-/emojis/2/peach.png b/public/-/emojis/2/peach.png
new file mode 100644
index 00000000000..a432bcbcdb7
--- /dev/null
+++ b/public/-/emojis/2/peach.png
Binary files differ
diff --git a/public/-/emojis/2/peanuts.png b/public/-/emojis/2/peanuts.png
new file mode 100644
index 00000000000..dbcb5e3f13c
--- /dev/null
+++ b/public/-/emojis/2/peanuts.png
Binary files differ
diff --git a/public/-/emojis/2/pear.png b/public/-/emojis/2/pear.png
new file mode 100644
index 00000000000..89f121d93ef
--- /dev/null
+++ b/public/-/emojis/2/pear.png
Binary files differ
diff --git a/public/-/emojis/2/pen_ballpoint.png b/public/-/emojis/2/pen_ballpoint.png
new file mode 100644
index 00000000000..b28ecf7a4de
--- /dev/null
+++ b/public/-/emojis/2/pen_ballpoint.png
Binary files differ
diff --git a/public/-/emojis/2/pen_fountain.png b/public/-/emojis/2/pen_fountain.png
new file mode 100644
index 00000000000..8610ec1eb35
--- /dev/null
+++ b/public/-/emojis/2/pen_fountain.png
Binary files differ
diff --git a/public/-/emojis/2/pencil.png b/public/-/emojis/2/pencil.png
new file mode 100644
index 00000000000..69795a5c331
--- /dev/null
+++ b/public/-/emojis/2/pencil.png
Binary files differ
diff --git a/public/-/emojis/2/pencil2.png b/public/-/emojis/2/pencil2.png
new file mode 100644
index 00000000000..c0b04c7d34e
--- /dev/null
+++ b/public/-/emojis/2/pencil2.png
Binary files differ
diff --git a/public/-/emojis/2/penguin.png b/public/-/emojis/2/penguin.png
new file mode 100644
index 00000000000..3787ce64f36
--- /dev/null
+++ b/public/-/emojis/2/penguin.png
Binary files differ
diff --git a/public/-/emojis/2/pensive.png b/public/-/emojis/2/pensive.png
new file mode 100644
index 00000000000..1ca0d392746
--- /dev/null
+++ b/public/-/emojis/2/pensive.png
Binary files differ
diff --git a/public/-/emojis/2/performing_arts.png b/public/-/emojis/2/performing_arts.png
new file mode 100644
index 00000000000..817aaac81fa
--- /dev/null
+++ b/public/-/emojis/2/performing_arts.png
Binary files differ
diff --git a/public/-/emojis/2/persevere.png b/public/-/emojis/2/persevere.png
new file mode 100644
index 00000000000..0300cecd2b1
--- /dev/null
+++ b/public/-/emojis/2/persevere.png
Binary files differ
diff --git a/public/-/emojis/2/person_frowning.png b/public/-/emojis/2/person_frowning.png
new file mode 100644
index 00000000000..ef83e19282e
--- /dev/null
+++ b/public/-/emojis/2/person_frowning.png
Binary files differ
diff --git a/public/-/emojis/2/person_frowning_tone1.png b/public/-/emojis/2/person_frowning_tone1.png
new file mode 100644
index 00000000000..1c1d5f031ca
--- /dev/null
+++ b/public/-/emojis/2/person_frowning_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/person_frowning_tone2.png b/public/-/emojis/2/person_frowning_tone2.png
new file mode 100644
index 00000000000..669f500c408
--- /dev/null
+++ b/public/-/emojis/2/person_frowning_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/person_frowning_tone3.png b/public/-/emojis/2/person_frowning_tone3.png
new file mode 100644
index 00000000000..467477ab715
--- /dev/null
+++ b/public/-/emojis/2/person_frowning_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/person_frowning_tone4.png b/public/-/emojis/2/person_frowning_tone4.png
new file mode 100644
index 00000000000..594954e686a
--- /dev/null
+++ b/public/-/emojis/2/person_frowning_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/person_frowning_tone5.png b/public/-/emojis/2/person_frowning_tone5.png
new file mode 100644
index 00000000000..f3f923ce7c4
--- /dev/null
+++ b/public/-/emojis/2/person_frowning_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/person_with_blond_hair.png b/public/-/emojis/2/person_with_blond_hair.png
new file mode 100644
index 00000000000..a55c1fe3bba
--- /dev/null
+++ b/public/-/emojis/2/person_with_blond_hair.png
Binary files differ
diff --git a/public/-/emojis/2/person_with_blond_hair_tone1.png b/public/-/emojis/2/person_with_blond_hair_tone1.png
new file mode 100644
index 00000000000..f5c55e083f2
--- /dev/null
+++ b/public/-/emojis/2/person_with_blond_hair_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/person_with_blond_hair_tone2.png b/public/-/emojis/2/person_with_blond_hair_tone2.png
new file mode 100644
index 00000000000..a520269d964
--- /dev/null
+++ b/public/-/emojis/2/person_with_blond_hair_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/person_with_blond_hair_tone3.png b/public/-/emojis/2/person_with_blond_hair_tone3.png
new file mode 100644
index 00000000000..6da4018043b
--- /dev/null
+++ b/public/-/emojis/2/person_with_blond_hair_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/person_with_blond_hair_tone4.png b/public/-/emojis/2/person_with_blond_hair_tone4.png
new file mode 100644
index 00000000000..b680160dd1a
--- /dev/null
+++ b/public/-/emojis/2/person_with_blond_hair_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/person_with_blond_hair_tone5.png b/public/-/emojis/2/person_with_blond_hair_tone5.png
new file mode 100644
index 00000000000..798f5c6a3d1
--- /dev/null
+++ b/public/-/emojis/2/person_with_blond_hair_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/person_with_pouting_face.png b/public/-/emojis/2/person_with_pouting_face.png
new file mode 100644
index 00000000000..7a4b7892d7d
--- /dev/null
+++ b/public/-/emojis/2/person_with_pouting_face.png
Binary files differ
diff --git a/public/-/emojis/2/person_with_pouting_face_tone1.png b/public/-/emojis/2/person_with_pouting_face_tone1.png
new file mode 100644
index 00000000000..41700c179b9
--- /dev/null
+++ b/public/-/emojis/2/person_with_pouting_face_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/person_with_pouting_face_tone2.png b/public/-/emojis/2/person_with_pouting_face_tone2.png
new file mode 100644
index 00000000000..14d6be7d79a
--- /dev/null
+++ b/public/-/emojis/2/person_with_pouting_face_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/person_with_pouting_face_tone3.png b/public/-/emojis/2/person_with_pouting_face_tone3.png
new file mode 100644
index 00000000000..541061e5935
--- /dev/null
+++ b/public/-/emojis/2/person_with_pouting_face_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/person_with_pouting_face_tone4.png b/public/-/emojis/2/person_with_pouting_face_tone4.png
new file mode 100644
index 00000000000..e797d3f2532
--- /dev/null
+++ b/public/-/emojis/2/person_with_pouting_face_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/person_with_pouting_face_tone5.png b/public/-/emojis/2/person_with_pouting_face_tone5.png
new file mode 100644
index 00000000000..d245c8b7e35
--- /dev/null
+++ b/public/-/emojis/2/person_with_pouting_face_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/pick.png b/public/-/emojis/2/pick.png
new file mode 100644
index 00000000000..a3b573f104f
--- /dev/null
+++ b/public/-/emojis/2/pick.png
Binary files differ
diff --git a/public/-/emojis/2/pig.png b/public/-/emojis/2/pig.png
new file mode 100644
index 00000000000..c8f36d0b6bf
--- /dev/null
+++ b/public/-/emojis/2/pig.png
Binary files differ
diff --git a/public/-/emojis/2/pig2.png b/public/-/emojis/2/pig2.png
new file mode 100644
index 00000000000..e3313b515e6
--- /dev/null
+++ b/public/-/emojis/2/pig2.png
Binary files differ
diff --git a/public/-/emojis/2/pig_nose.png b/public/-/emojis/2/pig_nose.png
new file mode 100644
index 00000000000..34eb7ca5e74
--- /dev/null
+++ b/public/-/emojis/2/pig_nose.png
Binary files differ
diff --git a/public/-/emojis/2/pill.png b/public/-/emojis/2/pill.png
new file mode 100644
index 00000000000..7a926596862
--- /dev/null
+++ b/public/-/emojis/2/pill.png
Binary files differ
diff --git a/public/-/emojis/2/pineapple.png b/public/-/emojis/2/pineapple.png
new file mode 100644
index 00000000000..e1cef9c1106
--- /dev/null
+++ b/public/-/emojis/2/pineapple.png
Binary files differ
diff --git a/public/-/emojis/2/ping_pong.png b/public/-/emojis/2/ping_pong.png
new file mode 100644
index 00000000000..fc1de71206a
--- /dev/null
+++ b/public/-/emojis/2/ping_pong.png
Binary files differ
diff --git a/public/-/emojis/2/pisces.png b/public/-/emojis/2/pisces.png
new file mode 100644
index 00000000000..5b748a7422a
--- /dev/null
+++ b/public/-/emojis/2/pisces.png
Binary files differ
diff --git a/public/-/emojis/2/pizza.png b/public/-/emojis/2/pizza.png
new file mode 100644
index 00000000000..522a6a88b1c
--- /dev/null
+++ b/public/-/emojis/2/pizza.png
Binary files differ
diff --git a/public/-/emojis/2/place_of_worship.png b/public/-/emojis/2/place_of_worship.png
new file mode 100644
index 00000000000..e36b7b7222e
--- /dev/null
+++ b/public/-/emojis/2/place_of_worship.png
Binary files differ
diff --git a/public/-/emojis/2/play_pause.png b/public/-/emojis/2/play_pause.png
new file mode 100644
index 00000000000..1955922e2f6
--- /dev/null
+++ b/public/-/emojis/2/play_pause.png
Binary files differ
diff --git a/public/-/emojis/2/point_down.png b/public/-/emojis/2/point_down.png
new file mode 100644
index 00000000000..0f1ff30678b
--- /dev/null
+++ b/public/-/emojis/2/point_down.png
Binary files differ
diff --git a/public/-/emojis/2/point_down_tone1.png b/public/-/emojis/2/point_down_tone1.png
new file mode 100644
index 00000000000..1940b678983
--- /dev/null
+++ b/public/-/emojis/2/point_down_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/point_down_tone2.png b/public/-/emojis/2/point_down_tone2.png
new file mode 100644
index 00000000000..f5818c7ff48
--- /dev/null
+++ b/public/-/emojis/2/point_down_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/point_down_tone3.png b/public/-/emojis/2/point_down_tone3.png
new file mode 100644
index 00000000000..80ad44feeb5
--- /dev/null
+++ b/public/-/emojis/2/point_down_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/point_down_tone4.png b/public/-/emojis/2/point_down_tone4.png
new file mode 100644
index 00000000000..dd6ade5547e
--- /dev/null
+++ b/public/-/emojis/2/point_down_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/point_down_tone5.png b/public/-/emojis/2/point_down_tone5.png
new file mode 100644
index 00000000000..b1f9d1f5fde
--- /dev/null
+++ b/public/-/emojis/2/point_down_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/point_left.png b/public/-/emojis/2/point_left.png
new file mode 100644
index 00000000000..1330a37c03c
--- /dev/null
+++ b/public/-/emojis/2/point_left.png
Binary files differ
diff --git a/public/-/emojis/2/point_left_tone1.png b/public/-/emojis/2/point_left_tone1.png
new file mode 100644
index 00000000000..70870fe06a5
--- /dev/null
+++ b/public/-/emojis/2/point_left_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/point_left_tone2.png b/public/-/emojis/2/point_left_tone2.png
new file mode 100644
index 00000000000..7a44d8abe73
--- /dev/null
+++ b/public/-/emojis/2/point_left_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/point_left_tone3.png b/public/-/emojis/2/point_left_tone3.png
new file mode 100644
index 00000000000..493c1cf043f
--- /dev/null
+++ b/public/-/emojis/2/point_left_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/point_left_tone4.png b/public/-/emojis/2/point_left_tone4.png
new file mode 100644
index 00000000000..96ba4c680e4
--- /dev/null
+++ b/public/-/emojis/2/point_left_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/point_left_tone5.png b/public/-/emojis/2/point_left_tone5.png
new file mode 100644
index 00000000000..4be3b09c8fa
--- /dev/null
+++ b/public/-/emojis/2/point_left_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/point_right.png b/public/-/emojis/2/point_right.png
new file mode 100644
index 00000000000..4ff5710e09c
--- /dev/null
+++ b/public/-/emojis/2/point_right.png
Binary files differ
diff --git a/public/-/emojis/2/point_right_tone1.png b/public/-/emojis/2/point_right_tone1.png
new file mode 100644
index 00000000000..b44895c5b51
--- /dev/null
+++ b/public/-/emojis/2/point_right_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/point_right_tone2.png b/public/-/emojis/2/point_right_tone2.png
new file mode 100644
index 00000000000..5b8fe2514fb
--- /dev/null
+++ b/public/-/emojis/2/point_right_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/point_right_tone3.png b/public/-/emojis/2/point_right_tone3.png
new file mode 100644
index 00000000000..93c05c4c6a7
--- /dev/null
+++ b/public/-/emojis/2/point_right_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/point_right_tone4.png b/public/-/emojis/2/point_right_tone4.png
new file mode 100644
index 00000000000..02e05e05607
--- /dev/null
+++ b/public/-/emojis/2/point_right_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/point_right_tone5.png b/public/-/emojis/2/point_right_tone5.png
new file mode 100644
index 00000000000..abf9ed1b55b
--- /dev/null
+++ b/public/-/emojis/2/point_right_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/point_up.png b/public/-/emojis/2/point_up.png
new file mode 100644
index 00000000000..459c347afc2
--- /dev/null
+++ b/public/-/emojis/2/point_up.png
Binary files differ
diff --git a/public/-/emojis/2/point_up_2.png b/public/-/emojis/2/point_up_2.png
new file mode 100644
index 00000000000..40588555177
--- /dev/null
+++ b/public/-/emojis/2/point_up_2.png
Binary files differ
diff --git a/public/-/emojis/2/point_up_2_tone1.png b/public/-/emojis/2/point_up_2_tone1.png
new file mode 100644
index 00000000000..5d7b820ebf1
--- /dev/null
+++ b/public/-/emojis/2/point_up_2_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/point_up_2_tone2.png b/public/-/emojis/2/point_up_2_tone2.png
new file mode 100644
index 00000000000..46ff4c2f95b
--- /dev/null
+++ b/public/-/emojis/2/point_up_2_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/point_up_2_tone3.png b/public/-/emojis/2/point_up_2_tone3.png
new file mode 100644
index 00000000000..39d3622b96a
--- /dev/null
+++ b/public/-/emojis/2/point_up_2_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/point_up_2_tone4.png b/public/-/emojis/2/point_up_2_tone4.png
new file mode 100644
index 00000000000..00eb6198fc4
--- /dev/null
+++ b/public/-/emojis/2/point_up_2_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/point_up_2_tone5.png b/public/-/emojis/2/point_up_2_tone5.png
new file mode 100644
index 00000000000..e1614d1e2b5
--- /dev/null
+++ b/public/-/emojis/2/point_up_2_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/point_up_tone1.png b/public/-/emojis/2/point_up_tone1.png
new file mode 100644
index 00000000000..74eb90e3ec4
--- /dev/null
+++ b/public/-/emojis/2/point_up_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/point_up_tone2.png b/public/-/emojis/2/point_up_tone2.png
new file mode 100644
index 00000000000..17e77dd605e
--- /dev/null
+++ b/public/-/emojis/2/point_up_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/point_up_tone3.png b/public/-/emojis/2/point_up_tone3.png
new file mode 100644
index 00000000000..3998e0b3517
--- /dev/null
+++ b/public/-/emojis/2/point_up_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/point_up_tone4.png b/public/-/emojis/2/point_up_tone4.png
new file mode 100644
index 00000000000..39cb4748ba0
--- /dev/null
+++ b/public/-/emojis/2/point_up_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/point_up_tone5.png b/public/-/emojis/2/point_up_tone5.png
new file mode 100644
index 00000000000..83ba921d16a
--- /dev/null
+++ b/public/-/emojis/2/point_up_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/police_car.png b/public/-/emojis/2/police_car.png
new file mode 100644
index 00000000000..9ac6495da1b
--- /dev/null
+++ b/public/-/emojis/2/police_car.png
Binary files differ
diff --git a/public/-/emojis/2/poodle.png b/public/-/emojis/2/poodle.png
new file mode 100644
index 00000000000..0a2794d990c
--- /dev/null
+++ b/public/-/emojis/2/poodle.png
Binary files differ
diff --git a/public/-/emojis/2/poop.png b/public/-/emojis/2/poop.png
new file mode 100644
index 00000000000..c5361b89319
--- /dev/null
+++ b/public/-/emojis/2/poop.png
Binary files differ
diff --git a/public/-/emojis/2/popcorn.png b/public/-/emojis/2/popcorn.png
new file mode 100644
index 00000000000..f83b38506f2
--- /dev/null
+++ b/public/-/emojis/2/popcorn.png
Binary files differ
diff --git a/public/-/emojis/2/post_office.png b/public/-/emojis/2/post_office.png
new file mode 100644
index 00000000000..35c62a68ea0
--- /dev/null
+++ b/public/-/emojis/2/post_office.png
Binary files differ
diff --git a/public/-/emojis/2/postal_horn.png b/public/-/emojis/2/postal_horn.png
new file mode 100644
index 00000000000..b76d1b2b350
--- /dev/null
+++ b/public/-/emojis/2/postal_horn.png
Binary files differ
diff --git a/public/-/emojis/2/postbox.png b/public/-/emojis/2/postbox.png
new file mode 100644
index 00000000000..9390b8a6870
--- /dev/null
+++ b/public/-/emojis/2/postbox.png
Binary files differ
diff --git a/public/-/emojis/2/potable_water.png b/public/-/emojis/2/potable_water.png
new file mode 100644
index 00000000000..ba2253dc45f
--- /dev/null
+++ b/public/-/emojis/2/potable_water.png
Binary files differ
diff --git a/public/-/emojis/2/potato.png b/public/-/emojis/2/potato.png
new file mode 100644
index 00000000000..915781de25e
--- /dev/null
+++ b/public/-/emojis/2/potato.png
Binary files differ
diff --git a/public/-/emojis/2/pouch.png b/public/-/emojis/2/pouch.png
new file mode 100644
index 00000000000..53781258d34
--- /dev/null
+++ b/public/-/emojis/2/pouch.png
Binary files differ
diff --git a/public/-/emojis/2/poultry_leg.png b/public/-/emojis/2/poultry_leg.png
new file mode 100644
index 00000000000..73226f25c54
--- /dev/null
+++ b/public/-/emojis/2/poultry_leg.png
Binary files differ
diff --git a/public/-/emojis/2/pound.png b/public/-/emojis/2/pound.png
new file mode 100644
index 00000000000..2e2e1e4910f
--- /dev/null
+++ b/public/-/emojis/2/pound.png
Binary files differ
diff --git a/public/-/emojis/2/pouting_cat.png b/public/-/emojis/2/pouting_cat.png
new file mode 100644
index 00000000000..3849bcb3b4b
--- /dev/null
+++ b/public/-/emojis/2/pouting_cat.png
Binary files differ
diff --git a/public/-/emojis/2/pray.png b/public/-/emojis/2/pray.png
new file mode 100644
index 00000000000..50665c75185
--- /dev/null
+++ b/public/-/emojis/2/pray.png
Binary files differ
diff --git a/public/-/emojis/2/pray_tone1.png b/public/-/emojis/2/pray_tone1.png
new file mode 100644
index 00000000000..b984a73ddeb
--- /dev/null
+++ b/public/-/emojis/2/pray_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/pray_tone2.png b/public/-/emojis/2/pray_tone2.png
new file mode 100644
index 00000000000..c407a8b3660
--- /dev/null
+++ b/public/-/emojis/2/pray_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/pray_tone3.png b/public/-/emojis/2/pray_tone3.png
new file mode 100644
index 00000000000..4e3793a7763
--- /dev/null
+++ b/public/-/emojis/2/pray_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/pray_tone4.png b/public/-/emojis/2/pray_tone4.png
new file mode 100644
index 00000000000..2fbfd040536
--- /dev/null
+++ b/public/-/emojis/2/pray_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/pray_tone5.png b/public/-/emojis/2/pray_tone5.png
new file mode 100644
index 00000000000..a135b50bb7b
--- /dev/null
+++ b/public/-/emojis/2/pray_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/prayer_beads.png b/public/-/emojis/2/prayer_beads.png
new file mode 100644
index 00000000000..dc0b65983d2
--- /dev/null
+++ b/public/-/emojis/2/prayer_beads.png
Binary files differ
diff --git a/public/-/emojis/2/pregnant_woman.png b/public/-/emojis/2/pregnant_woman.png
new file mode 100644
index 00000000000..7643f388f21
--- /dev/null
+++ b/public/-/emojis/2/pregnant_woman.png
Binary files differ
diff --git a/public/-/emojis/2/pregnant_woman_tone1.png b/public/-/emojis/2/pregnant_woman_tone1.png
new file mode 100644
index 00000000000..8600bfdb3d3
--- /dev/null
+++ b/public/-/emojis/2/pregnant_woman_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/pregnant_woman_tone2.png b/public/-/emojis/2/pregnant_woman_tone2.png
new file mode 100644
index 00000000000..bb4e83036c6
--- /dev/null
+++ b/public/-/emojis/2/pregnant_woman_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/pregnant_woman_tone3.png b/public/-/emojis/2/pregnant_woman_tone3.png
new file mode 100644
index 00000000000..317409a05d4
--- /dev/null
+++ b/public/-/emojis/2/pregnant_woman_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/pregnant_woman_tone4.png b/public/-/emojis/2/pregnant_woman_tone4.png
new file mode 100644
index 00000000000..bf7446637bd
--- /dev/null
+++ b/public/-/emojis/2/pregnant_woman_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/pregnant_woman_tone5.png b/public/-/emojis/2/pregnant_woman_tone5.png
new file mode 100644
index 00000000000..622d4309648
--- /dev/null
+++ b/public/-/emojis/2/pregnant_woman_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/prince.png b/public/-/emojis/2/prince.png
new file mode 100644
index 00000000000..89917fcb358
--- /dev/null
+++ b/public/-/emojis/2/prince.png
Binary files differ
diff --git a/public/-/emojis/2/prince_tone1.png b/public/-/emojis/2/prince_tone1.png
new file mode 100644
index 00000000000..04801cdd4ad
--- /dev/null
+++ b/public/-/emojis/2/prince_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/prince_tone2.png b/public/-/emojis/2/prince_tone2.png
new file mode 100644
index 00000000000..2fb88ccbf6f
--- /dev/null
+++ b/public/-/emojis/2/prince_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/prince_tone3.png b/public/-/emojis/2/prince_tone3.png
new file mode 100644
index 00000000000..232f5df4923
--- /dev/null
+++ b/public/-/emojis/2/prince_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/prince_tone4.png b/public/-/emojis/2/prince_tone4.png
new file mode 100644
index 00000000000..d867a211d9b
--- /dev/null
+++ b/public/-/emojis/2/prince_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/prince_tone5.png b/public/-/emojis/2/prince_tone5.png
new file mode 100644
index 00000000000..32985896d79
--- /dev/null
+++ b/public/-/emojis/2/prince_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/princess.png b/public/-/emojis/2/princess.png
new file mode 100644
index 00000000000..7060e9857bf
--- /dev/null
+++ b/public/-/emojis/2/princess.png
Binary files differ
diff --git a/public/-/emojis/2/princess_tone1.png b/public/-/emojis/2/princess_tone1.png
new file mode 100644
index 00000000000..ff3f587f348
--- /dev/null
+++ b/public/-/emojis/2/princess_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/princess_tone2.png b/public/-/emojis/2/princess_tone2.png
new file mode 100644
index 00000000000..4efdc45b19c
--- /dev/null
+++ b/public/-/emojis/2/princess_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/princess_tone3.png b/public/-/emojis/2/princess_tone3.png
new file mode 100644
index 00000000000..2ad3726ba78
--- /dev/null
+++ b/public/-/emojis/2/princess_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/princess_tone4.png b/public/-/emojis/2/princess_tone4.png
new file mode 100644
index 00000000000..5073b327fd5
--- /dev/null
+++ b/public/-/emojis/2/princess_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/princess_tone5.png b/public/-/emojis/2/princess_tone5.png
new file mode 100644
index 00000000000..1ad4d672027
--- /dev/null
+++ b/public/-/emojis/2/princess_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/printer.png b/public/-/emojis/2/printer.png
new file mode 100644
index 00000000000..788641e1801
--- /dev/null
+++ b/public/-/emojis/2/printer.png
Binary files differ
diff --git a/public/-/emojis/2/projector.png b/public/-/emojis/2/projector.png
new file mode 100644
index 00000000000..125cf081a54
--- /dev/null
+++ b/public/-/emojis/2/projector.png
Binary files differ
diff --git a/public/-/emojis/2/punch.png b/public/-/emojis/2/punch.png
new file mode 100644
index 00000000000..1f8b6839cd9
--- /dev/null
+++ b/public/-/emojis/2/punch.png
Binary files differ
diff --git a/public/-/emojis/2/punch_tone1.png b/public/-/emojis/2/punch_tone1.png
new file mode 100644
index 00000000000..f5413ee12c3
--- /dev/null
+++ b/public/-/emojis/2/punch_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/punch_tone2.png b/public/-/emojis/2/punch_tone2.png
new file mode 100644
index 00000000000..3808a169bc2
--- /dev/null
+++ b/public/-/emojis/2/punch_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/punch_tone3.png b/public/-/emojis/2/punch_tone3.png
new file mode 100644
index 00000000000..2eca7fc6d97
--- /dev/null
+++ b/public/-/emojis/2/punch_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/punch_tone4.png b/public/-/emojis/2/punch_tone4.png
new file mode 100644
index 00000000000..8e3a6afb208
--- /dev/null
+++ b/public/-/emojis/2/punch_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/punch_tone5.png b/public/-/emojis/2/punch_tone5.png
new file mode 100644
index 00000000000..7108cd27092
--- /dev/null
+++ b/public/-/emojis/2/punch_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/purple_heart.png b/public/-/emojis/2/purple_heart.png
new file mode 100644
index 00000000000..1056c2fba01
--- /dev/null
+++ b/public/-/emojis/2/purple_heart.png
Binary files differ
diff --git a/public/-/emojis/2/purse.png b/public/-/emojis/2/purse.png
new file mode 100644
index 00000000000..7a492707535
--- /dev/null
+++ b/public/-/emojis/2/purse.png
Binary files differ
diff --git a/public/-/emojis/2/pushpin.png b/public/-/emojis/2/pushpin.png
new file mode 100644
index 00000000000..b42d77e0573
--- /dev/null
+++ b/public/-/emojis/2/pushpin.png
Binary files differ
diff --git a/public/-/emojis/2/put_litter_in_its_place.png b/public/-/emojis/2/put_litter_in_its_place.png
new file mode 100644
index 00000000000..50338046ec6
--- /dev/null
+++ b/public/-/emojis/2/put_litter_in_its_place.png
Binary files differ
diff --git a/public/-/emojis/2/question.png b/public/-/emojis/2/question.png
new file mode 100644
index 00000000000..e224bd99b83
--- /dev/null
+++ b/public/-/emojis/2/question.png
Binary files differ
diff --git a/public/-/emojis/2/rabbit.png b/public/-/emojis/2/rabbit.png
new file mode 100644
index 00000000000..ee77df1edd4
--- /dev/null
+++ b/public/-/emojis/2/rabbit.png
Binary files differ
diff --git a/public/-/emojis/2/rabbit2.png b/public/-/emojis/2/rabbit2.png
new file mode 100644
index 00000000000..6d098ccf322
--- /dev/null
+++ b/public/-/emojis/2/rabbit2.png
Binary files differ
diff --git a/public/-/emojis/2/race_car.png b/public/-/emojis/2/race_car.png
new file mode 100644
index 00000000000..d6c180cab6d
--- /dev/null
+++ b/public/-/emojis/2/race_car.png
Binary files differ
diff --git a/public/-/emojis/2/racehorse.png b/public/-/emojis/2/racehorse.png
new file mode 100644
index 00000000000..7fde8bdee57
--- /dev/null
+++ b/public/-/emojis/2/racehorse.png
Binary files differ
diff --git a/public/-/emojis/2/radio.png b/public/-/emojis/2/radio.png
new file mode 100644
index 00000000000..eaf4b74a5b9
--- /dev/null
+++ b/public/-/emojis/2/radio.png
Binary files differ
diff --git a/public/-/emojis/2/radio_button.png b/public/-/emojis/2/radio_button.png
new file mode 100644
index 00000000000..021cbe4a69c
--- /dev/null
+++ b/public/-/emojis/2/radio_button.png
Binary files differ
diff --git a/public/-/emojis/2/radioactive.png b/public/-/emojis/2/radioactive.png
new file mode 100644
index 00000000000..af922f09b2b
--- /dev/null
+++ b/public/-/emojis/2/radioactive.png
Binary files differ
diff --git a/public/-/emojis/2/rage.png b/public/-/emojis/2/rage.png
new file mode 100644
index 00000000000..68d461fd0fd
--- /dev/null
+++ b/public/-/emojis/2/rage.png
Binary files differ
diff --git a/public/-/emojis/2/railway_car.png b/public/-/emojis/2/railway_car.png
new file mode 100644
index 00000000000..7df2c4c0058
--- /dev/null
+++ b/public/-/emojis/2/railway_car.png
Binary files differ
diff --git a/public/-/emojis/2/railway_track.png b/public/-/emojis/2/railway_track.png
new file mode 100644
index 00000000000..e37328e72ef
--- /dev/null
+++ b/public/-/emojis/2/railway_track.png
Binary files differ
diff --git a/public/-/emojis/2/rainbow.png b/public/-/emojis/2/rainbow.png
new file mode 100644
index 00000000000..ad03c746f94
--- /dev/null
+++ b/public/-/emojis/2/rainbow.png
Binary files differ
diff --git a/public/-/emojis/2/raised_back_of_hand.png b/public/-/emojis/2/raised_back_of_hand.png
new file mode 100644
index 00000000000..e5d2399b3a0
--- /dev/null
+++ b/public/-/emojis/2/raised_back_of_hand.png
Binary files differ
diff --git a/public/-/emojis/2/raised_back_of_hand_tone1.png b/public/-/emojis/2/raised_back_of_hand_tone1.png
new file mode 100644
index 00000000000..08e8ebfc163
--- /dev/null
+++ b/public/-/emojis/2/raised_back_of_hand_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/raised_back_of_hand_tone2.png b/public/-/emojis/2/raised_back_of_hand_tone2.png
new file mode 100644
index 00000000000..7123e2dab44
--- /dev/null
+++ b/public/-/emojis/2/raised_back_of_hand_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/raised_back_of_hand_tone3.png b/public/-/emojis/2/raised_back_of_hand_tone3.png
new file mode 100644
index 00000000000..7289a913c85
--- /dev/null
+++ b/public/-/emojis/2/raised_back_of_hand_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/raised_back_of_hand_tone4.png b/public/-/emojis/2/raised_back_of_hand_tone4.png
new file mode 100644
index 00000000000..67a77a92b65
--- /dev/null
+++ b/public/-/emojis/2/raised_back_of_hand_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/raised_back_of_hand_tone5.png b/public/-/emojis/2/raised_back_of_hand_tone5.png
new file mode 100644
index 00000000000..5e067c1681c
--- /dev/null
+++ b/public/-/emojis/2/raised_back_of_hand_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/raised_hand.png b/public/-/emojis/2/raised_hand.png
new file mode 100644
index 00000000000..e9bdf7e5a5e
--- /dev/null
+++ b/public/-/emojis/2/raised_hand.png
Binary files differ
diff --git a/public/-/emojis/2/raised_hand_tone1.png b/public/-/emojis/2/raised_hand_tone1.png
new file mode 100644
index 00000000000..1f241453f0d
--- /dev/null
+++ b/public/-/emojis/2/raised_hand_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/raised_hand_tone2.png b/public/-/emojis/2/raised_hand_tone2.png
new file mode 100644
index 00000000000..36128fff984
--- /dev/null
+++ b/public/-/emojis/2/raised_hand_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/raised_hand_tone3.png b/public/-/emojis/2/raised_hand_tone3.png
new file mode 100644
index 00000000000..81569a49088
--- /dev/null
+++ b/public/-/emojis/2/raised_hand_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/raised_hand_tone4.png b/public/-/emojis/2/raised_hand_tone4.png
new file mode 100644
index 00000000000..ee7c304811b
--- /dev/null
+++ b/public/-/emojis/2/raised_hand_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/raised_hand_tone5.png b/public/-/emojis/2/raised_hand_tone5.png
new file mode 100644
index 00000000000..29cf0754048
--- /dev/null
+++ b/public/-/emojis/2/raised_hand_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/raised_hands.png b/public/-/emojis/2/raised_hands.png
new file mode 100644
index 00000000000..d60ecbfed71
--- /dev/null
+++ b/public/-/emojis/2/raised_hands.png
Binary files differ
diff --git a/public/-/emojis/2/raised_hands_tone1.png b/public/-/emojis/2/raised_hands_tone1.png
new file mode 100644
index 00000000000..ed9b563956d
--- /dev/null
+++ b/public/-/emojis/2/raised_hands_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/raised_hands_tone2.png b/public/-/emojis/2/raised_hands_tone2.png
new file mode 100644
index 00000000000..dd6fdab1b91
--- /dev/null
+++ b/public/-/emojis/2/raised_hands_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/raised_hands_tone3.png b/public/-/emojis/2/raised_hands_tone3.png
new file mode 100644
index 00000000000..6d60cf17a02
--- /dev/null
+++ b/public/-/emojis/2/raised_hands_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/raised_hands_tone4.png b/public/-/emojis/2/raised_hands_tone4.png
new file mode 100644
index 00000000000..1af063fa865
--- /dev/null
+++ b/public/-/emojis/2/raised_hands_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/raised_hands_tone5.png b/public/-/emojis/2/raised_hands_tone5.png
new file mode 100644
index 00000000000..bae4d1c0e96
--- /dev/null
+++ b/public/-/emojis/2/raised_hands_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/raising_hand.png b/public/-/emojis/2/raising_hand.png
new file mode 100644
index 00000000000..d1e1b7d3cd6
--- /dev/null
+++ b/public/-/emojis/2/raising_hand.png
Binary files differ
diff --git a/public/-/emojis/2/raising_hand_tone1.png b/public/-/emojis/2/raising_hand_tone1.png
new file mode 100644
index 00000000000..47bd7568b49
--- /dev/null
+++ b/public/-/emojis/2/raising_hand_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/raising_hand_tone2.png b/public/-/emojis/2/raising_hand_tone2.png
new file mode 100644
index 00000000000..4701e2834b2
--- /dev/null
+++ b/public/-/emojis/2/raising_hand_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/raising_hand_tone3.png b/public/-/emojis/2/raising_hand_tone3.png
new file mode 100644
index 00000000000..6dcb187d3b4
--- /dev/null
+++ b/public/-/emojis/2/raising_hand_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/raising_hand_tone4.png b/public/-/emojis/2/raising_hand_tone4.png
new file mode 100644
index 00000000000..6c66cf724a2
--- /dev/null
+++ b/public/-/emojis/2/raising_hand_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/raising_hand_tone5.png b/public/-/emojis/2/raising_hand_tone5.png
new file mode 100644
index 00000000000..e4649bef629
--- /dev/null
+++ b/public/-/emojis/2/raising_hand_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/ram.png b/public/-/emojis/2/ram.png
new file mode 100644
index 00000000000..ed720a34104
--- /dev/null
+++ b/public/-/emojis/2/ram.png
Binary files differ
diff --git a/public/-/emojis/2/ramen.png b/public/-/emojis/2/ramen.png
new file mode 100644
index 00000000000..cc394a81082
--- /dev/null
+++ b/public/-/emojis/2/ramen.png
Binary files differ
diff --git a/public/-/emojis/2/rat.png b/public/-/emojis/2/rat.png
new file mode 100644
index 00000000000..43525c25090
--- /dev/null
+++ b/public/-/emojis/2/rat.png
Binary files differ
diff --git a/public/-/emojis/2/record_button.png b/public/-/emojis/2/record_button.png
new file mode 100644
index 00000000000..de602cd4b2a
--- /dev/null
+++ b/public/-/emojis/2/record_button.png
Binary files differ
diff --git a/public/-/emojis/2/recycle.png b/public/-/emojis/2/recycle.png
new file mode 100644
index 00000000000..43ceec54afb
--- /dev/null
+++ b/public/-/emojis/2/recycle.png
Binary files differ
diff --git a/public/-/emojis/2/red_car.png b/public/-/emojis/2/red_car.png
new file mode 100644
index 00000000000..e03036bdfc9
--- /dev/null
+++ b/public/-/emojis/2/red_car.png
Binary files differ
diff --git a/public/-/emojis/2/red_circle.png b/public/-/emojis/2/red_circle.png
new file mode 100644
index 00000000000..2599e084dfc
--- /dev/null
+++ b/public/-/emojis/2/red_circle.png
Binary files differ
diff --git a/public/-/emojis/2/registered.png b/public/-/emojis/2/registered.png
new file mode 100644
index 00000000000..e0d3d28cff2
--- /dev/null
+++ b/public/-/emojis/2/registered.png
Binary files differ
diff --git a/public/-/emojis/2/relaxed.png b/public/-/emojis/2/relaxed.png
new file mode 100644
index 00000000000..aeababb5735
--- /dev/null
+++ b/public/-/emojis/2/relaxed.png
Binary files differ
diff --git a/public/-/emojis/2/relieved.png b/public/-/emojis/2/relieved.png
new file mode 100644
index 00000000000..5aab9acec08
--- /dev/null
+++ b/public/-/emojis/2/relieved.png
Binary files differ
diff --git a/public/-/emojis/2/reminder_ribbon.png b/public/-/emojis/2/reminder_ribbon.png
new file mode 100644
index 00000000000..a2b4e44f3b0
--- /dev/null
+++ b/public/-/emojis/2/reminder_ribbon.png
Binary files differ
diff --git a/public/-/emojis/2/repeat.png b/public/-/emojis/2/repeat.png
new file mode 100644
index 00000000000..b23951091eb
--- /dev/null
+++ b/public/-/emojis/2/repeat.png
Binary files differ
diff --git a/public/-/emojis/2/repeat_one.png b/public/-/emojis/2/repeat_one.png
new file mode 100644
index 00000000000..054653bc56e
--- /dev/null
+++ b/public/-/emojis/2/repeat_one.png
Binary files differ
diff --git a/public/-/emojis/2/restroom.png b/public/-/emojis/2/restroom.png
new file mode 100644
index 00000000000..6617f52373c
--- /dev/null
+++ b/public/-/emojis/2/restroom.png
Binary files differ
diff --git a/public/-/emojis/2/revolving_hearts.png b/public/-/emojis/2/revolving_hearts.png
new file mode 100644
index 00000000000..dac2c409365
--- /dev/null
+++ b/public/-/emojis/2/revolving_hearts.png
Binary files differ
diff --git a/public/-/emojis/2/rewind.png b/public/-/emojis/2/rewind.png
new file mode 100644
index 00000000000..46bf1722918
--- /dev/null
+++ b/public/-/emojis/2/rewind.png
Binary files differ
diff --git a/public/-/emojis/2/rhino.png b/public/-/emojis/2/rhino.png
new file mode 100644
index 00000000000..668a446803d
--- /dev/null
+++ b/public/-/emojis/2/rhino.png
Binary files differ
diff --git a/public/-/emojis/2/ribbon.png b/public/-/emojis/2/ribbon.png
new file mode 100644
index 00000000000..4d1f568c1d9
--- /dev/null
+++ b/public/-/emojis/2/ribbon.png
Binary files differ
diff --git a/public/-/emojis/2/rice.png b/public/-/emojis/2/rice.png
new file mode 100644
index 00000000000..0b1ddf99281
--- /dev/null
+++ b/public/-/emojis/2/rice.png
Binary files differ
diff --git a/public/-/emojis/2/rice_ball.png b/public/-/emojis/2/rice_ball.png
new file mode 100644
index 00000000000..c06515c8e08
--- /dev/null
+++ b/public/-/emojis/2/rice_ball.png
Binary files differ
diff --git a/public/-/emojis/2/rice_cracker.png b/public/-/emojis/2/rice_cracker.png
new file mode 100644
index 00000000000..025b0557fc0
--- /dev/null
+++ b/public/-/emojis/2/rice_cracker.png
Binary files differ
diff --git a/public/-/emojis/2/rice_scene.png b/public/-/emojis/2/rice_scene.png
new file mode 100644
index 00000000000..243e7ce2ac0
--- /dev/null
+++ b/public/-/emojis/2/rice_scene.png
Binary files differ
diff --git a/public/-/emojis/2/right_facing_fist.png b/public/-/emojis/2/right_facing_fist.png
new file mode 100644
index 00000000000..70a51237341
--- /dev/null
+++ b/public/-/emojis/2/right_facing_fist.png
Binary files differ
diff --git a/public/-/emojis/2/right_facing_fist_tone1.png b/public/-/emojis/2/right_facing_fist_tone1.png
new file mode 100644
index 00000000000..bda21235986
--- /dev/null
+++ b/public/-/emojis/2/right_facing_fist_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/right_facing_fist_tone2.png b/public/-/emojis/2/right_facing_fist_tone2.png
new file mode 100644
index 00000000000..2b5d2514d8d
--- /dev/null
+++ b/public/-/emojis/2/right_facing_fist_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/right_facing_fist_tone3.png b/public/-/emojis/2/right_facing_fist_tone3.png
new file mode 100644
index 00000000000..40f330a55c1
--- /dev/null
+++ b/public/-/emojis/2/right_facing_fist_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/right_facing_fist_tone4.png b/public/-/emojis/2/right_facing_fist_tone4.png
new file mode 100644
index 00000000000..5f1c1293194
--- /dev/null
+++ b/public/-/emojis/2/right_facing_fist_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/right_facing_fist_tone5.png b/public/-/emojis/2/right_facing_fist_tone5.png
new file mode 100644
index 00000000000..3a93306f255
--- /dev/null
+++ b/public/-/emojis/2/right_facing_fist_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/ring.png b/public/-/emojis/2/ring.png
new file mode 100644
index 00000000000..3fc92c8efa1
--- /dev/null
+++ b/public/-/emojis/2/ring.png
Binary files differ
diff --git a/public/-/emojis/2/robot.png b/public/-/emojis/2/robot.png
new file mode 100644
index 00000000000..ddf197b52ea
--- /dev/null
+++ b/public/-/emojis/2/robot.png
Binary files differ
diff --git a/public/-/emojis/2/rocket.png b/public/-/emojis/2/rocket.png
new file mode 100644
index 00000000000..06a8c008b68
--- /dev/null
+++ b/public/-/emojis/2/rocket.png
Binary files differ
diff --git a/public/-/emojis/2/rofl.png b/public/-/emojis/2/rofl.png
new file mode 100644
index 00000000000..53673cef6cc
--- /dev/null
+++ b/public/-/emojis/2/rofl.png
Binary files differ
diff --git a/public/-/emojis/2/roller_coaster.png b/public/-/emojis/2/roller_coaster.png
new file mode 100644
index 00000000000..5b511bf6de2
--- /dev/null
+++ b/public/-/emojis/2/roller_coaster.png
Binary files differ
diff --git a/public/-/emojis/2/rolling_eyes.png b/public/-/emojis/2/rolling_eyes.png
new file mode 100644
index 00000000000..8470e15ff1b
--- /dev/null
+++ b/public/-/emojis/2/rolling_eyes.png
Binary files differ
diff --git a/public/-/emojis/2/rooster.png b/public/-/emojis/2/rooster.png
new file mode 100644
index 00000000000..9b464ad2831
--- /dev/null
+++ b/public/-/emojis/2/rooster.png
Binary files differ
diff --git a/public/-/emojis/2/rose.png b/public/-/emojis/2/rose.png
new file mode 100644
index 00000000000..3b74c1e6901
--- /dev/null
+++ b/public/-/emojis/2/rose.png
Binary files differ
diff --git a/public/-/emojis/2/rosette.png b/public/-/emojis/2/rosette.png
new file mode 100644
index 00000000000..9607481278a
--- /dev/null
+++ b/public/-/emojis/2/rosette.png
Binary files differ
diff --git a/public/-/emojis/2/rotating_light.png b/public/-/emojis/2/rotating_light.png
new file mode 100644
index 00000000000..d868b247cd0
--- /dev/null
+++ b/public/-/emojis/2/rotating_light.png
Binary files differ
diff --git a/public/-/emojis/2/round_pushpin.png b/public/-/emojis/2/round_pushpin.png
new file mode 100644
index 00000000000..8b3b49c3ec1
--- /dev/null
+++ b/public/-/emojis/2/round_pushpin.png
Binary files differ
diff --git a/public/-/emojis/2/rowboat.png b/public/-/emojis/2/rowboat.png
new file mode 100644
index 00000000000..40705e7e2ad
--- /dev/null
+++ b/public/-/emojis/2/rowboat.png
Binary files differ
diff --git a/public/-/emojis/2/rowboat_tone1.png b/public/-/emojis/2/rowboat_tone1.png
new file mode 100644
index 00000000000..9014b2f8960
--- /dev/null
+++ b/public/-/emojis/2/rowboat_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/rowboat_tone2.png b/public/-/emojis/2/rowboat_tone2.png
new file mode 100644
index 00000000000..70dbf641c14
--- /dev/null
+++ b/public/-/emojis/2/rowboat_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/rowboat_tone3.png b/public/-/emojis/2/rowboat_tone3.png
new file mode 100644
index 00000000000..12b23c9b54a
--- /dev/null
+++ b/public/-/emojis/2/rowboat_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/rowboat_tone4.png b/public/-/emojis/2/rowboat_tone4.png
new file mode 100644
index 00000000000..67b741783a9
--- /dev/null
+++ b/public/-/emojis/2/rowboat_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/rowboat_tone5.png b/public/-/emojis/2/rowboat_tone5.png
new file mode 100644
index 00000000000..01ed0805197
--- /dev/null
+++ b/public/-/emojis/2/rowboat_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/rugby_football.png b/public/-/emojis/2/rugby_football.png
new file mode 100644
index 00000000000..eb6aece5982
--- /dev/null
+++ b/public/-/emojis/2/rugby_football.png
Binary files differ
diff --git a/public/-/emojis/2/runner.png b/public/-/emojis/2/runner.png
new file mode 100644
index 00000000000..ac4142a0d74
--- /dev/null
+++ b/public/-/emojis/2/runner.png
Binary files differ
diff --git a/public/-/emojis/2/runner_tone1.png b/public/-/emojis/2/runner_tone1.png
new file mode 100644
index 00000000000..91eedefb220
--- /dev/null
+++ b/public/-/emojis/2/runner_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/runner_tone2.png b/public/-/emojis/2/runner_tone2.png
new file mode 100644
index 00000000000..671eebc851c
--- /dev/null
+++ b/public/-/emojis/2/runner_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/runner_tone3.png b/public/-/emojis/2/runner_tone3.png
new file mode 100644
index 00000000000..c878f4bea7c
--- /dev/null
+++ b/public/-/emojis/2/runner_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/runner_tone4.png b/public/-/emojis/2/runner_tone4.png
new file mode 100644
index 00000000000..e411c49c4c8
--- /dev/null
+++ b/public/-/emojis/2/runner_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/runner_tone5.png b/public/-/emojis/2/runner_tone5.png
new file mode 100644
index 00000000000..481c43d92c8
--- /dev/null
+++ b/public/-/emojis/2/runner_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/running_shirt_with_sash.png b/public/-/emojis/2/running_shirt_with_sash.png
new file mode 100644
index 00000000000..354b0f86fab
--- /dev/null
+++ b/public/-/emojis/2/running_shirt_with_sash.png
Binary files differ
diff --git a/public/-/emojis/2/sa.png b/public/-/emojis/2/sa.png
new file mode 100644
index 00000000000..efda8e0ef41
--- /dev/null
+++ b/public/-/emojis/2/sa.png
Binary files differ
diff --git a/public/-/emojis/2/sagittarius.png b/public/-/emojis/2/sagittarius.png
new file mode 100644
index 00000000000..638df61a64f
--- /dev/null
+++ b/public/-/emojis/2/sagittarius.png
Binary files differ
diff --git a/public/-/emojis/2/sailboat.png b/public/-/emojis/2/sailboat.png
new file mode 100644
index 00000000000..a4affb08500
--- /dev/null
+++ b/public/-/emojis/2/sailboat.png
Binary files differ
diff --git a/public/-/emojis/2/sake.png b/public/-/emojis/2/sake.png
new file mode 100644
index 00000000000..32c31b2b19b
--- /dev/null
+++ b/public/-/emojis/2/sake.png
Binary files differ
diff --git a/public/-/emojis/2/salad.png b/public/-/emojis/2/salad.png
new file mode 100644
index 00000000000..e199bd390e3
--- /dev/null
+++ b/public/-/emojis/2/salad.png
Binary files differ
diff --git a/public/-/emojis/2/sandal.png b/public/-/emojis/2/sandal.png
new file mode 100644
index 00000000000..8f641221862
--- /dev/null
+++ b/public/-/emojis/2/sandal.png
Binary files differ
diff --git a/public/-/emojis/2/santa.png b/public/-/emojis/2/santa.png
new file mode 100644
index 00000000000..dbea807e355
--- /dev/null
+++ b/public/-/emojis/2/santa.png
Binary files differ
diff --git a/public/-/emojis/2/santa_tone1.png b/public/-/emojis/2/santa_tone1.png
new file mode 100644
index 00000000000..c53dafd0dd2
--- /dev/null
+++ b/public/-/emojis/2/santa_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/santa_tone2.png b/public/-/emojis/2/santa_tone2.png
new file mode 100644
index 00000000000..8dcc1470f1e
--- /dev/null
+++ b/public/-/emojis/2/santa_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/santa_tone3.png b/public/-/emojis/2/santa_tone3.png
new file mode 100644
index 00000000000..32c58d37b01
--- /dev/null
+++ b/public/-/emojis/2/santa_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/santa_tone4.png b/public/-/emojis/2/santa_tone4.png
new file mode 100644
index 00000000000..434846b95a7
--- /dev/null
+++ b/public/-/emojis/2/santa_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/santa_tone5.png b/public/-/emojis/2/santa_tone5.png
new file mode 100644
index 00000000000..9920f21d2bb
--- /dev/null
+++ b/public/-/emojis/2/santa_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/satellite.png b/public/-/emojis/2/satellite.png
new file mode 100644
index 00000000000..5c559370b45
--- /dev/null
+++ b/public/-/emojis/2/satellite.png
Binary files differ
diff --git a/public/-/emojis/2/satellite_orbital.png b/public/-/emojis/2/satellite_orbital.png
new file mode 100644
index 00000000000..a08470226f2
--- /dev/null
+++ b/public/-/emojis/2/satellite_orbital.png
Binary files differ
diff --git a/public/-/emojis/2/saxophone.png b/public/-/emojis/2/saxophone.png
new file mode 100644
index 00000000000..1a9fa8f0592
--- /dev/null
+++ b/public/-/emojis/2/saxophone.png
Binary files differ
diff --git a/public/-/emojis/2/scales.png b/public/-/emojis/2/scales.png
new file mode 100644
index 00000000000..60485a6d431
--- /dev/null
+++ b/public/-/emojis/2/scales.png
Binary files differ
diff --git a/public/-/emojis/2/school.png b/public/-/emojis/2/school.png
new file mode 100644
index 00000000000..34b8e4cb70e
--- /dev/null
+++ b/public/-/emojis/2/school.png
Binary files differ
diff --git a/public/-/emojis/2/school_satchel.png b/public/-/emojis/2/school_satchel.png
new file mode 100644
index 00000000000..f3d84f31a0e
--- /dev/null
+++ b/public/-/emojis/2/school_satchel.png
Binary files differ
diff --git a/public/-/emojis/2/scissors.png b/public/-/emojis/2/scissors.png
new file mode 100644
index 00000000000..f1fab8c74dd
--- /dev/null
+++ b/public/-/emojis/2/scissors.png
Binary files differ
diff --git a/public/-/emojis/2/scooter.png b/public/-/emojis/2/scooter.png
new file mode 100644
index 00000000000..cae1aa50482
--- /dev/null
+++ b/public/-/emojis/2/scooter.png
Binary files differ
diff --git a/public/-/emojis/2/scorpion.png b/public/-/emojis/2/scorpion.png
new file mode 100644
index 00000000000..8d8c145857b
--- /dev/null
+++ b/public/-/emojis/2/scorpion.png
Binary files differ
diff --git a/public/-/emojis/2/scorpius.png b/public/-/emojis/2/scorpius.png
new file mode 100644
index 00000000000..059b45a80de
--- /dev/null
+++ b/public/-/emojis/2/scorpius.png
Binary files differ
diff --git a/public/-/emojis/2/scream.png b/public/-/emojis/2/scream.png
new file mode 100644
index 00000000000..81467f32ba3
--- /dev/null
+++ b/public/-/emojis/2/scream.png
Binary files differ
diff --git a/public/-/emojis/2/scream_cat.png b/public/-/emojis/2/scream_cat.png
new file mode 100644
index 00000000000..c682fe7654a
--- /dev/null
+++ b/public/-/emojis/2/scream_cat.png
Binary files differ
diff --git a/public/-/emojis/2/scroll.png b/public/-/emojis/2/scroll.png
new file mode 100644
index 00000000000..ddec9deb6f9
--- /dev/null
+++ b/public/-/emojis/2/scroll.png
Binary files differ
diff --git a/public/-/emojis/2/seat.png b/public/-/emojis/2/seat.png
new file mode 100644
index 00000000000..4cf5b744f1e
--- /dev/null
+++ b/public/-/emojis/2/seat.png
Binary files differ
diff --git a/public/-/emojis/2/second_place.png b/public/-/emojis/2/second_place.png
new file mode 100644
index 00000000000..478e95852ea
--- /dev/null
+++ b/public/-/emojis/2/second_place.png
Binary files differ
diff --git a/public/-/emojis/2/secret.png b/public/-/emojis/2/secret.png
new file mode 100644
index 00000000000..1f0ef02fa53
--- /dev/null
+++ b/public/-/emojis/2/secret.png
Binary files differ
diff --git a/public/-/emojis/2/see_no_evil.png b/public/-/emojis/2/see_no_evil.png
new file mode 100644
index 00000000000..7e500f70664
--- /dev/null
+++ b/public/-/emojis/2/see_no_evil.png
Binary files differ
diff --git a/public/-/emojis/2/seedling.png b/public/-/emojis/2/seedling.png
new file mode 100644
index 00000000000..9ce4e16a3d7
--- /dev/null
+++ b/public/-/emojis/2/seedling.png
Binary files differ
diff --git a/public/-/emojis/2/selfie.png b/public/-/emojis/2/selfie.png
new file mode 100644
index 00000000000..f66a0726e03
--- /dev/null
+++ b/public/-/emojis/2/selfie.png
Binary files differ
diff --git a/public/-/emojis/2/selfie_tone1.png b/public/-/emojis/2/selfie_tone1.png
new file mode 100644
index 00000000000..ff8497da02f
--- /dev/null
+++ b/public/-/emojis/2/selfie_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/selfie_tone2.png b/public/-/emojis/2/selfie_tone2.png
new file mode 100644
index 00000000000..cda07827962
--- /dev/null
+++ b/public/-/emojis/2/selfie_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/selfie_tone3.png b/public/-/emojis/2/selfie_tone3.png
new file mode 100644
index 00000000000..c40fdff8972
--- /dev/null
+++ b/public/-/emojis/2/selfie_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/selfie_tone4.png b/public/-/emojis/2/selfie_tone4.png
new file mode 100644
index 00000000000..c60858f1006
--- /dev/null
+++ b/public/-/emojis/2/selfie_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/selfie_tone5.png b/public/-/emojis/2/selfie_tone5.png
new file mode 100644
index 00000000000..4718b7c8494
--- /dev/null
+++ b/public/-/emojis/2/selfie_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/seven.png b/public/-/emojis/2/seven.png
new file mode 100644
index 00000000000..e254ef6fdd4
--- /dev/null
+++ b/public/-/emojis/2/seven.png
Binary files differ
diff --git a/public/-/emojis/2/shallow_pan_of_food.png b/public/-/emojis/2/shallow_pan_of_food.png
new file mode 100644
index 00000000000..0fbf77d45b1
--- /dev/null
+++ b/public/-/emojis/2/shallow_pan_of_food.png
Binary files differ
diff --git a/public/-/emojis/2/shamrock.png b/public/-/emojis/2/shamrock.png
new file mode 100644
index 00000000000..7fed4712809
--- /dev/null
+++ b/public/-/emojis/2/shamrock.png
Binary files differ
diff --git a/public/-/emojis/2/shark.png b/public/-/emojis/2/shark.png
new file mode 100644
index 00000000000..97d2f93a79d
--- /dev/null
+++ b/public/-/emojis/2/shark.png
Binary files differ
diff --git a/public/-/emojis/2/shaved_ice.png b/public/-/emojis/2/shaved_ice.png
new file mode 100644
index 00000000000..a8483b92c9c
--- /dev/null
+++ b/public/-/emojis/2/shaved_ice.png
Binary files differ
diff --git a/public/-/emojis/2/sheep.png b/public/-/emojis/2/sheep.png
new file mode 100644
index 00000000000..31168c85de2
--- /dev/null
+++ b/public/-/emojis/2/sheep.png
Binary files differ
diff --git a/public/-/emojis/2/shell.png b/public/-/emojis/2/shell.png
new file mode 100644
index 00000000000..500130bf8bb
--- /dev/null
+++ b/public/-/emojis/2/shell.png
Binary files differ
diff --git a/public/-/emojis/2/shield.png b/public/-/emojis/2/shield.png
new file mode 100644
index 00000000000..1ef6a7e057a
--- /dev/null
+++ b/public/-/emojis/2/shield.png
Binary files differ
diff --git a/public/-/emojis/2/shinto_shrine.png b/public/-/emojis/2/shinto_shrine.png
new file mode 100644
index 00000000000..037d405f70e
--- /dev/null
+++ b/public/-/emojis/2/shinto_shrine.png
Binary files differ
diff --git a/public/-/emojis/2/ship.png b/public/-/emojis/2/ship.png
new file mode 100644
index 00000000000..5863070b294
--- /dev/null
+++ b/public/-/emojis/2/ship.png
Binary files differ
diff --git a/public/-/emojis/2/shirt.png b/public/-/emojis/2/shirt.png
new file mode 100644
index 00000000000..b86a2dc6d26
--- /dev/null
+++ b/public/-/emojis/2/shirt.png
Binary files differ
diff --git a/public/-/emojis/2/shopping_bags.png b/public/-/emojis/2/shopping_bags.png
new file mode 100644
index 00000000000..b37726047d3
--- /dev/null
+++ b/public/-/emojis/2/shopping_bags.png
Binary files differ
diff --git a/public/-/emojis/2/shopping_cart.png b/public/-/emojis/2/shopping_cart.png
new file mode 100644
index 00000000000..037e4edb689
--- /dev/null
+++ b/public/-/emojis/2/shopping_cart.png
Binary files differ
diff --git a/public/-/emojis/2/shower.png b/public/-/emojis/2/shower.png
new file mode 100644
index 00000000000..223abf3322c
--- /dev/null
+++ b/public/-/emojis/2/shower.png
Binary files differ
diff --git a/public/-/emojis/2/shrimp.png b/public/-/emojis/2/shrimp.png
new file mode 100644
index 00000000000..7a3667cc1ff
--- /dev/null
+++ b/public/-/emojis/2/shrimp.png
Binary files differ
diff --git a/public/-/emojis/2/shrug.png b/public/-/emojis/2/shrug.png
new file mode 100644
index 00000000000..cfc3d1471b3
--- /dev/null
+++ b/public/-/emojis/2/shrug.png
Binary files differ
diff --git a/public/-/emojis/2/shrug_tone1.png b/public/-/emojis/2/shrug_tone1.png
new file mode 100644
index 00000000000..e2f3d24f8b9
--- /dev/null
+++ b/public/-/emojis/2/shrug_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/shrug_tone2.png b/public/-/emojis/2/shrug_tone2.png
new file mode 100644
index 00000000000..7e359abee83
--- /dev/null
+++ b/public/-/emojis/2/shrug_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/shrug_tone3.png b/public/-/emojis/2/shrug_tone3.png
new file mode 100644
index 00000000000..301b4922f47
--- /dev/null
+++ b/public/-/emojis/2/shrug_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/shrug_tone4.png b/public/-/emojis/2/shrug_tone4.png
new file mode 100644
index 00000000000..7e95a0e23b6
--- /dev/null
+++ b/public/-/emojis/2/shrug_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/shrug_tone5.png b/public/-/emojis/2/shrug_tone5.png
new file mode 100644
index 00000000000..771f7611e2d
--- /dev/null
+++ b/public/-/emojis/2/shrug_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/signal_strength.png b/public/-/emojis/2/signal_strength.png
new file mode 100644
index 00000000000..9a98a83072e
--- /dev/null
+++ b/public/-/emojis/2/signal_strength.png
Binary files differ
diff --git a/public/-/emojis/2/six.png b/public/-/emojis/2/six.png
new file mode 100644
index 00000000000..fc4482573a7
--- /dev/null
+++ b/public/-/emojis/2/six.png
Binary files differ
diff --git a/public/-/emojis/2/six_pointed_star.png b/public/-/emojis/2/six_pointed_star.png
new file mode 100644
index 00000000000..762094850fa
--- /dev/null
+++ b/public/-/emojis/2/six_pointed_star.png
Binary files differ
diff --git a/public/-/emojis/2/ski.png b/public/-/emojis/2/ski.png
new file mode 100644
index 00000000000..4bbb1966368
--- /dev/null
+++ b/public/-/emojis/2/ski.png
Binary files differ
diff --git a/public/-/emojis/2/skier.png b/public/-/emojis/2/skier.png
new file mode 100644
index 00000000000..3a50c6f49ff
--- /dev/null
+++ b/public/-/emojis/2/skier.png
Binary files differ
diff --git a/public/-/emojis/2/skull.png b/public/-/emojis/2/skull.png
new file mode 100644
index 00000000000..de8357e5fde
--- /dev/null
+++ b/public/-/emojis/2/skull.png
Binary files differ
diff --git a/public/-/emojis/2/skull_crossbones.png b/public/-/emojis/2/skull_crossbones.png
new file mode 100644
index 00000000000..0840efc4b90
--- /dev/null
+++ b/public/-/emojis/2/skull_crossbones.png
Binary files differ
diff --git a/public/-/emojis/2/sleeping.png b/public/-/emojis/2/sleeping.png
new file mode 100644
index 00000000000..7d2315f4c04
--- /dev/null
+++ b/public/-/emojis/2/sleeping.png
Binary files differ
diff --git a/public/-/emojis/2/sleeping_accommodation.png b/public/-/emojis/2/sleeping_accommodation.png
new file mode 100644
index 00000000000..a4cfd898944
--- /dev/null
+++ b/public/-/emojis/2/sleeping_accommodation.png
Binary files differ
diff --git a/public/-/emojis/2/sleepy.png b/public/-/emojis/2/sleepy.png
new file mode 100644
index 00000000000..ad0fb9b87bf
--- /dev/null
+++ b/public/-/emojis/2/sleepy.png
Binary files differ
diff --git a/public/-/emojis/2/slight_frown.png b/public/-/emojis/2/slight_frown.png
new file mode 100644
index 00000000000..adb072c7fa5
--- /dev/null
+++ b/public/-/emojis/2/slight_frown.png
Binary files differ
diff --git a/public/-/emojis/2/slight_smile.png b/public/-/emojis/2/slight_smile.png
new file mode 100644
index 00000000000..e38c9ba1b92
--- /dev/null
+++ b/public/-/emojis/2/slight_smile.png
Binary files differ
diff --git a/public/-/emojis/2/slot_machine.png b/public/-/emojis/2/slot_machine.png
new file mode 100644
index 00000000000..37bfb6b2260
--- /dev/null
+++ b/public/-/emojis/2/slot_machine.png
Binary files differ
diff --git a/public/-/emojis/2/small_blue_diamond.png b/public/-/emojis/2/small_blue_diamond.png
new file mode 100644
index 00000000000..b83d4e1129e
--- /dev/null
+++ b/public/-/emojis/2/small_blue_diamond.png
Binary files differ
diff --git a/public/-/emojis/2/small_orange_diamond.png b/public/-/emojis/2/small_orange_diamond.png
new file mode 100644
index 00000000000..d15c9971d4a
--- /dev/null
+++ b/public/-/emojis/2/small_orange_diamond.png
Binary files differ
diff --git a/public/-/emojis/2/small_red_triangle.png b/public/-/emojis/2/small_red_triangle.png
new file mode 100644
index 00000000000..d4b36bec645
--- /dev/null
+++ b/public/-/emojis/2/small_red_triangle.png
Binary files differ
diff --git a/public/-/emojis/2/small_red_triangle_down.png b/public/-/emojis/2/small_red_triangle_down.png
new file mode 100644
index 00000000000..f5934bc46c6
--- /dev/null
+++ b/public/-/emojis/2/small_red_triangle_down.png
Binary files differ
diff --git a/public/-/emojis/2/smile.png b/public/-/emojis/2/smile.png
new file mode 100644
index 00000000000..020856fbfa0
--- /dev/null
+++ b/public/-/emojis/2/smile.png
Binary files differ
diff --git a/public/-/emojis/2/smile_cat.png b/public/-/emojis/2/smile_cat.png
new file mode 100644
index 00000000000..7bd86d9ad43
--- /dev/null
+++ b/public/-/emojis/2/smile_cat.png
Binary files differ
diff --git a/public/-/emojis/2/smiley.png b/public/-/emojis/2/smiley.png
new file mode 100644
index 00000000000..25db0d4936d
--- /dev/null
+++ b/public/-/emojis/2/smiley.png
Binary files differ
diff --git a/public/-/emojis/2/smiley_cat.png b/public/-/emojis/2/smiley_cat.png
new file mode 100644
index 00000000000..4b56e4fca6d
--- /dev/null
+++ b/public/-/emojis/2/smiley_cat.png
Binary files differ
diff --git a/public/-/emojis/2/smiling_imp.png b/public/-/emojis/2/smiling_imp.png
new file mode 100644
index 00000000000..1c23402e37b
--- /dev/null
+++ b/public/-/emojis/2/smiling_imp.png
Binary files differ
diff --git a/public/-/emojis/2/smirk.png b/public/-/emojis/2/smirk.png
new file mode 100644
index 00000000000..efb6db0393b
--- /dev/null
+++ b/public/-/emojis/2/smirk.png
Binary files differ
diff --git a/public/-/emojis/2/smirk_cat.png b/public/-/emojis/2/smirk_cat.png
new file mode 100644
index 00000000000..cb2f3f03d42
--- /dev/null
+++ b/public/-/emojis/2/smirk_cat.png
Binary files differ
diff --git a/public/-/emojis/2/smoking.png b/public/-/emojis/2/smoking.png
new file mode 100644
index 00000000000..017dff2df8a
--- /dev/null
+++ b/public/-/emojis/2/smoking.png
Binary files differ
diff --git a/public/-/emojis/2/snail.png b/public/-/emojis/2/snail.png
new file mode 100644
index 00000000000..28a31806c82
--- /dev/null
+++ b/public/-/emojis/2/snail.png
Binary files differ
diff --git a/public/-/emojis/2/snake.png b/public/-/emojis/2/snake.png
new file mode 100644
index 00000000000..11680226a2f
--- /dev/null
+++ b/public/-/emojis/2/snake.png
Binary files differ
diff --git a/public/-/emojis/2/sneezing_face.png b/public/-/emojis/2/sneezing_face.png
new file mode 100644
index 00000000000..f807fe90a10
--- /dev/null
+++ b/public/-/emojis/2/sneezing_face.png
Binary files differ
diff --git a/public/-/emojis/2/snowboarder.png b/public/-/emojis/2/snowboarder.png
new file mode 100644
index 00000000000..fd70915bfc6
--- /dev/null
+++ b/public/-/emojis/2/snowboarder.png
Binary files differ
diff --git a/public/-/emojis/2/snowflake.png b/public/-/emojis/2/snowflake.png
new file mode 100644
index 00000000000..9eaf9ede6e2
--- /dev/null
+++ b/public/-/emojis/2/snowflake.png
Binary files differ
diff --git a/public/-/emojis/2/snowman.png b/public/-/emojis/2/snowman.png
new file mode 100644
index 00000000000..a1c8bbd32ac
--- /dev/null
+++ b/public/-/emojis/2/snowman.png
Binary files differ
diff --git a/public/-/emojis/2/snowman2.png b/public/-/emojis/2/snowman2.png
new file mode 100644
index 00000000000..67c7572ca8d
--- /dev/null
+++ b/public/-/emojis/2/snowman2.png
Binary files differ
diff --git a/public/-/emojis/2/sob.png b/public/-/emojis/2/sob.png
new file mode 100644
index 00000000000..5e386c89b4e
--- /dev/null
+++ b/public/-/emojis/2/sob.png
Binary files differ
diff --git a/public/-/emojis/2/soccer.png b/public/-/emojis/2/soccer.png
new file mode 100644
index 00000000000..a850058d657
--- /dev/null
+++ b/public/-/emojis/2/soccer.png
Binary files differ
diff --git a/public/-/emojis/2/soon.png b/public/-/emojis/2/soon.png
new file mode 100644
index 00000000000..1a2c8507203
--- /dev/null
+++ b/public/-/emojis/2/soon.png
Binary files differ
diff --git a/public/-/emojis/2/sos.png b/public/-/emojis/2/sos.png
new file mode 100644
index 00000000000..5d014eb40a0
--- /dev/null
+++ b/public/-/emojis/2/sos.png
Binary files differ
diff --git a/public/-/emojis/2/sound.png b/public/-/emojis/2/sound.png
new file mode 100644
index 00000000000..8745dcbfea6
--- /dev/null
+++ b/public/-/emojis/2/sound.png
Binary files differ
diff --git a/public/-/emojis/2/space_invader.png b/public/-/emojis/2/space_invader.png
new file mode 100644
index 00000000000..20b6a7dc292
--- /dev/null
+++ b/public/-/emojis/2/space_invader.png
Binary files differ
diff --git a/public/-/emojis/2/spades.png b/public/-/emojis/2/spades.png
new file mode 100644
index 00000000000..391970ee89f
--- /dev/null
+++ b/public/-/emojis/2/spades.png
Binary files differ
diff --git a/public/-/emojis/2/spaghetti.png b/public/-/emojis/2/spaghetti.png
new file mode 100644
index 00000000000..7b090699d8c
--- /dev/null
+++ b/public/-/emojis/2/spaghetti.png
Binary files differ
diff --git a/public/-/emojis/2/sparkle.png b/public/-/emojis/2/sparkle.png
new file mode 100644
index 00000000000..0afb772cea3
--- /dev/null
+++ b/public/-/emojis/2/sparkle.png
Binary files differ
diff --git a/public/-/emojis/2/sparkler.png b/public/-/emojis/2/sparkler.png
new file mode 100644
index 00000000000..d161be56b5e
--- /dev/null
+++ b/public/-/emojis/2/sparkler.png
Binary files differ
diff --git a/public/-/emojis/2/sparkles.png b/public/-/emojis/2/sparkles.png
new file mode 100644
index 00000000000..bb495239cfb
--- /dev/null
+++ b/public/-/emojis/2/sparkles.png
Binary files differ
diff --git a/public/-/emojis/2/sparkling_heart.png b/public/-/emojis/2/sparkling_heart.png
new file mode 100644
index 00000000000..32dcf9aa915
--- /dev/null
+++ b/public/-/emojis/2/sparkling_heart.png
Binary files differ
diff --git a/public/-/emojis/2/speak_no_evil.png b/public/-/emojis/2/speak_no_evil.png
new file mode 100644
index 00000000000..e9bfeec5f42
--- /dev/null
+++ b/public/-/emojis/2/speak_no_evil.png
Binary files differ
diff --git a/public/-/emojis/2/speaker.png b/public/-/emojis/2/speaker.png
new file mode 100644
index 00000000000..53a81d34d85
--- /dev/null
+++ b/public/-/emojis/2/speaker.png
Binary files differ
diff --git a/public/-/emojis/2/speaking_head.png b/public/-/emojis/2/speaking_head.png
new file mode 100644
index 00000000000..98d13b4655f
--- /dev/null
+++ b/public/-/emojis/2/speaking_head.png
Binary files differ
diff --git a/public/-/emojis/2/speech_balloon.png b/public/-/emojis/2/speech_balloon.png
new file mode 100644
index 00000000000..68931bd98bd
--- /dev/null
+++ b/public/-/emojis/2/speech_balloon.png
Binary files differ
diff --git a/public/-/emojis/2/speech_left.png b/public/-/emojis/2/speech_left.png
new file mode 100644
index 00000000000..752e6968ef7
--- /dev/null
+++ b/public/-/emojis/2/speech_left.png
Binary files differ
diff --git a/public/-/emojis/2/speedboat.png b/public/-/emojis/2/speedboat.png
new file mode 100644
index 00000000000..0ea80037c32
--- /dev/null
+++ b/public/-/emojis/2/speedboat.png
Binary files differ
diff --git a/public/-/emojis/2/spider.png b/public/-/emojis/2/spider.png
new file mode 100644
index 00000000000..afabcf2cea4
--- /dev/null
+++ b/public/-/emojis/2/spider.png
Binary files differ
diff --git a/public/-/emojis/2/spider_web.png b/public/-/emojis/2/spider_web.png
new file mode 100644
index 00000000000..145f80430af
--- /dev/null
+++ b/public/-/emojis/2/spider_web.png
Binary files differ
diff --git a/public/-/emojis/2/spoon.png b/public/-/emojis/2/spoon.png
new file mode 100644
index 00000000000..e1b338a307c
--- /dev/null
+++ b/public/-/emojis/2/spoon.png
Binary files differ
diff --git a/public/-/emojis/2/spy.png b/public/-/emojis/2/spy.png
new file mode 100644
index 00000000000..7fe4c2b0066
--- /dev/null
+++ b/public/-/emojis/2/spy.png
Binary files differ
diff --git a/public/-/emojis/2/spy_tone1.png b/public/-/emojis/2/spy_tone1.png
new file mode 100644
index 00000000000..019fe0e53b2
--- /dev/null
+++ b/public/-/emojis/2/spy_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/spy_tone2.png b/public/-/emojis/2/spy_tone2.png
new file mode 100644
index 00000000000..cadc40ed53c
--- /dev/null
+++ b/public/-/emojis/2/spy_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/spy_tone3.png b/public/-/emojis/2/spy_tone3.png
new file mode 100644
index 00000000000..d994a09ecf4
--- /dev/null
+++ b/public/-/emojis/2/spy_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/spy_tone4.png b/public/-/emojis/2/spy_tone4.png
new file mode 100644
index 00000000000..92695bc1074
--- /dev/null
+++ b/public/-/emojis/2/spy_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/spy_tone5.png b/public/-/emojis/2/spy_tone5.png
new file mode 100644
index 00000000000..78f55b54ada
--- /dev/null
+++ b/public/-/emojis/2/spy_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/squid.png b/public/-/emojis/2/squid.png
new file mode 100644
index 00000000000..c6a4e665b74
--- /dev/null
+++ b/public/-/emojis/2/squid.png
Binary files differ
diff --git a/public/-/emojis/2/stadium.png b/public/-/emojis/2/stadium.png
new file mode 100644
index 00000000000..facc7d4fc36
--- /dev/null
+++ b/public/-/emojis/2/stadium.png
Binary files differ
diff --git a/public/-/emojis/2/star.png b/public/-/emojis/2/star.png
new file mode 100644
index 00000000000..aac6c64711d
--- /dev/null
+++ b/public/-/emojis/2/star.png
Binary files differ
diff --git a/public/-/emojis/2/star2.png b/public/-/emojis/2/star2.png
new file mode 100644
index 00000000000..adaf11e6e39
--- /dev/null
+++ b/public/-/emojis/2/star2.png
Binary files differ
diff --git a/public/-/emojis/2/star_and_crescent.png b/public/-/emojis/2/star_and_crescent.png
new file mode 100644
index 00000000000..5ab5193e942
--- /dev/null
+++ b/public/-/emojis/2/star_and_crescent.png
Binary files differ
diff --git a/public/-/emojis/2/star_of_david.png b/public/-/emojis/2/star_of_david.png
new file mode 100644
index 00000000000..88e957492c2
--- /dev/null
+++ b/public/-/emojis/2/star_of_david.png
Binary files differ
diff --git a/public/-/emojis/2/stars.png b/public/-/emojis/2/stars.png
new file mode 100644
index 00000000000..4567af681a5
--- /dev/null
+++ b/public/-/emojis/2/stars.png
Binary files differ
diff --git a/public/-/emojis/2/station.png b/public/-/emojis/2/station.png
new file mode 100644
index 00000000000..d8a43944883
--- /dev/null
+++ b/public/-/emojis/2/station.png
Binary files differ
diff --git a/public/-/emojis/2/statue_of_liberty.png b/public/-/emojis/2/statue_of_liberty.png
new file mode 100644
index 00000000000..6a6a59c078d
--- /dev/null
+++ b/public/-/emojis/2/statue_of_liberty.png
Binary files differ
diff --git a/public/-/emojis/2/steam_locomotive.png b/public/-/emojis/2/steam_locomotive.png
new file mode 100644
index 00000000000..95a570c62bd
--- /dev/null
+++ b/public/-/emojis/2/steam_locomotive.png
Binary files differ
diff --git a/public/-/emojis/2/stew.png b/public/-/emojis/2/stew.png
new file mode 100644
index 00000000000..369f9c6fca5
--- /dev/null
+++ b/public/-/emojis/2/stew.png
Binary files differ
diff --git a/public/-/emojis/2/stop_button.png b/public/-/emojis/2/stop_button.png
new file mode 100644
index 00000000000..5df39ab4adb
--- /dev/null
+++ b/public/-/emojis/2/stop_button.png
Binary files differ
diff --git a/public/-/emojis/2/stopwatch.png b/public/-/emojis/2/stopwatch.png
new file mode 100644
index 00000000000..1610ba9e6fc
--- /dev/null
+++ b/public/-/emojis/2/stopwatch.png
Binary files differ
diff --git a/public/-/emojis/2/straight_ruler.png b/public/-/emojis/2/straight_ruler.png
new file mode 100644
index 00000000000..3479fb1c6bd
--- /dev/null
+++ b/public/-/emojis/2/straight_ruler.png
Binary files differ
diff --git a/public/-/emojis/2/strawberry.png b/public/-/emojis/2/strawberry.png
new file mode 100644
index 00000000000..726356e830d
--- /dev/null
+++ b/public/-/emojis/2/strawberry.png
Binary files differ
diff --git a/public/-/emojis/2/stuck_out_tongue.png b/public/-/emojis/2/stuck_out_tongue.png
new file mode 100644
index 00000000000..0d48279a13e
--- /dev/null
+++ b/public/-/emojis/2/stuck_out_tongue.png
Binary files differ
diff --git a/public/-/emojis/2/stuck_out_tongue_closed_eyes.png b/public/-/emojis/2/stuck_out_tongue_closed_eyes.png
new file mode 100644
index 00000000000..6c2d8152d3d
--- /dev/null
+++ b/public/-/emojis/2/stuck_out_tongue_closed_eyes.png
Binary files differ
diff --git a/public/-/emojis/2/stuck_out_tongue_winking_eye.png b/public/-/emojis/2/stuck_out_tongue_winking_eye.png
new file mode 100644
index 00000000000..0d939158bac
--- /dev/null
+++ b/public/-/emojis/2/stuck_out_tongue_winking_eye.png
Binary files differ
diff --git a/public/-/emojis/2/stuffed_flatbread.png b/public/-/emojis/2/stuffed_flatbread.png
new file mode 100644
index 00000000000..fab6f0cf60e
--- /dev/null
+++ b/public/-/emojis/2/stuffed_flatbread.png
Binary files differ
diff --git a/public/-/emojis/2/sun_with_face.png b/public/-/emojis/2/sun_with_face.png
new file mode 100644
index 00000000000..09ca3548bda
--- /dev/null
+++ b/public/-/emojis/2/sun_with_face.png
Binary files differ
diff --git a/public/-/emojis/2/sunflower.png b/public/-/emojis/2/sunflower.png
new file mode 100644
index 00000000000..470cff7ab65
--- /dev/null
+++ b/public/-/emojis/2/sunflower.png
Binary files differ
diff --git a/public/-/emojis/2/sunglasses.png b/public/-/emojis/2/sunglasses.png
new file mode 100644
index 00000000000..c5e7e6e5287
--- /dev/null
+++ b/public/-/emojis/2/sunglasses.png
Binary files differ
diff --git a/public/-/emojis/2/sunny.png b/public/-/emojis/2/sunny.png
new file mode 100644
index 00000000000..a746a886798
--- /dev/null
+++ b/public/-/emojis/2/sunny.png
Binary files differ
diff --git a/public/-/emojis/2/sunrise.png b/public/-/emojis/2/sunrise.png
new file mode 100644
index 00000000000..369d13fc5a7
--- /dev/null
+++ b/public/-/emojis/2/sunrise.png
Binary files differ
diff --git a/public/-/emojis/2/sunrise_over_mountains.png b/public/-/emojis/2/sunrise_over_mountains.png
new file mode 100644
index 00000000000..7ef6d6dfc1f
--- /dev/null
+++ b/public/-/emojis/2/sunrise_over_mountains.png
Binary files differ
diff --git a/public/-/emojis/2/surfer.png b/public/-/emojis/2/surfer.png
new file mode 100644
index 00000000000..b4dee78ca5d
--- /dev/null
+++ b/public/-/emojis/2/surfer.png
Binary files differ
diff --git a/public/-/emojis/2/surfer_tone1.png b/public/-/emojis/2/surfer_tone1.png
new file mode 100644
index 00000000000..12f91117845
--- /dev/null
+++ b/public/-/emojis/2/surfer_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/surfer_tone2.png b/public/-/emojis/2/surfer_tone2.png
new file mode 100644
index 00000000000..2ce3ec7b545
--- /dev/null
+++ b/public/-/emojis/2/surfer_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/surfer_tone3.png b/public/-/emojis/2/surfer_tone3.png
new file mode 100644
index 00000000000..46d81855192
--- /dev/null
+++ b/public/-/emojis/2/surfer_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/surfer_tone4.png b/public/-/emojis/2/surfer_tone4.png
new file mode 100644
index 00000000000..a45e877308e
--- /dev/null
+++ b/public/-/emojis/2/surfer_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/surfer_tone5.png b/public/-/emojis/2/surfer_tone5.png
new file mode 100644
index 00000000000..f76eed71b82
--- /dev/null
+++ b/public/-/emojis/2/surfer_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/sushi.png b/public/-/emojis/2/sushi.png
new file mode 100644
index 00000000000..6c4b87ec2f6
--- /dev/null
+++ b/public/-/emojis/2/sushi.png
Binary files differ
diff --git a/public/-/emojis/2/suspension_railway.png b/public/-/emojis/2/suspension_railway.png
new file mode 100644
index 00000000000..e1aa1a18873
--- /dev/null
+++ b/public/-/emojis/2/suspension_railway.png
Binary files differ
diff --git a/public/-/emojis/2/sweat.png b/public/-/emojis/2/sweat.png
new file mode 100644
index 00000000000..2122850839b
--- /dev/null
+++ b/public/-/emojis/2/sweat.png
Binary files differ
diff --git a/public/-/emojis/2/sweat_drops.png b/public/-/emojis/2/sweat_drops.png
new file mode 100644
index 00000000000..392c04cc7ba
--- /dev/null
+++ b/public/-/emojis/2/sweat_drops.png
Binary files differ
diff --git a/public/-/emojis/2/sweat_smile.png b/public/-/emojis/2/sweat_smile.png
new file mode 100644
index 00000000000..f632526bdf8
--- /dev/null
+++ b/public/-/emojis/2/sweat_smile.png
Binary files differ
diff --git a/public/-/emojis/2/sweet_potato.png b/public/-/emojis/2/sweet_potato.png
new file mode 100644
index 00000000000..abfbe70a528
--- /dev/null
+++ b/public/-/emojis/2/sweet_potato.png
Binary files differ
diff --git a/public/-/emojis/2/swimmer.png b/public/-/emojis/2/swimmer.png
new file mode 100644
index 00000000000..985910c928c
--- /dev/null
+++ b/public/-/emojis/2/swimmer.png
Binary files differ
diff --git a/public/-/emojis/2/swimmer_tone1.png b/public/-/emojis/2/swimmer_tone1.png
new file mode 100644
index 00000000000..7735655aaab
--- /dev/null
+++ b/public/-/emojis/2/swimmer_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/swimmer_tone2.png b/public/-/emojis/2/swimmer_tone2.png
new file mode 100644
index 00000000000..e3d8f4ef2c8
--- /dev/null
+++ b/public/-/emojis/2/swimmer_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/swimmer_tone3.png b/public/-/emojis/2/swimmer_tone3.png
new file mode 100644
index 00000000000..4d187d1f13e
--- /dev/null
+++ b/public/-/emojis/2/swimmer_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/swimmer_tone4.png b/public/-/emojis/2/swimmer_tone4.png
new file mode 100644
index 00000000000..e19f0fcd07f
--- /dev/null
+++ b/public/-/emojis/2/swimmer_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/swimmer_tone5.png b/public/-/emojis/2/swimmer_tone5.png
new file mode 100644
index 00000000000..bc485bebe87
--- /dev/null
+++ b/public/-/emojis/2/swimmer_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/symbols.png b/public/-/emojis/2/symbols.png
new file mode 100644
index 00000000000..dcd10763aec
--- /dev/null
+++ b/public/-/emojis/2/symbols.png
Binary files differ
diff --git a/public/-/emojis/2/synagogue.png b/public/-/emojis/2/synagogue.png
new file mode 100644
index 00000000000..bf42bf77742
--- /dev/null
+++ b/public/-/emojis/2/synagogue.png
Binary files differ
diff --git a/public/-/emojis/2/syringe.png b/public/-/emojis/2/syringe.png
new file mode 100644
index 00000000000..6bff9419b63
--- /dev/null
+++ b/public/-/emojis/2/syringe.png
Binary files differ
diff --git a/public/-/emojis/2/taco.png b/public/-/emojis/2/taco.png
new file mode 100644
index 00000000000..6760f289b87
--- /dev/null
+++ b/public/-/emojis/2/taco.png
Binary files differ
diff --git a/public/-/emojis/2/tada.png b/public/-/emojis/2/tada.png
new file mode 100644
index 00000000000..29822f25ad1
--- /dev/null
+++ b/public/-/emojis/2/tada.png
Binary files differ
diff --git a/public/-/emojis/2/tanabata_tree.png b/public/-/emojis/2/tanabata_tree.png
new file mode 100644
index 00000000000..b944198d57a
--- /dev/null
+++ b/public/-/emojis/2/tanabata_tree.png
Binary files differ
diff --git a/public/-/emojis/2/tangerine.png b/public/-/emojis/2/tangerine.png
new file mode 100644
index 00000000000..90ae7bec598
--- /dev/null
+++ b/public/-/emojis/2/tangerine.png
Binary files differ
diff --git a/public/-/emojis/2/taurus.png b/public/-/emojis/2/taurus.png
new file mode 100644
index 00000000000..f6cac21ebe0
--- /dev/null
+++ b/public/-/emojis/2/taurus.png
Binary files differ
diff --git a/public/-/emojis/2/taxi.png b/public/-/emojis/2/taxi.png
new file mode 100644
index 00000000000..fc1b5c2c7ef
--- /dev/null
+++ b/public/-/emojis/2/taxi.png
Binary files differ
diff --git a/public/-/emojis/2/tea.png b/public/-/emojis/2/tea.png
new file mode 100644
index 00000000000..1ce3af7dcae
--- /dev/null
+++ b/public/-/emojis/2/tea.png
Binary files differ
diff --git a/public/-/emojis/2/telephone.png b/public/-/emojis/2/telephone.png
new file mode 100644
index 00000000000..715668433bd
--- /dev/null
+++ b/public/-/emojis/2/telephone.png
Binary files differ
diff --git a/public/-/emojis/2/telephone_receiver.png b/public/-/emojis/2/telephone_receiver.png
new file mode 100644
index 00000000000..310596e7c22
--- /dev/null
+++ b/public/-/emojis/2/telephone_receiver.png
Binary files differ
diff --git a/public/-/emojis/2/telescope.png b/public/-/emojis/2/telescope.png
new file mode 100644
index 00000000000..c2a5539f619
--- /dev/null
+++ b/public/-/emojis/2/telescope.png
Binary files differ
diff --git a/public/-/emojis/2/ten.png b/public/-/emojis/2/ten.png
new file mode 100644
index 00000000000..095b845f60f
--- /dev/null
+++ b/public/-/emojis/2/ten.png
Binary files differ
diff --git a/public/-/emojis/2/tennis.png b/public/-/emojis/2/tennis.png
new file mode 100644
index 00000000000..5e17e45d876
--- /dev/null
+++ b/public/-/emojis/2/tennis.png
Binary files differ
diff --git a/public/-/emojis/2/tent.png b/public/-/emojis/2/tent.png
new file mode 100644
index 00000000000..154bf32a14c
--- /dev/null
+++ b/public/-/emojis/2/tent.png
Binary files differ
diff --git a/public/-/emojis/2/thermometer.png b/public/-/emojis/2/thermometer.png
new file mode 100644
index 00000000000..59948a90828
--- /dev/null
+++ b/public/-/emojis/2/thermometer.png
Binary files differ
diff --git a/public/-/emojis/2/thermometer_face.png b/public/-/emojis/2/thermometer_face.png
new file mode 100644
index 00000000000..7f66be79dc2
--- /dev/null
+++ b/public/-/emojis/2/thermometer_face.png
Binary files differ
diff --git a/public/-/emojis/2/thinking.png b/public/-/emojis/2/thinking.png
new file mode 100644
index 00000000000..9d2d2239434
--- /dev/null
+++ b/public/-/emojis/2/thinking.png
Binary files differ
diff --git a/public/-/emojis/2/third_place.png b/public/-/emojis/2/third_place.png
new file mode 100644
index 00000000000..8735d669da5
--- /dev/null
+++ b/public/-/emojis/2/third_place.png
Binary files differ
diff --git a/public/-/emojis/2/thought_balloon.png b/public/-/emojis/2/thought_balloon.png
new file mode 100644
index 00000000000..d03489c53c2
--- /dev/null
+++ b/public/-/emojis/2/thought_balloon.png
Binary files differ
diff --git a/public/-/emojis/2/three.png b/public/-/emojis/2/three.png
new file mode 100644
index 00000000000..ff06694841c
--- /dev/null
+++ b/public/-/emojis/2/three.png
Binary files differ
diff --git a/public/-/emojis/2/thumbsdown.png b/public/-/emojis/2/thumbsdown.png
new file mode 100644
index 00000000000..5f46c1e086d
--- /dev/null
+++ b/public/-/emojis/2/thumbsdown.png
Binary files differ
diff --git a/public/-/emojis/2/thumbsdown_tone1.png b/public/-/emojis/2/thumbsdown_tone1.png
new file mode 100644
index 00000000000..a1a4f42c338
--- /dev/null
+++ b/public/-/emojis/2/thumbsdown_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/thumbsdown_tone2.png b/public/-/emojis/2/thumbsdown_tone2.png
new file mode 100644
index 00000000000..eae40534e95
--- /dev/null
+++ b/public/-/emojis/2/thumbsdown_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/thumbsdown_tone3.png b/public/-/emojis/2/thumbsdown_tone3.png
new file mode 100644
index 00000000000..d795af13536
--- /dev/null
+++ b/public/-/emojis/2/thumbsdown_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/thumbsdown_tone4.png b/public/-/emojis/2/thumbsdown_tone4.png
new file mode 100644
index 00000000000..07d1afac9c5
--- /dev/null
+++ b/public/-/emojis/2/thumbsdown_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/thumbsdown_tone5.png b/public/-/emojis/2/thumbsdown_tone5.png
new file mode 100644
index 00000000000..847ce3a82ce
--- /dev/null
+++ b/public/-/emojis/2/thumbsdown_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/thumbsup.png b/public/-/emojis/2/thumbsup.png
new file mode 100644
index 00000000000..5cebe8a7787
--- /dev/null
+++ b/public/-/emojis/2/thumbsup.png
Binary files differ
diff --git a/public/-/emojis/2/thumbsup_tone1.png b/public/-/emojis/2/thumbsup_tone1.png
new file mode 100644
index 00000000000..76b734a2e32
--- /dev/null
+++ b/public/-/emojis/2/thumbsup_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/thumbsup_tone2.png b/public/-/emojis/2/thumbsup_tone2.png
new file mode 100644
index 00000000000..c7d900d86c5
--- /dev/null
+++ b/public/-/emojis/2/thumbsup_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/thumbsup_tone3.png b/public/-/emojis/2/thumbsup_tone3.png
new file mode 100644
index 00000000000..5bd66fd212d
--- /dev/null
+++ b/public/-/emojis/2/thumbsup_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/thumbsup_tone4.png b/public/-/emojis/2/thumbsup_tone4.png
new file mode 100644
index 00000000000..37b2d15fd7b
--- /dev/null
+++ b/public/-/emojis/2/thumbsup_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/thumbsup_tone5.png b/public/-/emojis/2/thumbsup_tone5.png
new file mode 100644
index 00000000000..c5d208280c3
--- /dev/null
+++ b/public/-/emojis/2/thumbsup_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/thunder_cloud_rain.png b/public/-/emojis/2/thunder_cloud_rain.png
new file mode 100644
index 00000000000..c6e07334eb9
--- /dev/null
+++ b/public/-/emojis/2/thunder_cloud_rain.png
Binary files differ
diff --git a/public/-/emojis/2/ticket.png b/public/-/emojis/2/ticket.png
new file mode 100644
index 00000000000..b8949469865
--- /dev/null
+++ b/public/-/emojis/2/ticket.png
Binary files differ
diff --git a/public/-/emojis/2/tickets.png b/public/-/emojis/2/tickets.png
new file mode 100644
index 00000000000..1b240c3b83e
--- /dev/null
+++ b/public/-/emojis/2/tickets.png
Binary files differ
diff --git a/public/-/emojis/2/tiger.png b/public/-/emojis/2/tiger.png
new file mode 100644
index 00000000000..398db6aceeb
--- /dev/null
+++ b/public/-/emojis/2/tiger.png
Binary files differ
diff --git a/public/-/emojis/2/tiger2.png b/public/-/emojis/2/tiger2.png
new file mode 100644
index 00000000000..e5409e67fb4
--- /dev/null
+++ b/public/-/emojis/2/tiger2.png
Binary files differ
diff --git a/public/-/emojis/2/timer.png b/public/-/emojis/2/timer.png
new file mode 100644
index 00000000000..dcff365af63
--- /dev/null
+++ b/public/-/emojis/2/timer.png
Binary files differ
diff --git a/public/-/emojis/2/tired_face.png b/public/-/emojis/2/tired_face.png
new file mode 100644
index 00000000000..823b8aaeba0
--- /dev/null
+++ b/public/-/emojis/2/tired_face.png
Binary files differ
diff --git a/public/-/emojis/2/tm.png b/public/-/emojis/2/tm.png
new file mode 100644
index 00000000000..d353953a40c
--- /dev/null
+++ b/public/-/emojis/2/tm.png
Binary files differ
diff --git a/public/-/emojis/2/toilet.png b/public/-/emojis/2/toilet.png
new file mode 100644
index 00000000000..828879db5ec
--- /dev/null
+++ b/public/-/emojis/2/toilet.png
Binary files differ
diff --git a/public/-/emojis/2/tokyo_tower.png b/public/-/emojis/2/tokyo_tower.png
new file mode 100644
index 00000000000..4366f3413a6
--- /dev/null
+++ b/public/-/emojis/2/tokyo_tower.png
Binary files differ
diff --git a/public/-/emojis/2/tomato.png b/public/-/emojis/2/tomato.png
new file mode 100644
index 00000000000..74ba9aa90a8
--- /dev/null
+++ b/public/-/emojis/2/tomato.png
Binary files differ
diff --git a/public/-/emojis/2/tone1.png b/public/-/emojis/2/tone1.png
new file mode 100644
index 00000000000..d36f06f2763
--- /dev/null
+++ b/public/-/emojis/2/tone1.png
Binary files differ
diff --git a/public/-/emojis/2/tone2.png b/public/-/emojis/2/tone2.png
new file mode 100644
index 00000000000..8c08edd81cb
--- /dev/null
+++ b/public/-/emojis/2/tone2.png
Binary files differ
diff --git a/public/-/emojis/2/tone3.png b/public/-/emojis/2/tone3.png
new file mode 100644
index 00000000000..af925abe698
--- /dev/null
+++ b/public/-/emojis/2/tone3.png
Binary files differ
diff --git a/public/-/emojis/2/tone4.png b/public/-/emojis/2/tone4.png
new file mode 100644
index 00000000000..fb59d7b4419
--- /dev/null
+++ b/public/-/emojis/2/tone4.png
Binary files differ
diff --git a/public/-/emojis/2/tone5.png b/public/-/emojis/2/tone5.png
new file mode 100644
index 00000000000..b504a423322
--- /dev/null
+++ b/public/-/emojis/2/tone5.png
Binary files differ
diff --git a/public/-/emojis/2/tongue.png b/public/-/emojis/2/tongue.png
new file mode 100644
index 00000000000..d0d9d44b2ec
--- /dev/null
+++ b/public/-/emojis/2/tongue.png
Binary files differ
diff --git a/public/-/emojis/2/tools.png b/public/-/emojis/2/tools.png
new file mode 100644
index 00000000000..6a1936bc74e
--- /dev/null
+++ b/public/-/emojis/2/tools.png
Binary files differ
diff --git a/public/-/emojis/2/top.png b/public/-/emojis/2/top.png
new file mode 100644
index 00000000000..25dab3dea95
--- /dev/null
+++ b/public/-/emojis/2/top.png
Binary files differ
diff --git a/public/-/emojis/2/tophat.png b/public/-/emojis/2/tophat.png
new file mode 100644
index 00000000000..9f783e522cb
--- /dev/null
+++ b/public/-/emojis/2/tophat.png
Binary files differ
diff --git a/public/-/emojis/2/track_next.png b/public/-/emojis/2/track_next.png
new file mode 100644
index 00000000000..f6d79d955d9
--- /dev/null
+++ b/public/-/emojis/2/track_next.png
Binary files differ
diff --git a/public/-/emojis/2/track_previous.png b/public/-/emojis/2/track_previous.png
new file mode 100644
index 00000000000..ec520b9356d
--- /dev/null
+++ b/public/-/emojis/2/track_previous.png
Binary files differ
diff --git a/public/-/emojis/2/trackball.png b/public/-/emojis/2/trackball.png
new file mode 100644
index 00000000000..b3e7df4c87b
--- /dev/null
+++ b/public/-/emojis/2/trackball.png
Binary files differ
diff --git a/public/-/emojis/2/tractor.png b/public/-/emojis/2/tractor.png
new file mode 100644
index 00000000000..63c75e8845b
--- /dev/null
+++ b/public/-/emojis/2/tractor.png
Binary files differ
diff --git a/public/-/emojis/2/traffic_light.png b/public/-/emojis/2/traffic_light.png
new file mode 100644
index 00000000000..d93af70b1f5
--- /dev/null
+++ b/public/-/emojis/2/traffic_light.png
Binary files differ
diff --git a/public/-/emojis/2/train.png b/public/-/emojis/2/train.png
new file mode 100644
index 00000000000..f96833196a9
--- /dev/null
+++ b/public/-/emojis/2/train.png
Binary files differ
diff --git a/public/-/emojis/2/train2.png b/public/-/emojis/2/train2.png
new file mode 100644
index 00000000000..5062b323b46
--- /dev/null
+++ b/public/-/emojis/2/train2.png
Binary files differ
diff --git a/public/-/emojis/2/tram.png b/public/-/emojis/2/tram.png
new file mode 100644
index 00000000000..c544d624f42
--- /dev/null
+++ b/public/-/emojis/2/tram.png
Binary files differ
diff --git a/public/-/emojis/2/triangular_flag_on_post.png b/public/-/emojis/2/triangular_flag_on_post.png
new file mode 100644
index 00000000000..f1d2b3b3ee7
--- /dev/null
+++ b/public/-/emojis/2/triangular_flag_on_post.png
Binary files differ
diff --git a/public/-/emojis/2/triangular_ruler.png b/public/-/emojis/2/triangular_ruler.png
new file mode 100644
index 00000000000..06d1b219853
--- /dev/null
+++ b/public/-/emojis/2/triangular_ruler.png
Binary files differ
diff --git a/public/-/emojis/2/trident.png b/public/-/emojis/2/trident.png
new file mode 100644
index 00000000000..00bbaf72b0e
--- /dev/null
+++ b/public/-/emojis/2/trident.png
Binary files differ
diff --git a/public/-/emojis/2/triumph.png b/public/-/emojis/2/triumph.png
new file mode 100644
index 00000000000..950ce46587f
--- /dev/null
+++ b/public/-/emojis/2/triumph.png
Binary files differ
diff --git a/public/-/emojis/2/trolleybus.png b/public/-/emojis/2/trolleybus.png
new file mode 100644
index 00000000000..9c28d71c413
--- /dev/null
+++ b/public/-/emojis/2/trolleybus.png
Binary files differ
diff --git a/public/-/emojis/2/trophy.png b/public/-/emojis/2/trophy.png
new file mode 100644
index 00000000000..b2ad4f41106
--- /dev/null
+++ b/public/-/emojis/2/trophy.png
Binary files differ
diff --git a/public/-/emojis/2/tropical_drink.png b/public/-/emojis/2/tropical_drink.png
new file mode 100644
index 00000000000..2d65920c251
--- /dev/null
+++ b/public/-/emojis/2/tropical_drink.png
Binary files differ
diff --git a/public/-/emojis/2/tropical_fish.png b/public/-/emojis/2/tropical_fish.png
new file mode 100644
index 00000000000..d45b9c27f09
--- /dev/null
+++ b/public/-/emojis/2/tropical_fish.png
Binary files differ
diff --git a/public/-/emojis/2/truck.png b/public/-/emojis/2/truck.png
new file mode 100644
index 00000000000..ebd86859411
--- /dev/null
+++ b/public/-/emojis/2/truck.png
Binary files differ
diff --git a/public/-/emojis/2/trumpet.png b/public/-/emojis/2/trumpet.png
new file mode 100644
index 00000000000..c3d1f597f99
--- /dev/null
+++ b/public/-/emojis/2/trumpet.png
Binary files differ
diff --git a/public/-/emojis/2/tulip.png b/public/-/emojis/2/tulip.png
new file mode 100644
index 00000000000..8645096f26c
--- /dev/null
+++ b/public/-/emojis/2/tulip.png
Binary files differ
diff --git a/public/-/emojis/2/tumbler_glass.png b/public/-/emojis/2/tumbler_glass.png
new file mode 100644
index 00000000000..82d941552da
--- /dev/null
+++ b/public/-/emojis/2/tumbler_glass.png
Binary files differ
diff --git a/public/-/emojis/2/turkey.png b/public/-/emojis/2/turkey.png
new file mode 100644
index 00000000000..9de58f0f129
--- /dev/null
+++ b/public/-/emojis/2/turkey.png
Binary files differ
diff --git a/public/-/emojis/2/turtle.png b/public/-/emojis/2/turtle.png
new file mode 100644
index 00000000000..c4b54451a92
--- /dev/null
+++ b/public/-/emojis/2/turtle.png
Binary files differ
diff --git a/public/-/emojis/2/tv.png b/public/-/emojis/2/tv.png
new file mode 100644
index 00000000000..3f07ce033de
--- /dev/null
+++ b/public/-/emojis/2/tv.png
Binary files differ
diff --git a/public/-/emojis/2/twisted_rightwards_arrows.png b/public/-/emojis/2/twisted_rightwards_arrows.png
new file mode 100644
index 00000000000..4fe9d76f52d
--- /dev/null
+++ b/public/-/emojis/2/twisted_rightwards_arrows.png
Binary files differ
diff --git a/public/-/emojis/2/two.png b/public/-/emojis/2/two.png
new file mode 100644
index 00000000000..1cce3c264ac
--- /dev/null
+++ b/public/-/emojis/2/two.png
Binary files differ
diff --git a/public/-/emojis/2/two_hearts.png b/public/-/emojis/2/two_hearts.png
new file mode 100644
index 00000000000..6208168d076
--- /dev/null
+++ b/public/-/emojis/2/two_hearts.png
Binary files differ
diff --git a/public/-/emojis/2/two_men_holding_hands.png b/public/-/emojis/2/two_men_holding_hands.png
new file mode 100644
index 00000000000..3cacda77c25
--- /dev/null
+++ b/public/-/emojis/2/two_men_holding_hands.png
Binary files differ
diff --git a/public/-/emojis/2/two_women_holding_hands.png b/public/-/emojis/2/two_women_holding_hands.png
new file mode 100644
index 00000000000..f141a967450
--- /dev/null
+++ b/public/-/emojis/2/two_women_holding_hands.png
Binary files differ
diff --git a/public/-/emojis/2/u5272.png b/public/-/emojis/2/u5272.png
new file mode 100644
index 00000000000..af2bdaf6f67
--- /dev/null
+++ b/public/-/emojis/2/u5272.png
Binary files differ
diff --git a/public/-/emojis/2/u5408.png b/public/-/emojis/2/u5408.png
new file mode 100644
index 00000000000..f5b45188612
--- /dev/null
+++ b/public/-/emojis/2/u5408.png
Binary files differ
diff --git a/public/-/emojis/2/u55b6.png b/public/-/emojis/2/u55b6.png
new file mode 100644
index 00000000000..3e092ffecc2
--- /dev/null
+++ b/public/-/emojis/2/u55b6.png
Binary files differ
diff --git a/public/-/emojis/2/u6307.png b/public/-/emojis/2/u6307.png
new file mode 100644
index 00000000000..2a0e7a8a65f
--- /dev/null
+++ b/public/-/emojis/2/u6307.png
Binary files differ
diff --git a/public/-/emojis/2/u6708.png b/public/-/emojis/2/u6708.png
new file mode 100644
index 00000000000..d039b4606f1
--- /dev/null
+++ b/public/-/emojis/2/u6708.png
Binary files differ
diff --git a/public/-/emojis/2/u6709.png b/public/-/emojis/2/u6709.png
new file mode 100644
index 00000000000..b789aab56f4
--- /dev/null
+++ b/public/-/emojis/2/u6709.png
Binary files differ
diff --git a/public/-/emojis/2/u6e80.png b/public/-/emojis/2/u6e80.png
new file mode 100644
index 00000000000..8289f0fec7f
--- /dev/null
+++ b/public/-/emojis/2/u6e80.png
Binary files differ
diff --git a/public/-/emojis/2/u7121.png b/public/-/emojis/2/u7121.png
new file mode 100644
index 00000000000..eb2c66415b3
--- /dev/null
+++ b/public/-/emojis/2/u7121.png
Binary files differ
diff --git a/public/-/emojis/2/u7533.png b/public/-/emojis/2/u7533.png
new file mode 100644
index 00000000000..5829da3fe8e
--- /dev/null
+++ b/public/-/emojis/2/u7533.png
Binary files differ
diff --git a/public/-/emojis/2/u7981.png b/public/-/emojis/2/u7981.png
new file mode 100644
index 00000000000..d455dab4329
--- /dev/null
+++ b/public/-/emojis/2/u7981.png
Binary files differ
diff --git a/public/-/emojis/2/u7a7a.png b/public/-/emojis/2/u7a7a.png
new file mode 100644
index 00000000000..1d3d13041d6
--- /dev/null
+++ b/public/-/emojis/2/u7a7a.png
Binary files differ
diff --git a/public/-/emojis/2/umbrella.png b/public/-/emojis/2/umbrella.png
new file mode 100644
index 00000000000..56a6e5eb923
--- /dev/null
+++ b/public/-/emojis/2/umbrella.png
Binary files differ
diff --git a/public/-/emojis/2/umbrella2.png b/public/-/emojis/2/umbrella2.png
new file mode 100644
index 00000000000..7ce97ac53df
--- /dev/null
+++ b/public/-/emojis/2/umbrella2.png
Binary files differ
diff --git a/public/-/emojis/2/unamused.png b/public/-/emojis/2/unamused.png
new file mode 100644
index 00000000000..0e4cc248916
--- /dev/null
+++ b/public/-/emojis/2/unamused.png
Binary files differ
diff --git a/public/-/emojis/2/underage.png b/public/-/emojis/2/underage.png
new file mode 100644
index 00000000000..9921bd26260
--- /dev/null
+++ b/public/-/emojis/2/underage.png
Binary files differ
diff --git a/public/-/emojis/2/unicorn.png b/public/-/emojis/2/unicorn.png
new file mode 100644
index 00000000000..d37e6849fa3
--- /dev/null
+++ b/public/-/emojis/2/unicorn.png
Binary files differ
diff --git a/public/-/emojis/2/unlock.png b/public/-/emojis/2/unlock.png
new file mode 100644
index 00000000000..a6c556e31d2
--- /dev/null
+++ b/public/-/emojis/2/unlock.png
Binary files differ
diff --git a/public/-/emojis/2/up.png b/public/-/emojis/2/up.png
new file mode 100644
index 00000000000..4f72637fcaf
--- /dev/null
+++ b/public/-/emojis/2/up.png
Binary files differ
diff --git a/public/-/emojis/2/upside_down.png b/public/-/emojis/2/upside_down.png
new file mode 100644
index 00000000000..c993b35aa95
--- /dev/null
+++ b/public/-/emojis/2/upside_down.png
Binary files differ
diff --git a/public/-/emojis/2/urn.png b/public/-/emojis/2/urn.png
new file mode 100644
index 00000000000..340954510da
--- /dev/null
+++ b/public/-/emojis/2/urn.png
Binary files differ
diff --git a/public/-/emojis/2/v.png b/public/-/emojis/2/v.png
new file mode 100644
index 00000000000..55b99f99a95
--- /dev/null
+++ b/public/-/emojis/2/v.png
Binary files differ
diff --git a/public/-/emojis/2/v_tone1.png b/public/-/emojis/2/v_tone1.png
new file mode 100644
index 00000000000..f05ddd7132e
--- /dev/null
+++ b/public/-/emojis/2/v_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/v_tone2.png b/public/-/emojis/2/v_tone2.png
new file mode 100644
index 00000000000..3dc8e215ec6
--- /dev/null
+++ b/public/-/emojis/2/v_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/v_tone3.png b/public/-/emojis/2/v_tone3.png
new file mode 100644
index 00000000000..ac5033f39f1
--- /dev/null
+++ b/public/-/emojis/2/v_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/v_tone4.png b/public/-/emojis/2/v_tone4.png
new file mode 100644
index 00000000000..495c1a2c84b
--- /dev/null
+++ b/public/-/emojis/2/v_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/v_tone5.png b/public/-/emojis/2/v_tone5.png
new file mode 100644
index 00000000000..581e075bf78
--- /dev/null
+++ b/public/-/emojis/2/v_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/vertical_traffic_light.png b/public/-/emojis/2/vertical_traffic_light.png
new file mode 100644
index 00000000000..fc3148c2ab8
--- /dev/null
+++ b/public/-/emojis/2/vertical_traffic_light.png
Binary files differ
diff --git a/public/-/emojis/2/vhs.png b/public/-/emojis/2/vhs.png
new file mode 100644
index 00000000000..11c6e63b4a3
--- /dev/null
+++ b/public/-/emojis/2/vhs.png
Binary files differ
diff --git a/public/-/emojis/2/vibration_mode.png b/public/-/emojis/2/vibration_mode.png
new file mode 100644
index 00000000000..fe2699ba676
--- /dev/null
+++ b/public/-/emojis/2/vibration_mode.png
Binary files differ
diff --git a/public/-/emojis/2/video_camera.png b/public/-/emojis/2/video_camera.png
new file mode 100644
index 00000000000..89d9725d50e
--- /dev/null
+++ b/public/-/emojis/2/video_camera.png
Binary files differ
diff --git a/public/-/emojis/2/video_game.png b/public/-/emojis/2/video_game.png
new file mode 100644
index 00000000000..552c18f8ca5
--- /dev/null
+++ b/public/-/emojis/2/video_game.png
Binary files differ
diff --git a/public/-/emojis/2/violin.png b/public/-/emojis/2/violin.png
new file mode 100644
index 00000000000..578d1c7b2b9
--- /dev/null
+++ b/public/-/emojis/2/violin.png
Binary files differ
diff --git a/public/-/emojis/2/virgo.png b/public/-/emojis/2/virgo.png
new file mode 100644
index 00000000000..2e7254a45e7
--- /dev/null
+++ b/public/-/emojis/2/virgo.png
Binary files differ
diff --git a/public/-/emojis/2/volcano.png b/public/-/emojis/2/volcano.png
new file mode 100644
index 00000000000..bc210edcb1c
--- /dev/null
+++ b/public/-/emojis/2/volcano.png
Binary files differ
diff --git a/public/-/emojis/2/volleyball.png b/public/-/emojis/2/volleyball.png
new file mode 100644
index 00000000000..8eeef790dcc
--- /dev/null
+++ b/public/-/emojis/2/volleyball.png
Binary files differ
diff --git a/public/-/emojis/2/vs.png b/public/-/emojis/2/vs.png
new file mode 100644
index 00000000000..c55dba709a0
--- /dev/null
+++ b/public/-/emojis/2/vs.png
Binary files differ
diff --git a/public/-/emojis/2/vulcan.png b/public/-/emojis/2/vulcan.png
new file mode 100644
index 00000000000..91bedcdb15a
--- /dev/null
+++ b/public/-/emojis/2/vulcan.png
Binary files differ
diff --git a/public/-/emojis/2/vulcan_tone1.png b/public/-/emojis/2/vulcan_tone1.png
new file mode 100644
index 00000000000..ec1fa548399
--- /dev/null
+++ b/public/-/emojis/2/vulcan_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/vulcan_tone2.png b/public/-/emojis/2/vulcan_tone2.png
new file mode 100644
index 00000000000..85c89abfb4e
--- /dev/null
+++ b/public/-/emojis/2/vulcan_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/vulcan_tone3.png b/public/-/emojis/2/vulcan_tone3.png
new file mode 100644
index 00000000000..b0dde6562b8
--- /dev/null
+++ b/public/-/emojis/2/vulcan_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/vulcan_tone4.png b/public/-/emojis/2/vulcan_tone4.png
new file mode 100644
index 00000000000..b1c7ff8f608
--- /dev/null
+++ b/public/-/emojis/2/vulcan_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/vulcan_tone5.png b/public/-/emojis/2/vulcan_tone5.png
new file mode 100644
index 00000000000..6d80c03bd82
--- /dev/null
+++ b/public/-/emojis/2/vulcan_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/walking.png b/public/-/emojis/2/walking.png
new file mode 100644
index 00000000000..d682c0a05b0
--- /dev/null
+++ b/public/-/emojis/2/walking.png
Binary files differ
diff --git a/public/-/emojis/2/walking_tone1.png b/public/-/emojis/2/walking_tone1.png
new file mode 100644
index 00000000000..0012e8bf9be
--- /dev/null
+++ b/public/-/emojis/2/walking_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/walking_tone2.png b/public/-/emojis/2/walking_tone2.png
new file mode 100644
index 00000000000..6e4315de104
--- /dev/null
+++ b/public/-/emojis/2/walking_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/walking_tone3.png b/public/-/emojis/2/walking_tone3.png
new file mode 100644
index 00000000000..23db8941f74
--- /dev/null
+++ b/public/-/emojis/2/walking_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/walking_tone4.png b/public/-/emojis/2/walking_tone4.png
new file mode 100644
index 00000000000..09ed954c93b
--- /dev/null
+++ b/public/-/emojis/2/walking_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/walking_tone5.png b/public/-/emojis/2/walking_tone5.png
new file mode 100644
index 00000000000..c4d8d3b5ef4
--- /dev/null
+++ b/public/-/emojis/2/walking_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/waning_crescent_moon.png b/public/-/emojis/2/waning_crescent_moon.png
new file mode 100644
index 00000000000..7b8237edbb3
--- /dev/null
+++ b/public/-/emojis/2/waning_crescent_moon.png
Binary files differ
diff --git a/public/-/emojis/2/waning_gibbous_moon.png b/public/-/emojis/2/waning_gibbous_moon.png
new file mode 100644
index 00000000000..59b7f2cb950
--- /dev/null
+++ b/public/-/emojis/2/waning_gibbous_moon.png
Binary files differ
diff --git a/public/-/emojis/2/warning.png b/public/-/emojis/2/warning.png
new file mode 100644
index 00000000000..57784fe8def
--- /dev/null
+++ b/public/-/emojis/2/warning.png
Binary files differ
diff --git a/public/-/emojis/2/wastebasket.png b/public/-/emojis/2/wastebasket.png
new file mode 100644
index 00000000000..cd8057de563
--- /dev/null
+++ b/public/-/emojis/2/wastebasket.png
Binary files differ
diff --git a/public/-/emojis/2/watch.png b/public/-/emojis/2/watch.png
new file mode 100644
index 00000000000..e11a17bb054
--- /dev/null
+++ b/public/-/emojis/2/watch.png
Binary files differ
diff --git a/public/-/emojis/2/water_buffalo.png b/public/-/emojis/2/water_buffalo.png
new file mode 100644
index 00000000000..bd32406dae1
--- /dev/null
+++ b/public/-/emojis/2/water_buffalo.png
Binary files differ
diff --git a/public/-/emojis/2/water_polo.png b/public/-/emojis/2/water_polo.png
new file mode 100644
index 00000000000..90206e62917
--- /dev/null
+++ b/public/-/emojis/2/water_polo.png
Binary files differ
diff --git a/public/-/emojis/2/water_polo_tone1.png b/public/-/emojis/2/water_polo_tone1.png
new file mode 100644
index 00000000000..f463506ac69
--- /dev/null
+++ b/public/-/emojis/2/water_polo_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/water_polo_tone2.png b/public/-/emojis/2/water_polo_tone2.png
new file mode 100644
index 00000000000..a02eaaa6b3f
--- /dev/null
+++ b/public/-/emojis/2/water_polo_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/water_polo_tone3.png b/public/-/emojis/2/water_polo_tone3.png
new file mode 100644
index 00000000000..f4f80b9946c
--- /dev/null
+++ b/public/-/emojis/2/water_polo_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/water_polo_tone4.png b/public/-/emojis/2/water_polo_tone4.png
new file mode 100644
index 00000000000..260b27791c2
--- /dev/null
+++ b/public/-/emojis/2/water_polo_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/water_polo_tone5.png b/public/-/emojis/2/water_polo_tone5.png
new file mode 100644
index 00000000000..73cb325ba51
--- /dev/null
+++ b/public/-/emojis/2/water_polo_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/watermelon.png b/public/-/emojis/2/watermelon.png
new file mode 100644
index 00000000000..93448a8f2c4
--- /dev/null
+++ b/public/-/emojis/2/watermelon.png
Binary files differ
diff --git a/public/-/emojis/2/wave.png b/public/-/emojis/2/wave.png
new file mode 100644
index 00000000000..3161c2a6faf
--- /dev/null
+++ b/public/-/emojis/2/wave.png
Binary files differ
diff --git a/public/-/emojis/2/wave_tone1.png b/public/-/emojis/2/wave_tone1.png
new file mode 100644
index 00000000000..a45cc13862c
--- /dev/null
+++ b/public/-/emojis/2/wave_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/wave_tone2.png b/public/-/emojis/2/wave_tone2.png
new file mode 100644
index 00000000000..af3f1ae0e4a
--- /dev/null
+++ b/public/-/emojis/2/wave_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/wave_tone3.png b/public/-/emojis/2/wave_tone3.png
new file mode 100644
index 00000000000..7d1f9c475cc
--- /dev/null
+++ b/public/-/emojis/2/wave_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/wave_tone4.png b/public/-/emojis/2/wave_tone4.png
new file mode 100644
index 00000000000..c4e29a1ea8d
--- /dev/null
+++ b/public/-/emojis/2/wave_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/wave_tone5.png b/public/-/emojis/2/wave_tone5.png
new file mode 100644
index 00000000000..91925afcb28
--- /dev/null
+++ b/public/-/emojis/2/wave_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/wavy_dash.png b/public/-/emojis/2/wavy_dash.png
new file mode 100644
index 00000000000..54b7c2eff3f
--- /dev/null
+++ b/public/-/emojis/2/wavy_dash.png
Binary files differ
diff --git a/public/-/emojis/2/waxing_crescent_moon.png b/public/-/emojis/2/waxing_crescent_moon.png
new file mode 100644
index 00000000000..ae26131838d
--- /dev/null
+++ b/public/-/emojis/2/waxing_crescent_moon.png
Binary files differ
diff --git a/public/-/emojis/2/waxing_gibbous_moon.png b/public/-/emojis/2/waxing_gibbous_moon.png
new file mode 100644
index 00000000000..3c50dd6b778
--- /dev/null
+++ b/public/-/emojis/2/waxing_gibbous_moon.png
Binary files differ
diff --git a/public/-/emojis/2/wc.png b/public/-/emojis/2/wc.png
new file mode 100644
index 00000000000..be3d80ab1ac
--- /dev/null
+++ b/public/-/emojis/2/wc.png
Binary files differ
diff --git a/public/-/emojis/2/weary.png b/public/-/emojis/2/weary.png
new file mode 100644
index 00000000000..1492622b838
--- /dev/null
+++ b/public/-/emojis/2/weary.png
Binary files differ
diff --git a/public/-/emojis/2/wedding.png b/public/-/emojis/2/wedding.png
new file mode 100644
index 00000000000..ac86a232e67
--- /dev/null
+++ b/public/-/emojis/2/wedding.png
Binary files differ
diff --git a/public/-/emojis/2/whale.png b/public/-/emojis/2/whale.png
new file mode 100644
index 00000000000..d6326af1a15
--- /dev/null
+++ b/public/-/emojis/2/whale.png
Binary files differ
diff --git a/public/-/emojis/2/whale2.png b/public/-/emojis/2/whale2.png
new file mode 100644
index 00000000000..7b586e17b52
--- /dev/null
+++ b/public/-/emojis/2/whale2.png
Binary files differ
diff --git a/public/-/emojis/2/wheel_of_dharma.png b/public/-/emojis/2/wheel_of_dharma.png
new file mode 100644
index 00000000000..3fff7c63b61
--- /dev/null
+++ b/public/-/emojis/2/wheel_of_dharma.png
Binary files differ
diff --git a/public/-/emojis/2/wheelchair.png b/public/-/emojis/2/wheelchair.png
new file mode 100644
index 00000000000..260c05e88bd
--- /dev/null
+++ b/public/-/emojis/2/wheelchair.png
Binary files differ
diff --git a/public/-/emojis/2/white_check_mark.png b/public/-/emojis/2/white_check_mark.png
new file mode 100644
index 00000000000..82035d48bc0
--- /dev/null
+++ b/public/-/emojis/2/white_check_mark.png
Binary files differ
diff --git a/public/-/emojis/2/white_circle.png b/public/-/emojis/2/white_circle.png
new file mode 100644
index 00000000000..e5aa5bb4e70
--- /dev/null
+++ b/public/-/emojis/2/white_circle.png
Binary files differ
diff --git a/public/-/emojis/2/white_flower.png b/public/-/emojis/2/white_flower.png
new file mode 100644
index 00000000000..e165fe1910a
--- /dev/null
+++ b/public/-/emojis/2/white_flower.png
Binary files differ
diff --git a/public/-/emojis/2/white_large_square.png b/public/-/emojis/2/white_large_square.png
new file mode 100644
index 00000000000..2e216c74f19
--- /dev/null
+++ b/public/-/emojis/2/white_large_square.png
Binary files differ
diff --git a/public/-/emojis/2/white_medium_small_square.png b/public/-/emojis/2/white_medium_small_square.png
new file mode 100644
index 00000000000..eb79781b466
--- /dev/null
+++ b/public/-/emojis/2/white_medium_small_square.png
Binary files differ
diff --git a/public/-/emojis/2/white_medium_square.png b/public/-/emojis/2/white_medium_square.png
new file mode 100644
index 00000000000..6b7c6585b32
--- /dev/null
+++ b/public/-/emojis/2/white_medium_square.png
Binary files differ
diff --git a/public/-/emojis/2/white_small_square.png b/public/-/emojis/2/white_small_square.png
new file mode 100644
index 00000000000..09f2f1d1bbf
--- /dev/null
+++ b/public/-/emojis/2/white_small_square.png
Binary files differ
diff --git a/public/-/emojis/2/white_square_button.png b/public/-/emojis/2/white_square_button.png
new file mode 100644
index 00000000000..1eb1af7a77b
--- /dev/null
+++ b/public/-/emojis/2/white_square_button.png
Binary files differ
diff --git a/public/-/emojis/2/white_sun_cloud.png b/public/-/emojis/2/white_sun_cloud.png
new file mode 100644
index 00000000000..a6982814fa4
--- /dev/null
+++ b/public/-/emojis/2/white_sun_cloud.png
Binary files differ
diff --git a/public/-/emojis/2/white_sun_rain_cloud.png b/public/-/emojis/2/white_sun_rain_cloud.png
new file mode 100644
index 00000000000..a4b13e900a4
--- /dev/null
+++ b/public/-/emojis/2/white_sun_rain_cloud.png
Binary files differ
diff --git a/public/-/emojis/2/white_sun_small_cloud.png b/public/-/emojis/2/white_sun_small_cloud.png
new file mode 100644
index 00000000000..6c00833eb19
--- /dev/null
+++ b/public/-/emojis/2/white_sun_small_cloud.png
Binary files differ
diff --git a/public/-/emojis/2/wilted_rose.png b/public/-/emojis/2/wilted_rose.png
new file mode 100644
index 00000000000..03919a12094
--- /dev/null
+++ b/public/-/emojis/2/wilted_rose.png
Binary files differ
diff --git a/public/-/emojis/2/wind_blowing_face.png b/public/-/emojis/2/wind_blowing_face.png
new file mode 100644
index 00000000000..32e658bcbec
--- /dev/null
+++ b/public/-/emojis/2/wind_blowing_face.png
Binary files differ
diff --git a/public/-/emojis/2/wind_chime.png b/public/-/emojis/2/wind_chime.png
new file mode 100644
index 00000000000..5f5add3cba5
--- /dev/null
+++ b/public/-/emojis/2/wind_chime.png
Binary files differ
diff --git a/public/-/emojis/2/wine_glass.png b/public/-/emojis/2/wine_glass.png
new file mode 100644
index 00000000000..63c94e0cf6c
--- /dev/null
+++ b/public/-/emojis/2/wine_glass.png
Binary files differ
diff --git a/public/-/emojis/2/wink.png b/public/-/emojis/2/wink.png
new file mode 100644
index 00000000000..c605d9c2c78
--- /dev/null
+++ b/public/-/emojis/2/wink.png
Binary files differ
diff --git a/public/-/emojis/2/wolf.png b/public/-/emojis/2/wolf.png
new file mode 100644
index 00000000000..b5b06c27786
--- /dev/null
+++ b/public/-/emojis/2/wolf.png
Binary files differ
diff --git a/public/-/emojis/2/woman.png b/public/-/emojis/2/woman.png
new file mode 100644
index 00000000000..75533da530f
--- /dev/null
+++ b/public/-/emojis/2/woman.png
Binary files differ
diff --git a/public/-/emojis/2/woman_tone1.png b/public/-/emojis/2/woman_tone1.png
new file mode 100644
index 00000000000..a41f4f2f555
--- /dev/null
+++ b/public/-/emojis/2/woman_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/woman_tone2.png b/public/-/emojis/2/woman_tone2.png
new file mode 100644
index 00000000000..6ec6de75016
--- /dev/null
+++ b/public/-/emojis/2/woman_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/woman_tone3.png b/public/-/emojis/2/woman_tone3.png
new file mode 100644
index 00000000000..9c08adebd65
--- /dev/null
+++ b/public/-/emojis/2/woman_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/woman_tone4.png b/public/-/emojis/2/woman_tone4.png
new file mode 100644
index 00000000000..88cbdbc798a
--- /dev/null
+++ b/public/-/emojis/2/woman_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/woman_tone5.png b/public/-/emojis/2/woman_tone5.png
new file mode 100644
index 00000000000..b02ec4b4af1
--- /dev/null
+++ b/public/-/emojis/2/woman_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/womans_clothes.png b/public/-/emojis/2/womans_clothes.png
new file mode 100644
index 00000000000..86f89f19f37
--- /dev/null
+++ b/public/-/emojis/2/womans_clothes.png
Binary files differ
diff --git a/public/-/emojis/2/womans_hat.png b/public/-/emojis/2/womans_hat.png
new file mode 100644
index 00000000000..b69fcad7e49
--- /dev/null
+++ b/public/-/emojis/2/womans_hat.png
Binary files differ
diff --git a/public/-/emojis/2/womens.png b/public/-/emojis/2/womens.png
new file mode 100644
index 00000000000..ea38f1a854d
--- /dev/null
+++ b/public/-/emojis/2/womens.png
Binary files differ
diff --git a/public/-/emojis/2/worried.png b/public/-/emojis/2/worried.png
new file mode 100644
index 00000000000..b85910fb297
--- /dev/null
+++ b/public/-/emojis/2/worried.png
Binary files differ
diff --git a/public/-/emojis/2/wrench.png b/public/-/emojis/2/wrench.png
new file mode 100644
index 00000000000..feff25c2113
--- /dev/null
+++ b/public/-/emojis/2/wrench.png
Binary files differ
diff --git a/public/-/emojis/2/wrestlers.png b/public/-/emojis/2/wrestlers.png
new file mode 100644
index 00000000000..58175c6ecbe
--- /dev/null
+++ b/public/-/emojis/2/wrestlers.png
Binary files differ
diff --git a/public/-/emojis/2/wrestlers_tone1.png b/public/-/emojis/2/wrestlers_tone1.png
new file mode 100644
index 00000000000..55c8bb3fcc2
--- /dev/null
+++ b/public/-/emojis/2/wrestlers_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/wrestlers_tone2.png b/public/-/emojis/2/wrestlers_tone2.png
new file mode 100644
index 00000000000..2ae6989956d
--- /dev/null
+++ b/public/-/emojis/2/wrestlers_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/wrestlers_tone3.png b/public/-/emojis/2/wrestlers_tone3.png
new file mode 100644
index 00000000000..bff6020b931
--- /dev/null
+++ b/public/-/emojis/2/wrestlers_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/wrestlers_tone4.png b/public/-/emojis/2/wrestlers_tone4.png
new file mode 100644
index 00000000000..d09cf19262b
--- /dev/null
+++ b/public/-/emojis/2/wrestlers_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/wrestlers_tone5.png b/public/-/emojis/2/wrestlers_tone5.png
new file mode 100644
index 00000000000..0850e7d1e42
--- /dev/null
+++ b/public/-/emojis/2/wrestlers_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/writing_hand.png b/public/-/emojis/2/writing_hand.png
new file mode 100644
index 00000000000..9a2691a0dc4
--- /dev/null
+++ b/public/-/emojis/2/writing_hand.png
Binary files differ
diff --git a/public/-/emojis/2/writing_hand_tone1.png b/public/-/emojis/2/writing_hand_tone1.png
new file mode 100644
index 00000000000..bf821143858
--- /dev/null
+++ b/public/-/emojis/2/writing_hand_tone1.png
Binary files differ
diff --git a/public/-/emojis/2/writing_hand_tone2.png b/public/-/emojis/2/writing_hand_tone2.png
new file mode 100644
index 00000000000..c7fa4523983
--- /dev/null
+++ b/public/-/emojis/2/writing_hand_tone2.png
Binary files differ
diff --git a/public/-/emojis/2/writing_hand_tone3.png b/public/-/emojis/2/writing_hand_tone3.png
new file mode 100644
index 00000000000..c41e68bd2bc
--- /dev/null
+++ b/public/-/emojis/2/writing_hand_tone3.png
Binary files differ
diff --git a/public/-/emojis/2/writing_hand_tone4.png b/public/-/emojis/2/writing_hand_tone4.png
new file mode 100644
index 00000000000..448d3507e9c
--- /dev/null
+++ b/public/-/emojis/2/writing_hand_tone4.png
Binary files differ
diff --git a/public/-/emojis/2/writing_hand_tone5.png b/public/-/emojis/2/writing_hand_tone5.png
new file mode 100644
index 00000000000..7959873d60d
--- /dev/null
+++ b/public/-/emojis/2/writing_hand_tone5.png
Binary files differ
diff --git a/public/-/emojis/2/x.png b/public/-/emojis/2/x.png
new file mode 100644
index 00000000000..9406c87c5f0
--- /dev/null
+++ b/public/-/emojis/2/x.png
Binary files differ
diff --git a/public/-/emojis/2/yellow_heart.png b/public/-/emojis/2/yellow_heart.png
new file mode 100644
index 00000000000..8067e9413e8
--- /dev/null
+++ b/public/-/emojis/2/yellow_heart.png
Binary files differ
diff --git a/public/-/emojis/2/yen.png b/public/-/emojis/2/yen.png
new file mode 100644
index 00000000000..72258005f08
--- /dev/null
+++ b/public/-/emojis/2/yen.png
Binary files differ
diff --git a/public/-/emojis/2/yin_yang.png b/public/-/emojis/2/yin_yang.png
new file mode 100644
index 00000000000..35ae33c4326
--- /dev/null
+++ b/public/-/emojis/2/yin_yang.png
Binary files differ
diff --git a/public/-/emojis/2/yum.png b/public/-/emojis/2/yum.png
new file mode 100644
index 00000000000..ead526319f4
--- /dev/null
+++ b/public/-/emojis/2/yum.png
Binary files differ
diff --git a/public/-/emojis/2/zap.png b/public/-/emojis/2/zap.png
new file mode 100644
index 00000000000..7271a50bcba
--- /dev/null
+++ b/public/-/emojis/2/zap.png
Binary files differ
diff --git a/public/-/emojis/2/zero.png b/public/-/emojis/2/zero.png
new file mode 100644
index 00000000000..db3f638a02c
--- /dev/null
+++ b/public/-/emojis/2/zero.png
Binary files differ
diff --git a/public/-/emojis/2/zipper_mouth.png b/public/-/emojis/2/zipper_mouth.png
new file mode 100644
index 00000000000..58915b98f57
--- /dev/null
+++ b/public/-/emojis/2/zipper_mouth.png
Binary files differ
diff --git a/public/-/emojis/2/zzz.png b/public/-/emojis/2/zzz.png
new file mode 100644
index 00000000000..4b146f52bde
--- /dev/null
+++ b/public/-/emojis/2/zzz.png
Binary files differ
diff --git a/public/robots.txt b/public/robots.txt
index e2cc6cf21b8..3eb867062f1 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -44,6 +44,7 @@ User-Agent: *
Disallow: /groups/*/analytics
Disallow: /groups/*/contribution_analytics
Disallow: /groups/*/group_members
+Disallow: /groups/*/-/saml/sso
# Project details
User-Agent: *
diff --git a/qa/Gemfile b/qa/Gemfile
index ee90d049d7b..498d05b2254 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -7,9 +7,9 @@ gem 'activesupport', '~> 6.1.4.1' # This should stay in sync with the root's Gem
gem 'allure-rspec', '~> 2.15.0'
gem 'capybara', '~> 3.35.0'
gem 'capybara-screenshot', '~> 1.0.23'
-gem 'rake', '~> 12.3.3'
+gem 'rake', '~> 13'
gem 'rspec', '~> 3.10'
-gem 'selenium-webdriver', '~> 4.0.0.rc1'
+gem 'selenium-webdriver', '~> 4.0'
gem 'airborne', '~> 0.3.4', require: false # airborne is messing with rspec sandboxed mode so not requiring by default
gem 'rest-client', '~> 2.1.0'
gem 'rspec-retry', '~> 0.6.1', require: 'rspec/retry'
@@ -22,9 +22,11 @@ gem 'timecop', '~> 0.9.1'
gem 'parallel', '~> 1.19'
gem 'rspec-parameterized', '~> 0.4.2'
gem 'octokit', '~> 4.21'
-gem 'webdrivers', '~> 4.6'
+gem 'webdrivers', '~> 5.0'
gem 'zeitwerk', '~> 2.4'
gem 'influxdb-client', '~> 1.17'
+gem 'terminal-table', '~> 1.8', require: false
+gem 'slack-notifier', '~> 2.4', require: false
gem 'chemlab', '~> 0.9'
gem 'chemlab-library-www-gitlab-com', '~> 0.1'
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 153a141d3fd..2b5b5e368cf 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -11,7 +11,7 @@ GEM
adamantium (0.2.0)
ice_nine (~> 0.11.0)
memoizable (~> 0.4.0)
- addressable (2.7.0)
+ addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
airborne (0.3.4)
activesupport
@@ -27,7 +27,7 @@ GEM
oj (>= 3.10, < 4)
require_all (>= 2, < 4)
uuid (>= 2.3, < 3)
- ast (2.4.1)
+ ast (2.4.2)
binding_ninja (0.2.3)
byebug (9.1.0)
capybara (3.35.3)
@@ -41,7 +41,7 @@ GEM
capybara-screenshot (1.0.23)
capybara (>= 1.0, < 4)
launchy
- chemlab (0.9.1)
+ chemlab (0.9.2)
colorize (~> 0.8)
i18n (~> 1.8)
rake (>= 12, < 14)
@@ -88,27 +88,25 @@ GEM
gitlab (4.16.1)
httparty (~> 0.14, >= 0.14.0)
terminal-table (~> 1.5, >= 1.5.1)
- gitlab-qa (7.9.1)
+ gitlab-qa (7.14.0)
activesupport (~> 6.1)
gitlab (~> 4.16.1)
- http (= 4.3.0)
+ http (~> 5.0)
nokogiri (~> 1.10)
table_print (= 1.5.7)
- http (4.3.0)
- addressable (~> 2.3)
+ http (5.0.4)
+ addressable (~> 2.8)
http-cookie (~> 1.0)
http-form_data (~> 2.2)
- http-parser (~> 1.2.0)
+ llhttp-ffi (~> 0.4.0)
http-accept (1.7.0)
- http-cookie (1.0.3)
+ http-cookie (1.0.4)
domain_name (~> 0.5)
http-form_data (2.3.0)
- http-parser (1.2.3)
- ffi-compiler (>= 1.0, < 2.0)
- httparty (0.19.0)
+ httparty (0.20.0)
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
- i18n (1.8.10)
+ i18n (1.8.11)
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
influxdb-client (1.17.0)
@@ -116,22 +114,25 @@ GEM
rake
launchy (2.4.3)
addressable (~> 2.3)
+ llhttp-ffi (0.4.0)
+ ffi-compiler (~> 1.0)
+ rake (~> 13.0)
macaddr (1.7.2)
systemu (~> 2.6.5)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
method_source (0.9.0)
- mime-types (3.3.1)
+ mime-types (3.4.0)
mime-types-data (~> 3.2015)
- mime-types-data (3.2021.0704)
+ mime-types-data (3.2021.1115)
mini_mime (1.1.0)
- mini_portile2 (2.5.3)
+ mini_portile2 (2.6.1)
minitest (5.14.4)
multi_xml (0.6.0)
multipart-post (2.1.1)
netrc (0.11.0)
- nokogiri (1.11.7)
- mini_portile2 (~> 2.5.0)
+ nokogiri (1.12.5)
+ mini_portile2 (~> 2.6.1)
racc (~> 1.4)
octokit (4.21.0)
faraday (>= 0.9)
@@ -140,7 +141,7 @@ GEM
parallel (1.19.2)
parallel_tests (2.29.0)
parallel
- parser (2.7.1.4)
+ parser (3.0.2.0)
ast (~> 2.4.1)
proc_to_ast (0.1.0)
coderay
@@ -153,12 +154,12 @@ GEM
pry-byebug (3.5.1)
byebug (~> 9.1)
pry (~> 0.10)
- public_suffix (4.0.1)
- racc (1.5.2)
+ public_suffix (4.0.6)
+ racc (1.6.0)
rack (2.2.3)
rack-test (1.1.0)
rack (>= 1.0, < 3)
- rake (12.3.3)
+ rake (13.0.6)
regexp_parser (2.1.1)
require_all (3.0.0)
rest-client (2.1.0)
@@ -198,10 +199,11 @@ GEM
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
- selenium-webdriver (4.0.0.rc1)
+ selenium-webdriver (4.0.3)
childprocess (>= 0.5, < 5.0)
- rexml (~> 3.2)
+ rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2)
+ slack-notifier (2.4.0)
systemu (2.6.5)
table_print (1.5.7)
terminal-table (1.8.0)
@@ -212,7 +214,7 @@ GEM
concurrent-ruby (~> 1.0)
unf (0.1.4)
unf_ext
- unf_ext (0.0.7.7)
+ unf_ext (0.0.8)
unicode-display_width (1.8.0)
unparser (0.4.7)
abstract_type (~> 0.0.7)
@@ -227,13 +229,13 @@ GEM
watir (6.19.1)
regexp_parser (>= 1.2, < 3)
selenium-webdriver (>= 3.142.7)
- webdrivers (4.6.0)
+ webdrivers (5.0.0)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
- selenium-webdriver (>= 3.0, < 4.0)
+ selenium-webdriver (~> 4.0)
xpath (3.2.0)
nokogiri (~> 1.8)
- zeitwerk (2.4.2)
+ zeitwerk (2.5.1)
PLATFORMS
ruby
@@ -255,7 +257,7 @@ DEPENDENCIES
parallel (~> 1.19)
parallel_tests (~> 2.29)
pry-byebug (~> 3.5.1)
- rake (~> 12.3.3)
+ rake (~> 13)
rest-client (~> 2.1.0)
rotp (~> 3.1.0)
rspec (~> 3.10)
@@ -263,10 +265,12 @@ DEPENDENCIES
rspec-retry (~> 0.6.1)
rspec_junit_formatter (~> 0.4.1)
ruby-debug-ide (~> 0.7.0)
- selenium-webdriver (~> 4.0.0.rc1)
+ selenium-webdriver (~> 4.0)
+ slack-notifier (~> 2.4)
+ terminal-table (~> 1.8)
timecop (~> 0.9.1)
- webdrivers (~> 4.6)
+ webdrivers (~> 5.0)
zeitwerk (~> 2.4)
BUNDLED WITH
- 2.2.22
+ 2.2.30
diff --git a/qa/Rakefile b/qa/Rakefile
index f24c81a9ec2..57360e98ca2 100644
--- a/qa/Rakefile
+++ b/qa/Rakefile
@@ -2,6 +2,7 @@
# rubocop:disable Rails/RakeEnvironment
load 'tasks/webdrivers.rake'
+load 'tasks/reliable_report.rake'
require_relative 'qa/tools/revoke_all_personal_access_tokens'
require_relative 'qa/tools/delete_subgroups'
diff --git a/qa/chemlab-library-gitlab.gemspec b/qa/chemlab-library-gitlab.gemspec
index 34a55ba8927..9af4a650d98 100644
--- a/qa/chemlab-library-gitlab.gemspec
+++ b/qa/chemlab-library-gitlab.gemspec
@@ -19,4 +19,5 @@ Gem::Specification.new do |spec|
spec.require_paths = ['lib']
spec.add_runtime_dependency 'chemlab', '~> 0.9'
+ spec.add_runtime_dependency 'zeitwerk', '~> 2.4'
end
diff --git a/qa/lib/gitlab.rb b/qa/lib/gitlab.rb
index 4418e51facb..8c33071633d 100644
--- a/qa/lib/gitlab.rb
+++ b/qa/lib/gitlab.rb
@@ -1,31 +1,14 @@
# frozen_string_literal: true
require 'chemlab/library'
+require 'zeitwerk'
+
+loader = Zeitwerk::Loader.new
+loader.push_dir(__dir__)
+loader.ignore("#{__dir__}/gitlab/**/*.stub.rb") # ignore page stubs
+loader.setup
# Chemlab Page Libraries for GitLab
module Gitlab
include Chemlab::Library
-
- module Page
- module Main
- autoload :Login, 'gitlab/page/main/login'
- autoload :SignUp, 'gitlab/page/main/sign_up'
- end
-
- module Subscriptions
- autoload :New, 'gitlab/page/subscriptions/new'
- end
-
- module Admin
- autoload :Dashboard, 'gitlab/page/admin/dashboard'
- autoload :Subscription, 'gitlab/page/admin/subscription'
- end
-
- module Group
- module Settings
- autoload :Billing, 'gitlab/page/group/settings/billing'
- autoload :UsageQuotas, 'gitlab/page/group/settings/usage_quotas'
- end
- end
- end
end
diff --git a/qa/lib/gitlab/page/admin/subscription.rb b/qa/lib/gitlab/page/admin/subscription.rb
index 0f7c6b4c211..cdd9bb20b42 100644
--- a/qa/lib/gitlab/page/admin/subscription.rb
+++ b/qa/lib/gitlab/page/admin/subscription.rb
@@ -6,7 +6,16 @@ module Gitlab
class Subscription < Chemlab::Page
path '/admin/subscription'
+ p :plan
+ p :started
+ p :name
+ p :company
+ p :email
+ h2 :billable_users
+ h2 :maximum_users
h2 :users_in_subscription
+ h2 :users_over_subscription
+ table :subscription_history
end
end
end
diff --git a/qa/lib/gitlab/page/admin/subscription.stub.rb b/qa/lib/gitlab/page/admin/subscription.stub.rb
index 51f23e7f0d0..89d7bfb95d9 100644
--- a/qa/lib/gitlab/page/admin/subscription.stub.rb
+++ b/qa/lib/gitlab/page/admin/subscription.stub.rb
@@ -4,6 +4,174 @@ module Gitlab
module Page
module Admin
module Subscription
+ # @note Defined as +p :plan+
+ # @return [String] The text content or value of +plan+
+ def plan
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.plan_element).to exist
+ # end
+ # @return [Watir::P] The raw +P+ element
+ def plan_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_plan
+ # end
+ # @return [Boolean] true if the +plan+ element is present on the page
+ def plan?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +p :started+
+ # @return [String] The text content or value of +started+
+ def started
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.started_element).to exist
+ # end
+ # @return [Watir::P] The raw +P+ element
+ def started_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_started
+ # end
+ # @return [Boolean] true if the +started+ element is present on the page
+ def started?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +p :name+
+ # @return [String] The text content or value of +name+
+ def name
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.name_element).to exist
+ # end
+ # @return [Watir::P] The raw +P+ element
+ def name_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_name
+ # end
+ # @return [Boolean] true if the +name+ element is present on the page
+ def name?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +p :company+
+ # @return [String] The text content or value of +company+
+ def company
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.company_element).to exist
+ # end
+ # @return [Watir::P] The raw +P+ element
+ def company_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_company
+ # end
+ # @return [Boolean] true if the +company+ element is present on the page
+ def company?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +p :email+
+ # @return [String] The text content or value of +email+
+ def email
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.email_element).to exist
+ # end
+ # @return [Watir::P] The raw +P+ element
+ def email_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_email
+ # end
+ # @return [Boolean] true if the +email+ element is present on the page
+ def email?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +h2 :billable_users+
+ # @return [String] The text content or value of +billable_users+
+ def billable_users
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.billable_users_element).to exist
+ # end
+ # @return [Watir::H2] The raw +H2+ element
+ def billable_users_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_billable_users
+ # end
+ # @return [Boolean] true if the +billable_users+ element is present on the page
+ def billable_users?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +h2 :maximum_users+
+ # @return [String] The text content or value of +maximum_users+
+ def maximum_users
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.maximum_users_element).to exist
+ # end
+ # @return [Watir::H2] The raw +H2+ element
+ def maximum_users_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_maximum_users
+ # end
+ # @return [Boolean] true if the +maximum_users+ element is present on the page
+ def maximum_users?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
# @note Defined as +h2 :users_in_subscription+
# @return [String] The text content or value of +users_in_subscription+
def users_in_subscription
@@ -27,6 +195,54 @@ module Gitlab
def users_in_subscription?
# This is a stub, used for indexing. The method is dynamically generated.
end
+
+ # @note Defined as +h2 :users_over_subscription+
+ # @return [String] The text content or value of +users_over_subscription+
+ def users_over_subscription
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.users_over_subscription_element).to exist
+ # end
+ # @return [Watir::H2] The raw +H2+ element
+ def users_over_subscription_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_users_over_subscription
+ # end
+ # @return [Boolean] true if the +users_over_subscription+ element is present on the page
+ def users_over_subscription?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @note Defined as +table :subscription_history+
+ # @return [String] The text content or value of +subscription_history+
+ def subscription_history
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription.subscription_history_element).to exist
+ # end
+ # @return [Watir::Table] The raw +Table+ element
+ def subscription_history_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Admin::Subscription.perform do |subscription|
+ # expect(subscription).to be_subscription_history
+ # end
+ # @return [Boolean] true if the +subscription_history+ element is present on the page
+ def subscription_history?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
end
end
end
diff --git a/qa/lib/gitlab/page/main/welcome.rb b/qa/lib/gitlab/page/main/welcome.rb
new file mode 100644
index 00000000000..a2df1da61c9
--- /dev/null
+++ b/qa/lib/gitlab/page/main/welcome.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Page
+ module Main
+ class Welcome < Chemlab::Page
+ path '/users/sign_up/welcome'
+
+ button :get_started_button
+ end
+ end
+ end
+end
diff --git a/qa/lib/gitlab/page/main/welcome.stub.rb b/qa/lib/gitlab/page/main/welcome.stub.rb
new file mode 100644
index 00000000000..a10e697bcbf
--- /dev/null
+++ b/qa/lib/gitlab/page/main/welcome.stub.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Page
+ module Main
+ module Welcome
+ # @note Defined as +button :get_started_button+
+ # Clicks +get_started_button+
+ def get_started_button
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Main::Welcome.perform do |welcome|
+ # expect(welcome.get_started_button_element).to exist
+ # end
+ # @return [Watir::Button] The raw +Button+ element
+ def get_started_button_element
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+
+ # @example
+ # Gitlab::Page::Main::Welcome.perform do |welcome|
+ # expect(welcome).to be_get_started_button
+ # end
+ # @return [Boolean] true if the +get_started_button+ element is present on the page
+ def get_started_button?
+ # This is a stub, used for indexing. The method is dynamically generated.
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa.rb b/qa/qa.rb
index cc83efb90e8..1cdf6bc89ca 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -50,7 +50,8 @@ module QA
"user_gpg" => "UserGPG",
"smtp" => "SMTP",
"otp" => "OTP",
- "jira_api" => "JiraAPI"
+ "jira_api" => "JiraAPI",
+ "registry_tls" => "RegistryTLS"
)
loader.setup
diff --git a/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb b/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb
index a13c92d5c6d..8eac8419022 100644
--- a/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb
+++ b/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb
@@ -24,8 +24,7 @@ spec:
args:
- --token-file=/config/token
- --kas-address
- - "<%= kas_wss_address %>" # Use this for GitLab chart deployments
- # - "<%= kas_grpc_address %>" # Use this for GDK
+ - "<%= kas_wss_address %>"
volumeMounts:
- name: token-volume
mountPath: /config
diff --git a/qa/qa/fixtures/rubygems_package/mygem.gemspec b/qa/qa/fixtures/rubygems_package/mygem.gemspec
deleted file mode 100644
index 33d8c88e5ac..00000000000
--- a/qa/qa/fixtures/rubygems_package/mygem.gemspec
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-Gem::Specification.new do |s|
- s.name = 'mygem'
- s.authors = ['Tanuki Steve', 'Hal 9000']
- s.author = 'Tanuki Steve'
- s.version = '0.0.1'
- s.date = '2011-09-29'
- s.summary = 'package is the best'
- s.files = ['lib/hello_gem.rb']
- s.require_paths = ['lib']
-
- s.description = 'A test package for GitLab.'
- s.email = 'tanuki@not_real.com'
- s.homepage = 'https://gitlab.com/ruby-co/my-package'
- s.license = 'MIT'
-
- s.metadata = {
- 'bug_tracker_uri' => 'https://gitlab.com/ruby-co/my-package/issues',
- 'changelog_uri' => 'https://gitlab.com/ruby-co/my-package/CHANGELOG.md',
- 'documentation_uri' => 'https://gitlab.com/ruby-co/my-package/docs',
- 'mailing_list_uri' => 'https://gitlab.com/ruby-co/my-package/mailme',
- 'source_code_uri' => 'https://gitlab.com/ruby-co/my-package'
- }
-
- s.bindir = 'bin'
- s.platform = Gem::Platform::RUBY
- s.post_install_message = 'Installed, thank you!'
- s.rdoc_options = ['--main']
- s.required_ruby_version = '>= 2.7.0'
- s.required_rubygems_version = '>= 1.8.11'
- s.requirements = 'A high powered server or calculator'
- s.rubygems_version = '1.8.09'
-
- s.add_dependency 'dependency_1', '~> 1.2.3'
- s.add_dependency 'dependency_2', '3.0.0'
- s.add_dependency 'dependency_3', '>= 1.0.0'
- s.add_dependency 'dependency_4'
-end
diff --git a/qa/qa/flow/login.rb b/qa/qa/flow/login.rb
index 05a509588f1..5f7e0227ac5 100644
--- a/qa/qa/flow/login.rb
+++ b/qa/qa/flow/login.rb
@@ -23,8 +23,11 @@ module QA
end
def sign_in(as: nil, address: :gitlab, skip_page_validation: false, admin: false)
- Page::Main::Menu.perform(&:sign_out) if Page::Main::Menu.perform(&:signed_in?)
- Runtime::Browser.visit(address, Page::Main::Login)
+ unless Page::Main::Login.perform(&:on_login_page?)
+ Page::Main::Menu.perform(&:sign_out) if Page::Main::Menu.perform(&:signed_in?)
+ Runtime::Browser.visit(address, Page::Main::Login)
+ end
+
Page::Main::Login.perform do |login|
if admin
login.sign_in_using_admin_credentials
diff --git a/qa/qa/mobile/page/main/menu.rb b/qa/qa/mobile/page/main/menu.rb
new file mode 100644
index 00000000000..40bb421b383
--- /dev/null
+++ b/qa/qa/mobile/page/main/menu.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module QA
+ module Mobile
+ module Page
+ module Main
+ module Menu
+ extend QA::Page::PageConcern
+
+ def self.prepended(base)
+ super
+
+ base.class_eval do
+ view 'app/views/layouts/header/_default.html.haml' do
+ element :mobile_navbar_button, required: true
+ end
+
+ view 'app/assets/javascripts/nav/components/responsive_home.vue' do
+ element :mobile_new_dropdown
+ end
+ end
+ end
+
+ def open_mobile_menu
+ if has_no_element?(:user_avatar)
+ Support::Retrier.retry_until do
+ click_element(:mobile_navbar_button)
+ has_element?(:user_avatar)
+ end
+ end
+ end
+
+ def open_mobile_new_dropdown
+ open_mobile_menu
+
+ Support::Retrier.retry_until do
+ find('[data-qa-selector="mobile_new_dropdown"] > button').click
+ has_css?('.dropdown-menu-right.show')
+ end
+ end
+
+ def has_personal_area?(wait: Capybara.default_max_wait_time)
+ open_mobile_menu
+ super
+ end
+
+ def has_no_personal_area?(wait: Capybara.default_max_wait_time)
+ open_mobile_menu
+ super
+ end
+
+ def within_user_menu
+ open_mobile_menu
+ super
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/mobile/page/profile/menu.rb b/qa/qa/mobile/page/profile/menu.rb
new file mode 100644
index 00000000000..34c53a95e03
--- /dev/null
+++ b/qa/qa/mobile/page/profile/menu.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module QA
+ module Mobile
+ module Page
+ module Profile
+ module Menu
+ extend QA::Page::PageConcern
+
+ def self.prepended(base)
+ super
+
+ base.class_eval do
+ prepend QA::Mobile::Page::Main::Menu
+ end
+ end
+
+ def within_sidebar
+ open_mobile_nav_sidebar
+ super
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/mobile/page/project/issue/show.rb b/qa/qa/mobile/page/project/issue/show.rb
new file mode 100644
index 00000000000..017ecebcb69
--- /dev/null
+++ b/qa/qa/mobile/page/project/issue/show.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module QA
+ module Mobile
+ module Page
+ module Project
+ module Issue
+ module Show
+ extend QA::Page::PageConcern
+
+ def self.prepended(base)
+ super
+
+ base.class_eval do
+ view 'app/assets/javascripts/issue_show/components/header_actions.vue' do
+ element :issue_actions_dropdown
+ element :mobile_close_issue_button
+ element :mobile_reopen_issue_button
+ end
+ end
+ end
+
+ def click_close_issue_button
+ find('[data-qa-selector="issue_actions_dropdown"] > button').click
+ find_element(:mobile_close_issue_button, visible: false).click
+ end
+
+ def has_reopen_issue_button?
+ find('[data-qa-selector="issue_actions_dropdown"] > button').click
+ has_element?(:mobile_reopen_issue_button)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/mobile/page/project/show.rb b/qa/qa/mobile/page/project/show.rb
new file mode 100644
index 00000000000..8a0a222c852
--- /dev/null
+++ b/qa/qa/mobile/page/project/show.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module QA
+ module Mobile
+ module Page
+ module Project
+ module Show
+ extend QA::Page::PageConcern
+
+ def self.prepended(base)
+ super
+
+ base.class_eval do
+ prepend QA::Mobile::Page::Main::Menu
+
+ view 'app/assets/javascripts/nav/components/top_nav_new_dropdown.vue' do
+ element :new_issue_mobile_button
+ end
+ end
+ end
+
+ def go_to_new_issue
+ open_mobile_new_dropdown
+
+ click_element(:new_issue_mobile_button)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/mobile/page/sub_menus/common.rb b/qa/qa/mobile/page/sub_menus/common.rb
new file mode 100644
index 00000000000..6a0477a3f31
--- /dev/null
+++ b/qa/qa/mobile/page/sub_menus/common.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module QA
+ module Mobile
+ module Page
+ module SubMenus
+ module Common
+ def open_mobile_nav_sidebar
+ if has_element?(:project_sidebar, visible: false)
+ Support::Retrier.retry_until do
+ click_element(:toggle_mobile_nav_button)
+ has_element?(:project_sidebar, visible: true)
+ end
+ end
+ end
+
+ def within_sidebar
+ wait_for_requests
+
+ open_mobile_nav_sidebar
+
+ super
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index 9debdc1d4dd..4708063b2eb 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -57,16 +57,25 @@ module QA
end
end
- def retry_until(max_attempts: 3, reload: false, sleep_interval: 0, raise_on_failure: true)
- Support::Retrier.retry_until(max_attempts: max_attempts, reload_page: (reload && self), sleep_interval: sleep_interval, raise_on_failure: raise_on_failure) do
- yield
- end
- end
-
- def retry_on_exception(max_attempts: 3, reload: false, sleep_interval: 0.5)
- Support::Retrier.retry_on_exception(max_attempts: max_attempts, reload_page: (reload && self), sleep_interval: sleep_interval) do
- yield
- end
+ def retry_until(max_attempts: 3, reload: false, sleep_interval: 0, raise_on_failure: true, message: nil, &block)
+ Support::Retrier.retry_until(
+ max_attempts: max_attempts,
+ reload_page: (reload && self),
+ sleep_interval: sleep_interval,
+ raise_on_failure: raise_on_failure,
+ message: message,
+ &block
+ )
+ end
+
+ def retry_on_exception(max_attempts: 3, reload: false, sleep_interval: 0.5, message: nil, &block)
+ Support::Retrier.retry_on_exception(
+ max_attempts: max_attempts,
+ reload_page: (reload && self),
+ sleep_interval: sleep_interval,
+ message: message,
+ &block
+ )
end
def scroll_to(selector, text: nil)
diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb
index 971e7634f6d..77962570aed 100644
--- a/qa/qa/page/component/issuable/sidebar.rb
+++ b/qa/qa/page/component/issuable/sidebar.rb
@@ -22,20 +22,16 @@ module QA
element :labels_block
end
- base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue' do
- element :selected_label_content
+ base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue' do
+ element :dropdown_input_field
end
- base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue' do
+ base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue' do
element :labels_dropdown_content
end
- base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue' do
- element :labels_edit_button
- end
-
- base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue' do
- element :dropdown_input_field
+ base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue' do
+ element :selected_label_content
end
base.view 'app/views/shared/issuable/_sidebar.html.haml' do
@@ -53,7 +49,7 @@ module QA
end
def assign_milestone(milestone)
- within_element(:milestone_block) do
+ wait_milestone_block_finish_loading do
click_element(:edit_link)
click_on(milestone.title)
end
@@ -70,14 +66,14 @@ module QA
end
def has_assignee?(username)
- within_element(:assignee_block) do
- has_text?(username, wait: 1)
+ wait_assignees_block_finish_loading do
+ has_text?(username)
end
end
def has_no_assignee?(username)
- within_element(:assignee_block) do
- has_no_text?(username, wait: 1)
+ wait_assignees_block_finish_loading do
+ has_no_text?(username)
end
end
@@ -88,8 +84,14 @@ module QA
end
def has_label?(label)
- within_element(:labels_block) do
- !!has_element?(:selected_label_content, label_name: label)
+ wait_labels_block_finish_loading do
+ has_element?(:selected_label_content, label_name: label)
+ end
+ end
+
+ def has_no_label?(label)
+ wait_labels_block_finish_loading do
+ has_no_element?(:selected_label_content, label_name: label)
end
end
@@ -103,33 +105,34 @@ module QA
find_element(:more_assignees_link)
end
- def select_labels_and_refresh(labels)
- Support::Retrier.retry_until do
- click_element(:labels_edit_button)
- has_element?(:labels_dropdown_content, text: labels.first)
- end
+ def select_labels(labels)
+ within_element(:labels_block) do
+ click_element(:edit_link)
- labels.each do |label|
- within_element(:labels_dropdown_content) do
- send_keys_to_element(:dropdown_input_field, [label, :enter])
+ labels.each do |label|
+ within_element(:labels_dropdown_content) do
+ fill_element(:dropdown_input_field, label)
+ click_button(text: label)
+ end
end
end
- click_element(:labels_edit_button)
-
- labels.each do |label|
- has_element?(:labels_block, text: label, wait: 0)
- end
-
- refresh
-
- wait_for_requests
+ click_element(:title) # to blur dropdown
end
def toggle_more_assignees_link
click_element(:more_assignees_link)
end
+ # When the labels_widget feature flag is enabled, wait until the labels widget appears
+ def wait_for_labels_widget_feature_flag
+ Support::Retrier.retry_until(max_duration: 60, reload_page: page, retry_on_exception: true, sleep_interval: 5) do
+ within_element(:labels_block) do
+ find_element(:edit_link)
+ end
+ end
+ end
+
private
def wait_assignees_block_finish_loading
@@ -141,6 +144,15 @@ module QA
end
end
+ def wait_labels_block_finish_loading
+ within_element(:labels_block) do
+ wait_until(reload: false, max_duration: 10, sleep_interval: 1) do
+ finished_loading_block?
+ yield
+ end
+ end
+ end
+
def wait_milestone_block_finish_loading
within_element(:milestone_block) do
wait_until(reload: false, max_duration: 10, sleep_interval: 1) do
diff --git a/qa/qa/page/component/issue_board/show.rb b/qa/qa/page/component/issue_board/show.rb
index 1c1f7ab17f3..2259a65b546 100644
--- a/qa/qa/page/component/issue_board/show.rb
+++ b/qa/qa/page/component/issue_board/show.rb
@@ -24,14 +24,6 @@ module QA
element :create_new_board_button
end
- view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue' do
- element :labels_dropdown_content
- end
-
- view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue' do
- element :labels_edit_button
- end
-
view 'app/assets/javascripts/boards/components/board_content.vue' do
element :boards_list
end
@@ -85,6 +77,7 @@ module QA
def click_boards_config_button
click_element(:boards_config_button)
+ wait_for_requests
end
def click_boards_dropdown_button
@@ -97,16 +90,6 @@ module QA
click_element(:focus_mode_button)
end
- def configure_by_label(label)
- click_boards_config_button
- click_element(:labels_edit_button)
- find_element(:labels_dropdown_content).find('li', text: label).click
- # Clicking the edit button again closes the dropdown and allows the save button to be clicked
- click_element(:labels_edit_button)
- click_element(:save_changes_button)
- wait_boards_list_finish_loading
- end
-
def create_new_board(board_name)
click_boards_dropdown_button
click_element(:create_new_board_button)
diff --git a/qa/qa/page/group/bulk_import.rb b/qa/qa/page/group/bulk_import.rb
index a62823f3469..90bc7a66dcc 100644
--- a/qa/qa/page/group/bulk_import.rb
+++ b/qa/qa/page/group/bulk_import.rb
@@ -34,7 +34,7 @@ module QA
click_element(:target_namespace_selector_dropdown)
click_element(:target_group_dropdown_item, group_name: target_group_name)
- retry_until do
+ retry_until(message: "Triggering import") do
click_element(:import_group_button)
# Make sure import started before waiting for completion
has_no_element?(:import_status_indicator, text: "Not started", wait: 1)
diff --git a/qa/qa/page/group/settings/package_registries.rb b/qa/qa/page/group/settings/package_registries.rb
index 5c93c0d6222..433872a378a 100644
--- a/qa/qa/page/group/settings/package_registries.rb
+++ b/qa/qa/page/group/settings/package_registries.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-
module QA
module Page
module Group
@@ -20,22 +19,33 @@ module QA
def set_allow_duplicates_disabled
expand_content :package_registry_settings_content do
- click_element(:allow_duplicates_toggle) if duplicates_enabled?
+ click_on_allow_duplicates_button if duplicates_enabled?
end
end
def set_allow_duplicates_enabled
expand_content :package_registry_settings_content do
- click_element(:allow_duplicates_toggle) if duplicates_disabled?
+ click_on_allow_duplicates_button unless duplicates_enabled?
+ end
+ end
+
+ def click_on_allow_duplicates_button
+ with_allow_duplicates_button do |button|
+ button.click
end
end
def duplicates_enabled?
- has_element?(:allow_duplicates_label, text: 'Allow duplicates')
+ with_allow_duplicates_button do |button|
+ button[:class].include?('is-checked')
+ end
end
- def duplicates_disabled?
- has_element?(:allow_duplicates_label, text: 'Do not allow duplicates')
+ def with_allow_duplicates_button
+ within_element :allow_duplicates_toggle do
+ toggle = find('button.gl-toggle:not(.is-disabled)')
+ yield(toggle)
+ end
end
def has_dependency_proxy_enabled?
diff --git a/qa/qa/page/group/show.rb b/qa/qa/page/group/show.rb
index 38d919be4db..2cd78f9f17a 100644
--- a/qa/qa/page/group/show.rb
+++ b/qa/qa/page/group/show.rb
@@ -9,6 +9,7 @@ module QA
view 'app/views/groups/_home_panel.html.haml' do
element :new_project_button
element :new_subgroup_button
+ element :group_id_content
end
view 'app/assets/javascripts/groups/constants.js' do
@@ -40,6 +41,10 @@ module QA
click_element :new_project_button
end
+ def group_id
+ find_element(:group_id_content).text.delete('Group ID: ')
+ end
+
def leave_group
accept_alert do
click_element :leave_group_link
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index c3170478733..5cba9d4bce4 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -45,6 +45,10 @@ module QA
has_element?(:sign_in_button)
end
+ def on_login_page?
+ has_element?(:login_page, wait: 0)
+ end
+
def sign_in_using_credentials(user: nil, skip_page_validation: false)
# Don't try to log-in if we're already logged-in
return if Page::Main::Menu.perform(&:signed_in?)
@@ -164,6 +168,8 @@ module QA
fill_element :password_field, user.password
click_element :sign_in_button
+ Support::WaitForRequests.wait_for_requests
+
Page::Main::Terms.perform do |terms|
terms.accept_terms if terms.visible?
end
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
index ad5cd971afc..e3bb585955b 100644
--- a/qa/qa/page/main/menu.rb
+++ b/qa/qa/page/main/menu.rb
@@ -4,6 +4,8 @@ module QA
module Page
module Main
class Menu < Page::Base
+ prepend Mobile::Page::Main::Menu if Runtime::Env.mobile_layout?
+
view 'app/views/layouts/header/_current_user_dropdown.html.haml' do
element :sign_out_link
element :edit_profile_link
@@ -12,12 +14,12 @@ module QA
view 'app/views/layouts/header/_default.html.haml' do
element :navbar, required: true
element :canary_badge_link
- element :user_avatar, required: true
- element :user_menu, required: true
+ element :user_avatar, required: !QA::Runtime::Env.mobile_layout?
+ element :user_menu, required: !QA::Runtime::Env.mobile_layout?
element :stop_impersonation_link
- element :issues_shortcut_button, required: true
- element :merge_requests_shortcut_button, required: true
- element :todos_shortcut_button, required: true
+ element :issues_shortcut_button, required: !QA::Runtime::Env.mobile_layout?
+ element :merge_requests_shortcut_button, required: !QA::Runtime::Env.mobile_layout?
+ element :todos_shortcut_button, required: !QA::Runtime::Env.mobile_layout?
end
view 'app/assets/javascripts/nav/components/top_nav_app.vue' do
@@ -98,10 +100,14 @@ module QA
end
def signed_in?
+ return false if Page::Main::Login.perform(&:on_login_page?)
+
has_personal_area?(wait: 0)
end
def not_signed_in?
+ return true if Page::Main::Login.perform(&:on_login_page?)
+
has_no_personal_area?
end
@@ -115,7 +121,7 @@ module QA
click_element :sign_out_link
end
- has_no_element?(:user_avatar)
+ not_signed_in?
end
end
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index d4fa3b38f02..f8d063ac6bd 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -99,6 +99,8 @@ module QA
view 'app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue' do
element :add_suggestion_batch_button
+ element :applied_badge
+ element :applying_badge
end
view 'app/views/projects/merge_requests/_description.html.haml' do
@@ -354,7 +356,7 @@ module QA
end
def apply_suggestion_with_message(message)
- click_element(:apply_suggestion_dropdown)
+ all_elements(:apply_suggestion_dropdown, minimum: 1).first.click
fill_element(:commit_message_field, message)
click_element(:commit_with_custom_message_button)
end
@@ -363,6 +365,13 @@ module QA
all_elements(:add_suggestion_batch_button, minimum: 1).first.click
end
+ def has_suggestions_applied?(count = 1)
+ wait_until(reload: false) do
+ has_no_element?(:applying_badge)
+ end
+ all_elements(:applied_badge, count: count)
+ end
+
def cherry_pick!
click_element(:cherry_pick_button, Page::Component::CommitModal)
click_element(:submit_commit_button)
diff --git a/qa/qa/page/profile/menu.rb b/qa/qa/page/profile/menu.rb
index a12db2918dc..d638a378610 100644
--- a/qa/qa/page/profile/menu.rb
+++ b/qa/qa/page/profile/menu.rb
@@ -4,6 +4,10 @@ module QA
module Page
module Profile
class Menu < Page::Base
+ # We need to check remote_mobile_device_name instead of mobile_layout? here
+ # since tablets have the regular top navigation bar but still close the left nav
+ prepend QA::Mobile::Page::Profile::Menu if QA::Runtime::Env.remote_mobile_device_name
+
view 'app/views/layouts/nav/sidebar/_profile.html.haml' do
element :access_token_link, 'link_to profile_personal_access_tokens_path' # rubocop:disable QA/ElementWithPattern
element :access_token_title, 'Access Tokens' # rubocop:disable QA/ElementWithPattern
diff --git a/qa/qa/page/project/fork/new.rb b/qa/qa/page/project/fork/new.rb
index 7062702679a..cd743b648d8 100644
--- a/qa/qa/page/project/fork/new.rb
+++ b/qa/qa/page/project/fork/new.rb
@@ -12,6 +12,7 @@ module QA
view 'app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue' do
element :fork_namespace_dropdown
element :fork_project_button
+ element :fork_privacy_button
end
def fork_project(namespace = Runtime::Namespace.path)
@@ -19,6 +20,7 @@ module QA
click_element(:fork_namespace_button, name: namespace)
else
select_element(:fork_namespace_dropdown, namespace)
+ click_element(:fork_privacy_button, privacy_level: 'public')
click_element(:fork_project_button)
end
end
diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb
index bb35c5eb17c..47f7e701ae8 100644
--- a/qa/qa/page/project/import/github.rb
+++ b/qa/qa/page/project/import/github.rb
@@ -49,7 +49,12 @@ module QA
click_element(:target_namespace_selector_dropdown)
click_element(:target_group_dropdown_item, group_name: target_group_path)
fill_element(:project_path_field, project_name)
- click_element(:import_button)
+
+ retry_until do
+ click_element(:import_button)
+ # Make sure import started before waiting for completion
+ has_no_element?(:import_status_indicator, text: "Not started", wait: 1)
+ end
end
end
diff --git a/qa/qa/page/project/infrastructure/kubernetes/add.rb b/qa/qa/page/project/infrastructure/kubernetes/add.rb
index e2d50c1bcf1..ed9ecb51a46 100644
--- a/qa/qa/page/project/infrastructure/kubernetes/add.rb
+++ b/qa/qa/page/project/infrastructure/kubernetes/add.rb
@@ -11,7 +11,7 @@ module QA
end
def add_existing_cluster
- click_element(:add_existing_cluster_tab)
+ page.find('.gl-tab-nav-item', text: 'Connect existing cluster').click
end
end
end
diff --git a/qa/qa/page/project/infrastructure/kubernetes/index.rb b/qa/qa/page/project/infrastructure/kubernetes/index.rb
index bdcaf7ffaff..0424682179e 100644
--- a/qa/qa/page/project/infrastructure/kubernetes/index.rb
+++ b/qa/qa/page/project/infrastructure/kubernetes/index.rb
@@ -6,12 +6,12 @@ module QA
module Infrastructure
module Kubernetes
class Index < Page::Base
- view 'app/views/clusters/clusters/_empty_state.html.haml' do
- element :add_kubernetes_cluster_link
+ view 'app/assets/javascripts/clusters_list/components/clusters_view_all.vue' do
+ element :connect_existing_cluster_button
end
- def add_kubernetes_cluster
- click_element :add_kubernetes_cluster_link
+ def connect_existing_cluster
+ click_link 'Connect existing cluster'
end
def has_cluster?(cluster)
diff --git a/qa/qa/page/project/infrastructure/kubernetes/show.rb b/qa/qa/page/project/infrastructure/kubernetes/show.rb
index 62a04a53a2f..6de5024e525 100644
--- a/qa/qa/page/project/infrastructure/kubernetes/show.rb
+++ b/qa/qa/page/project/infrastructure/kubernetes/show.rb
@@ -7,26 +7,9 @@ module QA
module Kubernetes
class Show < Page::Base
view 'app/assets/javascripts/clusters/forms/components/integration_form.vue' do
- element :integration_status_toggle, required: true
- element :base_domain_field, required: true
- element :save_changes_button, required: true
- end
-
- view 'app/views/clusters/clusters/_details_tab.html.haml' do
- element :details, required: true
- end
-
- view 'app/views/clusters/clusters/_health.html.haml' do
- element :cluster_health_section
- end
-
- view 'app/views/clusters/clusters/_health_tab.html.haml' do
- element :health, required: true
- end
-
- def open_details
- has_element?(:details, wait: 30)
- click_element :details
+ element :integration_status_toggle
+ element :base_domain_field
+ element :save_changes_button
end
def set_domain(domain)
@@ -36,29 +19,6 @@ module QA
def save_domain
click_element :save_changes_button, Page::Project::Infrastructure::Kubernetes::Show
end
-
- def wait_for_cluster_health
- wait_until(max_duration: 120, sleep_interval: 3, reload: true) do
- has_cluster_health_graphs?
- end
- end
-
- def open_health
- has_element?(:health, wait: 30)
- click_element :health
- end
-
- def has_cluster_health_graphs?
- within_cluster_health_section do
- has_text?('CPU Usage')
- end
- end
-
- def within_cluster_health_section
- within_element :cluster_health_section do
- yield
- end
- end
end
end
end
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index 7a5a153db86..3b033830420 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -9,6 +9,7 @@ module QA
include Page::Component::Note
include Page::Component::DesignManagement
include Page::Component::Issuable::Sidebar
+ prepend Mobile::Page::Project::Issue::Show if Runtime::Env.mobile_layout?
view 'app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue' do
element :remove_related_issue_button
@@ -64,6 +65,10 @@ module QA
def has_metrics_unfurled?
has_element?(:prometheus_graph_widgets, wait: 30)
end
+
+ def has_reopen_issue_button?
+ has_element?(:reopen_issue_button)
+ end
end
end
end
diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb
index 78b6bebe02e..2fb925b3930 100644
--- a/qa/qa/page/project/job/show.rb
+++ b/qa/qa/page/project/job/show.rb
@@ -62,6 +62,12 @@ module QA
has_element? :job_log_content
end
+ def has_status?(status, wait: 30)
+ wait_until(reload: false, max_duration: wait, sleep_interval: 1) do
+ status_badge == status
+ end
+ end
+
private
def loaded?(wait: 60)
diff --git a/qa/qa/page/project/monitor/metrics/show.rb b/qa/qa/page/project/monitor/metrics/show.rb
index 0129ee06cb6..70ebc795595 100644
--- a/qa/qa/page/project/monitor/metrics/show.rb
+++ b/qa/qa/page/project/monitor/metrics/show.rb
@@ -31,7 +31,6 @@ module QA
view 'app/assets/javascripts/monitoring/components/dashboard_panel.vue' do
element :prometheus_graph_widgets
element :prometheus_widgets_dropdown
- element :alert_widget_menu_item
element :generate_chart_link_menu_item
end
diff --git a/qa/qa/page/project/new.rb b/qa/qa/page/project/new.rb
index 3ecdabeeed2..5ff52527774 100644
--- a/qa/qa/page/project/new.rb
+++ b/qa/qa/page/project/new.rb
@@ -13,6 +13,7 @@ module QA
view 'app/views/projects/_new_project_fields.html.haml' do
element :initialize_with_readme_checkbox
+ element :initialize_with_sast_checkbox
element :project_namespace_field, 'namespaces_options' # rubocop:disable QA/ElementWithPattern
element :project_name, 'text_field :name' # rubocop:disable QA/ElementWithPattern
element :project_path, 'text_field :path' # rubocop:disable QA/ElementWithPattern
@@ -79,6 +80,13 @@ module QA
choose visibility.capitalize
end
+ # Disable experiment for SAST at project creation https://gitlab.com/gitlab-org/gitlab/-/issues/333196
+ def disable_initialize_with_sast
+ return unless has_element?(:initialize_with_sast_checkbox)
+
+ uncheck_element(:initialize_with_sast_checkbox)
+ end
+
def click_github_link
click_link 'GitHub'
end
diff --git a/qa/qa/page/project/registry/show.rb b/qa/qa/page/project/registry/show.rb
index f2472a83401..270445560be 100644
--- a/qa/qa/page/project/registry/show.rb
+++ b/qa/qa/page/project/registry/show.rb
@@ -5,15 +5,15 @@ module QA
module Project
module Registry
class Show < QA::Page::Base
- view 'app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue' do
+ view 'app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue' do
element :registry_image_content
end
- view 'app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue' do
+ view 'app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue' do
element :more_actions_menu
end
- view 'app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue' do
+ view 'app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue' do
element :tag_delete_button
end
diff --git a/qa/qa/page/project/settings/deploy_tokens.rb b/qa/qa/page/project/settings/deploy_tokens.rb
index 7b61c81154a..407d57bc54e 100644
--- a/qa/qa/page/project/settings/deploy_tokens.rb
+++ b/qa/qa/page/project/settings/deploy_tokens.rb
@@ -12,6 +12,7 @@ module QA
element :deploy_token_read_package_registry_checkbox
element :deploy_token_write_package_registry_checkbox
element :deploy_token_read_registry_checkbox
+ element :deploy_token_write_registry_checkbox
element :create_deploy_token_button
end
@@ -29,11 +30,12 @@ module QA
fill_element(:deploy_token_expires_at_field, expires_at.to_s + "\n")
end
- def fill_scopes(read_repository: false, read_registry: false, read_package_registry: false, write_package_registry: false)
- check_element(:deploy_token_read_repository_checkbox) if read_repository
- check_element(:deploy_token_read_package_registry_checkbox) if read_package_registry
- check_element(:deploy_token_write_package_registry_checkbox) if write_package_registry
- check_element(:deploy_token_read_registry_checkbox) if read_registry
+ def fill_scopes(scopes)
+ check_element(:deploy_token_read_repository_checkbox) if scopes.include? :read_repository
+ check_element(:deploy_token_read_package_registry_checkbox) if scopes.include? :read_package_registry
+ check_element(:deploy_token_write_package_registry_checkbox) if scopes.include? :write_package_registry
+ check_element(:deploy_token_read_registry_checkbox) if scopes.include? :read_registry
+ check_element(:deploy_token_write_registry_checkbox) if scopes.include? :write_registry
end
def add_token
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index 6e5097c3812..65a1f726a8a 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -9,6 +9,7 @@ module QA
include Page::Component::Breadcrumbs
include Page::Project::SubMenus::Settings
include Page::File::Shared::CommitMessage
+ prepend Mobile::Page::Project::Show if Runtime::Env.mobile_layout?
view 'app/assets/javascripts/repository/components/preview/index.vue' do
element :blob_viewer_content
@@ -117,7 +118,7 @@ module QA
end
def go_to_new_issue
- click_element :new_menu_toggle
+ click_element(:new_menu_toggle)
click_element(:new_issue_link)
end
@@ -153,6 +154,10 @@ module QA
click_element(:web_ide_button)
end
+ def open_web_ide_via_shortcut
+ page.driver.send_keys('.')
+ end
+
def has_edit_fork_button?
has_element?(:web_ide_button, text: 'Edit fork in Web IDE')
end
diff --git a/qa/qa/page/project/sub_menus/common.rb b/qa/qa/page/project/sub_menus/common.rb
index c20710bc393..112f49a90ee 100644
--- a/qa/qa/page/project/sub_menus/common.rb
+++ b/qa/qa/page/project/sub_menus/common.rb
@@ -19,6 +19,10 @@ module QA
view 'app/views/shared/nav/_sidebar_menu.html.haml' do
element :sidebar_menu_link
end
+
+ view 'app/views/layouts/nav/_breadcrumbs.html.haml' do
+ element :toggle_mobile_nav_button
+ end
end
end
diff --git a/qa/qa/page/sub_menus/common.rb b/qa/qa/page/sub_menus/common.rb
index 2efeeb062e8..518b3b4e84e 100644
--- a/qa/qa/page/sub_menus/common.rb
+++ b/qa/qa/page/sub_menus/common.rb
@@ -4,6 +4,10 @@ module QA
module Page
module SubMenus
module Common
+ # We need to check remote_mobile_device_name instead of mobile_layout? here
+ # since tablets have the regular top navigation bar but still close the left nav
+ prepend Mobile::Page::SubMenus::Common if QA::Runtime::Env.remote_mobile_device_name
+
def hover_element(element)
within_sidebar do
find_element(element).hover
diff --git a/qa/qa/resource/base.rb b/qa/qa/resource/base.rb
index a7243b7ebc2..26a2a668cc1 100644
--- a/qa/qa/resource/base.rb
+++ b/qa/qa/resource/base.rb
@@ -77,17 +77,24 @@ module QA
def log_fabrication(method, resource, parents, args)
start = Time.now
- yield.tap do
+ Support::FabricationTracker.start_fabrication
+ result = yield.tap do
+ fabrication_time = Time.now - start
+
+ Support::FabricationTracker.save_fabrication(:"#{method}_fabrication", fabrication_time)
Runtime::Logger.debug do
msg = ["==#{'=' * parents.size}>"]
msg << "Built a #{name}"
msg << "as a dependency of #{parents.last}" if parents.any?
msg << "via #{method}"
- msg << "in #{Time.now - start} seconds"
+ msg << "in #{fabrication_time} seconds"
msg.join(' ')
end
end
+ Support::FabricationTracker.finish_fabrication
+
+ result
end
# Define custom attribute
diff --git a/qa/qa/resource/bulk_import_group.rb b/qa/qa/resource/bulk_import_group.rb
index 5380bb16f10..e8dc2d291b8 100644
--- a/qa/qa/resource/bulk_import_group.rb
+++ b/qa/qa/resource/bulk_import_group.rb
@@ -59,6 +59,9 @@ module QA
}
end
+ # Get import status
+ #
+ # @return [String]
def import_status
response = get(Runtime::API::Request.new(api_client, "/bulk_imports/#{import_id}").url)
@@ -69,6 +72,15 @@ module QA
parse_body(response)[:status]
end
+ # Get import details
+ #
+ # @return [Array]
+ def import_details
+ response = get(Runtime::API::Request.new(api_client, "/bulk_imports/#{import_id}/entities").url)
+
+ parse_body(response)
+ end
+
private
def transform_api_resource(api_resource)
diff --git a/qa/qa/resource/clusters/agent.rb b/qa/qa/resource/clusters/agent.rb
index cad5a4c6b1d..ee5a292b9b3 100644
--- a/qa/qa/resource/clusters/agent.rb
+++ b/qa/qa/resource/clusters/agent.rb
@@ -19,13 +19,12 @@ module QA
def fabricate!
puts 'TODO: FABRICATE VIA UI'
end
- # TODO
- #
- # The UI for this model is not yet implemented. So far it can only be
- # created through the GraphQL API
- # def fabricate
- #
- # end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
def api_get_path
"gid://gitlab/Clusters::Agent/#{id}"
diff --git a/qa/qa/resource/clusters/agent_token.rb b/qa/qa/resource/clusters/agent_token.rb
index 3286f46cdb2..6d803b94564 100644
--- a/qa/qa/resource/clusters/agent_token.rb
+++ b/qa/qa/resource/clusters/agent_token.rb
@@ -13,13 +13,12 @@ module QA
def fabricate!
puts 'TODO: FABRICATE VIA UI'
end
- # TODO
- #
- # The UI for this model is not yet implemented. So far it can only be
- # created through the GraphQL API
- # def fabricate
- #
- # end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
def api_get_path
"gid://gitlab/Clusters::AgentToken/#{id}"
diff --git a/qa/qa/resource/deploy_token.rb b/qa/qa/resource/deploy_token.rb
index 151454c37b1..f5d3b87fc2b 100644
--- a/qa/qa/resource/deploy_token.rb
+++ b/qa/qa/resource/deploy_token.rb
@@ -4,6 +4,7 @@ module QA
module Resource
class DeployToken < Base
attr_accessor :name, :expires_at
+ attr_writer :scopes
attribute :username do
Page::Project::Settings::Repository.perform do |repository_page|
@@ -37,7 +38,7 @@ module QA
setting.expand_deploy_tokens do |page|
page.fill_token_name(name)
page.fill_token_expires_at(expires_at)
- page.fill_scopes(read_repository: true, read_package_registry: true, write_package_registry: true)
+ page.fill_scopes(@scopes)
page.add_token
end
diff --git a/qa/qa/resource/file.rb b/qa/qa/resource/file.rb
index 4ca180373f6..9b05c0cb456 100644
--- a/qa/qa/resource/file.rb
+++ b/qa/qa/resource/file.rb
@@ -67,7 +67,7 @@ module QA
private
def transform_api_resource(api_resource)
- api_resource[:web_url] = "#{Runtime::Scenario.gitlab_address}/#{project.full_path}/-/tree/#{branch}/#{api_resource[:file_path]}"
+ api_resource[:web_url] = "#{Runtime::Scenario.gitlab_address}/#{project.full_path}/-/blob/#{branch}/#{api_resource[:file_path]}"
api_resource
end
end
diff --git a/qa/qa/resource/fork.rb b/qa/qa/resource/fork.rb
index b3814011f2c..d0313670e8b 100644
--- a/qa/qa/resource/fork.rb
+++ b/qa/qa/resource/fork.rb
@@ -37,11 +37,9 @@ module QA
namespace_path ||= user.name
# Sign out as admin and sign is as the fork user
- Page::Main::Menu.perform(&:sign_out)
- Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.perform do |login|
- login.sign_in_using_credentials(user: user)
- end
+ Flow::Login.sign_in(as: user)
+
+ @api_client = Runtime::API::Client.new(:gitlab, is_new_session: false, user: user)
upstream.visit!
diff --git a/qa/qa/resource/issue.rb b/qa/qa/resource/issue.rb
index 9214d4eff4a..344f177932f 100644
--- a/qa/qa/resource/issue.rb
+++ b/qa/qa/resource/issue.rb
@@ -9,6 +9,7 @@ module QA
Project.fabricate! do |resource|
resource.name = 'project-for-issues'
resource.description = 'project for adding issues'
+ resource.api_client = api_client
end
end
@@ -93,6 +94,52 @@ module QA
attempts: attempts
)
end
+
+ # Object comparison
+ #
+ # @param [QA::Resource::Issue] other
+ # @return [Boolean]
+ def ==(other)
+ other.is_a?(Issue) && comparable_issue == other.comparable_issue
+ end
+
+ # Override inspect for a better rspec failure diff output
+ #
+ # @return [String]
+ def inspect
+ JSON.pretty_generate(comparable_issue)
+ end
+
+ protected
+
+ # Return subset of fields for comparing issues
+ #
+ # @return [Hash]
+ def comparable_issue
+ reload! if api_response.nil?
+
+ api_resource.slice(
+ :state,
+ :description,
+ :type,
+ :title,
+ :labels,
+ :milestone,
+ :upvotes,
+ :downvotes,
+ :merge_requests_count,
+ :user_notes_count,
+ :due_date,
+ :has_tasks,
+ :task_status,
+ :confidential,
+ :discussion_locked,
+ :issue_type,
+ :task_completion_status,
+ :closed_at,
+ :created_at
+ )
+ end
end
end
end
diff --git a/qa/qa/resource/kubernetes_cluster/project_cluster.rb b/qa/qa/resource/kubernetes_cluster/project_cluster.rb
index b3eba77fc46..0a63ff47694 100644
--- a/qa/qa/resource/kubernetes_cluster/project_cluster.rb
+++ b/qa/qa/resource/kubernetes_cluster/project_cluster.rb
@@ -13,8 +13,8 @@ module QA
Resource::Project.fabricate!
end
- def ingress_ip
- @ingress_ip ||= @cluster.fetch_external_ip_for_ingress
+ attribute :ingress_ip do
+ @cluster.fetch_external_ip_for_ingress
end
def fabricate!
@@ -24,7 +24,7 @@ module QA
&:go_to_infrastructure_kubernetes)
Page::Project::Infrastructure::Kubernetes::Index.perform(
- &:add_kubernetes_cluster)
+ &:connect_existing_cluster)
Page::Project::Infrastructure::Kubernetes::Add.perform(
&:add_existing_cluster)
@@ -39,14 +39,10 @@ module QA
end
Page::Project::Infrastructure::Kubernetes::Show.perform do |show|
- # We must wait a few seconds for permissions to be set up correctly for new cluster
- sleep 25
-
if @install_ingress
- populate(:ingress_ip)
+ ingress_ip
- show.open_details
- show.set_domain("#{ingress_ip}.nip.io")
+ show.set_domain("#{@ingress_ip}.nip.io")
show.save_domain
end
end
diff --git a/qa/qa/resource/merge_request_from_fork.rb b/qa/qa/resource/merge_request_from_fork.rb
index b0579cf37b8..512f3eb7bfc 100644
--- a/qa/qa/resource/merge_request_from_fork.rb
+++ b/qa/qa/resource/merge_request_from_fork.rb
@@ -6,7 +6,7 @@ module QA
attr_accessor :fork_branch
attribute :fork do
- Fork.fabricate_via_api!
+ Fork.fabricate_via_browser_ui!
end
attribute :push do
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index 3f6a4eee5ac..864f3a14c3d 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -27,7 +27,9 @@ module QA
:import_error
attribute :group do
- Group.fabricate!
+ Group.fabricate! do |group|
+ group.api_client = api_client
+ end
end
attribute :path_with_namespace do
@@ -91,6 +93,7 @@ module QA
new_page.choose_name(@name)
new_page.add_description(@description)
new_page.set_visibility(@visibility)
+ new_page.disable_initialize_with_sast
new_page.disable_initialize_with_readme unless @initialize_with_readme
new_page.create_new_project
end
@@ -214,6 +217,10 @@ module QA
"#{api_get_path}/wikis"
end
+ def api_push_rules_path
+ "#{api_get_path}/push_rule"
+ end
+
def api_post_body
post_body = {
name: name,
@@ -358,6 +365,15 @@ module QA
parse_body(response)
end
+ def push_rules
+ response = get(request_url(api_push_rules_path))
+ parse_body(response)
+ end
+
+ def add_push_rules(rules)
+ api_post_to(api_push_rules_path, rules)
+ end
+
# Object comparison
#
# @param [QA::Resource::Project] other
diff --git a/qa/qa/resource/sandbox.rb b/qa/qa/resource/sandbox.rb
index b351d78a184..385e0fa4f7e 100644
--- a/qa/qa/resource/sandbox.rb
+++ b/qa/qa/resource/sandbox.rb
@@ -7,6 +7,17 @@ module QA
# creating it if it doesn't yet exist.
#
class Sandbox < GroupBase
+ class << self
+ # Force top level group creation via UI if test is executed on dot_com environment
+ def fabricate!(*args, &prepare_block)
+ return fabricate_via_browser_ui!(*args, &prepare_block) if Specs::Helpers::ContextSelector.dot_com?
+
+ fabricate_via_api!(*args, &prepare_block)
+ rescue NotImplementedError
+ fabricate_via_browser_ui!(*args, &prepare_block)
+ end
+ end
+
def initialize
@path = Runtime::Namespace.sandbox_name
end
@@ -14,6 +25,8 @@ module QA
alias_method :full_path, :path
def fabricate!
+ Flow::Login.sign_in_unless_signed_in
+
Page::Main::Menu.perform(&:go_to_groups)
Page::Dashboard::Groups.perform do |groups_page|
@@ -23,10 +36,13 @@ module QA
groups_page.click_new_group
Page::Group::New.perform do |group|
+ group.click_create_group
group.set_path(path)
group.set_visibility('Public')
group.create
end
+
+ @id = Page::Group::Show.perform(&:group_id)
end
end
end
diff --git a/qa/qa/runtime/allure_report.rb b/qa/qa/runtime/allure_report.rb
index 5f628050f3b..9ae04dbe111 100644
--- a/qa/qa/runtime/allure_report.rb
+++ b/qa/qa/runtime/allure_report.rb
@@ -76,6 +76,15 @@ module QA
RSpec.configure do |config|
config.add_formatter(AllureRspecFormatter)
config.add_formatter(QA::Support::Formatters::AllureMetadataFormatter)
+
+ config.append_after do |example|
+ Allure.add_attachment(
+ name: 'browser.log',
+ source: Capybara.current_session.driver.browser.logs.get(:browser).map(&:to_s).join("\n\n"),
+ type: Allure::ContentType::TXT,
+ test_case: true
+ )
+ end
end
end
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index 0566bc237bb..f1d93ce376a 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -99,7 +99,7 @@ module QA
end
# Disable /dev/shm use in CI. See https://gitlab.com/gitlab-org/gitlab/issues/4252
- capabilities['goog:chromeOptions'][:args] << 'disable-dev-shm-usage' if QA::Runtime::Env.running_in_ci?
+ capabilities['goog:chromeOptions'][:args] << 'disable-dev-shm-usage' if QA::Runtime::Env.disable_dev_shm?
# Specify the user-agent to allow challenges to be bypassed
# See https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/11938
@@ -205,6 +205,9 @@ module QA
simulate_slow_connection if Runtime::Env.simulate_slow_connection?
+ # Wait until the new page is ready for us to interact with it
+ Support::WaitForRequests.wait_for_requests
+
page_class.validate_elements_present! if page_class.respond_to?(:validate_elements_present!)
if QA::Runtime::Env.qa_cookies
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index cdfa95457c7..163710a1510 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -80,6 +80,11 @@ module QA
enabled?(ENV['CHROME_REUSE_PROFILE'], default: false)
end
+ # Disable /dev/shm use in CI. See https://gitlab.com/gitlab-org/gitlab/issues/4252
+ def disable_dev_shm?
+ running_in_ci? || enabled?(ENV['CHROME_DISABLE_DEV_SHM'], default: false)
+ end
+
def accept_insecure_certs?
enabled?(ENV['ACCEPT_INSECURE_CERTS'])
end
@@ -153,6 +158,12 @@ module QA
ENV['QA_REMOTE_MOBILE_DEVICE_NAME']
end
+ def mobile_layout?
+ return false if ENV['QA_REMOTE_MOBILE_DEVICE_NAME'].blank?
+
+ !(ENV['QA_REMOTE_MOBILE_DEVICE_NAME'].downcase.include?('ipad') || ENV['QA_REMOTE_MOBILE_DEVICE_NAME'].downcase.include?('tablet'))
+ end
+
def user_username
ENV['GITLAB_USERNAME']
end
@@ -392,7 +403,7 @@ module QA
end
def gitlab_agentk_version
- ENV.fetch('GITLAB_AGENTK_VERSION', 'v13.7.0')
+ ENV.fetch('GITLAB_AGENTK_VERSION', 'v14.4.0')
end
def transient_trials
diff --git a/qa/qa/runtime/feature.rb b/qa/qa/runtime/feature.rb
index 58408524f54..ec28813c1f6 100644
--- a/qa/qa/runtime/feature.rb
+++ b/qa/qa/runtime/feature.rb
@@ -5,15 +5,16 @@ require 'active_support/core_ext/object/blank'
module QA
module Runtime
class Feature
+ SetFeatureError = Class.new(RuntimeError)
+ AuthorizationError = Class.new(RuntimeError)
+ UnknownScopeError = Class.new(RuntimeError)
+ UnknownStateError = Class.new(RuntimeError)
+
class << self
# Documentation: https://docs.gitlab.com/ee/api/features.html
include Support::API
- SetFeatureError = Class.new(RuntimeError)
- AuthorizationError = Class.new(RuntimeError)
- UnknownScopeError = Class.new(RuntimeError)
-
def remove(key)
request = Runtime::API::Request.new(api_client, "/features/#{key}")
response = delete(request.url)
@@ -30,6 +31,23 @@ module QA
set_and_verify(key, enable: false, **scopes)
end
+ # Set one or more flags to their specified state.
+ #
+ # @param [Hash] flags The feature flags and desired values, e.g., { 'flag1' => 'enabled', 'flag2' => "disabled" }
+ # @param [Hash] scopes The scope (user, project, group) to apply the feature flag to.
+ def set(flags, **scopes)
+ flags.each_pair do |flag, state|
+ case state
+ when 'enabled', 'enable', 'true', 1, true
+ enable(flag, **scopes)
+ when 'disabled', 'disable', 'false', 0, false
+ disable(flag, **scopes)
+ else
+ raise UnknownStateError, "Unknown feature flag state: #{state}"
+ end
+ end
+ end
+
def enabled?(key, **scopes)
feature = JSON.parse(get_features).find { |flag| flag['name'] == key.to_s }
feature && (feature['state'] == 'on' || feature['state'] == 'conditional' && scopes.present? && enabled_scope?(feature['gates'], **scopes))
@@ -47,15 +65,15 @@ module QA
scopes.each do |key, value|
case key
when :project, :group, :user
- actors = gates.filter { |i| i['key'] == 'actors' }.first['value']
- break actors.include?("#{key.to_s.capitalize}:#{value.id}")
+ actors = gates.find { |i| i['key'] == 'actors' }['value']
+ return actors.include?("#{key.to_s.capitalize}:#{value.id}")
when :feature_group
- groups = gates.filter { |i| i['key'] == 'groups' }.first['value']
- break groups.include?(value)
- else
- raise UnknownScopeError, "Unknown scope: #{key}"
+ groups = gates.find { |i| i['key'] == 'groups' }['value']
+ return groups.include?(value)
end
end
+
+ raise UnknownScopeError, "Unknown scope in: #{scopes}"
end
def get_features
diff --git a/qa/qa/scenario/bootable.rb b/qa/qa/scenario/bootable.rb
index 841ac4dd560..ae180ffce1c 100644
--- a/qa/qa/scenario/bootable.rb
+++ b/qa/qa/scenario/bootable.rb
@@ -17,6 +17,22 @@ module QA
arguments = OptionParser.new do |parser|
options.to_a.each do |opt|
+ # The argument for the --set-feature-flags option should look something like "flag1=enabled,flag2=disabled"
+ # Here we translate that string into a hash, e.g.: { 'flag1' => 'enabled', 'flag2' => "disabled" }
+ if opt.name == :set_feature_flags
+ parser.on(opt.arg, opt.desc) do |flags|
+ value = flags.split(',').each_with_object({}) do |pair, hash|
+ flag_name, flag_value = pair.split('=')
+ raise '--set-feature-flags requires flag name and flag state for each flag, e.g., flag1=enabled,flag2=disabled' unless flag_name && flag_value
+
+ hash[flag_name] = flag_value
+ end
+ Runtime::Scenario.define(opt.name, value)
+ end
+
+ next
+ end
+
parser.on(opt.arg, opt.desc) do |value|
Runtime::Scenario.define(opt.name, value)
end
diff --git a/qa/qa/scenario/shared_attributes.rb b/qa/qa/scenario/shared_attributes.rb
index e2eaca42277..ddbe28f05d9 100644
--- a/qa/qa/scenario/shared_attributes.rb
+++ b/qa/qa/scenario/shared_attributes.rb
@@ -8,6 +8,9 @@ module QA
attribute :gitlab_address, '--address URL', 'Address of the instance to test'
attribute :enable_feature, '--enable-feature FEATURE_FLAG', 'Enable a feature before running tests'
attribute :disable_feature, '--disable-feature FEATURE_FLAG', 'Disable a feature before running tests'
+ attribute :set_feature_flags, '--set-feature-flags FEATURE_FLAGS',
+ 'Set one or more feature flags before running tests. ' \
+ 'Specify FEATURE_FLAGS as comma-separated flag=state pairs, e.g., "flag1=enabled,flag2=disabled"'
attribute :parallel, '--parallel', 'Execute tests in parallel'
attribute :loop, '--loop', 'Execute test repeatedly'
end
diff --git a/qa/qa/scenario/template.rb b/qa/qa/scenario/template.rb
index d0a201e3d22..50bb952f1fd 100644
--- a/qa/qa/scenario/template.rb
+++ b/qa/qa/scenario/template.rb
@@ -38,8 +38,8 @@ module QA
Runtime::Release.perform_before_hooks
Runtime::Feature.enable(options[:enable_feature]) if options.key?(:enable_feature)
-
Runtime::Feature.disable(options[:disable_feature]) if options.key?(:disable_feature) && (@feature_enabled = Runtime::Feature.enabled?(options[:disable_feature]))
+ Runtime::Feature.set(options[:set_feature_flags]) if options.key?(:set_feature_flags)
Specs::Runner.perform do |specs|
specs.tty = true
diff --git a/qa/qa/scenario/test/instance/reliable.rb b/qa/qa/scenario/test/instance/reliable.rb
new file mode 100644
index 00000000000..725ab59f24a
--- /dev/null
+++ b/qa/qa/scenario/test/instance/reliable.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Instance
+ class Reliable < Template
+ include Bootable
+ include SharedAttributes
+
+ tags :reliable
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/scenario/test/integration/ldap_no_tls.rb b/qa/qa/scenario/test/integration/ldap_no_tls.rb
index bbf4c847f33..19f62b6ed80 100644
--- a/qa/qa/scenario/test/integration/ldap_no_tls.rb
+++ b/qa/qa/scenario/test/integration/ldap_no_tls.rb
@@ -1,3 +1,4 @@
+# rubocop:todo Naming/FileName
# frozen_string_literal: true
module QA
@@ -11,3 +12,5 @@ module QA
end
end
end
+
+# rubocop:enable Naming/FileName
diff --git a/qa/qa/scenario/test/integration/ldap_tls.rb b/qa/qa/scenario/test/integration/ldap_tls.rb
index 2a767e57bc6..109fbe6fd74 100644
--- a/qa/qa/scenario/test/integration/ldap_tls.rb
+++ b/qa/qa/scenario/test/integration/ldap_tls.rb
@@ -1,3 +1,4 @@
+# rubocop:todo Naming/FileName
# frozen_string_literal: true
module QA
@@ -11,3 +12,5 @@ module QA
end
end
end
+
+# rubocop:enable Naming/FileName
diff --git a/qa/qa/scenario/test/integration/registry_tls.rb b/qa/qa/scenario/test/integration/registry_tls.rb
new file mode 100644
index 00000000000..4e9d6b6ea97
--- /dev/null
+++ b/qa/qa/scenario/test/integration/registry_tls.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Integration
+ class RegistryTLS < Test::Instance::All
+ tags :registry_tls
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/service/cluster_provider/gcloud.rb b/qa/qa/service/cluster_provider/gcloud.rb
index f0fb5eee6e3..c6d1f6cfe88 100644
--- a/qa/qa/service/cluster_provider/gcloud.rb
+++ b/qa/qa/service/cluster_provider/gcloud.rb
@@ -24,16 +24,6 @@ module QA
)
end
- def set_credentials(admin_user)
- master_auth = JSON.parse(`gcloud container clusters describe #{cluster_name} --region #{@region} --format 'json(masterAuth.username, masterAuth.password)'`)
-
- shell <<~CMD.tr("\n", ' ')
- kubectl config set-credentials #{admin_user}
- --username #{master_auth['masterAuth']['username']}
- --password #{master_auth['masterAuth']['password']}
- CMD
- end
-
def setup
login_if_not_already_logged_in
create_cluster
@@ -43,6 +33,12 @@ module QA
delete_cluster
end
+ def install_ingress
+ QA::Runtime::Logger.info "Attempting to install Ingress on cluster #{cluster_name}"
+ shell 'kubectl create -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-0.31.0/deploy/static/provider/cloud/deploy.yaml'
+ wait_for_ingress
+ end
+
private
def login_if_not_already_logged_in
@@ -59,7 +55,7 @@ module QA
end
def attempt_login_with_env_vars
- puts "No gcloud account. Attempting to login from env vars GCLOUD_ACCOUNT_EMAIL and GCLOUD_ACCOUNT_KEY."
+ QA::Runtime::Logger.debug("Logging in with GCLOUD_ACCOUNT_EMAIL and GCLOUD_ACCOUNT_KEY.")
gcloud_account_key = Tempfile.new('gcloud-account-key')
gcloud_account_key.write(Runtime::Env.gcloud_account_key)
gcloud_account_key.close
@@ -80,7 +76,6 @@ module QA
gcloud container clusters
create #{cluster_name}
#{auth_options}
- --enable-basic-auth
--region #{@region}
--disk-size 10GB
--num-nodes #{Runtime::Env.gcloud_num_nodes}
@@ -109,6 +104,18 @@ module QA
def get_region
Runtime::Env.gcloud_region || @available_regions.delete(@available_regions.sample)
end
+
+ def wait_for_ingress
+ QA::Runtime::Logger.info 'Waiting for Ingress controller pod to be initialized'
+
+ Support::Retrier.retry_until(max_attempts: 60, sleep_interval: 1) do
+ service_available?('kubectl get pods --all-namespaces -l app.kubernetes.io/component=controller | grep -o "ingress-nginx-controller.*1/1"')
+ end
+ end
+
+ def service_available?(command)
+ system("#{command} > /dev/null 2>&1")
+ end
end
end
end
diff --git a/qa/qa/service/kubernetes_cluster.rb b/qa/qa/service/kubernetes_cluster.rb
index 674bcdca9bb..ec53b9d8163 100644
--- a/qa/qa/service/kubernetes_cluster.rb
+++ b/qa/qa/service/kubernetes_cluster.rb
@@ -41,6 +41,10 @@ module QA
cluster_name
end
+ def install_ingress
+ @provider.install_ingress
+ end
+
def create_secret(secret, secret_name)
shell("kubectl create secret generic #{secret_name} --from-literal=token='#{secret}'")
end
@@ -70,7 +74,13 @@ module QA
end
def fetch_external_ip_for_ingress
- `kubectl get svc --all-namespaces --no-headers=true -l app.kubernetes.io/name=ingress-nginx -o custom-columns=:'status.loadBalancer.ingress[0].ip' | grep -v 'none'`
+ install_ingress
+
+ # need to wait since the ingress-nginx service has an initial delay set of 10 seconds
+ sleep 10
+ ingress_ip = `kubectl get svc --all-namespaces --no-headers=true -l app.kubernetes.io/name=ingress-nginx -o custom-columns=:'status.loadBalancer.ingress[0].ip' | grep -v 'none'`
+ QA::Runtime::Logger.debug "Has ingress address set to: #{ingress_ip}"
+ ingress_ip
end
private
@@ -82,7 +92,6 @@ module QA
def fetch_credentials
return global_credentials unless rbac
- @provider.set_credentials(admin_user)
create_service_account(admin_user)
account_credentials
end
diff --git a/qa/qa/service/praefect_manager.rb b/qa/qa/service/praefect_manager.rb
index 71e3383a534..dbb49f18881 100644
--- a/qa/qa/service/praefect_manager.rb
+++ b/qa/qa/service/praefect_manager.rb
@@ -19,6 +19,8 @@ module QA
@virtual_storage = 'default'
end
+ attr_reader :primary_node, :secondary_node, :tertiary_node
+
# Executes the praefect `dataloss` command.
#
# @return [Boolean] whether dataloss has occurred
@@ -376,7 +378,6 @@ module QA
select job from replication_queue
where state = 'ready'
and job ->> 'change' = 'update'
- and job ->> 'source_node_storage' = '#{current_primary_node}'
and job ->> 'target_node_storage' = '#{@primary_node}';
SQL
) do |line|
@@ -396,6 +397,97 @@ module QA
result.size >= 5
end
+ def list_untracked_repositories
+ untracked_repositories = []
+ shell "docker exec #{@praefect} bash -c 'gitlab-ctl praefect list-untracked-repositories'" do |line|
+ # Results look like this depending on whether untracked items found or not
+ # Running list-untracked-repositories
+ # Done.
+
+ # Running list-untracked-repositories
+ # {"relative_path":"@hashed/aa/bb.git","storage":"gitaly1","virtual_storage":"default"}
+ # {"relative_path":"@hashed/bb/cc.git","storage":"gitaly3","virtual_storage":"default"}
+ # Done.
+
+ QA::Runtime::Logger.debug(line.chomp)
+ next if line.start_with?('Running list-untracked-repositories')
+ next if line.start_with?('Done.')
+
+ untracked_repositories.append(JSON.parse(line))
+ end
+
+ QA::Runtime::Logger.debug("list_untracked_repositories --- #{untracked_repositories}")
+ untracked_repositories
+ end
+
+ def track_repository_in_praefect(relative_path, storage, virtual_storage)
+ cmd = "gitlab-ctl praefect track-repository --repository-relative-path #{relative_path} --authoritative-storage #{storage} --virtual-storage-name #{virtual_storage}"
+ shell "docker exec #{@praefect} bash -c '#{cmd}'"
+ end
+
+ def remove_tracked_praefect_repository(relative_path, virtual_storage)
+ cmd = "gitlab-ctl praefect remove-repository --repository-relative-path #{relative_path} --virtual-storage-name #{virtual_storage}"
+ shell "docker exec #{@praefect} bash -c '#{cmd}'"
+ end
+
+ def add_repo_to_disk(node, repo_path)
+ cmd = "GIT_DIR=. git init --initial-branch=main /var/opt/gitlab/git-data/repositories/#{repo_path}"
+ shell "docker exec --user git #{node} bash -c '#{cmd}'"
+ end
+
+ def remove_repo_from_disk(repo_path)
+ cmd = "rm -rf /var/opt/gitlab/git-data/repositories/#{repo_path}"
+ shell "docker exec #{@primary_node} bash -c '#{cmd}'"
+ shell "docker exec #{@secondary_node} bash -c '#{cmd}'"
+ shell "docker exec #{@tertiary_node} bash -c '#{cmd}'"
+ end
+
+ def remove_repository_from_praefect_database(relative_path)
+ shell sql_to_docker_exec_cmd("delete from repositories where relative_path = '#{relative_path}';")
+ shell sql_to_docker_exec_cmd("delete from storage_repositories where relative_path = '#{relative_path}';")
+ end
+
+ def praefect_database_tracks_repo?(relative_path)
+ storage_repositories = []
+ shell sql_to_docker_exec_cmd("SELECT count(*) FROM storage_repositories where relative_path='#{relative_path}';") do |line|
+ storage_repositories << line
+ end
+ QA::Runtime::Logger.debug("storage_repositories count is ---#{storage_repositories}")
+
+ repositories = []
+ shell sql_to_docker_exec_cmd("SELECT count(*) FROM repositories where relative_path='#{relative_path}';") do |line|
+ repositories << line
+ end
+ QA::Runtime::Logger.debug("repositories count is ---#{repositories}")
+
+ (storage_repositories[2].to_i >= 1) && (repositories[2].to_i >= 1)
+ end
+
+ def repository_replicated_to_disk?(node, relative_path)
+ Support::Waiter.wait_until(max_duration: 300, sleep_interval: 3, raise_on_failure: false) do
+ result = []
+ shell sql_to_docker_exec_cmd("SELECT count(*) FROM storage_repositories where relative_path='#{relative_path}';") do |line|
+ result << line
+ end
+ QA::Runtime::Logger.debug("result is ---#{result}")
+ result[2].to_i == 3
+ end
+
+ repository_exists_on_node_disk?(node, relative_path)
+ end
+
+ def repository_exists_on_node_disk?(node, relative_path)
+ # If the dir does not exist it has a non zero exit code leading to a error being raised
+ # Instead we echo a test line if the dir does not exist, which has a zero exit code, with no output
+ bash_command = "test -d /var/opt/gitlab/git-data/repositories/#{relative_path} || echo -n 'DIR_DOES_NOT_EXIST'"
+ result = []
+ shell "docker exec #{node} bash -c '#{bash_command}'" do |line|
+ result << line
+ end
+ QA::Runtime::Logger.debug("result is ---#{result}")
+ result.exclude?("DIR_DOES_NOT_EXIST")
+ end
+
private
def current_primary_node
diff --git a/qa/qa/specs/features/api/1_manage/bulk_import_group_spec.rb b/qa/qa/specs/features/api/1_manage/bulk_import_group_spec.rb
index 8b4900957c5..158881ed94c 100644
--- a/qa/qa/specs/features/api/1_manage/bulk_import_group_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/bulk_import_group_spec.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :requires_admin do
+ # run only base UI validation on staging because test requires top level group creation which is problematic
+ # on staging environment
+ RSpec.describe 'Manage', :requires_admin, except: { subdomain: :staging } do
describe 'Bulk group import' do
- let!(:staging?) { Runtime::Scenario.gitlab_address.include?('staging.gitlab.com') }
-
let(:import_wait_duration) { { max_duration: 300, sleep_interval: 2 } }
let(:admin_api_client) { Runtime::API::Client.as_admin }
let(:user) do
@@ -38,11 +38,13 @@ module QA
end
before do
- Runtime::Feature.enable(:top_level_group_creation_enabled) if staging?
-
sandbox.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
end
+ after do
+ user.remove_via_api!
+ end
+
context 'with subgroups and labels' do
let(:subgroup) do
Resource::Group.fabricate_via_api! do |group|
@@ -155,12 +157,6 @@ module QA
expect(imported_member.access_level).to eq(Resource::Members::AccessLevel::DEVELOPER)
end
end
-
- after do
- user.remove_via_api!
- ensure
- Runtime::Feature.disable(:top_level_group_creation_enabled) if staging?
- end
end
end
end
diff --git a/qa/qa/specs/features/api/1_manage/bulk_import_project_spec.rb b/qa/qa/specs/features/api/1_manage/bulk_import_project_spec.rb
index 9935908d55e..14c94e99446 100644
--- a/qa/qa/specs/features/api/1_manage/bulk_import_project_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/bulk_import_project_spec.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :requires_admin do
+ # run only base UI validation on staging because test requires top level group creation which is problematic
+ # on staging environment
+ RSpec.describe 'Manage', :requires_admin, except: { subdomain: :staging } do
describe 'Bulk project import' do
- let!(:staging?) { Runtime::Scenario.gitlab_address.include?('staging.gitlab.com') }
-
let(:import_wait_duration) { { max_duration: 300, sleep_interval: 2 } }
let(:admin_api_client) { Runtime::API::Client.as_admin }
let(:user) do
@@ -33,6 +33,7 @@ module QA
Resource::Project.fabricate_via_api! do |project|
project.api_client = api_client
project.group = source_group
+ project.initialize_with_readme = true
end
end
@@ -44,33 +45,87 @@ module QA
end
end
+ let(:imported_projects) do
+ imported_group.reload!.projects
+ end
+
+ let(:project_import_failures) do
+ imported_group.import_details
+ .find { |entity| entity[:destination_name] == source_project.name }
+ &.fetch(:failures)
+ end
+
before do
Runtime::Feature.enable(:bulk_import_projects)
- Runtime::Feature.enable(:top_level_group_creation_enabled) if staging?
sandbox.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
- source_project # fabricate source group and project
+ source_project.tap { |project| project.add_push_rules(member_check: true) } # fabricate source group and project
end
after do
user.remove_via_api!
ensure
Runtime::Feature.disable(:bulk_import_projects)
- Runtime::Feature.disable(:top_level_group_creation_enabled) if staging?
end
context 'with project' do
+ before do
+ imported_group # trigger import
+ end
+
it(
'successfully imports project',
testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2297'
) do
expect { imported_group.import_status }.to eventually_eq('finished').within(import_wait_duration)
+ expect(imported_projects.count).to eq(1), "Expected to have 1 imported project"
- imported_projects = imported_group.reload!.projects
aggregate_failures do
- expect(imported_projects.count).to eq(1)
expect(imported_projects.first).to eq(source_project)
+ expect(project_import_failures).to be_empty, "Expected no errors, was: #{project_import_failures}"
+ end
+ end
+ end
+
+ context 'with project issues' do
+ let(:source_issue) do
+ Resource::Issue.fabricate_via_api! do |issue|
+ issue.api_client = api_client
+ issue.project = source_project
+ issue.labels = %w[label_one label_two]
+ end
+ end
+
+ let(:imported_issues) do
+ imported_projects.first.issues
+ end
+
+ let(:imported_issue) do
+ issue = imported_issues.first
+ Resource::Issue.init do |resource|
+ resource.api_client = api_client
+ resource.project = imported_projects.first
+ resource.iid = issue[:iid]
+ end
+ end
+
+ before do
+ source_issue # fabricate source group, project, issue
+ imported_group # trigger import
+ end
+
+ it(
+ 'successfully imports issue',
+ testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2325'
+ ) do
+ expect { imported_group.import_status }.to eventually_eq('finished').within(import_wait_duration)
+ expect(imported_projects.count).to eq(1), "Expected to have 1 imported project"
+
+ aggregate_failures do
+ expect(imported_issues.count).to eq(1)
+ expect(imported_issue.reload!).to eq(source_issue)
+ expect(project_import_failures).to be_empty, "Expected no errors, was: #{project_import_failures}"
end
end
end
diff --git a/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
index ec4f0387128..b85a0116f01 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- context 'Gitaly automatic failover and recovery', :orchestrated, :gitaly_cluster, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/238953', type: :flaky } do
+ context 'Gitaly automatic failover and recovery', :orchestrated, :gitaly_cluster do
# Variables shared between contexts. They're used and shared between
# contexts so they can't be `let` variables.
praefect_manager = Service::PraefectManager.new
diff --git a/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb
index 37670b70fd8..62437598f3b 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
context 'Gitaly' do
- describe 'Backend node recovery', :orchestrated, :gitaly_cluster, :skip_live_env, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/322647', type: :flaky } do
+ describe 'Backend node recovery', :orchestrated, :gitaly_cluster, :skip_live_env do
let(:praefect_manager) { Service::PraefectManager.new }
let(:project) do
Resource::Project.fabricate! do |project|
@@ -31,14 +31,6 @@ module QA
praefect_manager.stop_primary_node
praefect_manager.wait_for_gitaly_check
- # Confirm that we have access to the repo after failover
- Support::Waiter.wait_until(retry_on_exception: true, sleep_interval: 5) do
- Resource::Repository::Commit.fabricate_via_api! do |commits|
- commits.project = project
- commits.sha = project.default_branch
- end
- end
-
# Push a commit to the new primary
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
@@ -58,6 +50,11 @@ module QA
# Wait for automatic replication
praefect_manager.wait_for_replication(project.id)
+ # Force switch to the old primary node
+ # This ensures that the commit was replicated
+ praefect_manager.stop_secondary_node
+ praefect_manager.stop_tertiary_node
+
# Confirm that both commits are available
expect(project.commits.map { |commit| commit[:message].chomp })
.to include("Initial commit").and include("pushed after failover")
diff --git a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
index 1aea1bd1189..dfc2de02bf0 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
@@ -16,9 +16,15 @@ module QA
end
before do
+ praefect_manager.start_all_nodes
praefect_manager.wait_for_replication(project.id)
end
+ after do
+ # Leave the cluster in a suitable state for subsequent tests
+ praefect_manager.start_all_nodes
+ end
+
it 'reads from each node', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1264' do
pre_read_data = praefect_manager.query_read_distribution
@@ -42,9 +48,7 @@ module QA
after do
# Leave the cluster in a suitable state for subsequent tests
- praefect_manager.start_secondary_node
- praefect_manager.wait_for_health_check_all_nodes
- praefect_manager.wait_for_reliable_connection
+ praefect_manager.start_all_nodes
end
it 'does not read from the unhealthy node', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1263' do
diff --git a/qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb
new file mode 100644
index 00000000000..07ea7971396
--- /dev/null
+++ b/qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ context 'Praefect repository commands', :orchestrated, :gitaly_cluster do
+ let(:praefect_manager) { Service::PraefectManager.new }
+
+ let(:repo1) { { "relative_path" => "@hashed/repo1.git", "storage" => "gitaly1", "virtual_storage" => "default" } }
+ let(:repo2) { { "relative_path" => "@hashed/path/to/repo2.git", "storage" => "gitaly3", "virtual_storage" => "default" } }
+
+ before do
+ praefect_manager.add_repo_to_disk(praefect_manager.primary_node, repo1["relative_path"])
+ praefect_manager.add_repo_to_disk(praefect_manager.tertiary_node, repo2["relative_path"])
+ end
+
+ after do
+ praefect_manager.remove_repo_from_disk(repo1["relative_path"])
+ praefect_manager.remove_repo_from_disk(repo2["relative_path"])
+ praefect_manager.remove_repository_from_praefect_database(repo1["relative_path"])
+ praefect_manager.remove_repository_from_praefect_database(repo2["relative_path"])
+ end
+
+ it 'allows admin to manage difference between praefect database and disk state', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2344' do
+ # Some repos are on disk that praefect is not aware of
+ untracked_repositories = praefect_manager.list_untracked_repositories
+ expect(untracked_repositories).to include(repo1)
+ expect(untracked_repositories).to include(repo2)
+
+ # admin manually adds the first repo to the praefect database
+ praefect_manager.track_repository_in_praefect(repo1["relative_path"], repo1["storage"], repo1["virtual_storage"])
+ untracked_repositories = praefect_manager.list_untracked_repositories
+ expect(untracked_repositories).not_to include(repo1)
+ expect(untracked_repositories).to include(repo2)
+ expect(praefect_manager.repository_exists_on_node_disk?(praefect_manager.primary_node, repo1["relative_path"])).to be true
+ expect(praefect_manager.praefect_database_tracks_repo?(repo1["relative_path"])).to be true
+
+ # admin manually adds the second repo to the praefect database
+ praefect_manager.track_repository_in_praefect(repo2["relative_path"], repo2["storage"], repo2["virtual_storage"])
+ untracked_repositories = praefect_manager.list_untracked_repositories
+ expect(untracked_repositories).not_to include(repo2)
+ expect(praefect_manager.repository_exists_on_node_disk?(praefect_manager.tertiary_node, repo2["relative_path"])).to be true
+ expect(praefect_manager.praefect_database_tracks_repo?(repo2["relative_path"])).to be true
+
+ # admin ensures replication to other nodes occurs
+ expect(praefect_manager.repository_replicated_to_disk?(praefect_manager.secondary_node, repo1["relative_path"])).to be true
+ expect(praefect_manager.repository_replicated_to_disk?(praefect_manager.tertiary_node, repo1["relative_path"])).to be true
+ expect(praefect_manager.repository_replicated_to_disk?(praefect_manager.primary_node, repo2["relative_path"])).to be true
+ expect(praefect_manager.repository_replicated_to_disk?(praefect_manager.secondary_node, repo2["relative_path"])).to be true
+
+ # admin chooses to remove the first repo completely from praefect and disk
+ praefect_manager.remove_tracked_praefect_repository(repo1["relative_path"], repo1["virtual_storage"])
+ expect(praefect_manager.repository_exists_on_node_disk?(praefect_manager.primary_node, repo1["relative_path"])).to be false
+ expect(praefect_manager.repository_exists_on_node_disk?(praefect_manager.secondary_node, repo1["relative_path"])).to be false
+ expect(praefect_manager.repository_exists_on_node_disk?(praefect_manager.tertiary_node, repo1["relative_path"])).to be false
+ expect(praefect_manager.praefect_database_tracks_repo?(repo1["relative_path"])).to be false
+
+ untracked_repositories = praefect_manager.list_untracked_repositories
+ expect(untracked_repositories).not_to include(repo1)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb
index c136d14c1e5..15d51c14d26 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb
@@ -4,17 +4,16 @@ module QA
RSpec.describe 'Manage', :requires_admin do
describe 'Bulk group import' do
let!(:staging?) { Runtime::Scenario.gitlab_address.include?('staging.gitlab.com') }
-
- let(:admin_api_client) { Runtime::API::Client.as_admin }
- let(:user) do
+ let!(:admin_api_client) { Runtime::API::Client.as_admin }
+ let!(:user) do
Resource::User.fabricate_via_api! do |usr|
usr.api_client = admin_api_client
usr.hard_delete_on_api_removal = true
end
end
- let(:api_client) { Runtime::API::Client.new(user: user) }
- let(:personal_access_token) { api_client.personal_access_token }
+ let!(:api_client) { Runtime::API::Client.new(user: user) }
+ let!(:personal_access_token) { api_client.personal_access_token }
let(:sandbox) do
Resource::Sandbox.fabricate_via_api! do |group|
@@ -23,7 +22,7 @@ module QA
end
let(:source_group) do
- Resource::Sandbox.fabricate_via_api! do |group|
+ Resource::Sandbox.fabricate! do |group|
group.api_client = api_client
group.path = "source-group-for-import-#{SecureRandom.hex(4)}"
end
@@ -38,14 +37,12 @@ module QA
end
before do
- Runtime::Feature.enable(:top_level_group_creation_enabled) if staging?
-
sandbox.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
- # create groups explicitly before connecting gitlab instance
+ Flow::Login.sign_in(as: user)
+
source_group
- Flow::Login.sign_in(as: user)
Page::Main::Menu.perform(&:go_to_create_group)
Page::Group::New.perform do |group|
group.switch_to_import_tab
@@ -53,6 +50,10 @@ module QA
end
end
+ after do
+ user.remove_via_api!
+ end
+
it(
'imports group from UI',
testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1806',
@@ -72,12 +73,6 @@ module QA
end
end
end
-
- after do
- user.remove_via_api!
- ensure
- Runtime::Feature.disable(:top_level_group_creation_enabled) if staging?
- end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
index ca95d567316..9625771164c 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :smoke do
+ RSpec.describe 'Manage', :smoke, :mobile do
describe 'basic user login' do
it 'user logs in using basic credentials and logs out', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1578' do
Flow::Login.sign_in
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb
index 2b1c956039f..734529f319a 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :mixed_env, :smoke, only: { subdomain: :staging } do
+ RSpec.describe 'Manage', only: { subdomain: :staging }, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/344213', type: :stale } do
describe 'basic user' do
it 'remains logged in when redirected from canary to non-canary node', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2251' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
index af4e7126c29..34a7431e328 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
@@ -5,13 +5,13 @@ module QA
describe 'Project', :requires_admin do
shared_examples 'successful project creation' do
it 'creates a new project' do
- Page::Project::Show.perform do |project|
- expect(project).to have_content(project_name)
- expect(project).to have_content(
+ Page::Project::Show.perform do |project_page|
+ expect(project_page).to have_content(project_name)
+ expect(project_page).to have_content(
/Project \S?#{project_name}\S+ was successfully created/
)
- expect(project).to have_content('create awesome project test')
- expect(project).to have_content('The repository for this project is empty')
+ expect(project_page).to have_content('create awesome project test')
+ expect(project_page).to have_content('The repository for this project is empty')
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
index 4e3739a7672..c078c4bf12e 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
@@ -4,7 +4,6 @@ module QA
RSpec.describe 'Manage', :github, :requires_admin do
describe 'Project import' do
let(:github_repo) { 'gitlab-qa-github/test-project' }
- let(:imported_project_name) { 'imported-project' }
let(:api_client) { Runtime::API::Client.as_admin }
let(:group) { Resource::Group.fabricate_via_api! { |resource| resource.api_client = api_client } }
let(:user) do
@@ -17,11 +16,10 @@ module QA
let(:imported_project) do
Resource::ProjectImportedFromGithub.init do |project|
project.import = true
- project.add_name_uuid = false
- project.name = imported_project_name
project.group = group
project.github_personal_access_token = Runtime::Env.github_access_token
project.github_repository_path = github_repo
+ project.api_client = api_client
end
end
@@ -43,7 +41,7 @@ module QA
it 'imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1607' do
Page::Project::Import::Github.perform do |import_page|
import_page.add_personal_access_token(Runtime::Env.github_access_token)
- import_page.import!(github_repo, group.full_path, imported_project_name)
+ import_page.import!(github_repo, group.full_path, imported_project.name)
aggregate_failures do
expect(import_page).to have_imported_project(github_repo)
@@ -56,7 +54,7 @@ module QA
imported_project.reload!.visit!
Page::Project::Show.perform do |project|
aggregate_failures do
- expect(project).to have_content(imported_project_name)
+ expect(project).to have_content(imported_project.name)
expect(project).to have_content('This test project is used for automated GitHub import by GitLab QA.')
end
end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
index 7519f4daae2..81ae8b82ef6 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
@@ -9,7 +9,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1185' do
+ it 'creates an issue', :mobile, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1185' do
issue = Resource::Issue.fabricate_via_browser_ui!
Page::Project::Menu.perform(&:click_issues)
@@ -19,13 +19,13 @@ module QA
end
end
- it 'closes an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1222' do
+ it 'closes an issue', :mobile, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1222' do
closed_issue.visit!
Page::Project::Issue::Show.perform do |issue_page|
issue_page.click_close_issue_button
- expect(issue_page).to have_element(:reopen_issue_button)
+ expect(issue_page).to have_reopen_issue_button
end
Page::Project::Menu.perform(&:click_issues)
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb
index 1752513a831..96c9c9b55b4 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- context 'Add batch suggestions to a Merge Request', :transient do
+ context 'Add batch suggestions to a Merge Request' do
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'suggestions_project'
@@ -46,13 +46,13 @@ module QA
merge_request.visit!
end
- it 'applies multiple suggestions', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1838', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/342131', type: :stale } do
+ it 'applies multiple suggestions', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1838' do
Page::MergeRequest::Show.perform do |merge_request|
merge_request.click_diffs_tab
4.times { merge_request.add_suggestion_to_batch }
merge_request.apply_suggestion_with_message("Custom commit message")
- expect(merge_request).to have_css('.badge-success', text: "Applied", count: 4)
+ expect(merge_request).to have_suggestions_applied(4)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb
index 339010cd1df..719006e87eb 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb
@@ -48,7 +48,7 @@ module QA
merge_request.click_diffs_tab
merge_request.apply_suggestion_with_message(commit_message)
- expect(merge_request).to have_css('.badge-success', text: 'Applied')
+ expect(merge_request).to have_suggestions_applied
merge_request.click_commits_tab
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb
index c648fecf847..158e841514c 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb
@@ -21,7 +21,8 @@ module QA
it 'can link to a specific line of code in Web IDE', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1844' do
project.visit!
- Page::Project::Show.perform(&:open_web_ide!)
+ # Open Web IDE by using a keyboard shortcut
+ Page::Project::Show.perform(&:open_web_ide_via_shortcut)
Page::Project::WebIDE::Edit.perform do |ide|
ide.select_file('app.js')
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
index 47117ae751f..e6910ad8592 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Verify', :runner do
+ RSpec.describe 'Verify', :smoke, :runner do
describe 'Pipeline creation and processing' do
let(:executor) { "qa-runner-#{Time.now.to_i}" }
- let(:max_wait) { 30 }
let(:project) do
Resource::Project.fabricate_via_api! do |project|
@@ -21,11 +20,10 @@ module QA
end
after do
- runner.remove_via_api!
+ [runner, project].each(&:remove_via_api!)
end
it 'users creates a pipeline which gets processed', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1601' do
- # TODO: Convert back to :smoke once proved to be stable. Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300909
Flow::Login.sign_in
Resource::Repository::Commit.fabricate_via_api! do |commit|
@@ -68,19 +66,21 @@ module QA
Flow::Pipeline.visit_latest_pipeline
- {
- 'test-success': :passed,
- 'test-failure': :failed,
- 'test-tags-mismatch': :pending,
- 'test-artifacts': :passed
- }.each do |job, status|
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job(job)
- end
+ aggregate_failures do
+ {
+ 'test-success': 'passed',
+ 'test-failure': 'failed',
+ 'test-tags-mismatch': 'pending',
+ 'test-artifacts': 'passed'
+ }.each do |job, status|
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job(job)
+ end
- Page::Project::Job::Show.perform do |show|
- expect(show).to public_send("be_#{status}")
- show.click_element(:pipeline_path, Page::Project::Pipeline::Show)
+ Page::Project::Job::Show.perform do |show|
+ expect(show).to have_status(status), "Expected job status to be #{status} but got #{show.status_badge} instead."
+ show.click_element(:pipeline_path, Page::Project::Pipeline::Show)
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb
deleted file mode 100644
index a8f1fc2a7de..00000000000
--- a/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Package', :orchestrated, :packages, :object_storage, quarantine: {
- only: { job: 'object_storage' },
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/335981',
- type: :bug
- } do
- describe 'Conan Repository' do
- include Runtime::Fixtures
-
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'conan-package-project'
- end
- end
-
- let(:package) do
- Resource::Package.init do |package|
- package.name = 'conantest'
- package.project = project
- end
- end
-
- let!(:runner) do
- Resource::Runner.fabricate! do |runner|
- runner.name = "qa-runner-#{Time.now.to_i}"
- runner.tags = ["runner-for-#{project.name}"]
- runner.executor = :docker
- runner.project = project
- end
- end
-
- let(:gitlab_address_with_port) do
- uri = URI.parse(Runtime::Scenario.gitlab_address)
- "#{uri.scheme}://#{uri.host}:#{uri.port}"
- end
-
- after do
- runner.remove_via_api!
- package.remove_via_api!
- end
-
- it 'publishes, installs, and deletes a Conan package', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1638' do
- Flow::Login.sign_in
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([{
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: conanio/gcc7
-
- test_package:
- stage: deploy
- script:
- - "conan remote add gitlab #{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/conan"
- - "conan new #{package.name}/0.1 -t"
- - "conan create . mycompany/stable"
- - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package.name}/0.1@mycompany/stable --all --remote=gitlab"
- - "conan install #{package.name}/0.1@mycompany/stable --remote=gitlab"
- tags:
- - "runner-for-#{project.name}"
- YAML
- }])
- end
-
- project.visit!
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('test_package')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- Page::Project::Menu.perform(&:click_packages_link)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package.name)
- index.click_package(package.name)
- end
-
- Page::Project::Packages::Show.perform(&:click_delete)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package.name)
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb
new file mode 100644
index 00000000000..51735d79fbd
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb
@@ -0,0 +1,191 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, only: { pipeline: :main } do
+ describe 'Self-managed Container Registry' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-registry'
+ project.template_name = 'express'
+ project.visibility = :private
+ end
+ end
+
+ let(:project_deploy_token) do
+ Resource::DeployToken.fabricate_via_browser_ui! do |deploy_token|
+ deploy_token.name = 'registry-deploy-token'
+ deploy_token.project = project
+ deploy_token.scopes = [
+ :read_repository,
+ :read_package_registry,
+ :write_package_registry,
+ :read_registry,
+ :write_registry
+ ]
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let(:personal_access_token) { Runtime::Env.personal_access_token }
+
+ before do
+ Flow::Login.sign_in
+ project.visit!
+ end
+
+ after do
+ runner.remove_via_api!
+ project.remove_via_api!
+ end
+
+ where(:authentication_token_type, :token_name) do
+ :personal_access_token | 'Personal Access Token'
+ :project_deploy_token | 'Deploy Token'
+ :ci_job_token | 'Job Token'
+ end
+
+ with_them do
+ let(:auth_token) do
+ case authentication_token_type
+ when :personal_access_token
+ "\"#{personal_access_token}\""
+ when :project_deploy_token
+ "\"#{project_deploy_token.password}\""
+ when :ci_job_token
+ '$CI_JOB_TOKEN'
+ end
+ end
+
+ let(:auth_user) do
+ case authentication_token_type
+ when :personal_access_token
+ "$CI_REGISTRY_USER"
+ when :project_deploy_token
+ "\"#{project_deploy_token.username}\""
+ when :ci_job_token
+ 'gitlab-ci-token'
+ end
+ end
+
+ context "when tls is disabled" do
+ it "using a #{params[:token_name]}, pushes image and deletes tag", :registry do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ build:
+ image: docker:19.03.12
+ stage: build
+ services:
+ - name: docker:19.03.12-dind
+ command: ["--insecure-registry=gitlab.test:5050"]
+ variables:
+ IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+ script:
+ - docker login -u #{auth_user} -p #{auth_token} gitlab.test:5050
+ - docker build -t $IMAGE_TAG .
+ - docker push $IMAGE_TAG
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ }])
+ end
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('build')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Page::Project::Menu.perform(&:go_to_container_registry)
+
+ Page::Project::Registry::Show.perform do |registry|
+ expect(registry).to have_registry_repository(project.path_with_namespace)
+
+ registry.click_on_image(project.path_with_namespace)
+ expect(registry).to have_tag('master')
+
+ registry.click_delete
+ expect(registry).not_to have_tag('master')
+ end
+ end
+ end
+ end
+
+ context "when tls is enabled" do
+ it "pushes image and deletes tag", :registry_tls, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2378' do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ build:
+ image: docker:19.03.12
+ stage: build
+ services:
+ - name: docker:19.03.12-dind
+ command:
+ - /bin/sh
+ - -c
+ - |
+ apk add --no-cache openssl
+ true | openssl s_client -showcerts -connect gitlab.test:5050 > /usr/local/share/ca-certificates/gitlab.test.crt
+ update-ca-certificates
+ dockerd-entrypoint.sh || exit
+ variables:
+ IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+ script:
+ - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD gitlab.test:5050
+ - docker build -t $IMAGE_TAG .
+ - docker push $IMAGE_TAG
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ }])
+ end
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('build')
+ end
+
+ Support::Retrier.retry_until(max_duration: 800, sleep_interval: 10) do
+ project.pipelines.last[:status] == 'success'
+ end
+
+ Page::Project::Menu.perform(&:go_to_container_registry)
+
+ Page::Project::Registry::Show.perform do |registry|
+ expect(registry).to have_registry_repository(project.path_with_namespace)
+
+ registry.click_on_image(project.path_with_namespace)
+ expect(registry).to have_tag('master')
+
+ registry.click_delete
+ expect(registry).not_to have_tag('master')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb
index 65519cdebec..65519cdebec 100644
--- a/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb
new file mode 100644
index 00000000000..82b7af8eba7
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package' do
+ # TODO: Remove :requires_admin when the `Runtime::Feature.enable` method call is removed
+ describe 'Container Registry Online Garbage Collection', :registry_gc, :requires_admin, only: { subdomain: %i[pre] } do
+ let(:group) { Resource::Group.fabricate_via_api! }
+
+ let(:imported_project) do
+ Resource::ProjectImportedFromURL.fabricate_via_browser_ui! do |project|
+ project.name = 'container-registry'
+ project.group = group
+ project.gitlab_repository_path = 'https://gitlab.com/gitlab-org/container-registry.git'
+ end
+ end
+
+ let!(:gitlab_ci_yaml) do
+ <<~YAML
+ variables:
+ GOPATH: $CI_PROJECT_DIR/.go
+ BUILD_CACHE: $CI_PROJECT_DIR/.online-gc-tester
+ STAGE_ONE_VALIDATION_DELAY: "6m"
+ STAGE_TWO_VALIDATION_DELAY: "12m"
+ STAGE_THREE_VALIDATION_DELAY: "6m"
+ STAGE_FOUR_VALIDATION_DELAY: "12m"
+ STAGE_FIVE_VALIDATION_DELAY: "12m"
+
+ stages:
+ - generate
+ - build
+ - test
+
+ .base: &base
+ image: docker:19
+ services:
+ - docker:19-dind
+ variables:
+ DOCKER_HOST: tcp://docker:2376
+ DOCKER_TLS_CERTDIR: "/certs"
+ DOCKER_TLS_VERIFY: 1
+ DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client"
+ before_script:
+ - until docker info; do sleep 1; done
+ - mkdir -p $GOPATH
+ - mkdir -p $BUILD_CACHE
+ - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+
+ test:
+ stage: generate
+ extends: .base
+ script:
+ - apk add go make git
+ - make binaries
+ - ./bin/online-gc-tester generate --base-dir=$BUILD_CACHE
+ - ./bin/online-gc-tester build --base-dir=$BUILD_CACHE
+ - ./bin/online-gc-tester push --base-dir=$BUILD_CACHE
+ - ./bin/online-gc-tester pull --base-dir=$BUILD_CACHE
+ - ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=1 --delay=$STAGE_ONE_VALIDATION_DELAY
+ - ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=2 --delay=$STAGE_TWO_VALIDATION_DELAY
+ - ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=3 --delay=$STAGE_THREE_VALIDATION_DELAY
+ - ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=4 --delay=$STAGE_FOUR_VALIDATION_DELAY
+ - ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=5 --delay=$STAGE_FIVE_VALIDATION_DELAY
+ timeout: 1h 30m
+ YAML
+ end
+
+ before do
+ Runtime::Feature.enable(:paginatable_namespace_drop_down_for_project_creation)
+
+ Flow::Login.sign_in
+
+ imported_project
+
+ Page::Project::Menu.perform(&:go_to_repository_settings)
+
+ Page::Project::Settings::Repository.perform do |setting|
+ setting.expand_default_branch
+ end
+
+ Page::Project::Settings::DefaultBranch.perform do |setting|
+ setting.set_default_branch('online-gc-test-builder-poc')
+ setting.click_save_changes_button
+ end
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = imported_project
+ commit.branch = 'online-gc-test-builder-poc'
+ commit.commit_message = 'Update .gitlab-ci.yml'
+ commit.update_files([{
+ file_path: '.gitlab-ci.yml',
+ content: gitlab_ci_yaml
+ }])
+ end
+ end
+
+ it 'runs the online garbage collector tool', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1889' do
+ imported_project.visit!
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('test')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 3900)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry_omnibus_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry_omnibus_spec.rb
deleted file mode 100644
index 3d02c2884a2..00000000000
--- a/qa/qa/specs/features/browser_ui/5_package/container_registry_omnibus_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Package', :registry, :orchestrated, only: { pipeline: :main } do
- describe 'Self-managed Container Registry' do
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'project-with-registry'
- project.template_name = 'express'
- end
- end
-
- let!(:runner) do
- Resource::Runner.fabricate! do |runner|
- runner.name = "qa-runner-#{Time.now.to_i}"
- runner.tags = ["runner-for-#{project.name}"]
- runner.executor = :docker
- runner.project = project
- end
- end
-
- before do
- Flow::Login.sign_in
- project.visit!
- end
-
- after do
- runner.remove_via_api!
- end
-
- it "pushes image and deletes tag", testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1911' do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([{
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- build:
- image: docker:19.03.12
- stage: build
- services:
- - name: docker:19.03.12-dind
- command:
- - /bin/sh
- - -c
- - |
- apk add --no-cache openssl
- true | openssl s_client -showcerts -connect gitlab.test:5050 > /usr/local/share/ca-certificates/gitlab.test.crt
- update-ca-certificates
- dockerd-entrypoint.sh || exit
- variables:
- IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
- script:
- - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD gitlab.test:5050
- - docker build -t $IMAGE_TAG .
- - docker push $IMAGE_TAG
- tags:
- - "runner-for-#{project.name}"
- YAML
- }])
- end
-
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('build')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- Page::Project::Menu.perform(&:go_to_container_registry)
-
- Page::Project::Registry::Show.perform do |registry|
- expect(registry).to have_registry_repository(project.path_with_namespace)
-
- registry.click_on_image(project.path_with_namespace)
- expect(registry).to have_tag('master')
-
- registry.click_delete
- expect(registry).not_to have_tag('master')
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb b/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
new file mode 100644
index 00000000000..b941d5434df
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :registry, only: { pipeline: :main } do
+ describe 'Dependency Proxy' do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'dependency-proxy-project'
+ project.visibility = :private
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
+ let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" }
+ let(:dependency_proxy_url) { "#{gitlab_host_with_port}/#{project.group.full_path}/dependency_proxy/containers" }
+ let(:image_sha) { 'alpine@sha256:c3d45491770c51da4ef58318e3714da686bc7165338b7ab5ac758e75c7455efb' }
+
+ before do
+ Flow::Login.sign_in
+
+ project.group.visit!
+
+ Page::Group::Menu.perform(&:go_to_package_settings)
+
+ Page::Group::Settings::PackageRegistries.perform do |index|
+ expect(index).to have_dependency_proxy_enabled
+ end
+ end
+
+ after do
+ runner.remove_via_api!
+ end
+
+ where(:docker_client_version) do
+ %w[docker:19.03.12 docker:20.10]
+ end
+
+ with_them do
+ it "pulls an image using the dependency proxy" do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ dependency-proxy-pull-test:
+ image: "#{docker_client_version}"
+ services:
+ - name: "#{docker_client_version}-dind"
+ command: ["--insecure-registry=gitlab.test:80"]
+ before_script:
+ - apk add curl jq grep
+ - echo $CI_DEPENDENCY_PROXY_SERVER
+ - docker login -u "$CI_DEPENDENCY_PROXY_USER" -p "$CI_DEPENDENCY_PROXY_PASSWORD" gitlab.test:80
+ script:
+ - docker pull #{dependency_proxy_url}/#{image_sha}
+ - TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq --raw-output .token)
+ - 'curl --head --header "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" 2>&1'
+ - docker pull #{dependency_proxy_url}/#{image_sha}
+ - 'curl --head --header "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" 2>&1'
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ }])
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('dependency-proxy-pull-test')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ project.group.visit!
+
+ Page::Group::Menu.perform(&:go_to_dependency_proxy)
+
+ Page::Group::DependencyProxy.perform do |index|
+ expect(index).to have_blob_count("Contains 1 blobs of images")
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/dependency_proxy_spec.rb b/qa/qa/specs/features/browser_ui/5_package/dependency_proxy_spec.rb
deleted file mode 100644
index ea7f7cc1c05..00000000000
--- a/qa/qa/specs/features/browser_ui/5_package/dependency_proxy_spec.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Package', :orchestrated, :registry do
- describe 'Dependency Proxy' do
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'dependency-proxy-project'
- project.visibility = :private
- end
- end
-
- let!(:runner) do
- Resource::Runner.fabricate! do |runner|
- runner.name = "qa-runner-#{Time.now.to_i}"
- runner.tags = ["runner-for-#{project.name}"]
- runner.executor = :docker
- runner.project = project
- end
- end
-
- let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
- let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" }
- let(:dependency_proxy_url) { "#{gitlab_host_with_port}/#{project.group.full_path}/dependency_proxy/containers" }
-
- before do
- Flow::Login.sign_in
-
- project.group.visit!
-
- Page::Group::Menu.perform(&:go_to_package_settings)
-
- Page::Group::Settings::PackageRegistries.perform do |index|
- expect(index).to have_dependency_proxy_enabled
- end
- end
-
- after do
- runner.remove_via_api!
- end
-
- where(:docker_client_version) do
- %w[docker:19.03.12 docker:20.10]
- end
-
- with_them do
- it "pulls an image using the dependency proxy" do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([{
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- dependency-proxy-pull-test:
- image: "#{docker_client_version}"
- services:
- - name: "#{docker_client_version}-dind"
- command:
- - /bin/sh
- - -c
- - |
- apk add --no-cache openssl
- true | openssl s_client -showcerts -connect gitlab.test:5050 > /usr/local/share/ca-certificates/gitlab.test.crt
- update-ca-certificates
- dockerd-entrypoint.sh || exit
- before_script:
- - apk add curl jq grep
- - docker login -u "$CI_DEPENDENCY_PROXY_USER" -p "$CI_DEPENDENCY_PROXY_PASSWORD" "$CI_DEPENDENCY_PROXY_SERVER"
- script:
- - docker pull #{dependency_proxy_url}/alpine:latest
- - TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq --raw-output .token)
- - 'curl --head --header "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" 2>&1'
- - docker pull #{dependency_proxy_url}/alpine:latest
- - 'curl --head --header "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" 2>&1'
- tags:
- - "runner-for-#{project.name}"
- YAML
- }])
- end
-
- project.visit!
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('dependency-proxy-pull-test')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- project.group.visit!
-
- Page::Group::Menu.perform(&:go_to_dependency_proxy)
-
- Page::Group::DependencyProxy.perform do |index|
- expect(index).to have_blob_count("Contains 2 blobs of images")
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb
deleted file mode 100644
index 2e5fa2c2904..00000000000
--- a/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb
+++ /dev/null
@@ -1,120 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
- describe 'Generic Repository' do
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'generic-package-project'
- end
- end
-
- let(:package) do
- Resource::Package.init do |package|
- package.name = "my_package"
- package.project = project
- end
- end
-
- let!(:runner) do
- Resource::Runner.fabricate! do |runner|
- runner.name = "qa-runner-#{Time.now.to_i}"
- runner.tags = ["runner-for-#{project.name}"]
- runner.executor = :docker
- runner.project = project
- end
- end
-
- let(:gitlab_ci_yaml) do
- <<~YAML
- image: curlimages/curl:latest
-
- stages:
- - upload
- - download
-
- upload:
- stage: upload
- script:
- - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file file.txt ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my_package/0.0.1/file.txt'
- tags:
- - "runner-for-#{project.name}"
- download:
- stage: download
- script:
- - 'wget --header="JOB-TOKEN: $CI_JOB_TOKEN" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my_package/0.0.1/file.txt -O file_downloaded.txt'
- tags:
- - "runner-for-#{project.name}"
- YAML
- end
-
- let(:file_txt) do
- <<~EOF
- Hello, world!
- EOF
- end
-
- before do
- Flow::Login.sign_in
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([{
- file_path: '.gitlab-ci.yml',
- content: gitlab_ci_yaml
- },
- {
- file_path: 'file.txt',
- content: file_txt
- }]
- )
- end
-
- project.visit!
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('upload')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
-
- job.click_element(:pipeline_path)
- end
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('download')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
- end
-
- after do
- runner.remove_via_api!
- package.remove_via_api!
- end
-
- it 'uploads a generic package, downloads and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1628' do
- Page::Project::Menu.perform(&:click_packages_link)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package.name)
- index.click_package(package.name)
- end
-
- Page::Project::Packages::Show.perform(&:click_delete)
-
- Page::Project::Packages::Index.perform do |index|
- aggregate_failures 'package deletion' do
- expect(index).to have_content("Package deleted successfully")
- expect(index).to have_no_package(package.name)
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/5_package/helm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/helm_registry_spec.rb
deleted file mode 100644
index fe52fd03ad8..00000000000
--- a/qa/qa/specs/features/browser_ui/5_package/helm_registry_spec.rb
+++ /dev/null
@@ -1,150 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
- describe 'Helm Registry' do
- include Runtime::Fixtures
- include_context 'packages registry qa scenario'
-
- let(:package_name) { 'gitlab_qa_helm' }
- let(:package_version) { '1.3.7' }
- let(:package_type) { 'helm' }
-
- let(:package_gitlab_ci_file) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- deploy:
- image: alpine:3
- script:
- - apk add helm --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing
- - apk add curl
- - helm create #{package_name}
- - cp ./Chart.yaml #{package_name}
- - helm package #{package_name}
- - http_code=$(curl --write-out "%{http_code}" --request POST --form 'chart=@#{package_name}-#{package_version}.tgz' --user #{username}:#{access_token} ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/api/stable/charts --output /dev/null --silent)
- - '[ $http_code = "201" ]'
- only:
- - "#{package_project.default_branch}"
- tags:
- - "runner-for-#{package_project.group.name}"
- YAML
- }
- end
-
- let(:package_chart_yaml_file) do
- {
- file_path: "Chart.yaml",
- content:
- <<~EOF
- apiVersion: v2
- name: #{package_name}
- description: GitLab QA helm package
- type: application
- version: #{package_version}
- appVersion: "1.16.0"
- EOF
- }
- end
-
- let(:client_gitlab_ci_file) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- pull:
- image: alpine:3
- script:
- - apk add helm --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing
- - helm repo add --username #{username} --password #{access_token} gitlab_qa ${CI_API_V4_URL}/projects/#{package_project.id}/packages/helm/stable
- - helm repo update
- - helm pull gitlab_qa/#{package_name}
- only:
- - "#{client_project.default_branch}"
- tags:
- - "runner-for-#{client_project.group.name}"
- YAML
- }
- end
-
- %i[personal_access_token ci_job_token project_deploy_token].each do |authentication_token_type|
- context "using a #{authentication_token_type}" do
- let(:username) do
- case authentication_token_type
- when :personal_access_token
- Runtime::User.username
- when :ci_job_token
- 'gitlab-ci-token'
- when :project_deploy_token
- project_deploy_token.username
- end
- end
-
- let(:access_token) do
- case authentication_token_type
- when :personal_access_token
- personal_access_token
- when :ci_job_token
- '${CI_JOB_TOKEN}'
- when :project_deploy_token
- project_deploy_token.password
- end
- end
-
- it "pushes and pulls a helm chart" do
- # pushing
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = package_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([package_gitlab_ci_file, package_chart_yaml_file])
- end
-
- package_project.visit!
-
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('deploy')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- Page::Project::Menu.perform(&:click_packages_link)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package_name)
-
- index.click_package(package_name)
- end
-
- Page::Project::Packages::Show.perform do |show|
- expect(show).to have_package_info(package_name, package_version)
- end
-
- # pulling
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = client_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([client_gitlab_ci_file])
- end
-
- client_project.visit!
-
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('pull')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
deleted file mode 100644
index ec9feca84b9..00000000000
--- a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
+++ /dev/null
@@ -1,195 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
- describe 'Maven Repository with Gradle' do
- using RSpec::Parameterized::TableSyntax
- include Runtime::Fixtures
- include_context 'packages registry qa scenario'
-
- let(:group_id) { 'com.gitlab.qa' }
- let(:artifact_id) { 'maven_gradle' }
- let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') }
- let(:package_version) { '1.3.7' }
- let(:package_type) { 'maven_gradle' }
-
- let(:package_gitlab_ci_file) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- deploy:
- image: gradle:6.5-jdk11
- script:
- - 'gradle publish'
- only:
- - "#{package_project.default_branch}"
- tags:
- - "runner-for-#{package_project.group.name}"
- YAML
- }
- end
-
- let(:package_build_gradle_file) do
- {
- file_path: 'build.gradle',
- content:
- <<~EOF
- plugins {
- id 'java'
- id 'maven-publish'
- }
-
- publishing {
- publications {
- library(MavenPublication) {
- groupId '#{group_id}'
- artifactId '#{artifact_id}'
- version '#{package_version}'
- from components.java
- }
- }
- repositories {
- maven {
- url "#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/packages/maven"
- credentials(HttpHeaderCredentials) {
- name = "Private-Token"
- value = "#{personal_access_token}"
- }
- authentication {
- header(HttpHeaderAuthentication)
- }
- }
- }
- }
- EOF
- }
- end
-
- let(:client_gitlab_ci_file) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- build:
- image: gradle:6.5-jdk11
- script:
- - 'gradle build'
- only:
- - "#{client_project.default_branch}"
- tags:
- - "runner-for-#{client_project.group.name}"
- YAML
- }
- end
-
- where(:authentication_token_type, :maven_header_name) do
- :personal_access_token | 'Private-Token'
- :ci_job_token | 'Job-Token'
- :project_deploy_token | 'Deploy-Token'
- end
-
- with_them do
- let(:token) do
- case authentication_token_type
- when :personal_access_token
- "\"#{personal_access_token}\""
- when :ci_job_token
- 'System.getenv("CI_JOB_TOKEN")'
- when :project_deploy_token
- "\"#{project_deploy_token.password}\""
- end
- end
-
- let(:client_build_gradle_file) do
- {
- file_path: 'build.gradle',
- content:
- <<~EOF
- plugins {
- id 'java'
- id 'application'
- }
-
- repositories {
- jcenter()
- maven {
- url "#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/packages/maven"
- name "GitLab"
- credentials(HttpHeaderCredentials) {
- name = '#{maven_header_name}'
- value = #{token}
- }
- authentication {
- header(HttpHeaderAuthentication)
- }
- }
- }
-
- dependencies {
- implementation group: '#{group_id}', name: '#{artifact_id}', version: '#{package_version}'
- testImplementation 'junit:junit:4.12'
- }
-
- application {
- mainClassName = 'gradle_maven_app.App'
- }
- EOF
- }
- end
-
- it "pushes and pulls a maven package via gradle using #{params[:authentication_token_type]}" do
- # pushing
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = package_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([package_gitlab_ci_file, package_build_gradle_file])
- end
-
- package_project.visit!
-
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('deploy')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- Page::Project::Menu.perform(&:click_packages_link)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package_name)
-
- index.click_package(package_name)
- end
-
- Page::Project::Packages::Show.perform do |show|
- expect(show).to have_package_info(package_name, package_version)
- end
-
- # pulling
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = client_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([client_gitlab_ci_file, client_build_gradle_file])
- end
-
- client_project.visit!
-
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('build')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb
deleted file mode 100644
index bf1d2a04dba..00000000000
--- a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb
+++ /dev/null
@@ -1,340 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Package', :orchestrated, :packages, :reliable, :object_storage do
- describe 'Maven Repository' do
- include Runtime::Fixtures
-
- let(:group_id) { 'com.gitlab.qa' }
- let(:artifact_id) { "maven-#{SecureRandom.hex(8)}" }
- let(:another_artifact_id) { "maven-#{SecureRandom.hex(8)}" }
- let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') }
- let(:auth_token) do
- unless Page::Main::Menu.perform(&:signed_in?)
- Flow::Login.sign_in
- end
-
- Resource::PersonalAccessToken.fabricate!.token
- end
-
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'maven-package-project'
- end
- end
-
- let(:another_project) do
- Resource::Project.fabricate_via_api! do |another_project|
- another_project.name = 'another-maven-package-project'
- another_project.group = project.group
- end
- end
-
- let(:package) do
- Resource::Package.init do |package|
- package.name = package_name
- package.project = project
- end
- end
-
- let!(:runner) do
- Resource::Runner.fabricate! do |runner|
- runner.name = "qa-runner-#{Time.now.to_i}"
- runner.tags = ["runner-for-#{project.group.name}"]
- runner.executor = :docker
- runner.token = project.group.runners_token
- end
- end
-
- let!(:gitlab_address_with_port) do
- uri = URI.parse(Runtime::Scenario.gitlab_address)
- "#{uri.scheme}://#{uri.host}:#{uri.port}"
- end
-
- let(:pom_xml) do
- {
- file_path: 'pom.xml',
- content: <<~XML
- <project>
- <groupId>#{group_id}</groupId>
- <artifactId>#{artifact_id}</artifactId>
- <version>1.0</version>
- <modelVersion>4.0.0</modelVersion>
- <repositories>
- <repository>
- <id>#{project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/groups/#{project.group.id}/-/packages/maven</url>
- </repository>
- </repositories>
- <distributionManagement>
- <repository>
- <id>#{project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/maven</url>
- </repository>
- <snapshotRepository>
- <id>#{project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/maven</url>
- </snapshotRepository>
- </distributionManagement>
- </project>
- XML
- }
- end
-
- let(:pom_xml_another_project) do
- {
- file_path: 'pom.xml',
- content: <<~XML
- <project>
- <groupId>#{group_id}</groupId>
- <artifactId>#{another_artifact_id}</artifactId>
- <version>1.0</version>
- <modelVersion>4.0.0</modelVersion>
- <repositories>
- <repository>
- <id>#{another_project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/groups/#{another_project.group.id}/-/packages/maven</url>
- </repository>
- </repositories>
- <distributionManagement>
- <repository>
- <id>#{another_project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/projects/#{another_project.id}/packages/maven</url>
- </repository>
- <snapshotRepository>
- <id>#{another_project.name}</id>
- <url>#{gitlab_address_with_port}/api/v4/projects/#{another_project.id}/packages/maven</url>
- </snapshotRepository>
- </distributionManagement>
- <dependencies>
- <dependency>
- <groupId>#{group_id}</groupId>
- <artifactId>#{artifact_id}</artifactId>
- <version>1.0</version>
- </dependency>
- </dependencies>
- </project>
- XML
- }
- end
-
- let(:settings_xml) do
- {
- file_path: 'settings.xml',
- content: <<~XML
- <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
- <servers>
- <server>
- <id>#{project.name}</id>
- <configuration>
- <httpHeaders>
- <property>
- <name>Private-Token</name>
- <value>#{auth_token}</value>
- </property>
- </httpHeaders>
- </configuration>
- </server>
- </servers>
- </settings>
- XML
- }
- end
-
- let(:gitlab_ci_deploy_yml) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- deploy:
- image: maven:3.6-jdk-11
- script:
- - 'mvn deploy -s settings.xml'
- - "mvn dependency:get -Dartifact=#{group_id}:#{artifact_id}:1.0"
- only:
- - "#{project.default_branch}"
- tags:
- - "runner-for-#{project.group.name}"
- YAML
- }
- end
-
- let(:gitlab_ci_install_yml) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- install:
- image: maven:3.6-jdk-11
- script:
- - "mvn install"
- only:
- - "#{project.default_branch}"
- tags:
- - "runner-for-#{another_project.group.name}"
- YAML
- }
- end
-
- after do
- runner.remove_via_api!
- project.remove_via_api!
- another_project.remove_via_api!
- end
-
- it 'pushes and pulls a Maven package via CI and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1627' do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- gitlab_ci_deploy_yml,
- settings_xml,
- pom_xml
- ])
- end
-
- project.visit!
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('deploy')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = another_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- gitlab_ci_install_yml,
- pom_xml_another_project
- ])
- end
-
- another_project.visit!
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('install')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- project.visit!
-
- Page::Project::Menu.perform(&:click_packages_link)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package_name)
-
- index.click_package(package_name)
- end
-
- Page::Project::Packages::Show.perform do |show|
- expect(show).to have_package_info(package_name, "1.0")
- show.click_delete
- end
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package_name)
- end
- end
-
- context 'when "allow duplicate" setting is disabled' do
- before do
- Flow::Login.sign_in
-
- project.group.visit!
-
- Page::Group::Menu.perform(&:go_to_package_settings)
- Page::Group::Settings::PackageRegistries.perform(&:set_allow_duplicates_disabled)
- end
-
- it 'prevents users from publishing duplicate Maven packages at the group level', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1830' do
- with_fixtures([pom_xml, settings_xml]) do |dir|
- Service::DockerRun::Maven.new(dir).publish!
- end
-
- project.visit!
- Page::Project::Menu.perform(&:click_packages_link)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package_name)
- end
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = another_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- gitlab_ci_deploy_yml,
- settings_xml,
- pom_xml
- ])
- end
-
- another_project.visit!
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('deploy')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).not_to be_successful(timeout: 800)
- end
- end
- end
-
- context 'when "allow duplicate" setting is enabled' do
- before do
- Flow::Login.sign_in
-
- project.group.visit!
-
- Page::Group::Menu.perform(&:go_to_package_settings)
- Page::Group::Settings::PackageRegistries.perform(&:set_allow_duplicates_enabled)
- end
-
- it 'allows users to publish duplicate Maven packages at the group level', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1829' do
- with_fixtures([pom_xml, settings_xml]) do |dir|
- Service::DockerRun::Maven.new(dir).publish!
- end
-
- project.visit!
- Page::Project::Menu.perform(&:click_packages_link)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package_name)
- end
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = another_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- gitlab_ci_deploy_yml,
- settings_xml,
- pom_xml
- ])
- end
-
- another_project.visit!
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('deploy')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
deleted file mode 100644
index 5a3b4388f0c..00000000000
--- a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
+++ /dev/null
@@ -1,233 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Package', :orchestrated, :packages, :reliable, :object_storage do
- describe 'npm registry' do
- using RSpec::Parameterized::TableSyntax
- include Runtime::Fixtures
-
- let!(:registry_scope) { Runtime::Namespace.sandbox_name }
- let!(:personal_access_token) do
- unless Page::Main::Menu.perform(&:signed_in?)
- Flow::Login.sign_in
- end
-
- Resource::PersonalAccessToken.fabricate!.token
- end
-
- let(:project_deploy_token) do
- Resource::DeployToken.fabricate_via_browser_ui! do |deploy_token|
- deploy_token.name = 'npm-deploy-token'
- deploy_token.project = project
- end
- end
-
- let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
- let(:gitlab_address_with_port) { "#{uri.scheme}://#{uri.host}:#{uri.port}" }
- let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" }
-
- let!(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'npm-project'
- end
- end
-
- let!(:another_project) do
- Resource::Project.fabricate_via_api! do |another_project|
- another_project.name = 'npm-another-project'
- another_project.template_name = 'express'
- another_project.group = project.group
- end
- end
-
- let!(:runner) do
- Resource::Runner.fabricate! do |runner|
- runner.name = "qa-runner-#{Time.now.to_i}"
- runner.tags = ["runner-for-#{project.group.name}"]
- runner.executor = :docker
- runner.token = project.group.runners_token
- end
- end
-
- let(:gitlab_ci_deploy_yaml) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: node:14-buster
-
- stages:
- - deploy
-
- deploy:
- stage: deploy
- script:
- - npm publish
- only:
- - "#{project.default_branch}"
- tags:
- - "runner-for-#{project.group.name}"
- YAML
- }
- end
-
- let(:gitlab_ci_install_yaml) do
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: node:latest
-
- stages:
- - install
-
- install:
- stage: install
- script:
- - "npm config set @#{registry_scope}:registry #{gitlab_address_with_port}/api/v4/packages/npm/"
- - "npm install #{package.name}"
- cache:
- key: ${CI_BUILD_REF_NAME}
- paths:
- - node_modules/
- artifacts:
- paths:
- - node_modules/
- only:
- - "#{another_project.default_branch}"
- tags:
- - "runner-for-#{another_project.group.name}"
- YAML
- }
- end
-
- let(:package_json) do
- {
- file_path: 'package.json',
- content: <<~JSON
- {
- "name": "#{package.name}",
- "version": "1.0.0",
- "description": "Example package for GitLab npm registry",
- "publishConfig": {
- "@#{registry_scope}:registry": "#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/npm/"
- }
- }
- JSON
- }
- end
-
- let(:package) do
- Resource::Package.init do |package|
- package.name = "@#{registry_scope}/#{project.name}"
- package.project = project
- end
- end
-
- after do
- package.remove_via_api!
- runner.remove_via_api!
- project.remove_via_api!
- another_project.remove_via_api!
- end
-
- where(:authentication_token_type, :token_name) do
- :personal_access_token | 'Personal Access Token'
- :ci_job_token | 'CI Job Token'
- :project_deploy_token | 'Deploy Token'
- end
-
- with_them do
- let(:auth_token) do
- case authentication_token_type
- when :personal_access_token
- "\"#{personal_access_token}\""
- when :ci_job_token
- '${CI_JOB_TOKEN}'
- when :project_deploy_token
- "\"#{project_deploy_token.password}\""
- end
- end
-
- let(:npmrc) do
- {
- file_path: '.npmrc',
- content: <<~NPMRC
- //#{gitlab_host_with_port}/api/v4/projects/#{project.id}/packages/npm/:_authToken=#{auth_token}
- @#{registry_scope}:registry=#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/npm/
- NPMRC
- }
- end
-
- it "push and pull a npm package via CI using a #{params[:token_name]}", testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1772' do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- gitlab_ci_deploy_yaml,
- npmrc,
- package_json
- ])
- end
-
- project.visit!
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('deploy')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = another_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- gitlab_ci_install_yaml
- ])
- end
-
- another_project.visit!
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('install')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- job.click_browse_button
- end
-
- Page::Project::Artifact::Show.perform do |artifacts|
- artifacts.go_to_directory('node_modules')
- artifacts.go_to_directory("@#{registry_scope}")
- expect(artifacts).to have_content( "#{project.name}")
- end
-
- project.visit!
- Page::Project::Menu.perform(&:click_packages_link)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package.name)
-
- index.click_package(package.name)
- end
-
- Page::Project::Packages::Show.perform do |show|
- expect(show).to have_package_info(package.name, "1.0.0")
-
- show.click_delete
- end
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package.name)
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
deleted file mode 100644
index 8a6752ed817..00000000000
--- a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
+++ /dev/null
@@ -1,210 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
- describe 'NuGet Repository' do
- using RSpec::Parameterized::TableSyntax
- include Runtime::Fixtures
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'nuget-package-project'
- project.template_name = 'dotnetcore'
- end
- end
-
- let(:personal_access_token) do
- unless Page::Main::Menu.perform(&:signed_in?)
- Flow::Login.sign_in
- end
-
- Resource::PersonalAccessToken.fabricate!
- end
-
- let(:group_deploy_token) do
- Resource::GroupDeployToken.fabricate_via_browser_ui! do |deploy_token|
- deploy_token.name = 'nuget-group-deploy-token'
- deploy_token.group = project.group
- end
- end
-
- let(:package) do
- Resource::Package.init do |package|
- package.name = "dotnetcore-#{SecureRandom.hex(8)}"
- package.project = project
- end
- end
-
- let(:another_project) do
- Resource::Project.fabricate_via_api! do |another_project|
- another_project.name = 'nuget-package-install-project'
- another_project.template_name = 'dotnetcore'
- another_project.group = project.group
- end
- end
-
- let!(:runner) do
- Resource::Runner.fabricate! do |runner|
- runner.name = "qa-runner-#{Time.now.to_i}"
- runner.tags = ["runner-for-#{project.group.name}"]
- runner.executor = :docker
- runner.token = project.group.runners_token
- end
- end
-
- after do
- runner.remove_via_api!
- package.remove_via_api!
- end
-
- where(:authentication_token_type, :token_name) do
- :personal_access_token | 'Personal Access Token'
- :ci_job_token | 'CI Job Token'
- :group_deploy_token | 'Deploy Token'
- end
-
- with_them do
- let(:auth_token_password) do
- case authentication_token_type
- when :personal_access_token
- "\"#{personal_access_token.token}\""
- when :ci_job_token
- '${CI_JOB_TOKEN}'
- when :group_deploy_token
- "\"#{group_deploy_token.password}\""
- end
- end
-
- let(:auth_token_username) do
- case authentication_token_type
- when :personal_access_token
- "\"#{personal_access_token.user.username}\""
- when :ci_job_token
- 'gitlab-ci-token'
- when :group_deploy_token
- "\"#{group_deploy_token.username}\""
- end
- end
-
- it "publishes a nuget package at the project level, installs and deletes it at the group level using a #{params[:token_name]}", testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1073' do
- Flow::Login.sign_in
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.update_files(
- [
- {
- file_path: '.gitlab-ci.yml',
- content: <<~YAML
- image: mcr.microsoft.com/dotnet/sdk:5.0
-
- stages:
- - deploy
-
- deploy:
- stage: deploy
- script:
- - dotnet restore -p:Configuration=Release
- - dotnet build -c Release
- - dotnet pack -c Release -p:PackageID=#{package.name}
- - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username #{auth_token_username} --password #{auth_token_password} --store-password-in-clear-text
- - dotnet nuget push "bin/Release/*.nupkg" --source gitlab
- rules:
- - if: '$CI_COMMIT_BRANCH == "#{project.default_branch}"'
- tags:
- - "runner-for-#{project.group.name}"
- YAML
- }
- ]
- )
- end
-
- project.visit!
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('deploy')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- another_project.visit!
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = another_project
- commit.commit_message = 'Add new csproj file'
- commit.add_files(
- [
- {
- file_path: 'otherdotnet.csproj',
- content: <<~EOF
- <Project Sdk="Microsoft.NET.Sdk">
-
- <PropertyGroup>
- <OutputType>Exe</OutputType>
- <TargetFramework>net5.0</TargetFramework>
- </PropertyGroup>
-
- </Project>
- EOF
- }
- ]
- )
- commit.update_files(
- [
- {
- file_path: '.gitlab-ci.yml',
- content: <<~YAML
- image: mcr.microsoft.com/dotnet/sdk:5.0
-
- stages:
- - install
-
- install:
- stage: install
- script:
- - dotnet nuget locals all --clear
- - dotnet nuget add source "$CI_SERVER_URL/api/v4/groups/#{another_project.group.id}/-/packages/nuget/index.json" --name gitlab --username #{auth_token_username} --password #{auth_token_password} --store-password-in-clear-text
- - "dotnet add otherdotnet.csproj package #{package.name} --version 1.0.0"
- only:
- - "#{another_project.default_branch}"
- tags:
- - "runner-for-#{project.group.name}"
- YAML
- }
- ]
- )
- end
-
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('install')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- project.group.visit!
-
- Page::Group::Menu.perform(&:go_to_group_packages)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package.name)
- index.click_package(package.name)
- end
-
- Page::Project::Packages::Show.perform(&:click_delete)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_content('Package deleted successfully')
- expect(index).not_to have_package(package.name)
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/5_package/online_garbage_collection_spec.rb b/qa/qa/specs/features/browser_ui/5_package/online_garbage_collection_spec.rb
deleted file mode 100644
index 3ec76e8afad..00000000000
--- a/qa/qa/specs/features/browser_ui/5_package/online_garbage_collection_spec.rb
+++ /dev/null
@@ -1,108 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Package' do
- describe 'Container Registry Online Garbage Collection', :registry_gc, only: { subdomain: %i[pre] } do
- let(:group) { Resource::Group.fabricate_via_api! }
-
- let(:imported_project) do
- Resource::ProjectImportedFromURL.fabricate_via_browser_ui! do |project|
- project.name = 'container-registry'
- project.group = group
- project.gitlab_repository_path = 'https://gitlab.com/gitlab-org/container-registry.git'
- end
- end
-
- let!(:gitlab_ci_yaml) do
- <<~YAML
- variables:
- GOPATH: $CI_PROJECT_DIR/.go
- BUILD_CACHE: $CI_PROJECT_DIR/.online-gc-tester
- STAGE_ONE_VALIDATION_DELAY: "6m"
- STAGE_TWO_VALIDATION_DELAY: "12m"
- STAGE_THREE_VALIDATION_DELAY: "6m"
- STAGE_FOUR_VALIDATION_DELAY: "12m"
- STAGE_FIVE_VALIDATION_DELAY: "12m"
-
- stages:
- - generate
- - build
- - test
-
- .base: &base
- image: docker:19
- services:
- - docker:19-dind
- variables:
- DOCKER_HOST: tcp://docker:2376
- DOCKER_TLS_CERTDIR: "/certs"
- DOCKER_TLS_VERIFY: 1
- DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client"
- before_script:
- - until docker info; do sleep 1; done
- - mkdir -p $GOPATH
- - mkdir -p $BUILD_CACHE
- - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
-
- test:
- stage: generate
- extends: .base
- script:
- - apk add go make git
- - make binaries
- - ./bin/online-gc-tester generate --base-dir=$BUILD_CACHE
- - ./bin/online-gc-tester build --base-dir=$BUILD_CACHE
- - ./bin/online-gc-tester push --base-dir=$BUILD_CACHE
- - ./bin/online-gc-tester pull --base-dir=$BUILD_CACHE
- - ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=1 --delay=$STAGE_ONE_VALIDATION_DELAY
- - ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=2 --delay=$STAGE_TWO_VALIDATION_DELAY
- - ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=3 --delay=$STAGE_THREE_VALIDATION_DELAY
- - ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=4 --delay=$STAGE_FOUR_VALIDATION_DELAY
- - ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=5 --delay=$STAGE_FIVE_VALIDATION_DELAY
- timeout: 1h 30m
- YAML
- end
-
- before do
- Flow::Login.sign_in
-
- imported_project
-
- Page::Project::Menu.perform(&:go_to_repository_settings)
-
- Page::Project::Settings::Repository.perform do |setting|
- setting.expand_default_branch
- end
-
- Page::Project::Settings::DefaultBranch.perform do |setting|
- setting.set_default_branch('online-gc-test-builder-poc')
- setting.click_save_changes_button
- end
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = imported_project
- commit.branch = 'online-gc-test-builder-poc'
- commit.commit_message = 'Update .gitlab-ci.yml'
- commit.update_files([{
- file_path: '.gitlab-ci.yml',
- content: gitlab_ci_yaml
- }])
- end
- end
-
- it 'runs the online garbage collector tool', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1889' do
- imported_project.visit!
-
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('test')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 3900)
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
index 9ddf485870d..9ddf485870d 100644
--- a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
new file mode 100644
index 00000000000..126be22d760
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :packages, :object_storage, quarantine: {
+ only: { job: 'object_storage' },
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/335981',
+ type: :bug
+ } do
+ describe 'Conan Repository' do
+ include Runtime::Fixtures
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'conan-package-project'
+ end
+ end
+
+ let(:package) do
+ Resource::Package.init do |package|
+ package.name = "conantest-#{SecureRandom.hex(8)}"
+ package.project = project
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let(:gitlab_address_with_port) do
+ uri = URI.parse(Runtime::Scenario.gitlab_address)
+ "#{uri.scheme}://#{uri.host}:#{uri.port}"
+ end
+
+ after do
+ runner.remove_via_api!
+ package.remove_via_api!
+ end
+
+ it 'publishes, installs, and deletes a Conan package', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1638' do
+ Flow::Login.sign_in
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ image: conanio/gcc7
+
+ test_package:
+ stage: deploy
+ script:
+ - "conan remote add gitlab #{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/conan"
+ - "conan new #{package.name}/0.1 -t"
+ - "conan create . mycompany/stable"
+ - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package.name}/0.1@mycompany/stable --all --remote=gitlab"
+ - "conan install #{package.name}/0.1@mycompany/stable --remote=gitlab"
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ }])
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('test_package')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package.name)
+ index.click_package(package.name)
+ end
+
+ Page::Project::Packages::Show.perform(&:click_delete)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).not_to have_package(package.name)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
new file mode 100644
index 00000000000..86aca120eed
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
+ describe 'Generic Repository' do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'generic-package-project'
+ end
+ end
+
+ let(:package) do
+ Resource::Package.init do |package|
+ package.name = "my_package-#{SecureRandom.hex(8)}"
+ package.project = project
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let(:gitlab_ci_yaml) do
+ <<~YAML
+ image: curlimages/curl:latest
+
+ stages:
+ - upload
+ - download
+
+ upload:
+ stage: upload
+ script:
+ - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file file.txt ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/#{package.name}/0.0.1/file.txt'
+ tags:
+ - "runner-for-#{project.name}"
+ download:
+ stage: download
+ script:
+ - 'wget --header="JOB-TOKEN: $CI_JOB_TOKEN" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/#{package.name}/0.0.1/file.txt -O file_downloaded.txt'
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ end
+
+ let(:file_txt) do
+ <<~EOF
+ Hello, world!
+ EOF
+ end
+
+ before do
+ Flow::Login.sign_in
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content: gitlab_ci_yaml
+ },
+ {
+ file_path: 'file.txt',
+ content: file_txt
+ }]
+ )
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('upload')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+
+ job.click_element(:pipeline_path)
+ end
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('download')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+ end
+
+ after do
+ runner.remove_via_api!
+ package.remove_via_api!
+ end
+
+ it 'uploads a generic package, downloads and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1628' do
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package.name)
+ index.click_package(package.name)
+ end
+
+ Page::Project::Packages::Show.perform(&:click_delete)
+
+ Page::Project::Packages::Index.perform do |index|
+ aggregate_failures 'package deletion' do
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).to have_no_package(package.name)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb
new file mode 100644
index 00000000000..3f5e8b1a630
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb
@@ -0,0 +1,150 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
+ describe 'Helm Registry' do
+ include Runtime::Fixtures
+ include_context 'packages registry qa scenario'
+
+ let(:package_name) { "gitlab_qa_helm-#{SecureRandom.hex(8)}" }
+ let(:package_version) { '1.3.7' }
+ let(:package_type) { 'helm' }
+
+ let(:package_gitlab_ci_file) do
+ {
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ deploy:
+ image: alpine:3
+ script:
+ - apk add helm --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing
+ - apk add curl
+ - helm create #{package_name}
+ - cp ./Chart.yaml #{package_name}
+ - helm package #{package_name}
+ - http_code=$(curl --write-out "%{http_code}" --request POST --form 'chart=@#{package_name}-#{package_version}.tgz' --user #{username}:#{access_token} ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/api/stable/charts --output /dev/null --silent)
+ - '[ $http_code = "201" ]'
+ only:
+ - "#{package_project.default_branch}"
+ tags:
+ - "runner-for-#{package_project.group.name}"
+ YAML
+ }
+ end
+
+ let(:package_chart_yaml_file) do
+ {
+ file_path: "Chart.yaml",
+ content:
+ <<~EOF
+ apiVersion: v2
+ name: #{package_name}
+ description: GitLab QA helm package
+ type: application
+ version: #{package_version}
+ appVersion: "1.16.0"
+ EOF
+ }
+ end
+
+ let(:client_gitlab_ci_file) do
+ {
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ pull:
+ image: alpine:3
+ script:
+ - apk add helm --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing
+ - helm repo add --username #{username} --password #{access_token} gitlab_qa ${CI_API_V4_URL}/projects/#{package_project.id}/packages/helm/stable
+ - helm repo update
+ - helm pull gitlab_qa/#{package_name}
+ only:
+ - "#{client_project.default_branch}"
+ tags:
+ - "runner-for-#{client_project.group.name}"
+ YAML
+ }
+ end
+
+ %i[personal_access_token ci_job_token project_deploy_token].each do |authentication_token_type|
+ context "using a #{authentication_token_type}" do
+ let(:username) do
+ case authentication_token_type
+ when :personal_access_token
+ Runtime::User.username
+ when :ci_job_token
+ 'gitlab-ci-token'
+ when :project_deploy_token
+ project_deploy_token.username
+ end
+ end
+
+ let(:access_token) do
+ case authentication_token_type
+ when :personal_access_token
+ personal_access_token
+ when :ci_job_token
+ '${CI_JOB_TOKEN}'
+ when :project_deploy_token
+ project_deploy_token.password
+ end
+ end
+
+ it "pushes and pulls a helm chart" do
+ # pushing
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = package_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([package_gitlab_ci_file, package_chart_yaml_file])
+ end
+
+ package_project.visit!
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package_name)
+
+ index.click_package(package_name)
+ end
+
+ Page::Project::Packages::Show.perform do |show|
+ expect(show).to have_package_info(package_name, package_version)
+ end
+
+ # pulling
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = client_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([client_gitlab_ci_file])
+ end
+
+ client_project.visit!
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('pull')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
new file mode 100644
index 00000000000..2aa93de0b9e
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
@@ -0,0 +1,195 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
+ describe 'Maven Repository with Gradle' do
+ using RSpec::Parameterized::TableSyntax
+ include Runtime::Fixtures
+ include_context 'packages registry qa scenario'
+
+ let(:group_id) { 'com.gitlab.qa' }
+ let(:artifact_id) { "maven_gradle-#{SecureRandom.hex(8)}" }
+ let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') }
+ let(:package_version) { '1.3.7' }
+ let(:package_type) { 'maven_gradle' }
+
+ let(:package_gitlab_ci_file) do
+ {
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ deploy:
+ image: gradle:6.5-jdk11
+ script:
+ - 'gradle publish'
+ only:
+ - "#{package_project.default_branch}"
+ tags:
+ - "runner-for-#{package_project.group.name}"
+ YAML
+ }
+ end
+
+ let(:package_build_gradle_file) do
+ {
+ file_path: 'build.gradle',
+ content:
+ <<~EOF
+ plugins {
+ id 'java'
+ id 'maven-publish'
+ }
+
+ publishing {
+ publications {
+ library(MavenPublication) {
+ groupId '#{group_id}'
+ artifactId '#{artifact_id}'
+ version '#{package_version}'
+ from components.java
+ }
+ }
+ repositories {
+ maven {
+ url "#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/packages/maven"
+ credentials(HttpHeaderCredentials) {
+ name = "Private-Token"
+ value = "#{personal_access_token}"
+ }
+ authentication {
+ header(HttpHeaderAuthentication)
+ }
+ }
+ }
+ }
+ EOF
+ }
+ end
+
+ let(:client_gitlab_ci_file) do
+ {
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ build:
+ image: gradle:6.5-jdk11
+ script:
+ - 'gradle build'
+ only:
+ - "#{client_project.default_branch}"
+ tags:
+ - "runner-for-#{client_project.group.name}"
+ YAML
+ }
+ end
+
+ where(:authentication_token_type, :maven_header_name) do
+ :personal_access_token | 'Private-Token'
+ :ci_job_token | 'Job-Token'
+ :project_deploy_token | 'Deploy-Token'
+ end
+
+ with_them do
+ let(:token) do
+ case authentication_token_type
+ when :personal_access_token
+ "\"#{personal_access_token}\""
+ when :ci_job_token
+ 'System.getenv("CI_JOB_TOKEN")'
+ when :project_deploy_token
+ "\"#{project_deploy_token.password}\""
+ end
+ end
+
+ let(:client_build_gradle_file) do
+ {
+ file_path: 'build.gradle',
+ content:
+ <<~EOF
+ plugins {
+ id 'java'
+ id 'application'
+ }
+
+ repositories {
+ jcenter()
+ maven {
+ url "#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/packages/maven"
+ name "GitLab"
+ credentials(HttpHeaderCredentials) {
+ name = '#{maven_header_name}'
+ value = #{token}
+ }
+ authentication {
+ header(HttpHeaderAuthentication)
+ }
+ }
+ }
+
+ dependencies {
+ implementation group: '#{group_id}', name: '#{artifact_id}', version: '#{package_version}'
+ testImplementation 'junit:junit:4.12'
+ }
+
+ application {
+ mainClassName = 'gradle_maven_app.App'
+ }
+ EOF
+ }
+ end
+
+ it "pushes and pulls a maven package via gradle using #{params[:authentication_token_type]}" do
+ # pushing
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = package_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([package_gitlab_ci_file, package_build_gradle_file])
+ end
+
+ package_project.visit!
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package_name)
+
+ index.click_package(package_name)
+ end
+
+ Page::Project::Packages::Show.perform do |show|
+ expect(show).to have_package_info(package_name, package_version)
+ end
+
+ # pulling
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = client_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([client_gitlab_ci_file, client_build_gradle_file])
+ end
+
+ client_project.visit!
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('build')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb
new file mode 100644
index 00000000000..f42093bffcd
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb
@@ -0,0 +1,317 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
+ describe 'Maven Repository' do
+ using RSpec::Parameterized::TableSyntax
+ include Runtime::Fixtures
+ include_context 'packages registry qa scenario'
+
+ let(:group_id) { 'com.gitlab.qa' }
+ let(:artifact_id) { "maven-#{SecureRandom.hex(8)}" }
+ let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') }
+ let(:package_version) { '1.3.7' }
+ let(:package_type) { 'maven' }
+
+ let(:package_gitlab_ci_file) do
+ {
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ deploy:
+ image: maven:3.6-jdk-11
+ script:
+ - 'mvn deploy -s settings.xml'
+ only:
+ - "#{package_project.default_branch}"
+ tags:
+ - "runner-for-#{package_project.group.name}"
+ YAML
+ }
+ end
+
+ let(:package_pom_file) do
+ {
+ file_path: 'pom.xml',
+ content: <<~XML
+ <project>
+ <groupId>#{group_id}</groupId>
+ <artifactId>#{artifact_id}</artifactId>
+ <version>#{package_version}</version>
+ <modelVersion>4.0.0</modelVersion>
+ <repositories>
+ <repository>
+ <id>#{package_project.name}</id>
+ <url>#{gitlab_address_with_port}/api/v4/groups/#{package_project.group.id}/-/packages/maven</url>
+ </repository>
+ </repositories>
+ <distributionManagement>
+ <repository>
+ <id>#{package_project.name}</id>
+ <url>#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/packages/maven</url>
+ </repository>
+ <snapshotRepository>
+ <id>#{package_project.name}</id>
+ <url>#{gitlab_address_with_port}/api/v4/projects/#{package_project.id}/packages/maven</url>
+ </snapshotRepository>
+ </distributionManagement>
+ </project>
+ XML
+ }
+ end
+
+ let(:client_gitlab_ci_file) do
+ {
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ install:
+ image: maven:3.6-jdk-11
+ script:
+ - "mvn install -s settings.xml"
+ only:
+ - "#{client_project.default_branch}"
+ tags:
+ - "runner-for-#{client_project.group.name}"
+ YAML
+ }
+ end
+
+ let(:client_pom_file) do
+ {
+ file_path: 'pom.xml',
+ content: <<~XML
+ <project>
+ <groupId>#{group_id}</groupId>
+ <artifactId>maven_client</artifactId>
+ <version>1.0</version>
+ <modelVersion>4.0.0</modelVersion>
+ <repositories>
+ <repository>
+ <id>#{package_project.name}</id>
+ <url>#{gitlab_address_with_port}/api/v4/groups/#{package_project.group.id}/-/packages/maven</url>
+ </repository>
+ </repositories>
+ <dependencies>
+ <dependency>
+ <groupId>#{group_id}</groupId>
+ <artifactId>#{artifact_id}</artifactId>
+ <version>#{package_version}</version>
+ </dependency>
+ </dependencies>
+ </project>
+ XML
+ }
+ end
+
+ let(:settings_xml_with_pat) do
+ {
+ file_path: 'settings.xml',
+ content: <<~XML
+ <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
+ <servers>
+ <server>
+ <id>#{package_project.name}</id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>Private-Token</name>
+ <value>#{personal_access_token}</value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+ </settings>
+ XML
+ }
+ end
+
+ where(:authentication_token_type, :maven_header_name) do
+ :personal_access_token | 'Private-Token'
+ :ci_job_token | 'Job-Token'
+ :project_deploy_token | 'Deploy-Token'
+ end
+
+ with_them do
+ let(:token) do
+ case authentication_token_type
+ when :personal_access_token
+ personal_access_token
+ when :ci_job_token
+ '${env.CI_JOB_TOKEN}'
+ when :project_deploy_token
+ project_deploy_token.password
+ end
+ end
+
+ let(:settings_xml) do
+ {
+ file_path: 'settings.xml',
+ content: <<~XML
+ <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
+ <servers>
+ <server>
+ <id>#{package_project.name}</id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>#{maven_header_name}</name>
+ <value>#{token}</value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+ </settings>
+ XML
+ }
+ end
+
+ it "pushes and pulls a maven package via maven using #{params[:authentication_token_type]}" do
+ # pushing
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = package_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ package_gitlab_ci_file,
+ package_pom_file,
+ settings_xml
+ ])
+ end
+
+ package_project.visit!
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package_name)
+
+ index.click_package(package_name)
+ end
+
+ Page::Project::Packages::Show.perform do |show|
+ expect(show).to have_package_info(package_name, package_version)
+ end
+
+ # pulling
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = client_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ client_gitlab_ci_file,
+ client_pom_file,
+ settings_xml
+ ])
+ end
+
+ client_project.visit!
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('install')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+ end
+
+ context 'duplication setting' do
+ before do
+ package_project.group.visit!
+
+ Page::Group::Menu.perform(&:go_to_package_settings)
+ end
+
+ context 'when disabled' do
+ before do
+ Page::Group::Settings::PackageRegistries.perform(&:set_allow_duplicates_disabled)
+ end
+
+ it "prevents users from publishing group level Maven packages duplicates using #{params[:authentication_token_type]}" do
+ create_duplicated_package
+
+ push_duplicated_package
+
+ client_project.visit!
+
+ show_latest_deploy_job
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).not_to be_successful(timeout: 800)
+ end
+ end
+ end
+
+ context 'when enabled' do
+ before do
+ Page::Group::Settings::PackageRegistries.perform(&:set_allow_duplicates_enabled)
+ end
+
+ it "allows users to publish group level Maven packages duplicates using #{params[:authentication_token_type]}" do
+ create_duplicated_package
+
+ push_duplicated_package
+
+ show_latest_deploy_job
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+ end
+ end
+
+ def create_duplicated_package
+ with_fixtures([package_pom_file, settings_xml_with_pat]) do |dir|
+ Service::DockerRun::Maven.new(dir).publish!
+ end
+
+ package_project.visit!
+
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package_name)
+ end
+ end
+
+ def push_duplicated_package
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = client_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ package_gitlab_ci_file,
+ package_pom_file,
+ settings_xml
+ ])
+ end
+ end
+
+ def show_latest_deploy_job
+ client_project.visit!
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
new file mode 100644
index 00000000000..f2b1c1b01a0
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
@@ -0,0 +1,228 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package Registry', :orchestrated, :packages, :reliable, :object_storage do
+ describe 'npm instance level endpoint' do
+ using RSpec::Parameterized::TableSyntax
+ include Runtime::Fixtures
+
+ let!(:registry_scope) { Runtime::Namespace.sandbox_name }
+ let!(:personal_access_token) do
+ unless Page::Main::Menu.perform(&:signed_in?)
+ Flow::Login.sign_in
+ end
+
+ Resource::PersonalAccessToken.fabricate!.token
+ end
+
+ let(:project_deploy_token) do
+ Resource::DeployToken.fabricate_via_browser_ui! do |deploy_token|
+ deploy_token.name = 'npm-deploy-token'
+ deploy_token.project = project
+ deploy_token.scopes = [
+ :read_repository,
+ :read_package_registry,
+ :write_package_registry
+ ]
+ end
+ end
+
+ let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
+ let(:gitlab_address_with_port) { "#{uri.scheme}://#{uri.host}:#{uri.port}" }
+ let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" }
+
+ let!(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'npm-instace-level-publish'
+ end
+ end
+
+ let!(:another_project) do
+ Resource::Project.fabricate_via_api! do |another_project|
+ another_project.name = 'npm-instance-level-install'
+ another_project.template_name = 'express'
+ another_project.group = project.group
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.group.name}"]
+ runner.executor = :docker
+ runner.token = project.group.runners_token
+ end
+ end
+
+ let(:gitlab_ci_deploy_yaml) do
+ {
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ image: node:latest
+
+ stages:
+ - deploy
+
+ deploy:
+ stage: deploy
+ script:
+ - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=#{auth_token}">.npmrc
+ - npm publish
+ only:
+ - "#{project.default_branch}"
+ tags:
+ - "runner-for-#{project.group.name}"
+ YAML
+ }
+ end
+
+ let(:gitlab_ci_install_yaml) do
+ {
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ image: node:latest
+
+ stages:
+ - install
+
+ install:
+ stage: install
+ script:
+ - "npm config set @#{registry_scope}:registry #{gitlab_address_with_port}/api/v4/packages/npm/"
+ - "npm install #{package.name}"
+ cache:
+ key: ${CI_BUILD_REF_NAME}
+ paths:
+ - node_modules/
+ artifacts:
+ paths:
+ - node_modules/
+ only:
+ - "#{another_project.default_branch}"
+ tags:
+ - "runner-for-#{another_project.group.name}"
+ YAML
+ }
+ end
+
+ let(:package_json) do
+ {
+ file_path: 'package.json',
+ content: <<~JSON
+ {
+ "name": "#{package.name}",
+ "version": "1.0.0",
+ "description": "Example package for GitLab npm registry",
+ "publishConfig": {
+ "@#{registry_scope}:registry": "#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/npm/"
+ }
+ }
+ JSON
+ }
+ end
+
+ let(:package) do
+ Resource::Package.init do |package|
+ package.name = "@#{registry_scope}/#{project.name}-#{SecureRandom.hex(8)}"
+ package.project = project
+ end
+ end
+
+ after do
+ package.remove_via_api!
+ runner.remove_via_api!
+ project.remove_via_api!
+ another_project.remove_via_api!
+ end
+
+ where(:authentication_token_type, :token_name) do
+ :personal_access_token | 'Personal Access Token'
+ :ci_job_token | 'CI Job Token'
+ :project_deploy_token | 'Deploy Token'
+ end
+
+ with_them do
+ let(:auth_token) do
+ case authentication_token_type
+ when :personal_access_token
+ "\"#{personal_access_token}\""
+ when :ci_job_token
+ '${CI_JOB_TOKEN}'
+ when :project_deploy_token
+ "\"#{project_deploy_token.password}\""
+ end
+ end
+
+ it "push and pull a npm package via CI using a #{params[:token_name]}" do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ gitlab_ci_deploy_yaml,
+ package_json
+ ])
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = another_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ gitlab_ci_install_yaml
+ ])
+ end
+
+ another_project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('install')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ job.click_browse_button
+ end
+
+ Page::Project::Artifact::Show.perform do |artifacts|
+ artifacts.go_to_directory('node_modules')
+ artifacts.go_to_directory("@#{registry_scope}")
+ expect(artifacts).to have_content( "#{project.name}")
+ end
+
+ project.visit!
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package.name)
+
+ index.click_package(package.name)
+ end
+
+ Page::Project::Packages::Show.perform do |show|
+ expect(show).to have_package_info(package.name, "1.0.0")
+
+ show.click_delete
+ end
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).not_to have_package(package.name)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
new file mode 100644
index 00000000000..832f8c7f72c
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
@@ -0,0 +1,197 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package Registry', :orchestrated, :packages, :reliable, :object_storage do
+ describe 'npm project level endpoint' do
+ using RSpec::Parameterized::TableSyntax
+ include Runtime::Fixtures
+
+ let!(:registry_scope) { Runtime::Namespace.sandbox_name }
+ let!(:personal_access_token) do
+ unless Page::Main::Menu.perform(&:signed_in?)
+ Flow::Login.sign_in
+ end
+
+ Resource::PersonalAccessToken.fabricate!.token
+ end
+
+ let(:project_deploy_token) do
+ Resource::DeployToken.fabricate_via_browser_ui! do |deploy_token|
+ deploy_token.name = 'npm-deploy-token'
+ deploy_token.project = project
+ deploy_token.scopes = [
+ :read_repository,
+ :read_package_registry,
+ :write_package_registry
+ ]
+ end
+ end
+
+ let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
+ let(:gitlab_address_with_port) { "#{uri.scheme}://#{uri.host}:#{uri.port}" }
+ let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" }
+
+ let!(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'npm-project-level'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let(:gitlab_ci_yaml) do
+ {
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ image: node:latest
+
+ stages:
+ - deploy
+ - install
+
+ deploy:
+ stage: deploy
+ script:
+ - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=#{auth_token}">.npmrc
+ - npm publish
+ only:
+ - "#{project.default_branch}"
+ tags:
+ - "runner-for-#{project.name}"
+ install:
+ stage: install
+ script:
+ - "npm config set @#{registry_scope}:registry #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/"
+ - "npm install #{package.name}"
+ cache:
+ key: ${CI_BUILD_REF_NAME}
+ paths:
+ - node_modules/
+ artifacts:
+ paths:
+ - node_modules/
+ only:
+ - "#{project.default_branch}"
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ }
+ end
+
+ let(:package_json) do
+ {
+ file_path: 'package.json',
+ content: <<~JSON
+ {
+ "name": "@#{registry_scope}/mypackage",
+ "version": "1.0.0",
+ "description": "Example package for GitLab npm registry",
+ "publishConfig": {
+ "@#{registry_scope}:registry": "#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/npm/"
+ }
+ }
+ JSON
+ }
+ end
+
+ let(:package) do
+ Resource::Package.init do |package|
+ package.name = "@#{registry_scope}/mypackage-#{SecureRandom.hex(8)}"
+ package.project = project
+ end
+ end
+
+ after do
+ package.remove_via_api!
+ runner.remove_via_api!
+ project.remove_via_api!
+ end
+
+ where(:authentication_token_type, :token_name) do
+ :personal_access_token | 'Personal Access Token'
+ :ci_job_token | 'CI Job Token'
+ :project_deploy_token | 'Deploy Token'
+ end
+
+ with_them do
+ let(:auth_token) do
+ case authentication_token_type
+ when :personal_access_token
+ "\"#{personal_access_token}\""
+ when :ci_job_token
+ '${CI_JOB_TOKEN}'
+ when :project_deploy_token
+ "\"#{project_deploy_token.password}\""
+ end
+ end
+
+ it "push and pull a npm package via CI using a #{params[:token_name]}", quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/344537', type: :investigating } do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ gitlab_ci_yaml,
+ package_json
+ ])
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('install')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ job.click_browse_button
+ end
+
+ Page::Project::Artifact::Show.perform do |artifacts|
+ artifacts.go_to_directory('node_modules')
+ artifacts.go_to_directory("@#{registry_scope}")
+ expect(artifacts).to have_content("mypackage")
+ end
+
+ project.visit!
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package.name)
+
+ index.click_package(package.name)
+ end
+
+ Page::Project::Packages::Show.perform do |show|
+ expect(show).to have_package_info(package.name, "1.0.0")
+
+ show.click_delete
+ end
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).not_to have_package(package.name)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb
new file mode 100644
index 00000000000..0b4825715c1
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb
@@ -0,0 +1,210 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
+ describe 'NuGet Repository' do
+ using RSpec::Parameterized::TableSyntax
+ include Runtime::Fixtures
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'nuget-package-project'
+ project.template_name = 'dotnetcore'
+ end
+ end
+
+ let(:personal_access_token) do
+ unless Page::Main::Menu.perform(&:signed_in?)
+ Flow::Login.sign_in
+ end
+
+ Resource::PersonalAccessToken.fabricate!
+ end
+
+ let(:group_deploy_token) do
+ Resource::GroupDeployToken.fabricate_via_browser_ui! do |deploy_token|
+ deploy_token.name = 'nuget-group-deploy-token'
+ deploy_token.group = project.group
+ end
+ end
+
+ let(:package) do
+ Resource::Package.init do |package|
+ package.name = "dotnetcore-#{SecureRandom.hex(8)}"
+ package.project = project
+ end
+ end
+
+ let(:another_project) do
+ Resource::Project.fabricate_via_api! do |another_project|
+ another_project.name = 'nuget-package-install-project'
+ another_project.template_name = 'dotnetcore'
+ another_project.group = project.group
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.group.name}"]
+ runner.executor = :docker
+ runner.token = project.group.runners_token
+ end
+ end
+
+ after do
+ runner.remove_via_api!
+ package.remove_via_api!
+ end
+
+ where(:authentication_token_type, :token_name) do
+ :personal_access_token | 'Personal Access Token'
+ :ci_job_token | 'CI Job Token'
+ :group_deploy_token | 'Deploy Token'
+ end
+
+ with_them do
+ let(:auth_token_password) do
+ case authentication_token_type
+ when :personal_access_token
+ "\"#{personal_access_token.token}\""
+ when :ci_job_token
+ '${CI_JOB_TOKEN}'
+ when :group_deploy_token
+ "\"#{group_deploy_token.password}\""
+ end
+ end
+
+ let(:auth_token_username) do
+ case authentication_token_type
+ when :personal_access_token
+ "\"#{personal_access_token.user.username}\""
+ when :ci_job_token
+ 'gitlab-ci-token'
+ when :group_deploy_token
+ "\"#{group_deploy_token.username}\""
+ end
+ end
+
+ it "publishes a nuget package at the project level, installs and deletes it at the group level using a #{params[:token_name]}" do
+ Flow::Login.sign_in
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.update_files(
+ [
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ image: mcr.microsoft.com/dotnet/sdk:5.0
+
+ stages:
+ - deploy
+
+ deploy:
+ stage: deploy
+ script:
+ - dotnet restore -p:Configuration=Release
+ - dotnet build -c Release
+ - dotnet pack -c Release -p:PackageID=#{package.name}
+ - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username #{auth_token_username} --password #{auth_token_password} --store-password-in-clear-text
+ - dotnet nuget push "bin/Release/*.nupkg" --source gitlab
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "#{project.default_branch}"'
+ tags:
+ - "runner-for-#{project.group.name}"
+ YAML
+ }
+ ]
+ )
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('deploy')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ another_project.visit!
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = another_project
+ commit.commit_message = 'Add new csproj file'
+ commit.add_files(
+ [
+ {
+ file_path: 'otherdotnet.csproj',
+ content: <<~EOF
+ <Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net5.0</TargetFramework>
+ </PropertyGroup>
+
+ </Project>
+ EOF
+ }
+ ]
+ )
+ commit.update_files(
+ [
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ image: mcr.microsoft.com/dotnet/sdk:5.0
+
+ stages:
+ - install
+
+ install:
+ stage: install
+ script:
+ - dotnet nuget locals all --clear
+ - dotnet nuget add source "$CI_SERVER_URL/api/v4/groups/#{another_project.group.id}/-/packages/nuget/index.json" --name gitlab --username #{auth_token_username} --password #{auth_token_password} --store-password-in-clear-text
+ - "dotnet add otherdotnet.csproj package #{package.name} --version 1.0.0"
+ only:
+ - "#{another_project.default_branch}"
+ tags:
+ - "runner-for-#{project.group.name}"
+ YAML
+ }
+ ]
+ )
+ end
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('install')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ project.group.visit!
+
+ Page::Group::Menu.perform(&:go_to_group_packages)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package.name)
+ index.click_package(package.name)
+ end
+
+ Page::Project::Packages::Show.perform(&:click_delete)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_content('Package deleted successfully')
+ expect(index).not_to have_package(package.name)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
new file mode 100644
index 00000000000..e727a89a584
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
@@ -0,0 +1,166 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
+ describe 'PyPI Repository' do
+ include Runtime::Fixtures
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'pypi-package-project'
+ end
+ end
+
+ let(:package) do
+ Resource::Package.init do |package|
+ package.name = "mypypipackage-#{SecureRandom.hex(8)}"
+ package.project = project
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
+ let(:gitlab_address_with_port) { "#{uri.scheme}://#{uri.host}:#{uri.port}" }
+ let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" }
+ let(:personal_access_token) { Runtime::Env.personal_access_token }
+
+ before do
+ Flow::Login.sign_in
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ image: python:latest
+ stages:
+ - run
+ - install
+
+ run:
+ stage: run
+ script:
+ - pip install twine
+ - python setup.py sdist bdist_wheel
+ - "TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python -m twine upload --repository-url #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi dist/*"
+ tags:
+ - "runner-for-#{project.name}"
+ install:
+ stage: install
+ script:
+ - "pip install #{package.name} --no-deps --index-url #{uri.scheme}://#{personal_access_token}:#{personal_access_token}@#{gitlab_host_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host #{gitlab_host_with_port}"
+ tags:
+ - "runner-for-#{project.name}"
+
+ YAML
+ },
+ {
+ file_path: 'setup.py',
+ content:
+ <<~EOF
+ import setuptools
+
+ setuptools.setup(
+ name="#{package.name}",
+ version="0.0.1",
+ author="Example Author",
+ author_email="author@example.com",
+ description="A small example package",
+ packages=setuptools.find_packages(),
+ classifiers=[
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+ ],
+ python_requires='>=3.6',
+ )
+ EOF
+
+ }])
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('run')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('install')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+ end
+
+ after do
+ runner.remove_via_api!
+ package.remove_via_api!
+ project&.remove_via_api!
+ end
+
+ context 'when at the project level' do
+ it 'publishes and installs a pypi package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1635' do
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package.name)
+ index.click_package(package.name)
+ end
+
+ Page::Project::Packages::Show.perform(&:click_delete)
+
+ Page::Project::Packages::Index.perform do |index|
+ aggregate_failures do
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).not_to have_package(package.name)
+ end
+ end
+ end
+ end
+
+ context 'Geo', :orchestrated, :geo do
+ it 'replicates a published pypi package to the Geo secondary site', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1219', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/325556', type: :investigating } do
+ QA::Runtime::Logger.debug('Visiting the secondary Geo site')
+
+ QA::Flow::Login.while_signed_in(address: :geo_secondary) do
+ EE::Page::Main::Banner.perform do |banner|
+ expect(banner).to have_secondary_read_only_banner
+ end
+
+ Page::Main::Menu.perform(&:go_to_projects)
+
+ Page::Dashboard::Projects.perform do |dashboard|
+ dashboard.wait_for_project_replication(project.name)
+ dashboard.go_to_project(project.name)
+ end
+
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ index.wait_for_package_replication(package.name)
+ expect(index).to have_package(package.name)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
new file mode 100644
index 00000000000..ecf14a25b8d
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
@@ -0,0 +1,163 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Package', :orchestrated, :requires_admin, :packages, :object_storage do
+ describe 'RubyGems Repository' do
+ include Runtime::Fixtures
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'rubygems-package-project'
+ end
+ end
+
+ let(:package) do
+ Resource::Package.init do |package|
+ package.name = "mygem-#{SecureRandom.hex(8)}"
+ package.project = project
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{project.name}"]
+ runner.executor = :docker
+ runner.project = project
+ end
+ end
+
+ let(:gitlab_address_with_port) do
+ uri = URI.parse(Runtime::Scenario.gitlab_address)
+ "#{uri.scheme}://#{uri.host}:#{uri.port}"
+ end
+
+ before do
+ Runtime::Feature.enable(:rubygem_packages, project: project)
+ end
+
+ after do
+ Runtime::Feature.disable(:rubygem_packages, project: project)
+ runner.remove_via_api!
+ package.remove_via_api!
+ project.remove_via_api!
+ end
+
+ it 'publishes and deletes a Ruby gem', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1906' do
+ Flow::Login.sign_in
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add package files'
+ commit.add_files(
+ [
+ {
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ image: ruby
+
+ test_package:
+ stage: deploy
+ before_script:
+ - mkdir ~/.gem
+ - echo "---" > ~/.gem/credentials
+ - |
+ echo "#{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems: '${CI_JOB_TOKEN}'" >> ~/.gem/credentials
+ - chmod 0600 ~/.gem/credentials
+ script:
+ - gem build #{package.name}
+ - gem push #{package.name}-0.0.1.gem --host #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ },
+ {
+ file_path: 'lib/hello_gem.rb',
+ content:
+ <<~RUBY
+ class HelloWorld
+ def self.hi
+ puts "Hello world!"
+ end
+ end
+ RUBY
+ },
+ {
+ file_path: "#{package.name}.gemspec",
+ content:
+ <<~RUBY
+ # frozen_string_literal: true
+
+ Gem::Specification.new do |s|
+ s.name = '#{package.name}'
+ s.authors = ['Tanuki Steve', 'Hal 9000']
+ s.author = 'Tanuki Steve'
+ s.version = '0.0.1'
+ s.date = '2011-09-29'
+ s.summary = 'this is a test package'
+ s.files = ['lib/hello_gem.rb']
+ s.require_paths = ['lib']
+
+ s.description = 'A test package for GitLab.'
+ s.email = 'tanuki@not_real.com'
+ s.homepage = 'https://gitlab.com/ruby-co/my-package'
+ s.license = 'MIT'
+
+ s.metadata = {
+ 'bug_tracker_uri' => 'https://gitlab.com/ruby-co/my-package/issues',
+ 'changelog_uri' => 'https://gitlab.com/ruby-co/my-package/CHANGELOG.md',
+ 'documentation_uri' => 'https://gitlab.com/ruby-co/my-package/docs',
+ 'mailing_list_uri' => 'https://gitlab.com/ruby-co/my-package/mailme',
+ 'source_code_uri' => 'https://gitlab.com/ruby-co/my-package'
+ }
+
+ s.bindir = 'bin'
+ s.platform = Gem::Platform::RUBY
+ s.post_install_message = 'Installed, thank you!'
+ s.rdoc_options = ['--main']
+ s.required_ruby_version = '>= 2.7.0'
+ s.required_rubygems_version = '>= 1.8.11'
+ s.requirements = 'A high powered server or calculator'
+ s.rubygems_version = '1.8.09'
+
+ s.add_dependency 'dependency_1', '~> 1.2.3'
+ s.add_dependency 'dependency_2', '3.0.0'
+ s.add_dependency 'dependency_3', '>= 1.0.0'
+ s.add_dependency 'dependency_4'
+ end
+
+ RUBY
+ }
+ ]
+ )
+ end
+
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('test_package')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Page::Project::Menu.perform(&:click_packages_link)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_package(package.name)
+ index.click_package(package.name)
+ end
+
+ Page::Project::Packages::Show.perform(&:click_delete)
+
+ Page::Project::Packages::Index.perform do |index|
+ expect(index).to have_content("Package deleted successfully")
+ expect(index).not_to have_package(package.name)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb
deleted file mode 100644
index dfc9202ebed..00000000000
--- a/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb
+++ /dev/null
@@ -1,166 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Package', :orchestrated, :packages, :object_storage do
- describe 'PyPI Repository' do
- include Runtime::Fixtures
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'pypi-package-project'
- end
- end
-
- let(:package) do
- Resource::Package.init do |package|
- package.name = 'mypypipackage'
- package.project = project
- end
- end
-
- let!(:runner) do
- Resource::Runner.fabricate! do |runner|
- runner.name = "qa-runner-#{Time.now.to_i}"
- runner.tags = ["runner-for-#{project.name}"]
- runner.executor = :docker
- runner.project = project
- end
- end
-
- let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
- let(:gitlab_address_with_port) { "#{uri.scheme}://#{uri.host}:#{uri.port}" }
- let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" }
- let(:personal_access_token) { Runtime::Env.personal_access_token }
-
- before do
- Flow::Login.sign_in
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([{
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: python:latest
- stages:
- - run
- - install
-
- run:
- stage: run
- script:
- - pip install twine
- - python setup.py sdist bdist_wheel
- - "TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python -m twine upload --repository-url #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi dist/*"
- tags:
- - "runner-for-#{project.name}"
- install:
- stage: install
- script:
- - "pip install mypypipackage --no-deps --index-url #{uri.scheme}://#{personal_access_token}:#{personal_access_token}@#{gitlab_host_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host #{gitlab_host_with_port}"
- tags:
- - "runner-for-#{project.name}"
-
- YAML
- },
- {
- file_path: 'setup.py',
- content:
- <<~EOF
- import setuptools
-
- setuptools.setup(
- name="mypypipackage",
- version="0.0.1",
- author="Example Author",
- author_email="author@example.com",
- description="A small example package",
- packages=setuptools.find_packages(),
- classifiers=[
- "Programming Language :: Python :: 3",
- "License :: OSI Approved :: MIT License",
- "Operating System :: OS Independent",
- ],
- python_requires='>=3.6',
- )
- EOF
-
- }])
- end
-
- project.visit!
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('run')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('install')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
- end
-
- after do
- runner.remove_via_api!
- package.remove_via_api!
- project&.remove_via_api!
- end
-
- context 'when at the project level' do
- it 'publishes and installs a pypi package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1635' do
- Page::Project::Menu.perform(&:click_packages_link)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package.name)
- index.click_package(package.name)
- end
-
- Page::Project::Packages::Show.perform(&:click_delete)
-
- Page::Project::Packages::Index.perform do |index|
- aggregate_failures do
- expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package.name)
- end
- end
- end
- end
-
- context 'Geo', :orchestrated, :geo do
- it 'replicates a published pypi package to the Geo secondary site', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1219', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/325556', type: :investigating } do
- QA::Runtime::Logger.debug('Visiting the secondary Geo site')
-
- QA::Flow::Login.while_signed_in(address: :geo_secondary) do
- EE::Page::Main::Banner.perform do |banner|
- expect(banner).to have_secondary_read_only_banner
- end
-
- Page::Main::Menu.perform(&:go_to_projects)
-
- Page::Dashboard::Projects.perform do |dashboard|
- dashboard.wait_for_project_replication(project.name)
- dashboard.go_to_project(project.name)
- end
-
- Page::Project::Menu.perform(&:click_packages_link)
-
- Page::Project::Packages::Index.perform do |index|
- index.wait_for_package_replication(package.name)
- expect(index).to have_package(package.name)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/5_package/rubygems_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/rubygems_registry_spec.rb
deleted file mode 100644
index 9a45b072eed..00000000000
--- a/qa/qa/specs/features/browser_ui/5_package/rubygems_registry_spec.rb
+++ /dev/null
@@ -1,125 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Package', :orchestrated, :requires_admin, :packages, :object_storage do
- describe 'RubyGems Repository' do
- include Runtime::Fixtures
-
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'rubygems-package-project'
- end
- end
-
- let(:package) do
- Resource::Package.init do |package|
- package.name = 'mygem'
- package.project = project
- end
- end
-
- let!(:runner) do
- Resource::Runner.fabricate! do |runner|
- runner.name = "qa-runner-#{Time.now.to_i}"
- runner.tags = ["runner-for-#{project.name}"]
- runner.executor = :docker
- runner.project = project
- end
- end
-
- let(:gitlab_address_with_port) do
- uri = URI.parse(Runtime::Scenario.gitlab_address)
- "#{uri.scheme}://#{uri.host}:#{uri.port}"
- end
-
- before do
- Runtime::Feature.enable(:rubygem_packages, project: project)
- end
-
- after do
- Runtime::Feature.disable(:rubygem_packages, project: project)
- runner.remove_via_api!
- package.remove_via_api!
- project.remove_via_api!
- end
-
- it 'publishes and deletes a Ruby gem', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1906' do
- Flow::Login.sign_in
-
- Resource::Repository::ProjectPush.fabricate! do |push|
- push.project = project
- push.directory = Pathname
- .new(__dir__)
- .join('../../../../fixtures/rubygems_package')
- push.commit_message = 'RubyGems package'
- end
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add mygem.gemspec'
- commit.add_files(
- [
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: ruby
-
- test_package:
- stage: deploy
- before_script:
- - mkdir ~/.gem
- - echo "---" > ~/.gem/credentials
- - |
- echo "#{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems: '${CI_JOB_TOKEN}'" >> ~/.gem/credentials
- - chmod 0600 ~/.gem/credentials
- script:
- - gem build mygem
- - gem push mygem-0.0.1.gem --host #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems
- tags:
- - "runner-for-#{project.name}"
- YAML
- },
- {
- file_path: 'lib/hello_gem.rb',
- content:
- <<~RUBY
- class HelloWorld
- def self.hi
- puts "Hello world!"
- end
- end
- RUBY
- }
- ]
- )
- end
-
- project.visit!
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('test_package')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- Page::Project::Menu.perform(&:click_packages_link)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package.name)
- index.click_package(package.name)
- end
-
- Page::Project::Packages::Show.perform(&:click_delete)
-
- Page::Project::Packages::Index.perform do |index|
- expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package.name)
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
index 23625ab645d..81ccc585cf9 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
@@ -12,6 +12,7 @@ module QA
deploy_token = Resource::DeployToken.fabricate_via_browser_ui! do |resource|
resource.name = deploy_token_name
resource.expires_at = one_week_from_now
+ resource.scopes = [:read_repository]
end
expect(deploy_token.username.length).to be > 0
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index 655c806a37a..e20b76f6bf8 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Configure' do
+ RSpec.describe 'Configure', only: { subdomain: :staging } do
let(:project) do
Resource::Project.fabricate_via_api! do |project|
- project.name = Runtime::Env.auto_devops_project_name || 'autodevops-project'
+ project.name = 'autodevops-project'
project.auto_devops_enabled = true
end
end
@@ -13,35 +13,24 @@ module QA
disable_optional_jobs(project)
end
- describe 'Auto DevOps support', :orchestrated, :kubernetes, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/251090', type: :stale } do
+ describe 'Auto DevOps support' do
context 'when rbac is enabled' do
let(:cluster) { Service::KubernetesCluster.new.create! }
after do
cluster&.remove!
+ project.remove_via_api!
end
it 'runs auto devops', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1422' do
Flow::Login.sign_in
- # Set an application secret CI variable (prefixed with K8S_SECRET_)
- Resource::CiVariable.fabricate! do |resource|
- resource.project = project
- resource.key = 'K8S_SECRET_OPTIONAL_MESSAGE'
- resource.value = 'you_can_see_this_variable'
- resource.masked = false
- end
-
- # Connect K8s cluster
Resource::KubernetesCluster::ProjectCluster.fabricate! do |k8s_cluster|
k8s_cluster.project = project
k8s_cluster.cluster = cluster
k8s_cluster.install_ingress = true
- k8s_cluster.install_prometheus = true
- k8s_cluster.install_runner = true
end
- # Create Auto DevOps compatible repo
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.directory = Pathname
@@ -78,46 +67,6 @@ module QA
job.click_element(:pipeline_path)
end
-
- Page::Project::Menu.perform(&:go_to_deployments_environments)
- Page::Project::Deployments::Environments::Index.perform do |index|
- index.click_environment_link('production')
- end
- Page::Project::Deployments::Environments::Show.perform do |show|
- show.view_deployment do
- expect(page).to have_content('Hello World!')
- expect(page).to have_content('you_can_see_this_variable')
- end
- end
- end
- end
- end
-
- describe 'Auto DevOps', :smoke do
- before do
- Flow::Login.sign_in
-
- project.visit!
-
- Page::Project::Menu.perform(&:go_to_ci_cd_settings)
- Page::Project::Settings::CiCd.perform(&:expand_auto_devops)
- Page::Project::Settings::AutoDevops.perform(&:enable_autodevops)
-
- # Create AutoDevOps repo
- Resource::Repository::ProjectPush.fabricate! do |push|
- push.project = project
- push.directory = Pathname
- .new(__dir__)
- .join('../../../../../fixtures/auto_devops_rack')
- push.commit_message = 'Create AutoDevOps compatible Project'
- end
- end
-
- it 'runs an AutoDevOps pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1564' do
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- expect(pipeline).to have_tag('Auto DevOps')
end
end
end
@@ -128,7 +77,8 @@ module QA
%w[
CODE_QUALITY_DISABLED LICENSE_MANAGEMENT_DISABLED
SAST_DISABLED DAST_DISABLED DEPENDENCY_SCANNING_DISABLED
- CONTAINER_SCANNING_DISABLED
+ CONTAINER_SCANNING_DISABLED BROWSER_PERFORMANCE_DISABLED
+ SECRET_DETECTION_DISABLED
].each do |key|
Resource::CiVariable.fabricate_via_api! do |resource|
resource.project = project
diff --git a/qa/qa/specs/helpers/context_selector.rb b/qa/qa/specs/helpers/context_selector.rb
index 57665babf68..9ac79ad6196 100644
--- a/qa/qa/specs/helpers/context_selector.rb
+++ b/qa/qa/specs/helpers/context_selector.rb
@@ -45,11 +45,11 @@ module QA
opts[:subdomain] = case option[:subdomain]
when Array
- "(#{option[:subdomain].join("|")})."
+ "(#{option[:subdomain].join("|")})\\."
when Regexp
option[:subdomain]
else
- "(#{option[:subdomain]})."
+ "(#{option[:subdomain]})\\."
end
end
end
diff --git a/qa/qa/support/fabrication_tracker.rb b/qa/qa/support/fabrication_tracker.rb
new file mode 100644
index 00000000000..3238cc5b0db
--- /dev/null
+++ b/qa/qa/support/fabrication_tracker.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module QA
+ module Support
+ # Threadsafe fabrication time tracker
+ #
+ # Ongoing fabrication is added to callstack by start_fabrication and taken out by finish_fabrication
+ #
+ # Fabrication runtime is saved only for the first fabrication in the stack to properly represent the real time
+ # fabrications might take as top level fabrication runtime will always include nested fabrications runtime
+ #
+ class FabricationTracker
+ class << self
+ # Start fabrication and increment ongoing fabrication count
+ #
+ # @return [void]
+ def start_fabrication
+ Thread.current[:fabrications_ongoing] = 0 unless Thread.current.key?(:fabrications_ongoing)
+
+ Thread.current[:fabrications_ongoing] += 1
+ end
+
+ # Finish fabrication and decrement ongoing fabrication count
+ #
+ # @return [void]
+ def finish_fabrication
+ Thread.current[:fabrications_ongoing] -= 1
+ end
+
+ # Save fabrication time if it's first in fabrication stack
+ #
+ # @param [Symbol] type
+ # @param [Symbol] time
+ # @return [void]
+ def save_fabrication(type, time)
+ return unless Thread.current.key?(type)
+ return unless top_level_fabrication?
+
+ Thread.current[type] += time
+ end
+
+ private
+
+ # Check if current fabrication is the only one in the stack
+ #
+ # @return [Boolean]
+ def top_level_fabrication?
+ Thread.current[:fabrications_ongoing] == 1
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/support/formatters/test_stats_formatter.rb b/qa/qa/support/formatters/test_stats_formatter.rb
index 0484bd7f90f..b54b6a51d11 100644
--- a/qa/qa/support/formatters/test_stats_formatter.rb
+++ b/qa/qa/support/formatters/test_stats_formatter.rb
@@ -57,6 +57,8 @@ module QA
# @return [Hash]
def test_stats(example)
file_path = example.metadata[:file_path].gsub('./qa/specs/features', '')
+ api_fabrication = ((example.metadata[:api_fabrication] || 0) * 1000).round
+ ui_fabrication = ((example.metadata[:browser_ui_fabrication] || 0) * 1000).round
{
name: 'test-stats',
@@ -76,6 +78,9 @@ module QA
fields: {
id: example.id,
run_time: (example.execution_result.run_time * 1000).round,
+ api_fabrication: api_fabrication,
+ ui_fabrication: ui_fabrication,
+ total_fabrication: api_fabrication + ui_fabrication,
retry_attempts: example.metadata[:retry_attempts] || 0,
job_url: QA::Runtime::Env.ci_job_url,
pipeline_url: env('CI_PIPELINE_URL'),
@@ -98,14 +103,18 @@ module QA
#
# @return [String]
def job_name
- @job_name ||= QA::Runtime::Env.ci_job_name.gsub(%r{ \d{1,2}/\d{1,2}}, '')
+ @job_name ||= QA::Runtime::Env.ci_job_name&.gsub(%r{ \d{1,2}/\d{1,2}}, '')
end
# Single common timestamp for all exported example metrics to keep data points consistently grouped
#
# @return [Time]
def time
- @time ||= DateTime.strptime(env('CI_PIPELINE_CREATED_AT')).to_time
+ @time ||= begin
+ return Time.now unless env('CI_PIPELINE_CREATED_AT')
+
+ DateTime.strptime(env('CI_PIPELINE_CREATED_AT')).to_time
+ end
end
# Is a merge request execution
diff --git a/qa/qa/support/helpers/plan.rb b/qa/qa/support/helpers/plan.rb
new file mode 100644
index 00000000000..298a6d3f036
--- /dev/null
+++ b/qa/qa/support/helpers/plan.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module QA
+ module Support
+ module Helpers
+ module Plan
+ FREE = { name: 'free', price: 0, yearly_price: 0, ci_minutes: 400 }.freeze
+
+ PREMIUM = {
+ plan_id: '2c92a00d76f0d5060176f2fb0a5029ff',
+ rate_charge_id: '2c92a00d76f0d5060176f2fb0a672a02',
+ name: 'premium',
+ price: 19,
+ yearly_price: 228,
+ ci_minutes: 10000
+ }.freeze
+
+ PREMIUM_SELF_MANAGED = {
+ plan_id: '2c92a01176f0d50a0176f3043c4d4a53',
+ rate_charge_id: '2c92a01176f0d50a0176f3043c6a4a58',
+ name: 'premium',
+ price: 19,
+ yearly_price: 228
+ }.freeze
+
+ ULTIMATE = {
+ plan_id: '2c92a0ff76f0d5250176f2f8c86f305a',
+ rate_charge_id: '2c92a0ff76f0d5250176f2f8c896305c',
+ name: 'ultimate',
+ price: 99,
+ yearly_price: 1188,
+ ci_minutes: 50000
+ }.freeze
+
+ ULTIMATE_SELF_MANAGED = {
+ plan_id: '2c92a00c76f0c6c20176f2f9328b33c9',
+ rate_charge_id: '2c92a00c76f0c6c20176f2fcbb645b5f',
+ name: 'ultimate',
+ price: 99,
+ yearly_price: 1188
+ }.freeze
+
+ CI_MINUTES = {
+ plan_id: '2c92a0086a07f4a8016a2c0a1f7b4b4c',
+ rate_charge_id: '2c92a0fd6a07f4c6016a2c0af07c3f21',
+ name: 'ci_minutes',
+ price: 10,
+ ci_minutes: 1000
+ }.freeze
+
+ STORAGE = {
+ plan_id: '2c92a00f7279a6f5017279d299d01cf9',
+ rate_charge_id: '2c92a0ff7279a74f017279d5bea71fc5',
+ name: 'storage',
+ price: 60,
+ storage: 10
+ }.freeze
+
+ LICENSE_TYPE = {
+ license_file: 'license file',
+ cloud_license: 'cloud license'
+ }.freeze
+ end
+ end
+ end
+end
diff --git a/qa/qa/support/matchers/eventually_matcher.rb b/qa/qa/support/matchers/eventually_matcher.rb
index ff8adab424b..dedef8e6b98 100644
--- a/qa/qa/support/matchers/eventually_matcher.rb
+++ b/qa/qa/support/matchers/eventually_matcher.rb
@@ -59,8 +59,10 @@ module QA
def wait_and_check(actual, expectation_name)
attempt = 0
- QA::Runtime::Logger.debug("Running eventually matcher with '#{operator_msg}' operator")
- QA::Support::Retrier.retry_until(**@retry_args) do
+ QA::Runtime::Logger.debug(
+ "Running eventually matcher with '#{operator_msg}' operator with: #{@retry_args}"
+ )
+ QA::Support::Retrier.retry_until(**@retry_args, log: false) do
QA::Runtime::Logger.debug("evaluating expectation, attempt: #{attempt += 1}")
public_send(expectation_name, actual)
diff --git a/qa/qa/support/matchers/have_matcher.rb b/qa/qa/support/matchers/have_matcher.rb
index 7001f53a7b7..47d2d246460 100644
--- a/qa/qa/support/matchers/have_matcher.rb
+++ b/qa/qa/support/matchers/have_matcher.rb
@@ -19,6 +19,7 @@ module QA
related_issue_item
snippet_description
tag
+ label
].each do |predicate|
RSpec::Matchers.define "have_#{predicate}" do |*args, **kwargs|
match do |page_object|
diff --git a/qa/qa/support/repeater.rb b/qa/qa/support/repeater.rb
index b3a2472d702..a4e8035f964 100644
--- a/qa/qa/support/repeater.rb
+++ b/qa/qa/support/repeater.rb
@@ -18,17 +18,34 @@ module QA
sleep_interval: 0,
raise_on_failure: true,
retry_on_exception: false,
- log: true
+ log: true,
+ message: nil
)
attempts = 0
start = Time.now
begin
while remaining_attempts?(attempts, max_attempts) && remaining_time?(start, max_duration)
- QA::Runtime::Logger.debug("Attempt number #{attempts + 1}") if max_attempts && log
+ # start logging from the second attempt
+ if log && attempts == 1
+ msg = ["Retrying action with:"]
+ msg << "max_attempts: #{max_attempts};" if max_attempts
+ msg << "max_duration: #{max_duration};" if max_duration
+ msg << "reload_page: #{reload_page};" if reload_page
+ msg << "sleep_interval: #{sleep_interval};"
+ msg << "raise_on_failure: #{raise_on_failure};"
+ msg << "retry_on_exception: #{retry_on_exception}"
+
+ QA::Runtime::Logger.debug(msg.join(' '))
+ end
+
+ QA::Runtime::Logger.debug("Attempt number #{attempts + 1}") if log && max_attempts && attempts > 0
result = yield
- return result if result
+ if result
+ log_completion(log, attempts)
+ return result
+ end
sleep_and_reload_if_needed(sleep_interval, reload_page)
attempts += 1
@@ -47,13 +64,18 @@ module QA
unless remaining_attempts?(attempts, max_attempts)
raise(
RetriesExceededError,
- "Retry condition not met after #{max_attempts} #{'attempt'.pluralize(max_attempts)}"
+ "#{message || 'Retry'} failed after #{max_attempts} #{'attempt'.pluralize(max_attempts)}"
)
end
- raise WaitExceededError, "Wait condition not met after #{max_duration} #{'second'.pluralize(max_duration)}"
+ raise(
+ WaitExceededError,
+ "#{message || 'Wait'} failed after #{max_duration} #{'second'.pluralize(max_duration)}"
+ )
end
+ log_completion(log, attempts)
+
false
end
@@ -71,6 +93,17 @@ module QA
def remaining_time?(start, max_duration)
max_duration ? Time.now - start < max_duration : true
end
+
+ # Log completion if more than one attempt performed
+ #
+ # @param [Boolean] log
+ # @param [Integer] attempts
+ # @return [void]
+ def log_completion(log, attempts)
+ return unless log && attempts > 0
+
+ QA::Runtime::Logger.debug('ended retry')
+ end
end
end
end
diff --git a/qa/qa/support/retrier.rb b/qa/qa/support/retrier.rb
index aa568d633fc..aa36bf5922e 100644
--- a/qa/qa/support/retrier.rb
+++ b/qa/qa/support/retrier.rb
@@ -7,21 +7,15 @@ module QA
module_function
- def retry_on_exception(max_attempts: 3, reload_page: nil, sleep_interval: 0.5, log: true)
- if log
- msg = ["with retry_on_exception: max_attempts: #{max_attempts}"]
- msg << "reload_page: #{reload_page}" if reload_page
- msg << "sleep_interval: #{sleep_interval}"
- QA::Runtime::Logger.debug(msg.join('; '))
- end
-
+ def retry_on_exception(max_attempts: 3, reload_page: nil, sleep_interval: 0.5, log: true, message: nil)
result = nil
repeat_until(
max_attempts: max_attempts,
reload_page: reload_page,
sleep_interval: sleep_interval,
retry_on_exception: true,
- log: log
+ log: log,
+ message: message
) do
result = yield
@@ -29,7 +23,6 @@ module QA
# We set it to `true` so that it doesn't repeat if there's no exception
true
end
- QA::Runtime::Logger.debug("ended retry_on_exception") if log
result
end
@@ -41,25 +34,12 @@ module QA
sleep_interval: 0,
raise_on_failure: true,
retry_on_exception: false,
- log: true
+ log: true,
+ message: nil
)
# For backwards-compatibility
max_attempts = 3 if max_attempts.nil? && max_duration.nil?
- if log
- start_msg = ["with retry_until:"]
- start_msg << "max_attempts: #{max_attempts};" if max_attempts
- start_msg << "max_duration: #{max_duration};" if max_duration
- start_msg.push(*[
- "reload_page: #{reload_page};",
- "sleep_interval: #{sleep_interval};",
- "raise_on_failure: #{raise_on_failure};",
- "retry_on_exception: #{retry_on_exception}"
- ])
-
- QA::Runtime::Logger.debug(start_msg.join(' '))
- end
-
result = nil
repeat_until(
max_attempts: max_attempts,
@@ -68,11 +48,11 @@ module QA
sleep_interval: sleep_interval,
raise_on_failure: raise_on_failure,
retry_on_exception: retry_on_exception,
- log: log
+ log: log,
+ message: message
) do
result = yield
end
- QA::Runtime::Logger.debug("ended retry_until") if log
result
end
diff --git a/qa/qa/support/waiter.rb b/qa/qa/support/waiter.rb
index 9ccc0d9484f..6dbbd197b01 100644
--- a/qa/qa/support/waiter.rb
+++ b/qa/qa/support/waiter.rb
@@ -7,20 +7,16 @@ module QA
module_function
- def wait_until(max_duration: singleton_class::DEFAULT_MAX_WAIT_TIME, reload_page: nil, sleep_interval: 0.1, raise_on_failure: true, retry_on_exception: false, log: true)
- if log
- QA::Runtime::Logger.debug(
- <<~MSG.tr("\n", ' ')
- with wait_until: max_duration: #{max_duration};
- reload_page: #{reload_page};
- sleep_interval: #{sleep_interval};
- raise_on_failure: #{raise_on_failure}
- MSG
- )
- end
-
+ def wait_until(
+ max_duration: singleton_class::DEFAULT_MAX_WAIT_TIME,
+ reload_page: nil,
+ sleep_interval: 0.1,
+ raise_on_failure: true,
+ retry_on_exception: false,
+ log: true
+ )
result = nil
- self.repeat_until(
+ repeat_until(
max_duration: max_duration,
reload_page: reload_page,
sleep_interval: sleep_interval,
@@ -30,7 +26,6 @@ module QA
) do
result = yield
end
- QA::Runtime::Logger.debug("ended wait_until") if log
result
end
diff --git a/qa/qa/tools/reliable_report.rb b/qa/qa/tools/reliable_report.rb
new file mode 100644
index 00000000000..9d2079171c1
--- /dev/null
+++ b/qa/qa/tools/reliable_report.rb
@@ -0,0 +1,234 @@
+# frozen_string_literal: true
+
+require "influxdb-client"
+require "terminal-table"
+require "slack-notifier"
+
+module QA
+ module Tools
+ class ReliableReport
+ def initialize(run_type, range = 30)
+ @results = 10
+ @slack_channel = "#quality-reports"
+ @range = range
+ @run_type = run_type
+ @stable_title = "Top #{results} stable specs for past #{@range} days in '#{run_type}' runs"
+ @unstable_title = "Top #{results} unstable reliable specs for past #{@range} days in '#{run_type}' runs"
+ end
+
+ # Print top stable specs
+ #
+ # @return [void]
+ def show_top_stable
+ puts terminal_table(
+ rows: top_stable.map { |k, v| [name_column(k, v[:file]), *table_params(v.values)] },
+ title: stable_title
+ )
+ end
+
+ # Post top stable spec report to slack
+ # Slice table in to multiple messages due to max char limitation
+ #
+ # @return [void]
+ def notify_top_stable
+ tables = top_stable.each_slice(5).map do |slice|
+ terminal_table(
+ rows: slice.map { |spec| [name_column(spec[0], spec[1][:file]), *table_params(spec[1].values)] }
+ )
+ end
+
+ puts "\nSending top stable spec report to #{slack_channel} slack channel"
+ slack_args = { icon_emoji: ":mtg_green:", username: "Stable Spec Report" }
+ notifier.post(text: "*#{stable_title}*", **slack_args)
+ tables.each { |table| notifier.post(text: "```#{table}```", **slack_args) }
+ end
+
+ # Print top unstable specs
+ #
+ # @return [void]
+ def show_top_unstable
+ return puts("No unstable tests present!") if top_unstable_reliable.empty?
+
+ puts terminal_table(
+ rows: top_unstable_reliable.map { |k, v| [name_column(k, v[:file]), *table_params(v.values)] },
+ title: unstable_title
+ )
+ end
+
+ # Post top unstable reliable spec report to slack
+ # Slice table in to multiple messages due to max char limitation
+ #
+ # @return [void]
+ def notify_top_unstable
+ return puts("No unstable tests present!") if top_unstable_reliable.empty?
+
+ tables = top_unstable_reliable.each_slice(5).map do |slice|
+ terminal_table(
+ rows: slice.map { |spec| [name_column(spec[0], spec[1][:file]), *table_params(spec[1].values)] }
+ )
+ end
+
+ puts "\nSending top unstable reliable spec report to #{slack_channel} slack channel"
+ slack_args = { icon_emoji: ":sadpanda:", username: "Unstable Spec Report" }
+ notifier.post(text: "*#{unstable_title}*", **slack_args)
+ tables.each { |table| notifier.post(text: "```#{table}```", **slack_args) }
+ end
+
+ private
+
+ attr_reader :results,
+ :slack_channel,
+ :range,
+ :run_type,
+ :stable_title,
+ :unstable_title
+
+ # Top stable specs
+ #
+ # @return [Hash]
+ def top_stable
+ @top_stable ||= runs(reliable: false).sort_by { |k, v| [v[:failure_rate], -v[:runs]] }[0..results - 1].to_h
+ end
+
+ # Top unstable reliable specs
+ #
+ # @return [Hash]
+ def top_unstable_reliable
+ @top_unstable_reliable ||= runs(reliable: true)
+ .reject { |k, v| v[:failure_rate] == 0 }
+ .sort_by { |k, v| -v[:failure_rate] }[0..results - 1]
+ .to_h
+ end
+
+ # Terminal table for result formatting
+ #
+ # @return [Terminal::Table]
+ def terminal_table(rows:, title: nil)
+ Terminal::Table.new(
+ headings: ["name", "runs", "failed", "failure rate"],
+ style: { all_separators: true },
+ title: title,
+ rows: rows
+ )
+ end
+
+ # Spec parameters for table row
+ #
+ # @param [Array] parameters
+ # @return [Array]
+ def table_params(parameters)
+ [*parameters[1..2], "#{parameters.last}%"]
+ end
+
+ # Name column value
+ #
+ # @param [String] name
+ # @param [String] file
+ # @return [String]
+ def name_column(name, file)
+ spec_name = name.length > 100 ? "#{name} ".scan(/.{1,100} /).map(&:strip).join("\n") : name
+ name_line = "name: '#{spec_name}'"
+ file_line = "file: '#{file}'"
+
+ "#{name_line}\n#{file_line.ljust(110)}"
+ end
+
+ # Test executions grouped by name
+ #
+ # @param [Boolean] reliable
+ # @return [Hash]
+ def runs(reliable:)
+ puts("Fetching data on #{reliable ? 'reliable ' : ''}test execution for past 30 days in '#{run_type}' runs")
+ puts
+
+ query_api.query(query: query(reliable)).values.each_with_object({}) do |table, result|
+ records = table.records
+ name = records.last.values["name"]
+ file = records.last.values["file_path"].split("/").last
+ runs = records.count
+ failed = records.count { |r| r.values["status"] == "failed" }
+ failure_rate = (failed.to_f / runs.to_f) * 100
+
+ result[name] = {
+ file: file,
+ runs: runs,
+ failed: failed,
+ failure_rate: failure_rate == 0 ? failure_rate.round(0) : failure_rate.round(2)
+ }
+ end
+ end
+
+ # Flux query
+ #
+ # @param [Boolean] reliable
+ # @return [String]
+ def query(reliable)
+ <<~QUERY
+ from(bucket: "e2e-test-stats")
+ |> range(start: -#{range}d)
+ |> filter(fn: (r) => r._measurement == "test-stats" and
+ r.run_type == "#{run_type}" and
+ r.status != "pending" and
+ r.merge_request == "false" and
+ r.quarantined == "false" and
+ r.reliable == "#{reliable}" and
+ r._field == "id"
+ )
+ |> group(columns: ["name"])
+ QUERY
+ end
+
+ # Query client
+ #
+ # @return [QueryApi]
+ def query_api
+ @query_api ||= influx_client.create_query_api
+ end
+
+ # InfluxDb client
+ #
+ # @return [InfluxDB2::Client]
+ def influx_client
+ @influx_client ||= InfluxDB2::Client.new(
+ influxdb_url,
+ influxdb_token,
+ bucket: "e2e-test-stats",
+ org: "gitlab-qa",
+ precision: InfluxDB2::WritePrecision::NANOSECOND
+ )
+ end
+
+ # Slack notifier
+ #
+ # @return [Slack::Notifier]
+ def notifier
+ @notifier ||= Slack::Notifier.new(
+ slack_webhook_url,
+ channel: slack_channel,
+ username: "Reliable spec reporter"
+ )
+ end
+
+ # InfluxDb instance url
+ #
+ # @return [String]
+ def influxdb_url
+ @influxdb_url ||= ENV["QA_INFLUXDB_URL"] || raise("Missing QA_INFLUXDB_URL environment variable")
+ end
+
+ # Influxdb token
+ #
+ # @return [String]
+ def influxdb_token
+ @influxdb_token ||= ENV["QA_INFLUXDB_TOKEN"] || raise("Missing QA_INFLUXDB_TOKEN environment variable")
+ end
+
+ # Slack webhook url
+ #
+ # @return [String]
+ def slack_webhook_url
+ @slack_webhook_url ||= ENV["CI_SLACK_WEBHOOK_URL"] || raise("Missing CI_SLACK_WEBHOOK_URL environment variable")
+ end
+ end
+ end
+end
diff --git a/qa/spec/runtime/feature_spec.rb b/qa/spec/runtime/feature_spec.rb
index 39c20dd3070..88f5cd5be93 100644
--- a/qa/spec/runtime/feature_spec.rb
+++ b/qa/spec/runtime/feature_spec.rb
@@ -175,6 +175,20 @@ RSpec.describe QA::Runtime::Feature do
expect(described_class.enabled?(feature_flag)).to be_truthy
end
+ it 'raises an error when the scope is unknown' do
+ expect(QA::Runtime::API::Request)
+ .to receive(:new)
+ .with(api_client, "/features")
+ .and_return(request)
+ expect(described_class)
+ .to receive(:get)
+ .and_return(
+ Struct.new(:code, :body)
+ .new(200, %([{ "name": "a_flag", "state": "conditional", "gates": { "key": "groups", "value": ["foo"] } }])))
+
+ expect { described_class.enabled?(feature_flag, scope: 'foo') }.to raise_error(QA::Runtime::Feature::UnknownScopeError)
+ end
+
context 'when a project scope is provided' do
it_behaves_like 'checks a feature flag' do
let(:scope) { :project }
@@ -212,4 +226,38 @@ RSpec.describe QA::Runtime::Feature do
end
end
end
+
+ describe '.set' do
+ let(:scope) { { scope: 'actor' } }
+
+ it 'raises an error when the flag state is unknown' do
+ expect(described_class).not_to receive(:enable)
+ expect(described_class).not_to receive(:disable)
+
+ expect { described_class.set({ foo: 'bar' }, **scope) }.to raise_error(QA::Runtime::Feature::UnknownStateError, 'Unknown feature flag state: bar')
+ end
+
+ it 'enables feature flags' do
+ expect(described_class).to receive(:enable).with(:flag1, scope)
+ expect(described_class).to receive(:enable).with(:flag2, scope)
+ expect(described_class).not_to receive(:disable)
+
+ described_class.set({ flag1: 'enabled', flag2: 'enable' }, **scope)
+ end
+
+ it 'disables feature flags' do
+ expect(described_class).to receive(:disable).with(:flag1, scope)
+ expect(described_class).to receive(:disable).with(:flag2, scope)
+ expect(described_class).not_to receive(:enable)
+
+ described_class.set({ flag1: 'disable', flag2: 'disable' }, **scope)
+ end
+
+ it 'enables and disables feature flags' do
+ expect(described_class).to receive(:enable).with(:flag1, scope)
+ expect(described_class).to receive(:disable).with(:flag2, scope)
+
+ described_class.set({ flag1: 'enabled', flag2: 'disabled' }, **scope)
+ end
+ end
end
diff --git a/qa/spec/scenario/test/instance/reliable_spec.rb b/qa/spec/scenario/test/instance/reliable_spec.rb
new file mode 100644
index 00000000000..4001d386bf3
--- /dev/null
+++ b/qa/spec/scenario/test/instance/reliable_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+RSpec.describe QA::Scenario::Test::Instance::Reliable do
+ it_behaves_like 'a QA scenario class' do
+ let(:tags) { [:reliable] }
+ end
+end
diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb
index e25892a008f..640f2de0ca2 100644
--- a/qa/spec/spec_helper.rb
+++ b/qa/spec/spec_helper.rb
@@ -27,8 +27,12 @@ RSpec.configure do |config|
config.add_formatter QA::Support::Formatters::QuarantineFormatter
config.add_formatter QA::Support::Formatters::TestStatsFormatter if QA::Runtime::Env.export_metrics?
- config.before do |example|
+ config.prepend_before do |example|
QA::Runtime::Logger.debug("\nStarting test: #{example.full_description}\n")
+
+ # Reset fabrication counters tracked in resource base
+ Thread.current[:api_fabrication] = 0
+ Thread.current[:browser_ui_fabrication] = 0
end
config.after do
@@ -36,6 +40,12 @@ RSpec.configure do |config|
QA::Git::Repository.new.delete_netrc
end
+ # Add fabrication time to spec metadata
+ config.append_after do |example|
+ example.metadata[:api_fabrication] = Thread.current[:api_fabrication]
+ example.metadata[:browser_ui_fabrication] = Thread.current[:browser_ui_fabrication]
+ end
+
config.after(:context) do
if !QA::Runtime::Browser.blank_page? && QA::Page::Main::Menu.perform(&:signed_in?)
QA::Page::Main::Menu.perform(&:sign_out)
diff --git a/qa/spec/specs/allure_report_spec.rb b/qa/spec/specs/allure_report_spec.rb
index 03bf77039cc..06b09106140 100644
--- a/qa/spec/specs/allure_report_spec.rb
+++ b/qa/spec/specs/allure_report_spec.rb
@@ -3,7 +3,7 @@
describe QA::Runtime::AllureReport do
include QA::Support::Helpers::StubEnv
- let(:rspec_config) { double('RSpec::Core::Configuration', 'add_formatter': nil, after: nil) }
+ let(:rspec_config) { double('RSpec::Core::Configuration', 'add_formatter': nil, append_after: nil) }
let(:png_path) { 'png_path' }
let(:html_path) { 'html_path' }
@@ -46,6 +46,8 @@ describe QA::Runtime::AllureReport do
let(:html_file) { 'html-file' }
let(:ci_job) { 'ee:relative 5' }
let(:versions) { { version: '14', revision: '6ced31db947' } }
+ let(:session) { double('session') }
+ let(:browser_log) { ['log message 1', 'log message 2'] }
before do
stub_env('CI', 'true')
@@ -58,6 +60,9 @@ describe QA::Runtime::AllureReport do
allow(RestClient::Request).to receive(:execute) { double('response', code: 200, body: versions.to_json) }
allow(QA::Runtime::Scenario).to receive(:method_missing).with(:gitlab_address).and_return('gitlab.com')
+ allow(Capybara).to receive(:current_session).and_return(session)
+ allow(session).to receive_message_chain('driver.browser.logs.get').and_return(browser_log)
+
described_class.configure!
end
@@ -76,7 +81,11 @@ describe QA::Runtime::AllureReport do
.with(QA::Support::Formatters::AllureMetadataFormatter).ordered
end
- it 'configures screenshot saving' do
+ it 'configures attachments saving' do
+ expect(rspec_config).to have_received(:append_after) do |&arg|
+ arg.call
+ end
+
aggregate_failures do
expect(Allure).to have_received(:add_attachment).with(
name: 'screenshot',
@@ -90,6 +99,12 @@ describe QA::Runtime::AllureReport do
type: 'text/html',
test_case: true
)
+ expect(Allure).to have_received(:add_attachment).with(
+ name: 'browser.log',
+ source: browser_log.join("\n\n"),
+ type: Allure::ContentType::TXT,
+ test_case: true
+ )
end
end
end
diff --git a/qa/spec/specs/helpers/context_selector_spec.rb b/qa/spec/specs/helpers/context_selector_spec.rb
index 0152fee6f5b..5a320cde71f 100644
--- a/qa/spec/specs/helpers/context_selector_spec.rb
+++ b/qa/spec/specs/helpers/context_selector_spec.rb
@@ -186,6 +186,24 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
end
end
+ context 'staging-ref' do
+ before do
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://staging-ref.gitlab.com/')
+ end
+
+ it 'runs on staging-ref' do
+ group = describe_successfully do
+ it('does not run in staging', only: { subdomain: :staging }) {}
+ it('runs in staging-ref', only: { subdomain: /^staging-ref./ }) {}
+ end
+
+ aggregate_failures do
+ expect(group.examples[0].execution_result.status).to eq(:pending)
+ expect(group.examples[1].execution_result.status).to eq(:passed)
+ end
+ end
+ end
+
context 'production' do
before do
QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.com/')
diff --git a/qa/spec/support/formatters/test_stats_formatter_spec.rb b/qa/spec/support/formatters/test_stats_formatter_spec.rb
index 859d45a660b..f9baf9bd9d9 100644
--- a/qa/spec/support/formatters/test_stats_formatter_spec.rb
+++ b/qa/spec/support/formatters/test_stats_formatter_spec.rb
@@ -20,6 +20,8 @@ describe QA::Support::Formatters::TestStatsFormatter do
let(:influx_write_api) { instance_double('InfluxDB2::WriteApi', write: nil) }
let(:stage) { '1_manage' }
let(:file_path) { "./qa/specs/features/#{stage}/subfolder/some_spec.rb" }
+ let(:ui_fabrication) { 0 }
+ let(:api_fabrication) { 0 }
let(:influx_client_args) do
{
@@ -48,6 +50,9 @@ describe QA::Support::Formatters::TestStatsFormatter do
fields: {
id: './spec/support/formatters/test_stats_formatter_spec.rb[1:1]',
run_time: 0,
+ api_fabrication: api_fabrication * 1000,
+ ui_fabrication: ui_fabrication * 1000,
+ total_fabrication: (api_fabrication + ui_fabrication) * 1000,
retry_attempts: 0,
job_url: ci_job_url,
pipeline_url: ci_pipeline_url,
@@ -69,6 +74,11 @@ describe QA::Support::Formatters::TestStatsFormatter do
RSpec::Core::Sandbox.sandboxed do |config|
config.formatter = QA::Support::Formatters::TestStatsFormatter
+ config.append_after do |example|
+ example.metadata[:api_fabrication] = Thread.current[:api_fabrication]
+ example.metadata[:browser_ui_fabrication] = Thread.current[:browser_ui_fabrication]
+ end
+
config.before(:context) { RSpec.current_example = nil }
example.run
@@ -171,5 +181,21 @@ describe QA::Support::Formatters::TestStatsFormatter do
expect(influx_write_api).to have_received(:write).with(data: [data])
end
end
+
+ context 'with fabrication runtimes' do
+ let(:ui_fabrication) { 10 }
+ let(:api_fabrication) { 4 }
+
+ before do
+ Thread.current[:api_fabrication] = api_fabrication
+ Thread.current[:browser_ui_fabrication] = ui_fabrication
+ end
+
+ it 'exports data to influxdb with fabrication times' do
+ run_spec
+
+ expect(influx_write_api).to have_received(:write).with(data: [data])
+ end
+ end
end
end
diff --git a/qa/spec/support/repeater_spec.rb b/qa/spec/support/repeater_spec.rb
index da8d6b18fb0..4fa3bcde5e7 100644
--- a/qa/spec/support/repeater_spec.rb
+++ b/qa/spec/support/repeater_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe QA::Support::Repeater do
context 'when retry_on_exception is not provided (default: false)' do
context 'when max_duration is provided' do
context 'when max duration is reached' do
- it 'raises an exception' do
+ it 'raises an exception with default message' do
expect do
Timecop.freeze do
subject.repeat_until(max_duration: 1) do
@@ -31,7 +31,20 @@ RSpec.describe QA::Support::Repeater do
false
end
end
- end.to raise_error(QA::Support::Repeater::WaitExceededError, "Wait condition not met after 1 second")
+ end.to raise_error(QA::Support::Repeater::WaitExceededError, "Wait failed after 1 second")
+ end
+
+ it 'raises an exception with custom message' do
+ message = 'Some custom action'
+
+ expect do
+ Timecop.freeze do
+ subject.repeat_until(max_duration: 1, message: message) do
+ Timecop.travel(2)
+ false
+ end
+ end
+ end.to raise_error(QA::Support::Repeater::WaitExceededError, "#{message} failed after 1 second")
end
it 'ignores attempts' do
@@ -70,14 +83,26 @@ RSpec.describe QA::Support::Repeater do
context 'when max_attempts is provided' do
context 'when max_attempts is reached' do
- it 'raises an exception' do
+ it 'raises an exception with default message' do
expect do
Timecop.freeze do
subject.repeat_until(max_attempts: 1) do
false
end
end
- end.to raise_error(QA::Support::Repeater::RetriesExceededError, "Retry condition not met after 1 attempt")
+ end.to raise_error(QA::Support::Repeater::RetriesExceededError, "Retry failed after 1 attempt")
+ end
+
+ it 'raises an exception with custom message' do
+ message = 'Some custom action'
+
+ expect do
+ Timecop.freeze do
+ subject.repeat_until(max_attempts: 1, message: message) do
+ false
+ end
+ end
+ end.to raise_error(QA::Support::Repeater::RetriesExceededError, "#{message} failed after 1 attempt")
end
it 'ignores duration' do
@@ -126,7 +151,7 @@ RSpec.describe QA::Support::Repeater do
false
end
end
- end.to raise_error(QA::Support::Repeater::RetriesExceededError, "Retry condition not met after 1 attempt")
+ end.to raise_error(QA::Support::Repeater::RetriesExceededError, "Retry failed after 1 attempt")
end
end
@@ -141,7 +166,7 @@ RSpec.describe QA::Support::Repeater do
false
end
end
- end.to raise_error(QA::Support::Repeater::WaitExceededError, "Wait condition not met after 1 second")
+ end.to raise_error(QA::Support::Repeater::WaitExceededError, "Wait failed after 1 second")
end
end
end
@@ -210,7 +235,7 @@ RSpec.describe QA::Support::Repeater do
false
end
end
- end.to raise_error(QA::Support::Repeater::RetriesExceededError, "Retry condition not met after 1 attempt")
+ end.to raise_error(QA::Support::Repeater::RetriesExceededError, "Retry failed after 1 attempt")
end
end
@@ -225,7 +250,7 @@ RSpec.describe QA::Support::Repeater do
false
end
end
- end.to raise_error(QA::Support::Repeater::WaitExceededError, "Wait condition not met after 1 second")
+ end.to raise_error(QA::Support::Repeater::WaitExceededError, "Wait failed after 1 second")
end
end
end
@@ -380,34 +405,67 @@ RSpec.describe QA::Support::Repeater do
end
end
- it 'logs attempts' do
- attempted = false
+ context 'with logging' do
+ before do
+ allow(QA::Runtime::Logger).to receive(:debug)
+ end
- expect do
- subject.repeat_until(max_attempts: 1) do
- unless attempted
- attempted = true
- break false
- end
+ it 'skips logging single attempt with max_attempts' do
+ subject.repeat_until(max_attempts: 3) do
+ true
+ end
+ expect(QA::Runtime::Logger).not_to have_received(:debug)
+ end
+
+ it 'skips logging single attempt with max_duration' do
+ subject.repeat_until(max_duration: 3) do
true
end
- end.to output(/Attempt number/).to_stdout_from_any_process
- end
- it 'allows logging to be silenced' do
- attempted = false
+ expect(QA::Runtime::Logger).not_to have_received(:debug)
+ end
- expect do
- subject.repeat_until(max_attempts: 1, log: false) do
- unless attempted
- attempted = true
- break false
- end
+ it 'allows logging to be silenced' do
+ subject.repeat_until(max_attempts: 3, log: false, raise_on_failure: false) do
+ false
+ end
- true
+ expect(QA::Runtime::Logger).not_to have_received(:debug)
+ end
+
+ it 'starts logging on subsequent attempts for max_duration' do
+ subject.repeat_until(max_duration: 0.3, sleep_interval: 0.1, raise_on_failure: false) do
+ false
+ end
+
+ aggregate_failures do
+ expect(QA::Runtime::Logger).to have_received(:debug).with(<<~MSG.strip).ordered.once
+ Retrying action with: max_duration: 0.3; sleep_interval: 0.1; raise_on_failure: false; retry_on_exception: false
+ MSG
+ expect(QA::Runtime::Logger).to have_received(:debug).with('ended retry').ordered.once
+ expect(QA::Runtime::Logger).not_to have_received(:debug).with(/Attempt number/)
+ end
+ end
+
+ it 'starts logging subsequent attempts for max_attempts' do
+ attempts = 0
+ subject.repeat_until(max_attempts: 4, raise_on_failure: false) do
+ next true if attempts == 2
+
+ attempts += 1
+ false
end
- end.not_to output.to_stdout_from_any_process
+
+ aggregate_failures do
+ expect(QA::Runtime::Logger).to have_received(:debug).with(<<~MSG.strip).ordered.once
+ Retrying action with: max_attempts: 4; sleep_interval: 0; raise_on_failure: false; retry_on_exception: false
+ MSG
+ expect(QA::Runtime::Logger).to have_received(:debug).with('Attempt number 2').ordered.once
+ expect(QA::Runtime::Logger).to have_received(:debug).with('Attempt number 3').ordered.once
+ expect(QA::Runtime::Logger).to have_received(:debug).with('ended retry').ordered.once
+ end
+ end
end
end
end
diff --git a/qa/spec/support/retrier_spec.rb b/qa/spec/support/retrier_spec.rb
index 9ad3e85fea9..1f303093a00 100644
--- a/qa/spec/support/retrier_spec.rb
+++ b/qa/spec/support/retrier_spec.rb
@@ -1,42 +1,7 @@
# frozen_string_literal: true
RSpec.describe QA::Support::Retrier do
- before do
- logger = ::Logger.new $stdout
- logger.level = ::Logger::DEBUG
- QA::Runtime::Logger.logger = logger
- end
-
describe '.retry_until' do
- context 'when the condition is true' do
- it 'logs max attempts (3 by default)' do
- expect { subject.retry_until { true } }
- .to output(/with retry_until: max_attempts: 3; reload_page: ; sleep_interval: 0; raise_on_failure: true; retry_on_exception: false/).to_stdout_from_any_process
- end
-
- it 'logs max duration' do
- expect { subject.retry_until(max_duration: 1) { true } }
- .to output(/with retry_until: max_duration: 1; reload_page: ; sleep_interval: 0; raise_on_failure: true; retry_on_exception: false/).to_stdout_from_any_process
- end
-
- it 'logs the end' do
- expect { subject.retry_until { true } }
- .to output(/ended retry_until$/).to_stdout_from_any_process
- end
- end
-
- context 'when the condition is false' do
- it 'logs the start' do
- expect { subject.retry_until(max_duration: 0, raise_on_failure: false) { false } }
- .to output(/with retry_until: max_duration: 0; reload_page: ; sleep_interval: 0; raise_on_failure: false; retry_on_exception: false/).to_stdout_from_any_process
- end
-
- it 'logs the end' do
- expect { subject.retry_until(max_duration: 0, raise_on_failure: false) { false } }
- .to output(/ended retry_until$/).to_stdout_from_any_process
- end
- end
-
context 'when max_duration and max_attempts are nil' do
it 'sets max attempts to 3 by default' do
expect(subject).to receive(:repeat_until).with(hash_including(max_attempts: 3))
@@ -62,35 +27,21 @@ RSpec.describe QA::Support::Retrier do
subject.retry_until
end
- end
- describe '.retry_on_exception' do
- context 'when the condition is true' do
- it 'logs max_attempts, reload_page, and sleep_interval parameters' do
- message = /with retry_on_exception: max_attempts: 1; reload_page: true; sleep_interval: 0/
- expect { subject.retry_on_exception(max_attempts: 1, reload_page: true, sleep_interval: 0) { true } }
- .to output(message).to_stdout_from_any_process
- end
+ it 'allows logs to be silenced' do
+ expect(subject).to receive(:repeat_until).with(hash_including(log: false))
- it 'logs the end' do
- expect { subject.retry_on_exception(max_attempts: 1, reload_page: nil, sleep_interval: 0) { true } }
- .to output(/ended retry_on_exception$/).to_stdout_from_any_process
- end
+ subject.retry_until(log: false)
end
- context 'when the condition is false' do
- it 'logs the start' do
- message = /with retry_on_exception: max_attempts: 1; reload_page: true; sleep_interval: 0/
- expect { subject.retry_on_exception(max_attempts: 1, reload_page: true, sleep_interval: 0) { false } }
- .to output(message).to_stdout_from_any_process
- end
+ it 'sets custom error message' do
+ expect(subject).to receive(:repeat_until).with(hash_including(message: 'Custom message'))
- it 'logs the end' do
- expect { subject.retry_on_exception(max_attempts: 1, reload_page: nil, sleep_interval: 0) { false } }
- .to output(/ended retry_on_exception$/).to_stdout_from_any_process
- end
+ subject.retry_until(message: 'Custom message')
end
+ end
+ describe '.retry_on_exception' do
it 'does not repeat if no exception is raised' do
loop_counter = 0
return_value = "test passed"
@@ -121,5 +72,11 @@ RSpec.describe QA::Support::Retrier do
subject.retry_on_exception
end
+
+ it 'allows logs to be silenced' do
+ expect(subject).to receive(:repeat_until).with(hash_including(log: false))
+
+ subject.retry_on_exception(log: false)
+ end
end
end
diff --git a/qa/spec/support/shared_contexts/packages_registry_shared_context.rb b/qa/spec/support/shared_contexts/packages_registry_shared_context.rb
index 6e197015640..e686d254a44 100644
--- a/qa/spec/support/shared_contexts/packages_registry_shared_context.rb
+++ b/qa/spec/support/shared_contexts/packages_registry_shared_context.rb
@@ -43,8 +43,13 @@ module QA
let(:project_deploy_token) do
Resource::DeployToken.fabricate_via_browser_ui! do |deploy_token|
- deploy_token.name = 'helm-package-deploy-token'
+ deploy_token.name = 'package-deploy-token'
deploy_token.project = package_project
+ deploy_token.scopes = [
+ :read_repository,
+ :read_package_registry,
+ :write_package_registry
+ ]
end
end
diff --git a/qa/spec/support/waiter_spec.rb b/qa/spec/support/waiter_spec.rb
index d0b216b5dc1..c575a27bc35 100644
--- a/qa/spec/support/waiter_spec.rb
+++ b/qa/spec/support/waiter_spec.rb
@@ -1,40 +1,11 @@
# frozen_string_literal: true
RSpec.describe QA::Support::Waiter do
- before do
- logger = ::Logger.new $stdout
- logger.level = ::Logger::DEBUG
- QA::Runtime::Logger.logger = logger
- end
-
describe '.wait_until' do
- context 'when the condition is true' do
- it 'logs the start' do
- expect { subject.wait_until(max_duration: 0, raise_on_failure: false) { true } }
- .to output(/with wait_until: max_duration: 0; reload_page: ; sleep_interval: 0.1/).to_stdout_from_any_process
- end
-
- it 'logs the end' do
- expect { subject.wait_until(max_duration: 0, raise_on_failure: false) { true } }
- .to output(/ended wait_until$/).to_stdout_from_any_process
- end
- end
-
- context 'when the condition is false' do
- it 'logs the start' do
- expect { subject.wait_until(max_duration: 0, raise_on_failure: false) { false } }
- .to output(/with wait_until: max_duration: 0; reload_page: ; sleep_interval: 0.1/).to_stdout_from_any_process
- end
-
- it 'logs the end' do
- expect { subject.wait_until(max_duration: 0, raise_on_failure: false) { false } }
- .to output(/ended wait_until$/).to_stdout_from_any_process
- end
- end
-
it 'allows logs to be silenced' do
- expect { subject.wait_until(max_duration: 0, raise_on_failure: false, log: false) { false } }
- .not_to output.to_stdout_from_any_process
+ expect(subject).to receive(:repeat_until).with(hash_including(log: false))
+
+ subject.wait_until(log: false)
end
it 'sets max_duration to 60 by default' do
diff --git a/qa/spec/tools/reliable_report_spec.rb b/qa/spec/tools/reliable_report_spec.rb
new file mode 100644
index 00000000000..c7d4d28fb21
--- /dev/null
+++ b/qa/spec/tools/reliable_report_spec.rb
@@ -0,0 +1,145 @@
+# frozen_string_literal: true
+
+describe QA::Tools::ReliableReport do
+ include QA::Support::Helpers::StubEnv
+
+ subject(:reporter) { described_class.new(run_type, range) }
+
+ let(:slack_notifier) { instance_double("Slack::Notifier", post: nil) }
+ let(:influx_client) { instance_double("InfluxDB2::Client", create_query_api: query_api) }
+ let(:query_api) { instance_double("InfluxDB2::QueryApi") }
+
+ let(:slack_channel) { "#quality-reports" }
+ let(:run_type) { "package-and-qa" }
+ let(:range) { 30 }
+ let(:results) { 10 }
+
+ let(:runs) { { 0 => stable_spec, 1 => unstable_spec } }
+
+ let(:stable_spec) do
+ spec_values = { "name" => "stable spec", "status" => "passed", "file_path" => "some/spec.rb" }
+ instance_double(
+ "InfluxDB2::FluxTable",
+ records: [
+ instance_double("InfluxDB2::FluxRecord", values: spec_values),
+ instance_double("InfluxDB2::FluxRecord", values: spec_values),
+ instance_double("InfluxDB2::FluxRecord", values: spec_values)
+ ]
+ )
+ end
+
+ let(:unstable_spec) do
+ spec_values = { "name" => "unstable spec", "status" => "failed", "file_path" => "some/spec.rb" }
+ instance_double(
+ "InfluxDB2::FluxTable",
+ records: [
+ instance_double("InfluxDB2::FluxRecord", values: { **spec_values, "status" => "passed" }),
+ instance_double("InfluxDB2::FluxRecord", values: spec_values),
+ instance_double("InfluxDB2::FluxRecord", values: spec_values)
+ ]
+ )
+ end
+
+ def flux_query(reliable)
+ <<~QUERY
+ from(bucket: "e2e-test-stats")
+ |> range(start: -#{range}d)
+ |> filter(fn: (r) => r._measurement == "test-stats" and
+ r.run_type == "#{run_type}" and
+ r.status != "pending" and
+ r.merge_request == "false" and
+ r.quarantined == "false" and
+ r.reliable == "#{reliable}" and
+ r._field == "id"
+ )
+ |> group(columns: ["name"])
+ QUERY
+ end
+
+ def table(rows, title = nil)
+ Terminal::Table.new(
+ headings: ["name", "runs", "failed", "failure rate"],
+ style: { all_separators: true },
+ title: title,
+ rows: rows
+ )
+ end
+
+ def name_column(spec_name)
+ name = "name: '#{spec_name}'"
+ file = "file: 'spec.rb'".ljust(110)
+
+ "#{name}\n#{file}"
+ end
+
+ before do
+ stub_env("QA_INFLUXDB_URL", "url")
+ stub_env("QA_INFLUXDB_TOKEN", "token")
+ stub_env("CI_SLACK_WEBHOOK_URL", "slack_url")
+
+ allow(Slack::Notifier).to receive(:new).and_return(slack_notifier)
+ allow(InfluxDB2::Client).to receive(:new).and_return(influx_client)
+ allow(query_api).to receive(:query).with(query: query).and_return(runs)
+ end
+
+ context "with stable spec report" do
+ let(:query) { flux_query(false) }
+ let(:fetch_message) { "Fetching data on test execution for past #{range} days in '#{run_type}' runs" }
+ let(:slack_send_message) { "Sending top stable spec report to #{slack_channel} slack channel" }
+ let(:title) { "Top #{results} stable specs for past #{range} days in '#{run_type}' runs" }
+ let(:rows) do
+ [
+ [name_column("stable spec"), 3, 0, "0%"],
+ [name_column("unstable spec"), 3, 2, "66.67%"]
+ ]
+ end
+
+ it "prints top stable spec report to console" do
+ expect { reporter.show_top_stable }.to output("#{fetch_message}\n\n#{table(rows, title)}\n").to_stdout
+ end
+
+ it "sends top stable spec report to slack" do
+ slack_args = { icon_emoji: ":mtg_green:", username: "Stable Spec Report" }
+
+ expect { reporter.notify_top_stable }.to output("#{fetch_message}\n\n\n#{slack_send_message}\n").to_stdout
+ expect(slack_notifier).to have_received(:post).with(text: "*#{title}*", **slack_args)
+ expect(slack_notifier).to have_received(:post).with(text: "```#{table(rows)}```", **slack_args)
+ end
+ end
+
+ context "with unstable spec report" do
+ let(:query) { flux_query(true) }
+ let(:fetch_message) { "Fetching data on reliable test execution for past #{range} days in '#{run_type}' runs" }
+ let(:slack_send_message) { "Sending top unstable reliable spec report to #{slack_channel} slack channel" }
+ let(:title) { "Top #{results} unstable reliable specs for past #{range} days in '#{run_type}' runs" }
+ let(:rows) { [[name_column("unstable spec"), 3, 2, "66.67%"]] }
+
+ it "prints top unstable spec report to console" do
+ expect { reporter.show_top_unstable }.to output("#{fetch_message}\n\n#{table(rows, title)}\n").to_stdout
+ end
+
+ it "sends top unstable reliable spec report to slack" do
+ slack_args = { icon_emoji: ":sadpanda:", username: "Unstable Spec Report" }
+
+ expect { reporter.notify_top_unstable }.to output("#{fetch_message}\n\n\n#{slack_send_message}\n").to_stdout
+ expect(slack_notifier).to have_received(:post).with(text: "*#{title}*", **slack_args)
+ expect(slack_notifier).to have_received(:post).with(text: "```#{table(rows)}```", **slack_args)
+ end
+ end
+
+ context "without unstable reliable specs" do
+ let(:query) { flux_query(true) }
+ let(:runs) { { 0 => stable_spec } }
+ let(:fetch_message) { "Fetching data on reliable test execution for past #{range} days in '#{run_type}' runs" }
+ let(:no_result_message) { "No unstable tests present!" }
+
+ it "prints no result message to console" do
+ expect { reporter.show_top_unstable }.to output("#{fetch_message}\n\n#{no_result_message}\n").to_stdout
+ end
+
+ it "skips slack notification" do
+ expect { reporter.notify_top_unstable }.to output("#{fetch_message}\n\n#{no_result_message}\n").to_stdout
+ expect(slack_notifier).not_to have_received(:post)
+ end
+ end
+end
diff --git a/qa/tasks/reliable_report.rake b/qa/tasks/reliable_report.rake
new file mode 100644
index 00000000000..204c959093a
--- /dev/null
+++ b/qa/tasks/reliable_report.rake
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+# rubocop:disable Rails/RakeEnvironment
+
+require_relative "../qa/tools/reliable_report"
+
+desc "Fetch top most reliable specs"
+task :reliable_spec_report, [:run_type, :range, :create_slack_report] do |_task, args|
+ report = QA::Tools::ReliableReport.new(args[:run_type] || "package-and-qa", args[:range])
+
+ report.show_top_stable
+ report.notify_top_stable if args[:create_slack_report] == 'true'
+end
+
+desc "Fetch top most unstable reliable specs"
+task :unreliable_spec_report, [:run_type, :range, :create_slack_report] do |_task, args|
+ report = QA::Tools::ReliableReport.new(args[:run_type] || "package-and-qa", args[:range])
+
+ report.show_top_unstable
+ report.notify_top_unstable if args[:create_slack_report] == 'true'
+end
+# rubocop:enable Rails/RakeEnvironment
diff --git a/rubocop/cop/gitlab/bulk_insert.rb b/rubocop/cop/gitlab/bulk_insert.rb
index 4c8c232043f..baaefc2533c 100644
--- a/rubocop/cop/gitlab/bulk_insert.rb
+++ b/rubocop/cop/gitlab/bulk_insert.rb
@@ -3,13 +3,13 @@
module RuboCop
module Cop
module Gitlab
- # Cop that disallows the use of `Gitlab::Database.main.bulk_insert`, in favour of using
+ # Cop that disallows the use of `legacy_bulk_insert`, in favour of using
# the `BulkInsertSafe` module.
class BulkInsert < RuboCop::Cop::Cop
- MSG = 'Use the `BulkInsertSafe` concern, instead of using `Gitlab::Database.main.bulk_insert`. See https://docs.gitlab.com/ee/development/insert_into_tables_in_batches.html'
+ MSG = 'Use the `BulkInsertSafe` concern, instead of using `LegacyBulkInsert.bulk_insert`. See https://docs.gitlab.com/ee/development/insert_into_tables_in_batches.html'
def_node_matcher :raw_union?, <<~PATTERN
- (send (send (const (const _ :Gitlab) :Database) :main) :bulk_insert ...)
+ (send _ :legacy_bulk_insert ...)
PATTERN
def on_send(node)
diff --git a/rubocop/cop/gitlab/change_timzone.rb b/rubocop/cop/gitlab/change_timezone.rb
index c30a057d51c..c30a057d51c 100644
--- a/rubocop/cop/gitlab/change_timzone.rb
+++ b/rubocop/cop/gitlab/change_timezone.rb
diff --git a/rubocop/cop/gitlab/keys-first-and-values-first.rb b/rubocop/cop/gitlab/keys_first_and_values_first.rb
index e9bf266cdd7..e9bf266cdd7 100644
--- a/rubocop/cop/gitlab/keys-first-and-values-first.rb
+++ b/rubocop/cop/gitlab/keys_first_and_values_first.rb
diff --git a/rubocop/cop/gitlab/mark_used_feature_flags.rb b/rubocop/cop/gitlab/mark_used_feature_flags.rb
index 03ee4805f4e..d3c5cfb827e 100644
--- a/rubocop/cop/gitlab/mark_used_feature_flags.rb
+++ b/rubocop/cop/gitlab/mark_used_feature_flags.rb
@@ -255,10 +255,17 @@ module RuboCop
]
# For EE additionally process `ee/` feature flags
- if File.exist?(File.expand_path('../../../ee/app/models/license.rb', __dir__)) && !%w[true 1].include?(ENV['FOSS_ONLY'].to_s)
+ is_ee = File.exist?(File.expand_path('../../../ee/app/models/license.rb', __dir__)) && !%w[true 1].include?(ENV['FOSS_ONLY'].to_s)
+ if is_ee
flags_paths << 'ee/config/feature_flags/**/*.yml'
end
+ # For JH additionally process `jh/` feature flags
+ is_jh = is_ee && Dir.exist?(File.expand_path('../../../jh', __dir__)) && !%w[true 1].include?(ENV['EE_ONLY'].to_s)
+ if is_jh
+ flags_paths << 'jh/config/feature_flags/**/*.yml'
+ end
+
flags_paths.each_with_object([]) do |flags_path, memo|
flags_path = File.expand_path("../../../#{flags_path}", __dir__)
Dir.glob(flags_path).each do |path|
diff --git a/rubocop/cop/qa/duplicate_testcase_link.rb b/rubocop/cop/qa/duplicate_testcase_link.rb
new file mode 100644
index 00000000000..82549707a83
--- /dev/null
+++ b/rubocop/cop/qa/duplicate_testcase_link.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module QA
+ # This cop checks for duplicate testcase links across e2e specs
+ #
+ # @example
+ #
+ # # bad
+ # it 'some test', testcase: '(...)/quality/test_cases/1892'
+ # it 'another test, testcase: '(...)/quality/test_cases/1892'
+ #
+ # # good
+ # it 'some test', testcase: '(...)/quality/test_cases/1892'
+ # it 'another test, testcase: '(...)/quality/test_cases/1894'
+ class DuplicateTestcaseLink < RuboCop::Cop::Cop
+ MESSAGE = "Don't reuse the same testcase link in different tests. Replace one of `%s`."
+
+ @testcase_set = Set.new
+
+ def_node_matcher :duplicate_testcase_link, <<~PATTERN
+ (block
+ (send nil? ...
+ ...
+ (hash
+ (pair
+ (sym :testcase)
+ (str $_))...)...)...)
+ PATTERN
+
+ def on_block(node)
+ duplicate_testcase_link(node) do |link|
+ break unless self.class.duplicate?(link)
+
+ add_offense(node, message: MESSAGE % link)
+ end
+ end
+
+ def self.duplicate?(link)
+ !@testcase_set.add?(link)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb
index c8a573410d8..5a5e76a87e2 100644
--- a/rubocop/rubocop.rb
+++ b/rubocop/rubocop.rb
@@ -1,4 +1,7 @@
+# rubocop:disable Naming/FileName
# frozen_string_literal: true
# Auto-require all cops under `rubocop/cop/**/*.rb`
Dir[File.join(__dir__, 'cop', '**', '*.rb')].sort.each(&method(:require))
+
+# rubocop:enable Naming/FileName
diff --git a/scripts/api/default_options.rb b/scripts/api/default_options.rb
index 70fb9683733..d10666e3a68 100644
--- a/scripts/api/default_options.rb
+++ b/scripts/api/default_options.rb
@@ -9,3 +9,10 @@ module API
endpoint: ENV['CI_API_V4_URL'] || 'https://gitlab.com/api/v4'
}.freeze
end
+
+module Host
+ DEFAULT_OPTIONS = {
+ instance_base_url: ENV['CI_SERVER_URL'],
+ mr_id: ENV['CI_MERGE_REQUEST_ID']
+ }.freeze
+end
diff --git a/scripts/changed-feature-flags b/scripts/changed-feature-flags
new file mode 100755
index 00000000000..3a4f18bd78f
--- /dev/null
+++ b/scripts/changed-feature-flags
@@ -0,0 +1,59 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'yaml'
+require 'optparse'
+require_relative 'api/default_options'
+
+# This script returns the desired feature flag state as a comma-separated string for the feature flags in the specified files.
+# Each desired feature flag state is specified as 'feature-flag=state'.
+#
+# For example, if the specified files included `config/feature_flags/development/ci_yaml_limit_size.yml` and the desired
+# state as specified by the second argument was enabled, the value returned would be `ci_yaml_limit_size=enabled`
+
+class GetFeatureFlagsFromFiles
+ def initialize(options)
+ @files = options.delete(:files)
+ @state = options.delete(:state)
+ end
+
+ def extracted_flags
+ files.each_with_object([]) do |file_path, all|
+ next unless file_path =~ %r{/feature_flags/(development|ops)/.*\.yml}
+ next unless File.exist?(file_path)
+
+ ff_yaml = YAML.safe_load(File.read(file_path))
+ ff_to_add = "#{ff_yaml['name']}"
+ ff_to_add += "=#{state}" unless state.to_s.empty?
+
+ all << ff_to_add
+ end.join(',')
+ end
+
+ private
+
+ attr_reader :files, :state
+end
+
+if $0 == __FILE__
+ options = API::DEFAULT_OPTIONS.dup
+
+ OptionParser.new do |opts|
+ opts.on("-f", "--files FILES", Array, "Comma-separated list of feature flag config files") do |value|
+ options[:files] = value
+ end
+
+ opts.on("-s", "--state STATE", String,
+ "The desired state of the feature flags (enabled or disabled). If not specified the output will only list the feature flags."
+ ) do |value|
+ options[:state] = value
+ end
+
+ opts.on("-h", "--help", "Prints this help") do
+ puts opts
+ exit
+ end
+ end.parse!
+
+ puts GetFeatureFlagsFromFiles.new(options).extracted_flags
+end
diff --git a/scripts/docs_screenshots.rb b/scripts/docs_screenshots.rb
index 094e7e87960..a734540eb69 100755
--- a/scripts/docs_screenshots.rb
+++ b/scripts/docs_screenshots.rb
@@ -5,7 +5,7 @@
require 'png_quantizator'
require 'open3'
require 'parallel'
-require_relative '../tooling/lib/tooling/images'
+require_relative '../tooling/lib/tooling/image'
generator = ARGV[0]
milestone = ARGV[1]
diff --git a/scripts/failed_tests.rb b/scripts/failed_tests.rb
new file mode 100755
index 00000000000..fb13df7bf62
--- /dev/null
+++ b/scripts/failed_tests.rb
@@ -0,0 +1,122 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'optparse'
+require 'fileutils'
+require 'uri'
+require 'json'
+require 'set'
+
+class FailedTests
+ def initialize(options)
+ @filename = options.delete(:previous_tests_report_path)
+ @output_directory = options.delete(:output_directory)
+ @rspec_pg_regex = options.delete(:rspec_pg_regex)
+ @rspec_ee_pg_regex = options.delete(:rspec_ee_pg_regex)
+ end
+
+ def output_failed_test_files
+ create_output_dir
+
+ failed_files_for_suite_collection.each do |suite_collection_name, suite_collection_files|
+ failed_test_files = suite_collection_files.map { |filepath| filepath.delete_prefix('./') }.join(' ')
+
+ output_file = File.join(output_directory, "#{suite_collection_name}_failed_files.txt")
+
+ File.open(output_file, 'w') do |file|
+ file.write(failed_test_files)
+ end
+ end
+ end
+
+ def failed_files_for_suite_collection
+ suite_map.each_with_object(Hash.new { |h, k| h[k] = Set.new }) do |(suite_collection_name, suite_collection_regex), hash|
+ failed_suites.each do |suite|
+ hash[suite_collection_name].merge(failed_files(suite)) if suite['name'] =~ suite_collection_regex
+ end
+ end
+ end
+
+ def suite_map
+ @suite_map ||= {
+ rspec: rspec_pg_regex,
+ rspec_ee: rspec_ee_pg_regex,
+ jest: /jest/
+ }
+ end
+
+ private
+
+ attr_reader :filename, :output_directory, :rspec_pg_regex, :rspec_ee_pg_regex
+
+ def file_contents
+ @file_contents ||= begin
+ File.read(filename)
+ rescue Errno::ENOENT
+ '{}'
+ end
+ end
+
+ def file_contents_as_json
+ @file_contents_as_json ||= begin
+ JSON.parse(file_contents)
+ rescue JSON::ParserError
+ {}
+ end
+ end
+
+ def failed_suites
+ return [] unless file_contents_as_json['suites']
+
+ file_contents_as_json['suites'].select { |suite| suite['failed_count'] > 0 }
+ end
+
+ def failed_files(suite)
+ return [] unless suite
+
+ suite['test_cases'].each_with_object([]) do |failure_hash, failed_cases|
+ failed_cases << failure_hash['file'] if failure_hash['status'] == 'failed'
+ end
+ end
+
+ def create_output_dir
+ return if File.directory?(output_directory)
+
+ puts 'Creating output directory...'
+ FileUtils.mkdir_p(output_directory)
+ end
+end
+
+if $0 == __FILE__
+ options = {
+ previous_tests_report_path: 'test_results/previous/test_reports.json',
+ output_directory: 'tmp/previous_failed_tests/',
+ rspec_pg_regex: /rspec .+ pg12( .+)?/,
+ rspec_ee_pg_regex: /rspec-ee .+ pg12( .+)?/
+ }
+
+ OptionParser.new do |opts|
+ opts.on("-p", "--previous-tests-report-path PREVIOUS_TESTS_REPORT_PATH", String, "Path of the file listing previous test failures") do |value|
+ options[:previous_tests_report_path] = value
+ end
+
+ opts.on("-o", "--output-directory OUTPUT_DIRECTORY", String, "Output directory for failed test files") do |value|
+ options[:output_directory] = value
+ end
+
+ opts.on("--rspec-pg-regex RSPEC_PG_REGEX", Regexp, "Regex to use when finding matching RSpec jobs") do |value|
+ options[:rspec_pg_regex] = value
+ end
+
+ opts.on("--rspec-ee-pg-regex RSPEC_EE_PG_REGEX", Regexp, "Regex to use when finding matching RSpec EE jobs") do |value|
+ options[:rspec_ee_pg_regex] = value
+ end
+
+ opts.on("-h", "--help", "Prints this help") do
+ puts opts
+ exit
+ end
+ end.parse!
+
+ FailedTests.new(options).output_failed_test_files
+end
diff --git a/scripts/lint-doc.sh b/scripts/lint-doc.sh
index e99b8a47301..1698d724fd2 100755
--- a/scripts/lint-doc.sh
+++ b/scripts/lint-doc.sh
@@ -128,7 +128,7 @@ function run_locally_or_in_docker() {
$cmd $args
elif hash docker 2>/dev/null
then
- docker run -t -v ${PWD}:/gitlab -w /gitlab --rm registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.13-vale-2.10.2-markdownlint-0.26.0 ${cmd} ${args}
+ docker run -t -v ${PWD}:/gitlab -w /gitlab --rm registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.14-vale-2.12.0-markdownlint-0.29.0 ${cmd} ${args}
else
echo
echo " ✖ ERROR: '${cmd}' not found. Install '${cmd}' or Docker to proceed." >&2
diff --git a/scripts/no-dir-check b/scripts/no-dir-check
new file mode 100755
index 00000000000..bbb303da9b2
--- /dev/null
+++ b/scripts/no-dir-check
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+dir_name = ARGV.first || abort('ERROR: Please specify a directory.')
+dir_path = File.expand_path(dir_name, "#{__dir__}/..")
+
+if Dir.exist?(dir_path)
+ abort("ERROR: This repository contains #{dir_name}/ directory. #{dir_name.upcase} changes should go to the corresponding repository.")
+end
diff --git a/scripts/no-ee-check b/scripts/no-ee-check
deleted file mode 100755
index a878a4424e9..00000000000
--- a/scripts/no-ee-check
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env ruby
-# frozen_string_literal: true
-
-ee_path = File.join(File.expand_path(__dir__), '../ee')
-
-if Dir.exist?(ee_path)
- puts 'The repository contains /ee directory. There should be no /ee directory in CE repo.'
- exit 1
-end
diff --git a/scripts/pipeline_test_report_builder.rb b/scripts/pipeline_test_report_builder.rb
new file mode 100755
index 00000000000..2101decf59a
--- /dev/null
+++ b/scripts/pipeline_test_report_builder.rb
@@ -0,0 +1,153 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'optparse'
+require 'time'
+require 'fileutils'
+require 'uri'
+require 'cgi'
+require 'net/http'
+require 'json'
+require_relative 'api/default_options'
+
+# Request list of pipelines for MR
+# https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab/merge_requests/69053/pipelines
+# Find latest failed pipeline
+# Retrieve list of failed builds for test stage in pipeline
+# https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab/pipelines/363788864/jobs/?scope=failed
+# Retrieve test reports for these builds
+# https://gitlab.com/gitlab-org/gitlab/-/pipelines/363788864/tests/suite.json?build_ids[]=1555608749
+# Push into expected format for failed tests
+class PipelineTestReportBuilder
+ def initialize(options)
+ @target_project = options.delete(:target_project)
+ @mr_id = options.delete(:mr_id) || Host::DEFAULT_OPTIONS[:mr_id]
+ @instance_base_url = options.delete(:instance_base_url) || Host::DEFAULT_OPTIONS[:instance_base_url]
+ @output_file_path = options.delete(:output_file_path)
+ end
+
+ def test_report_for_latest_pipeline
+ build_test_report_json_for_pipeline(previous_pipeline)
+ end
+
+ def execute
+ if output_file_path
+ FileUtils.mkdir_p(File.dirname(output_file_path))
+ end
+
+ File.open(output_file_path, 'w') do |file|
+ file.write(test_report_for_latest_pipeline)
+ end
+ end
+
+ def previous_pipeline
+ # Top of the list will always be the current pipeline
+ # Second from top will be the previous pipeline
+ pipelines_for_mr.sort_by { |a| -Time.parse(a['created_at']).to_i }[1]
+ end
+
+ private
+
+ attr_reader :target_project, :mr_id, :instance_base_url, :output_file_path
+
+ def pipeline_project_api_base_url(pipeline)
+ "#{instance_base_url}/api/v4/projects/#{pipeline['project_id']}"
+ end
+
+ def target_project_api_base_url
+ "#{instance_base_url}/api/v4/projects/#{CGI.escape(target_project)}"
+ end
+
+ def pipelines_for_mr
+ fetch("#{target_project_api_base_url}/merge_requests/#{mr_id}/pipelines")
+ end
+
+ def failed_builds_for_pipeline(pipeline)
+ fetch("#{pipeline_project_api_base_url(pipeline)}/pipelines/#{pipeline['id']}/jobs?scope=failed&per_page=100")
+ end
+
+ # Method uses the test suite endpoint to gather test results for a particular build.
+ # Here we request individual builds, even though it is possible to supply multiple build IDs.
+ # The reason for this; it is possible to lose the job context and name when requesting multiple builds.
+ # Please see for more info: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69053#note_709939709
+ def test_report_for_build(pipeline, build_id)
+ fetch("#{pipeline['web_url']}/tests/suite.json?build_ids[]=#{build_id}")
+ end
+
+ def build_test_report_json_for_pipeline(pipeline)
+ # empty file if no previous failed pipeline
+ return {}.to_json if pipeline.nil? || pipeline['status'] != 'failed'
+
+ test_report = {}
+
+ puts "Discovered last failed pipeline (#{pipeline['id']}) for MR!#{mr_id}"
+
+ failed_builds_for_test_stage = failed_builds_for_pipeline(pipeline).select do |failed_build|
+ failed_build['stage'] == 'test'
+ end
+
+ puts "#{failed_builds_for_test_stage.length} failed builds in test stage found..."
+
+ if failed_builds_for_test_stage.any?
+ test_report['suites'] ||= []
+
+ failed_builds_for_test_stage.each do |failed_build|
+ test_report['suites'] << test_report_for_build(pipeline, failed_build['id'])
+ end
+ end
+
+ test_report.to_json
+ end
+
+ def fetch(uri_str)
+ uri = URI(uri_str)
+
+ puts "URL: #{uri}"
+
+ request = Net::HTTP::Get.new(uri)
+
+ body = ''
+
+ Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
+ http.request(request) do |response|
+ case response
+ when Net::HTTPSuccess
+ body = response.read_body
+ else
+ raise "Unexpected response: #{response.value}"
+ end
+ end
+ end
+
+ JSON.parse(body)
+ end
+end
+
+if $0 == __FILE__
+ options = Host::DEFAULT_OPTIONS.dup
+
+ OptionParser.new do |opts|
+ opts.on("-t", "--target-project TARGET_PROJECT", String, "Project where to find the merge request") do |value|
+ options[:target_project] = value
+ end
+
+ opts.on("-m", "--mr-id MR_ID", String, "A merge request ID") do |value|
+ options[:mr_id] = value
+ end
+
+ opts.on("-i", "--instance-base-url INSTANCE_BASE_URL", String, "URL of the instance where project and merge request resides") do |value|
+ options[:instance_base_url] = value
+ end
+
+ opts.on("-o", "--output-file-path OUTPUT_PATH", String, "A path for output file") do |value|
+ options[:output_file_path] = value
+ end
+
+ opts.on("-h", "--help", "Prints this help") do
+ puts opts
+ exit
+ end
+ end.parse!
+
+ PipelineTestReportBuilder.new(options).execute
+end
diff --git a/scripts/regenerate-schema b/scripts/regenerate-schema
index 485bb2d5505..06230942dcd 100755
--- a/scripts/regenerate-schema
+++ b/scripts/regenerate-schema
@@ -126,7 +126,7 @@ class SchemaRegenerator
# In order to properly reset the database and re-run migrations
# the schema migrations for new migrations must be removed.
def remove_schema_migration_files
- (untracked_schema_migrations + commited_schema_migrations).each do |schema_migration|
+ (untracked_schema_migrations + committed_schema_migrations).each do |schema_migration|
FileUtils.rm(schema_migration)
end
end
@@ -144,7 +144,7 @@ class SchemaRegenerator
# List of untracked schema migrations
#
# Get a list of schema migrations that have been committed since the last
- def commited_schema_migrations
+ def committed_schema_migrations
git_command = "git diff --name-only --diff-filter=A #{merge_base} -- #{SCHEMA_MIGRATIONS_DIR}"
run(git_command).chomp.split("\n")
end
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index 8ec26e7ba89..edb55a83555 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -10,7 +10,12 @@ function deploy_exists() {
helm status --namespace "${namespace}" "${release}" >/dev/null 2>&1
deploy_exists=$?
- echoinfo "Deployment status for ${release} is ${deploy_exists}"
+ if [ $deploy_exists -eq 0 ]; then
+ echoinfo "Previous deployment for ${release} found."
+ else
+ echoerr "Previous deployment for ${release} NOT found."
+ fi
+
return $deploy_exists
}
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index accc52a7ece..cabd2e6380c 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -26,6 +26,8 @@ function retrieve_tests_metadata() {
fi
if [[ ! -f "${FLAKY_RSPEC_SUITE_REPORT_PATH}" ]]; then
+ # Fixed ID to get the report back to a good state after https://gitlab.com/gitlab-org/gitlab/-/issues/345798 / https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74617
+ test_metadata_job_id=1766932099
scripts/api/download_job_artifact.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" --job-id "${test_metadata_job_id}" --artifact-path "${FLAKY_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
fi
fi
@@ -89,6 +91,25 @@ function crystalball_rspec_data_exists() {
compgen -G "crystalball/rspec*.yml" >/dev/null
}
+function retrieve_previous_failed_tests() {
+ local directory_for_output_reports="${1}"
+ local rspec_pg_regex="${2}"
+ local rspec_ee_pg_regex="${3}"
+ local pipeline_report_path="test_results/previous/test_reports.json"
+
+ # Used to query merge requests. This variable reflects where the merge request has been created
+ local target_project_path="${CI_MERGE_REQUEST_PROJECT_PATH}"
+ local instance_url="${CI_SERVER_URL}"
+
+ echo 'Attempting to build pipeline test report...'
+
+ scripts/pipeline_test_report_builder.rb --instance-base-url "${instance_url}" --target-project "${target_project_path}" --mr-id "${CI_MERGE_REQUEST_IID}" --output-file-path "${pipeline_report_path}"
+
+ echo 'Generating failed tests lists...'
+
+ scripts/failed_tests.rb --previous-tests-report-path "${pipeline_report_path}" --output-directory "${directory_for_output_reports}" --rspec-pg-regex "${rspec_pg_regex}" --rspec-ee-pg-regex "${rspec_ee_pg_regex}"
+}
+
function rspec_simple_job() {
local rspec_opts="${1}"
@@ -140,6 +161,7 @@ function rspec_paralellized_job() {
fi
echo "KNAPSACK_TEST_FILE_PATTERN: ${KNAPSACK_TEST_FILE_PATTERN}"
+ echo "SKIP_FLAKY_TESTS_AUTOMATICALLY: ${SKIP_FLAKY_TESTS_AUTOMATICALLY}"
if [[ -d "ee/" ]]; then
export KNAPSACK_GENERATE_REPORT="true"
@@ -147,6 +169,7 @@ function rspec_paralellized_job() {
export SUITE_FLAKY_RSPEC_REPORT_PATH="${FLAKY_RSPEC_SUITE_REPORT_PATH}"
export FLAKY_RSPEC_REPORT_PATH="rspec_flaky/all_${report_name}_report.json"
export NEW_FLAKY_RSPEC_REPORT_PATH="rspec_flaky/new_${report_name}_report.json"
+ export SKIPPED_FLAKY_TESTS_REPORT_PATH="rspec_flaky/skipped_flaky_tests_${report_name}_report.txt"
if [[ ! -f $FLAKY_RSPEC_REPORT_PATH ]]; then
echo "{}" > "${FLAKY_RSPEC_REPORT_PATH}"
@@ -172,6 +195,25 @@ function rspec_paralellized_job() {
date
}
+function rspec_rerun_previous_failed_tests() {
+ local test_file_count_threshold=${RSPEC_PREVIOUS_FAILED_TEST_FILE_COUNT_THRESHOLD:-10}
+ local matching_tests_file=${1}
+ local rspec_opts=${2}
+ local test_files="$(cat "${matching_tests_file}")"
+ local test_file_count=$(wc -w "${matching_tests_file}" | awk {'print $1'})
+
+ if [[ "${test_file_count}" -gt "${test_file_count_threshold}" ]]; then
+ echo "This job is intentionally exited because there are more than ${test_file_count_threshold} test files to rerun."
+ exit 0
+ fi
+
+ if [[ -n $test_files ]]; then
+ rspec_simple_job "${test_files}"
+ else
+ echo "No failed test files to rerun"
+ fi
+}
+
function rspec_fail_fast() {
local test_file_count_threshold=${RSPEC_FAIL_FAST_TEST_FILE_COUNT_THRESHOLD:-10}
local matching_tests_file=${1}
diff --git a/scripts/schema_changed.sh b/scripts/schema_changed.sh
index f564f717e95..2fcb85df75b 100755
--- a/scripts/schema_changed.sh
+++ b/scripts/schema_changed.sh
@@ -1,25 +1,21 @@
#!/bin/sh
-schema_changed() {
- if [ ! -z "$(git diff --name-only -- db/structure.sql)" ]; then
- printf "Schema changes are not cleanly committed to db/structure.sql\n"
- printf "The diff is as follows:\n"
- diff=$(git diff -p --binary -- db/structure.sql)
- printf "%s" "$diff"
- exit 1
- else
- printf "Schema changes are correctly applied to db/structure.sql\n"
- fi
+if [ -n "$(git diff --name-only -- db/structure.sql)" ]; then
+ printf "Schema changes are not cleanly committed to db/structure.sql\n"
+ printf "The diff is as follows:\n"
+ diff=$(git diff -p --binary -- db/structure.sql)
+ printf "%s" "$diff"
+ exit 1
+else
+ printf "Schema changes are correctly applied to db/structure.sql\n"
+fi
- if [ ! -z "$(git add -A -n db/schema_migrations)" ]; then
- printf "Schema version files have not been committed to the repository:\n"
- printf "The following files should be committed:\n"
- diff=$(git add -A -n db/schema_migrations)
- printf "%s" "$diff"
- exit 2
- else
- printf "Schema changes are correctly applied to db/structure.sql and db/schema_migrations/\n"
- fi
-}
-
-schema_changed
+if [ -n "$(git add -A -n db/schema_migrations)" ]; then
+ printf "Schema version files have not been committed to the repository:\n"
+ printf "The following files should be committed:\n"
+ diff=$(git add -A -n db/schema_migrations)
+ printf "%s" "$diff"
+ exit 2
+else
+ printf "Schema changes are correctly applied to db/structure.sql and db/schema_migrations/\n"
+fi
diff --git a/scripts/security-harness b/scripts/security-harness
index ec062fc17cc..df499be23f5 100755
--- a/scripts/security-harness
+++ b/scripts/security-harness
@@ -4,7 +4,6 @@
require 'digest'
require 'fileutils'
-require 'open3'
if ENV['NO_COLOR']
SHELL_RED = ''
@@ -19,7 +18,7 @@ else
end
LEFTHOOK_GLOBAL_CONFIG_PATH = File.expand_path("../lefthook.yml", __dir__)
-HOOK_PATH = Open3.capture3("git rev-parse --path-format=absolute --git-path hooks/pre-push")[0].strip
+HOOK_PATH = `git rev-parse --path-format=absolute --git-path hooks/pre-push`.split.last
HOOK_DATA = <<~HOOK
#!/usr/bin/env bash
diff --git a/scripts/static-analysis b/scripts/static-analysis
index f50e4a24b58..9c6a948adc1 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -43,13 +43,7 @@ class StaticAnalysis
# contain values that a FOSS installation won't find. To work
# around this we will only enable this task on EE installations.
TASKS_WITH_DURATIONS_SECONDS = [
- Task.new(%w[bin/rake lint:haml], 562),
- # We need to disable the cache for this cop since it creates files under tmp/feature_flags/*.used,
- # the cache would prevent these files from being created.
- Task.new(%w[bundle exec rubocop --only Gitlab/MarkUsedFeatureFlags --cache false], 400),
(Gitlab.ee? ? Task.new(%w[bin/rake gettext:updated_check], 360) : nil),
- Task.new(%w[yarn run lint:eslint:all], 312),
- Task.new(%w[bundle exec rubocop --parallel], 60),
Task.new(%w[yarn run lint:prettier], 160),
Task.new(%w[bin/rake gettext:lint], 85),
Task.new(%W[bundle exec license_finder --decisions-file config/dependency_decisions.yml --project-path #{project_path}], 20),
diff --git a/scripts/trigger-build b/scripts/trigger-build
index 5af45ec09f2..e5fa55f8582 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build
@@ -154,7 +154,8 @@ module Trigger
'SECURITY_SOURCES' => Trigger.security? ? 'true' : 'false',
'ee' => Trigger.ee? ? 'true' : 'false',
'QA_BRANCH' => ENV['QA_BRANCH'] || 'master',
- 'CACHE_UPDATE' => ENV['OMNIBUS_GITLAB_CACHE_UPDATE']
+ 'CACHE_UPDATE' => ENV['OMNIBUS_GITLAB_CACHE_UPDATE'],
+ 'GITLAB_QA_OPTIONS' => ENV['GITLAB_QA_OPTIONS']
}
end
end
diff --git a/scripts/used-feature-flags b/scripts/used-feature-flags
index e6a8149da71..7d81e4b2cb2 100755
--- a/scripts/used-feature-flags
+++ b/scripts/used-feature-flags
@@ -27,7 +27,8 @@ flags_paths = [
]
# For EE additionally process `ee/` feature flags
-if File.exist?('ee/app/models/license.rb') && !%w[true 1].include?(ENV['FOSS_ONLY'].to_s)
+is_ee = File.exist?('ee/app/models/license.rb') && !%w[true 1].include?(ENV['FOSS_ONLY'].to_s)
+if is_ee
flags_paths << 'ee/config/feature_flags/**/*.yml'
# Geo feature flags are constructed dynamically and there's no explicit checks in the codebase so we mark all
@@ -41,6 +42,19 @@ if File.exist?('ee/app/models/license.rb') && !%w[true 1].include?(ENV['FOSS_ONL
end
end
+# For JH additionally process `jh/` feature flags
+is_jh = is_ee && Dir.exist?('jh') && !%w[true 1].include?(ENV['EE_ONLY'].to_s)
+if is_jh
+ flags_paths << 'jh/config/feature_flags/**/*.yml'
+
+ Dir.glob('jh/app/replicators/geo/*_replicator.rb').each_with_object(Set.new) do |path, memo|
+ replicator_name = File.basename(path, '.rb')
+ feature_flag_name = "geo_#{replicator_name.delete_suffix('_replicator')}_replication"
+
+ FileUtils.touch(File.join('tmp', 'feature_flags', "#{feature_flag_name}.used"))
+ end
+end
+
all_flags = {}
additional_flags = Set.new
diff --git a/scripts/utils.sh b/scripts/utils.sh
index faabc151963..ed27edcadb2 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -172,5 +172,5 @@ function danger_as_local() {
# Force danger to skip CI source GitLab and fallback to "local only git repo".
unset GITLAB_CI
# We need to base SHA to help danger determine the base commit for this shallow clone.
- bundle exec danger dry_run --fail-on-errors=true --verbose --base="${CI_MERGE_REQUEST_DIFF_BASE_SHA}"
+ bundle exec danger dry_run --fail-on-errors=true --verbose --base="${CI_MERGE_REQUEST_DIFF_BASE_SHA}" --head="${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA:-$CI_COMMIT_SHA}"
}
diff --git a/scripts/verify-tff-mapping b/scripts/verify-tff-mapping
index ee86f9ecde5..b09fd09a737 100755
--- a/scripts/verify-tff-mapping
+++ b/scripts/verify-tff-mapping
@@ -102,8 +102,8 @@ tests = [
{
explanation: 'Migration should map to its non-timestamped spec',
- source: 'db/migrate/20200116175538_update_timestamp_softwarelicensespolicy.rb',
- expected: ['spec/migrations/update_timestamp_softwarelicensespolicy_spec.rb']
+ source: 'db/migrate/20210818220234_add_default_project_approval_rules_vuln_allowed.rb',
+ expected: ['spec/migrations/add_default_project_approval_rules_vuln_allowed_spec.rb']
},
{
diff --git a/sidekiq_cluster/cli.rb b/sidekiq_cluster/cli.rb
new file mode 100644
index 00000000000..55b4521d37d
--- /dev/null
+++ b/sidekiq_cluster/cli.rb
@@ -0,0 +1,224 @@
+# frozen_string_literal: true
+
+require 'optparse'
+require 'logger'
+require 'time'
+
+# In environments where code is preloaded and cached such as `spring`,
+# we may run into "already initialized" warnings, hence the check.
+require_relative '../lib/gitlab' unless Object.const_defined?('Gitlab')
+require_relative '../lib/gitlab/utils'
+require_relative '../lib/gitlab/sidekiq_config/cli_methods'
+require_relative '../lib/gitlab/sidekiq_config/worker_matcher'
+require_relative '../lib/gitlab/sidekiq_logging/json_formatter'
+require_relative 'sidekiq_cluster'
+
+module Gitlab
+ module SidekiqCluster
+ class CLI
+ CommandError = Class.new(StandardError)
+
+ def initialize(log_output = $stderr)
+ # As recommended by https://github.com/mperham/sidekiq/wiki/Advanced-Options#concurrency
+ @max_concurrency = 50
+ @min_concurrency = 0
+ @environment = ENV['RAILS_ENV'] || 'development'
+ @pid = nil
+ @interval = 5
+ @alive = true
+ @processes = []
+ @logger = Logger.new(log_output)
+ @logger.formatter = ::Gitlab::SidekiqLogging::JSONFormatter.new
+ @rails_path = Dir.pwd
+ @dryrun = false
+ @list_queues = false
+ end
+
+ def run(argv = ARGV)
+ if argv.empty?
+ raise CommandError,
+ 'You must specify at least one queue to start a worker for'
+ end
+
+ option_parser.parse!(argv)
+
+ if @dryrun && @list_queues
+ raise CommandError,
+ 'The --dryrun and --list-queues options are mutually exclusive'
+ end
+
+ worker_metadatas = SidekiqConfig::CliMethods.worker_metadatas(@rails_path)
+ worker_queues = SidekiqConfig::CliMethods.worker_queues(@rails_path)
+
+ queue_groups = argv.map do |queues_or_query_string|
+ if queues_or_query_string =~ /[\r\n]/
+ raise CommandError,
+ 'The queue arguments cannot contain newlines'
+ end
+
+ next worker_queues if queues_or_query_string == SidekiqConfig::WorkerMatcher::WILDCARD_MATCH
+
+ # When using the queue query syntax, we treat each queue group
+ # as a worker attribute query, and resolve the queues for the
+ # queue group using this query.
+
+ if @queue_selector
+ SidekiqConfig::CliMethods.query_queues(queues_or_query_string, worker_metadatas)
+ else
+ SidekiqConfig::CliMethods.expand_queues(queues_or_query_string.split(','), worker_queues)
+ end
+ end
+
+ if @negate_queues
+ queue_groups.map! { |queues| worker_queues - queues }
+ end
+
+ if queue_groups.all?(&:empty?)
+ raise CommandError,
+ 'No queues found, you must select at least one queue'
+ end
+
+ if @list_queues
+ puts queue_groups.map(&:sort) # rubocop:disable Rails/Output
+
+ return
+ end
+
+ unless @dryrun
+ @logger.info("Starting cluster with #{queue_groups.length} processes")
+ end
+
+ @processes = SidekiqCluster.start(
+ queue_groups,
+ env: @environment,
+ directory: @rails_path,
+ max_concurrency: @max_concurrency,
+ min_concurrency: @min_concurrency,
+ dryrun: @dryrun,
+ timeout: soft_timeout_seconds
+ )
+
+ return if @dryrun
+
+ write_pid
+ trap_signals
+ start_loop
+ end
+
+ def write_pid
+ SidekiqCluster.write_pid(@pid) if @pid
+ end
+
+ def soft_timeout_seconds
+ @soft_timeout_seconds || DEFAULT_SOFT_TIMEOUT_SECONDS
+ end
+
+ # The amount of time it'll wait for killing the alive Sidekiq processes.
+ def hard_timeout_seconds
+ soft_timeout_seconds + DEFAULT_HARD_TIMEOUT_SECONDS
+ end
+
+ def monotonic_time
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second)
+ end
+
+ def continue_waiting?(deadline)
+ SidekiqCluster.any_alive?(@processes) && monotonic_time < deadline
+ end
+
+ def hard_stop_stuck_pids
+ SidekiqCluster.signal_processes(SidekiqCluster.pids_alive(@processes), "-KILL")
+ end
+
+ def wait_for_termination
+ deadline = monotonic_time + hard_timeout_seconds
+ sleep(CHECK_TERMINATE_INTERVAL_SECONDS) while continue_waiting?(deadline)
+
+ hard_stop_stuck_pids
+ end
+
+ def trap_signals
+ SidekiqCluster.trap_terminate do |signal|
+ @alive = false
+ SidekiqCluster.signal_processes(@processes, signal)
+ wait_for_termination
+ end
+
+ SidekiqCluster.trap_forward do |signal|
+ SidekiqCluster.signal_processes(@processes, signal)
+ end
+ end
+
+ def start_loop
+ while @alive
+ sleep(@interval)
+
+ unless SidekiqCluster.all_alive?(@processes)
+ # If a child process died we'll just terminate the whole cluster. It's up to
+ # runit and such to then restart the cluster.
+ @logger.info('A worker terminated, shutting down the cluster')
+
+ SidekiqCluster.signal_processes(@processes, :TERM)
+ break
+ end
+ end
+ end
+
+ def option_parser
+ OptionParser.new do |opt|
+ opt.banner = "#{File.basename(__FILE__)} [QUEUE,QUEUE] [QUEUE] ... [OPTIONS]"
+
+ opt.separator "\nOptions:\n"
+
+ opt.on('-h', '--help', 'Shows this help message') do
+ abort opt.to_s
+ end
+
+ opt.on('-m', '--max-concurrency INT', 'Maximum threads to use with Sidekiq (default: 50, 0 to disable)') do |int|
+ @max_concurrency = int.to_i
+ end
+
+ opt.on('--min-concurrency INT', 'Minimum threads to use with Sidekiq (default: 0)') do |int|
+ @min_concurrency = int.to_i
+ end
+
+ opt.on('-e', '--environment ENV', 'The application environment') do |env|
+ @environment = env
+ end
+
+ opt.on('-P', '--pidfile PATH', 'Path to the PID file') do |pid|
+ @pid = pid
+ end
+
+ opt.on('-r', '--require PATH', 'Location of the Rails application') do |path|
+ @rails_path = path
+ end
+
+ opt.on('--queue-selector', 'Run workers based on the provided selector') do |queue_selector|
+ @queue_selector = queue_selector
+ end
+
+ opt.on('-n', '--negate', 'Run workers for all queues in sidekiq_queues.yml except the given ones') do
+ @negate_queues = true
+ end
+
+ opt.on('-i', '--interval INT', 'The number of seconds to wait between worker checks') do |int|
+ @interval = int.to_i
+ end
+
+ opt.on('-t', '--timeout INT', 'Graceful timeout for all running processes') do |timeout|
+ @soft_timeout_seconds = timeout.to_i
+ end
+
+ opt.on('-d', '--dryrun', 'Print commands that would be run without this flag, and quit') do |int|
+ @dryrun = true
+ end
+
+ opt.on('--list-queues', 'List matching queues, and quit') do |int|
+ @list_queues = true
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/sidekiq_cluster/dependencies.rb b/sidekiq_cluster/dependencies.rb
new file mode 100644
index 00000000000..91e91475f15
--- /dev/null
+++ b/sidekiq_cluster/dependencies.rb
@@ -0,0 +1,6 @@
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+require 'shellwords'
+
+# rubocop:enable Naming/FileName
diff --git a/sidekiq_cluster/sidekiq_cluster.rb b/sidekiq_cluster/sidekiq_cluster.rb
new file mode 100644
index 00000000000..49478ba740d
--- /dev/null
+++ b/sidekiq_cluster/sidekiq_cluster.rb
@@ -0,0 +1,184 @@
+# frozen_string_literal: true
+
+require_relative 'dependencies'
+
+module Gitlab
+ module SidekiqCluster
+ CHECK_TERMINATE_INTERVAL_SECONDS = 1
+
+ # How long to wait when asking for a clean termination.
+ # It maps the Sidekiq default timeout:
+ # https://github.com/mperham/sidekiq/wiki/Signals#term
+ #
+ # This value is passed to Sidekiq's `-t` if none
+ # is given through arguments.
+ DEFAULT_SOFT_TIMEOUT_SECONDS = 25
+
+ # After surpassing the soft timeout.
+ DEFAULT_HARD_TIMEOUT_SECONDS = 5
+
+ # The signals that should terminate both the master and workers.
+ TERMINATE_SIGNALS = %i(INT TERM).freeze
+
+ # The signals that should simply be forwarded to the workers.
+ FORWARD_SIGNALS = %i(TTIN USR1 USR2 HUP).freeze
+
+ # Traps the given signals and yields the block whenever these signals are
+ # received.
+ #
+ # The block is passed the name of the signal.
+ #
+ # Example:
+ #
+ # trap_signals(%i(HUP TERM)) do |signal|
+ # ...
+ # end
+ def self.trap_signals(signals)
+ signals.each do |signal|
+ trap(signal) do
+ yield signal
+ end
+ end
+ end
+
+ def self.trap_terminate(&block)
+ trap_signals(TERMINATE_SIGNALS, &block)
+ end
+
+ def self.trap_forward(&block)
+ trap_signals(FORWARD_SIGNALS, &block)
+ end
+
+ def self.signal(pid, signal)
+ Process.kill(signal, pid)
+ true
+ rescue Errno::ESRCH
+ false
+ end
+
+ def self.signal_processes(pids, signal)
+ pids.each { |pid| signal(pid, signal) }
+ end
+
+ # Starts Sidekiq workers for the pairs of processes.
+ #
+ # Example:
+ #
+ # start([ ['foo'], ['bar', 'baz'] ], :production)
+ #
+ # This would start two Sidekiq processes: one processing "foo", and one
+ # processing "bar" and "baz". Each one is placed in its own process group.
+ #
+ # queues - An Array containing Arrays. Each sub Array should specify the
+ # queues to use for a single process.
+ #
+ # directory - The directory of the Rails application.
+ #
+ # Returns an Array containing the PIDs of the started processes.
+ def self.start(queues, env: :development, directory: Dir.pwd, max_concurrency: 50, min_concurrency: 0, timeout: DEFAULT_SOFT_TIMEOUT_SECONDS, dryrun: false)
+ queues.map.with_index do |pair, index|
+ start_sidekiq(pair, env: env,
+ directory: directory,
+ max_concurrency: max_concurrency,
+ min_concurrency: min_concurrency,
+ worker_id: index,
+ timeout: timeout,
+ dryrun: dryrun)
+ end
+ end
+
+ # Starts a Sidekiq process that processes _only_ the given queues.
+ #
+ # Returns the PID of the started process.
+ def self.start_sidekiq(queues, env:, directory:, max_concurrency:, min_concurrency:, worker_id:, timeout:, dryrun:)
+ counts = count_by_queue(queues)
+
+ cmd = %w[bundle exec sidekiq]
+ cmd << "-c#{self.concurrency(queues, min_concurrency, max_concurrency)}"
+ cmd << "-e#{env}"
+ cmd << "-t#{timeout}"
+ cmd << "-gqueues:#{proc_details(counts)}"
+ cmd << "-r#{directory}"
+
+ counts.each do |queue, count|
+ cmd << "-q#{queue},#{count}"
+ end
+
+ if dryrun
+ puts Shellwords.join(cmd) # rubocop:disable Rails/Output
+ return
+ end
+
+ pid = Process.spawn(
+ { 'ENABLE_SIDEKIQ_CLUSTER' => '1',
+ 'SIDEKIQ_WORKER_ID' => worker_id.to_s },
+ *cmd,
+ pgroup: true,
+ err: $stderr,
+ out: $stdout
+ )
+
+ wait_async(pid)
+
+ pid
+ end
+
+ def self.count_by_queue(queues)
+ queues.tally
+ end
+
+ def self.proc_details(counts)
+ counts.map do |queue, count|
+ if count == 1
+ queue
+ else
+ "#{queue} (#{count})"
+ end
+ end.join(',')
+ end
+
+ def self.concurrency(queues, min_concurrency, max_concurrency)
+ concurrency_from_queues = queues.length + 1
+ max = max_concurrency > 0 ? max_concurrency : concurrency_from_queues
+ min = [min_concurrency, max].min
+
+ concurrency_from_queues.clamp(min, max)
+ end
+
+ # Waits for the given process to complete using a separate thread.
+ def self.wait_async(pid)
+ Thread.new do
+ Process.wait(pid) rescue Errno::ECHILD
+ end
+ end
+
+ # Returns true if all the processes are alive.
+ def self.all_alive?(pids)
+ pids.each do |pid|
+ return false unless process_alive?(pid)
+ end
+
+ true
+ end
+
+ def self.any_alive?(pids)
+ pids_alive(pids).any?
+ end
+
+ def self.pids_alive(pids)
+ pids.select { |pid| process_alive?(pid) }
+ end
+
+ def self.process_alive?(pid)
+ # Signal 0 tests whether the process exists and we have access to send signals
+ # but is otherwise a noop (doesn't actually send a signal to the process)
+ signal(pid, 0)
+ end
+
+ def self.write_pid(path)
+ File.open(path, 'w') do |handle|
+ handle.write(Process.pid.to_s)
+ end
+ end
+ end
+end
diff --git a/spec/commands/sidekiq_cluster/cli_spec.rb b/spec/commands/sidekiq_cluster/cli_spec.rb
new file mode 100644
index 00000000000..baa4a2b4ec3
--- /dev/null
+++ b/spec/commands/sidekiq_cluster/cli_spec.rb
@@ -0,0 +1,336 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+
+require_relative '../../../sidekiq_cluster/cli'
+
+RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath
+ let(:cli) { described_class.new('/dev/null') }
+ let(:timeout) { Gitlab::SidekiqCluster::DEFAULT_SOFT_TIMEOUT_SECONDS }
+ let(:default_options) do
+ { env: 'test', directory: Dir.pwd, max_concurrency: 50, min_concurrency: 0, dryrun: false, timeout: timeout }
+ end
+
+ before do
+ stub_env('RAILS_ENV', 'test')
+ end
+
+ describe '#run' do
+ context 'without any arguments' do
+ it 'raises CommandError' do
+ expect { cli.run([]) }.to raise_error(described_class::CommandError)
+ end
+ end
+
+ context 'with arguments' do
+ before do
+ allow(cli).to receive(:write_pid)
+ allow(cli).to receive(:trap_signals)
+ allow(cli).to receive(:start_loop)
+ end
+
+ it 'starts the Sidekiq workers' do
+ expect(Gitlab::SidekiqCluster).to receive(:start)
+ .with([['foo']], default_options)
+ .and_return([])
+
+ cli.run(%w(foo))
+ end
+
+ it 'allows the special * selector' do
+ worker_queues = %w(foo bar baz)
+
+ expect(Gitlab::SidekiqConfig::CliMethods)
+ .to receive(:worker_queues).and_return(worker_queues)
+
+ expect(Gitlab::SidekiqCluster)
+ .to receive(:start).with([worker_queues], default_options)
+
+ cli.run(%w(*))
+ end
+
+ it 'raises an error when the arguments contain newlines' do
+ invalid_arguments = [
+ ["foo\n"],
+ ["foo\r"],
+ %W[foo b\nar]
+ ]
+
+ invalid_arguments.each do |arguments|
+ expect { cli.run(arguments) }.to raise_error(described_class::CommandError)
+ end
+ end
+
+ context 'with --negate flag' do
+ it 'starts Sidekiq workers for all queues in all_queues.yml except the ones in argv' do
+ expect(Gitlab::SidekiqConfig::CliMethods).to receive(:worker_queues).and_return(['baz'])
+ expect(Gitlab::SidekiqCluster).to receive(:start)
+ .with([['baz']], default_options)
+ .and_return([])
+
+ cli.run(%w(foo -n))
+ end
+ end
+
+ context 'with --max-concurrency flag' do
+ it 'starts Sidekiq workers for specified queues with a max concurrency' do
+ expect(Gitlab::SidekiqConfig::CliMethods).to receive(:worker_queues).and_return(%w(foo bar baz))
+ expect(Gitlab::SidekiqCluster).to receive(:start)
+ .with([%w(foo bar baz), %w(solo)], default_options.merge(max_concurrency: 2))
+ .and_return([])
+
+ cli.run(%w(foo,bar,baz solo -m 2))
+ end
+ end
+
+ context 'with --min-concurrency flag' do
+ it 'starts Sidekiq workers for specified queues with a min concurrency' do
+ expect(Gitlab::SidekiqConfig::CliMethods).to receive(:worker_queues).and_return(%w(foo bar baz))
+ expect(Gitlab::SidekiqCluster).to receive(:start)
+ .with([%w(foo bar baz), %w(solo)], default_options.merge(min_concurrency: 2))
+ .and_return([])
+
+ cli.run(%w(foo,bar,baz solo --min-concurrency 2))
+ end
+ end
+
+ context 'with --timeout flag' do
+ it 'when given', 'starts Sidekiq workers with given timeout' do
+ expect(Gitlab::SidekiqCluster).to receive(:start)
+ .with([['foo']], default_options.merge(timeout: 10))
+
+ cli.run(%w(foo --timeout 10))
+ end
+
+ it 'when not given', 'starts Sidekiq workers with default timeout' do
+ expect(Gitlab::SidekiqCluster).to receive(:start)
+ .with([['foo']], default_options.merge(timeout: Gitlab::SidekiqCluster::DEFAULT_SOFT_TIMEOUT_SECONDS))
+
+ cli.run(%w(foo))
+ end
+ end
+
+ context 'with --list-queues flag' do
+ it 'errors when given --list-queues and --dryrun' do
+ expect { cli.run(%w(foo --list-queues --dryrun)) }.to raise_error(described_class::CommandError)
+ end
+
+ it 'prints out a list of queues in alphabetical order' do
+ expected_queues = [
+ 'epics:epics_update_epics_dates',
+ 'epics_new_epic_issue',
+ 'new_epic',
+ 'todos_destroyer:todos_destroyer_confidential_epic'
+ ]
+
+ allow(Gitlab::SidekiqConfig::CliMethods).to receive(:query_queues).and_return(expected_queues.shuffle)
+
+ expect(cli).to receive(:puts).with([expected_queues])
+
+ cli.run(%w(--queue-selector feature_category=epics --list-queues))
+ end
+ end
+
+ context 'queue namespace expansion' do
+ it 'starts Sidekiq workers for all queues in all_queues.yml with a namespace in argv' do
+ expect(Gitlab::SidekiqConfig::CliMethods).to receive(:worker_queues).and_return(['cronjob:foo', 'cronjob:bar'])
+ expect(Gitlab::SidekiqCluster).to receive(:start)
+ .with([['cronjob', 'cronjob:foo', 'cronjob:bar']], default_options)
+ .and_return([])
+
+ cli.run(%w(cronjob))
+ end
+ end
+
+ context "with --queue-selector" do
+ where do
+ {
+ 'memory-bound queues' => {
+ query: 'resource_boundary=memory',
+ included_queues: %w(project_export),
+ excluded_queues: %w(merge)
+ },
+ 'memory- or CPU-bound queues' => {
+ query: 'resource_boundary=memory,cpu',
+ included_queues: %w(auto_merge:auto_merge_process project_export),
+ excluded_queues: %w(merge)
+ },
+ 'high urgency CI queues' => {
+ query: 'feature_category=continuous_integration&urgency=high',
+ included_queues: %w(pipeline_cache:expire_job_cache pipeline_cache:expire_pipeline_cache),
+ excluded_queues: %w(merge)
+ },
+ 'CPU-bound high urgency CI queues' => {
+ query: 'feature_category=continuous_integration&urgency=high&resource_boundary=cpu',
+ included_queues: %w(pipeline_cache:expire_pipeline_cache),
+ excluded_queues: %w(pipeline_cache:expire_job_cache merge)
+ },
+ 'CPU-bound high urgency non-CI queues' => {
+ query: 'feature_category!=continuous_integration&urgency=high&resource_boundary=cpu',
+ included_queues: %w(new_issue),
+ excluded_queues: %w(pipeline_cache:expire_pipeline_cache)
+ },
+ 'CI and SCM queues' => {
+ query: 'feature_category=continuous_integration|feature_category=source_code_management',
+ included_queues: %w(pipeline_cache:expire_job_cache merge),
+ excluded_queues: %w(mailers)
+ }
+ }
+ end
+
+ with_them do
+ it 'expands queues by attributes' do
+ expect(Gitlab::SidekiqCluster).to receive(:start) do |queues, opts|
+ expect(opts).to eq(default_options)
+ expect(queues.first).to include(*included_queues)
+ expect(queues.first).not_to include(*excluded_queues)
+
+ []
+ end
+
+ cli.run(%W(--queue-selector #{query}))
+ end
+
+ it 'works when negated' do
+ expect(Gitlab::SidekiqCluster).to receive(:start) do |queues, opts|
+ expect(opts).to eq(default_options)
+ expect(queues.first).not_to include(*included_queues)
+ expect(queues.first).to include(*excluded_queues)
+
+ []
+ end
+
+ cli.run(%W(--negate --queue-selector #{query}))
+ end
+ end
+
+ it 'expands multiple queue groups correctly' do
+ expect(Gitlab::SidekiqCluster)
+ .to receive(:start)
+ .with([['chat_notification'], ['project_export']], default_options)
+ .and_return([])
+
+ cli.run(%w(--queue-selector feature_category=chatops&has_external_dependencies=true resource_boundary=memory&feature_category=importers))
+ end
+
+ it 'allows the special * selector' do
+ worker_queues = %w(foo bar baz)
+
+ expect(Gitlab::SidekiqConfig::CliMethods)
+ .to receive(:worker_queues).and_return(worker_queues)
+
+ expect(Gitlab::SidekiqCluster)
+ .to receive(:start).with([worker_queues], default_options)
+
+ cli.run(%w(--queue-selector *))
+ end
+
+ it 'errors when the selector matches no queues' do
+ expect(Gitlab::SidekiqCluster).not_to receive(:start)
+
+ expect { cli.run(%w(--queue-selector has_external_dependencies=true&has_external_dependencies=false)) }
+ .to raise_error(described_class::CommandError)
+ end
+
+ it 'errors on an invalid query multiple queue groups correctly' do
+ expect(Gitlab::SidekiqCluster).not_to receive(:start)
+
+ expect { cli.run(%w(--queue-selector unknown_field=chatops)) }
+ .to raise_error(Gitlab::SidekiqConfig::WorkerMatcher::QueryError)
+ end
+ end
+ end
+ end
+
+ describe '#write_pid' do
+ context 'when a PID is specified' do
+ it 'writes the PID to a file' do
+ expect(Gitlab::SidekiqCluster).to receive(:write_pid).with('/dev/null')
+
+ cli.option_parser.parse!(%w(-P /dev/null))
+ cli.write_pid
+ end
+ end
+
+ context 'when no PID is specified' do
+ it 'does not write a PID' do
+ expect(Gitlab::SidekiqCluster).not_to receive(:write_pid)
+
+ cli.write_pid
+ end
+ end
+ end
+
+ describe '#wait_for_termination' do
+ it 'waits for termination of all sub-processes and succeeds after 3 checks' do
+ expect(Gitlab::SidekiqCluster).to receive(:any_alive?)
+ .with(an_instance_of(Array)).and_return(true, true, true, false)
+
+ expect(Gitlab::SidekiqCluster).to receive(:pids_alive)
+ .with([]).and_return([])
+
+ expect(Gitlab::SidekiqCluster).to receive(:signal_processes)
+ .with([], "-KILL")
+
+ stub_const("Gitlab::SidekiqCluster::CHECK_TERMINATE_INTERVAL_SECONDS", 0.1)
+ allow(cli).to receive(:terminate_timeout_seconds) { 1 }
+
+ cli.wait_for_termination
+ end
+
+ context 'with hanging workers' do
+ before do
+ expect(cli).to receive(:write_pid)
+ expect(cli).to receive(:trap_signals)
+ expect(cli).to receive(:start_loop)
+ end
+
+ it 'hard kills workers after timeout expires' do
+ worker_pids = [101, 102, 103]
+ expect(Gitlab::SidekiqCluster).to receive(:start)
+ .with([['foo']], default_options)
+ .and_return(worker_pids)
+
+ expect(Gitlab::SidekiqCluster).to receive(:any_alive?)
+ .with(worker_pids).and_return(true).at_least(10).times
+
+ expect(Gitlab::SidekiqCluster).to receive(:pids_alive)
+ .with(worker_pids).and_return([102])
+
+ expect(Gitlab::SidekiqCluster).to receive(:signal_processes)
+ .with([102], "-KILL")
+
+ cli.run(%w(foo))
+
+ stub_const("Gitlab::SidekiqCluster::CHECK_TERMINATE_INTERVAL_SECONDS", 0.1)
+ allow(cli).to receive(:terminate_timeout_seconds) { 1 }
+
+ cli.wait_for_termination
+ end
+ end
+ end
+
+ describe '#trap_signals' do
+ it 'traps the termination and forwarding signals' do
+ expect(Gitlab::SidekiqCluster).to receive(:trap_terminate)
+ expect(Gitlab::SidekiqCluster).to receive(:trap_forward)
+
+ cli.trap_signals
+ end
+ end
+
+ describe '#start_loop' do
+ it 'runs until one of the processes has been terminated' do
+ allow(cli).to receive(:sleep).with(a_kind_of(Numeric))
+
+ expect(Gitlab::SidekiqCluster).to receive(:all_alive?)
+ .with(an_instance_of(Array)).and_return(false)
+
+ expect(Gitlab::SidekiqCluster).to receive(:signal_processes)
+ .with(an_instance_of(Array), :TERM)
+
+ cli.start_loop
+ end
+ end
+end
diff --git a/spec/controllers/admin/integrations_controller_spec.rb b/spec/controllers/admin/integrations_controller_spec.rb
index 1793b3a86d1..cf6a6385425 100644
--- a/spec/controllers/admin/integrations_controller_spec.rb
+++ b/spec/controllers/admin/integrations_controller_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Admin::IntegrationsController do
sign_in(admin)
end
- it_behaves_like IntegrationsActions do
+ it_behaves_like Integrations::Actions do
let(:integration_attributes) { { instance: true, project: nil } }
let(:routing_params) do
diff --git a/spec/controllers/admin/runners_controller_spec.rb b/spec/controllers/admin/runners_controller_spec.rb
index 996964fdcf0..b9a59e9ae5f 100644
--- a/spec/controllers/admin/runners_controller_spec.rb
+++ b/spec/controllers/admin/runners_controller_spec.rb
@@ -12,9 +12,11 @@ RSpec.describe Admin::RunnersController do
describe '#index' do
render_views
- it 'lists all runners' do
+ before do
get :index
+ end
+ it 'renders index template' do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:index)
end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index e9a49319f21..e623c1ab940 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -501,11 +501,16 @@ RSpec.describe ApplicationController do
describe '#append_info_to_payload' do
controller(described_class) do
attr_reader :last_payload
+ urgency :high, [:foo]
def index
render html: 'authenticated'
end
+ def foo
+ render html: ''
+ end
+
def append_info_to_payload(payload)
super
@@ -513,6 +518,13 @@ RSpec.describe ApplicationController do
end
end
+ before do
+ routes.draw do
+ get 'index' => 'anonymous#index'
+ get 'foo' => 'anonymous#foo'
+ end
+ end
+
it 'does not log errors with a 200 response' do
get :index
@@ -534,6 +546,22 @@ RSpec.describe ApplicationController do
expect(controller.last_payload[:metadata]).to include('meta.user' => user.username)
end
+
+ context 'urgency information' do
+ it 'adds default urgency information to the payload' do
+ get :index
+
+ expect(controller.last_payload[:request_urgency]).to eq(:default)
+ expect(controller.last_payload[:target_duration_s]).to eq(1)
+ end
+
+ it 'adds customized urgency information to the payload' do
+ get :foo
+
+ expect(controller.last_payload[:request_urgency]).to eq(:high)
+ expect(controller.last_payload[:target_duration_s]).to eq(0.25)
+ end
+ end
end
describe '#access_denied' do
@@ -895,7 +923,7 @@ RSpec.describe ApplicationController do
describe '#set_current_context' do
controller(described_class) do
- feature_category :issue_tracking
+ feature_category :team_planning
def index
Gitlab::ApplicationContext.with_raw_context do |context|
@@ -949,7 +977,7 @@ RSpec.describe ApplicationController do
it 'sets the feature_category as defined in the controller' do
get :index, format: :json
- expect(json_response['meta.feature_category']).to eq('issue_tracking')
+ expect(json_response['meta.feature_category']).to eq('team_planning')
end
it 'assigns the context to a variable for logging' do
diff --git a/spec/controllers/concerns/group_tree_spec.rb b/spec/controllers/concerns/group_tree_spec.rb
index e808f1caa6e..921706b2042 100644
--- a/spec/controllers/concerns/group_tree_spec.rb
+++ b/spec/controllers/concerns/group_tree_spec.rb
@@ -102,13 +102,5 @@ RSpec.describe GroupTree do
end
it_behaves_like 'returns filtered groups'
-
- context 'when feature flag :linear_group_tree_ancestor_scopes is disabled' do
- before do
- stub_feature_flags(linear_group_tree_ancestor_scopes: false)
- end
-
- it_behaves_like 'returns filtered groups'
- end
end
end
diff --git a/spec/controllers/concerns/import_url_params_spec.rb b/spec/controllers/concerns/import_url_params_spec.rb
index 72f13cdcc94..ddffb243f7a 100644
--- a/spec/controllers/concerns/import_url_params_spec.rb
+++ b/spec/controllers/concerns/import_url_params_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe ImportUrlParams do
let(:import_url_params) do
- controller = OpenStruct.new(params: params).extend(described_class)
+ controller = double('controller', params: params).extend(described_class)
controller.import_url_params
end
diff --git a/spec/controllers/concerns/renders_commits_spec.rb b/spec/controllers/concerns/renders_commits_spec.rb
index 5c918267f50..acdeb98bb16 100644
--- a/spec/controllers/concerns/renders_commits_spec.rb
+++ b/spec/controllers/concerns/renders_commits_spec.rb
@@ -64,6 +64,12 @@ RSpec.describe RendersCommits do
subject.prepare_commits_for_rendering(merge_request.commits.take(1))
end
+ # Populate Banzai::Filter::References::ReferenceCache
+ subject.prepare_commits_for_rendering(merge_request.commits)
+
+ # Reset lazy_latest_pipeline cache to simulate a new request
+ BatchLoader::Executor.clear_current
+
expect do
subject.prepare_commits_for_rendering(merge_request.commits)
merge_request.commits.each(&:latest_pipeline)
diff --git a/spec/controllers/confirmations_controller_spec.rb b/spec/controllers/confirmations_controller_spec.rb
index 401ee36b387..1c7f8de32bb 100644
--- a/spec/controllers/confirmations_controller_spec.rb
+++ b/spec/controllers/confirmations_controller_spec.rb
@@ -123,4 +123,45 @@ RSpec.describe ConfirmationsController do
end
end
end
+
+ describe '#create' do
+ let(:user) { create(:user) }
+
+ subject(:perform_request) { post(:create, params: { user: { email: user.email } }) }
+
+ context 'when reCAPTCHA is disabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: false)
+ end
+
+ it 'successfully sends password reset when reCAPTCHA is not solved' do
+ perform_request
+
+ expect(response).to redirect_to(dashboard_projects_path)
+ end
+ end
+
+ context 'when reCAPTCHA is enabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: true)
+ end
+
+ it 'displays an error when the reCAPTCHA is not solved' do
+ Recaptcha.configuration.skip_verify_env.delete('test')
+
+ perform_request
+
+ expect(response).to render_template(:new)
+ expect(flash[:alert]).to include 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'
+ end
+
+ it 'successfully sends password reset when reCAPTCHA is solved' do
+ Recaptcha.configuration.skip_verify_env << 'test'
+
+ perform_request
+
+ expect(response).to redirect_to(dashboard_projects_path)
+ end
+ end
+ end
end
diff --git a/spec/controllers/dashboard/todos_controller_spec.rb b/spec/controllers/dashboard/todos_controller_spec.rb
index f0aa351bee0..cf528b414c0 100644
--- a/spec/controllers/dashboard/todos_controller_spec.rb
+++ b/spec/controllers/dashboard/todos_controller_spec.rb
@@ -62,7 +62,7 @@ RSpec.describe Dashboard::TodosController do
create(:issue, project: project, assignees: [user])
group_2 = create(:group)
group_2.add_owner(user)
- project_2 = create(:project)
+ project_2 = create(:project, namespace: user.namespace)
project_2.add_developer(user)
merge_request_2 = create(:merge_request, source_project: project_2)
create(:todo, project: project, author: author, user: user, target: merge_request_2)
diff --git a/spec/controllers/explore/projects_controller_spec.rb b/spec/controllers/explore/projects_controller_spec.rb
index 2297198878d..f2328303102 100644
--- a/spec/controllers/explore/projects_controller_spec.rb
+++ b/spec/controllers/explore/projects_controller_spec.rb
@@ -74,6 +74,28 @@ RSpec.describe Explore::ProjectsController do
end
end
end
+
+ describe 'GET #topic' do
+ context 'when topic does not exist' do
+ it 'renders a 404 error' do
+ get :topic, params: { topic_name: 'topic1' }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ context 'when topic exists' do
+ before do
+ create(:topic, name: 'topic1')
+ end
+
+ it 'renders the template' do
+ get :topic, params: { topic_name: 'topic1' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template('topic')
+ end
+ end
+ end
end
shared_examples "blocks high page numbers" do
diff --git a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
index fa402d556c7..b22307578ab 100644
--- a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
+++ b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
@@ -124,6 +124,34 @@ RSpec.describe Groups::DependencyProxyForContainersController do
end
end
+ shared_examples 'authorize action with permission' do
+ context 'with a valid user' do
+ before do
+ group.add_guest(user)
+ end
+
+ it 'sends Workhorse local file instructions', :aggregate_failures do
+ subject
+
+ expect(response.headers['Content-Type']).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
+ expect(json_response['TempPath']).to eq(DependencyProxy::FileUploader.workhorse_local_upload_path)
+ expect(json_response['RemoteObject']).to be_nil
+ expect(json_response['MaximumSize']).to eq(maximum_size)
+ end
+
+ it 'sends Workhorse remote object instructions', :aggregate_failures do
+ stub_dependency_proxy_object_storage(direct_upload: true)
+
+ subject
+
+ expect(response.headers['Content-Type']).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
+ expect(json_response['TempPath']).to be_nil
+ expect(json_response['RemoteObject']).not_to be_nil
+ expect(json_response['MaximumSize']).to eq(maximum_size)
+ end
+ end
+ end
+
before do
allow(Gitlab.config.dependency_proxy)
.to receive(:enabled).and_return(true)
@@ -136,7 +164,8 @@ RSpec.describe Groups::DependencyProxyForContainersController do
end
describe 'GET #manifest' do
- let_it_be(:manifest) { create(:dependency_proxy_manifest) }
+ let_it_be(:tag) { 'latest' }
+ let_it_be(:manifest) { create(:dependency_proxy_manifest, file_name: "alpine:#{tag}.json", group: group) }
let(:pull_response) { { status: :success, manifest: manifest, from_cache: false } }
@@ -146,7 +175,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do
end
end
- subject { get_manifest }
+ subject { get_manifest(tag) }
context 'feature enabled' do
before do
@@ -207,11 +236,26 @@ RSpec.describe Groups::DependencyProxyForContainersController do
it_behaves_like 'a successful manifest pull'
it_behaves_like 'a package tracking event', described_class.name, 'pull_manifest'
- context 'with a cache entry' do
- let(:pull_response) { { status: :success, manifest: manifest, from_cache: true } }
+ context 'with workhorse response' do
+ let(:pull_response) { { status: :success, manifest: nil, from_cache: false } }
- it_behaves_like 'returning response status', :success
- it_behaves_like 'a package tracking event', described_class.name, 'pull_manifest_from_cache'
+ it 'returns Workhorse send-dependency instructions', :aggregate_failures do
+ subject
+
+ send_data_type, send_data = workhorse_send_data
+ header, url = send_data.values_at('Header', 'Url')
+
+ expect(send_data_type).to eq('send-dependency')
+ expect(header).to eq(
+ "Authorization" => ["Bearer abcd1234"],
+ "Accept" => ::ContainerRegistry::Client::ACCEPTED_TYPES
+ )
+ expect(url).to eq(DependencyProxy::Registry.manifest_url('alpine', tag))
+ expect(response.headers['Content-Type']).to eq('application/gzip')
+ expect(response.headers['Content-Disposition']).to eq(
+ ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: manifest.file_name)
+ )
+ end
end
end
@@ -237,8 +281,8 @@ RSpec.describe Groups::DependencyProxyForContainersController do
it_behaves_like 'not found when disabled'
- def get_manifest
- get :manifest, params: { group_id: group.to_param, image: 'alpine', tag: '3.9.2' }
+ def get_manifest(tag)
+ get :manifest, params: { group_id: group.to_param, image: 'alpine', tag: tag }
end
end
@@ -381,39 +425,28 @@ RSpec.describe Groups::DependencyProxyForContainersController do
end
end
- describe 'GET #authorize_upload_blob' do
+ describe 'POST #authorize_upload_blob' do
let(:blob_sha) { 'a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4' }
+ let(:maximum_size) { DependencyProxy::Blob::MAX_FILE_SIZE }
- subject(:authorize_upload_blob) do
+ subject do
request.headers.merge!(workhorse_internal_api_request_header)
- get :authorize_upload_blob, params: { group_id: group.to_param, image: 'alpine', sha: blob_sha }
+ post :authorize_upload_blob, params: { group_id: group.to_param, image: 'alpine', sha: blob_sha }
end
it_behaves_like 'without permission'
-
- context 'with a valid user' do
- before do
- group.add_guest(user)
- end
-
- it 'sends Workhorse file upload instructions', :aggregate_failures do
- authorize_upload_blob
-
- expect(response.headers['Content-Type']).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
- expect(json_response['TempPath']).to eq(DependencyProxy::FileUploader.workhorse_local_upload_path)
- end
- end
+ it_behaves_like 'authorize action with permission'
end
- describe 'GET #upload_blob' do
+ describe 'POST #upload_blob' do
let(:blob_sha) { 'a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4' }
let(:file) { fixture_file_upload("spec/fixtures/dependency_proxy/#{blob_sha}.gz", 'application/gzip') }
subject do
request.headers.merge!(workhorse_internal_api_request_header)
- get :upload_blob, params: {
+ post :upload_blob, params: {
group_id: group.to_param,
image: 'alpine',
sha: blob_sha,
@@ -436,6 +469,79 @@ RSpec.describe Groups::DependencyProxyForContainersController do
end
end
+ describe 'POST #authorize_upload_manifest' do
+ let(:maximum_size) { DependencyProxy::Manifest::MAX_FILE_SIZE }
+
+ subject do
+ request.headers.merge!(workhorse_internal_api_request_header)
+
+ post :authorize_upload_manifest, params: { group_id: group.to_param, image: 'alpine', tag: 'latest' }
+ end
+
+ it_behaves_like 'without permission'
+ it_behaves_like 'authorize action with permission'
+ end
+
+ describe 'POST #upload_manifest' do
+ let_it_be(:file) { fixture_file_upload("spec/fixtures/dependency_proxy/manifest", 'application/json') }
+ let_it_be(:image) { 'alpine' }
+ let_it_be(:tag) { 'latest' }
+ let_it_be(:content_type) { 'v2/manifest' }
+ let_it_be(:digest) { 'foo' }
+ let_it_be(:file_name) { "#{image}:#{tag}.json" }
+
+ subject do
+ request.headers.merge!(
+ workhorse_internal_api_request_header.merge!(
+ {
+ Gitlab::Workhorse::SEND_DEPENDENCY_CONTENT_TYPE_HEADER => content_type,
+ DependencyProxy::Manifest::DIGEST_HEADER => digest
+ }
+ )
+ )
+ params = {
+ group_id: group.to_param,
+ image: image,
+ tag: tag,
+ file: file,
+ file_name: file_name
+ }
+
+ post :upload_manifest, params: params
+ end
+
+ it_behaves_like 'without permission'
+
+ context 'with a valid user' do
+ before do
+ group.add_guest(user)
+ end
+
+ it_behaves_like 'a package tracking event', described_class.name, 'pull_manifest'
+
+ context 'with no existing manifest' do
+ it 'creates a manifest' do
+ expect { subject }.to change { group.dependency_proxy_manifests.count }.by(1)
+
+ manifest = group.dependency_proxy_manifests.first.reload
+ expect(manifest.content_type).to eq(content_type)
+ expect(manifest.digest).to eq(digest)
+ expect(manifest.file_name).to eq(file_name)
+ end
+ end
+
+ context 'with existing stale manifest' do
+ let_it_be(:old_digest) { 'asdf' }
+ let_it_be_with_reload(:manifest) { create(:dependency_proxy_manifest, file_name: file_name, digest: old_digest, group: group) }
+
+ it 'updates the existing manifest' do
+ expect { subject }.to change { group.dependency_proxy_manifests.count }.by(0)
+ .and change { manifest.reload.digest }.from(old_digest).to(digest)
+ end
+ end
+ end
+ end
+
def enable_dependency_proxy
group.create_dependency_proxy_setting!(enabled: true)
end
diff --git a/spec/controllers/groups/settings/integrations_controller_spec.rb b/spec/controllers/groups/settings/integrations_controller_spec.rb
index 31d1946652d..c070094babd 100644
--- a/spec/controllers/groups/settings/integrations_controller_spec.rb
+++ b/spec/controllers/groups/settings/integrations_controller_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Groups::Settings::IntegrationsController do
sign_in(user)
end
- it_behaves_like IntegrationsActions do
+ it_behaves_like Integrations::Actions do
let(:integration_attributes) { { group: group, project: nil } }
let(:routing_params) do
@@ -78,7 +78,7 @@ RSpec.describe Groups::Settings::IntegrationsController do
describe '#update' do
include JiraServiceHelper
- let(:integration) { create(:jira_integration, project: nil, group_id: group.id) }
+ let(:integration) { create(:jira_integration, :group, group: group) }
before do
group.add_owner(user)
@@ -108,7 +108,7 @@ RSpec.describe Groups::Settings::IntegrationsController do
end
describe '#reset' do
- let_it_be(:integration) { create(:jira_integration, group: group, project: nil) }
+ let_it_be(:integration) { create(:jira_integration, :group, group: group) }
let_it_be(:inheriting_integration) { create(:jira_integration, inherit_from_id: integration.id) }
subject do
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index a7625e65603..2525146c673 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -82,6 +82,16 @@ RSpec.describe GroupsController, factory_default: :keep do
expect(subject).to redirect_to group_import_path(group)
end
end
+
+ context 'publishing the invite_members_for_task experiment' do
+ it 'publishes the experiment data to the client' do
+ wrapped_experiment(experiment(:invite_members_for_task)) do |e|
+ expect(e).to receive(:publish_to_client)
+ end
+
+ get :show, params: { id: group.to_param, open_modal: 'invite_members_for_task' }, format: format
+ end
+ end
end
describe 'GET #details' do
diff --git a/spec/controllers/import/bitbucket_controller_spec.rb b/spec/controllers/import/bitbucket_controller_spec.rb
index 0427715d1ac..91e43adc472 100644
--- a/spec/controllers/import/bitbucket_controller_spec.rb
+++ b/spec/controllers/import/bitbucket_controller_spec.rb
@@ -252,6 +252,30 @@ RSpec.describe Import::BitbucketController do
end
end
end
+
+ context "when exceptions occur" do
+ shared_examples "handles exceptions" do
+ it "logs an exception" do
+ expect(Bitbucket::Client).to receive(:new).and_raise(error)
+ expect(controller).to receive(:log_exception)
+
+ post :create, format: :json
+ end
+ end
+
+ context "for OAuth2 errors" do
+ let(:fake_response) { double('Faraday::Response', headers: {}, body: '', status: 403) }
+ let(:error) { OAuth2::Error.new(OAuth2::Response.new(fake_response)) }
+
+ it_behaves_like "handles exceptions"
+ end
+
+ context "for Bitbucket errors" do
+ let(:error) { Bitbucket::Error::Unauthorized.new("error") }
+
+ it_behaves_like "handles exceptions"
+ end
+ end
end
context 'user has chosen an existing nested namespace and name for the project' do
diff --git a/spec/controllers/jira_connect/app_descriptor_controller_spec.rb b/spec/controllers/jira_connect/app_descriptor_controller_spec.rb
index 9d890efdd33..4f8b2b90637 100644
--- a/spec/controllers/jira_connect/app_descriptor_controller_spec.rb
+++ b/spec/controllers/jira_connect/app_descriptor_controller_spec.rb
@@ -90,17 +90,5 @@ RSpec.describe JiraConnect::AppDescriptorController do
)
)
end
-
- context 'when jira_connect_asymmetric_jwt is disabled' do
- before do
- stub_feature_flags(jira_connect_asymmetric_jwt: false)
- end
-
- specify do
- get :show
-
- expect(json_response).to include('apiMigrations' => include('signed-install' => false))
- end
- end
end
end
diff --git a/spec/controllers/jira_connect/events_controller_spec.rb b/spec/controllers/jira_connect/events_controller_spec.rb
index 78bd0dc8318..2a70a2ea683 100644
--- a/spec/controllers/jira_connect/events_controller_spec.rb
+++ b/spec/controllers/jira_connect/events_controller_spec.rb
@@ -77,18 +77,6 @@ RSpec.describe JiraConnect::EventsController do
expect(installation.base_url).to eq('https://test.atlassian.net')
end
- context 'when jira_connect_asymmetric_jwt is disabled' do
- before do
- stub_feature_flags(jira_connect_asymmetric_jwt: false)
- end
-
- it 'saves the jira installation data without JWT validation' do
- expect(Atlassian::JiraConnect::AsymmetricJwt).not_to receive(:new)
-
- expect { subject }.to change { JiraConnectInstallation.count }.by(1)
- end
- end
-
context 'when it is a version update and shared_secret is not sent' do
let(:params) do
{
@@ -110,22 +98,6 @@ RSpec.describe JiraConnect::EventsController do
expect { subject }.not_to change { JiraConnectInstallation.count }
expect(response).to have_gitlab_http_status(:ok)
end
-
- context 'when jira_connect_asymmetric_jwt is disabled' do
- before do
- stub_feature_flags(jira_connect_asymmetric_jwt: false)
- end
-
- it 'decodes the JWT token in authorization header and returns 200 without creating a new installation' do
- request.headers["Authorization"] = "Bearer #{Atlassian::Jwt.encode({ iss: client_key }, shared_secret)}"
-
- expect(Atlassian::JiraConnect::AsymmetricJwt).not_to receive(:new)
-
- expect { subject }.not_to change { JiraConnectInstallation.count }
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
end
end
end
@@ -153,23 +125,6 @@ RSpec.describe JiraConnect::EventsController do
it 'does not delete the installation' do
expect { post_uninstalled }.not_to change { JiraConnectInstallation.count }
end
-
- context 'when jira_connect_asymmetric_jwt is disabled' do
- before do
- stub_feature_flags(jira_connect_asymmetric_jwt: false)
- request.headers['Authorization'] = 'JWT invalid token'
- end
-
- it 'returns 403' do
- post_uninstalled
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
- it 'does not delete the installation' do
- expect { post_uninstalled }.not_to change { JiraConnectInstallation.count }
- end
- end
end
context 'when JWT is valid' do
@@ -197,36 +152,6 @@ RSpec.describe JiraConnect::EventsController do
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
-
- context 'when jira_connect_asymmetric_jwt is disabled' do
- before do
- stub_feature_flags(jira_connect_asymmetric_jwt: false)
-
- request.headers['Authorization'] = "JWT #{Atlassian::Jwt.encode({ iss: installation.client_key, qsh: qsh }, installation.shared_secret)}"
- end
-
- let(:qsh) { Atlassian::Jwt.create_query_string_hash('https://gitlab.test/events/uninstalled', 'POST', 'https://gitlab.test') }
-
- it 'calls the DestroyService and returns ok in case of success' do
- expect_next_instance_of(JiraConnectInstallations::DestroyService, installation, jira_base_path, jira_event_path) do |destroy_service|
- expect(destroy_service).to receive(:execute).and_return(true)
- end
-
- post_uninstalled
-
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'calls the DestroyService and returns unprocessable_entity in case of failure' do
- expect_next_instance_of(JiraConnectInstallations::DestroyService, installation, jira_base_path, jira_event_path) do |destroy_service|
- expect(destroy_service).to receive(:execute).and_return(false)
- end
-
- post_uninstalled
-
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- end
- end
end
end
end
diff --git a/spec/controllers/oauth/authorizations_controller_spec.rb b/spec/controllers/oauth/authorizations_controller_spec.rb
index 0e25f6a96d7..98cc8d83e0c 100644
--- a/spec/controllers/oauth/authorizations_controller_spec.rb
+++ b/spec/controllers/oauth/authorizations_controller_spec.rb
@@ -3,8 +3,7 @@
require 'spec_helper'
RSpec.describe Oauth::AuthorizationsController do
- let(:user) { create(:user, confirmed_at: confirmed_at) }
- let(:confirmed_at) { 1.hour.ago }
+ let(:user) { create(:user) }
let!(:application) { create(:oauth_application, scopes: 'api read_user', redirect_uri: 'http://example.com') }
let(:params) do
{
@@ -40,7 +39,7 @@ RSpec.describe Oauth::AuthorizationsController do
end
context 'when the user is unconfirmed' do
- let(:confirmed_at) { nil }
+ let(:user) { create(:user, :unconfirmed) }
it 'returns 200 and renders error view' do
subject
@@ -73,8 +72,6 @@ RSpec.describe Oauth::AuthorizationsController do
include_examples "Implicit grant can't be used in confidential application"
context 'when the user is confirmed' do
- let(:confirmed_at) { 1.hour.ago }
-
context 'when there is already an access token for the application with a matching scope' do
before do
scopes = Doorkeeper::OAuth::Scopes.from_string('api')
diff --git a/spec/controllers/passwords_controller_spec.rb b/spec/controllers/passwords_controller_spec.rb
index 08d68d7cec8..01c032d9e3b 100644
--- a/spec/controllers/passwords_controller_spec.rb
+++ b/spec/controllers/passwords_controller_spec.rb
@@ -91,4 +91,47 @@ RSpec.describe PasswordsController do
end
end
end
+
+ describe '#create' do
+ let(:user) { create(:user) }
+
+ subject(:perform_request) { post(:create, params: { user: { email: user.email } }) }
+
+ context 'when reCAPTCHA is disabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: false)
+ end
+
+ it 'successfully sends password reset when reCAPTCHA is not solved' do
+ perform_request
+
+ expect(response).to redirect_to(new_user_session_path)
+ expect(flash[:notice]).to include 'If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes.'
+ end
+ end
+
+ context 'when reCAPTCHA is enabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: true)
+ end
+
+ it 'displays an error when the reCAPTCHA is not solved' do
+ Recaptcha.configuration.skip_verify_env.delete('test')
+
+ perform_request
+
+ expect(response).to render_template(:new)
+ expect(flash[:alert]).to include 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'
+ end
+
+ it 'successfully sends password reset when reCAPTCHA is solved' do
+ Recaptcha.configuration.skip_verify_env << 'test'
+
+ perform_request
+
+ expect(response).to redirect_to(new_user_session_path)
+ expect(flash[:notice]).to include 'If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes.'
+ end
+ end
+ end
end
diff --git a/spec/controllers/profiles/accounts_controller_spec.rb b/spec/controllers/profiles/accounts_controller_spec.rb
index c6e7866a659..011528016ce 100644
--- a/spec/controllers/profiles/accounts_controller_spec.rb
+++ b/spec/controllers/profiles/accounts_controller_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe Profiles::AccountsController do
end
end
- [:twitter, :facebook, :google_oauth2, :gitlab, :github, :bitbucket, :crowd, :auth0, :authentiq].each do |provider|
+ [:twitter, :facebook, :google_oauth2, :gitlab, :github, :bitbucket, :crowd, :auth0, :authentiq, :dingtalk].each do |provider|
describe "#{provider} provider" do
let(:user) { create(:omniauth_user, provider: provider.to_s) }
diff --git a/spec/controllers/profiles/two_factor_auths_controller_spec.rb b/spec/controllers/profiles/two_factor_auths_controller_spec.rb
index e57bd5be937..47086ccdd2c 100644
--- a/spec/controllers/profiles/two_factor_auths_controller_spec.rb
+++ b/spec/controllers/profiles/two_factor_auths_controller_spec.rb
@@ -62,6 +62,32 @@ RSpec.describe Profiles::TwoFactorAuthsController do
expect(flash[:alert]).to be_nil
end
end
+
+ context 'when password authentication is disabled' do
+ before do
+ stub_application_setting(password_authentication_enabled_for_web: false)
+ end
+
+ it 'does not require the current password', :aggregate_failures do
+ go
+
+ expect(response).not_to redirect_to(redirect_path)
+ expect(flash[:alert]).to be_nil
+ end
+ end
+
+ context 'when the user is an LDAP user' do
+ before do
+ allow(user).to receive(:ldap_user?).and_return(true)
+ end
+
+ it 'does not require the current password', :aggregate_failures do
+ go
+
+ expect(response).not_to redirect_to(redirect_path)
+ expect(flash[:alert]).to be_nil
+ end
+ end
end
describe 'GET show' do
@@ -149,7 +175,7 @@ RSpec.describe Profiles::TwoFactorAuthsController do
it 'assigns error' do
go
- expect(assigns[:error]).to eq _('Invalid pin code')
+ expect(assigns[:error]).to eq({ message: 'Invalid pin code.' })
end
it 'assigns qr_code' do
diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb
index 4959003d788..9a1f8a8442d 100644
--- a/spec/controllers/profiles_controller_spec.rb
+++ b/spec/controllers/profiles_controller_spec.rb
@@ -125,6 +125,8 @@ RSpec.describe ProfilesController, :request_store do
end
describe 'GET audit_log' do
+ let(:auth_event) { create(:authentication_event, user: user) }
+
it 'tracks search event', :snowplow do
sign_in(user)
@@ -136,6 +138,14 @@ RSpec.describe ProfilesController, :request_store do
user: user
)
end
+
+ it 'loads page correctly' do
+ sign_in(user)
+
+ get :audit_log
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
end
describe 'PUT update_username' do
diff --git a/spec/controllers/projects/alerting/notifications_controller_spec.rb b/spec/controllers/projects/alerting/notifications_controller_spec.rb
index 2fff8026b22..b3feeb7c07b 100644
--- a/spec/controllers/projects/alerting/notifications_controller_spec.rb
+++ b/spec/controllers/projects/alerting/notifications_controller_spec.rb
@@ -16,7 +16,9 @@ RSpec.describe Projects::Alerting::NotificationsController do
end
shared_examples 'process alert payload' do |notify_service_class|
- let(:service_response) { ServiceResponse.success }
+ let(:alert_1) { build(:alert_management_alert, project: project) }
+ let(:alert_2) { build(:alert_management_alert, project: project) }
+ let(:service_response) { ServiceResponse.success(payload: { alerts: [alert_1, alert_2] }) }
let(:notify_service) { instance_double(notify_service_class, execute: service_response) }
before do
@@ -30,9 +32,13 @@ RSpec.describe Projects::Alerting::NotificationsController do
context 'when notification service succeeds' do
let(:permitted_params) { ActionController::Parameters.new(payload).permit! }
- it 'responds with ok' do
+ it 'responds with the alert data' do
make_request
+ expect(json_response).to contain_exactly(
+ { 'iid' => alert_1.iid, 'title' => alert_1.title },
+ { 'iid' => alert_2.iid, 'title' => alert_2.title }
+ )
expect(response).to have_gitlab_http_status(:ok)
end
diff --git a/spec/controllers/projects/analytics/cycle_analytics/stages_controller_spec.rb b/spec/controllers/projects/analytics/cycle_analytics/stages_controller_spec.rb
index 1351ba35a71..3f0318c3973 100644
--- a/spec/controllers/projects/analytics/cycle_analytics/stages_controller_spec.rb
+++ b/spec/controllers/projects/analytics/cycle_analytics/stages_controller_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe Projects::Analytics::CycleAnalytics::StagesController do
end
before do
+ stub_feature_flags(use_vsa_aggregated_tables: false)
sign_in(user)
end
diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb
index 43e8bbd83cf..d9dedb04b0d 100644
--- a/spec/controllers/projects/branches_controller_spec.rb
+++ b/spec/controllers/projects/branches_controller_spec.rb
@@ -356,7 +356,7 @@ RSpec.describe Projects::BranchesController do
context "valid branch name with encoded slashes" do
let(:branch) { "improve%2Fawesome" }
- it { expect(response).to have_gitlab_http_status(:ok) }
+ it { expect(response).to have_gitlab_http_status(:not_found) }
it { expect(response.body).to be_blank }
end
@@ -396,10 +396,10 @@ RSpec.describe Projects::BranchesController do
let(:branch) { 'improve%2Fawesome' }
it 'returns JSON response with message' do
- expect(json_response).to eql('message' => 'Branch was deleted')
+ expect(json_response).to eql('message' => 'No such branch')
end
- it { expect(response).to have_gitlab_http_status(:ok) }
+ it { expect(response).to have_gitlab_http_status(:not_found) }
end
context 'invalid branch name, valid ref' do
diff --git a/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb b/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb
index 942402a6d00..d55aad20689 100644
--- a/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb
+++ b/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb
@@ -6,6 +6,8 @@ RSpec.describe Projects::Ci::PipelineEditorController do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
+ subject(:show_request) { get :show, params: { namespace_id: project.namespace, project_id: project } }
+
before do
sign_in(user)
end
@@ -14,8 +16,7 @@ RSpec.describe Projects::Ci::PipelineEditorController do
context 'with enough privileges' do
before do
project.add_developer(user)
-
- get :show, params: { namespace_id: project.namespace, project_id: project }
+ show_request
end
it { expect(response).to have_gitlab_http_status(:ok) }
@@ -28,13 +29,24 @@ RSpec.describe Projects::Ci::PipelineEditorController do
context 'without enough privileges' do
before do
project.add_reporter(user)
-
- get :show, params: { namespace_id: project.namespace, project_id: project }
+ show_request
end
it 'responds with 404' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
+
+ describe 'pipeline_editor_walkthrough experiment' do
+ before do
+ project.add_developer(user)
+ end
+
+ subject(:action) { show_request }
+
+ it_behaves_like 'tracks assignment and records the subject', :pipeline_editor_walkthrough, :namespace do
+ subject { project.namespace }
+ end
+ end
end
end
diff --git a/spec/controllers/projects/commits_controller_spec.rb b/spec/controllers/projects/commits_controller_spec.rb
index 4cf77fde3a1..a8e71d73beb 100644
--- a/spec/controllers/projects/commits_controller_spec.rb
+++ b/spec/controllers/projects/commits_controller_spec.rb
@@ -67,6 +67,29 @@ RSpec.describe Projects::CommitsController do
end
end
+ context "with an invalid limit" do
+ let(:id) { "master/README.md" }
+
+ it "uses the default limit" do
+ expect_any_instance_of(Repository).to receive(:commits).with(
+ "master",
+ path: "README.md",
+ limit: described_class::COMMITS_DEFAULT_LIMIT,
+ offset: 0
+ ).and_call_original
+
+ get(:show,
+ params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: id,
+ limit: "foo"
+ })
+
+ expect(response).to be_successful
+ end
+ end
+
context "when the ref name ends in .atom" do
context "when the ref does not exist with the suffix" do
before do
diff --git a/spec/controllers/projects/hooks_controller_spec.rb b/spec/controllers/projects/hooks_controller_spec.rb
index 17baf38ef32..2ab18ccddbf 100644
--- a/spec/controllers/projects/hooks_controller_spec.rb
+++ b/spec/controllers/projects/hooks_controller_spec.rb
@@ -109,7 +109,7 @@ RSpec.describe Projects::HooksController do
describe '#test' do
let(:hook) { create(:project_hook, project: project) }
- context 'when the endpoint receives requests above the limit' do
+ context 'when the endpoint receives requests above the limit', :freeze_time, :clean_gitlab_redis_rate_limiting do
before do
allow(Gitlab::ApplicationRateLimiter).to receive(:rate_limits)
.and_return(project_testing_hook: { threshold: 1, interval: 1.minute })
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 0b3bd4d78ac..68cccfa8bde 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -1084,28 +1084,30 @@ RSpec.describe Projects::IssuesController do
end
context 'real-time sidebar feature flag' do
- using RSpec::Parameterized::TableSyntax
-
let_it_be(:project) { create(:project, :public) }
let_it_be(:issue) { create(:issue, project: project) }
- where(:action_cable_in_app_enabled, :feature_flag_enabled, :gon_feature_flag) do
- true | true | true
- true | false | true
- false | true | true
- false | false | false
+ context 'when enabled' do
+ before do
+ stub_feature_flags(real_time_issue_sidebar: true)
+ end
+
+ it 'pushes the correct value to the frontend' do
+ go(id: issue.to_param)
+
+ expect(Gon.features).to include('realTimeIssueSidebar' => true)
+ end
end
- with_them do
+ context 'when disabled' do
before do
- expect(Gitlab::ActionCable::Config).to receive(:in_app?).and_return(action_cable_in_app_enabled)
- stub_feature_flags(real_time_issue_sidebar: feature_flag_enabled)
+ stub_feature_flags(real_time_issue_sidebar: false)
end
- it 'broadcasts to the issues channel based on ActionCable and feature flag values' do
+ it 'pushes the correct value to the frontend' do
go(id: issue.to_param)
- expect(Gon.features).to include('realTimeIssueSidebar' => gon_feature_flag)
+ expect(Gon.features).to include('realTimeIssueSidebar' => false)
end
end
end
@@ -1406,14 +1408,14 @@ RSpec.describe Projects::IssuesController do
end
end
- context 'when the endpoint receives requests above the limit' do
+ context 'when the endpoint receives requests above the limit', :freeze_time, :clean_gitlab_redis_rate_limiting do
before do
- stub_application_setting(issues_create_limit: 5)
+ stub_application_setting(issues_create_limit: 1)
end
context 'when issue creation limits imposed' do
it 'prevents from creating more issues', :request_store do
- 5.times { post_new_issue }
+ post_new_issue
expect { post_new_issue }
.to change { Gitlab::GitalyClient.get_request_count }.by(1) # creates 1 projects and 0 issues
@@ -1440,7 +1442,7 @@ RSpec.describe Projects::IssuesController do
project.add_developer(user)
sign_in(user)
- 6.times do
+ 2.times do
post :create, params: {
namespace_id: project.namespace.to_param,
project_id: project,
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index 06c29e767ad..ed68d6a87b8 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -463,12 +463,25 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
- context 'when job has trace' do
+ context 'when job has live trace' do
let(:job) { create(:ci_build, :running, :trace_live, pipeline: pipeline) }
- it "has_trace is true" do
+ it 'has_trace is true' do
get_show_json
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('job/job_details')
+ expect(json_response['has_trace']).to be true
+ end
+ end
+
+ context 'when has live trace and unarchived artifact' do
+ let(:job) { create(:ci_build, :running, :trace_live, :unarchived_trace_artifact, pipeline: pipeline) }
+
+ it 'has_trace is true' do
+ get_show_json
+
+ expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
expect(json_response['has_trace']).to be true
end
@@ -631,15 +644,25 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
- context 'when job has a trace' do
+ context 'when job has a live trace' do
let(:job) { create(:ci_build, :trace_live, pipeline: pipeline) }
- it 'returns a trace' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('job/build_trace')
- expect(json_response['id']).to eq job.id
- expect(json_response['status']).to eq job.status
- expect(json_response['lines']).to eq [{ 'content' => [{ 'text' => 'BUILD TRACE' }], 'offset' => 0 }]
+ shared_examples_for 'returns trace' do
+ it 'returns a trace' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('job/build_trace')
+ expect(json_response['id']).to eq job.id
+ expect(json_response['status']).to eq job.status
+ expect(json_response['lines']).to match_array [{ 'content' => [{ 'text' => 'BUILD TRACE' }], 'offset' => 0 }]
+ end
+ end
+
+ it_behaves_like 'returns trace'
+
+ context 'when job has unarchived artifact' do
+ let(:job) { create(:ci_build, :trace_live, :unarchived_trace_artifact, pipeline: pipeline) }
+
+ it_behaves_like 'returns trace'
end
context 'when job is running' do
@@ -1055,9 +1078,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
post_erase
end
- context 'when job is erasable' do
- let(:job) { create(:ci_build, :erasable, :trace_artifact, pipeline: pipeline) }
-
+ shared_examples_for 'erases' do
it 'redirects to the erased job page' do
expect(response).to have_gitlab_http_status(:found)
expect(response).to redirect_to(namespace_project_job_path(id: job.id))
@@ -1073,7 +1094,19 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
- context 'when job is not erasable' do
+ context 'when job is successful and has artifacts' do
+ let(:job) { create(:ci_build, :erasable, :trace_artifact, pipeline: pipeline) }
+
+ it_behaves_like 'erases'
+ end
+
+ context 'when job has live trace and unarchived artifact' do
+ let(:job) { create(:ci_build, :success, :trace_live, :unarchived_trace_artifact, pipeline: pipeline) }
+
+ it_behaves_like 'erases'
+ end
+
+ context 'when job is erased' do
let(:job) { create(:ci_build, :erased, pipeline: pipeline) }
it 'returns unprocessable_entity' do
@@ -1165,16 +1198,26 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
- context "when job has a trace file" do
+ context 'when job has a live trace' do
let(:job) { create(:ci_build, :trace_live, pipeline: pipeline) }
- it 'sends a trace file' do
- response = subject
+ shared_examples_for 'sends live trace' do
+ it 'sends a trace file' do
+ response = subject
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers["Content-Type"]).to eq("text/plain; charset=utf-8")
- expect(response.headers["Content-Disposition"]).to match(/^inline/)
- expect(response.body).to eq("BUILD TRACE")
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers["Content-Type"]).to eq("text/plain; charset=utf-8")
+ expect(response.headers["Content-Disposition"]).to match(/^inline/)
+ expect(response.body).to eq("BUILD TRACE")
+ end
+ end
+
+ it_behaves_like 'sends live trace'
+
+ context 'and when job has unarchived artifact' do
+ let(:job) { create(:ci_build, :trace_live, :unarchived_trace_artifact, pipeline: pipeline) }
+
+ it_behaves_like 'sends live trace'
end
end
diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
index 3d7636b1f30..5b1c6777523 100644
--- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
@@ -86,10 +86,11 @@ RSpec.describe Projects::MergeRequests::DiffsController do
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
+ let(:maintainer) { true }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
before do
- project.add_maintainer(user)
+ project.add_maintainer(user) if maintainer
sign_in(user)
end
@@ -383,8 +384,9 @@ RSpec.describe Projects::MergeRequests::DiffsController do
end
context 'when the user cannot view the merge request' do
+ let(:maintainer) { false }
+
before do
- project.team.truncate
diff_for_path(old_path: existing_path, new_path: existing_path)
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 438fc2f2106..46b332a8938 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -10,7 +10,8 @@ RSpec.describe Projects::MergeRequestsController do
let_it_be_with_reload(:project_public_with_private_builds) { create(:project, :repository, :public, :builds_private) }
let(:user) { project.owner }
- let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
+ let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: merge_request_source_project, allow_collaboration: false) }
+ let(:merge_request_source_project) { project }
before do
sign_in(user)
@@ -506,6 +507,7 @@ RSpec.describe Projects::MergeRequestsController do
end
it 'starts the merge immediately with permitted params' do
+ allow(MergeWorker).to receive(:with_status).and_return(MergeWorker)
expect(MergeWorker).to receive(:perform_async).with(merge_request.id, anything, { 'sha' => merge_request.diff_head_sha })
merge_with_sha
@@ -2073,19 +2075,21 @@ RSpec.describe Projects::MergeRequestsController do
end
describe 'POST #rebase' do
- let(:viewer) { user }
-
def post_rebase
post :rebase, params: { namespace_id: project.namespace, project_id: project, id: merge_request }
end
+ before do
+ allow(RebaseWorker).to receive(:with_status).and_return(RebaseWorker)
+ end
+
def expect_rebase_worker_for(user)
expect(RebaseWorker).to receive(:perform_async).with(merge_request.id, user.id, false)
end
context 'successfully' do
it 'enqeues a RebaseWorker' do
- expect_rebase_worker_for(viewer)
+ expect_rebase_worker_for(user)
post_rebase
@@ -2108,17 +2112,17 @@ RSpec.describe Projects::MergeRequestsController do
context 'with a forked project' do
let(:forked_project) { fork_project(project, fork_owner, repository: true) }
let(:fork_owner) { create(:user) }
+ let(:merge_request_source_project) { forked_project }
- before do
- project.add_developer(fork_owner)
+ context 'user cannot push to source branch' do
+ before do
+ project.add_developer(fork_owner)
- merge_request.update!(source_project: forked_project)
- forked_project.add_reporter(user)
- end
+ forked_project.add_reporter(user)
+ end
- context 'user cannot push to source branch' do
it 'returns 404' do
- expect_rebase_worker_for(viewer).never
+ expect_rebase_worker_for(user).never
post_rebase
diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb
index d92862f0ca3..66af546b113 100644
--- a/spec/controllers/projects/notes_controller_spec.rb
+++ b/spec/controllers/projects/notes_controller_spec.rb
@@ -1007,6 +1007,35 @@ RSpec.describe Projects::NotesController do
end
end
+ describe 'GET outdated_line_change' do
+ let(:request_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: note,
+ format: 'json'
+ }
+ end
+
+ before do
+ service = double
+ allow(service).to receive(:execute).and_return([{ line_text: 'Test' }])
+ allow(MergeRequests::OutdatedDiscussionDiffLinesService).to receive(:new).once.and_return(service)
+
+ sign_in(user)
+ project.add_developer(user)
+ end
+
+ it "successfully renders expected JSON response" do
+ get :outdated_line_change, params: request_params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an(Array)
+ expect(json_response.count).to eq(1)
+ expect(json_response.first).to include({ "line_text" => "Test" })
+ end
+ end
+
# Convert a time to an integer number of microseconds
def microseconds(time)
(time.to_i * 1_000_000) + time.usec
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index 1354e894872..14c613ff9c4 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe Projects::PipelinesController do
end
end
- it 'does not execute N+1 queries' do
+ it 'does not execute N+1 queries', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/345470' do
get_pipelines_index_json
control_count = ActiveRecord::QueryRecorder.new do
diff --git a/spec/controllers/projects/prometheus/alerts_controller_spec.rb b/spec/controllers/projects/prometheus/alerts_controller_spec.rb
index 46de8aa4baf..d66ad445c32 100644
--- a/spec/controllers/projects/prometheus/alerts_controller_spec.rb
+++ b/spec/controllers/projects/prometheus/alerts_controller_spec.rb
@@ -160,7 +160,9 @@ RSpec.describe Projects::Prometheus::AlertsController do
end
describe 'POST #notify' do
- let(:service_response) { ServiceResponse.success }
+ let(:alert_1) { build(:alert_management_alert, :prometheus, project: project) }
+ let(:alert_2) { build(:alert_management_alert, :prometheus, project: project) }
+ let(:service_response) { ServiceResponse.success(payload: { alerts: [alert_1, alert_2] }) }
let(:notify_service) { instance_double(Projects::Prometheus::Alerts::NotifyService, execute: service_response) }
before do
@@ -173,10 +175,15 @@ RSpec.describe Projects::Prometheus::AlertsController do
end
it 'returns ok if notification succeeds' do
- expect(notify_service).to receive(:execute).and_return(ServiceResponse.success)
+ expect(notify_service).to receive(:execute).and_return(service_response)
post :notify, params: project_params, session: { as: :json }
+ expect(json_response).to contain_exactly(
+ { 'iid' => alert_1.iid, 'title' => alert_1.title },
+ { 'iid' => alert_2.iid, 'title' => alert_2.title }
+ )
+
expect(response).to have_gitlab_http_status(:ok)
end
diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb
index a1e36ec5c4c..120020273f9 100644
--- a/spec/controllers/projects/releases_controller_spec.rb
+++ b/spec/controllers/projects/releases_controller_spec.rb
@@ -207,7 +207,18 @@ RSpec.describe Projects::ReleasesController do
let(:project) { private_project }
let(:user) { guest }
- it_behaves_like 'not found'
+ it_behaves_like 'successful request'
+ end
+
+ context 'when user is an external user for the project' do
+ let(:project) { private_project }
+ let(:user) { create(:user) }
+
+ it 'behaves like not found' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
end
end
diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb
index 482ba552f8f..29988da6e60 100644
--- a/spec/controllers/projects/services_controller_spec.rb
+++ b/spec/controllers/projects/services_controller_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe Projects::ServicesController do
project.add_maintainer(user)
end
- it_behaves_like IntegrationsActions do
+ it_behaves_like Integrations::Actions do
let(:integration_attributes) { { project: project } }
let(:routing_params) do
@@ -254,7 +254,7 @@ RSpec.describe Projects::ServicesController do
let_it_be(:project) { create(:project, group: group) }
let_it_be(:jira_integration) { create(:jira_integration, project: project) }
- let(:group_integration) { create(:jira_integration, group: group, project: nil, url: 'http://group.com', password: 'group') }
+ let(:group_integration) { create(:jira_integration, :group, group: group, url: 'http://group.com', password: 'group') }
let(:integration_params) { { inherit_from_id: group_integration.id, url: 'http://custom.com', password: 'custom' } }
it 'ignores submitted params and inherits group settings' do
@@ -269,7 +269,7 @@ RSpec.describe Projects::ServicesController do
context 'when param `inherit_from_id` is set to an unrelated group' do
let_it_be(:group) { create(:group) }
- let(:group_integration) { create(:jira_integration, group: group, project: nil, url: 'http://group.com', password: 'group') }
+ let(:group_integration) { create(:jira_integration, :group, group: group, url: 'http://group.com', password: 'group') }
let(:integration_params) { { inherit_from_id: group_integration.id, url: 'http://custom.com', password: 'custom' } }
it 'ignores the param and saves the submitted settings' do
diff --git a/spec/controllers/projects/tags_controller_spec.rb b/spec/controllers/projects/tags_controller_spec.rb
index d0719643b7f..0045c0a484b 100644
--- a/spec/controllers/projects/tags_controller_spec.rb
+++ b/spec/controllers/projects/tags_controller_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Projects::TagsController do
with_them do
it 'returns 503 status code' do
expect_next_instance_of(TagsFinder) do |finder|
- expect(finder).to receive(:execute).and_return([[], Gitlab::Git::CommandError.new])
+ expect(finder).to receive(:execute).and_raise(Gitlab::Git::CommandError)
end
get :index, params: { namespace_id: project.namespace.to_param, project_id: project }, format: format
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index b34cfedb767..dafa639a2d5 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -213,21 +213,6 @@ RSpec.describe ProjectsController do
before do
sign_in(user)
-
- allow(controller).to receive(:record_experiment_user)
- end
-
- context 'when user can push to default branch', :experiment do
- let(:user) { empty_project.owner }
-
- it 'creates an "view_project_show" experiment tracking event' do
- expect(experiment(:empty_repo_upload)).to track(
- :view_project_show,
- property: 'empty'
- ).on_next_instance
-
- get :show, params: { namespace_id: empty_project.namespace, id: empty_project }
- end
end
User.project_views.keys.each do |project_view|
@@ -1158,6 +1143,22 @@ RSpec.describe ProjectsController do
expect(json_response["Commits"]).to include("123456")
end
+ context 'when gitaly is unavailable' do
+ before do
+ expect_next_instance_of(TagsFinder) do |finder|
+ allow(finder).to receive(:execute).and_raise(Gitlab::Git::CommandError)
+ end
+ end
+
+ it 'gets an empty list of tags' do
+ get :refs, params: { namespace_id: project.namespace, id: project, ref: "123456" }
+
+ expect(json_response["Branches"]).to include("master")
+ expect(json_response["Tags"]).to eq([])
+ expect(json_response["Commits"]).to include("123456")
+ end
+ end
+
context "when preferred language is Japanese" do
before do
user.update!(preferred_language: 'ja')
diff --git a/spec/controllers/registrations/welcome_controller_spec.rb b/spec/controllers/registrations/welcome_controller_spec.rb
index 034c9b3d1c0..0a1e6b8ec8f 100644
--- a/spec/controllers/registrations/welcome_controller_spec.rb
+++ b/spec/controllers/registrations/welcome_controller_spec.rb
@@ -97,6 +97,16 @@ RSpec.describe Registrations::WelcomeController do
expect(subject).to redirect_to(dashboard_projects_path)
end
end
+
+ context 'when tasks to be done are assigned' do
+ let!(:member1) { create(:group_member, user: user, tasks_to_be_done: %w(ci code)) }
+
+ before do
+ stub_experiments(invite_members_for_task: true)
+ end
+
+ it { is_expected.to redirect_to(issues_dashboard_path(assignee_username: user.username)) }
+ end
end
end
end
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index a25c597edb2..baf500c2b57 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -499,13 +499,12 @@ RSpec.describe RegistrationsController do
expect(User.last.name).to eq("#{base_user_params[:first_name]} #{base_user_params[:last_name]}")
end
- it 'sets the username and caller_id in the context' do
+ it 'sets the caller_id in the context' do
expect(controller).to receive(:create).and_wrap_original do |m, *args|
m.call(*args)
expect(Gitlab::ApplicationContext.current)
- .to include('meta.user' => base_user_params[:username],
- 'meta.caller_id' => 'RegistrationsController#create')
+ .to include('meta.caller_id' => 'RegistrationsController#create')
end
subject
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index 5eccb0b46ef..521b4cd4002 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -18,8 +18,8 @@ RSpec.describe 'Database schema' do
approvals: %w[user_id],
approver_groups: %w[target_id],
approvers: %w[target_id user_id],
- analytics_cycle_analytics_merge_request_stage_events: %w[author_id group_id merge_request_id milestone_id project_id stage_event_hash_id],
- analytics_cycle_analytics_issue_stage_events: %w[author_id group_id issue_id milestone_id project_id stage_event_hash_id],
+ analytics_cycle_analytics_merge_request_stage_events: %w[author_id group_id merge_request_id milestone_id project_id stage_event_hash_id state_id],
+ analytics_cycle_analytics_issue_stage_events: %w[author_id group_id issue_id milestone_id project_id stage_event_hash_id state_id],
audit_events: %w[author_id entity_id target_id],
award_emoji: %w[awardable_id user_id],
aws_roles: %w[role_external_id],
@@ -29,6 +29,7 @@ RSpec.describe 'Database schema' do
ci_builds: %w[erased_by_id runner_id trigger_request_id user_id],
ci_namespace_monthly_usages: %w[namespace_id],
ci_pipelines: %w[user_id],
+ ci_pipeline_chat_data: %w[chat_name_id], # it uses the loose foreign key featue
ci_runner_projects: %w[runner_id],
ci_trigger_requests: %w[commit_id],
cluster_providers_aws: %w[security_group_id vpc_id access_key_id],
@@ -48,7 +49,6 @@ RSpec.describe 'Database schema' do
geo_node_statuses: %w[last_event_id cursor_last_event_id],
geo_nodes: %w[oauth_application_id],
geo_repository_deleted_events: %w[project_id],
- geo_upload_deleted_events: %w[upload_id model_id],
gitlab_subscription_histories: %w[gitlab_subscription_id hosted_plan_id namespace_id],
identities: %w[user_id],
import_failures: %w[project_id],
@@ -66,7 +66,6 @@ RSpec.describe 'Database schema' do
oauth_access_grants: %w[resource_owner_id application_id],
oauth_access_tokens: %w[resource_owner_id application_id],
oauth_applications: %w[owner_id],
- open_project_tracker_data: %w[closed_status_id],
packages_build_infos: %w[pipeline_id],
packages_package_file_build_infos: %w[pipeline_id],
product_analytics_events_experimental: %w[event_id txn_id user_id],
@@ -210,7 +209,7 @@ RSpec.describe 'Database schema' do
# We are skipping GEO models for now as it adds up complexity
describe 'for jsonb columns' do
- it 'uses json schema validator' do
+ it 'uses json schema validator', :eager_load do
columns_name_with_jsonb.each do |hash|
next if models_by_table_name[hash["table_name"]].nil?
diff --git a/spec/experiments/change_continuous_onboarding_link_urls_experiment_spec.rb b/spec/experiments/change_continuous_onboarding_link_urls_experiment_spec.rb
new file mode 100644
index 00000000000..815aaf7c397
--- /dev/null
+++ b/spec/experiments/change_continuous_onboarding_link_urls_experiment_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ChangeContinuousOnboardingLinkUrlsExperiment, :snowplow do
+ before do
+ stub_experiments(change_continuous_onboarding_link_urls: 'control')
+ end
+
+ describe '#track' do
+ context 'when no namespace has been set' do
+ it 'tracks the action as normal' do
+ subject.track(:some_action)
+
+ expect_snowplow_event(
+ category: subject.name,
+ action: 'some_action',
+ namespace: nil,
+ context: [
+ {
+ schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/1-0-0',
+ data: an_instance_of(Hash)
+ }
+ ]
+ )
+ end
+ end
+
+ context 'when a namespace has been set' do
+ let_it_be(:namespace) { create(:namespace) }
+
+ before do
+ subject.namespace = namespace
+ end
+
+ it 'tracks the action and merges the namespace into the event args' do
+ subject.track(:some_action)
+
+ expect_snowplow_event(
+ category: subject.name,
+ action: 'some_action',
+ namespace: namespace,
+ context: [
+ {
+ schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/1-0-0',
+ data: an_instance_of(Hash)
+ }
+ ]
+ )
+ end
+ end
+ end
+end
diff --git a/spec/experiments/empty_repo_upload_experiment_spec.rb b/spec/experiments/empty_repo_upload_experiment_spec.rb
deleted file mode 100644
index 10cbedbe8ba..00000000000
--- a/spec/experiments/empty_repo_upload_experiment_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe EmptyRepoUploadExperiment, :experiment do
- subject { described_class.new(project: project) }
-
- let(:project) { create(:project, :repository) }
-
- describe '#track_initial_write' do
- context 'when experiment is turned on' do
- before do
- stub_experiments(empty_repo_upload: :control)
- end
-
- it "tracks an event for the first commit on a project" do
- expect(subject).to receive(:commit_count_for).with(project, max_count: described_class::INITIAL_COMMIT_COUNT, experiment: 'empty_repo_upload').and_return(1)
-
- expect(subject).to receive(:track).with(:initial_write, project: project).and_call_original
-
- subject.track_initial_write
- end
-
- it "doesn't track an event for projects with a commit count more than 1" do
- expect(subject).to receive(:commit_count_for).and_return(2)
-
- expect(subject).not_to receive(:track)
-
- subject.track_initial_write
- end
-
- it "doesn't track if the project is older" do
- expect(project).to receive(:created_at).and_return(described_class::TRACKING_START_DATE - 1.minute)
-
- expect(subject).not_to receive(:track)
-
- subject.track_initial_write
- end
- end
-
- context 'when experiment is turned off' do
- it "doesn't track when we generally shouldn't" do
- expect(subject).not_to receive(:track)
-
- subject.track_initial_write
- end
- end
- end
-end
diff --git a/spec/factories/analytics/cycle_analytics/issue_stage_events.rb b/spec/factories/analytics/cycle_analytics/issue_stage_events.rb
new file mode 100644
index 00000000000..8ad88152611
--- /dev/null
+++ b/spec/factories/analytics/cycle_analytics/issue_stage_events.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :cycle_analytics_issue_stage_event, class: 'Analytics::CycleAnalytics::IssueStageEvent' do
+ sequence(:stage_event_hash_id) { |n| n }
+ sequence(:issue_id) { 0 }
+ sequence(:group_id) { 0 }
+ sequence(:project_id) { 0 }
+
+ start_event_timestamp { 3.weeks.ago.to_date }
+ end_event_timestamp { 2.weeks.ago.to_date }
+ end
+end
diff --git a/spec/factories/analytics/cycle_analytics/merge_request_stage_events.rb b/spec/factories/analytics/cycle_analytics/merge_request_stage_events.rb
new file mode 100644
index 00000000000..d8fa43b024f
--- /dev/null
+++ b/spec/factories/analytics/cycle_analytics/merge_request_stage_events.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :cycle_analytics_merge_request_stage_event, class: 'Analytics::CycleAnalytics::MergeRequestStageEvent' do
+ sequence(:stage_event_hash_id) { |n| n }
+ sequence(:merge_request_id) { 0 }
+ sequence(:group_id) { 0 }
+ sequence(:project_id) { 0 }
+
+ start_event_timestamp { 3.weeks.ago.to_date }
+ end_event_timestamp { 2.weeks.ago.to_date }
+ end
+end
diff --git a/spec/factories/authentication_event.rb b/spec/factories/authentication_event.rb
index ff539c6f5c4..e02698fac38 100644
--- a/spec/factories/authentication_event.rb
+++ b/spec/factories/authentication_event.rb
@@ -7,5 +7,13 @@ FactoryBot.define do
user_name { 'Jane Doe' }
ip_address { '127.0.0.1' }
result { :failed }
+
+ trait :successful do
+ result { :success }
+ end
+
+ trait :failed do
+ result { :failed }
+ end
end
end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index 1108c606df3..98023334894 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -282,6 +282,12 @@ FactoryBot.define do
end
end
+ trait :unarchived_trace_artifact do
+ after(:create) do |build, evaluator|
+ create(:ci_job_artifact, :unarchived_trace_artifact, job: build)
+ end
+ end
+
trait :trace_with_duplicate_sections do
after(:create) do |build, evaluator|
trace = File.binread(
@@ -443,7 +449,7 @@ FactoryBot.define do
options do
{
image: { name: 'ruby:2.7', entrypoint: '/bin/sh' },
- services: ['postgres', { name: 'docker:stable-dind', entrypoint: '/bin/sh', command: 'sleep 30', alias: 'docker' }],
+ services: ['postgres', { name: 'docker:stable-dind', entrypoint: '/bin/sh', command: 'sleep 30', alias: 'docker' }, { name: 'mysql:latest', variables: { MYSQL_ROOT_PASSWORD: 'root123.' } }],
script: %w(echo),
after_script: %w(ls date),
artifacts: {
diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb
index 2f4eb99a073..223de873a04 100644
--- a/spec/factories/ci/job_artifacts.rb
+++ b/spec/factories/ci/job_artifacts.rb
@@ -87,6 +87,17 @@ FactoryBot.define do
end
end
+ trait :unarchived_trace_artifact do
+ file_type { :trace }
+ file_format { :raw }
+
+ after(:build) do |artifact, evaluator|
+ file = double('file', path: '/path/to/job.log')
+ artifact.file = file
+ allow(artifact.file).to receive(:file).and_return(CarrierWave::SanitizedFile.new(file))
+ end
+ end
+
trait :junit do
file_type { :junit }
file_format { :gzip }
diff --git a/spec/factories/ci/pipelines.rb b/spec/factories/ci/pipelines.rb
index ae3404a41a2..1d25964a4be 100644
--- a/spec/factories/ci/pipelines.rb
+++ b/spec/factories/ci/pipelines.rb
@@ -213,6 +213,14 @@ FactoryBot.define do
end
end
+ trait :with_persisted_artifacts do
+ status { :success }
+
+ after(:create) do |pipeline, evaluator|
+ pipeline.builds << create(:ci_build, :artifacts, pipeline: pipeline, project: pipeline.project)
+ end
+ end
+
trait :with_job do
after(:build) do |pipeline, evaluator|
pipeline.builds << build(:ci_build, pipeline: pipeline, project: pipeline.project)
diff --git a/spec/factories/ci/reports/security/findings.rb b/spec/factories/ci/reports/security/findings.rb
index e3971bc48f3..8a39fce971f 100644
--- a/spec/factories/ci/reports/security/findings.rb
+++ b/spec/factories/ci/reports/security/findings.rb
@@ -9,7 +9,7 @@ FactoryBot.define do
metadata_version { 'sast:1.0' }
name { 'Cipher with no integrity' }
report_type { :sast }
- raw_metadata do
+ original_data do
{
description: "The cipher does not provide data integrity update 1",
solution: "GCM mode introduces an HMAC into the resulting encrypted data, providing integrity of the result.",
@@ -26,7 +26,7 @@ FactoryBot.define do
url: "https://crypto.stackexchange.com/questions/31428/pbewithmd5anddes-cipher-does-not-check-for-integrity-first"
}
]
- }.to_json
+ }.deep_stringify_keys
end
scanner factory: :ci_reports_security_scanner
severity { :high }
diff --git a/spec/factories/ci/runner_namespaces.rb b/spec/factories/ci/runner_namespaces.rb
index a5060d196ca..e3cebed789b 100644
--- a/spec/factories/ci/runner_namespaces.rb
+++ b/spec/factories/ci/runner_namespaces.rb
@@ -2,7 +2,14 @@
FactoryBot.define do
factory :ci_runner_namespace, class: 'Ci::RunnerNamespace' do
- runner factory: [:ci_runner, :group]
group
+
+ after(:build) do |runner_namespace, evaluator|
+ unless runner_namespace.runner.present?
+ runner_namespace.runner = build(
+ :ci_runner, :group, runner_namespaces: [runner_namespace]
+ )
+ end
+ end
end
end
diff --git a/spec/factories/ci/runners.rb b/spec/factories/ci/runners.rb
index d0853df4e4b..6665b7b76a0 100644
--- a/spec/factories/ci/runners.rb
+++ b/spec/factories/ci/runners.rb
@@ -11,6 +11,7 @@ FactoryBot.define do
runner_type { :instance_type }
transient do
+ groups { [] }
projects { [] }
end
@@ -18,6 +19,10 @@ FactoryBot.define do
evaluator.projects.each do |proj|
runner.runner_projects << build(:ci_runner_project, project: proj)
end
+
+ evaluator.groups.each do |group|
+ runner.runner_namespaces << build(:ci_runner_namespace, namespace: group)
+ end
end
trait :online do
@@ -32,7 +37,9 @@ FactoryBot.define do
runner_type { :group_type }
after(:build) do |runner, evaluator|
- runner.groups << build(:group) if runner.groups.empty?
+ if runner.runner_namespaces.empty?
+ runner.runner_namespaces << build(:ci_runner_namespace)
+ end
end
end
diff --git a/spec/factories/customer_relations/issue_customer_relations_contacts.rb b/spec/factories/customer_relations/issue_customer_relations_contacts.rb
new file mode 100644
index 00000000000..6a4fecfb3cf
--- /dev/null
+++ b/spec/factories/customer_relations/issue_customer_relations_contacts.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :issue_customer_relations_contact, class: 'CustomerRelations::IssueContact' do
+ issue { association(:issue, project: project) }
+ contact { association(:contact, group: group) }
+
+ transient do
+ group { association(:group) }
+ project { association(:project, group: group) }
+ end
+
+ trait :for_contact do
+ issue { association(:issue, project: project) }
+ contact { raise ArgumentError, '`contact` is manadatory' }
+
+ transient do
+ project { association(:project, group: contact.group) }
+ end
+ end
+
+ trait :for_issue do
+ issue { raise ArgumentError, '`issue` is manadatory' }
+ contact { association(:contact, group: issue.project.group) }
+ end
+ end
+end
diff --git a/spec/factories/design_management/designs.rb b/spec/factories/design_management/designs.rb
index c23a67fe95b..56a1b55b969 100644
--- a/spec/factories/design_management/designs.rb
+++ b/spec/factories/design_management/designs.rb
@@ -39,7 +39,7 @@ FactoryBot.define do
sha = commit_version[action]
version = DesignManagement::Version.new(sha: sha, issue: issue, author: evaluator.author)
version.save!(validate: false) # We need it to have an ID, validate later
- Gitlab::Database.main.bulk_insert(dv_table_name, [action.row_attrs(version)]) # rubocop:disable Gitlab/BulkInsert
+ ApplicationRecord.legacy_bulk_insert(dv_table_name, [action.row_attrs(version)]) # rubocop:disable Gitlab/BulkInsert
end
# always a creation
diff --git a/spec/factories/error_tracking/error_event.rb b/spec/factories/error_tracking/error_event.rb
index 9620e3999d6..83f38150b11 100644
--- a/spec/factories/error_tracking/error_event.rb
+++ b/spec/factories/error_tracking/error_event.rb
@@ -63,5 +63,9 @@ FactoryBot.define do
level { 'error' }
occurred_at { Time.now.iso8601 }
payload { Gitlab::Json.parse(File.read(Rails.root.join('spec/fixtures/', 'error_tracking/parsed_event.json'))) }
+
+ trait :browser do
+ payload { Gitlab::Json.parse(File.read(Rails.root.join('spec/fixtures/', 'error_tracking/browser_event.json'))) }
+ end
end
end
diff --git a/spec/factories/gitlab/database/reindexing/queued_action.rb b/spec/factories/gitlab/database/reindexing/queued_action.rb
new file mode 100644
index 00000000000..30e12a81272
--- /dev/null
+++ b/spec/factories/gitlab/database/reindexing/queued_action.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :reindexing_queued_action, class: 'Gitlab::Database::Reindexing::QueuedAction' do
+ association :index, factory: :postgres_index
+
+ state { Gitlab::Database::Reindexing::QueuedAction.states[:queued] }
+ index_identifier { index.identifier }
+ end
+end
diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb
index 37ddbc09616..ab2321c81c4 100644
--- a/spec/factories/group_members.rb
+++ b/spec/factories/group_members.rb
@@ -34,5 +34,18 @@ FactoryBot.define do
access_level { GroupMember::MINIMAL_ACCESS }
end
+
+ transient do
+ tasks_to_be_done { [] }
+ end
+
+ after(:build) do |group_member, evaluator|
+ if evaluator.tasks_to_be_done.present?
+ build(:member_task,
+ member: group_member,
+ project: build(:project, namespace: group_member.source),
+ tasks_to_be_done: evaluator.tasks_to_be_done)
+ end
+ end
end
end
diff --git a/spec/factories/integrations.rb b/spec/factories/integrations.rb
index 63f85c04ac7..76415f82ed0 100644
--- a/spec/factories/integrations.rb
+++ b/spec/factories/integrations.rb
@@ -111,6 +111,12 @@ FactoryBot.define do
end
end
+ factory :shimo_integration, class: 'Integrations::Shimo' do
+ project
+ active { true }
+ external_wiki_url { 'https://shimo.example.com/desktop' }
+ end
+
factory :confluence_integration, class: 'Integrations::Confluence' do
project
active { true }
@@ -216,6 +222,11 @@ FactoryBot.define do
template { true }
end
+ trait :group do
+ group
+ project { nil }
+ end
+
trait :instance do
project { nil }
instance { true }
diff --git a/spec/factories/member_tasks.rb b/spec/factories/member_tasks.rb
new file mode 100644
index 00000000000..133ccce5f8a
--- /dev/null
+++ b/spec/factories/member_tasks.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :member_task do
+ member { association(:group_member, :invited) }
+ project { association(:project, namespace: member.source) }
+ tasks_to_be_done { [:ci, :code] }
+ end
+end
diff --git a/spec/factories/namespaces/project_namespaces.rb b/spec/factories/namespaces/project_namespaces.rb
index ca9fc5f8768..6bf17088741 100644
--- a/spec/factories/namespaces/project_namespaces.rb
+++ b/spec/factories/namespaces/project_namespaces.rb
@@ -2,7 +2,7 @@
FactoryBot.define do
factory :project_namespace, class: 'Namespaces::ProjectNamespace' do
- project
+ association :project, factory: :project, strategy: :build
parent { project.namespace }
visibility_level { project.visibility_level }
name { project.name }
diff --git a/spec/factories/operations/feature_flags/strategy.rb b/spec/factories/operations/feature_flags/strategy.rb
index bdb5d9f0f3c..8d04b6d25aa 100644
--- a/spec/factories/operations/feature_flags/strategy.rb
+++ b/spec/factories/operations/feature_flags/strategy.rb
@@ -5,5 +5,37 @@ FactoryBot.define do
association :feature_flag, factory: :operations_feature_flag
name { "default" }
parameters { {} }
+
+ trait :default do
+ name { "default" }
+ parameters { {} }
+ end
+
+ trait :gitlab_userlist do
+ association :user_list, factory: :operations_feature_flag_user_list
+ name { "gitlabUserList" }
+ parameters { {} }
+ end
+
+ trait :flexible_rollout do
+ name { "flexibleRollout" }
+ parameters do
+ {
+ groupId: 'default',
+ rollout: '10',
+ stickiness: 'default'
+ }
+ end
+ end
+
+ trait :gradual_rollout do
+ name { "gradualRolloutUserId" }
+ parameters { { percentage: '10', groupId: 'default' } }
+ end
+
+ trait :userwithid do
+ name { "userWithId" }
+ parameters { { userIds: 'user1' } }
+ end
end
end
diff --git a/spec/factories/packages/helm/file_metadatum.rb b/spec/factories/packages/helm/file_metadatum.rb
index 3f599b5d5c0..590956e5d49 100644
--- a/spec/factories/packages/helm/file_metadatum.rb
+++ b/spec/factories/packages/helm/file_metadatum.rb
@@ -9,7 +9,11 @@ FactoryBot.define do
package_file { association(:helm_package_file, without_loaded_metadatum: true) }
sequence(:channel) { |n| "#{FFaker::Lorem.word}-#{n}" }
metadata do
- { 'name': package_file.package.name, 'version': package_file.package.version, 'apiVersion': 'v2' }.tap do |defaults|
+ {
+ 'name': package_file.package.name,
+ 'version': package_file.package.version,
+ 'apiVersion': 'v2'
+ }.tap do |defaults|
defaults['description'] = description if description
end
end
diff --git a/spec/factories/packages/npm/metadata.rb b/spec/factories/packages/npm/metadata.rb
new file mode 100644
index 00000000000..c8acaa10199
--- /dev/null
+++ b/spec/factories/packages/npm/metadata.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :npm_metadatum, class: 'Packages::Npm::Metadatum' do
+ package { association(:npm_package) }
+
+ package_json do
+ {
+ 'name': package.name,
+ 'version': package.version,
+ 'dist': {
+ 'tarball': 'http://localhost/tarball.tgz',
+ 'shasum': '1234567890'
+ }
+ }
+ end
+ end
+end
diff --git a/spec/factories/project_members.rb b/spec/factories/project_members.rb
index 3e83ab7118c..f2dedc178c7 100644
--- a/spec/factories/project_members.rb
+++ b/spec/factories/project_members.rb
@@ -23,5 +23,15 @@ FactoryBot.define do
trait :blocked do
after(:build) { |project_member, _| project_member.user.block! }
end
+
+ transient do
+ tasks_to_be_done { [] }
+ end
+
+ after(:build) do |project_member, evaluator|
+ if evaluator.tasks_to_be_done.present?
+ build(:member_task, member: project_member, project: project_member.source, tasks_to_be_done: evaluator.tasks_to_be_done)
+ end
+ end
end
end
diff --git a/spec/factories/user_highest_roles.rb b/spec/factories/user_highest_roles.rb
index 761a8b6c583..ee5794b55fb 100644
--- a/spec/factories/user_highest_roles.rb
+++ b/spec/factories/user_highest_roles.rb
@@ -5,10 +5,10 @@ FactoryBot.define do
highest_access_level { nil }
user
- trait(:guest) { highest_access_level { GroupMember::GUEST } }
- trait(:reporter) { highest_access_level { GroupMember::REPORTER } }
- trait(:developer) { highest_access_level { GroupMember::DEVELOPER } }
- trait(:maintainer) { highest_access_level { GroupMember::MAINTAINER } }
- trait(:owner) { highest_access_level { GroupMember::OWNER } }
+ trait(:guest) { highest_access_level { GroupMember::GUEST } }
+ trait(:reporter) { highest_access_level { GroupMember::REPORTER } }
+ trait(:developer) { highest_access_level { GroupMember::DEVELOPER } }
+ trait(:maintainer) { highest_access_level { GroupMember::MAINTAINER } }
+ trait(:owner) { highest_access_level { GroupMember::OWNER } }
end
end
diff --git a/spec/factories/users/credit_card_validations.rb b/spec/factories/users/credit_card_validations.rb
index 09940347708..509e86e7bd3 100644
--- a/spec/factories/users/credit_card_validations.rb
+++ b/spec/factories/users/credit_card_validations.rb
@@ -3,7 +3,10 @@
FactoryBot.define do
factory :credit_card_validation, class: 'Users::CreditCardValidation' do
user
-
- credit_card_validated_at { Time.current }
+ sequence(:credit_card_validated_at) { |n| Time.current + n }
+ expiration_date { 1.year.from_now.end_of_month }
+ last_digits { 10 }
+ holder_name { 'John Smith' }
+ network { 'AmericanExpress' }
end
end
diff --git a/spec/factories_spec.rb b/spec/factories_spec.rb
index 7dc38b25fac..811ed18dce3 100644
--- a/spec/factories_spec.rb
+++ b/spec/factories_spec.rb
@@ -22,6 +22,8 @@ RSpec.describe 'factories' do
[:debian_project_component_file, :object_storage],
[:debian_project_distribution, :object_storage],
[:debian_file_metadatum, :unknown],
+ [:issue_customer_relations_contact, :for_contact],
+ [:issue_customer_relations_contact, :for_issue],
[:package_file, :object_storage],
[:pages_domain, :without_certificate],
[:pages_domain, :without_key],
@@ -72,6 +74,8 @@ RSpec.describe 'factories' do
fork_network_member
group_member
import_state
+ issue_customer_relations_contact
+ member_task
milestone_release
namespace
project_broken_repo
diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb
index cb69eac8035..0785c736cfb 100644
--- a/spec/features/admin/admin_appearance_spec.rb
+++ b/spec/features/admin/admin_appearance_spec.rb
@@ -94,7 +94,7 @@ RSpec.describe 'Admin Appearance' do
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
visit new_project_path
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
expect_custom_new_project_appearance(appearance)
end
diff --git a/spec/features/admin/admin_deploy_keys_spec.rb b/spec/features/admin/admin_deploy_keys_spec.rb
index c326d0fd741..53caf0fac33 100644
--- a/spec/features/admin/admin_deploy_keys_spec.rb
+++ b/spec/features/admin/admin_deploy_keys_spec.rb
@@ -3,11 +3,13 @@
require 'spec_helper'
RSpec.describe 'admin deploy keys' do
+ let_it_be(:admin) { create(:admin) }
+
let!(:deploy_key) { create(:deploy_key, public: true) }
let!(:another_deploy_key) { create(:another_deploy_key, public: true) }
before do
- admin = create(:admin)
+ stub_feature_flags(admin_deploy_keys_vue: false)
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
end
@@ -15,7 +17,7 @@ RSpec.describe 'admin deploy keys' do
it 'show all public deploy keys' do
visit admin_deploy_keys_path
- page.within(find('.deploy-keys-list', match: :first)) do
+ page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
expect(page).to have_content(deploy_key.title)
expect(page).to have_content(another_deploy_key.title)
end
@@ -26,7 +28,7 @@ RSpec.describe 'admin deploy keys' do
visit admin_deploy_keys_path
- page.within(find('.deploy-keys-list', match: :first)) do
+ page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
expect(page).to have_content(write_key.project.full_name)
end
end
@@ -46,7 +48,7 @@ RSpec.describe 'admin deploy keys' do
expect(current_path).to eq admin_deploy_keys_path
- page.within(find('.deploy-keys-list', match: :first)) do
+ page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
expect(page).to have_content('laptop')
end
end
@@ -64,7 +66,7 @@ RSpec.describe 'admin deploy keys' do
expect(current_path).to eq admin_deploy_keys_path
- page.within(find('.deploy-keys-list', match: :first)) do
+ page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
expect(page).to have_content('new-title')
end
end
@@ -79,9 +81,23 @@ RSpec.describe 'admin deploy keys' do
find('tr', text: deploy_key.title).click_link('Remove')
expect(current_path).to eq admin_deploy_keys_path
- page.within(find('.deploy-keys-list', match: :first)) do
+ page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
expect(page).not_to have_content(deploy_key.title)
end
end
end
+
+ context 'when `admin_deploy_keys_vue` feature flag is enabled', :js do
+ before do
+ stub_feature_flags(admin_deploy_keys_vue: true)
+
+ visit admin_deploy_keys_path
+ end
+
+ it 'renders the Vue app', :aggregate_failures do
+ expect(page).to have_content('Public deploy keys')
+ expect(page).to have_selector('[data-testid="deploy-keys-list"]')
+ expect(page).to have_link('New deploy key', href: new_admin_deploy_key_path)
+ end
+ end
end
diff --git a/spec/features/admin/admin_disables_two_factor_spec.rb b/spec/features/admin/admin_disables_two_factor_spec.rb
index 1f34c4ed17c..f65e85b4cb6 100644
--- a/spec/features/admin/admin_disables_two_factor_spec.rb
+++ b/spec/features/admin/admin_disables_two_factor_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Admin disables 2FA for a user' do
it 'successfully', :js do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
admin = create(:admin)
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index 8315b8f44b0..8d4e7a7442c 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -252,6 +252,7 @@ RSpec.describe 'Admin Groups' do
describe 'admin remove themself from a group', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/222342' do
it 'removes admin from the group' do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
group.add_user(current_user, Gitlab::Access::DEVELOPER)
visit group_group_members_path(group)
diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb
index a501efd82ed..32e4d18227e 100644
--- a/spec/features/admin/admin_hooks_spec.rb
+++ b/spec/features/admin/admin_hooks_spec.rb
@@ -79,6 +79,7 @@ RSpec.describe 'Admin::Hooks' do
let(:hook_url) { generate(:url) }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
create(:system_hook, url: hook_url)
end
diff --git a/spec/features/admin/admin_labels_spec.rb b/spec/features/admin/admin_labels_spec.rb
index 08d81906d9f..65de1160cfd 100644
--- a/spec/features/admin/admin_labels_spec.rb
+++ b/spec/features/admin/admin_labels_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe 'admin issues labels' do
describe 'list' do
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
visit admin_labels_path
end
diff --git a/spec/features/admin/admin_manage_applications_spec.rb b/spec/features/admin/admin_manage_applications_spec.rb
index b6437fce540..4cf290293bd 100644
--- a/spec/features/admin/admin_manage_applications_spec.rb
+++ b/spec/features/admin/admin_manage_applications_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe 'admin manage applications' do
let_it_be(:new_application_path) { new_admin_application_path }
let_it_be(:applications_path) { admin_applications_path }
+ let_it_be(:index_path) { admin_applications_path }
before do
admin = create(:admin)
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 8053be89ffc..7e2751daefa 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -24,40 +24,37 @@ RSpec.describe "Admin Runners" do
visit admin_runners_path
- expect(page).to have_text "Set up a shared runner manually"
+ expect(page).to have_text "Register an instance runner"
expect(page).to have_text "Runners currently online: 1"
end
- it 'with an instance runner shows an instance badge and no project count' do
+ it 'with an instance runner shows an instance badge' do
runner = create(:ci_runner, :instance)
visit admin_runners_path
within "[data-testid='runner-row-#{runner.id}']" do
expect(page).to have_selector '.badge', text: 'shared'
- expect(page).to have_text 'n/a'
end
end
- it 'with a group runner shows a group badge and no project count' do
+ it 'with a group runner shows a group badge' do
runner = create(:ci_runner, :group, groups: [group])
visit admin_runners_path
within "[data-testid='runner-row-#{runner.id}']" do
expect(page).to have_selector '.badge', text: 'group'
- expect(page).to have_text 'n/a'
end
end
- it 'with a project runner shows a project badge and project count' do
+ it 'with a project runner shows a project badge' do
runner = create(:ci_runner, :project, projects: [project])
visit admin_runners_path
within "[data-testid='runner-row-#{runner.id}']" do
expect(page).to have_selector '.badge', text: 'specific'
- expect(page).to have_text '1'
end
end
@@ -69,6 +66,13 @@ RSpec.describe "Admin Runners" do
visit admin_runners_path
end
+ it 'runner types tabs have total counts and can be selected' do
+ expect(page).to have_link('All 2')
+ expect(page).to have_link('Instance 2')
+ expect(page).to have_link('Group 0')
+ expect(page).to have_link('Project 0')
+ end
+
it 'shows runners' do
expect(page).to have_content("runner-foo")
expect(page).to have_content("runner-bar")
@@ -137,6 +141,19 @@ RSpec.describe "Admin Runners" do
expect(page).not_to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
end
+
+ it 'shows correct runner when type is selected and search term is entered' do
+ create(:ci_runner, :instance, description: 'runner-connected', contacted_at: Time.now)
+ create(:ci_runner, :instance, description: 'runner-not-connected', contacted_at: nil)
+
+ visit admin_runners_path
+
+ # use the string "Not" to avoid using space and trigger an early selection
+ input_filtered_search_filter_is_only('Status', 'Not')
+
+ expect(page).not_to have_content 'runner-connected'
+ expect(page).to have_content 'runner-not-connected'
+ end
end
describe 'filter by type' do
@@ -145,13 +162,25 @@ RSpec.describe "Admin Runners" do
create(:ci_runner, :group, description: 'runner-group', groups: [group])
end
+ it '"All" tab is selected by default' do
+ visit admin_runners_path
+
+ page.within('[data-testid="runner-type-tabs"]') do
+ expect(page).to have_link('All', class: 'active')
+ end
+ end
+
it 'shows correct runner when type matches' do
visit admin_runners_path
expect(page).to have_content 'runner-project'
expect(page).to have_content 'runner-group'
- input_filtered_search_filter_is_only('Type', 'project')
+ page.within('[data-testid="runner-type-tabs"]') do
+ click_on('Project')
+
+ expect(page).to have_link('Project', class: 'active')
+ end
expect(page).to have_content 'runner-project'
expect(page).not_to have_content 'runner-group'
@@ -160,7 +189,11 @@ RSpec.describe "Admin Runners" do
it 'shows no runner when type does not match' do
visit admin_runners_path
- input_filtered_search_filter_is_only('Type', 'instance')
+ page.within('[data-testid="runner-type-tabs"]') do
+ click_on 'Instance'
+
+ expect(page).to have_link('Instance', class: 'active')
+ end
expect(page).not_to have_content 'runner-project'
expect(page).not_to have_content 'runner-group'
@@ -173,7 +206,9 @@ RSpec.describe "Admin Runners" do
visit admin_runners_path
- input_filtered_search_filter_is_only('Type', 'project')
+ page.within('[data-testid="runner-type-tabs"]') do
+ click_on 'Project'
+ end
expect(page).to have_content 'runner-project'
expect(page).to have_content 'runner-2-project'
@@ -185,6 +220,26 @@ RSpec.describe "Admin Runners" do
expect(page).not_to have_content 'runner-2-project'
expect(page).not_to have_content 'runner-group'
end
+
+ it 'maintains the same filter when switching between runner types' do
+ create(:ci_runner, :project, description: 'runner-paused-project', active: false, projects: [project])
+
+ visit admin_runners_path
+
+ input_filtered_search_filter_is_only('Status', 'Active')
+
+ expect(page).to have_content 'runner-project'
+ expect(page).to have_content 'runner-group'
+ expect(page).not_to have_content 'runner-paused-project'
+
+ page.within('[data-testid="runner-type-tabs"]') do
+ click_on 'Project'
+ end
+
+ expect(page).to have_content 'runner-project'
+ expect(page).not_to have_content 'runner-group'
+ expect(page).not_to have_content 'runner-paused-project'
+ end
end
describe 'filter by tag' do
@@ -267,29 +322,55 @@ RSpec.describe "Admin Runners" do
end
it 'has all necessary texts including no runner message' do
- expect(page).to have_text "Set up a shared runner manually"
+ expect(page).to have_text "Register an instance runner"
expect(page).to have_text "Runners currently online: 0"
expect(page).to have_text 'No runners found'
end
end
- describe 'runners registration token' do
+ describe 'runners registration' do
let!(:token) { Gitlab::CurrentSettings.runners_registration_token }
before do
visit admin_runners_path
+
+ click_on 'Register an instance runner'
+ end
+
+ describe 'show registration instructions' do
+ before do
+ click_on 'Show runner installation and registration instructions'
+
+ wait_for_requests
+ end
+
+ it 'opens runner installation modal' do
+ expect(page).to have_text "Install a runner"
+
+ expect(page).to have_text "Environment"
+ expect(page).to have_text "Architecture"
+ expect(page).to have_text "Download and install binary"
+ end
+
+ it 'dismisses runner installation modal' do
+ page.within('[role="dialog"]') do
+ click_button('Close', match: :first)
+ end
+
+ expect(page).not_to have_text "Install a runner"
+ end
end
it 'has a registration token' do
click_on 'Click to reveal'
- expect(page.find('[data-testid="registration-token"]')).to have_content(token)
+ expect(page.find('[data-testid="token-value"]')).to have_content(token)
end
describe 'reset registration token' do
- let(:page_token) { find('[data-testid="registration-token"]').text }
+ let(:page_token) { find('[data-testid="token-value"]').text }
before do
- click_button 'Reset registration token'
+ click_on 'Reset registration token'
page.accept_alert
@@ -297,6 +378,8 @@ RSpec.describe "Admin Runners" do
end
it 'changes registration token' do
+ click_on 'Register an instance runner'
+
click_on 'Click to reveal'
expect(page_token).not_to eq token
end
diff --git a/spec/features/admin/admin_sees_project_statistics_spec.rb b/spec/features/admin/admin_sees_project_statistics_spec.rb
index 3433cc01b8e..9d9217c4574 100644
--- a/spec/features/admin/admin_sees_project_statistics_spec.rb
+++ b/spec/features/admin/admin_sees_project_statistics_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe "Admin > Admin sees project statistics" do
let(:project) { create(:project, :repository) }
it "shows project statistics" do
- expect(page).to have_content("Storage: 0 Bytes (Repository: 0 Bytes / Wikis: 0 Bytes / Build Artifacts: 0 Bytes / LFS: 0 Bytes / Snippets: 0 Bytes / Packages: 0 Bytes / Uploads: 0 Bytes)")
+ expect(page).to have_content("Storage: 0 Bytes (Repository: 0 Bytes / Wikis: 0 Bytes / Build Artifacts: 0 Bytes / Pipeline Artifacts: 0 Bytes / LFS: 0 Bytes / Snippets: 0 Bytes / Packages: 0 Bytes / Uploads: 0 Bytes)")
end
end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 1c50a7f891f..0a39baca259 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -491,22 +491,22 @@ RSpec.describe 'Admin updates settings' do
group = create(:group)
page.within('.as-performance-bar') do
- check 'Allow non-administrators to access to the performance bar'
+ check 'Allow non-administrators access to the performance bar'
fill_in 'Allow access to members of the following group', with: group.path
click_on 'Save changes'
end
expect(page).to have_content "Application settings saved successfully"
- expect(find_field('Allow non-administrators to access to the performance bar')).to be_checked
+ expect(find_field('Allow non-administrators access to the performance bar')).to be_checked
expect(find_field('Allow access to members of the following group').value).to eq group.path
page.within('.as-performance-bar') do
- uncheck 'Allow non-administrators to access to the performance bar'
+ uncheck 'Allow non-administrators access to the performance bar'
click_on 'Save changes'
end
expect(page).to have_content 'Application settings saved successfully'
- expect(find_field('Allow non-administrators to access to the performance bar')).not_to be_checked
+ expect(find_field('Allow non-administrators access to the performance bar')).not_to be_checked
expect(find_field('Allow access to members of the following group').value).to be_nil
end
diff --git a/spec/features/admin/admin_users_impersonation_tokens_spec.rb b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
index ed8ea84fbf8..6643ebe82e6 100644
--- a/spec/features/admin/admin_users_impersonation_tokens_spec.rb
+++ b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
@@ -74,6 +74,7 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do
let!(:impersonation_token) { create(:personal_access_token, :impersonation, user: user) }
it "allows revocation of an active impersonation token" do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
visit admin_user_impersonation_tokens_path(user_id: user.username)
accept_confirm { click_on "Revoke" }
diff --git a/spec/features/admin/admin_uses_repository_checks_spec.rb b/spec/features/admin/admin_uses_repository_checks_spec.rb
index 0e448446085..c13313609b5 100644
--- a/spec/features/admin/admin_uses_repository_checks_spec.rb
+++ b/spec/features/admin/admin_uses_repository_checks_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe 'Admin uses repository checks', :request_store do
let(:admin) { create(:admin) }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
end
diff --git a/spec/features/admin/clusters/eks_spec.rb b/spec/features/admin/clusters/eks_spec.rb
index a1bac720349..bb2678de2ae 100644
--- a/spec/features/admin/clusters/eks_spec.rb
+++ b/spec/features/admin/clusters/eks_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe 'Instance-level AWS EKS Cluster', :js do
before do
visit admin_clusters_path
- click_link 'Integrate with a cluster certificate'
+ click_link 'Connect with a certificate'
end
context 'when user creates a cluster on AWS EKS' do
diff --git a/spec/features/admin/users/user_spec.rb b/spec/features/admin/users/user_spec.rb
index 624bfde7359..73477fb93dd 100644
--- a/spec/features/admin/users/user_spec.rb
+++ b/spec/features/admin/users/user_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe 'Admin::Users::User' do
let_it_be(:current_user) { create(:admin) }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
sign_in(current_user)
gitlab_enable_admin_mode_sign_in(current_user)
end
diff --git a/spec/features/admin/users/users_spec.rb b/spec/features/admin/users/users_spec.rb
index 119b01ff552..fa943245fcb 100644
--- a/spec/features/admin/users/users_spec.rb
+++ b/spec/features/admin/users/users_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe 'Admin::Users' do
let_it_be(:current_user) { create(:admin) }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
sign_in(current_user)
gitlab_enable_admin_mode_sign_in(current_user)
end
@@ -164,7 +165,7 @@ RSpec.describe 'Admin::Users' do
visit admin_users_path
- page.within('.filter-two-factor-enabled small') do
+ page.within('.filter-two-factor-enabled .gl-tab-counter-badge') do
expect(page).to have_content('1')
end
end
@@ -181,7 +182,7 @@ RSpec.describe 'Admin::Users' do
it 'counts users who have not enabled 2FA' do
visit admin_users_path
- page.within('.filter-two-factor-disabled small') do
+ page.within('.filter-two-factor-disabled .gl-tab-counter-badge') do
expect(page).to have_content('2') # Including admin
end
end
@@ -200,7 +201,7 @@ RSpec.describe 'Admin::Users' do
visit admin_users_path
- page.within('.filter-blocked-pending-approval small') do
+ page.within('.filter-blocked-pending-approval .gl-tab-counter-badge') do
expect(page).to have_content('2')
end
end
diff --git a/spec/features/alert_management/alert_management_list_spec.rb b/spec/features/alert_management/alert_management_list_spec.rb
index 1e710169c9c..2fbce27033e 100644
--- a/spec/features/alert_management/alert_management_list_spec.rb
+++ b/spec/features/alert_management/alert_management_list_spec.rb
@@ -55,28 +55,4 @@ RSpec.describe 'Alert Management index', :js do
it_behaves_like 'alert page with title, filtered search, and table'
end
end
-
- describe 'managed_alerts_deprecation feature flag' do
- subject { page }
-
- before do
- stub_feature_flags(managed_alerts_deprecation: feature_flag_value)
- sign_in(developer)
-
- visit project_alert_management_index_path(project)
- wait_for_requests
- end
-
- context 'feature flag on' do
- let(:feature_flag_value) { true }
-
- it { is_expected.to have_pushed_frontend_feature_flags(managedAlertsDeprecation: true) }
- end
-
- context 'feature flag off' do
- let(:feature_flag_value) { false }
-
- it { is_expected.to have_pushed_frontend_feature_flags(managedAlertsDeprecation: false) }
- end
- end
end
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index 9a5b5bbfc34..2f21961d1fc 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -536,6 +536,7 @@ RSpec.describe 'Project issue boards', :js do
let_it_be(:user_guest) { create(:user) }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
project.add_guest(user_guest)
sign_in(user_guest)
visit project_board_path(project, board)
diff --git a/spec/features/clusters/create_agent_spec.rb b/spec/features/clusters/create_agent_spec.rb
new file mode 100644
index 00000000000..f40932c4750
--- /dev/null
+++ b/spec/features/clusters/create_agent_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Cluster agent registration', :js do
+ let_it_be(:project) { create(:project, :custom_repo, files: { '.gitlab/agents/example-agent-1/config.yaml' => '' }) }
+ let_it_be(:current_user) { create(:user, maintainer_projects: [project]) }
+
+ before do
+ allow(Gitlab::Kas).to receive(:enabled?).and_return(true)
+ allow(Gitlab::Kas).to receive(:internal_url).and_return('kas.example.internal')
+
+ allow_next_instance_of(Gitlab::Kas::Client) do |client|
+ allow(client).to receive(:list_agent_config_files).and_return([
+ double(agent_name: 'example-agent-1', path: '.gitlab/agents/example-agent-1/config.yaml'),
+ double(agent_name: 'example-agent-2', path: '.gitlab/agents/example-agent-2/config.yaml')
+ ])
+ end
+
+ allow(Devise).to receive(:friendly_token).and_return('example-agent-token')
+
+ sign_in(current_user)
+ visit project_clusters_path(project)
+ end
+
+ it 'allows the user to select an agent to install, and displays the resulting agent token' do
+ click_button('Actions')
+ expect(page).to have_content('Install new Agent')
+
+ click_button('Select an Agent')
+ click_button('example-agent-2')
+ click_button('Register Agent')
+
+ expect(page).to have_content('The token value will not be shown again after you close this window.')
+ expect(page).to have_content('example-agent-token')
+ expect(page).to have_content('docker run --pull=always --rm')
+
+ within find('.modal-footer') do
+ click_button('Close')
+ end
+
+ expect(page).to have_link('example-agent-2')
+ end
+end
diff --git a/spec/features/contextual_sidebar_spec.rb b/spec/features/contextual_sidebar_spec.rb
index 39881a28b11..29c7e0ddd21 100644
--- a/spec/features/contextual_sidebar_spec.rb
+++ b/spec/features/contextual_sidebar_spec.rb
@@ -3,35 +3,110 @@
require 'spec_helper'
RSpec.describe 'Contextual sidebar', :js do
- let_it_be(:project) { create(:project) }
+ context 'when context is a project' do
+ let_it_be(:project) { create(:project) }
- let(:user) { project.owner }
+ let(:user) { project.owner }
- before do
- sign_in(user)
+ before do
+ sign_in(user)
+ end
- visit project_path(project)
- end
+ context 'when analyzing the menu' do
+ before do
+ visit project_path(project)
+ end
+
+ it 'shows flyout navs when collapsed or expanded apart from on the active item when expanded', :aggregate_failures do
+ expect(page).not_to have_selector('.js-sidebar-collapsed')
+
+ find('.rspec-link-pipelines').hover
+
+ expect(page).to have_selector('.is-showing-fly-out')
+
+ find('.rspec-project-link').hover
+
+ expect(page).not_to have_selector('.is-showing-fly-out')
+
+ find('.rspec-toggle-sidebar').click
+
+ find('.rspec-link-pipelines').hover
+
+ expect(page).to have_selector('.is-showing-fly-out')
- it 'shows flyout navs when collapsed or expanded apart from on the active item when expanded', :aggregate_failures do
- expect(page).not_to have_selector('.js-sidebar-collapsed')
+ find('.rspec-project-link').hover
+
+ expect(page).to have_selector('.is-showing-fly-out')
+ end
+ end
+
+ context 'with invite_members_in_side_nav experiment', :experiment do
+ it 'allows opening of modal for the candidate experience' do
+ stub_experiments(invite_members_in_side_nav: :candidate)
+ expect(experiment(:invite_members_in_side_nav)).to track(:assignment)
+ .with_context(group: project.group)
+ .on_next_instance
+
+ visit project_path(project)
+
+ page.within '[data-test-id="side-nav-invite-members"' do
+ find('[data-test-id="invite-members-button"').click
+ end
+
+ expect(page).to have_content("You're inviting members to the")
+ end
+
+ it 'does not have invite members link in side nav for the control experience' do
+ stub_experiments(invite_members_in_side_nav: :control)
+ expect(experiment(:invite_members_in_side_nav)).to track(:assignment)
+ .with_context(group: project.group)
+ .on_next_instance
+
+ visit project_path(project)
+
+ expect(page).not_to have_css('[data-test-id="side-nav-invite-members"')
+ end
+ end
+ end
- find('.rspec-link-pipelines').hover
+ context 'when context is a group' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) do
+ create(:group).tap do |g|
+ g.add_owner(user)
+ end
+ end
- expect(page).to have_selector('.is-showing-fly-out')
+ before do
+ sign_in(user)
+ end
- find('.rspec-project-link').hover
+ context 'with invite_members_in_side_nav experiment', :experiment do
+ it 'allows opening of modal for the candidate experience' do
+ stub_experiments(invite_members_in_side_nav: :candidate)
+ expect(experiment(:invite_members_in_side_nav)).to track(:assignment)
+ .with_context(group: group)
+ .on_next_instance
- expect(page).not_to have_selector('.is-showing-fly-out')
+ visit group_path(group)
- find('.rspec-toggle-sidebar').click
+ page.within '[data-test-id="side-nav-invite-members"' do
+ find('[data-test-id="invite-members-button"').click
+ end
- find('.rspec-link-pipelines').hover
+ expect(page).to have_content("You're inviting members to the")
+ end
- expect(page).to have_selector('.is-showing-fly-out')
+ it 'does not have invite members link in side nav for the control experience' do
+ stub_experiments(invite_members_in_side_nav: :control)
+ expect(experiment(:invite_members_in_side_nav)).to track(:assignment)
+ .with_context(group: group)
+ .on_next_instance
- find('.rspec-project-link').hover
+ visit group_path(group)
- expect(page).to have_selector('.is-showing-fly-out')
+ expect(page).not_to have_css('[data-test-id="side-nav-invite-members"')
+ end
+ end
end
end
diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb
index 34a55118cb3..69361f66a71 100644
--- a/spec/features/cycle_analytics_spec.rb
+++ b/spec/features/cycle_analytics_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe 'Value Stream Analytics', :js do
let_it_be(:user) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:stage_table_selector) { '[data-testid="vsa-stage-table"]' }
+ let_it_be(:stage_filter_bar) { '[data-testid="vsa-filter-bar"]' }
let_it_be(:stage_table_event_selector) { '[data-testid="vsa-stage-event"]' }
let_it_be(:stage_table_event_title_selector) { '[data-testid="vsa-stage-event-title"]' }
let_it_be(:stage_table_pagination_selector) { '[data-testid="vsa-stage-pagination"]' }
@@ -27,9 +28,16 @@ RSpec.describe 'Value Stream Analytics', :js do
def set_daterange(from_date, to_date)
page.find(".js-daterange-picker-from input").set(from_date)
page.find(".js-daterange-picker-to input").set(to_date)
+
+ # simulate a blur event
+ page.find(".js-daterange-picker-to input").send_keys(:tab)
wait_for_all_requests
end
+ before do
+ stub_feature_flags(use_vsa_aggregated_tables: false)
+ end
+
context 'as an allowed user' do
context 'when project is new' do
before do
@@ -97,7 +105,7 @@ RSpec.describe 'Value Stream Analytics', :js do
end
end
- it 'shows data on each stage', :sidekiq_might_not_need_inline do
+ it 'shows data on each stage', :sidekiq_might_not_need_inline, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338332' do
expect_issue_to_be_present
click_stage('Plan')
@@ -133,7 +141,7 @@ RSpec.describe 'Value Stream Analytics', :js do
expect(metrics_values).to eq(['-'] * 4)
end
- it 'can sort records' do
+ it 'can sort records', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338332' do
# NOTE: checking that the string changes should suffice
# depending on the order the tests are run we might run into problems with hard coded strings
original_first_title = first_stage_title
@@ -158,6 +166,18 @@ RSpec.describe 'Value Stream Analytics', :js do
expect(page).not_to have_text(original_first_title, exact: true)
end
+ it 'can navigate directly to a value stream stream stage with filters applied' do
+ visit project_cycle_analytics_path(project, created_before: '2019-12-31', created_after: '2019-11-01', stage_id: 'code', milestone_title: milestone.title)
+ wait_for_requests
+
+ expect(page).to have_selector('.gl-path-active-item-indigo', text: 'Code')
+ expect(page.find(".js-daterange-picker-from input").value).to eq("2019-11-01")
+ expect(page.find(".js-daterange-picker-to input").value).to eq("2019-12-31")
+
+ filter_bar = page.find(stage_filter_bar)
+ expect(filter_bar.find(".gl-filtered-search-token-data-content").text).to eq("%#{milestone.title}")
+ end
+
def stage_time_column
stage_table.find(stage_table_duration_column_header_selector).ancestor("th")
end
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index 27419479479..82288a6c1a6 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -80,7 +80,7 @@ RSpec.describe 'Dashboard Projects' do
visit dashboard_projects_path
expect(page).to have_content(project.name)
- expect(find('.nav-links li:nth-child(1) .badge-pill')).to have_content(1)
+ expect(find('.gl-tabs-nav li:nth-child(1) .badge-pill')).to have_content(1)
end
it 'shows personal projects on personal projects tab', :js do
@@ -128,8 +128,8 @@ RSpec.describe 'Dashboard Projects' do
expect(page).not_to have_content(project.name)
expect(page).to have_content(project2.name)
- expect(find('.nav-links li:nth-child(1) .badge-pill')).to have_content(1)
- expect(find('.nav-links li:nth-child(2) .badge-pill')).to have_content(1)
+ expect(find('.gl-tabs-nav li:nth-child(1) .badge-pill')).to have_content(1)
+ expect(find('.gl-tabs-nav li:nth-child(2) .badge-pill')).to have_content(1)
end
it 'does not show tabs to filter by all projects or personal' do
@@ -204,7 +204,7 @@ RSpec.describe 'Dashboard Projects' do
visit dashboard_projects_path
expect(page).to have_selector('[data-testid="project_topic_list"]')
- expect(page).to have_link('topic1', href: explore_projects_path(topic: 'topic1'))
+ expect(page).to have_link('topic1', href: topic_explore_projects_path(topic_name: 'topic1'))
end
end
diff --git a/spec/features/explore/topics_spec.rb b/spec/features/explore/topics_spec.rb
new file mode 100644
index 00000000000..9d2e76bc3a1
--- /dev/null
+++ b/spec/features/explore/topics_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Explore Topics' do
+ context 'when no topics exist' do
+ it 'renders empty message', :aggregate_failures do
+ visit topics_explore_projects_path
+
+ expect(current_path).to eq topics_explore_projects_path
+ expect(page).to have_content('There are no topics to show.')
+ end
+ end
+
+ context 'when topics exist' do
+ let!(:topic) { create(:topic, name: 'topic1') }
+
+ it 'renders topic list' do
+ visit topics_explore_projects_path
+
+ expect(current_path).to eq topics_explore_projects_path
+ expect(page).to have_content('topic1')
+ end
+ end
+end
diff --git a/spec/features/graphql_known_operations_spec.rb b/spec/features/graphql_known_operations_spec.rb
new file mode 100644
index 00000000000..ef406f12902
--- /dev/null
+++ b/spec/features/graphql_known_operations_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# We need to distinguish between known and unknown GraphQL operations. This spec
+# tests that we set up Gitlab::Graphql::KnownOperations.default which requires
+# integration of FE queries, webpack plugin, and BE.
+RSpec.describe 'Graphql known operations', :js do
+ around do |example|
+ # Let's make sure we aren't receiving or leaving behind any side-effects
+ # https://gitlab.com/gitlab-org/gitlab/-/jobs/1743294100
+ ::Gitlab::Graphql::KnownOperations.instance_variable_set(:@default, nil)
+ ::Gitlab::Webpack::GraphqlKnownOperations.clear_memoization!
+
+ example.run
+
+ ::Gitlab::Graphql::KnownOperations.instance_variable_set(:@default, nil)
+ ::Gitlab::Webpack::GraphqlKnownOperations.clear_memoization!
+ end
+
+ it 'collects known Graphql operations from the code', :aggregate_failures do
+ # Check that we include some arbitrary operation name we expect
+ known_operations = Gitlab::Graphql::KnownOperations.default.operations.map(&:name)
+
+ expect(known_operations).to include("searchProjects")
+ expect(known_operations.length).to be > 20
+ expect(known_operations).to all( match(%r{^[a-z]+}i) )
+ end
+end
diff --git a/spec/features/groups/clusters/eks_spec.rb b/spec/features/groups/clusters/eks_spec.rb
index c361c502cbb..fe62efbd3bf 100644
--- a/spec/features/groups/clusters/eks_spec.rb
+++ b/spec/features/groups/clusters/eks_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe 'Group AWS EKS Cluster', :js do
before do
visit group_clusters_path(group)
- click_link 'Integrate with a cluster certificate'
+ click_link 'Connect with a certificate'
end
context 'when user creates a cluster on AWS EKS' do
diff --git a/spec/features/groups/clusters/user_spec.rb b/spec/features/groups/clusters/user_spec.rb
index 2a7ededa39b..1788167c94c 100644
--- a/spec/features/groups/clusters/user_spec.rb
+++ b/spec/features/groups/clusters/user_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'User Cluster', :js do
before do
visit group_clusters_path(group)
- click_link 'Integrate with a cluster certificate'
+ click_link 'Connect with a certificate'
click_link 'Connect existing cluster'
end
@@ -129,7 +129,7 @@ RSpec.describe 'User Cluster', :js do
it 'user sees creation form with the successful message' do
expect(page).to have_content('Kubernetes cluster integration was successfully removed.')
- expect(page).to have_link('Integrate with a cluster certificate')
+ expect(page).to have_link('Connect with a certificate')
end
end
end
diff --git a/spec/features/groups/dependency_proxy_spec.rb b/spec/features/groups/dependency_proxy_spec.rb
index d6b0bdc8ea4..623fb065bfc 100644
--- a/spec/features/groups/dependency_proxy_spec.rb
+++ b/spec/features/groups/dependency_proxy_spec.rb
@@ -56,9 +56,14 @@ RSpec.describe 'Group Dependency Proxy' do
visit settings_path
wait_for_requests
- click_button 'Enable Proxy'
+ proxy_toggle = find('[data-testid="dependency-proxy-setting-toggle"]')
+ proxy_toggle_button = proxy_toggle.find('button')
- expect(page).to have_button 'Enable Proxy', class: '!is-checked'
+ expect(proxy_toggle).to have_css("button.is-checked")
+
+ proxy_toggle_button.click
+
+ expect(proxy_toggle).not_to have_css("button.is-checked")
visit path
diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb
index 489beb70ab3..4e59ab40d04 100644
--- a/spec/features/groups/issues_spec.rb
+++ b/spec/features/groups/issues_spec.rb
@@ -83,6 +83,18 @@ RSpec.describe 'Group issues page' do
end
end
+ it 'truncates issue counts if over the threshold', :clean_gitlab_redis_cache do
+ allow(Rails.cache).to receive(:read).and_call_original
+ allow(Rails.cache).to receive(:read).with(
+ ['group', group.id, 'issues'],
+ { expires_in: Gitlab::IssuablesCountForState::CACHE_EXPIRES_IN }
+ ).and_return({ opened: 1050, closed: 500, all: 1550 })
+
+ visit issues_group_path(group)
+
+ expect(page).to have_text('Open 1.1k Closed 500 All 1.6k')
+ end
+
context 'when project is archived' do
before do
::Projects::UpdateService.new(project, user_in_group, archived: true).execute
@@ -94,41 +106,6 @@ RSpec.describe 'Group issues page' do
expect(page).not_to have_content issue.title[0..80]
end
end
-
- context 'when cached issues state count is enabled', :clean_gitlab_redis_cache do
- before do
- stub_feature_flags(cached_issues_state_count: true)
- end
-
- it 'truncates issue counts if over the threshold' do
- allow(Rails.cache).to receive(:read).and_call_original
- allow(Rails.cache).to receive(:read).with(
- ['group', group.id, 'issues'],
- { expires_in: Gitlab::IssuablesCountForState::CACHE_EXPIRES_IN }
- ).and_return({ opened: 1050, closed: 500, all: 1550 })
-
- visit issues_group_path(group)
-
- expect(page).to have_text('Open 1.1k Closed 500 All 1.6k')
- end
- end
-
- context 'when cached issues state count is disabled', :clean_gitlab_redis_cache do
- before do
- stub_feature_flags(cached_issues_state_count: false)
- end
-
- it 'does not truncate counts if they are over the threshold' do
- allow_next_instance_of(IssuesFinder) do |finder|
- allow(finder).to receive(:count_by_state).and_return(true)
- .and_return({ opened: 1050, closed: 500, all: 1550 })
- end
-
- visit issues_group_path(group)
-
- expect(page).to have_text('Open 1,050 Closed 500 All 1,550')
- end
- end
end
context 'projects with issues disabled' do
diff --git a/spec/features/groups/labels/subscription_spec.rb b/spec/features/groups/labels/subscription_spec.rb
index dedded777ac..231c4b33bee 100644
--- a/spec/features/groups/labels/subscription_spec.rb
+++ b/spec/features/groups/labels/subscription_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe 'Labels subscription' do
end
it 'does not show subscribed tab' do
- page.within('.nav-tabs') do
+ page.within('.gl-tabs-nav') do
expect(page).not_to have_link 'Subscribed'
end
end
@@ -86,7 +86,7 @@ RSpec.describe 'Labels subscription' do
end
def click_subscribed_tab
- page.within('.nav-tabs') do
+ page.within('.gl-tabs-nav') do
click_link 'Subscribed'
end
end
diff --git a/spec/features/groups/members/leave_group_spec.rb b/spec/features/groups/members/leave_group_spec.rb
index b73313745e9..e6bf1ffc2f7 100644
--- a/spec/features/groups/members/leave_group_spec.rb
+++ b/spec/features/groups/members/leave_group_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe 'Groups > Members > Leave group' do
let(:group) { create(:group) }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
sign_in(user)
end
diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb
index 0a159056569..22409e9e7f6 100644
--- a/spec/features/groups/navbar_spec.rb
+++ b/spec/features/groups/navbar_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe 'Group navbar' do
insert_package_nav(_('Kubernetes'))
stub_feature_flags(group_iterations: false)
+ stub_feature_flags(customer_relations: false)
stub_config(dependency_proxy: { enabled: false })
stub_config(registry: { enabled: false })
stub_group_wikis(false)
@@ -40,6 +41,22 @@ RSpec.describe 'Group navbar' do
it_behaves_like 'verified navigation bar'
end
+ context 'when customer_relations feature flag is enabled' do
+ before do
+ stub_feature_flags(customer_relations: true)
+
+ if Gitlab.ee?
+ insert_customer_relations_nav(_('Analytics'))
+ else
+ insert_customer_relations_nav(_('Packages & Registries'))
+ end
+
+ visit group_path(group)
+ end
+
+ it_behaves_like 'verified navigation bar'
+ end
+
context 'when dependency proxy is available' do
before do
stub_config(dependency_proxy: { enabled: true })
diff --git a/spec/features/groups/packages_spec.rb b/spec/features/groups/packages_spec.rb
index 0dfc7180187..3c2ade6b274 100644
--- a/spec/features/groups/packages_spec.rb
+++ b/spec/features/groups/packages_spec.rb
@@ -28,10 +28,6 @@ RSpec.describe 'Group Packages' do
context 'when feature is available', :js do
before do
- # we are simply setting the featrure flag to false because the new UI has nothing to test yet
- # when the refactor is complete or almost complete we will turn on the feature tests
- # see https://gitlab.com/gitlab-org/gitlab/-/issues/330846 for status of this work
- stub_feature_flags(package_list_apollo: false)
visit_group_packages
end
diff --git a/spec/features/groups/settings/manage_applications_spec.rb b/spec/features/groups/settings/manage_applications_spec.rb
index 5f84f61678d..277471cb304 100644
--- a/spec/features/groups/settings/manage_applications_spec.rb
+++ b/spec/features/groups/settings/manage_applications_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe 'User manages applications' do
let_it_be(:group) { create(:group) }
let_it_be(:user) { create(:user) }
let_it_be(:new_application_path) { group_settings_applications_path(group) }
+ let_it_be(:index_path) { group_settings_applications_path(group) }
before do
group.add_owner(user)
diff --git a/spec/features/incidents/user_creates_new_incident_spec.rb b/spec/features/incidents/user_creates_new_incident_spec.rb
index 99a137b5852..685f6ab791a 100644
--- a/spec/features/incidents/user_creates_new_incident_spec.rb
+++ b/spec/features/incidents/user_creates_new_incident_spec.rb
@@ -4,52 +4,49 @@ require 'spec_helper'
RSpec.describe 'Incident Management index', :js do
let_it_be(:project) { create(:project) }
- let_it_be(:developer) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:incident) { create(:incident, project: project) }
before_all do
- project.add_developer(developer)
+ project.add_reporter(reporter)
project.add_guest(guest)
end
- shared_examples 'create incident form' do
- it 'shows the create new issue button' do
- expect(page).to have_selector('.create-incident-button')
- end
+ before do
+ sign_in(user)
- it 'when clicked shows the create issue page with the Incident type pre-selected' do
- find('.create-incident-button').click
- wait_for_all_requests
+ visit project_incidents_path(project)
+ wait_for_all_requests
+ end
- expect(page).to have_selector('.dropdown-menu-toggle')
- expect(page).to have_selector('.js-issuable-type-filter-dropdown-wrap')
+ describe 'incident list is visited' do
+ context 'by reporter' do
+ let(:user) { reporter }
- page.within('.js-issuable-type-filter-dropdown-wrap') do
- expect(page).to have_content('Incident')
+ it 'shows the create new incident button' do
+ expect(page).to have_selector('.create-incident-button')
end
- end
- end
- context 'when a developer displays the incident list' do
- before do
- sign_in(developer)
+ it 'when clicked shows the create issue page with the Incident type pre-selected' do
+ find('.create-incident-button').click
+ wait_for_all_requests
- visit project_incidents_path(project)
- wait_for_all_requests
- end
+ expect(page).to have_selector('.dropdown-menu-toggle')
+ expect(page).to have_selector('.js-issuable-type-filter-dropdown-wrap')
- it_behaves_like 'create incident form'
+ page.within('.js-issuable-type-filter-dropdown-wrap') do
+ expect(page).to have_content('Incident')
+ end
+ end
+ end
end
- context 'when a guest displays the incident list' do
- before do
- sign_in(guest)
+ context 'by guest' do
+ let(:user) { guest }
- visit project_incidents_path(project)
- wait_for_all_requests
+ it 'does not show new incident button' do
+ expect(page).not_to have_selector('.create-incident-button')
end
-
- it_behaves_like 'create incident form'
end
end
diff --git a/spec/features/incidents/user_views_incident_spec.rb b/spec/features/incidents/user_views_incident_spec.rb
index 244b66f7a9a..fe54f7708c9 100644
--- a/spec/features/incidents/user_views_incident_spec.rb
+++ b/spec/features/incidents/user_views_incident_spec.rb
@@ -22,12 +22,30 @@ RSpec.describe "User views incident" do
it_behaves_like 'page meta description', ' Description header Lorem ipsum dolor sit amet'
- it 'shows the merge request and incident actions', :js, :aggregate_failures do
- click_button 'Incident actions'
+ describe 'user actions' do
+ it 'shows the merge request and incident actions', :js, :aggregate_failures do
+ click_button 'Incident actions'
- expect(page).to have_link('New incident', href: new_project_issue_path(project, { issuable_template: 'incident', issue: { issue_type: 'incident', description: "Related to \##{incident.iid}.\n\n" } }))
- expect(page).to have_button('Create merge request')
- expect(page).to have_button('Close incident')
+ expect(page).to have_link('New incident', href: new_project_issue_path(project, { issuable_template: 'incident', issue: { issue_type: 'incident', description: "Related to \##{incident.iid}.\n\n" } }))
+ expect(page).to have_button('Create merge request')
+ expect(page).to have_button('Close incident')
+ end
+
+ context 'when user is a guest' do
+ before do
+ project.add_guest(user)
+
+ login_as(user)
+
+ visit(project_issues_incident_path(project, incident))
+ end
+
+ it 'does not show the incident action', :js, :aggregate_failures do
+ click_button 'Incident actions'
+
+ expect(page).not_to have_link('New incident')
+ end
+ end
end
context 'when the project is archived' do
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index 87fb8955dcc..f9ab780d2d6 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -103,6 +103,20 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
expect(page).to have_content('You are already a member of this group.')
end
end
+
+ context 'when email case doesnt match', :js do
+ let(:invite_email) { 'User@example.com' }
+ let(:user) { create(:user, email: 'user@example.com') }
+
+ before do
+ sign_in(user)
+ visit invite_path(group_invite.raw_invite_token)
+ end
+
+ it 'accepts invite' do
+ expect(page).to have_content('You have been granted Developer access to group Owned.')
+ end
+ end
end
context 'when declining the invitation from invitation reminder email' do
diff --git a/spec/features/issuables/markdown_references/internal_references_spec.rb b/spec/features/issuables/markdown_references/internal_references_spec.rb
index 07d4271eed7..2dcabb38b8f 100644
--- a/spec/features/issuables/markdown_references/internal_references_spec.rb
+++ b/spec/features/issuables/markdown_references/internal_references_spec.rb
@@ -53,9 +53,7 @@ RSpec.describe "Internal references", :js do
end
it "doesn't show any references", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/257832' do
- page.within(".issue-details") do
- expect(page).not_to have_content("#merge-requests .merge-requests-title")
- end
+ expect(page).not_to have_text 'Related merge requests'
end
end
@@ -65,12 +63,9 @@ RSpec.describe "Internal references", :js do
end
it "shows references", :sidekiq_might_not_need_inline do
- page.within("#merge-requests .merge-requests-title") do
- expect(page).to have_content("Related merge requests")
- expect(page).to have_css(".mr-count-badge")
- end
+ expect(page).to have_text 'Related merge requests 1'
- page.within("#merge-requests ul") do
+ page.within('.related-items-list') do
expect(page).to have_content(private_project_merge_request.title)
expect(page).to have_css(".ic-issue-open-m")
end
@@ -122,9 +117,7 @@ RSpec.describe "Internal references", :js do
end
it "doesn't show any references", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/257832' do
- page.within(".merge-request-details") do
- expect(page).not_to have_content("#merge-requests .merge-requests-title")
- end
+ expect(page).not_to have_text 'Related merge requests'
end
end
diff --git a/spec/features/issue_rebalancing_spec.rb b/spec/features/issue_rebalancing_spec.rb
new file mode 100644
index 00000000000..978768270ec
--- /dev/null
+++ b/spec/features/issue_rebalancing_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Issue rebalancing' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:user) { create(:user) }
+
+ let(:alert_message_regex) { /Issues are being rebalanced at the moment/ }
+
+ before_all do
+ create(:issue, project: project)
+
+ group.add_developer(user)
+ end
+
+ context 'when issue rebalancing is in progress' do
+ before do
+ sign_in(user)
+
+ stub_feature_flags(block_issue_repositioning: true)
+ end
+
+ it 'shows an alert in project boards' do
+ board = create(:board, project: project)
+
+ visit project_board_path(project, board)
+
+ expect(page).to have_selector('.gl-alert-info', text: alert_message_regex, count: 1)
+ end
+
+ it 'shows an alert in group boards' do
+ board = create(:board, group: group)
+
+ visit group_board_path(group, board)
+
+ expect(page).to have_selector('.gl-alert-info', text: alert_message_regex, count: 1)
+ end
+
+ it 'shows an alert in project issues list with manual sort' do
+ visit project_issues_path(project, sort: 'relative_position')
+
+ expect(page).to have_selector('.gl-alert-info', text: alert_message_regex, count: 1)
+ end
+
+ it 'shows an alert in group issues list with manual sort' do
+ visit issues_group_path(group, sort: 'relative_position')
+
+ expect(page).to have_selector('.gl-alert-info', text: alert_message_regex, count: 1)
+ end
+
+ it 'does not show an alert in project issues list with other sorts' do
+ visit project_issues_path(project, sort: 'created_date')
+
+ expect(page).not_to have_selector('.gl-alert-info', text: alert_message_regex)
+ end
+
+ it 'does not show an alert in group issues list with other sorts' do
+ visit issues_group_path(group, sort: 'created_date')
+
+ expect(page).not_to have_selector('.gl-alert-info', text: alert_message_regex)
+ end
+ end
+end
diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb
index 4bad67acc87..b26f65316c5 100644
--- a/spec/features/issues/form_spec.rb
+++ b/spec/features/issues/form_spec.rb
@@ -4,25 +4,29 @@ require 'spec_helper'
RSpec.describe 'New/edit issue', :js do
include ActionView::Helpers::JavaScriptHelper
- include FormHelper
let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user)}
- let_it_be(:user2) { create(:user)}
+ let_it_be(:user) { create(:user) }
+ let_it_be(:user2) { create(:user) }
let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:label) { create(:label, project: project) }
let_it_be(:label2) { create(:label, project: project) }
let_it_be(:issue) { create(:issue, project: project, assignees: [user], milestone: milestone) }
- before do
- stub_licensed_features(multiple_issue_assignees: false, issue_weights: false)
+ let(:current_user) { user }
+ before_all do
project.add_maintainer(user)
project.add_maintainer(user2)
- sign_in(user)
end
- context 'new issue' do
+ before do
+ stub_licensed_features(multiple_issue_assignees: false, issue_weights: false)
+
+ sign_in(current_user)
+ end
+
+ describe 'new issue' do
before do
visit new_project_issue_path(project)
end
@@ -235,29 +239,61 @@ RSpec.describe 'New/edit issue', :js do
end
describe 'displays issue type options in the dropdown' do
+ shared_examples 'type option is visible' do |label:, identifier:|
+ it "shows #{identifier} option", :aggregate_failures do
+ page.within('[data-testid="issue-type-select-dropdown"]') do
+ expect(page).to have_selector(%([data-testid="issue-type-#{identifier}-icon"]))
+ expect(page).to have_content(label)
+ end
+ end
+ end
+
+ shared_examples 'type option is missing' do |label:, identifier:|
+ it "does not show #{identifier} option", :aggregate_failures do
+ page.within('[data-testid="issue-type-select-dropdown"]') do
+ expect(page).not_to have_selector(%([data-testid="issue-type-#{identifier}-icon"]))
+ expect(page).not_to have_content(label)
+ end
+ end
+ end
+
before do
page.within('.issue-form') do
click_button 'Issue'
end
end
- it 'correctly displays the Issue type option with an icon', :aggregate_failures do
- page.within('[data-testid="issue-type-select-dropdown"]') do
- expect(page).to have_selector('[data-testid="issue-type-issue-icon"]')
- expect(page).to have_content('Issue')
+ context 'when user is guest' do
+ let_it_be(:guest) { create(:user) }
+
+ let(:current_user) { guest }
+
+ before_all do
+ project.add_guest(guest)
end
+
+ it_behaves_like 'type option is visible', label: 'Issue', identifier: :issue
+ it_behaves_like 'type option is missing', label: 'Incident', identifier: :incident
end
- it 'correctly displays the Incident type option with an icon', :aggregate_failures do
- page.within('[data-testid="issue-type-select-dropdown"]') do
- expect(page).to have_selector('[data-testid="issue-type-incident-icon"]')
- expect(page).to have_content('Incident')
+ context 'when user is reporter' do
+ let_it_be(:reporter) { create(:user) }
+
+ let(:current_user) { reporter }
+
+ before_all do
+ project.add_reporter(reporter)
end
+
+ it_behaves_like 'type option is visible', label: 'Issue', identifier: :issue
+ it_behaves_like 'type option is visible', label: 'Incident', identifier: :incident
end
end
describe 'milestone' do
- let!(:milestone) { create(:milestone, title: '">&lt;img src=x onerror=alert(document.domain)&gt;', project: project) }
+ let!(:milestone) do
+ create(:milestone, title: '">&lt;img src=x onerror=alert(document.domain)&gt;', project: project)
+ end
it 'escapes milestone' do
click_button 'Milestone'
@@ -274,7 +310,7 @@ RSpec.describe 'New/edit issue', :js do
end
end
- context 'edit issue' do
+ describe 'edit issue' do
before do
visit edit_project_issue_path(project, issue)
end
@@ -329,7 +365,7 @@ RSpec.describe 'New/edit issue', :js do
end
end
- context 'inline edit' do
+ describe 'inline edit' do
before do
visit project_issue_path(project, issue)
end
diff --git a/spec/features/issues/issue_detail_spec.rb b/spec/features/issues/issue_detail_spec.rb
index 531c3634b5e..b37c8e9d1cf 100644
--- a/spec/features/issues/issue_detail_spec.rb
+++ b/spec/features/issues/issue_detail_spec.rb
@@ -3,8 +3,9 @@
require 'spec_helper'
RSpec.describe 'Issue Detail', :js do
+ let_it_be_with_refind(:project) { create(:project, :public) }
+
let(:user) { create(:user) }
- let(:project) { create(:project, :public) }
let(:issue) { create(:issue, project: project, author: user) }
let(:incident) { create(:incident, project: project, author: user) }
@@ -90,7 +91,13 @@ RSpec.describe 'Issue Detail', :js do
end
describe 'user updates `issue_type` via the issue type dropdown' do
- context 'when an issue `issue_type` is edited by a signed in user' do
+ let_it_be(:reporter) { create(:user) }
+
+ before_all do
+ project.add_reporter(reporter)
+ end
+
+ describe 'when an issue `issue_type` is edited' do
before do
sign_in(user)
@@ -98,18 +105,33 @@ RSpec.describe 'Issue Detail', :js do
wait_for_requests
end
- it 'routes the user to the incident details page when the `issue_type` is set to incident' do
- open_issue_edit_form
+ context 'by non-member author' do
+ it 'cannot see Incident option' do
+ open_issue_edit_form
+
+ page.within('[data-testid="issuable-form"]') do
+ expect(page).to have_content('Issue')
+ expect(page).not_to have_content('Incident')
+ end
+ end
+ end
+
+ context 'by reporter' do
+ let(:user) { reporter }
- page.within('[data-testid="issuable-form"]') do
- update_type_select('Issue', 'Incident')
+ it 'routes the user to the incident details page when the `issue_type` is set to incident' do
+ open_issue_edit_form
- expect(page).to have_current_path(project_issues_incident_path(project, issue))
+ page.within('[data-testid="issuable-form"]') do
+ update_type_select('Issue', 'Incident')
+
+ expect(page).to have_current_path(project_issues_incident_path(project, issue))
+ end
end
end
end
- context 'when an incident `issue_type` is edited by a signed in user' do
+ describe 'when an incident `issue_type` is edited' do
before do
sign_in(user)
@@ -117,13 +139,29 @@ RSpec.describe 'Issue Detail', :js do
wait_for_requests
end
- it 'routes the user to the issue details page when the `issue_type` is set to issue' do
- open_issue_edit_form
+ context 'by non-member author' do
+ it 'routes the user to the issue details page when the `issue_type` is set to issue' do
+ open_issue_edit_form
+
+ page.within('[data-testid="issuable-form"]') do
+ update_type_select('Incident', 'Issue')
+
+ expect(page).to have_current_path(project_issue_path(project, incident))
+ end
+ end
+ end
+
+ context 'by reporter' do
+ let(:user) { reporter }
+
+ it 'routes the user to the issue details page when the `issue_type` is set to issue' do
+ open_issue_edit_form
- page.within('[data-testid="issuable-form"]') do
- update_type_select('Incident', 'Issue')
+ page.within('[data-testid="issuable-form"]') do
+ update_type_select('Incident', 'Issue')
- expect(page).to have_current_path(project_issue_path(project, incident))
+ expect(page).to have_current_path(project_issue_path(project, incident))
+ end
end
end
end
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index f46aa5c21b6..37e324e6ded 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -171,7 +171,7 @@ RSpec.describe "User creates issue" do
end
context 'form create handles issue creation by default' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
before do
visit new_project_issue_path(project)
@@ -187,30 +187,22 @@ RSpec.describe "User creates issue" do
end
context 'form create handles incident creation' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
before do
visit new_project_issue_path(project, { issuable_template: 'incident', issue: { issue_type: 'incident' } })
end
- it 'pre-fills the issue type dropdown with incident type' do
- expect(find('.js-issuable-type-filter-dropdown-wrap .dropdown-toggle-text')).to have_content('Incident')
- end
-
- it 'hides the epic select' do
- expect(page).not_to have_selector('.epic-dropdown-container')
+ it 'does not pre-fill the issue type dropdown with incident type' do
+ expect(find('.js-issuable-type-filter-dropdown-wrap .dropdown-toggle-text')).not_to have_content('Incident')
end
it 'shows the milestone select' do
expect(page).to have_selector('.qa-issuable-milestone-dropdown') # rubocop:disable QA/SelectorUsage
end
- it 'hides the weight input' do
- expect(page).not_to have_selector('.qa-issuable-weight-input') # rubocop:disable QA/SelectorUsage
- end
-
- it 'shows the incident help text' do
- expect(page).to have_text('A modified issue to guide the resolution of incidents.')
+ it 'hides the incident help text' do
+ expect(page).not_to have_text('A modified issue to guide the resolution of incidents.')
end
end
@@ -242,6 +234,44 @@ RSpec.describe "User creates issue" do
end
end
+ context 'when signed in as reporter', :js do
+ let_it_be(:project) { create(:project) }
+
+ before_all do
+ project.add_reporter(user)
+ end
+
+ before do
+ sign_in(user)
+ end
+
+ context 'form create handles incident creation' do
+ before do
+ visit new_project_issue_path(project, { issuable_template: 'incident', issue: { issue_type: 'incident' } })
+ end
+
+ it 'pre-fills the issue type dropdown with incident type' do
+ expect(find('.js-issuable-type-filter-dropdown-wrap .dropdown-toggle-text')).to have_content('Incident')
+ end
+
+ it 'hides the epic select' do
+ expect(page).not_to have_selector('.epic-dropdown-container')
+ end
+
+ it 'shows the milestone select' do
+ expect(page).to have_selector('.qa-issuable-milestone-dropdown') # rubocop:disable QA/SelectorUsage
+ end
+
+ it 'hides the weight input' do
+ expect(page).not_to have_selector('.qa-issuable-weight-input') # rubocop:disable QA/SelectorUsage
+ end
+
+ it 'shows the incident help text' do
+ expect(page).to have_text('A modified issue to guide the resolution of incidents.')
+ end
+ end
+ end
+
context "when signed in as user with special characters in their name" do
let(:user_special) { create(:user, name: "Jon O'Shea") }
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index 63c36a20adc..76cec2502e3 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -146,8 +146,7 @@ RSpec.describe "Issues > User edits issue", :js do
fill_in 'Comment', with: '/label ~syzygy'
click_button 'Comment'
-
- wait_for_requests
+ expect(page).to have_text('added syzygy label just now')
page.within '.block.labels' do
# Remove `verisimilitude` label
@@ -155,8 +154,6 @@ RSpec.describe "Issues > User edits issue", :js do
click_button
end
- wait_for_requests
-
expect(page).to have_text('syzygy')
expect(page).not_to have_text('verisimilitude')
end
diff --git a/spec/features/issues/user_toggles_subscription_spec.rb b/spec/features/issues/user_toggles_subscription_spec.rb
index 9809bb34d26..541bbc8a8e7 100644
--- a/spec/features/issues/user_toggles_subscription_spec.rb
+++ b/spec/features/issues/user_toggles_subscription_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe "User toggles subscription", :js do
it 'is disabled' do
expect(page).to have_content('Disabled by project owner')
- expect(page).to have_button('Notifications', class: 'is-disabled')
+ expect(page).to have_selector('[data-testid="subscription-toggle"]', class: 'is-disabled')
end
end
end
diff --git a/spec/features/issues/user_uses_quick_actions_spec.rb b/spec/features/issues/user_uses_quick_actions_spec.rb
index d88b816b186..c6d743ed38f 100644
--- a/spec/features/issues/user_uses_quick_actions_spec.rb
+++ b/spec/features/issues/user_uses_quick_actions_spec.rb
@@ -44,5 +44,6 @@ RSpec.describe 'Issues > User uses quick actions', :js do
it_behaves_like 'move quick action'
it_behaves_like 'zoom quick actions'
it_behaves_like 'clone quick action'
+ it_behaves_like 'promote_to_incident quick action'
end
end
diff --git a/spec/features/jira_connect/subscriptions_spec.rb b/spec/features/jira_connect/subscriptions_spec.rb
index 9be6b7c67ee..e1589ba997e 100644
--- a/spec/features/jira_connect/subscriptions_spec.rb
+++ b/spec/features/jira_connect/subscriptions_spec.rb
@@ -40,8 +40,8 @@ RSpec.describe 'Subscriptions Content Security Policy' do
visit jira_connect_subscriptions_path(jwt: jwt)
is_expected.to include("frame-ancestors 'self' https://*.atlassian.net")
- is_expected.to include("script-src 'self' https://some-cdn.test https://connect-cdn.atl-paas.net https://unpkg.com/jquery@3.3.1/")
- is_expected.to include("style-src 'self' https://some-cdn.test 'unsafe-inline' https://unpkg.com/@atlaskit/")
+ is_expected.to include("script-src 'self' https://some-cdn.test https://connect-cdn.atl-paas.net")
+ is_expected.to include("style-src 'self' https://some-cdn.test 'unsafe-inline'")
end
end
end
diff --git a/spec/features/merge_request/user_approves_spec.rb b/spec/features/merge_request/user_approves_spec.rb
index f401dd598f3..4f7bcb58551 100644
--- a/spec/features/merge_request/user_approves_spec.rb
+++ b/spec/features/merge_request/user_approves_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe 'Merge request > User approves', :js do
it 'approves merge request' do
click_approval_button('Approve')
- expect(page).to have_content('Merge request approved')
+ expect(page).to have_content('Approved by you')
verify_approvals_count_on_index!
diff --git a/spec/features/merge_request/user_assigns_themselves_spec.rb b/spec/features/merge_request/user_assigns_themselves_spec.rb
index 04d401683bf..fc925781a3b 100644
--- a/spec/features/merge_request/user_assigns_themselves_spec.rb
+++ b/spec/features/merge_request/user_assigns_themselves_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Merge request > User assigns themselves' do
visit project_merge_request_path(project, merge_request)
end
- it 'updates related issues', :js do
+ it 'updates related issues', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/343006' do
click_link 'Assign yourself to these issues'
expect(page).to have_content '2 issues have been assigned to you'
diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb
index 54c3fe738d2..f9b554c5ed2 100644
--- a/spec/features/merge_request/user_comments_on_diff_spec.rb
+++ b/spec/features/merge_request/user_comments_on_diff_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe 'User comments on a diff', :js do
let(:user) { create(:user) }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb
index 1d3d76d3486..06795344c5c 100644
--- a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb
+++ b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb
@@ -26,33 +26,27 @@ RSpec.describe 'Merge request < User customizes merge commit message', :js do
].join("\n\n")
end
- let(:message_with_description) do
- [
- "Merge branch 'feature' into 'master'",
- merge_request.title,
- merge_request.description,
- "See merge request #{merge_request.to_reference(full: true)}"
- ].join("\n\n")
- end
-
before do
project.add_maintainer(user)
sign_in(user)
visit project_merge_request_path(project, merge_request)
end
- it 'toggles commit message between message with description and without description' do
+ it 'has commit message without description' do
expect(page).not_to have_selector('#merge-message-edit')
first('.js-mr-widget-commits-count').click
expect(textbox).to be_visible
expect(textbox.value).to eq(default_message)
+ end
- check('Include merge request description')
-
- expect(textbox.value).to eq(message_with_description)
-
- uncheck('Include merge request description')
+ context 'when target project has merge commit template set' do
+ let(:project) { create(:project, :public, :repository, merge_commit_template: '%{title}') }
- expect(textbox.value).to eq(default_message)
+ it 'uses merge commit template' do
+ expect(page).not_to have_selector('#merge-message-edit')
+ first('.js-mr-widget-commits-count').click
+ expect(textbox).to be_visible
+ expect(textbox.value).to eq(merge_request.title)
+ end
end
end
diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
index af5ba14e310..9057b96bff0 100644
--- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do
click_button "Merge when pipeline succeeds"
expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds"
- expect(page).to have_content "The source branch will not be deleted"
+ expect(page).to have_content "Does not delete the source branch"
expect(page).to have_selector ".js-cancel-auto-merge"
visit project_merge_request_path(project, merge_request) # Needed to refresh the page
expect(page).to have_content /enabled an automatic merge when the pipeline for \h{8} succeeds/i
@@ -126,7 +126,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do
it 'allows to delete source branch' do
click_button "Delete source branch"
- expect(page).to have_content "The source branch will be deleted"
+ expect(page).to have_content "Deletes the source branch"
end
context 'when pipeline succeeds' do
diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb
index c339a7d9976..79e46e69157 100644
--- a/spec/features/merge_request/user_posts_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
project.add_developer(user)
sign_in(user)
+ stub_feature_flags(bootstrap_confirmation_modals: false)
end
context 'when hovering over a parallel view diff file' do
@@ -237,8 +238,10 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
def should_allow_dismissing_a_comment(line_holder, diff_side = nil)
write_comment_on_line(line_holder, diff_side)
- accept_confirm do
- find('.js-close-discussion-note-form').click
+ find('.js-close-discussion-note-form').click
+
+ page.within('.modal') do
+ click_button 'OK'
end
assert_comment_dismissal(line_holder)
diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb
index 83d9388914b..0416474218f 100644
--- a/spec/features/merge_request/user_posts_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_notes_spec.rb
@@ -18,8 +18,10 @@ RSpec.describe 'Merge request > User posts notes', :js do
end
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
project.add_maintainer(user)
sign_in(user)
+
visit project_merge_request_path(project, merge_request)
end
diff --git a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
index 90cdc28d1bd..64cd5aa2bb1 100644
--- a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
@@ -79,6 +79,7 @@ RSpec.describe 'Merge request > User sees avatars on diff notes', :js do
%w(parallel).each do |view|
context "#{view} view" do
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
visit diffs_project_merge_request_path(project, merge_request, view: view)
wait_for_requests
diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
index 873cc0a89c6..345404cc28f 100644
--- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
@@ -110,6 +110,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do
let(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
build.success!
deployment.update!(on_stop: manual.name)
visit project_merge_request_path(project, merge_request)
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index f74b097ab3e..0117cf01e53 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -426,7 +426,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
it 'user cannot remove source branch', :sidekiq_might_not_need_inline do
expect(page).not_to have_field('remove-source-branch-input')
- expect(page).to have_content('The source branch will be deleted')
+ expect(page).to have_content('Deletes the source branch')
end
end
diff --git a/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb b/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb
index 3893a9cdf28..2191849edd9 100644
--- a/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb
+++ b/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb
@@ -16,7 +16,8 @@ RSpec.describe 'Merge request > User sees suggest pipeline', :js do
end
it 'shows the suggest pipeline widget and then allows dismissal correctly' do
- expect(page).to have_content('Are you adding technical debt or code vulnerabilities?')
+ content = 'GitLab CI/CD can automatically build, test, and deploy your application'
+ expect(page).to have_content(content)
page.within '.mr-pipeline-suggest' do
find('[data-testid="close"]').click
@@ -24,17 +25,16 @@ RSpec.describe 'Merge request > User sees suggest pipeline', :js do
wait_for_requests
- expect(page).not_to have_content('Are you adding technical debt or code vulnerabilities?')
+ expect(page).not_to have_content(content)
# Reload so we know the user callout was registered
visit page.current_url
- expect(page).not_to have_content('Are you adding technical debt or code vulnerabilities?')
+ expect(page).not_to have_content(content)
end
- it 'runs tour from start to finish ensuring all nudges are executed' do
- # nudge 1
- expect(page).to have_content('Are you adding technical debt or code vulnerabilities?')
+ it 'takes the user to the pipeline editor with a pre-filled CI config file form' do
+ expect(page).to have_content('GitLab CI/CD can automatically build, test, and deploy your application')
page.within '.mr-pipeline-suggest' do
find('[data-testid="ok"]').click
@@ -42,30 +42,14 @@ RSpec.describe 'Merge request > User sees suggest pipeline', :js do
wait_for_requests
- # nudge 2
- expect(page).to have_content('Choose Code Quality to add a pipeline that tests the quality of your code.')
+ # Drawer is open
+ expect(page).to have_content('This template creates a simple test pipeline. To use it:')
- find('.js-gitlab-ci-yml-selector').click
+ # Editor shows template
+ expect(page).to have_content('This file is a template, and might need editing before it works on your project.')
- wait_for_requests
-
- within '.gitlab-ci-yml-selector' do
- find('.dropdown-input-field').set('Jekyll')
- find('.dropdown-content li', text: 'Jekyll').click
- end
-
- wait_for_requests
-
- expect(page).not_to have_content('Choose Code Quality to add a pipeline that tests the quality of your code.')
- # nudge 3
- expect(page).to have_content('The template is ready!')
-
- find('#commit-changes').click
-
- wait_for_requests
-
- # nudge 4
- expect(page).to have_content("That's it, well done!")
+ # Commit form is shown
+ expect(page).to have_button('Commit changes')
end
context 'when feature setting is disabled' do
diff --git a/spec/features/oauth_login_spec.rb b/spec/features/oauth_login_spec.rb
index 3402bda5a41..0ea14bc00a5 100644
--- a/spec/features/oauth_login_spec.rb
+++ b/spec/features/oauth_login_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe 'OAuth Login', :js, :allow_forgery_protection do
end
providers = [:github, :twitter, :bitbucket, :gitlab, :google_oauth2,
- :facebook, :cas3, :auth0, :authentiq, :salesforce]
+ :facebook, :cas3, :auth0, :authentiq, :salesforce, :dingtalk]
around do |example|
with_omniauth_full_host { example.run }
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index 9a261c6d9c8..7d935298f38 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe 'Profile account page', :js do
let(:user) { create(:user) }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
sign_in(user)
end
@@ -80,6 +81,7 @@ RSpec.describe 'Profile account page', :js do
describe 'when I reset incoming email token' do
before do
allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true)
+ stub_feature_flags(bootstrap_confirmation_modals: false)
visit profile_personal_access_tokens_path
end
diff --git a/spec/features/profiles/active_sessions_spec.rb b/spec/features/profiles/active_sessions_spec.rb
index fd64704b7c8..a515c7b1c1f 100644
--- a/spec/features/profiles/active_sessions_spec.rb
+++ b/spec/features/profiles/active_sessions_spec.rb
@@ -11,6 +11,10 @@ RSpec.describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do
let(:admin) { create(:admin) }
+ before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
+ end
+
it 'user sees their active sessions' do
travel_to(Time.zone.parse('2018-03-12 09:06')) do
Capybara::Session.new(:session1)
diff --git a/spec/features/profiles/emails_spec.rb b/spec/features/profiles/emails_spec.rb
index 6b6f628e2d5..8f05de60be9 100644
--- a/spec/features/profiles/emails_spec.rb
+++ b/spec/features/profiles/emails_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Profile > Emails' do
let(:user) { create(:user) }
+ let(:other_user) { create(:user) }
before do
sign_in(user)
@@ -23,15 +24,25 @@ RSpec.describe 'Profile > Emails' do
expect(page).to have_content('Resend confirmation email')
end
- it 'does not add a duplicate email' do
- fill_in('Email', with: user.email)
+ it 'does not add an email that is the primary email of another user' do
+ fill_in('Email', with: other_user.email)
click_button('Add email address')
- email = user.emails.find_by(email: user.email)
+ email = user.emails.find_by(email: other_user.email)
expect(email).to be_nil
expect(page).to have_content('Email has already been taken')
end
+ it 'adds an email that is the primary email of the same user' do
+ fill_in('Email', with: user.email)
+ click_button('Add email address')
+
+ email = user.emails.find_by(email: user.email)
+ expect(email).to be_present
+ expect(page).to have_content("#{user.email} Verified")
+ expect(page).not_to have_content("#{user.email} Unverified")
+ end
+
it 'does not add an invalid email' do
fill_in('Email', with: 'test.@example.com')
click_button('Add email address')
diff --git a/spec/features/profiles/oauth_applications_spec.rb b/spec/features/profiles/oauth_applications_spec.rb
index 2735f601307..6827dff5434 100644
--- a/spec/features/profiles/oauth_applications_spec.rb
+++ b/spec/features/profiles/oauth_applications_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe 'Profile > Applications' do
let(:application) { create(:oauth_application, owner: user) }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
sign_in(user)
end
diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb
index 8f44299b18f..74505633cae 100644
--- a/spec/features/profiles/personal_access_tokens_spec.rb
+++ b/spec/features/profiles/personal_access_tokens_spec.rb
@@ -34,6 +34,7 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
end
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
sign_in(user)
end
diff --git a/spec/features/profiles/two_factor_auths_spec.rb b/spec/features/profiles/two_factor_auths_spec.rb
index 3f5789e119a..a9256a73d7b 100644
--- a/spec/features/profiles/two_factor_auths_spec.rb
+++ b/spec/features/profiles/two_factor_auths_spec.rb
@@ -45,6 +45,19 @@ RSpec.describe 'Two factor auths' do
expect(page).to have_content('Status: Enabled')
end
end
+
+ context 'when invalid pin is provided' do
+ let_it_be(:user) { create(:omniauth_user) }
+
+ it 'renders a error alert with a link to the troubleshooting section' do
+ visit profile_two_factor_auth_path
+
+ fill_in 'pin_code', with: '123'
+ click_button 'Register with two-factor app'
+
+ expect(page).to have_link('Try the troubleshooting steps here.', href: help_page_path('user/profile/account/two_factor_authentication.md', anchor: 'troubleshooting'))
+ end
+ end
end
context 'when user has two-factor authentication enabled' do
@@ -57,7 +70,9 @@ RSpec.describe 'Two factor auths' do
click_button 'Disable two-factor authentication'
- page.accept_alert
+ page.within('[role="dialog"]') do
+ click_button 'Disable'
+ end
expect(page).to have_content('You must provide a valid current password')
@@ -65,7 +80,9 @@ RSpec.describe 'Two factor auths' do
click_button 'Disable two-factor authentication'
- page.accept_alert
+ page.within('[role="dialog"]') do
+ click_button 'Disable'
+ end
expect(page).to have_content('Two-factor authentication has been disabled successfully!')
expect(page).to have_content('Enable two-factor authentication')
@@ -95,7 +112,9 @@ RSpec.describe 'Two factor auths' do
click_button 'Disable two-factor authentication'
- page.accept_alert
+ page.within('[role="dialog"]') do
+ click_button 'Disable'
+ end
expect(page).to have_content('Two-factor authentication has been disabled successfully!')
expect(page).to have_content('Enable two-factor authentication')
diff --git a/spec/features/profiles/user_manages_applications_spec.rb b/spec/features/profiles/user_manages_applications_spec.rb
index c76ef2613fd..ea7a6b4b6ba 100644
--- a/spec/features/profiles/user_manages_applications_spec.rb
+++ b/spec/features/profiles/user_manages_applications_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe 'User manages applications' do
let_it_be(:user) { create(:user) }
let_it_be(:new_application_path) { applications_profile_path }
+ let_it_be(:index_path) { oauth_applications_path }
before do
sign_in(user)
diff --git a/spec/features/profiles/user_manages_emails_spec.rb b/spec/features/profiles/user_manages_emails_spec.rb
index 373c4f565f2..b037d5048aa 100644
--- a/spec/features/profiles/user_manages_emails_spec.rb
+++ b/spec/features/profiles/user_manages_emails_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'User manages emails' do
let(:user) { create(:user) }
+ let(:other_user) { create(:user) }
before do
sign_in(user)
@@ -11,7 +12,7 @@ RSpec.describe 'User manages emails' do
visit(profile_emails_path)
end
- it "shows user's emails" do
+ it "shows user's emails", :aggregate_failures do
expect(page).to have_content(user.email)
user.emails.each do |email|
@@ -19,7 +20,7 @@ RSpec.describe 'User manages emails' do
end
end
- it 'adds an email' do
+ it 'adds an email', :aggregate_failures do
fill_in('email_email', with: 'my@email.com')
click_button('Add')
@@ -34,21 +35,21 @@ RSpec.describe 'User manages emails' do
end
end
- it 'does not add a duplicate email' do
- fill_in('email_email', with: user.email)
+ it 'does not add an email that is the primary email of another user', :aggregate_failures do
+ fill_in('email_email', with: other_user.email)
click_button('Add')
- email = user.emails.find_by(email: user.email)
+ email = user.emails.find_by(email: other_user.email)
expect(email).to be_nil
- expect(page).to have_content(user.email)
+ expect(page).to have_content('Email has already been taken')
user.emails.each do |email|
expect(page).to have_content(email.email)
end
end
- it 'removes an email' do
+ it 'removes an email', :aggregate_failures do
fill_in('email_email', with: 'my@email.com')
click_button('Add')
diff --git a/spec/features/profiles/user_visits_profile_spec.rb b/spec/features/profiles/user_visits_profile_spec.rb
index 475fda5e7a1..273d52996d3 100644
--- a/spec/features/profiles/user_visits_profile_spec.rb
+++ b/spec/features/profiles/user_visits_profile_spec.rb
@@ -21,6 +21,14 @@ RSpec.describe 'User visits their profile' do
expect(page).to have_content "This information will appear on your profile"
end
+ it 'shows user readme' do
+ create(:project, :repository, :public, path: user.username, namespace: user.namespace)
+
+ visit(user_path(user))
+
+ expect(find('.file-content')).to have_content('testme')
+ end
+
context 'when user has groups' do
let(:group) do
create :group do |group|
diff --git a/spec/features/project_variables_spec.rb b/spec/features/project_variables_spec.rb
index 5139c724d82..cc59fea173b 100644
--- a/spec/features/project_variables_spec.rb
+++ b/spec/features/project_variables_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe 'Project variables', :js do
click_button('Add variable')
page.within('#add-ci-variable') do
- find('[data-qa-selector="ci_variable_key_field"] input').set('akey') # rubocop:disable QA/SelectorUsage
+ fill_in 'Key', with: 'akey'
find('#ci-variable-value').set('akey_value')
find('[data-testid="environment-scope"]').click
find('[data-testid="ci-environment-search"]').set('review/*')
diff --git a/spec/features/projects/branches/user_deletes_branch_spec.rb b/spec/features/projects/branches/user_deletes_branch_spec.rb
index 3b8f49accc5..8fc5c3d2e1b 100644
--- a/spec/features/projects/branches/user_deletes_branch_spec.rb
+++ b/spec/features/projects/branches/user_deletes_branch_spec.rb
@@ -35,6 +35,7 @@ RSpec.describe "User deletes branch", :js do
context 'when the feature flag :delete_branch_confirmation_modals is disabled' do
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
stub_feature_flags(delete_branch_confirmation_modals: false)
end
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index 0a79719f14a..2725c6a91be 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -179,6 +179,7 @@ RSpec.describe 'Branches' do
context 'when the delete_branch_confirmation_modals feature flag is disabled' do
it 'removes branch after confirmation', :js do
stub_feature_flags(delete_branch_confirmation_modals: false)
+ stub_feature_flags(bootstrap_confirmation_modals: false)
visit project_branches_filtered_path(project, state: 'all')
diff --git a/spec/features/projects/cluster_agents_spec.rb b/spec/features/projects/cluster_agents_spec.rb
new file mode 100644
index 00000000000..3ef710169f0
--- /dev/null
+++ b/spec/features/projects/cluster_agents_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'ClusterAgents', :js do
+ let_it_be(:token) { create(:cluster_agent_token, description: 'feature test token')}
+
+ let(:agent) { token.agent }
+ let(:project) { agent.project }
+ let(:user) { project.creator }
+
+ before do
+ gitlab_sign_in(user)
+ end
+
+ context 'when user does not have any agents and visits the index page' do
+ let(:empty_project) { create(:project) }
+
+ before do
+ empty_project.add_maintainer(user)
+ visit project_clusters_path(empty_project)
+ end
+
+ it 'displays empty state', :aggregate_failures do
+ expect(page).to have_content('Install new Agent')
+ expect(page).to have_selector('.empty-state')
+ end
+ end
+
+ context 'when user has an agent' do
+ context 'when visiting the index page' do
+ before do
+ visit project_clusters_path(project)
+ end
+
+ it 'displays a table with agent', :aggregate_failures do
+ expect(page).to have_content(agent.name)
+ expect(page).to have_selector('[data-testid="cluster-agent-list-table"] tbody tr', count: 1)
+ end
+ end
+
+ context 'when visiting the show page' do
+ before do
+ visit project_cluster_agent_path(project, agent.name)
+ end
+
+ it 'displays agent and token information', :aggregate_failures do
+ expect(page).to have_content(agent.name)
+ expect(page).to have_content(token.description)
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/clusters/eks_spec.rb b/spec/features/projects/clusters/eks_spec.rb
index 9f3f331cfab..09c10c0b3a9 100644
--- a/spec/features/projects/clusters/eks_spec.rb
+++ b/spec/features/projects/clusters/eks_spec.rb
@@ -19,7 +19,8 @@ RSpec.describe 'AWS EKS Cluster', :js do
before do
visit project_clusters_path(project)
- click_link 'Integrate with a cluster certificate'
+ click_link 'Certificate based'
+ click_link 'Connect with a certificate'
end
context 'when user creates a cluster on AWS EKS' do
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index 21e587288f5..e1659cd2fbf 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -33,7 +33,8 @@ RSpec.describe 'Gcp Cluster', :js do
before do
visit project_clusters_path(project)
- click_link 'Integrate with a cluster certificate'
+ click_link 'Certificate based'
+ click_link 'Connect with a certificate'
click_link 'Create new cluster'
click_link 'Google GKE'
end
@@ -143,8 +144,9 @@ RSpec.describe 'Gcp Cluster', :js do
before do
visit project_clusters_path(project)
- click_link 'Connect cluster with certificate'
- click_link 'Connect existing cluster'
+ click_link 'Certificate based'
+ click_button(class: 'dropdown-toggle-split')
+ click_link 'Connect with certificate'
end
it 'user sees the "Environment scope" field' do
@@ -158,11 +160,12 @@ RSpec.describe 'Gcp Cluster', :js do
click_button 'Remove integration and resources'
fill_in 'confirm_cluster_name_input', with: cluster.name
click_button 'Remove integration'
+ click_link 'Certificate based'
end
it 'user sees creation form with the successful message' do
expect(page).to have_content('Kubernetes cluster integration was successfully removed.')
- expect(page).to have_link('Integrate with a cluster certificate')
+ expect(page).to have_link('Connect with a certificate')
end
end
end
@@ -171,6 +174,7 @@ RSpec.describe 'Gcp Cluster', :js do
context 'when user has not dismissed GCP signup offer' do
before do
visit project_clusters_path(project)
+ click_link 'Certificate based'
end
it 'user sees offer on cluster index page' do
@@ -178,7 +182,7 @@ RSpec.describe 'Gcp Cluster', :js do
end
it 'user sees offer on cluster create page' do
- click_link 'Integrate with a cluster certificate'
+ click_link 'Connect with a certificate'
expect(page).to have_css('.gcp-signup-offer')
end
@@ -187,6 +191,7 @@ RSpec.describe 'Gcp Cluster', :js do
context 'when user has dismissed GCP signup offer' do
before do
visit project_clusters_path(project)
+ click_link 'Certificate based'
end
it 'user does not see offer after dismissing' do
@@ -195,19 +200,18 @@ RSpec.describe 'Gcp Cluster', :js do
find('.gcp-signup-offer .js-close').click
wait_for_requests
- click_link 'Integrate with a cluster certificate'
+ click_link 'Connect with a certificate'
expect(page).not_to have_css('.gcp-signup-offer')
end
end
context 'when third party offers are disabled', :clean_gitlab_redis_shared_state do
- let(:admin) { create(:admin) }
+ let(:user) { create(:admin) }
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(user)
visit general_admin_application_settings_path
end
diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb
index 5b60edbcf87..d3f709bfb53 100644
--- a/spec/features/projects/clusters/user_spec.rb
+++ b/spec/features/projects/clusters/user_spec.rb
@@ -25,7 +25,8 @@ RSpec.describe 'User Cluster', :js do
before do
visit project_clusters_path(project)
- click_link 'Integrate with a cluster certificate'
+ click_link 'Certificate based'
+ click_link 'Connect with a certificate'
click_link 'Connect existing cluster'
end
@@ -112,11 +113,12 @@ RSpec.describe 'User Cluster', :js do
click_button 'Remove integration and resources'
fill_in 'confirm_cluster_name_input', with: cluster.name
click_button 'Remove integration'
+ click_link 'Certificate based'
end
it 'user sees creation form with the successful message' do
expect(page).to have_content('Kubernetes cluster integration was successfully removed.')
- expect(page).to have_link('Integrate with a cluster certificate')
+ expect(page).to have_link('Connect with a certificate')
end
end
end
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
index 6b03301aa74..a49fa4c9e31 100644
--- a/spec/features/projects/clusters_spec.rb
+++ b/spec/features/projects/clusters_spec.rb
@@ -16,10 +16,11 @@ RSpec.describe 'Clusters', :js do
context 'when user does not have a cluster and visits cluster index page' do
before do
visit project_clusters_path(project)
+ click_link 'Certificate based'
end
it 'sees empty state' do
- expect(page).to have_link('Integrate with a cluster certificate')
+ expect(page).to have_link('Connect with a certificate')
expect(page).to have_selector('.empty-state')
end
end
@@ -33,16 +34,17 @@ RSpec.describe 'Clusters', :js do
before do
create(:cluster, :provided_by_user, name: 'default-cluster', environment_scope: '*', projects: [project])
visit project_clusters_path(project)
+ click_link 'Certificate based'
+ click_button(class: 'dropdown-toggle-split')
end
it 'user sees an add cluster button' do
- expect(page).to have_selector('.js-add-cluster:not(.readonly)')
+ expect(page).to have_content('Connect with certificate')
end
context 'when user filled form with environment scope' do
before do
- click_link 'Connect cluster with certificate'
- click_link 'Connect existing cluster'
+ click_link 'Connect with certificate'
fill_in 'cluster_name', with: 'staging-cluster'
fill_in 'cluster_environment_scope', with: 'staging/*'
click_button 'Add Kubernetes cluster'
@@ -70,8 +72,7 @@ RSpec.describe 'Clusters', :js do
context 'when user updates duplicated environment scope' do
before do
- click_link 'Connect cluster with certificate'
- click_link 'Connect existing cluster'
+ click_link 'Connect with certificate'
fill_in 'cluster_name', with: 'staging-cluster'
fill_in 'cluster_environment_scope', with: '*'
fill_in 'cluster_platform_kubernetes_attributes_api_url', with: 'https://0.0.0.0'
@@ -108,15 +109,12 @@ RSpec.describe 'Clusters', :js do
create(:cluster, :provided_by_gcp, name: 'default-cluster', environment_scope: '*', projects: [project])
visit project_clusters_path(project)
- end
-
- it 'user sees a add cluster button' do
- expect(page).to have_selector('.js-add-cluster:not(.readonly)')
+ click_link 'Certificate based'
end
context 'when user filled form with environment scope' do
before do
- click_link 'Connect cluster with certificate'
+ click_button(class: 'dropdown-toggle-split')
click_link 'Create new cluster'
click_link 'Google GKE'
@@ -161,7 +159,7 @@ RSpec.describe 'Clusters', :js do
context 'when user updates duplicated environment scope' do
before do
- click_link 'Connect cluster with certificate'
+ click_button(class: 'dropdown-toggle-split')
click_link 'Create new cluster'
click_link 'Google GKE'
@@ -192,6 +190,7 @@ RSpec.describe 'Clusters', :js do
before do
visit project_clusters_path(project)
+ click_link 'Certificate based'
end
it 'user sees a table with one cluster' do
@@ -214,7 +213,8 @@ RSpec.describe 'Clusters', :js do
before do
visit project_clusters_path(project)
- click_link 'Integrate with a cluster certificate'
+ click_link 'Certificate based'
+ click_link 'Connect with a certificate'
click_link 'Create new cluster'
end
diff --git a/spec/features/projects/commit/comments/user_deletes_comments_spec.rb b/spec/features/projects/commit/comments/user_deletes_comments_spec.rb
index 431cbb4ffbb..67d3276fc14 100644
--- a/spec/features/projects/commit/comments/user_deletes_comments_spec.rb
+++ b/spec/features/projects/commit/comments/user_deletes_comments_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe "User deletes comments on a commit", :js do
let(:user) { create(:user) }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
sign_in(user)
project.add_developer(user)
diff --git a/spec/features/projects/commit/user_comments_on_commit_spec.rb b/spec/features/projects/commit/user_comments_on_commit_spec.rb
index 6997c2d8338..b0be6edb245 100644
--- a/spec/features/projects/commit/user_comments_on_commit_spec.rb
+++ b/spec/features/projects/commit/user_comments_on_commit_spec.rb
@@ -93,6 +93,8 @@ RSpec.describe "User comments on commit", :js do
context "when deleting comment" do
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
+
visit(project_commit_path(project, sample_commit.id))
add_note(comment_text)
diff --git a/spec/features/projects/confluence/user_views_confluence_page_spec.rb b/spec/features/projects/confluence/user_views_confluence_page_spec.rb
index ece2f82f5c6..49e7839f16c 100644
--- a/spec/features/projects/confluence/user_views_confluence_page_spec.rb
+++ b/spec/features/projects/confluence/user_views_confluence_page_spec.rb
@@ -16,9 +16,12 @@ RSpec.describe 'User views the Confluence page' do
visit project_wikis_confluence_path(project)
+ expect(page).to have_css('.nav-sidebar li.active', text: 'Confluence', match: :first)
+
element = page.find('.row.empty-state')
expect(element).to have_link('Go to Confluence', href: service.confluence_url)
+ expect(element).to have_link('Confluence epic', href: 'https://gitlab.com/groups/gitlab-org/-/epics/3629')
end
it 'does not show the page when the Confluence integration disabled' do
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index 5320f68b525..bcbf2f46f79 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -23,10 +23,6 @@ RSpec.describe 'Environment' do
let!(:action) { }
let!(:cluster) { }
- before do
- visit_environment(environment)
- end
-
context 'with auto-stop' do
let!(:environment) { create(:environment, :will_auto_stop, name: 'staging', project: project) }
@@ -52,12 +48,20 @@ RSpec.describe 'Environment' do
end
context 'without deployments' do
+ before do
+ visit_environment(environment)
+ end
+
it 'does not show deployments' do
expect(page).to have_content('You don\'t have any deployments right now.')
end
end
context 'with deployments' do
+ before do
+ visit_environment(environment)
+ end
+
context 'when there is no related deployable' do
let(:deployment) do
create(:deployment, :success, environment: environment, deployable: nil)
@@ -108,6 +112,26 @@ RSpec.describe 'Environment' do
end
end
+ context 'with many deployments' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+
+ let!(:second) { create(:deployment, environment: environment, deployable: build, status: :success, finished_at: Time.current) }
+ let!(:first) { create(:deployment, environment: environment, deployable: build, status: :running) }
+ let!(:last) { create(:deployment, environment: environment, deployable: build, status: :success, finished_at: 2.days.ago) }
+ let!(:third) { create(:deployment, environment: environment, deployable: build, status: :canceled, finished_at: 1.day.ago) }
+
+ before do
+ visit_environment(environment)
+ end
+
+ it 'shows all of them in ordered way' do
+ ids = find_all('[data-testid="deployment-id"]').map { |e| e.text }
+ expected_ordered_ids = [first, second, third, last].map { |d| "##{d.iid}" }
+ expect(ids).to eq(expected_ordered_ids)
+ end
+ end
+
context 'with related deployable present' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
@@ -116,6 +140,10 @@ RSpec.describe 'Environment' do
create(:deployment, :success, environment: environment, deployable: build)
end
+ before do
+ visit_environment(environment)
+ end
+
it 'does show build name' do
expect(page).to have_link("#{build.name} (##{build.id})")
end
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index 34e2ca7c8a7..3b83c25b629 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe 'Environments page', :js do
let(:role) { :developer }
before do
+ stub_feature_flags(new_environments_table: false)
project.add_role(user, role)
sign_in(user)
end
@@ -142,6 +143,8 @@ RSpec.describe 'Environments page', :js do
create(:environment, project: project, state: :available)
end
+ stub_feature_flags(bootstrap_confirmation_modals: false)
+
context 'when there are no deployments' do
before do
visit_environments(project)
diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb
index 00e85a215b8..3afd1937652 100644
--- a/spec/features/projects/import_export/import_file_spec.rb
+++ b/spec/features/projects/import_export/import_file_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe 'Import/Export - project import integration test', :js do
it 'user imports an exported project successfully', :sidekiq_might_not_need_inline do
visit new_project_path
- click_import_project
+ click_link 'Import project'
click_link 'GitLab export'
fill_in :name, with: 'Test Project Name', visible: true
@@ -50,7 +50,7 @@ RSpec.describe 'Import/Export - project import integration test', :js do
visit new_project_path
- click_import_project
+ click_link 'Import project'
click_link 'GitLab export'
fill_in :name, with: project.name, visible: true
attach_file('file', file)
@@ -61,8 +61,4 @@ RSpec.describe 'Import/Export - project import integration test', :js do
end
end
end
-
- def click_import_project
- find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
- end
end
diff --git a/spec/features/projects/infrastructure_registry_spec.rb b/spec/features/projects/infrastructure_registry_spec.rb
index ee35e02b5e8..27d0866bc69 100644
--- a/spec/features/projects/infrastructure_registry_spec.rb
+++ b/spec/features/projects/infrastructure_registry_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe 'Infrastructure Registry' do
expect(page).to have_current_path(project_infrastructure_registry_path(terraform_module.project, terraform_module))
- expect(page).to have_css('.packages-app h1[data-testid="title"]', text: terraform_module.name)
+ expect(page).to have_css('.packages-app h2[data-testid="title"]', text: terraform_module.name)
expect(page).to have_content('Provision instructions')
expect(page).to have_content('Registry setup')
diff --git a/spec/features/projects/integrations/user_uses_inherited_settings_spec.rb b/spec/features/projects/integrations/user_uses_inherited_settings_spec.rb
index f46cade9d5f..d2c4418f0d6 100644
--- a/spec/features/projects/integrations/user_uses_inherited_settings_spec.rb
+++ b/spec/features/projects/integrations/user_uses_inherited_settings_spec.rb
@@ -84,7 +84,7 @@ RSpec.describe 'User uses inherited settings', :js do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:parent_settings) { { url: 'http://group.com', password: 'group' } }
- let_it_be(:parent_integration) { create(:jira_integration, group: group, project: nil, **parent_settings) }
+ let_it_be(:parent_integration) { create(:jira_integration, :group, group: group, **parent_settings) }
it_behaves_like 'inherited settings'
end
diff --git a/spec/features/projects/jobs/user_browses_job_spec.rb b/spec/features/projects/jobs/user_browses_job_spec.rb
index 060b7ffbfc9..12e88bbf6a5 100644
--- a/spec/features/projects/jobs/user_browses_job_spec.rb
+++ b/spec/features/projects/jobs/user_browses_job_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe 'User browses a job', :js do
before do
project.add_maintainer(user)
project.enable_ci
+ stub_feature_flags(bootstrap_confirmation_modals: false)
sign_in(user)
@@ -36,8 +37,18 @@ RSpec.describe 'User browses a job', :js do
expect(page).to have_content('Job has been erased')
end
- context 'with a failed job' do
- let!(:build) { create(:ci_build, :failed, :trace_artifact, pipeline: pipeline) }
+ context 'with unarchived trace artifact' do
+ let!(:build) { create(:ci_build, :success, :unarchived_trace_artifact, :coverage, pipeline: pipeline) }
+
+ it 'shows no trace message', :js do
+ wait_for_requests
+
+ expect(page).to have_content('This job does not have a trace.')
+ end
+ end
+
+ context 'with a failed job and live trace' do
+ let!(:build) { create(:ci_build, :failed, :trace_live, pipeline: pipeline) }
it 'displays the failure reason' do
wait_for_all_requests
@@ -46,6 +57,18 @@ RSpec.describe 'User browses a job', :js do
".build-job > a[title='test - failed - (unknown failure)']")
end
end
+
+ context 'with unarchived trace artifact' do
+ let!(:artifact) { create(:ci_job_artifact, :unarchived_trace_artifact, job: build) }
+
+ it 'displays the failure reason from the live trace' do
+ wait_for_all_requests
+ within('.builds-container') do
+ expect(page).to have_selector(
+ ".build-job > a[title='test - failed - (unknown failure)']")
+ end
+ end
+ end
end
context 'when a failed job has been retried' do
diff --git a/spec/features/projects/jobs/user_triggers_manual_job_with_variables_spec.rb b/spec/features/projects/jobs/user_triggers_manual_job_with_variables_spec.rb
new file mode 100644
index 00000000000..e8a14694d88
--- /dev/null
+++ b/spec/features/projects/jobs/user_triggers_manual_job_with_variables_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'User triggers manual job with variables', :js do
+ let(:user) { create(:user) }
+ let(:user_access_level) { :developer }
+ let(:project) { create(:project, :repository, namespace: user.namespace) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') }
+ let!(:build) { create(:ci_build, :manual, pipeline: pipeline) }
+
+ before do
+ project.add_maintainer(user)
+ project.enable_ci
+
+ sign_in(user)
+
+ visit(project_job_path(project, build))
+ end
+
+ it 'passes values correctly' do
+ page.within(find("[data-testid='ci-variable-row']")) do
+ find("[data-testid='ci-variable-key']").set('key_name')
+ find("[data-testid='ci-variable-value']").set('key_value')
+ end
+
+ find("[data-testid='trigger-manual-job-btn']").click
+
+ wait_for_requests
+
+ expect(build.job_variables.as_json).to contain_exactly(
+ hash_including('key' => 'key_name', 'value' => 'key_value'))
+ end
+end
diff --git a/spec/features/projects/members/member_leaves_project_spec.rb b/spec/features/projects/members/member_leaves_project_spec.rb
index c4bd0b81dc0..4881a7bdf1a 100644
--- a/spec/features/projects/members/member_leaves_project_spec.rb
+++ b/spec/features/projects/members/member_leaves_project_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe 'Projects > Members > Member leaves project' do
before do
project.add_developer(user)
sign_in(user)
+ stub_feature_flags(bootstrap_confirmation_modals: false)
end
it 'user leaves project' do
diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb
index 113ba692497..dcaef5f4ef0 100644
--- a/spec/features/projects/members/user_requests_access_spec.rb
+++ b/spec/features/projects/members/user_requests_access_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe 'Projects > Members > User requests access', :js do
before do
sign_in(user)
visit project_path(project)
+ stub_feature_flags(bootstrap_confirmation_modals: false)
end
it 'request access feature is disabled' do
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index dacbaa826a0..4dedd5689de 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe 'New project', :js do
)
visit new_project_path
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
expect(page).to have_content 'Other visibility settings have been disabled by the administrator.'
end
@@ -34,7 +34,7 @@ RSpec.describe 'New project', :js do
)
visit new_project_path
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
expect(page).to have_content 'Visibility settings have been disabled by the administrator.'
end
@@ -49,14 +49,14 @@ RSpec.describe 'New project', :js do
it 'shows "New project" page', :js do
visit new_project_path
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
expect(page).to have_content('Project name')
expect(page).to have_content('Project URL')
expect(page).to have_content('Project slug')
click_link('New project')
- find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Import project'
expect(page).to have_link('GitHub')
expect(page).to have_link('Bitbucket')
@@ -69,7 +69,7 @@ RSpec.describe 'New project', :js do
before do
visit new_project_path
- find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Import project'
end
it 'has Manifest file' do
@@ -83,7 +83,7 @@ RSpec.describe 'New project', :js do
stub_application_setting(default_project_visibility: level)
visit new_project_path
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
page.within('#blank-project-pane') do
expect(find_field("project_visibility_level_#{level}")).to be_checked
end
@@ -91,7 +91,7 @@ RSpec.describe 'New project', :js do
it "saves visibility level #{level} on validation error" do
visit new_project_path
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
choose(key)
click_button('Create project')
@@ -111,7 +111,7 @@ RSpec.describe 'New project', :js do
context 'when admin mode is enabled', :enable_admin_mode do
it 'has private selected' do
visit new_project_path(namespace_id: group.id)
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
page.within('#blank-project-pane') do
expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked
@@ -138,7 +138,7 @@ RSpec.describe 'New project', :js do
context 'when admin mode is enabled', :enable_admin_mode do
it 'has private selected' do
visit new_project_path(namespace_id: group.id, project: { visibility_level: Gitlab::VisibilityLevel::PRIVATE })
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
page.within('#blank-project-pane') do
expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked
@@ -159,7 +159,7 @@ RSpec.describe 'New project', :js do
context 'Readme selector' do
it 'shows the initialize with Readme checkbox on "Blank project" tab' do
visit new_project_path
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
expect(page).to have_css('input#project_initialize_with_readme')
expect(page).to have_content('Initialize repository with a README')
@@ -167,7 +167,7 @@ RSpec.describe 'New project', :js do
it 'does not show the initialize with Readme checkbox on "Create from template" tab' do
visit new_project_path
- find('[data-qa-panel-name="create_from_template"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create from template'
first('.choose-template').click
page.within '.project-fields-form' do
@@ -178,7 +178,7 @@ RSpec.describe 'New project', :js do
it 'does not show the initialize with Readme checkbox on "Import project" tab' do
visit new_project_path
- find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Import project'
first('.js-import-git-toggle-button').click
page.within '#import-project-pane' do
@@ -192,7 +192,7 @@ RSpec.describe 'New project', :js do
context 'with user namespace' do
before do
visit new_project_path
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
end
it 'selects the user namespace' do
@@ -208,7 +208,7 @@ RSpec.describe 'New project', :js do
before do
group.add_owner(user)
visit new_project_path(namespace_id: group.id)
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
end
it 'selects the group namespace' do
@@ -225,7 +225,7 @@ RSpec.describe 'New project', :js do
before do
group.add_maintainer(user)
visit new_project_path(namespace_id: subgroup.id)
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
end
it 'selects the group namespace' do
@@ -245,7 +245,7 @@ RSpec.describe 'New project', :js do
internal_group.add_owner(user)
private_group.add_owner(user)
visit new_project_path(namespace_id: public_group.id)
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
end
it 'enables the correct visibility options' do
@@ -275,7 +275,7 @@ RSpec.describe 'New project', :js do
context 'Import project options', :js do
before do
visit new_project_path
- find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Import project'
end
context 'from git repository url, "Repo by URL"' do
@@ -351,7 +351,7 @@ RSpec.describe 'New project', :js do
before do
group.add_developer(user)
visit new_project_path(namespace_id: group.id)
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
end
it 'selects the group namespace' do
diff --git a/spec/features/projects/packages_spec.rb b/spec/features/projects/packages_spec.rb
index 9b1e87192f5..7fcc8200b1c 100644
--- a/spec/features/projects/packages_spec.rb
+++ b/spec/features/projects/packages_spec.rb
@@ -27,10 +27,6 @@ RSpec.describe 'Packages' do
context 'when feature is available', :js do
before do
- # we are simply setting the featrure flag to false because the new UI has nothing to test yet
- # when the refactor is complete or almost complete we will turn on the feature tests
- # see https://gitlab.com/gitlab-org/gitlab/-/issues/330846 for status of this work
- stub_feature_flags(package_list_apollo: false)
visit_project_packages
end
diff --git a/spec/features/projects/pages/user_adds_domain_spec.rb b/spec/features/projects/pages/user_adds_domain_spec.rb
index de9effe3dc7..06f130ae69c 100644
--- a/spec/features/projects/pages/user_adds_domain_spec.rb
+++ b/spec/features/projects/pages/user_adds_domain_spec.rb
@@ -14,6 +14,8 @@ RSpec.describe 'User adds pages domain', :js do
project.add_maintainer(user)
sign_in(user)
+
+ stub_feature_flags(bootstrap_confirmation_modals: false)
end
context 'when pages are exposed on external HTTP address', :http_pages_enabled do
diff --git a/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb
index cf8438d5e6f..a3fc5804e13 100644
--- a/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb
+++ b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled do
before do
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
stub_lets_encrypt_settings
+ stub_feature_flags(bootstrap_confirmation_modals: false)
project.add_role(user, role)
sign_in(user)
diff --git a/spec/features/projects/pages/user_edits_settings_spec.rb b/spec/features/projects/pages/user_edits_settings_spec.rb
index 71d4cce2784..1226e1dc2ed 100644
--- a/spec/features/projects/pages/user_edits_settings_spec.rb
+++ b/spec/features/projects/pages/user_edits_settings_spec.rb
@@ -176,6 +176,7 @@ RSpec.describe 'Pages edits pages settings', :js do
describe 'Remove page' do
context 'when pages are deployed' do
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
project.mark_pages_as_deployed
end
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
index 94e3331b173..9df430c0f78 100644
--- a/spec/features/projects/pipeline_schedules_spec.rb
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe 'Pipeline Schedules', :js do
context 'logged in as maintainer' do
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
project.add_maintainer(user)
gitlab_sign_in(user)
end
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index bd22c8632e4..e38c4989f26 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -317,6 +317,7 @@ RSpec.describe 'Pipelines', :js do
end
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
visit_project_pipelines
end
@@ -635,7 +636,7 @@ RSpec.describe 'Pipelines', :js do
# header
expect(page).to have_text("##{pipeline.id}")
- expect(page).to have_selector(%Q(img[alt$="#{pipeline.user.name}'s avatar"]))
+ expect(page).to have_selector(%Q(img[src="#{pipeline.user.avatar_url}"]))
expect(page).to have_link(pipeline.user.name, href: user_path(pipeline.user))
# stages
diff --git a/spec/features/projects/releases/user_views_releases_spec.rb b/spec/features/projects/releases/user_views_releases_spec.rb
index 6bc4c66b8ca..98935fdf872 100644
--- a/spec/features/projects/releases/user_views_releases_spec.rb
+++ b/spec/features/projects/releases/user_views_releases_spec.rb
@@ -123,11 +123,11 @@ RSpec.describe 'User views releases', :js do
within('.release-block', match: :first) do
expect(page).to have_content(release_v3.description)
+ expect(page).to have_content(release_v3.tag)
+ expect(page).to have_content(release_v3.name)
# The following properties (sometimes) include Git info,
# so they are not rendered for Guest users
- expect(page).not_to have_content(release_v3.name)
- expect(page).not_to have_content(release_v3.tag)
expect(page).not_to have_content(release_v3.commit.short_id)
end
end
diff --git a/spec/features/projects/settings/access_tokens_spec.rb b/spec/features/projects/settings/access_tokens_spec.rb
index 4941b936c0c..d8de9e0449e 100644
--- a/spec/features/projects/settings/access_tokens_spec.rb
+++ b/spec/features/projects/settings/access_tokens_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe 'Project > Settings > Access Tokens', :js do
end
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
sign_in(user)
end
diff --git a/spec/features/projects/settings/packages_settings_spec.rb b/spec/features/projects/settings/packages_settings_spec.rb
index 62f31fd027b..e70839e9720 100644
--- a/spec/features/projects/settings/packages_settings_spec.rb
+++ b/spec/features/projects/settings/packages_settings_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe 'Projects > Settings > Packages', :js do
let(:packages_enabled) { true }
it 'displays the packages toggle button' do
- expect(page).to have_button('Packages', class: 'gl-toggle')
+ expect(page).to have_selector('[data-testid="toggle-label"]', text: 'Packages')
expect(page).to have_selector('input[name="project[packages_enabled]"] + button', visible: true)
end
end
@@ -28,7 +28,7 @@ RSpec.describe 'Projects > Settings > Packages', :js do
let(:packages_enabled) { false }
it 'does not show up in UI' do
- expect(page).not_to have_button('Packages', class: 'gl-toggle')
+ expect(page).not_to have_selector('[data-testid="toggle-label"]', text: 'Packages')
end
end
end
diff --git a/spec/features/projects/settings/service_desk_setting_spec.rb b/spec/features/projects/settings/service_desk_setting_spec.rb
index 0924f8320e1..0df4bd3f0d9 100644
--- a/spec/features/projects/settings/service_desk_setting_spec.rb
+++ b/spec/features/projects/settings/service_desk_setting_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe 'Service Desk Setting', :js, :clean_gitlab_redis_cache do
wait_for_requests
project.reload
- expect(find('[data-testid="incoming-email"]').value).to eq(project.service_desk_incoming_address)
+ expect(find('[data-testid="incoming-email"]').value).to eq(project.service_desk_custom_address)
page.within '#js-service-desk' do
fill_in('service-desk-project-suffix', with: 'foo')
diff --git a/spec/features/projects/settings/user_searches_in_settings_spec.rb b/spec/features/projects/settings/user_searches_in_settings_spec.rb
index 7ed96d01189..44b5464a1b0 100644
--- a/spec/features/projects/settings/user_searches_in_settings_spec.rb
+++ b/spec/features/projects/settings/user_searches_in_settings_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe 'User searches project settings', :js do
let_it_be(:project) { create(:project, :repository, namespace: user.namespace, pages_https_only: false) }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
sign_in(user)
end
diff --git a/spec/features/projects/settings/user_tags_project_spec.rb b/spec/features/projects/settings/user_tags_project_spec.rb
index ff19ed22744..e9a2aa29352 100644
--- a/spec/features/projects/settings/user_tags_project_spec.rb
+++ b/spec/features/projects/settings/user_tags_project_spec.rb
@@ -2,22 +2,40 @@
require 'spec_helper'
-RSpec.describe 'Projects > Settings > User tags a project' do
+RSpec.describe 'Projects > Settings > User tags a project', :js do
let(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace) }
+ let!(:topic) { create(:topic, name: 'topic1') }
before do
sign_in(user)
visit edit_project_path(project)
+ wait_for_all_requests
end
- it 'sets project topics' do
- fill_in 'Topics', with: 'topic1, topic2'
+ it 'select existing topic' do
+ fill_in class: 'gl-token-selector-input', with: 'topic1'
+ wait_for_all_requests
+
+ find('.gl-avatar-labeled[entity-name="topic1"]').click
+
+ page.within '.general-settings' do
+ click_button 'Save changes'
+ end
+
+ expect(find('#project_topic_list_field', visible: :hidden).value).to eq 'topic1'
+ end
+
+ it 'select new topic' do
+ fill_in class: 'gl-token-selector-input', with: 'topic2'
+ wait_for_all_requests
+
+ click_button 'Add "topic2"'
page.within '.general-settings' do
click_button 'Save changes'
end
- expect(find_field('Topics').value).to eq 'topic1, topic2'
+ expect(find('#project_topic_list_field', visible: :hidden).value).to eq 'topic2'
end
end
diff --git a/spec/features/projects/show/no_password_spec.rb b/spec/features/projects/show/no_password_spec.rb
index d18ff75b324..ed06f4e14d3 100644
--- a/spec/features/projects/show/no_password_spec.rb
+++ b/spec/features/projects/show/no_password_spec.rb
@@ -3,6 +3,9 @@
require 'spec_helper'
RSpec.describe 'No Password Alert' do
+ let_it_be(:message_password_auth_enabled) { 'Your account is authenticated with SSO or SAML. To push and pull over HTTP with Git using this account, you must set a password or set up a Personal Access Token to use instead of a password. For more information, see Clone with HTTPS.' }
+ let_it_be(:message_password_auth_disabled) { 'Your account is authenticated with SSO or SAML. To push and pull over HTTP with Git using this account, you must set up a Personal Access Token to use instead of a password. For more information, see Clone with HTTPS.' }
+
let(:project) { create(:project, :repository, namespace: user.namespace) }
context 'with internal auth enabled' do
@@ -15,7 +18,7 @@ RSpec.describe 'No Password Alert' do
let(:user) { create(:user) }
it 'shows no alert' do
- expect(page).not_to have_content "You won't be able to pull or push repositories via HTTP until you set a password on your account"
+ expect(page).not_to have_content message_password_auth_enabled
end
end
@@ -23,7 +26,7 @@ RSpec.describe 'No Password Alert' do
let(:user) { create(:user, password_automatically_set: true) }
it 'shows a password alert' do
- expect(page).to have_content "You won't be able to pull or push repositories via HTTP until you set a password on your account"
+ expect(page).to have_content message_password_auth_enabled
end
end
end
@@ -41,7 +44,7 @@ RSpec.describe 'No Password Alert' do
gitlab_sign_in_via('saml', user, 'my-uid')
visit project_path(project)
- expect(page).to have_content "You won't be able to pull or push repositories via HTTP until you create a personal access token on your account"
+ expect(page).to have_content message_password_auth_disabled
end
end
@@ -51,7 +54,7 @@ RSpec.describe 'No Password Alert' do
gitlab_sign_in_via('saml', user, 'my-uid')
visit project_path(project)
- expect(page).not_to have_content "You won't be able to pull or push repositories via HTTP until you create a personal access token on your account"
+ expect(page).not_to have_content message_password_auth_disabled
end
end
end
diff --git a/spec/features/projects/show/user_uploads_files_spec.rb b/spec/features/projects/show/user_uploads_files_spec.rb
index 51e41397439..92b54d83ef3 100644
--- a/spec/features/projects/show/user_uploads_files_spec.rb
+++ b/spec/features/projects/show/user_uploads_files_spec.rb
@@ -44,27 +44,27 @@ RSpec.describe 'Projects > Show > User uploads files' do
end
end
- context 'when in the empty_repo_upload experiment' do
- before do
- stub_experiments(empty_repo_upload: :candidate)
+ context 'with an empty repo' do
+ let(:project) { create(:project, :empty_repo, creator: user) }
+ before do
visit(project_path(project))
end
- context 'with an empty repo' do
- let(:project) { create(:project, :empty_repo, creator: user) }
-
- [true, false].each do |value|
- include_examples 'uploads and commits a new text file via "upload file" button', drop: value
- end
+ [true, false].each do |value|
+ include_examples 'uploads and commits a new text file via "upload file" button', drop: value
end
+ end
- context 'with a nonempty repo' do
- let(:project) { create(:project, :repository, creator: user) }
+ context 'with a nonempty repo' do
+ let(:project) { create(:project, :repository, creator: user) }
- [true, false].each do |value|
- include_examples 'uploads and commits a new text file via "upload file" button', drop: value
- end
+ before do
+ visit(project_path(project))
+ end
+
+ [true, false].each do |value|
+ include_examples 'uploads and commits a new text file via "upload file" button', drop: value
end
end
end
diff --git a/spec/features/projects/user_changes_project_visibility_spec.rb b/spec/features/projects/user_changes_project_visibility_spec.rb
index 39b8cddd005..345d16982fd 100644
--- a/spec/features/projects/user_changes_project_visibility_spec.rb
+++ b/spec/features/projects/user_changes_project_visibility_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe 'User changes public project visibility', :js do
click_button 'Save changes'
end
- find('.js-confirm-danger-input').send_keys(project.path_with_namespace)
+ find('.js-legacy-confirm-danger-input').send_keys(project.path_with_namespace)
page.within '.modal' do
click_button 'Reduce project visibility'
diff --git a/spec/features/projects/user_creates_project_spec.rb b/spec/features/projects/user_creates_project_spec.rb
index 5d482f9fbd0..f5e8a5e8fc1 100644
--- a/spec/features/projects/user_creates_project_spec.rb
+++ b/spec/features/projects/user_creates_project_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe 'User creates a project', :js do
it 'creates a new project' do
visit(new_project_path)
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
fill_in(:project_name, with: 'Empty')
expect(page).to have_checked_field 'Initialize repository with a README'
@@ -38,7 +38,7 @@ RSpec.describe 'User creates a project', :js do
visit(new_project_path)
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
fill_in(:project_name, with: 'With initial commits')
expect(page).to have_checked_field 'Initialize repository with a README'
@@ -67,7 +67,7 @@ RSpec.describe 'User creates a project', :js do
it 'creates a new project' do
visit(new_project_path)
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
fill_in :project_name, with: 'A Subgroup Project'
fill_in :project_path, with: 'a-subgroup-project'
@@ -96,7 +96,7 @@ RSpec.describe 'User creates a project', :js do
it 'creates a new project' do
visit(new_project_path)
- find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create blank project'
fill_in :project_name, with: 'a-new-project'
fill_in :project_path, with: 'a-new-project'
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index 59ad7d31ea7..c4619b5498e 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe 'Project' do
shared_examples 'creates from template' do |template, sub_template_tab = nil|
it "is created from template", :js do
- find('[data-qa-panel-name="create_from_template"]').click # rubocop:disable QA/SelectorUsage
+ click_link 'Create from template'
find(".project-template #{sub_template_tab}").click if sub_template_tab
find("label[for=#{template.name}]").click
fill_in("project_name", with: template.name)
@@ -133,7 +133,7 @@ RSpec.describe 'Project' do
visit path
expect(page).to have_selector('[data-testid="project_topic_list"]')
- expect(page).to have_link('topic1', href: explore_projects_path(topic: 'topic1'))
+ expect(page).to have_link('topic1', href: topic_explore_projects_path(topic_name: 'topic1'))
end
it 'shows up to 3 project topics' do
@@ -142,9 +142,9 @@ RSpec.describe 'Project' do
visit path
expect(page).to have_selector('[data-testid="project_topic_list"]')
- expect(page).to have_link('topic1', href: explore_projects_path(topic: 'topic1'))
- expect(page).to have_link('topic2', href: explore_projects_path(topic: 'topic2'))
- expect(page).to have_link('topic3', href: explore_projects_path(topic: 'topic3'))
+ expect(page).to have_link('topic1', href: topic_explore_projects_path(topic_name: 'topic1'))
+ expect(page).to have_link('topic2', href: topic_explore_projects_path(topic_name: 'topic2'))
+ expect(page).to have_link('topic3', href: topic_explore_projects_path(topic_name: 'topic3'))
expect(page).to have_content('+ 1 more')
end
end
@@ -257,7 +257,7 @@ RSpec.describe 'Project' do
end
it 'deletes a project', :sidekiq_inline do
- expect { remove_with_confirm('Delete project', project.path, 'Yes, delete project') }.to change { Project.count }.by(-1)
+ expect { remove_with_confirm('Delete project', project.path_with_namespace, 'Yes, delete project') }.to change { Project.count }.by(-1)
expect(page).to have_content "Project '#{project.full_name}' is in the process of being deleted."
expect(Project.all.count).to be_zero
expect(project.issues).to be_empty
diff --git a/spec/features/signed_commits_spec.rb b/spec/features/signed_commits_spec.rb
index d679e4dbb99..610a80eb12c 100644
--- a/spec/features/signed_commits_spec.rb
+++ b/spec/features/signed_commits_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe 'GPG signed commits' do
perform_enqueued_jobs do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
+ user.reload # necessary to reload the association with gpg_keys
end
visit project_commit_path(project, ref)
@@ -114,6 +115,19 @@ RSpec.describe 'GPG signed commits' do
end
end
+ it 'unverified signature: commit contains multiple GPG signatures' do
+ user_1_key
+
+ visit project_commit_path(project, GpgHelpers::MULTIPLE_SIGNATURES_SHA)
+ wait_for_all_requests
+
+ page.find('.gpg-status-box', text: 'Unverified').click
+
+ within '.popover' do
+ expect(page).to have_content "This commit was signed with multiple signatures."
+ end
+ end
+
it 'verified and the gpg user has a gitlab profile' do
user_1_key
@@ -168,7 +182,7 @@ RSpec.describe 'GPG signed commits' do
page.find('.gpg-status-box', text: 'Unverified').click
within '.popover' do
- expect(page).to have_content 'This commit was signed with an unverified signature'
+ expect(page).to have_content 'This commit was signed with multiple signatures.'
end
end
end
diff --git a/spec/features/snippets/notes_on_personal_snippets_spec.rb b/spec/features/snippets/notes_on_personal_snippets_spec.rb
index fc88cd9205c..6bd31d7314c 100644
--- a/spec/features/snippets/notes_on_personal_snippets_spec.rb
+++ b/spec/features/snippets/notes_on_personal_snippets_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe 'Comments on personal snippets', :js do
end
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
sign_in user
visit snippet_path(snippet)
diff --git a/spec/features/snippets/user_creates_snippet_spec.rb b/spec/features/snippets/user_creates_snippet_spec.rb
index ca050daa62a..82fe895d397 100644
--- a/spec/features/snippets/user_creates_snippet_spec.rb
+++ b/spec/features/snippets/user_creates_snippet_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe 'User creates snippet', :js do
let(:snippet_title_field) { 'snippet-title' }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
sign_in(user)
visit new_snippet_path
diff --git a/spec/features/topic_show_spec.rb b/spec/features/topic_show_spec.rb
new file mode 100644
index 00000000000..3a9865a6503
--- /dev/null
+++ b/spec/features/topic_show_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Topic show page' do
+ let_it_be(:topic) { create(:topic, name: 'my-topic', description: 'This is **my** topic https://google.com/ :poop: ```\ncode\n```', avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) }
+
+ context 'when topic does not exist' do
+ let(:path) { topic_explore_projects_path(topic_name: 'non-existing') }
+
+ it 'renders 404' do
+ visit path
+
+ expect(status_code).to eq(404)
+ end
+ end
+
+ context 'when topic exists' do
+ before do
+ visit topic_explore_projects_path(topic_name: topic.name)
+ end
+
+ it 'shows name, avatar and description as markdown' do
+ expect(page).to have_content(topic.name)
+ expect(page).to have_selector('.avatar-container > img.topic-avatar')
+ expect(find('.topic-description')).to have_selector('p > strong')
+ expect(find('.topic-description')).to have_selector('p > a[rel]')
+ expect(find('.topic-description')).to have_selector('p > gl-emoji')
+ expect(find('.topic-description')).to have_selector('p > code')
+ end
+
+ context 'with associated projects' do
+ let!(:project) { create(:project, :public, topic_list: topic.name) }
+
+ it 'shows project list' do
+ visit topic_explore_projects_path(topic_name: topic.name)
+
+ expect(find('.projects-list .project-name')).to have_content(project.name)
+ end
+ end
+
+ context 'without associated projects' do
+ it 'shows correct empty state message' do
+ expect(page).to have_content('Explore public groups to find projects to contribute to.')
+ end
+ end
+ end
+end
diff --git a/spec/features/triggers_spec.rb b/spec/features/triggers_spec.rb
index 6fa805d8c74..2ddd86dd807 100644
--- a/spec/features/triggers_spec.rb
+++ b/spec/features/triggers_spec.rb
@@ -72,6 +72,7 @@ RSpec.describe 'Triggers', :js do
describe 'trigger "Revoke" workflow' do
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
create(:ci_trigger, owner: user2, project: @project, description: trigger_title)
visit project_settings_ci_cd_path(@project)
end
diff --git a/spec/features/users/confirmation_spec.rb b/spec/features/users/confirmation_spec.rb
new file mode 100644
index 00000000000..aaa49c75223
--- /dev/null
+++ b/spec/features/users/confirmation_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'User confirmation' do
+ describe 'resend confirmation instructions' do
+ context 'when recaptcha is enabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: true)
+ allow(Gitlab::Recaptcha).to receive(:load_configurations!)
+ visit new_user_confirmation_path
+ end
+
+ it 'renders recaptcha' do
+ expect(page).to have_css('.g-recaptcha')
+ end
+ end
+
+ context 'when recaptcha is not enabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: false)
+ visit new_user_confirmation_path
+ end
+
+ it 'does not render recaptcha' do
+ expect(page).not_to have_css('.g-recaptcha')
+ end
+ end
+ end
+end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 10c1c2cb26e..66ebd00d368 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -753,7 +753,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_shared_state do
end
end
- context 'when terms are enforced' do
+ context 'when terms are enforced', :js do
let(:user) { create(:user) }
before do
@@ -802,7 +802,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_shared_state do
end
context 'when the user did not enable 2FA' do
- it 'asks to set 2FA before asking to accept the terms', :js do
+ it 'asks to set 2FA before asking to accept the terms' do
expect(authentication_metrics)
.to increment(:user_authenticated_counter)
@@ -887,7 +887,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_shared_state do
end
end
- context 'when the user does not have an email configured', :js do
+ context 'when the user does not have an email configured' do
let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'saml', email: 'temp-email-for-oauth-user@gitlab.localhost') }
before do
diff --git a/spec/features/users/password_spec.rb b/spec/features/users/password_spec.rb
new file mode 100644
index 00000000000..793a11c616e
--- /dev/null
+++ b/spec/features/users/password_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'User password' do
+ describe 'send password reset' do
+ context 'when recaptcha is enabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: true)
+ allow(Gitlab::Recaptcha).to receive(:load_configurations!)
+ visit new_user_password_path
+ end
+
+ it 'renders recaptcha' do
+ expect(page).to have_css('.g-recaptcha')
+ end
+ end
+
+ context 'when recaptcha is not enabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: false)
+ visit new_user_password_path
+ end
+
+ it 'does not render recaptcha' do
+ expect(page).not_to have_css('.g-recaptcha')
+ end
+ end
+ end
+end
diff --git a/spec/features/users/terms_spec.rb b/spec/features/users/terms_spec.rb
index 8ba79d77c22..7cfe74f8aa9 100644
--- a/spec/features/users/terms_spec.rb
+++ b/spec/features/users/terms_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Users > Terms' do
+RSpec.describe 'Users > Terms', :js do
include TermsHelper
let!(:term) { create(:term, terms: 'By accepting, you promise to be nice!') }
diff --git a/spec/finders/autocomplete/routes_finder_spec.rb b/spec/finders/autocomplete/routes_finder_spec.rb
new file mode 100644
index 00000000000..c5b040a5640
--- /dev/null
+++ b/spec/finders/autocomplete/routes_finder_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Autocomplete::RoutesFinder do
+ describe '#execute' do
+ let_it_be(:user) { create(:user, username: 'user_path') }
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:group) { create(:group, path: 'path1') }
+ let_it_be(:group2) { create(:group, path: 'path2') }
+ let_it_be(:group3) { create(:group, path: 'not-matching') }
+ let_it_be(:project) { create(:project, path: 'path3', namespace: user.namespace) }
+ let_it_be(:project2) { create(:project, path: 'path4') }
+ let_it_be(:project_namespace) { create(:project_namespace, parent: group, path: 'path5') }
+
+ let(:current_user) { user }
+ let(:search) { 'path' }
+
+ before do
+ group.add_owner(user)
+ end
+
+ context 'for NamespacesOnly' do
+ subject { Autocomplete::RoutesFinder::NamespacesOnly.new(current_user, search: search).execute }
+
+ let(:user_route) { Route.find_by_path(user.username) }
+
+ it 'finds only user namespace and groups matching the search excluding project namespaces' do
+ is_expected.to match_array([group.route, user_route])
+ end
+
+ context 'when user is admin' do
+ let(:current_user) { admin }
+
+ it 'finds all namespaces matching the search excluding project namespaces' do
+ is_expected.to match_array([group.route, group2.route, user_route])
+ end
+ end
+ end
+
+ context 'for ProjectsOnly' do
+ subject { Autocomplete::RoutesFinder::ProjectsOnly.new(current_user, search: 'path').execute }
+
+ it 'finds only matching projects the user has access to' do
+ is_expected.to match_array([project.route])
+ end
+
+ context 'when user is admin' do
+ let(:current_user) { admin }
+
+ it 'finds all projects matching the search' do
+ is_expected.to match_array([project.route, project2.route])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/finders/branches_finder_spec.rb b/spec/finders/branches_finder_spec.rb
index f9d525c33a4..11b7ab08fb2 100644
--- a/spec/finders/branches_finder_spec.rb
+++ b/spec/finders/branches_finder_spec.rb
@@ -208,10 +208,10 @@ RSpec.describe BranchesFinder do
context 'by page_token only' do
let(:params) { { page_token: 'feature' } }
- it 'returns nothing' do
- result = subject
-
- expect(result.count).to eq(0)
+ it 'raises an error' do
+ expect do
+ subject
+ end.to raise_error(Gitlab::Git::CommandError, '13:could not find page token.')
end
end
diff --git a/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb b/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb
index 8a802e9660b..a7cf041f553 100644
--- a/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb
+++ b/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb
@@ -135,86 +135,6 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
end
context 'when pipelines exist for the branch and merge request' do
- shared_examples 'returns all pipelines for merge request' do
- it 'returns merge request pipeline first' do
- expect(subject.all).to eq([detached_merge_request_pipeline, branch_pipeline])
- end
-
- context 'when there are a branch pipeline and a merge request pipeline' do
- let!(:branch_pipeline_2) do
- create(:ci_pipeline, source: :push, project: project,
- ref: source_ref, sha: shas.first)
- end
-
- let!(:detached_merge_request_pipeline_2) do
- create(:ci_pipeline, source: :merge_request_event, project: project,
- ref: source_ref, sha: shas.first, merge_request: merge_request)
- end
-
- it 'returns merge request pipelines first' do
- expect(subject.all)
- .to eq([detached_merge_request_pipeline_2,
- detached_merge_request_pipeline,
- branch_pipeline_2,
- branch_pipeline])
- end
- end
-
- context 'when there are multiple merge request pipelines from the same branch' do
- let!(:branch_pipeline_2) do
- create(:ci_pipeline, source: :push, project: project,
- ref: source_ref, sha: shas.first)
- end
-
- let!(:branch_pipeline_with_sha_not_belonging_to_merge_request) do
- create(:ci_pipeline, source: :push, project: project, ref: source_ref)
- end
-
- let!(:detached_merge_request_pipeline_2) do
- create(:ci_pipeline, source: :merge_request_event, project: project,
- ref: source_ref, sha: shas.first, merge_request: merge_request_2)
- end
-
- let(:merge_request_2) do
- create(:merge_request, source_project: project, source_branch: source_ref,
- target_project: project, target_branch: 'stable')
- end
-
- before do
- shas.each.with_index do |sha, index|
- create(:merge_request_diff_commit,
- merge_request_diff: merge_request_2.merge_request_diff,
- sha: sha, relative_order: index)
- end
- end
-
- it 'returns only related merge request pipelines' do
- expect(subject.all)
- .to eq([detached_merge_request_pipeline,
- branch_pipeline_2,
- branch_pipeline])
-
- expect(described_class.new(merge_request_2, nil).all)
- .to match_array([detached_merge_request_pipeline_2, branch_pipeline_2, branch_pipeline])
- end
- end
-
- context 'when detached merge request pipeline is run on head ref of the merge request' do
- let!(:detached_merge_request_pipeline) do
- create(:ci_pipeline, source: :merge_request_event, project: project,
- ref: merge_request.ref_path, sha: shas.second, merge_request: merge_request)
- end
-
- it 'sets the head ref of the merge request to the pipeline ref' do
- expect(detached_merge_request_pipeline.ref).to match(%r{refs/merge-requests/\d+/head})
- end
-
- it 'includes the detached merge request pipeline even though the ref is custom path' do
- expect(merge_request.all_pipelines).to include(detached_merge_request_pipeline)
- end
- end
- end
-
let(:source_ref) { 'feature' }
let(:target_ref) { 'master' }
@@ -240,20 +160,76 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
let(:project) { create(:project, :repository) }
let(:shas) { project.repository.commits(source_ref, limit: 2).map(&:id) }
- context 'when `decomposed_ci_query_in_pipelines_for_merge_request_finder` feature flag enabled' do
- before do
- stub_feature_flags(decomposed_ci_query_in_pipelines_for_merge_request_finder: merge_request.target_project)
+ it 'returns merge request pipeline first' do
+ expect(subject.all).to match_array([detached_merge_request_pipeline, branch_pipeline])
+ end
+
+ context 'when there are a branch pipeline and a merge request pipeline' do
+ let!(:branch_pipeline_2) do
+ create(:ci_pipeline, source: :push, project: project,
+ ref: source_ref, sha: shas.first)
+ end
+
+ let!(:detached_merge_request_pipeline_2) do
+ create(:ci_pipeline, source: :merge_request_event, project: project,
+ ref: source_ref, sha: shas.first, merge_request: merge_request)
end
- it_behaves_like 'returns all pipelines for merge request'
+ it 'returns merge request pipelines first' do
+ expect(subject.all)
+ .to match_array([detached_merge_request_pipeline_2, detached_merge_request_pipeline, branch_pipeline_2, branch_pipeline])
+ end
end
- context 'when `decomposed_ci_query_in_pipelines_for_merge_request_finder` feature flag disabled' do
+ context 'when there are multiple merge request pipelines from the same branch' do
+ let!(:branch_pipeline_2) do
+ create(:ci_pipeline, source: :push, project: project,
+ ref: source_ref, sha: shas.first)
+ end
+
+ let!(:branch_pipeline_with_sha_not_belonging_to_merge_request) do
+ create(:ci_pipeline, source: :push, project: project, ref: source_ref)
+ end
+
+ let!(:detached_merge_request_pipeline_2) do
+ create(:ci_pipeline, source: :merge_request_event, project: project,
+ ref: source_ref, sha: shas.first, merge_request: merge_request_2)
+ end
+
+ let(:merge_request_2) do
+ create(:merge_request, source_project: project, source_branch: source_ref,
+ target_project: project, target_branch: 'stable')
+ end
+
before do
- stub_feature_flags(decomposed_ci_query_in_pipelines_for_merge_request_finder: false)
+ shas.each.with_index do |sha, index|
+ create(:merge_request_diff_commit,
+ merge_request_diff: merge_request_2.merge_request_diff,
+ sha: sha, relative_order: index)
+ end
end
- it_behaves_like 'returns all pipelines for merge request'
+ it 'returns only related merge request pipelines' do
+ expect(subject.all).to match_array([detached_merge_request_pipeline, branch_pipeline_2, branch_pipeline])
+
+ expect(described_class.new(merge_request_2, nil).all)
+ .to match_array([detached_merge_request_pipeline_2, branch_pipeline_2, branch_pipeline])
+ end
+ end
+
+ context 'when detached merge request pipeline is run on head ref of the merge request' do
+ let!(:detached_merge_request_pipeline) do
+ create(:ci_pipeline, source: :merge_request_event, project: project,
+ ref: merge_request.ref_path, sha: shas.second, merge_request: merge_request)
+ end
+
+ it 'sets the head ref of the merge request to the pipeline ref' do
+ expect(detached_merge_request_pipeline.ref).to match(%r{refs/merge-requests/\d+/head})
+ end
+
+ it 'includes the detached merge request pipeline even though the ref is custom path' do
+ expect(merge_request.all_pipelines).to include(detached_merge_request_pipeline)
+ end
end
end
end
diff --git a/spec/finders/clusters/agent_authorizations_finder_spec.rb b/spec/finders/clusters/agent_authorizations_finder_spec.rb
new file mode 100644
index 00000000000..687906db0d7
--- /dev/null
+++ b/spec/finders/clusters/agent_authorizations_finder_spec.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Clusters::AgentAuthorizationsFinder do
+ describe '#execute' do
+ let_it_be(:top_level_group) { create(:group) }
+ let_it_be(:subgroup1) { create(:group, parent: top_level_group) }
+ let_it_be(:subgroup2) { create(:group, parent: subgroup1) }
+ let_it_be(:bottom_level_group) { create(:group, parent: subgroup2) }
+
+ let_it_be(:agent_configuration_project) { create(:project, namespace: subgroup1) }
+ let_it_be(:requesting_project, reload: true) { create(:project, namespace: bottom_level_group) }
+
+ let_it_be(:staging_agent) { create(:cluster_agent, project: agent_configuration_project) }
+ let_it_be(:production_agent) { create(:cluster_agent, project: agent_configuration_project) }
+
+ subject { described_class.new(requesting_project).execute }
+
+ shared_examples_for 'access_as' do
+ let(:config) { { access_as: { access_as => {} } } }
+
+ context 'agent' do
+ let(:access_as) { :agent }
+
+ it { is_expected.to match_array [authorization] }
+ end
+
+ context 'impersonate' do
+ let(:access_as) { :impersonate }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'ci_user' do
+ let(:access_as) { :ci_user }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'ci_job' do
+ let(:access_as) { :ci_job }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ describe 'project authorizations' do
+ context 'agent configuration project does not share a root namespace with the given project' do
+ let(:unrelated_agent) { create(:cluster_agent) }
+
+ before do
+ create(:agent_project_authorization, agent: unrelated_agent, project: requesting_project)
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'with project authorizations present' do
+ let!(:authorization) { create(:agent_project_authorization, agent: production_agent, project: requesting_project) }
+
+ it { is_expected.to match_array [authorization] }
+ end
+
+ context 'with overlapping authorizations' do
+ let!(:agent) { create(:cluster_agent, project: requesting_project) }
+ let!(:project_authorization) { create(:agent_project_authorization, agent: agent, project: requesting_project) }
+ let!(:group_authorization) { create(:agent_group_authorization, agent: agent, group: bottom_level_group) }
+
+ it { is_expected.to match_array [project_authorization] }
+ end
+
+ it_behaves_like 'access_as' do
+ let!(:authorization) { create(:agent_project_authorization, agent: production_agent, project: requesting_project, config: config) }
+ end
+ end
+
+ describe 'implicit authorizations' do
+ let!(:associated_agent) { create(:cluster_agent, project: requesting_project) }
+
+ it 'returns authorizations for agents directly associated with the project' do
+ expect(subject.count).to eq(1)
+
+ authorization = subject.first
+ expect(authorization).to be_a(Clusters::Agents::ImplicitAuthorization)
+ expect(authorization.agent).to eq(associated_agent)
+ end
+ end
+
+ describe 'authorized groups' do
+ context 'agent configuration project is outside the requesting project hierarchy' do
+ let(:unrelated_agent) { create(:cluster_agent) }
+
+ before do
+ create(:agent_group_authorization, agent: unrelated_agent, group: top_level_group)
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'multiple agents are authorized for the same group' do
+ let!(:staging_auth) { create(:agent_group_authorization, agent: staging_agent, group: bottom_level_group) }
+ let!(:production_auth) { create(:agent_group_authorization, agent: production_agent, group: bottom_level_group) }
+
+ it 'returns authorizations for all agents' do
+ expect(subject).to contain_exactly(staging_auth, production_auth)
+ end
+ end
+
+ context 'a single agent is authorized to more than one matching group' do
+ let!(:bottom_level_auth) { create(:agent_group_authorization, agent: production_agent, group: bottom_level_group) }
+ let!(:top_level_auth) { create(:agent_group_authorization, agent: production_agent, group: top_level_group) }
+
+ it 'picks the authorization for the closest group to the requesting project' do
+ expect(subject).to contain_exactly(bottom_level_auth)
+ end
+ end
+
+ it_behaves_like 'access_as' do
+ let!(:authorization) { create(:agent_group_authorization, agent: production_agent, group: top_level_group, config: config) }
+ end
+ end
+ end
+end
diff --git a/spec/finders/environments/environments_by_deployments_finder_spec.rb b/spec/finders/environments/environments_by_deployments_finder_spec.rb
index 1b86aced67d..7804ffa4ef1 100644
--- a/spec/finders/environments/environments_by_deployments_finder_spec.rb
+++ b/spec/finders/environments/environments_by_deployments_finder_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Environments::EnvironmentsByDeploymentsFinder do
project.add_maintainer(user)
end
- describe '#execute' do
+ shared_examples 'execute' do
context 'tagged deployment' do
let(:environment_two) { create(:environment, project: project) }
# Environments need to include commits, so rewind two commits to fit
@@ -124,4 +124,16 @@ RSpec.describe Environments::EnvironmentsByDeploymentsFinder do
end
end
end
+
+ describe "#execute" do
+ include_examples 'execute'
+
+ context 'when environments_by_deployments_finder_exists_optimization is disabled' do
+ before do
+ stub_feature_flags(environments_by_deployments_finder_exists_optimization: false)
+ end
+
+ include_examples 'execute'
+ end
+ end
end
diff --git a/spec/finders/members_finder_spec.rb b/spec/finders/members_finder_spec.rb
index 749e319f9c7..aa7d32e51ac 100644
--- a/spec/finders/members_finder_spec.rb
+++ b/spec/finders/members_finder_spec.rb
@@ -202,13 +202,5 @@ RSpec.describe MembersFinder, '#execute' do
end
it_behaves_like 'with invited_groups param'
-
- context 'when feature flag :linear_members_finder_ancestor_scopes is disabled' do
- before do
- stub_feature_flags(linear_members_finder_ancestor_scopes: false)
- end
-
- it_behaves_like 'with invited_groups param'
- end
end
end
diff --git a/spec/finders/tags_finder_spec.rb b/spec/finders/tags_finder_spec.rb
index fe015d53ac9..acc86547271 100644
--- a/spec/finders/tags_finder_spec.rb
+++ b/spec/finders/tags_finder_spec.rb
@@ -7,13 +7,8 @@ RSpec.describe TagsFinder do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:repository) { project.repository }
- def load_tags(params)
- tags_finder = described_class.new(repository, params)
- tags, error = tags_finder.execute
-
- expect(error).to eq(nil)
-
- tags
+ def load_tags(params, gitaly_pagination: false)
+ described_class.new(repository, params).execute(gitaly_pagination: gitaly_pagination)
end
describe '#execute' do
@@ -101,15 +96,79 @@ RSpec.describe TagsFinder do
end
end
+ context 'with Gitaly pagination' do
+ subject { load_tags(params, gitaly_pagination: true) }
+
+ context 'by page_token and per_page' do
+ let(:params) { { page_token: 'v1.0.0', per_page: 1 } }
+
+ it 'filters tags' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(v1.1.0))
+ end
+ end
+
+ context 'by next page_token and per_page' do
+ let(:params) { { page_token: 'v1.1.0', per_page: 2 } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(v1.1.1))
+ end
+ end
+
+ context 'by per_page only' do
+ let(:params) { { per_page: 2 } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(v1.0.0 v1.1.0))
+ end
+ end
+
+ context 'by page_token only' do
+ let(:params) { { page_token: 'feature' } }
+
+ it 'raises an error' do
+ expect do
+ subject
+ end.to raise_error(Gitlab::Git::InvalidPageToken, 'Invalid page token: refs/tags/feature')
+ end
+ end
+
+ context 'pagination and sort' do
+ context 'by per_page' do
+ let(:params) { { sort: 'updated_desc', per_page: 5 } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(v1.1.1 v1.1.0 v1.0.0))
+ end
+ end
+
+ context 'by page_token and per_page' do
+ let(:params) { { sort: 'updated_desc', page_token: 'v1.1.1', per_page: 2 } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(v1.1.0 v1.0.0))
+ end
+ end
+ end
+ end
+
context 'when Gitaly is unavailable' do
- it 'returns empty list of tags' do
+ it 'raises an exception' do
expect(Gitlab::GitalyClient).to receive(:call).and_raise(GRPC::Unavailable)
tags_finder = described_class.new(repository, {})
- tags, error = tags_finder.execute
- expect(error).to be_a(Gitlab::Git::CommandError)
- expect(tags).to eq([])
+ expect { tags_finder.execute }.to raise_error(Gitlab::Git::CommandError)
end
end
end
diff --git a/spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json b/spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json
index 73904438ede..296e18fca47 100644
--- a/spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json
+++ b/spec/fixtures/api/schemas/analytics/cycle_analytics/summary.json
@@ -14,6 +14,9 @@
},
"unit": {
"type": "string"
+ },
+ "links": {
+ "type": "array"
}
},
"additionalProperties": false
diff --git a/spec/fixtures/api/schemas/graphql/packages/package_details.json b/spec/fixtures/api/schemas/graphql/packages/package_details.json
index 2824ca64325..9ef7f6c9271 100644
--- a/spec/fixtures/api/schemas/graphql/packages/package_details.json
+++ b/spec/fixtures/api/schemas/graphql/packages/package_details.json
@@ -12,7 +12,6 @@
"tags",
"pipelines",
"versions",
- "metadata",
"status",
"canDestroy"
],
@@ -47,7 +46,8 @@
"GENERIC",
"GOLANG",
"RUBYGEMS",
- "DEBIAN"
+ "DEBIAN",
+ "HELM"
]
},
"tags": {
diff --git a/spec/fixtures/api/schemas/public_api/v4/deploy_key.json b/spec/fixtures/api/schemas/public_api/v4/deploy_key.json
new file mode 100644
index 00000000000..3dbdfcc95a1
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/deploy_key.json
@@ -0,0 +1,25 @@
+{
+ "type": "object",
+ "required": [
+ "id",
+ "title",
+ "created_at",
+ "expires_at",
+ "key",
+ "fingerprint",
+ "projects_with_write_access"
+ ],
+ "properties": {
+ "id": { "type": "integer" },
+ "title": { "type": "string" },
+ "created_at": { "type": "string", "format": "date-time" },
+ "expires_at": { "type": ["string", "null"], "format": "date-time" },
+ "key": { "type": "string" },
+ "fingerprint": { "type": "string" },
+ "projects_with_write_access": {
+ "type": "array",
+ "items": { "$ref": "project/identity.json" }
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/deploy_keys.json b/spec/fixtures/api/schemas/public_api/v4/deploy_keys.json
new file mode 100644
index 00000000000..82ddbdddbee
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/deploy_keys.json
@@ -0,0 +1,4 @@
+{
+ "type": "array",
+ "items": { "$ref": "deploy_key.json" }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/npm_package_version.json b/spec/fixtures/api/schemas/public_api/v4/packages/npm_package_version.json
index 3e74dc0a1c2..64969d71250 100644
--- a/spec/fixtures/api/schemas/public_api/v4/packages/npm_package_version.json
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/npm_package_version.json
@@ -36,11 +36,11 @@
".{1,}": { "type": "string" }
}
},
- "deprecated": {
- "type": "object",
- "patternProperties": {
- ".{1,}": { "type": "string" }
- }
- }
+ "deprecated": { "type": "string"},
+ "bin": { "type": "string" },
+ "directories": { "type": "array" },
+ "engines": { "type": "object" },
+ "_hasShrinkwrap": { "type": "boolean" },
+ "additionalProperties": true
}
}
diff --git a/spec/fixtures/bulk_imports/gz/milestones.ndjson.gz b/spec/fixtures/bulk_imports/gz/milestones.ndjson.gz
deleted file mode 100644
index f959cd7a0bd..00000000000
--- a/spec/fixtures/bulk_imports/gz/milestones.ndjson.gz
+++ /dev/null
Binary files differ
diff --git a/spec/fixtures/bulk_imports/milestones.ndjson b/spec/fixtures/bulk_imports/milestones.ndjson
deleted file mode 100644
index 40523f276e7..00000000000
--- a/spec/fixtures/bulk_imports/milestones.ndjson
+++ /dev/null
@@ -1,5 +0,0 @@
-{"id":7642,"title":"v4.0","project_id":null,"description":"Et laudantium enim omnis ea reprehenderit iure.","due_date":null,"created_at":"2019-11-20T17:02:14.336Z","updated_at":"2019-11-20T17:02:14.336Z","state":"closed","iid":5,"start_date":null,"group_id":4351}
-{"id":7641,"title":"v3.0","project_id":null,"description":"Et repellat culpa nemo consequatur ut reprehenderit.","due_date":null,"created_at":"2019-11-20T17:02:14.323Z","updated_at":"2019-11-20T17:02:14.323Z","state":"active","iid":4,"start_date":null,"group_id":4351}
-{"id":7640,"title":"v2.0","project_id":null,"description":"Velit cupiditate est neque voluptates iste rem sunt.","due_date":null,"created_at":"2019-11-20T17:02:14.309Z","updated_at":"2019-11-20T17:02:14.309Z","state":"active","iid":3,"start_date":null,"group_id":4351}
-{"id":7639,"title":"v1.0","project_id":null,"description":"Amet velit repellat ut rerum aut cum.","due_date":null,"created_at":"2019-11-20T17:02:14.296Z","updated_at":"2019-11-20T17:02:14.296Z","state":"active","iid":2,"start_date":null,"group_id":4351}
-{"id":7638,"title":"v0.0","project_id":null,"description":"Ea quia asperiores ut modi dolorem sunt non numquam.","due_date":null,"created_at":"2019-11-20T17:02:14.282Z","updated_at":"2019-11-20T17:02:14.282Z","state":"active","iid":1,"start_date":null,"group_id":4351}
diff --git a/spec/fixtures/emails/service_desk_all_quoted.eml b/spec/fixtures/emails/service_desk_all_quoted.eml
new file mode 100644
index 00000000000..102ebf1f30e
--- /dev/null
+++ b/spec/fixtures/emails/service_desk_all_quoted.eml
@@ -0,0 +1,22 @@
+Return-Path: <jake@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+email-test-project_id-issue-@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
+Date: Thu, 13 Jun 2013 17:03:48 -0400
+From: Jake the Dog <jake@adventuretime.ooo>
+To: incoming+email-test-project_id-issue-@appmail.adventuretime.ooo
+Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Subject: The message subject! @all
+Mime-Version: 1.0
+Content-Type: text/plain;
+ charset=ISO-8859-1
+Content-Transfer-Encoding: 7bit
+X-Sieve: CMU Sieve 2.2
+X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
+ 13 Jun 2013 14:03:48 -0700 (PDT)
+X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
+
+> This is an empty quote
+> someone did forward this email without
+> adding any new content.
diff --git a/spec/fixtures/emails/service_desk_custom_address_no_key.eml b/spec/fixtures/emails/service_desk_custom_address_no_key.eml
new file mode 100644
index 00000000000..4781e3d4fbd
--- /dev/null
+++ b/spec/fixtures/emails/service_desk_custom_address_no_key.eml
@@ -0,0 +1,27 @@
+Return-Path: <jake@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <support+project_slug-project_key@example.com>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
+Date: Thu, 13 Jun 2013 17:03:48 -0400
+From: Jake the Dog <jake@adventuretime.ooo>
+To: support+email-test-project_id-issue-@example.com
+Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Subject: The message subject! @all
+Mime-Version: 1.0
+Content-Type: text/plain;
+ charset=ISO-8859-1
+Content-Transfer-Encoding: 7bit
+X-Sieve: CMU Sieve 2.2
+X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
+ 13 Jun 2013 14:03:48 -0700 (PDT)
+X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
+
+Service desk stuff!
+
+```
+a = b
+```
+
+/label ~label1
+/assign @user1
+/close
diff --git a/spec/fixtures/emails/service_desk_forwarded.eml b/spec/fixtures/emails/service_desk_forwarded.eml
index 56987972808..ab509cf55af 100644
--- a/spec/fixtures/emails/service_desk_forwarded.eml
+++ b/spec/fixtures/emails/service_desk_forwarded.eml
@@ -1,11 +1,11 @@
Delivered-To: incoming+email-test-project_id-issue-@appmail.adventuretime.ooo
-Return-Path: <jake@adventuretime.ooo>
+Return-Path: <jake.g@adventuretime.ooo>
Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+email-test-project_id-issue-@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
Date: Thu, 13 Jun 2013 17:03:48 -0400
-From: Jake the Dog <jake@adventuretime.ooo>
+From: Jake the Dog <jake.g@adventuretime.ooo>
To: support@adventuretime.ooo
Delivered-To: support@adventuretime.ooo
Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
diff --git a/spec/fixtures/error_tracking/browser_event.json b/spec/fixtures/error_tracking/browser_event.json
new file mode 100644
index 00000000000..65918c3dc7a
--- /dev/null
+++ b/spec/fixtures/error_tracking/browser_event.json
@@ -0,0 +1 @@
+{"sdk":{"name":"sentry.javascript.browser","version":"5.7.1","packages":[{"name":"npm:@sentry/browser","version":"5.7.1"}],"integrations":["InboundFilters","FunctionToString","TryCatch","Breadcrumbs","GlobalHandlers","LinkedErrors","UserAgent","Dedupe","ExtraErrorData","ReportingObserver","RewriteFrames","Vue"]},"level":"error","request":{"url":"http://localhost:5444/","headers":{"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Firefox/91.0"}},"event_id":"6a32dc45cd924196930e06aa21b48c8d","platform":"javascript","exception":{"values":[{"type":"TypeError","value":"Cannot read property 'filter' of undefined","mechanism":{"type":"generic","handled":true},"stacktrace":{"frames":[{"colno":34,"in_app":true,"lineno":6395,"filename":"webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js","function":"hydrate"},{"colno":57,"in_app":true,"lineno":6362,"filename":"webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js","function":"hydrate"},{"colno":13,"in_app":true,"lineno":3115,"filename":"webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js","function":"init"},{"colno":10,"in_app":true,"lineno":8399,"filename":"webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js","function":"Vue.prototype.$mount"},{"colno":3,"in_app":true,"lineno":4061,"filename":"webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js","function":"mountComponent"},{"colno":12,"in_app":true,"lineno":4456,"filename":"webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js","function":"Watcher"},{"colno":25,"in_app":true,"lineno":4467,"filename":"webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js","function":"get"},{"colno":10,"in_app":true,"lineno":4048,"filename":"webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js","function":"updateComponent"},{"colno":19,"in_app":true,"lineno":3933,"filename":"webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js","function":"lifecycleMixin/Vue.prototype._update"},{"colno":24,"in_app":true,"lineno":6477,"filename":"webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js","function":"patch"},{"colno":34,"in_app":true,"lineno":6395,"filename":"webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js","function":"hydrate"},{"colno":64,"in_app":true,"lineno":78,"filename":"webpack-internal:///./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./pages/index.vue?vue&type=script&lang=js&","function":"data"}]}}]},"environment":"development"} \ No newline at end of file
diff --git a/spec/fixtures/error_tracking/go_parsed_event.json b/spec/fixtures/error_tracking/go_parsed_event.json
new file mode 100644
index 00000000000..9811fc261c0
--- /dev/null
+++ b/spec/fixtures/error_tracking/go_parsed_event.json
@@ -0,0 +1 @@
+{"contexts":{"device":{"arch":"amd64","num_cpu":20},"os":{"name":"linux"},"runtime":{"go_maxprocs":20,"go_numcgocalls":5,"go_numroutines":2,"name":"go","version":"go1.17.1"}},"environment":"Accumulate","event_id":"a6d33282b0d44ed1a5982c48b62e2a4e","level":"error","platform":"go","release":"accumulated@version unknown","sdk":{"name":"sentry.go","version":"0.11.0","integrations":["ContextifyFrames","Environment","IgnoreErrors","Modules"],"packages":[{"name":"sentry-go","version":"0.11.0"}]},"server_name":"Laurelin","user":{},"modules":{"github.com/AccumulateNetwork/accumulated":"(devel)","github.com/AccumulateNetwork/jsonrpc2/v15":"v15.0.0-20210802145948-43d2d974a106","github.com/AndreasBriese/bbloom":"v0.0.0-20190825152654-46b345b51c96","github.com/Workiva/go-datastructures":"v1.0.53","github.com/beorn7/perks":"v1.0.1","github.com/btcsuite/btcd":"v0.22.0-beta","github.com/cespare/xxhash":"v1.1.0","github.com/cespare/xxhash/v2":"v2.1.2","github.com/davecgh/go-spew":"v1.1.2-0.20180830191138-d8f796af33cc","github.com/dgraph-io/badger":"v1.6.2","github.com/dgraph-io/ristretto":"v0.0.4-0.20210122082011-bb5d392ed82d","github.com/dustin/go-humanize":"v1.0.0","github.com/fatih/color":"v1.13.0","github.com/fsnotify/fsnotify":"v1.5.1","github.com/getsentry/sentry-go":"v0.11.0","github.com/go-kit/kit":"v0.11.0","github.com/go-playground/locales":"v0.14.0","github.com/go-playground/universal-translator":"v0.18.0","github.com/go-playground/validator/v10":"v10.9.0","github.com/gogo/protobuf":"v1.3.2","github.com/golang/protobuf":"v1.5.2","github.com/golang/snappy":"v0.0.1","github.com/google/btree":"v1.0.0","github.com/google/orderedcode":"v0.0.1","github.com/google/uuid":"v1.3.0","github.com/gorilla/mux":"v1.8.0","github.com/gorilla/websocket":"v1.4.2","github.com/grpc-ecosystem/go-grpc-middleware":"v1.3.0","github.com/grpc-ecosystem/go-grpc-prometheus":"v1.2.0","github.com/hashicorp/hcl":"v1.0.0","github.com/leodido/go-urn":"v1.2.1","github.com/lib/pq":"v1.10.3","github.com/libp2p/go-buffer-pool":"v0.0.2","github.com/magiconair/properties":"v1.8.5","github.com/mattn/go-colorable":"v0.1.9","github.com/mattn/go-isatty":"v0.0.14","github.com/matttproud/golang_protobuf_extensions":"v1.0.1","github.com/minio/highwayhash":"v1.0.2","github.com/mitchellh/mapstructure":"v1.4.2","github.com/oasisprotocol/curve25519-voi":"v0.0.0-20210609091139-0a56a4bca00b","github.com/pelletier/go-toml":"v1.9.4","github.com/pkg/errors":"v0.9.1","github.com/pmezard/go-difflib":"v1.0.0","github.com/prometheus/client_golang":"v1.11.0","github.com/prometheus/client_model":"v0.2.0","github.com/prometheus/common":"v0.30.0","github.com/prometheus/procfs":"v0.7.3","github.com/rcrowley/go-metrics":"v0.0.0-20200313005456-10cdbea86bc0","github.com/rs/cors":"v1.8.0","github.com/rs/zerolog":"v1.24.0","github.com/spf13/afero":"v1.6.0","github.com/spf13/cast":"v1.4.1","github.com/spf13/cobra":"v1.2.1","github.com/spf13/jwalterweatherman":"v1.1.0","github.com/spf13/pflag":"v1.0.5","github.com/spf13/viper":"v1.8.1","github.com/stretchr/testify":"v1.7.0","github.com/subosito/gotenv":"v1.2.0","github.com/syndtr/goleveldb":"v1.0.1-0.20200815110645-5c35d600f0ca","github.com/tendermint/tendermint":"v0.35.0-rc1","github.com/tendermint/tm-db":"v0.6.4","github.com/ybbus/jsonrpc/v2":"v2.1.6","golang.org/x/crypto":"v0.0.0-20210711020723-a769d52b0f97","golang.org/x/net":"v0.0.0-20210805182204-aaa1db679c0d","golang.org/x/sys":"v0.0.0-20210917161153-d61c044b1678","golang.org/x/term":"v0.0.0-20201126162022-7de9c90e9dd1","golang.org/x/text":"v0.3.7","google.golang.org/genproto":"v0.0.0-20210602131652-f16073e35f0c","google.golang.org/grpc":"v1.40.0","google.golang.org/protobuf":"v1.27.1","gopkg.in/ini.v1":"v1.63.2","gopkg.in/yaml.v2":"v2.4.0","gopkg.in/yaml.v3":"v3.0.0-20210107192922-496545a6307b"},"exception":[{"type":"*errors.errorString","value":"Hello world","stacktrace":{"frames":[{"function":"main","module":"main","abs_path":"SRC/cmd/accumulated/main.go","lineno":37,"pre_context":["func init() {","\tcmdMain.PersistentFlags().StringVarP(&flagMain.WorkDir, \"work-dir\", \"w\", defaultWorkDir, \"Working directory for configuration and data\")","}","","func main() {"],"context_line":"\tcmdMain.Execute()","post_context":["}","","func printUsageAndExit1(cmd *cobra.Command, args []string) {","\tcmd.Usage()","\tos.Exit(1)"],"in_app":true},{"function":"(*Command).Execute","module":"github.com/spf13/cobra","abs_path":"GOPATH/pkg/mod/github.com/spf13/cobra@v1.2.1/command.go","lineno":902,"pre_context":["","// Execute uses the args (os.Args[1:] by default)","// and run through the command tree finding appropriate matches","// for commands and then corresponding flags.","func (c *Command) Execute() error {"],"context_line":"\t_, err := c.ExecuteC()","post_context":["\treturn err","}","","// ExecuteContextC is the same as ExecuteC(), but sets the ctx on the command.","// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs"],"in_app":true},{"function":"(*Command).ExecuteC","module":"github.com/spf13/cobra","abs_path":"GOPATH/pkg/mod/github.com/spf13/cobra@v1.2.1/command.go","lineno":974,"pre_context":["\t// if context is present on the parent command.","\tif cmd.ctx == nil {","\t\tcmd.ctx = c.ctx","\t}",""],"context_line":"\terr = cmd.execute(flags)","post_context":["\tif err != nil {","\t\t// Always show help if requested, even if SilenceErrors is in","\t\t// effect","\t\tif err == flag.ErrHelp {","\t\t\tcmd.HelpFunc()(cmd, args)"],"in_app":true},{"function":"(*Command).execute","module":"github.com/spf13/cobra","abs_path":"GOPATH/pkg/mod/github.com/spf13/cobra@v1.2.1/command.go","lineno":860,"pre_context":["\tif c.RunE != nil {","\t\tif err := c.RunE(c, argWoFlags); err != nil {","\t\t\treturn err","\t\t}","\t} else {"],"context_line":"\t\tc.Run(c, argWoFlags)","post_context":["\t}","\tif c.PostRunE != nil {","\t\tif err := c.PostRunE(c, argWoFlags); err != nil {","\t\t\treturn err","\t\t}"],"in_app":true},{"function":"runNode","module":"main","abs_path":"SRC/cmd/accumulated/cmd_run.go","lineno":76,"pre_context":["\t\tif err != nil {","\t\t\tfmt.Fprintf(os.Stderr, \"Error: configuring sentry: %v\\n\", err)","\t\t\tos.Exit(1)","\t\t}","\t\tdefer sentry.Flush(2 * time.Second)"],"context_line":"\t\tsentry.CaptureException(errors.New(\"Hello world\"))","post_context":["\t\t// sentry.CaptureMessage(\"Hello world\")","\t\tsentry.Flush(time.Second)","\t}","","\tdbPath := filepath.Join(config.RootDir, \"valacc.db\")"],"in_app":true}]}}],"timestamp":"2021-10-08T19:49:21.932425444-05:00"}
diff --git a/spec/fixtures/error_tracking/python_event.json b/spec/fixtures/error_tracking/python_event.json
new file mode 100644
index 00000000000..4b27cb47e5b
--- /dev/null
+++ b/spec/fixtures/error_tracking/python_event.json
@@ -0,0 +1 @@
+{"level":"error","exception":{"values":[{"module":null,"type":"ZeroDivisionError","value":"division by zero","mechanism":{"type":"django","handled":false},"stacktrace":{"frames":[{"filename":"django/core/handlers/exception.py","abs_path":"/Users/dzaporozhets/.asdf/installs/python/3.8.12/lib/python3.8/site-packages/django/core/handlers/exception.py","function":"inner","module":"django.core.handlers.exception","lineno":47,"pre_context":[" return inner"," else:"," @wraps(get_response)"," def inner(request):"," try:"],"context_line":" response = get_response(request)","post_context":[" except Exception as exc:"," response = response_for_exception(request, exc)"," return response"," return inner",""],"vars":{"request":"\u003cWSGIRequest: GET '/polls/'\u003e","exc":"ZeroDivisionError('division by zero')","get_response":"\u003cbound method BaseHandler._get_response of \u003cdjango.core.handlers.wsgi.WSGIHandler object at 0x10f012550\u003e\u003e"},"in_app":true},{"filename":"django/core/handlers/base.py","abs_path":"/Users/dzaporozhets/.asdf/installs/python/3.8.12/lib/python3.8/site-packages/django/core/handlers/base.py","function":"_get_response","module":"django.core.handlers.base","lineno":181,"pre_context":[" wrapped_callback = self.make_view_atomic(callback)"," # If it is an asynchronous view, run it in a subthread."," if asyncio.iscoroutinefunction(wrapped_callback):"," wrapped_callback = async_to_sync(wrapped_callback)"," try:"],"context_line":" response = wrapped_callback(request, *callback_args, **callback_kwargs)","post_context":[" except Exception as e:"," response = self.process_exception_by_middleware(e, request)"," if response is None:"," raise",""],"vars":{"self":"\u003cdjango.core.handlers.wsgi.WSGIHandler object at 0x10f012550\u003e","request":"\u003cWSGIRequest: GET '/polls/'\u003e","response":"None","callback":"\u003cfunction index at 0x10f7b6820\u003e","callback_args":[],"callback_kwargs":{},"middleware_method":"\u003cfunction CsrfViewMiddleware.process_view at 0x113853a60\u003e","wrapped_callback":"\u003cfunction index at 0x113d41040\u003e"},"in_app":true},{"filename":"polls/views.py","abs_path":"/Users/dzaporozhets/Projects/pysite/polls/views.py","function":"index","module":"polls.views","lineno":15,"pre_context":[" # We recommend adjusting this value in production."," traces_sample_rate=1.0,",")","","def index(request):"],"context_line":" division_by_zero = 1 / 0","post_context":[" return HttpResponse(\"Hello, world. You're at the polls index.\")"],"vars":{"request":"\u003cWSGIRequest: GET '/polls/'\u003e"},"in_app":true}]}}]},"event_id":"dbae4fc6415f408786174a929363d26f","timestamp":"2021-10-07T14:52:18.257544Z","breadcrumbs":{"values":[]},"transaction":"/polls/","contexts":{"trace":{"trace_id":"20b50c065f4f4b5d99862e5ea08b45aa","span_id":"a4ecb3118f7f9f5a","parent_span_id":"af50a83a73a41c28","op":"django.middleware","description":"django.middleware.clickjacking.XFrameOptionsMiddleware.__call__"},"runtime":{"name":"CPython","version":"3.8.12","build":"3.8.12 (default, Oct 6 2021, 13:48:19) \n[Clang 12.0.5 (clang-1205.0.22.9)]"}},"modules":{"urllib3":"1.26.7","sqlparse":"0.4.2","setuptools":"56.0.0","sentry-sdk":"1.4.3","pytz":"2021.3","pip":"21.1.1","django":"3.2.8","certifi":"2021.5.30","asgiref":"3.4.1"},"extra":{"sys.argv":["manage.py","runserver"]},"request":{"url":"http://localhost:8000/polls/","query_string":"","method":"GET","env":{"SERVER_NAME":"1.0.0.127.in-addr.arpa","SERVER_PORT":"8000"},"headers":{"Content-Length":"","Content-Type":"text/plain","Host":"localhost:8000","User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:92.0) Gecko/20100101 Firefox/92.0","Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","Accept-Language":"en-US,en;q=0.5","Accept-Encoding":"gzip, deflate","Connection":"keep-alive","Cookie":"","Upgrade-Insecure-Requests":"1","Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1","Cache-Control":"max-age=0"}},"environment":"production","server_name":"DZ-GitLab-MBP-15.local","sdk":{"name":"sentry.python","version":"1.4.3","packages":[{"name":"pypi:sentry-sdk","version":"1.4.3"}],"integrations":["argv","atexit","dedupe","django","excepthook","logging","modules","stdlib","threading"]},"platform":"python","_meta":{"request":{"headers":{"Cookie":{"":{"rem":[["!config","x",0,2968]]}}}}}} \ No newline at end of file
diff --git a/spec/fixtures/gitlab/import_export/lightweight_project_export.tar.gz b/spec/fixtures/gitlab/import_export/lightweight_project_export.tar.gz
index e3ec4f603b9..e5f6f195fe5 100644
--- a/spec/fixtures/gitlab/import_export/lightweight_project_export.tar.gz
+++ b/spec/fixtures/gitlab/import_export/lightweight_project_export.tar.gz
Binary files differ
diff --git a/spec/fixtures/lib/gitlab/import_export/complex/project.json b/spec/fixtures/lib/gitlab/import_export/complex/project.json
index fd4c2d55124..95f2ce45b46 100644
--- a/spec/fixtures/lib/gitlab/import_export/complex/project.json
+++ b/spec/fixtures/lib/gitlab/import_export/complex/project.json
@@ -2795,11 +2795,7 @@
"sha": "bb5206fee213d983da88c47f9cf4cc6caf9c66dc",
"message": "Feature conflict added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-08-06T08:35:52.000+02:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-08-06T08:35:52.000+02:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -2815,11 +2811,7 @@
"sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e",
"message": "Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T10:01:38.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T10:01:38.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -2835,11 +2827,7 @@
"sha": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d",
"message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:57:31.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:57:31.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -2855,11 +2843,7 @@
"sha": "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9",
"message": "More submodules\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:54:21.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:54:21.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -2875,11 +2859,7 @@
"sha": "d14d6c0abdd253381df51a723d58691b2ee1ab08",
"message": "Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:49:50.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:49:50.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -2895,11 +2875,7 @@
"sha": "c1acaa58bbcbc3eafe538cb8274ba387047b69f8",
"message": "Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:48:32.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:48:32.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -3291,11 +3267,7 @@
"relative_order": 0,
"message": "Feature added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:26:01.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:26:01.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -3562,11 +3534,7 @@
"sha": "94b8d581c48d894b86661718582fecbc5e3ed2eb",
"message": "fixes #10\n",
"authored_date": "2016-01-19T13:22:56.000+01:00",
- "author_name": "James Lopez",
- "author_email": "james@jameslopez.es",
"committed_date": "2016-01-19T13:22:56.000+01:00",
- "committer_name": "James Lopez",
- "committer_email": "james@jameslopez.es",
"commit_author": {
"name": "James Lopez",
"email": "james@jameslopez.es"
@@ -3833,11 +3801,7 @@
"sha": "ddd4ff416a931589c695eb4f5b23f844426f6928",
"message": "fixes #10\n",
"authored_date": "2016-01-19T14:14:43.000+01:00",
- "author_name": "James Lopez",
- "author_email": "james@jameslopez.es",
"committed_date": "2016-01-19T14:14:43.000+01:00",
- "committer_name": "James Lopez",
- "committer_email": "james@jameslopez.es",
"commit_author": {
"name": "James Lopez",
"email": "james@jameslopez.es"
@@ -3853,11 +3817,7 @@
"sha": "be93687618e4b132087f430a4d8fc3a609c9b77c",
"message": "Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6",
"authored_date": "2015-12-07T12:52:12.000+01:00",
- "author_name": "Marin Jankovski",
- "author_email": "marin@gitlab.com",
"committed_date": "2015-12-07T12:52:12.000+01:00",
- "committer_name": "Marin Jankovski",
- "committer_email": "marin@gitlab.com",
"commit_author": {
"name": "Marin Jankovski",
"email": "marin@gitlab.com"
@@ -3873,11 +3833,7 @@
"sha": "048721d90c449b244b7b4c53a9186b04330174ec",
"message": "LFS object pointer.\n",
"authored_date": "2015-12-07T11:54:28.000+01:00",
- "author_name": "Marin Jankovski",
- "author_email": "maxlazio@gmail.com",
"committed_date": "2015-12-07T11:54:28.000+01:00",
- "committer_name": "Marin Jankovski",
- "committer_email": "maxlazio@gmail.com",
"commit_author": {
"name": "Marin Jankovski",
"email": "maxlazio@gmail.com"
@@ -3893,11 +3849,7 @@
"sha": "5f923865dde3436854e9ceb9cdb7815618d4e849",
"message": "GitLab currently doesn't support patches that involve a merge commit: add a commit here\n",
"authored_date": "2015-11-13T16:27:12.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T16:27:12.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -3913,11 +3865,7 @@
"sha": "d2d430676773caa88cdaf7c55944073b2fd5561a",
"message": "Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5",
"authored_date": "2015-11-13T08:50:17.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T08:50:17.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -3933,11 +3881,7 @@
"sha": "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73",
"message": "Add GitLab SVG\n",
"authored_date": "2015-11-13T08:39:43.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T08:39:43.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -3953,11 +3897,7 @@
"sha": "59e29889be61e6e0e5e223bfa9ac2721d31605b8",
"message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4",
"authored_date": "2015-11-13T07:21:40.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T07:21:40.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -3973,11 +3913,7 @@
"sha": "66eceea0db202bb39c4e445e8ca28689645366c5",
"message": "add spaces in whitespace file\n",
"authored_date": "2015-11-13T06:01:27.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T06:01:27.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -3993,11 +3929,7 @@
"sha": "08f22f255f082689c0d7d39d19205085311542bc",
"message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n",
"authored_date": "2015-11-13T06:00:16.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T06:00:16.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -4013,11 +3945,7 @@
"sha": "19e2e9b4ef76b422ce1154af39a91323ccc57434",
"message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3",
"authored_date": "2015-11-13T05:23:14.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T05:23:14.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -4033,11 +3961,7 @@
"sha": "c642fe9b8b9f28f9225d7ea953fe14e74748d53b",
"message": "add whitespace in empty\n",
"authored_date": "2015-11-13T05:08:45.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T05:08:45.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -4053,11 +3977,7 @@
"sha": "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0",
"message": "add empty file\n",
"authored_date": "2015-11-13T05:08:04.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T05:08:04.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -4073,11 +3993,7 @@
"sha": "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd",
"message": "Add ISO-8859 test file\n",
"authored_date": "2015-08-25T17:53:12.000+02:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@packetzoom.com",
"committed_date": "2015-08-25T17:53:12.000+02:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@packetzoom.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@packetzoom.com"
@@ -4093,11 +4009,7 @@
"sha": "e56497bb5f03a90a51293fc6d516788730953899",
"message": "Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/275#note_732774)\n\nSee merge request !2\n",
"authored_date": "2015-01-10T22:23:29.000+01:00",
- "author_name": "Sytse Sijbrandij",
- "author_email": "sytse@gitlab.com",
"committed_date": "2015-01-10T22:23:29.000+01:00",
- "committer_name": "Sytse Sijbrandij",
- "committer_email": "sytse@gitlab.com",
"commit_author": {
"name": "Sytse Sijbrandij",
"email": "sytse@gitlab.com"
@@ -4113,11 +4025,7 @@
"sha": "4cd80ccab63c82b4bad16faa5193fbd2aa06df40",
"message": "add directory structure for tree_helper spec\n",
"authored_date": "2015-01-10T21:28:18.000+01:00",
- "author_name": "marmis85",
- "author_email": "marmis85@gmail.com",
"committed_date": "2015-01-10T21:28:18.000+01:00",
- "committer_name": "marmis85",
- "committer_email": "marmis85@gmail.com",
"commit_author": {
"name": "marmis85",
"email": "marmis85@gmail.com"
@@ -4133,11 +4041,7 @@
"sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e",
"message": "Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T10:01:38.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T10:01:38.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -4153,11 +4057,7 @@
"sha": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d",
"message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:57:31.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:57:31.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -4173,11 +4073,7 @@
"sha": "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9",
"message": "More submodules\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:54:21.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:54:21.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -4193,11 +4089,7 @@
"sha": "d14d6c0abdd253381df51a723d58691b2ee1ab08",
"message": "Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:49:50.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:49:50.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -4213,11 +4105,7 @@
"sha": "c1acaa58bbcbc3eafe538cb8274ba387047b69f8",
"message": "Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:48:32.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:48:32.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -4678,11 +4566,7 @@
"sha": "0bfedc29d30280c7e8564e19f654584b459e5868",
"message": "fixes #10\n",
"authored_date": "2016-01-19T15:25:23.000+01:00",
- "author_name": "James Lopez",
- "author_email": "james@jameslopez.es",
"committed_date": "2016-01-19T15:25:23.000+01:00",
- "committer_name": "James Lopez",
- "committer_email": "james@jameslopez.es",
"commit_author": {
"name": "James Lopez",
"email": "james@jameslopez.es"
@@ -4698,11 +4582,7 @@
"sha": "be93687618e4b132087f430a4d8fc3a609c9b77c",
"message": "Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6",
"authored_date": "2015-12-07T12:52:12.000+01:00",
- "author_name": "Marin Jankovski",
- "author_email": "marin@gitlab.com",
"committed_date": "2015-12-07T12:52:12.000+01:00",
- "committer_name": "Marin Jankovski",
- "committer_email": "marin@gitlab.com",
"commit_author": {
"name": "Marin Jankovski",
"email": "marin@gitlab.com"
@@ -4718,11 +4598,7 @@
"sha": "048721d90c449b244b7b4c53a9186b04330174ec",
"message": "LFS object pointer.\n",
"authored_date": "2015-12-07T11:54:28.000+01:00",
- "author_name": "Marin Jankovski",
- "author_email": "maxlazio@gmail.com",
"committed_date": "2015-12-07T11:54:28.000+01:00",
- "committer_name": "Marin Jankovski",
- "committer_email": "maxlazio@gmail.com",
"commit_author": {
"name": "Marin Jankovski",
"email": "maxlazio@gmail.com"
@@ -4738,11 +4614,7 @@
"sha": "5f923865dde3436854e9ceb9cdb7815618d4e849",
"message": "GitLab currently doesn't support patches that involve a merge commit: add a commit here\n",
"authored_date": "2015-11-13T16:27:12.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T16:27:12.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -4758,11 +4630,7 @@
"sha": "d2d430676773caa88cdaf7c55944073b2fd5561a",
"message": "Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5",
"authored_date": "2015-11-13T08:50:17.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T08:50:17.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -4778,11 +4646,7 @@
"sha": "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73",
"message": "Add GitLab SVG\n",
"authored_date": "2015-11-13T08:39:43.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T08:39:43.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -4798,11 +4662,7 @@
"sha": "59e29889be61e6e0e5e223bfa9ac2721d31605b8",
"message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4",
"authored_date": "2015-11-13T07:21:40.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T07:21:40.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -4818,11 +4678,7 @@
"sha": "66eceea0db202bb39c4e445e8ca28689645366c5",
"message": "add spaces in whitespace file\n",
"authored_date": "2015-11-13T06:01:27.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T06:01:27.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -4838,11 +4694,7 @@
"sha": "08f22f255f082689c0d7d39d19205085311542bc",
"message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n",
"authored_date": "2015-11-13T06:00:16.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T06:00:16.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -4858,11 +4710,7 @@
"sha": "19e2e9b4ef76b422ce1154af39a91323ccc57434",
"message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3",
"authored_date": "2015-11-13T05:23:14.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T05:23:14.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -4878,11 +4726,7 @@
"sha": "c642fe9b8b9f28f9225d7ea953fe14e74748d53b",
"message": "add whitespace in empty\n",
"authored_date": "2015-11-13T05:08:45.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T05:08:45.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -4898,11 +4742,7 @@
"sha": "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0",
"message": "add empty file\n",
"authored_date": "2015-11-13T05:08:04.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T05:08:04.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -4918,11 +4758,7 @@
"sha": "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd",
"message": "Add ISO-8859 test file\n",
"authored_date": "2015-08-25T17:53:12.000+02:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@packetzoom.com",
"committed_date": "2015-08-25T17:53:12.000+02:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@packetzoom.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@packetzoom.com"
@@ -4938,11 +4774,7 @@
"sha": "e56497bb5f03a90a51293fc6d516788730953899",
"message": "Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/275#note_732774)\n\nSee merge request !2\n",
"authored_date": "2015-01-10T22:23:29.000+01:00",
- "author_name": "Sytse Sijbrandij",
- "author_email": "sytse@gitlab.com",
"committed_date": "2015-01-10T22:23:29.000+01:00",
- "committer_name": "Sytse Sijbrandij",
- "committer_email": "sytse@gitlab.com",
"commit_author": {
"name": "Sytse Sijbrandij",
"email": "sytse@gitlab.com"
@@ -4958,11 +4790,7 @@
"sha": "4cd80ccab63c82b4bad16faa5193fbd2aa06df40",
"message": "add directory structure for tree_helper spec\n",
"authored_date": "2015-01-10T21:28:18.000+01:00",
- "author_name": "marmis85",
- "author_email": "marmis85@gmail.com",
"committed_date": "2015-01-10T21:28:18.000+01:00",
- "committer_name": "marmis85",
- "committer_email": "marmis85@gmail.com",
"commit_author": {
"name": "marmis85",
"email": "marmis85@gmail.com"
@@ -5307,11 +5135,7 @@
"sha": "97a0df9696e2aebf10c31b3016f40214e0e8f243",
"message": "fixes #10\n",
"authored_date": "2016-01-19T14:08:21.000+01:00",
- "author_name": "James Lopez",
- "author_email": "james@jameslopez.es",
"committed_date": "2016-01-19T14:08:21.000+01:00",
- "committer_name": "James Lopez",
- "committer_email": "james@jameslopez.es",
"commit_author": {
"name": "James Lopez",
"email": "james@jameslopez.es"
@@ -5327,11 +5151,7 @@
"sha": "be93687618e4b132087f430a4d8fc3a609c9b77c",
"message": "Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6",
"authored_date": "2015-12-07T12:52:12.000+01:00",
- "author_name": "Marin Jankovski",
- "author_email": "marin@gitlab.com",
"committed_date": "2015-12-07T12:52:12.000+01:00",
- "committer_name": "Marin Jankovski",
- "committer_email": "marin@gitlab.com",
"commit_author": {
"name": "Marin Jankovski",
"email": "marin@gitlab.com"
@@ -5347,11 +5167,7 @@
"sha": "048721d90c449b244b7b4c53a9186b04330174ec",
"message": "LFS object pointer.\n",
"authored_date": "2015-12-07T11:54:28.000+01:00",
- "author_name": "Marin Jankovski",
- "author_email": "maxlazio@gmail.com",
"committed_date": "2015-12-07T11:54:28.000+01:00",
- "committer_name": "Marin Jankovski",
- "committer_email": "maxlazio@gmail.com",
"commit_author": {
"name": "Marin Jankovski",
"email": "maxlazio@gmail.com"
@@ -5367,11 +5183,7 @@
"sha": "5f923865dde3436854e9ceb9cdb7815618d4e849",
"message": "GitLab currently doesn't support patches that involve a merge commit: add a commit here\n",
"authored_date": "2015-11-13T16:27:12.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T16:27:12.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -5387,11 +5199,7 @@
"sha": "d2d430676773caa88cdaf7c55944073b2fd5561a",
"message": "Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5",
"authored_date": "2015-11-13T08:50:17.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T08:50:17.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -5407,11 +5215,7 @@
"sha": "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73",
"message": "Add GitLab SVG\n",
"authored_date": "2015-11-13T08:39:43.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T08:39:43.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -5427,11 +5231,7 @@
"sha": "59e29889be61e6e0e5e223bfa9ac2721d31605b8",
"message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4",
"authored_date": "2015-11-13T07:21:40.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T07:21:40.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -5447,11 +5247,7 @@
"sha": "66eceea0db202bb39c4e445e8ca28689645366c5",
"message": "add spaces in whitespace file\n",
"authored_date": "2015-11-13T06:01:27.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T06:01:27.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -5467,11 +5263,7 @@
"sha": "08f22f255f082689c0d7d39d19205085311542bc",
"message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n",
"authored_date": "2015-11-13T06:00:16.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T06:00:16.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -5487,11 +5279,7 @@
"sha": "19e2e9b4ef76b422ce1154af39a91323ccc57434",
"message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3",
"authored_date": "2015-11-13T05:23:14.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T05:23:14.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -5507,11 +5295,7 @@
"sha": "c642fe9b8b9f28f9225d7ea953fe14e74748d53b",
"message": "add whitespace in empty\n",
"authored_date": "2015-11-13T05:08:45.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T05:08:45.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -5527,11 +5311,7 @@
"sha": "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0",
"message": "add empty file\n",
"authored_date": "2015-11-13T05:08:04.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T05:08:04.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -5547,11 +5327,7 @@
"sha": "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd",
"message": "Add ISO-8859 test file\n",
"authored_date": "2015-08-25T17:53:12.000+02:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@packetzoom.com",
"committed_date": "2015-08-25T17:53:12.000+02:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@packetzoom.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@packetzoom.com"
@@ -6119,11 +5895,7 @@
"sha": "f998ac87ac9244f15e9c15109a6f4e62a54b779d",
"message": "fixes #10\n",
"authored_date": "2016-01-19T14:43:23.000+01:00",
- "author_name": "James Lopez",
- "author_email": "james@jameslopez.es",
"committed_date": "2016-01-19T14:43:23.000+01:00",
- "committer_name": "James Lopez",
- "committer_email": "james@jameslopez.es",
"commit_author": {
"name": "James Lopez",
"email": "james@jameslopez.es"
@@ -6139,11 +5911,7 @@
"sha": "be93687618e4b132087f430a4d8fc3a609c9b77c",
"message": "Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6",
"authored_date": "2015-12-07T12:52:12.000+01:00",
- "author_name": "Marin Jankovski",
- "author_email": "marin@gitlab.com",
"committed_date": "2015-12-07T12:52:12.000+01:00",
- "committer_name": "Marin Jankovski",
- "committer_email": "marin@gitlab.com",
"commit_author": {
"name": "Marin Jankovski",
"email": "marin@gitlab.com"
@@ -6159,11 +5927,7 @@
"sha": "048721d90c449b244b7b4c53a9186b04330174ec",
"message": "LFS object pointer.\n",
"authored_date": "2015-12-07T11:54:28.000+01:00",
- "author_name": "Marin Jankovski",
- "author_email": "maxlazio@gmail.com",
"committed_date": "2015-12-07T11:54:28.000+01:00",
- "committer_name": "Marin Jankovski",
- "committer_email": "maxlazio@gmail.com",
"commit_author": {
"name": "Marin Jankovski",
"email": "maxlazio@gmail.com"
@@ -6179,11 +5943,7 @@
"sha": "5f923865dde3436854e9ceb9cdb7815618d4e849",
"message": "GitLab currently doesn't support patches that involve a merge commit: add a commit here\n",
"authored_date": "2015-11-13T16:27:12.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T16:27:12.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -6199,11 +5959,7 @@
"sha": "d2d430676773caa88cdaf7c55944073b2fd5561a",
"message": "Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5",
"authored_date": "2015-11-13T08:50:17.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T08:50:17.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -6219,11 +5975,7 @@
"sha": "2ea1f3dec713d940208fb5ce4a38765ecb5d3f73",
"message": "Add GitLab SVG\n",
"authored_date": "2015-11-13T08:39:43.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T08:39:43.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -6239,11 +5991,7 @@
"sha": "59e29889be61e6e0e5e223bfa9ac2721d31605b8",
"message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4",
"authored_date": "2015-11-13T07:21:40.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T07:21:40.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -6259,11 +6007,7 @@
"sha": "66eceea0db202bb39c4e445e8ca28689645366c5",
"message": "add spaces in whitespace file\n",
"authored_date": "2015-11-13T06:01:27.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T06:01:27.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -6279,11 +6023,7 @@
"sha": "08f22f255f082689c0d7d39d19205085311542bc",
"message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n",
"authored_date": "2015-11-13T06:00:16.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T06:00:16.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -6299,11 +6039,7 @@
"sha": "19e2e9b4ef76b422ce1154af39a91323ccc57434",
"message": "Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3",
"authored_date": "2015-11-13T05:23:14.000+01:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@gmail.com",
"committed_date": "2015-11-13T05:23:14.000+01:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@gmail.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@gmail.com"
@@ -6319,11 +6055,7 @@
"sha": "c642fe9b8b9f28f9225d7ea953fe14e74748d53b",
"message": "add whitespace in empty\n",
"authored_date": "2015-11-13T05:08:45.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T05:08:45.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -6339,11 +6071,7 @@
"sha": "9a944d90955aaf45f6d0c88f30e27f8d2c41cec0",
"message": "add empty file\n",
"authored_date": "2015-11-13T05:08:04.000+01:00",
- "author_name": "윤민ì‹",
- "author_email": "minsik.yoon@samsung.com",
"committed_date": "2015-11-13T05:08:04.000+01:00",
- "committer_name": "윤민ì‹",
- "committer_email": "minsik.yoon@samsung.com",
"commit_author": {
"name": "윤민ì‹",
"email": "minsik.yoon@samsung.com"
@@ -6359,11 +6087,7 @@
"sha": "c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd",
"message": "Add ISO-8859 test file\n",
"authored_date": "2015-08-25T17:53:12.000+02:00",
- "author_name": "Stan Hu",
- "author_email": "stanhu@packetzoom.com",
"committed_date": "2015-08-25T17:53:12.000+02:00",
- "committer_name": "Stan Hu",
- "committer_email": "stanhu@packetzoom.com",
"commit_author": {
"name": "Stan Hu",
"email": "stanhu@packetzoom.com"
@@ -6379,11 +6103,7 @@
"sha": "e56497bb5f03a90a51293fc6d516788730953899",
"message": "Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/275#note_732774)\n\nSee merge request !2\n",
"authored_date": "2015-01-10T22:23:29.000+01:00",
- "author_name": "Sytse Sijbrandij",
- "author_email": "sytse@gitlab.com",
"committed_date": "2015-01-10T22:23:29.000+01:00",
- "committer_name": "Sytse Sijbrandij",
- "committer_email": "sytse@gitlab.com",
"commit_author": {
"name": "Sytse Sijbrandij",
"email": "sytse@gitlab.com"
@@ -6399,11 +6119,7 @@
"sha": "4cd80ccab63c82b4bad16faa5193fbd2aa06df40",
"message": "add directory structure for tree_helper spec\n",
"authored_date": "2015-01-10T21:28:18.000+01:00",
- "author_name": "marmis85",
- "author_email": "marmis85@gmail.com",
"committed_date": "2015-01-10T21:28:18.000+01:00",
- "committer_name": "marmis85",
- "committer_email": "marmis85@gmail.com",
"commit_author": {
"name": "marmis85",
"email": "marmis85@gmail.com"
@@ -6419,11 +6135,7 @@
"sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e",
"message": "Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T10:01:38.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T10:01:38.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -6439,11 +6151,7 @@
"sha": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d",
"message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:57:31.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:57:31.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -6459,11 +6167,7 @@
"sha": "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9",
"message": "More submodules\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:54:21.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:54:21.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -6479,11 +6183,7 @@
"sha": "d14d6c0abdd253381df51a723d58691b2ee1ab08",
"message": "Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:49:50.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:49:50.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -6499,11 +6199,7 @@
"sha": "c1acaa58bbcbc3eafe538cb8274ba387047b69f8",
"message": "Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-02-27T09:48:32.000+01:00",
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:48:32.000+01:00",
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author": {
"name": "Dmitriy Zaporozhets",
"email": "dmitriy.zaporozhets@gmail.com"
@@ -6952,11 +6648,7 @@
"sha": "a4e5dfebf42e34596526acb8611bc7ed80e4eb3f",
"message": "fixes #10\n",
"authored_date": "2016-01-19T15:44:02.000+01:00",
- "author_name": "James Lopez",
- "author_email": "james@jameslopez.es",
"committed_date": "2016-01-19T15:44:02.000+01:00",
- "committer_name": "James Lopez",
- "committer_email": "james@jameslopez.es",
"commit_author": {
"name": "James Lopez",
"email": "james@jameslopez.es"
diff --git a/spec/fixtures/lib/gitlab/import_export/complex/tree/project/merge_requests.ndjson b/spec/fixtures/lib/gitlab/import_export/complex/tree/project/merge_requests.ndjson
index 741360c0b8e..16e45509a1b 100644
--- a/spec/fixtures/lib/gitlab/import_export/complex/tree/project/merge_requests.ndjson
+++ b/spec/fixtures/lib/gitlab/import_export/complex/tree/project/merge_requests.ndjson
@@ -1,9 +1,9 @@
-{"id":27,"target_branch":"feature","source_branch":"feature_conflict","source_project_id":2147483547,"author_id":1,"assignee_id":null,"title":"MR1","created_at":"2016-06-14T15:02:36.568Z","updated_at":"2016-06-14T15:02:56.815Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":9,"description":null,"position":0,"updated_by_id":null,"merge_error":null,"diff_head_sha":"HEAD","source_branch_sha":"ABCD","target_branch_sha":"DCBA","merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":true,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":669,"note":"added 3 commits\n\n<ul><li>16ea4e20...074a2a32 - 2 commits from branch <code>master</code></li><li>ca223a02 - readme: fix typos</li></ul>\n\n[Compare with previous version](/group/project/merge_requests/1/diffs?diff_id=1189&start_sha=16ea4e207fb258fe4e9c73185a725207c9a4f3e1)","noteable_type":"MergeRequest","author_id":26,"created_at":"2020-03-28T12:47:33.461Z","updated_at":"2020-03-28T12:47:33.461Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"system":true,"st_diff":null,"updated_by_id":null,"position":null,"original_position":null,"resolved_at":null,"resolved_by_id":null,"discussion_id":null,"change_position":null,"resolved_by_push":null,"confidential":null,"type":null,"author":{"name":"User 4"},"award_emoji":[],"system_note_metadata":{"id":4789,"commit_count":3,"action":"commit","created_at":"2020-03-28T12:47:33.461Z","updated_at":"2020-03-28T12:47:33.461Z"},"events":[],"suggestions":[]},{"id":670,"note":"unmarked as a **Work In Progress**","noteable_type":"MergeRequest","author_id":26,"created_at":"2020-03-28T12:48:36.951Z","updated_at":"2020-03-28T12:48:36.951Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"system":true,"st_diff":null,"updated_by_id":null,"position":null,"original_position":null,"resolved_at":null,"resolved_by_id":null,"discussion_id":null,"change_position":null,"resolved_by_push":null,"confidential":null,"type":null,"author":{"name":"User 4"},"award_emoji":[],"system_note_metadata":{"id":4790,"commit_count":null,"action":"title","created_at":"2020-03-28T12:48:36.951Z","updated_at":"2020-03-28T12:48:36.951Z"},"events":[],"suggestions":[]},{"id":671,"note":"Sit voluptatibus eveniet architecto quidem.","note_html":"<p>something else entirely</p>","cached_markdown_version":917504,"noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:56.632Z","updated_at":"2016-06-14T15:02:56.632Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[],"award_emoji":[{"id":1,"name":"tada","user_id":1,"awardable_type":"Note","awardable_id":1,"created_at":"2019-11-05T15:37:21.287Z","updated_at":"2019-11-05T15:37:21.287Z"}]},{"id":672,"note":"Odio maxime ratione voluptatibus sed.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:56.656Z","updated_at":"2016-06-14T15:02:56.656Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":673,"note":"Et deserunt et omnis nihil excepturi accusantium.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:56.679Z","updated_at":"2016-06-14T15:02:56.679Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":674,"note":"Saepe asperiores exercitationem non dignissimos laborum reiciendis et ipsum.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:56.700Z","updated_at":"2016-06-14T15:02:56.700Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[],"suggestions":[{"id":1,"note_id":674,"relative_order":0,"applied":false,"commit_id":null,"from_content":"Original line\n","to_content":"New line\n","lines_above":0,"lines_below":0,"outdated":false}]},{"id":675,"note":"Numquam est at dolor quo et sed eligendi similique.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:56.720Z","updated_at":"2016-06-14T15:02:56.720Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":676,"note":"Et perferendis aliquam sunt nisi labore delectus.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:56.742Z","updated_at":"2016-06-14T15:02:56.742Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":677,"note":"Aut ex rerum et in.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:56.791Z","updated_at":"2016-06-14T15:02:56.791Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":678,"note":"Dolor laborum earum ut exercitationem.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:56.814Z","updated_at":"2016-06-14T15:02:56.814Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"resource_label_events":[{"id":243,"action":"add","issue_id":null,"merge_request_id":27,"label_id":null,"user_id":1,"created_at":"2018-08-28T08:24:00.494Z"}],"merge_request_diff":{"id":27,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":27,"relative_order":0,"sha":"bb5206fee213d983da88c47f9cf4cc6caf9c66dc","message":"Feature conflict added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-08-06T08:35:52.000+02:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-08-06T08:35:52.000+02:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":1,"sha":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","message":"Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T10:01:38.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T10:01:38.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":2,"sha":"570e7b2abdd848b95f2f578043fc23bd6f6fd24d","message":"Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:57:31.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:57:31.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":3,"sha":"6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9","message":"More submodules\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:54:21.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:54:21.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":4,"sha":"d14d6c0abdd253381df51a723d58691b2ee1ab08","message":"Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:49:50.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:49:50.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":5,"sha":"c1acaa58bbcbc3eafe538cb8274ba387047b69f8","message":"Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:48:32.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:48:32.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":27,"relative_order":0,"utf8_diff":"Binary files a/.DS_Store and /dev/null differ\n","new_path":".DS_Store","old_path":".DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":27,"relative_order":1,"utf8_diff":"--- a/.gitignore\n+++ b/.gitignore\n@@ -17,3 +17,4 @@ rerun.txt\n pickle-email-*.html\n .project\n config/initializers/secret_token.rb\n+.DS_Store\n","new_path":".gitignore","old_path":".gitignore","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":2,"utf8_diff":"--- a/.gitmodules\n+++ b/.gitmodules\n@@ -1,3 +1,9 @@\n [submodule \"six\"]\n \tpath = six\n \turl = git://github.com/randx/six.git\n+[submodule \"gitlab-shell\"]\n+\tpath = gitlab-shell\n+\turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n","new_path":".gitmodules","old_path":".gitmodules","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":3,"utf8_diff":"Binary files a/files/.DS_Store and /dev/null differ\n","new_path":"files/.DS_Store","old_path":"files/.DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":27,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/files/ruby/feature.rb\n@@ -0,0 +1,4 @@\n+# This file was changed in feature branch\n+# We put different code here to make merge conflict\n+class Conflict\n+end\n","new_path":"files/ruby/feature.rb","old_path":"files/ruby/feature.rb","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":5,"utf8_diff":"--- a/files/ruby/popen.rb\n+++ b/files/ruby/popen.rb\n@@ -6,12 +6,18 @@ module Popen\n \n def popen(cmd, path=nil)\n unless cmd.is_a?(Array)\n- raise \"System commands must be given as an array of strings\"\n+ raise RuntimeError, \"System commands must be given as an array of strings\"\n end\n \n path ||= Dir.pwd\n- vars = { \"PWD\" => path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" => path\n+ }\n+\n+ options = {\n+ chdir: path\n+ }\n \n unless File.directory?(path)\n FileUtils.mkdir_p(path)\n@@ -19,6 +25,7 @@ module Popen\n \n @cmd_output = \"\"\n @cmd_status = 0\n+\n Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|\n @cmd_output << stdout.read\n @cmd_output << stderr.read\n","new_path":"files/ruby/popen.rb","old_path":"files/ruby/popen.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":6,"utf8_diff":"--- a/files/ruby/regex.rb\n+++ b/files/ruby/regex.rb\n@@ -19,14 +19,12 @@ module Gitlab\n end\n \n def archive_formats_regex\n- #|zip|tar| tar.gz | tar.bz2 |\n- /(zip|tar|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n+ /(zip|tar|7z|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n end\n \n def git_reference_regex\n # Valid git ref regex, see:\n # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html\n-\n %r{\n (?!\n (?# doesn't begins with)\n","new_path":"files/ruby/regex.rb","old_path":"files/ruby/regex.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":7,"utf8_diff":"--- /dev/null\n+++ b/gitlab-grack\n@@ -0,0 +1 @@\n+Subproject commit 645f6c4c82fd3f5e06f67134450a570b795e55a6\n","new_path":"gitlab-grack","old_path":"gitlab-grack","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":8,"utf8_diff":"--- /dev/null\n+++ b/gitlab-shell\n@@ -0,0 +1 @@\n+Subproject commit 79bceae69cb5750d6567b223597999bfa91cb3b9\n","new_path":"gitlab-shell","old_path":"gitlab-shell","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":27,"created_at":"2016-06-14T15:02:36.572Z","updated_at":"2016-06-14T15:02:36.658Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"9"},"events":[{"id":221,"target_type":"MergeRequest","target_id":27,"project_id":36,"created_at":"2016-06-14T15:02:36.703Z","updated_at":"2016-06-14T15:02:36.703Z","action":1,"author_id":1},{"id":187,"target_type":"MergeRequest","target_id":27,"project_id":5,"created_at":"2016-06-14T15:02:36.703Z","updated_at":"2016-06-14T15:02:36.703Z","action":1,"author_id":1}],"approvals_before_merge":1,"award_emoji":[{"id":1,"name":"thumbsup","user_id":1,"awardable_type":"MergeRequest","awardable_id":27,"created_at":"2020-01-07T11:21:21.235Z","updated_at":"2020-01-07T11:21:21.235Z"},{"id":2,"name":"drum","user_id":1,"awardable_type":"MergeRequest","awardable_id":27,"created_at":"2020-01-07T11:21:21.235Z","updated_at":"2020-01-07T11:21:21.235Z"}]}
-{"id":26,"target_branch":"master","source_branch":"feature","source_project_id":4,"author_id":1,"assignee_id":null,"title":"MR2","created_at":"2016-06-14T15:02:36.418Z","updated_at":"2016-06-14T15:02:57.013Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":8,"description":null,"position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":679,"note":"Qui rerum totam nisi est.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:56.848Z","updated_at":"2016-06-14T15:02:56.848Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":680,"note":"Pariatur magni corrupti consequatur debitis minima error beatae voluptatem.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:56.871Z","updated_at":"2016-06-14T15:02:56.871Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":681,"note":"Qui quis ut modi eos rerum ratione.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:56.895Z","updated_at":"2016-06-14T15:02:56.895Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":682,"note":"Illum quidem expedita mollitia fugit.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:56.918Z","updated_at":"2016-06-14T15:02:56.918Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":683,"note":"Consectetur voluptate sit sint possimus veritatis quod.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:56.942Z","updated_at":"2016-06-14T15:02:56.942Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":684,"note":"Natus libero quibusdam rem assumenda deleniti accusamus sed earum.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:56.966Z","updated_at":"2016-06-14T15:02:56.966Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":685,"note":"Tenetur autem nihil rerum odit.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:56.989Z","updated_at":"2016-06-14T15:02:56.989Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":686,"note":"Quia maiores et odio sed.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:57.012Z","updated_at":"2016-06-14T15:02:57.012Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":26,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":26,"sha":"0b4bc9a49b562e85de7cc9e834518ea6828729b9","relative_order":0,"message":"Feature added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:26:01.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:26:01.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":26,"relative_order":0,"utf8_diff":"--- /dev/null\n+++ b/files/ruby/feature.rb\n@@ -0,0 +1,5 @@\n+class Feature\n+ def foo\n+ puts 'bar'\n+ end\n+end\n","new_path":"files/ruby/feature.rb","old_path":"files/ruby/feature.rb","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":26,"created_at":"2016-06-14T15:02:36.421Z","updated_at":"2016-06-14T15:02:36.474Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"1"},"events":[{"id":222,"target_type":"MergeRequest","target_id":26,"project_id":36,"created_at":"2016-06-14T15:02:36.496Z","updated_at":"2016-06-14T15:02:36.496Z","action":1,"author_id":1},{"id":186,"target_type":"MergeRequest","target_id":26,"project_id":5,"created_at":"2016-06-14T15:02:36.496Z","updated_at":"2016-06-14T15:02:36.496Z","action":1,"author_id":1}]}
-{"id":15,"target_branch":"test-7","source_branch":"test-1","source_project_id":5,"author_id":22,"assignee_id":16,"title":"Qui accusantium et inventore facilis doloribus occaecati officiis.","created_at":"2016-06-14T15:02:25.168Z","updated_at":"2016-06-14T15:02:59.521Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":7,"description":"Et commodi deserunt aspernatur vero rerum. Ut non dolorum alias in odit est libero. Voluptatibus eos in et vitae repudiandae facilis ex mollitia.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":777,"note":"Pariatur voluptas placeat aspernatur culpa suscipit soluta.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:59.348Z","updated_at":"2016-06-14T15:02:59.348Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":778,"note":"Alias et iure mollitia suscipit molestiae voluptatum nostrum asperiores.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:59.372Z","updated_at":"2016-06-14T15:02:59.372Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":779,"note":"Laudantium qui eum qui sunt.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:59.395Z","updated_at":"2016-06-14T15:02:59.395Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":780,"note":"Quas rem est iusto ut delectus fugiat recusandae mollitia.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:59.418Z","updated_at":"2016-06-14T15:02:59.418Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":781,"note":"Repellendus ab et qui nesciunt.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:59.444Z","updated_at":"2016-06-14T15:02:59.444Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":782,"note":"Non possimus voluptatum odio qui ut.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:59.469Z","updated_at":"2016-06-14T15:02:59.469Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":783,"note":"Dolores repellendus eum ducimus quam ab dolorem quia.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:59.494Z","updated_at":"2016-06-14T15:02:59.494Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":784,"note":"Facilis dolorem aut corrupti id ratione occaecati.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:59.520Z","updated_at":"2016-06-14T15:02:59.520Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":15,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":15,"relative_order":0,"sha":"94b8d581c48d894b86661718582fecbc5e3ed2eb","message":"fixes #10\n","authored_date":"2016-01-19T13:22:56.000+01:00","author_name":"James Lopez","author_email":"james@jameslopez.es","committed_date":"2016-01-19T13:22:56.000+01:00","committer_name":"James Lopez","committer_email":"james@jameslopez.es","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}}],"merge_request_diff_files":[{"merge_request_diff_id":15,"relative_order":0,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":15,"created_at":"2016-06-14T15:02:25.171Z","updated_at":"2016-06-14T15:02:25.230Z","base_commit_sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","real_size":"1"},"events":[{"id":223,"target_type":"MergeRequest","target_id":15,"project_id":36,"created_at":"2016-06-14T15:02:25.262Z","updated_at":"2016-06-14T15:02:25.262Z","action":1,"author_id":1},{"id":175,"target_type":"MergeRequest","target_id":15,"project_id":5,"created_at":"2016-06-14T15:02:25.262Z","updated_at":"2016-06-14T15:02:25.262Z","action":1,"author_id":22}]}
-{"id":14,"target_branch":"fix","source_branch":"test-3","source_project_id":5,"author_id":20,"assignee_id":20,"title":"In voluptas aut sequi voluptatem ullam vel corporis illum consequatur.","created_at":"2016-06-14T15:02:24.760Z","updated_at":"2016-06-14T15:02:59.749Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":6,"description":"Dicta magnam non voluptates nam dignissimos nostrum deserunt. Dolorum et suscipit iure quae doloremque. Necessitatibus saepe aut labore sed.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":785,"note":"Atque cupiditate necessitatibus deserunt minus natus odit.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:59.559Z","updated_at":"2016-06-14T15:02:59.559Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":786,"note":"Non dolorem provident mollitia nesciunt optio ex eveniet.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:59.587Z","updated_at":"2016-06-14T15:02:59.587Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":787,"note":"Similique officia nemo quasi commodi accusantium quae qui.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:59.621Z","updated_at":"2016-06-14T15:02:59.621Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":788,"note":"Et est et alias ad dolor qui.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:59.650Z","updated_at":"2016-06-14T15:02:59.650Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":789,"note":"Numquam temporibus ratione voluptatibus aliquid.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:59.675Z","updated_at":"2016-06-14T15:02:59.675Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":790,"note":"Ut ex aliquam consectetur perferendis est hic aut quia.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:59.703Z","updated_at":"2016-06-14T15:02:59.703Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":791,"note":"Esse eos quam quaerat aut ut asperiores officiis.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:59.726Z","updated_at":"2016-06-14T15:02:59.726Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":792,"note":"Sint facilis accusantium iure blanditiis.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:59.748Z","updated_at":"2016-06-14T15:02:59.748Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":14,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":14,"relative_order":0,"sha":"ddd4ff416a931589c695eb4f5b23f844426f6928","message":"fixes #10\n","authored_date":"2016-01-19T14:14:43.000+01:00","author_name":"James Lopez","author_email":"james@jameslopez.es","committed_date":"2016-01-19T14:14:43.000+01:00","committer_name":"James Lopez","committer_email":"james@jameslopez.es","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}},{"merge_request_diff_id":14,"relative_order":1,"sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","message":"Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6","authored_date":"2015-12-07T12:52:12.000+01:00","author_name":"Marin Jankovski","author_email":"marin@gitlab.com","committed_date":"2015-12-07T12:52:12.000+01:00","committer_name":"Marin Jankovski","committer_email":"marin@gitlab.com","commit_author":{"name":"Marin Jankovski","email":"marin@gitlab.com"},"committer":{"name":"Marin Jankovski","email":"marin@gitlab.com"}},{"merge_request_diff_id":14,"relative_order":2,"sha":"048721d90c449b244b7b4c53a9186b04330174ec","message":"LFS object pointer.\n","authored_date":"2015-12-07T11:54:28.000+01:00","author_name":"Marin Jankovski","author_email":"maxlazio@gmail.com","committed_date":"2015-12-07T11:54:28.000+01:00","committer_name":"Marin Jankovski","committer_email":"maxlazio@gmail.com","commit_author":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"},"committer":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"}},{"merge_request_diff_id":14,"relative_order":3,"sha":"5f923865dde3436854e9ceb9cdb7815618d4e849","message":"GitLab currently doesn't support patches that involve a merge commit: add a commit here\n","authored_date":"2015-11-13T16:27:12.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T16:27:12.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":4,"sha":"d2d430676773caa88cdaf7c55944073b2fd5561a","message":"Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5","authored_date":"2015-11-13T08:50:17.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T08:50:17.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":5,"sha":"2ea1f3dec713d940208fb5ce4a38765ecb5d3f73","message":"Add GitLab SVG\n","authored_date":"2015-11-13T08:39:43.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T08:39:43.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":6,"sha":"59e29889be61e6e0e5e223bfa9ac2721d31605b8","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4","authored_date":"2015-11-13T07:21:40.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T07:21:40.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":7,"sha":"66eceea0db202bb39c4e445e8ca28689645366c5","message":"add spaces in whitespace file\n","authored_date":"2015-11-13T06:01:27.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T06:01:27.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":14,"relative_order":8,"sha":"08f22f255f082689c0d7d39d19205085311542bc","message":"remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n","authored_date":"2015-11-13T06:00:16.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T06:00:16.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":14,"relative_order":9,"sha":"19e2e9b4ef76b422ce1154af39a91323ccc57434","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3","authored_date":"2015-11-13T05:23:14.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T05:23:14.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":10,"sha":"c642fe9b8b9f28f9225d7ea953fe14e74748d53b","message":"add whitespace in empty\n","authored_date":"2015-11-13T05:08:45.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T05:08:45.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":14,"relative_order":11,"sha":"9a944d90955aaf45f6d0c88f30e27f8d2c41cec0","message":"add empty file\n","authored_date":"2015-11-13T05:08:04.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T05:08:04.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":14,"relative_order":12,"sha":"c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd","message":"Add ISO-8859 test file\n","authored_date":"2015-08-25T17:53:12.000+02:00","author_name":"Stan Hu","author_email":"stanhu@packetzoom.com","committed_date":"2015-08-25T17:53:12.000+02:00","committer_name":"Stan Hu","committer_email":"stanhu@packetzoom.com","commit_author":{"name":"Stan Hu","email":"stanhu@packetzoom.com"},"committer":{"name":"Stan Hu","email":"stanhu@packetzoom.com"}},{"merge_request_diff_id":14,"relative_order":13,"sha":"e56497bb5f03a90a51293fc6d516788730953899","message":"Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/275#note_732774)\n\nSee merge request !2\n","authored_date":"2015-01-10T22:23:29.000+01:00","author_name":"Sytse Sijbrandij","author_email":"sytse@gitlab.com","committed_date":"2015-01-10T22:23:29.000+01:00","committer_name":"Sytse Sijbrandij","committer_email":"sytse@gitlab.com","commit_author":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"},"committer":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"}},{"merge_request_diff_id":14,"relative_order":14,"sha":"4cd80ccab63c82b4bad16faa5193fbd2aa06df40","message":"add directory structure for tree_helper spec\n","authored_date":"2015-01-10T21:28:18.000+01:00","author_name":"marmis85","author_email":"marmis85@gmail.com","committed_date":"2015-01-10T21:28:18.000+01:00","committer_name":"marmis85","committer_email":"marmis85@gmail.com","commit_author":{"name":"marmis85","email":"marmis85@gmail.com"},"committer":{"name":"marmis85","email":"marmis85@gmail.com"}},{"merge_request_diff_id":14,"relative_order":15,"sha":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","message":"Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T10:01:38.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T10:01:38.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":14,"relative_order":16,"sha":"570e7b2abdd848b95f2f578043fc23bd6f6fd24d","message":"Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:57:31.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:57:31.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":14,"relative_order":17,"sha":"6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9","message":"More submodules\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:54:21.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:54:21.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":14,"relative_order":18,"sha":"d14d6c0abdd253381df51a723d58691b2ee1ab08","message":"Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:49:50.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:49:50.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":14,"relative_order":19,"sha":"c1acaa58bbcbc3eafe538cb8274ba387047b69f8","message":"Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:48:32.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:48:32.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":14,"relative_order":0,"utf8_diff":"Binary files a/.DS_Store and /dev/null differ\n","new_path":".DS_Store","old_path":".DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":14,"relative_order":1,"utf8_diff":"--- a/.gitignore\n+++ b/.gitignore\n@@ -17,3 +17,4 @@ rerun.txt\n pickle-email-*.html\n .project\n config/initializers/secret_token.rb\n+.DS_Store\n","new_path":".gitignore","old_path":".gitignore","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":2,"utf8_diff":"--- a/.gitmodules\n+++ b/.gitmodules\n@@ -1,3 +1,9 @@\n [submodule \"six\"]\n \tpath = six\n \turl = git://github.com/randx/six.git\n+[submodule \"gitlab-shell\"]\n+\tpath = gitlab-shell\n+\turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n","new_path":".gitmodules","old_path":".gitmodules","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":3,"utf8_diff":"--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n","new_path":"CHANGELOG","old_path":"CHANGELOG","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n","new_path":"encoding/iso8859.txt","old_path":"encoding/iso8859.txt","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":5,"utf8_diff":"Binary files a/files/.DS_Store and /dev/null differ\n","new_path":"files/.DS_Store","old_path":"files/.DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":14,"relative_order":6,"utf8_diff":"--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n+<svg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n+ <!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->\n+ <title>wm</title>\n+ <desc>Created with Sketch.</desc>\n+ <defs>\n+ <path id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"></path>\n+ </defs>\n+ <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n+ <path d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\">\n+ <g id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\">\n+ <g id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\">\n+ <path d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"></path>\n+ </g>\n+ <g id=\"g16\">\n+ <g id=\"g18-Clipped\">\n+ <mask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\">\n+ <use xlink:href=\"#path-1\"></use>\n+ </mask>\n+ <g id=\"path22\"></g>\n+ <g id=\"g18\" mask=\"url(#mask-2)\">\n+ <g transform=\"translate(382.736659, 312.879425)\">\n+ <g id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\">\n+ <path d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\">\n+ <path d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\">\n+ <path d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\">\n+ <path d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <path d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <path d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\">\n+ <path d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\">\n+ <path d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path54\"></g>\n+ </g>\n+ <g id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\">\n+ <path d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <g id=\"path62\"></g>\n+ </g>\n+ <g id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\">\n+ <path d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path70\"></g>\n+ </g>\n+ <g id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\">\n+ <path d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <path d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\">\n+ <path d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\">\n+ <path d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+</svg>\n\\ No newline at end of file\n","new_path":"files/images/wm.svg","old_path":"files/images/wm.svg","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":7,"utf8_diff":"--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n","new_path":"files/lfs/lfs_object.iso","old_path":"files/lfs/lfs_object.iso","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":8,"utf8_diff":"--- a/files/ruby/popen.rb\n+++ b/files/ruby/popen.rb\n@@ -6,12 +6,18 @@ module Popen\n \n def popen(cmd, path=nil)\n unless cmd.is_a?(Array)\n- raise \"System commands must be given as an array of strings\"\n+ raise RuntimeError, \"System commands must be given as an array of strings\"\n end\n \n path ||= Dir.pwd\n- vars = { \"PWD\" => path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" => path\n+ }\n+\n+ options = {\n+ chdir: path\n+ }\n \n unless File.directory?(path)\n FileUtils.mkdir_p(path)\n@@ -19,6 +25,7 @@ module Popen\n \n @cmd_output = \"\"\n @cmd_status = 0\n+\n Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|\n @cmd_output << stdout.read\n @cmd_output << stderr.read\n","new_path":"files/ruby/popen.rb","old_path":"files/ruby/popen.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":9,"utf8_diff":"--- a/files/ruby/regex.rb\n+++ b/files/ruby/regex.rb\n@@ -19,14 +19,12 @@ module Gitlab\n end\n \n def archive_formats_regex\n- #|zip|tar| tar.gz | tar.bz2 |\n- /(zip|tar|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n+ /(zip|tar|7z|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n end\n \n def git_reference_regex\n # Valid git ref regex, see:\n # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html\n-\n %r{\n (?!\n (?# doesn't begins with)\n","new_path":"files/ruby/regex.rb","old_path":"files/ruby/regex.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":10,"utf8_diff":"--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n","new_path":"files/whitespace","old_path":"files/whitespace","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":11,"utf8_diff":"--- /dev/null\n+++ b/foo/bar/.gitkeep\n","new_path":"foo/bar/.gitkeep","old_path":"foo/bar/.gitkeep","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":12,"utf8_diff":"--- /dev/null\n+++ b/gitlab-grack\n@@ -0,0 +1 @@\n+Subproject commit 645f6c4c82fd3f5e06f67134450a570b795e55a6\n","new_path":"gitlab-grack","old_path":"gitlab-grack","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":13,"utf8_diff":"--- /dev/null\n+++ b/gitlab-shell\n@@ -0,0 +1 @@\n+Subproject commit 79bceae69cb5750d6567b223597999bfa91cb3b9\n","new_path":"gitlab-shell","old_path":"gitlab-shell","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":14,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":14,"created_at":"2016-06-14T15:02:24.770Z","updated_at":"2016-06-14T15:02:25.007Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"15"},"events":[{"id":224,"target_type":"MergeRequest","target_id":14,"project_id":36,"created_at":"2016-06-14T15:02:25.113Z","updated_at":"2016-06-14T15:02:25.113Z","action":1,"author_id":1},{"id":174,"target_type":"MergeRequest","target_id":14,"project_id":5,"created_at":"2016-06-14T15:02:25.113Z","updated_at":"2016-06-14T15:02:25.113Z","action":1,"author_id":20}]}
-{"id":13,"target_branch":"improve/awesome","source_branch":"test-8","source_project_id":5,"author_id":16,"assignee_id":25,"title":"Voluptates consequatur eius nemo amet libero animi illum delectus tempore.","created_at":"2016-06-14T15:02:24.415Z","updated_at":"2016-06-14T15:02:59.958Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":5,"description":"Est eaque quasi qui qui. Similique voluptatem impedit iusto ratione reprehenderit. Itaque est illum ut nulla aut.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":793,"note":"In illum maxime aperiam nulla est aspernatur.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:59.782Z","updated_at":"2016-06-14T15:02:59.782Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[{"merge_request_diff_id":14,"id":529,"target_type":"Note","target_id":793,"project_id":4,"created_at":"2016-07-07T14:35:12.128Z","updated_at":"2016-07-07T14:35:12.128Z","action":6,"author_id":1}]},{"id":794,"note":"Enim quia perferendis cum distinctio tenetur optio voluptas veniam.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:59.807Z","updated_at":"2016-06-14T15:02:59.807Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":795,"note":"Dolor ad quia quis pariatur ducimus.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:59.831Z","updated_at":"2016-06-14T15:02:59.831Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":796,"note":"Et a odio voluptate aut.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:59.854Z","updated_at":"2016-06-14T15:02:59.854Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":797,"note":"Quis nihil temporibus voluptatum modi minima a ut.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:59.879Z","updated_at":"2016-06-14T15:02:59.879Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":798,"note":"Ut alias consequatur in nostrum.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:59.904Z","updated_at":"2016-06-14T15:02:59.904Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":799,"note":"Voluptatibus aperiam assumenda et neque sint libero.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:59.926Z","updated_at":"2016-06-14T15:02:59.926Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":800,"note":"Veritatis voluptatem dolor dolores magni quo ut ipsa fuga.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:59.956Z","updated_at":"2016-06-14T15:02:59.956Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":13,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":13,"relative_order":0,"sha":"0bfedc29d30280c7e8564e19f654584b459e5868","message":"fixes #10\n","authored_date":"2016-01-19T15:25:23.000+01:00","author_name":"James Lopez","author_email":"james@jameslopez.es","committed_date":"2016-01-19T15:25:23.000+01:00","committer_name":"James Lopez","committer_email":"james@jameslopez.es","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}},{"merge_request_diff_id":13,"relative_order":1,"sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","message":"Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6","authored_date":"2015-12-07T12:52:12.000+01:00","author_name":"Marin Jankovski","author_email":"marin@gitlab.com","committed_date":"2015-12-07T12:52:12.000+01:00","committer_name":"Marin Jankovski","committer_email":"marin@gitlab.com","commit_author":{"name":"Marin Jankovski","email":"marin@gitlab.com"},"committer":{"name":"Marin Jankovski","email":"marin@gitlab.com"}},{"merge_request_diff_id":13,"relative_order":2,"sha":"048721d90c449b244b7b4c53a9186b04330174ec","message":"LFS object pointer.\n","authored_date":"2015-12-07T11:54:28.000+01:00","author_name":"Marin Jankovski","author_email":"maxlazio@gmail.com","committed_date":"2015-12-07T11:54:28.000+01:00","committer_name":"Marin Jankovski","committer_email":"maxlazio@gmail.com","commit_author":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"},"committer":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"}},{"merge_request_diff_id":13,"relative_order":3,"sha":"5f923865dde3436854e9ceb9cdb7815618d4e849","message":"GitLab currently doesn't support patches that involve a merge commit: add a commit here\n","authored_date":"2015-11-13T16:27:12.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T16:27:12.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":4,"sha":"d2d430676773caa88cdaf7c55944073b2fd5561a","message":"Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5","authored_date":"2015-11-13T08:50:17.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T08:50:17.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":5,"sha":"2ea1f3dec713d940208fb5ce4a38765ecb5d3f73","message":"Add GitLab SVG\n","authored_date":"2015-11-13T08:39:43.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T08:39:43.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":6,"sha":"59e29889be61e6e0e5e223bfa9ac2721d31605b8","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4","authored_date":"2015-11-13T07:21:40.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T07:21:40.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":7,"sha":"66eceea0db202bb39c4e445e8ca28689645366c5","message":"add spaces in whitespace file\n","authored_date":"2015-11-13T06:01:27.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T06:01:27.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":13,"relative_order":8,"sha":"08f22f255f082689c0d7d39d19205085311542bc","message":"remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n","authored_date":"2015-11-13T06:00:16.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T06:00:16.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":13,"relative_order":9,"sha":"19e2e9b4ef76b422ce1154af39a91323ccc57434","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3","authored_date":"2015-11-13T05:23:14.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T05:23:14.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":10,"sha":"c642fe9b8b9f28f9225d7ea953fe14e74748d53b","message":"add whitespace in empty\n","authored_date":"2015-11-13T05:08:45.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T05:08:45.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":13,"relative_order":11,"sha":"9a944d90955aaf45f6d0c88f30e27f8d2c41cec0","message":"add empty file\n","authored_date":"2015-11-13T05:08:04.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T05:08:04.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":13,"relative_order":12,"sha":"c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd","message":"Add ISO-8859 test file\n","authored_date":"2015-08-25T17:53:12.000+02:00","author_name":"Stan Hu","author_email":"stanhu@packetzoom.com","committed_date":"2015-08-25T17:53:12.000+02:00","committer_name":"Stan Hu","committer_email":"stanhu@packetzoom.com","commit_author":{"name":"Stan Hu","email":"stanhu@packetzoom.com"},"committer":{"name":"Stan Hu","email":"stanhu@packetzoom.com"}},{"merge_request_diff_id":13,"relative_order":13,"sha":"e56497bb5f03a90a51293fc6d516788730953899","message":"Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/275#note_732774)\n\nSee merge request !2\n","authored_date":"2015-01-10T22:23:29.000+01:00","author_name":"Sytse Sijbrandij","author_email":"sytse@gitlab.com","committed_date":"2015-01-10T22:23:29.000+01:00","committer_name":"Sytse Sijbrandij","committer_email":"sytse@gitlab.com","commit_author":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"},"committer":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"}},{"merge_request_diff_id":13,"relative_order":14,"sha":"4cd80ccab63c82b4bad16faa5193fbd2aa06df40","message":"add directory structure for tree_helper spec\n","authored_date":"2015-01-10T21:28:18.000+01:00","author_name":"marmis85","author_email":"marmis85@gmail.com","committed_date":"2015-01-10T21:28:18.000+01:00","committer_name":"marmis85","committer_email":"marmis85@gmail.com","commit_author":{"name":"marmis85","email":"marmis85@gmail.com"},"committer":{"name":"marmis85","email":"marmis85@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":13,"relative_order":0,"utf8_diff":"--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n","new_path":"CHANGELOG","old_path":"CHANGELOG","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":1,"utf8_diff":"--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n","new_path":"encoding/iso8859.txt","old_path":"encoding/iso8859.txt","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":2,"utf8_diff":"--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n+<svg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n+ <!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->\n+ <title>wm</title>\n+ <desc>Created with Sketch.</desc>\n+ <defs>\n+ <path id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"></path>\n+ </defs>\n+ <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n+ <path d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\">\n+ <g id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\">\n+ <g id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\">\n+ <path d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"></path>\n+ </g>\n+ <g id=\"g16\">\n+ <g id=\"g18-Clipped\">\n+ <mask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\">\n+ <use xlink:href=\"#path-1\"></use>\n+ </mask>\n+ <g id=\"path22\"></g>\n+ <g id=\"g18\" mask=\"url(#mask-2)\">\n+ <g transform=\"translate(382.736659, 312.879425)\">\n+ <g id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\">\n+ <path d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\">\n+ <path d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\">\n+ <path d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\">\n+ <path d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <path d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <path d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\">\n+ <path d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\">\n+ <path d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path54\"></g>\n+ </g>\n+ <g id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\">\n+ <path d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <g id=\"path62\"></g>\n+ </g>\n+ <g id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\">\n+ <path d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path70\"></g>\n+ </g>\n+ <g id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\">\n+ <path d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <path d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\">\n+ <path d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\">\n+ <path d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+</svg>\n\\ No newline at end of file\n","new_path":"files/images/wm.svg","old_path":"files/images/wm.svg","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":3,"utf8_diff":"--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n","new_path":"files/lfs/lfs_object.iso","old_path":"files/lfs/lfs_object.iso","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n","new_path":"files/whitespace","old_path":"files/whitespace","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":5,"utf8_diff":"--- /dev/null\n+++ b/foo/bar/.gitkeep\n","new_path":"foo/bar/.gitkeep","old_path":"foo/bar/.gitkeep","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":6,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":13,"created_at":"2016-06-14T15:02:24.420Z","updated_at":"2016-06-14T15:02:24.561Z","base_commit_sha":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","real_size":"7"},"events":[{"id":225,"target_type":"MergeRequest","target_id":13,"project_id":36,"created_at":"2016-06-14T15:02:24.636Z","updated_at":"2016-06-14T15:02:24.636Z","action":1,"author_id":16},{"id":173,"target_type":"MergeRequest","target_id":13,"project_id":5,"created_at":"2016-06-14T15:02:24.636Z","updated_at":"2016-06-14T15:02:24.636Z","action":1,"author_id":16}]}
-{"id":12,"target_branch":"flatten-dirs","source_branch":"test-2","source_project_id":5,"author_id":1,"assignee_id":22,"title":"In a rerum harum nihil accusamus aut quia nobis non.","created_at":"2016-06-14T15:02:24.000Z","updated_at":"2016-06-14T15:03:00.225Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":4,"description":"Nam magnam odit velit rerum. Sapiente dolore sunt saepe debitis. Culpa maiores ut ad dolores dolorem et.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":801,"note":"Nihil dicta molestias expedita atque.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:03:00.001Z","updated_at":"2016-06-14T15:03:00.001Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":802,"note":"Illum culpa voluptas enim accusantium deserunt.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:03:00.034Z","updated_at":"2016-06-14T15:03:00.034Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":803,"note":"Dicta esse aliquam laboriosam unde alias.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:03:00.065Z","updated_at":"2016-06-14T15:03:00.065Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":804,"note":"Dicta autem et sed molestiae ut quae.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:03:00.097Z","updated_at":"2016-06-14T15:03:00.097Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":805,"note":"Ut ut temporibus voluptas dolore quia velit.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:03:00.129Z","updated_at":"2016-06-14T15:03:00.129Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":806,"note":"Dolores similique sint pariatur error id quia fugit aut.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:03:00.162Z","updated_at":"2016-06-14T15:03:00.162Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":807,"note":"Quisquam provident nihil aperiam voluptatem.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:03:00.193Z","updated_at":"2016-06-14T15:03:00.193Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":808,"note":"Similique quo vero expedita deserunt ipsam earum.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:03:00.224Z","updated_at":"2016-06-14T15:03:00.224Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":12,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":12,"relative_order":0,"sha":"97a0df9696e2aebf10c31b3016f40214e0e8f243","message":"fixes #10\n","authored_date":"2016-01-19T14:08:21.000+01:00","author_name":"James Lopez","author_email":"james@jameslopez.es","committed_date":"2016-01-19T14:08:21.000+01:00","committer_name":"James Lopez","committer_email":"james@jameslopez.es","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}},{"merge_request_diff_id":12,"relative_order":1,"sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","message":"Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6","authored_date":"2015-12-07T12:52:12.000+01:00","author_name":"Marin Jankovski","author_email":"marin@gitlab.com","committed_date":"2015-12-07T12:52:12.000+01:00","committer_name":"Marin Jankovski","committer_email":"marin@gitlab.com","commit_author":{"name":"Marin Jankovski","email":"marin@gitlab.com"},"committer":{"name":"Marin Jankovski","email":"marin@gitlab.com"}},{"merge_request_diff_id":12,"relative_order":2,"sha":"048721d90c449b244b7b4c53a9186b04330174ec","message":"LFS object pointer.\n","authored_date":"2015-12-07T11:54:28.000+01:00","author_name":"Marin Jankovski","author_email":"maxlazio@gmail.com","committed_date":"2015-12-07T11:54:28.000+01:00","committer_name":"Marin Jankovski","committer_email":"maxlazio@gmail.com","commit_author":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"},"committer":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"}},{"merge_request_diff_id":12,"relative_order":3,"sha":"5f923865dde3436854e9ceb9cdb7815618d4e849","message":"GitLab currently doesn't support patches that involve a merge commit: add a commit here\n","authored_date":"2015-11-13T16:27:12.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T16:27:12.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":12,"relative_order":4,"sha":"d2d430676773caa88cdaf7c55944073b2fd5561a","message":"Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5","authored_date":"2015-11-13T08:50:17.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T08:50:17.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":12,"relative_order":5,"sha":"2ea1f3dec713d940208fb5ce4a38765ecb5d3f73","message":"Add GitLab SVG\n","authored_date":"2015-11-13T08:39:43.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T08:39:43.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":12,"relative_order":6,"sha":"59e29889be61e6e0e5e223bfa9ac2721d31605b8","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4","authored_date":"2015-11-13T07:21:40.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T07:21:40.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":12,"relative_order":7,"sha":"66eceea0db202bb39c4e445e8ca28689645366c5","message":"add spaces in whitespace file\n","authored_date":"2015-11-13T06:01:27.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T06:01:27.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":12,"relative_order":8,"sha":"08f22f255f082689c0d7d39d19205085311542bc","message":"remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n","authored_date":"2015-11-13T06:00:16.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T06:00:16.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":12,"relative_order":9,"sha":"19e2e9b4ef76b422ce1154af39a91323ccc57434","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3","authored_date":"2015-11-13T05:23:14.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T05:23:14.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":12,"relative_order":10,"sha":"c642fe9b8b9f28f9225d7ea953fe14e74748d53b","message":"add whitespace in empty\n","authored_date":"2015-11-13T05:08:45.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T05:08:45.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":12,"relative_order":11,"sha":"9a944d90955aaf45f6d0c88f30e27f8d2c41cec0","message":"add empty file\n","authored_date":"2015-11-13T05:08:04.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T05:08:04.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":12,"relative_order":12,"sha":"c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd","message":"Add ISO-8859 test file\n","authored_date":"2015-08-25T17:53:12.000+02:00","author_name":"Stan Hu","author_email":"stanhu@packetzoom.com","committed_date":"2015-08-25T17:53:12.000+02:00","committer_name":"Stan Hu","committer_email":"stanhu@packetzoom.com","commit_author":{"name":"Stan Hu","email":"stanhu@packetzoom.com"},"committer":{"name":"Stan Hu","email":"stanhu@packetzoom.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":12,"relative_order":0,"utf8_diff":"--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n","new_path":"CHANGELOG","old_path":"CHANGELOG","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":12,"relative_order":1,"utf8_diff":"--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n","new_path":"encoding/iso8859.txt","old_path":"encoding/iso8859.txt","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":12,"relative_order":2,"utf8_diff":"--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n+<svg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n+ <!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->\n+ <title>wm</title>\n+ <desc>Created with Sketch.</desc>\n+ <defs>\n+ <path id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"></path>\n+ </defs>\n+ <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n+ <path d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\">\n+ <g id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\">\n+ <g id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\">\n+ <path d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"></path>\n+ </g>\n+ <g id=\"g16\">\n+ <g id=\"g18-Clipped\">\n+ <mask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\">\n+ <use xlink:href=\"#path-1\"></use>\n+ </mask>\n+ <g id=\"path22\"></g>\n+ <g id=\"g18\" mask=\"url(#mask-2)\">\n+ <g transform=\"translate(382.736659, 312.879425)\">\n+ <g id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\">\n+ <path d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\">\n+ <path d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\">\n+ <path d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\">\n+ <path d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <path d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <path d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\">\n+ <path d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\">\n+ <path d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path54\"></g>\n+ </g>\n+ <g id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\">\n+ <path d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <g id=\"path62\"></g>\n+ </g>\n+ <g id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\">\n+ <path d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path70\"></g>\n+ </g>\n+ <g id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\">\n+ <path d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <path d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\">\n+ <path d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\">\n+ <path d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+</svg>\n\\ No newline at end of file\n","new_path":"files/images/wm.svg","old_path":"files/images/wm.svg","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":12,"relative_order":3,"utf8_diff":"--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n","new_path":"files/lfs/lfs_object.iso","old_path":"files/lfs/lfs_object.iso","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":12,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n","new_path":"files/whitespace","old_path":"files/whitespace","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":12,"relative_order":5,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":12,"created_at":"2016-06-14T15:02:24.006Z","updated_at":"2016-06-14T15:02:24.169Z","base_commit_sha":"e56497bb5f03a90a51293fc6d516788730953899","real_size":"6"},"events":[{"id":226,"target_type":"MergeRequest","target_id":12,"project_id":36,"created_at":"2016-06-14T15:02:24.253Z","updated_at":"2016-06-14T15:02:24.253Z","action":1,"author_id":1},{"id":172,"target_type":"MergeRequest","target_id":12,"project_id":5,"created_at":"2016-06-14T15:02:24.253Z","updated_at":"2016-06-14T15:02:24.253Z","action":1,"author_id":1}]}
+{"id":27,"target_branch":"feature","source_branch":"feature_conflict","source_project_id":2147483547,"author_id":1,"assignee_id":null,"title":"MR1","created_at":"2016-06-14T15:02:36.568Z","updated_at":"2016-06-14T15:02:56.815Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":9,"description":null,"position":0,"updated_by_id":null,"merge_error":null,"diff_head_sha":"HEAD","source_branch_sha":"ABCD","target_branch_sha":"DCBA","merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":true,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":669,"note":"added 3 commits\n\n<ul><li>16ea4e20...074a2a32 - 2 commits from branch <code>master</code></li><li>ca223a02 - readme: fix typos</li></ul>\n\n[Compare with previous version](/group/project/merge_requests/1/diffs?diff_id=1189&start_sha=16ea4e207fb258fe4e9c73185a725207c9a4f3e1)","noteable_type":"MergeRequest","author_id":26,"created_at":"2020-03-28T12:47:33.461Z","updated_at":"2020-03-28T12:47:33.461Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"system":true,"st_diff":null,"updated_by_id":null,"position":null,"original_position":null,"resolved_at":null,"resolved_by_id":null,"discussion_id":null,"change_position":null,"resolved_by_push":null,"confidential":null,"type":null,"author":{"name":"User 4"},"award_emoji":[],"system_note_metadata":{"id":4789,"commit_count":3,"action":"commit","created_at":"2020-03-28T12:47:33.461Z","updated_at":"2020-03-28T12:47:33.461Z"},"events":[],"suggestions":[]},{"id":670,"note":"unmarked as a **Work In Progress**","noteable_type":"MergeRequest","author_id":26,"created_at":"2020-03-28T12:48:36.951Z","updated_at":"2020-03-28T12:48:36.951Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"system":true,"st_diff":null,"updated_by_id":null,"position":null,"original_position":null,"resolved_at":null,"resolved_by_id":null,"discussion_id":null,"change_position":null,"resolved_by_push":null,"confidential":null,"type":null,"author":{"name":"User 4"},"award_emoji":[],"system_note_metadata":{"id":4790,"commit_count":null,"action":"title","created_at":"2020-03-28T12:48:36.951Z","updated_at":"2020-03-28T12:48:36.951Z"},"events":[],"suggestions":[]},{"id":671,"note":"Sit voluptatibus eveniet architecto quidem.","note_html":"<p>something else entirely</p>","cached_markdown_version":917504,"noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:56.632Z","updated_at":"2016-06-14T15:02:56.632Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[],"award_emoji":[{"id":1,"name":"tada","user_id":1,"awardable_type":"Note","awardable_id":1,"created_at":"2019-11-05T15:37:21.287Z","updated_at":"2019-11-05T15:37:21.287Z"}]},{"id":672,"note":"Odio maxime ratione voluptatibus sed.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:56.656Z","updated_at":"2016-06-14T15:02:56.656Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":673,"note":"Et deserunt et omnis nihil excepturi accusantium.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:56.679Z","updated_at":"2016-06-14T15:02:56.679Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":674,"note":"Saepe asperiores exercitationem non dignissimos laborum reiciendis et ipsum.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:56.700Z","updated_at":"2016-06-14T15:02:56.700Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[],"suggestions":[{"id":1,"note_id":674,"relative_order":0,"applied":false,"commit_id":null,"from_content":"Original line\n","to_content":"New line\n","lines_above":0,"lines_below":0,"outdated":false}]},{"id":675,"note":"Numquam est at dolor quo et sed eligendi similique.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:56.720Z","updated_at":"2016-06-14T15:02:56.720Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":676,"note":"Et perferendis aliquam sunt nisi labore delectus.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:56.742Z","updated_at":"2016-06-14T15:02:56.742Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":677,"note":"Aut ex rerum et in.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:56.791Z","updated_at":"2016-06-14T15:02:56.791Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":678,"note":"Dolor laborum earum ut exercitationem.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:56.814Z","updated_at":"2016-06-14T15:02:56.814Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"resource_label_events":[{"id":243,"action":"add","issue_id":null,"merge_request_id":27,"label_id":null,"user_id":1,"created_at":"2018-08-28T08:24:00.494Z"}],"merge_request_diff":{"id":27,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":27,"relative_order":0,"sha":"bb5206fee213d983da88c47f9cf4cc6caf9c66dc","message":"Feature conflict added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-08-06T08:35:52.000+02:00","committed_date":"2014-08-06T08:35:52.000+02:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":1,"sha":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","message":"Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T10:01:38.000+01:00","committed_date":"2014-02-27T10:01:38.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":2,"sha":"570e7b2abdd848b95f2f578043fc23bd6f6fd24d","message":"Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:57:31.000+01:00","committed_date":"2014-02-27T09:57:31.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":3,"sha":"6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9","message":"More submodules\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:54:21.000+01:00","committed_date":"2014-02-27T09:54:21.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":4,"sha":"d14d6c0abdd253381df51a723d58691b2ee1ab08","message":"Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:49:50.000+01:00","committed_date":"2014-02-27T09:49:50.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":5,"sha":"c1acaa58bbcbc3eafe538cb8274ba387047b69f8","message":"Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:48:32.000+01:00","committed_date":"2014-02-27T09:48:32.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":27,"relative_order":0,"utf8_diff":"Binary files a/.DS_Store and /dev/null differ\n","new_path":".DS_Store","old_path":".DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":27,"relative_order":1,"utf8_diff":"--- a/.gitignore\n+++ b/.gitignore\n@@ -17,3 +17,4 @@ rerun.txt\n pickle-email-*.html\n .project\n config/initializers/secret_token.rb\n+.DS_Store\n","new_path":".gitignore","old_path":".gitignore","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":2,"utf8_diff":"--- a/.gitmodules\n+++ b/.gitmodules\n@@ -1,3 +1,9 @@\n [submodule \"six\"]\n \tpath = six\n \turl = git://github.com/randx/six.git\n+[submodule \"gitlab-shell\"]\n+\tpath = gitlab-shell\n+\turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n","new_path":".gitmodules","old_path":".gitmodules","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":3,"utf8_diff":"Binary files a/files/.DS_Store and /dev/null differ\n","new_path":"files/.DS_Store","old_path":"files/.DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":27,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/files/ruby/feature.rb\n@@ -0,0 +1,4 @@\n+# This file was changed in feature branch\n+# We put different code here to make merge conflict\n+class Conflict\n+end\n","new_path":"files/ruby/feature.rb","old_path":"files/ruby/feature.rb","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":5,"utf8_diff":"--- a/files/ruby/popen.rb\n+++ b/files/ruby/popen.rb\n@@ -6,12 +6,18 @@ module Popen\n \n def popen(cmd, path=nil)\n unless cmd.is_a?(Array)\n- raise \"System commands must be given as an array of strings\"\n+ raise RuntimeError, \"System commands must be given as an array of strings\"\n end\n \n path ||= Dir.pwd\n- vars = { \"PWD\" => path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" => path\n+ }\n+\n+ options = {\n+ chdir: path\n+ }\n \n unless File.directory?(path)\n FileUtils.mkdir_p(path)\n@@ -19,6 +25,7 @@ module Popen\n \n @cmd_output = \"\"\n @cmd_status = 0\n+\n Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|\n @cmd_output << stdout.read\n @cmd_output << stderr.read\n","new_path":"files/ruby/popen.rb","old_path":"files/ruby/popen.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":6,"utf8_diff":"--- a/files/ruby/regex.rb\n+++ b/files/ruby/regex.rb\n@@ -19,14 +19,12 @@ module Gitlab\n end\n \n def archive_formats_regex\n- #|zip|tar| tar.gz | tar.bz2 |\n- /(zip|tar|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n+ /(zip|tar|7z|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n end\n \n def git_reference_regex\n # Valid git ref regex, see:\n # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html\n-\n %r{\n (?!\n (?# doesn't begins with)\n","new_path":"files/ruby/regex.rb","old_path":"files/ruby/regex.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":7,"utf8_diff":"--- /dev/null\n+++ b/gitlab-grack\n@@ -0,0 +1 @@\n+Subproject commit 645f6c4c82fd3f5e06f67134450a570b795e55a6\n","new_path":"gitlab-grack","old_path":"gitlab-grack","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":8,"utf8_diff":"--- /dev/null\n+++ b/gitlab-shell\n@@ -0,0 +1 @@\n+Subproject commit 79bceae69cb5750d6567b223597999bfa91cb3b9\n","new_path":"gitlab-shell","old_path":"gitlab-shell","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":27,"created_at":"2016-06-14T15:02:36.572Z","updated_at":"2016-06-14T15:02:36.658Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"9"},"events":[{"id":221,"target_type":"MergeRequest","target_id":27,"project_id":36,"created_at":"2016-06-14T15:02:36.703Z","updated_at":"2016-06-14T15:02:36.703Z","action":1,"author_id":1},{"id":187,"target_type":"MergeRequest","target_id":27,"project_id":5,"created_at":"2016-06-14T15:02:36.703Z","updated_at":"2016-06-14T15:02:36.703Z","action":1,"author_id":1}],"approvals_before_merge":1,"award_emoji":[{"id":1,"name":"thumbsup","user_id":1,"awardable_type":"MergeRequest","awardable_id":27,"created_at":"2020-01-07T11:21:21.235Z","updated_at":"2020-01-07T11:21:21.235Z"},{"id":2,"name":"drum","user_id":1,"awardable_type":"MergeRequest","awardable_id":27,"created_at":"2020-01-07T11:21:21.235Z","updated_at":"2020-01-07T11:21:21.235Z"}]}
+{"id":26,"target_branch":"master","source_branch":"feature","source_project_id":4,"author_id":1,"assignee_id":null,"title":"MR2","created_at":"2016-06-14T15:02:36.418Z","updated_at":"2016-06-14T15:02:57.013Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":8,"description":null,"position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":679,"note":"Qui rerum totam nisi est.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:56.848Z","updated_at":"2016-06-14T15:02:56.848Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":680,"note":"Pariatur magni corrupti consequatur debitis minima error beatae voluptatem.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:56.871Z","updated_at":"2016-06-14T15:02:56.871Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":681,"note":"Qui quis ut modi eos rerum ratione.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:56.895Z","updated_at":"2016-06-14T15:02:56.895Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":682,"note":"Illum quidem expedita mollitia fugit.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:56.918Z","updated_at":"2016-06-14T15:02:56.918Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":683,"note":"Consectetur voluptate sit sint possimus veritatis quod.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:56.942Z","updated_at":"2016-06-14T15:02:56.942Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":684,"note":"Natus libero quibusdam rem assumenda deleniti accusamus sed earum.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:56.966Z","updated_at":"2016-06-14T15:02:56.966Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":685,"note":"Tenetur autem nihil rerum odit.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:56.989Z","updated_at":"2016-06-14T15:02:56.989Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":686,"note":"Quia maiores et odio sed.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:57.012Z","updated_at":"2016-06-14T15:02:57.012Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":26,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":26,"sha":"0b4bc9a49b562e85de7cc9e834518ea6828729b9","relative_order":0,"message":"Feature added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:26:01.000+01:00","committed_date":"2014-02-27T09:26:01.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":26,"relative_order":0,"utf8_diff":"--- /dev/null\n+++ b/files/ruby/feature.rb\n@@ -0,0 +1,5 @@\n+class Feature\n+ def foo\n+ puts 'bar'\n+ end\n+end\n","new_path":"files/ruby/feature.rb","old_path":"files/ruby/feature.rb","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":26,"created_at":"2016-06-14T15:02:36.421Z","updated_at":"2016-06-14T15:02:36.474Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"1"},"events":[{"id":222,"target_type":"MergeRequest","target_id":26,"project_id":36,"created_at":"2016-06-14T15:02:36.496Z","updated_at":"2016-06-14T15:02:36.496Z","action":1,"author_id":1},{"id":186,"target_type":"MergeRequest","target_id":26,"project_id":5,"created_at":"2016-06-14T15:02:36.496Z","updated_at":"2016-06-14T15:02:36.496Z","action":1,"author_id":1}]}
+{"id":15,"target_branch":"test-7","source_branch":"test-1","source_project_id":5,"author_id":22,"assignee_id":16,"title":"Qui accusantium et inventore facilis doloribus occaecati officiis.","created_at":"2016-06-14T15:02:25.168Z","updated_at":"2016-06-14T15:02:59.521Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":7,"description":"Et commodi deserunt aspernatur vero rerum. Ut non dolorum alias in odit est libero. Voluptatibus eos in et vitae repudiandae facilis ex mollitia.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":777,"note":"Pariatur voluptas placeat aspernatur culpa suscipit soluta.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:59.348Z","updated_at":"2016-06-14T15:02:59.348Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":778,"note":"Alias et iure mollitia suscipit molestiae voluptatum nostrum asperiores.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:59.372Z","updated_at":"2016-06-14T15:02:59.372Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":779,"note":"Laudantium qui eum qui sunt.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:59.395Z","updated_at":"2016-06-14T15:02:59.395Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":780,"note":"Quas rem est iusto ut delectus fugiat recusandae mollitia.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:59.418Z","updated_at":"2016-06-14T15:02:59.418Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":781,"note":"Repellendus ab et qui nesciunt.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:59.444Z","updated_at":"2016-06-14T15:02:59.444Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":782,"note":"Non possimus voluptatum odio qui ut.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:59.469Z","updated_at":"2016-06-14T15:02:59.469Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":783,"note":"Dolores repellendus eum ducimus quam ab dolorem quia.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:59.494Z","updated_at":"2016-06-14T15:02:59.494Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":784,"note":"Facilis dolorem aut corrupti id ratione occaecati.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:59.520Z","updated_at":"2016-06-14T15:02:59.520Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":15,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":15,"relative_order":0,"sha":"94b8d581c48d894b86661718582fecbc5e3ed2eb","message":"fixes #10\n","authored_date":"2016-01-19T13:22:56.000+01:00","committed_date":"2016-01-19T13:22:56.000+01:00","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}}],"merge_request_diff_files":[{"merge_request_diff_id":15,"relative_order":0,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":15,"created_at":"2016-06-14T15:02:25.171Z","updated_at":"2016-06-14T15:02:25.230Z","base_commit_sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","real_size":"1"},"events":[{"id":223,"target_type":"MergeRequest","target_id":15,"project_id":36,"created_at":"2016-06-14T15:02:25.262Z","updated_at":"2016-06-14T15:02:25.262Z","action":1,"author_id":1},{"id":175,"target_type":"MergeRequest","target_id":15,"project_id":5,"created_at":"2016-06-14T15:02:25.262Z","updated_at":"2016-06-14T15:02:25.262Z","action":1,"author_id":22}]}
+{"id":14,"target_branch":"fix","source_branch":"test-3","source_project_id":5,"author_id":20,"assignee_id":20,"title":"In voluptas aut sequi voluptatem ullam vel corporis illum consequatur.","created_at":"2016-06-14T15:02:24.760Z","updated_at":"2016-06-14T15:02:59.749Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":6,"description":"Dicta magnam non voluptates nam dignissimos nostrum deserunt. Dolorum et suscipit iure quae doloremque. Necessitatibus saepe aut labore sed.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":785,"note":"Atque cupiditate necessitatibus deserunt minus natus odit.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:59.559Z","updated_at":"2016-06-14T15:02:59.559Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":786,"note":"Non dolorem provident mollitia nesciunt optio ex eveniet.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:59.587Z","updated_at":"2016-06-14T15:02:59.587Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":787,"note":"Similique officia nemo quasi commodi accusantium quae qui.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:59.621Z","updated_at":"2016-06-14T15:02:59.621Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":788,"note":"Et est et alias ad dolor qui.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:59.650Z","updated_at":"2016-06-14T15:02:59.650Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":789,"note":"Numquam temporibus ratione voluptatibus aliquid.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:59.675Z","updated_at":"2016-06-14T15:02:59.675Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":790,"note":"Ut ex aliquam consectetur perferendis est hic aut quia.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:59.703Z","updated_at":"2016-06-14T15:02:59.703Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":791,"note":"Esse eos quam quaerat aut ut asperiores officiis.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:59.726Z","updated_at":"2016-06-14T15:02:59.726Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":792,"note":"Sint facilis accusantium iure blanditiis.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:59.748Z","updated_at":"2016-06-14T15:02:59.748Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":14,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":14,"relative_order":0,"sha":"ddd4ff416a931589c695eb4f5b23f844426f6928","message":"fixes #10\n","authored_date":"2016-01-19T14:14:43.000+01:00","committed_date":"2016-01-19T14:14:43.000+01:00","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}},{"merge_request_diff_id":14,"relative_order":1,"sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","message":"Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6","authored_date":"2015-12-07T12:52:12.000+01:00","committed_date":"2015-12-07T12:52:12.000+01:00","commit_author":{"name":"Marin Jankovski","email":"marin@gitlab.com"},"committer":{"name":"Marin Jankovski","email":"marin@gitlab.com"}},{"merge_request_diff_id":14,"relative_order":2,"sha":"048721d90c449b244b7b4c53a9186b04330174ec","message":"LFS object pointer.\n","authored_date":"2015-12-07T11:54:28.000+01:00","committed_date":"2015-12-07T11:54:28.000+01:00","commit_author":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"},"committer":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"}},{"merge_request_diff_id":14,"relative_order":3,"sha":"5f923865dde3436854e9ceb9cdb7815618d4e849","message":"GitLab currently doesn't support patches that involve a merge commit: add a commit here\n","authored_date":"2015-11-13T16:27:12.000+01:00","committed_date":"2015-11-13T16:27:12.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":4,"sha":"d2d430676773caa88cdaf7c55944073b2fd5561a","message":"Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5","authored_date":"2015-11-13T08:50:17.000+01:00","committed_date":"2015-11-13T08:50:17.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":5,"sha":"2ea1f3dec713d940208fb5ce4a38765ecb5d3f73","message":"Add GitLab SVG\n","authored_date":"2015-11-13T08:39:43.000+01:00","committed_date":"2015-11-13T08:39:43.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":6,"sha":"59e29889be61e6e0e5e223bfa9ac2721d31605b8","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4","authored_date":"2015-11-13T07:21:40.000+01:00","committed_date":"2015-11-13T07:21:40.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":7,"sha":"66eceea0db202bb39c4e445e8ca28689645366c5","message":"add spaces in whitespace file\n","authored_date":"2015-11-13T06:01:27.000+01:00","committed_date":"2015-11-13T06:01:27.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":14,"relative_order":8,"sha":"08f22f255f082689c0d7d39d19205085311542bc","message":"remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n","authored_date":"2015-11-13T06:00:16.000+01:00","committed_date":"2015-11-13T06:00:16.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":14,"relative_order":9,"sha":"19e2e9b4ef76b422ce1154af39a91323ccc57434","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3","authored_date":"2015-11-13T05:23:14.000+01:00","committed_date":"2015-11-13T05:23:14.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":10,"sha":"c642fe9b8b9f28f9225d7ea953fe14e74748d53b","message":"add whitespace in empty\n","authored_date":"2015-11-13T05:08:45.000+01:00","committed_date":"2015-11-13T05:08:45.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":14,"relative_order":11,"sha":"9a944d90955aaf45f6d0c88f30e27f8d2c41cec0","message":"add empty file\n","authored_date":"2015-11-13T05:08:04.000+01:00","committed_date":"2015-11-13T05:08:04.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":14,"relative_order":12,"sha":"c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd","message":"Add ISO-8859 test file\n","authored_date":"2015-08-25T17:53:12.000+02:00","committed_date":"2015-08-25T17:53:12.000+02:00","commit_author":{"name":"Stan Hu","email":"stanhu@packetzoom.com"},"committer":{"name":"Stan Hu","email":"stanhu@packetzoom.com"}},{"merge_request_diff_id":14,"relative_order":13,"sha":"e56497bb5f03a90a51293fc6d516788730953899","message":"Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/275#note_732774)\n\nSee merge request !2\n","authored_date":"2015-01-10T22:23:29.000+01:00","committed_date":"2015-01-10T22:23:29.000+01:00","commit_author":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"},"committer":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"}},{"merge_request_diff_id":14,"relative_order":14,"sha":"4cd80ccab63c82b4bad16faa5193fbd2aa06df40","message":"add directory structure for tree_helper spec\n","authored_date":"2015-01-10T21:28:18.000+01:00","committed_date":"2015-01-10T21:28:18.000+01:00","commit_author":{"name":"marmis85","email":"marmis85@gmail.com"},"committer":{"name":"marmis85","email":"marmis85@gmail.com"}},{"merge_request_diff_id":14,"relative_order":15,"sha":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","message":"Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T10:01:38.000+01:00","committed_date":"2014-02-27T10:01:38.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":14,"relative_order":16,"sha":"570e7b2abdd848b95f2f578043fc23bd6f6fd24d","message":"Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:57:31.000+01:00","committed_date":"2014-02-27T09:57:31.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":14,"relative_order":17,"sha":"6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9","message":"More submodules\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:54:21.000+01:00","committed_date":"2014-02-27T09:54:21.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":14,"relative_order":18,"sha":"d14d6c0abdd253381df51a723d58691b2ee1ab08","message":"Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:49:50.000+01:00","committed_date":"2014-02-27T09:49:50.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":14,"relative_order":19,"sha":"c1acaa58bbcbc3eafe538cb8274ba387047b69f8","message":"Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:48:32.000+01:00","committed_date":"2014-02-27T09:48:32.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":14,"relative_order":0,"utf8_diff":"Binary files a/.DS_Store and /dev/null differ\n","new_path":".DS_Store","old_path":".DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":14,"relative_order":1,"utf8_diff":"--- a/.gitignore\n+++ b/.gitignore\n@@ -17,3 +17,4 @@ rerun.txt\n pickle-email-*.html\n .project\n config/initializers/secret_token.rb\n+.DS_Store\n","new_path":".gitignore","old_path":".gitignore","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":2,"utf8_diff":"--- a/.gitmodules\n+++ b/.gitmodules\n@@ -1,3 +1,9 @@\n [submodule \"six\"]\n \tpath = six\n \turl = git://github.com/randx/six.git\n+[submodule \"gitlab-shell\"]\n+\tpath = gitlab-shell\n+\turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n","new_path":".gitmodules","old_path":".gitmodules","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":3,"utf8_diff":"--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n","new_path":"CHANGELOG","old_path":"CHANGELOG","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n","new_path":"encoding/iso8859.txt","old_path":"encoding/iso8859.txt","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":5,"utf8_diff":"Binary files a/files/.DS_Store and /dev/null differ\n","new_path":"files/.DS_Store","old_path":"files/.DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":14,"relative_order":6,"utf8_diff":"--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n+<svg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n+ <!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->\n+ <title>wm</title>\n+ <desc>Created with Sketch.</desc>\n+ <defs>\n+ <path id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"></path>\n+ </defs>\n+ <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n+ <path d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\">\n+ <g id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\">\n+ <g id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\">\n+ <path d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"></path>\n+ </g>\n+ <g id=\"g16\">\n+ <g id=\"g18-Clipped\">\n+ <mask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\">\n+ <use xlink:href=\"#path-1\"></use>\n+ </mask>\n+ <g id=\"path22\"></g>\n+ <g id=\"g18\" mask=\"url(#mask-2)\">\n+ <g transform=\"translate(382.736659, 312.879425)\">\n+ <g id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\">\n+ <path d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\">\n+ <path d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\">\n+ <path d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\">\n+ <path d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <path d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <path d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\">\n+ <path d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\">\n+ <path d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path54\"></g>\n+ </g>\n+ <g id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\">\n+ <path d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <g id=\"path62\"></g>\n+ </g>\n+ <g id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\">\n+ <path d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path70\"></g>\n+ </g>\n+ <g id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\">\n+ <path d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <path d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\">\n+ <path d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\">\n+ <path d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+</svg>\n\\ No newline at end of file\n","new_path":"files/images/wm.svg","old_path":"files/images/wm.svg","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":7,"utf8_diff":"--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n","new_path":"files/lfs/lfs_object.iso","old_path":"files/lfs/lfs_object.iso","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":8,"utf8_diff":"--- a/files/ruby/popen.rb\n+++ b/files/ruby/popen.rb\n@@ -6,12 +6,18 @@ module Popen\n \n def popen(cmd, path=nil)\n unless cmd.is_a?(Array)\n- raise \"System commands must be given as an array of strings\"\n+ raise RuntimeError, \"System commands must be given as an array of strings\"\n end\n \n path ||= Dir.pwd\n- vars = { \"PWD\" => path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" => path\n+ }\n+\n+ options = {\n+ chdir: path\n+ }\n \n unless File.directory?(path)\n FileUtils.mkdir_p(path)\n@@ -19,6 +25,7 @@ module Popen\n \n @cmd_output = \"\"\n @cmd_status = 0\n+\n Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|\n @cmd_output << stdout.read\n @cmd_output << stderr.read\n","new_path":"files/ruby/popen.rb","old_path":"files/ruby/popen.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":9,"utf8_diff":"--- a/files/ruby/regex.rb\n+++ b/files/ruby/regex.rb\n@@ -19,14 +19,12 @@ module Gitlab\n end\n \n def archive_formats_regex\n- #|zip|tar| tar.gz | tar.bz2 |\n- /(zip|tar|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n+ /(zip|tar|7z|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n end\n \n def git_reference_regex\n # Valid git ref regex, see:\n # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html\n-\n %r{\n (?!\n (?# doesn't begins with)\n","new_path":"files/ruby/regex.rb","old_path":"files/ruby/regex.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":10,"utf8_diff":"--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n","new_path":"files/whitespace","old_path":"files/whitespace","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":11,"utf8_diff":"--- /dev/null\n+++ b/foo/bar/.gitkeep\n","new_path":"foo/bar/.gitkeep","old_path":"foo/bar/.gitkeep","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":12,"utf8_diff":"--- /dev/null\n+++ b/gitlab-grack\n@@ -0,0 +1 @@\n+Subproject commit 645f6c4c82fd3f5e06f67134450a570b795e55a6\n","new_path":"gitlab-grack","old_path":"gitlab-grack","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":13,"utf8_diff":"--- /dev/null\n+++ b/gitlab-shell\n@@ -0,0 +1 @@\n+Subproject commit 79bceae69cb5750d6567b223597999bfa91cb3b9\n","new_path":"gitlab-shell","old_path":"gitlab-shell","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":14,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":14,"created_at":"2016-06-14T15:02:24.770Z","updated_at":"2016-06-14T15:02:25.007Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"15"},"events":[{"id":224,"target_type":"MergeRequest","target_id":14,"project_id":36,"created_at":"2016-06-14T15:02:25.113Z","updated_at":"2016-06-14T15:02:25.113Z","action":1,"author_id":1},{"id":174,"target_type":"MergeRequest","target_id":14,"project_id":5,"created_at":"2016-06-14T15:02:25.113Z","updated_at":"2016-06-14T15:02:25.113Z","action":1,"author_id":20}]}
+{"id":13,"target_branch":"improve/awesome","source_branch":"test-8","source_project_id":5,"author_id":16,"assignee_id":25,"title":"Voluptates consequatur eius nemo amet libero animi illum delectus tempore.","created_at":"2016-06-14T15:02:24.415Z","updated_at":"2016-06-14T15:02:59.958Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":5,"description":"Est eaque quasi qui qui. Similique voluptatem impedit iusto ratione reprehenderit. Itaque est illum ut nulla aut.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":793,"note":"In illum maxime aperiam nulla est aspernatur.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:59.782Z","updated_at":"2016-06-14T15:02:59.782Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[{"merge_request_diff_id":14,"id":529,"target_type":"Note","target_id":793,"project_id":4,"created_at":"2016-07-07T14:35:12.128Z","updated_at":"2016-07-07T14:35:12.128Z","action":6,"author_id":1}]},{"id":794,"note":"Enim quia perferendis cum distinctio tenetur optio voluptas veniam.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:59.807Z","updated_at":"2016-06-14T15:02:59.807Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":795,"note":"Dolor ad quia quis pariatur ducimus.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:59.831Z","updated_at":"2016-06-14T15:02:59.831Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":796,"note":"Et a odio voluptate aut.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:59.854Z","updated_at":"2016-06-14T15:02:59.854Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":797,"note":"Quis nihil temporibus voluptatum modi minima a ut.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:59.879Z","updated_at":"2016-06-14T15:02:59.879Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":798,"note":"Ut alias consequatur in nostrum.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:59.904Z","updated_at":"2016-06-14T15:02:59.904Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":799,"note":"Voluptatibus aperiam assumenda et neque sint libero.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:59.926Z","updated_at":"2016-06-14T15:02:59.926Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":800,"note":"Veritatis voluptatem dolor dolores magni quo ut ipsa fuga.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:59.956Z","updated_at":"2016-06-14T15:02:59.956Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":13,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":13,"relative_order":0,"sha":"0bfedc29d30280c7e8564e19f654584b459e5868","message":"fixes #10\n","authored_date":"2016-01-19T15:25:23.000+01:00","committed_date":"2016-01-19T15:25:23.000+01:00","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}},{"merge_request_diff_id":13,"relative_order":1,"sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","message":"Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6","authored_date":"2015-12-07T12:52:12.000+01:00","committed_date":"2015-12-07T12:52:12.000+01:00","commit_author":{"name":"Marin Jankovski","email":"marin@gitlab.com"},"committer":{"name":"Marin Jankovski","email":"marin@gitlab.com"}},{"merge_request_diff_id":13,"relative_order":2,"sha":"048721d90c449b244b7b4c53a9186b04330174ec","message":"LFS object pointer.\n","authored_date":"2015-12-07T11:54:28.000+01:00","committed_date":"2015-12-07T11:54:28.000+01:00","commit_author":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"},"committer":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"}},{"merge_request_diff_id":13,"relative_order":3,"sha":"5f923865dde3436854e9ceb9cdb7815618d4e849","message":"GitLab currently doesn't support patches that involve a merge commit: add a commit here\n","authored_date":"2015-11-13T16:27:12.000+01:00","committed_date":"2015-11-13T16:27:12.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":4,"sha":"d2d430676773caa88cdaf7c55944073b2fd5561a","message":"Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5","authored_date":"2015-11-13T08:50:17.000+01:00","committed_date":"2015-11-13T08:50:17.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":5,"sha":"2ea1f3dec713d940208fb5ce4a38765ecb5d3f73","message":"Add GitLab SVG\n","authored_date":"2015-11-13T08:39:43.000+01:00","committed_date":"2015-11-13T08:39:43.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":6,"sha":"59e29889be61e6e0e5e223bfa9ac2721d31605b8","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4","authored_date":"2015-11-13T07:21:40.000+01:00","committed_date":"2015-11-13T07:21:40.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":7,"sha":"66eceea0db202bb39c4e445e8ca28689645366c5","message":"add spaces in whitespace file\n","authored_date":"2015-11-13T06:01:27.000+01:00","committed_date":"2015-11-13T06:01:27.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":13,"relative_order":8,"sha":"08f22f255f082689c0d7d39d19205085311542bc","message":"remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n","authored_date":"2015-11-13T06:00:16.000+01:00","committed_date":"2015-11-13T06:00:16.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":13,"relative_order":9,"sha":"19e2e9b4ef76b422ce1154af39a91323ccc57434","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3","authored_date":"2015-11-13T05:23:14.000+01:00","committed_date":"2015-11-13T05:23:14.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":10,"sha":"c642fe9b8b9f28f9225d7ea953fe14e74748d53b","message":"add whitespace in empty\n","authored_date":"2015-11-13T05:08:45.000+01:00","committed_date":"2015-11-13T05:08:45.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":13,"relative_order":11,"sha":"9a944d90955aaf45f6d0c88f30e27f8d2c41cec0","message":"add empty file\n","authored_date":"2015-11-13T05:08:04.000+01:00","committed_date":"2015-11-13T05:08:04.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":13,"relative_order":12,"sha":"c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd","message":"Add ISO-8859 test file\n","authored_date":"2015-08-25T17:53:12.000+02:00","committed_date":"2015-08-25T17:53:12.000+02:00","commit_author":{"name":"Stan Hu","email":"stanhu@packetzoom.com"},"committer":{"name":"Stan Hu","email":"stanhu@packetzoom.com"}},{"merge_request_diff_id":13,"relative_order":13,"sha":"e56497bb5f03a90a51293fc6d516788730953899","message":"Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/275#note_732774)\n\nSee merge request !2\n","authored_date":"2015-01-10T22:23:29.000+01:00","committed_date":"2015-01-10T22:23:29.000+01:00","commit_author":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"},"committer":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"}},{"merge_request_diff_id":13,"relative_order":14,"sha":"4cd80ccab63c82b4bad16faa5193fbd2aa06df40","message":"add directory structure for tree_helper spec\n","authored_date":"2015-01-10T21:28:18.000+01:00","committed_date":"2015-01-10T21:28:18.000+01:00","commit_author":{"name":"marmis85","email":"marmis85@gmail.com"},"committer":{"name":"marmis85","email":"marmis85@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":13,"relative_order":0,"utf8_diff":"--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n","new_path":"CHANGELOG","old_path":"CHANGELOG","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":1,"utf8_diff":"--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n","new_path":"encoding/iso8859.txt","old_path":"encoding/iso8859.txt","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":2,"utf8_diff":"--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n+<svg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n+ <!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->\n+ <title>wm</title>\n+ <desc>Created with Sketch.</desc>\n+ <defs>\n+ <path id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"></path>\n+ </defs>\n+ <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n+ <path d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\">\n+ <g id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\">\n+ <g id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\">\n+ <path d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"></path>\n+ </g>\n+ <g id=\"g16\">\n+ <g id=\"g18-Clipped\">\n+ <mask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\">\n+ <use xlink:href=\"#path-1\"></use>\n+ </mask>\n+ <g id=\"path22\"></g>\n+ <g id=\"g18\" mask=\"url(#mask-2)\">\n+ <g transform=\"translate(382.736659, 312.879425)\">\n+ <g id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\">\n+ <path d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\">\n+ <path d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\">\n+ <path d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\">\n+ <path d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <path d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <path d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\">\n+ <path d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\">\n+ <path d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path54\"></g>\n+ </g>\n+ <g id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\">\n+ <path d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <g id=\"path62\"></g>\n+ </g>\n+ <g id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\">\n+ <path d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path70\"></g>\n+ </g>\n+ <g id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\">\n+ <path d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <path d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\">\n+ <path d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\">\n+ <path d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+</svg>\n\\ No newline at end of file\n","new_path":"files/images/wm.svg","old_path":"files/images/wm.svg","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":3,"utf8_diff":"--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n","new_path":"files/lfs/lfs_object.iso","old_path":"files/lfs/lfs_object.iso","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n","new_path":"files/whitespace","old_path":"files/whitespace","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":5,"utf8_diff":"--- /dev/null\n+++ b/foo/bar/.gitkeep\n","new_path":"foo/bar/.gitkeep","old_path":"foo/bar/.gitkeep","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":6,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":13,"created_at":"2016-06-14T15:02:24.420Z","updated_at":"2016-06-14T15:02:24.561Z","base_commit_sha":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","real_size":"7"},"events":[{"id":225,"target_type":"MergeRequest","target_id":13,"project_id":36,"created_at":"2016-06-14T15:02:24.636Z","updated_at":"2016-06-14T15:02:24.636Z","action":1,"author_id":16},{"id":173,"target_type":"MergeRequest","target_id":13,"project_id":5,"created_at":"2016-06-14T15:02:24.636Z","updated_at":"2016-06-14T15:02:24.636Z","action":1,"author_id":16}]}
+{"id":12,"target_branch":"flatten-dirs","source_branch":"test-2","source_project_id":5,"author_id":1,"assignee_id":22,"title":"In a rerum harum nihil accusamus aut quia nobis non.","created_at":"2016-06-14T15:02:24.000Z","updated_at":"2016-06-14T15:03:00.225Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":4,"description":"Nam magnam odit velit rerum. Sapiente dolore sunt saepe debitis. Culpa maiores ut ad dolores dolorem et.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":801,"note":"Nihil dicta molestias expedita atque.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:03:00.001Z","updated_at":"2016-06-14T15:03:00.001Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":802,"note":"Illum culpa voluptas enim accusantium deserunt.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:03:00.034Z","updated_at":"2016-06-14T15:03:00.034Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":803,"note":"Dicta esse aliquam laboriosam unde alias.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:03:00.065Z","updated_at":"2016-06-14T15:03:00.065Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":804,"note":"Dicta autem et sed molestiae ut quae.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:03:00.097Z","updated_at":"2016-06-14T15:03:00.097Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":805,"note":"Ut ut temporibus voluptas dolore quia velit.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:03:00.129Z","updated_at":"2016-06-14T15:03:00.129Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":806,"note":"Dolores similique sint pariatur error id quia fugit aut.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:03:00.162Z","updated_at":"2016-06-14T15:03:00.162Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":807,"note":"Quisquam provident nihil aperiam voluptatem.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:03:00.193Z","updated_at":"2016-06-14T15:03:00.193Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":808,"note":"Similique quo vero expedita deserunt ipsam earum.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:03:00.224Z","updated_at":"2016-06-14T15:03:00.224Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":12,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":12,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":12,"relative_order":0,"sha":"97a0df9696e2aebf10c31b3016f40214e0e8f243","message":"fixes #10\n","authored_date":"2016-01-19T14:08:21.000+01:00","committed_date":"2016-01-19T14:08:21.000+01:00","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}},{"merge_request_diff_id":12,"relative_order":1,"sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","message":"Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6","authored_date":"2015-12-07T12:52:12.000+01:00","committed_date":"2015-12-07T12:52:12.000+01:00","commit_author":{"name":"Marin Jankovski","email":"marin@gitlab.com"},"committer":{"name":"Marin Jankovski","email":"marin@gitlab.com"}},{"merge_request_diff_id":12,"relative_order":2,"sha":"048721d90c449b244b7b4c53a9186b04330174ec","message":"LFS object pointer.\n","authored_date":"2015-12-07T11:54:28.000+01:00","committed_date":"2015-12-07T11:54:28.000+01:00","commit_author":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"},"committer":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"}},{"merge_request_diff_id":12,"relative_order":3,"sha":"5f923865dde3436854e9ceb9cdb7815618d4e849","message":"GitLab currently doesn't support patches that involve a merge commit: add a commit here\n","authored_date":"2015-11-13T16:27:12.000+01:00","committed_date":"2015-11-13T16:27:12.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":12,"relative_order":4,"sha":"d2d430676773caa88cdaf7c55944073b2fd5561a","message":"Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5","authored_date":"2015-11-13T08:50:17.000+01:00","committed_date":"2015-11-13T08:50:17.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":12,"relative_order":5,"sha":"2ea1f3dec713d940208fb5ce4a38765ecb5d3f73","message":"Add GitLab SVG\n","authored_date":"2015-11-13T08:39:43.000+01:00","committed_date":"2015-11-13T08:39:43.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":12,"relative_order":6,"sha":"59e29889be61e6e0e5e223bfa9ac2721d31605b8","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4","authored_date":"2015-11-13T07:21:40.000+01:00","committed_date":"2015-11-13T07:21:40.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":12,"relative_order":7,"sha":"66eceea0db202bb39c4e445e8ca28689645366c5","message":"add spaces in whitespace file\n","authored_date":"2015-11-13T06:01:27.000+01:00","committed_date":"2015-11-13T06:01:27.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":12,"relative_order":8,"sha":"08f22f255f082689c0d7d39d19205085311542bc","message":"remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n","authored_date":"2015-11-13T06:00:16.000+01:00","committed_date":"2015-11-13T06:00:16.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":12,"relative_order":9,"sha":"19e2e9b4ef76b422ce1154af39a91323ccc57434","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3","authored_date":"2015-11-13T05:23:14.000+01:00","committed_date":"2015-11-13T05:23:14.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":12,"relative_order":10,"sha":"c642fe9b8b9f28f9225d7ea953fe14e74748d53b","message":"add whitespace in empty\n","authored_date":"2015-11-13T05:08:45.000+01:00","committed_date":"2015-11-13T05:08:45.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":12,"relative_order":11,"sha":"9a944d90955aaf45f6d0c88f30e27f8d2c41cec0","message":"add empty file\n","authored_date":"2015-11-13T05:08:04.000+01:00","committed_date":"2015-11-13T05:08:04.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":12,"relative_order":12,"sha":"c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd","message":"Add ISO-8859 test file\n","authored_date":"2015-08-25T17:53:12.000+02:00","committed_date":"2015-08-25T17:53:12.000+02:00","commit_author":{"name":"Stan Hu","email":"stanhu@packetzoom.com"},"committer":{"name":"Stan Hu","email":"stanhu@packetzoom.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":12,"relative_order":0,"utf8_diff":"--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n","new_path":"CHANGELOG","old_path":"CHANGELOG","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":12,"relative_order":1,"utf8_diff":"--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n","new_path":"encoding/iso8859.txt","old_path":"encoding/iso8859.txt","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":12,"relative_order":2,"utf8_diff":"--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n+<svg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n+ <!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->\n+ <title>wm</title>\n+ <desc>Created with Sketch.</desc>\n+ <defs>\n+ <path id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"></path>\n+ </defs>\n+ <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n+ <path d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\">\n+ <g id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\">\n+ <g id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\">\n+ <path d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"></path>\n+ </g>\n+ <g id=\"g16\">\n+ <g id=\"g18-Clipped\">\n+ <mask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\">\n+ <use xlink:href=\"#path-1\"></use>\n+ </mask>\n+ <g id=\"path22\"></g>\n+ <g id=\"g18\" mask=\"url(#mask-2)\">\n+ <g transform=\"translate(382.736659, 312.879425)\">\n+ <g id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\">\n+ <path d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\">\n+ <path d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\">\n+ <path d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\">\n+ <path d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <path d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <path d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\">\n+ <path d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\">\n+ <path d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path54\"></g>\n+ </g>\n+ <g id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\">\n+ <path d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <g id=\"path62\"></g>\n+ </g>\n+ <g id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\">\n+ <path d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path70\"></g>\n+ </g>\n+ <g id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\">\n+ <path d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <path d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\">\n+ <path d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\">\n+ <path d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+</svg>\n\\ No newline at end of file\n","new_path":"files/images/wm.svg","old_path":"files/images/wm.svg","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":12,"relative_order":3,"utf8_diff":"--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n","new_path":"files/lfs/lfs_object.iso","old_path":"files/lfs/lfs_object.iso","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":12,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n","new_path":"files/whitespace","old_path":"files/whitespace","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":12,"relative_order":5,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":12,"created_at":"2016-06-14T15:02:24.006Z","updated_at":"2016-06-14T15:02:24.169Z","base_commit_sha":"e56497bb5f03a90a51293fc6d516788730953899","real_size":"6"},"events":[{"id":226,"target_type":"MergeRequest","target_id":12,"project_id":36,"created_at":"2016-06-14T15:02:24.253Z","updated_at":"2016-06-14T15:02:24.253Z","action":1,"author_id":1},{"id":172,"target_type":"MergeRequest","target_id":12,"project_id":5,"created_at":"2016-06-14T15:02:24.253Z","updated_at":"2016-06-14T15:02:24.253Z","action":1,"author_id":1}]}
{"id":11,"target_branch":"test-15","source_branch":"'test'","source_project_id":5,"author_id":16,"assignee_id":16,"title":"Corporis provident similique perspiciatis dolores eos animi.","created_at":"2016-06-14T15:02:23.767Z","updated_at":"2016-06-14T15:03:00.475Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":3,"description":"Libero nesciunt mollitia quis odit eos vero quasi. Iure voluptatem ut sint pariatur voluptates ut aut. Laborum possimus unde illum ipsum eum.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":809,"note":"Omnis ratione laboriosam dolores qui.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:03:00.260Z","updated_at":"2016-06-14T15:03:00.260Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":11,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":810,"note":"Voluptas voluptates pariatur dolores maxime est voluptas.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:03:00.290Z","updated_at":"2016-06-14T15:03:00.290Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":11,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":811,"note":"Sit perspiciatis facilis ipsum consequatur.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:03:00.323Z","updated_at":"2016-06-14T15:03:00.323Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":11,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":812,"note":"Ut neque aliquam nam et est.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:03:00.349Z","updated_at":"2016-06-14T15:03:00.349Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":11,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":813,"note":"Et debitis rerum minima sit aut dolorem.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:03:00.374Z","updated_at":"2016-06-14T15:03:00.374Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":11,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":814,"note":"Ea nisi earum fugit iste aperiam consequatur.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:03:00.397Z","updated_at":"2016-06-14T15:03:00.397Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":11,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":815,"note":"Amet ratione consequatur laudantium rerum voluptas est nobis.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:03:00.450Z","updated_at":"2016-06-14T15:03:00.450Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":11,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":816,"note":"Ab ducimus cumque quia dolorem vitae sint beatae rerum.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:03:00.474Z","updated_at":"2016-06-14T15:03:00.474Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":11,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":11,"state":"empty","merge_request_diff_commits":[],"merge_request_diff_files":[],"merge_request_id":11,"created_at":"2016-06-14T15:02:23.772Z","updated_at":"2016-06-14T15:02:23.833Z","base_commit_sha":"e56497bb5f03a90a51293fc6d516788730953899","real_size":null},"events":[{"id":227,"target_type":"MergeRequest","target_id":11,"project_id":36,"created_at":"2016-06-14T15:02:23.865Z","updated_at":"2016-06-14T15:02:23.865Z","action":1,"author_id":16},{"id":171,"target_type":"MergeRequest","target_id":11,"project_id":5,"created_at":"2016-06-14T15:02:23.865Z","updated_at":"2016-06-14T15:02:23.865Z","action":1,"author_id":16}]}
-{"id":10,"target_branch":"feature","source_branch":"test-5","source_project_id":5,"author_id":20,"assignee_id":25,"title":"Eligendi reprehenderit doloribus quia et sit id.","created_at":"2016-06-14T15:02:23.014Z","updated_at":"2016-06-14T15:03:00.685Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":2,"description":"Ut dolor quia aliquid dolore et nisi. Est minus suscipit enim quaerat sapiente consequatur rerum. Eveniet provident consequatur dolor accusantium reiciendis.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":817,"note":"Recusandae et voluptas enim qui et.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:03:00.510Z","updated_at":"2016-06-14T15:03:00.510Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":818,"note":"Asperiores dolorem rerum ipsum totam.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:03:00.538Z","updated_at":"2016-06-14T15:03:00.538Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":819,"note":"Qui quam et iure quasi provident cumque itaque sequi.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:03:00.562Z","updated_at":"2016-06-14T15:03:00.562Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":820,"note":"Sint accusantium aliquid iste qui iusto minus vel.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:03:00.585Z","updated_at":"2016-06-14T15:03:00.585Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":821,"note":"Dolor corrupti dolorem blanditiis voluptas.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:03:00.610Z","updated_at":"2016-06-14T15:03:00.610Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":822,"note":"Est perferendis assumenda aliquam aliquid sit ipsum ullam aut.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:03:00.635Z","updated_at":"2016-06-14T15:03:00.635Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":823,"note":"Hic neque reiciendis quaerat maiores.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:03:00.659Z","updated_at":"2016-06-14T15:03:00.659Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":824,"note":"Sequi architecto doloribus ut vel autem.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:03:00.683Z","updated_at":"2016-06-14T15:03:00.683Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":10,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":10,"relative_order":0,"sha":"f998ac87ac9244f15e9c15109a6f4e62a54b779d","message":"fixes #10\n","authored_date":"2016-01-19T14:43:23.000+01:00","author_name":"James Lopez","author_email":"james@jameslopez.es","committed_date":"2016-01-19T14:43:23.000+01:00","committer_name":"James Lopez","committer_email":"james@jameslopez.es","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}},{"merge_request_diff_id":10,"relative_order":1,"sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","message":"Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6","authored_date":"2015-12-07T12:52:12.000+01:00","author_name":"Marin Jankovski","author_email":"marin@gitlab.com","committed_date":"2015-12-07T12:52:12.000+01:00","committer_name":"Marin Jankovski","committer_email":"marin@gitlab.com","commit_author":{"name":"Marin Jankovski","email":"marin@gitlab.com"},"committer":{"name":"Marin Jankovski","email":"marin@gitlab.com"}},{"merge_request_diff_id":10,"relative_order":2,"sha":"048721d90c449b244b7b4c53a9186b04330174ec","message":"LFS object pointer.\n","authored_date":"2015-12-07T11:54:28.000+01:00","author_name":"Marin Jankovski","author_email":"maxlazio@gmail.com","committed_date":"2015-12-07T11:54:28.000+01:00","committer_name":"Marin Jankovski","committer_email":"maxlazio@gmail.com","commit_author":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"},"committer":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"}},{"merge_request_diff_id":10,"relative_order":3,"sha":"5f923865dde3436854e9ceb9cdb7815618d4e849","message":"GitLab currently doesn't support patches that involve a merge commit: add a commit here\n","authored_date":"2015-11-13T16:27:12.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T16:27:12.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":10,"relative_order":4,"sha":"d2d430676773caa88cdaf7c55944073b2fd5561a","message":"Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5","authored_date":"2015-11-13T08:50:17.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T08:50:17.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":10,"relative_order":5,"sha":"2ea1f3dec713d940208fb5ce4a38765ecb5d3f73","message":"Add GitLab SVG\n","authored_date":"2015-11-13T08:39:43.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T08:39:43.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":10,"relative_order":6,"sha":"59e29889be61e6e0e5e223bfa9ac2721d31605b8","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4","authored_date":"2015-11-13T07:21:40.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T07:21:40.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":10,"relative_order":7,"sha":"66eceea0db202bb39c4e445e8ca28689645366c5","message":"add spaces in whitespace file\n","authored_date":"2015-11-13T06:01:27.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T06:01:27.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":10,"relative_order":8,"sha":"08f22f255f082689c0d7d39d19205085311542bc","message":"remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n","authored_date":"2015-11-13T06:00:16.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T06:00:16.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":10,"relative_order":9,"sha":"19e2e9b4ef76b422ce1154af39a91323ccc57434","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3","authored_date":"2015-11-13T05:23:14.000+01:00","author_name":"Stan Hu","author_email":"stanhu@gmail.com","committed_date":"2015-11-13T05:23:14.000+01:00","committer_name":"Stan Hu","committer_email":"stanhu@gmail.com","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":10,"relative_order":10,"sha":"c642fe9b8b9f28f9225d7ea953fe14e74748d53b","message":"add whitespace in empty\n","authored_date":"2015-11-13T05:08:45.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T05:08:45.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":10,"relative_order":11,"sha":"9a944d90955aaf45f6d0c88f30e27f8d2c41cec0","message":"add empty file\n","authored_date":"2015-11-13T05:08:04.000+01:00","author_name":"윤민ì‹","author_email":"minsik.yoon@samsung.com","committed_date":"2015-11-13T05:08:04.000+01:00","committer_name":"윤민ì‹","committer_email":"minsik.yoon@samsung.com","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":10,"relative_order":12,"sha":"c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd","message":"Add ISO-8859 test file\n","authored_date":"2015-08-25T17:53:12.000+02:00","author_name":"Stan Hu","author_email":"stanhu@packetzoom.com","committed_date":"2015-08-25T17:53:12.000+02:00","committer_name":"Stan Hu","committer_email":"stanhu@packetzoom.com","commit_author":{"name":"Stan Hu","email":"stanhu@packetzoom.com"},"committer":{"name":"Stan Hu","email":"stanhu@packetzoom.com"}},{"merge_request_diff_id":10,"relative_order":13,"sha":"e56497bb5f03a90a51293fc6d516788730953899","message":"Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/275#note_732774)\n\nSee merge request !2\n","authored_date":"2015-01-10T22:23:29.000+01:00","author_name":"Sytse Sijbrandij","author_email":"sytse@gitlab.com","committed_date":"2015-01-10T22:23:29.000+01:00","committer_name":"Sytse Sijbrandij","committer_email":"sytse@gitlab.com","commit_author":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"},"committer":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"}},{"merge_request_diff_id":10,"relative_order":14,"sha":"4cd80ccab63c82b4bad16faa5193fbd2aa06df40","message":"add directory structure for tree_helper spec\n","authored_date":"2015-01-10T21:28:18.000+01:00","author_name":"marmis85","author_email":"marmis85@gmail.com","committed_date":"2015-01-10T21:28:18.000+01:00","committer_name":"marmis85","committer_email":"marmis85@gmail.com","commit_author":{"name":"marmis85","email":"marmis85@gmail.com"},"committer":{"name":"marmis85","email":"marmis85@gmail.com"}},{"merge_request_diff_id":10,"relative_order":16,"sha":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","message":"Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T10:01:38.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T10:01:38.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":10,"relative_order":17,"sha":"570e7b2abdd848b95f2f578043fc23bd6f6fd24d","message":"Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:57:31.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:57:31.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":10,"relative_order":18,"sha":"6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9","message":"More submodules\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:54:21.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:54:21.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":10,"relative_order":19,"sha":"d14d6c0abdd253381df51a723d58691b2ee1ab08","message":"Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:49:50.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:49:50.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":10,"relative_order":20,"sha":"c1acaa58bbcbc3eafe538cb8274ba387047b69f8","message":"Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:48:32.000+01:00","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","committed_date":"2014-02-27T09:48:32.000+01:00","committer_name":"Dmitriy Zaporozhets","committer_email":"dmitriy.zaporozhets@gmail.com","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":10,"relative_order":0,"utf8_diff":"Binary files a/.DS_Store and /dev/null differ\n","new_path":".DS_Store","old_path":".DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":10,"relative_order":1,"utf8_diff":"--- a/.gitignore\n+++ b/.gitignore\n@@ -17,3 +17,4 @@ rerun.txt\n pickle-email-*.html\n .project\n config/initializers/secret_token.rb\n+.DS_Store\n","new_path":".gitignore","old_path":".gitignore","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":2,"utf8_diff":"--- a/.gitmodules\n+++ b/.gitmodules\n@@ -1,3 +1,9 @@\n [submodule \"six\"]\n \tpath = six\n \turl = git://github.com/randx/six.git\n+[submodule \"gitlab-shell\"]\n+\tpath = gitlab-shell\n+\turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n","new_path":".gitmodules","old_path":".gitmodules","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":3,"utf8_diff":"--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n","new_path":"CHANGELOG","old_path":"CHANGELOG","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n","new_path":"encoding/iso8859.txt","old_path":"encoding/iso8859.txt","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":5,"utf8_diff":"Binary files a/files/.DS_Store and /dev/null differ\n","new_path":"files/.DS_Store","old_path":"files/.DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":10,"relative_order":6,"utf8_diff":"--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n+<svg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n+ <!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->\n+ <title>wm</title>\n+ <desc>Created with Sketch.</desc>\n+ <defs>\n+ <path id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"></path>\n+ </defs>\n+ <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n+ <path d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\">\n+ <g id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\">\n+ <g id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\">\n+ <path d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"></path>\n+ </g>\n+ <g id=\"g16\">\n+ <g id=\"g18-Clipped\">\n+ <mask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\">\n+ <use xlink:href=\"#path-1\"></use>\n+ </mask>\n+ <g id=\"path22\"></g>\n+ <g id=\"g18\" mask=\"url(#mask-2)\">\n+ <g transform=\"translate(382.736659, 312.879425)\">\n+ <g id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\">\n+ <path d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\">\n+ <path d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\">\n+ <path d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\">\n+ <path d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <path d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <path d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\">\n+ <path d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\">\n+ <path d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path54\"></g>\n+ </g>\n+ <g id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\">\n+ <path d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <g id=\"path62\"></g>\n+ </g>\n+ <g id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\">\n+ <path d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path70\"></g>\n+ </g>\n+ <g id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\">\n+ <path d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <path d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\">\n+ <path d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\">\n+ <path d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+</svg>\n\\ No newline at end of file\n","new_path":"files/images/wm.svg","old_path":"files/images/wm.svg","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":7,"utf8_diff":"--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n","new_path":"files/lfs/lfs_object.iso","old_path":"files/lfs/lfs_object.iso","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":8,"utf8_diff":"--- a/files/ruby/popen.rb\n+++ b/files/ruby/popen.rb\n@@ -6,12 +6,18 @@ module Popen\n \n def popen(cmd, path=nil)\n unless cmd.is_a?(Array)\n- raise \"System commands must be given as an array of strings\"\n+ raise RuntimeError, \"System commands must be given as an array of strings\"\n end\n \n path ||= Dir.pwd\n- vars = { \"PWD\" => path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" => path\n+ }\n+\n+ options = {\n+ chdir: path\n+ }\n \n unless File.directory?(path)\n FileUtils.mkdir_p(path)\n@@ -19,6 +25,7 @@ module Popen\n \n @cmd_output = \"\"\n @cmd_status = 0\n+\n Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|\n @cmd_output << stdout.read\n @cmd_output << stderr.read\n","new_path":"files/ruby/popen.rb","old_path":"files/ruby/popen.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":9,"utf8_diff":"--- a/files/ruby/regex.rb\n+++ b/files/ruby/regex.rb\n@@ -19,14 +19,12 @@ module Gitlab\n end\n \n def archive_formats_regex\n- #|zip|tar| tar.gz | tar.bz2 |\n- /(zip|tar|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n+ /(zip|tar|7z|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n end\n \n def git_reference_regex\n # Valid git ref regex, see:\n # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html\n-\n %r{\n (?!\n (?# doesn't begins with)\n","new_path":"files/ruby/regex.rb","old_path":"files/ruby/regex.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":10,"utf8_diff":"--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n","new_path":"files/whitespace","old_path":"files/whitespace","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":11,"utf8_diff":"--- /dev/null\n+++ b/foo/bar/.gitkeep\n","new_path":"foo/bar/.gitkeep","old_path":"foo/bar/.gitkeep","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":12,"utf8_diff":"--- /dev/null\n+++ b/gitlab-grack\n@@ -0,0 +1 @@\n+Subproject commit 645f6c4c82fd3f5e06f67134450a570b795e55a6\n","new_path":"gitlab-grack","old_path":"gitlab-grack","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":13,"utf8_diff":"--- /dev/null\n+++ b/gitlab-shell\n@@ -0,0 +1 @@\n+Subproject commit 79bceae69cb5750d6567b223597999bfa91cb3b9\n","new_path":"gitlab-shell","old_path":"gitlab-shell","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":14,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":10,"created_at":"2016-06-14T15:02:23.019Z","updated_at":"2016-06-14T15:02:23.493Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"15"},"events":[{"id":228,"target_type":"MergeRequest","target_id":10,"project_id":36,"created_at":"2016-06-14T15:02:23.660Z","updated_at":"2016-06-14T15:02:23.660Z","action":1,"author_id":1},{"id":170,"target_type":"MergeRequest","target_id":10,"project_id":5,"created_at":"2016-06-14T15:02:23.660Z","updated_at":"2016-06-14T15:02:23.660Z","action":1,"author_id":20}]}
-{"id":9,"target_branch":"test-6","source_branch":"test-12","source_project_id":5,"author_id":16,"assignee_id":6,"title":"Et ipsam voluptas velit sequi illum ut.","created_at":"2016-06-14T15:02:22.825Z","updated_at":"2016-06-14T15:03:00.904Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":1,"description":"Eveniet nihil ratione veniam similique qui aut sapiente tempora. Sed praesentium iusto dignissimos possimus id repudiandae quo nihil. Qui doloremque autem et iure fugit.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":825,"note":"Aliquid voluptatem consequatur voluptas ex perspiciatis.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:03:00.722Z","updated_at":"2016-06-14T15:03:00.722Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":826,"note":"Itaque optio voluptatem praesentium voluptas.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:03:00.745Z","updated_at":"2016-06-14T15:03:00.745Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":827,"note":"Ut est corporis fuga asperiores delectus excepturi aperiam.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:03:00.771Z","updated_at":"2016-06-14T15:03:00.771Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":828,"note":"Similique ea dolore officiis temporibus.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:03:00.798Z","updated_at":"2016-06-14T15:03:00.798Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":829,"note":"Qui laudantium qui quae quis.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:03:00.828Z","updated_at":"2016-06-14T15:03:00.828Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":830,"note":"Et vel voluptas amet laborum qui soluta.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:03:00.850Z","updated_at":"2016-06-14T15:03:00.850Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":831,"note":"Enim ad consequuntur assumenda provident voluptatem similique deleniti.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:03:00.876Z","updated_at":"2016-06-14T15:03:00.876Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":832,"note":"Officiis sequi commodi pariatur totam fugiat voluptas corporis dignissimos.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:03:00.902Z","updated_at":"2016-06-14T15:03:00.902Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":9,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":9,"relative_order":0,"sha":"a4e5dfebf42e34596526acb8611bc7ed80e4eb3f","message":"fixes #10\n","authored_date":"2016-01-19T15:44:02.000+01:00","author_name":"James Lopez","author_email":"james@jameslopez.es","committed_date":"2016-01-19T15:44:02.000+01:00","committer_name":"James Lopez","committer_email":"james@jameslopez.es","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}}],"merge_request_diff_files":[{"merge_request_diff_id":9,"relative_order":0,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":9,"created_at":"2016-06-14T15:02:22.829Z","updated_at":"2016-06-14T15:02:22.900Z","base_commit_sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","real_size":"1"},"events":[{"id":229,"target_type":"MergeRequest","target_id":9,"project_id":36,"created_at":"2016-06-14T15:02:22.927Z","updated_at":"2016-06-14T15:02:22.927Z","action":1,"author_id":16},{"id":169,"target_type":"MergeRequest","target_id":9,"project_id":5,"created_at":"2016-06-14T15:02:22.927Z","updated_at":"2016-06-14T15:02:22.927Z","action":1,"author_id":16}]}
+{"id":10,"target_branch":"feature","source_branch":"test-5","source_project_id":5,"author_id":20,"assignee_id":25,"title":"Eligendi reprehenderit doloribus quia et sit id.","created_at":"2016-06-14T15:02:23.014Z","updated_at":"2016-06-14T15:03:00.685Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":2,"description":"Ut dolor quia aliquid dolore et nisi. Est minus suscipit enim quaerat sapiente consequatur rerum. Eveniet provident consequatur dolor accusantium reiciendis.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":817,"note":"Recusandae et voluptas enim qui et.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:03:00.510Z","updated_at":"2016-06-14T15:03:00.510Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":818,"note":"Asperiores dolorem rerum ipsum totam.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:03:00.538Z","updated_at":"2016-06-14T15:03:00.538Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":819,"note":"Qui quam et iure quasi provident cumque itaque sequi.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:03:00.562Z","updated_at":"2016-06-14T15:03:00.562Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":820,"note":"Sint accusantium aliquid iste qui iusto minus vel.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:03:00.585Z","updated_at":"2016-06-14T15:03:00.585Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":821,"note":"Dolor corrupti dolorem blanditiis voluptas.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:03:00.610Z","updated_at":"2016-06-14T15:03:00.610Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":822,"note":"Est perferendis assumenda aliquam aliquid sit ipsum ullam aut.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:03:00.635Z","updated_at":"2016-06-14T15:03:00.635Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":823,"note":"Hic neque reiciendis quaerat maiores.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:03:00.659Z","updated_at":"2016-06-14T15:03:00.659Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":824,"note":"Sequi architecto doloribus ut vel autem.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:03:00.683Z","updated_at":"2016-06-14T15:03:00.683Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":10,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":10,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":10,"relative_order":0,"sha":"f998ac87ac9244f15e9c15109a6f4e62a54b779d","message":"fixes #10\n","authored_date":"2016-01-19T14:43:23.000+01:00","committed_date":"2016-01-19T14:43:23.000+01:00","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}},{"merge_request_diff_id":10,"relative_order":1,"sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","message":"Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6","authored_date":"2015-12-07T12:52:12.000+01:00","committed_date":"2015-12-07T12:52:12.000+01:00","commit_author":{"name":"Marin Jankovski","email":"marin@gitlab.com"},"committer":{"name":"Marin Jankovski","email":"marin@gitlab.com"}},{"merge_request_diff_id":10,"relative_order":2,"sha":"048721d90c449b244b7b4c53a9186b04330174ec","message":"LFS object pointer.\n","authored_date":"2015-12-07T11:54:28.000+01:00","committed_date":"2015-12-07T11:54:28.000+01:00","commit_author":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"},"committer":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"}},{"merge_request_diff_id":10,"relative_order":3,"sha":"5f923865dde3436854e9ceb9cdb7815618d4e849","message":"GitLab currently doesn't support patches that involve a merge commit: add a commit here\n","authored_date":"2015-11-13T16:27:12.000+01:00","committed_date":"2015-11-13T16:27:12.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":10,"relative_order":4,"sha":"d2d430676773caa88cdaf7c55944073b2fd5561a","message":"Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5","authored_date":"2015-11-13T08:50:17.000+01:00","committed_date":"2015-11-13T08:50:17.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":10,"relative_order":5,"sha":"2ea1f3dec713d940208fb5ce4a38765ecb5d3f73","message":"Add GitLab SVG\n","authored_date":"2015-11-13T08:39:43.000+01:00","committed_date":"2015-11-13T08:39:43.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":10,"relative_order":6,"sha":"59e29889be61e6e0e5e223bfa9ac2721d31605b8","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4","authored_date":"2015-11-13T07:21:40.000+01:00","committed_date":"2015-11-13T07:21:40.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":10,"relative_order":7,"sha":"66eceea0db202bb39c4e445e8ca28689645366c5","message":"add spaces in whitespace file\n","authored_date":"2015-11-13T06:01:27.000+01:00","committed_date":"2015-11-13T06:01:27.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":10,"relative_order":8,"sha":"08f22f255f082689c0d7d39d19205085311542bc","message":"remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n","authored_date":"2015-11-13T06:00:16.000+01:00","committed_date":"2015-11-13T06:00:16.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":10,"relative_order":9,"sha":"19e2e9b4ef76b422ce1154af39a91323ccc57434","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3","authored_date":"2015-11-13T05:23:14.000+01:00","committed_date":"2015-11-13T05:23:14.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":10,"relative_order":10,"sha":"c642fe9b8b9f28f9225d7ea953fe14e74748d53b","message":"add whitespace in empty\n","authored_date":"2015-11-13T05:08:45.000+01:00","committed_date":"2015-11-13T05:08:45.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":10,"relative_order":11,"sha":"9a944d90955aaf45f6d0c88f30e27f8d2c41cec0","message":"add empty file\n","authored_date":"2015-11-13T05:08:04.000+01:00","committed_date":"2015-11-13T05:08:04.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":10,"relative_order":12,"sha":"c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd","message":"Add ISO-8859 test file\n","authored_date":"2015-08-25T17:53:12.000+02:00","committed_date":"2015-08-25T17:53:12.000+02:00","commit_author":{"name":"Stan Hu","email":"stanhu@packetzoom.com"},"committer":{"name":"Stan Hu","email":"stanhu@packetzoom.com"}},{"merge_request_diff_id":10,"relative_order":13,"sha":"e56497bb5f03a90a51293fc6d516788730953899","message":"Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/275#note_732774)\n\nSee merge request !2\n","authored_date":"2015-01-10T22:23:29.000+01:00","committed_date":"2015-01-10T22:23:29.000+01:00","commit_author":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"},"committer":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"}},{"merge_request_diff_id":10,"relative_order":14,"sha":"4cd80ccab63c82b4bad16faa5193fbd2aa06df40","message":"add directory structure for tree_helper spec\n","authored_date":"2015-01-10T21:28:18.000+01:00","committed_date":"2015-01-10T21:28:18.000+01:00","commit_author":{"name":"marmis85","email":"marmis85@gmail.com"},"committer":{"name":"marmis85","email":"marmis85@gmail.com"}},{"merge_request_diff_id":10,"relative_order":16,"sha":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","message":"Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T10:01:38.000+01:00","committed_date":"2014-02-27T10:01:38.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":10,"relative_order":17,"sha":"570e7b2abdd848b95f2f578043fc23bd6f6fd24d","message":"Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:57:31.000+01:00","committed_date":"2014-02-27T09:57:31.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":10,"relative_order":18,"sha":"6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9","message":"More submodules\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:54:21.000+01:00","committed_date":"2014-02-27T09:54:21.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":10,"relative_order":19,"sha":"d14d6c0abdd253381df51a723d58691b2ee1ab08","message":"Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:49:50.000+01:00","committed_date":"2014-02-27T09:49:50.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":10,"relative_order":20,"sha":"c1acaa58bbcbc3eafe538cb8274ba387047b69f8","message":"Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:48:32.000+01:00","committed_date":"2014-02-27T09:48:32.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":10,"relative_order":0,"utf8_diff":"Binary files a/.DS_Store and /dev/null differ\n","new_path":".DS_Store","old_path":".DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":10,"relative_order":1,"utf8_diff":"--- a/.gitignore\n+++ b/.gitignore\n@@ -17,3 +17,4 @@ rerun.txt\n pickle-email-*.html\n .project\n config/initializers/secret_token.rb\n+.DS_Store\n","new_path":".gitignore","old_path":".gitignore","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":2,"utf8_diff":"--- a/.gitmodules\n+++ b/.gitmodules\n@@ -1,3 +1,9 @@\n [submodule \"six\"]\n \tpath = six\n \turl = git://github.com/randx/six.git\n+[submodule \"gitlab-shell\"]\n+\tpath = gitlab-shell\n+\turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n","new_path":".gitmodules","old_path":".gitmodules","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":3,"utf8_diff":"--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n","new_path":"CHANGELOG","old_path":"CHANGELOG","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n","new_path":"encoding/iso8859.txt","old_path":"encoding/iso8859.txt","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":5,"utf8_diff":"Binary files a/files/.DS_Store and /dev/null differ\n","new_path":"files/.DS_Store","old_path":"files/.DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":10,"relative_order":6,"utf8_diff":"--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n+<svg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n+ <!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->\n+ <title>wm</title>\n+ <desc>Created with Sketch.</desc>\n+ <defs>\n+ <path id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"></path>\n+ </defs>\n+ <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n+ <path d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\">\n+ <g id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\">\n+ <g id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\">\n+ <path d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"></path>\n+ </g>\n+ <g id=\"g16\">\n+ <g id=\"g18-Clipped\">\n+ <mask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\">\n+ <use xlink:href=\"#path-1\"></use>\n+ </mask>\n+ <g id=\"path22\"></g>\n+ <g id=\"g18\" mask=\"url(#mask-2)\">\n+ <g transform=\"translate(382.736659, 312.879425)\">\n+ <g id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\">\n+ <path d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\">\n+ <path d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\">\n+ <path d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\">\n+ <path d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <path d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <path d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\">\n+ <path d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\">\n+ <path d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path54\"></g>\n+ </g>\n+ <g id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\">\n+ <path d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <g id=\"path62\"></g>\n+ </g>\n+ <g id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\">\n+ <path d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path70\"></g>\n+ </g>\n+ <g id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\">\n+ <path d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <path d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\">\n+ <path d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\">\n+ <path d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+</svg>\n\\ No newline at end of file\n","new_path":"files/images/wm.svg","old_path":"files/images/wm.svg","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":7,"utf8_diff":"--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n","new_path":"files/lfs/lfs_object.iso","old_path":"files/lfs/lfs_object.iso","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":8,"utf8_diff":"--- a/files/ruby/popen.rb\n+++ b/files/ruby/popen.rb\n@@ -6,12 +6,18 @@ module Popen\n \n def popen(cmd, path=nil)\n unless cmd.is_a?(Array)\n- raise \"System commands must be given as an array of strings\"\n+ raise RuntimeError, \"System commands must be given as an array of strings\"\n end\n \n path ||= Dir.pwd\n- vars = { \"PWD\" => path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" => path\n+ }\n+\n+ options = {\n+ chdir: path\n+ }\n \n unless File.directory?(path)\n FileUtils.mkdir_p(path)\n@@ -19,6 +25,7 @@ module Popen\n \n @cmd_output = \"\"\n @cmd_status = 0\n+\n Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|\n @cmd_output << stdout.read\n @cmd_output << stderr.read\n","new_path":"files/ruby/popen.rb","old_path":"files/ruby/popen.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":9,"utf8_diff":"--- a/files/ruby/regex.rb\n+++ b/files/ruby/regex.rb\n@@ -19,14 +19,12 @@ module Gitlab\n end\n \n def archive_formats_regex\n- #|zip|tar| tar.gz | tar.bz2 |\n- /(zip|tar|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n+ /(zip|tar|7z|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n end\n \n def git_reference_regex\n # Valid git ref regex, see:\n # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html\n-\n %r{\n (?!\n (?# doesn't begins with)\n","new_path":"files/ruby/regex.rb","old_path":"files/ruby/regex.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":10,"utf8_diff":"--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n","new_path":"files/whitespace","old_path":"files/whitespace","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":11,"utf8_diff":"--- /dev/null\n+++ b/foo/bar/.gitkeep\n","new_path":"foo/bar/.gitkeep","old_path":"foo/bar/.gitkeep","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":12,"utf8_diff":"--- /dev/null\n+++ b/gitlab-grack\n@@ -0,0 +1 @@\n+Subproject commit 645f6c4c82fd3f5e06f67134450a570b795e55a6\n","new_path":"gitlab-grack","old_path":"gitlab-grack","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":13,"utf8_diff":"--- /dev/null\n+++ b/gitlab-shell\n@@ -0,0 +1 @@\n+Subproject commit 79bceae69cb5750d6567b223597999bfa91cb3b9\n","new_path":"gitlab-shell","old_path":"gitlab-shell","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":10,"relative_order":14,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":10,"created_at":"2016-06-14T15:02:23.019Z","updated_at":"2016-06-14T15:02:23.493Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"15"},"events":[{"id":228,"target_type":"MergeRequest","target_id":10,"project_id":36,"created_at":"2016-06-14T15:02:23.660Z","updated_at":"2016-06-14T15:02:23.660Z","action":1,"author_id":1},{"id":170,"target_type":"MergeRequest","target_id":10,"project_id":5,"created_at":"2016-06-14T15:02:23.660Z","updated_at":"2016-06-14T15:02:23.660Z","action":1,"author_id":20}]}
+{"id":9,"target_branch":"test-6","source_branch":"test-12","source_project_id":5,"author_id":16,"assignee_id":6,"title":"Et ipsam voluptas velit sequi illum ut.","created_at":"2016-06-14T15:02:22.825Z","updated_at":"2016-06-14T15:03:00.904Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":1,"description":"Eveniet nihil ratione veniam similique qui aut sapiente tempora. Sed praesentium iusto dignissimos possimus id repudiandae quo nihil. Qui doloremque autem et iure fugit.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":825,"note":"Aliquid voluptatem consequatur voluptas ex perspiciatis.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:03:00.722Z","updated_at":"2016-06-14T15:03:00.722Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":826,"note":"Itaque optio voluptatem praesentium voluptas.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:03:00.745Z","updated_at":"2016-06-14T15:03:00.745Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":827,"note":"Ut est corporis fuga asperiores delectus excepturi aperiam.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:03:00.771Z","updated_at":"2016-06-14T15:03:00.771Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":828,"note":"Similique ea dolore officiis temporibus.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:03:00.798Z","updated_at":"2016-06-14T15:03:00.798Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":829,"note":"Qui laudantium qui quae quis.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:03:00.828Z","updated_at":"2016-06-14T15:03:00.828Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":830,"note":"Et vel voluptas amet laborum qui soluta.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:03:00.850Z","updated_at":"2016-06-14T15:03:00.850Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":831,"note":"Enim ad consequuntur assumenda provident voluptatem similique deleniti.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:03:00.876Z","updated_at":"2016-06-14T15:03:00.876Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":832,"note":"Officiis sequi commodi pariatur totam fugiat voluptas corporis dignissimos.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:03:00.902Z","updated_at":"2016-06-14T15:03:00.902Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":9,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":9,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":9,"relative_order":0,"sha":"a4e5dfebf42e34596526acb8611bc7ed80e4eb3f","message":"fixes #10\n","authored_date":"2016-01-19T15:44:02.000+01:00","committed_date":"2016-01-19T15:44:02.000+01:00","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}}],"merge_request_diff_files":[{"merge_request_diff_id":9,"relative_order":0,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":9,"created_at":"2016-06-14T15:02:22.829Z","updated_at":"2016-06-14T15:02:22.900Z","base_commit_sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","real_size":"1"},"events":[{"id":229,"target_type":"MergeRequest","target_id":9,"project_id":36,"created_at":"2016-06-14T15:02:22.927Z","updated_at":"2016-06-14T15:02:22.927Z","action":1,"author_id":16},{"id":169,"target_type":"MergeRequest","target_id":9,"project_id":5,"created_at":"2016-06-14T15:02:22.927Z","updated_at":"2016-06-14T15:02:22.927Z","action":1,"author_id":16}]}
diff --git a/spec/fixtures/packages/npm/payload.json b/spec/fixtures/packages/npm/payload.json
index 664aa636001..5ecb013b9bf 100644
--- a/spec/fixtures/packages/npm/payload.json
+++ b/spec/fixtures/packages/npm/payload.json
@@ -14,7 +14,8 @@
"express":"^4.16.4"
},
"dist":{
- "shasum":"f572d396fae9206628714fb2ce00f72e94f2258f"
+ "shasum":"f572d396fae9206628714fb2ce00f72e94f2258f",
+ "tarball":"http://localhost/npm/package.tgz"
}
}
},
diff --git a/spec/fixtures/packages/npm/payload_with_duplicated_packages.json b/spec/fixtures/packages/npm/payload_with_duplicated_packages.json
index a6ea8760bd5..bc4a7b3f55a 100644
--- a/spec/fixtures/packages/npm/payload_with_duplicated_packages.json
+++ b/spec/fixtures/packages/npm/payload_with_duplicated_packages.json
@@ -28,7 +28,8 @@
"express":"^4.16.4"
},
"dist":{
- "shasum":"f572d396fae9206628714fb2ce00f72e94f2258f"
+ "shasum":"f572d396fae9206628714fb2ce00f72e94f2258f",
+ "tarball":"http://localhost/npm/package.tgz"
}
}
},
diff --git a/spec/fixtures/scripts/test_report.json b/spec/fixtures/scripts/test_report.json
new file mode 100644
index 00000000000..29fd9a4bcb5
--- /dev/null
+++ b/spec/fixtures/scripts/test_report.json
@@ -0,0 +1,36 @@
+{
+ "suites": [
+ {
+ "name": "rspec unit pg12",
+ "total_time": 975.6635620000018,
+ "total_count": 3811,
+ "success_count": 3800,
+ "failed_count": 1,
+ "skipped_count": 10,
+ "error_count": 0,
+ "suite_error": null,
+ "test_cases": [
+ {
+ "status": "failed",
+ "name": "Note associations is expected not to belong to project required: ",
+ "classname": "spec.models.note_spec",
+ "file": "./spec/models/note_spec.rb",
+ "execution_time": 0.209091,
+ "system_output": "Failure/Error: it { is_expected.not_to belong_to(:project) }\n Did not expect Note to have a belongs_to association called project\n./spec/models/note_spec.rb:9:in `block (3 levels) in <top (required)>'\n./spec/spec_helper.rb:392:in `block (3 levels) in <top (required)>'\n./spec/support/sidekiq_middleware.rb:9:in `with_sidekiq_server_middleware'\n./spec/spec_helper.rb:383:in `block (2 levels) in <top (required)>'\n./spec/spec_helper.rb:379:in `block (3 levels) in <top (required)>'\n./lib/gitlab/application_context.rb:31:in `with_raw_context'\n./spec/spec_helper.rb:379:in `block (2 levels) in <top (required)>'\n./spec/support/database/prevent_cross_joins.rb:95:in `block (3 levels) in <top (required)>'\n./spec/support/database/prevent_cross_joins.rb:62:in `with_cross_joins_prevented'\n./spec/support/database/prevent_cross_joins.rb:95:in `block (2 levels) in <top (required)>'",
+ "stack_trace": null,
+ "recent_failures": null
+ },
+ {
+ "status": "success",
+ "name": "Gitlab::ImportExport yields the initial tree when importing and exporting it again",
+ "classname": "spec.lib.gitlab.import_export.import_export_equivalence_spec",
+ "file": "./spec/lib/gitlab/import_export/import_export_equivalence_spec.rb",
+ "execution_time": 17.084198,
+ "system_output": null,
+ "stack_trace": null,
+ "recent_failures": null
+ }
+ ]
+ }
+ ]
+}
diff --git a/spec/frontend/__helpers__/experimentation_helper.js b/spec/frontend/__helpers__/experimentation_helper.js
index 7a2ef61216a..e0156226acc 100644
--- a/spec/frontend/__helpers__/experimentation_helper.js
+++ b/spec/frontend/__helpers__/experimentation_helper.js
@@ -1,5 +1,6 @@
import { merge } from 'lodash';
+// This helper is for specs that use `gitlab/experimentation` module
export function withGonExperiment(experimentKey, value = true) {
let origGon;
@@ -12,16 +13,26 @@ export function withGonExperiment(experimentKey, value = true) {
window.gon = origGon;
});
}
-// This helper is for specs that use `gitlab-experiment` utilities, which have a different schema that gets pushed via Gon compared to `Experimentation Module`
-export function assignGitlabExperiment(experimentKey, variant) {
- let origGon;
- beforeEach(() => {
- origGon = window.gon;
- window.gon = { experiment: { [experimentKey]: { variant } } };
- });
+// The following helper is for specs that use `gitlab-experiment` utilities,
+// which have a different schema that gets pushed to the frontend compared to
+// the `Experimentation` Module.
+//
+// Usage: stubExperiments({ experiment_feature_flag_name: 'variant_name', ... })
+export function stubExperiments(experiments = {}) {
+ // Deprecated
+ window.gon = window.gon || {};
+ window.gon.experiment = window.gon.experiment || {};
+ // Preferred
+ window.gl = window.gl || {};
+ window.gl.experiments = window.gl.experiemnts || {};
- afterEach(() => {
- window.gon = origGon;
+ Object.entries(experiments).forEach(([name, variant]) => {
+ const experimentData = { experiment: name, variant };
+
+ // Deprecated
+ window.gon.experiment[name] = experimentData;
+ // Preferred
+ window.gl.experiments[name] = experimentData;
});
}
diff --git a/spec/frontend/__mocks__/@gitlab/ui.js b/spec/frontend/__mocks__/@gitlab/ui.js
index 4c491a87fcb..6b3f1f01e6a 100644
--- a/spec/frontend/__mocks__/@gitlab/ui.js
+++ b/spec/frontend/__mocks__/@gitlab/ui.js
@@ -14,7 +14,9 @@ export * from '@gitlab/ui';
*/
jest.mock('@gitlab/ui/dist/directives/tooltip.js', () => ({
- bind() {},
+ GlTooltipDirective: {
+ bind() {},
+ },
}));
jest.mock('@gitlab/ui/dist/components/base/tooltip/tooltip.js', () => ({
diff --git a/spec/frontend/admin/analytics/devops_score/components/devops_score_callout_spec.js b/spec/frontend/admin/analytics/devops_score/components/devops_score_callout_spec.js
index ee14e002f1b..c9a899ab78b 100644
--- a/spec/frontend/admin/analytics/devops_score/components/devops_score_callout_spec.js
+++ b/spec/frontend/admin/analytics/devops_score/components/devops_score_callout_spec.js
@@ -1,7 +1,7 @@
import { GlBanner } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import DevopsScoreCallout from '~/analytics/devops_report/components/devops_score_callout.vue';
-import { INTRO_COOKIE_KEY } from '~/analytics/devops_report/constants';
+import DevopsScoreCallout from '~/analytics/devops_reports/components/devops_score_callout.vue';
+import { INTRO_COOKIE_KEY } from '~/analytics/devops_reports/constants';
import * as utils from '~/lib/utils/common_utils';
import { devopsReportDocsPath, devopsScoreIntroImagePath } from '../mock_data';
diff --git a/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js b/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js
index 8f8dac977de..824eb033671 100644
--- a/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js
+++ b/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js
@@ -2,8 +2,8 @@ import { GlTable, GlBadge, GlEmptyState } from '@gitlab/ui';
import { GlSingleStat } from '@gitlab/ui/dist/charts';
import { mount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import DevopsScore from '~/analytics/devops_report/components/devops_score.vue';
-import DevopsScoreCallout from '~/analytics/devops_report/components/devops_score_callout.vue';
+import DevopsScore from '~/analytics/devops_reports/components/devops_score.vue';
+import DevopsScoreCallout from '~/analytics/devops_reports/components/devops_score_callout.vue';
import { devopsScoreMetricsData, noDataImagePath, devopsScoreTableHeaders } from '../mock_data';
describe('DevopsScore', () => {
diff --git a/spec/frontend/admin/deploy_keys/components/table_spec.js b/spec/frontend/admin/deploy_keys/components/table_spec.js
new file mode 100644
index 00000000000..3b3be488043
--- /dev/null
+++ b/spec/frontend/admin/deploy_keys/components/table_spec.js
@@ -0,0 +1,47 @@
+import { merge } from 'lodash';
+import { GlTable, GlButton } from '@gitlab/ui';
+
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import DeployKeysTable from '~/admin/deploy_keys/components/table.vue';
+
+describe('DeployKeysTable', () => {
+ let wrapper;
+
+ const defaultProvide = {
+ createPath: '/admin/deploy_keys/new',
+ deletePath: '/admin/deploy_keys/:id',
+ editPath: '/admin/deploy_keys/:id/edit',
+ emptyStateSvgPath: '/assets/illustrations/empty-state/empty-deploy-keys.svg',
+ };
+
+ const createComponent = (provide = {}) => {
+ wrapper = mountExtended(DeployKeysTable, {
+ provide: merge({}, defaultProvide, provide),
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders page title', () => {
+ createComponent();
+
+ expect(wrapper.findByText(DeployKeysTable.i18n.pageTitle).exists()).toBe(true);
+ });
+
+ it('renders table', () => {
+ createComponent();
+
+ expect(wrapper.findComponent(GlTable).exists()).toBe(true);
+ });
+
+ it('renders `New deploy key` button', () => {
+ createComponent();
+
+ const newDeployKeyButton = wrapper.findComponent(GlButton);
+
+ expect(newDeployKeyButton.text()).toBe(DeployKeysTable.i18n.newDeployKeyButtonText);
+ expect(newDeployKeyButton.attributes('href')).toBe(defaultProvide.createPath);
+ });
+});
diff --git a/spec/frontend/alert_handler_spec.js b/spec/frontend/alert_handler_spec.js
index e4cd38a7799..228053b1b2b 100644
--- a/spec/frontend/alert_handler_spec.js
+++ b/spec/frontend/alert_handler_spec.js
@@ -26,12 +26,12 @@ describe('Alert Handler', () => {
});
it('should render the alert', () => {
- expect(findFirstAlert()).toExist();
+ expect(findFirstAlert()).not.toBe(null);
});
it('should dismiss the alert on click', () => {
findFirstDismissButton().click();
- expect(findFirstAlert()).not.toExist();
+ expect(findFirstAlert()).toBe(null);
});
});
@@ -58,12 +58,12 @@ describe('Alert Handler', () => {
});
it('should render the banner', () => {
- expect(findFirstBanner()).toExist();
+ expect(findFirstBanner()).not.toBe(null);
});
it('should dismiss the banner on click', () => {
findFirstDismissButton().click();
- expect(findFirstBanner()).not.toExist();
+ expect(findFirstBanner()).toBe(null);
});
});
@@ -79,12 +79,12 @@ describe('Alert Handler', () => {
});
it('should render the banner', () => {
- expect(findFirstAlert()).toExist();
+ expect(findFirstAlert()).not.toBe(null);
});
it('should dismiss the banner on click', () => {
findFirstDismissButtonByClass().click();
- expect(findFirstAlert()).not.toExist();
+ expect(findFirstAlert()).toBe(null);
});
});
});
diff --git a/spec/frontend/alert_management/components/alert_management_table_spec.js b/spec/frontend/alert_management/components/alert_management_table_spec.js
index 20e8bc059ec..39aab8dc1f8 100644
--- a/spec/frontend/alert_management/components/alert_management_table_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_table_spec.js
@@ -40,7 +40,6 @@ describe('AlertManagementTable', () => {
resolved: 11,
all: 26,
};
- const findDeprecationNotice = () => wrapper.findByTestId('alerts-deprecation-warning');
function mountComponent({ provide = {}, data = {}, loading = false, stubs = {} } = {}) {
wrapper = extendedWrapper(
@@ -49,7 +48,6 @@ describe('AlertManagementTable', () => {
...defaultProvideValues,
alertManagementEnabled: true,
userCanEnableAlertManagement: true,
- hasManagedPrometheus: false,
...provide,
},
data() {
@@ -237,22 +235,6 @@ describe('AlertManagementTable', () => {
expect(visitUrl).toHaveBeenCalledWith('/1527542/details', true);
});
- it.each`
- managedAlertsDeprecation | hasManagedPrometheus | isVisible
- ${false} | ${false} | ${false}
- ${false} | ${true} | ${true}
- ${true} | ${false} | ${false}
- ${true} | ${true} | ${false}
- `(
- 'when the deprecation feature flag is $managedAlertsDeprecation and has managed prometheus is $hasManagedPrometheus',
- ({ hasManagedPrometheus, managedAlertsDeprecation, isVisible }) => {
- mountComponent({
- provide: { hasManagedPrometheus, glFeatures: { managedAlertsDeprecation } },
- });
- expect(findDeprecationNotice().exists()).toBe(isVisible);
- },
- );
-
describe('alert issue links', () => {
beforeEach(() => {
mountComponent({
diff --git a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
index 298596085ef..bdc1dde7d48 100644
--- a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
+++ b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
@@ -1,4 +1,12 @@
-import { GlForm, GlFormSelect, GlFormInput, GlToggle, GlFormTextarea, GlTab } from '@gitlab/ui';
+import {
+ GlForm,
+ GlFormSelect,
+ GlFormInput,
+ GlToggle,
+ GlFormTextarea,
+ GlTab,
+ GlLink,
+} from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
@@ -58,7 +66,6 @@ describe('AlertsSettingsForm', () => {
afterEach(() => {
if (wrapper) {
wrapper.destroy();
- wrapper = null;
}
});
@@ -69,7 +76,7 @@ describe('AlertsSettingsForm', () => {
const enableIntegration = (index, value) => {
findFormFields().at(index).setValue(value);
- findFormToggle().trigger('click');
+ findFormToggle().vm.$emit('change', true);
};
describe('with default values', () => {
@@ -102,6 +109,12 @@ describe('AlertsSettingsForm', () => {
expect(findFormFields().at(0).attributes('id')).not.toBe('name-integration');
});
+ it('verify pricing link url', () => {
+ createComponent({ props: { canAddIntegration: false } });
+ const link = findMultiSupportText().findComponent(GlLink);
+ expect(link.attributes('href')).toMatch(/https:\/\/about.gitlab.(com|cn)\/pricing/);
+ });
+
describe('form tabs', () => {
it('renders 3 tabs', () => {
expect(findTabs()).toHaveLength(3);
diff --git a/spec/frontend/analytics/devops_report/components/service_ping_disabled_spec.js b/spec/frontend/analytics/devops_report/components/service_ping_disabled_spec.js
deleted file mode 100644
index c5c40e9a360..00000000000
--- a/spec/frontend/analytics/devops_report/components/service_ping_disabled_spec.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import { GlEmptyState, GlSprintf } from '@gitlab/ui';
-import { TEST_HOST } from 'helpers/test_constants';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
-import ServicePingDisabled from '~/analytics/devops_report/components/service_ping_disabled.vue';
-
-describe('~/analytics/devops_report/components/service_ping_disabled.vue', () => {
- let wrapper;
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const createWrapper = ({ isAdmin = false } = {}) => {
- wrapper = mountExtended(ServicePingDisabled, {
- provide: {
- isAdmin,
- svgPath: TEST_HOST,
- primaryButtonPath: TEST_HOST,
- },
- });
- };
-
- const findEmptyState = () => wrapper.findComponent(GlEmptyState);
- const findMessageForRegularUsers = () => wrapper.findComponent(GlSprintf);
- const findDocsLink = () => wrapper.findByRole('link', { name: 'service ping' });
- const findPowerOnButton = () => wrapper.findByRole('link', { name: 'Turn on service ping' });
-
- it('renders empty state with provided SVG path', () => {
- createWrapper();
-
- expect(findEmptyState().props('svgPath')).toBe(TEST_HOST);
- });
-
- describe('for regular users', () => {
- beforeEach(() => {
- createWrapper({ isAdmin: false });
- });
-
- it('renders message without power-on button', () => {
- expect(findMessageForRegularUsers().exists()).toBe(true);
- expect(findPowerOnButton().exists()).toBe(false);
- });
-
- it('renders docs link', () => {
- expect(findDocsLink().exists()).toBe(true);
- expect(findDocsLink().attributes('href')).toBe('/help/development/service_ping/index.md');
- });
- });
-
- describe('for admins', () => {
- beforeEach(() => {
- createWrapper({ isAdmin: true });
- });
-
- it('renders power-on button', () => {
- expect(findPowerOnButton().exists()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/analytics/devops_reports/components/service_ping_disabled_spec.js b/spec/frontend/analytics/devops_reports/components/service_ping_disabled_spec.js
new file mode 100644
index 00000000000..c62bfb11f7b
--- /dev/null
+++ b/spec/frontend/analytics/devops_reports/components/service_ping_disabled_spec.js
@@ -0,0 +1,59 @@
+import { GlEmptyState, GlSprintf } from '@gitlab/ui';
+import { TEST_HOST } from 'helpers/test_constants';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import ServicePingDisabled from '~/analytics/devops_reports/components/service_ping_disabled.vue';
+
+describe('~/analytics/devops_reports/components/service_ping_disabled.vue', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const createWrapper = ({ isAdmin = false } = {}) => {
+ wrapper = mountExtended(ServicePingDisabled, {
+ provide: {
+ isAdmin,
+ svgPath: TEST_HOST,
+ primaryButtonPath: TEST_HOST,
+ },
+ });
+ };
+
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findMessageForRegularUsers = () => wrapper.findComponent(GlSprintf);
+ const findDocsLink = () => wrapper.findByRole('link', { name: 'service ping' });
+ const findPowerOnButton = () => wrapper.findByRole('link', { name: 'Turn on service ping' });
+
+ it('renders empty state with provided SVG path', () => {
+ createWrapper();
+
+ expect(findEmptyState().props('svgPath')).toBe(TEST_HOST);
+ });
+
+ describe('for regular users', () => {
+ beforeEach(() => {
+ createWrapper({ isAdmin: false });
+ });
+
+ it('renders message without power-on button', () => {
+ expect(findMessageForRegularUsers().exists()).toBe(true);
+ expect(findPowerOnButton().exists()).toBe(false);
+ });
+
+ it('renders docs link', () => {
+ expect(findDocsLink().exists()).toBe(true);
+ expect(findDocsLink().attributes('href')).toBe('/help/development/service_ping/index.md');
+ });
+ });
+
+ describe('for admins', () => {
+ beforeEach(() => {
+ createWrapper({ isAdmin: true });
+ });
+
+ it('renders power-on button', () => {
+ expect(findPowerOnButton().exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/authentication/two_factor_auth/components/manage_two_factor_form_spec.js b/spec/frontend/authentication/two_factor_auth/components/manage_two_factor_form_spec.js
index 870375318e3..694c16a85c4 100644
--- a/spec/frontend/authentication/two_factor_auth/components/manage_two_factor_form_spec.js
+++ b/spec/frontend/authentication/two_factor_auth/components/manage_two_factor_form_spec.js
@@ -1,7 +1,6 @@
-import { within } from '@testing-library/dom';
-import { GlForm } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { GlForm, GlModal } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { stubComponent } from 'helpers/stub_component';
import ManageTwoFactorForm, {
i18n,
} from '~/authentication/two_factor_auth/components/manage_two_factor_form.vue';
@@ -17,100 +16,133 @@ describe('ManageTwoFactorForm', () => {
let wrapper;
const createComponent = (options = {}) => {
- wrapper = extendedWrapper(
- mount(ManageTwoFactorForm, {
- provide: {
- ...defaultProvide,
- webauthnEnabled: options?.webauthnEnabled ?? false,
- isCurrentPasswordRequired: options?.currentPasswordRequired ?? true,
- },
- }),
- );
+ wrapper = mountExtended(ManageTwoFactorForm, {
+ provide: {
+ ...defaultProvide,
+ webauthnEnabled: options?.webauthnEnabled ?? false,
+ isCurrentPasswordRequired: options?.currentPasswordRequired ?? true,
+ },
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ template: `
+ <div>
+ <slot name="modal-title"></slot>
+ <slot></slot>
+ <slot name="modal-footer"></slot>
+ </div>`,
+ }),
+ },
+ });
};
- const queryByText = (text, options) => within(wrapper.element).queryByText(text, options);
- const queryByLabelText = (text, options) =>
- within(wrapper.element).queryByLabelText(text, options);
-
const findForm = () => wrapper.findComponent(GlForm);
const findMethodInput = () => wrapper.findByTestId('test-2fa-method-field');
const findDisableButton = () => wrapper.findByTestId('test-2fa-disable-button');
const findRegenerateCodesButton = () => wrapper.findByTestId('test-2fa-regenerate-codes-button');
+ const findConfirmationModal = () => wrapper.findComponent(GlModal);
+
+ const itShowsConfirmationModal = (confirmText) => {
+ it('shows confirmation modal', async () => {
+ await wrapper.findByLabelText('Current password').setValue('foo bar');
+ await findDisableButton().trigger('click');
+
+ expect(findConfirmationModal().props('visible')).toBe(true);
+ expect(findConfirmationModal().html()).toContain(confirmText);
+ });
+ };
+
+ const itShowsValidationMessageIfCurrentPasswordFieldIsEmpty = (findButtonFunction) => {
+ it('shows validation message if `Current password` is empty', async () => {
+ await findButtonFunction().trigger('click');
+
+ expect(wrapper.findByText(i18n.currentPasswordInvalidFeedback).exists()).toBe(true);
+ });
+ };
beforeEach(() => {
createComponent();
});
- describe('Current password field', () => {
- it('renders the current password field', () => {
- expect(queryByLabelText(i18n.currentPassword).tagName).toEqual('INPUT');
+ describe('`Current password` field', () => {
+ describe('when required', () => {
+ it('renders the current password field', () => {
+ expect(wrapper.findByLabelText(i18n.currentPassword).exists()).toBe(true);
+ });
});
- });
- describe('when current password is not required', () => {
- beforeEach(() => {
- createComponent({
- currentPasswordRequired: false,
+ describe('when not required', () => {
+ beforeEach(() => {
+ createComponent({
+ currentPasswordRequired: false,
+ });
});
- });
- it('does not render the current password field', () => {
- expect(queryByLabelText(i18n.currentPassword)).toBe(null);
+ it('does not render the current password field', () => {
+ expect(wrapper.findByLabelText(i18n.currentPassword).exists()).toBe(false);
+ });
});
});
describe('Disable button', () => {
it('renders the component with correct attributes', () => {
expect(findDisableButton().exists()).toBe(true);
- expect(findDisableButton().attributes()).toMatchObject({
- 'data-confirm': i18n.confirm,
- 'data-form-action': defaultProvide.profileTwoFactorAuthPath,
- 'data-form-method': defaultProvide.profileTwoFactorAuthMethod,
- });
});
- it('has the right confirm text', () => {
- expect(findDisableButton().attributes('data-confirm')).toBe(i18n.confirm);
- });
+ describe('when clicked', () => {
+ itShowsValidationMessageIfCurrentPasswordFieldIsEmpty(findDisableButton);
- describe('when webauthnEnabled', () => {
- beforeEach(() => {
- createComponent({
- webauthnEnabled: true,
+ itShowsConfirmationModal(i18n.confirm);
+
+ describe('when webauthnEnabled', () => {
+ beforeEach(() => {
+ createComponent({
+ webauthnEnabled: true,
+ });
});
- });
- it('has the right confirm text', () => {
- expect(findDisableButton().attributes('data-confirm')).toBe(i18n.confirmWebAuthn);
+ itShowsConfirmationModal(i18n.confirmWebAuthn);
});
- });
- it('modifies the form action and method when submitted through the button', async () => {
- const form = findForm();
- const disableButton = findDisableButton().element;
- const methodInput = findMethodInput();
+ it('modifies the form action and method when submitted through the button', async () => {
+ const form = findForm();
+ const methodInput = findMethodInput();
+ const submitSpy = jest.spyOn(form.element, 'submit');
+
+ await wrapper.findByLabelText('Current password').setValue('foo bar');
+ await findDisableButton().trigger('click');
+
+ expect(form.attributes('action')).toBe(defaultProvide.profileTwoFactorAuthPath);
+ expect(methodInput.attributes('value')).toBe(defaultProvide.profileTwoFactorAuthMethod);
- await form.vm.$emit('submit', { submitter: disableButton });
+ findConfirmationModal().vm.$emit('primary');
- expect(form.attributes('action')).toBe(defaultProvide.profileTwoFactorAuthPath);
- expect(methodInput.attributes('value')).toBe(defaultProvide.profileTwoFactorAuthMethod);
+ expect(submitSpy).toHaveBeenCalled();
+ });
});
});
describe('Regenerate recovery codes button', () => {
it('renders the button', () => {
- expect(queryByText(i18n.regenerateRecoveryCodes)).toEqual(expect.any(HTMLElement));
+ expect(findRegenerateCodesButton().exists()).toBe(true);
});
- it('modifies the form action and method when submitted through the button', async () => {
- const form = findForm();
- const regenerateCodesButton = findRegenerateCodesButton().element;
- const methodInput = findMethodInput();
+ describe('when clicked', () => {
+ itShowsValidationMessageIfCurrentPasswordFieldIsEmpty(findRegenerateCodesButton);
+
+ it('modifies the form action and method when submitted through the button', async () => {
+ const form = findForm();
+ const methodInput = findMethodInput();
+ const submitSpy = jest.spyOn(form.element, 'submit');
- await form.vm.$emit('submit', { submitter: regenerateCodesButton });
+ await wrapper.findByLabelText('Current password').setValue('foo bar');
+ await findRegenerateCodesButton().trigger('click');
- expect(form.attributes('action')).toBe(defaultProvide.codesProfileTwoFactorAuthPath);
- expect(methodInput.attributes('value')).toBe(defaultProvide.codesProfileTwoFactorAuthMethod);
+ expect(form.attributes('action')).toBe(defaultProvide.codesProfileTwoFactorAuthPath);
+ expect(methodInput.attributes('value')).toBe(
+ defaultProvide.codesProfileTwoFactorAuthMethod,
+ );
+ expect(submitSpy).toHaveBeenCalled();
+ });
});
});
});
diff --git a/spec/frontend/batch_comments/components/preview_dropdown_spec.js b/spec/frontend/batch_comments/components/preview_dropdown_spec.js
index 41be04d0b7e..5327879f003 100644
--- a/spec/frontend/batch_comments/components/preview_dropdown_spec.js
+++ b/spec/frontend/batch_comments/components/preview_dropdown_spec.js
@@ -7,7 +7,7 @@ Vue.use(Vuex);
let wrapper;
-const toggleActiveFileByHash = jest.fn();
+const setCurrentFileHash = jest.fn();
const scrollToDraft = jest.fn();
function factory({ viewDiffsFileByFile = false, draftsCount = 1, sortedDrafts = [] } = {}) {
@@ -16,7 +16,7 @@ function factory({ viewDiffsFileByFile = false, draftsCount = 1, sortedDrafts =
diffs: {
namespaced: true,
actions: {
- toggleActiveFileByHash,
+ setCurrentFileHash,
},
state: {
viewDiffsFileByFile,
@@ -51,7 +51,7 @@ describe('Batch comments preview dropdown', () => {
await Vue.nextTick();
- expect(toggleActiveFileByHash).toHaveBeenCalledWith(expect.anything(), 'hash');
+ expect(setCurrentFileHash).toHaveBeenCalledWith(expect.anything(), 'hash');
expect(scrollToDraft).toHaveBeenCalledWith(expect.anything(), { id: 1, file_hash: 'hash' });
});
diff --git a/spec/frontend/behaviors/gl_emoji_spec.js b/spec/frontend/behaviors/gl_emoji_spec.js
index 286ed269421..d23a0a84997 100644
--- a/spec/frontend/behaviors/gl_emoji_spec.js
+++ b/spec/frontend/behaviors/gl_emoji_spec.js
@@ -56,13 +56,13 @@ describe('gl_emoji', () => {
'bomb emoji just with name attribute',
'<gl-emoji data-name="bomb"></gl-emoji>',
'<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb">💣</gl-emoji>',
- '<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/1/bomb.png" width="20" height="20" align="absmiddle"></gl-emoji>',
+ `<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" width="20" height="20" align="absmiddle"></gl-emoji>`,
],
[
'bomb emoji with name attribute and unicode version',
'<gl-emoji data-name="bomb" data-unicode-version="6.0">💣</gl-emoji>',
'<gl-emoji data-name="bomb" data-unicode-version="6.0">💣</gl-emoji>',
- '<gl-emoji data-name="bomb" data-unicode-version="6.0"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/1/bomb.png" width="20" height="20" align="absmiddle"></gl-emoji>',
+ `<gl-emoji data-name="bomb" data-unicode-version="6.0"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" width="20" height="20" align="absmiddle"></gl-emoji>`,
],
[
'bomb emoji with sprite fallback',
@@ -80,7 +80,7 @@ describe('gl_emoji', () => {
'invalid emoji',
'<gl-emoji data-name="invalid_emoji"></gl-emoji>',
'<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament">â”</gl-emoji>',
- '<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament"><img class="emoji" title=":grey_question:" alt=":grey_question:" src="/-/emojis/1/grey_question.png" width="20" height="20" align="absmiddle"></gl-emoji>',
+ `<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament"><img class="emoji" title=":grey_question:" alt=":grey_question:" src="/-/emojis/${EMOJI_VERSION}/grey_question.png" width="20" height="20" align="absmiddle"></gl-emoji>`,
],
])('%s', (name, markup, withEmojiSupport, withoutEmojiSupport) => {
it(`renders correctly with emoji support`, async () => {
diff --git a/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap b/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap
index 31fb6addcac..db9684239a1 100644
--- a/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap
+++ b/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap
@@ -4,9 +4,17 @@ exports[`Blob Header Default Actions rendering matches the snapshot 1`] = `
<div
class="js-file-title file-title-flex-parent"
>
- <blob-filepath-stub
- blob="[object Object]"
- />
+ <div
+ class="gl-display-flex"
+ >
+ <table-of-contents-stub
+ class="gl-pr-2"
+ />
+
+ <blob-filepath-stub
+ blob="[object Object]"
+ />
+ </div>
<div
class="gl-display-none gl-sm-display-flex"
diff --git a/spec/frontend/blob/components/blob_header_spec.js b/spec/frontend/blob/components/blob_header_spec.js
index f841785be42..bd81b1594bf 100644
--- a/spec/frontend/blob/components/blob_header_spec.js
+++ b/spec/frontend/blob/components/blob_header_spec.js
@@ -3,6 +3,7 @@ import BlobHeader from '~/blob/components/blob_header.vue';
import DefaultActions from '~/blob/components/blob_header_default_actions.vue';
import BlobFilepath from '~/blob/components/blob_header_filepath.vue';
import ViewerSwitcher from '~/blob/components/blob_header_viewer_switcher.vue';
+import TableContents from '~/blob/components/table_contents.vue';
import { Blob } from './mock_data';
@@ -43,6 +44,7 @@ describe('Blob Header Default Actions', () => {
it('renders all components', () => {
createComponent();
+ expect(wrapper.find(TableContents).exists()).toBe(true);
expect(wrapper.find(ViewerSwitcher).exists()).toBe(true);
expect(findDefaultActions().exists()).toBe(true);
expect(wrapper.find(BlobFilepath).exists()).toBe(true);
diff --git a/spec/frontend/blob/components/table_contents_spec.js b/spec/frontend/blob/components/table_contents_spec.js
index 09633dc5d5d..ade35d39b4f 100644
--- a/spec/frontend/blob/components/table_contents_spec.js
+++ b/spec/frontend/blob/components/table_contents_spec.js
@@ -32,10 +32,30 @@ describe('Markdown table of contents component', () => {
});
describe('not loaded', () => {
+ const findDropdownItem = () => wrapper.findComponent(GlDropdownItem);
+
it('does not populate dropdown', () => {
createComponent();
- expect(wrapper.findComponent(GlDropdownItem).exists()).toBe(false);
+ expect(findDropdownItem().exists()).toBe(false);
+ });
+
+ it('does not show dropdown when loading blob content', async () => {
+ createComponent();
+
+ await setLoaded(false);
+
+ expect(findDropdownItem().exists()).toBe(false);
+ });
+
+ it('does not show dropdown when viewing non-rich content', async () => {
+ createComponent();
+
+ document.querySelector('.blob-viewer').setAttribute('data-type', 'simple');
+
+ await setLoaded(true);
+
+ expect(findDropdownItem().exists()).toBe(false);
});
});
diff --git a/spec/frontend/boards/components/board_card_spec.js b/spec/frontend/boards/components/board_card_spec.js
index 25ec568e48d..5742dfdc5d2 100644
--- a/spec/frontend/boards/components/board_card_spec.js
+++ b/spec/frontend/boards/components/board_card_spec.js
@@ -64,12 +64,12 @@ describe('Board card', () => {
};
const selectCard = async () => {
- wrapper.trigger('mouseup');
+ wrapper.trigger('click');
await wrapper.vm.$nextTick();
};
const multiSelectCard = async () => {
- wrapper.trigger('mouseup', { ctrlKey: true });
+ wrapper.trigger('click', { ctrlKey: true });
await wrapper.vm.$nextTick();
};
diff --git a/spec/frontend/boards/components/board_filtered_search_spec.js b/spec/frontend/boards/components/board_filtered_search_spec.js
index dc93890f27a..b858d6e95a0 100644
--- a/spec/frontend/boards/components/board_filtered_search_spec.js
+++ b/spec/frontend/boards/components/board_filtered_search_spec.js
@@ -7,6 +7,7 @@ import { __ } from '~/locale';
import FilteredSearchBarRoot from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
+import { createStore } from '~/boards/stores';
Vue.use(Vuex);
@@ -42,17 +43,13 @@ describe('BoardFilteredSearch', () => {
},
];
- const createComponent = ({ initialFilterParams = {} } = {}) => {
- store = new Vuex.Store({
- actions: {
- performSearch: jest.fn(),
- },
- });
-
+ const createComponent = ({ initialFilterParams = {}, props = {} } = {}) => {
+ store = createStore();
wrapper = shallowMount(BoardFilteredSearch, {
provide: { initialFilterParams, fullPath: '' },
store,
propsData: {
+ ...props,
tokens,
},
});
@@ -68,11 +65,7 @@ describe('BoardFilteredSearch', () => {
beforeEach(() => {
createComponent();
- jest.spyOn(store, 'dispatch');
- });
-
- it('renders FilteredSearch', () => {
- expect(findFilteredSearch().exists()).toBe(true);
+ jest.spyOn(store, 'dispatch').mockImplementation();
});
it('passes the correct tokens to FilteredSearch', () => {
@@ -99,6 +92,22 @@ describe('BoardFilteredSearch', () => {
});
});
+ describe('when eeFilters is not empty', () => {
+ it('passes the correct initialFilterValue to FitleredSearchBarRoot', () => {
+ createComponent({ props: { eeFilters: { labelName: ['label'] } } });
+
+ expect(findFilteredSearch().props('initialFilterValue')).toEqual([
+ { type: 'label_name', value: { data: 'label', operator: '=' } },
+ ]);
+ });
+ });
+
+ it('renders FilteredSearch', () => {
+ createComponent();
+
+ expect(findFilteredSearch().exists()).toBe(true);
+ });
+
describe('when searching', () => {
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/boards/components/board_form_spec.js b/spec/frontend/boards/components/board_form_spec.js
index 52f1907654a..692fd3ec555 100644
--- a/spec/frontend/boards/components/board_form_spec.js
+++ b/spec/frontend/boards/components/board_form_spec.js
@@ -1,7 +1,6 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import setWindowLocation from 'helpers/set_window_location_helper';
-import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
import BoardForm from '~/boards/components/board_form.vue';
@@ -18,21 +17,18 @@ jest.mock('~/lib/utils/url_utility', () => ({
}));
const currentBoard = {
- id: 1,
+ id: 'gid://gitlab/Board/1',
name: 'test',
labels: [],
- milestone_id: undefined,
+ milestone: {},
assignee: {},
- assignee_id: undefined,
weight: null,
- hide_backlog_list: false,
- hide_closed_list: false,
+ hideBacklogList: false,
+ hideClosedList: false,
};
const defaultProps = {
canAdminBoard: false,
- labelsPath: `${TEST_HOST}/labels/path`,
- labelsWebUrl: `${TEST_HOST}/-/labels`,
currentBoard,
currentPage: '',
};
@@ -252,7 +248,7 @@ describe('BoardForm', () => {
mutation: updateBoardMutation,
variables: {
input: expect.objectContaining({
- id: `gid://gitlab/Board/${currentBoard.id}`,
+ id: currentBoard.id,
}),
},
});
@@ -278,7 +274,7 @@ describe('BoardForm', () => {
mutation: updateBoardMutation,
variables: {
input: expect.objectContaining({
- id: `gid://gitlab/Board/${currentBoard.id}`,
+ id: currentBoard.id,
}),
},
});
@@ -326,7 +322,7 @@ describe('BoardForm', () => {
expect(mutate).toHaveBeenCalledWith({
mutation: destroyBoardMutation,
variables: {
- id: 'gid://gitlab/Board/1',
+ id: currentBoard.id,
},
});
diff --git a/spec/frontend/boards/components/boards_selector_spec.js b/spec/frontend/boards/components/boards_selector_spec.js
index bf317b51e83..c841c17a029 100644
--- a/spec/frontend/boards/components/boards_selector_spec.js
+++ b/spec/frontend/boards/components/boards_selector_spec.js
@@ -1,13 +1,22 @@
import { GlDropdown, GlLoadingIcon, GlDropdownSectionHeader } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import Vuex from 'vuex';
import { TEST_HOST } from 'spec/test_constants';
import BoardsSelector from '~/boards/components/boards_selector.vue';
+import groupBoardQuery from '~/boards/graphql/group_board.query.graphql';
+import projectBoardQuery from '~/boards/graphql/project_board.query.graphql';
+import defaultStore from '~/boards/stores';
import axios from '~/lib/utils/axios_utils';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { mockGroupBoardResponse, mockProjectBoardResponse } from '../mock_data';
const throttleDuration = 1;
+Vue.use(VueApollo);
+
function boardGenerator(n) {
return new Array(n).fill().map((board, index) => {
const id = `${index}`;
@@ -25,9 +34,27 @@ describe('BoardsSelector', () => {
let allBoardsResponse;
let recentBoardsResponse;
let mock;
+ let fakeApollo;
+ let store;
const boards = boardGenerator(20);
const recentBoards = boardGenerator(5);
+ const createStore = ({ isGroupBoard = false, isProjectBoard = false } = {}) => {
+ store = new Vuex.Store({
+ ...defaultStore,
+ actions: {
+ setError: jest.fn(),
+ },
+ getters: {
+ isGroupBoard: () => isGroupBoard,
+ isProjectBoard: () => isProjectBoard,
+ },
+ state: {
+ boardType: isGroupBoard ? 'group' : 'project',
+ },
+ });
+ };
+
const fillSearchBox = (filterTerm) => {
const searchBox = wrapper.find({ ref: 'searchBox' });
const searchBoxInput = searchBox.find('input');
@@ -40,52 +67,27 @@ describe('BoardsSelector', () => {
const getLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findDropdown = () => wrapper.find(GlDropdown);
- beforeEach(() => {
- mock = new MockAdapter(axios);
- const $apollo = {
- queries: {
- boards: {
- loading: false,
- },
- },
- };
+ const projectBoardQueryHandlerSuccess = jest.fn().mockResolvedValue(mockProjectBoardResponse);
+ const groupBoardQueryHandlerSuccess = jest.fn().mockResolvedValue(mockGroupBoardResponse);
- allBoardsResponse = Promise.resolve({
- data: {
- group: {
- boards: {
- edges: boards.map((board) => ({ node: board })),
- },
- },
- },
- });
- recentBoardsResponse = Promise.resolve({
- data: recentBoards,
- });
+ const createComponent = () => {
+ fakeApollo = createMockApollo([
+ [projectBoardQuery, projectBoardQueryHandlerSuccess],
+ [groupBoardQuery, groupBoardQueryHandlerSuccess],
+ ]);
wrapper = mount(BoardsSelector, {
+ store,
+ apolloProvider: fakeApollo,
propsData: {
throttleDuration,
- currentBoard: {
- id: 1,
- name: 'Development',
- milestone_id: null,
- weight: null,
- assignee_id: null,
- labels: [],
- },
boardBaseUrl: `${TEST_HOST}/board/base/url`,
hasMissingBoards: false,
canAdminBoard: true,
multipleIssueBoardsAvailable: true,
- labelsPath: `${TEST_HOST}/labels/path`,
- labelsWebUrl: `${TEST_HOST}/labels`,
- projectId: 42,
- groupId: 19,
scopedIssueBoardFeatureEnabled: true,
weights: [],
},
- mocks: { $apollo },
attachTo: document.body,
provide: {
fullPath: '',
@@ -98,12 +100,7 @@ describe('BoardsSelector', () => {
[options.loadingKey]: true,
});
});
-
- mock.onGet(`${TEST_HOST}/recent`).replyOnce(200, recentBoards);
-
- // Emits gl-dropdown show event to simulate the dropdown is opened at initialization time
- findDropdown().vm.$emit('show');
- });
+ };
afterEach(() => {
wrapper.destroy();
@@ -111,104 +108,158 @@ describe('BoardsSelector', () => {
mock.restore();
});
- describe('loading', () => {
- // we are testing loading state, so don't resolve responses until after the tests
- afterEach(() => {
- return Promise.all([allBoardsResponse, recentBoardsResponse]).then(() => nextTick());
- });
+ describe('fetching all boards', () => {
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
- it('shows loading spinner', () => {
- expect(getDropdownHeaders()).toHaveLength(0);
- expect(getDropdownItems()).toHaveLength(0);
- expect(getLoadingIcon().exists()).toBe(true);
+ allBoardsResponse = Promise.resolve({
+ data: {
+ group: {
+ boards: {
+ edges: boards.map((board) => ({ node: board })),
+ },
+ },
+ },
+ });
+ recentBoardsResponse = Promise.resolve({
+ data: recentBoards,
+ });
+
+ createStore();
+ createComponent();
+
+ mock.onGet(`${TEST_HOST}/recent`).replyOnce(200, recentBoards);
});
- });
- describe('loaded', () => {
- beforeEach(async () => {
- await wrapper.setData({
- loadingBoards: false,
+ describe('loading', () => {
+ beforeEach(async () => {
+ // Wait for current board to be loaded
+ await nextTick();
+
+ // Emits gl-dropdown show event to simulate the dropdown is opened at initialization time
+ findDropdown().vm.$emit('show');
+ });
+
+ // we are testing loading state, so don't resolve responses until after the tests
+ afterEach(async () => {
+ await Promise.all([allBoardsResponse, recentBoardsResponse]);
+ await nextTick();
});
- return Promise.all([allBoardsResponse, recentBoardsResponse]).then(() => nextTick());
- });
- it('hides loading spinner', async () => {
- await wrapper.vm.$nextTick();
- expect(getLoadingIcon().exists()).toBe(false);
+ it('shows loading spinner', () => {
+ expect(getDropdownHeaders()).toHaveLength(0);
+ expect(getDropdownItems()).toHaveLength(0);
+ expect(getLoadingIcon().exists()).toBe(true);
+ });
});
- describe('filtering', () => {
- beforeEach(() => {
- wrapper.setData({
- boards,
- });
+ describe('loaded', () => {
+ beforeEach(async () => {
+ // Wait for current board to be loaded
+ await nextTick();
+
+ // Emits gl-dropdown show event to simulate the dropdown is opened at initialization time
+ findDropdown().vm.$emit('show');
- return nextTick();
+ await wrapper.setData({
+ loadingBoards: false,
+ loadingRecentBoards: false,
+ });
+ await Promise.all([allBoardsResponse, recentBoardsResponse]);
+ await nextTick();
});
- it('shows all boards without filtering', () => {
- expect(getDropdownItems()).toHaveLength(boards.length + recentBoards.length);
+ it('hides loading spinner', async () => {
+ await nextTick();
+ expect(getLoadingIcon().exists()).toBe(false);
});
- it('shows only matching boards when filtering', () => {
- const filterTerm = 'board1';
- const expectedCount = boards.filter((board) => board.name.includes(filterTerm)).length;
+ describe('filtering', () => {
+ beforeEach(async () => {
+ wrapper.setData({
+ boards,
+ });
+
+ await nextTick();
+ });
- fillSearchBox(filterTerm);
+ it('shows all boards without filtering', () => {
+ expect(getDropdownItems()).toHaveLength(boards.length + recentBoards.length);
+ });
- return nextTick().then(() => {
+ it('shows only matching boards when filtering', async () => {
+ const filterTerm = 'board1';
+ const expectedCount = boards.filter((board) => board.name.includes(filterTerm)).length;
+
+ fillSearchBox(filterTerm);
+
+ await nextTick();
expect(getDropdownItems()).toHaveLength(expectedCount);
});
- });
- it('shows message if there are no matching boards', () => {
- fillSearchBox('does not exist');
+ it('shows message if there are no matching boards', async () => {
+ fillSearchBox('does not exist');
- return nextTick().then(() => {
+ await nextTick();
expect(getDropdownItems()).toHaveLength(0);
expect(wrapper.text().includes('No matching boards found')).toBe(true);
});
});
- });
- describe('recent boards section', () => {
- it('shows only when boards are greater than 10', () => {
- wrapper.setData({
- boards,
- });
+ describe('recent boards section', () => {
+ it('shows only when boards are greater than 10', async () => {
+ wrapper.setData({
+ boards,
+ });
- return nextTick().then(() => {
+ await nextTick();
expect(getDropdownHeaders()).toHaveLength(2);
});
- });
- it('does not show when boards are less than 10', () => {
- wrapper.setData({
- boards: boards.slice(0, 5),
- });
+ it('does not show when boards are less than 10', async () => {
+ wrapper.setData({
+ boards: boards.slice(0, 5),
+ });
- return nextTick().then(() => {
+ await nextTick();
expect(getDropdownHeaders()).toHaveLength(0);
});
- });
- it('does not show when recentBoards api returns empty array', () => {
- wrapper.setData({
- recentBoards: [],
- });
+ it('does not show when recentBoards api returns empty array', async () => {
+ wrapper.setData({
+ recentBoards: [],
+ });
- return nextTick().then(() => {
+ await nextTick();
expect(getDropdownHeaders()).toHaveLength(0);
});
- });
- it('does not show when search is active', () => {
- fillSearchBox('Random string');
+ it('does not show when search is active', async () => {
+ fillSearchBox('Random string');
- return nextTick().then(() => {
+ await nextTick();
expect(getDropdownHeaders()).toHaveLength(0);
});
});
});
});
+
+ describe('fetching current board', () => {
+ it.each`
+ boardType | queryHandler | notCalledHandler
+ ${'group'} | ${groupBoardQueryHandlerSuccess} | ${projectBoardQueryHandlerSuccess}
+ ${'project'} | ${projectBoardQueryHandlerSuccess} | ${groupBoardQueryHandlerSuccess}
+ `('fetches $boardType board', async ({ boardType, queryHandler, notCalledHandler }) => {
+ createStore({
+ isProjectBoard: boardType === 'project',
+ isGroupBoard: boardType === 'group',
+ });
+ createComponent();
+
+ await nextTick();
+
+ expect(queryHandler).toHaveBeenCalled();
+ expect(notCalledHandler).not.toHaveBeenCalled();
+ });
+ });
});
diff --git a/spec/frontend/boards/components/issue_board_filtered_search_spec.js b/spec/frontend/boards/components/issue_board_filtered_search_spec.js
index b6de46f8db8..45c5c87d800 100644
--- a/spec/frontend/boards/components/issue_board_filtered_search_spec.js
+++ b/spec/frontend/boards/components/issue_board_filtered_search_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import BoardFilteredSearch from '~/boards/components/board_filtered_search.vue';
+import BoardFilteredSearch from 'ee_else_ce/boards/components/board_filtered_search.vue';
import IssueBoardFilteredSpec from '~/boards/components/issue_board_filtered_search.vue';
import issueBoardFilters from '~/boards/issue_board_filters';
import { mockTokens } from '../mock_data';
@@ -9,39 +9,60 @@ jest.mock('~/boards/issue_board_filters');
describe('IssueBoardFilter', () => {
let wrapper;
- const createComponent = () => {
+ const findBoardsFilteredSearch = () => wrapper.findComponent(BoardFilteredSearch);
+
+ const createComponent = ({ isSignedIn = false } = {}) => {
wrapper = shallowMount(IssueBoardFilteredSpec, {
- props: { fullPath: '', boardType: '' },
+ propsData: { fullPath: 'gitlab-org', boardType: 'group' },
+ provide: {
+ isSignedIn,
+ },
});
};
+ let fetchAuthorsSpy;
+ let fetchLabelsSpy;
+ beforeEach(() => {
+ fetchAuthorsSpy = jest.fn();
+ fetchLabelsSpy = jest.fn();
+
+ issueBoardFilters.mockReturnValue({
+ fetchAuthors: fetchAuthorsSpy,
+ fetchLabels: fetchLabelsSpy,
+ });
+ });
+
afterEach(() => {
wrapper.destroy();
});
describe('default', () => {
- let fetchAuthorsSpy;
- let fetchLabelsSpy;
beforeEach(() => {
- fetchAuthorsSpy = jest.fn();
- fetchLabelsSpy = jest.fn();
-
- issueBoardFilters.mockReturnValue({
- fetchAuthors: fetchAuthorsSpy,
- fetchLabels: fetchLabelsSpy,
- });
-
createComponent();
});
it('finds BoardFilteredSearch', () => {
- expect(wrapper.find(BoardFilteredSearch).exists()).toBe(true);
+ expect(findBoardsFilteredSearch().exists()).toBe(true);
});
- it('passes the correct tokens to BoardFilteredSearch', () => {
- const tokens = mockTokens(fetchLabelsSpy, fetchAuthorsSpy, wrapper.vm.fetchMilestones);
+ it.each`
+ isSignedIn
+ ${true}
+ ${false}
+ `(
+ 'passes the correct tokens to BoardFilteredSearch when user sign in is $isSignedIn',
+ ({ isSignedIn }) => {
+ createComponent({ isSignedIn });
- expect(wrapper.find(BoardFilteredSearch).props('tokens')).toEqual(tokens);
- });
+ const tokens = mockTokens(
+ fetchLabelsSpy,
+ fetchAuthorsSpy,
+ wrapper.vm.fetchMilestones,
+ isSignedIn,
+ );
+
+ expect(findBoardsFilteredSearch().props('tokens')).toEqual(tokens);
+ },
+ );
});
});
diff --git a/spec/frontend/boards/components/new_board_button_spec.js b/spec/frontend/boards/components/new_board_button_spec.js
new file mode 100644
index 00000000000..075fe225ec2
--- /dev/null
+++ b/spec/frontend/boards/components/new_board_button_spec.js
@@ -0,0 +1,75 @@
+import { mount } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
+import NewBoardButton from '~/boards/components/new_board_button.vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { stubExperiments } from 'helpers/experimentation_helper';
+import eventHub from '~/boards/eventhub';
+
+const FEATURE = 'prominent_create_board_btn';
+
+describe('NewBoardButton', () => {
+ let wrapper;
+
+ const createComponent = (args = {}) =>
+ extendedWrapper(
+ mount(NewBoardButton, {
+ provide: {
+ canAdminBoard: true,
+ multipleIssueBoardsAvailable: true,
+ ...args,
+ },
+ }),
+ );
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ describe('control variant', () => {
+ beforeAll(() => {
+ stubExperiments({ [FEATURE]: 'control' });
+ });
+
+ it('renders nothing', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.text()).toBe('');
+ });
+ });
+
+ describe('candidate variant', () => {
+ beforeAll(() => {
+ stubExperiments({ [FEATURE]: 'candidate' });
+ });
+
+ it('renders New board button when `candidate` variant', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.text()).toBe('New board');
+ });
+
+ it('renders nothing when `canAdminBoard` is `false`', () => {
+ wrapper = createComponent({ canAdminBoard: false });
+
+ expect(wrapper.find(GlButton).exists()).toBe(false);
+ });
+
+ it('renders nothing when `multipleIssueBoardsAvailable` is `false`', () => {
+ wrapper = createComponent({ multipleIssueBoardsAvailable: false });
+
+ expect(wrapper.find(GlButton).exists()).toBe(false);
+ });
+
+ it('emits `showBoardModal` when button is clicked', () => {
+ jest.spyOn(eventHub, '$emit').mockImplementation();
+
+ wrapper = createComponent();
+
+ wrapper.find(GlButton).vm.$emit('click', { preventDefault: () => {} });
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('showBoardModal', 'new');
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
index 60474767f2d..fb9d823107e 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
@@ -105,6 +105,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
describe('when labels are updated over existing labels', () => {
const testLabelsPayload = [
{ id: 5, set: true },
+ { id: 6, set: false },
{ id: 7, set: true },
];
const expectedLabels = [{ id: 5 }, { id: 7 }];
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
index 8847f626c1f..6e1b528babc 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
@@ -14,8 +14,8 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
let store;
const findNotificationHeader = () => wrapper.find("[data-testid='notification-header-text']");
- const findToggle = () => wrapper.find(GlToggle);
- const findGlLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findToggle = () => wrapper.findComponent(GlToggle);
+ const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const createComponent = (activeBoardItem = { ...mockActiveIssue }) => {
store = createStore();
@@ -32,7 +32,6 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
afterEach(() => {
wrapper.destroy();
- wrapper = null;
store = null;
jest.clearAllMocks();
});
@@ -104,7 +103,7 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
expect(findGlLoadingIcon().exists()).toBe(false);
- findToggle().trigger('click');
+ findToggle().vm.$emit('change');
await wrapper.vm.$nextTick();
@@ -129,7 +128,7 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
expect(findGlLoadingIcon().exists()).toBe(false);
- findToggle().trigger('click');
+ findToggle().vm.$emit('change');
await wrapper.vm.$nextTick();
@@ -152,7 +151,7 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
});
jest.spyOn(wrapper.vm, 'setError').mockImplementation(() => {});
- findToggle().trigger('click');
+ findToggle().vm.$emit('change');
await wrapper.vm.$nextTick();
expect(wrapper.vm.setError).toHaveBeenCalled();
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index 6a4f344bbfb..8fcad99f8a7 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -4,6 +4,7 @@ import { ListType } from '~/boards/constants';
import { __ } from '~/locale';
import { DEFAULT_MILESTONES_GRAPHQL } from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
+import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue';
@@ -12,6 +13,7 @@ export const boardObj = {
id: 1,
name: 'test',
milestone_id: null,
+ labels: [],
};
export const listObj = {
@@ -29,17 +31,27 @@ export const listObj = {
},
};
-export const listObjDuplicate = {
- id: listObj.id,
- position: 1,
- title: 'Test',
- list_type: 'label',
- weight: 3,
- label: {
- id: listObj.label.id,
- title: 'Test',
- color: '#ff0000',
- description: 'testing;',
+export const mockGroupBoardResponse = {
+ data: {
+ workspace: {
+ board: {
+ id: 'gid://gitlab/Board/1',
+ name: 'Development',
+ },
+ __typename: 'Group',
+ },
+ },
+};
+
+export const mockProjectBoardResponse = {
+ data: {
+ workspace: {
+ board: {
+ id: 'gid://gitlab/Board/2',
+ name: 'Development',
+ },
+ __typename: 'Project',
+ },
},
};
@@ -538,7 +550,16 @@ export const mockMoveData = {
...mockMoveIssueParams,
};
-export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones) => [
+export const mockEmojiToken = {
+ type: 'my_reaction_emoji',
+ icon: 'thumb-up',
+ title: 'My-Reaction',
+ unique: true,
+ token: EmojiToken,
+ fetchEmojis: expect.any(Function),
+};
+
+export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji) => [
{
icon: 'user',
title: __('Assignee'),
@@ -579,6 +600,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones) => [
symbol: '~',
fetchLabels,
},
+ ...(hasEmoji ? [mockEmojiToken] : []),
{
icon: 'clock',
title: __('Milestone'),
@@ -593,7 +615,6 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones) => [
icon: 'issues',
title: __('Type'),
type: 'types',
- operators: [{ value: '=', description: 'is' }],
token: GlFilteredSearchToken,
unique: true,
options: [
@@ -609,3 +630,43 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones) => [
unique: true,
},
];
+
+export const mockLabel1 = {
+ id: 'gid://gitlab/GroupLabel/121',
+ title: 'To Do',
+ color: '#F0AD4E',
+ textColor: '#FFFFFF',
+ description: null,
+};
+
+export const mockLabel2 = {
+ id: 'gid://gitlab/GroupLabel/122',
+ title: 'Doing',
+ color: '#F0AD4E',
+ textColor: '#FFFFFF',
+ description: null,
+};
+
+export const mockProjectLabelsResponse = {
+ data: {
+ workspace: {
+ id: 'gid://gitlab/Project/1',
+ labels: {
+ nodes: [mockLabel1, mockLabel2],
+ },
+ __typename: 'Project',
+ },
+ },
+};
+
+export const mockGroupLabelsResponse = {
+ data: {
+ workspace: {
+ id: 'gid://gitlab/Group/1',
+ labels: {
+ nodes: [mockLabel1, mockLabel2],
+ },
+ __typename: 'Group',
+ },
+ },
+};
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index 0b90912a584..e245325b956 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -27,6 +27,7 @@ import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql'
import actions from '~/boards/stores/actions';
import * as types from '~/boards/stores/mutation_types';
import mutations from '~/boards/stores/mutations';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import {
mockLists,
@@ -1572,12 +1573,13 @@ describe('setActiveIssueLabels', () => {
const getters = { activeBoardItem: mockIssue };
const testLabelIds = labels.map((label) => label.id);
const input = {
- addLabelIds: testLabelIds,
+ labelIds: testLabelIds,
removeLabelIds: [],
projectPath: 'h/b',
+ labels,
};
- it('should assign labels on success, and sets loading state for labels', (done) => {
+ it('should assign labels on success', (done) => {
jest
.spyOn(gqlClient, 'mutate')
.mockResolvedValue({ data: { updateIssue: { issue: { labels: { nodes: labels } } } } });
@@ -1594,14 +1596,6 @@ describe('setActiveIssueLabels', () => {
{ ...state, ...getters },
[
{
- type: types.SET_LABELS_LOADING,
- payload: true,
- },
- {
- type: types.SET_LABELS_LOADING,
- payload: false,
- },
- {
type: types.UPDATE_BOARD_ITEM_BY_ID,
payload,
},
@@ -1618,6 +1612,64 @@ describe('setActiveIssueLabels', () => {
await expect(actions.setActiveIssueLabels({ getters }, input)).rejects.toThrow(Error);
});
+
+ describe('labels_widget FF on', () => {
+ beforeEach(() => {
+ window.gon = {
+ features: { labelsWidget: true },
+ };
+
+ getters.activeBoardItem = { ...mockIssue, labels };
+ });
+
+ afterEach(() => {
+ window.gon = {
+ features: {},
+ };
+ });
+
+ it('should assign labels', () => {
+ const payload = {
+ itemId: getters.activeBoardItem.id,
+ prop: 'labels',
+ value: labels,
+ };
+
+ testAction(
+ actions.setActiveIssueLabels,
+ input,
+ { ...state, ...getters },
+ [
+ {
+ type: types.UPDATE_BOARD_ITEM_BY_ID,
+ payload,
+ },
+ ],
+ [],
+ );
+ });
+
+ it('should remove label', () => {
+ const payload = {
+ itemId: getters.activeBoardItem.id,
+ prop: 'labels',
+ value: [labels[1]],
+ };
+
+ testAction(
+ actions.setActiveIssueLabels,
+ { ...input, removeLabelIds: [getIdFromGraphQLId(labels[0].id)] },
+ { ...state, ...getters },
+ [
+ {
+ type: types.UPDATE_BOARD_ITEM_BY_ID,
+ payload,
+ },
+ ],
+ [],
+ );
+ });
+ });
});
describe('setActiveItemSubscribed', () => {
diff --git a/spec/frontend/chronic_duration_spec.js b/spec/frontend/chronic_duration_spec.js
new file mode 100644
index 00000000000..32652e13dfc
--- /dev/null
+++ b/spec/frontend/chronic_duration_spec.js
@@ -0,0 +1,354 @@
+/*
+ * NOTE:
+ * Changes to this file should be kept in sync with
+ * https://gitlab.com/gitlab-org/gitlab-chronic-duration/-/blob/master/spec/lib/chronic_duration_spec.rb.
+ */
+
+/*
+ * This code is based on code from
+ * https://gitlab.com/gitlab-org/gitlab-chronic-duration and is
+ * distributed under the following license:
+ *
+ * MIT License
+ *
+ * Copyright (c) Henry Poydar
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+import {
+ parseChronicDuration,
+ outputChronicDuration,
+ DurationParseError,
+} from '~/chronic_duration';
+
+describe('parseChronicDuration', () => {
+ /*
+ * TODO The Ruby implementation of this algorithm uses the Numerizer module,
+ * which converts strings like "forty two" to "42", but there is no
+ * JavaScript equivalent of Numerizer. Skip it for now until Numerizer is
+ * ported to JavaScript.
+ */
+ const EXEMPLARS = {
+ '1:20': 60 + 20,
+ '1:20.51': 60 + 20.51,
+ '4:01:01': 4 * 3600 + 60 + 1,
+ '3 mins 4 sec': 3 * 60 + 4,
+ '3 Mins 4 Sec': 3 * 60 + 4,
+ // 'three mins four sec': 3 * 60 + 4,
+ '2 hrs 20 min': 2 * 3600 + 20 * 60,
+ '2h20min': 2 * 3600 + 20 * 60,
+ '6 mos 1 day': 6 * 30 * 24 * 3600 + 24 * 3600,
+ '1 year 6 mos 1 day': 1 * 31557600 + 6 * 30 * 24 * 3600 + 24 * 3600,
+ '2.5 hrs': 2.5 * 3600,
+ '47 yrs 6 mos and 4.5d': 47 * 31557600 + 6 * 30 * 24 * 3600 + 4.5 * 24 * 3600,
+ // 'two hours and twenty minutes': 2 * 3600 + 20 * 60,
+ // 'four hours and forty minutes': 4 * 3600 + 40 * 60,
+ // 'four hours, and fourty minutes': 4 * 3600 + 40 * 60,
+ '3 weeks and, 2 days': 3600 * 24 * 7 * 3 + 3600 * 24 * 2,
+ '3 weeks, plus 2 days': 3600 * 24 * 7 * 3 + 3600 * 24 * 2,
+ '3 weeks with 2 days': 3600 * 24 * 7 * 3 + 3600 * 24 * 2,
+ '1 month': 3600 * 24 * 30,
+ '2 months': 3600 * 24 * 30 * 2,
+ '18 months': 3600 * 24 * 30 * 18,
+ '1 year 6 months': 3600 * 24 * (365.25 + 6 * 30),
+ day: 3600 * 24,
+ 'minute 30s': 90,
+ };
+
+ describe("when string can't be parsed", () => {
+ it('returns null', () => {
+ expect(parseChronicDuration('gobblygoo')).toBeNull();
+ });
+
+ it('cannot parse zero', () => {
+ expect(parseChronicDuration('0')).toBeNull();
+ });
+
+ describe('when .raiseExceptions set to true', () => {
+ it('raises with DurationParseError', () => {
+ expect(() => parseChronicDuration('23 gobblygoos', { raiseExceptions: true })).toThrowError(
+ DurationParseError,
+ );
+ });
+
+ it('does not raise when string is empty', () => {
+ expect(parseChronicDuration('', { raiseExceptions: true })).toBeNull();
+ });
+ });
+ });
+
+ it('should return zero if the string parses as zero and the .keepZero option is true', () => {
+ expect(parseChronicDuration('0', { keepZero: true })).toBe(0);
+ });
+
+ it('should return a float if seconds are in decimals', () => {
+ expect(parseChronicDuration('12 mins 3.141 seconds')).toBeCloseTo(723.141, 4);
+ });
+
+ it('should return an integer unless the seconds are in decimals', () => {
+ expect(parseChronicDuration('12 mins 3 seconds')).toBe(723);
+ });
+
+ it('should be able to parse minutes by default', () => {
+ expect(parseChronicDuration('5', { defaultUnit: 'minutes' })).toBe(300);
+ });
+
+ Object.entries(EXEMPLARS).forEach(([k, v]) => {
+ it(`parses a duration like ${k}`, () => {
+ expect(parseChronicDuration(k)).toBe(v);
+ });
+ });
+
+ describe('with .hoursPerDay and .daysPerMonth params', () => {
+ it('uses provided .hoursPerDay', () => {
+ expect(parseChronicDuration('1d', { hoursPerDay: 24 })).toBe(24 * 60 * 60);
+ expect(parseChronicDuration('1d', { hoursPerDay: 8 })).toBe(8 * 60 * 60);
+ });
+
+ it('uses provided .daysPerMonth', () => {
+ expect(parseChronicDuration('1mo', { daysPerMonth: 30 })).toBe(30 * 24 * 60 * 60);
+ expect(parseChronicDuration('1mo', { daysPerMonth: 20 })).toBe(20 * 24 * 60 * 60);
+
+ expect(parseChronicDuration('1w', { daysPerMonth: 30 })).toBe(7 * 24 * 60 * 60);
+ expect(parseChronicDuration('1w', { daysPerMonth: 20 })).toBe(5 * 24 * 60 * 60);
+ });
+
+ it('uses provided both .hoursPerDay and .daysPerMonth', () => {
+ expect(parseChronicDuration('1mo', { daysPerMonth: 30, hoursPerDay: 24 })).toBe(
+ 30 * 24 * 60 * 60,
+ );
+ expect(parseChronicDuration('1mo', { daysPerMonth: 20, hoursPerDay: 8 })).toBe(
+ 20 * 8 * 60 * 60,
+ );
+
+ expect(parseChronicDuration('1w', { daysPerMonth: 30, hoursPerDay: 24 })).toBe(
+ 7 * 24 * 60 * 60,
+ );
+ expect(parseChronicDuration('1w', { daysPerMonth: 20, hoursPerDay: 8 })).toBe(
+ 5 * 8 * 60 * 60,
+ );
+ });
+ });
+});
+
+describe('outputChronicDuration', () => {
+ const EXEMPLARS = {
+ [60 + 20]: {
+ micro: '1m20s',
+ short: '1m 20s',
+ default: '1 min 20 secs',
+ long: '1 minute 20 seconds',
+ chrono: '1:20',
+ },
+ [60 + 20.51]: {
+ micro: '1m20.51s',
+ short: '1m 20.51s',
+ default: '1 min 20.51 secs',
+ long: '1 minute 20.51 seconds',
+ chrono: '1:20.51',
+ },
+ [60 + 20.51928]: {
+ micro: '1m20.51928s',
+ short: '1m 20.51928s',
+ default: '1 min 20.51928 secs',
+ long: '1 minute 20.51928 seconds',
+ chrono: '1:20.51928',
+ },
+ [4 * 3600 + 60 + 1]: {
+ micro: '4h1m1s',
+ short: '4h 1m 1s',
+ default: '4 hrs 1 min 1 sec',
+ long: '4 hours 1 minute 1 second',
+ chrono: '4:01:01',
+ },
+ [2 * 3600 + 20 * 60]: {
+ micro: '2h20m',
+ short: '2h 20m',
+ default: '2 hrs 20 mins',
+ long: '2 hours 20 minutes',
+ chrono: '2:20',
+ },
+ [2 * 3600 + 20 * 60]: {
+ micro: '2h20m',
+ short: '2h 20m',
+ default: '2 hrs 20 mins',
+ long: '2 hours 20 minutes',
+ chrono: '2:20:00',
+ },
+ [6 * 30 * 24 * 3600 + 24 * 3600]: {
+ micro: '6mo1d',
+ short: '6mo 1d',
+ default: '6 mos 1 day',
+ long: '6 months 1 day',
+ chrono: '6:01:00:00:00', // Yuck. FIXME
+ },
+ [365.25 * 24 * 3600 + 24 * 3600]: {
+ micro: '1y1d',
+ short: '1y 1d',
+ default: '1 yr 1 day',
+ long: '1 year 1 day',
+ chrono: '1:00:01:00:00:00',
+ },
+ [3 * 365.25 * 24 * 3600 + 24 * 3600]: {
+ micro: '3y1d',
+ short: '3y 1d',
+ default: '3 yrs 1 day',
+ long: '3 years 1 day',
+ chrono: '3:00:01:00:00:00',
+ },
+ [3600 * 24 * 30 * 18]: {
+ micro: '18mo',
+ short: '18mo',
+ default: '18 mos',
+ long: '18 months',
+ chrono: '18:00:00:00:00',
+ },
+ };
+
+ Object.entries(EXEMPLARS).forEach(([k, v]) => {
+ const kf = parseFloat(k);
+ Object.entries(v).forEach(([key, val]) => {
+ it(`properly outputs a duration of ${kf} seconds as ${val} using the ${key} format option`, () => {
+ expect(outputChronicDuration(kf, { format: key })).toBe(val);
+ });
+ });
+ });
+
+ const KEEP_ZERO_EXEMPLARS = {
+ true: {
+ micro: '0s',
+ short: '0s',
+ default: '0 secs',
+ long: '0 seconds',
+ chrono: '0',
+ },
+ '': {
+ micro: null,
+ short: null,
+ default: null,
+ long: null,
+ chrono: '0',
+ },
+ };
+
+ Object.entries(KEEP_ZERO_EXEMPLARS).forEach(([k, v]) => {
+ const kb = Boolean(k);
+ Object.entries(v).forEach(([key, val]) => {
+ it(`should properly output a duration of 0 seconds as ${val} using the ${key} format option, if the .keepZero option is ${kb}`, () => {
+ expect(outputChronicDuration(0, { format: key, keepZero: kb })).toBe(val);
+ });
+ });
+ });
+
+ it('returns weeks when needed', () => {
+ expect(outputChronicDuration(45 * 24 * 60 * 60, { weeks: true })).toMatch(/.*wk.*/);
+ });
+
+ it('returns hours and minutes only when .limitToHours option specified', () => {
+ expect(outputChronicDuration(395 * 24 * 60 * 60 + 15 * 60, { limitToHours: true })).toBe(
+ '9480 hrs 15 mins',
+ );
+ });
+
+ describe('with .hoursPerDay and .daysPerMonth params', () => {
+ it('uses provided .hoursPerDay', () => {
+ expect(outputChronicDuration(24 * 60 * 60, { hoursPerDay: 24 })).toBe('1 day');
+ expect(outputChronicDuration(24 * 60 * 60, { hoursPerDay: 8 })).toBe('3 days');
+ });
+
+ it('uses provided .daysPerMonth', () => {
+ expect(outputChronicDuration(7 * 24 * 60 * 60, { weeks: true, daysPerMonth: 30 })).toBe(
+ '1 wk',
+ );
+ expect(outputChronicDuration(7 * 24 * 60 * 60, { weeks: true, daysPerMonth: 20 })).toBe(
+ '1 wk 2 days',
+ );
+ });
+
+ it('uses provided both .hoursPerDay and .daysPerMonth', () => {
+ expect(
+ outputChronicDuration(7 * 24 * 60 * 60, { weeks: true, daysPerMonth: 30, hoursPerDay: 24 }),
+ ).toBe('1 wk');
+ expect(
+ outputChronicDuration(5 * 8 * 60 * 60, { weeks: true, daysPerMonth: 20, hoursPerDay: 8 }),
+ ).toBe('1 wk');
+ });
+
+ it('uses provided params alongside with .weeks when converting to months', () => {
+ expect(outputChronicDuration(30 * 24 * 60 * 60, { daysPerMonth: 30, hoursPerDay: 24 })).toBe(
+ '1 mo',
+ );
+ expect(
+ outputChronicDuration(30 * 24 * 60 * 60, {
+ daysPerMonth: 30,
+ hoursPerDay: 24,
+ weeks: true,
+ }),
+ ).toBe('1 mo 2 days');
+
+ expect(outputChronicDuration(20 * 8 * 60 * 60, { daysPerMonth: 20, hoursPerDay: 8 })).toBe(
+ '1 mo',
+ );
+ expect(
+ outputChronicDuration(20 * 8 * 60 * 60, { daysPerMonth: 20, hoursPerDay: 8, weeks: true }),
+ ).toBe('1 mo');
+ });
+ });
+
+ it('returns the specified number of units if provided', () => {
+ expect(outputChronicDuration(4 * 3600 + 60 + 1, { units: 2 })).toBe('4 hrs 1 min');
+ expect(
+ outputChronicDuration(6 * 30 * 24 * 3600 + 24 * 3600 + 3600 + 60 + 1, {
+ units: 3,
+ format: 'long',
+ }),
+ ).toBe('6 months 1 day 1 hour');
+ });
+
+ describe('when the format is not specified', () => {
+ it('uses the default format', () => {
+ expect(outputChronicDuration(2 * 3600 + 20 * 60)).toBe('2 hrs 20 mins');
+ });
+ });
+
+ Object.entries(EXEMPLARS).forEach(([seconds, formatSpec]) => {
+ const secondsF = parseFloat(seconds);
+ Object.keys(formatSpec).forEach((format) => {
+ it(`outputs a duration for ${seconds} that parses back to the same thing when using the ${format} format`, () => {
+ expect(parseChronicDuration(outputChronicDuration(secondsF, { format }))).toBe(secondsF);
+ });
+ });
+ });
+
+ it('uses user-specified joiner if provided', () => {
+ expect(outputChronicDuration(2 * 3600 + 20 * 60, { joiner: ', ' })).toBe('2 hrs, 20 mins');
+ });
+});
+
+describe('work week', () => {
+ it('should parse knowing the work week', () => {
+ const week = parseChronicDuration('5d', { hoursPerDay: 8, daysPerMonth: 20 });
+ expect(parseChronicDuration('40h', { hoursPerDay: 8, daysPerMonth: 20 })).toBe(week);
+ expect(parseChronicDuration('1w', { hoursPerDay: 8, daysPerMonth: 20 })).toBe(week);
+ });
+});
diff --git a/spec/frontend/clusters/agents/components/show_spec.js b/spec/frontend/clusters/agents/components/show_spec.js
index fd04ff8b3e7..c502e7d813e 100644
--- a/spec/frontend/clusters/agents/components/show_spec.js
+++ b/spec/frontend/clusters/agents/components/show_spec.js
@@ -1,6 +1,8 @@
import { GlAlert, GlKeysetPagination, GlLoadingIcon, GlSprintf, GlTab } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ClusterAgentShow from '~/clusters/agents/components/show.vue';
import TokenTable from '~/clusters/agents/components/token_table.vue';
import getAgentQuery from '~/clusters/agents/graphql/queries/get_cluster_agent.query.graphql';
@@ -40,28 +42,34 @@ describe('ClusterAgentShow', () => {
queryResponse || jest.fn().mockResolvedValue({ data: { project: { clusterAgent } } });
const apolloProvider = createMockApollo([[getAgentQuery, agentQueryResponse]]);
- wrapper = shallowMount(ClusterAgentShow, {
- localVue,
- apolloProvider,
- propsData,
- stubs: { GlSprintf, TimeAgoTooltip, GlTab },
- });
+ wrapper = extendedWrapper(
+ shallowMount(ClusterAgentShow, {
+ localVue,
+ apolloProvider,
+ propsData,
+ stubs: { GlSprintf, TimeAgoTooltip, GlTab },
+ }),
+ );
};
- const createWrapperWithoutApollo = ({ clusterAgent, loading = false }) => {
+ const createWrapperWithoutApollo = ({ clusterAgent, loading = false, slots = {} }) => {
const $apollo = { queries: { clusterAgent: { loading } } };
- wrapper = shallowMount(ClusterAgentShow, {
- propsData,
- mocks: { $apollo, clusterAgent },
- stubs: { GlTab },
- });
+ wrapper = extendedWrapper(
+ shallowMount(ClusterAgentShow, {
+ propsData,
+ mocks: { $apollo, clusterAgent },
+ slots,
+ stubs: { GlTab },
+ }),
+ );
};
- const findCreatedText = () => wrapper.find('[data-testid="cluster-agent-create-info"]').text();
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findPaginationButtons = () => wrapper.find(GlKeysetPagination);
- const findTokenCount = () => wrapper.find('[data-testid="cluster-agent-token-count"]').text();
+ const findCreatedText = () => wrapper.findByTestId('cluster-agent-create-info').text();
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findPaginationButtons = () => wrapper.findComponent(GlKeysetPagination);
+ const findTokenCount = () => wrapper.findByTestId('cluster-agent-token-count').text();
+ const findEESecurityTabSlot = () => wrapper.findByTestId('ee-security-tab');
afterEach(() => {
wrapper.destroy();
@@ -87,7 +95,7 @@ describe('ClusterAgentShow', () => {
});
it('renders token table', () => {
- expect(wrapper.find(TokenTable).exists()).toBe(true);
+ expect(wrapper.findComponent(TokenTable).exists()).toBe(true);
});
it('should not render pagination buttons when there are no additional pages', () => {
@@ -188,8 +196,27 @@ describe('ClusterAgentShow', () => {
});
it('displays an alert message', () => {
- expect(wrapper.find(GlAlert).exists()).toBe(true);
+ expect(wrapper.findComponent(GlAlert).exists()).toBe(true);
expect(wrapper.text()).toContain(ClusterAgentShow.i18n.loadingError);
});
});
+
+ describe('ee-security-tab slot', () => {
+ it('does not display when a slot is not passed in', async () => {
+ createWrapperWithoutApollo({ clusterAgent: defaultClusterAgent });
+ await nextTick();
+ expect(findEESecurityTabSlot().exists()).toBe(false);
+ });
+
+ it('does display when a slot is passed in', async () => {
+ createWrapperWithoutApollo({
+ clusterAgent: defaultClusterAgent,
+ slots: {
+ 'ee-security-tab': `<gl-tab data-testid="ee-security-tab">Security Tab!</gl-tab>`,
+ },
+ });
+ await nextTick();
+ expect(findEESecurityTabSlot().exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js b/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js
index e2726b93ea5..41bd492148e 100644
--- a/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js
+++ b/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js
@@ -1,18 +1,20 @@
-import { GlModal } from '@gitlab/ui';
+import { GlModal, GlSprintf } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { stubComponent } from 'helpers/stub_component';
import RemoveClusterConfirmation from '~/clusters/components/remove_cluster_confirmation.vue';
import SplitButton from '~/vue_shared/components/split_button.vue';
describe('Remove cluster confirmation modal', () => {
let wrapper;
- const createComponent = (props = {}) => {
+ const createComponent = ({ props = {}, stubs = {} } = {}) => {
wrapper = mount(RemoveClusterConfirmation, {
propsData: {
clusterPath: 'clusterPath',
clusterName: 'clusterName',
...props,
},
+ stubs,
});
};
@@ -27,35 +29,44 @@ describe('Remove cluster confirmation modal', () => {
});
describe('split button dropdown', () => {
- const findModal = () => wrapper.find(GlModal).vm;
- const findSplitButton = () => wrapper.find(SplitButton);
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findSplitButton = () => wrapper.findComponent(SplitButton);
beforeEach(() => {
- createComponent({ clusterName: 'my-test-cluster' });
- jest.spyOn(findModal(), 'show').mockReturnValue();
+ createComponent({
+ props: { clusterName: 'my-test-cluster' },
+ stubs: { GlSprintf, GlModal: stubComponent(GlModal) },
+ });
+ jest.spyOn(findModal().vm, 'show').mockReturnValue();
});
- it('opens modal with "cleanup" option', () => {
+ it('opens modal with "cleanup" option', async () => {
findSplitButton().vm.$emit('remove-cluster-and-cleanup');
- return wrapper.vm.$nextTick().then(() => {
- expect(findModal().show).toHaveBeenCalled();
- expect(wrapper.vm.confirmCleanup).toEqual(true);
- });
+ await wrapper.vm.$nextTick();
+
+ expect(findModal().vm.show).toHaveBeenCalled();
+ expect(wrapper.vm.confirmCleanup).toEqual(true);
+ expect(findModal().html()).toContain(
+ '<strong>To remove your integration and resources, type <code>my-test-cluster</code> to confirm:</strong>',
+ );
});
- it('opens modal without "cleanup" option', () => {
+ it('opens modal without "cleanup" option', async () => {
findSplitButton().vm.$emit('remove-cluster');
- return wrapper.vm.$nextTick().then(() => {
- expect(findModal().show).toHaveBeenCalled();
- expect(wrapper.vm.confirmCleanup).toEqual(false);
- });
+ await wrapper.vm.$nextTick();
+
+ expect(findModal().vm.show).toHaveBeenCalled();
+ expect(wrapper.vm.confirmCleanup).toEqual(false);
+ expect(findModal().html()).toContain(
+ '<strong>To remove your integration, type <code>my-test-cluster</code> to confirm:</strong>',
+ );
});
describe('with cluster management project', () => {
beforeEach(() => {
- createComponent({ hasManagementProject: true });
+ createComponent({ props: { hasManagementProject: true } });
});
it('renders regular button instead', () => {
diff --git a/spec/frontend/clusters_list/components/agent_empty_state_spec.js b/spec/frontend/clusters_list/components/agent_empty_state_spec.js
index a548721588e..38f0e0ba2c4 100644
--- a/spec/frontend/clusters_list/components/agent_empty_state_spec.js
+++ b/spec/frontend/clusters_list/components/agent_empty_state_spec.js
@@ -1,13 +1,12 @@
import { GlAlert, GlEmptyState, GlSprintf } from '@gitlab/ui';
import AgentEmptyState from '~/clusters_list/components/agent_empty_state.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { helpPagePath } from '~/helpers/help_page_helper';
const emptyStateImage = '/path/to/image';
const projectPath = 'path/to/project';
-const agentDocsUrl = 'path/to/agentDocs';
-const installDocsUrl = 'path/to/installDocs';
-const getStartedDocsUrl = 'path/to/getStartedDocs';
-const integrationDocsUrl = 'path/to/integrationDocs';
+const multipleClustersDocsUrl = helpPagePath('user/project/clusters/multiple_kubernetes_clusters');
+const installDocsUrl = helpPagePath('administration/clusters/kas');
describe('AgentEmptyStateComponent', () => {
let wrapper;
@@ -18,14 +17,10 @@ describe('AgentEmptyStateComponent', () => {
const provideData = {
emptyStateImage,
projectPath,
- agentDocsUrl,
- installDocsUrl,
- getStartedDocsUrl,
- integrationDocsUrl,
};
const findConfigurationsAlert = () => wrapper.findComponent(GlAlert);
- const findAgentDocsLink = () => wrapper.findByTestId('agent-docs-link');
+ const findMultipleClustersDocsLink = () => wrapper.findByTestId('multiple-clusters-docs-link');
const findInstallDocsLink = () => wrapper.findByTestId('install-docs-link');
const findIntegrationButton = () => wrapper.findByTestId('integration-primary-button');
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
@@ -41,12 +36,11 @@ describe('AgentEmptyStateComponent', () => {
afterEach(() => {
if (wrapper) {
wrapper.destroy();
- wrapper = null;
}
});
it('renders correct href attributes for the links', () => {
- expect(findAgentDocsLink().attributes('href')).toBe(agentDocsUrl);
+ expect(findMultipleClustersDocsLink().attributes('href')).toBe(multipleClustersDocsUrl);
expect(findInstallDocsLink().attributes('href')).toBe(installDocsUrl);
});
diff --git a/spec/frontend/clusters_list/components/agent_table_spec.js b/spec/frontend/clusters_list/components/agent_table_spec.js
index e3b90584f29..a6d76b069cf 100644
--- a/spec/frontend/clusters_list/components/agent_table_spec.js
+++ b/spec/frontend/clusters_list/components/agent_table_spec.js
@@ -1,4 +1,4 @@
-import { GlButton, GlLink, GlIcon } from '@gitlab/ui';
+import { GlLink, GlIcon } from '@gitlab/ui';
import AgentTable from '~/clusters_list/components/agent_table.vue';
import { ACTIVE_CONNECTION_TIME } from '~/clusters_list/constants';
import { mountExtended } from 'helpers/vue_test_utils_helper';
@@ -47,7 +47,6 @@ const propsData = {
},
],
};
-const provideData = { integrationDocsUrl: 'path/to/integrationDocs' };
describe('AgentTable', () => {
let wrapper;
@@ -60,7 +59,7 @@ describe('AgentTable', () => {
wrapper.findAllByTestId('cluster-agent-configuration-link').at(at);
beforeEach(() => {
- wrapper = mountExtended(AgentTable, { propsData, provide: provideData });
+ wrapper = mountExtended(AgentTable, { propsData });
});
afterEach(() => {
@@ -70,10 +69,6 @@ describe('AgentTable', () => {
}
});
- it('displays header button', () => {
- expect(wrapper.find(GlButton).text()).toBe('Install a new GitLab Agent');
- });
-
describe('agent table', () => {
it.each`
agentName | link | lineNumber
diff --git a/spec/frontend/clusters_list/components/agents_spec.js b/spec/frontend/clusters_list/components/agents_spec.js
index 54d5ae94172..2dec7cdc973 100644
--- a/spec/frontend/clusters_list/components/agents_spec.js
+++ b/spec/frontend/clusters_list/components/agents_spec.js
@@ -14,7 +14,7 @@ localVue.use(VueApollo);
describe('Agents', () => {
let wrapper;
- const propsData = {
+ const defaultProps = {
defaultBranchName: 'default',
};
const provideData = {
@@ -22,12 +22,12 @@ describe('Agents', () => {
kasAddress: 'kas.example.com',
};
- const createWrapper = ({ agents = [], pageInfo = null, trees = [] }) => {
+ const createWrapper = ({ props = {}, agents = [], pageInfo = null, trees = [], count = 0 }) => {
const provide = provideData;
const apolloQueryResponse = {
data: {
project: {
- clusterAgents: { nodes: agents, pageInfo, tokens: { nodes: [] } },
+ clusterAgents: { nodes: agents, pageInfo, tokens: { nodes: [] }, count },
repository: { tree: { trees: { nodes: trees, pageInfo } } },
},
},
@@ -40,7 +40,10 @@ describe('Agents', () => {
wrapper = shallowMount(Agents, {
localVue,
apolloProvider,
- propsData,
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
provide: provideData,
});
@@ -54,7 +57,6 @@ describe('Agents', () => {
afterEach(() => {
if (wrapper) {
wrapper.destroy();
- wrapper = null;
}
});
@@ -81,6 +83,8 @@ describe('Agents', () => {
},
];
+ const count = 2;
+
const trees = [
{
name: 'agent-2',
@@ -121,7 +125,7 @@ describe('Agents', () => {
];
beforeEach(() => {
- return createWrapper({ agents, trees });
+ return createWrapper({ agents, count, trees });
});
it('should render agent table', () => {
@@ -133,6 +137,10 @@ describe('Agents', () => {
expect(findAgentTable().props('agents')).toMatchObject(expectedAgentsList);
});
+ it('should emit agents count to the parent component', () => {
+ expect(wrapper.emitted().onAgentsLoad).toEqual([[count]]);
+ });
+
describe('when the agent has recently connected tokens', () => {
it('should set agent status to active', () => {
expect(findAgentTable().props('agents')).toMatchObject(expectedAgentsList);
@@ -180,6 +188,20 @@ describe('Agents', () => {
it('should pass pageInfo to the pagination component', () => {
expect(findPaginationButtons().props()).toMatchObject(pageInfo);
});
+
+ describe('when limit is passed from the parent component', () => {
+ beforeEach(() => {
+ return createWrapper({
+ props: { limit: 6 },
+ agents,
+ pageInfo,
+ });
+ });
+
+ it('should not render pagination buttons', () => {
+ expect(findPaginationButtons().exists()).toBe(false);
+ });
+ });
});
});
@@ -234,7 +256,11 @@ describe('Agents', () => {
};
beforeEach(() => {
- wrapper = shallowMount(Agents, { mocks, propsData, provide: provideData });
+ wrapper = shallowMount(Agents, {
+ mocks,
+ propsData: defaultProps,
+ provide: provideData,
+ });
return wrapper.vm.$nextTick();
});
diff --git a/spec/frontend/clusters_list/components/clusters_actions_spec.js b/spec/frontend/clusters_list/components/clusters_actions_spec.js
new file mode 100644
index 00000000000..cb8303ca4b2
--- /dev/null
+++ b/spec/frontend/clusters_list/components/clusters_actions_spec.js
@@ -0,0 +1,55 @@
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ClustersActions from '~/clusters_list/components/clusters_actions.vue';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { INSTALL_AGENT_MODAL_ID, CLUSTERS_ACTIONS } from '~/clusters_list/constants';
+
+describe('ClustersActionsComponent', () => {
+ let wrapper;
+
+ const newClusterPath = 'path/to/create/cluster';
+ const addClusterPath = 'path/to/connect/existing/cluster';
+
+ const provideData = {
+ newClusterPath,
+ addClusterPath,
+ };
+
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findNewClusterLink = () => wrapper.findByTestId('new-cluster-link');
+ const findConnectClusterLink = () => wrapper.findByTestId('connect-cluster-link');
+ const findConnectNewAgentLink = () => wrapper.findByTestId('connect-new-agent-link');
+
+ beforeEach(() => {
+ wrapper = shallowMountExtended(ClustersActions, {
+ provide: provideData,
+ directives: {
+ GlModalDirective: createMockDirective(),
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders actions menu', () => {
+ expect(findDropdown().props('text')).toBe(CLUSTERS_ACTIONS.actionsButton);
+ });
+
+ it('renders a dropdown with 3 actions items', () => {
+ expect(findDropdownItems()).toHaveLength(3);
+ });
+
+ it('renders correct href attributes for the links', () => {
+ expect(findNewClusterLink().attributes('href')).toBe(newClusterPath);
+ expect(findConnectClusterLink().attributes('href')).toBe(addClusterPath);
+ });
+
+ it('renders correct modal id for the agent link', () => {
+ const binding = getBinding(findConnectNewAgentLink().element, 'gl-modal-directive');
+
+ expect(binding.value).toBe(INSTALL_AGENT_MODAL_ID);
+ });
+});
diff --git a/spec/frontend/clusters_list/components/clusters_empty_state_spec.js b/spec/frontend/clusters_list/components/clusters_empty_state_spec.js
new file mode 100644
index 00000000000..f7e1791d0f7
--- /dev/null
+++ b/spec/frontend/clusters_list/components/clusters_empty_state_spec.js
@@ -0,0 +1,104 @@
+import { GlEmptyState, GlButton } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ClustersEmptyState from '~/clusters_list/components/clusters_empty_state.vue';
+import ClusterStore from '~/clusters_list/store';
+
+const clustersEmptyStateImage = 'path/to/svg';
+const newClusterPath = '/path/to/connect/cluster';
+const emptyStateHelpText = 'empty state text';
+const canAddCluster = true;
+
+describe('ClustersEmptyStateComponent', () => {
+ let wrapper;
+
+ const propsData = {
+ isChildComponent: false,
+ };
+
+ const provideData = {
+ clustersEmptyStateImage,
+ emptyStateHelpText: null,
+ newClusterPath,
+ };
+
+ const entryData = {
+ canAddCluster,
+ };
+
+ const findButton = () => wrapper.findComponent(GlButton);
+ const findEmptyStateText = () => wrapper.findByTestId('clusters-empty-state-text');
+
+ beforeEach(() => {
+ wrapper = shallowMountExtended(ClustersEmptyState, {
+ store: ClusterStore(entryData),
+ propsData,
+ provide: provideData,
+ stubs: { GlEmptyState },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('when the component is loaded independently', () => {
+ it('should render the action button', () => {
+ expect(findButton().exists()).toBe(true);
+ });
+ });
+
+ describe('when the help text is not provided', () => {
+ it('should not render the empty state text', () => {
+ expect(findEmptyStateText().exists()).toBe(false);
+ });
+ });
+
+ describe('when the component is loaded as a child component', () => {
+ beforeEach(() => {
+ propsData.isChildComponent = true;
+ wrapper = shallowMountExtended(ClustersEmptyState, {
+ store: ClusterStore(entryData),
+ propsData,
+ provide: provideData,
+ });
+ });
+
+ afterEach(() => {
+ propsData.isChildComponent = false;
+ });
+
+ it('should not render the action button', () => {
+ expect(findButton().exists()).toBe(false);
+ });
+ });
+
+ describe('when the help text is provided', () => {
+ beforeEach(() => {
+ provideData.emptyStateHelpText = emptyStateHelpText;
+ wrapper = shallowMountExtended(ClustersEmptyState, {
+ store: ClusterStore(entryData),
+ propsData,
+ provide: provideData,
+ });
+ });
+
+ it('should show the empty state text', () => {
+ expect(findEmptyStateText().text()).toBe(emptyStateHelpText);
+ });
+ });
+
+ describe('when the user cannot add clusters', () => {
+ entryData.canAddCluster = false;
+ beforeEach(() => {
+ wrapper = shallowMountExtended(ClustersEmptyState, {
+ store: ClusterStore(entryData),
+ propsData,
+ provide: provideData,
+ stubs: { GlEmptyState },
+ });
+ });
+ it('should disable the button', () => {
+ expect(findButton().props('disabled')).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/clusters_list/components/clusters_main_view_spec.js b/spec/frontend/clusters_list/components/clusters_main_view_spec.js
new file mode 100644
index 00000000000..c2233e5d39c
--- /dev/null
+++ b/spec/frontend/clusters_list/components/clusters_main_view_spec.js
@@ -0,0 +1,82 @@
+import { GlTabs, GlTab } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ClustersMainView from '~/clusters_list/components/clusters_main_view.vue';
+import InstallAgentModal from '~/clusters_list/components/install_agent_modal.vue';
+import {
+ AGENT,
+ CERTIFICATE_BASED,
+ CLUSTERS_TABS,
+ MAX_CLUSTERS_LIST,
+ MAX_LIST_COUNT,
+} from '~/clusters_list/constants';
+
+const defaultBranchName = 'default-branch';
+
+describe('ClustersMainViewComponent', () => {
+ let wrapper;
+
+ const propsData = {
+ defaultBranchName,
+ };
+
+ beforeEach(() => {
+ wrapper = shallowMountExtended(ClustersMainView, {
+ propsData,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findTabs = () => wrapper.findComponent(GlTabs);
+ const findAllTabs = () => wrapper.findAllComponents(GlTab);
+ const findGlTabAtIndex = (index) => findAllTabs().at(index);
+ const findComponent = () => wrapper.findByTestId('clusters-tab-component');
+ const findModal = () => wrapper.findComponent(InstallAgentModal);
+
+ it('renders `GlTabs` with `syncActiveTabWithQueryParams` and `queryParamName` props set', () => {
+ expect(findTabs().exists()).toBe(true);
+ expect(findTabs().props('syncActiveTabWithQueryParams')).toBe(true);
+ });
+
+ it('renders correct number of tabs', () => {
+ expect(findAllTabs()).toHaveLength(CLUSTERS_TABS.length);
+ });
+
+ it('passes child-component param to the component', () => {
+ expect(findComponent().props('defaultBranchName')).toBe(defaultBranchName);
+ });
+
+ it('passes correct max-agents param to the modal', () => {
+ expect(findModal().props('maxAgents')).toBe(MAX_CLUSTERS_LIST);
+ });
+
+ describe('tabs', () => {
+ it.each`
+ tabTitle | queryParamValue | lineNumber
+ ${'All'} | ${'all'} | ${0}
+ ${'Agent'} | ${AGENT} | ${1}
+ ${'Certificate based'} | ${CERTIFICATE_BASED} | ${2}
+ `(
+ 'renders correct tab title and query param value',
+ ({ tabTitle, queryParamValue, lineNumber }) => {
+ expect(findGlTabAtIndex(lineNumber).attributes('title')).toBe(tabTitle);
+ expect(findGlTabAtIndex(lineNumber).props('queryParamValue')).toBe(queryParamValue);
+ },
+ );
+ });
+
+ describe('when the child component emits the tab change event', () => {
+ beforeEach(() => {
+ findComponent().vm.$emit('changeTab', AGENT);
+ });
+ it('changes the tab', () => {
+ expect(findTabs().attributes('value')).toBe('1');
+ });
+
+ it('passes correct max-agents param to the modal', () => {
+ expect(findModal().props('maxAgents')).toBe(MAX_LIST_COUNT);
+ });
+ });
+});
diff --git a/spec/frontend/clusters_list/components/clusters_spec.js b/spec/frontend/clusters_list/components/clusters_spec.js
index 941a3adb625..a34202c789d 100644
--- a/spec/frontend/clusters_list/components/clusters_spec.js
+++ b/spec/frontend/clusters_list/components/clusters_spec.js
@@ -8,6 +8,7 @@ import * as Sentry from '@sentry/browser';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import Clusters from '~/clusters_list/components/clusters.vue';
+import ClustersEmptyState from '~/clusters_list/components/clusters_empty_state.vue';
import ClusterStore from '~/clusters_list/store';
import axios from '~/lib/utils/axios_utils';
import { apiData } from '../mock_data';
@@ -18,26 +19,38 @@ describe('Clusters', () => {
let wrapper;
const endpoint = 'some/endpoint';
+ const totalClustersNumber = 6;
+ const clustersEmptyStateImage = 'path/to/svg';
+ const emptyStateHelpText = null;
+ const newClusterPath = '/path/to/new/cluster';
const entryData = {
endpoint,
imgTagsAwsText: 'AWS Icon',
imgTagsDefaultText: 'Default Icon',
imgTagsGcpText: 'GCP Icon',
+ totalClusters: totalClustersNumber,
};
- const findLoader = () => wrapper.find(GlLoadingIcon);
- const findPaginatedButtons = () => wrapper.find(GlPagination);
- const findTable = () => wrapper.find(GlTable);
+ const provideData = {
+ clustersEmptyStateImage,
+ emptyStateHelpText,
+ newClusterPath,
+ };
+
+ const findLoader = () => wrapper.findComponent(GlLoadingIcon);
+ const findPaginatedButtons = () => wrapper.findComponent(GlPagination);
+ const findTable = () => wrapper.findComponent(GlTable);
const findStatuses = () => findTable().findAll('.js-status');
+ const findEmptyState = () => wrapper.findComponent(ClustersEmptyState);
const mockPollingApi = (response, body, header) => {
mock.onGet(`${endpoint}?page=${header['x-page']}`).reply(response, body, header);
};
- const mountWrapper = () => {
+ const createWrapper = ({ propsData = {} }) => {
store = ClusterStore(entryData);
- wrapper = mount(Clusters, { store });
+ wrapper = mount(Clusters, { propsData, provide: provideData, store, stubs: { GlTable } });
return axios.waitForAll();
};
@@ -57,7 +70,7 @@ describe('Clusters', () => {
mock = new MockAdapter(axios);
mockPollingApi(200, apiData, paginationHeader());
- return mountWrapper();
+ return createWrapper({});
});
afterEach(() => {
@@ -70,7 +83,6 @@ describe('Clusters', () => {
describe('when data is loading', () => {
beforeEach(() => {
wrapper.vm.$store.state.loadingClusters = true;
- return wrapper.vm.$nextTick();
});
it('displays a loader instead of the table while loading', () => {
@@ -79,23 +91,29 @@ describe('Clusters', () => {
});
});
- it('displays a table component', () => {
- expect(findTable().exists()).toBe(true);
+ describe('when clusters are present', () => {
+ it('displays a table component', () => {
+ expect(findTable().exists()).toBe(true);
+ });
});
- it('renders the correct table headers', () => {
- const tableHeaders = wrapper.vm.fields;
- const headers = findTable().findAll('th');
-
- expect(headers.length).toBe(tableHeaders.length);
-
- tableHeaders.forEach((headerText, i) =>
- expect(headers.at(i).text()).toEqual(headerText.label),
- );
+ describe('when there are no clusters', () => {
+ beforeEach(() => {
+ wrapper.vm.$store.state.totalClusters = 0;
+ });
+ it('should render empty state', () => {
+ expect(findEmptyState().exists()).toBe(true);
+ });
});
- it('should stack on smaller devices', () => {
- expect(findTable().classes()).toContain('b-table-stacked-md');
+ describe('when is loaded as a child component', () => {
+ beforeEach(() => {
+ createWrapper({ limit: 6 });
+ });
+
+ it("shouldn't render pagination buttons", () => {
+ expect(findPaginatedButtons().exists()).toBe(false);
+ });
});
});
@@ -240,7 +258,7 @@ describe('Clusters', () => {
beforeEach(() => {
mockPollingApi(200, apiData, paginationHeader(totalFirstPage, perPage, 1));
- return mountWrapper();
+ return createWrapper({});
});
it('should load to page 1 with header values', () => {
diff --git a/spec/frontend/clusters_list/components/clusters_view_all_spec.js b/spec/frontend/clusters_list/components/clusters_view_all_spec.js
new file mode 100644
index 00000000000..6ef56beddee
--- /dev/null
+++ b/spec/frontend/clusters_list/components/clusters_view_all_spec.js
@@ -0,0 +1,243 @@
+import { GlCard, GlLoadingIcon, GlButton, GlSprintf, GlBadge } from '@gitlab/ui';
+import { createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ClustersViewAll from '~/clusters_list/components/clusters_view_all.vue';
+import Agents from '~/clusters_list/components/agents.vue';
+import Clusters from '~/clusters_list/components/clusters.vue';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import {
+ AGENT,
+ CERTIFICATE_BASED,
+ AGENT_CARD_INFO,
+ CERTIFICATE_BASED_CARD_INFO,
+ MAX_CLUSTERS_LIST,
+ INSTALL_AGENT_MODAL_ID,
+} from '~/clusters_list/constants';
+import { sprintf } from '~/locale';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+const addClusterPath = '/path/to/add/cluster';
+const defaultBranchName = 'default-branch';
+
+describe('ClustersViewAllComponent', () => {
+ let wrapper;
+
+ const event = {
+ preventDefault: jest.fn(),
+ };
+
+ const propsData = {
+ defaultBranchName,
+ };
+
+ const provideData = {
+ addClusterPath,
+ };
+
+ const entryData = {
+ loadingClusters: false,
+ totalClusters: 0,
+ };
+
+ const findCards = () => wrapper.findAllComponents(GlCard);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findAgentsComponent = () => wrapper.findComponent(Agents);
+ const findClustersComponent = () => wrapper.findComponent(Clusters);
+ const findCardsContainer = () => wrapper.findByTestId('clusters-cards-container');
+ const findAgentCardTitle = () => wrapper.findByTestId('agent-card-title');
+ const findRecommendedBadge = () => wrapper.findComponent(GlBadge);
+ const findClustersCardTitle = () => wrapper.findByTestId('clusters-card-title');
+ const findFooterButton = (line) => findCards().at(line).findComponent(GlButton);
+
+ const createStore = (initialState) =>
+ new Vuex.Store({
+ state: initialState,
+ });
+
+ const createWrapper = ({ initialState }) => {
+ wrapper = shallowMountExtended(ClustersViewAll, {
+ localVue,
+ store: createStore(initialState),
+ propsData,
+ provide: provideData,
+ directives: {
+ GlModalDirective: createMockDirective(),
+ },
+ stubs: { GlCard, GlSprintf },
+ });
+ };
+
+ beforeEach(() => {
+ createWrapper({ initialState: entryData });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('when agents and clusters are not loaded', () => {
+ const initialState = {
+ loadingClusters: true,
+ totalClusters: 0,
+ };
+ beforeEach(() => {
+ createWrapper({ initialState });
+ });
+
+ it('should show the loading icon', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+ });
+
+ describe('when both agents and clusters are loaded', () => {
+ beforeEach(() => {
+ findAgentsComponent().vm.$emit('onAgentsLoad', 6);
+ });
+
+ it("shouldn't show the loading icon", () => {
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+
+ it('should make content visible', () => {
+ expect(findCardsContainer().isVisible()).toBe(true);
+ });
+
+ it('should render 2 cards', () => {
+ expect(findCards().length).toBe(2);
+ });
+ });
+
+ describe('agents card', () => {
+ it('should show recommended badge', () => {
+ expect(findRecommendedBadge().exists()).toBe(true);
+ });
+
+ it('should render Agents component', () => {
+ expect(findAgentsComponent().exists()).toBe(true);
+ });
+
+ it('should pass the limit prop', () => {
+ expect(findAgentsComponent().props('limit')).toBe(MAX_CLUSTERS_LIST);
+ });
+
+ it('should pass the default-branch-name prop', () => {
+ expect(findAgentsComponent().props('defaultBranchName')).toBe(defaultBranchName);
+ });
+
+ describe('when there are no agents', () => {
+ it('should show the empty title', () => {
+ expect(findAgentCardTitle().text()).toBe(AGENT_CARD_INFO.emptyTitle);
+ });
+
+ it('should show install new Agent button in the footer', () => {
+ expect(findFooterButton(0).exists()).toBe(true);
+ });
+
+ it('should render correct modal id for the agent link', () => {
+ const binding = getBinding(findFooterButton(0).element, 'gl-modal-directive');
+
+ expect(binding.value).toBe(INSTALL_AGENT_MODAL_ID);
+ });
+ });
+
+ describe('when the agents are present', () => {
+ const findFooterLink = () => wrapper.findByTestId('agents-tab-footer-link');
+ const agentsNumber = 7;
+
+ beforeEach(() => {
+ findAgentsComponent().vm.$emit('onAgentsLoad', agentsNumber);
+ });
+
+ it('should show the correct title', () => {
+ expect(findAgentCardTitle().text()).toBe(
+ sprintf(AGENT_CARD_INFO.title, { number: MAX_CLUSTERS_LIST, total: agentsNumber }),
+ );
+ });
+
+ it('should show the link to the Agents tab in the footer', () => {
+ expect(findFooterLink().exists()).toBe(true);
+ expect(findFooterLink().text()).toBe(
+ sprintf(AGENT_CARD_INFO.footerText, { number: agentsNumber }),
+ );
+ expect(findFooterLink().attributes('href')).toBe(`?tab=${AGENT}`);
+ });
+
+ describe('when clicking on the footer link', () => {
+ beforeEach(() => {
+ findFooterLink().vm.$emit('click', event);
+ });
+
+ it('should trigger tab change', () => {
+ expect(wrapper.emitted('changeTab')).toEqual([[AGENT]]);
+ });
+ });
+ });
+ });
+
+ describe('clusters tab', () => {
+ it('should pass the limit prop', () => {
+ expect(findClustersComponent().props('limit')).toBe(MAX_CLUSTERS_LIST);
+ });
+
+ it('should pass the is-child-component prop', () => {
+ expect(findClustersComponent().props('isChildComponent')).toBe(true);
+ });
+
+ describe('when there are no clusters', () => {
+ it('should show the empty title', () => {
+ expect(findClustersCardTitle().text()).toBe(CERTIFICATE_BASED_CARD_INFO.emptyTitle);
+ });
+
+ it('should show install new Agent button in the footer', () => {
+ expect(findFooterButton(1).exists()).toBe(true);
+ });
+
+ it('should render correct href for the button in the footer', () => {
+ expect(findFooterButton(1).attributes('href')).toBe(addClusterPath);
+ });
+ });
+
+ describe('when the clusters are present', () => {
+ const findFooterLink = () => wrapper.findByTestId('clusters-tab-footer-link');
+
+ const clustersNumber = 7;
+ const initialState = {
+ loadingClusters: false,
+ totalClusters: clustersNumber,
+ };
+
+ beforeEach(() => {
+ createWrapper({ initialState });
+ });
+
+ it('should show the correct title', () => {
+ expect(findClustersCardTitle().text()).toBe(
+ sprintf(CERTIFICATE_BASED_CARD_INFO.title, {
+ number: MAX_CLUSTERS_LIST,
+ total: clustersNumber,
+ }),
+ );
+ });
+
+ it('should show the link to the Clusters tab in the footer', () => {
+ expect(findFooterLink().exists()).toBe(true);
+ expect(findFooterLink().text()).toBe(
+ sprintf(CERTIFICATE_BASED_CARD_INFO.footerText, { number: clustersNumber }),
+ );
+ });
+
+ describe('when clicking on the footer link', () => {
+ beforeEach(() => {
+ findFooterLink().vm.$emit('click', event);
+ });
+
+ it('should trigger tab change', () => {
+ expect(wrapper.emitted('changeTab')).toEqual([[CERTIFICATE_BASED]]);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/clusters_list/components/install_agent_modal_spec.js b/spec/frontend/clusters_list/components/install_agent_modal_spec.js
index 98ca5e05b3f..6c2ea45b99b 100644
--- a/spec/frontend/clusters_list/components/install_agent_modal_spec.js
+++ b/spec/frontend/clusters_list/components/install_agent_modal_spec.js
@@ -3,7 +3,8 @@ import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import AvailableAgentsDropdown from '~/clusters_list/components/available_agents_dropdown.vue';
import InstallAgentModal from '~/clusters_list/components/install_agent_modal.vue';
-import { I18N_INSTALL_AGENT_MODAL } from '~/clusters_list/constants';
+import { I18N_INSTALL_AGENT_MODAL, MAX_LIST_COUNT } from '~/clusters_list/constants';
+import getAgentsQuery from '~/clusters_list/graphql/queries/get_agents.query.graphql';
import createAgentMutation from '~/clusters_list/graphql/mutations/create_agent.mutation.graphql';
import createAgentTokenMutation from '~/clusters_list/graphql/mutations/create_agent_token.mutation.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -14,12 +15,17 @@ import {
createAgentErrorResponse,
createAgentTokenResponse,
createAgentTokenErrorResponse,
+ getAgentResponse,
} from '../mocks/apollo';
import ModalStub from '../stubs';
const localVue = createLocalVue();
localVue.use(VueApollo);
+const projectPath = 'path/to/project';
+const defaultBranchName = 'default';
+const maxAgents = MAX_LIST_COUNT;
+
describe('InstallAgentModal', () => {
let wrapper;
let apolloProvider;
@@ -45,10 +51,15 @@ describe('InstallAgentModal', () => {
const createWrapper = () => {
const provide = {
- projectPath: 'path/to/project',
+ projectPath,
kasAddress: 'kas.example.com',
};
+ const propsData = {
+ defaultBranchName,
+ maxAgents,
+ };
+
wrapper = shallowMount(InstallAgentModal, {
attachTo: document.body,
stubs: {
@@ -57,11 +68,26 @@ describe('InstallAgentModal', () => {
localVue,
apolloProvider,
provide,
+ propsData,
+ });
+ };
+
+ const writeQuery = () => {
+ apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: getAgentsQuery,
+ variables: {
+ projectPath,
+ defaultBranchName,
+ first: MAX_LIST_COUNT,
+ last: null,
+ },
+ data: getAgentResponse.data,
});
};
const mockSelectedAgentResponse = () => {
createWrapper();
+ writeQuery();
wrapper.vm.setAgentName('agent-name');
findActionButton().vm.$emit('click');
@@ -95,7 +121,7 @@ describe('InstallAgentModal', () => {
it('renders a disabled next button', () => {
expect(findActionButton().isVisible()).toBe(true);
- expect(findActionButton().text()).toBe(i18n.next);
+ expect(findActionButton().text()).toBe(i18n.registerAgentButton);
expectDisabledAttribute(findActionButton(), true);
});
});
@@ -126,7 +152,7 @@ describe('InstallAgentModal', () => {
it('creates an agent and token', () => {
expect(createAgentHandler).toHaveBeenCalledWith({
- input: { name: 'agent-name', projectPath: 'path/to/project' },
+ input: { name: 'agent-name', projectPath },
});
expect(createAgentTokenHandler).toHaveBeenCalledWith({
@@ -134,9 +160,9 @@ describe('InstallAgentModal', () => {
});
});
- it('renders a done button', () => {
+ it('renders a close button', () => {
expect(findActionButton().isVisible()).toBe(true);
- expect(findActionButton().text()).toBe(i18n.done);
+ expect(findActionButton().text()).toBe(i18n.close);
expectDisabledAttribute(findActionButton(), false);
});
diff --git a/spec/frontend/clusters_list/mocks/apollo.js b/spec/frontend/clusters_list/mocks/apollo.js
index 27b71a0d4b5..1a7ef84a6d9 100644
--- a/spec/frontend/clusters_list/mocks/apollo.js
+++ b/spec/frontend/clusters_list/mocks/apollo.js
@@ -1,8 +1,29 @@
+const agent = {
+ id: 'agent-id',
+ name: 'agent-name',
+ webPath: 'agent-webPath',
+};
+const token = {
+ id: 'token-id',
+ lastUsedAt: null,
+};
+const tokens = {
+ nodes: [token],
+};
+const pageInfo = {
+ endCursor: '',
+ hasNextPage: false,
+ hasPreviousPage: false,
+ startCursor: '',
+};
+const count = 1;
+
export const createAgentResponse = {
data: {
createClusterAgent: {
clusterAgent: {
- id: 'agent-id',
+ ...agent,
+ tokens,
},
errors: [],
},
@@ -13,7 +34,8 @@ export const createAgentErrorResponse = {
data: {
createClusterAgent: {
clusterAgent: {
- id: 'agent-id',
+ ...agent,
+ tokens,
},
errors: ['could not create agent'],
},
@@ -23,9 +45,7 @@ export const createAgentErrorResponse = {
export const createAgentTokenResponse = {
data: {
clusterAgentTokenCreate: {
- token: {
- id: 'token-id',
- },
+ token,
secret: 'mock-agent-token',
errors: [],
},
@@ -35,11 +55,22 @@ export const createAgentTokenResponse = {
export const createAgentTokenErrorResponse = {
data: {
clusterAgentTokenCreate: {
- token: {
- id: 'token-id',
- },
+ token,
secret: 'mock-agent-token',
errors: ['could not create agent token'],
},
},
};
+
+export const getAgentResponse = {
+ data: {
+ project: {
+ clusterAgents: { nodes: [{ ...agent, tokens }], pageInfo, count },
+ repository: {
+ tree: {
+ trees: { nodes: [{ ...agent, path: null }], pageInfo },
+ },
+ },
+ },
+ },
+};
diff --git a/spec/frontend/clusters_list/store/mutations_spec.js b/spec/frontend/clusters_list/store/mutations_spec.js
index c0fe634a703..ae264eee449 100644
--- a/spec/frontend/clusters_list/store/mutations_spec.js
+++ b/spec/frontend/clusters_list/store/mutations_spec.js
@@ -26,7 +26,7 @@ describe('Admin statistics panel mutations', () => {
expect(state.clusters).toBe(apiData.clusters);
expect(state.clustersPerPage).toBe(paginationInformation.perPage);
expect(state.hasAncestorClusters).toBe(apiData.has_ancestor_clusters);
- expect(state.totalCulsters).toBe(paginationInformation.total);
+ expect(state.totalClusters).toBe(paginationInformation.total);
});
});
@@ -57,4 +57,12 @@ describe('Admin statistics panel mutations', () => {
expect(state.page).toBe(123);
});
});
+
+ describe(`${types.SET_CLUSTERS_PER_PAGE}`, () => {
+ it('changes clustersPerPage value', () => {
+ mutations[types.SET_CLUSTERS_PER_PAGE](state, 123);
+
+ expect(state.clustersPerPage).toBe(123);
+ });
+ });
});
diff --git a/spec/frontend/commit/pipelines/pipelines_table_spec.js b/spec/frontend/commit/pipelines/pipelines_table_spec.js
index 17f7be9d1d7..c376b58cc72 100644
--- a/spec/frontend/commit/pipelines/pipelines_table_spec.js
+++ b/spec/frontend/commit/pipelines/pipelines_table_spec.js
@@ -1,4 +1,4 @@
-import { GlEmptyState, GlLoadingIcon, GlModal, GlTable } from '@gitlab/ui';
+import { GlEmptyState, GlLoadingIcon, GlModal, GlTableLite } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import fixture from 'test_fixtures/pipelines/pipelines.json';
@@ -6,8 +6,13 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
import PipelinesTable from '~/commit/pipelines/pipelines_table.vue';
+import { TOAST_MESSAGE } from '~/pipelines/constants';
import axios from '~/lib/utils/axios_utils';
+const $toast = {
+ show: jest.fn(),
+};
+
describe('Pipelines table in Commits and Merge requests', () => {
let wrapper;
let pipeline;
@@ -17,7 +22,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
const findRunPipelineBtnMobile = () => wrapper.findByTestId('run_pipeline_button_mobile');
const findLoadingState = () => wrapper.findComponent(GlLoadingIcon);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
- const findTable = () => wrapper.findComponent(GlTable);
+ const findTable = () => wrapper.findComponent(GlTableLite);
const findTableRows = () => wrapper.findAllByTestId('pipeline-table-row');
const findModal = () => wrapper.findComponent(GlModal);
@@ -30,6 +35,9 @@ describe('Pipelines table in Commits and Merge requests', () => {
errorStateSvgPath: 'foo',
...props,
},
+ mocks: {
+ $toast,
+ },
}),
);
};
@@ -178,6 +186,12 @@ describe('Pipelines table in Commits and Merge requests', () => {
await waitForPromises();
});
+ it('displays a toast message during pipeline creation', async () => {
+ await findRunPipelineBtn().trigger('click');
+
+ expect($toast.show).toHaveBeenCalledWith(TOAST_MESSAGE);
+ });
+
it('on desktop, shows a loading button', async () => {
await findRunPipelineBtn().trigger('click');
diff --git a/spec/frontend/confirm_modal_spec.js b/spec/frontend/confirm_modal_spec.js
index 8a12ff3a01f..5e5345cbd2b 100644
--- a/spec/frontend/confirm_modal_spec.js
+++ b/spec/frontend/confirm_modal_spec.js
@@ -72,7 +72,7 @@ describe('ConfirmModal', () => {
it('starts with only JsHooks', () => {
expect(findJsHooks()).toHaveLength(buttons.length);
- expect(findModal()).not.toExist();
+ expect(findModal()).toBe(null);
});
describe('when button clicked', () => {
@@ -87,7 +87,7 @@ describe('ConfirmModal', () => {
describe('GlModal', () => {
it('is rendered', () => {
- expect(findModal()).toExist();
+ expect(findModal()).not.toBe(null);
expect(modalIsHidden()).toBe(false);
});
diff --git a/spec/frontend/content_editor/components/content_editor_alert_spec.js b/spec/frontend/content_editor/components/content_editor_alert_spec.js
new file mode 100644
index 00000000000..2ddcd8f024e
--- /dev/null
+++ b/spec/frontend/content_editor/components/content_editor_alert_spec.js
@@ -0,0 +1,60 @@
+import { GlAlert } from '@gitlab/ui';
+import { nextTick } from 'vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ContentEditorAlert from '~/content_editor/components/content_editor_alert.vue';
+import EditorStateObserver from '~/content_editor/components/editor_state_observer.vue';
+import { createTestEditor, emitEditorEvent } from '../test_utils';
+
+describe('content_editor/components/content_editor_alert', () => {
+ let wrapper;
+ let tiptapEditor;
+
+ const findErrorAlert = () => wrapper.findComponent(GlAlert);
+
+ const createWrapper = async () => {
+ tiptapEditor = createTestEditor();
+
+ wrapper = shallowMountExtended(ContentEditorAlert, {
+ provide: {
+ tiptapEditor,
+ },
+ stubs: {
+ EditorStateObserver,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it.each`
+ variant | message
+ ${'danger'} | ${'An error occurred'}
+ ${'warning'} | ${'A warning'}
+ `(
+ 'renders error when content editor emits an error event for variant: $variant',
+ async ({ message, variant }) => {
+ createWrapper();
+
+ await emitEditorEvent({ tiptapEditor, event: 'alert', params: { message, variant } });
+
+ expect(findErrorAlert().text()).toBe(message);
+ expect(findErrorAlert().attributes().variant).toBe(variant);
+ },
+ );
+
+ it('allows dismissing the error', async () => {
+ const message = 'error message';
+
+ createWrapper();
+
+ await emitEditorEvent({ tiptapEditor, event: 'alert', params: { message } });
+
+ findErrorAlert().vm.$emit('dismiss');
+
+ await nextTick();
+
+ expect(findErrorAlert().exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/content_editor/components/content_editor_error_spec.js b/spec/frontend/content_editor/components/content_editor_error_spec.js
deleted file mode 100644
index 8723fb5a338..00000000000
--- a/spec/frontend/content_editor/components/content_editor_error_spec.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import { GlAlert } from '@gitlab/ui';
-import { nextTick } from 'vue';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import ContentEditorError from '~/content_editor/components/content_editor_error.vue';
-import EditorStateObserver from '~/content_editor/components/editor_state_observer.vue';
-import { createTestEditor, emitEditorEvent } from '../test_utils';
-
-describe('content_editor/components/content_editor_error', () => {
- let wrapper;
- let tiptapEditor;
-
- const findErrorAlert = () => wrapper.findComponent(GlAlert);
-
- const createWrapper = async () => {
- tiptapEditor = createTestEditor();
-
- wrapper = shallowMountExtended(ContentEditorError, {
- provide: {
- tiptapEditor,
- },
- stubs: {
- EditorStateObserver,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders error when content editor emits an error event', async () => {
- const error = 'error message';
-
- createWrapper();
-
- await emitEditorEvent({ tiptapEditor, event: 'error', params: { error } });
-
- expect(findErrorAlert().text()).toBe(error);
- });
-
- it('allows dismissing the error', async () => {
- const error = 'error message';
-
- createWrapper();
-
- await emitEditorEvent({ tiptapEditor, event: 'error', params: { error } });
-
- findErrorAlert().vm.$emit('dismiss');
-
- await nextTick();
-
- expect(findErrorAlert().exists()).toBe(false);
- });
-});
diff --git a/spec/frontend/content_editor/components/content_editor_spec.js b/spec/frontend/content_editor/components/content_editor_spec.js
index 3d1ef03083d..9a772c41e52 100644
--- a/spec/frontend/content_editor/components/content_editor_spec.js
+++ b/spec/frontend/content_editor/components/content_editor_spec.js
@@ -3,7 +3,7 @@ import { EditorContent } from '@tiptap/vue-2';
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ContentEditor from '~/content_editor/components/content_editor.vue';
-import ContentEditorError from '~/content_editor/components/content_editor_error.vue';
+import ContentEditorAlert from '~/content_editor/components/content_editor_alert.vue';
import ContentEditorProvider from '~/content_editor/components/content_editor_provider.vue';
import EditorStateObserver from '~/content_editor/components/editor_state_observer.vue';
import FormattingBubbleMenu from '~/content_editor/components/formatting_bubble_menu.vue';
@@ -111,10 +111,10 @@ describe('ContentEditor', () => {
]);
});
- it('renders content_editor_error component', () => {
+ it('renders content_editor_alert component', () => {
createWrapper();
- expect(wrapper.findComponent(ContentEditorError).exists()).toBe(true);
+ expect(wrapper.findComponent(ContentEditorAlert).exists()).toBe(true);
});
describe('when loading content', () => {
diff --git a/spec/frontend/content_editor/components/wrappers/table_cell_base_spec.js b/spec/frontend/content_editor/components/wrappers/table_cell_base_spec.js
index e48f59f6d9c..6017a145a87 100644
--- a/spec/frontend/content_editor/components/wrappers/table_cell_base_spec.js
+++ b/spec/frontend/content_editor/components/wrappers/table_cell_base_spec.js
@@ -11,13 +11,13 @@ jest.mock('prosemirror-tables');
describe('content/components/wrappers/table_cell_base', () => {
let wrapper;
let editor;
- let getPos;
+ let node;
const createWrapper = async (propsData = { cellType: 'td' }) => {
wrapper = shallowMountExtended(TableCellBaseWrapper, {
propsData: {
editor,
- getPos,
+ node,
...propsData,
},
});
@@ -36,7 +36,7 @@ describe('content/components/wrappers/table_cell_base', () => {
const setCurrentPositionInCell = () => {
const { $cursor } = editor.state.selection;
- getPos.mockReturnValue($cursor.pos - $cursor.parentOffset - 1);
+ jest.spyOn($cursor, 'node').mockReturnValue(node);
};
const mockDropdownHide = () => {
/*
@@ -48,7 +48,7 @@ describe('content/components/wrappers/table_cell_base', () => {
};
beforeEach(() => {
- getPos = jest.fn();
+ node = {};
editor = createTestEditor({});
});
diff --git a/spec/frontend/content_editor/components/wrappers/table_cell_body_spec.js b/spec/frontend/content_editor/components/wrappers/table_cell_body_spec.js
index 5d26c44ba03..2aefbc77545 100644
--- a/spec/frontend/content_editor/components/wrappers/table_cell_body_spec.js
+++ b/spec/frontend/content_editor/components/wrappers/table_cell_body_spec.js
@@ -6,19 +6,19 @@ import { createTestEditor } from '../../test_utils';
describe('content/components/wrappers/table_cell_body', () => {
let wrapper;
let editor;
- let getPos;
+ let node;
const createWrapper = async () => {
wrapper = shallowMount(TableCellBodyWrapper, {
propsData: {
editor,
- getPos,
+ node,
},
});
};
beforeEach(() => {
- getPos = jest.fn();
+ node = {};
editor = createTestEditor({});
});
@@ -30,7 +30,7 @@ describe('content/components/wrappers/table_cell_body', () => {
createWrapper();
expect(wrapper.findComponent(TableCellBaseWrapper).props()).toEqual({
editor,
- getPos,
+ node,
cellType: 'td',
});
});
diff --git a/spec/frontend/content_editor/components/wrappers/table_cell_header_spec.js b/spec/frontend/content_editor/components/wrappers/table_cell_header_spec.js
index e561191418d..e48df8734a6 100644
--- a/spec/frontend/content_editor/components/wrappers/table_cell_header_spec.js
+++ b/spec/frontend/content_editor/components/wrappers/table_cell_header_spec.js
@@ -6,19 +6,19 @@ import { createTestEditor } from '../../test_utils';
describe('content/components/wrappers/table_cell_header', () => {
let wrapper;
let editor;
- let getPos;
+ let node;
const createWrapper = async () => {
wrapper = shallowMount(TableCellHeaderWrapper, {
propsData: {
editor,
- getPos,
+ node,
},
});
};
beforeEach(() => {
- getPos = jest.fn();
+ node = {};
editor = createTestEditor({});
});
@@ -30,7 +30,7 @@ describe('content/components/wrappers/table_cell_header', () => {
createWrapper();
expect(wrapper.findComponent(TableCellBaseWrapper).props()).toEqual({
editor,
- getPos,
+ node,
cellType: 'th',
});
});
diff --git a/spec/frontend/content_editor/extensions/attachment_spec.js b/spec/frontend/content_editor/extensions/attachment_spec.js
index d4f05a25bd6..d2d2cd98a78 100644
--- a/spec/frontend/content_editor/extensions/attachment_spec.js
+++ b/spec/frontend/content_editor/extensions/attachment_spec.js
@@ -74,10 +74,10 @@ describe('content_editor/extensions/attachment', () => {
});
it.each`
- eventType | propName | eventData | output
- ${'paste'} | ${'handlePaste'} | ${{ clipboardData: { files: [attachmentFile] } }} | ${true}
- ${'paste'} | ${'handlePaste'} | ${{ clipboardData: { files: [] } }} | ${undefined}
- ${'drop'} | ${'handleDrop'} | ${{ dataTransfer: { files: [attachmentFile] } }} | ${true}
+ eventType | propName | eventData | output
+ ${'paste'} | ${'handlePaste'} | ${{ clipboardData: { getData: jest.fn(), files: [attachmentFile] } }} | ${true}
+ ${'paste'} | ${'handlePaste'} | ${{ clipboardData: { getData: jest.fn(), files: [] } }} | ${undefined}
+ ${'drop'} | ${'handleDrop'} | ${{ dataTransfer: { getData: jest.fn(), files: [attachmentFile] } }} | ${true}
`('handles $eventType properly', ({ eventType, propName, eventData, output }) => {
const event = Object.assign(new Event(eventType), eventData);
const handled = tiptapEditor.view.someProp(propName, (eventHandler) => {
@@ -157,11 +157,11 @@ describe('content_editor/extensions/attachment', () => {
});
});
- it('emits an error event that includes an error message', (done) => {
+ it('emits an alert event that includes an error message', (done) => {
tiptapEditor.commands.uploadAttachment({ file: imageFile });
- tiptapEditor.on('error', ({ error }) => {
- expect(error).toBe('An error occurred while uploading the image. Please try again.');
+ tiptapEditor.on('alert', ({ message }) => {
+ expect(message).toBe('An error occurred while uploading the image. Please try again.');
done();
});
});
@@ -233,11 +233,11 @@ describe('content_editor/extensions/attachment', () => {
});
});
- it('emits an error event that includes an error message', (done) => {
+ it('emits an alert event that includes an error message', (done) => {
tiptapEditor.commands.uploadAttachment({ file: attachmentFile });
- tiptapEditor.on('error', ({ error }) => {
- expect(error).toBe('An error occurred while uploading the file. Please try again.');
+ tiptapEditor.on('alert', ({ message }) => {
+ expect(message).toBe('An error occurred while uploading the file. Please try again.');
done();
});
});
diff --git a/spec/frontend/content_editor/extensions/blockquote_spec.js b/spec/frontend/content_editor/extensions/blockquote_spec.js
index c5b5044352d..1644647ba69 100644
--- a/spec/frontend/content_editor/extensions/blockquote_spec.js
+++ b/spec/frontend/content_editor/extensions/blockquote_spec.js
@@ -1,19 +1,37 @@
-import { multilineInputRegex } from '~/content_editor/extensions/blockquote';
+import Blockquote from '~/content_editor/extensions/blockquote';
+import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
describe('content_editor/extensions/blockquote', () => {
- describe.each`
- input | matches
- ${'>>> '} | ${true}
- ${' >>> '} | ${true}
- ${'\t>>> '} | ${true}
- ${'>> '} | ${false}
- ${'>>>x '} | ${false}
- ${'> '} | ${false}
- `('multilineInputRegex', ({ input, matches }) => {
- it(`${matches ? 'matches' : 'does not match'}: "${input}"`, () => {
- const match = new RegExp(multilineInputRegex).test(input);
+ let tiptapEditor;
+ let doc;
+ let p;
+ let blockquote;
- expect(match).toBe(matches);
- });
+ beforeEach(() => {
+ tiptapEditor = createTestEditor({ extensions: [Blockquote] });
+
+ ({
+ builders: { doc, p, blockquote },
+ } = createDocBuilder({
+ tiptapEditor,
+ names: {
+ blockquote: { nodeType: Blockquote.name },
+ },
+ }));
+ });
+
+ it.each`
+ input | insertedNode
+ ${'>>> '} | ${() => blockquote({ multiline: true }, p())}
+ ${'> '} | ${() => blockquote(p())}
+ ${' >>> '} | ${() => blockquote({ multiline: true }, p())}
+ ${'>> '} | ${() => p()}
+ ${'>>>x '} | ${() => p()}
+ `('with input=$input, then should insert a $insertedNode', ({ input, insertedNode }) => {
+ const expectedDoc = doc(insertedNode());
+
+ triggerNodeInputRule({ tiptapEditor, inputRuleText: input });
+
+ expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
});
});
diff --git a/spec/frontend/content_editor/extensions/emoji_spec.js b/spec/frontend/content_editor/extensions/emoji_spec.js
index c1b8dc9bdbb..939c46e991a 100644
--- a/spec/frontend/content_editor/extensions/emoji_spec.js
+++ b/spec/frontend/content_editor/extensions/emoji_spec.js
@@ -1,6 +1,6 @@
import { initEmojiMock } from 'helpers/emoji';
import Emoji from '~/content_editor/extensions/emoji';
-import { createTestEditor, createDocBuilder } from '../test_utils';
+import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
describe('content_editor/extensions/emoji', () => {
let tiptapEditor;
@@ -28,18 +28,16 @@ describe('content_editor/extensions/emoji', () => {
describe('when typing a valid emoji input rule', () => {
it('inserts an emoji node', () => {
- const { view } = tiptapEditor;
- const { selection } = view.state;
const expectedDoc = doc(
p(
' ',
emoji({ moji: 'â¤', name: 'heart', title: 'heavy black heart', unicodeVersion: '1.1' }),
),
);
- // Triggers the event handler that input rules listen to
- view.someProp('handleTextInput', (f) => f(view, selection.from, selection.to, ':heart:'));
- expect(eq(tiptapEditor.state.doc, expectedDoc)).toBe(true);
+ triggerNodeInputRule({ tiptapEditor, inputRuleText: ':heart:' });
+
+ expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
});
});
diff --git a/spec/frontend/content_editor/extensions/frontmatter_spec.js b/spec/frontend/content_editor/extensions/frontmatter_spec.js
new file mode 100644
index 00000000000..517f6947b9a
--- /dev/null
+++ b/spec/frontend/content_editor/extensions/frontmatter_spec.js
@@ -0,0 +1,30 @@
+import Frontmatter from '~/content_editor/extensions/frontmatter';
+import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
+
+describe('content_editor/extensions/frontmatter', () => {
+ let tiptapEditor;
+ let doc;
+ let p;
+
+ beforeEach(() => {
+ tiptapEditor = createTestEditor({ extensions: [Frontmatter] });
+
+ ({
+ builders: { doc, p },
+ } = createDocBuilder({
+ tiptapEditor,
+ names: {
+ frontmatter: { nodeType: Frontmatter.name },
+ },
+ }));
+ });
+
+ it('does not insert a frontmatter block when executing code block input rule', () => {
+ const expectedDoc = doc(p(''));
+ const inputRuleText = '``` ';
+
+ triggerNodeInputRule({ tiptapEditor, inputRuleText });
+
+ expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
+ });
+});
diff --git a/spec/frontend/content_editor/extensions/horizontal_rule_spec.js b/spec/frontend/content_editor/extensions/horizontal_rule_spec.js
index a1bc7f0e8ed..322c04a42e1 100644
--- a/spec/frontend/content_editor/extensions/horizontal_rule_spec.js
+++ b/spec/frontend/content_editor/extensions/horizontal_rule_spec.js
@@ -1,20 +1,39 @@
-import { hrInputRuleRegExp } from '~/content_editor/extensions/horizontal_rule';
+import HorizontalRule from '~/content_editor/extensions/horizontal_rule';
+import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
describe('content_editor/extensions/horizontal_rule', () => {
- describe.each`
- input | matches
- ${'---'} | ${true}
- ${'--'} | ${false}
- ${'---x'} | ${false}
- ${' ---x'} | ${false}
- ${' --- '} | ${false}
- ${'x---x'} | ${false}
- ${'x---'} | ${false}
- `('hrInputRuleRegExp', ({ input, matches }) => {
- it(`${matches ? 'matches' : 'does not match'}: "${input}"`, () => {
- const match = new RegExp(hrInputRuleRegExp).test(input);
+ let tiptapEditor;
+ let doc;
+ let p;
+ let horizontalRule;
- expect(match).toBe(matches);
- });
+ beforeEach(() => {
+ tiptapEditor = createTestEditor({ extensions: [HorizontalRule] });
+
+ ({
+ builders: { doc, p, horizontalRule },
+ } = createDocBuilder({
+ tiptapEditor,
+ names: {
+ horizontalRule: { nodeType: HorizontalRule.name },
+ },
+ }));
+ });
+
+ it.each`
+ input | insertedNodes
+ ${'---'} | ${() => [p(), horizontalRule()]}
+ ${'--'} | ${() => [p()]}
+ ${'---x'} | ${() => [p()]}
+ ${' ---x'} | ${() => [p()]}
+ ${' --- '} | ${() => [p()]}
+ ${'x---x'} | ${() => [p()]}
+ ${'x---'} | ${() => [p()]}
+ `('with input=$input, then should insert a $insertedNode', ({ input, insertedNodes }) => {
+ const expectedDoc = doc(...insertedNodes());
+
+ triggerNodeInputRule({ tiptapEditor, inputRuleText: input });
+
+ expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
});
});
diff --git a/spec/frontend/content_editor/extensions/inline_diff_spec.js b/spec/frontend/content_editor/extensions/inline_diff_spec.js
index 63cdf665e7f..99c559a20b1 100644
--- a/spec/frontend/content_editor/extensions/inline_diff_spec.js
+++ b/spec/frontend/content_editor/extensions/inline_diff_spec.js
@@ -1,27 +1,43 @@
-import { inputRegexAddition, inputRegexDeletion } from '~/content_editor/extensions/inline_diff';
+import InlineDiff from '~/content_editor/extensions/inline_diff';
+import { createTestEditor, createDocBuilder, triggerMarkInputRule } from '../test_utils';
describe('content_editor/extensions/inline_diff', () => {
- describe.each`
- inputRegex | description | input | matches
- ${inputRegexAddition} | ${'inputRegexAddition'} | ${'hello{+world+}'} | ${true}
- ${inputRegexAddition} | ${'inputRegexAddition'} | ${'hello{+ world +}'} | ${true}
- ${inputRegexAddition} | ${'inputRegexAddition'} | ${'hello {+ world+}'} | ${true}
- ${inputRegexAddition} | ${'inputRegexAddition'} | ${'{+hello world +}'} | ${true}
- ${inputRegexAddition} | ${'inputRegexAddition'} | ${'{+hello with \nnewline+}'} | ${false}
- ${inputRegexAddition} | ${'inputRegexAddition'} | ${'{+open only'} | ${false}
- ${inputRegexAddition} | ${'inputRegexAddition'} | ${'close only+}'} | ${false}
- ${inputRegexDeletion} | ${'inputRegexDeletion'} | ${'hello{-world-}'} | ${true}
- ${inputRegexDeletion} | ${'inputRegexDeletion'} | ${'hello{- world -}'} | ${true}
- ${inputRegexDeletion} | ${'inputRegexDeletion'} | ${'hello {- world-}'} | ${true}
- ${inputRegexDeletion} | ${'inputRegexDeletion'} | ${'{-hello world -}'} | ${true}
- ${inputRegexDeletion} | ${'inputRegexDeletion'} | ${'{+hello with \nnewline+}'} | ${false}
- ${inputRegexDeletion} | ${'inputRegexDeletion'} | ${'{-open only'} | ${false}
- ${inputRegexDeletion} | ${'inputRegexDeletion'} | ${'close only-}'} | ${false}
- `('$description', ({ inputRegex, input, matches }) => {
- it(`${matches ? 'matches' : 'does not match'}: "${input}"`, () => {
- const match = new RegExp(inputRegex).test(input);
+ let tiptapEditor;
+ let doc;
+ let p;
+ let inlineDiff;
- expect(match).toBe(matches);
- });
+ beforeEach(() => {
+ tiptapEditor = createTestEditor({ extensions: [InlineDiff] });
+ ({
+ builders: { doc, p, inlineDiff },
+ } = createDocBuilder({
+ tiptapEditor,
+ names: {
+ inlineDiff: { markType: InlineDiff.name },
+ },
+ }));
+ });
+
+ it.each`
+ input | insertedNode
+ ${'hello{+world+}'} | ${() => p('hello', inlineDiff('world'))}
+ ${'hello{+ world +}'} | ${() => p('hello', inlineDiff(' world '))}
+ ${'{+hello with \nnewline+}'} | ${() => p('{+hello with newline+}')}
+ ${'{+open only'} | ${() => p('{+open only')}
+ ${'close only+}'} | ${() => p('close only+}')}
+ ${'hello{-world-}'} | ${() => p('hello', inlineDiff({ type: 'deletion' }, 'world'))}
+ ${'hello{- world -}'} | ${() => p('hello', inlineDiff({ type: 'deletion' }, ' world '))}
+ ${'hello {- world-}'} | ${() => p('hello ', inlineDiff({ type: 'deletion' }, ' world'))}
+ ${'{-hello world -}'} | ${() => p(inlineDiff({ type: 'deletion' }, 'hello world '))}
+ ${'{-hello with \nnewline-}'} | ${() => p('{-hello with newline-}')}
+ ${'{-open only'} | ${() => p('{-open only')}
+ ${'close only-}'} | ${() => p('close only-}')}
+ `('with input=$input, then should insert a $insertedNode', ({ input, insertedNode }) => {
+ const expectedDoc = doc(insertedNode());
+
+ triggerMarkInputRule({ tiptapEditor, inputRuleText: input });
+
+ expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
});
});
diff --git a/spec/frontend/content_editor/extensions/link_spec.js b/spec/frontend/content_editor/extensions/link_spec.js
index 026b2a06df3..ead898554d1 100644
--- a/spec/frontend/content_editor/extensions/link_spec.js
+++ b/spec/frontend/content_editor/extensions/link_spec.js
@@ -1,61 +1,46 @@
-import {
- markdownLinkSyntaxInputRuleRegExp,
- urlSyntaxRegExp,
- extractHrefFromMarkdownLink,
-} from '~/content_editor/extensions/link';
+import Link from '~/content_editor/extensions/link';
+import { createTestEditor, createDocBuilder, triggerMarkInputRule } from '../test_utils';
describe('content_editor/extensions/link', () => {
- describe.each`
- input | matches
- ${'[gitlab](https://gitlab.com)'} | ${true}
- ${'[documentation](readme.md)'} | ${true}
- ${'[link 123](readme.md)'} | ${true}
- ${'[link 123](read me.md)'} | ${true}
- ${'text'} | ${false}
- ${'documentation](readme.md'} | ${false}
- ${'https://www.google.com'} | ${false}
- `('markdownLinkSyntaxInputRuleRegExp', ({ input, matches }) => {
- it(`${matches ? 'matches' : 'does not match'} ${input}`, () => {
- const match = new RegExp(markdownLinkSyntaxInputRuleRegExp).exec(input);
-
- expect(Boolean(match?.groups.href)).toBe(matches);
- });
+ let tiptapEditor;
+ let doc;
+ let p;
+ let link;
+
+ beforeEach(() => {
+ tiptapEditor = createTestEditor({ extensions: [Link] });
+ ({
+ builders: { doc, p, link },
+ } = createDocBuilder({
+ tiptapEditor,
+ names: {
+ link: { markType: Link.name },
+ },
+ }));
});
- describe.each`
- input | matches
- ${'http://example.com '} | ${true}
- ${'https://example.com '} | ${true}
- ${'www.example.com '} | ${true}
- ${'example.com/ab.html '} | ${false}
- ${'text'} | ${false}
- ${' http://example.com '} | ${true}
- ${'https://www.google.com '} | ${true}
- `('urlSyntaxRegExp', ({ input, matches }) => {
- it(`${matches ? 'matches' : 'does not match'} ${input}`, () => {
- const match = new RegExp(urlSyntaxRegExp).exec(input);
-
- expect(Boolean(match?.groups.href)).toBe(matches);
- });
+ afterEach(() => {
+ tiptapEditor.destroy();
});
- describe('extractHrefFromMarkdownLink', () => {
- const input = '[gitlab](https://gitlab.com)';
- const href = 'https://gitlab.com';
- let match;
- let result;
-
- beforeEach(() => {
- match = new RegExp(markdownLinkSyntaxInputRuleRegExp).exec(input);
- result = extractHrefFromMarkdownLink(match);
- });
-
- it('extracts the url from a markdown link captured by markdownLinkSyntaxInputRuleRegExp', () => {
- expect(result).toEqual({ href });
- });
-
- it('makes sure that url text is the last capture group', () => {
- expect(match[match.length - 1]).toEqual('gitlab');
- });
+ it.each`
+ input | insertedNode
+ ${'[gitlab](https://gitlab.com)'} | ${() => p(link({ href: 'https://gitlab.com' }, 'gitlab'))}
+ ${'[documentation](readme.md)'} | ${() => p(link({ href: 'readme.md' }, 'documentation'))}
+ ${'[link 123](readme.md)'} | ${() => p(link({ href: 'readme.md' }, 'link 123'))}
+ ${'[link 123](read me.md)'} | ${() => p(link({ href: 'read me.md' }, 'link 123'))}
+ ${'text'} | ${() => p('text')}
+ ${'documentation](readme.md'} | ${() => p('documentation](readme.md')}
+ ${'http://example.com '} | ${() => p(link({ href: 'http://example.com' }, 'http://example.com'))}
+ ${'https://example.com '} | ${() => p(link({ href: 'https://example.com' }, 'https://example.com'))}
+ ${'www.example.com '} | ${() => p(link({ href: 'www.example.com' }, 'www.example.com'))}
+ ${'example.com/ab.html '} | ${() => p('example.com/ab.html')}
+ ${'https://www.google.com '} | ${() => p(link({ href: 'https://www.google.com' }, 'https://www.google.com'))}
+ `('with input=$input, then should insert a $insertedNode', ({ input, insertedNode }) => {
+ const expectedDoc = doc(insertedNode());
+
+ triggerMarkInputRule({ tiptapEditor, inputRuleText: input });
+
+ expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
});
});
diff --git a/spec/frontend/content_editor/extensions/math_inline_spec.js b/spec/frontend/content_editor/extensions/math_inline_spec.js
index 82eb85477de..abf10317b5a 100644
--- a/spec/frontend/content_editor/extensions/math_inline_spec.js
+++ b/spec/frontend/content_editor/extensions/math_inline_spec.js
@@ -1,5 +1,5 @@
import MathInline from '~/content_editor/extensions/math_inline';
-import { createTestEditor, createDocBuilder } from '../test_utils';
+import { createTestEditor, createDocBuilder, triggerMarkInputRule } from '../test_utils';
describe('content_editor/extensions/math_inline', () => {
let tiptapEditor;
@@ -26,16 +26,9 @@ describe('content_editor/extensions/math_inline', () => {
${'$`a^2`'} | ${() => p('$`a^2`')}
${'`a^2`$'} | ${() => p('`a^2`$')}
`('with input=$input, then should insert a $insertedNode', ({ input, insertedNode }) => {
- const { view } = tiptapEditor;
const expectedDoc = doc(insertedNode());
- tiptapEditor.chain().setContent(input).setTextSelection(0).run();
-
- const { state } = tiptapEditor;
- const { selection } = state;
-
- // Triggers the event handler that input rules listen to
- view.someProp('handleTextInput', (f) => f(view, selection.from, input.length + 1, input));
+ triggerMarkInputRule({ tiptapEditor, inputRuleText: input });
expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
});
diff --git a/spec/frontend/content_editor/extensions/table_of_contents_spec.js b/spec/frontend/content_editor/extensions/table_of_contents_spec.js
index 83818899c17..0ddd88b39fe 100644
--- a/spec/frontend/content_editor/extensions/table_of_contents_spec.js
+++ b/spec/frontend/content_editor/extensions/table_of_contents_spec.js
@@ -1,13 +1,17 @@
import TableOfContents from '~/content_editor/extensions/table_of_contents';
-import { createTestEditor, createDocBuilder } from '../test_utils';
+import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
-describe('content_editor/extensions/emoji', () => {
+describe('content_editor/extensions/table_of_contents', () => {
let tiptapEditor;
- let builders;
+ let doc;
+ let tableOfContents;
+ let p;
beforeEach(() => {
tiptapEditor = createTestEditor({ extensions: [TableOfContents] });
- ({ builders } = createDocBuilder({
+ ({
+ builders: { doc, p, tableOfContents },
+ } = createDocBuilder({
tiptapEditor,
names: { tableOfContents: { nodeType: TableOfContents.name } },
}));
@@ -15,20 +19,16 @@ describe('content_editor/extensions/emoji', () => {
it.each`
input | insertedNode
- ${'[[_TOC_]]'} | ${'tableOfContents'}
- ${'[TOC]'} | ${'tableOfContents'}
- ${'[toc]'} | ${'p'}
- ${'TOC'} | ${'p'}
- ${'[_TOC_]'} | ${'p'}
- ${'[[TOC]]'} | ${'p'}
+ ${'[[_TOC_]]'} | ${() => tableOfContents()}
+ ${'[TOC]'} | ${() => tableOfContents()}
+ ${'[toc]'} | ${() => p()}
+ ${'TOC'} | ${() => p()}
+ ${'[_TOC_]'} | ${() => p()}
+ ${'[[TOC]]'} | ${() => p()}
`('with input=$input, then should insert a $insertedNode', ({ input, insertedNode }) => {
- const { doc } = builders;
- const { view } = tiptapEditor;
- const { selection } = view.state;
- const expectedDoc = doc(builders[insertedNode]());
+ const expectedDoc = doc(insertedNode());
- // Triggers the event handler that input rules listen to
- view.someProp('handleTextInput', (f) => f(view, selection.from, selection.to, input));
+ triggerNodeInputRule({ tiptapEditor, inputRuleText: input });
expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
});
diff --git a/spec/frontend/content_editor/extensions/table_spec.js b/spec/frontend/content_editor/extensions/table_spec.js
new file mode 100644
index 00000000000..121fe9192db
--- /dev/null
+++ b/spec/frontend/content_editor/extensions/table_spec.js
@@ -0,0 +1,102 @@
+import Bold from '~/content_editor/extensions/bold';
+import BulletList from '~/content_editor/extensions/bullet_list';
+import ListItem from '~/content_editor/extensions/list_item';
+import Table from '~/content_editor/extensions/table';
+import TableCell from '~/content_editor/extensions/table_cell';
+import TableRow from '~/content_editor/extensions/table_row';
+import TableHeader from '~/content_editor/extensions/table_header';
+import { createTestEditor, createDocBuilder } from '../test_utils';
+
+describe('content_editor/extensions/table', () => {
+ let tiptapEditor;
+ let doc;
+ let p;
+ let table;
+ let tableHeader;
+ let tableCell;
+ let tableRow;
+ let initialDoc;
+ let mockAlert;
+
+ beforeEach(() => {
+ tiptapEditor = createTestEditor({
+ extensions: [Table, TableCell, TableRow, TableHeader, BulletList, Bold, ListItem],
+ });
+
+ ({
+ builders: { doc, p, table, tableCell, tableHeader, tableRow },
+ } = createDocBuilder({
+ tiptapEditor,
+ names: {
+ bold: { markType: Bold.name },
+ table: { nodeType: Table.name },
+ tableHeader: { nodeType: TableHeader.name },
+ tableCell: { nodeType: TableCell.name },
+ tableRow: { nodeType: TableRow.name },
+ bulletList: { nodeType: BulletList.name },
+ listItem: { nodeType: ListItem.name },
+ },
+ }));
+
+ initialDoc = doc(
+ table(
+ { isMarkdown: true },
+ tableRow(tableHeader(p('This is')), tableHeader(p('a table'))),
+ tableRow(tableCell(p('this is')), tableCell(p('the first row'))),
+ ),
+ );
+
+ mockAlert = jest.fn();
+ });
+
+ it('triggers a warning (just once) if the table is markdown, but the changes in the document will render an HTML table instead', () => {
+ tiptapEditor.commands.setContent(initialDoc.toJSON());
+
+ tiptapEditor.on('alert', mockAlert);
+
+ tiptapEditor.commands.setTextSelection({ from: 20, to: 22 });
+ tiptapEditor.commands.toggleBulletList();
+
+ jest.advanceTimersByTime(1001);
+ expect(mockAlert).toHaveBeenCalled();
+
+ mockAlert.mockReset();
+
+ tiptapEditor.commands.setTextSelection({ from: 4, to: 6 });
+ tiptapEditor.commands.toggleBulletList();
+
+ jest.advanceTimersByTime(1001);
+ expect(mockAlert).not.toHaveBeenCalled();
+ });
+
+ it('does not trigger a warning if the table is markdown, and the changes in the document can generate a markdown table', () => {
+ tiptapEditor.commands.setContent(initialDoc.toJSON());
+
+ tiptapEditor.on('alert', mockAlert);
+
+ tiptapEditor.commands.setTextSelection({ from: 20, to: 22 });
+ tiptapEditor.commands.toggleBold();
+
+ jest.advanceTimersByTime(1001);
+ expect(mockAlert).not.toHaveBeenCalled();
+ });
+
+ it('does not trigger any warnings if the table is not markdown', () => {
+ initialDoc = doc(
+ table(
+ tableRow(tableHeader(p('This is')), tableHeader(p('a table'))),
+ tableRow(tableCell(p('this is')), tableCell(p('the first row'))),
+ ),
+ );
+
+ tiptapEditor.commands.setContent(initialDoc.toJSON());
+
+ tiptapEditor.on('alert', mockAlert);
+
+ tiptapEditor.commands.setTextSelection({ from: 20, to: 22 });
+ tiptapEditor.commands.toggleBulletList();
+
+ jest.advanceTimersByTime(1001);
+ expect(mockAlert).not.toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/content_editor/extensions/word_break_spec.js b/spec/frontend/content_editor/extensions/word_break_spec.js
new file mode 100644
index 00000000000..23167269d7d
--- /dev/null
+++ b/spec/frontend/content_editor/extensions/word_break_spec.js
@@ -0,0 +1,35 @@
+import WordBreak from '~/content_editor/extensions/word_break';
+import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
+
+describe('content_editor/extensions/word_break', () => {
+ let tiptapEditor;
+ let doc;
+ let p;
+ let wordBreak;
+
+ beforeEach(() => {
+ tiptapEditor = createTestEditor({ extensions: [WordBreak] });
+
+ ({
+ builders: { doc, p, wordBreak },
+ } = createDocBuilder({
+ tiptapEditor,
+ names: {
+ wordBreak: { nodeType: WordBreak.name },
+ },
+ }));
+ });
+
+ it.each`
+ input | insertedNode
+ ${'<wbr>'} | ${() => p(wordBreak())}
+ ${'<wbr'} | ${() => p()}
+ ${'wbr>'} | ${() => p()}
+ `('with input=$input, then should insert a $insertedNode', ({ input, insertedNode }) => {
+ const expectedDoc = doc(insertedNode());
+
+ triggerNodeInputRule({ tiptapEditor, inputRuleText: input });
+
+ expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
+ });
+});
diff --git a/spec/frontend/content_editor/services/markdown_serializer_spec.js b/spec/frontend/content_editor/services/markdown_serializer_spec.js
index 33056ab9e4a..cfd93c2df10 100644
--- a/spec/frontend/content_editor/services/markdown_serializer_spec.js
+++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js
@@ -34,10 +34,6 @@ import { createTestEditor, createDocBuilder } from '../test_utils';
jest.mock('~/emoji');
-jest.mock('~/content_editor/services/feature_flags', () => ({
- isBlockTablesFeatureEnabled: jest.fn().mockReturnValue(true),
-}));
-
const tiptapEditor = createTestEditor({
extensions: [
Blockquote,
diff --git a/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js b/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js
index afe09a75f16..459780cc7cf 100644
--- a/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js
+++ b/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js
@@ -10,7 +10,7 @@ import Heading from '~/content_editor/extensions/heading';
import ListItem from '~/content_editor/extensions/list_item';
import trackInputRulesAndShortcuts from '~/content_editor/services/track_input_rules_and_shortcuts';
import { ENTER_KEY, BACKSPACE_KEY } from '~/lib/utils/keys';
-import { createTestEditor } from '../test_utils';
+import { createTestEditor, triggerNodeInputRule } from '../test_utils';
describe('content_editor/services/track_input_rules_and_shortcuts', () => {
let trackingSpy;
@@ -70,14 +70,7 @@ describe('content_editor/services/track_input_rules_and_shortcuts', () => {
describe('when creating a heading using an input rule', () => {
it('sends a tracking event indicating that a heading was created using an input rule', async () => {
const nodeName = Heading.name;
- const { view } = editor;
- const { selection } = view.state;
-
- // Triggers the event handler that input rules listen to
- view.someProp('handleTextInput', (f) => f(view, selection.from, selection.to, '## '));
-
- editor.chain().insertContent(HEADING_TEXT).run();
-
+ triggerNodeInputRule({ tiptapEditor: editor, inputRuleText: '## ' });
expect(trackingSpy).toHaveBeenCalledWith(undefined, INPUT_RULE_TRACKING_ACTION, {
label: CONTENT_EDITOR_TRACKING_LABEL,
property: `${nodeName}`,
diff --git a/spec/frontend/content_editor/test_utils.js b/spec/frontend/content_editor/test_utils.js
index cf5aa3f2938..b236c630e13 100644
--- a/spec/frontend/content_editor/test_utils.js
+++ b/spec/frontend/content_editor/test_utils.js
@@ -119,3 +119,26 @@ export const createTestContentEditorExtension = ({ commands = [] } = {}) => {
},
};
};
+
+export const triggerNodeInputRule = ({ tiptapEditor, inputRuleText }) => {
+ const { view } = tiptapEditor;
+ const { state } = tiptapEditor;
+ const { selection } = state;
+
+ // Triggers the event handler that input rules listen to
+ view.someProp('handleTextInput', (f) => f(view, selection.from, selection.to, inputRuleText));
+};
+
+export const triggerMarkInputRule = ({ tiptapEditor, inputRuleText }) => {
+ const { view } = tiptapEditor;
+
+ tiptapEditor.chain().setContent(inputRuleText).setTextSelection(0).run();
+
+ const { state } = tiptapEditor;
+ const { selection } = state;
+
+ // Triggers the event handler that input rules listen to
+ view.someProp('handleTextInput', (f) =>
+ f(view, selection.from, inputRuleText.length + 1, inputRuleText),
+ );
+};
diff --git a/spec/frontend/create_merge_request_dropdown_spec.js b/spec/frontend/create_merge_request_dropdown_spec.js
index 8878891701f..9f07eea433a 100644
--- a/spec/frontend/create_merge_request_dropdown_spec.js
+++ b/spec/frontend/create_merge_request_dropdown_spec.js
@@ -46,7 +46,10 @@ describe('CreateMergeRequestDropdown', () => {
dropdown
.getRef('contains#hash')
.then(() => {
- expect(axios.get).toHaveBeenCalledWith(endpoint);
+ expect(axios.get).toHaveBeenCalledWith(
+ endpoint,
+ expect.objectContaining({ cancelToken: expect.anything() }),
+ );
})
.then(done)
.catch(done.fail);
diff --git a/spec/frontend/crm/contacts_root_spec.js b/spec/frontend/crm/contacts_root_spec.js
new file mode 100644
index 00000000000..79b85969eb4
--- /dev/null
+++ b/spec/frontend/crm/contacts_root_spec.js
@@ -0,0 +1,60 @@
+import { GlLoadingIcon } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import ContactsRoot from '~/crm/components/contacts_root.vue';
+import getGroupContactsQuery from '~/crm/components/queries/get_group_contacts.query.graphql';
+import { getGroupContactsQueryResponse } from './mock_data';
+
+jest.mock('~/flash');
+
+describe('Customer relations contacts root app', () => {
+ Vue.use(VueApollo);
+ let wrapper;
+ let fakeApollo;
+
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findRowByName = (rowName) => wrapper.findAllByRole('row', { name: rowName });
+ const successQueryHandler = jest.fn().mockResolvedValue(getGroupContactsQueryResponse);
+
+ const mountComponent = ({
+ queryHandler = successQueryHandler,
+ mountFunction = shallowMountExtended,
+ } = {}) => {
+ fakeApollo = createMockApollo([[getGroupContactsQuery, queryHandler]]);
+ wrapper = mountFunction(ContactsRoot, {
+ provide: { groupFullPath: 'flightjs' },
+ apolloProvider: fakeApollo,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ fakeApollo = null;
+ });
+
+ it('should render loading spinner', () => {
+ mountComponent();
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+
+ it('should render error message on reject', async () => {
+ mountComponent({ queryHandler: jest.fn().mockRejectedValue('ERROR') });
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalled();
+ });
+
+ it('renders correct results', async () => {
+ mountComponent({ mountFunction: mountExtended });
+ await waitForPromises();
+
+ expect(findRowByName(/Marty/i)).toHaveLength(1);
+ expect(findRowByName(/George/i)).toHaveLength(1);
+ expect(findRowByName(/jd@gitlab.com/i)).toHaveLength(1);
+ });
+});
diff --git a/spec/frontend/crm/mock_data.js b/spec/frontend/crm/mock_data.js
new file mode 100644
index 00000000000..4197621aaa6
--- /dev/null
+++ b/spec/frontend/crm/mock_data.js
@@ -0,0 +1,81 @@
+export const getGroupContactsQueryResponse = {
+ data: {
+ group: {
+ __typename: 'Group',
+ id: 'gid://gitlab/Group/26',
+ contacts: {
+ nodes: [
+ {
+ __typename: 'CustomerRelationsContact',
+ id: 'gid://gitlab/CustomerRelations::Contact/12',
+ firstName: 'Marty',
+ lastName: 'McFly',
+ email: 'example@gitlab.com',
+ phone: null,
+ description: null,
+ organization: {
+ __typename: 'CustomerRelationsOrganization',
+ id: 'gid://gitlab/CustomerRelations::Organization/2',
+ name: 'Tech Giant Inc',
+ },
+ },
+ {
+ __typename: 'CustomerRelationsContact',
+ id: 'gid://gitlab/CustomerRelations::Contact/16',
+ firstName: 'Boy',
+ lastName: 'George',
+ email: null,
+ phone: null,
+ description: null,
+ organization: null,
+ },
+ {
+ __typename: 'CustomerRelationsContact',
+ id: 'gid://gitlab/CustomerRelations::Contact/13',
+ firstName: 'Jane',
+ lastName: 'Doe',
+ email: 'jd@gitlab.com',
+ phone: '+44 44 4444 4444',
+ description: 'Vice President',
+ organization: null,
+ },
+ ],
+ __typename: 'CustomerRelationsContactConnection',
+ },
+ },
+ },
+};
+
+export const getGroupOrganizationsQueryResponse = {
+ data: {
+ group: {
+ __typename: 'Group',
+ id: 'gid://gitlab/Group/26',
+ organizations: {
+ nodes: [
+ {
+ __typename: 'CustomerRelationsOrganization',
+ id: 'gid://gitlab/CustomerRelations::Organization/1',
+ name: 'Test Inc',
+ defaultRate: 100,
+ description: null,
+ },
+ {
+ __typename: 'CustomerRelationsOrganization',
+ id: 'gid://gitlab/CustomerRelations::Organization/2',
+ name: 'ABC Company',
+ defaultRate: 110,
+ description: 'VIP',
+ },
+ {
+ __typename: 'CustomerRelationsOrganization',
+ id: 'gid://gitlab/CustomerRelations::Organization/3',
+ name: 'GitLab',
+ defaultRate: 120,
+ description: null,
+ },
+ ],
+ },
+ },
+ },
+};
diff --git a/spec/frontend/crm/organizations_root_spec.js b/spec/frontend/crm/organizations_root_spec.js
new file mode 100644
index 00000000000..a69a099e03d
--- /dev/null
+++ b/spec/frontend/crm/organizations_root_spec.js
@@ -0,0 +1,60 @@
+import { GlLoadingIcon } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import OrganizationsRoot from '~/crm/components/organizations_root.vue';
+import getGroupOrganizationsQuery from '~/crm/components/queries/get_group_organizations.query.graphql';
+import { getGroupOrganizationsQueryResponse } from './mock_data';
+
+jest.mock('~/flash');
+
+describe('Customer relations organizations root app', () => {
+ Vue.use(VueApollo);
+ let wrapper;
+ let fakeApollo;
+
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findRowByName = (rowName) => wrapper.findAllByRole('row', { name: rowName });
+ const successQueryHandler = jest.fn().mockResolvedValue(getGroupOrganizationsQueryResponse);
+
+ const mountComponent = ({
+ queryHandler = successQueryHandler,
+ mountFunction = shallowMountExtended,
+ } = {}) => {
+ fakeApollo = createMockApollo([[getGroupOrganizationsQuery, queryHandler]]);
+ wrapper = mountFunction(OrganizationsRoot, {
+ provide: { groupFullPath: 'flightjs' },
+ apolloProvider: fakeApollo,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ fakeApollo = null;
+ });
+
+ it('should render loading spinner', () => {
+ mountComponent();
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+
+ it('should render error message on reject', async () => {
+ mountComponent({ queryHandler: jest.fn().mockRejectedValue('ERROR') });
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalled();
+ });
+
+ it('renders correct results', async () => {
+ mountComponent({ mountFunction: mountExtended });
+ await waitForPromises();
+
+ expect(findRowByName(/Test Inc/i)).toHaveLength(1);
+ expect(findRowByName(/VIP/i)).toHaveLength(1);
+ expect(findRowByName(/120/i)).toHaveLength(1);
+ });
+});
diff --git a/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js b/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js
index c41adf523f8..2001f5c1441 100644
--- a/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js
+++ b/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js
@@ -4,8 +4,6 @@ import { TEST_HOST } from 'helpers/test_constants';
import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
import axios from '~/lib/utils/axios_utils';
-const { CancelToken } = axios;
-
describe('custom metrics form fields component', () => {
let wrapper;
let mockAxios;
@@ -116,14 +114,14 @@ describe('custom metrics form fields component', () => {
it('receives and validates a persisted value', () => {
const query = 'persistedQuery';
- const axiosPost = jest.spyOn(axios, 'post');
- const source = CancelToken.source();
+ jest.spyOn(axios, 'post');
+
mountComponent({ metricPersisted: true, ...makeFormData({ query }) });
- expect(axiosPost).toHaveBeenCalledWith(
+ expect(axios.post).toHaveBeenCalledWith(
validateQueryPath,
{ query },
- { cancelToken: source.token },
+ expect.objectContaining({ cancelToken: expect.anything() }),
);
expect(getNamedInput(queryInputName).value).toBe(query);
jest.runAllTimers();
diff --git a/spec/frontend/cycle_analytics/metric_popover_spec.js b/spec/frontend/cycle_analytics/metric_popover_spec.js
new file mode 100644
index 00000000000..5a622fcacd5
--- /dev/null
+++ b/spec/frontend/cycle_analytics/metric_popover_spec.js
@@ -0,0 +1,102 @@
+import { GlLink, GlIcon } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import MetricPopover from '~/cycle_analytics/components/metric_popover.vue';
+
+const MOCK_METRIC = {
+ key: 'deployment-frequency',
+ label: 'Deployment Frequency',
+ value: '10.0',
+ unit: 'per day',
+ description: 'Average number of deployments to production per day.',
+ links: [],
+};
+
+describe('MetricPopover', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ return shallowMountExtended(MetricPopover, {
+ propsData: {
+ target: 'deployment-frequency',
+ ...props,
+ },
+ stubs: {
+ 'gl-popover': { template: '<div><slot name="title"></slot><slot></slot></div>' },
+ },
+ });
+ };
+
+ const findMetricLabel = () => wrapper.findByTestId('metric-label');
+ const findAllMetricLinks = () => wrapper.findAll('[data-testid="metric-link"]');
+ const findMetricDescription = () => wrapper.findByTestId('metric-description');
+ const findMetricDocsLink = () => wrapper.findByTestId('metric-docs-link');
+ const findMetricDocsLinkIcon = () => findMetricDocsLink().find(GlIcon);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders the metric label', () => {
+ wrapper = createComponent({ metric: MOCK_METRIC });
+ expect(findMetricLabel().text()).toBe(MOCK_METRIC.label);
+ });
+
+ it('renders the metric description', () => {
+ wrapper = createComponent({ metric: MOCK_METRIC });
+ expect(findMetricDescription().text()).toBe(MOCK_METRIC.description);
+ });
+
+ describe('with links', () => {
+ const links = [
+ {
+ name: 'Deployment frequency',
+ url: '/groups/gitlab-org/-/analytics/ci_cd?tab=deployment-frequency',
+ label: 'Dashboard',
+ },
+ {
+ name: 'Another link',
+ url: '/groups/gitlab-org/-/analytics/another-link',
+ label: 'Another link',
+ },
+ ];
+ const docsLink = {
+ name: 'Deployment frequency',
+ url: '/help/user/analytics/index#definitions',
+ label: 'Go to docs',
+ docs_link: true,
+ };
+ const linksWithDocs = [...links, docsLink];
+
+ describe.each`
+ hasDocsLink | allLinks | displayedMetricLinks
+ ${true} | ${linksWithDocs} | ${links}
+ ${false} | ${links} | ${links}
+ `(
+ 'when one link has docs_link=$hasDocsLink',
+ ({ hasDocsLink, allLinks, displayedMetricLinks }) => {
+ beforeEach(() => {
+ wrapper = createComponent({ metric: { ...MOCK_METRIC, links: allLinks } });
+ });
+
+ displayedMetricLinks.forEach((link, idx) => {
+ it(`renders a link for "${link.name}"`, () => {
+ const allLinkContainers = findAllMetricLinks();
+
+ expect(allLinkContainers.at(idx).text()).toContain(link.name);
+ expect(allLinkContainers.at(idx).find(GlLink).attributes('href')).toBe(link.url);
+ });
+ });
+
+ it(`${hasDocsLink ? 'renders' : "doesn't render"} a docs link`, () => {
+ expect(findMetricDocsLink().exists()).toBe(hasDocsLink);
+
+ if (hasDocsLink) {
+ expect(findMetricDocsLink().attributes('href')).toBe(docsLink.url);
+ expect(findMetricDocsLink().text()).toBe(docsLink.label);
+ expect(findMetricDocsLinkIcon().attributes('name')).toBe('external-link');
+ }
+ });
+ },
+ );
+ });
+});
diff --git a/spec/frontend/cycle_analytics/mock_data.js b/spec/frontend/cycle_analytics/mock_data.js
index 1882457960a..c482bd4e910 100644
--- a/spec/frontend/cycle_analytics/mock_data.js
+++ b/spec/frontend/cycle_analytics/mock_data.js
@@ -1,10 +1,14 @@
-/* eslint-disable import/no-deprecated */
+import valueStreamAnalyticsStages from 'test_fixtures/projects/analytics/value_stream_analytics/stages.json';
+import issueStageFixtures from 'test_fixtures/projects/analytics/value_stream_analytics/events/issue.json';
+import planStageFixtures from 'test_fixtures/projects/analytics/value_stream_analytics/events/plan.json';
+import reviewStageFixtures from 'test_fixtures/projects/analytics/value_stream_analytics/events/review.json';
+import codeStageFixtures from 'test_fixtures/projects/analytics/value_stream_analytics/events/code.json';
+import testStageFixtures from 'test_fixtures/projects/analytics/value_stream_analytics/events/test.json';
+import stagingStageFixtures from 'test_fixtures/projects/analytics/value_stream_analytics/events/staging.json';
-import { getJSONFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
import {
DEFAULT_VALUE_STREAM,
- DEFAULT_DAYS_IN_PAST,
PAGINATION_TYPE,
PAGINATION_SORT_DIRECTION_DESC,
PAGINATION_SORT_FIELD_END_EVENT,
@@ -12,6 +16,7 @@ import {
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { getDateInPast } from '~/lib/utils/datetime_utility';
+const DEFAULT_DAYS_IN_PAST = 30;
export const createdBefore = new Date(2019, 0, 14);
export const createdAfter = getDateInPast(createdBefore, DEFAULT_DAYS_IN_PAST);
@@ -20,28 +25,16 @@ export const deepCamelCase = (obj) => convertObjectPropsToCamelCase(obj, { deep:
export const getStageByTitle = (stages, title) =>
stages.find((stage) => stage.title && stage.title.toLowerCase().trim() === title) || {};
-const fixtureEndpoints = {
- customizableCycleAnalyticsStagesAndEvents:
- 'projects/analytics/value_stream_analytics/stages.json',
- stageEvents: (stage) => `projects/analytics/value_stream_analytics/events/${stage}.json`,
- metricsData: 'projects/analytics/value_stream_analytics/summary.json',
-};
-
-export const metricsData = getJSONFixture(fixtureEndpoints.metricsData);
-
-export const customizableStagesAndEvents = getJSONFixture(
- fixtureEndpoints.customizableCycleAnalyticsStagesAndEvents,
-);
-
export const defaultStages = ['issue', 'plan', 'review', 'code', 'test', 'staging'];
-const stageFixtures = defaultStages.reduce((acc, stage) => {
- const events = getJSONFixture(fixtureEndpoints.stageEvents(stage));
- return {
- ...acc,
- [stage]: events,
- };
-}, {});
+const stageFixtures = {
+ issue: issueStageFixtures,
+ plan: planStageFixtures,
+ review: reviewStageFixtures,
+ code: codeStageFixtures,
+ test: testStageFixtures,
+ staging: stagingStageFixtures,
+};
export const summary = [
{ value: '20', title: 'New Issues' },
@@ -260,7 +253,7 @@ export const selectedProjects = [
},
];
-export const rawValueStreamStages = customizableStagesAndEvents.stages;
+export const rawValueStreamStages = valueStreamAnalyticsStages.stages;
export const valueStreamStages = rawValueStreamStages.map((s) =>
convertObjectPropsToCamelCase(s, { deep: true }),
diff --git a/spec/frontend/cycle_analytics/store/actions_spec.js b/spec/frontend/cycle_analytics/store/actions_spec.js
index 993e6b6b73a..e775e941b4c 100644
--- a/spec/frontend/cycle_analytics/store/actions_spec.js
+++ b/spec/frontend/cycle_analytics/store/actions_spec.js
@@ -57,22 +57,12 @@ describe('Project Value Stream Analytics actions', () => {
const mutationTypes = (arr) => arr.map(({ type }) => type);
- const mockFetchStageDataActions = [
- { type: 'setLoading', payload: true },
- { type: 'fetchCycleAnalyticsData' },
- { type: 'fetchStageData' },
- { type: 'fetchStageMedians' },
- { type: 'fetchStageCountValues' },
- { type: 'setLoading', payload: false },
- ];
-
describe.each`
- action | payload | expectedActions | expectedMutations
- ${'setLoading'} | ${true} | ${[]} | ${[{ type: 'SET_LOADING', payload: true }]}
- ${'setDateRange'} | ${{ createdAfter, createdBefore }} | ${mockFetchStageDataActions} | ${[mockSetDateActionCommit]}
- ${'setFilters'} | ${[]} | ${mockFetchStageDataActions} | ${[]}
- ${'setSelectedStage'} | ${{ selectedStage }} | ${[{ type: 'fetchStageData' }]} | ${[{ type: 'SET_SELECTED_STAGE', payload: { selectedStage } }]}
- ${'setSelectedValueStream'} | ${{ selectedValueStream }} | ${[{ type: 'fetchValueStreamStages' }, { type: 'fetchCycleAnalyticsData' }]} | ${[{ type: 'SET_SELECTED_VALUE_STREAM', payload: { selectedValueStream } }]}
+ action | payload | expectedActions | expectedMutations
+ ${'setDateRange'} | ${{ createdAfter, createdBefore }} | ${[{ type: 'refetchStageData' }]} | ${[mockSetDateActionCommit]}
+ ${'setFilters'} | ${[]} | ${[{ type: 'refetchStageData' }]} | ${[]}
+ ${'setSelectedStage'} | ${{ selectedStage }} | ${[{ type: 'refetchStageData' }]} | ${[{ type: 'SET_SELECTED_STAGE', payload: { selectedStage } }]}
+ ${'setSelectedValueStream'} | ${{ selectedValueStream }} | ${[{ type: 'fetchValueStreamStages' }]} | ${[{ type: 'SET_SELECTED_VALUE_STREAM', payload: { selectedValueStream } }]}
`('$action', ({ action, payload, expectedActions, expectedMutations }) => {
const types = mutationTypes(expectedMutations);
it(`will dispatch ${expectedActions} and commit ${types}`, () =>
@@ -86,9 +76,18 @@ describe('Project Value Stream Analytics actions', () => {
});
describe('initializeVsa', () => {
- let mockDispatch;
- let mockCommit;
- const payload = { endpoints: mockEndpoints };
+ const selectedAuthor = 'Author';
+ const selectedMilestone = 'Milestone 1';
+ const selectedAssigneeList = ['Assignee 1', 'Assignee 2'];
+ const selectedLabelList = ['Label 1', 'Label 2'];
+ const payload = {
+ endpoints: mockEndpoints,
+ selectedAuthor,
+ selectedMilestone,
+ selectedAssigneeList,
+ selectedLabelList,
+ selectedStage,
+ };
const mockFilterEndpoints = {
groupEndpoint: 'foo',
labelsEndpoint: mockLabelsPath,
@@ -96,27 +95,63 @@ describe('Project Value Stream Analytics actions', () => {
projectEndpoint: '/namespace/-/analytics/value_stream_analytics/value_streams',
};
+ it('will dispatch fetchValueStreams actions and commit SET_LOADING and INITIALIZE_VSA', () => {
+ return testAction({
+ action: actions.initializeVsa,
+ state: {},
+ payload,
+ expectedMutations: [
+ { type: 'INITIALIZE_VSA', payload },
+ { type: 'SET_LOADING', payload: true },
+ { type: 'SET_LOADING', payload: false },
+ ],
+ expectedActions: [
+ { type: 'filters/setEndpoints', payload: mockFilterEndpoints },
+ {
+ type: 'filters/initialize',
+ payload: { selectedAuthor, selectedMilestone, selectedAssigneeList, selectedLabelList },
+ },
+ { type: 'fetchValueStreams' },
+ { type: 'setInitialStage', payload: selectedStage },
+ ],
+ });
+ });
+ });
+
+ describe('setInitialStage', () => {
beforeEach(() => {
- mockDispatch = jest.fn(() => Promise.resolve());
- mockCommit = jest.fn();
+ state = { ...state, stages: allowedStages };
});
- it('will dispatch the setLoading and fetchValueStreams actions and commit INITIALIZE_VSA', async () => {
- await actions.initializeVsa(
- {
- ...state,
- dispatch: mockDispatch,
- commit: mockCommit,
- },
- payload,
- );
- expect(mockCommit).toHaveBeenCalledWith('INITIALIZE_VSA', { endpoints: mockEndpoints });
-
- expect(mockDispatch).toHaveBeenCalledTimes(4);
- expect(mockDispatch).toHaveBeenCalledWith('filters/setEndpoints', mockFilterEndpoints);
- expect(mockDispatch).toHaveBeenCalledWith('setLoading', true);
- expect(mockDispatch).toHaveBeenCalledWith('fetchValueStreams');
- expect(mockDispatch).toHaveBeenCalledWith('setLoading', false);
+ describe('with a selected stage', () => {
+ it('will commit `SET_SELECTED_STAGE` and fetchValueStreamStageData actions', () => {
+ const fakeStage = { ...selectedStage, id: 'fake', name: 'fake-stae' };
+ return testAction({
+ action: actions.setInitialStage,
+ state,
+ payload: fakeStage,
+ expectedMutations: [
+ {
+ type: 'SET_SELECTED_STAGE',
+ payload: fakeStage,
+ },
+ ],
+ expectedActions: [{ type: 'fetchValueStreamStageData' }],
+ });
+ });
+ });
+
+ describe('without a selected stage', () => {
+ it('will select the first stage from the value stream', () => {
+ const [firstStage] = allowedStages;
+ testAction({
+ action: actions.setInitialStage,
+ state,
+ payload: null,
+ expectedMutations: [{ type: 'SET_SELECTED_STAGE', payload: firstStage }],
+ expectedActions: [{ type: 'fetchValueStreamStageData' }],
+ });
+ });
});
});
@@ -270,12 +305,7 @@ describe('Project Value Stream Analytics actions', () => {
state,
payload: {},
expectedMutations: [{ type: 'REQUEST_VALUE_STREAMS' }],
- expectedActions: [
- { type: 'receiveValueStreamsSuccess' },
- { type: 'setSelectedStage' },
- { type: 'fetchStageMedians' },
- { type: 'fetchStageCountValues' },
- ],
+ expectedActions: [{ type: 'receiveValueStreamsSuccess' }],
}));
describe('with a failing request', () => {
@@ -483,4 +513,34 @@ describe('Project Value Stream Analytics actions', () => {
}));
});
});
+
+ describe('refetchStageData', () => {
+ it('will commit SET_LOADING and dispatch fetchValueStreamStageData actions', () =>
+ testAction({
+ action: actions.refetchStageData,
+ state,
+ payload: {},
+ expectedMutations: [
+ { type: 'SET_LOADING', payload: true },
+ { type: 'SET_LOADING', payload: false },
+ ],
+ expectedActions: [{ type: 'fetchValueStreamStageData' }],
+ }));
+ });
+
+ describe('fetchValueStreamStageData', () => {
+ it('will dispatch the fetchCycleAnalyticsData, fetchStageData, fetchStageMedians and fetchStageCountValues actions', () =>
+ testAction({
+ action: actions.fetchValueStreamStageData,
+ state,
+ payload: {},
+ expectedMutations: [],
+ expectedActions: [
+ { type: 'fetchCycleAnalyticsData' },
+ { type: 'fetchStageData' },
+ { type: 'fetchStageMedians' },
+ { type: 'fetchStageCountValues' },
+ ],
+ }));
+ });
});
diff --git a/spec/frontend/cycle_analytics/store/mutations_spec.js b/spec/frontend/cycle_analytics/store/mutations_spec.js
index 4860225c995..2670a390e9c 100644
--- a/spec/frontend/cycle_analytics/store/mutations_spec.js
+++ b/spec/frontend/cycle_analytics/store/mutations_spec.js
@@ -101,6 +101,7 @@ describe('Project Value Stream Analytics mutations', () => {
${types.SET_SELECTED_VALUE_STREAM} | ${selectedValueStream} | ${'selectedValueStream'} | ${selectedValueStream}
${types.SET_PAGINATION} | ${pagination} | ${'pagination'} | ${{ ...pagination, sort: PAGINATION_SORT_FIELD_END_EVENT, direction: PAGINATION_SORT_DIRECTION_DESC }}
${types.SET_PAGINATION} | ${{ ...pagination, sort: 'duration', direction: 'asc' }} | ${'pagination'} | ${{ ...pagination, sort: 'duration', direction: 'asc' }}
+ ${types.SET_SELECTED_STAGE} | ${selectedStage} | ${'selectedStage'} | ${selectedStage}
${types.RECEIVE_VALUE_STREAMS_SUCCESS} | ${[selectedValueStream]} | ${'valueStreams'} | ${[selectedValueStream]}
${types.RECEIVE_VALUE_STREAM_STAGES_SUCCESS} | ${{ stages: rawValueStreamStages }} | ${'stages'} | ${valueStreamStages}
${types.RECEIVE_STAGE_MEDIANS_SUCCESS} | ${rawStageMedians} | ${'medians'} | ${formattedStageMedians}
diff --git a/spec/frontend/cycle_analytics/utils_spec.js b/spec/frontend/cycle_analytics/utils_spec.js
index 74d64cd8d71..a6d6d022781 100644
--- a/spec/frontend/cycle_analytics/utils_spec.js
+++ b/spec/frontend/cycle_analytics/utils_spec.js
@@ -1,11 +1,11 @@
-import { useFakeDate } from 'helpers/fake_date';
+import metricsData from 'test_fixtures/projects/analytics/value_stream_analytics/summary.json';
import {
transformStagesForPathNavigation,
medianTimeToParsedSeconds,
formatMedianValues,
filterStagesByHiddenStatus,
- calculateFormattedDayInPast,
prepareTimeMetricsData,
+ buildCycleAnalyticsInitialData,
} from '~/cycle_analytics/utils';
import { slugify } from '~/lib/utils/text_utility';
import {
@@ -14,7 +14,6 @@ import {
stageMedians,
pathNavIssueMetric,
rawStageMedians,
- metricsData,
} from './mock_data';
describe('Value stream analytics utils', () => {
@@ -90,14 +89,6 @@ describe('Value stream analytics utils', () => {
});
});
- describe('calculateFormattedDayInPast', () => {
- useFakeDate(1815, 11, 10);
-
- it('will return 2 dates, now and past', () => {
- expect(calculateFormattedDayInPast(5)).toEqual({ now: '1815-12-10', past: '1815-12-05' });
- });
- });
-
describe('prepareTimeMetricsData', () => {
let prepared;
const [first, second] = metricsData;
@@ -125,4 +116,87 @@ describe('Value stream analytics utils', () => {
]);
});
});
+
+ describe('buildCycleAnalyticsInitialData', () => {
+ let res = null;
+ const projectId = '5';
+ const createdAfter = '2021-09-01';
+ const createdBefore = '2021-11-06';
+ const groupId = '146';
+ const groupPath = 'fake-group';
+ const fullPath = 'fake-group/fake-project';
+ const labelsPath = '/fake-group/fake-project/-/labels.json';
+ const milestonesPath = '/fake-group/fake-project/-/milestones.json';
+ const requestPath = '/fake-group/fake-project/-/value_stream_analytics';
+
+ const rawData = {
+ projectId,
+ createdBefore,
+ createdAfter,
+ fullPath,
+ requestPath,
+ labelsPath,
+ milestonesPath,
+ groupId,
+ groupPath,
+ };
+
+ describe('with minimal data', () => {
+ beforeEach(() => {
+ res = buildCycleAnalyticsInitialData(rawData);
+ });
+
+ it('sets the projectId', () => {
+ expect(res.projectId).toBe(parseInt(projectId, 10));
+ });
+
+ it('sets the date range', () => {
+ expect(res.createdBefore).toEqual(new Date(createdBefore));
+ expect(res.createdAfter).toEqual(new Date(createdAfter));
+ });
+
+ it('sets the endpoints', () => {
+ const { endpoints } = res;
+ expect(endpoints.fullPath).toBe(fullPath);
+ expect(endpoints.requestPath).toBe(requestPath);
+ expect(endpoints.labelsPath).toBe(labelsPath);
+ expect(endpoints.milestonesPath).toBe(milestonesPath);
+ expect(endpoints.groupId).toBe(parseInt(groupId, 10));
+ expect(endpoints.groupPath).toBe(groupPath);
+ });
+
+ it('returns null when there is no stage', () => {
+ expect(res.selectedStage).toBeNull();
+ });
+
+ it('returns false for missing features', () => {
+ expect(res.features.cycleAnalyticsForGroups).toBe(false);
+ });
+ });
+
+ describe('with a stage set', () => {
+ const jsonStage = '{"id":"fakeStage","title":"fakeStage"}';
+
+ it('parses the selectedStage data', () => {
+ res = buildCycleAnalyticsInitialData({ ...rawData, stage: jsonStage });
+
+ const { selectedStage: stage } = res;
+
+ expect(stage.id).toBe('fakeStage');
+ expect(stage.title).toBe('fakeStage');
+ });
+ });
+
+ describe('with features set', () => {
+ const fakeFeatures = { cycleAnalyticsForGroups: true };
+
+ it('sets the feature flags', () => {
+ res = buildCycleAnalyticsInitialData({
+ ...rawData,
+ gon: { licensed_features: fakeFeatures },
+ });
+ expect(res.features).toEqual(fakeFeatures);
+ });
+ });
+ });
});
diff --git a/spec/frontend/cycle_analytics/value_stream_metrics_spec.js b/spec/frontend/cycle_analytics/value_stream_metrics_spec.js
index ffdb49a828c..c97e4845bc2 100644
--- a/spec/frontend/cycle_analytics/value_stream_metrics_spec.js
+++ b/spec/frontend/cycle_analytics/value_stream_metrics_spec.js
@@ -1,13 +1,16 @@
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import { GlSingleStat } from '@gitlab/ui/dist/charts';
import { shallowMount } from '@vue/test-utils';
+import metricsData from 'test_fixtures/projects/analytics/value_stream_analytics/summary.json';
import waitForPromises from 'helpers/wait_for_promises';
import { METRIC_TYPE_SUMMARY } from '~/api/analytics_api';
import ValueStreamMetrics from '~/cycle_analytics/components/value_stream_metrics.vue';
import createFlash from '~/flash';
-import { group, metricsData } from './mock_data';
+import { redirectTo } from '~/lib/utils/url_utility';
+import { group } from './mock_data';
jest.mock('~/flash');
+jest.mock('~/lib/utils/url_utility');
describe('ValueStreamMetrics', () => {
let wrapper;
@@ -43,7 +46,6 @@ describe('ValueStreamMetrics', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('with successful requests', () => {
@@ -55,7 +57,23 @@ describe('ValueStreamMetrics', () => {
it('will display a loader with pending requests', async () => {
await wrapper.vm.$nextTick();
- expect(wrapper.find(GlSkeletonLoading).exists()).toBe(true);
+ expect(wrapper.findComponent(GlSkeletonLoading).exists()).toBe(true);
+ });
+
+ it('renders hidden GlSingleStat components for each metric', async () => {
+ await waitForPromises();
+
+ wrapper.setData({ isLoading: true });
+
+ await wrapper.vm.$nextTick();
+
+ const components = findMetrics();
+
+ expect(components).toHaveLength(metricsData.length);
+
+ metricsData.forEach((metric, index) => {
+ expect(components.at(index).isVisible()).toBe(false);
+ });
});
describe('with data loaded', () => {
@@ -67,19 +85,31 @@ describe('ValueStreamMetrics', () => {
expectToHaveRequest({ params: {} });
});
- it.each`
- index | value | title | unit
- ${0} | ${metricsData[0].value} | ${metricsData[0].title} | ${metricsData[0].unit}
- ${1} | ${metricsData[1].value} | ${metricsData[1].title} | ${metricsData[1].unit}
- ${2} | ${metricsData[2].value} | ${metricsData[2].title} | ${metricsData[2].unit}
- ${3} | ${metricsData[3].value} | ${metricsData[3].title} | ${metricsData[3].unit}
- `(
- 'renders a single stat component for the $title with value and unit',
- ({ index, value, title, unit }) => {
+ describe.each`
+ index | value | title | unit | clickable
+ ${0} | ${metricsData[0].value} | ${metricsData[0].title} | ${metricsData[0].unit} | ${false}
+ ${1} | ${metricsData[1].value} | ${metricsData[1].title} | ${metricsData[1].unit} | ${false}
+ ${2} | ${metricsData[2].value} | ${metricsData[2].title} | ${metricsData[2].unit} | ${false}
+ ${3} | ${metricsData[3].value} | ${metricsData[3].title} | ${metricsData[3].unit} | ${true}
+ `('metric tiles', ({ index, value, title, unit, clickable }) => {
+ it(`renders a single stat component for "${title}" with value and unit`, () => {
const metric = findMetrics().at(index);
expect(metric.props()).toMatchObject({ value, title, unit: unit ?? '' });
- },
- );
+ expect(metric.isVisible()).toBe(true);
+ });
+
+ it(`${
+ clickable ? 'redirects' : "doesn't redirect"
+ } when the user clicks the "${title}" metric`, () => {
+ const metric = findMetrics().at(index);
+ metric.vm.$emit('click');
+ if (clickable) {
+ expect(redirectTo).toHaveBeenCalledWith(metricsData[index].links[0].url);
+ } else {
+ expect(redirectTo).not.toHaveBeenCalled();
+ }
+ });
+ });
it('will not display a loading icon', () => {
expect(wrapper.find(GlSkeletonLoading).exists()).toBe(false);
diff --git a/spec/frontend/delete_label_modal_spec.js b/spec/frontend/delete_label_modal_spec.js
index df70d3a8393..0b3e6fe652a 100644
--- a/spec/frontend/delete_label_modal_spec.js
+++ b/spec/frontend/delete_label_modal_spec.js
@@ -40,7 +40,7 @@ describe('DeleteLabelModal', () => {
it('starts with only js-containers', () => {
expect(findJsHooks()).toHaveLength(buttons.length);
- expect(findModal()).not.toExist();
+ expect(findModal()).toBe(null);
});
describe('when first button clicked', () => {
@@ -54,7 +54,7 @@ describe('DeleteLabelModal', () => {
});
it('renders GlModal', () => {
- expect(findModal()).toExist();
+ expect(findModal()).not.toBe(null);
});
});
diff --git a/spec/frontend/deploy_keys/components/key_spec.js b/spec/frontend/deploy_keys/components/key_spec.js
index 511b9d6ef55..51c120d8213 100644
--- a/spec/frontend/deploy_keys/components/key_spec.js
+++ b/spec/frontend/deploy_keys/components/key_spec.js
@@ -50,20 +50,20 @@ describe('Deploy keys key', () => {
it('shows pencil button for editing', () => {
createComponent({ deployKey });
- expect(wrapper.find('.btn [data-testid="pencil-icon"]')).toExist();
+ expect(wrapper.find('.btn [data-testid="pencil-icon"]').exists()).toBe(true);
});
it('shows disable button when the project is not deletable', () => {
createComponent({ deployKey });
- expect(wrapper.find('.btn [data-testid="cancel-icon"]')).toExist();
+ expect(wrapper.find('.btn [data-testid="cancel-icon"]').exists()).toBe(true);
});
it('shows remove button when the project is deletable', () => {
createComponent({
deployKey: { ...deployKey, destroyed_when_orphaned: true, almost_orphaned: true },
});
- expect(wrapper.find('.btn [data-testid="remove-icon"]')).toExist();
+ expect(wrapper.find('.btn [data-testid="remove-icon"]').exists()).toBe(true);
});
});
@@ -137,7 +137,7 @@ describe('Deploy keys key', () => {
it('shows pencil button for editing', () => {
createComponent({ deployKey });
- expect(wrapper.find('.btn [data-testid="pencil-icon"]')).toExist();
+ expect(wrapper.find('.btn [data-testid="pencil-icon"]').exists()).toBe(true);
});
it('shows disable button when key is enabled', () => {
@@ -145,7 +145,7 @@ describe('Deploy keys key', () => {
createComponent({ deployKey });
- expect(wrapper.find('.btn [data-testid="cancel-icon"]')).toExist();
+ expect(wrapper.find('.btn [data-testid="cancel-icon"]').exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/deploy_keys/components/keys_panel_spec.js b/spec/frontend/deploy_keys/components/keys_panel_spec.js
index f3b907e5450..f5f76d5d493 100644
--- a/spec/frontend/deploy_keys/components/keys_panel_spec.js
+++ b/spec/frontend/deploy_keys/components/keys_panel_spec.js
@@ -37,7 +37,7 @@ describe('Deploy keys panel', () => {
mountComponent();
const tableHeader = findTableRowHeader();
- expect(tableHeader).toExist();
+ expect(tableHeader.exists()).toBe(true);
expect(tableHeader.text()).toContain('Deploy key');
expect(tableHeader.text()).toContain('Project usage');
expect(tableHeader.text()).toContain('Created');
diff --git a/spec/frontend/deprecated_jquery_dropdown_spec.js b/spec/frontend/deprecated_jquery_dropdown_spec.js
index 7e4c6e131b4..bec91fe5fc5 100644
--- a/spec/frontend/deprecated_jquery_dropdown_spec.js
+++ b/spec/frontend/deprecated_jquery_dropdown_spec.js
@@ -1,10 +1,9 @@
/* eslint-disable no-param-reassign */
import $ from 'jquery';
+import mockProjects from 'test_fixtures_static/projects.json';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import '~/lib/utils/common_utils';
-// eslint-disable-next-line import/no-deprecated
-import { getJSONFixture } from 'helpers/fixtures';
import { visitUrl } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility', () => ({
@@ -68,8 +67,7 @@ describe('deprecatedJQueryDropdown', () => {
loadFixtures('static/deprecated_jquery_dropdown.html');
test.dropdownContainerElement = $('.dropdown.inline');
test.$dropdownMenuElement = $('.dropdown-menu', test.dropdownContainerElement);
- // eslint-disable-next-line import/no-deprecated
- test.projectsData = getJSONFixture('static/projects.json');
+ test.projectsData = JSON.parse(JSON.stringify(mockProjects));
});
afterEach(() => {
diff --git a/spec/frontend/design_management/components/list/item_spec.js b/spec/frontend/design_management/components/list/item_spec.js
index 58636ece91e..ed105b112be 100644
--- a/spec/frontend/design_management/components/list/item_spec.js
+++ b/spec/frontend/design_management/components/list/item_spec.js
@@ -87,7 +87,7 @@ describe('Design management list item component', () => {
describe('before image is loaded', () => {
it('renders loading spinner', () => {
- expect(wrapper.find(GlLoadingIcon)).toExist();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
});
diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js
index ce79feae2e7..427161a391b 100644
--- a/spec/frontend/design_management/pages/index_spec.js
+++ b/spec/frontend/design_management/pages/index_spec.js
@@ -669,6 +669,20 @@ describe('Design management index page', () => {
expect(variables.files).toEqual(event.clipboardData.files.map((f) => new File([f], '')));
});
+ it('display original file name', () => {
+ event.clipboardData.files = [new File([new Blob()], 'test.png', { type: 'image/png' })];
+ document.dispatchEvent(event);
+
+ const [{ mutation, variables }] = mockMutate.mock.calls[0];
+ expect(mutation).toBe(uploadDesignMutation);
+ expect(variables).toStrictEqual({
+ files: expect.any(Array),
+ iid: '1',
+ projectPath: 'project-path',
+ });
+ expect(variables.files[0].name).toEqual('test.png');
+ });
+
it('renames a design if it has an image.png filename', () => {
event.clipboardData.getData = () => 'image.png';
document.dispatchEvent(event);
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index 0527c2153f4..d50ac0529d6 100644
--- a/spec/frontend/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -388,15 +388,24 @@ describe('diffs/components/app', () => {
wrapper.vm.jumpToFile(+1);
- expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['diffs/scrollToFile', '222.js']);
+ expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual([
+ 'diffs/scrollToFile',
+ { path: '222.js' },
+ ]);
store.state.diffs.currentDiffFileId = '222';
wrapper.vm.jumpToFile(+1);
- expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['diffs/scrollToFile', '333.js']);
+ expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual([
+ 'diffs/scrollToFile',
+ { path: '333.js' },
+ ]);
store.state.diffs.currentDiffFileId = '333';
wrapper.vm.jumpToFile(-1);
- expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['diffs/scrollToFile', '222.js']);
+ expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual([
+ 'diffs/scrollToFile',
+ { path: '222.js' },
+ ]);
});
it('does not jump to previous file from the first one', async () => {
@@ -702,23 +711,4 @@ describe('diffs/components/app', () => {
);
});
});
-
- describe('fluid layout', () => {
- beforeEach(() => {
- setFixtures(
- '<div><div class="merge-request-container limit-container-width container-limited"></div></div>',
- );
- });
-
- it('removes limited container classes when on diffs tab', () => {
- createComponent({ isFluidLayout: false, shouldShow: true }, () => {}, {
- glFeatures: { mrChangesFluidLayout: true },
- });
-
- const containerClassList = document.querySelector('.merge-request-container').classList;
-
- expect(containerClassList).not.toContain('container-limited');
- expect(containerClassList).not.toContain('limit-container-width');
- });
- });
});
diff --git a/spec/frontend/diffs/components/diff_discussions_spec.js b/spec/frontend/diffs/components/diff_discussions_spec.js
index bd6f4cd2545..c847a79435a 100644
--- a/spec/frontend/diffs/components/diff_discussions_spec.js
+++ b/spec/frontend/diffs/components/diff_discussions_spec.js
@@ -1,6 +1,7 @@
import { GlIcon } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
+import { discussionIntersectionObserverHandlerFactory } from '~/diffs/utils/discussions';
import { createStore } from '~/mr_notes/stores';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
@@ -19,6 +20,9 @@ describe('DiffDiscussions', () => {
store = createStore();
wrapper = mount(localVue.extend(DiffDiscussions), {
store,
+ provide: {
+ discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
+ },
propsData: {
discussions: getDiscussionsMockData(),
...props,
diff --git a/spec/frontend/diffs/components/diff_file_header_spec.js b/spec/frontend/diffs/components/diff_file_header_spec.js
index b16ef8fe6b0..342b4bfcc50 100644
--- a/spec/frontend/diffs/components/diff_file_header_spec.js
+++ b/spec/frontend/diffs/components/diff_file_header_spec.js
@@ -7,7 +7,7 @@ import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
import { DIFF_FILE_AUTOMATIC_COLLAPSE, DIFF_FILE_MANUAL_COLLAPSE } from '~/diffs/constants';
import { reviewFile } from '~/diffs/store/actions';
-import { SET_MR_FILE_REVIEWS } from '~/diffs/store/mutation_types';
+import { SET_DIFF_FILE_VIEWED, SET_MR_FILE_REVIEWS } from '~/diffs/store/mutation_types';
import { diffViewerModes } from '~/ide/constants';
import { scrollToElement } from '~/lib/utils/common_utils';
import { truncateSha } from '~/lib/utils/text_utility';
@@ -23,6 +23,7 @@ jest.mock('~/lib/utils/common_utils');
const diffFile = Object.freeze(
Object.assign(diffDiscussionsMockData.diff_file, {
id: '123',
+ file_hash: 'xyz',
file_identifier_hash: 'abc',
edit_path: 'link:/to/edit/path',
blob: {
@@ -58,7 +59,7 @@ describe('DiffFileHeader component', () => {
toggleFileDiscussions: jest.fn(),
toggleFileDiscussionWrappers: jest.fn(),
toggleFullDiff: jest.fn(),
- toggleActiveFileByHash: jest.fn(),
+ setCurrentFileHash: jest.fn(),
setFileCollapsedByUser: jest.fn(),
reviewFile: jest.fn(),
},
@@ -240,18 +241,19 @@ describe('DiffFileHeader component', () => {
});
describe('for any file', () => {
- const otherModes = Object.keys(diffViewerModes).filter((m) => m !== 'mode_changed');
+ const allModes = Object.keys(diffViewerModes).map((m) => [m]);
- it('for mode_changed file mode displays mode changes', () => {
+ it.each(allModes)('for %s file mode displays mode changes', (mode) => {
createComponent({
props: {
diffFile: {
...diffFile,
+ mode_changed: true,
a_mode: 'old-mode',
b_mode: 'new-mode',
viewer: {
...diffFile.viewer,
- name: diffViewerModes.mode_changed,
+ name: diffViewerModes[mode],
},
},
},
@@ -259,13 +261,14 @@ describe('DiffFileHeader component', () => {
expect(findModeChangedLine().text()).toMatch(/old-mode.+new-mode/);
});
- it.each(otherModes.map((m) => [m]))(
+ it.each(allModes.filter((m) => m[0] !== 'mode_changed'))(
'for %s file mode does not display mode changes',
(mode) => {
createComponent({
props: {
diffFile: {
...diffFile,
+ mode_changed: false,
a_mode: 'old-mode',
b_mode: 'new-mode',
viewer: {
@@ -553,7 +556,13 @@ describe('DiffFileHeader component', () => {
reviewFile,
{ file, reviewed: true },
{},
- [{ type: SET_MR_FILE_REVIEWS, payload: { [file.file_identifier_hash]: [file.id] } }],
+ [
+ { type: SET_DIFF_FILE_VIEWED, payload: { id: file.file_hash, seen: true } },
+ {
+ type: SET_MR_FILE_REVIEWS,
+ payload: { [file.file_identifier_hash]: [file.id, `hash:${file.file_hash}`] },
+ },
+ ],
[],
);
});
diff --git a/spec/frontend/diffs/components/diff_line_note_form_spec.js b/spec/frontend/diffs/components/diff_line_note_form_spec.js
index a192f7e2e9a..0ccf996e220 100644
--- a/spec/frontend/diffs/components/diff_line_note_form_spec.js
+++ b/spec/frontend/diffs/components/diff_line_note_form_spec.js
@@ -1,10 +1,18 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DiffLineNoteForm from '~/diffs/components/diff_line_note_form.vue';
import { createStore } from '~/mr_notes/stores';
import NoteForm from '~/notes/components/note_form.vue';
+import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { noteableDataMock } from '../../notes/mock_data';
import diffFileMockData from '../mock_data/diff_file';
+jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal', () => {
+ return {
+ confirmAction: jest.fn(),
+ };
+});
+
describe('DiffLineNoteForm', () => {
let wrapper;
let diffFile;
@@ -24,57 +32,68 @@ describe('DiffLineNoteForm', () => {
return shallowMount(DiffLineNoteForm, {
store,
propsData: {
- diffFileHash: diffFile.file_hash,
- diffLines,
- line: diffLines[0],
- noteTargetLine: diffLines[0],
+ ...{
+ diffFileHash: diffFile.file_hash,
+ diffLines,
+ line: diffLines[1],
+ range: { start: diffLines[0], end: diffLines[1] },
+ noteTargetLine: diffLines[1],
+ },
+ ...(args.props || {}),
},
});
};
+ const findNoteForm = () => wrapper.findComponent(NoteForm);
+
describe('methods', () => {
beforeEach(() => {
wrapper = createComponent();
});
describe('handleCancelCommentForm', () => {
+ afterEach(() => {
+ confirmAction.mockReset();
+ });
+
it('should ask for confirmation when shouldConfirm and isDirty passed as truthy', () => {
- jest.spyOn(window, 'confirm').mockReturnValue(false);
+ confirmAction.mockResolvedValueOnce(false);
- wrapper.vm.handleCancelCommentForm(true, true);
+ findNoteForm().vm.$emit('cancelForm', true, true);
- expect(window.confirm).toHaveBeenCalled();
+ expect(confirmAction).toHaveBeenCalled();
});
- it('should ask for confirmation when one of the params false', () => {
- jest.spyOn(window, 'confirm').mockReturnValue(false);
+ it('should not ask for confirmation when one of the params false', () => {
+ confirmAction.mockResolvedValueOnce(false);
- wrapper.vm.handleCancelCommentForm(true, false);
+ findNoteForm().vm.$emit('cancelForm', true, false);
- expect(window.confirm).not.toHaveBeenCalled();
+ expect(confirmAction).not.toHaveBeenCalled();
- wrapper.vm.handleCancelCommentForm(false, true);
+ findNoteForm().vm.$emit('cancelForm', false, true);
- expect(window.confirm).not.toHaveBeenCalled();
+ expect(confirmAction).not.toHaveBeenCalled();
});
- it('should call cancelCommentForm with lineCode', (done) => {
- jest.spyOn(window, 'confirm').mockImplementation(() => {});
+ it('should call cancelCommentForm with lineCode', async () => {
+ confirmAction.mockResolvedValueOnce(true);
jest.spyOn(wrapper.vm, 'cancelCommentForm').mockImplementation(() => {});
jest.spyOn(wrapper.vm, 'resetAutoSave').mockImplementation(() => {});
- wrapper.vm.handleCancelCommentForm();
- expect(window.confirm).not.toHaveBeenCalled();
- wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.cancelCommentForm).toHaveBeenCalledWith({
- lineCode: diffLines[0].line_code,
- fileHash: wrapper.vm.diffFileHash,
- });
+ findNoteForm().vm.$emit('cancelForm', true, true);
+
+ await nextTick();
+
+ expect(confirmAction).toHaveBeenCalled();
- expect(wrapper.vm.resetAutoSave).toHaveBeenCalled();
+ await nextTick();
- done();
+ expect(wrapper.vm.cancelCommentForm).toHaveBeenCalledWith({
+ lineCode: diffLines[1].line_code,
+ fileHash: wrapper.vm.diffFileHash,
});
+ expect(wrapper.vm.resetAutoSave).toHaveBeenCalled();
});
});
@@ -88,13 +107,13 @@ describe('DiffLineNoteForm', () => {
start: {
line_code: wrapper.vm.commentLineStart.line_code,
type: wrapper.vm.commentLineStart.type,
- new_line: 1,
+ new_line: 2,
old_line: null,
},
end: {
line_code: wrapper.vm.line.line_code,
type: wrapper.vm.line.type,
- new_line: 1,
+ new_line: 2,
old_line: null,
},
};
@@ -118,9 +137,25 @@ describe('DiffLineNoteForm', () => {
});
});
+ describe('created', () => {
+ it('should use the provided `range` of lines', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.vm.lines.start).toBe(diffLines[0]);
+ expect(wrapper.vm.lines.end).toBe(diffLines[1]);
+ });
+
+ it("should fill the internal `lines` data with the provided `line` if there's no provided `range", () => {
+ wrapper = createComponent({ props: { range: null } });
+
+ expect(wrapper.vm.lines.start).toBe(diffLines[1]);
+ expect(wrapper.vm.lines.end).toBe(diffLines[1]);
+ });
+ });
+
describe('mounted', () => {
it('should init autosave', () => {
- const key = 'autosave/Note/Issue/98//DiffNote//1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_1';
+ const key = 'autosave/Note/Issue/98//DiffNote//1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2';
wrapper = createComponent();
expect(wrapper.vm.autosave).toBeDefined();
diff --git a/spec/frontend/diffs/components/tree_list_spec.js b/spec/frontend/diffs/components/tree_list_spec.js
index f316a9fdf01..31044b0818c 100644
--- a/spec/frontend/diffs/components/tree_list_spec.js
+++ b/spec/frontend/diffs/components/tree_list_spec.js
@@ -113,7 +113,9 @@ describe('Diffs tree list component', () => {
wrapper.find('.file-row').trigger('click');
- expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith('diffs/scrollToFile', 'app/index.js');
+ expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith('diffs/scrollToFile', {
+ path: 'app/index.js',
+ });
});
it('renders as file list when renderTreeList is false', () => {
diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js
index 85734e05aeb..b5003a54917 100644
--- a/spec/frontend/diffs/store/actions_spec.js
+++ b/spec/frontend/diffs/store/actions_spec.js
@@ -99,6 +99,10 @@ describe('DiffsStoreActions', () => {
const projectPath = '/root/project';
const dismissEndpoint = '/-/user_callouts';
const showSuggestPopover = false;
+ const mrReviews = {
+ a: ['z', 'hash:a'],
+ b: ['y', 'hash:a'],
+ };
testAction(
setBaseConfig,
@@ -110,6 +114,7 @@ describe('DiffsStoreActions', () => {
projectPath,
dismissEndpoint,
showSuggestPopover,
+ mrReviews,
},
{
endpoint: '',
@@ -131,8 +136,21 @@ describe('DiffsStoreActions', () => {
projectPath,
dismissEndpoint,
showSuggestPopover,
+ mrReviews,
},
},
+ {
+ type: types.SET_DIFF_FILE_VIEWED,
+ payload: { id: 'z', seen: true },
+ },
+ {
+ type: types.SET_DIFF_FILE_VIEWED,
+ payload: { id: 'a', seen: true },
+ },
+ {
+ type: types.SET_DIFF_FILE_VIEWED,
+ payload: { id: 'y', seen: true },
+ },
],
[],
done,
@@ -190,10 +208,10 @@ describe('DiffsStoreActions', () => {
{ type: types.SET_RETRIEVING_BATCHES, payload: true },
{ type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res1.diff_files } },
{ type: types.SET_BATCH_LOADING_STATE, payload: 'loaded' },
- { type: types.VIEW_DIFF_FILE, payload: 'test' },
+ { type: types.SET_CURRENT_DIFF_FILE, payload: 'test' },
{ type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res2.diff_files } },
{ type: types.SET_BATCH_LOADING_STATE, payload: 'loaded' },
- { type: types.VIEW_DIFF_FILE, payload: 'test2' },
+ { type: types.SET_CURRENT_DIFF_FILE, payload: 'test2' },
{ type: types.SET_RETRIEVING_BATCHES, payload: false },
{ type: types.SET_BATCH_LOADING_STATE, payload: 'error' },
],
@@ -307,7 +325,7 @@ describe('DiffsStoreActions', () => {
it('should mark currently selected diff and set lineHash and fileHash of highlightedRow', () => {
testAction(setHighlightedRow, 'ABC_123', {}, [
{ type: types.SET_HIGHLIGHTED_ROW, payload: 'ABC_123' },
- { type: types.VIEW_DIFF_FILE, payload: 'ABC' },
+ { type: types.SET_CURRENT_DIFF_FILE, payload: 'ABC' },
]);
});
});
@@ -890,12 +908,12 @@ describe('DiffsStoreActions', () => {
},
};
- scrollToFile({ state, commit, getters }, 'path');
+ scrollToFile({ state, commit, getters }, { path: 'path' });
expect(document.location.hash).toBe('#test');
});
- it('commits VIEW_DIFF_FILE', () => {
+ it('commits SET_CURRENT_DIFF_FILE', () => {
const state = {
treeEntries: {
path: {
@@ -904,9 +922,9 @@ describe('DiffsStoreActions', () => {
},
};
- scrollToFile({ state, commit, getters }, 'path');
+ scrollToFile({ state, commit, getters }, { path: 'path' });
- expect(commit).toHaveBeenCalledWith(types.VIEW_DIFF_FILE, 'test');
+ expect(commit).toHaveBeenCalledWith(types.SET_CURRENT_DIFF_FILE, 'test');
});
});
@@ -1428,7 +1446,7 @@ describe('DiffsStoreActions', () => {
});
describe('setCurrentDiffFileIdFromNote', () => {
- it('commits VIEW_DIFF_FILE', () => {
+ it('commits SET_CURRENT_DIFF_FILE', () => {
const commit = jest.fn();
const state = { diffFiles: [{ file_hash: '123' }] };
const rootGetters = {
@@ -1438,10 +1456,10 @@ describe('DiffsStoreActions', () => {
setCurrentDiffFileIdFromNote({ commit, state, rootGetters }, '1');
- expect(commit).toHaveBeenCalledWith(types.VIEW_DIFF_FILE, '123');
+ expect(commit).toHaveBeenCalledWith(types.SET_CURRENT_DIFF_FILE, '123');
});
- it('does not commit VIEW_DIFF_FILE when discussion has no diff_file', () => {
+ it('does not commit SET_CURRENT_DIFF_FILE when discussion has no diff_file', () => {
const commit = jest.fn();
const state = { diffFiles: [{ file_hash: '123' }] };
const rootGetters = {
@@ -1454,7 +1472,7 @@ describe('DiffsStoreActions', () => {
expect(commit).not.toHaveBeenCalled();
});
- it('does not commit VIEW_DIFF_FILE when diff file does not exist', () => {
+ it('does not commit SET_CURRENT_DIFF_FILE when diff file does not exist', () => {
const commit = jest.fn();
const state = { diffFiles: [{ file_hash: '123' }] };
const rootGetters = {
@@ -1469,12 +1487,12 @@ describe('DiffsStoreActions', () => {
});
describe('navigateToDiffFileIndex', () => {
- it('commits VIEW_DIFF_FILE', (done) => {
+ it('commits SET_CURRENT_DIFF_FILE', (done) => {
testAction(
navigateToDiffFileIndex,
0,
{ diffFiles: [{ file_hash: '123' }] },
- [{ type: types.VIEW_DIFF_FILE, payload: '123' }],
+ [{ type: types.SET_CURRENT_DIFF_FILE, payload: '123' }],
[],
done,
);
@@ -1523,13 +1541,14 @@ describe('DiffsStoreActions', () => {
describe('reviewFile', () => {
const file = {
id: '123',
+ file_hash: 'xyz',
file_identifier_hash: 'abc',
load_collapsed_diff_url: 'gitlab-org/gitlab-test/-/merge_requests/1/diffs',
};
it.each`
- reviews | diffFile | reviewed
- ${{ abc: ['123'] }} | ${file} | ${true}
- ${{}} | ${file} | ${false}
+ reviews | diffFile | reviewed
+ ${{ abc: ['123', 'hash:xyz'] }} | ${file} | ${true}
+ ${{}} | ${file} | ${false}
`(
'sets reviews ($reviews) to localStorage and state for file $file if it is marked reviewed=$reviewed',
({ reviews, diffFile, reviewed }) => {
diff --git a/spec/frontend/diffs/store/mutations_spec.js b/spec/frontend/diffs/store/mutations_spec.js
index fc9ba223d5a..c104fcd5fb9 100644
--- a/spec/frontend/diffs/store/mutations_spec.js
+++ b/spec/frontend/diffs/store/mutations_spec.js
@@ -633,16 +633,36 @@ describe('DiffsStoreMutations', () => {
});
});
- describe('VIEW_DIFF_FILE', () => {
+ describe('SET_CURRENT_DIFF_FILE', () => {
it('updates currentDiffFileId', () => {
const state = createState();
- mutations[types.VIEW_DIFF_FILE](state, 'somefileid');
+ mutations[types.SET_CURRENT_DIFF_FILE](state, 'somefileid');
expect(state.currentDiffFileId).toBe('somefileid');
});
});
+ describe('SET_DIFF_FILE_VIEWED', () => {
+ let state;
+
+ beforeEach(() => {
+ state = {
+ viewedDiffFileIds: { 123: true },
+ };
+ });
+
+ it.each`
+ id | bool | outcome
+ ${'abc'} | ${true} | ${{ 123: true, abc: true }}
+ ${'123'} | ${false} | ${{ 123: false }}
+ `('sets the viewed files list to $bool for the id $id', ({ id, bool, outcome }) => {
+ mutations[types.SET_DIFF_FILE_VIEWED](state, { id, seen: bool });
+
+ expect(state.viewedDiffFileIds).toEqual(outcome);
+ });
+ });
+
describe('Set highlighted row', () => {
it('sets highlighted row', () => {
const state = createState();
diff --git a/spec/frontend/diffs/utils/diff_line_spec.js b/spec/frontend/diffs/utils/diff_line_spec.js
new file mode 100644
index 00000000000..adcb4a4433c
--- /dev/null
+++ b/spec/frontend/diffs/utils/diff_line_spec.js
@@ -0,0 +1,30 @@
+import { pickDirection } from '~/diffs/utils/diff_line';
+
+describe('diff_line utilities', () => {
+ describe('pickDirection', () => {
+ const left = {
+ line_code: 'left',
+ };
+ const right = {
+ line_code: 'right',
+ };
+ const defaultLine = {
+ left,
+ right,
+ };
+
+ it.each`
+ code | pick | line | pickDescription
+ ${'left'} | ${left} | ${defaultLine} | ${'the left line'}
+ ${'right'} | ${right} | ${defaultLine} | ${'the right line'}
+ ${'junk'} | ${left} | ${defaultLine} | ${'the default: the left line'}
+ ${'junk'} | ${right} | ${{ right }} | ${"the right line if there's no left line to default to"}
+ ${'right'} | ${left} | ${{ left }} | ${"the left line when there isn't a right line to match"}
+ `(
+ 'when provided a line and a line code `$code`, picks $pickDescription',
+ ({ code, line, pick }) => {
+ expect(pickDirection({ line, code })).toBe(pick);
+ },
+ );
+ });
+});
diff --git a/spec/frontend/diffs/utils/discussions_spec.js b/spec/frontend/diffs/utils/discussions_spec.js
new file mode 100644
index 00000000000..9a3d442d943
--- /dev/null
+++ b/spec/frontend/diffs/utils/discussions_spec.js
@@ -0,0 +1,133 @@
+import { discussionIntersectionObserverHandlerFactory } from '~/diffs/utils/discussions';
+
+describe('Diff Discussions Utils', () => {
+ describe('discussionIntersectionObserverHandlerFactory', () => {
+ it('creates a handler function', () => {
+ expect(discussionIntersectionObserverHandlerFactory()).toBeInstanceOf(Function);
+ });
+
+ describe('intersection observer handler', () => {
+ const functions = {
+ setCurrentDiscussionId: jest.fn(),
+ getPreviousUnresolvedDiscussionId: jest.fn().mockImplementation((id) => {
+ return Number(id) - 1;
+ }),
+ };
+ const defaultProcessableWrapper = {
+ entry: {
+ time: 0,
+ isIntersecting: true,
+ rootBounds: {
+ bottom: 0,
+ },
+ boundingClientRect: {
+ top: 0,
+ },
+ },
+ currentDiscussion: {
+ id: 1,
+ },
+ isFirstUnresolved: false,
+ isDiffsPage: true,
+ };
+ let handler;
+ let getMock;
+ let setMock;
+
+ beforeEach(() => {
+ functions.setCurrentDiscussionId.mockClear();
+ functions.getPreviousUnresolvedDiscussionId.mockClear();
+
+ defaultProcessableWrapper.functions = functions;
+
+ setMock = functions.setCurrentDiscussionId.mock;
+ getMock = functions.getPreviousUnresolvedDiscussionId.mock;
+ handler = discussionIntersectionObserverHandlerFactory();
+ });
+
+ it('debounces multiple simultaneous requests into one queue', () => {
+ handler(defaultProcessableWrapper);
+ handler(defaultProcessableWrapper);
+ handler(defaultProcessableWrapper);
+ handler(defaultProcessableWrapper);
+
+ expect(setTimeout).toHaveBeenCalledTimes(4);
+ expect(clearTimeout).toHaveBeenCalledTimes(3);
+
+ // By only advancing to one timer, we ensure it's all being batched into one queue
+ jest.advanceTimersToNextTimer();
+
+ expect(functions.setCurrentDiscussionId).toHaveBeenCalledTimes(4);
+ });
+
+ it('properly processes, sorts and executes the correct actions for a set of observed intersections', () => {
+ handler(defaultProcessableWrapper);
+ handler({
+ // This observation is here to be filtered out because it's a scrollDown
+ ...defaultProcessableWrapper,
+ entry: {
+ ...defaultProcessableWrapper.entry,
+ isIntersecting: false,
+ boundingClientRect: { top: 10 },
+ rootBounds: { bottom: 100 },
+ },
+ });
+ handler({
+ ...defaultProcessableWrapper,
+ entry: {
+ ...defaultProcessableWrapper.entry,
+ time: 101,
+ isIntersecting: false,
+ rootBounds: { bottom: -100 },
+ },
+ currentDiscussion: { id: 20 },
+ });
+ handler({
+ ...defaultProcessableWrapper,
+ entry: {
+ ...defaultProcessableWrapper.entry,
+ time: 100,
+ isIntersecting: false,
+ boundingClientRect: { top: 100 },
+ },
+ currentDiscussion: { id: 30 },
+ isDiffsPage: false,
+ });
+ handler({
+ ...defaultProcessableWrapper,
+ isFirstUnresolved: true,
+ entry: {
+ ...defaultProcessableWrapper.entry,
+ time: 100,
+ isIntersecting: false,
+ boundingClientRect: { top: 200 },
+ },
+ });
+
+ jest.advanceTimersToNextTimer();
+
+ expect(setMock.calls.length).toBe(4);
+ expect(setMock.calls[0]).toEqual([1]);
+ expect(setMock.calls[1]).toEqual([29]);
+ expect(setMock.calls[2]).toEqual([null]);
+ expect(setMock.calls[3]).toEqual([19]);
+
+ expect(getMock.calls.length).toBe(2);
+ expect(getMock.calls[0]).toEqual([30, false]);
+ expect(getMock.calls[1]).toEqual([20, true]);
+
+ [
+ setMock.invocationCallOrder[0],
+ getMock.invocationCallOrder[0],
+ setMock.invocationCallOrder[1],
+ setMock.invocationCallOrder[2],
+ getMock.invocationCallOrder[1],
+ setMock.invocationCallOrder[3],
+ ].forEach((order, idx, list) => {
+ // Compare each invocation sequence to the one before it (except the first one)
+ expect(list[idx - 1] || -1).toBeLessThan(order);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/diffs/utils/file_reviews_spec.js b/spec/frontend/diffs/utils/file_reviews_spec.js
index 230ec12409c..ccd27a5ae3e 100644
--- a/spec/frontend/diffs/utils/file_reviews_spec.js
+++ b/spec/frontend/diffs/utils/file_reviews_spec.js
@@ -11,14 +11,14 @@ import {
function getDefaultReviews() {
return {
- abc: ['123', '098'],
+ abc: ['123', 'hash:xyz', '098', 'hash:uvw'],
};
}
describe('File Review(s) utilities', () => {
const mrPath = 'my/fake/mr/42';
const storageKey = `${mrPath}-file-reviews`;
- const file = { id: '123', file_identifier_hash: 'abc' };
+ const file = { id: '123', file_hash: 'xyz', file_identifier_hash: 'abc' };
const storedValue = JSON.stringify(getDefaultReviews());
let reviews;
@@ -44,14 +44,14 @@ describe('File Review(s) utilities', () => {
});
describe('reviewStatuses', () => {
- const file1 = { id: '123', file_identifier_hash: 'abc' };
- const file2 = { id: '098', file_identifier_hash: 'abc' };
+ const file1 = { id: '123', hash: 'xyz', file_identifier_hash: 'abc' };
+ const file2 = { id: '098', hash: 'uvw', file_identifier_hash: 'abc' };
it.each`
mrReviews | files | fileReviews
${{}} | ${[file1, file2]} | ${{ 123: false, '098': false }}
- ${{ abc: ['123'] }} | ${[file1, file2]} | ${{ 123: true, '098': false }}
- ${{ abc: ['098'] }} | ${[file1, file2]} | ${{ 123: false, '098': true }}
+ ${{ abc: ['123', 'hash:xyz'] }} | ${[file1, file2]} | ${{ 123: true, '098': false }}
+ ${{ abc: ['098', 'hash:uvw'] }} | ${[file1, file2]} | ${{ 123: false, '098': true }}
${{ def: ['123'] }} | ${[file1, file2]} | ${{ 123: false, '098': false }}
${{ abc: ['123'], def: ['098'] }} | ${[]} | ${{}}
`(
@@ -128,7 +128,7 @@ describe('File Review(s) utilities', () => {
describe('markFileReview', () => {
it("adds a review when there's nothing that already exists", () => {
- expect(markFileReview(null, file)).toStrictEqual({ abc: ['123'] });
+ expect(markFileReview(null, file)).toStrictEqual({ abc: ['123', 'hash:xyz'] });
});
it("overwrites an existing review if it's for the same file (identifier hash)", () => {
@@ -136,15 +136,15 @@ describe('File Review(s) utilities', () => {
});
it('removes a review from the list when `reviewed` is `false`', () => {
- expect(markFileReview(reviews, file, false)).toStrictEqual({ abc: ['098'] });
+ expect(markFileReview(reviews, file, false)).toStrictEqual({ abc: ['098', 'hash:uvw'] });
});
it('adds a new review if the file ID is new', () => {
- const updatedFile = { ...file, id: '098' };
- const allReviews = markFileReview({ abc: ['123'] }, updatedFile);
+ const updatedFile = { ...file, id: '098', file_hash: 'uvw' };
+ const allReviews = markFileReview({ abc: ['123', 'hash:xyz'] }, updatedFile);
expect(allReviews).toStrictEqual(getDefaultReviews());
- expect(allReviews.abc).toStrictEqual(['123', '098']);
+ expect(allReviews.abc).toStrictEqual(['123', 'hash:xyz', '098', 'hash:uvw']);
});
it.each`
@@ -158,7 +158,7 @@ describe('File Review(s) utilities', () => {
it('removes the file key if there are no more reviews for it', () => {
let updated = markFileReview(reviews, file, false);
- updated = markFileReview(updated, { ...file, id: '098' }, false);
+ updated = markFileReview(updated, { ...file, id: '098', file_hash: 'uvw' }, false);
expect(updated).toStrictEqual({});
});
diff --git a/spec/frontend/dropzone_input_spec.js b/spec/frontend/dropzone_input_spec.js
index acf7d0780cd..12e10f7c5f4 100644
--- a/spec/frontend/dropzone_input_spec.js
+++ b/spec/frontend/dropzone_input_spec.js
@@ -71,6 +71,7 @@ describe('dropzone_input', () => {
triggerPasteEvent({
types: ['text/plain', 'text/html', 'text/rtf', 'Files'],
getData: () => longFileName,
+ files: [new File([new Blob()], longFileName, { type: 'image/png' })],
items: [
{
kind: 'file',
@@ -84,6 +85,24 @@ describe('dropzone_input', () => {
await waitForPromises();
expect(axiosMock.history.post[0].data.get('file').name).toHaveLength(246);
});
+
+ it('display original file name in comment box', async () => {
+ const axiosMock = new MockAdapter(axios);
+ triggerPasteEvent({
+ types: ['Files'],
+ files: [new File([new Blob()], 'test.png', { type: 'image/png' })],
+ items: [
+ {
+ kind: 'file',
+ type: 'image/png',
+ getAsFile: () => new Blob(),
+ },
+ ],
+ });
+ axiosMock.onPost().reply(httpStatusCodes.OK, { link: { markdown: 'foo' } });
+ await waitForPromises();
+ expect(axiosMock.history.post[0].data.get('file').name).toEqual('test.png');
+ });
});
describe('shows error message', () => {
diff --git a/spec/frontend/editor/helpers.js b/spec/frontend/editor/helpers.js
new file mode 100644
index 00000000000..6f7cdf6efb3
--- /dev/null
+++ b/spec/frontend/editor/helpers.js
@@ -0,0 +1,53 @@
+export class MyClassExtension {
+ // eslint-disable-next-line class-methods-use-this
+ provides() {
+ return {
+ shared: () => 'extension',
+ classExtMethod: () => 'class own method',
+ };
+ }
+}
+
+export function MyFnExtension() {
+ return {
+ fnExtMethod: () => 'fn own method',
+ provides: () => {
+ return {
+ fnExtMethod: () => 'class own method',
+ };
+ },
+ };
+}
+
+export const MyConstExt = () => {
+ return {
+ provides: () => {
+ return {
+ constExtMethod: () => 'const own method',
+ };
+ },
+ };
+};
+
+export const conflictingExtensions = {
+ WithInstanceExt: () => {
+ return {
+ provides: () => {
+ return {
+ use: () => 'A conflict with instance',
+ ownMethod: () => 'Non-conflicting method',
+ };
+ },
+ };
+ },
+ WithAnotherExt: () => {
+ return {
+ provides: () => {
+ return {
+ shared: () => 'A conflict with extension',
+ ownMethod: () => 'Non-conflicting method',
+ };
+ },
+ };
+ },
+};
diff --git a/spec/frontend/editor/source_editor_extension_base_spec.js b/spec/frontend/editor/source_editor_extension_base_spec.js
index 2c06ae03892..a0fb1178b3b 100644
--- a/spec/frontend/editor/source_editor_extension_base_spec.js
+++ b/spec/frontend/editor/source_editor_extension_base_spec.js
@@ -148,7 +148,10 @@ describe('The basis for an Source Editor extension', () => {
revealLineInCenter: revealSpy,
deltaDecorations: decorationsSpy,
};
- const defaultDecorationOptions = { isWholeLine: true, className: 'active-line-text' };
+ const defaultDecorationOptions = {
+ isWholeLine: true,
+ className: 'active-line-text',
+ };
useFakeRequestAnimationFrame();
@@ -157,18 +160,22 @@ describe('The basis for an Source Editor extension', () => {
});
it.each`
- desc | hash | shouldReveal | expectedRange
- ${'properly decorates a single line'} | ${'#L10'} | ${true} | ${[10, 1, 10, 1]}
- ${'properly decorates multiple lines'} | ${'#L7-42'} | ${true} | ${[7, 1, 42, 1]}
- ${'correctly highlights if lines are reversed'} | ${'#L42-7'} | ${true} | ${[7, 1, 42, 1]}
- ${'highlights one line if start/end are the same'} | ${'#L7-7'} | ${true} | ${[7, 1, 7, 1]}
- ${'does not highlight if there is no hash'} | ${''} | ${false} | ${null}
- ${'does not highlight if the hash is undefined'} | ${undefined} | ${false} | ${null}
- ${'does not highlight if hash is incomplete 1'} | ${'#L'} | ${false} | ${null}
- ${'does not highlight if hash is incomplete 2'} | ${'#L-'} | ${false} | ${null}
- `('$desc', ({ hash, shouldReveal, expectedRange } = {}) => {
+ desc | hash | bounds | shouldReveal | expectedRange
+ ${'properly decorates a single line'} | ${'#L10'} | ${undefined} | ${true} | ${[10, 1, 10, 1]}
+ ${'properly decorates multiple lines'} | ${'#L7-42'} | ${undefined} | ${true} | ${[7, 1, 42, 1]}
+ ${'correctly highlights if lines are reversed'} | ${'#L42-7'} | ${undefined} | ${true} | ${[7, 1, 42, 1]}
+ ${'highlights one line if start/end are the same'} | ${'#L7-7'} | ${undefined} | ${true} | ${[7, 1, 7, 1]}
+ ${'does not highlight if there is no hash'} | ${''} | ${undefined} | ${false} | ${null}
+ ${'does not highlight if the hash is undefined'} | ${undefined} | ${undefined} | ${false} | ${null}
+ ${'does not highlight if hash is incomplete 1'} | ${'#L'} | ${undefined} | ${false} | ${null}
+ ${'does not highlight if hash is incomplete 2'} | ${'#L-'} | ${undefined} | ${false} | ${null}
+ ${'highlights lines if bounds are passed'} | ${undefined} | ${[17, 42]} | ${true} | ${[17, 1, 42, 1]}
+ ${'highlights one line if bounds has a single value'} | ${undefined} | ${[17]} | ${true} | ${[17, 1, 17, 1]}
+ ${'does not highlight if bounds is invalid'} | ${undefined} | ${[Number.NaN]} | ${false} | ${null}
+ ${'uses bounds if both hash and bounds exist'} | ${'#L7-42'} | ${[3, 5]} | ${true} | ${[3, 1, 5, 1]}
+ `('$desc', ({ hash, bounds, shouldReveal, expectedRange } = {}) => {
window.location.hash = hash;
- SourceEditorExtension.highlightLines(instance);
+ SourceEditorExtension.highlightLines(instance, bounds);
if (!shouldReveal) {
expect(revealSpy).not.toHaveBeenCalled();
expect(decorationsSpy).not.toHaveBeenCalled();
@@ -193,6 +200,43 @@ describe('The basis for an Source Editor extension', () => {
SourceEditorExtension.highlightLines(instance);
expect(instance.lineDecorations).toBe('foo');
});
+
+ it('replaces existing line highlights', () => {
+ const oldLineDecorations = [
+ {
+ range: new Range(1, 1, 20, 1),
+ options: { isWholeLine: true, className: 'active-line-text' },
+ },
+ ];
+ const newLineDecorations = [
+ {
+ range: new Range(7, 1, 10, 1),
+ options: { isWholeLine: true, className: 'active-line-text' },
+ },
+ ];
+ instance.lineDecorations = oldLineDecorations;
+ SourceEditorExtension.highlightLines(instance, [7, 10]);
+ expect(decorationsSpy).toHaveBeenCalledWith(oldLineDecorations, newLineDecorations);
+ });
+ });
+
+ describe('removeHighlights', () => {
+ const decorationsSpy = jest.fn();
+ const lineDecorations = [
+ {
+ range: new Range(1, 1, 20, 1),
+ options: { isWholeLine: true, className: 'active-line-text' },
+ },
+ ];
+ const instance = {
+ deltaDecorations: decorationsSpy,
+ lineDecorations,
+ };
+
+ it('removes all existing decorations', () => {
+ SourceEditorExtension.removeHighlights(instance);
+ expect(decorationsSpy).toHaveBeenCalledWith(lineDecorations, []);
+ });
});
describe('setupLineLinking', () => {
diff --git a/spec/frontend/editor/source_editor_extension_spec.js b/spec/frontend/editor/source_editor_extension_spec.js
new file mode 100644
index 00000000000..6f2eb07a043
--- /dev/null
+++ b/spec/frontend/editor/source_editor_extension_spec.js
@@ -0,0 +1,65 @@
+import EditorExtension from '~/editor/source_editor_extension';
+import { EDITOR_EXTENSION_DEFINITION_ERROR } from '~/editor/constants';
+import * as helpers from './helpers';
+
+describe('Editor Extension', () => {
+ const dummyObj = { foo: 'bar' };
+
+ it.each`
+ definition | setupOptions
+ ${undefined} | ${undefined}
+ ${undefined} | ${{}}
+ ${undefined} | ${dummyObj}
+ ${{}} | ${dummyObj}
+ ${dummyObj} | ${dummyObj}
+ `(
+ 'throws when definition = $definition and setupOptions = $setupOptions',
+ ({ definition, setupOptions }) => {
+ const constructExtension = () => new EditorExtension({ definition, setupOptions });
+ expect(constructExtension).toThrowError(EDITOR_EXTENSION_DEFINITION_ERROR);
+ },
+ );
+
+ it.each`
+ definition | setupOptions | expectedName
+ ${helpers.MyClassExtension} | ${undefined} | ${'MyClassExtension'}
+ ${helpers.MyClassExtension} | ${{}} | ${'MyClassExtension'}
+ ${helpers.MyClassExtension} | ${dummyObj} | ${'MyClassExtension'}
+ ${helpers.MyFnExtension} | ${undefined} | ${'MyFnExtension'}
+ ${helpers.MyFnExtension} | ${{}} | ${'MyFnExtension'}
+ ${helpers.MyFnExtension} | ${dummyObj} | ${'MyFnExtension'}
+ ${helpers.MyConstExt} | ${undefined} | ${'MyConstExt'}
+ ${helpers.MyConstExt} | ${{}} | ${'MyConstExt'}
+ ${helpers.MyConstExt} | ${dummyObj} | ${'MyConstExt'}
+ `(
+ 'correctly creates extension for definition = $definition and setupOptions = $setupOptions',
+ ({ definition, setupOptions, expectedName }) => {
+ const extension = new EditorExtension({ definition, setupOptions });
+ // eslint-disable-next-line new-cap
+ const constructedDefinition = new definition();
+
+ expect(extension).toEqual(
+ expect.objectContaining({
+ name: expectedName,
+ setupOptions,
+ }),
+ );
+ expect(extension.obj.constructor.prototype).toBe(constructedDefinition.constructor.prototype);
+ },
+ );
+
+ describe('api', () => {
+ it.each`
+ definition | expectedKeys
+ ${helpers.MyClassExtension} | ${['shared', 'classExtMethod']}
+ ${helpers.MyFnExtension} | ${['fnExtMethod']}
+ ${helpers.MyConstExt} | ${['constExtMethod']}
+ `('correctly returns API for $definition', ({ definition, expectedKeys }) => {
+ const extension = new EditorExtension({ definition });
+ const expectedApi = Object.fromEntries(
+ expectedKeys.map((key) => [key, expect.any(Function)]),
+ );
+ expect(extension.api).toEqual(expect.objectContaining(expectedApi));
+ });
+ });
+});
diff --git a/spec/frontend/editor/source_editor_instance_spec.js b/spec/frontend/editor/source_editor_instance_spec.js
new file mode 100644
index 00000000000..87b20a4ba73
--- /dev/null
+++ b/spec/frontend/editor/source_editor_instance_spec.js
@@ -0,0 +1,387 @@
+import { editor as monacoEditor } from 'monaco-editor';
+import {
+ EDITOR_EXTENSION_NAMING_CONFLICT_ERROR,
+ EDITOR_EXTENSION_NO_DEFINITION_ERROR,
+ EDITOR_EXTENSION_DEFINITION_TYPE_ERROR,
+ EDITOR_EXTENSION_NOT_REGISTERED_ERROR,
+ EDITOR_EXTENSION_NOT_SPECIFIED_FOR_UNUSE_ERROR,
+} from '~/editor/constants';
+import Instance from '~/editor/source_editor_instance';
+import { sprintf } from '~/locale';
+import { MyClassExtension, conflictingExtensions, MyFnExtension, MyConstExt } from './helpers';
+
+describe('Source Editor Instance', () => {
+ let seInstance;
+
+ const defSetupOptions = { foo: 'bar' };
+ const fullExtensionsArray = [
+ { definition: MyClassExtension },
+ { definition: MyFnExtension },
+ { definition: MyConstExt },
+ ];
+ const fullExtensionsArrayWithOptions = [
+ { definition: MyClassExtension, setupOptions: defSetupOptions },
+ { definition: MyFnExtension, setupOptions: defSetupOptions },
+ { definition: MyConstExt, setupOptions: defSetupOptions },
+ ];
+
+ const fooFn = jest.fn();
+ class DummyExt {
+ // eslint-disable-next-line class-methods-use-this
+ provides() {
+ return {
+ fooFn,
+ };
+ }
+ }
+
+ afterEach(() => {
+ seInstance = undefined;
+ });
+
+ it('sets up the registry for the methods coming from extensions', () => {
+ seInstance = new Instance();
+ expect(seInstance.methods).toBeDefined();
+
+ seInstance.use({ definition: MyClassExtension });
+ expect(seInstance.methods).toEqual({
+ shared: 'MyClassExtension',
+ classExtMethod: 'MyClassExtension',
+ });
+
+ seInstance.use({ definition: MyFnExtension });
+ expect(seInstance.methods).toEqual({
+ shared: 'MyClassExtension',
+ classExtMethod: 'MyClassExtension',
+ fnExtMethod: 'MyFnExtension',
+ });
+ });
+
+ describe('proxy', () => {
+ it('returns prop from an extension if extension provides it', () => {
+ seInstance = new Instance();
+ seInstance.use({ definition: DummyExt });
+
+ expect(fooFn).not.toHaveBeenCalled();
+ seInstance.fooFn();
+ expect(fooFn).toHaveBeenCalled();
+ });
+
+ it('returns props from SE instance itself if no extension provides the prop', () => {
+ seInstance = new Instance({
+ use: fooFn,
+ });
+ jest.spyOn(seInstance, 'use').mockImplementation(() => {});
+ expect(seInstance.use).not.toHaveBeenCalled();
+ expect(fooFn).not.toHaveBeenCalled();
+ seInstance.use();
+ expect(seInstance.use).toHaveBeenCalled();
+ expect(fooFn).not.toHaveBeenCalled();
+ });
+
+ it('returns props from Monaco instance when the prop does not exist on the SE instance', () => {
+ seInstance = new Instance({
+ fooFn,
+ });
+
+ expect(fooFn).not.toHaveBeenCalled();
+ seInstance.fooFn();
+ expect(fooFn).toHaveBeenCalled();
+ });
+ });
+
+ describe('public API', () => {
+ it.each(['use', 'unuse'], 'provides "%s" as public method by default', (method) => {
+ seInstance = new Instance();
+ expect(seInstance[method]).toBeDefined();
+ });
+
+ describe('use', () => {
+ it('extends the SE instance with methods provided by an extension', () => {
+ seInstance = new Instance();
+ seInstance.use({ definition: DummyExt });
+
+ expect(fooFn).not.toHaveBeenCalled();
+ seInstance.fooFn();
+ expect(fooFn).toHaveBeenCalled();
+ });
+
+ it.each`
+ extensions | expectedProps
+ ${{ definition: MyClassExtension }} | ${['shared', 'classExtMethod']}
+ ${{ definition: MyFnExtension }} | ${['fnExtMethod']}
+ ${{ definition: MyConstExt }} | ${['constExtMethod']}
+ ${fullExtensionsArray} | ${['shared', 'classExtMethod', 'fnExtMethod', 'constExtMethod']}
+ ${fullExtensionsArrayWithOptions} | ${['shared', 'classExtMethod', 'fnExtMethod', 'constExtMethod']}
+ `(
+ 'Should register $expectedProps when extension is "$extensions"',
+ ({ extensions, expectedProps }) => {
+ seInstance = new Instance();
+ expect(seInstance.extensionsAPI).toHaveLength(0);
+
+ seInstance.use(extensions);
+
+ expect(seInstance.extensionsAPI).toEqual(expectedProps);
+ },
+ );
+
+ it.each`
+ definition | preInstalledExtDefinition | expectedErrorProp
+ ${conflictingExtensions.WithInstanceExt} | ${MyClassExtension} | ${'use'}
+ ${conflictingExtensions.WithInstanceExt} | ${null} | ${'use'}
+ ${conflictingExtensions.WithAnotherExt} | ${null} | ${undefined}
+ ${conflictingExtensions.WithAnotherExt} | ${MyClassExtension} | ${'shared'}
+ ${MyClassExtension} | ${conflictingExtensions.WithAnotherExt} | ${'shared'}
+ `(
+ 'logs the naming conflict error when registering $definition',
+ ({ definition, preInstalledExtDefinition, expectedErrorProp }) => {
+ seInstance = new Instance();
+ jest.spyOn(console, 'error').mockImplementation(() => {});
+
+ if (preInstalledExtDefinition) {
+ seInstance.use({ definition: preInstalledExtDefinition });
+ // eslint-disable-next-line no-console
+ expect(console.error).not.toHaveBeenCalled();
+ }
+
+ seInstance.use({ definition });
+
+ if (expectedErrorProp) {
+ // eslint-disable-next-line no-console
+ expect(console.error).toHaveBeenCalledWith(
+ expect.any(String),
+ expect.stringContaining(
+ sprintf(EDITOR_EXTENSION_NAMING_CONFLICT_ERROR, { prop: expectedErrorProp }),
+ ),
+ );
+ } else {
+ // eslint-disable-next-line no-console
+ expect(console.error).not.toHaveBeenCalled();
+ }
+ },
+ );
+
+ it.each`
+ extensions | thrownError
+ ${''} | ${EDITOR_EXTENSION_NO_DEFINITION_ERROR}
+ ${undefined} | ${EDITOR_EXTENSION_NO_DEFINITION_ERROR}
+ ${{}} | ${EDITOR_EXTENSION_NO_DEFINITION_ERROR}
+ ${{ foo: 'bar' }} | ${EDITOR_EXTENSION_NO_DEFINITION_ERROR}
+ ${{ definition: '' }} | ${EDITOR_EXTENSION_NO_DEFINITION_ERROR}
+ ${{ definition: undefined }} | ${EDITOR_EXTENSION_NO_DEFINITION_ERROR}
+ ${{ definition: [] }} | ${EDITOR_EXTENSION_DEFINITION_TYPE_ERROR}
+ ${{ definition: {} }} | ${EDITOR_EXTENSION_DEFINITION_TYPE_ERROR}
+ ${{ definition: { foo: 'bar' } }} | ${EDITOR_EXTENSION_DEFINITION_TYPE_ERROR}
+ `(
+ 'Should throw $thrownError when extension is "$extensions"',
+ ({ extensions, thrownError }) => {
+ seInstance = new Instance();
+ const useExtension = () => {
+ seInstance.use(extensions);
+ };
+ expect(useExtension).toThrowError(thrownError);
+ },
+ );
+
+ describe('global extensions registry', () => {
+ let extensionStore;
+
+ beforeEach(() => {
+ extensionStore = new Map();
+ seInstance = new Instance({}, extensionStore);
+ });
+
+ it('stores _instances_ of the used extensions in a global registry', () => {
+ const extension = seInstance.use({ definition: MyClassExtension });
+
+ expect(extensionStore.size).toBe(1);
+ expect(extensionStore.entries().next().value).toEqual(['MyClassExtension', extension]);
+ });
+
+ it('does not duplicate entries in the registry', () => {
+ jest.spyOn(extensionStore, 'set');
+
+ const extension1 = seInstance.use({ definition: MyClassExtension });
+ seInstance.use({ definition: MyClassExtension });
+
+ expect(extensionStore.set).toHaveBeenCalledTimes(1);
+ expect(extensionStore.set).toHaveBeenCalledWith('MyClassExtension', extension1);
+ });
+
+ it.each`
+ desc | currentSetupOptions | newSetupOptions | expectedCallTimes
+ ${'updates'} | ${undefined} | ${defSetupOptions} | ${2}
+ ${'updates'} | ${defSetupOptions} | ${undefined} | ${2}
+ ${'updates'} | ${{ foo: 'bar' }} | ${{ foo: 'new' }} | ${2}
+ ${'does not update'} | ${undefined} | ${undefined} | ${1}
+ ${'does not update'} | ${{}} | ${{}} | ${1}
+ ${'does not update'} | ${defSetupOptions} | ${defSetupOptions} | ${1}
+ `(
+ '$desc the extensions entry when setupOptions "$currentSetupOptions" get changed to "$newSetupOptions"',
+ ({ currentSetupOptions, newSetupOptions, expectedCallTimes }) => {
+ jest.spyOn(extensionStore, 'set');
+
+ const extension1 = seInstance.use({
+ definition: MyClassExtension,
+ setupOptions: currentSetupOptions,
+ });
+ const extension2 = seInstance.use({
+ definition: MyClassExtension,
+ setupOptions: newSetupOptions,
+ });
+
+ expect(extensionStore.size).toBe(1);
+ expect(extensionStore.set).toHaveBeenCalledTimes(expectedCallTimes);
+ if (expectedCallTimes > 1) {
+ expect(extensionStore.set).toHaveBeenCalledWith('MyClassExtension', extension2);
+ } else {
+ expect(extensionStore.set).toHaveBeenCalledWith('MyClassExtension', extension1);
+ }
+ },
+ );
+ });
+ });
+
+ describe('unuse', () => {
+ it.each`
+ unuseExtension | thrownError
+ ${undefined} | ${EDITOR_EXTENSION_NOT_SPECIFIED_FOR_UNUSE_ERROR}
+ ${''} | ${EDITOR_EXTENSION_NOT_SPECIFIED_FOR_UNUSE_ERROR}
+ ${{}} | ${sprintf(EDITOR_EXTENSION_NOT_REGISTERED_ERROR, { name: '' })}
+ ${[]} | ${EDITOR_EXTENSION_NOT_SPECIFIED_FOR_UNUSE_ERROR}
+ `(
+ `Should throw "${EDITOR_EXTENSION_NOT_SPECIFIED_FOR_UNUSE_ERROR}" when extension is "$unuseExtension"`,
+ ({ unuseExtension, thrownError }) => {
+ seInstance = new Instance();
+ const unuse = () => {
+ seInstance.unuse(unuseExtension);
+ };
+ expect(unuse).toThrowError(thrownError);
+ },
+ );
+
+ it.each`
+ initExtensions | unuseExtensionIndex | remainingAPI
+ ${{ definition: MyClassExtension }} | ${0} | ${[]}
+ ${{ definition: MyFnExtension }} | ${0} | ${[]}
+ ${{ definition: MyConstExt }} | ${0} | ${[]}
+ ${fullExtensionsArray} | ${0} | ${['fnExtMethod', 'constExtMethod']}
+ ${fullExtensionsArray} | ${1} | ${['shared', 'classExtMethod', 'constExtMethod']}
+ ${fullExtensionsArray} | ${2} | ${['shared', 'classExtMethod', 'fnExtMethod']}
+ `(
+ 'un-registers properties introduced by single extension $unuseExtension',
+ ({ initExtensions, unuseExtensionIndex, remainingAPI }) => {
+ seInstance = new Instance();
+ const extensions = seInstance.use(initExtensions);
+
+ if (Array.isArray(initExtensions)) {
+ seInstance.unuse(extensions[unuseExtensionIndex]);
+ } else {
+ seInstance.unuse(extensions);
+ }
+ expect(seInstance.extensionsAPI).toEqual(remainingAPI);
+ },
+ );
+
+ it.each`
+ unuseExtensionIndex | remainingAPI
+ ${[0, 1]} | ${['constExtMethod']}
+ ${[0, 2]} | ${['fnExtMethod']}
+ ${[1, 2]} | ${['shared', 'classExtMethod']}
+ `(
+ 'un-registers properties introduced by multiple extensions $unuseExtension',
+ ({ unuseExtensionIndex, remainingAPI }) => {
+ seInstance = new Instance();
+ const extensions = seInstance.use(fullExtensionsArray);
+ const extensionsToUnuse = extensions.filter((ext, index) =>
+ unuseExtensionIndex.includes(index),
+ );
+
+ seInstance.unuse(extensionsToUnuse);
+ expect(seInstance.extensionsAPI).toEqual(remainingAPI);
+ },
+ );
+
+ it('it does not remove entry from the global registry to keep for potential future re-use', () => {
+ const extensionStore = new Map();
+ seInstance = new Instance({}, extensionStore);
+ const extensions = seInstance.use(fullExtensionsArray);
+ const verifyExpectations = () => {
+ const entries = extensionStore.entries();
+ const mockExtensions = ['MyClassExtension', 'MyFnExtension', 'MyConstExt'];
+ expect(extensionStore.size).toBe(mockExtensions.length);
+ mockExtensions.forEach((ext, index) => {
+ expect(entries.next().value).toEqual([ext, extensions[index]]);
+ });
+ };
+
+ verifyExpectations();
+ seInstance.unuse(extensions);
+ verifyExpectations();
+ });
+ });
+
+ describe('updateModelLanguage', () => {
+ let instanceModel;
+
+ beforeEach(() => {
+ instanceModel = monacoEditor.createModel('');
+ seInstance = new Instance({
+ getModel: () => instanceModel,
+ });
+ });
+
+ it.each`
+ path | expectedLanguage
+ ${'foo.js'} | ${'javascript'}
+ ${'foo.md'} | ${'markdown'}
+ ${'foo.rb'} | ${'ruby'}
+ ${''} | ${'plaintext'}
+ ${undefined} | ${'plaintext'}
+ ${'test.nonexistingext'} | ${'plaintext'}
+ `(
+ 'changes language of an attached model to "$expectedLanguage" when filepath is "$path"',
+ ({ path, expectedLanguage }) => {
+ seInstance.updateModelLanguage(path);
+ expect(instanceModel.getLanguageIdentifier().language).toBe(expectedLanguage);
+ },
+ );
+ });
+
+ describe('extensions life-cycle callbacks', () => {
+ const onSetup = jest.fn().mockImplementation(() => {});
+ const onUse = jest.fn().mockImplementation(() => {});
+ const onBeforeUnuse = jest.fn().mockImplementation(() => {});
+ const onUnuse = jest.fn().mockImplementation(() => {});
+ const MyFullExtWithCallbacks = () => {
+ return {
+ onSetup,
+ onUse,
+ onBeforeUnuse,
+ onUnuse,
+ };
+ };
+
+ it('passes correct arguments to callback fns when using an extension', () => {
+ seInstance = new Instance();
+ seInstance.use({
+ definition: MyFullExtWithCallbacks,
+ setupOptions: defSetupOptions,
+ });
+ expect(onSetup).toHaveBeenCalledWith(defSetupOptions, seInstance);
+ expect(onUse).toHaveBeenCalledWith(seInstance);
+ });
+
+ it('passes correct arguments to callback fns when un-using an extension', () => {
+ seInstance = new Instance();
+ const extension = seInstance.use({
+ definition: MyFullExtWithCallbacks,
+ setupOptions: defSetupOptions,
+ });
+ seInstance.unuse(extension);
+ expect(onBeforeUnuse).toHaveBeenCalledWith(seInstance);
+ expect(onUnuse).toHaveBeenCalledWith(seInstance);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/editor/source_editor_yaml_ext_spec.js b/spec/frontend/editor/source_editor_yaml_ext_spec.js
new file mode 100644
index 00000000000..97d2b0b21d0
--- /dev/null
+++ b/spec/frontend/editor/source_editor_yaml_ext_spec.js
@@ -0,0 +1,449 @@
+import { Document } from 'yaml';
+import SourceEditor from '~/editor/source_editor';
+import { YamlEditorExtension } from '~/editor/extensions/source_editor_yaml_ext';
+import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
+
+const getEditorInstance = (editorInstanceOptions = {}) => {
+ setFixtures('<div id="editor"></div>');
+ return new SourceEditor().createInstance({
+ el: document.getElementById('editor'),
+ blobPath: '.gitlab-ci.yml',
+ language: 'yaml',
+ ...editorInstanceOptions,
+ });
+};
+
+const getEditorInstanceWithExtension = (extensionOptions = {}, editorInstanceOptions = {}) => {
+ setFixtures('<div id="editor"></div>');
+ const instance = getEditorInstance(editorInstanceOptions);
+ instance.use(new YamlEditorExtension({ instance, ...extensionOptions }));
+
+ // Remove the below once
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/325992 is resolved
+ if (editorInstanceOptions.value && !extensionOptions.model) {
+ instance.setValue(editorInstanceOptions.value);
+ }
+
+ return instance;
+};
+
+describe('YamlCreatorExtension', () => {
+ describe('constructor', () => {
+ it('saves constructor options', () => {
+ const instance = getEditorInstanceWithExtension({
+ highlightPath: 'foo',
+ enableComments: true,
+ });
+ expect(instance).toEqual(
+ expect.objectContaining({
+ options: expect.objectContaining({
+ highlightPath: 'foo',
+ enableComments: true,
+ }),
+ }),
+ );
+ });
+
+ it('dumps values loaded with the model constructor options', () => {
+ const model = { foo: 'bar' };
+ const expected = 'foo: bar\n';
+ const instance = getEditorInstanceWithExtension({ model });
+ expect(instance.getDoc().get('foo')).toBeDefined();
+ expect(instance.getValue()).toEqual(expected);
+ });
+
+ it('registers the onUpdate() function', () => {
+ const instance = getEditorInstance();
+ const onDidChangeModelContent = jest.spyOn(instance, 'onDidChangeModelContent');
+ instance.use(new YamlEditorExtension({ instance }));
+ expect(onDidChangeModelContent).toHaveBeenCalledWith(expect.any(Function));
+ });
+
+ it("If not provided with a load constructor option, it will parse the editor's value", () => {
+ const editorValue = 'foo: bar';
+ const instance = getEditorInstanceWithExtension({}, { value: editorValue });
+ expect(instance.getDoc().get('foo')).toBeDefined();
+ });
+
+ it("Prefers values loaded with the load constructor option over the editor's existing value", () => {
+ const editorValue = 'oldValue: this should be overriden';
+ const model = { thisShould: 'be the actual value' };
+ const expected = 'thisShould: be the actual value\n';
+ const instance = getEditorInstanceWithExtension({ model }, { value: editorValue });
+ expect(instance.getDoc().get('oldValue')).toBeUndefined();
+ expect(instance.getValue()).toEqual(expected);
+ });
+ });
+
+ describe('initFromModel', () => {
+ const model = { foo: 'bar', 1: 2, abc: ['def'] };
+ const doc = new Document(model);
+
+ it('should call transformComments if enableComments is true', () => {
+ const instance = getEditorInstanceWithExtension({ enableComments: true });
+ const transformComments = jest.spyOn(YamlEditorExtension, 'transformComments');
+ YamlEditorExtension.initFromModel(instance, model);
+ expect(transformComments).toHaveBeenCalled();
+ });
+
+ it('should not call transformComments if enableComments is false', () => {
+ const instance = getEditorInstanceWithExtension({ enableComments: false });
+ const transformComments = jest.spyOn(YamlEditorExtension, 'transformComments');
+ YamlEditorExtension.initFromModel(instance, model);
+ expect(transformComments).not.toHaveBeenCalled();
+ });
+
+ it('should call setValue with the stringified model', () => {
+ const instance = getEditorInstanceWithExtension();
+ const setValue = jest.spyOn(instance, 'setValue');
+ YamlEditorExtension.initFromModel(instance, model);
+ expect(setValue).toHaveBeenCalledWith(doc.toString());
+ });
+ });
+
+ describe('wrapCommentString', () => {
+ const longString =
+ 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.';
+
+ it('should add spaces before each line', () => {
+ const result = YamlEditorExtension.wrapCommentString(longString);
+ const lines = result.split('\n');
+ expect(lines.every((ln) => ln.startsWith(' '))).toBe(true);
+ });
+
+ it('should break long comments into lines of max. 79 chars', () => {
+ // 79 = 80 char width minus 1 char for the '#' at the start of each line
+ const result = YamlEditorExtension.wrapCommentString(longString);
+ const lines = result.split('\n');
+ expect(lines.every((ln) => ln.length <= 79)).toBe(true);
+ });
+
+ it('should decrease the line width if passed a level by 2 chars per level', () => {
+ for (let i = 0; i <= 5; i += 1) {
+ const result = YamlEditorExtension.wrapCommentString(longString, i);
+ const lines = result.split('\n');
+ const decreaseLineWidthBy = i * 2;
+ const maxLineWith = 79 - decreaseLineWidthBy;
+ const isValidLine = (ln) => {
+ if (ln.length <= maxLineWith) return true;
+ // The line may exceed the max line width in case the word is the
+ // only one in the line and thus cannot be broken further
+ return ln.split(' ').length <= 1;
+ };
+ expect(lines.every(isValidLine)).toBe(true);
+ }
+ });
+
+ it('return null if passed an invalid string value', () => {
+ expect(YamlEditorExtension.wrapCommentString(null)).toBe(null);
+ expect(YamlEditorExtension.wrapCommentString()).toBe(null);
+ });
+
+ it('throw an error if passed an invalid level value', () => {
+ expect(() => YamlEditorExtension.wrapCommentString('abc', -5)).toThrow(
+ 'Invalid value "-5" for variable `level`',
+ );
+ expect(() => YamlEditorExtension.wrapCommentString('abc', 'invalid')).toThrow(
+ 'Invalid value "invalid" for variable `level`',
+ );
+ });
+ });
+
+ describe('transformComments', () => {
+ const getInstanceWithModel = (model) => {
+ return getEditorInstanceWithExtension({
+ model,
+ enableComments: true,
+ });
+ };
+
+ it('converts comments inside an array', () => {
+ const model = ['# test comment', 'def', '# foo', 999];
+ const expected = `# test comment\n- def\n# foo\n- 999\n`;
+ const instance = getInstanceWithModel(model);
+ expect(instance.getValue()).toEqual(expected);
+ });
+
+ it('converts generic comments inside an object and places them at the top', () => {
+ const model = { foo: 'bar', 1: 2, '#': 'test comment' };
+ const expected = `# test comment\n"1": 2\nfoo: bar\n`;
+ const instance = getInstanceWithModel(model);
+ expect(instance.getValue()).toEqual(expected);
+ });
+
+ it('adds specific comments before the mentioned entry of an object', () => {
+ const model = { foo: 'bar', 1: 2, '#|foo': 'foo comment' };
+ const expected = `"1": 2\n# foo comment\nfoo: bar\n`;
+ const instance = getInstanceWithModel(model);
+ expect(instance.getValue()).toEqual(expected);
+ });
+
+ it('limits long comments to 80 char width, including indentation', () => {
+ const model = {
+ '#|foo':
+ 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.',
+ foo: {
+ nested1: {
+ nested2: {
+ nested3: {
+ '#|bar':
+ 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.',
+ bar: 'baz',
+ },
+ },
+ },
+ },
+ };
+ const expected = `# Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
+# eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
+# voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
+foo:
+ nested1:
+ nested2:
+ nested3:
+ # Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
+ # nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
+ # sed diam voluptua. At vero eos et accusam et justo duo dolores et ea
+ # rebum.
+ bar: baz
+`;
+ const instance = getInstanceWithModel(model);
+ expect(instance.getValue()).toEqual(expected);
+ });
+ });
+
+ describe('getDoc', () => {
+ it('returns a yaml `Document` Type', () => {
+ const instance = getEditorInstanceWithExtension();
+ expect(instance.getDoc()).toBeInstanceOf(Document);
+ });
+ });
+
+ describe('setDoc', () => {
+ const model = { foo: 'bar', 1: 2, abc: ['def'] };
+ const doc = new Document(model);
+
+ it('should call transformComments if enableComments is true', () => {
+ const spy = jest.spyOn(YamlEditorExtension, 'transformComments');
+ const instance = getEditorInstanceWithExtension({ enableComments: true });
+ instance.setDoc(doc);
+ expect(spy).toHaveBeenCalledWith(doc);
+ });
+
+ it('should not call transformComments if enableComments is false', () => {
+ const spy = jest.spyOn(YamlEditorExtension, 'transformComments');
+ const instance = getEditorInstanceWithExtension({ enableComments: false });
+ instance.setDoc(doc);
+ expect(spy).not.toHaveBeenCalled();
+ });
+
+ it("should call setValue with the stringified doc if the editor's value is empty", () => {
+ const instance = getEditorInstanceWithExtension();
+ const setValue = jest.spyOn(instance, 'setValue');
+ const updateValue = jest.spyOn(instance, 'updateValue');
+ instance.setDoc(doc);
+ expect(setValue).toHaveBeenCalledWith(doc.toString());
+ expect(updateValue).not.toHaveBeenCalled();
+ });
+
+ it("should call updateValue with the stringified doc if the editor's value is not empty", () => {
+ const instance = getEditorInstanceWithExtension({}, { value: 'asjkdhkasjdh' });
+ const setValue = jest.spyOn(instance, 'setValue');
+ const updateValue = jest.spyOn(instance, 'updateValue');
+ instance.setDoc(doc);
+ expect(setValue).not.toHaveBeenCalled();
+ expect(updateValue).toHaveBeenCalledWith(doc.toString());
+ });
+
+ it('should trigger the onUpdate method', () => {
+ const instance = getEditorInstanceWithExtension();
+ const onUpdate = jest.spyOn(instance, 'onUpdate');
+ instance.setDoc(doc);
+ expect(onUpdate).toHaveBeenCalled();
+ });
+ });
+
+ describe('getDataModel', () => {
+ it('returns the model as JS', () => {
+ const value = 'abc: def\nfoo:\n - bar\n - baz\n';
+ const expected = { abc: 'def', foo: ['bar', 'baz'] };
+ const instance = getEditorInstanceWithExtension({}, { value });
+ expect(instance.getDataModel()).toEqual(expected);
+ });
+ });
+
+ describe('setDataModel', () => {
+ it('sets the value to a YAML-representation of the Doc', () => {
+ const model = {
+ abc: ['def'],
+ '#|foo': 'foo comment',
+ foo: {
+ '#|abc': 'abc comment',
+ abc: [{ def: 'ghl', lorem: 'ipsum' }, '# array comment', null],
+ bar: 'baz',
+ },
+ };
+ const expected =
+ 'abc:\n' +
+ ' - def\n' +
+ '# foo comment\n' +
+ 'foo:\n' +
+ ' # abc comment\n' +
+ ' abc:\n' +
+ ' - def: ghl\n' +
+ ' lorem: ipsum\n' +
+ ' # array comment\n' +
+ ' - null\n' +
+ ' bar: baz\n';
+
+ const instance = getEditorInstanceWithExtension({ enableComments: true });
+ const setValue = jest.spyOn(instance, 'setValue');
+
+ instance.setDataModel(model);
+
+ expect(setValue).toHaveBeenCalledWith(expected);
+ });
+
+ it('causes the editor value to be updated', () => {
+ const initialModel = { foo: 'this should be overriden' };
+ const initialValue = 'foo: this should be overriden\n';
+ const newValue = { thisShould: 'be the actual value' };
+ const expected = 'thisShould: be the actual value\n';
+ const instance = getEditorInstanceWithExtension({ model: initialModel });
+ expect(instance.getValue()).toEqual(initialValue);
+ instance.setDataModel(newValue);
+ expect(instance.getValue()).toEqual(expected);
+ });
+ });
+
+ describe('onUpdate', () => {
+ it('calls highlight', () => {
+ const highlightPath = 'foo';
+ const instance = getEditorInstanceWithExtension({ highlightPath });
+ instance.highlight = jest.fn();
+ instance.onUpdate();
+ expect(instance.highlight).toHaveBeenCalledWith(highlightPath);
+ });
+ });
+
+ describe('updateValue', () => {
+ it("causes the editor's value to be updated", () => {
+ const oldValue = 'foobar';
+ const newValue = 'bazboo';
+ const instance = getEditorInstanceWithExtension({}, { value: oldValue });
+ instance.updateValue(newValue);
+ expect(instance.getValue()).toEqual(newValue);
+ });
+ });
+
+ describe('highlight', () => {
+ const highlightPathOnSetup = 'abc';
+ const value = `foo:
+ bar:
+ - baz
+ - boo
+ abc: def
+`;
+ let instance;
+ let highlightLinesSpy;
+ let removeHighlightsSpy;
+
+ beforeEach(() => {
+ instance = getEditorInstanceWithExtension({ highlightPath: highlightPathOnSetup }, { value });
+ highlightLinesSpy = jest.spyOn(SourceEditorExtension, 'highlightLines');
+ removeHighlightsSpy = jest.spyOn(SourceEditorExtension, 'removeHighlights');
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('saves the highlighted path in highlightPath', () => {
+ const path = 'foo.bar';
+ instance.highlight(path);
+ expect(instance.options.highlightPath).toEqual(path);
+ });
+
+ it('calls highlightLines with a number of lines', () => {
+ const path = 'foo.bar';
+ instance.highlight(path);
+ expect(highlightLinesSpy).toHaveBeenCalledWith(instance, [2, 4]);
+ });
+
+ it('calls removeHighlights if path is null', () => {
+ instance.highlight(null);
+ expect(removeHighlightsSpy).toHaveBeenCalledWith(instance);
+ expect(highlightLinesSpy).not.toHaveBeenCalled();
+ expect(instance.options.highlightPath).toBeNull();
+ });
+
+ it('throws an error if path is invalid and does not change the highlighted path', () => {
+ expect(() => instance.highlight('invalidPath[0]')).toThrow(
+ 'The node invalidPath[0] could not be found inside the document.',
+ );
+ expect(instance.options.highlightPath).toEqual(highlightPathOnSetup);
+ expect(highlightLinesSpy).not.toHaveBeenCalled();
+ expect(removeHighlightsSpy).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('locate', () => {
+ const options = {
+ enableComments: true,
+ model: {
+ abc: ['def'],
+ '#|foo': 'foo comment',
+ foo: {
+ '#|abc': 'abc comment',
+ abc: [{ def: 'ghl', lorem: 'ipsum' }, '# array comment', null],
+ bar: 'baz',
+ },
+ },
+ };
+
+ const value =
+ /* 1 */ 'abc:\n' +
+ /* 2 */ ' - def\n' +
+ /* 3 */ '# foo comment\n' +
+ /* 4 */ 'foo:\n' +
+ /* 5 */ ' # abc comment\n' +
+ /* 6 */ ' abc:\n' +
+ /* 7 */ ' - def: ghl\n' +
+ /* 8 */ ' lorem: ipsum\n' +
+ /* 9 */ ' # array comment\n' +
+ /* 10 */ ' - null\n' +
+ /* 11 */ ' bar: baz\n';
+
+ it('asserts that the test setup is correct', () => {
+ const instance = getEditorInstanceWithExtension(options);
+ expect(instance.getValue()).toEqual(value);
+ });
+
+ it('returns the expected line numbers for a path to an object inside the yaml', () => {
+ const path = 'foo.abc';
+ const expected = [6, 10];
+ const instance = getEditorInstanceWithExtension(options);
+ expect(instance.locate(path)).toEqual(expected);
+ });
+
+ it('throws an error if a path cannot be found inside the yaml', () => {
+ const path = 'baz[8]';
+ const instance = getEditorInstanceWithExtension(options);
+ expect(() => instance.locate(path)).toThrow();
+ });
+
+ it('returns the expected line numbers for a path to an array entry inside the yaml', () => {
+ const path = 'foo.abc[0]';
+ const expected = [7, 8];
+ const instance = getEditorInstanceWithExtension(options);
+ expect(instance.locate(path)).toEqual(expected);
+ });
+
+ it('returns the expected line numbers for a path that includes a comment inside the yaml', () => {
+ const path = 'foo';
+ const expected = [4, 11];
+ const instance = getEditorInstanceWithExtension(options);
+ expect(instance.locate(path)).toEqual(expected);
+ });
+ });
+});
diff --git a/spec/frontend/environments/graphql/mock_data.js b/spec/frontend/environments/graphql/mock_data.js
new file mode 100644
index 00000000000..e56b6448b7d
--- /dev/null
+++ b/spec/frontend/environments/graphql/mock_data.js
@@ -0,0 +1,530 @@
+export const environmentsApp = {
+ environments: [
+ {
+ name: 'review',
+ size: 2,
+ latest: {
+ id: 42,
+ global_id: 'gid://gitlab/Environment/42',
+ name: 'review/goodbye',
+ state: 'available',
+ external_url: 'https://example.org',
+ environment_type: 'review',
+ name_without_type: 'goodbye',
+ last_deployment: null,
+ has_stop_action: false,
+ rollout_status: null,
+ environment_path: '/h5bp/html5-boilerplate/-/environments/42',
+ stop_path: '/h5bp/html5-boilerplate/-/environments/42/stop',
+ cancel_auto_stop_path: '/h5bp/html5-boilerplate/-/environments/42/cancel_auto_stop',
+ delete_path: '/api/v4/projects/8/environments/42',
+ folder_path: '/h5bp/html5-boilerplate/-/environments/folders/review',
+ created_at: '2021-10-04T19:27:20.639Z',
+ updated_at: '2021-10-04T19:27:20.639Z',
+ can_stop: true,
+ logs_path: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fgoodbye',
+ logs_api_path: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fgoodbye',
+ enable_advanced_logs_querying: false,
+ can_delete: false,
+ has_opened_alert: false,
+ },
+ },
+ {
+ name: 'production',
+ size: 1,
+ latest: {
+ id: 8,
+ global_id: 'gid://gitlab/Environment/8',
+ name: 'production',
+ state: 'available',
+ external_url: 'https://example.org',
+ environment_type: null,
+ name_without_type: 'production',
+ last_deployment: {
+ id: 80,
+ iid: 24,
+ sha: '4ca0310329e8f251b892d7be205eec8b7dd220e5',
+ ref: {
+ name: 'root-master-patch-18104',
+ ref_path: '/h5bp/html5-boilerplate/-/tree/root-master-patch-18104',
+ },
+ status: 'success',
+ created_at: '2021-10-08T19:53:54.543Z',
+ deployed_at: '2021-10-08T20:02:36.763Z',
+ tag: false,
+ 'last?': true,
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ web_url: 'http://gdk.test:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ deployable: {
+ id: 911,
+ name: 'deploy-job',
+ started: '2021-10-08T19:54:00.658Z',
+ complete: true,
+ archived: false,
+ build_path: '/h5bp/html5-boilerplate/-/jobs/911',
+ retry_path: '/h5bp/html5-boilerplate/-/jobs/911/retry',
+ play_path: '/h5bp/html5-boilerplate/-/jobs/911/play',
+ playable: true,
+ scheduled: false,
+ created_at: '2021-10-08T19:53:54.482Z',
+ updated_at: '2021-10-08T20:02:36.730Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'manual play action',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/h5bp/html5-boilerplate/-/jobs/911',
+ illustration: {
+ image:
+ '/assets/illustrations/manual_action-c55aee2c5f9ebe9f72751480af8bb307be1a6f35552f344cc6d1bf979d3422f6.svg',
+ size: 'svg-394',
+ title: 'This job requires a manual action',
+ content:
+ 'This job requires manual intervention to start. Before starting this job, you can add variables below for last-minute configuration changes.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'play',
+ title: 'Play',
+ path: '/h5bp/html5-boilerplate/-/jobs/911/play',
+ method: 'post',
+ button_title: 'Trigger this manual action',
+ },
+ },
+ },
+ commit: {
+ id: '4ca0310329e8f251b892d7be205eec8b7dd220e5',
+ short_id: '4ca03103',
+ created_at: '2021-10-08T19:27:01.000+00:00',
+ parent_ids: ['b385360b15bd61391a0efbd101788d4a80387270'],
+ title: 'Update .gitlab-ci.yml',
+ message: 'Update .gitlab-ci.yml',
+ author_name: 'Administrator',
+ author_email: 'admin@example.com',
+ authored_date: '2021-10-08T19:27:01.000+00:00',
+ committer_name: 'Administrator',
+ committer_email: 'admin@example.com',
+ committed_date: '2021-10-08T19:27:01.000+00:00',
+ trailers: {},
+ web_url:
+ 'http://gdk.test:3000/h5bp/html5-boilerplate/-/commit/4ca0310329e8f251b892d7be205eec8b7dd220e5',
+ author: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ web_url: 'http://gdk.test:3000/root',
+ show_status: false,
+ path: '/root',
+ },
+ author_gravatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ commit_url:
+ 'http://gdk.test:3000/h5bp/html5-boilerplate/-/commit/4ca0310329e8f251b892d7be205eec8b7dd220e5',
+ commit_path:
+ '/h5bp/html5-boilerplate/-/commit/4ca0310329e8f251b892d7be205eec8b7dd220e5',
+ },
+ manual_actions: [],
+ scheduled_actions: [],
+ playable_build: {
+ retry_path: '/h5bp/html5-boilerplate/-/jobs/911/retry',
+ play_path: '/h5bp/html5-boilerplate/-/jobs/911/play',
+ },
+ cluster: null,
+ },
+ has_stop_action: false,
+ rollout_status: null,
+ environment_path: '/h5bp/html5-boilerplate/-/environments/8',
+ stop_path: '/h5bp/html5-boilerplate/-/environments/8/stop',
+ cancel_auto_stop_path: '/h5bp/html5-boilerplate/-/environments/8/cancel_auto_stop',
+ delete_path: '/api/v4/projects/8/environments/8',
+ folder_path: '/h5bp/html5-boilerplate/-/environments/folders/production',
+ created_at: '2021-06-17T15:09:38.599Z',
+ updated_at: '2021-10-08T19:50:44.445Z',
+ can_stop: true,
+ logs_path: '/h5bp/html5-boilerplate/-/logs?environment_name=production',
+ logs_api_path: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=production',
+ enable_advanced_logs_querying: false,
+ can_delete: false,
+ has_opened_alert: false,
+ },
+ },
+ {
+ name: 'staging',
+ size: 1,
+ latest: {
+ id: 7,
+ global_id: 'gid://gitlab/Environment/7',
+ name: 'staging',
+ state: 'available',
+ external_url: null,
+ environment_type: null,
+ name_without_type: 'staging',
+ last_deployment: null,
+ has_stop_action: false,
+ rollout_status: null,
+ environment_path: '/h5bp/html5-boilerplate/-/environments/7',
+ stop_path: '/h5bp/html5-boilerplate/-/environments/7/stop',
+ cancel_auto_stop_path: '/h5bp/html5-boilerplate/-/environments/7/cancel_auto_stop',
+ delete_path: '/api/v4/projects/8/environments/7',
+ folder_path: '/h5bp/html5-boilerplate/-/environments/folders/staging',
+ created_at: '2021-06-17T15:09:38.570Z',
+ updated_at: '2021-06-17T15:09:38.570Z',
+ can_stop: true,
+ logs_path: '/h5bp/html5-boilerplate/-/logs?environment_name=staging',
+ logs_api_path: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=staging',
+ enable_advanced_logs_querying: false,
+ can_delete: false,
+ has_opened_alert: false,
+ },
+ },
+ ],
+ review_app: {
+ can_setup_review_app: true,
+ all_clusters_empty: true,
+ review_snippet:
+ '{"deploy_review"=>{"stage"=>"deploy", "script"=>["echo \\"Deploy a review app\\""], "environment"=>{"name"=>"review/$CI_COMMIT_REF_NAME", "url"=>"https://$CI_ENVIRONMENT_SLUG.example.com"}, "only"=>["branches"]}}',
+ },
+ available_count: 4,
+ stopped_count: 0,
+};
+
+export const resolvedEnvironmentsApp = {
+ availableCount: 4,
+ environments: [
+ {
+ name: 'review',
+ size: 2,
+ latest: {
+ id: 42,
+ globalId: 'gid://gitlab/Environment/42',
+ name: 'review/goodbye',
+ state: 'available',
+ externalUrl: 'https://example.org',
+ environmentType: 'review',
+ nameWithoutType: 'goodbye',
+ lastDeployment: null,
+ hasStopAction: false,
+ rolloutStatus: null,
+ environmentPath: '/h5bp/html5-boilerplate/-/environments/42',
+ stopPath: '/h5bp/html5-boilerplate/-/environments/42/stop',
+ cancelAutoStopPath: '/h5bp/html5-boilerplate/-/environments/42/cancel_auto_stop',
+ deletePath: '/api/v4/projects/8/environments/42',
+ folderPath: '/h5bp/html5-boilerplate/-/environments/folders/review',
+ createdAt: '2021-10-04T19:27:20.639Z',
+ updatedAt: '2021-10-04T19:27:20.639Z',
+ canStop: true,
+ logsPath: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fgoodbye',
+ logsApiPath: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fgoodbye',
+ enableAdvancedLogsQuerying: false,
+ canDelete: false,
+ hasOpenedAlert: false,
+ },
+ __typename: 'NestedLocalEnvironment',
+ },
+ {
+ name: 'production',
+ size: 1,
+ latest: {
+ id: 8,
+ globalId: 'gid://gitlab/Environment/8',
+ name: 'production',
+ state: 'available',
+ externalUrl: 'https://example.org',
+ environmentType: null,
+ nameWithoutType: 'production',
+ lastDeployment: {
+ id: 80,
+ iid: 24,
+ sha: '4ca0310329e8f251b892d7be205eec8b7dd220e5',
+ ref: {
+ name: 'root-master-patch-18104',
+ refPath: '/h5bp/html5-boilerplate/-/tree/root-master-patch-18104',
+ },
+ status: 'success',
+ createdAt: '2021-10-08T19:53:54.543Z',
+ deployedAt: '2021-10-08T20:02:36.763Z',
+ tag: false,
+ 'last?': true,
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ webUrl: 'http://gdk.test:3000/root',
+ showStatus: false,
+ path: '/root',
+ },
+ deployable: {
+ id: 911,
+ name: 'deploy-job',
+ started: '2021-10-08T19:54:00.658Z',
+ complete: true,
+ archived: false,
+ buildPath: '/h5bp/html5-boilerplate/-/jobs/911',
+ retryPath: '/h5bp/html5-boilerplate/-/jobs/911/retry',
+ playPath: '/h5bp/html5-boilerplate/-/jobs/911/play',
+ playable: true,
+ scheduled: false,
+ createdAt: '2021-10-08T19:53:54.482Z',
+ updatedAt: '2021-10-08T20:02:36.730Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'manual play action',
+ group: 'success',
+ tooltip: 'passed',
+ hasDetails: true,
+ detailsPath: '/h5bp/html5-boilerplate/-/jobs/911',
+ illustration: {
+ image:
+ '/assets/illustrations/manual_action-c55aee2c5f9ebe9f72751480af8bb307be1a6f35552f344cc6d1bf979d3422f6.svg',
+ size: 'svg-394',
+ title: 'This job requires a manual action',
+ content:
+ 'This job requires manual intervention to start. Before starting this job, you can add variables below for last-minute configuration changes.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'play',
+ title: 'Play',
+ path: '/h5bp/html5-boilerplate/-/jobs/911/play',
+ method: 'post',
+ buttonTitle: 'Trigger this manual action',
+ },
+ },
+ },
+ commit: {
+ id: '4ca0310329e8f251b892d7be205eec8b7dd220e5',
+ shortId: '4ca03103',
+ createdAt: '2021-10-08T19:27:01.000+00:00',
+ parentIds: ['b385360b15bd61391a0efbd101788d4a80387270'],
+ title: 'Update .gitlab-ci.yml',
+ message: 'Update .gitlab-ci.yml',
+ authorName: 'Administrator',
+ authorEmail: 'admin@example.com',
+ authoredDate: '2021-10-08T19:27:01.000+00:00',
+ committerName: 'Administrator',
+ committerEmail: 'admin@example.com',
+ committedDate: '2021-10-08T19:27:01.000+00:00',
+ trailers: {},
+ webUrl:
+ 'http://gdk.test:3000/h5bp/html5-boilerplate/-/commit/4ca0310329e8f251b892d7be205eec8b7dd220e5',
+ author: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ webUrl: 'http://gdk.test:3000/root',
+ showStatus: false,
+ path: '/root',
+ },
+ authorGravatarUrl:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ commitUrl:
+ 'http://gdk.test:3000/h5bp/html5-boilerplate/-/commit/4ca0310329e8f251b892d7be205eec8b7dd220e5',
+ commitPath: '/h5bp/html5-boilerplate/-/commit/4ca0310329e8f251b892d7be205eec8b7dd220e5',
+ },
+ manualActions: [],
+ scheduledActions: [],
+ playableBuild: {
+ retryPath: '/h5bp/html5-boilerplate/-/jobs/911/retry',
+ playPath: '/h5bp/html5-boilerplate/-/jobs/911/play',
+ },
+ cluster: null,
+ },
+ hasStopAction: false,
+ rolloutStatus: null,
+ environmentPath: '/h5bp/html5-boilerplate/-/environments/8',
+ stopPath: '/h5bp/html5-boilerplate/-/environments/8/stop',
+ cancelAutoStopPath: '/h5bp/html5-boilerplate/-/environments/8/cancel_auto_stop',
+ deletePath: '/api/v4/projects/8/environments/8',
+ folderPath: '/h5bp/html5-boilerplate/-/environments/folders/production',
+ createdAt: '2021-06-17T15:09:38.599Z',
+ updatedAt: '2021-10-08T19:50:44.445Z',
+ canStop: true,
+ logsPath: '/h5bp/html5-boilerplate/-/logs?environment_name=production',
+ logsApiPath: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=production',
+ enableAdvancedLogsQuerying: false,
+ canDelete: false,
+ hasOpenedAlert: false,
+ },
+ __typename: 'NestedLocalEnvironment',
+ },
+ {
+ name: 'staging',
+ size: 1,
+ latest: {
+ id: 7,
+ globalId: 'gid://gitlab/Environment/7',
+ name: 'staging',
+ state: 'available',
+ externalUrl: null,
+ environmentType: null,
+ nameWithoutType: 'staging',
+ lastDeployment: null,
+ hasStopAction: false,
+ rolloutStatus: null,
+ environmentPath: '/h5bp/html5-boilerplate/-/environments/7',
+ stopPath: '/h5bp/html5-boilerplate/-/environments/7/stop',
+ cancelAutoStopPath: '/h5bp/html5-boilerplate/-/environments/7/cancel_auto_stop',
+ deletePath: '/api/v4/projects/8/environments/7',
+ folderPath: '/h5bp/html5-boilerplate/-/environments/folders/staging',
+ createdAt: '2021-06-17T15:09:38.570Z',
+ updatedAt: '2021-06-17T15:09:38.570Z',
+ canStop: true,
+ logsPath: '/h5bp/html5-boilerplate/-/logs?environment_name=staging',
+ logsApiPath: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=staging',
+ enableAdvancedLogsQuerying: false,
+ canDelete: false,
+ hasOpenedAlert: false,
+ },
+ __typename: 'NestedLocalEnvironment',
+ },
+ ],
+ reviewApp: {
+ canSetupReviewApp: true,
+ allClustersEmpty: true,
+ reviewSnippet:
+ '{"deploy_review"=>{"stage"=>"deploy", "script"=>["echo \\"Deploy a review app\\""], "environment"=>{"name"=>"review/$CI_COMMIT_REF_NAME", "url"=>"https://$CI_ENVIRONMENT_SLUG.example.com"}, "only"=>["branches"]}}',
+ __typename: 'ReviewApp',
+ },
+ stoppedCount: 0,
+ __typename: 'LocalEnvironmentApp',
+};
+
+export const folder = {
+ environments: [
+ {
+ id: 42,
+ global_id: 'gid://gitlab/Environment/42',
+ name: 'review/goodbye',
+ state: 'available',
+ external_url: 'https://example.org',
+ environment_type: 'review',
+ name_without_type: 'goodbye',
+ last_deployment: null,
+ has_stop_action: false,
+ rollout_status: null,
+ environment_path: '/h5bp/html5-boilerplate/-/environments/42',
+ stop_path: '/h5bp/html5-boilerplate/-/environments/42/stop',
+ cancel_auto_stop_path: '/h5bp/html5-boilerplate/-/environments/42/cancel_auto_stop',
+ delete_path: '/api/v4/projects/8/environments/42',
+ folder_path: '/h5bp/html5-boilerplate/-/environments/folders/review',
+ created_at: '2021-10-04T19:27:20.639Z',
+ updated_at: '2021-10-04T19:27:20.639Z',
+ can_stop: true,
+ logs_path: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fgoodbye',
+ logs_api_path: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fgoodbye',
+ enable_advanced_logs_querying: false,
+ can_delete: false,
+ has_opened_alert: false,
+ },
+ {
+ id: 41,
+ global_id: 'gid://gitlab/Environment/41',
+ name: 'review/hello',
+ state: 'available',
+ external_url: 'https://example.org',
+ environment_type: 'review',
+ name_without_type: 'hello',
+ last_deployment: null,
+ has_stop_action: false,
+ rollout_status: null,
+ environment_path: '/h5bp/html5-boilerplate/-/environments/41',
+ stop_path: '/h5bp/html5-boilerplate/-/environments/41/stop',
+ cancel_auto_stop_path: '/h5bp/html5-boilerplate/-/environments/41/cancel_auto_stop',
+ delete_path: '/api/v4/projects/8/environments/41',
+ folder_path: '/h5bp/html5-boilerplate/-/environments/folders/review',
+ created_at: '2021-10-04T19:27:00.527Z',
+ updated_at: '2021-10-04T19:27:00.527Z',
+ can_stop: true,
+ logs_path: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fhello',
+ logs_api_path: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fhello',
+ enable_advanced_logs_querying: false,
+ can_delete: false,
+ has_opened_alert: false,
+ },
+ ],
+ available_count: 2,
+ stopped_count: 0,
+};
+
+export const resolvedFolder = {
+ availableCount: 2,
+ environments: [
+ {
+ id: 42,
+ globalId: 'gid://gitlab/Environment/42',
+ name: 'review/goodbye',
+ state: 'available',
+ externalUrl: 'https://example.org',
+ environmentType: 'review',
+ nameWithoutType: 'goodbye',
+ lastDeployment: null,
+ hasStopAction: false,
+ rolloutStatus: null,
+ environmentPath: '/h5bp/html5-boilerplate/-/environments/42',
+ stopPath: '/h5bp/html5-boilerplate/-/environments/42/stop',
+ cancelAutoStopPath: '/h5bp/html5-boilerplate/-/environments/42/cancel_auto_stop',
+ deletePath: '/api/v4/projects/8/environments/42',
+ folderPath: '/h5bp/html5-boilerplate/-/environments/folders/review',
+ createdAt: '2021-10-04T19:27:20.639Z',
+ updatedAt: '2021-10-04T19:27:20.639Z',
+ canStop: true,
+ logsPath: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fgoodbye',
+ logsApiPath: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fgoodbye',
+ enableAdvancedLogsQuerying: false,
+ canDelete: false,
+ hasOpenedAlert: false,
+ __typename: 'LocalEnvironment',
+ },
+ {
+ id: 41,
+ globalId: 'gid://gitlab/Environment/41',
+ name: 'review/hello',
+ state: 'available',
+ externalUrl: 'https://example.org',
+ environmentType: 'review',
+ nameWithoutType: 'hello',
+ lastDeployment: null,
+ hasStopAction: false,
+ rolloutStatus: null,
+ environmentPath: '/h5bp/html5-boilerplate/-/environments/41',
+ stopPath: '/h5bp/html5-boilerplate/-/environments/41/stop',
+ cancelAutoStopPath: '/h5bp/html5-boilerplate/-/environments/41/cancel_auto_stop',
+ deletePath: '/api/v4/projects/8/environments/41',
+ folderPath: '/h5bp/html5-boilerplate/-/environments/folders/review',
+ createdAt: '2021-10-04T19:27:00.527Z',
+ updatedAt: '2021-10-04T19:27:00.527Z',
+ canStop: true,
+ logsPath: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fhello',
+ logsApiPath: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fhello',
+ enableAdvancedLogsQuerying: false,
+ canDelete: false,
+ hasOpenedAlert: false,
+ __typename: 'LocalEnvironment',
+ },
+ ],
+ stoppedCount: 0,
+ __typename: 'LocalEnvironmentFolder',
+};
diff --git a/spec/frontend/environments/graphql/resolvers_spec.js b/spec/frontend/environments/graphql/resolvers_spec.js
new file mode 100644
index 00000000000..4d2a0818996
--- /dev/null
+++ b/spec/frontend/environments/graphql/resolvers_spec.js
@@ -0,0 +1,91 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import { resolvers } from '~/environments/graphql/resolvers';
+import { TEST_HOST } from 'helpers/test_constants';
+import { environmentsApp, resolvedEnvironmentsApp, folder, resolvedFolder } from './mock_data';
+
+const ENDPOINT = `${TEST_HOST}/environments`;
+
+describe('~/frontend/environments/graphql/resolvers', () => {
+ let mockResolvers;
+ let mock;
+
+ beforeEach(() => {
+ mockResolvers = resolvers(ENDPOINT);
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.reset();
+ });
+
+ describe('environmentApp', () => {
+ it('should fetch environments and map them to frontend data', async () => {
+ mock.onGet(ENDPOINT, { params: { nested: true } }).reply(200, environmentsApp);
+
+ const app = await mockResolvers.Query.environmentApp();
+ expect(app).toEqual(resolvedEnvironmentsApp);
+ });
+ });
+ describe('folder', () => {
+ it('should fetch the folder url passed to it', async () => {
+ mock.onGet(ENDPOINT, { params: { per_page: 3 } }).reply(200, folder);
+
+ const environmentFolder = await mockResolvers.Query.folder(null, {
+ environment: { folderPath: ENDPOINT },
+ });
+
+ expect(environmentFolder).toEqual(resolvedFolder);
+ });
+ });
+ describe('stopEnvironment', () => {
+ it('should post to the stop environment path', async () => {
+ mock.onPost(ENDPOINT).reply(200);
+
+ await mockResolvers.Mutations.stopEnvironment(null, { environment: { stopPath: ENDPOINT } });
+
+ expect(mock.history.post).toContainEqual(
+ expect.objectContaining({ url: ENDPOINT, method: 'post' }),
+ );
+ });
+ });
+ describe('rollbackEnvironment', () => {
+ it('should post to the retry environment path', async () => {
+ mock.onPost(ENDPOINT).reply(200);
+
+ await mockResolvers.Mutations.rollbackEnvironment(null, {
+ environment: { retryUrl: ENDPOINT },
+ });
+
+ expect(mock.history.post).toContainEqual(
+ expect.objectContaining({ url: ENDPOINT, method: 'post' }),
+ );
+ });
+ });
+ describe('deleteEnvironment', () => {
+ it('should DELETE to the delete environment path', async () => {
+ mock.onDelete(ENDPOINT).reply(200);
+
+ await mockResolvers.Mutations.deleteEnvironment(null, {
+ environment: { deletePath: ENDPOINT },
+ });
+
+ expect(mock.history.delete).toContainEqual(
+ expect.objectContaining({ url: ENDPOINT, method: 'delete' }),
+ );
+ });
+ });
+ describe('cancelAutoStop', () => {
+ it('should post to the auto stop path', async () => {
+ mock.onPost(ENDPOINT).reply(200);
+
+ await mockResolvers.Mutations.cancelAutoStop(null, {
+ environment: { autoStopPath: ENDPOINT },
+ });
+
+ expect(mock.history.post).toContainEqual(
+ expect.objectContaining({ url: ENDPOINT, method: 'post' }),
+ );
+ });
+ });
+});
diff --git a/spec/frontend/environments/new_environment_folder_spec.js b/spec/frontend/environments/new_environment_folder_spec.js
new file mode 100644
index 00000000000..5696e187a86
--- /dev/null
+++ b/spec/frontend/environments/new_environment_folder_spec.js
@@ -0,0 +1,74 @@
+import VueApollo from 'vue-apollo';
+import Vue from 'vue';
+import { GlCollapse, GlIcon } from '@gitlab/ui';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import EnvironmentsFolder from '~/environments/components/new_environment_folder.vue';
+import { s__ } from '~/locale';
+import { resolvedEnvironmentsApp, resolvedFolder } from './graphql/mock_data';
+
+Vue.use(VueApollo);
+
+describe('~/environments/components/new_environments_folder.vue', () => {
+ let wrapper;
+ let environmentFolderMock;
+ let nestedEnvironment;
+ let folderName;
+
+ const findLink = () => wrapper.findByRole('link', { name: s__('Environments|Show all') });
+
+ const createApolloProvider = () => {
+ const mockResolvers = { Query: { folder: environmentFolderMock } };
+
+ return createMockApollo([], mockResolvers);
+ };
+
+ const createWrapper = (propsData, apolloProvider) =>
+ mountExtended(EnvironmentsFolder, { apolloProvider, propsData });
+
+ beforeEach(() => {
+ environmentFolderMock = jest.fn();
+ [nestedEnvironment] = resolvedEnvironmentsApp.environments;
+ environmentFolderMock.mockReturnValue(resolvedFolder);
+ wrapper = createWrapper({ nestedEnvironment }, createApolloProvider());
+ folderName = wrapper.findByText(nestedEnvironment.name);
+ });
+
+ afterEach(() => {
+ wrapper?.destroy();
+ });
+
+ it('displays the name of the folder', () => {
+ expect(folderName.text()).toBe(nestedEnvironment.name);
+ });
+
+ describe('collapse', () => {
+ let icons;
+ let collapse;
+
+ beforeEach(() => {
+ collapse = wrapper.findComponent(GlCollapse);
+ icons = wrapper.findAllComponents(GlIcon);
+ });
+
+ it('is collapsed by default', () => {
+ const link = findLink();
+
+ expect(collapse.attributes('visible')).toBeUndefined();
+ expect(icons.wrappers.map((i) => i.props('name'))).toEqual(['angle-right', 'folder-o']);
+ expect(folderName.classes('gl-font-weight-bold')).toBe(false);
+ expect(link.exists()).toBe(false);
+ });
+
+ it('opens on click', async () => {
+ await folderName.trigger('click');
+
+ const link = findLink();
+
+ expect(collapse.attributes('visible')).toBe('true');
+ expect(icons.wrappers.map((i) => i.props('name'))).toEqual(['angle-down', 'folder-open']);
+ expect(folderName.classes('gl-font-weight-bold')).toBe(true);
+ expect(link.attributes('href')).toBe(nestedEnvironment.latest.folderPath);
+ });
+ });
+});
diff --git a/spec/frontend/environments/new_environments_app_spec.js b/spec/frontend/environments/new_environments_app_spec.js
new file mode 100644
index 00000000000..0ad8e8f442c
--- /dev/null
+++ b/spec/frontend/environments/new_environments_app_spec.js
@@ -0,0 +1,50 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { mount } from '@vue/test-utils';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import EnvironmentsApp from '~/environments/components/new_environments_app.vue';
+import EnvironmentsFolder from '~/environments/components/new_environment_folder.vue';
+import { resolvedEnvironmentsApp, resolvedFolder } from './graphql/mock_data';
+
+Vue.use(VueApollo);
+
+describe('~/environments/components/new_environments_app.vue', () => {
+ let wrapper;
+ let environmentAppMock;
+ let environmentFolderMock;
+
+ const createApolloProvider = () => {
+ const mockResolvers = {
+ Query: { environmentApp: environmentAppMock, folder: environmentFolderMock },
+ };
+
+ return createMockApollo([], mockResolvers);
+ };
+
+ const createWrapper = (apolloProvider) => mount(EnvironmentsApp, { apolloProvider });
+
+ beforeEach(() => {
+ environmentAppMock = jest.fn();
+ environmentFolderMock = jest.fn();
+ });
+
+ afterEach(() => {
+ wrapper?.destroy();
+ });
+
+ it('should show all the folders that are fetched', async () => {
+ environmentAppMock.mockReturnValue(resolvedEnvironmentsApp);
+ environmentFolderMock.mockReturnValue(resolvedFolder);
+ const apolloProvider = createApolloProvider();
+ wrapper = createWrapper(apolloProvider);
+
+ await waitForPromises();
+ await Vue.nextTick();
+
+ const text = wrapper.findAllComponents(EnvironmentsFolder).wrappers.map((w) => w.text());
+
+ expect(text).toContainEqual(expect.stringMatching('review'));
+ expect(text).not.toContainEqual(expect.stringMatching('production'));
+ });
+});
diff --git a/spec/frontend/experimentation/utils_spec.js b/spec/frontend/experimentation/utils_spec.js
index de060f5eb8c..923795ca3f3 100644
--- a/spec/frontend/experimentation/utils_spec.js
+++ b/spec/frontend/experimentation/utils_spec.js
@@ -1,4 +1,4 @@
-import { assignGitlabExperiment } from 'helpers/experimentation_helper';
+import { stubExperiments } from 'helpers/experimentation_helper';
import {
DEFAULT_VARIANT,
CANDIDATE_VARIANT,
@@ -7,15 +7,45 @@ import {
import * as experimentUtils from '~/experimentation/utils';
describe('experiment Utilities', () => {
- const TEST_KEY = 'abc';
+ const ABC_KEY = 'abc';
+ const DEF_KEY = 'def';
+
+ let origGon;
+ let origGl;
+
+ beforeEach(() => {
+ origGon = window.gon;
+ origGl = window.gl;
+ window.gon.experiment = {};
+ window.gl.experiments = {};
+ });
+
+ afterEach(() => {
+ window.gon = origGon;
+ window.gl = origGl;
+ });
describe('getExperimentData', () => {
+ const ABC_DATA = '_abc_data_';
+ const ABC_DATA2 = '_updated_abc_data_';
+ const DEF_DATA = '_def_data_';
+
describe.each`
- gon | input | output
- ${[TEST_KEY, '_data_']} | ${[TEST_KEY]} | ${{ variant: '_data_' }}
- ${[]} | ${[TEST_KEY]} | ${undefined}
- `('with input=$input and gon=$gon', ({ gon, input, output }) => {
- assignGitlabExperiment(...gon);
+ gonData | glData | input | output
+ ${[ABC_KEY, ABC_DATA]} | ${[]} | ${[ABC_KEY]} | ${{ experiment: ABC_KEY, variant: ABC_DATA }}
+ ${[]} | ${[ABC_KEY, ABC_DATA]} | ${[ABC_KEY]} | ${{ experiment: ABC_KEY, variant: ABC_DATA }}
+ ${[ABC_KEY, ABC_DATA]} | ${[DEF_KEY, DEF_DATA]} | ${[ABC_KEY]} | ${{ experiment: ABC_KEY, variant: ABC_DATA }}
+ ${[ABC_KEY, ABC_DATA]} | ${[DEF_KEY, DEF_DATA]} | ${[DEF_KEY]} | ${{ experiment: DEF_KEY, variant: DEF_DATA }}
+ ${[ABC_KEY, ABC_DATA]} | ${[ABC_KEY, ABC_DATA2]} | ${[ABC_KEY]} | ${{ experiment: ABC_KEY, variant: ABC_DATA2 }}
+ ${[]} | ${[]} | ${[ABC_KEY]} | ${undefined}
+ `('with input=$input, gon=$gonData, & gl=$glData', ({ gonData, glData, input, output }) => {
+ beforeEach(() => {
+ const [gonKey, gonVariant] = gonData;
+ const [glKey, glVariant] = glData;
+
+ if (gonKey) window.gon.experiment[gonKey] = { experiment: gonKey, variant: gonVariant };
+ if (glKey) window.gl.experiments[glKey] = { experiment: glKey, variant: glVariant };
+ });
it(`returns ${output}`, () => {
expect(experimentUtils.getExperimentData(...input)).toEqual(output);
@@ -25,106 +55,129 @@ describe('experiment Utilities', () => {
describe('getAllExperimentContexts', () => {
const schema = TRACKING_CONTEXT_SCHEMA;
- let origGon;
-
- beforeEach(() => {
- origGon = window.gon;
- });
-
- afterEach(() => {
- window.gon = origGon;
- });
it('collects all of the experiment contexts into a single array', () => {
- const experiments = [
- { experiment: 'abc', variant: 'candidate' },
- { experiment: 'def', variant: 'control' },
- { experiment: 'ghi', variant: 'blue' },
- ];
- window.gon = {
- experiment: experiments.reduce((collector, { experiment, variant }) => {
- return { ...collector, [experiment]: { experiment, variant } };
- }, {}),
- };
+ const experiments = { [ABC_KEY]: 'candidate', [DEF_KEY]: 'control', ghi: 'blue' };
+
+ stubExperiments(experiments);
expect(experimentUtils.getAllExperimentContexts()).toEqual(
- experiments.map((data) => ({ schema, data })),
+ Object.entries(experiments).map(([experiment, variant]) => ({
+ schema,
+ data: { experiment, variant },
+ })),
);
});
it('returns an empty array if there are no experiments', () => {
- window.gon.experiment = {};
-
expect(experimentUtils.getAllExperimentContexts()).toEqual([]);
});
- it('includes all additional experiment data', () => {
- const experiment = 'experimentWithCustomData';
- const data = { experiment, variant: 'control', color: 'blue', style: 'rounded' };
- window.gon.experiment[experiment] = data;
+ it('only collects the data properties which are supported by the schema', () => {
+ origGl = window.gl;
+ window.gl.experiments = {
+ my_experiment: { experiment: 'my_experiment', variant: 'control', excluded: false },
+ };
+
+ expect(experimentUtils.getAllExperimentContexts()).toEqual([
+ { schema, data: { experiment: 'my_experiment', variant: 'control' } },
+ ]);
- expect(experimentUtils.getAllExperimentContexts()).toContainEqual({ schema, data });
+ window.gl = origGl;
});
});
describe('isExperimentVariant', () => {
describe.each`
- gon | input | output
- ${[TEST_KEY, DEFAULT_VARIANT]} | ${[TEST_KEY, DEFAULT_VARIANT]} | ${true}
- ${[TEST_KEY, '_variant_name']} | ${[TEST_KEY, '_variant_name']} | ${true}
- ${[TEST_KEY, '_variant_name']} | ${[TEST_KEY, '_bogus_name']} | ${false}
- ${[TEST_KEY, '_variant_name']} | ${['boguskey', '_variant_name']} | ${false}
- ${[]} | ${[TEST_KEY, '_variant_name']} | ${false}
- `('with input=$input and gon=$gon', ({ gon, input, output }) => {
- assignGitlabExperiment(...gon);
-
- it(`returns ${output}`, () => {
- expect(experimentUtils.isExperimentVariant(...input)).toEqual(output);
- });
- });
+ experiment | variant | input | output
+ ${ABC_KEY} | ${DEFAULT_VARIANT} | ${[ABC_KEY, DEFAULT_VARIANT]} | ${true}
+ ${ABC_KEY} | ${'_variant_name'} | ${[ABC_KEY, '_variant_name']} | ${true}
+ ${ABC_KEY} | ${'_variant_name'} | ${[ABC_KEY, '_bogus_name']} | ${false}
+ ${ABC_KEY} | ${'_variant_name'} | ${['boguskey', '_variant_name']} | ${false}
+ ${undefined} | ${undefined} | ${[ABC_KEY, '_variant_name']} | ${false}
+ `(
+ 'with input=$input, experiment=$experiment, variant=$variant',
+ ({ experiment, variant, input, output }) => {
+ it(`returns ${output}`, () => {
+ if (experiment) stubExperiments({ [experiment]: variant });
+
+ expect(experimentUtils.isExperimentVariant(...input)).toEqual(output);
+ });
+ },
+ );
});
describe('experiment', () => {
+ const experiment = 'marley';
+ const useSpy = jest.fn();
const controlSpy = jest.fn();
+ const trySpy = jest.fn();
const candidateSpy = jest.fn();
const getUpStandUpSpy = jest.fn();
const variants = {
- use: controlSpy,
- try: candidateSpy,
+ use: useSpy,
+ try: trySpy,
get_up_stand_up: getUpStandUpSpy,
};
describe('when there is no experiment data', () => {
- it('calls control variant', () => {
- experimentUtils.experiment('marley', variants);
- expect(controlSpy).toHaveBeenCalled();
+ it('calls the use variant', () => {
+ experimentUtils.experiment(experiment, variants);
+ expect(useSpy).toHaveBeenCalled();
+ });
+
+ describe("when 'control' is provided instead of 'use'", () => {
+ it('calls the control variant', () => {
+ experimentUtils.experiment(experiment, { control: controlSpy });
+ expect(controlSpy).toHaveBeenCalled();
+ });
});
});
describe('when experiment variant is "control"', () => {
- assignGitlabExperiment('marley', DEFAULT_VARIANT);
+ beforeEach(() => {
+ stubExperiments({ [experiment]: DEFAULT_VARIANT });
+ });
- it('calls the control variant', () => {
- experimentUtils.experiment('marley', variants);
- expect(controlSpy).toHaveBeenCalled();
+ it('calls the use variant', () => {
+ experimentUtils.experiment(experiment, variants);
+ expect(useSpy).toHaveBeenCalled();
+ });
+
+ describe("when 'control' is provided instead of 'use'", () => {
+ it('calls the control variant', () => {
+ experimentUtils.experiment(experiment, { control: controlSpy });
+ expect(controlSpy).toHaveBeenCalled();
+ });
});
});
describe('when experiment variant is "candidate"', () => {
- assignGitlabExperiment('marley', CANDIDATE_VARIANT);
+ beforeEach(() => {
+ stubExperiments({ [experiment]: CANDIDATE_VARIANT });
+ });
- it('calls the candidate variant', () => {
- experimentUtils.experiment('marley', variants);
- expect(candidateSpy).toHaveBeenCalled();
+ it('calls the try variant', () => {
+ experimentUtils.experiment(experiment, variants);
+ expect(trySpy).toHaveBeenCalled();
+ });
+
+ describe("when 'candidate' is provided instead of 'try'", () => {
+ it('calls the candidate variant', () => {
+ experimentUtils.experiment(experiment, { candidate: candidateSpy });
+ expect(candidateSpy).toHaveBeenCalled();
+ });
});
});
describe('when experiment variant is "get_up_stand_up"', () => {
- assignGitlabExperiment('marley', 'get_up_stand_up');
+ beforeEach(() => {
+ stubExperiments({ [experiment]: 'get_up_stand_up' });
+ });
it('calls the get-up-stand-up variant', () => {
- experimentUtils.experiment('marley', variants);
+ experimentUtils.experiment(experiment, variants);
expect(getUpStandUpSpy).toHaveBeenCalled();
});
});
@@ -132,14 +185,17 @@ describe('experiment Utilities', () => {
describe('getExperimentVariant', () => {
it.each`
- gon | input | output
- ${{ experiment: { [TEST_KEY]: { variant: DEFAULT_VARIANT } } }} | ${[TEST_KEY]} | ${DEFAULT_VARIANT}
- ${{ experiment: { [TEST_KEY]: { variant: CANDIDATE_VARIANT } } }} | ${[TEST_KEY]} | ${CANDIDATE_VARIANT}
- ${{}} | ${[TEST_KEY]} | ${DEFAULT_VARIANT}
- `('with input=$input and gon=$gon, returns $output', ({ gon, input, output }) => {
- window.gon = gon;
-
- expect(experimentUtils.getExperimentVariant(...input)).toEqual(output);
- });
+ experiment | variant | input | output
+ ${ABC_KEY} | ${DEFAULT_VARIANT} | ${ABC_KEY} | ${DEFAULT_VARIANT}
+ ${ABC_KEY} | ${CANDIDATE_VARIANT} | ${ABC_KEY} | ${CANDIDATE_VARIANT}
+ ${undefined} | ${undefined} | ${ABC_KEY} | ${DEFAULT_VARIANT}
+ `(
+ 'with input=$input, experiment=$experiment, & variant=$variant; returns $output',
+ ({ experiment, variant, input, output }) => {
+ stubExperiments({ [experiment]: variant });
+
+ expect(experimentUtils.getExperimentVariant(input)).toEqual(output);
+ },
+ );
});
});
diff --git a/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js b/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js
index 27ec6a7280f..f244da228b3 100644
--- a/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js
+++ b/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js
@@ -1,5 +1,6 @@
import { GlModal, GlSprintf, GlAlert } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import Component from '~/feature_flags/components/configure_feature_flags_modal.vue';
describe('Configure Feature Flags Modal', () => {
@@ -20,7 +21,7 @@ describe('Configure Feature Flags Modal', () => {
};
let wrapper;
- const factory = (props = {}, { mountFn = shallowMount, ...options } = {}) => {
+ const factory = (props = {}, { mountFn = shallowMountExtended, ...options } = {}) => {
wrapper = mountFn(Component, {
provide,
stubs: { GlSprintf },
@@ -140,11 +141,13 @@ describe('Configure Feature Flags Modal', () => {
describe('has rotate error', () => {
afterEach(() => wrapper.destroy());
- beforeEach(factory.bind(null, { hasRotateError: false }));
+ beforeEach(() => {
+ factory({ hasRotateError: true });
+ });
it('should display an error', async () => {
- expect(wrapper.find('.text-danger')).toExist();
- expect(wrapper.find('[name="warning"]')).toExist();
+ expect(wrapper.findByTestId('rotate-error').exists()).toBe(true);
+ expect(wrapper.find('[name="warning"]').exists()).toBe(true);
});
});
diff --git a/spec/frontend/filterable_list_spec.js b/spec/frontend/filterable_list_spec.js
index 556cf6f8137..3fd5d198e3a 100644
--- a/spec/frontend/filterable_list_spec.js
+++ b/spec/frontend/filterable_list_spec.js
@@ -1,5 +1,4 @@
-// eslint-disable-next-line import/no-deprecated
-import { getJSONFixture, setHTMLFixture } from 'helpers/fixtures';
+import { setHTMLFixture } from 'helpers/fixtures';
import FilterableList from '~/filterable_list';
describe('FilterableList', () => {
@@ -15,8 +14,6 @@ describe('FilterableList', () => {
</div>
<div class="js-projects-list-holder"></div>
`);
- // eslint-disable-next-line import/no-deprecated
- getJSONFixture('static/projects.json');
form = document.querySelector('form#project-filter-form');
filter = document.querySelector('.js-projects-list-filter');
holder = document.querySelector('.js-projects-list-holder');
diff --git a/spec/frontend/fixtures/api_markdown.yml b/spec/frontend/fixtures/api_markdown.yml
index 45f73260887..8fd6a5531db 100644
--- a/spec/frontend/fixtures/api_markdown.yml
+++ b/spec/frontend/fixtures/api_markdown.yml
@@ -2,63 +2,75 @@
# spec/frontend/fixtures/api_markdown.rb and
# spec/frontend/content_editor/extensions/markdown_processing_spec.js
---
+- name: attachment_image
+ context: group
+ markdown: '![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)'
+- name: attachment_image
+ context: project
+ markdown: '![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)'
+- name: attachment_image
+ context: project_wiki
+ markdown: '![test-file](test-file.png)'
+- name: attachment_link
+ context: group
+ markdown: '[test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)'
+- name: attachment_link
+ context: project
+ markdown: '[test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)'
+- name: attachment_link
+ context: project_wiki
+ markdown: '[test-file](test-file.zip)'
+- name: audio
+ markdown: '![Sample Audio](https://gitlab.com/gitlab.mp3)'
+- name: audio_and_video_in_lists
+ markdown: |-
+ * ![Sample Audio](https://gitlab.com/1.mp3)
+ * ![Sample Video](https://gitlab.com/2.mp4)
+
+ 1. ![Sample Video](https://gitlab.com/1.mp4)
+ 2. ![Sample Audio](https://gitlab.com/2.mp3)
+
+ * [x] ![Sample Audio](https://gitlab.com/1.mp3)
+ * [x] ![Sample Audio](https://gitlab.com/2.mp3)
+ * [x] ![Sample Video](https://gitlab.com/3.mp4)
+- name: blockquote
+ markdown: |-
+ > This is a blockquote
+ >
+ > This is another one
- name: bold
markdown: '**bold**'
-- name: emphasis
- markdown: '_emphasized text_'
-- name: inline_code
- markdown: '`code`'
-- name: inline_diff
+- name: bullet_list_style_1
markdown: |-
- * {-deleted-}
- * {+added+}
-- name: strike
- markdown: '~~del~~'
-- name: horizontal_rule
- markdown: '---'
-- name: html_marks
+ * list item 1
+ * list item 2
+ * embedded list item 3
+- name: bullet_list_style_2
markdown: |-
- * Content editor is ~~great~~<ins>amazing</ins>.
- * If the changes <abbr title="Looks good to merge">LGTM</abbr>, please <abbr title="Merge when pipeline succeeds">MWPS</abbr>.
- * The English song <q>Oh I do like to be beside the seaside</q> looks like this in Hebrew: <span dir="rtl">××”, ×× ×™ ×והב להיות ליד חוף ×”×™×</span>. In the computer's memory, this is stored as <bdo dir="ltr">××”, ×× ×™ ×והב להיות ליד חוף ×”×™×</bdo>.
- * <cite>The Scream</cite> by Edvard Munch. Painted in 1893.
- * <dfn>HTML</dfn> is the standard markup language for creating web pages.
- * Do not forget to buy <mark>milk</mark> today.
- * This is a paragraph and <small>smaller text goes here</small>.
- * The concert starts at <time datetime="20:00">20:00</time> and you'll be able to enjoy the band for at least <time datetime="PT2H30M">2h 30m</time>.
- * Press <kbd>Ctrl</kbd> + <kbd>C</kbd> to copy text (Windows).
- * WWF's goal is to: <q>Build a future where people live in harmony with nature.</q> We hope they succeed.
- * The error occured was: <samp>Keyboard not found. Press F1 to continue.</samp>
- * The area of a triangle is: 1/2 x <var>b</var> x <var>h</var>, where <var>b</var> is the base, and <var>h</var> is the vertical height.
- * <ruby>æ¼¢<rt>ã„ㄢˋ</rt></ruby>
- * C<sub>7</sub>H<sub>16</sub> + O<sub>2</sub> → CO<sub>2</sub> + H<sub>2</sub>O
- * The **Pythagorean theorem** is often expressed as <var>a<sup>2</sup></var> + <var>b<sup>2</sup></var> = <var>c<sup>2</sup></var>
-- name: div
+ - list item 1
+ - list item 2
+ * embedded list item 3
+- name: bullet_list_style_3
markdown: |-
- <div>plain text</div>
- <div>
-
- just a plain ol' div, not much to _expect_!
-
- </div>
-- name: figure
+ + list item 1
+ + list item 2
+ - embedded list item 3
+- name: code_block
markdown: |-
- <figure>
-
- ![Elephant at sunset](elephant-sunset.jpg)
-
- <figcaption>An elephant at sunset</figcaption>
- </figure>
- <figure>
-
- ![A crocodile wearing crocs](croc-crocs.jpg)
-
- <figcaption>
-
- A crocodile wearing _crocs_!
-
- </figcaption>
- </figure>
+ ```javascript
+ console.log('hello world')
+ ```
+- name: color_chips
+ markdown: |-
+ - `#F00`
+ - `#F00A`
+ - `#FF0000`
+ - `#FF0000AA`
+ - `RGB(0,255,0)`
+ - `RGB(0%,100%,0%)`
+ - `RGBA(0,255,0,0.3)`
+ - `HSL(540,70%,50%)`
+ - `HSLA(540,70%,50%,0.3)`
- name: description_list
markdown: |-
<dl>
@@ -106,31 +118,57 @@
```
</details>
-- name: link
- markdown: '[GitLab](https://gitlab.com)'
-- name: attachment_link
- context: project_wiki
- markdown: '[test-file](test-file.zip)'
-- name: attachment_link
- context: project
- markdown: '[test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)'
-- name: attachment_link
- context: group
- markdown: '[test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)'
-- name: attachment_image
- context: project_wiki
- markdown: '![test-file](test-file.png)'
-- name: attachment_image
- context: project
- markdown: '![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)'
-- name: attachment_image
- context: group
- markdown: '![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)'
-- name: code_block
+- name: div
markdown: |-
- ```javascript
- console.log('hello world')
- ```
+ <div>plain text</div>
+ <div>
+
+ just a plain ol' div, not much to _expect_!
+
+ </div>
+- name: emoji
+ markdown: ':sparkles: :heart: :100:'
+- name: emphasis
+ markdown: '_emphasized text_'
+- name: figure
+ markdown: |-
+ <figure>
+
+ ![Elephant at sunset](elephant-sunset.jpg)
+
+ <figcaption>An elephant at sunset</figcaption>
+ </figure>
+ <figure>
+
+ ![A crocodile wearing crocs](croc-crocs.jpg)
+
+ <figcaption>
+
+ A crocodile wearing _crocs_!
+
+ </figcaption>
+ </figure>
+- name: frontmatter_json
+ markdown: |-
+ ;;;
+ {
+ "title": "Page title"
+ }
+ ;;;
+- name: frontmatter_toml
+ markdown: |-
+ +++
+ title = "Page title"
+ +++
+- name: frontmatter_yaml
+ markdown: |-
+ ---
+ title: Page title
+ ---
+- name: hard_break
+ markdown: |-
+ This is a line after a\
+ hard break
- name: headings
markdown: |-
# Heading 1
@@ -144,29 +182,44 @@
##### Heading 5
###### Heading 6
-- name: blockquote
- markdown: |-
- > This is a blockquote
- >
- > This is another one
-- name: thematic_break
- markdown: |-
- ---
-- name: bullet_list_style_1
+- name: horizontal_rule
+ markdown: '---'
+- name: html_marks
markdown: |-
- * list item 1
- * list item 2
- * embedded list item 3
-- name: bullet_list_style_2
+ * Content editor is ~~great~~<ins>amazing</ins>.
+ * If the changes <abbr title="Looks good to merge">LGTM</abbr>, please <abbr title="Merge when pipeline succeeds">MWPS</abbr>.
+ * The English song <q>Oh I do like to be beside the seaside</q> looks like this in Hebrew: <span dir="rtl">××”, ×× ×™ ×והב להיות ליד חוף ×”×™×</span>. In the computer's memory, this is stored as <bdo dir="ltr">××”, ×× ×™ ×והב להיות ליד חוף ×”×™×</bdo>.
+ * <cite>The Scream</cite> by Edvard Munch. Painted in 1893.
+ * <dfn>HTML</dfn> is the standard markup language for creating web pages.
+ * Do not forget to buy <mark>milk</mark> today.
+ * This is a paragraph and <small>smaller text goes here</small>.
+ * The concert starts at <time datetime="20:00">20:00</time> and you'll be able to enjoy the band for at least <time datetime="PT2H30M">2h 30m</time>.
+ * Press <kbd>Ctrl</kbd> + <kbd>C</kbd> to copy text (Windows).
+ * WWF's goal is to: <q>Build a future where people live in harmony with nature.</q> We hope they succeed.
+ * The error occured was: <samp>Keyboard not found. Press F1 to continue.</samp>
+ * The area of a triangle is: 1/2 x <var>b</var> x <var>h</var>, where <var>b</var> is the base, and <var>h</var> is the vertical height.
+ * <ruby>æ¼¢<rt>ã„ㄢˋ</rt></ruby>
+ * C<sub>7</sub>H<sub>16</sub> + O<sub>2</sub> → CO<sub>2</sub> + H<sub>2</sub>O
+ * The **Pythagorean theorem** is often expressed as <var>a<sup>2</sup></var> + <var>b<sup>2</sup></var> = <var>c<sup>2</sup></var>
+- name: image
+ markdown: '![alt text](https://gitlab.com/logo.png)'
+- name: inline_code
+ markdown: '`code`'
+- name: inline_diff
markdown: |-
- - list item 1
- - list item 2
- * embedded list item 3
-- name: bullet_list_style_3
+ * {-deleted-}
+ * {+added+}
+- name: link
+ markdown: '[GitLab](https://gitlab.com)'
+- name: math
markdown: |-
- + list item 1
- + list item 2
- - embedded list item 3
+ This math is inline $`a^2+b^2=c^2`$.
+
+ This is on a separate line:
+
+ ```math
+ a^2+b^2=c^2
+ ```
- name: ordered_list
markdown: |-
1. list item 1
@@ -177,14 +230,6 @@
134. list item 1
135. list item 2
136. list item 3
-- name: task_list
- markdown: |-
- * [x] hello
- * [x] world
- * [ ] example
- * [ ] of nested
- * [x] task list
- * [ ] items
- name: ordered_task_list
markdown: |-
1. [x] hello
@@ -198,12 +243,12 @@
4893. [x] hello
4894. [x] world
4895. [ ] example
-- name: image
- markdown: '![alt text](https://gitlab.com/logo.png)'
-- name: hard_break
+- name: reference
+ context: project_wiki
markdown: |-
- This is a line after a\
- hard break
+ Hi @gitlab - thank you for reporting this ~bug (#1) we hope to fix it in %1.1 as part of !1
+- name: strike
+ markdown: '~~del~~'
- name: table
markdown: |-
| header | header |
@@ -212,27 +257,6 @@
| ~~strike~~ | cell with _italic_ |
# content after table
-- name: emoji
- markdown: ':sparkles: :heart: :100:'
-- name: reference
- context: project_wiki
- markdown: |-
- Hi @gitlab - thank you for reporting this ~bug (#1) we hope to fix it in %1.1 as part of !1
-- name: audio
- markdown: '![Sample Audio](https://gitlab.com/gitlab.mp3)'
-- name: video
- markdown: '![Sample Video](https://gitlab.com/gitlab.mp4)'
-- name: audio_and_video_in_lists
- markdown: |-
- * ![Sample Audio](https://gitlab.com/1.mp3)
- * ![Sample Video](https://gitlab.com/2.mp4)
-
- 1. ![Sample Video](https://gitlab.com/1.mp4)
- 2. ![Sample Audio](https://gitlab.com/2.mp3)
-
- * [x] ![Sample Audio](https://gitlab.com/1.mp3)
- * [x] ![Sample Audio](https://gitlab.com/2.mp3)
- * [x] ![Sample Video](https://gitlab.com/3.mp4)
- name: table_of_contents
markdown: |-
[[_TOC_]]
@@ -248,42 +272,18 @@
# Sit amit
### I don't know
-- name: word_break
- markdown: Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz
-- name: frontmatter_yaml
- markdown: |-
- ---
- title: Page title
- ---
-- name: frontmatter_toml
- markdown: |-
- +++
- title = "Page title"
- +++
-- name: frontmatter_json
- markdown: |-
- ;;;
- {
- "title": "Page title"
- }
- ;;;
-- name: color_chips
+- name: task_list
markdown: |-
- - `#F00`
- - `#F00A`
- - `#FF0000`
- - `#FF0000AA`
- - `RGB(0,255,0)`
- - `RGB(0%,100%,0%)`
- - `RGBA(0,255,0,0.3)`
- - `HSL(540,70%,50%)`
- - `HSLA(540,70%,50%,0.3)`
-- name: math
+ * [x] hello
+ * [x] world
+ * [ ] example
+ * [ ] of nested
+ * [x] task list
+ * [ ] items
+- name: thematic_break
markdown: |-
- This math is inline $`a^2+b^2=c^2`$.
-
- This is on a separate line:
-
- ```math
- a^2+b^2=c^2
- ```
+ ---
+- name: video
+ markdown: '![Sample Video](https://gitlab.com/gitlab.mp4)'
+- name: word_break
+ markdown: Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz
diff --git a/spec/frontend/fixtures/projects.rb b/spec/frontend/fixtures/projects.rb
index 3c8964d398a..23c18c97df2 100644
--- a/spec/frontend/fixtures/projects.rb
+++ b/spec/frontend/fixtures/projects.rb
@@ -65,5 +65,31 @@ RSpec.describe 'Projects (JavaScript fixtures)', type: :controller do
expect_graphql_errors_to_be_empty
end
end
+
+ context 'project storage count query' do
+ before do
+ project.statistics.update!(
+ repository_size: 3900000,
+ lfs_objects_size: 4800000,
+ build_artifacts_size: 400000,
+ pipeline_artifacts_size: 400000,
+ wiki_size: 300000,
+ packages_size: 3800000,
+ uploads_size: 900000
+ )
+ end
+
+ base_input_path = 'projects/storage_counter/queries/'
+ base_output_path = 'graphql/projects/storage_counter/'
+ query_name = 'project_storage.query.graphql'
+
+ it "#{base_output_path}#{query_name}.json" do
+ query = get_graphql_query_as_string("#{base_input_path}#{query_name}")
+
+ post_graphql(query, current_user: user, variables: { fullPath: project.full_path })
+
+ expect_graphql_errors_to_be_empty
+ end
+ end
end
end
diff --git a/spec/frontend/flash_spec.js b/spec/frontend/flash_spec.js
index 96e5202780b..f7bde8d2f16 100644
--- a/spec/frontend/flash_spec.js
+++ b/spec/frontend/flash_spec.js
@@ -3,6 +3,7 @@ import createFlash, {
createAction,
hideFlash,
removeFlashClickListener,
+ FLASH_CLOSED_EVENT,
} from '~/flash';
describe('Flash', () => {
@@ -79,6 +80,16 @@ describe('Flash', () => {
expect(el.remove.mock.calls.length).toBe(1);
});
+
+ it(`dispatches ${FLASH_CLOSED_EVENT} event after transitionend event`, () => {
+ jest.spyOn(el, 'dispatchEvent');
+
+ hideFlash(el);
+
+ el.dispatchEvent(new Event('transitionend'));
+
+ expect(el.dispatchEvent).toHaveBeenCalledWith(new Event(FLASH_CLOSED_EVENT));
+ });
});
describe('createAction', () => {
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js
index eb11df2fe43..631e3307f7f 100644
--- a/spec/frontend/gfm_auto_complete_spec.js
+++ b/spec/frontend/gfm_auto_complete_spec.js
@@ -2,7 +2,7 @@
import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import labelsFixture from 'test_fixtures/autocomplete_sources/labels.json';
-import GfmAutoComplete, { membersBeforeSave } from 'ee_else_ce/gfm_auto_complete';
+import GfmAutoComplete, { membersBeforeSave, highlighter } from 'ee_else_ce/gfm_auto_complete';
import { initEmojiMock } from 'helpers/emoji';
import '~/lib/utils/jquery_at_who';
import { TEST_HOST } from 'helpers/test_constants';
@@ -858,4 +858,14 @@ describe('GfmAutoComplete', () => {
);
});
});
+
+ describe('highlighter', () => {
+ it('escapes regex', () => {
+ const li = '<li>couple (woman,woman) <gl-emoji data-name="couple_ww"></gl-emoji></li>';
+
+ expect(highlighter(li, ')')).toBe(
+ '<li> couple (woman,woman<strong>)</strong> <gl-emoji data-name="couple_ww"></gl-emoji></li>',
+ );
+ });
+ });
});
diff --git a/spec/frontend/google_cloud/components/app_spec.js b/spec/frontend/google_cloud/components/app_spec.js
new file mode 100644
index 00000000000..bb86eb5c22e
--- /dev/null
+++ b/spec/frontend/google_cloud/components/app_spec.js
@@ -0,0 +1,66 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlTab, GlTabs } from '@gitlab/ui';
+import App from '~/google_cloud/components/app.vue';
+import IncubationBanner from '~/google_cloud/components/incubation_banner.vue';
+import ServiceAccounts from '~/google_cloud/components/service_accounts.vue';
+
+describe('google_cloud App component', () => {
+ let wrapper;
+
+ const findIncubationBanner = () => wrapper.findComponent(IncubationBanner);
+ const findTabs = () => wrapper.findComponent(GlTabs);
+ const findTabItems = () => findTabs().findAllComponents(GlTab);
+ const findConfigurationTab = () => findTabItems().at(0);
+ const findDeploymentTab = () => findTabItems().at(1);
+ const findServicesTab = () => findTabItems().at(2);
+ const findServiceAccounts = () => findConfigurationTab().findComponent(ServiceAccounts);
+
+ beforeEach(() => {
+ const propsData = {
+ serviceAccounts: [{}, {}],
+ createServiceAccountUrl: '#url-create-service-account',
+ emptyIllustrationUrl: '#url-empty-illustration',
+ };
+ wrapper = shallowMount(App, { propsData });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should contain incubation banner', () => {
+ expect(findIncubationBanner().exists()).toBe(true);
+ });
+
+ describe('google_cloud App tabs', () => {
+ it('should contain tabs', () => {
+ expect(findTabs().exists()).toBe(true);
+ });
+
+ it('should contain three tab items', () => {
+ expect(findTabItems().length).toBe(3);
+ });
+
+ describe('configuration tab', () => {
+ it('should exist', () => {
+ expect(findConfigurationTab().exists()).toBe(true);
+ });
+
+ it('should contain service accounts component', () => {
+ expect(findServiceAccounts().exists()).toBe(true);
+ });
+ });
+
+ describe('deployments tab', () => {
+ it('should exist', () => {
+ expect(findDeploymentTab().exists()).toBe(true);
+ });
+ });
+
+ describe('services tab', () => {
+ it('should exist', () => {
+ expect(findServicesTab().exists()).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/google_cloud/components/incubation_banner_spec.js b/spec/frontend/google_cloud/components/incubation_banner_spec.js
new file mode 100644
index 00000000000..89517be4ef1
--- /dev/null
+++ b/spec/frontend/google_cloud/components/incubation_banner_spec.js
@@ -0,0 +1,60 @@
+import { mount } from '@vue/test-utils';
+import { GlAlert, GlLink } from '@gitlab/ui';
+import IncubationBanner from '~/google_cloud/components/incubation_banner.vue';
+
+describe('IncubationBanner component', () => {
+ let wrapper;
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findLinks = () => wrapper.findAllComponents(GlLink);
+ const findFeatureRequestLink = () => findLinks().at(0);
+ const findReportBugLink = () => findLinks().at(1);
+ const findShareFeedbackLink = () => findLinks().at(2);
+
+ beforeEach(() => {
+ const propsData = {
+ shareFeedbackUrl: 'url_general_feedback',
+ reportBugUrl: 'url_report_bug',
+ featureRequestUrl: 'url_feature_request',
+ };
+ wrapper = mount(IncubationBanner, { propsData });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('contains alert', () => {
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it('contains relevant text', () => {
+ expect(findAlert().text()).toContain(
+ 'This is an experimental feature developed by GitLab Incubation Engineering.',
+ );
+ });
+
+ describe('has relevant gl-links', () => {
+ it('three in total', () => {
+ expect(findLinks().length).toBe(3);
+ });
+
+ it('contains feature request link', () => {
+ const link = findFeatureRequestLink();
+ expect(link.text()).toBe('request a feature');
+ expect(link.attributes('href')).toBe('url_feature_request');
+ });
+
+ it('contains report bug link', () => {
+ const link = findReportBugLink();
+ expect(link.text()).toBe('report a bug');
+ expect(link.attributes('href')).toBe('url_report_bug');
+ });
+
+ it('contains share feedback link', () => {
+ const link = findShareFeedbackLink();
+ expect(link.text()).toBe('share feedback');
+ expect(link.attributes('href')).toBe('url_general_feedback');
+ });
+ });
+});
diff --git a/spec/frontend/google_cloud/components/service_accounts_spec.js b/spec/frontend/google_cloud/components/service_accounts_spec.js
new file mode 100644
index 00000000000..3d097078f03
--- /dev/null
+++ b/spec/frontend/google_cloud/components/service_accounts_spec.js
@@ -0,0 +1,79 @@
+import { mount } from '@vue/test-utils';
+import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
+import ServiceAccounts from '~/google_cloud/components/service_accounts.vue';
+
+describe('ServiceAccounts component', () => {
+ describe('when the project does not have any service accounts', () => {
+ let wrapper;
+
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findButtonInEmptyState = () => findEmptyState().findComponent(GlButton);
+
+ beforeEach(() => {
+ const propsData = {
+ list: [],
+ createUrl: '#create-url',
+ emptyIllustrationUrl: '#empty-illustration-url',
+ };
+ wrapper = mount(ServiceAccounts, { propsData });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('shows the empty state component', () => {
+ expect(findEmptyState().exists()).toBe(true);
+ });
+ it('shows the link to create new service accounts', () => {
+ const button = findButtonInEmptyState();
+ expect(button.exists()).toBe(true);
+ expect(button.text()).toBe('Create service account');
+ expect(button.attributes('href')).toBe('#create-url');
+ });
+ });
+
+ describe('when three service accounts are passed via props', () => {
+ let wrapper;
+
+ const findTitle = () => wrapper.find('h2');
+ const findDescription = () => wrapper.find('p');
+ const findTable = () => wrapper.findComponent(GlTable);
+ const findRows = () => findTable().findAll('tr');
+ const findButton = () => wrapper.findComponent(GlButton);
+
+ beforeEach(() => {
+ const propsData = {
+ list: [{}, {}, {}],
+ createUrl: '#create-url',
+ emptyIllustrationUrl: '#empty-illustration-url',
+ };
+ wrapper = mount(ServiceAccounts, { propsData });
+ });
+
+ it('shows the title', () => {
+ expect(findTitle().text()).toBe('Service Accounts');
+ });
+
+ it('shows the description', () => {
+ expect(findDescription().text()).toBe(
+ 'Service Accounts keys authorize GitLab to deploy your Google Cloud project',
+ );
+ });
+
+ it('shows the table', () => {
+ expect(findTable().exists()).toBe(true);
+ });
+
+ it('table must have three rows + header row', () => {
+ expect(findRows().length).toBe(4);
+ });
+
+ it('shows the link to create new service accounts', () => {
+ const button = findButton();
+ expect(button.exists()).toBe(true);
+ expect(button.text()).toBe('Create service account');
+ expect(button.attributes('href')).toBe('#create-url');
+ });
+ });
+});
diff --git a/spec/frontend/graphql_shared/utils_spec.js b/spec/frontend/graphql_shared/utils_spec.js
index 1732f24eeff..9f478eedbfb 100644
--- a/spec/frontend/graphql_shared/utils_spec.js
+++ b/spec/frontend/graphql_shared/utils_spec.js
@@ -52,6 +52,10 @@ describe('getIdFromGraphQLId', () => {
output: null,
},
{
+ input: 'gid://gitlab/Environments/0',
+ output: 0,
+ },
+ {
input: 'gid://gitlab/Environments/123',
output: 123,
},
diff --git a/spec/frontend/group_settings/components/shared_runners_form_spec.js b/spec/frontend/group_settings/components/shared_runners_form_spec.js
index 78950a8fe20..617d91178e4 100644
--- a/spec/frontend/group_settings/components/shared_runners_form_spec.js
+++ b/spec/frontend/group_settings/components/shared_runners_form_spec.js
@@ -3,13 +3,16 @@ import { shallowMount } from '@vue/test-utils';
import MockAxiosAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import SharedRunnersForm from '~/group_settings/components/shared_runners_form.vue';
-import { ENABLED, DISABLED, ALLOW_OVERRIDE } from '~/group_settings/constants';
import axios from '~/lib/utils/axios_utils';
-const TEST_UPDATE_PATH = '/test/update';
-const DISABLED_PAYLOAD = { shared_runners_setting: DISABLED };
-const ENABLED_PAYLOAD = { shared_runners_setting: ENABLED };
-const OVERRIDE_PAYLOAD = { shared_runners_setting: ALLOW_OVERRIDE };
+const provide = {
+ updatePath: '/test/update',
+ sharedRunnersAvailability: 'enabled',
+ parentSharedRunnersAvailability: null,
+ runnerDisabled: 'disabled',
+ runnerEnabled: 'enabled',
+ runnerAllowOverride: 'allow_override',
+};
jest.mock('~/flash');
@@ -17,13 +20,11 @@ describe('group_settings/components/shared_runners_form', () => {
let wrapper;
let mock;
- const createComponent = (props = {}) => {
+ const createComponent = (provides = {}) => {
wrapper = shallowMount(SharedRunnersForm, {
- propsData: {
- updatePath: TEST_UPDATE_PATH,
- sharedRunnersAvailability: ENABLED,
- parentSharedRunnersAvailability: null,
- ...props,
+ provide: {
+ ...provide,
+ ...provides,
},
});
};
@@ -33,13 +34,13 @@ describe('group_settings/components/shared_runners_form', () => {
const findEnabledToggle = () => wrapper.find('[data-testid="enable-runners-toggle"]');
const findOverrideToggle = () => wrapper.find('[data-testid="override-runners-toggle"]');
const changeToggle = (toggle) => toggle.vm.$emit('change', !toggle.props('value'));
- const getRequestPayload = () => JSON.parse(mock.history.put[0].data);
+ const getSharedRunnersSetting = () => JSON.parse(mock.history.put[0].data).shared_runners_setting;
const isLoadingIconVisible = () => findLoadingIcon().exists();
beforeEach(() => {
mock = new MockAxiosAdapter(axios);
- mock.onPut(TEST_UPDATE_PATH).reply(200);
+ mock.onPut(provide.updatePath).reply(200);
});
afterEach(() => {
@@ -95,7 +96,7 @@ describe('group_settings/components/shared_runners_form', () => {
await waitForPromises();
- expect(getRequestPayload()).toEqual(ENABLED_PAYLOAD);
+ expect(getSharedRunnersSetting()).toEqual(provide.runnerEnabled);
expect(findOverrideToggle().exists()).toBe(false);
});
@@ -104,14 +105,14 @@ describe('group_settings/components/shared_runners_form', () => {
await waitForPromises();
- expect(getRequestPayload()).toEqual(DISABLED_PAYLOAD);
+ expect(getSharedRunnersSetting()).toEqual(provide.runnerDisabled);
expect(findOverrideToggle().exists()).toBe(true);
});
});
describe('override toggle', () => {
beforeEach(() => {
- createComponent({ sharedRunnersAvailability: ALLOW_OVERRIDE });
+ createComponent({ sharedRunnersAvailability: provide.runnerAllowOverride });
});
it('enabling the override toggle sends correct payload', async () => {
@@ -119,7 +120,7 @@ describe('group_settings/components/shared_runners_form', () => {
await waitForPromises();
- expect(getRequestPayload()).toEqual(OVERRIDE_PAYLOAD);
+ expect(getSharedRunnersSetting()).toEqual(provide.runnerAllowOverride);
});
it('disabling the override toggle sends correct payload', async () => {
@@ -127,21 +128,21 @@ describe('group_settings/components/shared_runners_form', () => {
await waitForPromises();
- expect(getRequestPayload()).toEqual(DISABLED_PAYLOAD);
+ expect(getSharedRunnersSetting()).toEqual(provide.runnerDisabled);
});
});
describe('toggle disabled state', () => {
- it(`toggles are not disabled with setting ${DISABLED}`, () => {
- createComponent({ sharedRunnersAvailability: DISABLED });
+ it(`toggles are not disabled with setting ${provide.runnerDisabled}`, () => {
+ createComponent({ sharedRunnersAvailability: provide.runnerDisabled });
expect(findEnabledToggle().props('disabled')).toBe(false);
expect(findOverrideToggle().props('disabled')).toBe(false);
});
it('toggles are disabled', () => {
createComponent({
- sharedRunnersAvailability: DISABLED,
- parentSharedRunnersAvailability: DISABLED,
+ sharedRunnersAvailability: provide.runnerDisabled,
+ parentSharedRunnersAvailability: provide.runnerDisabled,
});
expect(findEnabledToggle().props('disabled')).toBe(true);
expect(findOverrideToggle().props('disabled')).toBe(true);
@@ -154,7 +155,7 @@ describe('group_settings/components/shared_runners_form', () => {
${{ error: 'Undefined error' }} | ${'Undefined error Refresh the page and try again.'}
`(`with error $errorObj`, ({ errorObj, message }) => {
beforeEach(async () => {
- mock.onPut(TEST_UPDATE_PATH).reply(500, errorObj);
+ mock.onPut(provide.updatePath).reply(500, errorObj);
createComponent();
changeToggle(findEnabledToggle());
diff --git a/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap b/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap
index 194a619c4aa..47e3a56e83d 100644
--- a/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap
+++ b/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap
@@ -8,7 +8,7 @@ exports[`IDE pipelines list when loaded renders empty state when no latestPipeli
<empty-state-stub
cansetci="true"
- class="mb-auto mt-auto"
+ class="gl-p-5"
emptystatesvgpath="http://test.host"
/>
</div>
diff --git a/spec/frontend/ide/components/shared/commit_message_field_spec.js b/spec/frontend/ide/components/shared/commit_message_field_spec.js
new file mode 100644
index 00000000000..f4f9b95b233
--- /dev/null
+++ b/spec/frontend/ide/components/shared/commit_message_field_spec.js
@@ -0,0 +1,149 @@
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CommitMessageField from '~/ide/components/shared/commit_message_field.vue';
+
+const DEFAULT_PROPS = {
+ text: 'foo text',
+ placeholder: 'foo placeholder',
+};
+
+describe('CommitMessageField', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(CommitMessageField, {
+ propsData: {
+ ...DEFAULT_PROPS,
+ ...props,
+ },
+ attachTo: document.body,
+ }),
+ );
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findTextArea = () => wrapper.find('textarea');
+ const findHighlights = () => wrapper.findByTestId('highlights');
+ const findHighlightsText = () => wrapper.findByTestId('highlights-text');
+ const findHighlightsMark = () => wrapper.findByTestId('highlights-mark');
+ const findHighlightsTexts = () => wrapper.findAllByTestId('highlights-text');
+ const findHighlightsMarks = () => wrapper.findAllByTestId('highlights-mark');
+
+ const fillText = async (text) => {
+ wrapper.setProps({ text });
+ await nextTick();
+ };
+
+ it('emits input event on input', () => {
+ const value = 'foo';
+
+ createComponent();
+ findTextArea().setValue(value);
+ expect(wrapper.emitted('input')[0][0]).toEqual(value);
+ });
+
+ describe('focus classes', () => {
+ beforeEach(async () => {
+ createComponent();
+ findTextArea().trigger('focus');
+ await nextTick();
+ });
+
+ it('is added on textarea focus', async () => {
+ expect(wrapper.attributes('class')).toEqual(
+ expect.stringContaining('gl-outline-none! gl-focus-ring-border-1-gray-900!'),
+ );
+ });
+
+ it('is removed on textarea blur', async () => {
+ findTextArea().trigger('blur');
+ await nextTick();
+
+ expect(wrapper.attributes('class')).toEqual(
+ expect.not.stringContaining('gl-outline-none! gl-focus-ring-border-1-gray-900!'),
+ );
+ });
+ });
+
+ describe('highlights', () => {
+ describe('subject line', () => {
+ it('does not highlight less than 50 characters', async () => {
+ const text = 'text less than 50 chars';
+
+ createComponent();
+ await fillText(text);
+
+ expect(findHighlightsText().text()).toEqual(text);
+ expect(findHighlightsMark().text()).toBeFalsy();
+ });
+
+ it('highlights characters over 50 length', async () => {
+ const text =
+ 'text less than 50 chars that should not highlighted. text more than 50 should be highlighted';
+
+ createComponent();
+ await fillText(text);
+
+ expect(findHighlightsText().text()).toEqual(text.slice(0, 50));
+ expect(findHighlightsMark().text()).toEqual(text.slice(50));
+ });
+ });
+
+ describe('body text', () => {
+ it('does not highlight body text less tan 72 characters', async () => {
+ const text = 'subject line\nbody content';
+
+ createComponent();
+ await fillText(text);
+
+ expect(findHighlightsTexts()).toHaveLength(2);
+ expect(findHighlightsMarks().at(1).attributes('style')).toEqual('display: none;');
+ });
+
+ it('highlights body text more than 72 characters', async () => {
+ const text =
+ 'subject line\nbody content that will be highlighted when it is more than 72 characters in length';
+
+ createComponent();
+ await fillText(text);
+
+ expect(findHighlightsTexts()).toHaveLength(2);
+ expect(findHighlightsMarks().at(1).attributes('style')).not.toEqual('display: none;');
+ expect(findHighlightsMarks().at(1).element.textContent).toEqual(' in length');
+ });
+
+ it('highlights body text & subject line', async () => {
+ const text =
+ 'text less than 50 chars that should not highlighted\nbody content that will be highlighted when it is more than 72 characters in length';
+
+ createComponent();
+ await fillText(text);
+
+ expect(findHighlightsTexts()).toHaveLength(2);
+ expect(findHighlightsMarks()).toHaveLength(2);
+ expect(findHighlightsMarks().at(0).element.textContent).toEqual('d');
+ expect(findHighlightsMarks().at(1).element.textContent).toEqual(' in length');
+ });
+ });
+ });
+
+ describe('scrolling textarea', () => {
+ it('updates transform of highlights', async () => {
+ const yCoord = 50;
+
+ createComponent();
+ await fillText('subject line\n\n\n\n\n\n\n\n\n\n\nbody content');
+
+ wrapper.vm.$el.querySelector('textarea').scrollTo(0, yCoord);
+ await nextTick();
+
+ expect(wrapper.vm.scrollTop).toEqual(yCoord);
+ expect(findHighlights().attributes('style')).toEqual('transform: translate3d(0, -50px, 0);');
+ });
+ });
+});
diff --git a/spec/frontend/ide/stores/mutations_spec.js b/spec/frontend/ide/stores/mutations_spec.js
index 23fe23bdef9..4602a0837e0 100644
--- a/spec/frontend/ide/stores/mutations_spec.js
+++ b/spec/frontend/ide/stores/mutations_spec.js
@@ -86,12 +86,12 @@ describe('Multi-file store mutations', () => {
mutations.SET_EMPTY_STATE_SVGS(localState, {
emptyStateSvgPath: 'emptyState',
noChangesStateSvgPath: 'noChanges',
- committedStateSvgPath: 'commited',
+ committedStateSvgPath: 'committed',
});
expect(localState.emptyStateSvgPath).toBe('emptyState');
expect(localState.noChangesStateSvgPath).toBe('noChanges');
- expect(localState.committedStateSvgPath).toBe('commited');
+ expect(localState.committedStateSvgPath).toBe('committed');
});
});
diff --git a/spec/frontend/import_entities/components/group_dropdown_spec.js b/spec/frontend/import_entities/components/group_dropdown_spec.js
index f7aa0e889ea..1c1e1e7ebd4 100644
--- a/spec/frontend/import_entities/components/group_dropdown_spec.js
+++ b/spec/frontend/import_entities/components/group_dropdown_spec.js
@@ -24,14 +24,21 @@ describe('Import entities group dropdown component', () => {
});
it('passes namespaces from props to default slot', () => {
- const namespaces = ['ns1', 'ns2'];
+ const namespaces = [
+ { id: 1, fullPath: 'ns1' },
+ { id: 2, fullPath: 'ns2' },
+ ];
createComponent({ namespaces });
expect(namespacesTracker).toHaveBeenCalledWith({ namespaces });
});
it('filters namespaces based on user input', async () => {
- const namespaces = ['match1', 'some unrelated', 'match2'];
+ const namespaces = [
+ { id: 1, fullPath: 'match1' },
+ { id: 2, fullPath: 'some unrelated' },
+ { id: 3, fullPath: 'match2' },
+ ];
createComponent({ namespaces });
namespacesTracker.mockReset();
@@ -39,6 +46,11 @@ describe('Import entities group dropdown component', () => {
await nextTick();
- expect(namespacesTracker).toHaveBeenCalledWith({ namespaces: ['match1', 'match2'] });
+ expect(namespacesTracker).toHaveBeenCalledWith({
+ namespaces: [
+ { id: 1, fullPath: 'match1' },
+ { id: 3, fullPath: 'match2' },
+ ],
+ });
});
});
diff --git a/spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js b/spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js
index 60f0780fdb3..cd56f573011 100644
--- a/spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js
@@ -1,8 +1,6 @@
import { GlButton, GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { STATUSES } from '~/import_entities/constants';
import ImportActionsCell from '~/import_entities/import_groups/components/import_actions_cell.vue';
-import { generateFakeEntry } from '../graphql/fixtures';
describe('import actions cell', () => {
let wrapper;
@@ -10,7 +8,9 @@ describe('import actions cell', () => {
const createComponent = (props) => {
wrapper = shallowMount(ImportActionsCell, {
propsData: {
- groupPathRegex: /^[a-zA-Z]+$/,
+ isFinished: false,
+ isAvailableForImport: false,
+ isInvalid: false,
...props,
},
});
@@ -20,10 +20,9 @@ describe('import actions cell', () => {
wrapper.destroy();
});
- describe('when import status is NONE', () => {
+ describe('when group is available for import', () => {
beforeEach(() => {
- const group = generateFakeEntry({ id: 1, status: STATUSES.NONE });
- createComponent({ group });
+ createComponent({ isAvailableForImport: true });
});
it('renders import button', () => {
@@ -37,10 +36,9 @@ describe('import actions cell', () => {
});
});
- describe('when import status is FINISHED', () => {
+ describe('when group is finished', () => {
beforeEach(() => {
- const group = generateFakeEntry({ id: 1, status: STATUSES.FINISHED });
- createComponent({ group });
+ createComponent({ isAvailableForImport: true, isFinished: true });
});
it('renders re-import button', () => {
@@ -58,29 +56,22 @@ describe('import actions cell', () => {
});
});
- it('does not render import button when group import is in progress', () => {
- const group = generateFakeEntry({ id: 1, status: STATUSES.STARTED });
- createComponent({ group });
+ it('does not render import button when group is not available for import', () => {
+ createComponent({ isAvailableForImport: false });
const button = wrapper.findComponent(GlButton);
expect(button.exists()).toBe(false);
});
- it('renders import button as disabled when there are validation errors', () => {
- const group = generateFakeEntry({
- id: 1,
- status: STATUSES.NONE,
- validation_errors: [{ field: 'new_name', message: 'something ' }],
- });
- createComponent({ group });
+ it('renders import button as disabled when group is invalid', () => {
+ createComponent({ isInvalid: true, isAvailableForImport: true });
const button = wrapper.findComponent(GlButton);
expect(button.props().disabled).toBe(true);
});
it('emits import-group event when import button is clicked', () => {
- const group = generateFakeEntry({ id: 1, status: STATUSES.NONE });
- createComponent({ group });
+ createComponent({ isAvailableForImport: true });
const button = wrapper.findComponent(GlButton);
button.vm.$emit('click');
diff --git a/spec/frontend/import_entities/import_groups/components/import_source_cell_spec.js b/spec/frontend/import_entities/import_groups/components/import_source_cell_spec.js
index 2a56efd1cbb..f2735d86493 100644
--- a/spec/frontend/import_entities/import_groups/components/import_source_cell_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_source_cell_spec.js
@@ -4,6 +4,11 @@ import { STATUSES } from '~/import_entities/constants';
import ImportSourceCell from '~/import_entities/import_groups/components/import_source_cell.vue';
import { generateFakeEntry } from '../graphql/fixtures';
+const generateFakeTableEntry = ({ flags = {}, ...entry }) => ({
+ ...generateFakeEntry(entry),
+ flags,
+});
+
describe('import source cell', () => {
let wrapper;
let group;
@@ -23,14 +28,14 @@ describe('import source cell', () => {
describe('when group status is NONE', () => {
beforeEach(() => {
- group = generateFakeEntry({ id: 1, status: STATUSES.NONE });
+ group = generateFakeTableEntry({ id: 1, status: STATUSES.NONE });
createComponent({ group });
});
it('renders link to a group', () => {
const link = wrapper.findComponent(GlLink);
- expect(link.attributes().href).toBe(group.web_url);
- expect(link.text()).toContain(group.full_path);
+ expect(link.attributes().href).toBe(group.webUrl);
+ expect(link.text()).toContain(group.fullPath);
});
it('does not render last imported line', () => {
@@ -40,20 +45,24 @@ describe('import source cell', () => {
describe('when group status is FINISHED', () => {
beforeEach(() => {
- group = generateFakeEntry({ id: 1, status: STATUSES.FINISHED });
+ group = generateFakeTableEntry({
+ id: 1,
+ status: STATUSES.FINISHED,
+ flags: {
+ isFinished: true,
+ },
+ });
createComponent({ group });
});
it('renders link to a group', () => {
const link = wrapper.findComponent(GlLink);
- expect(link.attributes().href).toBe(group.web_url);
- expect(link.text()).toContain(group.full_path);
+ expect(link.attributes().href).toBe(group.webUrl);
+ expect(link.text()).toContain(group.fullPath);
});
it('renders last imported line', () => {
- expect(wrapper.text()).toMatchInterpolatedText(
- 'fake_group_1 Last imported to root/last-group1',
- );
+ expect(wrapper.text()).toMatchInterpolatedText('fake_group_1 Last imported to root/group1');
});
});
});
diff --git a/spec/frontend/import_entities/import_groups/components/import_table_spec.js b/spec/frontend/import_entities/import_groups/components/import_table_spec.js
index f43e545e049..6e3df21e30a 100644
--- a/spec/frontend/import_entities/import_groups/components/import_table_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_table_spec.js
@@ -1,39 +1,30 @@
-import {
- GlButton,
- GlEmptyState,
- GlLoadingIcon,
- GlSearchBoxByClick,
- GlDropdown,
- GlDropdownItem,
- GlTable,
-} from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
+import MockAdapter from 'axios-mock-adapter';
import createMockApollo from 'helpers/mock_apollo_helper';
-import stubChildren from 'helpers/stub_children';
-import { stubComponent } from 'helpers/stub_component';
import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import httpStatus from '~/lib/utils/http_status';
+import axios from '~/lib/utils/axios_utils';
import { STATUSES } from '~/import_entities/constants';
-import ImportActionsCell from '~/import_entities/import_groups/components/import_actions_cell.vue';
+import { i18n } from '~/import_entities/import_groups/constants';
import ImportTable from '~/import_entities/import_groups/components/import_table.vue';
-import ImportTargetCell from '~/import_entities/import_groups/components/import_target_cell.vue';
import importGroupsMutation from '~/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql';
-import setImportTargetMutation from '~/import_entities/import_groups/graphql/mutations/set_import_target.mutation.graphql';
import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
import { availableNamespacesFixture, generateFakeEntry } from '../graphql/fixtures';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+jest.mock('~/flash');
+jest.mock('~/import_entities/import_groups/services/status_poller');
-const GlDropdownStub = stubComponent(GlDropdown, {
- template: '<div><h1 ref="text"><slot name="button-content"></slot></h1><slot></slot></div>',
-});
+Vue.use(VueApollo);
describe('import table', () => {
let wrapper;
let apolloProvider;
+ let axiosMock;
const SOURCE_URL = 'https://demo.host';
const FAKE_GROUP = generateFakeEntry({ id: 1, status: STATUSES.NONE });
@@ -44,76 +35,81 @@ describe('import table', () => {
const FAKE_PAGE_INFO = { page: 1, perPage: 20, total: 40, totalPages: 2 };
const findImportSelectedButton = () =>
- wrapper.findAllComponents(GlButton).wrappers.find((w) => w.text() === 'Import selected');
- const findPaginationDropdown = () => wrapper.findComponent(GlDropdown);
- const findPaginationDropdownText = () => findPaginationDropdown().find({ ref: 'text' }).text();
+ wrapper.findAll('button').wrappers.find((w) => w.text() === 'Import selected');
+ const findImportButtons = () =>
+ wrapper.findAll('button').wrappers.filter((w) => w.text() === 'Import');
+ const findPaginationDropdown = () => wrapper.find('[aria-label="Page size"]');
+ const findPaginationDropdownText = () => findPaginationDropdown().find('button').text();
- // TODO: remove this ugly approach when
- // issue: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1531
- const findTable = () => wrapper.vm.getTableRef();
+ const selectRow = (idx) =>
+ wrapper.findAll('tbody td input[type=checkbox]').at(idx).trigger('click');
- const createComponent = ({ bulkImportSourceGroups }) => {
+ const createComponent = ({ bulkImportSourceGroups, importGroups }) => {
apolloProvider = createMockApollo([], {
Query: {
availableNamespaces: () => availableNamespacesFixture,
bulkImportSourceGroups,
},
Mutation: {
- setTargetNamespace: jest.fn(),
- setNewName: jest.fn(),
- importGroup: jest.fn(),
+ importGroups,
},
});
wrapper = mount(ImportTable, {
propsData: {
groupPathRegex: /.*/,
+ jobsPath: '/fake_job_path',
sourceUrl: SOURCE_URL,
- groupUrlErrorMessage: 'Please choose a group URL with no special characters or spaces.',
- },
- stubs: {
- ...stubChildren(ImportTable),
- GlSprintf: false,
- GlDropdown: GlDropdownStub,
- GlTable: false,
},
- localVue,
apolloProvider,
});
};
+ beforeAll(() => {
+ gon.api_version = 'v4';
+ });
+
+ beforeEach(() => {
+ axiosMock = new MockAdapter(axios);
+ axiosMock.onGet(/.*\/exists$/, () => []).reply(200);
+ });
+
afterEach(() => {
wrapper.destroy();
});
- it('renders loading icon while performing request', async () => {
- createComponent({
- bulkImportSourceGroups: () => new Promise(() => {}),
+ describe('loading state', () => {
+ it('renders loading icon while performing request', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => new Promise(() => {}),
+ });
+ await waitForPromises();
+
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
- await waitForPromises();
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- });
+ it('does not renders loading icon when request is completed', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => [],
+ });
+ await waitForPromises();
- it('does not renders loading icon when request is completed', async () => {
- createComponent({
- bulkImportSourceGroups: () => [],
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
- await waitForPromises();
-
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
- it('renders message about empty state when no groups are available for import', async () => {
- createComponent({
- bulkImportSourceGroups: () => ({
- nodes: [],
- pageInfo: FAKE_PAGE_INFO,
- }),
- });
- await waitForPromises();
+ describe('empty state', () => {
+ it('renders message about empty state when no groups are available for import', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => ({
+ nodes: [],
+ pageInfo: FAKE_PAGE_INFO,
+ }),
+ });
+ await waitForPromises();
- expect(wrapper.find(GlEmptyState).props().title).toBe('You have no groups to import');
+ expect(wrapper.find(GlEmptyState).props().title).toBe('You have no groups to import');
+ });
});
it('renders import row for each group in response', async () => {
@@ -140,40 +136,51 @@ describe('import table', () => {
expect(wrapper.text()).not.toContain('Showing 1-0');
});
- describe('converts row events to mutation invocations', () => {
- beforeEach(() => {
- createComponent({
- bulkImportSourceGroups: () => ({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO }),
- });
- return waitForPromises();
+ it('invokes importGroups mutation when row button is clicked', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => ({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO }),
});
- it.each`
- event | payload | mutation | variables
- ${'update-target-namespace'} | ${'new-namespace'} | ${setImportTargetMutation} | ${{ sourceGroupId: FAKE_GROUP.id, targetNamespace: 'new-namespace', newName: 'group1' }}
- ${'update-new-name'} | ${'new-name'} | ${setImportTargetMutation} | ${{ sourceGroupId: FAKE_GROUP.id, targetNamespace: 'root', newName: 'new-name' }}
- `('correctly maps $event to mutation', async ({ event, payload, mutation, variables }) => {
- jest.spyOn(apolloProvider.defaultClient, 'mutate');
- wrapper.find(ImportTargetCell).vm.$emit(event, payload);
- await waitForPromises();
- expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledWith({
- mutation,
- variables,
- });
- });
+ jest.spyOn(apolloProvider.defaultClient, 'mutate');
- it('invokes importGroups mutation when row button is clicked', async () => {
- jest.spyOn(apolloProvider.defaultClient, 'mutate');
+ await waitForPromises();
- wrapper.findComponent(ImportActionsCell).vm.$emit('import-group');
- await waitForPromises();
- expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledWith({
- mutation: importGroupsMutation,
- variables: { sourceGroupIds: [FAKE_GROUP.id] },
- });
+ await findImportButtons()[0].trigger('click');
+ expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledWith({
+ mutation: importGroupsMutation,
+ variables: {
+ importRequests: [
+ {
+ newName: FAKE_GROUP.lastImportTarget.newName,
+ sourceGroupId: FAKE_GROUP.id,
+ targetNamespace: availableNamespacesFixture[0].fullPath,
+ },
+ ],
+ },
});
});
+ it('displays error if importing group fails', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => ({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO }),
+ importGroups: () => {
+ throw new Error();
+ },
+ });
+
+ axiosMock.onPost('/import/bulk_imports.json').reply(httpStatus.BAD_REQUEST);
+
+ await waitForPromises();
+ await findImportButtons()[0].trigger('click');
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: i18n.ERROR_IMPORT,
+ }),
+ );
+ });
+
describe('pagination', () => {
const bulkImportSourceGroupsQueryMock = jest
.fn()
@@ -195,10 +202,10 @@ describe('import table', () => {
});
it('updates page size when selected in Dropdown', async () => {
- const otherOption = wrapper.findAllComponents(GlDropdownItem).at(1);
+ const otherOption = findPaginationDropdown().findAll('li p').at(1);
expect(otherOption.text()).toMatchInterpolatedText('50 items per page');
- otherOption.vm.$emit('click');
+ await otherOption.trigger('click');
await waitForPromises();
expect(findPaginationDropdownText()).toMatchInterpolatedText('50 items per page');
@@ -247,7 +254,11 @@ describe('import table', () => {
return waitForPromises();
});
- const findFilterInput = () => wrapper.find(GlSearchBoxByClick);
+ const setFilter = (value) => {
+ const input = wrapper.find('input[placeholder="Filter by source group"]');
+ input.setValue(value);
+ return input.trigger('keydown.enter');
+ };
it('properly passes filter to graphql query when search box is submitted', async () => {
createComponent({
@@ -256,7 +267,7 @@ describe('import table', () => {
await waitForPromises();
const FILTER_VALUE = 'foo';
- findFilterInput().vm.$emit('submit', FILTER_VALUE);
+ await setFilter(FILTER_VALUE);
await waitForPromises();
expect(bulkImportSourceGroupsQueryMock).toHaveBeenCalledWith(
@@ -274,7 +285,7 @@ describe('import table', () => {
await waitForPromises();
const FILTER_VALUE = 'foo';
- findFilterInput().vm.$emit('submit', FILTER_VALUE);
+ await setFilter(FILTER_VALUE);
await waitForPromises();
expect(wrapper.text()).toContain('Showing 1-1 of 40 groups matching filter "foo" from');
@@ -282,12 +293,14 @@ describe('import table', () => {
it('properly resets filter in graphql query when search box is cleared', async () => {
const FILTER_VALUE = 'foo';
- findFilterInput().vm.$emit('submit', FILTER_VALUE);
+ await setFilter(FILTER_VALUE);
await waitForPromises();
bulkImportSourceGroupsQueryMock.mockClear();
await apolloProvider.defaultClient.resetStore();
- findFilterInput().vm.$emit('clear');
+
+ await setFilter('');
+
await waitForPromises();
expect(bulkImportSourceGroupsQueryMock).toHaveBeenCalledWith(
@@ -320,8 +333,8 @@ describe('import table', () => {
}),
});
await waitForPromises();
- wrapper.find(GlTable).vm.$emit('row-selected', [FAKE_GROUPS[0]]);
- await nextTick();
+
+ await selectRow(0);
expect(findImportSelectedButton().props().disabled).toBe(false);
});
@@ -337,7 +350,7 @@ describe('import table', () => {
});
await waitForPromises();
- findTable().selectRow(0);
+ await selectRow(0);
await nextTick();
expect(findImportSelectedButton().props().disabled).toBe(true);
@@ -348,7 +361,6 @@ describe('import table', () => {
generateFakeEntry({
id: 2,
status: STATUSES.NONE,
- validation_errors: [{ field: 'new_name', message: 'FAKE_VALIDATION_ERROR' }],
}),
];
@@ -360,9 +372,9 @@ describe('import table', () => {
});
await waitForPromises();
- // TODO: remove this ugly approach when
- // issue: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1531
- findTable().selectRow(0);
+ await wrapper.find('tbody input[aria-label="New name"]').setValue('');
+ jest.runOnlyPendingTimers();
+ await selectRow(0);
await nextTick();
expect(findImportSelectedButton().props().disabled).toBe(true);
@@ -384,15 +396,28 @@ describe('import table', () => {
jest.spyOn(apolloProvider.defaultClient, 'mutate');
await waitForPromises();
- findTable().selectRow(0);
- findTable().selectRow(1);
+ await selectRow(0);
+ await selectRow(1);
await nextTick();
- findImportSelectedButton().vm.$emit('click');
+ await findImportSelectedButton().trigger('click');
expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledWith({
mutation: importGroupsMutation,
- variables: { sourceGroupIds: [NEW_GROUPS[0].id, NEW_GROUPS[1].id] },
+ variables: {
+ importRequests: [
+ {
+ targetNamespace: availableNamespacesFixture[0].fullPath,
+ newName: NEW_GROUPS[0].lastImportTarget.newName,
+ sourceGroupId: NEW_GROUPS[0].id,
+ },
+ {
+ targetNamespace: availableNamespacesFixture[0].fullPath,
+ newName: NEW_GROUPS[1].lastImportTarget.newName,
+ sourceGroupId: NEW_GROUPS[1].id,
+ },
+ ],
+ },
});
});
});
diff --git a/spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js b/spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js
index be83a61841f..3c2367e22f5 100644
--- a/spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js
@@ -3,20 +3,20 @@ import { shallowMount } from '@vue/test-utils';
import ImportGroupDropdown from '~/import_entities/components/group_dropdown.vue';
import { STATUSES } from '~/import_entities/constants';
import ImportTargetCell from '~/import_entities/import_groups/components/import_target_cell.vue';
-import { availableNamespacesFixture } from '../graphql/fixtures';
-
-const getFakeGroup = (status) => ({
- web_url: 'https://fake.host/',
- full_path: 'fake_group_1',
- full_name: 'fake_name_1',
- import_target: {
- target_namespace: 'root',
- new_name: 'group1',
- },
- id: 1,
- validation_errors: [],
- progress: { status },
-});
+import { generateFakeEntry, availableNamespacesFixture } from '../graphql/fixtures';
+
+const generateFakeTableEntry = ({ flags = {}, ...config }) => {
+ const entry = generateFakeEntry(config);
+
+ return {
+ ...entry,
+ importTarget: {
+ targetNamespace: availableNamespacesFixture[0],
+ newName: entry.lastImportTarget.newName,
+ },
+ flags,
+ };
+};
describe('import target cell', () => {
let wrapper;
@@ -31,7 +31,6 @@ describe('import target cell', () => {
propsData: {
availableNamespaces: availableNamespacesFixture,
groupPathRegex: /.*/,
- groupUrlErrorMessage: 'Please choose a group URL with no special characters or spaces.',
...props,
},
});
@@ -44,11 +43,11 @@ describe('import target cell', () => {
describe('events', () => {
beforeEach(() => {
- group = getFakeGroup(STATUSES.NONE);
+ group = generateFakeTableEntry({ id: 1, status: STATUSES.NONE });
createComponent({ group });
});
- it('invokes $event', () => {
+ it('emits update-new-name when input value is changed', () => {
findNameInput().vm.$emit('input', 'demo');
expect(wrapper.emitted('update-new-name')).toBeDefined();
expect(wrapper.emitted('update-new-name')[0][0]).toBe('demo');
@@ -56,18 +55,23 @@ describe('import target cell', () => {
it('emits update-target-namespace when dropdown option is clicked', () => {
const dropdownItem = findNamespaceDropdown().findAllComponents(GlDropdownItem).at(2);
- const dropdownItemText = dropdownItem.text();
dropdownItem.vm.$emit('click');
expect(wrapper.emitted('update-target-namespace')).toBeDefined();
- expect(wrapper.emitted('update-target-namespace')[0][0]).toBe(dropdownItemText);
+ expect(wrapper.emitted('update-target-namespace')[0][0]).toBe(availableNamespacesFixture[1]);
});
});
describe('when entity status is NONE', () => {
beforeEach(() => {
- group = getFakeGroup(STATUSES.NONE);
+ group = generateFakeTableEntry({
+ id: 1,
+ status: STATUSES.NONE,
+ flags: {
+ isAvailableForImport: true,
+ },
+ });
createComponent({ group });
});
@@ -78,7 +82,7 @@ describe('import target cell', () => {
it('renders only no parent option if available namespaces list is empty', () => {
createComponent({
- group: getFakeGroup(STATUSES.NONE),
+ group: generateFakeTableEntry({ id: 1, status: STATUSES.NONE }),
availableNamespaces: [],
});
@@ -92,7 +96,7 @@ describe('import target cell', () => {
it('renders both no parent option and available namespaces list when available namespaces list is not empty', () => {
createComponent({
- group: getFakeGroup(STATUSES.NONE),
+ group: generateFakeTableEntry({ id: 1, status: STATUSES.NONE }),
availableNamespaces: availableNamespacesFixture,
});
@@ -104,9 +108,12 @@ describe('import target cell', () => {
expect(rest).toHaveLength(availableNamespacesFixture.length);
});
- describe('when entity status is SCHEDULING', () => {
+ describe('when entity is not available for import', () => {
beforeEach(() => {
- group = getFakeGroup(STATUSES.SCHEDULING);
+ group = generateFakeTableEntry({
+ id: 1,
+ flags: { isAvailableForImport: false },
+ });
createComponent({ group });
});
@@ -115,9 +122,9 @@ describe('import target cell', () => {
});
});
- describe('when entity status is FINISHED', () => {
+ describe('when entity is available for import', () => {
beforeEach(() => {
- group = getFakeGroup(STATUSES.FINISHED);
+ group = generateFakeTableEntry({ id: 1, flags: { isAvailableForImport: true } });
createComponent({ group });
});
@@ -125,41 +132,4 @@ describe('import target cell', () => {
expect(findNamespaceDropdown().attributes('disabled')).toBe(undefined);
});
});
-
- describe('validations', () => {
- it('reports invalid group name when name is not matching regex', () => {
- createComponent({
- group: {
- ...getFakeGroup(STATUSES.NONE),
- import_target: {
- target_namespace: 'root',
- new_name: 'very`bad`name',
- },
- },
- groupPathRegex: /^[a-zA-Z]+$/,
- });
-
- expect(wrapper.text()).toContain(
- 'Please choose a group URL with no special characters or spaces.',
- );
- });
-
- it('reports invalid group name if relevant validation error exists', async () => {
- const FAKE_ERROR_MESSAGE = 'fake error';
-
- createComponent({
- group: {
- ...getFakeGroup(STATUSES.NONE),
- validation_errors: [
- {
- field: 'new_name',
- message: FAKE_ERROR_MESSAGE,
- },
- ],
- },
- });
-
- expect(wrapper.text()).toContain(FAKE_ERROR_MESSAGE);
- });
- });
});
diff --git a/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js b/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js
index e1d65095888..f3447494578 100644
--- a/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js
+++ b/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js
@@ -2,32 +2,27 @@ import { InMemoryCache } from 'apollo-cache-inmemory';
import MockAdapter from 'axios-mock-adapter';
import { createMockClient } from 'mock-apollo-client';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
import { STATUSES } from '~/import_entities/constants';
import {
clientTypenames,
createResolvers,
} from '~/import_entities/import_groups/graphql/client_factory';
-import addValidationErrorMutation from '~/import_entities/import_groups/graphql/mutations/add_validation_error.mutation.graphql';
+import { LocalStorageCache } from '~/import_entities/import_groups/graphql/services/local_storage_cache';
import importGroupsMutation from '~/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql';
-import removeValidationErrorMutation from '~/import_entities/import_groups/graphql/mutations/remove_validation_error.mutation.graphql';
-import setImportProgressMutation from '~/import_entities/import_groups/graphql/mutations/set_import_progress.mutation.graphql';
-import setImportTargetMutation from '~/import_entities/import_groups/graphql/mutations/set_import_target.mutation.graphql';
import updateImportStatusMutation from '~/import_entities/import_groups/graphql/mutations/update_import_status.mutation.graphql';
import availableNamespacesQuery from '~/import_entities/import_groups/graphql/queries/available_namespaces.query.graphql';
-import bulkImportSourceGroupQuery from '~/import_entities/import_groups/graphql/queries/bulk_import_source_group.query.graphql';
import bulkImportSourceGroupsQuery from '~/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql';
-import groupAndProjectQuery from '~/import_entities/import_groups/graphql/queries/group_and_project.query.graphql';
-import { StatusPoller } from '~/import_entities/import_groups/graphql/services/status_poller';
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
import { statusEndpointFixture, availableNamespacesFixture } from './fixtures';
jest.mock('~/flash');
-jest.mock('~/import_entities/import_groups/graphql/services/status_poller', () => ({
- StatusPoller: jest.fn().mockImplementation(function mock() {
- this.startPolling = jest.fn();
+jest.mock('~/import_entities/import_groups/graphql/services/local_storage_cache', () => ({
+ LocalStorageCache: jest.fn().mockImplementation(function mock() {
+ this.get = jest.fn();
+ this.set = jest.fn();
+ this.updateStatusByJobId = jest.fn();
}),
}));
@@ -38,13 +33,6 @@ const FAKE_ENDPOINTS = {
jobs: '/fake_jobs',
};
-const FAKE_GROUP_AND_PROJECTS_QUERY_HANDLER = jest.fn().mockResolvedValue({
- data: {
- existingGroup: null,
- existingProject: null,
- },
-});
-
describe('Bulk import resolvers', () => {
let axiosMockAdapter;
let client;
@@ -58,14 +46,28 @@ describe('Bulk import resolvers', () => {
resolvers: createResolvers({ endpoints: FAKE_ENDPOINTS, ...extraResolverArgs }),
});
- mockedClient.setRequestHandler(groupAndProjectQuery, FAKE_GROUP_AND_PROJECTS_QUERY_HANDLER);
-
return mockedClient;
};
- beforeEach(() => {
+ let results;
+ beforeEach(async () => {
axiosMockAdapter = new MockAdapter(axios);
client = createClient();
+
+ axiosMockAdapter.onGet(FAKE_ENDPOINTS.status).reply(httpStatus.OK, statusEndpointFixture);
+ axiosMockAdapter.onGet(FAKE_ENDPOINTS.availableNamespaces).reply(
+ httpStatus.OK,
+ availableNamespacesFixture.map((ns) => ({
+ id: ns.id,
+ full_path: ns.fullPath,
+ })),
+ );
+
+ client.watchQuery({ query: bulkImportSourceGroupsQuery }).subscribe(({ data }) => {
+ results = data.bulkImportSourceGroups.nodes;
+ });
+
+ return waitForPromises();
});
afterEach(() => {
@@ -74,104 +76,41 @@ describe('Bulk import resolvers', () => {
describe('queries', () => {
describe('availableNamespaces', () => {
- let results;
-
+ let namespacesResults;
beforeEach(async () => {
- axiosMockAdapter
- .onGet(FAKE_ENDPOINTS.availableNamespaces)
- .reply(httpStatus.OK, availableNamespacesFixture);
-
const response = await client.query({ query: availableNamespacesQuery });
- results = response.data.availableNamespaces;
+ namespacesResults = response.data.availableNamespaces;
});
it('mirrors REST endpoint response fields', () => {
const extractRelevantFields = (obj) => ({ id: obj.id, full_path: obj.full_path });
- expect(results.map(extractRelevantFields)).toStrictEqual(
+ expect(namespacesResults.map(extractRelevantFields)).toStrictEqual(
availableNamespacesFixture.map(extractRelevantFields),
);
});
});
- describe('bulkImportSourceGroup', () => {
- beforeEach(async () => {
- axiosMockAdapter.onGet(FAKE_ENDPOINTS.status).reply(httpStatus.OK, statusEndpointFixture);
- axiosMockAdapter
- .onGet(FAKE_ENDPOINTS.availableNamespaces)
- .reply(httpStatus.OK, availableNamespacesFixture);
-
- return client.query({
- query: bulkImportSourceGroupsQuery,
- });
- });
-
- it('returns group', async () => {
- const { id } = statusEndpointFixture.importable_data[0];
- const {
- data: { bulkImportSourceGroup: group },
- } = await client.query({
- query: bulkImportSourceGroupQuery,
- variables: { id: id.toString() },
- });
-
- expect(group).toMatchObject(statusEndpointFixture.importable_data[0]);
- });
- });
-
describe('bulkImportSourceGroups', () => {
- let results;
-
- beforeEach(async () => {
- axiosMockAdapter.onGet(FAKE_ENDPOINTS.status).reply(httpStatus.OK, statusEndpointFixture);
- axiosMockAdapter
- .onGet(FAKE_ENDPOINTS.availableNamespaces)
- .reply(httpStatus.OK, availableNamespacesFixture);
- });
-
it('respects cached import state when provided by group manager', async () => {
- const FAKE_JOB_ID = '1';
- const FAKE_STATUS = 'DEMO_STATUS';
- const FAKE_IMPORT_TARGET = {
- new_name: 'test-name',
- target_namespace: 'test-namespace',
+ const [localStorageCache] = LocalStorageCache.mock.instances;
+ const CACHED_DATA = {
+ progress: {
+ id: 'DEMO',
+ status: 'cached',
+ },
};
- const TARGET_INDEX = 0;
+ localStorageCache.get.mockReturnValueOnce(CACHED_DATA);
- const clientWithMockedManager = createClient({
- GroupsManager: jest.fn().mockImplementation(() => ({
- getImportStateFromStorageByGroupId(groupId) {
- if (groupId === statusEndpointFixture.importable_data[TARGET_INDEX].id) {
- return {
- jobId: FAKE_JOB_ID,
- importState: {
- status: FAKE_STATUS,
- importTarget: FAKE_IMPORT_TARGET,
- },
- };
- }
-
- return null;
- },
- })),
- });
-
- const clientResponse = await clientWithMockedManager.query({
+ const updatedResults = await client.query({
query: bulkImportSourceGroupsQuery,
+ fetchPolicy: 'no-cache',
});
- const clientResults = clientResponse.data.bulkImportSourceGroups.nodes;
-
- expect(clientResults[TARGET_INDEX].import_target).toStrictEqual(FAKE_IMPORT_TARGET);
- expect(clientResults[TARGET_INDEX].progress.status).toBe(FAKE_STATUS);
- });
-
- it('populates each result instance with empty import_target when there are no available namespaces', async () => {
- axiosMockAdapter.onGet(FAKE_ENDPOINTS.availableNamespaces).reply(httpStatus.OK, []);
-
- const response = await client.query({ query: bulkImportSourceGroupsQuery });
- results = response.data.bulkImportSourceGroups.nodes;
- expect(results.every((r) => r.import_target.target_namespace === '')).toBe(true);
+ expect(updatedResults.data.bulkImportSourceGroups.nodes[0].progress).toStrictEqual({
+ __typename: clientTypenames.BulkImportProgress,
+ ...CACHED_DATA.progress,
+ });
});
describe('when called', () => {
@@ -181,37 +120,23 @@ describe('Bulk import resolvers', () => {
});
it('mirrors REST endpoint response fields', () => {
- const MIRRORED_FIELDS = ['id', 'full_name', 'full_path', 'web_url'];
+ const MIRRORED_FIELDS = [
+ { from: 'id', to: 'id' },
+ { from: 'full_name', to: 'fullName' },
+ { from: 'full_path', to: 'fullPath' },
+ { from: 'web_url', to: 'webUrl' },
+ ];
expect(
results.every((r, idx) =>
MIRRORED_FIELDS.every(
- (field) => r[field] === statusEndpointFixture.importable_data[idx][field],
+ (field) => r[field.to] === statusEndpointFixture.importable_data[idx][field.from],
),
),
).toBe(true);
});
- it('populates each result instance with status default to none', () => {
- expect(results.every((r) => r.progress.status === STATUSES.NONE)).toBe(true);
- });
-
- it('populates each result instance with import_target defaulted to first available namespace', () => {
- expect(
- results.every(
- (r) => r.import_target.target_namespace === availableNamespacesFixture[0].full_path,
- ),
- ).toBe(true);
- });
-
- it('starts polling when request completes', async () => {
- const [statusPoller] = StatusPoller.mock.instances;
- expect(statusPoller.startPolling).toHaveBeenCalled();
- });
-
- it('requests validation status when request completes', async () => {
- expect(FAKE_GROUP_AND_PROJECTS_QUERY_HANDLER).not.toHaveBeenCalled();
- jest.runOnlyPendingTimers();
- expect(FAKE_GROUP_AND_PROJECTS_QUERY_HANDLER).toHaveBeenCalled();
+ it('populates each result instance with empty status', () => {
+ expect(results.every((r) => r.progress === null)).toBe(true);
});
});
@@ -223,6 +148,7 @@ describe('Bulk import resolvers', () => {
`(
'properly passes GraphQL variable $variable as REST $queryParam query parameter',
async ({ variable, queryParam, value }) => {
+ axiosMockAdapter.resetHistory();
await client.query({
query: bulkImportSourceGroupsQuery,
variables: { [variable]: value },
@@ -237,275 +163,61 @@ describe('Bulk import resolvers', () => {
});
describe('mutations', () => {
- const GROUP_ID = 1;
-
beforeEach(() => {
- client.writeQuery({
- query: bulkImportSourceGroupsQuery,
- data: {
- bulkImportSourceGroups: {
- nodes: [
- {
- __typename: clientTypenames.BulkImportSourceGroup,
- id: GROUP_ID,
- progress: {
- id: `test-${GROUP_ID}`,
- status: STATUSES.NONE,
- },
- web_url: 'https://fake.host/1',
- full_path: 'fake_group_1',
- full_name: 'fake_name_1',
- import_target: {
- target_namespace: 'root',
- new_name: 'group1',
- },
- last_import_target: {
- target_namespace: 'root',
- new_name: 'group1',
- },
- validation_errors: [],
- },
- ],
- pageInfo: {
- page: 1,
- perPage: 20,
- total: 37,
- totalPages: 2,
- },
- },
- },
- });
+ axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(httpStatus.OK, { id: 1 });
});
- describe('setImportTarget', () => {
- it('updates group target namespace and name', async () => {
- const NEW_TARGET_NAMESPACE = 'target';
- const NEW_NAME = 'new';
-
- const {
- data: {
- setImportTarget: {
- id: idInResponse,
- import_target: { target_namespace: namespaceInResponse, new_name: newNameInResponse },
- },
- },
- } = await client.mutate({
- mutation: setImportTargetMutation,
- variables: {
- sourceGroupId: GROUP_ID,
- targetNamespace: NEW_TARGET_NAMESPACE,
- newName: NEW_NAME,
- },
- });
-
- expect(idInResponse).toBe(GROUP_ID);
- expect(namespaceInResponse).toBe(NEW_TARGET_NAMESPACE);
- expect(newNameInResponse).toBe(NEW_NAME);
- });
-
- it('invokes validation', async () => {
- const NEW_TARGET_NAMESPACE = 'target';
- const NEW_NAME = 'new';
-
+ describe('importGroup', () => {
+ it('sets import status to CREATED when request completes', async () => {
await client.mutate({
- mutation: setImportTargetMutation,
+ mutation: importGroupsMutation,
variables: {
- sourceGroupId: GROUP_ID,
- targetNamespace: NEW_TARGET_NAMESPACE,
- newName: NEW_NAME,
+ importRequests: [
+ {
+ sourceGroupId: statusEndpointFixture.importable_data[0].id,
+ newName: 'test',
+ targetNamespace: 'root',
+ },
+ ],
},
});
- expect(FAKE_GROUP_AND_PROJECTS_QUERY_HANDLER).toHaveBeenCalledWith({
- fullPath: `${NEW_TARGET_NAMESPACE}/${NEW_NAME}`,
- });
- });
- });
-
- describe('importGroup', () => {
- it('sets status to SCHEDULING when request initiates', async () => {
- axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(() => new Promise(() => {}));
-
- client.mutate({
- mutation: importGroupsMutation,
- variables: { sourceGroupIds: [GROUP_ID] },
- });
- await waitForPromises();
-
- const {
- bulkImportSourceGroups: { nodes: intermediateResults },
- } = client.readQuery({
- query: bulkImportSourceGroupsQuery,
- });
-
- expect(intermediateResults[0].progress.status).toBe(STATUSES.SCHEDULING);
- });
-
- describe('when request completes', () => {
- let results;
-
- beforeEach(() => {
- client
- .watchQuery({
- query: bulkImportSourceGroupsQuery,
- fetchPolicy: 'cache-only',
- })
- .subscribe(({ data }) => {
- results = data.bulkImportSourceGroups.nodes;
- });
- });
-
- it('sets import status to CREATED when request completes', async () => {
- axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(httpStatus.OK, { id: 1 });
- await client.mutate({
- mutation: importGroupsMutation,
- variables: { sourceGroupIds: [GROUP_ID] },
- });
- await waitForPromises();
-
- expect(results[0].progress.status).toBe(STATUSES.CREATED);
- });
-
- it('resets status to NONE if request fails', async () => {
- axiosMockAdapter
- .onPost(FAKE_ENDPOINTS.createBulkImport)
- .reply(httpStatus.INTERNAL_SERVER_ERROR);
-
- client
- .mutate({
- mutation: [importGroupsMutation],
- variables: { sourceGroupIds: [GROUP_ID] },
- })
- .catch(() => {});
- await waitForPromises();
-
- expect(results[0].progress.status).toBe(STATUSES.NONE);
- });
- });
-
- it('shows default error message when server error is not provided', async () => {
- axiosMockAdapter
- .onPost(FAKE_ENDPOINTS.createBulkImport)
- .reply(httpStatus.INTERNAL_SERVER_ERROR);
-
- client
- .mutate({
- mutation: importGroupsMutation,
- variables: { sourceGroupIds: [GROUP_ID] },
- })
- .catch(() => {});
- await waitForPromises();
-
- expect(createFlash).toHaveBeenCalledWith({ message: 'Importing the group failed' });
- });
-
- it('shows provided error message when error is included in backend response', async () => {
- const CUSTOM_MESSAGE = 'custom message';
-
- axiosMockAdapter
- .onPost(FAKE_ENDPOINTS.createBulkImport)
- .reply(httpStatus.INTERNAL_SERVER_ERROR, { error: CUSTOM_MESSAGE });
-
- client
- .mutate({
- mutation: importGroupsMutation,
- variables: { sourceGroupIds: [GROUP_ID] },
- })
- .catch(() => {});
- await waitForPromises();
-
- expect(createFlash).toHaveBeenCalledWith({ message: CUSTOM_MESSAGE });
+ await axios.waitForAll();
+ expect(results[0].progress.status).toBe(STATUSES.CREATED);
});
});
- it('setImportProgress updates group progress and sets import target', async () => {
+ it('updateImportStatus updates status', async () => {
const NEW_STATUS = 'dummy';
- const FAKE_JOB_ID = 5;
- const IMPORT_TARGET = {
- __typename: 'ClientBulkImportTarget',
- new_name: 'fake_name',
- target_namespace: 'fake_target',
- };
- const {
- data: {
- setImportProgress: { progress, last_import_target: lastImportTarget },
- },
- } = await client.mutate({
- mutation: setImportProgressMutation,
+ await client.mutate({
+ mutation: importGroupsMutation,
variables: {
- sourceGroupId: GROUP_ID,
- status: NEW_STATUS,
- jobId: FAKE_JOB_ID,
- importTarget: IMPORT_TARGET,
+ importRequests: [
+ {
+ sourceGroupId: statusEndpointFixture.importable_data[0].id,
+ newName: 'test',
+ targetNamespace: 'root',
+ },
+ ],
},
});
+ await axios.waitForAll();
+ await waitForPromises();
- expect(lastImportTarget).toStrictEqual(IMPORT_TARGET);
-
- expect(progress).toStrictEqual({
- __typename: clientTypenames.BulkImportProgress,
- id: FAKE_JOB_ID,
- status: NEW_STATUS,
- });
- });
+ const { id } = results[0].progress;
- it('updateImportStatus returns new status', async () => {
- const NEW_STATUS = 'dummy';
- const FAKE_JOB_ID = 5;
const {
data: { updateImportStatus: statusInResponse },
} = await client.mutate({
mutation: updateImportStatusMutation,
- variables: { id: FAKE_JOB_ID, status: NEW_STATUS },
+ variables: { id, status: NEW_STATUS },
});
expect(statusInResponse).toStrictEqual({
__typename: clientTypenames.BulkImportProgress,
- id: FAKE_JOB_ID,
+ id,
status: NEW_STATUS,
});
});
-
- it('addValidationError adds error to group', async () => {
- const FAKE_FIELD = 'some-field';
- const FAKE_MESSAGE = 'some-message';
- const {
- data: {
- addValidationError: { validation_errors: validationErrors },
- },
- } = await client.mutate({
- mutation: addValidationErrorMutation,
- variables: { sourceGroupId: GROUP_ID, field: FAKE_FIELD, message: FAKE_MESSAGE },
- });
-
- expect(validationErrors).toStrictEqual([
- {
- __typename: clientTypenames.BulkImportValidationError,
- field: FAKE_FIELD,
- message: FAKE_MESSAGE,
- },
- ]);
- });
-
- it('removeValidationError removes error from group', async () => {
- const FAKE_FIELD = 'some-field';
- const FAKE_MESSAGE = 'some-message';
-
- await client.mutate({
- mutation: addValidationErrorMutation,
- variables: { sourceGroupId: GROUP_ID, field: FAKE_FIELD, message: FAKE_MESSAGE },
- });
-
- const {
- data: {
- removeValidationError: { validation_errors: validationErrors },
- },
- } = await client.mutate({
- mutation: removeValidationErrorMutation,
- variables: { sourceGroupId: GROUP_ID, field: FAKE_FIELD },
- });
-
- expect(validationErrors).toStrictEqual([]);
- });
});
});
diff --git a/spec/frontend/import_entities/import_groups/graphql/fixtures.js b/spec/frontend/import_entities/import_groups/graphql/fixtures.js
index d1bd52693b6..5f6f9987a8f 100644
--- a/spec/frontend/import_entities/import_groups/graphql/fixtures.js
+++ b/spec/frontend/import_entities/import_groups/graphql/fixtures.js
@@ -1,24 +1,24 @@
+import { STATUSES } from '~/import_entities/constants';
import { clientTypenames } from '~/import_entities/import_groups/graphql/client_factory';
export const generateFakeEntry = ({ id, status, ...rest }) => ({
__typename: clientTypenames.BulkImportSourceGroup,
- web_url: `https://fake.host/${id}`,
- full_path: `fake_group_${id}`,
- full_name: `fake_name_${id}`,
- import_target: {
- target_namespace: 'root',
- new_name: `group${id}`,
- },
- last_import_target: {
- target_namespace: 'root',
- new_name: `last-group${id}`,
+ webUrl: `https://fake.host/${id}`,
+ fullPath: `fake_group_${id}`,
+ fullName: `fake_name_${id}`,
+ lastImportTarget: {
+ id,
+ targetNamespace: 'root',
+ newName: `group${id}`,
},
id,
- progress: {
- id: `test-${id}`,
- status,
- },
- validation_errors: [],
+ progress:
+ status === STATUSES.NONE || status === STATUSES.PENDING
+ ? null
+ : {
+ id,
+ status,
+ },
...rest,
});
@@ -51,9 +51,9 @@ export const statusEndpointFixture = {
],
};
-export const availableNamespacesFixture = [
- { id: 24, full_path: 'Commit451' },
- { id: 22, full_path: 'gitlab-org' },
- { id: 23, full_path: 'gnuwget' },
- { id: 25, full_path: 'jashkenas' },
-];
+export const availableNamespacesFixture = Object.freeze([
+ { id: 24, fullPath: 'Commit451' },
+ { id: 22, fullPath: 'gitlab-org' },
+ { id: 23, fullPath: 'gnuwget' },
+ { id: 25, fullPath: 'jashkenas' },
+]);
diff --git a/spec/frontend/import_entities/import_groups/graphql/services/local_storage_cache_spec.js b/spec/frontend/import_entities/import_groups/graphql/services/local_storage_cache_spec.js
new file mode 100644
index 00000000000..b44a2767ad8
--- /dev/null
+++ b/spec/frontend/import_entities/import_groups/graphql/services/local_storage_cache_spec.js
@@ -0,0 +1,61 @@
+import {
+ KEY,
+ LocalStorageCache,
+} from '~/import_entities/import_groups/graphql/services/local_storage_cache';
+
+describe('Local storage cache', () => {
+ let cache;
+ let storage;
+
+ beforeEach(() => {
+ storage = {
+ getItem: jest.fn(),
+ setItem: jest.fn(),
+ };
+
+ cache = new LocalStorageCache({ storage });
+ });
+
+ describe('storage management', () => {
+ const IMPORT_URL = 'http://fake.url';
+
+ it('loads state from storage on creation', () => {
+ expect(storage.getItem).toHaveBeenCalledWith(KEY);
+ });
+
+ it('saves to storage when set is called', () => {
+ const STORAGE_CONTENT = { fake: 'content ' };
+ cache.set(IMPORT_URL, STORAGE_CONTENT);
+ expect(storage.setItem).toHaveBeenCalledWith(
+ KEY,
+ JSON.stringify({ [IMPORT_URL]: STORAGE_CONTENT }),
+ );
+ });
+
+ it('updates status by job id', () => {
+ const CHANGED_STATUS = 'changed';
+ const JOB_ID = 2;
+
+ cache.set(IMPORT_URL, {
+ progress: {
+ id: JOB_ID,
+ status: 'original',
+ },
+ });
+
+ cache.updateStatusByJobId(JOB_ID, CHANGED_STATUS);
+
+ expect(storage.setItem).toHaveBeenCalledWith(
+ KEY,
+ JSON.stringify({
+ [IMPORT_URL]: {
+ progress: {
+ id: JOB_ID,
+ status: CHANGED_STATUS,
+ },
+ },
+ }),
+ );
+ });
+ });
+});
diff --git a/spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js b/spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js
deleted file mode 100644
index f06babcb149..00000000000
--- a/spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import {
- KEY,
- SourceGroupsManager,
-} from '~/import_entities/import_groups/graphql/services/source_groups_manager';
-
-const FAKE_SOURCE_URL = 'http://demo.host';
-
-describe('SourceGroupsManager', () => {
- let manager;
- let storage;
-
- beforeEach(() => {
- storage = {
- getItem: jest.fn(),
- setItem: jest.fn(),
- };
-
- manager = new SourceGroupsManager({ storage, sourceUrl: FAKE_SOURCE_URL });
- });
-
- describe('storage management', () => {
- const IMPORT_ID = 1;
- const IMPORT_TARGET = { new_name: 'demo', target_namespace: 'foo' };
- const STATUS = 'FAKE_STATUS';
- const FAKE_GROUP = { id: 1, import_target: IMPORT_TARGET, status: STATUS };
-
- it('loads state from storage on creation', () => {
- expect(storage.getItem).toHaveBeenCalledWith(KEY);
- });
-
- it('saves to storage when createImportState is called', () => {
- const FAKE_STATUS = 'fake;';
- manager.createImportState(IMPORT_ID, { status: FAKE_STATUS, groups: [FAKE_GROUP] });
- const storedObject = JSON.parse(storage.setItem.mock.calls[0][1]);
- expect(Object.values(storedObject)[0]).toStrictEqual({
- status: FAKE_STATUS,
- groups: [
- {
- id: FAKE_GROUP.id,
- importTarget: IMPORT_TARGET,
- },
- ],
- });
- });
-
- it('updates storage when previous state is available', () => {
- const CHANGED_STATUS = 'changed';
-
- manager.createImportState(IMPORT_ID, { status: STATUS, groups: [FAKE_GROUP] });
-
- manager.updateImportProgress(IMPORT_ID, CHANGED_STATUS);
- const storedObject = JSON.parse(storage.setItem.mock.calls[1][1]);
- expect(Object.values(storedObject)[0]).toStrictEqual({
- status: CHANGED_STATUS,
- groups: [
- {
- id: FAKE_GROUP.id,
- importTarget: IMPORT_TARGET,
- },
- ],
- });
- });
- });
-});
diff --git a/spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js b/spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js
deleted file mode 100644
index 9c47647c430..00000000000
--- a/spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js
+++ /dev/null
@@ -1,102 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import Visibility from 'visibilityjs';
-import createFlash from '~/flash';
-import { STATUSES } from '~/import_entities/constants';
-import { StatusPoller } from '~/import_entities/import_groups/graphql/services/status_poller';
-import axios from '~/lib/utils/axios_utils';
-import Poll from '~/lib/utils/poll';
-
-jest.mock('visibilityjs');
-jest.mock('~/flash');
-jest.mock('~/lib/utils/poll');
-jest.mock('~/import_entities/import_groups/graphql/services/source_groups_manager', () => ({
- SourceGroupsManager: jest.fn().mockImplementation(function mock() {
- this.setImportStatus = jest.fn();
- this.findByImportId = jest.fn();
- }),
-}));
-
-const FAKE_POLL_PATH = '/fake/poll/path';
-
-describe('Bulk import status poller', () => {
- let poller;
- let mockAdapter;
- let updateImportStatus;
-
- const getPollHistory = () => mockAdapter.history.get.filter((x) => x.url === FAKE_POLL_PATH);
-
- beforeEach(() => {
- mockAdapter = new MockAdapter(axios);
- mockAdapter.onGet(FAKE_POLL_PATH).reply(200, {});
- updateImportStatus = jest.fn();
- poller = new StatusPoller({ updateImportStatus, pollPath: FAKE_POLL_PATH });
- });
-
- it('creates poller with proper config', () => {
- expect(Poll.mock.calls).toHaveLength(1);
- const [[pollConfig]] = Poll.mock.calls;
- expect(typeof pollConfig.method).toBe('string');
-
- const pollOperation = pollConfig.resource[pollConfig.method];
- expect(typeof pollOperation).toBe('function');
- });
-
- it('invokes axios when polling is performed', async () => {
- const [[pollConfig]] = Poll.mock.calls;
- const pollOperation = pollConfig.resource[pollConfig.method];
- expect(getPollHistory()).toHaveLength(0);
-
- pollOperation();
- await axios.waitForAll();
-
- expect(getPollHistory()).toHaveLength(1);
- });
-
- it('subscribes to visibility changes', () => {
- expect(Visibility.change).toHaveBeenCalled();
- });
-
- it.each`
- isHidden | action
- ${true} | ${'stop'}
- ${false} | ${'restart'}
- `('$action polling when hidden is $isHidden', ({ action, isHidden }) => {
- const [pollInstance] = Poll.mock.instances;
- const [[changeHandler]] = Visibility.change.mock.calls;
- Visibility.hidden.mockReturnValue(isHidden);
- expect(pollInstance[action]).not.toHaveBeenCalled();
-
- changeHandler();
-
- expect(pollInstance[action]).toHaveBeenCalled();
- });
-
- it('does not perform polling when constructed', async () => {
- await axios.waitForAll();
-
- expect(getPollHistory()).toHaveLength(0);
- });
-
- it('immediately start polling when requested', async () => {
- const [pollInstance] = Poll.mock.instances;
-
- poller.startPolling();
-
- expect(pollInstance.makeRequest).toHaveBeenCalled();
- });
-
- it('when error occurs shows flash with error', () => {
- const [[pollConfig]] = Poll.mock.calls;
- pollConfig.errorCallback();
- expect(createFlash).toHaveBeenCalled();
- });
-
- it('when success response arrives updates relevant group status', () => {
- const FAKE_ID = 5;
- const [[pollConfig]] = Poll.mock.calls;
- const FAKE_RESPONSE = { id: FAKE_ID, status_name: STATUSES.FINISHED };
- pollConfig.successCallback({ data: [FAKE_RESPONSE] });
-
- expect(updateImportStatus).toHaveBeenCalledWith(FAKE_RESPONSE);
- });
-});
diff --git a/spec/frontend/import_entities/import_groups/services/status_poller_spec.js b/spec/frontend/import_entities/import_groups/services/status_poller_spec.js
new file mode 100644
index 00000000000..01f976562c6
--- /dev/null
+++ b/spec/frontend/import_entities/import_groups/services/status_poller_spec.js
@@ -0,0 +1,97 @@
+import MockAdapter from 'axios-mock-adapter';
+import Visibility from 'visibilityjs';
+import createFlash from '~/flash';
+import { STATUSES } from '~/import_entities/constants';
+import { StatusPoller } from '~/import_entities/import_groups/services/status_poller';
+import axios from '~/lib/utils/axios_utils';
+import Poll from '~/lib/utils/poll';
+
+jest.mock('visibilityjs');
+jest.mock('~/flash');
+jest.mock('~/lib/utils/poll');
+
+const FAKE_POLL_PATH = '/fake/poll/path';
+
+describe('Bulk import status poller', () => {
+ let poller;
+ let mockAdapter;
+ let updateImportStatus;
+
+ const getPollHistory = () => mockAdapter.history.get.filter((x) => x.url === FAKE_POLL_PATH);
+
+ beforeEach(() => {
+ mockAdapter = new MockAdapter(axios);
+ mockAdapter.onGet(FAKE_POLL_PATH).reply(200, {});
+ updateImportStatus = jest.fn();
+ poller = new StatusPoller({ updateImportStatus, pollPath: FAKE_POLL_PATH });
+ });
+
+ it('creates poller with proper config', () => {
+ expect(Poll.mock.calls).toHaveLength(1);
+ const [[pollConfig]] = Poll.mock.calls;
+ expect(typeof pollConfig.method).toBe('string');
+
+ const pollOperation = pollConfig.resource[pollConfig.method];
+ expect(typeof pollOperation).toBe('function');
+ });
+
+ it('invokes axios when polling is performed', async () => {
+ const [[pollConfig]] = Poll.mock.calls;
+ const pollOperation = pollConfig.resource[pollConfig.method];
+ expect(getPollHistory()).toHaveLength(0);
+
+ pollOperation();
+ await axios.waitForAll();
+
+ expect(getPollHistory()).toHaveLength(1);
+ });
+
+ it('subscribes to visibility changes', () => {
+ expect(Visibility.change).toHaveBeenCalled();
+ });
+
+ it.each`
+ isHidden | action
+ ${true} | ${'stop'}
+ ${false} | ${'restart'}
+ `('$action polling when hidden is $isHidden', ({ action, isHidden }) => {
+ const [pollInstance] = Poll.mock.instances;
+ const [[changeHandler]] = Visibility.change.mock.calls;
+ Visibility.hidden.mockReturnValue(isHidden);
+ expect(pollInstance[action]).not.toHaveBeenCalled();
+
+ changeHandler();
+
+ expect(pollInstance[action]).toHaveBeenCalled();
+ });
+
+ it('does not perform polling when constructed', async () => {
+ await axios.waitForAll();
+
+ expect(getPollHistory()).toHaveLength(0);
+ });
+
+ it('immediately start polling when requested', async () => {
+ const [pollInstance] = Poll.mock.instances;
+
+ poller.startPolling();
+ await Promise.resolve();
+
+ expect(pollInstance.makeRequest).toHaveBeenCalled();
+ });
+
+ it('when error occurs shows flash with error', () => {
+ const [[pollConfig]] = Poll.mock.calls;
+ pollConfig.errorCallback();
+ expect(createFlash).toHaveBeenCalled();
+ });
+
+ it('when success response arrives updates relevant group status', () => {
+ const FAKE_ID = 5;
+ const [[pollConfig]] = Poll.mock.calls;
+ const FAKE_RESPONSE = { id: FAKE_ID, status_name: STATUSES.FINISHED };
+ pollConfig.successCallback({ data: [FAKE_RESPONSE] });
+
+ expect(updateImportStatus).toHaveBeenCalledWith(FAKE_RESPONSE);
+ });
+});
diff --git a/spec/frontend/incidents/components/incidents_list_spec.js b/spec/frontend/incidents/components/incidents_list_spec.js
index 8d4ccab2a40..48545ffd2d6 100644
--- a/spec/frontend/incidents/components/incidents_list_spec.js
+++ b/spec/frontend/incidents/components/incidents_list_spec.js
@@ -78,6 +78,7 @@ describe('Incidents List', () => {
authorUsernameQuery: '',
assigneeUsernameQuery: '',
slaFeatureAvailable: true,
+ canCreateIncident: true,
...provide,
},
stubs: {
@@ -105,21 +106,23 @@ describe('Incidents List', () => {
describe('empty state', () => {
const {
- emptyState: { title, emptyClosedTabTitle, description },
+ emptyState: { title, emptyClosedTabTitle, description, cannotCreateIncidentDescription },
} = I18N;
it.each`
- statusFilter | all | closed | expectedTitle | expectedDescription
- ${'all'} | ${2} | ${1} | ${title} | ${description}
- ${'open'} | ${2} | ${0} | ${title} | ${description}
- ${'closed'} | ${0} | ${0} | ${title} | ${description}
- ${'closed'} | ${2} | ${0} | ${emptyClosedTabTitle} | ${undefined}
+ statusFilter | all | closed | expectedTitle | canCreateIncident | expectedDescription
+ ${'all'} | ${2} | ${1} | ${title} | ${true} | ${description}
+ ${'open'} | ${2} | ${0} | ${title} | ${true} | ${description}
+ ${'closed'} | ${0} | ${0} | ${title} | ${true} | ${description}
+ ${'closed'} | ${2} | ${0} | ${emptyClosedTabTitle} | ${true} | ${undefined}
+ ${'all'} | ${2} | ${1} | ${title} | ${false} | ${cannotCreateIncidentDescription}
`(
`when active tab is $statusFilter and there are $all incidents in total and $closed closed incidents, the empty state
has title: $expectedTitle and description: $expectedDescription`,
- ({ statusFilter, all, closed, expectedTitle, expectedDescription }) => {
+ ({ statusFilter, all, closed, expectedTitle, expectedDescription, canCreateIncident }) => {
mountComponent({
data: { incidents: { list: [] }, incidentsCount: { all, closed }, statusFilter },
+ provide: { canCreateIncident },
loading: false,
});
expect(findEmptyState().exists()).toBe(true);
@@ -219,6 +222,15 @@ describe('Incidents List', () => {
expect(findCreateIncidentBtn().exists()).toBe(false);
});
+ it("doesn't show the button when user does not have incident creation permissions", () => {
+ mountComponent({
+ data: { incidents: { list: mockIncidents }, incidentsCount: {} },
+ provide: { canCreateIncident: false },
+ loading: false,
+ });
+ expect(findCreateIncidentBtn().exists()).toBe(false);
+ });
+
it('should track create new incident button', async () => {
findCreateIncidentBtn().vm.$emit('click');
await wrapper.vm.$nextTick();
diff --git a/spec/frontend/integrations/edit/components/dynamic_field_spec.js b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
index da8a2f41c1b..bf044e388ea 100644
--- a/spec/frontend/integrations/edit/components/dynamic_field_spec.js
+++ b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
@@ -35,136 +35,145 @@ describe('DynamicField', () => {
const findGlFormTextarea = () => wrapper.findComponent(GlFormTextarea);
describe('template', () => {
- describe.each([
- [true, 'disabled', 'readonly'],
- [false, undefined, undefined],
- ])('dynamic field, when isInheriting = `%p`', (isInheriting, disabled, readonly) => {
- describe('type is checkbox', () => {
- beforeEach(() => {
- createComponent(
- {
- type: 'checkbox',
- },
- isInheriting,
- );
- });
+ describe.each`
+ isInheriting | disabled | readonly | checkboxLabel
+ ${true} | ${'disabled'} | ${'readonly'} | ${undefined}
+ ${false} | ${undefined} | ${undefined} | ${'Custom checkbox label'}
+ `(
+ 'dynamic field, when isInheriting = `%p`',
+ ({ isInheriting, disabled, readonly, checkboxLabel }) => {
+ describe('type is checkbox', () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ type: 'checkbox',
+ checkboxLabel,
+ },
+ isInheriting,
+ );
+ });
- it(`renders GlFormCheckbox, which ${isInheriting ? 'is' : 'is not'} disabled`, () => {
- expect(findGlFormCheckbox().exists()).toBe(true);
- expect(findGlFormCheckbox().find('[type=checkbox]').attributes('disabled')).toBe(
- disabled,
- );
- });
+ it(`renders GlFormCheckbox, which ${isInheriting ? 'is' : 'is not'} disabled`, () => {
+ expect(findGlFormCheckbox().exists()).toBe(true);
+ expect(findGlFormCheckbox().find('[type=checkbox]').attributes('disabled')).toBe(
+ disabled,
+ );
+ });
- it('does not render other types of input', () => {
- expect(findGlFormSelect().exists()).toBe(false);
- expect(findGlFormTextarea().exists()).toBe(false);
- expect(findGlFormInput().exists()).toBe(false);
- });
- });
+ it(`renders GlFormCheckbox with correct text content when checkboxLabel is ${checkboxLabel}`, () => {
+ expect(findGlFormCheckbox().text()).toBe(checkboxLabel ?? defaultProps.title);
+ });
- describe('type is select', () => {
- beforeEach(() => {
- createComponent(
- {
- type: 'select',
- choices: [
- ['all', 'All details'],
- ['standard', 'Standard'],
- ],
- },
- isInheriting,
- );
+ it('does not render other types of input', () => {
+ expect(findGlFormSelect().exists()).toBe(false);
+ expect(findGlFormTextarea().exists()).toBe(false);
+ expect(findGlFormInput().exists()).toBe(false);
+ });
});
- it(`renders GlFormSelect, which ${isInheriting ? 'is' : 'is not'} disabled`, () => {
- expect(findGlFormSelect().exists()).toBe(true);
- expect(findGlFormSelect().findAll('option')).toHaveLength(2);
- expect(findGlFormSelect().find('select').attributes('disabled')).toBe(disabled);
- });
+ describe('type is select', () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ type: 'select',
+ choices: [
+ ['all', 'All details'],
+ ['standard', 'Standard'],
+ ],
+ },
+ isInheriting,
+ );
+ });
- it('does not render other types of input', () => {
- expect(findGlFormCheckbox().exists()).toBe(false);
- expect(findGlFormTextarea().exists()).toBe(false);
- expect(findGlFormInput().exists()).toBe(false);
- });
- });
+ it(`renders GlFormSelect, which ${isInheriting ? 'is' : 'is not'} disabled`, () => {
+ expect(findGlFormSelect().exists()).toBe(true);
+ expect(findGlFormSelect().findAll('option')).toHaveLength(2);
+ expect(findGlFormSelect().find('select').attributes('disabled')).toBe(disabled);
+ });
- describe('type is textarea', () => {
- beforeEach(() => {
- createComponent(
- {
- type: 'textarea',
- },
- isInheriting,
- );
+ it('does not render other types of input', () => {
+ expect(findGlFormCheckbox().exists()).toBe(false);
+ expect(findGlFormTextarea().exists()).toBe(false);
+ expect(findGlFormInput().exists()).toBe(false);
+ });
});
- it(`renders GlFormTextarea, which ${isInheriting ? 'is' : 'is not'} readonly`, () => {
- expect(findGlFormTextarea().exists()).toBe(true);
- expect(findGlFormTextarea().find('textarea').attributes('readonly')).toBe(readonly);
- });
+ describe('type is textarea', () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ type: 'textarea',
+ },
+ isInheriting,
+ );
+ });
- it('does not render other types of input', () => {
- expect(findGlFormCheckbox().exists()).toBe(false);
- expect(findGlFormSelect().exists()).toBe(false);
- expect(findGlFormInput().exists()).toBe(false);
- });
- });
+ it(`renders GlFormTextarea, which ${isInheriting ? 'is' : 'is not'} readonly`, () => {
+ expect(findGlFormTextarea().exists()).toBe(true);
+ expect(findGlFormTextarea().find('textarea').attributes('readonly')).toBe(readonly);
+ });
- describe('type is password', () => {
- beforeEach(() => {
- createComponent(
- {
- type: 'password',
- },
- isInheriting,
- );
+ it('does not render other types of input', () => {
+ expect(findGlFormCheckbox().exists()).toBe(false);
+ expect(findGlFormSelect().exists()).toBe(false);
+ expect(findGlFormInput().exists()).toBe(false);
+ });
});
- it(`renders GlFormInput, which ${isInheriting ? 'is' : 'is not'} readonly`, () => {
- expect(findGlFormInput().exists()).toBe(true);
- expect(findGlFormInput().attributes('type')).toBe('password');
- expect(findGlFormInput().attributes('readonly')).toBe(readonly);
- });
+ describe('type is password', () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ type: 'password',
+ },
+ isInheriting,
+ );
+ });
- it('does not render other types of input', () => {
- expect(findGlFormCheckbox().exists()).toBe(false);
- expect(findGlFormSelect().exists()).toBe(false);
- expect(findGlFormTextarea().exists()).toBe(false);
- });
- });
+ it(`renders GlFormInput, which ${isInheriting ? 'is' : 'is not'} readonly`, () => {
+ expect(findGlFormInput().exists()).toBe(true);
+ expect(findGlFormInput().attributes('type')).toBe('password');
+ expect(findGlFormInput().attributes('readonly')).toBe(readonly);
+ });
- describe('type is text', () => {
- beforeEach(() => {
- createComponent(
- {
- type: 'text',
- required: true,
- },
- isInheriting,
- );
+ it('does not render other types of input', () => {
+ expect(findGlFormCheckbox().exists()).toBe(false);
+ expect(findGlFormSelect().exists()).toBe(false);
+ expect(findGlFormTextarea().exists()).toBe(false);
+ });
});
- it(`renders GlFormInput, which ${isInheriting ? 'is' : 'is not'} readonly`, () => {
- expect(findGlFormInput().exists()).toBe(true);
- expect(findGlFormInput().attributes()).toMatchObject({
- type: 'text',
- id: 'service_project_url',
- name: 'service[project_url]',
- placeholder: defaultProps.placeholder,
- required: 'required',
+ describe('type is text', () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ type: 'text',
+ required: true,
+ },
+ isInheriting,
+ );
});
- expect(findGlFormInput().attributes('readonly')).toBe(readonly);
- });
- it('does not render other types of input', () => {
- expect(findGlFormCheckbox().exists()).toBe(false);
- expect(findGlFormSelect().exists()).toBe(false);
- expect(findGlFormTextarea().exists()).toBe(false);
+ it(`renders GlFormInput, which ${isInheriting ? 'is' : 'is not'} readonly`, () => {
+ expect(findGlFormInput().exists()).toBe(true);
+ expect(findGlFormInput().attributes()).toMatchObject({
+ type: 'text',
+ id: 'service_project_url',
+ name: 'service[project_url]',
+ placeholder: defaultProps.placeholder,
+ required: 'required',
+ });
+ expect(findGlFormInput().attributes('readonly')).toBe(readonly);
+ });
+
+ it('does not render other types of input', () => {
+ expect(findGlFormCheckbox().exists()).toBe(false);
+ expect(findGlFormSelect().exists()).toBe(false);
+ expect(findGlFormTextarea().exists()).toBe(false);
+ });
});
- });
- });
+ },
+ );
describe('help text', () => {
it('renders description with help text', () => {
diff --git a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
index 119afbfecfe..3a664b652ac 100644
--- a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
@@ -1,7 +1,10 @@
import { GlFormCheckbox, GlFormInput } from '@gitlab/ui';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { GET_JIRA_ISSUE_TYPES_EVENT } from '~/integrations/constants';
+import {
+ GET_JIRA_ISSUE_TYPES_EVENT,
+ VALIDATE_INTEGRATION_FORM_EVENT,
+} from '~/integrations/constants';
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
import eventHub from '~/integrations/edit/event_hub';
import { createStore } from '~/integrations/edit/store';
@@ -17,12 +20,17 @@ describe('JiraIssuesFields', () => {
upgradePlanPath: 'https://gitlab.com',
};
- const createComponent = ({ isInheriting = false, props, ...options } = {}) => {
+ const createComponent = ({
+ isInheriting = false,
+ mountFn = mountExtended,
+ props,
+ ...options
+ } = {}) => {
store = createStore({
defaultState: isInheriting ? {} : undefined,
});
- wrapper = mountExtended(JiraIssuesFields, {
+ wrapper = mountFn(JiraIssuesFields, {
propsData: { ...defaultProps, ...props },
store,
stubs: ['jira-issue-creation-vulnerabilities'],
@@ -38,12 +46,19 @@ describe('JiraIssuesFields', () => {
const findEnableCheckboxDisabled = () =>
findEnableCheckbox().find('[type=checkbox]').attributes('disabled');
const findProjectKey = () => wrapper.findComponent(GlFormInput);
+ const findProjectKeyFormGroup = () => wrapper.findByTestId('project-key-form-group');
const findPremiumUpgradeCTA = () => wrapper.findByTestId('premium-upgrade-cta');
const findUltimateUpgradeCTA = () => wrapper.findByTestId('ultimate-upgrade-cta');
const findJiraForVulnerabilities = () => wrapper.findByTestId('jira-for-vulnerabilities');
+ const findConflictWarning = () => wrapper.findByTestId('conflict-warning-text');
const setEnableCheckbox = async (isEnabled = true) =>
findEnableCheckbox().vm.$emit('input', isEnabled);
+ const assertProjectKeyState = (expectedStateValue) => {
+ expect(findProjectKey().attributes('state')).toBe(expectedStateValue);
+ expect(findProjectKeyFormGroup().attributes('state')).toBe(expectedStateValue);
+ };
+
describe('template', () => {
describe.each`
showJiraIssuesIntegration | showJiraVulnerabilitiesIntegration
@@ -151,19 +166,18 @@ describe('JiraIssuesFields', () => {
});
describe('GitLab issues warning', () => {
- const expectedText = 'Consider disabling GitLab issues';
-
- it('contains warning when GitLab issues is enabled', () => {
- createComponent();
-
- expect(wrapper.text()).toContain(expectedText);
- });
-
- it('does not contain warning when GitLab issues is disabled', () => {
- createComponent({ props: { gitlabIssuesEnabled: false } });
-
- expect(wrapper.text()).not.toContain(expectedText);
- });
+ it.each`
+ gitlabIssuesEnabled | scenario
+ ${true} | ${'displays conflict warning'}
+ ${false} | ${'does not display conflict warning'}
+ `(
+ '$scenario when `gitlabIssuesEnabled` is `$gitlabIssuesEnabled`',
+ ({ gitlabIssuesEnabled }) => {
+ createComponent({ props: { gitlabIssuesEnabled } });
+
+ expect(findConflictWarning().exists()).toBe(gitlabIssuesEnabled);
+ },
+ );
});
describe('Vulnerabilities creation', () => {
@@ -211,5 +225,44 @@ describe('JiraIssuesFields', () => {
expect(eventHubEmitSpy).toHaveBeenCalledWith(GET_JIRA_ISSUE_TYPES_EVENT);
});
});
+
+ describe('Project key input field', () => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ initialProjectKey: '',
+ initialEnableJiraIssues: true,
+ },
+ mountFn: shallowMountExtended,
+ });
+ });
+
+ it('sets Project Key `state` attribute to `true` by default', () => {
+ assertProjectKeyState('true');
+ });
+
+ describe('when event hub recieves `VALIDATE_INTEGRATION_FORM_EVENT` event', () => {
+ describe('with no project key', () => {
+ it('sets Project Key `state` attribute to `undefined`', async () => {
+ eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
+ await wrapper.vm.$nextTick();
+
+ assertProjectKeyState(undefined);
+ });
+ });
+
+ describe('when project key is set', () => {
+ it('sets Project Key `state` attribute to `true`', async () => {
+ eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
+
+ // set the project key
+ await findProjectKey().vm.$emit('input', 'AB');
+ await wrapper.vm.$nextTick();
+
+ assertProjectKeyState('true');
+ });
+ });
+ });
+ });
});
});
diff --git a/spec/frontend/integrations/integration_settings_form_spec.js b/spec/frontend/integrations/integration_settings_form_spec.js
index f8f3f0fd318..c35d178e518 100644
--- a/spec/frontend/integrations/integration_settings_form_spec.js
+++ b/spec/frontend/integrations/integration_settings_form_spec.js
@@ -1,27 +1,38 @@
import MockAdaptor from 'axios-mock-adapter';
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
+import eventHub from '~/integrations/edit/event_hub';
import axios from '~/lib/utils/axios_utils';
import toast from '~/vue_shared/plugins/global_toast';
+import {
+ I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
+ I18N_SUCCESSFUL_CONNECTION_MESSAGE,
+ I18N_DEFAULT_ERROR_MESSAGE,
+ GET_JIRA_ISSUE_TYPES_EVENT,
+ TOGGLE_INTEGRATION_EVENT,
+ TEST_INTEGRATION_EVENT,
+ SAVE_INTEGRATION_EVENT,
+} from '~/integrations/constants';
+import waitForPromises from 'helpers/wait_for_promises';
jest.mock('~/vue_shared/plugins/global_toast');
+jest.mock('lodash/delay', () => (callback) => callback());
+
+const FIXTURE = 'services/edit_service.html';
describe('IntegrationSettingsForm', () => {
- const FIXTURE = 'services/edit_service.html';
+ let integrationSettingsForm;
+
+ const mockStoreDispatch = () => jest.spyOn(integrationSettingsForm.vue.$store, 'dispatch');
beforeEach(() => {
loadFixtures(FIXTURE);
+
+ integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
+ integrationSettingsForm.init();
});
describe('constructor', () => {
- let integrationSettingsForm;
-
- beforeEach(() => {
- integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- jest.spyOn(integrationSettingsForm, 'init').mockImplementation(() => {});
- });
-
it('should initialize form element refs on class object', () => {
- // Form Reference
expect(integrationSettingsForm.$form).toBeDefined();
expect(integrationSettingsForm.$form.nodeName).toBe('FORM');
expect(integrationSettingsForm.formActive).toBeDefined();
@@ -32,180 +43,206 @@ describe('IntegrationSettingsForm', () => {
});
});
- describe('toggleServiceState', () => {
- let integrationSettingsForm;
+ describe('event handling', () => {
+ let mockAxios;
beforeEach(() => {
- integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- });
-
- it('should remove `novalidate` attribute to form when called with `true`', () => {
- integrationSettingsForm.formActive = true;
- integrationSettingsForm.toggleServiceState();
-
- expect(integrationSettingsForm.$form.getAttribute('novalidate')).toBe(null);
- });
-
- it('should set `novalidate` attribute to form when called with `false`', () => {
- integrationSettingsForm.formActive = false;
- integrationSettingsForm.toggleServiceState();
-
- expect(integrationSettingsForm.$form.getAttribute('novalidate')).toBeDefined();
- });
- });
-
- describe('testSettings', () => {
- let integrationSettingsForm;
- let formData;
- let mock;
-
- beforeEach(() => {
- mock = new MockAdaptor(axios);
-
+ mockAxios = new MockAdaptor(axios);
jest.spyOn(axios, 'put');
-
- integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- integrationSettingsForm.init();
-
- formData = new FormData(integrationSettingsForm.$form);
});
afterEach(() => {
- mock.restore();
+ mockAxios.restore();
+ eventHub.dispose(); // clear event hub handlers
});
- it('should make an ajax request with provided `formData`', async () => {
- await integrationSettingsForm.testSettings(formData);
+ describe('when event hub receives `TOGGLE_INTEGRATION_EVENT`', () => {
+ it('should remove `novalidate` attribute to form when called with `true`', () => {
+ eventHub.$emit(TOGGLE_INTEGRATION_EVENT, true);
- expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData);
- });
+ expect(integrationSettingsForm.$form.getAttribute('novalidate')).toBe(null);
+ });
- it('should show success message if test is successful', async () => {
- jest.spyOn(integrationSettingsForm.$form, 'submit').mockImplementation(() => {});
+ it('should set `novalidate` attribute to form when called with `false`', () => {
+ eventHub.$emit(TOGGLE_INTEGRATION_EVENT, false);
- mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: false,
+ expect(integrationSettingsForm.$form.getAttribute('novalidate')).toBe('novalidate');
});
+ });
- await integrationSettingsForm.testSettings(formData);
+ describe('when event hub receives `TEST_INTEGRATION_EVENT`', () => {
+ describe('when form is valid', () => {
+ beforeEach(() => {
+ jest.spyOn(integrationSettingsForm.$form, 'checkValidity').mockReturnValue(true);
+ });
- expect(toast).toHaveBeenCalledWith('Connection successful.');
- });
+ it('should make an ajax request with provided `formData`', async () => {
+ eventHub.$emit(TEST_INTEGRATION_EVENT);
+ await waitForPromises();
- it('should show error message if ajax request responds with test error', async () => {
- const errorMessage = 'Test failed.';
- const serviceResponse = 'some error';
+ expect(axios.put).toHaveBeenCalledWith(
+ integrationSettingsForm.testEndPoint,
+ new FormData(integrationSettingsForm.$form),
+ );
+ });
- mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: true,
- message: errorMessage,
- service_response: serviceResponse,
- test_failed: false,
- });
+ it('should show success message if test is successful', async () => {
+ jest.spyOn(integrationSettingsForm.$form, 'submit').mockImplementation(() => {});
- await integrationSettingsForm.testSettings(formData);
+ mockAxios.onPut(integrationSettingsForm.testEndPoint).reply(200, {
+ error: false,
+ });
- expect(toast).toHaveBeenCalledWith(`${errorMessage} ${serviceResponse}`);
- });
+ eventHub.$emit(TEST_INTEGRATION_EVENT);
+ await waitForPromises();
- it('should show error message if ajax request failed', async () => {
- const errorMessage = 'Something went wrong on our end.';
+ expect(toast).toHaveBeenCalledWith(I18N_SUCCESSFUL_CONNECTION_MESSAGE);
+ });
- mock.onPut(integrationSettingsForm.testEndPoint).networkError();
+ it('should show error message if ajax request responds with test error', async () => {
+ const errorMessage = 'Test failed.';
+ const serviceResponse = 'some error';
- await integrationSettingsForm.testSettings(formData);
+ mockAxios.onPut(integrationSettingsForm.testEndPoint).reply(200, {
+ error: true,
+ message: errorMessage,
+ service_response: serviceResponse,
+ test_failed: false,
+ });
- expect(toast).toHaveBeenCalledWith(errorMessage);
- });
+ eventHub.$emit(TEST_INTEGRATION_EVENT);
+ await waitForPromises();
- it('should always dispatch `setIsTesting` with `false` once request is completed', async () => {
- const dispatchSpy = jest.fn();
+ expect(toast).toHaveBeenCalledWith(`${errorMessage} ${serviceResponse}`);
+ });
- mock.onPut(integrationSettingsForm.testEndPoint).networkError();
+ it('should show error message if ajax request failed', async () => {
+ mockAxios.onPut(integrationSettingsForm.testEndPoint).networkError();
- integrationSettingsForm.vue.$store = { dispatch: dispatchSpy };
+ eventHub.$emit(TEST_INTEGRATION_EVENT);
+ await waitForPromises();
- await integrationSettingsForm.testSettings(formData);
+ expect(toast).toHaveBeenCalledWith(I18N_DEFAULT_ERROR_MESSAGE);
+ });
- expect(dispatchSpy).toHaveBeenCalledWith('setIsTesting', false);
- });
- });
+ it('should always dispatch `setIsTesting` with `false` once request is completed', async () => {
+ const dispatchSpy = mockStoreDispatch();
+ mockAxios.onPut(integrationSettingsForm.testEndPoint).networkError();
- describe('getJiraIssueTypes', () => {
- let integrationSettingsForm;
- let formData;
- let mock;
+ eventHub.$emit(TEST_INTEGRATION_EVENT);
+ await waitForPromises();
- beforeEach(() => {
- mock = new MockAdaptor(axios);
+ expect(dispatchSpy).toHaveBeenCalledWith('setIsTesting', false);
+ });
+ });
- jest.spyOn(axios, 'put');
+ describe('when form is invalid', () => {
+ beforeEach(() => {
+ jest.spyOn(integrationSettingsForm.$form, 'checkValidity').mockReturnValue(false);
+ jest.spyOn(integrationSettingsForm, 'testSettings');
+ });
- integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- integrationSettingsForm.init();
+ it('should dispatch `setIsTesting` with `false` and not call `testSettings`', async () => {
+ const dispatchSpy = mockStoreDispatch();
- formData = new FormData(integrationSettingsForm.$form);
- });
+ eventHub.$emit(TEST_INTEGRATION_EVENT);
+ await waitForPromises();
- afterEach(() => {
- mock.restore();
+ expect(dispatchSpy).toHaveBeenCalledWith('setIsTesting', false);
+ expect(integrationSettingsForm.testSettings).not.toHaveBeenCalled();
+ });
+ });
});
- it('should always dispatch `requestJiraIssueTypes`', async () => {
- const dispatchSpy = jest.fn();
-
- mock.onPut(integrationSettingsForm.testEndPoint).networkError();
+ describe('when event hub receives `GET_JIRA_ISSUE_TYPES_EVENT`', () => {
+ it('should always dispatch `requestJiraIssueTypes`', () => {
+ const dispatchSpy = mockStoreDispatch();
+ mockAxios.onPut(integrationSettingsForm.testEndPoint).networkError();
- integrationSettingsForm.vue.$store = { dispatch: dispatchSpy };
+ eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT);
- await integrationSettingsForm.getJiraIssueTypes();
+ expect(dispatchSpy).toHaveBeenCalledWith('requestJiraIssueTypes');
+ });
- expect(dispatchSpy).toHaveBeenCalledWith('requestJiraIssueTypes');
- });
+ it('should make an ajax request with provided `formData`', () => {
+ eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT);
- it('should make an ajax request with provided `formData`', async () => {
- await integrationSettingsForm.getJiraIssueTypes(formData);
+ expect(axios.put).toHaveBeenCalledWith(
+ integrationSettingsForm.testEndPoint,
+ new FormData(integrationSettingsForm.$form),
+ );
+ });
- expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData);
- });
+ it('should dispatch `receiveJiraIssueTypesSuccess` with the correct payload if ajax request is successful', async () => {
+ const dispatchSpy = mockStoreDispatch();
+ const mockData = ['ISSUE', 'EPIC'];
+ mockAxios.onPut(integrationSettingsForm.testEndPoint).reply(200, {
+ error: false,
+ issuetypes: mockData,
+ });
- it('should dispatch `receiveJiraIssueTypesSuccess` with the correct payload if ajax request is successful', async () => {
- const mockData = ['ISSUE', 'EPIC'];
- const dispatchSpy = jest.fn();
+ eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT);
+ await waitForPromises();
- mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: false,
- issuetypes: mockData,
+ expect(dispatchSpy).toHaveBeenCalledWith('receiveJiraIssueTypesSuccess', mockData);
});
- integrationSettingsForm.vue.$store = { dispatch: dispatchSpy };
-
- await integrationSettingsForm.getJiraIssueTypes(formData);
+ it.each(['Custom error message here', undefined])(
+ 'should dispatch "receiveJiraIssueTypesError" with a message if the backend responds with error',
+ async (responseErrorMessage) => {
+ const dispatchSpy = mockStoreDispatch();
+
+ const expectedErrorMessage =
+ responseErrorMessage || I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE;
+ mockAxios.onPut(integrationSettingsForm.testEndPoint).reply(200, {
+ error: true,
+ message: responseErrorMessage,
+ });
+
+ eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT);
+ await waitForPromises();
+
+ expect(dispatchSpy).toHaveBeenCalledWith(
+ 'receiveJiraIssueTypesError',
+ expectedErrorMessage,
+ );
+ },
+ );
+ });
+
+ describe('when event hub receives `SAVE_INTEGRATION_EVENT`', () => {
+ describe('when form is valid', () => {
+ beforeEach(() => {
+ jest.spyOn(integrationSettingsForm.$form, 'checkValidity').mockReturnValue(true);
+ jest.spyOn(integrationSettingsForm.$form, 'submit');
+ });
- expect(dispatchSpy).toHaveBeenCalledWith('receiveJiraIssueTypesSuccess', mockData);
- });
+ it('should submit the form', async () => {
+ eventHub.$emit(SAVE_INTEGRATION_EVENT);
+ await waitForPromises();
- it.each(['something went wrong', undefined])(
- 'should dispatch "receiveJiraIssueTypesError" with a message if the backend responds with error',
- async (responseErrorMessage) => {
- const defaultErrorMessage = 'Connection failed. Please check your settings.';
- const expectedErrorMessage = responseErrorMessage || defaultErrorMessage;
- const dispatchSpy = jest.fn();
+ expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
+ expect(integrationSettingsForm.$form.submit).toHaveBeenCalledTimes(1);
+ });
+ });
- mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: true,
- message: responseErrorMessage,
+ describe('when form is invalid', () => {
+ beforeEach(() => {
+ jest.spyOn(integrationSettingsForm.$form, 'checkValidity').mockReturnValue(false);
+ jest.spyOn(integrationSettingsForm.$form, 'submit');
});
- integrationSettingsForm.vue.$store = { dispatch: dispatchSpy };
+ it('should dispatch `setIsSaving` with `false` and not submit form', async () => {
+ const dispatchSpy = mockStoreDispatch();
- await integrationSettingsForm.getJiraIssueTypes(formData);
+ eventHub.$emit(SAVE_INTEGRATION_EVENT);
- expect(dispatchSpy).toHaveBeenCalledWith(
- 'receiveJiraIssueTypesError',
- expectedErrorMessage,
- );
- },
- );
+ await waitForPromises();
+
+ expect(dispatchSpy).toHaveBeenCalledWith('setIsSaving', false);
+ expect(integrationSettingsForm.$form.submit).not.toHaveBeenCalled();
+ });
+ });
+ });
});
});
diff --git a/spec/frontend/invite_members/components/confetti_spec.js b/spec/frontend/invite_members/components/confetti_spec.js
new file mode 100644
index 00000000000..2f361f1dc1e
--- /dev/null
+++ b/spec/frontend/invite_members/components/confetti_spec.js
@@ -0,0 +1,28 @@
+import { shallowMount } from '@vue/test-utils';
+import confetti from 'canvas-confetti';
+import Confetti from '~/invite_members/components/confetti.vue';
+
+jest.mock('canvas-confetti', () => ({
+ create: jest.fn(),
+}));
+
+let wrapper;
+
+const createComponent = () => {
+ wrapper = shallowMount(Confetti);
+};
+
+afterEach(() => {
+ wrapper.destroy();
+});
+
+describe('Confetti', () => {
+ it('initiates confetti', () => {
+ const basicCannon = jest.spyOn(Confetti.methods, 'basicCannon').mockImplementation(() => {});
+
+ createComponent();
+
+ expect(confetti.create).toHaveBeenCalled();
+ expect(basicCannon).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js
index 8c3c549a5eb..5be79004640 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -15,17 +15,34 @@ import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
import ExperimentTracking from '~/experimentation/experiment_tracking';
import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue';
+import ModalConfetti from '~/invite_members/components/confetti.vue';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
-import { INVITE_MEMBERS_IN_COMMENT, MEMBER_AREAS_OF_FOCUS } from '~/invite_members/constants';
+import {
+ INVITE_MEMBERS_IN_COMMENT,
+ MEMBER_AREAS_OF_FOCUS,
+ INVITE_MEMBERS_FOR_TASK,
+ CANCEL_BUTTON_TEXT,
+ INVITE_BUTTON_TEXT,
+ MEMBERS_MODAL_CELEBRATE_INTRO,
+ MEMBERS_MODAL_CELEBRATE_TITLE,
+ MEMBERS_MODAL_DEFAULT_TITLE,
+ MEMBERS_PLACEHOLDER,
+ MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT,
+} from '~/invite_members/constants';
import eventHub from '~/invite_members/event_hub';
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
+import { getParameterValues } from '~/lib/utils/url_utility';
import { apiPaths, membersApiResponse, invitationsApiResponse } from '../mock_data/api_responses';
let wrapper;
let mock;
jest.mock('~/experimentation/experiment_tracking');
+jest.mock('~/lib/utils/url_utility', () => ({
+ ...jest.requireActual('~/lib/utils/url_utility'),
+ getParameterValues: jest.fn(() => []),
+}));
const id = '1';
const name = 'test name';
@@ -40,6 +57,15 @@ const areasOfFocusOptions = [
{ text: 'area1', value: 'area1' },
{ text: 'area2', value: 'area2' },
];
+const tasksToBeDoneOptions = [
+ { text: 'First task', value: 'first' },
+ { text: 'Second task', value: 'second' },
+];
+const newProjectPath = 'projects/new';
+const projects = [
+ { text: 'First project', value: '1' },
+ { text: 'Second project', value: '2' },
+];
const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' };
const user2 = { id: 2, name: 'Name Two', username: 'one_2', avatar_url: '' };
@@ -56,9 +82,13 @@ const user4 = {
avatar_url: '',
};
const sharedGroup = { id: '981' };
+const GlEmoji = { template: '<img/>' };
const createComponent = (data = {}, props = {}) => {
wrapper = shallowMountExtended(InviteMembersModal, {
+ provide: {
+ newProjectPath,
+ },
propsData: {
id,
name,
@@ -68,6 +98,8 @@ const createComponent = (data = {}, props = {}) => {
areasOfFocusOptions,
defaultAccessLevel,
noSelectionAreasOfFocus,
+ tasksToBeDoneOptions,
+ projects,
helpLink,
...props,
},
@@ -81,6 +113,7 @@ const createComponent = (data = {}, props = {}) => {
}),
GlDropdown: true,
GlDropdownItem: true,
+ GlEmoji,
GlSprintf,
GlFormGroup: stubComponent(GlFormGroup, {
props: ['state', 'invalidFeedback', 'description'],
@@ -131,6 +164,11 @@ describe('InviteMembersModal', () => {
const membersFormGroupDescription = () => findMembersFormGroup().props('description');
const findMembersSelect = () => wrapper.findComponent(MembersTokenSelect);
const findAreaofFocusCheckBoxGroup = () => wrapper.findComponent(GlFormCheckboxGroup);
+ const findTasksToBeDone = () => wrapper.findByTestId('invite-members-modal-tasks-to-be-done');
+ const findTasks = () => wrapper.findByTestId('invite-members-modal-tasks');
+ const findProjectSelect = () => wrapper.findByTestId('invite-members-modal-project-select');
+ const findNoProjectsAlert = () => wrapper.findByTestId('invite-members-modal-no-projects-alert');
+ const findCelebrationEmoji = () => wrapper.findComponent(GlModal).find(GlEmoji);
describe('rendering the modal', () => {
beforeEach(() => {
@@ -138,15 +176,15 @@ describe('InviteMembersModal', () => {
});
it('renders the modal with the correct title', () => {
- expect(wrapper.findComponent(GlModal).props('title')).toBe('Invite members');
+ expect(wrapper.findComponent(GlModal).props('title')).toBe(MEMBERS_MODAL_DEFAULT_TITLE);
});
it('renders the Cancel button text correctly', () => {
- expect(findCancelButton().text()).toBe('Cancel');
+ expect(findCancelButton().text()).toBe(CANCEL_BUTTON_TEXT);
});
it('renders the Invite button text correctly', () => {
- expect(findInviteButton().text()).toBe('Invite');
+ expect(findInviteButton().text()).toBe(INVITE_BUTTON_TEXT);
});
it('renders the Invite button modal without isLoading', () => {
@@ -171,7 +209,7 @@ describe('InviteMembersModal', () => {
describe('rendering the access expiration date field', () => {
it('renders the datepicker', () => {
- expect(findDatepicker()).toExist();
+ expect(findDatepicker().exists()).toBe(true);
});
});
});
@@ -191,14 +229,164 @@ describe('InviteMembersModal', () => {
});
});
+ describe('rendering the tasks to be done', () => {
+ const setupComponent = (
+ extraData = {},
+ props = {},
+ urlParameter = ['invite_members_for_task'],
+ ) => {
+ const data = {
+ selectedAccessLevel: 30,
+ selectedTasksToBeDone: ['ci', 'code'],
+ ...extraData,
+ };
+ getParameterValues.mockImplementation(() => urlParameter);
+ createComponent(data, props);
+ };
+
+ afterAll(() => {
+ getParameterValues.mockImplementation(() => []);
+ });
+
+ it('renders the tasks to be done', () => {
+ setupComponent();
+
+ expect(findTasksToBeDone().exists()).toBe(true);
+ });
+
+ describe('when the selected access level is lower than 30', () => {
+ it('does not render the tasks to be done', () => {
+ setupComponent({ selectedAccessLevel: 20 });
+
+ expect(findTasksToBeDone().exists()).toBe(false);
+ });
+ });
+
+ describe('when the url does not contain the parameter `open_modal=invite_members_for_task`', () => {
+ it('does not render the tasks to be done', () => {
+ setupComponent({}, {}, []);
+
+ expect(findTasksToBeDone().exists()).toBe(false);
+ });
+ });
+
+ describe('rendering the tasks', () => {
+ it('renders the tasks', () => {
+ setupComponent();
+
+ expect(findTasks().exists()).toBe(true);
+ });
+
+ it('does not render an alert', () => {
+ setupComponent();
+
+ expect(findNoProjectsAlert().exists()).toBe(false);
+ });
+
+ describe('when there are no projects passed in the data', () => {
+ it('does not render the tasks', () => {
+ setupComponent({}, { projects: [] });
+
+ expect(findTasks().exists()).toBe(false);
+ });
+
+ it('renders an alert with a link to the new projects path', () => {
+ setupComponent({}, { projects: [] });
+
+ expect(findNoProjectsAlert().exists()).toBe(true);
+ expect(findNoProjectsAlert().findComponent(GlLink).attributes('href')).toBe(
+ newProjectPath,
+ );
+ });
+ });
+ });
+
+ describe('rendering the project dropdown', () => {
+ it('renders the project select', () => {
+ setupComponent();
+
+ expect(findProjectSelect().exists()).toBe(true);
+ });
+
+ describe('when the modal is shown for a project', () => {
+ it('does not render the project select', () => {
+ setupComponent({}, { isProject: true });
+
+ expect(findProjectSelect().exists()).toBe(false);
+ });
+ });
+
+ describe('when no tasks are selected', () => {
+ it('does not render the project select', () => {
+ setupComponent({ selectedTasksToBeDone: [] });
+
+ expect(findProjectSelect().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('tracking events', () => {
+ it('tracks the view for invite_members_for_task', () => {
+ setupComponent();
+
+ expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name);
+ expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(
+ INVITE_MEMBERS_FOR_TASK.view,
+ );
+ });
+
+ it('tracks the submit for invite_members_for_task', () => {
+ setupComponent();
+ clickInviteButton();
+
+ expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name, {
+ label: 'selected_tasks_to_be_done',
+ property: 'ci,code',
+ });
+ expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(
+ INVITE_MEMBERS_FOR_TASK.submit,
+ );
+ });
+ });
+ });
+
describe('displaying the correct introText and form group description', () => {
describe('when inviting to a project', () => {
describe('when inviting members', () => {
- it('includes the correct invitee, type, and formatted name', () => {
+ beforeEach(() => {
createInviteMembersToProjectWrapper();
+ });
+ it('renders the modal without confetti', () => {
+ expect(wrapper.findComponent(ModalConfetti).exists()).toBe(false);
+ });
+
+ it('includes the correct invitee, type, and formatted name', () => {
expect(findIntroText()).toBe("You're inviting members to the test name project.");
- expect(membersFormGroupDescription()).toBe('Select members or type email addresses');
+ expect(findCelebrationEmoji().exists()).toBe(false);
+ expect(membersFormGroupDescription()).toBe(MEMBERS_PLACEHOLDER);
+ });
+ });
+
+ describe('when inviting members with celebration', () => {
+ beforeEach(() => {
+ createComponent({ mode: 'celebrate', inviteeType: 'members' }, { isProject: true });
+ });
+
+ it('renders the modal with confetti', () => {
+ expect(wrapper.findComponent(ModalConfetti).exists()).toBe(true);
+ });
+
+ it('renders the modal with the correct title', () => {
+ expect(wrapper.findComponent(GlModal).props('title')).toBe(MEMBERS_MODAL_CELEBRATE_TITLE);
+ });
+
+ it('includes the correct celebration text and emoji', () => {
+ expect(findIntroText()).toBe(
+ `${MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT} ${MEMBERS_MODAL_CELEBRATE_INTRO}`,
+ );
+ expect(findCelebrationEmoji().exists()).toBe(true);
+ expect(membersFormGroupDescription()).toBe(MEMBERS_PLACEHOLDER);
});
});
@@ -218,7 +406,7 @@ describe('InviteMembersModal', () => {
createInviteMembersToGroupWrapper();
expect(findIntroText()).toBe("You're inviting members to the test name group.");
- expect(membersFormGroupDescription()).toBe('Select members or type email addresses');
+ expect(membersFormGroupDescription()).toBe(MEMBERS_PLACEHOLDER);
});
});
@@ -267,6 +455,8 @@ describe('InviteMembersModal', () => {
invite_source: inviteSource,
format: 'json',
areas_of_focus: noSelectionAreasOfFocus,
+ tasks_to_be_done: [],
+ tasks_project_id: '',
};
describe('when member is added successfully', () => {
@@ -448,6 +638,8 @@ describe('InviteMembersModal', () => {
email: 'email@example.com',
invite_source: inviteSource,
areas_of_focus: noSelectionAreasOfFocus,
+ tasks_to_be_done: [],
+ tasks_project_id: '',
format: 'json',
};
@@ -576,6 +768,8 @@ describe('InviteMembersModal', () => {
invite_source: inviteSource,
areas_of_focus: noSelectionAreasOfFocus,
format: 'json',
+ tasks_to_be_done: [],
+ tasks_project_id: '',
};
const emailPostData = { ...postData, email: 'email@example.com' };
diff --git a/spec/frontend/invite_members/components/invite_members_trigger_spec.js b/spec/frontend/invite_members/components/invite_members_trigger_spec.js
index b2ebb9e4a47..3fce23f854c 100644
--- a/spec/frontend/invite_members/components/invite_members_trigger_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_trigger_spec.js
@@ -1,8 +1,9 @@
-import { GlButton, GlLink } from '@gitlab/ui';
+import { GlButton, GlLink, GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import ExperimentTracking from '~/experimentation/experiment_tracking';
import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
import eventHub from '~/invite_members/event_hub';
+import { TRIGGER_ELEMENT_BUTTON, TRIGGER_ELEMENT_SIDE_NAV } from '~/invite_members/constants';
jest.mock('~/experimentation/experiment_tracking');
@@ -15,6 +16,7 @@ let findButton;
const triggerComponent = {
button: GlButton,
anchor: GlLink,
+ 'side-nav': GlLink,
};
const createComponent = (props = {}) => {
@@ -27,9 +29,23 @@ const createComponent = (props = {}) => {
});
};
-describe.each(['button', 'anchor'])('with triggerElement as %s', (triggerElement) => {
- triggerProps = { triggerElement, triggerSource };
- findButton = () => wrapper.findComponent(triggerComponent[triggerElement]);
+const triggerItems = [
+ {
+ triggerElement: TRIGGER_ELEMENT_BUTTON,
+ },
+ {
+ triggerElement: 'anchor',
+ },
+ {
+ triggerElement: TRIGGER_ELEMENT_SIDE_NAV,
+ icon: 'plus',
+ },
+];
+
+describe.each(triggerItems)('with triggerElement as %s', (triggerItem) => {
+ triggerProps = { ...triggerItem, triggerSource };
+
+ findButton = () => wrapper.findComponent(triggerComponent[triggerItem.triggerElement]);
afterEach(() => {
wrapper.destroy();
@@ -91,3 +107,14 @@ describe.each(['button', 'anchor'])('with triggerElement as %s', (triggerElement
});
});
});
+
+describe('side-nav with icon', () => {
+ it('includes the specified icon with correct size when triggerElement is link', () => {
+ const findIcon = () => wrapper.findComponent(GlIcon);
+
+ createComponent({ triggerElement: TRIGGER_ELEMENT_SIDE_NAV, icon: 'plus' });
+
+ expect(findIcon().exists()).toBe(true);
+ expect(findIcon().props('name')).toBe('plus');
+ });
+});
diff --git a/spec/frontend/issuable/components/csv_import_modal_spec.js b/spec/frontend/issuable/components/csv_import_modal_spec.js
index 307323ef07a..f4636fd7e6a 100644
--- a/spec/frontend/issuable/components/csv_import_modal_spec.js
+++ b/spec/frontend/issuable/components/csv_import_modal_spec.js
@@ -1,7 +1,8 @@
-import { GlButton, GlModal } from '@gitlab/ui';
+import { GlModal } from '@gitlab/ui';
import { stubComponent } from 'helpers/stub_component';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import CsvImportModal from '~/issuable/components/csv_import_modal.vue';
+import { __ } from '~/locale';
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
@@ -36,7 +37,6 @@ describe('CsvImportModal', () => {
});
const findModal = () => wrapper.findComponent(GlModal);
- const findPrimaryButton = () => wrapper.findComponent(GlButton);
const findForm = () => wrapper.find('form');
const findFileInput = () => wrapper.findByLabelText('Upload CSV file');
const findAuthenticityToken = () => new FormData(findForm().element).get('authenticity_token');
@@ -64,11 +64,11 @@ describe('CsvImportModal', () => {
expect(findForm().exists()).toBe(true);
expect(findForm().attributes('action')).toBe(importCsvIssuesPath);
expect(findAuthenticityToken()).toBe('mock-csrf-token');
- expect(findFileInput()).toExist();
+ expect(findFileInput().exists()).toBe(true);
});
it('displays the correct primary button action text', () => {
- expect(findPrimaryButton()).toExist();
+ expect(findModal().props('actionPrimary')).toEqual({ text: __('Import issues') });
});
it('submits the form when the primary action is clicked', () => {
diff --git a/spec/frontend/issue_show/components/app_spec.js b/spec/frontend/issue_show/components/app_spec.js
index bd05cb1ac5a..e32215b4aa6 100644
--- a/spec/frontend/issue_show/components/app_spec.js
+++ b/spec/frontend/issue_show/components/app_spec.js
@@ -8,7 +8,7 @@ import IssuableApp from '~/issue_show/components/app.vue';
import DescriptionComponent from '~/issue_show/components/description.vue';
import IncidentTabs from '~/issue_show/components/incidents/incident_tabs.vue';
import PinnedLinks from '~/issue_show/components/pinned_links.vue';
-import { IssuableStatus, IssuableStatusText } from '~/issue_show/constants';
+import { IssuableStatus, IssuableStatusText, POLLING_DELAY } from '~/issue_show/constants';
import eventHub from '~/issue_show/event_hub';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
@@ -643,4 +643,40 @@ describe('Issuable output', () => {
});
});
});
+
+ describe('taskListUpdateStarted', () => {
+ it('stops polling', () => {
+ jest.spyOn(wrapper.vm.poll, 'stop');
+
+ wrapper.vm.taskListUpdateStarted();
+
+ expect(wrapper.vm.poll.stop).toHaveBeenCalled();
+ });
+ });
+
+ describe('taskListUpdateSucceeded', () => {
+ it('enables polling', () => {
+ jest.spyOn(wrapper.vm.poll, 'enable');
+ jest.spyOn(wrapper.vm.poll, 'makeDelayedRequest');
+
+ wrapper.vm.taskListUpdateSucceeded();
+
+ expect(wrapper.vm.poll.enable).toHaveBeenCalled();
+ expect(wrapper.vm.poll.makeDelayedRequest).toHaveBeenCalledWith(POLLING_DELAY);
+ });
+ });
+
+ describe('taskListUpdateFailed', () => {
+ it('enables polling and calls updateStoreState', () => {
+ jest.spyOn(wrapper.vm.poll, 'enable');
+ jest.spyOn(wrapper.vm.poll, 'makeDelayedRequest');
+ jest.spyOn(wrapper.vm, 'updateStoreState');
+
+ wrapper.vm.taskListUpdateFailed();
+
+ expect(wrapper.vm.poll.enable).toHaveBeenCalled();
+ expect(wrapper.vm.poll.makeDelayedRequest).toHaveBeenCalledWith(POLLING_DELAY);
+ expect(wrapper.vm.updateStoreState).toHaveBeenCalled();
+ });
+ });
});
diff --git a/spec/frontend/issue_show/components/description_spec.js b/spec/frontend/issue_show/components/description_spec.js
index cdf06ecc31f..bdcc82cab81 100644
--- a/spec/frontend/issue_show/components/description_spec.js
+++ b/spec/frontend/issue_show/components/description_spec.js
@@ -114,6 +114,8 @@ describe('Description component', () => {
dataType: 'issuableType',
fieldName: 'description',
selector: '.detail-page-description',
+ onUpdate: expect.any(Function),
+ onSuccess: expect.any(Function),
onError: expect.any(Function),
lockVersion: 0,
});
@@ -150,6 +152,26 @@ describe('Description component', () => {
});
});
+ describe('taskListUpdateStarted', () => {
+ it('emits event to parent', () => {
+ const spy = jest.spyOn(vm, '$emit');
+
+ vm.taskListUpdateStarted();
+
+ expect(spy).toHaveBeenCalledWith('taskListUpdateStarted');
+ });
+ });
+
+ describe('taskListUpdateSuccess', () => {
+ it('emits event to parent', () => {
+ const spy = jest.spyOn(vm, '$emit');
+
+ vm.taskListUpdateSuccess();
+
+ expect(spy).toHaveBeenCalledWith('taskListUpdateSucceeded');
+ });
+ });
+
describe('taskListUpdateError', () => {
it('should create flash notification and emit an event to parent', () => {
const msg =
diff --git a/spec/frontend/issue_show/components/fields/type_spec.js b/spec/frontend/issue_show/components/fields/type_spec.js
index fac745716d7..95ae6f37877 100644
--- a/spec/frontend/issue_show/components/fields/type_spec.js
+++ b/spec/frontend/issue_show/components/fields/type_spec.js
@@ -39,7 +39,7 @@ describe('Issue type field component', () => {
const findTypeFromDropDownItemIconAt = (at) =>
findTypeFromDropDownItems().at(at).findComponent(GlIcon);
- const createComponent = ({ data } = {}) => {
+ const createComponent = ({ data } = {}, provide) => {
fakeApollo = createMockApollo([], mockResolvers);
wrapper = shallowMount(IssueTypeField, {
@@ -51,6 +51,10 @@ describe('Issue type field component', () => {
...data,
};
},
+ provide: {
+ canCreateIncident: true,
+ ...provide,
+ },
});
};
@@ -92,5 +96,25 @@ describe('Issue type field component', () => {
await wrapper.vm.$nextTick();
expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.incident);
});
+
+ describe('when user is a guest', () => {
+ it('hides the incident type from the dropdown', async () => {
+ createComponent({}, { canCreateIncident: false, issueType: 'issue' });
+ await waitForPromises();
+
+ expect(findTypeFromDropDownItemAt(0).isVisible()).toBe(true);
+ expect(findTypeFromDropDownItemAt(1).isVisible()).toBe(false);
+ expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.issue);
+ });
+
+ it('and incident is selected, includes incident in the dropdown', async () => {
+ createComponent({}, { canCreateIncident: false, issueType: 'incident' });
+ await waitForPromises();
+
+ expect(findTypeFromDropDownItemAt(0).isVisible()).toBe(true);
+ expect(findTypeFromDropDownItemAt(1).isVisible()).toBe(true);
+ expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.incident);
+ });
+ });
});
});
diff --git a/spec/frontend/issues_list/components/issues_list_app_spec.js b/spec/frontend/issues_list/components/issues_list_app_spec.js
index 6b443062f12..3f52c7b4afe 100644
--- a/spec/frontend/issues_list/components/issues_list_app_spec.js
+++ b/spec/frontend/issues_list/components/issues_list_app_spec.js
@@ -37,6 +37,7 @@ import {
TOKEN_TYPE_LABEL,
TOKEN_TYPE_MILESTONE,
TOKEN_TYPE_MY_REACTION,
+ TOKEN_TYPE_RELEASE,
TOKEN_TYPE_TYPE,
TOKEN_TYPE_WEIGHT,
urlSortParams,
@@ -581,6 +582,7 @@ describe('IssuesListApp component', () => {
{ type: TOKEN_TYPE_MILESTONE },
{ type: TOKEN_TYPE_LABEL },
{ type: TOKEN_TYPE_TYPE },
+ { type: TOKEN_TYPE_RELEASE },
{ type: TOKEN_TYPE_MY_REACTION },
{ type: TOKEN_TYPE_CONFIDENTIAL },
{ type: TOKEN_TYPE_ITERATION },
diff --git a/spec/frontend/issues_list/components/new_issue_dropdown_spec.js b/spec/frontend/issues_list/components/new_issue_dropdown_spec.js
index 1fcaa99cf5a..1c9a87e8af2 100644
--- a/spec/frontend/issues_list/components/new_issue_dropdown_spec.js
+++ b/spec/frontend/issues_list/components/new_issue_dropdown_spec.js
@@ -8,7 +8,7 @@ import { DASH_SCOPE, joinPaths } from '~/lib/utils/url_utility';
import {
emptySearchProjectsQueryResponse,
project1,
- project2,
+ project3,
searchProjectsQueryResponse,
} from '../mock_data';
@@ -72,7 +72,7 @@ describe('NewIssueDropdown component', () => {
expect(inputSpy).toHaveBeenCalledTimes(1);
});
- it('renders expected dropdown items', async () => {
+ it('renders projects with issues enabled', async () => {
wrapper = mountComponent({ mountFn: mount });
await showDropdown();
@@ -80,7 +80,7 @@ describe('NewIssueDropdown component', () => {
const listItems = wrapper.findAll('li');
expect(listItems.at(0).text()).toBe(project1.nameWithNamespace);
- expect(listItems.at(1).text()).toBe(project2.nameWithNamespace);
+ expect(listItems.at(1).text()).toBe(project3.nameWithNamespace);
});
it('renders `No matches found` when there are no matches', async () => {
diff --git a/spec/frontend/issues_list/mock_data.js b/spec/frontend/issues_list/mock_data.js
index 3be256d8094..19a8af4d9c2 100644
--- a/spec/frontend/issues_list/mock_data.js
+++ b/spec/frontend/issues_list/mock_data.js
@@ -95,16 +95,29 @@ export const locationSearch = [
'assignee_username[]=lisa',
'not[assignee_username][]=patty',
'not[assignee_username][]=selma',
+ 'milestone_title=season+3',
'milestone_title=season+4',
'not[milestone_title]=season+20',
+ 'not[milestone_title]=season+30',
'label_name[]=cartoon',
'label_name[]=tv',
'not[label_name][]=live action',
'not[label_name][]=drama',
+ 'release_tag=v3',
+ 'release_tag=v4',
+ 'not[release_tag]=v20',
+ 'not[release_tag]=v30',
+ 'type[]=issue',
+ 'type[]=feature',
+ 'not[type][]=bug',
+ 'not[type][]=incident',
'my_reaction_emoji=thumbsup',
- 'confidential=no',
+ 'not[my_reaction_emoji]=thumbsdown',
+ 'confidential=yes',
'iteration_id=4',
+ 'iteration_id=12',
'not[iteration_id]=20',
+ 'not[iteration_id]=42',
'epic_id=12',
'not[epic_id]=34',
'weight=1',
@@ -114,10 +127,10 @@ export const locationSearch = [
export const locationSearchWithSpecialValues = [
'assignee_id=123',
'assignee_username=bart',
- 'type[]=issue',
- 'type[]=incident',
'my_reaction_emoji=None',
'iteration_id=Current',
+ 'label_name[]=None',
+ 'release_tag=None',
'milestone_title=Upcoming',
'epic_id=None',
'weight=None',
@@ -130,16 +143,29 @@ export const filteredTokens = [
{ type: 'assignee_username', value: { data: 'lisa', operator: OPERATOR_IS } },
{ type: 'assignee_username', value: { data: 'patty', operator: OPERATOR_IS_NOT } },
{ type: 'assignee_username', value: { data: 'selma', operator: OPERATOR_IS_NOT } },
+ { type: 'milestone', value: { data: 'season 3', operator: OPERATOR_IS } },
{ type: 'milestone', value: { data: 'season 4', operator: OPERATOR_IS } },
{ type: 'milestone', value: { data: 'season 20', operator: OPERATOR_IS_NOT } },
+ { type: 'milestone', value: { data: 'season 30', operator: OPERATOR_IS_NOT } },
{ type: 'labels', value: { data: 'cartoon', operator: OPERATOR_IS } },
{ type: 'labels', value: { data: 'tv', operator: OPERATOR_IS } },
{ type: 'labels', value: { data: 'live action', operator: OPERATOR_IS_NOT } },
{ type: 'labels', value: { data: 'drama', operator: OPERATOR_IS_NOT } },
+ { type: 'release', value: { data: 'v3', operator: OPERATOR_IS } },
+ { type: 'release', value: { data: 'v4', operator: OPERATOR_IS } },
+ { type: 'release', value: { data: 'v20', operator: OPERATOR_IS_NOT } },
+ { type: 'release', value: { data: 'v30', operator: OPERATOR_IS_NOT } },
+ { type: 'type', value: { data: 'issue', operator: OPERATOR_IS } },
+ { type: 'type', value: { data: 'feature', operator: OPERATOR_IS } },
+ { type: 'type', value: { data: 'bug', operator: OPERATOR_IS_NOT } },
+ { type: 'type', value: { data: 'incident', operator: OPERATOR_IS_NOT } },
{ type: 'my_reaction_emoji', value: { data: 'thumbsup', operator: OPERATOR_IS } },
- { type: 'confidential', value: { data: 'no', operator: OPERATOR_IS } },
+ { type: 'my_reaction_emoji', value: { data: 'thumbsdown', operator: OPERATOR_IS_NOT } },
+ { type: 'confidential', value: { data: 'yes', operator: OPERATOR_IS } },
{ type: 'iteration', value: { data: '4', operator: OPERATOR_IS } },
+ { type: 'iteration', value: { data: '12', operator: OPERATOR_IS } },
{ type: 'iteration', value: { data: '20', operator: OPERATOR_IS_NOT } },
+ { type: 'iteration', value: { data: '42', operator: OPERATOR_IS_NOT } },
{ type: 'epic_id', value: { data: '12', operator: OPERATOR_IS } },
{ type: 'epic_id', value: { data: '34', operator: OPERATOR_IS_NOT } },
{ type: 'weight', value: { data: '1', operator: OPERATOR_IS } },
@@ -151,10 +177,10 @@ export const filteredTokens = [
export const filteredTokensWithSpecialValues = [
{ type: 'assignee_username', value: { data: '123', operator: OPERATOR_IS } },
{ type: 'assignee_username', value: { data: 'bart', operator: OPERATOR_IS } },
- { type: 'type', value: { data: 'issue', operator: OPERATOR_IS } },
- { type: 'type', value: { data: 'incident', operator: OPERATOR_IS } },
{ type: 'my_reaction_emoji', value: { data: 'None', operator: OPERATOR_IS } },
{ type: 'iteration', value: { data: 'Current', operator: OPERATOR_IS } },
+ { type: 'labels', value: { data: 'None', operator: OPERATOR_IS } },
+ { type: 'release', value: { data: 'None', operator: OPERATOR_IS } },
{ type: 'milestone', value: { data: 'Upcoming', operator: OPERATOR_IS } },
{ type: 'epic_id', value: { data: 'None', operator: OPERATOR_IS } },
{ type: 'weight', value: { data: 'None', operator: OPERATOR_IS } },
@@ -163,19 +189,24 @@ export const filteredTokensWithSpecialValues = [
export const apiParams = {
authorUsername: 'homer',
assigneeUsernames: ['bart', 'lisa'],
- milestoneTitle: 'season 4',
+ milestoneTitle: ['season 3', 'season 4'],
labelName: ['cartoon', 'tv'],
+ releaseTag: ['v3', 'v4'],
+ types: ['ISSUE', 'FEATURE'],
myReactionEmoji: 'thumbsup',
- confidential: 'no',
- iterationId: '4',
+ confidential: true,
+ iterationId: ['4', '12'],
epicId: '12',
weight: '1',
not: {
authorUsername: 'marge',
assigneeUsernames: ['patty', 'selma'],
- milestoneTitle: 'season 20',
+ milestoneTitle: ['season 20', 'season 30'],
labelName: ['live action', 'drama'],
- iterationId: '20',
+ releaseTag: ['v20', 'v30'],
+ types: ['BUG', 'INCIDENT'],
+ myReactionEmoji: 'thumbsdown',
+ iterationId: ['20', '42'],
epicId: '34',
weight: '3',
},
@@ -184,8 +215,9 @@ export const apiParams = {
export const apiParamsWithSpecialValues = {
assigneeId: '123',
assigneeUsernames: 'bart',
- types: ['ISSUE', 'INCIDENT'],
+ labelName: 'None',
myReactionEmoji: 'None',
+ releaseTagWildcardId: 'NONE',
iterationWildcardId: 'CURRENT',
milestoneWildcardId: 'UPCOMING',
epicId: 'None',
@@ -197,14 +229,19 @@ export const urlParams = {
'not[author_username]': 'marge',
'assignee_username[]': ['bart', 'lisa'],
'not[assignee_username][]': ['patty', 'selma'],
- milestone_title: 'season 4',
- 'not[milestone_title]': 'season 20',
+ milestone_title: ['season 3', 'season 4'],
+ 'not[milestone_title]': ['season 20', 'season 30'],
'label_name[]': ['cartoon', 'tv'],
'not[label_name][]': ['live action', 'drama'],
+ release_tag: ['v3', 'v4'],
+ 'not[release_tag]': ['v20', 'v30'],
+ 'type[]': ['issue', 'feature'],
+ 'not[type][]': ['bug', 'incident'],
my_reaction_emoji: 'thumbsup',
- confidential: 'no',
- iteration_id: '4',
- 'not[iteration_id]': '20',
+ 'not[my_reaction_emoji]': 'thumbsdown',
+ confidential: 'yes',
+ iteration_id: ['4', '12'],
+ 'not[iteration_id]': ['20', '42'],
epic_id: '12',
'not[epic_id]': '34',
weight: '1',
@@ -214,7 +251,8 @@ export const urlParams = {
export const urlParamsWithSpecialValues = {
assignee_id: '123',
'assignee_username[]': 'bart',
- 'type[]': ['issue', 'incident'],
+ 'label_name[]': 'None',
+ release_tag: 'None',
my_reaction_emoji: 'None',
iteration_id: 'Current',
milestone_title: 'Upcoming',
@@ -224,6 +262,7 @@ export const urlParamsWithSpecialValues = {
export const project1 = {
id: 'gid://gitlab/Group/26',
+ issuesEnabled: true,
name: 'Super Mario Project',
nameWithNamespace: 'Mushroom Kingdom / Super Mario Project',
webUrl: 'https://127.0.0.1:3000/mushroom-kingdom/super-mario-project',
@@ -231,16 +270,25 @@ export const project1 = {
export const project2 = {
id: 'gid://gitlab/Group/59',
+ issuesEnabled: false,
name: 'Mario Kart Project',
nameWithNamespace: 'Mushroom Kingdom / Mario Kart Project',
webUrl: 'https://127.0.0.1:3000/mushroom-kingdom/mario-kart-project',
};
+export const project3 = {
+ id: 'gid://gitlab/Group/103',
+ issuesEnabled: true,
+ name: 'Mario Party Project',
+ nameWithNamespace: 'Mushroom Kingdom / Mario Party Project',
+ webUrl: 'https://127.0.0.1:3000/mushroom-kingdom/mario-party-project',
+};
+
export const searchProjectsQueryResponse = {
data: {
group: {
projects: {
- nodes: [project1, project2],
+ nodes: [project1, project2, project3],
},
},
},
diff --git a/spec/frontend/issues_list/utils_spec.js b/spec/frontend/issues_list/utils_spec.js
index 458776d9ec5..8e1d70db92d 100644
--- a/spec/frontend/issues_list/utils_spec.js
+++ b/spec/frontend/issues_list/utils_spec.js
@@ -58,10 +58,10 @@ describe('getDueDateValue', () => {
describe('getSortOptions', () => {
describe.each`
hasIssueWeightsFeature | hasBlockedIssuesFeature | length | containsWeight | containsBlocking
- ${false} | ${false} | ${8} | ${false} | ${false}
- ${true} | ${false} | ${9} | ${true} | ${false}
- ${false} | ${true} | ${9} | ${false} | ${true}
- ${true} | ${true} | ${10} | ${true} | ${true}
+ ${false} | ${false} | ${9} | ${false} | ${false}
+ ${true} | ${false} | ${10} | ${true} | ${false}
+ ${false} | ${true} | ${10} | ${false} | ${true}
+ ${true} | ${true} | ${11} | ${true} | ${true}
`(
'when hasIssueWeightsFeature=$hasIssueWeightsFeature and hasBlockedIssuesFeature=$hasBlockedIssuesFeature',
({
diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js
new file mode 100644
index 00000000000..5ec1b7b7932
--- /dev/null
+++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js
@@ -0,0 +1,44 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import AddNamespaceButton from '~/jira_connect/subscriptions/components/add_namespace_button.vue';
+import AddNamespaceModal from '~/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal.vue';
+import { ADD_NAMESPACE_MODAL_ID } from '~/jira_connect/subscriptions/constants';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+
+describe('AddNamespaceButton', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(AddNamespaceButton, {
+ directives: {
+ glModal: createMockDirective(),
+ },
+ });
+ };
+
+ const findButton = () => wrapper.findComponent(GlButton);
+ const findModal = () => wrapper.findComponent(AddNamespaceModal);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays a button', () => {
+ expect(findButton().exists()).toBe(true);
+ });
+
+ it('contains a modal', () => {
+ expect(findModal().exists()).toBe(true);
+ });
+
+ it('button is bound to the modal', () => {
+ const { value } = getBinding(findButton().element, 'gl-modal');
+
+ expect(value).toBeTruthy();
+ expect(value).toBe(ADD_NAMESPACE_MODAL_ID);
+ });
+});
diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal_spec.js
new file mode 100644
index 00000000000..d80381107f2
--- /dev/null
+++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal_spec.js
@@ -0,0 +1,36 @@
+import { shallowMount } from '@vue/test-utils';
+import AddNamespaceModal from '~/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal.vue';
+import GroupsList from '~/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue';
+import { ADD_NAMESPACE_MODAL_ID } from '~/jira_connect/subscriptions/constants';
+
+describe('AddNamespaceModal', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(AddNamespaceModal);
+ };
+
+ const findModal = () => wrapper.findComponent(AddNamespaceModal);
+ const findGroupsList = () => wrapper.findComponent(GroupsList);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays modal with correct props', () => {
+ const modal = findModal();
+ expect(modal.exists()).toBe(true);
+ expect(modal.attributes()).toMatchObject({
+ modalid: ADD_NAMESPACE_MODAL_ID,
+ title: AddNamespaceModal.modal.title,
+ });
+ });
+
+ it('displays GroupList', () => {
+ expect(findGroupsList().exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js
new file mode 100644
index 00000000000..15e9a740c83
--- /dev/null
+++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js
@@ -0,0 +1,112 @@
+import { GlButton } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+import waitForPromises from 'helpers/wait_for_promises';
+
+import * as JiraConnectApi from '~/jira_connect/subscriptions/api';
+import GroupItemName from '~/jira_connect/subscriptions/components/group_item_name.vue';
+import GroupsListItem from '~/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue';
+import { persistAlert, reloadPage } from '~/jira_connect/subscriptions/utils';
+import { mockGroup1 } from '../../mock_data';
+
+jest.mock('~/jira_connect/subscriptions/utils');
+
+describe('GroupsListItem', () => {
+ let wrapper;
+ const mockSubscriptionPath = 'subscriptionPath';
+
+ const createComponent = ({ mountFn = shallowMount } = {}) => {
+ wrapper = mountFn(GroupsListItem, {
+ propsData: {
+ group: mockGroup1,
+ },
+ provide: {
+ subscriptionsPath: mockSubscriptionPath,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findGroupItemName = () => wrapper.findComponent(GroupItemName);
+ const findLinkButton = () => wrapper.findComponent(GlButton);
+ const clickLinkButton = () => findLinkButton().trigger('click');
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders GroupItemName', () => {
+ expect(findGroupItemName().exists()).toBe(true);
+ expect(findGroupItemName().props('group')).toBe(mockGroup1);
+ });
+
+ it('renders Link button', () => {
+ expect(findLinkButton().exists()).toBe(true);
+ expect(findLinkButton().text()).toBe('Link');
+ });
+ });
+
+ describe('on Link button click', () => {
+ let addSubscriptionSpy;
+
+ beforeEach(() => {
+ createComponent({ mountFn: mount });
+
+ addSubscriptionSpy = jest.spyOn(JiraConnectApi, 'addSubscription').mockResolvedValue();
+ });
+
+ it('sets button to loading and sends request', async () => {
+ expect(findLinkButton().props('loading')).toBe(false);
+
+ clickLinkButton();
+
+ await wrapper.vm.$nextTick();
+
+ expect(findLinkButton().props('loading')).toBe(true);
+
+ await waitForPromises();
+
+ expect(addSubscriptionSpy).toHaveBeenCalledWith(mockSubscriptionPath, mockGroup1.full_path);
+ expect(persistAlert).toHaveBeenCalledWith({
+ linkUrl: '/help/integration/jira_development_panel.html#usage',
+ message:
+ 'You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}',
+ title: 'Namespace successfully linked',
+ variant: 'success',
+ });
+ });
+
+ describe('when request is successful', () => {
+ it('reloads the page', async () => {
+ clickLinkButton();
+
+ await waitForPromises();
+
+ expect(reloadPage).toHaveBeenCalled();
+ });
+ });
+
+ describe('when request has errors', () => {
+ const mockErrorMessage = 'error message';
+ const mockError = { response: { data: { error: mockErrorMessage } } };
+
+ beforeEach(() => {
+ addSubscriptionSpy = jest
+ .spyOn(JiraConnectApi, 'addSubscription')
+ .mockRejectedValue(mockError);
+ });
+
+ it('emits `error` event', async () => {
+ clickLinkButton();
+
+ await waitForPromises();
+
+ expect(reloadPage).not.toHaveBeenCalled();
+ expect(wrapper.emitted('error')[0][0]).toBe(mockErrorMessage);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js
new file mode 100644
index 00000000000..04aba8bda23
--- /dev/null
+++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js
@@ -0,0 +1,303 @@
+import { GlAlert, GlLoadingIcon, GlSearchBoxByType, GlPagination } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { fetchGroups } from '~/jira_connect/subscriptions/api';
+import GroupsList from '~/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue';
+import GroupsListItem from '~/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue';
+import { DEFAULT_GROUPS_PER_PAGE } from '~/jira_connect/subscriptions/constants';
+import { mockGroup1, mockGroup2 } from '../../mock_data';
+
+const createMockGroup = (groupId) => {
+ return {
+ ...mockGroup1,
+ id: groupId,
+ };
+};
+
+const createMockGroups = (count) => {
+ return [...new Array(count)].map((_, idx) => createMockGroup(idx));
+};
+
+jest.mock('~/jira_connect/subscriptions/api', () => {
+ return {
+ fetchGroups: jest.fn(),
+ };
+});
+
+const mockGroupsPath = '/groups';
+
+describe('GroupsList', () => {
+ let wrapper;
+
+ const mockEmptyResponse = { data: [] };
+
+ const createComponent = (options = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(GroupsList, {
+ provide: {
+ groupsPath: mockGroupsPath,
+ },
+ ...options,
+ }),
+ );
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findGlAlert = () => wrapper.findComponent(GlAlert);
+ const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findAllItems = () => wrapper.findAll(GroupsListItem);
+ const findFirstItem = () => findAllItems().at(0);
+ const findSecondItem = () => findAllItems().at(1);
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
+ const findGroupsList = () => wrapper.findByTestId('groups-list');
+ const findPagination = () => wrapper.findComponent(GlPagination);
+
+ describe('when groups are loading', () => {
+ it('renders loading icon', async () => {
+ fetchGroups.mockReturnValue(new Promise(() => {}));
+ createComponent();
+
+ await wrapper.vm.$nextTick();
+
+ expect(findGlLoadingIcon().exists()).toBe(true);
+ });
+ });
+
+ describe('when groups fetch fails', () => {
+ it('renders error message', async () => {
+ fetchGroups.mockRejectedValue();
+ createComponent();
+
+ await waitForPromises();
+
+ expect(findGlLoadingIcon().exists()).toBe(false);
+ expect(findGlAlert().exists()).toBe(true);
+ expect(findGlAlert().text()).toBe('Failed to load namespaces. Please try again.');
+ });
+ });
+
+ describe('with no groups returned', () => {
+ it('renders empty state', async () => {
+ fetchGroups.mockResolvedValue(mockEmptyResponse);
+ createComponent();
+
+ await waitForPromises();
+
+ expect(findGlLoadingIcon().exists()).toBe(false);
+ expect(wrapper.text()).toContain('No available namespaces');
+ });
+ });
+
+ describe('with groups returned', () => {
+ beforeEach(async () => {
+ fetchGroups.mockResolvedValue({
+ headers: { 'X-PAGE': 1, 'X-TOTAL': 2 },
+ data: [mockGroup1, mockGroup2],
+ });
+ createComponent();
+
+ await waitForPromises();
+ });
+
+ it('renders groups list', () => {
+ expect(findAllItems()).toHaveLength(2);
+ expect(findFirstItem().props('group')).toBe(mockGroup1);
+ expect(findSecondItem().props('group')).toBe(mockGroup2);
+ });
+
+ it('sets GroupListItem `disabled` prop to `false`', () => {
+ findAllItems().wrappers.forEach((groupListItem) => {
+ expect(groupListItem.props('disabled')).toBe(false);
+ });
+ });
+
+ it('does not set opacity of the groups list', () => {
+ expect(findGroupsList().classes()).not.toContain('gl-opacity-5');
+ });
+
+ it('shows error message on $emit from item', async () => {
+ const errorMessage = 'error message';
+
+ findFirstItem().vm.$emit('error', errorMessage);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findGlAlert().exists()).toBe(true);
+ expect(findGlAlert().text()).toContain(errorMessage);
+ });
+
+ describe('when searching groups', () => {
+ const mockSearchTeam = 'mock search term';
+
+ describe('while groups are loading', () => {
+ beforeEach(async () => {
+ fetchGroups.mockClear();
+ fetchGroups.mockReturnValue(new Promise(() => {}));
+
+ findSearchBox().vm.$emit('input', mockSearchTeam);
+ await wrapper.vm.$nextTick();
+ });
+
+ it('calls `fetchGroups` with search term', () => {
+ expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
+ page: 1,
+ perPage: DEFAULT_GROUPS_PER_PAGE,
+ search: mockSearchTeam,
+ });
+ });
+
+ it('disables GroupListItems', () => {
+ findAllItems().wrappers.forEach((groupListItem) => {
+ expect(groupListItem.props('disabled')).toBe(true);
+ });
+ });
+
+ it('sets opacity of the groups list', () => {
+ expect(findGroupsList().classes()).toContain('gl-opacity-5');
+ });
+
+ it('sets loading prop of the search box', () => {
+ expect(findSearchBox().props('isLoading')).toBe(true);
+ });
+
+ it('sets value prop of the search box to the search term', () => {
+ expect(findSearchBox().props('value')).toBe(mockSearchTeam);
+ });
+ });
+
+ describe('when group search finishes loading', () => {
+ beforeEach(async () => {
+ fetchGroups.mockResolvedValue({ data: [mockGroup1] });
+ findSearchBox().vm.$emit('input');
+
+ await waitForPromises();
+ });
+
+ it('renders new groups list', () => {
+ expect(findAllItems()).toHaveLength(1);
+ expect(findFirstItem().props('group')).toBe(mockGroup1);
+ });
+ });
+
+ it.each`
+ userSearchTerm | finalSearchTerm
+ ${'gitl'} | ${'gitl'}
+ ${'git'} | ${'git'}
+ ${'gi'} | ${''}
+ ${'g'} | ${''}
+ ${''} | ${''}
+ ${undefined} | ${undefined}
+ `(
+ 'searches for "$finalSearchTerm" when user enters "$userSearchTerm"',
+ async ({ userSearchTerm, finalSearchTerm }) => {
+ fetchGroups.mockResolvedValue({
+ data: [mockGroup1],
+ headers: { 'X-PAGE': 1, 'X-TOTAL': 1 },
+ });
+
+ createComponent();
+ await waitForPromises();
+
+ const searchBox = findSearchBox();
+ searchBox.vm.$emit('input', userSearchTerm);
+
+ expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
+ page: 1,
+ perPage: DEFAULT_GROUPS_PER_PAGE,
+ search: finalSearchTerm,
+ });
+ },
+ );
+ });
+
+ describe('when page=2', () => {
+ beforeEach(async () => {
+ const totalItems = DEFAULT_GROUPS_PER_PAGE + 1;
+ const mockGroups = createMockGroups(totalItems);
+ fetchGroups.mockResolvedValue({
+ headers: { 'X-TOTAL': totalItems, 'X-PAGE': 1 },
+ data: mockGroups,
+ });
+ createComponent();
+ await waitForPromises();
+
+ const paginationEl = findPagination();
+ paginationEl.vm.$emit('input', 2);
+ });
+
+ it('should load results for page 2', () => {
+ expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
+ page: 2,
+ perPage: DEFAULT_GROUPS_PER_PAGE,
+ search: '',
+ });
+ });
+
+ it('resets page to 1 on search `input` event', () => {
+ const mockSearchTerm = 'gitlab';
+ const searchBox = findSearchBox();
+
+ searchBox.vm.$emit('input', mockSearchTerm);
+
+ expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
+ page: 1,
+ perPage: DEFAULT_GROUPS_PER_PAGE,
+ search: mockSearchTerm,
+ });
+ });
+ });
+ });
+
+ describe('pagination', () => {
+ it.each`
+ scenario | totalItems | shouldShowPagination
+ ${'renders pagination'} | ${DEFAULT_GROUPS_PER_PAGE + 1} | ${true}
+ ${'does not render pagination'} | ${DEFAULT_GROUPS_PER_PAGE} | ${false}
+ ${'does not render pagination'} | ${2} | ${false}
+ ${'does not render pagination'} | ${0} | ${false}
+ `('$scenario with $totalItems groups', async ({ totalItems, shouldShowPagination }) => {
+ const mockGroups = createMockGroups(totalItems);
+ fetchGroups.mockResolvedValue({
+ headers: { 'X-TOTAL': totalItems, 'X-PAGE': 1 },
+ data: mockGroups,
+ });
+ createComponent();
+ await waitForPromises();
+
+ const paginationEl = findPagination();
+
+ expect(paginationEl.exists()).toBe(shouldShowPagination);
+ if (shouldShowPagination) {
+ expect(paginationEl.props('totalItems')).toBe(totalItems);
+ }
+ });
+
+ describe('when `input` event triggered', () => {
+ beforeEach(async () => {
+ const MOCK_TOTAL_ITEMS = DEFAULT_GROUPS_PER_PAGE + 1;
+ fetchGroups.mockResolvedValue({
+ headers: { 'X-TOTAL': MOCK_TOTAL_ITEMS, 'X-PAGE': 1 },
+ data: createMockGroups(MOCK_TOTAL_ITEMS),
+ });
+
+ createComponent();
+ await waitForPromises();
+ });
+
+ it('executes `fetchGroups` with correct arguments', () => {
+ const paginationEl = findPagination();
+ paginationEl.vm.$emit('input', 2);
+
+ expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
+ page: 2,
+ perPage: DEFAULT_GROUPS_PER_PAGE,
+ search: '',
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/subscriptions/components/app_spec.js b/spec/frontend/jira_connect/subscriptions/components/app_spec.js
index 8915a7697a5..8e464968453 100644
--- a/spec/frontend/jira_connect/subscriptions/components/app_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/components/app_spec.js
@@ -1,14 +1,17 @@
-import { GlAlert, GlButton, GlModal, GlLink } from '@gitlab/ui';
+import { GlAlert, GlLink, GlEmptyState } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue';
+import AddNamespaceButton from '~/jira_connect/subscriptions/components/add_namespace_button.vue';
+import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue';
+import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue';
import createStore from '~/jira_connect/subscriptions/store';
import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types';
import { __ } from '~/locale';
+import { mockSubscription } from '../mock_data';
jest.mock('~/jira_connect/subscriptions/utils', () => ({
retrieveAlert: jest.fn().mockReturnValue({ message: 'error message' }),
- getLocation: jest.fn(),
}));
describe('JiraConnectApp', () => {
@@ -17,8 +20,10 @@ describe('JiraConnectApp', () => {
const findAlert = () => wrapper.findComponent(GlAlert);
const findAlertLink = () => findAlert().findComponent(GlLink);
- const findGlButton = () => wrapper.findComponent(GlButton);
- const findGlModal = () => wrapper.findComponent(GlModal);
+ const findSignInButton = () => wrapper.findComponent(SignInButton);
+ const findAddNamespaceButton = () => wrapper.findComponent(AddNamespaceButton);
+ const findSubscriptionsList = () => wrapper.findComponent(SubscriptionsList);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const createComponent = ({ provide, mountFn = shallowMount } = {}) => {
store = createStore();
@@ -34,96 +39,115 @@ describe('JiraConnectApp', () => {
});
describe('template', () => {
- describe('when user is not logged in', () => {
- beforeEach(() => {
- createComponent({
- provide: {
- usersPath: '/users',
- },
+ describe.each`
+ scenario | usersPath | subscriptions | expectSignInButton | expectEmptyState | expectNamespaceButton | expectSubscriptionsList
+ ${'user is not signed in with subscriptions'} | ${'/users'} | ${[mockSubscription]} | ${true} | ${false} | ${false} | ${true}
+ ${'user is not signed in without subscriptions'} | ${'/users'} | ${undefined} | ${true} | ${false} | ${false} | ${false}
+ ${'user is signed in with subscriptions'} | ${undefined} | ${[mockSubscription]} | ${false} | ${false} | ${true} | ${true}
+ ${'user is signed in without subscriptions'} | ${undefined} | ${undefined} | ${false} | ${true} | ${false} | ${false}
+ `(
+ 'when $scenario',
+ ({
+ usersPath,
+ expectSignInButton,
+ subscriptions,
+ expectEmptyState,
+ expectNamespaceButton,
+ expectSubscriptionsList,
+ }) => {
+ beforeEach(() => {
+ createComponent({
+ provide: {
+ usersPath,
+ subscriptions,
+ },
+ });
});
- });
- it('renders "Sign in" button', () => {
- expect(findGlButton().text()).toBe('Sign in to add namespaces');
- expect(findGlModal().exists()).toBe(false);
- });
- });
+ it(`${expectSignInButton ? 'renders' : 'does not render'} sign in button`, () => {
+ expect(findSignInButton().exists()).toBe(expectSignInButton);
+ });
- describe('when user is logged in', () => {
- beforeEach(() => {
- createComponent();
- });
+ it(`${expectEmptyState ? 'renders' : 'does not render'} empty state`, () => {
+ expect(findEmptyState().exists()).toBe(expectEmptyState);
+ });
- it('renders "Add" button and modal', () => {
- expect(findGlButton().text()).toBe('Add namespace');
- expect(findGlModal().exists()).toBe(true);
- });
- });
+ it(`${
+ expectNamespaceButton ? 'renders' : 'does not render'
+ } button to add namespace`, () => {
+ expect(findAddNamespaceButton().exists()).toBe(expectNamespaceButton);
+ });
+
+ it(`${expectSubscriptionsList ? 'renders' : 'does not render'} subscriptions list`, () => {
+ expect(findSubscriptionsList().exists()).toBe(expectSubscriptionsList);
+ });
+ },
+ );
+ });
- describe('alert', () => {
- it.each`
- message | variant | alertShouldRender
- ${'Test error'} | ${'danger'} | ${true}
- ${'Test notice'} | ${'info'} | ${true}
- ${''} | ${undefined} | ${false}
- ${undefined} | ${undefined} | ${false}
- `(
- 'renders correct alert when message is `$message` and variant is `$variant`',
- async ({ message, alertShouldRender, variant }) => {
- createComponent();
-
- store.commit(SET_ALERT, { message, variant });
- await wrapper.vm.$nextTick();
-
- const alert = findAlert();
-
- expect(alert.exists()).toBe(alertShouldRender);
- if (alertShouldRender) {
- expect(alert.isVisible()).toBe(alertShouldRender);
- expect(alert.html()).toContain(message);
- expect(alert.props('variant')).toBe(variant);
- expect(findAlertLink().exists()).toBe(false);
- }
- },
- );
-
- it('hides alert on @dismiss event', async () => {
+ describe('alert', () => {
+ it.each`
+ message | variant | alertShouldRender
+ ${'Test error'} | ${'danger'} | ${true}
+ ${'Test notice'} | ${'info'} | ${true}
+ ${''} | ${undefined} | ${false}
+ ${undefined} | ${undefined} | ${false}
+ `(
+ 'renders correct alert when message is `$message` and variant is `$variant`',
+ async ({ message, alertShouldRender, variant }) => {
createComponent();
- store.commit(SET_ALERT, { message: 'test message' });
+ store.commit(SET_ALERT, { message, variant });
await wrapper.vm.$nextTick();
- findAlert().vm.$emit('dismiss');
- await wrapper.vm.$nextTick();
+ const alert = findAlert();
- expect(findAlert().exists()).toBe(false);
- });
+ expect(alert.exists()).toBe(alertShouldRender);
+ if (alertShouldRender) {
+ expect(alert.isVisible()).toBe(alertShouldRender);
+ expect(alert.html()).toContain(message);
+ expect(alert.props('variant')).toBe(variant);
+ expect(findAlertLink().exists()).toBe(false);
+ }
+ },
+ );
- it('renders link when `linkUrl` is set', async () => {
- createComponent({ mountFn: mount });
+ it('hides alert on @dismiss event', async () => {
+ createComponent();
- store.commit(SET_ALERT, {
- message: __('test message %{linkStart}test link%{linkEnd}'),
- linkUrl: 'https://gitlab.com',
- });
- await wrapper.vm.$nextTick();
+ store.commit(SET_ALERT, { message: 'test message' });
+ await wrapper.vm.$nextTick();
+
+ findAlert().vm.$emit('dismiss');
+ await wrapper.vm.$nextTick();
+
+ expect(findAlert().exists()).toBe(false);
+ });
- const alertLink = findAlertLink();
+ it('renders link when `linkUrl` is set', async () => {
+ createComponent({ mountFn: mount });
- expect(alertLink.exists()).toBe(true);
- expect(alertLink.text()).toContain('test link');
- expect(alertLink.attributes('href')).toBe('https://gitlab.com');
+ store.commit(SET_ALERT, {
+ message: __('test message %{linkStart}test link%{linkEnd}'),
+ linkUrl: 'https://gitlab.com',
});
+ await wrapper.vm.$nextTick();
- describe('when alert is set in localStoage', () => {
- it('renders alert on mount', () => {
- createComponent();
+ const alertLink = findAlertLink();
- const alert = findAlert();
+ expect(alertLink.exists()).toBe(true);
+ expect(alertLink.text()).toContain('test link');
+ expect(alertLink.attributes('href')).toBe('https://gitlab.com');
+ });
- expect(alert.exists()).toBe(true);
- expect(alert.html()).toContain('error message');
- });
+ describe('when alert is set in localStoage', () => {
+ it('renders alert on mount', () => {
+ createComponent();
+
+ const alert = findAlert();
+
+ expect(alert.exists()).toBe(true);
+ expect(alert.html()).toContain('error message');
});
});
});
diff --git a/spec/frontend/jira_connect/subscriptions/components/groups_list_item_spec.js b/spec/frontend/jira_connect/subscriptions/components/groups_list_item_spec.js
deleted file mode 100644
index b69435df83a..00000000000
--- a/spec/frontend/jira_connect/subscriptions/components/groups_list_item_spec.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import { GlButton } from '@gitlab/ui';
-import { mount, shallowMount } from '@vue/test-utils';
-import waitForPromises from 'helpers/wait_for_promises';
-
-import * as JiraConnectApi from '~/jira_connect/subscriptions/api';
-import GroupItemName from '~/jira_connect/subscriptions/components/group_item_name.vue';
-import GroupsListItem from '~/jira_connect/subscriptions/components/groups_list_item.vue';
-import { persistAlert, reloadPage } from '~/jira_connect/subscriptions/utils';
-import { mockGroup1 } from '../mock_data';
-
-jest.mock('~/jira_connect/subscriptions/utils');
-
-describe('GroupsListItem', () => {
- let wrapper;
- const mockSubscriptionPath = 'subscriptionPath';
-
- const createComponent = ({ mountFn = shallowMount } = {}) => {
- wrapper = mountFn(GroupsListItem, {
- propsData: {
- group: mockGroup1,
- },
- provide: {
- subscriptionsPath: mockSubscriptionPath,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const findGroupItemName = () => wrapper.findComponent(GroupItemName);
- const findLinkButton = () => wrapper.findComponent(GlButton);
- const clickLinkButton = () => findLinkButton().trigger('click');
-
- describe('template', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders GroupItemName', () => {
- expect(findGroupItemName().exists()).toBe(true);
- expect(findGroupItemName().props('group')).toBe(mockGroup1);
- });
-
- it('renders Link button', () => {
- expect(findLinkButton().exists()).toBe(true);
- expect(findLinkButton().text()).toBe('Link');
- });
- });
-
- describe('on Link button click', () => {
- let addSubscriptionSpy;
-
- beforeEach(() => {
- createComponent({ mountFn: mount });
-
- addSubscriptionSpy = jest.spyOn(JiraConnectApi, 'addSubscription').mockResolvedValue();
- });
-
- it('sets button to loading and sends request', async () => {
- expect(findLinkButton().props('loading')).toBe(false);
-
- clickLinkButton();
-
- await wrapper.vm.$nextTick();
-
- expect(findLinkButton().props('loading')).toBe(true);
-
- await waitForPromises();
-
- expect(addSubscriptionSpy).toHaveBeenCalledWith(mockSubscriptionPath, mockGroup1.full_path);
- expect(persistAlert).toHaveBeenCalledWith({
- linkUrl: '/help/integration/jira_development_panel.html#usage',
- message:
- 'You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}',
- title: 'Namespace successfully linked',
- variant: 'success',
- });
- });
-
- describe('when request is successful', () => {
- it('reloads the page', async () => {
- clickLinkButton();
-
- await waitForPromises();
-
- expect(reloadPage).toHaveBeenCalled();
- });
- });
-
- describe('when request has errors', () => {
- const mockErrorMessage = 'error message';
- const mockError = { response: { data: { error: mockErrorMessage } } };
-
- beforeEach(() => {
- addSubscriptionSpy = jest
- .spyOn(JiraConnectApi, 'addSubscription')
- .mockRejectedValue(mockError);
- });
-
- it('emits `error` event', async () => {
- clickLinkButton();
-
- await waitForPromises();
-
- expect(reloadPage).not.toHaveBeenCalled();
- expect(wrapper.emitted('error')[0][0]).toBe(mockErrorMessage);
- });
- });
- });
-});
diff --git a/spec/frontend/jira_connect/subscriptions/components/groups_list_spec.js b/spec/frontend/jira_connect/subscriptions/components/groups_list_spec.js
deleted file mode 100644
index d3a9a3bfd41..00000000000
--- a/spec/frontend/jira_connect/subscriptions/components/groups_list_spec.js
+++ /dev/null
@@ -1,303 +0,0 @@
-import { GlAlert, GlLoadingIcon, GlSearchBoxByType, GlPagination } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import { fetchGroups } from '~/jira_connect/subscriptions/api';
-import GroupsList from '~/jira_connect/subscriptions/components/groups_list.vue';
-import GroupsListItem from '~/jira_connect/subscriptions/components/groups_list_item.vue';
-import { DEFAULT_GROUPS_PER_PAGE } from '~/jira_connect/subscriptions/constants';
-import { mockGroup1, mockGroup2 } from '../mock_data';
-
-const createMockGroup = (groupId) => {
- return {
- ...mockGroup1,
- id: groupId,
- };
-};
-
-const createMockGroups = (count) => {
- return [...new Array(count)].map((_, idx) => createMockGroup(idx));
-};
-
-jest.mock('~/jira_connect/subscriptions/api', () => {
- return {
- fetchGroups: jest.fn(),
- };
-});
-
-const mockGroupsPath = '/groups';
-
-describe('GroupsList', () => {
- let wrapper;
-
- const mockEmptyResponse = { data: [] };
-
- const createComponent = (options = {}) => {
- wrapper = extendedWrapper(
- shallowMount(GroupsList, {
- provide: {
- groupsPath: mockGroupsPath,
- },
- ...options,
- }),
- );
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const findGlAlert = () => wrapper.findComponent(GlAlert);
- const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
- const findAllItems = () => wrapper.findAll(GroupsListItem);
- const findFirstItem = () => findAllItems().at(0);
- const findSecondItem = () => findAllItems().at(1);
- const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
- const findGroupsList = () => wrapper.findByTestId('groups-list');
- const findPagination = () => wrapper.findComponent(GlPagination);
-
- describe('when groups are loading', () => {
- it('renders loading icon', async () => {
- fetchGroups.mockReturnValue(new Promise(() => {}));
- createComponent();
-
- await wrapper.vm.$nextTick();
-
- expect(findGlLoadingIcon().exists()).toBe(true);
- });
- });
-
- describe('when groups fetch fails', () => {
- it('renders error message', async () => {
- fetchGroups.mockRejectedValue();
- createComponent();
-
- await waitForPromises();
-
- expect(findGlLoadingIcon().exists()).toBe(false);
- expect(findGlAlert().exists()).toBe(true);
- expect(findGlAlert().text()).toBe('Failed to load namespaces. Please try again.');
- });
- });
-
- describe('with no groups returned', () => {
- it('renders empty state', async () => {
- fetchGroups.mockResolvedValue(mockEmptyResponse);
- createComponent();
-
- await waitForPromises();
-
- expect(findGlLoadingIcon().exists()).toBe(false);
- expect(wrapper.text()).toContain('No available namespaces');
- });
- });
-
- describe('with groups returned', () => {
- beforeEach(async () => {
- fetchGroups.mockResolvedValue({
- headers: { 'X-PAGE': 1, 'X-TOTAL': 2 },
- data: [mockGroup1, mockGroup2],
- });
- createComponent();
-
- await waitForPromises();
- });
-
- it('renders groups list', () => {
- expect(findAllItems()).toHaveLength(2);
- expect(findFirstItem().props('group')).toBe(mockGroup1);
- expect(findSecondItem().props('group')).toBe(mockGroup2);
- });
-
- it('sets GroupListItem `disabled` prop to `false`', () => {
- findAllItems().wrappers.forEach((groupListItem) => {
- expect(groupListItem.props('disabled')).toBe(false);
- });
- });
-
- it('does not set opacity of the groups list', () => {
- expect(findGroupsList().classes()).not.toContain('gl-opacity-5');
- });
-
- it('shows error message on $emit from item', async () => {
- const errorMessage = 'error message';
-
- findFirstItem().vm.$emit('error', errorMessage);
-
- await wrapper.vm.$nextTick();
-
- expect(findGlAlert().exists()).toBe(true);
- expect(findGlAlert().text()).toContain(errorMessage);
- });
-
- describe('when searching groups', () => {
- const mockSearchTeam = 'mock search term';
-
- describe('while groups are loading', () => {
- beforeEach(async () => {
- fetchGroups.mockClear();
- fetchGroups.mockReturnValue(new Promise(() => {}));
-
- findSearchBox().vm.$emit('input', mockSearchTeam);
- await wrapper.vm.$nextTick();
- });
-
- it('calls `fetchGroups` with search term', () => {
- expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
- page: 1,
- perPage: DEFAULT_GROUPS_PER_PAGE,
- search: mockSearchTeam,
- });
- });
-
- it('disables GroupListItems', () => {
- findAllItems().wrappers.forEach((groupListItem) => {
- expect(groupListItem.props('disabled')).toBe(true);
- });
- });
-
- it('sets opacity of the groups list', () => {
- expect(findGroupsList().classes()).toContain('gl-opacity-5');
- });
-
- it('sets loading prop of the search box', () => {
- expect(findSearchBox().props('isLoading')).toBe(true);
- });
-
- it('sets value prop of the search box to the search term', () => {
- expect(findSearchBox().props('value')).toBe(mockSearchTeam);
- });
- });
-
- describe('when group search finishes loading', () => {
- beforeEach(async () => {
- fetchGroups.mockResolvedValue({ data: [mockGroup1] });
- findSearchBox().vm.$emit('input');
-
- await waitForPromises();
- });
-
- it('renders new groups list', () => {
- expect(findAllItems()).toHaveLength(1);
- expect(findFirstItem().props('group')).toBe(mockGroup1);
- });
- });
-
- it.each`
- userSearchTerm | finalSearchTerm
- ${'gitl'} | ${'gitl'}
- ${'git'} | ${'git'}
- ${'gi'} | ${''}
- ${'g'} | ${''}
- ${''} | ${''}
- ${undefined} | ${undefined}
- `(
- 'searches for "$finalSearchTerm" when user enters "$userSearchTerm"',
- async ({ userSearchTerm, finalSearchTerm }) => {
- fetchGroups.mockResolvedValue({
- data: [mockGroup1],
- headers: { 'X-PAGE': 1, 'X-TOTAL': 1 },
- });
-
- createComponent();
- await waitForPromises();
-
- const searchBox = findSearchBox();
- searchBox.vm.$emit('input', userSearchTerm);
-
- expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
- page: 1,
- perPage: DEFAULT_GROUPS_PER_PAGE,
- search: finalSearchTerm,
- });
- },
- );
- });
-
- describe('when page=2', () => {
- beforeEach(async () => {
- const totalItems = DEFAULT_GROUPS_PER_PAGE + 1;
- const mockGroups = createMockGroups(totalItems);
- fetchGroups.mockResolvedValue({
- headers: { 'X-TOTAL': totalItems, 'X-PAGE': 1 },
- data: mockGroups,
- });
- createComponent();
- await waitForPromises();
-
- const paginationEl = findPagination();
- paginationEl.vm.$emit('input', 2);
- });
-
- it('should load results for page 2', () => {
- expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
- page: 2,
- perPage: DEFAULT_GROUPS_PER_PAGE,
- search: '',
- });
- });
-
- it('resets page to 1 on search `input` event', () => {
- const mockSearchTerm = 'gitlab';
- const searchBox = findSearchBox();
-
- searchBox.vm.$emit('input', mockSearchTerm);
-
- expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
- page: 1,
- perPage: DEFAULT_GROUPS_PER_PAGE,
- search: mockSearchTerm,
- });
- });
- });
- });
-
- describe('pagination', () => {
- it.each`
- scenario | totalItems | shouldShowPagination
- ${'renders pagination'} | ${DEFAULT_GROUPS_PER_PAGE + 1} | ${true}
- ${'does not render pagination'} | ${DEFAULT_GROUPS_PER_PAGE} | ${false}
- ${'does not render pagination'} | ${2} | ${false}
- ${'does not render pagination'} | ${0} | ${false}
- `('$scenario with $totalItems groups', async ({ totalItems, shouldShowPagination }) => {
- const mockGroups = createMockGroups(totalItems);
- fetchGroups.mockResolvedValue({
- headers: { 'X-TOTAL': totalItems, 'X-PAGE': 1 },
- data: mockGroups,
- });
- createComponent();
- await waitForPromises();
-
- const paginationEl = findPagination();
-
- expect(paginationEl.exists()).toBe(shouldShowPagination);
- if (shouldShowPagination) {
- expect(paginationEl.props('totalItems')).toBe(totalItems);
- }
- });
-
- describe('when `input` event triggered', () => {
- beforeEach(async () => {
- const MOCK_TOTAL_ITEMS = DEFAULT_GROUPS_PER_PAGE + 1;
- fetchGroups.mockResolvedValue({
- headers: { 'X-TOTAL': MOCK_TOTAL_ITEMS, 'X-PAGE': 1 },
- data: createMockGroups(MOCK_TOTAL_ITEMS),
- });
-
- createComponent();
- await waitForPromises();
- });
-
- it('executes `fetchGroups` with correct arguments', () => {
- const paginationEl = findPagination();
- paginationEl.vm.$emit('input', 2);
-
- expect(fetchGroups).toHaveBeenLastCalledWith(mockGroupsPath, {
- page: 2,
- perPage: DEFAULT_GROUPS_PER_PAGE,
- search: '',
- });
- });
- });
- });
-});
diff --git a/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js b/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js
new file mode 100644
index 00000000000..cb5ae877c47
--- /dev/null
+++ b/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js
@@ -0,0 +1,48 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils';
+import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue';
+import waitForPromises from 'helpers/wait_for_promises';
+
+const MOCK_USERS_PATH = '/user';
+
+jest.mock('~/jira_connect/subscriptions/utils');
+
+describe('SignInButton', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(SignInButton, {
+ propsData: {
+ usersPath: MOCK_USERS_PATH,
+ },
+ });
+ };
+
+ const findButton = () => wrapper.findComponent(GlButton);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays a button', () => {
+ createComponent();
+
+ expect(findButton().exists()).toBe(true);
+ });
+
+ describe.each`
+ expectedHref
+ ${MOCK_USERS_PATH}
+ ${`${MOCK_USERS_PATH}?return_to=${encodeURIComponent('https://test.jira.com')}`}
+ `('when getGitlabSignInURL resolves with `$expectedHref`', ({ expectedHref }) => {
+ it(`sets button href to ${expectedHref}`, async () => {
+ getGitlabSignInURL.mockResolvedValue(expectedHref);
+ createComponent();
+
+ await waitForPromises();
+
+ expect(findButton().attributes('href')).toBe(expectedHref);
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js b/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js
index 32b43765843..4e4a2b58600 100644
--- a/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js
@@ -1,12 +1,15 @@
-import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
-import { mount, shallowMount } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import * as JiraConnectApi from '~/jira_connect/subscriptions/api';
+import GroupItemName from '~/jira_connect/subscriptions/components/group_item_name.vue';
+
import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue';
import createStore from '~/jira_connect/subscriptions/store';
import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types';
import { reloadPage } from '~/jira_connect/subscriptions/utils';
+import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { mockSubscription } from '../mock_data';
jest.mock('~/jira_connect/subscriptions/utils');
@@ -15,11 +18,13 @@ describe('SubscriptionsList', () => {
let wrapper;
let store;
- const createComponent = ({ mountFn = shallowMount, provide = {} } = {}) => {
+ const createComponent = () => {
store = createStore();
- wrapper = mountFn(SubscriptionsList, {
- provide,
+ wrapper = mount(SubscriptionsList, {
+ provide: {
+ subscriptions: [mockSubscription],
+ },
store,
});
};
@@ -28,28 +33,28 @@ describe('SubscriptionsList', () => {
wrapper.destroy();
});
- const findGlEmptyState = () => wrapper.findComponent(GlEmptyState);
- const findGlTable = () => wrapper.findComponent(GlTable);
- const findUnlinkButton = () => findGlTable().findComponent(GlButton);
+ const findUnlinkButton = () => wrapper.findComponent(GlButton);
const clickUnlinkButton = () => findUnlinkButton().trigger('click');
describe('template', () => {
- it('renders GlEmptyState when subscriptions is empty', () => {
+ beforeEach(() => {
createComponent();
+ });
+
+ it('renders "name" cell correctly', () => {
+ const groupItemNames = wrapper.findAllComponents(GroupItemName);
+ expect(groupItemNames.wrappers).toHaveLength(1);
- expect(findGlEmptyState().exists()).toBe(true);
- expect(findGlTable().exists()).toBe(false);
+ const item = groupItemNames.at(0);
+ expect(item.props('group')).toBe(mockSubscription.group);
});
- it('renders GlTable when subscriptions are present', () => {
- createComponent({
- provide: {
- subscriptions: [mockSubscription],
- },
- });
+ it('renders "created at" cell correctly', () => {
+ const timeAgoTooltips = wrapper.findAllComponents(TimeagoTooltip);
+ expect(timeAgoTooltips.wrappers).toHaveLength(1);
- expect(findGlEmptyState().exists()).toBe(false);
- expect(findGlTable().exists()).toBe(true);
+ const item = timeAgoTooltips.at(0);
+ expect(item.props('time')).toBe(mockSubscription.created_at);
});
});
@@ -57,12 +62,7 @@ describe('SubscriptionsList', () => {
let removeSubscriptionSpy;
beforeEach(() => {
- createComponent({
- mountFn: mount,
- provide: {
- subscriptions: [mockSubscription],
- },
- });
+ createComponent();
removeSubscriptionSpy = jest.spyOn(JiraConnectApi, 'removeSubscription').mockResolvedValue();
});
diff --git a/spec/frontend/jira_connect/subscriptions/index_spec.js b/spec/frontend/jira_connect/subscriptions/index_spec.js
index 786f3b4a7d3..b97918a198e 100644
--- a/spec/frontend/jira_connect/subscriptions/index_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/index_spec.js
@@ -1,24 +1,36 @@
import { initJiraConnect } from '~/jira_connect/subscriptions';
+import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils';
-jest.mock('~/jira_connect/subscriptions/utils', () => ({
- getLocation: jest.fn().mockResolvedValue('test/location'),
-}));
+jest.mock('~/jira_connect/subscriptions/utils');
describe('initJiraConnect', () => {
- beforeEach(async () => {
+ const mockInitialHref = 'https://gitlab.com';
+
+ beforeEach(() => {
setFixtures(`
- <a class="js-jira-connect-sign-in" href="https://gitlab.com">Sign In</a>
- <a class="js-jira-connect-sign-in" href="https://gitlab.com">Another Sign In</a>
+ <a class="js-jira-connect-sign-in" href="${mockInitialHref}">Sign In</a>
+ <a class="js-jira-connect-sign-in" href="${mockInitialHref}">Another Sign In</a>
`);
-
- await initJiraConnect();
});
+ const assertSignInLinks = (expectedLink) => {
+ Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => {
+ expect(el.getAttribute('href')).toBe(expectedLink);
+ });
+ };
+
describe('Sign in links', () => {
- it('have `return_to` query parameter', () => {
- Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => {
- expect(el.href).toContain('return_to=test/location');
- });
+ it('are updated on initialization', async () => {
+ const mockSignInLink = `https://gitlab.com?return_to=${encodeURIComponent('/test/location')}`;
+ getGitlabSignInURL.mockResolvedValue(mockSignInLink);
+
+ // assert the initial state
+ assertSignInLinks(mockInitialHref);
+
+ await initJiraConnect();
+
+ // assert the update has occurred
+ assertSignInLinks(mockSignInLink);
});
});
});
diff --git a/spec/frontend/jira_connect/subscriptions/utils_spec.js b/spec/frontend/jira_connect/subscriptions/utils_spec.js
index 2dd95de1b8c..762d9eb3443 100644
--- a/spec/frontend/jira_connect/subscriptions/utils_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/utils_spec.js
@@ -8,6 +8,7 @@ import {
getLocation,
reloadPage,
sizeToParent,
+ getGitlabSignInURL,
} from '~/jira_connect/subscriptions/utils';
describe('JiraConnect utils', () => {
@@ -137,4 +138,25 @@ describe('JiraConnect utils', () => {
});
});
});
+
+ describe('getGitlabSignInURL', () => {
+ const mockSignInURL = 'https://gitlab.com/sign_in';
+
+ it.each`
+ returnTo | expectResult
+ ${undefined} | ${mockSignInURL}
+ ${''} | ${mockSignInURL}
+ ${'/test/location'} | ${`${mockSignInURL}?return_to=${encodeURIComponent('/test/location')}`}
+ `(
+ 'returns `$expectResult` when `AP.getLocation` resolves to `$returnTo`',
+ async ({ returnTo, expectResult }) => {
+ global.AP = {
+ getLocation: jest.fn().mockImplementation((cb) => cb(returnTo)),
+ };
+
+ const url = await getGitlabSignInURL(mockSignInURL);
+ expect(url).toBe(expectResult);
+ },
+ );
+ });
});
diff --git a/spec/frontend/jobs/components/manual_variables_form_spec.js b/spec/frontend/jobs/components/manual_variables_form_spec.js
index 7e42ee957d3..a5278af8e33 100644
--- a/spec/frontend/jobs/components/manual_variables_form_spec.js
+++ b/spec/frontend/jobs/components/manual_variables_form_spec.js
@@ -1,9 +1,9 @@
import { GlSprintf, GlLink } from '@gitlab/ui';
-import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import { createLocalVue, mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import Form from '~/jobs/components/manual_variables_form.vue';
+import ManualVariablesForm from '~/jobs/components/manual_variables_form.vue';
const localVue = createLocalVue();
@@ -21,7 +21,7 @@ describe('Manual Variables Form', () => {
},
};
- const createComponent = ({ props = {}, mountFn = shallowMount } = {}) => {
+ const createComponent = (props = {}) => {
store = new Vuex.Store({
actions: {
triggerManualJob: jest.fn(),
@@ -29,7 +29,7 @@ describe('Manual Variables Form', () => {
});
wrapper = extendedWrapper(
- mountFn(localVue.extend(Form), {
+ mount(localVue.extend(ManualVariablesForm), {
propsData: { ...requiredProps, ...props },
localVue,
store,
@@ -40,88 +40,120 @@ describe('Manual Variables Form', () => {
);
};
- const findInputKey = () => wrapper.findComponent({ ref: 'inputKey' });
- const findInputValue = () => wrapper.findComponent({ ref: 'inputSecretValue' });
const findHelpText = () => wrapper.findComponent(GlSprintf);
const findHelpLink = () => wrapper.findComponent(GlLink);
const findTriggerBtn = () => wrapper.findByTestId('trigger-manual-job-btn');
const findDeleteVarBtn = () => wrapper.findByTestId('delete-variable-btn');
+ const findAllDeleteVarBtns = () => wrapper.findAllByTestId('delete-variable-btn');
+ const findDeleteVarBtnPlaceholder = () => wrapper.findByTestId('delete-variable-btn-placeholder');
const findCiVariableKey = () => wrapper.findByTestId('ci-variable-key');
+ const findAllCiVariableKeys = () => wrapper.findAllByTestId('ci-variable-key');
const findCiVariableValue = () => wrapper.findByTestId('ci-variable-value');
const findAllVariables = () => wrapper.findAllByTestId('ci-variable-row');
+ const setCiVariableKey = () => {
+ findCiVariableKey().setValue('new key');
+ findCiVariableKey().vm.$emit('change');
+ nextTick();
+ };
+
+ const setCiVariableKeyByPosition = (position, value) => {
+ findAllCiVariableKeys().at(position).setValue(value);
+ findAllCiVariableKeys().at(position).vm.$emit('change');
+ nextTick();
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
afterEach(() => {
wrapper.destroy();
});
- describe('shallowMount', () => {
- beforeEach(() => {
- createComponent();
- });
+ it('creates a new variable when user enters a new key value', async () => {
+ expect(findAllVariables()).toHaveLength(1);
- it('renders empty form with correct placeholders', () => {
- expect(findInputKey().attributes('placeholder')).toBe('Input variable key');
- expect(findInputValue().attributes('placeholder')).toBe('Input variable value');
- });
+ await setCiVariableKey();
- it('renders help text with provided link', () => {
- expect(findHelpText().exists()).toBe(true);
- expect(findHelpLink().attributes('href')).toBe(
- '/help/ci/variables/index#add-a-cicd-variable-to-a-project',
- );
- });
+ expect(findAllVariables()).toHaveLength(2);
+ });
- describe('when adding a new variable', () => {
- it('creates a new variable when user types a new key and resets the form', async () => {
- await findInputKey().setValue('new key');
+ it('does not create extra empty variables', async () => {
+ expect(findAllVariables()).toHaveLength(1);
- expect(findAllVariables()).toHaveLength(1);
- expect(findCiVariableKey().element.value).toBe('new key');
- expect(findInputKey().attributes('value')).toBe(undefined);
- });
+ await setCiVariableKey();
- it('creates a new variable when user types a new value and resets the form', async () => {
- await findInputValue().setValue('new value');
+ expect(findAllVariables()).toHaveLength(2);
- expect(findAllVariables()).toHaveLength(1);
- expect(findCiVariableValue().element.value).toBe('new value');
- expect(findInputValue().attributes('value')).toBe(undefined);
- });
- });
+ await setCiVariableKey();
+
+ expect(findAllVariables()).toHaveLength(2);
});
- describe('mount', () => {
- beforeEach(() => {
- createComponent({ mountFn: mount });
- });
+ it('removes the correct variable row', async () => {
+ const variableKeyNameOne = 'key-one';
+ const variableKeyNameThree = 'key-three';
- describe('when deleting a variable', () => {
- it('removes the variable row', async () => {
- await wrapper.setData({
- variables: [
- {
- key: 'new key',
- secret_value: 'value',
- id: '1',
- },
- ],
- });
+ await setCiVariableKeyByPosition(0, variableKeyNameOne);
- findDeleteVarBtn().trigger('click');
+ await setCiVariableKeyByPosition(1, 'key-two');
- await wrapper.vm.$nextTick();
+ await setCiVariableKeyByPosition(2, variableKeyNameThree);
- expect(findAllVariables()).toHaveLength(0);
- });
- });
+ expect(findAllVariables()).toHaveLength(4);
- it('trigger button is disabled after trigger action', async () => {
- expect(findTriggerBtn().props('disabled')).toBe(false);
+ await findAllDeleteVarBtns().at(1).trigger('click');
- await findTriggerBtn().trigger('click');
+ expect(findAllVariables()).toHaveLength(3);
- expect(findTriggerBtn().props('disabled')).toBe(true);
- });
+ expect(findAllCiVariableKeys().at(0).element.value).toBe(variableKeyNameOne);
+ expect(findAllCiVariableKeys().at(1).element.value).toBe(variableKeyNameThree);
+ expect(findAllCiVariableKeys().at(2).element.value).toBe('');
+ });
+
+ it('trigger button is disabled after trigger action', async () => {
+ expect(findTriggerBtn().props('disabled')).toBe(false);
+
+ await findTriggerBtn().trigger('click');
+
+ expect(findTriggerBtn().props('disabled')).toBe(true);
+ });
+
+ it('delete variable button should only show when there is more than one variable', async () => {
+ expect(findDeleteVarBtn().exists()).toBe(false);
+
+ await setCiVariableKey();
+
+ expect(findDeleteVarBtn().exists()).toBe(true);
+ });
+
+ it('delete variable button placeholder should only exist when a user cannot remove', async () => {
+ expect(findDeleteVarBtnPlaceholder().exists()).toBe(true);
+ });
+
+ it('renders help text with provided link', () => {
+ expect(findHelpText().exists()).toBe(true);
+ expect(findHelpLink().attributes('href')).toBe(
+ '/help/ci/variables/index#add-a-cicd-variable-to-a-project',
+ );
+ });
+
+ it('passes variables in correct format', async () => {
+ jest.spyOn(store, 'dispatch');
+
+ await setCiVariableKey();
+
+ await findCiVariableValue().setValue('new value');
+
+ await findTriggerBtn().trigger('click');
+
+ expect(store.dispatch).toHaveBeenCalledWith('triggerManualJob', [
+ {
+ key: 'new key',
+ secret_value: 'new value',
+ },
+ ]);
});
});
diff --git a/spec/frontend/lib/apollo/suppress_network_errors_during_navigation_link_spec.js b/spec/frontend/lib/apollo/suppress_network_errors_during_navigation_link_spec.js
index 852106db44e..7b604724977 100644
--- a/spec/frontend/lib/apollo/suppress_network_errors_during_navigation_link_spec.js
+++ b/spec/frontend/lib/apollo/suppress_network_errors_during_navigation_link_spec.js
@@ -47,107 +47,95 @@ describe('getSuppressNetworkErrorsDuringNavigationLink', () => {
subscription = link.request(mockOperation).subscribe(observer);
};
- describe('when disabled', () => {
- it('returns null', () => {
- expect(getSuppressNetworkErrorsDuringNavigationLink()).toBe(null);
- });
+ it('returns an ApolloLink', () => {
+ expect(getSuppressNetworkErrorsDuringNavigationLink()).toEqual(expect.any(ApolloLink));
});
- describe('when enabled', () => {
- beforeEach(() => {
- window.gon = { features: { suppressApolloErrorsDuringNavigation: true } };
- });
-
- it('returns an ApolloLink', () => {
- expect(getSuppressNetworkErrorsDuringNavigationLink()).toEqual(expect.any(ApolloLink));
- });
-
- describe('suppression case', () => {
- describe('when navigating away', () => {
- beforeEach(() => {
- isNavigatingAway.mockReturnValue(true);
- });
-
- describe('given a network error', () => {
- it('does not forward the error', async () => {
- const spy = jest.fn();
+ describe('suppression case', () => {
+ describe('when navigating away', () => {
+ beforeEach(() => {
+ isNavigatingAway.mockReturnValue(true);
+ });
- createSubscription(makeMockNetworkErrorLink(), {
- next: spy,
- error: spy,
- complete: spy,
- });
+ describe('given a network error', () => {
+ it('does not forward the error', async () => {
+ const spy = jest.fn();
- // It's hard to test for something _not_ happening. The best we can
- // do is wait a bit to make sure nothing happens.
- await waitForPromises();
- expect(spy).not.toHaveBeenCalled();
+ createSubscription(makeMockNetworkErrorLink(), {
+ next: spy,
+ error: spy,
+ complete: spy,
});
+
+ // It's hard to test for something _not_ happening. The best we can
+ // do is wait a bit to make sure nothing happens.
+ await waitForPromises();
+ expect(spy).not.toHaveBeenCalled();
});
});
});
+ });
- describe('non-suppression cases', () => {
- describe('when not navigating away', () => {
- beforeEach(() => {
- isNavigatingAway.mockReturnValue(false);
- });
+ describe('non-suppression cases', () => {
+ describe('when not navigating away', () => {
+ beforeEach(() => {
+ isNavigatingAway.mockReturnValue(false);
+ });
- it('forwards successful requests', (done) => {
- createSubscription(makeMockSuccessLink(), {
- next({ data }) {
- expect(data).toEqual({ foo: { id: 1 } });
- },
- error: () => done.fail('Should not happen'),
- complete: () => done(),
- });
+ it('forwards successful requests', (done) => {
+ createSubscription(makeMockSuccessLink(), {
+ next({ data }) {
+ expect(data).toEqual({ foo: { id: 1 } });
+ },
+ error: () => done.fail('Should not happen'),
+ complete: () => done(),
});
+ });
- it('forwards GraphQL errors', (done) => {
- createSubscription(makeMockGraphQLErrorLink(), {
- next({ errors }) {
- expect(errors).toEqual([{ message: 'foo' }]);
- },
- error: () => done.fail('Should not happen'),
- complete: () => done(),
- });
+ it('forwards GraphQL errors', (done) => {
+ createSubscription(makeMockGraphQLErrorLink(), {
+ next({ errors }) {
+ expect(errors).toEqual([{ message: 'foo' }]);
+ },
+ error: () => done.fail('Should not happen'),
+ complete: () => done(),
});
+ });
- it('forwards network errors', (done) => {
- createSubscription(makeMockNetworkErrorLink(), {
- next: () => done.fail('Should not happen'),
- error: (error) => {
- expect(error.message).toBe('NetworkError');
- done();
- },
- complete: () => done.fail('Should not happen'),
- });
+ it('forwards network errors', (done) => {
+ createSubscription(makeMockNetworkErrorLink(), {
+ next: () => done.fail('Should not happen'),
+ error: (error) => {
+ expect(error.message).toBe('NetworkError');
+ done();
+ },
+ complete: () => done.fail('Should not happen'),
});
});
+ });
- describe('when navigating away', () => {
- beforeEach(() => {
- isNavigatingAway.mockReturnValue(true);
- });
+ describe('when navigating away', () => {
+ beforeEach(() => {
+ isNavigatingAway.mockReturnValue(true);
+ });
- it('forwards successful requests', (done) => {
- createSubscription(makeMockSuccessLink(), {
- next({ data }) {
- expect(data).toEqual({ foo: { id: 1 } });
- },
- error: () => done.fail('Should not happen'),
- complete: () => done(),
- });
+ it('forwards successful requests', (done) => {
+ createSubscription(makeMockSuccessLink(), {
+ next({ data }) {
+ expect(data).toEqual({ foo: { id: 1 } });
+ },
+ error: () => done.fail('Should not happen'),
+ complete: () => done(),
});
+ });
- it('forwards GraphQL errors', (done) => {
- createSubscription(makeMockGraphQLErrorLink(), {
- next({ errors }) {
- expect(errors).toEqual([{ message: 'foo' }]);
- },
- error: () => done.fail('Should not happen'),
- complete: () => done(),
- });
+ it('forwards GraphQL errors', (done) => {
+ createSubscription(makeMockGraphQLErrorLink(), {
+ next({ errors }) {
+ expect(errors).toEqual([{ message: 'foo' }]);
+ },
+ error: () => done.fail('Should not happen'),
+ complete: () => done(),
});
});
});
diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js
index f5a74ee7f09..de1be5bc337 100644
--- a/spec/frontend/lib/utils/common_utils_spec.js
+++ b/spec/frontend/lib/utils/common_utils_spec.js
@@ -279,6 +279,14 @@ describe('common_utils', () => {
top: elementTopWithContext,
});
});
+
+ it('passes through behaviour', () => {
+ commonUtils.scrollToElementWithContext(`#${id}`, { behavior: 'smooth' });
+ expect(window.scrollTo).toHaveBeenCalledWith({
+ behavior: 'smooth',
+ top: elementTopWithContext,
+ });
+ });
});
});
@@ -1000,6 +1008,21 @@ describe('common_utils', () => {
});
});
+ describe('scopedLabelKey', () => {
+ it.each`
+ label | expectedLabelKey
+ ${undefined} | ${''}
+ ${''} | ${''}
+ ${'title'} | ${'title'}
+ ${'scoped::value'} | ${'scoped'}
+ ${'scoped::label::value'} | ${'scoped::label'}
+ ${'scoped::label-some::value'} | ${'scoped::label-some'}
+ ${'scoped::label::some::value'} | ${'scoped::label::some'}
+ `('returns "$expectedLabelKey" when label is "$label"', ({ label, expectedLabelKey }) => {
+ expect(commonUtils.scopedLabelKey({ title: label })).toBe(expectedLabelKey);
+ });
+ });
+
describe('getDashPath', () => {
it('returns the path following /-/', () => {
expect(commonUtils.getDashPath('/some/-/url-with-dashes-/')).toEqual('url-with-dashes-/');
diff --git a/spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js b/spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js
new file mode 100644
index 00000000000..d19f9352bbc
--- /dev/null
+++ b/spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js
@@ -0,0 +1,59 @@
+import { GlModal } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import ConfirmModal from '~/lib/utils/confirm_via_gl_modal/confirm_modal.vue';
+
+describe('Confirm Modal', () => {
+ let wrapper;
+ let modal;
+
+ const createComponent = ({ primaryText, primaryVariant } = {}) => {
+ wrapper = mount(ConfirmModal, {
+ propsData: {
+ primaryText,
+ primaryVariant,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findGlModal = () => wrapper.findComponent(GlModal);
+
+ describe('Modal events', () => {
+ beforeEach(() => {
+ createComponent();
+ modal = findGlModal();
+ });
+
+ it('should emit `confirmed` event on `primary` modal event', () => {
+ findGlModal().vm.$emit('primary');
+ expect(wrapper.emitted('confirmed')).toBeTruthy();
+ });
+
+ it('should emit closed` event on `hidden` modal event', () => {
+ modal.vm.$emit('hidden');
+ expect(wrapper.emitted('closed')).toBeTruthy();
+ });
+ });
+
+ describe('Custom properties', () => {
+ it('should pass correct custom primary text & button variant to the modal when provided', () => {
+ const primaryText = "Let's do it!";
+ const primaryVariant = 'danger';
+
+ createComponent({ primaryText, primaryVariant });
+ const customProps = findGlModal().props('actionPrimary');
+ expect(customProps.text).toBe(primaryText);
+ expect(customProps.attributes.variant).toBe(primaryVariant);
+ });
+
+ it('should pass default primary text & button variant to the modal if no custom values provided', () => {
+ createComponent();
+ const customProps = findGlModal().props('actionPrimary');
+ expect(customProps.text).toBe('OK');
+ expect(customProps.attributes.variant).toBe('confirm');
+ });
+ });
+});
diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js
index f6ad41d5478..7a64b654baa 100644
--- a/spec/frontend/lib/utils/datetime_utility_spec.js
+++ b/spec/frontend/lib/utils/datetime_utility_spec.js
@@ -185,15 +185,15 @@ describe('dateInWords', () => {
const date = new Date('07/01/2016');
it('should return date in words', () => {
- expect(datetimeUtility.dateInWords(date)).toEqual(s__('July 1, 2016'));
+ expect(datetimeUtility.dateInWords(date)).toEqual(__('July 1, 2016'));
});
it('should return abbreviated month name', () => {
- expect(datetimeUtility.dateInWords(date, true)).toEqual(s__('Jul 1, 2016'));
+ expect(datetimeUtility.dateInWords(date, true)).toEqual(__('Jul 1, 2016'));
});
it('should return date in words without year', () => {
- expect(datetimeUtility.dateInWords(date, true, true)).toEqual(s__('Jul 1'));
+ expect(datetimeUtility.dateInWords(date, true, true)).toEqual(__('Jul 1'));
});
});
@@ -201,11 +201,11 @@ describe('monthInWords', () => {
const date = new Date('2017-01-20');
it('returns month name from provided date', () => {
- expect(datetimeUtility.monthInWords(date)).toBe(s__('January'));
+ expect(datetimeUtility.monthInWords(date)).toBe(__('January'));
});
it('returns abbreviated month name from provided date', () => {
- expect(datetimeUtility.monthInWords(date, true)).toBe(s__('Jan'));
+ expect(datetimeUtility.monthInWords(date, true)).toBe(__('Jan'));
});
});
diff --git a/spec/frontend/lib/utils/file_upload_spec.js b/spec/frontend/lib/utils/file_upload_spec.js
index 1dff5d4f925..ff11107ea60 100644
--- a/spec/frontend/lib/utils/file_upload_spec.js
+++ b/spec/frontend/lib/utils/file_upload_spec.js
@@ -1,4 +1,4 @@
-import fileUpload, { getFilename } from '~/lib/utils/file_upload';
+import fileUpload, { getFilename, validateImageName } from '~/lib/utils/file_upload';
describe('File upload', () => {
beforeEach(() => {
@@ -64,13 +64,23 @@ describe('File upload', () => {
});
describe('getFilename', () => {
- it('returns first value correctly', () => {
- const event = {
- clipboardData: {
- getData: () => 'test.png\rtest.txt',
- },
- };
-
- expect(getFilename(event)).toBe('test.png');
+ it('returns file name', () => {
+ const file = new File([], 'test.jpg');
+
+ expect(getFilename(file)).toBe('test.jpg');
+ });
+});
+
+describe('file name validator', () => {
+ it('validate file name', () => {
+ const file = new File([], 'test.jpg');
+
+ expect(validateImageName(file)).toBe('test.jpg');
+ });
+
+ it('illegal file name should be rename to image.png', () => {
+ const file = new File([], 'test<.png');
+
+ expect(validateImageName(file)).toBe('image.png');
});
});
diff --git a/spec/frontend/lib/utils/text_markdown_spec.js b/spec/frontend/lib/utils/text_markdown_spec.js
index acbf1a975b8..ab81ec47b64 100644
--- a/spec/frontend/lib/utils/text_markdown_spec.js
+++ b/spec/frontend/lib/utils/text_markdown_spec.js
@@ -100,11 +100,11 @@ describe('init markdown', () => {
text: textArea.value,
tag: '```suggestion:-0+0\n{text}\n```',
blockTag: true,
- selected: '# Does not parse the %br currently.',
+ selected: '# Does not %br parse the %br currently.',
wrap: false,
});
- expect(textArea.value).toContain('# Does not parse the \\n currently.');
+ expect(textArea.value).toContain('# Does not \\n parse the \\n currently.');
});
it('inserts the tag on the same line if the current line only contains spaces', () => {
diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js
index 36e1a453ef4..c6edba19c56 100644
--- a/spec/frontend/lib/utils/url_utility_spec.js
+++ b/spec/frontend/lib/utils/url_utility_spec.js
@@ -1060,4 +1060,12 @@ describe('URL utility', () => {
},
);
});
+
+ describe('defaultPromoUrl', () => {
+ it('Gitlab about page url', () => {
+ const url = 'https://about.gitlab.com';
+
+ expect(urlUtils.PROMO_URL).toBe(url);
+ });
+ });
});
diff --git a/spec/frontend/members/mock_data.js b/spec/frontend/members/mock_data.js
index f42ee295511..218db0b587a 100644
--- a/spec/frontend/members/mock_data.js
+++ b/spec/frontend/members/mock_data.js
@@ -39,7 +39,7 @@ export const member = {
Developer: 30,
Maintainer: 40,
Owner: 50,
- 'Minimal Access': 5,
+ 'Minimal access': 5,
},
};
diff --git a/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap b/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap
deleted file mode 100644
index 2a8ce1d3f30..00000000000
--- a/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap
+++ /dev/null
@@ -1,43 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`AlertWidget Alert firing displays a warning icon and matches snapshot 1`] = `
-<gl-badge-stub
- class="d-flex-center text-truncate"
- size="md"
- variant="danger"
->
- <gl-icon-stub
- class="flex-shrink-0"
- name="warning"
- size="16"
- />
-
- <span
- class="text-truncate gl-pl-2"
- >
- Firing:
- alert-label &gt; 42
-
- </span>
-</gl-badge-stub>
-`;
-
-exports[`AlertWidget Alert not firing displays a warning icon and matches snapshot 1`] = `
-<gl-badge-stub
- class="d-flex-center text-truncate"
- size="md"
- variant="neutral"
->
- <gl-icon-stub
- class="flex-shrink-0"
- name="warning"
- size="16"
- />
-
- <span
- class="text-truncate gl-pl-2"
- >
- alert-label &gt; 42
- </span>
-</gl-badge-stub>
-`;
diff --git a/spec/frontend/monitoring/alert_widget_spec.js b/spec/frontend/monitoring/alert_widget_spec.js
deleted file mode 100644
index 9bf9e8ad7cc..00000000000
--- a/spec/frontend/monitoring/alert_widget_spec.js
+++ /dev/null
@@ -1,423 +0,0 @@
-import { GlLoadingIcon, GlTooltip, GlSprintf, GlBadge } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
-import AlertWidget from '~/monitoring/components/alert_widget.vue';
-
-const mockReadAlert = jest.fn();
-const mockCreateAlert = jest.fn();
-const mockUpdateAlert = jest.fn();
-const mockDeleteAlert = jest.fn();
-
-jest.mock('~/flash');
-jest.mock(
- '~/monitoring/services/alerts_service',
- () =>
- function AlertsServiceMock() {
- return {
- readAlert: mockReadAlert,
- createAlert: mockCreateAlert,
- updateAlert: mockUpdateAlert,
- deleteAlert: mockDeleteAlert,
- };
- },
-);
-
-describe('AlertWidget', () => {
- let wrapper;
-
- const nonFiringAlertResult = [
- {
- values: [
- [0, 1],
- [1, 42],
- [2, 41],
- ],
- },
- ];
- const firingAlertResult = [
- {
- values: [
- [0, 42],
- [1, 43],
- [2, 44],
- ],
- },
- ];
- const metricId = '5';
- const alertPath = 'my/alert.json';
-
- const relevantQueries = [
- {
- metricId,
- label: 'alert-label',
- alert_path: alertPath,
- result: nonFiringAlertResult,
- },
- ];
-
- const firingRelevantQueries = [
- {
- metricId,
- label: 'alert-label',
- alert_path: alertPath,
- result: firingAlertResult,
- },
- ];
-
- const defaultProps = {
- alertsEndpoint: '',
- relevantQueries,
- alertsToManage: {},
- modalId: 'alert-modal-1',
- };
-
- const propsWithAlert = {
- relevantQueries,
- };
-
- const propsWithAlertData = {
- relevantQueries,
- alertsToManage: {
- [alertPath]: { operator: '>', threshold: 42, alert_path: alertPath, metricId },
- },
- };
-
- const createComponent = (propsData) => {
- wrapper = shallowMount(AlertWidget, {
- stubs: { GlTooltip, GlSprintf },
- propsData: {
- ...defaultProps,
- ...propsData,
- },
- });
- };
- const hasLoadingIcon = () => wrapper.find(GlLoadingIcon).exists();
- const findWidgetForm = () => wrapper.find({ ref: 'widgetForm' });
- const findAlertErrorMessage = () => wrapper.find({ ref: 'alertErrorMessage' });
- const findCurrentSettingsText = () =>
- wrapper.find({ ref: 'alertCurrentSetting' }).text().replace(/\s\s+/g, ' ');
- const findBadge = () => wrapper.find(GlBadge);
- const findTooltip = () => wrapper.find(GlTooltip);
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('displays a loading spinner and disables form when fetching alerts', () => {
- let resolveReadAlert;
- mockReadAlert.mockReturnValue(
- new Promise((resolve) => {
- resolveReadAlert = resolve;
- }),
- );
- createComponent(defaultProps);
- return wrapper.vm
- .$nextTick()
- .then(() => {
- expect(hasLoadingIcon()).toBe(true);
- expect(findWidgetForm().props('disabled')).toBe(true);
-
- resolveReadAlert({ operator: '==', threshold: 42 });
- })
- .then(() => waitForPromises())
- .then(() => {
- expect(hasLoadingIcon()).toBe(false);
- expect(findWidgetForm().props('disabled')).toBe(false);
- });
- });
-
- it('does not render loading spinner if showLoadingState is false', () => {
- let resolveReadAlert;
- mockReadAlert.mockReturnValue(
- new Promise((resolve) => {
- resolveReadAlert = resolve;
- }),
- );
- createComponent({
- ...defaultProps,
- showLoadingState: false,
- });
- return wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
-
- resolveReadAlert({ operator: '==', threshold: 42 });
- })
- .then(() => waitForPromises())
- .then(() => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- });
- });
-
- it('displays an error message when fetch fails', () => {
- mockReadAlert.mockRejectedValue();
- createComponent(propsWithAlert);
- expect(hasLoadingIcon()).toBe(true);
-
- return waitForPromises().then(() => {
- expect(createFlash).toHaveBeenCalled();
- expect(hasLoadingIcon()).toBe(false);
- });
- });
-
- describe('Alert not firing', () => {
- it('displays a warning icon and matches snapshot', () => {
- mockReadAlert.mockResolvedValue({ operator: '>', threshold: 42 });
- createComponent(propsWithAlertData);
-
- return waitForPromises().then(() => {
- expect(findBadge().element).toMatchSnapshot();
- });
- });
-
- it('displays an alert summary when there is a single alert', () => {
- mockReadAlert.mockResolvedValue({ operator: '>', threshold: 42 });
- createComponent(propsWithAlertData);
- return waitForPromises().then(() => {
- expect(findCurrentSettingsText()).toEqual('alert-label > 42');
- });
- });
-
- it('displays a combined alert summary when there are multiple alerts', () => {
- mockReadAlert.mockResolvedValue({ operator: '>', threshold: 42 });
- const propsWithManyAlerts = {
- relevantQueries: [
- ...relevantQueries,
- ...[
- {
- metricId: '6',
- alert_path: 'my/alert2.json',
- label: 'alert-label2',
- result: [{ values: [] }],
- },
- ],
- ],
- alertsToManage: {
- 'my/alert.json': {
- operator: '>',
- threshold: 42,
- alert_path: alertPath,
- metricId,
- },
- 'my/alert2.json': {
- operator: '==',
- threshold: 900,
- alert_path: 'my/alert2.json',
- metricId: '6',
- },
- },
- };
- createComponent(propsWithManyAlerts);
- return waitForPromises().then(() => {
- expect(findCurrentSettingsText()).toContain('2 alerts applied');
- });
- });
- });
-
- describe('Alert firing', () => {
- it('displays a warning icon and matches snapshot', () => {
- mockReadAlert.mockResolvedValue({ operator: '>', threshold: 42 });
- propsWithAlertData.relevantQueries = firingRelevantQueries;
- createComponent(propsWithAlertData);
-
- return waitForPromises().then(() => {
- expect(findBadge().element).toMatchSnapshot();
- });
- });
-
- it('displays an alert summary when there is a single alert', () => {
- mockReadAlert.mockResolvedValue({ operator: '>', threshold: 42 });
- propsWithAlertData.relevantQueries = firingRelevantQueries;
- createComponent(propsWithAlertData);
- return waitForPromises().then(() => {
- expect(findCurrentSettingsText()).toEqual('Firing: alert-label > 42');
- });
- });
-
- it('displays a combined alert summary when there are multiple alerts', () => {
- mockReadAlert.mockResolvedValue({ operator: '>', threshold: 42 });
- const propsWithManyAlerts = {
- relevantQueries: [
- ...firingRelevantQueries,
- ...[
- {
- metricId: '6',
- alert_path: 'my/alert2.json',
- label: 'alert-label2',
- result: [{ values: [] }],
- },
- ],
- ],
- alertsToManage: {
- 'my/alert.json': {
- operator: '>',
- threshold: 42,
- alert_path: alertPath,
- metricId,
- },
- 'my/alert2.json': {
- operator: '==',
- threshold: 900,
- alert_path: 'my/alert2.json',
- metricId: '6',
- },
- },
- };
- createComponent(propsWithManyAlerts);
-
- return waitForPromises().then(() => {
- expect(findCurrentSettingsText()).toContain('2 alerts applied, 1 firing');
- });
- });
-
- it('should display tooltip with thresholds summary', () => {
- mockReadAlert.mockResolvedValue({ operator: '>', threshold: 42 });
- const propsWithManyAlerts = {
- relevantQueries: [
- ...firingRelevantQueries,
- ...[
- {
- metricId: '6',
- alert_path: 'my/alert2.json',
- label: 'alert-label2',
- result: [{ values: [] }],
- },
- ],
- ],
- alertsToManage: {
- 'my/alert.json': {
- operator: '>',
- threshold: 42,
- alert_path: alertPath,
- metricId,
- },
- 'my/alert2.json': {
- operator: '==',
- threshold: 900,
- alert_path: 'my/alert2.json',
- metricId: '6',
- },
- },
- };
- createComponent(propsWithManyAlerts);
-
- return waitForPromises().then(() => {
- expect(findTooltip().text().replace(/\s\s+/g, ' ')).toEqual('Firing: alert-label > 42');
- });
- });
- });
-
- it('creates an alert with an appropriate handler', () => {
- const alertParams = {
- operator: '<',
- threshold: 4,
- prometheus_metric_id: '5',
- };
- mockReadAlert.mockResolvedValue({ operator: '>', threshold: 42 });
- const fakeAlertPath = 'foo/bar';
- mockCreateAlert.mockResolvedValue({ alert_path: fakeAlertPath, ...alertParams });
- createComponent({
- alertsToManage: {
- [fakeAlertPath]: {
- alert_path: fakeAlertPath,
- operator: '<',
- threshold: 4,
- prometheus_metric_id: '5',
- metricId: '5',
- },
- },
- });
-
- findWidgetForm().vm.$emit('create', alertParams);
-
- expect(mockCreateAlert).toHaveBeenCalledWith(alertParams);
- });
-
- it('updates an alert with an appropriate handler', () => {
- const alertParams = { operator: '<', threshold: 4, alert_path: alertPath };
- const newAlertParams = { operator: '==', threshold: 12 };
- mockReadAlert.mockResolvedValue(alertParams);
- mockUpdateAlert.mockResolvedValue({ ...alertParams, ...newAlertParams });
- createComponent({
- ...propsWithAlertData,
- alertsToManage: {
- [alertPath]: {
- alert_path: alertPath,
- operator: '==',
- threshold: 12,
- metricId: '5',
- },
- },
- });
-
- findWidgetForm().vm.$emit('update', {
- alert: alertPath,
- ...newAlertParams,
- prometheus_metric_id: '5',
- });
-
- expect(mockUpdateAlert).toHaveBeenCalledWith(alertPath, newAlertParams);
- });
-
- it('deletes an alert with an appropriate handler', () => {
- const alertParams = { alert_path: alertPath, operator: '>', threshold: 42 };
- mockReadAlert.mockResolvedValue(alertParams);
- mockDeleteAlert.mockResolvedValue({});
- createComponent({
- ...propsWithAlert,
- alertsToManage: {
- [alertPath]: {
- alert_path: alertPath,
- operator: '>',
- threshold: 42,
- metricId: '5',
- },
- },
- });
-
- findWidgetForm().vm.$emit('delete', { alert: alertPath });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(mockDeleteAlert).toHaveBeenCalledWith(alertPath);
- expect(findAlertErrorMessage().exists()).toBe(false);
- });
- });
-
- describe('when delete fails', () => {
- beforeEach(() => {
- const alertParams = { alert_path: alertPath, operator: '>', threshold: 42 };
- mockReadAlert.mockResolvedValue(alertParams);
- mockDeleteAlert.mockRejectedValue();
-
- createComponent({
- ...propsWithAlert,
- alertsToManage: {
- [alertPath]: {
- alert_path: alertPath,
- operator: '>',
- threshold: 42,
- metricId: '5',
- },
- },
- });
-
- findWidgetForm().vm.$emit('delete', { alert: alertPath });
- return wrapper.vm.$nextTick();
- });
-
- it('shows error message', () => {
- expect(findAlertErrorMessage().text()).toEqual('Error deleting alert');
- });
-
- it('dismisses error message on cancel', () => {
- findWidgetForm().vm.$emit('cancel');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findAlertErrorMessage().exists()).toBe(false);
- });
- });
- });
-});
diff --git a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
index 47b6c463377..aaa0a91ffe0 100644
--- a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
+++ b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
@@ -8,8 +8,6 @@ exports[`Dashboard template matches the default snapshot 1`] = `
metricsdashboardbasepath="/monitoring/monitor-project/-/environments/1/metrics"
metricsendpoint="/monitoring/monitor-project/-/environments/1/additional_metrics.json"
>
- <alerts-deprecation-warning-stub />
-
<div
class="prometheus-graphs-header d-sm-flex flex-sm-wrap pt-2 pr-1 pb-0 pl-2 border-bottom bg-gray-light"
>
diff --git a/spec/frontend/monitoring/components/alert_widget_form_spec.js b/spec/frontend/monitoring/components/alert_widget_form_spec.js
deleted file mode 100644
index e0ef1040f6b..00000000000
--- a/spec/frontend/monitoring/components/alert_widget_form_spec.js
+++ /dev/null
@@ -1,242 +0,0 @@
-import { GlLink } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import INVALID_URL from '~/lib/utils/invalid_url';
-import AlertWidgetForm from '~/monitoring/components/alert_widget_form.vue';
-import ModalStub from '../stubs/modal_stub';
-
-describe('AlertWidgetForm', () => {
- let wrapper;
-
- const metricId = '8';
- const alertPath = 'alert';
- const relevantQueries = [{ metricId, alert_path: alertPath, label: 'alert-label' }];
- const dataTrackingOptions = {
- create: { action: 'click_button', label: 'create_alert' },
- delete: { action: 'click_button', label: 'delete_alert' },
- update: { action: 'click_button', label: 'update_alert' },
- };
-
- const defaultProps = {
- disabled: false,
- relevantQueries,
- modalId: 'alert-modal-1',
- };
-
- const propsWithAlertData = {
- ...defaultProps,
- alertsToManage: {
- alert: {
- alert_path: alertPath,
- operator: '<',
- threshold: 5,
- metricId,
- runbookUrl: INVALID_URL,
- },
- },
- configuredAlert: metricId,
- };
-
- function createComponent(props = {}) {
- const propsData = {
- ...defaultProps,
- ...props,
- };
-
- wrapper = shallowMount(AlertWidgetForm, {
- propsData,
- stubs: {
- GlModal: ModalStub,
- },
- });
- }
-
- const modal = () => wrapper.find(ModalStub);
- const modalTitle = () => modal().attributes('title');
- const submitButton = () => modal().find(GlLink);
- const findRunbookField = () => modal().find('[data-testid="alertRunbookField"]');
- const findThresholdField = () => modal().find('[data-qa-selector="alert_threshold_field"]');
- const submitButtonTrackingOpts = () =>
- JSON.parse(submitButton().attributes('data-tracking-options'));
- const stubEvent = { preventDefault: jest.fn() };
-
- afterEach(() => {
- if (wrapper) wrapper.destroy();
- });
-
- it('disables the form when disabled prop is set', () => {
- createComponent({ disabled: true });
-
- expect(modal().attributes('ok-disabled')).toBe('true');
- });
-
- it('disables the form if no query is selected', () => {
- createComponent();
-
- expect(modal().attributes('ok-disabled')).toBe('true');
- });
-
- it('shows correct title and button text', () => {
- createComponent();
-
- expect(modalTitle()).toBe('Add alert');
- expect(submitButton().text()).toBe('Add');
- });
-
- it('sets tracking options for create alert', () => {
- createComponent();
-
- expect(submitButtonTrackingOpts()).toEqual(dataTrackingOptions.create);
- });
-
- it('emits a "create" event when form submitted without existing alert', async () => {
- createComponent(defaultProps);
-
- modal().vm.$emit('shown');
-
- findThresholdField().vm.$emit('input', 900);
- findRunbookField().vm.$emit('input', INVALID_URL);
-
- modal().vm.$emit('ok', stubEvent);
-
- expect(wrapper.emitted().create[0]).toEqual([
- {
- alert: undefined,
- operator: '>',
- threshold: 900,
- prometheus_metric_id: '8',
- runbookUrl: INVALID_URL,
- },
- ]);
- });
-
- it('resets form when modal is dismissed (hidden)', () => {
- createComponent(defaultProps);
-
- modal().vm.$emit('shown');
-
- findThresholdField().vm.$emit('input', 800);
- findRunbookField().vm.$emit('input', INVALID_URL);
-
- modal().vm.$emit('hidden');
-
- expect(wrapper.vm.selectedAlert).toEqual({});
- expect(wrapper.vm.operator).toBe(null);
- expect(wrapper.vm.threshold).toBe(null);
- expect(wrapper.vm.prometheusMetricId).toBe(null);
- expect(wrapper.vm.runbookUrl).toBe(null);
- });
-
- it('sets selectedAlert to the provided configuredAlert on modal show', () => {
- createComponent(propsWithAlertData);
-
- modal().vm.$emit('shown');
-
- expect(wrapper.vm.selectedAlert).toEqual(propsWithAlertData.alertsToManage[alertPath]);
- });
-
- it('sets selectedAlert to the first relevantQueries if there is only one option on modal show', () => {
- createComponent({
- ...propsWithAlertData,
- configuredAlert: '',
- });
-
- modal().vm.$emit('shown');
-
- expect(wrapper.vm.selectedAlert).toEqual(propsWithAlertData.alertsToManage[alertPath]);
- });
-
- it('does not set selectedAlert to the first relevantQueries if there is more than one option on modal show', () => {
- createComponent({
- relevantQueries: [
- {
- metricId: '8',
- alertPath: 'alert',
- label: 'alert-label',
- },
- {
- metricId: '9',
- alertPath: 'alert',
- label: 'alert-label',
- },
- ],
- });
-
- modal().vm.$emit('shown');
-
- expect(wrapper.vm.selectedAlert).toEqual({});
- });
-
- describe('with existing alert', () => {
- beforeEach(() => {
- createComponent(propsWithAlertData);
-
- modal().vm.$emit('shown');
- });
-
- it('sets tracking options for delete alert', () => {
- expect(submitButtonTrackingOpts()).toEqual(dataTrackingOptions.delete);
- });
-
- it('updates button text', () => {
- expect(modalTitle()).toBe('Edit alert');
- expect(submitButton().text()).toBe('Delete');
- });
-
- it('emits "delete" event when form values unchanged', () => {
- modal().vm.$emit('ok', stubEvent);
-
- expect(wrapper.emitted().delete[0]).toEqual([
- {
- alert: 'alert',
- operator: '<',
- threshold: 5,
- prometheus_metric_id: '8',
- runbookUrl: INVALID_URL,
- },
- ]);
- });
- });
-
- it('emits "update" event when form changed', () => {
- const updatedRunbookUrl = `${INVALID_URL}/test`;
-
- createComponent(propsWithAlertData);
-
- modal().vm.$emit('shown');
-
- findRunbookField().vm.$emit('input', updatedRunbookUrl);
- findThresholdField().vm.$emit('input', 11);
-
- modal().vm.$emit('ok', stubEvent);
-
- expect(wrapper.emitted().update[0]).toEqual([
- {
- alert: 'alert',
- operator: '<',
- threshold: 11,
- prometheus_metric_id: '8',
- runbookUrl: updatedRunbookUrl,
- },
- ]);
- });
-
- it('sets tracking options for update alert', async () => {
- createComponent(propsWithAlertData);
-
- modal().vm.$emit('shown');
-
- findThresholdField().vm.$emit('input', 11);
-
- await wrapper.vm.$nextTick();
-
- expect(submitButtonTrackingOpts()).toEqual(dataTrackingOptions.update);
- });
-
- describe('alert runbooks', () => {
- it('shows the runbook field', () => {
- createComponent();
-
- expect(findRunbookField().exists()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/monitoring/components/charts/anomaly_spec.js b/spec/frontend/monitoring/components/charts/anomaly_spec.js
index c44fd8dce33..8dc6132709e 100644
--- a/spec/frontend/monitoring/components/charts/anomaly_spec.js
+++ b/spec/frontend/monitoring/components/charts/anomaly_spec.js
@@ -159,10 +159,6 @@ describe('Anomaly chart component', () => {
const { deploymentData } = getTimeSeriesProps();
expect(deploymentData).toEqual(anomalyDeploymentData);
});
- it('"thresholds" keeps the same value', () => {
- const { thresholds } = getTimeSeriesProps();
- expect(thresholds).toEqual(inputThresholds);
- });
it('"projectPath" keeps the same value', () => {
const { projectPath } = getTimeSeriesProps();
expect(projectPath).toEqual(mockProjectPath);
diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js
index ea6e4f4a5ed..27f7489aa49 100644
--- a/spec/frontend/monitoring/components/charts/time_series_spec.js
+++ b/spec/frontend/monitoring/components/charts/time_series_spec.js
@@ -643,7 +643,6 @@ describe('Time series component', () => {
expect(props.data).toBe(wrapper.vm.chartData);
expect(props.option).toBe(wrapper.vm.chartOptions);
expect(props.formatTooltipText).toBe(wrapper.vm.formatTooltipText);
- expect(props.thresholds).toBe(wrapper.vm.thresholds);
});
it('receives a tooltip title', () => {
diff --git a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
index 8af6075a416..400ac2e8f85 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
@@ -28,7 +28,6 @@ describe('dashboard invalid url parameters', () => {
},
},
options,
- provide: { hasManagedPrometheus: false },
});
};
diff --git a/spec/frontend/monitoring/components/dashboard_panel_spec.js b/spec/frontend/monitoring/components/dashboard_panel_spec.js
index c8951dff9ed..9a73dc820af 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_spec.js
@@ -5,7 +5,6 @@ import Vuex from 'vuex';
import { setTestTimeout } from 'helpers/timeout';
import axios from '~/lib/utils/axios_utils';
import invalidUrl from '~/lib/utils/invalid_url';
-import AlertWidget from '~/monitoring/components/alert_widget.vue';
import MonitorAnomalyChart from '~/monitoring/components/charts/anomaly.vue';
import MonitorBarChart from '~/monitoring/components/charts/bar.vue';
@@ -28,7 +27,6 @@ import {
barGraphData,
} from '../graph_data';
import {
- mockAlert,
mockLogsHref,
mockLogsPath,
mockNamespace,
@@ -56,7 +54,6 @@ describe('Dashboard Panel', () => {
const findCtxMenu = () => wrapper.find({ ref: 'contextualMenu' });
const findMenuItems = () => wrapper.findAll(GlDropdownItem);
const findMenuItemByText = (text) => findMenuItems().filter((i) => i.text() === text);
- const findAlertsWidget = () => wrapper.find(AlertWidget);
const createWrapper = (props, { mountFn = shallowMount, ...options } = {}) => {
wrapper = mountFn(DashboardPanel, {
@@ -80,9 +77,6 @@ describe('Dashboard Panel', () => {
});
};
- const setMetricsSavedToDb = (val) =>
- monitoringDashboard.getters.metricsSavedToDb.mockReturnValue(val);
-
beforeEach(() => {
setTestTimeout(1000);
@@ -601,42 +595,6 @@ describe('Dashboard Panel', () => {
});
});
- describe('panel alerts', () => {
- beforeEach(() => {
- mockGetterReturnValue('metricsSavedToDb', []);
-
- createWrapper();
- });
-
- describe.each`
- desc | metricsSavedToDb | props | isShown
- ${'with permission and no metrics in db'} | ${[]} | ${{}} | ${false}
- ${'with permission and related metrics in db'} | ${[graphData.metrics[0].metricId]} | ${{}} | ${true}
- ${'without permission and related metrics in db'} | ${[graphData.metrics[0].metricId]} | ${{ prometheusAlertsAvailable: false }} | ${false}
- ${'with permission and unrelated metrics in db'} | ${['another_metric_id']} | ${{}} | ${false}
- `('$desc', ({ metricsSavedToDb, isShown, props }) => {
- const showsDesc = isShown ? 'shows' : 'does not show';
-
- beforeEach(() => {
- setMetricsSavedToDb(metricsSavedToDb);
- createWrapper({
- alertsEndpoint: '/endpoint',
- prometheusAlertsAvailable: true,
- ...props,
- });
- return wrapper.vm.$nextTick();
- });
-
- it(`${showsDesc} alert widget`, () => {
- expect(findAlertsWidget().exists()).toBe(isShown);
- });
-
- it(`${showsDesc} alert configuration`, () => {
- expect(findMenuItemByText('Alerts').exists()).toBe(isShown);
- });
- });
- });
-
describe('When graphData contains links', () => {
const findManageLinksItem = () => wrapper.find({ ref: 'manageLinksItem' });
const mockLinks = [
@@ -730,13 +688,6 @@ describe('Dashboard Panel', () => {
describe('Runbook url', () => {
const findRunbookLinks = () => wrapper.findAll('[data-testid="runbookLink"]');
- const { metricId } = graphData.metrics[0];
- const { alert_path: alertPath } = mockAlert;
-
- const mockRunbookAlert = {
- ...mockAlert,
- metricId,
- };
beforeEach(() => {
mockGetterReturnValue('metricsSavedToDb', []);
@@ -747,62 +698,5 @@ describe('Dashboard Panel', () => {
expect(findRunbookLinks().length).toBe(0);
});
-
- describe('when alerts are present', () => {
- beforeEach(() => {
- setMetricsSavedToDb([metricId]);
-
- createWrapper({
- alertsEndpoint: '/endpoint',
- prometheusAlertsAvailable: true,
- });
- });
-
- it('does not show a runbook link when a runbook is not set', async () => {
- findAlertsWidget().vm.$emit('setAlerts', alertPath, {
- ...mockRunbookAlert,
- runbookUrl: '',
- });
-
- await wrapper.vm.$nextTick();
-
- expect(findRunbookLinks().length).toBe(0);
- });
-
- it('shows a runbook link when a runbook is set', async () => {
- findAlertsWidget().vm.$emit('setAlerts', alertPath, mockRunbookAlert);
-
- await wrapper.vm.$nextTick();
-
- expect(findRunbookLinks().length).toBe(1);
- expect(findRunbookLinks().at(0).attributes('href')).toBe(invalidUrl);
- });
- });
-
- describe('managed alert deprecation feature flag', () => {
- beforeEach(() => {
- setMetricsSavedToDb([metricId]);
- });
-
- it('shows alerts when alerts are not deprecated', () => {
- createWrapper(
- { alertsEndpoint: '/endpoint', prometheusAlertsAvailable: true },
- { provide: { glFeatures: { managedAlertsDeprecation: false } } },
- );
-
- expect(findAlertsWidget().exists()).toBe(true);
- expect(findMenuItemByText('Alerts').exists()).toBe(true);
- });
-
- it('hides alerts when alerts are deprecated', () => {
- createWrapper(
- { alertsEndpoint: '/endpoint', prometheusAlertsAvailable: true },
- { provide: { glFeatures: { managedAlertsDeprecation: true } } },
- );
-
- expect(findAlertsWidget().exists()).toBe(false);
- expect(findMenuItemByText('Alerts').exists()).toBe(false);
- });
- });
});
});
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index f899580b3df..9331048bce3 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -46,7 +46,6 @@ describe('Dashboard', () => {
stubs: {
DashboardHeader,
},
- provide: { hasManagedPrometheus: false },
...options,
});
};
@@ -60,9 +59,6 @@ describe('Dashboard', () => {
'dashboard-panel': true,
'dashboard-header': DashboardHeader,
},
- provide: {
- hasManagedPrometheus: false,
- },
...options,
});
};
@@ -412,7 +408,7 @@ describe('Dashboard', () => {
});
});
- describe('when all requests have been commited by the store', () => {
+ describe('when all requests have been committed by the store', () => {
beforeEach(() => {
store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, {
currentEnvironmentName: 'production',
@@ -460,7 +456,7 @@ describe('Dashboard', () => {
it('shows the links section', () => {
expect(wrapper.vm.shouldShowLinksSection).toBe(true);
- expect(wrapper.find(LinksSection)).toExist();
+ expect(wrapper.findComponent(LinksSection).exists()).toBe(true);
});
});
@@ -807,29 +803,4 @@ describe('Dashboard', () => {
expect(dashboardPanel.exists()).toBe(true);
});
});
-
- describe('alerts deprecation', () => {
- beforeEach(() => {
- setupStoreWithData(store);
- });
-
- const findDeprecationNotice = () => wrapper.findByTestId('alerts-deprecation-warning');
-
- it.each`
- managedAlertsDeprecation | hasManagedPrometheus | isVisible
- ${false} | ${false} | ${false}
- ${false} | ${true} | ${true}
- ${true} | ${false} | ${false}
- ${true} | ${true} | ${false}
- `(
- 'when the deprecation feature flag is $managedAlertsDeprecation and has managed prometheus is $hasManagedPrometheus',
- ({ hasManagedPrometheus, managedAlertsDeprecation, isVisible }) => {
- createMountedWrapper(
- {},
- { provide: { hasManagedPrometheus, glFeatures: { managedAlertsDeprecation } } },
- );
- expect(findDeprecationNotice().exists()).toBe(isVisible);
- },
- );
- });
});
diff --git a/spec/frontend/monitoring/components/dashboard_url_time_spec.js b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
index bea263f143a..e6785f34597 100644
--- a/spec/frontend/monitoring/components/dashboard_url_time_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
@@ -31,7 +31,6 @@ describe('dashboard invalid url parameters', () => {
store,
stubs: { 'graph-group': true, 'dashboard-panel': true, 'dashboard-header': DashboardHeader },
...options,
- provide: { hasManagedPrometheus: false },
});
};
diff --git a/spec/frontend/monitoring/components/links_section_spec.js b/spec/frontend/monitoring/components/links_section_spec.js
index 8fc287c50e4..e37abf6722a 100644
--- a/spec/frontend/monitoring/components/links_section_spec.js
+++ b/spec/frontend/monitoring/components/links_section_spec.js
@@ -1,5 +1,7 @@
import { GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+
import LinksSection from '~/monitoring/components/links_section.vue';
import { createStore } from '~/monitoring/stores';
@@ -26,12 +28,12 @@ describe('Links Section component', () => {
createShallowWrapper();
});
- it('does not render a section if no links are present', () => {
+ it('does not render a section if no links are present', async () => {
setState();
- return wrapper.vm.$nextTick(() => {
- expect(findLinks()).not.toExist();
- });
+ await nextTick();
+
+ expect(findLinks().length).toBe(0);
});
it('renders a link inside a section', () => {
diff --git a/spec/frontend/monitoring/components/variables/text_field_spec.js b/spec/frontend/monitoring/components/variables/text_field_spec.js
index 28e02dff4bf..c879803fddd 100644
--- a/spec/frontend/monitoring/components/variables/text_field_spec.js
+++ b/spec/frontend/monitoring/components/variables/text_field_spec.js
@@ -15,12 +15,12 @@ describe('Text variable component', () => {
});
};
- const findInput = () => wrapper.find(GlFormInput);
+ const findInput = () => wrapper.findComponent(GlFormInput);
it('renders a text input when all props are passed', () => {
createShallowWrapper();
- expect(findInput()).toExist();
+ expect(findInput().exists()).toBe(true);
});
it('always has a default value', () => {
diff --git a/spec/frontend/monitoring/pages/dashboard_page_spec.js b/spec/frontend/monitoring/pages/dashboard_page_spec.js
index dbe9cc21ad5..c5a8b50ee60 100644
--- a/spec/frontend/monitoring/pages/dashboard_page_spec.js
+++ b/spec/frontend/monitoring/pages/dashboard_page_spec.js
@@ -29,7 +29,7 @@ describe('monitoring/pages/dashboard_page', () => {
});
};
- const findDashboardComponent = () => wrapper.find(Dashboard);
+ const findDashboardComponent = () => wrapper.findComponent(Dashboard);
beforeEach(() => {
buildRouter();
@@ -60,7 +60,7 @@ describe('monitoring/pages/dashboard_page', () => {
smallEmptyState: false,
};
- expect(findDashboardComponent()).toExist();
+ expect(findDashboardComponent().exists()).toBe(true);
expect(allProps).toMatchObject(findDashboardComponent().props());
});
});
diff --git a/spec/frontend/monitoring/router_spec.js b/spec/frontend/monitoring/router_spec.js
index 2a712d4361f..b027d60f61e 100644
--- a/spec/frontend/monitoring/router_spec.js
+++ b/spec/frontend/monitoring/router_spec.js
@@ -20,8 +20,6 @@ const MockApp = {
template: `<router-view :dashboard-props="dashboardProps"/>`,
};
-const provide = { hasManagedPrometheus: false };
-
describe('Monitoring router', () => {
let router;
let store;
@@ -39,7 +37,6 @@ describe('Monitoring router', () => {
localVue,
store,
router,
- provide,
});
};
diff --git a/spec/frontend/notes/components/discussion_counter_spec.js b/spec/frontend/notes/components/discussion_counter_spec.js
index 9db0f823d84..c454d502beb 100644
--- a/spec/frontend/notes/components/discussion_counter_spec.js
+++ b/spec/frontend/notes/components/discussion_counter_spec.js
@@ -53,7 +53,7 @@ describe('DiscussionCounter component', () => {
describe('has no resolvable discussions', () => {
it('does not render', () => {
- store.commit(types.SET_INITIAL_DISCUSSIONS, [{ ...discussionMock, resolvable: false }]);
+ store.commit(types.ADD_OR_UPDATE_DISCUSSIONS, [{ ...discussionMock, resolvable: false }]);
store.dispatch('updateResolvableDiscussionsCounts');
wrapper = shallowMount(DiscussionCounter, { store, localVue });
@@ -64,7 +64,7 @@ describe('DiscussionCounter component', () => {
describe('has resolvable discussions', () => {
const updateStore = (note = {}) => {
discussionMock.notes[0] = { ...discussionMock.notes[0], ...note };
- store.commit(types.SET_INITIAL_DISCUSSIONS, [discussionMock]);
+ store.commit(types.ADD_OR_UPDATE_DISCUSSIONS, [discussionMock]);
store.dispatch('updateResolvableDiscussionsCounts');
};
@@ -97,7 +97,7 @@ describe('DiscussionCounter component', () => {
let toggleAllButton;
const updateStoreWithExpanded = (expanded) => {
const discussion = { ...discussionMock, expanded };
- store.commit(types.SET_INITIAL_DISCUSSIONS, [discussion]);
+ store.commit(types.ADD_OR_UPDATE_DISCUSSIONS, [discussion]);
store.dispatch('updateResolvableDiscussionsCounts');
wrapper = shallowMount(DiscussionCounter, { store, localVue });
toggleAllButton = wrapper.find('.toggle-all-discussions-btn');
diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js
index 59ac75f00e6..ff840a55535 100644
--- a/spec/frontend/notes/components/discussion_notes_spec.js
+++ b/spec/frontend/notes/components/discussion_notes_spec.js
@@ -1,6 +1,7 @@
import { getByRole } from '@testing-library/dom';
import { shallowMount, mount } from '@vue/test-utils';
import '~/behaviors/markdown/render_gfm';
+import { discussionIntersectionObserverHandlerFactory } from '~/diffs/utils/discussions';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import NoteableNote from '~/notes/components/noteable_note.vue';
import { SYSTEM_NOTE } from '~/notes/constants';
@@ -26,6 +27,9 @@ describe('DiscussionNotes', () => {
const createComponent = (props, mountingMethod = shallowMount) => {
wrapper = mountingMethod(DiscussionNotes, {
store,
+ provide: {
+ discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
+ },
propsData: {
discussion: discussionMock,
isExpanded: false,
diff --git a/spec/frontend/notes/components/multiline_comment_form_spec.js b/spec/frontend/notes/components/multiline_comment_form_spec.js
index b6d603c6358..b027a261c15 100644
--- a/spec/frontend/notes/components/multiline_comment_form_spec.js
+++ b/spec/frontend/notes/components/multiline_comment_form_spec.js
@@ -50,18 +50,6 @@ describe('MultilineCommentForm', () => {
expect(wrapper.vm.commentLineStart).toEqual(lineRange.start);
expect(setSelectedCommentPosition).toHaveBeenCalled();
});
-
- it('sets commentLineStart to selectedCommentPosition', () => {
- const notes = {
- selectedCommentPosition: {
- start: { ...testLine },
- },
- };
- const wrapper = createWrapper({}, { notes });
-
- expect(wrapper.vm.commentLineStart).toEqual(wrapper.vm.selectedCommentPosition.start);
- expect(setSelectedCommentPosition).not.toHaveBeenCalled();
- });
});
describe('destroyed', () => {
diff --git a/spec/frontend/notes/components/note_body_spec.js b/spec/frontend/notes/components/note_body_spec.js
index 40251244423..4e345c9ac8d 100644
--- a/spec/frontend/notes/components/note_body_spec.js
+++ b/spec/frontend/notes/components/note_body_spec.js
@@ -58,7 +58,6 @@ describe('issue_note_body component', () => {
it('adds autosave', () => {
const autosaveKey = `autosave/Note/${note.noteable_type}/${note.id}`;
- expect(vm.autosave).toExist();
expect(vm.autosave.key).toEqual(autosaveKey);
});
});
diff --git a/spec/frontend/notes/components/note_form_spec.js b/spec/frontend/notes/components/note_form_spec.js
index abc888cd245..48bfd6eac5a 100644
--- a/spec/frontend/notes/components/note_form_spec.js
+++ b/spec/frontend/notes/components/note_form_spec.js
@@ -1,3 +1,4 @@
+import { GlLink } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import batchComments from '~/batch_comments/stores/modules/batch_comments';
@@ -91,6 +92,7 @@ describe('issue_note_form component', () => {
expect(conflictWarning.exists()).toBe(true);
expect(conflictWarning.text().replace(/\s+/g, ' ').trim()).toBe(message);
+ expect(conflictWarning.find(GlLink).attributes('href')).toBe('#note_545');
});
});
diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js
index 727ef02dcbb..6aab60edc4e 100644
--- a/spec/frontend/notes/components/noteable_discussion_spec.js
+++ b/spec/frontend/notes/components/noteable_discussion_spec.js
@@ -3,6 +3,7 @@ import { nextTick } from 'vue';
import discussionWithTwoUnresolvedNotes from 'test_fixtures/merge_requests/resolved_diff_discussion.json';
import { trimText } from 'helpers/text_helper';
import mockDiffFile from 'jest/diffs/mock_data/diff_file';
+import { discussionIntersectionObserverHandlerFactory } from '~/diffs/utils/discussions';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
@@ -31,6 +32,9 @@ describe('noteable_discussion component', () => {
wrapper = mount(NoteableDiscussion, {
store,
+ provide: {
+ discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
+ },
propsData: { discussion: discussionMock },
});
});
@@ -167,6 +171,9 @@ describe('noteable_discussion component', () => {
wrapper = mount(NoteableDiscussion, {
store,
+ provide: {
+ discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
+ },
propsData: { discussion: discussionMock },
});
});
@@ -185,6 +192,9 @@ describe('noteable_discussion component', () => {
wrapper = mount(NoteableDiscussion, {
store,
+ provide: {
+ discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
+ },
propsData: { discussion: discussionMock },
});
});
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index 241a89b2218..b3dbc26878f 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -2,11 +2,14 @@ import { mount, shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import Vue from 'vue';
+import setWindowLocation from 'helpers/set_window_location_helper';
import { setTestTimeout } from 'helpers/timeout';
+import waitForPromises from 'helpers/wait_for_promises';
import DraftNote from '~/batch_comments/components/draft_note.vue';
import batchComments from '~/batch_comments/stores/modules/batch_comments';
import axios from '~/lib/utils/axios_utils';
import * as urlUtility from '~/lib/utils/url_utility';
+import { discussionIntersectionObserverHandlerFactory } from '~/diffs/utils/discussions';
import CommentForm from '~/notes/components/comment_form.vue';
import NotesApp from '~/notes/components/notes_app.vue';
import * as constants from '~/notes/constants';
@@ -76,6 +79,9 @@ describe('note_app', () => {
</div>`,
},
{
+ provide: {
+ discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
+ },
propsData,
store,
},
@@ -430,4 +436,57 @@ describe('note_app', () => {
);
});
});
+
+ describe('fetching discussions', () => {
+ describe('when note anchor is not present', () => {
+ it('does not include extra query params', async () => {
+ wrapper = shallowMount(NotesApp, { propsData, store: createStore() });
+ await waitForPromises();
+
+ expect(axiosMock.history.get[0].params).toBeUndefined();
+ });
+ });
+
+ describe('when note anchor is present', () => {
+ const mountWithNotesFilter = (notesFilter) =>
+ shallowMount(NotesApp, {
+ propsData: {
+ ...propsData,
+ notesData: {
+ ...propsData.notesData,
+ notesFilter,
+ },
+ },
+ store: createStore(),
+ });
+
+ beforeEach(() => {
+ setWindowLocation('#note_1');
+ });
+
+ it('does not include extra query params when filter is undefined', async () => {
+ wrapper = mountWithNotesFilter(undefined);
+ await waitForPromises();
+
+ expect(axiosMock.history.get[0].params).toBeUndefined();
+ });
+
+ it('does not include extra query params when filter is already set to default', async () => {
+ wrapper = mountWithNotesFilter(constants.DISCUSSION_FILTERS_DEFAULT_VALUE);
+ await waitForPromises();
+
+ expect(axiosMock.history.get[0].params).toBeUndefined();
+ });
+
+ it('includes extra query params when filter is not set to default', async () => {
+ wrapper = mountWithNotesFilter(constants.COMMENTS_ONLY_FILTER_VALUE);
+ await waitForPromises();
+
+ expect(axiosMock.history.get[0].params).toEqual({
+ notes_filter: constants.DISCUSSION_FILTERS_DEFAULT_VALUE,
+ persist_filter: false,
+ });
+ });
+ });
+ });
});
diff --git a/spec/frontend/notes/mixins/discussion_navigation_spec.js b/spec/frontend/notes/mixins/discussion_navigation_spec.js
index 6a6e47ffcc5..26a072b82f8 100644
--- a/spec/frontend/notes/mixins/discussion_navigation_spec.js
+++ b/spec/frontend/notes/mixins/discussion_navigation_spec.js
@@ -1,4 +1,5 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { nextTick } from 'vue';
import Vuex from 'vuex';
import { setHTMLFixture } from 'helpers/fixtures';
import createEventHub from '~/helpers/event_hub_factory';
@@ -7,12 +8,15 @@ import eventHub from '~/notes/event_hub';
import discussionNavigation from '~/notes/mixins/discussion_navigation';
import notesModule from '~/notes/stores/modules';
+let scrollToFile;
const discussion = (id, index) => ({
id,
resolvable: index % 2 === 0,
active: true,
notes: [{}],
diff_discussion: true,
+ position: { new_line: 1, old_line: 1 },
+ diff_file: { file_path: 'test.js' },
});
const createDiscussions = () => [...'abcde'].map(discussion);
const createComponent = () => ({
@@ -45,6 +49,7 @@ describe('Discussion navigation mixin', () => {
jest.spyOn(utils, 'scrollToElement');
expandDiscussion = jest.fn();
+ scrollToFile = jest.fn();
const { actions, ...notesRest } = notesModule();
store = new Vuex.Store({
modules: {
@@ -52,6 +57,10 @@ describe('Discussion navigation mixin', () => {
...notesRest,
actions: { ...actions, expandDiscussion },
},
+ diffs: {
+ namespaced: true,
+ actions: { scrollToFile },
+ },
},
});
store.state.notes.discussions = createDiscussions();
@@ -136,6 +145,7 @@ describe('Discussion navigation mixin', () => {
it('scrolls to element', () => {
expect(utils.scrollToElement).toHaveBeenCalledWith(
findDiscussion('div.discussion', expected),
+ { behavior: 'smooth' },
);
});
});
@@ -163,6 +173,7 @@ describe('Discussion navigation mixin', () => {
expect(utils.scrollToElementWithContext).toHaveBeenCalledWith(
findDiscussion('ul.notes', expected),
+ { behavior: 'smooth' },
);
});
});
@@ -203,10 +214,60 @@ describe('Discussion navigation mixin', () => {
it('scrolls to discussion', () => {
expect(utils.scrollToElement).toHaveBeenCalledWith(
findDiscussion('div.discussion', expected),
+ { behavior: 'smooth' },
);
});
});
});
});
+
+ describe.each`
+ diffsVirtualScrolling
+ ${false}
+ ${true}
+ `('virtual scrolling feature is $diffsVirtualScrolling', ({ diffsVirtualScrolling }) => {
+ beforeEach(() => {
+ window.gon = { features: { diffsVirtualScrolling } };
+
+ jest.spyOn(store, 'dispatch');
+
+ store.state.notes.currentDiscussionId = 'a';
+ window.location.hash = 'test';
+ });
+
+ afterEach(() => {
+ window.gon = {};
+ window.location.hash = '';
+ });
+
+ it('resets location hash if diffsVirtualScrolling flag is true', async () => {
+ wrapper.vm.jumpToNextDiscussion();
+
+ await nextTick();
+
+ expect(window.location.hash).toBe(diffsVirtualScrolling ? '' : '#test');
+ });
+
+ it.each`
+ tabValue | hashValue
+ ${'diffs'} | ${false}
+ ${'show'} | ${!diffsVirtualScrolling}
+ ${'other'} | ${!diffsVirtualScrolling}
+ `(
+ 'calls scrollToFile with setHash as $hashValue when the tab is $tabValue',
+ async ({ hashValue, tabValue }) => {
+ window.mrTabs.currentAction = tabValue;
+
+ wrapper.vm.jumpToNextDiscussion();
+
+ await nextTick();
+
+ expect(store.dispatch).toHaveBeenCalledWith('diffs/scrollToFile', {
+ path: 'test.js',
+ setHash: hashValue,
+ });
+ },
+ );
+ });
});
});
diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js
index 2ff65d3f47e..bbe074f0105 100644
--- a/spec/frontend/notes/stores/actions_spec.js
+++ b/spec/frontend/notes/stores/actions_spec.js
@@ -119,7 +119,7 @@ describe('Actions Notes Store', () => {
actions.setInitialNotes,
[individualNote],
{ notes: [] },
- [{ type: 'SET_INITIAL_DISCUSSIONS', payload: [individualNote] }],
+ [{ type: 'ADD_OR_UPDATE_DISCUSSIONS', payload: [individualNote] }],
[],
done,
);
@@ -1395,4 +1395,93 @@ describe('Actions Notes Store', () => {
);
});
});
+
+ describe('fetchDiscussions', () => {
+ const discussion = { notes: [] };
+
+ afterEach(() => {
+ window.gon = {};
+ });
+
+ it('updates the discussions and dispatches `updateResolvableDiscussionsCounts`', (done) => {
+ axiosMock.onAny().reply(200, { discussion });
+ testAction(
+ actions.fetchDiscussions,
+ {},
+ null,
+ [
+ { type: mutationTypes.ADD_OR_UPDATE_DISCUSSIONS, payload: { discussion } },
+ { type: mutationTypes.SET_FETCHING_DISCUSSIONS, payload: false },
+ ],
+ [{ type: 'updateResolvableDiscussionsCounts' }],
+ done,
+ );
+ });
+
+ it('dispatches `fetchDiscussionsBatch` action if `paginatedIssueDiscussions` feature flag is enabled', (done) => {
+ window.gon = { features: { paginatedIssueDiscussions: true } };
+
+ testAction(
+ actions.fetchDiscussions,
+ { path: 'test-path', filter: 'test-filter', persistFilter: 'test-persist-filter' },
+ null,
+ [],
+ [
+ {
+ type: 'fetchDiscussionsBatch',
+ payload: {
+ config: {
+ params: { notes_filter: 'test-filter', persist_filter: 'test-persist-filter' },
+ },
+ path: 'test-path',
+ perPage: 20,
+ },
+ },
+ ],
+ done,
+ );
+ });
+ });
+
+ describe('fetchDiscussionsBatch', () => {
+ const discussion = { notes: [] };
+
+ const config = {
+ params: { notes_filter: 'test-filter', persist_filter: 'test-persist-filter' },
+ };
+
+ const actionPayload = { config, path: 'test-path', perPage: 20 };
+
+ it('updates the discussions and dispatches `updateResolvableDiscussionsCounts if there are no headers', (done) => {
+ axiosMock.onAny().reply(200, { discussion }, {});
+ testAction(
+ actions.fetchDiscussionsBatch,
+ actionPayload,
+ null,
+ [
+ { type: mutationTypes.ADD_OR_UPDATE_DISCUSSIONS, payload: { discussion } },
+ { type: mutationTypes.SET_FETCHING_DISCUSSIONS, payload: false },
+ ],
+ [{ type: 'updateResolvableDiscussionsCounts' }],
+ done,
+ );
+ });
+
+ it('dispatches itself if there is `x-next-page-cursor` header', (done) => {
+ axiosMock.onAny().reply(200, { discussion }, { 'x-next-page-cursor': 1 });
+ testAction(
+ actions.fetchDiscussionsBatch,
+ actionPayload,
+ null,
+ [{ type: mutationTypes.ADD_OR_UPDATE_DISCUSSIONS, payload: { discussion } }],
+ [
+ {
+ type: 'fetchDiscussionsBatch',
+ payload: { ...actionPayload, perPage: 30, cursor: 1 },
+ },
+ ],
+ done,
+ );
+ });
+ });
});
diff --git a/spec/frontend/notes/stores/mutation_spec.js b/spec/frontend/notes/stores/mutation_spec.js
index 99e24f724f4..c9e24039b64 100644
--- a/spec/frontend/notes/stores/mutation_spec.js
+++ b/spec/frontend/notes/stores/mutation_spec.js
@@ -159,7 +159,7 @@ describe('Notes Store mutations', () => {
});
});
- describe('SET_INITIAL_DISCUSSIONS', () => {
+ describe('ADD_OR_UPDATE_DISCUSSIONS', () => {
it('should set the initial notes received', () => {
const state = {
discussions: [],
@@ -169,15 +169,17 @@ describe('Notes Store mutations', () => {
individual_note: true,
notes: [
{
+ id: 100,
note: '1',
},
{
+ id: 101,
note: '2',
},
],
};
- mutations.SET_INITIAL_DISCUSSIONS(state, [note, legacyNote]);
+ mutations.ADD_OR_UPDATE_DISCUSSIONS(state, [note, legacyNote]);
expect(state.discussions[0].id).toEqual(note.id);
expect(state.discussions[1].notes[0].note).toBe(legacyNote.notes[0].note);
@@ -190,7 +192,7 @@ describe('Notes Store mutations', () => {
discussions: [],
};
- mutations.SET_INITIAL_DISCUSSIONS(state, [
+ mutations.ADD_OR_UPDATE_DISCUSSIONS(state, [
{
...note,
diff_file: {
@@ -208,7 +210,7 @@ describe('Notes Store mutations', () => {
discussions: [],
};
- mutations.SET_INITIAL_DISCUSSIONS(state, [
+ mutations.ADD_OR_UPDATE_DISCUSSIONS(state, [
{
...note,
diff_file: {
diff --git a/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap b/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
index dbebdeeb452..67e2594d29f 100644
--- a/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
+++ b/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
@@ -2,11 +2,11 @@
exports[`packages_list_app renders 1`] = `
<div>
- <div
- help-url="foo"
+ <infrastructure-title-stub
+ helpurl="foo"
/>
- <div />
+ <infrastructure-search-stub />
<div>
<section
diff --git a/spec/frontend/packages/list/components/packages_list_app_spec.js b/spec/frontend/packages/list/components/packages_list_app_spec.js
index b94192c531c..5f7555a3a2b 100644
--- a/spec/frontend/packages/list/components/packages_list_app_spec.js
+++ b/spec/frontend/packages/list/components/packages_list_app_spec.js
@@ -9,6 +9,7 @@ import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages/list/constants';
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import * as packageUtils from '~/packages_and_registries/shared/utils';
+import InfrastructureSearch from '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue';
jest.mock('~/lib/utils/common_utils');
jest.mock('~/flash');
@@ -26,18 +27,9 @@ describe('packages_list_app', () => {
};
const GlLoadingIcon = { name: 'gl-loading-icon', template: '<div>loading</div>' };
- // we need to manually stub dynamic imported components because shallowMount is not able to stub them automatically. See: https://github.com/vuejs/vue-test-utils/issues/1279
- const PackageSearch = { name: 'PackageSearch', template: '<div></div>' };
- const PackageTitle = { name: 'PackageTitle', template: '<div></div>' };
- const InfrastructureTitle = { name: 'InfrastructureTitle', template: '<div></div>' };
- const InfrastructureSearch = { name: 'InfrastructureSearch', template: '<div></div>' };
-
const emptyListHelpUrl = 'helpUrl';
const findEmptyState = () => wrapper.find(GlEmptyState);
const findListComponent = () => wrapper.find(PackageList);
- const findPackageSearch = () => wrapper.find(PackageSearch);
- const findPackageTitle = () => wrapper.find(PackageTitle);
- const findInfrastructureTitle = () => wrapper.find(InfrastructureTitle);
const findInfrastructureSearch = () => wrapper.find(InfrastructureSearch);
const createStore = (filter = []) => {
@@ -66,10 +58,6 @@ describe('packages_list_app', () => {
PackageList,
GlSprintf,
GlLink,
- PackageSearch,
- PackageTitle,
- InfrastructureTitle,
- InfrastructureSearch,
},
provide,
});
@@ -191,48 +179,23 @@ describe('packages_list_app', () => {
});
});
- describe('Package Search', () => {
+ describe('Search', () => {
it('exists', () => {
mountComponent();
- expect(findPackageSearch().exists()).toBe(true);
+ expect(findInfrastructureSearch().exists()).toBe(true);
});
it('on update fetches data from the store', () => {
mountComponent();
store.dispatch.mockClear();
- findPackageSearch().vm.$emit('update');
+ findInfrastructureSearch().vm.$emit('update');
expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
});
});
- describe('Infrastructure config', () => {
- it('defaults to package registry components', () => {
- mountComponent();
-
- expect(findPackageSearch().exists()).toBe(true);
- expect(findPackageTitle().exists()).toBe(true);
-
- expect(findInfrastructureTitle().exists()).toBe(false);
- expect(findInfrastructureSearch().exists()).toBe(false);
- });
-
- it('mount different component based on the provided values', () => {
- mountComponent({
- titleComponent: 'InfrastructureTitle',
- searchComponent: 'InfrastructureSearch',
- });
-
- expect(findPackageSearch().exists()).toBe(false);
- expect(findPackageTitle().exists()).toBe(false);
-
- expect(findInfrastructureTitle().exists()).toBe(true);
- expect(findInfrastructureSearch().exists()).toBe(true);
- });
- });
-
describe('delete alert handling', () => {
const originalLocation = window.location.href;
const search = `?${SHOW_DELETE_SUCCESS_ALERT}=true`;
diff --git a/spec/frontend/packages/list/components/packages_search_spec.js b/spec/frontend/packages/list/components/packages_search_spec.js
deleted file mode 100644
index 30fad74b493..00000000000
--- a/spec/frontend/packages/list/components/packages_search_spec.js
+++ /dev/null
@@ -1,128 +0,0 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
-import component from '~/packages/list/components/package_search.vue';
-import PackageTypeToken from '~/packages/list/components/tokens/package_type_token.vue';
-import { sortableFields } from '~/packages/list/utils';
-import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
-import UrlSync from '~/vue_shared/components/url_sync.vue';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('Package Search', () => {
- let wrapper;
- let store;
-
- const findRegistrySearch = () => wrapper.findComponent(RegistrySearch);
- const findUrlSync = () => wrapper.findComponent(UrlSync);
-
- const createStore = (isGroupPage) => {
- const state = {
- config: {
- isGroupPage,
- },
- sorting: {
- orderBy: 'version',
- sort: 'desc',
- },
- filter: [],
- };
- store = new Vuex.Store({
- state,
- });
- store.dispatch = jest.fn();
- };
-
- const mountComponent = (isGroupPage = false) => {
- createStore(isGroupPage);
-
- wrapper = shallowMount(component, {
- localVue,
- store,
- stubs: {
- UrlSync,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('has a registry search component', () => {
- mountComponent();
-
- expect(findRegistrySearch().exists()).toBe(true);
- expect(findRegistrySearch().props()).toMatchObject({
- filter: store.state.filter,
- sorting: store.state.sorting,
- tokens: expect.arrayContaining([
- expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
- ]),
- sortableFields: sortableFields(),
- });
- });
-
- it.each`
- isGroupPage | page
- ${false} | ${'project'}
- ${true} | ${'group'}
- `('in a $page page binds the right props', ({ isGroupPage }) => {
- mountComponent(isGroupPage);
-
- expect(findRegistrySearch().props()).toMatchObject({
- filter: store.state.filter,
- sorting: store.state.sorting,
- tokens: expect.arrayContaining([
- expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
- ]),
- sortableFields: sortableFields(isGroupPage),
- });
- });
-
- it('on sorting:changed emits update event and calls vuex setSorting', () => {
- const payload = { sort: 'foo' };
-
- mountComponent();
-
- findRegistrySearch().vm.$emit('sorting:changed', payload);
-
- expect(store.dispatch).toHaveBeenCalledWith('setSorting', payload);
- expect(wrapper.emitted('update')).toEqual([[]]);
- });
-
- it('on filter:changed calls vuex setFilter', () => {
- const payload = ['foo'];
-
- mountComponent();
-
- findRegistrySearch().vm.$emit('filter:changed', payload);
-
- expect(store.dispatch).toHaveBeenCalledWith('setFilter', payload);
- });
-
- it('on filter:submit emits update event', () => {
- mountComponent();
-
- findRegistrySearch().vm.$emit('filter:submit');
-
- expect(wrapper.emitted('update')).toEqual([[]]);
- });
-
- it('has a UrlSync component', () => {
- mountComponent();
-
- expect(findUrlSync().exists()).toBe(true);
- });
-
- it('on query:changed calls updateQuery from UrlSync', () => {
- jest.spyOn(UrlSync.methods, 'updateQuery').mockImplementation(() => {});
-
- mountComponent();
-
- findRegistrySearch().vm.$emit('query:changed');
-
- expect(UrlSync.methods.updateQuery).toHaveBeenCalled();
- });
-});
diff --git a/spec/frontend/packages/list/components/packages_title_spec.js b/spec/frontend/packages/list/components/packages_title_spec.js
deleted file mode 100644
index a17f72e3133..00000000000
--- a/spec/frontend/packages/list/components/packages_title_spec.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '~/packages/list//constants';
-import PackageTitle from '~/packages/list/components/package_title.vue';
-import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
-
-describe('PackageTitle', () => {
- let wrapper;
- let store;
-
- const findTitleArea = () => wrapper.find(TitleArea);
- const findMetadataItem = () => wrapper.find(MetadataItem);
-
- const mountComponent = (propsData = { helpUrl: 'foo' }) => {
- wrapper = shallowMount(PackageTitle, {
- store,
- propsData,
- stubs: {
- TitleArea,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('title area', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findTitleArea().exists()).toBe(true);
- });
-
- it('has the correct props', () => {
- mountComponent();
-
- expect(findTitleArea().props()).toMatchObject({
- title: LIST_TITLE_TEXT,
- infoMessages: [{ text: LIST_INTRO_TEXT, link: 'foo' }],
- });
- });
- });
-
- describe.each`
- count | exist | text
- ${null} | ${false} | ${''}
- ${undefined} | ${false} | ${''}
- ${0} | ${true} | ${'0 Packages'}
- ${1} | ${true} | ${'1 Package'}
- ${2} | ${true} | ${'2 Packages'}
- `('when count is $count metadata item', ({ count, exist, text }) => {
- beforeEach(() => {
- mountComponent({ count, helpUrl: 'foo' });
- });
-
- it(`is ${exist} that it exists`, () => {
- expect(findMetadataItem().exists()).toBe(exist);
- });
-
- if (exist) {
- it('has the correct props', () => {
- expect(findMetadataItem().props()).toMatchObject({
- icon: 'package',
- text,
- });
- });
- }
- });
-});
diff --git a/spec/frontend/packages/list/components/tokens/package_type_token_spec.js b/spec/frontend/packages/list/components/tokens/package_type_token_spec.js
deleted file mode 100644
index b0cbe34f0b9..00000000000
--- a/spec/frontend/packages/list/components/tokens/package_type_token_spec.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import component from '~/packages/list/components/tokens/package_type_token.vue';
-import { PACKAGE_TYPES } from '~/packages/list/constants';
-
-describe('packages_filter', () => {
- let wrapper;
-
- const findFilteredSearchToken = () => wrapper.find(GlFilteredSearchToken);
- const findFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion);
-
- const mountComponent = ({ attrs, listeners } = {}) => {
- wrapper = shallowMount(component, {
- attrs,
- listeners,
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('it binds all of his attrs to filtered search token', () => {
- mountComponent({ attrs: { foo: 'bar' } });
-
- expect(findFilteredSearchToken().attributes('foo')).toBe('bar');
- });
-
- it('it binds all of his events to filtered search token', () => {
- const clickListener = jest.fn();
- mountComponent({ listeners: { click: clickListener } });
-
- findFilteredSearchToken().vm.$emit('click');
-
- expect(clickListener).toHaveBeenCalled();
- });
-
- it.each(PACKAGE_TYPES.map((p, index) => [p, index]))(
- 'displays a suggestion for %p',
- (packageType, index) => {
- mountComponent();
- const item = findFilteredSearchSuggestions().at(index);
- expect(item.text()).toBe(packageType.title);
- expect(item.props('value')).toBe(packageType.type);
- },
- );
-});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap b/spec/frontend/packages_and_registries/container_registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
new file mode 100644
index 00000000000..7044c1285d8
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
@@ -0,0 +1,84 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Registry Breadcrumb when is not rootRoute renders 1`] = `
+<div
+ class="gl-breadcrumbs"
+>
+
+ <ol
+ class="breadcrumb gl-breadcrumb-list"
+ >
+ <li
+ class="breadcrumb-item gl-breadcrumb-item"
+ >
+ <a
+ class=""
+ href="/"
+ target="_self"
+ >
+ <span>
+
+ </span>
+
+ <span
+ class="gl-breadcrumb-separator"
+ data-testid="separator"
+ >
+ <svg
+ aria-hidden="true"
+ class="gl-icon s8"
+ data-testid="angle-right-icon"
+ role="img"
+ >
+ <use
+ href="#angle-right"
+ />
+ </svg>
+ </span>
+ </a>
+ </li>
+ <li
+ class="breadcrumb-item gl-breadcrumb-item"
+ >
+ <a
+ class=""
+ href="#"
+ target="_self"
+ >
+ <span>
+
+ </span>
+
+ <!---->
+ </a>
+ </li>
+ </ol>
+</div>
+`;
+
+exports[`Registry Breadcrumb when is rootRoute renders 1`] = `
+<div
+ class="gl-breadcrumbs"
+>
+
+ <ol
+ class="breadcrumb gl-breadcrumb-list"
+ >
+ <li
+ class="breadcrumb-item gl-breadcrumb-item"
+ >
+ <a
+ class=""
+ href="/"
+ target="_self"
+ >
+ <span>
+
+ </span>
+
+ <!---->
+ </a>
+ </li>
+ </ol>
+</div>
+`;
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_button_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_button_spec.js
new file mode 100644
index 00000000000..6d7bf528495
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_button_spec.js
@@ -0,0 +1,73 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import component from '~/packages_and_registries/container_registry/explorer/components/delete_button.vue';
+
+describe('delete_button', () => {
+ let wrapper;
+
+ const defaultProps = {
+ title: 'Foo title',
+ tooltipTitle: 'Bar tooltipTitle',
+ };
+
+ const findButton = () => wrapper.find(GlButton);
+
+ const mountComponent = (props) => {
+ wrapper = shallowMount(component, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('tooltip', () => {
+ it('the title is controlled by tooltipTitle prop', () => {
+ mountComponent();
+ const tooltip = getBinding(wrapper.element, 'gl-tooltip');
+ expect(tooltip).toBeDefined();
+ expect(tooltip.value.title).toBe(defaultProps.tooltipTitle);
+ });
+
+ it('is disabled when tooltipTitle is disabled', () => {
+ mountComponent({ tooltipDisabled: true });
+ const tooltip = getBinding(wrapper.element, 'gl-tooltip');
+ expect(tooltip.value.disabled).toBe(true);
+ });
+
+ describe('button', () => {
+ it('exists', () => {
+ mountComponent();
+ expect(findButton().exists()).toBe(true);
+ });
+
+ it('has the correct props/attributes bound', () => {
+ mountComponent({ disabled: true });
+ expect(findButton().attributes()).toMatchObject({
+ 'aria-label': 'Foo title',
+ icon: 'remove',
+ title: 'Foo title',
+ variant: 'danger',
+ disabled: 'true',
+ category: 'secondary',
+ });
+ });
+
+ it('emits a delete event', () => {
+ mountComponent();
+ expect(wrapper.emitted('delete')).toEqual(undefined);
+ findButton().vm.$emit('click');
+ expect(wrapper.emitted('delete')).toEqual([[]]);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_image_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_image_spec.js
new file mode 100644
index 00000000000..620c96e8c9e
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_image_spec.js
@@ -0,0 +1,152 @@
+import { shallowMount } from '@vue/test-utils';
+import waitForPromises from 'helpers/wait_for_promises';
+import component from '~/packages_and_registries/container_registry/explorer/components/delete_image.vue';
+import { GRAPHQL_PAGE_SIZE } from '~/packages_and_registries/container_registry/explorer/constants/index';
+import deleteContainerRepositoryMutation from '~/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql';
+import getContainerRepositoryDetailsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
+
+describe('Delete Image', () => {
+ let wrapper;
+ const id = '1';
+ const storeMock = {
+ readQuery: jest.fn().mockReturnValue({
+ containerRepository: {
+ status: 'foo',
+ },
+ }),
+ writeQuery: jest.fn(),
+ };
+
+ const updatePayload = {
+ data: {
+ destroyContainerRepository: {
+ containerRepository: {
+ status: 'baz',
+ },
+ },
+ },
+ };
+
+ const findButton = () => wrapper.find('button');
+
+ const mountComponent = ({
+ propsData = { id },
+ mutate = jest.fn().mockResolvedValue({}),
+ } = {}) => {
+ wrapper = shallowMount(component, {
+ propsData,
+ mocks: {
+ $apollo: {
+ mutate,
+ },
+ },
+ scopedSlots: {
+ default: '<button @click="props.doDelete">test</button>',
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('executes apollo mutate on doDelete', () => {
+ const mutate = jest.fn().mockResolvedValue({});
+ mountComponent({ mutate });
+
+ wrapper.vm.doDelete();
+
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: deleteContainerRepositoryMutation,
+ variables: {
+ id,
+ },
+ update: undefined,
+ });
+ });
+
+ it('on success emits the correct events', async () => {
+ const mutate = jest.fn().mockResolvedValue({});
+ mountComponent({ mutate });
+
+ wrapper.vm.doDelete();
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('start')).toEqual([[]]);
+ expect(wrapper.emitted('success')).toEqual([[]]);
+ expect(wrapper.emitted('end')).toEqual([[]]);
+ });
+
+ it('when a payload contains an error emits an error event', async () => {
+ const mutate = jest
+ .fn()
+ .mockResolvedValue({ data: { destroyContainerRepository: { errors: ['foo'] } } });
+
+ mountComponent({ mutate });
+ wrapper.vm.doDelete();
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('error')).toEqual([[['foo']]]);
+ });
+
+ it('when the api call errors emits an error event', async () => {
+ const mutate = jest.fn().mockRejectedValue('error');
+
+ mountComponent({ mutate });
+ wrapper.vm.doDelete();
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('error')).toEqual([[['error']]]);
+ });
+
+ it('uses the update function, when the prop is set to true', () => {
+ const mutate = jest.fn().mockResolvedValue({});
+
+ mountComponent({ mutate, propsData: { id, useUpdateFn: true } });
+ wrapper.vm.doDelete();
+
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: deleteContainerRepositoryMutation,
+ variables: {
+ id,
+ },
+ update: wrapper.vm.updateImageStatus,
+ });
+ });
+
+ it('updateImage status reads and write to the cache', () => {
+ mountComponent();
+
+ const variables = {
+ id,
+ first: GRAPHQL_PAGE_SIZE,
+ };
+
+ wrapper.vm.updateImageStatus(storeMock, updatePayload);
+
+ expect(storeMock.readQuery).toHaveBeenCalledWith({
+ query: getContainerRepositoryDetailsQuery,
+ variables,
+ });
+ expect(storeMock.writeQuery).toHaveBeenCalledWith({
+ query: getContainerRepositoryDetailsQuery,
+ variables,
+ data: {
+ containerRepository: {
+ status: updatePayload.data.destroyContainerRepository.containerRepository.status,
+ },
+ },
+ });
+ });
+
+ it('binds the doDelete function to the default scoped slot', () => {
+ const mutate = jest.fn().mockResolvedValue({});
+ mountComponent({ mutate });
+ findButton().trigger('click');
+ expect(mutate).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap
index 5f191ef5561..5f191ef5561 100644
--- a/spec/frontend/registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_alert_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_alert_spec.js
new file mode 100644
index 00000000000..e25162f4da5
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_alert_spec.js
@@ -0,0 +1,116 @@
+import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import component from '~/packages_and_registries/container_registry/explorer/components/details_page/delete_alert.vue';
+import {
+ DELETE_TAG_SUCCESS_MESSAGE,
+ DELETE_TAG_ERROR_MESSAGE,
+ DELETE_TAGS_SUCCESS_MESSAGE,
+ DELETE_TAGS_ERROR_MESSAGE,
+ ADMIN_GARBAGE_COLLECTION_TIP,
+} from '~/packages_and_registries/container_registry/explorer/constants';
+
+describe('Delete alert', () => {
+ let wrapper;
+
+ const findAlert = () => wrapper.find(GlAlert);
+ const findLink = () => wrapper.find(GlLink);
+
+ const mountComponent = (propsData) => {
+ wrapper = shallowMount(component, { stubs: { GlSprintf }, propsData });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when deleteAlertType is null', () => {
+ it('does not show the alert', () => {
+ mountComponent();
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('when deleteAlertType is not null', () => {
+ describe('success states', () => {
+ describe.each`
+ deleteAlertType | message
+ ${'success_tag'} | ${DELETE_TAG_SUCCESS_MESSAGE}
+ ${'success_tags'} | ${DELETE_TAGS_SUCCESS_MESSAGE}
+ `('when deleteAlertType is $deleteAlertType', ({ deleteAlertType, message }) => {
+ it('alert exists', () => {
+ mountComponent({ deleteAlertType });
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ describe('when the user is an admin', () => {
+ beforeEach(() => {
+ mountComponent({
+ deleteAlertType,
+ isAdmin: true,
+ garbageCollectionHelpPagePath: 'foo',
+ });
+ });
+
+ it(`alert title is ${message}`, () => {
+ expect(findAlert().attributes('title')).toBe(message);
+ });
+
+ it('alert body contains admin tip', () => {
+ expect(findAlert().text()).toMatchInterpolatedText(ADMIN_GARBAGE_COLLECTION_TIP);
+ });
+
+ it('alert body contains link', () => {
+ const alertLink = findLink();
+ expect(alertLink.exists()).toBe(true);
+ expect(alertLink.attributes('href')).toBe('foo');
+ });
+ });
+
+ describe('when the user is not an admin', () => {
+ it('alert exist and text is appropriate', () => {
+ mountComponent({ deleteAlertType });
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(message);
+ });
+ });
+ });
+ });
+ describe('error states', () => {
+ describe.each`
+ deleteAlertType | message
+ ${'danger_tag'} | ${DELETE_TAG_ERROR_MESSAGE}
+ ${'danger_tags'} | ${DELETE_TAGS_ERROR_MESSAGE}
+ `('when deleteAlertType is $deleteAlertType', ({ deleteAlertType, message }) => {
+ it('alert exists', () => {
+ mountComponent({ deleteAlertType });
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ describe('when the user is an admin', () => {
+ it('alert exist and text is appropriate', () => {
+ mountComponent({ deleteAlertType });
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(message);
+ });
+ });
+
+ describe('when the user is not an admin', () => {
+ it('alert exist and text is appropriate', () => {
+ mountComponent({ deleteAlertType });
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(message);
+ });
+ });
+ });
+ });
+
+ describe('dismissing alert', () => {
+ it('GlAlert dismiss event triggers a change event', () => {
+ mountComponent({ deleteAlertType: 'success_tags' });
+ findAlert().vm.$emit('dismiss');
+ expect(wrapper.emitted('change')).toEqual([[null]]);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_modal_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_modal_spec.js
new file mode 100644
index 00000000000..16c9485e69e
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_modal_spec.js
@@ -0,0 +1,152 @@
+import { GlSprintf, GlFormInput } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import component from '~/packages_and_registries/container_registry/explorer/components/details_page/delete_modal.vue';
+import {
+ REMOVE_TAG_CONFIRMATION_TEXT,
+ REMOVE_TAGS_CONFIRMATION_TEXT,
+ DELETE_IMAGE_CONFIRMATION_TITLE,
+ DELETE_IMAGE_CONFIRMATION_TEXT,
+} from '~/packages_and_registries/container_registry/explorer/constants';
+import { GlModal } from '../../stubs';
+
+describe('Delete Modal', () => {
+ let wrapper;
+
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findDescription = () => wrapper.find('[data-testid="description"]');
+ const findInputComponent = () => wrapper.findComponent(GlFormInput);
+
+ const mountComponent = (propsData) => {
+ wrapper = shallowMount(component, {
+ propsData,
+ stubs: {
+ GlSprintf,
+ GlModal,
+ },
+ });
+ };
+
+ const expectPrimaryActionStatus = (disabled = true) =>
+ expect(findModal().props('actionPrimary')).toMatchObject(
+ expect.objectContaining({
+ attributes: [{ variant: 'danger' }, { disabled }],
+ }),
+ );
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('contains a GlModal', () => {
+ mountComponent();
+ expect(findModal().exists()).toBe(true);
+ });
+
+ describe('events', () => {
+ it.each`
+ glEvent | localEvent
+ ${'primary'} | ${'confirmDelete'}
+ ${'cancel'} | ${'cancelDelete'}
+ `('GlModal $glEvent emits $localEvent', ({ glEvent, localEvent }) => {
+ mountComponent();
+ findModal().vm.$emit(glEvent);
+ expect(wrapper.emitted(localEvent)).toEqual([[]]);
+ });
+ });
+
+ describe('methods', () => {
+ it('show calls gl-modal show', () => {
+ mountComponent();
+ wrapper.vm.show();
+ expect(GlModal.methods.show).toHaveBeenCalled();
+ });
+ });
+
+ describe('when we are deleting images', () => {
+ it('has the correct title', () => {
+ mountComponent({ deleteImage: true });
+
+ expect(wrapper.text()).toContain(DELETE_IMAGE_CONFIRMATION_TITLE);
+ });
+
+ it('has the correct description', () => {
+ mountComponent({ deleteImage: true });
+
+ expect(wrapper.text()).toContain(
+ DELETE_IMAGE_CONFIRMATION_TEXT.replace('%{code}', '').trim(),
+ );
+ });
+
+ describe('delete button', () => {
+ const itemsToBeDeleted = [{ project: { path: 'foo' } }];
+
+ it('is disabled by default', () => {
+ mountComponent({ deleteImage: true });
+
+ expectPrimaryActionStatus();
+ });
+
+ it('if the user types something different from the project path is disabled', async () => {
+ mountComponent({ deleteImage: true, itemsToBeDeleted });
+
+ findInputComponent().vm.$emit('input', 'bar');
+
+ await nextTick();
+
+ expectPrimaryActionStatus();
+ });
+
+ it('if the user types the project path it is enabled', async () => {
+ mountComponent({ deleteImage: true, itemsToBeDeleted });
+
+ findInputComponent().vm.$emit('input', 'foo');
+
+ await nextTick();
+
+ expectPrimaryActionStatus(false);
+ });
+ });
+ });
+
+ describe('when we are deleting tags', () => {
+ it('delete button is enabled', () => {
+ mountComponent();
+
+ expectPrimaryActionStatus(false);
+ });
+
+ describe('itemsToBeDeleted contains one element', () => {
+ beforeEach(() => {
+ mountComponent({ itemsToBeDeleted: [{ path: 'foo' }] });
+ });
+
+ it(`has the correct description`, () => {
+ expect(findDescription().text()).toBe(
+ REMOVE_TAG_CONFIRMATION_TEXT.replace('%{item}', 'foo'),
+ );
+ });
+
+ it('has the correct title', () => {
+ expect(wrapper.text()).toContain('Remove tag');
+ });
+ });
+
+ describe('itemsToBeDeleted contains more than element', () => {
+ beforeEach(() => {
+ mountComponent({ itemsToBeDeleted: [{ path: 'foo' }, { path: 'bar' }] });
+ });
+
+ it(`has the correct description`, () => {
+ expect(findDescription().text()).toBe(
+ REMOVE_TAGS_CONFIRMATION_TEXT.replace('%{item}', '2'),
+ );
+ });
+
+ it('has the correct title', () => {
+ expect(wrapper.text()).toContain('Remove tags');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js
new file mode 100644
index 00000000000..f06300efa29
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js
@@ -0,0 +1,304 @@
+import { GlDropdownItem, GlIcon } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import { GlDropdown } from 'jest/packages_and_registries/container_registry/explorer/stubs';
+import { useFakeDate } from 'helpers/fake_date';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import waitForPromises from 'helpers/wait_for_promises';
+import component from '~/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue';
+import {
+ UNSCHEDULED_STATUS,
+ SCHEDULED_STATUS,
+ ONGOING_STATUS,
+ UNFINISHED_STATUS,
+ CLEANUP_DISABLED_TEXT,
+ CLEANUP_DISABLED_TOOLTIP,
+ CLEANUP_SCHEDULED_TOOLTIP,
+ CLEANUP_ONGOING_TOOLTIP,
+ CLEANUP_UNFINISHED_TOOLTIP,
+ ROOT_IMAGE_TEXT,
+ ROOT_IMAGE_TOOLTIP,
+} from '~/packages_and_registries/container_registry/explorer/constants';
+import getContainerRepositoryTagCountQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags_count.query.graphql';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+import { imageTagsCountMock } from '../../mock_data';
+
+describe('Details Header', () => {
+ let wrapper;
+ let apolloProvider;
+ let localVue;
+
+ const defaultImage = {
+ name: 'foo',
+ updatedAt: '2020-11-03T13:29:21Z',
+ canDelete: true,
+ project: {
+ visibility: 'public',
+ containerExpirationPolicy: {
+ enabled: false,
+ },
+ },
+ };
+
+ // set the date to Dec 4, 2020
+ useFakeDate(2020, 11, 4);
+ const findByTestId = (testId) => wrapper.find(`[data-testid="${testId}"]`);
+
+ const findLastUpdatedAndVisibility = () => findByTestId('updated-and-visibility');
+ const findTitle = () => findByTestId('title');
+ const findTagsCount = () => findByTestId('tags-count');
+ const findCleanup = () => findByTestId('cleanup');
+ const findDeleteButton = () => wrapper.findComponent(GlDropdownItem);
+ const findInfoIcon = () => wrapper.findComponent(GlIcon);
+
+ const waitForMetadataItems = async () => {
+ // Metadata items are printed by a loop in the title-area and it takes two ticks for them to be available
+ await wrapper.vm.$nextTick();
+ await wrapper.vm.$nextTick();
+ };
+
+ const mountComponent = ({
+ propsData = { image: defaultImage },
+ resolver = jest.fn().mockResolvedValue(imageTagsCountMock()),
+ $apollo = undefined,
+ } = {}) => {
+ const mocks = {};
+
+ if ($apollo) {
+ mocks.$apollo = $apollo;
+ } else {
+ localVue = createLocalVue();
+ localVue.use(VueApollo);
+
+ const requestHandlers = [[getContainerRepositoryTagCountQuery, resolver]];
+ apolloProvider = createMockApollo(requestHandlers);
+ }
+
+ wrapper = shallowMount(component, {
+ localVue,
+ apolloProvider,
+ propsData,
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ mocks,
+ stubs: {
+ TitleArea,
+ GlDropdown,
+ GlDropdownItem,
+ },
+ });
+ };
+
+ afterEach(() => {
+ // if we want to mix createMockApollo and manual mocks we need to reset everything
+ wrapper.destroy();
+ apolloProvider = undefined;
+ localVue = undefined;
+ wrapper = null;
+ });
+
+ describe('image name', () => {
+ describe('missing image name', () => {
+ beforeEach(() => {
+ mountComponent({ propsData: { image: { ...defaultImage, name: '' } } });
+
+ return waitForPromises();
+ });
+
+ it('root image ', () => {
+ expect(findTitle().text()).toBe(ROOT_IMAGE_TEXT);
+ });
+
+ it('has an icon', () => {
+ expect(findInfoIcon().exists()).toBe(true);
+ expect(findInfoIcon().props('name')).toBe('information-o');
+ });
+
+ it('has a tooltip', () => {
+ const tooltip = getBinding(findInfoIcon().element, 'gl-tooltip');
+ expect(tooltip.value).toBe(ROOT_IMAGE_TOOLTIP);
+ });
+ });
+
+ describe('with image name present', () => {
+ beforeEach(() => {
+ mountComponent();
+
+ return waitForPromises();
+ });
+
+ it('shows image.name ', () => {
+ expect(findTitle().text()).toContain('foo');
+ });
+
+ it('has no icon', () => {
+ expect(findInfoIcon().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('delete button', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findDeleteButton().exists()).toBe(true);
+ });
+
+ it('has the correct text', () => {
+ mountComponent();
+
+ expect(findDeleteButton().text()).toBe('Delete image repository');
+ });
+
+ it('has the correct props', () => {
+ mountComponent();
+
+ expect(findDeleteButton().attributes()).toMatchObject(
+ expect.objectContaining({
+ variant: 'danger',
+ }),
+ );
+ });
+
+ it('emits the correct event', () => {
+ mountComponent();
+
+ findDeleteButton().vm.$emit('click');
+
+ expect(wrapper.emitted('delete')).toEqual([[]]);
+ });
+
+ it.each`
+ canDelete | disabled | isDisabled
+ ${true} | ${false} | ${undefined}
+ ${true} | ${true} | ${'true'}
+ ${false} | ${false} | ${'true'}
+ ${false} | ${true} | ${'true'}
+ `(
+ 'when canDelete is $canDelete and disabled is $disabled is $isDisabled that the button is disabled',
+ ({ canDelete, disabled, isDisabled }) => {
+ mountComponent({ propsData: { image: { ...defaultImage, canDelete }, disabled } });
+
+ expect(findDeleteButton().attributes('disabled')).toBe(isDisabled);
+ },
+ );
+ });
+
+ describe('metadata items', () => {
+ describe('tags count', () => {
+ it('displays "-- tags" while loading', async () => {
+ // here we are forced to mock apollo because `waitForMetadataItems` waits
+ // for two ticks, de facto allowing the promise to resolve, so there is
+ // no way to catch the component as both rendered and in loading state
+ mountComponent({ $apollo: { queries: { containerRepository: { loading: true } } } });
+
+ await waitForMetadataItems();
+
+ expect(findTagsCount().props('text')).toBe('-- tags');
+ });
+
+ it('when there is more than one tag has the correct text', async () => {
+ mountComponent();
+
+ await waitForPromises();
+ await waitForMetadataItems();
+
+ expect(findTagsCount().props('text')).toBe('13 tags');
+ });
+
+ it('when there is one tag has the correct text', async () => {
+ mountComponent({
+ resolver: jest.fn().mockResolvedValue(imageTagsCountMock({ tagsCount: 1 })),
+ });
+
+ await waitForPromises();
+ await waitForMetadataItems();
+
+ expect(findTagsCount().props('text')).toBe('1 tag');
+ });
+
+ it('has the correct icon', async () => {
+ mountComponent();
+ await waitForMetadataItems();
+
+ expect(findTagsCount().props('icon')).toBe('tag');
+ });
+ });
+
+ describe('cleanup metadata item', () => {
+ it('has the correct icon', async () => {
+ mountComponent();
+ await waitForMetadataItems();
+
+ expect(findCleanup().props('icon')).toBe('expire');
+ });
+
+ it('when the expiration policy is disabled', async () => {
+ mountComponent();
+ await waitForMetadataItems();
+
+ expect(findCleanup().props()).toMatchObject({
+ text: CLEANUP_DISABLED_TEXT,
+ textTooltip: CLEANUP_DISABLED_TOOLTIP,
+ });
+ });
+
+ it.each`
+ status | text | tooltip
+ ${UNSCHEDULED_STATUS} | ${'Cleanup will run in 1 month'} | ${''}
+ ${SCHEDULED_STATUS} | ${'Cleanup pending'} | ${CLEANUP_SCHEDULED_TOOLTIP}
+ ${ONGOING_STATUS} | ${'Cleanup in progress'} | ${CLEANUP_ONGOING_TOOLTIP}
+ ${UNFINISHED_STATUS} | ${'Cleanup incomplete'} | ${CLEANUP_UNFINISHED_TOOLTIP}
+ `(
+ 'when the status is $status the text is $text and the tooltip is $tooltip',
+ async ({ status, text, tooltip }) => {
+ mountComponent({
+ propsData: {
+ image: {
+ ...defaultImage,
+ expirationPolicyCleanupStatus: status,
+ project: {
+ containerExpirationPolicy: { enabled: true, nextRunAt: '2021-01-03T14:29:21Z' },
+ },
+ },
+ },
+ });
+ await waitForMetadataItems();
+
+ expect(findCleanup().props()).toMatchObject({
+ text,
+ textTooltip: tooltip,
+ });
+ },
+ );
+ });
+
+ describe('visibility and updated at ', () => {
+ it('has last updated text', async () => {
+ mountComponent();
+ await waitForMetadataItems();
+
+ expect(findLastUpdatedAndVisibility().props('text')).toBe('Last updated 1 month ago');
+ });
+
+ describe('visibility icon', () => {
+ it('shows an eye when the project is public', async () => {
+ mountComponent();
+ await waitForMetadataItems();
+
+ expect(findLastUpdatedAndVisibility().props('icon')).toBe('eye');
+ });
+ it('shows an eye slashed when the project is not public', async () => {
+ mountComponent({
+ propsData: { image: { ...defaultImage, project: { visibility: 'private' } } },
+ });
+ await waitForMetadataItems();
+
+ expect(findLastUpdatedAndVisibility().props('icon')).toBe('eye-slash');
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/empty_state_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/empty_state_spec.js
new file mode 100644
index 00000000000..f14284e9efe
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/empty_state_spec.js
@@ -0,0 +1,54 @@
+import { GlEmptyState } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import component from '~/packages_and_registries/container_registry/explorer/components/details_page/empty_state.vue';
+import {
+ NO_TAGS_TITLE,
+ NO_TAGS_MESSAGE,
+ MISSING_OR_DELETED_IMAGE_TITLE,
+ MISSING_OR_DELETED_IMAGE_MESSAGE,
+} from '~/packages_and_registries/container_registry/explorer/constants';
+
+describe('EmptyTagsState component', () => {
+ let wrapper;
+
+ const findEmptyState = () => wrapper.find(GlEmptyState);
+
+ const mountComponent = (propsData) => {
+ wrapper = shallowMount(component, {
+ stubs: {
+ GlEmptyState,
+ },
+ propsData,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('contains gl-empty-state', () => {
+ mountComponent();
+ expect(findEmptyState().exists()).toBe(true);
+ });
+
+ it.each`
+ isEmptyImage | title | description
+ ${false} | ${NO_TAGS_TITLE} | ${NO_TAGS_MESSAGE}
+ ${true} | ${MISSING_OR_DELETED_IMAGE_TITLE} | ${MISSING_OR_DELETED_IMAGE_MESSAGE}
+ `(
+ 'when isEmptyImage is $isEmptyImage has the correct props',
+ ({ isEmptyImage, title, description }) => {
+ mountComponent({
+ noContainersImage: 'foo',
+ isEmptyImage,
+ });
+
+ expect(findEmptyState().props()).toMatchObject({
+ title,
+ description,
+ svgPath: 'foo',
+ });
+ },
+ );
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert_spec.js
new file mode 100644
index 00000000000..1a27481a828
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert_spec.js
@@ -0,0 +1,74 @@
+import { GlAlert, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import component from '~/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert.vue';
+import {
+ DELETE_ALERT_TITLE,
+ DELETE_ALERT_LINK_TEXT,
+} from '~/packages_and_registries/container_registry/explorer/constants';
+
+describe('Partial Cleanup alert', () => {
+ let wrapper;
+
+ const findAlert = () => wrapper.find(GlAlert);
+ const findRunLink = () => wrapper.find('[data-testid="run-link"');
+ const findHelpLink = () => wrapper.find('[data-testid="help-link"');
+
+ const mountComponent = () => {
+ wrapper = shallowMount(component, {
+ stubs: { GlSprintf },
+ propsData: {
+ runCleanupPoliciesHelpPagePath: 'foo',
+ cleanupPoliciesHelpPagePath: 'bar',
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it(`gl-alert has the correct properties`, () => {
+ mountComponent();
+
+ expect(findAlert().props()).toMatchObject({
+ title: DELETE_ALERT_TITLE,
+ variant: 'warning',
+ });
+ });
+
+ it('has the right text', () => {
+ mountComponent();
+
+ expect(wrapper.text()).toMatchInterpolatedText(DELETE_ALERT_LINK_TEXT);
+ });
+
+ it('contains run link', () => {
+ mountComponent();
+
+ const link = findRunLink();
+ expect(link.exists()).toBe(true);
+ expect(link.attributes()).toMatchObject({
+ href: 'foo',
+ target: '_blank',
+ });
+ });
+
+ it('contains help link', () => {
+ mountComponent();
+
+ const link = findHelpLink();
+ expect(link.exists()).toBe(true);
+ expect(link.attributes()).toMatchObject({
+ href: 'bar',
+ target: '_blank',
+ });
+ });
+
+ it('GlAlert dismiss event triggers a dismiss event', () => {
+ mountComponent();
+
+ findAlert().vm.$emit('dismiss');
+ expect(wrapper.emitted('dismiss')).toEqual([[]]);
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/status_alert_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/status_alert_spec.js
new file mode 100644
index 00000000000..a11b102d9a6
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/status_alert_spec.js
@@ -0,0 +1,57 @@
+import { GlLink, GlSprintf, GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import component from '~/packages_and_registries/container_registry/explorer/components/details_page/status_alert.vue';
+import {
+ DELETE_SCHEDULED,
+ DELETE_FAILED,
+ PACKAGE_DELETE_HELP_PAGE_PATH,
+ SCHEDULED_FOR_DELETION_STATUS_TITLE,
+ SCHEDULED_FOR_DELETION_STATUS_MESSAGE,
+ FAILED_DELETION_STATUS_TITLE,
+ FAILED_DELETION_STATUS_MESSAGE,
+} from '~/packages_and_registries/container_registry/explorer/constants';
+
+describe('Status Alert', () => {
+ let wrapper;
+
+ const findLink = () => wrapper.find(GlLink);
+ const findAlert = () => wrapper.find(GlAlert);
+ const findMessage = () => wrapper.find('[data-testid="message"]');
+
+ const mountComponent = (propsData) => {
+ wrapper = shallowMount(component, {
+ propsData,
+ stubs: {
+ GlSprintf,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it.each`
+ status | title | variant | message | link
+ ${DELETE_SCHEDULED} | ${SCHEDULED_FOR_DELETION_STATUS_TITLE} | ${'info'} | ${SCHEDULED_FOR_DELETION_STATUS_MESSAGE} | ${PACKAGE_DELETE_HELP_PAGE_PATH}
+ ${DELETE_FAILED} | ${FAILED_DELETION_STATUS_TITLE} | ${'warning'} | ${FAILED_DELETION_STATUS_MESSAGE} | ${''}
+ `(
+ `when the status is $status, title is $title, variant is $variant, message is $message and the link is $link`,
+ ({ status, title, variant, message, link }) => {
+ mountComponent({ status });
+
+ expect(findMessage().text()).toMatchInterpolatedText(message);
+ expect(findAlert().props()).toMatchObject({
+ title,
+ variant,
+ });
+ if (link) {
+ expect(findLink().attributes()).toMatchObject({
+ target: '_blank',
+ href: link,
+ });
+ }
+ },
+ );
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js
new file mode 100644
index 00000000000..00b1d03b7c2
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js
@@ -0,0 +1,382 @@
+import { GlFormCheckbox, GlSprintf, GlIcon, GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+
+import component from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue';
+import {
+ REMOVE_TAG_BUTTON_TITLE,
+ MISSING_MANIFEST_WARNING_TOOLTIP,
+ NOT_AVAILABLE_TEXT,
+ NOT_AVAILABLE_SIZE,
+} from '~/packages_and_registries/container_registry/explorer/constants/index';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+
+import { tagsMock } from '../../mock_data';
+import { ListItem } from '../../stubs';
+
+describe('tags list row', () => {
+ let wrapper;
+ const [tag] = [...tagsMock];
+
+ const defaultProps = { tag, isMobile: false, index: 0 };
+
+ const findCheckbox = () => wrapper.findComponent(GlFormCheckbox);
+ const findName = () => wrapper.find('[data-testid="name"]');
+ const findSize = () => wrapper.find('[data-testid="size"]');
+ const findTime = () => wrapper.find('[data-testid="time"]');
+ const findShortRevision = () => wrapper.find('[data-testid="digest"]');
+ const findClipboardButton = () => wrapper.findComponent(ClipboardButton);
+ const findTimeAgoTooltip = () => wrapper.findComponent(TimeAgoTooltip);
+ const findDetailsRows = () => wrapper.findAll(DetailsRow);
+ const findPublishedDateDetail = () => wrapper.find('[data-testid="published-date-detail"]');
+ const findManifestDetail = () => wrapper.find('[data-testid="manifest-detail"]');
+ const findConfigurationDetail = () => wrapper.find('[data-testid="configuration-detail"]');
+ const findWarningIcon = () => wrapper.findComponent(GlIcon);
+ const findAdditionalActionsMenu = () => wrapper.findComponent(GlDropdown);
+ const findDeleteButton = () => wrapper.findComponent(GlDropdownItem);
+
+ const mountComponent = (propsData = defaultProps) => {
+ wrapper = shallowMount(component, {
+ stubs: {
+ GlSprintf,
+ ListItem,
+ DetailsRow,
+ GlDropdown,
+ },
+ propsData,
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('checkbox', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findCheckbox().exists()).toBe(true);
+ });
+
+ it("does not exist when the row can't be deleted", () => {
+ const customTag = { ...tag, canDelete: false };
+
+ mountComponent({ ...defaultProps, tag: customTag });
+
+ expect(findCheckbox().exists()).toBe(false);
+ });
+
+ it.each`
+ digest | disabled
+ ${'foo'} | ${true}
+ ${null} | ${false}
+ ${null} | ${true}
+ ${'foo'} | ${true}
+ `('is disabled when the digest $digest and disabled is $disabled', ({ digest, disabled }) => {
+ mountComponent({ tag: { ...tag, digest }, disabled });
+
+ expect(findCheckbox().attributes('disabled')).toBe('true');
+ });
+
+ it('is wired to the selected prop', () => {
+ mountComponent({ ...defaultProps, selected: true });
+
+ expect(findCheckbox().attributes('checked')).toBe('true');
+ });
+
+ it('when changed emit a select event', () => {
+ mountComponent();
+
+ findCheckbox().vm.$emit('change');
+
+ expect(wrapper.emitted('select')).toEqual([[]]);
+ });
+ });
+
+ describe('tag name', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findName().exists()).toBe(true);
+ });
+
+ it('has the correct text', () => {
+ mountComponent();
+
+ expect(findName().text()).toBe(tag.name);
+ });
+
+ it('has a tooltip', () => {
+ mountComponent();
+
+ const tooltip = getBinding(findName().element, 'gl-tooltip');
+
+ expect(tooltip.value.title).toBe(tag.name);
+ });
+
+ it('on mobile has mw-s class', () => {
+ mountComponent({ ...defaultProps, isMobile: true });
+
+ expect(findName().classes('mw-s')).toBe(true);
+ });
+ });
+
+ describe('clipboard button', () => {
+ it('exist if tag.location exist', () => {
+ mountComponent();
+
+ expect(findClipboardButton().exists()).toBe(true);
+ });
+
+ it('is hidden if tag does not have a location', () => {
+ mountComponent({ ...defaultProps, tag: { ...tag, location: null } });
+
+ expect(findClipboardButton().exists()).toBe(false);
+ });
+
+ it('has the correct props/attributes', () => {
+ mountComponent();
+
+ expect(findClipboardButton().attributes()).toMatchObject({
+ text: tag.location,
+ title: tag.location,
+ });
+ });
+
+ it('is disabled when the component is disabled', () => {
+ mountComponent({ ...defaultProps, disabled: true });
+
+ expect(findClipboardButton().attributes('disabled')).toBe('true');
+ });
+ });
+
+ describe('warning icon', () => {
+ it('is normally hidden', () => {
+ mountComponent();
+
+ expect(findWarningIcon().exists()).toBe(false);
+ });
+
+ it('is shown when the tag is broken', () => {
+ mountComponent({ tag: { ...tag, digest: null } });
+
+ expect(findWarningIcon().exists()).toBe(true);
+ });
+
+ it('has an appropriate tooltip', () => {
+ mountComponent({ tag: { ...tag, digest: null } });
+
+ const tooltip = getBinding(findWarningIcon().element, 'gl-tooltip');
+ expect(tooltip.value.title).toBe(MISSING_MANIFEST_WARNING_TOOLTIP);
+ });
+ });
+
+ describe('size', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findSize().exists()).toBe(true);
+ });
+
+ it('contains the totalSize and layers', () => {
+ mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '1024', layers: 10 } });
+
+ expect(findSize().text()).toMatchInterpolatedText('1.00 KiB · 10 layers');
+ });
+
+ it('when totalSize is giantic', () => {
+ mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '1099511627776', layers: 2 } });
+
+ expect(findSize().text()).toMatchInterpolatedText('1024.00 GiB · 2 layers');
+ });
+
+ it('when totalSize is missing', () => {
+ mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '0', layers: 10 } });
+
+ expect(findSize().text()).toMatchInterpolatedText(`${NOT_AVAILABLE_SIZE} · 10 layers`);
+ });
+
+ it('when layers are missing', () => {
+ mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '1024' } });
+
+ expect(findSize().text()).toMatchInterpolatedText('1.00 KiB');
+ });
+
+ it('when there is 1 layer', () => {
+ mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '0', layers: 1 } });
+
+ expect(findSize().text()).toMatchInterpolatedText(`${NOT_AVAILABLE_SIZE} · 1 layer`);
+ });
+ });
+
+ describe('time', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findTime().exists()).toBe(true);
+ });
+
+ it('has the correct text', () => {
+ mountComponent();
+
+ expect(findTime().text()).toBe('Published');
+ });
+
+ it('contains time_ago_tooltip component', () => {
+ mountComponent();
+
+ expect(findTimeAgoTooltip().exists()).toBe(true);
+ });
+
+ it('pass the correct props to time ago tooltip', () => {
+ mountComponent();
+
+ expect(findTimeAgoTooltip().attributes()).toMatchObject({ time: tag.createdAt });
+ });
+ });
+
+ describe('digest', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findShortRevision().exists()).toBe(true);
+ });
+
+ it('has the correct text', () => {
+ mountComponent();
+
+ expect(findShortRevision().text()).toMatchInterpolatedText('Digest: 2cf3d2f');
+ });
+
+ it(`displays ${NOT_AVAILABLE_TEXT} when digest is missing`, () => {
+ mountComponent({ tag: { ...tag, digest: null } });
+
+ expect(findShortRevision().text()).toMatchInterpolatedText(`Digest: ${NOT_AVAILABLE_TEXT}`);
+ });
+ });
+
+ describe('additional actions menu', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findAdditionalActionsMenu().exists()).toBe(true);
+ });
+
+ it('has the correct props', () => {
+ mountComponent();
+
+ expect(findAdditionalActionsMenu().props()).toMatchObject({
+ icon: 'ellipsis_v',
+ text: 'More actions',
+ textSrOnly: true,
+ category: 'tertiary',
+ right: true,
+ });
+ });
+
+ it.each`
+ canDelete | digest | disabled | buttonDisabled
+ ${true} | ${null} | ${true} | ${true}
+ ${false} | ${'foo'} | ${true} | ${true}
+ ${false} | ${null} | ${true} | ${true}
+ ${true} | ${'foo'} | ${true} | ${true}
+ ${true} | ${'foo'} | ${false} | ${false}
+ `(
+ 'is $visible that is visible when canDelete is $canDelete and digest is $digest and disabled is $disabled',
+ ({ canDelete, digest, disabled, buttonDisabled }) => {
+ mountComponent({ ...defaultProps, tag: { ...tag, canDelete, digest }, disabled });
+
+ expect(findAdditionalActionsMenu().props('disabled')).toBe(buttonDisabled);
+ expect(findAdditionalActionsMenu().classes('gl-opacity-0')).toBe(buttonDisabled);
+ expect(findAdditionalActionsMenu().classes('gl-pointer-events-none')).toBe(buttonDisabled);
+ },
+ );
+
+ describe('delete button', () => {
+ it('exists and has the correct attrs', () => {
+ mountComponent();
+
+ expect(findDeleteButton().exists()).toBe(true);
+ expect(findDeleteButton().attributes()).toMatchObject({
+ variant: 'danger',
+ });
+ expect(findDeleteButton().text()).toBe(REMOVE_TAG_BUTTON_TITLE);
+ });
+
+ it('delete event emits delete', () => {
+ mountComponent();
+
+ findDeleteButton().vm.$emit('click');
+
+ expect(wrapper.emitted('delete')).toEqual([[]]);
+ });
+ });
+ });
+
+ describe('details rows', () => {
+ describe('when the tag has a digest', () => {
+ it('has 3 details rows', async () => {
+ mountComponent();
+ await nextTick();
+
+ expect(findDetailsRows().length).toBe(3);
+ });
+
+ describe.each`
+ name | finderFunction | text | icon | clipboard
+ ${'published date detail'} | ${findPublishedDateDetail} | ${'Published to the gitlab-org/gitlab-test/rails-12009 image repository at 01:29 UTC on 2020-11-03'} | ${'clock'} | ${false}
+ ${'manifest detail'} | ${findManifestDetail} | ${'Manifest digest: sha256:2cf3d2fdac1b04a14301d47d51cb88dcd26714c74f91440eeee99ce399089062'} | ${'log'} | ${true}
+ ${'configuration detail'} | ${findConfigurationDetail} | ${'Configuration digest: sha256:c2613843ab33aabf847965442b13a8b55a56ae28837ce182627c0716eb08c02b'} | ${'cloud-gear'} | ${true}
+ `('$name details row', ({ finderFunction, text, icon, clipboard }) => {
+ it(`has ${text} as text`, async () => {
+ mountComponent();
+ await nextTick();
+
+ expect(finderFunction().text()).toMatchInterpolatedText(text);
+ });
+
+ it(`has the ${icon} icon`, async () => {
+ mountComponent();
+ await nextTick();
+
+ expect(finderFunction().props('icon')).toBe(icon);
+ });
+
+ if (clipboard) {
+ it(`clipboard button exist`, async () => {
+ mountComponent();
+ await nextTick();
+
+ expect(finderFunction().find(ClipboardButton).exists()).toBe(clipboard);
+ });
+
+ it('is disabled when the component is disabled', async () => {
+ mountComponent({ ...defaultProps, disabled: true });
+ await nextTick();
+
+ expect(finderFunction().findComponent(ClipboardButton).attributes('disabled')).toBe(
+ 'true',
+ );
+ });
+ }
+ });
+ });
+
+ describe('when the tag does not have a digest', () => {
+ it('hides the details rows', async () => {
+ mountComponent({ tag: { ...tag, digest: null } });
+
+ await nextTick();
+ expect(findDetailsRows().length).toBe(0);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
new file mode 100644
index 00000000000..9a42c82d7e0
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
@@ -0,0 +1,314 @@
+import { GlButton, GlKeysetPagination } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import EmptyTagsState from '~/packages_and_registries/container_registry/explorer/components/details_page/empty_state.vue';
+import component from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue';
+import TagsListRow from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue';
+import TagsLoader from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue';
+import {
+ TAGS_LIST_TITLE,
+ REMOVE_TAGS_BUTTON_TITLE,
+} from '~/packages_and_registries/container_registry/explorer/constants/index';
+import getContainerRepositoryTagsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql';
+import { tagsMock, imageTagsMock, tagsPageInfo } from '../../mock_data';
+
+const localVue = createLocalVue();
+
+describe('Tags List', () => {
+ let wrapper;
+ let apolloProvider;
+ const tags = [...tagsMock];
+ const readOnlyTags = tags.map((t) => ({ ...t, canDelete: false }));
+
+ const findTagsListRow = () => wrapper.findAll(TagsListRow);
+ const findDeleteButton = () => wrapper.find(GlButton);
+ const findListTitle = () => wrapper.find('[data-testid="list-title"]');
+ const findPagination = () => wrapper.find(GlKeysetPagination);
+ const findEmptyState = () => wrapper.find(EmptyTagsState);
+ const findTagsLoader = () => wrapper.find(TagsLoader);
+
+ const waitForApolloRequestRender = async () => {
+ await waitForPromises();
+ await nextTick();
+ };
+
+ const mountComponent = ({
+ propsData = { isMobile: false, id: 1 },
+ resolver = jest.fn().mockResolvedValue(imageTagsMock()),
+ } = {}) => {
+ localVue.use(VueApollo);
+
+ const requestHandlers = [[getContainerRepositoryTagsQuery, resolver]];
+
+ apolloProvider = createMockApollo(requestHandlers);
+ wrapper = shallowMount(component, {
+ localVue,
+ apolloProvider,
+ propsData,
+ provide() {
+ return {
+ config: {},
+ };
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('List title', () => {
+ it('exists', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findListTitle().exists()).toBe(true);
+ });
+
+ it('has the correct text', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findListTitle().text()).toBe(TAGS_LIST_TITLE);
+ });
+ });
+
+ describe('delete button', () => {
+ it.each`
+ inputTags | isMobile | isVisible
+ ${tags} | ${false} | ${true}
+ ${tags} | ${true} | ${false}
+ ${readOnlyTags} | ${false} | ${false}
+ ${readOnlyTags} | ${true} | ${false}
+ `(
+ 'is $isVisible that delete button exists when tags is $inputTags and isMobile is $isMobile',
+ async ({ inputTags, isMobile, isVisible }) => {
+ mountComponent({
+ propsData: { tags: inputTags, isMobile, id: 1 },
+ resolver: jest.fn().mockResolvedValue(imageTagsMock(inputTags)),
+ });
+
+ await waitForApolloRequestRender();
+
+ expect(findDeleteButton().exists()).toBe(isVisible);
+ },
+ );
+
+ it('has the correct text', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findDeleteButton().text()).toBe(REMOVE_TAGS_BUTTON_TITLE);
+ });
+
+ it('has the correct props', async () => {
+ mountComponent();
+ await waitForApolloRequestRender();
+
+ expect(findDeleteButton().attributes()).toMatchObject({
+ category: 'secondary',
+ variant: 'danger',
+ });
+ });
+
+ it.each`
+ disabled | doSelect | buttonDisabled
+ ${true} | ${false} | ${'true'}
+ ${true} | ${true} | ${'true'}
+ ${false} | ${false} | ${'true'}
+ ${false} | ${true} | ${undefined}
+ `(
+ 'is $buttonDisabled that the button is disabled when the component disabled state is $disabled and is $doSelect that the user selected a tag',
+ async ({ disabled, buttonDisabled, doSelect }) => {
+ mountComponent({ propsData: { tags, disabled, isMobile: false, id: 1 } });
+
+ await waitForApolloRequestRender();
+
+ if (doSelect) {
+ findTagsListRow().at(0).vm.$emit('select');
+ await nextTick();
+ }
+
+ expect(findDeleteButton().attributes('disabled')).toBe(buttonDisabled);
+ },
+ );
+
+ it('click event emits a deleted event with selected items', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ findTagsListRow().at(0).vm.$emit('select');
+ findDeleteButton().vm.$emit('click');
+
+ expect(wrapper.emitted('delete')[0][0][0].name).toBe(tags[0].name);
+ });
+ });
+
+ describe('list rows', () => {
+ it('one row exist for each tag', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findTagsListRow()).toHaveLength(tags.length);
+ });
+
+ it('the correct props are bound to it', async () => {
+ mountComponent({ propsData: { disabled: true, id: 1 } });
+
+ await waitForApolloRequestRender();
+
+ const rows = findTagsListRow();
+
+ expect(rows.at(0).attributes()).toMatchObject({
+ first: 'true',
+ disabled: 'true',
+ });
+ });
+
+ describe('events', () => {
+ it('select event update the selected items', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ findTagsListRow().at(0).vm.$emit('select');
+
+ await nextTick();
+
+ expect(findTagsListRow().at(0).attributes('selected')).toBe('true');
+ });
+
+ it('delete event emit a delete event', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ findTagsListRow().at(0).vm.$emit('delete');
+ expect(wrapper.emitted('delete')[0][0][0].name).toBe(tags[0].name);
+ });
+ });
+ });
+
+ describe('when the list of tags is empty', () => {
+ const resolver = jest.fn().mockResolvedValue(imageTagsMock([]));
+
+ it('has the empty state', async () => {
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ expect(findEmptyState().exists()).toBe(true);
+ });
+
+ it('does not show the loader', async () => {
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ expect(findTagsLoader().exists()).toBe(false);
+ });
+
+ it('does not show the list', async () => {
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ expect(findTagsListRow().exists()).toBe(false);
+ expect(findListTitle().exists()).toBe(false);
+ });
+ });
+
+ describe('pagination', () => {
+ it('exists', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findPagination().exists()).toBe(true);
+ });
+
+ it('is hidden when loading', () => {
+ mountComponent();
+
+ expect(findPagination().exists()).toBe(false);
+ });
+
+ it('is hidden when there are no more pages', async () => {
+ mountComponent({ resolver: jest.fn().mockResolvedValue(imageTagsMock([])) });
+
+ await waitForApolloRequestRender();
+
+ expect(findPagination().exists()).toBe(false);
+ });
+
+ it('is wired to the correct pagination props', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findPagination().props()).toMatchObject({
+ hasNextPage: tagsPageInfo.hasNextPage,
+ hasPreviousPage: tagsPageInfo.hasPreviousPage,
+ });
+ });
+
+ it('fetch next page when user clicks next', async () => {
+ const resolver = jest.fn().mockResolvedValue(imageTagsMock());
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ findPagination().vm.$emit('next');
+
+ expect(resolver).toHaveBeenCalledWith(
+ expect.objectContaining({ after: tagsPageInfo.endCursor }),
+ );
+ });
+
+ it('fetch previous page when user clicks prev', async () => {
+ const resolver = jest.fn().mockResolvedValue(imageTagsMock());
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ findPagination().vm.$emit('prev');
+
+ expect(resolver).toHaveBeenCalledWith(
+ expect.objectContaining({ first: null, before: tagsPageInfo.startCursor }),
+ );
+ });
+ });
+
+ describe('loading state', () => {
+ it.each`
+ isImageLoading | queryExecuting | loadingVisible
+ ${true} | ${true} | ${true}
+ ${true} | ${false} | ${true}
+ ${false} | ${true} | ${true}
+ ${false} | ${false} | ${false}
+ `(
+ 'when the isImageLoading is $isImageLoading, and is $queryExecuting that the query is still executing is $loadingVisible that the loader is shown',
+ async ({ isImageLoading, queryExecuting, loadingVisible }) => {
+ mountComponent({ propsData: { isImageLoading, isMobile: false, id: 1 } });
+
+ if (!queryExecuting) {
+ await waitForApolloRequestRender();
+ }
+
+ expect(findTagsLoader().exists()).toBe(loadingVisible);
+ expect(findTagsListRow().exists()).toBe(!loadingVisible);
+ expect(findListTitle().exists()).toBe(!loadingVisible);
+ expect(findPagination().exists()).toBe(!loadingVisible);
+ },
+ );
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js
new file mode 100644
index 00000000000..060dc9dc5f3
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js
@@ -0,0 +1,45 @@
+import { shallowMount } from '@vue/test-utils';
+import component from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue';
+import { GlSkeletonLoader } from '../../stubs';
+
+describe('TagsLoader component', () => {
+ let wrapper;
+
+ const findGlSkeletonLoaders = () => wrapper.findAll(GlSkeletonLoader);
+
+ const mountComponent = () => {
+ wrapper = shallowMount(component, {
+ stubs: {
+ GlSkeletonLoader,
+ },
+ // set the repeat to 1 to avoid a long and verbose snapshot
+ loader: {
+ ...component.loader,
+ repeat: 1,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('produces the correct amount of loaders ', () => {
+ mountComponent();
+ expect(findGlSkeletonLoaders().length).toBe(1);
+ });
+
+ it('has the correct props', () => {
+ mountComponent();
+ expect(findGlSkeletonLoaders().at(0).props()).toMatchObject({
+ width: component.loader.width,
+ height: component.loader.height,
+ });
+ });
+
+ it('has the correct markup', () => {
+ mountComponent();
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap
index 56579847468..56579847468 100644
--- a/spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap
diff --git a/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
index 46b07b4c2d6..46b07b4c2d6 100644
--- a/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js
new file mode 100644
index 00000000000..e8ddad2d8ca
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js
@@ -0,0 +1,87 @@
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import CleanupStatus from '~/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue';
+import {
+ CLEANUP_TIMED_OUT_ERROR_MESSAGE,
+ CLEANUP_STATUS_SCHEDULED,
+ CLEANUP_STATUS_ONGOING,
+ CLEANUP_STATUS_UNFINISHED,
+ UNFINISHED_STATUS,
+ UNSCHEDULED_STATUS,
+ SCHEDULED_STATUS,
+ ONGOING_STATUS,
+} from '~/packages_and_registries/container_registry/explorer/constants';
+
+describe('cleanup_status', () => {
+ let wrapper;
+
+ const findMainIcon = () => wrapper.findByTestId('main-icon');
+ const findExtraInfoIcon = () => wrapper.findByTestId('extra-info');
+
+ const mountComponent = (propsData = { status: SCHEDULED_STATUS }) => {
+ wrapper = shallowMountExtended(CleanupStatus, {
+ propsData,
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it.each`
+ status | visible | text
+ ${UNFINISHED_STATUS} | ${true} | ${CLEANUP_STATUS_UNFINISHED}
+ ${SCHEDULED_STATUS} | ${true} | ${CLEANUP_STATUS_SCHEDULED}
+ ${ONGOING_STATUS} | ${true} | ${CLEANUP_STATUS_ONGOING}
+ ${UNSCHEDULED_STATUS} | ${false} | ${''}
+ `(
+ 'when the status is $status is $visible that the component is mounted and has the correct text',
+ ({ status, visible, text }) => {
+ mountComponent({ status });
+
+ expect(findMainIcon().exists()).toBe(visible);
+ expect(wrapper.text()).toBe(text);
+ },
+ );
+
+ describe('main icon', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findMainIcon().exists()).toBe(true);
+ });
+
+ it(`has the orange class when the status is ${UNFINISHED_STATUS}`, () => {
+ mountComponent({ status: UNFINISHED_STATUS });
+
+ expect(findMainIcon().classes('gl-text-orange-500')).toBe(true);
+ });
+ });
+
+ describe('extra info icon', () => {
+ it.each`
+ status | visible
+ ${UNFINISHED_STATUS} | ${true}
+ ${SCHEDULED_STATUS} | ${false}
+ ${ONGOING_STATUS} | ${false}
+ `(
+ 'when the status is $status is $visible that the extra icon is visible',
+ ({ status, visible }) => {
+ mountComponent({ status });
+
+ expect(findExtraInfoIcon().exists()).toBe(visible);
+ },
+ );
+
+ it(`has a tooltip`, () => {
+ mountComponent({ status: UNFINISHED_STATUS });
+
+ const tooltip = getBinding(findExtraInfoIcon().element, 'gl-tooltip');
+
+ expect(tooltip.value.title).toBe(CLEANUP_TIMED_OUT_ERROR_MESSAGE);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cli_commands_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cli_commands_spec.js
new file mode 100644
index 00000000000..4039fba869b
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cli_commands_spec.js
@@ -0,0 +1,94 @@
+import { GlDropdown } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import QuickstartDropdown from '~/packages_and_registries/container_registry/explorer/components/list_page/cli_commands.vue';
+import {
+ QUICK_START,
+ LOGIN_COMMAND_LABEL,
+ COPY_LOGIN_TITLE,
+ BUILD_COMMAND_LABEL,
+ COPY_BUILD_TITLE,
+ PUSH_COMMAND_LABEL,
+ COPY_PUSH_TITLE,
+} from '~/packages_and_registries/container_registry/explorer/constants';
+import Tracking from '~/tracking';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
+
+import { dockerCommands } from '../../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('cli_commands', () => {
+ let wrapper;
+
+ const config = {
+ repositoryUrl: 'foo',
+ registryHostUrlWithPort: 'bar',
+ };
+
+ const findDropdownButton = () => wrapper.find(GlDropdown);
+ const findCodeInstruction = () => wrapper.findAll(CodeInstruction);
+
+ const mountComponent = () => {
+ wrapper = mount(QuickstartDropdown, {
+ localVue,
+ provide() {
+ return {
+ config,
+ ...dockerCommands,
+ };
+ },
+ });
+ };
+
+ beforeEach(() => {
+ jest.spyOn(Tracking, 'event');
+ mountComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('shows the correct text on the button', () => {
+ expect(findDropdownButton().text()).toContain(QUICK_START);
+ });
+
+ it('clicking on the dropdown emit a tracking event', () => {
+ findDropdownButton().vm.$emit('shown');
+ expect(Tracking.event).toHaveBeenCalledWith(
+ undefined,
+ 'click_dropdown',
+ expect.objectContaining({ label: 'quickstart_dropdown' }),
+ );
+ });
+
+ describe.each`
+ index | labelText | titleText | command | trackedEvent
+ ${0} | ${LOGIN_COMMAND_LABEL} | ${COPY_LOGIN_TITLE} | ${dockerCommands.dockerLoginCommand} | ${'click_copy_login'}
+ ${1} | ${BUILD_COMMAND_LABEL} | ${COPY_BUILD_TITLE} | ${dockerCommands.dockerBuildCommand} | ${'click_copy_build'}
+ ${2} | ${PUSH_COMMAND_LABEL} | ${COPY_PUSH_TITLE} | ${dockerCommands.dockerPushCommand} | ${'click_copy_push'}
+ `('code instructions at $index', ({ index, labelText, titleText, command, trackedEvent }) => {
+ let codeInstruction;
+
+ beforeEach(() => {
+ codeInstruction = findCodeInstruction().at(index);
+ });
+
+ it('exists', () => {
+ expect(codeInstruction.exists()).toBe(true);
+ });
+
+ it(`has the correct props`, () => {
+ expect(codeInstruction.props()).toMatchObject({
+ label: labelText,
+ instruction: command,
+ copyText: titleText,
+ trackingAction: trackedEvent,
+ trackingLabel: 'quickstart_dropdown',
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js
new file mode 100644
index 00000000000..027cdf732bc
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js
@@ -0,0 +1,37 @@
+import { GlSprintf } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import groupEmptyState from '~/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state.vue';
+import { GlEmptyState } from '../../stubs';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('Registry Group Empty state', () => {
+ let wrapper;
+ const config = {
+ noContainersImage: 'foo',
+ helpPagePath: 'baz',
+ };
+
+ beforeEach(() => {
+ wrapper = shallowMount(groupEmptyState, {
+ localVue,
+ stubs: {
+ GlEmptyState,
+ GlSprintf,
+ },
+ provide() {
+ return { config };
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('to match the default snapshot', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js
new file mode 100644
index 00000000000..411bef54e40
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js
@@ -0,0 +1,223 @@
+import { GlIcon, GlSprintf, GlSkeletonLoader } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import DeleteButton from '~/packages_and_registries/container_registry/explorer/components/delete_button.vue';
+import CleanupStatus from '~/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue';
+import Component from '~/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue';
+import {
+ ROW_SCHEDULED_FOR_DELETION,
+ LIST_DELETE_BUTTON_DISABLED,
+ REMOVE_REPOSITORY_LABEL,
+ IMAGE_DELETE_SCHEDULED_STATUS,
+ SCHEDULED_STATUS,
+ ROOT_IMAGE_TEXT,
+} from '~/packages_and_registries/container_registry/explorer/constants';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
+import { imagesListResponse } from '../../mock_data';
+import { RouterLink } from '../../stubs';
+
+describe('Image List Row', () => {
+ let wrapper;
+ const [item] = imagesListResponse;
+
+ const findDetailsLink = () => wrapper.find('[data-testid="details-link"]');
+ const findTagsCount = () => wrapper.find('[data-testid="tags-count"]');
+ const findDeleteBtn = () => wrapper.findComponent(DeleteButton);
+ const findClipboardButton = () => wrapper.findComponent(ClipboardButton);
+ const findCleanupStatus = () => wrapper.findComponent(CleanupStatus);
+ const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
+ const findListItemComponent = () => wrapper.findComponent(ListItem);
+
+ const mountComponent = (props) => {
+ wrapper = shallowMount(Component, {
+ stubs: {
+ RouterLink,
+ GlSprintf,
+ ListItem,
+ },
+ propsData: {
+ item,
+ ...props,
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('list item component', () => {
+ describe('tooltip', () => {
+ it(`the title is ${ROW_SCHEDULED_FOR_DELETION}`, () => {
+ mountComponent();
+
+ const tooltip = getBinding(wrapper.element, 'gl-tooltip');
+ expect(tooltip).toBeDefined();
+ expect(tooltip.value.title).toBe(ROW_SCHEDULED_FOR_DELETION);
+ });
+
+ it('is disabled when item is being deleted', () => {
+ mountComponent({ item: { ...item, status: IMAGE_DELETE_SCHEDULED_STATUS } });
+
+ const tooltip = getBinding(wrapper.element, 'gl-tooltip');
+ expect(tooltip.value.disabled).toBe(false);
+ });
+ });
+
+ it('is disabled when the item is in deleting status', () => {
+ mountComponent({ item: { ...item, status: IMAGE_DELETE_SCHEDULED_STATUS } });
+
+ expect(findListItemComponent().props('disabled')).toBe(true);
+ });
+ });
+
+ describe('image title and path', () => {
+ it('contains a link to the details page', () => {
+ mountComponent();
+
+ const link = findDetailsLink();
+ expect(link.text()).toBe(item.path);
+ expect(findDetailsLink().props('to')).toMatchObject({
+ name: 'details',
+ params: {
+ id: getIdFromGraphQLId(item.id),
+ },
+ });
+ });
+
+ it(`when the image has no name appends ${ROOT_IMAGE_TEXT} to the path`, () => {
+ mountComponent({ item: { ...item, name: '' } });
+
+ expect(findDetailsLink().text()).toBe(`${item.path}/ ${ROOT_IMAGE_TEXT}`);
+ });
+
+ it('contains a clipboard button', () => {
+ mountComponent();
+ const button = findClipboardButton();
+ expect(button.exists()).toBe(true);
+ expect(button.props('text')).toBe(item.location);
+ expect(button.props('title')).toBe(item.location);
+ });
+
+ describe('cleanup status component', () => {
+ it.each`
+ expirationPolicyCleanupStatus | shown
+ ${null} | ${false}
+ ${SCHEDULED_STATUS} | ${true}
+ `(
+ 'when expirationPolicyCleanupStatus is $expirationPolicyCleanupStatus it is $shown that the component exists',
+ ({ expirationPolicyCleanupStatus, shown }) => {
+ mountComponent({ item: { ...item, expirationPolicyCleanupStatus } });
+
+ expect(findCleanupStatus().exists()).toBe(shown);
+
+ if (shown) {
+ expect(findCleanupStatus().props()).toMatchObject({
+ status: expirationPolicyCleanupStatus,
+ });
+ }
+ },
+ );
+ });
+
+ describe('when the item is deleting', () => {
+ beforeEach(() => {
+ mountComponent({ item: { ...item, status: IMAGE_DELETE_SCHEDULED_STATUS } });
+ });
+
+ it('the router link is disabled', () => {
+ // we check the event prop as is the only workaround to disable a router link
+ expect(findDetailsLink().props('event')).toBe('');
+ });
+ it('the clipboard button is disabled', () => {
+ expect(findClipboardButton().attributes('disabled')).toBe('true');
+ });
+ });
+ });
+
+ describe('delete button', () => {
+ it('exists', () => {
+ mountComponent();
+ expect(findDeleteBtn().exists()).toBe(true);
+ });
+
+ it('has the correct props', () => {
+ mountComponent();
+
+ expect(findDeleteBtn().props()).toMatchObject({
+ title: REMOVE_REPOSITORY_LABEL,
+ tooltipDisabled: item.canDelete,
+ tooltipTitle: LIST_DELETE_BUTTON_DISABLED,
+ });
+ });
+
+ it('emits a delete event', () => {
+ mountComponent();
+
+ findDeleteBtn().vm.$emit('delete');
+ expect(wrapper.emitted('delete')).toEqual([[item]]);
+ });
+
+ it.each`
+ canDelete | status | state
+ ${false} | ${''} | ${true}
+ ${false} | ${IMAGE_DELETE_SCHEDULED_STATUS} | ${true}
+ ${true} | ${IMAGE_DELETE_SCHEDULED_STATUS} | ${true}
+ ${true} | ${''} | ${false}
+ `(
+ 'disabled is $state when canDelete is $canDelete and status is $status',
+ ({ canDelete, status, state }) => {
+ mountComponent({ item: { ...item, canDelete, status } });
+
+ expect(findDeleteBtn().props('disabled')).toBe(state);
+ },
+ );
+ });
+
+ describe('tags count', () => {
+ it('exists', () => {
+ mountComponent();
+ expect(findTagsCount().exists()).toBe(true);
+ });
+
+ it('contains a tag icon', () => {
+ mountComponent();
+ const icon = findTagsCount().find(GlIcon);
+ expect(icon.exists()).toBe(true);
+ expect(icon.props('name')).toBe('tag');
+ });
+
+ describe('loading state', () => {
+ it('shows a loader when metadataLoading is true', () => {
+ mountComponent({ metadataLoading: true });
+
+ expect(findSkeletonLoader().exists()).toBe(true);
+ });
+
+ it('hides the tags count while loading', () => {
+ mountComponent({ metadataLoading: true });
+
+ expect(findTagsCount().exists()).toBe(false);
+ });
+ });
+
+ describe('tags count text', () => {
+ it('with one tag in the image', () => {
+ mountComponent({ item: { ...item, tagsCount: 1 } });
+
+ expect(findTagsCount().text()).toMatchInterpolatedText('1 Tag');
+ });
+ it('with more than one tag in the image', () => {
+ mountComponent({ item: { ...item, tagsCount: 3 } });
+
+ expect(findTagsCount().text()).toMatchInterpolatedText('3 Tags');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js
new file mode 100644
index 00000000000..e0119954ed4
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js
@@ -0,0 +1,88 @@
+import { GlKeysetPagination } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Component from '~/packages_and_registries/container_registry/explorer/components/list_page/image_list.vue';
+import ImageListRow from '~/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue';
+
+import { imagesListResponse, pageInfo as defaultPageInfo } from '../../mock_data';
+
+describe('Image List', () => {
+ let wrapper;
+
+ const findRow = () => wrapper.findAll(ImageListRow);
+ const findPagination = () => wrapper.find(GlKeysetPagination);
+
+ const mountComponent = (props) => {
+ wrapper = shallowMount(Component, {
+ propsData: {
+ images: imagesListResponse,
+ pageInfo: defaultPageInfo,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('list', () => {
+ it('contains one list element for each image', () => {
+ mountComponent();
+
+ expect(findRow().length).toBe(imagesListResponse.length);
+ });
+
+ it('when delete event is emitted on the row it emits up a delete event', () => {
+ mountComponent();
+
+ findRow().at(0).vm.$emit('delete', 'foo');
+ expect(wrapper.emitted('delete')).toEqual([['foo']]);
+ });
+
+ it('passes down the metadataLoading prop', () => {
+ mountComponent({ metadataLoading: true });
+ expect(findRow().at(0).props('metadataLoading')).toBe(true);
+ });
+ });
+
+ describe('pagination', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findPagination().exists()).toBe(true);
+ });
+
+ it.each`
+ hasNextPage | hasPreviousPage | isVisible
+ ${true} | ${true} | ${true}
+ ${true} | ${false} | ${true}
+ ${false} | ${true} | ${true}
+ `(
+ 'when hasNextPage is $hasNextPage and hasPreviousPage is $hasPreviousPage: is $isVisible that the component is visible',
+ ({ hasNextPage, hasPreviousPage, isVisible }) => {
+ mountComponent({ pageInfo: { ...defaultPageInfo, hasNextPage, hasPreviousPage } });
+
+ expect(findPagination().exists()).toBe(isVisible);
+ expect(findPagination().props('hasPreviousPage')).toBe(hasPreviousPage);
+ expect(findPagination().props('hasNextPage')).toBe(hasNextPage);
+ },
+ );
+
+ it('emits "prev-page" when the user clicks the back page button', () => {
+ mountComponent();
+
+ findPagination().vm.$emit('prev');
+
+ expect(wrapper.emitted('prev-page')).toEqual([[]]);
+ });
+
+ it('emits "next-page" when the user clicks the forward page button', () => {
+ mountComponent();
+
+ findPagination().vm.$emit('next');
+
+ expect(wrapper.emitted('next-page')).toEqual([[]]);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js
new file mode 100644
index 00000000000..21748ae2813
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js
@@ -0,0 +1,45 @@
+import { GlSprintf } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import projectEmptyState from '~/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state.vue';
+import { dockerCommands } from '../../mock_data';
+import { GlEmptyState } from '../../stubs';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('Registry Project Empty state', () => {
+ let wrapper;
+ const config = {
+ repositoryUrl: 'foo',
+ registryHostUrlWithPort: 'bar',
+ helpPagePath: 'baz',
+ twoFactorAuthHelpLink: 'barBaz',
+ personalAccessTokensHelpLink: 'fooBaz',
+ noContainersImage: 'bazFoo',
+ };
+
+ beforeEach(() => {
+ wrapper = shallowMount(projectEmptyState, {
+ localVue,
+ stubs: {
+ GlEmptyState,
+ GlSprintf,
+ },
+ provide() {
+ return {
+ config,
+ ...dockerCommands,
+ };
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('to match the default snapshot', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js
new file mode 100644
index 00000000000..92cfeb7633e
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js
@@ -0,0 +1,135 @@
+import { GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Component from '~/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue';
+import {
+ CONTAINER_REGISTRY_TITLE,
+ LIST_INTRO_TEXT,
+ EXPIRATION_POLICY_DISABLED_TEXT,
+} from '~/packages_and_registries/container_registry/explorer/constants';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+
+jest.mock('~/lib/utils/datetime_utility', () => ({
+ approximateDuration: jest.fn(),
+ calculateRemainingMilliseconds: jest.fn(),
+}));
+
+describe('registry_header', () => {
+ let wrapper;
+
+ const findTitleArea = () => wrapper.find(TitleArea);
+ const findCommandsSlot = () => wrapper.find('[data-testid="commands-slot"]');
+ const findImagesCountSubHeader = () => wrapper.find('[data-testid="images-count"]');
+ const findExpirationPolicySubHeader = () => wrapper.find('[data-testid="expiration-policy"]');
+
+ const mountComponent = (propsData, slots) => {
+ wrapper = shallowMount(Component, {
+ stubs: {
+ GlSprintf,
+ TitleArea,
+ },
+ propsData,
+ slots,
+ });
+ return wrapper.vm.$nextTick();
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('header', () => {
+ it('has a title', () => {
+ mountComponent({ metadataLoading: true });
+
+ expect(findTitleArea().props()).toMatchObject({
+ title: CONTAINER_REGISTRY_TITLE,
+ metadataLoading: true,
+ });
+ });
+
+ it('has a commands slot', () => {
+ mountComponent(null, { commands: '<div data-testid="commands-slot">baz</div>' });
+
+ expect(findCommandsSlot().text()).toBe('baz');
+ });
+
+ describe('sub header parts', () => {
+ describe('images count', () => {
+ it('exists', async () => {
+ await mountComponent({ imagesCount: 1 });
+
+ expect(findImagesCountSubHeader().exists()).toBe(true);
+ });
+
+ it('when there is one image', async () => {
+ await mountComponent({ imagesCount: 1 });
+
+ expect(findImagesCountSubHeader().props()).toMatchObject({
+ text: '1 Image repository',
+ icon: 'container-image',
+ });
+ });
+
+ it('when there is more than one image', async () => {
+ await mountComponent({ imagesCount: 3 });
+
+ expect(findImagesCountSubHeader().props('text')).toBe('3 Image repositories');
+ });
+ });
+
+ describe('expiration policy', () => {
+ it('when is disabled', async () => {
+ await mountComponent({
+ expirationPolicy: { enabled: false },
+ expirationPolicyHelpPagePath: 'foo',
+ imagesCount: 1,
+ });
+
+ const text = findExpirationPolicySubHeader();
+ expect(text.exists()).toBe(true);
+ expect(text.props()).toMatchObject({
+ text: EXPIRATION_POLICY_DISABLED_TEXT,
+ icon: 'expire',
+ size: 'xl',
+ });
+ });
+
+ it('when is enabled', async () => {
+ await mountComponent({
+ expirationPolicy: { enabled: true },
+ expirationPolicyHelpPagePath: 'foo',
+ imagesCount: 1,
+ });
+
+ const text = findExpirationPolicySubHeader();
+ expect(text.exists()).toBe(true);
+ expect(text.props('text')).toBe('Expiration policy will run in ');
+ });
+ it('when the expiration policy is completely disabled', async () => {
+ await mountComponent({
+ expirationPolicy: { enabled: true },
+ expirationPolicyHelpPagePath: 'foo',
+ imagesCount: 1,
+ hideExpirationPolicyData: true,
+ });
+
+ const text = findExpirationPolicySubHeader();
+ expect(text.exists()).toBe(false);
+ });
+ });
+ });
+ });
+
+ describe('info messages', () => {
+ describe('default message', () => {
+ it('is correctly bound to title_area props', () => {
+ mountComponent({ helpPagePath: 'foo' });
+
+ expect(findTitleArea().props('infoMessages')).toEqual([
+ { text: LIST_INTRO_TEXT, link: 'foo' },
+ ]);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/registry_breadcrumb_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/registry_breadcrumb_spec.js
new file mode 100644
index 00000000000..e5a8438f23f
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/registry_breadcrumb_spec.js
@@ -0,0 +1,78 @@
+import { mount } from '@vue/test-utils';
+
+import component from '~/packages_and_registries/container_registry/explorer/components/registry_breadcrumb.vue';
+
+describe('Registry Breadcrumb', () => {
+ let wrapper;
+ const nameGenerator = jest.fn();
+
+ const routes = [
+ { name: 'list', path: '/', meta: { nameGenerator, root: true } },
+ { name: 'details', path: '/:id', meta: { nameGenerator } },
+ ];
+
+ const mountComponent = ($route) => {
+ wrapper = mount(component, {
+ mocks: {
+ $route,
+ $router: {
+ options: {
+ routes,
+ },
+ },
+ },
+ });
+ };
+
+ beforeEach(() => {
+ nameGenerator.mockClear();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when is rootRoute', () => {
+ beforeEach(() => {
+ mountComponent(routes[0]);
+ });
+
+ it('renders', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('contains only a single router-link to list', () => {
+ const links = wrapper.findAll('a');
+
+ expect(links).toHaveLength(1);
+ expect(links.at(0).attributes('href')).toBe('/');
+ });
+
+ it('the link text is calculated by nameGenerator', () => {
+ expect(nameGenerator).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('when is not rootRoute', () => {
+ beforeEach(() => {
+ mountComponent(routes[1]);
+ });
+
+ it('renders', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('contains two router-links to list and details', () => {
+ const links = wrapper.findAll('a');
+
+ expect(links).toHaveLength(2);
+ expect(links.at(0).attributes('href')).toBe('/');
+ expect(links.at(1).attributes('href')).toBe('#');
+ });
+
+ it('the link text is calculated by nameGenerator', () => {
+ expect(nameGenerator).toHaveBeenCalledTimes(2);
+ });
+ });
+});
diff --git a/spec/frontend/registry/explorer/mock_data.js b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
index 6a835a28807..6a835a28807 100644
--- a/spec/frontend/registry/explorer/mock_data.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
new file mode 100644
index 00000000000..adc9a64e5c9
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
@@ -0,0 +1,521 @@
+import { GlKeysetPagination } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import axios from '~/lib/utils/axios_utils';
+import DeleteImage from '~/packages_and_registries/container_registry/explorer/components/delete_image.vue';
+import DeleteAlert from '~/packages_and_registries/container_registry/explorer/components/details_page/delete_alert.vue';
+import DetailsHeader from '~/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue';
+import EmptyTagsState from '~/packages_and_registries/container_registry/explorer/components/details_page/empty_state.vue';
+import PartialCleanupAlert from '~/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert.vue';
+import StatusAlert from '~/packages_and_registries/container_registry/explorer/components/details_page/status_alert.vue';
+import TagsList from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue';
+import TagsLoader from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue';
+
+import {
+ UNFINISHED_STATUS,
+ DELETE_SCHEDULED,
+ ALERT_DANGER_IMAGE,
+ MISSING_OR_DELETED_IMAGE_BREADCRUMB,
+ ROOT_IMAGE_TEXT,
+} from '~/packages_and_registries/container_registry/explorer/constants';
+import deleteContainerRepositoryTagsMutation from '~/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql';
+import getContainerRepositoryDetailsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
+
+import component from '~/packages_and_registries/container_registry/explorer/pages/details.vue';
+import Tracking from '~/tracking';
+
+import {
+ graphQLImageDetailsMock,
+ graphQLDeleteImageRepositoryTagsMock,
+ containerRepositoryMock,
+ graphQLEmptyImageDetailsMock,
+ tagsMock,
+} from '../mock_data';
+import { DeleteModal } from '../stubs';
+
+const localVue = createLocalVue();
+
+describe('Details Page', () => {
+ let wrapper;
+ let apolloProvider;
+
+ const findDeleteModal = () => wrapper.find(DeleteModal);
+ const findPagination = () => wrapper.find(GlKeysetPagination);
+ const findTagsLoader = () => wrapper.find(TagsLoader);
+ const findTagsList = () => wrapper.find(TagsList);
+ const findDeleteAlert = () => wrapper.find(DeleteAlert);
+ const findDetailsHeader = () => wrapper.find(DetailsHeader);
+ const findEmptyState = () => wrapper.find(EmptyTagsState);
+ const findPartialCleanupAlert = () => wrapper.find(PartialCleanupAlert);
+ const findStatusAlert = () => wrapper.find(StatusAlert);
+ const findDeleteImage = () => wrapper.find(DeleteImage);
+
+ const routeId = 1;
+
+ const breadCrumbState = {
+ updateName: jest.fn(),
+ };
+
+ const cleanTags = tagsMock.map((t) => {
+ const result = { ...t };
+ // eslint-disable-next-line no-underscore-dangle
+ delete result.__typename;
+ return result;
+ });
+
+ const waitForApolloRequestRender = async () => {
+ await waitForPromises();
+ await wrapper.vm.$nextTick();
+ };
+
+ const mountComponent = ({
+ resolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock()),
+ mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock),
+ options,
+ config = {},
+ } = {}) => {
+ localVue.use(VueApollo);
+
+ const requestHandlers = [
+ [getContainerRepositoryDetailsQuery, resolver],
+ [deleteContainerRepositoryTagsMutation, mutationResolver],
+ ];
+
+ apolloProvider = createMockApollo(requestHandlers);
+
+ wrapper = shallowMount(component, {
+ localVue,
+ apolloProvider,
+ stubs: {
+ DeleteModal,
+ DeleteImage,
+ },
+ mocks: {
+ $route: {
+ params: {
+ id: routeId,
+ },
+ },
+ },
+ provide() {
+ return {
+ breadCrumbState,
+ config,
+ };
+ },
+ ...options,
+ });
+ };
+
+ beforeEach(() => {
+ jest.spyOn(Tracking, 'event');
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when isLoading is true', () => {
+ it('shows the loader', () => {
+ mountComponent();
+
+ expect(findTagsLoader().exists()).toBe(true);
+ });
+
+ it('does not show the list', () => {
+ mountComponent();
+
+ expect(findTagsList().exists()).toBe(false);
+ });
+ });
+
+ describe('when the image does not exist', () => {
+ it('does not show the default ui', async () => {
+ mountComponent({ resolver: jest.fn().mockResolvedValue(graphQLEmptyImageDetailsMock) });
+
+ await waitForApolloRequestRender();
+
+ expect(findTagsLoader().exists()).toBe(false);
+ expect(findDetailsHeader().exists()).toBe(false);
+ expect(findTagsList().exists()).toBe(false);
+ expect(findPagination().exists()).toBe(false);
+ });
+
+ it('shows an empty state message', async () => {
+ mountComponent({ resolver: jest.fn().mockResolvedValue(graphQLEmptyImageDetailsMock) });
+
+ await waitForApolloRequestRender();
+
+ expect(findEmptyState().exists()).toBe(true);
+ });
+ });
+
+ describe('list', () => {
+ it('exists', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findTagsList().exists()).toBe(true);
+ });
+
+ it('has the correct props bound', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findTagsList().props()).toMatchObject({
+ isMobile: false,
+ });
+ });
+
+ describe('deleteEvent', () => {
+ describe('single item', () => {
+ let tagToBeDeleted;
+ beforeEach(async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ [tagToBeDeleted] = cleanTags;
+ findTagsList().vm.$emit('delete', [tagToBeDeleted]);
+ });
+
+ it('open the modal', async () => {
+ expect(DeleteModal.methods.show).toHaveBeenCalled();
+ });
+
+ it('tracks a single delete event', () => {
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
+ label: 'registry_tag_delete',
+ });
+ });
+ });
+
+ describe('multiple items', () => {
+ beforeEach(async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ findTagsList().vm.$emit('delete', cleanTags);
+ });
+
+ it('open the modal', () => {
+ expect(DeleteModal.methods.show).toHaveBeenCalled();
+ });
+
+ it('tracks a single delete event', () => {
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
+ label: 'bulk_registry_tag_delete',
+ });
+ });
+ });
+ });
+ });
+
+ describe('modal', () => {
+ it('exists', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findDeleteModal().exists()).toBe(true);
+ });
+
+ describe('cancel event', () => {
+ it('tracks cancel_delete', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ findDeleteModal().vm.$emit('cancel');
+
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, 'cancel_delete', {
+ label: 'registry_tag_delete',
+ });
+ });
+ });
+
+ describe('confirmDelete event', () => {
+ let mutationResolver;
+
+ beforeEach(() => {
+ mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock);
+ mountComponent({ mutationResolver });
+
+ return waitForApolloRequestRender();
+ });
+ describe('when one item is selected to be deleted', () => {
+ it('calls apollo mutation with the right parameters', async () => {
+ findTagsList().vm.$emit('delete', [cleanTags[0]]);
+
+ await wrapper.vm.$nextTick();
+
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(mutationResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ tagNames: [cleanTags[0].name] }),
+ );
+ });
+ });
+
+ describe('when more than one item is selected to be deleted', () => {
+ it('calls apollo mutation with the right parameters', async () => {
+ findTagsList().vm.$emit('delete', tagsMock);
+
+ await wrapper.vm.$nextTick();
+
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(mutationResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ tagNames: tagsMock.map((t) => t.name) }),
+ );
+ });
+ });
+ });
+ });
+
+ describe('Header', () => {
+ it('exists', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+ expect(findDetailsHeader().exists()).toBe(true);
+ });
+
+ it('has the correct props', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+ expect(findDetailsHeader().props()).toMatchObject({
+ image: {
+ name: containerRepositoryMock.name,
+ project: {
+ visibility: containerRepositoryMock.project.visibility,
+ },
+ },
+ });
+ });
+ });
+
+ describe('Delete Alert', () => {
+ const config = {
+ isAdmin: true,
+ garbageCollectionHelpPagePath: 'baz',
+ };
+ const deleteAlertType = 'success_tag';
+
+ it('exists', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+ expect(findDeleteAlert().exists()).toBe(true);
+ });
+
+ it('has the correct props', async () => {
+ mountComponent({
+ options: {
+ data: () => ({
+ deleteAlertType,
+ }),
+ },
+ config,
+ });
+
+ await waitForApolloRequestRender();
+
+ expect(findDeleteAlert().props()).toEqual({ ...config, deleteAlertType });
+ });
+ });
+
+ describe('Partial Cleanup Alert', () => {
+ const config = {
+ runCleanupPoliciesHelpPagePath: 'foo',
+ expirationPolicyHelpPagePath: 'bar',
+ userCalloutsPath: 'call_out_path',
+ userCalloutId: 'call_out_id',
+ showUnfinishedTagCleanupCallout: true,
+ };
+
+ describe(`when expirationPolicyCleanupStatus is ${UNFINISHED_STATUS}`, () => {
+ let resolver;
+
+ beforeEach(() => {
+ resolver = jest.fn().mockResolvedValue(
+ graphQLImageDetailsMock({
+ expirationPolicyCleanupStatus: UNFINISHED_STATUS,
+ }),
+ );
+ });
+
+ it('exists', async () => {
+ mountComponent({ resolver, config });
+
+ await waitForApolloRequestRender();
+
+ expect(findPartialCleanupAlert().exists()).toBe(true);
+ });
+
+ it('has the correct props', async () => {
+ mountComponent({ resolver, config });
+
+ await waitForApolloRequestRender();
+
+ expect(findPartialCleanupAlert().props()).toEqual({
+ runCleanupPoliciesHelpPagePath: config.runCleanupPoliciesHelpPagePath,
+ cleanupPoliciesHelpPagePath: config.expirationPolicyHelpPagePath,
+ });
+ });
+
+ it('dismiss hides the component', async () => {
+ jest.spyOn(axios, 'post').mockReturnValue();
+
+ mountComponent({ resolver, config });
+
+ await waitForApolloRequestRender();
+
+ expect(findPartialCleanupAlert().exists()).toBe(true);
+
+ findPartialCleanupAlert().vm.$emit('dismiss');
+
+ await wrapper.vm.$nextTick();
+
+ expect(axios.post).toHaveBeenCalledWith(config.userCalloutsPath, {
+ feature_name: config.userCalloutId,
+ });
+ expect(findPartialCleanupAlert().exists()).toBe(false);
+ });
+
+ it('is hidden if the callout is dismissed', async () => {
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ expect(findPartialCleanupAlert().exists()).toBe(false);
+ });
+ });
+
+ describe(`when expirationPolicyCleanupStatus is not ${UNFINISHED_STATUS}`, () => {
+ it('the component is hidden', async () => {
+ mountComponent({ config });
+
+ await waitForApolloRequestRender();
+
+ expect(findPartialCleanupAlert().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('Breadcrumb connection', () => {
+ it('when the details are fetched updates the name', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(breadCrumbState.updateName).toHaveBeenCalledWith(containerRepositoryMock.name);
+ });
+
+ it(`when the image is missing set the breadcrumb to ${MISSING_OR_DELETED_IMAGE_BREADCRUMB}`, async () => {
+ mountComponent({ resolver: jest.fn().mockResolvedValue(graphQLEmptyImageDetailsMock) });
+
+ await waitForApolloRequestRender();
+
+ expect(breadCrumbState.updateName).toHaveBeenCalledWith(MISSING_OR_DELETED_IMAGE_BREADCRUMB);
+ });
+
+ it(`when the image has no name set the breadcrumb to ${ROOT_IMAGE_TEXT}`, async () => {
+ mountComponent({
+ resolver: jest
+ .fn()
+ .mockResolvedValue(graphQLImageDetailsMock({ ...containerRepositoryMock, name: null })),
+ });
+
+ await waitForApolloRequestRender();
+
+ expect(breadCrumbState.updateName).toHaveBeenCalledWith(ROOT_IMAGE_TEXT);
+ });
+ });
+
+ describe('when the image has a status different from null', () => {
+ const resolver = jest
+ .fn()
+ .mockResolvedValue(graphQLImageDetailsMock({ status: DELETE_SCHEDULED }));
+ it('disables all the actions', async () => {
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ expect(findDetailsHeader().props('disabled')).toBe(true);
+ expect(findTagsList().props('disabled')).toBe(true);
+ });
+
+ it('shows a status alert', async () => {
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ expect(findStatusAlert().exists()).toBe(true);
+ expect(findStatusAlert().props()).toMatchObject({
+ status: DELETE_SCHEDULED,
+ });
+ });
+ });
+
+ describe('delete the image', () => {
+ const mountComponentAndDeleteImage = async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+ findDetailsHeader().vm.$emit('delete');
+
+ await wrapper.vm.$nextTick();
+ };
+
+ it('on delete event it deletes the image', async () => {
+ await mountComponentAndDeleteImage();
+
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(findDeleteImage().emitted('start')).toEqual([[]]);
+ });
+
+ it('binds the correct props to the modal', async () => {
+ await mountComponentAndDeleteImage();
+
+ expect(findDeleteModal().props()).toMatchObject({
+ itemsToBeDeleted: [{ path: 'gitlab-org/gitlab-test/rails-12009' }],
+ deleteImage: true,
+ });
+ });
+
+ it('binds correctly to delete-image start and end events', async () => {
+ mountComponent();
+
+ findDeleteImage().vm.$emit('start');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findTagsLoader().exists()).toBe(true);
+
+ findDeleteImage().vm.$emit('end');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findTagsLoader().exists()).toBe(false);
+ });
+
+ it('binds correctly to delete-image error event', async () => {
+ mountComponent();
+
+ findDeleteImage().vm.$emit('error');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findDeleteAlert().props('deleteAlertType')).toBe(ALERT_DANGER_IMAGE);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/pages/index_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/index_spec.js
new file mode 100644
index 00000000000..5f4cb8969bc
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/index_spec.js
@@ -0,0 +1,24 @@
+import { shallowMount } from '@vue/test-utils';
+import component from '~/packages_and_registries/container_registry/explorer/pages/index.vue';
+
+describe('List Page', () => {
+ let wrapper;
+
+ const findRouterView = () => wrapper.find({ ref: 'router-view' });
+
+ const mountComponent = () => {
+ wrapper = shallowMount(component, {
+ stubs: {
+ RouterView: true,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('has a router view', () => {
+ expect(findRouterView().exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js
new file mode 100644
index 00000000000..051d1e2a169
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js
@@ -0,0 +1,597 @@
+import { GlSkeletonLoader, GlSprintf, GlAlert } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
+import CleanupPolicyEnabledAlert from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
+import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
+import DeleteImage from '~/packages_and_registries/container_registry/explorer/components/delete_image.vue';
+import CliCommands from '~/packages_and_registries/container_registry/explorer/components/list_page/cli_commands.vue';
+import GroupEmptyState from '~/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state.vue';
+import ImageList from '~/packages_and_registries/container_registry/explorer/components/list_page/image_list.vue';
+import ProjectEmptyState from '~/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state.vue';
+import RegistryHeader from '~/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue';
+import {
+ DELETE_IMAGE_SUCCESS_MESSAGE,
+ DELETE_IMAGE_ERROR_MESSAGE,
+ SORT_FIELDS,
+} from '~/packages_and_registries/container_registry/explorer/constants';
+import deleteContainerRepositoryMutation from '~/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql';
+import getContainerRepositoriesDetails from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repositories_details.query.graphql';
+import component from '~/packages_and_registries/container_registry/explorer/pages/list.vue';
+import Tracking from '~/tracking';
+import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+
+import { $toast } from 'jest/packages_and_registries/shared/mocks';
+import {
+ graphQLImageListMock,
+ graphQLImageDeleteMock,
+ deletedContainerRepository,
+ graphQLEmptyImageListMock,
+ graphQLEmptyGroupImageListMock,
+ pageInfo,
+ graphQLProjectImageRepositoriesDetailsMock,
+ dockerCommands,
+} from '../mock_data';
+import { GlModal, GlEmptyState } from '../stubs';
+
+const localVue = createLocalVue();
+
+describe('List Page', () => {
+ let wrapper;
+ let apolloProvider;
+
+ const findDeleteModal = () => wrapper.findComponent(GlModal);
+ const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
+
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+
+ const findCliCommands = () => wrapper.findComponent(CliCommands);
+ const findProjectEmptyState = () => wrapper.findComponent(ProjectEmptyState);
+ const findGroupEmptyState = () => wrapper.findComponent(GroupEmptyState);
+ const findRegistryHeader = () => wrapper.findComponent(RegistryHeader);
+
+ const findDeleteAlert = () => wrapper.findComponent(GlAlert);
+ const findImageList = () => wrapper.findComponent(ImageList);
+ const findRegistrySearch = () => wrapper.findComponent(RegistrySearch);
+ const findEmptySearchMessage = () => wrapper.find('[data-testid="emptySearch"]');
+ const findDeleteImage = () => wrapper.findComponent(DeleteImage);
+ const findCleanupAlert = () => wrapper.findComponent(CleanupPolicyEnabledAlert);
+
+ const waitForApolloRequestRender = async () => {
+ jest.runOnlyPendingTimers();
+ await waitForPromises();
+ await nextTick();
+ };
+
+ const mountComponent = ({
+ mocks,
+ resolver = jest.fn().mockResolvedValue(graphQLImageListMock),
+ detailsResolver = jest.fn().mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock),
+ mutationResolver = jest.fn().mockResolvedValue(graphQLImageDeleteMock),
+ config = { isGroupPage: false },
+ query = {},
+ } = {}) => {
+ localVue.use(VueApollo);
+
+ const requestHandlers = [
+ [getContainerRepositoriesQuery, resolver],
+ [getContainerRepositoriesDetails, detailsResolver],
+ [deleteContainerRepositoryMutation, mutationResolver],
+ ];
+
+ apolloProvider = createMockApollo(requestHandlers);
+
+ wrapper = shallowMount(component, {
+ localVue,
+ apolloProvider,
+ stubs: {
+ GlModal,
+ GlEmptyState,
+ GlSprintf,
+ RegistryHeader,
+ TitleArea,
+ DeleteImage,
+ },
+ mocks: {
+ $toast,
+ $route: {
+ name: 'foo',
+ query,
+ },
+ ...mocks,
+ },
+ provide() {
+ return {
+ config,
+ ...dockerCommands,
+ };
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('contains registry header', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findRegistryHeader().exists()).toBe(true);
+ expect(findRegistryHeader().props()).toMatchObject({
+ imagesCount: 2,
+ metadataLoading: false,
+ });
+ });
+
+ describe.each([
+ { error: 'connectionError', errorName: 'connection error' },
+ { error: 'invalidPathError', errorName: 'invalid path error' },
+ ])('handling $errorName', ({ error }) => {
+ const config = {
+ containersErrorImage: 'foo',
+ helpPagePath: 'bar',
+ isGroupPage: false,
+ };
+ config[error] = true;
+
+ it('should show an empty state', () => {
+ mountComponent({ config });
+
+ expect(findEmptyState().exists()).toBe(true);
+ });
+
+ it('empty state should have an svg-path', () => {
+ mountComponent({ config });
+
+ expect(findEmptyState().props('svgPath')).toBe(config.containersErrorImage);
+ });
+
+ it('empty state should have a description', () => {
+ mountComponent({ config });
+
+ expect(findEmptyState().props('title')).toContain('connection error');
+ });
+
+ it('should not show the loading or default state', () => {
+ mountComponent({ config });
+
+ expect(findSkeletonLoader().exists()).toBe(false);
+ expect(findImageList().exists()).toBe(false);
+ });
+ });
+
+ describe('isLoading is true', () => {
+ it('shows the skeleton loader', async () => {
+ mountComponent();
+
+ await nextTick();
+
+ expect(findSkeletonLoader().exists()).toBe(true);
+ });
+
+ it('imagesList is not visible', () => {
+ mountComponent();
+
+ expect(findImageList().exists()).toBe(false);
+ });
+
+ it('cli commands is not visible', () => {
+ mountComponent();
+
+ expect(findCliCommands().exists()).toBe(false);
+ });
+
+ it('title has the metadataLoading props set to true', async () => {
+ mountComponent();
+
+ await nextTick();
+
+ expect(findRegistryHeader().props('metadataLoading')).toBe(true);
+ });
+ });
+
+ describe('list is empty', () => {
+ describe('project page', () => {
+ const resolver = jest.fn().mockResolvedValue(graphQLEmptyImageListMock);
+
+ it('cli commands is not visible', async () => {
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ expect(findCliCommands().exists()).toBe(false);
+ });
+
+ it('project empty state is visible', async () => {
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ expect(findProjectEmptyState().exists()).toBe(true);
+ });
+ });
+
+ describe('group page', () => {
+ const resolver = jest.fn().mockResolvedValue(graphQLEmptyGroupImageListMock);
+
+ const config = {
+ isGroupPage: true,
+ };
+
+ it('group empty state is visible', async () => {
+ mountComponent({ resolver, config });
+
+ await waitForApolloRequestRender();
+
+ expect(findGroupEmptyState().exists()).toBe(true);
+ });
+
+ it('cli commands is not visible', async () => {
+ mountComponent({ resolver, config });
+
+ await waitForApolloRequestRender();
+
+ expect(findCliCommands().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('list is not empty', () => {
+ describe('unfiltered state', () => {
+ it('quick start is visible', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findCliCommands().exists()).toBe(true);
+ });
+
+ it('list component is visible', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findImageList().exists()).toBe(true);
+ });
+
+ describe('additional metadata', () => {
+ it('is called on component load', async () => {
+ const detailsResolver = jest
+ .fn()
+ .mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
+ mountComponent({ detailsResolver });
+
+ jest.runOnlyPendingTimers();
+ await waitForPromises();
+
+ expect(detailsResolver).toHaveBeenCalled();
+ });
+
+ it('does not block the list ui to show', async () => {
+ const detailsResolver = jest.fn().mockRejectedValue();
+ mountComponent({ detailsResolver });
+
+ await waitForApolloRequestRender();
+
+ expect(findImageList().exists()).toBe(true);
+ });
+
+ it('loading state is passed to list component', async () => {
+ // this is a promise that never resolves, to trick apollo to think that this request is still loading
+ const detailsResolver = jest.fn().mockImplementation(() => new Promise(() => {}));
+
+ mountComponent({ detailsResolver });
+ await waitForApolloRequestRender();
+
+ expect(findImageList().props('metadataLoading')).toBe(true);
+ });
+ });
+
+ describe('delete image', () => {
+ const selectImageForDeletion = async () => {
+ await waitForApolloRequestRender();
+
+ findImageList().vm.$emit('delete', deletedContainerRepository);
+ };
+
+ it('should call deleteItem when confirming deletion', async () => {
+ const mutationResolver = jest.fn().mockResolvedValue(graphQLImageDeleteMock);
+ mountComponent({ mutationResolver });
+
+ await selectImageForDeletion();
+
+ findDeleteModal().vm.$emit('primary');
+ await waitForApolloRequestRender();
+
+ expect(wrapper.vm.itemToDelete).toEqual(deletedContainerRepository);
+
+ const updatedImage = findImageList()
+ .props('images')
+ .find((i) => i.id === deletedContainerRepository.id);
+
+ expect(updatedImage.status).toBe(deletedContainerRepository.status);
+ });
+
+ it('should show a success alert when delete request is successful', async () => {
+ mountComponent();
+
+ await selectImageForDeletion();
+
+ findDeleteImage().vm.$emit('success');
+ await nextTick();
+
+ const alert = findDeleteAlert();
+ expect(alert.exists()).toBe(true);
+ expect(alert.text().replace(/\s\s+/gm, ' ')).toBe(
+ DELETE_IMAGE_SUCCESS_MESSAGE.replace('%{title}', wrapper.vm.itemToDelete.path),
+ );
+ });
+
+ describe('when delete request fails it shows an alert', () => {
+ it('user recoverable error', async () => {
+ mountComponent();
+
+ await selectImageForDeletion();
+
+ findDeleteImage().vm.$emit('error');
+ await nextTick();
+
+ const alert = findDeleteAlert();
+ expect(alert.exists()).toBe(true);
+ expect(alert.text().replace(/\s\s+/gm, ' ')).toBe(
+ DELETE_IMAGE_ERROR_MESSAGE.replace('%{title}', wrapper.vm.itemToDelete.path),
+ );
+ });
+ });
+ });
+ });
+
+ describe('search and sorting', () => {
+ const doSearch = async () => {
+ await waitForApolloRequestRender();
+ findRegistrySearch().vm.$emit('filter:changed', [
+ { type: FILTERED_SEARCH_TERM, value: { data: 'centos6' } },
+ ]);
+
+ findRegistrySearch().vm.$emit('filter:submit');
+
+ await nextTick();
+ };
+
+ it('has a search box element', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ const registrySearch = findRegistrySearch();
+ expect(registrySearch.exists()).toBe(true);
+ expect(registrySearch.props()).toMatchObject({
+ filter: [],
+ sorting: { orderBy: 'UPDATED', sort: 'desc' },
+ sortableFields: SORT_FIELDS,
+ tokens: [],
+ });
+ });
+
+ it('performs sorting', async () => {
+ const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ findRegistrySearch().vm.$emit('sorting:changed', { sort: 'asc' });
+ await nextTick();
+
+ expect(resolver).toHaveBeenCalledWith(expect.objectContaining({ sort: 'UPDATED_DESC' }));
+ });
+
+ it('performs a search', async () => {
+ const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
+ mountComponent({ resolver });
+
+ await doSearch();
+
+ expect(resolver).toHaveBeenCalledWith(expect.objectContaining({ name: 'centos6' }));
+ });
+
+ it('when search result is empty displays an empty search message', async () => {
+ const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
+ const detailsResolver = jest
+ .fn()
+ .mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
+ mountComponent({ resolver, detailsResolver });
+
+ await waitForApolloRequestRender();
+
+ resolver.mockResolvedValue(graphQLEmptyImageListMock);
+ detailsResolver.mockResolvedValue(graphQLEmptyImageListMock);
+
+ await doSearch();
+
+ expect(findEmptySearchMessage().exists()).toBe(true);
+ });
+ });
+
+ describe('pagination', () => {
+ it('prev-page event triggers a fetchMore request', async () => {
+ const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
+ const detailsResolver = jest
+ .fn()
+ .mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
+ mountComponent({ resolver, detailsResolver });
+
+ await waitForApolloRequestRender();
+
+ findImageList().vm.$emit('prev-page');
+ await nextTick();
+
+ expect(resolver).toHaveBeenCalledWith(
+ expect.objectContaining({ before: pageInfo.startCursor }),
+ );
+ expect(detailsResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ before: pageInfo.startCursor }),
+ );
+ });
+
+ it('next-page event triggers a fetchMore request', async () => {
+ const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
+ const detailsResolver = jest
+ .fn()
+ .mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
+ mountComponent({ resolver, detailsResolver });
+
+ await waitForApolloRequestRender();
+
+ findImageList().vm.$emit('next-page');
+ await nextTick();
+
+ expect(resolver).toHaveBeenCalledWith(
+ expect.objectContaining({ after: pageInfo.endCursor }),
+ );
+ expect(detailsResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ after: pageInfo.endCursor }),
+ );
+ });
+ });
+ });
+
+ describe('modal', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('exists', () => {
+ expect(findDeleteModal().exists()).toBe(true);
+ });
+
+ it('contains a description with the path of the item to delete', async () => {
+ findImageList().vm.$emit('delete', { path: 'foo' });
+ await nextTick();
+ expect(findDeleteModal().html()).toContain('foo');
+ });
+ });
+
+ describe('tracking', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ const testTrackingCall = (action) => {
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, action, {
+ label: 'registry_repository_delete',
+ });
+ };
+
+ beforeEach(() => {
+ jest.spyOn(Tracking, 'event');
+ });
+
+ it('send an event when delete button is clicked', () => {
+ findImageList().vm.$emit('delete', {});
+
+ testTrackingCall('click_button');
+ });
+
+ it('send an event when cancel is pressed on modal', () => {
+ const deleteModal = findDeleteModal();
+ deleteModal.vm.$emit('cancel');
+ testTrackingCall('cancel_delete');
+ });
+
+ it('send an event when the deletion starts', () => {
+ findDeleteImage().vm.$emit('start');
+ testTrackingCall('confirm_delete');
+ });
+ });
+
+ describe('url query string handling', () => {
+ const defaultQueryParams = {
+ search: [1, 2],
+ sort: 'asc',
+ orderBy: 'CREATED',
+ };
+ const queryChangePayload = 'foo';
+
+ it('query:updated event pushes the new query to the router', async () => {
+ const push = jest.fn();
+ mountComponent({ mocks: { $router: { push } } });
+
+ await nextTick();
+
+ findRegistrySearch().vm.$emit('query:changed', queryChangePayload);
+
+ expect(push).toHaveBeenCalledWith({ query: queryChangePayload });
+ });
+
+ it('graphql API call has the variables set from the URL', async () => {
+ const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
+ mountComponent({ query: defaultQueryParams, resolver });
+
+ await nextTick();
+
+ expect(resolver).toHaveBeenCalledWith(
+ expect.objectContaining({
+ name: 1,
+ sort: 'CREATED_ASC',
+ }),
+ );
+ });
+
+ it.each`
+ sort | orderBy | search | payload
+ ${'ASC'} | ${undefined} | ${undefined} | ${{ sort: 'UPDATED_ASC' }}
+ ${undefined} | ${'bar'} | ${undefined} | ${{ sort: 'BAR_DESC' }}
+ ${'ASC'} | ${'bar'} | ${undefined} | ${{ sort: 'BAR_ASC' }}
+ ${undefined} | ${undefined} | ${undefined} | ${{}}
+ ${undefined} | ${undefined} | ${['one']} | ${{ name: 'one' }}
+ ${undefined} | ${undefined} | ${['one', 'two']} | ${{ name: 'one' }}
+ ${undefined} | ${'UPDATED'} | ${['one', 'two']} | ${{ name: 'one', sort: 'UPDATED_DESC' }}
+ ${'ASC'} | ${'UPDATED'} | ${['one', 'two']} | ${{ name: 'one', sort: 'UPDATED_ASC' }}
+ `(
+ 'with sort equal to $sort, orderBy equal to $orderBy, search set to $search API call has the variables set as $payload',
+ async ({ sort, orderBy, search, payload }) => {
+ const resolver = jest.fn().mockResolvedValue({ sort, orderBy });
+ mountComponent({ query: { sort, orderBy, search }, resolver });
+
+ await nextTick();
+
+ expect(resolver).toHaveBeenCalledWith(expect.objectContaining(payload));
+ },
+ );
+ });
+
+ describe('cleanup is on alert', () => {
+ it('exist when showCleanupPolicyOnAlert is true and has the correct props', async () => {
+ mountComponent({
+ config: {
+ showCleanupPolicyOnAlert: true,
+ projectPath: 'foo',
+ isGroupPage: false,
+ cleanupPoliciesSettingsPath: 'bar',
+ },
+ });
+
+ await waitForApolloRequestRender();
+
+ expect(findCleanupAlert().exists()).toBe(true);
+ expect(findCleanupAlert().props()).toMatchObject({
+ projectPath: 'foo',
+ cleanupPoliciesSettingsPath: 'bar',
+ });
+ });
+
+ it('is hidden when showCleanupPolicyOnAlert is false', async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+
+ expect(findCleanupAlert().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/stubs.js b/spec/frontend/packages_and_registries/container_registry/explorer/stubs.js
new file mode 100644
index 00000000000..7d281a53a59
--- /dev/null
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/stubs.js
@@ -0,0 +1,45 @@
+import {
+ GlModal as RealGlModal,
+ GlEmptyState as RealGlEmptyState,
+ GlSkeletonLoader as RealGlSkeletonLoader,
+ GlDropdown as RealGlDropdown,
+} from '@gitlab/ui';
+import { RouterLinkStub } from '@vue/test-utils';
+import { stubComponent } from 'helpers/stub_component';
+import RealDeleteModal from '~/packages_and_registries/container_registry/explorer/components/details_page/delete_modal.vue';
+import RealListItem from '~/vue_shared/components/registry/list_item.vue';
+
+export const GlModal = stubComponent(RealGlModal, {
+ template: '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-ok"></slot></div>',
+ methods: {
+ show: jest.fn(),
+ },
+});
+
+export const GlEmptyState = stubComponent(RealGlEmptyState, {
+ template: '<div><slot name="description"></slot></div>',
+});
+
+export const RouterLink = RouterLinkStub;
+
+export const DeleteModal = stubComponent(RealDeleteModal, {
+ methods: {
+ show: jest.fn(),
+ },
+});
+
+export const GlSkeletonLoader = stubComponent(RealGlSkeletonLoader);
+
+export const ListItem = {
+ ...RealListItem,
+ data() {
+ return {
+ detailsSlots: [],
+ isDetailsShown: true,
+ };
+ },
+};
+
+export const GlDropdown = stubComponent(RealGlDropdown, {
+ template: '<div><slot></slot></div>',
+});
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
index 1f0252965b0..625f00a8666 100644
--- a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
+++ b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
@@ -1,32 +1,40 @@
-import { GlFormInputGroup, GlFormGroup, GlSkeletonLoader, GlSprintf } from '@gitlab/ui';
+import {
+ GlFormInputGroup,
+ GlFormGroup,
+ GlSkeletonLoader,
+ GlSprintf,
+ GlEmptyState,
+} from '@gitlab/ui';
import { createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { stripTypenames } from 'helpers/graphql_helpers';
import waitForPromises from 'helpers/wait_for_promises';
+import { GRAPHQL_PAGE_SIZE } from '~/packages_and_registries/dependency_proxy/constants';
import DependencyProxyApp from '~/packages_and_registries/dependency_proxy/app.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import ManifestsList from '~/packages_and_registries/dependency_proxy/components/manifests_list.vue';
import getDependencyProxyDetailsQuery from '~/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql';
-import { proxyDetailsQuery, proxyData } from './mock_data';
+import { proxyDetailsQuery, proxyData, pagination, proxyManifests } from './mock_data';
const localVue = createLocalVue();
describe('DependencyProxyApp', () => {
let wrapper;
let apolloProvider;
+ let resolver;
const provideDefaults = {
groupPath: 'gitlab-org',
dependencyProxyAvailable: true,
+ noManifestsIllustration: 'noManifestsIllustration',
};
- function createComponent({
- provide = provideDefaults,
- resolver = jest.fn().mockResolvedValue(proxyDetailsQuery()),
- } = {}) {
+ function createComponent({ provide = provideDefaults } = {}) {
localVue.use(VueApollo);
const requestHandlers = [[getDependencyProxyDetailsQuery, resolver]];
@@ -53,6 +61,12 @@ describe('DependencyProxyApp', () => {
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
const findMainArea = () => wrapper.findByTestId('main-area');
const findProxyCountText = () => wrapper.findByTestId('proxy-count');
+ const findManifestList = () => wrapper.findComponent(ManifestsList);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+
+ beforeEach(() => {
+ resolver = jest.fn().mockResolvedValue(proxyDetailsQuery());
+ });
afterEach(() => {
wrapper.destroy();
@@ -78,8 +92,8 @@ describe('DependencyProxyApp', () => {
});
it('does not call the graphql endpoint', async () => {
- const resolver = jest.fn().mockResolvedValue(proxyDetailsQuery());
- createComponent({ ...createComponentArguments, resolver });
+ resolver = jest.fn().mockResolvedValue(proxyDetailsQuery());
+ createComponent({ ...createComponentArguments });
await waitForPromises();
@@ -145,14 +159,73 @@ describe('DependencyProxyApp', () => {
it('from group has a description with proxy count', () => {
expect(findProxyCountText().text()).toBe('Contains 2 blobs of images (1024 Bytes)');
});
+
+ describe('manifest lists', () => {
+ describe('when there are no manifests', () => {
+ beforeEach(() => {
+ resolver = jest.fn().mockResolvedValue(
+ proxyDetailsQuery({
+ extend: { dependencyProxyManifests: { nodes: [], pageInfo: pagination() } },
+ }),
+ );
+ createComponent();
+ return waitForPromises();
+ });
+
+ it('shows the empty state message', () => {
+ expect(findEmptyState().props()).toMatchObject({
+ svgPath: provideDefaults.noManifestsIllustration,
+ title: DependencyProxyApp.i18n.noManifestTitle,
+ });
+ });
+
+ it('hides the list', () => {
+ expect(findManifestList().exists()).toBe(false);
+ });
+ });
+
+ describe('when there are manifests', () => {
+ it('hides the empty state message', () => {
+ expect(findEmptyState().exists()).toBe(false);
+ });
+
+ it('shows list', () => {
+ expect(findManifestList().props()).toMatchObject({
+ manifests: proxyManifests(),
+ pagination: stripTypenames(pagination()),
+ });
+ });
+
+ it('prev-page event on list fetches the previous page', () => {
+ findManifestList().vm.$emit('prev-page');
+
+ expect(resolver).toHaveBeenCalledWith({
+ before: pagination().startCursor,
+ first: null,
+ fullPath: provideDefaults.groupPath,
+ last: GRAPHQL_PAGE_SIZE,
+ });
+ });
+
+ it('next-page event on list fetches the next page', () => {
+ findManifestList().vm.$emit('next-page');
+
+ expect(resolver).toHaveBeenCalledWith({
+ after: pagination().endCursor,
+ first: GRAPHQL_PAGE_SIZE,
+ fullPath: provideDefaults.groupPath,
+ });
+ });
+ });
+ });
});
+
describe('when the dependency proxy is disabled', () => {
beforeEach(() => {
- createComponent({
- resolver: jest
- .fn()
- .mockResolvedValue(proxyDetailsQuery({ extendSettings: { enabled: false } })),
- });
+ resolver = jest
+ .fn()
+ .mockResolvedValue(proxyDetailsQuery({ extendSettings: { enabled: false } }));
+ createComponent();
return waitForPromises();
});
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js
new file mode 100644
index 00000000000..9e4c747a1bd
--- /dev/null
+++ b/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js
@@ -0,0 +1,84 @@
+import { GlKeysetPagination } from '@gitlab/ui';
+import { stripTypenames } from 'helpers/graphql_helpers';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ManifestRow from '~/packages_and_registries/dependency_proxy/components/manifest_row.vue';
+
+import Component from '~/packages_and_registries/dependency_proxy/components/manifests_list.vue';
+import {
+ proxyManifests,
+ pagination,
+} from 'jest/packages_and_registries/dependency_proxy/mock_data';
+
+describe('Manifests List', () => {
+ let wrapper;
+
+ const defaultProps = {
+ manifests: proxyManifests(),
+ pagination: stripTypenames(pagination()),
+ };
+
+ const createComponent = (propsData = defaultProps) => {
+ wrapper = shallowMountExtended(Component, {
+ propsData,
+ });
+ };
+
+ const findRows = () => wrapper.findAllComponents(ManifestRow);
+ const findPagination = () => wrapper.findComponent(GlKeysetPagination);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('has the correct title', () => {
+ createComponent();
+
+ expect(wrapper.text()).toContain(Component.i18n.listTitle);
+ });
+
+ it('shows a row for every manifest', () => {
+ createComponent();
+
+ expect(findRows().length).toBe(defaultProps.manifests.length);
+ });
+
+ it('binds a manifest to each row', () => {
+ createComponent();
+
+ expect(findRows().at(0).props()).toMatchObject({
+ manifest: defaultProps.manifests[0],
+ });
+ });
+
+ describe('pagination', () => {
+ it('is hidden when there is no next or prev pages', () => {
+ createComponent({ ...defaultProps, pagination: {} });
+
+ expect(findPagination().exists()).toBe(false);
+ });
+
+ it('has the correct props', () => {
+ createComponent();
+
+ expect(findPagination().props()).toMatchObject({
+ ...defaultProps.pagination,
+ });
+ });
+
+ it('emits the next-page event', () => {
+ createComponent();
+
+ findPagination().vm.$emit('next');
+
+ expect(wrapper.emitted('next-page')).toEqual([[]]);
+ });
+
+ it('emits the prev-page event', () => {
+ createComponent();
+
+ findPagination().vm.$emit('prev');
+
+ expect(wrapper.emitted('prev-page')).toEqual([[]]);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_row_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_row_spec.js
new file mode 100644
index 00000000000..b7cbd875497
--- /dev/null
+++ b/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_row_spec.js
@@ -0,0 +1,59 @@
+import { GlSprintf } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
+import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import Component from '~/packages_and_registries/dependency_proxy/components/manifest_row.vue';
+import { proxyManifests } from 'jest/packages_and_registries/dependency_proxy/mock_data';
+
+describe('Manifest Row', () => {
+ let wrapper;
+
+ const defaultProps = {
+ manifest: proxyManifests()[0],
+ };
+
+ const createComponent = (propsData = defaultProps) => {
+ wrapper = shallowMountExtended(Component, {
+ propsData,
+ stubs: {
+ GlSprintf,
+ TimeagoTooltip,
+ ListItem,
+ },
+ });
+ };
+
+ const findListItem = () => wrapper.findComponent(ListItem);
+ const findCachedMessages = () => wrapper.findByTestId('cached-message');
+ const findTimeAgoTooltip = () => wrapper.findComponent(TimeagoTooltip);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('has a list item', () => {
+ expect(findListItem().exists()).toBe(true);
+ });
+
+ it('displays the name', () => {
+ expect(wrapper.text()).toContain('alpine');
+ });
+
+ it('displays the version', () => {
+ expect(wrapper.text()).toContain('latest');
+ });
+
+ it('displays the cached time', () => {
+ expect(findCachedMessages().text()).toContain('Cached');
+ });
+
+ it('has a time ago tooltip component', () => {
+ expect(findTimeAgoTooltip().props()).toMatchObject({
+ time: defaultProps.manifest.createdAt,
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/mock_data.js b/spec/frontend/packages_and_registries/dependency_proxy/mock_data.js
index 23d42e109f9..8bad22b5287 100644
--- a/spec/frontend/packages_and_registries/dependency_proxy/mock_data.js
+++ b/spec/frontend/packages_and_registries/dependency_proxy/mock_data.js
@@ -7,7 +7,21 @@ export const proxyData = () => ({
export const proxySettings = (extend = {}) => ({ enabled: true, ...extend });
-export const proxyDetailsQuery = ({ extendSettings = {} } = {}) => ({
+export const proxyManifests = () => [
+ { createdAt: '2021-09-22T09:45:28Z', imageName: 'alpine:latest' },
+ { createdAt: '2021-09-21T09:45:28Z', imageName: 'alpine:stable' },
+];
+
+export const pagination = (extend) => ({
+ endCursor: 'eyJpZCI6IjIwNSIsIm5hbWUiOiJteS9jb21wYW55L2FwcC9teS1hcHAifQ',
+ hasNextPage: true,
+ hasPreviousPage: true,
+ startCursor: 'eyJpZCI6IjI0NyIsIm5hbWUiOiJ2ZXJzaW9uX3Rlc3QxIn0',
+ __typename: 'PageInfo',
+ ...extend,
+});
+
+export const proxyDetailsQuery = ({ extendSettings = {}, extend } = {}) => ({
data: {
group: {
...proxyData(),
@@ -16,6 +30,11 @@ export const proxyDetailsQuery = ({ extendSettings = {} } = {}) => ({
...proxySettings(extendSettings),
__typename: 'DependencyProxySetting',
},
+ dependencyProxyManifests: {
+ nodes: proxyManifests(),
+ pageInfo: pagination(),
+ },
+ ...extend,
},
},
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap
index 451cf743e35..519014bb9cf 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap
@@ -19,15 +19,15 @@ exports[`PackageTitle renders with tags 1`] = `
<div
class="gl-display-flex gl-flex-direction-column"
>
- <h1
- class="gl-font-size-h1 gl-mt-3 gl-mb-2"
+ <h2
+ class="gl-font-size-h1 gl-mt-3 gl-mb-0"
data-testid="title"
>
@gitlab-org/package-15
- </h1>
+ </h2>
<div
- class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-1"
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-3"
>
<gl-icon-stub
class="gl-mr-3"
@@ -117,15 +117,15 @@ exports[`PackageTitle renders without tags 1`] = `
<div
class="gl-display-flex gl-flex-direction-column"
>
- <h1
- class="gl-font-size-h1 gl-mt-3 gl-mb-2"
+ <h2
+ class="gl-font-size-h1 gl-mt-3 gl-mb-0"
data-testid="title"
>
@gitlab-org/package-15
- </h1>
+ </h2>
<div
- class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-1"
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-3"
>
<gl-icon-stub
class="gl-mr-3"
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap
index 8f69f943112..c95538546c1 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap
@@ -27,6 +27,7 @@ exports[`VersionRow renders 1`] = `
>
<span
class="gl-truncate"
+ data-testid="truncate-end-container"
title="@gitlab-org/package-15"
>
<span
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/app_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/app_spec.js
index 5119512564f..0bea84693f6 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/app_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/app_spec.js
@@ -16,16 +16,15 @@ import PackageFiles from '~/packages_and_registries/package_registry/components/
import PackageHistory from '~/packages_and_registries/package_registry/components/details/package_history.vue';
import PackageTitle from '~/packages_and_registries/package_registry/components/details/package_title.vue';
import VersionRow from '~/packages_and_registries/package_registry/components/details/version_row.vue';
+import DeletePackage from '~/packages_and_registries/package_registry/components/functional/delete_package.vue';
import {
FETCH_PACKAGE_DETAILS_ERROR_MESSAGE,
- DELETE_PACKAGE_ERROR_MESSAGE,
PACKAGE_TYPE_COMPOSER,
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
DELETE_PACKAGE_FILE_ERROR_MESSAGE,
PACKAGE_TYPE_NUGET,
} from '~/packages_and_registries/package_registry/constants';
-import destroyPackageMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package.mutation.graphql';
import destroyPackageFileMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_file.mutation.graphql';
import getPackageDetails from '~/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql';
import {
@@ -34,8 +33,6 @@ import {
packageVersions,
dependencyLinks,
emptyPackageDetailsQuery,
- packageDestroyMutation,
- packageDestroyMutationError,
packageFiles,
packageDestroyFileMutation,
packageDestroyFileMutationError,
@@ -64,14 +61,12 @@ describe('PackagesApp', () => {
function createComponent({
resolver = jest.fn().mockResolvedValue(packageDetailsQuery()),
- mutationResolver = jest.fn().mockResolvedValue(packageDestroyMutation()),
fileDeleteMutationResolver = jest.fn().mockResolvedValue(packageDestroyFileMutation()),
} = {}) {
localVue.use(VueApollo);
const requestHandlers = [
[getPackageDetails, resolver],
- [destroyPackageMutation, mutationResolver],
[destroyPackageFileMutation, fileDeleteMutationResolver],
];
apolloProvider = createMockApollo(requestHandlers);
@@ -82,6 +77,7 @@ describe('PackagesApp', () => {
provide,
stubs: {
PackageTitle,
+ DeletePackage,
GlModal: {
template: '<div></div>',
methods: {
@@ -108,6 +104,7 @@ describe('PackagesApp', () => {
const findDependenciesCountBadge = () => wrapper.findComponent(GlBadge);
const findNoDependenciesMessage = () => wrapper.findByTestId('no-dependencies-message');
const findDependencyRows = () => wrapper.findAllComponents(DependencyRow);
+ const findDeletePackage = () => wrapper.findComponent(DeletePackage);
afterEach(() => {
wrapper.destroy();
@@ -187,14 +184,6 @@ describe('PackagesApp', () => {
});
};
- const performDeletePackage = async () => {
- await findDeleteButton().trigger('click');
-
- findDeleteModal().vm.$emit('primary');
-
- await waitForPromises();
- };
-
afterEach(() => {
Object.defineProperty(document, 'referrer', {
value: originalReferrer,
@@ -220,7 +209,7 @@ describe('PackagesApp', () => {
await waitForPromises();
- await performDeletePackage();
+ findDeletePackage().vm.$emit('end');
expect(window.location.replace).toHaveBeenCalledWith(
'projectListUrl?showSuccessDeleteAlert=true',
@@ -234,45 +223,13 @@ describe('PackagesApp', () => {
await waitForPromises();
- await performDeletePackage();
+ findDeletePackage().vm.$emit('end');
expect(window.location.replace).toHaveBeenCalledWith(
'groupListUrl?showSuccessDeleteAlert=true',
);
});
});
-
- describe('request failure', () => {
- it('on global failure it displays an alert', async () => {
- createComponent({ mutationResolver: jest.fn().mockRejectedValue() });
-
- await waitForPromises();
-
- await performDeletePackage();
-
- expect(createFlash).toHaveBeenCalledWith(
- expect.objectContaining({
- message: DELETE_PACKAGE_ERROR_MESSAGE,
- }),
- );
- });
-
- it('on payload with error it displays an alert', async () => {
- createComponent({
- mutationResolver: jest.fn().mockResolvedValue(packageDestroyMutationError()),
- });
-
- await waitForPromises();
-
- await performDeletePackage();
-
- expect(createFlash).toHaveBeenCalledWith(
- expect.objectContaining({
- message: DELETE_PACKAGE_ERROR_MESSAGE,
- }),
- );
- });
- });
});
describe('package files', () => {
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/installations_commands_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/installations_commands_spec.js
index b24946c8638..8bb05b00e65 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/installations_commands_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/installations_commands_spec.js
@@ -33,12 +33,12 @@ describe('InstallationCommands', () => {
});
}
- const npmInstallation = () => wrapper.find(NpmInstallation);
- const mavenInstallation = () => wrapper.find(MavenInstallation);
- const conanInstallation = () => wrapper.find(ConanInstallation);
- const nugetInstallation = () => wrapper.find(NugetInstallation);
- const pypiInstallation = () => wrapper.find(PypiInstallation);
- const composerInstallation = () => wrapper.find(ComposerInstallation);
+ const npmInstallation = () => wrapper.findComponent(NpmInstallation);
+ const mavenInstallation = () => wrapper.findComponent(MavenInstallation);
+ const conanInstallation = () => wrapper.findComponent(ConanInstallation);
+ const nugetInstallation = () => wrapper.findComponent(NugetInstallation);
+ const pypiInstallation = () => wrapper.findComponent(PypiInstallation);
+ const composerInstallation = () => wrapper.findComponent(ComposerInstallation);
afterEach(() => {
wrapper.destroy();
@@ -57,7 +57,7 @@ describe('InstallationCommands', () => {
it(`${packageEntity.packageType} instructions exist`, () => {
createComponent({ packageEntity });
- expect(selector()).toExist();
+ expect(selector().exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js b/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js
new file mode 100644
index 00000000000..5de30829fa5
--- /dev/null
+++ b/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js
@@ -0,0 +1,160 @@
+import { createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import waitForPromises from 'helpers/wait_for_promises';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import createFlash from '~/flash';
+import DeletePackage from '~/packages_and_registries/package_registry/components/functional/delete_package.vue';
+
+import destroyPackageMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package.mutation.graphql';
+import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';
+import {
+ packageDestroyMutation,
+ packageDestroyMutationError,
+ packagesListQuery,
+} from '../../mock_data';
+
+jest.mock('~/flash');
+
+const localVue = createLocalVue();
+
+describe('DeletePackage', () => {
+ let wrapper;
+ let apolloProvider;
+ let resolver;
+ let mutationResolver;
+
+ const eventPayload = { id: '1' };
+
+ function createComponent(propsData = {}) {
+ localVue.use(VueApollo);
+
+ const requestHandlers = [
+ [getPackagesQuery, resolver],
+ [destroyPackageMutation, mutationResolver],
+ ];
+ apolloProvider = createMockApollo(requestHandlers);
+
+ wrapper = shallowMountExtended(DeletePackage, {
+ propsData,
+ localVue,
+ apolloProvider,
+ scopedSlots: {
+ default(props) {
+ return this.$createElement('button', {
+ attrs: {
+ 'data-testid': 'trigger-button',
+ },
+ on: {
+ click: props.deletePackage,
+ },
+ });
+ },
+ },
+ });
+ }
+
+ const findButton = () => wrapper.findByTestId('trigger-button');
+
+ const clickOnButtonAndWait = (payload) => {
+ findButton().trigger('click', payload);
+ return waitForPromises();
+ };
+
+ beforeEach(() => {
+ resolver = jest.fn().mockResolvedValue(packagesListQuery());
+ mutationResolver = jest.fn().mockResolvedValue(packageDestroyMutation());
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('binds deletePackage method to the default slot', () => {
+ createComponent();
+
+ findButton().trigger('click');
+
+ expect(wrapper.emitted('start')).toEqual([[]]);
+ });
+
+ it('calls apollo mutation', async () => {
+ createComponent();
+
+ await clickOnButtonAndWait(eventPayload);
+
+ expect(mutationResolver).toHaveBeenCalledWith(eventPayload);
+ });
+
+ it('passes refetchQueries to apollo mutate', async () => {
+ const variables = { isGroupPage: true };
+ createComponent({
+ refetchQueries: [{ query: getPackagesQuery, variables }],
+ });
+
+ await clickOnButtonAndWait(eventPayload);
+
+ expect(mutationResolver).toHaveBeenCalledWith(eventPayload);
+ expect(resolver).toHaveBeenCalledWith(variables);
+ });
+
+ describe('on mutation success', () => {
+ it('emits end event', async () => {
+ createComponent();
+
+ await clickOnButtonAndWait(eventPayload);
+
+ expect(wrapper.emitted('end')).toEqual([[]]);
+ });
+
+ it('does not call createFlash', async () => {
+ createComponent();
+
+ await clickOnButtonAndWait(eventPayload);
+
+ expect(createFlash).not.toHaveBeenCalled();
+ });
+
+ it('calls createFlash with the success message when showSuccessAlert is true', async () => {
+ createComponent({ showSuccessAlert: true });
+
+ await clickOnButtonAndWait(eventPayload);
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: DeletePackage.i18n.successMessage,
+ type: 'success',
+ });
+ });
+ });
+
+ describe.each`
+ errorType | mutationResolverResponse
+ ${'connectionError'} | ${jest.fn().mockRejectedValue()}
+ ${'localError'} | ${jest.fn().mockResolvedValue(packageDestroyMutationError())}
+ `('on mutation $errorType', ({ mutationResolverResponse }) => {
+ beforeEach(() => {
+ mutationResolver = mutationResolverResponse;
+ });
+
+ it('emits end event', async () => {
+ createComponent();
+
+ await clickOnButtonAndWait(eventPayload);
+
+ expect(wrapper.emitted('end')).toEqual([[]]);
+ });
+
+ it('calls createFlash with the error message', async () => {
+ createComponent({ showSuccessAlert: true });
+
+ await clickOnButtonAndWait(eventPayload);
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: DeletePackage.i18n.errorMessage,
+ type: 'warning',
+ captureError: true,
+ error: expect.any(Error),
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/app_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/app_spec.js.snap
index 1b556be5873..5af75868084 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/app_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/app_spec.js.snap
@@ -8,5 +8,62 @@ exports[`PackagesListApp renders 1`] = `
/>
<package-search-stub />
+
+ <div>
+ <section
+ class="row empty-state text-center"
+ >
+ <div
+ class="col-12"
+ >
+ <div
+ class="svg-250 svg-content"
+ >
+ <img
+ alt=""
+ class="gl-max-w-full"
+ role="img"
+ src="emptyListIllustration"
+ />
+ </div>
+ </div>
+
+ <div
+ class="col-12"
+ >
+ <div
+ class="text-content gl-mx-auto gl-my-0 gl-p-5"
+ >
+ <h1
+ class="h4"
+ >
+ There are no packages yet
+ </h1>
+
+ <p>
+ Learn how to
+ <b-link-stub
+ class="gl-link"
+ event="click"
+ href="emptyListHelpUrl"
+ routertag="a"
+ target="_blank"
+ >
+ publish and share your packages
+ </b-link-stub>
+ with GitLab.
+ </p>
+
+ <div
+ class="gl-display-flex gl-flex-wrap gl-justify-content-center"
+ >
+ <!---->
+
+ <!---->
+ </div>
+ </div>
+ </div>
+ </section>
+ </div>
</div>
`;
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/app_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/app_spec.js
index 3958cdf21bb..ad848f367e0 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/app_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/app_spec.js
@@ -2,22 +2,25 @@ import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
import { createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
+import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import PackageListApp from '~/packages_and_registries/package_registry/components/list/app.vue';
import PackageTitle from '~/packages_and_registries/package_registry/components/list/package_title.vue';
import PackageSearch from '~/packages_and_registries/package_registry/components/list/package_search.vue';
+import OriginalPackageList from '~/packages_and_registries/package_registry/components/list/packages_list.vue';
+import DeletePackage from '~/packages_and_registries/package_registry/components/functional/delete_package.vue';
import {
PROJECT_RESOURCE_TYPE,
GROUP_RESOURCE_TYPE,
- LIST_QUERY_DEBOUNCE_TIME,
+ GRAPHQL_PAGE_SIZE,
} from '~/packages_and_registries/package_registry/constants';
import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';
-import { packagesListQuery } from '../../mock_data';
+import { packagesListQuery, packageData, pagination } from '../../mock_data';
jest.mock('~/lib/utils/common_utils');
jest.mock('~/flash');
@@ -39,11 +42,20 @@ describe('PackagesListApp', () => {
const PackageList = {
name: 'package-list',
template: '<div><slot name="empty-state"></slot></div>',
+ props: OriginalPackageList.props,
};
const GlLoadingIcon = { name: 'gl-loading-icon', template: '<div>loading</div>' };
+ const searchPayload = {
+ sort: 'VERSION_DESC',
+ filters: { packageName: 'foo', packageType: 'CONAN' },
+ };
+
const findPackageTitle = () => wrapper.findComponent(PackageTitle);
const findSearch = () => wrapper.findComponent(PackageSearch);
+ const findListComponent = () => wrapper.findComponent(PackageList);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findDeletePackage = () => wrapper.findComponent(DeletePackage);
const mountComponent = ({
resolver = jest.fn().mockResolvedValue(packagesListQuery()),
@@ -61,9 +73,10 @@ describe('PackagesListApp', () => {
stubs: {
GlEmptyState,
GlLoadingIcon,
- PackageList,
GlSprintf,
GlLink,
+ PackageList,
+ DeletePackage,
},
});
};
@@ -72,15 +85,24 @@ describe('PackagesListApp', () => {
wrapper.destroy();
});
- const waitForDebouncedApollo = () => {
- jest.advanceTimersByTime(LIST_QUERY_DEBOUNCE_TIME);
+ const waitForFirstRequest = () => {
+ // emit a search update so the query is executed
+ findSearch().vm.$emit('update', { sort: 'NAME_DESC', filters: [] });
return waitForPromises();
};
+ it('does not execute the query without sort being set', () => {
+ const resolver = jest.fn().mockResolvedValue(packagesListQuery());
+
+ mountComponent({ resolver });
+
+ expect(resolver).not.toHaveBeenCalled();
+ });
+
it('renders', async () => {
mountComponent();
- await waitForDebouncedApollo();
+ await waitForFirstRequest();
expect(wrapper.element).toMatchSnapshot();
});
@@ -88,7 +110,7 @@ describe('PackagesListApp', () => {
it('has a package title', async () => {
mountComponent();
- await waitForDebouncedApollo();
+ await waitForFirstRequest();
expect(findPackageTitle().exists()).toBe(true);
expect(findPackageTitle().props('count')).toBe(2);
@@ -105,25 +127,54 @@ describe('PackagesListApp', () => {
const resolver = jest.fn().mockResolvedValue(packagesListQuery());
mountComponent({ resolver });
- const payload = {
- sort: 'VERSION_DESC',
- filters: { packageName: 'foo', packageType: 'CONAN' },
- };
-
- findSearch().vm.$emit('update', payload);
+ findSearch().vm.$emit('update', searchPayload);
- await waitForDebouncedApollo();
- jest.advanceTimersByTime(LIST_QUERY_DEBOUNCE_TIME);
+ await waitForPromises();
expect(resolver).toHaveBeenCalledWith(
expect.objectContaining({
- groupSort: payload.sort,
- ...payload.filters,
+ groupSort: searchPayload.sort,
+ ...searchPayload.filters,
}),
);
});
});
+ describe('list component', () => {
+ let resolver;
+
+ beforeEach(() => {
+ resolver = jest.fn().mockResolvedValue(packagesListQuery());
+ mountComponent({ resolver });
+
+ return waitForFirstRequest();
+ });
+
+ it('exists and has the right props', () => {
+ expect(findListComponent().props()).toMatchObject({
+ list: expect.arrayContaining([expect.objectContaining({ id: packageData().id })]),
+ isLoading: false,
+ pageInfo: expect.objectContaining({ endCursor: pagination().endCursor }),
+ });
+ });
+
+ it('when list emits next-page fetches the next set of records', () => {
+ findListComponent().vm.$emit('next-page');
+
+ expect(resolver).toHaveBeenCalledWith(
+ expect.objectContaining({ after: pagination().endCursor, first: GRAPHQL_PAGE_SIZE }),
+ );
+ });
+
+ it('when list emits prev-page fetches the prev set of records', () => {
+ findListComponent().vm.$emit('prev-page');
+
+ expect(resolver).toHaveBeenCalledWith(
+ expect.objectContaining({ before: pagination().startCursor, last: GRAPHQL_PAGE_SIZE }),
+ );
+ });
+ });
+
describe.each`
type | sortType
${PROJECT_RESOURCE_TYPE} | ${'sort'}
@@ -136,9 +187,9 @@ describe('PackagesListApp', () => {
beforeEach(() => {
provide = { ...defaultProvide, isGroupPage };
- resolver = jest.fn().mockResolvedValue(packagesListQuery(type));
+ resolver = jest.fn().mockResolvedValue(packagesListQuery({ type }));
mountComponent({ provide, resolver });
- return waitForDebouncedApollo();
+ return waitForFirstRequest();
});
it('succeeds', () => {
@@ -147,8 +198,85 @@ describe('PackagesListApp', () => {
it('calls the resolver with the right parameters', () => {
expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({ isGroupPage, [sortType]: '' }),
+ expect.objectContaining({ isGroupPage, [sortType]: 'NAME_DESC' }),
);
});
});
+
+ describe('empty state', () => {
+ beforeEach(() => {
+ const resolver = jest.fn().mockResolvedValue(packagesListQuery({ extend: { nodes: [] } }));
+ mountComponent({ resolver });
+
+ return waitForFirstRequest();
+ });
+ it('generate the correct empty list link', () => {
+ const link = findListComponent().findComponent(GlLink);
+
+ expect(link.attributes('href')).toBe(defaultProvide.emptyListHelpUrl);
+ expect(link.text()).toBe('publish and share your packages');
+ });
+
+ it('includes the right content on the default tab', () => {
+ expect(findEmptyState().text()).toContain(PackageListApp.i18n.emptyPageTitle);
+ });
+ });
+
+ describe('filter without results', () => {
+ beforeEach(async () => {
+ mountComponent();
+
+ await waitForFirstRequest();
+
+ findSearch().vm.$emit('update', searchPayload);
+
+ return nextTick();
+ });
+
+ it('should show specific empty message', () => {
+ expect(findEmptyState().text()).toContain(PackageListApp.i18n.noResultsTitle);
+ expect(findEmptyState().text()).toContain(PackageListApp.i18n.widenFilters);
+ });
+ });
+
+ describe('delete package', () => {
+ it('exists and has the correct props', async () => {
+ mountComponent();
+
+ await waitForFirstRequest();
+
+ expect(findDeletePackage().props()).toMatchObject({
+ refetchQueries: [{ query: getPackagesQuery, variables: {} }],
+ showSuccessAlert: true,
+ });
+ });
+
+ it('deletePackage is bound to package-list package:delete event', async () => {
+ mountComponent();
+
+ await waitForFirstRequest();
+
+ findListComponent().vm.$emit('package:delete', { id: 1 });
+
+ expect(findDeletePackage().emitted('start')).toEqual([[]]);
+ });
+
+ it('start and end event set loading correctly', async () => {
+ mountComponent();
+
+ await waitForFirstRequest();
+
+ findDeletePackage().vm.$emit('start');
+
+ await nextTick();
+
+ expect(findListComponent().props('isLoading')).toBe(true);
+
+ findDeletePackage().vm.$emit('end');
+
+ await nextTick();
+
+ expect(findListComponent().props('isLoading')).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js
index b624e66482d..de4e9c8ae5b 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js
@@ -1,93 +1,86 @@
-import { GlTable, GlPagination, GlModal } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
-import { last } from 'lodash';
-import Vuex from 'vuex';
-import stubChildren from 'helpers/stub_children';
-import { packageList } from 'jest/packages/mock_data';
+import { GlKeysetPagination, GlModal, GlSprintf } from '@gitlab/ui';
+import { nextTick } from 'vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import PackagesListRow from '~/packages/shared/components/package_list_row.vue';
import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
-import { TrackingActions } from '~/packages/shared/constants';
-import * as SharedUtils from '~/packages/shared/utils';
+import {
+ DELETE_PACKAGE_TRACKING_ACTION,
+ REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
+ CANCEL_DELETE_PACKAGE_TRACKING_ACTION,
+} from '~/packages_and_registries/package_registry/constants';
import PackagesList from '~/packages_and_registries/package_registry/components/list/packages_list.vue';
import Tracking from '~/tracking';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
+import { packageData } from '../../mock_data';
describe('packages_list', () => {
let wrapper;
- let store;
+
+ const firstPackage = packageData();
+ const secondPackage = {
+ ...packageData(),
+ id: 'gid://gitlab/Packages::Package/112',
+ name: 'second-package',
+ };
+
+ const defaultProps = {
+ list: [firstPackage, secondPackage],
+ isLoading: false,
+ pageInfo: {},
+ };
const EmptySlotStub = { name: 'empty-slot-stub', template: '<div>bar</div>' };
+ const GlModalStub = {
+ name: GlModal.name,
+ template: '<div><slot></slot></div>',
+ methods: { show: jest.fn() },
+ };
- const findPackagesListLoader = () => wrapper.find(PackagesListLoader);
- const findPackageListPagination = () => wrapper.find(GlPagination);
- const findPackageListDeleteModal = () => wrapper.find(GlModal);
- const findEmptySlot = () => wrapper.find(EmptySlotStub);
- const findPackagesListRow = () => wrapper.find(PackagesListRow);
-
- const createStore = (isGroupPage, packages, isLoading) => {
- const state = {
- isLoading,
- packages,
- pagination: {
- perPage: 1,
- total: 1,
- page: 1,
- },
- config: {
- isGroupPage,
+ const findPackagesListLoader = () => wrapper.findComponent(PackagesListLoader);
+ const findPackageListPagination = () => wrapper.findComponent(GlKeysetPagination);
+ const findPackageListDeleteModal = () => wrapper.findComponent(GlModalStub);
+ const findEmptySlot = () => wrapper.findComponent(EmptySlotStub);
+ const findPackagesListRow = () => wrapper.findComponent(PackagesListRow);
+
+ const mountComponent = (props) => {
+ wrapper = shallowMountExtended(PackagesList, {
+ propsData: {
+ ...defaultProps,
+ ...props,
},
- sorting: {
- orderBy: 'version',
- sort: 'desc',
+ stubs: {
+ GlModal: GlModalStub,
+ GlSprintf,
},
- };
- store = new Vuex.Store({
- state,
- getters: {
- getList: () => packages,
+ slots: {
+ 'empty-state': EmptySlotStub,
},
});
- store.dispatch = jest.fn();
};
- const mountComponent = ({
- isGroupPage = false,
- packages = packageList,
- isLoading = false,
- ...options
- } = {}) => {
- createStore(isGroupPage, packages, isLoading);
-
- wrapper = mount(PackagesList, {
- localVue,
- store,
- stubs: {
- ...stubChildren(PackagesList),
- GlTable,
- GlModal,
- },
- ...options,
- });
- };
+ beforeEach(() => {
+ GlModalStub.methods.show.mockReset();
+ });
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('when is loading', () => {
beforeEach(() => {
- mountComponent({
- packages: [],
- isLoading: true,
- });
+ mountComponent({ isLoading: true });
});
- it('shows skeleton loader when loading', () => {
+ it('shows skeleton loader', () => {
expect(findPackagesListLoader().exists()).toBe(true);
});
+
+ it('does not show the rows', () => {
+ expect(findPackagesListRow().exists()).toBe(false);
+ });
+
+ it('does not show the pagination', () => {
+ expect(findPackageListPagination().exists()).toBe(false);
+ });
});
describe('when is not loading', () => {
@@ -95,74 +88,61 @@ describe('packages_list', () => {
mountComponent();
});
- it('does not show skeleton loader when not loading', () => {
+ it('does not show skeleton loader', () => {
expect(findPackagesListLoader().exists()).toBe(false);
});
- });
- describe('layout', () => {
- beforeEach(() => {
- mountComponent();
+ it('shows the rows', () => {
+ expect(findPackagesListRow().exists()).toBe(true);
});
+ });
+ describe('layout', () => {
it('contains a pagination component', () => {
- const sorting = findPackageListPagination();
- expect(sorting.exists()).toBe(true);
+ mountComponent({ pageInfo: { hasPreviousPage: true } });
+
+ expect(findPackageListPagination().exists()).toBe(true);
});
it('contains a modal component', () => {
- const sorting = findPackageListDeleteModal();
- expect(sorting.exists()).toBe(true);
+ mountComponent();
+
+ expect(findPackageListDeleteModal().exists()).toBe(true);
});
});
describe('when the user can destroy the package', () => {
beforeEach(() => {
mountComponent();
+ findPackagesListRow().vm.$emit('packageToDelete', firstPackage);
+ return nextTick();
});
- it('setItemToBeDeleted sets itemToBeDeleted and open the modal', () => {
- const mockModalShow = jest.spyOn(wrapper.vm.$refs.packageListDeleteModal, 'show');
- const item = last(wrapper.vm.list);
+ it('deleting a package opens the modal', () => {
+ expect(findPackageListDeleteModal().text()).toContain(firstPackage.name);
+ });
- findPackagesListRow().vm.$emit('packageToDelete', item);
+ it('confirming on the modal emits package:delete', async () => {
+ findPackageListDeleteModal().vm.$emit('ok');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.itemToBeDeleted).toEqual(item);
- expect(mockModalShow).toHaveBeenCalled();
- });
- });
+ await nextTick();
- it('deleteItemConfirmation resets itemToBeDeleted', () => {
- wrapper.setData({ itemToBeDeleted: 1 });
- wrapper.vm.deleteItemConfirmation();
- expect(wrapper.vm.itemToBeDeleted).toEqual(null);
+ expect(wrapper.emitted('package:delete')[0]).toEqual([firstPackage]);
});
- it('deleteItemConfirmation emit package:delete', () => {
- const itemToBeDeleted = { id: 2 };
- wrapper.setData({ itemToBeDeleted });
- wrapper.vm.deleteItemConfirmation();
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.emitted('package:delete')[0]).toEqual([itemToBeDeleted]);
- });
- });
+ it('closing the modal resets itemToBeDeleted', async () => {
+ // triggering the v-model
+ findPackageListDeleteModal().vm.$emit('input', false);
- it('deleteItemCanceled resets itemToBeDeleted', () => {
- wrapper.setData({ itemToBeDeleted: 1 });
- wrapper.vm.deleteItemCanceled();
- expect(wrapper.vm.itemToBeDeleted).toEqual(null);
+ await nextTick();
+
+ expect(findPackageListDeleteModal().text()).not.toContain(firstPackage.name);
});
});
describe('when the list is empty', () => {
beforeEach(() => {
- mountComponent({
- packages: [],
- slots: {
- 'empty-state': EmptySlotStub,
- },
- });
+ mountComponent({ list: [] });
});
it('show the empty slot', () => {
@@ -171,45 +151,59 @@ describe('packages_list', () => {
});
});
- describe('pagination component', () => {
- let pagination;
- let modelEvent;
-
+ describe('pagination ', () => {
beforeEach(() => {
- mountComponent();
- pagination = findPackageListPagination();
- // retrieve the event used by v-model, a more sturdy approach than hardcoding it
- modelEvent = pagination.vm.$options.model.event;
+ mountComponent({ pageInfo: { hasPreviousPage: true } });
});
- it('emits page:changed events when the page changes', () => {
- pagination.vm.$emit(modelEvent, 2);
- expect(wrapper.emitted('page:changed')).toEqual([[2]]);
+ it('emits prev-page events when the prev event is fired', () => {
+ findPackageListPagination().vm.$emit('prev');
+
+ expect(wrapper.emitted('prev-page')).toEqual([[]]);
+ });
+
+ it('emits next-page events when the next event is fired', () => {
+ findPackageListPagination().vm.$emit('next');
+
+ expect(wrapper.emitted('next-page')).toEqual([[]]);
});
});
describe('tracking', () => {
let eventSpy;
- let utilSpy;
- const category = 'foo';
+ const category = 'UI::NpmPackages';
beforeEach(() => {
- mountComponent();
eventSpy = jest.spyOn(Tracking, 'event');
- utilSpy = jest.spyOn(SharedUtils, 'packageTypeToTrackCategory').mockReturnValue(category);
- wrapper.setData({ itemToBeDeleted: { package_type: 'conan' } });
+ mountComponent();
+ findPackagesListRow().vm.$emit('packageToDelete', firstPackage);
+ return nextTick();
});
- it('tracking category calls packageTypeToTrackCategory', () => {
- expect(wrapper.vm.tracking.category).toBe(category);
- expect(utilSpy).toHaveBeenCalledWith('conan');
+ it('requesting the delete tracks the right action', () => {
+ expect(eventSpy).toHaveBeenCalledWith(
+ category,
+ REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
+ expect.any(Object),
+ );
+ });
+
+ it('confirming delete tracks the right action', () => {
+ findPackageListDeleteModal().vm.$emit('ok');
+
+ expect(eventSpy).toHaveBeenCalledWith(
+ category,
+ DELETE_PACKAGE_TRACKING_ACTION,
+ expect.any(Object),
+ );
});
- it('deleteItemConfirmation calls event', () => {
- wrapper.vm.deleteItemConfirmation();
+ it('canceling delete tracks the right action', () => {
+ findPackageListDeleteModal().vm.$emit('cancel');
+
expect(eventSpy).toHaveBeenCalledWith(
category,
- TrackingActions.DELETE_PACKAGE,
+ CANCEL_DELETE_PACKAGE_TRACKING_ACTION,
expect.any(Object),
);
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js
index e65b2a6f320..bed7a07ff36 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js
@@ -1,6 +1,6 @@
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { sortableFields } from '~/packages/list/utils';
+import { sortableFields } from '~/packages_and_registries/package_registry/utils';
import component from '~/packages_and_registries/package_registry/components/list/package_search.vue';
import PackageTypeToken from '~/packages_and_registries/package_registry/components/list/tokens/package_type_token.vue';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/packages_title_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/packages_title_spec.js
index 3fa96ce1d29..e992ba12faa 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/packages_title_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/packages_title_spec.js
@@ -1,5 +1,4 @@
import { shallowMount } from '@vue/test-utils';
-import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '~/packages/list/constants';
import PackageTitle from '~/packages_and_registries/package_registry/components/list/package_title.vue';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
@@ -37,8 +36,8 @@ describe('PackageTitle', () => {
mountComponent();
expect(findTitleArea().props()).toMatchObject({
- title: LIST_TITLE_TEXT,
- infoMessages: [{ text: LIST_INTRO_TEXT, link: 'foo' }],
+ title: PackageTitle.i18n.LIST_TITLE_TEXT,
+ infoMessages: [{ text: PackageTitle.i18n.LIST_INTRO_TEXT, link: 'foo' }],
});
});
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js
index b0cbe34f0b9..26b2f3b359f 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js
@@ -1,7 +1,7 @@
import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import component from '~/packages/list/components/tokens/package_type_token.vue';
-import { PACKAGE_TYPES } from '~/packages/list/constants';
+import component from '~/packages_and_registries/package_registry/components/list/tokens/package_type_token.vue';
+import { PACKAGE_TYPES } from '~/packages_and_registries/package_registry/constants';
describe('packages_filter', () => {
let wrapper;
@@ -41,8 +41,8 @@ describe('packages_filter', () => {
(packageType, index) => {
mountComponent();
const item = findFilteredSearchSuggestions().at(index);
- expect(item.text()).toBe(packageType.title);
- expect(item.props('value')).toBe(packageType.type);
+ expect(item.text()).toBe(packageType);
+ expect(item.props('value')).toBe(packageType);
},
);
});
diff --git a/spec/frontend/packages_and_registries/package_registry/mock_data.js b/spec/frontend/packages_and_registries/package_registry/mock_data.js
index 70fc096fa44..bacc748db81 100644
--- a/spec/frontend/packages_and_registries/package_registry/mock_data.js
+++ b/spec/frontend/packages_and_registries/package_registry/mock_data.js
@@ -1,3 +1,5 @@
+import capitalize from 'lodash/capitalize';
+
export const packageTags = () => [
{ id: 'gid://gitlab/Packages::Tag/87', name: 'bananas_9', __typename: 'PackageTag' },
{ id: 'gid://gitlab/Packages::Tag/86', name: 'bananas_8', __typename: 'PackageTag' },
@@ -156,6 +158,15 @@ export const nugetMetadata = () => ({
projectUrl: 'projectUrl',
});
+export const pagination = (extend) => ({
+ endCursor: 'eyJpZCI6IjIwNSIsIm5hbWUiOiJteS9jb21wYW55L2FwcC9teS1hcHAifQ',
+ hasNextPage: true,
+ hasPreviousPage: true,
+ startCursor: 'eyJpZCI6IjI0NyIsIm5hbWUiOiJ2ZXJzaW9uX3Rlc3QxIn0',
+ __typename: 'PageInfo',
+ ...extend,
+});
+
export const packageDetailsQuery = (extendPackage) => ({
data: {
package: {
@@ -256,7 +267,7 @@ export const packageDestroyFileMutationError = () => ({
],
});
-export const packagesListQuery = (type = 'group') => ({
+export const packagesListQuery = ({ type = 'group', extend = {}, extendPagination = {} } = {}) => ({
data: {
[type]: {
packages: {
@@ -277,9 +288,11 @@ export const packagesListQuery = (type = 'group') => ({
pipelines: { nodes: [] },
},
],
+ pageInfo: pagination(extendPagination),
__typename: 'PackageConnection',
},
- __typename: 'Group',
+ ...extend,
+ __typename: capitalize(type),
},
},
});
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js
index c56244a9138..5c9ade7f785 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlFormGroup, GlFormSelect } from 'jest/registry/shared/stubs';
+import { GlFormGroup, GlFormSelect } from 'jest/packages_and_registries/shared/stubs';
import component from '~/packages_and_registries/settings/project/components/expiration_dropdown.vue';
describe('ExpirationDropdown', () => {
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js
index dd876d1d295..6b681924fcf 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js
@@ -1,6 +1,6 @@
import { GlSprintf, GlFormInput, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlFormGroup } from 'jest/registry/shared/stubs';
+import { GlFormGroup } from 'jest/packages_and_registries/shared/stubs';
import component from '~/packages_and_registries/settings/project/components/expiration_input.vue';
import { NAME_REGEX_LENGTH } from '~/packages_and_registries/settings/project/constants';
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js
index 854830391c5..94f7783afe7 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js
@@ -1,6 +1,6 @@
import { GlFormInput } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlFormGroup } from 'jest/registry/shared/stubs';
+import { GlFormGroup } from 'jest/packages_and_registries/shared/stubs';
import component from '~/packages_and_registries/settings/project/components/expiration_run_text.vue';
import {
NEXT_CLEANUP_LABEL,
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js
index 3a3eb089b43..45039614e49 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js
@@ -1,6 +1,6 @@
import { GlToggle, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlFormGroup } from 'jest/registry/shared/stubs';
+import { GlFormGroup } from 'jest/packages_and_registries/shared/stubs';
import component from '~/packages_and_registries/settings/project/components/expiration_toggle.vue';
import {
ENABLED_TOGGLE_DESCRIPTION,
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js
index 3a71af94d5a..bc104a25ef9 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js
@@ -2,7 +2,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { GlCard, GlLoadingIcon } from 'jest/registry/shared/stubs';
+import { GlCard, GlLoadingIcon } from 'jest/packages_and_registries/shared/stubs';
import component from '~/packages_and_registries/settings/project/components/settings_form.vue';
import {
UPDATE_SETTINGS_ERROR_MESSAGE,
diff --git a/spec/frontend/registry/shared/mocks.js b/spec/frontend/packages_and_registries/shared/mocks.js
index fdef38b6f10..fdef38b6f10 100644
--- a/spec/frontend/registry/shared/mocks.js
+++ b/spec/frontend/packages_and_registries/shared/mocks.js
diff --git a/spec/frontend/registry/shared/stubs.js b/spec/frontend/packages_and_registries/shared/stubs.js
index ad41eb42df4..ad41eb42df4 100644
--- a/spec/frontend/registry/shared/stubs.js
+++ b/spec/frontend/packages_and_registries/shared/stubs.js
diff --git a/spec/frontend/pages/admin/projects/components/namespace_select_spec.js b/spec/frontend/pages/admin/projects/components/namespace_select_spec.js
index c579aa2f2da..1fcc00489e3 100644
--- a/spec/frontend/pages/admin/projects/components/namespace_select_spec.js
+++ b/spec/frontend/pages/admin/projects/components/namespace_select_spec.js
@@ -38,7 +38,7 @@ describe('Dropdown select component', () => {
it('creates a hidden input if fieldName is provided', () => {
mountDropdown({ fieldName: 'namespace-input' });
- expect(findNamespaceInput()).toExist();
+ expect(findNamespaceInput().exists()).toBe(true);
expect(findNamespaceInput().attributes('name')).toBe('namespace-input');
});
@@ -57,9 +57,9 @@ describe('Dropdown select component', () => {
// wait for dropdown options to populate
await wrapper.vm.$nextTick();
- expect(findDropdownOption('user: Administrator')).toExist();
- expect(findDropdownOption('group: GitLab Org')).toExist();
- expect(findDropdownOption('group: Foobar')).not.toExist();
+ expect(findDropdownOption('user: Administrator').exists()).toBe(true);
+ expect(findDropdownOption('group: GitLab Org').exists()).toBe(true);
+ expect(findDropdownOption('group: Foobar').exists()).toBe(false);
findDropdownOption('user: Administrator').trigger('click');
await wrapper.vm.$nextTick();
diff --git a/spec/frontend/pages/dashboard/todos/index/todos_spec.js b/spec/frontend/pages/dashboard/todos/index/todos_spec.js
index de8b29d54fc..5bba98bdf96 100644
--- a/spec/frontend/pages/dashboard/todos/index/todos_spec.js
+++ b/spec/frontend/pages/dashboard/todos/index/todos_spec.js
@@ -94,13 +94,13 @@ describe('Todos', () => {
});
it('updates pending text', () => {
- expect(document.querySelector('.todos-pending .badge').innerHTML).toEqual(
+ expect(document.querySelector('.js-todos-pending .badge').innerHTML).toEqual(
addDelimiter(TEST_COUNT_BIG),
);
});
it('updates done text', () => {
- expect(document.querySelector('.todos-done .badge').innerHTML).toEqual(
+ expect(document.querySelector('.js-todos-done .badge').innerHTML).toEqual(
addDelimiter(TEST_DONE_COUNT_BIG),
);
});
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap
index 3aa0e99a858..3e371a8765f 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap
+++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap
@@ -135,6 +135,7 @@ exports[`Learn GitLab renders correctly 1`] = `
<a
class="gl-link"
data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Set up CI/CD"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
@@ -156,6 +157,7 @@ exports[`Learn GitLab renders correctly 1`] = `
<a
class="gl-link"
data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Start a free Ultimate trial"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
@@ -177,6 +179,7 @@ exports[`Learn GitLab renders correctly 1`] = `
<a
class="gl-link"
data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Add code owners"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
@@ -205,6 +208,7 @@ exports[`Learn GitLab renders correctly 1`] = `
<a
class="gl-link"
data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Add merge request approval"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
@@ -269,6 +273,7 @@ exports[`Learn GitLab renders correctly 1`] = `
<a
class="gl-link"
data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Create an issue"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
@@ -290,6 +295,7 @@ exports[`Learn GitLab renders correctly 1`] = `
<a
class="gl-link"
data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Submit a merge request"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
@@ -347,6 +353,7 @@ exports[`Learn GitLab renders correctly 1`] = `
<a
class="gl-link"
data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
data-track-label="Run a Security scan using CI/CD"
data-track-property="Growth::Conversion::Experiment::LearnGitLab"
href="http://example.com/"
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js
index f8099d7e95a..7e97a539a99 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js
+++ b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js
@@ -1,13 +1,17 @@
import { GlProgressBar } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import LearnGitlab from '~/pages/projects/learn_gitlab/components/learn_gitlab.vue';
+import eventHub from '~/invite_members/event_hub';
import { testActions, testSections } from './mock_data';
describe('Learn GitLab', () => {
let wrapper;
+ let inviteMembersOpen = false;
const createWrapper = () => {
- wrapper = mount(LearnGitlab, { propsData: { actions: testActions, sections: testSections } });
+ wrapper = mount(LearnGitlab, {
+ propsData: { actions: testActions, sections: testSections, inviteMembersOpen },
+ });
};
beforeEach(() => {
@@ -17,6 +21,7 @@ describe('Learn GitLab', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
+ inviteMembersOpen = false;
});
it('renders correctly', () => {
@@ -35,4 +40,30 @@ describe('Learn GitLab', () => {
expect(progressBar.attributes('value')).toBe('2');
expect(progressBar.attributes('max')).toBe('9');
});
+
+ describe('Invite Members Modal', () => {
+ let spy;
+
+ beforeEach(() => {
+ spy = jest.spyOn(eventHub, '$emit');
+ });
+
+ it('emits openModal', () => {
+ inviteMembersOpen = true;
+
+ createWrapper();
+
+ expect(spy).toHaveBeenCalledWith('openModal', {
+ mode: 'celebrate',
+ inviteeType: 'members',
+ source: 'learn-gitlab',
+ });
+ });
+
+ it('does not emit openModal', () => {
+ createWrapper();
+
+ expect(spy).not.toHaveBeenCalled();
+ });
+ });
});
diff --git a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
index 082a8977710..9d510b3d231 100644
--- a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
+++ b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
@@ -8,9 +8,11 @@ import waitForPromises from 'helpers/wait_for_promises';
import ContentEditor from '~/content_editor/components/content_editor.vue';
import WikiForm from '~/pages/shared/wikis/components/wiki_form.vue';
import {
- WIKI_CONTENT_EDITOR_TRACKING_LABEL,
CONTENT_EDITOR_LOADED_ACTION,
SAVED_USING_CONTENT_EDITOR_ACTION,
+ WIKI_CONTENT_EDITOR_TRACKING_LABEL,
+ WIKI_FORMAT_LABEL,
+ WIKI_FORMAT_UPDATED_ACTION,
} from '~/pages/shared/wikis/constants';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
@@ -65,7 +67,6 @@ describe('WikiForm', () => {
const pageInfoPersisted = {
...pageInfoNew,
persisted: true,
-
title: 'My page',
content: ' My page content ',
format: 'markdown',
@@ -177,7 +178,7 @@ describe('WikiForm', () => {
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain(titleHelpText);
- expect(findTitleHelpLink().attributes().href).toEqual(titleHelpLink);
+ expect(findTitleHelpLink().attributes().href).toBe(titleHelpLink);
},
);
@@ -186,7 +187,7 @@ describe('WikiForm', () => {
await wrapper.vm.$nextTick();
- expect(findMarkdownHelpLink().attributes().href).toEqual(
+ expect(findMarkdownHelpLink().attributes().href).toBe(
'/help/user/markdown#wiki-specific-markdown',
);
});
@@ -220,8 +221,8 @@ describe('WikiForm', () => {
expect(e.preventDefault).not.toHaveBeenCalled();
});
- it('does not trigger tracking event', async () => {
- expect(trackingSpy).not.toHaveBeenCalled();
+ it('triggers wiki format tracking event', async () => {
+ expect(trackingSpy).toHaveBeenCalledTimes(1);
});
it('does not trim page content', () => {
@@ -273,7 +274,7 @@ describe('WikiForm', () => {
({ persisted, redirectLink }) => {
createWrapper(persisted);
- expect(findCancelButton().attributes().href).toEqual(redirectLink);
+ expect(findCancelButton().attributes().href).toBe(redirectLink);
},
);
});
@@ -438,7 +439,7 @@ describe('WikiForm', () => {
});
});
- it('triggers tracking event on form submit', async () => {
+ it('triggers tracking events on form submit', async () => {
triggerFormSubmit();
await wrapper.vm.$nextTick();
@@ -446,6 +447,15 @@ describe('WikiForm', () => {
expect(trackingSpy).toHaveBeenCalledWith(undefined, SAVED_USING_CONTENT_EDITOR_ACTION, {
label: WIKI_CONTENT_EDITOR_TRACKING_LABEL,
});
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, WIKI_FORMAT_UPDATED_ACTION, {
+ label: WIKI_FORMAT_LABEL,
+ value: findFormat().element.value,
+ extra: {
+ old_format: pageInfoPersisted.format,
+ project_path: pageInfoPersisted.path,
+ },
+ });
});
it('updates content from content editor on form submit', async () => {
diff --git a/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js b/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
index 8040c9d701c..23219042008 100644
--- a/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
+++ b/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
@@ -5,6 +5,9 @@ import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
import { mockCommitMessage, mockDefaultBranch } from '../../mock_data';
+const scrollIntoViewMock = jest.fn();
+HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
+
describe('Pipeline Editor | Commit Form', () => {
let wrapper;
@@ -113,4 +116,20 @@ describe('Pipeline Editor | Commit Form', () => {
expect(findSubmitBtn().attributes('disabled')).toBe('disabled');
});
});
+
+ describe('when scrollToCommitForm becomes true', () => {
+ beforeEach(async () => {
+ createComponent();
+ wrapper.setProps({ scrollToCommitForm: true });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('scrolls into view', () => {
+ expect(scrollIntoViewMock).toHaveBeenCalledWith({ behavior: 'smooth' });
+ });
+
+ it('emits "scrolled-to-commit-form"', () => {
+ expect(wrapper.emitted()['scrolled-to-commit-form']).toBeTruthy();
+ });
+ });
});
diff --git a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
index 2f934898ef1..efc345d8877 100644
--- a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
+++ b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
@@ -52,6 +52,7 @@ describe('Pipeline Editor | Commit section', () => {
const defaultProps = {
ciFileContent: mockCiYml,
commitSha: mockCommitSha,
+ isNewCiConfigFile: false,
};
const createComponent = ({ props = {}, options = {}, provide = {} } = {}) => {
@@ -72,7 +73,6 @@ describe('Pipeline Editor | Commit section', () => {
data() {
return {
currentBranch: mockDefaultBranch,
- isNewCiConfigFile: Boolean(options?.isNewCiConfigfile),
};
},
mocks: {
@@ -115,7 +115,7 @@ describe('Pipeline Editor | Commit section', () => {
describe('when the user commits a new file', () => {
beforeEach(async () => {
- createComponent({ options: { isNewCiConfigfile: true } });
+ createComponent({ props: { isNewCiConfigFile: true } });
await submitCommit();
});
@@ -277,4 +277,16 @@ describe('Pipeline Editor | Commit section', () => {
expect(wrapper.emitted('resetContent')).toHaveLength(1);
});
});
+
+ it('sets listeners on commit form', () => {
+ const handler = jest.fn();
+ createComponent({ options: { listeners: { event: handler } } });
+ findCommitForm().vm.$emit('event');
+ expect(handler).toHaveBeenCalled();
+ });
+
+ it('passes down scroll-to-commit-form prop to commit form', () => {
+ createComponent({ props: { 'scroll-to-commit-form': true } });
+ expect(findCommitForm().props('scrollToCommitForm')).toBe(true);
+ });
});
diff --git a/spec/frontend/pipeline_editor/components/drawer/pipeline_editor_drawer_spec.js b/spec/frontend/pipeline_editor/components/drawer/pipeline_editor_drawer_spec.js
index 1b68cd3dc43..4df7768b035 100644
--- a/spec/frontend/pipeline_editor/components/drawer/pipeline_editor_drawer_spec.js
+++ b/spec/frontend/pipeline_editor/components/drawer/pipeline_editor_drawer_spec.js
@@ -1,6 +1,7 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
+import { stubExperiments } from 'helpers/experimentation_helper';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import FirstPipelineCard from '~/pipeline_editor/components/drawer/cards/first_pipeline_card.vue';
import GettingStartedCard from '~/pipeline_editor/components/drawer/cards/getting_started_card.vue';
@@ -33,19 +34,41 @@ describe('Pipeline editor drawer', () => {
const clickToggleBtn = async () => findToggleBtn().vm.$emit('click');
+ const originalObjects = [];
+
+ beforeEach(() => {
+ originalObjects.push(window.gon, window.gl);
+ stubExperiments({ pipeline_editor_walkthrough: 'control' });
+ });
+
afterEach(() => {
wrapper.destroy();
localStorage.clear();
+ [window.gon, window.gl] = originalObjects;
});
- it('it sets the drawer to be opened by default', async () => {
- createComponent();
-
- expect(findDrawerContent().exists()).toBe(false);
-
- await nextTick();
+ describe('default expanded state', () => {
+ describe('when experiment control', () => {
+ it('sets the drawer to be opened by default', async () => {
+ createComponent();
+ expect(findDrawerContent().exists()).toBe(false);
+ await nextTick();
+ expect(findDrawerContent().exists()).toBe(true);
+ });
+ });
- expect(findDrawerContent().exists()).toBe(true);
+ describe('when experiment candidate', () => {
+ beforeEach(() => {
+ stubExperiments({ pipeline_editor_walkthrough: 'candidate' });
+ });
+
+ it('sets the drawer to be closed by default', async () => {
+ createComponent();
+ expect(findDrawerContent().exists()).toBe(false);
+ await nextTick();
+ expect(findDrawerContent().exists()).toBe(false);
+ });
+ });
});
describe('when the drawer is collapsed', () => {
diff --git a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
index b5881790b0b..6532c4e289d 100644
--- a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
+++ b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
@@ -36,8 +36,9 @@ describe('Pipeline editor branch switcher', () => {
let mockLastCommitBranchQuery;
const createComponent = (
- { currentBranch, isQueryLoading, mountFn, options } = {
+ { currentBranch, isQueryLoading, mountFn, options, props } = {
currentBranch: mockDefaultBranch,
+ hasUnsavedChanges: false,
isQueryLoading: false,
mountFn: shallowMount,
options: {},
@@ -45,6 +46,7 @@ describe('Pipeline editor branch switcher', () => {
) => {
wrapper = mountFn(BranchSwitcher, {
propsData: {
+ ...props,
paginationLimit: mockBranchPaginationLimit,
},
provide: {
@@ -70,7 +72,7 @@ describe('Pipeline editor branch switcher', () => {
});
};
- const createComponentWithApollo = (mountFn = shallowMount) => {
+ const createComponentWithApollo = ({ mountFn = shallowMount, props = {} } = {}) => {
const handlers = [[getAvailableBranchesQuery, mockAvailableBranchQuery]];
const resolvers = {
Query: {
@@ -86,6 +88,7 @@ describe('Pipeline editor branch switcher', () => {
createComponent({
mountFn,
+ props,
options: {
localVue,
apolloProvider: mockApollo,
@@ -138,8 +141,8 @@ describe('Pipeline editor branch switcher', () => {
createComponentWithApollo();
});
- it('does not render dropdown', () => {
- expect(findDropdown().exists()).toBe(false);
+ it('disables the dropdown', () => {
+ expect(findDropdown().props('disabled')).toBe(true);
});
});
@@ -149,7 +152,7 @@ describe('Pipeline editor branch switcher', () => {
availableBranches: mockProjectBranches,
currentBranch: mockDefaultBranch,
});
- createComponentWithApollo(mount);
+ createComponentWithApollo({ mountFn: mount });
await waitForPromises();
});
@@ -186,7 +189,7 @@ describe('Pipeline editor branch switcher', () => {
});
it('does not render dropdown', () => {
- expect(findDropdown().exists()).toBe(false);
+ expect(findDropdown().props('disabled')).toBe(true);
});
it('shows an error message', () => {
@@ -201,7 +204,7 @@ describe('Pipeline editor branch switcher', () => {
availableBranches: mockProjectBranches,
currentBranch: mockDefaultBranch,
});
- createComponentWithApollo(mount);
+ createComponentWithApollo({ mountFn: mount });
await waitForPromises();
});
@@ -247,6 +250,23 @@ describe('Pipeline editor branch switcher', () => {
expect(wrapper.emitted('refetchContent')).toBeUndefined();
});
+
+ describe('with unsaved changes', () => {
+ beforeEach(async () => {
+ createComponentWithApollo({ mountFn: mount, props: { hasUnsavedChanges: true } });
+ await waitForPromises();
+ });
+
+ it('emits `select-branch` event and does not switch branch', async () => {
+ expect(wrapper.emitted('select-branch')).toBeUndefined();
+
+ const branch = findDropdownItems().at(1);
+ await branch.vm.$emit('click');
+
+ expect(wrapper.emitted('select-branch')).toEqual([[branch.text()]]);
+ expect(wrapper.emitted('refetchContent')).toBeUndefined();
+ });
+ });
});
describe('when searching', () => {
@@ -255,7 +275,7 @@ describe('Pipeline editor branch switcher', () => {
availableBranches: mockProjectBranches,
currentBranch: mockDefaultBranch,
});
- createComponentWithApollo(mount);
+ createComponentWithApollo({ mountFn: mount });
await waitForPromises();
});
@@ -429,7 +449,7 @@ describe('Pipeline editor branch switcher', () => {
availableBranches: mockProjectBranches,
currentBranch: mockDefaultBranch,
});
- createComponentWithApollo(mount);
+ createComponentWithApollo({ mountFn: mount });
await waitForPromises();
await createNewBranch();
});
diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
index 44656b2b67d..29ab52bde8f 100644
--- a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
@@ -16,7 +16,7 @@ describe('Pipeline Status', () => {
let mockApollo;
let mockPipelineQuery;
- const createComponentWithApollo = (glFeatures = {}) => {
+ const createComponentWithApollo = () => {
const handlers = [[getPipelineQuery, mockPipelineQuery]];
mockApollo = createMockApollo(handlers);
@@ -27,7 +27,6 @@ describe('Pipeline Status', () => {
commitSha: mockCommitSha,
},
provide: {
- glFeatures,
projectFullPath: mockProjectFullPath,
},
stubs: { GlLink, GlSprintf },
@@ -40,6 +39,8 @@ describe('Pipeline Status', () => {
const findPipelineId = () => wrapper.find('[data-testid="pipeline-id"]');
const findPipelineCommit = () => wrapper.find('[data-testid="pipeline-commit"]');
const findPipelineErrorMsg = () => wrapper.find('[data-testid="pipeline-error-msg"]');
+ const findPipelineNotTriggeredErrorMsg = () =>
+ wrapper.find('[data-testid="pipeline-not-triggered-error-msg"]');
const findPipelineLoadingMsg = () => wrapper.find('[data-testid="pipeline-loading-msg"]');
const findPipelineViewBtn = () => wrapper.find('[data-testid="pipeline-view-btn"]');
const findStatusIcon = () => wrapper.find('[data-testid="pipeline-status-icon"]');
@@ -95,17 +96,18 @@ describe('Pipeline Status', () => {
it('renders pipeline data', () => {
const {
id,
+ commit: { title },
detailedStatus: { detailsPath },
} = mockProjectPipeline().pipeline;
expect(findStatusIcon().exists()).toBe(true);
expect(findPipelineId().text()).toBe(`#${id.match(/\d+/g)[0]}`);
- expect(findPipelineCommit().text()).toBe(mockCommitSha);
+ expect(findPipelineCommit().text()).toBe(`${mockCommitSha}: ${title}`);
expect(findPipelineViewBtn().attributes('href')).toBe(detailsPath);
});
- it('does not render the pipeline mini graph', () => {
- expect(findPipelineEditorMiniGraph().exists()).toBe(false);
+ it('renders the pipeline mini graph', () => {
+ expect(findPipelineEditorMiniGraph().exists()).toBe(true);
});
});
@@ -117,7 +119,8 @@ describe('Pipeline Status', () => {
await waitForPromises();
});
- it('renders error', () => {
+ it('renders api error', () => {
+ expect(findPipelineNotTriggeredErrorMsg().exists()).toBe(false);
expect(findIcon().attributes('name')).toBe('warning-solid');
expect(findPipelineErrorMsg().text()).toBe(i18n.fetchError);
});
@@ -129,20 +132,22 @@ describe('Pipeline Status', () => {
expect(findPipelineViewBtn().exists()).toBe(false);
});
});
- });
- describe('when feature flag for pipeline mini graph is enabled', () => {
- beforeEach(() => {
- mockPipelineQuery.mockResolvedValue({
- data: { project: mockProjectPipeline() },
- });
+ describe('when pipeline is null', () => {
+ beforeEach(() => {
+ mockPipelineQuery.mockResolvedValue({
+ data: { project: { pipeline: null } },
+ });
- createComponentWithApollo({ pipelineEditorMiniGraph: true });
- waitForPromises();
- });
+ createComponentWithApollo();
+ waitForPromises();
+ });
- it('renders the pipeline mini graph', () => {
- expect(findPipelineEditorMiniGraph().exists()).toBe(true);
+ it('renders pipeline not triggered error', () => {
+ expect(findPipelineErrorMsg().exists()).toBe(false);
+ expect(findIcon().attributes('name')).toBe('information-o');
+ expect(findPipelineNotTriggeredErrorMsg().text()).toBe(i18n.pipelineNotTriggeredMsg);
+ });
});
});
});
diff --git a/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js b/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js
index 3d7c3c839da..6b9f576917f 100644
--- a/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js
@@ -1,22 +1,54 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
import PipelineEditorMiniGraph from '~/pipeline_editor/components/header/pipeline_editor_mini_graph.vue';
import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue';
-import { mockProjectPipeline } from '../../mock_data';
+import getLinkedPipelinesQuery from '~/projects/commit_box/info/graphql/queries/get_linked_pipelines.query.graphql';
+import { PIPELINE_FAILURE } from '~/pipeline_editor/constants';
+import { mockLinkedPipelines, mockProjectFullPath, mockProjectPipeline } from '../../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
describe('Pipeline Status', () => {
let wrapper;
+ let mockApollo;
+ let mockLinkedPipelinesQuery;
- const createComponent = ({ hasStages = true } = {}) => {
+ const createComponent = ({ hasStages = true, options } = {}) => {
wrapper = shallowMount(PipelineEditorMiniGraph, {
+ provide: {
+ dataMethod: 'graphql',
+ projectFullPath: mockProjectFullPath,
+ },
propsData: {
pipeline: mockProjectPipeline({ hasStages }).pipeline,
},
+ ...options,
+ });
+ };
+
+ const createComponentWithApollo = (hasStages = true) => {
+ const handlers = [[getLinkedPipelinesQuery, mockLinkedPipelinesQuery]];
+ mockApollo = createMockApollo(handlers);
+
+ createComponent({
+ hasStages,
+ options: {
+ localVue,
+ apolloProvider: mockApollo,
+ },
});
};
const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph);
+ beforeEach(() => {
+ mockLinkedPipelinesQuery = jest.fn();
+ });
+
afterEach(() => {
+ mockLinkedPipelinesQuery.mockReset();
wrapper.destroy();
});
@@ -39,4 +71,38 @@ describe('Pipeline Status', () => {
expect(findPipelineMiniGraph().exists()).toBe(false);
});
});
+
+ describe('when querying upstream and downstream pipelines', () => {
+ describe('when query succeeds', () => {
+ beforeEach(() => {
+ mockLinkedPipelinesQuery.mockResolvedValue(mockLinkedPipelines());
+ createComponentWithApollo();
+ });
+
+ it('should call the query with the correct variables', () => {
+ expect(mockLinkedPipelinesQuery).toHaveBeenCalledTimes(1);
+ expect(mockLinkedPipelinesQuery).toHaveBeenCalledWith({
+ fullPath: mockProjectFullPath,
+ iid: mockProjectPipeline().pipeline.iid,
+ });
+ });
+ });
+
+ describe('when query fails', () => {
+ beforeEach(() => {
+ mockLinkedPipelinesQuery.mockRejectedValue(new Error());
+ createComponentWithApollo();
+ });
+
+ it('should emit an error event when query fails', async () => {
+ expect(wrapper.emitted('showError')).toHaveLength(1);
+ expect(wrapper.emitted('showError')[0]).toEqual([
+ {
+ type: PIPELINE_FAILURE,
+ reasons: [wrapper.vm.$options.i18n.linkedPipelinesFetchError],
+ },
+ ]);
+ });
+ });
+ });
});
diff --git a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
index 5cf8d47bc23..f6154f50bc0 100644
--- a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
+++ b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
@@ -1,19 +1,27 @@
-import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import { GlAlert, GlLoadingIcon, GlTabs } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
+import setWindowLocation from 'helpers/set_window_location_helper';
import CiConfigMergedPreview from '~/pipeline_editor/components/editor/ci_config_merged_preview.vue';
+import WalkthroughPopover from '~/pipeline_editor/components/walkthrough_popover.vue';
import CiLint from '~/pipeline_editor/components/lint/ci_lint.vue';
import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
import EditorTab from '~/pipeline_editor/components/ui/editor_tab.vue';
+import { stubExperiments } from 'helpers/experimentation_helper';
import {
+ CREATE_TAB,
EDITOR_APP_STATUS_EMPTY,
- EDITOR_APP_STATUS_ERROR,
EDITOR_APP_STATUS_LOADING,
EDITOR_APP_STATUS_INVALID,
EDITOR_APP_STATUS_VALID,
+ MERGED_TAB,
+ TAB_QUERY_PARAM,
+ TABS_INDEX,
} from '~/pipeline_editor/constants';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
-import { mockLintResponse, mockCiYml } from '../mock_data';
+import { mockLintResponse, mockLintResponseWithoutMerged, mockCiYml } from '../mock_data';
+
+Vue.config.ignoredElements = ['gl-emoji'];
describe('Pipeline editor tabs component', () => {
let wrapper;
@@ -22,6 +30,7 @@ describe('Pipeline editor tabs component', () => {
};
const createComponent = ({
+ listeners = {},
props = {},
provide = {},
appStatus = EDITOR_APP_STATUS_VALID,
@@ -31,6 +40,7 @@ describe('Pipeline editor tabs component', () => {
propsData: {
ciConfigData: mockLintResponse,
ciFileContent: mockCiYml,
+ isNewCiConfigFile: true,
...props,
},
data() {
@@ -43,6 +53,7 @@ describe('Pipeline editor tabs component', () => {
TextEditor: MockTextEditor,
EditorTab,
},
+ listeners,
});
};
@@ -53,10 +64,12 @@ describe('Pipeline editor tabs component', () => {
const findAlert = () => wrapper.findComponent(GlAlert);
const findCiLint = () => wrapper.findComponent(CiLint);
+ const findGlTabs = () => wrapper.findComponent(GlTabs);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findPipelineGraph = () => wrapper.findComponent(PipelineGraph);
const findTextEditor = () => wrapper.findComponent(MockTextEditor);
const findMergedPreview = () => wrapper.findComponent(CiConfigMergedPreview);
+ const findWalkthroughPopover = () => wrapper.findComponent(WalkthroughPopover);
afterEach(() => {
wrapper.destroy();
@@ -137,7 +150,7 @@ describe('Pipeline editor tabs component', () => {
describe('when there is a fetch error', () => {
beforeEach(() => {
- createComponent({ appStatus: EDITOR_APP_STATUS_ERROR });
+ createComponent({ props: { ciConfigData: mockLintResponseWithoutMerged } });
});
it('show an error message', () => {
@@ -181,4 +194,113 @@ describe('Pipeline editor tabs component', () => {
},
);
});
+
+ describe('default tab based on url query param', () => {
+ const gitlabUrl = 'https://gitlab.test/ci/editor/';
+ const matchObject = {
+ hostname: 'gitlab.test',
+ pathname: '/ci/editor/',
+ search: '',
+ };
+
+ it(`is ${CREATE_TAB} if the query param ${TAB_QUERY_PARAM} is not present`, () => {
+ setWindowLocation(gitlabUrl);
+ createComponent();
+
+ expect(window.location).toMatchObject(matchObject);
+ });
+
+ it(`is ${CREATE_TAB} tab if the query param ${TAB_QUERY_PARAM} is invalid`, () => {
+ const queryValue = 'FOO';
+ setWindowLocation(`${gitlabUrl}?${TAB_QUERY_PARAM}=${queryValue}`);
+ createComponent();
+
+ // If the query param remains unchanged, then we have ignored it.
+ expect(window.location).toMatchObject({
+ ...matchObject,
+ search: `?${TAB_QUERY_PARAM}=${queryValue}`,
+ });
+ });
+
+ it('is the tab specified in query param and transform it into an index value', async () => {
+ setWindowLocation(`${gitlabUrl}?${TAB_QUERY_PARAM}=${MERGED_TAB}`);
+ createComponent();
+
+ // If the query param has changed to an index, it means we have synced the
+ // query with.
+ expect(window.location).toMatchObject({
+ ...matchObject,
+ search: `?${TAB_QUERY_PARAM}=${TABS_INDEX[MERGED_TAB]}`,
+ });
+ });
+ });
+
+ describe('glTabs', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('passes the `sync-active-tab-with-query-params` prop', () => {
+ expect(findGlTabs().props('syncActiveTabWithQueryParams')).toBe(true);
+ });
+ });
+
+ describe('pipeline_editor_walkthrough experiment', () => {
+ describe('when in control path', () => {
+ beforeEach(() => {
+ stubExperiments({ pipeline_editor_walkthrough: 'control' });
+ });
+
+ it('does not show walkthrough popover', async () => {
+ createComponent({ mountFn: mount });
+ await nextTick();
+ expect(findWalkthroughPopover().exists()).toBe(false);
+ });
+ });
+
+ describe('when in candidate path', () => {
+ beforeEach(() => {
+ stubExperiments({ pipeline_editor_walkthrough: 'candidate' });
+ });
+
+ describe('when isNewCiConfigFile prop is true (default)', () => {
+ beforeEach(async () => {
+ createComponent({
+ mountFn: mount,
+ });
+ await nextTick();
+ });
+
+ it('shows walkthrough popover', async () => {
+ expect(findWalkthroughPopover().exists()).toBe(true);
+ });
+ });
+
+ describe('when isNewCiConfigFile prop is false', () => {
+ it('does not show walkthrough popover', async () => {
+ createComponent({ props: { isNewCiConfigFile: false }, mountFn: mount });
+ await nextTick();
+ expect(findWalkthroughPopover().exists()).toBe(false);
+ });
+ });
+ });
+ });
+
+ it('sets listeners on walkthrough popover', async () => {
+ stubExperiments({ pipeline_editor_walkthrough: 'candidate' });
+
+ const handler = jest.fn();
+
+ createComponent({
+ mountFn: mount,
+ listeners: {
+ event: handler,
+ },
+ });
+ await nextTick();
+
+ findWalkthroughPopover().vm.$emit('event');
+
+ expect(handler).toHaveBeenCalled();
+ });
});
diff --git a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js
index 9f910ed4f9c..a55176ccd79 100644
--- a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js
+++ b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_messages_spec.js
@@ -11,6 +11,7 @@ import {
DEFAULT_FAILURE,
DEFAULT_SUCCESS,
LOAD_FAILURE_UNKNOWN,
+ PIPELINE_FAILURE,
} from '~/pipeline_editor/constants';
beforeEach(() => {
@@ -65,6 +66,7 @@ describe('Pipeline Editor messages', () => {
failureType | message | expectedFailureType
${COMMIT_FAILURE} | ${'failed commit'} | ${COMMIT_FAILURE}
${LOAD_FAILURE_UNKNOWN} | ${'loading failure'} | ${LOAD_FAILURE_UNKNOWN}
+ ${PIPELINE_FAILURE} | ${'pipeline failure'} | ${PIPELINE_FAILURE}
${'random'} | ${'error without a specified type'} | ${DEFAULT_FAILURE}
`('shows a message for $message', ({ failureType, expectedFailureType }) => {
createComponent({ failureType, showFailure: true });
diff --git a/spec/frontend/pipeline_editor/components/walkthrough_popover_spec.js b/spec/frontend/pipeline_editor/components/walkthrough_popover_spec.js
new file mode 100644
index 00000000000..a9ce89ff521
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/walkthrough_popover_spec.js
@@ -0,0 +1,29 @@
+import { mount, shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import WalkthroughPopover from '~/pipeline_editor/components/walkthrough_popover.vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+
+Vue.config.ignoredElements = ['gl-emoji'];
+
+describe('WalkthroughPopover component', () => {
+ let wrapper;
+
+ const createComponent = (mountFn = shallowMount) => {
+ return extendedWrapper(mountFn(WalkthroughPopover));
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('CTA button clicked', () => {
+ beforeEach(async () => {
+ wrapper = createComponent(mount);
+ await wrapper.findByTestId('ctaBtn').trigger('click');
+ });
+
+ it('emits "walkthrough-popover-cta-clicked" event', async () => {
+ expect(wrapper.emitted()['walkthrough-popover-cta-clicked']).toBeTruthy();
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/mock_data.js b/spec/frontend/pipeline_editor/mock_data.js
index 0b0ff14486e..1bfc5c3b93d 100644
--- a/spec/frontend/pipeline_editor/mock_data.js
+++ b/spec/frontend/pipeline_editor/mock_data.js
@@ -1,4 +1,4 @@
-import { CI_CONFIG_STATUS_VALID } from '~/pipeline_editor/constants';
+import { CI_CONFIG_STATUS_INVALID, CI_CONFIG_STATUS_VALID } from '~/pipeline_editor/constants';
import { unwrapStagesWithNeeds } from '~/pipelines/components/unwrapping_utils';
export const mockProjectNamespace = 'user1';
@@ -35,6 +35,17 @@ job_build:
- echo "build"
needs: ["job_test_2"]
`;
+
+export const mockCiTemplateQueryResponse = {
+ data: {
+ project: {
+ ciTemplate: {
+ content: mockCiYml,
+ },
+ },
+ },
+};
+
export const mockBlobContentQueryResponse = {
data: {
project: { repository: { blobs: { nodes: [{ rawBlob: mockCiYml }] } } },
@@ -274,11 +285,14 @@ export const mockProjectPipeline = ({ hasStages = true } = {}) => {
return {
pipeline: {
- commitPath: '/-/commit/aabbccdd',
id: 'gid://gitlab/Ci::Pipeline/118',
iid: '28',
shortSha: mockCommitSha,
status: 'SUCCESS',
+ commit: {
+ title: 'Update .gitlabe-ci.yml',
+ webPath: '/-/commit/aabbccdd',
+ },
detailedStatus: {
detailsPath: '/root/sample-ci-project/-/pipelines/118',
group: 'success',
@@ -290,6 +304,62 @@ export const mockProjectPipeline = ({ hasStages = true } = {}) => {
};
};
+export const mockLinkedPipelines = ({ hasDownstream = true, hasUpstream = true } = {}) => {
+ let upstream = null;
+ let downstream = {
+ nodes: [],
+ __typename: 'PipelineConnection',
+ };
+
+ if (hasDownstream) {
+ downstream = {
+ nodes: [
+ {
+ id: 'gid://gitlab/Ci::Pipeline/612',
+ path: '/root/job-log-sections/-/pipelines/612',
+ project: { name: 'job-log-sections', __typename: 'Project' },
+ detailedStatus: {
+ group: 'success',
+ icon: 'status_success',
+ label: 'passed',
+ __typename: 'DetailedStatus',
+ },
+ __typename: 'Pipeline',
+ },
+ ],
+ __typename: 'PipelineConnection',
+ };
+ }
+
+ if (hasUpstream) {
+ upstream = {
+ id: 'gid://gitlab/Ci::Pipeline/610',
+ path: '/root/trigger-downstream/-/pipelines/610',
+ project: { name: 'trigger-downstream', __typename: 'Project' },
+ detailedStatus: {
+ group: 'success',
+ icon: 'status_success',
+ label: 'passed',
+ __typename: 'DetailedStatus',
+ },
+ __typename: 'Pipeline',
+ };
+ }
+
+ return {
+ data: {
+ project: {
+ pipeline: {
+ path: '/root/ci-project/-/pipelines/790',
+ downstream,
+ upstream,
+ },
+ __typename: 'Project',
+ },
+ },
+ };
+};
+
export const mockLintResponse = {
valid: true,
mergedYaml: mockCiYml,
@@ -326,6 +396,14 @@ export const mockLintResponse = {
],
};
+export const mockLintResponseWithoutMerged = {
+ valid: false,
+ status: CI_CONFIG_STATUS_INVALID,
+ errors: ['error'],
+ warnings: [],
+ jobs: [],
+};
+
export const mockJobs = [
{
name: 'job_1',
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
index b6713319e69..f6afef595c6 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
@@ -1,11 +1,9 @@
-import { GlAlert, GlButton, GlLoadingIcon, GlTabs } from '@gitlab/ui';
+import { GlAlert, GlButton, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import setWindowLocation from 'helpers/set_window_location_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
-import TextEditor from '~/pipeline_editor/components/editor/text_editor.vue';
import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
import PipelineEditorEmptyState from '~/pipeline_editor/components/ui/pipeline_editor_empty_state.vue';
@@ -13,17 +11,21 @@ import PipelineEditorMessages from '~/pipeline_editor/components/ui/pipeline_edi
import { COMMIT_SUCCESS, COMMIT_FAILURE } from '~/pipeline_editor/constants';
import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.graphql';
import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.graphql';
-import getPipelineQuery from '~/pipeline_editor/graphql/queries/client/pipeline.graphql';
import getTemplate from '~/pipeline_editor/graphql/queries/get_starter_template.query.graphql';
import getLatestCommitShaQuery from '~/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql';
+
+import getPipelineQuery from '~/pipeline_editor/graphql/queries/client/pipeline.graphql';
+
import PipelineEditorApp from '~/pipeline_editor/pipeline_editor_app.vue';
import PipelineEditorHome from '~/pipeline_editor/pipeline_editor_home.vue';
+
import {
mockCiConfigPath,
mockCiConfigQueryResponse,
mockBlobContentQueryResponse,
mockBlobContentQueryResponseNoCiFile,
mockCiYml,
+ mockCiTemplateQueryResponse,
mockCommitSha,
mockCommitShaResults,
mockDefaultBranch,
@@ -35,10 +37,6 @@ import {
const localVue = createLocalVue();
localVue.use(VueApollo);
-const MockSourceEditor = {
- template: '<div/>',
-};
-
const mockProvide = {
ciConfigPath: mockCiConfigPath,
defaultBranch: mockDefaultBranch,
@@ -55,19 +53,15 @@ describe('Pipeline editor app component', () => {
let mockLatestCommitShaQuery;
let mockPipelineQuery;
- const createComponent = ({ blobLoading = false, options = {}, provide = {} } = {}) => {
+ const createComponent = ({
+ blobLoading = false,
+ options = {},
+ provide = {},
+ stubs = {},
+ } = {}) => {
wrapper = shallowMount(PipelineEditorApp, {
provide: { ...mockProvide, ...provide },
- stubs: {
- GlTabs,
- GlButton,
- CommitForm,
- PipelineEditorHome,
- PipelineEditorTabs,
- PipelineEditorMessages,
- SourceEditor: MockSourceEditor,
- PipelineEditorEmptyState,
- },
+ stubs,
data() {
return {
commitSha: '',
@@ -89,7 +83,7 @@ describe('Pipeline editor app component', () => {
});
};
- const createComponentWithApollo = async ({ props = {}, provide = {} } = {}) => {
+ const createComponentWithApollo = async ({ provide = {}, stubs = {} } = {}) => {
const handlers = [
[getBlobContent, mockBlobContentData],
[getCiConfigData, mockCiConfigData],
@@ -97,7 +91,6 @@ describe('Pipeline editor app component', () => {
[getLatestCommitShaQuery, mockLatestCommitShaQuery],
[getPipelineQuery, mockPipelineQuery],
];
-
mockApollo = createMockApollo(handlers);
const options = {
@@ -105,13 +98,15 @@ describe('Pipeline editor app component', () => {
data() {
return {
currentBranch: mockDefaultBranch,
+ lastCommitBranch: '',
+ appStatus: '',
};
},
mocks: {},
apolloProvider: mockApollo,
};
- createComponent({ props, provide, options });
+ createComponent({ provide, stubs, options });
return waitForPromises();
};
@@ -119,7 +114,6 @@ describe('Pipeline editor app component', () => {
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findAlert = () => wrapper.findComponent(GlAlert);
const findEditorHome = () => wrapper.findComponent(PipelineEditorHome);
- const findTextEditor = () => wrapper.findComponent(TextEditor);
const findEmptyState = () => wrapper.findComponent(PipelineEditorEmptyState);
const findEmptyStateButton = () =>
wrapper.findComponent(PipelineEditorEmptyState).findComponent(GlButton);
@@ -141,7 +135,7 @@ describe('Pipeline editor app component', () => {
createComponent({ blobLoading: true });
expect(findLoadingIcon().exists()).toBe(true);
- expect(findTextEditor().exists()).toBe(false);
+ expect(findEditorHome().exists()).toBe(false);
});
});
@@ -185,7 +179,11 @@ describe('Pipeline editor app component', () => {
describe('when no CI config file exists', () => {
beforeEach(async () => {
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponseNoCiFile);
- await createComponentWithApollo();
+ await createComponentWithApollo({
+ stubs: {
+ PipelineEditorEmptyState,
+ },
+ });
jest
.spyOn(wrapper.vm.$apollo.queries.commitSha, 'startPolling')
@@ -206,8 +204,12 @@ describe('Pipeline editor app component', () => {
it('shows a unkown error message', async () => {
const loadUnknownFailureText = 'The CI configuration was not loaded, please try again.';
- mockBlobContentData.mockRejectedValueOnce(new Error('My error!'));
- await createComponentWithApollo();
+ mockBlobContentData.mockRejectedValueOnce();
+ await createComponentWithApollo({
+ stubs: {
+ PipelineEditorMessages,
+ },
+ });
expect(findEmptyState().exists()).toBe(false);
@@ -222,15 +224,20 @@ describe('Pipeline editor app component', () => {
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponseNoCiFile);
mockLatestCommitShaQuery.mockResolvedValue(mockEmptyCommitShaResults);
- await createComponentWithApollo();
+ await createComponentWithApollo({
+ stubs: {
+ PipelineEditorHome,
+ PipelineEditorEmptyState,
+ },
+ });
expect(findEmptyState().exists()).toBe(true);
- expect(findTextEditor().exists()).toBe(false);
+ expect(findEditorHome().exists()).toBe(false);
await findEmptyStateButton().vm.$emit('click');
expect(findEmptyState().exists()).toBe(false);
- expect(findTextEditor().exists()).toBe(true);
+ expect(findEditorHome().exists()).toBe(true);
});
});
@@ -241,7 +248,7 @@ describe('Pipeline editor app component', () => {
describe('and the commit mutation succeeds', () => {
beforeEach(async () => {
window.scrollTo = jest.fn();
- await createComponentWithApollo();
+ await createComponentWithApollo({ stubs: { PipelineEditorMessages } });
findEditorHome().vm.$emit('commit', { type: COMMIT_SUCCESS });
});
@@ -295,7 +302,7 @@ describe('Pipeline editor app component', () => {
beforeEach(async () => {
window.scrollTo = jest.fn();
- await createComponentWithApollo();
+ await createComponentWithApollo({ stubs: { PipelineEditorMessages } });
findEditorHome().vm.$emit('showError', {
type: COMMIT_FAILURE,
@@ -319,7 +326,7 @@ describe('Pipeline editor app component', () => {
beforeEach(async () => {
window.scrollTo = jest.fn();
- await createComponentWithApollo();
+ await createComponentWithApollo({ stubs: { PipelineEditorMessages } });
findEditorHome().vm.$emit('showError', {
type: COMMIT_FAILURE,
@@ -342,6 +349,8 @@ describe('Pipeline editor app component', () => {
describe('when refetching content', () => {
beforeEach(() => {
+ mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
+ mockCiConfigData.mockResolvedValue(mockCiConfigQueryResponse);
mockLatestCommitShaQuery.mockResolvedValue(mockCommitShaResults);
});
@@ -377,7 +386,10 @@ describe('Pipeline editor app component', () => {
const originalLocation = window.location.href;
beforeEach(() => {
+ mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
+ mockCiConfigData.mockResolvedValue(mockCiConfigQueryResponse);
mockLatestCommitShaQuery.mockResolvedValue(mockCommitShaResults);
+ mockGetTemplate.mockResolvedValue(mockCiTemplateQueryResponse);
setWindowLocation('?template=Android');
});
@@ -386,7 +398,9 @@ describe('Pipeline editor app component', () => {
});
it('renders the given template', async () => {
- await createComponentWithApollo();
+ await createComponentWithApollo({
+ stubs: { PipelineEditorHome, PipelineEditorTabs },
+ });
expect(mockGetTemplate).toHaveBeenCalledWith({
projectPath: mockProjectFullPath,
@@ -394,7 +408,40 @@ describe('Pipeline editor app component', () => {
});
expect(findEmptyState().exists()).toBe(false);
- expect(findTextEditor().exists()).toBe(true);
+ expect(findEditorHome().exists()).toBe(true);
+ });
+ });
+
+ describe('when add_new_config_file query param is present', () => {
+ const originalLocation = window.location.href;
+
+ beforeEach(() => {
+ setWindowLocation('?add_new_config_file=true');
+
+ mockCiConfigData.mockResolvedValue(mockCiConfigQueryResponse);
+ });
+
+ afterEach(() => {
+ setWindowLocation(originalLocation);
+ });
+
+ describe('when CI config file does not exist', () => {
+ beforeEach(async () => {
+ mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponseNoCiFile);
+ mockLatestCommitShaQuery.mockResolvedValue(mockEmptyCommitShaResults);
+ mockGetTemplate.mockResolvedValue(mockCiTemplateQueryResponse);
+
+ await createComponentWithApollo();
+
+ jest
+ .spyOn(wrapper.vm.$apollo.queries.commitSha, 'startPolling')
+ .mockImplementation(jest.fn());
+ });
+
+ it('skips empty state and shows editor home component', () => {
+ expect(findEmptyState().exists()).toBe(false);
+ expect(findEditorHome().exists()).toBe(true);
+ });
});
});
});
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
index 335049892ec..6f969546171 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
@@ -1,21 +1,25 @@
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
-
+import { GlModal } from '@gitlab/ui';
import CommitSection from '~/pipeline_editor/components/commit/commit_section.vue';
import PipelineEditorDrawer from '~/pipeline_editor/components/drawer/pipeline_editor_drawer.vue';
import PipelineEditorFileNav from '~/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue';
+import BranchSwitcher from '~/pipeline_editor/components/file_nav/branch_switcher.vue';
import PipelineEditorHeader from '~/pipeline_editor/components/header/pipeline_editor_header.vue';
import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
-import { MERGED_TAB, VISUALIZE_TAB } from '~/pipeline_editor/constants';
+import { MERGED_TAB, VISUALIZE_TAB, CREATE_TAB, LINT_TAB } from '~/pipeline_editor/constants';
import PipelineEditorHome from '~/pipeline_editor/pipeline_editor_home.vue';
import { mockLintResponse, mockCiYml } from './mock_data';
+jest.mock('~/lib/utils/common_utils');
+
describe('Pipeline editor home wrapper', () => {
let wrapper;
- const createComponent = ({ props = {}, glFeatures = {} } = {}) => {
+ const createComponent = ({ props = {}, glFeatures = {}, data = {}, stubs = {} } = {}) => {
wrapper = shallowMount(PipelineEditorHome, {
+ data: () => data,
propsData: {
ciConfigData: mockLintResponse,
ciFileContent: mockCiYml,
@@ -24,22 +28,26 @@ describe('Pipeline editor home wrapper', () => {
...props,
},
provide: {
+ projectFullPath: '',
+ totalBranches: 19,
glFeatures: {
...glFeatures,
},
},
+ stubs,
});
};
+ const findBranchSwitcher = () => wrapper.findComponent(BranchSwitcher);
const findCommitSection = () => wrapper.findComponent(CommitSection);
const findFileNav = () => wrapper.findComponent(PipelineEditorFileNav);
+ const findModal = () => wrapper.findComponent(GlModal);
const findPipelineEditorDrawer = () => wrapper.findComponent(PipelineEditorDrawer);
const findPipelineEditorHeader = () => wrapper.findComponent(PipelineEditorHeader);
const findPipelineEditorTabs = () => wrapper.findComponent(PipelineEditorTabs);
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('renders', () => {
@@ -68,29 +76,103 @@ describe('Pipeline editor home wrapper', () => {
});
});
+ describe('modal when switching branch', () => {
+ describe('when `showSwitchBranchModal` value is false', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('is not visible', () => {
+ expect(findModal().exists()).toBe(false);
+ });
+ });
+ describe('when `showSwitchBranchModal` value is true', () => {
+ beforeEach(() => {
+ createComponent({
+ data: { showSwitchBranchModal: true },
+ stubs: { PipelineEditorFileNav },
+ });
+ });
+
+ it('is visible', () => {
+ expect(findModal().exists()).toBe(true);
+ });
+
+ it('pass down `shouldLoadNewBranch` to the branch switcher when primary is selected', async () => {
+ expect(findBranchSwitcher().props('shouldLoadNewBranch')).toBe(false);
+
+ await findModal().vm.$emit('primary');
+
+ expect(findBranchSwitcher().props('shouldLoadNewBranch')).toBe(true);
+ });
+
+ it('closes the modal when secondary action is selected', async () => {
+ expect(findModal().exists()).toBe(true);
+
+ await findModal().vm.$emit('secondary');
+
+ expect(findModal().exists()).toBe(false);
+ });
+ });
+ });
+
describe('commit form toggle', () => {
beforeEach(() => {
createComponent();
});
- it('hides the commit form when in the merged tab', async () => {
- expect(findCommitSection().exists()).toBe(true);
+ it.each`
+ tab | shouldShow
+ ${MERGED_TAB} | ${false}
+ ${VISUALIZE_TAB} | ${false}
+ ${LINT_TAB} | ${false}
+ ${CREATE_TAB} | ${true}
+ `(
+ 'when the active tab is $tab the commit form is shown: $shouldShow',
+ async ({ tab, shouldShow }) => {
+ expect(findCommitSection().exists()).toBe(true);
- findPipelineEditorTabs().vm.$emit('set-current-tab', MERGED_TAB);
- await nextTick();
- expect(findCommitSection().exists()).toBe(false);
- });
+ findPipelineEditorTabs().vm.$emit('set-current-tab', tab);
+
+ await nextTick();
- it('shows the form again when leaving the merged tab', async () => {
+ expect(findCommitSection().exists()).toBe(shouldShow);
+ },
+ );
+
+ it('shows the commit form again when coming back to the create tab', async () => {
expect(findCommitSection().exists()).toBe(true);
findPipelineEditorTabs().vm.$emit('set-current-tab', MERGED_TAB);
await nextTick();
expect(findCommitSection().exists()).toBe(false);
- findPipelineEditorTabs().vm.$emit('set-current-tab', VISUALIZE_TAB);
+ findPipelineEditorTabs().vm.$emit('set-current-tab', CREATE_TAB);
await nextTick();
expect(findCommitSection().exists()).toBe(true);
});
});
+
+ describe('WalkthroughPopover events', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ describe('when "walkthrough-popover-cta-clicked" is emitted from pipeline editor tabs', () => {
+ it('passes down `scrollToCommitForm=true` to commit section', async () => {
+ expect(findCommitSection().props('scrollToCommitForm')).toBe(false);
+ await findPipelineEditorTabs().vm.$emit('walkthrough-popover-cta-clicked');
+ expect(findCommitSection().props('scrollToCommitForm')).toBe(true);
+ });
+ });
+
+ describe('when "scrolled-to-commit-form" is emitted from commit section', () => {
+ it('passes down `scrollToCommitForm=false` to commit section', async () => {
+ await findPipelineEditorTabs().vm.$emit('walkthrough-popover-cta-clicked');
+ expect(findCommitSection().props('scrollToCommitForm')).toBe(true);
+ await findCommitSection().vm.$emit('scrolled-to-commit-form');
+ expect(findCommitSection().props('scrollToCommitForm')).toBe(false);
+ });
+ });
+ });
});
diff --git a/spec/frontend/pipelines/empty_state_spec.js b/spec/frontend/pipelines/empty_state_spec.js
index 1af3065477d..31b74a06efd 100644
--- a/spec/frontend/pipelines/empty_state_spec.js
+++ b/spec/frontend/pipelines/empty_state_spec.js
@@ -35,7 +35,7 @@ describe('Pipelines Empty State', () => {
});
it('should render the CI/CD templates', () => {
- expect(pipelinesCiTemplates()).toExist();
+ expect(pipelinesCiTemplates().exists()).toBe(true);
});
});
diff --git a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
index 2e8979f2b9d..db4de6deeb7 100644
--- a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
@@ -327,7 +327,7 @@ describe('Pipeline graph wrapper', () => {
expect(getLinksLayer().exists()).toBe(true);
expect(getLinksLayer().props('showLinks')).toBe(false);
expect(getViewSelector().props('type')).toBe(LAYER_VIEW);
- await getDependenciesToggle().trigger('click');
+ await getDependenciesToggle().vm.$emit('change', true);
jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
expect(wrapper.findComponent(LinksLayer).props('showLinks')).toBe(true);
diff --git a/spec/frontend/pipelines/graph/graph_view_selector_spec.js b/spec/frontend/pipelines/graph/graph_view_selector_spec.js
index 5b2a29de443..f4faa25545b 100644
--- a/spec/frontend/pipelines/graph/graph_view_selector_spec.js
+++ b/spec/frontend/pipelines/graph/graph_view_selector_spec.js
@@ -111,7 +111,7 @@ describe('the graph view selector component', () => {
expect(wrapper.emitted().updateShowLinksState).toBeUndefined();
expect(findToggleLoader().exists()).toBe(false);
- await findDependenciesToggle().trigger('click');
+ await findDependenciesToggle().vm.$emit('change', true);
/*
Loading happens before the event is emitted or timers are run.
Then we run the timer because the event is emitted in setInterval
diff --git a/spec/frontend/pipelines/pipelines_artifacts_spec.js b/spec/frontend/pipelines/pipelines_artifacts_spec.js
index f33c66dedf3..2d876841e06 100644
--- a/spec/frontend/pipelines/pipelines_artifacts_spec.js
+++ b/spec/frontend/pipelines/pipelines_artifacts_spec.js
@@ -1,15 +1,9 @@
-import { GlAlert, GlDropdown, GlDropdownItem, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import MockAdapter from 'axios-mock-adapter';
-import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
-import PipelineArtifacts, {
- i18n,
-} from '~/pipelines/components/pipelines_list/pipelines_artifacts.vue';
+import PipelineArtifacts from '~/pipelines/components/pipelines_list/pipelines_artifacts.vue';
describe('Pipelines Artifacts dropdown', () => {
let wrapper;
- let mockAxios;
const artifacts = [
{
@@ -21,23 +15,13 @@ describe('Pipelines Artifacts dropdown', () => {
path: '/download/path-two',
},
];
- const artifactsEndpointPlaceholder = ':pipeline_artifacts_id';
- const artifactsEndpoint = `endpoint/${artifactsEndpointPlaceholder}/artifacts.json`;
const pipelineId = 108;
- const createComponent = ({ mockData = {} } = {}) => {
+ const createComponent = ({ mockArtifacts = artifacts } = {}) => {
wrapper = shallowMount(PipelineArtifacts, {
- provide: {
- artifactsEndpoint,
- artifactsEndpointPlaceholder,
- },
propsData: {
pipelineId,
- },
- data() {
- return {
- ...mockData,
- };
+ artifacts: mockArtifacts,
},
stubs: {
GlSprintf,
@@ -45,80 +29,33 @@ describe('Pipelines Artifacts dropdown', () => {
});
};
- const findAlert = () => wrapper.findComponent(GlAlert);
const findDropdown = () => wrapper.findComponent(GlDropdown);
- const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findFirstGlDropdownItem = () => wrapper.find(GlDropdownItem);
const findAllGlDropdownItems = () => wrapper.find(GlDropdown).findAll(GlDropdownItem);
- beforeEach(() => {
- mockAxios = new MockAdapter(axios);
- });
-
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
- it('should render the dropdown', () => {
- createComponent();
-
- expect(findDropdown().exists()).toBe(true);
- });
-
- it('should fetch artifacts on dropdown click', async () => {
- const endpoint = artifactsEndpoint.replace(artifactsEndpointPlaceholder, pipelineId);
- mockAxios.onGet(endpoint).replyOnce(200, { artifacts });
- createComponent();
- findDropdown().vm.$emit('show');
- await waitForPromises();
-
- expect(mockAxios.history.get).toHaveLength(1);
- expect(wrapper.vm.artifacts).toEqual(artifacts);
- });
-
it('should render a dropdown with all the provided artifacts', () => {
- createComponent({ mockData: { artifacts } });
+ createComponent();
expect(findAllGlDropdownItems()).toHaveLength(artifacts.length);
});
it('should render a link with the provided path', () => {
- createComponent({ mockData: { artifacts } });
+ createComponent();
expect(findFirstGlDropdownItem().attributes('href')).toBe(artifacts[0].path);
expect(findFirstGlDropdownItem().text()).toBe(artifacts[0].name);
});
- describe('with a failing request', () => {
- it('should render an error message', async () => {
- const endpoint = artifactsEndpoint.replace(artifactsEndpointPlaceholder, pipelineId);
- mockAxios.onGet(endpoint).replyOnce(500);
- createComponent();
- findDropdown().vm.$emit('show');
- await waitForPromises();
-
- const error = findAlert();
- expect(error.exists()).toBe(true);
- expect(error.text()).toBe(i18n.artifactsFetchErrorMessage);
- });
- });
-
- describe('with no artifacts received', () => {
- it('should render empty alert message', () => {
- createComponent({ mockData: { artifacts: [] } });
-
- const emptyAlert = findAlert();
- expect(emptyAlert.exists()).toBe(true);
- expect(emptyAlert.text()).toBe(i18n.noArtifacts);
- });
- });
-
- describe('when artifacts are loading', () => {
- it('should show loading icon', () => {
- createComponent({ mockData: { isLoading: true } });
+ describe('with no artifacts', () => {
+ it('should not render the dropdown', () => {
+ createComponent({ mockArtifacts: [] });
- expect(findLoadingIcon().exists()).toBe(true);
+ expect(findDropdown().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js
index 2875498bb52..c024730570c 100644
--- a/spec/frontend/pipelines/pipelines_spec.js
+++ b/spec/frontend/pipelines/pipelines_spec.js
@@ -554,7 +554,7 @@ describe('Pipelines', () => {
});
it('renders the CI/CD templates', () => {
- expect(wrapper.find(PipelinesCiTemplates)).toExist();
+ expect(wrapper.findComponent(PipelinesCiTemplates).exists()).toBe(true);
});
describe('when the code_quality_walkthrough experiment is active', () => {
@@ -568,7 +568,7 @@ describe('Pipelines', () => {
});
it('renders the CI/CD templates', () => {
- expect(wrapper.find(PipelinesCiTemplates)).toExist();
+ expect(wrapper.findComponent(PipelinesCiTemplates).exists()).toBe(true);
});
});
@@ -597,7 +597,7 @@ describe('Pipelines', () => {
});
it('renders the CI/CD templates', () => {
- expect(wrapper.find(PipelinesCiTemplates)).toExist();
+ expect(wrapper.findComponent(PipelinesCiTemplates).exists()).toBe(true);
});
});
diff --git a/spec/frontend/pipelines/pipelines_table_spec.js b/spec/frontend/pipelines/pipelines_table_spec.js
index fb019b463b1..6fdbe907aed 100644
--- a/spec/frontend/pipelines/pipelines_table_spec.js
+++ b/spec/frontend/pipelines/pipelines_table_spec.js
@@ -1,5 +1,5 @@
import '~/commons';
-import { GlTable } from '@gitlab/ui';
+import { GlTableLite } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import fixture from 'test_fixtures/pipelines/pipelines.json';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
@@ -44,7 +44,7 @@ describe('Pipelines Table', () => {
);
};
- const findGlTable = () => wrapper.findComponent(GlTable);
+ const findGlTableLite = () => wrapper.findComponent(GlTableLite);
const findStatusBadge = () => wrapper.findComponent(CiBadge);
const findPipelineInfo = () => wrapper.findComponent(PipelineUrl);
const findTriggerer = () => wrapper.findComponent(PipelineTriggerer);
@@ -77,7 +77,7 @@ describe('Pipelines Table', () => {
});
it('displays table', () => {
- expect(findGlTable().exists()).toBe(true);
+ expect(findGlTableLite().exists()).toBe(true);
});
it('should render table head with correct columns', () => {
diff --git a/spec/frontend/projects/commit/components/form_modal_spec.js b/spec/frontend/projects/commit/components/form_modal_spec.js
index 0c8089430d0..93e2ae13628 100644
--- a/spec/frontend/projects/commit/components/form_modal_spec.js
+++ b/spec/frontend/projects/commit/components/form_modal_spec.js
@@ -3,6 +3,7 @@ import { within } from '@testing-library/dom';
import { shallowMount, mount, createWrapper } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import api from '~/api';
import axios from '~/lib/utils/axios_utils';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import BranchesDropdown from '~/projects/commit/components/branches_dropdown.vue';
@@ -12,6 +13,8 @@ import eventHub from '~/projects/commit/event_hub';
import createStore from '~/projects/commit/store';
import mockData from '../mock_data';
+jest.mock('~/api');
+
describe('CommitFormModal', () => {
let wrapper;
let store;
@@ -167,4 +170,16 @@ describe('CommitFormModal', () => {
expect(findTargetProject().attributes('value')).toBe('_changed_project_value_');
});
});
+
+ it('action primary button triggers Redis HLL tracking api call', async () => {
+ createComponent(mount, {}, {}, { primaryActionEventName: 'test_event' });
+
+ await wrapper.vm.$nextTick();
+
+ jest.spyOn(findForm().element, 'submit');
+
+ getByText(mockData.modalPropsData.i18n.actionPrimaryText).trigger('click');
+
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith('test_event');
+ });
});
diff --git a/spec/frontend/projects/commits/components/author_select_spec.js b/spec/frontend/projects/commits/components/author_select_spec.js
index 9a8f7ff7582..60d36597fda 100644
--- a/spec/frontend/projects/commits/components/author_select_spec.js
+++ b/spec/frontend/projects/commits/components/author_select_spec.js
@@ -115,7 +115,7 @@ describe('Author Select', () => {
});
it('does not have popover text by default', () => {
- expect(wrapper.attributes('title')).not.toExist();
+ expect(wrapper.attributes('title')).toBeUndefined();
});
});
diff --git a/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap b/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
index c255fcce321..e1e1aac09aa 100644
--- a/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
+++ b/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
@@ -52,9 +52,44 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
title="You are about to permanently delete this project"
variant="danger"
>
- <gl-sprintf-stub
- message="Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
- />
+ <p>
+ This project is
+ <strong>
+ NOT
+ </strong>
+ a fork, and has the following:
+ </p>
+
+ <ul>
+ <li>
+ 1 issue
+ </li>
+
+ <li>
+ 2 merge requests
+ </li>
+
+ <li>
+ 3 forks
+ </li>
+
+ <li>
+ 4 stars
+ </li>
+ </ul>
+ After a project is permanently deleted, it
+ <strong>
+ cannot be recovered
+ </strong>
+ . Permanently deleting this project will
+ <strong>
+ immediately delete
+ </strong>
+ its repositories and
+ <strong>
+ all related resources
+ </strong>
+ , including issues, merge requests etc.
</gl-alert-stub>
<p
diff --git a/spec/frontend/projects/components/project_delete_button_spec.js b/spec/frontend/projects/components/project_delete_button_spec.js
index 444e465ebaa..bb6021fadda 100644
--- a/spec/frontend/projects/components/project_delete_button_spec.js
+++ b/spec/frontend/projects/components/project_delete_button_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { GlSprintf } from '@gitlab/ui';
import ProjectDeleteButton from '~/projects/components/project_delete_button.vue';
import SharedDeleteButton from '~/projects/components/shared/delete_button.vue';
@@ -12,6 +13,11 @@ describe('Project remove modal', () => {
const defaultProps = {
confirmPhrase: 'foo',
formPath: 'some/path',
+ isFork: false,
+ issuesCount: 1,
+ mergeRequestsCount: 2,
+ forksCount: 3,
+ starsCount: 4,
};
const createComponent = (props = {}) => {
@@ -21,6 +27,7 @@ describe('Project remove modal', () => {
...props,
},
stubs: {
+ GlSprintf,
SharedDeleteButton,
},
});
@@ -41,7 +48,10 @@ describe('Project remove modal', () => {
});
it('passes confirmPhrase and formPath props to the shared delete button', () => {
- expect(findSharedDeleteButton().props()).toEqual(defaultProps);
+ expect(findSharedDeleteButton().props()).toEqual({
+ confirmPhrase: defaultProps.confirmPhrase,
+ formPath: defaultProps.formPath,
+ });
});
});
});
diff --git a/spec/frontend/projects/details/upload_button_spec.js b/spec/frontend/projects/details/upload_button_spec.js
index ebb2b499ead..d7308963088 100644
--- a/spec/frontend/projects/details/upload_button_spec.js
+++ b/spec/frontend/projects/details/upload_button_spec.js
@@ -1,11 +1,8 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import UploadButton from '~/projects/details/upload_button.vue';
-import { trackFileUploadEvent } from '~/projects/upload_file_experiment_tracking';
import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
-jest.mock('~/projects/upload_file_experiment_tracking');
-
const MODAL_ID = 'details-modal-upload-blob';
describe('UploadButton', () => {
@@ -50,10 +47,6 @@ describe('UploadButton', () => {
wrapper.find(GlButton).vm.$emit('click');
});
- it('tracks the click_upload_modal_trigger event', () => {
- expect(trackFileUploadEvent).toHaveBeenCalledWith('click_upload_modal_trigger');
- });
-
it('opens the modal', () => {
expect(glModalDirective).toHaveBeenCalledWith(MODAL_ID);
});
diff --git a/spec/frontend/projects/new/components/new_project_url_select_spec.js b/spec/frontend/projects/new/components/new_project_url_select_spec.js
index aa16b71172b..b3f177a1f12 100644
--- a/spec/frontend/projects/new/components/new_project_url_select_spec.js
+++ b/spec/frontend/projects/new/components/new_project_url_select_spec.js
@@ -24,14 +24,23 @@ describe('NewProjectUrlSelect component', () => {
{
id: 'gid://gitlab/Group/26',
fullPath: 'flightjs',
+ name: 'Flight JS',
+ visibility: 'public',
+ webUrl: 'http://127.0.0.1:3000/flightjs',
},
{
id: 'gid://gitlab/Group/28',
fullPath: 'h5bp',
+ name: 'H5BP',
+ visibility: 'public',
+ webUrl: 'http://127.0.0.1:3000/h5bp',
},
{
id: 'gid://gitlab/Group/30',
fullPath: 'h5bp/subgroup',
+ name: 'H5BP Subgroup',
+ visibility: 'private',
+ webUrl: 'http://127.0.0.1:3000/h5bp/subgroup',
},
],
},
@@ -79,6 +88,10 @@ describe('NewProjectUrlSelect component', () => {
const findDropdown = () => wrapper.findComponent(GlDropdown);
const findInput = () => wrapper.findComponent(GlSearchBoxByType);
const findHiddenInput = () => wrapper.find('input');
+ const clickDropdownItem = async () => {
+ wrapper.findComponent(GlDropdownItem).vm.$emit('click');
+ await wrapper.vm.$nextTick();
+ };
afterEach(() => {
wrapper.destroy();
@@ -127,7 +140,6 @@ describe('NewProjectUrlSelect component', () => {
it('focuses on the input when the dropdown is opened', async () => {
wrapper = mountComponent({ mountFn: mount });
-
jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
@@ -140,7 +152,6 @@ describe('NewProjectUrlSelect component', () => {
it('renders expected dropdown items', async () => {
wrapper = mountComponent({ mountFn: mount });
-
jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
@@ -160,7 +171,6 @@ describe('NewProjectUrlSelect component', () => {
beforeEach(async () => {
wrapper = mountComponent({ mountFn: mount });
-
jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
@@ -195,23 +205,38 @@ describe('NewProjectUrlSelect component', () => {
};
wrapper = mountComponent({ search: 'no matches', queryResponse, mountFn: mount });
-
jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
expect(wrapper.find('li').text()).toBe('No matches found');
});
- it('updates hidden input with selected namespace', async () => {
+ it('emits `update-visibility` event to update the visibility radio options', async () => {
wrapper = mountComponent();
-
jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
- wrapper.findComponent(GlDropdownItem).vm.$emit('click');
+ const spy = jest.spyOn(eventHub, '$emit');
+ await clickDropdownItem();
+
+ const namespace = data.currentUser.groups.nodes[0];
+
+ expect(spy).toHaveBeenCalledWith('update-visibility', {
+ name: namespace.name,
+ visibility: namespace.visibility,
+ showPath: namespace.webUrl,
+ editPath: `${namespace.webUrl}/-/edit`,
+ });
+ });
+
+ it('updates hidden input with selected namespace', async () => {
+ wrapper = mountComponent();
+ jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
+ await clickDropdownItem();
+
expect(findHiddenInput().attributes()).toMatchObject({
name: 'project[namespace_id]',
value: getIdFromGraphQLId(data.currentUser.groups.nodes[0].id).toString(),
diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js
index 987a215eb4c..b4067f6a72b 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js
@@ -11,6 +11,7 @@ jest.mock('~/lib/utils/url_utility');
const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} };
const LeadTimeChartsStub = { name: 'LeadTimeCharts', render: () => {} };
+const ProjectQualitySummaryStub = { name: 'ProjectQualitySummary', render: () => {} };
describe('ProjectsPipelinesChartsApp', () => {
let wrapper;
@@ -23,10 +24,12 @@ describe('ProjectsPipelinesChartsApp', () => {
{
provide: {
shouldRenderDoraCharts: true,
+ shouldRenderQualitySummary: true,
},
stubs: {
DeploymentFrequencyCharts: DeploymentFrequencyChartsStub,
LeadTimeCharts: LeadTimeChartsStub,
+ ProjectQualitySummary: ProjectQualitySummaryStub,
},
},
mountOptions,
@@ -44,6 +47,7 @@ describe('ProjectsPipelinesChartsApp', () => {
const findLeadTimeCharts = () => wrapper.find(LeadTimeChartsStub);
const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub);
const findPipelineCharts = () => wrapper.find(PipelineCharts);
+ const findProjectQualitySummary = () => wrapper.find(ProjectQualitySummaryStub);
describe('when all charts are available', () => {
beforeEach(() => {
@@ -70,6 +74,10 @@ describe('ProjectsPipelinesChartsApp', () => {
expect(findLeadTimeCharts().exists()).toBe(true);
});
+ it('renders the project quality summary', () => {
+ expect(findProjectQualitySummary().exists()).toBe(true);
+ });
+
it('sets the tab and url when a tab is clicked', async () => {
let chartsPath;
setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`);
@@ -163,9 +171,11 @@ describe('ProjectsPipelinesChartsApp', () => {
});
});
- describe('when the dora charts are not available', () => {
+ describe('when the dora charts are not available and project quality summary is not available', () => {
beforeEach(() => {
- createComponent({ provide: { shouldRenderDoraCharts: false } });
+ createComponent({
+ provide: { shouldRenderDoraCharts: false, shouldRenderQualitySummary: false },
+ });
});
it('does not render tabs', () => {
@@ -176,4 +186,14 @@ describe('ProjectsPipelinesChartsApp', () => {
expect(findPipelineCharts().exists()).toBe(true);
});
});
+
+ describe('when the project quality summary is not available', () => {
+ beforeEach(() => {
+ createComponent({ provide: { shouldRenderQualitySummary: false } });
+ });
+
+ it('does not render the tab', () => {
+ expect(findProjectQualitySummary().exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/projects/projects_filterable_list_spec.js b/spec/frontend/projects/projects_filterable_list_spec.js
index d4dbf85b5ca..a41e8b7bc09 100644
--- a/spec/frontend/projects/projects_filterable_list_spec.js
+++ b/spec/frontend/projects/projects_filterable_list_spec.js
@@ -1,5 +1,4 @@
-// eslint-disable-next-line import/no-deprecated
-import { getJSONFixture, setHTMLFixture } from 'helpers/fixtures';
+import { setHTMLFixture } from 'helpers/fixtures';
import ProjectsFilterableList from '~/projects/projects_filterable_list';
describe('ProjectsFilterableList', () => {
@@ -15,8 +14,6 @@ describe('ProjectsFilterableList', () => {
</div>
<div class="js-projects-list-holder"></div>
`);
- // eslint-disable-next-line import/no-deprecated
- getJSONFixture('static/projects.json');
form = document.querySelector('form#project-filter-form');
filter = document.querySelector('.js-projects-list-filter');
holder = document.querySelector('.js-projects-list-holder');
diff --git a/spec/frontend/projects/settings/topics/components/topics_token_selector_spec.js b/spec/frontend/projects/settings/topics/components/topics_token_selector_spec.js
new file mode 100644
index 00000000000..dbea94cbd53
--- /dev/null
+++ b/spec/frontend/projects/settings/topics/components/topics_token_selector_spec.js
@@ -0,0 +1,98 @@
+import { GlTokenSelector, GlToken } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import TopicsTokenSelector from '~/projects/settings/topics/components/topics_token_selector.vue';
+
+const mockTopics = [
+ { id: 1, name: 'topic1', avatarUrl: 'avatar.com/topic1.png' },
+ { id: 2, name: 'GitLab', avatarUrl: 'avatar.com/GitLab.png' },
+];
+
+describe('TopicsTokenSelector', () => {
+ let wrapper;
+ let div;
+ let input;
+
+ const createComponent = (selected) => {
+ wrapper = mount(TopicsTokenSelector, {
+ attachTo: div,
+ propsData: {
+ selected,
+ },
+ data() {
+ return {
+ topics: mockTopics,
+ };
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ topics: { loading: false },
+ },
+ },
+ },
+ });
+ };
+
+ const findTokenSelector = () => wrapper.findComponent(GlTokenSelector);
+
+ const findTokenSelectorInput = () => findTokenSelector().find('input[type="text"]');
+
+ const setTokenSelectorInputValue = (value) => {
+ const tokenSelectorInput = findTokenSelectorInput();
+
+ tokenSelectorInput.element.value = value;
+ tokenSelectorInput.trigger('input');
+
+ return nextTick();
+ };
+
+ const tokenSelectorTriggerEnter = (event) => {
+ const tokenSelectorInput = findTokenSelectorInput();
+ tokenSelectorInput.trigger('keydown.enter', event);
+ };
+
+ beforeEach(() => {
+ div = document.createElement('div');
+ input = document.createElement('input');
+ input.setAttribute('type', 'text');
+ input.id = 'project_topic_list_field';
+ document.body.appendChild(div);
+ document.body.appendChild(input);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ div.remove();
+ input.remove();
+ });
+
+ describe('when component is mounted', () => {
+ it('parses selected into tokens', async () => {
+ const selected = [
+ { id: 11, name: 'topic1' },
+ { id: 12, name: 'topic2' },
+ { id: 13, name: 'topic3' },
+ ];
+ createComponent(selected);
+ await nextTick();
+
+ wrapper.findAllComponents(GlToken).wrappers.forEach((tokenWrapper, index) => {
+ expect(tokenWrapper.text()).toBe(selected[index].name);
+ });
+ });
+ });
+
+ describe('when enter key is pressed', () => {
+ it('does not submit the form if token selector text input has a value', async () => {
+ createComponent();
+
+ await setTokenSelectorInputValue('topic');
+
+ const event = { preventDefault: jest.fn() };
+ tokenSelectorTriggerEnter(event);
+
+ expect(event.preventDefault).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/projects/settings_service_desk/components/mock_data.js b/spec/frontend/projects/settings_service_desk/components/mock_data.js
new file mode 100644
index 00000000000..934778ff601
--- /dev/null
+++ b/spec/frontend/projects/settings_service_desk/components/mock_data.js
@@ -0,0 +1,8 @@
+export const TEMPLATES = [
+ 'Project #1',
+ [
+ { name: 'Bug', project_id: 1 },
+ { name: 'Documentation', project_id: 1 },
+ { name: 'Security release', project_id: 1 },
+ ],
+];
diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js
index 8acf2376860..62224612387 100644
--- a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js
+++ b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js
@@ -21,6 +21,7 @@ describe('ServiceDeskRoot', () => {
outgoingName: 'GitLab Support Bot',
projectKey: 'key',
selectedTemplate: 'Bug',
+ selectedFileTemplateProjectId: 42,
templates: ['Bug', 'Documentation'],
};
@@ -52,6 +53,7 @@ describe('ServiceDeskRoot', () => {
initialOutgoingName: provideData.outgoingName,
initialProjectKey: provideData.projectKey,
initialSelectedTemplate: provideData.selectedTemplate,
+ initialSelectedFileTemplateProjectId: provideData.selectedFileTemplateProjectId,
isEnabled: provideData.initialIsEnabled,
isTemplateSaving: false,
templates: provideData.templates,
diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
index eacf858f22c..0fd3e7446da 100644
--- a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
+++ b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
@@ -1,4 +1,4 @@
-import { GlButton, GlFormSelect, GlLoadingIcon, GlToggle } from '@gitlab/ui';
+import { GlButton, GlDropdown, GlLoadingIcon, GlToggle } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
@@ -13,7 +13,7 @@ describe('ServiceDeskSetting', () => {
const findIncomingEmail = () => wrapper.findByTestId('incoming-email');
const findIncomingEmailLabel = () => wrapper.findByTestId('incoming-email-describer');
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findTemplateDropdown = () => wrapper.find(GlFormSelect);
+ const findTemplateDropdown = () => wrapper.find(GlDropdown);
const findToggle = () => wrapper.find(GlToggle);
const createComponent = ({ props = {}, mountFunction = shallowMount } = {}) =>
@@ -128,6 +128,23 @@ describe('ServiceDeskSetting', () => {
expect(input.exists()).toBe(true);
expect(input.attributes('disabled')).toBeUndefined();
});
+
+ it('shows error when value contains uppercase or special chars', async () => {
+ wrapper = createComponent({
+ props: { customEmailEnabled: true },
+ mountFunction: mount,
+ });
+
+ const input = wrapper.findByTestId('project-suffix');
+
+ input.setValue('abc_A.');
+ input.trigger('blur');
+
+ await wrapper.vm.$nextTick();
+
+ const errorText = wrapper.find('.text-danger');
+ expect(errorText.exists()).toBe(true);
+ });
});
describe('customEmail is the same as incomingEmail', () => {
@@ -144,63 +161,6 @@ describe('ServiceDeskSetting', () => {
});
});
});
-
- describe('templates dropdown', () => {
- it('renders a dropdown to choose a template', () => {
- wrapper = createComponent();
-
- expect(findTemplateDropdown().exists()).toBe(true);
- });
-
- it('renders a dropdown with a default value of ""', () => {
- wrapper = createComponent({ mountFunction: mount });
-
- expect(findTemplateDropdown().element.value).toEqual('');
- });
-
- it('renders a dropdown with a value of "Bug" when it is the initial value', () => {
- const templates = ['Bug', 'Documentation', 'Security release'];
-
- wrapper = createComponent({
- props: { initialSelectedTemplate: 'Bug', templates },
- mountFunction: mount,
- });
-
- expect(findTemplateDropdown().element.value).toEqual('Bug');
- });
-
- it('renders a dropdown with no options when the project has no templates', () => {
- wrapper = createComponent({
- props: { templates: [] },
- mountFunction: mount,
- });
-
- // The dropdown by default has one empty option
- expect(findTemplateDropdown().element.children).toHaveLength(1);
- });
-
- it('renders a dropdown with options when the project has templates', () => {
- const templates = ['Bug', 'Documentation', 'Security release'];
-
- wrapper = createComponent({
- props: { templates },
- mountFunction: mount,
- });
-
- // An empty-named template is prepended so the user can select no template
- const expectedTemplates = [''].concat(templates);
-
- const dropdown = findTemplateDropdown();
- const dropdownList = Array.from(dropdown.element.children).map(
- (option) => option.innerText,
- );
-
- expect(dropdown.element.children).toHaveLength(expectedTemplates.length);
- expect(dropdownList.includes('Bug')).toEqual(true);
- expect(dropdownList.includes('Documentation')).toEqual(true);
- expect(dropdownList.includes('Security release')).toEqual(true);
- });
- });
});
describe('save button', () => {
@@ -214,6 +174,7 @@ describe('ServiceDeskSetting', () => {
wrapper = createComponent({
props: {
initialSelectedTemplate: 'Bug',
+ initialSelectedFileTemplateProjectId: 42,
initialOutgoingName: 'GitLab Support Bot',
initialProjectKey: 'key',
},
@@ -225,6 +186,7 @@ describe('ServiceDeskSetting', () => {
const payload = {
selectedTemplate: 'Bug',
+ fileTemplateProjectId: 42,
outgoingName: 'GitLab Support Bot',
projectKey: 'key',
};
diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_template_dropdown_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_template_dropdown_spec.js
new file mode 100644
index 00000000000..cdb355f5a9b
--- /dev/null
+++ b/spec/frontend/projects/settings_service_desk/components/service_desk_template_dropdown_spec.js
@@ -0,0 +1,80 @@
+import { GlDropdown, GlDropdownSectionHeader, GlDropdownItem } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import ServiceDeskTemplateDropdown from '~/projects/settings_service_desk/components/service_desk_setting.vue';
+import { TEMPLATES } from './mock_data';
+
+describe('ServiceDeskTemplateDropdown', () => {
+ let wrapper;
+
+ const findTemplateDropdown = () => wrapper.find(GlDropdown);
+
+ const createComponent = ({ props = {} } = {}) =>
+ extendedWrapper(
+ mount(ServiceDeskTemplateDropdown, {
+ propsData: {
+ isEnabled: true,
+ ...props,
+ },
+ }),
+ );
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ describe('templates dropdown', () => {
+ it('renders a dropdown to choose a template', () => {
+ wrapper = createComponent();
+
+ expect(findTemplateDropdown().exists()).toBe(true);
+ });
+
+ it('renders a dropdown with a default value of "Choose a template"', () => {
+ wrapper = createComponent();
+
+ expect(findTemplateDropdown().props('text')).toEqual('Choose a template');
+ });
+
+ it('renders a dropdown with a value of "Bug" when it is the initial value', () => {
+ const templates = TEMPLATES;
+
+ wrapper = createComponent({
+ props: { initialSelectedTemplate: 'Bug', initialSelectedTemplateProjectId: 1, templates },
+ });
+
+ expect(findTemplateDropdown().props('text')).toEqual('Bug');
+ });
+
+ it('renders a dropdown with header items', () => {
+ wrapper = createComponent({
+ props: { templates: TEMPLATES },
+ });
+
+ const headerItems = wrapper.findAll(GlDropdownSectionHeader);
+
+ expect(headerItems).toHaveLength(1);
+ expect(headerItems.at(0).text()).toBe(TEMPLATES[0]);
+ });
+
+ it('renders a dropdown with options when the project has templates', () => {
+ const templates = TEMPLATES;
+
+ wrapper = createComponent({
+ props: { templates },
+ });
+
+ const expectedTemplates = templates[1];
+
+ const items = wrapper.findAll(GlDropdownItem);
+ const dropdownList = expectedTemplates.map((_, index) => items.at(index).text());
+
+ expect(items).toHaveLength(expectedTemplates.length);
+ expect(dropdownList.includes('Bug')).toEqual(true);
+ expect(dropdownList.includes('Documentation')).toEqual(true);
+ expect(dropdownList.includes('Security release')).toEqual(true);
+ });
+ });
+});
diff --git a/spec/frontend/projects/storage_counter/components/storage_table_spec.js b/spec/frontend/projects/storage_counter/components/storage_table_spec.js
index 14298318fff..c9e56d8f033 100644
--- a/spec/frontend/projects/storage_counter/components/storage_table_spec.js
+++ b/spec/frontend/projects/storage_counter/components/storage_table_spec.js
@@ -1,4 +1,4 @@
-import { GlTable } from '@gitlab/ui';
+import { GlTableLite } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import StorageTable from '~/projects/storage_counter/components/storage_table.vue';
@@ -22,7 +22,7 @@ describe('StorageTable', () => {
);
};
- const findTable = () => wrapper.findComponent(GlTable);
+ const findTable = () => wrapper.findComponent(GlTableLite);
beforeEach(() => {
createComponent();
@@ -37,6 +37,7 @@ describe('StorageTable', () => {
({ storageType: { id, name, description } }) => {
expect(wrapper.findByTestId(`${id}-name`).text()).toBe(name);
expect(wrapper.findByTestId(`${id}-description`).text()).toBe(description);
+ expect(wrapper.findByTestId(`${id}-icon`).props('name')).toBe(id);
expect(wrapper.findByTestId(`${id}-help-link`).attributes('href')).toBe(
defaultProvideValues.helpLinks[id.replace(`Size`, `HelpPagePath`)]
.replace(`Size`, ``)
diff --git a/spec/frontend/projects/storage_counter/components/storage_type_icon_spec.js b/spec/frontend/projects/storage_counter/components/storage_type_icon_spec.js
new file mode 100644
index 00000000000..01efd6f14bd
--- /dev/null
+++ b/spec/frontend/projects/storage_counter/components/storage_type_icon_spec.js
@@ -0,0 +1,41 @@
+import { mount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
+import StorageTypeIcon from '~/projects/storage_counter/components/storage_type_icon.vue';
+
+describe('StorageTypeIcon', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = mount(StorageTypeIcon, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ const findGlIcon = () => wrapper.findComponent(GlIcon);
+
+ describe('rendering icon', () => {
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it.each`
+ expected | provided
+ ${'doc-image'} | ${'lfsObjectsSize'}
+ ${'snippet'} | ${'snippetsSize'}
+ ${'infrastructure-registry'} | ${'repositorySize'}
+ ${'package'} | ${'packagesSize'}
+ ${'upload'} | ${'uploadsSize'}
+ ${'disk'} | ${'wikiSize'}
+ ${'disk'} | ${'anything-else'}
+ `(
+ 'renders icon with name of $expected when name prop is $provided',
+ ({ expected, provided }) => {
+ createComponent({ name: provided });
+
+ expect(findGlIcon().props('name')).toBe(expected);
+ },
+ );
+ });
+});
diff --git a/spec/frontend/projects/storage_counter/mock_data.js b/spec/frontend/projects/storage_counter/mock_data.js
index b9fa68b3ec7..6b3e23ac386 100644
--- a/spec/frontend/projects/storage_counter/mock_data.js
+++ b/spec/frontend/projects/storage_counter/mock_data.js
@@ -1,23 +1,6 @@
-export const mockGetProjectStorageCountGraphQLResponse = {
- data: {
- project: {
- id: 'gid://gitlab/Project/20',
- statistics: {
- buildArtifactsSize: 400000.0,
- pipelineArtifactsSize: 25000.0,
- lfsObjectsSize: 4800000.0,
- packagesSize: 3800000.0,
- repositorySize: 3900000.0,
- snippetsSize: 1200000.0,
- storageSize: 15300000.0,
- uploadsSize: 900000.0,
- wikiSize: 300000.0,
- __typename: 'ProjectStatistics',
- },
- __typename: 'Project',
- },
- },
-};
+import mockGetProjectStorageCountGraphQLResponse from 'test_fixtures/graphql/projects/storage_counter/project_storage.query.graphql.json';
+
+export { mockGetProjectStorageCountGraphQLResponse };
export const mockEmptyResponse = { data: { project: null } };
@@ -37,7 +20,7 @@ export const defaultProvideValues = {
export const projectData = {
storage: {
- totalUsage: '14.6 MiB',
+ totalUsage: '13.8 MiB',
storageTypes: [
{
storageType: {
@@ -45,7 +28,7 @@ export const projectData = {
name: 'Artifacts',
description: 'Pipeline artifacts and job artifacts, created with CI/CD.',
warningMessage:
- 'There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}.',
+ 'Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}.',
helpPath: '/build-artifacts',
},
value: 400000,
@@ -53,7 +36,7 @@ export const projectData = {
{
storageType: {
id: 'lfsObjectsSize',
- name: 'LFS Storage',
+ name: 'LFS storage',
description: 'Audio samples, videos, datasets, and graphics.',
helpPath: '/lsf-objects',
},
@@ -72,7 +55,7 @@ export const projectData = {
storageType: {
id: 'repositorySize',
name: 'Repository',
- description: 'Git repository, managed by the Gitaly service.',
+ description: 'Git repository.',
helpPath: '/repository',
},
value: 3900000,
@@ -84,7 +67,7 @@ export const projectData = {
description: 'Shared bits of code and text.',
helpPath: '/snippets',
},
- value: 1200000,
+ value: 0,
},
{
storageType: {
diff --git a/spec/frontend/projects/storage_counter/utils_spec.js b/spec/frontend/projects/storage_counter/utils_spec.js
index 57c755266a0..fb91975a3cf 100644
--- a/spec/frontend/projects/storage_counter/utils_spec.js
+++ b/spec/frontend/projects/storage_counter/utils_spec.js
@@ -14,4 +14,21 @@ describe('parseGetProjectStorageResults', () => {
),
).toMatchObject(projectData);
});
+
+ it('includes storage type with size of 0 in returned value', () => {
+ const mockedResponse = mockGetProjectStorageCountGraphQLResponse.data;
+ // ensuring a specific storage type item has size of 0
+ mockedResponse.project.statistics.repositorySize = 0;
+
+ const response = parseGetProjectStorageResults(mockedResponse, defaultProvideValues.helpLinks);
+
+ expect(response.storage.storageTypes).toEqual(
+ expect.arrayContaining([
+ {
+ storageType: expect.any(Object),
+ value: 0,
+ },
+ ]),
+ );
+ });
});
diff --git a/spec/frontend/projects/upload_file_experiment_tracking_spec.js b/spec/frontend/projects/upload_file_experiment_tracking_spec.js
deleted file mode 100644
index 6817529e07e..00000000000
--- a/spec/frontend/projects/upload_file_experiment_tracking_spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import ExperimentTracking from '~/experimentation/experiment_tracking';
-import { trackFileUploadEvent } from '~/projects/upload_file_experiment_tracking';
-
-jest.mock('~/experimentation/experiment_tracking');
-
-const eventName = 'click_upload_modal_form_submit';
-const fixture = `<a class='js-upload-file-experiment-trigger'></a><div class='project-home-panel empty-project'></div>`;
-
-beforeEach(() => {
- document.body.innerHTML = fixture;
-});
-
-afterEach(() => {
- document.body.innerHTML = '';
-});
-
-describe('trackFileUploadEvent', () => {
- it('initializes ExperimentTracking with the correct tracking event', () => {
- trackFileUploadEvent(eventName);
-
- expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(eventName);
- });
-
- it('calls ExperimentTracking with the correct arguments', () => {
- trackFileUploadEvent(eventName);
-
- expect(ExperimentTracking).toHaveBeenCalledWith('empty_repo_upload', {
- label: 'blob-upload-modal',
- property: 'empty',
- });
- });
-
- it('calls ExperimentTracking with the correct arguments when the project is not empty', () => {
- document.querySelector('.empty-project').remove();
-
- trackFileUploadEvent(eventName);
-
- expect(ExperimentTracking).toHaveBeenCalledWith('empty_repo_upload', {
- label: 'blob-upload-modal',
- property: 'nonempty',
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap b/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
deleted file mode 100644
index f80e2ce6ecc..00000000000
--- a/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
+++ /dev/null
@@ -1,72 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Registry Breadcrumb when is not rootRoute renders 1`] = `
-<div
- class="gl-breadcrumbs"
->
- <ol
- class="breadcrumb gl-breadcrumb-list"
- >
-
- <li
- class="breadcrumb-item gl-breadcrumb-item"
- >
- <a
- class=""
- href="/"
- target="_self"
- />
- </li>
-
- <span
- class="gl-breadcrumb-separator"
- data-testid="separator"
- >
- <svg
- aria-hidden="true"
- class="gl-icon s8"
- data-testid="angle-right-icon"
- role="img"
- >
- <use
- href="#angle-right"
- />
- </svg>
- </span>
- <li
- class="breadcrumb-item gl-breadcrumb-item"
- >
- <a
- class=""
- href="#"
- target="_self"
- />
- </li>
-
- <!---->
- </ol>
-</div>
-`;
-
-exports[`Registry Breadcrumb when is rootRoute renders 1`] = `
-<div
- class="gl-breadcrumbs"
->
- <ol
- class="breadcrumb gl-breadcrumb-list"
- >
-
- <li
- class="breadcrumb-item gl-breadcrumb-item"
- >
- <a
- class=""
- href="/"
- target="_self"
- />
- </li>
-
- <!---->
- </ol>
-</div>
-`;
diff --git a/spec/frontend/registry/explorer/components/delete_button_spec.js b/spec/frontend/registry/explorer/components/delete_button_spec.js
deleted file mode 100644
index 4597c42add9..00000000000
--- a/spec/frontend/registry/explorer/components/delete_button_spec.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import { GlButton } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import component from '~/registry/explorer/components/delete_button.vue';
-
-describe('delete_button', () => {
- let wrapper;
-
- const defaultProps = {
- title: 'Foo title',
- tooltipTitle: 'Bar tooltipTitle',
- };
-
- const findButton = () => wrapper.find(GlButton);
-
- const mountComponent = (props) => {
- wrapper = shallowMount(component, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('tooltip', () => {
- it('the title is controlled by tooltipTitle prop', () => {
- mountComponent();
- const tooltip = getBinding(wrapper.element, 'gl-tooltip');
- expect(tooltip).toBeDefined();
- expect(tooltip.value.title).toBe(defaultProps.tooltipTitle);
- });
-
- it('is disabled when tooltipTitle is disabled', () => {
- mountComponent({ tooltipDisabled: true });
- const tooltip = getBinding(wrapper.element, 'gl-tooltip');
- expect(tooltip.value.disabled).toBe(true);
- });
-
- describe('button', () => {
- it('exists', () => {
- mountComponent();
- expect(findButton().exists()).toBe(true);
- });
-
- it('has the correct props/attributes bound', () => {
- mountComponent({ disabled: true });
- expect(findButton().attributes()).toMatchObject({
- 'aria-label': 'Foo title',
- icon: 'remove',
- title: 'Foo title',
- variant: 'danger',
- disabled: 'true',
- category: 'secondary',
- });
- });
-
- it('emits a delete event', () => {
- mountComponent();
- expect(wrapper.emitted('delete')).toEqual(undefined);
- findButton().vm.$emit('click');
- expect(wrapper.emitted('delete')).toEqual([[]]);
- });
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/delete_image_spec.js b/spec/frontend/registry/explorer/components/delete_image_spec.js
deleted file mode 100644
index 9a0d070e42b..00000000000
--- a/spec/frontend/registry/explorer/components/delete_image_spec.js
+++ /dev/null
@@ -1,152 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import waitForPromises from 'helpers/wait_for_promises';
-import component from '~/registry/explorer/components/delete_image.vue';
-import { GRAPHQL_PAGE_SIZE } from '~/registry/explorer/constants/index';
-import deleteContainerRepositoryMutation from '~/registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql';
-import getContainerRepositoryDetailsQuery from '~/registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
-
-describe('Delete Image', () => {
- let wrapper;
- const id = '1';
- const storeMock = {
- readQuery: jest.fn().mockReturnValue({
- containerRepository: {
- status: 'foo',
- },
- }),
- writeQuery: jest.fn(),
- };
-
- const updatePayload = {
- data: {
- destroyContainerRepository: {
- containerRepository: {
- status: 'baz',
- },
- },
- },
- };
-
- const findButton = () => wrapper.find('button');
-
- const mountComponent = ({
- propsData = { id },
- mutate = jest.fn().mockResolvedValue({}),
- } = {}) => {
- wrapper = shallowMount(component, {
- propsData,
- mocks: {
- $apollo: {
- mutate,
- },
- },
- scopedSlots: {
- default: '<button @click="props.doDelete">test</button>',
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('executes apollo mutate on doDelete', () => {
- const mutate = jest.fn().mockResolvedValue({});
- mountComponent({ mutate });
-
- wrapper.vm.doDelete();
-
- expect(mutate).toHaveBeenCalledWith({
- mutation: deleteContainerRepositoryMutation,
- variables: {
- id,
- },
- update: undefined,
- });
- });
-
- it('on success emits the correct events', async () => {
- const mutate = jest.fn().mockResolvedValue({});
- mountComponent({ mutate });
-
- wrapper.vm.doDelete();
-
- await waitForPromises();
-
- expect(wrapper.emitted('start')).toEqual([[]]);
- expect(wrapper.emitted('success')).toEqual([[]]);
- expect(wrapper.emitted('end')).toEqual([[]]);
- });
-
- it('when a payload contains an error emits an error event', async () => {
- const mutate = jest
- .fn()
- .mockResolvedValue({ data: { destroyContainerRepository: { errors: ['foo'] } } });
-
- mountComponent({ mutate });
- wrapper.vm.doDelete();
-
- await waitForPromises();
-
- expect(wrapper.emitted('error')).toEqual([[['foo']]]);
- });
-
- it('when the api call errors emits an error event', async () => {
- const mutate = jest.fn().mockRejectedValue('error');
-
- mountComponent({ mutate });
- wrapper.vm.doDelete();
-
- await waitForPromises();
-
- expect(wrapper.emitted('error')).toEqual([[['error']]]);
- });
-
- it('uses the update function, when the prop is set to true', () => {
- const mutate = jest.fn().mockResolvedValue({});
-
- mountComponent({ mutate, propsData: { id, useUpdateFn: true } });
- wrapper.vm.doDelete();
-
- expect(mutate).toHaveBeenCalledWith({
- mutation: deleteContainerRepositoryMutation,
- variables: {
- id,
- },
- update: wrapper.vm.updateImageStatus,
- });
- });
-
- it('updateImage status reads and write to the cache', () => {
- mountComponent();
-
- const variables = {
- id,
- first: GRAPHQL_PAGE_SIZE,
- };
-
- wrapper.vm.updateImageStatus(storeMock, updatePayload);
-
- expect(storeMock.readQuery).toHaveBeenCalledWith({
- query: getContainerRepositoryDetailsQuery,
- variables,
- });
- expect(storeMock.writeQuery).toHaveBeenCalledWith({
- query: getContainerRepositoryDetailsQuery,
- variables,
- data: {
- containerRepository: {
- status: updatePayload.data.destroyContainerRepository.containerRepository.status,
- },
- },
- });
- });
-
- it('binds the doDelete function to the default scoped slot', () => {
- const mutate = jest.fn().mockResolvedValue({});
- mountComponent({ mutate });
- findButton().trigger('click');
- expect(mutate).toHaveBeenCalled();
- });
-});
diff --git a/spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js b/spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js
deleted file mode 100644
index c2a2a4e06ea..00000000000
--- a/spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js
+++ /dev/null
@@ -1,116 +0,0 @@
-import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import component from '~/registry/explorer/components/details_page/delete_alert.vue';
-import {
- DELETE_TAG_SUCCESS_MESSAGE,
- DELETE_TAG_ERROR_MESSAGE,
- DELETE_TAGS_SUCCESS_MESSAGE,
- DELETE_TAGS_ERROR_MESSAGE,
- ADMIN_GARBAGE_COLLECTION_TIP,
-} from '~/registry/explorer/constants';
-
-describe('Delete alert', () => {
- let wrapper;
-
- const findAlert = () => wrapper.find(GlAlert);
- const findLink = () => wrapper.find(GlLink);
-
- const mountComponent = (propsData) => {
- wrapper = shallowMount(component, { stubs: { GlSprintf }, propsData });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('when deleteAlertType is null', () => {
- it('does not show the alert', () => {
- mountComponent();
- expect(findAlert().exists()).toBe(false);
- });
- });
-
- describe('when deleteAlertType is not null', () => {
- describe('success states', () => {
- describe.each`
- deleteAlertType | message
- ${'success_tag'} | ${DELETE_TAG_SUCCESS_MESSAGE}
- ${'success_tags'} | ${DELETE_TAGS_SUCCESS_MESSAGE}
- `('when deleteAlertType is $deleteAlertType', ({ deleteAlertType, message }) => {
- it('alert exists', () => {
- mountComponent({ deleteAlertType });
- expect(findAlert().exists()).toBe(true);
- });
-
- describe('when the user is an admin', () => {
- beforeEach(() => {
- mountComponent({
- deleteAlertType,
- isAdmin: true,
- garbageCollectionHelpPagePath: 'foo',
- });
- });
-
- it(`alert title is ${message}`, () => {
- expect(findAlert().attributes('title')).toBe(message);
- });
-
- it('alert body contains admin tip', () => {
- expect(findAlert().text()).toMatchInterpolatedText(ADMIN_GARBAGE_COLLECTION_TIP);
- });
-
- it('alert body contains link', () => {
- const alertLink = findLink();
- expect(alertLink.exists()).toBe(true);
- expect(alertLink.attributes('href')).toBe('foo');
- });
- });
-
- describe('when the user is not an admin', () => {
- it('alert exist and text is appropriate', () => {
- mountComponent({ deleteAlertType });
- expect(findAlert().exists()).toBe(true);
- expect(findAlert().text()).toBe(message);
- });
- });
- });
- });
- describe('error states', () => {
- describe.each`
- deleteAlertType | message
- ${'danger_tag'} | ${DELETE_TAG_ERROR_MESSAGE}
- ${'danger_tags'} | ${DELETE_TAGS_ERROR_MESSAGE}
- `('when deleteAlertType is $deleteAlertType', ({ deleteAlertType, message }) => {
- it('alert exists', () => {
- mountComponent({ deleteAlertType });
- expect(findAlert().exists()).toBe(true);
- });
-
- describe('when the user is an admin', () => {
- it('alert exist and text is appropriate', () => {
- mountComponent({ deleteAlertType });
- expect(findAlert().exists()).toBe(true);
- expect(findAlert().text()).toBe(message);
- });
- });
-
- describe('when the user is not an admin', () => {
- it('alert exist and text is appropriate', () => {
- mountComponent({ deleteAlertType });
- expect(findAlert().exists()).toBe(true);
- expect(findAlert().text()).toBe(message);
- });
- });
- });
- });
-
- describe('dismissing alert', () => {
- it('GlAlert dismiss event triggers a change event', () => {
- mountComponent({ deleteAlertType: 'success_tags' });
- findAlert().vm.$emit('dismiss');
- expect(wrapper.emitted('change')).toEqual([[null]]);
- });
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js b/spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js
deleted file mode 100644
index d2fe5af3a94..00000000000
--- a/spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js
+++ /dev/null
@@ -1,152 +0,0 @@
-import { GlSprintf, GlFormInput } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import component from '~/registry/explorer/components/details_page/delete_modal.vue';
-import {
- REMOVE_TAG_CONFIRMATION_TEXT,
- REMOVE_TAGS_CONFIRMATION_TEXT,
- DELETE_IMAGE_CONFIRMATION_TITLE,
- DELETE_IMAGE_CONFIRMATION_TEXT,
-} from '~/registry/explorer/constants';
-import { GlModal } from '../../stubs';
-
-describe('Delete Modal', () => {
- let wrapper;
-
- const findModal = () => wrapper.findComponent(GlModal);
- const findDescription = () => wrapper.find('[data-testid="description"]');
- const findInputComponent = () => wrapper.findComponent(GlFormInput);
-
- const mountComponent = (propsData) => {
- wrapper = shallowMount(component, {
- propsData,
- stubs: {
- GlSprintf,
- GlModal,
- },
- });
- };
-
- const expectPrimaryActionStatus = (disabled = true) =>
- expect(findModal().props('actionPrimary')).toMatchObject(
- expect.objectContaining({
- attributes: [{ variant: 'danger' }, { disabled }],
- }),
- );
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('contains a GlModal', () => {
- mountComponent();
- expect(findModal().exists()).toBe(true);
- });
-
- describe('events', () => {
- it.each`
- glEvent | localEvent
- ${'primary'} | ${'confirmDelete'}
- ${'cancel'} | ${'cancelDelete'}
- `('GlModal $glEvent emits $localEvent', ({ glEvent, localEvent }) => {
- mountComponent();
- findModal().vm.$emit(glEvent);
- expect(wrapper.emitted(localEvent)).toEqual([[]]);
- });
- });
-
- describe('methods', () => {
- it('show calls gl-modal show', () => {
- mountComponent();
- wrapper.vm.show();
- expect(GlModal.methods.show).toHaveBeenCalled();
- });
- });
-
- describe('when we are deleting images', () => {
- it('has the correct title', () => {
- mountComponent({ deleteImage: true });
-
- expect(wrapper.text()).toContain(DELETE_IMAGE_CONFIRMATION_TITLE);
- });
-
- it('has the correct description', () => {
- mountComponent({ deleteImage: true });
-
- expect(wrapper.text()).toContain(
- DELETE_IMAGE_CONFIRMATION_TEXT.replace('%{code}', '').trim(),
- );
- });
-
- describe('delete button', () => {
- const itemsToBeDeleted = [{ project: { path: 'foo' } }];
-
- it('is disabled by default', () => {
- mountComponent({ deleteImage: true });
-
- expectPrimaryActionStatus();
- });
-
- it('if the user types something different from the project path is disabled', async () => {
- mountComponent({ deleteImage: true, itemsToBeDeleted });
-
- findInputComponent().vm.$emit('input', 'bar');
-
- await nextTick();
-
- expectPrimaryActionStatus();
- });
-
- it('if the user types the project path it is enabled', async () => {
- mountComponent({ deleteImage: true, itemsToBeDeleted });
-
- findInputComponent().vm.$emit('input', 'foo');
-
- await nextTick();
-
- expectPrimaryActionStatus(false);
- });
- });
- });
-
- describe('when we are deleting tags', () => {
- it('delete button is enabled', () => {
- mountComponent();
-
- expectPrimaryActionStatus(false);
- });
-
- describe('itemsToBeDeleted contains one element', () => {
- beforeEach(() => {
- mountComponent({ itemsToBeDeleted: [{ path: 'foo' }] });
- });
-
- it(`has the correct description`, () => {
- expect(findDescription().text()).toBe(
- REMOVE_TAG_CONFIRMATION_TEXT.replace('%{item}', 'foo'),
- );
- });
-
- it('has the correct title', () => {
- expect(wrapper.text()).toContain('Remove tag');
- });
- });
-
- describe('itemsToBeDeleted contains more than element', () => {
- beforeEach(() => {
- mountComponent({ itemsToBeDeleted: [{ path: 'foo' }, { path: 'bar' }] });
- });
-
- it(`has the correct description`, () => {
- expect(findDescription().text()).toBe(
- REMOVE_TAGS_CONFIRMATION_TEXT.replace('%{item}', '2'),
- );
- });
-
- it('has the correct title', () => {
- expect(wrapper.text()).toContain('Remove tags');
- });
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/details_page/details_header_spec.js b/spec/frontend/registry/explorer/components/details_page/details_header_spec.js
deleted file mode 100644
index acff5c21940..00000000000
--- a/spec/frontend/registry/explorer/components/details_page/details_header_spec.js
+++ /dev/null
@@ -1,304 +0,0 @@
-import { GlDropdownItem, GlIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import VueApollo from 'vue-apollo';
-import { useFakeDate } from 'helpers/fake_date';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import waitForPromises from 'helpers/wait_for_promises';
-import { GlDropdown } from 'jest/registry/explorer/stubs';
-import component from '~/registry/explorer/components/details_page/details_header.vue';
-import {
- UNSCHEDULED_STATUS,
- SCHEDULED_STATUS,
- ONGOING_STATUS,
- UNFINISHED_STATUS,
- CLEANUP_DISABLED_TEXT,
- CLEANUP_DISABLED_TOOLTIP,
- CLEANUP_SCHEDULED_TOOLTIP,
- CLEANUP_ONGOING_TOOLTIP,
- CLEANUP_UNFINISHED_TOOLTIP,
- ROOT_IMAGE_TEXT,
- ROOT_IMAGE_TOOLTIP,
-} from '~/registry/explorer/constants';
-import getContainerRepositoryTagCountQuery from '~/registry/explorer/graphql/queries/get_container_repository_tags_count.query.graphql';
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
-import { imageTagsCountMock } from '../../mock_data';
-
-describe('Details Header', () => {
- let wrapper;
- let apolloProvider;
- let localVue;
-
- const defaultImage = {
- name: 'foo',
- updatedAt: '2020-11-03T13:29:21Z',
- canDelete: true,
- project: {
- visibility: 'public',
- containerExpirationPolicy: {
- enabled: false,
- },
- },
- };
-
- // set the date to Dec 4, 2020
- useFakeDate(2020, 11, 4);
- const findByTestId = (testId) => wrapper.find(`[data-testid="${testId}"]`);
-
- const findLastUpdatedAndVisibility = () => findByTestId('updated-and-visibility');
- const findTitle = () => findByTestId('title');
- const findTagsCount = () => findByTestId('tags-count');
- const findCleanup = () => findByTestId('cleanup');
- const findDeleteButton = () => wrapper.findComponent(GlDropdownItem);
- const findInfoIcon = () => wrapper.findComponent(GlIcon);
-
- const waitForMetadataItems = async () => {
- // Metadata items are printed by a loop in the title-area and it takes two ticks for them to be available
- await wrapper.vm.$nextTick();
- await wrapper.vm.$nextTick();
- };
-
- const mountComponent = ({
- propsData = { image: defaultImage },
- resolver = jest.fn().mockResolvedValue(imageTagsCountMock()),
- $apollo = undefined,
- } = {}) => {
- const mocks = {};
-
- if ($apollo) {
- mocks.$apollo = $apollo;
- } else {
- localVue = createLocalVue();
- localVue.use(VueApollo);
-
- const requestHandlers = [[getContainerRepositoryTagCountQuery, resolver]];
- apolloProvider = createMockApollo(requestHandlers);
- }
-
- wrapper = shallowMount(component, {
- localVue,
- apolloProvider,
- propsData,
- directives: {
- GlTooltip: createMockDirective(),
- },
- mocks,
- stubs: {
- TitleArea,
- GlDropdown,
- GlDropdownItem,
- },
- });
- };
-
- afterEach(() => {
- // if we want to mix createMockApollo and manual mocks we need to reset everything
- wrapper.destroy();
- apolloProvider = undefined;
- localVue = undefined;
- wrapper = null;
- });
-
- describe('image name', () => {
- describe('missing image name', () => {
- beforeEach(() => {
- mountComponent({ propsData: { image: { ...defaultImage, name: '' } } });
-
- return waitForPromises();
- });
-
- it('root image ', () => {
- expect(findTitle().text()).toBe(ROOT_IMAGE_TEXT);
- });
-
- it('has an icon', () => {
- expect(findInfoIcon().exists()).toBe(true);
- expect(findInfoIcon().props('name')).toBe('information-o');
- });
-
- it('has a tooltip', () => {
- const tooltip = getBinding(findInfoIcon().element, 'gl-tooltip');
- expect(tooltip.value).toBe(ROOT_IMAGE_TOOLTIP);
- });
- });
-
- describe('with image name present', () => {
- beforeEach(() => {
- mountComponent();
-
- return waitForPromises();
- });
-
- it('shows image.name ', () => {
- expect(findTitle().text()).toContain('foo');
- });
-
- it('has no icon', () => {
- expect(findInfoIcon().exists()).toBe(false);
- });
- });
- });
-
- describe('delete button', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findDeleteButton().exists()).toBe(true);
- });
-
- it('has the correct text', () => {
- mountComponent();
-
- expect(findDeleteButton().text()).toBe('Delete image repository');
- });
-
- it('has the correct props', () => {
- mountComponent();
-
- expect(findDeleteButton().attributes()).toMatchObject(
- expect.objectContaining({
- variant: 'danger',
- }),
- );
- });
-
- it('emits the correct event', () => {
- mountComponent();
-
- findDeleteButton().vm.$emit('click');
-
- expect(wrapper.emitted('delete')).toEqual([[]]);
- });
-
- it.each`
- canDelete | disabled | isDisabled
- ${true} | ${false} | ${undefined}
- ${true} | ${true} | ${'true'}
- ${false} | ${false} | ${'true'}
- ${false} | ${true} | ${'true'}
- `(
- 'when canDelete is $canDelete and disabled is $disabled is $isDisabled that the button is disabled',
- ({ canDelete, disabled, isDisabled }) => {
- mountComponent({ propsData: { image: { ...defaultImage, canDelete }, disabled } });
-
- expect(findDeleteButton().attributes('disabled')).toBe(isDisabled);
- },
- );
- });
-
- describe('metadata items', () => {
- describe('tags count', () => {
- it('displays "-- tags" while loading', async () => {
- // here we are forced to mock apollo because `waitForMetadataItems` waits
- // for two ticks, de facto allowing the promise to resolve, so there is
- // no way to catch the component as both rendered and in loading state
- mountComponent({ $apollo: { queries: { containerRepository: { loading: true } } } });
-
- await waitForMetadataItems();
-
- expect(findTagsCount().props('text')).toBe('-- tags');
- });
-
- it('when there is more than one tag has the correct text', async () => {
- mountComponent();
-
- await waitForPromises();
- await waitForMetadataItems();
-
- expect(findTagsCount().props('text')).toBe('13 tags');
- });
-
- it('when there is one tag has the correct text', async () => {
- mountComponent({
- resolver: jest.fn().mockResolvedValue(imageTagsCountMock({ tagsCount: 1 })),
- });
-
- await waitForPromises();
- await waitForMetadataItems();
-
- expect(findTagsCount().props('text')).toBe('1 tag');
- });
-
- it('has the correct icon', async () => {
- mountComponent();
- await waitForMetadataItems();
-
- expect(findTagsCount().props('icon')).toBe('tag');
- });
- });
-
- describe('cleanup metadata item', () => {
- it('has the correct icon', async () => {
- mountComponent();
- await waitForMetadataItems();
-
- expect(findCleanup().props('icon')).toBe('expire');
- });
-
- it('when the expiration policy is disabled', async () => {
- mountComponent();
- await waitForMetadataItems();
-
- expect(findCleanup().props()).toMatchObject({
- text: CLEANUP_DISABLED_TEXT,
- textTooltip: CLEANUP_DISABLED_TOOLTIP,
- });
- });
-
- it.each`
- status | text | tooltip
- ${UNSCHEDULED_STATUS} | ${'Cleanup will run in 1 month'} | ${''}
- ${SCHEDULED_STATUS} | ${'Cleanup pending'} | ${CLEANUP_SCHEDULED_TOOLTIP}
- ${ONGOING_STATUS} | ${'Cleanup in progress'} | ${CLEANUP_ONGOING_TOOLTIP}
- ${UNFINISHED_STATUS} | ${'Cleanup incomplete'} | ${CLEANUP_UNFINISHED_TOOLTIP}
- `(
- 'when the status is $status the text is $text and the tooltip is $tooltip',
- async ({ status, text, tooltip }) => {
- mountComponent({
- propsData: {
- image: {
- ...defaultImage,
- expirationPolicyCleanupStatus: status,
- project: {
- containerExpirationPolicy: { enabled: true, nextRunAt: '2021-01-03T14:29:21Z' },
- },
- },
- },
- });
- await waitForMetadataItems();
-
- expect(findCleanup().props()).toMatchObject({
- text,
- textTooltip: tooltip,
- });
- },
- );
- });
-
- describe('visibility and updated at ', () => {
- it('has last updated text', async () => {
- mountComponent();
- await waitForMetadataItems();
-
- expect(findLastUpdatedAndVisibility().props('text')).toBe('Last updated 1 month ago');
- });
-
- describe('visibility icon', () => {
- it('shows an eye when the project is public', async () => {
- mountComponent();
- await waitForMetadataItems();
-
- expect(findLastUpdatedAndVisibility().props('icon')).toBe('eye');
- });
- it('shows an eye slashed when the project is not public', async () => {
- mountComponent({
- propsData: { image: { ...defaultImage, project: { visibility: 'private' } } },
- });
- await waitForMetadataItems();
-
- expect(findLastUpdatedAndVisibility().props('icon')).toBe('eye-slash');
- });
- });
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/details_page/empty_state_spec.js b/spec/frontend/registry/explorer/components/details_page/empty_state_spec.js
deleted file mode 100644
index 14b15945631..00000000000
--- a/spec/frontend/registry/explorer/components/details_page/empty_state_spec.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import { GlEmptyState } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import component from '~/registry/explorer/components/details_page/empty_state.vue';
-import {
- NO_TAGS_TITLE,
- NO_TAGS_MESSAGE,
- MISSING_OR_DELETED_IMAGE_TITLE,
- MISSING_OR_DELETED_IMAGE_MESSAGE,
-} from '~/registry/explorer/constants';
-
-describe('EmptyTagsState component', () => {
- let wrapper;
-
- const findEmptyState = () => wrapper.find(GlEmptyState);
-
- const mountComponent = (propsData) => {
- wrapper = shallowMount(component, {
- stubs: {
- GlEmptyState,
- },
- propsData,
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('contains gl-empty-state', () => {
- mountComponent();
- expect(findEmptyState().exists()).toBe(true);
- });
-
- it.each`
- isEmptyImage | title | description
- ${false} | ${NO_TAGS_TITLE} | ${NO_TAGS_MESSAGE}
- ${true} | ${MISSING_OR_DELETED_IMAGE_TITLE} | ${MISSING_OR_DELETED_IMAGE_MESSAGE}
- `(
- 'when isEmptyImage is $isEmptyImage has the correct props',
- ({ isEmptyImage, title, description }) => {
- mountComponent({
- noContainersImage: 'foo',
- isEmptyImage,
- });
-
- expect(findEmptyState().props()).toMatchObject({
- title,
- description,
- svgPath: 'foo',
- });
- },
- );
-});
diff --git a/spec/frontend/registry/explorer/components/details_page/partial_cleanup_alert_spec.js b/spec/frontend/registry/explorer/components/details_page/partial_cleanup_alert_spec.js
deleted file mode 100644
index af8a23e412c..00000000000
--- a/spec/frontend/registry/explorer/components/details_page/partial_cleanup_alert_spec.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import { GlAlert, GlSprintf } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import component from '~/registry/explorer/components/details_page/partial_cleanup_alert.vue';
-import { DELETE_ALERT_TITLE, DELETE_ALERT_LINK_TEXT } from '~/registry/explorer/constants';
-
-describe('Partial Cleanup alert', () => {
- let wrapper;
-
- const findAlert = () => wrapper.find(GlAlert);
- const findRunLink = () => wrapper.find('[data-testid="run-link"');
- const findHelpLink = () => wrapper.find('[data-testid="help-link"');
-
- const mountComponent = () => {
- wrapper = shallowMount(component, {
- stubs: { GlSprintf },
- propsData: {
- runCleanupPoliciesHelpPagePath: 'foo',
- cleanupPoliciesHelpPagePath: 'bar',
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it(`gl-alert has the correct properties`, () => {
- mountComponent();
-
- expect(findAlert().props()).toMatchObject({
- title: DELETE_ALERT_TITLE,
- variant: 'warning',
- });
- });
-
- it('has the right text', () => {
- mountComponent();
-
- expect(wrapper.text()).toMatchInterpolatedText(DELETE_ALERT_LINK_TEXT);
- });
-
- it('contains run link', () => {
- mountComponent();
-
- const link = findRunLink();
- expect(link.exists()).toBe(true);
- expect(link.attributes()).toMatchObject({
- href: 'foo',
- target: '_blank',
- });
- });
-
- it('contains help link', () => {
- mountComponent();
-
- const link = findHelpLink();
- expect(link.exists()).toBe(true);
- expect(link.attributes()).toMatchObject({
- href: 'bar',
- target: '_blank',
- });
- });
-
- it('GlAlert dismiss event triggers a dismiss event', () => {
- mountComponent();
-
- findAlert().vm.$emit('dismiss');
- expect(wrapper.emitted('dismiss')).toEqual([[]]);
- });
-});
diff --git a/spec/frontend/registry/explorer/components/details_page/status_alert_spec.js b/spec/frontend/registry/explorer/components/details_page/status_alert_spec.js
deleted file mode 100644
index b079883cefd..00000000000
--- a/spec/frontend/registry/explorer/components/details_page/status_alert_spec.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import { GlLink, GlSprintf, GlAlert } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import component from '~/registry/explorer/components/details_page/status_alert.vue';
-import {
- DELETE_SCHEDULED,
- DELETE_FAILED,
- PACKAGE_DELETE_HELP_PAGE_PATH,
- SCHEDULED_FOR_DELETION_STATUS_TITLE,
- SCHEDULED_FOR_DELETION_STATUS_MESSAGE,
- FAILED_DELETION_STATUS_TITLE,
- FAILED_DELETION_STATUS_MESSAGE,
-} from '~/registry/explorer/constants';
-
-describe('Status Alert', () => {
- let wrapper;
-
- const findLink = () => wrapper.find(GlLink);
- const findAlert = () => wrapper.find(GlAlert);
- const findMessage = () => wrapper.find('[data-testid="message"]');
-
- const mountComponent = (propsData) => {
- wrapper = shallowMount(component, {
- propsData,
- stubs: {
- GlSprintf,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it.each`
- status | title | variant | message | link
- ${DELETE_SCHEDULED} | ${SCHEDULED_FOR_DELETION_STATUS_TITLE} | ${'info'} | ${SCHEDULED_FOR_DELETION_STATUS_MESSAGE} | ${PACKAGE_DELETE_HELP_PAGE_PATH}
- ${DELETE_FAILED} | ${FAILED_DELETION_STATUS_TITLE} | ${'warning'} | ${FAILED_DELETION_STATUS_MESSAGE} | ${''}
- `(
- `when the status is $status, title is $title, variant is $variant, message is $message and the link is $link`,
- ({ status, title, variant, message, link }) => {
- mountComponent({ status });
-
- expect(findMessage().text()).toMatchInterpolatedText(message);
- expect(findAlert().props()).toMatchObject({
- title,
- variant,
- });
- if (link) {
- expect(findLink().attributes()).toMatchObject({
- target: '_blank',
- href: link,
- });
- }
- },
- );
-});
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js b/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js
deleted file mode 100644
index a5da37a2786..00000000000
--- a/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js
+++ /dev/null
@@ -1,382 +0,0 @@
-import { GlFormCheckbox, GlSprintf, GlIcon, GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-
-import component from '~/registry/explorer/components/details_page/tags_list_row.vue';
-import {
- REMOVE_TAG_BUTTON_TITLE,
- MISSING_MANIFEST_WARNING_TOOLTIP,
- NOT_AVAILABLE_TEXT,
- NOT_AVAILABLE_SIZE,
-} from '~/registry/explorer/constants/index';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-
-import { tagsMock } from '../../mock_data';
-import { ListItem } from '../../stubs';
-
-describe('tags list row', () => {
- let wrapper;
- const [tag] = [...tagsMock];
-
- const defaultProps = { tag, isMobile: false, index: 0 };
-
- const findCheckbox = () => wrapper.findComponent(GlFormCheckbox);
- const findName = () => wrapper.find('[data-testid="name"]');
- const findSize = () => wrapper.find('[data-testid="size"]');
- const findTime = () => wrapper.find('[data-testid="time"]');
- const findShortRevision = () => wrapper.find('[data-testid="digest"]');
- const findClipboardButton = () => wrapper.findComponent(ClipboardButton);
- const findTimeAgoTooltip = () => wrapper.findComponent(TimeAgoTooltip);
- const findDetailsRows = () => wrapper.findAll(DetailsRow);
- const findPublishedDateDetail = () => wrapper.find('[data-testid="published-date-detail"]');
- const findManifestDetail = () => wrapper.find('[data-testid="manifest-detail"]');
- const findConfigurationDetail = () => wrapper.find('[data-testid="configuration-detail"]');
- const findWarningIcon = () => wrapper.findComponent(GlIcon);
- const findAdditionalActionsMenu = () => wrapper.findComponent(GlDropdown);
- const findDeleteButton = () => wrapper.findComponent(GlDropdownItem);
-
- const mountComponent = (propsData = defaultProps) => {
- wrapper = shallowMount(component, {
- stubs: {
- GlSprintf,
- ListItem,
- DetailsRow,
- GlDropdown,
- },
- propsData,
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('checkbox', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findCheckbox().exists()).toBe(true);
- });
-
- it("does not exist when the row can't be deleted", () => {
- const customTag = { ...tag, canDelete: false };
-
- mountComponent({ ...defaultProps, tag: customTag });
-
- expect(findCheckbox().exists()).toBe(false);
- });
-
- it.each`
- digest | disabled
- ${'foo'} | ${true}
- ${null} | ${false}
- ${null} | ${true}
- ${'foo'} | ${true}
- `('is disabled when the digest $digest and disabled is $disabled', ({ digest, disabled }) => {
- mountComponent({ tag: { ...tag, digest }, disabled });
-
- expect(findCheckbox().attributes('disabled')).toBe('true');
- });
-
- it('is wired to the selected prop', () => {
- mountComponent({ ...defaultProps, selected: true });
-
- expect(findCheckbox().attributes('checked')).toBe('true');
- });
-
- it('when changed emit a select event', () => {
- mountComponent();
-
- findCheckbox().vm.$emit('change');
-
- expect(wrapper.emitted('select')).toEqual([[]]);
- });
- });
-
- describe('tag name', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findName().exists()).toBe(true);
- });
-
- it('has the correct text', () => {
- mountComponent();
-
- expect(findName().text()).toBe(tag.name);
- });
-
- it('has a tooltip', () => {
- mountComponent();
-
- const tooltip = getBinding(findName().element, 'gl-tooltip');
-
- expect(tooltip.value.title).toBe(tag.name);
- });
-
- it('on mobile has mw-s class', () => {
- mountComponent({ ...defaultProps, isMobile: true });
-
- expect(findName().classes('mw-s')).toBe(true);
- });
- });
-
- describe('clipboard button', () => {
- it('exist if tag.location exist', () => {
- mountComponent();
-
- expect(findClipboardButton().exists()).toBe(true);
- });
-
- it('is hidden if tag does not have a location', () => {
- mountComponent({ ...defaultProps, tag: { ...tag, location: null } });
-
- expect(findClipboardButton().exists()).toBe(false);
- });
-
- it('has the correct props/attributes', () => {
- mountComponent();
-
- expect(findClipboardButton().attributes()).toMatchObject({
- text: tag.location,
- title: tag.location,
- });
- });
-
- it('is disabled when the component is disabled', () => {
- mountComponent({ ...defaultProps, disabled: true });
-
- expect(findClipboardButton().attributes('disabled')).toBe('true');
- });
- });
-
- describe('warning icon', () => {
- it('is normally hidden', () => {
- mountComponent();
-
- expect(findWarningIcon().exists()).toBe(false);
- });
-
- it('is shown when the tag is broken', () => {
- mountComponent({ tag: { ...tag, digest: null } });
-
- expect(findWarningIcon().exists()).toBe(true);
- });
-
- it('has an appropriate tooltip', () => {
- mountComponent({ tag: { ...tag, digest: null } });
-
- const tooltip = getBinding(findWarningIcon().element, 'gl-tooltip');
- expect(tooltip.value.title).toBe(MISSING_MANIFEST_WARNING_TOOLTIP);
- });
- });
-
- describe('size', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findSize().exists()).toBe(true);
- });
-
- it('contains the totalSize and layers', () => {
- mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '1024', layers: 10 } });
-
- expect(findSize().text()).toMatchInterpolatedText('1.00 KiB · 10 layers');
- });
-
- it('when totalSize is giantic', () => {
- mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '1099511627776', layers: 2 } });
-
- expect(findSize().text()).toMatchInterpolatedText('1024.00 GiB · 2 layers');
- });
-
- it('when totalSize is missing', () => {
- mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '0', layers: 10 } });
-
- expect(findSize().text()).toMatchInterpolatedText(`${NOT_AVAILABLE_SIZE} · 10 layers`);
- });
-
- it('when layers are missing', () => {
- mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '1024' } });
-
- expect(findSize().text()).toMatchInterpolatedText('1.00 KiB');
- });
-
- it('when there is 1 layer', () => {
- mountComponent({ ...defaultProps, tag: { ...tag, totalSize: '0', layers: 1 } });
-
- expect(findSize().text()).toMatchInterpolatedText(`${NOT_AVAILABLE_SIZE} · 1 layer`);
- });
- });
-
- describe('time', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findTime().exists()).toBe(true);
- });
-
- it('has the correct text', () => {
- mountComponent();
-
- expect(findTime().text()).toBe('Published');
- });
-
- it('contains time_ago_tooltip component', () => {
- mountComponent();
-
- expect(findTimeAgoTooltip().exists()).toBe(true);
- });
-
- it('pass the correct props to time ago tooltip', () => {
- mountComponent();
-
- expect(findTimeAgoTooltip().attributes()).toMatchObject({ time: tag.createdAt });
- });
- });
-
- describe('digest', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findShortRevision().exists()).toBe(true);
- });
-
- it('has the correct text', () => {
- mountComponent();
-
- expect(findShortRevision().text()).toMatchInterpolatedText('Digest: 2cf3d2f');
- });
-
- it(`displays ${NOT_AVAILABLE_TEXT} when digest is missing`, () => {
- mountComponent({ tag: { ...tag, digest: null } });
-
- expect(findShortRevision().text()).toMatchInterpolatedText(`Digest: ${NOT_AVAILABLE_TEXT}`);
- });
- });
-
- describe('additional actions menu', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findAdditionalActionsMenu().exists()).toBe(true);
- });
-
- it('has the correct props', () => {
- mountComponent();
-
- expect(findAdditionalActionsMenu().props()).toMatchObject({
- icon: 'ellipsis_v',
- text: 'More actions',
- textSrOnly: true,
- category: 'tertiary',
- right: true,
- });
- });
-
- it.each`
- canDelete | digest | disabled | buttonDisabled
- ${true} | ${null} | ${true} | ${true}
- ${false} | ${'foo'} | ${true} | ${true}
- ${false} | ${null} | ${true} | ${true}
- ${true} | ${'foo'} | ${true} | ${true}
- ${true} | ${'foo'} | ${false} | ${false}
- `(
- 'is $visible that is visible when canDelete is $canDelete and digest is $digest and disabled is $disabled',
- ({ canDelete, digest, disabled, buttonDisabled }) => {
- mountComponent({ ...defaultProps, tag: { ...tag, canDelete, digest }, disabled });
-
- expect(findAdditionalActionsMenu().props('disabled')).toBe(buttonDisabled);
- expect(findAdditionalActionsMenu().classes('gl-opacity-0')).toBe(buttonDisabled);
- expect(findAdditionalActionsMenu().classes('gl-pointer-events-none')).toBe(buttonDisabled);
- },
- );
-
- describe('delete button', () => {
- it('exists and has the correct attrs', () => {
- mountComponent();
-
- expect(findDeleteButton().exists()).toBe(true);
- expect(findDeleteButton().attributes()).toMatchObject({
- variant: 'danger',
- });
- expect(findDeleteButton().text()).toBe(REMOVE_TAG_BUTTON_TITLE);
- });
-
- it('delete event emits delete', () => {
- mountComponent();
-
- findDeleteButton().vm.$emit('click');
-
- expect(wrapper.emitted('delete')).toEqual([[]]);
- });
- });
- });
-
- describe('details rows', () => {
- describe('when the tag has a digest', () => {
- it('has 3 details rows', async () => {
- mountComponent();
- await nextTick();
-
- expect(findDetailsRows().length).toBe(3);
- });
-
- describe.each`
- name | finderFunction | text | icon | clipboard
- ${'published date detail'} | ${findPublishedDateDetail} | ${'Published to the gitlab-org/gitlab-test/rails-12009 image repository at 01:29 UTC on 2020-11-03'} | ${'clock'} | ${false}
- ${'manifest detail'} | ${findManifestDetail} | ${'Manifest digest: sha256:2cf3d2fdac1b04a14301d47d51cb88dcd26714c74f91440eeee99ce399089062'} | ${'log'} | ${true}
- ${'configuration detail'} | ${findConfigurationDetail} | ${'Configuration digest: sha256:c2613843ab33aabf847965442b13a8b55a56ae28837ce182627c0716eb08c02b'} | ${'cloud-gear'} | ${true}
- `('$name details row', ({ finderFunction, text, icon, clipboard }) => {
- it(`has ${text} as text`, async () => {
- mountComponent();
- await nextTick();
-
- expect(finderFunction().text()).toMatchInterpolatedText(text);
- });
-
- it(`has the ${icon} icon`, async () => {
- mountComponent();
- await nextTick();
-
- expect(finderFunction().props('icon')).toBe(icon);
- });
-
- if (clipboard) {
- it(`clipboard button exist`, async () => {
- mountComponent();
- await nextTick();
-
- expect(finderFunction().find(ClipboardButton).exists()).toBe(clipboard);
- });
-
- it('is disabled when the component is disabled', async () => {
- mountComponent({ ...defaultProps, disabled: true });
- await nextTick();
-
- expect(finderFunction().findComponent(ClipboardButton).attributes('disabled')).toBe(
- 'true',
- );
- });
- }
- });
- });
-
- describe('when the tag does not have a digest', () => {
- it('hides the details rows', async () => {
- mountComponent({ tag: { ...tag, digest: null } });
-
- await nextTick();
- expect(findDetailsRows().length).toBe(0);
- });
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js b/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js
deleted file mode 100644
index 51934cd074d..00000000000
--- a/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js
+++ /dev/null
@@ -1,311 +0,0 @@
-import { GlButton, GlKeysetPagination } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import EmptyTagsState from '~/registry/explorer/components/details_page/empty_state.vue';
-import component from '~/registry/explorer/components/details_page/tags_list.vue';
-import TagsListRow from '~/registry/explorer/components/details_page/tags_list_row.vue';
-import TagsLoader from '~/registry/explorer/components/details_page/tags_loader.vue';
-import { TAGS_LIST_TITLE, REMOVE_TAGS_BUTTON_TITLE } from '~/registry/explorer/constants/index';
-import getContainerRepositoryTagsQuery from '~/registry/explorer/graphql/queries/get_container_repository_tags.query.graphql';
-import { tagsMock, imageTagsMock, tagsPageInfo } from '../../mock_data';
-
-const localVue = createLocalVue();
-
-describe('Tags List', () => {
- let wrapper;
- let apolloProvider;
- const tags = [...tagsMock];
- const readOnlyTags = tags.map((t) => ({ ...t, canDelete: false }));
-
- const findTagsListRow = () => wrapper.findAll(TagsListRow);
- const findDeleteButton = () => wrapper.find(GlButton);
- const findListTitle = () => wrapper.find('[data-testid="list-title"]');
- const findPagination = () => wrapper.find(GlKeysetPagination);
- const findEmptyState = () => wrapper.find(EmptyTagsState);
- const findTagsLoader = () => wrapper.find(TagsLoader);
-
- const waitForApolloRequestRender = async () => {
- await waitForPromises();
- await nextTick();
- };
-
- const mountComponent = ({
- propsData = { isMobile: false, id: 1 },
- resolver = jest.fn().mockResolvedValue(imageTagsMock()),
- } = {}) => {
- localVue.use(VueApollo);
-
- const requestHandlers = [[getContainerRepositoryTagsQuery, resolver]];
-
- apolloProvider = createMockApollo(requestHandlers);
- wrapper = shallowMount(component, {
- localVue,
- apolloProvider,
- propsData,
- provide() {
- return {
- config: {},
- };
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('List title', () => {
- it('exists', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findListTitle().exists()).toBe(true);
- });
-
- it('has the correct text', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findListTitle().text()).toBe(TAGS_LIST_TITLE);
- });
- });
-
- describe('delete button', () => {
- it.each`
- inputTags | isMobile | isVisible
- ${tags} | ${false} | ${true}
- ${tags} | ${true} | ${false}
- ${readOnlyTags} | ${false} | ${false}
- ${readOnlyTags} | ${true} | ${false}
- `(
- 'is $isVisible that delete button exists when tags is $inputTags and isMobile is $isMobile',
- async ({ inputTags, isMobile, isVisible }) => {
- mountComponent({
- propsData: { tags: inputTags, isMobile, id: 1 },
- resolver: jest.fn().mockResolvedValue(imageTagsMock(inputTags)),
- });
-
- await waitForApolloRequestRender();
-
- expect(findDeleteButton().exists()).toBe(isVisible);
- },
- );
-
- it('has the correct text', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findDeleteButton().text()).toBe(REMOVE_TAGS_BUTTON_TITLE);
- });
-
- it('has the correct props', async () => {
- mountComponent();
- await waitForApolloRequestRender();
-
- expect(findDeleteButton().attributes()).toMatchObject({
- category: 'secondary',
- variant: 'danger',
- });
- });
-
- it.each`
- disabled | doSelect | buttonDisabled
- ${true} | ${false} | ${'true'}
- ${true} | ${true} | ${'true'}
- ${false} | ${false} | ${'true'}
- ${false} | ${true} | ${undefined}
- `(
- 'is $buttonDisabled that the button is disabled when the component disabled state is $disabled and is $doSelect that the user selected a tag',
- async ({ disabled, buttonDisabled, doSelect }) => {
- mountComponent({ propsData: { tags, disabled, isMobile: false, id: 1 } });
-
- await waitForApolloRequestRender();
-
- if (doSelect) {
- findTagsListRow().at(0).vm.$emit('select');
- await nextTick();
- }
-
- expect(findDeleteButton().attributes('disabled')).toBe(buttonDisabled);
- },
- );
-
- it('click event emits a deleted event with selected items', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- findTagsListRow().at(0).vm.$emit('select');
- findDeleteButton().vm.$emit('click');
-
- expect(wrapper.emitted('delete')[0][0][0].name).toBe(tags[0].name);
- });
- });
-
- describe('list rows', () => {
- it('one row exist for each tag', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findTagsListRow()).toHaveLength(tags.length);
- });
-
- it('the correct props are bound to it', async () => {
- mountComponent({ propsData: { disabled: true, id: 1 } });
-
- await waitForApolloRequestRender();
-
- const rows = findTagsListRow();
-
- expect(rows.at(0).attributes()).toMatchObject({
- first: 'true',
- disabled: 'true',
- });
- });
-
- describe('events', () => {
- it('select event update the selected items', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- findTagsListRow().at(0).vm.$emit('select');
-
- await nextTick();
-
- expect(findTagsListRow().at(0).attributes('selected')).toBe('true');
- });
-
- it('delete event emit a delete event', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- findTagsListRow().at(0).vm.$emit('delete');
- expect(wrapper.emitted('delete')[0][0][0].name).toBe(tags[0].name);
- });
- });
- });
-
- describe('when the list of tags is empty', () => {
- const resolver = jest.fn().mockResolvedValue(imageTagsMock([]));
-
- it('has the empty state', async () => {
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- expect(findEmptyState().exists()).toBe(true);
- });
-
- it('does not show the loader', async () => {
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- expect(findTagsLoader().exists()).toBe(false);
- });
-
- it('does not show the list', async () => {
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- expect(findTagsListRow().exists()).toBe(false);
- expect(findListTitle().exists()).toBe(false);
- });
- });
-
- describe('pagination', () => {
- it('exists', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findPagination().exists()).toBe(true);
- });
-
- it('is hidden when loading', () => {
- mountComponent();
-
- expect(findPagination().exists()).toBe(false);
- });
-
- it('is hidden when there are no more pages', async () => {
- mountComponent({ resolver: jest.fn().mockResolvedValue(imageTagsMock([])) });
-
- await waitForApolloRequestRender();
-
- expect(findPagination().exists()).toBe(false);
- });
-
- it('is wired to the correct pagination props', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findPagination().props()).toMatchObject({
- hasNextPage: tagsPageInfo.hasNextPage,
- hasPreviousPage: tagsPageInfo.hasPreviousPage,
- });
- });
-
- it('fetch next page when user clicks next', async () => {
- const resolver = jest.fn().mockResolvedValue(imageTagsMock());
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- findPagination().vm.$emit('next');
-
- expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({ after: tagsPageInfo.endCursor }),
- );
- });
-
- it('fetch previous page when user clicks prev', async () => {
- const resolver = jest.fn().mockResolvedValue(imageTagsMock());
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- findPagination().vm.$emit('prev');
-
- expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({ first: null, before: tagsPageInfo.startCursor }),
- );
- });
- });
-
- describe('loading state', () => {
- it.each`
- isImageLoading | queryExecuting | loadingVisible
- ${true} | ${true} | ${true}
- ${true} | ${false} | ${true}
- ${false} | ${true} | ${true}
- ${false} | ${false} | ${false}
- `(
- 'when the isImageLoading is $isImageLoading, and is $queryExecuting that the query is still executing is $loadingVisible that the loader is shown',
- async ({ isImageLoading, queryExecuting, loadingVisible }) => {
- mountComponent({ propsData: { isImageLoading, isMobile: false, id: 1 } });
-
- if (!queryExecuting) {
- await waitForApolloRequestRender();
- }
-
- expect(findTagsLoader().exists()).toBe(loadingVisible);
- expect(findTagsListRow().exists()).toBe(!loadingVisible);
- expect(findListTitle().exists()).toBe(!loadingVisible);
- expect(findPagination().exists()).toBe(!loadingVisible);
- },
- );
- });
-});
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js b/spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js
deleted file mode 100644
index 40d84d9d4a5..00000000000
--- a/spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import component from '~/registry/explorer/components/details_page/tags_loader.vue';
-import { GlSkeletonLoader } from '../../stubs';
-
-describe('TagsLoader component', () => {
- let wrapper;
-
- const findGlSkeletonLoaders = () => wrapper.findAll(GlSkeletonLoader);
-
- const mountComponent = () => {
- wrapper = shallowMount(component, {
- stubs: {
- GlSkeletonLoader,
- },
- // set the repeat to 1 to avoid a long and verbose snapshot
- loader: {
- ...component.loader,
- repeat: 1,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('produces the correct amount of loaders ', () => {
- mountComponent();
- expect(findGlSkeletonLoaders().length).toBe(1);
- });
-
- it('has the correct props', () => {
- mountComponent();
- expect(findGlSkeletonLoaders().at(0).props()).toMatchObject({
- width: component.loader.width,
- height: component.loader.height,
- });
- });
-
- it('has the correct markup', () => {
- mountComponent();
- expect(wrapper.element).toMatchSnapshot();
- });
-});
diff --git a/spec/frontend/registry/explorer/components/list_page/cleanup_status_spec.js b/spec/frontend/registry/explorer/components/list_page/cleanup_status_spec.js
deleted file mode 100644
index 8f2c049a357..00000000000
--- a/spec/frontend/registry/explorer/components/list_page/cleanup_status_spec.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import CleanupStatus from '~/registry/explorer/components/list_page/cleanup_status.vue';
-import {
- CLEANUP_TIMED_OUT_ERROR_MESSAGE,
- CLEANUP_STATUS_SCHEDULED,
- CLEANUP_STATUS_ONGOING,
- CLEANUP_STATUS_UNFINISHED,
- UNFINISHED_STATUS,
- UNSCHEDULED_STATUS,
- SCHEDULED_STATUS,
- ONGOING_STATUS,
-} from '~/registry/explorer/constants';
-
-describe('cleanup_status', () => {
- let wrapper;
-
- const findMainIcon = () => wrapper.findByTestId('main-icon');
- const findExtraInfoIcon = () => wrapper.findByTestId('extra-info');
-
- const mountComponent = (propsData = { status: SCHEDULED_STATUS }) => {
- wrapper = shallowMountExtended(CleanupStatus, {
- propsData,
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it.each`
- status | visible | text
- ${UNFINISHED_STATUS} | ${true} | ${CLEANUP_STATUS_UNFINISHED}
- ${SCHEDULED_STATUS} | ${true} | ${CLEANUP_STATUS_SCHEDULED}
- ${ONGOING_STATUS} | ${true} | ${CLEANUP_STATUS_ONGOING}
- ${UNSCHEDULED_STATUS} | ${false} | ${''}
- `(
- 'when the status is $status is $visible that the component is mounted and has the correct text',
- ({ status, visible, text }) => {
- mountComponent({ status });
-
- expect(findMainIcon().exists()).toBe(visible);
- expect(wrapper.text()).toBe(text);
- },
- );
-
- describe('main icon', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findMainIcon().exists()).toBe(true);
- });
-
- it(`has the orange class when the status is ${UNFINISHED_STATUS}`, () => {
- mountComponent({ status: UNFINISHED_STATUS });
-
- expect(findMainIcon().classes('gl-text-orange-500')).toBe(true);
- });
- });
-
- describe('extra info icon', () => {
- it.each`
- status | visible
- ${UNFINISHED_STATUS} | ${true}
- ${SCHEDULED_STATUS} | ${false}
- ${ONGOING_STATUS} | ${false}
- `(
- 'when the status is $status is $visible that the extra icon is visible',
- ({ status, visible }) => {
- mountComponent({ status });
-
- expect(findExtraInfoIcon().exists()).toBe(visible);
- },
- );
-
- it(`has a tooltip`, () => {
- mountComponent({ status: UNFINISHED_STATUS });
-
- const tooltip = getBinding(findExtraInfoIcon().element, 'gl-tooltip');
-
- expect(tooltip.value.title).toBe(CLEANUP_TIMED_OUT_ERROR_MESSAGE);
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js b/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
deleted file mode 100644
index 8ca8fca65ed..00000000000
--- a/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
+++ /dev/null
@@ -1,94 +0,0 @@
-import { GlDropdown } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
-import QuickstartDropdown from '~/registry/explorer/components/list_page/cli_commands.vue';
-import {
- QUICK_START,
- LOGIN_COMMAND_LABEL,
- COPY_LOGIN_TITLE,
- BUILD_COMMAND_LABEL,
- COPY_BUILD_TITLE,
- PUSH_COMMAND_LABEL,
- COPY_PUSH_TITLE,
-} from '~/registry/explorer/constants';
-import Tracking from '~/tracking';
-import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
-
-import { dockerCommands } from '../../mock_data';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('cli_commands', () => {
- let wrapper;
-
- const config = {
- repositoryUrl: 'foo',
- registryHostUrlWithPort: 'bar',
- };
-
- const findDropdownButton = () => wrapper.find(GlDropdown);
- const findCodeInstruction = () => wrapper.findAll(CodeInstruction);
-
- const mountComponent = () => {
- wrapper = mount(QuickstartDropdown, {
- localVue,
- provide() {
- return {
- config,
- ...dockerCommands,
- };
- },
- });
- };
-
- beforeEach(() => {
- jest.spyOn(Tracking, 'event');
- mountComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('shows the correct text on the button', () => {
- expect(findDropdownButton().text()).toContain(QUICK_START);
- });
-
- it('clicking on the dropdown emit a tracking event', () => {
- findDropdownButton().vm.$emit('shown');
- expect(Tracking.event).toHaveBeenCalledWith(
- undefined,
- 'click_dropdown',
- expect.objectContaining({ label: 'quickstart_dropdown' }),
- );
- });
-
- describe.each`
- index | labelText | titleText | command | trackedEvent
- ${0} | ${LOGIN_COMMAND_LABEL} | ${COPY_LOGIN_TITLE} | ${dockerCommands.dockerLoginCommand} | ${'click_copy_login'}
- ${1} | ${BUILD_COMMAND_LABEL} | ${COPY_BUILD_TITLE} | ${dockerCommands.dockerBuildCommand} | ${'click_copy_build'}
- ${2} | ${PUSH_COMMAND_LABEL} | ${COPY_PUSH_TITLE} | ${dockerCommands.dockerPushCommand} | ${'click_copy_push'}
- `('code instructions at $index', ({ index, labelText, titleText, command, trackedEvent }) => {
- let codeInstruction;
-
- beforeEach(() => {
- codeInstruction = findCodeInstruction().at(index);
- });
-
- it('exists', () => {
- expect(codeInstruction.exists()).toBe(true);
- });
-
- it(`has the correct props`, () => {
- expect(codeInstruction.props()).toMatchObject({
- label: labelText,
- instruction: command,
- copyText: titleText,
- trackingAction: trackedEvent,
- trackingLabel: 'quickstart_dropdown',
- });
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js b/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js
deleted file mode 100644
index 989a60625e2..00000000000
--- a/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import { GlSprintf } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
-import groupEmptyState from '~/registry/explorer/components/list_page/group_empty_state.vue';
-import { GlEmptyState } from '../../stubs';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('Registry Group Empty state', () => {
- let wrapper;
- const config = {
- noContainersImage: 'foo',
- helpPagePath: 'baz',
- };
-
- beforeEach(() => {
- wrapper = shallowMount(groupEmptyState, {
- localVue,
- stubs: {
- GlEmptyState,
- GlSprintf,
- },
- provide() {
- return { config };
- },
- });
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('to match the default snapshot', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
-});
diff --git a/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js b/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js
deleted file mode 100644
index db0f869ab52..00000000000
--- a/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js
+++ /dev/null
@@ -1,223 +0,0 @@
-import { GlIcon, GlSprintf, GlSkeletonLoader } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import DeleteButton from '~/registry/explorer/components/delete_button.vue';
-import CleanupStatus from '~/registry/explorer/components/list_page/cleanup_status.vue';
-import Component from '~/registry/explorer/components/list_page/image_list_row.vue';
-import {
- ROW_SCHEDULED_FOR_DELETION,
- LIST_DELETE_BUTTON_DISABLED,
- REMOVE_REPOSITORY_LABEL,
- IMAGE_DELETE_SCHEDULED_STATUS,
- SCHEDULED_STATUS,
- ROOT_IMAGE_TEXT,
-} from '~/registry/explorer/constants';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import ListItem from '~/vue_shared/components/registry/list_item.vue';
-import { imagesListResponse } from '../../mock_data';
-import { RouterLink } from '../../stubs';
-
-describe('Image List Row', () => {
- let wrapper;
- const [item] = imagesListResponse;
-
- const findDetailsLink = () => wrapper.find('[data-testid="details-link"]');
- const findTagsCount = () => wrapper.find('[data-testid="tags-count"]');
- const findDeleteBtn = () => wrapper.findComponent(DeleteButton);
- const findClipboardButton = () => wrapper.findComponent(ClipboardButton);
- const findCleanupStatus = () => wrapper.findComponent(CleanupStatus);
- const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
- const findListItemComponent = () => wrapper.findComponent(ListItem);
-
- const mountComponent = (props) => {
- wrapper = shallowMount(Component, {
- stubs: {
- RouterLink,
- GlSprintf,
- ListItem,
- },
- propsData: {
- item,
- ...props,
- },
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('list item component', () => {
- describe('tooltip', () => {
- it(`the title is ${ROW_SCHEDULED_FOR_DELETION}`, () => {
- mountComponent();
-
- const tooltip = getBinding(wrapper.element, 'gl-tooltip');
- expect(tooltip).toBeDefined();
- expect(tooltip.value.title).toBe(ROW_SCHEDULED_FOR_DELETION);
- });
-
- it('is disabled when item is being deleted', () => {
- mountComponent({ item: { ...item, status: IMAGE_DELETE_SCHEDULED_STATUS } });
-
- const tooltip = getBinding(wrapper.element, 'gl-tooltip');
- expect(tooltip.value.disabled).toBe(false);
- });
- });
-
- it('is disabled when the item is in deleting status', () => {
- mountComponent({ item: { ...item, status: IMAGE_DELETE_SCHEDULED_STATUS } });
-
- expect(findListItemComponent().props('disabled')).toBe(true);
- });
- });
-
- describe('image title and path', () => {
- it('contains a link to the details page', () => {
- mountComponent();
-
- const link = findDetailsLink();
- expect(link.text()).toBe(item.path);
- expect(findDetailsLink().props('to')).toMatchObject({
- name: 'details',
- params: {
- id: getIdFromGraphQLId(item.id),
- },
- });
- });
-
- it(`when the image has no name appends ${ROOT_IMAGE_TEXT} to the path`, () => {
- mountComponent({ item: { ...item, name: '' } });
-
- expect(findDetailsLink().text()).toBe(`${item.path}/ ${ROOT_IMAGE_TEXT}`);
- });
-
- it('contains a clipboard button', () => {
- mountComponent();
- const button = findClipboardButton();
- expect(button.exists()).toBe(true);
- expect(button.props('text')).toBe(item.location);
- expect(button.props('title')).toBe(item.location);
- });
-
- describe('cleanup status component', () => {
- it.each`
- expirationPolicyCleanupStatus | shown
- ${null} | ${false}
- ${SCHEDULED_STATUS} | ${true}
- `(
- 'when expirationPolicyCleanupStatus is $expirationPolicyCleanupStatus it is $shown that the component exists',
- ({ expirationPolicyCleanupStatus, shown }) => {
- mountComponent({ item: { ...item, expirationPolicyCleanupStatus } });
-
- expect(findCleanupStatus().exists()).toBe(shown);
-
- if (shown) {
- expect(findCleanupStatus().props()).toMatchObject({
- status: expirationPolicyCleanupStatus,
- });
- }
- },
- );
- });
-
- describe('when the item is deleting', () => {
- beforeEach(() => {
- mountComponent({ item: { ...item, status: IMAGE_DELETE_SCHEDULED_STATUS } });
- });
-
- it('the router link is disabled', () => {
- // we check the event prop as is the only workaround to disable a router link
- expect(findDetailsLink().props('event')).toBe('');
- });
- it('the clipboard button is disabled', () => {
- expect(findClipboardButton().attributes('disabled')).toBe('true');
- });
- });
- });
-
- describe('delete button', () => {
- it('exists', () => {
- mountComponent();
- expect(findDeleteBtn().exists()).toBe(true);
- });
-
- it('has the correct props', () => {
- mountComponent();
-
- expect(findDeleteBtn().props()).toMatchObject({
- title: REMOVE_REPOSITORY_LABEL,
- tooltipDisabled: item.canDelete,
- tooltipTitle: LIST_DELETE_BUTTON_DISABLED,
- });
- });
-
- it('emits a delete event', () => {
- mountComponent();
-
- findDeleteBtn().vm.$emit('delete');
- expect(wrapper.emitted('delete')).toEqual([[item]]);
- });
-
- it.each`
- canDelete | status | state
- ${false} | ${''} | ${true}
- ${false} | ${IMAGE_DELETE_SCHEDULED_STATUS} | ${true}
- ${true} | ${IMAGE_DELETE_SCHEDULED_STATUS} | ${true}
- ${true} | ${''} | ${false}
- `(
- 'disabled is $state when canDelete is $canDelete and status is $status',
- ({ canDelete, status, state }) => {
- mountComponent({ item: { ...item, canDelete, status } });
-
- expect(findDeleteBtn().props('disabled')).toBe(state);
- },
- );
- });
-
- describe('tags count', () => {
- it('exists', () => {
- mountComponent();
- expect(findTagsCount().exists()).toBe(true);
- });
-
- it('contains a tag icon', () => {
- mountComponent();
- const icon = findTagsCount().find(GlIcon);
- expect(icon.exists()).toBe(true);
- expect(icon.props('name')).toBe('tag');
- });
-
- describe('loading state', () => {
- it('shows a loader when metadataLoading is true', () => {
- mountComponent({ metadataLoading: true });
-
- expect(findSkeletonLoader().exists()).toBe(true);
- });
-
- it('hides the tags count while loading', () => {
- mountComponent({ metadataLoading: true });
-
- expect(findTagsCount().exists()).toBe(false);
- });
- });
-
- describe('tags count text', () => {
- it('with one tag in the image', () => {
- mountComponent({ item: { ...item, tagsCount: 1 } });
-
- expect(findTagsCount().text()).toMatchInterpolatedText('1 Tag');
- });
- it('with more than one tag in the image', () => {
- mountComponent({ item: { ...item, tagsCount: 3 } });
-
- expect(findTagsCount().text()).toMatchInterpolatedText('3 Tags');
- });
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/list_page/image_list_spec.js b/spec/frontend/registry/explorer/components/list_page/image_list_spec.js
deleted file mode 100644
index d7dd825ca3e..00000000000
--- a/spec/frontend/registry/explorer/components/list_page/image_list_spec.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import { GlKeysetPagination } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import Component from '~/registry/explorer/components/list_page/image_list.vue';
-import ImageListRow from '~/registry/explorer/components/list_page/image_list_row.vue';
-
-import { imagesListResponse, pageInfo as defaultPageInfo } from '../../mock_data';
-
-describe('Image List', () => {
- let wrapper;
-
- const findRow = () => wrapper.findAll(ImageListRow);
- const findPagination = () => wrapper.find(GlKeysetPagination);
-
- const mountComponent = (props) => {
- wrapper = shallowMount(Component, {
- propsData: {
- images: imagesListResponse,
- pageInfo: defaultPageInfo,
- ...props,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('list', () => {
- it('contains one list element for each image', () => {
- mountComponent();
-
- expect(findRow().length).toBe(imagesListResponse.length);
- });
-
- it('when delete event is emitted on the row it emits up a delete event', () => {
- mountComponent();
-
- findRow().at(0).vm.$emit('delete', 'foo');
- expect(wrapper.emitted('delete')).toEqual([['foo']]);
- });
-
- it('passes down the metadataLoading prop', () => {
- mountComponent({ metadataLoading: true });
- expect(findRow().at(0).props('metadataLoading')).toBe(true);
- });
- });
-
- describe('pagination', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findPagination().exists()).toBe(true);
- });
-
- it.each`
- hasNextPage | hasPreviousPage | isVisible
- ${true} | ${true} | ${true}
- ${true} | ${false} | ${true}
- ${false} | ${true} | ${true}
- `(
- 'when hasNextPage is $hasNextPage and hasPreviousPage is $hasPreviousPage: is $isVisible that the component is visible',
- ({ hasNextPage, hasPreviousPage, isVisible }) => {
- mountComponent({ pageInfo: { ...defaultPageInfo, hasNextPage, hasPreviousPage } });
-
- expect(findPagination().exists()).toBe(isVisible);
- expect(findPagination().props('hasPreviousPage')).toBe(hasPreviousPage);
- expect(findPagination().props('hasNextPage')).toBe(hasNextPage);
- },
- );
-
- it('emits "prev-page" when the user clicks the back page button', () => {
- mountComponent();
-
- findPagination().vm.$emit('prev');
-
- expect(wrapper.emitted('prev-page')).toEqual([[]]);
- });
-
- it('emits "next-page" when the user clicks the forward page button', () => {
- mountComponent();
-
- findPagination().vm.$emit('next');
-
- expect(wrapper.emitted('next-page')).toEqual([[]]);
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js b/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js
deleted file mode 100644
index 111aa45f231..00000000000
--- a/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import { GlSprintf } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
-import projectEmptyState from '~/registry/explorer/components/list_page/project_empty_state.vue';
-import { dockerCommands } from '../../mock_data';
-import { GlEmptyState } from '../../stubs';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('Registry Project Empty state', () => {
- let wrapper;
- const config = {
- repositoryUrl: 'foo',
- registryHostUrlWithPort: 'bar',
- helpPagePath: 'baz',
- twoFactorAuthHelpLink: 'barBaz',
- personalAccessTokensHelpLink: 'fooBaz',
- noContainersImage: 'bazFoo',
- };
-
- beforeEach(() => {
- wrapper = shallowMount(projectEmptyState, {
- localVue,
- stubs: {
- GlEmptyState,
- GlSprintf,
- },
- provide() {
- return {
- config,
- ...dockerCommands,
- };
- },
- });
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('to match the default snapshot', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
-});
diff --git a/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js b/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
deleted file mode 100644
index 11a3acd9eb9..00000000000
--- a/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
+++ /dev/null
@@ -1,135 +0,0 @@
-import { GlSprintf } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import Component from '~/registry/explorer/components/list_page/registry_header.vue';
-import {
- CONTAINER_REGISTRY_TITLE,
- LIST_INTRO_TEXT,
- EXPIRATION_POLICY_DISABLED_TEXT,
-} from '~/registry/explorer/constants';
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
-
-jest.mock('~/lib/utils/datetime_utility', () => ({
- approximateDuration: jest.fn(),
- calculateRemainingMilliseconds: jest.fn(),
-}));
-
-describe('registry_header', () => {
- let wrapper;
-
- const findTitleArea = () => wrapper.find(TitleArea);
- const findCommandsSlot = () => wrapper.find('[data-testid="commands-slot"]');
- const findImagesCountSubHeader = () => wrapper.find('[data-testid="images-count"]');
- const findExpirationPolicySubHeader = () => wrapper.find('[data-testid="expiration-policy"]');
-
- const mountComponent = (propsData, slots) => {
- wrapper = shallowMount(Component, {
- stubs: {
- GlSprintf,
- TitleArea,
- },
- propsData,
- slots,
- });
- return wrapper.vm.$nextTick();
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('header', () => {
- it('has a title', () => {
- mountComponent({ metadataLoading: true });
-
- expect(findTitleArea().props()).toMatchObject({
- title: CONTAINER_REGISTRY_TITLE,
- metadataLoading: true,
- });
- });
-
- it('has a commands slot', () => {
- mountComponent(null, { commands: '<div data-testid="commands-slot">baz</div>' });
-
- expect(findCommandsSlot().text()).toBe('baz');
- });
-
- describe('sub header parts', () => {
- describe('images count', () => {
- it('exists', async () => {
- await mountComponent({ imagesCount: 1 });
-
- expect(findImagesCountSubHeader().exists()).toBe(true);
- });
-
- it('when there is one image', async () => {
- await mountComponent({ imagesCount: 1 });
-
- expect(findImagesCountSubHeader().props()).toMatchObject({
- text: '1 Image repository',
- icon: 'container-image',
- });
- });
-
- it('when there is more than one image', async () => {
- await mountComponent({ imagesCount: 3 });
-
- expect(findImagesCountSubHeader().props('text')).toBe('3 Image repositories');
- });
- });
-
- describe('expiration policy', () => {
- it('when is disabled', async () => {
- await mountComponent({
- expirationPolicy: { enabled: false },
- expirationPolicyHelpPagePath: 'foo',
- imagesCount: 1,
- });
-
- const text = findExpirationPolicySubHeader();
- expect(text.exists()).toBe(true);
- expect(text.props()).toMatchObject({
- text: EXPIRATION_POLICY_DISABLED_TEXT,
- icon: 'expire',
- size: 'xl',
- });
- });
-
- it('when is enabled', async () => {
- await mountComponent({
- expirationPolicy: { enabled: true },
- expirationPolicyHelpPagePath: 'foo',
- imagesCount: 1,
- });
-
- const text = findExpirationPolicySubHeader();
- expect(text.exists()).toBe(true);
- expect(text.props('text')).toBe('Expiration policy will run in ');
- });
- it('when the expiration policy is completely disabled', async () => {
- await mountComponent({
- expirationPolicy: { enabled: true },
- expirationPolicyHelpPagePath: 'foo',
- imagesCount: 1,
- hideExpirationPolicyData: true,
- });
-
- const text = findExpirationPolicySubHeader();
- expect(text.exists()).toBe(false);
- });
- });
- });
- });
-
- describe('info messages', () => {
- describe('default message', () => {
- it('is correctly bound to title_area props', () => {
- mountComponent({ helpPagePath: 'foo' });
-
- expect(findTitleArea().props('infoMessages')).toEqual([
- { text: LIST_INTRO_TEXT, link: 'foo' },
- ]);
- });
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js b/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
deleted file mode 100644
index 487f33594c1..00000000000
--- a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import { mount } from '@vue/test-utils';
-
-import component from '~/registry/explorer/components/registry_breadcrumb.vue';
-
-describe('Registry Breadcrumb', () => {
- let wrapper;
- const nameGenerator = jest.fn();
-
- const routes = [
- { name: 'list', path: '/', meta: { nameGenerator, root: true } },
- { name: 'details', path: '/:id', meta: { nameGenerator } },
- ];
-
- const mountComponent = ($route) => {
- wrapper = mount(component, {
- mocks: {
- $route,
- $router: {
- options: {
- routes,
- },
- },
- },
- });
- };
-
- beforeEach(() => {
- nameGenerator.mockClear();
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('when is rootRoute', () => {
- beforeEach(() => {
- mountComponent(routes[0]);
- });
-
- it('renders', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('contains only a single router-link to list', () => {
- const links = wrapper.findAll('a');
-
- expect(links).toHaveLength(1);
- expect(links.at(0).attributes('href')).toBe('/');
- });
-
- it('the link text is calculated by nameGenerator', () => {
- expect(nameGenerator).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('when is not rootRoute', () => {
- beforeEach(() => {
- mountComponent(routes[1]);
- });
-
- it('renders', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('contains two router-links to list and details', () => {
- const links = wrapper.findAll('a');
-
- expect(links).toHaveLength(2);
- expect(links.at(0).attributes('href')).toBe('/');
- expect(links.at(1).attributes('href')).toBe('#');
- });
-
- it('the link text is calculated by nameGenerator', () => {
- expect(nameGenerator).toHaveBeenCalledTimes(2);
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/pages/details_spec.js b/spec/frontend/registry/explorer/pages/details_spec.js
deleted file mode 100644
index 21af9dcc60f..00000000000
--- a/spec/frontend/registry/explorer/pages/details_spec.js
+++ /dev/null
@@ -1,521 +0,0 @@
-import { GlKeysetPagination } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
-import DeleteImage from '~/registry/explorer/components/delete_image.vue';
-import DeleteAlert from '~/registry/explorer/components/details_page/delete_alert.vue';
-import DetailsHeader from '~/registry/explorer/components/details_page/details_header.vue';
-import EmptyTagsState from '~/registry/explorer/components/details_page/empty_state.vue';
-import PartialCleanupAlert from '~/registry/explorer/components/details_page/partial_cleanup_alert.vue';
-import StatusAlert from '~/registry/explorer/components/details_page/status_alert.vue';
-import TagsList from '~/registry/explorer/components/details_page/tags_list.vue';
-import TagsLoader from '~/registry/explorer/components/details_page/tags_loader.vue';
-
-import {
- UNFINISHED_STATUS,
- DELETE_SCHEDULED,
- ALERT_DANGER_IMAGE,
- MISSING_OR_DELETED_IMAGE_BREADCRUMB,
- ROOT_IMAGE_TEXT,
-} from '~/registry/explorer/constants';
-import deleteContainerRepositoryTagsMutation from '~/registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql';
-import getContainerRepositoryDetailsQuery from '~/registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
-
-import component from '~/registry/explorer/pages/details.vue';
-import Tracking from '~/tracking';
-
-import {
- graphQLImageDetailsMock,
- graphQLDeleteImageRepositoryTagsMock,
- containerRepositoryMock,
- graphQLEmptyImageDetailsMock,
- tagsMock,
-} from '../mock_data';
-import { DeleteModal } from '../stubs';
-
-const localVue = createLocalVue();
-
-describe('Details Page', () => {
- let wrapper;
- let apolloProvider;
-
- const findDeleteModal = () => wrapper.find(DeleteModal);
- const findPagination = () => wrapper.find(GlKeysetPagination);
- const findTagsLoader = () => wrapper.find(TagsLoader);
- const findTagsList = () => wrapper.find(TagsList);
- const findDeleteAlert = () => wrapper.find(DeleteAlert);
- const findDetailsHeader = () => wrapper.find(DetailsHeader);
- const findEmptyState = () => wrapper.find(EmptyTagsState);
- const findPartialCleanupAlert = () => wrapper.find(PartialCleanupAlert);
- const findStatusAlert = () => wrapper.find(StatusAlert);
- const findDeleteImage = () => wrapper.find(DeleteImage);
-
- const routeId = 1;
-
- const breadCrumbState = {
- updateName: jest.fn(),
- };
-
- const cleanTags = tagsMock.map((t) => {
- const result = { ...t };
- // eslint-disable-next-line no-underscore-dangle
- delete result.__typename;
- return result;
- });
-
- const waitForApolloRequestRender = async () => {
- await waitForPromises();
- await wrapper.vm.$nextTick();
- };
-
- const mountComponent = ({
- resolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock()),
- mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock),
- options,
- config = {},
- } = {}) => {
- localVue.use(VueApollo);
-
- const requestHandlers = [
- [getContainerRepositoryDetailsQuery, resolver],
- [deleteContainerRepositoryTagsMutation, mutationResolver],
- ];
-
- apolloProvider = createMockApollo(requestHandlers);
-
- wrapper = shallowMount(component, {
- localVue,
- apolloProvider,
- stubs: {
- DeleteModal,
- DeleteImage,
- },
- mocks: {
- $route: {
- params: {
- id: routeId,
- },
- },
- },
- provide() {
- return {
- breadCrumbState,
- config,
- };
- },
- ...options,
- });
- };
-
- beforeEach(() => {
- jest.spyOn(Tracking, 'event');
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('when isLoading is true', () => {
- it('shows the loader', () => {
- mountComponent();
-
- expect(findTagsLoader().exists()).toBe(true);
- });
-
- it('does not show the list', () => {
- mountComponent();
-
- expect(findTagsList().exists()).toBe(false);
- });
- });
-
- describe('when the image does not exist', () => {
- it('does not show the default ui', async () => {
- mountComponent({ resolver: jest.fn().mockResolvedValue(graphQLEmptyImageDetailsMock) });
-
- await waitForApolloRequestRender();
-
- expect(findTagsLoader().exists()).toBe(false);
- expect(findDetailsHeader().exists()).toBe(false);
- expect(findTagsList().exists()).toBe(false);
- expect(findPagination().exists()).toBe(false);
- });
-
- it('shows an empty state message', async () => {
- mountComponent({ resolver: jest.fn().mockResolvedValue(graphQLEmptyImageDetailsMock) });
-
- await waitForApolloRequestRender();
-
- expect(findEmptyState().exists()).toBe(true);
- });
- });
-
- describe('list', () => {
- it('exists', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findTagsList().exists()).toBe(true);
- });
-
- it('has the correct props bound', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findTagsList().props()).toMatchObject({
- isMobile: false,
- });
- });
-
- describe('deleteEvent', () => {
- describe('single item', () => {
- let tagToBeDeleted;
- beforeEach(async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- [tagToBeDeleted] = cleanTags;
- findTagsList().vm.$emit('delete', [tagToBeDeleted]);
- });
-
- it('open the modal', async () => {
- expect(DeleteModal.methods.show).toHaveBeenCalled();
- });
-
- it('tracks a single delete event', () => {
- expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
- label: 'registry_tag_delete',
- });
- });
- });
-
- describe('multiple items', () => {
- beforeEach(async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- findTagsList().vm.$emit('delete', cleanTags);
- });
-
- it('open the modal', () => {
- expect(DeleteModal.methods.show).toHaveBeenCalled();
- });
-
- it('tracks a single delete event', () => {
- expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
- label: 'bulk_registry_tag_delete',
- });
- });
- });
- });
- });
-
- describe('modal', () => {
- it('exists', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findDeleteModal().exists()).toBe(true);
- });
-
- describe('cancel event', () => {
- it('tracks cancel_delete', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- findDeleteModal().vm.$emit('cancel');
-
- expect(Tracking.event).toHaveBeenCalledWith(undefined, 'cancel_delete', {
- label: 'registry_tag_delete',
- });
- });
- });
-
- describe('confirmDelete event', () => {
- let mutationResolver;
-
- beforeEach(() => {
- mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock);
- mountComponent({ mutationResolver });
-
- return waitForApolloRequestRender();
- });
- describe('when one item is selected to be deleted', () => {
- it('calls apollo mutation with the right parameters', async () => {
- findTagsList().vm.$emit('delete', [cleanTags[0]]);
-
- await wrapper.vm.$nextTick();
-
- findDeleteModal().vm.$emit('confirmDelete');
-
- expect(mutationResolver).toHaveBeenCalledWith(
- expect.objectContaining({ tagNames: [cleanTags[0].name] }),
- );
- });
- });
-
- describe('when more than one item is selected to be deleted', () => {
- it('calls apollo mutation with the right parameters', async () => {
- findTagsList().vm.$emit('delete', tagsMock);
-
- await wrapper.vm.$nextTick();
-
- findDeleteModal().vm.$emit('confirmDelete');
-
- expect(mutationResolver).toHaveBeenCalledWith(
- expect.objectContaining({ tagNames: tagsMock.map((t) => t.name) }),
- );
- });
- });
- });
- });
-
- describe('Header', () => {
- it('exists', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
- expect(findDetailsHeader().exists()).toBe(true);
- });
-
- it('has the correct props', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
- expect(findDetailsHeader().props()).toMatchObject({
- image: {
- name: containerRepositoryMock.name,
- project: {
- visibility: containerRepositoryMock.project.visibility,
- },
- },
- });
- });
- });
-
- describe('Delete Alert', () => {
- const config = {
- isAdmin: true,
- garbageCollectionHelpPagePath: 'baz',
- };
- const deleteAlertType = 'success_tag';
-
- it('exists', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
- expect(findDeleteAlert().exists()).toBe(true);
- });
-
- it('has the correct props', async () => {
- mountComponent({
- options: {
- data: () => ({
- deleteAlertType,
- }),
- },
- config,
- });
-
- await waitForApolloRequestRender();
-
- expect(findDeleteAlert().props()).toEqual({ ...config, deleteAlertType });
- });
- });
-
- describe('Partial Cleanup Alert', () => {
- const config = {
- runCleanupPoliciesHelpPagePath: 'foo',
- expirationPolicyHelpPagePath: 'bar',
- userCalloutsPath: 'call_out_path',
- userCalloutId: 'call_out_id',
- showUnfinishedTagCleanupCallout: true,
- };
-
- describe(`when expirationPolicyCleanupStatus is ${UNFINISHED_STATUS}`, () => {
- let resolver;
-
- beforeEach(() => {
- resolver = jest.fn().mockResolvedValue(
- graphQLImageDetailsMock({
- expirationPolicyCleanupStatus: UNFINISHED_STATUS,
- }),
- );
- });
-
- it('exists', async () => {
- mountComponent({ resolver, config });
-
- await waitForApolloRequestRender();
-
- expect(findPartialCleanupAlert().exists()).toBe(true);
- });
-
- it('has the correct props', async () => {
- mountComponent({ resolver, config });
-
- await waitForApolloRequestRender();
-
- expect(findPartialCleanupAlert().props()).toEqual({
- runCleanupPoliciesHelpPagePath: config.runCleanupPoliciesHelpPagePath,
- cleanupPoliciesHelpPagePath: config.expirationPolicyHelpPagePath,
- });
- });
-
- it('dismiss hides the component', async () => {
- jest.spyOn(axios, 'post').mockReturnValue();
-
- mountComponent({ resolver, config });
-
- await waitForApolloRequestRender();
-
- expect(findPartialCleanupAlert().exists()).toBe(true);
-
- findPartialCleanupAlert().vm.$emit('dismiss');
-
- await wrapper.vm.$nextTick();
-
- expect(axios.post).toHaveBeenCalledWith(config.userCalloutsPath, {
- feature_name: config.userCalloutId,
- });
- expect(findPartialCleanupAlert().exists()).toBe(false);
- });
-
- it('is hidden if the callout is dismissed', async () => {
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- expect(findPartialCleanupAlert().exists()).toBe(false);
- });
- });
-
- describe(`when expirationPolicyCleanupStatus is not ${UNFINISHED_STATUS}`, () => {
- it('the component is hidden', async () => {
- mountComponent({ config });
-
- await waitForApolloRequestRender();
-
- expect(findPartialCleanupAlert().exists()).toBe(false);
- });
- });
- });
-
- describe('Breadcrumb connection', () => {
- it('when the details are fetched updates the name', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(breadCrumbState.updateName).toHaveBeenCalledWith(containerRepositoryMock.name);
- });
-
- it(`when the image is missing set the breadcrumb to ${MISSING_OR_DELETED_IMAGE_BREADCRUMB}`, async () => {
- mountComponent({ resolver: jest.fn().mockResolvedValue(graphQLEmptyImageDetailsMock) });
-
- await waitForApolloRequestRender();
-
- expect(breadCrumbState.updateName).toHaveBeenCalledWith(MISSING_OR_DELETED_IMAGE_BREADCRUMB);
- });
-
- it(`when the image has no name set the breadcrumb to ${ROOT_IMAGE_TEXT}`, async () => {
- mountComponent({
- resolver: jest
- .fn()
- .mockResolvedValue(graphQLImageDetailsMock({ ...containerRepositoryMock, name: null })),
- });
-
- await waitForApolloRequestRender();
-
- expect(breadCrumbState.updateName).toHaveBeenCalledWith(ROOT_IMAGE_TEXT);
- });
- });
-
- describe('when the image has a status different from null', () => {
- const resolver = jest
- .fn()
- .mockResolvedValue(graphQLImageDetailsMock({ status: DELETE_SCHEDULED }));
- it('disables all the actions', async () => {
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- expect(findDetailsHeader().props('disabled')).toBe(true);
- expect(findTagsList().props('disabled')).toBe(true);
- });
-
- it('shows a status alert', async () => {
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- expect(findStatusAlert().exists()).toBe(true);
- expect(findStatusAlert().props()).toMatchObject({
- status: DELETE_SCHEDULED,
- });
- });
- });
-
- describe('delete the image', () => {
- const mountComponentAndDeleteImage = async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
- findDetailsHeader().vm.$emit('delete');
-
- await wrapper.vm.$nextTick();
- };
-
- it('on delete event it deletes the image', async () => {
- await mountComponentAndDeleteImage();
-
- findDeleteModal().vm.$emit('confirmDelete');
-
- expect(findDeleteImage().emitted('start')).toEqual([[]]);
- });
-
- it('binds the correct props to the modal', async () => {
- await mountComponentAndDeleteImage();
-
- expect(findDeleteModal().props()).toMatchObject({
- itemsToBeDeleted: [{ path: 'gitlab-org/gitlab-test/rails-12009' }],
- deleteImage: true,
- });
- });
-
- it('binds correctly to delete-image start and end events', async () => {
- mountComponent();
-
- findDeleteImage().vm.$emit('start');
-
- await wrapper.vm.$nextTick();
-
- expect(findTagsLoader().exists()).toBe(true);
-
- findDeleteImage().vm.$emit('end');
-
- await wrapper.vm.$nextTick();
-
- expect(findTagsLoader().exists()).toBe(false);
- });
-
- it('binds correctly to delete-image error event', async () => {
- mountComponent();
-
- findDeleteImage().vm.$emit('error');
-
- await wrapper.vm.$nextTick();
-
- expect(findDeleteAlert().props('deleteAlertType')).toBe(ALERT_DANGER_IMAGE);
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/pages/index_spec.js b/spec/frontend/registry/explorer/pages/index_spec.js
deleted file mode 100644
index b5f718b3e61..00000000000
--- a/spec/frontend/registry/explorer/pages/index_spec.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import component from '~/registry/explorer/pages/index.vue';
-
-describe('List Page', () => {
- let wrapper;
-
- const findRouterView = () => wrapper.find({ ref: 'router-view' });
-
- const mountComponent = () => {
- wrapper = shallowMount(component, {
- stubs: {
- RouterView: true,
- },
- });
- };
-
- beforeEach(() => {
- mountComponent();
- });
-
- it('has a router view', () => {
- expect(findRouterView().exists()).toBe(true);
- });
-});
diff --git a/spec/frontend/registry/explorer/pages/list_spec.js b/spec/frontend/registry/explorer/pages/list_spec.js
deleted file mode 100644
index e1f24a2b65b..00000000000
--- a/spec/frontend/registry/explorer/pages/list_spec.js
+++ /dev/null
@@ -1,597 +0,0 @@
-import { GlSkeletonLoader, GlSprintf, GlAlert } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
-import CleanupPolicyEnabledAlert from '~/packages_and_registries/shared/components/cleanup_policy_enabled_alert.vue';
-import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
-import DeleteImage from '~/registry/explorer/components/delete_image.vue';
-import CliCommands from '~/registry/explorer/components/list_page/cli_commands.vue';
-import GroupEmptyState from '~/registry/explorer/components/list_page/group_empty_state.vue';
-import ImageList from '~/registry/explorer/components/list_page/image_list.vue';
-import ProjectEmptyState from '~/registry/explorer/components/list_page/project_empty_state.vue';
-import RegistryHeader from '~/registry/explorer/components/list_page/registry_header.vue';
-import {
- DELETE_IMAGE_SUCCESS_MESSAGE,
- DELETE_IMAGE_ERROR_MESSAGE,
- SORT_FIELDS,
-} from '~/registry/explorer/constants';
-import deleteContainerRepositoryMutation from '~/registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql';
-import getContainerRepositoriesDetails from '~/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql';
-import component from '~/registry/explorer/pages/list.vue';
-import Tracking from '~/tracking';
-import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
-
-import { $toast } from '../../shared/mocks';
-import {
- graphQLImageListMock,
- graphQLImageDeleteMock,
- deletedContainerRepository,
- graphQLEmptyImageListMock,
- graphQLEmptyGroupImageListMock,
- pageInfo,
- graphQLProjectImageRepositoriesDetailsMock,
- dockerCommands,
-} from '../mock_data';
-import { GlModal, GlEmptyState } from '../stubs';
-
-const localVue = createLocalVue();
-
-describe('List Page', () => {
- let wrapper;
- let apolloProvider;
-
- const findDeleteModal = () => wrapper.findComponent(GlModal);
- const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
-
- const findEmptyState = () => wrapper.findComponent(GlEmptyState);
-
- const findCliCommands = () => wrapper.findComponent(CliCommands);
- const findProjectEmptyState = () => wrapper.findComponent(ProjectEmptyState);
- const findGroupEmptyState = () => wrapper.findComponent(GroupEmptyState);
- const findRegistryHeader = () => wrapper.findComponent(RegistryHeader);
-
- const findDeleteAlert = () => wrapper.findComponent(GlAlert);
- const findImageList = () => wrapper.findComponent(ImageList);
- const findRegistrySearch = () => wrapper.findComponent(RegistrySearch);
- const findEmptySearchMessage = () => wrapper.find('[data-testid="emptySearch"]');
- const findDeleteImage = () => wrapper.findComponent(DeleteImage);
- const findCleanupAlert = () => wrapper.findComponent(CleanupPolicyEnabledAlert);
-
- const waitForApolloRequestRender = async () => {
- jest.runOnlyPendingTimers();
- await waitForPromises();
- await nextTick();
- };
-
- const mountComponent = ({
- mocks,
- resolver = jest.fn().mockResolvedValue(graphQLImageListMock),
- detailsResolver = jest.fn().mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock),
- mutationResolver = jest.fn().mockResolvedValue(graphQLImageDeleteMock),
- config = { isGroupPage: false },
- query = {},
- } = {}) => {
- localVue.use(VueApollo);
-
- const requestHandlers = [
- [getContainerRepositoriesQuery, resolver],
- [getContainerRepositoriesDetails, detailsResolver],
- [deleteContainerRepositoryMutation, mutationResolver],
- ];
-
- apolloProvider = createMockApollo(requestHandlers);
-
- wrapper = shallowMount(component, {
- localVue,
- apolloProvider,
- stubs: {
- GlModal,
- GlEmptyState,
- GlSprintf,
- RegistryHeader,
- TitleArea,
- DeleteImage,
- },
- mocks: {
- $toast,
- $route: {
- name: 'foo',
- query,
- },
- ...mocks,
- },
- provide() {
- return {
- config,
- ...dockerCommands,
- };
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('contains registry header', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findRegistryHeader().exists()).toBe(true);
- expect(findRegistryHeader().props()).toMatchObject({
- imagesCount: 2,
- metadataLoading: false,
- });
- });
-
- describe.each([
- { error: 'connectionError', errorName: 'connection error' },
- { error: 'invalidPathError', errorName: 'invalid path error' },
- ])('handling $errorName', ({ error }) => {
- const config = {
- containersErrorImage: 'foo',
- helpPagePath: 'bar',
- isGroupPage: false,
- };
- config[error] = true;
-
- it('should show an empty state', () => {
- mountComponent({ config });
-
- expect(findEmptyState().exists()).toBe(true);
- });
-
- it('empty state should have an svg-path', () => {
- mountComponent({ config });
-
- expect(findEmptyState().props('svgPath')).toBe(config.containersErrorImage);
- });
-
- it('empty state should have a description', () => {
- mountComponent({ config });
-
- expect(findEmptyState().props('title')).toContain('connection error');
- });
-
- it('should not show the loading or default state', () => {
- mountComponent({ config });
-
- expect(findSkeletonLoader().exists()).toBe(false);
- expect(findImageList().exists()).toBe(false);
- });
- });
-
- describe('isLoading is true', () => {
- it('shows the skeleton loader', async () => {
- mountComponent();
-
- await nextTick();
-
- expect(findSkeletonLoader().exists()).toBe(true);
- });
-
- it('imagesList is not visible', () => {
- mountComponent();
-
- expect(findImageList().exists()).toBe(false);
- });
-
- it('cli commands is not visible', () => {
- mountComponent();
-
- expect(findCliCommands().exists()).toBe(false);
- });
-
- it('title has the metadataLoading props set to true', async () => {
- mountComponent();
-
- await nextTick();
-
- expect(findRegistryHeader().props('metadataLoading')).toBe(true);
- });
- });
-
- describe('list is empty', () => {
- describe('project page', () => {
- const resolver = jest.fn().mockResolvedValue(graphQLEmptyImageListMock);
-
- it('cli commands is not visible', async () => {
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- expect(findCliCommands().exists()).toBe(false);
- });
-
- it('project empty state is visible', async () => {
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- expect(findProjectEmptyState().exists()).toBe(true);
- });
- });
-
- describe('group page', () => {
- const resolver = jest.fn().mockResolvedValue(graphQLEmptyGroupImageListMock);
-
- const config = {
- isGroupPage: true,
- };
-
- it('group empty state is visible', async () => {
- mountComponent({ resolver, config });
-
- await waitForApolloRequestRender();
-
- expect(findGroupEmptyState().exists()).toBe(true);
- });
-
- it('cli commands is not visible', async () => {
- mountComponent({ resolver, config });
-
- await waitForApolloRequestRender();
-
- expect(findCliCommands().exists()).toBe(false);
- });
- });
- });
-
- describe('list is not empty', () => {
- describe('unfiltered state', () => {
- it('quick start is visible', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findCliCommands().exists()).toBe(true);
- });
-
- it('list component is visible', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findImageList().exists()).toBe(true);
- });
-
- describe('additional metadata', () => {
- it('is called on component load', async () => {
- const detailsResolver = jest
- .fn()
- .mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
- mountComponent({ detailsResolver });
-
- jest.runOnlyPendingTimers();
- await waitForPromises();
-
- expect(detailsResolver).toHaveBeenCalled();
- });
-
- it('does not block the list ui to show', async () => {
- const detailsResolver = jest.fn().mockRejectedValue();
- mountComponent({ detailsResolver });
-
- await waitForApolloRequestRender();
-
- expect(findImageList().exists()).toBe(true);
- });
-
- it('loading state is passed to list component', async () => {
- // this is a promise that never resolves, to trick apollo to think that this request is still loading
- const detailsResolver = jest.fn().mockImplementation(() => new Promise(() => {}));
-
- mountComponent({ detailsResolver });
- await waitForApolloRequestRender();
-
- expect(findImageList().props('metadataLoading')).toBe(true);
- });
- });
-
- describe('delete image', () => {
- const selectImageForDeletion = async () => {
- await waitForApolloRequestRender();
-
- findImageList().vm.$emit('delete', deletedContainerRepository);
- };
-
- it('should call deleteItem when confirming deletion', async () => {
- const mutationResolver = jest.fn().mockResolvedValue(graphQLImageDeleteMock);
- mountComponent({ mutationResolver });
-
- await selectImageForDeletion();
-
- findDeleteModal().vm.$emit('primary');
- await waitForApolloRequestRender();
-
- expect(wrapper.vm.itemToDelete).toEqual(deletedContainerRepository);
-
- const updatedImage = findImageList()
- .props('images')
- .find((i) => i.id === deletedContainerRepository.id);
-
- expect(updatedImage.status).toBe(deletedContainerRepository.status);
- });
-
- it('should show a success alert when delete request is successful', async () => {
- mountComponent();
-
- await selectImageForDeletion();
-
- findDeleteImage().vm.$emit('success');
- await nextTick();
-
- const alert = findDeleteAlert();
- expect(alert.exists()).toBe(true);
- expect(alert.text().replace(/\s\s+/gm, ' ')).toBe(
- DELETE_IMAGE_SUCCESS_MESSAGE.replace('%{title}', wrapper.vm.itemToDelete.path),
- );
- });
-
- describe('when delete request fails it shows an alert', () => {
- it('user recoverable error', async () => {
- mountComponent();
-
- await selectImageForDeletion();
-
- findDeleteImage().vm.$emit('error');
- await nextTick();
-
- const alert = findDeleteAlert();
- expect(alert.exists()).toBe(true);
- expect(alert.text().replace(/\s\s+/gm, ' ')).toBe(
- DELETE_IMAGE_ERROR_MESSAGE.replace('%{title}', wrapper.vm.itemToDelete.path),
- );
- });
- });
- });
- });
-
- describe('search and sorting', () => {
- const doSearch = async () => {
- await waitForApolloRequestRender();
- findRegistrySearch().vm.$emit('filter:changed', [
- { type: FILTERED_SEARCH_TERM, value: { data: 'centos6' } },
- ]);
-
- findRegistrySearch().vm.$emit('filter:submit');
-
- await nextTick();
- };
-
- it('has a search box element', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- const registrySearch = findRegistrySearch();
- expect(registrySearch.exists()).toBe(true);
- expect(registrySearch.props()).toMatchObject({
- filter: [],
- sorting: { orderBy: 'UPDATED', sort: 'desc' },
- sortableFields: SORT_FIELDS,
- tokens: [],
- });
- });
-
- it('performs sorting', async () => {
- const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- findRegistrySearch().vm.$emit('sorting:changed', { sort: 'asc' });
- await nextTick();
-
- expect(resolver).toHaveBeenCalledWith(expect.objectContaining({ sort: 'UPDATED_DESC' }));
- });
-
- it('performs a search', async () => {
- const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
- mountComponent({ resolver });
-
- await doSearch();
-
- expect(resolver).toHaveBeenCalledWith(expect.objectContaining({ name: 'centos6' }));
- });
-
- it('when search result is empty displays an empty search message', async () => {
- const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
- const detailsResolver = jest
- .fn()
- .mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
- mountComponent({ resolver, detailsResolver });
-
- await waitForApolloRequestRender();
-
- resolver.mockResolvedValue(graphQLEmptyImageListMock);
- detailsResolver.mockResolvedValue(graphQLEmptyImageListMock);
-
- await doSearch();
-
- expect(findEmptySearchMessage().exists()).toBe(true);
- });
- });
-
- describe('pagination', () => {
- it('prev-page event triggers a fetchMore request', async () => {
- const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
- const detailsResolver = jest
- .fn()
- .mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
- mountComponent({ resolver, detailsResolver });
-
- await waitForApolloRequestRender();
-
- findImageList().vm.$emit('prev-page');
- await nextTick();
-
- expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({ before: pageInfo.startCursor }),
- );
- expect(detailsResolver).toHaveBeenCalledWith(
- expect.objectContaining({ before: pageInfo.startCursor }),
- );
- });
-
- it('next-page event triggers a fetchMore request', async () => {
- const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
- const detailsResolver = jest
- .fn()
- .mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
- mountComponent({ resolver, detailsResolver });
-
- await waitForApolloRequestRender();
-
- findImageList().vm.$emit('next-page');
- await nextTick();
-
- expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({ after: pageInfo.endCursor }),
- );
- expect(detailsResolver).toHaveBeenCalledWith(
- expect.objectContaining({ after: pageInfo.endCursor }),
- );
- });
- });
- });
-
- describe('modal', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- it('exists', () => {
- expect(findDeleteModal().exists()).toBe(true);
- });
-
- it('contains a description with the path of the item to delete', async () => {
- findImageList().vm.$emit('delete', { path: 'foo' });
- await nextTick();
- expect(findDeleteModal().html()).toContain('foo');
- });
- });
-
- describe('tracking', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- const testTrackingCall = (action) => {
- expect(Tracking.event).toHaveBeenCalledWith(undefined, action, {
- label: 'registry_repository_delete',
- });
- };
-
- beforeEach(() => {
- jest.spyOn(Tracking, 'event');
- });
-
- it('send an event when delete button is clicked', () => {
- findImageList().vm.$emit('delete', {});
-
- testTrackingCall('click_button');
- });
-
- it('send an event when cancel is pressed on modal', () => {
- const deleteModal = findDeleteModal();
- deleteModal.vm.$emit('cancel');
- testTrackingCall('cancel_delete');
- });
-
- it('send an event when the deletion starts', () => {
- findDeleteImage().vm.$emit('start');
- testTrackingCall('confirm_delete');
- });
- });
-
- describe('url query string handling', () => {
- const defaultQueryParams = {
- search: [1, 2],
- sort: 'asc',
- orderBy: 'CREATED',
- };
- const queryChangePayload = 'foo';
-
- it('query:updated event pushes the new query to the router', async () => {
- const push = jest.fn();
- mountComponent({ mocks: { $router: { push } } });
-
- await nextTick();
-
- findRegistrySearch().vm.$emit('query:changed', queryChangePayload);
-
- expect(push).toHaveBeenCalledWith({ query: queryChangePayload });
- });
-
- it('graphql API call has the variables set from the URL', async () => {
- const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
- mountComponent({ query: defaultQueryParams, resolver });
-
- await nextTick();
-
- expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({
- name: 1,
- sort: 'CREATED_ASC',
- }),
- );
- });
-
- it.each`
- sort | orderBy | search | payload
- ${'ASC'} | ${undefined} | ${undefined} | ${{ sort: 'UPDATED_ASC' }}
- ${undefined} | ${'bar'} | ${undefined} | ${{ sort: 'BAR_DESC' }}
- ${'ASC'} | ${'bar'} | ${undefined} | ${{ sort: 'BAR_ASC' }}
- ${undefined} | ${undefined} | ${undefined} | ${{}}
- ${undefined} | ${undefined} | ${['one']} | ${{ name: 'one' }}
- ${undefined} | ${undefined} | ${['one', 'two']} | ${{ name: 'one' }}
- ${undefined} | ${'UPDATED'} | ${['one', 'two']} | ${{ name: 'one', sort: 'UPDATED_DESC' }}
- ${'ASC'} | ${'UPDATED'} | ${['one', 'two']} | ${{ name: 'one', sort: 'UPDATED_ASC' }}
- `(
- 'with sort equal to $sort, orderBy equal to $orderBy, search set to $search API call has the variables set as $payload',
- async ({ sort, orderBy, search, payload }) => {
- const resolver = jest.fn().mockResolvedValue({ sort, orderBy });
- mountComponent({ query: { sort, orderBy, search }, resolver });
-
- await nextTick();
-
- expect(resolver).toHaveBeenCalledWith(expect.objectContaining(payload));
- },
- );
- });
-
- describe('cleanup is on alert', () => {
- it('exist when showCleanupPolicyOnAlert is true and has the correct props', async () => {
- mountComponent({
- config: {
- showCleanupPolicyOnAlert: true,
- projectPath: 'foo',
- isGroupPage: false,
- cleanupPoliciesSettingsPath: 'bar',
- },
- });
-
- await waitForApolloRequestRender();
-
- expect(findCleanupAlert().exists()).toBe(true);
- expect(findCleanupAlert().props()).toMatchObject({
- projectPath: 'foo',
- cleanupPoliciesSettingsPath: 'bar',
- });
- });
-
- it('is hidden when showCleanupPolicyOnAlert is false', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findCleanupAlert().exists()).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/stubs.js b/spec/frontend/registry/explorer/stubs.js
deleted file mode 100644
index 4f65e73d3fa..00000000000
--- a/spec/frontend/registry/explorer/stubs.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import {
- GlModal as RealGlModal,
- GlEmptyState as RealGlEmptyState,
- GlSkeletonLoader as RealGlSkeletonLoader,
- GlDropdown as RealGlDropdown,
-} from '@gitlab/ui';
-import { RouterLinkStub } from '@vue/test-utils';
-import { stubComponent } from 'helpers/stub_component';
-import RealDeleteModal from '~/registry/explorer/components/details_page/delete_modal.vue';
-import RealListItem from '~/vue_shared/components/registry/list_item.vue';
-
-export const GlModal = stubComponent(RealGlModal, {
- template: '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-ok"></slot></div>',
- methods: {
- show: jest.fn(),
- },
-});
-
-export const GlEmptyState = stubComponent(RealGlEmptyState, {
- template: '<div><slot name="description"></slot></div>',
-});
-
-export const RouterLink = RouterLinkStub;
-
-export const DeleteModal = stubComponent(RealDeleteModal, {
- methods: {
- show: jest.fn(),
- },
-});
-
-export const GlSkeletonLoader = stubComponent(RealGlSkeletonLoader);
-
-export const ListItem = {
- ...RealListItem,
- data() {
- return {
- detailsSlots: [],
- isDetailsShown: true,
- };
- },
-};
-
-export const GlDropdown = stubComponent(RealGlDropdown, {
- template: '<div><slot></slot></div>',
-});
diff --git a/spec/frontend/related_merge_requests/components/related_merge_requests_spec.js b/spec/frontend/related_merge_requests/components/related_merge_requests_spec.js
index 67f62815720..486fb699275 100644
--- a/spec/frontend/related_merge_requests/components/related_merge_requests_spec.js
+++ b/spec/frontend/related_merge_requests/components/related_merge_requests_spec.js
@@ -66,8 +66,8 @@ describe('RelatedMergeRequests', () => {
describe('template', () => {
it('should render related merge request items', () => {
- expect(wrapper.find('.js-items-count').text()).toEqual('2');
- expect(wrapper.findAll(RelatedIssuableItem).length).toEqual(2);
+ expect(wrapper.find('[data-testid="count"]').text()).toBe('2');
+ expect(wrapper.findAll(RelatedIssuableItem)).toHaveLength(2);
const props = wrapper.findAll(RelatedIssuableItem).at(1).props();
const data = mockData[1];
diff --git a/spec/frontend/releases/components/tag_field_new_spec.js b/spec/frontend/releases/components/tag_field_new_spec.js
index 114e46ce64b..0f416e46dba 100644
--- a/spec/frontend/releases/components/tag_field_new_spec.js
+++ b/spec/frontend/releases/components/tag_field_new_spec.js
@@ -1,6 +1,7 @@
import { GlDropdownItem } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import Vue from 'vue';
+import { __ } from '~/locale';
import TagFieldNew from '~/releases/components/tag_field_new.vue';
import createStore from '~/releases/stores';
import createEditNewModule from '~/releases/stores/modules/edit_new';
@@ -84,7 +85,8 @@ describe('releases/components/tag_field_new', () => {
beforeEach(() => createComponent());
it('renders a label', () => {
- expect(findTagNameFormGroup().attributes().label).toBe('Tag name');
+ expect(findTagNameFormGroup().attributes().label).toBe(__('Tag name'));
+ expect(findTagNameFormGroup().props().labelDescription).toBe(__('*Required'));
});
describe('when the user selects a new tag name', () => {
diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js
index 59db537282b..d40e97bf5a3 100644
--- a/spec/frontend/repository/components/blob_content_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_content_viewer_spec.js
@@ -1,5 +1,5 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
+import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
@@ -19,6 +19,15 @@ import TextViewer from '~/repository/components/blob_viewers/text_viewer.vue';
import blobInfoQuery from '~/repository/queries/blob_info.query.graphql';
import { redirectTo } from '~/lib/utils/url_utility';
import { isLoggedIn } from '~/lib/utils/common_utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import {
+ simpleViewerMock,
+ richViewerMock,
+ projectMock,
+ userPermissionsMock,
+ propsMock,
+ refMock,
+} from '../mock_data';
jest.mock('~/repository/components/blob_viewers');
jest.mock('~/lib/utils/url_utility');
@@ -27,151 +36,63 @@ jest.mock('~/lib/utils/common_utils');
let wrapper;
let mockResolver;
-const simpleMockData = {
- name: 'some_file.js',
- size: 123,
- rawSize: 123,
- rawTextBlob: 'raw content',
- type: 'text',
- fileType: 'text',
- tooLarge: false,
- path: 'some_file.js',
- webPath: 'some_file.js',
- editBlobPath: 'some_file.js/edit',
- ideEditPath: 'some_file.js/ide/edit',
- forkAndEditPath: 'some_file.js/fork/edit',
- ideForkAndEditPath: 'some_file.js/fork/ide',
- canModifyBlob: true,
- storedExternally: false,
- rawPath: 'some_file.js',
- externalStorageUrl: 'some_file.js',
- replacePath: 'some_file.js/replace',
- deletePath: 'some_file.js/delete',
- simpleViewer: {
- fileType: 'text',
- tooLarge: false,
- type: 'simple',
- renderError: null,
- },
- richViewer: null,
-};
-const richMockData = {
- ...simpleMockData,
- richViewer: {
- fileType: 'markup',
- tooLarge: false,
- type: 'rich',
- renderError: null,
- },
-};
-
-const projectMockData = {
- userPermissions: {
- pushCode: true,
- downloadCode: true,
- createMergeRequestIn: true,
- forkProject: true,
- },
- repository: {
- empty: false,
- },
-};
-
const localVue = createLocalVue();
const mockAxios = new MockAdapter(axios);
-const createComponentWithApollo = (mockData = {}, inject = {}) => {
+const createComponent = async (mockData = {}, mountFn = shallowMount) => {
localVue.use(VueApollo);
- const defaultPushCode = projectMockData.userPermissions.pushCode;
- const defaultDownloadCode = projectMockData.userPermissions.downloadCode;
- const defaultEmptyRepo = projectMockData.repository.empty;
const {
- blobs,
- emptyRepo = defaultEmptyRepo,
- canPushCode = defaultPushCode,
- canDownloadCode = defaultDownloadCode,
- createMergeRequestIn = projectMockData.userPermissions.createMergeRequestIn,
- forkProject = projectMockData.userPermissions.forkProject,
- pathLocks = [],
+ blob = simpleViewerMock,
+ empty = projectMock.repository.empty,
+ pushCode = userPermissionsMock.pushCode,
+ forkProject = userPermissionsMock.forkProject,
+ downloadCode = userPermissionsMock.downloadCode,
+ createMergeRequestIn = userPermissionsMock.createMergeRequestIn,
+ isBinary,
+ inject = {},
} = mockData;
- mockResolver = jest.fn().mockResolvedValue({
- data: {
- project: {
- id: '1234',
- userPermissions: {
- pushCode: canPushCode,
- downloadCode: canDownloadCode,
- createMergeRequestIn,
- forkProject,
- },
- pathLocks: {
- nodes: pathLocks,
- },
- repository: {
- empty: emptyRepo,
- blobs: {
- nodes: [blobs],
- },
- },
- },
+ const project = {
+ ...projectMock,
+ userPermissions: {
+ pushCode,
+ forkProject,
+ downloadCode,
+ createMergeRequestIn,
+ },
+ repository: {
+ empty,
+ blobs: { nodes: [blob] },
},
+ };
+
+ mockResolver = jest.fn().mockResolvedValue({
+ data: { isBinary, project },
});
const fakeApollo = createMockApollo([[blobInfoQuery, mockResolver]]);
- wrapper = shallowMount(BlobContentViewer, {
- localVue,
- apolloProvider: fakeApollo,
- propsData: {
- path: 'some_file.js',
- projectPath: 'some/path',
- },
- mixins: [
- {
- data: () => ({ ref: 'default-ref' }),
- },
- ],
- provide: {
- ...inject,
- },
- });
-};
+ wrapper = extendedWrapper(
+ mountFn(BlobContentViewer, {
+ localVue,
+ apolloProvider: fakeApollo,
+ propsData: propsMock,
+ mixins: [{ data: () => ({ ref: refMock }) }],
+ provide: { ...inject },
+ }),
+ );
-const createFactory = (mountFn) => (
- { props = {}, mockData = {}, stubs = {} } = {},
- loading = false,
-) => {
- wrapper = mountFn(BlobContentViewer, {
- propsData: {
- path: 'some_file.js',
- projectPath: 'some/path',
- ...props,
- },
- mocks: {
- $apollo: {
- queries: {
- project: {
- loading,
- refetch: jest.fn(),
- },
- },
- },
- },
- stubs,
- });
+ wrapper.setData({ project, isBinary });
- wrapper.setData(mockData);
+ await waitForPromises();
};
-const factory = createFactory(shallowMount);
-const fullFactory = createFactory(mount);
-
describe('Blob content viewer component', () => {
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findBlobHeader = () => wrapper.findComponent(BlobHeader);
const findBlobEdit = () => wrapper.findComponent(BlobEdit);
+ const findPipelineEditor = () => wrapper.findByTestId('pipeline-editor');
const findBlobContent = () => wrapper.findComponent(BlobContent);
const findBlobButtonGroup = () => wrapper.findComponent(BlobButtonGroup);
const findForkSuggestion = () => wrapper.findComponent(ForkSuggestion);
@@ -187,25 +108,24 @@ describe('Blob content viewer component', () => {
});
it('renders a GlLoadingIcon component', () => {
- factory({ mockData: { blobInfo: simpleMockData } }, true);
+ createComponent();
expect(findLoadingIcon().exists()).toBe(true);
});
describe('simple viewer', () => {
- beforeEach(() => {
- factory({ mockData: { blobInfo: simpleMockData } });
- });
+ it('renders a BlobHeader component', async () => {
+ await createComponent();
- it('renders a BlobHeader component', () => {
expect(findBlobHeader().props('activeViewerType')).toEqual('simple');
expect(findBlobHeader().props('hasRenderError')).toEqual(false);
expect(findBlobHeader().props('hideViewerSwitcher')).toEqual(true);
- expect(findBlobHeader().props('blob')).toEqual(simpleMockData);
+ expect(findBlobHeader().props('blob')).toEqual(simpleViewerMock);
});
- it('renders a BlobContent component', () => {
- expect(findBlobContent().props('loading')).toEqual(false);
+ it('renders a BlobContent component', async () => {
+ await createComponent();
+
expect(findBlobContent().props('isRawContent')).toBe(true);
expect(findBlobContent().props('activeViewer')).toEqual({
fileType: 'text',
@@ -217,8 +137,7 @@ describe('Blob content viewer component', () => {
describe('legacy viewers', () => {
it('loads a legacy viewer when a viewer component is not available', async () => {
- createComponentWithApollo({ blobs: { ...simpleMockData, fileType: 'unknown' } });
- await waitForPromises();
+ await createComponent({ blob: { ...simpleViewerMock, fileType: 'unknown' } });
expect(mockAxios.history.get).toHaveLength(1);
expect(mockAxios.history.get[0].url).toEqual('some_file.js?format=json&viewer=simple');
@@ -227,21 +146,18 @@ describe('Blob content viewer component', () => {
});
describe('rich viewer', () => {
- beforeEach(() => {
- factory({
- mockData: { blobInfo: richMockData, activeViewerType: 'rich' },
- });
- });
+ it('renders a BlobHeader component', async () => {
+ await createComponent({ blob: richViewerMock });
- it('renders a BlobHeader component', () => {
expect(findBlobHeader().props('activeViewerType')).toEqual('rich');
expect(findBlobHeader().props('hasRenderError')).toEqual(false);
expect(findBlobHeader().props('hideViewerSwitcher')).toEqual(false);
- expect(findBlobHeader().props('blob')).toEqual(richMockData);
+ expect(findBlobHeader().props('blob')).toEqual(richViewerMock);
});
- it('renders a BlobContent component', () => {
- expect(findBlobContent().props('loading')).toEqual(false);
+ it('renders a BlobContent component', async () => {
+ await createComponent({ blob: richViewerMock });
+
expect(findBlobContent().props('isRawContent')).toBe(true);
expect(findBlobContent().props('activeViewer')).toEqual({
fileType: 'markup',
@@ -252,6 +168,8 @@ describe('Blob content viewer component', () => {
});
it('updates viewer type when viewer changed is clicked', async () => {
+ await createComponent({ blob: richViewerMock });
+
expect(findBlobContent().props('activeViewer')).toEqual(
expect.objectContaining({
type: 'rich',
@@ -273,8 +191,7 @@ describe('Blob content viewer component', () => {
describe('legacy viewers', () => {
it('loads a legacy viewer when a viewer component is not available', async () => {
- createComponentWithApollo({ blobs: { ...richMockData, fileType: 'unknown' } });
- await waitForPromises();
+ await createComponent({ blob: { ...richViewerMock, fileType: 'unknown' } });
expect(mockAxios.history.get).toHaveLength(1);
expect(mockAxios.history.get[0].url).toEqual('some_file.js?format=json&viewer=rich');
@@ -287,9 +204,9 @@ describe('Blob content viewer component', () => {
viewerProps.mockRestore();
});
- it('does not render a BlobContent component if a Blob viewer is available', () => {
- loadViewer.mockReturnValueOnce(() => true);
- factory({ mockData: { blobInfo: richMockData } });
+ it('does not render a BlobContent component if a Blob viewer is available', async () => {
+ loadViewer.mockReturnValue(() => true);
+ await createComponent({ blob: richViewerMock });
expect(findBlobContent().exists()).toBe(false);
});
@@ -305,15 +222,13 @@ describe('Blob content viewer component', () => {
loadViewer.mockReturnValue(loadViewerReturnValue);
viewerProps.mockReturnValue(viewerPropsReturnValue);
- factory({
- mockData: {
- blobInfo: {
- ...simpleMockData,
- fileType: null,
- simpleViewer: {
- ...simpleMockData.simpleViewer,
- fileType: viewer,
- },
+ createComponent({
+ blob: {
+ ...simpleViewerMock,
+ fileType: 'null',
+ simpleViewer: {
+ ...simpleViewerMock.simpleViewer,
+ fileType: viewer,
},
},
});
@@ -327,18 +242,10 @@ describe('Blob content viewer component', () => {
});
describe('BlobHeader action slot', () => {
- const { ideEditPath, editBlobPath } = simpleMockData;
+ const { ideEditPath, editBlobPath } = simpleViewerMock;
it('renders BlobHeaderEdit buttons in simple viewer', async () => {
- fullFactory({
- mockData: { blobInfo: simpleMockData },
- stubs: {
- BlobContent: true,
- BlobReplace: true,
- },
- });
-
- await nextTick();
+ await createComponent({ inject: { BlobContent: true, BlobReplace: true } }, mount);
expect(findBlobEdit().props()).toMatchObject({
editPath: editBlobPath,
@@ -348,15 +255,7 @@ describe('Blob content viewer component', () => {
});
it('renders BlobHeaderEdit button in rich viewer', async () => {
- fullFactory({
- mockData: { blobInfo: richMockData },
- stubs: {
- BlobContent: true,
- BlobReplace: true,
- },
- });
-
- await nextTick();
+ await createComponent({ blob: richViewerMock }, mount);
expect(findBlobEdit().props()).toMatchObject({
editPath: editBlobPath,
@@ -366,15 +265,7 @@ describe('Blob content viewer component', () => {
});
it('renders BlobHeaderEdit button for binary files', async () => {
- fullFactory({
- mockData: { blobInfo: richMockData, isBinary: true },
- stubs: {
- BlobContent: true,
- BlobReplace: true,
- },
- });
-
- await nextTick();
+ await createComponent({ blob: richViewerMock, isBinary: true }, mount);
expect(findBlobEdit().props()).toMatchObject({
editPath: editBlobPath,
@@ -383,42 +274,36 @@ describe('Blob content viewer component', () => {
});
});
- describe('blob header binary file', () => {
- it.each([richMockData, { simpleViewer: { fileType: 'download' } }])(
- 'passes the correct isBinary value when viewing a binary file',
- async (blobInfo) => {
- fullFactory({
- mockData: {
- blobInfo,
- isBinary: true,
- },
- stubs: { BlobContent: true, BlobReplace: true },
- });
+ it('renders Pipeline Editor button for .gitlab-ci files', async () => {
+ const pipelineEditorPath = 'some/path/.gitlab-ce';
+ const blob = { ...simpleViewerMock, pipelineEditorPath };
+ await createComponent({ blob, inject: { BlobContent: true, BlobReplace: true } }, mount);
- await nextTick();
+ expect(findPipelineEditor().exists()).toBe(true);
+ expect(findPipelineEditor().attributes('href')).toBe(pipelineEditorPath);
+ });
- expect(findBlobHeader().props('isBinary')).toBe(true);
- },
- );
+ describe('blob header binary file', () => {
+ it('passes the correct isBinary value when viewing a binary file', async () => {
+ await createComponent({ blob: richViewerMock, isBinary: true });
+
+ expect(findBlobHeader().props('isBinary')).toBe(true);
+ });
it('passes the correct header props when viewing a non-text file', async () => {
- fullFactory({
- mockData: {
- blobInfo: {
- ...simpleMockData,
+ await createComponent(
+ {
+ blob: {
+ ...simpleViewerMock,
simpleViewer: {
- ...simpleMockData.simpleViewer,
+ ...simpleViewerMock.simpleViewer,
fileType: 'image',
},
},
+ isBinary: true,
},
- stubs: {
- BlobContent: true,
- BlobReplace: true,
- },
- });
-
- await nextTick();
+ mount,
+ );
expect(findBlobHeader().props('hideViewerSwitcher')).toBe(true);
expect(findBlobHeader().props('isBinary')).toBe(true);
@@ -427,27 +312,16 @@ describe('Blob content viewer component', () => {
});
describe('BlobButtonGroup', () => {
- const { name, path, replacePath, webPath } = simpleMockData;
+ const { name, path, replacePath, webPath } = simpleViewerMock;
const {
userPermissions: { pushCode, downloadCode },
repository: { empty },
- } = projectMockData;
+ } = projectMock;
it('renders component', async () => {
window.gon.current_user_id = 1;
- fullFactory({
- mockData: {
- blobInfo: simpleMockData,
- project: { userPermissions: { pushCode, downloadCode }, repository: { empty } },
- },
- stubs: {
- BlobContent: true,
- BlobButtonGroup: true,
- },
- });
-
- await nextTick();
+ await createComponent({ pushCode, downloadCode, empty }, mount);
expect(findBlobButtonGroup().props()).toMatchObject({
name,
@@ -467,21 +341,14 @@ describe('Blob content viewer component', () => {
${false} | ${true} | ${false}
${true} | ${false} | ${false}
`('passes the correct lock states', async ({ canPushCode, canDownloadCode, canLock }) => {
- fullFactory({
- mockData: {
- blobInfo: simpleMockData,
- project: {
- userPermissions: { pushCode: canPushCode, downloadCode: canDownloadCode },
- repository: { empty },
- },
+ await createComponent(
+ {
+ pushCode: canPushCode,
+ downloadCode: canDownloadCode,
+ empty,
},
- stubs: {
- BlobContent: true,
- BlobButtonGroup: true,
- },
- });
-
- await nextTick();
+ mount,
+ );
expect(findBlobButtonGroup().props('canLock')).toBe(canLock);
});
@@ -489,15 +356,7 @@ describe('Blob content viewer component', () => {
it('does not render if not logged in', async () => {
isLoggedIn.mockReturnValueOnce(false);
- fullFactory({
- mockData: { blobInfo: simpleMockData },
- stubs: {
- BlobContent: true,
- BlobReplace: true,
- },
- });
-
- await nextTick();
+ await createComponent();
expect(findBlobButtonGroup().exists()).toBe(false);
});
@@ -506,10 +365,7 @@ describe('Blob content viewer component', () => {
describe('blob info query', () => {
it('is called with originalBranch value if the prop has a value', async () => {
- const inject = { originalBranch: 'some-branch' };
- createComponentWithApollo({ blobs: simpleMockData }, inject);
-
- await waitForPromises();
+ await createComponent({ inject: { originalBranch: 'some-branch' } });
expect(mockResolver).toHaveBeenCalledWith(
expect.objectContaining({
@@ -519,10 +375,7 @@ describe('Blob content viewer component', () => {
});
it('is called with ref value if the originalBranch prop has no value', async () => {
- const inject = { originalBranch: null };
- createComponentWithApollo({ blobs: simpleMockData }, inject);
-
- await waitForPromises();
+ await createComponent();
expect(mockResolver).toHaveBeenCalledWith(
expect.objectContaining({
@@ -533,24 +386,16 @@ describe('Blob content viewer component', () => {
});
describe('edit blob', () => {
- beforeEach(() => {
- fullFactory({
- mockData: { blobInfo: simpleMockData },
- stubs: {
- BlobContent: true,
- BlobReplace: true,
- },
- });
- });
+ beforeEach(() => createComponent({}, mount));
it('simple edit redirects to the simple editor', () => {
findBlobEdit().vm.$emit('edit', 'simple');
- expect(redirectTo).toHaveBeenCalledWith(simpleMockData.editBlobPath);
+ expect(redirectTo).toHaveBeenCalledWith(simpleViewerMock.editBlobPath);
});
it('IDE edit redirects to the IDE editor', () => {
findBlobEdit().vm.$emit('edit', 'ide');
- expect(redirectTo).toHaveBeenCalledWith(simpleMockData.ideEditPath);
+ expect(redirectTo).toHaveBeenCalledWith(simpleViewerMock.ideEditPath);
});
it.each`
@@ -569,16 +414,14 @@ describe('Blob content viewer component', () => {
showForkSuggestion,
}) => {
isLoggedIn.mockReturnValueOnce(loggedIn);
- fullFactory({
- mockData: {
- blobInfo: { ...simpleMockData, canModifyBlob },
- project: { userPermissions: { createMergeRequestIn, forkProject } },
+ await createComponent(
+ {
+ blob: { ...simpleViewerMock, canModifyBlob },
+ createMergeRequestIn,
+ forkProject,
},
- stubs: {
- BlobContent: true,
- BlobButtonGroup: true,
- },
- });
+ mount,
+ );
findBlobEdit().vm.$emit('edit', 'simple');
await nextTick();
diff --git a/spec/frontend/repository/components/upload_blob_modal_spec.js b/spec/frontend/repository/components/upload_blob_modal_spec.js
index 08a6583b60c..36847107558 100644
--- a/spec/frontend/repository/components/upload_blob_modal_spec.js
+++ b/spec/frontend/repository/components/upload_blob_modal_spec.js
@@ -6,11 +6,9 @@ import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
import { visitUrl } from '~/lib/utils/url_utility';
-import { trackFileUploadEvent } from '~/projects/upload_file_experiment_tracking';
import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
import UploadDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
-jest.mock('~/projects/upload_file_experiment_tracking');
jest.mock('~/flash');
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn(),
@@ -162,10 +160,6 @@ describe('UploadBlobModal', () => {
await waitForPromises();
});
- it('tracks the click_upload_modal_trigger event when opening the modal', () => {
- expect(trackFileUploadEvent).toHaveBeenCalledWith('click_upload_modal_form_submit');
- });
-
it('redirects to the uploaded file', () => {
expect(visitUrl).toHaveBeenCalled();
});
@@ -185,10 +179,6 @@ describe('UploadBlobModal', () => {
await waitForPromises();
});
- it('does not track an event', () => {
- expect(trackFileUploadEvent).not.toHaveBeenCalled();
- });
-
it('creates a flash error', () => {
expect(createFlash).toHaveBeenCalledWith({
message: 'Error uploading file. Please try again.',
diff --git a/spec/frontend/repository/mock_data.js b/spec/frontend/repository/mock_data.js
new file mode 100644
index 00000000000..adf5991ac3c
--- /dev/null
+++ b/spec/frontend/repository/mock_data.js
@@ -0,0 +1,57 @@
+export const simpleViewerMock = {
+ name: 'some_file.js',
+ size: 123,
+ rawSize: 123,
+ rawTextBlob: 'raw content',
+ fileType: 'text',
+ path: 'some_file.js',
+ webPath: 'some_file.js',
+ editBlobPath: 'some_file.js/edit',
+ ideEditPath: 'some_file.js/ide/edit',
+ forkAndEditPath: 'some_file.js/fork/edit',
+ ideForkAndEditPath: 'some_file.js/fork/ide',
+ canModifyBlob: true,
+ storedExternally: false,
+ rawPath: 'some_file.js',
+ replacePath: 'some_file.js/replace',
+ pipelineEditorPath: '',
+ simpleViewer: {
+ fileType: 'text',
+ tooLarge: false,
+ type: 'simple',
+ renderError: null,
+ },
+ richViewer: null,
+};
+
+export const richViewerMock = {
+ ...simpleViewerMock,
+ richViewer: {
+ fileType: 'markup',
+ tooLarge: false,
+ type: 'rich',
+ renderError: null,
+ },
+};
+
+export const userPermissionsMock = {
+ pushCode: true,
+ forkProject: true,
+ downloadCode: true,
+ createMergeRequestIn: true,
+};
+
+export const projectMock = {
+ id: '1234',
+ userPermissions: userPermissionsMock,
+ pathLocks: {
+ nodes: [],
+ },
+ repository: {
+ empty: false,
+ },
+};
+
+export const propsMock = { path: 'some_file.js', projectPath: 'some/path' };
+
+export const refMock = 'default-ref';
diff --git a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
index 33e9c122080..7eda9aa2850 100644
--- a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
+++ b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
@@ -10,9 +10,10 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { updateHistory } from '~/lib/utils/url_utility';
import AdminRunnersApp from '~/runner/admin_runners/admin_runners_app.vue';
+import RunnerTypeTabs from '~/runner/components/runner_type_tabs.vue';
import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.vue';
import RunnerList from '~/runner/components/runner_list.vue';
-import RunnerManualSetupHelp from '~/runner/components/runner_manual_setup_help.vue';
+import RegistrationDropdown from '~/runner/components/registration/registration_dropdown.vue';
import RunnerPagination from '~/runner/components/runner_pagination.vue';
import {
@@ -22,7 +23,6 @@ import {
DEFAULT_SORT,
INSTANCE_TYPE,
PARAM_KEY_STATUS,
- PARAM_KEY_RUNNER_TYPE,
PARAM_KEY_TAG,
STATUS_ACTIVE,
RUNNER_PAGE_SIZE,
@@ -34,7 +34,11 @@ import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered
import { runnersData, runnersDataPaginated } from '../mock_data';
const mockRegistrationToken = 'MOCK_REGISTRATION_TOKEN';
-const mockActiveRunnersCount = 2;
+const mockActiveRunnersCount = '2';
+const mockAllRunnersCount = '6';
+const mockInstanceRunnersCount = '3';
+const mockGroupRunnersCount = '2';
+const mockProjectRunnersCount = '1';
jest.mock('~/flash');
jest.mock('~/runner/sentry_utils');
@@ -50,7 +54,8 @@ describe('AdminRunnersApp', () => {
let wrapper;
let mockRunnersQuery;
- const findRunnerManualSetupHelp = () => wrapper.findComponent(RunnerManualSetupHelp);
+ const findRegistrationDropdown = () => wrapper.findComponent(RegistrationDropdown);
+ const findRunnerTypeTabs = () => wrapper.findComponent(RunnerTypeTabs);
const findRunnerList = () => wrapper.findComponent(RunnerList);
const findRunnerPagination = () => extendedWrapper(wrapper.findComponent(RunnerPagination));
const findRunnerPaginationPrev = () =>
@@ -66,8 +71,12 @@ describe('AdminRunnersApp', () => {
localVue,
apolloProvider: createMockApollo(handlers),
propsData: {
- activeRunnersCount: mockActiveRunnersCount,
registrationToken: mockRegistrationToken,
+ activeRunnersCount: mockActiveRunnersCount,
+ allRunnersCount: mockAllRunnersCount,
+ instanceRunnersCount: mockInstanceRunnersCount,
+ groupRunnersCount: mockGroupRunnersCount,
+ projectRunnersCount: mockProjectRunnersCount,
...props,
},
});
@@ -86,8 +95,19 @@ describe('AdminRunnersApp', () => {
wrapper.destroy();
});
+ it('shows the runner tabs with a runner count', async () => {
+ createComponent({ mountFn: mount });
+
+ await waitForPromises();
+
+ expect(findRunnerTypeTabs().text()).toMatchInterpolatedText(
+ `All ${mockAllRunnersCount} Instance ${mockInstanceRunnersCount} Group ${mockGroupRunnersCount} Project ${mockProjectRunnersCount}`,
+ );
+ });
+
it('shows the runner setup instructions', () => {
- expect(findRunnerManualSetupHelp().props('registrationToken')).toBe(mockRegistrationToken);
+ expect(findRegistrationDropdown().props('registrationToken')).toBe(mockRegistrationToken);
+ expect(findRegistrationDropdown().props('type')).toBe(INSTANCE_TYPE);
});
it('shows the runners list', () => {
@@ -126,10 +146,6 @@ describe('AdminRunnersApp', () => {
options: expect.any(Array),
}),
expect.objectContaining({
- type: PARAM_KEY_RUNNER_TYPE,
- options: expect.any(Array),
- }),
- expect.objectContaining({
type: PARAM_KEY_TAG,
recentTokenValuesStorageKey: `${ADMIN_FILTERED_SEARCH_NAMESPACE}-recent-tags`,
}),
@@ -154,9 +170,9 @@ describe('AdminRunnersApp', () => {
it('sets the filters in the search bar', () => {
expect(findRunnerFilteredSearchBar().props('value')).toEqual({
+ runnerType: INSTANCE_TYPE,
filters: [
{ type: 'status', value: { data: STATUS_ACTIVE, operator: '=' } },
- { type: 'runner_type', value: { data: INSTANCE_TYPE, operator: '=' } },
{ type: 'tag', value: { data: 'tag1', operator: '=' } },
],
sort: 'CREATED_DESC',
@@ -178,6 +194,7 @@ describe('AdminRunnersApp', () => {
describe('when a filter is selected by the user', () => {
beforeEach(() => {
findRunnerFilteredSearchBar().vm.$emit('input', {
+ runnerType: null,
filters: [{ type: PARAM_KEY_STATUS, value: { data: STATUS_ACTIVE, operator: '=' } }],
sort: CREATED_ASC,
});
diff --git a/spec/frontend/runner/components/cells/runner_actions_cell_spec.js b/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
index 5aa3879ac3e..2874bdbe280 100644
--- a/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
+++ b/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
@@ -8,12 +8,11 @@ import RunnerActionCell from '~/runner/components/cells/runner_actions_cell.vue'
import getGroupRunnersQuery from '~/runner/graphql/get_group_runners.query.graphql';
import getRunnersQuery from '~/runner/graphql/get_runners.query.graphql';
import runnerDeleteMutation from '~/runner/graphql/runner_delete.mutation.graphql';
-import runnerUpdateMutation from '~/runner/graphql/runner_update.mutation.graphql';
+import runnerActionsUpdateMutation from '~/runner/graphql/runner_actions_update.mutation.graphql';
import { captureException } from '~/runner/sentry_utils';
-import { runnersData, runnerData } from '../../mock_data';
+import { runnersData } from '../../mock_data';
const mockRunner = runnersData.data.runners.nodes[0];
-const mockRunnerDetails = runnerData.data.runner;
const getRunnersQueryName = getRunnersQuery.definitions[0].name.value;
const getGroupRunnersQueryName = getGroupRunnersQuery.definitions[0].name.value;
@@ -27,7 +26,7 @@ jest.mock('~/runner/sentry_utils');
describe('RunnerTypeCell', () => {
let wrapper;
const runnerDeleteMutationHandler = jest.fn();
- const runnerUpdateMutationHandler = jest.fn();
+ const runnerActionsUpdateMutationHandler = jest.fn();
const findEditBtn = () => wrapper.findByTestId('edit-runner');
const findToggleActiveBtn = () => wrapper.findByTestId('toggle-active-runner');
@@ -46,7 +45,7 @@ describe('RunnerTypeCell', () => {
localVue,
apolloProvider: createMockApollo([
[runnerDeleteMutation, runnerDeleteMutationHandler],
- [runnerUpdateMutation, runnerUpdateMutationHandler],
+ [runnerActionsUpdateMutation, runnerActionsUpdateMutationHandler],
]),
...options,
}),
@@ -62,10 +61,10 @@ describe('RunnerTypeCell', () => {
},
});
- runnerUpdateMutationHandler.mockResolvedValue({
+ runnerActionsUpdateMutationHandler.mockResolvedValue({
data: {
runnerUpdate: {
- runner: mockRunnerDetails,
+ runner: mockRunner,
errors: [],
},
},
@@ -74,7 +73,7 @@ describe('RunnerTypeCell', () => {
afterEach(() => {
runnerDeleteMutationHandler.mockReset();
- runnerUpdateMutationHandler.mockReset();
+ runnerActionsUpdateMutationHandler.mockReset();
wrapper.destroy();
});
@@ -116,12 +115,12 @@ describe('RunnerTypeCell', () => {
describe(`When clicking on the ${icon} button`, () => {
it(`The apollo mutation to set active to ${newActiveValue} is called`, async () => {
- expect(runnerUpdateMutationHandler).toHaveBeenCalledTimes(0);
+ expect(runnerActionsUpdateMutationHandler).toHaveBeenCalledTimes(0);
await findToggleActiveBtn().vm.$emit('click');
- expect(runnerUpdateMutationHandler).toHaveBeenCalledTimes(1);
- expect(runnerUpdateMutationHandler).toHaveBeenCalledWith({
+ expect(runnerActionsUpdateMutationHandler).toHaveBeenCalledTimes(1);
+ expect(runnerActionsUpdateMutationHandler).toHaveBeenCalledWith({
input: {
id: mockRunner.id,
active: newActiveValue,
@@ -145,7 +144,7 @@ describe('RunnerTypeCell', () => {
const mockErrorMsg = 'Update error!';
beforeEach(async () => {
- runnerUpdateMutationHandler.mockRejectedValueOnce(new Error(mockErrorMsg));
+ runnerActionsUpdateMutationHandler.mockRejectedValueOnce(new Error(mockErrorMsg));
await findToggleActiveBtn().vm.$emit('click');
});
@@ -167,10 +166,10 @@ describe('RunnerTypeCell', () => {
const mockErrorMsg2 = 'User not allowed!';
beforeEach(async () => {
- runnerUpdateMutationHandler.mockResolvedValue({
+ runnerActionsUpdateMutationHandler.mockResolvedValue({
data: {
runnerUpdate: {
- runner: runnerData.data.runner,
+ runner: mockRunner,
errors: [mockErrorMsg, mockErrorMsg2],
},
},
diff --git a/spec/frontend/runner/components/cells/runner_status_cell_spec.js b/spec/frontend/runner/components/cells/runner_status_cell_spec.js
new file mode 100644
index 00000000000..20a1cdf7236
--- /dev/null
+++ b/spec/frontend/runner/components/cells/runner_status_cell_spec.js
@@ -0,0 +1,69 @@
+import { GlBadge } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import RunnerStatusCell from '~/runner/components/cells/runner_status_cell.vue';
+import { INSTANCE_TYPE, STATUS_ONLINE, STATUS_OFFLINE } from '~/runner/constants';
+
+describe('RunnerTypeCell', () => {
+ let wrapper;
+
+ const findBadgeAt = (i) => wrapper.findAllComponents(GlBadge).at(i);
+
+ const createComponent = ({ runner = {} } = {}) => {
+ wrapper = mount(RunnerStatusCell, {
+ propsData: {
+ runner: {
+ runnerType: INSTANCE_TYPE,
+ active: true,
+ status: STATUS_ONLINE,
+ ...runner,
+ },
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Displays online status', () => {
+ createComponent();
+
+ expect(wrapper.text()).toMatchInterpolatedText('online');
+ expect(findBadgeAt(0).text()).toBe('online');
+ });
+
+ it('Displays offline status', () => {
+ createComponent({
+ runner: {
+ status: STATUS_OFFLINE,
+ },
+ });
+
+ expect(wrapper.text()).toMatchInterpolatedText('offline');
+ expect(findBadgeAt(0).text()).toBe('offline');
+ });
+
+ it('Displays paused status', () => {
+ createComponent({
+ runner: {
+ active: false,
+ status: STATUS_ONLINE,
+ },
+ });
+
+ expect(wrapper.text()).toMatchInterpolatedText('online paused');
+
+ expect(findBadgeAt(0).text()).toBe('online');
+ expect(findBadgeAt(1).text()).toBe('paused');
+ });
+
+ it('Is empty when data is missing', () => {
+ createComponent({
+ runner: {
+ status: null,
+ },
+ });
+
+ expect(wrapper.text()).toBe('');
+ });
+});
diff --git a/spec/frontend/runner/components/cells/runner_summary_cell_spec.js b/spec/frontend/runner/components/cells/runner_summary_cell_spec.js
index 1c9282e0acd..b6d957d27ea 100644
--- a/spec/frontend/runner/components/cells/runner_summary_cell_spec.js
+++ b/spec/frontend/runner/components/cells/runner_summary_cell_spec.js
@@ -1,5 +1,6 @@
-import { mount } from '@vue/test-utils';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import RunnerSummaryCell from '~/runner/components/cells/runner_summary_cell.vue';
+import { INSTANCE_TYPE, PROJECT_TYPE } from '~/runner/constants';
const mockId = '1';
const mockShortSha = '2P6oDVDm';
@@ -8,13 +9,17 @@ const mockDescription = 'runner-1';
describe('RunnerTypeCell', () => {
let wrapper;
- const createComponent = (options) => {
- wrapper = mount(RunnerSummaryCell, {
+ const findLockIcon = () => wrapper.findByTestId('lock-icon');
+
+ const createComponent = (runner, options) => {
+ wrapper = mountExtended(RunnerSummaryCell, {
propsData: {
runner: {
id: `gid://gitlab/Ci::Runner/${mockId}`,
shortSha: mockShortSha,
description: mockDescription,
+ runnerType: INSTANCE_TYPE,
+ ...runner,
},
},
...options,
@@ -33,6 +38,23 @@ describe('RunnerTypeCell', () => {
expect(wrapper.text()).toContain(`#${mockId} (${mockShortSha})`);
});
+ it('Displays the runner type', () => {
+ expect(wrapper.text()).toContain('shared');
+ });
+
+ it('Does not display the locked icon', () => {
+ expect(findLockIcon().exists()).toBe(false);
+ });
+
+ it('Displays the locked icon for locked runners', () => {
+ createComponent({
+ runnerType: PROJECT_TYPE,
+ locked: true,
+ });
+
+ expect(findLockIcon().exists()).toBe(true);
+ });
+
it('Displays the runner description', () => {
expect(wrapper.text()).toContain(mockDescription);
});
@@ -40,11 +62,14 @@ describe('RunnerTypeCell', () => {
it('Displays a custom slot', () => {
const slotContent = 'My custom runner summary';
- createComponent({
- slots: {
- 'runner-name': slotContent,
+ createComponent(
+ {},
+ {
+ slots: {
+ 'runner-name': slotContent,
+ },
},
- });
+ );
expect(wrapper.text()).toContain(slotContent);
});
diff --git a/spec/frontend/runner/components/cells/runner_type_cell_spec.js b/spec/frontend/runner/components/cells/runner_type_cell_spec.js
deleted file mode 100644
index 48958a282fc..00000000000
--- a/spec/frontend/runner/components/cells/runner_type_cell_spec.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import { GlBadge } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import RunnerTypeCell from '~/runner/components/cells/runner_type_cell.vue';
-import { INSTANCE_TYPE } from '~/runner/constants';
-
-describe('RunnerTypeCell', () => {
- let wrapper;
-
- const findBadges = () => wrapper.findAllComponents(GlBadge);
-
- const createComponent = ({ runner = {} } = {}) => {
- wrapper = mount(RunnerTypeCell, {
- propsData: {
- runner: {
- runnerType: INSTANCE_TYPE,
- active: true,
- locked: false,
- ...runner,
- },
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('Displays the runner type', () => {
- createComponent();
-
- expect(findBadges()).toHaveLength(1);
- expect(findBadges().at(0).text()).toBe('shared');
- });
-
- it('Displays locked and paused states', () => {
- createComponent({
- runner: {
- active: false,
- locked: true,
- },
- });
-
- expect(findBadges()).toHaveLength(3);
- expect(findBadges().at(0).text()).toBe('shared');
- expect(findBadges().at(1).text()).toBe('locked');
- expect(findBadges().at(2).text()).toBe('paused');
- });
-});
diff --git a/spec/frontend/runner/components/helpers/masked_value_spec.js b/spec/frontend/runner/components/helpers/masked_value_spec.js
deleted file mode 100644
index f87315057ec..00000000000
--- a/spec/frontend/runner/components/helpers/masked_value_spec.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import { GlButton } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import MaskedValue from '~/runner/components/helpers/masked_value.vue';
-
-const mockSecret = '01234567890';
-const mockMasked = '***********';
-
-describe('MaskedValue', () => {
- let wrapper;
-
- const findButton = () => wrapper.findComponent(GlButton);
-
- const createComponent = ({ props = {} } = {}) => {
- wrapper = shallowMount(MaskedValue, {
- propsData: {
- value: mockSecret,
- ...props,
- },
- });
- };
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('Displays masked value by default', () => {
- expect(wrapper.text()).toBe(mockMasked);
- });
-
- describe('When the icon is clicked', () => {
- beforeEach(() => {
- findButton().vm.$emit('click');
- });
-
- it('Displays the actual value', () => {
- expect(wrapper.text()).toBe(mockSecret);
- expect(wrapper.text()).not.toBe(mockMasked);
- });
-
- it('When user clicks again, displays masked value', async () => {
- await findButton().vm.$emit('click');
-
- expect(wrapper.text()).toBe(mockMasked);
- expect(wrapper.text()).not.toBe(mockSecret);
- });
- });
-});
diff --git a/spec/frontend/runner/components/registration/registration_dropdown_spec.js b/spec/frontend/runner/components/registration/registration_dropdown_spec.js
new file mode 100644
index 00000000000..d18d2bec18e
--- /dev/null
+++ b/spec/frontend/runner/components/registration/registration_dropdown_spec.js
@@ -0,0 +1,169 @@
+import { GlDropdown, GlDropdownItem, GlDropdownForm } from '@gitlab/ui';
+import { createLocalVue, mount, shallowMount, createWrapper } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+
+import RegistrationDropdown from '~/runner/components/registration/registration_dropdown.vue';
+import RegistrationTokenResetDropdownItem from '~/runner/components/registration/registration_token_reset_dropdown_item.vue';
+
+import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
+
+import getRunnerPlatformsQuery from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql';
+import getRunnerSetupInstructionsQuery from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql';
+
+import {
+ mockGraphqlRunnerPlatforms,
+ mockGraphqlInstructions,
+} from 'jest/vue_shared/components/runner_instructions/mock_data';
+
+const mockToken = '0123456789';
+const maskToken = '**********';
+
+describe('RegistrationDropdown', () => {
+ let wrapper;
+
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+
+ const findRegistrationInstructionsDropdownItem = () => wrapper.findComponent(GlDropdownItem);
+ const findTokenDropdownItem = () => wrapper.findComponent(GlDropdownForm);
+ const findTokenResetDropdownItem = () =>
+ wrapper.findComponent(RegistrationTokenResetDropdownItem);
+
+ const findToggleMaskButton = () => wrapper.findByTestId('toggle-masked');
+
+ const createComponent = ({ props = {}, ...options } = {}, mountFn = shallowMount) => {
+ wrapper = extendedWrapper(
+ mountFn(RegistrationDropdown, {
+ propsData: {
+ registrationToken: mockToken,
+ type: INSTANCE_TYPE,
+ ...props,
+ },
+ ...options,
+ }),
+ );
+ };
+
+ it.each`
+ type | text
+ ${INSTANCE_TYPE} | ${'Register an instance runner'}
+ ${GROUP_TYPE} | ${'Register a group runner'}
+ ${PROJECT_TYPE} | ${'Register a project runner'}
+ `('Dropdown text for type $type is "$text"', () => {
+ createComponent({ props: { type: INSTANCE_TYPE } }, mount);
+
+ expect(wrapper.text()).toContain('Register an instance runner');
+ });
+
+ it('Passes attributes to the dropdown component', () => {
+ createComponent({ attrs: { right: true } });
+
+ expect(findDropdown().attributes()).toMatchObject({ right: 'true' });
+ });
+
+ describe('Instructions dropdown item', () => {
+ it('Displays "Show runner" dropdown item', () => {
+ createComponent();
+
+ expect(findRegistrationInstructionsDropdownItem().text()).toBe(
+ 'Show runner installation and registration instructions',
+ );
+ });
+
+ describe('When the dropdown item is clicked', () => {
+ const localVue = createLocalVue();
+ localVue.use(VueApollo);
+
+ const requestHandlers = [
+ [getRunnerPlatformsQuery, jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms)],
+ [getRunnerSetupInstructionsQuery, jest.fn().mockResolvedValue(mockGraphqlInstructions)],
+ ];
+
+ const findModalInBody = () =>
+ createWrapper(document.body).find('[data-testid="runner-instructions-modal"]');
+
+ beforeEach(() => {
+ createComponent(
+ {
+ localVue,
+ // Mock load modal contents from API
+ apolloProvider: createMockApollo(requestHandlers),
+ // Use `attachTo` to find the modal
+ attachTo: document.body,
+ },
+ mount,
+ );
+
+ findRegistrationInstructionsDropdownItem().trigger('click');
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('opens the modal with contents', () => {
+ const modalText = findModalInBody()
+ .text()
+ .replace(/[\n\t\s]+/g, ' ');
+
+ expect(modalText).toContain('Install a runner');
+
+ // Environment selector
+ expect(modalText).toContain('Environment');
+ expect(modalText).toContain('Linux macOS Windows Docker Kubernetes');
+
+ // Architecture selector
+ expect(modalText).toContain('Architecture');
+ expect(modalText).toContain('amd64 amd64 386 arm arm64');
+
+ expect(modalText).toContain('Download and install binary');
+ });
+ });
+ });
+
+ describe('Registration token', () => {
+ it('Displays dropdown form for the registration token', () => {
+ createComponent();
+
+ expect(findTokenDropdownItem().exists()).toBe(true);
+ });
+
+ it('Displays masked value by default', () => {
+ createComponent({}, mount);
+
+ expect(findTokenDropdownItem().text()).toMatchInterpolatedText(
+ `Registration token ${maskToken}`,
+ );
+ });
+ });
+
+ describe('Reset token item', () => {
+ it('Displays registration token reset item', () => {
+ createComponent();
+
+ expect(findTokenResetDropdownItem().exists()).toBe(true);
+ });
+
+ it.each([INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE])('Set up token reset for %s', (type) => {
+ createComponent({ props: { type } });
+
+ expect(findTokenResetDropdownItem().props('type')).toBe(type);
+ });
+ });
+
+ it('Updates the token when it gets reset', async () => {
+ createComponent({}, mount);
+
+ const newToken = 'mock1';
+
+ findTokenResetDropdownItem().vm.$emit('tokenReset', newToken);
+ findToggleMaskButton().vm.$emit('click', { stopPropagation: jest.fn() });
+ await nextTick();
+
+ expect(findTokenDropdownItem().text()).toMatchInterpolatedText(
+ `Registration token ${newToken}`,
+ );
+ });
+});
diff --git a/spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js b/spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js
new file mode 100644
index 00000000000..0d002c272b4
--- /dev/null
+++ b/spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js
@@ -0,0 +1,194 @@
+import { GlDropdownItem, GlLoadingIcon, GlToast } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import RegistrationTokenResetDropdownItem from '~/runner/components/registration/registration_token_reset_dropdown_item.vue';
+import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
+import runnersRegistrationTokenResetMutation from '~/runner/graphql/runners_registration_token_reset.mutation.graphql';
+import { captureException } from '~/runner/sentry_utils';
+
+jest.mock('~/flash');
+jest.mock('~/runner/sentry_utils');
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+localVue.use(GlToast);
+
+const mockNewToken = 'NEW_TOKEN';
+
+describe('RegistrationTokenResetDropdownItem', () => {
+ let wrapper;
+ let runnersRegistrationTokenResetMutationHandler;
+ let showToast;
+
+ const findDropdownItem = () => wrapper.findComponent(GlDropdownItem);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+
+ const createComponent = ({ props, provide = {} } = {}) => {
+ wrapper = shallowMount(RegistrationTokenResetDropdownItem, {
+ localVue,
+ provide,
+ propsData: {
+ type: INSTANCE_TYPE,
+ ...props,
+ },
+ apolloProvider: createMockApollo([
+ [runnersRegistrationTokenResetMutation, runnersRegistrationTokenResetMutationHandler],
+ ]),
+ });
+
+ showToast = wrapper.vm.$toast ? jest.spyOn(wrapper.vm.$toast, 'show') : null;
+ };
+
+ beforeEach(() => {
+ runnersRegistrationTokenResetMutationHandler = jest.fn().mockResolvedValue({
+ data: {
+ runnersRegistrationTokenReset: {
+ token: mockNewToken,
+ errors: [],
+ },
+ },
+ });
+
+ createComponent();
+
+ jest.spyOn(window, 'confirm');
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Displays reset button', () => {
+ expect(findDropdownItem().exists()).toBe(true);
+ });
+
+ describe('On click and confirmation', () => {
+ const mockGroupId = '11';
+ const mockProjectId = '22';
+
+ describe.each`
+ type | provide | expectedInput
+ ${INSTANCE_TYPE} | ${{}} | ${{ type: INSTANCE_TYPE }}
+ ${GROUP_TYPE} | ${{ groupId: mockGroupId }} | ${{ type: GROUP_TYPE, id: `gid://gitlab/Group/${mockGroupId}` }}
+ ${PROJECT_TYPE} | ${{ projectId: mockProjectId }} | ${{ type: PROJECT_TYPE, id: `gid://gitlab/Project/${mockProjectId}` }}
+ `('Resets token of type $type', ({ type, provide, expectedInput }) => {
+ beforeEach(async () => {
+ createComponent({
+ provide,
+ props: { type },
+ });
+
+ window.confirm.mockReturnValueOnce(true);
+
+ findDropdownItem().trigger('click');
+ await waitForPromises();
+ });
+
+ it('resets token', () => {
+ expect(runnersRegistrationTokenResetMutationHandler).toHaveBeenCalledTimes(1);
+ expect(runnersRegistrationTokenResetMutationHandler).toHaveBeenCalledWith({
+ input: expectedInput,
+ });
+ });
+
+ it('emits result', () => {
+ expect(wrapper.emitted('tokenReset')).toHaveLength(1);
+ expect(wrapper.emitted('tokenReset')[0]).toEqual([mockNewToken]);
+ });
+
+ it('does not show a loading state', () => {
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+
+ it('shows confirmation', () => {
+ expect(showToast).toHaveBeenLastCalledWith(
+ expect.stringContaining('registration token generated'),
+ );
+ });
+ });
+ });
+
+ describe('On click without confirmation', () => {
+ beforeEach(async () => {
+ window.confirm.mockReturnValueOnce(false);
+ findDropdownItem().vm.$emit('click');
+ await waitForPromises();
+ });
+
+ it('does not reset token', () => {
+ expect(runnersRegistrationTokenResetMutationHandler).not.toHaveBeenCalled();
+ });
+
+ it('does not emit any result', () => {
+ expect(wrapper.emitted('tokenReset')).toBeUndefined();
+ });
+
+ it('does not show a loading state', () => {
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+
+ it('does not shows confirmation', () => {
+ expect(showToast).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('On error', () => {
+ it('On network error, error message is shown', async () => {
+ const mockErrorMsg = 'Token reset failed!';
+
+ runnersRegistrationTokenResetMutationHandler.mockRejectedValueOnce(new Error(mockErrorMsg));
+
+ window.confirm.mockReturnValueOnce(true);
+ findDropdownItem().trigger('click');
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenLastCalledWith({
+ message: `Network error: ${mockErrorMsg}`,
+ });
+ expect(captureException).toHaveBeenCalledWith({
+ error: new Error(`Network error: ${mockErrorMsg}`),
+ component: 'RunnerRegistrationTokenReset',
+ });
+ });
+
+ it('On validation error, error message is shown', async () => {
+ const mockErrorMsg = 'User not allowed!';
+ const mockErrorMsg2 = 'Type is not valid!';
+
+ runnersRegistrationTokenResetMutationHandler.mockResolvedValue({
+ data: {
+ runnersRegistrationTokenReset: {
+ token: null,
+ errors: [mockErrorMsg, mockErrorMsg2],
+ },
+ },
+ });
+
+ window.confirm.mockReturnValueOnce(true);
+ findDropdownItem().trigger('click');
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenLastCalledWith({
+ message: `${mockErrorMsg} ${mockErrorMsg2}`,
+ });
+ expect(captureException).toHaveBeenCalledWith({
+ error: new Error(`${mockErrorMsg} ${mockErrorMsg2}`),
+ component: 'RunnerRegistrationTokenReset',
+ });
+ });
+ });
+
+ describe('Immediately after click', () => {
+ it('shows loading state', async () => {
+ window.confirm.mockReturnValue(true);
+ findDropdownItem().trigger('click');
+ await nextTick();
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/registration/registration_token_spec.js b/spec/frontend/runner/components/registration/registration_token_spec.js
new file mode 100644
index 00000000000..f53ae165344
--- /dev/null
+++ b/spec/frontend/runner/components/registration/registration_token_spec.js
@@ -0,0 +1,109 @@
+import { nextTick } from 'vue';
+import { GlToast } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import RegistrationToken from '~/runner/components/registration/registration_token.vue';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
+
+const mockToken = '01234567890';
+const mockMasked = '***********';
+
+describe('RegistrationToken', () => {
+ let wrapper;
+ let stopPropagation;
+ let showToast;
+
+ const findToggleMaskButton = () => wrapper.findByTestId('toggle-masked');
+ const findCopyButton = () => wrapper.findComponent(ModalCopyButton);
+
+ const vueWithGlToast = () => {
+ const localVue = createLocalVue();
+ localVue.use(GlToast);
+ return localVue;
+ };
+
+ const createComponent = ({ props = {}, withGlToast = true } = {}) => {
+ const localVue = withGlToast ? vueWithGlToast() : undefined;
+
+ wrapper = extendedWrapper(
+ shallowMount(RegistrationToken, {
+ propsData: {
+ value: mockToken,
+ ...props,
+ },
+ localVue,
+ }),
+ );
+
+ showToast = wrapper.vm.$toast ? jest.spyOn(wrapper.vm.$toast, 'show') : null;
+ };
+
+ beforeEach(() => {
+ stopPropagation = jest.fn();
+
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Displays masked value by default', () => {
+ expect(wrapper.text()).toBe(mockMasked);
+ });
+
+ it('Displays button to reveal token', () => {
+ expect(findToggleMaskButton().attributes('aria-label')).toBe('Click to reveal');
+ });
+
+ it('Can copy the original token value', () => {
+ expect(findCopyButton().props('text')).toBe(mockToken);
+ });
+
+ describe('When the reveal icon is clicked', () => {
+ beforeEach(() => {
+ findToggleMaskButton().vm.$emit('click', { stopPropagation });
+ });
+
+ it('Click event is not propagated', async () => {
+ expect(stopPropagation).toHaveBeenCalledTimes(1);
+ });
+
+ it('Displays the actual value', () => {
+ expect(wrapper.text()).toBe(mockToken);
+ });
+
+ it('Can copy the original token value', () => {
+ expect(findCopyButton().props('text')).toBe(mockToken);
+ });
+
+ it('Displays button to mask token', () => {
+ expect(findToggleMaskButton().attributes('aria-label')).toBe('Click to hide');
+ });
+
+ it('When user clicks again, displays masked value', async () => {
+ findToggleMaskButton().vm.$emit('click', { stopPropagation });
+ await nextTick();
+
+ expect(wrapper.text()).toBe(mockMasked);
+ expect(findToggleMaskButton().attributes('aria-label')).toBe('Click to reveal');
+ });
+ });
+
+ describe('When the copy to clipboard button is clicked', () => {
+ it('shows a copied message', () => {
+ findCopyButton().vm.$emit('success');
+
+ expect(showToast).toHaveBeenCalledTimes(1);
+ expect(showToast).toHaveBeenCalledWith('Registration token copied!');
+ });
+
+ it('does not fail when toast is not defined', () => {
+ createComponent({ withGlToast: false });
+ findCopyButton().vm.$emit('success');
+
+ // This block also tests for unhandled errors
+ expect(showToast).toBeNull();
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/runner_contacted_state_badge_spec.js b/spec/frontend/runner/components/runner_contacted_state_badge_spec.js
new file mode 100644
index 00000000000..57a27f39826
--- /dev/null
+++ b/spec/frontend/runner/components/runner_contacted_state_badge_spec.js
@@ -0,0 +1,86 @@
+import { GlBadge } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import RunnerContactedStateBadge from '~/runner/components/runner_contacted_state_badge.vue';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { STATUS_ONLINE, STATUS_OFFLINE, STATUS_NOT_CONNECTED } from '~/runner/constants';
+
+describe('RunnerTypeBadge', () => {
+ let wrapper;
+
+ const findBadge = () => wrapper.findComponent(GlBadge);
+ const getTooltip = () => getBinding(findBadge().element, 'gl-tooltip');
+
+ const createComponent = ({ runner = {} } = {}) => {
+ wrapper = shallowMount(RunnerContactedStateBadge, {
+ propsData: {
+ runner: {
+ contactedAt: '2021-01-01T00:00:00Z',
+ status: STATUS_ONLINE,
+ ...runner,
+ },
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ beforeEach(() => {
+ jest.useFakeTimers('modern');
+ });
+
+ afterEach(() => {
+ jest.useFakeTimers('legacy');
+
+ wrapper.destroy();
+ });
+
+ it('renders online state', () => {
+ jest.setSystemTime(new Date('2021-01-01T00:01:00Z'));
+
+ createComponent();
+
+ expect(wrapper.text()).toBe('online');
+ expect(findBadge().props('variant')).toBe('success');
+ expect(getTooltip().value).toBe('Runner is online; last contact was 1 minute ago');
+ });
+
+ it('renders offline state', () => {
+ jest.setSystemTime(new Date('2021-01-02T00:00:00Z'));
+
+ createComponent({
+ runner: {
+ status: STATUS_OFFLINE,
+ },
+ });
+
+ expect(wrapper.text()).toBe('offline');
+ expect(findBadge().props('variant')).toBe('muted');
+ expect(getTooltip().value).toBe(
+ 'No recent contact from this runner; last contact was 1 day ago',
+ );
+ });
+
+ it('renders not connected state', () => {
+ createComponent({
+ runner: {
+ contactedAt: null,
+ status: STATUS_NOT_CONNECTED,
+ },
+ });
+
+ expect(wrapper.text()).toBe('not connected');
+ expect(findBadge().props('variant')).toBe('muted');
+ expect(getTooltip().value).toMatch('This runner has never connected');
+ });
+
+ it('does not fail when data is missing', () => {
+ createComponent({
+ runner: {
+ status: null,
+ },
+ });
+
+ expect(wrapper.text()).toBe('');
+ });
+});
diff --git a/spec/frontend/runner/components/runner_filtered_search_bar_spec.js b/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
index 46948af1f28..9ea0955f2a1 100644
--- a/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
+++ b/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
@@ -5,13 +5,7 @@ import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_
import { statusTokenConfig } from '~/runner/components/search_tokens/status_token_config';
import TagToken from '~/runner/components/search_tokens/tag_token.vue';
import { tagTokenConfig } from '~/runner/components/search_tokens/tag_token_config';
-import { typeTokenConfig } from '~/runner/components/search_tokens/type_token_config';
-import {
- PARAM_KEY_STATUS,
- PARAM_KEY_RUNNER_TYPE,
- PARAM_KEY_TAG,
- STATUS_ACTIVE,
-} from '~/runner/constants';
+import { PARAM_KEY_STATUS, PARAM_KEY_TAG, STATUS_ACTIVE, INSTANCE_TYPE } from '~/runner/constants';
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
@@ -31,6 +25,11 @@ describe('RunnerList', () => {
];
const mockActiveRunnersCount = 2;
+ const expectToHaveLastEmittedInput = (value) => {
+ const inputs = wrapper.emitted('input');
+ expect(inputs[inputs.length - 1][0]).toEqual(value);
+ };
+
const createComponent = ({ props = {}, options = {} } = {}) => {
wrapper = extendedWrapper(
shallowMount(RunnerFilteredSearchBar, {
@@ -38,6 +37,7 @@ describe('RunnerList', () => {
namespace: 'runners',
tokens: [],
value: {
+ runnerType: null,
filters: [],
sort: mockDefaultSort,
},
@@ -86,7 +86,7 @@ describe('RunnerList', () => {
it('sets tokens to the filtered search', () => {
createComponent({
props: {
- tokens: [statusTokenConfig, typeTokenConfig, tagTokenConfig],
+ tokens: [statusTokenConfig, tagTokenConfig],
},
});
@@ -97,11 +97,6 @@ describe('RunnerList', () => {
options: expect.any(Array),
}),
expect.objectContaining({
- type: PARAM_KEY_RUNNER_TYPE,
- token: BaseToken,
- options: expect.any(Array),
- }),
- expect.objectContaining({
type: PARAM_KEY_TAG,
token: TagToken,
}),
@@ -123,6 +118,7 @@ describe('RunnerList', () => {
createComponent({
props: {
value: {
+ runnerType: INSTANCE_TYPE,
sort: mockOtherSort,
filters: mockFilters,
},
@@ -142,30 +138,40 @@ describe('RunnerList', () => {
.text(),
).toEqual('Last contact');
});
+
+ it('when the user sets a filter, the "search" preserves the other filters', () => {
+ findGlFilteredSearch().vm.$emit('input', mockFilters);
+ findGlFilteredSearch().vm.$emit('submit');
+
+ expectToHaveLastEmittedInput({
+ runnerType: INSTANCE_TYPE,
+ filters: mockFilters,
+ sort: mockOtherSort,
+ pagination: { page: 1 },
+ });
+ });
});
it('when the user sets a filter, the "search" is emitted with filters', () => {
findGlFilteredSearch().vm.$emit('input', mockFilters);
findGlFilteredSearch().vm.$emit('submit');
- expect(wrapper.emitted('input')[0]).toEqual([
- {
- filters: mockFilters,
- sort: mockDefaultSort,
- pagination: { page: 1 },
- },
- ]);
+ expectToHaveLastEmittedInput({
+ runnerType: null,
+ filters: mockFilters,
+ sort: mockDefaultSort,
+ pagination: { page: 1 },
+ });
});
it('when the user sets a sorting method, the "search" is emitted with the sort', () => {
findSortOptions().at(1).vm.$emit('click');
- expect(wrapper.emitted('input')[0]).toEqual([
- {
- filters: [],
- sort: mockOtherSort,
- pagination: { page: 1 },
- },
- ]);
+ expectToHaveLastEmittedInput({
+ runnerType: null,
+ filters: [],
+ sort: mockOtherSort,
+ pagination: { page: 1 },
+ });
});
});
diff --git a/spec/frontend/runner/components/runner_list_spec.js b/spec/frontend/runner/components/runner_list_spec.js
index e24dffea1eb..986e55a2132 100644
--- a/spec/frontend/runner/components/runner_list_spec.js
+++ b/spec/frontend/runner/components/runner_list_spec.js
@@ -1,6 +1,5 @@
import { GlTable, GlSkeletonLoader } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
-import { cloneDeep } from 'lodash';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import RunnerList from '~/runner/components/runner_list.vue';
@@ -43,12 +42,10 @@ describe('RunnerList', () => {
const headerLabels = findHeaders().wrappers.map((w) => w.text());
expect(headerLabels).toEqual([
- 'Type/State',
- 'Runner',
+ 'Status',
+ 'Runner ID',
'Version',
'IP Address',
- 'Projects',
- 'Jobs',
'Tags',
'Last contact',
'', // actions has no label
@@ -65,7 +62,7 @@ describe('RunnerList', () => {
const { id, description, version, ipAddress, shortSha } = mockRunners[0];
// Badges
- expect(findCell({ fieldKey: 'type' }).text()).toMatchInterpolatedText('specific paused');
+ expect(findCell({ fieldKey: 'status' }).text()).toMatchInterpolatedText('not connected paused');
// Runner summary
expect(findCell({ fieldKey: 'summary' }).text()).toContain(
@@ -76,8 +73,6 @@ describe('RunnerList', () => {
// Other fields
expect(findCell({ fieldKey: 'version' }).text()).toBe(version);
expect(findCell({ fieldKey: 'ipAddress' }).text()).toBe(ipAddress);
- expect(findCell({ fieldKey: 'projectCount' }).text()).toBe('1');
- expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('0');
expect(findCell({ fieldKey: 'tagList' }).text()).toBe('');
expect(findCell({ fieldKey: 'contactedAt' }).text()).toEqual(expect.any(String));
@@ -88,54 +83,6 @@ describe('RunnerList', () => {
expect(actions.findByTestId('toggle-active-runner').exists()).toBe(true);
});
- describe('Table data formatting', () => {
- let mockRunnersCopy;
-
- beforeEach(() => {
- mockRunnersCopy = cloneDeep(mockRunners);
- });
-
- it('Formats null project counts', () => {
- mockRunnersCopy[0].projectCount = null;
-
- createComponent({ props: { runners: mockRunnersCopy } }, mount);
-
- expect(findCell({ fieldKey: 'projectCount' }).text()).toBe('n/a');
- });
-
- it('Formats 0 project counts', () => {
- mockRunnersCopy[0].projectCount = 0;
-
- createComponent({ props: { runners: mockRunnersCopy } }, mount);
-
- expect(findCell({ fieldKey: 'projectCount' }).text()).toBe('0');
- });
-
- it('Formats big project counts', () => {
- mockRunnersCopy[0].projectCount = 1000;
-
- createComponent({ props: { runners: mockRunnersCopy } }, mount);
-
- expect(findCell({ fieldKey: 'projectCount' }).text()).toBe('1,000');
- });
-
- it('Formats job counts', () => {
- mockRunnersCopy[0].jobCount = 1000;
-
- createComponent({ props: { runners: mockRunnersCopy } }, mount);
-
- expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('1,000');
- });
-
- it('Formats big job counts with a plus symbol', () => {
- mockRunnersCopy[0].jobCount = 1001;
-
- createComponent({ props: { runners: mockRunnersCopy } }, mount);
-
- expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('1,000+');
- });
- });
-
it('Shows runner identifier', () => {
const { id, shortSha } = mockRunners[0];
const numericId = getIdFromGraphQLId(id);
diff --git a/spec/frontend/runner/components/runner_manual_setup_help_spec.js b/spec/frontend/runner/components/runner_manual_setup_help_spec.js
deleted file mode 100644
index effef0e7ebf..00000000000
--- a/spec/frontend/runner/components/runner_manual_setup_help_spec.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import { GlSprintf } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import { TEST_HOST } from 'helpers/test_constants';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import MaskedValue from '~/runner/components/helpers/masked_value.vue';
-import RunnerManualSetupHelp from '~/runner/components/runner_manual_setup_help.vue';
-import RunnerRegistrationTokenReset from '~/runner/components/runner_registration_token_reset.vue';
-import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import RunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue';
-
-const mockRegistrationToken = 'MOCK_REGISTRATION_TOKEN';
-const mockRunnerInstallHelpPage = 'https://docs.gitlab.com/runner/install/';
-
-describe('RunnerManualSetupHelp', () => {
- let wrapper;
- let originalGon;
-
- const findRunnerInstructions = () => wrapper.findComponent(RunnerInstructions);
- const findRunnerRegistrationTokenReset = () =>
- wrapper.findComponent(RunnerRegistrationTokenReset);
- const findClipboardButtons = () => wrapper.findAllComponents(ClipboardButton);
- const findRunnerHelpTitle = () => wrapper.findByTestId('runner-help-title');
- const findCoordinatorUrl = () => wrapper.findByTestId('coordinator-url');
- const findRegistrationToken = () => wrapper.findByTestId('registration-token');
- const findRunnerHelpLink = () => wrapper.findByTestId('runner-help-link');
-
- const createComponent = ({ props = {} } = {}) => {
- wrapper = extendedWrapper(
- shallowMount(RunnerManualSetupHelp, {
- provide: {
- runnerInstallHelpPage: mockRunnerInstallHelpPage,
- },
- propsData: {
- registrationToken: mockRegistrationToken,
- type: INSTANCE_TYPE,
- ...props,
- },
- stubs: {
- MaskedValue,
- GlSprintf,
- },
- }),
- );
- };
-
- beforeAll(() => {
- originalGon = global.gon;
- global.gon = { gitlab_url: TEST_HOST };
- });
-
- afterAll(() => {
- global.gon = originalGon;
- });
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('Title contains the shared runner type', () => {
- createComponent({ props: { type: INSTANCE_TYPE } });
-
- expect(findRunnerHelpTitle().text()).toMatchInterpolatedText('Set up a shared runner manually');
- });
-
- it('Title contains the group runner type', () => {
- createComponent({ props: { type: GROUP_TYPE } });
-
- expect(findRunnerHelpTitle().text()).toMatchInterpolatedText('Set up a group runner manually');
- });
-
- it('Title contains the specific runner type', () => {
- createComponent({ props: { type: PROJECT_TYPE } });
-
- expect(findRunnerHelpTitle().text()).toMatchInterpolatedText(
- 'Set up a specific runner manually',
- );
- });
-
- it('Runner Install Page link', () => {
- expect(findRunnerHelpLink().attributes('href')).toBe(mockRunnerInstallHelpPage);
- });
-
- it('Displays the coordinator URL token', () => {
- expect(findCoordinatorUrl().text()).toBe(TEST_HOST);
- expect(findClipboardButtons().at(0).props('text')).toBe(TEST_HOST);
- });
-
- it('Displays the runner instructions', () => {
- expect(findRunnerInstructions().exists()).toBe(true);
- });
-
- it('Displays the registration token', async () => {
- findRegistrationToken().find('[data-testid="toggle-masked"]').vm.$emit('click');
-
- await nextTick();
-
- expect(findRegistrationToken().text()).toBe(mockRegistrationToken);
- expect(findClipboardButtons().at(1).props('text')).toBe(mockRegistrationToken);
- });
-
- it('Displays the runner registration token reset button', () => {
- expect(findRunnerRegistrationTokenReset().exists()).toBe(true);
- });
-
- it('Replaces the runner reset button', async () => {
- const mockNewRegistrationToken = 'NEW_MOCK_REGISTRATION_TOKEN';
-
- findRegistrationToken().find('[data-testid="toggle-masked"]').vm.$emit('click');
- findRunnerRegistrationTokenReset().vm.$emit('tokenReset', mockNewRegistrationToken);
-
- await nextTick();
-
- expect(findRegistrationToken().text()).toBe(mockNewRegistrationToken);
- expect(findClipboardButtons().at(1).props('text')).toBe(mockNewRegistrationToken);
- });
-});
diff --git a/spec/frontend/runner/components/runner_paused_badge_spec.js b/spec/frontend/runner/components/runner_paused_badge_spec.js
new file mode 100644
index 00000000000..18cfcfae864
--- /dev/null
+++ b/spec/frontend/runner/components/runner_paused_badge_spec.js
@@ -0,0 +1,45 @@
+import { GlBadge } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import RunnerStatePausedBadge from '~/runner/components/runner_paused_badge.vue';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+
+describe('RunnerTypeBadge', () => {
+ let wrapper;
+
+ const findBadge = () => wrapper.findComponent(GlBadge);
+ const getTooltip = () => getBinding(findBadge().element, 'gl-tooltip');
+
+ const createComponent = ({ props = {} } = {}) => {
+ wrapper = shallowMount(RunnerStatePausedBadge, {
+ propsData: {
+ ...props,
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders paused state', () => {
+ expect(wrapper.text()).toBe('paused');
+ expect(findBadge().props('variant')).toBe('danger');
+ });
+
+ it('renders tooltip', () => {
+ expect(getTooltip().value).toBeDefined();
+ });
+
+ it('passes arbitrary attributes to the badge', () => {
+ createComponent({ props: { size: 'sm' } });
+
+ expect(findBadge().props('size')).toBe('sm');
+ });
+});
diff --git a/spec/frontend/runner/components/runner_registration_token_reset_spec.js b/spec/frontend/runner/components/runner_registration_token_reset_spec.js
deleted file mode 100644
index 8b360b88417..00000000000
--- a/spec/frontend/runner/components/runner_registration_token_reset_spec.js
+++ /dev/null
@@ -1,189 +0,0 @@
-import { GlButton } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import createFlash, { FLASH_TYPES } from '~/flash';
-import RunnerRegistrationTokenReset from '~/runner/components/runner_registration_token_reset.vue';
-import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
-import runnersRegistrationTokenResetMutation from '~/runner/graphql/runners_registration_token_reset.mutation.graphql';
-import { captureException } from '~/runner/sentry_utils';
-
-jest.mock('~/flash');
-jest.mock('~/runner/sentry_utils');
-
-const localVue = createLocalVue();
-localVue.use(VueApollo);
-
-const mockNewToken = 'NEW_TOKEN';
-
-describe('RunnerRegistrationTokenReset', () => {
- let wrapper;
- let runnersRegistrationTokenResetMutationHandler;
-
- const findButton = () => wrapper.findComponent(GlButton);
-
- const createComponent = ({ props, provide = {} } = {}) => {
- wrapper = shallowMount(RunnerRegistrationTokenReset, {
- localVue,
- provide,
- propsData: {
- type: INSTANCE_TYPE,
- ...props,
- },
- apolloProvider: createMockApollo([
- [runnersRegistrationTokenResetMutation, runnersRegistrationTokenResetMutationHandler],
- ]),
- });
- };
-
- beforeEach(() => {
- runnersRegistrationTokenResetMutationHandler = jest.fn().mockResolvedValue({
- data: {
- runnersRegistrationTokenReset: {
- token: mockNewToken,
- errors: [],
- },
- },
- });
-
- createComponent();
-
- jest.spyOn(window, 'confirm');
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('Displays reset button', () => {
- expect(findButton().exists()).toBe(true);
- });
-
- describe('On click and confirmation', () => {
- const mockGroupId = '11';
- const mockProjectId = '22';
-
- describe.each`
- type | provide | expectedInput
- ${INSTANCE_TYPE} | ${{}} | ${{ type: INSTANCE_TYPE }}
- ${GROUP_TYPE} | ${{ groupId: mockGroupId }} | ${{ type: GROUP_TYPE, id: `gid://gitlab/Group/${mockGroupId}` }}
- ${PROJECT_TYPE} | ${{ projectId: mockProjectId }} | ${{ type: PROJECT_TYPE, id: `gid://gitlab/Project/${mockProjectId}` }}
- `('Resets token of type $type', ({ type, provide, expectedInput }) => {
- beforeEach(async () => {
- createComponent({
- provide,
- props: { type },
- });
-
- window.confirm.mockReturnValueOnce(true);
- findButton().vm.$emit('click');
- await waitForPromises();
- });
-
- it('resets token', () => {
- expect(runnersRegistrationTokenResetMutationHandler).toHaveBeenCalledTimes(1);
- expect(runnersRegistrationTokenResetMutationHandler).toHaveBeenCalledWith({
- input: expectedInput,
- });
- });
-
- it('emits result', () => {
- expect(wrapper.emitted('tokenReset')).toHaveLength(1);
- expect(wrapper.emitted('tokenReset')[0]).toEqual([mockNewToken]);
- });
-
- it('does not show a loading state', () => {
- expect(findButton().props('loading')).toBe(false);
- });
-
- it('shows confirmation', () => {
- expect(createFlash).toHaveBeenLastCalledWith({
- message: expect.stringContaining('registration token generated'),
- type: FLASH_TYPES.SUCCESS,
- });
- });
- });
- });
-
- describe('On click without confirmation', () => {
- beforeEach(async () => {
- window.confirm.mockReturnValueOnce(false);
- findButton().vm.$emit('click');
- await waitForPromises();
- });
-
- it('does not reset token', () => {
- expect(runnersRegistrationTokenResetMutationHandler).not.toHaveBeenCalled();
- });
-
- it('does not emit any result', () => {
- expect(wrapper.emitted('tokenReset')).toBeUndefined();
- });
-
- it('does not show a loading state', () => {
- expect(findButton().props('loading')).toBe(false);
- });
-
- it('does not shows confirmation', () => {
- expect(createFlash).not.toHaveBeenCalled();
- });
- });
-
- describe('On error', () => {
- it('On network error, error message is shown', async () => {
- const mockErrorMsg = 'Token reset failed!';
-
- runnersRegistrationTokenResetMutationHandler.mockRejectedValueOnce(new Error(mockErrorMsg));
-
- window.confirm.mockReturnValueOnce(true);
- findButton().vm.$emit('click');
- await waitForPromises();
-
- expect(createFlash).toHaveBeenLastCalledWith({
- message: `Network error: ${mockErrorMsg}`,
- });
- expect(captureException).toHaveBeenCalledWith({
- error: new Error(`Network error: ${mockErrorMsg}`),
- component: 'RunnerRegistrationTokenReset',
- });
- });
-
- it('On validation error, error message is shown', async () => {
- const mockErrorMsg = 'User not allowed!';
- const mockErrorMsg2 = 'Type is not valid!';
-
- runnersRegistrationTokenResetMutationHandler.mockResolvedValue({
- data: {
- runnersRegistrationTokenReset: {
- token: null,
- errors: [mockErrorMsg, mockErrorMsg2],
- },
- },
- });
-
- window.confirm.mockReturnValueOnce(true);
- findButton().vm.$emit('click');
- await waitForPromises();
-
- expect(createFlash).toHaveBeenLastCalledWith({
- message: `${mockErrorMsg} ${mockErrorMsg2}`,
- });
- expect(captureException).toHaveBeenCalledWith({
- error: new Error(`${mockErrorMsg} ${mockErrorMsg2}`),
- component: 'RunnerRegistrationTokenReset',
- });
- });
- });
-
- describe('Immediately after click', () => {
- it('shows loading state', async () => {
- window.confirm.mockReturnValue(true);
- findButton().vm.$emit('click');
- await nextTick();
-
- expect(findButton().props('loading')).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/runner/components/runner_state_locked_badge_spec.js b/spec/frontend/runner/components/runner_state_locked_badge_spec.js
deleted file mode 100644
index e92b671f5a1..00000000000
--- a/spec/frontend/runner/components/runner_state_locked_badge_spec.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import { GlBadge } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import RunnerStateLockedBadge from '~/runner/components/runner_state_locked_badge.vue';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-
-describe('RunnerTypeBadge', () => {
- let wrapper;
-
- const findBadge = () => wrapper.findComponent(GlBadge);
- const getTooltip = () => getBinding(findBadge().element, 'gl-tooltip');
-
- const createComponent = ({ props = {} } = {}) => {
- wrapper = shallowMount(RunnerStateLockedBadge, {
- propsData: {
- ...props,
- },
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
- };
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders locked state', () => {
- expect(wrapper.text()).toBe('locked');
- expect(findBadge().props('variant')).toBe('warning');
- });
-
- it('renders tooltip', () => {
- expect(getTooltip().value).toBeDefined();
- });
-
- it('passes arbitrary attributes to the badge', () => {
- createComponent({ props: { size: 'sm' } });
-
- expect(findBadge().props('size')).toBe('sm');
- });
-});
diff --git a/spec/frontend/runner/components/runner_state_paused_badge_spec.js b/spec/frontend/runner/components/runner_state_paused_badge_spec.js
deleted file mode 100644
index 8df56d6e3f3..00000000000
--- a/spec/frontend/runner/components/runner_state_paused_badge_spec.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import { GlBadge } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import RunnerStatePausedBadge from '~/runner/components/runner_state_paused_badge.vue';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-
-describe('RunnerTypeBadge', () => {
- let wrapper;
-
- const findBadge = () => wrapper.findComponent(GlBadge);
- const getTooltip = () => getBinding(findBadge().element, 'gl-tooltip');
-
- const createComponent = ({ props = {} } = {}) => {
- wrapper = shallowMount(RunnerStatePausedBadge, {
- propsData: {
- ...props,
- },
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
- };
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders paused state', () => {
- expect(wrapper.text()).toBe('paused');
- expect(findBadge().props('variant')).toBe('danger');
- });
-
- it('renders tooltip', () => {
- expect(getTooltip().value).toBeDefined();
- });
-
- it('passes arbitrary attributes to the badge', () => {
- createComponent({ props: { size: 'sm' } });
-
- expect(findBadge().props('size')).toBe('sm');
- });
-});
diff --git a/spec/frontend/runner/components/runner_tag_spec.js b/spec/frontend/runner/components/runner_tag_spec.js
index dda318f8153..bd05d4b2cfe 100644
--- a/spec/frontend/runner/components/runner_tag_spec.js
+++ b/spec/frontend/runner/components/runner_tag_spec.js
@@ -1,18 +1,35 @@
import { GlBadge } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import RunnerTag from '~/runner/components/runner_tag.vue';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+
+const mockTag = 'tag1';
describe('RunnerTag', () => {
let wrapper;
const findBadge = () => wrapper.findComponent(GlBadge);
+ const getTooltipValue = () => getBinding(findBadge().element, 'gl-tooltip').value;
+
+ const setDimensions = ({ scrollWidth, offsetWidth }) => {
+ jest.spyOn(findBadge().element, 'scrollWidth', 'get').mockReturnValue(scrollWidth);
+ jest.spyOn(findBadge().element, 'offsetWidth', 'get').mockReturnValue(offsetWidth);
+
+ // Mock trigger resize
+ getBinding(findBadge().element, 'gl-resize-observer').value();
+ };
const createComponent = ({ props = {} } = {}) => {
wrapper = shallowMount(RunnerTag, {
propsData: {
- tag: 'tag1',
+ tag: mockTag,
...props,
},
+ directives: {
+ GlTooltip: createMockDirective(),
+ GlResizeObserver: createMockDirective(),
+ },
});
};
@@ -25,21 +42,36 @@ describe('RunnerTag', () => {
});
it('Displays tag text', () => {
- expect(wrapper.text()).toBe('tag1');
+ expect(wrapper.text()).toBe(mockTag);
});
it('Displays tags with correct style', () => {
expect(findBadge().props()).toMatchObject({
- size: 'md',
- variant: 'info',
+ size: 'sm',
+ variant: 'neutral',
});
});
- it('Displays tags with small size', () => {
+ it('Displays tags with md size', () => {
createComponent({
- props: { size: 'sm' },
+ props: { size: 'md' },
});
- expect(findBadge().props('size')).toBe('sm');
+ expect(findBadge().props('size')).toBe('md');
});
+
+ it.each`
+ case | scrollWidth | offsetWidth | expectedTooltip
+ ${'overflowing'} | ${110} | ${100} | ${mockTag}
+ ${'not overflowing'} | ${90} | ${100} | ${''}
+ ${'almost overflowing'} | ${100} | ${100} | ${''}
+ `(
+ 'Sets "$expectedTooltip" as tooltip when $case',
+ async ({ scrollWidth, offsetWidth, expectedTooltip }) => {
+ setDimensions({ scrollWidth, offsetWidth });
+ await nextTick();
+
+ expect(getTooltipValue()).toBe(expectedTooltip);
+ },
+ );
});
diff --git a/spec/frontend/runner/components/runner_tags_spec.js b/spec/frontend/runner/components/runner_tags_spec.js
index b6487ade0d6..da89a659432 100644
--- a/spec/frontend/runner/components/runner_tags_spec.js
+++ b/spec/frontend/runner/components/runner_tags_spec.js
@@ -33,16 +33,16 @@ describe('RunnerTags', () => {
});
it('Displays tags with correct style', () => {
- expect(findBadge().props('size')).toBe('md');
- expect(findBadge().props('variant')).toBe('info');
+ expect(findBadge().props('size')).toBe('sm');
+ expect(findBadge().props('variant')).toBe('neutral');
});
- it('Displays tags with small size', () => {
+ it('Displays tags with md size', () => {
createComponent({
- props: { size: 'sm' },
+ props: { size: 'md' },
});
- expect(findBadge().props('size')).toBe('sm');
+ expect(findBadge().props('size')).toBe('md');
});
it('Is empty when there are no tags', () => {
diff --git a/spec/frontend/runner/components/runner_type_alert_spec.js b/spec/frontend/runner/components/runner_type_alert_spec.js
index e54e499743b..4023c75c9a8 100644
--- a/spec/frontend/runner/components/runner_type_alert_spec.js
+++ b/spec/frontend/runner/components/runner_type_alert_spec.js
@@ -23,11 +23,11 @@ describe('RunnerTypeAlert', () => {
});
describe.each`
- type | exampleText | anchor | variant
- ${INSTANCE_TYPE} | ${'This runner is available to all groups and projects'} | ${'#shared-runners'} | ${'success'}
- ${GROUP_TYPE} | ${'This runner is available to all projects and subgroups in a group'} | ${'#group-runners'} | ${'success'}
- ${PROJECT_TYPE} | ${'This runner is associated with one or more projects'} | ${'#specific-runners'} | ${'info'}
- `('When it is an $type level runner', ({ type, exampleText, anchor, variant }) => {
+ type | exampleText | anchor
+ ${INSTANCE_TYPE} | ${'This runner is available to all groups and projects'} | ${'#shared-runners'}
+ ${GROUP_TYPE} | ${'This runner is available to all projects and subgroups in a group'} | ${'#group-runners'}
+ ${PROJECT_TYPE} | ${'This runner is associated with one or more projects'} | ${'#specific-runners'}
+ `('When it is an $type level runner', ({ type, exampleText, anchor }) => {
beforeEach(() => {
createComponent({ props: { type } });
});
@@ -36,8 +36,8 @@ describe('RunnerTypeAlert', () => {
expect(wrapper.text()).toMatch(exampleText);
});
- it(`Shows a ${variant} variant`, () => {
- expect(findAlert().props('variant')).toBe(variant);
+ it(`Shows an "info" variant`, () => {
+ expect(findAlert().props('variant')).toBe('info');
});
it(`Links to anchor "${anchor}"`, () => {
diff --git a/spec/frontend/runner/components/runner_type_badge_spec.js b/spec/frontend/runner/components/runner_type_badge_spec.js
index fb344e65389..7bb0a2e6e2f 100644
--- a/spec/frontend/runner/components/runner_type_badge_spec.js
+++ b/spec/frontend/runner/components/runner_type_badge_spec.js
@@ -26,18 +26,18 @@ describe('RunnerTypeBadge', () => {
});
describe.each`
- type | text | variant
- ${INSTANCE_TYPE} | ${'shared'} | ${'success'}
- ${GROUP_TYPE} | ${'group'} | ${'success'}
- ${PROJECT_TYPE} | ${'specific'} | ${'info'}
- `('displays $type runner', ({ type, text, variant }) => {
+ type | text
+ ${INSTANCE_TYPE} | ${'shared'}
+ ${GROUP_TYPE} | ${'group'}
+ ${PROJECT_TYPE} | ${'specific'}
+ `('displays $type runner', ({ type, text }) => {
beforeEach(() => {
createComponent({ props: { type } });
});
- it(`as "${text}" with a ${variant} variant`, () => {
+ it(`as "${text}" with an "info" variant`, () => {
expect(findBadge().text()).toBe(text);
- expect(findBadge().props('variant')).toBe(variant);
+ expect(findBadge().props('variant')).toBe('info');
});
it('with a tooltip', () => {
diff --git a/spec/frontend/runner/components/runner_type_tabs_spec.js b/spec/frontend/runner/components/runner_type_tabs_spec.js
new file mode 100644
index 00000000000..4871d9c470a
--- /dev/null
+++ b/spec/frontend/runner/components/runner_type_tabs_spec.js
@@ -0,0 +1,109 @@
+import { GlTab } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import RunnerTypeTabs from '~/runner/components/runner_type_tabs.vue';
+import { INSTANCE_TYPE, GROUP_TYPE } from '~/runner/constants';
+
+const mockSearch = { runnerType: null, filters: [], pagination: { page: 1 }, sort: 'CREATED_DESC' };
+
+describe('RunnerTypeTabs', () => {
+ let wrapper;
+
+ const findTabs = () => wrapper.findAll(GlTab);
+ const findActiveTab = () =>
+ findTabs()
+ .filter((tab) => tab.attributes('active') === 'true')
+ .at(0);
+
+ const createComponent = ({ props, ...options } = {}) => {
+ wrapper = shallowMount(RunnerTypeTabs, {
+ propsData: {
+ value: mockSearch,
+ ...props,
+ },
+ stubs: {
+ GlTab,
+ },
+ ...options,
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Renders options to filter runners', () => {
+ expect(findTabs().wrappers.map((tab) => tab.text())).toEqual([
+ 'All',
+ 'Instance',
+ 'Group',
+ 'Project',
+ ]);
+ });
+
+ it('"All" is selected by default', () => {
+ expect(findActiveTab().text()).toBe('All');
+ });
+
+ it('Another tab can be preselected by the user', () => {
+ createComponent({
+ props: {
+ value: {
+ ...mockSearch,
+ runnerType: INSTANCE_TYPE,
+ },
+ },
+ });
+
+ expect(findActiveTab().text()).toBe('Instance');
+ });
+
+ describe('When the user selects a tab', () => {
+ const emittedValue = () => wrapper.emitted('input')[0][0];
+
+ beforeEach(() => {
+ findTabs().at(2).vm.$emit('click');
+ });
+
+ it(`Runner type is emitted`, () => {
+ expect(emittedValue()).toEqual({
+ ...mockSearch,
+ runnerType: GROUP_TYPE,
+ });
+ });
+
+ it('Runner type is selected', async () => {
+ const newValue = emittedValue();
+ await wrapper.setProps({ value: newValue });
+
+ expect(findActiveTab().text()).toBe('Group');
+ });
+ });
+
+ describe('When using a custom slot', () => {
+ const mockContent = 'content';
+
+ beforeEach(() => {
+ createComponent({
+ scopedSlots: {
+ title: `
+ <span>
+ {{props.tab.title}} ${mockContent}
+ </span>`,
+ },
+ });
+ });
+
+ it('Renders tabs with additional information', () => {
+ expect(findTabs().wrappers.map((tab) => tab.text())).toEqual([
+ `All ${mockContent}`,
+ `Instance ${mockContent}`,
+ `Group ${mockContent}`,
+ `Project ${mockContent}`,
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/runner/group_runners/group_runners_app_spec.js b/spec/frontend/runner/group_runners/group_runners_app_spec.js
index 5f3aabd4bc3..39bca743c80 100644
--- a/spec/frontend/runner/group_runners/group_runners_app_spec.js
+++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
import { GlLink } from '@gitlab/ui';
import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
@@ -11,7 +12,7 @@ import { updateHistory } from '~/lib/utils/url_utility';
import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.vue';
import RunnerList from '~/runner/components/runner_list.vue';
-import RunnerManualSetupHelp from '~/runner/components/runner_manual_setup_help.vue';
+import RegistrationDropdown from '~/runner/components/registration/registration_dropdown.vue';
import RunnerPagination from '~/runner/components/runner_pagination.vue';
import {
@@ -19,8 +20,8 @@ import {
CREATED_DESC,
DEFAULT_SORT,
INSTANCE_TYPE,
+ GROUP_TYPE,
PARAM_KEY_STATUS,
- PARAM_KEY_RUNNER_TYPE,
STATUS_ACTIVE,
RUNNER_PAGE_SIZE,
} from '~/runner/constants';
@@ -48,7 +49,7 @@ describe('GroupRunnersApp', () => {
let wrapper;
let mockGroupRunnersQuery;
- const findRunnerManualSetupHelp = () => wrapper.findComponent(RunnerManualSetupHelp);
+ const findRegistrationDropdown = () => wrapper.findComponent(RegistrationDropdown);
const findRunnerList = () => wrapper.findComponent(RunnerList);
const findRunnerPagination = () => extendedWrapper(wrapper.findComponent(RunnerPagination));
const findRunnerPaginationPrev = () =>
@@ -82,13 +83,13 @@ describe('GroupRunnersApp', () => {
});
it('shows the runner setup instructions', () => {
- expect(findRunnerManualSetupHelp().props('registrationToken')).toBe(mockRegistrationToken);
+ expect(findRegistrationDropdown().props('registrationToken')).toBe(mockRegistrationToken);
+ expect(findRegistrationDropdown().props('type')).toBe(GROUP_TYPE);
});
it('shows the runners list', () => {
- expect(findRunnerList().props('runners')).toEqual(
- groupRunnersData.data.group.runners.edges.map(({ node }) => node),
- );
+ const runners = findRunnerList().props('runners');
+ expect(runners).toEqual(groupRunnersData.data.group.runners.edges.map(({ node }) => node));
});
it('runner item links to the runner group page', async () => {
@@ -117,16 +118,15 @@ describe('GroupRunnersApp', () => {
it('sets tokens in the filtered search', () => {
createComponent({ mountFn: mount });
- expect(findFilteredSearch().props('tokens')).toEqual([
+ const tokens = findFilteredSearch().props('tokens');
+
+ expect(tokens).toHaveLength(1);
+ expect(tokens[0]).toEqual(
expect.objectContaining({
type: PARAM_KEY_STATUS,
options: expect.any(Array),
}),
- expect.objectContaining({
- type: PARAM_KEY_RUNNER_TYPE,
- options: expect.any(Array),
- }),
- ]);
+ );
});
describe('shows the active runner count', () => {
@@ -161,10 +161,8 @@ describe('GroupRunnersApp', () => {
it('sets the filters in the search bar', () => {
expect(findRunnerFilteredSearchBar().props('value')).toEqual({
- filters: [
- { type: 'status', value: { data: STATUS_ACTIVE, operator: '=' } },
- { type: 'runner_type', value: { data: INSTANCE_TYPE, operator: '=' } },
- ],
+ runnerType: INSTANCE_TYPE,
+ filters: [{ type: 'status', value: { data: STATUS_ACTIVE, operator: '=' } }],
sort: 'CREATED_DESC',
pagination: { page: 1 },
});
@@ -182,11 +180,14 @@ describe('GroupRunnersApp', () => {
});
describe('when a filter is selected by the user', () => {
- beforeEach(() => {
+ beforeEach(async () => {
findRunnerFilteredSearchBar().vm.$emit('input', {
+ runnerType: null,
filters: [{ type: PARAM_KEY_STATUS, value: { data: STATUS_ACTIVE, operator: '=' } }],
sort: CREATED_ASC,
});
+
+ await nextTick();
});
it('updates the browser url', () => {
diff --git a/spec/frontend/runner/runner_search_utils_spec.js b/spec/frontend/runner/runner_search_utils_spec.js
index 3a0c3abe7bd..0fc7917663e 100644
--- a/spec/frontend/runner/runner_search_utils_spec.js
+++ b/spec/frontend/runner/runner_search_utils_spec.js
@@ -1,5 +1,6 @@
import { RUNNER_PAGE_SIZE } from '~/runner/constants';
import {
+ searchValidator,
fromUrlQueryToSearch,
fromSearchToUrl,
fromSearchToVariables,
@@ -10,13 +11,14 @@ describe('search_params.js', () => {
{
name: 'a default query',
urlQuery: '',
- search: { filters: [], pagination: { page: 1 }, sort: 'CREATED_DESC' },
+ search: { runnerType: null, filters: [], pagination: { page: 1 }, sort: 'CREATED_DESC' },
graphqlVariables: { sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
},
{
name: 'a single status',
urlQuery: '?status[]=ACTIVE',
search: {
+ runnerType: null,
filters: [{ type: 'status', value: { data: 'ACTIVE', operator: '=' } }],
pagination: { page: 1 },
sort: 'CREATED_DESC',
@@ -27,6 +29,7 @@ describe('search_params.js', () => {
name: 'a single term text search',
urlQuery: '?search=something',
search: {
+ runnerType: null,
filters: [
{
type: 'filtered-search-term',
@@ -42,6 +45,7 @@ describe('search_params.js', () => {
name: 'a two terms text search',
urlQuery: '?search=something+else',
search: {
+ runnerType: null,
filters: [
{
type: 'filtered-search-term',
@@ -61,7 +65,8 @@ describe('search_params.js', () => {
name: 'single instance type',
urlQuery: '?runner_type[]=INSTANCE_TYPE',
search: {
- filters: [{ type: 'runner_type', value: { data: 'INSTANCE_TYPE', operator: '=' } }],
+ runnerType: 'INSTANCE_TYPE',
+ filters: [],
pagination: { page: 1 },
sort: 'CREATED_DESC',
},
@@ -71,6 +76,7 @@ describe('search_params.js', () => {
name: 'multiple runner status',
urlQuery: '?status[]=ACTIVE&status[]=PAUSED',
search: {
+ runnerType: null,
filters: [
{ type: 'status', value: { data: 'ACTIVE', operator: '=' } },
{ type: 'status', value: { data: 'PAUSED', operator: '=' } },
@@ -84,10 +90,8 @@ describe('search_params.js', () => {
name: 'multiple status, a single instance type and a non default sort',
urlQuery: '?status[]=ACTIVE&runner_type[]=INSTANCE_TYPE&sort=CREATED_ASC',
search: {
- filters: [
- { type: 'status', value: { data: 'ACTIVE', operator: '=' } },
- { type: 'runner_type', value: { data: 'INSTANCE_TYPE', operator: '=' } },
- ],
+ runnerType: 'INSTANCE_TYPE',
+ filters: [{ type: 'status', value: { data: 'ACTIVE', operator: '=' } }],
pagination: { page: 1 },
sort: 'CREATED_ASC',
},
@@ -102,6 +106,7 @@ describe('search_params.js', () => {
name: 'a tag',
urlQuery: '?tag[]=tag-1',
search: {
+ runnerType: null,
filters: [{ type: 'tag', value: { data: 'tag-1', operator: '=' } }],
pagination: { page: 1 },
sort: 'CREATED_DESC',
@@ -116,6 +121,7 @@ describe('search_params.js', () => {
name: 'two tags',
urlQuery: '?tag[]=tag-1&tag[]=tag-2',
search: {
+ runnerType: null,
filters: [
{ type: 'tag', value: { data: 'tag-1', operator: '=' } },
{ type: 'tag', value: { data: 'tag-2', operator: '=' } },
@@ -132,13 +138,19 @@ describe('search_params.js', () => {
{
name: 'the next page',
urlQuery: '?page=2&after=AFTER_CURSOR',
- search: { filters: [], pagination: { page: 2, after: 'AFTER_CURSOR' }, sort: 'CREATED_DESC' },
+ search: {
+ runnerType: null,
+ filters: [],
+ pagination: { page: 2, after: 'AFTER_CURSOR' },
+ sort: 'CREATED_DESC',
+ },
graphqlVariables: { sort: 'CREATED_DESC', after: 'AFTER_CURSOR', first: RUNNER_PAGE_SIZE },
},
{
name: 'the previous page',
urlQuery: '?page=2&before=BEFORE_CURSOR',
search: {
+ runnerType: null,
filters: [],
pagination: { page: 2, before: 'BEFORE_CURSOR' },
sort: 'CREATED_DESC',
@@ -150,9 +162,9 @@ describe('search_params.js', () => {
urlQuery:
'?status[]=ACTIVE&runner_type[]=INSTANCE_TYPE&tag[]=tag-1&tag[]=tag-2&sort=CREATED_ASC&page=2&after=AFTER_CURSOR',
search: {
+ runnerType: 'INSTANCE_TYPE',
filters: [
{ type: 'status', value: { data: 'ACTIVE', operator: '=' } },
- { type: 'runner_type', value: { data: 'INSTANCE_TYPE', operator: '=' } },
{ type: 'tag', value: { data: 'tag-1', operator: '=' } },
{ type: 'tag', value: { data: 'tag-2', operator: '=' } },
],
@@ -170,6 +182,14 @@ describe('search_params.js', () => {
},
];
+ describe('searchValidator', () => {
+ examples.forEach(({ name, search }) => {
+ it(`Validates ${name} as a search object`, () => {
+ expect(searchValidator(search)).toBe(true);
+ });
+ });
+ });
+
describe('fromUrlQueryToSearch', () => {
examples.forEach(({ name, urlQuery, search }) => {
it(`Converts ${name} to a search object`, () => {
diff --git a/spec/frontend/search/sidebar/components/app_spec.js b/spec/frontend/search/sidebar/components/app_spec.js
index b93527c1fe9..3bea0748c47 100644
--- a/spec/frontend/search/sidebar/components/app_spec.js
+++ b/spec/frontend/search/sidebar/components/app_spec.js
@@ -1,13 +1,13 @@
import { GlButton, GlLink } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { MOCK_QUERY } from 'jest/search/mock_data';
import GlobalSearchSidebar from '~/search/sidebar/components/app.vue';
import ConfidentialityFilter from '~/search/sidebar/components/confidentiality_filter.vue';
import StatusFilter from '~/search/sidebar/components/status_filter.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('GlobalSearchSidebar', () => {
let wrapper;
@@ -20,28 +20,26 @@ describe('GlobalSearchSidebar', () => {
const createComponent = (initialState) => {
const store = new Vuex.Store({
state: {
- query: MOCK_QUERY,
+ urlQuery: MOCK_QUERY,
...initialState,
},
actions: actionSpies,
});
wrapper = shallowMount(GlobalSearchSidebar, {
- localVue,
store,
});
};
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
const findSidebarForm = () => wrapper.find('form');
- const findStatusFilter = () => wrapper.find(StatusFilter);
- const findConfidentialityFilter = () => wrapper.find(ConfidentialityFilter);
- const findApplyButton = () => wrapper.find(GlButton);
- const findResetLinkButton = () => wrapper.find(GlLink);
+ const findStatusFilter = () => wrapper.findComponent(StatusFilter);
+ const findConfidentialityFilter = () => wrapper.findComponent(ConfidentialityFilter);
+ const findApplyButton = () => wrapper.findComponent(GlButton);
+ const findResetLinkButton = () => wrapper.findComponent(GlLink);
describe('template', () => {
beforeEach(() => {
@@ -61,10 +59,32 @@ describe('GlobalSearchSidebar', () => {
});
});
+ describe('ApplyButton', () => {
+ describe('when sidebarDirty is false', () => {
+ beforeEach(() => {
+ createComponent({ sidebarDirty: false });
+ });
+
+ it('disables the button', () => {
+ expect(findApplyButton().attributes('disabled')).toBe('true');
+ });
+ });
+
+ describe('when sidebarDirty is true', () => {
+ beforeEach(() => {
+ createComponent({ sidebarDirty: true });
+ });
+
+ it('enables the button', () => {
+ expect(findApplyButton().attributes('disabled')).toBe(undefined);
+ });
+ });
+ });
+
describe('ResetLinkButton', () => {
describe('with no filter selected', () => {
beforeEach(() => {
- createComponent({ query: {} });
+ createComponent({ urlQuery: {} });
});
it('does not render', () => {
@@ -74,10 +94,20 @@ describe('GlobalSearchSidebar', () => {
describe('with filter selected', () => {
beforeEach(() => {
- createComponent();
+ createComponent({ urlQuery: MOCK_QUERY });
+ });
+
+ it('does render', () => {
+ expect(findResetLinkButton().exists()).toBe(true);
+ });
+ });
+
+ describe('with filter selected and user updated query back to default', () => {
+ beforeEach(() => {
+ createComponent({ urlQuery: MOCK_QUERY, query: {} });
});
- it('does render when a filter selected', () => {
+ it('does render', () => {
expect(findResetLinkButton().exists()).toBe(true);
});
});
diff --git a/spec/frontend/search/store/actions_spec.js b/spec/frontend/search/store/actions_spec.js
index b50248bb295..5f8cee8160f 100644
--- a/spec/frontend/search/store/actions_spec.js
+++ b/spec/frontend/search/store/actions_spec.js
@@ -5,7 +5,11 @@ import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as urlUtils from '~/lib/utils/url_utility';
import * as actions from '~/search/store/actions';
-import { GROUPS_LOCAL_STORAGE_KEY, PROJECTS_LOCAL_STORAGE_KEY } from '~/search/store/constants';
+import {
+ GROUPS_LOCAL_STORAGE_KEY,
+ PROJECTS_LOCAL_STORAGE_KEY,
+ SIDEBAR_PARAMS,
+} from '~/search/store/constants';
import * as types from '~/search/store/mutation_types';
import createState from '~/search/store/state';
import * as storeUtils from '~/search/store/utils';
@@ -153,15 +157,24 @@ describe('Global Search Store Actions', () => {
});
});
- describe('setQuery', () => {
- const payload = { key: 'key1', value: 'value1' };
+ describe.each`
+ payload | isDirty | isDirtyMutation
+ ${{ key: SIDEBAR_PARAMS[0], value: 'test' }} | ${false} | ${[{ type: types.SET_SIDEBAR_DIRTY, payload: false }]}
+ ${{ key: SIDEBAR_PARAMS[0], value: 'test' }} | ${true} | ${[{ type: types.SET_SIDEBAR_DIRTY, payload: true }]}
+ ${{ key: SIDEBAR_PARAMS[1], value: 'test' }} | ${false} | ${[{ type: types.SET_SIDEBAR_DIRTY, payload: false }]}
+ ${{ key: SIDEBAR_PARAMS[1], value: 'test' }} | ${true} | ${[{ type: types.SET_SIDEBAR_DIRTY, payload: true }]}
+ ${{ key: 'non-sidebar', value: 'test' }} | ${false} | ${[]}
+ ${{ key: 'non-sidebar', value: 'test' }} | ${true} | ${[]}
+ `('setQuery', ({ payload, isDirty, isDirtyMutation }) => {
+ describe(`when filter param is ${payload.key} and utils.isSidebarDirty returns ${isDirty}`, () => {
+ const expectedMutations = [{ type: types.SET_QUERY, payload }].concat(isDirtyMutation);
- it('calls the SET_QUERY mutation', () => {
- return testAction({
- action: actions.setQuery,
- payload,
- state,
- expectedMutations: [{ type: types.SET_QUERY, payload }],
+ beforeEach(() => {
+ storeUtils.isSidebarDirty = jest.fn().mockReturnValue(isDirty);
+ });
+
+ it(`should dispatch the correct mutations`, () => {
+ return testAction({ action: actions.setQuery, payload, state, expectedMutations });
});
});
});
diff --git a/spec/frontend/search/store/mutations_spec.js b/spec/frontend/search/store/mutations_spec.js
index a60718a972d..25f9b692955 100644
--- a/spec/frontend/search/store/mutations_spec.js
+++ b/spec/frontend/search/store/mutations_spec.js
@@ -72,6 +72,16 @@ describe('Global Search Store Mutations', () => {
});
});
+ describe('SET_SIDEBAR_DIRTY', () => {
+ const value = true;
+
+ it('sets sidebarDirty to the value', () => {
+ mutations[types.SET_SIDEBAR_DIRTY](state, value);
+
+ expect(state.sidebarDirty).toBe(value);
+ });
+ });
+
describe('LOAD_FREQUENT_ITEMS', () => {
it('sets frequentItems[key] to data', () => {
const payload = { key: 'test-key', data: [1, 2, 3] };
diff --git a/spec/frontend/search/store/utils_spec.js b/spec/frontend/search/store/utils_spec.js
index bcdad9f89dd..20d764190b1 100644
--- a/spec/frontend/search/store/utils_spec.js
+++ b/spec/frontend/search/store/utils_spec.js
@@ -1,6 +1,11 @@
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
-import { MAX_FREQUENCY } from '~/search/store/constants';
-import { loadDataFromLS, setFrequentItemToLS, mergeById } from '~/search/store/utils';
+import { MAX_FREQUENCY, SIDEBAR_PARAMS } from '~/search/store/constants';
+import {
+ loadDataFromLS,
+ setFrequentItemToLS,
+ mergeById,
+ isSidebarDirty,
+} from '~/search/store/utils';
import {
MOCK_LS_KEY,
MOCK_GROUPS,
@@ -216,4 +221,24 @@ describe('Global Search Store Utils', () => {
});
});
});
+
+ describe.each`
+ description | currentQuery | urlQuery | isDirty
+ ${'identical'} | ${{ [SIDEBAR_PARAMS[0]]: 'default', [SIDEBAR_PARAMS[1]]: 'default' }} | ${{ [SIDEBAR_PARAMS[0]]: 'default', [SIDEBAR_PARAMS[1]]: 'default' }} | ${false}
+ ${'different'} | ${{ [SIDEBAR_PARAMS[0]]: 'default', [SIDEBAR_PARAMS[1]]: 'new' }} | ${{ [SIDEBAR_PARAMS[0]]: 'default', [SIDEBAR_PARAMS[1]]: 'default' }} | ${true}
+ ${'null/undefined'} | ${{ [SIDEBAR_PARAMS[0]]: null, [SIDEBAR_PARAMS[1]]: null }} | ${{ [SIDEBAR_PARAMS[0]]: undefined, [SIDEBAR_PARAMS[1]]: undefined }} | ${false}
+ ${'updated/undefined'} | ${{ [SIDEBAR_PARAMS[0]]: 'new', [SIDEBAR_PARAMS[1]]: 'new' }} | ${{ [SIDEBAR_PARAMS[0]]: undefined, [SIDEBAR_PARAMS[1]]: undefined }} | ${true}
+ `('isSidebarDirty', ({ description, currentQuery, urlQuery, isDirty }) => {
+ describe(`with ${description} sidebar query data`, () => {
+ let res;
+
+ beforeEach(() => {
+ res = isSidebarDirty(currentQuery, urlQuery);
+ });
+
+ it(`returns ${isDirty}`, () => {
+ expect(res).toStrictEqual(isDirty);
+ });
+ });
+ });
});
diff --git a/spec/frontend/security_configuration/components/app_spec.js b/spec/frontend/security_configuration/components/app_spec.js
index f27f45f2b26..d4ee9e6e43d 100644
--- a/spec/frontend/security_configuration/components/app_spec.js
+++ b/spec/frontend/security_configuration/components/app_spec.js
@@ -1,5 +1,6 @@
import { GlTab } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
import stubChildren from 'helpers/stub_children';
@@ -70,6 +71,7 @@ describe('App component', () => {
const findTabs = () => wrapper.findAllComponents(GlTab);
const findByTestId = (id) => wrapper.findByTestId(id);
const findFeatureCards = () => wrapper.findAllComponents(FeatureCard);
+ const findManageViaMRErrorAlert = () => wrapper.findByTestId('manage-via-mr-error-alert');
const findLink = ({ href, text, container = wrapper }) => {
const selector = `a[href="${href}"]`;
const link = container.find(selector);
@@ -132,12 +134,12 @@ describe('App component', () => {
it('renders main-heading with correct text', () => {
const mainHeading = findMainHeading();
- expect(mainHeading).toExist();
+ expect(mainHeading.exists()).toBe(true);
expect(mainHeading.text()).toContain('Security Configuration');
});
it('renders GlTab Component ', () => {
- expect(findTab()).toExist();
+ expect(findTab().exists()).toBe(true);
});
it('renders right amount of tabs with correct title ', () => {
@@ -173,6 +175,43 @@ describe('App component', () => {
});
});
+ describe('Manage via MR Error Alert', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ });
+ });
+
+ describe('on initial load', () => {
+ it('should not show Manage via MR Error Alert', () => {
+ expect(findManageViaMRErrorAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('when error occurs', () => {
+ it('should show Alert with error Message', async () => {
+ expect(findManageViaMRErrorAlert().exists()).toBe(false);
+ findFeatureCards().at(1).vm.$emit('error', 'There was a manage via MR error');
+
+ await nextTick();
+ expect(findManageViaMRErrorAlert().exists()).toBe(true);
+ expect(findManageViaMRErrorAlert().text()).toEqual('There was a manage via MR error');
+ });
+
+ it('should hide Alert when it is dismissed', async () => {
+ findFeatureCards().at(1).vm.$emit('error', 'There was a manage via MR error');
+
+ await nextTick();
+ expect(findManageViaMRErrorAlert().exists()).toBe(true);
+
+ findManageViaMRErrorAlert().vm.$emit('dismiss');
+ await nextTick();
+ expect(findManageViaMRErrorAlert().exists()).toBe(false);
+ });
+ });
+ });
+
describe('Auto DevOps hint alert', () => {
describe('given the right props', () => {
beforeEach(() => {
diff --git a/spec/frontend/security_configuration/components/feature_card_spec.js b/spec/frontend/security_configuration/components/feature_card_spec.js
index fdb1d2f86e3..0eca2c27075 100644
--- a/spec/frontend/security_configuration/components/feature_card_spec.js
+++ b/spec/frontend/security_configuration/components/feature_card_spec.js
@@ -80,7 +80,11 @@ describe('FeatureCard component', () => {
describe('basic structure', () => {
beforeEach(() => {
- feature = makeFeature();
+ feature = makeFeature({
+ type: 'sast',
+ available: true,
+ canEnableByMergeRequest: true,
+ });
createComponent({ feature });
});
@@ -97,6 +101,11 @@ describe('FeatureCard component', () => {
expect(links.exists()).toBe(true);
expect(links).toHaveLength(1);
});
+
+ it('should catch and emit manage-via-mr-error', () => {
+ findManageViaMr().vm.$emit('error', 'There was a manage via MR error');
+ expect(wrapper.emitted('error')).toEqual([['There was a manage via MR error']]);
+ });
});
describe('status', () => {
diff --git a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
index 7e81df1d7d2..c72c23a3a60 100644
--- a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
+++ b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
@@ -10,7 +10,7 @@ const DEFAULT_RENDER_COUNT = 5;
describe('UncollapsedAssigneeList component', () => {
let wrapper;
- function createComponent(props = {}) {
+ function createComponent(props = {}, glFeatures = {}) {
const propsData = {
users: [],
rootPath: TEST_HOST,
@@ -19,6 +19,7 @@ describe('UncollapsedAssigneeList component', () => {
wrapper = mount(UncollapsedAssigneeList, {
propsData,
+ provide: { glFeatures },
});
}
@@ -99,4 +100,22 @@ describe('UncollapsedAssigneeList component', () => {
});
});
});
+
+ describe('merge requests', () => {
+ it.each`
+ numberOfUsers
+ ${1}
+ ${5}
+ `('displays as a vertical list for $numberOfUsers of users', ({ numberOfUsers }) => {
+ createComponent(
+ {
+ users: UsersMockHelper.createNumberRandomUsers(numberOfUsers),
+ issuableType: 'merge_request',
+ },
+ { mrAttentionRequests: true },
+ );
+
+ expect(wrapper.findAll('[data-testid="username"]').length).toBe(numberOfUsers);
+ });
+ });
});
diff --git a/spec/frontend/sidebar/components/attention_required_toggle_spec.js b/spec/frontend/sidebar/components/attention_required_toggle_spec.js
new file mode 100644
index 00000000000..8555068cdd8
--- /dev/null
+++ b/spec/frontend/sidebar/components/attention_required_toggle_spec.js
@@ -0,0 +1,84 @@
+import { GlButton } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import AttentionRequestedToggle from '~/sidebar/components/attention_requested_toggle.vue';
+
+let wrapper;
+
+function factory(propsData = {}) {
+ wrapper = mount(AttentionRequestedToggle, { propsData });
+}
+
+const findToggle = () => wrapper.findComponent(GlButton);
+
+describe('Attention require toggle', () => {
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders button', () => {
+ factory({ type: 'reviewer', user: { attention_requested: false } });
+
+ expect(findToggle().exists()).toBe(true);
+ });
+
+ it.each`
+ attentionRequested | icon
+ ${true} | ${'star'}
+ ${false} | ${'star-o'}
+ `(
+ 'renders $icon icon when attention_requested is $attentionRequested',
+ ({ attentionRequested, icon }) => {
+ factory({ type: 'reviewer', user: { attention_requested: attentionRequested } });
+
+ expect(findToggle().props('icon')).toBe(icon);
+ },
+ );
+
+ it.each`
+ attentionRequested | variant
+ ${true} | ${'warning'}
+ ${false} | ${'default'}
+ `(
+ 'renders button with variant $variant when attention_requested is $attentionRequested',
+ ({ attentionRequested, variant }) => {
+ factory({ type: 'reviewer', user: { attention_requested: attentionRequested } });
+
+ expect(findToggle().props('variant')).toBe(variant);
+ },
+ );
+
+ it('emits toggle-attention-requested on click', async () => {
+ factory({ type: 'reviewer', user: { attention_requested: true } });
+
+ await findToggle().trigger('click');
+
+ expect(wrapper.emitted('toggle-attention-requested')[0]).toEqual([
+ {
+ user: { attention_requested: true },
+ callback: expect.anything(),
+ },
+ ]);
+ });
+
+ it('sets loading on click', async () => {
+ factory({ type: 'reviewer', user: { attention_requested: true } });
+
+ await findToggle().trigger('click');
+
+ expect(findToggle().props('loading')).toBe(true);
+ });
+
+ it.each`
+ type | attentionRequested | tooltip
+ ${'reviewer'} | ${true} | ${AttentionRequestedToggle.i18n.removeAttentionRequested}
+ ${'reviewer'} | ${false} | ${AttentionRequestedToggle.i18n.attentionRequestedReviewer}
+ ${'assignee'} | ${false} | ${AttentionRequestedToggle.i18n.attentionRequestedAssignee}
+ `(
+ 'sets tooltip as $tooltip when attention_requested is $attentionRequested and type is $type',
+ ({ type, attentionRequested, tooltip }) => {
+ factory({ type, user: { attention_requested: attentionRequested } });
+
+ expect(findToggle().attributes('aria-label')).toBe(tooltip);
+ },
+ );
+});
diff --git a/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js b/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js
index 6b80224083a..13887f28d22 100644
--- a/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js
+++ b/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
+import AttentionRequestedToggle from '~/sidebar/components/attention_requested_toggle.vue';
import ReviewerAvatarLink from '~/sidebar/components/reviewers/reviewer_avatar_link.vue';
import UncollapsedReviewerList from '~/sidebar/components/reviewers/uncollapsed_reviewer_list.vue';
import userDataMock from '../../user_data_mock';
@@ -9,7 +10,7 @@ describe('UncollapsedReviewerList component', () => {
const reviewerApprovalIcons = () => wrapper.findAll('[data-testid="re-approved"]');
- function createComponent(props = {}) {
+ function createComponent(props = {}, glFeatures = {}) {
const propsData = {
users: [],
rootPath: TEST_HOST,
@@ -18,6 +19,9 @@ describe('UncollapsedReviewerList component', () => {
wrapper = shallowMount(UncollapsedReviewerList, {
propsData,
+ provide: {
+ glFeatures,
+ },
});
}
@@ -110,4 +114,18 @@ describe('UncollapsedReviewerList component', () => {
expect(wrapper.find('[data-testid="re-request-success"]').exists()).toBe(true);
});
});
+
+ it('hides re-request review button when attentionRequired feature flag is enabled', () => {
+ createComponent({ users: [userDataMock()] }, { mrAttentionRequests: true });
+
+ expect(wrapper.findAll('[data-testid="re-request-button"]').length).toBe(0);
+ });
+
+ it('emits toggle-attention-requested', () => {
+ createComponent({ users: [userDataMock()] }, { mrAttentionRequests: true });
+
+ wrapper.find(AttentionRequestedToggle).vm.$emit('toggle-attention-requested', 'data');
+
+ expect(wrapper.emitted('toggle-attention-requested')[0]).toEqual(['data']);
+ });
});
diff --git a/spec/frontend/sidebar/components/time_tracking/report_spec.js b/spec/frontend/sidebar/components/time_tracking/report_spec.js
index 66218626e6b..64d143615a0 100644
--- a/spec/frontend/sidebar/components/time_tracking/report_spec.js
+++ b/spec/frontend/sidebar/components/time_tracking/report_spec.js
@@ -50,7 +50,7 @@ describe('Issuable Time Tracking Report', () => {
it('should render loading spinner', () => {
mountComponent();
- expect(findLoadingIcon()).toExist();
+ expect(findLoadingIcon().exists()).toBe(true);
});
it('should render error message on reject', async () => {
diff --git a/spec/frontend/sidebar/sidebar_mediator_spec.js b/spec/frontend/sidebar/sidebar_mediator_spec.js
index cb84c142d55..3d7baaff10a 100644
--- a/spec/frontend/sidebar/sidebar_mediator_spec.js
+++ b/spec/frontend/sidebar/sidebar_mediator_spec.js
@@ -4,8 +4,11 @@ import * as urlUtility from '~/lib/utils/url_utility';
import SidebarService, { gqClient } from '~/sidebar/services/sidebar_service';
import SidebarMediator from '~/sidebar/sidebar_mediator';
import SidebarStore from '~/sidebar/stores/sidebar_store';
+import toast from '~/vue_shared/plugins/global_toast';
import Mock from './mock_data';
+jest.mock('~/vue_shared/plugins/global_toast');
+
describe('Sidebar mediator', () => {
const { mediator: mediatorMockData } = Mock;
let mock;
@@ -115,4 +118,56 @@ describe('Sidebar mediator', () => {
urlSpy.mockRestore();
});
});
+
+ describe('toggleAttentionRequested', () => {
+ let attentionRequiredService;
+
+ beforeEach(() => {
+ attentionRequiredService = jest
+ .spyOn(mediator.service, 'toggleAttentionRequested')
+ .mockResolvedValue();
+ });
+
+ it('calls attentionRequired service method', async () => {
+ mediator.store.reviewers = [{ id: 1, attention_requested: false, username: 'root' }];
+
+ await mediator.toggleAttentionRequested('reviewer', {
+ user: { id: 1, username: 'root' },
+ callback: jest.fn(),
+ });
+
+ expect(attentionRequiredService).toHaveBeenCalledWith(1);
+ });
+
+ it.each`
+ type | method
+ ${'reviewer'} | ${'findReviewer'}
+ `('finds $type', ({ type, method }) => {
+ const methodSpy = jest.spyOn(mediator.store, method);
+
+ mediator.toggleAttentionRequested(type, { user: { id: 1 }, callback: jest.fn() });
+
+ expect(methodSpy).toHaveBeenCalledWith({ id: 1 });
+ });
+
+ it.each`
+ attentionRequested | toastMessage
+ ${true} | ${'Removed attention request from @root'}
+ ${false} | ${'Requested attention from @root'}
+ `(
+ 'it creates toast $toastMessage when attention_requested is $attentionRequested',
+ async ({ attentionRequested, toastMessage }) => {
+ mediator.store.reviewers = [
+ { id: 1, attention_requested: attentionRequested, username: 'root' },
+ ];
+
+ await mediator.toggleAttentionRequested('reviewer', {
+ user: { id: 1, username: 'root' },
+ callback: jest.fn(),
+ });
+
+ expect(toast).toHaveBeenCalledWith(toastMessage);
+ },
+ );
+ });
});
diff --git a/spec/frontend/task_list_spec.js b/spec/frontend/task_list_spec.js
index 2d7a735bd11..bf470e7e126 100644
--- a/spec/frontend/task_list_spec.js
+++ b/spec/frontend/task_list_spec.js
@@ -125,6 +125,7 @@ describe('TaskList', () => {
const response = { data: { lock_version: 3 } };
jest.spyOn(taskList, 'enableTaskListItems').mockImplementation(() => {});
jest.spyOn(taskList, 'disableTaskListItems').mockImplementation(() => {});
+ jest.spyOn(taskList, 'onUpdate').mockImplementation(() => {});
jest.spyOn(taskList, 'onSuccess').mockImplementation(() => {});
jest.spyOn(axios, 'patch').mockReturnValue(Promise.resolve(response));
@@ -151,8 +152,11 @@ describe('TaskList', () => {
},
};
- taskList
- .update(event)
+ const update = taskList.update(event);
+
+ expect(taskList.onUpdate).toHaveBeenCalled();
+
+ update
.then(() => {
expect(taskList.disableTaskListItems).toHaveBeenCalledWith(event);
expect(axios.patch).toHaveBeenCalledWith(endpoint, patchData);
@@ -168,12 +172,17 @@ describe('TaskList', () => {
it('should handle request error and enable task list items', (done) => {
const response = { data: { error: 1 } };
jest.spyOn(taskList, 'enableTaskListItems').mockImplementation(() => {});
+ jest.spyOn(taskList, 'onUpdate').mockImplementation(() => {});
jest.spyOn(taskList, 'onError').mockImplementation(() => {});
jest.spyOn(axios, 'patch').mockReturnValue(Promise.reject({ response })); // eslint-disable-line prefer-promise-reject-errors
const event = { detail: {} };
- taskList
- .update(event)
+
+ const update = taskList.update(event);
+
+ expect(taskList.onUpdate).toHaveBeenCalled();
+
+ update
.then(() => {
expect(taskList.enableTaskListItems).toHaveBeenCalledWith(event);
expect(taskList.onError).toHaveBeenCalledWith(response.data);
diff --git a/spec/frontend/terms/components/app_spec.js b/spec/frontend/terms/components/app_spec.js
new file mode 100644
index 00000000000..ee78b35843a
--- /dev/null
+++ b/spec/frontend/terms/components/app_spec.js
@@ -0,0 +1,171 @@
+import $ from 'jquery';
+import { merge } from 'lodash';
+import { GlIntersectionObserver } from '@gitlab/ui';
+import { nextTick } from 'vue';
+
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { FLASH_TYPES, FLASH_CLOSED_EVENT } from '~/flash';
+import { isLoggedIn } from '~/lib/utils/common_utils';
+import TermsApp from '~/terms/components/app.vue';
+
+jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
+jest.mock('~/lib/utils/common_utils');
+
+describe('TermsApp', () => {
+ let wrapper;
+ let renderGFMSpy;
+
+ const defaultProvide = {
+ terms: 'foo bar',
+ paths: {
+ accept: '/-/users/terms/1/accept',
+ decline: '/-/users/terms/1/decline',
+ root: '/',
+ },
+ permissions: {
+ canAccept: true,
+ canDecline: true,
+ },
+ };
+
+ const createComponent = (provide = {}) => {
+ wrapper = mountExtended(TermsApp, {
+ provide: merge({}, defaultProvide, provide),
+ });
+ };
+
+ beforeEach(() => {
+ renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
+ isLoggedIn.mockReturnValue(true);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findFormWithAction = (path) => wrapper.find(`form[action="${path}"]`);
+ const findButton = (path) => findFormWithAction(path).find('button[type="submit"]');
+ const findScrollableViewport = () => wrapper.findByTestId('scrollable-viewport');
+
+ const expectFormWithSubmitButton = (buttonText, path) => {
+ const form = findFormWithAction(path);
+ const submitButton = findButton(path);
+
+ expect(form.exists()).toBe(true);
+ expect(submitButton.exists()).toBe(true);
+ expect(submitButton.text()).toBe(buttonText);
+ expect(
+ form
+ .find('input[type="hidden"][name="authenticity_token"][value="mock-csrf-token"]')
+ .exists(),
+ ).toBe(true);
+ };
+
+ it('renders terms of service as markdown', () => {
+ createComponent();
+
+ expect(wrapper.findByText(defaultProvide.terms).exists()).toBe(true);
+ expect(renderGFMSpy).toHaveBeenCalled();
+ });
+
+ describe('accept button', () => {
+ it('is disabled until user scrolls to the bottom of the terms', async () => {
+ createComponent();
+
+ expect(findButton(defaultProvide.paths.accept).attributes('disabled')).toBe('disabled');
+
+ wrapper.find(GlIntersectionObserver).vm.$emit('appear');
+
+ await nextTick();
+
+ expect(findButton(defaultProvide.paths.accept).attributes('disabled')).toBeUndefined();
+ });
+
+ describe('when user has permissions to accept', () => {
+ it('renders form and button to accept terms', () => {
+ createComponent();
+
+ expectFormWithSubmitButton(TermsApp.i18n.accept, defaultProvide.paths.accept);
+ });
+ });
+
+ describe('when user does not have permissions to accept', () => {
+ it('renders continue button', () => {
+ createComponent({ permissions: { canAccept: false } });
+
+ expect(wrapper.findByText(TermsApp.i18n.continue).exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('decline button', () => {
+ describe('when user has permissions to decline', () => {
+ it('renders form and button to decline terms', () => {
+ createComponent();
+
+ expectFormWithSubmitButton(TermsApp.i18n.decline, defaultProvide.paths.decline);
+ });
+ });
+
+ describe('when user does not have permissions to decline', () => {
+ it('does not render decline button', () => {
+ createComponent({ permissions: { canDecline: false } });
+
+ expect(wrapper.findByText(TermsApp.i18n.decline).exists()).toBe(false);
+ });
+ });
+ });
+
+ it('sets height of scrollable viewport', () => {
+ jest.spyOn(document.documentElement, 'scrollHeight', 'get').mockImplementation(() => 800);
+ jest.spyOn(document.documentElement, 'clientHeight', 'get').mockImplementation(() => 600);
+
+ createComponent();
+
+ expect(findScrollableViewport().attributes('style')).toBe('max-height: calc(100vh - 200px);');
+ });
+
+ describe('when flash is closed', () => {
+ let flashEl;
+
+ beforeEach(() => {
+ flashEl = document.createElement('div');
+ flashEl.classList.add(`flash-${FLASH_TYPES.ALERT}`);
+ document.body.appendChild(flashEl);
+ });
+
+ afterEach(() => {
+ document.body.innerHTML = '';
+ });
+
+ it('recalculates height of scrollable viewport', () => {
+ jest.spyOn(document.documentElement, 'scrollHeight', 'get').mockImplementation(() => 800);
+ jest.spyOn(document.documentElement, 'clientHeight', 'get').mockImplementation(() => 600);
+
+ createComponent();
+
+ expect(findScrollableViewport().attributes('style')).toBe('max-height: calc(100vh - 200px);');
+
+ jest.spyOn(document.documentElement, 'scrollHeight', 'get').mockImplementation(() => 700);
+ jest.spyOn(document.documentElement, 'clientHeight', 'get').mockImplementation(() => 600);
+
+ flashEl.dispatchEvent(new Event(FLASH_CLOSED_EVENT));
+
+ expect(findScrollableViewport().attributes('style')).toBe('max-height: calc(100vh - 100px);');
+ });
+ });
+
+ describe('when user is signed out', () => {
+ beforeEach(() => {
+ isLoggedIn.mockReturnValue(false);
+ });
+
+ it('does not show any buttons', () => {
+ createComponent();
+
+ expect(wrapper.findByText(TermsApp.i18n.accept).exists()).toBe(false);
+ expect(wrapper.findByText(TermsApp.i18n.decline).exists()).toBe(false);
+ expect(wrapper.findByText(TermsApp.i18n.continue).exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index 2c8e0fff848..40f68c6385f 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -47,10 +47,12 @@ Object.assign(global, {
setFixtures: setHTMLFixture,
});
+const JQUERY_MATCHERS_TO_EXCLUDE = ['toHaveLength', 'toExist'];
+
// custom-jquery-matchers was written for an old Jest version, we need to make it compatible
Object.entries(jqueryMatchers).forEach(([matcherName, matcherFactory]) => {
- // Don't override existing Jest matcher
- if (matcherName === 'toHaveLength') {
+ // Exclude these jQuery matchers
+ if (JQUERY_MATCHERS_TO_EXCLUDE.includes(matcherName)) {
return;
}
diff --git a/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js b/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js
index c9dea4394f9..c2606346292 100644
--- a/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js
+++ b/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js
@@ -1,14 +1,20 @@
import { shallowMount } from '@vue/test-utils';
import { toNounSeriesText } from '~/lib/utils/grammar';
import ApprovalsSummary from '~/vue_merge_request_widget/components/approvals/approvals_summary.vue';
-import { APPROVED_MESSAGE } from '~/vue_merge_request_widget/components/approvals/messages';
+import {
+ APPROVED_BY_OTHERS,
+ APPROVED_BY_YOU,
+ APPROVED_BY_YOU_AND_OTHERS,
+} from '~/vue_merge_request_widget/components/approvals/messages';
import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
+const exampleUserId = 1;
const testApprovers = () => Array.from({ length: 5 }, (_, i) => i).map((id) => ({ id }));
const testRulesLeft = () => ['Lorem', 'Ipsum', 'dolar & sit'];
const TEST_APPROVALS_LEFT = 3;
describe('MRWidget approvals summary', () => {
+ const originalUserId = gon.current_user_id;
let wrapper;
const createComponent = (props = {}) => {
@@ -28,6 +34,7 @@ describe('MRWidget approvals summary', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
+ gon.current_user_id = originalUserId;
});
describe('when approved', () => {
@@ -38,7 +45,7 @@ describe('MRWidget approvals summary', () => {
});
it('shows approved message', () => {
- expect(wrapper.text()).toContain(APPROVED_MESSAGE);
+ expect(wrapper.text()).toContain(APPROVED_BY_OTHERS);
});
it('renders avatar list for approvers', () => {
@@ -51,6 +58,48 @@ describe('MRWidget approvals summary', () => {
}),
);
});
+
+ describe('by the current user', () => {
+ beforeEach(() => {
+ gon.current_user_id = exampleUserId;
+ createComponent({
+ approvers: [{ id: exampleUserId }],
+ approved: true,
+ });
+ });
+
+ it('shows "Approved by you" message', () => {
+ expect(wrapper.text()).toContain(APPROVED_BY_YOU);
+ });
+ });
+
+ describe('by the current user and others', () => {
+ beforeEach(() => {
+ gon.current_user_id = exampleUserId;
+ createComponent({
+ approvers: [{ id: exampleUserId }, { id: exampleUserId + 1 }],
+ approved: true,
+ });
+ });
+
+ it('shows "Approved by you and others" message', () => {
+ expect(wrapper.text()).toContain(APPROVED_BY_YOU_AND_OTHERS);
+ });
+ });
+
+ describe('by other users than the current user', () => {
+ beforeEach(() => {
+ gon.current_user_id = exampleUserId;
+ createComponent({
+ approvers: [{ id: exampleUserId + 1 }],
+ approved: true,
+ });
+ });
+
+ it('shows "Approved by others" message', () => {
+ expect(wrapper.text()).toContain(APPROVED_BY_OTHERS);
+ });
+ });
});
describe('when not approved', () => {
diff --git a/spec/frontend/vue_mr_widget/components/extensions/actions_spec.js b/spec/frontend/vue_mr_widget/components/extensions/actions_spec.js
index d5d779d7a34..a13db2f4d72 100644
--- a/spec/frontend/vue_mr_widget/components/extensions/actions_spec.js
+++ b/spec/frontend/vue_mr_widget/components/extensions/actions_spec.js
@@ -24,6 +24,18 @@ describe('MR widget extension actions', () => {
expect(wrapper.findAllComponents(GlButton)).toHaveLength(1);
});
+ it('calls action click handler', async () => {
+ const onClick = jest.fn();
+
+ factory({
+ tertiaryButtons: [{ text: 'hello world', onClick }],
+ });
+
+ await wrapper.findComponent(GlButton).vm.$emit('click');
+
+ expect(onClick).toHaveBeenCalled();
+ });
+
it('renders tertiary actions in dropdown', () => {
factory({
tertiaryButtons: [{ text: 'hello world', href: 'https://gitlab.com', target: '_blank' }],
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
index ecaca16a2cd..6347e3c3be3 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -1,5 +1,7 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
import { trimText } from 'helpers/text_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue';
@@ -39,6 +41,8 @@ describe('MRWidgetPipeline', () => {
const findMonitoringPipelineMessage = () => wrapper.findByTestId('monitoring-pipeline-message');
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const mockArtifactsRequest = () => new MockAdapter(axios).onGet().reply(200, []);
+
const createWrapper = (props = {}, mountFn = shallowMount) => {
wrapper = extendedWrapper(
mountFn(PipelineComponent, {
@@ -71,6 +75,8 @@ describe('MRWidgetPipeline', () => {
describe('with a pipeline', () => {
beforeEach(() => {
+ mockArtifactsRequest();
+
createWrapper(
{
pipelineCoverageDelta: mockData.pipelineCoverageDelta,
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js
index b5afc1ab21a..8e710b6d65f 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js
@@ -1,4 +1,4 @@
-import { GlLink, GlSprintf } from '@gitlab/ui';
+import { GlSprintf } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper';
@@ -7,9 +7,7 @@ import MrWidgetIcon from '~/vue_merge_request_widget/components/mr_widget_icon.v
import suggestPipelineComponent from '~/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue';
import {
SP_TRACK_LABEL,
- SP_LINK_TRACK_EVENT,
SP_SHOW_TRACK_EVENT,
- SP_LINK_TRACK_VALUE,
SP_SHOW_TRACK_VALUE,
SP_HELP_URL,
} from '~/vue_merge_request_widget/constants';
@@ -52,15 +50,8 @@ describe('MRWidgetSuggestPipeline', () => {
mockAxios.restore();
});
- it('renders add pipeline file link', () => {
- const link = wrapper.find(GlLink);
-
- expect(link.exists()).toBe(true);
- expect(link.attributes().href).toBe(suggestProps.pipelinePath);
- });
-
it('renders the expected text', () => {
- const messageText = /\s*No pipeline\s*Add the .gitlab-ci.yml file\s*to create one./;
+ const messageText = /Looks like there's no pipeline here./;
expect(wrapper.text()).toMatch(messageText);
});
@@ -109,18 +100,6 @@ describe('MRWidgetSuggestPipeline', () => {
});
});
- it('send an event when add pipeline link is clicked', () => {
- mockTrackingOnWrapper();
- const link = wrapper.find('[data-testid="add-pipeline-link"]');
- triggerEvent(link.element);
-
- expect(trackingSpy).toHaveBeenCalledWith('_category_', SP_LINK_TRACK_EVENT, {
- label: SP_TRACK_LABEL,
- property: suggestProps.humanAccess,
- value: SP_LINK_TRACK_VALUE.toString(),
- });
- });
-
it('send an event when ok button is clicked', () => {
mockTrackingOnWrapper();
const okBtn = findOkBtn();
diff --git a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
index 5981d2d7849..56a0218b374 100644
--- a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
+++ b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
@@ -50,7 +50,7 @@ exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have
<span
class="gl-mr-3"
>
- The source branch will not be deleted
+ Does not delete the source branch
</span>
<gl-button-stub
@@ -122,7 +122,7 @@ exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have c
<span
class="gl-mr-3"
>
- The source branch will not be deleted
+ Does not delete the source branch
</span>
<gl-button-stub
diff --git a/spec/frontend/vue_mr_widget/components/states/__snapshots__/new_ready_to_merge_spec.js.snap b/spec/frontend/vue_mr_widget/components/states/__snapshots__/new_ready_to_merge_spec.js.snap
index a6c36764c41..f9936f22ea3 100644
--- a/spec/frontend/vue_mr_widget/components/states/__snapshots__/new_ready_to_merge_spec.js.snap
+++ b/spec/frontend/vue_mr_widget/components/states/__snapshots__/new_ready_to_merge_spec.js.snap
@@ -9,7 +9,7 @@ exports[`New ready to merge state component renders permission text if canMerge
/>
<p
- class="media-body gl-m-0! gl-font-weight-bold"
+ class="media-body gl-m-0! gl-font-weight-bold gl-text-gray-900!"
>
Ready to merge by members who can write to the target branch.
@@ -27,7 +27,7 @@ exports[`New ready to merge state component renders permission text if canMerge
/>
<p
- class="media-body gl-m-0! gl-font-weight-bold"
+ class="media-body gl-m-0! gl-font-weight-bold gl-text-gray-900!"
>
Ready to merge!
diff --git a/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js b/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
index 8214cedc4a1..f965fc32dc1 100644
--- a/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
@@ -3,6 +3,7 @@ import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit
const testCommitMessage = 'Test commit message';
const testLabel = 'Test label';
+const testTextMuted = 'Test text muted';
const testInputId = 'test-input-id';
describe('Commits edit component', () => {
@@ -63,7 +64,7 @@ describe('Commits edit component', () => {
beforeEach(() => {
createComponent({
header: `<div class="test-header">${testCommitMessage}</div>`,
- checkbox: `<label class="test-checkbox">${testLabel}</label >`,
+ 'text-muted': `<p class="test-text-muted">${testTextMuted}</p>`,
});
});
@@ -74,11 +75,11 @@ describe('Commits edit component', () => {
expect(headerSlotElement.text()).toBe(testCommitMessage);
});
- it('renders checkbox slot correctly', () => {
- const checkboxSlotElement = wrapper.find('.test-checkbox');
+ it('renders text-muted slot correctly', () => {
+ const textMutedElement = wrapper.find('.test-text-muted');
- expect(checkboxSlotElement.exists()).toBe(true);
- expect(checkboxSlotElement.text()).toBe(testLabel);
+ expect(textMutedElement.exists()).toBe(true);
+ expect(textMutedElement.text()).toBe(testTextMuted);
});
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
index 4c1534574f5..d0a6af9970e 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
@@ -270,8 +270,8 @@ describe('MRWidgetAutoMergeEnabled', () => {
const normalizedText = wrapper.text().replace(/\s+/g, ' ');
- expect(normalizedText).toContain('The source branch will be deleted');
- expect(normalizedText).not.toContain('The source branch will not be deleted');
+ expect(normalizedText).toContain('Deletes the source branch');
+ expect(normalizedText).not.toContain('Does not delete the source branch');
});
it('should not show delete source branch button when user not able to delete source branch', () => {
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
index 2ff94a547f4..5858654e518 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
@@ -1,4 +1,4 @@
-import { shallowMount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
@@ -6,7 +6,7 @@ describe('Commits header component', () => {
let wrapper;
const createComponent = (props) => {
- wrapper = shallowMount(CommitsHeader, {
+ wrapper = mount(CommitsHeader, {
stubs: {
GlSprintf,
},
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js
index 9c3a6d581e8..e0f1f091129 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js
@@ -191,7 +191,7 @@ describe('MRWidgetMerged', () => {
});
it('shows button to copy commit SHA to clipboard', () => {
- expect(selectors.copyMergeShaButton).toExist();
+ expect(selectors.copyMergeShaButton).not.toBe(null);
expect(selectors.copyMergeShaButton.getAttribute('data-clipboard-text')).toBe(
vm.mr.mergeCommitSha,
);
@@ -201,14 +201,14 @@ describe('MRWidgetMerged', () => {
vm.mr.mergeCommitSha = null;
Vue.nextTick(() => {
- expect(selectors.copyMergeShaButton).not.toExist();
+ expect(selectors.copyMergeShaButton).toBe(null);
expect(vm.$el.querySelector('.mr-info-list').innerText).not.toContain('with');
done();
});
});
it('shows merge commit SHA link', () => {
- expect(selectors.mergeCommitShaLink).toExist();
+ expect(selectors.mergeCommitShaLink).not.toBe(null);
expect(selectors.mergeCommitShaLink.text).toContain(vm.mr.shortMergeCommitSha);
expect(selectors.mergeCommitShaLink.href).toBe(vm.mr.mergeCommitPath);
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js
index b6c16958993..e6b2e9fa176 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js
@@ -42,7 +42,7 @@ describe('MRWidgetMerging', () => {
.trim()
.replace(/\s\s+/g, ' ')
.replace(/[\r\n]+/g, ' '),
- ).toEqual('The changes will be merged into branch');
+ ).toEqual('Merges changes into branch');
expect(wrapper.find('a').attributes('href')).toBe('/branch-path');
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index f0fbb1d5851..016b6b2220b 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -269,19 +269,6 @@ describe('ReadyToMerge', () => {
});
describe('methods', () => {
- describe('updateMergeCommitMessage', () => {
- it('should revert flag and change commitMessage', () => {
- createComponent();
-
- wrapper.vm.updateMergeCommitMessage(true);
-
- expect(wrapper.vm.commitMessage).toEqual(commitMessageWithDescription);
- wrapper.vm.updateMergeCommitMessage(false);
-
- expect(wrapper.vm.commitMessage).toEqual(commitMessage);
- });
- });
-
describe('handleMergeButtonClick', () => {
const returnPromise = (status) =>
new Promise((resolve) => {
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js
index 8ead0002950..6abdbd11f5e 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js
@@ -1,4 +1,4 @@
-import { GlFormCheckbox } from '@gitlab/ui';
+import { GlFormCheckbox, GlLink } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import SquashBeforeMerge from '~/vue_merge_request_widget/components/states/squash_before_merge.vue';
import { SQUASH_BEFORE_MERGE } from '~/vue_merge_request_widget/i18n';
@@ -77,7 +77,7 @@ describe('Squash before merge component', () => {
value: false,
});
- const aboutLink = wrapper.find('a');
+ const aboutLink = wrapper.findComponent(GlLink);
expect(aboutLink.exists()).toBe(false);
});
@@ -88,7 +88,7 @@ describe('Squash before merge component', () => {
helpPath: 'test-path',
});
- const aboutLink = wrapper.find('a');
+ const aboutLink = wrapper.findComponent(GlLink);
expect(aboutLink.exists()).toBe(true);
});
@@ -99,7 +99,7 @@ describe('Squash before merge component', () => {
helpPath: 'test-path',
});
- const aboutLink = wrapper.find('a');
+ const aboutLink = wrapper.findComponent(GlLink);
expect(aboutLink.attributes('href')).toEqual('test-path');
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
index be15e4df66d..0fb0d5b0b68 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
@@ -46,7 +46,7 @@ describe('Wip', () => {
is_new_mr_data: true,
};
- describe('handleRemoveWIP', () => {
+ describe('handleRemoveDraft', () => {
it('should make a request to service and handle response', (done) => {
const vm = createComponent();
@@ -59,7 +59,7 @@ describe('Wip', () => {
}),
);
- vm.handleRemoveWIP();
+ vm.handleRemoveDraft();
setImmediate(() => {
expect(vm.isMakingRequest).toBeTruthy();
expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
@@ -84,7 +84,7 @@ describe('Wip', () => {
expect(el.innerText).toContain('This merge request is still a draft.');
expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy();
expect(el.querySelector('button').innerText).toContain('Merge');
- expect(el.querySelector('.js-remove-wip').innerText.replace(/\s\s+/g, ' ')).toContain(
+ expect(el.querySelector('.js-remove-draft').innerText.replace(/\s\s+/g, ' ')).toContain(
'Mark as ready',
);
});
@@ -93,7 +93,7 @@ describe('Wip', () => {
vm.mr.removeWIPPath = '';
Vue.nextTick(() => {
- expect(el.querySelector('.js-remove-wip')).toEqual(null);
+ expect(el.querySelector('.js-remove-draft')).toEqual(null);
done();
});
});
diff --git a/spec/frontend/vue_mr_widget/mock_data.js b/spec/frontend/vue_mr_widget/mock_data.js
index 34a741cf8f2..f0c1da346a1 100644
--- a/spec/frontend/vue_mr_widget/mock_data.js
+++ b/spec/frontend/vue_mr_widget/mock_data.js
@@ -51,7 +51,7 @@ export default {
target_branch: 'main',
target_project_id: 19,
target_project_full_path: '/group2/project2',
- merge_request_add_ci_config_path: '/group2/project2/new/pipeline',
+ merge_request_add_ci_config_path: '/root/group2/project2/-/ci/editor',
is_dismissed_suggest_pipeline: false,
user_callouts_path: 'some/callout/path',
suggest_pipeline_feature_id: 'suggest_pipeline',
diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
index 5aba6982886..550f156d095 100644
--- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
@@ -1,4 +1,4 @@
-import { GlBadge, GlLink, GlIcon } from '@gitlab/ui';
+import { GlBadge, GlLink, GlIcon, GlButton, GlDropdown } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import Vue, { nextTick } from 'vue';
@@ -6,6 +6,7 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { securityReportMergeRequestDownloadPathsQueryResponse } from 'jest/vue_shared/security_reports/mock_data';
+import api from '~/api';
import axios from '~/lib/utils/axios_utils';
import { setFaviconOverlay } from '~/lib/utils/favicon';
import notify from '~/lib/utils/notify';
@@ -23,6 +24,8 @@ import { faviconDataUrl, overlayDataUrl } from '../lib/utils/mock_data';
import mockData from './mock_data';
import testExtension from './test_extension';
+jest.mock('~/api.js');
+
jest.mock('~/smart_interval');
jest.mock('~/lib/utils/favicon');
@@ -540,7 +543,7 @@ describe('MrWidgetOptions', () => {
nextTick(() => {
const tooltip = wrapper.find('[data-testid="question-o-icon"]');
- expect(wrapper.text()).toContain('The source branch will be deleted');
+ expect(wrapper.text()).toContain('Deletes the source branch');
expect(tooltip.attributes('title')).toBe(
'A user with write access to the source branch selected this option',
);
@@ -556,7 +559,7 @@ describe('MrWidgetOptions', () => {
nextTick(() => {
expect(wrapper.text()).toContain('The source branch has been deleted');
- expect(wrapper.text()).not.toContain('The source branch will be deleted');
+ expect(wrapper.text()).not.toContain('Deletes the source branch');
done();
});
@@ -904,6 +907,18 @@ describe('MrWidgetOptions', () => {
expect(wrapper.text()).toContain('Test extension summary count: 1');
});
+ it('triggers trackRedisHllUserEvent API call', async () => {
+ await waitForPromises();
+
+ wrapper
+ .find('[data-testid="widget-extension"] [data-testid="toggle-button"]')
+ .trigger('click');
+
+ await Vue.nextTick();
+
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith('test_expand_event');
+ });
+
it('renders full data', async () => {
await waitForPromises();
@@ -913,6 +928,10 @@ describe('MrWidgetOptions', () => {
await Vue.nextTick();
+ expect(
+ wrapper.find('[data-testid="widget-extension-top-level"]').find(GlDropdown).exists(),
+ ).toBe(false);
+
const collapsedSection = wrapper.find('[data-testid="widget-extension-collapsed-section"]');
expect(collapsedSection.exists()).toBe(true);
expect(collapsedSection.text()).toContain('Hello world');
@@ -928,6 +947,9 @@ describe('MrWidgetOptions', () => {
// Renders a link in the row
expect(collapsedSection.find(GlLink).exists()).toBe(true);
expect(collapsedSection.find(GlLink).text()).toBe('GitLab.com');
+
+ expect(collapsedSection.find(GlButton).exists()).toBe(true);
+ expect(collapsedSection.find(GlButton).text()).toBe('Full report');
});
});
});
diff --git a/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js b/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js
index 631d4647b17..fc760f5c5be 100644
--- a/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js
+++ b/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js
@@ -15,7 +15,7 @@ describe('getStateKey', () => {
branchMissing: false,
commitsCount: 2,
hasConflicts: false,
- workInProgress: false,
+ draft: false,
};
const bound = getStateKey.bind(context);
@@ -49,9 +49,9 @@ describe('getStateKey', () => {
expect(bound()).toEqual('unresolvedDiscussions');
- context.workInProgress = true;
+ context.draft = true;
- expect(bound()).toEqual('workInProgress');
+ expect(bound()).toEqual('draft');
context.onlyAllowMergeIfPipelineSucceeds = true;
context.isPipelineFailed = true;
@@ -74,6 +74,7 @@ describe('getStateKey', () => {
expect(bound()).toEqual('nothingToMerge');
+ context.commitsCount = 1;
context.branchMissing = true;
expect(bound()).toEqual('missingBranch');
@@ -98,7 +99,7 @@ describe('getStateKey', () => {
branchMissing: false,
commitsCount: 2,
hasConflicts: false,
- workInProgress: false,
+ draft: false,
};
const bound = getStateKey.bind(context);
diff --git a/spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js b/spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js
index febcfcd4019..6eb68a1b00d 100644
--- a/spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js
+++ b/spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js
@@ -129,7 +129,7 @@ describe('MergeRequestStore', () => {
it('should set the add ci config path', () => {
store.setPaths({ ...mockData });
- expect(store.mergeRequestAddCiConfigPath).toBe('/group2/project2/new/pipeline');
+ expect(store.mergeRequestAddCiConfigPath).toBe('/root/group2/project2/-/ci/editor');
});
it('should set humanAccess=Maintainer when user has that role', () => {
diff --git a/spec/frontend/vue_mr_widget/test_extension.js b/spec/frontend/vue_mr_widget/test_extension.js
index a29a4d2fb46..65c1bd8473b 100644
--- a/spec/frontend/vue_mr_widget/test_extension.js
+++ b/spec/frontend/vue_mr_widget/test_extension.js
@@ -3,6 +3,7 @@ import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants';
export default {
name: 'WidgetTestExtension',
props: ['targetProjectFullPath'],
+ expandEvent: 'test_expand_event',
computed: {
summary({ count, targetProjectFullPath }) {
return `Test extension summary count: ${count} & ${targetProjectFullPath}`;
@@ -30,6 +31,7 @@ export default {
href: 'https://gitlab.com',
text: 'GitLab.com',
},
+ actions: [{ text: 'Full report', href: 'https://gitlab.com', target: '_blank' }],
},
]);
},
diff --git a/spec/frontend/vue_shared/components/alerts_deprecation_warning_spec.js b/spec/frontend/vue_shared/components/alerts_deprecation_warning_spec.js
deleted file mode 100644
index b73f4d6a396..00000000000
--- a/spec/frontend/vue_shared/components/alerts_deprecation_warning_spec.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import { GlAlert, GlLink } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import AlertDeprecationWarning from '~/vue_shared/components/alerts_deprecation_warning.vue';
-
-describe('AlertDetails', () => {
- let wrapper;
-
- function mountComponent(hasManagedPrometheus = false) {
- wrapper = mount(AlertDeprecationWarning, {
- provide: {
- hasManagedPrometheus,
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- const findAlert = () => wrapper.findComponent(GlAlert);
- const findLink = () => wrapper.findComponent(GlLink);
-
- describe('Alert details', () => {
- describe('with no manual prometheus', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- it('renders nothing', () => {
- expect(findAlert().exists()).toBe(false);
- });
- });
-
- describe('with manual prometheus', () => {
- beforeEach(() => {
- mountComponent(true);
- });
-
- it('renders a deprecation notice', () => {
- expect(findAlert().text()).toContain('GitLab-managed Prometheus is deprecated');
- expect(findLink().attributes('href')).toContain(
- 'operations/metrics/alerts.html#managed-prometheus-instances',
- );
- });
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/confirm_danger/confirm_danger_modal_spec.js b/spec/frontend/vue_shared/components/confirm_danger/confirm_danger_modal_spec.js
new file mode 100644
index 00000000000..f75694bd504
--- /dev/null
+++ b/spec/frontend/vue_shared/components/confirm_danger/confirm_danger_modal_spec.js
@@ -0,0 +1,99 @@
+import { GlModal, GlSprintf } from '@gitlab/ui';
+import {
+ CONFIRM_DANGER_WARNING,
+ CONFIRM_DANGER_MODAL_BUTTON,
+ CONFIRM_DANGER_MODAL_ID,
+} from '~/vue_shared/components/confirm_danger/constants';
+import ConfirmDangerModal from '~/vue_shared/components/confirm_danger/confirm_danger_modal.vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
+describe('Confirm Danger Modal', () => {
+ const confirmDangerMessage = 'This is a dangerous activity';
+ const confirmButtonText = 'Confirm button text';
+ const phrase = 'You must construct additional pylons';
+ const modalId = CONFIRM_DANGER_MODAL_ID;
+
+ let wrapper;
+
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findConfirmationPhrase = () => wrapper.findByTestId('confirm-danger-phrase');
+ const findConfirmationInput = () => wrapper.findByTestId('confirm-danger-input');
+ const findDefaultWarning = () => wrapper.findByTestId('confirm-danger-warning');
+ const findAdditionalMessage = () => wrapper.findByTestId('confirm-danger-message');
+ const findPrimaryAction = () => findModal().props('actionPrimary');
+ const findPrimaryActionAttributes = (attr) => findPrimaryAction().attributes[0][attr];
+
+ const createComponent = ({ provide = {} } = {}) =>
+ shallowMountExtended(ConfirmDangerModal, {
+ propsData: {
+ modalId,
+ phrase,
+ },
+ provide,
+ stubs: { GlSprintf },
+ });
+
+ beforeEach(() => {
+ wrapper = createComponent({ provide: { confirmDangerMessage, confirmButtonText } });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders the default warning message', () => {
+ expect(findDefaultWarning().text()).toBe(CONFIRM_DANGER_WARNING);
+ });
+
+ it('renders any additional messages', () => {
+ expect(findAdditionalMessage().text()).toBe(confirmDangerMessage);
+ });
+
+ it('renders the confirm button', () => {
+ expect(findPrimaryAction().text).toBe(confirmButtonText);
+ expect(findPrimaryActionAttributes('variant')).toBe('danger');
+ });
+
+ it('renders the correct confirmation phrase', () => {
+ expect(findConfirmationPhrase().text()).toBe(
+ `Please type ${phrase} to proceed or close this modal to cancel.`,
+ );
+ });
+
+ describe('without injected data', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('does not render any additional messages', () => {
+ expect(findAdditionalMessage().exists()).toBe(false);
+ });
+
+ it('renders the default confirm button', () => {
+ expect(findPrimaryAction().text).toBe(CONFIRM_DANGER_MODAL_BUTTON);
+ });
+ });
+
+ describe('with a valid confirmation phrase', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('enables the confirm button', async () => {
+ expect(findPrimaryActionAttributes('disabled')).toBe(true);
+
+ await findConfirmationInput().vm.$emit('input', phrase);
+
+ expect(findPrimaryActionAttributes('disabled')).toBe(false);
+ });
+
+ it('emits a `confirm` event when the button is clicked', async () => {
+ expect(wrapper.emitted('confirm')).toBeUndefined();
+
+ await findConfirmationInput().vm.$emit('input', phrase);
+ await findModal().vm.$emit('primary');
+
+ expect(wrapper.emitted('confirm')).not.toBeUndefined();
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/confirm_danger/confirm_danger_spec.js b/spec/frontend/vue_shared/components/confirm_danger/confirm_danger_spec.js
new file mode 100644
index 00000000000..220f897c035
--- /dev/null
+++ b/spec/frontend/vue_shared/components/confirm_danger/confirm_danger_spec.js
@@ -0,0 +1,61 @@
+import { GlButton } from '@gitlab/ui';
+import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
+import ConfirmDangerModal from '~/vue_shared/components/confirm_danger/confirm_danger_modal.vue';
+import { CONFIRM_DANGER_MODAL_ID } from '~/vue_shared/components/confirm_danger/constants';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
+describe('Confirm Danger Modal', () => {
+ let wrapper;
+
+ const phrase = 'En Taro Adun';
+ const buttonText = 'Click me!';
+ const modalId = CONFIRM_DANGER_MODAL_ID;
+
+ const findBtn = () => wrapper.findComponent(GlButton);
+ const findModal = () => wrapper.findComponent(ConfirmDangerModal);
+ const findModalProps = () => findModal().props();
+
+ const createComponent = (props = {}) =>
+ shallowMountExtended(ConfirmDanger, {
+ propsData: {
+ buttonText,
+ phrase,
+ ...props,
+ },
+ });
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders the button', () => {
+ expect(wrapper.html()).toContain(buttonText);
+ });
+
+ it('sets the modal properties', () => {
+ expect(findModalProps()).toMatchObject({
+ modalId,
+ phrase,
+ });
+ });
+
+ it('will disable the button if `disabled=true`', () => {
+ expect(findBtn().attributes('disabled')).toBeUndefined();
+
+ wrapper = createComponent({ disabled: true });
+
+ expect(findBtn().attributes('disabled')).toBe('true');
+ });
+
+ it('will emit `confirm` when the modal confirms', () => {
+ expect(wrapper.emitted('confirm')).toBeUndefined();
+
+ findModal().vm.$emit('confirm');
+
+ expect(wrapper.emitted('confirm')).not.toBeUndefined();
+ });
+});
diff --git a/spec/frontend/vue_shared/components/content_viewer/content_viewer_spec.js b/spec/frontend/vue_shared/components/content_viewer/content_viewer_spec.js
index 16e7e4dd5cc..f28805471f8 100644
--- a/spec/frontend/vue_shared/components/content_viewer/content_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/content_viewer/content_viewer_spec.js
@@ -16,6 +16,6 @@ describe('ContentViewer', () => {
propsData: { path, fileSize: 1024, type },
});
- expect(wrapper.find(selector).element).toExist();
+ expect(wrapper.find(selector).exists()).toBe(true);
});
});
diff --git a/spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js b/spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js
index 3ffb23dc7a0..1397fb0405e 100644
--- a/spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js
@@ -42,7 +42,7 @@ describe('MarkdownViewer', () => {
it('renders an animation container while the markdown is loading', () => {
createComponent();
- expect(wrapper.find('.animation-container')).toExist();
+ expect(wrapper.find('.animation-container').exists()).toBe(true);
});
it('renders markdown preview preview renders and loads rendered markdown from server', () => {
diff --git a/spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js b/spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js
index 016fe1f131e..b3af5fd3feb 100644
--- a/spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js
+++ b/spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js
@@ -34,6 +34,7 @@ describe('DropdownWidget component', () => {
// invokes `show` method of BDropdown used inside GlDropdown.
// Context: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54895#note_524281679
jest.spyOn(wrapper.vm, 'showDropdown').mockImplementation();
+ jest.spyOn(findDropdown().vm, 'hide').mockImplementation();
};
beforeEach(() => {
@@ -67,10 +68,7 @@ describe('DropdownWidget component', () => {
});
it('emits set-option event when clicking on an option', async () => {
- wrapper
- .findAll('[data-testid="unselected-option"]')
- .at(1)
- .vm.$emit('click', new Event('click'));
+ wrapper.findAll('[data-testid="unselected-option"]').at(1).trigger('click');
await wrapper.vm.$nextTick();
expect(wrapper.emitted('set-option')).toEqual([[wrapper.props().options[1]]]);
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
index 8e931aebfe0..64d15884333 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
@@ -25,6 +25,7 @@ import {
tokenValueMilestone,
tokenValueMembership,
tokenValueConfidential,
+ tokenValueEmpty,
} from './mock_data';
jest.mock('~/vue_shared/components/filtered_search_bar/filtered_search_utils', () => ({
@@ -43,6 +44,7 @@ const createComponent = ({
recentSearchesStorageKey = 'requirements',
tokens = mockAvailableTokens,
sortOptions,
+ initialFilterValue = [],
showCheckbox = false,
checkboxChecked = false,
searchInputPlaceholder = 'Filter requirements',
@@ -55,6 +57,7 @@ const createComponent = ({
recentSearchesStorageKey,
tokens,
sortOptions,
+ initialFilterValue,
showCheckbox,
checkboxChecked,
searchInputPlaceholder,
@@ -193,19 +196,27 @@ describe('FilteredSearchBarRoot', () => {
describe('watchers', () => {
describe('filterValue', () => {
- it('emits component event `onFilter` with empty array when `filterValue` is cleared by GlFilteredSearch', () => {
+ it('emits component event `onFilter` with empty array and false when filter was never selected', () => {
+ wrapper = createComponent({ initialFilterValue: [tokenValueEmpty] });
wrapper.setData({
initialRender: false,
- filterValue: [
- {
- type: 'filtered-search-term',
- value: { data: '' },
- },
- ],
+ filterValue: [tokenValueEmpty],
+ });
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.emitted('onFilter')[0]).toEqual([[], false]);
+ });
+ });
+
+ it('emits component event `onFilter` with empty array and true when initially selected filter value was cleared', () => {
+ wrapper = createComponent({ initialFilterValue: [tokenValueLabel] });
+ wrapper.setData({
+ initialRender: false,
+ filterValue: [tokenValueEmpty],
});
return wrapper.vm.$nextTick(() => {
- expect(wrapper.emitted('onFilter')[0]).toEqual([[]]);
+ expect(wrapper.emitted('onFilter')[0]).toEqual([[], true]);
});
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
index ae02c554e13..238c5d16db5 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
@@ -9,6 +9,7 @@ import EpicToken from '~/vue_shared/components/filtered_search_bar/tokens/epic_t
import IterationToken from '~/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
+import ReleaseToken from '~/vue_shared/components/filtered_search_bar/tokens/release_token.vue';
import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue';
export const mockAuthor1 = {
@@ -110,6 +111,18 @@ export const mockIterationToken = {
fetchIterations: () => Promise.resolve(),
};
+export const mockIterations = [
+ {
+ id: 1,
+ title: 'Iteration 1',
+ startDate: '2021-11-05',
+ dueDate: '2021-11-10',
+ iterationCadence: {
+ title: 'Cadence 1',
+ },
+ },
+];
+
export const mockLabelToken = {
type: 'label_name',
icon: 'labels',
@@ -132,6 +145,14 @@ export const mockMilestoneToken = {
fetchMilestones: () => Promise.resolve({ data: mockMilestones }),
};
+export const mockReleaseToken = {
+ type: 'release',
+ icon: 'rocket',
+ title: 'Release',
+ token: ReleaseToken,
+ fetchReleases: () => Promise.resolve(),
+};
+
export const mockEpicToken = {
type: 'epic_iid',
icon: 'clock',
@@ -282,6 +303,11 @@ export const tokenValuePlain = {
value: { data: 'foo' },
};
+export const tokenValueEmpty = {
+ type: 'filtered-search-term',
+ value: { data: '' },
+};
+
export const tokenValueEpic = {
type: 'epic_iid',
value: {
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
index 14fcffd3c50..b29c394e7ae 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
@@ -112,6 +112,35 @@ describe('AuthorToken', () => {
});
});
+ // TODO: rm when completed https://gitlab.com/gitlab-org/gitlab/-/issues/345756
+ describe('when there are null users presents', () => {
+ const mockAuthorsWithNullUser = mockAuthors.concat([null]);
+
+ beforeEach(() => {
+ jest
+ .spyOn(wrapper.vm.config, 'fetchAuthors')
+ .mockResolvedValue({ data: mockAuthorsWithNullUser });
+
+ getBaseToken().vm.$emit('fetch-suggestions', 'root');
+ });
+
+ describe('when res.data is present', () => {
+ it('filters the successful response when null values are present', () => {
+ return waitForPromises().then(() => {
+ expect(getBaseToken().props('suggestions')).toEqual(mockAuthors);
+ });
+ });
+ });
+
+ describe('when response is an array', () => {
+ it('filters the successful response when null values are present', () => {
+ return waitForPromises().then(() => {
+ expect(getBaseToken().props('suggestions')).toEqual(mockAuthors);
+ });
+ });
+ });
+ });
+
it('calls `createFlash` with flash error message when request fails', () => {
jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockRejectedValue({});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js
index af90ee93543..44bc16adb97 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js
@@ -1,9 +1,13 @@
-import { GlFilteredSearchToken, GlFilteredSearchTokenSegment } from '@gitlab/ui';
+import {
+ GlFilteredSearchToken,
+ GlFilteredSearchTokenSegment,
+ GlFilteredSearchSuggestion,
+} from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import IterationToken from '~/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue';
-import { mockIterationToken } from '../mock_data';
+import { mockIterationToken, mockIterations } from '../mock_data';
jest.mock('~/flash');
@@ -11,10 +15,16 @@ describe('IterationToken', () => {
const id = 123;
let wrapper;
- const createComponent = ({ config = mockIterationToken, value = { data: '' } } = {}) =>
+ const createComponent = ({
+ config = mockIterationToken,
+ value = { data: '' },
+ active = false,
+ stubs = {},
+ provide = {},
+ } = {}) =>
mount(IterationToken, {
propsData: {
- active: false,
+ active,
config,
value,
},
@@ -22,13 +32,39 @@ describe('IterationToken', () => {
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
suggestionsListClass: () => 'custom-class',
+ ...provide,
},
+ stubs,
});
afterEach(() => {
wrapper.destroy();
});
+ describe('when iteration cadence feature is available', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockIterationToken, initialIterations: mockIterations },
+ value: { data: 'i' },
+ stubs: { Portal: true },
+ provide: {
+ glFeatures: {
+ iterationCadences: true,
+ },
+ },
+ });
+
+ await wrapper.setData({ loading: false });
+ });
+
+ it('renders iteration start date and due date', () => {
+ const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+
+ expect(suggestions.at(3).text()).toContain('Nov 5, 2021 - Nov 10, 2021');
+ });
+ });
+
it('renders iteration value', async () => {
wrapper = createComponent({ value: { data: id } });
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js
new file mode 100644
index 00000000000..b804ff97b82
--- /dev/null
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js
@@ -0,0 +1,78 @@
+import { GlFilteredSearchToken, GlFilteredSearchTokenSegment } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import ReleaseToken from '~/vue_shared/components/filtered_search_bar/tokens/release_token.vue';
+import { mockReleaseToken } from '../mock_data';
+
+jest.mock('~/flash');
+
+describe('ReleaseToken', () => {
+ const id = 123;
+ let wrapper;
+
+ const createComponent = ({ config = mockReleaseToken, value = { data: '' } } = {}) =>
+ mount(ReleaseToken, {
+ propsData: {
+ active: false,
+ config,
+ value,
+ },
+ provide: {
+ portalName: 'fake target',
+ alignSuggestions: function fakeAlignSuggestions() {},
+ suggestionsListClass: () => 'custom-class',
+ },
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders release value', async () => {
+ wrapper = createComponent({ value: { data: id } });
+ await wrapper.vm.$nextTick();
+
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
+
+ expect(tokenSegments).toHaveLength(3); // `Release` `=` `v1`
+ expect(tokenSegments.at(2).text()).toBe(id.toString());
+ });
+
+ it('fetches initial values', () => {
+ const fetchReleasesSpy = jest.fn().mockResolvedValue();
+
+ wrapper = createComponent({
+ config: { ...mockReleaseToken, fetchReleases: fetchReleasesSpy },
+ value: { data: id },
+ });
+
+ expect(fetchReleasesSpy).toHaveBeenCalledWith(id);
+ });
+
+ it('fetches releases on user input', () => {
+ const search = 'hello';
+ const fetchReleasesSpy = jest.fn().mockResolvedValue();
+
+ wrapper = createComponent({
+ config: { ...mockReleaseToken, fetchReleases: fetchReleasesSpy },
+ });
+
+ wrapper.findComponent(GlFilteredSearchToken).vm.$emit('input', { data: search });
+
+ expect(fetchReleasesSpy).toHaveBeenCalledWith(search);
+ });
+
+ it('renders error message when request fails', async () => {
+ const fetchReleasesSpy = jest.fn().mockRejectedValue();
+
+ wrapper = createComponent({
+ config: { ...mockReleaseToken, fetchReleases: fetchReleasesSpy },
+ });
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'There was a problem fetching releases.',
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/header_ci_component_spec.js b/spec/frontend/vue_shared/components/header_ci_component_spec.js
index 42f4439df51..b76f475a6fb 100644
--- a/spec/frontend/vue_shared/components/header_ci_component_spec.js
+++ b/spec/frontend/vue_shared/components/header_ci_component_spec.js
@@ -1,4 +1,4 @@
-import { GlButton, GlLink } from '@gitlab/ui';
+import { GlButton, GlAvatarLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import CiIconBadge from '~/vue_shared/components/ci_badge_link.vue';
@@ -18,6 +18,7 @@ describe('Header CI Component', () => {
},
time: '2017-05-08T14:57:39.781Z',
user: {
+ id: 1234,
web_url: 'path',
name: 'Foo',
username: 'foobar',
@@ -29,7 +30,7 @@ describe('Header CI Component', () => {
const findIconBadge = () => wrapper.findComponent(CiIconBadge);
const findTimeAgo = () => wrapper.findComponent(TimeagoTooltip);
- const findUserLink = () => wrapper.findComponent(GlLink);
+ const findUserLink = () => wrapper.findComponent(GlAvatarLink);
const findSidebarToggleBtn = () => wrapper.findComponent(GlButton);
const findActionButtons = () => wrapper.findByTestId('ci-header-action-buttons');
const findHeaderItemText = () => wrapper.findByTestId('ci-header-item-text');
@@ -64,10 +65,6 @@ describe('Header CI Component', () => {
expect(findTimeAgo().exists()).toBe(true);
});
- it('should render user icon and name', () => {
- expect(findUserLink().text()).toContain(defaultProps.user.name);
- });
-
it('should render sidebar toggle button', () => {
expect(findSidebarToggleBtn().exists()).toBe(true);
});
@@ -77,6 +74,45 @@ describe('Header CI Component', () => {
});
});
+ describe('user avatar', () => {
+ beforeEach(() => {
+ createComponent({ itemName: 'Pipeline' });
+ });
+
+ it('contains the username', () => {
+ expect(findUserLink().text()).toContain(defaultProps.user.username);
+ });
+
+ it('has the correct data attributes', () => {
+ expect(findUserLink().attributes()).toMatchObject({
+ 'data-user-id': defaultProps.user.id.toString(),
+ 'data-username': defaultProps.user.username,
+ 'data-name': defaultProps.user.name,
+ });
+ });
+
+ describe('with data from GraphQL', () => {
+ const userId = 1;
+
+ beforeEach(() => {
+ createComponent({
+ itemName: 'Pipeline',
+ user: { ...defaultProps.user, id: `gid://gitlab/User/${1}` },
+ });
+ });
+
+ it('has the correct user id', () => {
+ expect(findUserLink().attributes('data-user-id')).toBe(userId.toString());
+ });
+ });
+
+ describe('with data from REST', () => {
+ it('has the correct user id', () => {
+ expect(findUserLink().attributes('data-user-id')).toBe(defaultProps.user.id.toString());
+ });
+ });
+ });
+
describe('with item id', () => {
beforeEach(() => {
createComponent({ itemName: 'Pipeline', itemId: '123' });
diff --git a/spec/frontend/vue_shared/components/notes/system_note_spec.js b/spec/frontend/vue_shared/components/notes/system_note_spec.js
index 48dacc50923..65f79bab005 100644
--- a/spec/frontend/vue_shared/components/notes/system_note_spec.js
+++ b/spec/frontend/vue_shared/components/notes/system_note_spec.js
@@ -1,13 +1,27 @@
+import MockAdapter from 'axios-mock-adapter';
import { mount } from '@vue/test-utils';
+import waitForPromises from 'helpers/wait_for_promises';
import initMRPopovers from '~/mr_popover/index';
import createStore from '~/notes/stores';
import IssueSystemNote from '~/vue_shared/components/notes/system_note.vue';
+import axios from '~/lib/utils/axios_utils';
jest.mock('~/mr_popover/index', () => jest.fn());
describe('system note component', () => {
let vm;
let props;
+ let mock;
+
+ function createComponent(propsData = {}) {
+ const store = createStore();
+ store.dispatch('setTargetNoteHash', `note_${props.note.id}`);
+
+ vm = mount(IssueSystemNote, {
+ store,
+ propsData,
+ });
+ }
beforeEach(() => {
props = {
@@ -27,28 +41,29 @@ describe('system note component', () => {
},
};
- const store = createStore();
- store.dispatch('setTargetNoteHash', `note_${props.note.id}`);
-
- vm = mount(IssueSystemNote, {
- store,
- propsData: props,
- });
+ mock = new MockAdapter(axios);
});
afterEach(() => {
vm.destroy();
+ mock.restore();
});
it('should render a list item with correct id', () => {
+ createComponent(props);
+
expect(vm.attributes('id')).toEqual(`note_${props.note.id}`);
});
it('should render target class is note is target note', () => {
+ createComponent(props);
+
expect(vm.classes()).toContain('target');
});
it('should render svg icon', () => {
+ createComponent(props);
+
expect(vm.find('.timeline-icon svg').exists()).toBe(true);
});
@@ -56,10 +71,31 @@ describe('system note component', () => {
// we need to strip them because they break layout of commit lists in system notes:
// https://gitlab.com/gitlab-org/gitlab-foss/uploads/b07a10670919254f0220d3ff5c1aa110/jqzI.png
it('removes wrapping paragraph from note HTML', () => {
+ createComponent(props);
+
expect(vm.find('.system-note-message').html()).toContain('<span>closed</span>');
});
it('should initMRPopovers onMount', () => {
+ createComponent(props);
+
expect(initMRPopovers).toHaveBeenCalled();
});
+
+ it('renders outdated code lines', async () => {
+ mock
+ .onGet('/outdated_line_change_path')
+ .reply(200, [
+ { rich_text: 'console.log', type: 'new', line_code: '123', old_line: null, new_line: 1 },
+ ]);
+
+ createComponent({
+ note: { ...props.note, outdated_line_change_path: '/outdated_line_change_path' },
+ });
+
+ await vm.find("[data-testid='outdated-lines-change-btn']").trigger('click');
+ await waitForPromises();
+
+ expect(vm.find("[data-testid='outdated-lines']").exists()).toBe(true);
+ });
});
diff --git a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
index 1ed7844b395..7fdacbe83a2 100644
--- a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
+++ b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
@@ -1,6 +1,5 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
-// eslint-disable-next-line import/no-deprecated
-import { getJSONFixture } from 'helpers/fixtures';
+import mockProjects from 'test_fixtures_static/projects.json';
import { trimText } from 'helpers/text_helper';
import ProjectAvatar from '~/vue_shared/components/deprecated_project_avatar/default.vue';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
@@ -13,8 +12,7 @@ describe('ProjectListItem component', () => {
let vm;
let options;
- // eslint-disable-next-line import/no-deprecated
- const project = getJSONFixture('static/projects.json')[0];
+ const project = JSON.parse(JSON.stringify(mockProjects))[0];
beforeEach(() => {
options = {
diff --git a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
index 1f97d3ff3fa..de5cee846a1 100644
--- a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
+++ b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
@@ -2,8 +2,7 @@ import { GlSearchBoxByType, GlInfiniteScroll } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import { head } from 'lodash';
import Vue from 'vue';
-// eslint-disable-next-line import/no-deprecated
-import { getJSONFixture } from 'helpers/fixtures';
+import mockProjects from 'test_fixtures_static/projects.json';
import { trimText } from 'helpers/text_helper';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
import ProjectSelector from '~/vue_shared/components/project_selector/project_selector.vue';
@@ -13,8 +12,7 @@ const localVue = createLocalVue();
describe('ProjectSelector component', () => {
let wrapper;
let vm;
- // eslint-disable-next-line import/no-deprecated
- const allProjects = getJSONFixture('static/projects.json');
+ const allProjects = mockProjects;
const searchResults = allProjects.slice(0, 5);
let selected = [];
selected = selected.concat(allProjects.slice(0, 3)).concat(allProjects.slice(5, 8));
diff --git a/spec/frontend/vue_shared/components/registry/title_area_spec.js b/spec/frontend/vue_shared/components/registry/title_area_spec.js
index 75aa3bc7096..b62676b35be 100644
--- a/spec/frontend/vue_shared/components/registry/title_area_spec.js
+++ b/spec/frontend/vue_shared/components/registry/title_area_spec.js
@@ -1,5 +1,6 @@
import { GlAvatar, GlSprintf, GlLink, GlSkeletonLoader } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import component from '~/vue_shared/components/registry/title_area.vue';
describe('title area', () => {
@@ -7,18 +8,18 @@ describe('title area', () => {
const DYNAMIC_SLOT = 'metadata-dynamic-slot';
- const findSubHeaderSlot = () => wrapper.find('[data-testid="sub-header"]');
- const findRightActionsSlot = () => wrapper.find('[data-testid="right-actions"]');
- const findMetadataSlot = (name) => wrapper.find(`[data-testid="${name}"]`);
- const findTitle = () => wrapper.find('[data-testid="title"]');
- const findAvatar = () => wrapper.find(GlAvatar);
- const findInfoMessages = () => wrapper.findAll('[data-testid="info-message"]');
- const findDynamicSlot = () => wrapper.find(`[data-testid="${DYNAMIC_SLOT}`);
+ const findSubHeaderSlot = () => wrapper.findByTestId('sub-header');
+ const findRightActionsSlot = () => wrapper.findByTestId('right-actions');
+ const findMetadataSlot = (name) => wrapper.findByTestId(name);
+ const findTitle = () => wrapper.findByTestId('title');
+ const findAvatar = () => wrapper.findComponent(GlAvatar);
+ const findInfoMessages = () => wrapper.findAllByTestId('info-message');
+ const findDynamicSlot = () => wrapper.findByTestId(DYNAMIC_SLOT);
const findSlotOrderElements = () => wrapper.findAll('[slot-test]');
- const findSkeletonLoader = () => wrapper.find(GlSkeletonLoader);
+ const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
const mountComponent = ({ propsData = { title: 'foo' }, slots } = {}) => {
- wrapper = shallowMount(component, {
+ wrapper = shallowMountExtended(component, {
propsData,
stubs: { GlSprintf },
slots: {
@@ -29,6 +30,12 @@ describe('title area', () => {
});
};
+ const generateSlotMocks = (names) =>
+ names.reduce((acc, current) => {
+ acc[current] = `<div data-testid="${current}" />`;
+ return acc;
+ }, {});
+
afterEach(() => {
wrapper.destroy();
wrapper = null;
@@ -40,6 +47,7 @@ describe('title area', () => {
expect(findTitle().text()).toBe('foo');
});
+
it('if slot is present uses slot', () => {
mountComponent({
slots: {
@@ -88,24 +96,21 @@ describe('title area', () => {
${['metadata-foo', 'metadata-bar']}
${['metadata-foo', 'metadata-bar', 'metadata-baz']}
`('$slotNames metadata slots', ({ slotNames }) => {
- const slotMocks = slotNames.reduce((acc, current) => {
- acc[current] = `<div data-testid="${current}" />`;
- return acc;
- }, {});
+ const slots = generateSlotMocks(slotNames);
it('exist when the slot is present', async () => {
- mountComponent({ slots: slotMocks });
+ mountComponent({ slots });
- await wrapper.vm.$nextTick();
+ await nextTick();
slotNames.forEach((name) => {
expect(findMetadataSlot(name).exists()).toBe(true);
});
});
it('is/are hidden when metadata-loading is true', async () => {
- mountComponent({ slots: slotMocks, propsData: { title: 'foo', metadataLoading: true } });
+ mountComponent({ slots, propsData: { title: 'foo', metadataLoading: true } });
- await wrapper.vm.$nextTick();
+ await nextTick();
slotNames.forEach((name) => {
expect(findMetadataSlot(name).exists()).toBe(false);
});
@@ -113,14 +118,20 @@ describe('title area', () => {
});
describe('metadata skeleton loader', () => {
- it('is hidden when metadata loading is false', () => {
- mountComponent();
+ const slots = generateSlotMocks(['metadata-foo']);
+
+ it('is hidden when metadata loading is false', async () => {
+ mountComponent({ slots });
+
+ await nextTick();
expect(findSkeletonLoader().exists()).toBe(false);
});
- it('is shown when metadata loading is true', () => {
- mountComponent({ propsData: { metadataLoading: true } });
+ it('is shown when metadata loading is true', async () => {
+ mountComponent({ propsData: { metadataLoading: true }, slots });
+
+ await nextTick();
expect(findSkeletonLoader().exists()).toBe(true);
});
@@ -143,7 +154,7 @@ describe('title area', () => {
// updating the slots like we do on line 141 does not cause the updated lifecycle-hook to be triggered
wrapper.vm.$forceUpdate();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDynamicSlot().exists()).toBe(true);
});
@@ -163,7 +174,7 @@ describe('title area', () => {
// updating the slots like we do on line 159 does not cause the updated lifecycle-hook to be triggered
wrapper.vm.$forceUpdate();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findSlotOrderElements().at(0).attributes('data-testid')).toBe(DYNAMIC_SLOT);
expect(findSlotOrderElements().at(1).attributes('data-testid')).toBe('metadata-foo');
diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
index 32ef2d27ba7..8536ffed573 100644
--- a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
+++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
@@ -1,4 +1,4 @@
-import { GlAlert, GlButton, GlLoadingIcon, GlSkeletonLoader } from '@gitlab/ui';
+import { GlAlert, GlModal, GlButton, GlLoadingIcon, GlSkeletonLoader } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
@@ -52,7 +52,7 @@ describe('RunnerInstructionsModal component', () => {
const findBinaryInstructions = () => wrapper.findByTestId('binary-instructions');
const findRegisterCommand = () => wrapper.findByTestId('register-command');
- const createComponent = () => {
+ const createComponent = ({ props, ...options } = {}) => {
const requestHandlers = [
[getRunnerPlatformsQuery, runnerPlatformsHandler],
[getRunnerSetupInstructionsQuery, runnerSetupInstructionsHandler],
@@ -64,9 +64,12 @@ describe('RunnerInstructionsModal component', () => {
shallowMount(RunnerInstructionsModal, {
propsData: {
modalId: 'runner-instructions-modal',
+ registrationToken: 'MY_TOKEN',
+ ...props,
},
localVue,
apolloProvider: fakeApollo,
+ ...options,
}),
);
};
@@ -118,18 +121,30 @@ describe('RunnerInstructionsModal component', () => {
expect(instructions).toBe(installInstructions);
});
- it('register command is shown', () => {
+ it('register command is shown with a replaced token', () => {
const instructions = findRegisterCommand().text();
- expect(instructions).toBe(registerInstructions);
+ expect(instructions).toBe(
+ 'sudo gitlab-runner register --url http://gdk.test:3000/ --registration-token MY_TOKEN',
+ );
+ });
+
+ describe('when a register token is not shown', () => {
+ beforeEach(async () => {
+ createComponent({ props: { registrationToken: undefined } });
+ await nextTick();
+ });
+
+ it('register command is shown without a defined registration token', () => {
+ const instructions = findRegisterCommand().text();
+
+ expect(instructions).toBe(registerInstructions);
+ });
});
});
describe('after a platform and architecture are selected', () => {
- const {
- installInstructions,
- registerInstructions,
- } = mockGraphqlInstructionsWindows.data.runnerSetup;
+ const { installInstructions } = mockGraphqlInstructionsWindows.data.runnerSetup;
beforeEach(async () => {
runnerSetupInstructionsHandler.mockResolvedValue(mockGraphqlInstructionsWindows);
@@ -157,7 +172,9 @@ describe('RunnerInstructionsModal component', () => {
it('register command is shown', () => {
const command = findRegisterCommand().text();
- expect(command).toBe(registerInstructions);
+ expect(command).toBe(
+ './gitlab-runner.exe register --url http://gdk.test:3000/ --registration-token MY_TOKEN',
+ );
});
});
@@ -217,4 +234,36 @@ describe('RunnerInstructionsModal component', () => {
expect(findRegisterCommand().exists()).toBe(false);
});
});
+
+ describe('GlModal API', () => {
+ const getGlModalStub = (methods) => {
+ return {
+ ...GlModal,
+ methods: {
+ ...GlModal.methods,
+ ...methods,
+ },
+ };
+ };
+
+ describe('show()', () => {
+ let mockShow;
+
+ beforeEach(() => {
+ mockShow = jest.fn();
+
+ createComponent({
+ stubs: {
+ GlModal: getGlModalStub({ show: mockShow }),
+ },
+ });
+ });
+
+ it('delegates show()', () => {
+ wrapper.vm.show();
+
+ expect(mockShow).toHaveBeenCalledTimes(1);
+ });
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/settings/__snapshots__/settings_block_spec.js.snap b/spec/frontend/vue_shared/components/settings/__snapshots__/settings_block_spec.js.snap
index 165caea2751..a0f46f07d6a 100644
--- a/spec/frontend/vue_shared/components/settings/__snapshots__/settings_block_spec.js.snap
+++ b/spec/frontend/vue_shared/components/settings/__snapshots__/settings_block_spec.js.snap
@@ -50,6 +50,7 @@ exports[`Settings Block renders the correct markup 1`] = `
class="settings-content"
id="settings_content_3"
role="region"
+ style="display: none;"
tabindex="-1"
>
<div
diff --git a/spec/frontend/vue_shared/components/settings/settings_block_spec.js b/spec/frontend/vue_shared/components/settings/settings_block_spec.js
index 528dfd89690..5e829653c13 100644
--- a/spec/frontend/vue_shared/components/settings/settings_block_spec.js
+++ b/spec/frontend/vue_shared/components/settings/settings_block_spec.js
@@ -1,12 +1,12 @@
import { GlButton } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
describe('Settings Block', () => {
let wrapper;
const mountComponent = (propsData) => {
- wrapper = shallowMount(SettingsBlock, {
+ wrapper = shallowMountExtended(SettingsBlock, {
propsData,
slots: {
title: '<div data-testid="title-slot"></div>',
@@ -20,11 +20,13 @@ describe('Settings Block', () => {
wrapper.destroy();
});
- const findDefaultSlot = () => wrapper.find('[data-testid="default-slot"]');
- const findTitleSlot = () => wrapper.find('[data-testid="title-slot"]');
- const findDescriptionSlot = () => wrapper.find('[data-testid="description-slot"]');
+ const findDefaultSlot = () => wrapper.findByTestId('default-slot');
+ const findTitleSlot = () => wrapper.findByTestId('title-slot');
+ const findDescriptionSlot = () => wrapper.findByTestId('description-slot');
const findExpandButton = () => wrapper.findComponent(GlButton);
- const findSectionTitleButton = () => wrapper.find('[data-testid="section-title-button"]');
+ const findSectionTitleButton = () => wrapper.findByTestId('section-title-button');
+ // we are using a non js class for this finder because this class determine the component structure
+ const findSettingsContent = () => wrapper.find('.settings-content');
const expectExpandedState = ({ expanded = true } = {}) => {
const settingsExpandButton = findExpandButton();
@@ -62,6 +64,26 @@ describe('Settings Block', () => {
expect(findDescriptionSlot().exists()).toBe(true);
});
+ it('content is hidden before first expansion', async () => {
+ // this is a regression test for the bug described here: https://gitlab.com/gitlab-org/gitlab/-/issues/331774
+ mountComponent();
+
+ // content is hidden
+ expect(findDefaultSlot().isVisible()).toBe(false);
+
+ // expand
+ await findSectionTitleButton().trigger('click');
+
+ // content is visible
+ expect(findDefaultSlot().isVisible()).toBe(true);
+
+ // collapse
+ await findSectionTitleButton().trigger('click');
+
+ // content is still visible (and we have a closing animation)
+ expect(findDefaultSlot().isVisible()).toBe(true);
+ });
+
describe('slide animation behaviour', () => {
it('is animated by default', () => {
mountComponent();
@@ -81,6 +103,20 @@ describe('Settings Block', () => {
expect(wrapper.classes('no-animate')).toBe(noAnimatedClass);
},
);
+
+ it('sets the animating class only during the animation', async () => {
+ mountComponent();
+
+ expect(wrapper.classes('animating')).toBe(false);
+
+ await findSectionTitleButton().trigger('click');
+
+ expect(wrapper.classes('animating')).toBe(true);
+
+ await findSettingsContent().trigger('animationend');
+
+ expect(wrapper.classes('animating')).toBe(false);
+ });
});
describe('expanded behaviour', () => {
diff --git a/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js b/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
index 240d6cb5a34..79e41ed0c9e 100644
--- a/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
@@ -1,36 +1,68 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import collapsedCalendarIcon from '~/vue_shared/components/sidebar/collapsed_calendar_icon.vue';
+import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-describe('collapsedCalendarIcon', () => {
- let vm;
- beforeEach(() => {
- const CollapsedCalendarIcon = Vue.extend(collapsedCalendarIcon);
- vm = mountComponent(CollapsedCalendarIcon, {
- containerClass: 'test-class',
- text: 'text',
- showIcon: false,
+import CollapsedCalendarIcon from '~/vue_shared/components/sidebar/collapsed_calendar_icon.vue';
+
+describe('CollapsedCalendarIcon', () => {
+ let wrapper;
+
+ const defaultProps = {
+ containerClass: 'test-class',
+ text: 'text',
+ tooltipText: 'tooltip text',
+ showIcon: false,
+ };
+
+ const createComponent = ({ props = {} } = {}) => {
+ wrapper = shallowMount(CollapsedCalendarIcon, {
+ propsData: { ...defaultProps, ...props },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
});
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
});
- it('should add class to container', () => {
- expect(vm.$el.classList.contains('test-class')).toEqual(true);
+ const findGlIcon = () => wrapper.findComponent(GlIcon);
+ const getTooltip = () => getBinding(wrapper.element, 'gl-tooltip');
+
+ it('adds class to container', () => {
+ expect(wrapper.classes()).toContain(defaultProps.containerClass);
+ });
+
+ it('does not render calendar icon when showIcon is false', () => {
+ expect(findGlIcon().exists()).toBe(false);
+ });
+
+ it('renders calendar icon when showIcon is true', () => {
+ createComponent({
+ props: { showIcon: true },
+ });
+
+ expect(findGlIcon().exists()).toBe(true);
});
- it('should hide calendar icon if showIcon', () => {
- expect(vm.$el.querySelector('[data-testid="calendar-icon"]')).toBeNull();
+ it('renders text', () => {
+ expect(wrapper.text()).toBe(defaultProps.text);
});
- it('should render text', () => {
- expect(vm.$el.querySelector('span').innerText.trim()).toEqual('text');
+ it('renders tooltipText as tooltip', () => {
+ expect(getTooltip().value).toBe(defaultProps.tooltipText);
});
- it('should emit click event when container is clicked', () => {
- const click = jest.fn();
- vm.$on('click', click);
+ it('emits click event when container is clicked', async () => {
+ wrapper.trigger('click');
- vm.$el.click();
+ await wrapper.vm.$nextTick();
- expect(click).toHaveBeenCalled();
+ expect(wrapper.emitted('click')[0]).toBeDefined();
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js b/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
index 230442ec547..e72b3bf45c4 100644
--- a/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
@@ -1,86 +1,103 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import collapsedGroupedDatePicker from '~/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue';
-
-describe('collapsedGroupedDatePicker', () => {
- let vm;
- beforeEach(() => {
- const CollapsedGroupedDatePicker = Vue.extend(collapsedGroupedDatePicker);
- vm = mountComponent(CollapsedGroupedDatePicker, {
- showToggleSidebar: true,
+import { shallowMount } from '@vue/test-utils';
+
+import CollapsedGroupedDatePicker from '~/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue';
+import CollapsedCalendarIcon from '~/vue_shared/components/sidebar/collapsed_calendar_icon.vue';
+
+describe('CollapsedGroupedDatePicker', () => {
+ let wrapper;
+
+ const defaultProps = {
+ showToggleSidebar: true,
+ };
+
+ const minDate = new Date('07/17/2016');
+ const maxDate = new Date('07/17/2017');
+
+ const createComponent = ({ props = {} } = {}) => {
+ wrapper = shallowMount(CollapsedGroupedDatePicker, {
+ propsData: { ...defaultProps, ...props },
});
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
});
- describe('toggleCollapse events', () => {
- beforeEach((done) => {
- jest.spyOn(vm, 'toggleSidebar').mockImplementation(() => {});
- vm.minDate = new Date('07/17/2016');
- Vue.nextTick(done);
- });
+ const findCollapsedCalendarIcon = () => wrapper.findComponent(CollapsedCalendarIcon);
+ const findAllCollapsedCalendarIcons = () => wrapper.findAllComponents(CollapsedCalendarIcon);
+ describe('toggleCollapse events', () => {
it('should emit when collapsed-calendar-icon is clicked', () => {
- vm.$el.querySelector('.sidebar-collapsed-icon').click();
+ createComponent();
- expect(vm.toggleSidebar).toHaveBeenCalled();
+ findCollapsedCalendarIcon().trigger('click');
+
+ expect(wrapper.emitted('toggleCollapse')[0]).toBeDefined();
});
});
describe('minDate and maxDate', () => {
- beforeEach((done) => {
- vm.minDate = new Date('07/17/2016');
- vm.maxDate = new Date('07/17/2017');
- Vue.nextTick(done);
- });
-
it('should render both collapsed-calendar-icon', () => {
- const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
-
- expect(icons.length).toEqual(2);
- expect(icons[0].innerText.trim()).toEqual('Jul 17 2016');
- expect(icons[1].innerText.trim()).toEqual('Jul 17 2017');
+ createComponent({
+ props: {
+ minDate,
+ maxDate,
+ },
+ });
+
+ const icons = findAllCollapsedCalendarIcons();
+
+ expect(icons.length).toBe(2);
+ expect(icons.at(0).text()).toBe('Jul 17 2016');
+ expect(icons.at(1).text()).toBe('Jul 17 2017');
});
});
describe('minDate', () => {
- beforeEach((done) => {
- vm.minDate = new Date('07/17/2016');
- Vue.nextTick(done);
- });
-
it('should render minDate in collapsed-calendar-icon', () => {
- const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+ createComponent({
+ props: {
+ minDate,
+ },
+ });
+
+ const icons = findAllCollapsedCalendarIcons();
- expect(icons.length).toEqual(1);
- expect(icons[0].innerText.trim()).toEqual('From Jul 17 2016');
+ expect(icons.length).toBe(1);
+ expect(icons.at(0).text()).toBe('From Jul 17 2016');
});
});
describe('maxDate', () => {
- beforeEach((done) => {
- vm.maxDate = new Date('07/17/2017');
- Vue.nextTick(done);
- });
-
it('should render maxDate in collapsed-calendar-icon', () => {
- const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
-
- expect(icons.length).toEqual(1);
- expect(icons[0].innerText.trim()).toEqual('Until Jul 17 2017');
+ createComponent({
+ props: {
+ maxDate,
+ },
+ });
+ const icons = findAllCollapsedCalendarIcons();
+
+ expect(icons.length).toBe(1);
+ expect(icons.at(0).text()).toBe('Until Jul 17 2017');
});
});
describe('no dates', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
it('should render None', () => {
- const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+ const icons = findAllCollapsedCalendarIcons();
- expect(icons.length).toEqual(1);
- expect(icons[0].innerText.trim()).toEqual('None');
+ expect(icons.length).toBe(1);
+ expect(icons.at(0).text()).toBe('None');
});
it('should have tooltip as `Start and due date`', () => {
- const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+ const icons = findAllCollapsedCalendarIcons();
- expect(icons[0].title).toBe('Start and due date');
+ expect(icons.at(0).props('tooltipText')).toBe('Start and due date');
});
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js b/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
index 3221e88192b..263d1e9d947 100644
--- a/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
@@ -1,3 +1,4 @@
+import { GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import DatePicker from '~/vue_shared/components/pikaday.vue';
import SidebarDatePicker from '~/vue_shared/components/sidebar/date_picker.vue';
@@ -5,14 +6,8 @@ import SidebarDatePicker from '~/vue_shared/components/sidebar/date_picker.vue';
describe('SidebarDatePicker', () => {
let wrapper;
- const mountComponent = (propsData = {}, data = {}) => {
- if (wrapper) {
- throw new Error('tried to call mountComponent without d');
- }
+ const createComponent = (propsData = {}, data = {}) => {
wrapper = mount(SidebarDatePicker, {
- stubs: {
- DatePicker: true,
- },
propsData,
data: () => data,
});
@@ -20,87 +15,93 @@ describe('SidebarDatePicker', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
+ const findDatePicker = () => wrapper.findComponent(DatePicker);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findEditButton = () => wrapper.find('.title .btn-blank');
+ const findRemoveButton = () => wrapper.find('.value-content .btn-blank');
+ const findSidebarToggle = () => wrapper.find('.title .gutter-toggle');
+ const findValueContent = () => wrapper.find('.value-content');
+
it('should emit toggleCollapse when collapsed toggle sidebar is clicked', () => {
- mountComponent();
+ createComponent();
- wrapper.find('.issuable-sidebar-header .gutter-toggle').element.click();
+ wrapper.find('.issuable-sidebar-header .gutter-toggle').trigger('click');
expect(wrapper.emitted('toggleCollapse')).toEqual([[]]);
});
it('should render collapsed-calendar-icon', () => {
- mountComponent();
+ createComponent();
- expect(wrapper.find('.sidebar-collapsed-icon').element).toBeDefined();
+ expect(wrapper.find('.sidebar-collapsed-icon').exists()).toBe(true);
});
it('should render value when not editing', () => {
- mountComponent();
+ createComponent();
- expect(wrapper.find('.value-content').element).toBeDefined();
+ expect(findValueContent().exists()).toBe(true);
});
it('should render None if there is no selectedDate', () => {
- mountComponent();
+ createComponent();
- expect(wrapper.find('.value-content span').text().trim()).toEqual('None');
+ expect(findValueContent().text()).toBe('None');
});
it('should render date-picker when editing', () => {
- mountComponent({}, { editing: true });
+ createComponent({}, { editing: true });
- expect(wrapper.find(DatePicker).element).toBeDefined();
+ expect(findDatePicker().exists()).toBe(true);
});
it('should render label', () => {
const label = 'label';
- mountComponent({ label });
- expect(wrapper.find('.title').text().trim()).toEqual(label);
+ createComponent({ label });
+ expect(wrapper.find('.title').text()).toBe(label);
});
it('should render loading-icon when isLoading', () => {
- mountComponent({ isLoading: true });
- expect(wrapper.find('.gl-spinner').element).toBeDefined();
+ createComponent({ isLoading: true });
+ expect(findLoadingIcon().exists()).toBe(true);
});
describe('editable', () => {
beforeEach(() => {
- mountComponent({ editable: true });
+ createComponent({ editable: true });
});
it('should render edit button', () => {
- expect(wrapper.find('.title .btn-blank').text().trim()).toEqual('Edit');
+ expect(findEditButton().text()).toBe('Edit');
});
it('should enable editing when edit button is clicked', async () => {
- wrapper.find('.title .btn-blank').element.click();
+ findEditButton().trigger('click');
await wrapper.vm.$nextTick();
- expect(wrapper.vm.editing).toEqual(true);
+ expect(wrapper.vm.editing).toBe(true);
});
});
it('should render date if selectedDate', () => {
- mountComponent({ selectedDate: new Date('07/07/2017') });
+ createComponent({ selectedDate: new Date('07/07/2017') });
- expect(wrapper.find('.value-content strong').text().trim()).toEqual('Jul 7, 2017');
+ expect(wrapper.find('.value-content strong').text()).toBe('Jul 7, 2017');
});
describe('selectedDate and editable', () => {
beforeEach(() => {
- mountComponent({ selectedDate: new Date('07/07/2017'), editable: true });
+ createComponent({ selectedDate: new Date('07/07/2017'), editable: true });
});
it('should render remove button if selectedDate and editable', () => {
- expect(wrapper.find('.value-content .btn-blank').text().trim()).toEqual('remove');
+ expect(findRemoveButton().text()).toBe('remove');
});
it('should emit saveDate with null when remove button is clicked', () => {
- wrapper.find('.value-content .btn-blank').element.click();
+ findRemoveButton().trigger('click');
expect(wrapper.emitted('saveDate')).toEqual([[null]]);
});
@@ -108,15 +109,15 @@ describe('SidebarDatePicker', () => {
describe('showToggleSidebar', () => {
beforeEach(() => {
- mountComponent({ showToggleSidebar: true });
+ createComponent({ showToggleSidebar: true });
});
it('should render toggle-sidebar when showToggleSidebar', () => {
- expect(wrapper.find('.title .gutter-toggle').element).toBeDefined();
+ expect(findSidebarToggle().exists()).toBe(true);
});
it('should emit toggleCollapse when toggle sidebar is clicked', () => {
- wrapper.find('.title .gutter-toggle').element.click();
+ findSidebarToggle().trigger('click');
expect(wrapper.emitted('toggleCollapse')).toEqual([[]]);
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed_spec.js
index 8c1693e8dcc..a7f9391cb5f 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed_spec.js
@@ -1,95 +1,74 @@
-import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import DropdownValueCollapsedComponent from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import dropdownValueCollapsedComponent from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue';
+import { mockCollapsedLabels as mockLabels, mockRegularLabel } from './mock_data';
-import { mockCollapsedLabels as mockLabels } from './mock_data';
-
-const createComponent = (labels = mockLabels) => {
- const Component = Vue.extend(dropdownValueCollapsedComponent);
+describe('DropdownValueCollapsedComponent', () => {
+ let wrapper;
- return mountComponent(Component, {
- labels,
- });
-};
+ const defaultProps = {
+ labels: [],
+ };
-describe('DropdownValueCollapsedComponent', () => {
- let vm;
+ const mockManyLabels = [...mockLabels, ...mockLabels, ...mockLabels];
- beforeEach(() => {
- vm = createComponent();
- });
+ const createComponent = ({ props = {} } = {}) => {
+ wrapper = shallowMount(DropdownValueCollapsedComponent, {
+ propsData: { ...defaultProps, ...props },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
- describe('computed', () => {
- describe('labelsList', () => {
- it('returns default text when `labels` prop is empty array', () => {
- const vmEmptyLabels = createComponent([]);
+ const findGlIcon = () => wrapper.findComponent(GlIcon);
+ const getTooltip = () => getBinding(wrapper.element, 'gl-tooltip');
- expect(vmEmptyLabels.labelsList).toBe('Labels');
- vmEmptyLabels.$destroy();
- });
-
- it('returns labels names separated by coma when `labels` prop has more than one item', () => {
- const labels = mockLabels.concat(mockLabels);
- const vmMoreLabels = createComponent(labels);
+ describe('template', () => {
+ it('renders tags icon element', () => {
+ createComponent();
- const expectedText = labels.map((label) => label.title).join(', ');
+ expect(findGlIcon().exists()).toBe(true);
+ });
- expect(vmMoreLabels.labelsList).toBe(expectedText);
- vmMoreLabels.$destroy();
- });
+ it('emits onValueClick event on click', async () => {
+ createComponent();
- it('returns labels names separated by coma with remaining labels count and `and more` phrase when `labels` prop has more than five items', () => {
- const mockMoreLabels = Object.assign([], mockLabels);
- for (let i = 0; i < 6; i += 1) {
- mockMoreLabels.unshift(mockLabels[0]);
- }
+ wrapper.trigger('click');
- const vmMoreLabels = createComponent(mockMoreLabels);
+ await wrapper.vm.$nextTick();
- const expectedText = `${mockMoreLabels
- .slice(0, 5)
- .map((label) => label.title)
- .join(', ')}, and ${mockMoreLabels.length - 5} more`;
+ expect(wrapper.emitted('onValueClick')[0]).toBeDefined();
+ });
- expect(vmMoreLabels.labelsList).toBe(expectedText);
- vmMoreLabels.$destroy();
+ describe.each`
+ scenario | labels | expectedResult | expectedText
+ ${'`labels` is empty'} | ${[]} | ${'default text'} | ${'Labels'}
+ ${'`labels` has 1 item'} | ${[mockRegularLabel]} | ${'label name'} | ${'Foo Label'}
+ ${'`labels` has 2 items'} | ${mockLabels} | ${'comma separated label names'} | ${'Foo Label, Foo::Bar'}
+ ${'`labels` has more than 5 items'} | ${mockManyLabels} | ${'comma separated label names with "and more" phrase'} | ${'Foo Label, Foo::Bar, Foo Label, Foo::Bar, Foo Label, and 1 more'}
+ `('when $scenario', ({ labels, expectedResult, expectedText }) => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ labels,
+ },
+ });
});
- it('returns first label name when `labels` prop has only one item present', () => {
- const text = mockLabels.map((label) => label.title).join(', ');
-
- expect(vm.labelsList).toBe(text);
+ it('renders labels count', () => {
+ expect(wrapper.text()).toBe(`${labels.length}`);
});
- });
- });
-
- describe('methods', () => {
- describe('handleClick', () => {
- it('emits onValueClick event on component', () => {
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
- vm.handleClick();
- expect(vm.$emit).toHaveBeenCalledWith('onValueClick');
+ it(`renders "${expectedResult}" as tooltip`, () => {
+ expect(getTooltip().value).toBe(expectedText);
});
});
});
-
- describe('template', () => {
- it('renders component container element with tooltip`', () => {
- expect(vm.$el.title).toBe(vm.labelsList);
- });
-
- it('renders tags icon element', () => {
- expect(vm.$el.querySelector('[data-testid="labels-icon"]')).not.toBeNull();
- });
-
- it('renders labels count', () => {
- expect(vm.$el.querySelector('span').innerText.trim()).toBe(`${vm.labels.length}`);
- });
- });
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
index d9b7cd5afa2..a60e6f52862 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
@@ -1,3 +1,4 @@
+import { cloneDeep } from 'lodash';
import * as types from '~/vue_shared/components/sidebar/labels_select_vue/store/mutation_types';
import mutations from '~/vue_shared/components/sidebar/labels_select_vue/store/mutations';
@@ -153,47 +154,40 @@ describe('LabelsSelect Mutations', () => {
});
describe(`${types.UPDATE_SELECTED_LABELS}`, () => {
- let labels;
-
- beforeEach(() => {
- labels = [
- { id: 1, title: 'scoped' },
- { id: 2, title: 'scoped::one', set: false },
- { id: 3, title: 'scoped::test', set: true },
- { id: 4, title: '' },
- ];
- });
-
- it('updates `state.labels` to include `touched` and `set` props based on provided `labels` param', () => {
- const updatedLabelIds = [2];
- const state = {
- labels,
- };
- mutations[types.UPDATE_SELECTED_LABELS](state, { labels: [{ id: 2 }] });
-
- state.labels.forEach((label) => {
- if (updatedLabelIds.includes(label.id)) {
- expect(label.touched).toBe(true);
- expect(label.set).toBe(true);
- }
+ const labels = [
+ { id: 1, title: 'scoped' },
+ { id: 2, title: 'scoped::label::one', set: false },
+ { id: 3, title: 'scoped::label::two', set: false },
+ { id: 4, title: 'scoped::label::three', set: true },
+ { id: 5, title: 'scoped::one', set: false },
+ { id: 6, title: 'scoped::two', set: false },
+ { id: 7, title: 'scoped::three', set: true },
+ { id: 8, title: '' },
+ ];
+
+ it.each`
+ label | labelGroupIds
+ ${labels[0]} | ${[]}
+ ${labels[1]} | ${[labels[2], labels[3]]}
+ ${labels[2]} | ${[labels[1], labels[3]]}
+ ${labels[3]} | ${[labels[1], labels[2]]}
+ ${labels[4]} | ${[labels[5], labels[6]]}
+ ${labels[5]} | ${[labels[4], labels[6]]}
+ ${labels[6]} | ${[labels[4], labels[5]]}
+ ${labels[7]} | ${[]}
+ `('updates `touched` and `set` props for $label.title', ({ label, labelGroupIds }) => {
+ const state = { labels: cloneDeep(labels) };
+
+ mutations[types.UPDATE_SELECTED_LABELS](state, { labels: [{ id: label.id }] });
+
+ expect(state.labels[label.id - 1]).toMatchObject({
+ touched: true,
+ set: !labels[label.id - 1].set,
});
- });
- describe('when label is scoped', () => {
- it('unsets the currently selected scoped label and sets the current label', () => {
- const state = {
- labels,
- };
- mutations[types.UPDATE_SELECTED_LABELS](state, {
- labels: [{ id: 2, title: 'scoped::one' }],
- });
-
- expect(state.labels).toEqual([
- { id: 1, title: 'scoped' },
- { id: 2, title: 'scoped::one', set: true, touched: true },
- { id: 3, title: 'scoped::test', set: false },
- { id: 4, title: '' },
- ]);
+ labelGroupIds.forEach((l) => {
+ expect(state.labels[l.id - 1].touched).toBeFalsy();
+ expect(state.labels[l.id - 1].set).toBe(false);
});
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js
index 8931584e12c..bf873f9162b 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js
@@ -5,8 +5,7 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
-import { IssuableType } from '~/issue_show/constants';
-import { labelsQueries } from '~/sidebar/constants';
+import { workspaceLabelsQueries } from '~/sidebar/constants';
import DropdownContentsCreateView from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue';
import createLabelMutation from '~/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql';
import {
@@ -50,11 +49,12 @@ describe('DropdownContentsCreateView', () => {
const createComponent = ({
mutationHandler = createLabelSuccessHandler,
- issuableType = IssuableType.Issue,
+ labelCreateType = 'project',
+ workspaceType = 'project',
} = {}) => {
const mockApollo = createMockApollo([[createLabelMutation, mutationHandler]]);
mockApollo.clients.defaultClient.cache.writeQuery({
- query: labelsQueries[issuableType].workspaceQuery,
+ query: workspaceLabelsQueries[workspaceType].query,
data: workspaceLabelsQueryResponse.data,
variables: {
fullPath: '',
@@ -66,8 +66,10 @@ describe('DropdownContentsCreateView', () => {
localVue,
apolloProvider: mockApollo,
propsData: {
- issuableType,
fullPath: '',
+ attrWorkspacePath: '',
+ labelCreateType,
+ workspaceType,
},
});
};
@@ -128,9 +130,11 @@ describe('DropdownContentsCreateView', () => {
it('emits a `hideCreateView` event on Cancel button click', () => {
createComponent();
- findCancelButton().vm.$emit('click');
+ const event = { stopPropagation: jest.fn() };
+ findCancelButton().vm.$emit('click', event);
expect(wrapper.emitted('hideCreateView')).toHaveLength(1);
+ expect(event.stopPropagation).toHaveBeenCalled();
});
describe('when label title and selected color are set', () => {
@@ -174,7 +178,7 @@ describe('DropdownContentsCreateView', () => {
});
it('calls a mutation with `groupPath` variable on the epic', () => {
- createComponent({ issuableType: IssuableType.Epic });
+ createComponent({ labelCreateType: 'group', workspaceType: 'group' });
fillLabelAttributes();
findCreateButton().vm.$emit('click');
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js
index fac3331a2b8..2980409fdce 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js
@@ -10,7 +10,6 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
-import { IssuableType } from '~/issue_show/constants';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
import DropdownContentsLabelsView from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue';
@@ -43,6 +42,7 @@ describe('DropdownContentsLabelsView', () => {
initialState = mockConfig,
queryHandler = successfulQueryHandler,
injected = {},
+ searchKey = '',
} = {}) => {
const mockApollo = createMockApollo([[projectLabelsQuery, queryHandler]]);
@@ -56,7 +56,9 @@ describe('DropdownContentsLabelsView', () => {
propsData: {
...initialState,
localSelectedLabels,
- issuableType: IssuableType.Issue,
+ searchKey,
+ labelCreateType: 'project',
+ workspaceType: 'project',
},
stubs: {
GlSearchBoxByType,
@@ -68,7 +70,6 @@ describe('DropdownContentsLabelsView', () => {
wrapper.destroy();
});
- const findSearchInput = () => wrapper.findComponent(GlSearchBoxByType);
const findLabels = () => wrapper.findAllComponents(LabelItem);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findObserver = () => wrapper.findComponent(GlIntersectionObserver);
@@ -81,12 +82,6 @@ describe('DropdownContentsLabelsView', () => {
}
describe('when loading labels', () => {
- it('renders disabled search input field', async () => {
- createComponent();
- await makeObserverAppear();
- expect(findSearchInput().props('disabled')).toBe(true);
- });
-
it('renders loading icon', async () => {
createComponent();
await makeObserverAppear();
@@ -107,10 +102,6 @@ describe('DropdownContentsLabelsView', () => {
await waitForPromises();
});
- it('renders enabled search input field', async () => {
- expect(findSearchInput().props('disabled')).toBe(false);
- });
-
it('does not render loading icon', async () => {
expect(findLoadingIcon().exists()).toBe(false);
});
@@ -132,9 +123,9 @@ describe('DropdownContentsLabelsView', () => {
},
},
}),
+ searchKey: '123',
});
await makeObserverAppear();
- findSearchInput().vm.$emit('input', '123');
await waitForPromises();
await nextTick();
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_spec.js
index 36704ac5ef3..8bcef347c96 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_spec.js
@@ -4,6 +4,8 @@ import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_w
import DropdownContents from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue';
import DropdownContentsCreateView from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue';
import DropdownContentsLabelsView from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue';
+import DropdownHeader from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue';
+import DropdownFooter from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_footer.vue';
import { mockLabels } from './mock_data';
@@ -26,7 +28,7 @@ const GlDropdownStub = {
describe('DropdownContent', () => {
let wrapper;
- const createComponent = ({ props = {}, injected = {}, data = {} } = {}) => {
+ const createComponent = ({ props = {}, data = {} } = {}) => {
wrapper = shallowMount(DropdownContents, {
propsData: {
labelsCreateTitle: 'test',
@@ -37,8 +39,10 @@ describe('DropdownContent', () => {
footerManageLabelTitle: 'manage',
dropdownButtonText: 'Labels',
variant: 'sidebar',
- issuableType: 'issue',
fullPath: 'test',
+ workspaceType: 'project',
+ labelCreateType: 'project',
+ attrWorkspacePath: 'path',
...props,
},
data() {
@@ -46,11 +50,6 @@ describe('DropdownContent', () => {
...data,
};
},
- provide: {
- allowLabelCreate: true,
- labelsManagePath: 'foo/bar',
- ...injected,
- },
stubs: {
GlDropdown: GlDropdownStub,
},
@@ -63,13 +62,10 @@ describe('DropdownContent', () => {
const findCreateView = () => wrapper.findComponent(DropdownContentsCreateView);
const findLabelsView = () => wrapper.findComponent(DropdownContentsLabelsView);
+ const findDropdownHeader = () => wrapper.findComponent(DropdownHeader);
+ const findDropdownFooter = () => wrapper.findComponent(DropdownFooter);
const findDropdown = () => wrapper.findComponent(GlDropdownStub);
- const findDropdownFooter = () => wrapper.find('[data-testid="dropdown-footer"]');
- const findDropdownHeader = () => wrapper.find('[data-testid="dropdown-header"]');
- const findCreateLabelButton = () => wrapper.find('[data-testid="create-label-button"]');
- const findGoBackButton = () => wrapper.find('[data-testid="go-back-button"]');
-
it('calls dropdown `show` method on `isVisible` prop change', async () => {
createComponent();
await wrapper.setProps({
@@ -136,6 +132,16 @@ describe('DropdownContent', () => {
expect(findDropdownHeader().exists()).toBe(true);
});
+ it('sets searchKey for labels view on input event from header', async () => {
+ createComponent();
+
+ expect(wrapper.vm.searchKey).toEqual('');
+ findDropdownHeader().vm.$emit('input', '123');
+ await nextTick();
+
+ expect(findLabelsView().props('searchKey')).toEqual('123');
+ });
+
describe('Create view', () => {
beforeEach(() => {
createComponent({ data: { showDropdownContentsCreateView: true } });
@@ -149,16 +155,8 @@ describe('DropdownContent', () => {
expect(findDropdownFooter().exists()).toBe(false);
});
- it('does not render create label button', () => {
- expect(findCreateLabelButton().exists()).toBe(false);
- });
-
- it('renders go back button', () => {
- expect(findGoBackButton().exists()).toBe(true);
- });
-
- it('changes the view to Labels view on back button click', async () => {
- findGoBackButton().vm.$emit('click', new MouseEvent('click'));
+ it('changes the view to Labels view on `toggleDropdownContentsCreateView` event', async () => {
+ findDropdownHeader().vm.$emit('toggleDropdownContentsCreateView');
await nextTick();
expect(findCreateView().exists()).toBe(false);
@@ -198,32 +196,5 @@ describe('DropdownContent', () => {
expect(findDropdownFooter().exists()).toBe(true);
});
-
- it('does not render go back button', () => {
- expect(findGoBackButton().exists()).toBe(false);
- });
-
- it('does not render create label button if `allowLabelCreate` is false', () => {
- createComponent({ injected: { allowLabelCreate: false } });
-
- expect(findCreateLabelButton().exists()).toBe(false);
- });
-
- describe('when `allowLabelCreate` is true', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders create label button', () => {
- expect(findCreateLabelButton().exists()).toBe(true);
- });
-
- it('changes the view to Create on create label button click', async () => {
- findCreateLabelButton().trigger('click');
-
- await nextTick();
- expect(findLabelsView().exists()).toBe(false);
- });
- });
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_footer_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_footer_spec.js
new file mode 100644
index 00000000000..0508a059195
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_footer_spec.js
@@ -0,0 +1,57 @@
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import DropdownFooter from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_footer.vue';
+
+describe('DropdownFooter', () => {
+ let wrapper;
+
+ const createComponent = ({ props = {}, injected = {} } = {}) => {
+ wrapper = shallowMount(DropdownFooter, {
+ propsData: {
+ footerCreateLabelTitle: 'create',
+ footerManageLabelTitle: 'manage',
+ ...props,
+ },
+ provide: {
+ allowLabelCreate: true,
+ labelsManagePath: 'foo/bar',
+ ...injected,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findCreateLabelButton = () => wrapper.find('[data-testid="create-label-button"]');
+
+ describe('Labels view', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('does not render create label button if `allowLabelCreate` is false', () => {
+ createComponent({ injected: { allowLabelCreate: false } });
+
+ expect(findCreateLabelButton().exists()).toBe(false);
+ });
+
+ describe('when `allowLabelCreate` is true', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders create label button', () => {
+ expect(findCreateLabelButton().exists()).toBe(true);
+ });
+
+ it('emits `toggleDropdownContentsCreateView` event on create label button click', async () => {
+ findCreateLabelButton().trigger('click');
+
+ await nextTick();
+ expect(wrapper.emitted('toggleDropdownContentsCreateView')).toEqual([[]]);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_header_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_header_spec.js
new file mode 100644
index 00000000000..592559ef305
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_header_spec.js
@@ -0,0 +1,75 @@
+import { GlSearchBoxByType } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import DropdownHeader from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue';
+
+describe('DropdownHeader', () => {
+ let wrapper;
+
+ const createComponent = ({
+ showDropdownContentsCreateView = false,
+ labelsFetchInProgress = false,
+ } = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(DropdownHeader, {
+ propsData: {
+ showDropdownContentsCreateView,
+ labelsFetchInProgress,
+ labelsCreateTitle: 'Create label',
+ labelsListTitle: 'Select label',
+ searchKey: '',
+ },
+ stubs: {
+ GlSearchBoxByType,
+ },
+ }),
+ );
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findSearchInput = () => wrapper.findComponent(GlSearchBoxByType);
+ const findGoBackButton = () => wrapper.findByTestId('go-back-button');
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ describe('Create view', () => {
+ beforeEach(() => {
+ createComponent({ showDropdownContentsCreateView: true });
+ });
+
+ it('renders go back button', () => {
+ expect(findGoBackButton().exists()).toBe(true);
+ });
+
+ it('does not render search input field', async () => {
+ expect(findSearchInput().exists()).toBe(false);
+ });
+ });
+
+ describe('Labels view', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('does not render go back button', () => {
+ expect(findGoBackButton().exists()).toBe(false);
+ });
+
+ it.each`
+ labelsFetchInProgress | disabled
+ ${true} | ${true}
+ ${false} | ${false}
+ `(
+ 'when labelsFetchInProgress is $labelsFetchInProgress, renders search input with disabled prop to $disabled',
+ ({ labelsFetchInProgress, disabled }) => {
+ createComponent({ labelsFetchInProgress });
+ expect(findSearchInput().props('disabled')).toBe(disabled);
+ },
+ );
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
index b5441d711a5..d4203528874 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
@@ -41,6 +41,8 @@ describe('LabelsSelectRoot', () => {
propsData: {
...config,
issuableType: IssuableType.Issue,
+ labelCreateType: 'project',
+ workspaceType: 'project',
},
stubs: {
SidebarEditableItem,
@@ -121,11 +123,11 @@ describe('LabelsSelectRoot', () => {
});
});
- it('emits `updateSelectedLabels` event on dropdown contents `setLabels` event', async () => {
+ it('emits `updateSelectedLabels` event on dropdown contents `setLabels` event if iid is not set', async () => {
const label = { id: 'gid://gitlab/ProjectLabel/1' };
- createComponent();
+ createComponent({ config: { ...mockConfig, iid: undefined } });
findDropdownContents().vm.$emit('setLabels', [label]);
- expect(wrapper.emitted('updateSelectedLabels')).toEqual([[[label]]]);
+ expect(wrapper.emitted('updateSelectedLabels')).toEqual([[{ labels: [label] }]]);
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js
index 23a457848d9..5c5bf5f2187 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js
@@ -40,12 +40,12 @@ export const mockConfig = {
labelsListTitle: 'Assign labels',
labelsCreateTitle: 'Create label',
variant: 'sidebar',
- selectedLabels: [mockRegularLabel, mockScopedLabel],
labelsSelectInProgress: false,
labelsFilterBasePath: '/gitlab-org/my-project/issues',
labelsFilterParam: 'label_name',
footerCreateLabelTitle: 'create',
footerManageLabelTitle: 'manage',
+ attrWorkspacePath: 'test',
};
export const mockSuggestedColors = {
@@ -80,6 +80,7 @@ export const createLabelSuccessfulResponse = {
color: '#dc143c',
description: null,
title: 'ewrwrwer',
+ textColor: '#000000',
__typename: 'Label',
},
errors: [],
@@ -91,6 +92,7 @@ export const createLabelSuccessfulResponse = {
export const workspaceLabelsQueryResponse = {
data: {
workspace: {
+ id: 'gid://gitlab/Project/126',
labels: {
nodes: [
{
@@ -98,12 +100,14 @@ export const workspaceLabelsQueryResponse = {
description: null,
id: 'gid://gitlab/ProjectLabel/1',
title: 'Label1',
+ textColor: '#000000',
},
{
color: '#2f7b2e',
description: null,
id: 'gid://gitlab/ProjectLabel/2',
title: 'Label2',
+ textColor: '#000000',
},
],
},
@@ -123,6 +127,7 @@ export const issuableLabelsQueryResponse = {
description: null,
id: 'gid://gitlab/ProjectLabel/1',
title: 'Label1',
+ textColor: '#000000',
},
],
},
diff --git a/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js b/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js
index f1c3e8a1ddc..a6c9bda1aa2 100644
--- a/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js
@@ -1,31 +1,45 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import toggleSidebar from '~/vue_shared/components/sidebar/toggle_sidebar.vue';
-
-describe('toggleSidebar', () => {
- let vm;
- beforeEach(() => {
- const ToggleSidebar = Vue.extend(toggleSidebar);
- vm = mountComponent(ToggleSidebar, {
- collapsed: true,
+import { GlButton } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+
+import ToggleSidebar from '~/vue_shared/components/sidebar/toggle_sidebar.vue';
+
+describe('ToggleSidebar', () => {
+ let wrapper;
+
+ const defaultProps = {
+ collapsed: true,
+ };
+
+ const createComponent = ({ mountFn = shallowMount, props = {} } = {}) => {
+ wrapper = mountFn(ToggleSidebar, {
+ propsData: { ...defaultProps, ...props },
});
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
});
+ const findGlButton = () => wrapper.findComponent(GlButton);
+
it('should render the "chevron-double-lg-left" icon when collapsed', () => {
- expect(vm.$el.querySelector('[data-testid="chevron-double-lg-left-icon"]')).not.toBeNull();
+ createComponent();
+
+ expect(findGlButton().props('icon')).toBe('chevron-double-lg-left');
});
it('should render the "chevron-double-lg-right" icon when expanded', async () => {
- vm.collapsed = false;
- await Vue.nextTick();
- expect(vm.$el.querySelector('[data-testid="chevron-double-lg-right-icon"]')).not.toBeNull();
+ createComponent({ props: { collapsed: false } });
+
+ expect(findGlButton().props('icon')).toBe('chevron-double-lg-right');
});
- it('should emit toggle event when button clicked', () => {
- const toggle = jest.fn();
- vm.$on('toggle', toggle);
- vm.$el.click();
+ it('should emit toggle event when button clicked', async () => {
+ createComponent({ mountFn: mount });
+
+ findGlButton().trigger('click');
+ await wrapper.vm.$nextTick();
- expect(toggle).toHaveBeenCalled();
+ expect(wrapper.emitted('toggle')[0]).toBeDefined();
});
});
diff --git a/spec/frontend/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list_spec.js b/spec/frontend/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list_spec.js
index a92f058f311..78abb89e7b8 100644
--- a/spec/frontend/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list_spec.js
+++ b/spec/frontend/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list_spec.js
@@ -82,7 +82,7 @@ describe('User deletion obstacles list', () => {
createComponent({ obstacles: [{ type, name, url, projectName, projectUrl }] });
const msg = findObstacles().text();
- expect(msg).toContain(`in Project ${projectName}`);
+ expect(msg).toContain(`in project ${projectName}`);
expect(findLinks().at(1).attributes('href')).toBe(projectUrl);
});
},
diff --git a/spec/frontend/whats_new/utils/notification_spec.js b/spec/frontend/whats_new/utils/notification_spec.js
index c361f934e59..ef61462a3c5 100644
--- a/spec/frontend/whats_new/utils/notification_spec.js
+++ b/spec/frontend/whats_new/utils/notification_spec.js
@@ -29,7 +29,7 @@ describe('~/whats_new/utils/notification', () => {
subject();
- expect(findNotificationCountEl()).toExist();
+ expect(findNotificationCountEl()).not.toBe(null);
expect(notificationEl.classList).toContain('with-notifications');
});
@@ -38,11 +38,11 @@ describe('~/whats_new/utils/notification', () => {
notificationEl.classList.add('with-notifications');
localStorage.setItem('display-whats-new-notification', 'version-digest');
- expect(findNotificationCountEl()).toExist();
+ expect(findNotificationCountEl()).not.toBe(null);
subject();
- expect(findNotificationCountEl()).not.toExist();
+ expect(findNotificationCountEl()).toBe(null);
expect(notificationEl.classList).not.toContain('with-notifications');
});
});
diff --git a/spec/frontend/work_items/components/app_spec.js b/spec/frontend/work_items/components/app_spec.js
new file mode 100644
index 00000000000..95034085493
--- /dev/null
+++ b/spec/frontend/work_items/components/app_spec.js
@@ -0,0 +1,24 @@
+import { shallowMount } from '@vue/test-utils';
+import App from '~/work_items/components/app.vue';
+
+describe('Work Items Application', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(App, {
+ stubs: {
+ 'router-view': true,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders a component', () => {
+ createComponent();
+
+ expect(wrapper.exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js
new file mode 100644
index 00000000000..efb4aa2feb2
--- /dev/null
+++ b/spec/frontend/work_items/mock_data.js
@@ -0,0 +1,17 @@
+export const workItemQueryResponse = {
+ workItem: {
+ __typename: 'WorkItem',
+ id: '1',
+ type: 'FEATURE',
+ widgets: {
+ __typename: 'WorkItemWidgetConnection',
+ nodes: [
+ {
+ __typename: 'TitleWidget',
+ type: 'TITLE',
+ contentText: 'Test',
+ },
+ ],
+ },
+ },
+};
diff --git a/spec/frontend/work_items/pages/work_item_root_spec.js b/spec/frontend/work_items/pages/work_item_root_spec.js
new file mode 100644
index 00000000000..64d02baed36
--- /dev/null
+++ b/spec/frontend/work_items/pages/work_item_root_spec.js
@@ -0,0 +1,70 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
+import WorkItemsRoot from '~/work_items/pages/work_item_root.vue';
+import { workItemQueryResponse } from '../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+const WORK_ITEM_ID = '1';
+
+describe('Work items root component', () => {
+ let wrapper;
+ let fakeApollo;
+
+ const findTitle = () => wrapper.find('[data-testid="title"]');
+
+ const createComponent = ({ queryResponse = workItemQueryResponse } = {}) => {
+ fakeApollo = createMockApollo();
+ fakeApollo.clients.defaultClient.cache.writeQuery({
+ query: workItemQuery,
+ variables: {
+ id: WORK_ITEM_ID,
+ },
+ data: queryResponse,
+ });
+
+ wrapper = shallowMount(WorkItemsRoot, {
+ propsData: {
+ id: WORK_ITEM_ID,
+ },
+ localVue,
+ apolloProvider: fakeApollo,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ fakeApollo = null;
+ });
+
+ it('renders the title if title is in the widgets list', () => {
+ createComponent();
+
+ expect(findTitle().exists()).toBe(true);
+ expect(findTitle().text()).toBe('Test');
+ });
+
+ it('does not render the title if title is not in the widgets list', () => {
+ const queryResponse = {
+ workItem: {
+ ...workItemQueryResponse.workItem,
+ widgets: {
+ __typename: 'WorkItemWidgetConnection',
+ nodes: [
+ {
+ __typename: 'SomeOtherWidget',
+ type: 'OTHER',
+ contentText: 'Test',
+ },
+ ],
+ },
+ },
+ };
+ createComponent({ queryResponse });
+
+ expect(findTitle().exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/work_items/router_spec.js b/spec/frontend/work_items/router_spec.js
new file mode 100644
index 00000000000..0a57eab753f
--- /dev/null
+++ b/spec/frontend/work_items/router_spec.js
@@ -0,0 +1,30 @@
+import { mount } from '@vue/test-utils';
+import App from '~/work_items/components/app.vue';
+import WorkItemsRoot from '~/work_items/pages/work_item_root.vue';
+import { createRouter } from '~/work_items/router';
+
+describe('Work items router', () => {
+ let wrapper;
+
+ const createComponent = async (routeArg) => {
+ const router = createRouter('/work_item');
+ if (routeArg !== undefined) {
+ await router.push(routeArg);
+ }
+
+ wrapper = mount(App, {
+ router,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ window.location.hash = '';
+ });
+
+ it('renders work item on `/1` route', async () => {
+ await createComponent('/1');
+
+ expect(wrapper.find(WorkItemsRoot).exists()).toBe(true);
+ });
+});
diff --git a/spec/graphql/mutations/customer_relations/contacts/create_spec.rb b/spec/graphql/mutations/customer_relations/contacts/create_spec.rb
index 21a1aa2741a..0f05504d4f2 100644
--- a/spec/graphql/mutations/customer_relations/contacts/create_spec.rb
+++ b/spec/graphql/mutations/customer_relations/contacts/create_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Mutations::CustomerRelations::Contacts::Create do
it 'raises an error' do
expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- .with_message("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
+ .with_message(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
end
end
@@ -45,7 +45,7 @@ RSpec.describe Mutations::CustomerRelations::Contacts::Create do
it 'raises an error' do
expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- .with_message('Feature disabled')
+ .with_message("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
end
end
@@ -97,5 +97,5 @@ RSpec.describe Mutations::CustomerRelations::Contacts::Create do
end
end
- specify { expect(described_class).to require_graphql_authorizations(:admin_contact) }
+ specify { expect(described_class).to require_graphql_authorizations(:admin_crm_contact) }
end
diff --git a/spec/graphql/mutations/customer_relations/contacts/update_spec.rb b/spec/graphql/mutations/customer_relations/contacts/update_spec.rb
index 93bc6f53cf9..4f59de194fd 100644
--- a/spec/graphql/mutations/customer_relations/contacts/update_spec.rb
+++ b/spec/graphql/mutations/customer_relations/contacts/update_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Mutations::CustomerRelations::Contacts::Update do
let(:last_name) { 'Smith' }
let(:email) { 'ls@gitlab.com' }
let(:description) { 'VIP' }
- let(:does_not_exist_or_no_permission) { "The resource that you are attempting to access does not exist or you don't have permission to perform this action" }
+ let(:does_not_exist_or_no_permission) { Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR }
let(:contact) { create(:contact, group: group) }
let(:attributes) do
{
@@ -65,11 +65,11 @@ RSpec.describe Mutations::CustomerRelations::Contacts::Update do
it 'raises an error' do
expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- .with_message('Feature disabled')
+ .with_message("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
end
end
end
end
- specify { expect(described_class).to require_graphql_authorizations(:admin_contact) }
+ specify { expect(described_class).to require_graphql_authorizations(:admin_crm_contact) }
end
diff --git a/spec/graphql/mutations/customer_relations/organizations/create_spec.rb b/spec/graphql/mutations/customer_relations/organizations/create_spec.rb
index 738a8d724ab..9be0f5d4289 100644
--- a/spec/graphql/mutations/customer_relations/organizations/create_spec.rb
+++ b/spec/graphql/mutations/customer_relations/organizations/create_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe Mutations::CustomerRelations::Organizations::Create do
it 'raises an error' do
expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- .with_message("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
+ .with_message(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
end
end
@@ -46,7 +46,7 @@ RSpec.describe Mutations::CustomerRelations::Organizations::Create do
it 'raises an error' do
expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- .with_message('Feature disabled')
+ .with_message("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
end
end
@@ -69,5 +69,5 @@ RSpec.describe Mutations::CustomerRelations::Organizations::Create do
end
end
- specify { expect(described_class).to require_graphql_authorizations(:admin_organization) }
+ specify { expect(described_class).to require_graphql_authorizations(:admin_crm_organization) }
end
diff --git a/spec/graphql/mutations/customer_relations/organizations/update_spec.rb b/spec/graphql/mutations/customer_relations/organizations/update_spec.rb
index 0bc6f184fe3..e3aa8eafe0c 100644
--- a/spec/graphql/mutations/customer_relations/organizations/update_spec.rb
+++ b/spec/graphql/mutations/customer_relations/organizations/update_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Mutations::CustomerRelations::Organizations::Update do
let(:name) { 'GitLab' }
let(:default_rate) { 1000.to_f }
let(:description) { 'VIP' }
- let(:does_not_exist_or_no_permission) { "The resource that you are attempting to access does not exist or you don't have permission to perform this action" }
+ let(:does_not_exist_or_no_permission) { Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR }
let(:organization) { create(:organization, group: group) }
let(:attributes) do
{
@@ -63,11 +63,11 @@ RSpec.describe Mutations::CustomerRelations::Organizations::Update do
it 'raises an error' do
expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- .with_message('Feature disabled')
+ .with_message("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
end
end
end
end
- specify { expect(described_class).to require_graphql_authorizations(:admin_organization) }
+ specify { expect(described_class).to require_graphql_authorizations(:admin_crm_organization) }
end
diff --git a/spec/graphql/mutations/discussions/toggle_resolve_spec.rb b/spec/graphql/mutations/discussions/toggle_resolve_spec.rb
index 8c11279a80a..2041b86d6e7 100644
--- a/spec/graphql/mutations/discussions/toggle_resolve_spec.rb
+++ b/spec/graphql/mutations/discussions/toggle_resolve_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Mutations::Discussions::ToggleResolve do
it 'raises an error if the resource is not accessible to the user' do
expect { subject }.to raise_error(
Gitlab::Graphql::Errors::ResourceNotAvailable,
- "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
)
end
end
@@ -41,7 +41,7 @@ RSpec.describe Mutations::Discussions::ToggleResolve do
it 'raises an error' do
expect { subject }.to raise_error(
Gitlab::Graphql::Errors::ResourceNotAvailable,
- "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
)
end
end
diff --git a/spec/graphql/mutations/environments/canary_ingress/update_spec.rb b/spec/graphql/mutations/environments/canary_ingress/update_spec.rb
index 2715a908f85..48e55828a6b 100644
--- a/spec/graphql/mutations/environments/canary_ingress/update_spec.rb
+++ b/spec/graphql/mutations/environments/canary_ingress/update_spec.rb
@@ -60,7 +60,7 @@ RSpec.describe Mutations::Environments::CanaryIngress::Update do
let(:user) { reporter }
it 'raises an error' do
- expect { subject }.to raise_error("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
+ expect { subject }.to raise_error(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
end
end
end
diff --git a/spec/graphql/mutations/merge_requests/set_wip_spec.rb b/spec/graphql/mutations/merge_requests/set_wip_spec.rb
deleted file mode 100644
index fae9c4f7fe0..00000000000
--- a/spec/graphql/mutations/merge_requests/set_wip_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Mutations::MergeRequests::SetWip do
- let(:merge_request) { create(:merge_request) }
- let(:user) { create(:user) }
-
- subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
-
- specify { expect(described_class).to require_graphql_authorizations(:update_merge_request) }
-
- describe '#resolve' do
- let(:wip) { true }
- let(:mutated_merge_request) { subject[:merge_request] }
-
- subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, wip: wip) }
-
- it_behaves_like 'permission level for merge request mutation is correctly verified'
-
- context 'when the user can update the merge request' do
- before do
- merge_request.project.add_developer(user)
- end
-
- it 'returns the merge request as a wip' do
- expect(mutated_merge_request).to eq(merge_request)
- expect(mutated_merge_request).to be_work_in_progress
- expect(subject[:errors]).to be_empty
- end
-
- it 'returns errors merge request could not be updated' do
- # Make the merge request invalid
- merge_request.allow_broken = true
- merge_request.update!(source_project: nil)
-
- expect(subject[:errors]).not_to be_empty
- end
-
- context 'when passing wip as false' do
- let(:wip) { false }
-
- it 'removes `wip` from the title' do
- merge_request.update!(title: "WIP: working on it")
-
- expect(mutated_merge_request).not_to be_work_in_progress
- end
-
- it 'does not do anything if the title did not start with wip' do
- expect(mutated_merge_request).not_to be_work_in_progress
- end
- end
- end
- end
-end
diff --git a/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb b/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb
index e78f755d5c7..39794a070c6 100644
--- a/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb
+++ b/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Mutations::Notes::RepositionImageDiffNote do
it 'raises an error if the resource is not accessible to the user' do
expect { subject }.to raise_error(
Gitlab::Graphql::Errors::ResourceNotAvailable,
- "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
)
end
end
diff --git a/spec/graphql/mutations/releases/delete_spec.rb b/spec/graphql/mutations/releases/delete_spec.rb
index d97f839ce87..9934aea0031 100644
--- a/spec/graphql/mutations/releases/delete_spec.rb
+++ b/spec/graphql/mutations/releases/delete_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Mutations::Releases::Delete do
shared_examples 'unauthorized or not found error' do
it 'raises a Gitlab::Graphql::Errors::ResourceNotAvailable error' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, "The resource that you are attempting to access does not exist or you don't have permission to perform this action")
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
end
end
diff --git a/spec/graphql/mutations/releases/update_spec.rb b/spec/graphql/mutations/releases/update_spec.rb
index 5ee63ac4dc2..9fae703b85a 100644
--- a/spec/graphql/mutations/releases/update_spec.rb
+++ b/spec/graphql/mutations/releases/update_spec.rb
@@ -232,7 +232,7 @@ RSpec.describe Mutations::Releases::Update do
let(:mutation_arguments) { super().merge(project_path: 'not/a/real/path') }
it 'raises an error' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, "The resource that you are attempting to access does not exist or you don't have permission to perform this action")
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
end
end
end
@@ -242,7 +242,7 @@ RSpec.describe Mutations::Releases::Update do
let(:current_user) { reporter }
it 'raises an error' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, "The resource that you are attempting to access does not exist or you don't have permission to perform this action")
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
end
end
end
diff --git a/spec/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb b/spec/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb
new file mode 100644
index 00000000000..f16d504a4ae
--- /dev/null
+++ b/spec/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Security::CiConfiguration::ConfigureSastIac do
+ include GraphqlHelpers
+
+ let(:service) { ::Security::CiConfiguration::SastIacCreateService }
+
+ subject { resolve(described_class, args: { project_path: project.full_path }, ctx: { current_user: user }) }
+
+ include_examples 'graphql mutations security ci configuration'
+end
diff --git a/spec/graphql/resolvers/concerns/resolves_groups_spec.rb b/spec/graphql/resolvers/concerns/resolves_groups_spec.rb
new file mode 100644
index 00000000000..bfbbae29e92
--- /dev/null
+++ b/spec/graphql/resolvers/concerns/resolves_groups_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ResolvesGroups do
+ include GraphqlHelpers
+ include AfterNextHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:groups) { create_pair(:group) }
+
+ let_it_be(:resolver) do
+ Class.new(Resolvers::BaseResolver) do
+ include ResolvesGroups
+ type Types::GroupType, null: true
+ end
+ end
+
+ let_it_be(:query_type) do
+ query_factory do |query|
+ query.field :groups,
+ Types::GroupType.connection_type,
+ null: true,
+ resolver: resolver
+ end
+ end
+
+ let_it_be(:lookahead_fields) do
+ <<~FIELDS
+ contacts { nodes { id } }
+ containerRepositoriesCount
+ customEmoji { nodes { id } }
+ fullPath
+ organizations { nodes { id } }
+ path
+ dependencyProxyBlobCount
+ dependencyProxyBlobs { nodes { fileName } }
+ dependencyProxyImageCount
+ dependencyProxyImageTtlPolicy { enabled }
+ dependencyProxySetting { enabled }
+ FIELDS
+ end
+
+ it 'avoids N+1 queries on the fields marked with lookahead' do
+ group_ids = groups.map(&:id)
+
+ allow_next(resolver).to receive(:resolve_groups).and_return(Group.id_in(group_ids))
+ # Prevent authorization queries from affecting the test.
+ allow(Ability).to receive(:allowed?).and_return(true)
+
+ single_group_query = ActiveRecord::QueryRecorder.new do
+ data = query_groups(limit: 1)
+ expect(data.size).to eq(1)
+ end
+
+ multi_group_query = -> {
+ data = query_groups(limit: 2)
+ expect(data.size).to eq(2)
+ }
+
+ expect { multi_group_query.call }.not_to exceed_query_limit(single_group_query)
+ end
+
+ def query_groups(limit:)
+ query_string = "{ groups(first: #{limit}) { nodes { id #{lookahead_fields} } } }"
+
+ data = execute_query(query_type, graphql: query_string)
+
+ graphql_dig_at(data, :data, :groups, :nodes)
+ end
+end
diff --git a/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb b/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb
index 865e892b12d..3fcfa967452 100644
--- a/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb
+++ b/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb
@@ -20,23 +20,37 @@ RSpec.describe ResolvesPipelines do
let_it_be(:project) { create(:project, :private) }
let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
let_it_be(:failed_pipeline) { create(:ci_pipeline, :failed, project: project) }
+ let_it_be(:success_pipeline) { create(:ci_pipeline, :success, project: project) }
let_it_be(:ref_pipeline) { create(:ci_pipeline, project: project, ref: 'awesome-feature') }
let_it_be(:sha_pipeline) { create(:ci_pipeline, project: project, sha: 'deadbeef') }
+ let_it_be(:all_pipelines) do
+ [
+ pipeline,
+ failed_pipeline,
+ success_pipeline,
+ ref_pipeline,
+ sha_pipeline
+ ]
+ end
before do
project.add_developer(current_user)
end
- it { is_expected.to have_graphql_arguments(:status, :ref, :sha, :source) }
+ it { is_expected.to have_graphql_arguments(:status, :scope, :ref, :sha, :source) }
it 'finds all pipelines' do
- expect(resolve_pipelines).to contain_exactly(pipeline, failed_pipeline, ref_pipeline, sha_pipeline)
+ expect(resolve_pipelines).to contain_exactly(*all_pipelines)
end
it 'allows filtering by status' do
expect(resolve_pipelines(status: 'failed')).to contain_exactly(failed_pipeline)
end
+ it 'allows filtering by scope' do
+ expect(resolve_pipelines(scope: 'finished')).to contain_exactly(failed_pipeline, success_pipeline)
+ end
+
it 'allows filtering by ref' do
expect(resolve_pipelines(ref: 'awesome-feature')).to contain_exactly(ref_pipeline)
end
@@ -54,7 +68,7 @@ RSpec.describe ResolvesPipelines do
end
it 'does not filter by source' do
- expect(resolve_pipelines(source: 'web')).to contain_exactly(pipeline, failed_pipeline, ref_pipeline, sha_pipeline, source_pipeline)
+ expect(resolve_pipelines(source: 'web')).to contain_exactly(*all_pipelines, source_pipeline)
end
end
@@ -64,7 +78,7 @@ RSpec.describe ResolvesPipelines do
end
it 'returns all the pipelines' do
- expect(resolve_pipelines).to contain_exactly(pipeline, failed_pipeline, ref_pipeline, sha_pipeline, source_pipeline)
+ expect(resolve_pipelines).to contain_exactly(*all_pipelines, source_pipeline)
end
end
end
diff --git a/spec/graphql/resolvers/group_issues_resolver_spec.rb b/spec/graphql/resolvers/group_issues_resolver_spec.rb
index 463cdca699b..e17429560ac 100644
--- a/spec/graphql/resolvers/group_issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_issues_resolver_spec.rb
@@ -29,15 +29,72 @@ RSpec.describe Resolvers::GroupIssuesResolver do
describe '#resolve' do
it 'finds all group issues' do
- result = resolve(described_class, obj: group, ctx: { current_user: current_user })
-
- expect(result).to contain_exactly(issue1, issue2, issue3)
+ expect(resolve_issues).to contain_exactly(issue1, issue2, issue3)
end
it 'finds all group and subgroup issues' do
- result = resolve(described_class, obj: group, args: { include_subgroups: true }, ctx: { current_user: current_user })
+ result = resolve_issues(include_subgroups: true)
expect(result).to contain_exactly(issue1, issue2, issue3, subissue1, subissue2, subissue3)
end
+
+ it 'returns issues without the specified issue_type' do
+ result = resolve_issues(not: { types: ['issue'] })
+
+ expect(result).to contain_exactly(issue1)
+ end
+
+ context 'confidential issues' do
+ let_it_be(:confidential_issue1) { create(:issue, project: project, confidential: true) }
+ let_it_be(:confidential_issue2) { create(:issue, project: other_project, confidential: true) }
+
+ context "when user is allowed to view confidential issues" do
+ it 'returns all viewable issues by default' do
+ expect(resolve_issues).to contain_exactly(issue1, issue2, issue3, confidential_issue1, confidential_issue2)
+ end
+
+ context 'filtering for confidential issues' do
+ it 'returns only the non-confidential issues for the group when filter is set to false' do
+ expect(resolve_issues({ confidential: false })).to contain_exactly(issue1, issue2, issue3)
+ end
+
+ it "returns only the confidential issues for the group when filter is set to true" do
+ expect(resolve_issues({ confidential: true })).to contain_exactly(confidential_issue1, confidential_issue2)
+ end
+ end
+ end
+
+ context "when user is not allowed to see confidential issues" do
+ before do
+ group.add_guest(current_user)
+ end
+
+ it 'returns all viewable issues by default' do
+ expect(resolve_issues).to contain_exactly(issue1, issue2, issue3)
+ end
+
+ context 'filtering for confidential issues' do
+ it 'does not return the confidential issues when filter is set to false' do
+ expect(resolve_issues({ confidential: false })).to contain_exactly(issue1, issue2, issue3)
+ end
+
+ it 'does not return the confidential issues when filter is set to true' do
+ expect(resolve_issues({ confidential: true })).to be_empty
+ end
+ end
+ end
+ end
+
+ context 'release_tag filter' do
+ it 'returns an error when trying to filter by negated release_tag' do
+ expect do
+ resolve_issues(not: { release_tag: ['v1.0'] })
+ end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'releaseTag filter is not allowed when parent is a group.')
+ end
+ end
+ end
+
+ def resolve_issues(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: group, args: args, ctx: context)
end
end
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index 9897e697009..3c892214aaf 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -26,14 +26,7 @@ RSpec.describe Resolvers::IssuesResolver do
expect(described_class).to have_nullable_graphql_type(Types::IssueType.connection_type)
end
- shared_context 'filtering for confidential issues' do
- let_it_be(:confidential_issue1) { create(:issue, project: project, confidential: true) }
- let_it_be(:confidential_issue2) { create(:issue, project: other_project, confidential: true) }
- end
-
context "with a project" do
- let(:obj) { project }
-
before_all do
project.add_developer(current_user)
project.add_reporter(reporter)
@@ -112,6 +105,54 @@ RSpec.describe Resolvers::IssuesResolver do
end
end
+ describe 'filter by release' do
+ let_it_be(:milestone1) { create(:milestone, project: project, start_date: 1.day.from_now, title: 'Version 1') }
+ let_it_be(:milestone2) { create(:milestone, project: project, start_date: 1.day.from_now, title: 'Version 2') }
+ let_it_be(:milestone3) { create(:milestone, project: project, start_date: 1.day.from_now, title: 'Version 3') }
+ let_it_be(:release1) { create(:release, tag: 'v1.0', milestones: [milestone1], project: project) }
+ let_it_be(:release2) { create(:release, tag: 'v2.0', milestones: [milestone2], project: project) }
+ let_it_be(:release3) { create(:release, tag: 'v3.0', milestones: [milestone3], project: project) }
+ let_it_be(:release_issue1) { create(:issue, project: project, milestone: milestone1) }
+ let_it_be(:release_issue2) { create(:issue, project: project, milestone: milestone2) }
+ let_it_be(:release_issue3) { create(:issue, project: project, milestone: milestone3) }
+
+ describe 'filter by release_tag' do
+ it 'returns all issues associated with the specified tags' do
+ expect(resolve_issues(release_tag: [release1.tag, release3.tag])).to contain_exactly(release_issue1, release_issue3)
+ end
+
+ context 'when release_tag_wildcard_id is also provided' do
+ it 'raises a mutually eclusive argument error' do
+ expect do
+ resolve_issues(release_tag: [release1.tag], release_tag_wildcard_id: 'ANY')
+ end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [releaseTag, releaseTagWildcardId] arguments is allowed at the same time.')
+ end
+ end
+ end
+
+ describe 'filter by negated release_tag' do
+ it 'returns all issues not associated with the specified tags' do
+ expect(resolve_issues(not: { release_tag: [release1.tag, release3.tag] })).to contain_exactly(release_issue2)
+ end
+ end
+
+ describe 'filter by release_tag_wildcard_id' do
+ subject { resolve_issues(release_tag_wildcard_id: wildcard_id) }
+
+ context 'when filtering by ANY' do
+ let(:wildcard_id) { 'ANY' }
+
+ it { is_expected.to contain_exactly(release_issue1, release_issue2, release_issue3) }
+ end
+
+ context 'when filtering by NONE' do
+ let(:wildcard_id) { 'NONE' }
+
+ it { is_expected.to contain_exactly(issue1, issue2) }
+ end
+ end
+ end
+
it 'filters by two assignees' do
assignee2 = create(:user)
issue2.update!(assignees: [assignee, assignee2])
@@ -230,7 +271,8 @@ RSpec.describe Resolvers::IssuesResolver do
end
context 'confidential issues' do
- include_context 'filtering for confidential issues'
+ let_it_be(:confidential_issue1) { create(:issue, project: project, confidential: true) }
+ let_it_be(:confidential_issue2) { create(:issue, project: other_project, confidential: true) }
context "when user is allowed to view confidential issues" do
it 'returns all viewable issues by default' do
@@ -561,64 +603,6 @@ RSpec.describe Resolvers::IssuesResolver do
end
end
- context "with a group" do
- let(:obj) { group }
-
- before do
- group.add_developer(current_user)
- end
-
- describe '#resolve' do
- it 'finds all group issues' do
- expect(resolve_issues).to contain_exactly(issue1, issue2, issue3)
- end
-
- it 'returns issues without the specified issue_type' do
- expect(resolve_issues({ not: { types: ['issue'] } })).to contain_exactly(issue1)
- end
-
- context "confidential issues" do
- include_context 'filtering for confidential issues'
-
- context "when user is allowed to view confidential issues" do
- it 'returns all viewable issues by default' do
- expect(resolve_issues).to contain_exactly(issue1, issue2, issue3, confidential_issue1, confidential_issue2)
- end
-
- context 'filtering for confidential issues' do
- it 'returns only the non-confidential issues for the group when filter is set to false' do
- expect(resolve_issues({ confidential: false })).to contain_exactly(issue1, issue2, issue3)
- end
-
- it "returns only the confidential issues for the group when filter is set to true" do
- expect(resolve_issues({ confidential: true })).to contain_exactly(confidential_issue1, confidential_issue2)
- end
- end
- end
-
- context "when user is not allowed to see confidential issues" do
- before do
- group.add_guest(current_user)
- end
-
- it 'returns all viewable issues by default' do
- expect(resolve_issues).to contain_exactly(issue1, issue2, issue3)
- end
-
- context 'filtering for confidential issues' do
- it 'does not return the confidential issues when filter is set to false' do
- expect(resolve_issues({ confidential: false })).to contain_exactly(issue1, issue2, issue3)
- end
-
- it 'does not return the confidential issues when filter is set to true' do
- expect(resolve_issues({ confidential: true })).to be_empty
- end
- end
- end
- end
- end
- end
-
context "when passing a non existent, batch loaded project" do
let!(:project) do
BatchLoader::GraphQL.for("non-existent-path").batch do |_fake_paths, loader, _|
@@ -626,8 +610,6 @@ RSpec.describe Resolvers::IssuesResolver do
end
end
- let(:obj) { project }
-
it "returns nil without breaking" do
expect(resolve_issues(iids: ["don't", "break"])).to be_empty
end
@@ -648,6 +630,6 @@ RSpec.describe Resolvers::IssuesResolver do
end
def resolve_issues(args = {}, context = { current_user: current_user })
- resolve(described_class, obj: obj, args: args, ctx: context)
+ resolve(described_class, obj: project, args: args, ctx: context)
end
end
diff --git a/spec/graphql/resolvers/merge_requests_resolver_spec.rb b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
index a897acf7eba..a931b0a3f77 100644
--- a/spec/graphql/resolvers/merge_requests_resolver_spec.rb
+++ b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
@@ -218,6 +218,54 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
end
+ context 'with created_after and created_before arguments' do
+ before do
+ merge_request_1.update!(created_at: 4.days.ago)
+ end
+
+ let(:all_mrs) do
+ [merge_request_1, merge_request_2, merge_request_3, merge_request_4, merge_request_5, merge_request_6, merge_request_with_milestone]
+ end
+
+ it 'returns merge requests created within a given period' do
+ result = resolve_mr(project, created_after: 5.days.ago, created_before: 2.days.ago)
+
+ expect(result).to contain_exactly(
+ merge_request_1
+ )
+ end
+
+ it 'returns some values filtered with created_before' do
+ result = resolve_mr(project, created_before: 1.day.ago)
+
+ expect(result).to contain_exactly(merge_request_1)
+ end
+
+ it 'returns some values filtered with created_after' do
+ result = resolve_mr(project, created_after: 3.days.ago)
+
+ expect(result).to match_array(all_mrs - [merge_request_1])
+ end
+
+ it 'does not return anything for dates (even in the future) not matching any MRs' do
+ result = resolve_mr(project, created_after: 5.days.from_now)
+
+ expect(result).to be_empty
+ end
+
+ it 'does not return anything for dates not matching any MRs' do
+ result = resolve_mr(project, created_before: 15.days.ago)
+
+ expect(result).to be_empty
+ end
+
+ it 'does not return any values for an impossible set' do
+ result = resolve_mr(project, created_after: 5.days.ago, created_before: 6.days.ago)
+
+ expect(result).to be_empty
+ end
+ end
+
context 'with milestone argument' do
it 'filters merge requests by milestone title' do
result = resolve_mr(project, milestone_title: milestone.title)
diff --git a/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb b/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb
index 75b9be7dfe7..c6d8c518fb7 100644
--- a/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb
@@ -90,7 +90,10 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do
end
it 'raises failure error' do
- expect { resolve_jira_projects }.to raise_error('An error occurred while requesting data from Jira: Some failure. Check your Jira integration configuration and try again.')
+ config_docs_link_url = Rails.application.routes.url_helpers.help_page_path('integration/jira/configure')
+ docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: config_docs_link_url }
+ error_message = 'An error occurred while requesting data from Jira: Some failure. Check your %{docs_link_start}Jira integration configuration</a> and try again.' % { docs_link_start: docs_link_start }
+ expect { resolve_jira_projects }.to raise_error(error_message)
end
end
end
diff --git a/spec/graphql/resolvers/timelog_resolver_spec.rb b/spec/graphql/resolvers/timelog_resolver_spec.rb
index f45f528fe7e..9b3f555071e 100644
--- a/spec/graphql/resolvers/timelog_resolver_spec.rb
+++ b/spec/graphql/resolvers/timelog_resolver_spec.rb
@@ -11,6 +11,8 @@ RSpec.describe Resolvers::TimelogResolver do
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:error_class) { Gitlab::Graphql::Errors::ArgumentError }
+ let(:timelogs) { resolve_timelogs(**args) }
+
specify do
expect(described_class).to have_non_null_graphql_type(::Types::TimelogType.connection_type)
end
@@ -24,8 +26,6 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { start_time: 6.days.ago, end_time: 2.days.ago.noon } }
it 'finds all timelogs within given dates' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs).to contain_exactly(timelog1)
end
@@ -33,8 +33,6 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { {} }
it 'finds all timelogs' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs).to contain_exactly(timelog1, timelog2, timelog3)
end
end
@@ -43,8 +41,6 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { start_time: 2.days.ago.noon } }
it 'finds timelogs after the start_time' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs).to contain_exactly(timelog2)
end
end
@@ -53,8 +49,6 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { end_time: 2.days.ago.noon } }
it 'finds timelogs before the end_time' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs).to contain_exactly(timelog1, timelog3)
end
end
@@ -63,8 +57,6 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { start_time: 6.days.ago, end_date: 2.days.ago } }
it 'finds timelogs until the end of day of end_date' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs).to contain_exactly(timelog1, timelog2)
end
end
@@ -73,8 +65,6 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { start_date: 6.days.ago, end_time: 2.days.ago.noon } }
it 'finds all timelogs within start_date and end_time' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs).to contain_exactly(timelog1)
end
end
@@ -96,7 +86,7 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { start_time: 6.days.ago, start_date: 6.days.ago } }
it 'returns correct error' do
- expect { resolve_timelogs(**args) }
+ expect { timelogs }
.to raise_error(error_class, /Provide either a start date or time, but not both/)
end
end
@@ -105,7 +95,7 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { end_time: 2.days.ago, end_date: 2.days.ago } }
it 'returns correct error' do
- expect { resolve_timelogs(**args) }
+ expect { timelogs }
.to raise_error(error_class, /Provide either an end date or time, but not both/)
end
end
@@ -114,14 +104,14 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { start_time: 2.days.ago, end_time: 6.days.ago } }
it 'returns correct error' do
- expect { resolve_timelogs(**args) }
+ expect { timelogs }
.to raise_error(error_class, /Start argument must be before End argument/)
end
end
end
end
- shared_examples "with a group" do
+ shared_examples 'with a group' do
let_it_be(:short_time_ago) { 5.days.ago.beginning_of_day }
let_it_be(:medium_time_ago) { 15.days.ago.beginning_of_day }
@@ -141,8 +131,6 @@ RSpec.describe Resolvers::TimelogResolver do
end
it 'finds all timelogs within given dates' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs).to contain_exactly(timelog1)
end
@@ -150,8 +138,6 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { start_date: short_time_ago } }
it 'finds timelogs until the end of day of end_date' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs).to contain_exactly(timelog1, timelog2)
end
end
@@ -160,8 +146,6 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { end_date: medium_time_ago } }
it 'finds timelogs until the end of day of end_date' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs).to contain_exactly(timelog3)
end
end
@@ -170,8 +154,6 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { start_time: short_time_ago, end_date: short_time_ago } }
it 'finds timelogs until the end of day of end_date' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs).to contain_exactly(timelog1, timelog2)
end
end
@@ -180,8 +162,6 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { start_date: short_time_ago, end_time: short_time_ago.noon } }
it 'finds all timelogs within start_date and end_time' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs).to contain_exactly(timelog1)
end
end
@@ -191,7 +171,7 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { start_time: short_time_ago, start_date: short_time_ago } }
it 'returns correct error' do
- expect { resolve_timelogs(**args) }
+ expect { timelogs }
.to raise_error(error_class, /Provide either a start date or time, but not both/)
end
end
@@ -200,7 +180,7 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { end_time: short_time_ago, end_date: short_time_ago } }
it 'returns correct error' do
- expect { resolve_timelogs(**args) }
+ expect { timelogs }
.to raise_error(error_class, /Provide either an end date or time, but not both/)
end
end
@@ -209,14 +189,14 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { { start_time: short_time_ago, end_time: medium_time_ago } }
it 'returns correct error' do
- expect { resolve_timelogs(**args) }
+ expect { timelogs }
.to raise_error(error_class, /Start argument must be before End argument/)
end
end
end
end
- shared_examples "with a user" do
+ shared_examples 'with a user' do
let_it_be(:short_time_ago) { 5.days.ago.beginning_of_day }
let_it_be(:medium_time_ago) { 15.days.ago.beginning_of_day }
@@ -228,20 +208,18 @@ RSpec.describe Resolvers::TimelogResolver do
let_it_be(:timelog3) { create(:merge_request_timelog, merge_request: merge_request, user: current_user) }
it 'blah' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs).to contain_exactly(timelog1, timelog3)
end
end
- context "on a project" do
+ context 'on a project' do
let(:object) { project }
let(:extra_args) { {} }
it_behaves_like 'with a project'
end
- context "with a project filter" do
+ context 'with a project filter' do
let(:object) { nil }
let(:extra_args) { { project_id: project.to_global_id } }
@@ -285,8 +263,6 @@ RSpec.describe Resolvers::TimelogResolver do
let(:extra_args) { {} }
it 'pagination returns `default_max_page_size` and sets `has_next_page` true' do
- timelogs = resolve_timelogs(**args)
-
expect(timelogs.items.count).to be(100)
expect(timelogs.has_next_page).to be(true)
end
@@ -298,7 +274,7 @@ RSpec.describe Resolvers::TimelogResolver do
let(:extra_args) { {} }
it 'returns correct error' do
- expect { resolve_timelogs(**args) }
+ expect { timelogs }
.to raise_error(error_class, /Provide at least one argument/)
end
end
diff --git a/spec/graphql/resolvers/topics_resolver_spec.rb b/spec/graphql/resolvers/topics_resolver_spec.rb
new file mode 100644
index 00000000000..3ff1dabc927
--- /dev/null
+++ b/spec/graphql/resolvers/topics_resolver_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::TopicsResolver do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ let!(:topic1) { create(:topic, name: 'GitLab', total_projects_count: 1) }
+ let!(:topic2) { create(:topic, name: 'git', total_projects_count: 2) }
+ let!(:topic3) { create(:topic, name: 'topic3', total_projects_count: 3) }
+
+ it 'finds all topics' do
+ expect(resolve_topics).to eq([topic3, topic2, topic1])
+ end
+
+ context 'with search' do
+ it 'searches environment by name' do
+ expect(resolve_topics(search: 'git')).to eq([topic2, topic1])
+ end
+
+ context 'when the search term does not match any topic' do
+ it 'is empty' do
+ expect(resolve_topics(search: 'nonsense')).to be_empty
+ end
+ end
+ end
+ end
+
+ def resolve_topics(args = {})
+ resolve(described_class, args: args)
+ end
+end
diff --git a/spec/graphql/types/alert_management/prometheus_integration_type_spec.rb b/spec/graphql/types/alert_management/prometheus_integration_type_spec.rb
index 31cf94aef44..bfb6958e327 100644
--- a/spec/graphql/types/alert_management/prometheus_integration_type_spec.rb
+++ b/spec/graphql/types/alert_management/prometheus_integration_type_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe GitlabSchema.types['AlertManagementPrometheusIntegration'] do
describe 'a group integration' do
let_it_be(:group) { create(:group) }
- let_it_be(:integration) { create(:prometheus_integration, project: nil, group: group) }
+ let_it_be(:integration) { create(:prometheus_integration, :group, group: group) }
# Since it is impossible to authorize the parent here, given that the
# project is nil, all fields should be redacted:
diff --git a/spec/graphql/types/ci/job_artifact_type_spec.rb b/spec/graphql/types/ci/job_artifact_type_spec.rb
index d4dc5ef214d..58b5f9cfcb7 100644
--- a/spec/graphql/types/ci/job_artifact_type_spec.rb
+++ b/spec/graphql/types/ci/job_artifact_type_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['CiJobArtifact'] do
it 'has the correct fields' do
- expected_fields = [:download_path, :file_type]
+ expected_fields = [:download_path, :file_type, :name]
expect(described_class).to have_graphql_fields(*expected_fields)
end
diff --git a/spec/graphql/types/ci/pipeline_scope_enum_spec.rb b/spec/graphql/types/ci/pipeline_scope_enum_spec.rb
new file mode 100644
index 00000000000..9dc6e5c6fae
--- /dev/null
+++ b/spec/graphql/types/ci/pipeline_scope_enum_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::PipelineScopeEnum do
+ it 'exposes all pipeline scopes' do
+ expect(described_class.values.keys).to contain_exactly(
+ *::Ci::PipelinesFinder::ALLOWED_SCOPES.keys.map(&:to_s)
+ )
+ end
+end
diff --git a/spec/graphql/types/ci/pipeline_status_enum_spec.rb b/spec/graphql/types/ci/pipeline_status_enum_spec.rb
new file mode 100644
index 00000000000..2d6683c6384
--- /dev/null
+++ b/spec/graphql/types/ci/pipeline_status_enum_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::PipelineStatusEnum do
+ it 'exposes all pipeline states' do
+ expect(described_class.values.keys).to contain_exactly(
+ *::Ci::Pipeline.all_state_names.map(&:to_s).map(&:upcase)
+ )
+ end
+end
diff --git a/spec/graphql/types/ci/pipeline_type_spec.rb b/spec/graphql/types/ci/pipeline_type_spec.rb
index 8c849114cf6..58724524785 100644
--- a/spec/graphql/types/ci/pipeline_type_spec.rb
+++ b/spec/graphql/types/ci/pipeline_type_spec.rb
@@ -12,8 +12,8 @@ RSpec.describe Types::Ci::PipelineType do
id iid sha before_sha complete status detailed_status config_source
duration queued_duration
coverage created_at updated_at started_at finished_at committed_at
- stages user retryable cancelable jobs source_job job downstream
- upstream path project active user_permissions warnings commit_path uses_needs
+ stages user retryable cancelable jobs source_job job job_artifacts downstream
+ upstream path project active user_permissions warnings commit commit_path uses_needs
test_report_summary test_suite ref
]
diff --git a/spec/graphql/types/commit_type_spec.rb b/spec/graphql/types/commit_type_spec.rb
index b43693e5804..2f74ce81761 100644
--- a/spec/graphql/types/commit_type_spec.rb
+++ b/spec/graphql/types/commit_type_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe GitlabSchema.types['Commit'] do
it 'contains attributes related to commit' do
expect(described_class).to have_graphql_fields(
- :id, :sha, :short_id, :title, :description, :description_html, :message, :title_html, :authored_date,
+ :id, :sha, :short_id, :title, :full_title, :full_title_html, :description, :description_html, :message, :title_html, :authored_date,
:author_name, :author_gravatar, :author, :web_url, :web_path,
:pipelines, :signature_html
)
diff --git a/spec/graphql/types/customer_relations/contact_type_spec.rb b/spec/graphql/types/customer_relations/contact_type_spec.rb
index a51ee705fb0..bb447f405b6 100644
--- a/spec/graphql/types/customer_relations/contact_type_spec.rb
+++ b/spec/graphql/types/customer_relations/contact_type_spec.rb
@@ -7,5 +7,5 @@ RSpec.describe GitlabSchema.types['CustomerRelationsContact'] do
it { expect(described_class.graphql_name).to eq('CustomerRelationsContact') }
it { expect(described_class).to have_graphql_fields(fields) }
- it { expect(described_class).to require_graphql_authorizations(:read_contact) }
+ it { expect(described_class).to require_graphql_authorizations(:read_crm_contact) }
end
diff --git a/spec/graphql/types/customer_relations/organization_type_spec.rb b/spec/graphql/types/customer_relations/organization_type_spec.rb
index 2562748477c..93844df1239 100644
--- a/spec/graphql/types/customer_relations/organization_type_spec.rb
+++ b/spec/graphql/types/customer_relations/organization_type_spec.rb
@@ -7,5 +7,5 @@ RSpec.describe GitlabSchema.types['CustomerRelationsOrganization'] do
it { expect(described_class.graphql_name).to eq('CustomerRelationsOrganization') }
it { expect(described_class).to have_graphql_fields(fields) }
- it { expect(described_class).to require_graphql_authorizations(:read_organization) }
+ it { expect(described_class).to require_graphql_authorizations(:read_crm_organization) }
end
diff --git a/spec/graphql/types/dependency_proxy/manifest_type_spec.rb b/spec/graphql/types/dependency_proxy/manifest_type_spec.rb
index 18cc89adfcb..b251ca63c4f 100644
--- a/spec/graphql/types/dependency_proxy/manifest_type_spec.rb
+++ b/spec/graphql/types/dependency_proxy/manifest_type_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['DependencyProxyManifest'] do
it 'includes dependency proxy manifest fields' do
expected_fields = %w[
- file_name image_name size created_at updated_at digest
+ id file_name image_name size created_at updated_at digest
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/evidence_type_spec.rb b/spec/graphql/types/evidence_type_spec.rb
index 92134e74d51..be85724eac5 100644
--- a/spec/graphql/types/evidence_type_spec.rb
+++ b/spec/graphql/types/evidence_type_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe GitlabSchema.types['ReleaseEvidence'] do
- it { expect(described_class).to require_graphql_authorizations(:download_code) }
+ specify { expect(described_class).to require_graphql_authorizations(:read_release_evidence) }
it 'has the expected fields' do
expected_fields = %w[
diff --git a/spec/graphql/types/merge_request_review_state_enum_spec.rb b/spec/graphql/types/merge_request_review_state_enum_spec.rb
index 486e1c4f502..407a1ae3c1f 100644
--- a/spec/graphql/types/merge_request_review_state_enum_spec.rb
+++ b/spec/graphql/types/merge_request_review_state_enum_spec.rb
@@ -12,6 +12,10 @@ RSpec.describe GitlabSchema.types['MergeRequestReviewState'] do
'UNREVIEWED' => have_attributes(
description: 'The merge request is unreviewed.',
value: 'unreviewed'
+ ),
+ 'ATTENTION_REQUESTED' => have_attributes(
+ description: 'The merge request is attention_requested.',
+ value: 'attention_requested'
)
)
end
diff --git a/spec/graphql/types/merge_request_type_spec.rb b/spec/graphql/types/merge_request_type_spec.rb
index bc3ccb0d9ba..b17b7c32289 100644
--- a/spec/graphql/types/merge_request_type_spec.rb
+++ b/spec/graphql/types/merge_request_type_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do
notes discussions user_permissions id iid title title_html description
description_html state created_at updated_at source_project target_project
project project_id source_project_id target_project_id source_branch
- target_branch work_in_progress draft merge_when_pipeline_succeeds diff_head_sha
+ target_branch draft merge_when_pipeline_succeeds diff_head_sha
merge_commit_sha user_notes_count user_discussions_count should_remove_source_branch
diff_refs diff_stats diff_stats_summary
force_remove_source_branch
diff --git a/spec/graphql/types/mutation_type_spec.rb b/spec/graphql/types/mutation_type_spec.rb
index c1a5c93c85b..95d835c88cf 100644
--- a/spec/graphql/types/mutation_type_spec.rb
+++ b/spec/graphql/types/mutation_type_spec.rb
@@ -3,14 +3,6 @@
require 'spec_helper'
RSpec.describe Types::MutationType do
- it 'is expected to have the deprecated MergeRequestSetWip' do
- field = get_field('MergeRequestSetWip')
-
- expect(field).to be_present
- expect(field.deprecation_reason).to be_present
- expect(field.resolver).to eq(Mutations::MergeRequests::SetWip)
- end
-
it 'is expected to have the MergeRequestSetDraft' do
expect(described_class).to have_graphql_mutation(Mutations::MergeRequests::SetDraft)
end
diff --git a/spec/graphql/types/packages/helm/dependency_type_spec.rb b/spec/graphql/types/packages/helm/dependency_type_spec.rb
new file mode 100644
index 00000000000..2047205275f
--- /dev/null
+++ b/spec/graphql/types/packages/helm/dependency_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageHelmDependencyType'] do
+ it { expect(described_class.graphql_name).to eq('PackageHelmDependencyType') }
+
+ it 'includes helm dependency fields' do
+ expected_fields = %w[
+ name version repository condition tags enabled import_values alias
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/packages/helm/file_metadatum_type_spec.rb b/spec/graphql/types/packages/helm/file_metadatum_type_spec.rb
new file mode 100644
index 00000000000..b7bcd6213b4
--- /dev/null
+++ b/spec/graphql/types/packages/helm/file_metadatum_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['HelmFileMetadata'] do
+ it { expect(described_class.graphql_name).to eq('HelmFileMetadata') }
+
+ it 'includes helm file metadatum fields' do
+ expected_fields = %w[
+ created_at updated_at channel metadata
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/packages/helm/maintainer_type_spec.rb b/spec/graphql/types/packages/helm/maintainer_type_spec.rb
new file mode 100644
index 00000000000..9ad51427d42
--- /dev/null
+++ b/spec/graphql/types/packages/helm/maintainer_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageHelmMaintainerType'] do
+ it { expect(described_class.graphql_name).to eq('PackageHelmMaintainerType') }
+
+ it 'includes helm maintainer fields' do
+ expected_fields = %w[
+ name email url
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/packages/helm/metadata_type_spec.rb b/spec/graphql/types/packages/helm/metadata_type_spec.rb
new file mode 100644
index 00000000000..04639450d9a
--- /dev/null
+++ b/spec/graphql/types/packages/helm/metadata_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageHelmMetadataType'] do
+ it { expect(described_class.graphql_name).to eq('PackageHelmMetadataType') }
+
+ it 'includes helm json fields' do
+ expected_fields = %w[
+ name home sources version description keywords maintainers icon apiVersion condition tags appVersion deprecated annotations kubeVersion dependencies type
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 45a718683be..4f205e861dd 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe GitlabSchema.types['Project'] do
container_repositories container_repositories_count
pipeline_analytics squash_read_only sast_ci_configuration
cluster_agent cluster_agents agent_configurations
- ci_template timelogs
+ ci_template timelogs merge_commit_template
]
expect(described_class).to include_graphql_fields(*expected_fields)
@@ -296,6 +296,8 @@ RSpec.describe GitlabSchema.types['Project'] do
:last,
:merged_after,
:merged_before,
+ :created_after,
+ :created_before,
:author_username,
:assignee_username,
:reviewer_username,
diff --git a/spec/graphql/types/projects/topic_type_spec.rb b/spec/graphql/types/projects/topic_type_spec.rb
new file mode 100644
index 00000000000..01c19e111be
--- /dev/null
+++ b/spec/graphql/types/projects/topic_type_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Projects::TopicType do
+ specify { expect(described_class.graphql_name).to eq('Topic') }
+
+ specify do
+ expect(described_class).to have_graphql_fields(
+ :id,
+ :name,
+ :description,
+ :description_html,
+ :avatar_url
+ )
+ end
+end
diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb
index 14ef03a64f9..49f0980bd08 100644
--- a/spec/graphql/types/query_type_spec.rb
+++ b/spec/graphql/types/query_type_spec.rb
@@ -28,6 +28,7 @@ RSpec.describe GitlabSchema.types['Query'] do
runners
timelogs
board_list
+ topics
]
expect(described_class).to have_graphql_fields(*expected_fields).at_least
diff --git a/spec/graphql/types/release_links_type_spec.rb b/spec/graphql/types/release_links_type_spec.rb
index 38c38d58baa..e77c4e3ddd1 100644
--- a/spec/graphql/types/release_links_type_spec.rb
+++ b/spec/graphql/types/release_links_type_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe GitlabSchema.types['ReleaseLinks'] do
- it { expect(described_class).to require_graphql_authorizations(:download_code) }
+ it { expect(described_class).to require_graphql_authorizations(:read_release) }
it 'has the expected fields' do
expected_fields = %w[
@@ -18,4 +18,46 @@ RSpec.describe GitlabSchema.types['ReleaseLinks'] do
expect(described_class).to include_graphql_fields(*expected_fields)
end
+
+ context 'individual field authorization' do
+ def fetch_authorizations(field_name)
+ described_class.fields.dig(field_name).instance_variable_get(:@authorize)
+ end
+
+ describe 'openedMergeRequestsUrl' do
+ it 'has valid authorization' do
+ expect(fetch_authorizations('openedMergeRequestsUrl')).to include(:download_code)
+ end
+ end
+
+ describe 'mergedMergeRequestsUrl' do
+ it 'has valid authorization' do
+ expect(fetch_authorizations('mergedMergeRequestsUrl')).to include(:download_code)
+ end
+ end
+
+ describe 'closedMergeRequestsUrl' do
+ it 'has valid authorization' do
+ expect(fetch_authorizations('closedMergeRequestsUrl')).to include(:download_code)
+ end
+ end
+
+ describe 'openedIssuesUrl' do
+ it 'has valid authorization' do
+ expect(fetch_authorizations('openedIssuesUrl')).to include(:download_code)
+ end
+ end
+
+ describe 'closedIssuesUrl' do
+ it 'has valid authorization' do
+ expect(fetch_authorizations('closedIssuesUrl')).to include(:download_code)
+ end
+ end
+
+ describe 'editUrl' do
+ it 'has valid authorization' do
+ expect(fetch_authorizations('editUrl')).to include(:update_release)
+ end
+ end
+ end
end
diff --git a/spec/graphql/types/repository/blob_type_spec.rb b/spec/graphql/types/repository/blob_type_spec.rb
index beab4dcebc2..7f37237f355 100644
--- a/spec/graphql/types/repository/blob_type_spec.rb
+++ b/spec/graphql/types/repository/blob_type_spec.rb
@@ -23,6 +23,7 @@ RSpec.describe Types::Repository::BlobType do
:stored_externally,
:raw_path,
:replace_path,
+ :pipeline_editor_path,
:simple_viewer,
:rich_viewer,
:plain_data,
diff --git a/spec/graphql/types/user_merge_request_interaction_type_spec.rb b/spec/graphql/types/user_merge_request_interaction_type_spec.rb
index f424c9200ab..1eaaa0c23d0 100644
--- a/spec/graphql/types/user_merge_request_interaction_type_spec.rb
+++ b/spec/graphql/types/user_merge_request_interaction_type_spec.rb
@@ -78,7 +78,7 @@ RSpec.describe GitlabSchema.types['UserMergeRequestInteraction'] do
merge_request.reviewers << user
end
- it { is_expected.to eq(Types::MergeRequestReviewStateEnum.values['UNREVIEWED'].value) }
+ it { is_expected.to eq(Types::MergeRequestReviewStateEnum.values['ATTENTION_REQUESTED'].value) }
it 'implies not reviewed' do
expect(resolve(:reviewed)).to be false
@@ -87,7 +87,8 @@ RSpec.describe GitlabSchema.types['UserMergeRequestInteraction'] do
context 'when the user has provided a review' do
before do
- merge_request.merge_request_reviewers.create!(reviewer: user, state: MergeRequestReviewer.states['reviewed'])
+ reviewer = merge_request.merge_request_reviewers.create!(reviewer: user)
+ reviewer.update!(state: MergeRequestReviewer.states['reviewed'])
end
it { is_expected.to eq(Types::MergeRequestReviewStateEnum.values['REVIEWED'].value) }
diff --git a/spec/helpers/admin/deploy_key_helper_spec.rb b/spec/helpers/admin/deploy_key_helper_spec.rb
new file mode 100644
index 00000000000..ca951ccf485
--- /dev/null
+++ b/spec/helpers/admin/deploy_key_helper_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Admin::DeployKeyHelper do
+ describe '#admin_deploy_keys_data' do
+ let_it_be(:edit_path) { '/admin/deploy_keys/:id/edit' }
+ let_it_be(:delete_path) { '/admin/deploy_keys/:id' }
+ let_it_be(:create_path) { '/admin/deploy_keys/new' }
+ let_it_be(:empty_state_svg_path) { '/assets/illustrations/empty-state/empty-deploy-keys-lg.svg' }
+
+ subject(:result) { helper.admin_deploy_keys_data }
+
+ it 'returns correct hash' do
+ expect(helper).to receive(:edit_admin_deploy_key_path).with(':id').and_return(edit_path)
+ expect(helper).to receive(:admin_deploy_key_path).with(':id').and_return(delete_path)
+ expect(helper).to receive(:new_admin_deploy_key_path).and_return(create_path)
+ expect(helper).to receive(:image_path).with('illustrations/empty-state/empty-deploy-keys-lg.svg').and_return(empty_state_svg_path)
+
+ expect(result).to eq({
+ edit_path: edit_path,
+ delete_path: delete_path,
+ create_path: create_path,
+ empty_state_svg_path: empty_state_svg_path
+ })
+ end
+ end
+end
diff --git a/spec/helpers/boards_helper_spec.rb b/spec/helpers/boards_helper_spec.rb
index cb4b6915b20..ec949fde30e 100644
--- a/spec/helpers/boards_helper_spec.rb
+++ b/spec/helpers/boards_helper_spec.rb
@@ -23,14 +23,14 @@ RSpec.describe BoardsHelper do
it 'returns correct path for base group' do
assign(:board, group_board)
- expect(helper.build_issue_link_base).to eq('/base/:project_path/issues')
+ expect(helper.build_issue_link_base).to eq('/:project_path/-/issues')
end
it 'returns correct path for subgroup' do
subgroup = create(:group, parent: base_group, path: 'sub')
assign(:board, create(:board, group: subgroup))
- expect(helper.build_issue_link_base).to eq('/base/sub/:project_path/issues')
+ expect(helper.build_issue_link_base).to eq('/:project_path/-/issues')
end
end
end
@@ -149,7 +149,7 @@ RSpec.describe BoardsHelper do
end
it 'returns correct path for base group' do
- expect(helper.build_issue_link_base).to eq("/#{base_group.full_path}/:project_path/issues")
+ expect(helper.build_issue_link_base).to eq("/:project_path/-/issues")
end
it 'returns required label endpoints' do
diff --git a/spec/helpers/ci/pipelines_helper_spec.rb b/spec/helpers/ci/pipelines_helper_spec.rb
index 94b5e707d73..751bcc97582 100644
--- a/spec/helpers/ci/pipelines_helper_spec.rb
+++ b/spec/helpers/ci/pipelines_helper_spec.rb
@@ -71,4 +71,26 @@ RSpec.describe Ci::PipelinesHelper do
it { expect(has_gitlab_ci?).to eq(result) }
end
end
+
+ describe 'has_pipeline_badges?' do
+ let(:pipeline) { create(:ci_empty_pipeline) }
+
+ subject { helper.has_pipeline_badges?(pipeline) }
+
+ context 'when pipeline has a badge' do
+ before do
+ pipeline.drop!(:config_error)
+ end
+
+ it 'shows pipeline badges' do
+ expect(subject).to eq(true)
+ end
+ end
+
+ context 'when pipeline has no badges' do
+ it 'shows pipeline badges' do
+ expect(subject).to eq(false)
+ end
+ end
+ end
end
diff --git a/spec/helpers/ci/runners_helper_spec.rb b/spec/helpers/ci/runners_helper_spec.rb
index 49ea2ac8d3b..173a0d3ab3c 100644
--- a/spec/helpers/ci/runners_helper_spec.rb
+++ b/spec/helpers/ci/runners_helper_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Ci::RunnersHelper do
- let_it_be(:user, refind: true) { create(:user) }
+ let_it_be(:user) { create(:user) }
before do
allow(helper).to receive(:current_user).and_return(user)
@@ -12,22 +12,22 @@ RSpec.describe Ci::RunnersHelper do
describe '#runner_status_icon', :clean_gitlab_redis_cache do
it "returns - not contacted yet" do
runner = create(:ci_runner)
- expect(runner_status_icon(runner)).to include("not connected yet")
+ expect(helper.runner_status_icon(runner)).to include("not connected yet")
end
it "returns offline text" do
runner = create(:ci_runner, contacted_at: 1.day.ago, active: true)
- expect(runner_status_icon(runner)).to include("Runner is offline")
+ expect(helper.runner_status_icon(runner)).to include("Runner is offline")
end
it "returns online text" do
runner = create(:ci_runner, contacted_at: 1.second.ago, active: true)
- expect(runner_status_icon(runner)).to include("Runner is online")
+ expect(helper.runner_status_icon(runner)).to include("Runner is online")
end
it "returns paused text" do
runner = create(:ci_runner, contacted_at: 1.second.ago, active: false)
- expect(runner_status_icon(runner)).to include("Runner is paused")
+ expect(helper.runner_status_icon(runner)).to include("Runner is paused")
end
end
@@ -42,7 +42,7 @@ RSpec.describe Ci::RunnersHelper do
context 'without sorting' do
it 'returns cached value' do
- expect(runner_contacted_at(runner)).to eq(contacted_at_cached)
+ expect(helper.runner_contacted_at(runner)).to eq(contacted_at_cached)
end
end
@@ -52,7 +52,7 @@ RSpec.describe Ci::RunnersHelper do
end
it 'returns cached value' do
- expect(runner_contacted_at(runner)).to eq(contacted_at_cached)
+ expect(helper.runner_contacted_at(runner)).to eq(contacted_at_cached)
end
end
@@ -62,29 +62,63 @@ RSpec.describe Ci::RunnersHelper do
end
it 'returns stored value' do
- expect(runner_contacted_at(runner)).to eq(contacted_at_stored)
+ expect(helper.runner_contacted_at(runner)).to eq(contacted_at_stored)
end
end
end
+ describe '#admin_runners_data_attributes' do
+ let_it_be(:admin) { create(:user, :admin) }
+ let_it_be(:instance_runner) { create(:ci_runner, :instance) }
+ let_it_be(:project_runner) { create(:ci_runner, :project ) }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(admin)
+ end
+
+ it 'returns the data in format' do
+ expect(helper.admin_runners_data_attributes).to eq({
+ runner_install_help_page: 'https://docs.gitlab.com/runner/install/',
+ registration_token: Gitlab::CurrentSettings.runners_registration_token,
+ active_runners_count: '0',
+ all_runners_count: '2',
+ instance_runners_count: '1',
+ group_runners_count: '0',
+ project_runners_count: '1'
+ })
+ end
+ end
+
describe '#group_shared_runners_settings_data' do
- let(:group) { create(:group, parent: parent, shared_runners_enabled: false) }
- let(:parent) { create(:group) }
+ let_it_be(:parent) { create(:group) }
+ let_it_be(:group) { create(:group, parent: parent, shared_runners_enabled: false) }
+
+ let(:runner_constants) do
+ {
+ runner_enabled: Namespace::SR_ENABLED,
+ runner_disabled: Namespace::SR_DISABLED_AND_UNOVERRIDABLE,
+ runner_allow_override: Namespace::SR_DISABLED_WITH_OVERRIDE
+ }
+ end
it 'returns group data for top level group' do
- data = group_shared_runners_settings_data(parent)
+ result = {
+ update_path: "/api/v4/groups/#{parent.id}",
+ shared_runners_availability: Namespace::SR_ENABLED,
+ parent_shared_runners_availability: nil
+ }.merge(runner_constants)
- expect(data[:update_path]).to eq("/api/v4/groups/#{parent.id}")
- expect(data[:shared_runners_availability]).to eq('enabled')
- expect(data[:parent_shared_runners_availability]).to eq(nil)
+ expect(helper.group_shared_runners_settings_data(parent)).to eq result
end
it 'returns group data for child group' do
- data = group_shared_runners_settings_data(group)
+ result = {
+ update_path: "/api/v4/groups/#{group.id}",
+ shared_runners_availability: Namespace::SR_DISABLED_AND_UNOVERRIDABLE,
+ parent_shared_runners_availability: Namespace::SR_ENABLED
+ }.merge(runner_constants)
- expect(data[:update_path]).to eq("/api/v4/groups/#{group.id}")
- expect(data[:shared_runners_availability]).to eq(Namespace::SR_DISABLED_AND_UNOVERRIDABLE)
- expect(data[:parent_shared_runners_availability]).to eq('enabled')
+ expect(helper.group_shared_runners_settings_data(group)).to eq result
end
end
@@ -92,7 +126,7 @@ RSpec.describe Ci::RunnersHelper do
let(:group) { create(:group) }
it 'returns group data to render a runner list' do
- data = group_runners_data_attributes(group)
+ data = helper.group_runners_data_attributes(group)
expect(data[:registration_token]).to eq(group.runners_token)
expect(data[:group_id]).to eq(group.id)
diff --git a/spec/helpers/clusters_helper_spec.rb b/spec/helpers/clusters_helper_spec.rb
index f1e19f17c72..51f111917d1 100644
--- a/spec/helpers/clusters_helper_spec.rb
+++ b/spec/helpers/clusters_helper_spec.rb
@@ -59,54 +59,96 @@ RSpec.describe ClustersHelper do
end
end
- describe '#js_cluster_agents_list_data' do
- let_it_be(:project) { build(:project, :repository) }
+ describe '#js_clusters_list_data' do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { build(:project) }
+ let_it_be(:clusterable) { ClusterablePresenter.fabricate(project, current_user: current_user) }
- subject { helper.js_cluster_agents_list_data(project) }
+ subject { helper.js_clusters_list_data(clusterable) }
- it 'displays project default branch' do
- expect(subject[:default_branch_name]).to eq(project.default_branch)
+ it 'displays endpoint path' do
+ expect(subject[:endpoint]).to eq("#{project_path(project)}/-/clusters.json")
end
- it 'displays image path' do
- expect(subject[:empty_state_image]).to match(%r(/illustrations/logos/clusters_empty|svg))
+ it 'generates svg image data', :aggregate_failures do
+ expect(subject.dig(:img_tags, :aws, :path)).to match(%r(/illustrations/logos/amazon_eks|svg))
+ expect(subject.dig(:img_tags, :default, :path)).to match(%r(/illustrations/logos/kubernetes|svg))
+ expect(subject.dig(:img_tags, :gcp, :path)).to match(%r(/illustrations/logos/google_gke|svg))
+
+ expect(subject.dig(:img_tags, :aws, :text)).to eq('Amazon EKS')
+ expect(subject.dig(:img_tags, :default, :text)).to eq('Kubernetes Cluster')
+ expect(subject.dig(:img_tags, :gcp, :text)).to eq('Google GKE')
end
- it 'displays project path' do
- expect(subject[:project_path]).to eq(project.full_path)
+ it 'displays and ancestor_help_path' do
+ expect(subject[:ancestor_help_path]).to eq(help_page_path('user/group/clusters/index', anchor: 'cluster-precedence'))
end
- it 'generates docs urls' do
- expect(subject[:agent_docs_url]).to eq(help_page_path('user/clusters/agent/index'))
- expect(subject[:install_docs_url]).to eq(help_page_path('administration/clusters/kas'))
- expect(subject[:get_started_docs_url]).to eq(help_page_path('user/clusters/agent/index', anchor: 'define-a-configuration-repository'))
- expect(subject[:integration_docs_url]).to eq(help_page_path('user/clusters/agent/index', anchor: 'get-started-with-gitops-and-the-gitlab-agent'))
+ it 'displays empty image path' do
+ expect(subject[:clusters_empty_state_image]).to match(%r(/illustrations/empty-state/empty-state-clusters|svg))
end
- it 'displays kas address' do
- expect(subject[:kas_address]).to eq(Gitlab::Kas.external_url)
+ it 'displays create cluster using certificate path' do
+ expect(subject[:new_cluster_path]).to eq("#{project_path(project)}/-/clusters/new?tab=create")
+ end
+
+ context 'user has no permissions to create a cluster' do
+ it 'displays that user can\t add cluster' do
+ expect(subject[:can_add_cluster]).to eq("false")
+ end
+ end
+
+ context 'user is a maintainer' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ it 'displays that the user can add cluster' do
+ expect(subject[:can_add_cluster]).to eq("true")
+ end
+ end
+
+ context 'project cluster' do
+ it 'doesn\'t display empty state help text' do
+ expect(subject[:empty_state_help_text]).to be_nil
+ end
+ end
+
+ context 'group cluster' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:clusterable) { ClusterablePresenter.fabricate(group, current_user: current_user) }
+
+ it 'displays empty state help text' do
+ expect(subject[:empty_state_help_text]).to eq(s_('ClusterIntegration|Adding an integration to your group will share the cluster across all your projects.'))
+ end
end
end
- describe '#js_clusters_list_data' do
- subject { helper.js_clusters_list_data('/path') }
+ describe '#js_clusters_data' do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { build(:project) }
+ let_it_be(:clusterable) { ClusterablePresenter.fabricate(project, current_user: current_user) }
- it 'displays endpoint path' do
- expect(subject[:endpoint]).to eq('/path')
+ subject { helper.js_clusters_data(clusterable) }
+
+ it 'displays project default branch' do
+ expect(subject[:default_branch_name]).to eq(project.default_branch)
end
- it 'generates svg image data', :aggregate_failures do
- expect(subject.dig(:img_tags, :aws, :path)).to match(%r(/illustrations/logos/amazon_eks|svg))
- expect(subject.dig(:img_tags, :default, :path)).to match(%r(/illustrations/logos/kubernetes|svg))
- expect(subject.dig(:img_tags, :gcp, :path)).to match(%r(/illustrations/logos/google_gke|svg))
+ it 'displays image path' do
+ expect(subject[:empty_state_image]).to match(%r(/illustrations/empty-state/empty-state-agents|svg))
+ end
- expect(subject.dig(:img_tags, :aws, :text)).to eq('Amazon EKS')
- expect(subject.dig(:img_tags, :default, :text)).to eq('Kubernetes Cluster')
- expect(subject.dig(:img_tags, :gcp, :text)).to eq('Google GKE')
+ it 'displays project path' do
+ expect(subject[:project_path]).to eq(project.full_path)
end
- it 'displays and ancestor_help_path' do
- expect(subject[:ancestor_help_path]).to eq(help_page_path('user/group/clusters/index', anchor: 'cluster-precedence'))
+ it 'displays add cluster using certificate path' do
+ expect(subject[:add_cluster_path]).to eq("#{project_path(project)}/-/clusters/new?tab=add")
+ end
+
+ it 'displays kas address' do
+ expect(subject[:kas_address]).to eq(Gitlab::Kas.external_url)
end
end
@@ -152,4 +194,24 @@ RSpec.describe ClustersHelper do
end
end
end
+
+ describe '#display_cluster_agents?' do
+ subject { helper.display_cluster_agents?(clusterable) }
+
+ context 'when clusterable is a project' do
+ let(:clusterable) { build(:project) }
+
+ it 'allows agents to display' do
+ expect(subject).to be_truthy
+ end
+ end
+
+ context 'when clusterable is a group' do
+ let(:clusterable) { build(:group) }
+
+ it 'does not allow agents to display' do
+ expect(subject).to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/helpers/emoji_helper_spec.rb b/spec/helpers/emoji_helper_spec.rb
index 15e4ce03960..6f4c962c0fb 100644
--- a/spec/helpers/emoji_helper_spec.rb
+++ b/spec/helpers/emoji_helper_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe EmojiHelper do
describe '#emoji_icon' do
let(:options) { {} }
let(:emoji_text) { 'rocket' }
+ let(:unicode_version) { '6.0' }
let(:aria_hidden_option) { "aria-hidden=\"true\"" }
subject { helper.emoji_icon(emoji_text, options) }
@@ -14,7 +15,7 @@ RSpec.describe EmojiHelper do
is_expected.to include('<gl-emoji',
"title=\"#{emoji_text}\"",
"data-name=\"#{emoji_text}\"",
- "data-unicode-version=\"#{::Gitlab::Emoji.emoji_unicode_version(emoji_text)}\"")
+ "data-unicode-version=\"#{unicode_version}\"")
is_expected.not_to include(aria_hidden_option)
end
@@ -25,7 +26,7 @@ RSpec.describe EmojiHelper do
is_expected.to include('<gl-emoji',
"title=\"#{emoji_text}\"",
"data-name=\"#{emoji_text}\"",
- "data-unicode-version=\"#{::Gitlab::Emoji.emoji_unicode_version(emoji_text)}\"",
+ "data-unicode-version=\"#{unicode_version}\"",
aria_hidden_option)
end
end
diff --git a/spec/helpers/environments_helper_spec.rb b/spec/helpers/environments_helper_spec.rb
index 60bed247d85..aef240db5b8 100644
--- a/spec/helpers/environments_helper_spec.rb
+++ b/spec/helpers/environments_helper_spec.rb
@@ -40,12 +40,10 @@ RSpec.describe EnvironmentsHelper do
'validate_query_path' => validate_query_project_prometheus_metrics_path(project),
'custom_metrics_available' => 'true',
'alerts_endpoint' => project_prometheus_alerts_path(project, environment_id: environment.id, format: :json),
- 'prometheus_alerts_available' => 'true',
'custom_dashboard_base_path' => Gitlab::Metrics::Dashboard::RepoDashboardFinder::DASHBOARD_ROOT,
'operations_settings_path' => project_settings_operations_path(project),
'can_access_operations_settings' => 'true',
- 'panel_preview_endpoint' => project_metrics_dashboards_builder_path(project, format: :json),
- 'has_managed_prometheus' => 'false'
+ 'panel_preview_endpoint' => project_metrics_dashboards_builder_path(project, format: :json)
)
end
@@ -63,20 +61,6 @@ RSpec.describe EnvironmentsHelper do
end
end
- context 'without read_prometheus_alerts permission' do
- before do
- allow(helper).to receive(:can?)
- .with(user, :read_prometheus_alerts, project)
- .and_return(false)
- end
-
- it 'returns false' do
- expect(metrics_data).to include(
- 'prometheus_alerts_available' => 'false'
- )
- end
- end
-
context 'with metrics_setting' do
before do
create(:project_metrics_setting, project: project, external_dashboard_url: 'http://gitlab.com')
@@ -120,52 +104,6 @@ RSpec.describe EnvironmentsHelper do
end
end
end
-
- context 'has_managed_prometheus' do
- context 'without prometheus integration' do
- it "doesn't have managed prometheus" do
- expect(metrics_data).to include(
- 'has_managed_prometheus' => 'false'
- )
- end
- end
-
- context 'with prometheus integration' do
- let_it_be(:prometheus_integration) { create(:prometheus_integration, project: project) }
-
- context 'when manual prometheus integration is active' do
- it "doesn't have managed prometheus" do
- prometheus_integration.update!(manual_configuration: true)
-
- expect(metrics_data).to include(
- 'has_managed_prometheus' => 'false'
- )
- end
- end
-
- context 'when prometheus integration is inactive' do
- it "doesn't have managed prometheus" do
- prometheus_integration.update!(manual_configuration: false)
-
- expect(metrics_data).to include(
- 'has_managed_prometheus' => 'false'
- )
- end
- end
-
- context 'when a cluster prometheus is available' do
- let(:cluster) { create(:cluster, projects: [project]) }
-
- it 'has managed prometheus' do
- create(:clusters_integrations_prometheus, cluster: cluster)
-
- expect(metrics_data).to include(
- 'has_managed_prometheus' => 'true'
- )
- end
- end
- end
- end
end
describe '#custom_metrics_available?' do
diff --git a/spec/helpers/graph_helper_spec.rb b/spec/helpers/graph_helper_spec.rb
index 0930417accb..a5d4e1313e1 100644
--- a/spec/helpers/graph_helper_spec.rb
+++ b/spec/helpers/graph_helper_spec.rb
@@ -27,4 +27,16 @@ RSpec.describe GraphHelper do
expect(should_render_dora_charts).to be(false)
end
end
+
+ describe '#should_render_quality_summary' do
+ let(:project) { create(:project, :private) }
+
+ before do
+ self.instance_variable_set(:@project, project)
+ end
+
+ it 'always returns false' do
+ expect(should_render_quality_summary).to be(false)
+ end
+ end
end
diff --git a/spec/helpers/groups/settings_helper_spec.rb b/spec/helpers/groups/settings_helper_spec.rb
new file mode 100644
index 00000000000..f8c0bfc19a1
--- /dev/null
+++ b/spec/helpers/groups/settings_helper_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::SettingsHelper do
+ include GroupsHelper
+
+ let_it_be(:group) { create(:group, path: "foo") }
+
+ describe('#group_settings_confirm_modal_data') do
+ using RSpec::Parameterized::TableSyntax
+
+ fake_form_id = "fake_form_id"
+
+ where(:is_paid, :is_button_disabled, :form_value_id) do
+ true | "true" | nil
+ true | "true" | fake_form_id
+ false | "false" | nil
+ false | "false" | fake_form_id
+ end
+
+ with_them do
+ it "returns expected parameters" do
+ allow(group).to receive(:paid?).and_return(is_paid)
+
+ expected = helper.group_settings_confirm_modal_data(group, form_value_id)
+ expect(expected).to eq({
+ button_text: "Remove group",
+ confirm_danger_message: remove_group_message(group),
+ remove_form_id: form_value_id,
+ phrase: group.full_path,
+ button_testid: "remove-group-button",
+ disabled: is_button_disabled
+ })
+ end
+ end
+ end
+end
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index 4d647696130..8859ed27022 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -92,7 +92,7 @@ RSpec.describe GroupsHelper do
shared_examples 'correct ancestor order' do
it 'outputs the groups in the correct order' do
expect(subject)
- .to match(%r{<li style="text-indent: 16px;"><a.*>#{deep_nested_group.name}.*</li>.*<a.*>#{very_deep_nested_group.name}</a>}m)
+ .to match(%r{<li><a.*>#{deep_nested_group.name}.*</li>.*<a.*>#{very_deep_nested_group.name}</a>}m)
end
end
diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb
index e0e05140d6c..02f0416a17a 100644
--- a/spec/helpers/invite_members_helper_spec.rb
+++ b/spec/helpers/invite_members_helper_spec.rb
@@ -59,7 +59,84 @@ RSpec.describe InviteMembersHelper do
no_selection_areas_of_focus: []
}
- expect(helper.common_invite_modal_dataset(project)).to match(attributes)
+ expect(helper.common_invite_modal_dataset(project)).to include(attributes)
+ end
+ end
+
+ context 'tasks_to_be_done' do
+ subject(:output) { helper.common_invite_modal_dataset(source) }
+
+ let_it_be(:source) { project }
+
+ before do
+ stub_experiments(invite_members_for_task: true)
+ end
+
+ context 'when not logged in' do
+ before do
+ allow(helper).to receive(:params).and_return({ open_modal: 'invite_members_for_task' })
+ end
+
+ it "doesn't have the tasks to be done attributes" do
+ expect(output[:tasks_to_be_done_options]).to be_nil
+ expect(output[:projects]).to be_nil
+ expect(output[:new_project_path]).to be_nil
+ end
+ end
+
+ context 'when logged in but the open_modal param is not present' do
+ before do
+ allow(helper).to receive(:current_user).and_return(developer)
+ end
+
+ it "doesn't have the tasks to be done attributes" do
+ expect(output[:tasks_to_be_done_options]).to be_nil
+ expect(output[:projects]).to be_nil
+ expect(output[:new_project_path]).to be_nil
+ end
+ end
+
+ context 'when logged in and the open_modal param is present' do
+ before do
+ allow(helper).to receive(:current_user).and_return(developer)
+ allow(helper).to receive(:params).and_return({ open_modal: 'invite_members_for_task' })
+ end
+
+ context 'for a group' do
+ let_it_be(:source) { create(:group, projects: [project]) }
+
+ it 'has the expected attributes', :aggregate_failures do
+ expect(output[:tasks_to_be_done_options]).to eq(
+ [
+ { value: :code, text: 'Create/import code into a project (repository)' },
+ { value: :ci, text: 'Set up CI/CD pipelines to build, test, deploy, and monitor code' },
+ { value: :issues, text: 'Create/import issues (tickets) to collaborate on ideas and plan work' }
+ ].to_json
+ )
+ expect(output[:projects]).to eq(
+ [{ id: project.id, title: project.title }].to_json
+ )
+ expect(output[:new_project_path]).to eq(
+ new_project_path(namespace_id: source.id)
+ )
+ end
+ end
+
+ context 'for a project' do
+ it 'has the expected attributes', :aggregate_failures do
+ expect(output[:tasks_to_be_done_options]).to eq(
+ [
+ { value: :code, text: 'Create/import code into a project (repository)' },
+ { value: :ci, text: 'Set up CI/CD pipelines to build, test, deploy, and monitor code' },
+ { value: :issues, text: 'Create/import issues (tickets) to collaborate on ideas and plan work' }
+ ].to_json
+ )
+ expect(output[:projects]).to eq(
+ [{ id: project.id, title: project.title }].to_json
+ )
+ expect(output[:new_project_path]).to eq('')
+ end
+ end
end
end
end
diff --git a/spec/helpers/issuables_description_templates_helper_spec.rb b/spec/helpers/issuables_description_templates_helper_spec.rb
index 55649e9087a..6b05bab7432 100644
--- a/spec/helpers/issuables_description_templates_helper_spec.rb
+++ b/spec/helpers/issuables_description_templates_helper_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
end
end
- describe '#issuable_templates_names' do
+ describe '#selected_template' do
let_it_be(:project) { build(:project) }
before do
@@ -63,7 +63,14 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
end
it 'returns project templates' do
- expect(helper.issuable_templates_names(Issue.new)).to eq(%w[another_issue_template custom_issue_template])
+ value = [
+ "",
+ [
+ { name: "another_issue_template", id: "another_issue_template", project_id: project.id },
+ { name: "custom_issue_template", id: "custom_issue_template", project_id: project.id }
+ ]
+ ].to_json
+ expect(helper.available_service_desk_templates_for(@project)).to eq(value)
end
end
@@ -71,7 +78,8 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
let(:templates) { {} }
it 'returns empty array' do
- expect(helper.issuable_templates_names(Issue.new)).to eq([])
+ value = [].to_json
+ expect(helper.available_service_desk_templates_for(@project)).to eq(value)
end
end
end
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index 30049745433..fa19395ebc7 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -169,26 +169,9 @@ RSpec.describe IssuablesHelper do
stub_const("Gitlab::IssuablesCountForState::THRESHOLD", 1000)
end
- context 'when feature flag cached_issues_state_count is disabled' do
- before do
- stub_feature_flags(cached_issues_state_count: false)
- end
-
- it 'returns complete count' do
- expect(helper.issuables_state_counter_text(:issues, :opened, true))
- .to eq('<span>Open</span> <span class="badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex">1,100</span>')
- end
- end
-
- context 'when feature flag cached_issues_state_count is enabled' do
- before do
- stub_feature_flags(cached_issues_state_count: true)
- end
-
- it 'returns truncated count' do
- expect(helper.issuables_state_counter_text(:issues, :opened, true))
- .to eq('<span>Open</span> <span class="badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex">1.1k</span>')
- end
+ it 'returns truncated count' do
+ expect(helper.issuables_state_counter_text(:issues, :opened, true))
+ .to eq('<span>Open</span> <span class="badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex">1.1k</span>')
end
end
end
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index 850051c7875..43b27dded3b 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -326,6 +326,7 @@ RSpec.describe IssuesHelper do
new_issue_path: new_project_issue_path(project, issue: { milestone_id: finder.milestones.first.id }),
project_import_jira_path: project_import_jira_path(project),
quick_actions_help_path: help_page_path('user/project/quick_actions'),
+ releases_path: project_releases_path(project, format: :json),
reset_path: new_issuable_address_project_path(project, issuable_type: 'issue'),
rss_path: '#',
show_new_issue_link: 'true',
diff --git a/spec/helpers/learn_gitlab_helper_spec.rb b/spec/helpers/learn_gitlab_helper_spec.rb
index 1159fd96d59..b9f34853a77 100644
--- a/spec/helpers/learn_gitlab_helper_spec.rb
+++ b/spec/helpers/learn_gitlab_helper_spec.rb
@@ -11,9 +11,6 @@ RSpec.describe LearnGitlabHelper do
let_it_be(:namespace) { project.namespace }
before do
- project.add_developer(user)
-
- allow(helper).to receive(:user).and_return(user)
allow_next_instance_of(LearnGitlab::Project) do |learn_gitlab|
allow(learn_gitlab).to receive(:project).and_return(project)
end
@@ -22,38 +19,7 @@ RSpec.describe LearnGitlabHelper do
OnboardingProgress.register(namespace, :git_write)
end
- describe '.onboarding_actions_data' do
- subject(:onboarding_actions_data) { helper.onboarding_actions_data(project) }
-
- it 'has all actions' do
- expect(onboarding_actions_data.keys).to contain_exactly(
- :issue_created,
- :git_write,
- :pipeline_created,
- :merge_request_created,
- :user_added,
- :trial_started,
- :required_mr_approvals_enabled,
- :code_owners_enabled,
- :security_scan_enabled
- )
- end
-
- it 'sets correct path and completion status' do
- expect(onboarding_actions_data[:git_write]).to eq({
- url: project_issue_url(project, LearnGitlab::Onboarding::ACTION_ISSUE_IDS[:git_write]),
- completed: true,
- svg: helper.image_path("learn_gitlab/git_write.svg")
- })
- expect(onboarding_actions_data[:pipeline_created]).to eq({
- url: project_issue_url(project, LearnGitlab::Onboarding::ACTION_ISSUE_IDS[:pipeline_created]),
- completed: false,
- svg: helper.image_path("learn_gitlab/pipeline_created.svg")
- })
- end
- end
-
- describe '.learn_gitlab_enabled?' do
+ describe '#learn_gitlab_enabled?' do
using RSpec::Parameterized::TableSyntax
let_it_be(:user) { create(:user) }
@@ -89,14 +55,121 @@ RSpec.describe LearnGitlabHelper do
end
end
- describe '.onboarding_sections_data' do
- subject(:sections) { helper.onboarding_sections_data }
+ describe '#learn_gitlab_data' do
+ subject(:learn_gitlab_data) { helper.learn_gitlab_data(project) }
+
+ let(:onboarding_actions_data) { Gitlab::Json.parse(learn_gitlab_data[:actions]).deep_symbolize_keys }
+ let(:onboarding_sections_data) { Gitlab::Json.parse(learn_gitlab_data[:sections]).deep_symbolize_keys }
+
+ shared_examples 'has all data' do
+ it 'has all actions' do
+ expected_keys = [
+ :issue_created,
+ :git_write,
+ :pipeline_created,
+ :merge_request_created,
+ :user_added,
+ :trial_started,
+ :required_mr_approvals_enabled,
+ :code_owners_enabled,
+ :security_scan_enabled
+ ]
+
+ expect(onboarding_actions_data.keys).to contain_exactly(*expected_keys)
+ end
- it 'has the right keys' do
- expect(sections.keys).to contain_exactly(:deploy, :plan, :workspace)
+ it 'has all section data', :aggregate_failures do
+ expect(onboarding_sections_data.keys).to contain_exactly(:deploy, :plan, :workspace)
+ expect(onboarding_sections_data.values.map { |section| section.keys }).to match_array([[:svg]] * 3)
+ end
end
- it 'has the svg' do
- expect(sections.values.map { |section| section.keys }).to eq([[:svg]] * 3)
+
+ it_behaves_like 'has all data'
+
+ it 'sets correct paths' do
+ expect(onboarding_actions_data).to match({
+ trial_started: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/issues/2\z})
+ ),
+ issue_created: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/issues/4\z})
+ ),
+ git_write: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/issues/6\z})
+ ),
+ pipeline_created: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/issues/7\z})
+ ),
+ user_added: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/issues/8\z})
+ ),
+ merge_request_created: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/issues/9\z})
+ ),
+ code_owners_enabled: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/issues/10\z})
+ ),
+ required_mr_approvals_enabled: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/issues/11\z})
+ ),
+ security_scan_enabled: a_hash_including(
+ url: a_string_matching(%r{docs\.gitlab\.com/ee/user/application_security/security_dashboard/#gitlab-security-dashboard-security-center-and-vulnerability-reports\z})
+ )
+ })
+ end
+
+ it 'sets correct completion statuses' do
+ expect(onboarding_actions_data).to match({
+ issue_created: a_hash_including(completed: false),
+ git_write: a_hash_including(completed: true),
+ pipeline_created: a_hash_including(completed: false),
+ merge_request_created: a_hash_including(completed: false),
+ user_added: a_hash_including(completed: false),
+ trial_started: a_hash_including(completed: false),
+ required_mr_approvals_enabled: a_hash_including(completed: false),
+ code_owners_enabled: a_hash_including(completed: false),
+ security_scan_enabled: a_hash_including(completed: false)
+ })
+ end
+
+ context 'when in the new action URLs experiment' do
+ before do
+ stub_experiments(change_continuous_onboarding_link_urls: :candidate)
+ end
+
+ it_behaves_like 'has all data'
+
+ it 'sets mostly new paths' do
+ expect(onboarding_actions_data).to match({
+ trial_started: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/issues/2\z})
+ ),
+ issue_created: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/issues\z})
+ ),
+ git_write: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab\z})
+ ),
+ pipeline_created: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/pipelines\z})
+ ),
+ user_added: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/project_members\z})
+ ),
+ merge_request_created: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/merge_requests\z})
+ ),
+ code_owners_enabled: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/issues/10\z})
+ ),
+ required_mr_approvals_enabled: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/issues/11\z})
+ ),
+ security_scan_enabled: a_hash_including(
+ url: a_string_matching(%r{/learn_gitlab/-/security/configuration\z})
+ )
+ })
+ end
end
end
end
diff --git a/spec/helpers/members_helper_spec.rb b/spec/helpers/members_helper_spec.rb
index c671379c4b4..e94eb63fc2c 100644
--- a/spec/helpers/members_helper_spec.rb
+++ b/spec/helpers/members_helper_spec.rb
@@ -68,4 +68,10 @@ RSpec.describe MembersHelper do
it { expect(leave_confirmation_message(project)).to eq "Are you sure you want to leave the \"#{project.full_name}\" project?" }
it { expect(leave_confirmation_message(group)).to eq "Are you sure you want to leave the \"#{group.name}\" group?" }
end
+
+ describe '#localized_tasks_to_be_done_choices' do
+ it 'has a translation for all `TASKS_TO_BE_DONE` keys' do
+ expect(localized_tasks_to_be_done_choices).to include(*MemberTask::TASKS.keys)
+ end
+ end
end
diff --git a/spec/helpers/nav/top_nav_helper_spec.rb b/spec/helpers/nav/top_nav_helper_spec.rb
index da7e5d5dce2..10bd45e3189 100644
--- a/spec/helpers/nav/top_nav_helper_spec.rb
+++ b/spec/helpers/nav/top_nav_helper_spec.rb
@@ -188,6 +188,11 @@ RSpec.describe Nav::TopNavHelper do
href: '/explore',
id: 'explore',
title: 'Explore projects'
+ ),
+ ::Gitlab::Nav::TopNavMenuItem.build(
+ href: '/explore/projects/topics',
+ id: 'topics',
+ title: 'Explore topics'
)
]
expect(projects_view[:linksPrimary]).to eq(expected_links_primary)
diff --git a/spec/helpers/notes_helper_spec.rb b/spec/helpers/notes_helper_spec.rb
index fc62bbf8bf8..913a38d353f 100644
--- a/spec/helpers/notes_helper_spec.rb
+++ b/spec/helpers/notes_helper_spec.rb
@@ -322,11 +322,21 @@ RSpec.describe NotesHelper do
describe '#notes_data' do
let(:issue) { create(:issue, project: project) }
- it 'sets last_fetched_at to 0 when start_at_zero is true' do
+ before do
@project = project
@noteable = issue
+ allow(helper).to receive(:current_user).and_return(guest)
+ end
+
+ it 'sets last_fetched_at to 0 when start_at_zero is true' do
expect(helper.notes_data(issue, true)[:lastFetchedAt]).to eq(0)
end
+
+ it 'includes the current notes filter for the user' do
+ guest.set_notes_filter(UserPreference::NOTES_FILTERS[:only_comments], issue)
+
+ expect(helper.notes_data(issue)[:notesFilter]).to eq(UserPreference::NOTES_FILTERS[:only_comments])
+ end
end
end
diff --git a/spec/helpers/one_trust_helper_spec.rb b/spec/helpers/one_trust_helper_spec.rb
index 85c38885304..20b731ac73d 100644
--- a/spec/helpers/one_trust_helper_spec.rb
+++ b/spec/helpers/one_trust_helper_spec.rb
@@ -4,11 +4,8 @@ require "spec_helper"
RSpec.describe OneTrustHelper do
describe '#one_trust_enabled?' do
- let(:user) { nil }
-
before do
stub_config(extra: { one_trust_id: SecureRandom.uuid })
- allow(helper).to receive(:current_user).and_return(user)
end
subject(:one_trust_enabled?) { helper.one_trust_enabled? }
@@ -18,20 +15,10 @@ RSpec.describe OneTrustHelper do
stub_feature_flags(ecomm_instrumentation: false)
end
- context 'when id is set and no user is set' do
- let(:user) { instance_double('User') }
-
- it { is_expected.to be_falsey }
- end
+ it { is_expected.to be_falsey }
end
context 'with ecomm_instrumentation feature flag enabled' do
- context 'when current user is set' do
- let(:user) { instance_double('User') }
-
- it { is_expected.to be_falsey }
- end
-
context 'when no id is set' do
before do
stub_config(extra: {})
@@ -39,10 +26,6 @@ RSpec.describe OneTrustHelper do
it { is_expected.to be_falsey }
end
-
- context 'when id is set and no user is set' do
- it { is_expected.to be_truthy }
- end
end
end
end
diff --git a/spec/helpers/projects/alert_management_helper_spec.rb b/spec/helpers/projects/alert_management_helper_spec.rb
index 2450f7838b3..0a5c4bedaa6 100644
--- a/spec/helpers/projects/alert_management_helper_spec.rb
+++ b/spec/helpers/projects/alert_management_helper_spec.rb
@@ -34,7 +34,6 @@ RSpec.describe Projects::AlertManagementHelper do
'empty-alert-svg-path' => match_asset_path('/assets/illustrations/alert-management-empty-state.svg'),
'user-can-enable-alert-management' => 'true',
'alert-management-enabled' => 'false',
- 'has-managed-prometheus' => 'false',
'text-query': nil,
'assignee-username-query': nil
)
@@ -45,52 +44,26 @@ RSpec.describe Projects::AlertManagementHelper do
let_it_be(:prometheus_integration) { create(:prometheus_integration, project: project) }
context 'when manual prometheus integration is active' do
- it "enables alert management and doesn't show managed prometheus" do
+ it "enables alert management" do
prometheus_integration.update!(manual_configuration: true)
expect(data).to include(
'alert-management-enabled' => 'true'
)
- expect(data).to include(
- 'has-managed-prometheus' => 'false'
- )
- end
- end
-
- context 'when a cluster prometheus is available' do
- let(:cluster) { create(:cluster, projects: [project]) }
-
- it 'has managed prometheus' do
- create(:clusters_integrations_prometheus, cluster: cluster)
-
- expect(data).to include(
- 'has-managed-prometheus' => 'true'
- )
end
end
- context 'when prometheus integration is inactive' do
- it 'disables alert management and hides managed prometheus' do
+ context 'when prometheus service is inactive' do
+ it 'disables alert management' do
prometheus_integration.update!(manual_configuration: false)
expect(data).to include(
'alert-management-enabled' => 'false'
)
- expect(data).to include(
- 'has-managed-prometheus' => 'false'
- )
end
end
end
- context 'without prometheus integration' do
- it "doesn't have managed prometheus" do
- expect(data).to include(
- 'has-managed-prometheus' => 'false'
- )
- end
- end
-
context 'with http integration' do
let_it_be(:integration) { create(:alert_management_http_integration, project: project) }
diff --git a/spec/helpers/projects/incidents_helper_spec.rb b/spec/helpers/projects/incidents_helper_spec.rb
index 7a8a6d5222f..d0dc18d56b0 100644
--- a/spec/helpers/projects/incidents_helper_spec.rb
+++ b/spec/helpers/projects/incidents_helper_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe Projects::IncidentsHelper do
include Gitlab::Routing.url_helpers
- let(:project) { create(:project) }
+ let(:user) { build_stubbed(:user) }
+ let(:project) { build_stubbed(:project) }
let(:project_path) { project.full_path }
let(:new_issue_path) { new_project_issue_path(project) }
let(:issue_path) { project_issues_path(project) }
@@ -17,21 +18,43 @@ RSpec.describe Projects::IncidentsHelper do
}
end
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ allow(helper).to receive(:can?)
+ .with(user, :create_incident, project)
+ .and_return(can_create_incident)
+ end
+
describe '#incidents_data' do
subject(:data) { helper.incidents_data(project, params) }
- it 'returns frontend configuration' do
- expect(data).to include(
- 'project-path' => project_path,
- 'new-issue-path' => new_issue_path,
- 'incident-template-name' => 'incident',
- 'incident-type' => 'incident',
- 'issue-path' => issue_path,
- 'empty-list-svg-path' => match_asset_path('/assets/illustrations/incident-empty-state.svg'),
- 'text-query': 'search text',
- 'author-username-query': 'root',
- 'assignee-username-query': 'max.power'
- )
+ shared_examples 'frontend configuration' do
+ it 'returns frontend configuration' do
+ expect(data).to include(
+ 'project-path' => project_path,
+ 'new-issue-path' => new_issue_path,
+ 'incident-template-name' => 'incident',
+ 'incident-type' => 'incident',
+ 'issue-path' => issue_path,
+ 'empty-list-svg-path' => match_asset_path('/assets/illustrations/incident-empty-state.svg'),
+ 'text-query': 'search text',
+ 'author-username-query': 'root',
+ 'assignee-username-query': 'max.power',
+ 'can-create-incident': can_create_incident.to_s
+ )
+ end
+ end
+
+ context 'when user can create incidents' do
+ let(:can_create_incident) { true }
+
+ include_examples 'frontend configuration'
+ end
+
+ context 'when user cannot create incidents' do
+ let(:can_create_incident) { false }
+
+ include_examples 'frontend configuration'
end
end
end
diff --git a/spec/helpers/projects/security/configuration_helper_spec.rb b/spec/helpers/projects/security/configuration_helper_spec.rb
index c5049bd87f0..4c30ba87897 100644
--- a/spec/helpers/projects/security/configuration_helper_spec.rb
+++ b/spec/helpers/projects/security/configuration_helper_spec.rb
@@ -8,6 +8,6 @@ RSpec.describe Projects::Security::ConfigurationHelper do
describe 'security_upgrade_path' do
subject { security_upgrade_path }
- it { is_expected.to eq('https://about.gitlab.com/pricing/') }
+ it { is_expected.to eq("https://#{ApplicationHelper.promo_host}/pricing/") }
end
end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 5d52c9178cb..5d2af567549 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -268,7 +268,7 @@ RSpec.describe ProjectsHelper do
end
end
- describe '#link_to_set_password' do
+ describe '#no_password_message' do
let(:user) { create(:user, password_automatically_set: true) }
before do
@@ -276,18 +276,18 @@ RSpec.describe ProjectsHelper do
end
context 'password authentication is enabled for Git' do
- it 'returns link to set a password' do
+ it 'returns message prompting user to set password or set up a PAT' do
stub_application_setting(password_authentication_enabled_for_git?: true)
- expect(helper.link_to_set_password).to match %r{<a href="#{edit_profile_password_path}">set a password</a>}
+ expect(helper.no_password_message).to eq('Your account is authenticated with SSO or SAML. To <a href="/help/gitlab-basics/start-using-git#pull-and-push" target="_blank" rel="noopener noreferrer">push and pull</a> over HTTP with Git using this account, you must <a href="/-/profile/password/edit">set a password</a> or <a href="/-/profile/personal_access_tokens">set up a Personal Access Token</a> to use instead of a password. For more information, see <a href="/help/gitlab-basics/start-using-git#clone-with-https" target="_blank" rel="noopener noreferrer">Clone with HTTPS</a>.')
end
end
context 'password authentication is disabled for Git' do
- it 'returns link to create a personal access token' do
+ it 'returns message prompting user to set up a PAT' do
stub_application_setting(password_authentication_enabled_for_git?: false)
- expect(helper.link_to_set_password).to match %r{<a href="#{profile_personal_access_tokens_path}">create a personal access token</a>}
+ expect(helper.no_password_message).to eq('Your account is authenticated with SSO or SAML. To <a href="/help/gitlab-basics/start-using-git#pull-and-push" target="_blank" rel="noopener noreferrer">push and pull</a> over HTTP with Git using this account, you must <a href="/-/profile/personal_access_tokens">set up a Personal Access Token</a> to use instead of a password. For more information, see <a href="/help/gitlab-basics/start-using-git#clone-with-https" target="_blank" rel="noopener noreferrer">Clone with HTTPS</a>.')
end
end
end
@@ -983,4 +983,12 @@ RSpec.describe ProjectsHelper do
it { is_expected.not_to include('project-highlight-puc') }
end
end
+
+ describe "#delete_confirm_phrase" do
+ subject { helper.delete_confirm_phrase(project) }
+
+ it 'includes the project path with namespace' do
+ expect(subject).to eq(project.path_with_namespace)
+ end
+ end
end
diff --git a/spec/helpers/routing/pseudonymization_helper_spec.rb b/spec/helpers/routing/pseudonymization_helper_spec.rb
index a28a86d1f53..82ed893289d 100644
--- a/spec/helpers/routing/pseudonymization_helper_spec.rb
+++ b/spec/helpers/routing/pseudonymization_helper_spec.rb
@@ -25,95 +25,196 @@ RSpec.describe ::Routing::PseudonymizationHelper do
describe 'when url has params to mask' do
context 'with controller for MR' do
- let(:masked_url) { "http://test.host/namespace:#{group.id}/project:#{project.id}/-/merge_requests/#{merge_request.id}" }
+ let(:masked_url) { "http://localhost/namespace#{group.id}/project#{project.id}/-/merge_requests/#{merge_request.id}" }
+ let(:request) do
+ double(:Request,
+ path_parameters: {
+ controller: "projects/merge_requests",
+ action: "show",
+ namespace_id: group.name,
+ project_id: project.name,
+ id: merge_request.id.to_s
+ },
+ protocol: 'http',
+ host: 'localhost',
+ query_string: '')
+ end
before do
- allow(Rails.application.routes).to receive(:recognize_path).and_return({
- controller: "projects/merge_requests",
- action: "show",
- namespace_id: group.name,
- project_id: project.name,
- id: merge_request.id.to_s
- })
+ allow(helper).to receive(:request).and_return(request)
end
it_behaves_like 'masked url'
end
context 'with controller for issue' do
- let(:masked_url) { "http://test.host/namespace:#{group.id}/project:#{project.id}/-/issues/#{issue.id}" }
+ let(:masked_url) { "http://localhost/namespace#{group.id}/project#{project.id}/-/issues/#{issue.id}" }
+ let(:request) do
+ double(:Request,
+ path_parameters: {
+ controller: "projects/issues",
+ action: "show",
+ namespace_id: group.name,
+ project_id: project.name,
+ id: issue.id.to_s
+ },
+ protocol: 'http',
+ host: 'localhost',
+ query_string: '')
+ end
before do
- allow(Rails.application.routes).to receive(:recognize_path).and_return({
- controller: "projects/issues",
- action: "show",
- namespace_id: group.name,
- project_id: project.name,
- id: issue.id.to_s
- })
+ allow(helper).to receive(:request).and_return(request)
end
it_behaves_like 'masked url'
end
context 'with controller for groups with subgroups and project' do
- let(:masked_url) { "http://test.host/namespace:#{subgroup.id}/project:#{subproject.id}"}
+ let(:masked_url) { "http://localhost/namespace#{subgroup.id}/project#{subproject.id}"}
+ let(:request) do
+ double(:Request,
+ path_parameters: {
+ controller: 'projects',
+ action: 'show',
+ namespace_id: subgroup.name,
+ id: subproject.name
+ },
+ protocol: 'http',
+ host: 'localhost',
+ query_string: '')
+ end
before do
allow(helper).to receive(:group).and_return(subgroup)
allow(helper).to receive(:project).and_return(subproject)
- allow(Rails.application.routes).to receive(:recognize_path).and_return({
- controller: 'projects',
- action: 'show',
- namespace_id: subgroup.name,
- id: subproject.name
- })
+ allow(helper).to receive(:request).and_return(request)
end
it_behaves_like 'masked url'
end
context 'with controller for groups and subgroups' do
- let(:masked_url) { "http://test.host/namespace:#{subgroup.id}"}
+ let(:masked_url) { "http://localhost/groups/namespace#{subgroup.id}/-/shared"}
+ let(:request) do
+ double(:Request,
+ path_parameters: {
+ controller: 'groups',
+ action: 'show',
+ id: subgroup.name
+ },
+ protocol: 'http',
+ host: 'localhost',
+ query_string: '')
+ end
before do
allow(helper).to receive(:group).and_return(subgroup)
- allow(Rails.application.routes).to receive(:recognize_path).and_return({
- controller: 'groups',
- action: 'show',
- id: subgroup.name
- })
+ allow(helper).to receive(:request).and_return(request)
end
it_behaves_like 'masked url'
end
context 'with controller for blob with file path' do
- let(:masked_url) { "http://test.host/namespace:#{group.id}/project:#{project.id}/-/blob/:repository_path" }
+ let(:masked_url) { "http://localhost/namespace#{group.id}/project#{project.id}/-/blob/:repository_path" }
+ let(:request) do
+ double(:Request,
+ path_parameters: {
+ controller: 'projects/blob',
+ action: 'show',
+ namespace_id: group.name,
+ project_id: project.name,
+ id: 'master/README.md'
+ },
+ protocol: 'http',
+ host: 'localhost',
+ query_string: '')
+ end
+
+ before do
+ allow(helper).to receive(:request).and_return(request)
+ end
+
+ it_behaves_like 'masked url'
+ end
+
+ context 'when assignee_username is present' do
+ let(:masked_url) { "http://localhost/dashboard/issues?assignee_username=masked_assignee_username" }
+ let(:request) do
+ double(:Request,
+ path_parameters: {
+ controller: 'dashboard',
+ action: 'issues'
+ },
+ protocol: 'http',
+ host: 'localhost',
+ query_string: 'assignee_username=root')
+ end
before do
- allow(Rails.application.routes).to receive(:recognize_path).and_return({
- controller: 'projects/blob',
- action: 'show',
- namespace_id: group.name,
- project_id: project.name,
- id: 'master/README.md'
- })
+ allow(helper).to receive(:request).and_return(request)
end
it_behaves_like 'masked url'
end
- context 'with non identifiable controller' do
- let(:masked_url) { "http://test.host/dashboard/issues?assignee_username=root" }
+ context 'when author_username is present' do
+ let(:masked_url) { "http://localhost/dashboard/issues?author_username=masked_author_username&scope=masked_scope&state=masked_state" }
+ let(:request) do
+ double(:Request,
+ path_parameters: {
+ controller: 'dashboard',
+ action: 'issues'
+ },
+ protocol: 'http',
+ host: 'localhost',
+ query_string: 'author_username=root&scope=all&state=opened')
+ end
before do
- controller.request.path = '/dashboard/issues'
- controller.request.query_string = 'assignee_username=root'
- allow(Rails.application.routes).to receive(:recognize_path).and_return({
- controller: 'dashboard',
- action: 'issues'
- })
+ allow(helper).to receive(:request).and_return(request)
+ end
+
+ it_behaves_like 'masked url'
+ end
+
+ context 'when some query params are not required to be masked' do
+ let(:masked_url) { "http://localhost/dashboard/issues?author_username=masked_author_username&scope=all&state=masked_state" }
+ let(:request) do
+ double(:Request,
+ path_parameters: {
+ controller: 'dashboard',
+ action: 'issues'
+ },
+ protocol: 'http',
+ host: 'localhost',
+ query_string: 'author_username=root&scope=all&state=opened')
+ end
+
+ before do
+ stub_const('Routing::PseudonymizationHelper::MaskHelper::QUERY_PARAMS_TO_NOT_MASK', %w[scope].freeze)
+ allow(helper).to receive(:request).and_return(request)
+ end
+
+ it_behaves_like 'masked url'
+ end
+
+ context 'when query string has keys with the same names as path params' do
+ let(:masked_url) { "http://localhost/dashboard/issues?action=masked_action&scope=masked_scope&state=masked_state" }
+ let(:request) do
+ double(:Request,
+ path_parameters: {
+ controller: 'dashboard',
+ action: 'issues'
+ },
+ protocol: 'http',
+ host: 'localhost',
+ query_string: 'action=foobar&scope=all&state=opened')
+ end
+
+ before do
+ allow(helper).to receive(:request).and_return(request)
end
it_behaves_like 'masked url'
@@ -121,9 +222,13 @@ RSpec.describe ::Routing::PseudonymizationHelper do
end
describe 'when url has no params to mask' do
- let(:root_url) { 'http://test.host' }
+ let(:root_url) { 'http://localhost/some/path' }
context 'returns root url' do
+ before do
+ controller.request.path = 'some/path'
+ end
+
it 'masked_page_url' do
expect(helper.masked_page_url).to eq(root_url)
end
@@ -132,17 +237,26 @@ RSpec.describe ::Routing::PseudonymizationHelper do
describe 'when it raises exception' do
context 'calls error tracking' do
+ let(:request) do
+ double(:Request,
+ path_parameters: {
+ controller: 'dashboard',
+ action: 'issues'
+ },
+ protocol: 'http',
+ host: 'localhost',
+ query_string: 'assignee_username=root',
+ original_fullpath: '/dashboard/issues?assignee_username=root')
+ end
+
before do
- controller.request.path = '/dashboard/issues'
- controller.request.query_string = 'assignee_username=root'
- allow(Rails.application.routes).to receive(:recognize_path).and_return({
- controller: 'dashboard',
- action: 'issues'
- })
+ allow(helper).to receive(:request).and_return(request)
end
it 'sends error to sentry and returns nil' do
- allow(helper).to receive(:mask_params).with(anything).and_raise(ActionController::RoutingError, 'Some routing error')
+ allow_next_instance_of(Routing::PseudonymizationHelper::MaskHelper) do |mask_helper|
+ allow(mask_helper).to receive(:mask_params).and_raise(ActionController::RoutingError, 'Some routing error')
+ end
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
ActionController::RoutingError,
diff --git a/spec/helpers/storage_helper_spec.rb b/spec/helpers/storage_helper_spec.rb
index 2cec7203fe1..d0646b30161 100644
--- a/spec/helpers/storage_helper_spec.rb
+++ b/spec/helpers/storage_helper_spec.rb
@@ -27,17 +27,18 @@ RSpec.describe StorageHelper do
create(:project,
namespace: namespace,
statistics: build(:project_statistics,
- namespace: namespace,
- repository_size: 10.kilobytes,
- wiki_size: 10.bytes,
- lfs_objects_size: 20.gigabytes,
- build_artifacts_size: 30.megabytes,
- snippets_size: 40.megabytes,
- packages_size: 12.megabytes,
- uploads_size: 15.megabytes))
+ namespace: namespace,
+ repository_size: 10.kilobytes,
+ wiki_size: 10.bytes,
+ lfs_objects_size: 20.gigabytes,
+ build_artifacts_size: 30.megabytes,
+ pipeline_artifacts_size: 11.megabytes,
+ snippets_size: 40.megabytes,
+ packages_size: 12.megabytes,
+ uploads_size: 15.megabytes))
end
- let(:message) { 'Repository: 10 KB / Wikis: 10 Bytes / Build Artifacts: 30 MB / LFS: 20 GB / Snippets: 40 MB / Packages: 12 MB / Uploads: 15 MB' }
+ let(:message) { 'Repository: 10 KB / Wikis: 10 Bytes / Build Artifacts: 30 MB / Pipeline Artifacts: 11 MB / LFS: 20 GB / Snippets: 40 MB / Packages: 12 MB / Uploads: 15 MB' }
it 'works on ProjectStatistics' do
expect(helper.storage_counters_details(project.statistics)).to eq(message)
diff --git a/spec/helpers/tab_helper_spec.rb b/spec/helpers/tab_helper_spec.rb
index 346bfc7850c..e5e88466946 100644
--- a/spec/helpers/tab_helper_spec.rb
+++ b/spec/helpers/tab_helper_spec.rb
@@ -36,7 +36,15 @@ RSpec.describe TabHelper do
expect(gl_tab_link_to('/url') { 'block content' }).to match(/block content/)
end
- it 'creates a tab with custom classes' do
+ it 'creates a tab with custom classes for enclosing list item without content block provided' do
+ expect(gl_tab_link_to('Link', '/url', { tab_class: 'my-class' })).to match(/<li class=".*my-class.*"/)
+ end
+
+ it 'creates a tab with custom classes for enclosing list item with content block provided' do
+ expect(gl_tab_link_to('/url', { tab_class: 'my-class' }) { 'Link' }).to match(/<li class=".*my-class.*"/)
+ end
+
+ it 'creates a tab with custom classes for anchor element' do
expect(gl_tab_link_to('Link', '/url', { class: 'my-class' })).to match(/<a class=".*my-class.*"/)
end
@@ -150,4 +158,22 @@ RSpec.describe TabHelper do
end
end
end
+
+ describe 'gl_tab_counter_badge' do
+ it 'creates a tab counter badge' do
+ expect(gl_tab_counter_badge(1)).to eq('<span class="badge badge-muted badge-pill gl-badge sm gl-tab-counter-badge">1</span>')
+ end
+
+ context 'with extra classes' do
+ it 'creates a tab counter badge with the correct class attribute' do
+ expect(gl_tab_counter_badge(1, { class: 'js-test' })).to eq('<span class="js-test badge badge-muted badge-pill gl-badge sm gl-tab-counter-badge">1</span>')
+ end
+ end
+
+ context 'with data attributes' do
+ it 'creates a tab counter badge with the data attributes' do
+ expect(gl_tab_counter_badge(1, { data: { some_attribute: 'foo' } })).to eq('<span class="badge badge-muted badge-pill gl-badge sm gl-tab-counter-badge" data-some-attribute="foo">1</span>')
+ end
+ end
+ end
end
diff --git a/spec/helpers/terms_helper_spec.rb b/spec/helpers/terms_helper_spec.rb
new file mode 100644
index 00000000000..9120aad4627
--- /dev/null
+++ b/spec/helpers/terms_helper_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe TermsHelper do
+ let_it_be(:current_user) { build(:user) }
+ let_it_be(:terms) { build(:term) }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(current_user)
+ end
+
+ describe '#terms_data' do
+ let_it_be(:redirect) { '%2F' }
+ let_it_be(:terms_markdown) { 'Lorem ipsum dolor sit amet' }
+ let_it_be(:accept_path) { '/-/users/terms/14/accept?redirect=%2F' }
+ let_it_be(:decline_path) { '/-/users/terms/14/decline?redirect=%2F' }
+
+ subject(:result) { Gitlab::Json.parse(helper.terms_data(terms, redirect)) }
+
+ it 'returns correct json' do
+ expect(helper).to receive(:markdown_field).with(terms, :terms).and_return(terms_markdown)
+ expect(helper).to receive(:can?).with(current_user, :accept_terms, terms).and_return(true)
+ expect(helper).to receive(:can?).with(current_user, :decline_terms, terms).and_return(true)
+ expect(helper).to receive(:accept_term_path).with(terms, { redirect: redirect }).and_return(accept_path)
+ expect(helper).to receive(:decline_term_path).with(terms, { redirect: redirect }).and_return(decline_path)
+
+ expected = {
+ terms: terms_markdown,
+ permissions: {
+ can_accept: true,
+ can_decline: true
+ },
+ paths: {
+ accept: accept_path,
+ decline: decline_path,
+ root: root_path
+ }
+ }.as_json
+
+ expect(result).to eq(expected)
+ end
+ end
+end
diff --git a/spec/helpers/time_zone_helper_spec.rb b/spec/helpers/time_zone_helper_spec.rb
index 43ad130c4b5..006fae5b814 100644
--- a/spec/helpers/time_zone_helper_spec.rb
+++ b/spec/helpers/time_zone_helper_spec.rb
@@ -100,4 +100,36 @@ RSpec.describe TimeZoneHelper, :aggregate_failures do
end
end
end
+
+ describe '#local_time_instance' do
+ let_it_be(:timezone) { 'UTC' }
+
+ before do
+ travel_to Time.find_zone(timezone).local(2021, 7, 20, 15, 30, 45)
+ end
+
+ context 'when timezone is `nil`' do
+ it 'returns the system timezone instance' do
+ expect(helper.local_time_instance(nil).name).to eq(timezone)
+ end
+ end
+
+ context 'when timezone is blank' do
+ it 'returns the system timezone instance' do
+ expect(helper.local_time_instance('').name).to eq(timezone)
+ end
+ end
+
+ context 'when a valid timezone is passed' do
+ it 'returns the local time instance' do
+ expect(helper.local_time_instance('America/Los_Angeles').name).to eq('America/Los_Angeles')
+ end
+ end
+
+ context 'when an invalid timezone is passed' do
+ it 'returns the system timezone instance' do
+ expect(helper.local_time_instance('Foo/Bar').name).to eq(timezone)
+ end
+ end
+ end
end
diff --git a/spec/helpers/user_callouts_helper_spec.rb b/spec/helpers/user_callouts_helper_spec.rb
index f738ba855b8..7abc67e29a4 100644
--- a/spec/helpers/user_callouts_helper_spec.rb
+++ b/spec/helpers/user_callouts_helper_spec.rb
@@ -216,20 +216,6 @@ RSpec.describe UserCalloutsHelper do
context 'when the invite_members_banner has not been dismissed' do
it { is_expected.to eq(true) }
- context 'when a user has dismissed this banner via cookies already' do
- before do
- helper.request.cookies["invite_#{group.id}_#{user.id}"] = 'true'
- end
-
- it { is_expected.to eq(false) }
-
- it 'creates the callout from cookie', :aggregate_failures do
- expect { subject }.to change { Users::GroupCallout.count }.by(1)
- expect(Users::GroupCallout.last).to have_attributes(group_id: group.id,
- feature_name: described_class::INVITE_MEMBERS_BANNER)
- end
- end
-
context 'when the group was just created' do
before do
flash[:notice] = "Group #{group.name} was successfully created"
diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb
index 480b1e2a0de..2b55319c70c 100644
--- a/spec/helpers/users_helper_spec.rb
+++ b/spec/helpers/users_helper_spec.rb
@@ -383,7 +383,7 @@ RSpec.describe UsersHelper do
end
context 'when `user.unconfirmed_email` is set' do
- let(:user) { create(:user, unconfirmed_email: 'foo@bar.com') }
+ let(:user) { create(:user, :unconfirmed, unconfirmed_email: 'foo@bar.com') }
it 'sets `modal_attributes.messageHtml` correctly' do
expect(Gitlab::Json.parse(confirm_user_data[:modal_attributes])['messageHtml']).to eq('This user has an unconfirmed email address (foo@bar.com). You may force a confirmation.')
diff --git a/spec/helpers/wiki_helper_spec.rb b/spec/helpers/wiki_helper_spec.rb
index dc76f92db1b..0d04ca2b876 100644
--- a/spec/helpers/wiki_helper_spec.rb
+++ b/spec/helpers/wiki_helper_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe WikiHelper do
it 'sets the title for the show action' do
expect(helper).to receive(:breadcrumb_title).with(page.human_title)
- expect(helper).to receive(:wiki_breadcrumb_dropdown_links).with(page.slug)
+ expect(helper).to receive(:wiki_breadcrumb_collapsed_links).with(page.slug)
expect(helper).to receive(:page_title).with(page.human_title, 'Wiki')
expect(helper).to receive(:add_to_breadcrumbs).with('Wiki', helper.wiki_path(page.wiki))
@@ -17,7 +17,7 @@ RSpec.describe WikiHelper do
it 'sets the title for a custom action' do
expect(helper).to receive(:breadcrumb_title).with(page.human_title)
- expect(helper).to receive(:wiki_breadcrumb_dropdown_links).with(page.slug)
+ expect(helper).to receive(:wiki_breadcrumb_collapsed_links).with(page.slug)
expect(helper).to receive(:page_title).with('Edit', page.human_title, 'Wiki')
expect(helper).to receive(:add_to_breadcrumbs).with('Wiki', helper.wiki_path(page.wiki))
@@ -27,7 +27,7 @@ RSpec.describe WikiHelper do
it 'sets the title for an unsaved page' do
expect(page).to receive(:persisted?).and_return(false)
expect(helper).not_to receive(:breadcrumb_title)
- expect(helper).not_to receive(:wiki_breadcrumb_dropdown_links)
+ expect(helper).not_to receive(:wiki_breadcrumb_collapsed_links)
expect(helper).to receive(:page_title).with('Wiki')
expect(helper).to receive(:add_to_breadcrumbs).with('Wiki', helper.wiki_path(page.wiki))
diff --git a/spec/initializers/0_postgresql_types_spec.rb b/spec/initializers/0_postgresql_types_spec.rb
new file mode 100644
index 00000000000..76b243033d0
--- /dev/null
+++ b/spec/initializers/0_postgresql_types_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'PostgreSQL registered types' do
+ subject(:types) { ApplicationRecord.connection.send(:type_map).keys }
+
+ # These can be obtained via SELECT oid, typname from pg_type
+ it 'includes custom and standard OIDs' do
+ expect(types).to include(28, 194, 1034, 3220, 23, 20)
+ end
+
+ it 'includes custom and standard types' do
+ expect(types).to include('xid', 'pg_node_tree', '_aclitem', 'pg_lsn', 'int4', 'int8')
+ end
+end
diff --git a/spec/initializers/100_patch_omniauth_oauth2_spec.rb b/spec/initializers/100_patch_omniauth_oauth2_spec.rb
index 0c436e4ef45..c30a1cdeafa 100644
--- a/spec/initializers/100_patch_omniauth_oauth2_spec.rb
+++ b/spec/initializers/100_patch_omniauth_oauth2_spec.rb
@@ -2,12 +2,10 @@
require 'spec_helper'
-RSpec.describe 'OmniAuth::Strategies::OAuth2', type: :strategy do
- let(:strategy) { [OmniAuth::Strategies::OAuth2] }
-
+RSpec.describe 'OmniAuth::Strategies::OAuth2' do
it 'verifies the gem version' do
current_version = OmniAuth::OAuth2::VERSION
- expected_version = '1.7.1'
+ expected_version = '1.7.2'
expect(current_version).to eq(expected_version), <<~EOF
New version #{current_version} of the `omniauth-oauth2` gem detected!
@@ -18,39 +16,18 @@ RSpec.describe 'OmniAuth::Strategies::OAuth2', type: :strategy do
EOF
end
- context 'when a custom error message is passed from an OAuth2 provider' do
- let(:message) { 'Please go to https://evil.com' }
- let(:state) { 'secret' }
- let(:callback_path) { '/users/auth/oauth2/callback' }
- let(:params) { { state: state, error: 'evil_key', error_description: message } }
- let(:error) { last_request.env['omniauth.error'] }
-
- before do
- env('rack.session', { 'omniauth.state' => state })
- end
-
- it 'returns the custom error message if the state is valid' do
- get callback_path, **params
-
- expect(error.message).to eq("evil_key | #{message}")
- end
+ context 'when a Faraday exception is raised' do
+ where(exception: [Faraday::TimeoutError, Faraday::ConnectionFailed])
- it 'returns the custom `error_reason` message if the `error_description` is blank' do
- get callback_path, **params.merge(error_description: ' ', error_reason: 'custom reason')
-
- expect(error.message).to eq('evil_key | custom reason')
- end
-
- it 'returns a CSRF error if the state is invalid' do
- get callback_path, **params.merge(state: 'invalid')
-
- expect(error.message).to eq('csrf_detected | CSRF detected')
- end
+ with_them do
+ it 'passes the exception to OmniAuth' do
+ instance = OmniAuth::Strategies::OAuth2.new(double)
- it 'returns a CSRF error if the state is missing' do
- get callback_path, **params.without(:state)
+ expect(instance).to receive(:original_callback_phase) { raise exception, 'message' }
+ expect(instance).to receive(:fail!).with(:timeout, kind_of(exception))
- expect(error.message).to eq('csrf_detected | CSRF detected')
+ instance.callback_phase
+ end
end
end
end
diff --git a/spec/initializers/carrierwave_patch_spec.rb b/spec/initializers/carrierwave_patch_spec.rb
index e219db2299d..b0f337935ef 100644
--- a/spec/initializers/carrierwave_patch_spec.rb
+++ b/spec/initializers/carrierwave_patch_spec.rb
@@ -15,9 +15,6 @@ RSpec.describe 'CarrierWave::Storage::Fog::File' do
subject { CarrierWave::Storage::Fog::File.new(uploader, storage, test_filename) }
before do
- require 'fog/azurerm'
- require 'fog/aws'
-
stub_object_storage(connection_params: connection_options, remote_directory: bucket_name)
allow(uploader).to receive(:fog_directory).and_return(bucket_name)
diff --git a/spec/initializers/database_config_spec.rb b/spec/initializers/database_config_spec.rb
index 23f7fd06254..230f1296760 100644
--- a/spec/initializers/database_config_spec.rb
+++ b/spec/initializers/database_config_spec.rb
@@ -7,56 +7,15 @@ RSpec.describe 'Database config initializer', :reestablished_active_record_base
load Rails.root.join('config/initializers/database_config.rb')
end
- before do
- allow(Gitlab::Runtime).to receive(:max_threads).and_return(max_threads)
- end
-
- let(:max_threads) { 8 }
-
it 'retains the correct database name for the connection' do
- previous_db_name = Gitlab::Database.main.scope.connection.pool.db_config.name
+ previous_db_name = ApplicationRecord.connection.pool.db_config.name
subject
- expect(Gitlab::Database.main.scope.connection.pool.db_config.name).to eq(previous_db_name)
+ expect(ApplicationRecord.connection.pool.db_config.name).to eq(previous_db_name)
end
- context 'when no custom headroom is specified' do
- it 'sets the pool size based on the number of worker threads' do
- old = ActiveRecord::Base.connection_db_config.pool
-
- expect(old).not_to eq(18)
-
- expect { subject }
- .to change { ActiveRecord::Base.connection_db_config.pool }
- .from(old)
- .to(18)
- end
-
- it 'overwrites custom pool settings' do
- config = Gitlab::Database.main.config.merge(pool: 42)
-
- allow(Gitlab::Database.main).to receive(:config).and_return(config)
- subject
-
- expect(ActiveRecord::Base.connection_db_config.pool).to eq(18)
- end
- end
-
- context "when specifying headroom through an ENV variable" do
- let(:headroom) { 15 }
-
- before do
- stub_env("DB_POOL_HEADROOM", headroom)
- end
-
- it "adds headroom on top of the calculated size" do
- old = ActiveRecord::Base.connection_db_config.pool
-
- expect { subject }
- .to change { ActiveRecord::Base.connection_db_config.pool }
- .from(old)
- .to(23)
- end
+ it 'does not overwrite custom pool settings' do
+ expect { subject }.not_to change { ActiveRecord::Base.connection_db_config.pool }
end
end
diff --git a/spec/initializers/session_store_spec.rb b/spec/initializers/session_store_spec.rb
new file mode 100644
index 00000000000..3da52ccc981
--- /dev/null
+++ b/spec/initializers/session_store_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Session initializer for GitLab' do
+ subject { Gitlab::Application.config }
+
+ let(:load_session_store) do
+ load Rails.root.join('config/initializers/session_store.rb')
+ end
+
+ describe 'config#session_store' do
+ context 'when the GITLAB_REDIS_STORE_WITH_SESSION_STORE env is not set' do
+ before do
+ stub_env('GITLAB_REDIS_STORE_WITH_SESSION_STORE', nil)
+ end
+
+ it 'initialized as a redis_store with a proper Redis::Store instance' do
+ expect(subject).to receive(:session_store).with(:redis_store, a_hash_including(redis_store: kind_of(::Redis::Store)))
+
+ load_session_store
+ end
+ end
+
+ context 'when the GITLAB_REDIS_STORE_WITH_SESSION_STORE env is disabled' do
+ before do
+ stub_env('GITLAB_REDIS_STORE_WITH_SESSION_STORE', false)
+ end
+
+ it 'initialized as a redis_store with a proper servers configuration' do
+ expect(subject).to receive(:session_store).with(:redis_store, a_hash_including(servers: kind_of(Hash)))
+
+ load_session_store
+ end
+ end
+ end
+end
diff --git a/spec/lib/api/ci/helpers/runner_spec.rb b/spec/lib/api/ci/helpers/runner_spec.rb
index cc871d66d40..37277e7dcbd 100644
--- a/spec/lib/api/ci/helpers/runner_spec.rb
+++ b/spec/lib/api/ci/helpers/runner_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe API::Ci::Helpers::Runner do
it 'handles sticking of a build when a build ID is specified' do
allow(helper).to receive(:params).and_return(id: build.id)
- expect(ApplicationRecord.sticking)
+ expect(Ci::Build.sticking)
.to receive(:stick_or_unstick_request)
.with({}, :build, build.id)
@@ -25,7 +25,7 @@ RSpec.describe API::Ci::Helpers::Runner do
it 'does not handle sticking if no build ID was specified' do
allow(helper).to receive(:params).and_return({})
- expect(ApplicationRecord.sticking)
+ expect(Ci::Build.sticking)
.not_to receive(:stick_or_unstick_request)
helper.current_job
@@ -44,7 +44,7 @@ RSpec.describe API::Ci::Helpers::Runner do
it 'handles sticking of a runner if a token is specified' do
allow(helper).to receive(:params).and_return(token: runner.token)
- expect(ApplicationRecord.sticking)
+ expect(Ci::Runner.sticking)
.to receive(:stick_or_unstick_request)
.with({}, :runner, runner.token)
@@ -54,7 +54,7 @@ RSpec.describe API::Ci::Helpers::Runner do
it 'does not handle sticking if no token was specified' do
allow(helper).to receive(:params).and_return({})
- expect(ApplicationRecord.sticking)
+ expect(Ci::Runner.sticking)
.not_to receive(:stick_or_unstick_request)
helper.current_runner
diff --git a/spec/lib/api/entities/projects/topic_spec.rb b/spec/lib/api/entities/projects/topic_spec.rb
new file mode 100644
index 00000000000..cdf142dbb7d
--- /dev/null
+++ b/spec/lib/api/entities/projects/topic_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Entities::Projects::Topic do
+ let(:topic) { create(:topic) }
+
+ subject { described_class.new(topic).as_json }
+
+ it 'exposes correct attributes' do
+ expect(subject).to include(
+ :id,
+ :name,
+ :description,
+ :total_projects_count,
+ :avatar_url
+ )
+ end
+end
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index 37e040a422b..2277bd78e86 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -351,12 +351,14 @@ RSpec.describe API::Helpers do
let(:send_git_blob) do
subject.send(:send_git_blob, repository, blob)
+ subject.header
end
before do
allow(subject).to receive(:env).and_return({})
allow(subject).to receive(:content_type)
allow(subject).to receive(:header).and_return({})
+ allow(subject).to receive(:body).and_return('')
allow(Gitlab::Workhorse).to receive(:send_git_blob)
end
diff --git a/spec/lib/atlassian/jira_connect/client_spec.rb b/spec/lib/atlassian/jira_connect/client_spec.rb
index 5c8d4282118..9201d1c5dcb 100644
--- a/spec/lib/atlassian/jira_connect/client_spec.rb
+++ b/spec/lib/atlassian/jira_connect/client_spec.rb
@@ -18,7 +18,15 @@ RSpec.describe Atlassian::JiraConnect::Client do
end
end
- describe '.generate_update_sequence_id' do
+ around do |example|
+ if example.metadata[:skip_freeze_time]
+ example.run
+ else
+ freeze_time { example.run }
+ end
+ end
+
+ describe '.generate_update_sequence_id', :skip_freeze_time do
it 'returns unix time in microseconds as integer', :aggregate_failures do
travel_to(Time.utc(1970, 1, 1, 0, 0, 1)) do
expect(described_class.generate_update_sequence_id).to eq(1000)
diff --git a/spec/lib/banzai/filter/emoji_filter_spec.rb b/spec/lib/banzai/filter/emoji_filter_spec.rb
index cb0b470eaa1..d621f63211b 100644
--- a/spec/lib/banzai/filter/emoji_filter_spec.rb
+++ b/spec/lib/banzai/filter/emoji_filter_spec.rb
@@ -28,9 +28,9 @@ RSpec.describe Banzai::Filter::EmojiFilter do
it 'replaces name versions of trademark, copyright, and registered trademark' do
doc = filter('<p>:tm: :copyright: :registered:</p>')
- expect(doc.css('gl-emoji')[0].text).to eq 'â„¢'
- expect(doc.css('gl-emoji')[1].text).to eq '©'
- expect(doc.css('gl-emoji')[2].text).to eq '®'
+ expect(doc.css('gl-emoji')[0].text).to eq 'â„¢ï¸'
+ expect(doc.css('gl-emoji')[1].text).to eq '©ï¸'
+ expect(doc.css('gl-emoji')[2].text).to eq '®ï¸'
end
it 'correctly encodes the URL' do
diff --git a/spec/lib/banzai/filter/footnote_filter_spec.rb b/spec/lib/banzai/filter/footnote_filter_spec.rb
index 01b7319fab1..54faa748d53 100644
--- a/spec/lib/banzai/filter/footnote_filter_spec.rb
+++ b/spec/lib/banzai/filter/footnote_filter_spec.rb
@@ -5,34 +5,42 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::FootnoteFilter do
include FilterSpecHelper
- # first[^1] and second[^second]
+ # rubocop:disable Style/AsciiComments
+ # first[^1] and second[^second] and third[^_😄_]
# [^1]: one
# [^second]: two
+ # [^_😄_]: three
+ # rubocop:enable Style/AsciiComments
let(:footnote) do
- <<~EOF
- <p>first<sup><a href="#fn1" id="fnref1">1</a></sup> and second<sup><a href="#fn2" id="fnref2">2</a></sup></p>
- <p>same reference<sup><a href="#fn1" id="fnref1">1</a></sup></p>
+ <<~EOF.strip_heredoc
+ <p>first<sup><a href="#fn-1" id="fnref-1">1</a></sup> and second<sup><a href="#fn-second" id="fnref-second">2</a></sup> and third<sup><a href="#fn-_%F0%9F%98%84_" id="fnref-_%F0%9F%98%84_">3</a></sup></p>
+
<ol>
- <li id="fn1">
- <p>one <a href="#fnref1">↩</a></p>
+ <li id="fn-1">
+ <p>one <a href="#fnref-1" aria-label="Back to content">↩</a></p>
</li>
- <li id="fn2">
- <p>two <a href="#fnref2">↩</a></p>
+ <li id="fn-second">
+ <p>two <a href="#fnref-second" aria-label="Back to content">↩</a></p>
+ </li>\n<li id="fn-_%F0%9F%98%84_">
+ <p>three <a href="#fnref-_%F0%9F%98%84_" aria-label="Back to content">↩</a></p>
</li>
</ol>
EOF
end
let(:filtered_footnote) do
- <<~EOF
- <p>first<sup class="footnote-ref"><a href="#fn1-#{identifier}" id="fnref1-#{identifier}">1</a></sup> and second<sup class="footnote-ref"><a href="#fn2-#{identifier}" id="fnref2-#{identifier}">2</a></sup></p>
- <p>same reference<sup class="footnote-ref"><a href="#fn1-#{identifier}" id="fnref1-#{identifier}">1</a></sup></p>
- <section class="footnotes"><ol>
- <li id="fn1-#{identifier}">
- <p>one <a href="#fnref1-#{identifier}" class="footnote-backref">↩</a></p>
+ <<~EOF.strip_heredoc
+ <p>first<sup class="footnote-ref"><a href="#fn-1-#{identifier}" id="fnref-1-#{identifier}" data-footnote-ref="">1</a></sup> and second<sup class="footnote-ref"><a href="#fn-second-#{identifier}" id="fnref-second-#{identifier}" data-footnote-ref="">2</a></sup> and third<sup class="footnote-ref"><a href="#fn-_%F0%9F%98%84_-#{identifier}" id="fnref-_%F0%9F%98%84_-#{identifier}" data-footnote-ref="">3</a></sup></p>
+
+ <section class=\"footnotes\" data-footnotes><ol>
+ <li id="fn-1-#{identifier}">
+ <p>one <a href="#fnref-1-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref="">↩</a></p>
+ </li>
+ <li id="fn-second-#{identifier}">
+ <p>two <a href="#fnref-second-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref="">↩</a></p>
</li>
- <li id="fn2-#{identifier}">
- <p>two <a href="#fnref2-#{identifier}" class="footnote-backref">↩</a></p>
+ <li id="fn-_%F0%9F%98%84_-#{identifier}">
+ <p>three <a href="#fnref-_%F0%9F%98%84_-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref="">↩</a></p>
</li>
</ol></section>
EOF
@@ -41,10 +49,56 @@ RSpec.describe Banzai::Filter::FootnoteFilter do
context 'when footnotes exist' do
let(:doc) { filter(footnote) }
let(:link_node) { doc.css('sup > a').first }
- let(:identifier) { link_node[:id].delete_prefix('fnref1-') }
+ let(:identifier) { link_node[:id].delete_prefix('fnref-1-') }
it 'properly adds the necessary ids and classes' do
expect(doc.to_html).to eq filtered_footnote
end
+
+ context 'using ruby-based HTML renderer' do
+ # first[^1] and second[^second]
+ # [^1]: one
+ # [^second]: two
+ let(:footnote) do
+ <<~EOF
+ <p>first<sup><a href="#fn1" id="fnref1">1</a></sup> and second<sup><a href="#fn2" id="fnref2">2</a></sup></p>
+ <p>same reference<sup><a href="#fn1" id="fnref1">1</a></sup></p>
+ <ol>
+ <li id="fn1">
+ <p>one <a href="#fnref1">↩</a></p>
+ </li>
+ <li id="fn2">
+ <p>two <a href="#fnref2">↩</a></p>
+ </li>
+ </ol>
+ EOF
+ end
+
+ let(:filtered_footnote) do
+ <<~EOF
+ <p>first<sup class="footnote-ref"><a href="#fn1-#{identifier}" id="fnref1-#{identifier}">1</a></sup> and second<sup class="footnote-ref"><a href="#fn2-#{identifier}" id="fnref2-#{identifier}">2</a></sup></p>
+ <p>same reference<sup class="footnote-ref"><a href="#fn1-#{identifier}" id="fnref1-#{identifier}">1</a></sup></p>
+ <section class="footnotes"><ol>
+ <li id="fn1-#{identifier}">
+ <p>one <a href="#fnref1-#{identifier}" class="footnote-backref">↩</a></p>
+ </li>
+ <li id="fn2-#{identifier}">
+ <p>two <a href="#fnref2-#{identifier}" class="footnote-backref">↩</a></p>
+ </li>
+ </ol></section>
+ EOF
+ end
+
+ let(:doc) { filter(footnote) }
+ let(:identifier) { link_node[:id].delete_prefix('fnref1-') }
+
+ before do
+ stub_feature_flags(use_cmark_renderer: false)
+ end
+
+ it 'properly adds the necessary ids and classes' do
+ expect(doc.to_html).to eq filtered_footnote
+ end
+ end
end
end
diff --git a/spec/lib/banzai/filter/markdown_filter_spec.rb b/spec/lib/banzai/filter/markdown_filter_spec.rb
index c5e84a0c1e7..a310de5c015 100644
--- a/spec/lib/banzai/filter/markdown_filter_spec.rb
+++ b/spec/lib/banzai/filter/markdown_filter_spec.rb
@@ -5,90 +5,125 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::MarkdownFilter do
include FilterSpecHelper
- describe 'markdown engine from context' do
- it 'defaults to CommonMark' do
- expect_next_instance_of(Banzai::Filter::MarkdownEngines::CommonMark) do |instance|
- expect(instance).to receive(:render).and_return('test')
+ shared_examples_for 'renders correct markdown' do
+ describe 'markdown engine from context' do
+ it 'defaults to CommonMark' do
+ expect_next_instance_of(Banzai::Filter::MarkdownEngines::CommonMark) do |instance|
+ expect(instance).to receive(:render).and_return('test')
+ end
+
+ filter('test')
end
- filter('test')
- end
+ it 'uses CommonMark' do
+ expect_next_instance_of(Banzai::Filter::MarkdownEngines::CommonMark) do |instance|
+ expect(instance).to receive(:render).and_return('test')
+ end
- it 'uses CommonMark' do
- expect_next_instance_of(Banzai::Filter::MarkdownEngines::CommonMark) do |instance|
- expect(instance).to receive(:render).and_return('test')
+ filter('test', { markdown_engine: :common_mark })
end
-
- filter('test', { markdown_engine: :common_mark })
end
- end
- describe 'code block' do
- context 'using CommonMark' do
- before do
- stub_const('Banzai::Filter::MarkdownFilter::DEFAULT_ENGINE', :common_mark)
+ describe 'code block' do
+ context 'using CommonMark' do
+ before do
+ stub_const('Banzai::Filter::MarkdownFilter::DEFAULT_ENGINE', :common_mark)
+ end
+
+ it 'adds language to lang attribute when specified' do
+ result = filter("```html\nsome code\n```", no_sourcepos: true)
+
+ if Feature.enabled?(:use_cmark_renderer)
+ expect(result).to start_with('<pre lang="html"><code>')
+ else
+ expect(result).to start_with('<pre><code lang="html">')
+ end
+ end
+
+ it 'does not add language to lang attribute when not specified' do
+ result = filter("```\nsome code\n```", no_sourcepos: true)
+
+ expect(result).to start_with('<pre><code>')
+ end
+
+ it 'works with utf8 chars in language' do
+ result = filter("```æ—¥\nsome code\n```", no_sourcepos: true)
+
+ if Feature.enabled?(:use_cmark_renderer)
+ expect(result).to start_with('<pre lang="æ—¥"><code>')
+ else
+ expect(result).to start_with('<pre><code lang="æ—¥">')
+ end
+ end
+
+ it 'works with additional language parameters' do
+ result = filter("```ruby:red gem foo\nsome code\n```", no_sourcepos: true)
+
+ if Feature.enabled?(:use_cmark_renderer)
+ expect(result).to start_with('<pre lang="ruby:red" data-meta="gem foo"><code>')
+ else
+ expect(result).to start_with('<pre><code lang="ruby:red gem foo">')
+ end
+ end
end
+ end
- it 'adds language to lang attribute when specified' do
- result = filter("```html\nsome code\n```", no_sourcepos: true)
-
- expect(result).to start_with('<pre><code lang="html">')
- end
-
- it 'does not add language to lang attribute when not specified' do
- result = filter("```\nsome code\n```", no_sourcepos: true)
-
- expect(result).to start_with('<pre><code>')
- end
+ describe 'source line position' do
+ context 'using CommonMark' do
+ before do
+ stub_const('Banzai::Filter::MarkdownFilter::DEFAULT_ENGINE', :common_mark)
+ end
- it 'works with utf8 chars in language' do
- result = filter("```æ—¥\nsome code\n```", no_sourcepos: true)
+ it 'defaults to add data-sourcepos' do
+ result = filter('test')
- expect(result).to start_with('<pre><code lang="æ—¥">')
- end
+ expect(result).to eq '<p data-sourcepos="1:1-1:4">test</p>'
+ end
- it 'works with additional language parameters' do
- result = filter("```ruby:red gem\nsome code\n```", no_sourcepos: true)
+ it 'disables data-sourcepos' do
+ result = filter('test', no_sourcepos: true)
- expect(result).to start_with('<pre><code lang="ruby:red gem">')
+ expect(result).to eq '<p>test</p>'
+ end
end
end
- end
- describe 'source line position' do
- context 'using CommonMark' do
- before do
- stub_const('Banzai::Filter::MarkdownFilter::DEFAULT_ENGINE', :common_mark)
- end
+ describe 'footnotes in tables' do
+ it 'processes footnotes in table cells' do
+ text = <<-MD.strip_heredoc
+ | Column1 |
+ | --------- |
+ | foot [^1] |
- it 'defaults to add data-sourcepos' do
- result = filter('test')
+ [^1]: a footnote
+ MD
- expect(result).to eq '<p data-sourcepos="1:1-1:4">test</p>'
- end
+ result = filter(text, no_sourcepos: true)
- it 'disables data-sourcepos' do
- result = filter('test', no_sourcepos: true)
+ expect(result).to include('<td>foot <sup')
- expect(result).to eq '<p>test</p>'
+ if Feature.enabled?(:use_cmark_renderer)
+ expect(result).to include('<section class="footnotes" data-footnotes>')
+ else
+ expect(result).to include('<section class="footnotes">')
+ end
end
end
end
- describe 'footnotes in tables' do
- it 'processes footnotes in table cells' do
- text = <<-MD.strip_heredoc
- | Column1 |
- | --------- |
- | foot [^1] |
-
- [^1]: a footnote
- MD
+ context 'using ruby-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: false)
+ end
- result = filter(text, no_sourcepos: true)
+ it_behaves_like 'renders correct markdown'
+ end
- expect(result).to include('<td>foot <sup')
- expect(result).to include('<section class="footnotes">')
+ context 'using c-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: true)
end
+
+ it_behaves_like 'renders correct markdown'
end
end
diff --git a/spec/lib/banzai/filter/plantuml_filter_spec.rb b/spec/lib/banzai/filter/plantuml_filter_spec.rb
index 5ad94c74514..d1a3b5689a8 100644
--- a/spec/lib/banzai/filter/plantuml_filter_spec.rb
+++ b/spec/lib/banzai/filter/plantuml_filter_spec.rb
@@ -5,30 +5,67 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::PlantumlFilter do
include FilterSpecHelper
- it 'replaces plantuml pre tag with img tag' do
- stub_application_setting(plantuml_enabled: true, plantuml_url: "http://localhost:8080")
- input = '<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
- output = '<div class="imageblock"><div class="content"><img class="plantuml" src="http://localhost:8080/png/U9npoazIqBLJ24uiIbImKl18pSd91m0rkGMq"></div></div>'
- doc = filter(input)
+ shared_examples_for 'renders correct markdown' do
+ it 'replaces plantuml pre tag with img tag' do
+ stub_application_setting(plantuml_enabled: true, plantuml_url: "http://localhost:8080")
- expect(doc.to_s).to eq output
+ input = if Feature.enabled?(:use_cmark_renderer)
+ '<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
+ else
+ '<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
+ end
+
+ output = '<div class="imageblock"><div class="content"><img class="plantuml" src="http://localhost:8080/png/U9npoazIqBLJ24uiIbImKl18pSd91m0rkGMq"></div></div>'
+ doc = filter(input)
+
+ expect(doc.to_s).to eq output
+ end
+
+ it 'does not replace plantuml pre tag with img tag if disabled' do
+ stub_application_setting(plantuml_enabled: false)
+
+ if Feature.enabled?(:use_cmark_renderer)
+ input = '<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
+ output = '<pre lang="plantuml"><code>Bob -&gt; Sara : Hello</code></pre>'
+ else
+ input = '<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
+ output = '<pre><code lang="plantuml">Bob -&gt; Sara : Hello</code></pre>'
+ end
+
+ doc = filter(input)
+
+ expect(doc.to_s).to eq output
+ end
+
+ it 'does not replace plantuml pre tag with img tag if url is invalid' do
+ stub_application_setting(plantuml_enabled: true, plantuml_url: "invalid")
+
+ input = if Feature.enabled?(:use_cmark_renderer)
+ '<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
+ else
+ '<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
+ end
+
+ output = '<div class="listingblock"><div class="content"><pre class="plantuml plantuml-error"> Error: cannot connect to PlantUML server at "invalid"</pre></div></div>'
+ doc = filter(input)
+
+ expect(doc.to_s).to eq output
+ end
end
- it 'does not replace plantuml pre tag with img tag if disabled' do
- stub_application_setting(plantuml_enabled: false)
- input = '<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
- output = '<pre><code lang="plantuml">Bob -&gt; Sara : Hello</code></pre>'
- doc = filter(input)
+ context 'using ruby-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: false)
+ end
- expect(doc.to_s).to eq output
+ it_behaves_like 'renders correct markdown'
end
- it 'does not replace plantuml pre tag with img tag if url is invalid' do
- stub_application_setting(plantuml_enabled: true, plantuml_url: "invalid")
- input = '<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
- output = '<div class="listingblock"><div class="content"><pre class="plantuml plantuml-error"> Error: cannot connect to PlantUML server at "invalid"</pre></div></div>'
- doc = filter(input)
+ context 'using c-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: true)
+ end
- expect(doc.to_s).to eq output
+ it_behaves_like 'renders correct markdown'
end
end
diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb
index f880fe06ce3..8eb8e5cf800 100644
--- a/spec/lib/banzai/filter/sanitization_filter_spec.rb
+++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb
@@ -45,10 +45,10 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
it 'allows `text-align` property in `style` attribute on table elements' do
html = <<~HTML
- <table>
- <tr><th style="text-align: center">Head</th></tr>
- <tr><td style="text-align: right">Body</th></tr>
- </table>
+ <table>
+ <tr><th style="text-align: center">Head</th></tr>
+ <tr><td style="text-align: right">Body</th></tr>
+ </table>
HTML
doc = filter(html)
@@ -140,14 +140,14 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
describe 'footnotes' do
it 'allows correct footnote id property on links' do
- exp = %q(<a href="#fn1" id="fnref1">foo/bar.md</a>)
+ exp = %q(<a href="#fn-first" id="fnref-first">foo/bar.md</a>)
act = filter(exp)
expect(act.to_html).to eq exp
end
it 'allows correct footnote id property on li element' do
- exp = %q(<ol><li id="fn1">footnote</li></ol>)
+ exp = %q(<ol><li id="fn-last">footnote</li></ol>)
act = filter(exp)
expect(act.to_html).to eq exp
@@ -156,7 +156,7 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
it 'removes invalid id for footnote links' do
exp = %q(<a href="#fn1">link</a>)
- %w[fnrefx test xfnref1].each do |id|
+ %w[fnrefx test xfnref-1].each do |id|
act = filter(%(<a href="#fn1" id="#{id}">link</a>))
expect(act.to_html).to eq exp
@@ -166,18 +166,58 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
it 'removes invalid id for footnote li' do
exp = %q(<ol><li>footnote</li></ol>)
- %w[fnx test xfn1].each do |id|
+ %w[fnx test xfn-1].each do |id|
act = filter(%(<ol><li id="#{id}">footnote</li></ol>))
expect(act.to_html).to eq exp
end
end
- it 'allows footnotes numbered higher than 9' do
- exp = %q(<a href="#fn15" id="fnref15">link</a><ol><li id="fn15">footnote</li></ol>)
- act = filter(exp)
+ context 'using ruby-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: false)
+ end
- expect(act.to_html).to eq exp
+ it 'allows correct footnote id property on links' do
+ exp = %q(<a href="#fn1" id="fnref1">foo/bar.md</a>)
+ act = filter(exp)
+
+ expect(act.to_html).to eq exp
+ end
+
+ it 'allows correct footnote id property on li element' do
+ exp = %q(<ol><li id="fn1">footnote</li></ol>)
+ act = filter(exp)
+
+ expect(act.to_html).to eq exp
+ end
+
+ it 'removes invalid id for footnote links' do
+ exp = %q(<a href="#fn1">link</a>)
+
+ %w[fnrefx test xfnref1].each do |id|
+ act = filter(%(<a href="#fn1" id="#{id}">link</a>))
+
+ expect(act.to_html).to eq exp
+ end
+ end
+
+ it 'removes invalid id for footnote li' do
+ exp = %q(<ol><li>footnote</li></ol>)
+
+ %w[fnx test xfn1].each do |id|
+ act = filter(%(<ol><li id="#{id}">footnote</li></ol>))
+
+ expect(act.to_html).to eq exp
+ end
+ end
+
+ it 'allows footnotes numbered higher than 9' do
+ exp = %q(<a href="#fn15" id="fnref15">link</a><ol><li id="fn15">footnote</li></ol>)
+ act = filter(exp)
+
+ expect(act.to_html).to eq exp
+ end
end
end
end
diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
index 7e45ecdd135..dfe022b51d2 100644
--- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
+++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
@@ -11,130 +11,210 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
# after Markdown rendering.
result = filter(%{<pre lang="#{lang}"><code>&lt;script&gt;alert(1)&lt;/script&gt;</code></pre>})
- expect(result.to_html).not_to include("<script>alert(1)</script>")
- expect(result.to_html).to include("alert(1)")
+ # `(1)` symbols are wrapped by lexer tags.
+ expect(result.to_html).not_to match(%r{<script>alert.*<\/script>})
+
+ # `<>` stands for lexer tags like <span ...>, not &lt;s above.
+ expect(result.to_html).to match(%r{alert(<.*>)?\((<.*>)?1(<.*>)?\)})
end
end
- context "when no language is specified" do
- it "highlights as plaintext" do
- result = filter('<pre><code>def fun end</code></pre>')
+ shared_examples_for 'renders correct markdown' do
+ context "when no language is specified" do
+ it "highlights as plaintext" do
+ result = filter('<pre><code>def fun end</code></pre>')
- expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">def fun end</span></code></pre>')
- end
+ expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">def fun end</span></code></pre>')
+ end
- include_examples "XSS prevention", ""
- end
+ include_examples "XSS prevention", ""
+ end
- context "when contains mermaid diagrams" do
- it "ignores mermaid blocks" do
- result = filter('<pre data-mermaid-style="display"><code>mermaid code</code></pre>')
+ context "when contains mermaid diagrams" do
+ it "ignores mermaid blocks" do
+ result = filter('<pre data-mermaid-style="display"><code>mermaid code</code></pre>')
- expect(result.to_html).to eq('<pre data-mermaid-style="display"><code>mermaid code</code></pre>')
+ expect(result.to_html).to eq('<pre data-mermaid-style="display"><code>mermaid code</code></pre>')
+ end
end
- end
- context "when a valid language is specified" do
- it "highlights as that language" do
- result = filter('<pre><code lang="ruby">def fun end</code></pre>')
+ context "when a valid language is specified" do
+ it "highlights as that language" do
+ result = if Feature.enabled?(:use_cmark_renderer)
+ filter('<pre lang="ruby"><code>def fun end</code></pre>')
+ else
+ filter('<pre><code lang="ruby">def fun end</code></pre>')
+ end
+
+ expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight language-ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">fun</span> <span class="k">end</span></span></code></pre>')
+ end
- expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight language-ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">fun</span> <span class="k">end</span></span></code></pre>')
+ include_examples "XSS prevention", "ruby"
end
- include_examples "XSS prevention", "ruby"
- end
+ context "when an invalid language is specified" do
+ it "highlights as plaintext" do
+ result = if Feature.enabled?(:use_cmark_renderer)
+ filter('<pre lang="gnuplot"><code>This is a test</code></pre>')
+ else
+ filter('<pre><code lang="gnuplot">This is a test</code></pre>')
+ end
- context "when an invalid language is specified" do
- it "highlights as plaintext" do
- result = filter('<pre><code lang="gnuplot">This is a test</code></pre>')
+ expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre>')
+ end
- expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre>')
+ include_examples "XSS prevention", "gnuplot"
end
- include_examples "XSS prevention", "gnuplot"
- end
+ context "languages that should be passed through" do
+ let(:delimiter) { described_class::LANG_PARAMS_DELIMITER }
+ let(:data_attr) { described_class::LANG_PARAMS_ATTR }
- context "languages that should be passed through" do
- let(:delimiter) { described_class::PARAMS_DELIMITER }
- let(:data_attr) { described_class::LANG_PARAMS_ATTR }
+ %w(math mermaid plantuml suggestion).each do |lang|
+ context "when #{lang} is specified" do
+ it "highlights as plaintext but with the correct language attribute and class" do
+ result = if Feature.enabled?(:use_cmark_renderer)
+ filter(%{<pre lang="#{lang}"><code>This is a test</code></pre>})
+ else
+ filter(%{<pre><code lang="#{lang}">This is a test</code></pre>})
+ end
- %w(math mermaid plantuml suggestion).each do |lang|
- context "when #{lang} is specified" do
- it "highlights as plaintext but with the correct language attribute and class" do
- result = filter(%{<pre><code lang="#{lang}">This is a test</code></pre>})
+ expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
+ end
- expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
+ include_examples "XSS prevention", lang
end
- include_examples "XSS prevention", lang
+ context "when #{lang} has extra params" do
+ let(:lang_params) { 'foo-bar-kux' }
+
+ let(:xss_lang) do
+ if Feature.enabled?(:use_cmark_renderer)
+ "#{lang} data-meta=\"foo-bar-kux\"&lt;script&gt;alert(1)&lt;/script&gt;"
+ else
+ "#{lang}#{described_class::LANG_PARAMS_DELIMITER}&lt;script&gt;alert(1)&lt;/script&gt;"
+ end
+ end
+
+ it "includes data-lang-params tag with extra information" do
+ result = if Feature.enabled?(:use_cmark_renderer)
+ filter(%{<pre lang="#{lang}" data-meta="#{lang_params}"><code>This is a test</code></pre>})
+ else
+ filter(%{<pre><code lang="#{lang}#{delimiter}#{lang_params}">This is a test</code></pre>})
+ end
+
+ expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
+ end
+
+ include_examples "XSS prevention", lang
+
+ if Feature.enabled?(:use_cmark_renderer)
+ include_examples "XSS prevention",
+ "#{lang} data-meta=\"foo-bar-kux\"&lt;script&gt;alert(1)&lt;/script&gt;"
+ else
+ include_examples "XSS prevention",
+ "#{lang}#{described_class::LANG_PARAMS_DELIMITER}&lt;script&gt;alert(1)&lt;/script&gt;"
+ end
+
+ include_examples "XSS prevention",
+ "#{lang} data-meta=\"foo-bar-kux\"<script>alert(1)</script>"
+ end
end
- context "when #{lang} has extra params" do
- let(:lang_params) { 'foo-bar-kux' }
+ context 'when multiple param delimiters are used' do
+ let(:lang) { 'suggestion' }
+ let(:lang_params) { '-1+10' }
- it "includes data-lang-params tag with extra information" do
- result = filter(%{<pre><code lang="#{lang}#{delimiter}#{lang_params}">This is a test</code></pre>})
+ let(:expected_result) do
+ %{<pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params} more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>}
+ end
- expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
+ context 'when delimiter is space' do
+ it 'delimits on the first appearance' do
+ if Feature.enabled?(:use_cmark_renderer)
+ result = filter(%{<pre lang="#{lang}" data-meta="#{lang_params} more-things"><code>This is a test</code></pre>})
+
+ expect(result.to_html).to eq(expected_result)
+ else
+ result = filter(%{<pre><code lang="#{lang}#{delimiter}#{lang_params}#{delimiter}more-things">This is a test</code></pre>})
+
+ expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params}#{delimiter}more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
+ end
+ end
end
- include_examples "XSS prevention", lang
- include_examples "XSS prevention",
- "#{lang}#{described_class::PARAMS_DELIMITER}&lt;script&gt;alert(1)&lt;/script&gt;"
- include_examples "XSS prevention",
- "#{lang}#{described_class::PARAMS_DELIMITER}<script>alert(1)</script>"
+ context 'when delimiter is colon' do
+ it 'delimits on the first appearance' do
+ result = filter(%{<pre lang="#{lang}#{delimiter}#{lang_params} more-things"><code>This is a test</code></pre>})
+
+ if Feature.enabled?(:use_cmark_renderer)
+ expect(result.to_html).to eq(expected_result)
+ else
+ expect(result.to_html).to eq(%{<pre class=\"code highlight js-syntax-highlight language-plaintext\" lang=\"plaintext\" v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">This is a test</span></code></pre>})
+ end
+ end
+ end
end
end
- context 'when multiple param delimiters are used' do
- let(:lang) { 'suggestion' }
- let(:lang_params) { '-1+10' }
+ context "when sourcepos metadata is available" do
+ it "includes it in the highlighted code block" do
+ result = filter('<pre data-sourcepos="1:1-3:3"><code lang="plaintext">This is a test</code></pre>')
- it "delimits on the first appearance" do
- result = filter(%{<pre><code lang="#{lang}#{delimiter}#{lang_params}#{delimiter}more-things">This is a test</code></pre>})
-
- expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params}#{delimiter}more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
+ expect(result.to_html).to eq('<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre>')
end
end
- end
- context "when sourcepos metadata is available" do
- it "includes it in the highlighted code block" do
- result = filter('<pre data-sourcepos="1:1-3:3"><code lang="plaintext">This is a test</code></pre>')
+ context "when Rouge lexing fails" do
+ before do
+ allow_next_instance_of(Rouge::Lexers::Ruby) do |instance|
+ allow(instance).to receive(:stream_tokens).and_raise(StandardError)
+ end
+ end
- expect(result.to_html).to eq('<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre>')
- end
- end
+ it "highlights as plaintext" do
+ result = if Feature.enabled?(:use_cmark_renderer)
+ filter('<pre lang="ruby"><code>This is a test</code></pre>')
+ else
+ filter('<pre><code lang="ruby">This is a test</code></pre>')
+ end
- context "when Rouge lexing fails" do
- before do
- allow_next_instance_of(Rouge::Lexers::Ruby) do |instance|
- allow(instance).to receive(:stream_tokens).and_raise(StandardError)
+ expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight" lang="" v-pre="true"><code><span id="LC1" class="line" lang="">This is a test</span></code></pre>')
end
+
+ include_examples "XSS prevention", "ruby"
end
- it "highlights as plaintext" do
- result = filter('<pre><code lang="ruby">This is a test</code></pre>')
+ context "when Rouge lexing fails after a retry" do
+ before do
+ allow_next_instance_of(Rouge::Lexers::PlainText) do |instance|
+ allow(instance).to receive(:stream_tokens).and_raise(StandardError)
+ end
+ end
- expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight" lang="" v-pre="true"><code><span id="LC1" class="line" lang="">This is a test</span></code></pre>')
- end
+ it "does not add highlighting classes" do
+ result = filter('<pre><code>This is a test</code></pre>')
+
+ expect(result.to_html).to eq('<pre><code>This is a test</code></pre>')
+ end
- include_examples "XSS prevention", "ruby"
+ include_examples "XSS prevention", "ruby"
+ end
end
- context "when Rouge lexing fails after a retry" do
+ context 'using ruby-based HTML renderer' do
before do
- allow_next_instance_of(Rouge::Lexers::PlainText) do |instance|
- allow(instance).to receive(:stream_tokens).and_raise(StandardError)
- end
+ stub_feature_flags(use_cmark_renderer: false)
end
- it "does not add highlighting classes" do
- result = filter('<pre><code>This is a test</code></pre>')
+ it_behaves_like 'renders correct markdown'
+ end
- expect(result.to_html).to eq('<pre><code>This is a test</code></pre>')
+ context 'using c-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: true)
end
- include_examples "XSS prevention", "ruby"
+ it_behaves_like 'renders correct markdown'
end
end
diff --git a/spec/lib/banzai/pipeline/emoji_pipeline_spec.rb b/spec/lib/banzai/pipeline/emoji_pipeline_spec.rb
index 6de9d65f1b2..8103846d4f7 100644
--- a/spec/lib/banzai/pipeline/emoji_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/emoji_pipeline_spec.rb
@@ -3,18 +3,20 @@
require 'spec_helper'
RSpec.describe Banzai::Pipeline::EmojiPipeline do
+ let(:emoji) { TanukiEmoji.find_by_alpha_code('100') }
+
def parse(text)
described_class.to_html(text, {})
end
it 'replaces emoji' do
- expected_result = "Hello world #{Gitlab::Emoji.gl_emoji_tag('100')}"
+ expected_result = "Hello world #{Gitlab::Emoji.gl_emoji_tag(emoji)}"
expect(parse('Hello world :100:')).to eq(expected_result)
end
it 'filters out HTML tags' do
- expected_result = "Hello &lt;b&gt;world&lt;/b&gt; #{Gitlab::Emoji.gl_emoji_tag('100')}"
+ expected_result = "Hello &lt;b&gt;world&lt;/b&gt; #{Gitlab::Emoji.gl_emoji_tag(emoji)}"
expect(parse('Hello <b>world</b> :100:')).to eq(expected_result)
end
diff --git a/spec/lib/banzai/pipeline/full_pipeline_spec.rb b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
index 7a335fad3f8..01bca7b23e8 100644
--- a/spec/lib/banzai/pipeline/full_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
@@ -31,29 +31,29 @@ RSpec.describe Banzai::Pipeline::FullPipeline do
describe 'footnotes' do
let(:project) { create(:project, :public) }
let(:html) { described_class.to_html(footnote_markdown, project: project) }
- let(:identifier) { html[/.*fnref1-(\d+).*/, 1] }
+ let(:identifier) { html[/.*fnref-1-(\d+).*/, 1] }
let(:footnote_markdown) do
<<~EOF
- first[^1] and second[^second] and twenty[^twenty]
+ first[^1] and second[^😄second] and twenty[^_twenty]
[^1]: one
- [^second]: two
- [^twenty]: twenty
+ [^😄second]: two
+ [^_twenty]: twenty
EOF
end
let(:filtered_footnote) do
- <<~EOF
- <p dir="auto">first<sup class="footnote-ref"><a href="#fn1-#{identifier}" id="fnref1-#{identifier}">1</a></sup> and second<sup class="footnote-ref"><a href="#fn2-#{identifier}" id="fnref2-#{identifier}">2</a></sup> and twenty<sup class="footnote-ref"><a href="#fn3-#{identifier}" id="fnref3-#{identifier}">3</a></sup></p>
+ <<~EOF.strip_heredoc
+ <p dir="auto">first<sup class="footnote-ref"><a href="#fn-1-#{identifier}" id="fnref-1-#{identifier}" data-footnote-ref="">1</a></sup> and second<sup class="footnote-ref"><a href="#fn-%F0%9F%98%84second-#{identifier}" id="fnref-%F0%9F%98%84second-#{identifier}" data-footnote-ref="">2</a></sup> and twenty<sup class="footnote-ref"><a href="#fn-_twenty-#{identifier}" id="fnref-_twenty-#{identifier}" data-footnote-ref="">3</a></sup></p>
- <section class="footnotes"><ol>
- <li id="fn1-#{identifier}">
- <p>one <a href="#fnref1-#{identifier}" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <section class="footnotes" data-footnotes><ol>
+ <li id="fn-1-#{identifier}">
+ <p>one <a href="#fnref-1-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref=""><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
- <li id="fn2-#{identifier}">
- <p>two <a href="#fnref2-#{identifier}" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <li id="fn-%F0%9F%98%84second-#{identifier}">
+ <p>two <a href="#fnref-%F0%9F%98%84second-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref=""><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
- <li id="fn3-#{identifier}">
- <p>twenty <a href="#fnref3-#{identifier}" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <li id="fn-_twenty-#{identifier}">
+ <p>twenty <a href="#fnref-_twenty-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref=""><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
</ol></section>
EOF
@@ -64,6 +64,47 @@ RSpec.describe Banzai::Pipeline::FullPipeline do
expect(html.lines.map(&:strip).join("\n")).to eq filtered_footnote
end
+
+ context 'using ruby-based HTML renderer' do
+ let(:html) { described_class.to_html(footnote_markdown, project: project) }
+ let(:identifier) { html[/.*fnref1-(\d+).*/, 1] }
+ let(:footnote_markdown) do
+ <<~EOF
+ first[^1] and second[^second] and twenty[^twenty]
+ [^1]: one
+ [^second]: two
+ [^twenty]: twenty
+ EOF
+ end
+
+ let(:filtered_footnote) do
+ <<~EOF
+ <p dir="auto">first<sup class="footnote-ref"><a href="#fn1-#{identifier}" id="fnref1-#{identifier}">1</a></sup> and second<sup class="footnote-ref"><a href="#fn2-#{identifier}" id="fnref2-#{identifier}">2</a></sup> and twenty<sup class="footnote-ref"><a href="#fn3-#{identifier}" id="fnref3-#{identifier}">3</a></sup></p>
+
+ <section class="footnotes"><ol>
+ <li id="fn1-#{identifier}">
+ <p>one <a href="#fnref1-#{identifier}" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ </li>
+ <li id="fn2-#{identifier}">
+ <p>two <a href="#fnref2-#{identifier}" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ </li>
+ <li id="fn3-#{identifier}">
+ <p>twenty <a href="#fnref3-#{identifier}" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ </li>
+ </ol></section>
+ EOF
+ end
+
+ before do
+ stub_feature_flags(use_cmark_renderer: false)
+ end
+
+ it 'properly adds the necessary ids and classes' do
+ stub_commonmark_sourcepos_disabled
+
+ expect(html.lines.map(&:strip).join("\n")).to eq filtered_footnote
+ end
+ end
end
describe 'links are detected as malicious' do
diff --git a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
index 4903f624469..394fcc06eba 100644
--- a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
@@ -5,18 +5,7 @@ require 'spec_helper'
RSpec.describe Banzai::Pipeline::PlainMarkdownPipeline do
using RSpec::Parameterized::TableSyntax
- describe 'backslash escapes' do
- let_it_be(:project) { create(:project, :public) }
- let_it_be(:issue) { create(:issue, project: project) }
-
- def correct_html_included(markdown, expected)
- result = described_class.call(markdown, {})
-
- expect(result[:output].to_html).to include(expected)
-
- result
- end
-
+ shared_examples_for 'renders correct markdown' do
describe 'CommonMark tests', :aggregate_failures do
it 'converts all reference punctuation to literals' do
reference_chars = Banzai::Filter::MarkdownPreEscapeFilter::REFERENCE_CHARACTERS
@@ -32,7 +21,7 @@ RSpec.describe Banzai::Pipeline::PlainMarkdownPipeline do
expect(result[:escaped_literals]).to be_truthy
end
- it 'ensure we handle all the GitLab reference characters' do
+ it 'ensure we handle all the GitLab reference characters', :eager_load do
reference_chars = ObjectSpace.each_object(Class).map do |klass|
next unless klass.included_modules.include?(Referable)
next unless klass.respond_to?(:reference_prefix)
@@ -79,10 +68,19 @@ RSpec.describe Banzai::Pipeline::PlainMarkdownPipeline do
end
describe 'work in all other contexts, including URLs and link titles, link references, and info strings in fenced code blocks' do
+ let(:markdown) { %Q(``` foo\\@bar\nfoo\n```) }
+
+ it 'renders correct html' do
+ if Feature.enabled?(:use_cmark_renderer)
+ correct_html_included(markdown, %Q(<pre data-sourcepos="1:1-3:3" lang="foo@bar"><code>foo\n</code></pre>))
+ else
+ correct_html_included(markdown, %Q(<code lang="foo@bar">foo\n</code>))
+ end
+ end
+
where(:markdown, :expected) do
%q![foo](/bar\@ "\@title")! | %q(<a href="/bar@" title="@title">foo</a>)
%Q![foo]\n\n[foo]: /bar\\@ "\\@title"! | %q(<a href="/bar@" title="@title">foo</a>)
- %Q(``` foo\\@bar\nfoo\n```) | %Q(<code lang="foo@bar">foo\n</code>)
end
with_them do
@@ -91,4 +89,33 @@ RSpec.describe Banzai::Pipeline::PlainMarkdownPipeline do
end
end
end
+
+ describe 'backslash escapes' do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:issue) { create(:issue, project: project) }
+
+ def correct_html_included(markdown, expected)
+ result = described_class.call(markdown, {})
+
+ expect(result[:output].to_html).to include(expected)
+
+ result
+ end
+
+ context 'using ruby-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: false)
+ end
+
+ it_behaves_like 'renders correct markdown'
+ end
+
+ context 'using c-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: true)
+ end
+
+ it_behaves_like 'renders correct markdown'
+ end
+ end
end
diff --git a/spec/lib/banzai/renderer_spec.rb b/spec/lib/banzai/renderer_spec.rb
index 52bf3087875..d487268da78 100644
--- a/spec/lib/banzai/renderer_spec.rb
+++ b/spec/lib/banzai/renderer_spec.rb
@@ -84,6 +84,24 @@ RSpec.describe Banzai::Renderer do
end
end
+ describe '#cacheless_render' do
+ context 'without cache' do
+ let(:object) { fake_object(fresh: false) }
+ let(:histogram) { double('prometheus histogram') }
+
+ it 'returns cacheless render field' do
+ allow(renderer).to receive(:render_result).and_return(output: 'test')
+ allow(renderer).to receive(:real_duration_histogram).and_return(histogram)
+ allow(renderer).to receive(:cpu_duration_histogram).and_return(histogram)
+
+ expect(renderer).to receive(:render_result).with('test', {})
+ expect(histogram).to receive(:observe).twice
+
+ renderer.cacheless_render('test')
+ end
+ end
+ end
+
describe '#post_process' do
let(:context_options) { {} }
let(:html) { 'Consequatur aperiam et nesciunt modi aut assumenda quo id. '}
diff --git a/spec/lib/bulk_imports/common/pipelines/milestones_pipeline_spec.rb b/spec/lib/bulk_imports/common/pipelines/milestones_pipeline_spec.rb
new file mode 100644
index 00000000000..9f71175f46f
--- /dev/null
+++ b/spec/lib/bulk_imports/common/pipelines/milestones_pipeline_spec.rb
@@ -0,0 +1,154 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Pipelines::MilestonesPipeline do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:bulk_import) { create(:bulk_import, user: user) }
+ let(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let(:context) { BulkImports::Pipeline::Context.new(tracker) }
+ let(:source_project_id) { nil } # if set, then exported_milestone is a project milestone
+ let(:source_group_id) { nil } # if set, then exported_milestone is a group milestone
+ let(:exported_milestone_for_project) do
+ exported_milestone_for_group.merge(
+ 'events' => [{
+ 'project_id' => source_project_id,
+ 'author_id' => 9,
+ 'created_at' => "2021-08-12T19:12:49.810Z",
+ 'updated_at' => "2021-08-12T19:12:49.810Z",
+ 'target_type' => "Milestone",
+ 'group_id' => source_group_id,
+ 'fingerprint' => 'f270eb9b27d0',
+ 'id' => 66,
+ 'action' => "created"
+ }]
+ )
+ end
+
+ let(:exported_milestone_for_group) do
+ {
+ 'id' => 1,
+ 'title' => "v1.0",
+ 'project_id' => source_project_id,
+ 'description' => "Amet velit repellat ut rerum aut cum.",
+ 'due_date' => "2019-11-22",
+ 'created_at' => "2019-11-20T17:02:14.296Z",
+ 'updated_at' => "2019-11-20T17:02:14.296Z",
+ 'state' => "active",
+ 'iid' => 2,
+ 'start_date' => "2019-11-21",
+ 'group_id' => source_group_id
+ }
+ end
+
+ before do
+ group.add_owner(user)
+
+ allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: exported_milestones))
+ end
+ end
+
+ subject { described_class.new(context) }
+
+ shared_examples 'bulk_imports milestones pipeline' do
+ let(:tested_entity) { nil }
+
+ describe '#run' do
+ it 'imports milestones into destination' do
+ expect { subject.run }.to change(Milestone, :count).by(1)
+
+ imported_milestone = tested_entity.milestones.first
+
+ expect(imported_milestone.title).to eq("v1.0")
+ expect(imported_milestone.description).to eq("Amet velit repellat ut rerum aut cum.")
+ expect(imported_milestone.due_date.to_s).to eq("2019-11-22")
+ expect(imported_milestone.created_at).to eq("2019-11-20T17:02:14.296Z")
+ expect(imported_milestone.updated_at).to eq("2019-11-20T17:02:14.296Z")
+ expect(imported_milestone.start_date.to_s).to eq("2019-11-21")
+ end
+ end
+
+ describe '#load' do
+ context 'when milestone is not persisted' do
+ it 'saves the milestone' do
+ milestone = build(:milestone, group: group)
+
+ expect(milestone).to receive(:save!)
+
+ subject.load(context, milestone)
+ end
+ end
+
+ context 'when milestone is persisted' do
+ it 'does not save milestone' do
+ milestone = create(:milestone, group: group)
+
+ expect(milestone).not_to receive(:save!)
+
+ subject.load(context, milestone)
+ end
+ end
+
+ context 'when milestone is missing' do
+ it 'returns' do
+ expect(subject.load(context, nil)).to be_nil
+ end
+ end
+ end
+ end
+
+ context 'group milestone' do
+ let(:exported_milestones) { [[exported_milestone_for_group, 0]] }
+ let(:entity) do
+ create(
+ :bulk_import_entity,
+ group: group,
+ bulk_import: bulk_import,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Group',
+ destination_namespace: group.full_path
+ )
+ end
+
+ it_behaves_like 'bulk_imports milestones pipeline' do
+ let(:tested_entity) { group }
+ let(:source_group_id) { 1 }
+ end
+ end
+
+ context 'project milestone' do
+ let(:project) { create(:project, group: group) }
+ let(:exported_milestones) { [[exported_milestone_for_project, 0]] }
+
+ let(:entity) do
+ create(
+ :bulk_import_entity,
+ :project_entity,
+ project: project,
+ bulk_import: bulk_import,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Project',
+ destination_namespace: group.full_path
+ )
+ end
+
+ it_behaves_like 'bulk_imports milestones pipeline' do
+ let(:tested_entity) { project }
+ let(:source_project_id) { 1 }
+
+ it 'imports events' do
+ subject.run
+
+ imported_event = tested_entity.milestones.first.events.first
+
+ expect(imported_event.created_at).to eq("2021-08-12T19:12:49.810Z")
+ expect(imported_event.updated_at).to eq("2021-08-12T19:12:49.810Z")
+ expect(imported_event.target_type).to eq("Milestone")
+ expect(imported_event.fingerprint).to eq("f270eb9b27d0")
+ expect(imported_event.action).to eq("created")
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb b/spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb
new file mode 100644
index 00000000000..a3cc866a406
--- /dev/null
+++ b/spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Pipelines::UploadsPipeline do
+ let_it_be(:tmpdir) { Dir.mktmpdir }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:entity) { create(:bulk_import_entity, :project_entity, project: project, source_full_path: 'test') }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+ let_it_be(:uploads_dir_path) { File.join(tmpdir, '72a497a02fe3ee09edae2ed06d390038') }
+ let_it_be(:upload_file_path) { File.join(uploads_dir_path, 'upload.txt')}
+
+ subject(:pipeline) { described_class.new(context) }
+
+ before do
+ stub_uploads_object_storage(FileUploader)
+
+ FileUtils.mkdir_p(uploads_dir_path)
+ FileUtils.touch(upload_file_path)
+ end
+
+ after do
+ FileUtils.remove_entry(tmpdir) if Dir.exist?(tmpdir)
+ end
+
+ describe '#run' do
+ it 'imports uploads into destination portable and removes tmpdir' do
+ allow(Dir).to receive(:mktmpdir).with('bulk_imports').and_return(tmpdir)
+ allow(pipeline).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [upload_file_path]))
+
+ pipeline.run
+
+ expect(project.uploads.map { |u| u.retrieve_uploader.filename }).to include('upload.txt')
+
+ expect(Dir.exist?(tmpdir)).to eq(false)
+ end
+ end
+
+ describe '#extract' do
+ it 'downloads & extracts upload paths' do
+ allow(Dir).to receive(:mktmpdir).and_return(tmpdir)
+ expect(pipeline).to receive(:untar_zxf)
+ file_download_service = instance_double("BulkImports::FileDownloadService")
+
+ expect(BulkImports::FileDownloadService)
+ .to receive(:new)
+ .with(
+ configuration: context.configuration,
+ relative_url: "/projects/test/export_relations/download?relation=uploads",
+ dir: tmpdir,
+ filename: 'uploads.tar.gz')
+ .and_return(file_download_service)
+
+ expect(file_download_service).to receive(:execute)
+
+ extracted_data = pipeline.extract(context)
+
+ expect(extracted_data.data).to contain_exactly(uploads_dir_path, upload_file_path)
+ end
+ end
+
+ describe '#load' do
+ it 'creates a file upload' do
+ expect { pipeline.load(context, upload_file_path) }.to change { project.uploads.count }.by(1)
+ end
+
+ context 'when dynamic path is nil' do
+ it 'returns' do
+ expect { pipeline.load(context, File.join(tmpdir, 'test')) }.not_to change { project.uploads.count }
+ end
+ end
+
+ context 'when path is a directory' do
+ it 'returns' do
+ expect { pipeline.load(context, uploads_dir_path) }.not_to change { project.uploads.count }
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/common/pipelines/wiki_pipeline_spec.rb b/spec/lib/bulk_imports/common/pipelines/wiki_pipeline_spec.rb
new file mode 100644
index 00000000000..0eefb7390dc
--- /dev/null
+++ b/spec/lib/bulk_imports/common/pipelines/wiki_pipeline_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Pipelines::WikiPipeline do
+ describe '#run' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:parent) { create(:project) }
+
+ let_it_be(:entity) do
+ create(
+ :bulk_import_entity,
+ :project_entity,
+ bulk_import: bulk_import,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Wiki',
+ destination_namespace: parent.full_path,
+ project: parent
+ )
+ end
+
+ it_behaves_like 'wiki pipeline imports a wiki for an entity'
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/graphql/get_milestones_query_spec.rb b/spec/lib/bulk_imports/groups/graphql/get_milestones_query_spec.rb
deleted file mode 100644
index 7a0f964c5f3..00000000000
--- a/spec/lib/bulk_imports/groups/graphql/get_milestones_query_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BulkImports::Groups::Graphql::GetMilestonesQuery do
- it 'has a valid query' do
- tracker = create(:bulk_import_tracker)
- context = BulkImports::Pipeline::Context.new(tracker)
-
- query = GraphQL::Query.new(
- GitlabSchema,
- described_class.to_s,
- variables: described_class.variables(context)
- )
- result = GitlabSchema.static_validator.validate(query)
-
- expect(result[:errors]).to be_empty
- end
-
- describe '#data_path' do
- it 'returns data path' do
- expected = %w[data group milestones nodes]
-
- expect(described_class.data_path).to eq(expected)
- end
- end
-
- describe '#page_info_path' do
- it 'returns pagination information path' do
- expected = %w[data group milestones page_info]
-
- expect(described_class.page_info_path).to eq(expected)
- end
- end
-end
diff --git a/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb b/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb
index de0b56045b3..69363bf0866 100644
--- a/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb
+++ b/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb
@@ -11,20 +11,66 @@ RSpec.describe BulkImports::Groups::Loaders::GroupLoader do
let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
let(:service_double) { instance_double(::Groups::CreateService) }
- let(:data) { { foo: :bar } }
+ let(:data) { { 'path' => 'test' } }
subject { described_class.new }
+ context 'when path is missing' do
+ it 'raises an error' do
+ expect { subject.load(context, {}) }.to raise_error(described_class::GroupCreationError, 'Path is missing')
+ end
+ end
+
+ context 'when destination namespace is not a group' do
+ it 'raises an error' do
+ entity.update!(destination_namespace: user.namespace.path)
+
+ expect { subject.load(context, data) }.to raise_error(described_class::GroupCreationError, 'Destination is not a group')
+ end
+ end
+
+ context 'when group exists' do
+ it 'raises an error' do
+ group1 = create(:group)
+ group2 = create(:group, parent: group1)
+ entity.update!(destination_namespace: group1.full_path)
+ data = { 'path' => group2.path }
+
+ expect { subject.load(context, data) }.to raise_error(described_class::GroupCreationError, 'Group exists')
+ end
+ end
+
+ context 'when there are other group errors' do
+ it 'raises an error with those errors' do
+ group = ::Group.new
+ group.validate
+ expected_errors = group.errors.full_messages.to_sentence
+
+ expect(::Groups::CreateService)
+ .to receive(:new)
+ .with(context.current_user, data)
+ .and_return(service_double)
+
+ expect(service_double).to receive(:execute).and_return(group)
+ expect(entity).not_to receive(:update!)
+
+ expect { subject.load(context, data) }.to raise_error(described_class::GroupCreationError, expected_errors)
+ end
+ end
+
context 'when user can create group' do
shared_examples 'calls Group Create Service to create a new group' do
it 'calls Group Create Service to create a new group' do
+ group_double = instance_double(::Group)
+
expect(::Groups::CreateService)
.to receive(:new)
.with(context.current_user, data)
.and_return(service_double)
- expect(service_double).to receive(:execute)
- expect(entity).to receive(:update!)
+ expect(service_double).to receive(:execute).and_return(group_double)
+ expect(group_double).to receive(:errors).and_return([])
+ expect(entity).to receive(:update!).with(group: group_double)
subject.load(context, data)
end
@@ -40,7 +86,7 @@ RSpec.describe BulkImports::Groups::Loaders::GroupLoader do
context 'when there is parent group' do
let(:parent) { create(:group) }
- let(:data) { { 'parent_id' => parent.id } }
+ let(:data) { { 'parent_id' => parent.id, 'path' => 'test' } }
before do
allow(Ability).to receive(:allowed?).with(user, :create_subgroup, parent).and_return(true)
@@ -55,7 +101,7 @@ RSpec.describe BulkImports::Groups::Loaders::GroupLoader do
it 'does not create new group' do
expect(::Groups::CreateService).not_to receive(:new)
- subject.load(context, data)
+ expect { subject.load(context, data) }.to raise_error(described_class::GroupCreationError, 'User not allowed to create group')
end
end
@@ -69,7 +115,7 @@ RSpec.describe BulkImports::Groups::Loaders::GroupLoader do
context 'when there is parent group' do
let(:parent) { create(:group) }
- let(:data) { { 'parent_id' => parent.id } }
+ let(:data) { { 'parent_id' => parent.id, 'path' => 'test' } }
before do
allow(Ability).to receive(:allowed?).with(user, :create_subgroup, parent).and_return(false)
diff --git a/spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb
deleted file mode 100644
index a8354e62459..00000000000
--- a/spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BulkImports::Groups::Pipelines::MilestonesPipeline do
- let_it_be(:user) { create(:user) }
- let_it_be(:group) { create(:group) }
- let_it_be(:bulk_import) { create(:bulk_import, user: user) }
- let_it_be(:filepath) { 'spec/fixtures/bulk_imports/gz/milestones.ndjson.gz' }
- let_it_be(:entity) do
- create(
- :bulk_import_entity,
- group: group,
- bulk_import: bulk_import,
- source_full_path: 'source/full/path',
- destination_name: 'My Destination Group',
- destination_namespace: group.full_path
- )
- end
-
- let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
- let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
-
- let(:tmpdir) { Dir.mktmpdir }
-
- before do
- FileUtils.copy_file(filepath, File.join(tmpdir, 'milestones.ndjson.gz'))
- group.add_owner(user)
- end
-
- subject { described_class.new(context) }
-
- describe '#run' do
- it 'imports group milestones into destination group and removes tmpdir' do
- allow(Dir).to receive(:mktmpdir).and_return(tmpdir)
- allow_next_instance_of(BulkImports::FileDownloadService) do |service|
- allow(service).to receive(:execute)
- end
-
- expect { subject.run }.to change(Milestone, :count).by(5)
- expect(group.milestones.pluck(:title)).to contain_exactly('v4.0', 'v3.0', 'v2.0', 'v1.0', 'v0.0')
- expect(File.directory?(tmpdir)).to eq(false)
- end
- end
-
- describe '#load' do
- context 'when milestone is not persisted' do
- it 'saves the milestone' do
- milestone = build(:milestone, group: group)
-
- expect(milestone).to receive(:save!)
-
- subject.load(context, milestone)
- end
- end
-
- context 'when milestone is persisted' do
- it 'does not save milestone' do
- milestone = create(:milestone, group: group)
-
- expect(milestone).not_to receive(:save!)
-
- subject.load(context, milestone)
- end
- end
-
- context 'when milestone is missing' do
- it 'returns' do
- expect(subject.load(context, nil)).to be_nil
- end
- end
- end
-end
diff --git a/spec/lib/bulk_imports/groups/stage_spec.rb b/spec/lib/bulk_imports/groups/stage_spec.rb
index b322b7b0edf..5719acac4d7 100644
--- a/spec/lib/bulk_imports/groups/stage_spec.rb
+++ b/spec/lib/bulk_imports/groups/stage_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe BulkImports::Groups::Stage do
[1, BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline],
[1, BulkImports::Groups::Pipelines::MembersPipeline],
[1, BulkImports::Common::Pipelines::LabelsPipeline],
- [1, BulkImports::Groups::Pipelines::MilestonesPipeline],
+ [1, BulkImports::Common::Pipelines::MilestonesPipeline],
[1, BulkImports::Groups::Pipelines::BadgesPipeline],
[2, BulkImports::Common::Pipelines::BoardsPipeline]
]
diff --git a/spec/lib/bulk_imports/ndjson_pipeline_spec.rb b/spec/lib/bulk_imports/ndjson_pipeline_spec.rb
index 7d156c2c3df..c5197fb29d9 100644
--- a/spec/lib/bulk_imports/ndjson_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/ndjson_pipeline_spec.rb
@@ -111,6 +111,7 @@ RSpec.describe BulkImports::NdjsonPipeline do
context = double(portable: group, current_user: user, import_export_config: config, bulk_import: import_double, entity: entity_double)
allow(subject).to receive(:import_export_config).and_return(config)
allow(subject).to receive(:context).and_return(context)
+ relation_object = double
expect(Gitlab::ImportExport::Group::RelationFactory)
.to receive(:create)
@@ -124,6 +125,8 @@ RSpec.describe BulkImports::NdjsonPipeline do
user: user,
excluded_keys: nil
)
+ .and_return(relation_object)
+ expect(relation_object).to receive(:assign_attributes).with(group: group)
subject.transform(context, data)
end
diff --git a/spec/lib/bulk_imports/projects/pipelines/external_pull_requests_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/external_pull_requests_pipeline_spec.rb
new file mode 100644
index 00000000000..8f610fcc2ae
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/pipelines/external_pull_requests_pipeline_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Pipelines::ExternalPullRequestsPipeline do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:bulk_import) { create(:bulk_import) }
+ let_it_be(:entity) { create(:bulk_import_entity, :project_entity, project: project, bulk_import: bulk_import) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ let(:attributes) { {} }
+ let(:external_pr) { project.external_pull_requests.last }
+ let(:external_pull_request) do
+ {
+ 'pull_request_iid' => 4,
+ 'source_branch' => 'feature',
+ 'target_branch' => 'main',
+ 'source_repository' => 'repository',
+ 'target_repository' => 'repository',
+ 'source_sha' => 'abc',
+ 'target_sha' => 'xyz',
+ 'status' => 'open',
+ 'created_at' => '2019-12-24T14:04:50.053Z',
+ 'updated_at' => '2019-12-24T14:05:18.138Z'
+ }.merge(attributes)
+ end
+
+ subject(:pipeline) { described_class.new(context) }
+
+ describe '#run' do
+ before do
+ allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
+ allow(extractor).to receive(:remove_tmp_dir)
+ allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [[external_pull_request, 0]]))
+ end
+
+ pipeline.run
+ end
+
+ it 'imports external pull request', :aggregate_failures do
+ expect(external_pr.pull_request_iid).to eq(external_pull_request['pull_request_iid'])
+ expect(external_pr.source_branch).to eq(external_pull_request['source_branch'])
+ expect(external_pr.target_branch).to eq(external_pull_request['target_branch'])
+ expect(external_pr.status).to eq(external_pull_request['status'])
+ expect(external_pr.created_at).to eq(external_pull_request['created_at'])
+ expect(external_pr.updated_at).to eq(external_pull_request['updated_at'])
+ end
+
+ context 'when status is closed' do
+ let(:attributes) { { 'status' => 'closed' } }
+
+ it 'imports closed external pull request' do
+ expect(external_pr.status).to eq(attributes['status'])
+ end
+ end
+
+ context 'when from fork' do
+ let(:attributes) { { 'source_repository' => 'source' } }
+
+ it 'does not create external pull request' do
+ expect(external_pr).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/pipelines/merge_requests_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/merge_requests_pipeline_spec.rb
new file mode 100644
index 00000000000..3f02356b41e
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/pipelines/merge_requests_pipeline_spec.rb
@@ -0,0 +1,297 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Pipelines::MergeRequestsPipeline do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :repository, group: group) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:entity) do
+ create(
+ :bulk_import_entity,
+ :project_entity,
+ project: project,
+ bulk_import: bulk_import,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Project',
+ destination_namespace: group.full_path
+ )
+ end
+
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ let(:mr) do
+ {
+ 'iid' => 7,
+ 'author_id' => 22,
+ 'source_project_id' => 1234,
+ 'target_project_id' => 1234,
+ 'title' => 'Imported MR',
+ 'description' => 'Description',
+ 'state' => 'opened',
+ 'source_branch' => 'feature',
+ 'target_branch' => 'main',
+ 'source_branch_sha' => 'ABCD',
+ 'target_branch_sha' => 'DCBA',
+ 'created_at' => '2020-06-14T15:02:47.967Z',
+ 'updated_at' => '2020-06-14T15:03:47.967Z',
+ 'merge_request_diff' => {
+ 'state' => 'collected',
+ 'base_commit_sha' => 'ae73cb07c9eeaf35924a10f713b364d32b2dd34f',
+ 'head_commit_sha' => 'a97f74ddaa848b707bea65441c903ae4bf5d844d',
+ 'start_commit_sha' => '9eea46b5c72ead701c22f516474b95049c9d9462',
+ 'merge_request_diff_commits' => [
+ {
+ 'sha' => 'COMMIT1',
+ 'relative_order' => 0,
+ 'message' => 'commit message',
+ 'authored_date' => '2014-08-06T08:35:52.000+02:00',
+ 'committed_date' => '2014-08-06T08:35:52.000+02:00',
+ 'commit_author' => {
+ 'name' => 'Commit Author',
+ 'email' => 'gitlab@example.com'
+ },
+ 'committer' => {
+ 'name' => 'Committer',
+ 'email' => 'committer@example.com'
+ }
+ }
+ ],
+ 'merge_request_diff_files' => [
+ {
+ 'relative_order' => 0,
+ 'utf8_diff' => '--- a/.gitignore\n+++ b/.gitignore\n@@ -1 +1 @@ test\n',
+ 'new_path' => '.gitignore',
+ 'old_path' => '.gitignore',
+ 'a_mode' => '100644',
+ 'b_mode' => '100644',
+ 'new_file' => false,
+ 'renamed_file' => false,
+ 'deleted_file' => false,
+ 'too_large' => false
+ }
+ ]
+ }
+ }.merge(attributes)
+ end
+
+ let(:attributes) { {} }
+ let(:imported_mr) { project.merge_requests.find_by_title(mr['title']) }
+
+ subject(:pipeline) { described_class.new(context) }
+
+ describe '#run' do
+ before do
+ group.add_owner(user)
+
+ allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
+ allow(extractor).to receive(:remove_tmp_dir)
+ allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [[mr, 0]]))
+ end
+
+ allow(project.repository).to receive(:fetch_source_branch!).and_return(true)
+ allow(project.repository).to receive(:branch_exists?).and_return(false)
+ allow(project.repository).to receive(:create_branch)
+
+ pipeline.run
+ end
+
+ it 'imports a merge request' do
+ expect(project.merge_requests.count).to eq(1)
+ expect(imported_mr.title).to eq(mr['title'])
+ expect(imported_mr.description).to eq(mr['description'])
+ expect(imported_mr.state).to eq(mr['state'])
+ expect(imported_mr.iid).to eq(mr['iid'])
+ expect(imported_mr.created_at).to eq(mr['created_at'])
+ expect(imported_mr.updated_at).to eq(mr['updated_at'])
+ expect(imported_mr.author).to eq(user)
+ end
+
+ context 'merge request state' do
+ context 'when mr is closed' do
+ let(:attributes) { { 'state' => 'closed' } }
+
+ it 'imported mr as closed' do
+ expect(imported_mr.state).to eq(attributes['state'])
+ end
+ end
+
+ context 'when mr is merged' do
+ let(:attributes) { { 'state' => 'merged' } }
+
+ it 'imported mr as merged' do
+ expect(imported_mr.state).to eq(attributes['state'])
+ end
+ end
+ end
+
+ context 'source & target project' do
+ it 'has the new project as target' do
+ expect(imported_mr.target_project).to eq(project)
+ end
+
+ it 'has the new project as source' do
+ expect(imported_mr.source_project).to eq(project)
+ end
+
+ context 'when source/target projects differ' do
+ let(:attributes) { { 'source_project_id' => 4321 } }
+
+ it 'has no source' do
+ expect(imported_mr.source_project).to be_nil
+ end
+
+ context 'when diff_head_sha is present' do
+ let(:attributes) { { 'diff_head_sha' => 'HEAD', 'source_project_id' => 4321 } }
+
+ it 'has the new project as source' do
+ expect(imported_mr.source_project).to eq(project)
+ end
+ end
+ end
+ end
+
+ context 'resource label events' do
+ let(:attributes) { { 'resource_label_events' => [{ 'action' => 'add', 'user_id' => 1 }] } }
+
+ it 'restores resource label events' do
+ expect(imported_mr.resource_label_events.first.action).to eq('add')
+ end
+ end
+
+ context 'award emoji' do
+ let(:attributes) { { 'award_emoji' => [{ 'name' => 'tada', 'user_id' => 22 }] } }
+
+ it 'has award emoji' do
+ expect(imported_mr.award_emoji.first.name).to eq(attributes['award_emoji'].first['name'])
+ end
+ end
+
+ context 'notes' do
+ let(:note) { imported_mr.notes.first }
+ let(:attributes) do
+ {
+ 'notes' => [
+ {
+ 'note' => 'Issue note',
+ 'note_html' => '<p>something else entirely</p>',
+ 'cached_markdown_version' => 917504,
+ 'author_id' => 22,
+ 'author' => { 'name' => 'User 22' },
+ 'created_at' => '2016-06-14T15:02:56.632Z',
+ 'updated_at' => '2016-06-14T15:02:47.770Z',
+ 'award_emoji' => [{ 'name' => 'clapper', 'user_id' => 22 }]
+ }
+ ]
+ }
+ end
+
+ it 'imports mr note' do
+ expect(note).to be_present
+ expect(note.note).to include('By User 22')
+ expect(note.note).to include(attributes['notes'].first['note'])
+ expect(note.author).to eq(user)
+ end
+
+ it 'has award emoji' do
+ emoji = note.award_emoji.first
+
+ expect(emoji.name).to eq('clapper')
+ expect(emoji.user).to eq(user)
+ end
+
+ it 'does not import note_html' do
+ expect(note.note_html).to match(attributes['notes'].first['note'])
+ expect(note.note_html).not_to match(attributes['notes'].first['note_html'])
+ end
+ end
+
+ context 'system note metadata' do
+ let(:attributes) do
+ {
+ 'notes' => [
+ {
+ 'note' => 'added 3 commits',
+ 'system' => true,
+ 'author_id' => 22,
+ 'author' => { 'name' => 'User 22' },
+ 'created_at' => '2016-06-14T15:02:56.632Z',
+ 'updated_at' => '2016-06-14T15:02:47.770Z',
+ 'system_note_metadata' => { 'action' => 'commit', 'commit_count' => 3 }
+ }
+ ]
+ }
+ end
+
+ it 'restores system note metadata' do
+ note = imported_mr.notes.first
+
+ expect(note.system).to eq(true)
+ expect(note.noteable_type).to eq('MergeRequest')
+ expect(note.system_note_metadata.action).to eq('commit')
+ expect(note.system_note_metadata.commit_count).to eq(3)
+ end
+ end
+
+ context 'diffs' do
+ it 'imports merge request diff' do
+ expect(imported_mr.merge_request_diff).to be_present
+ end
+
+ it 'has the correct data for merge request latest_merge_request_diff' do
+ expect(imported_mr.latest_merge_request_diff_id).to eq(imported_mr.merge_request_diffs.maximum(:id))
+ end
+
+ it 'imports diff files' do
+ expect(imported_mr.merge_request_diff.merge_request_diff_files.count).to eq(1)
+ end
+
+ context 'diff commits' do
+ it 'imports diff commits' do
+ expect(imported_mr.merge_request_diff.merge_request_diff_commits.count).to eq(1)
+ end
+
+ it 'assigns committer and author details to diff commits' do
+ commit = imported_mr.merge_request_diff.merge_request_diff_commits.first
+
+ expect(commit.commit_author_id).not_to be_nil
+ expect(commit.committer_id).not_to be_nil
+ end
+
+ it 'assigns the correct commit users to diff commits' do
+ commit = MergeRequestDiffCommit.find_by(sha: 'COMMIT1')
+
+ expect(commit.commit_author.name).to eq('Commit Author')
+ expect(commit.commit_author.email).to eq('gitlab@example.com')
+ expect(commit.committer.name).to eq('Committer')
+ expect(commit.committer.email).to eq('committer@example.com')
+ end
+ end
+ end
+
+ context 'labels' do
+ let(:attributes) do
+ {
+ 'label_links' => [
+ { 'label' => { 'title' => 'imported label 1', 'type' => 'ProjectLabel' } },
+ { 'label' => { 'title' => 'imported label 2', 'type' => 'ProjectLabel' } }
+ ]
+ }
+ end
+
+ it 'imports labels' do
+ expect(imported_mr.labels.pluck(:title)).to contain_exactly('imported label 1', 'imported label 2')
+ end
+ end
+
+ context 'milestone' do
+ let(:attributes) { { 'milestone' => { 'title' => 'imported milestone' } } }
+
+ it 'imports milestone' do
+ expect(imported_mr.milestone.title).to eq(attributes.dig('milestone', 'title'))
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/pipelines/protected_branches_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/protected_branches_pipeline_spec.rb
new file mode 100644
index 00000000000..7de2e266192
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/pipelines/protected_branches_pipeline_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Pipelines::ProtectedBranchesPipeline do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:entity) { create(:bulk_import_entity, :project_entity, project: project, bulk_import: bulk_import) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+ let_it_be(:protected_branch) do
+ {
+ 'name' => 'main',
+ 'created_at' => '2016-06-14T15:02:47.967Z',
+ 'updated_at' => '2016-06-14T15:02:47.967Z',
+ 'merge_access_levels' => [
+ {
+ 'access_level' => 40,
+ 'created_at' => '2016-06-15T15:02:47.967Z',
+ 'updated_at' => '2016-06-15T15:02:47.967Z'
+ }
+ ],
+ 'push_access_levels' => [
+ {
+ 'access_level' => 30,
+ 'created_at' => '2016-06-16T15:02:47.967Z',
+ 'updated_at' => '2016-06-16T15:02:47.967Z'
+ }
+ ]
+ }
+ end
+
+ subject(:pipeline) { described_class.new(context) }
+
+ describe '#run' do
+ it 'imports protected branch information' do
+ allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [protected_branch, 0]))
+ end
+
+ pipeline.run
+
+ imported_protected_branch = project.protected_branches.last
+ merge_access_level = imported_protected_branch.merge_access_levels.first
+ push_access_level = imported_protected_branch.push_access_levels.first
+
+ aggregate_failures do
+ expect(imported_protected_branch.name).to eq(protected_branch['name'])
+ expect(imported_protected_branch.updated_at).to eq(protected_branch['updated_at'])
+ expect(imported_protected_branch.created_at).to eq(protected_branch['created_at'])
+ expect(merge_access_level.access_level).to eq(protected_branch['merge_access_levels'].first['access_level'])
+ expect(merge_access_level.created_at).to eq(protected_branch['merge_access_levels'].first['created_at'])
+ expect(merge_access_level.updated_at).to eq(protected_branch['merge_access_levels'].first['updated_at'])
+ expect(push_access_level.access_level).to eq(protected_branch['push_access_levels'].first['access_level'])
+ expect(push_access_level.created_at).to eq(protected_branch['push_access_levels'].first['created_at'])
+ expect(push_access_level.updated_at).to eq(protected_branch['push_access_levels'].first['updated_at'])
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb
index af39ec7a11c..583485faf8d 100644
--- a/spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb
@@ -3,71 +3,72 @@
require 'spec_helper'
RSpec.describe BulkImports::Projects::Pipelines::RepositoryPipeline do
- describe '#run' do
- let_it_be(:user) { create(:user) }
- let_it_be(:parent) { create(:project) }
- let_it_be(:bulk_import) { create(:bulk_import, user: user) }
- let_it_be(:bulk_import_configuration) { create(:bulk_import_configuration, bulk_import: bulk_import) }
-
- let_it_be(:entity) do
- create(
- :bulk_import_entity,
- :project_entity,
- bulk_import: bulk_import,
- source_full_path: 'source/full/path',
- destination_name: 'My Destination Repository',
- destination_namespace: parent.full_path,
- project: parent
- )
- end
+ let_it_be(:user) { create(:user) }
+ let_it_be(:parent) { create(:project) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:bulk_import_configuration) { create(:bulk_import_configuration, bulk_import: bulk_import) }
+
+ let_it_be(:entity) do
+ create(
+ :bulk_import_entity,
+ :project_entity,
+ bulk_import: bulk_import,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Repository',
+ destination_namespace: parent.full_path,
+ project: parent
+ )
+ end
- let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
- let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
- context 'successfully imports repository' do
- let(:project_data) do
- {
- 'httpUrlToRepo' => 'http://test.git'
- }
- end
+ let(:extracted_data) { BulkImports::Pipeline::ExtractedData.new(data: project_data) }
- subject { described_class.new(context) }
+ subject(:pipeline) { described_class.new(context) }
+
+ before do
+ allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(extracted_data)
+ end
+ end
+
+ describe '#run' do
+ context 'successfully imports repository' do
+ let(:project_data) { { 'httpUrlToRepo' => 'http://test.git' } }
it 'imports new repository into destination project' do
- allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
- allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: project_data))
- end
+ url = project_data['httpUrlToRepo'].sub("://", "://oauth2:#{bulk_import_configuration.access_token}@")
- expect_next_instance_of(Gitlab::GitalyClient::RepositoryService) do |repository_service|
- url = project_data['httpUrlToRepo'].sub("://", "://oauth2:#{bulk_import_configuration.access_token}@")
- expect(repository_service).to receive(:import_repository).with(url).and_return 0
- end
+ expect(context.portable).to receive(:ensure_repository)
+ expect(context.portable.repository).to receive(:fetch_as_mirror).with(url)
- subject.run
+ pipeline.run
end
end
context 'blocked local networks' do
- let(:project_data) do
- {
- 'httpUrlToRepo' => 'http://localhost/foo.git'
- }
- end
+ let(:project_data) { { 'httpUrlToRepo' => 'http://localhost/foo.git' } }
- before do
+ it 'imports new repository into destination project' do
allow(Gitlab.config.gitlab).to receive(:host).and_return('notlocalhost.gitlab.com')
allow(Gitlab::CurrentSettings).to receive(:allow_local_requests_from_web_hooks_and_services?).and_return(false)
- allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
- allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: project_data))
- end
- end
- subject { described_class.new(context) }
+ pipeline.run
- it 'imports new repository into destination project' do
- subject.run
- expect(context.entity.failed?).to be_truthy
+ expect(context.entity.failed?).to eq(true)
end
end
end
+
+ describe '#after_run' do
+ it 'executes housekeeping service after import' do
+ service = instance_double(Repositories::HousekeepingService)
+
+ expect(Repositories::HousekeepingService).to receive(:new).with(context.portable, :gc).and_return(service)
+ expect(service).to receive(:execute)
+
+ pipeline.after_run(context)
+ end
+ end
end
diff --git a/spec/lib/bulk_imports/projects/stage_spec.rb b/spec/lib/bulk_imports/projects/stage_spec.rb
index c606cf7c556..e7670085f60 100644
--- a/spec/lib/bulk_imports/projects/stage_spec.rb
+++ b/spec/lib/bulk_imports/projects/stage_spec.rb
@@ -8,9 +8,15 @@ RSpec.describe BulkImports::Projects::Stage do
[0, BulkImports::Projects::Pipelines::ProjectPipeline],
[1, BulkImports::Projects::Pipelines::RepositoryPipeline],
[2, BulkImports::Common::Pipelines::LabelsPipeline],
+ [2, BulkImports::Common::Pipelines::MilestonesPipeline],
[3, BulkImports::Projects::Pipelines::IssuesPipeline],
[4, BulkImports::Common::Pipelines::BoardsPipeline],
- [5, BulkImports::Common::Pipelines::EntityFinisher]
+ [4, BulkImports::Projects::Pipelines::MergeRequestsPipeline],
+ [4, BulkImports::Projects::Pipelines::ExternalPullRequestsPipeline],
+ [4, BulkImports::Projects::Pipelines::ProtectedBranchesPipeline],
+ [5, BulkImports::Common::Pipelines::WikiPipeline],
+ [5, BulkImports::Common::Pipelines::UploadsPipeline],
+ [6, BulkImports::Common::Pipelines::EntityFinisher]
]
end
@@ -22,7 +28,8 @@ RSpec.describe BulkImports::Projects::Stage do
describe '#pipelines' do
it 'list all the pipelines with their stage number, ordered by stage' do
- expect(subject.pipelines).to eq(pipelines)
+ expect(subject.pipelines & pipelines).to contain_exactly(*pipelines)
+ expect(subject.pipelines.last.last).to eq(BulkImports::Common::Pipelines::EntityFinisher)
end
end
end
diff --git a/spec/lib/container_registry/client_spec.rb b/spec/lib/container_registry/client_spec.rb
index 47a8fcf5dd0..259d7d5ad13 100644
--- a/spec/lib/container_registry/client_spec.rb
+++ b/spec/lib/container_registry/client_spec.rb
@@ -279,7 +279,7 @@ RSpec.describe ContainerRegistry::Client do
it 'uploads the manifest and returns the digest' do
stub_request(:put, "http://container-registry/v2/path/manifests/tagA")
.with(body: "{\n \"foo\": \"bar\"\n}", headers: manifest_headers)
- .to_return(status: 200, body: "", headers: { 'docker-content-digest' => 'sha256:123' })
+ .to_return(status: 200, body: "", headers: { DependencyProxy::Manifest::DIGEST_HEADER => 'sha256:123' })
expect_new_faraday(timeout: false)
diff --git a/spec/lib/container_registry/tag_spec.rb b/spec/lib/container_registry/tag_spec.rb
index d6e6b254dd9..9b931ab6dbc 100644
--- a/spec/lib/container_registry/tag_spec.rb
+++ b/spec/lib/container_registry/tag_spec.rb
@@ -213,7 +213,7 @@ RSpec.describe ContainerRegistry::Tag do
before do
stub_request(:head, 'http://registry.gitlab/v2/group/test/manifests/tag')
.with(headers: headers)
- .to_return(status: 200, headers: { 'Docker-Content-Digest' => 'sha256:digest' })
+ .to_return(status: 200, headers: { DependencyProxy::Manifest::DIGEST_HEADER => 'sha256:digest' })
end
describe '#digest' do
diff --git a/spec/lib/error_tracking/collector/payload_validator_spec.rb b/spec/lib/error_tracking/collector/payload_validator_spec.rb
new file mode 100644
index 00000000000..852cf9eac6c
--- /dev/null
+++ b/spec/lib/error_tracking/collector/payload_validator_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ErrorTracking::Collector::PayloadValidator do
+ describe '#valid?' do
+ RSpec.shared_examples 'valid payload' do
+ it 'returns true' do
+ expect(described_class.new.valid?(payload)).to be_truthy
+ end
+ end
+
+ RSpec.shared_examples 'invalid payload' do
+ it 'returns false' do
+ expect(described_class.new.valid?(payload)).to be_falsey
+ end
+ end
+
+ context 'ruby payload' do
+ let(:payload) { Gitlab::Json.parse(fixture_file('error_tracking/parsed_event.json')) }
+
+ it_behaves_like 'valid payload'
+ end
+
+ context 'python payload' do
+ let(:payload) { Gitlab::Json.parse(fixture_file('error_tracking/python_event.json')) }
+
+ it_behaves_like 'valid payload'
+ end
+
+ context 'browser payload' do
+ let(:payload) { Gitlab::Json.parse(fixture_file('error_tracking/browser_event.json')) }
+
+ it_behaves_like 'valid payload'
+ end
+
+ context 'empty payload' do
+ let(:payload) { '' }
+
+ it_behaves_like 'invalid payload'
+ end
+
+ context 'invalid payload' do
+ let(:payload) { { 'foo' => 'bar' } }
+
+ it_behaves_like 'invalid payload'
+ end
+ end
+end
diff --git a/spec/lib/error_tracking/collector/sentry_request_parser_spec.rb b/spec/lib/error_tracking/collector/sentry_request_parser_spec.rb
index 6f12c6d25e0..06f4b64ce93 100644
--- a/spec/lib/error_tracking/collector/sentry_request_parser_spec.rb
+++ b/spec/lib/error_tracking/collector/sentry_request_parser_spec.rb
@@ -33,12 +33,5 @@ RSpec.describe ErrorTracking::Collector::SentryRequestParser do
context 'plain text sentry request' do
it_behaves_like 'valid parser'
end
-
- context 'gzip encoded sentry request' do
- let(:headers) { { 'Content-Encoding' => 'gzip' } }
- let(:body) { Zlib.gzip(raw_event) }
-
- it_behaves_like 'valid parser'
- end
end
end
diff --git a/spec/lib/feature/gitaly_spec.rb b/spec/lib/feature/gitaly_spec.rb
index 311589c3253..ed80e31e3cd 100644
--- a/spec/lib/feature/gitaly_spec.rb
+++ b/spec/lib/feature/gitaly_spec.rb
@@ -78,7 +78,9 @@ RSpec.describe Feature::Gitaly do
context 'when table does not exist' do
before do
- allow(::Gitlab::Database.main).to receive(:cached_table_exists?).and_return(false)
+ allow(Feature::FlipperFeature.database)
+ .to receive(:cached_table_exists?)
+ .and_return(false)
end
it 'returns an empty Hash' do
diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb
index 9d4820f9a4c..58e7292c125 100644
--- a/spec/lib/feature_spec.rb
+++ b/spec/lib/feature_spec.rb
@@ -102,12 +102,14 @@ RSpec.describe Feature, stub_feature_flags: false do
describe '.flipper' do
context 'when request store is inactive' do
- it 'memoizes the Flipper instance' do
+ it 'memoizes the Flipper instance but does not not enable Flipper memoization' do
expect(Flipper).to receive(:new).once.and_call_original
2.times do
- described_class.send(:flipper)
+ described_class.flipper
end
+
+ expect(described_class.flipper.adapter.memoizing?).to eq(false)
end
end
@@ -115,9 +117,11 @@ RSpec.describe Feature, stub_feature_flags: false do
it 'memoizes the Flipper instance' do
expect(Flipper).to receive(:new).once.and_call_original
- described_class.send(:flipper)
+ described_class.flipper
described_class.instance_variable_set(:@flipper, nil)
- described_class.send(:flipper)
+ described_class.flipper
+
+ expect(described_class.flipper.adapter.memoizing?).to eq(true)
end
end
end
@@ -310,7 +314,7 @@ RSpec.describe Feature, stub_feature_flags: false do
context 'when database exists' do
before do
- allow(Gitlab::Database.main).to receive(:exists?).and_return(true)
+ allow(ApplicationRecord.database).to receive(:exists?).and_return(true)
end
it 'checks the persisted status and returns false' do
@@ -322,7 +326,7 @@ RSpec.describe Feature, stub_feature_flags: false do
context 'when database does not exist' do
before do
- allow(Gitlab::Database.main).to receive(:exists?).and_return(false)
+ allow(ApplicationRecord.database).to receive(:exists?).and_return(false)
end
it 'returns false without checking the status in the database' do
diff --git a/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb b/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb
index 05833cf4ec4..b67425ae012 100644
--- a/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb
+++ b/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb
@@ -99,4 +99,15 @@ RSpec.describe Gitlab::UsageMetricDefinitionGenerator, :silence_stdout do
expect(YAML.safe_load(File.read(metric_definition_path))).to include("name" => "some name")
end
end
+
+ context 'with multiple file names' do
+ let(:key_paths) { ['counts_weekly.test_metric', 'counts_weekly.test1_metric'] }
+
+ it 'creates multiple files' do
+ described_class.new(key_paths, { 'dir' => dir }).invoke_all
+ files = Dir.glob(File.join(temp_dir, 'metrics/counts_7d/*_metric.yml'))
+
+ expect(files.count).to eq(2)
+ end
+ end
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder_spec.rb
new file mode 100644
index 00000000000..bf2f8d8159b
--- /dev/null
+++ b/spec/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder_spec.rb
@@ -0,0 +1,150 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Analytics::CycleAnalytics::Aggregated::BaseQueryBuilder do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:milestone) { create(:milestone, project: project) }
+ let_it_be(:user_1) { create(:user) }
+
+ let_it_be(:label_1) { create(:label, project: project) }
+ let_it_be(:label_2) { create(:label, project: project) }
+
+ let_it_be(:issue_1) { create(:issue, project: project, author: project.creator, labels: [label_1, label_2]) }
+ let_it_be(:issue_2) { create(:issue, project: project, milestone: milestone, assignees: [user_1]) }
+ let_it_be(:issue_3) { create(:issue, project: project) }
+ let_it_be(:issue_outside_project) { create(:issue) }
+
+ let_it_be(:stage) do
+ create(:cycle_analytics_project_stage,
+ project: project,
+ start_event_identifier: :issue_created,
+ end_event_identifier: :issue_deployed_to_production
+ )
+ end
+
+ let_it_be(:stage_event_1) do
+ create(:cycle_analytics_issue_stage_event,
+ stage_event_hash_id: stage.stage_event_hash_id,
+ group_id: group.id,
+ project_id: project.id,
+ issue_id: issue_1.id,
+ author_id: project.creator.id,
+ milestone_id: nil,
+ state_id: issue_1.state_id,
+ end_event_timestamp: 8.months.ago
+ )
+ end
+
+ let_it_be(:stage_event_2) do
+ create(:cycle_analytics_issue_stage_event,
+ stage_event_hash_id: stage.stage_event_hash_id,
+ group_id: group.id,
+ project_id: project.id,
+ issue_id: issue_2.id,
+ author_id: nil,
+ milestone_id: milestone.id,
+ state_id: issue_2.state_id
+ )
+ end
+
+ let_it_be(:stage_event_3) do
+ create(:cycle_analytics_issue_stage_event,
+ stage_event_hash_id: stage.stage_event_hash_id,
+ group_id: group.id,
+ project_id: project.id,
+ issue_id: issue_3.id,
+ author_id: nil,
+ milestone_id: milestone.id,
+ state_id: issue_3.state_id,
+ start_event_timestamp: 8.months.ago,
+ end_event_timestamp: nil
+ )
+ end
+
+ let(:params) do
+ {
+ from: 1.year.ago.to_date,
+ to: Date.today
+ }
+ end
+
+ subject(:issue_ids) { described_class.new(stage: stage, params: params).build.pluck(:issue_id) }
+
+ it 'scopes the query for the given project' do
+ expect(issue_ids).to match_array([issue_1.id, issue_2.id])
+ expect(issue_ids).not_to include([issue_outside_project.id])
+ end
+
+ describe 'author_username param' do
+ it 'returns stage events associated with the given author' do
+ params[:author_username] = project.creator.username
+
+ expect(issue_ids).to eq([issue_1.id])
+ end
+
+ it 'returns empty result when unknown author is given' do
+ params[:author_username] = 'no one'
+
+ expect(issue_ids).to be_empty
+ end
+ end
+
+ describe 'milestone_title param' do
+ it 'returns stage events associated with the milestone' do
+ params[:milestone_title] = milestone.title
+
+ expect(issue_ids).to eq([issue_2.id])
+ end
+
+ it 'returns empty result when unknown milestone is given' do
+ params[:milestone_title] = 'unknown milestone'
+
+ expect(issue_ids).to be_empty
+ end
+ end
+
+ describe 'label_name param' do
+ it 'returns stage events associated with multiple labels' do
+ params[:label_name] = [label_1.name, label_2.name]
+
+ expect(issue_ids).to eq([issue_1.id])
+ end
+
+ it 'does not include records with partial label match' do
+ params[:label_name] = [label_1.name, 'other label']
+
+ expect(issue_ids).to be_empty
+ end
+ end
+
+ describe 'assignee_username param' do
+ it 'returns stage events associated assignee' do
+ params[:assignee_username] = [user_1.username]
+
+ expect(issue_ids).to eq([issue_2.id])
+ end
+ end
+
+ describe 'timestamp filtering' do
+ before do
+ params[:from] = 1.year.ago
+ params[:to] = 6.months.ago
+ end
+
+ it 'filters by the end event time range' do
+ expect(issue_ids).to eq([issue_1.id])
+ end
+
+ context 'when in_progress items are requested' do
+ before do
+ params[:end_event_filter] = :in_progress
+ end
+
+ it 'filters by the start event time range' do
+ expect(issue_ids).to eq([issue_3.id])
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb
new file mode 100644
index 00000000000..045cdb129cb
--- /dev/null
+++ b/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb
@@ -0,0 +1,130 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Analytics::CycleAnalytics::Aggregated::RecordsFetcher do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:issue_1) { create(:issue, project: project) }
+ let_it_be(:issue_2) { create(:issue, project: project) }
+ let_it_be(:issue_3) { create(:issue, project: project) }
+
+ let_it_be(:stage_event_1) { create(:cycle_analytics_issue_stage_event, issue_id: issue_1.id, start_event_timestamp: 2.years.ago, end_event_timestamp: 1.year.ago) } # duration: 1 year
+ let_it_be(:stage_event_2) { create(:cycle_analytics_issue_stage_event, issue_id: issue_2.id, start_event_timestamp: 5.years.ago, end_event_timestamp: 2.years.ago) } # duration: 3 years
+ let_it_be(:stage_event_3) { create(:cycle_analytics_issue_stage_event, issue_id: issue_3.id, start_event_timestamp: 6.years.ago, end_event_timestamp: 3.months.ago) } # duration: 5+ years
+
+ let_it_be(:stage) { create(:cycle_analytics_project_stage, start_event_identifier: :issue_created, end_event_identifier: :issue_deployed_to_production, project: project) }
+
+ let(:params) { {} }
+
+ subject(:records_fetcher) do
+ described_class.new(stage: stage, query: Analytics::CycleAnalytics::IssueStageEvent.all, params: params)
+ end
+
+ shared_examples 'match returned records' do
+ it 'returns issues in the correct order' do
+ returned_iids = records_fetcher.serialized_records.pluck(:iid).map(&:to_i)
+
+ expect(returned_iids).to eq(expected_issue_ids)
+ end
+ end
+
+ describe '#serialized_records' do
+ describe 'sorting' do
+ context 'when sorting by end event DESC' do
+ let(:expected_issue_ids) { [issue_3.iid, issue_1.iid, issue_2.iid] }
+
+ before do
+ params[:sort] = :end_event
+ params[:direction] = :desc
+ end
+
+ it_behaves_like 'match returned records'
+ end
+
+ context 'when sorting by end event ASC' do
+ let(:expected_issue_ids) { [issue_2.iid, issue_1.iid, issue_3.iid] }
+
+ before do
+ params[:sort] = :end_event
+ params[:direction] = :asc
+ end
+
+ it_behaves_like 'match returned records'
+ end
+
+ context 'when sorting by duration DESC' do
+ let(:expected_issue_ids) { [issue_3.iid, issue_2.iid, issue_1.iid] }
+
+ before do
+ params[:sort] = :duration
+ params[:direction] = :desc
+ end
+
+ it_behaves_like 'match returned records'
+ end
+
+ context 'when sorting by duration ASC' do
+ let(:expected_issue_ids) { [issue_1.iid, issue_2.iid, issue_3.iid] }
+
+ before do
+ params[:sort] = :duration
+ params[:direction] = :asc
+ end
+
+ it_behaves_like 'match returned records'
+ end
+ end
+
+ describe 'pagination' do
+ let(:expected_issue_ids) { [issue_3.iid] }
+
+ before do
+ params[:sort] = :duration
+ params[:direction] = :asc
+ params[:page] = 2
+
+ stub_const('Gitlab::Analytics::CycleAnalytics::Aggregated::RecordsFetcher::MAX_RECORDS', 2)
+ end
+
+ it_behaves_like 'match returned records'
+ end
+
+ context 'when passing a block to serialized_records method' do
+ before do
+ params[:sort] = :duration
+ params[:direction] = :asc
+ end
+
+ it 'yields the underlying stage event scope' do
+ stage_event_records = []
+
+ records_fetcher.serialized_records do |scope|
+ stage_event_records.concat(scope.to_a)
+ end
+
+ expect(stage_event_records.map(&:issue_id)).to eq([issue_1.id, issue_2.id, issue_3.id])
+ end
+ end
+
+ context 'when the issue record no longer exists' do
+ it 'skips non-existing issue records' do
+ create(:cycle_analytics_issue_stage_event, {
+ issue_id: 0, # non-existing id
+ start_event_timestamp: 5.months.ago,
+ end_event_timestamp: 3.months.ago
+ })
+
+ stage_event_count = nil
+
+ records_fetcher.serialized_records do |scope|
+ stage_event_count = scope.to_a.size
+ end
+
+ issue_count = records_fetcher.serialized_records.to_a.size
+
+ expect(stage_event_count).to eq(4)
+ expect(issue_count).to eq(3)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/application_rate_limiter_spec.rb b/spec/lib/gitlab/application_rate_limiter_spec.rb
index 0fb99688d27..c74bcf8d678 100644
--- a/spec/lib/gitlab/application_rate_limiter_spec.rb
+++ b/spec/lib/gitlab/application_rate_limiter_spec.rb
@@ -3,76 +3,108 @@
require 'spec_helper'
RSpec.describe Gitlab::ApplicationRateLimiter do
- let(:redis) { double('redis') }
- let(:user) { create(:user) }
- let(:project) { create(:project) }
- let(:rate_limits) do
- {
- test_action: {
- threshold: 1,
- interval: 2.minutes
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+
+ subject { described_class }
+
+ describe '.throttled?', :clean_gitlab_redis_rate_limiting do
+ let(:rate_limits) do
+ {
+ test_action: {
+ threshold: 1,
+ interval: 2.minutes
+ },
+ another_action: {
+ threshold: 2,
+ interval: 3.minutes
+ }
}
- }
- end
+ end
- let(:key) { rate_limits.keys[0] }
+ before do
+ allow(described_class).to receive(:rate_limits).and_return(rate_limits)
+ end
- subject { described_class }
+ context 'when the key is invalid' do
+ context 'is provided as a Symbol' do
+ context 'but is not defined in the rate_limits Hash' do
+ it 'raises an InvalidKeyError exception' do
+ key = :key_not_in_rate_limits_hash
- before do
- allow(Gitlab::Redis::RateLimiting).to receive(:with).and_yield(redis)
- allow(described_class).to receive(:rate_limits).and_return(rate_limits)
- end
+ expect { subject.throttled?(key) }.to raise_error(Gitlab::ApplicationRateLimiter::InvalidKeyError)
+ end
+ end
+ end
- shared_examples 'action rate limiter' do
- it 'increases the throttle count and sets the expiration time' do
- expect(redis).to receive(:incr).with(cache_key).and_return(1)
- expect(redis).to receive(:expire).with(cache_key, 120)
+ context 'is provided as a String' do
+ context 'and is a String representation of an existing key in rate_limits Hash' do
+ it 'raises an InvalidKeyError exception' do
+ key = rate_limits.keys[0].to_s
- expect(subject.throttled?(key, scope: scope)).to be_falsy
- end
+ expect { subject.throttled?(key) }.to raise_error(Gitlab::ApplicationRateLimiter::InvalidKeyError)
+ end
+ end
- it 'returns true if the key is throttled' do
- expect(redis).to receive(:incr).with(cache_key).and_return(2)
- expect(redis).not_to receive(:expire)
+ context 'but is not defined in any form in the rate_limits Hash' do
+ it 'raises an InvalidKeyError exception' do
+ key = 'key_not_in_rate_limits_hash'
- expect(subject.throttled?(key, scope: scope)).to be_truthy
+ expect { subject.throttled?(key) }.to raise_error(Gitlab::ApplicationRateLimiter::InvalidKeyError)
+ end
+ end
+ end
end
- context 'when throttling is disabled' do
- it 'returns false and does not set expiration time' do
- expect(redis).not_to receive(:incr)
- expect(redis).not_to receive(:expire)
+ shared_examples 'throttles based on key and scope' do
+ let(:start_time) { Time.current.beginning_of_hour }
- expect(subject.throttled?(key, scope: scope, threshold: 0)).to be_falsy
+ it 'returns true when threshold is exceeded' do
+ travel_to(start_time) do
+ expect(subject.throttled?(:test_action, scope: scope)).to eq(false)
+ end
+
+ travel_to(start_time + 1.minute) do
+ expect(subject.throttled?(:test_action, scope: scope)).to eq(true)
+
+ # Assert that it does not affect other actions or scope
+ expect(subject.throttled?(:another_action, scope: scope)).to eq(false)
+ expect(subject.throttled?(:test_action, scope: [user])).to eq(false)
+ end
end
- end
- end
- context 'when the key is an array of only ActiveRecord models' do
- let(:scope) { [user, project] }
+ it 'returns false when interval has elapsed' do
+ travel_to(start_time) do
+ expect(subject.throttled?(:test_action, scope: scope)).to eq(false)
- let(:cache_key) do
- "application_rate_limiter:test_action:user:#{user.id}:project:#{project.id}"
- end
+ # another_action has a threshold of 3 so we simulate 2 requests
+ expect(subject.throttled?(:another_action, scope: scope)).to eq(false)
+ expect(subject.throttled?(:another_action, scope: scope)).to eq(false)
+ end
- it_behaves_like 'action rate limiter'
- end
+ travel_to(start_time + 2.minutes) do
+ expect(subject.throttled?(:test_action, scope: scope)).to eq(false)
- context 'when they key a combination of ActiveRecord models and strings' do
- let(:project) { create(:project, :public, :repository) }
- let(:commit) { project.repository.commit }
- let(:path) { 'app/controllers/groups_controller.rb' }
- let(:scope) { [project, commit, path] }
+ # Assert that another_action has its own interval that hasn't elapsed
+ expect(subject.throttled?(:another_action, scope: scope)).to eq(true)
+ end
+ end
+ end
+
+ context 'when using ActiveRecord models as scope' do
+ let(:scope) { [user, project] }
- let(:cache_key) do
- "application_rate_limiter:test_action:project:#{project.id}:commit:#{commit.sha}:#{path}"
+ it_behaves_like 'throttles based on key and scope'
end
- it_behaves_like 'action rate limiter'
+ context 'when using ActiveRecord models and strings as scope' do
+ let(:scope) { [project, 'app/controllers/groups_controller.rb'] }
+
+ it_behaves_like 'throttles based on key and scope'
+ end
end
- describe '#log_request' do
+ describe '.log_request' do
let(:file_path) { 'master/README.md' }
let(:type) { :raw_blob_request_limit }
let(:fullpath) { "/#{project.full_path}/raw/#{file_path}" }
@@ -102,7 +134,7 @@ RSpec.describe Gitlab::ApplicationRateLimiter do
end
context 'with a current_user' do
- let(:current_user) { create(:user) }
+ let(:current_user) { user }
let(:attributes) do
base_attributes.merge({
diff --git a/spec/lib/gitlab/asciidoc_spec.rb b/spec/lib/gitlab/asciidoc_spec.rb
index f3799c58fed..ac29bb22865 100644
--- a/spec/lib/gitlab/asciidoc_spec.rb
+++ b/spec/lib/gitlab/asciidoc_spec.rb
@@ -11,27 +11,13 @@ module Gitlab
allow_any_instance_of(ApplicationSetting).to receive(:current).and_return(::ApplicationSetting.create_from_defaults)
end
- context "without project" do
- let(:input) { '<b>ascii</b>' }
- let(:context) { {} }
- let(:html) { 'H<sub>2</sub>O' }
-
- it "converts the input using Asciidoctor and default options" do
- expected_asciidoc_opts = {
- safe: :secure,
- backend: :gitlab_html5,
- attributes: described_class::DEFAULT_ADOC_ATTRS.merge({ "kroki-server-url" => nil }),
- extensions: be_a(Proc)
- }
-
- expect(Asciidoctor).to receive(:convert)
- .with(input, expected_asciidoc_opts).and_return(html)
-
- expect(render(input, context)).to eq(html)
- end
+ shared_examples_for 'renders correct asciidoc' do
+ context "without project" do
+ let(:input) { '<b>ascii</b>' }
+ let(:context) { {} }
+ let(:html) { 'H<sub>2</sub>O' }
- context "with asciidoc_opts" do
- it "merges the options with default ones" do
+ it "converts the input using Asciidoctor and default options" do
expected_asciidoc_opts = {
safe: :secure,
backend: :gitlab_html5,
@@ -42,796 +28,839 @@ module Gitlab
expect(Asciidoctor).to receive(:convert)
.with(input, expected_asciidoc_opts).and_return(html)
- render(input, context)
+ expect(render(input, context)).to eq(html)
end
- end
- context "with requested path" do
- input = <<~ADOC
- Document name: {docname}.
- ADOC
-
- it "ignores {docname} when not available" do
- expect(render(input, {})).to include(input.strip)
- end
-
- [
- ['/', '', 'root'],
- ['README', 'README', 'just a filename'],
- ['doc/api/', '', 'a directory'],
- ['doc/api/README.adoc', 'README', 'a complete path']
- ].each do |path, basename, desc|
- it "sets {docname} for #{desc}" do
- expect(render(input, { requested_path: path })).to include(": #{basename}.")
- end
- end
- end
+ context "with asciidoc_opts" do
+ it "merges the options with default ones" do
+ expected_asciidoc_opts = {
+ safe: :secure,
+ backend: :gitlab_html5,
+ attributes: described_class::DEFAULT_ADOC_ATTRS.merge({ "kroki-server-url" => nil }),
+ extensions: be_a(Proc)
+ }
- context "XSS" do
- items = {
- 'link with extra attribute' => {
- input: 'link:mylink"onmouseover="alert(1)[Click Here]',
- output: "<div>\n<p><a href=\"mylink\">Click Here</a></p>\n</div>"
- },
- 'link with unsafe scheme' => {
- input: 'link:data://danger[Click Here]',
- output: "<div>\n<p><a>Click Here</a></p>\n</div>"
- },
- 'image with onerror' => {
- input: 'image:https://localhost.com/image.png[Alt text" onerror="alert(7)]',
- output: "<div>\n<p><span><a class=\"no-attachment-icon\" href=\"https://localhost.com/image.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt='Alt text\" onerror=\"alert(7)' class=\"lazy\" data-src=\"https://localhost.com/image.png\"></a></span></p>\n</div>"
- },
- 'fenced code with inline script' => {
- input: '```mypre"><script>alert(3)</script>',
- output: "<div>\n<div>\n<pre class=\"code highlight js-syntax-highlight language-plaintext\" lang=\"plaintext\" v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">\"&gt;</span></code></pre>\n</div>\n</div>"
- }
- }
+ expect(Asciidoctor).to receive(:convert)
+ .with(input, expected_asciidoc_opts).and_return(html)
- items.each do |name, data|
- it "does not convert dangerous #{name} into HTML" do
- expect(render(data[:input], context)).to include(data[:output])
+ render(input, context)
end
end
- it 'does not allow locked attributes to be overridden' do
+ context "with requested path" do
input = <<~ADOC
- {counter:max-include-depth:1234}
- <|-- {max-include-depth}
+ Document name: {docname}.
ADOC
- expect(render(input, {})).not_to include('1234')
- end
- end
+ it "ignores {docname} when not available" do
+ expect(render(input, {})).to include(input.strip)
+ end
- context "images" do
- it "does lazy load and link image" do
- input = 'image:https://localhost.com/image.png[]'
- output = "<div>\n<p><span><a class=\"no-attachment-icon\" href=\"https://localhost.com/image.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"image\" class=\"lazy\" data-src=\"https://localhost.com/image.png\"></a></span></p>\n</div>"
- expect(render(input, context)).to include(output)
+ [
+ ['/', '', 'root'],
+ ['README', 'README', 'just a filename'],
+ ['doc/api/', '', 'a directory'],
+ ['doc/api/README.adoc', 'README', 'a complete path']
+ ].each do |path, basename, desc|
+ it "sets {docname} for #{desc}" do
+ expect(render(input, { requested_path: path })).to include(": #{basename}.")
+ end
+ end
end
- it "does not automatically link image if link is explicitly defined" do
- input = 'image:https://localhost.com/image.png[link=https://gitlab.com]'
- output = "<div>\n<p><span><a href=\"https://gitlab.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"image\" class=\"lazy\" data-src=\"https://localhost.com/image.png\"></a></span></p>\n</div>"
- expect(render(input, context)).to include(output)
- end
- end
+ context "XSS" do
+ items = {
+ 'link with extra attribute' => {
+ input: 'link:mylink"onmouseover="alert(1)[Click Here]',
+ output: "<div>\n<p><a href=\"mylink\">Click Here</a></p>\n</div>"
+ },
+ 'link with unsafe scheme' => {
+ input: 'link:data://danger[Click Here]',
+ output: "<div>\n<p><a>Click Here</a></p>\n</div>"
+ },
+ 'image with onerror' => {
+ input: 'image:https://localhost.com/image.png[Alt text" onerror="alert(7)]',
+ output: "<div>\n<p><span><a class=\"no-attachment-icon\" href=\"https://localhost.com/image.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt='Alt text\" onerror=\"alert(7)' class=\"lazy\" data-src=\"https://localhost.com/image.png\"></a></span></p>\n</div>"
+ }
+ }
- context 'with admonition' do
- it 'preserves classes' do
- input = <<~ADOC
- NOTE: An admonition paragraph, like this note, grabs the reader’s attention.
- ADOC
+ items.each do |name, data|
+ it "does not convert dangerous #{name} into HTML" do
+ expect(render(data[:input], context)).to include(data[:output])
+ end
+ end
- output = <<~HTML
- <div class="admonitionblock">
- <table>
- <tr>
- <td class="icon">
- <i class="fa icon-note" title="Note"></i>
- </td>
- <td>
- An admonition paragraph, like this note, grabs the reader’s attention.
- </td>
- </tr>
- </table>
- </div>
- HTML
-
- expect(render(input, context)).to include(output.strip)
- end
- end
+ # `stub_feature_flags method` runs AFTER declaration of `items` above.
+ # So the spec in its current implementation won't pass.
+ # Move this test back to the items hash when removing `use_cmark_renderer` feature flag.
+ it "does not convert dangerous fenced code with inline script into HTML" do
+ input = '```mypre"><script>alert(3)</script>'
+ output =
+ if Feature.enabled?(:use_cmark_renderer)
+ "<div>\n<div>\n<pre class=\"code highlight js-syntax-highlight language-plaintext\" lang=\"plaintext\" v-pre=\"true\"><code></code></pre>\n</div>\n</div>"
+ else
+ "<div>\n<div>\n<pre class=\"code highlight js-syntax-highlight language-plaintext\" lang=\"plaintext\" v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">\"&gt;</span></code></pre>\n</div>\n</div>"
+ end
- context 'with passthrough' do
- it 'removes non heading ids' do
- input = <<~ADOC
- ++++
- <h2 id="foo">Title</h2>
- ++++
- ADOC
+ expect(render(input, context)).to include(output)
+ end
- output = <<~HTML
- <h2>Title</h2>
- HTML
+ it 'does not allow locked attributes to be overridden' do
+ input = <<~ADOC
+ {counter:max-include-depth:1234}
+ <|-- {max-include-depth}
+ ADOC
- expect(render(input, context)).to include(output.strip)
+ expect(render(input, {})).not_to include('1234')
+ end
end
- it 'removes non footnote def ids' do
- input = <<~ADOC
- ++++
- <div id="def">Footnote definition</div>
- ++++
- ADOC
-
- output = <<~HTML
- <div>Footnote definition</div>
- HTML
+ context "images" do
+ it "does lazy load and link image" do
+ input = 'image:https://localhost.com/image.png[]'
+ output = "<div>\n<p><span><a class=\"no-attachment-icon\" href=\"https://localhost.com/image.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"image\" class=\"lazy\" data-src=\"https://localhost.com/image.png\"></a></span></p>\n</div>"
+ expect(render(input, context)).to include(output)
+ end
- expect(render(input, context)).to include(output.strip)
+ it "does not automatically link image if link is explicitly defined" do
+ input = 'image:https://localhost.com/image.png[link=https://gitlab.com]'
+ output = "<div>\n<p><span><a href=\"https://gitlab.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"image\" class=\"lazy\" data-src=\"https://localhost.com/image.png\"></a></span></p>\n</div>"
+ expect(render(input, context)).to include(output)
+ end
end
- it 'removes non footnote ref ids' do
- input = <<~ADOC
- ++++
- <a id="ref">Footnote reference</a>
- ++++
- ADOC
-
- output = <<~HTML
- <a>Footnote reference</a>
- HTML
+ context 'with admonition' do
+ it 'preserves classes' do
+ input = <<~ADOC
+ NOTE: An admonition paragraph, like this note, grabs the reader’s attention.
+ ADOC
- expect(render(input, context)).to include(output.strip)
+ output = <<~HTML
+ <div class="admonitionblock">
+ <table>
+ <tr>
+ <td class="icon">
+ <i class="fa icon-note" title="Note"></i>
+ </td>
+ <td>
+ An admonition paragraph, like this note, grabs the reader’s attention.
+ </td>
+ </tr>
+ </table>
+ </div>
+ HTML
+
+ expect(render(input, context)).to include(output.strip)
+ end
end
- end
- context 'with footnotes' do
- it 'preserves ids and links' do
- input = <<~ADOC
- This paragraph has a footnote.footnote:[This is the text of the footnote.]
- ADOC
-
- output = <<~HTML
- <div>
- <p>This paragraph has a footnote.<sup>[<a id="_footnoteref_1" href="#_footnotedef_1" title="View footnote.">1</a>]</sup></p>
- </div>
- <div>
- <hr>
- <div id="_footnotedef_1">
- <a href="#_footnoteref_1">1</a>. This is the text of the footnote.
- </div>
- </div>
- HTML
-
- expect(render(input, context)).to include(output.strip)
- end
- end
+ context 'with passthrough' do
+ it 'removes non heading ids' do
+ input = <<~ADOC
+ ++++
+ <h2 id="foo">Title</h2>
+ ++++
+ ADOC
- context 'with section anchors' do
- it 'preserves ids and links' do
- input = <<~ADOC
- = Title
+ output = <<~HTML
+ <h2>Title</h2>
+ HTML
- == First section
+ expect(render(input, context)).to include(output.strip)
+ end
- This is the first section.
+ it 'removes non footnote def ids' do
+ input = <<~ADOC
+ ++++
+ <div id="def">Footnote definition</div>
+ ++++
+ ADOC
- == Second section
+ output = <<~HTML
+ <div>Footnote definition</div>
+ HTML
- This is the second section.
+ expect(render(input, context)).to include(output.strip)
+ end
- == Thunder âš¡ !
+ it 'removes non footnote ref ids' do
+ input = <<~ADOC
+ ++++
+ <a id="ref">Footnote reference</a>
+ ++++
+ ADOC
- This is the third section.
- ADOC
+ output = <<~HTML
+ <a>Footnote reference</a>
+ HTML
- output = <<~HTML
- <h1>Title</h1>
- <div>
- <h2 id="user-content-first-section">
- <a class="anchor" href="#user-content-first-section"></a>First section</h2>
- <div>
- <div>
- <p>This is the first section.</p>
- </div>
- </div>
- </div>
- <div>
- <h2 id="user-content-second-section">
- <a class="anchor" href="#user-content-second-section"></a>Second section</h2>
- <div>
- <div>
- <p>This is the second section.</p>
- </div>
- </div>
- </div>
- <div>
- <h2 id="user-content-thunder">
- <a class="anchor" href="#user-content-thunder"></a>Thunder âš¡ !</h2>
- <div>
- <div>
- <p>This is the third section.</p>
- </div>
- </div>
- </div>
- HTML
-
- expect(render(input, context)).to include(output.strip)
+ expect(render(input, context)).to include(output.strip)
+ end
end
- end
-
- context 'with xrefs' do
- it 'preserves ids' do
- input = <<~ADOC
- Learn how to xref:cross-references[use cross references].
- [[cross-references]]A link to another location within an AsciiDoc document or between AsciiDoc documents is called a cross reference (also referred to as an xref).
- ADOC
-
- output = <<~HTML
- <div>
- <p>Learn how to <a href="#cross-references">use cross references</a>.</p>
- </div>
- <div>
- <p><a id="user-content-cross-references"></a>A link to another location within an AsciiDoc document or between AsciiDoc documents is called a cross reference (also referred to as an xref).</p>
- </div>
- HTML
+ context 'with footnotes' do
+ it 'preserves ids and links' do
+ input = <<~ADOC
+ This paragraph has a footnote.footnote:[This is the text of the footnote.]
+ ADOC
- expect(render(input, context)).to include(output.strip)
+ output = <<~HTML
+ <div>
+ <p>This paragraph has a footnote.<sup>[<a id="_footnoteref_1" href="#_footnotedef_1" title="View footnote.">1</a>]</sup></p>
+ </div>
+ <div>
+ <hr>
+ <div id="_footnotedef_1">
+ <a href="#_footnoteref_1">1</a>. This is the text of the footnote.
+ </div>
+ </div>
+ HTML
+
+ expect(render(input, context)).to include(output.strip)
+ end
end
- end
- context 'with checklist' do
- it 'preserves classes' do
- input = <<~ADOC
- * [x] checked
- * [ ] not checked
- ADOC
+ context 'with section anchors' do
+ it 'preserves ids and links' do
+ input = <<~ADOC
+ = Title
+
+ == First section
+
+ This is the first section.
+
+ == Second section
+
+ This is the second section.
+
+ == Thunder âš¡ !
+
+ This is the third section.
+ ADOC
- output = <<~HTML
- <div>
- <ul class="checklist">
- <li>
- <p><i class="fa fa-check-square-o"></i> checked</p>
- </li>
- <li>
- <p><i class="fa fa-square-o"></i> not checked</p>
- </li>
- </ul>
- </div>
- HTML
-
- expect(render(input, context)).to include(output.strip)
+ output = <<~HTML
+ <h1>Title</h1>
+ <div>
+ <h2 id="user-content-first-section">
+ <a class="anchor" href="#user-content-first-section"></a>First section</h2>
+ <div>
+ <div>
+ <p>This is the first section.</p>
+ </div>
+ </div>
+ </div>
+ <div>
+ <h2 id="user-content-second-section">
+ <a class="anchor" href="#user-content-second-section"></a>Second section</h2>
+ <div>
+ <div>
+ <p>This is the second section.</p>
+ </div>
+ </div>
+ </div>
+ <div>
+ <h2 id="user-content-thunder">
+ <a class="anchor" href="#user-content-thunder"></a>Thunder âš¡ !</h2>
+ <div>
+ <div>
+ <p>This is the third section.</p>
+ </div>
+ </div>
+ </div>
+ HTML
+
+ expect(render(input, context)).to include(output.strip)
+ end
end
- end
-
- context 'with marks' do
- it 'preserves classes' do
- input = <<~ADOC
- Werewolves are allergic to #cassia cinnamon#.
-
- Did the werewolves read the [.small]#small print#?
- Where did all the [.underline.small]#cores# run off to?
+ context 'with xrefs' do
+ it 'preserves ids' do
+ input = <<~ADOC
+ Learn how to xref:cross-references[use cross references].
+
+ [[cross-references]]A link to another location within an AsciiDoc document or between AsciiDoc documents is called a cross reference (also referred to as an xref).
+ ADOC
- We need [.line-through]#ten# make that twenty VMs.
+ output = <<~HTML
+ <div>
+ <p>Learn how to <a href="#cross-references">use cross references</a>.</p>
+ </div>
+ <div>
+ <p><a id="user-content-cross-references"></a>A link to another location within an AsciiDoc document or between AsciiDoc documents is called a cross reference (also referred to as an xref).</p>
+ </div>
+ HTML
- [.big]##O##nce upon an infinite loop.
- ADOC
-
- output = <<~HTML
- <div>
- <p>Werewolves are allergic to <mark>cassia cinnamon</mark>.</p>
- </div>
- <div>
- <p>Did the werewolves read the <span class="small">small print</span>?</p>
- </div>
- <div>
- <p>Where did all the <span class="underline small">cores</span> run off to?</p>
- </div>
- <div>
- <p>We need <span class="line-through">ten</span> make that twenty VMs.</p>
- </div>
- <div>
- <p><span class="big">O</span>nce upon an infinite loop.</p>
- </div>
- HTML
-
- expect(render(input, context)).to include(output.strip)
+ expect(render(input, context)).to include(output.strip)
+ end
end
- end
- context 'with fenced block' do
- it 'highlights syntax' do
- input = <<~ADOC
- ```js
- console.log('hello world')
- ```
- ADOC
-
- output = <<~HTML
- <div>
- <div>
- <pre class="code highlight js-syntax-highlight language-javascript" lang="javascript" v-pre="true"><code><span id="LC1" class="line" lang="javascript"><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
- </div>
- </div>
- HTML
+ context 'with checklist' do
+ it 'preserves classes' do
+ input = <<~ADOC
+ * [x] checked
+ * [ ] not checked
+ ADOC
- expect(render(input, context)).to include(output.strip)
+ output = <<~HTML
+ <div>
+ <ul class="checklist">
+ <li>
+ <p><i class="fa fa-check-square-o"></i> checked</p>
+ </li>
+ <li>
+ <p><i class="fa fa-square-o"></i> not checked</p>
+ </li>
+ </ul>
+ </div>
+ HTML
+
+ expect(render(input, context)).to include(output.strip)
+ end
end
- end
- context 'with listing block' do
- it 'highlights syntax' do
- input = <<~ADOC
- [source,c++]
- .class.cpp
- ----
- #include <stdio.h>
-
- for (int i = 0; i < 5; i++) {
- std::cout<<"*"<<std::endl;
- }
- ----
- ADOC
+ context 'with marks' do
+ it 'preserves classes' do
+ input = <<~ADOC
+ Werewolves are allergic to #cassia cinnamon#.
+
+ Did the werewolves read the [.small]#small print#?
+
+ Where did all the [.underline.small]#cores# run off to?
+
+ We need [.line-through]#ten# make that twenty VMs.
+
+ [.big]##O##nce upon an infinite loop.
+ ADOC
- output = <<~HTML
- <div>
- <div>class.cpp</div>
- <div>
- <pre class="code highlight js-syntax-highlight language-cpp" lang="cpp" v-pre="true"><code><span id="LC1" class="line" lang="cpp"><span class="cp">#include &lt;stdio.h&gt;</span></span>
- <span id="LC2" class="line" lang="cpp"></span>
- <span id="LC3" class="line" lang="cpp"><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span></span>
- <span id="LC4" class="line" lang="cpp"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="o">&lt;&lt;</span><span class="s">"*"</span><span class="o">&lt;&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span></span>
- <span id="LC5" class="line" lang="cpp"><span class="p">}</span></span></code></pre>
- </div>
- </div>
- HTML
-
- expect(render(input, context)).to include(output.strip)
+ output = <<~HTML
+ <div>
+ <p>Werewolves are allergic to <mark>cassia cinnamon</mark>.</p>
+ </div>
+ <div>
+ <p>Did the werewolves read the <span class="small">small print</span>?</p>
+ </div>
+ <div>
+ <p>Where did all the <span class="underline small">cores</span> run off to?</p>
+ </div>
+ <div>
+ <p>We need <span class="line-through">ten</span> make that twenty VMs.</p>
+ </div>
+ <div>
+ <p><span class="big">O</span>nce upon an infinite loop.</p>
+ </div>
+ HTML
+
+ expect(render(input, context)).to include(output.strip)
+ end
end
- end
- context 'with stem block' do
- it 'does not apply syntax highlighting' do
- input = <<~ADOC
- [stem]
- ++++
- \sqrt{4} = 2
- ++++
- ADOC
+ context 'with fenced block' do
+ it 'highlights syntax' do
+ input = <<~ADOC
+ ```js
+ console.log('hello world')
+ ```
+ ADOC
- output = "<div>\n<div>\n\\$ qrt{4} = 2\\$\n</div>\n</div>"
+ output = <<~HTML
+ <div>
+ <div>
+ <pre class="code highlight js-syntax-highlight language-javascript" lang="javascript" v-pre="true"><code><span id="LC1" class="line" lang="javascript"><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
+ </div>
+ </div>
+ HTML
- expect(render(input, context)).to include(output)
+ expect(render(input, context)).to include(output.strip)
+ end
end
- end
- context 'external links' do
- it 'adds the `rel` attribute to the link' do
- output = render('link:https://google.com[Google]', context)
+ context 'with listing block' do
+ it 'highlights syntax' do
+ input = <<~ADOC
+ [source,c++]
+ .class.cpp
+ ----
+ #include <stdio.h>
+
+ for (int i = 0; i < 5; i++) {
+ std::cout<<"*"<<std::endl;
+ }
+ ----
+ ADOC
- expect(output).to include('rel="nofollow noreferrer noopener"')
+ output = <<~HTML
+ <div>
+ <div>class.cpp</div>
+ <div>
+ <pre class="code highlight js-syntax-highlight language-cpp" lang="cpp" v-pre="true"><code><span id="LC1" class="line" lang="cpp"><span class="cp">#include &lt;stdio.h&gt;</span></span>
+ <span id="LC2" class="line" lang="cpp"></span>
+ <span id="LC3" class="line" lang="cpp"><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span></span>
+ <span id="LC4" class="line" lang="cpp"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="o">&lt;&lt;</span><span class="s">"*"</span><span class="o">&lt;&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span></span>
+ <span id="LC5" class="line" lang="cpp"><span class="p">}</span></span></code></pre>
+ </div>
+ </div>
+ HTML
+
+ expect(render(input, context)).to include(output.strip)
+ end
end
- end
- context 'LaTex code' do
- it 'adds class js-render-math to the output' do
- input = <<~MD
- :stem: latexmath
-
- [stem]
- ++++
- \sqrt{4} = 2
- ++++
-
- another part
-
- [latexmath]
- ++++
- \beta_x \gamma
- ++++
+ context 'with stem block' do
+ it 'does not apply syntax highlighting' do
+ input = <<~ADOC
+ [stem]
+ ++++
+ \sqrt{4} = 2
+ ++++
+ ADOC
- stem:[2+2] is 4
- MD
+ output = "<div>\n<div>\n\\$ qrt{4} = 2\\$\n</div>\n</div>"
- expect(render(input, context)).to include('<pre data-math-style="display" class="code math js-render-math"><code>eta_x gamma</code></pre>')
- expect(render(input, context)).to include('<p><code data-math-style="inline" class="code math js-render-math">2+2</code> is 4</p>')
+ expect(render(input, context)).to include(output)
+ end
end
- end
- context 'outfilesuffix' do
- it 'defaults to adoc' do
- output = render("Inter-document reference <<README.adoc#>>", context)
+ context 'external links' do
+ it 'adds the `rel` attribute to the link' do
+ output = render('link:https://google.com[Google]', context)
- expect(output).to include("a href=\"README.adoc\"")
+ expect(output).to include('rel="nofollow noreferrer noopener"')
+ end
end
- end
- context 'with mermaid diagrams' do
- it 'adds class js-render-mermaid to the output' do
- input = <<~MD
- [mermaid]
- ....
- graph LR
- A[Square Rect] -- Link text --> B((Circle))
- A --> C(Round Rect)
- B --> D{Rhombus}
- C --> D
- ....
- MD
-
- output = <<~HTML
- <pre data-mermaid-style="display" class="js-render-mermaid">graph LR
- A[Square Rect] -- Link text --&gt; B((Circle))
- A --&gt; C(Round Rect)
- B --&gt; D{Rhombus}
- C --&gt; D</pre>
- HTML
-
- expect(render(input, context)).to include(output.strip)
+ context 'LaTex code' do
+ it 'adds class js-render-math to the output' do
+ input = <<~MD
+ :stem: latexmath
+
+ [stem]
+ ++++
+ \sqrt{4} = 2
+ ++++
+
+ another part
+
+ [latexmath]
+ ++++
+ \beta_x \gamma
+ ++++
+
+ stem:[2+2] is 4
+ MD
+
+ expect(render(input, context)).to include('<pre data-math-style="display" class="code math js-render-math"><code>eta_x gamma</code></pre>')
+ expect(render(input, context)).to include('<p><code data-math-style="inline" class="code math js-render-math">2+2</code> is 4</p>')
+ end
end
- it 'applies subs in diagram block' do
- input = <<~MD
- :class-name: AveryLongClass
+ context 'outfilesuffix' do
+ it 'defaults to adoc' do
+ output = render("Inter-document reference <<README.adoc#>>", context)
- [mermaid,subs=+attributes]
- ....
- classDiagram
- Class01 <|-- {class-name} : Cool
- ....
- MD
+ expect(output).to include("a href=\"README.adoc\"")
+ end
+ end
- output = <<~HTML
- <pre data-mermaid-style="display" class="js-render-mermaid">classDiagram
- Class01 &lt;|-- AveryLongClass : Cool</pre>
- HTML
+ context 'with mermaid diagrams' do
+ it 'adds class js-render-mermaid to the output' do
+ input = <<~MD
+ [mermaid]
+ ....
+ graph LR
+ A[Square Rect] -- Link text --> B((Circle))
+ A --> C(Round Rect)
+ B --> D{Rhombus}
+ C --> D
+ ....
+ MD
+
+ output = <<~HTML
+ <pre data-mermaid-style="display" class="js-render-mermaid">graph LR
+ A[Square Rect] -- Link text --&gt; B((Circle))
+ A --&gt; C(Round Rect)
+ B --&gt; D{Rhombus}
+ C --&gt; D</pre>
+ HTML
+
+ expect(render(input, context)).to include(output.strip)
+ end
- expect(render(input, context)).to include(output.strip)
+ it 'applies subs in diagram block' do
+ input = <<~MD
+ :class-name: AveryLongClass
+
+ [mermaid,subs=+attributes]
+ ....
+ classDiagram
+ Class01 <|-- {class-name} : Cool
+ ....
+ MD
+
+ output = <<~HTML
+ <pre data-mermaid-style="display" class="js-render-mermaid">classDiagram
+ Class01 &lt;|-- AveryLongClass : Cool</pre>
+ HTML
+
+ expect(render(input, context)).to include(output.strip)
+ end
end
- end
- context 'with Kroki enabled' do
- before do
- allow_any_instance_of(ApplicationSetting).to receive(:kroki_enabled).and_return(true)
- allow_any_instance_of(ApplicationSetting).to receive(:kroki_url).and_return('https://kroki.io')
- end
+ context 'with Kroki enabled' do
+ before do
+ allow_any_instance_of(ApplicationSetting).to receive(:kroki_enabled).and_return(true)
+ allow_any_instance_of(ApplicationSetting).to receive(:kroki_url).and_return('https://kroki.io')
+ end
- it 'converts a graphviz diagram to image' do
- input = <<~ADOC
- [graphviz]
- ....
- digraph G {
- Hello->World
- }
- ....
- ADOC
+ it 'converts a graphviz diagram to image' do
+ input = <<~ADOC
+ [graphviz]
+ ....
+ digraph G {
+ Hello->World
+ }
+ ....
+ ADOC
- output = <<~HTML
- <div>
- <div>
- <a class="no-attachment-icon" href="https://kroki.io/graphviz/svg/eNpLyUwvSizIUHBXqOZSUPBIzcnJ17ULzy_KSeGqBQCEzQka" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Diagram" class="lazy" data-src="https://kroki.io/graphviz/svg/eNpLyUwvSizIUHBXqOZSUPBIzcnJ17ULzy_KSeGqBQCEzQka"></a>
- </div>
- </div>
- HTML
+ output = <<~HTML
+ <div>
+ <div>
+ <a class="no-attachment-icon" href="https://kroki.io/graphviz/svg/eNpLyUwvSizIUHBXqOZSUPBIzcnJ17ULzy_KSeGqBQCEzQka" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Diagram" class="lazy" data-src="https://kroki.io/graphviz/svg/eNpLyUwvSizIUHBXqOZSUPBIzcnJ17ULzy_KSeGqBQCEzQka"></a>
+ </div>
+ </div>
+ HTML
- expect(render(input, context)).to include(output.strip)
- end
+ expect(render(input, context)).to include(output.strip)
+ end
- it 'does not convert a blockdiag diagram to image' do
- input = <<~ADOC
- [blockdiag]
- ....
- blockdiag {
- Kroki -> generates -> "Block diagrams";
- Kroki -> is -> "very easy!";
-
- Kroki [color = "greenyellow"];
- "Block diagrams" [color = "pink"];
- "very easy!" [color = "orange"];
- }
- ....
- ADOC
+ it 'does not convert a blockdiag diagram to image' do
+ input = <<~ADOC
+ [blockdiag]
+ ....
+ blockdiag {
+ Kroki -> generates -> "Block diagrams";
+ Kroki -> is -> "very easy!";
+
+ Kroki [color = "greenyellow"];
+ "Block diagrams" [color = "pink"];
+ "very easy!" [color = "orange"];
+ }
+ ....
+ ADOC
- output = <<~HTML
- <div>
- <div>
- <pre>blockdiag {
- Kroki -&gt; generates -&gt; "Block diagrams";
- Kroki -&gt; is -&gt; "very easy!";
-
- Kroki [color = "greenyellow"];
- "Block diagrams" [color = "pink"];
- "very easy!" [color = "orange"];
- }</pre>
- </div>
- </div>
- HTML
-
- expect(render(input, context)).to include(output.strip)
- end
+ output = <<~HTML
+ <div>
+ <div>
+ <pre>blockdiag {
+ Kroki -&gt; generates -&gt; "Block diagrams";
+ Kroki -&gt; is -&gt; "very easy!";
+
+ Kroki [color = "greenyellow"];
+ "Block diagrams" [color = "pink"];
+ "very easy!" [color = "orange"];
+ }</pre>
+ </div>
+ </div>
+ HTML
+
+ expect(render(input, context)).to include(output.strip)
+ end
- it 'does not allow kroki-plantuml-include to be overridden' do
- input = <<~ADOC
- [plantuml, test="{counter:kroki-plantuml-include:/etc/passwd}", format="png"]
- ....
- class BlockProcessor
+ it 'does not allow kroki-plantuml-include to be overridden' do
+ input = <<~ADOC
+ [plantuml, test="{counter:kroki-plantuml-include:/etc/passwd}", format="png"]
+ ....
+ class BlockProcessor
+
+ BlockProcessor <|-- {counter:kroki-plantuml-include}
+ ....
+ ADOC
- BlockProcessor <|-- {counter:kroki-plantuml-include}
- ....
- ADOC
+ output = <<~HTML
+ <div>
+ <div>
+ <a class=\"no-attachment-icon\" href=\"https://kroki.io/plantuml/png/eNpLzkksLlZwyslPzg4oyk9OLS7OL-LiQuUr2NTo6ipUJ-eX5pWkFlllF-VnZ-oW5CTmlZTm5uhm5iXnlKak1gIABQEb8A==\" target=\"_blank\" rel=\"noopener noreferrer\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Diagram\" class=\"lazy\" data-src=\"https://kroki.io/plantuml/png/eNpLzkksLlZwyslPzg4oyk9OLS7OL-LiQuUr2NTo6ipUJ-eX5pWkFlllF-VnZ-oW5CTmlZTm5uhm5iXnlKak1gIABQEb8A==\"></a>
+ </div>
+ </div>
+ HTML
+
+ expect(render(input, {})).to include(output.strip)
+ end
- output = <<~HTML
- <div>
- <div>
- <a class=\"no-attachment-icon\" href=\"https://kroki.io/plantuml/png/eNpLzkksLlZwyslPzg4oyk9OLS7OL-LiQuUr2NTo6ipUJ-eX5pWkFlllF-VnZ-oW5CTmlZTm5uhm5iXnlKak1gIABQEb8A==\" target=\"_blank\" rel=\"noopener noreferrer\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Diagram\" class=\"lazy\" data-src=\"https://kroki.io/plantuml/png/eNpLzkksLlZwyslPzg4oyk9OLS7OL-LiQuUr2NTo6ipUJ-eX5pWkFlllF-VnZ-oW5CTmlZTm5uhm5iXnlKak1gIABQEb8A==\"></a>
- </div>
- </div>
- HTML
+ it 'does not allow kroki-server-url to be overridden' do
+ input = <<~ADOC
+ [plantuml, test="{counter:kroki-server-url:evilsite}", format="png"]
+ ....
+ class BlockProcessor
+
+ BlockProcessor
+ ....
+ ADOC
- expect(render(input, {})).to include(output.strip)
+ expect(render(input, {})).not_to include('evilsite')
+ end
end
- it 'does not allow kroki-server-url to be overridden' do
- input = <<~ADOC
- [plantuml, test="{counter:kroki-server-url:evilsite}", format="png"]
- ....
- class BlockProcessor
+ context 'with Kroki and BlockDiag (additional format) enabled' do
+ before do
+ allow_any_instance_of(ApplicationSetting).to receive(:kroki_enabled).and_return(true)
+ allow_any_instance_of(ApplicationSetting).to receive(:kroki_url).and_return('https://kroki.io')
+ allow_any_instance_of(ApplicationSetting).to receive(:kroki_formats_blockdiag).and_return(true)
+ end
- BlockProcessor
- ....
- ADOC
+ it 'converts a blockdiag diagram to image' do
+ input = <<~ADOC
+ [blockdiag]
+ ....
+ blockdiag {
+ Kroki -> generates -> "Block diagrams";
+ Kroki -> is -> "very easy!";
+
+ Kroki [color = "greenyellow"];
+ "Block diagrams" [color = "pink"];
+ "very easy!" [color = "orange"];
+ }
+ ....
+ ADOC
- expect(render(input, {})).not_to include('evilsite')
+ output = <<~HTML
+ <div>
+ <div>
+ <a class="no-attachment-icon" href="https://kroki.io/blockdiag/svg/eNpdzDEKQjEQhOHeU4zpPYFoYesRxGJ9bwghMSsbUYJ4d10UCZbDfPynolOek0Q8FsDeNCestoisNLmy-Qg7R3Blcm5hPcr0ITdaB6X15fv-_YdJixo2CNHI2lmK3sPRA__RwV5SzV80ZAegJjXSyfMFptc71w==" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Diagram" class="lazy" data-src="https://kroki.io/blockdiag/svg/eNpdzDEKQjEQhOHeU4zpPYFoYesRxGJ9bwghMSsbUYJ4d10UCZbDfPynolOek0Q8FsDeNCestoisNLmy-Qg7R3Blcm5hPcr0ITdaB6X15fv-_YdJixo2CNHI2lmK3sPRA__RwV5SzV80ZAegJjXSyfMFptc71w=="></a>
+ </div>
+ </div>
+ HTML
+
+ expect(render(input, context)).to include(output.strip)
+ end
end
end
- context 'with Kroki and BlockDiag (additional format) enabled' do
- before do
- allow_any_instance_of(ApplicationSetting).to receive(:kroki_enabled).and_return(true)
- allow_any_instance_of(ApplicationSetting).to receive(:kroki_url).and_return('https://kroki.io')
- allow_any_instance_of(ApplicationSetting).to receive(:kroki_formats_blockdiag).and_return(true)
+ context 'with project' do
+ let(:context) do
+ {
+ commit: commit,
+ project: project,
+ ref: ref,
+ requested_path: requested_path
+ }
end
- it 'converts a blockdiag diagram to image' do
- input = <<~ADOC
- [blockdiag]
- ....
- blockdiag {
- Kroki -> generates -> "Block diagrams";
- Kroki -> is -> "very easy!";
-
- Kroki [color = "greenyellow"];
- "Block diagrams" [color = "pink"];
- "very easy!" [color = "orange"];
- }
- ....
- ADOC
-
- output = <<~HTML
- <div>
- <div>
- <a class="no-attachment-icon" href="https://kroki.io/blockdiag/svg/eNpdzDEKQjEQhOHeU4zpPYFoYesRxGJ9bwghMSsbUYJ4d10UCZbDfPynolOek0Q8FsDeNCestoisNLmy-Qg7R3Blcm5hPcr0ITdaB6X15fv-_YdJixo2CNHI2lmK3sPRA__RwV5SzV80ZAegJjXSyfMFptc71w==" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Diagram" class="lazy" data-src="https://kroki.io/blockdiag/svg/eNpdzDEKQjEQhOHeU4zpPYFoYesRxGJ9bwghMSsbUYJ4d10UCZbDfPynolOek0Q8FsDeNCestoisNLmy-Qg7R3Blcm5hPcr0ITdaB6X15fv-_YdJixo2CNHI2lmK3sPRA__RwV5SzV80ZAegJjXSyfMFptc71w=="></a>
- </div>
- </div>
- HTML
+ let(:commit) { project.commit(ref) }
+ let(:project) { create(:project, :repository) }
+ let(:ref) { 'asciidoc' }
+ let(:requested_path) { '/' }
- expect(render(input, context)).to include(output.strip)
- end
- end
- end
+ context 'include directive' do
+ subject(:output) { render(input, context) }
- context 'with project' do
- let(:context) do
- {
- commit: commit,
- project: project,
- ref: ref,
- requested_path: requested_path
- }
- end
+ let(:input) { "Include this:\n\ninclude::#{include_path}[]" }
- let(:commit) { project.commit(ref) }
- let(:project) { create(:project, :repository) }
- let(:ref) { 'asciidoc' }
- let(:requested_path) { '/' }
-
- context 'include directive' do
- subject(:output) { render(input, context) }
+ before do
+ current_file = requested_path
+ current_file += 'README.adoc' if requested_path.end_with? '/'
- let(:input) { "Include this:\n\ninclude::#{include_path}[]" }
+ create_file(current_file, "= AsciiDoc\n")
+ end
- before do
- current_file = requested_path
- current_file += 'README.adoc' if requested_path.end_with? '/'
+ def many_includes(target)
+ Array.new(10, "include::#{target}[]").join("\n")
+ end
- create_file(current_file, "= AsciiDoc\n")
- end
+ context 'cyclic imports' do
+ before do
+ create_file('doc/api/a.adoc', many_includes('b.adoc'))
+ create_file('doc/api/b.adoc', many_includes('a.adoc'))
+ end
- def many_includes(target)
- Array.new(10, "include::#{target}[]").join("\n")
- end
+ let(:include_path) { 'a.adoc' }
+ let(:requested_path) { 'doc/api/README.md' }
- context 'cyclic imports' do
- before do
- create_file('doc/api/a.adoc', many_includes('b.adoc'))
- create_file('doc/api/b.adoc', many_includes('a.adoc'))
+ it 'completes successfully' do
+ is_expected.to include('<p>Include this:</p>')
+ end
end
- let(:include_path) { 'a.adoc' }
- let(:requested_path) { 'doc/api/README.md' }
+ context 'with path to non-existing file' do
+ let(:include_path) { 'not-exists.adoc' }
- it 'completes successfully' do
- is_expected.to include('<p>Include this:</p>')
+ it 'renders Unresolved directive placeholder' do
+ is_expected.to include("<strong>[ERROR: include::#{include_path}[] - unresolved directive]</strong>")
+ end
end
- end
- context 'with path to non-existing file' do
- let(:include_path) { 'not-exists.adoc' }
+ shared_examples :invalid_include do
+ let(:include_path) { 'dk.png' }
- it 'renders Unresolved directive placeholder' do
- is_expected.to include("<strong>[ERROR: include::#{include_path}[] - unresolved directive]</strong>")
- end
- end
+ before do
+ allow(project.repository).to receive(:blob_at).and_return(blob)
+ end
- shared_examples :invalid_include do
- let(:include_path) { 'dk.png' }
+ it 'does not read the blob' do
+ expect(blob).not_to receive(:data)
+ end
- before do
- allow(project.repository).to receive(:blob_at).and_return(blob)
+ it 'renders Unresolved directive placeholder' do
+ is_expected.to include("<strong>[ERROR: include::#{include_path}[] - unresolved directive]</strong>")
+ end
end
- it 'does not read the blob' do
- expect(blob).not_to receive(:data)
- end
+ context 'with path to a binary file' do
+ let(:blob) { fake_blob(path: 'dk.png', binary: true) }
- it 'renders Unresolved directive placeholder' do
- is_expected.to include("<strong>[ERROR: include::#{include_path}[] - unresolved directive]</strong>")
+ include_examples :invalid_include
end
- end
-
- context 'with path to a binary file' do
- let(:blob) { fake_blob(path: 'dk.png', binary: true) }
- include_examples :invalid_include
- end
+ context 'with path to file in external storage' do
+ let(:blob) { fake_blob(path: 'dk.png', lfs: true) }
- context 'with path to file in external storage' do
- let(:blob) { fake_blob(path: 'dk.png', lfs: true) }
+ before do
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ project.update_attribute(:lfs_enabled, true)
+ end
- before do
- allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
- project.update_attribute(:lfs_enabled, true)
+ include_examples :invalid_include
end
- include_examples :invalid_include
- end
+ context 'with path to a textual file' do
+ let(:include_path) { 'sample.adoc' }
- context 'with path to a textual file' do
- let(:include_path) { 'sample.adoc' }
+ before do
+ create_file(file_path, "Content from #{include_path}")
+ end
- before do
- create_file(file_path, "Content from #{include_path}")
- end
-
- shared_examples :valid_include do
- [
- ['/doc/sample.adoc', 'doc/sample.adoc', 'absolute path'],
- ['sample.adoc', 'doc/api/sample.adoc', 'relative path'],
- ['./sample.adoc', 'doc/api/sample.adoc', 'relative path with leading ./'],
- ['../sample.adoc', 'doc/sample.adoc', 'relative path to a file up one directory'],
- ['../../sample.adoc', 'sample.adoc', 'relative path for a file up multiple directories']
- ].each do |include_path_, file_path_, desc|
- context "the file is specified by #{desc}" do
- let(:include_path) { include_path_ }
- let(:file_path) { file_path_ }
-
- it 'includes content of the file' do
- is_expected.to include('<p>Include this:</p>')
- is_expected.to include("<p>Content from #{include_path}</p>")
+ shared_examples :valid_include do
+ [
+ ['/doc/sample.adoc', 'doc/sample.adoc', 'absolute path'],
+ ['sample.adoc', 'doc/api/sample.adoc', 'relative path'],
+ ['./sample.adoc', 'doc/api/sample.adoc', 'relative path with leading ./'],
+ ['../sample.adoc', 'doc/sample.adoc', 'relative path to a file up one directory'],
+ ['../../sample.adoc', 'sample.adoc', 'relative path for a file up multiple directories']
+ ].each do |include_path_, file_path_, desc|
+ context "the file is specified by #{desc}" do
+ let(:include_path) { include_path_ }
+ let(:file_path) { file_path_ }
+
+ it 'includes content of the file' do
+ is_expected.to include('<p>Include this:</p>')
+ is_expected.to include("<p>Content from #{include_path}</p>")
+ end
end
end
end
- end
- context 'when requested path is a file in the repo' do
- let(:requested_path) { 'doc/api/README.adoc' }
+ context 'when requested path is a file in the repo' do
+ let(:requested_path) { 'doc/api/README.adoc' }
- include_examples :valid_include
+ include_examples :valid_include
- context 'without a commit (only ref)' do
- let(:commit) { nil }
+ context 'without a commit (only ref)' do
+ let(:commit) { nil }
- include_examples :valid_include
+ include_examples :valid_include
+ end
end
- end
- context 'when requested path is a directory in the repo' do
- let(:requested_path) { 'doc/api/' }
+ context 'when requested path is a directory in the repo' do
+ let(:requested_path) { 'doc/api/' }
- include_examples :valid_include
+ include_examples :valid_include
- context 'without a commit (only ref)' do
- let(:commit) { nil }
+ context 'without a commit (only ref)' do
+ let(:commit) { nil }
- include_examples :valid_include
+ include_examples :valid_include
+ end
end
end
- end
-
- context 'when repository is passed into the context' do
- let(:wiki_repo) { project.wiki.repository }
- let(:include_path) { 'wiki_file.adoc' }
- before do
- project.create_wiki
- context.merge!(repository: wiki_repo)
- end
+ context 'when repository is passed into the context' do
+ let(:wiki_repo) { project.wiki.repository }
+ let(:include_path) { 'wiki_file.adoc' }
- context 'when the file exists' do
before do
- create_file(include_path, 'Content from wiki', repository: wiki_repo)
+ project.create_wiki
+ context.merge!(repository: wiki_repo)
end
- it { is_expected.to include('<p>Content from wiki</p>') }
- end
-
- context 'when the file does not exist' do
- it { is_expected.to include("[ERROR: include::#{include_path}[] - unresolved directive]")}
- end
- end
-
- context 'recursive includes with relative paths' do
- let(:input) do
- <<~ADOC
- Source: requested file
+ context 'when the file exists' do
+ before do
+ create_file(include_path, 'Content from wiki', repository: wiki_repo)
+ end
- include::doc/README.adoc[]
+ it { is_expected.to include('<p>Content from wiki</p>') }
+ end
- include::license.adoc[]
- ADOC
+ context 'when the file does not exist' do
+ it { is_expected.to include("[ERROR: include::#{include_path}[] - unresolved directive]")}
+ end
end
- before do
- create_file 'doc/README.adoc', <<~ADOC
- Source: doc/README.adoc
-
- include::../license.adoc[]
+ context 'recursive includes with relative paths' do
+ let(:input) do
+ <<~ADOC
+ Source: requested file
+
+ include::doc/README.adoc[]
+
+ include::license.adoc[]
+ ADOC
+ end
- include::api/hello.adoc[]
- ADOC
- create_file 'license.adoc', <<~ADOC
- Source: license.adoc
- ADOC
- create_file 'doc/api/hello.adoc', <<~ADOC
- Source: doc/api/hello.adoc
+ before do
+ create_file 'doc/README.adoc', <<~ADOC
+ Source: doc/README.adoc
+
+ include::../license.adoc[]
+
+ include::api/hello.adoc[]
+ ADOC
+ create_file 'license.adoc', <<~ADOC
+ Source: license.adoc
+ ADOC
+ create_file 'doc/api/hello.adoc', <<~ADOC
+ Source: doc/api/hello.adoc
+
+ include::./common.adoc[]
+ ADOC
+ create_file 'doc/api/common.adoc', <<~ADOC
+ Source: doc/api/common.adoc
+ ADOC
+ end
- include::./common.adoc[]
- ADOC
- create_file 'doc/api/common.adoc', <<~ADOC
- Source: doc/api/common.adoc
- ADOC
+ it 'includes content of the included files recursively' do
+ expect(output.gsub(/<[^>]+>/, '').gsub(/\n\s*/, "\n").strip).to eq <<~ADOC.strip
+ Source: requested file
+ Source: doc/README.adoc
+ Source: license.adoc
+ Source: doc/api/hello.adoc
+ Source: doc/api/common.adoc
+ Source: license.adoc
+ ADOC
+ end
end
- it 'includes content of the included files recursively' do
- expect(output.gsub(/<[^>]+>/, '').gsub(/\n\s*/, "\n").strip).to eq <<~ADOC.strip
- Source: requested file
- Source: doc/README.adoc
- Source: license.adoc
- Source: doc/api/hello.adoc
- Source: doc/api/common.adoc
- Source: license.adoc
- ADOC
+ def create_file(path, content, repository: project.repository)
+ repository.create_file(project.creator, path, content,
+ message: "Add #{path}", branch_name: 'asciidoc')
end
end
+ end
+ end
- def create_file(path, content, repository: project.repository)
- repository.create_file(project.creator, path, content,
- message: "Add #{path}", branch_name: 'asciidoc')
- end
+ context 'using ruby-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: false)
+ end
+
+ it_behaves_like 'renders correct asciidoc'
+ end
+
+ context 'using c-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: true)
end
+
+ it_behaves_like 'renders correct asciidoc'
end
def render(*args)
diff --git a/spec/lib/gitlab/auth/auth_finders_spec.rb b/spec/lib/gitlab/auth/auth_finders_spec.rb
index b0522e269e0..f1c891b2adb 100644
--- a/spec/lib/gitlab/auth/auth_finders_spec.rb
+++ b/spec/lib/gitlab/auth/auth_finders_spec.rb
@@ -873,45 +873,65 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#find_user_from_job_token' do
+ let(:token) { job.token }
+
subject { find_user_from_job_token }
- context 'when the token is in the headers' do
- before do
- set_header(described_class::JOB_TOKEN_HEADER, token)
+ shared_examples 'finds user when job token allowed' do
+ context 'when the token is in the headers' do
+ before do
+ set_header(described_class::JOB_TOKEN_HEADER, token)
+ end
+
+ it_behaves_like 'find user from job token'
end
- it_behaves_like 'find user from job token'
- end
+ context 'when the token is in the job_token param' do
+ before do
+ set_param(described_class::JOB_TOKEN_PARAM, token)
+ end
- context 'when the token is in the job_token param' do
- before do
- set_param(described_class::JOB_TOKEN_PARAM, token)
+ it_behaves_like 'find user from job token'
end
- it_behaves_like 'find user from job token'
- end
+ context 'when the token is in the token param' do
+ before do
+ set_param(described_class::RUNNER_JOB_TOKEN_PARAM, token)
+ end
- context 'when the token is in the token param' do
- before do
- set_param(described_class::RUNNER_JOB_TOKEN_PARAM, token)
+ it_behaves_like 'find user from job token'
end
+ end
- it_behaves_like 'find user from job token'
+ context 'when route setting allows job_token' do
+ let(:route_authentication_setting) { { job_token_allowed: true } }
+
+ include_examples 'finds user when job token allowed'
end
- context 'when the job token is provided via basic auth' do
+ context 'when route setting is basic auth' do
let(:route_authentication_setting) { { job_token_allowed: :basic_auth } }
- let(:username) { ::Gitlab::Auth::CI_JOB_USER }
- let(:token) { job.token }
- before do
- set_basic_auth_header(username, token)
+ context 'when the token is provided via basic auth' do
+ let(:username) { ::Gitlab::Auth::CI_JOB_USER }
+
+ before do
+ set_basic_auth_header(username, token)
+ end
+
+ it { is_expected.to eq(user) }
end
- it { is_expected.to eq(user) }
+ include_examples 'finds user when job token allowed'
+ end
- context 'credentials are provided but route setting is incorrect' do
- let(:route_authentication_setting) { { job_token_allowed: :unknown } }
+ context 'when route setting job_token_allowed is invalid' do
+ let(:route_authentication_setting) { { job_token_allowed: false } }
+
+ context 'when the token is provided' do
+ before do
+ set_header(described_class::JOB_TOKEN_HEADER, token)
+ end
it { is_expected.to be_nil }
end
diff --git a/spec/lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule_spec.rb b/spec/lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule_spec.rb
index 81b8b5dde08..0b29163671c 100644
--- a/spec/lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule_spec.rb
+++ b/spec/lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::AddModifiedToApprovalMergeRequestRule, schema: 20200817195628 do
+RSpec.describe Gitlab::BackgroundMigration::AddModifiedToApprovalMergeRequestRule, schema: 20181228175414 do
let(:determine_if_rules_are_modified) { described_class.new }
let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab') }
diff --git a/spec/lib/gitlab/background_migration/add_primary_email_to_emails_if_user_confirmed_spec.rb b/spec/lib/gitlab/background_migration/add_primary_email_to_emails_if_user_confirmed_spec.rb
new file mode 100644
index 00000000000..b50a55a9e41
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/add_primary_email_to_emails_if_user_confirmed_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::AddPrimaryEmailToEmailsIfUserConfirmed do
+ let(:users) { table(:users) }
+ let(:emails) { table(:emails) }
+
+ let!(:unconfirmed_user) { users.create!(name: 'unconfirmed', email: 'unconfirmed@example.com', confirmed_at: nil, projects_limit: 100) }
+ let!(:confirmed_user_1) { users.create!(name: 'confirmed-1', email: 'confirmed-1@example.com', confirmed_at: 1.day.ago, projects_limit: 100) }
+ let!(:confirmed_user_2) { users.create!(name: 'confirmed-2', email: 'confirmed-2@example.com', confirmed_at: 1.day.ago, projects_limit: 100) }
+ let!(:email) { emails.create!(user_id: confirmed_user_1.id, email: 'confirmed-1@example.com', confirmed_at: 1.day.ago) }
+
+ let(:perform) { described_class.new.perform(users.first.id, users.last.id) }
+
+ it 'adds the primary email of confirmed users to Emails, unless already added', :aggregate_failures do
+ expect(emails.where(email: [unconfirmed_user.email, confirmed_user_2.email])).to be_empty
+
+ expect { perform }.not_to raise_error
+
+ expect(emails.where(email: unconfirmed_user.email).count).to eq(0)
+ expect(emails.where(email: confirmed_user_1.email, user_id: confirmed_user_1.id).count).to eq(1)
+ expect(emails.where(email: confirmed_user_2.email, user_id: confirmed_user_2.id).count).to eq(1)
+
+ email_2 = emails.find_by(email: confirmed_user_2.email, user_id: confirmed_user_2.id)
+ expect(email_2.confirmed_at).to eq(confirmed_user_2.reload.confirmed_at)
+ end
+
+ it 'sets timestamps on the created Emails' do
+ perform
+
+ email_2 = emails.find_by(email: confirmed_user_2.email, user_id: confirmed_user_2.id)
+
+ expect(email_2.created_at).not_to be_nil
+ expect(email_2.updated_at).not_to be_nil
+ end
+
+ context 'when a range of IDs is specified' do
+ let!(:confirmed_user_3) { users.create!(name: 'confirmed-3', email: 'confirmed-3@example.com', confirmed_at: 1.hour.ago, projects_limit: 100) }
+ let!(:confirmed_user_4) { users.create!(name: 'confirmed-4', email: 'confirmed-4@example.com', confirmed_at: 1.hour.ago, projects_limit: 100) }
+
+ it 'only acts on the specified range of IDs', :aggregate_failures do
+ expect do
+ described_class.new.perform(confirmed_user_2.id, confirmed_user_3.id)
+ end.to change { Email.count }.by(2)
+ expect(emails.where(email: confirmed_user_4.email).count).to eq(0)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_artifact_expiry_date_spec.rb b/spec/lib/gitlab/background_migration/backfill_artifact_expiry_date_spec.rb
index 49fa7b41916..6ab1e3ecd70 100644
--- a/spec/lib/gitlab/background_migration/backfill_artifact_expiry_date_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_artifact_expiry_date_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillArtifactExpiryDate, :migration, schema: 20201111152859 do
+RSpec.describe Gitlab::BackgroundMigration::BackfillArtifactExpiryDate, :migration, schema: 20181228175414 do
subject(:perform) { migration.perform(1, 99) }
let(:migration) { described_class.new }
diff --git a/spec/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments_spec.rb b/spec/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments_spec.rb
index 54c14e7a4b8..1404ada3647 100644
--- a/spec/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillDeploymentClustersFromDeployments, :migration, schema: 20200227140242 do
+RSpec.describe Gitlab::BackgroundMigration::BackfillDeploymentClustersFromDeployments, :migration, schema: 20181228175414 do
subject { described_class.new }
describe '#perform' do
diff --git a/spec/lib/gitlab/background_migration/backfill_design_internal_ids_spec.rb b/spec/lib/gitlab/background_migration/backfill_design_internal_ids_spec.rb
deleted file mode 100644
index 4bf59a02a31..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_design_internal_ids_spec.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillDesignInternalIds, :migration, schema: 20201030203854 do
- subject { described_class.new(designs) }
-
- let_it_be(:namespaces) { table(:namespaces) }
- let_it_be(:projects) { table(:projects) }
- let_it_be(:designs) { table(:design_management_designs) }
-
- let(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
- let(:project) { projects.create!(namespace_id: namespace.id) }
- let(:project_2) { projects.create!(namespace_id: namespace.id) }
-
- def create_design!(proj = project)
- designs.create!(project_id: proj.id, filename: generate(:filename))
- end
-
- def migrate!
- relation = designs.where(project_id: [project.id, project_2.id]).select(:project_id).distinct
-
- subject.perform(relation)
- end
-
- it 'backfills the iid for designs' do
- 3.times { create_design! }
-
- expect do
- migrate!
- end.to change { designs.pluck(:iid) }.from(contain_exactly(nil, nil, nil)).to(contain_exactly(1, 2, 3))
- end
-
- it 'scopes IIDs and handles range and starting-point correctly' do
- create_design!.update!(iid: 10)
- create_design!.update!(iid: 12)
- create_design!(project_2).update!(iid: 7)
- project_3 = projects.create!(namespace_id: namespace.id)
-
- 2.times { create_design! }
- 2.times { create_design!(project_2) }
- 2.times { create_design!(project_3) }
-
- migrate!
-
- expect(designs.where(project_id: project.id).pluck(:iid)).to contain_exactly(10, 12, 13, 14)
- expect(designs.where(project_id: project_2.id).pluck(:iid)).to contain_exactly(7, 8, 9)
- expect(designs.where(project_id: project_3.id).pluck(:iid)).to contain_exactly(nil, nil)
- end
-
- it 'updates the internal ID records' do
- design = create_design!
- 2.times { create_design! }
- design.update!(iid: 10)
- scope = { project_id: project.id }
- usage = :design_management_designs
- init = ->(_d, _s) { 0 }
-
- ::InternalId.track_greatest(design, scope, usage, 10, init)
-
- migrate!
-
- next_iid = ::InternalId.generate_next(design, scope, usage, init)
-
- expect(designs.pluck(:iid)).to contain_exactly(10, 11, 12)
- expect(design.reload.iid).to eq(10)
- expect(next_iid).to eq(13)
- end
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb b/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb
index 550bdc484c9..9194525e713 100644
--- a/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillEnvironmentIdDeploymentMergeRequests, schema: 20200312134637 do
+RSpec.describe Gitlab::BackgroundMigration::BackfillEnvironmentIdDeploymentMergeRequests, schema: 20181228175414 do
let(:environments) { table(:environments) }
let(:merge_requests) { table(:merge_requests) }
let(:deployments) { table(:deployments) }
diff --git a/spec/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2_spec.rb b/spec/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2_spec.rb
index 58864aac084..446d62bbd2a 100644
--- a/spec/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillJiraTrackerDeploymentType2, :migration, schema: 20201028182809 do
+RSpec.describe Gitlab::BackgroundMigration::BackfillJiraTrackerDeploymentType2, :migration, schema: 20181228175414 do
let_it_be(:jira_integration_temp) { described_class::JiraServiceTemp }
let_it_be(:jira_tracker_data_temp) { described_class::JiraTrackerDataTemp }
let_it_be(:atlassian_host) { 'https://api.atlassian.net' }
diff --git a/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb b/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb
index c2daa35703d..d33f52514da 100644
--- a/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillMergeRequestCleanupSchedules, schema: 20201103110018 do
+RSpec.describe Gitlab::BackgroundMigration::BackfillMergeRequestCleanupSchedules, schema: 20181228175414 do
let(:merge_requests) { table(:merge_requests) }
let(:cleanup_schedules) { table(:merge_request_cleanup_schedules) }
let(:metrics) { table(:merge_request_metrics) }
diff --git a/spec/lib/gitlab/background_migration/backfill_namespace_settings_spec.rb b/spec/lib/gitlab/background_migration/backfill_namespace_settings_spec.rb
index 43e76a2952e..0f8adca2ca4 100644
--- a/spec/lib/gitlab/background_migration/backfill_namespace_settings_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_namespace_settings_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceSettings, schema: 20200703125016 do
+RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceSettings, schema: 20181228175414 do
let(:namespaces) { table(:namespaces) }
let(:namespace_settings) { table(:namespace_settings) }
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
diff --git a/spec/lib/gitlab/background_migration/backfill_project_settings_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_settings_spec.rb
index 48c5674822a..e6b0db2ab73 100644
--- a/spec/lib/gitlab/background_migration/backfill_project_settings_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_project_settings_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillProjectSettings, schema: 20200114113341 do
+RSpec.describe Gitlab::BackgroundMigration::BackfillProjectSettings, schema: 20181228175414 do
let(:projects) { table(:projects) }
let(:project_settings) { table(:project_settings) }
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
diff --git a/spec/lib/gitlab/background_migration/backfill_push_rules_id_in_projects_spec.rb b/spec/lib/gitlab/background_migration/backfill_push_rules_id_in_projects_spec.rb
index 9ce6a3227b5..3468df3dccd 100644
--- a/spec/lib/gitlab/background_migration/backfill_push_rules_id_in_projects_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_push_rules_id_in_projects_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillPushRulesIdInProjects, :migration, schema: 2020_03_25_162730 do
+RSpec.describe Gitlab::BackgroundMigration::BackfillPushRulesIdInProjects, :migration, schema: 20181228175414 do
let(:push_rules) { table(:push_rules) }
let(:projects) { table(:projects) }
let(:project_settings) { table(:project_settings) }
diff --git a/spec/lib/gitlab/background_migration/backfill_user_namespace_spec.rb b/spec/lib/gitlab/background_migration/backfill_user_namespace_spec.rb
new file mode 100644
index 00000000000..395248b786d
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_user_namespace_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillUserNamespace, :migration, schema: 20210930211936 do
+ let(:migration) { described_class.new }
+ let(:namespaces_table) { table(:namespaces) }
+
+ let(:table_name) { 'namespaces' }
+ let(:batch_column) { :id }
+ let(:sub_batch_size) { 100 }
+ let(:pause_ms) { 0 }
+
+ subject(:perform_migration) { migration.perform(1, 10, table_name, batch_column, sub_batch_size, pause_ms) }
+
+ before do
+ namespaces_table.create!(id: 1, name: 'test1', path: 'test1', type: nil)
+ namespaces_table.create!(id: 2, name: 'test2', path: 'test2', type: 'User')
+ namespaces_table.create!(id: 3, name: 'test3', path: 'test3', type: 'Group')
+ namespaces_table.create!(id: 4, name: 'test4', path: 'test4', type: nil)
+ namespaces_table.create!(id: 11, name: 'test11', path: 'test11', type: nil)
+ end
+
+ it 'backfills `type` for the selected records', :aggregate_failures do
+ queries = ActiveRecord::QueryRecorder.new do
+ perform_migration
+ end
+
+ expect(queries.count).to eq(3)
+ expect(namespaces_table.where(type: 'User').count).to eq 3
+ expect(namespaces_table.where(type: 'User').pluck(:id)).to match_array([1, 2, 4])
+ end
+
+ it 'tracks timings of queries' do
+ expect(migration.batch_metrics.timings).to be_empty
+
+ expect { perform_migration }.to change { migration.batch_metrics.timings }
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb b/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
index 3e378db04d4..d4fc24d0559 100644
--- a/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
+++ b/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJob do
- let(:table_name) { :copy_primary_key_test }
+ let(:table_name) { :_test_copy_primary_key_test }
let(:test_table) { table(table_name) }
let(:sub_batch_size) { 1000 }
let(:pause_ms) { 0 }
diff --git a/spec/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics_spec.rb b/spec/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics_spec.rb
deleted file mode 100644
index 71bb794d539..00000000000
--- a/spec/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::CopyMergeRequestTargetProjectToMergeRequestMetrics, :migration, schema: 20200723125205 do
- let(:migration) { described_class.new }
-
- let_it_be(:namespaces) { table(:namespaces) }
- let_it_be(:projects) { table(:projects) }
- let_it_be(:merge_requests) { table(:merge_requests) }
- let_it_be(:metrics) { table(:merge_request_metrics) }
-
- let!(:namespace) { namespaces.create!(name: 'namespace', path: 'namespace') }
- let!(:project_1) { projects.create!(namespace_id: namespace.id) }
- let!(:project_2) { projects.create!(namespace_id: namespace.id) }
- let!(:merge_request_to_migrate_1) { merge_requests.create!(source_branch: 'a', target_branch: 'b', target_project_id: project_1.id) }
- let!(:merge_request_to_migrate_2) { merge_requests.create!(source_branch: 'c', target_branch: 'd', target_project_id: project_2.id) }
- let!(:merge_request_without_metrics) { merge_requests.create!(source_branch: 'e', target_branch: 'f', target_project_id: project_2.id) }
-
- let!(:metrics_1) { metrics.create!(merge_request_id: merge_request_to_migrate_1.id) }
- let!(:metrics_2) { metrics.create!(merge_request_id: merge_request_to_migrate_2.id) }
-
- let(:merge_request_ids) { [merge_request_to_migrate_1.id, merge_request_to_migrate_2.id, merge_request_without_metrics.id] }
-
- subject { migration.perform(merge_request_ids.min, merge_request_ids.max) }
-
- it 'copies `target_project_id` to the associated `merge_request_metrics` record' do
- subject
-
- expect(metrics_1.reload.target_project_id).to eq(project_1.id)
- expect(metrics_2.reload.target_project_id).to eq(project_2.id)
- end
-
- it 'does not create metrics record when it is missing' do
- subject
-
- expect(metrics.find_by_merge_request_id(merge_request_without_metrics.id)).to be_nil
- end
-end
diff --git a/spec/lib/gitlab/background_migration/drop_invalid_vulnerabilities_spec.rb b/spec/lib/gitlab/background_migration/drop_invalid_vulnerabilities_spec.rb
index c4beb719e1e..b83dc6fff7a 100644
--- a/spec/lib/gitlab/background_migration/drop_invalid_vulnerabilities_spec.rb
+++ b/spec/lib/gitlab/background_migration/drop_invalid_vulnerabilities_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::DropInvalidVulnerabilities, schema: 20201110110454 do
+RSpec.describe Gitlab::BackgroundMigration::DropInvalidVulnerabilities, schema: 20181228175414 do
let_it_be(:background_migration_jobs) { table(:background_migration_jobs) }
let_it_be(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
let_it_be(:users) { table(:users) }
diff --git a/spec/lib/gitlab/background_migration/fix_merge_request_diff_commit_users_spec.rb b/spec/lib/gitlab/background_migration/fix_merge_request_diff_commit_users_spec.rb
new file mode 100644
index 00000000000..c343ee438b8
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/fix_merge_request_diff_commit_users_spec.rb
@@ -0,0 +1,316 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# The underlying migration relies on the global models (e.g. Project). This
+# means we also need to use FactoryBot factories to ensure everything is
+# operating using the same types. If we use `table()` and similar methods we
+# would have to duplicate a lot of logic just for these tests.
+#
+# rubocop: disable RSpec/FactoriesInMigrationSpecs
+RSpec.describe Gitlab::BackgroundMigration::FixMergeRequestDiffCommitUsers do
+ let(:migration) { described_class.new }
+
+ describe '#perform' do
+ context 'when the project exists' do
+ it 'processes the project' do
+ project = create(:project)
+
+ expect(migration).to receive(:process).with(project)
+ expect(migration).to receive(:schedule_next_job)
+
+ migration.perform(project.id)
+ end
+
+ it 'marks the background job as finished' do
+ project = create(:project)
+
+ Gitlab::Database::BackgroundMigrationJob.create!(
+ class_name: 'FixMergeRequestDiffCommitUsers',
+ arguments: [project.id]
+ )
+
+ migration.perform(project.id)
+
+ job = Gitlab::Database::BackgroundMigrationJob
+ .find_by(class_name: 'FixMergeRequestDiffCommitUsers')
+
+ expect(job.status).to eq('succeeded')
+ end
+ end
+
+ context 'when the project does not exist' do
+ it 'does nothing' do
+ expect(migration).not_to receive(:process)
+ expect(migration).to receive(:schedule_next_job)
+
+ migration.perform(-1)
+ end
+ end
+ end
+
+ describe '#process' do
+ it 'processes the merge requests of the project' do
+ project = create(:project, :repository)
+ commit = project.commit
+ mr = create(
+ :merge_request_with_diffs,
+ source_project: project,
+ target_project: project
+ )
+
+ diff = mr.merge_request_diffs.first
+
+ create(
+ :merge_request_diff_commit,
+ merge_request_diff: diff,
+ sha: commit.sha,
+ relative_order: 9000
+ )
+
+ migration.process(project)
+
+ updated = diff
+ .merge_request_diff_commits
+ .find_by(sha: commit.sha, relative_order: 9000)
+
+ expect(updated.commit_author_id).not_to be_nil
+ expect(updated.committer_id).not_to be_nil
+ end
+ end
+
+ describe '#update_commit' do
+ let(:project) { create(:project, :repository) }
+ let(:mr) do
+ create(
+ :merge_request_with_diffs,
+ source_project: project,
+ target_project: project
+ )
+ end
+
+ let(:diff) { mr.merge_request_diffs.first }
+ let(:commit) { project.commit }
+
+ def update_row(migration, project, diff, row)
+ migration.update_commit(project, row)
+
+ diff
+ .merge_request_diff_commits
+ .find_by(sha: row.sha, relative_order: row.relative_order)
+ end
+
+ it 'populates missing commit authors' do
+ commit_row = create(
+ :merge_request_diff_commit,
+ merge_request_diff: diff,
+ sha: commit.sha,
+ relative_order: 9000
+ )
+
+ updated = update_row(migration, project, diff, commit_row)
+
+ expect(updated.commit_author.name).to eq(commit.to_hash[:author_name])
+ expect(updated.commit_author.email).to eq(commit.to_hash[:author_email])
+ end
+
+ it 'populates missing committers' do
+ commit_row = create(
+ :merge_request_diff_commit,
+ merge_request_diff: diff,
+ sha: commit.sha,
+ relative_order: 9000
+ )
+
+ updated = update_row(migration, project, diff, commit_row)
+
+ expect(updated.committer.name).to eq(commit.to_hash[:committer_name])
+ expect(updated.committer.email).to eq(commit.to_hash[:committer_email])
+ end
+
+ it 'leaves existing commit authors as-is' do
+ user = create(:merge_request_diff_commit_user)
+ commit_row = create(
+ :merge_request_diff_commit,
+ merge_request_diff: diff,
+ sha: commit.sha,
+ relative_order: 9000,
+ commit_author: user
+ )
+
+ updated = update_row(migration, project, diff, commit_row)
+
+ expect(updated.commit_author).to eq(user)
+ end
+
+ it 'leaves existing committers as-is' do
+ user = create(:merge_request_diff_commit_user)
+ commit_row = create(
+ :merge_request_diff_commit,
+ merge_request_diff: diff,
+ sha: commit.sha,
+ relative_order: 9000,
+ committer: user
+ )
+
+ updated = update_row(migration, project, diff, commit_row)
+
+ expect(updated.committer).to eq(user)
+ end
+
+ it 'does nothing when both the author and committer are present' do
+ user = create(:merge_request_diff_commit_user)
+ commit_row = create(
+ :merge_request_diff_commit,
+ merge_request_diff: diff,
+ sha: commit.sha,
+ relative_order: 9000,
+ committer: user,
+ commit_author: user
+ )
+
+ recorder = ActiveRecord::QueryRecorder.new do
+ migration.update_commit(project, commit_row)
+ end
+
+ expect(recorder.count).to be_zero
+ end
+
+ it 'does nothing if the commit does not exist in Git' do
+ user = create(:merge_request_diff_commit_user)
+ commit_row = create(
+ :merge_request_diff_commit,
+ merge_request_diff: diff,
+ sha: 'kittens',
+ relative_order: 9000,
+ committer: user,
+ commit_author: user
+ )
+
+ recorder = ActiveRecord::QueryRecorder.new do
+ migration.update_commit(project, commit_row)
+ end
+
+ expect(recorder.count).to be_zero
+ end
+
+ it 'does nothing when the committer/author are missing in the Git commit' do
+ user = create(:merge_request_diff_commit_user)
+ commit_row = create(
+ :merge_request_diff_commit,
+ merge_request_diff: diff,
+ sha: commit.sha,
+ relative_order: 9000,
+ committer: user,
+ commit_author: user
+ )
+
+ allow(migration).to receive(:find_or_create_user).and_return(nil)
+
+ recorder = ActiveRecord::QueryRecorder.new do
+ migration.update_commit(project, commit_row)
+ end
+
+ expect(recorder.count).to be_zero
+ end
+ end
+
+ describe '#schedule_next_job' do
+ it 'schedules the next background migration' do
+ Gitlab::Database::BackgroundMigrationJob
+ .create!(class_name: 'FixMergeRequestDiffCommitUsers', arguments: [42])
+
+ expect(BackgroundMigrationWorker)
+ .to receive(:perform_in)
+ .with(2.minutes, 'FixMergeRequestDiffCommitUsers', [42])
+
+ migration.schedule_next_job
+ end
+
+ it 'does nothing when there are no jobs' do
+ expect(BackgroundMigrationWorker)
+ .not_to receive(:perform_in)
+
+ migration.schedule_next_job
+ end
+ end
+
+ describe '#find_commit' do
+ let(:project) { create(:project, :repository) }
+
+ it 'finds a commit using Git' do
+ commit = project.commit
+ found = migration.find_commit(project, commit.sha)
+
+ expect(found).to eq(commit.to_hash)
+ end
+
+ it 'caches the results' do
+ commit = project.commit
+
+ migration.find_commit(project, commit.sha)
+
+ expect { migration.find_commit(project, commit.sha) }
+ .not_to change { Gitlab::GitalyClient.get_request_count }
+ end
+
+ it 'returns an empty hash if the commit does not exist' do
+ expect(migration.find_commit(project, 'kittens')).to eq({})
+ end
+ end
+
+ describe '#find_or_create_user' do
+ let(:project) { create(:project, :repository) }
+
+ it 'creates missing users' do
+ commit = project.commit.to_hash
+ id = migration.find_or_create_user(commit, :author_name, :author_email)
+
+ expect(MergeRequest::DiffCommitUser.count).to eq(1)
+
+ created = MergeRequest::DiffCommitUser.first
+
+ expect(created.name).to eq(commit[:author_name])
+ expect(created.email).to eq(commit[:author_email])
+ expect(created.id).to eq(id)
+ end
+
+ it 'returns users that already exist' do
+ commit = project.commit.to_hash
+ user1 = migration.find_or_create_user(commit, :author_name, :author_email)
+ user2 = migration.find_or_create_user(commit, :author_name, :author_email)
+
+ expect(user1).to eq(user2)
+ end
+
+ it 'caches the results' do
+ commit = project.commit.to_hash
+
+ migration.find_or_create_user(commit, :author_name, :author_email)
+
+ recorder = ActiveRecord::QueryRecorder.new do
+ migration.find_or_create_user(commit, :author_name, :author_email)
+ end
+
+ expect(recorder.count).to be_zero
+ end
+
+ it 'returns nil if the commit details are missing' do
+ id = migration.find_or_create_user({}, :author_name, :author_email)
+
+ expect(id).to be_nil
+ end
+ end
+
+ describe '#matches_row' do
+ it 'returns the query matches for the composite primary key' do
+ row = double(:commit, merge_request_diff_id: 4, relative_order: 5)
+ arel = migration.matches_row(row)
+
+ expect(arel.to_sql).to eq(
+ '("merge_request_diff_commits"."merge_request_diff_id", "merge_request_diff_commits"."relative_order") = (4, 5)'
+ )
+ end
+ end
+end
+# rubocop: enable RSpec/FactoriesInMigrationSpecs
diff --git a/spec/lib/gitlab/background_migration/fix_projects_without_project_feature_spec.rb b/spec/lib/gitlab/background_migration/fix_projects_without_project_feature_spec.rb
deleted file mode 100644
index d503824041b..00000000000
--- a/spec/lib/gitlab/background_migration/fix_projects_without_project_feature_spec.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::FixProjectsWithoutProjectFeature, schema: 2020_01_27_111840 do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:project_features) { table(:project_features) }
-
- let(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
-
- let!(:project) { projects.create!(namespace_id: namespace.id) }
- let(:private_project_without_feature) { projects.create!(namespace_id: namespace.id, visibility_level: 0) }
- let(:public_project_without_feature) { projects.create!(namespace_id: namespace.id, visibility_level: 20) }
- let!(:projects_without_feature) { [private_project_without_feature, public_project_without_feature] }
-
- before do
- project_features.create!({ project_id: project.id, pages_access_level: 20 })
- end
-
- subject { described_class.new.perform(Project.minimum(:id), Project.maximum(:id)) }
-
- def project_feature_records
- project_features.order(:project_id).pluck(:project_id)
- end
-
- def features(project)
- project_features.find_by(project_id: project.id)&.attributes
- end
-
- it 'creates a ProjectFeature for projects without it' do
- expect { subject }.to change { project_feature_records }.from([project.id]).to([project.id, *projects_without_feature.map(&:id)])
- end
-
- it 'creates ProjectFeature records with default values for a public project' do
- subject
-
- expect(features(public_project_without_feature)).to include(
- {
- "merge_requests_access_level" => 20,
- "issues_access_level" => 20,
- "wiki_access_level" => 20,
- "snippets_access_level" => 20,
- "builds_access_level" => 20,
- "repository_access_level" => 20,
- "pages_access_level" => 20,
- "forking_access_level" => 20
- }
- )
- end
-
- it 'creates ProjectFeature records with default values for a private project' do
- subject
-
- expect(features(private_project_without_feature)).to include("pages_access_level" => 10)
- end
-
- context 'when access control to pages is forced' do
- before do
- allow(::Gitlab::Pages).to receive(:access_control_is_forced?).and_return(true)
- end
-
- it 'creates ProjectFeature records with default values for a public project' do
- subject
-
- expect(features(public_project_without_feature)).to include("pages_access_level" => 10)
- end
- end
-
- it 'sets created_at/updated_at timestamps' do
- subject
-
- expect(project_features.where('created_at IS NULL OR updated_at IS NULL')).to be_empty
- end
-end
diff --git a/spec/lib/gitlab/background_migration/fix_projects_without_prometheus_service_spec.rb b/spec/lib/gitlab/background_migration/fix_projects_without_prometheus_service_spec.rb
deleted file mode 100644
index 9a497a9e01a..00000000000
--- a/spec/lib/gitlab/background_migration/fix_projects_without_prometheus_service_spec.rb
+++ /dev/null
@@ -1,234 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::FixProjectsWithoutPrometheusService, :migration, schema: 2020_02_20_115023 do
- def service_params_for(project_id, params = {})
- {
- project_id: project_id,
- active: false,
- properties: '{}',
- type: 'PrometheusService',
- template: false,
- push_events: true,
- issues_events: true,
- merge_requests_events: true,
- tag_push_events: true,
- note_events: true,
- category: 'monitoring',
- default: false,
- wiki_page_events: true,
- pipeline_events: true,
- confidential_issues_events: true,
- commit_events: true,
- job_events: true,
- confidential_note_events: true,
- deployment_events: false
- }.merge(params)
- end
-
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:services) { table(:services) }
- let(:clusters) { table(:clusters) }
- let(:cluster_groups) { table(:cluster_groups) }
- let(:clusters_applications_prometheus) { table(:clusters_applications_prometheus) }
- let(:namespace) { namespaces.create!(name: 'user', path: 'user') }
- let(:project) { projects.create!(namespace_id: namespace.id) }
-
- let(:application_statuses) do
- {
- errored: -1,
- installed: 3,
- updated: 5
- }
- end
-
- let(:cluster_types) do
- {
- instance_type: 1,
- group_type: 2,
- project_type: 3
- }
- end
-
- let(:columns) do
- %w(project_id active properties type template push_events
- issues_events merge_requests_events tag_push_events
- note_events category default wiki_page_events pipeline_events
- confidential_issues_events commit_events job_events
- confidential_note_events deployment_events)
- end
-
- describe '#perform' do
- shared_examples 'fix services entries state' do
- it 'is idempotent' do
- expect { subject.perform(project.id, project.id + 1) }.to change { services.order(:id).map { |row| row.attributes } }
-
- expect { subject.perform(project.id, project.id + 1) }.not_to change { services.order(:id).map { |row| row.attributes } }
- end
-
- context 'non prometheus services' do
- it 'does not change them' do
- other_type = 'SomeOtherService'
- services.create!(service_params_for(project.id, active: true, type: other_type))
-
- expect { subject.perform(project.id, project.id + 1) }.not_to change { services.where(type: other_type).order(:id).map { |row| row.attributes } }
- end
- end
-
- context 'prometheus integration services do not exist' do
- it 'creates missing services entries', :aggregate_failures do
- expect { subject.perform(project.id, project.id + 1) }.to change { services.count }.by(1)
- expect([service_params_for(project.id, active: true)]).to eq services.order(:id).map { |row| row.attributes.slice(*columns).symbolize_keys }
- end
-
- context 'template is present for prometheus services' do
- it 'creates missing services entries', :aggregate_failures do
- services.create!(service_params_for(nil, template: true, properties: { 'from_template' => true }.to_json))
-
- expect { subject.perform(project.id, project.id + 1) }.to change { services.count }.by(1)
- updated_rows = services.where(template: false).order(:id).map { |row| row.attributes.slice(*columns).symbolize_keys }
- expect([service_params_for(project.id, active: true, properties: { 'from_template' => true }.to_json)]).to eq updated_rows
- end
- end
- end
-
- context 'prometheus integration services exist' do
- context 'in active state' do
- it 'does not change them' do
- services.create!(service_params_for(project.id, active: true))
-
- expect { subject.perform(project.id, project.id + 1) }.not_to change { services.order(:id).map { |row| row.attributes } }
- end
- end
-
- context 'not in active state' do
- it 'sets active attribute to true' do
- service = services.create!(service_params_for(project.id, active: false))
-
- expect { subject.perform(project.id, project.id + 1) }.to change { service.reload.active? }.from(false).to(true)
- end
-
- context 'prometheus services are configured manually ' do
- it 'does not change them' do
- properties = '{"api_url":"http://test.dev","manual_configuration":"1"}'
- services.create!(service_params_for(project.id, properties: properties, active: false))
-
- expect { subject.perform(project.id, project.id + 1) }.not_to change { services.order(:id).map { |row| row.attributes } }
- end
- end
- end
- end
- end
-
- context 'k8s cluster shared on instance level' do
- let(:cluster) { clusters.create!(name: 'cluster', cluster_type: cluster_types[:instance_type]) }
-
- context 'with installed prometheus application' do
- before do
- clusters_applications_prometheus.create!(cluster_id: cluster.id, status: application_statuses[:installed], version: '123')
- end
-
- it_behaves_like 'fix services entries state'
- end
-
- context 'with updated prometheus application' do
- before do
- clusters_applications_prometheus.create!(cluster_id: cluster.id, status: application_statuses[:updated], version: '123')
- end
-
- it_behaves_like 'fix services entries state'
- end
-
- context 'with errored prometheus application' do
- before do
- clusters_applications_prometheus.create!(cluster_id: cluster.id, status: application_statuses[:errored], version: '123')
- end
-
- it 'does not change services entries' do
- expect { subject.perform(project.id, project.id + 1) }.not_to change { services.order(:id).map { |row| row.attributes } }
- end
- end
- end
-
- context 'k8s cluster shared on group level' do
- let(:cluster) { clusters.create!(name: 'cluster', cluster_type: cluster_types[:group_type]) }
-
- before do
- cluster_groups.create!(cluster_id: cluster.id, group_id: project.namespace_id)
- end
-
- context 'with installed prometheus application' do
- before do
- clusters_applications_prometheus.create!(cluster_id: cluster.id, status: application_statuses[:installed], version: '123')
- end
-
- it_behaves_like 'fix services entries state'
-
- context 'second k8s cluster without application available' do
- let(:namespace_2) { namespaces.create!(name: 'namespace2', path: 'namespace2') }
- let(:project_2) { projects.create!(namespace_id: namespace_2.id) }
-
- before do
- cluster_2 = clusters.create!(name: 'cluster2', cluster_type: cluster_types[:group_type])
- cluster_groups.create!(cluster_id: cluster_2.id, group_id: project_2.namespace_id)
- end
-
- it 'changed only affected services entries' do
- expect { subject.perform(project.id, project_2.id + 1) }.to change { services.count }.by(1)
- expect([service_params_for(project.id, active: true)]).to eq services.order(:id).map { |row| row.attributes.slice(*columns).symbolize_keys }
- end
- end
- end
-
- context 'with updated prometheus application' do
- before do
- clusters_applications_prometheus.create!(cluster_id: cluster.id, status: application_statuses[:updated], version: '123')
- end
-
- it_behaves_like 'fix services entries state'
- end
-
- context 'with errored prometheus application' do
- before do
- clusters_applications_prometheus.create!(cluster_id: cluster.id, status: application_statuses[:errored], version: '123')
- end
-
- it 'does not change services entries' do
- expect { subject.perform(project.id, project.id + 1) }.not_to change { services.order(:id).map { |row| row.attributes } }
- end
- end
-
- context 'with missing prometheus application' do
- it 'does not change services entries' do
- expect { subject.perform(project.id, project.id + 1) }.not_to change { services.order(:id).map { |row| row.attributes } }
- end
-
- context 'with inactive service' do
- it 'does not change services entries' do
- services.create!(service_params_for(project.id))
-
- expect { subject.perform(project.id, project.id + 1) }.not_to change { services.order(:id).map { |row| row.attributes } }
- end
- end
- end
- end
-
- context 'k8s cluster for single project' do
- let(:cluster) { clusters.create!(name: 'cluster', cluster_type: cluster_types[:project_type]) }
- let(:cluster_projects) { table(:cluster_projects) }
-
- context 'with installed prometheus application' do
- before do
- cluster_projects.create!(cluster_id: cluster.id, project_id: project.id)
- clusters_applications_prometheus.create!(cluster_id: cluster.id, status: application_statuses[:installed], version: '123')
- end
-
- it 'does not change services entries' do
- expect { subject.perform(project.id, project.id + 1) }.not_to change { services.order(:id).map { |row| row.attributes } }
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/job_coordinator_spec.rb b/spec/lib/gitlab/background_migration/job_coordinator_spec.rb
new file mode 100644
index 00000000000..a0543ca9958
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/job_coordinator_spec.rb
@@ -0,0 +1,344 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::JobCoordinator do
+ let(:database) { :main }
+ let(:worker_class) { BackgroundMigrationWorker }
+ let(:coordinator) { described_class.new(database, worker_class) }
+
+ describe '.for_database' do
+ it 'returns an executor with the correct worker class and database' do
+ coordinator = described_class.for_database(database)
+
+ expect(coordinator.database).to eq(database)
+ expect(coordinator.worker_class).to eq(worker_class)
+ end
+
+ context 'when passed in as a string' do
+ it 'retruns an executor with the correct worker class and database' do
+ coordinator = described_class.for_database(database.to_s)
+
+ expect(coordinator.database).to eq(database)
+ expect(coordinator.worker_class).to eq(worker_class)
+ end
+ end
+
+ context 'when an invalid value is given' do
+ it 'raises an error' do
+ expect do
+ described_class.for_database('notvalid')
+ end.to raise_error(ArgumentError, "database must be one of [main], got 'notvalid'")
+ end
+ end
+ end
+
+ describe '#queue' do
+ it 'returns background migration worker queue' do
+ expect(coordinator.queue).to eq(worker_class.sidekiq_options['queue'])
+ end
+ end
+
+ describe '#with_shared_connection' do
+ it 'yields to the block after properly configuring SharedModel' do
+ expect(Gitlab::Database::SharedModel).to receive(:using_connection)
+ .with(ActiveRecord::Base.connection).and_yield
+
+ expect { |b| coordinator.with_shared_connection(&b) }.to yield_with_no_args
+ end
+ end
+
+ describe '#steal' do
+ context 'when there are enqueued jobs present' do
+ let(:queue) do
+ [
+ double(args: ['Foo', [10, 20]], klass: worker_class.name),
+ double(args: ['Bar', [20, 30]], klass: worker_class.name),
+ double(args: ['Foo', [20, 30]], klass: 'MergeWorker')
+ ]
+ end
+
+ before do
+ allow(Sidekiq::Queue).to receive(:new)
+ .with(coordinator.queue)
+ .and_return(queue)
+ end
+
+ context 'when queue contains unprocessed jobs' do
+ it 'steals jobs from a queue' do
+ expect(queue[0]).to receive(:delete).and_return(true)
+
+ expect(coordinator).to receive(:perform).with('Foo', [10, 20])
+
+ coordinator.steal('Foo')
+ end
+
+ it 'sets up the shared connection while stealing jobs' do
+ connection = double('connection')
+ allow(coordinator).to receive(:connection).and_return(connection)
+
+ expect(coordinator).to receive(:with_shared_connection).and_call_original
+
+ expect(queue[0]).to receive(:delete).and_return(true)
+
+ expect(coordinator).to receive(:perform).with('Foo', [10, 20]) do
+ expect(Gitlab::Database::SharedModel.connection).to be(connection)
+ end
+
+ coordinator.steal('Foo') do
+ expect(Gitlab::Database::SharedModel.connection).to be(connection)
+
+ true # the job is only performed if the block returns true
+ end
+ end
+
+ it 'does not steal job that has already been taken' do
+ expect(queue[0]).to receive(:delete).and_return(false)
+
+ expect(coordinator).not_to receive(:perform)
+
+ coordinator.steal('Foo')
+ end
+
+ it 'does not steal jobs for a different migration' do
+ expect(coordinator).not_to receive(:perform)
+
+ expect(queue[0]).not_to receive(:delete)
+
+ coordinator.steal('Baz')
+ end
+
+ context 'when a custom predicate is given' do
+ it 'steals jobs that match the predicate' do
+ expect(queue[0]).to receive(:delete).and_return(true)
+
+ expect(coordinator).to receive(:perform).with('Foo', [10, 20])
+
+ coordinator.steal('Foo') { |job| job.args.second.first == 10 && job.args.second.second == 20 }
+ end
+
+ it 'does not steal jobs that do not match the predicate' do
+ expect(described_class).not_to receive(:perform)
+
+ expect(queue[0]).not_to receive(:delete)
+
+ coordinator.steal('Foo') { |(arg1, _)| arg1 == 5 }
+ end
+ end
+ end
+
+ context 'when one of the jobs raises an error' do
+ let(:migration) { spy(:migration) }
+
+ let(:queue) do
+ [double(args: ['Foo', [10, 20]], klass: worker_class.name),
+ double(args: ['Foo', [20, 30]], klass: worker_class.name)]
+ end
+
+ before do
+ stub_const('Gitlab::BackgroundMigration::Foo', migration)
+
+ allow(queue[0]).to receive(:delete).and_return(true)
+ allow(queue[1]).to receive(:delete).and_return(true)
+ end
+
+ it 'enqueues the migration again and re-raises the error' do
+ allow(migration).to receive(:perform).with(10, 20).and_raise(Exception, 'Migration error').once
+
+ expect(worker_class).to receive(:perform_async).with('Foo', [10, 20]).once
+
+ expect { coordinator.steal('Foo') }.to raise_error(Exception)
+ end
+ end
+ end
+
+ context 'when there are scheduled jobs present', :redis do
+ it 'steals all jobs from the scheduled sets' do
+ Sidekiq::Testing.disable! do
+ worker_class.perform_in(10.minutes, 'Object')
+
+ expect(Sidekiq::ScheduledSet.new).to be_one
+ expect(coordinator).to receive(:perform).with('Object', any_args)
+
+ coordinator.steal('Object')
+
+ expect(Sidekiq::ScheduledSet.new).to be_none
+ end
+ end
+ end
+
+ context 'when there are enqueued and scheduled jobs present', :redis do
+ it 'steals from the scheduled sets queue first' do
+ Sidekiq::Testing.disable! do
+ expect(coordinator).to receive(:perform).with('Object', [1]).ordered
+ expect(coordinator).to receive(:perform).with('Object', [2]).ordered
+
+ worker_class.perform_async('Object', [2])
+ worker_class.perform_in(10.minutes, 'Object', [1])
+
+ coordinator.steal('Object')
+ end
+ end
+ end
+
+ context 'when retry_dead_jobs is true', :redis do
+ let(:retry_queue) do
+ [double(args: ['Object', [3]], klass: worker_class.name, delete: true)]
+ end
+
+ let(:dead_queue) do
+ [double(args: ['Object', [4]], klass: worker_class.name, delete: true)]
+ end
+
+ before do
+ allow(Sidekiq::RetrySet).to receive(:new).and_return(retry_queue)
+ allow(Sidekiq::DeadSet).to receive(:new).and_return(dead_queue)
+ end
+
+ it 'steals from the dead and retry queue' do
+ Sidekiq::Testing.disable! do
+ expect(coordinator).to receive(:perform).with('Object', [1]).ordered
+ expect(coordinator).to receive(:perform).with('Object', [2]).ordered
+ expect(coordinator).to receive(:perform).with('Object', [3]).ordered
+ expect(coordinator).to receive(:perform).with('Object', [4]).ordered
+
+ worker_class.perform_async('Object', [2])
+ worker_class.perform_in(10.minutes, 'Object', [1])
+
+ coordinator.steal('Object', retry_dead_jobs: true)
+ end
+ end
+ end
+ end
+
+ describe '#perform' do
+ let(:migration) { spy(:migration) }
+ let(:connection) { double('connection') }
+
+ before do
+ stub_const('Gitlab::BackgroundMigration::Foo', migration)
+
+ allow(coordinator).to receive(:connection).and_return(connection)
+ end
+
+ it 'performs a background migration with the configured shared connection' do
+ expect(coordinator).to receive(:with_shared_connection).and_call_original
+
+ expect(migration).to receive(:perform).with(10, 20).once do
+ expect(Gitlab::Database::SharedModel.connection).to be(connection)
+ end
+
+ coordinator.perform('Foo', [10, 20])
+ end
+ end
+
+ describe '.remaining', :redis do
+ context 'when there are jobs remaining' do
+ before do
+ Sidekiq::Testing.disable! do
+ MergeWorker.perform_async('Foo')
+ MergeWorker.perform_in(10.minutes, 'Foo')
+
+ 5.times do
+ worker_class.perform_async('Foo')
+ end
+ 3.times do
+ worker_class.perform_in(10.minutes, 'Foo')
+ end
+ end
+ end
+
+ it 'returns the enqueued jobs plus the scheduled jobs' do
+ expect(coordinator.remaining).to eq(8)
+ end
+ end
+
+ context 'when there are no jobs remaining' do
+ it 'returns zero' do
+ expect(coordinator.remaining).to be_zero
+ end
+ end
+ end
+
+ describe '.exists?', :redis do
+ context 'when there are enqueued jobs present' do
+ before do
+ Sidekiq::Testing.disable! do
+ MergeWorker.perform_async('Bar')
+ worker_class.perform_async('Foo')
+ end
+ end
+
+ it 'returns true if specific job exists' do
+ expect(coordinator.exists?('Foo')).to eq(true)
+ end
+
+ it 'returns false if specific job does not exist' do
+ expect(coordinator.exists?('Bar')).to eq(false)
+ end
+ end
+
+ context 'when there are scheduled jobs present' do
+ before do
+ Sidekiq::Testing.disable! do
+ MergeWorker.perform_in(10.minutes, 'Bar')
+ worker_class.perform_in(10.minutes, 'Foo')
+ end
+ end
+
+ it 'returns true if specific job exists' do
+ expect(coordinator.exists?('Foo')).to eq(true)
+ end
+
+ it 'returns false if specific job does not exist' do
+ expect(coordinator.exists?('Bar')).to eq(false)
+ end
+ end
+ end
+
+ describe '.dead_jobs?' do
+ let(:queue) do
+ [
+ double(args: ['Foo', [10, 20]], klass: worker_class.name),
+ double(args: ['Bar'], klass: 'MergeWorker')
+ ]
+ end
+
+ context 'when there are dead jobs present' do
+ before do
+ allow(Sidekiq::DeadSet).to receive(:new).and_return(queue)
+ end
+
+ it 'returns true if specific job exists' do
+ expect(coordinator.dead_jobs?('Foo')).to eq(true)
+ end
+
+ it 'returns false if specific job does not exist' do
+ expect(coordinator.dead_jobs?('Bar')).to eq(false)
+ end
+ end
+ end
+
+ describe '.retrying_jobs?' do
+ let(:queue) do
+ [
+ double(args: ['Foo', [10, 20]], klass: worker_class.name),
+ double(args: ['Bar'], klass: 'MergeWorker')
+ ]
+ end
+
+ context 'when there are dead jobs present' do
+ before do
+ allow(Sidekiq::RetrySet).to receive(:new).and_return(queue)
+ end
+
+ it 'returns true if specific job exists' do
+ expect(coordinator.retrying_jobs?('Foo')).to eq(true)
+ end
+
+ it 'returns false if specific job does not exist' do
+ expect(coordinator.retrying_jobs?('Bar')).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/link_lfs_objects_projects_spec.rb b/spec/lib/gitlab/background_migration/link_lfs_objects_projects_spec.rb
index b7cf101dd8a..64e8afedf52 100644
--- a/spec/lib/gitlab/background_migration/link_lfs_objects_projects_spec.rb
+++ b/spec/lib/gitlab/background_migration/link_lfs_objects_projects_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::LinkLfsObjectsProjects, :migration, schema: 2020_03_10_075115 do
+RSpec.describe Gitlab::BackgroundMigration::LinkLfsObjectsProjects, :migration, schema: 20181228175414 do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
let(:fork_networks) { table(:fork_networks) }
diff --git a/spec/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys_spec.rb b/spec/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys_spec.rb
index c58b2d609e9..4287d6723cf 100644
--- a/spec/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys_spec.rb
+++ b/spec/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::MigrateFingerprintSha256WithinKeys, schema: 20200106071113 do
+RSpec.describe Gitlab::BackgroundMigration::MigrateFingerprintSha256WithinKeys, schema: 20181228175414 do
subject(:fingerprint_migrator) { described_class.new }
let(:key_table) { table(:keys) }
diff --git a/spec/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data_spec.rb b/spec/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data_spec.rb
deleted file mode 100644
index f2cd2acd4f3..00000000000
--- a/spec/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data_spec.rb
+++ /dev/null
@@ -1,327 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::MigrateIssueTrackersSensitiveData, schema: 20200130145430 do
- let(:services) { table(:services) }
-
- before do
- # we need to define the classes due to encryption
- issue_tracker_data = Class.new(ApplicationRecord) do
- self.table_name = 'issue_tracker_data'
-
- def self.encryption_options
- {
- key: Settings.attr_encrypted_db_key_base_32,
- encode: true,
- mode: :per_attribute_iv,
- algorithm: 'aes-256-gcm'
- }
- end
-
- attr_encrypted :project_url, encryption_options
- attr_encrypted :issues_url, encryption_options
- attr_encrypted :new_issue_url, encryption_options
- end
-
- jira_tracker_data = Class.new(ApplicationRecord) do
- self.table_name = 'jira_tracker_data'
-
- def self.encryption_options
- {
- key: Settings.attr_encrypted_db_key_base_32,
- encode: true,
- mode: :per_attribute_iv,
- algorithm: 'aes-256-gcm'
- }
- end
-
- attr_encrypted :url, encryption_options
- attr_encrypted :api_url, encryption_options
- attr_encrypted :username, encryption_options
- attr_encrypted :password, encryption_options
- end
-
- stub_const('IssueTrackerData', issue_tracker_data)
- stub_const('JiraTrackerData', jira_tracker_data)
- end
-
- let(:url) { 'http://base-url.tracker.com' }
- let(:new_issue_url) { 'http://base-url.tracker.com/new_issue' }
- let(:issues_url) { 'http://base-url.tracker.com/issues' }
- let(:api_url) { 'http://api.tracker.com' }
- let(:password) { 'passw1234' }
- let(:username) { 'user9' }
- let(:title) { 'Issue tracker' }
- let(:description) { 'Issue tracker description' }
-
- let(:jira_properties) do
- {
- 'api_url' => api_url,
- 'jira_issue_transition_id' => '5',
- 'password' => password,
- 'url' => url,
- 'username' => username,
- 'title' => title,
- 'description' => description,
- 'other_field' => 'something'
- }
- end
-
- let(:tracker_properties) do
- {
- 'project_url' => url,
- 'new_issue_url' => new_issue_url,
- 'issues_url' => issues_url,
- 'title' => title,
- 'description' => description,
- 'other_field' => 'something'
- }
- end
-
- let(:tracker_properties_no_url) do
- {
- 'new_issue_url' => new_issue_url,
- 'issues_url' => issues_url,
- 'title' => title,
- 'description' => description
- }
- end
-
- subject { described_class.new.perform(1, 100) }
-
- shared_examples 'handle properties' do
- it 'does not clear the properties' do
- expect { subject }.not_to change { service.reload.properties}
- end
- end
-
- context 'with Jira service' do
- let!(:service) do
- services.create!(id: 10, type: 'JiraService', title: nil, properties: jira_properties.to_json, category: 'issue_tracker')
- end
-
- it_behaves_like 'handle properties'
-
- it 'migrates data' do
- expect { subject }.to change { JiraTrackerData.count }.by(1)
-
- service.reload
- data = JiraTrackerData.find_by(service_id: service.id)
-
- expect(data.url).to eq(url)
- expect(data.api_url).to eq(api_url)
- expect(data.username).to eq(username)
- expect(data.password).to eq(password)
- expect(service.title).to eq(title)
- expect(service.description).to eq(description)
- end
- end
-
- context 'with bugzilla service' do
- let!(:service) do
- services.create!(id: 11, type: 'BugzillaService', title: nil, properties: tracker_properties.to_json, category: 'issue_tracker')
- end
-
- it_behaves_like 'handle properties'
-
- it 'migrates data' do
- expect { subject }.to change { IssueTrackerData.count }.by(1)
-
- service.reload
- data = IssueTrackerData.find_by(service_id: service.id)
-
- expect(data.project_url).to eq(url)
- expect(data.issues_url).to eq(issues_url)
- expect(data.new_issue_url).to eq(new_issue_url)
- expect(service.title).to eq(title)
- expect(service.description).to eq(description)
- end
- end
-
- context 'with youtrack service' do
- let!(:service) do
- services.create!(id: 12, type: 'YoutrackService', title: nil, properties: tracker_properties_no_url.to_json, category: 'issue_tracker')
- end
-
- it_behaves_like 'handle properties'
-
- it 'migrates data' do
- expect { subject }.to change { IssueTrackerData.count }.by(1)
-
- service.reload
- data = IssueTrackerData.find_by(service_id: service.id)
-
- expect(data.project_url).to be_nil
- expect(data.issues_url).to eq(issues_url)
- expect(data.new_issue_url).to eq(new_issue_url)
- expect(service.title).to eq(title)
- expect(service.description).to eq(description)
- end
- end
-
- context 'with gitlab service with no properties' do
- let!(:service) do
- services.create!(id: 13, type: 'GitlabIssueTrackerService', title: nil, properties: {}, category: 'issue_tracker')
- end
-
- it_behaves_like 'handle properties'
-
- it 'does not migrate data' do
- expect { subject }.not_to change { IssueTrackerData.count }
- end
- end
-
- context 'with redmine service already with data fields' do
- let!(:service) do
- services.create!(id: 14, type: 'RedmineService', title: nil, properties: tracker_properties_no_url.to_json, category: 'issue_tracker').tap do |service|
- IssueTrackerData.create!(service_id: service.id, project_url: url, new_issue_url: new_issue_url, issues_url: issues_url)
- end
- end
-
- it_behaves_like 'handle properties'
-
- it 'does not create new data fields record' do
- expect { subject }.not_to change { IssueTrackerData.count }
- end
- end
-
- context 'with custom issue tracker which has data fields record inconsistent with properties field' do
- let!(:service) do
- services.create!(id: 15, type: 'CustomIssueTrackerService', title: 'Existing title', properties: jira_properties.to_json, category: 'issue_tracker').tap do |service|
- IssueTrackerData.create!(service_id: service.id, project_url: 'http://other_url', new_issue_url: 'http://other_url/new_issue', issues_url: 'http://other_url/issues')
- end
- end
-
- it_behaves_like 'handle properties'
-
- it 'does not update the data fields record' do
- expect { subject }.not_to change { IssueTrackerData.count }
-
- service.reload
- data = IssueTrackerData.find_by(service_id: service.id)
-
- expect(data.project_url).to eq('http://other_url')
- expect(data.issues_url).to eq('http://other_url/issues')
- expect(data.new_issue_url).to eq('http://other_url/new_issue')
- expect(service.title).to eq('Existing title')
- end
- end
-
- context 'with Jira service which has data fields record inconsistent with properties field' do
- let!(:service) do
- services.create!(id: 16, type: 'CustomIssueTrackerService', description: 'Existing description', properties: jira_properties.to_json, category: 'issue_tracker').tap do |service|
- JiraTrackerData.create!(service_id: service.id, url: 'http://other_jira_url')
- end
- end
-
- it_behaves_like 'handle properties'
-
- it 'does not update the data fields record' do
- expect { subject }.not_to change { JiraTrackerData.count }
-
- service.reload
- data = JiraTrackerData.find_by(service_id: service.id)
-
- expect(data.url).to eq('http://other_jira_url')
- expect(data.password).to be_nil
- expect(data.username).to be_nil
- expect(data.api_url).to be_nil
- expect(service.description).to eq('Existing description')
- end
- end
-
- context 'non issue tracker service' do
- let!(:service) do
- services.create!(id: 17, title: nil, description: nil, type: 'OtherService', properties: tracker_properties.to_json)
- end
-
- it_behaves_like 'handle properties'
-
- it 'does not migrate any data' do
- expect { subject }.not_to change { IssueTrackerData.count }
-
- service.reload
- expect(service.title).to be_nil
- expect(service.description).to be_nil
- end
- end
-
- context 'Jira service with empty properties' do
- let!(:service) do
- services.create!(id: 18, type: 'JiraService', properties: '', category: 'issue_tracker')
- end
-
- it_behaves_like 'handle properties'
-
- it 'does not migrate any data' do
- expect { subject }.not_to change { JiraTrackerData.count }
- end
- end
-
- context 'Jira service with nil properties' do
- let!(:service) do
- services.create!(id: 18, type: 'JiraService', properties: nil, category: 'issue_tracker')
- end
-
- it_behaves_like 'handle properties'
-
- it 'does not migrate any data' do
- expect { subject }.not_to change { JiraTrackerData.count }
- end
- end
-
- context 'Jira service with invalid properties' do
- let!(:service) do
- services.create!(id: 18, type: 'JiraService', properties: 'invalid data', category: 'issue_tracker')
- end
-
- it_behaves_like 'handle properties'
-
- it 'does not migrate any data' do
- expect { subject }.not_to change { JiraTrackerData.count }
- end
- end
-
- context 'with Jira service with invalid properties, valid Jira service and valid bugzilla service' do
- let!(:jira_integration_invalid) do
- services.create!(id: 19, title: 'invalid - title', description: 'invalid - description', type: 'JiraService', properties: 'invalid data', category: 'issue_tracker')
- end
-
- let!(:jira_integration_valid) do
- services.create!(id: 20, type: 'JiraService', properties: jira_properties.to_json, category: 'issue_tracker')
- end
-
- let!(:bugzilla_integration_valid) do
- services.create!(id: 11, type: 'BugzillaService', title: nil, properties: tracker_properties.to_json, category: 'issue_tracker')
- end
-
- it 'migrates data for the valid service' do
- subject
-
- jira_integration_invalid.reload
- expect(JiraTrackerData.find_by(service_id: jira_integration_invalid.id)).to be_nil
- expect(jira_integration_invalid.title).to eq('invalid - title')
- expect(jira_integration_invalid.description).to eq('invalid - description')
- expect(jira_integration_invalid.properties).to eq('invalid data')
-
- jira_integration_valid.reload
- data = JiraTrackerData.find_by(service_id: jira_integration_valid.id)
-
- expect(data.url).to eq(url)
- expect(data.api_url).to eq(api_url)
- expect(data.username).to eq(username)
- expect(data.password).to eq(password)
- expect(jira_integration_valid.title).to eq(title)
- expect(jira_integration_valid.description).to eq(description)
-
- bugzilla_integration_valid.reload
- data = IssueTrackerData.find_by(service_id: bugzilla_integration_valid.id)
-
- expect(data.project_url).to eq(url)
- expect(data.issues_url).to eq(issues_url)
- expect(data.new_issue_url).to eq(new_issue_url)
- expect(bugzilla_integration_valid.title).to eq(title)
- expect(bugzilla_integration_valid.description).to eq(description)
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb b/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb
index 91e8dcdf880..31b6ee0c7cd 100644
--- a/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb
+++ b/spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::MigrateMergeRequestDiffCommitUsers do
+RSpec.describe Gitlab::BackgroundMigration::MigrateMergeRequestDiffCommitUsers, schema: 20211012134316 do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
let(:users) { table(:users) }
diff --git a/spec/lib/gitlab/background_migration/migrate_u2f_webauthn_spec.rb b/spec/lib/gitlab/background_migration/migrate_u2f_webauthn_spec.rb
index 9eda51f6ec4..ab183d01357 100644
--- a/spec/lib/gitlab/background_migration/migrate_u2f_webauthn_spec.rb
+++ b/spec/lib/gitlab/background_migration/migrate_u2f_webauthn_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
require 'webauthn/u2f_migrator'
-RSpec.describe Gitlab::BackgroundMigration::MigrateU2fWebauthn, :migration, schema: 20200925125321 do
+RSpec.describe Gitlab::BackgroundMigration::MigrateU2fWebauthn, :migration, schema: 20181228175414 do
let(:users) { table(:users) }
let(:user) { users.create!(email: 'email@email.com', name: 'foo', username: 'foo', projects_limit: 0) }
diff --git a/spec/lib/gitlab/background_migration/migrate_users_bio_to_user_details_spec.rb b/spec/lib/gitlab/background_migration/migrate_users_bio_to_user_details_spec.rb
deleted file mode 100644
index d90a5d30954..00000000000
--- a/spec/lib/gitlab/background_migration/migrate_users_bio_to_user_details_spec.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::MigrateUsersBioToUserDetails, :migration, schema: 20200323074147 do
- let(:users) { table(:users) }
-
- let(:user_details) do
- klass = table(:user_details)
- klass.primary_key = :user_id
- klass
- end
-
- let!(:user_needs_migration) { users.create!(name: 'user1', email: 'test1@test.com', projects_limit: 1, bio: 'bio') }
- let!(:user_needs_no_migration) { users.create!(name: 'user2', email: 'test2@test.com', projects_limit: 1) }
- let!(:user_also_needs_no_migration) { users.create!(name: 'user3', email: 'test3@test.com', projects_limit: 1, bio: '') }
- let!(:user_with_long_bio) { users.create!(name: 'user4', email: 'test4@test.com', projects_limit: 1, bio: 'a' * 256) } # 255 is the max
-
- let!(:user_already_has_details) { users.create!(name: 'user5', email: 'test5@test.com', projects_limit: 1, bio: 'my bio') }
- let!(:existing_user_details) { user_details.find_or_create_by!(user_id: user_already_has_details.id).update!(bio: 'my bio') }
-
- # unlikely scenario since we have triggers
- let!(:user_has_different_details) { users.create!(name: 'user6', email: 'test6@test.com', projects_limit: 1, bio: 'different') }
- let!(:different_existing_user_details) { user_details.find_or_create_by!(user_id: user_has_different_details.id).update!(bio: 'bio') }
-
- let(:user_ids) do
- [
- user_needs_migration,
- user_needs_no_migration,
- user_also_needs_no_migration,
- user_with_long_bio,
- user_already_has_details,
- user_has_different_details
- ].map(&:id)
- end
-
- subject { described_class.new.perform(user_ids.min, user_ids.max) }
-
- it 'migrates all relevant records' do
- subject
-
- all_user_details = user_details.all
- expect(all_user_details.size).to eq(4)
- end
-
- it 'migrates `bio`' do
- subject
-
- user_detail = user_details.find_by!(user_id: user_needs_migration.id)
-
- expect(user_detail.bio).to eq('bio')
- end
-
- it 'migrates long `bio`' do
- subject
-
- user_detail = user_details.find_by!(user_id: user_with_long_bio.id)
-
- expect(user_detail.bio).to eq('a' * 255)
- end
-
- it 'does not change existing user detail' do
- expect { subject }.not_to change { user_details.find_by!(user_id: user_already_has_details.id).attributes }
- end
-
- it 'changes existing user detail when the columns are different' do
- expect { subject }.to change { user_details.find_by!(user_id: user_has_different_details.id).bio }.from('bio').to('different')
- end
-
- it 'does not migrate record' do
- subject
-
- user_detail = user_details.find_by(user_id: user_needs_no_migration.id)
-
- expect(user_detail).to be_nil
- end
-
- it 'does not migrate empty bio' do
- subject
-
- user_detail = user_details.find_by(user_id: user_also_needs_no_migration.id)
-
- expect(user_detail).to be_nil
- end
-end
diff --git a/spec/lib/gitlab/background_migration/populate_canonical_emails_spec.rb b/spec/lib/gitlab/background_migration/populate_canonical_emails_spec.rb
index 36000dc3ffd..944ee98ed4a 100644
--- a/spec/lib/gitlab/background_migration/populate_canonical_emails_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_canonical_emails_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::PopulateCanonicalEmails, :migration, schema: 20200312053852 do
+RSpec.describe Gitlab::BackgroundMigration::PopulateCanonicalEmails, :migration, schema: 20181228175414 do
let(:migration) { described_class.new }
let_it_be(:users_table) { table(:users) }
diff --git a/spec/lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities_spec.rb b/spec/lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities_spec.rb
index bc55f240a58..dc8c8c75b83 100644
--- a/spec/lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe ::Gitlab::BackgroundMigration::PopulateDismissedStateForVulnerabilities, schema: 2020_11_30_103926 do
+RSpec.describe ::Gitlab::BackgroundMigration::PopulateDismissedStateForVulnerabilities, schema: 20181228175414 do
let(:users) { table(:users) }
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
diff --git a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
index 07b1d99d333..25006e663ab 100644
--- a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityFeedback, schema: 20201211090634 do
+RSpec.describe Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityFeedback, schema: 20181228175414 do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
let(:users) { table(:users) }
diff --git a/spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb b/spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb
index c6385340ca3..6722321d5f7 100644
--- a/spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::PopulateHasVulnerabilities, schema: 20201103192526 do
+RSpec.describe Gitlab::BackgroundMigration::PopulateHasVulnerabilities, schema: 20181228175414 do
let(:users) { table(:users) }
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
diff --git a/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb b/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb
index f724b007e01..a03a11489b5 100644
--- a/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::PopulateIssueEmailParticipants, schema: 20201128210234 do
+RSpec.describe Gitlab::BackgroundMigration::PopulateIssueEmailParticipants, schema: 20181228175414 do
let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
let!(:project) { table(:projects).create!(id: 1, namespace_id: namespace.id) }
let!(:issue1) { table(:issues).create!(id: 1, project_id: project.id, service_desk_reply_to: "a@gitlab.com") }
diff --git a/spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb b/spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb
index 44c5f3d1381..1c987d3876f 100644
--- a/spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation, schema: 20201028160832 do
+RSpec.describe Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation, schema: 20181228175414 do
let(:users) { table(:users) }
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
diff --git a/spec/lib/gitlab/background_migration/populate_personal_snippet_statistics_spec.rb b/spec/lib/gitlab/background_migration/populate_personal_snippet_statistics_spec.rb
index e746451b1b9..f9628849dbf 100644
--- a/spec/lib/gitlab/background_migration/populate_personal_snippet_statistics_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_personal_snippet_statistics_spec.rb
@@ -111,11 +111,11 @@ RSpec.describe Gitlab::BackgroundMigration::PopulatePersonalSnippetStatistics do
if with_repo
allow(snippet).to receive(:disk_path).and_return(disk_path(snippet))
+ raw_repository(snippet).create_repository
+
TestEnv.copy_repo(snippet,
bare_repo: TestEnv.factory_repo_path_bare,
refs: TestEnv::BRANCH_SHA)
-
- raw_repository(snippet).create_repository
end
end
end
diff --git a/spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb b/spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb
index 897f5e81372..7884e0d97c0 100644
--- a/spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb
@@ -183,11 +183,11 @@ RSpec.describe Gitlab::BackgroundMigration::PopulateProjectSnippetStatistics do
if with_repo
allow(snippet).to receive(:disk_path).and_return(disk_path(snippet))
+ raw_repository(snippet).create_repository
+
TestEnv.copy_repo(snippet,
bare_repo: TestEnv.factory_repo_path_bare,
refs: TestEnv::BRANCH_SHA)
-
- raw_repository(snippet).create_repository
end
end
end
diff --git a/spec/lib/gitlab/background_migration/populate_user_highest_roles_table_spec.rb b/spec/lib/gitlab/background_migration/populate_user_highest_roles_table_spec.rb
deleted file mode 100644
index b3cacc60cdc..00000000000
--- a/spec/lib/gitlab/background_migration/populate_user_highest_roles_table_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::PopulateUserHighestRolesTable, schema: 20200311130802 do
- let(:members) { table(:members) }
- let(:users) { table(:users) }
- let(:user_highest_roles) { table(:user_highest_roles) }
-
- def create_user(id, params = {})
- user_params = {
- id: id,
- state: 'active',
- user_type: nil,
- bot_type: nil,
- ghost: nil,
- email: "user#{id}@example.com",
- projects_limit: 0
- }.merge(params)
-
- users.create!(user_params)
- end
-
- def create_member(id, access_level, params = {})
- params = {
- user_id: id,
- access_level: access_level,
- source_id: 1,
- source_type: 'Group',
- notification_level: 0
- }.merge(params)
-
- members.create!(params)
- end
-
- before do
- create_user(1)
- create_user(2, state: 'blocked')
- create_user(3, user_type: 2)
- create_user(4)
- create_user(5, bot_type: 1)
- create_user(6, ghost: true)
- create_user(7, ghost: false)
- create_user(8)
-
- create_member(1, 40)
- create_member(7, 30)
- create_member(8, 20, requested_at: Time.current)
-
- user_highest_roles.create!(user_id: 1, highest_access_level: 50)
- end
-
- describe '#perform' do
- it 'creates user_highest_roles rows according to users', :aggregate_failures do
- expect { subject.perform(1, 8) }.to change(UserHighestRole, :count).from(1).to(4)
-
- created_or_updated_rows = [
- { 'user_id' => 1, 'highest_access_level' => 40 },
- { 'user_id' => 4, 'highest_access_level' => nil },
- { 'user_id' => 7, 'highest_access_level' => 30 },
- { 'user_id' => 8, 'highest_access_level' => nil }
- ]
-
- rows = user_highest_roles.order(:user_id).map do |row|
- row.attributes.slice('user_id', 'highest_access_level')
- end
-
- expect(rows).to match_array(created_or_updated_rows)
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb b/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb
new file mode 100644
index 00000000000..24259b06469
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb
@@ -0,0 +1,254 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNamespaces, :migration do
+ include MigrationsHelpers
+
+ context 'when migrating data', :aggregate_failures do
+ let(:projects) { table(:projects) }
+ let(:namespaces) { table(:namespaces) }
+
+ let(:parent_group1) { namespaces.create!(name: 'parent_group1', path: 'parent_group1', visibility_level: 20, type: 'Group') }
+ let(:parent_group2) { namespaces.create!(name: 'test1', path: 'test1', runners_token: 'my-token1', project_creation_level: 1, visibility_level: 20, type: 'Group') }
+
+ let(:parent_group1_project) { projects.create!(name: 'parent_group1_project', path: 'parent_group1_project', namespace_id: parent_group1.id, visibility_level: 20) }
+ let(:parent_group2_project) { projects.create!(name: 'parent_group2_project', path: 'parent_group2_project', namespace_id: parent_group2.id, visibility_level: 20) }
+
+ let(:child_nodes_count) { 2 }
+ let(:tree_depth) { 3 }
+
+ let(:backfilled_namespace) { nil }
+
+ before do
+ BackfillProjectNamespaces::TreeGenerator.new(namespaces, projects, [parent_group1, parent_group2], child_nodes_count, tree_depth).build_tree
+ end
+
+ describe '#up' do
+ shared_examples 'back-fill project namespaces' do
+ it 'back-fills all project namespaces' do
+ start_id = ::Project.minimum(:id)
+ end_id = ::Project.maximum(:id)
+ projects_count = ::Project.count
+ batches_count = (projects_count / described_class::BATCH_SIZE.to_f).ceil
+ project_namespaces_count = ::Namespace.where(type: 'Project').count
+ migration = described_class.new
+
+ expect(projects_count).not_to eq(project_namespaces_count)
+ expect(migration).to receive(:batch_insert_namespaces).exactly(batches_count).and_call_original
+ expect(migration).to receive(:batch_update_projects).exactly(batches_count).and_call_original
+ expect(migration).to receive(:batch_update_project_namespaces_traversal_ids).exactly(batches_count).and_call_original
+
+ expect { migration.perform(start_id, end_id, nil, 'up') }.to change(Namespace.where(type: 'Project'), :count)
+
+ expect(projects_count).to eq(::Namespace.where(type: 'Project').count)
+ check_projects_in_sync_with(Namespace.where(type: 'Project'))
+ end
+
+ context 'when passing specific group as parameter' do
+ let(:backfilled_namespace) { parent_group1 }
+
+ it 'back-fills project namespaces for the specified group hierarchy' do
+ backfilled_namespace_projects = base_ancestor(backfilled_namespace).first.all_projects
+ start_id = backfilled_namespace_projects.minimum(:id)
+ end_id = backfilled_namespace_projects.maximum(:id)
+ group_projects_count = backfilled_namespace_projects.count
+ batches_count = (group_projects_count / described_class::BATCH_SIZE.to_f).ceil
+ project_namespaces_in_hierarchy = project_namespaces_in_hierarchy(base_ancestor(backfilled_namespace))
+
+ migration = described_class.new
+
+ expect(project_namespaces_in_hierarchy.count).to eq(0)
+ expect(migration).to receive(:batch_insert_namespaces).exactly(batches_count).and_call_original
+ expect(migration).to receive(:batch_update_projects).exactly(batches_count).and_call_original
+ expect(migration).to receive(:batch_update_project_namespaces_traversal_ids).exactly(batches_count).and_call_original
+
+ expect(group_projects_count).to eq(14)
+ expect(project_namespaces_in_hierarchy.count).to eq(0)
+
+ migration.perform(start_id, end_id, backfilled_namespace.id, 'up')
+
+ expect(project_namespaces_in_hierarchy.count).to eq(14)
+ check_projects_in_sync_with(project_namespaces_in_hierarchy)
+ end
+ end
+
+ context 'when projects already have project namespaces' do
+ before do
+ hierarchy1_projects = base_ancestor(parent_group1).first.all_projects
+ start_id = hierarchy1_projects.minimum(:id)
+ end_id = hierarchy1_projects.maximum(:id)
+
+ described_class.new.perform(start_id, end_id, parent_group1.id, 'up')
+ end
+
+ it 'does not duplicate project namespaces' do
+ # check there are already some project namespaces but not for all
+ projects_count = ::Project.count
+ start_id = ::Project.minimum(:id)
+ end_id = ::Project.maximum(:id)
+ batches_count = (projects_count / described_class::BATCH_SIZE.to_f).ceil
+ project_namespaces = ::Namespace.where(type: 'Project')
+ migration = described_class.new
+
+ expect(project_namespaces_in_hierarchy(base_ancestor(parent_group1)).count).to be >= 14
+ expect(project_namespaces_in_hierarchy(base_ancestor(parent_group2)).count).to eq(0)
+ expect(projects_count).not_to eq(project_namespaces.count)
+
+ # run migration again to test we do not generate extra project namespaces
+ expect(migration).to receive(:batch_insert_namespaces).exactly(batches_count).and_call_original
+ expect(migration).to receive(:batch_update_projects).exactly(batches_count).and_call_original
+ expect(migration).to receive(:batch_update_project_namespaces_traversal_ids).exactly(batches_count).and_call_original
+
+ expect { migration.perform(start_id, end_id, nil, 'up') }.to change(project_namespaces, :count).by(14)
+
+ expect(projects_count).to eq(project_namespaces.count)
+ end
+ end
+ end
+
+ it 'checks no project namespaces exist in the defined hierarchies' do
+ hierarchy1_project_namespaces = project_namespaces_in_hierarchy(base_ancestor(parent_group1))
+ hierarchy2_project_namespaces = project_namespaces_in_hierarchy(base_ancestor(parent_group2))
+ hierarchy1_projects_count = base_ancestor(parent_group1).first.all_projects.count
+ hierarchy2_projects_count = base_ancestor(parent_group2).first.all_projects.count
+
+ expect(hierarchy1_project_namespaces).to be_empty
+ expect(hierarchy2_project_namespaces).to be_empty
+ expect(hierarchy1_projects_count).to eq(14)
+ expect(hierarchy2_projects_count).to eq(14)
+ end
+
+ context 'back-fill project namespaces in a single batch' do
+ it_behaves_like 'back-fill project namespaces'
+ end
+
+ context 'back-fill project namespaces in batches' do
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 2)
+ end
+
+ it_behaves_like 'back-fill project namespaces'
+ end
+ end
+
+ describe '#down' do
+ before do
+ start_id = ::Project.minimum(:id)
+ end_id = ::Project.maximum(:id)
+ # back-fill first
+ described_class.new.perform(start_id, end_id, nil, 'up')
+ end
+
+ shared_examples 'cleanup project namespaces' do
+ it 'removes project namespaces' do
+ projects_count = ::Project.count
+ start_id = ::Project.minimum(:id)
+ end_id = ::Project.maximum(:id)
+ migration = described_class.new
+ batches_count = (projects_count / described_class::BATCH_SIZE.to_f).ceil
+
+ expect(projects_count).to be > 0
+ expect(projects_count).to eq(::Namespace.where(type: 'Project').count)
+
+ expect(migration).to receive(:nullify_project_namespaces_in_projects).exactly(batches_count).and_call_original
+ expect(migration).to receive(:delete_project_namespace_records).exactly(batches_count).and_call_original
+
+ migration.perform(start_id, end_id, nil, 'down')
+
+ expect(::Project.count).to be > 0
+ expect(::Namespace.where(type: 'Project').count).to eq(0)
+ end
+
+ context 'when passing specific group as parameter' do
+ let(:backfilled_namespace) { parent_group1 }
+
+ it 'removes project namespaces only for the specific group hierarchy' do
+ backfilled_namespace_projects = base_ancestor(backfilled_namespace).first.all_projects
+ start_id = backfilled_namespace_projects.minimum(:id)
+ end_id = backfilled_namespace_projects.maximum(:id)
+ group_projects_count = backfilled_namespace_projects.count
+ batches_count = (group_projects_count / described_class::BATCH_SIZE.to_f).ceil
+ project_namespaces_in_hierarchy = project_namespaces_in_hierarchy(base_ancestor(backfilled_namespace))
+ migration = described_class.new
+
+ expect(project_namespaces_in_hierarchy.count).to eq(14)
+ expect(migration).to receive(:nullify_project_namespaces_in_projects).exactly(batches_count).and_call_original
+ expect(migration).to receive(:delete_project_namespace_records).exactly(batches_count).and_call_original
+
+ migration.perform(start_id, end_id, backfilled_namespace.id, 'down')
+
+ expect(::Namespace.where(type: 'Project').count).to be > 0
+ expect(project_namespaces_in_hierarchy.count).to eq(0)
+ end
+ end
+ end
+
+ context 'cleanup project namespaces in a single batch' do
+ it_behaves_like 'cleanup project namespaces'
+ end
+
+ context 'cleanup project namespaces in batches' do
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 2)
+ end
+
+ it_behaves_like 'cleanup project namespaces'
+ end
+ end
+ end
+
+ def base_ancestor(ancestor)
+ ::Namespace.where(id: ancestor.id)
+ end
+
+ def project_namespaces_in_hierarchy(base_node)
+ Gitlab::ObjectHierarchy.new(base_node).base_and_descendants.where(type: 'Project')
+ end
+
+ def check_projects_in_sync_with(namespaces)
+ project_namespaces_attrs = namespaces.order(:id).pluck(:id, :name, :path, :parent_id, :visibility_level, :shared_runners_enabled)
+ corresponding_projects_attrs = Project.where(project_namespace_id: project_namespaces_attrs.map(&:first))
+ .order(:project_namespace_id).pluck(:project_namespace_id, :name, :path, :namespace_id, :visibility_level, :shared_runners_enabled)
+
+ expect(project_namespaces_attrs).to eq(corresponding_projects_attrs)
+ end
+end
+
+module BackfillProjectNamespaces
+ class TreeGenerator
+ def initialize(namespaces, projects, parent_nodes, child_nodes_count, tree_depth)
+ parent_nodes_ids = parent_nodes.map(&:id)
+
+ @namespaces = namespaces
+ @projects = projects
+ @subgroups_depth = tree_depth
+ @resource_count = child_nodes_count
+ @all_groups = [parent_nodes_ids]
+ end
+
+ def build_tree
+ (1..@subgroups_depth).each do |level|
+ parent_level = level - 1
+ current_level = level
+ parent_groups = @all_groups[parent_level]
+
+ parent_groups.each do |parent_id|
+ @resource_count.times do |i|
+ group_path = "child#{i}_level#{level}"
+ project_path = "project#{i}_level#{level}"
+ sub_group = @namespaces.create!(name: group_path, path: group_path, parent_id: parent_id, visibility_level: 20, type: 'Group')
+ @projects.create!(name: project_path, path: project_path, namespace_id: sub_group.id, visibility_level: 20)
+
+ track_group_id(current_level, sub_group.id)
+ end
+ end
+ end
+ end
+
+ def track_group_id(depth_level, group_id)
+ @all_groups[depth_level] ||= []
+ @all_groups[depth_level] << group_id
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id_spec.rb b/spec/lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id_spec.rb
index c1ba1607b89..1830a7fc099 100644
--- a/spec/lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id_spec.rb
+++ b/spec/lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::RecalculateProjectAuthorizationsWithMinMaxUserId, schema: 20200204113224 do
+RSpec.describe Gitlab::BackgroundMigration::RecalculateProjectAuthorizationsWithMinMaxUserId, schema: 20181228175414 do
let(:users_table) { table(:users) }
let(:min) { 1 }
let(:max) { 5 }
diff --git a/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb b/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb
index 30908145782..4cdb56d3d3b 100644
--- a/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb
+++ b/spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid, schema: 20201110110454 do
+RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid, schema: 20181228175414 do
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
let(:users) { table(:users) }
let(:user) { create_user! }
diff --git a/spec/lib/gitlab/background_migration/remove_duplicate_services_spec.rb b/spec/lib/gitlab/background_migration/remove_duplicate_services_spec.rb
index 391b27b28e6..afcdaaf1cb8 100644
--- a/spec/lib/gitlab/background_migration/remove_duplicate_services_spec.rb
+++ b/spec/lib/gitlab/background_migration/remove_duplicate_services_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateServices, :migration, schema: 20201207165956 do
+RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateServices, :migration, schema: 20181228175414 do
let_it_be(:users) { table(:users) }
let_it_be(:namespaces) { table(:namespaces) }
let_it_be(:projects) { table(:projects) }
diff --git a/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb b/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb
index 47e1d4620cd..7214225c32c 100644
--- a/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb
+++ b/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb
@@ -5,9 +5,9 @@ RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindin
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
let(:users) { table(:users) }
let(:user) { create_user! }
- let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
+ let(:project) { table(:projects).create!(id: 14219619, namespace_id: namespace.id) }
let(:scanners) { table(:vulnerability_scanners) }
- let!(:scanner) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+ let!(:scanner1) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
let!(:scanner2) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') }
let!(:scanner3) { scanners.create!(project_id: project.id, external_id: 'test 3', name: 'test scanner 3') }
let!(:unrelated_scanner) { scanners.create!(project_id: project.id, external_id: 'unreleated_scanner', name: 'unrelated scanner') }
@@ -16,43 +16,68 @@ RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindin
let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
let(:vulnerability_identifier) do
vulnerability_identifiers.create!(
+ id: 1244459,
project_id: project.id,
external_type: 'vulnerability-identifier',
external_id: 'vulnerability-identifier',
- fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
+ fingerprint: '0a203e8cd5260a1948edbedc76c7cb91ad6a2e45',
name: 'vulnerability identifier')
end
- let!(:first_finding) do
+ let!(:vulnerability_for_first_duplicate) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let!(:first_finding_duplicate) do
create_finding!(
- uuid: "test1",
- vulnerability_id: nil,
+ id: 5606961,
+ uuid: "bd95c085-71aa-51d7-9bb6-08ae669c262e",
+ vulnerability_id: vulnerability_for_first_duplicate.id,
report_type: 0,
- location_fingerprint: '2bda3014914481791847d8eca38d1a8d13b6ad76',
+ location_fingerprint: '00049d5119c2cb3bfb3d1ee1f6e031fe925aed75',
primary_identifier_id: vulnerability_identifier.id,
- scanner_id: scanner.id,
+ scanner_id: scanner1.id,
project_id: project.id
)
end
- let!(:first_duplicate) do
+ let!(:vulnerability_for_second_duplicate) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let!(:second_finding_duplicate) do
create_finding!(
- uuid: "test2",
- vulnerability_id: nil,
+ id: 8765432,
+ uuid: "5b714f58-1176-5b26-8fd5-e11dfcb031b5",
+ vulnerability_id: vulnerability_for_second_duplicate.id,
report_type: 0,
- location_fingerprint: '2bda3014914481791847d8eca38d1a8d13b6ad76',
+ location_fingerprint: '00049d5119c2cb3bfb3d1ee1f6e031fe925aed75',
primary_identifier_id: vulnerability_identifier.id,
scanner_id: scanner2.id,
project_id: project.id
)
end
- let!(:second_duplicate) do
+ let!(:vulnerability_for_third_duplicate) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let!(:third_finding_duplicate) do
create_finding!(
- uuid: "test3",
- vulnerability_id: nil,
+ id: 8832995,
+ uuid: "cfe435fa-b25b-5199-a56d-7b007cc9e2d4",
+ vulnerability_id: vulnerability_for_third_duplicate.id,
report_type: 0,
- location_fingerprint: '2bda3014914481791847d8eca38d1a8d13b6ad76',
+ location_fingerprint: '00049d5119c2cb3bfb3d1ee1f6e031fe925aed75',
primary_identifier_id: vulnerability_identifier.id,
scanner_id: scanner3.id,
project_id: project.id
@@ -61,6 +86,7 @@ RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindin
let!(:unrelated_finding) do
create_finding!(
+ id: 9999999,
uuid: "unreleated_finding",
vulnerability_id: nil,
report_type: 1,
@@ -71,7 +97,7 @@ RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindin
)
end
- subject { described_class.new.perform(first_finding.id, unrelated_finding.id) }
+ subject { described_class.new.perform(first_finding_duplicate.id, unrelated_finding.id) }
before do
stub_const("#{described_class}::DELETE_BATCH_SIZE", 1)
@@ -82,7 +108,15 @@ RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindin
expect { subject }.to change { vulnerability_findings.count }.from(4).to(2)
- expect(vulnerability_findings.pluck(:id)).to eq([second_duplicate.id, unrelated_finding.id])
+ expect(vulnerability_findings.pluck(:id)).to match_array([third_finding_duplicate.id, unrelated_finding.id])
+ end
+
+ it "removes vulnerabilites without findings" do
+ expect(vulnerabilities.count).to eq(3)
+
+ expect { subject }.to change { vulnerabilities.count }.from(3).to(1)
+
+ expect(vulnerabilities.pluck(:id)).to match_array([vulnerability_for_third_duplicate.id])
end
private
@@ -100,11 +134,12 @@ RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindin
# rubocop:disable Metrics/ParameterLists
def create_finding!(
+ id: nil,
vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:,
name: "test", severity: 7, confidence: 7, report_type: 0,
project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
metadata_version: 'test', raw_metadata: 'test', uuid: 'test')
- vulnerability_findings.create!(
+ params = {
vulnerability_id: vulnerability_id,
project_id: project_id,
name: name,
@@ -118,7 +153,9 @@ RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindin
metadata_version: metadata_version,
raw_metadata: raw_metadata,
uuid: uuid
- )
+ }
+ params[:id] = id unless id.nil?
+ vulnerability_findings.create!(params)
end
# rubocop:enable Metrics/ParameterLists
diff --git a/spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb b/spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb
index 561a602fab9..6cfdbb5a14e 100644
--- a/spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb
+++ b/spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::ReplaceBlockedByLinks, schema: 20201015073808 do
+RSpec.describe Gitlab::BackgroundMigration::ReplaceBlockedByLinks, schema: 20181228175414 do
let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
let(:project) { table(:projects).create!(namespace_id: namespace.id, name: 'gitlab') }
let(:issue1) { table(:issues).create!(project_id: project.id, title: 'a') }
diff --git a/spec/lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects_spec.rb b/spec/lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects_spec.rb
index 68aa64a1c7d..ef90b5674f0 100644
--- a/spec/lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects_spec.rb
+++ b/spec/lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::ResetSharedRunnersForTransferredProjects, schema: 20201110161542 do
+RSpec.describe Gitlab::BackgroundMigration::ResetSharedRunnersForTransferredProjects, schema: 20181228175414 do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
diff --git a/spec/lib/gitlab/background_migration/set_default_iteration_cadences_spec.rb b/spec/lib/gitlab/background_migration/set_default_iteration_cadences_spec.rb
deleted file mode 100644
index 46c919f0854..00000000000
--- a/spec/lib/gitlab/background_migration/set_default_iteration_cadences_spec.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::SetDefaultIterationCadences, schema: 20201231133921 do
- let(:namespaces) { table(:namespaces) }
- let(:iterations) { table(:sprints) }
- let(:iterations_cadences) { table(:iterations_cadences) }
-
- describe '#perform' do
- context 'when no iteration cadences exists' do
- let!(:group_1) { namespaces.create!(name: 'group 1', path: 'group-1') }
- let!(:group_2) { namespaces.create!(name: 'group 2', path: 'group-2') }
- let!(:group_3) { namespaces.create!(name: 'group 3', path: 'group-3') }
-
- let!(:iteration_1) { iterations.create!(group_id: group_1.id, iid: 1, title: 'Iteration 1', start_date: 10.days.ago, due_date: 8.days.ago) }
- let!(:iteration_2) { iterations.create!(group_id: group_3.id, iid: 1, title: 'Iteration 2', start_date: 10.days.ago, due_date: 8.days.ago) }
- let!(:iteration_3) { iterations.create!(group_id: group_3.id, iid: 1, title: 'Iteration 3', start_date: 5.days.ago, due_date: 2.days.ago) }
-
- subject { described_class.new.perform(group_1.id, group_2.id, group_3.id, namespaces.last.id + 1) }
-
- before do
- subject
- end
-
- it 'creates iterations_cadence records for the requested groups' do
- expect(iterations_cadences.count).to eq(2)
- end
-
- it 'assigns the iteration cadences to the iterations correctly' do
- iterations_cadence = iterations_cadences.find_by(group_id: group_1.id)
- iteration_records = iterations.where(iterations_cadence_id: iterations_cadence.id)
-
- expect(iterations_cadence.start_date).to eq(iteration_1.start_date)
- expect(iterations_cadence.last_run_date).to eq(iteration_1.start_date)
- expect(iterations_cadence.title).to eq('group 1 Iterations')
- expect(iteration_records.size).to eq(1)
- expect(iteration_records.first.id).to eq(iteration_1.id)
-
- iterations_cadence = iterations_cadences.find_by(group_id: group_3.id)
- iteration_records = iterations.where(iterations_cadence_id: iterations_cadence.id)
-
- expect(iterations_cadence.start_date).to eq(iteration_3.start_date)
- expect(iterations_cadence.last_run_date).to eq(iteration_3.start_date)
- expect(iterations_cadence.title).to eq('group 3 Iterations')
- expect(iteration_records.size).to eq(2)
- expect(iteration_records.first.id).to eq(iteration_2.id)
- expect(iteration_records.second.id).to eq(iteration_3.id)
- end
-
- it 'does not call Group class' do
- expect(::Group).not_to receive(:where)
-
- subject
- end
- end
-
- context 'when an iteration cadence exists for a group' do
- let!(:group) { namespaces.create!(name: 'group', path: 'group') }
-
- let!(:iterations_cadence_1) { iterations_cadences.create!(group_id: group.id, start_date: 2.days.ago, title: 'Cadence 1') }
-
- let!(:iteration_1) { iterations.create!(group_id: group.id, iid: 1, title: 'Iteration 1', start_date: 10.days.ago, due_date: 8.days.ago) }
- let!(:iteration_2) { iterations.create!(group_id: group.id, iterations_cadence_id: iterations_cadence_1.id, iid: 2, title: 'Iteration 2', start_date: 5.days.ago, due_date: 3.days.ago) }
-
- subject { described_class.new.perform(group.id) }
-
- it 'does not create a new iterations_cadence' do
- expect { subject }.not_to change { iterations_cadences.count }
- end
-
- it 'assigns iteration cadences to iterations if needed' do
- subject
-
- expect(iteration_1.reload.iterations_cadence_id).to eq(iterations_cadence_1.id)
- expect(iteration_2.reload.iterations_cadence_id).to eq(iterations_cadence_1.id)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb b/spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb
index f23518625e4..1fdbdf25706 100644
--- a/spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb
+++ b/spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::SetMergeRequestDiffFilesCount, schema: 20200807152315 do
+RSpec.describe Gitlab::BackgroundMigration::SetMergeRequestDiffFilesCount, schema: 20181228175414 do
let(:merge_request_diff_files) { table(:merge_request_diff_files) }
let(:merge_request_diffs) { table(:merge_request_diffs) }
let(:merge_requests) { table(:merge_requests) }
diff --git a/spec/lib/gitlab/background_migration/set_null_external_diff_store_to_local_value_spec.rb b/spec/lib/gitlab/background_migration/set_null_external_diff_store_to_local_value_spec.rb
deleted file mode 100644
index 6079ad2dd2a..00000000000
--- a/spec/lib/gitlab/background_migration/set_null_external_diff_store_to_local_value_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-# The test setup must begin before
-# 20200804041930_add_not_null_constraint_on_external_diff_store_to_merge_request_diffs.rb
-# has run, or else we cannot insert a row with `NULL` `external_diff_store` to
-# test against.
-RSpec.describe Gitlab::BackgroundMigration::SetNullExternalDiffStoreToLocalValue, schema: 20200804035230 do
- let!(:merge_request_diffs) { table(:merge_request_diffs) }
- let!(:merge_requests) { table(:merge_requests) }
- let!(:namespaces) { table(:namespaces) }
- let!(:projects) { table(:projects) }
- let!(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
- let!(:project) { projects.create!(namespace_id: namespace.id) }
- let!(:merge_request) { merge_requests.create!(source_branch: 'x', target_branch: 'master', target_project_id: project.id) }
-
- it 'correctly migrates nil external_diff_store to 1' do
- external_diff_store_1 = merge_request_diffs.create!(external_diff_store: 1, merge_request_id: merge_request.id)
- external_diff_store_2 = merge_request_diffs.create!(external_diff_store: 2, merge_request_id: merge_request.id)
- external_diff_store_nil = merge_request_diffs.create!(external_diff_store: nil, merge_request_id: merge_request.id)
-
- described_class.new.perform(external_diff_store_1.id, external_diff_store_nil.id)
-
- external_diff_store_1.reload
- external_diff_store_2.reload
- external_diff_store_nil.reload
-
- expect(external_diff_store_1.external_diff_store).to eq(1) # unchanged
- expect(external_diff_store_2.external_diff_store).to eq(2) # unchanged
- expect(external_diff_store_nil.external_diff_store).to eq(1) # nil => 1
- end
-end
diff --git a/spec/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value_spec.rb b/spec/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value_spec.rb
deleted file mode 100644
index 40d41262fc7..00000000000
--- a/spec/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-# The test setup must begin before
-# 20200806004742_add_not_null_constraint_on_file_store_to_package_files.rb
-# has run, or else we cannot insert a row with `NULL` `file_store` to
-# test against.
-RSpec.describe Gitlab::BackgroundMigration::SetNullPackageFilesFileStoreToLocalValue, schema: 20200806004232 do
- let!(:packages_package_files) { table(:packages_package_files) }
- let!(:packages_packages) { table(:packages_packages) }
- let!(:projects) { table(:projects) }
- let!(:namespaces) { table(:namespaces) }
- let!(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
- let!(:project) { projects.create!(namespace_id: namespace.id) }
- let!(:package) { packages_packages.create!(project_id: project.id, name: 'bar', package_type: 1) }
-
- it 'correctly migrates nil file_store to 1' do
- file_store_1 = packages_package_files.create!(file_store: 1, file_name: 'foo_1', file: 'foo_1', package_id: package.id)
- file_store_2 = packages_package_files.create!(file_store: 2, file_name: 'foo_2', file: 'foo_2', package_id: package.id)
- file_store_nil = packages_package_files.create!(file_store: nil, file_name: 'foo_nil', file: 'foo_nil', package_id: package.id)
-
- described_class.new.perform(file_store_1.id, file_store_nil.id)
-
- file_store_1.reload
- file_store_2.reload
- file_store_nil.reload
-
- expect(file_store_1.file_store).to eq(1) # unchanged
- expect(file_store_2.file_store).to eq(2) # unchanged
- expect(file_store_nil.file_store).to eq(1) # nil => 1
- end
-end
diff --git a/spec/lib/gitlab/background_migration/steal_migrate_merge_request_diff_commit_users_spec.rb b/spec/lib/gitlab/background_migration/steal_migrate_merge_request_diff_commit_users_spec.rb
index f2fb2ab6b6e..841a7f306d7 100644
--- a/spec/lib/gitlab/background_migration/steal_migrate_merge_request_diff_commit_users_spec.rb
+++ b/spec/lib/gitlab/background_migration/steal_migrate_merge_request_diff_commit_users_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::StealMigrateMergeRequestDiffCommitUsers do
+RSpec.describe Gitlab::BackgroundMigration::StealMigrateMergeRequestDiffCommitUsers, schema: 20211012134316 do
let(:migration) { described_class.new }
describe '#perform' do
diff --git a/spec/lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb b/spec/lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
index 6c0a1d3a5b0..de9799c3642 100644
--- a/spec/lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
+++ b/spec/lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::UpdateExistingSubgroupToMatchVisibilityLevelOfParent, schema: 2020_01_10_121314 do
+RSpec.describe Gitlab::BackgroundMigration::UpdateExistingSubgroupToMatchVisibilityLevelOfParent, schema: 20181228175414 do
include MigrationHelpers::NamespacesHelpers
context 'private visibility level' do
diff --git a/spec/lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth_spec.rb b/spec/lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth_spec.rb
index bebb398413b..33f5e38100e 100644
--- a/spec/lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth_spec.rb
+++ b/spec/lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::UpdateExistingUsersThatRequireTwoFactorAuth, schema: 20201030121314 do
+RSpec.describe Gitlab::BackgroundMigration::UpdateExistingUsersThatRequireTwoFactorAuth, schema: 20181228175414 do
include MigrationHelpers::NamespacesHelpers
let(:group_with_2fa_parent) { create_namespace('parent', Gitlab::VisibilityLevel::PRIVATE) }
diff --git a/spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb b/spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb
index 2dae4a65eeb..7af11ffa1e0 100644
--- a/spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb
+++ b/spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb
@@ -1,120 +1,8 @@
# frozen_string_literal: true
require 'spec_helper'
-require './db/post_migrate/20200128134110_migrate_commit_notes_mentions_to_db'
-require './db/post_migrate/20200211155539_migrate_merge_request_mentions_to_db'
-
-RSpec.describe Gitlab::BackgroundMigration::UserMentions::CreateResourceUserMention, schema: 20200211155539 do
- include MigrationsHelpers
-
- context 'when migrating data' do
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:notes) { table(:notes) }
- let(:routes) { table(:routes) }
-
- let(:author) { users.create!(email: 'author@example.com', notification_email: 'author@example.com', name: 'author', username: 'author', projects_limit: 10, state: 'active') }
- let(:member) { users.create!(email: 'member@example.com', notification_email: 'member@example.com', name: 'member', username: 'member', projects_limit: 10, state: 'active') }
- let(:admin) { users.create!(email: 'administrator@example.com', notification_email: 'administrator@example.com', name: 'administrator', username: 'administrator', admin: 1, projects_limit: 10, state: 'active') }
- let(:john_doe) { users.create!(email: 'john_doe@example.com', notification_email: 'john_doe@example.com', name: 'john_doe', username: 'john_doe', projects_limit: 10, state: 'active') }
- let(:skipped) { users.create!(email: 'skipped@example.com', notification_email: 'skipped@example.com', name: 'skipped', username: 'skipped', projects_limit: 10, state: 'active') }
-
- let(:mentioned_users) { [author, member, admin, john_doe, skipped] }
- let(:mentioned_users_refs) { mentioned_users.map { |u| "@#{u.username}" }.join(' ') }
-
- let(:group) { namespaces.create!(name: 'test1', path: 'test1', runners_token: 'my-token1', project_creation_level: 1, visibility_level: 20, type: 'Group') }
- let(:inaccessible_group) { namespaces.create!(name: 'test2', path: 'test2', runners_token: 'my-token2', project_creation_level: 1, visibility_level: 0, type: 'Group') }
- let(:project) { projects.create!(name: 'gitlab1', path: 'gitlab1', namespace_id: group.id, visibility_level: 0) }
-
- let(:mentioned_groups) { [group, inaccessible_group] }
- let(:group_mentions) { [group, inaccessible_group].map { |gr| "@#{gr.path}" }.join(' ') }
- let(:description_mentions) { "description with mentions #{mentioned_users_refs} and #{group_mentions}" }
-
- before do
- # build personal namespaces and routes for users
- mentioned_users.each do |u|
- namespace = namespaces.create!(path: u.username, name: u.name, runners_token: "my-token-u#{u.id}", owner_id: u.id, type: nil)
- routes.create!(path: namespace.path, source_type: 'Namespace', source_id: namespace.id)
- end
-
- # build namespaces and routes for groups
- mentioned_groups.each do |gr|
- routes.create!(path: gr.path, source_type: 'Namespace', source_id: gr.id)
- end
- end
-
- context 'migrate merge request mentions' do
- let(:merge_requests) { table(:merge_requests) }
- let(:merge_request_user_mentions) { table(:merge_request_user_mentions) }
-
- let!(:mr1) do
- merge_requests.create!(
- title: "title 1", state_id: 1, target_branch: 'feature1', source_branch: 'master',
- source_project_id: project.id, target_project_id: project.id, author_id: author.id,
- description: description_mentions
- )
- end
-
- let!(:mr2) do
- merge_requests.create!(
- title: "title 2", state_id: 1, target_branch: 'feature2', source_branch: 'master',
- source_project_id: project.id, target_project_id: project.id, author_id: author.id,
- description: 'some description'
- )
- end
-
- let!(:mr3) do
- merge_requests.create!(
- title: "title 3", state_id: 1, target_branch: 'feature3', source_branch: 'master',
- source_project_id: project.id, target_project_id: project.id, author_id: author.id,
- description: 'description with an email@example.com and some other @ char here.')
- end
-
- let(:user_mentions) { merge_request_user_mentions }
- let(:resource) { merge_request }
-
- it_behaves_like 'resource mentions migration', MigrateMergeRequestMentionsToDb, 'MergeRequest'
-
- context 'when FF disabled' do
- before do
- stub_feature_flags(migrate_user_mentions: false)
- end
-
- it_behaves_like 'resource migration not run', MigrateMergeRequestMentionsToDb, 'MergeRequest'
- end
- end
-
- context 'migrate commit mentions' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
- let(:commit) { Commit.new(RepoHelpers.sample_commit, project) }
- let(:commit_user_mentions) { table(:commit_user_mentions) }
-
- let!(:note1) { notes.create!(commit_id: commit.id, noteable_type: 'Commit', project_id: project.id, author_id: author.id, note: description_mentions) }
- let!(:note2) { notes.create!(commit_id: commit.id, noteable_type: 'Commit', project_id: project.id, author_id: author.id, note: 'sample note') }
- let!(:note3) { notes.create!(commit_id: commit.id, noteable_type: 'Commit', project_id: project.id, author_id: author.id, note: description_mentions, system: true) }
-
- # this not does not have actual mentions
- let!(:note4) { notes.create!(commit_id: commit.id, noteable_type: 'Commit', project_id: project.id, author_id: author.id, note: 'note for an email@somesite.com and some other random @ ref' ) }
- # this should have pointed to an innexisted commit record in a commits table
- # but because commit is not an AR we'll just make it so that it does not have mentions
- let!(:note5) { notes.create!(commit_id: 'abc', noteable_type: 'Commit', project_id: project.id, author_id: author.id, note: 'note for an email@somesite.com and some other random @ ref') }
-
- let(:user_mentions) { commit_user_mentions }
- let(:resource) { commit }
-
- it_behaves_like 'resource notes mentions migration', MigrateCommitNotesMentionsToDb, 'Commit'
-
- context 'when FF disabled' do
- before do
- stub_feature_flags(migrate_user_mentions: false)
- end
-
- it_behaves_like 'resource notes migration not run', MigrateCommitNotesMentionsToDb, 'Commit'
- end
- end
- end
+RSpec.describe Gitlab::BackgroundMigration::UserMentions::CreateResourceUserMention, schema: 20181228175414 do
context 'checks no_quote_columns' do
it 'has correct no_quote_columns' do
expect(Gitlab::BackgroundMigration::UserMentions::Models::MergeRequest.no_quote_columns).to match([:note_id, :merge_request_id])
diff --git a/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb b/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb
index 07f4429f7d9..5c197526a55 100644
--- a/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb
+++ b/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::WrongfullyConfirmedEmailUnconfirmer, schema: 20200615111857 do
+RSpec.describe Gitlab::BackgroundMigration::WrongfullyConfirmedEmailUnconfirmer, schema: 20181228175414 do
let(:users) { table(:users) }
let(:emails) { table(:emails) }
let(:user_synced_attributes_metadata) { table(:user_synced_attributes_metadata) }
diff --git a/spec/lib/gitlab/background_migration_spec.rb b/spec/lib/gitlab/background_migration_spec.rb
index f32e6891716..777dc8112a7 100644
--- a/spec/lib/gitlab/background_migration_spec.rb
+++ b/spec/lib/gitlab/background_migration_spec.rb
@@ -3,6 +3,14 @@
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration do
+ let(:coordinator) { described_class::JobCoordinator.for_database(:main) }
+
+ before do
+ allow(described_class).to receive(:coordinator_for_database)
+ .with(:main)
+ .and_return(coordinator)
+ end
+
describe '.queue' do
it 'returns background migration worker queue' do
expect(described_class.queue)
@@ -11,7 +19,7 @@ RSpec.describe Gitlab::BackgroundMigration do
end
describe '.steal' do
- context 'when there are enqueued jobs present' do
+ context 'when the queue contains unprocessed jobs' do
let(:queue) do
[
double(args: ['Foo', [10, 20]], klass: 'BackgroundMigrationWorker'),
@@ -22,110 +30,34 @@ RSpec.describe Gitlab::BackgroundMigration do
before do
allow(Sidekiq::Queue).to receive(:new)
- .with(described_class.queue)
+ .with(coordinator.queue)
.and_return(queue)
end
- context 'when queue contains unprocessed jobs' do
- it 'steals jobs from a queue' do
- expect(queue[0]).to receive(:delete).and_return(true)
-
- expect(described_class).to receive(:perform)
- .with('Foo', [10, 20])
-
- described_class.steal('Foo')
- end
-
- it 'does not steal job that has already been taken' do
- expect(queue[0]).to receive(:delete).and_return(false)
-
- expect(described_class).not_to receive(:perform)
-
- described_class.steal('Foo')
- end
-
- it 'does not steal jobs for a different migration' do
- expect(described_class).not_to receive(:perform)
+ it 'uses the coordinator to steal jobs' do
+ expect(queue[0]).to receive(:delete).and_return(true)
- expect(queue[0]).not_to receive(:delete)
-
- described_class.steal('Baz')
- end
-
- context 'when a custom predicate is given' do
- it 'steals jobs that match the predicate' do
- expect(queue[0]).to receive(:delete).and_return(true)
-
- expect(described_class).to receive(:perform)
- .with('Foo', [10, 20])
-
- described_class.steal('Foo') { |job| job.args.second.first == 10 && job.args.second.second == 20 }
- end
+ expect(coordinator).to receive(:steal).with('Foo', retry_dead_jobs: false).and_call_original
+ expect(coordinator).to receive(:perform).with('Foo', [10, 20])
- it 'does not steal jobs that do not match the predicate' do
- expect(described_class).not_to receive(:perform)
-
- expect(queue[0]).not_to receive(:delete)
-
- described_class.steal('Foo') { |(arg1, _)| arg1 == 5 }
- end
- end
+ described_class.steal('Foo')
end
- context 'when one of the jobs raises an error' do
- let(:migration) { spy(:migration) }
-
- let(:queue) do
- [double(args: ['Foo', [10, 20]], klass: 'BackgroundMigrationWorker'),
- double(args: ['Foo', [20, 30]], klass: 'BackgroundMigrationWorker')]
- end
-
- before do
- stub_const("#{described_class}::Foo", migration)
-
- allow(queue[0]).to receive(:delete).and_return(true)
- allow(queue[1]).to receive(:delete).and_return(true)
- end
-
- it 'enqueues the migration again and re-raises the error' do
- allow(migration).to receive(:perform).with(10, 20)
- .and_raise(Exception, 'Migration error').once
+ context 'when a custom predicate is given' do
+ it 'steals jobs that match the predicate' do
+ expect(queue[0]).to receive(:delete).and_return(true)
- expect(BackgroundMigrationWorker).to receive(:perform_async)
- .with('Foo', [10, 20]).once
+ expect(coordinator).to receive(:perform).with('Foo', [10, 20])
- expect { described_class.steal('Foo') }.to raise_error(Exception)
+ described_class.steal('Foo') { |job| job.args.second.first == 10 && job.args.second.second == 20 }
end
- end
- end
- context 'when there are scheduled jobs present', :redis do
- it 'steals all jobs from the scheduled sets' do
- Sidekiq::Testing.disable! do
- BackgroundMigrationWorker.perform_in(10.minutes, 'Object')
-
- expect(Sidekiq::ScheduledSet.new).to be_one
- expect(described_class).to receive(:perform).with('Object', any_args)
-
- described_class.steal('Object')
+ it 'does not steal jobs that do not match the predicate' do
+ expect(coordinator).not_to receive(:perform)
- expect(Sidekiq::ScheduledSet.new).to be_none
- end
- end
- end
-
- context 'when there are enqueued and scheduled jobs present', :redis do
- it 'steals from the scheduled sets queue first' do
- Sidekiq::Testing.disable! do
- expect(described_class).to receive(:perform)
- .with('Object', [1]).ordered
- expect(described_class).to receive(:perform)
- .with('Object', [2]).ordered
-
- BackgroundMigrationWorker.perform_async('Object', [2])
- BackgroundMigrationWorker.perform_in(10.minutes, 'Object', [1])
+ expect(queue[0]).not_to receive(:delete)
- described_class.steal('Object')
+ described_class.steal('Foo') { |(arg1, _)| arg1 == 5 }
end
end
end
@@ -146,14 +78,10 @@ RSpec.describe Gitlab::BackgroundMigration do
it 'steals from the dead and retry queue' do
Sidekiq::Testing.disable! do
- expect(described_class).to receive(:perform)
- .with('Object', [1]).ordered
- expect(described_class).to receive(:perform)
- .with('Object', [2]).ordered
- expect(described_class).to receive(:perform)
- .with('Object', [3]).ordered
- expect(described_class).to receive(:perform)
- .with('Object', [4]).ordered
+ expect(coordinator).to receive(:perform).with('Object', [1]).ordered
+ expect(coordinator).to receive(:perform).with('Object', [2]).ordered
+ expect(coordinator).to receive(:perform).with('Object', [3]).ordered
+ expect(coordinator).to receive(:perform).with('Object', [4]).ordered
BackgroundMigrationWorker.perform_async('Object', [2])
BackgroundMigrationWorker.perform_in(10.minutes, 'Object', [1])
@@ -171,131 +99,54 @@ RSpec.describe Gitlab::BackgroundMigration do
stub_const("#{described_class.name}::Foo", migration)
end
- it 'performs a background migration' do
+ it 'uses the coordinator to perform a background migration' do
+ expect(coordinator).to receive(:perform).with('Foo', [10, 20]).and_call_original
expect(migration).to receive(:perform).with(10, 20).once
described_class.perform('Foo', [10, 20])
end
+ end
- context 'backward compatibility' do
- it 'performs a background migration for fully-qualified job classes' do
- expect(migration).to receive(:perform).with(10, 20).once
- expect(Gitlab::ErrorTracking)
- .to receive(:track_and_raise_for_dev_exception)
- .with(instance_of(StandardError), hash_including(:class_name))
-
- described_class.perform('Gitlab::BackgroundMigration::Foo', [10, 20])
+ describe '.exists?', :redis do
+ before do
+ Sidekiq::Testing.disable! do
+ MergeWorker.perform_async('Bar')
+ BackgroundMigrationWorker.perform_async('Foo')
end
end
- end
- describe '.remaining', :redis do
- context 'when there are jobs remaining' do
- before do
- Sidekiq::Testing.disable! do
- MergeWorker.perform_async('Foo')
- MergeWorker.perform_in(10.minutes, 'Foo')
-
- 5.times do
- BackgroundMigrationWorker.perform_async('Foo')
- end
- 3.times do
- BackgroundMigrationWorker.perform_in(10.minutes, 'Foo')
- end
- end
- end
+ it 'uses the coordinator to find if a job exists' do
+ expect(coordinator).to receive(:exists?).with('Foo', []).and_call_original
- it 'returns the enqueued jobs plus the scheduled jobs' do
- expect(described_class.remaining).to eq(8)
- end
+ expect(described_class.exists?('Foo')).to eq(true)
end
- context 'when there are no jobs remaining' do
- it 'returns zero' do
- expect(described_class.remaining).to be_zero
- end
+ it 'uses the coordinator to find a job does not exist' do
+ expect(coordinator).to receive(:exists?).with('Bar', []).and_call_original
+
+ expect(described_class.exists?('Bar')).to eq(false)
end
end
- describe '.exists?', :redis do
- context 'when there are enqueued jobs present' do
- before do
- Sidekiq::Testing.disable! do
- MergeWorker.perform_async('Bar')
+ describe '.remaining', :redis do
+ before do
+ Sidekiq::Testing.disable! do
+ MergeWorker.perform_async('Foo')
+ MergeWorker.perform_in(10.minutes, 'Foo')
+
+ 5.times do
BackgroundMigrationWorker.perform_async('Foo')
end
- end
-
- it 'returns true if specific job exists' do
- expect(described_class.exists?('Foo')).to eq(true)
- end
-
- it 'returns false if specific job does not exist' do
- expect(described_class.exists?('Bar')).to eq(false)
- end
- end
-
- context 'when there are scheduled jobs present' do
- before do
- Sidekiq::Testing.disable! do
- MergeWorker.perform_in(10.minutes, 'Bar')
+ 3.times do
BackgroundMigrationWorker.perform_in(10.minutes, 'Foo')
end
end
-
- it 'returns true if specific job exists' do
- expect(described_class.exists?('Foo')).to eq(true)
- end
-
- it 'returns false if specific job does not exist' do
- expect(described_class.exists?('Bar')).to eq(false)
- end
- end
- end
-
- describe '.dead_jobs?' do
- let(:queue) do
- [
- double(args: ['Foo', [10, 20]], klass: 'BackgroundMigrationWorker'),
- double(args: ['Bar'], klass: 'MergeWorker')
- ]
end
- context 'when there are dead jobs present' do
- before do
- allow(Sidekiq::DeadSet).to receive(:new).and_return(queue)
- end
-
- it 'returns true if specific job exists' do
- expect(described_class.dead_jobs?('Foo')).to eq(true)
- end
+ it 'uses the coordinator to find the number of remaining jobs' do
+ expect(coordinator).to receive(:remaining).and_call_original
- it 'returns false if specific job does not exist' do
- expect(described_class.dead_jobs?('Bar')).to eq(false)
- end
- end
- end
-
- describe '.retrying_jobs?' do
- let(:queue) do
- [
- double(args: ['Foo', [10, 20]], klass: 'BackgroundMigrationWorker'),
- double(args: ['Bar'], klass: 'MergeWorker')
- ]
- end
-
- context 'when there are dead jobs present' do
- before do
- allow(Sidekiq::RetrySet).to receive(:new).and_return(queue)
- end
-
- it 'returns true if specific job exists' do
- expect(described_class.retrying_jobs?('Foo')).to eq(true)
- end
-
- it 'returns false if specific job does not exist' do
- expect(described_class.retrying_jobs?('Bar')).to eq(false)
- end
+ expect(described_class.remaining).to eq(8)
end
end
end
diff --git a/spec/lib/gitlab/bare_repository_import/importer_spec.rb b/spec/lib/gitlab/bare_repository_import/importer_spec.rb
index e09430a858c..b0d721a74ce 100644
--- a/spec/lib/gitlab/bare_repository_import/importer_spec.rb
+++ b/spec/lib/gitlab/bare_repository_import/importer_spec.rb
@@ -89,10 +89,8 @@ RSpec.describe Gitlab::BareRepositoryImport::Importer, :seed_helper do
project = Project.find_by_full_path(project_path)
repo_path = "#{project.disk_path}.git"
- hook_path = File.join(repo_path, 'hooks')
expect(gitlab_shell.repository_exists?(project.repository_storage, repo_path)).to be(true)
- expect(TestEnv.storage_dir_exists?(project.repository_storage, hook_path)).to be(true)
end
context 'hashed storage enabled' do
diff --git a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
index 4e4d921d67f..f9313f0ff28 100644
--- a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
@@ -142,7 +142,7 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
expect { subject.execute }.to change { MergeRequest.count }.by(1)
merge_request = MergeRequest.first
- expect(merge_request.author).to eq(pull_request_author)
+ expect(merge_request.author).to eq(expected_author)
end
end
@@ -151,7 +151,25 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
stub_feature_flags(bitbucket_server_user_mapping_by_username: false)
end
- include_examples 'imports pull requests'
+ context 'when email is not present' do
+ before do
+ allow(pull_request).to receive(:author_email).and_return(nil)
+ end
+
+ let(:expected_author) { project_creator }
+
+ include_examples 'imports pull requests'
+ end
+
+ context 'when email is present' do
+ before do
+ allow(pull_request).to receive(:author_email).and_return(pull_request_author.email)
+ end
+
+ let(:expected_author) { pull_request_author }
+
+ include_examples 'imports pull requests'
+ end
end
context 'when bitbucket_server_user_mapping_by_username feature flag is enabled' do
@@ -159,19 +177,24 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
stub_feature_flags(bitbucket_server_user_mapping_by_username: true)
end
- include_examples 'imports pull requests' do
- context 'when username is not present' do
- before do
- allow(pull_request).to receive(:author_username).and_return(nil)
- end
+ context 'when username is not present' do
+ before do
+ allow(pull_request).to receive(:author_username).and_return(nil)
+ end
- it 'maps by email' do
- expect { subject.execute }.to change { MergeRequest.count }.by(1)
+ let(:expected_author) { project_creator }
- merge_request = MergeRequest.first
- expect(merge_request.author).to eq(pull_request_author)
- end
+ include_examples 'imports pull requests'
+ end
+
+ context 'when username is present' do
+ before do
+ allow(pull_request).to receive(:author_username).and_return(pull_request_author.username)
end
+
+ let(:expected_author) { pull_request_author }
+
+ include_examples 'imports pull requests'
end
end
@@ -228,7 +251,23 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
allow(subject.client).to receive(:activities).and_return([pr_comment])
end
- it 'maps by email' do
+ it 'defaults to import user' do
+ expect { subject.execute }.to change { MergeRequest.count }.by(1)
+
+ merge_request = MergeRequest.first
+ expect(merge_request.notes.count).to eq(1)
+ note = merge_request.notes.first
+ expect(note.author).to eq(project_creator)
+ end
+ end
+
+ context 'when username is present' do
+ before do
+ allow(pr_note).to receive(:author_username).and_return(note_author.username)
+ allow(subject.client).to receive(:activities).and_return([pr_comment])
+ end
+
+ it 'maps by username' do
expect { subject.execute }.to change { MergeRequest.count }.by(1)
merge_request = MergeRequest.first
@@ -241,7 +280,7 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
end
context 'metrics' do
- let(:histogram) { double(:histogram) }
+ let(:histogram) { double(:histogram).as_null_object }
let(:counter) { double('counter', increment: true) }
before do
@@ -276,7 +315,6 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
)
expect(counter).to receive(:increment)
- allow(histogram).to receive(:observe).with({ importer: :bitbucket_server_importer }, anything)
subject.execute
end
@@ -384,13 +422,13 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
allow(inline_note).to receive(:author_username).and_return(nil)
end
- it 'maps by email' do
+ it 'defaults to import user' do
expect { subject.execute }.to change { MergeRequest.count }.by(1)
notes = MergeRequest.first.notes.order(:id).to_a
- expect(notes.first.author).to eq(inline_note_author)
- expect(notes.last.author).to eq(reply_author)
+ expect(notes.first.author).to eq(project_creator)
+ expect(notes.last.author).to eq(project_creator)
end
end
end
diff --git a/spec/lib/gitlab/blob_helper_spec.rb b/spec/lib/gitlab/blob_helper_spec.rb
index 65fa5bf0120..a2f20dcd4fc 100644
--- a/spec/lib/gitlab/blob_helper_spec.rb
+++ b/spec/lib/gitlab/blob_helper_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Gitlab::BlobHelper do
let(:project) { create(:project) }
let(:blob) { fake_blob(path: 'file.txt') }
+ let(:webp_blob) { fake_blob(path: 'file.webp') }
let(:large_blob) { fake_blob(path: 'test.pdf', size: 2.megabytes, binary: true) }
describe '#extname' do
@@ -62,8 +63,15 @@ RSpec.describe Gitlab::BlobHelper do
end
describe '#image?' do
- it 'returns false' do
- expect(blob.image?).to be_falsey
+ context 'with a .txt file' do
+ it 'returns false' do
+ expect(blob.image?).to be_falsey
+ end
+ end
+ context 'with a .webp file' do
+ it 'returns true' do
+ expect(webp_blob.image?).to be_truthy
+ end
end
end
diff --git a/spec/lib/gitlab/ci/artifact_file_reader_spec.rb b/spec/lib/gitlab/ci/artifact_file_reader_spec.rb
index 83a37655ea9..e982f0eb015 100644
--- a/spec/lib/gitlab/ci/artifact_file_reader_spec.rb
+++ b/spec/lib/gitlab/ci/artifact_file_reader_spec.rb
@@ -18,17 +18,6 @@ RSpec.describe Gitlab::Ci::ArtifactFileReader do
expect(YAML.safe_load(subject).keys).to contain_exactly('rspec', 'time', 'custom')
end
- context 'when FF ci_new_artifact_file_reader is disabled' do
- before do
- stub_feature_flags(ci_new_artifact_file_reader: false)
- end
-
- it 'returns the content at the path' do
- is_expected.to be_present
- expect(YAML.safe_load(subject).keys).to contain_exactly('rspec', 'time', 'custom')
- end
- end
-
context 'when path does not exist' do
let(:path) { 'file/does/not/exist.txt' }
let(:expected_error) do
diff --git a/spec/lib/gitlab/ci/artifacts/metrics_spec.rb b/spec/lib/gitlab/ci/artifacts/metrics_spec.rb
index 3a2095498ec..0ce76285b03 100644
--- a/spec/lib/gitlab/ci/artifacts/metrics_spec.rb
+++ b/spec/lib/gitlab/ci/artifacts/metrics_spec.rb
@@ -10,9 +10,9 @@ RSpec.describe Gitlab::Ci::Artifacts::Metrics, :prometheus do
let(:counter) { metrics.send(:destroyed_artifacts_counter) }
it 'increments a single counter' do
- subject.increment_destroyed_artifacts(10)
- subject.increment_destroyed_artifacts(20)
- subject.increment_destroyed_artifacts(30)
+ subject.increment_destroyed_artifacts_count(10)
+ subject.increment_destroyed_artifacts_count(20)
+ subject.increment_destroyed_artifacts_count(30)
expect(counter.get).to eq 60
expect(counter.values.count).to eq 1
diff --git a/spec/lib/gitlab/ci/build/auto_retry_spec.rb b/spec/lib/gitlab/ci/build/auto_retry_spec.rb
index fc5999d59ac..9ff9200322e 100644
--- a/spec/lib/gitlab/ci/build/auto_retry_spec.rb
+++ b/spec/lib/gitlab/ci/build/auto_retry_spec.rb
@@ -25,6 +25,8 @@ RSpec.describe Gitlab::Ci::Build::AutoRetry do
"quota is exceeded" | 0 | { max: 2 } | :ci_quota_exceeded | false
"no matching runner" | 0 | { max: 2 } | :no_matching_runner | false
"missing dependencies" | 0 | { max: 2 } | :missing_dependency_failure | false
+ "forward deployment failure" | 0 | { max: 2 } | :forward_deployment_failure | false
+ "environment creation failure" | 0 | { max: 2 } | :environment_creation_failure | false
end
with_them do
diff --git a/spec/lib/gitlab/ci/build/rules/rule/clause/exists_spec.rb b/spec/lib/gitlab/ci/build/rules/rule/clause/exists_spec.rb
index 86dd5569a96..f192862c1c4 100644
--- a/spec/lib/gitlab/ci/build/rules/rule/clause/exists_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules/rule/clause/exists_spec.rb
@@ -3,10 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Exists do
- describe '#satisfied_by?' do
- let(:pipeline) { build(:ci_pipeline, project: project, sha: project.repository.head_commit.sha) }
-
- subject { described_class.new(globs).satisfied_by?(pipeline, nil) }
+ shared_examples 'an exists rule with a context' do
+ subject { described_class.new(globs).satisfied_by?(pipeline, context) }
it_behaves_like 'a glob matching rule' do
let(:project) { create(:project, :custom_repo, files: files) }
@@ -24,4 +22,26 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Exists do
it { is_expected.to be_truthy }
end
end
+
+ describe '#satisfied_by?' do
+ let(:pipeline) { build(:ci_pipeline, project: project, sha: project.repository.head_commit.sha) }
+
+ context 'when context is Build::Context::Build' do
+ it_behaves_like 'an exists rule with a context' do
+ let(:context) { Gitlab::Ci::Build::Context::Build.new(pipeline, sha: 'abc1234') }
+ end
+ end
+
+ context 'when context is Build::Context::Global' do
+ it_behaves_like 'an exists rule with a context' do
+ let(:context) { Gitlab::Ci::Build::Context::Global.new(pipeline, yaml_variables: {}) }
+ end
+ end
+
+ context 'when context is Config::External::Context' do
+ it_behaves_like 'an exists rule with a context' do
+ let(:context) { Gitlab::Ci::Config::External::Context.new(project: project, sha: project.repository.tree.sha) }
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/config/entry/include/rules/rule_spec.rb b/spec/lib/gitlab/ci/config/entry/include/rules/rule_spec.rb
index b99048e2c18..0505b17ea91 100644
--- a/spec/lib/gitlab/ci/config/entry/include/rules/rule_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/include/rules/rule_spec.rb
@@ -5,7 +5,7 @@ require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Config::Entry::Include::Rules::Rule do
let(:factory) do
Gitlab::Config::Entry::Factory.new(described_class)
- .value(config)
+ .value(config)
end
subject(:entry) { factory.create! }
@@ -25,6 +25,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Include::Rules::Rule do
it { is_expected.to be_valid }
end
+ context 'when specifying an exists: clause' do
+ let(:config) { { exists: './this.md' } }
+
+ it { is_expected.to be_valid }
+ end
+
context 'using a list of multiple expressions' do
let(:config) { { if: ['$MY_VAR == "this"', '$YOUR_VAR == "that"'] } }
@@ -86,5 +92,13 @@ RSpec.describe Gitlab::Ci::Config::Entry::Include::Rules::Rule do
expect(subject).to eq(if: '$THIS || $THAT')
end
end
+
+ context 'when specifying an exists: clause' do
+ let(:config) { { exists: './test.md' } }
+
+ it 'returns the config' do
+ expect(subject).to eq(exists: './test.md')
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
index b872f6644a2..c9c28e2eb8b 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -33,6 +33,14 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
end
end
+ context 'when job name is more than 255' do
+ let(:entry) { node_class.new(config, name: ('a' * 256).to_sym) }
+
+ it 'shows a validation error' do
+ expect(entry.errors).to include "job name is too long (maximum is 255 characters)"
+ end
+ end
+
context 'when job name is empty' do
let(:entry) { node_class.new(config, name: ''.to_sym) }
diff --git a/spec/lib/gitlab/ci/config/extendable_spec.rb b/spec/lib/gitlab/ci/config/extendable_spec.rb
index 481f55d790e..2fc009569fc 100644
--- a/spec/lib/gitlab/ci/config/extendable_spec.rb
+++ b/spec/lib/gitlab/ci/config/extendable_spec.rb
@@ -73,6 +73,50 @@ RSpec.describe Gitlab::Ci::Config::Extendable do
end
end
+ context 'when the job tries to delete an extension key' do
+ let(:hash) do
+ {
+ something: {
+ script: 'deploy',
+ only: { variables: %w[$SOMETHING] }
+ },
+
+ test1: {
+ extends: 'something',
+ script: 'ls',
+ only: {}
+ },
+
+ test2: {
+ extends: 'something',
+ script: 'ls',
+ only: nil
+ }
+ }
+ end
+
+ it 'deletes the key if assigned to null' do
+ expect(subject.to_hash).to eq(
+ something: {
+ script: 'deploy',
+ only: { variables: %w[$SOMETHING] }
+ },
+ test1: {
+ extends: 'something',
+ script: 'ls',
+ only: {
+ variables: %w[$SOMETHING]
+ }
+ },
+ test2: {
+ extends: 'something',
+ script: 'ls',
+ only: nil
+ }
+ )
+ end
+ end
+
context 'when a hash uses recursive extensions' do
let(:hash) do
{
diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
index c2f28253f54..2e9e6f95071 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -406,7 +406,7 @@ RSpec.describe Gitlab::Ci::Config::External::Processor do
context 'when rules defined' do
context 'when a rule is invalid' do
let(:values) do
- { include: [{ local: 'builds.yml', rules: [{ exists: ['$MY_VAR'] }] }] }
+ { include: [{ local: 'builds.yml', rules: [{ changes: ['$MY_VAR'] }] }] }
end
it 'raises IncludeError' do
diff --git a/spec/lib/gitlab/ci/config/external/rules_spec.rb b/spec/lib/gitlab/ci/config/external/rules_spec.rb
index 9a5c29befa2..1e42cb30ae7 100644
--- a/spec/lib/gitlab/ci/config/external/rules_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/rules_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::External::Rules do
let(:rule_hashes) {}
@@ -32,6 +32,26 @@ RSpec.describe Gitlab::Ci::Config::External::Rules do
end
end
+ context 'when there is a rule with exists' do
+ let(:project) { create(:project, :repository) }
+ let(:context) { double(project: project, sha: project.repository.tree.sha, top_level_worktree_paths: ['test.md']) }
+ let(:rule_hashes) { [{ exists: 'Dockerfile' }] }
+
+ context 'when the file does not exist' do
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when the file exists' do
+ let(:context) { double(project: project, sha: project.repository.tree.sha, top_level_worktree_paths: ['Dockerfile']) }
+
+ before do
+ project.repository.create_file(project.owner, 'Dockerfile', "commit", message: 'test', branch_name: "master")
+ end
+
+ it { is_expected.to eq(true) }
+ end
+ end
+
context 'when there is a rule with if and when' do
let(:rule_hashes) { [{ if: '$MY_VAR == "hello"', when: 'on_success' }] }
@@ -41,12 +61,12 @@ RSpec.describe Gitlab::Ci::Config::External::Rules do
end
end
- context 'when there is a rule with exists' do
- let(:rule_hashes) { [{ exists: ['$MY_VAR'] }] }
+ context 'when there is a rule with changes' do
+ let(:rule_hashes) { [{ changes: ['$MY_VAR'] }] }
it 'raises an error' do
expect { result }.to raise_error(described_class::InvalidIncludeRulesError,
- 'invalid include rule: {:exists=>["$MY_VAR"]}')
+ 'invalid include rule: {:changes=>["$MY_VAR"]}')
end
end
end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index 3ec4519748f..1b3e8a2ce4a 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Gitlab::Ci::Config do
end
let(:config) do
- described_class.new(yml, project: nil, sha: nil, user: nil)
+ described_class.new(yml, project: nil, pipeline: nil, sha: nil, user: nil)
end
context 'when config is valid' do
@@ -286,9 +286,12 @@ RSpec.describe Gitlab::Ci::Config do
end
context "when using 'include' directive" do
- let(:group) { create(:group) }
+ let_it_be(:group) { create(:group) }
+
let(:project) { create(:project, :repository, group: group) }
let(:main_project) { create(:project, :repository, :public, group: group) }
+ let(:pipeline) { build(:ci_pipeline, project: project) }
+
let(:remote_location) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' }
let(:local_location) { 'spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml' }
@@ -327,7 +330,7 @@ RSpec.describe Gitlab::Ci::Config do
end
let(:config) do
- described_class.new(gitlab_ci_yml, project: project, sha: '12345', user: user)
+ described_class.new(gitlab_ci_yml, project: project, pipeline: pipeline, sha: '12345', user: user)
end
before do
@@ -594,7 +597,7 @@ RSpec.describe Gitlab::Ci::Config do
job1: {
script: ["echo 'hello from main file'"],
variables: {
- VARIABLE_DEFINED_IN_MAIN_FILE: 'some value'
+ VARIABLE_DEFINED_IN_MAIN_FILE: 'some value'
}
}
})
@@ -725,26 +728,91 @@ RSpec.describe Gitlab::Ci::Config do
end
context "when an 'include' has rules" do
+ context "when the rule is an if" do
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ - local: #{local_location}
+ rules:
+ - if: $CI_PROJECT_ID == "#{project_id}"
+ image: ruby:2.7
+ HEREDOC
+ end
+
+ context 'when the rules condition is satisfied' do
+ let(:project_id) { project.id }
+
+ it 'includes the file' do
+ expect(config.to_hash).to include(local_location_hash)
+ end
+ end
+
+ context 'when the rules condition is satisfied' do
+ let(:project_id) { non_existing_record_id }
+
+ it 'does not include the file' do
+ expect(config.to_hash).not_to include(local_location_hash)
+ end
+ end
+ end
+
+ context "when the rule is an exists" do
+ let(:gitlab_ci_yml) do
+ <<~HEREDOC
+ include:
+ - local: #{local_location}
+ rules:
+ - exists: "#{filename}"
+ image: ruby:2.7
+ HEREDOC
+ end
+
+ before do
+ project.repository.create_file(
+ project.creator,
+ 'my_builds.yml',
+ local_file_content,
+ message: 'Add my_builds.yml',
+ branch_name: '12345'
+ )
+ end
+
+ context 'when the exists file does not exist' do
+ let(:filename) { 'not_a_real_file.md' }
+
+ it 'does not include the file' do
+ expect(config.to_hash).not_to include(local_location_hash)
+ end
+ end
+
+ context 'when the exists file does exist' do
+ let(:filename) { 'my_builds.yml' }
+
+ it 'does include the file' do
+ expect(config.to_hash).to include(local_location_hash)
+ end
+ end
+ end
+ end
+
+ context "when an 'include' has rules with a pipeline variable" do
let(:gitlab_ci_yml) do
<<~HEREDOC
include:
- local: #{local_location}
rules:
- - if: $CI_PROJECT_ID == "#{project_id}"
- image: ruby:2.7
+ - if: $CI_COMMIT_SHA == "#{project.commit.sha}"
HEREDOC
end
- context 'when the rules condition is satisfied' do
- let(:project_id) { project.id }
-
+ context 'when a pipeline is passed' do
it 'includes the file' do
expect(config.to_hash).to include(local_location_hash)
end
end
- context 'when the rules condition is satisfied' do
- let(:project_id) { non_existing_record_id }
+ context 'when a pipeline is not passed' do
+ let(:pipeline) { nil }
it 'does not include the file' do
expect(config.to_hash).not_to include(local_location_hash)
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
index 16517b39a45..cf21c98dbd5 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
@@ -83,7 +83,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
end
end
- it 'respects the defined payload schema' do
+ it 'respects the defined payload schema', :saas do
expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
expect(params[:body]).to match_schema('/external_validation')
expect(params[:timeout]).to eq(described_class::DEFAULT_VALIDATION_REQUEST_TIMEOUT)
diff --git a/spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb b/spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb
index c52994fc6a2..5b0917c5c6f 100644
--- a/spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Quota::Deployments do
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:default_plan, reload: true) { create(:default_plan) }
- let_it_be(:project, reload: true) { create(:project, :repository, namespace: namespace) }
+ let_it_be_with_refind(:namespace) { create(:namespace) }
+ let_it_be_with_reload(:default_plan) { create(:default_plan) }
+ let_it_be_with_reload(:project) { create(:project, :repository, namespace: namespace) }
let_it_be(:plan_limits) { create(:plan_limits, plan: default_plan) }
let(:pipeline) { build_stubbed(:ci_pipeline, project: project) }
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index 3aa6b2e3c05..e2b64e65938 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
- let_it_be(:project) { create(:project, :repository) }
+ let_it_be_with_reload(:project) { create(:project, :repository) }
let_it_be(:head_sha) { project.repository.head_commit.id }
let(:pipeline) { build(:ci_empty_pipeline, project: project, sha: head_sha) }
@@ -13,7 +13,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
let(:previous_stages) { [] }
let(:current_stage) { double(seeds_names: [attributes[:name]]) }
- let(:seed_build) { described_class.new(seed_context, attributes, previous_stages, current_stage) }
+ let(:seed_build) { described_class.new(seed_context, attributes, previous_stages + [current_stage]) }
describe '#attributes' do
subject { seed_build.attributes }
@@ -393,12 +393,14 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
describe '#to_resource' do
subject { seed_build.to_resource }
- context 'when job is not a bridge' do
+ context 'when job is Ci::Build' do
it { is_expected.to be_a(::Ci::Build) }
it { is_expected.to be_valid }
shared_examples_for 'deployment job' do
it 'returns a job with deployment' do
+ expect { subject }.to change { Environment.count }.by(1)
+
expect(subject.deployment).not_to be_nil
expect(subject.deployment.deployable).to eq(subject)
expect(subject.deployment.environment.name).to eq(expected_environment_name)
@@ -413,6 +415,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
shared_examples_for 'ensures environment existence' do
it 'has environment' do
+ expect { subject }.to change { Environment.count }.by(1)
+
expect(subject).to be_has_environment
expect(subject.environment).to eq(environment_name)
expect(subject.metadata.expanded_environment_name).to eq(expected_environment_name)
@@ -422,6 +426,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
shared_examples_for 'ensures environment inexistence' do
it 'does not have environment' do
+ expect { subject }.not_to change { Environment.count }
+
expect(subject).not_to be_has_environment
expect(subject.environment).to be_nil
expect(subject.metadata&.expanded_environment_name).to be_nil
@@ -1212,14 +1218,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
]
end
- context 'when FF :variable_inside_variable is enabled' do
- before do
- stub_feature_flags(variable_inside_variable: [project])
- end
-
- it "does not have errors" do
- expect(subject.errors).to be_empty
- end
+ it "does not have errors" do
+ expect(subject.errors).to be_empty
end
end
@@ -1232,36 +1232,20 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
]
end
- context 'when FF :variable_inside_variable is disabled' do
- before do
- stub_feature_flags(variable_inside_variable: false)
- end
-
- it "does not have errors" do
- expect(subject.errors).to be_empty
- end
+ it "returns an error" do
+ expect(subject.errors).to contain_exactly(
+ 'rspec: circular variable reference detected: ["A", "B", "C"]')
end
- context 'when FF :variable_inside_variable is enabled' do
- before do
- stub_feature_flags(variable_inside_variable: [project])
- end
+ context 'with job:rules:[if:]' do
+ let(:attributes) { { name: 'rspec', ref: 'master', rules: [{ if: '$C != null', when: 'always' }] } }
- it "returns an error" do
- expect(subject.errors).to contain_exactly(
- 'rspec: circular variable reference detected: ["A", "B", "C"]')
+ it "included? does not raise" do
+ expect { subject.included? }.not_to raise_error
end
- context 'with job:rules:[if:]' do
- let(:attributes) { { name: 'rspec', ref: 'master', rules: [{ if: '$C != null', when: 'always' }] } }
-
- it "included? does not raise" do
- expect { subject.included? }.not_to raise_error
- end
-
- it "included? returns true" do
- expect(subject.included?).to eq(true)
- end
+ it "included? returns true" do
+ expect(subject.included?).to eq(true)
end
end
end
diff --git a/spec/lib/gitlab/ci/reports/security/report_spec.rb b/spec/lib/gitlab/ci/reports/security/report_spec.rb
index 5a85c3f19fc..a8b962ee970 100644
--- a/spec/lib/gitlab/ci/reports/security/report_spec.rb
+++ b/spec/lib/gitlab/ci/reports/security/report_spec.rb
@@ -221,4 +221,26 @@ RSpec.describe Gitlab::Ci::Reports::Security::Report do
end
end
end
+
+ describe '#has_signatures?' do
+ let(:finding) { create(:ci_reports_security_finding, signatures: signatures) }
+
+ subject { report.has_signatures? }
+
+ before do
+ report.add_finding(finding)
+ end
+
+ context 'when the findings of the report does not have signatures' do
+ let(:signatures) { [] }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when the findings of the report have signatures' do
+ let(:signatures) { [instance_double(Gitlab::Ci::Reports::Security::FindingSignature)] }
+
+ it { is_expected.to be_truthy }
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/reports/security/reports_spec.rb b/spec/lib/gitlab/ci/reports/security/reports_spec.rb
index 9b1e02f1418..79eee642552 100644
--- a/spec/lib/gitlab/ci/reports/security/reports_spec.rb
+++ b/spec/lib/gitlab/ci/reports/security/reports_spec.rb
@@ -54,11 +54,12 @@ RSpec.describe Gitlab::Ci::Reports::Security::Reports do
end
describe "#violates_default_policy_against?" do
- let(:high_severity_dast) { build(:ci_reports_security_finding, severity: 'high', report_type: :dast) }
+ let(:high_severity_dast) { build(:ci_reports_security_finding, severity: 'high', report_type: 'dast') }
let(:vulnerabilities_allowed) { 0 }
let(:severity_levels) { %w(critical high) }
+ let(:vulnerability_states) { %w(newly_detected)}
- subject { security_reports.violates_default_policy_against?(target_reports, vulnerabilities_allowed, severity_levels) }
+ subject { security_reports.violates_default_policy_against?(target_reports, vulnerabilities_allowed, severity_levels, vulnerability_states) }
before do
security_reports.get_report('sast', artifact).add_finding(high_severity_dast)
@@ -108,6 +109,22 @@ RSpec.describe Gitlab::Ci::Reports::Security::Reports do
it { is_expected.to be(false) }
end
+
+ context 'with related report_types' do
+ let(:report_types) { %w(dast sast) }
+
+ subject { security_reports.violates_default_policy_against?(target_reports, vulnerabilities_allowed, severity_levels, vulnerability_states, report_types) }
+
+ it { is_expected.to be(true) }
+ end
+
+ context 'with unrelated report_types' do
+ let(:report_types) { %w(dependency_scanning sast) }
+
+ subject { security_reports.violates_default_policy_against?(target_reports, vulnerabilities_allowed, severity_levels, vulnerability_states, report_types) }
+
+ it { is_expected.to be(false) }
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
index d377cf0c735..789f694b4b4 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
@@ -27,9 +27,9 @@ RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
end
describe 'the created pipeline' do
- let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
+ let_it_be(:project, refind: true) { create(:project, :repository) }
+ let(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
@@ -43,23 +43,23 @@ RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
allow(project).to receive(:default_branch).and_return(default_branch)
end
- context 'with no cluster' do
+ context 'with no cluster or agent' do
it 'does not create any kubernetes deployment jobs' do
expect(build_names).to eq %w(placeholder)
end
end
context 'with only a disabled cluster' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp, enabled: false, projects: [project]) }
+ before do
+ create(:cluster, :project, :provided_by_gcp, enabled: false, projects: [project])
+ end
it 'does not create any kubernetes deployment jobs' do
expect(build_names).to eq %w(placeholder)
end
end
- context 'with an active cluster' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp, projects: [project]) }
-
+ shared_examples_for 'pipeline with deployment jobs' do
context 'on master' do
it 'by default' do
expect(build_names).to include('production')
@@ -218,5 +218,21 @@ RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
end
end
end
+
+ context 'with an agent' do
+ before do
+ create(:cluster_agent, project: project)
+ end
+
+ it_behaves_like 'pipeline with deployment jobs'
+ end
+
+ context 'with a cluster' do
+ before do
+ create(:cluster, :project, :provided_by_gcp, projects: [project])
+ end
+
+ it_behaves_like 'pipeline with deployment jobs'
+ end
end
end
diff --git a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb
new file mode 100644
index 00000000000..b9256ece78b
--- /dev/null
+++ b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Jobs/SAST-IaC.latest.gitlab-ci.yml' do
+ subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Jobs/SAST-IaC.latest') }
+
+ describe 'the created pipeline' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
+
+ let(:default_branch) { 'main' }
+ let(:pipeline_ref) { default_branch }
+ let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
+ let(:pipeline) { service.execute!(:push).payload }
+ let(:build_names) { pipeline.builds.pluck(:name) }
+
+ before do
+ stub_ci_pipeline_yaml_file(template.content)
+ allow_next_instance_of(Ci::BuildScheduleWorker) do |instance|
+ allow(instance).to receive(:perform).and_return(true)
+ end
+ allow(project).to receive(:default_branch).and_return(default_branch)
+ end
+
+ context 'on feature branch' do
+ let(:pipeline_ref) { 'feature' }
+
+ it 'creates the kics-iac-sast job' do
+ expect(build_names).to contain_exactly('kics-iac-sast')
+ end
+ end
+
+ context 'on merge request' do
+ let(:service) { MergeRequests::CreatePipelineService.new(project: project, current_user: user) }
+ let(:merge_request) { create(:merge_request, :simple, source_project: project) }
+ let(:pipeline) { service.execute(merge_request).payload }
+
+ it 'has no jobs' do
+ expect(pipeline).to be_merge_request_event
+ expect(build_names).to be_empty
+ end
+ end
+
+ context 'SAST_DISABLED is set' do
+ before do
+ create(:ci_variable, key: 'SAST_DISABLED', value: 'true', project: project)
+ end
+
+ context 'on default branch' do
+ it 'has no jobs' do
+ expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError)
+ end
+ end
+
+ context 'on feature branch' do
+ let(:pipeline_ref) { 'feature' }
+
+ it 'has no jobs' do
+ expect { pipeline }.to raise_error(Ci::CreatePipelineService::CreateError)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
index 7602309627b..64ef6ecd7f8 100644
--- a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
@@ -148,9 +148,7 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
it_behaves_like 'no Kubernetes deployment job'
end
- context 'when the project has an active cluster' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp, projects: [project]) }
-
+ shared_examples 'pipeline with Kubernetes jobs' do
describe 'deployment-related builds' do
context 'on default branch' do
it 'does not include rollout jobs besides production' do
@@ -233,6 +231,22 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
end
end
end
+
+ context 'when a cluster is attached' do
+ before do
+ create(:cluster, :project, :provided_by_gcp, projects: [project])
+ end
+
+ it_behaves_like 'pipeline with Kubernetes jobs'
+ end
+
+ context 'when project has an Agent is present' do
+ before do
+ create(:cluster_agent, project: project)
+ end
+
+ it_behaves_like 'pipeline with Kubernetes jobs'
+ end
end
describe 'buildpack detection' do
diff --git a/spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb
new file mode 100644
index 00000000000..c7dbbea4622
--- /dev/null
+++ b/spec/lib/gitlab/ci/templates/kaniko_gitlab_ci_yaml_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Kaniko.gitlab-ci.yml' do
+ subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Kaniko') }
+
+ describe 'the created pipeline' do
+ let(:pipeline_branch) { 'master' }
+ let(:project) { create(:project, :custom_repo, files: { 'Dockerfile' => 'FROM alpine:latest' }) }
+ let(:user) { project.owner }
+ let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
+ let(:pipeline) { service.execute!(:push).payload }
+ let(:build_names) { pipeline.builds.pluck(:name) }
+
+ before do
+ stub_ci_pipeline_yaml_file(template.content)
+ allow(Ci::BuildScheduleWorker).to receive(:perform).and_return(true)
+ end
+
+ it 'creates "kaniko-build" job' do
+ expect(build_names).to include('kaniko-build')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
index 3d1306e82a5..fd5d5d6af7f 100644
--- a/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe 'Terraform.latest.gitlab-ci.yml' do
context 'on master branch' do
it 'creates init, validate and build jobs', :aggregate_failures do
expect(pipeline.errors).to be_empty
- expect(build_names).to include('init', 'validate', 'build', 'deploy')
+ expect(build_names).to include('validate', 'build', 'deploy')
end
end
diff --git a/spec/lib/gitlab/ci/trace/archive_spec.rb b/spec/lib/gitlab/ci/trace/archive_spec.rb
index c9fc4e720c4..5e965f94347 100644
--- a/spec/lib/gitlab/ci/trace/archive_spec.rb
+++ b/spec/lib/gitlab/ci/trace/archive_spec.rb
@@ -3,99 +3,134 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Trace::Archive do
- let_it_be(:job) { create(:ci_build, :success, :trace_live) }
- let_it_be_with_reload(:trace_metadata) { create(:ci_build_trace_metadata, build: job) }
- let_it_be(:src_checksum) do
- job.trace.read { |stream| Digest::MD5.hexdigest(stream.raw) }
- end
-
- let(:metrics) { spy('metrics') }
-
- describe '#execute' do
- subject { described_class.new(job, trace_metadata, metrics) }
-
- it 'computes and assigns checksum' do
- Gitlab::Ci::Trace::ChunkedIO.new(job) do |stream|
- expect { subject.execute!(stream) }.to change { Ci::JobArtifact.count }.by(1)
- end
-
- expect(trace_metadata.checksum).to eq(src_checksum)
- expect(trace_metadata.trace_artifact).to eq(job.job_artifacts_trace)
+ context 'with transactional fixtures' do
+ let_it_be(:job) { create(:ci_build, :success, :trace_live) }
+ let_it_be_with_reload(:trace_metadata) { create(:ci_build_trace_metadata, build: job) }
+ let_it_be(:src_checksum) do
+ job.trace.read { |stream| Digest::MD5.hexdigest(stream.raw) }
end
- context 'validating artifact checksum' do
- let(:trace) { 'abc' }
- let(:stream) { StringIO.new(trace, 'rb') }
- let(:src_checksum) { Digest::MD5.hexdigest(trace) }
+ let(:metrics) { spy('metrics') }
- context 'when the object store is disabled' do
- before do
- stub_artifacts_object_storage(enabled: false)
- end
-
- it 'skips validation' do
- subject.execute!(stream)
+ describe '#execute' do
+ subject { described_class.new(job, trace_metadata, metrics) }
- expect(trace_metadata.checksum).to eq(src_checksum)
- expect(trace_metadata.remote_checksum).to be_nil
- expect(metrics)
- .not_to have_received(:increment_error_counter)
- .with(type: :archive_invalid_checksum)
+ it 'computes and assigns checksum' do
+ Gitlab::Ci::Trace::ChunkedIO.new(job) do |stream|
+ expect { subject.execute!(stream) }.to change { Ci::JobArtifact.count }.by(1)
end
+
+ expect(trace_metadata.checksum).to eq(src_checksum)
+ expect(trace_metadata.trace_artifact).to eq(job.job_artifacts_trace)
end
- context 'with background_upload enabled' do
- before do
- stub_artifacts_object_storage(background_upload: true)
- end
+ context 'validating artifact checksum' do
+ let(:trace) { 'abc' }
+ let(:stream) { StringIO.new(trace, 'rb') }
+ let(:src_checksum) { Digest::MD5.hexdigest(trace) }
- it 'skips validation' do
- subject.execute!(stream)
+ context 'when the object store is disabled' do
+ before do
+ stub_artifacts_object_storage(enabled: false)
+ end
- expect(trace_metadata.checksum).to eq(src_checksum)
- expect(trace_metadata.remote_checksum).to be_nil
- expect(metrics)
- .not_to have_received(:increment_error_counter)
- .with(type: :archive_invalid_checksum)
+ it 'skips validation' do
+ subject.execute!(stream)
+ expect(trace_metadata.checksum).to eq(src_checksum)
+ expect(trace_metadata.remote_checksum).to be_nil
+ expect(metrics)
+ .not_to have_received(:increment_error_counter)
+ .with(error_reason: :archive_invalid_checksum)
+ end
end
- end
- context 'with direct_upload enabled' do
- before do
- stub_artifacts_object_storage(direct_upload: true)
- end
+ context 'with background_upload enabled' do
+ before do
+ stub_artifacts_object_storage(background_upload: true)
+ end
- it 'validates the archived trace' do
- subject.execute!(stream)
+ it 'skips validation' do
+ subject.execute!(stream)
- expect(trace_metadata.checksum).to eq(src_checksum)
- expect(trace_metadata.remote_checksum).to eq(src_checksum)
- expect(metrics)
- .not_to have_received(:increment_error_counter)
- .with(type: :archive_invalid_checksum)
+ expect(trace_metadata.checksum).to eq(src_checksum)
+ expect(trace_metadata.remote_checksum).to be_nil
+ expect(metrics)
+ .not_to have_received(:increment_error_counter)
+ .with(error_reason: :archive_invalid_checksum)
+ end
end
- context 'when the checksum does not match' do
- let(:invalid_remote_checksum) { SecureRandom.hex }
-
+ context 'with direct_upload enabled' do
before do
- expect(::Gitlab::Ci::Trace::RemoteChecksum)
- .to receive(:new)
- .with(an_instance_of(Ci::JobArtifact))
- .and_return(double(md5_checksum: invalid_remote_checksum))
+ stub_artifacts_object_storage(direct_upload: true)
end
it 'validates the archived trace' do
subject.execute!(stream)
expect(trace_metadata.checksum).to eq(src_checksum)
- expect(trace_metadata.remote_checksum).to eq(invalid_remote_checksum)
+ expect(trace_metadata.remote_checksum).to eq(src_checksum)
expect(metrics)
- .to have_received(:increment_error_counter)
- .with(type: :archive_invalid_checksum)
+ .not_to have_received(:increment_error_counter)
+ .with(error_reason: :archive_invalid_checksum)
+ end
+
+ context 'when the checksum does not match' do
+ let(:invalid_remote_checksum) { SecureRandom.hex }
+
+ before do
+ expect(::Gitlab::Ci::Trace::RemoteChecksum)
+ .to receive(:new)
+ .with(an_instance_of(Ci::JobArtifact))
+ .and_return(double(md5_checksum: invalid_remote_checksum))
+ end
+
+ it 'validates the archived trace' do
+ subject.execute!(stream)
+
+ expect(trace_metadata.checksum).to eq(src_checksum)
+ expect(trace_metadata.remote_checksum).to eq(invalid_remote_checksum)
+ expect(metrics)
+ .to have_received(:increment_error_counter)
+ .with(error_reason: :archive_invalid_checksum)
+ end
end
end
end
end
end
+
+ context 'without transactional fixtures', :delete do
+ let(:job) { create(:ci_build, :success, :trace_live) }
+ let(:trace_metadata) { create(:ci_build_trace_metadata, build: job) }
+ let(:stream) { StringIO.new('abc', 'rb') }
+
+ describe '#execute!' do
+ subject(:execute) do
+ ::Gitlab::Ci::Trace::Archive.new(job, trace_metadata).execute!(stream)
+ end
+
+ before do
+ stub_artifacts_object_storage(direct_upload: true)
+ end
+
+ it 'does not upload the trace inside a database transaction', :delete do
+ expect(Ci::ApplicationRecord.connection.transaction_open?).to be_falsey
+
+ allow_next_instance_of(Ci::JobArtifact) do |artifact|
+ artifact.job_id = job.id
+
+ expect(artifact)
+ .to receive(:store_file!)
+ .and_wrap_original do |store_method, *args|
+ expect(Ci::ApplicationRecord.connection.transaction_open?).to be_falsey
+
+ store_method.call(*args)
+ end
+ end
+
+ execute
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/trace/metrics_spec.rb b/spec/lib/gitlab/ci/trace/metrics_spec.rb
index 53e55a57973..733ffbbea22 100644
--- a/spec/lib/gitlab/ci/trace/metrics_spec.rb
+++ b/spec/lib/gitlab/ci/trace/metrics_spec.rb
@@ -17,23 +17,23 @@ RSpec.describe Gitlab::Ci::Trace::Metrics, :prometheus do
end
describe '#increment_error_counter' do
- context 'when the operation type is known' do
+ context 'when the error reason is known' do
it 'increments the counter' do
- subject.increment_error_counter(type: :chunks_invalid_size)
- subject.increment_error_counter(type: :chunks_invalid_checksum)
- subject.increment_error_counter(type: :archive_invalid_checksum)
+ subject.increment_error_counter(error_reason: :chunks_invalid_size)
+ subject.increment_error_counter(error_reason: :chunks_invalid_checksum)
+ subject.increment_error_counter(error_reason: :archive_invalid_checksum)
- expect(described_class.trace_errors_counter.get(type: :chunks_invalid_size)).to eq 1
- expect(described_class.trace_errors_counter.get(type: :chunks_invalid_checksum)).to eq 1
- expect(described_class.trace_errors_counter.get(type: :archive_invalid_checksum)).to eq 1
+ expect(described_class.trace_errors_counter.get(error_reason: :chunks_invalid_size)).to eq 1
+ expect(described_class.trace_errors_counter.get(error_reason: :chunks_invalid_checksum)).to eq 1
+ expect(described_class.trace_errors_counter.get(error_reason: :archive_invalid_checksum)).to eq 1
expect(described_class.trace_errors_counter.values.count).to eq 3
end
end
- context 'when the operation type is known' do
+ context 'when the error reason is unknown' do
it 'raises an exception' do
- expect { subject.increment_error_counter(type: :invalid_type) }
+ expect { subject.increment_error_counter(error_reason: :invalid_type) }
.to raise_error(ArgumentError)
end
end
diff --git a/spec/lib/gitlab/ci/trace_spec.rb b/spec/lib/gitlab/ci/trace_spec.rb
index 1a31b2dad56..888ceb7ff9a 100644
--- a/spec/lib/gitlab/ci/trace_spec.rb
+++ b/spec/lib/gitlab/ci/trace_spec.rb
@@ -25,16 +25,6 @@ RSpec.describe Gitlab::Ci::Trace, :clean_gitlab_redis_shared_state, factory_defa
artifact1.file.migrate!(ObjectStorage::Store::REMOTE)
end
- it 'reloads the trace after is it migrated' do
- stub_const('Gitlab::HttpIO::BUFFER_SIZE', test_data.length)
-
- expect_next_instance_of(Gitlab::HttpIO) do |http_io|
- expect(http_io).to receive(:get_chunk).and_return(test_data, "")
- end
-
- expect(artifact2.job.trace.raw).to eq(test_data)
- end
-
it 'reloads the trace in case of a chunk error' do
chunk_error = described_class::ChunkedIO::FailedToGetChunkError
diff --git a/spec/lib/gitlab/ci/variables/builder_spec.rb b/spec/lib/gitlab/ci/variables/builder_spec.rb
new file mode 100644
index 00000000000..10275f33484
--- /dev/null
+++ b/spec/lib/gitlab/ci/variables/builder_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Variables::Builder do
+ let(:builder) { described_class.new(pipeline) }
+ let(:pipeline) { create(:ci_pipeline) }
+ let(:job) { create(:ci_build, pipeline: pipeline) }
+
+ describe '#scoped_variables' do
+ let(:environment) { job.expanded_environment_name }
+ let(:dependencies) { true }
+
+ subject { builder.scoped_variables(job, environment: environment, dependencies: dependencies) }
+
+ it 'returns the expected variables' do
+ keys = %w[CI_JOB_NAME
+ CI_JOB_STAGE
+ CI_NODE_TOTAL
+ CI_BUILD_NAME
+ CI_BUILD_STAGE]
+
+ subject.map { |env| env[:key] }.tap do |names|
+ expect(names).to include(*keys)
+ end
+ end
+
+ context 'feature flag disabled' do
+ before do
+ stub_feature_flags(ci_predefined_vars_in_builder: false)
+ end
+
+ it 'returns no variables' do
+ expect(subject.map { |env| env[:key] }).to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/variables/collection_spec.rb b/spec/lib/gitlab/ci/variables/collection_spec.rb
index 7ba98380986..26c560565e0 100644
--- a/spec/lib/gitlab/ci/variables/collection_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection_spec.rb
@@ -358,302 +358,210 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
end
describe '#sort_and_expand_all' do
- context 'when FF :variable_inside_variable is disabled' do
- let_it_be(:project_with_flag_disabled) { create(:project) }
- let_it_be(:project_with_flag_enabled) { create(:project) }
-
- before do
- stub_feature_flags(variable_inside_variable: [project_with_flag_enabled])
- end
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
- context 'table tests' do
- using RSpec::Parameterized::TableSyntax
-
- where do
- {
- "empty array": {
- variables: [],
- keep_undefined: false
- },
- "simple expansions": {
- variables: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result' },
- { key: 'variable3', value: 'key$variable$variable2' }
- ],
- keep_undefined: false
- },
- "complex expansion": {
- variables: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'key${variable}' }
- ],
- keep_undefined: false
- },
- "out-of-order variable reference": {
- variables: [
- { key: 'variable2', value: 'key${variable}' },
- { key: 'variable', value: 'value' }
- ],
- keep_undefined: false
- },
- "complex expansions with raw variable": {
- variables: [
- { key: 'variable3', value: 'key_${variable}_${variable2}' },
- { key: 'variable', value: '$variable2', raw: true },
- { key: 'variable2', value: 'value2' }
- ],
- keep_undefined: false
- },
- "escaped characters in complex expansions are kept intact": {
- variables: [
- { key: 'variable3', value: 'key_${variable}_$${HOME}_%%HOME%%' },
- { key: 'variable', value: '$variable2' },
- { key: 'variable2', value: 'value2' }
- ],
- keep_undefined: false
- },
- "array with cyclic dependency": {
- variables: [
- { key: 'variable', value: '$variable2' },
- { key: 'variable2', value: '$variable3' },
- { key: 'variable3', value: 'key$variable$variable2' }
- ],
- keep_undefined: true
- }
+ where do
+ {
+ "empty array": {
+ variables: [],
+ keep_undefined: false,
+ result: []
+ },
+ "simple expansions": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'key$variable$variable2' },
+ { key: 'variable4', value: 'key$variable$variable3' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'keyvalueresult' },
+ { key: 'variable4', value: 'keyvaluekeyvalueresult' }
+ ]
+ },
+ "complex expansion": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'key${variable}' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'keyvalue' }
+ ]
+ },
+ "unused variables": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result2' },
+ { key: 'variable3', value: 'result3' },
+ { key: 'variable4', value: 'key$variable$variable3' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result2' },
+ { key: 'variable3', value: 'result3' },
+ { key: 'variable4', value: 'keyvalueresult3' }
+ ]
+ },
+ "complex expansions": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'key${variable}${variable2}' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'keyvalueresult' }
+ ]
+ },
+ "escaped characters in complex expansions keeping undefined are kept intact": {
+ variables: [
+ { key: 'variable3', value: 'key_${variable}_$${HOME}_%%HOME%%' },
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: 'value' }
+ ],
+ keep_undefined: true,
+ result: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'value' },
+ { key: 'variable3', value: 'key_value_$${HOME}_%%HOME%%' }
+ ]
+ },
+ "escaped characters in complex expansions discarding undefined are kept intact": {
+ variables: [
+ { key: 'variable2', value: 'key_${variable4}_$${HOME}_%%HOME%%' },
+ { key: 'variable', value: 'value_$${HOME}_%%HOME%%' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable', value: 'value_$${HOME}_%%HOME%%' },
+ { key: 'variable2', value: 'key__$${HOME}_%%HOME%%' }
+ ]
+ },
+ "out-of-order expansion": {
+ variables: [
+ { key: 'variable3', value: 'key$variable2$variable' },
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable2', value: 'result' },
+ { key: 'variable', value: 'value' },
+ { key: 'variable3', value: 'keyresultvalue' }
+ ]
+ },
+ "out-of-order complex expansion": {
+ variables: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'key${variable2}${variable}' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable2', value: 'result' },
+ { key: 'variable3', value: 'keyresultvalue' }
+ ]
+ },
+ "missing variable discarding original": {
+ variables: [
+ { key: 'variable2', value: 'key$variable' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable2', value: 'key' }
+ ]
+ },
+ "missing variable keeping original": {
+ variables: [
+ { key: 'variable2', value: 'key$variable' }
+ ],
+ keep_undefined: true,
+ result: [
+ { key: 'variable2', value: 'key$variable' }
+ ]
+ },
+ "complex expansions with missing variable keeping original": {
+ variables: [
+ { key: 'variable4', value: 'key${variable}${variable2}${variable3}' },
+ { key: 'variable', value: 'value' },
+ { key: 'variable3', value: 'value3' }
+ ],
+ keep_undefined: true,
+ result: [
+ { key: 'variable', value: 'value' },
+ { key: 'variable3', value: 'value3' },
+ { key: 'variable4', value: 'keyvalue${variable2}value3' }
+ ]
+ },
+ "complex expansions with raw variable": {
+ variables: [
+ { key: 'variable3', value: 'key_${variable}_${variable2}' },
+ { key: 'variable', value: '$variable2', raw: true },
+ { key: 'variable2', value: 'value2' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable', value: '$variable2', raw: true },
+ { key: 'variable2', value: 'value2' },
+ { key: 'variable3', value: 'key_$variable2_value2' }
+ ]
+ },
+ "variable value referencing password with special characters": {
+ variables: [
+ { key: 'VAR', value: '$PASSWORD' },
+ { key: 'PASSWORD', value: 'my_password$$_%%_$A' },
+ { key: 'A', value: 'value' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'VAR', value: 'my_password$$_%%_value' },
+ { key: 'PASSWORD', value: 'my_password$$_%%_value' },
+ { key: 'A', value: 'value' }
+ ]
+ },
+ "cyclic dependency causes original array to be returned": {
+ variables: [
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: '$variable3' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ],
+ keep_undefined: false,
+ result: [
+ { key: 'variable', value: '$variable2' },
+ { key: 'variable2', value: '$variable3' },
+ { key: 'variable3', value: 'key$variable$variable2' }
+ ]
}
- end
-
- with_them do
- let(:collection) { Gitlab::Ci::Variables::Collection.new(variables, keep_undefined: keep_undefined) }
-
- subject { collection.sort_and_expand_all(project_with_flag_disabled) }
-
- it 'returns Collection' do
- is_expected.to be_an_instance_of(Gitlab::Ci::Variables::Collection)
- end
-
- it 'does not expand variables' do
- var_hash = variables.pluck(:key, :value).to_h
- expect(subject.to_hash).to eq(var_hash)
- end
- end
+ }
end
- end
- context 'when FF :variable_inside_variable is enabled' do
- let_it_be(:project_with_flag_disabled) { create(:project) }
- let_it_be(:project_with_flag_enabled) { create(:project) }
+ with_them do
+ let(:collection) { Gitlab::Ci::Variables::Collection.new(variables) }
- before do
- stub_feature_flags(variable_inside_variable: [project_with_flag_enabled])
- end
+ subject { collection.sort_and_expand_all(keep_undefined: keep_undefined) }
- context 'table tests' do
- using RSpec::Parameterized::TableSyntax
-
- where do
- {
- "empty array": {
- variables: [],
- keep_undefined: false,
- result: []
- },
- "simple expansions": {
- variables: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result' },
- { key: 'variable3', value: 'key$variable$variable2' },
- { key: 'variable4', value: 'key$variable$variable3' }
- ],
- keep_undefined: false,
- result: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result' },
- { key: 'variable3', value: 'keyvalueresult' },
- { key: 'variable4', value: 'keyvaluekeyvalueresult' }
- ]
- },
- "complex expansion": {
- variables: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'key${variable}' }
- ],
- keep_undefined: false,
- result: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'keyvalue' }
- ]
- },
- "unused variables": {
- variables: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result2' },
- { key: 'variable3', value: 'result3' },
- { key: 'variable4', value: 'key$variable$variable3' }
- ],
- keep_undefined: false,
- result: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result2' },
- { key: 'variable3', value: 'result3' },
- { key: 'variable4', value: 'keyvalueresult3' }
- ]
- },
- "complex expansions": {
- variables: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result' },
- { key: 'variable3', value: 'key${variable}${variable2}' }
- ],
- keep_undefined: false,
- result: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result' },
- { key: 'variable3', value: 'keyvalueresult' }
- ]
- },
- "escaped characters in complex expansions keeping undefined are kept intact": {
- variables: [
- { key: 'variable3', value: 'key_${variable}_$${HOME}_%%HOME%%' },
- { key: 'variable', value: '$variable2' },
- { key: 'variable2', value: 'value' }
- ],
- keep_undefined: true,
- result: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'value' },
- { key: 'variable3', value: 'key_value_$${HOME}_%%HOME%%' }
- ]
- },
- "escaped characters in complex expansions discarding undefined are kept intact": {
- variables: [
- { key: 'variable2', value: 'key_${variable4}_$${HOME}_%%HOME%%' },
- { key: 'variable', value: 'value_$${HOME}_%%HOME%%' }
- ],
- keep_undefined: false,
- result: [
- { key: 'variable', value: 'value_$${HOME}_%%HOME%%' },
- { key: 'variable2', value: 'key__$${HOME}_%%HOME%%' }
- ]
- },
- "out-of-order expansion": {
- variables: [
- { key: 'variable3', value: 'key$variable2$variable' },
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result' }
- ],
- keep_undefined: false,
- result: [
- { key: 'variable2', value: 'result' },
- { key: 'variable', value: 'value' },
- { key: 'variable3', value: 'keyresultvalue' }
- ]
- },
- "out-of-order complex expansion": {
- variables: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result' },
- { key: 'variable3', value: 'key${variable2}${variable}' }
- ],
- keep_undefined: false,
- result: [
- { key: 'variable', value: 'value' },
- { key: 'variable2', value: 'result' },
- { key: 'variable3', value: 'keyresultvalue' }
- ]
- },
- "missing variable discarding original": {
- variables: [
- { key: 'variable2', value: 'key$variable' }
- ],
- keep_undefined: false,
- result: [
- { key: 'variable2', value: 'key' }
- ]
- },
- "missing variable keeping original": {
- variables: [
- { key: 'variable2', value: 'key$variable' }
- ],
- keep_undefined: true,
- result: [
- { key: 'variable2', value: 'key$variable' }
- ]
- },
- "complex expansions with missing variable keeping original": {
- variables: [
- { key: 'variable4', value: 'key${variable}${variable2}${variable3}' },
- { key: 'variable', value: 'value' },
- { key: 'variable3', value: 'value3' }
- ],
- keep_undefined: true,
- result: [
- { key: 'variable', value: 'value' },
- { key: 'variable3', value: 'value3' },
- { key: 'variable4', value: 'keyvalue${variable2}value3' }
- ]
- },
- "complex expansions with raw variable": {
- variables: [
- { key: 'variable3', value: 'key_${variable}_${variable2}' },
- { key: 'variable', value: '$variable2', raw: true },
- { key: 'variable2', value: 'value2' }
- ],
- keep_undefined: false,
- result: [
- { key: 'variable', value: '$variable2', raw: true },
- { key: 'variable2', value: 'value2' },
- { key: 'variable3', value: 'key_$variable2_value2' }
- ]
- },
- "variable value referencing password with special characters": {
- variables: [
- { key: 'VAR', value: '$PASSWORD' },
- { key: 'PASSWORD', value: 'my_password$$_%%_$A' },
- { key: 'A', value: 'value' }
- ],
- keep_undefined: false,
- result: [
- { key: 'VAR', value: 'my_password$$_%%_value' },
- { key: 'PASSWORD', value: 'my_password$$_%%_value' },
- { key: 'A', value: 'value' }
- ]
- },
- "cyclic dependency causes original array to be returned": {
- variables: [
- { key: 'variable', value: '$variable2' },
- { key: 'variable2', value: '$variable3' },
- { key: 'variable3', value: 'key$variable$variable2' }
- ],
- keep_undefined: false,
- result: [
- { key: 'variable', value: '$variable2' },
- { key: 'variable2', value: '$variable3' },
- { key: 'variable3', value: 'key$variable$variable2' }
- ]
- }
- }
+ it 'returns Collection' do
+ is_expected.to be_an_instance_of(Gitlab::Ci::Variables::Collection)
end
- with_them do
- let(:collection) { Gitlab::Ci::Variables::Collection.new(variables) }
-
- subject { collection.sort_and_expand_all(project_with_flag_enabled, keep_undefined: keep_undefined) }
-
- it 'returns Collection' do
- is_expected.to be_an_instance_of(Gitlab::Ci::Variables::Collection)
- end
-
- it 'expands variables' do
- var_hash = result.to_h { |env| [env.fetch(:key), env.fetch(:value)] }
- .with_indifferent_access
- expect(subject.to_hash).to eq(var_hash)
- end
+ it 'expands variables' do
+ var_hash = result.to_h { |env| [env.fetch(:key), env.fetch(:value)] }
+ .with_indifferent_access
+ expect(subject.to_hash).to eq(var_hash)
+ end
- it 'preserves raw attribute' do
- expect(subject.pluck(:key, :raw).to_h).to eq(collection.pluck(:key, :raw).to_h)
- end
+ it 'preserves raw attribute' do
+ expect(subject.pluck(:key, :raw).to_h).to eq(collection.pluck(:key, :raw).to_h)
end
end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 1591c2e6b60..f00a801286d 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -1046,6 +1046,64 @@ module Gitlab
end
end
+ context 'when overriding `extends`' do
+ let(:config) do
+ <<~YAML
+ .base:
+ script: test
+ variables:
+ VAR1: base var 1
+
+ test1:
+ extends: .base
+ variables:
+ VAR1: test1 var 1
+ VAR2: test2 var 2
+
+ test2:
+ extends: .base
+ variables:
+ VAR2: test2 var 2
+
+ test3:
+ extends: .base
+ variables: {}
+
+ test4:
+ extends: .base
+ variables: null
+ YAML
+ end
+
+ it 'correctly extends jobs' do
+ expect(config_processor.builds[0]).to include(
+ name: 'test1',
+ options: { script: ['test'] },
+ job_variables: [{ key: 'VAR1', value: 'test1 var 1', public: true },
+ { key: 'VAR2', value: 'test2 var 2', public: true }]
+ )
+
+ expect(config_processor.builds[1]).to include(
+ name: 'test2',
+ options: { script: ['test'] },
+ job_variables: [{ key: 'VAR1', value: 'base var 1', public: true },
+ { key: 'VAR2', value: 'test2 var 2', public: true }]
+ )
+
+ expect(config_processor.builds[2]).to include(
+ name: 'test3',
+ options: { script: ['test'] },
+ job_variables: [{ key: 'VAR1', value: 'base var 1', public: true }]
+ )
+
+ expect(config_processor.builds[3]).to include(
+ name: 'test4',
+ options: { script: ['test'] },
+ job_variables: []
+ )
+ end
+ end
+
context 'when using recursive `extends`' do
let(:config) do
<<~YAML
diff --git a/spec/lib/gitlab/config_checker/external_database_checker_spec.rb b/spec/lib/gitlab/config_checker/external_database_checker_spec.rb
index 5a4e9001ac9..933b6d6be9e 100644
--- a/spec/lib/gitlab/config_checker/external_database_checker_spec.rb
+++ b/spec/lib/gitlab/config_checker/external_database_checker_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::ConfigChecker::ExternalDatabaseChecker do
context 'when database meets minimum supported version' do
before do
- allow(Gitlab::Database.main).to receive(:postgresql_minimum_supported_version?).and_return(true)
+ allow(ApplicationRecord.database).to receive(:postgresql_minimum_supported_version?).and_return(true)
end
it { is_expected.to be_empty }
@@ -16,7 +16,7 @@ RSpec.describe Gitlab::ConfigChecker::ExternalDatabaseChecker do
context 'when database does not meet minimum supported version' do
before do
- allow(Gitlab::Database.main).to receive(:postgresql_minimum_supported_version?).and_return(false)
+ allow(ApplicationRecord.database).to receive(:postgresql_minimum_supported_version?).and_return(false)
end
let(:notice_deprecated_database) do
@@ -26,7 +26,7 @@ RSpec.describe Gitlab::ConfigChecker::ExternalDatabaseChecker do
'%{pg_version_minimum} is required for this version of GitLab. ' \
'Please upgrade your environment to a supported PostgreSQL version, ' \
'see %{pg_requirements_url} for details.') % {
- pg_version_current: Gitlab::Database.main.version,
+ pg_version_current: ApplicationRecord.database.version,
pg_version_minimum: Gitlab::Database::MINIMUM_POSTGRES_VERSION,
pg_requirements_url: '<a href="https://docs.gitlab.com/ee/install/requirements.html#database">database requirements</a>'
}
diff --git a/spec/lib/gitlab/container_repository/tags/cache_spec.rb b/spec/lib/gitlab/container_repository/tags/cache_spec.rb
new file mode 100644
index 00000000000..f84c1ce173f
--- /dev/null
+++ b/spec/lib/gitlab/container_repository/tags/cache_spec.rb
@@ -0,0 +1,133 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Gitlab::ContainerRepository::Tags::Cache, :clean_gitlab_redis_cache do
+ let_it_be(:dummy_tag_class) { Struct.new(:name, :created_at) }
+ let_it_be(:repository) { create(:container_repository) }
+
+ let(:tags) { create_tags(5) }
+ let(:service) { described_class.new(repository) }
+
+ shared_examples 'not interacting with redis' do
+ it 'does not interact with redis' do
+ expect(::Gitlab::Redis::Cache).not_to receive(:with)
+
+ subject
+ end
+ end
+
+ describe '#populate' do
+ subject { service.populate(tags) }
+
+ context 'with tags' do
+ it 'gets values from redis' do
+ expect(::Gitlab::Redis::Cache).to receive(:with).and_call_original
+
+ expect(subject).to eq(0)
+
+ tags.each { |t| expect(t.created_at).to eq(nil) }
+ end
+
+ context 'with cached values' do
+ let(:cached_tags) { tags.first(2) }
+
+ before do
+ ::Gitlab::Redis::Cache.with do |redis|
+ cached_tags.each do |tag|
+ redis.set(cache_key(tag), rfc3339(10.days.ago))
+ end
+ end
+ end
+
+ it 'gets values from redis' do
+ expect(::Gitlab::Redis::Cache).to receive(:with).and_call_original
+
+ expect(subject).to eq(2)
+
+ cached_tags.each { |t| expect(t.created_at).not_to eq(nil) }
+ (tags - cached_tags).each { |t| expect(t.created_at).to eq(nil) }
+ end
+ end
+ end
+
+ context 'with no tags' do
+ let(:tags) { [] }
+
+ it_behaves_like 'not interacting with redis'
+ end
+ end
+
+ describe '#insert' do
+ let(:max_ttl) { 90.days }
+
+ subject { service.insert(tags, max_ttl) }
+
+ context 'with tags' do
+ let(:tag) { tags.first }
+ let(:ttl) { 90.days - 3.days }
+
+ before do
+ travel_to(Time.zone.local(2021, 9, 2, 12, 0, 0))
+
+ tag.created_at = DateTime.rfc3339(3.days.ago.rfc3339)
+ end
+
+ after do
+ travel_back
+ end
+
+ it 'inserts values in redis' do
+ ::Gitlab::Redis::Cache.with do |redis|
+ expect(redis)
+ .to receive(:set)
+ .with(cache_key(tag), rfc3339(tag.created_at), ex: ttl.to_i)
+ .and_call_original
+ end
+
+ subject
+ end
+
+ context 'with some of them already cached' do
+ let(:tag) { tags.first }
+
+ before do
+ ::Gitlab::Redis::Cache.with do |redis|
+ redis.set(cache_key(tag), rfc3339(10.days.ago))
+ end
+ service.populate(tags)
+ end
+
+ it_behaves_like 'not interacting with redis'
+ end
+ end
+
+ context 'with no tags' do
+ let(:tags) { [] }
+
+ it_behaves_like 'not interacting with redis'
+ end
+
+ context 'with no expires_in' do
+ let(:max_ttl) { nil }
+
+ it_behaves_like 'not interacting with redis'
+ end
+ end
+
+ def create_tags(size)
+ Array.new(size) do |i|
+ dummy_tag_class.new("Tag #{i}", nil)
+ end
+ end
+
+ def cache_key(tag)
+ "container_repository:{#{repository.id}}:tag:#{tag.name}:created_at"
+ end
+
+ def rfc3339(date_time)
+ # DateTime rfc3339 is different ActiveSupport::TimeWithZone rfc3339
+ # The caching will use DateTime rfc3339
+ DateTime.rfc3339(date_time.rfc3339).rfc3339
+ end
+end
diff --git a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
index 3ec332dace5..c0476d38380 100644
--- a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
+++ b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
expect(directives.has_key?('report_uri')).to be_truthy
expect(directives['report_uri']).to be_nil
- expect(directives['child_src']).to eq(directives['frame_src'])
+ expect(directives['child_src']).to eq("#{directives['frame_src']} #{directives['worker_src']}")
end
context 'adds all websocket origins to support Safari' do
@@ -77,13 +77,15 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
context 'when CDN host is defined' do
before do
- stub_config_setting(cdn_host: 'https://example.com')
+ stub_config_setting(cdn_host: 'https://cdn.example.com')
end
it 'adds CDN host to CSP' do
- expect(directives['script_src']).to eq("'strict-dynamic' 'self' 'unsafe-inline' 'unsafe-eval' https://www.google.com/recaptcha/ https://www.recaptcha.net https://apis.google.com https://example.com")
- expect(directives['style_src']).to eq("'self' 'unsafe-inline' https://example.com")
- expect(directives['font_src']).to eq("'self' https://example.com")
+ expect(directives['script_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.script_src + " https://cdn.example.com")
+ expect(directives['style_src']).to eq("'self' 'unsafe-inline' https://cdn.example.com")
+ expect(directives['font_src']).to eq("'self' https://cdn.example.com")
+ expect(directives['worker_src']).to eq('http://localhost/assets/ blob: data: https://cdn.example.com')
+ expect(directives['frame_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.frame_src + " https://cdn.example.com http://localhost/admin/sidekiq http://localhost/admin/sidekiq/ http://localhost/-/speedscope/index.html")
end
end
@@ -99,8 +101,10 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
end
context 'when CUSTOMER_PORTAL_URL is set' do
+ let(:customer_portal_url) { 'https://customers.example.com' }
+
before do
- stub_env('CUSTOMER_PORTAL_URL', 'https://customers.example.com')
+ stub_env('CUSTOMER_PORTAL_URL', customer_portal_url)
end
context 'when in production' do
@@ -109,7 +113,7 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
end
it 'does not add CUSTOMER_PORTAL_URL to CSP' do
- expect(directives['frame_src']).to eq("'self' https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://content.googleapis.com https://content-compute.googleapis.com https://content-cloudbilling.googleapis.com https://content-cloudresourcemanager.googleapis.com")
+ expect(directives['frame_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.frame_src + " http://localhost/admin/sidekiq http://localhost/admin/sidekiq/ http://localhost/-/speedscope/index.html")
end
end
@@ -119,7 +123,36 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
end
it 'adds CUSTOMER_PORTAL_URL to CSP' do
- expect(directives['frame_src']).to eq("'self' https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://content.googleapis.com https://content-compute.googleapis.com https://content-cloudbilling.googleapis.com https://content-cloudresourcemanager.googleapis.com https://customers.example.com")
+ expect(directives['frame_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.frame_src + " http://localhost/rails/letter_opener/ https://customers.example.com http://localhost/admin/sidekiq http://localhost/admin/sidekiq/ http://localhost/-/speedscope/index.html")
+ end
+ end
+ end
+
+ context 'letter_opener applicaiton URL' do
+ let(:gitlab_url) { 'http://gitlab.example.com' }
+ let(:letter_opener_url) { "#{gitlab_url}/rails/letter_opener/" }
+
+ before do
+ stub_config_setting(url: gitlab_url)
+ end
+
+ context 'when in production' do
+ before do
+ allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('production'))
+ end
+
+ it 'does not add letter_opener to CSP' do
+ expect(directives['frame_src']).not_to include(letter_opener_url)
+ end
+ end
+
+ context 'when in development' do
+ before do
+ allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('development'))
+ end
+
+ it 'adds letter_opener to CSP' do
+ expect(directives['frame_src']).to include(letter_opener_url)
end
end
end
diff --git a/spec/lib/gitlab/contributions_calendar_spec.rb b/spec/lib/gitlab/contributions_calendar_spec.rb
index 67b2ea7a1d4..384609c6664 100644
--- a/spec/lib/gitlab/contributions_calendar_spec.rb
+++ b/spec/lib/gitlab/contributions_calendar_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::ContributionsCalendar do
let(:contributor) { create(:user) }
let(:user) { create(:user) }
+ let(:travel_time) { nil }
let(:private_project) do
create(:project, :private) do |project|
@@ -31,7 +32,7 @@ RSpec.describe Gitlab::ContributionsCalendar do
let(:last_year) { today - 1.year }
before do
- travel_to Time.now.utc.end_of_day
+ travel_to travel_time || Time.now.utc.end_of_day
end
after do
@@ -89,7 +90,7 @@ RSpec.describe Gitlab::ContributionsCalendar do
expect(calendar(contributor).activity_dates[today]).to eq(2)
end
- context "when events fall under different dates depending on the time zone" do
+ context "when events fall under different dates depending on the system time zone" do
before do
create_event(public_project, today, 1)
create_event(public_project, today, 4)
@@ -116,6 +117,37 @@ RSpec.describe Gitlab::ContributionsCalendar do
end
end
end
+
+ context "when events fall under different dates depending on the contributor's time zone" do
+ before do
+ create_event(public_project, today, 1)
+ create_event(public_project, today, 4)
+ create_event(public_project, today, 10)
+ create_event(public_project, today, 16)
+ create_event(public_project, today, 23)
+ end
+
+ it "renders correct event counts within the UTC timezone" do
+ Time.use_zone('UTC') do
+ contributor.timezone = 'UTC'
+ expect(calendar.activity_dates).to eq(today => 5)
+ end
+ end
+
+ it "renders correct event counts within the Sydney timezone" do
+ Time.use_zone('UTC') do
+ contributor.timezone = 'Sydney'
+ expect(calendar.activity_dates).to eq(today => 3, tomorrow => 2)
+ end
+ end
+
+ it "renders correct event counts within the US Central timezone" do
+ Time.use_zone('UTC') do
+ contributor.timezone = 'Central Time (US & Canada)'
+ expect(calendar.activity_dates).to eq(yesterday => 2, today => 3)
+ end
+ end
+ end
end
describe '#events_by_date' do
@@ -152,14 +184,38 @@ RSpec.describe Gitlab::ContributionsCalendar do
end
describe '#starting_year' do
- it "is the start of last year" do
- expect(calendar.starting_year).to eq(last_year.year)
+ let(:travel_time) { Time.find_zone('UTC').local(2020, 12, 31, 19, 0, 0) }
+
+ context "when the contributor's timezone is not set" do
+ it "is the start of last year in the system timezone" do
+ expect(calendar.starting_year).to eq(2019)
+ end
+ end
+
+ context "when the contributor's timezone is set to Sydney" do
+ let(:contributor) { create(:user, { timezone: 'Sydney' }) }
+
+ it "is the start of last year in Sydney" do
+ expect(calendar.starting_year).to eq(2020)
+ end
end
end
describe '#starting_month' do
- it "is the start of this month" do
- expect(calendar.starting_month).to eq(today.month)
+ let(:travel_time) { Time.find_zone('UTC').local(2020, 12, 31, 19, 0, 0) }
+
+ context "when the contributor's timezone is not set" do
+ it "is the start of this month in the system timezone" do
+ expect(calendar.starting_month).to eq(12)
+ end
+ end
+
+ context "when the contributor's timezone is set to Sydney" do
+ let(:contributor) { create(:user, { timezone: 'Sydney' }) }
+
+ it "is the start of this month in Sydney" do
+ expect(calendar.starting_month).to eq(1)
+ end
end
end
end
diff --git a/spec/lib/gitlab/database/async_indexes/postgres_async_index_spec.rb b/spec/lib/gitlab/database/async_indexes/postgres_async_index_spec.rb
index 434cba4edde..223730f87c0 100644
--- a/spec/lib/gitlab/database/async_indexes/postgres_async_index_spec.rb
+++ b/spec/lib/gitlab/database/async_indexes/postgres_async_index_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::AsyncIndexes::PostgresAsyncIndex, type: :model do
+ it { is_expected.to be_a Gitlab::Database::SharedModel }
+
describe 'validations' do
let(:identifier_limit) { described_class::MAX_IDENTIFIER_LENGTH }
let(:definition_limit) { described_class::MAX_DEFINITION_LENGTH }
diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
index 779e8e40c97..04c18a98ee6 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
@@ -286,7 +286,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
let(:migration_wrapper) { Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper.new }
let(:migration_helpers) { ActiveRecord::Migration.new }
- let(:table_name) { :_batched_migrations_test_table }
+ let(:table_name) { :_test_batched_migrations_test_table }
let(:column_name) { :some_id }
let(:job_arguments) { [:some_id, :some_id_convert_to_bigint] }
diff --git a/spec/lib/gitlab/database/batch_count_spec.rb b/spec/lib/gitlab/database/batch_count_spec.rb
index da13bc425d1..9831510f014 100644
--- a/spec/lib/gitlab/database/batch_count_spec.rb
+++ b/spec/lib/gitlab/database/batch_count_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Gitlab::Database::BatchCount do
end
before do
- allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(in_transaction)
+ allow(model.connection).to receive(:transaction_open?).and_return(in_transaction)
end
def calculate_batch_size(batch_size)
diff --git a/spec/lib/gitlab/database/connection_spec.rb b/spec/lib/gitlab/database/connection_spec.rb
deleted file mode 100644
index ee1df141cd6..00000000000
--- a/spec/lib/gitlab/database/connection_spec.rb
+++ /dev/null
@@ -1,442 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Database::Connection do
- let(:connection) { described_class.new }
-
- describe '#config' do
- it 'returns a HashWithIndifferentAccess' do
- expect(connection.config).to be_an_instance_of(HashWithIndifferentAccess)
- end
-
- it 'returns a default pool size' do
- expect(connection.config)
- .to include(pool: Gitlab::Database.default_pool_size)
- end
-
- it 'does not cache its results' do
- a = connection.config
- b = connection.config
-
- expect(a).not_to equal(b)
- end
- end
-
- describe '#pool_size' do
- context 'when no explicit size is configured' do
- it 'returns the default pool size' do
- expect(connection).to receive(:config).and_return({ pool: nil })
-
- expect(connection.pool_size).to eq(Gitlab::Database.default_pool_size)
- end
- end
-
- context 'when an explicit pool size is set' do
- it 'returns the pool size' do
- expect(connection).to receive(:config).and_return({ pool: 4 })
-
- expect(connection.pool_size).to eq(4)
- end
- end
- end
-
- describe '#username' do
- context 'when a username is set' do
- it 'returns the username' do
- allow(connection).to receive(:config).and_return(username: 'bob')
-
- expect(connection.username).to eq('bob')
- end
- end
-
- context 'when a username is not set' do
- it 'returns the value of the USER environment variable' do
- allow(connection).to receive(:config).and_return(username: nil)
- allow(ENV).to receive(:[]).with('USER').and_return('bob')
-
- expect(connection.username).to eq('bob')
- end
- end
- end
-
- describe '#database_name' do
- it 'returns the name of the database' do
- allow(connection).to receive(:config).and_return(database: 'test')
-
- expect(connection.database_name).to eq('test')
- end
- end
-
- describe '#adapter_name' do
- it 'returns the database adapter name' do
- allow(connection).to receive(:config).and_return(adapter: 'test')
-
- expect(connection.adapter_name).to eq('test')
- end
- end
-
- describe '#human_adapter_name' do
- context 'when the adapter is PostgreSQL' do
- it 'returns PostgreSQL' do
- allow(connection).to receive(:config).and_return(adapter: 'postgresql')
-
- expect(connection.human_adapter_name).to eq('PostgreSQL')
- end
- end
-
- context 'when the adapter is not PostgreSQL' do
- it 'returns Unknown' do
- allow(connection).to receive(:config).and_return(adapter: 'kittens')
-
- expect(connection.human_adapter_name).to eq('Unknown')
- end
- end
- end
-
- describe '#postgresql?' do
- context 'when using PostgreSQL' do
- it 'returns true' do
- allow(connection).to receive(:adapter_name).and_return('PostgreSQL')
-
- expect(connection.postgresql?).to eq(true)
- end
- end
-
- context 'when not using PostgreSQL' do
- it 'returns false' do
- allow(connection).to receive(:adapter_name).and_return('MySQL')
-
- expect(connection.postgresql?).to eq(false)
- end
- end
- end
-
- describe '#db_config_with_default_pool_size' do
- it 'returns db_config with our default pool size' do
- allow(Gitlab::Database).to receive(:default_pool_size).and_return(9)
-
- expect(connection.db_config_with_default_pool_size.pool).to eq(9)
- end
-
- it 'returns db_config with the correct database name' do
- db_name = connection.scope.connection.pool.db_config.name
-
- expect(connection.db_config_with_default_pool_size.name).to eq(db_name)
- end
- end
-
- describe '#disable_prepared_statements', :reestablished_active_record_base do
- it 'disables prepared statements' do
- connection.scope.establish_connection(
- ::Gitlab::Database.main.config.merge(prepared_statements: true)
- )
-
- expect(connection.scope.connection.prepared_statements).to eq(true)
-
- connection.disable_prepared_statements
-
- expect(connection.scope.connection.prepared_statements).to eq(false)
- end
-
- it 'retains the connection name' do
- connection.disable_prepared_statements
-
- expect(connection.scope.connection_db_config.name).to eq('main')
- end
-
- context 'with dynamic connection pool size' do
- before do
- connection.scope.establish_connection(connection.config.merge(pool: 7))
- end
-
- it 'retains the set pool size' do
- connection.disable_prepared_statements
-
- expect(connection.scope.connection.prepared_statements).to eq(false)
- expect(connection.scope.connection.pool.size).to eq(7)
- end
- end
- end
-
- describe '#db_read_only?' do
- it 'detects a read-only database' do
- allow(connection.scope.connection)
- .to receive(:execute)
- .with('SELECT pg_is_in_recovery()')
- .and_return([{ "pg_is_in_recovery" => "t" }])
-
- expect(connection.db_read_only?).to be_truthy
- end
-
- it 'detects a read-only database' do
- allow(connection.scope.connection)
- .to receive(:execute)
- .with('SELECT pg_is_in_recovery()')
- .and_return([{ "pg_is_in_recovery" => true }])
-
- expect(connection.db_read_only?).to be_truthy
- end
-
- it 'detects a read-write database' do
- allow(connection.scope.connection)
- .to receive(:execute)
- .with('SELECT pg_is_in_recovery()')
- .and_return([{ "pg_is_in_recovery" => "f" }])
-
- expect(connection.db_read_only?).to be_falsey
- end
-
- it 'detects a read-write database' do
- allow(connection.scope.connection)
- .to receive(:execute)
- .with('SELECT pg_is_in_recovery()')
- .and_return([{ "pg_is_in_recovery" => false }])
-
- expect(connection.db_read_only?).to be_falsey
- end
- end
-
- describe '#db_read_write?' do
- it 'detects a read-only database' do
- allow(connection.scope.connection)
- .to receive(:execute)
- .with('SELECT pg_is_in_recovery()')
- .and_return([{ "pg_is_in_recovery" => "t" }])
-
- expect(connection.db_read_write?).to eq(false)
- end
-
- it 'detects a read-only database' do
- allow(connection.scope.connection)
- .to receive(:execute)
- .with('SELECT pg_is_in_recovery()')
- .and_return([{ "pg_is_in_recovery" => true }])
-
- expect(connection.db_read_write?).to eq(false)
- end
-
- it 'detects a read-write database' do
- allow(connection.scope.connection)
- .to receive(:execute)
- .with('SELECT pg_is_in_recovery()')
- .and_return([{ "pg_is_in_recovery" => "f" }])
-
- expect(connection.db_read_write?).to eq(true)
- end
-
- it 'detects a read-write database' do
- allow(connection.scope.connection)
- .to receive(:execute)
- .with('SELECT pg_is_in_recovery()')
- .and_return([{ "pg_is_in_recovery" => false }])
-
- expect(connection.db_read_write?).to eq(true)
- end
- end
-
- describe '#version' do
- around do |example|
- connection.instance_variable_set(:@version, nil)
- example.run
- connection.instance_variable_set(:@version, nil)
- end
-
- context "on postgresql" do
- it "extracts the version number" do
- allow(connection)
- .to receive(:database_version)
- .and_return("PostgreSQL 9.4.4 on x86_64-apple-darwin14.3.0")
-
- expect(connection.version).to eq '9.4.4'
- end
- end
-
- it 'memoizes the result' do
- count = ActiveRecord::QueryRecorder
- .new { 2.times { connection.version } }
- .count
-
- expect(count).to eq(1)
- end
- end
-
- describe '#postgresql_minimum_supported_version?' do
- it 'returns false when using PostgreSQL 10' do
- allow(connection).to receive(:version).and_return('10')
-
- expect(connection.postgresql_minimum_supported_version?).to eq(false)
- end
-
- it 'returns false when using PostgreSQL 11' do
- allow(connection).to receive(:version).and_return('11')
-
- expect(connection.postgresql_minimum_supported_version?).to eq(false)
- end
-
- it 'returns true when using PostgreSQL 12' do
- allow(connection).to receive(:version).and_return('12')
-
- expect(connection.postgresql_minimum_supported_version?).to eq(true)
- end
- end
-
- describe '#bulk_insert' do
- before do
- allow(connection).to receive(:connection).and_return(dummy_connection)
- allow(dummy_connection).to receive(:quote_column_name, &:itself)
- allow(dummy_connection).to receive(:quote, &:itself)
- allow(dummy_connection).to receive(:execute)
- end
-
- let(:dummy_connection) { double(:connection) }
-
- let(:rows) do
- [
- { a: 1, b: 2, c: 3 },
- { c: 6, a: 4, b: 5 }
- ]
- end
-
- it 'does nothing with empty rows' do
- expect(dummy_connection).not_to receive(:execute)
-
- connection.bulk_insert('test', [])
- end
-
- it 'uses the ordering from the first row' do
- expect(dummy_connection).to receive(:execute) do |sql|
- expect(sql).to include('(1, 2, 3)')
- expect(sql).to include('(4, 5, 6)')
- end
-
- connection.bulk_insert('test', rows)
- end
-
- it 'quotes column names' do
- expect(dummy_connection).to receive(:quote_column_name).with(:a)
- expect(dummy_connection).to receive(:quote_column_name).with(:b)
- expect(dummy_connection).to receive(:quote_column_name).with(:c)
-
- connection.bulk_insert('test', rows)
- end
-
- it 'quotes values' do
- 1.upto(6) do |i|
- expect(dummy_connection).to receive(:quote).with(i)
- end
-
- connection.bulk_insert('test', rows)
- end
-
- it 'does not quote values of a column in the disable_quote option' do
- [1, 2, 4, 5].each do |i|
- expect(dummy_connection).to receive(:quote).with(i)
- end
-
- connection.bulk_insert('test', rows, disable_quote: :c)
- end
-
- it 'does not quote values of columns in the disable_quote option' do
- [2, 5].each do |i|
- expect(dummy_connection).to receive(:quote).with(i)
- end
-
- connection.bulk_insert('test', rows, disable_quote: [:a, :c])
- end
-
- it 'handles non-UTF-8 data' do
- expect { connection.bulk_insert('test', [{ a: "\255" }]) }.not_to raise_error
- end
-
- context 'when using PostgreSQL' do
- it 'allows the returning of the IDs of the inserted rows' do
- result = double(:result, values: [['10']])
-
- expect(dummy_connection)
- .to receive(:execute)
- .with(/RETURNING id/)
- .and_return(result)
-
- ids = connection
- .bulk_insert('test', [{ number: 10 }], return_ids: true)
-
- expect(ids).to eq([10])
- end
-
- it 'allows setting the upsert to do nothing' do
- expect(dummy_connection)
- .to receive(:execute)
- .with(/ON CONFLICT DO NOTHING/)
-
- connection
- .bulk_insert('test', [{ number: 10 }], on_conflict: :do_nothing)
- end
- end
- end
-
- describe '#cached_column_exists?' do
- it 'only retrieves the data from the schema cache' do
- queries = ActiveRecord::QueryRecorder.new do
- 2.times do
- expect(connection.cached_column_exists?(:projects, :id)).to be_truthy
- expect(connection.cached_column_exists?(:projects, :bogus_column)).to be_falsey
- end
- end
-
- expect(queries.count).to eq(0)
- end
- end
-
- describe '#cached_table_exists?' do
- it 'only retrieves the data from the schema cache' do
- queries = ActiveRecord::QueryRecorder.new do
- 2.times do
- expect(connection.cached_table_exists?(:projects)).to be_truthy
- expect(connection.cached_table_exists?(:bogus_table_name)).to be_falsey
- end
- end
-
- expect(queries.count).to eq(0)
- end
-
- it 'returns false when database does not exist' do
- expect(connection.scope).to receive(:connection) do
- raise ActiveRecord::NoDatabaseError, 'broken'
- end
-
- expect(connection.cached_table_exists?(:projects)).to be(false)
- end
- end
-
- describe '#exists?' do
- it 'returns true if the database exists' do
- expect(connection.exists?).to be(true)
- end
-
- it "returns false if the database doesn't exist" do
- expect(connection.scope.connection.schema_cache)
- .to receive(:database_version)
- .and_raise(ActiveRecord::NoDatabaseError)
-
- expect(connection.exists?).to be(false)
- end
- end
-
- describe '#system_id' do
- it 'returns the PostgreSQL system identifier' do
- expect(connection.system_id).to be_an_instance_of(Integer)
- end
- end
-
- describe '#get_write_location' do
- it 'returns a string' do
- expect(connection.get_write_location(connection.scope.connection))
- .to be_a(String)
- end
-
- it 'returns nil if there are no results' do
- expect(connection.get_write_location(double(select_all: []))).to be_nil
- end
- end
-end
diff --git a/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb b/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
index cdcc862c376..9d49db1f018 100644
--- a/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
+++ b/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
@@ -38,7 +38,8 @@ RSpec.describe Gitlab::Database::Count::ReltuplesCountStrategy do
it 'returns nil counts for inherited tables' do
models.each { |model| expect(model).not_to receive(:count) }
- expect(subject).to eq({ Namespace => 3 })
+ # 3 Namespaces as parents for each Project and 3 ProjectNamespaces(for each Project)
+ expect(subject).to eq({ Namespace => 6 })
end
end
diff --git a/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb b/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb
index c2028f8c238..2f261aebf02 100644
--- a/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb
+++ b/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb
@@ -47,7 +47,8 @@ RSpec.describe Gitlab::Database::Count::TablesampleCountStrategy do
result = subject
expect(result[Project]).to eq(3)
expect(result[Group]).to eq(1)
- expect(result[Namespace]).to eq(4)
+ # 1-Group, 3 namespaces for each project and 3 project namespaces for each project
+ expect(result[Namespace]).to eq(7)
end
end
diff --git a/spec/lib/gitlab/database/each_database_spec.rb b/spec/lib/gitlab/database/each_database_spec.rb
new file mode 100644
index 00000000000..9327fc4ff78
--- /dev/null
+++ b/spec/lib/gitlab/database/each_database_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::EachDatabase do
+ describe '.each_database_connection' do
+ let(:expected_connections) do
+ Gitlab::Database.database_base_models.map { |name, model| [model.connection, name] }
+ end
+
+ it 'yields each connection after connecting SharedModel' do
+ expected_connections.each do |connection, _|
+ expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(connection).and_yield
+ end
+
+ yielded_connections = []
+
+ described_class.each_database_connection do |connection, name|
+ yielded_connections << [connection, name]
+ end
+
+ expect(yielded_connections).to match_array(expected_connections)
+ end
+ end
+
+ describe '.each_model_connection' do
+ let(:model1) { double(connection: double, table_name: 'table1') }
+ let(:model2) { double(connection: double, table_name: 'table2') }
+
+ before do
+ allow(model1.connection).to receive_message_chain('pool.db_config.name').and_return('name1')
+ allow(model2.connection).to receive_message_chain('pool.db_config.name').and_return('name2')
+ end
+
+ it 'yields each model after connecting SharedModel' do
+ expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(model1.connection).and_yield
+ expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(model2.connection).and_yield
+
+ yielded_models = []
+
+ described_class.each_model_connection([model1, model2]) do |model, name|
+ yielded_models << [model, name]
+ end
+
+ expect(yielded_models).to match_array([[model1, 'name1'], [model2, 'name2']])
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/gitlab_schema_spec.rb b/spec/lib/gitlab/database/gitlab_schema_spec.rb
new file mode 100644
index 00000000000..255efc99ff6
--- /dev/null
+++ b/spec/lib/gitlab/database/gitlab_schema_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::GitlabSchema do
+ describe '.tables_to_schema' do
+ subject { described_class.tables_to_schema }
+
+ it 'all tables have assigned a known gitlab_schema' do
+ is_expected.to all(
+ match([be_a(String), be_in([:gitlab_shared, :gitlab_main, :gitlab_ci])])
+ )
+ end
+
+ # This being run across different databases indirectly also tests
+ # a general consistency of structure across databases
+ Gitlab::Database.database_base_models.each do |db_config_name, db_class|
+ let(:db_data_sources) { db_class.connection.data_sources }
+
+ context "for #{db_config_name} using #{db_class}" do
+ it 'new data sources are added' do
+ missing_tables = db_data_sources.to_set - subject.keys
+
+ expect(missing_tables).to be_empty, \
+ "Missing table(s) #{missing_tables.to_a} not found in #{described_class}.tables_to_schema. " \
+ "Any new tables must be added to lib/gitlab/database/gitlab_schemas.yml."
+ end
+
+ it 'non-existing data sources are removed' do
+ extra_tables = subject.keys.to_set - db_data_sources
+
+ expect(extra_tables).to be_empty, \
+ "Extra table(s) #{extra_tables.to_a} found in #{described_class}.tables_to_schema. " \
+ "Any removed or renamed tables must be removed from lib/gitlab/database/gitlab_schemas.yml."
+ end
+ end
+ end
+ end
+
+ describe '.table_schema' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:name, :classification) do
+ 'ci_builds' | :gitlab_ci
+ 'my_schema.ci_builds' | :gitlab_ci
+ 'information_schema.columns' | :gitlab_shared
+ 'audit_events_part_5fc467ac26' | :gitlab_main
+ '_test_my_table' | :gitlab_shared
+ 'pg_attribute' | :gitlab_shared
+ 'my_other_table' | :undefined_my_other_table
+ end
+
+ with_them do
+ subject { described_class.table_schema(name) }
+
+ it { is_expected.to eq(classification) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/configuration_spec.rb b/spec/lib/gitlab/database/load_balancing/configuration_spec.rb
index 3e5249a3dea..eef248afdf2 100644
--- a/spec/lib/gitlab/database/load_balancing/configuration_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/configuration_spec.rb
@@ -3,17 +3,12 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::LoadBalancing::Configuration do
- let(:model) do
- config = ActiveRecord::DatabaseConfigurations::HashConfig
- .new('main', 'test', configuration_hash)
-
- double(:model, connection_db_config: config)
- end
+ let(:configuration_hash) { {} }
+ let(:db_config) { ActiveRecord::DatabaseConfigurations::HashConfig.new('test', 'ci', configuration_hash) }
+ let(:model) { double(:model, connection_db_config: db_config) }
describe '.for_model' do
context 'when load balancing is not configured' do
- let(:configuration_hash) { {} }
-
it 'uses the default settings' do
config = described_class.for_model(model)
@@ -105,6 +100,14 @@ RSpec.describe Gitlab::Database::LoadBalancing::Configuration do
expect(config.pool_size).to eq(4)
end
end
+
+ it 'calls reuse_primary_connection!' do
+ expect_next_instance_of(described_class) do |subject|
+ expect(subject).to receive(:reuse_primary_connection!).and_call_original
+ end
+
+ described_class.for_model(model)
+ end
end
describe '#load_balancing_enabled?' do
@@ -180,4 +183,60 @@ RSpec.describe Gitlab::Database::LoadBalancing::Configuration do
end
end
end
+
+ describe '#db_config_name' do
+ let(:config) { described_class.new(model) }
+
+ subject { config.db_config_name }
+
+ it 'returns connection name as symbol' do
+ is_expected.to eq(:ci)
+ end
+ end
+
+ describe '#replica_db_config' do
+ let(:model) { double(:model, connection_db_config: db_config, connection_specification_name: 'Ci::ApplicationRecord') }
+ let(:config) { described_class.for_model(model) }
+
+ it 'returns exactly db_config' do
+ expect(config.replica_db_config).to eq(db_config)
+ end
+
+ context 'when GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci=main' do
+ it 'does not change replica_db_config' do
+ stub_env('GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci', 'main')
+
+ expect(config.replica_db_config).to eq(db_config)
+ end
+ end
+ end
+
+ describe 'reuse_primary_connection!' do
+ let(:model) { double(:model, connection_db_config: db_config, connection_specification_name: 'Ci::ApplicationRecord') }
+ let(:config) { described_class.for_model(model) }
+
+ context 'when GITLAB_LOAD_BALANCING_REUSE_PRIMARY_* not configured' do
+ it 'the primary connection uses default specification' do
+ stub_env('GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci', nil)
+
+ expect(config.primary_connection_specification_name).to eq('Ci::ApplicationRecord')
+ end
+ end
+
+ context 'when GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci=main' do
+ it 'the primary connection uses main connection' do
+ stub_env('GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci', 'main')
+
+ expect(config.primary_connection_specification_name).to eq('ActiveRecord::Base')
+ end
+ end
+
+ context 'when GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci=unknown' do
+ it 'raises exception' do
+ stub_env('GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci', 'unknown')
+
+ expect { config.reuse_primary_connection! }.to raise_error /Invalid value for/
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb b/spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb
index ba2f9485066..ee2718171c0 100644
--- a/spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb
@@ -3,12 +3,9 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
- let(:proxy) do
- config = Gitlab::Database::LoadBalancing::Configuration
- .new(ActiveRecord::Base)
-
- described_class.new(Gitlab::Database::LoadBalancing::LoadBalancer.new(config))
- end
+ let(:config) { Gitlab::Database::LoadBalancing::Configuration.new(ActiveRecord::Base) }
+ let(:load_balancer) { Gitlab::Database::LoadBalancing::LoadBalancer.new(config) }
+ let(:proxy) { described_class.new(load_balancer) }
describe '#select' do
it 'performs a read' do
@@ -85,7 +82,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
describe '.insert_all!' do
before do
ActiveRecord::Schema.define do
- create_table :connection_proxy_bulk_insert, force: true do |t|
+ create_table :_test_connection_proxy_bulk_insert, force: true do |t|
t.string :name, null: true
end
end
@@ -93,13 +90,13 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
after do
ActiveRecord::Schema.define do
- drop_table :connection_proxy_bulk_insert, force: true
+ drop_table :_test_connection_proxy_bulk_insert, force: true
end
end
let(:model_class) do
Class.new(ApplicationRecord) do
- self.table_name = "connection_proxy_bulk_insert"
+ self.table_name = "_test_connection_proxy_bulk_insert"
end
end
@@ -143,9 +140,9 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
context 'with a read query' do
it 'runs the transaction and any nested queries on the replica' do
- expect(proxy.load_balancer).to receive(:read)
+ expect(load_balancer).to receive(:read)
.twice.and_yield(replica)
- expect(proxy.load_balancer).not_to receive(:read_write)
+ expect(load_balancer).not_to receive(:read_write)
expect(session).not_to receive(:write!)
proxy.transaction { proxy.select('true') }
@@ -154,8 +151,8 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
context 'with a write query' do
it 'raises an exception' do
- allow(proxy.load_balancer).to receive(:read).and_yield(replica)
- allow(proxy.load_balancer).to receive(:read_write).and_yield(replica)
+ allow(load_balancer).to receive(:read).and_yield(replica)
+ allow(load_balancer).to receive(:read_write).and_yield(replica)
expect do
proxy.transaction { proxy.insert('something') }
@@ -178,9 +175,9 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
context 'with a read query' do
it 'runs the transaction and any nested queries on the primary and stick to it' do
- expect(proxy.load_balancer).to receive(:read_write)
+ expect(load_balancer).to receive(:read_write)
.twice.and_yield(primary)
- expect(proxy.load_balancer).not_to receive(:read)
+ expect(load_balancer).not_to receive(:read)
expect(session).to receive(:write!)
proxy.transaction { proxy.select('true') }
@@ -189,9 +186,9 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
context 'with a write query' do
it 'runs the transaction and any nested queries on the primary and stick to it' do
- expect(proxy.load_balancer).to receive(:read_write)
+ expect(load_balancer).to receive(:read_write)
.twice.and_yield(primary)
- expect(proxy.load_balancer).not_to receive(:read)
+ expect(load_balancer).not_to receive(:read)
expect(session).to receive(:write!).twice
proxy.transaction { proxy.insert('something') }
@@ -209,7 +206,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
end
it 'properly forwards keyword arguments' do
- allow(proxy.load_balancer).to receive(:read_write)
+ allow(load_balancer).to receive(:read_write)
expect(proxy).to receive(:write_using_load_balancer).and_call_original
@@ -234,7 +231,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
end
it 'properly forwards keyword arguments' do
- allow(proxy.load_balancer).to receive(:read)
+ allow(load_balancer).to receive(:read)
expect(proxy).to receive(:read_using_load_balancer).and_call_original
@@ -259,7 +256,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
allow(session).to receive(:use_replicas_for_read_queries?).and_return(false)
expect(connection).to receive(:foo).with('foo')
- expect(proxy.load_balancer).to receive(:read).and_yield(connection)
+ expect(load_balancer).to receive(:read).and_yield(connection)
proxy.read_using_load_balancer(:foo, 'foo')
end
@@ -271,7 +268,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
allow(session).to receive(:use_replicas_for_read_queries?).and_return(true)
expect(connection).to receive(:foo).with('foo')
- expect(proxy.load_balancer).to receive(:read).and_yield(connection)
+ expect(load_balancer).to receive(:read).and_yield(connection)
proxy.read_using_load_balancer(:foo, 'foo')
end
@@ -283,7 +280,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
allow(session).to receive(:use_replicas_for_read_queries?).and_return(true)
expect(connection).to receive(:foo).with('foo')
- expect(proxy.load_balancer).to receive(:read).and_yield(connection)
+ expect(load_balancer).to receive(:read).and_yield(connection)
proxy.read_using_load_balancer(:foo, 'foo')
end
@@ -296,7 +293,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
expect(connection).to receive(:foo).with('foo')
- expect(proxy.load_balancer).to receive(:read_write)
+ expect(load_balancer).to receive(:read_write)
.and_yield(connection)
proxy.read_using_load_balancer(:foo, 'foo')
@@ -314,7 +311,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
end
it 'uses but does not stick to the primary' do
- expect(proxy.load_balancer).to receive(:read_write).and_yield(connection)
+ expect(load_balancer).to receive(:read_write).and_yield(connection)
expect(connection).to receive(:foo).with('foo')
expect(session).not_to receive(:write!)
diff --git a/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb b/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
index f824d4cefdf..37b83729125 100644
--- a/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
@@ -4,10 +4,11 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
let(:conflict_error) { Class.new(RuntimeError) }
- let(:db_host) { ActiveRecord::Base.connection_pool.db_config.host }
+ let(:model) { ActiveRecord::Base }
+ let(:db_host) { model.connection_pool.db_config.host }
let(:config) do
Gitlab::Database::LoadBalancing::Configuration
- .new(ActiveRecord::Base, [db_host, db_host])
+ .new(model, [db_host, db_host])
end
let(:lb) { described_class.new(config) }
@@ -88,6 +89,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
host = double(:host)
allow(lb).to receive(:host).and_return(host)
+ allow(Rails.application.executor).to receive(:active?).and_return(true)
allow(host).to receive(:query_cache_enabled).and_return(false)
allow(host).to receive(:connection).and_return(connection)
@@ -96,6 +98,20 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
lb.read { 10 }
end
+ it 'does not enable query cache when outside Rails executor context' do
+ connection = double(:connection)
+ host = double(:host)
+
+ allow(lb).to receive(:host).and_return(host)
+ allow(Rails.application.executor).to receive(:active?).and_return(false)
+ allow(host).to receive(:query_cache_enabled).and_return(false)
+ allow(host).to receive(:connection).and_return(connection)
+
+ expect(host).not_to receive(:enable_query_cache!)
+
+ lb.read { 10 }
+ end
+
it 'marks hosts that are offline' do
allow(lb).to receive(:connection_error?).and_return(true)
@@ -216,7 +232,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
it 'does not create conflicts with other load balancers when caching hosts' do
ci_config = Gitlab::Database::LoadBalancing::Configuration
- .new(Ci::CiDatabaseRecord, [db_host, db_host])
+ .new(Ci::ApplicationRecord, [db_host, db_host])
lb1 = described_class.new(config)
lb2 = described_class.new(ci_config)
@@ -459,4 +475,84 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
lb.disconnect!(timeout: 30)
end
end
+
+ describe '#get_write_location' do
+ it 'returns a string' do
+ expect(lb.send(:get_write_location, lb.pool.connection))
+ .to be_a(String)
+ end
+
+ it 'returns nil if there are no results' do
+ expect(lb.send(:get_write_location, double(select_all: []))).to be_nil
+ end
+ end
+
+ describe 'primary connection re-use', :reestablished_active_record_base do
+ let(:model) { Ci::ApplicationRecord }
+
+ around do |example|
+ if Gitlab::Database.has_config?(:ci)
+ example.run
+ else
+ # fake additional Database
+ model.establish_connection(
+ ActiveRecord::DatabaseConfigurations::HashConfig.new(Rails.env, 'ci', ActiveRecord::Base.connection_db_config.configuration_hash)
+ )
+
+ example.run
+
+ # Cleanup connection_specification_name for Ci::ApplicationRecord
+ model.remove_connection
+ end
+ end
+
+ describe '#read' do
+ it 'returns ci replica connection' do
+ expect { |b| lb.read(&b) }.to yield_with_args do |args|
+ expect(args.pool.db_config.name).to eq('ci_replica')
+ end
+ end
+
+ context 'when GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci=main' do
+ it 'returns ci replica connection' do
+ stub_env('GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci', 'main')
+
+ expect { |b| lb.read(&b) }.to yield_with_args do |args|
+ expect(args.pool.db_config.name).to eq('ci_replica')
+ end
+ end
+ end
+ end
+
+ describe '#read_write' do
+ it 'returns Ci::ApplicationRecord connection' do
+ expect { |b| lb.read_write(&b) }.to yield_with_args do |args|
+ expect(args.pool.db_config.name).to eq('ci')
+ end
+ end
+
+ context 'when GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci=main' do
+ it 'returns ActiveRecord::Base connection' do
+ stub_env('GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci', 'main')
+
+ expect { |b| lb.read_write(&b) }.to yield_with_args do |args|
+ expect(args.pool.db_config.name).to eq('main')
+ end
+ end
+ end
+ end
+ end
+
+ describe '#wal_diff' do
+ it 'returns the diff between two write locations' do
+ loc1 = lb.send(:get_write_location, lb.pool.connection)
+
+ create(:user) # This ensures we get a new WAL location
+
+ loc2 = lb.send(:get_write_location, lb.pool.connection)
+ diff = lb.wal_diff(loc2, loc1)
+
+ expect(diff).to be_positive
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/load_balancing/primary_host_spec.rb b/spec/lib/gitlab/database/load_balancing/primary_host_spec.rb
index 45d81808971..02c9499bedb 100644
--- a/spec/lib/gitlab/database/load_balancing/primary_host_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/primary_host_spec.rb
@@ -51,7 +51,11 @@ RSpec.describe Gitlab::Database::LoadBalancing::PrimaryHost do
end
describe '#offline!' do
- it 'does nothing' do
+ it 'logs the event but does nothing else' do
+ expect(Gitlab::Database::LoadBalancing::Logger).to receive(:warn)
+ .with(hash_including(event: :host_offline))
+ .and_call_original
+
expect(host.offline!).to be_nil
end
end
diff --git a/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb b/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb
index af7e2a4b167..b768d4ecea3 100644
--- a/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb
@@ -6,12 +6,12 @@ RSpec.describe Gitlab::Database::LoadBalancing::RackMiddleware, :redis do
let(:app) { double(:app) }
let(:middleware) { described_class.new(app) }
let(:warden_user) { double(:warden, user: double(:user, id: 42)) }
- let(:single_sticking_object) { Set.new([[ActiveRecord::Base, :user, 42]]) }
+ let(:single_sticking_object) { Set.new([[ActiveRecord::Base.sticking, :user, 42]]) }
let(:multiple_sticking_objects) do
Set.new([
- [ActiveRecord::Base, :user, 42],
- [ActiveRecord::Base, :runner, '123456789'],
- [ActiveRecord::Base, :runner, '1234']
+ [ActiveRecord::Base.sticking, :user, 42],
+ [ActiveRecord::Base.sticking, :runner, '123456789'],
+ [ActiveRecord::Base.sticking, :runner, '1234']
])
end
@@ -162,7 +162,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::RackMiddleware, :redis do
it 'returns the warden user if present' do
env = { 'warden' => warden_user }
ids = Gitlab::Database::LoadBalancing.base_models.map do |model|
- [model, :user, 42]
+ [model.sticking, :user, 42]
end
expect(middleware.sticking_namespaces(env)).to eq(ids)
@@ -181,9 +181,9 @@ RSpec.describe Gitlab::Database::LoadBalancing::RackMiddleware, :redis do
env = { described_class::STICK_OBJECT => multiple_sticking_objects }
expect(middleware.sticking_namespaces(env)).to eq([
- [ActiveRecord::Base, :user, 42],
- [ActiveRecord::Base, :runner, '123456789'],
- [ActiveRecord::Base, :runner, '1234']
+ [ActiveRecord::Base.sticking, :user, 42],
+ [ActiveRecord::Base.sticking, :runner, '123456789'],
+ [ActiveRecord::Base.sticking, :runner, '1234']
])
end
end
diff --git a/spec/lib/gitlab/database/load_balancing/setup_spec.rb b/spec/lib/gitlab/database/load_balancing/setup_spec.rb
index 01646bc76ef..953d83d3b48 100644
--- a/spec/lib/gitlab/database/load_balancing/setup_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/setup_spec.rb
@@ -7,19 +7,20 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
it 'sets up the load balancer' do
setup = described_class.new(ActiveRecord::Base)
- expect(setup).to receive(:disable_prepared_statements)
- expect(setup).to receive(:setup_load_balancer)
+ expect(setup).to receive(:configure_connection)
+ expect(setup).to receive(:setup_connection_proxy)
expect(setup).to receive(:setup_service_discovery)
+ expect(setup).to receive(:setup_feature_flag_to_model_load_balancing)
setup.setup
end
end
- describe '#disable_prepared_statements' do
- it 'disables prepared statements and reconnects to the database' do
+ describe '#configure_connection' do
+ it 'configures pool, prepared statements and reconnects to the database' do
config = double(
:config,
- configuration_hash: { host: 'localhost' },
+ configuration_hash: { host: 'localhost', pool: 2, prepared_statements: true },
env_name: 'test',
name: 'main'
)
@@ -27,7 +28,11 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
expect(ActiveRecord::DatabaseConfigurations::HashConfig)
.to receive(:new)
- .with('test', 'main', { host: 'localhost', prepared_statements: false })
+ .with('test', 'main', {
+ host: 'localhost',
+ prepared_statements: false,
+ pool: Gitlab::Database.default_pool_size
+ })
.and_call_original
# HashConfig doesn't implement its own #==, so we can't directly compare
@@ -36,11 +41,11 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
.to receive(:establish_connection)
.with(an_instance_of(ActiveRecord::DatabaseConfigurations::HashConfig))
- described_class.new(model).disable_prepared_statements
+ described_class.new(model).configure_connection
end
end
- describe '#setup_load_balancer' do
+ describe '#setup_connection_proxy' do
it 'sets up the load balancer' do
model = Class.new(ActiveRecord::Base)
setup = described_class.new(model)
@@ -54,9 +59,9 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
.with(setup.configuration)
.and_return(lb)
- setup.setup_load_balancer
+ setup.setup_connection_proxy
- expect(model.connection.load_balancer).to eq(lb)
+ expect(model.load_balancer).to eq(lb)
expect(model.sticking)
.to be_an_instance_of(Gitlab::Database::LoadBalancing::Sticking)
end
@@ -77,7 +82,6 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
model = ActiveRecord::Base
setup = described_class.new(model)
sv = instance_spy(Gitlab::Database::LoadBalancing::ServiceDiscovery)
- lb = model.connection.load_balancer
allow(setup.configuration)
.to receive(:service_discovery_enabled?)
@@ -85,7 +89,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
allow(Gitlab::Database::LoadBalancing::ServiceDiscovery)
.to receive(:new)
- .with(lb, setup.configuration.service_discovery)
+ .with(setup.load_balancer, setup.configuration.service_discovery)
.and_return(sv)
expect(sv).to receive(:perform_service_discovery)
@@ -98,7 +102,6 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
model = ActiveRecord::Base
setup = described_class.new(model, start_service_discovery: true)
sv = instance_spy(Gitlab::Database::LoadBalancing::ServiceDiscovery)
- lb = model.connection.load_balancer
allow(setup.configuration)
.to receive(:service_discovery_enabled?)
@@ -106,7 +109,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
allow(Gitlab::Database::LoadBalancing::ServiceDiscovery)
.to receive(:new)
- .with(lb, setup.configuration.service_discovery)
+ .with(setup.load_balancer, setup.configuration.service_discovery)
.and_return(sv)
expect(sv).to receive(:perform_service_discovery)
@@ -116,4 +119,181 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
end
end
end
+
+ describe '#setup_feature_flag_to_model_load_balancing', :reestablished_active_record_base do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "with model LB enabled it picks a dedicated CI connection" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: 'true',
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
+ request_store_active: false,
+ ff_use_model_load_balancing: nil,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'ci_replica', write: 'ci' }
+ }
+ },
+ "with model LB enabled and re-use of primary connection it uses CI connection for reads" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: 'true',
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: 'main',
+ request_store_active: false,
+ ff_use_model_load_balancing: nil,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'ci_replica', write: 'main' }
+ }
+ },
+ "with model LB disabled it fallbacks to use main" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: 'false',
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
+ request_store_active: false,
+ ff_use_model_load_balancing: nil,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'main_replica', write: 'main' }
+ }
+ },
+ "with model LB disabled, but re-use configured it fallbacks to use main" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: 'false',
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: 'main',
+ request_store_active: false,
+ ff_use_model_load_balancing: nil,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'main_replica', write: 'main' }
+ }
+ },
+ "with FF disabled without RequestStore it uses main" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
+ request_store_active: false,
+ ff_use_model_load_balancing: false,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'main_replica', write: 'main' }
+ }
+ },
+ "with FF enabled without RequestStore sticking of FF does not work, so it fallbacks to use main" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
+ request_store_active: false,
+ ff_use_model_load_balancing: true,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'main_replica', write: 'main' }
+ }
+ },
+ "with FF disabled with RequestStore it uses main" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
+ request_store_active: true,
+ ff_use_model_load_balancing: false,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'main_replica', write: 'main' }
+ }
+ },
+ "with FF enabled with RequestStore it sticks FF and uses CI connection" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
+ request_store_active: true,
+ ff_use_model_load_balancing: true,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'ci_replica', write: 'ci' }
+ }
+ },
+ "with re-use and FF enabled with RequestStore it sticks FF and uses CI connection for reads" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: 'main',
+ request_store_active: true,
+ ff_use_model_load_balancing: true,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'ci_replica', write: 'main' }
+ }
+ }
+ }
+ end
+
+ with_them do
+ let(:ci_class) do
+ Class.new(ActiveRecord::Base) do
+ def self.name
+ 'Ci::ApplicationRecordTemporary'
+ end
+
+ establish_connection ActiveRecord::DatabaseConfigurations::HashConfig.new(
+ Rails.env,
+ 'ci',
+ ActiveRecord::Base.connection_db_config.configuration_hash
+ )
+ end
+ end
+
+ let(:models) do
+ {
+ main: ActiveRecord::Base,
+ ci: ci_class
+ }
+ end
+
+ around do |example|
+ if request_store_active
+ Gitlab::WithRequestStore.with_request_store do
+ RequestStore.clear!
+
+ example.run
+ end
+ else
+ example.run
+ end
+ end
+
+ before do
+ # Rewrite `class_attribute` to use rspec mocking and prevent modifying the objects
+ allow_next_instance_of(described_class) do |setup|
+ allow(setup).to receive(:configure_connection)
+
+ allow(setup).to receive(:setup_class_attribute) do |attribute, value|
+ allow(setup.model).to receive(attribute) { value }
+ end
+ end
+
+ stub_env('GITLAB_USE_MODEL_LOAD_BALANCING', env_GITLAB_USE_MODEL_LOAD_BALANCING)
+ stub_env('GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci', env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci)
+ stub_feature_flags(use_model_load_balancing: ff_use_model_load_balancing)
+
+ # Make load balancer to force init with a dedicated replicas connections
+ models.each do |_, model|
+ described_class.new(model).tap do |subject|
+ subject.configuration.hosts = [subject.configuration.replica_db_config.host]
+ subject.setup
+ end
+ end
+ end
+
+ it 'results match expectations' do
+ result = models.transform_values do |model|
+ load_balancer = model.connection.instance_variable_get(:@load_balancer)
+
+ {
+ read: load_balancer.read { |connection| connection.pool.db_config.name },
+ write: load_balancer.read_write { |connection| connection.pool.db_config.name }
+ }
+ end
+
+ expect(result).to eq(expectations)
+ end
+
+ it 'does return load_balancer assigned to a given connection' do
+ models.each do |name, model|
+ expect(model.load_balancer.name).to eq(name)
+ expect(model.sticking.instance_variable_get(:@load_balancer)).to eq(model.load_balancer)
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb b/spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb
index 08dd6a0a788..9acf80e684f 100644
--- a/spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb
@@ -181,11 +181,11 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqClientMiddleware do
end
context 'when worker data consistency is :delayed' do
- include_examples 'mark data consistency location', :delayed
+ include_examples 'mark data consistency location', :delayed
end
context 'when worker data consistency is :sticky' do
- include_examples 'mark data consistency location', :sticky
+ include_examples 'mark data consistency location', :sticky
end
end
end
diff --git a/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb b/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb
index 06efdcd8f99..de2ad662d16 100644
--- a/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb
@@ -64,7 +64,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
let(:wal_locations) { { Gitlab::Database::MAIN_DATABASE_NAME.to_sym => location } }
it 'does not stick to the primary', :aggregate_failures do
- expect(ActiveRecord::Base.connection.load_balancer)
+ expect(ActiveRecord::Base.load_balancer)
.to receive(:select_up_to_date_host)
.with(location)
.and_return(true)
@@ -107,7 +107,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
let(:job) { { 'job_id' => 'a180b47c-3fd6-41b8-81e9-34da61c3400e', 'dedup_wal_locations' => wal_locations } }
before do
- allow(ActiveRecord::Base.connection.load_balancer)
+ allow(ActiveRecord::Base.load_balancer)
.to receive(:select_up_to_date_host)
.with(wal_locations[:main])
.and_return(true)
@@ -120,7 +120,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
let(:job) { { 'job_id' => 'a180b47c-3fd6-41b8-81e9-34da61c3400e', 'database_write_location' => '0/D525E3A8' } }
before do
- allow(ActiveRecord::Base.connection.load_balancer)
+ allow(ActiveRecord::Base.load_balancer)
.to receive(:select_up_to_date_host)
.with('0/D525E3A8')
.and_return(true)
diff --git a/spec/lib/gitlab/database/load_balancing/sticking_spec.rb b/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
index 8ceda52ee85..d88554614cf 100644
--- a/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
let(:sticking) do
- described_class.new(ActiveRecord::Base.connection.load_balancer)
+ described_class.new(ActiveRecord::Base.load_balancer)
end
after do
@@ -22,7 +22,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
sticking.stick_or_unstick_request(env, :user, 42)
expect(env[Gitlab::Database::LoadBalancing::RackMiddleware::STICK_OBJECT].to_a)
- .to eq([[ActiveRecord::Base, :user, 42]])
+ .to eq([[sticking, :user, 42]])
end
it 'sticks or unsticks multiple objects and updates the Rack environment' do
@@ -42,8 +42,8 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
sticking.stick_or_unstick_request(env, :runner, '123456789')
expect(env[Gitlab::Database::LoadBalancing::RackMiddleware::STICK_OBJECT].to_a).to eq([
- [ActiveRecord::Base, :user, 42],
- [ActiveRecord::Base, :runner, '123456789']
+ [sticking, :user, 42],
+ [sticking, :runner, '123456789']
])
end
end
@@ -73,7 +73,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
end
describe '#all_caught_up?' do
- let(:lb) { ActiveRecord::Base.connection.load_balancer }
+ let(:lb) { ActiveRecord::Base.load_balancer }
let(:last_write_location) { 'foo' }
before do
@@ -137,7 +137,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
end
describe '#unstick_or_continue_sticking' do
- let(:lb) { ActiveRecord::Base.connection.load_balancer }
+ let(:lb) { ActiveRecord::Base.load_balancer }
it 'simply returns if no write location could be found' do
allow(sticking)
@@ -182,13 +182,13 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
RSpec.shared_examples 'sticking' do
before do
- allow(ActiveRecord::Base.connection.load_balancer)
+ allow(ActiveRecord::Base.load_balancer)
.to receive(:primary_write_location)
.and_return('foo')
end
it 'sticks an entity to the primary', :aggregate_failures do
- allow(ActiveRecord::Base.connection.load_balancer)
+ allow(ActiveRecord::Base.load_balancer)
.to receive(:primary_only?)
.and_return(false)
@@ -227,11 +227,11 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
describe '#mark_primary_write_location' do
it 'updates the write location with the load balancer' do
- allow(ActiveRecord::Base.connection.load_balancer)
+ allow(ActiveRecord::Base.load_balancer)
.to receive(:primary_write_location)
.and_return('foo')
- allow(ActiveRecord::Base.connection.load_balancer)
+ allow(ActiveRecord::Base.load_balancer)
.to receive(:primary_only?)
.and_return(false)
@@ -291,7 +291,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
end
describe '#select_caught_up_replicas' do
- let(:lb) { ActiveRecord::Base.connection.load_balancer }
+ let(:lb) { ActiveRecord::Base.load_balancer }
context 'with no write location' do
before do
diff --git a/spec/lib/gitlab/database/load_balancing_spec.rb b/spec/lib/gitlab/database/load_balancing_spec.rb
index bf5314e2c34..65ffe539910 100644
--- a/spec/lib/gitlab/database/load_balancing_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Gitlab::Database::LoadBalancing do
expect(models).to include(ActiveRecord::Base)
if Gitlab::Database.has_config?(:ci)
- expect(models).to include(Ci::CiDatabaseRecord)
+ expect(models).to include(Ci::ApplicationRecord)
end
end
@@ -76,7 +76,7 @@ RSpec.describe Gitlab::Database::LoadBalancing do
context 'when a read connection is used' do
it 'returns :replica' do
- proxy.load_balancer.read do |connection|
+ load_balancer.read do |connection|
expect(described_class.db_role_for_connection(connection)).to eq(:replica)
end
end
@@ -84,7 +84,7 @@ RSpec.describe Gitlab::Database::LoadBalancing do
context 'when a read_write connection is used' do
it 'returns :primary' do
- proxy.load_balancer.read_write do |connection|
+ load_balancer.read_write do |connection|
expect(described_class.db_role_for_connection(connection)).to eq(:primary)
end
end
@@ -105,7 +105,7 @@ RSpec.describe Gitlab::Database::LoadBalancing do
describe 'LoadBalancing integration tests', :database_replica, :delete do
before(:all) do
ActiveRecord::Schema.define do
- create_table :load_balancing_test, force: true do |t|
+ create_table :_test_load_balancing_test, force: true do |t|
t.string :name, null: true
end
end
@@ -113,13 +113,13 @@ RSpec.describe Gitlab::Database::LoadBalancing do
after(:all) do
ActiveRecord::Schema.define do
- drop_table :load_balancing_test, force: true
+ drop_table :_test_load_balancing_test, force: true
end
end
let(:model) do
Class.new(ApplicationRecord) do
- self.table_name = "load_balancing_test"
+ self.table_name = "_test_load_balancing_test"
end
end
@@ -443,7 +443,7 @@ RSpec.describe Gitlab::Database::LoadBalancing do
elsif payload[:name] == 'SQL' # Custom query
true
else
- keywords = %w[load_balancing_test]
+ keywords = %w[_test_load_balancing_test]
keywords += %w[begin commit] if include_transaction
keywords.any? { |keyword| payload[:sql].downcase.include?(keyword) }
end
diff --git a/spec/lib/gitlab/database/migration_helpers/loose_foreign_key_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers/loose_foreign_key_helpers_spec.rb
index 54b3ad22faf..f1dbfbbff18 100644
--- a/spec/lib/gitlab/database/migration_helpers/loose_foreign_key_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers/loose_foreign_key_helpers_spec.rb
@@ -9,18 +9,18 @@ RSpec.describe Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers do
let(:model) do
Class.new(ApplicationRecord) do
- self.table_name = 'loose_fk_test_table'
+ self.table_name = '_test_loose_fk_test_table'
end
end
before(:all) do
- migration.create_table :loose_fk_test_table do |t|
+ migration.create_table :_test_loose_fk_test_table do |t|
t.timestamps
end
end
after(:all) do
- migration.drop_table :loose_fk_test_table
+ migration.drop_table :_test_loose_fk_test_table
end
before do
@@ -37,7 +37,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers do
context 'when the record deletion tracker trigger is installed' do
before do
- migration.track_record_deletions(:loose_fk_test_table)
+ migration.track_record_deletions(:_test_loose_fk_test_table)
end
it 'stores the record deletion' do
@@ -50,7 +50,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers do
deleted_record = LooseForeignKeys::DeletedRecord.all.first
expect(deleted_record.primary_key_value).to eq(record_to_be_deleted.id)
- expect(deleted_record.fully_qualified_table_name).to eq('public.loose_fk_test_table')
+ expect(deleted_record.fully_qualified_table_name).to eq('public._test_loose_fk_test_table')
expect(deleted_record.partition).to eq(1)
end
diff --git a/spec/lib/gitlab/database/migration_helpers/v2_spec.rb b/spec/lib/gitlab/database/migration_helpers/v2_spec.rb
index 854e97ef897..acf775b3538 100644
--- a/spec/lib/gitlab/database/migration_helpers/v2_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers/v2_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
let(:model) { Class.new(ActiveRecord::Base) }
before do
- model.table_name = :test_table
+ model.table_name = :_test_table
end
context 'when called inside a transaction block' do
@@ -30,19 +30,19 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
it 'raises an error' do
expect do
- migration.public_send(operation, :test_table, :original, :renamed)
+ migration.public_send(operation, :_test_table, :original, :renamed)
end.to raise_error("#{operation} can not be run inside a transaction")
end
end
context 'when the existing column has a default value' do
before do
- migration.change_column_default :test_table, existing_column, 'default value'
+ migration.change_column_default :_test_table, existing_column, 'default value'
end
it 'raises an error' do
expect do
- migration.public_send(operation, :test_table, :original, :renamed)
+ migration.public_send(operation, :_test_table, :original, :renamed)
end.to raise_error("#{operation} does not currently support columns with default values")
end
end
@@ -51,18 +51,18 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
context 'when the batch column does not exist' do
it 'raises an error' do
expect do
- migration.public_send(operation, :test_table, :original, :renamed, batch_column_name: :missing)
- end.to raise_error('Column missing does not exist on test_table')
+ migration.public_send(operation, :_test_table, :original, :renamed, batch_column_name: :missing)
+ end.to raise_error('Column missing does not exist on _test_table')
end
end
context 'when the batch column does exist' do
it 'passes it when creating the column' do
expect(migration).to receive(:create_column_from)
- .with(:test_table, existing_column, added_column, type: nil, batch_column_name: :status)
+ .with(:_test_table, existing_column, added_column, type: nil, batch_column_name: :status)
.and_call_original
- migration.public_send(operation, :test_table, :original, :renamed, batch_column_name: :status)
+ migration.public_send(operation, :_test_table, :original, :renamed, batch_column_name: :status)
end
end
end
@@ -71,17 +71,17 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
existing_record_1 = model.create!(status: 0, existing_column => 'existing')
existing_record_2 = model.create!(status: 0, existing_column => nil)
- migration.send(operation, :test_table, :original, :renamed)
+ migration.send(operation, :_test_table, :original, :renamed)
model.reset_column_information
- expect(migration.column_exists?(:test_table, added_column)).to eq(true)
+ expect(migration.column_exists?(:_test_table, added_column)).to eq(true)
expect(existing_record_1.reload).to have_attributes(status: 0, original: 'existing', renamed: 'existing')
expect(existing_record_2.reload).to have_attributes(status: 0, original: nil, renamed: nil)
end
it 'installs triggers to sync new data' do
- migration.public_send(operation, :test_table, :original, :renamed)
+ migration.public_send(operation, :_test_table, :original, :renamed)
model.reset_column_information
new_record_1 = model.create!(status: 1, original: 'first')
@@ -102,7 +102,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
before do
allow(migration).to receive(:transaction_open?).and_return(false)
- migration.create_table :test_table do |t|
+ migration.create_table :_test_table do |t|
t.integer :status, null: false
t.text :original
t.text :other_column
@@ -118,8 +118,8 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
context 'when the column to rename does not exist' do
it 'raises an error' do
expect do
- migration.rename_column_concurrently :test_table, :missing_column, :renamed
- end.to raise_error('Column missing_column does not exist on test_table')
+ migration.rename_column_concurrently :_test_table, :missing_column, :renamed
+ end.to raise_error('Column missing_column does not exist on _test_table')
end
end
end
@@ -128,7 +128,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
before do
allow(migration).to receive(:transaction_open?).and_return(false)
- migration.create_table :test_table do |t|
+ migration.create_table :_test_table do |t|
t.integer :status, null: false
t.text :other_column
t.text :renamed
@@ -144,8 +144,8 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
context 'when the renamed column does not exist' do
it 'raises an error' do
expect do
- migration.undo_cleanup_concurrent_column_rename :test_table, :original, :missing_column
- end.to raise_error('Column missing_column does not exist on test_table')
+ migration.undo_cleanup_concurrent_column_rename :_test_table, :original, :missing_column
+ end.to raise_error('Column missing_column does not exist on _test_table')
end
end
end
@@ -156,25 +156,25 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
before do
allow(migration).to receive(:transaction_open?).and_return(false)
- migration.create_table :test_table do |t|
+ migration.create_table :_test_table do |t|
t.integer :status, null: false
t.text :original
t.text :other_column
end
- migration.rename_column_concurrently :test_table, :original, :renamed
+ migration.rename_column_concurrently :_test_table, :original, :renamed
end
context 'when the helper is called repeatedly' do
before do
- migration.public_send(operation, :test_table, :original, :renamed)
+ migration.public_send(operation, :_test_table, :original, :renamed)
end
it 'does not make repeated attempts to cleanup' do
expect(migration).not_to receive(:remove_column)
expect do
- migration.public_send(operation, :test_table, :original, :renamed)
+ migration.public_send(operation, :_test_table, :original, :renamed)
end.not_to raise_error
end
end
@@ -182,26 +182,26 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
context 'when the renamed column exists' do
let(:triggers) do
[
- ['trigger_7cc71f92fd63', 'function_for_trigger_7cc71f92fd63', before: 'insert'],
- ['trigger_f1a1f619636a', 'function_for_trigger_f1a1f619636a', before: 'update'],
- ['trigger_769a49938884', 'function_for_trigger_769a49938884', before: 'update']
+ ['trigger_020dbcb8cdd0', 'function_for_trigger_020dbcb8cdd0', before: 'insert'],
+ ['trigger_6edaca641d03', 'function_for_trigger_6edaca641d03', before: 'update'],
+ ['trigger_a3fb9f3add34', 'function_for_trigger_a3fb9f3add34', before: 'update']
]
end
it 'removes the sync triggers and renamed columns' do
triggers.each do |(trigger_name, function_name, event)|
expect_function_to_exist(function_name)
- expect_valid_function_trigger(:test_table, trigger_name, function_name, event)
+ expect_valid_function_trigger(:_test_table, trigger_name, function_name, event)
end
- expect(migration.column_exists?(:test_table, added_column)).to eq(true)
+ expect(migration.column_exists?(:_test_table, added_column)).to eq(true)
- migration.public_send(operation, :test_table, :original, :renamed)
+ migration.public_send(operation, :_test_table, :original, :renamed)
- expect(migration.column_exists?(:test_table, added_column)).to eq(false)
+ expect(migration.column_exists?(:_test_table, added_column)).to eq(false)
triggers.each do |(trigger_name, function_name, _)|
- expect_trigger_not_to_exist(:test_table, trigger_name)
+ expect_trigger_not_to_exist(:_test_table, trigger_name)
expect_function_not_to_exist(function_name)
end
end
@@ -223,7 +223,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
end
describe '#create_table' do
- let(:table_name) { :test_table }
+ let(:table_name) { :_test_table }
let(:column_attributes) do
[
{ name: 'id', sql_type: 'bigint', null: false, default: nil },
@@ -245,7 +245,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
end
expect_table_columns_to_match(column_attributes, table_name)
- expect_check_constraint(table_name, 'check_cda6f69506', 'char_length(name) <= 100')
+ expect_check_constraint(table_name, 'check_e9982cf9da', 'char_length(name) <= 100')
end
end
end
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index d89af1521a2..ea755f5a368 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -31,16 +31,10 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
describe '#add_timestamps_with_timezone' do
- let(:in_transaction) { false }
-
- before do
- allow(model).to receive(:transaction_open?).and_return(in_transaction)
- allow(model).to receive(:disable_statement_timeout)
- end
-
it 'adds "created_at" and "updated_at" fields with the "datetime_with_timezone" data type' do
Gitlab::Database::MigrationHelpers::DEFAULT_TIMESTAMP_COLUMNS.each do |column_name|
- expect(model).to receive(:add_column).with(:foo, column_name, :datetime_with_timezone, { null: false })
+ expect(model).to receive(:add_column)
+ .with(:foo, column_name, :datetime_with_timezone, { default: nil, null: false })
end
model.add_timestamps_with_timezone(:foo)
@@ -48,7 +42,8 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
it 'can disable the NOT NULL constraint' do
Gitlab::Database::MigrationHelpers::DEFAULT_TIMESTAMP_COLUMNS.each do |column_name|
- expect(model).to receive(:add_column).with(:foo, column_name, :datetime_with_timezone, { null: true })
+ expect(model).to receive(:add_column)
+ .with(:foo, column_name, :datetime_with_timezone, { default: nil, null: true })
end
model.add_timestamps_with_timezone(:foo, null: true)
@@ -64,9 +59,10 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
it 'can add choice of acceptable columns' do
expect(model).to receive(:add_column).with(:foo, :created_at, :datetime_with_timezone, anything)
expect(model).to receive(:add_column).with(:foo, :deleted_at, :datetime_with_timezone, anything)
+ expect(model).to receive(:add_column).with(:foo, :processed_at, :datetime_with_timezone, anything)
expect(model).not_to receive(:add_column).with(:foo, :updated_at, :datetime_with_timezone, anything)
- model.add_timestamps_with_timezone(:foo, columns: [:created_at, :deleted_at])
+ model.add_timestamps_with_timezone(:foo, columns: [:created_at, :deleted_at, :processed_at])
end
it 'cannot add unacceptable column names' do
@@ -74,29 +70,6 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
model.add_timestamps_with_timezone(:foo, columns: [:bar])
end.to raise_error %r/Illegal timestamp column name/
end
-
- context 'in a transaction' do
- let(:in_transaction) { true }
-
- before do
- allow(model).to receive(:add_column).with(any_args).and_call_original
- allow(model).to receive(:add_column)
- .with(:foo, anything, :datetime_with_timezone, anything)
- .and_return(nil)
- end
-
- it 'cannot add a default value' do
- expect do
- model.add_timestamps_with_timezone(:foo, default: :i_cause_an_error)
- end.to raise_error %r/add_timestamps_with_timezone/
- end
-
- it 'can add columns without defaults' do
- expect do
- model.add_timestamps_with_timezone(:foo)
- end.not_to raise_error
- end
- end
end
describe '#create_table_with_constraints' do
@@ -271,12 +244,92 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
model.add_concurrent_index(:users, :foo, unique: true)
end
- it 'does nothing if the index exists already' do
- expect(model).to receive(:index_exists?)
- .with(:users, :foo, { algorithm: :concurrently, unique: true }).and_return(true)
- expect(model).not_to receive(:add_index)
+ context 'when the index exists and is valid' do
+ before do
+ model.add_index :users, :id, unique: true
+ end
- model.add_concurrent_index(:users, :foo, unique: true)
+ it 'does leaves the existing index' do
+ expect(model).to receive(:index_exists?)
+ .with(:users, :id, { algorithm: :concurrently, unique: true }).and_call_original
+
+ expect(model).not_to receive(:remove_index)
+ expect(model).not_to receive(:add_index)
+
+ model.add_concurrent_index(:users, :id, unique: true)
+ end
+ end
+
+ context 'when an invalid copy of the index exists' do
+ before do
+ model.add_index :users, :id, unique: true, name: index_name
+
+ model.connection.execute(<<~SQL)
+ UPDATE pg_index
+ SET indisvalid = false
+ WHERE indexrelid = '#{index_name}'::regclass
+ SQL
+ end
+
+ context 'when the default name is used' do
+ let(:index_name) { model.index_name(:users, :id) }
+
+ it 'drops and recreates the index' do
+ expect(model).to receive(:index_exists?)
+ .with(:users, :id, { algorithm: :concurrently, unique: true }).and_call_original
+ expect(model).to receive(:index_invalid?).with(index_name, schema: nil).and_call_original
+
+ expect(model).to receive(:remove_concurrent_index_by_name).with(:users, index_name)
+
+ expect(model).to receive(:add_index)
+ .with(:users, :id, { algorithm: :concurrently, unique: true })
+
+ model.add_concurrent_index(:users, :id, unique: true)
+ end
+ end
+
+ context 'when a custom name is used' do
+ let(:index_name) { 'my_test_index' }
+
+ it 'drops and recreates the index' do
+ expect(model).to receive(:index_exists?)
+ .with(:users, :id, { algorithm: :concurrently, unique: true, name: index_name }).and_call_original
+ expect(model).to receive(:index_invalid?).with(index_name, schema: nil).and_call_original
+
+ expect(model).to receive(:remove_concurrent_index_by_name).with(:users, index_name)
+
+ expect(model).to receive(:add_index)
+ .with(:users, :id, { algorithm: :concurrently, unique: true, name: index_name })
+
+ model.add_concurrent_index(:users, :id, unique: true, name: index_name)
+ end
+ end
+
+ context 'when a qualified table name is used' do
+ let(:other_schema) { 'foo_schema' }
+ let(:index_name) { 'my_test_index' }
+ let(:table_name) { "#{other_schema}.users" }
+
+ before do
+ model.connection.execute(<<~SQL)
+ CREATE SCHEMA #{other_schema};
+ ALTER TABLE users SET SCHEMA #{other_schema};
+ SQL
+ end
+
+ it 'drops and recreates the index' do
+ expect(model).to receive(:index_exists?)
+ .with(table_name, :id, { algorithm: :concurrently, unique: true, name: index_name }).and_call_original
+ expect(model).to receive(:index_invalid?).with(index_name, schema: other_schema).and_call_original
+
+ expect(model).to receive(:remove_concurrent_index_by_name).with(table_name, index_name)
+
+ expect(model).to receive(:add_index)
+ .with(table_name, :id, { algorithm: :concurrently, unique: true, name: index_name })
+
+ model.add_concurrent_index(table_name, :id, unique: true, name: index_name)
+ end
+ end
end
it 'unprepares the async index creation' do
diff --git a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
index 1a7116e75e5..e42a6c970ea 100644
--- a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
@@ -583,12 +583,33 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
end
describe '#finalized_background_migration' do
- include_context 'background migration job class'
+ let(:job_coordinator) { Gitlab::BackgroundMigration::JobCoordinator.new(:main, BackgroundMigrationWorker) }
+
+ let!(:job_class_name) { 'TestJob' }
+ let!(:job_class) { Class.new }
+ let!(:job_perform_method) do
+ ->(*arguments) do
+ Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
+ # Value is 'TestJob' defined by :job_class_name in the let! above.
+ # Scoping prohibits us from directly referencing job_class_name.
+ RSpec.current_example.example_group_instance.job_class_name,
+ arguments
+ )
+ end
+ end
let!(:tracked_pending_job) { create(:background_migration_job, class_name: job_class_name, status: :pending, arguments: [1]) }
let!(:tracked_successful_job) { create(:background_migration_job, class_name: job_class_name, status: :succeeded, arguments: [2]) }
before do
+ job_class.define_method(:perform, job_perform_method)
+
+ allow(Gitlab::BackgroundMigration).to receive(:coordinator_for_database)
+ .with(:main).and_return(job_coordinator)
+
+ expect(job_coordinator).to receive(:migration_class_for)
+ .with(job_class_name).at_least(:once) { job_class }
+
Sidekiq::Testing.disable! do
BackgroundMigrationWorker.perform_async(job_class_name, [1, 2])
BackgroundMigrationWorker.perform_async(job_class_name, [3, 4])
diff --git a/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb b/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb
new file mode 100644
index 00000000000..e65f89747c4
--- /dev/null
+++ b/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Migrations::Observers::TransactionDuration do
+ subject(:transaction_duration_observer) { described_class.new(observation, directory_path) }
+
+ let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
+ let(:directory_path) { Dir.mktmpdir }
+ let(:log_file) { "#{directory_path}/#{migration_version}_#{migration_name}-transaction-duration.json" }
+ let(:transaction_duration) { Gitlab::Json.parse(File.read(log_file)) }
+ let(:migration_version) { 20210422152437 }
+ let(:migration_name) { 'test' }
+
+ after do
+ FileUtils.remove_entry(directory_path)
+ end
+
+ it 'records real and sub transactions duration', :delete do
+ observe
+
+ entry = transaction_duration[0]
+ start_time, end_time, transaction_type = entry.values_at('start_time', 'end_time', 'transaction_type')
+ start_time = DateTime.parse(start_time)
+ end_time = DateTime.parse(end_time)
+
+ aggregate_failures do
+ expect(transaction_duration.size).to eq(3)
+ expect(start_time).to be_before(end_time)
+ expect(transaction_type).not_to be_nil
+ end
+ end
+
+ context 'when there are sub-transactions' do
+ it 'records transaction duration' do
+ observe_sub_transaction
+
+ expect(transaction_duration.size).to eq(1)
+
+ entry = transaction_duration[0]['transaction_type']
+
+ expect(entry).to eql 'sub_transaction'
+ end
+ end
+
+ context 'when there are real-transactions' do
+ it 'records transaction duration', :delete do
+ observe_real_transaction
+
+ expect(transaction_duration.size).to eq(1)
+
+ entry = transaction_duration[0]['transaction_type']
+
+ expect(entry).to eql 'real_transaction'
+ end
+ end
+
+ private
+
+ def observe
+ transaction_duration_observer.before
+ run_transaction
+ transaction_duration_observer.after
+ transaction_duration_observer.record
+ end
+
+ def observe_sub_transaction
+ transaction_duration_observer.before
+ run_sub_transactions
+ transaction_duration_observer.after
+ transaction_duration_observer.record
+ end
+
+ def observe_real_transaction
+ transaction_duration_observer.before
+ run_real_transactions
+ transaction_duration_observer.after
+ transaction_duration_observer.record
+ end
+
+ def run_real_transactions
+ ActiveRecord::Base.transaction do
+ end
+ end
+
+ def run_sub_transactions
+ ActiveRecord::Base.transaction(requires_new: true) do
+ end
+ end
+
+ def run_transaction
+ ActiveRecord::Base.connection_pool.with_connection do |connection|
+ Gitlab::Database::SharedModel.using_connection(connection) do
+ Gitlab::Database::SharedModel.transaction do
+ Gitlab::Database::SharedModel.transaction(requires_new: true) do
+ Gitlab::Database::SharedModel.transaction do
+ Gitlab::Database::SharedModel.transaction do
+ Gitlab::Database::SharedModel.transaction(requires_new: true) do
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/partitioning/detached_partition_dropper_spec.rb b/spec/lib/gitlab/database/partitioning/detached_partition_dropper_spec.rb
index 8c406c90e36..b2c4e4b54a4 100644
--- a/spec/lib/gitlab/database/partitioning/detached_partition_dropper_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/detached_partition_dropper_spec.rb
@@ -5,6 +5,8 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Partitioning::DetachedPartitionDropper do
include Database::TableSchemaHelpers
+ subject(:dropper) { described_class.new }
+
let(:connection) { ActiveRecord::Base.connection }
def expect_partition_present(name)
@@ -23,10 +25,18 @@ RSpec.describe Gitlab::Database::Partitioning::DetachedPartitionDropper do
before do
connection.execute(<<~SQL)
+ CREATE TABLE referenced_table (
+ id bigserial primary key not null
+ )
+ SQL
+ connection.execute(<<~SQL)
+
CREATE TABLE parent_table (
id bigserial not null,
+ referenced_id bigint not null,
created_at timestamptz not null,
- primary key (id, created_at)
+ primary key (id, created_at),
+ constraint fk_referenced foreign key (referenced_id) references referenced_table(id)
) PARTITION BY RANGE(created_at)
SQL
end
@@ -59,7 +69,7 @@ RSpec.describe Gitlab::Database::Partitioning::DetachedPartitionDropper do
attached: false,
drop_after: 1.day.from_now)
- subject.perform
+ dropper.perform
expect_partition_present('test_partition')
end
@@ -75,7 +85,7 @@ RSpec.describe Gitlab::Database::Partitioning::DetachedPartitionDropper do
end
it 'drops the partition' do
- subject.perform
+ dropper.perform
expect(table_oid('test_partition')).to be_nil
end
@@ -86,16 +96,62 @@ RSpec.describe Gitlab::Database::Partitioning::DetachedPartitionDropper do
end
it 'does not drop the partition' do
- subject.perform
+ dropper.perform
expect(table_oid('test_partition')).not_to be_nil
end
end
+ context 'removing foreign keys' do
+ it 'removes foreign keys from the table before dropping it' do
+ expect(dropper).to receive(:drop_detached_partition).and_wrap_original do |drop_method, partition_name|
+ expect(partition_name).to eq('test_partition')
+ expect(foreign_key_exists_by_name(partition_name, 'fk_referenced', schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)).to be_falsey
+
+ drop_method.call(partition_name)
+ end
+
+ expect(foreign_key_exists_by_name('test_partition', 'fk_referenced', schema: Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA)).to be_truthy
+
+ dropper.perform
+ end
+
+ it 'does not remove foreign keys from the parent table' do
+ expect { dropper.perform }.not_to change { foreign_key_exists_by_name('parent_table', 'fk_referenced') }.from(true)
+ end
+
+ context 'when another process drops the foreign key' do
+ it 'skips dropping that foreign key' do
+ expect(dropper).to receive(:drop_foreign_key_if_present).and_wrap_original do |drop_meth, *args|
+ connection.execute('alter table gitlab_partitions_dynamic.test_partition drop constraint fk_referenced;')
+ drop_meth.call(*args)
+ end
+
+ dropper.perform
+
+ expect_partition_removed('test_partition')
+ end
+ end
+
+ context 'when another process drops the partition' do
+ it 'skips dropping the foreign key' do
+ expect(dropper).to receive(:drop_foreign_key_if_present).and_wrap_original do |drop_meth, *args|
+ connection.execute('drop table gitlab_partitions_dynamic.test_partition')
+ Postgresql::DetachedPartition.where(table_name: 'test_partition').delete_all
+ end
+
+ expect(Gitlab::AppLogger).not_to receive(:error)
+ dropper.perform
+ end
+ end
+ end
+
context 'when another process drops the table while the first waits for a lock' do
it 'skips the table' do
+ # First call to .lock is for removing foreign keys
+ expect(Postgresql::DetachedPartition).to receive(:lock).once.ordered.and_call_original
# Rspec's receive_method_chain does not support .and_wrap_original, so we need to nest here.
- expect(Postgresql::DetachedPartition).to receive(:lock).and_wrap_original do |lock_meth|
+ expect(Postgresql::DetachedPartition).to receive(:lock).once.ordered.and_wrap_original do |lock_meth|
locked = lock_meth.call
expect(locked).to receive(:find_by).and_wrap_original do |find_meth, *find_args|
# Another process drops the table then deletes this entry
@@ -106,9 +162,9 @@ RSpec.describe Gitlab::Database::Partitioning::DetachedPartitionDropper do
locked
end
- expect(subject).not_to receive(:drop_one)
+ expect(dropper).not_to receive(:drop_one)
- subject.perform
+ dropper.perform
end
end
end
@@ -123,19 +179,26 @@ RSpec.describe Gitlab::Database::Partitioning::DetachedPartitionDropper do
end
it 'does not drop the partition, but does remove the DetachedPartition entry' do
- subject.perform
+ dropper.perform
aggregate_failures do
expect(table_oid('test_partition')).not_to be_nil
expect(Postgresql::DetachedPartition.find_by(table_name: 'test_partition')).to be_nil
end
end
- it 'removes the detached_partition entry' do
- detached_partition = Postgresql::DetachedPartition.find_by!(table_name: 'test_partition')
+ context 'when another process removes the entry before this process' do
+ it 'does nothing' do
+ expect(Postgresql::DetachedPartition).to receive(:lock).and_wrap_original do |lock_meth|
+ Postgresql::DetachedPartition.delete_all
+ lock_meth.call
+ end
- subject.perform
+ expect(Gitlab::AppLogger).not_to receive(:error)
- expect(Postgresql::DetachedPartition.exists?(id: detached_partition.id)).to be_falsey
+ dropper.perform
+
+ expect(table_oid('test_partition')).not_to be_nil
+ end
end
end
@@ -155,7 +218,7 @@ RSpec.describe Gitlab::Database::Partitioning::DetachedPartitionDropper do
end
it 'drops both partitions' do
- subject.perform
+ dropper.perform
expect_partition_removed('partition_1')
expect_partition_removed('partition_2')
@@ -163,10 +226,10 @@ RSpec.describe Gitlab::Database::Partitioning::DetachedPartitionDropper do
context 'when the first drop returns an error' do
it 'still drops the second partition' do
- expect(subject).to receive(:drop_detached_partition).ordered.and_raise('injected error')
- expect(subject).to receive(:drop_detached_partition).ordered.and_call_original
+ expect(dropper).to receive(:drop_detached_partition).ordered.and_raise('injected error')
+ expect(dropper).to receive(:drop_detached_partition).ordered.and_call_original
- subject.perform
+ dropper.perform
# We don't know which partition we tried to drop first, so the tests here have to work with either one
expect(Postgresql::DetachedPartition.count).to eq(1)
diff --git a/spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb b/spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb
index 27ada12b067..67d80d71e2a 100644
--- a/spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Gitlab::Database::Partitioning::MonthlyStrategy do
let(:model) { double('model', table_name: table_name) }
let(:partitioning_key) { double }
- let(:table_name) { :partitioned_test }
+ let(:table_name) { :_test_partitioned_test }
before do
connection.execute(<<~SQL)
@@ -18,11 +18,11 @@ RSpec.describe Gitlab::Database::Partitioning::MonthlyStrategy do
(id serial not null, created_at timestamptz not null, PRIMARY KEY (id, created_at))
PARTITION BY RANGE (created_at);
- CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.partitioned_test_000000
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_000000
PARTITION OF #{table_name}
FOR VALUES FROM (MINVALUE) TO ('2020-05-01');
- CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.partitioned_test_202005
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_202005
PARTITION OF #{table_name}
FOR VALUES FROM ('2020-05-01') TO ('2020-06-01');
SQL
@@ -30,8 +30,8 @@ RSpec.describe Gitlab::Database::Partitioning::MonthlyStrategy do
it 'detects both partitions' do
expect(subject).to eq([
- Gitlab::Database::Partitioning::TimePartition.new(table_name, nil, '2020-05-01', partition_name: 'partitioned_test_000000'),
- Gitlab::Database::Partitioning::TimePartition.new(table_name, '2020-05-01', '2020-06-01', partition_name: 'partitioned_test_202005')
+ Gitlab::Database::Partitioning::TimePartition.new(table_name, nil, '2020-05-01', partition_name: '_test_partitioned_test_000000'),
+ Gitlab::Database::Partitioning::TimePartition.new(table_name, '2020-05-01', '2020-06-01', partition_name: '_test_partitioned_test_202005')
])
end
end
@@ -41,7 +41,7 @@ RSpec.describe Gitlab::Database::Partitioning::MonthlyStrategy do
let(:model) do
Class.new(ActiveRecord::Base) do
- self.table_name = 'partitioned_test'
+ self.table_name = '_test_partitioned_test'
self.primary_key = :id
end
end
@@ -59,11 +59,11 @@ RSpec.describe Gitlab::Database::Partitioning::MonthlyStrategy do
(id serial not null, created_at timestamptz not null, PRIMARY KEY (id, created_at))
PARTITION BY RANGE (created_at);
- CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.partitioned_test_000000
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_000000
PARTITION OF #{model.table_name}
FOR VALUES FROM (MINVALUE) TO ('2020-05-01');
- CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.partitioned_test_202006
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_202006
PARTITION OF #{model.table_name}
FOR VALUES FROM ('2020-06-01') TO ('2020-07-01');
SQL
@@ -166,7 +166,7 @@ RSpec.describe Gitlab::Database::Partitioning::MonthlyStrategy do
(id serial not null, created_at timestamptz not null, PRIMARY KEY (id, created_at))
PARTITION BY RANGE (created_at);
- CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.partitioned_test_202006
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_202006
PARTITION OF #{model.table_name}
FOR VALUES FROM ('2020-06-01') TO ('2020-07-01');
SQL
@@ -181,13 +181,13 @@ RSpec.describe Gitlab::Database::Partitioning::MonthlyStrategy do
describe '#extra_partitions' do
let(:model) do
Class.new(ActiveRecord::Base) do
- self.table_name = 'partitioned_test'
+ self.table_name = '_test_partitioned_test'
self.primary_key = :id
end
end
let(:partitioning_key) { :created_at }
- let(:table_name) { :partitioned_test }
+ let(:table_name) { :_test_partitioned_test }
around do |example|
travel_to(Date.parse('2020-08-22')) { example.run }
@@ -200,15 +200,15 @@ RSpec.describe Gitlab::Database::Partitioning::MonthlyStrategy do
(id serial not null, created_at timestamptz not null, PRIMARY KEY (id, created_at))
PARTITION BY RANGE (created_at);
- CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.partitioned_test_000000
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_000000
PARTITION OF #{table_name}
FOR VALUES FROM (MINVALUE) TO ('2020-05-01');
- CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.partitioned_test_202005
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_202005
PARTITION OF #{table_name}
FOR VALUES FROM ('2020-05-01') TO ('2020-06-01');
- CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.partitioned_test_202006
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_202006
PARTITION OF #{table_name}
FOR VALUES FROM ('2020-06-01') TO ('2020-07-01')
SQL
@@ -235,7 +235,7 @@ RSpec.describe Gitlab::Database::Partitioning::MonthlyStrategy do
it 'prunes the unbounded partition ending 2020-05-01' do
min_value_to_may = Gitlab::Database::Partitioning::TimePartition.new(model.table_name, nil, '2020-05-01',
- partition_name: 'partitioned_test_000000')
+ partition_name: '_test_partitioned_test_000000')
expect(subject).to contain_exactly(min_value_to_may)
end
@@ -246,8 +246,8 @@ RSpec.describe Gitlab::Database::Partitioning::MonthlyStrategy do
it 'prunes the unbounded partition and the partition for May-June' do
expect(subject).to contain_exactly(
- Gitlab::Database::Partitioning::TimePartition.new(model.table_name, nil, '2020-05-01', partition_name: 'partitioned_test_000000'),
- Gitlab::Database::Partitioning::TimePartition.new(model.table_name, '2020-05-01', '2020-06-01', partition_name: 'partitioned_test_202005')
+ Gitlab::Database::Partitioning::TimePartition.new(model.table_name, nil, '2020-05-01', partition_name: '_test_partitioned_test_000000'),
+ Gitlab::Database::Partitioning::TimePartition.new(model.table_name, '2020-05-01', '2020-06-01', partition_name: '_test_partitioned_test_202005')
)
end
@@ -256,16 +256,16 @@ RSpec.describe Gitlab::Database::Partitioning::MonthlyStrategy do
it 'prunes empty partitions' do
expect(subject).to contain_exactly(
- Gitlab::Database::Partitioning::TimePartition.new(model.table_name, nil, '2020-05-01', partition_name: 'partitioned_test_000000'),
- Gitlab::Database::Partitioning::TimePartition.new(model.table_name, '2020-05-01', '2020-06-01', partition_name: 'partitioned_test_202005')
+ Gitlab::Database::Partitioning::TimePartition.new(model.table_name, nil, '2020-05-01', partition_name: '_test_partitioned_test_000000'),
+ Gitlab::Database::Partitioning::TimePartition.new(model.table_name, '2020-05-01', '2020-06-01', partition_name: '_test_partitioned_test_202005')
)
end
it 'does not prune non-empty partitions' do
- connection.execute("INSERT INTO #{table_name} (created_at) VALUES (('2020-05-15'))") # inserting one record into partitioned_test_202005
+ connection.execute("INSERT INTO #{table_name} (created_at) VALUES (('2020-05-15'))") # inserting one record into _test_partitioned_test_202005
expect(subject).to contain_exactly(
- Gitlab::Database::Partitioning::TimePartition.new(model.table_name, nil, '2020-05-01', partition_name: 'partitioned_test_000000')
+ Gitlab::Database::Partitioning::TimePartition.new(model.table_name, nil, '2020-05-01', partition_name: '_test_partitioned_test_000000')
)
end
end
diff --git a/spec/lib/gitlab/database/partitioning/multi_database_partition_dropper_spec.rb b/spec/lib/gitlab/database/partitioning/multi_database_partition_dropper_spec.rb
deleted file mode 100644
index 56d6ebb7aff..00000000000
--- a/spec/lib/gitlab/database/partitioning/multi_database_partition_dropper_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Database::Partitioning::MultiDatabasePartitionDropper, '#drop_detached_partitions' do
- subject(:drop_detached_partitions) { multi_db_dropper.drop_detached_partitions }
-
- let(:multi_db_dropper) { described_class.new }
-
- let(:connection_wrapper1) { double(scope: scope1) }
- let(:connection_wrapper2) { double(scope: scope2) }
-
- let(:scope1) { double(connection: connection1) }
- let(:scope2) { double(connection: connection2) }
-
- let(:connection1) { double('connection') }
- let(:connection2) { double('connection') }
-
- let(:dropper_class) { Gitlab::Database::Partitioning::DetachedPartitionDropper }
- let(:dropper1) { double('partition dropper') }
- let(:dropper2) { double('partition dropper') }
-
- before do
- allow(multi_db_dropper).to receive(:databases).and_return({ db1: connection_wrapper1, db2: connection_wrapper2 })
- end
-
- it 'drops detached partitions for each database' do
- expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(connection1).and_yield.ordered
- expect(dropper_class).to receive(:new).and_return(dropper1).ordered
- expect(dropper1).to receive(:perform)
-
- expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(connection2).and_yield.ordered
- expect(dropper_class).to receive(:new).and_return(dropper2).ordered
- expect(dropper2).to receive(:perform)
-
- drop_detached_partitions
- end
-end
diff --git a/spec/lib/gitlab/database/partitioning/multi_database_partition_manager_spec.rb b/spec/lib/gitlab/database/partitioning/multi_database_partition_manager_spec.rb
deleted file mode 100644
index 3c94c1bf4ea..00000000000
--- a/spec/lib/gitlab/database/partitioning/multi_database_partition_manager_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Database::Partitioning::MultiDatabasePartitionManager, '#sync_partitions' do
- subject(:sync_partitions) { manager.sync_partitions }
-
- let(:manager) { described_class.new(models) }
- let(:models) { [model1, model2] }
-
- let(:model1) { double('model1', connection: connection1, table_name: 'table1') }
- let(:model2) { double('model2', connection: connection1, table_name: 'table2') }
-
- let(:connection1) { double('connection1') }
- let(:connection2) { double('connection2') }
-
- let(:target_manager_class) { Gitlab::Database::Partitioning::PartitionManager }
- let(:target_manager1) { double('partition manager') }
- let(:target_manager2) { double('partition manager') }
-
- before do
- allow(manager).to receive(:connection_name).and_return('name')
- end
-
- it 'syncs model partitions, setting up the appropriate connection for each', :aggregate_failures do
- expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(model1.connection).and_yield.ordered
- expect(target_manager_class).to receive(:new).with(model1).and_return(target_manager1).ordered
- expect(target_manager1).to receive(:sync_partitions)
-
- expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(model2.connection).and_yield.ordered
- expect(target_manager_class).to receive(:new).with(model2).and_return(target_manager2).ordered
- expect(target_manager2).to receive(:sync_partitions)
-
- sync_partitions
- end
-end
diff --git a/spec/lib/gitlab/database/partitioning/partition_manager_spec.rb b/spec/lib/gitlab/database/partitioning/partition_manager_spec.rb
index 7c4cfcfb3a9..1c6f5c5c694 100644
--- a/spec/lib/gitlab/database/partitioning/partition_manager_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/partition_manager_spec.rb
@@ -195,7 +195,7 @@ RSpec.describe Gitlab::Database::Partitioning::PartitionManager do
end
# Postgres 11 does not support foreign keys to partitioned tables
- if Gitlab::Database.main.version.to_f >= 12
+ if ApplicationRecord.database.version.to_f >= 12
context 'when the model is the target of a foreign key' do
before do
connection.execute(<<~SQL)
diff --git a/spec/lib/gitlab/database/partitioning/partition_monitoring_spec.rb b/spec/lib/gitlab/database/partitioning/partition_monitoring_spec.rb
index 7024cbd55ff..006ce8a7f48 100644
--- a/spec/lib/gitlab/database/partitioning/partition_monitoring_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/partition_monitoring_spec.rb
@@ -4,9 +4,8 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Partitioning::PartitionMonitoring do
describe '#report_metrics' do
- subject { described_class.new(models).report_metrics }
+ subject { described_class.new.report_metrics_for_model(model) }
- let(:models) { [model] }
let(:model) { double(partitioning_strategy: partitioning_strategy, table_name: table) }
let(:partitioning_strategy) { double(missing_partitions: missing_partitions, current_partitions: current_partitions, extra_partitions: extra_partitions) }
let(:table) { "some_table" }
diff --git a/spec/lib/gitlab/database/partitioning/replace_table_spec.rb b/spec/lib/gitlab/database/partitioning/replace_table_spec.rb
index 8e27797208c..fdf514b519f 100644
--- a/spec/lib/gitlab/database/partitioning/replace_table_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/replace_table_spec.rb
@@ -5,7 +5,9 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Partitioning::ReplaceTable, '#perform' do
include Database::TableSchemaHelpers
- subject(:replace_table) { described_class.new(original_table, replacement_table, archived_table, 'id').perform }
+ subject(:replace_table) do
+ described_class.new(connection, original_table, replacement_table, archived_table, 'id').perform
+ end
let(:original_table) { '_test_original_table' }
let(:replacement_table) { '_test_replacement_table' }
diff --git a/spec/lib/gitlab/database/partitioning_spec.rb b/spec/lib/gitlab/database/partitioning_spec.rb
index 486af9413e8..154cc2b7972 100644
--- a/spec/lib/gitlab/database/partitioning_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_spec.rb
@@ -3,52 +3,175 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::Partitioning do
+ include Database::PartitioningHelpers
+ include Database::TableSchemaHelpers
+
+ let(:connection) { ApplicationRecord.connection }
+
+ around do |example|
+ previously_registered_models = described_class.registered_models.dup
+ described_class.instance_variable_set('@registered_models', Set.new)
+
+ previously_registered_tables = described_class.registered_tables.dup
+ described_class.instance_variable_set('@registered_tables', Set.new)
+
+ example.run
+
+ described_class.instance_variable_set('@registered_models', previously_registered_models)
+ described_class.instance_variable_set('@registered_tables', previously_registered_tables)
+ end
+
+ describe '.register_models' do
+ context 'ensure that the registered models have partitioning strategy' do
+ it 'fails when partitioning_strategy is not specified for the model' do
+ model = Class.new(ApplicationRecord)
+ expect { described_class.register_models([model]) }.to raise_error /should have partitioning strategy defined/
+ end
+ end
+ end
+
+ describe '.sync_partitions_ignore_db_error' do
+ it 'calls sync_partitions' do
+ expect(described_class).to receive(:sync_partitions)
+
+ described_class.sync_partitions_ignore_db_error
+ end
+
+ [ActiveRecord::ActiveRecordError, PG::Error].each do |error|
+ context "when #{error} is raised" do
+ before do
+ expect(described_class).to receive(:sync_partitions)
+ .and_raise(error)
+ end
+
+ it 'ignores it' do
+ described_class.sync_partitions_ignore_db_error
+ end
+ end
+ end
+
+ context 'when DISABLE_POSTGRES_PARTITION_CREATION_ON_STARTUP is set' do
+ before do
+ stub_env('DISABLE_POSTGRES_PARTITION_CREATION_ON_STARTUP', '1')
+ end
+
+ it 'does not call sync_partitions' do
+ expect(described_class).to receive(:sync_partitions).never
+
+ described_class.sync_partitions_ignore_db_error
+ end
+ end
+ end
+
describe '.sync_partitions' do
- let(:partition_manager_class) { described_class::MultiDatabasePartitionManager }
- let(:partition_manager) { double('partition manager') }
+ let(:table_names) { %w[partitioning_test1 partitioning_test2] }
+ let(:models) do
+ table_names.map do |table_name|
+ Class.new(ApplicationRecord) do
+ include PartitionedTable
+
+ self.table_name = table_name
+ partitioned_by :created_at, strategy: :monthly
+ end
+ end
+ end
+
+ before do
+ table_names.each do |table_name|
+ connection.execute(<<~SQL)
+ CREATE TABLE #{table_name} (
+ id serial not null,
+ created_at timestamptz not null,
+ PRIMARY KEY (id, created_at))
+ PARTITION BY RANGE (created_at);
+ SQL
+ end
+ end
+
+ it 'manages partitions for each given model' do
+ expect { described_class.sync_partitions(models)}
+ .to change { find_partitions(table_names.first).size }.from(0)
+ .and change { find_partitions(table_names.last).size }.from(0)
+ end
context 'when no partitioned models are given' do
- it 'calls the partition manager with the registered models' do
- expect(partition_manager_class).to receive(:new)
- .with(described_class.registered_models)
- .and_return(partition_manager)
+ it 'manages partitions for each registered model' do
+ described_class.register_models([models.first])
+ described_class.register_tables([
+ {
+ table_name: table_names.last,
+ partitioned_column: :created_at, strategy: :monthly
+ }
+ ])
- expect(partition_manager).to receive(:sync_partitions)
+ expect { described_class.sync_partitions }
+ .to change { find_partitions(table_names.first).size }.from(0)
+ .and change { find_partitions(table_names.last).size }.from(0)
+ end
+ end
+ end
+
+ describe '.report_metrics' do
+ let(:model1) { double('model') }
+ let(:model2) { double('model') }
+
+ let(:partition_monitoring_class) { described_class::PartitionMonitoring }
+
+ context 'when no partitioned models are given' do
+ it 'reports metrics for each registered model' do
+ expect_next_instance_of(partition_monitoring_class) do |partition_monitor|
+ expect(partition_monitor).to receive(:report_metrics_for_model).with(model1)
+ expect(partition_monitor).to receive(:report_metrics_for_model).with(model2)
+ end
+
+ expect(Gitlab::Database::EachDatabase).to receive(:each_model_connection)
+ .with(described_class.__send__(:registered_models))
+ .and_yield(model1)
+ .and_yield(model2)
- described_class.sync_partitions
+ described_class.report_metrics
end
end
context 'when partitioned models are given' do
- it 'calls the partition manager with the given models' do
- models = ['my special model']
+ it 'reports metrics for each given model' do
+ expect_next_instance_of(partition_monitoring_class) do |partition_monitor|
+ expect(partition_monitor).to receive(:report_metrics_for_model).with(model1)
+ expect(partition_monitor).to receive(:report_metrics_for_model).with(model2)
+ end
- expect(partition_manager_class).to receive(:new)
- .with(models)
- .and_return(partition_manager)
+ expect(Gitlab::Database::EachDatabase).to receive(:each_model_connection)
+ .with([model1, model2])
+ .and_yield(model1)
+ .and_yield(model2)
- expect(partition_manager).to receive(:sync_partitions)
-
- described_class.sync_partitions(models)
+ described_class.report_metrics([model1, model2])
end
end
end
describe '.drop_detached_partitions' do
- let(:partition_dropper_class) { described_class::MultiDatabasePartitionDropper }
+ let(:table_names) { %w[detached_test_partition1 detached_test_partition2] }
+
+ before do
+ table_names.each do |table_name|
+ connection.create_table("#{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.#{table_name}")
- it 'delegates to the partition dropper' do
- expect_next_instance_of(partition_dropper_class) do |partition_dropper|
- expect(partition_dropper).to receive(:drop_detached_partitions)
+ Postgresql::DetachedPartition.create!(table_name: table_name, drop_after: 1.year.ago)
end
+ end
- described_class.drop_detached_partitions
+ it 'drops detached partitions for each database' do
+ expect(Gitlab::Database::EachDatabase).to receive(:each_database_connection).and_yield
+
+ expect { described_class.drop_detached_partitions }
+ .to change { Postgresql::DetachedPartition.count }.from(2).to(0)
+ .and change { table_exists?(table_names.first) }.from(true).to(false)
+ .and change { table_exists?(table_names.last) }.from(true).to(false)
end
- end
- context 'ensure that the registered models have partitioning strategy' do
- it 'fails when partitioning_strategy is not specified for the model' do
- expect(described_class.registered_models).to all(respond_to(:partitioning_strategy))
+ def table_exists?(table_name)
+ table_oid(table_name).present?
end
end
end
diff --git a/spec/lib/gitlab/database/postgres_foreign_key_spec.rb b/spec/lib/gitlab/database/postgres_foreign_key_spec.rb
index ec39e5bfee7..b0e08ca1e67 100644
--- a/spec/lib/gitlab/database/postgres_foreign_key_spec.rb
+++ b/spec/lib/gitlab/database/postgres_foreign_key_spec.rb
@@ -38,4 +38,16 @@ RSpec.describe Gitlab::Database::PostgresForeignKey, type: :model do
expect(described_class.by_referenced_table_identifier('public.referenced_table')).to contain_exactly(expected)
end
end
+
+ describe '#by_constrained_table_identifier' do
+ it 'throws an error when the identifier name is not fully qualified' do
+ expect { described_class.by_constrained_table_identifier('constrained_table') }.to raise_error(ArgumentError, /not fully qualified/)
+ end
+
+ it 'finds the foreign keys for the constrained table' do
+ expected = described_class.where(name: %w[fk_constrained_to_referenced fk_constrained_to_other_referenced]).to_a
+
+ expect(described_class.by_constrained_table_identifier('public.constrained_table')).to match_array(expected)
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/postgres_hll/batch_distinct_counter_spec.rb b/spec/lib/gitlab/database/postgres_hll/batch_distinct_counter_spec.rb
index 2c550f14a08..c9bbc32e059 100644
--- a/spec/lib/gitlab/database/postgres_hll/batch_distinct_counter_spec.rb
+++ b/spec/lib/gitlab/database/postgres_hll/batch_distinct_counter_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Gitlab::Database::PostgresHll::BatchDistinctCounter do
end
before do
- allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(in_transaction)
+ allow(model.connection).to receive(:transaction_open?).and_return(in_transaction)
end
context 'unit test for different counting parameters' do
diff --git a/spec/lib/gitlab/database/postgres_index_bloat_estimate_spec.rb b/spec/lib/gitlab/database/postgres_index_bloat_estimate_spec.rb
index da4422bd442..13ac9190ab7 100644
--- a/spec/lib/gitlab/database/postgres_index_bloat_estimate_spec.rb
+++ b/spec/lib/gitlab/database/postgres_index_bloat_estimate_spec.rb
@@ -13,6 +13,8 @@ RSpec.describe Gitlab::Database::PostgresIndexBloatEstimate do
let(:identifier) { 'public.schema_migrations_pkey' }
+ it { is_expected.to be_a Gitlab::Database::SharedModel }
+
describe '#bloat_size' do
it 'returns the bloat size in bytes' do
# We cannot reach much more about the bloat size estimate here
diff --git a/spec/lib/gitlab/database/postgres_index_spec.rb b/spec/lib/gitlab/database/postgres_index_spec.rb
index 9088719d5a4..db66736676b 100644
--- a/spec/lib/gitlab/database/postgres_index_spec.rb
+++ b/spec/lib/gitlab/database/postgres_index_spec.rb
@@ -22,6 +22,8 @@ RSpec.describe Gitlab::Database::PostgresIndex do
it_behaves_like 'a postgres model'
+ it { is_expected.to be_a Gitlab::Database::SharedModel }
+
describe '.reindexing_support' do
it 'only non partitioned indexes' do
expect(described_class.reindexing_support).to all(have_attributes(partitioned: false))
diff --git a/spec/lib/gitlab/database/query_analyzer_spec.rb b/spec/lib/gitlab/database/query_analyzer_spec.rb
new file mode 100644
index 00000000000..82a1c7143d5
--- /dev/null
+++ b/spec/lib/gitlab/database/query_analyzer_spec.rb
@@ -0,0 +1,144 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::QueryAnalyzer, query_analyzers: false do
+ let(:analyzer) { double(:query_analyzer) }
+ let(:disabled_analyzer) { double(:disabled_query_analyzer) }
+
+ before do
+ allow(described_class.instance).to receive(:all_analyzers).and_return([analyzer, disabled_analyzer])
+ allow(analyzer).to receive(:enabled?).and_return(true)
+ allow(analyzer).to receive(:suppressed?).and_return(false)
+ allow(analyzer).to receive(:begin!)
+ allow(analyzer).to receive(:end!)
+ allow(disabled_analyzer).to receive(:enabled?).and_return(false)
+ end
+
+ context 'the hook is enabled by default in specs' do
+ it 'does process queries and gets normalized SQL' do
+ expect(analyzer).to receive(:enabled?).and_return(true)
+ expect(analyzer).to receive(:analyze) do |parsed|
+ expect(parsed.sql).to include("SELECT $1 FROM projects")
+ expect(parsed.pg.tables).to eq(%w[projects])
+ end
+
+ described_class.instance.within do
+ Project.connection.execute("SELECT 1 FROM projects")
+ end
+ end
+
+ it 'does prevent recursive execution' do
+ expect(analyzer).to receive(:enabled?).and_return(true)
+ expect(analyzer).to receive(:analyze) do
+ Project.connection.execute("SELECT 1 FROM projects")
+ end
+
+ described_class.instance.within do
+ Project.connection.execute("SELECT 1 FROM projects")
+ end
+ end
+ end
+
+ describe '#within' do
+ context 'when it is already initialized' do
+ around do |example|
+ described_class.instance.within do
+ example.run
+ end
+ end
+
+ it 'does not evaluate enabled? again do yield block' do
+ expect(analyzer).not_to receive(:enabled?)
+
+ expect { |b| described_class.instance.within(&b) }.to yield_control
+ end
+ end
+
+ context 'when initializer is enabled' do
+ before do
+ expect(analyzer).to receive(:enabled?).and_return(true)
+ end
+
+ it 'calls begin! and end!' do
+ expect(analyzer).to receive(:begin!)
+ expect(analyzer).to receive(:end!)
+
+ expect { |b| described_class.instance.within(&b) }.to yield_control
+ end
+
+ it 'when begin! raises the end! is not called' do
+ expect(analyzer).to receive(:begin!).and_raise('exception')
+ expect(analyzer).not_to receive(:end!)
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
+
+ expect { |b| described_class.instance.within(&b) }.to yield_control
+ end
+ end
+ end
+
+ describe '#process_sql' do
+ it 'does not analyze query if not enabled' do
+ expect(analyzer).to receive(:enabled?).and_return(false)
+ expect(analyzer).not_to receive(:analyze)
+
+ process_sql("SELECT 1 FROM projects")
+ end
+
+ it 'does analyze query if enabled' do
+ expect(analyzer).to receive(:enabled?).and_return(true)
+ expect(analyzer).to receive(:analyze) do |parsed|
+ expect(parsed.sql).to eq("SELECT $1 FROM projects")
+ expect(parsed.pg.tables).to eq(%w[projects])
+ end
+
+ process_sql("SELECT 1 FROM projects")
+ end
+
+ it 'does track exception if query cannot be parsed' do
+ expect(analyzer).to receive(:enabled?).and_return(true)
+ expect(analyzer).not_to receive(:analyze)
+ expect(Gitlab::ErrorTracking).to receive(:track_exception)
+
+ expect { process_sql("invalid query") }.not_to raise_error
+ end
+
+ it 'does track exception if analyzer raises exception on enabled?' do
+ expect(analyzer).to receive(:enabled?).and_raise('exception')
+ expect(analyzer).not_to receive(:analyze)
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
+
+ expect { process_sql("SELECT 1 FROM projects") }.not_to raise_error
+ end
+
+ it 'does track exception if analyzer raises exception on analyze' do
+ expect(analyzer).to receive(:enabled?).and_return(true)
+ expect(analyzer).to receive(:analyze).and_raise('exception')
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
+
+ expect { process_sql("SELECT 1 FROM projects") }.not_to raise_error
+ end
+
+ it 'does call analyze only on enabled initializers' do
+ expect(analyzer).to receive(:analyze)
+ expect(disabled_analyzer).not_to receive(:analyze)
+
+ expect { process_sql("SELECT 1 FROM projects") }.not_to raise_error
+ end
+
+ it 'does not call analyze on suppressed analyzers' do
+ expect(analyzer).to receive(:suppressed?).and_return(true)
+ expect(analyzer).not_to receive(:analyze)
+
+ expect { process_sql("SELECT 1 FROM projects") }.not_to raise_error
+ end
+
+ def process_sql(sql)
+ described_class.instance.within do
+ ApplicationRecord.load_balancer.read_write do |connection|
+ described_class.instance.process_sql(sql, connection)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb b/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb
new file mode 100644
index 00000000000..ab5f05e3ec4
--- /dev/null
+++ b/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::QueryAnalyzers::GitlabSchemasMetrics, query_analyzers: false do
+ let(:analyzer) { described_class }
+
+ before do
+ allow(Gitlab::Database::QueryAnalyzer.instance).to receive(:all_analyzers).and_return([analyzer])
+ end
+
+ it 'does not increment metrics if feature flag is disabled' do
+ stub_feature_flags(query_analyzer_gitlab_schema_metrics: false)
+
+ expect(analyzer).not_to receive(:analyze)
+
+ process_sql(ActiveRecord::Base, "SELECT 1 FROM projects")
+ end
+
+ context 'properly observes all queries', :mocked_ci_connection do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "for simple query observes schema correctly" => {
+ model: ApplicationRecord,
+ sql: "SELECT 1 FROM projects",
+ expectations: {
+ gitlab_schemas: "gitlab_main",
+ db_config_name: "main"
+ }
+ },
+ "for query accessing gitlab_ci and gitlab_main" => {
+ model: ApplicationRecord,
+ sql: "SELECT 1 FROM projects LEFT JOIN ci_builds ON ci_builds.project_id=projects.id",
+ expectations: {
+ gitlab_schemas: "gitlab_ci,gitlab_main",
+ db_config_name: "main"
+ }
+ },
+ "for query accessing gitlab_ci and gitlab_main the gitlab_schemas is always ordered" => {
+ model: ApplicationRecord,
+ sql: "SELECT 1 FROM ci_builds LEFT JOIN projects ON ci_builds.project_id=projects.id",
+ expectations: {
+ gitlab_schemas: "gitlab_ci,gitlab_main",
+ db_config_name: "main"
+ }
+ },
+ "for query accessing CI database" => {
+ model: Ci::ApplicationRecord,
+ sql: "SELECT 1 FROM ci_builds",
+ expectations: {
+ gitlab_schemas: "gitlab_ci",
+ db_config_name: "ci"
+ }
+ }
+ }
+ end
+
+ with_them do
+ around do |example|
+ Gitlab::Database::QueryAnalyzer.instance.within { example.run }
+ end
+
+ it do
+ expect(described_class.schemas_metrics).to receive(:increment)
+ .with(expectations).and_call_original
+
+ process_sql(model, sql)
+ end
+ end
+ end
+
+ def process_sql(model, sql)
+ Gitlab::Database::QueryAnalyzer.instance.within do
+ # Skip load balancer and retrieve connection assigned to model
+ Gitlab::Database::QueryAnalyzer.instance.process_sql(sql, model.retrieve_connection)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb b/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb
new file mode 100644
index 00000000000..eb8ccb0bd89
--- /dev/null
+++ b/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb
@@ -0,0 +1,167 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification, query_analyzers: false do
+ let_it_be(:pipeline, refind: true) { create(:ci_pipeline) }
+ let_it_be(:project, refind: true) { create(:project) }
+
+ before do
+ allow(Gitlab::Database::QueryAnalyzer.instance).to receive(:all_analyzers).and_return([described_class])
+ end
+
+ around do |example|
+ Gitlab::Database::QueryAnalyzer.instance.within { example.run }
+ end
+
+ shared_examples 'successful examples' do
+ context 'outside transaction' do
+ it { expect { run_queries }.not_to raise_error }
+ end
+
+ context 'within transaction' do
+ it do
+ Project.transaction do
+ expect { run_queries }.not_to raise_error
+ end
+ end
+ end
+
+ context 'within nested transaction' do
+ it do
+ Project.transaction(requires_new: true) do
+ Project.transaction(requires_new: true) do
+ expect { run_queries }.not_to raise_error
+ end
+ end
+ end
+ end
+ end
+
+ context 'when CI and other tables are read in a transaction' do
+ def run_queries
+ pipeline.reload
+ project.reload
+ end
+
+ include_examples 'successful examples'
+ end
+
+ context 'when only CI data is modified' do
+ def run_queries
+ pipeline.touch
+ project.reload
+ end
+
+ include_examples 'successful examples'
+ end
+
+ context 'when other data is modified' do
+ def run_queries
+ pipeline.reload
+ project.touch
+ end
+
+ include_examples 'successful examples'
+ end
+
+ context 'when both CI and other data is modified' do
+ def run_queries
+ project.touch
+ pipeline.touch
+ end
+
+ context 'outside transaction' do
+ it { expect { run_queries }.not_to raise_error }
+ end
+
+ context 'when data modification happens in a transaction' do
+ it 'raises error' do
+ Project.transaction do
+ expect { run_queries }.to raise_error /Cross-database data modification/
+ end
+ end
+
+ context 'when data modification happens in nested transactions' do
+ it 'raises error' do
+ Project.transaction(requires_new: true) do
+ project.touch
+ Project.transaction(requires_new: true) do
+ expect { pipeline.touch }.to raise_error /Cross-database data modification/
+ end
+ end
+ end
+ end
+ end
+
+ context 'when executing a SELECT FOR UPDATE query' do
+ def run_queries
+ project.touch
+ pipeline.lock!
+ end
+
+ context 'outside transaction' do
+ it { expect { run_queries }.not_to raise_error }
+ end
+
+ context 'when data modification happens in a transaction' do
+ it 'raises error' do
+ Project.transaction do
+ expect { run_queries }.to raise_error /Cross-database data modification/
+ end
+ end
+
+ context 'when the modification is inside a factory save! call' do
+ let(:runner) { create(:ci_runner, :project, projects: [build(:project)]) }
+
+ it 'does not raise an error' do
+ runner
+ end
+ end
+ end
+ end
+
+ context 'when CI association is modified through project' do
+ def run_queries
+ project.variables.build(key: 'a', value: 'v')
+ project.save!
+ end
+
+ include_examples 'successful examples'
+ end
+
+ describe '.allow_cross_database_modification_within_transaction' do
+ it 'skips raising error' do
+ expect do
+ described_class.allow_cross_database_modification_within_transaction(url: 'gitlab-issue') do
+ Project.transaction do
+ pipeline.touch
+ project.touch
+ end
+ end
+ end.not_to raise_error
+ end
+
+ it 'skips raising error on factory creation' do
+ expect do
+ described_class.allow_cross_database_modification_within_transaction(url: 'gitlab-issue') do
+ ApplicationRecord.transaction do
+ create(:ci_pipeline)
+ end
+ end
+ end.not_to raise_error
+ end
+ end
+ end
+
+ context 'when some table with a defined schema and another table with undefined gitlab_schema is modified' do
+ it 'raises an error including including message about undefined schema' do
+ expect do
+ Project.transaction do
+ project.touch
+ project.connection.execute('UPDATE foo_bars_undefined_table SET a=1 WHERE id = -1')
+ end
+ end.to raise_error /Cross-database data modification.*The gitlab_schema was undefined/
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/reflection_spec.rb b/spec/lib/gitlab/database/reflection_spec.rb
new file mode 100644
index 00000000000..7c3d797817d
--- /dev/null
+++ b/spec/lib/gitlab/database/reflection_spec.rb
@@ -0,0 +1,280 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Reflection do
+ let(:database) { described_class.new(ApplicationRecord) }
+
+ describe '#username' do
+ context 'when a username is set' do
+ it 'returns the username' do
+ allow(database).to receive(:config).and_return(username: 'bob')
+
+ expect(database.username).to eq('bob')
+ end
+ end
+
+ context 'when a username is not set' do
+ it 'returns the value of the USER environment variable' do
+ allow(database).to receive(:config).and_return(username: nil)
+ allow(ENV).to receive(:[]).with('USER').and_return('bob')
+
+ expect(database.username).to eq('bob')
+ end
+ end
+ end
+
+ describe '#database_name' do
+ it 'returns the name of the database' do
+ allow(database).to receive(:config).and_return(database: 'test')
+
+ expect(database.database_name).to eq('test')
+ end
+ end
+
+ describe '#adapter_name' do
+ it 'returns the database adapter name' do
+ allow(database).to receive(:config).and_return(adapter: 'test')
+
+ expect(database.adapter_name).to eq('test')
+ end
+ end
+
+ describe '#human_adapter_name' do
+ context 'when the adapter is PostgreSQL' do
+ it 'returns PostgreSQL' do
+ allow(database).to receive(:config).and_return(adapter: 'postgresql')
+
+ expect(database.human_adapter_name).to eq('PostgreSQL')
+ end
+ end
+
+ context 'when the adapter is not PostgreSQL' do
+ it 'returns Unknown' do
+ allow(database).to receive(:config).and_return(adapter: 'kittens')
+
+ expect(database.human_adapter_name).to eq('Unknown')
+ end
+ end
+ end
+
+ describe '#postgresql?' do
+ context 'when using PostgreSQL' do
+ it 'returns true' do
+ allow(database).to receive(:adapter_name).and_return('PostgreSQL')
+
+ expect(database.postgresql?).to eq(true)
+ end
+ end
+
+ context 'when not using PostgreSQL' do
+ it 'returns false' do
+ allow(database).to receive(:adapter_name).and_return('MySQL')
+
+ expect(database.postgresql?).to eq(false)
+ end
+ end
+ end
+
+ describe '#db_read_only?' do
+ it 'detects a read-only database' do
+ allow(database.model.connection)
+ .to receive(:execute)
+ .with('SELECT pg_is_in_recovery()')
+ .and_return([{ "pg_is_in_recovery" => "t" }])
+
+ expect(database.db_read_only?).to be_truthy
+ end
+
+ it 'detects a read-only database' do
+ allow(database.model.connection)
+ .to receive(:execute)
+ .with('SELECT pg_is_in_recovery()')
+ .and_return([{ "pg_is_in_recovery" => true }])
+
+ expect(database.db_read_only?).to be_truthy
+ end
+
+ it 'detects a read-write database' do
+ allow(database.model.connection)
+ .to receive(:execute)
+ .with('SELECT pg_is_in_recovery()')
+ .and_return([{ "pg_is_in_recovery" => "f" }])
+
+ expect(database.db_read_only?).to be_falsey
+ end
+
+ it 'detects a read-write database' do
+ allow(database.model.connection)
+ .to receive(:execute)
+ .with('SELECT pg_is_in_recovery()')
+ .and_return([{ "pg_is_in_recovery" => false }])
+
+ expect(database.db_read_only?).to be_falsey
+ end
+ end
+
+ describe '#db_read_write?' do
+ it 'detects a read-only database' do
+ allow(database.model.connection)
+ .to receive(:execute)
+ .with('SELECT pg_is_in_recovery()')
+ .and_return([{ "pg_is_in_recovery" => "t" }])
+
+ expect(database.db_read_write?).to eq(false)
+ end
+
+ it 'detects a read-only database' do
+ allow(database.model.connection)
+ .to receive(:execute)
+ .with('SELECT pg_is_in_recovery()')
+ .and_return([{ "pg_is_in_recovery" => true }])
+
+ expect(database.db_read_write?).to eq(false)
+ end
+
+ it 'detects a read-write database' do
+ allow(database.model.connection)
+ .to receive(:execute)
+ .with('SELECT pg_is_in_recovery()')
+ .and_return([{ "pg_is_in_recovery" => "f" }])
+
+ expect(database.db_read_write?).to eq(true)
+ end
+
+ it 'detects a read-write database' do
+ allow(database.model.connection)
+ .to receive(:execute)
+ .with('SELECT pg_is_in_recovery()')
+ .and_return([{ "pg_is_in_recovery" => false }])
+
+ expect(database.db_read_write?).to eq(true)
+ end
+ end
+
+ describe '#version' do
+ around do |example|
+ database.instance_variable_set(:@version, nil)
+ example.run
+ database.instance_variable_set(:@version, nil)
+ end
+
+ context "on postgresql" do
+ it "extracts the version number" do
+ allow(database)
+ .to receive(:database_version)
+ .and_return("PostgreSQL 9.4.4 on x86_64-apple-darwin14.3.0")
+
+ expect(database.version).to eq '9.4.4'
+ end
+ end
+
+ it 'memoizes the result' do
+ count = ActiveRecord::QueryRecorder
+ .new { 2.times { database.version } }
+ .count
+
+ expect(count).to eq(1)
+ end
+ end
+
+ describe '#postgresql_minimum_supported_version?' do
+ it 'returns false when using PostgreSQL 10' do
+ allow(database).to receive(:version).and_return('10')
+
+ expect(database.postgresql_minimum_supported_version?).to eq(false)
+ end
+
+ it 'returns false when using PostgreSQL 11' do
+ allow(database).to receive(:version).and_return('11')
+
+ expect(database.postgresql_minimum_supported_version?).to eq(false)
+ end
+
+ it 'returns true when using PostgreSQL 12' do
+ allow(database).to receive(:version).and_return('12')
+
+ expect(database.postgresql_minimum_supported_version?).to eq(true)
+ end
+ end
+
+ describe '#cached_column_exists?' do
+ it 'only retrieves the data from the schema cache' do
+ database = described_class.new(Project)
+ queries = ActiveRecord::QueryRecorder.new do
+ 2.times do
+ expect(database.cached_column_exists?(:id)).to be_truthy
+ expect(database.cached_column_exists?(:bogus_column)).to be_falsey
+ end
+ end
+
+ expect(queries.count).to eq(0)
+ end
+ end
+
+ describe '#cached_table_exists?' do
+ it 'only retrieves the data from the schema cache' do
+ dummy = Class.new(ActiveRecord::Base) do
+ self.table_name = 'bogus_table_name'
+ end
+
+ queries = ActiveRecord::QueryRecorder.new do
+ 2.times do
+ expect(described_class.new(Project).cached_table_exists?).to be_truthy
+ expect(described_class.new(dummy).cached_table_exists?).to be_falsey
+ end
+ end
+
+ expect(queries.count).to eq(0)
+ end
+
+ it 'returns false when database does not exist' do
+ database = described_class.new(Project)
+
+ expect(database.model).to receive(:connection) do
+ raise ActiveRecord::NoDatabaseError, 'broken'
+ end
+
+ expect(database.cached_table_exists?).to be(false)
+ end
+ end
+
+ describe '#exists?' do
+ it 'returns true if the database exists' do
+ expect(database.exists?).to be(true)
+ end
+
+ it "returns false if the database doesn't exist" do
+ expect(database.model.connection.schema_cache)
+ .to receive(:database_version)
+ .and_raise(ActiveRecord::NoDatabaseError)
+
+ expect(database.exists?).to be(false)
+ end
+ end
+
+ describe '#system_id' do
+ it 'returns the PostgreSQL system identifier' do
+ expect(database.system_id).to be_an_instance_of(Integer)
+ end
+ end
+
+ describe '#config' do
+ it 'returns a HashWithIndifferentAccess' do
+ expect(database.config)
+ .to be_an_instance_of(HashWithIndifferentAccess)
+ end
+
+ it 'returns a default pool size' do
+ expect(database.config)
+ .to include(pool: Gitlab::Database.default_pool_size)
+ end
+
+ it 'does not cache its results' do
+ a = database.config
+ b = database.config
+
+ expect(a).not_to equal(b)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/reindexing/index_selection_spec.rb b/spec/lib/gitlab/database/reindexing/index_selection_spec.rb
index ee3f2b1b415..2ae9037959d 100644
--- a/spec/lib/gitlab/database/reindexing/index_selection_spec.rb
+++ b/spec/lib/gitlab/database/reindexing/index_selection_spec.rb
@@ -46,14 +46,14 @@ RSpec.describe Gitlab::Database::Reindexing::IndexSelection do
expect(subject).not_to include(excluded.index)
end
- it 'excludes indexes larger than 100 GB ondisk size' do
- excluded = create(
+ it 'includes indexes larger than 100 GB ondisk size' do
+ included = create(
:postgres_index_bloat_estimate,
index: create(:postgres_index, ondisk_size_bytes: 101.gigabytes),
bloat_size_bytes: 25.gigabyte
)
- expect(subject).not_to include(excluded.index)
+ expect(subject).to include(included.index)
end
context 'with time frozen' do
diff --git a/spec/lib/gitlab/database/reindexing/reindex_action_spec.rb b/spec/lib/gitlab/database/reindexing/reindex_action_spec.rb
index a8f196d8f0e..1b409924acc 100644
--- a/spec/lib/gitlab/database/reindexing/reindex_action_spec.rb
+++ b/spec/lib/gitlab/database/reindexing/reindex_action_spec.rb
@@ -11,6 +11,8 @@ RSpec.describe Gitlab::Database::Reindexing::ReindexAction do
swapout_view_for_table(:postgres_indexes)
end
+ it { is_expected.to be_a Gitlab::Database::SharedModel }
+
describe '.create_for' do
subject { described_class.create_for(index) }
diff --git a/spec/lib/gitlab/database/reindexing/reindex_concurrently_spec.rb b/spec/lib/gitlab/database/reindexing/reindex_concurrently_spec.rb
index 6f87475fc94..db267ff4f14 100644
--- a/spec/lib/gitlab/database/reindexing/reindex_concurrently_spec.rb
+++ b/spec/lib/gitlab/database/reindexing/reindex_concurrently_spec.rb
@@ -62,7 +62,7 @@ RSpec.describe Gitlab::Database::Reindexing::ReindexConcurrently, '#perform' do
it 'recreates the index using REINDEX with a long statement timeout' do
expect_to_execute_in_order(
- "SET statement_timeout TO '32400s'",
+ "SET statement_timeout TO '86400s'",
"REINDEX INDEX CONCURRENTLY \"public\".\"#{index.name}\"",
"RESET statement_timeout"
)
@@ -84,7 +84,7 @@ RSpec.describe Gitlab::Database::Reindexing::ReindexConcurrently, '#perform' do
it 'drops the dangling indexes while controlling lock_timeout' do
expect_to_execute_in_order(
# Regular index rebuild
- "SET statement_timeout TO '32400s'",
+ "SET statement_timeout TO '86400s'",
"REINDEX INDEX CONCURRENTLY \"public\".\"#{index_name}\"",
"RESET statement_timeout",
# Drop _ccnew index
diff --git a/spec/lib/gitlab/database/reindexing_spec.rb b/spec/lib/gitlab/database/reindexing_spec.rb
index 550f9db2b5b..13aff343432 100644
--- a/spec/lib/gitlab/database/reindexing_spec.rb
+++ b/spec/lib/gitlab/database/reindexing_spec.rb
@@ -4,10 +4,63 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Reindexing do
include ExclusiveLeaseHelpers
+ include Database::DatabaseHelpers
- describe '.perform' do
- subject { described_class.perform(candidate_indexes) }
+ describe '.automatic_reindexing' do
+ subject { described_class.automatic_reindexing(maximum_records: limit) }
+ let(:limit) { 5 }
+
+ before_all do
+ swapout_view_for_table(:postgres_indexes)
+ end
+
+ before do
+ allow(Gitlab::Database::Reindexing).to receive(:cleanup_leftovers!)
+ allow(Gitlab::Database::Reindexing).to receive(:perform_from_queue).and_return(0)
+ allow(Gitlab::Database::Reindexing).to receive(:perform_with_heuristic).and_return(0)
+ end
+
+ it 'cleans up leftovers, before consuming the queue' do
+ expect(Gitlab::Database::Reindexing).to receive(:cleanup_leftovers!).ordered
+ expect(Gitlab::Database::Reindexing).to receive(:perform_from_queue).ordered
+
+ subject
+ end
+
+ context 'with records in the queue' do
+ before do
+ create(:reindexing_queued_action)
+ end
+
+ context 'with enough records in the queue to reach limit' do
+ let(:limit) { 1 }
+
+ it 'does not perform reindexing with heuristic' do
+ expect(Gitlab::Database::Reindexing).to receive(:perform_from_queue).and_return(limit)
+ expect(Gitlab::Database::Reindexing).not_to receive(:perform_with_heuristic)
+
+ subject
+ end
+ end
+
+ context 'without enough records in the queue to reach limit' do
+ let(:limit) { 2 }
+
+ it 'continues if the queue did not have enough records' do
+ expect(Gitlab::Database::Reindexing).to receive(:perform_from_queue).ordered.and_return(1)
+ expect(Gitlab::Database::Reindexing).to receive(:perform_with_heuristic).with(maximum_records: 1).ordered
+
+ subject
+ end
+ end
+ end
+ end
+
+ describe '.perform_with_heuristic' do
+ subject { described_class.perform_with_heuristic(candidate_indexes, maximum_records: limit) }
+
+ let(:limit) { 2 }
let(:coordinator) { instance_double(Gitlab::Database::Reindexing::Coordinator) }
let(:index_selection) { instance_double(Gitlab::Database::Reindexing::IndexSelection) }
let(:candidate_indexes) { double }
@@ -15,7 +68,7 @@ RSpec.describe Gitlab::Database::Reindexing do
it 'delegates to Coordinator' do
expect(Gitlab::Database::Reindexing::IndexSelection).to receive(:new).with(candidate_indexes).and_return(index_selection)
- expect(index_selection).to receive(:take).with(2).and_return(indexes)
+ expect(index_selection).to receive(:take).with(limit).and_return(indexes)
indexes.each do |index|
expect(Gitlab::Database::Reindexing::Coordinator).to receive(:new).with(index).and_return(coordinator)
@@ -26,6 +79,59 @@ RSpec.describe Gitlab::Database::Reindexing do
end
end
+ describe '.perform_from_queue' do
+ subject { described_class.perform_from_queue(maximum_records: limit) }
+
+ before_all do
+ swapout_view_for_table(:postgres_indexes)
+ end
+
+ let(:limit) { 2 }
+ let(:queued_actions) { create_list(:reindexing_queued_action, 3) }
+ let(:coordinator) { instance_double(Gitlab::Database::Reindexing::Coordinator) }
+
+ before do
+ queued_actions.take(limit).each do |action|
+ allow(Gitlab::Database::Reindexing::Coordinator).to receive(:new).with(action.index).and_return(coordinator)
+ allow(coordinator).to receive(:perform)
+ end
+ end
+
+ it 'consumes the queue in order of created_at and applies the limit' do
+ queued_actions.take(limit).each do |action|
+ expect(Gitlab::Database::Reindexing::Coordinator).to receive(:new).ordered.with(action.index).and_return(coordinator)
+ expect(coordinator).to receive(:perform)
+ end
+
+ subject
+ end
+
+ it 'updates queued action and sets state to done' do
+ subject
+
+ queue = queued_actions
+
+ queue.shift(limit).each do |action|
+ expect(action.reload.state).to eq('done')
+ end
+
+ queue.each do |action|
+ expect(action.reload.state).to eq('queued')
+ end
+ end
+
+ it 'updates queued action upon error and sets state to failed' do
+ expect(Gitlab::Database::Reindexing::Coordinator).to receive(:new).ordered.with(queued_actions.first.index).and_return(coordinator)
+ expect(coordinator).to receive(:perform).and_raise('something went wrong')
+
+ subject
+
+ states = queued_actions.map(&:reload).map(&:state)
+
+ expect(states).to eq(%w(failed done queued))
+ end
+ end
+
describe '.cleanup_leftovers!' do
subject { described_class.cleanup_leftovers! }
diff --git a/spec/lib/gitlab/database/schema_cache_with_renamed_table_spec.rb b/spec/lib/gitlab/database/schema_cache_with_renamed_table_spec.rb
index 8c0c4155ccc..7caee414719 100644
--- a/spec/lib/gitlab/database/schema_cache_with_renamed_table_spec.rb
+++ b/spec/lib/gitlab/database/schema_cache_with_renamed_table_spec.rb
@@ -11,12 +11,12 @@ RSpec.describe Gitlab::Database::SchemaCacheWithRenamedTable do
let(:new_model) do
Class.new(ActiveRecord::Base) do
- self.table_name = 'projects_new'
+ self.table_name = '_test_projects_new'
end
end
before do
- stub_const('Gitlab::Database::TABLES_TO_BE_RENAMED', { 'projects' => 'projects_new' })
+ stub_const('Gitlab::Database::TABLES_TO_BE_RENAMED', { 'projects' => '_test_projects_new' })
end
context 'when table is not renamed yet' do
@@ -32,8 +32,8 @@ RSpec.describe Gitlab::Database::SchemaCacheWithRenamedTable do
context 'when table is renamed' do
before do
- ActiveRecord::Base.connection.execute("ALTER TABLE projects RENAME TO projects_new")
- ActiveRecord::Base.connection.execute("CREATE VIEW projects AS SELECT * FROM projects_new")
+ ActiveRecord::Base.connection.execute("ALTER TABLE projects RENAME TO _test_projects_new")
+ ActiveRecord::Base.connection.execute("CREATE VIEW projects AS SELECT * FROM _test_projects_new")
old_model.reset_column_information
ActiveRecord::Base.connection.schema_cache.clear!
@@ -54,14 +54,14 @@ RSpec.describe Gitlab::Database::SchemaCacheWithRenamedTable do
it 'has the same indexes' do
indexes_for_old_table = ActiveRecord::Base.connection.schema_cache.indexes('projects')
- indexes_for_new_table = ActiveRecord::Base.connection.schema_cache.indexes('projects_new')
+ indexes_for_new_table = ActiveRecord::Base.connection.schema_cache.indexes('_test_projects_new')
expect(indexes_for_old_table).to eq(indexes_for_new_table)
end
it 'has the same column_hash' do
columns_hash_for_old_table = ActiveRecord::Base.connection.schema_cache.columns_hash('projects')
- columns_hash_for_new_table = ActiveRecord::Base.connection.schema_cache.columns_hash('projects_new')
+ columns_hash_for_new_table = ActiveRecord::Base.connection.schema_cache.columns_hash('_test_projects_new')
expect(columns_hash_for_old_table).to eq(columns_hash_for_new_table)
end
diff --git a/spec/lib/gitlab/database/schema_migrations/context_spec.rb b/spec/lib/gitlab/database/schema_migrations/context_spec.rb
index 0323fa22b78..07c97ea0ec3 100644
--- a/spec/lib/gitlab/database/schema_migrations/context_spec.rb
+++ b/spec/lib/gitlab/database/schema_migrations/context_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Gitlab::Database::SchemaMigrations::Context do
end
context 'CI database' do
- let(:connection_class) { Ci::CiDatabaseRecord }
+ let(:connection_class) { Ci::ApplicationRecord }
it 'returns a directory path that is database specific' do
skip_if_multiple_databases_not_setup
diff --git a/spec/lib/gitlab/database/shared_model_spec.rb b/spec/lib/gitlab/database/shared_model_spec.rb
index 5d616aeb05f..94f2b5a3434 100644
--- a/spec/lib/gitlab/database/shared_model_spec.rb
+++ b/spec/lib/gitlab/database/shared_model_spec.rb
@@ -27,6 +27,38 @@ RSpec.describe Gitlab::Database::SharedModel do
end
end
+ context 'when multiple connection overrides are nested', :aggregate_failures do
+ let(:second_connection) { double('connection') }
+
+ it 'allows the nesting with the same connection object' do
+ expect_original_connection_around do
+ described_class.using_connection(new_connection) do
+ expect(described_class.connection).to be(new_connection)
+
+ described_class.using_connection(new_connection) do
+ expect(described_class.connection).to be(new_connection)
+ end
+
+ expect(described_class.connection).to be(new_connection)
+ end
+ end
+ end
+
+ it 'raises an error if the connection is changed' do
+ expect_original_connection_around do
+ described_class.using_connection(new_connection) do
+ expect(described_class.connection).to be(new_connection)
+
+ expect do
+ described_class.using_connection(second_connection) {}
+ end.to raise_error(/cannot nest connection overrides/)
+
+ expect(described_class.connection).to be(new_connection)
+ end
+ end
+ end
+ end
+
context 'when the block raises an error', :aggregate_failures do
it 're-raises the error, removing the overridden connection' do
expect_original_connection_around do
diff --git a/spec/lib/gitlab/database/unidirectional_copy_trigger_spec.rb b/spec/lib/gitlab/database/unidirectional_copy_trigger_spec.rb
index 2955c208f16..bbddb5f1af5 100644
--- a/spec/lib/gitlab/database/unidirectional_copy_trigger_spec.rb
+++ b/spec/lib/gitlab/database/unidirectional_copy_trigger_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Gitlab::Database::UnidirectionalCopyTrigger do
let(:table_name) { '_test_table' }
let(:connection) { ActiveRecord::Base.connection }
- let(:copy_trigger) { described_class.on_table(table_name) }
+ let(:copy_trigger) { described_class.on_table(table_name, connection: connection) }
describe '#name' do
context 'when a single column name is given' do
diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb
index a2e7b6d27b9..5ec7c338a2a 100644
--- a/spec/lib/gitlab/database_spec.rb
+++ b/spec/lib/gitlab/database_spec.rb
@@ -15,13 +15,6 @@ RSpec.describe Gitlab::Database do
end
end
- describe '.databases' do
- it 'stores connections as a HashWithIndifferentAccess' do
- expect(described_class.databases.has_key?('main')).to be true
- expect(described_class.databases.has_key?(:main)).to be true
- end
- end
-
describe '.default_pool_size' do
before do
allow(Gitlab::Runtime).to receive(:max_threads).and_return(7)
@@ -112,18 +105,30 @@ RSpec.describe Gitlab::Database do
end
describe '.check_postgres_version_and_print_warning' do
+ let(:reflect) { instance_spy(Gitlab::Database::Reflection) }
+
subject { described_class.check_postgres_version_and_print_warning }
+ before do
+ allow(Gitlab::Database::Reflection)
+ .to receive(:new)
+ .and_return(reflect)
+ end
+
it 'prints a warning if not compliant with minimum postgres version' do
- allow(described_class.main).to receive(:postgresql_minimum_supported_version?).and_return(false)
+ allow(reflect).to receive(:postgresql_minimum_supported_version?).and_return(false)
- expect(Kernel).to receive(:warn).with(/You are using PostgreSQL/)
+ expect(Kernel)
+ .to receive(:warn)
+ .with(/You are using PostgreSQL/)
+ .exactly(Gitlab::Database.database_base_models.length)
+ .times
subject
end
it 'doesnt print a warning if compliant with minimum postgres version' do
- allow(described_class.main).to receive(:postgresql_minimum_supported_version?).and_return(true)
+ allow(reflect).to receive(:postgresql_minimum_supported_version?).and_return(true)
expect(Kernel).not_to receive(:warn).with(/You are using PostgreSQL/)
@@ -131,7 +136,7 @@ RSpec.describe Gitlab::Database do
end
it 'doesnt print a warning in Rails runner environment' do
- allow(described_class.main).to receive(:postgresql_minimum_supported_version?).and_return(false)
+ allow(reflect).to receive(:postgresql_minimum_supported_version?).and_return(false)
allow(Gitlab::Runtime).to receive(:rails_runner?).and_return(true)
expect(Kernel).not_to receive(:warn).with(/You are using PostgreSQL/)
@@ -140,13 +145,13 @@ RSpec.describe Gitlab::Database do
end
it 'ignores ActiveRecord errors' do
- allow(described_class.main).to receive(:postgresql_minimum_supported_version?).and_raise(ActiveRecord::ActiveRecordError)
+ allow(reflect).to receive(:postgresql_minimum_supported_version?).and_raise(ActiveRecord::ActiveRecordError)
expect { subject }.not_to raise_error
end
it 'ignores Postgres errors' do
- allow(described_class.main).to receive(:postgresql_minimum_supported_version?).and_raise(PG::Error)
+ allow(reflect).to receive(:postgresql_minimum_supported_version?).and_raise(PG::Error)
expect { subject }.not_to raise_error
end
@@ -205,7 +210,7 @@ RSpec.describe Gitlab::Database do
context 'when replicas are configured', :database_replica do
it 'returns the name for a replica' do
- replica = ActiveRecord::Base.connection.load_balancer.host
+ replica = ActiveRecord::Base.load_balancer.host
expect(described_class.db_config_name(replica)).to eq('main_replica')
end
diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb
index 1800d2d6b60..4b437397688 100644
--- a/spec/lib/gitlab/diff/file_spec.rb
+++ b/spec/lib/gitlab/diff/file_spec.rb
@@ -51,6 +51,48 @@ RSpec.describe Gitlab::Diff::File do
project.commit(branch_name).diffs.diff_files.first
end
+ describe 'initialize' do
+ context 'when file is ipynb with a change after transformation' do
+ let(:commit) { project.commit("f6b7a707") }
+ let(:diff) { commit.raw_diffs.first }
+ let(:diff_file) { described_class.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }
+
+ context 'and :jupyter_clean_diffs is enabled' do
+ before do
+ stub_feature_flags(jupyter_clean_diffs: true)
+ end
+
+ it 'recreates the diff by transforming the files' do
+ expect(diff_file.diff.diff).not_to include('"| Fake')
+ end
+ end
+
+ context 'but :jupyter_clean_diffs is disabled' do
+ before do
+ stub_feature_flags(jupyter_clean_diffs: false)
+ end
+
+ it 'does not recreate the diff' do
+ expect(diff_file.diff.diff).to include('"| Fake')
+ end
+ end
+ end
+
+ context 'when file is ipynb, but there only changes that are removed' do
+ let(:commit) { project.commit("2b5ef814") }
+ let(:diff) { commit.raw_diffs.first }
+ let(:diff_file) { described_class.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }
+
+ before do
+ stub_feature_flags(jupyter_clean_diffs: true)
+ end
+
+ it 'does not recreate the diff' do
+ expect(diff_file.diff.diff).to include('execution_count')
+ end
+ end
+ end
+
describe '#diff_lines' do
let(:diff_lines) { diff_file.diff_lines }
diff --git a/spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb b/spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb
index bdeaabec1f1..b646cf38178 100644
--- a/spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb
+++ b/spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb
@@ -581,13 +581,16 @@ RSpec.describe Gitlab::Diff::PositionTracer::LineStrategy, :clean_gitlab_redis_c
)
end
- it "returns the new position but drops line_range information" do
+ it "returns the new position" do
expect_change_position(
old_path: file_name,
new_path: file_name,
old_line: nil,
new_line: 2,
- line_range: nil
+ line_range: {
+ "start_line_code" => 1,
+ "end_line_code" => 2
+ }
)
end
end
diff --git a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
index 8cb1ccc065b..c579027788d 100644
--- a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
end
let(:email_raw) { email_fixture('emails/service_desk.eml') }
+ let(:author_email) { 'jake@adventuretime.ooo' }
let_it_be(:group) { create(:group, :private, name: "email") }
let(:expected_description) do
@@ -45,7 +46,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
receiver.execute
new_issue = Issue.last
- expect(new_issue.issue_email_participants.first.email).to eq("jake@adventuretime.ooo")
+ expect(new_issue.issue_email_participants.first.email).to eq(author_email)
end
it 'sends thank you email' do
@@ -196,60 +197,123 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
end
end
- context 'when using service desk key' do
- let_it_be(:service_desk_key) { 'mykey' }
+ context 'when all lines of email are quoted' do
+ let(:email_raw) { email_fixture('emails/service_desk_all_quoted.eml') }
- let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml') }
+ it 'creates email with correct body' do
+ receiver.execute
+
+ issue = Issue.last
+ expect(issue.description).to include('> This is an empty quote')
+ end
+ end
+
+ context 'when using custom service desk address' do
let(:receiver) { Gitlab::Email::ServiceDeskReceiver.new(email_raw) }
before do
stub_service_desk_email_setting(enabled: true, address: 'support+%{key}@example.com')
end
- before_all do
- create(:service_desk_setting, project: project, project_key: service_desk_key)
- end
+ context 'when using project key' do
+ let_it_be(:service_desk_key) { 'mykey' }
- it_behaves_like 'a new issue request'
+ let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml') }
+
+ before_all do
+ create(:service_desk_setting, project: project, project_key: service_desk_key)
+ end
+
+ it_behaves_like 'a new issue request'
+
+ context 'when there is no project with the key' do
+ let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml', key: 'some_key') }
+
+ it 'bounces the email' do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
+ end
+ end
+
+ context 'when the project slug does not match' do
+ let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml', slug: 'some-slug') }
+
+ it 'bounces the email' do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
+ end
+ end
+
+ context 'when there are multiple projects with same key' do
+ let_it_be(:project_with_same_key) { create(:project, group: group, service_desk_enabled: true) }
+
+ let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml', slug: project_with_same_key.full_path_slug.to_s) }
- context 'when there is no project with the key' do
- let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml', key: 'some_key') }
+ before do
+ create(:service_desk_setting, project: project_with_same_key, project_key: service_desk_key)
+ end
- it 'bounces the email' do
- expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
+ it 'process email for project with matching slug' do
+ expect { receiver.execute }.to change { Issue.count }.by(1)
+ expect(Issue.last.project).to eq(project_with_same_key)
+ end
end
end
- context 'when the project slug does not match' do
- let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml', slug: 'some-slug') }
+ context 'when project key is not set' do
+ let(:email_raw) { email_fixture('emails/service_desk_custom_address_no_key.eml') }
- it 'bounces the email' do
- expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
+ before do
+ stub_service_desk_email_setting(enabled: true, address: 'support+%{key}@example.com')
end
+
+ it_behaves_like 'a new issue request'
end
+ end
+ end
- context 'when there are multiple projects with same key' do
- let_it_be(:project_with_same_key) { create(:project, group: group, service_desk_enabled: true) }
+ context 'when rate limiting is in effect', :freeze_time, :clean_gitlab_redis_rate_limiting do
+ let(:receiver) { Gitlab::Email::Receiver.new(email_raw) }
- let(:email_raw) { service_desk_fixture('emails/service_desk_custom_address.eml', slug: project_with_same_key.full_path_slug.to_s) }
+ subject { 2.times { receiver.execute } }
- before do
- create(:service_desk_setting, project: project_with_same_key, project_key: service_desk_key)
+ before do
+ stub_feature_flags(rate_limited_service_issues_create: true)
+ stub_application_setting(issues_create_limit: 1)
+ end
+
+ context 'when too many requests are sent by one user' do
+ it 'raises an error' do
+ expect { subject }.to raise_error(RateLimitedService::RateLimitedError)
+ end
+
+ it 'creates 1 issue' do
+ expect do
+ subject
+ rescue RateLimitedService::RateLimitedError
+ end.to change { Issue.count }.by(1)
+ end
+
+ context 'when requests are sent by different users' do
+ let(:email_raw_2) { email_fixture('emails/service_desk_forwarded.eml') }
+ let(:receiver2) { Gitlab::Email::Receiver.new(email_raw_2) }
+
+ subject do
+ receiver.execute
+ receiver2.execute
end
- it 'process email for project with matching slug' do
- expect { receiver.execute }.to change { Issue.count }.by(1)
- expect(Issue.last.project).to eq(project_with_same_key)
+ it 'creates 2 issues' do
+ expect { subject }.to change { Issue.count }.by(2)
end
end
end
- context 'when rate limiting is in effect' do
- it 'allows unlimited new issue creation' do
- stub_application_setting(issues_create_limit: 1)
- setup_attachment
+ context 'when limit is higher than sent emails' do
+ before do
+ stub_application_setting(issues_create_limit: 2)
+ end
- expect { 2.times { receiver.execute } }.to change { Issue.count }.by(2)
+ it 'creates 2 issues' do
+ expect { subject }.to change { Issue.count }.by(2)
end
end
end
@@ -323,6 +387,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
end
context 'when the email is forwarded through an alias' do
+ let(:author_email) { 'jake.g@adventuretime.ooo' }
let(:email_raw) { email_fixture('emails/service_desk_forwarded.eml') }
it_behaves_like 'a new issue request'
diff --git a/spec/lib/gitlab/email/hook/smime_signature_interceptor_spec.rb b/spec/lib/gitlab/email/hook/smime_signature_interceptor_spec.rb
index 0a1f04ed793..352eb596cd9 100644
--- a/spec/lib/gitlab/email/hook/smime_signature_interceptor_spec.rb
+++ b/spec/lib/gitlab/email/hook/smime_signature_interceptor_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Gitlab::Email::Hook::SmimeSignatureInterceptor do
end
before do
- allow(Gitlab::X509::Certificate).to receive_messages(from_files: certificate)
+ allow(Gitlab::Email::Hook::SmimeSignatureInterceptor).to receive(:certificate).and_return(certificate)
Mail.register_interceptor(described_class)
mail.deliver_now
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/base_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/base_spec.rb
index 277f1158f8b..0521123f1ef 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/base_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/base_spec.rb
@@ -82,4 +82,29 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Base do
it { is_expected.to include('This is email 1 of 3 in the Create series', Gitlab::Routing.url_helpers.profile_notifications_url) }
end
end
+
+ describe '#series?' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject do
+ test_class = "Gitlab::Email::Message::InProductMarketing::#{track.to_s.classify}".constantize
+ test_class.new(group: group, user: user, series: series).series?
+ end
+
+ where(:track, :result) do
+ :create | true
+ :team_short | true
+ :trial_short | true
+ :admin_verify | true
+ :verify | true
+ :trial | true
+ :team | true
+ :experience | true
+ :invite_team | false
+ end
+
+ with_them do
+ it { is_expected.to eq result }
+ end
+ end
end
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/experience_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/experience_spec.rb
index b742eff3f56..8cd2345822e 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/experience_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/experience_spec.rb
@@ -22,14 +22,36 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Experience do
expect(message.cta_text).to be_nil
end
- describe '#feedback_link' do
- let(:member_count) { 2 }
+ describe 'feedback URL' do
+ before do
+ allow(message).to receive(:onboarding_progress).and_return(1)
+ allow(message).to receive(:show_invite_link).and_return(true)
+ end
+
+ subject do
+ message.feedback_link(1)
+ end
+
+ it { is_expected.to start_with(Gitlab::Saas.com_url) }
+
+ context 'when in development' do
+ let(:root_url) { 'http://example.com' }
+
+ before do
+ allow(message).to receive(:root_url).and_return(root_url)
+ stub_rails_env('development')
+ end
+
+ it { is_expected.to start_with(root_url) }
+ end
+ end
+
+ describe 'feedback URL show_invite_link query param' do
let(:user_access) { GroupMember::DEVELOPER }
let(:preferred_language) { 'en' }
before do
allow(message).to receive(:onboarding_progress).and_return(1)
- allow(group).to receive(:member_count).and_return(member_count)
allow(group).to receive(:max_member_access_for_user).and_return(user_access)
allow(user).to receive(:preferred_language).and_return(preferred_language)
end
@@ -41,12 +63,6 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Experience do
it { is_expected.to eq('true') }
- context 'with only one member' do
- let(:member_count) { 1 }
-
- it { is_expected.to eq('false') }
- end
-
context 'with less than developer access' do
let(:user_access) { GroupMember::GUEST }
@@ -59,6 +75,41 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Experience do
it { is_expected.to eq('false') }
end
end
+
+ describe 'feedback URL show_incentive query param' do
+ let(:show_invite_link) { true }
+ let(:member_count) { 2 }
+ let(:query) do
+ uri = URI.parse(message.feedback_link(1))
+ Rack::Utils.parse_query(uri.query).with_indifferent_access
+ end
+
+ before do
+ allow(message).to receive(:onboarding_progress).and_return(1)
+ allow(message).to receive(:show_invite_link).and_return(show_invite_link)
+ allow(group).to receive(:member_count).and_return(member_count)
+ end
+
+ subject { query[:show_incentive] }
+
+ it { is_expected.to eq('true') }
+
+ context 'with only one member' do
+ let(:member_count) { 1 }
+
+ it "is not present" do
+ expect(query).not_to have_key(:show_incentive)
+ end
+ end
+
+ context 'show_invite_link is false' do
+ let(:show_invite_link) { false }
+
+ it "is not present" do
+ expect(query).not_to have_key(:show_incentive)
+ end
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/invite_team_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/invite_team_spec.rb
new file mode 100644
index 00000000000..8319560f594
--- /dev/null
+++ b/spec/lib/gitlab/email/message/in_product_marketing/invite_team_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Email::Message::InProductMarketing::InviteTeam do
+ let_it_be(:group) { build(:group) }
+ let_it_be(:user) { build(:user) }
+
+ let(:series) { 0 }
+
+ subject(:message) { described_class.new(group: group, user: user, series: series) }
+
+ describe 'initialize' do
+ context 'when series is valid' do
+ it 'does not raise error' do
+ expect { subject }.not_to raise_error(ArgumentError)
+ end
+ end
+
+ context 'when series is invalid' do
+ let(:series) { 1 }
+
+ it 'raises error' do
+ expect { subject }.to raise_error(ArgumentError)
+ end
+ end
+ end
+
+ it 'contains the correct message', :aggregate_failures do
+ expect(message.subject_line).to eq 'Invite your teammates to GitLab'
+ expect(message.tagline).to be_empty
+ expect(message.title).to eq 'GitLab is better with teammates to help out!'
+ expect(message.subtitle).to be_empty
+ expect(message.body_line1).to eq 'Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running.'
+ expect(message.body_line2).to be_empty
+ expect(message.cta_text).to eq 'Invite your teammates to help'
+ expect(message.logo_path).to eq 'mailers/in_product_marketing/team-0.png'
+ end
+end
diff --git a/spec/lib/gitlab/email/message/in_product_marketing_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing_spec.rb
index 9ffc4a340a3..594df7440bb 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing_spec.rb
@@ -10,10 +10,15 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing do
context 'when track exists' do
where(:track, :expected_class) do
- :create | described_class::Create
- :verify | described_class::Verify
- :trial | described_class::Trial
- :team | described_class::Team
+ :create | described_class::Create
+ :team_short | described_class::TeamShort
+ :trial_short | described_class::TrialShort
+ :admin_verify | described_class::AdminVerify
+ :verify | described_class::Verify
+ :trial | described_class::Trial
+ :team | described_class::Team
+ :experience | described_class::Experience
+ :invite_team | described_class::InviteTeam
end
with_them do
diff --git a/spec/lib/gitlab/email/reply_parser_spec.rb b/spec/lib/gitlab/email/reply_parser_spec.rb
index 3b01b568fb4..c0d177aff4d 100644
--- a/spec/lib/gitlab/email/reply_parser_spec.rb
+++ b/spec/lib/gitlab/email/reply_parser_spec.rb
@@ -21,6 +21,30 @@ RSpec.describe Gitlab::Email::ReplyParser do
expect(test_parse_body(fixture_file("emails/no_content_reply.eml"))).to eq("")
end
+ context 'when allow_only_quotes is true' do
+ it "returns quoted text from email" do
+ text = test_parse_body(fixture_file("emails/no_content_reply.eml"), allow_only_quotes: true)
+
+ expect(text).to eq(
+ <<-BODY.strip_heredoc.chomp
+ >
+ >
+ >
+ > eviltrout posted in 'Adventure Time Sux' on Discourse Meta:
+ >
+ > ---
+ > hey guys everyone knows adventure time sucks!
+ >
+ > ---
+ > Please visit this link to respond: http://localhost:3000/t/adventure-time-sux/1234/3
+ >
+ > To unsubscribe from these emails, visit your [user preferences](http://localhost:3000/user_preferences).
+ >
+ BODY
+ )
+ end
+ end
+
it "properly renders plaintext-only email" do
expect(test_parse_body(fixture_file("emails/plaintext_only.eml")))
.to eq(
diff --git a/spec/lib/gitlab/emoji_spec.rb b/spec/lib/gitlab/emoji_spec.rb
index 8f855489c12..0db3b5f3b11 100644
--- a/spec/lib/gitlab/emoji_spec.rb
+++ b/spec/lib/gitlab/emoji_spec.rb
@@ -3,90 +3,6 @@
require 'spec_helper'
RSpec.describe Gitlab::Emoji do
- let_it_be(:emojis) { Gemojione.index.instance_variable_get(:@emoji_by_name) }
- let_it_be(:emojis_by_moji) { Gemojione.index.instance_variable_get(:@emoji_by_moji) }
- let_it_be(:emoji_unicode_versions_by_name) { Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'emoji-unicode-version-map.json'))) }
- let_it_be(:emojis_aliases) { Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'aliases.json'))) }
-
- describe '.emojis' do
- it 'returns emojis' do
- current_emojis = described_class.emojis
-
- expect(current_emojis).to eq(emojis)
- end
- end
-
- describe '.emojis_by_moji' do
- it 'return emojis by moji' do
- current_emojis_by_moji = described_class.emojis_by_moji
-
- expect(current_emojis_by_moji).to eq(emojis_by_moji)
- end
- end
-
- describe '.emojis_unicodes' do
- it 'returns emoji unicodes' do
- emoji_keys = described_class.emojis_unicodes
-
- expect(emoji_keys).to eq(emojis_by_moji.keys)
- end
- end
-
- describe '.emojis_names' do
- it 'returns emoji names' do
- emoji_names = described_class.emojis_names
-
- expect(emoji_names).to eq(emojis.keys)
- end
- end
-
- describe '.emojis_aliases' do
- it 'returns emoji aliases' do
- emoji_aliases = described_class.emojis_aliases
-
- expect(emoji_aliases).to eq(emojis_aliases)
- end
- end
-
- describe '.emoji_filename' do
- it 'returns emoji filename' do
- # "100" => {"unicode"=>"1F4AF"...}
- emoji_filename = described_class.emoji_filename('100')
-
- expect(emoji_filename).to eq(emojis['100']['unicode'])
- end
- end
-
- describe '.emoji_unicode_filename' do
- it 'returns emoji unicode filename' do
- emoji_unicode_filename = described_class.emoji_unicode_filename('💯')
-
- expect(emoji_unicode_filename).to eq(emojis_by_moji['💯']['unicode'])
- end
- end
-
- describe '.emoji_unicode_version' do
- it 'returns emoji unicode version by name' do
- emoji_unicode_version = described_class.emoji_unicode_version('100')
-
- expect(emoji_unicode_version).to eq(emoji_unicode_versions_by_name['100'])
- end
- end
-
- describe '.normalize_emoji_name' do
- it 'returns same name if not found in aliases' do
- emoji_name = described_class.normalize_emoji_name('random')
-
- expect(emoji_name).to eq('random')
- end
-
- it 'returns name if name found in aliases' do
- emoji_name = described_class.normalize_emoji_name('small_airplane')
-
- expect(emoji_name).to eq(emojis_aliases['small_airplane'])
- end
- end
-
describe '.emoji_image_tag' do
it 'returns emoji image tag' do
emoji_image = described_class.emoji_image_tag('emoji_one', 'src_url')
@@ -104,29 +20,17 @@ RSpec.describe Gitlab::Emoji do
end
end
- describe '.emoji_exists?' do
- it 'returns true if the name exists' do
- emoji_exists = described_class.emoji_exists?('100')
-
- expect(emoji_exists).to be_truthy
- end
-
- it 'returns false if the name does not exist' do
- emoji_exists = described_class.emoji_exists?('random')
-
- expect(emoji_exists).to be_falsey
- end
- end
-
describe '.gl_emoji_tag' do
it 'returns gl emoji tag if emoji is found' do
- gl_tag = described_class.gl_emoji_tag('small_airplane')
+ emoji = TanukiEmoji.find_by_alpha_code('small_airplane')
+ gl_tag = described_class.gl_emoji_tag(emoji)
expect(gl_tag).to eq('<gl-emoji title="small airplane" data-name="airplane_small" data-unicode-version="7.0">🛩</gl-emoji>')
end
- it 'returns nil if emoji name is not found' do
- gl_tag = described_class.gl_emoji_tag('random')
+ it 'returns nil if emoji is not found' do
+ emoji = TanukiEmoji.find_by_alpha_code('random')
+ gl_tag = described_class.gl_emoji_tag(emoji)
expect(gl_tag).to be_nil
end
diff --git a/spec/lib/gitlab/etag_caching/middleware_spec.rb b/spec/lib/gitlab/etag_caching/middleware_spec.rb
index c4da89e5f5c..982c0d911bc 100644
--- a/spec/lib/gitlab/etag_caching/middleware_spec.rb
+++ b/spec/lib/gitlab/etag_caching/middleware_spec.rb
@@ -174,7 +174,7 @@ RSpec.describe Gitlab::EtagCaching::Middleware, :clean_gitlab_redis_shared_state
it "pushes route's feature category to the context" do
expect(Gitlab::ApplicationContext).to receive(:push).with(
- feature_category: 'issue_tracking'
+ feature_category: 'team_planning'
)
_, _, _ = middleware.call(build_request(path, if_none_match))
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index f4dba5e8d58..11510daf9c0 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -715,6 +715,14 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
it { is_expected.not_to include("feature") }
end
+ describe '#first_ref_by_oid' do
+ let(:commit) { described_class.find(repository, 'master') }
+
+ subject { commit.first_ref_by_oid(repository) }
+
+ it { is_expected.to eq("master") }
+ end
+
describe '.get_message' do
let(:commit_ids) { %w[6d394385cf567f80a8fd85055db1ab4c5295806f cfe32cf61b73a0d5e9f13e774abde7ff789b1660] }
diff --git a/spec/lib/gitlab/git/object_pool_spec.rb b/spec/lib/gitlab/git/object_pool_spec.rb
index e1873c6ddb5..91960ebbede 100644
--- a/spec/lib/gitlab/git/object_pool_spec.rb
+++ b/spec/lib/gitlab/git/object_pool_spec.rb
@@ -112,7 +112,7 @@ RSpec.describe Gitlab::Git::ObjectPool do
subject.fetch
- expect(subject.repository.commit_count('refs/remotes/origin/master')).to eq(commit_count)
+ expect(subject.repository.commit_count('refs/remotes/origin/heads/master')).to eq(commit_count)
expect(subject.repository.commit(new_commit_id).id).to eq(new_commit_id)
end
end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index c7b68ff3e28..f1b6a59abf9 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -125,7 +125,22 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
it 'gets tags from GitalyClient' do
expect_next_instance_of(Gitlab::GitalyClient::RefService) do |service|
- expect(service).to receive(:tags).with(sort_by: 'name_asc')
+ expect(service).to receive(:tags).with(sort_by: 'name_asc', pagination_params: nil)
+ end
+
+ subject
+ end
+ end
+
+ context 'with pagination option' do
+ subject { repository.tags(pagination_params: { limit: 5, page_token: 'refs/tags/v1.0.0' }) }
+
+ it 'gets tags from GitalyClient' do
+ expect_next_instance_of(Gitlab::GitalyClient::RefService) do |service|
+ expect(service).to receive(:tags).with(
+ sort_by: nil,
+ pagination_params: { limit: 5, page_token: 'refs/tags/v1.0.0' }
+ )
end
subject
@@ -1888,6 +1903,44 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end
end
+ describe '#list_refs' do
+ it 'returns a list of branches with their head commit' do
+ refs = repository.list_refs
+ reference = refs.first
+
+ expect(refs).to be_an(Enumerable)
+ expect(reference).to be_a(Gitaly::ListRefsResponse::Reference)
+ expect(reference.name).to be_a(String)
+ expect(reference.target).to be_a(String)
+ end
+ end
+
+ describe '#refs_by_oid' do
+ it 'returns a list of refs from a OID' do
+ refs = repository.refs_by_oid(oid: repository.commit.id)
+
+ expect(refs).to be_an(Array)
+ expect(refs).to include(Gitlab::Git::BRANCH_REF_PREFIX + repository.root_ref)
+ end
+
+ it 'returns a single ref from a OID' do
+ refs = repository.refs_by_oid(oid: repository.commit.id, limit: 1)
+
+ expect(refs).to be_an(Array)
+ expect(refs).to eq([Gitlab::Git::BRANCH_REF_PREFIX + repository.root_ref])
+ end
+
+ it 'returns empty for unknown ID' do
+ expect(repository.refs_by_oid(oid: Gitlab::Git::BLANK_SHA, limit: 0)).to eq([])
+ end
+
+ it 'returns nil for an empty repo' do
+ project = create(:project)
+
+ expect(project.repository.refs_by_oid(oid: SeedRepo::Commit::ID, limit: 0)).to be_nil
+ end
+ end
+
describe '#set_full_path' do
before do
repository_rugged.config["gitlab.fullpath"] = repository_path
diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
index 554a91f2bc5..d8e397dd6f3 100644
--- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
@@ -112,15 +112,38 @@ RSpec.describe Gitlab::GitalyClient::CommitService do
let(:from) { 'master' }
let(:to) { Gitlab::Git::EMPTY_TREE_ID }
- it 'sends an RPC request' do
- request = Gitaly::CommitsBetweenRequest.new(
- repository: repository_message, from: from, to: to
- )
+ context 'with between_commits_via_list_commits enabled' do
+ before do
+ stub_feature_flags(between_commits_via_list_commits: true)
+ end
- expect_any_instance_of(Gitaly::CommitService::Stub).to receive(:commits_between)
- .with(request, kind_of(Hash)).and_return([])
+ it 'sends an RPC request' do
+ request = Gitaly::ListCommitsRequest.new(
+ repository: repository_message, revisions: ["^" + from, to], reverse: true
+ )
+
+ expect_any_instance_of(Gitaly::CommitService::Stub).to receive(:list_commits)
+ .with(request, kind_of(Hash)).and_return([])
- described_class.new(repository).between(from, to)
+ described_class.new(repository).between(from, to)
+ end
+ end
+
+ context 'with between_commits_via_list_commits disabled' do
+ before do
+ stub_feature_flags(between_commits_via_list_commits: false)
+ end
+
+ it 'sends an RPC request' do
+ request = Gitaly::CommitsBetweenRequest.new(
+ repository: repository_message, from: from, to: to
+ )
+
+ expect_any_instance_of(Gitaly::CommitService::Stub).to receive(:commits_between)
+ .with(request, kind_of(Hash)).and_return([])
+
+ described_class.new(repository).between(from, to)
+ end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
index d308612ef31..2e37c98a591 100644
--- a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
@@ -190,6 +190,22 @@ RSpec.describe Gitlab::GitalyClient::RefService do
client.tags(sort_by: 'name_asc')
end
end
+
+ context 'with pagination option' do
+ it 'sends a correct find_all_tags message' do
+ expected_pagination = Gitaly::PaginationParameter.new(
+ limit: 5,
+ page_token: 'refs/tags/v1.0.0'
+ )
+
+ expect_any_instance_of(Gitaly::RefService::Stub)
+ .to receive(:find_all_tags)
+ .with(gitaly_request_with_params(pagination_params: expected_pagination), kind_of(Hash))
+ .and_return([])
+
+ client.tags(pagination_params: { limit: 5, page_token: 'refs/tags/v1.0.0' })
+ end
+ end
end
describe '#branch_names_contains_sha' do
@@ -252,6 +268,26 @@ RSpec.describe Gitlab::GitalyClient::RefService do
end
end
+ describe '#list_refs' do
+ it 'sends a list_refs message' do
+ expect_any_instance_of(Gitaly::RefService::Stub)
+ .to receive(:list_refs)
+ .with(gitaly_request_with_params(patterns: ['refs/heads/']), kind_of(Hash))
+ .and_call_original
+
+ client.list_refs
+ end
+
+ it 'accepts a patterns argument' do
+ expect_any_instance_of(Gitaly::RefService::Stub)
+ .to receive(:list_refs)
+ .with(gitaly_request_with_params(patterns: ['refs/tags/']), kind_of(Hash))
+ .and_call_original
+
+ client.list_refs([Gitlab::Git::TAG_REF_PREFIX])
+ end
+ end
+
describe '#pack_refs' do
it 'sends a pack_refs message' do
expect_any_instance_of(Gitaly::RefService::Stub)
@@ -262,4 +298,19 @@ RSpec.describe Gitlab::GitalyClient::RefService do
client.pack_refs
end
end
+
+ describe '#find_refs_by_oid' do
+ let(:oid) { project.repository.commit.id }
+
+ it 'sends a find_refs_by_oid message' do
+ expect_any_instance_of(Gitaly::RefService::Stub)
+ .to receive(:find_refs_by_oid)
+ .with(gitaly_request_with_params(sort_field: 'refname', oid: oid, limit: 1), kind_of(Hash))
+ .and_call_original
+
+ refs = client.find_refs_by_oid(oid: oid, limit: 1)
+
+ expect(refs.to_a).to eq([Gitlab::Git::BRANCH_REF_PREFIX + project.repository.root_ref])
+ end
+ end
end
diff --git a/spec/lib/gitlab/gitaly_client_spec.rb b/spec/lib/gitlab/gitaly_client_spec.rb
index 16f75691288..ba4ea1069d8 100644
--- a/spec/lib/gitlab/gitaly_client_spec.rb
+++ b/spec/lib/gitlab/gitaly_client_spec.rb
@@ -5,14 +5,6 @@ require 'spec_helper'
# We stub Gitaly in `spec/support/gitaly.rb` for other tests. We don't want
# those stubs while testing the GitalyClient itself.
RSpec.describe Gitlab::GitalyClient do
- let(:sample_cert) { Rails.root.join('spec/fixtures/clusters/sample_cert.pem').to_s }
-
- before do
- allow(described_class)
- .to receive(:stub_cert_paths)
- .and_return([sample_cert])
- end
-
def stub_repos_storages(address)
allow(Gitlab.config.repositories).to receive(:storages).and_return({
'default' => { 'gitaly_address' => address }
@@ -142,21 +134,6 @@ RSpec.describe Gitlab::GitalyClient do
end
end
- describe '.stub_certs' do
- it 'skips certificates if OpenSSLError is raised and report it' do
- expect(Gitlab::ErrorTracking)
- .to receive(:track_and_raise_for_dev_exception)
- .with(
- a_kind_of(OpenSSL::X509::CertificateError),
- cert_file: a_kind_of(String)).at_least(:once)
-
- expect(OpenSSL::X509::Certificate)
- .to receive(:new)
- .and_raise(OpenSSL::X509::CertificateError).at_least(:once)
-
- expect(described_class.stub_certs).to be_a(String)
- end
- end
describe '.stub_creds' do
it 'returns :this_channel_is_insecure if unix' do
address = 'unix:/tmp/gitaly.sock'
diff --git a/spec/lib/gitlab/github_import/bulk_importing_spec.rb b/spec/lib/gitlab/github_import/bulk_importing_spec.rb
index 6c94973b5a8..e170496ff7b 100644
--- a/spec/lib/gitlab/github_import/bulk_importing_spec.rb
+++ b/spec/lib/gitlab/github_import/bulk_importing_spec.rb
@@ -116,13 +116,13 @@ RSpec.describe Gitlab::GithubImport::BulkImporting do
value: 5
)
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
+ expect(ApplicationRecord)
+ .to receive(:legacy_bulk_insert)
.ordered
.with('kittens', rows.first(5))
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
+ expect(ApplicationRecord)
+ .to receive(:legacy_bulk_insert)
.ordered
.with('kittens', rows.last(5))
diff --git a/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb b/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
index 3dc15c7c059..0448ada6bca 100644
--- a/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
@@ -2,156 +2,226 @@
require 'spec_helper'
-RSpec.describe Gitlab::GithubImport::Importer::DiffNoteImporter do
- let(:project) { create(:project) }
- let(:client) { double(:client) }
- let(:user) { create(:user) }
- let(:created_at) { Time.new(2017, 1, 1, 12, 00) }
- let(:updated_at) { Time.new(2017, 1, 1, 12, 15) }
+RSpec.describe Gitlab::GithubImport::Importer::DiffNoteImporter, :aggregate_failures do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
- let(:hunk) do
- '@@ -1 +1 @@
+ let(:client) { double(:client) }
+ let(:discussion_id) { 'b0fa404393eeebb4e82becb8104f238812bb1fe6' }
+ let(:created_at) { Time.new(2017, 1, 1, 12, 00).utc }
+ let(:updated_at) { Time.new(2017, 1, 1, 12, 15).utc }
+ let(:note_body) { 'Hello' }
+ let(:file_path) { 'files/ruby/popen.rb' }
+
+ let(:diff_hunk) do
+ '@@ -14 +14 @@
-Hello
+Hello world'
end
- let(:note) do
+ let(:note_representation) do
Gitlab::GithubImport::Representation::DiffNote.new(
noteable_type: 'MergeRequest',
noteable_id: 1,
commit_id: '123abc',
original_commit_id: 'original123abc',
- file_path: 'README.md',
- diff_hunk: hunk,
- author: Gitlab::GithubImport::Representation::User
- .new(id: user.id, login: user.username),
- note: 'Hello',
+ file_path: file_path,
+ author: Gitlab::GithubImport::Representation::User.new(id: user.id, login: user.username),
+ note: note_body,
created_at: created_at,
updated_at: updated_at,
- github_id: 1
+ start_line: nil,
+ end_line: 15,
+ github_id: 1,
+ diff_hunk: diff_hunk,
+ side: 'RIGHT'
)
end
- let(:importer) { described_class.new(note, project, client) }
+ subject(:importer) { described_class.new(note_representation, project, client) }
+
+ shared_examples 'diff notes without suggestion' do
+ it 'imports the note as legacy diff note' do
+ stub_user_finder(user.id, true)
+
+ expect { subject.execute }
+ .to change(LegacyDiffNote, :count)
+ .by(1)
+
+ note = project.notes.diff_notes.take
+ expect(note).to be_valid
+ expect(note.author_id).to eq(user.id)
+ expect(note.commit_id).to eq('original123abc')
+ expect(note.created_at).to eq(created_at)
+ expect(note.diff).to be_an_instance_of(Gitlab::Git::Diff)
+ expect(note.discussion_id).to eq(discussion_id)
+ expect(note.line_code).to eq(note_representation.line_code)
+ expect(note.note).to eq('Hello')
+ expect(note.noteable_id).to eq(merge_request.id)
+ expect(note.noteable_type).to eq('MergeRequest')
+ expect(note.project_id).to eq(project.id)
+ expect(note.st_diff).to eq(note_representation.diff_hash)
+ expect(note.system).to eq(false)
+ expect(note.type).to eq('LegacyDiffNote')
+ expect(note.updated_at).to eq(updated_at)
+ end
+
+ it 'adds a "created by:" note when the author cannot be found' do
+ stub_user_finder(project.creator_id, false)
+
+ expect { subject.execute }
+ .to change(LegacyDiffNote, :count)
+ .by(1)
+
+ note = project.notes.diff_notes.take
+ expect(note).to be_valid
+ expect(note.author_id).to eq(project.creator_id)
+ expect(note.note).to eq("*Created by: #{user.username}*\n\nHello")
+ end
+
+ it 'does not import the note when a foreign key error is raised' do
+ stub_user_finder(project.creator_id, false)
+
+ expect(ApplicationRecord)
+ .to receive(:legacy_bulk_insert)
+ .and_raise(ActiveRecord::InvalidForeignKey, 'invalid foreign key')
+
+ expect { subject.execute }
+ .not_to change(LegacyDiffNote, :count)
+ end
+ end
describe '#execute' do
context 'when the merge request no longer exists' do
it 'does not import anything' do
- expect(Gitlab::Database.main).not_to receive(:bulk_insert)
+ expect(ApplicationRecord).not_to receive(:legacy_bulk_insert)
- importer.execute
+ expect { subject.execute }
+ .to not_change(DiffNote, :count)
+ .and not_change(LegacyDiffNote, :count)
end
end
context 'when the merge request exists' do
- let!(:merge_request) do
+ let_it_be(:merge_request) do
create(:merge_request, source_project: project, target_project: project)
end
before do
- allow(importer)
- .to receive(:find_merge_request_id)
- .and_return(merge_request.id)
+ expect_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
+ expect(finder)
+ .to receive(:database_id)
+ .and_return(merge_request.id)
+ end
+
+ expect(Discussion)
+ .to receive(:discussion_id)
+ .and_return(discussion_id)
end
- it 'imports the note' do
- allow(importer.user_finder)
- .to receive(:author_id_for)
- .and_return([user.id, true])
-
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
- .with(
- LegacyDiffNote.table_name,
- [
- {
- discussion_id: anything,
- noteable_type: 'MergeRequest',
- noteable_id: merge_request.id,
- project_id: project.id,
- author_id: user.id,
- note: 'Hello',
- system: false,
- commit_id: 'original123abc',
- line_code: note.line_code,
- type: 'LegacyDiffNote',
- created_at: created_at,
- updated_at: updated_at,
- st_diff: note.diff_hash.to_yaml
- }
- ]
- )
- .and_call_original
-
- importer.execute
+ context 'when github_importer_use_diff_note_with_suggestions is disabled' do
+ before do
+ stub_feature_flags(github_importer_use_diff_note_with_suggestions: false)
+ end
+
+ it_behaves_like 'diff notes without suggestion'
+
+ context 'when the note has suggestions' do
+ let(:note_body) do
+ <<~EOB
+ Suggestion:
+ ```suggestion
+ what do you think to do it like this
+ ```
+ EOB
+ end
+
+ it 'imports the note' do
+ stub_user_finder(user.id, true)
+
+ expect { subject.execute }
+ .to change(LegacyDiffNote, :count)
+ .and not_change(DiffNote, :count)
+
+ note = project.notes.diff_notes.take
+ expect(note).to be_valid
+ expect(note.note)
+ .to eq <<~NOTE
+ Suggestion:
+ ```suggestion:-0+0
+ what do you think to do it like this
+ ```
+ NOTE
+ end
+ end
end
- it 'imports the note when the author could not be found' do
- allow(importer.user_finder)
- .to receive(:author_id_for)
- .and_return([project.creator_id, false])
-
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
- .with(
- LegacyDiffNote.table_name,
- [
- {
- discussion_id: anything,
- noteable_type: 'MergeRequest',
- noteable_id: merge_request.id,
- project_id: project.id,
- author_id: project.creator_id,
- note: "*Created by: #{user.username}*\n\nHello",
- system: false,
- commit_id: 'original123abc',
- line_code: note.line_code,
- type: 'LegacyDiffNote',
- created_at: created_at,
- updated_at: updated_at,
- st_diff: note.diff_hash.to_yaml
- }
- ]
- )
- .and_call_original
-
- importer.execute
- end
-
- it 'produces a valid LegacyDiffNote' do
- allow(importer.user_finder)
- .to receive(:author_id_for)
- .and_return([user.id, true])
-
- importer.execute
-
- note = project.notes.diff_notes.take
-
- expect(note).to be_valid
- expect(note.diff).to be_an_instance_of(Gitlab::Git::Diff)
- end
-
- it 'does not import the note when a foreign key error is raised' do
- allow(importer.user_finder)
- .to receive(:author_id_for)
- .and_return([project.creator_id, false])
-
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
- .and_raise(ActiveRecord::InvalidForeignKey, 'invalid foreign key')
-
- expect { importer.execute }.not_to raise_error
+ context 'when github_importer_use_diff_note_with_suggestions is enabled' do
+ before do
+ stub_feature_flags(github_importer_use_diff_note_with_suggestions: true)
+ end
+
+ it_behaves_like 'diff notes without suggestion'
+
+ context 'when the note has suggestions' do
+ let(:note_body) do
+ <<~EOB
+ Suggestion:
+ ```suggestion
+ what do you think to do it like this
+ ```
+ EOB
+ end
+
+ it 'imports the note as diff note' do
+ stub_user_finder(user.id, true)
+
+ expect { subject.execute }
+ .to change(DiffNote, :count)
+ .by(1)
+
+ note = project.notes.diff_notes.take
+ expect(note).to be_valid
+ expect(note.noteable_type).to eq('MergeRequest')
+ expect(note.noteable_id).to eq(merge_request.id)
+ expect(note.project_id).to eq(project.id)
+ expect(note.author_id).to eq(user.id)
+ expect(note.system).to eq(false)
+ expect(note.discussion_id).to eq(discussion_id)
+ expect(note.commit_id).to eq('original123abc')
+ expect(note.line_code).to eq(note_representation.line_code)
+ expect(note.type).to eq('DiffNote')
+ expect(note.created_at).to eq(created_at)
+ expect(note.updated_at).to eq(updated_at)
+ expect(note.position.to_h).to eq({
+ base_sha: merge_request.diffs.diff_refs.base_sha,
+ head_sha: merge_request.diffs.diff_refs.head_sha,
+ start_sha: merge_request.diffs.diff_refs.start_sha,
+ new_line: 15,
+ old_line: nil,
+ new_path: file_path,
+ old_path: file_path,
+ position_type: 'text',
+ line_range: nil
+ })
+ expect(note.note)
+ .to eq <<~NOTE
+ Suggestion:
+ ```suggestion:-0+0
+ what do you think to do it like this
+ ```
+ NOTE
+ end
+ end
end
end
end
- describe '#find_merge_request_id' do
- it 'returns a merge request ID' do
- expect_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |instance|
- expect(instance).to receive(:database_id).and_return(10)
- end
-
- expect(importer.find_merge_request_id).to eq(10)
+ def stub_user_finder(user, found)
+ expect_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
+ expect(finder)
+ .to receive(:author_id_for)
+ .and_return([user, found])
end
end
end
diff --git a/spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb b/spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb
index be4fc3cbf16..1c7b35ed928 100644
--- a/spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb
@@ -19,7 +19,9 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNotesImporter do
updated_at: Time.zone.now,
line: 23,
start_line: nil,
+ in_reply_to_id: nil,
id: 1,
+ side: 'RIGHT',
body: <<~BODY
Hello World
diff --git a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
index 0926000428c..4287c32b947 100644
--- a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
@@ -190,8 +190,8 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redi
.with(issue.assignees[1])
.and_return(5)
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
+ expect(ApplicationRecord)
+ .to receive(:legacy_bulk_insert)
.with(
IssueAssignee.table_name,
[{ issue_id: 1, user_id: 4 }, { issue_id: 1, user_id: 5 }]
diff --git a/spec/lib/gitlab/github_import/importer/label_links_importer_spec.rb b/spec/lib/gitlab/github_import/importer/label_links_importer_spec.rb
index 241a0fef600..e68849755b2 100644
--- a/spec/lib/gitlab/github_import/importer/label_links_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/label_links_importer_spec.rb
@@ -39,8 +39,8 @@ RSpec.describe Gitlab::GithubImport::Importer::LabelLinksImporter do
.and_return(1)
freeze_time do
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
+ expect(ApplicationRecord)
+ .to receive(:legacy_bulk_insert)
.with(
LabelLink.table_name,
[
@@ -64,8 +64,8 @@ RSpec.describe Gitlab::GithubImport::Importer::LabelLinksImporter do
.with('bug')
.and_return(nil)
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
+ expect(ApplicationRecord)
+ .to receive(:legacy_bulk_insert)
.with(LabelLink.table_name, [])
importer.create_labels
diff --git a/spec/lib/gitlab/github_import/importer/note_importer_spec.rb b/spec/lib/gitlab/github_import/importer/note_importer_spec.rb
index 820f46c7286..96d8acbd3de 100644
--- a/spec/lib/gitlab/github_import/importer/note_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/note_importer_spec.rb
@@ -41,8 +41,8 @@ RSpec.describe Gitlab::GithubImport::Importer::NoteImporter do
.with(github_note)
.and_return([user.id, true])
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
+ expect(ApplicationRecord)
+ .to receive(:legacy_bulk_insert)
.with(
Note.table_name,
[
@@ -71,8 +71,8 @@ RSpec.describe Gitlab::GithubImport::Importer::NoteImporter do
.with(github_note)
.and_return([project.creator_id, false])
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
+ expect(ApplicationRecord)
+ .to receive(:legacy_bulk_insert)
.with(
Note.table_name,
[
@@ -115,7 +115,7 @@ RSpec.describe Gitlab::GithubImport::Importer::NoteImporter do
context 'when the noteable does not exist' do
it 'does not import the note' do
- expect(Gitlab::Database.main).not_to receive(:bulk_insert)
+ expect(ApplicationRecord).not_to receive(:legacy_bulk_insert)
importer.execute
end
@@ -134,8 +134,8 @@ RSpec.describe Gitlab::GithubImport::Importer::NoteImporter do
.with(github_note)
.and_return([user.id, true])
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
+ expect(ApplicationRecord)
+ .to receive(:legacy_bulk_insert)
.and_raise(ActiveRecord::InvalidForeignKey, 'invalid foreign key')
expect { importer.execute }.not_to raise_error
diff --git a/spec/lib/gitlab/github_import/importer/pull_requests_merged_by_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests_merged_by_importer_spec.rb
index 4a47d103cde..b6c162aafa9 100644
--- a/spec/lib/gitlab/github_import/importer/pull_requests_merged_by_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_requests_merged_by_importer_spec.rb
@@ -4,7 +4,8 @@ require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Importer::PullRequestsMergedByImporter do
let(:client) { double }
- let(:project) { create(:project, import_source: 'http://somegithub.com') }
+
+ let_it_be(:project) { create(:project, import_source: 'http://somegithub.com') }
subject { described_class.new(project, client) }
@@ -27,14 +28,11 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsMergedByImporter do
end
describe '#each_object_to_import', :clean_gitlab_redis_cache do
- it 'fetchs the merged pull requests data' do
- create(
- :merged_merge_request,
- iid: 999,
- source_project: project,
- target_project: project
- )
+ let!(:merge_request) do
+ create(:merged_merge_request, iid: 999, source_project: project, target_project: project)
+ end
+ it 'fetches the merged pull requests data' do
pull_request = double
allow(client)
@@ -48,5 +46,16 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsMergedByImporter do
subject.each_object_to_import {}
end
+
+ it 'skips cached merge requests' do
+ Gitlab::Cache::Import::Caching.set_add(
+ "github-importer/already-imported/#{project.id}/pull_requests_merged_by",
+ merge_request.id
+ )
+
+ expect(client).not_to receive(:pull_request)
+
+ subject.each_object_to_import {}
+ end
end
end
diff --git a/spec/lib/gitlab/github_import/representation/diff_note_spec.rb b/spec/lib/gitlab/github_import/representation/diff_note_spec.rb
index 81722c0eba7..63834cfdb94 100644
--- a/spec/lib/gitlab/github_import/representation/diff_note_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/diff_note_spec.rb
@@ -2,23 +2,44 @@
require 'spec_helper'
-RSpec.describe Gitlab::GithubImport::Representation::DiffNote do
+RSpec.describe Gitlab::GithubImport::Representation::DiffNote, :clean_gitlab_redis_shared_state do
let(:hunk) do
'@@ -1 +1 @@
-Hello
+Hello world'
end
+ let(:merge_request) do
+ double(
+ :merge_request,
+ id: 54,
+ diff_refs: double(
+ :refs,
+ base_sha: 'base',
+ start_sha: 'start',
+ head_sha: 'head'
+ )
+ )
+ end
+
+ let(:project) { double(:project, id: 836) }
+ let(:note_id) { 1 }
+ let(:in_reply_to_id) { nil }
+ let(:start_line) { nil }
+ let(:end_line) { 23 }
+ let(:note_body) { 'Hello world' }
+ let(:user_data) { { 'id' => 4, 'login' => 'alice' } }
+ let(:side) { 'RIGHT' }
let(:created_at) { Time.new(2017, 1, 1, 12, 00) }
let(:updated_at) { Time.new(2017, 1, 1, 12, 15) }
- shared_examples 'a DiffNote' do
+ shared_examples 'a DiffNote representation' do
it 'returns an instance of DiffNote' do
expect(note).to be_an_instance_of(described_class)
end
context 'the returned DiffNote' do
- it 'includes the number of the note' do
+ it 'includes the number of the merge request' do
expect(note.noteable_id).to eq(42)
end
@@ -30,18 +51,6 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNote do
expect(note.commit_id).to eq('123abc')
end
- it 'includes the user details' do
- expect(note.author)
- .to be_an_instance_of(Gitlab::GithubImport::Representation::User)
-
- expect(note.author.id).to eq(4)
- expect(note.author.login).to eq('alice')
- end
-
- it 'includes the note body' do
- expect(note.note).to eq('Hello world')
- end
-
it 'includes the created timestamp' do
expect(note.created_at).to eq(created_at)
end
@@ -51,209 +60,250 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNote do
end
it 'includes the GitHub ID' do
- expect(note.note_id).to eq(1)
+ expect(note.note_id).to eq(note_id)
end
it 'returns the noteable type' do
expect(note.noteable_type).to eq('MergeRequest')
end
- end
- end
-
- describe '.from_api_response' do
- let(:response) do
- double(
- :response,
- html_url: 'https://github.com/foo/bar/pull/42',
- path: 'README.md',
- commit_id: '123abc',
- original_commit_id: 'original123abc',
- diff_hunk: hunk,
- user: double(:user, id: 4, login: 'alice'),
- body: 'Hello world',
- created_at: created_at,
- updated_at: updated_at,
- line: 23,
- start_line: nil,
- id: 1
- )
- end
-
- it_behaves_like 'a DiffNote' do
- let(:note) { described_class.from_api_response(response) }
- end
-
- it 'does not set the user if the response did not include a user' do
- allow(response)
- .to receive(:user)
- .and_return(nil)
-
- note = described_class.from_api_response(response)
-
- expect(note.author).to be_nil
- end
-
- it 'formats a suggestion in the note body' do
- allow(response)
- .to receive(:body)
- .and_return <<~BODY
- ```suggestion
- Hello World
- ```
- BODY
-
- note = described_class.from_api_response(response)
-
- expect(note.note).to eq <<~BODY
- ```suggestion:-0+0
- Hello World
- ```
- BODY
- end
- end
-
- describe '.from_json_hash' do
- let(:hash) do
- {
- 'noteable_type' => 'MergeRequest',
- 'noteable_id' => 42,
- 'file_path' => 'README.md',
- 'commit_id' => '123abc',
- 'original_commit_id' => 'original123abc',
- 'diff_hunk' => hunk,
- 'author' => { 'id' => 4, 'login' => 'alice' },
- 'note' => 'Hello world',
- 'created_at' => created_at.to_s,
- 'updated_at' => updated_at.to_s,
- 'note_id' => 1
- }
- end
- it_behaves_like 'a DiffNote' do
- let(:note) { described_class.from_json_hash(hash) }
- end
-
- it 'does not convert the author if it was not specified' do
- hash.delete('author')
-
- note = described_class.from_json_hash(hash)
+ describe '#diff_hash' do
+ it 'returns a Hash containing the diff details' do
+ expect(note.diff_hash).to eq(
+ diff: hunk,
+ new_path: 'README.md',
+ old_path: 'README.md',
+ a_mode: '100644',
+ b_mode: '100644',
+ new_file: false
+ )
+ end
+ end
- expect(note.author).to be_nil
- end
+ describe '#diff_position' do
+ before do
+ note.merge_request = double(
+ :merge_request,
+ diff_refs: double(
+ :refs,
+ base_sha: 'base',
+ start_sha: 'start',
+ head_sha: 'head'
+ )
+ )
+ end
+
+ context 'when the diff is an addition' do
+ it 'returns a Gitlab::Diff::Position' do
+ expect(note.diff_position.to_h).to eq(
+ base_sha: 'base',
+ head_sha: 'head',
+ line_range: nil,
+ new_line: 23,
+ new_path: 'README.md',
+ old_line: nil,
+ old_path: 'README.md',
+ position_type: 'text',
+ start_sha: 'start'
+ )
+ end
+ end
+
+ context 'when the diff is an deletion' do
+ let(:side) { 'LEFT' }
+
+ it 'returns a Gitlab::Diff::Position' do
+ expect(note.diff_position.to_h).to eq(
+ base_sha: 'base',
+ head_sha: 'head',
+ line_range: nil,
+ old_line: 23,
+ new_path: 'README.md',
+ new_line: nil,
+ old_path: 'README.md',
+ position_type: 'text',
+ start_sha: 'start'
+ )
+ end
+ end
+ end
- it 'formats a suggestion in the note body' do
- hash['note'] = <<~BODY
- ```suggestion
- Hello World
- ```
- BODY
+ describe '#discussion_id' do
+ before do
+ note.project = project
+ note.merge_request = merge_request
+ end
+
+ context 'when the note is a reply to a discussion' do
+ it 'uses the cached value as the discussion_id only when responding an existing discussion' do
+ expect(Discussion)
+ .to receive(:discussion_id)
+ .and_return('FIRST_DISCUSSION_ID', 'SECOND_DISCUSSION_ID')
+
+ # Creates the first discussion id and caches its value
+ expect(note.discussion_id)
+ .to eq('FIRST_DISCUSSION_ID')
+
+ reply_note = described_class.from_json_hash(
+ 'note_id' => note.note_id + 1,
+ 'in_reply_to_id' => note.note_id
+ )
+ reply_note.project = project
+ reply_note.merge_request = merge_request
+
+ # Reading from the cached value
+ expect(reply_note.discussion_id)
+ .to eq('FIRST_DISCUSSION_ID')
+
+ new_discussion_note = described_class.from_json_hash(
+ 'note_id' => note.note_id + 2,
+ 'in_reply_to_id' => nil
+ )
+ new_discussion_note.project = project
+ new_discussion_note.merge_request = merge_request
+
+ # Because it's a new discussion, it must not use the cached value
+ expect(new_discussion_note.discussion_id)
+ .to eq('SECOND_DISCUSSION_ID')
+ end
+ end
+ end
- note = described_class.from_json_hash(hash)
+ describe '#github_identifiers' do
+ it 'returns a hash with needed identifiers' do
+ expect(note.github_identifiers).to eq(
+ noteable_id: 42,
+ noteable_type: 'MergeRequest',
+ note_id: 1
+ )
+ end
+ end
- expect(note.note).to eq <<~BODY
- ```suggestion:-0+0
- Hello World
- ```
- BODY
- end
- end
+ describe '#line_code' do
+ it 'generates the proper line code' do
+ note = described_class.new(diff_hunk: hunk, file_path: 'README.md')
- describe '#line_code' do
- it 'returns a String' do
- note = described_class.new(diff_hunk: hunk, file_path: 'README.md')
+ expect(note.line_code).to eq('8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_2_2')
+ end
+ end
- expect(note.line_code).to be_an_instance_of(String)
+ describe '#note and #contains_suggestion?' do
+ it 'includes the note body' do
+ expect(note.note).to eq('Hello world')
+ expect(note.contains_suggestion?).to eq(false)
+ end
+
+ context 'when the note have a suggestion' do
+ let(:note_body) do
+ <<~BODY
+ ```suggestion
+ Hello World
+ ```
+ BODY
+ end
+
+ it 'returns the suggestion formatted in the note' do
+ expect(note.note).to eq <<~BODY
+ ```suggestion:-0+0
+ Hello World
+ ```
+ BODY
+ expect(note.contains_suggestion?).to eq(true)
+ end
+ end
+
+ context 'when the note have a multiline suggestion' do
+ let(:start_line) { 20 }
+ let(:end_line) { 23 }
+ let(:note_body) do
+ <<~BODY
+ ```suggestion
+ Hello World
+ ```
+ BODY
+ end
+
+ it 'returns the multi-line suggestion formatted in the note' do
+ expect(note.note).to eq <<~BODY
+ ```suggestion:-3+0
+ Hello World
+ ```
+ BODY
+ expect(note.contains_suggestion?).to eq(true)
+ end
+ end
+
+ describe '#author' do
+ it 'includes the user details' do
+ expect(note.author).to be_an_instance_of(
+ Gitlab::GithubImport::Representation::User
+ )
+
+ expect(note.author.id).to eq(4)
+ expect(note.author.login).to eq('alice')
+ end
+
+ context 'when the author is empty' do
+ let(:user_data) { nil }
+
+ it 'does not set the user if the response did not include a user' do
+ expect(note.author).to be_nil
+ end
+ end
+ end
+ end
end
end
- describe '#diff_hash' do
- it 'returns a Hash containing the diff details' do
- note = described_class.from_json_hash(
- 'noteable_type' => 'MergeRequest',
- 'noteable_id' => 42,
- 'file_path' => 'README.md',
- 'commit_id' => '123abc',
- 'original_commit_id' => 'original123abc',
- 'diff_hunk' => hunk,
- 'author' => { 'id' => 4, 'login' => 'alice' },
- 'note' => 'Hello world',
- 'created_at' => created_at.to_s,
- 'updated_at' => updated_at.to_s,
- 'note_id' => 1
- )
-
- expect(note.diff_hash).to eq(
- diff: hunk,
- new_path: 'README.md',
- old_path: 'README.md',
- a_mode: '100644',
- b_mode: '100644',
- new_file: false
- )
- end
- end
+ describe '.from_api_response' do
+ it_behaves_like 'a DiffNote representation' do
+ let(:response) do
+ double(
+ :response,
+ id: note_id,
+ html_url: 'https://github.com/foo/bar/pull/42',
+ path: 'README.md',
+ commit_id: '123abc',
+ original_commit_id: 'original123abc',
+ side: side,
+ user: user_data && double(:user, user_data),
+ diff_hunk: hunk,
+ body: note_body,
+ created_at: created_at,
+ updated_at: updated_at,
+ line: end_line,
+ start_line: start_line,
+ in_reply_to_id: in_reply_to_id
+ )
+ end
- describe '#github_identifiers' do
- it 'returns a hash with needed identifiers' do
- github_identifiers = {
- noteable_id: 42,
- noteable_type: 'MergeRequest',
- note_id: 1
- }
- other_attributes = { something_else: '_something_else_' }
- note = described_class.new(github_identifiers.merge(other_attributes))
-
- expect(note.github_identifiers).to eq(github_identifiers)
+ subject(:note) { described_class.from_api_response(response) }
end
end
- describe '#note' do
- it 'returns the given note' do
- hash = {
- 'note': 'simple text'
- }
-
- note = described_class.new(hash)
-
- expect(note.note).to eq 'simple text'
- end
-
- it 'returns the suggestion formatted in the note' do
- hash = {
- 'note': <<~BODY
- ```suggestion
- Hello World
- ```
- BODY
- }
-
- note = described_class.new(hash)
-
- expect(note.note).to eq <<~BODY
- ```suggestion:-0+0
- Hello World
- ```
- BODY
- end
+ describe '.from_json_hash' do
+ it_behaves_like 'a DiffNote representation' do
+ let(:hash) do
+ {
+ 'note_id' => note_id,
+ 'noteable_type' => 'MergeRequest',
+ 'noteable_id' => 42,
+ 'file_path' => 'README.md',
+ 'commit_id' => '123abc',
+ 'original_commit_id' => 'original123abc',
+ 'side' => side,
+ 'author' => user_data,
+ 'diff_hunk' => hunk,
+ 'note' => note_body,
+ 'created_at' => created_at.to_s,
+ 'updated_at' => updated_at.to_s,
+ 'end_line' => end_line,
+ 'start_line' => start_line,
+ 'in_reply_to_id' => in_reply_to_id
+ }
+ end
- it 'returns the multi-line suggestion formatted in the note' do
- hash = {
- 'start_line': 20,
- 'end_line': 23,
- 'note': <<~BODY
- ```suggestion
- Hello World
- ```
- BODY
- }
-
- note = described_class.new(hash)
-
- expect(note.note).to eq <<~BODY
- ```suggestion:-3+0
- Hello World
- ```
- BODY
+ subject(:note) { described_class.from_json_hash(hash) }
end
end
end
diff --git a/spec/lib/gitlab/github_import/representation/diff_notes/suggestion_formatter_spec.rb b/spec/lib/gitlab/github_import/representation/diff_notes/suggestion_formatter_spec.rb
index 2ffd5f50d3b..bcb8575bdbf 100644
--- a/spec/lib/gitlab/github_import/representation/diff_notes/suggestion_formatter_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/diff_notes/suggestion_formatter_spec.rb
@@ -9,13 +9,19 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNotes::SuggestionFormat
```
BODY
- expect(described_class.formatted_note_for(note: note)).to eq(note)
+ note_formatter = described_class.new(note: note)
+
+ expect(note_formatter.formatted_note).to eq(note)
+ expect(note_formatter.contains_suggestion?).to eq(false)
end
it 'handles nil value for note' do
note = nil
- expect(described_class.formatted_note_for(note: note)).to eq(note)
+ note_formatter = described_class.new(note: note)
+
+ expect(note_formatter.formatted_note).to eq(note)
+ expect(note_formatter.contains_suggestion?).to eq(false)
end
it 'does not allow over 3 leading spaces for valid suggestion' do
@@ -26,7 +32,10 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNotes::SuggestionFormat
```
BODY
- expect(described_class.formatted_note_for(note: note)).to eq(note)
+ note_formatter = described_class.new(note: note)
+
+ expect(note_formatter.formatted_note).to eq(note)
+ expect(note_formatter.contains_suggestion?).to eq(false)
end
it 'allows up to 3 leading spaces' do
@@ -44,7 +53,10 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNotes::SuggestionFormat
```
BODY
- expect(described_class.formatted_note_for(note: note)).to eq(expected)
+ note_formatter = described_class.new(note: note)
+
+ expect(note_formatter.formatted_note).to eq(expected)
+ expect(note_formatter.contains_suggestion?).to eq(true)
end
it 'does nothing when there is any text without space after the suggestion tag' do
@@ -53,7 +65,10 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNotes::SuggestionFormat
```
BODY
- expect(described_class.formatted_note_for(note: note)).to eq(note)
+ note_formatter = described_class.new(note: note)
+
+ expect(note_formatter.formatted_note).to eq(note)
+ expect(note_formatter.contains_suggestion?).to eq(false)
end
it 'formats single-line suggestions' do
@@ -71,7 +86,10 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNotes::SuggestionFormat
```
BODY
- expect(described_class.formatted_note_for(note: note)).to eq(expected)
+ note_formatter = described_class.new(note: note)
+
+ expect(note_formatter.formatted_note).to eq(expected)
+ expect(note_formatter.contains_suggestion?).to eq(true)
end
it 'ignores text after suggestion tag on the same line' do
@@ -89,7 +107,10 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNotes::SuggestionFormat
```
BODY
- expect(described_class.formatted_note_for(note: note)).to eq(expected)
+ note_formatter = described_class.new(note: note)
+
+ expect(note_formatter.formatted_note).to eq(expected)
+ expect(note_formatter.contains_suggestion?).to eq(true)
end
it 'formats multiple single-line suggestions' do
@@ -115,7 +136,10 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNotes::SuggestionFormat
```
BODY
- expect(described_class.formatted_note_for(note: note)).to eq(expected)
+ note_formatter = described_class.new(note: note)
+
+ expect(note_formatter.formatted_note).to eq(expected)
+ expect(note_formatter.contains_suggestion?).to eq(true)
end
it 'formats multi-line suggestions' do
@@ -133,7 +157,10 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNotes::SuggestionFormat
```
BODY
- expect(described_class.formatted_note_for(note: note, start_line: 6, end_line: 8)).to eq(expected)
+ note_formatter = described_class.new(note: note, start_line: 6, end_line: 8)
+
+ expect(note_formatter.formatted_note).to eq(expected)
+ expect(note_formatter.contains_suggestion?).to eq(true)
end
it 'formats multiple multi-line suggestions' do
@@ -159,6 +186,9 @@ RSpec.describe Gitlab::GithubImport::Representation::DiffNotes::SuggestionFormat
```
BODY
- expect(described_class.formatted_note_for(note: note, start_line: 6, end_line: 8)).to eq(expected)
+ note_formatter = described_class.new(note: note, start_line: 6, end_line: 8)
+
+ expect(note_formatter.formatted_note).to eq(expected)
+ expect(note_formatter.contains_suggestion?).to eq(true)
end
end
diff --git a/spec/lib/gitlab/gpg/commit_spec.rb b/spec/lib/gitlab/gpg/commit_spec.rb
index 55102554508..20d5972bd88 100644
--- a/spec/lib/gitlab/gpg/commit_spec.rb
+++ b/spec/lib/gitlab/gpg/commit_spec.rb
@@ -136,7 +136,7 @@ RSpec.describe Gitlab::Gpg::Commit do
it 'returns a valid signature' do
verified_signature = double('verified-signature', fingerprint: GpgHelpers::User1.fingerprint, valid?: true)
allow(GPGME::Crypto).to receive(:new).and_return(crypto)
- allow(crypto).to receive(:verify).and_return(verified_signature)
+ allow(crypto).to receive(:verify).and_yield(verified_signature)
signature = described_class.new(commit).signature
@@ -178,7 +178,7 @@ RSpec.describe Gitlab::Gpg::Commit do
keyid = GpgHelpers::User1.fingerprint.last(16)
verified_signature = double('verified-signature', fingerprint: keyid, valid?: true)
allow(GPGME::Crypto).to receive(:new).and_return(crypto)
- allow(crypto).to receive(:verify).and_return(verified_signature)
+ allow(crypto).to receive(:verify).and_yield(verified_signature)
signature = described_class.new(commit).signature
@@ -194,6 +194,71 @@ RSpec.describe Gitlab::Gpg::Commit do
end
end
+ context 'commit with multiple signatures' do
+ let!(:commit) { create :commit, project: project, sha: commit_sha, committer_email: GpgHelpers::User1.emails.first }
+
+ let!(:user) { create(:user, email: GpgHelpers::User1.emails.first) }
+
+ let!(:gpg_key) do
+ create :gpg_key, key: GpgHelpers::User1.public_key, user: user
+ end
+
+ let!(:crypto) { instance_double(GPGME::Crypto) }
+
+ before do
+ fake_signature = [
+ GpgHelpers::User1.signed_commit_signature,
+ GpgHelpers::User1.signed_commit_base_data
+ ]
+
+ allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
+ .with(Gitlab::Git::Repository, commit_sha)
+ .and_return(fake_signature)
+ end
+
+ it 'returns an invalid signatures error' do
+ verified_signature = double('verified-signature', fingerprint: GpgHelpers::User1.fingerprint, valid?: true)
+ allow(GPGME::Crypto).to receive(:new).and_return(crypto)
+ allow(crypto).to receive(:verify).and_yield(verified_signature).and_yield(verified_signature)
+
+ signature = described_class.new(commit).signature
+
+ expect(signature).to have_attributes(
+ commit_sha: commit_sha,
+ project: project,
+ gpg_key: gpg_key,
+ gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
+ gpg_key_user_name: GpgHelpers::User1.names.first,
+ gpg_key_user_email: GpgHelpers::User1.emails.first,
+ verification_status: 'multiple_signatures'
+ )
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(multiple_gpg_signatures: false)
+ end
+
+ it 'returns an valid signature' do
+ verified_signature = double('verified-signature', fingerprint: GpgHelpers::User1.fingerprint, valid?: true)
+ allow(GPGME::Crypto).to receive(:new).and_return(crypto)
+ allow(crypto).to receive(:verify).and_yield(verified_signature).and_yield(verified_signature)
+
+ signature = described_class.new(commit).signature
+
+ expect(signature).to have_attributes(
+ commit_sha: commit_sha,
+ project: project,
+ gpg_key: gpg_key,
+ gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
+ gpg_key_user_name: GpgHelpers::User1.names.first,
+ gpg_key_user_email: GpgHelpers::User1.emails.first,
+ verification_status: 'verified'
+ )
+ end
+ end
+ end
+
context 'commit signed with a subkey' do
let!(:commit) { create :commit, project: project, sha: commit_sha, committer_email: GpgHelpers::User3.emails.first }
diff --git a/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb b/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb
index c1516a48b80..771f6e1ec46 100644
--- a/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb
+++ b/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb
@@ -140,6 +140,8 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
key: GpgHelpers::User1.public_key,
user: user
+ user.reload # necessary to reload the association with gpg_keys
+
expect(invalid_gpg_signature.reload.verification_status).to eq 'unverified_key'
# InvalidGpgSignatureUpdater is called by the after_update hook
diff --git a/spec/lib/gitlab/grape_logging/loggers/perf_logger_spec.rb b/spec/lib/gitlab/grape_logging/loggers/perf_logger_spec.rb
index 641fb27a071..ef4bc0ca104 100644
--- a/spec/lib/gitlab/grape_logging/loggers/perf_logger_spec.rb
+++ b/spec/lib/gitlab/grape_logging/loggers/perf_logger_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::GrapeLogging::Loggers::PerfLogger do
- let(:mock_request) { OpenStruct.new(env: {}) }
+ let(:mock_request) { double('env', env: {}) }
describe ".parameters" do
subject { described_class.new.parameters(mock_request, nil) }
diff --git a/spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb b/spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb
index 9538c4bae2b..4cd9f9dfad0 100644
--- a/spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb
+++ b/spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Gitlab::GrapeLogging::Loggers::QueueDurationLogger do
let(:start_time) { Time.new(2018, 01, 01) }
describe 'when no proxy time is available' do
- let(:mock_request) { OpenStruct.new(env: {}) }
+ let(:mock_request) { double('env', env: {}) }
it 'returns an empty hash' do
expect(subject.parameters(mock_request, nil)).to eq({})
@@ -18,7 +18,7 @@ RSpec.describe Gitlab::GrapeLogging::Loggers::QueueDurationLogger do
describe 'when a proxy time is available' do
let(:mock_request) do
- OpenStruct.new(
+ double('env',
env: {
'HTTP_GITLAB_WORKHORSE_PROXY_START' => (start_time - 1.hour).to_i * (10**9)
}
diff --git a/spec/lib/gitlab/grape_logging/loggers/urgency_logger_spec.rb b/spec/lib/gitlab/grape_logging/loggers/urgency_logger_spec.rb
new file mode 100644
index 00000000000..464534f0271
--- /dev/null
+++ b/spec/lib/gitlab/grape_logging/loggers/urgency_logger_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GrapeLogging::Loggers::UrgencyLogger do
+ def endpoint(options, namespace: '')
+ Struct.new(:options, :namespace).new(options, namespace)
+ end
+
+ let(:api_class) do
+ Class.new(API::Base) do
+ namespace 'testing' do
+ # rubocop:disable Rails/HttpPositionalArguments
+ # This is not the get that performs a request, but the one from Grape
+ get 'test', urgency: :high do
+ {}
+ end
+ # rubocop:enable Rails/HttpPositionalArguments
+ end
+ end
+ end
+
+ describe ".parameters" do
+ where(:request_env, :expected_parameters) do
+ [
+ [{}, {}],
+ [{ 'api.endpoint' => endpoint({}) }, {}],
+ [{ 'api.endpoint' => endpoint({ for: 'something weird' }) }, {}],
+ [
+ { 'api.endpoint' => endpoint({ for: api_class, path: [] }) },
+ { request_urgency: :default, target_duration_s: 1 }
+ ],
+ [
+ { 'api.endpoint' => endpoint({ for: api_class, path: ['test'] }, namespace: '/testing') },
+ { request_urgency: :high, target_duration_s: 0.25 }
+ ]
+ ]
+ end
+
+ with_them do
+ let(:request) { double('request', env: request_env) }
+
+ subject { described_class.new.parameters(request, nil) }
+
+ it { is_expected.to eq(expected_parameters) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/known_operations_spec.rb b/spec/lib/gitlab/graphql/known_operations_spec.rb
new file mode 100644
index 00000000000..411c0876f82
--- /dev/null
+++ b/spec/lib/gitlab/graphql/known_operations_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+require "support/graphql/fake_query_type"
+
+RSpec.describe Gitlab::Graphql::KnownOperations do
+ using RSpec::Parameterized::TableSyntax
+
+ # Include duplicated operation names to test that we are unique-ifying them
+ let(:fake_operations) { %w(foo foo bar bar) }
+ let(:fake_schema) do
+ Class.new(GraphQL::Schema) do
+ query Graphql::FakeQueryType
+ end
+ end
+
+ subject { described_class.new(fake_operations) }
+
+ describe "#from_query" do
+ where(:query_string, :expected) do
+ "query { helloWorld }" | described_class::ANONYMOUS
+ "query fuzzyyy { helloWorld }" | described_class::UNKNOWN
+ "query foo { helloWorld }" | described_class::Operation.new("foo")
+ end
+
+ with_them do
+ it "returns known operation name from GraphQL Query" do
+ query = ::GraphQL::Query.new(fake_schema, query_string)
+
+ expect(subject.from_query(query)).to eq(expected)
+ end
+ end
+ end
+
+ describe "#operations" do
+ it "returns array of known operations" do
+ expect(subject.operations.map(&:name)).to match_array(%w(anonymous unknown foo bar))
+ end
+ end
+
+ describe "Operation#to_caller_id" do
+ where(:query_string, :expected) do
+ "query { helloWorld }" | "graphql:#{described_class::ANONYMOUS.name}"
+ "query foo { helloWorld }" | "graphql:foo"
+ end
+
+ with_them do
+ it "formats operation name for caller_id metric property" do
+ query = ::GraphQL::Query.new(fake_schema, query_string)
+
+ expect(subject.from_query(query).to_caller_id).to eq(expected)
+ end
+ end
+ end
+
+ describe "Opeartion#query_urgency" do
+ it "returns the associated query urgency" do
+ query = ::GraphQL::Query.new(fake_schema, "query foo { helloWorld }")
+
+ expect(subject.from_query(query).query_urgency).to equal(::Gitlab::EndpointAttributes::DEFAULT_URGENCY)
+ end
+ end
+
+ describe ".default" do
+ it "returns a memoization of values from webpack", :aggregate_failures do
+ # .default could have been referenced in another spec, so we need to clean it up here
+ described_class.instance_variable_set(:@default, nil)
+
+ expect(Gitlab::Webpack::GraphqlKnownOperations).to receive(:load).once.and_return(fake_operations)
+
+ 2.times { described_class.default }
+
+ # Uses reference equality to verify memoization
+ expect(described_class.default).to equal(described_class.default)
+ expect(described_class.default).to be_a(described_class)
+ expect(described_class.default.operations.map(&:name)).to include(*fake_operations)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/pagination/connections_spec.rb b/spec/lib/gitlab/graphql/pagination/connections_spec.rb
index f3f59113c81..97389b6250e 100644
--- a/spec/lib/gitlab/graphql/pagination/connections_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/connections_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe ::Gitlab::Graphql::Pagination::Connections do
before(:all) do
ActiveRecord::Schema.define do
- create_table :testing_pagination_nodes, force: true do |t|
+ create_table :_test_testing_pagination_nodes, force: true do |t|
t.integer :value, null: false
end
end
@@ -16,13 +16,13 @@ RSpec.describe ::Gitlab::Graphql::Pagination::Connections do
after(:all) do
ActiveRecord::Schema.define do
- drop_table :testing_pagination_nodes, force: true
+ drop_table :_test_testing_pagination_nodes, force: true
end
end
let_it_be(:node_model) do
Class.new(ActiveRecord::Base) do
- self.table_name = 'testing_pagination_nodes'
+ self.table_name = '_test_testing_pagination_nodes'
end
end
diff --git a/spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb b/spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb
index fc723138d88..dee8f9e3c64 100644
--- a/spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb
+++ b/spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb
@@ -18,12 +18,6 @@ RSpec.describe Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer do
GRAPHQL
end
- describe 'variables' do
- subject { initial_value.fetch(:variables) }
-
- it { is_expected.to eq('{:body=>"[FILTERED]"}') }
- end
-
describe '#final_value' do
let(:monotonic_time_before) { 42 }
let(:monotonic_time_after) { 500 }
@@ -42,7 +36,14 @@ RSpec.describe Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer do
it 'inserts duration in seconds to memo and sets request store' do
expect { final_value }.to change { memo[:duration_s] }.to(monotonic_time_duration)
- .and change { RequestStore.store[:graphql_logs] }.to([memo])
+ .and change { RequestStore.store[:graphql_logs] }.to([{
+ complexity: 4,
+ depth: 2,
+ operation_name: query.operation_name,
+ used_deprecated_fields: [],
+ used_fields: [],
+ variables: { body: "[FILTERED]" }.to_s
+ }])
end
end
end
diff --git a/spec/lib/gitlab/graphql/tracers/application_context_tracer_spec.rb b/spec/lib/gitlab/graphql/tracers/application_context_tracer_spec.rb
new file mode 100644
index 00000000000..6eff816b95a
--- /dev/null
+++ b/spec/lib/gitlab/graphql/tracers/application_context_tracer_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+require "fast_spec_helper"
+require "support/graphql/fake_tracer"
+require "support/graphql/fake_query_type"
+
+RSpec.describe Gitlab::Graphql::Tracers::ApplicationContextTracer do
+ let(:tracer_spy) { spy('tracer_spy') }
+ let(:default_known_operations) { ::Gitlab::Graphql::KnownOperations.new(['fooOperation']) }
+ let(:dummy_schema) do
+ schema = Class.new(GraphQL::Schema) do
+ use Gitlab::Graphql::Tracers::ApplicationContextTracer
+
+ query Graphql::FakeQueryType
+ end
+
+ fake_tracer = Graphql::FakeTracer.new(lambda do |key, *args|
+ tracer_spy.trace(key, Gitlab::ApplicationContext.current)
+ end)
+
+ schema.tracer(fake_tracer)
+
+ schema
+ end
+
+ before do
+ allow(::Gitlab::Graphql::KnownOperations).to receive(:default).and_return(default_known_operations)
+ end
+
+ it "sets application context during execute_query and cleans up afterwards", :aggregate_failures do
+ dummy_schema.execute("query fooOperation { helloWorld }")
+
+ # "parse" is just an arbitrary trace event that isn't setting caller_id
+ expect(tracer_spy).to have_received(:trace).with("parse", hash_excluding("meta.caller_id"))
+ expect(tracer_spy).to have_received(:trace).with("execute_query", hash_including("meta.caller_id" => "graphql:fooOperation")).once
+ expect(Gitlab::ApplicationContext.current).not_to include("meta.caller_id")
+ end
+
+ it "sets caller_id when operation is not known" do
+ dummy_schema.execute("query fuzz { helloWorld }")
+
+ expect(tracer_spy).to have_received(:trace).with("execute_query", hash_including("meta.caller_id" => "graphql:unknown")).once
+ end
+end
diff --git a/spec/lib/gitlab/graphql/tracers/logger_tracer_spec.rb b/spec/lib/gitlab/graphql/tracers/logger_tracer_spec.rb
new file mode 100644
index 00000000000..d83ac4dabc5
--- /dev/null
+++ b/spec/lib/gitlab/graphql/tracers/logger_tracer_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+require "fast_spec_helper"
+require "support/graphql/fake_query_type"
+
+RSpec.describe Gitlab::Graphql::Tracers::LoggerTracer do
+ let(:dummy_schema) do
+ Class.new(GraphQL::Schema) do
+ # LoggerTracer depends on TimerTracer
+ use Gitlab::Graphql::Tracers::LoggerTracer
+ use Gitlab::Graphql::Tracers::TimerTracer
+
+ query_analyzer Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer.new
+
+ query Graphql::FakeQueryType
+ end
+ end
+
+ around do |example|
+ Gitlab::ApplicationContext.with_context(caller_id: 'caller_a', feature_category: 'feature_a') do
+ example.run
+ end
+ end
+
+ it "logs every query", :aggregate_failures do
+ variables = { name: "Ada Lovelace" }
+ query_string = 'query fooOperation($name: String) { helloWorld(message: $name) }'
+
+ # Build an actual query so we don't have to hardocde the "fingerprint" calculations
+ query = GraphQL::Query.new(dummy_schema, query_string, variables: variables)
+
+ expect(::Gitlab::GraphqlLogger).to receive(:info).with({
+ "correlation_id" => anything,
+ "meta.caller_id" => "caller_a",
+ "meta.feature_category" => "feature_a",
+ "query_analysis.duration_s" => kind_of(Numeric),
+ "query_analysis.complexity" => 1,
+ "query_analysis.depth" => 1,
+ "query_analysis.used_deprecated_fields" => [],
+ "query_analysis.used_fields" => ["FakeQuery.helloWorld"],
+ duration_s: be > 0,
+ is_mutation: false,
+ operation_fingerprint: query.operation_fingerprint,
+ operation_name: 'fooOperation',
+ query_fingerprint: query.fingerprint,
+ query_string: query_string,
+ trace_type: "execute_query",
+ variables: variables.to_s
+ })
+
+ dummy_schema.execute(query_string, variables: variables)
+ end
+end
diff --git a/spec/lib/gitlab/graphql/tracers/metrics_tracer_spec.rb b/spec/lib/gitlab/graphql/tracers/metrics_tracer_spec.rb
new file mode 100644
index 00000000000..ff6a76aa319
--- /dev/null
+++ b/spec/lib/gitlab/graphql/tracers/metrics_tracer_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+require "support/graphql/fake_query_type"
+
+RSpec.describe Gitlab::Graphql::Tracers::MetricsTracer do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:default_known_operations) { ::Gitlab::Graphql::KnownOperations.new(%w(lorem foo bar)) }
+
+ let(:fake_schema) do
+ Class.new(GraphQL::Schema) do
+ use Gitlab::Graphql::Tracers::ApplicationContextTracer
+ use Gitlab::Graphql::Tracers::MetricsTracer
+ use Gitlab::Graphql::Tracers::TimerTracer
+
+ query Graphql::FakeQueryType
+ end
+ end
+
+ around do |example|
+ ::Gitlab::ApplicationContext.with_context(feature_category: 'test_feature_category') do
+ example.run
+ end
+ end
+
+ before do
+ allow(::Gitlab::Graphql::KnownOperations).to receive(:default).and_return(default_known_operations)
+ end
+
+ describe 'when used as tracer and query is executed' do
+ where(:duration, :expected_success) do
+ 0.1 | true
+ 0.1 + ::Gitlab::EndpointAttributes::DEFAULT_URGENCY.duration | false
+ end
+
+ with_them do
+ it 'increments sli' do
+ # Trigger initialization
+ fake_schema
+
+ # setup timer
+ current_time = 0
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time) { current_time += duration }
+
+ expect(Gitlab::Metrics::RailsSlis.graphql_query_apdex).to receive(:increment).with(
+ labels: {
+ endpoint_id: 'graphql:lorem',
+ feature_category: 'test_feature_category',
+ query_urgency: ::Gitlab::EndpointAttributes::DEFAULT_URGENCY.name
+ },
+ success: expected_success
+ )
+
+ fake_schema.execute("query lorem { helloWorld }")
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/tracers/timer_tracer_spec.rb b/spec/lib/gitlab/graphql/tracers/timer_tracer_spec.rb
new file mode 100644
index 00000000000..7f837e28772
--- /dev/null
+++ b/spec/lib/gitlab/graphql/tracers/timer_tracer_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+require "fast_spec_helper"
+require "support/graphql/fake_tracer"
+require "support/graphql/fake_query_type"
+
+RSpec.describe Gitlab::Graphql::Tracers::TimerTracer do
+ let(:expected_duration) { 5 }
+ let(:tracer_spy) { spy('tracer_spy') }
+ let(:dummy_schema) do
+ schema = Class.new(GraphQL::Schema) do
+ use Gitlab::Graphql::Tracers::TimerTracer
+
+ query Graphql::FakeQueryType
+ end
+
+ schema.tracer(Graphql::FakeTracer.new(lambda { |*args| tracer_spy.trace(*args) }))
+
+ schema
+ end
+
+ before do
+ current_time = 0
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time) do
+ current_time += expected_duration
+ end
+ end
+
+ it "adds duration_s to the trace metadata", :aggregate_failures do
+ query_string = "query fooOperation { helloWorld }"
+
+ dummy_schema.execute(query_string)
+
+ # "parse" and "execute_query" are just arbitrary trace events
+ expect(tracer_spy).to have_received(:trace).with("parse", {
+ duration_s: expected_duration,
+ query_string: query_string
+ })
+ expect(tracer_spy).to have_received(:trace).with("execute_query", {
+ # greater than expected duration because other calls made to `.monotonic_time` are outside our control
+ duration_s: be >= expected_duration,
+ query: instance_of(GraphQL::Query)
+ })
+ end
+end
diff --git a/spec/lib/gitlab/health_checks/redis/redis_check_spec.rb b/spec/lib/gitlab/health_checks/redis/redis_check_spec.rb
index 43e890a6c4f..145d573b6de 100644
--- a/spec/lib/gitlab/health_checks/redis/redis_check_spec.rb
+++ b/spec/lib/gitlab/health_checks/redis/redis_check_spec.rb
@@ -4,5 +4,5 @@ require 'spec_helper'
require_relative '../simple_check_shared'
RSpec.describe Gitlab::HealthChecks::Redis::RedisCheck do
- include_examples 'simple_check', 'redis_ping', 'Redis', 'PONG'
+ include_examples 'simple_check', 'redis_ping', 'Redis', true
end
diff --git a/spec/lib/gitlab/import/database_helpers_spec.rb b/spec/lib/gitlab/import/database_helpers_spec.rb
index 079faed2518..05d1c0ae078 100644
--- a/spec/lib/gitlab/import/database_helpers_spec.rb
+++ b/spec/lib/gitlab/import/database_helpers_spec.rb
@@ -16,8 +16,8 @@ RSpec.describe Gitlab::Import::DatabaseHelpers do
let(:project) { create(:project) }
it 'returns the ID returned by the query' do
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
+ expect(ApplicationRecord)
+ .to receive(:legacy_bulk_insert)
.with(Issue.table_name, [attributes], return_ids: true)
.and_return([10])
diff --git a/spec/lib/gitlab/import/metrics_spec.rb b/spec/lib/gitlab/import/metrics_spec.rb
index 035294a620f..9b8b58d00f3 100644
--- a/spec/lib/gitlab/import/metrics_spec.rb
+++ b/spec/lib/gitlab/import/metrics_spec.rb
@@ -94,20 +94,6 @@ RSpec.describe Gitlab::Import::Metrics, :aggregate_failures do
expect(histogram).to have_received(:observe).with({ importer: :test_importer }, anything)
end
end
-
- context 'when project is a github import' do
- before do
- project.import_type = 'github'
- end
-
- it 'emits importer metrics' do
- expect(subject).to receive(:track_usage_event).with(:github_import_project_success, project.id)
-
- subject.track_finished_import
-
- expect(histogram).to have_received(:observe).with({ project: project.full_path }, anything)
- end
- end
end
describe '#issues_counter' do
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 10f0e687077..b474f5825fd 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -60,6 +60,7 @@ issues:
- incident_management_issuable_escalation_status
- pending_escalations
- customer_relations_contacts
+- issue_customer_relations_contacts
work_item_type:
- issues
events:
@@ -132,6 +133,7 @@ project_members:
- user
- source
- project
+- member_task
merge_requests:
- status_check_responses
- subscriptions
@@ -382,6 +384,7 @@ project:
- emails_on_push_integration
- pipelines_email_integration
- mattermost_slash_commands_integration
+- shimo_integration
- slack_slash_commands_integration
- irker_integration
- packagist_integration
diff --git a/spec/lib/gitlab/import_export/attributes_permitter_spec.rb b/spec/lib/gitlab/import_export/attributes_permitter_spec.rb
index 2b974f8985d..8ae387d95e3 100644
--- a/spec/lib/gitlab/import_export/attributes_permitter_spec.rb
+++ b/spec/lib/gitlab/import_export/attributes_permitter_spec.rb
@@ -80,25 +80,66 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter do
let(:attributes_permitter) { described_class.new }
- where(:relation_name, :permitted_attributes_defined) do
- :user | false
- :author | false
- :ci_cd_settings | true
- :metrics_setting | true
- :project_badges | true
- :pipeline_schedules | true
- :error_tracking_setting | true
- :auto_devops | true
- :boards | true
- :custom_attributes | true
- :labels | true
- :protected_branches | true
- :protected_tags | true
- :create_access_levels | true
- :merge_access_levels | true
- :push_access_levels | true
- :releases | true
- :links | true
+ where(:relation_name, :permitted_attributes_defined ) do
+ :user | true
+ :author | false
+ :ci_cd_settings | true
+ :metrics_setting | true
+ :project_badges | true
+ :pipeline_schedules | true
+ :error_tracking_setting | true
+ :auto_devops | true
+ :boards | true
+ :custom_attributes | true
+ :label | true
+ :labels | true
+ :protected_branches | true
+ :protected_tags | true
+ :create_access_levels | true
+ :merge_access_levels | true
+ :push_access_levels | true
+ :releases | true
+ :links | true
+ :priorities | true
+ :milestone | true
+ :milestones | true
+ :snippets | true
+ :project_members | true
+ :merge_request | true
+ :merge_requests | true
+ :award_emoji | true
+ :commit_author | true
+ :committer | true
+ :events | true
+ :label_links | true
+ :merge_request_diff | true
+ :merge_request_diff_commits | true
+ :merge_request_diff_files | true
+ :metrics | true
+ :notes | true
+ :push_event_payload | true
+ :resource_label_events | true
+ :suggestions | true
+ :system_note_metadata | true
+ :timelogs | true
+ :container_expiration_policy | true
+ :project_feature | true
+ :prometheus_metrics | true
+ :service_desk_setting | true
+ :external_pull_request | true
+ :external_pull_requests | true
+ :statuses | true
+ :ci_pipelines | true
+ :stages | true
+ :actions | true
+ :design | true
+ :designs | true
+ :design_versions | true
+ :issue_assignees | true
+ :sentry_issue | true
+ :zoom_meetings | true
+ :issues | true
+ :group_members | true
end
with_them do
@@ -109,9 +150,11 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter do
describe 'included_attributes for Project' do
subject { described_class.new }
+ additional_attributes = { user: %w[id] }
+
Gitlab::ImportExport::Config.new.to_h[:included_attributes].each do |relation_sym, permitted_attributes|
context "for #{relation_sym}" do
- it_behaves_like 'a permitted attribute', relation_sym, permitted_attributes
+ it_behaves_like 'a permitted attribute', relation_sym, permitted_attributes, additional_attributes[relation_sym]
end
end
end
diff --git a/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb b/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
index fc08a13a8bd..d5f31f235f5 100644
--- a/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
+++ b/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
@@ -207,9 +207,9 @@ RSpec.describe Gitlab::ImportExport::FastHashSerializer do
context 'relation ordering' do
it 'orders exported pipelines by primary key' do
- expected_order = project.ci_pipelines.reorder(:id).ids
+ expected_order = project.ci_pipelines.reorder(:id).pluck(:sha)
- expect(subject['ci_pipelines'].pluck('id')).to eq(expected_order)
+ expect(subject['ci_pipelines'].pluck('sha')).to eq(expected_order)
end
end
diff --git a/spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb
new file mode 100644
index 00000000000..473dbf5ecc5
--- /dev/null
+++ b/spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+# This spec is a lightweight version of:
+# * project/tree_restorer_spec.rb
+#
+# In depth testing is being done in the above specs.
+# This spec tests that restore project works
+# but does not have 100% relation coverage.
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::ImportExport::Group::RelationTreeRestorer do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:importable) { create(:group, parent: group) }
+
+ include_context 'relation tree restorer shared context' do
+ let(:importable_name) { nil }
+ end
+
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/group_exports/no_children/group.json' }
+ let(:relation_reader) do
+ Gitlab::ImportExport::Json::LegacyReader::File.new(
+ path,
+ relation_names: reader.group_relation_names)
+ end
+
+ let(:reader) do
+ Gitlab::ImportExport::Reader.new(
+ shared: shared,
+ config: Gitlab::ImportExport::Config.new(config: Gitlab::ImportExport.legacy_group_config_file).to_h
+ )
+ end
+
+ let(:relation_tree_restorer) do
+ described_class.new(
+ user: user,
+ shared: shared,
+ relation_reader: relation_reader,
+ object_builder: Gitlab::ImportExport::Group::ObjectBuilder,
+ members_mapper: members_mapper,
+ relation_factory: Gitlab::ImportExport::Group::RelationFactory,
+ reader: reader,
+ importable: importable,
+ importable_path: nil,
+ importable_attributes: attributes
+ )
+ end
+
+ subject { relation_tree_restorer.restore }
+
+ shared_examples 'logging of relations creation' do
+ context 'when log_import_export_relation_creation feature flag is enabled' do
+ before do
+ stub_feature_flags(log_import_export_relation_creation: group)
+ end
+
+ it 'logs top-level relation creation' do
+ expect(shared.logger)
+ .to receive(:info)
+ .with(hash_including(message: '[Project/Group Import] Created new object relation'))
+ .at_least(:once)
+
+ subject
+ end
+ end
+
+ context 'when log_import_export_relation_creation feature flag is disabled' do
+ before do
+ stub_feature_flags(log_import_export_relation_creation: false)
+ end
+
+ it 'does not log top-level relation creation' do
+ expect(shared.logger)
+ .to receive(:info)
+ .with(hash_including(message: '[Project/Group Import] Created new object relation'))
+ .never
+
+ subject
+ end
+ end
+ end
+
+ it 'restores group tree' do
+ expect(subject).to eq(true)
+ end
+
+ include_examples 'logging of relations creation'
+end
diff --git a/spec/lib/gitlab/import_export/project/object_builder_spec.rb b/spec/lib/gitlab/import_export/project/object_builder_spec.rb
index 4c9f9f7c690..189b798c2e8 100644
--- a/spec/lib/gitlab/import_export/project/object_builder_spec.rb
+++ b/spec/lib/gitlab/import_export/project/object_builder_spec.rb
@@ -123,6 +123,24 @@ RSpec.describe Gitlab::ImportExport::Project::ObjectBuilder do
expect(milestone.persisted?).to be true
end
+
+ context 'with clashing iid' do
+ it 'creates milestone and claims iid for the new milestone' do
+ clashing_iid = 1
+ create(:milestone, iid: clashing_iid, project: project)
+
+ milestone = described_class.build(Milestone,
+ 'iid' => clashing_iid,
+ 'title' => 'milestone',
+ 'project' => project,
+ 'group' => nil,
+ 'group_id' => nil)
+
+ expect(milestone.persisted?).to be true
+ expect(Milestone.count).to eq(2)
+ expect(milestone.iid).to eq(clashing_iid)
+ end
+ end
end
context 'merge_request' do
@@ -176,4 +194,118 @@ RSpec.describe Gitlab::ImportExport::Project::ObjectBuilder do
expect(found.email).to eq('alice@example.com')
end
end
+
+ context 'merge request diff commits' do
+ context 'when the "committer" object is present' do
+ it 'uses this object as the committer' do
+ user = MergeRequest::DiffCommitUser
+ .find_or_create('Alice', 'alice@example.com')
+
+ commit = described_class.build(
+ MergeRequestDiffCommit,
+ {
+ 'committer' => user,
+ 'committer_name' => 'Bla',
+ 'committer_email' => 'bla@example.com',
+ 'author_name' => 'Bla',
+ 'author_email' => 'bla@example.com'
+ }
+ )
+
+ expect(commit.committer).to eq(user)
+ end
+ end
+
+ context 'when the "committer" object is missing' do
+ it 'creates one from the committer name and Email' do
+ commit = described_class.build(
+ MergeRequestDiffCommit,
+ {
+ 'committer_name' => 'Alice',
+ 'committer_email' => 'alice@example.com',
+ 'author_name' => 'Alice',
+ 'author_email' => 'alice@example.com'
+ }
+ )
+
+ expect(commit.committer.name).to eq('Alice')
+ expect(commit.committer.email).to eq('alice@example.com')
+ end
+ end
+
+ context 'when the "commit_author" object is present' do
+ it 'uses this object as the author' do
+ user = MergeRequest::DiffCommitUser
+ .find_or_create('Alice', 'alice@example.com')
+
+ commit = described_class.build(
+ MergeRequestDiffCommit,
+ {
+ 'committer_name' => 'Alice',
+ 'committer_email' => 'alice@example.com',
+ 'commit_author' => user,
+ 'author_name' => 'Bla',
+ 'author_email' => 'bla@example.com'
+ }
+ )
+
+ expect(commit.commit_author).to eq(user)
+ end
+ end
+
+ context 'when the "commit_author" object is missing' do
+ it 'creates one from the author name and Email' do
+ commit = described_class.build(
+ MergeRequestDiffCommit,
+ {
+ 'committer_name' => 'Alice',
+ 'committer_email' => 'alice@example.com',
+ 'author_name' => 'Alice',
+ 'author_email' => 'alice@example.com'
+ }
+ )
+
+ expect(commit.commit_author.name).to eq('Alice')
+ expect(commit.commit_author.email).to eq('alice@example.com')
+ end
+ end
+ end
+
+ describe '#find_or_create_diff_commit_user' do
+ context 'when the user already exists' do
+ it 'returns the existing user' do
+ user = MergeRequest::DiffCommitUser
+ .find_or_create('Alice', 'alice@example.com')
+
+ found = described_class
+ .new(MergeRequestDiffCommit, {})
+ .send(:find_or_create_diff_commit_user, user.name, user.email)
+
+ expect(found).to eq(user)
+ end
+ end
+
+ context 'when the user does not exist' do
+ it 'creates the user' do
+ found = described_class
+ .new(MergeRequestDiffCommit, {})
+ .send(:find_or_create_diff_commit_user, 'Alice', 'alice@example.com')
+
+ expect(found.name).to eq('Alice')
+ expect(found.email).to eq('alice@example.com')
+ end
+ end
+
+ it 'caches the results' do
+ builder = described_class.new(MergeRequestDiffCommit, {})
+
+ builder.send(:find_or_create_diff_commit_user, 'Alice', 'alice@example.com')
+
+ record = ActiveRecord::QueryRecorder.new do
+ builder.send(:find_or_create_diff_commit_user, 'Alice', 'alice@example.com')
+ end
+
+ expect(record.count).to eq(1)
+ end
+ end
end
diff --git a/spec/lib/gitlab/import_export/project/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/relation_tree_restorer_spec.rb
new file mode 100644
index 00000000000..5ebace263ba
--- /dev/null
+++ b/spec/lib/gitlab/import_export/project/relation_tree_restorer_spec.rb
@@ -0,0 +1,150 @@
+# frozen_string_literal: true
+
+# This spec is a lightweight version of:
+# * project/tree_restorer_spec.rb
+#
+# In depth testing is being done in the above specs.
+# This spec tests that restore project works
+# but does not have 100% relation coverage.
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::ImportExport::Project::RelationTreeRestorer do
+ let_it_be(:importable, reload: true) do
+ create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project')
+ end
+
+ include_context 'relation tree restorer shared context' do
+ let(:importable_name) { 'project' }
+ end
+
+ let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
+ let(:relation_tree_restorer) do
+ described_class.new(
+ user: user,
+ shared: shared,
+ relation_reader: relation_reader,
+ object_builder: Gitlab::ImportExport::Project::ObjectBuilder,
+ members_mapper: members_mapper,
+ relation_factory: Gitlab::ImportExport::Project::RelationFactory,
+ reader: reader,
+ importable: importable,
+ importable_path: 'project',
+ importable_attributes: attributes
+ )
+ end
+
+ subject { relation_tree_restorer.restore }
+
+ shared_examples 'import project successfully' do
+ describe 'imported project' do
+ it 'has the project attributes and relations', :aggregate_failures do
+ expect(subject).to eq(true)
+
+ project = Project.find_by_path('project')
+
+ expect(project.description).to eq('Nisi et repellendus ut enim quo accusamus vel magnam.')
+ expect(project.labels.count).to eq(3)
+ expect(project.boards.count).to eq(1)
+ expect(project.project_feature).not_to be_nil
+ expect(project.custom_attributes.count).to eq(2)
+ expect(project.project_badges.count).to eq(2)
+ expect(project.snippets.count).to eq(1)
+ end
+ end
+ end
+
+ shared_examples 'logging of relations creation' do
+ context 'when log_import_export_relation_creation feature flag is enabled' do
+ before do
+ stub_feature_flags(log_import_export_relation_creation: group)
+ end
+
+ it 'logs top-level relation creation' do
+ expect(shared.logger)
+ .to receive(:info)
+ .with(hash_including(message: '[Project/Group Import] Created new object relation'))
+ .at_least(:once)
+
+ subject
+ end
+ end
+
+ context 'when log_import_export_relation_creation feature flag is disabled' do
+ before do
+ stub_feature_flags(log_import_export_relation_creation: false)
+ end
+
+ it 'does not log top-level relation creation' do
+ expect(shared.logger)
+ .to receive(:info)
+ .with(hash_including(message: '[Project/Group Import] Created new object relation'))
+ .never
+
+ subject
+ end
+ end
+ end
+
+ context 'with legacy reader' do
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/project.json' }
+ let(:relation_reader) do
+ Gitlab::ImportExport::Json::LegacyReader::File.new(
+ path,
+ relation_names: reader.project_relation_names,
+ allowed_path: 'project'
+ )
+ end
+
+ let(:attributes) { relation_reader.consume_attributes('project') }
+
+ it_behaves_like 'import project successfully'
+
+ context 'with logging of relations creation' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:importable) do
+ create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project', group: group)
+ end
+
+ include_examples 'logging of relations creation'
+ end
+ end
+
+ context 'with ndjson reader' do
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/tree' }
+ let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
+
+ it_behaves_like 'import project successfully'
+
+ context 'when inside a group' do
+ let_it_be(:group) do
+ create(:group, :disabled_and_unoverridable)
+ end
+
+ before do
+ importable.update!(shared_runners_enabled: false, group: group)
+ end
+
+ it_behaves_like 'import project successfully'
+ end
+ end
+
+ context 'with invalid relations' do
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/project_with_invalid_relations/tree' }
+ let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
+
+ it 'logs the invalid relation and its errors' do
+ expect(shared.logger)
+ .to receive(:warn)
+ .with(
+ error_messages: "Title can't be blank. Title is invalid",
+ message: '[Project/Group Import] Invalid object relation built',
+ relation_class: 'ProjectLabel',
+ relation_index: 0,
+ relation_key: 'labels'
+ ).once
+
+ relation_tree_restorer.restore
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
index f6a028383f2..3dab84af744 100644
--- a/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb
@@ -10,19 +10,26 @@
require 'spec_helper'
RSpec.describe Gitlab::ImportExport::Project::Sample::RelationTreeRestorer do
- include_context 'relation tree restorer shared context'
+ let_it_be(:importable) { create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project') }
+ include_context 'relation tree restorer shared context' do
+ let(:importable_name) { 'project' }
+ end
+
+ let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/sample_data/tree' }
+ let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
let(:sample_data_relation_tree_restorer) do
described_class.new(
user: user,
shared: shared,
relation_reader: relation_reader,
- object_builder: object_builder,
+ object_builder: Gitlab::ImportExport::Project::ObjectBuilder,
members_mapper: members_mapper,
- relation_factory: relation_factory,
+ relation_factory: Gitlab::ImportExport::Project::Sample::RelationFactory,
reader: reader,
importable: importable,
- importable_path: importable_path,
+ importable_path: 'project',
importable_attributes: attributes
)
end
@@ -69,32 +76,21 @@ RSpec.describe Gitlab::ImportExport::Project::Sample::RelationTreeRestorer do
end
end
- context 'when restoring a project' do
- let(:importable) { create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project') }
- let(:importable_name) { 'project' }
- let(:importable_path) { 'project' }
- let(:object_builder) { Gitlab::ImportExport::Project::ObjectBuilder }
- let(:relation_factory) { Gitlab::ImportExport::Project::Sample::RelationFactory }
- let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
- let(:path) { 'spec/fixtures/lib/gitlab/import_export/sample_data/tree' }
- let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
-
- it 'initializes relation_factory with date_calculator as parameter' do
- expect(Gitlab::ImportExport::Project::Sample::RelationFactory).to receive(:create).with(hash_including(:date_calculator)).at_least(:once).times
+ it 'initializes relation_factory with date_calculator as parameter' do
+ expect(Gitlab::ImportExport::Project::Sample::RelationFactory).to receive(:create).with(hash_including(:date_calculator)).at_least(:once).times
- subject
- end
+ subject
+ end
- context 'when relation tree restorer is initialized' do
- it 'initializes date calculator with due dates' do
- expect(Gitlab::ImportExport::Project::Sample::DateCalculator).to receive(:new).with(Array)
+ context 'when relation tree restorer is initialized' do
+ it 'initializes date calculator with due dates' do
+ expect(Gitlab::ImportExport::Project::Sample::DateCalculator).to receive(:new).with(Array)
- sample_data_relation_tree_restorer
- end
+ sample_data_relation_tree_restorer
end
+ end
- context 'using ndjson reader' do
- it_behaves_like 'import project successfully'
- end
+ context 'using ndjson reader' do
+ it_behaves_like 'import project successfully'
end
end
diff --git a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
index f512f49764d..cd3d29f1a51 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
]
RSpec::Mocks.with_temporary_scope do
- @project = create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project')
+ @project = create(:project, :repository, :builds_enabled, :issues_disabled, name: 'project', path: 'project')
@shared = @project.import_export_shared
stub_all_feature_flags
@@ -36,7 +36,6 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
allow_any_instance_of(Gitlab::Git::Repository).to receive(:branch_exists?).and_return(false)
expect(@shared).not_to receive(:error)
- expect_any_instance_of(Gitlab::Git::Repository).to receive(:create_branch).with('feature', 'DCBA')
allow_any_instance_of(Gitlab::Git::Repository).to receive(:create_branch)
project_tree_restorer = described_class.new(user: @user, shared: @shared, project: @project)
diff --git a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
index 374d688576e..f68ec21039d 100644
--- a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
@@ -5,6 +5,9 @@ require 'spec_helper'
RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
let_it_be(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
let_it_be(:exportable_path) { 'project' }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { setup_project }
shared_examples 'saves project tree successfully' do |ndjson_enabled|
include ImportExport::CommonUtil
@@ -12,9 +15,6 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
subject { get_json(full_path, exportable_path, relation_name, ndjson_enabled) }
describe 'saves project tree attributes' do
- let_it_be(:user) { create(:user) }
- let_it_be(:group) { create(:group) }
- let_it_be(:project) { setup_project }
let_it_be(:shared) { project.import_export_shared }
let(:relation_name) { :projects }
@@ -402,6 +402,50 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
it_behaves_like "saves project tree successfully", true
end
+ context 'when streaming has to retry', :aggregate_failures do
+ let(:shared) { double('shared', export_path: exportable_path) }
+ let(:logger) { Gitlab::Import::Logger.build }
+ let(:serializer) { double('serializer') }
+ let(:error_class) { Net::OpenTimeout }
+ let(:info_params) do
+ {
+ 'error.class': error_class,
+ project_name: project.name,
+ project_id: project.id
+ }
+ end
+
+ before do
+ allow(Gitlab::ImportExport::Json::StreamingSerializer).to receive(:new).and_return(serializer)
+ end
+
+ subject(:project_tree_saver) do
+ described_class.new(project: project, current_user: user, shared: shared, logger: logger)
+ end
+
+ it 'retries and succeeds' do
+ call_count = 0
+ allow(serializer).to receive(:execute) do
+ call_count += 1
+ call_count > 1 ? true : raise(error_class, 'execution expired')
+ end
+
+ expect(logger).to receive(:info).with(hash_including(info_params)).once
+
+ expect(project_tree_saver.save).to be(true)
+ end
+
+ it 'retries and does not succeed' do
+ retry_count = 3
+ allow(serializer).to receive(:execute).and_raise(error_class, 'execution expired')
+
+ expect(logger).to receive(:info).with(hash_including(info_params)).exactly(retry_count).times
+ expect(shared).to receive(:error).with(instance_of(error_class))
+
+ expect(project_tree_saver.save).to be(false)
+ end
+ end
+
def setup_project
release = create(:release)
diff --git a/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
deleted file mode 100644
index 5e4075c2b59..00000000000
--- a/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
+++ /dev/null
@@ -1,184 +0,0 @@
-# frozen_string_literal: true
-
-# This spec is a lightweight version of:
-# * project/tree_restorer_spec.rb
-#
-# In depth testing is being done in the above specs.
-# This spec tests that restore project works
-# but does not have 100% relation coverage.
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::ImportExport::RelationTreeRestorer do
- include_context 'relation tree restorer shared context'
-
- let(:relation_tree_restorer) do
- described_class.new(
- user: user,
- shared: shared,
- relation_reader: relation_reader,
- object_builder: object_builder,
- members_mapper: members_mapper,
- relation_factory: relation_factory,
- reader: reader,
- importable: importable,
- importable_path: importable_path,
- importable_attributes: attributes
- )
- end
-
- subject { relation_tree_restorer.restore }
-
- shared_examples 'import project successfully' do
- describe 'imported project' do
- it 'has the project attributes and relations', :aggregate_failures do
- expect(subject).to eq(true)
-
- project = Project.find_by_path('project')
-
- expect(project.description).to eq('Nisi et repellendus ut enim quo accusamus vel magnam.')
- expect(project.labels.count).to eq(3)
- expect(project.boards.count).to eq(1)
- expect(project.project_feature).not_to be_nil
- expect(project.custom_attributes.count).to eq(2)
- expect(project.project_badges.count).to eq(2)
- expect(project.snippets.count).to eq(1)
- end
- end
- end
-
- shared_examples 'logging of relations creation' do
- context 'when log_import_export_relation_creation feature flag is enabled' do
- before do
- stub_feature_flags(log_import_export_relation_creation: group)
- end
-
- it 'logs top-level relation creation' do
- expect(relation_tree_restorer.shared.logger)
- .to receive(:info)
- .with(hash_including(message: '[Project/Group Import] Created new object relation'))
- .at_least(:once)
-
- subject
- end
- end
-
- context 'when log_import_export_relation_creation feature flag is disabled' do
- before do
- stub_feature_flags(log_import_export_relation_creation: false)
- end
-
- it 'does not log top-level relation creation' do
- expect(relation_tree_restorer.shared.logger)
- .to receive(:info)
- .with(hash_including(message: '[Project/Group Import] Created new object relation'))
- .never
-
- subject
- end
- end
- end
-
- context 'when restoring a project' do
- let_it_be(:importable, reload: true) do
- create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project')
- end
-
- let(:importable_name) { 'project' }
- let(:importable_path) { 'project' }
- let(:object_builder) { Gitlab::ImportExport::Project::ObjectBuilder }
- let(:relation_factory) { Gitlab::ImportExport::Project::RelationFactory }
- let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
-
- context 'using legacy reader' do
- let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/project.json' }
- let(:relation_reader) do
- Gitlab::ImportExport::Json::LegacyReader::File.new(
- path,
- relation_names: reader.project_relation_names,
- allowed_path: 'project'
- )
- end
-
- let(:attributes) { relation_reader.consume_attributes('project') }
-
- it_behaves_like 'import project successfully'
-
- context 'logging of relations creation' do
- let_it_be(:group) { create(:group) }
- let_it_be(:importable) do
- create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project', group: group)
- end
-
- include_examples 'logging of relations creation'
- end
- end
-
- context 'using ndjson reader' do
- let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/tree' }
- let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
-
- it_behaves_like 'import project successfully'
-
- context 'when inside a group' do
- let_it_be(:group) do
- create(:group, :disabled_and_unoverridable)
- end
-
- before do
- importable.update!(shared_runners_enabled: false, group: group)
- end
-
- it_behaves_like 'import project successfully'
- end
- end
-
- context 'with invalid relations' do
- let(:path) { 'spec/fixtures/lib/gitlab/import_export/project_with_invalid_relations/tree' }
- let(:relation_reader) { Gitlab::ImportExport::Json::NdjsonReader.new(path) }
-
- it 'logs the invalid relation and its errors' do
- expect(relation_tree_restorer.shared.logger)
- .to receive(:warn)
- .with(
- error_messages: "Title can't be blank. Title is invalid",
- message: '[Project/Group Import] Invalid object relation built',
- relation_class: 'ProjectLabel',
- relation_index: 0,
- relation_key: 'labels'
- ).once
-
- relation_tree_restorer.restore
- end
- end
- end
-
- context 'when restoring a group' do
- let_it_be(:group) { create(:group) }
- let_it_be(:importable) { create(:group, parent: group) }
-
- let(:path) { 'spec/fixtures/lib/gitlab/import_export/group_exports/no_children/group.json' }
- let(:importable_name) { nil }
- let(:importable_path) { nil }
- let(:object_builder) { Gitlab::ImportExport::Group::ObjectBuilder }
- let(:relation_factory) { Gitlab::ImportExport::Group::RelationFactory }
- let(:relation_reader) do
- Gitlab::ImportExport::Json::LegacyReader::File.new(
- path,
- relation_names: reader.group_relation_names)
- end
-
- let(:reader) do
- Gitlab::ImportExport::Reader.new(
- shared: shared,
- config: Gitlab::ImportExport::Config.new(config: Gitlab::ImportExport.legacy_group_config_file).to_h
- )
- end
-
- it 'restores group tree' do
- expect(subject).to eq(true)
- end
-
- include_examples 'logging of relations creation'
- end
-end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 4b125cab49b..9daa3b32fd1 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -561,6 +561,7 @@ Project:
- require_password_to_approve
- autoclose_referenced_issues
- suggestion_commit_message
+- merge_commit_template
ProjectTracingSetting:
- external_url
Author:
@@ -692,6 +693,7 @@ ProjectCiCdSetting:
ProjectSetting:
- allow_merge_on_skipped_pipeline
- has_confluence
+- has_shimo
- has_vulnerabilities
ProtectedEnvironment:
- id
diff --git a/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb b/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb
index b2a11353d0c..09280402e2b 100644
--- a/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb
+++ b/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb
@@ -111,45 +111,4 @@ RSpec.describe Gitlab::Instrumentation::RedisInterceptor, :clean_gitlab_redis_sh
end
end
end
-
- context 'when a command takes longer than DURATION_ERROR_THRESHOLD' do
- let(:threshold) { 0.5 }
-
- before do
- stub_const("#{described_class}::DURATION_ERROR_THRESHOLD", threshold)
- end
-
- context 'when report_on_long_redis_durations is disabled' do
- it 'does nothing' do
- stub_feature_flags(report_on_long_redis_durations: false)
-
- expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
-
- Gitlab::Redis::SharedState.with { |r| r.mget('foo', 'foo') { sleep threshold + 0.1 } }
- end
- end
-
- context 'when report_on_long_redis_durations is enabled' do
- context 'for an instance other than SharedState' do
- it 'does nothing' do
- expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
-
- Gitlab::Redis::Queues.with { |r| r.mget('foo', 'foo') { sleep threshold + 0.1 } }
- end
- end
-
- context 'for the SharedState instance' do
- it 'tracks an exception and continues' do
- expect(Gitlab::ErrorTracking)
- .to receive(:track_exception)
- .with(an_instance_of(described_class::MysteryRedisDurationError),
- command: 'mget',
- duration: be > threshold,
- timestamp: a_string_matching(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{5}/))
-
- Gitlab::Redis::SharedState.with { |r| r.mget('foo', 'foo') { sleep threshold + 0.1 } }
- end
- end
- end
- end
end
diff --git a/spec/lib/gitlab/instrumentation_helper_spec.rb b/spec/lib/gitlab/instrumentation_helper_spec.rb
index 52d3623c304..a9663012e9a 100644
--- a/spec/lib/gitlab/instrumentation_helper_spec.rb
+++ b/spec/lib/gitlab/instrumentation_helper_spec.rb
@@ -147,6 +147,25 @@ RSpec.describe Gitlab::InstrumentationHelper do
expect(payload).not_to include(:caught_up_replica_pick_fail)
end
end
+
+ context 'when there is an uploaded file' do
+ it 'adds upload data' do
+ uploaded_file = UploadedFile.from_params({
+ 'name' => 'dir/foo.txt',
+ 'sha256' => 'sha256',
+ 'remote_url' => 'http://localhost/file',
+ 'remote_id' => '1234567890',
+ 'etag' => 'etag1234567890',
+ 'upload_duration' => '5.05',
+ 'size' => '123456'
+ }, nil)
+
+ subject
+
+ expect(payload[:uploaded_file_upload_duration_s]).to eq(uploaded_file.upload_duration)
+ expect(payload[:uploaded_file_size_bytes]).to eq(uploaded_file.size)
+ end
+ end
end
describe 'duration calculations' do
diff --git a/spec/lib/gitlab/issues/rebalancing/state_spec.rb b/spec/lib/gitlab/issues/rebalancing/state_spec.rb
index bdd0dbd365d..a849330ad35 100644
--- a/spec/lib/gitlab/issues/rebalancing/state_spec.rb
+++ b/spec/lib/gitlab/issues/rebalancing/state_spec.rb
@@ -94,7 +94,7 @@ RSpec.describe Gitlab::Issues::Rebalancing::State, :clean_gitlab_redis_shared_st
context 'when tracking new rebalance' do
it 'returns as expired for non existent key' do
::Gitlab::Redis::SharedState.with do |redis|
- expect(redis.ttl(rebalance_caching.send(:concurrent_running_rebalances_key))).to be < 0
+ expect(redis.ttl(Gitlab::Issues::Rebalancing::State::CONCURRENT_RUNNING_REBALANCES_KEY)).to be < 0
end
end
@@ -102,7 +102,7 @@ RSpec.describe Gitlab::Issues::Rebalancing::State, :clean_gitlab_redis_shared_st
rebalance_caching.track_new_running_rebalance
::Gitlab::Redis::SharedState.with do |redis|
- expect(redis.ttl(rebalance_caching.send(:concurrent_running_rebalances_key))).to be_between(0, described_class::REDIS_EXPIRY_TIME.ago.to_i)
+ expect(redis.ttl(Gitlab::Issues::Rebalancing::State::CONCURRENT_RUNNING_REBALANCES_KEY)).to be_between(0, described_class::REDIS_EXPIRY_TIME.ago.to_i)
end
end
end
@@ -169,7 +169,7 @@ RSpec.describe Gitlab::Issues::Rebalancing::State, :clean_gitlab_redis_shared_st
rebalance_caching.cleanup_cache
- expect(check_existing_keys).to eq(0)
+ expect(check_existing_keys).to eq(1)
end
end
end
@@ -183,6 +183,16 @@ RSpec.describe Gitlab::Issues::Rebalancing::State, :clean_gitlab_redis_shared_st
it { expect(rebalance_caching.send(:rebalanced_container_type)).to eq(described_class::NAMESPACE) }
it_behaves_like 'issues rebalance caching'
+
+ describe '.fetch_rebalancing_groups_and_projects' do
+ before do
+ rebalance_caching.track_new_running_rebalance
+ end
+
+ it 'caches recently finished rebalance key' do
+ expect(described_class.fetch_rebalancing_groups_and_projects).to eq([[group.id], []])
+ end
+ end
end
context 'rebalancing issues in a project' do
@@ -193,6 +203,16 @@ RSpec.describe Gitlab::Issues::Rebalancing::State, :clean_gitlab_redis_shared_st
it { expect(rebalance_caching.send(:rebalanced_container_type)).to eq(described_class::PROJECT) }
it_behaves_like 'issues rebalance caching'
+
+ describe '.fetch_rebalancing_groups_and_projects' do
+ before do
+ rebalance_caching.track_new_running_rebalance
+ end
+
+ it 'caches recently finished rebalance key' do
+ expect(described_class.fetch_rebalancing_groups_and_projects).to eq([[], [project.id]])
+ end
+ end
end
# count - how many issue ids to generate, issue ids will start at 1
@@ -212,11 +232,14 @@ RSpec.describe Gitlab::Issues::Rebalancing::State, :clean_gitlab_redis_shared_st
def check_existing_keys
index = 0
+ # spec only, we do not actually scan keys in the code
+ recently_finished_keys_count = Gitlab::Redis::SharedState.with { |redis| redis.scan(0, match: "#{described_class::RECENTLY_FINISHED_REBALANCE_PREFIX}:*") }.last.count
index += 1 if rebalance_caching.get_current_index > 0
index += 1 if rebalance_caching.get_current_project_id.present?
index += 1 if rebalance_caching.get_cached_issue_ids(0, 100).present?
index += 1 if rebalance_caching.rebalance_in_progress?
+ index += 1 if recently_finished_keys_count > 0
index
end
diff --git a/spec/lib/gitlab/lograge/custom_options_spec.rb b/spec/lib/gitlab/lograge/custom_options_spec.rb
index 9daedfc37e4..a4ae39a835a 100644
--- a/spec/lib/gitlab/lograge/custom_options_spec.rb
+++ b/spec/lib/gitlab/lograge/custom_options_spec.rb
@@ -19,7 +19,13 @@ RSpec.describe Gitlab::Lograge::CustomOptions do
user_id: 'test',
cf_ray: SecureRandom.hex,
cf_request_id: SecureRandom.hex,
- metadata: { 'meta.user' => 'jane.doe' }
+ metadata: { 'meta.user' => 'jane.doe' },
+ request_urgency: :default,
+ target_duration_s: 1,
+ remote_ip: '192.168.1.2',
+ ua: 'Nyxt',
+ queue_duration_s: 0.2,
+ etag_route: '/etag'
}
end
@@ -66,6 +72,18 @@ RSpec.describe Gitlab::Lograge::CustomOptions do
end
end
+ context 'trusted payload' do
+ it { is_expected.to include(event_payload.slice(*described_class::KNOWN_PAYLOAD_PARAMS)) }
+
+ context 'payload with rejected fields' do
+ let(:event_payload) { { params: {}, request_urgency: :high, something: 'random', username: nil } }
+
+ it { is_expected.to include({ request_urgency: :high }) }
+ it { is_expected.not_to include({ something: 'random' }) }
+ it { is_expected.not_to include({ username: nil }) }
+ end
+ end
+
context 'when correlation_id is overridden' do
let(:correlation_id_key) { Labkit::Correlation::CorrelationId::LOG_KEY }
diff --git a/spec/lib/gitlab/merge_requests/merge_commit_message_spec.rb b/spec/lib/gitlab/merge_requests/merge_commit_message_spec.rb
new file mode 100644
index 00000000000..884f8df5e56
--- /dev/null
+++ b/spec/lib/gitlab/merge_requests/merge_commit_message_spec.rb
@@ -0,0 +1,219 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::MergeRequests::MergeCommitMessage do
+ let(:merge_commit_template) { nil }
+ let(:project) { create(:project, :public, :repository, merge_commit_template: merge_commit_template) }
+ let(:user) { project.creator }
+ let(:merge_request_description) { "Merge Request Description\nNext line" }
+ let(:merge_request_title) { 'Bugfix' }
+ let(:merge_request) do
+ create(
+ :merge_request,
+ :simple,
+ source_project: project,
+ target_project: project,
+ author: user,
+ description: merge_request_description,
+ title: merge_request_title
+ )
+ end
+
+ subject { described_class.new(merge_request: merge_request) }
+
+ it 'returns nil when template is not set in target project' do
+ expect(subject.message).to be_nil
+ end
+
+ context 'when project has custom merge commit template' do
+ let(:merge_commit_template) { <<~MSG.rstrip }
+ %{title}
+
+ See merge request %{reference}
+ MSG
+
+ it 'uses custom template' do
+ expect(subject.message).to eq <<~MSG.rstrip
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+
+ context 'when project has merge commit template with closed issues' do
+ let(:merge_commit_template) { <<~MSG.rstrip }
+ Merge branch '%{source_branch}' into '%{target_branch}'
+
+ %{title}
+
+ %{issues}
+
+ See merge request %{reference}
+ MSG
+
+ it 'omits issues and new lines when no issues are mentioned in description' do
+ expect(subject.message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+
+ context 'when MR closes issues' do
+ let(:issue_1) { create(:issue, project: project) }
+ let(:issue_2) { create(:issue, project: project) }
+ let(:merge_request_description) { "Description\n\nclosing #{issue_1.to_reference}, #{issue_2.to_reference}" }
+
+ it 'includes them and keeps new line characters' do
+ expect(subject.message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ Closes #{issue_1.to_reference} and #{issue_2.to_reference}
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+ end
+
+ context 'when project has merge commit template with description' do
+ let(:merge_commit_template) { <<~MSG.rstrip }
+ Merge branch '%{source_branch}' into '%{target_branch}'
+
+ %{title}
+
+ %{description}
+
+ See merge request %{reference}
+ MSG
+
+ it 'uses template' do
+ expect(subject.message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ Merge Request Description
+ Next line
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+
+ context 'when description is empty string' do
+ let(:merge_request_description) { '' }
+
+ it 'skips description placeholder and removes new line characters before it' do
+ expect(subject.message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+
+ context 'when description is nil' do
+ let(:merge_request_description) { nil }
+
+ it 'skips description placeholder and removes new line characters before it' do
+ expect(subject.message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+
+ context 'when description is blank string' do
+ let(:merge_request_description) { "\n\r \n" }
+
+ it 'skips description placeholder and removes new line characters before it' do
+ expect(subject.message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+ end
+
+ context 'when custom merge commit template contains placeholder in the middle or beginning of the line' do
+ let(:merge_commit_template) { <<~MSG.rstrip }
+ Merge branch '%{source_branch}' into '%{target_branch}'
+
+ %{description} %{title}
+
+ See merge request %{reference}
+ MSG
+
+ it 'uses custom template' do
+ expect(subject.message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Merge Request Description
+ Next line Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+
+ context 'when description is empty string' do
+ let(:merge_request_description) { '' }
+
+ it 'does not remove new line characters before empty placeholder' do
+ expect(subject.message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+ end
+
+ context 'when project has template with CRLF newlines' do
+ let(:merge_commit_template) do
+ "Merge branch '%{source_branch}' into '%{target_branch}'\r\n\r\n%{title}\r\n\r\n%{description}\r\n\r\nSee merge request %{reference}"
+ end
+
+ it 'converts it to LF newlines' do
+ expect(subject.message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ Merge Request Description
+ Next line
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+
+ context 'when description is empty string' do
+ let(:merge_request_description) { '' }
+
+ it 'skips description placeholder and removes new line characters before it' do
+ expect(subject.message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/background_transaction_spec.rb b/spec/lib/gitlab/metrics/background_transaction_spec.rb
index d36ee24fc50..83bee84df99 100644
--- a/spec/lib/gitlab/metrics/background_transaction_spec.rb
+++ b/spec/lib/gitlab/metrics/background_transaction_spec.rb
@@ -4,27 +4,28 @@ require 'spec_helper'
RSpec.describe Gitlab::Metrics::BackgroundTransaction do
let(:transaction) { described_class.new }
- let(:prometheus_metric) { instance_double(Prometheus::Client::Metric, base_labels: {}) }
-
- before do
- allow(described_class).to receive(:prometheus_metric).and_return(prometheus_metric)
- end
describe '#run' do
+ let(:prometheus_metric) { instance_double(Prometheus::Client::Metric, base_labels: {}) }
+
+ before do
+ allow(described_class).to receive(:prometheus_metric).and_return(prometheus_metric)
+ end
+
it 'yields the supplied block' do
expect { |b| transaction.run(&b) }.to yield_control
end
it 'stores the transaction in the current thread' do
transaction.run do
- expect(Thread.current[described_class::BACKGROUND_THREAD_KEY]).to eq(transaction)
+ expect(Thread.current[described_class::THREAD_KEY]).to eq(transaction)
end
end
it 'removes the transaction from the current thread upon completion' do
transaction.run { }
- expect(Thread.current[described_class::BACKGROUND_THREAD_KEY]).to be_nil
+ expect(Thread.current[described_class::THREAD_KEY]).to be_nil
end
end
@@ -68,7 +69,10 @@ RSpec.describe Gitlab::Metrics::BackgroundTransaction do
end
end
- RSpec.shared_examples 'metric with labels' do |metric_method|
+ it_behaves_like 'transaction metrics with labels' do
+ let(:transaction_obj) { described_class.new }
+ let(:labels) { { endpoint_id: 'TestWorker', feature_category: 'projects', queue: 'test_worker' } }
+
before do
test_worker_class = Class.new do
def self.queue
@@ -78,33 +82,10 @@ RSpec.describe Gitlab::Metrics::BackgroundTransaction do
stub_const('TestWorker', test_worker_class)
end
- it 'measures with correct labels and value' do
- value = 1
- expect(prometheus_metric).to receive(metric_method).with({
- endpoint_id: 'TestWorker', feature_category: 'projects', queue: 'test_worker'
- }, value)
-
+ around do |example|
Gitlab::ApplicationContext.with_raw_context(feature_category: 'projects', caller_id: 'TestWorker') do
- transaction.send(metric_method, :test_metric, value)
+ example.run
end
end
end
-
- describe '#increment' do
- let(:prometheus_metric) { instance_double(Prometheus::Client::Counter, :increment, base_labels: {}) }
-
- it_behaves_like 'metric with labels', :increment
- end
-
- describe '#set' do
- let(:prometheus_metric) { instance_double(Prometheus::Client::Gauge, :set, base_labels: {}) }
-
- it_behaves_like 'metric with labels', :set
- end
-
- describe '#observe' do
- let(:prometheus_metric) { instance_double(Prometheus::Client::Histogram, :observe, base_labels: {}) }
-
- it_behaves_like 'metric with labels', :observe
- end
end
diff --git a/spec/lib/gitlab/metrics/method_call_spec.rb b/spec/lib/gitlab/metrics/method_call_spec.rb
index fb5436a90e3..6aa89c7cb05 100644
--- a/spec/lib/gitlab/metrics/method_call_spec.rb
+++ b/spec/lib/gitlab/metrics/method_call_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe Gitlab::Metrics::MethodCall do
it 'metric is not a NullMetric' do
method_call.measure { 'foo' }
- expect(::Gitlab::Metrics::Transaction.prometheus_metric(:gitlab_method_call_duration_seconds, :histogram)).not_to be_instance_of(Gitlab::Metrics::NullMetric)
+ expect(::Gitlab::Metrics::WebTransaction.prometheus_metric(:gitlab_method_call_duration_seconds, :histogram)).not_to be_instance_of(Gitlab::Metrics::NullMetric)
end
it 'observes the performance of the supplied block' do
@@ -63,7 +63,7 @@ RSpec.describe Gitlab::Metrics::MethodCall do
it 'observes using NullMetric' do
method_call.measure { 'foo' }
- expect(::Gitlab::Metrics::Transaction.prometheus_metric(:gitlab_method_call_duration_seconds, :histogram)).to be_instance_of(Gitlab::Metrics::NullMetric)
+ expect(::Gitlab::Metrics::WebTransaction.prometheus_metric(:gitlab_method_call_duration_seconds, :histogram)).to be_instance_of(Gitlab::Metrics::NullMetric)
end
end
end
diff --git a/spec/lib/gitlab/metrics/rails_slis_spec.rb b/spec/lib/gitlab/metrics/rails_slis_spec.rb
index 16fcb9d46a2..a5ccf7fafa4 100644
--- a/spec/lib/gitlab/metrics/rails_slis_spec.rb
+++ b/spec/lib/gitlab/metrics/rails_slis_spec.rb
@@ -10,49 +10,62 @@ RSpec.describe Gitlab::Metrics::RailsSlis do
allow(Gitlab::RequestEndpoints).to receive(:all_api_endpoints).and_return([api_route])
allow(Gitlab::RequestEndpoints).to receive(:all_controller_actions).and_return([[ProjectsController, 'show']])
+ allow(Gitlab::Graphql::KnownOperations).to receive(:default).and_return(Gitlab::Graphql::KnownOperations.new(%w(foo bar)))
end
describe '.initialize_request_slis_if_needed!' do
- it "initializes the SLI for all possible endpoints if they weren't" do
+ it "initializes the SLI for all possible endpoints if they weren't", :aggregate_failures do
possible_labels = [
{
endpoint_id: "GET /api/:version/version",
- feature_category: :not_owned
+ feature_category: :not_owned,
+ request_urgency: :default
},
{
endpoint_id: "ProjectsController#show",
- feature_category: :projects
+ feature_category: :projects,
+ request_urgency: :default
}
]
+ possible_graphql_labels = ['graphql:foo', 'graphql:bar', 'graphql:unknown', 'graphql:anonymous'].map do |endpoint_id|
+ {
+ endpoint_id: endpoint_id,
+ feature_category: nil,
+ query_urgency: ::Gitlab::EndpointAttributes::DEFAULT_URGENCY.name
+ }
+ end
+
expect(Gitlab::Metrics::Sli).to receive(:initialized?).with(:rails_request_apdex) { false }
+ expect(Gitlab::Metrics::Sli).to receive(:initialized?).with(:graphql_query_apdex) { false }
expect(Gitlab::Metrics::Sli).to receive(:initialize_sli).with(:rails_request_apdex, array_including(*possible_labels)).and_call_original
+ expect(Gitlab::Metrics::Sli).to receive(:initialize_sli).with(:graphql_query_apdex, array_including(*possible_graphql_labels)).and_call_original
described_class.initialize_request_slis_if_needed!
end
- it 'does not initialize the SLI if they were initialized already' do
+ it 'does not initialize the SLI if they were initialized already', :aggregate_failures do
expect(Gitlab::Metrics::Sli).to receive(:initialized?).with(:rails_request_apdex) { true }
+ expect(Gitlab::Metrics::Sli).to receive(:initialized?).with(:graphql_query_apdex) { true }
expect(Gitlab::Metrics::Sli).not_to receive(:initialize_sli)
described_class.initialize_request_slis_if_needed!
end
+ end
- it 'does not initialize anything if the feature flag is disabled' do
- stub_feature_flags(request_apdex_counters: false)
-
- expect(Gitlab::Metrics::Sli).not_to receive(:initialize_sli)
- expect(Gitlab::Metrics::Sli).not_to receive(:initialized?)
-
+ describe '.request_apdex' do
+ it 'returns the initialized request apdex SLI object' do
described_class.initialize_request_slis_if_needed!
+
+ expect(described_class.request_apdex).to be_initialized
end
end
- describe '.request_apdex' do
+ describe '.graphql_query_apdex' do
it 'returns the initialized request apdex SLI object' do
described_class.initialize_request_slis_if_needed!
- expect(described_class.request_apdex).to be_initialized
+ expect(described_class.graphql_query_apdex).to be_initialized
end
end
end
diff --git a/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb b/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
index 5870f9a8f68..3396de9b12c 100644
--- a/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
+++ b/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb
@@ -36,7 +36,8 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
it 'tracks request count and duration' do
expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '200', feature_category: 'unknown')
expect(described_class).to receive_message_chain(:http_request_duration_seconds, :observe).with({ method: 'get' }, a_positive_execution_time)
- expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(labels: { feature_category: 'unknown', endpoint_id: 'unknown' }, success: true)
+ expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment)
+ .with(labels: { feature_category: 'unknown', endpoint_id: 'unknown', request_urgency: :default }, success: true)
subject.call(env)
end
@@ -115,14 +116,14 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
context 'application context' do
context 'when a context is present' do
before do
- ::Gitlab::ApplicationContext.push(feature_category: 'issue_tracking', caller_id: 'IssuesController#show')
+ ::Gitlab::ApplicationContext.push(feature_category: 'team_planning', caller_id: 'IssuesController#show')
end
it 'adds the feature category to the labels for required metrics' do
- expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '200', feature_category: 'issue_tracking')
+ expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '200', feature_category: 'team_planning')
expect(described_class).not_to receive(:http_health_requests_total)
expect(Gitlab::Metrics::RailsSlis.request_apdex)
- .to receive(:increment).with(labels: { feature_category: 'issue_tracking', endpoint_id: 'IssuesController#show' }, success: true)
+ .to receive(:increment).with(labels: { feature_category: 'team_planning', endpoint_id: 'IssuesController#show', request_urgency: :default }, success: true)
subject.call(env)
end
@@ -140,12 +141,12 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
context 'when application raises an exception when the feature category context is present' do
before do
- ::Gitlab::ApplicationContext.push(feature_category: 'issue_tracking')
+ ::Gitlab::ApplicationContext.push(feature_category: 'team_planning')
allow(app).to receive(:call).and_raise(StandardError)
end
it 'adds the feature category to the labels for http_requests_total' do
- expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: 'undefined', feature_category: 'issue_tracking')
+ expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: 'undefined', feature_category: 'team_planning')
expect(Gitlab::Metrics::RailsSlis).not_to receive(:request_apdex)
expect { subject.call(env) }.to raise_error(StandardError)
@@ -156,7 +157,8 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
it 'sets the required labels to unknown' do
expect(described_class).to receive_message_chain(:http_requests_total, :increment).with(method: 'get', status: '200', feature_category: 'unknown')
expect(described_class).not_to receive(:http_health_requests_total)
- expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(labels: { feature_category: 'unknown', endpoint_id: 'unknown' }, success: true)
+ expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment)
+ .with(labels: { feature_category: 'unknown', endpoint_id: 'unknown', request_urgency: :default }, success: true)
subject.call(env)
end
@@ -206,7 +208,11 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
it "captures SLI metrics" do
expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
- labels: { feature_category: 'hello_world', endpoint_id: 'GET /projects/:id/archive' },
+ labels: {
+ feature_category: 'hello_world',
+ endpoint_id: 'GET /projects/:id/archive',
+ request_urgency: request_urgency_name
+ },
success: success
)
subject.call(env)
@@ -235,7 +241,11 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
it "captures SLI metrics" do
expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
- labels: { feature_category: 'hello_world', endpoint_id: 'AnonymousController#index' },
+ labels: {
+ feature_category: 'hello_world',
+ endpoint_id: 'AnonymousController#index',
+ request_urgency: request_urgency_name
+ },
success: success
)
subject.call(env)
@@ -255,17 +265,25 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
let(:api_handler) { Class.new(::API::Base) }
- it "falls back request's expectation to medium (1 second)" do
+ it "falls back request's expectation to default (1 second)" do
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 100.9)
expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
- labels: { feature_category: 'unknown', endpoint_id: 'unknown' },
+ labels: {
+ feature_category: 'unknown',
+ endpoint_id: 'unknown',
+ request_urgency: :default
+ },
success: true
)
subject.call(env)
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 101)
expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
- labels: { feature_category: 'unknown', endpoint_id: 'unknown' },
+ labels: {
+ feature_category: 'unknown',
+ endpoint_id: 'unknown',
+ request_urgency: :default
+ },
success: false
)
subject.call(env)
@@ -281,17 +299,25 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
{ 'action_controller.instance' => controller_instance, 'REQUEST_METHOD' => 'GET' }
end
- it "falls back request's expectation to medium (1 second)" do
+ it "falls back request's expectation to default (1 second)" do
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 100.9)
expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
- labels: { feature_category: 'unknown', endpoint_id: 'unknown' },
+ labels: {
+ feature_category: 'unknown',
+ endpoint_id: 'unknown',
+ request_urgency: :default
+ },
success: true
)
subject.call(env)
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 101)
expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
- labels: { feature_category: 'unknown', endpoint_id: 'unknown' },
+ labels: {
+ feature_category: 'unknown',
+ endpoint_id: 'unknown',
+ request_urgency: :default
+ },
success: false
)
subject.call(env)
@@ -303,17 +329,25 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
{ 'REQUEST_METHOD' => 'GET' }
end
- it "falls back request's expectation to medium (1 second)" do
+ it "falls back request's expectation to default (1 second)" do
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 100.9)
expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
- labels: { feature_category: 'unknown', endpoint_id: 'unknown' },
+ labels: {
+ feature_category: 'unknown',
+ endpoint_id: 'unknown',
+ request_urgency: :default
+ },
success: true
)
subject.call(env)
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100, 101)
expect(Gitlab::Metrics::RailsSlis.request_apdex).to receive(:increment).with(
- labels: { feature_category: 'unknown', endpoint_id: 'unknown' },
+ labels: {
+ feature_category: 'unknown',
+ endpoint_id: 'unknown',
+ request_urgency: :default
+ },
success: false
)
subject.call(env)
diff --git a/spec/lib/gitlab/metrics/samplers/action_cable_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/action_cable_sampler_spec.rb
index f751416f4ec..d834b796179 100644
--- a/spec/lib/gitlab/metrics/samplers/action_cable_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/action_cable_sampler_spec.rb
@@ -23,64 +23,46 @@ RSpec.describe Gitlab::Metrics::Samplers::ActionCableSampler do
allow(pool).to receive(:queue_length).and_return(6)
end
- shared_examples 'collects metrics' do |expected_labels|
- it 'includes active connections' do
- expect(subject.metrics[:active_connections]).to receive(:set).with(expected_labels, 0)
+ it 'includes active connections' do
+ expect(subject.metrics[:active_connections]).to receive(:set).with({}, 0)
- subject.sample
- end
-
- it 'includes minimum worker pool size' do
- expect(subject.metrics[:pool_min_size]).to receive(:set).with(expected_labels, 1)
-
- subject.sample
- end
-
- it 'includes maximum worker pool size' do
- expect(subject.metrics[:pool_max_size]).to receive(:set).with(expected_labels, 2)
-
- subject.sample
- end
+ subject.sample
+ end
- it 'includes current worker pool size' do
- expect(subject.metrics[:pool_current_size]).to receive(:set).with(expected_labels, 3)
+ it 'includes minimum worker pool size' do
+ expect(subject.metrics[:pool_min_size]).to receive(:set).with({}, 1)
- subject.sample
- end
+ subject.sample
+ end
- it 'includes largest worker pool size' do
- expect(subject.metrics[:pool_largest_size]).to receive(:set).with(expected_labels, 4)
+ it 'includes maximum worker pool size' do
+ expect(subject.metrics[:pool_max_size]).to receive(:set).with({}, 2)
- subject.sample
- end
+ subject.sample
+ end
- it 'includes worker pool completed task count' do
- expect(subject.metrics[:pool_completed_tasks]).to receive(:set).with(expected_labels, 5)
+ it 'includes current worker pool size' do
+ expect(subject.metrics[:pool_current_size]).to receive(:set).with({}, 3)
- subject.sample
- end
+ subject.sample
+ end
- it 'includes worker pool pending task count' do
- expect(subject.metrics[:pool_pending_tasks]).to receive(:set).with(expected_labels, 6)
+ it 'includes largest worker pool size' do
+ expect(subject.metrics[:pool_largest_size]).to receive(:set).with({}, 4)
- subject.sample
- end
+ subject.sample
end
- context 'for in-app mode' do
- before do
- expect(Gitlab::ActionCable::Config).to receive(:in_app?).and_return(true)
- end
+ it 'includes worker pool completed task count' do
+ expect(subject.metrics[:pool_completed_tasks]).to receive(:set).with({}, 5)
- it_behaves_like 'collects metrics', server_mode: 'in-app'
+ subject.sample
end
- context 'for standalone mode' do
- before do
- expect(Gitlab::ActionCable::Config).to receive(:in_app?).and_return(false)
- end
+ it 'includes worker pool pending task count' do
+ expect(subject.metrics[:pool_pending_tasks]).to receive(:set).with({}, 6)
- it_behaves_like 'collects metrics', server_mode: 'standalone'
+ subject.sample
end
end
end
diff --git a/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb
index 7dda10ab41d..e97a4fdddcb 100644
--- a/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb
@@ -18,8 +18,8 @@ RSpec.describe Gitlab::Metrics::Samplers::DatabaseSampler do
let(:labels) do
{
class: 'ActiveRecord::Base',
- host: Gitlab::Database.main.config['host'],
- port: Gitlab::Database.main.config['port']
+ host: ApplicationRecord.database.config['host'],
+ port: ApplicationRecord.database.config['port']
}
end
diff --git a/spec/lib/gitlab/metrics/subscribers/external_http_spec.rb b/spec/lib/gitlab/metrics/subscribers/external_http_spec.rb
index adbc05cb711..e489ac97b9c 100644
--- a/spec/lib/gitlab/metrics/subscribers/external_http_spec.rb
+++ b/spec/lib/gitlab/metrics/subscribers/external_http_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Metrics::Subscribers::ExternalHttp, :request_store do
- let(:transaction) { Gitlab::Metrics::Transaction.new }
+ let(:transaction) { Gitlab::Metrics::WebTransaction.new({}) }
let(:subscriber) { described_class.new }
around do |example|
diff --git a/spec/lib/gitlab/metrics/transaction_spec.rb b/spec/lib/gitlab/metrics/transaction_spec.rb
index 2ff8efcd7cb..b1c15db5193 100644
--- a/spec/lib/gitlab/metrics/transaction_spec.rb
+++ b/spec/lib/gitlab/metrics/transaction_spec.rb
@@ -3,172 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Metrics::Transaction do
- let(:transaction) { described_class.new }
-
- let(:sensitive_tags) do
- {
- path: 'private',
- branch: 'sensitive'
- }
- end
-
- describe '#method_call_for' do
- it 'returns a MethodCall' do
- method = transaction.method_call_for('Foo#bar', :Foo, '#bar')
-
- expect(method).to be_an_instance_of(Gitlab::Metrics::MethodCall)
- end
- end
-
describe '#run' do
- specify { expect { transaction.run }.to raise_error(NotImplementedError) }
- end
-
- describe '#add_event' do
- let(:prometheus_metric) { instance_double(Prometheus::Client::Counter, increment: nil, base_labels: {}) }
-
- it 'adds a metric' do
- expect(prometheus_metric).to receive(:increment)
- expect(described_class).to receive(:fetch_metric).with(:counter, :gitlab_transaction_event_meow_total).and_return(prometheus_metric)
-
- transaction.add_event(:meow)
- end
-
- it 'allows tracking of custom tags' do
- expect(prometheus_metric).to receive(:increment).with(hash_including(animal: "dog"))
- expect(described_class).to receive(:fetch_metric).with(:counter, :gitlab_transaction_event_bau_total).and_return(prometheus_metric)
-
- transaction.add_event(:bau, animal: 'dog')
- end
-
- context 'with sensitive tags' do
- before do
- transaction.add_event(:baubau, **sensitive_tags.merge(sane: 'yes'))
- allow(described_class).to receive(:prometheus_metric).and_return(prometheus_metric)
- end
-
- it 'filters tags' do
- expect(prometheus_metric).not_to receive(:increment).with(hash_including(sensitive_tags))
-
- transaction.add_event(:baubau, **sensitive_tags.merge(sane: 'yes'))
- end
- end
- end
-
- describe '#increment' do
- let(:prometheus_metric) { instance_double(Prometheus::Client::Counter, increment: nil, base_labels: {}) }
-
- it 'adds a metric' do
- expect(prometheus_metric).to receive(:increment)
- expect(::Gitlab::Metrics).to receive(:counter).with(:meow, 'Meow counter', hash_including(:controller, :action)).and_return(prometheus_metric)
-
- transaction.increment(:meow, 1)
- end
-
- context 'with block' do
- it 'overrides docstring' do
- expect(::Gitlab::Metrics).to receive(:counter).with(:block_docstring, 'test', hash_including(:controller, :action)).and_return(prometheus_metric)
-
- transaction.increment(:block_docstring, 1) do
- docstring 'test'
- end
- end
-
- it 'overrides labels' do
- expect(::Gitlab::Metrics).to receive(:counter).with(:block_labels, 'Block labels counter', hash_including(:controller, :action, :sane)).and_return(prometheus_metric)
-
- labels = { sane: 'yes' }
- transaction.increment(:block_labels, 1, labels) do
- label_keys %i(sane)
- end
- end
-
- it 'filters sensitive tags' do
- expect(::Gitlab::Metrics).to receive(:counter).with(:metric_with_sensitive_block, 'Metric with sensitive block counter', hash_excluding(sensitive_tags)).and_return(prometheus_metric)
-
- labels_keys = sensitive_tags.keys
- transaction.increment(:metric_with_sensitive_block, 1, sensitive_tags) do
- label_keys labels_keys
- end
- end
- end
- end
-
- describe '#set' do
- let(:prometheus_metric) { instance_double(Prometheus::Client::Gauge, set: nil, base_labels: {}) }
-
- it 'adds a metric' do
- expect(prometheus_metric).to receive(:set)
- expect(::Gitlab::Metrics).to receive(:gauge).with(:meow_set, 'Meow set gauge', hash_including(:controller, :action), :all).and_return(prometheus_metric)
-
- transaction.set(:meow_set, 1)
- end
-
- context 'with block' do
- it 'overrides docstring' do
- expect(::Gitlab::Metrics).to receive(:gauge).with(:block_docstring_set, 'test', hash_including(:controller, :action), :all).and_return(prometheus_metric)
-
- transaction.set(:block_docstring_set, 1) do
- docstring 'test'
- end
- end
-
- it 'overrides labels' do
- expect(::Gitlab::Metrics).to receive(:gauge).with(:block_labels_set, 'Block labels set gauge', hash_including(:controller, :action, :sane), :all).and_return(prometheus_metric)
-
- labels = { sane: 'yes' }
- transaction.set(:block_labels_set, 1, labels) do
- label_keys %i(sane)
- end
- end
-
- it 'filters sensitive tags' do
- expect(::Gitlab::Metrics).to receive(:gauge).with(:metric_set_with_sensitive_block, 'Metric set with sensitive block gauge', hash_excluding(sensitive_tags), :all).and_return(prometheus_metric)
-
- label_keys = sensitive_tags.keys
- transaction.set(:metric_set_with_sensitive_block, 1, sensitive_tags) do
- label_keys label_keys
- end
- end
- end
- end
-
- describe '#observe' do
- let(:prometheus_metric) { instance_double(Prometheus::Client::Histogram, observe: nil, base_labels: {}) }
-
- it 'adds a metric' do
- expect(prometheus_metric).to receive(:observe)
- expect(::Gitlab::Metrics).to receive(:histogram).with(:meow_observe, 'Meow observe histogram', hash_including(:controller, :action), kind_of(Array)).and_return(prometheus_metric)
-
- transaction.observe(:meow_observe, 1)
- end
-
- context 'with block' do
- it 'overrides docstring' do
- expect(::Gitlab::Metrics).to receive(:histogram).with(:block_docstring_observe, 'test', hash_including(:controller, :action), kind_of(Array)).and_return(prometheus_metric)
-
- transaction.observe(:block_docstring_observe, 1) do
- docstring 'test'
- end
- end
-
- it 'overrides labels' do
- expect(::Gitlab::Metrics).to receive(:histogram).with(:block_labels_observe, 'Block labels observe histogram', hash_including(:controller, :action, :sane), kind_of(Array)).and_return(prometheus_metric)
-
- labels = { sane: 'yes' }
- transaction.observe(:block_labels_observe, 1, labels) do
- label_keys %i(sane)
- end
- end
-
- it 'filters sensitive tags' do
- expect(::Gitlab::Metrics).to receive(:histogram).with(:metric_observe_with_sensitive_block, 'Metric observe with sensitive block histogram', hash_excluding(sensitive_tags), kind_of(Array)).and_return(prometheus_metric)
-
- label_keys = sensitive_tags.keys
- transaction.observe(:metric_observe_with_sensitive_block, 1, sensitive_tags) do
- label_keys label_keys
- end
- end
- end
+ specify { expect { described_class.new.run }.to raise_error(NotImplementedError) }
end
end
diff --git a/spec/lib/gitlab/metrics/web_transaction_spec.rb b/spec/lib/gitlab/metrics/web_transaction_spec.rb
index 9e22dccb2a2..06ce58a9e84 100644
--- a/spec/lib/gitlab/metrics/web_transaction_spec.rb
+++ b/spec/lib/gitlab/metrics/web_transaction_spec.rb
@@ -5,41 +5,14 @@ require 'spec_helper'
RSpec.describe Gitlab::Metrics::WebTransaction do
let(:env) { {} }
let(:transaction) { described_class.new(env) }
- let(:prometheus_metric) { instance_double(Prometheus::Client::Metric, base_labels: {}) }
- before do
- allow(described_class).to receive(:prometheus_metric).and_return(prometheus_metric)
- end
-
- RSpec.shared_context 'ActionController request' do
- let(:request) { double(:request, format: double(:format, ref: :html)) }
- let(:controller_class) { double(:controller_class, name: 'TestController') }
-
- before do
- controller = double(:controller, class: controller_class, action_name: 'show', request: request)
- env['action_controller.instance'] = controller
- end
- end
+ describe '#run' do
+ let(:prometheus_metric) { instance_double(Prometheus::Client::Metric, base_labels: {}) }
- RSpec.shared_context 'transaction observe metrics' do
before do
+ allow(described_class).to receive(:prometheus_metric).and_return(prometheus_metric)
allow(transaction).to receive(:observe)
end
- end
-
- RSpec.shared_examples 'metric with labels' do |metric_method|
- include_context 'ActionController request'
-
- it 'measures with correct labels and value' do
- value = 1
- expect(prometheus_metric).to receive(metric_method).with({ controller: 'TestController', action: 'show', feature_category: ::Gitlab::FeatureCategories::FEATURE_CATEGORY_DEFAULT }, value)
-
- transaction.send(metric_method, :bau, value)
- end
- end
-
- describe '#run' do
- include_context 'transaction observe metrics'
it 'yields the supplied block' do
expect { |b| transaction.run(&b) }.to yield_control
@@ -88,14 +61,6 @@ RSpec.describe Gitlab::Metrics::WebTransaction do
end
end
- describe '#method_call_for' do
- it 'returns a MethodCall' do
- method = transaction.method_call_for('Foo#bar', :Foo, '#bar')
-
- expect(method).to be_an_instance_of(Gitlab::Metrics::MethodCall)
- end
- end
-
describe '#labels' do
context 'when request goes to Grape endpoint' do
before do
@@ -115,7 +80,7 @@ RSpec.describe Gitlab::Metrics::WebTransaction do
end
it 'contains only the labels defined for transactions' do
- expect(transaction.labels.keys).to contain_exactly(*described_class.superclass::BASE_LABEL_KEYS)
+ expect(transaction.labels.keys).to contain_exactly(*described_class::BASE_LABEL_KEYS)
end
it 'does not provide labels if route infos are missing' do
@@ -129,14 +94,20 @@ RSpec.describe Gitlab::Metrics::WebTransaction do
end
context 'when request goes to ActionController' do
- include_context 'ActionController request'
+ let(:request) { double(:request, format: double(:format, ref: :html)) }
+ let(:controller_class) { double(:controller_class, name: 'TestController') }
+
+ before do
+ controller = double(:controller, class: controller_class, action_name: 'show', request: request)
+ env['action_controller.instance'] = controller
+ end
it 'tags a transaction with the name and action of a controller' do
expect(transaction.labels).to eq({ controller: 'TestController', action: 'show', feature_category: ::Gitlab::FeatureCategories::FEATURE_CATEGORY_DEFAULT })
end
it 'contains only the labels defined for transactions' do
- expect(transaction.labels.keys).to contain_exactly(*described_class.superclass::BASE_LABEL_KEYS)
+ expect(transaction.labels.keys).to contain_exactly(*described_class::BASE_LABEL_KEYS)
end
context 'when the request content type is not :html' do
@@ -170,37 +141,16 @@ RSpec.describe Gitlab::Metrics::WebTransaction do
end
end
- describe '#add_event' do
- let(:prometheus_metric) { instance_double(Prometheus::Client::Counter, :increment, base_labels: {}) }
-
- it 'adds a metric' do
- expect(prometheus_metric).to receive(:increment)
-
- transaction.add_event(:meow)
- end
+ it_behaves_like 'transaction metrics with labels' do
+ let(:request) { double(:request, format: double(:format, ref: :html)) }
+ let(:controller_class) { double(:controller_class, name: 'TestController') }
+ let(:controller) { double(:controller, class: controller_class, action_name: 'show', request: request) }
- it 'allows tracking of custom tags' do
- expect(prometheus_metric).to receive(:increment).with(animal: "dog")
+ let(:transaction_obj) { described_class.new({ 'action_controller.instance' => controller }) }
+ let(:labels) { { controller: 'TestController', action: 'show', feature_category: 'projects' } }
- transaction.add_event(:bau, animal: 'dog')
+ before do
+ ::Gitlab::ApplicationContext.push(feature_category: 'projects')
end
end
-
- describe '#increment' do
- let(:prometheus_metric) { instance_double(Prometheus::Client::Counter, :increment, base_labels: {}) }
-
- it_behaves_like 'metric with labels', :increment
- end
-
- describe '#set' do
- let(:prometheus_metric) { instance_double(Prometheus::Client::Gauge, :set, base_labels: {}) }
-
- it_behaves_like 'metric with labels', :set
- end
-
- describe '#observe' do
- let(:prometheus_metric) { instance_double(Prometheus::Client::Histogram, :observe, base_labels: {}) }
-
- it_behaves_like 'metric with labels', :observe
- end
end
diff --git a/spec/lib/gitlab/middleware/compressed_json_spec.rb b/spec/lib/gitlab/middleware/compressed_json_spec.rb
new file mode 100644
index 00000000000..c5efc568971
--- /dev/null
+++ b/spec/lib/gitlab/middleware/compressed_json_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Middleware::CompressedJson do
+ let_it_be(:decompressed_input) { '{"foo": "bar"}' }
+ let_it_be(:input) { ActiveSupport::Gzip.compress(decompressed_input) }
+
+ let(:app) { double(:app) }
+ let(:middleware) { described_class.new(app) }
+ let(:env) do
+ {
+ 'HTTP_CONTENT_ENCODING' => 'gzip',
+ 'REQUEST_METHOD' => 'POST',
+ 'CONTENT_TYPE' => 'application/json',
+ 'PATH_INFO' => path,
+ 'rack.input' => StringIO.new(input)
+ }
+ end
+
+ shared_examples 'decompress middleware' do
+ it 'replaces input with a decompressed content' do
+ expect(app).to receive(:call)
+
+ middleware.call(env)
+
+ expect(env['rack.input'].read).to eq(decompressed_input)
+ expect(env['CONTENT_LENGTH']).to eq(decompressed_input.length)
+ expect(env['HTTP_CONTENT_ENCODING']).to be_nil
+ end
+ end
+
+ describe '#call' do
+ context 'with collector route' do
+ let(:path) { '/api/v4/error_tracking/collector/1/store'}
+
+ it_behaves_like 'decompress middleware'
+ end
+
+ context 'with collector route under relative url' do
+ let(:path) { '/gitlab/api/v4/error_tracking/collector/1/store'}
+
+ before do
+ stub_config_setting(relative_url_root: '/gitlab')
+ end
+
+ it_behaves_like 'decompress middleware'
+ end
+
+ context 'with some other route' do
+ let(:path) { '/api/projects/123' }
+
+ it 'keeps the original input' do
+ expect(app).to receive(:call)
+
+ middleware.call(env)
+
+ expect(env['rack.input'].read).to eq(input)
+ expect(env['HTTP_CONTENT_ENCODING']).to eq('gzip')
+ end
+ end
+
+ context 'payload is too large' do
+ let(:body_limit) { Gitlab::Middleware::CompressedJson::MAXIMUM_BODY_SIZE }
+ let(:decompressed_input) { 'a' * (body_limit + 100) }
+ let(:input) { ActiveSupport::Gzip.compress(decompressed_input) }
+ let(:path) { '/api/v4/error_tracking/collector/1/envelope'}
+
+ it 'reads only limited size' do
+ expect(middleware.call(env))
+ .to eq([413, { 'Content-Type' => 'text/plain' }, ['Payload Too Large']])
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/middleware/go_spec.rb b/spec/lib/gitlab/middleware/go_spec.rb
index 0ce95fdb5af..1ef548ab29b 100644
--- a/spec/lib/gitlab/middleware/go_spec.rb
+++ b/spec/lib/gitlab/middleware/go_spec.rb
@@ -147,6 +147,22 @@ RSpec.describe Gitlab::Middleware::Go do
end
end
end
+
+ context 'when a personal access token is missing' do
+ before do
+ env['REMOTE_ADDR'] = '192.168.0.1'
+ env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(current_user.username, 'dummy_password')
+ end
+
+ it 'returns unauthorized' do
+ expect(Gitlab::Auth).to receive(:find_for_git_client).and_raise(Gitlab::Auth::MissingPersonalAccessTokenError)
+ response = go
+
+ expect(response[0]).to eq(401)
+ expect(response[1]['Content-Length']).to be_nil
+ expect(response[2]).to eq([''])
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/middleware/query_analyzer_spec.rb b/spec/lib/gitlab/middleware/query_analyzer_spec.rb
new file mode 100644
index 00000000000..5ebe6a92da6
--- /dev/null
+++ b/spec/lib/gitlab/middleware/query_analyzer_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Middleware::QueryAnalyzer, query_analyzers: false do
+ describe 'the PreventCrossDatabaseModification' do
+ describe '#call' do
+ let(:app) { double(:app) }
+ let(:middleware) { described_class.new(app) }
+ let(:env) { {} }
+
+ subject { middleware.call(env) }
+
+ context 'when there is a cross modification' do
+ before do
+ allow(app).to receive(:call) do
+ Project.transaction do
+ Project.where(id: -1).update_all(id: -1)
+ ::Ci::Pipeline.where(id: -1).update_all(id: -1)
+ end
+ end
+ end
+
+ it 'detects cross modifications and tracks exception' do
+ expect(::Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
+
+ expect { subject }.not_to raise_error
+ end
+
+ context 'when the detect_cross_database_modification is disabled' do
+ before do
+ stub_feature_flags(detect_cross_database_modification: false)
+ end
+
+ it 'does not detect cross modifications' do
+ expect(::Gitlab::ErrorTracking).not_to receive(:track_and_raise_for_dev_exception)
+
+ subject
+ end
+ end
+ end
+
+ context 'when there is no cross modification' do
+ before do
+ allow(app).to receive(:call) do
+ Project.transaction do
+ Project.where(id: -1).update_all(id: -1)
+ Namespace.where(id: -1).update_all(id: -1)
+ end
+ end
+ end
+
+ it 'does not log anything' do
+ expect(::Gitlab::ErrorTracking).not_to receive(:track_and_raise_for_dev_exception)
+
+ subject
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/path_regex_spec.rb b/spec/lib/gitlab/path_regex_spec.rb
index 2f38ed58727..f0ba0f0459d 100644
--- a/spec/lib/gitlab/path_regex_spec.rb
+++ b/spec/lib/gitlab/path_regex_spec.rb
@@ -425,6 +425,9 @@ RSpec.describe Gitlab::PathRegex do
it { is_expected.not_to match('gitlab.org/') }
it { is_expected.not_to match('/gitlab.org') }
it { is_expected.not_to match('gitlab git') }
+ it { is_expected.not_to match('gitlab?') }
+ it { is_expected.to match('gitlab.org-') }
+ it { is_expected.to match('gitlab.org_') }
end
describe '.project_path_format_regex' do
@@ -437,6 +440,14 @@ RSpec.describe Gitlab::PathRegex do
it { is_expected.not_to match('?gitlab') }
it { is_expected.not_to match('git lab') }
it { is_expected.not_to match('gitlab.git') }
+ it { is_expected.not_to match('gitlab?') }
+ it { is_expected.not_to match('gitlab git') }
+ it { is_expected.to match('gitlab.org') }
+ it { is_expected.to match('gitlab.org-') }
+ it { is_expected.to match('gitlab.org_') }
+ it { is_expected.to match('gitlab.org.') }
+ it { is_expected.not_to match('gitlab.org/') }
+ it { is_expected.not_to match('/gitlab.org') }
end
context 'repository routes' do
diff --git a/spec/lib/gitlab/project_template_spec.rb b/spec/lib/gitlab/project_template_spec.rb
index 4eb13e63b46..05417e721c7 100644
--- a/spec/lib/gitlab/project_template_spec.rb
+++ b/spec/lib/gitlab/project_template_spec.rb
@@ -10,8 +10,8 @@ RSpec.describe Gitlab::ProjectTemplate do
gomicro gatsby hugo jekyll plainhtml gitbook
hexo sse_middleman gitpod_spring_petclinic nfhugo
nfjekyll nfplainhtml nfgitbook nfhexo salesforcedx
- serverless_framework jsonnet cluster_management
- kotlin_native_linux
+ serverless_framework tencent_serverless_framework
+ jsonnet cluster_management kotlin_native_linux
]
expect(described_class.all).to be_an(Array)
diff --git a/spec/lib/gitlab/prometheus_client_spec.rb b/spec/lib/gitlab/prometheus_client_spec.rb
index 82ef4675553..89ddde4a01d 100644
--- a/spec/lib/gitlab/prometheus_client_spec.rb
+++ b/spec/lib/gitlab/prometheus_client_spec.rb
@@ -107,36 +107,14 @@ RSpec.describe Gitlab::PrometheusClient do
let(:prometheus_url) {"https://prometheus.invalid.example.com/api/v1/query?query=1"}
shared_examples 'exceptions are raised' do
- it 'raises a Gitlab::PrometheusClient::ConnectionError error when a SocketError is rescued' do
- req_stub = stub_prometheus_request_with_exception(prometheus_url, SocketError)
+ Gitlab::HTTP::HTTP_ERRORS.each do |error|
+ it "raises a Gitlab::PrometheusClient::ConnectionError when a #{error} is rescued" do
+ req_stub = stub_prometheus_request_with_exception(prometheus_url, error.new)
- expect { subject }
- .to raise_error(Gitlab::PrometheusClient::ConnectionError, "Can't connect to #{prometheus_url}")
- expect(req_stub).to have_been_requested
- end
-
- it 'raises a Gitlab::PrometheusClient::ConnectionError error when a SSLError is rescued' do
- req_stub = stub_prometheus_request_with_exception(prometheus_url, OpenSSL::SSL::SSLError)
-
- expect { subject }
- .to raise_error(Gitlab::PrometheusClient::ConnectionError, "#{prometheus_url} contains invalid SSL data")
- expect(req_stub).to have_been_requested
- end
-
- it 'raises a Gitlab::PrometheusClient::ConnectionError error when a Gitlab::HTTP::ResponseError is rescued' do
- req_stub = stub_prometheus_request_with_exception(prometheus_url, Gitlab::HTTP::ResponseError)
-
- expect { subject }
- .to raise_error(Gitlab::PrometheusClient::ConnectionError, "Network connection error")
- expect(req_stub).to have_been_requested
- end
-
- it 'raises a Gitlab::PrometheusClient::ConnectionError error when a Gitlab::HTTP::ResponseError with a code is rescued' do
- req_stub = stub_prometheus_request_with_exception(prometheus_url, Gitlab::HTTP::ResponseError.new(code: 400))
-
- expect { subject }
- .to raise_error(Gitlab::PrometheusClient::ConnectionError, "Network connection error")
- expect(req_stub).to have_been_requested
+ expect { subject }
+ .to raise_error(Gitlab::PrometheusClient::ConnectionError, kind_of(String))
+ expect(req_stub).to have_been_requested
+ end
end
end
diff --git a/spec/lib/gitlab/redis/multi_store_spec.rb b/spec/lib/gitlab/redis/multi_store_spec.rb
new file mode 100644
index 00000000000..bf1bf65bb9b
--- /dev/null
+++ b/spec/lib/gitlab/redis/multi_store_spec.rb
@@ -0,0 +1,474 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Redis::MultiStore do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:redis_store_class) do
+ Class.new(Gitlab::Redis::Wrapper) do
+ def config_file_name
+ config_file_name = "spec/fixtures/config/redis_new_format_host.yml"
+ Rails.root.join(config_file_name).to_s
+ end
+
+ def self.name
+ 'Sessions'
+ end
+ end
+ end
+
+ let_it_be(:primary_db) { 1 }
+ let_it_be(:secondary_db) { 2 }
+ let_it_be(:primary_store) { create_redis_store(redis_store_class.params, db: primary_db, serializer: nil) }
+ let_it_be(:secondary_store) { create_redis_store(redis_store_class.params, db: secondary_db, serializer: nil) }
+ let_it_be(:instance_name) { 'TestStore' }
+ let_it_be(:multi_store) { described_class.new(primary_store, secondary_store, instance_name)}
+
+ subject { multi_store.send(name, *args) }
+
+ after(:all) do
+ primary_store.flushdb
+ secondary_store.flushdb
+ end
+
+ context 'when primary_store is nil' do
+ let(:multi_store) { described_class.new(nil, secondary_store, instance_name)}
+
+ it 'fails with exception' do
+ expect { multi_store }.to raise_error(ArgumentError, /primary_store is required/)
+ end
+ end
+
+ context 'when secondary_store is nil' do
+ let(:multi_store) { described_class.new(primary_store, nil, instance_name)}
+
+ it 'fails with exception' do
+ expect { multi_store }.to raise_error(ArgumentError, /secondary_store is required/)
+ end
+ end
+
+ context 'when primary_store is not a ::Redis instance' do
+ before do
+ allow(primary_store).to receive(:is_a?).with(::Redis).and_return(false)
+ end
+
+ it 'fails with exception' do
+ expect { described_class.new(primary_store, secondary_store, instance_name) }.to raise_error(ArgumentError, /invalid primary_store/)
+ end
+ end
+
+ context 'when secondary_store is not a ::Redis instance' do
+ before do
+ allow(secondary_store).to receive(:is_a?).with(::Redis).and_return(false)
+ end
+
+ it 'fails with exception' do
+ expect { described_class.new(primary_store, secondary_store, instance_name) }.to raise_error(ArgumentError, /invalid secondary_store/)
+ end
+ end
+
+ context 'with READ redis commands' do
+ let_it_be(:key1) { "redis:{1}:key_a" }
+ let_it_be(:key2) { "redis:{1}:key_b" }
+ let_it_be(:value1) { "redis_value1"}
+ let_it_be(:value2) { "redis_value2"}
+ let_it_be(:skey) { "redis:set:key" }
+ let_it_be(:keys) { [key1, key2] }
+ let_it_be(:values) { [value1, value2] }
+ let_it_be(:svalues) { [value2, value1] }
+
+ where(:case_name, :name, :args, :value, :block) do
+ 'execute :get command' | :get | ref(:key1) | ref(:value1) | nil
+ 'execute :mget command' | :mget | ref(:keys) | ref(:values) | nil
+ 'execute :mget with block' | :mget | ref(:keys) | ref(:values) | ->(value) { value }
+ 'execute :smembers command' | :smembers | ref(:skey) | ref(:svalues) | nil
+ 'execute :scard command' | :scard | ref(:skey) | 2 | nil
+ end
+
+ before(:all) do
+ primary_store.multi do |multi|
+ multi.set(key1, value1)
+ multi.set(key2, value2)
+ multi.sadd(skey, value1)
+ multi.sadd(skey, value2)
+ end
+
+ secondary_store.multi do |multi|
+ multi.set(key1, value1)
+ multi.set(key2, value2)
+ multi.sadd(skey, value1)
+ multi.sadd(skey, value2)
+ end
+ end
+
+ RSpec.shared_examples_for 'reads correct value' do
+ it 'returns the correct value' do
+ if value.is_a?(Array)
+ # :smembers does not guarantee the order it will return the values (unsorted set)
+ is_expected.to match_array(value)
+ else
+ is_expected.to eq(value)
+ end
+ end
+ end
+
+ RSpec.shared_examples_for 'fallback read from the secondary store' do
+ it 'fallback and execute on secondary instance' do
+ expect(secondary_store).to receive(name).with(*args).and_call_original
+
+ subject
+ end
+
+ it 'logs the ReadFromPrimaryError' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(an_instance_of(Gitlab::Redis::MultiStore::ReadFromPrimaryError),
+ hash_including(command_name: name, extra: hash_including(instance_name: instance_name)))
+
+ subject
+ end
+
+ it 'increment read fallback count metrics' do
+ expect(multi_store).to receive(:increment_read_fallback_count).with(name)
+
+ subject
+ end
+
+ include_examples 'reads correct value'
+
+ context 'when fallback read from the secondary instance raises an exception' do
+ before do
+ allow(secondary_store).to receive(name).with(*args).and_raise(StandardError)
+ end
+
+ it 'fails with exception' do
+ expect { subject }.to raise_error(StandardError)
+ end
+ end
+ end
+
+ RSpec.shared_examples_for 'secondary store' do
+ it 'execute on the secondary instance' do
+ expect(secondary_store).to receive(name).with(*args).and_call_original
+
+ subject
+ end
+
+ include_examples 'reads correct value'
+
+ it 'does not execute on the primary store' do
+ expect(primary_store).not_to receive(name)
+
+ subject
+ end
+ end
+
+ with_them do
+ describe "#{name}" do
+ before do
+ allow(primary_store).to receive(name).and_call_original
+ allow(secondary_store).to receive(name).and_call_original
+ end
+
+ context 'with feature flag :use_multi_store enabled' do
+ before do
+ stub_feature_flags(use_multi_store: true)
+ end
+
+ context 'when reading from the primary is successful' do
+ it 'returns the correct value' do
+ expect(primary_store).to receive(name).with(*args).and_call_original
+
+ subject
+ end
+
+ it 'does not execute on the secondary store' do
+ expect(secondary_store).not_to receive(name)
+
+ subject
+ end
+
+ include_examples 'reads correct value'
+ end
+
+ context 'when reading from primary instance is raising an exception' do
+ before do
+ allow(primary_store).to receive(name).with(*args).and_raise(StandardError)
+ allow(Gitlab::ErrorTracking).to receive(:log_exception)
+ end
+
+ it 'logs the exception' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(an_instance_of(StandardError),
+ hash_including(extra: hash_including(:multi_store_error_message, instance_name: instance_name),
+ command_name: name))
+
+ subject
+ end
+
+ include_examples 'fallback read from the secondary store'
+ end
+
+ context 'when reading from primary instance return no value' do
+ before do
+ allow(primary_store).to receive(name).and_return(nil)
+ end
+
+ include_examples 'fallback read from the secondary store'
+ end
+
+ context 'when the command is executed within pipelined block' do
+ subject do
+ multi_store.pipelined do
+ multi_store.send(name, *args)
+ end
+ end
+
+ it 'is executed only 1 time on primary instance' do
+ expect(primary_store).to receive(name).with(*args).once
+
+ subject
+ end
+ end
+
+ if params[:block]
+ subject do
+ multi_store.send(name, *args, &block)
+ end
+
+ context 'when block is provided' do
+ it 'yields to the block' do
+ expect(primary_store).to receive(name).and_yield(value)
+
+ subject
+ end
+
+ include_examples 'reads correct value'
+ end
+ end
+ end
+
+ context 'with feature flag :use_multi_store is disabled' do
+ before do
+ stub_feature_flags(use_multi_store: false)
+ end
+
+ it_behaves_like 'secondary store'
+ end
+
+ context 'with both primary and secondary store using same redis instance' do
+ let(:primary_store) { create_redis_store(redis_store_class.params, db: primary_db, serializer: nil) }
+ let(:secondary_store) { create_redis_store(redis_store_class.params, db: primary_db, serializer: nil) }
+ let(:multi_store) { described_class.new(primary_store, secondary_store, instance_name)}
+
+ it_behaves_like 'secondary store'
+ end
+ end
+ end
+ end
+
+ context 'with WRITE redis commands' do
+ let_it_be(:key1) { "redis:{1}:key_a" }
+ let_it_be(:key2) { "redis:{1}:key_b" }
+ let_it_be(:value1) { "redis_value1"}
+ let_it_be(:value2) { "redis_value2"}
+ let_it_be(:key1_value1) { [key1, value1] }
+ let_it_be(:key1_value2) { [key1, value2] }
+ let_it_be(:ttl) { 10 }
+ let_it_be(:key1_ttl_value1) { [key1, ttl, value1] }
+ let_it_be(:skey) { "redis:set:key" }
+ let_it_be(:svalues1) { [value2, value1] }
+ let_it_be(:svalues2) { [value1] }
+ let_it_be(:skey_value1) { [skey, value1] }
+ let_it_be(:skey_value2) { [skey, value2] }
+
+ where(:case_name, :name, :args, :expected_value, :verification_name, :verification_args) do
+ 'execute :set command' | :set | ref(:key1_value1) | ref(:value1) | :get | ref(:key1)
+ 'execute :setnx command' | :setnx | ref(:key1_value2) | ref(:value1) | :get | ref(:key2)
+ 'execute :setex command' | :setex | ref(:key1_ttl_value1) | ref(:ttl) | :ttl | ref(:key1)
+ 'execute :sadd command' | :sadd | ref(:skey_value2) | ref(:svalues1) | :smembers | ref(:skey)
+ 'execute :srem command' | :srem | ref(:skey_value1) | [] | :smembers | ref(:skey)
+ 'execute :del command' | :del | ref(:key2) | nil | :get | ref(:key2)
+ 'execute :flushdb command' | :flushdb | nil | 0 | :dbsize | nil
+ end
+
+ before do
+ primary_store.flushdb
+ secondary_store.flushdb
+
+ primary_store.multi do |multi|
+ multi.set(key2, value1)
+ multi.sadd(skey, value1)
+ end
+
+ secondary_store.multi do |multi|
+ multi.set(key2, value1)
+ multi.sadd(skey, value1)
+ end
+ end
+
+ RSpec.shared_examples_for 'verify that store contains values' do |store|
+ it "#{store} redis store contains correct values", :aggregate_errors do
+ subject
+
+ redis_store = multi_store.send(store)
+
+ if expected_value.is_a?(Array)
+ # :smembers does not guarantee the order it will return the values
+ expect(redis_store.send(verification_name, *verification_args)).to match_array(expected_value)
+ else
+ expect(redis_store.send(verification_name, *verification_args)).to eq(expected_value)
+ end
+ end
+ end
+
+ with_them do
+ describe "#{name}" do
+ let(:expected_args) {args || no_args }
+
+ before do
+ allow(primary_store).to receive(name).and_call_original
+ allow(secondary_store).to receive(name).and_call_original
+ end
+
+ context 'with feature flag :use_multi_store enabled' do
+ before do
+ stub_feature_flags(use_multi_store: true)
+ end
+
+ context 'when executing on primary instance is successful' do
+ it 'executes on both primary and secondary redis store', :aggregate_errors do
+ expect(primary_store).to receive(name).with(*expected_args).and_call_original
+ expect(secondary_store).to receive(name).with(*expected_args).and_call_original
+
+ subject
+ end
+
+ include_examples 'verify that store contains values', :primary_store
+ include_examples 'verify that store contains values', :secondary_store
+ end
+
+ context 'when executing on the primary instance is raising an exception' do
+ before do
+ allow(primary_store).to receive(name).with(*expected_args).and_raise(StandardError)
+ allow(Gitlab::ErrorTracking).to receive(:log_exception)
+ end
+
+ it 'logs the exception and execute on secondary instance', :aggregate_errors do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(an_instance_of(StandardError),
+ hash_including(extra: hash_including(:multi_store_error_message), command_name: name))
+ expect(secondary_store).to receive(name).with(*expected_args).and_call_original
+
+ subject
+ end
+
+ include_examples 'verify that store contains values', :secondary_store
+ end
+
+ context 'when the command is executed within pipelined block' do
+ subject do
+ multi_store.pipelined do
+ multi_store.send(name, *args)
+ end
+ end
+
+ it 'is executed only 1 time on each instance', :aggregate_errors do
+ expect(primary_store).to receive(name).with(*expected_args).once
+ expect(secondary_store).to receive(name).with(*expected_args).once
+
+ subject
+ end
+
+ include_examples 'verify that store contains values', :primary_store
+ include_examples 'verify that store contains values', :secondary_store
+ end
+ end
+
+ context 'with feature flag :use_multi_store is disabled' do
+ before do
+ stub_feature_flags(use_multi_store: false)
+ end
+
+ it 'executes only on the secondary redis store', :aggregate_errors do
+ expect(secondary_store).to receive(name).with(*expected_args)
+ expect(primary_store).not_to receive(name).with(*expected_args)
+
+ subject
+ end
+
+ include_examples 'verify that store contains values', :secondary_store
+ end
+ end
+ end
+ end
+
+ context 'with unsupported command' do
+ before do
+ primary_store.flushdb
+ secondary_store.flushdb
+ end
+
+ let_it_be(:key) { "redis:counter" }
+
+ subject do
+ multi_store.incr(key)
+ end
+
+ it 'executes method missing' do
+ expect(multi_store).to receive(:method_missing)
+
+ subject
+ end
+
+ it 'logs MethodMissingError' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(an_instance_of(Gitlab::Redis::MultiStore::MethodMissingError),
+ hash_including(command_name: :incr, extra: hash_including(instance_name: instance_name)))
+
+ subject
+ end
+
+ it 'increments method missing counter' do
+ expect(multi_store).to receive(:increment_method_missing_count).with(:incr)
+
+ subject
+ end
+
+ it 'fallback and executes only on the secondary store', :aggregate_errors do
+ expect(secondary_store).to receive(:incr).with(key).and_call_original
+ expect(primary_store).not_to receive(:incr)
+
+ subject
+ end
+
+ it 'correct value is stored on the secondary store', :aggregate_errors do
+ subject
+
+ expect(primary_store.get(key)).to be_nil
+ expect(secondary_store.get(key)).to eq('1')
+ end
+
+ context 'when the command is executed within pipelined block' do
+ subject do
+ multi_store.pipelined do
+ multi_store.incr(key)
+ end
+ end
+
+ it 'is executed only 1 time on each instance', :aggregate_errors do
+ expect(primary_store).to receive(:incr).with(key).once
+ expect(secondary_store).to receive(:incr).with(key).once
+
+ subject
+ end
+
+ it "both redis stores are containing correct values", :aggregate_errors do
+ subject
+
+ expect(primary_store.get(key)).to eq('1')
+ expect(secondary_store.get(key)).to eq('1')
+ end
+ end
+ end
+
+ def create_redis_store(options, extras = {})
+ ::Redis::Store.new(options.merge(extras))
+ end
+end
diff --git a/spec/lib/gitlab/runtime_spec.rb b/spec/lib/gitlab/runtime_spec.rb
index f51c5dd3d20..4627a8db82e 100644
--- a/spec/lib/gitlab/runtime_spec.rb
+++ b/spec/lib/gitlab/runtime_spec.rb
@@ -48,10 +48,9 @@ RSpec.describe Gitlab::Runtime do
before do
stub_const('::Puma', puma_type)
- stub_env('ACTION_CABLE_IN_APP', 'false')
end
- it_behaves_like "valid runtime", :puma, 1
+ it_behaves_like "valid runtime", :puma, 1 + Gitlab::ActionCable::Config.worker_pool_size
end
context "puma with cli_config" do
@@ -61,27 +60,16 @@ RSpec.describe Gitlab::Runtime do
before do
stub_const('::Puma', puma_type)
allow(puma_type).to receive_message_chain(:cli_config, :options).and_return(max_threads: 2, workers: max_workers)
- stub_env('ACTION_CABLE_IN_APP', 'false')
end
- it_behaves_like "valid runtime", :puma, 3
+ it_behaves_like "valid runtime", :puma, 3 + Gitlab::ActionCable::Config.worker_pool_size
- context "when ActionCable in-app mode is enabled" do
+ context "when ActionCable worker pool size is configured" do
before do
- stub_env('ACTION_CABLE_IN_APP', 'true')
- stub_env('ACTION_CABLE_WORKER_POOL_SIZE', '3')
+ stub_env('ACTION_CABLE_WORKER_POOL_SIZE', 10)
end
- it_behaves_like "valid runtime", :puma, 6
- end
-
- context "when ActionCable standalone is run" do
- before do
- stub_const('ACTION_CABLE_SERVER', true)
- stub_env('ACTION_CABLE_WORKER_POOL_SIZE', '8')
- end
-
- it_behaves_like "valid runtime", :puma, 11
+ it_behaves_like "valid runtime", :puma, 13
end
describe ".puma_in_clustered_mode?" do
@@ -108,7 +96,7 @@ RSpec.describe Gitlab::Runtime do
allow(sidekiq_type).to receive(:options).and_return(concurrency: 2)
end
- it_behaves_like "valid runtime", :sidekiq, 4
+ it_behaves_like "valid runtime", :sidekiq, 5
end
context "console" do
diff --git a/spec/lib/gitlab/search_results_spec.rb b/spec/lib/gitlab/search_results_spec.rb
index 27d65e14347..a38073e7c51 100644
--- a/spec/lib/gitlab/search_results_spec.rb
+++ b/spec/lib/gitlab/search_results_spec.rb
@@ -96,6 +96,18 @@ RSpec.describe Gitlab::SearchResults do
end
end
+ describe '#aggregations' do
+ where(:scope) do
+ %w(projects issues merge_requests blobs commits wiki_blobs epics milestones users unknown)
+ end
+
+ with_them do
+ it 'returns an empty array' do
+ expect(results.aggregations(scope)).to match_array([])
+ end
+ end
+ end
+
context "when count_limit is lower than total amount" do
before do
allow(results).to receive(:count_limit).and_return(1)
diff --git a/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb b/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb
deleted file mode 100644
index e818b03cf75..00000000000
--- a/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb
+++ /dev/null
@@ -1,334 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rspec-parameterized'
-
-RSpec.describe Gitlab::SidekiqCluster::CLI do
- let(:cli) { described_class.new('/dev/null') }
- let(:timeout) { described_class::DEFAULT_SOFT_TIMEOUT_SECONDS }
- let(:default_options) do
- { env: 'test', directory: Dir.pwd, max_concurrency: 50, min_concurrency: 0, dryrun: false, timeout: timeout }
- end
-
- before do
- stub_env('RAILS_ENV', 'test')
- end
-
- describe '#run' do
- context 'without any arguments' do
- it 'raises CommandError' do
- expect { cli.run([]) }.to raise_error(described_class::CommandError)
- end
- end
-
- context 'with arguments' do
- before do
- allow(cli).to receive(:write_pid)
- allow(cli).to receive(:trap_signals)
- allow(cli).to receive(:start_loop)
- end
-
- it 'starts the Sidekiq workers' do
- expect(Gitlab::SidekiqCluster).to receive(:start)
- .with([['foo']], default_options)
- .and_return([])
-
- cli.run(%w(foo))
- end
-
- it 'allows the special * selector' do
- worker_queues = %w(foo bar baz)
-
- expect(Gitlab::SidekiqConfig::CliMethods)
- .to receive(:worker_queues).and_return(worker_queues)
-
- expect(Gitlab::SidekiqCluster)
- .to receive(:start).with([worker_queues], default_options)
-
- cli.run(%w(*))
- end
-
- it 'raises an error when the arguments contain newlines' do
- invalid_arguments = [
- ["foo\n"],
- ["foo\r"],
- %W[foo b\nar]
- ]
-
- invalid_arguments.each do |arguments|
- expect { cli.run(arguments) }.to raise_error(described_class::CommandError)
- end
- end
-
- context 'with --negate flag' do
- it 'starts Sidekiq workers for all queues in all_queues.yml except the ones in argv' do
- expect(Gitlab::SidekiqConfig::CliMethods).to receive(:worker_queues).and_return(['baz'])
- expect(Gitlab::SidekiqCluster).to receive(:start)
- .with([['baz']], default_options)
- .and_return([])
-
- cli.run(%w(foo -n))
- end
- end
-
- context 'with --max-concurrency flag' do
- it 'starts Sidekiq workers for specified queues with a max concurrency' do
- expect(Gitlab::SidekiqConfig::CliMethods).to receive(:worker_queues).and_return(%w(foo bar baz))
- expect(Gitlab::SidekiqCluster).to receive(:start)
- .with([%w(foo bar baz), %w(solo)], default_options.merge(max_concurrency: 2))
- .and_return([])
-
- cli.run(%w(foo,bar,baz solo -m 2))
- end
- end
-
- context 'with --min-concurrency flag' do
- it 'starts Sidekiq workers for specified queues with a min concurrency' do
- expect(Gitlab::SidekiqConfig::CliMethods).to receive(:worker_queues).and_return(%w(foo bar baz))
- expect(Gitlab::SidekiqCluster).to receive(:start)
- .with([%w(foo bar baz), %w(solo)], default_options.merge(min_concurrency: 2))
- .and_return([])
-
- cli.run(%w(foo,bar,baz solo --min-concurrency 2))
- end
- end
-
- context 'with --timeout flag' do
- it 'when given', 'starts Sidekiq workers with given timeout' do
- expect(Gitlab::SidekiqCluster).to receive(:start)
- .with([['foo']], default_options.merge(timeout: 10))
-
- cli.run(%w(foo --timeout 10))
- end
-
- it 'when not given', 'starts Sidekiq workers with default timeout' do
- expect(Gitlab::SidekiqCluster).to receive(:start)
- .with([['foo']], default_options.merge(timeout: described_class::DEFAULT_SOFT_TIMEOUT_SECONDS))
-
- cli.run(%w(foo))
- end
- end
-
- context 'with --list-queues flag' do
- it 'errors when given --list-queues and --dryrun' do
- expect { cli.run(%w(foo --list-queues --dryrun)) }.to raise_error(described_class::CommandError)
- end
-
- it 'prints out a list of queues in alphabetical order' do
- expected_queues = [
- 'epics:epics_update_epics_dates',
- 'epics_new_epic_issue',
- 'new_epic',
- 'todos_destroyer:todos_destroyer_confidential_epic'
- ]
-
- allow(Gitlab::SidekiqConfig::CliMethods).to receive(:query_queues).and_return(expected_queues.shuffle)
-
- expect(cli).to receive(:puts).with([expected_queues])
-
- cli.run(%w(--queue-selector feature_category=epics --list-queues))
- end
- end
-
- context 'queue namespace expansion' do
- it 'starts Sidekiq workers for all queues in all_queues.yml with a namespace in argv' do
- expect(Gitlab::SidekiqConfig::CliMethods).to receive(:worker_queues).and_return(['cronjob:foo', 'cronjob:bar'])
- expect(Gitlab::SidekiqCluster).to receive(:start)
- .with([['cronjob', 'cronjob:foo', 'cronjob:bar']], default_options)
- .and_return([])
-
- cli.run(%w(cronjob))
- end
- end
-
- context "with --queue-selector" do
- where do
- {
- 'memory-bound queues' => {
- query: 'resource_boundary=memory',
- included_queues: %w(project_export),
- excluded_queues: %w(merge)
- },
- 'memory- or CPU-bound queues' => {
- query: 'resource_boundary=memory,cpu',
- included_queues: %w(auto_merge:auto_merge_process project_export),
- excluded_queues: %w(merge)
- },
- 'high urgency CI queues' => {
- query: 'feature_category=continuous_integration&urgency=high',
- included_queues: %w(pipeline_cache:expire_job_cache pipeline_cache:expire_pipeline_cache),
- excluded_queues: %w(merge)
- },
- 'CPU-bound high urgency CI queues' => {
- query: 'feature_category=continuous_integration&urgency=high&resource_boundary=cpu',
- included_queues: %w(pipeline_cache:expire_pipeline_cache),
- excluded_queues: %w(pipeline_cache:expire_job_cache merge)
- },
- 'CPU-bound high urgency non-CI queues' => {
- query: 'feature_category!=continuous_integration&urgency=high&resource_boundary=cpu',
- included_queues: %w(new_issue),
- excluded_queues: %w(pipeline_cache:expire_pipeline_cache)
- },
- 'CI and SCM queues' => {
- query: 'feature_category=continuous_integration|feature_category=source_code_management',
- included_queues: %w(pipeline_cache:expire_job_cache merge),
- excluded_queues: %w(mailers)
- }
- }
- end
-
- with_them do
- it 'expands queues by attributes' do
- expect(Gitlab::SidekiqCluster).to receive(:start) do |queues, opts|
- expect(opts).to eq(default_options)
- expect(queues.first).to include(*included_queues)
- expect(queues.first).not_to include(*excluded_queues)
-
- []
- end
-
- cli.run(%W(--queue-selector #{query}))
- end
-
- it 'works when negated' do
- expect(Gitlab::SidekiqCluster).to receive(:start) do |queues, opts|
- expect(opts).to eq(default_options)
- expect(queues.first).not_to include(*included_queues)
- expect(queues.first).to include(*excluded_queues)
-
- []
- end
-
- cli.run(%W(--negate --queue-selector #{query}))
- end
- end
-
- it 'expands multiple queue groups correctly' do
- expect(Gitlab::SidekiqCluster)
- .to receive(:start)
- .with([['chat_notification'], ['project_export']], default_options)
- .and_return([])
-
- cli.run(%w(--queue-selector feature_category=chatops&has_external_dependencies=true resource_boundary=memory&feature_category=importers))
- end
-
- it 'allows the special * selector' do
- worker_queues = %w(foo bar baz)
-
- expect(Gitlab::SidekiqConfig::CliMethods)
- .to receive(:worker_queues).and_return(worker_queues)
-
- expect(Gitlab::SidekiqCluster)
- .to receive(:start).with([worker_queues], default_options)
-
- cli.run(%w(--queue-selector *))
- end
-
- it 'errors when the selector matches no queues' do
- expect(Gitlab::SidekiqCluster).not_to receive(:start)
-
- expect { cli.run(%w(--queue-selector has_external_dependencies=true&has_external_dependencies=false)) }
- .to raise_error(described_class::CommandError)
- end
-
- it 'errors on an invalid query multiple queue groups correctly' do
- expect(Gitlab::SidekiqCluster).not_to receive(:start)
-
- expect { cli.run(%w(--queue-selector unknown_field=chatops)) }
- .to raise_error(Gitlab::SidekiqConfig::WorkerMatcher::QueryError)
- end
- end
- end
- end
-
- describe '#write_pid' do
- context 'when a PID is specified' do
- it 'writes the PID to a file' do
- expect(Gitlab::SidekiqCluster).to receive(:write_pid).with('/dev/null')
-
- cli.option_parser.parse!(%w(-P /dev/null))
- cli.write_pid
- end
- end
-
- context 'when no PID is specified' do
- it 'does not write a PID' do
- expect(Gitlab::SidekiqCluster).not_to receive(:write_pid)
-
- cli.write_pid
- end
- end
- end
-
- describe '#wait_for_termination' do
- it 'waits for termination of all sub-processes and succeeds after 3 checks' do
- expect(Gitlab::SidekiqCluster).to receive(:any_alive?)
- .with(an_instance_of(Array)).and_return(true, true, true, false)
-
- expect(Gitlab::SidekiqCluster).to receive(:pids_alive)
- .with([]).and_return([])
-
- expect(Gitlab::SidekiqCluster).to receive(:signal_processes)
- .with([], "-KILL")
-
- stub_const("Gitlab::SidekiqCluster::CLI::CHECK_TERMINATE_INTERVAL_SECONDS", 0.1)
- allow(cli).to receive(:terminate_timeout_seconds) { 1 }
-
- cli.wait_for_termination
- end
-
- context 'with hanging workers' do
- before do
- expect(cli).to receive(:write_pid)
- expect(cli).to receive(:trap_signals)
- expect(cli).to receive(:start_loop)
- end
-
- it 'hard kills workers after timeout expires' do
- worker_pids = [101, 102, 103]
- expect(Gitlab::SidekiqCluster).to receive(:start)
- .with([['foo']], default_options)
- .and_return(worker_pids)
-
- expect(Gitlab::SidekiqCluster).to receive(:any_alive?)
- .with(worker_pids).and_return(true).at_least(10).times
-
- expect(Gitlab::SidekiqCluster).to receive(:pids_alive)
- .with(worker_pids).and_return([102])
-
- expect(Gitlab::SidekiqCluster).to receive(:signal_processes)
- .with([102], "-KILL")
-
- cli.run(%w(foo))
-
- stub_const("Gitlab::SidekiqCluster::CLI::CHECK_TERMINATE_INTERVAL_SECONDS", 0.1)
- allow(cli).to receive(:terminate_timeout_seconds) { 1 }
-
- cli.wait_for_termination
- end
- end
- end
-
- describe '#trap_signals' do
- it 'traps the termination and forwarding signals' do
- expect(Gitlab::SidekiqCluster).to receive(:trap_terminate)
- expect(Gitlab::SidekiqCluster).to receive(:trap_forward)
-
- cli.trap_signals
- end
- end
-
- describe '#start_loop' do
- it 'runs until one of the processes has been terminated' do
- allow(cli).to receive(:sleep).with(a_kind_of(Numeric))
-
- expect(Gitlab::SidekiqCluster).to receive(:all_alive?)
- .with(an_instance_of(Array)).and_return(false)
-
- expect(Gitlab::SidekiqCluster).to receive(:signal_processes)
- .with(an_instance_of(Array), :TERM)
-
- cli.start_loop
- end
- end
-end
diff --git a/spec/lib/gitlab/sidekiq_cluster_spec.rb b/spec/lib/gitlab/sidekiq_cluster_spec.rb
deleted file mode 100644
index 3c6ea054968..00000000000
--- a/spec/lib/gitlab/sidekiq_cluster_spec.rb
+++ /dev/null
@@ -1,207 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rspec-parameterized'
-
-RSpec.describe Gitlab::SidekiqCluster do
- describe '.trap_signals' do
- it 'traps the given signals' do
- expect(described_class).to receive(:trap).ordered.with(:INT)
- expect(described_class).to receive(:trap).ordered.with(:HUP)
-
- described_class.trap_signals(%i(INT HUP))
- end
- end
-
- describe '.trap_terminate' do
- it 'traps the termination signals' do
- expect(described_class).to receive(:trap_signals)
- .with(described_class::TERMINATE_SIGNALS)
-
- described_class.trap_terminate { }
- end
- end
-
- describe '.trap_forward' do
- it 'traps the signals to forward' do
- expect(described_class).to receive(:trap_signals)
- .with(described_class::FORWARD_SIGNALS)
-
- described_class.trap_forward { }
- end
- end
-
- describe '.signal' do
- it 'sends a signal to the given process' do
- allow(Process).to receive(:kill).with(:INT, 4)
- expect(described_class.signal(4, :INT)).to eq(true)
- end
-
- it 'returns false when the process does not exist' do
- allow(Process).to receive(:kill).with(:INT, 4).and_raise(Errno::ESRCH)
- expect(described_class.signal(4, :INT)).to eq(false)
- end
- end
-
- describe '.signal_processes' do
- it 'sends a signal to every given process' do
- expect(described_class).to receive(:signal).with(1, :INT)
-
- described_class.signal_processes([1], :INT)
- end
- end
-
- describe '.start' do
- it 'starts Sidekiq with the given queues, environment and options' do
- expected_options = {
- env: :production,
- directory: 'foo/bar',
- max_concurrency: 20,
- min_concurrency: 10,
- timeout: 25,
- dryrun: true
- }
-
- expect(described_class).to receive(:start_sidekiq).ordered.with(%w(foo), expected_options.merge(worker_id: 0))
- expect(described_class).to receive(:start_sidekiq).ordered.with(%w(bar baz), expected_options.merge(worker_id: 1))
-
- described_class.start([%w(foo), %w(bar baz)], env: :production, directory: 'foo/bar', max_concurrency: 20, min_concurrency: 10, dryrun: true)
- end
-
- it 'starts Sidekiq with the given queues and sensible default options' do
- expected_options = {
- env: :development,
- directory: an_instance_of(String),
- max_concurrency: 50,
- min_concurrency: 0,
- worker_id: an_instance_of(Integer),
- timeout: 25,
- dryrun: false
- }
-
- expect(described_class).to receive(:start_sidekiq).ordered.with(%w(foo bar baz), expected_options)
- expect(described_class).to receive(:start_sidekiq).ordered.with(%w(solo), expected_options)
-
- described_class.start([%w(foo bar baz), %w(solo)])
- end
- end
-
- describe '.start_sidekiq' do
- let(:first_worker_id) { 0 }
- let(:options) do
- { env: :production, directory: 'foo/bar', max_concurrency: 20, min_concurrency: 0, worker_id: first_worker_id, timeout: 10, dryrun: false }
- end
-
- let(:env) { { "ENABLE_SIDEKIQ_CLUSTER" => "1", "SIDEKIQ_WORKER_ID" => first_worker_id.to_s } }
- let(:args) { ['bundle', 'exec', 'sidekiq', anything, '-eproduction', '-t10', *([anything] * 5)] }
-
- it 'starts a Sidekiq process' do
- allow(Process).to receive(:spawn).and_return(1)
-
- expect(described_class).to receive(:wait_async).with(1)
- expect(described_class.start_sidekiq(%w(foo), **options)).to eq(1)
- end
-
- it 'handles duplicate queue names' do
- allow(Process)
- .to receive(:spawn)
- .with(env, *args, anything)
- .and_return(1)
-
- expect(described_class).to receive(:wait_async).with(1)
- expect(described_class.start_sidekiq(%w(foo foo bar baz), **options)).to eq(1)
- end
-
- it 'runs the sidekiq process in a new process group' do
- expect(Process)
- .to receive(:spawn)
- .with(anything, *args, a_hash_including(pgroup: true))
- .and_return(1)
-
- allow(described_class).to receive(:wait_async)
- expect(described_class.start_sidekiq(%w(foo bar baz), **options)).to eq(1)
- end
- end
-
- describe '.count_by_queue' do
- it 'tallies the queue counts' do
- queues = [%w(foo), %w(bar baz), %w(foo)]
-
- expect(described_class.count_by_queue(queues)).to eq(%w(foo) => 2, %w(bar baz) => 1)
- end
- end
-
- describe '.concurrency' do
- using RSpec::Parameterized::TableSyntax
-
- where(:queue_count, :min, :max, :expected) do
- 2 | 0 | 0 | 3 # No min or max specified
- 2 | 0 | 9 | 3 # No min specified, value < max
- 2 | 1 | 4 | 3 # Value between min and max
- 2 | 4 | 5 | 4 # Value below range
- 5 | 2 | 3 | 3 # Value above range
- 2 | 1 | 1 | 1 # Value above explicit setting (min == max)
- 0 | 3 | 3 | 3 # Value below explicit setting (min == max)
- 1 | 4 | 3 | 3 # Min greater than max
- end
-
- with_them do
- let(:queues) { Array.new(queue_count) }
-
- it { expect(described_class.concurrency(queues, min, max)).to eq(expected) }
- end
- end
-
- describe '.wait_async' do
- it 'waits for a process in a separate thread' do
- thread = described_class.wait_async(Process.spawn('true'))
-
- # Upon success Process.wait just returns the PID.
- expect(thread.value).to be_a_kind_of(Numeric)
- end
- end
-
- # In the X_alive? checks, we check negative PIDs sometimes as a simple way
- # to be sure the pids are definitely for non-existent processes.
- # Note that -1 is special, and sends the signal to every process we have permission
- # for, so we use -2, -3 etc
- describe '.all_alive?' do
- it 'returns true if all processes are alive' do
- processes = [Process.pid]
-
- expect(described_class.all_alive?(processes)).to eq(true)
- end
-
- it 'returns false when a thread was not alive' do
- processes = [-2]
-
- expect(described_class.all_alive?(processes)).to eq(false)
- end
- end
-
- describe '.any_alive?' do
- it 'returns true if at least one process is alive' do
- processes = [Process.pid, -2]
-
- expect(described_class.any_alive?(processes)).to eq(true)
- end
-
- it 'returns false when all threads are dead' do
- processes = [-2, -3]
-
- expect(described_class.any_alive?(processes)).to eq(false)
- end
- end
-
- describe '.write_pid' do
- it 'writes the PID of the current process to the given file' do
- handle = double(:handle)
-
- allow(File).to receive(:open).with('/dev/null', 'w').and_yield(handle)
-
- expect(handle).to receive(:write).with(Process.pid.to_s)
-
- described_class.write_pid('/dev/null')
- end
- end
-end
diff --git a/spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb b/spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb
index bc63289a344..576b36c1829 100644
--- a/spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb
+++ b/spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb
@@ -11,12 +11,12 @@ RSpec.describe Gitlab::SidekiqConfig::CliMethods do
end
def stub_exists(exists: true)
- ['app/workers/all_queues.yml', 'ee/app/workers/all_queues.yml'].each do |path|
+ ['app/workers/all_queues.yml', 'ee/app/workers/all_queues.yml', 'jh/app/workers/all_queues.yml'].each do |path|
allow(File).to receive(:exist?).with(expand_path(path)).and_return(exists)
end
end
- def stub_contents(foss_queues, ee_queues)
+ def stub_contents(foss_queues, ee_queues, jh_queues)
allow(YAML).to receive(:load_file)
.with(expand_path('app/workers/all_queues.yml'))
.and_return(foss_queues)
@@ -24,6 +24,10 @@ RSpec.describe Gitlab::SidekiqConfig::CliMethods do
allow(YAML).to receive(:load_file)
.with(expand_path('ee/app/workers/all_queues.yml'))
.and_return(ee_queues)
+
+ allow(YAML).to receive(:load_file)
+ .with(expand_path('jh/app/workers/all_queues.yml'))
+ .and_return(jh_queues)
end
before do
@@ -45,8 +49,9 @@ RSpec.describe Gitlab::SidekiqConfig::CliMethods do
end
it 'flattens and joins the contents' do
- expected_queues = %w[queue_a queue_b]
- expected_queues = expected_queues.first(1) unless Gitlab.ee?
+ expected_queues = %w[queue_a]
+ expected_queues << 'queue_b' if Gitlab.ee?
+ expected_queues << 'queue_c' if Gitlab.jh?
expect(described_class.worker_queues(dummy_root))
.to match_array(expected_queues)
@@ -55,7 +60,7 @@ RSpec.describe Gitlab::SidekiqConfig::CliMethods do
context 'when the file contains an array of hashes' do
before do
- stub_contents([{ name: 'queue_a' }], [{ name: 'queue_b' }])
+ stub_contents([{ name: 'queue_a' }], [{ name: 'queue_b' }], [{ name: 'queue_c' }])
end
include_examples 'valid file contents'
diff --git a/spec/lib/gitlab/sidekiq_config/worker_spec.rb b/spec/lib/gitlab/sidekiq_config/worker_spec.rb
index f4d7a4b3359..9c252b3d50b 100644
--- a/spec/lib/gitlab/sidekiq_config/worker_spec.rb
+++ b/spec/lib/gitlab/sidekiq_config/worker_spec.rb
@@ -18,19 +18,26 @@ RSpec.describe Gitlab::SidekiqConfig::Worker do
get_tags: attributes[:tags]
)
- described_class.new(inner_worker, ee: false)
+ described_class.new(inner_worker, ee: false, jh: false)
end
describe '#ee?' do
it 'returns the EE status set on creation' do
- expect(described_class.new(double, ee: true)).to be_ee
- expect(described_class.new(double, ee: false)).not_to be_ee
+ expect(described_class.new(double, ee: true, jh: false)).to be_ee
+ expect(described_class.new(double, ee: false, jh: false)).not_to be_ee
+ end
+ end
+
+ describe '#jh?' do
+ it 'returns the JH status set on creation' do
+ expect(described_class.new(double, ee: false, jh: true)).to be_jh
+ expect(described_class.new(double, ee: false, jh: false)).not_to be_jh
end
end
describe '#==' do
def worker_with_yaml(yaml)
- described_class.new(double, ee: false).tap do |worker|
+ described_class.new(double, ee: false, jh: false).tap do |worker|
allow(worker).to receive(:to_yaml).and_return(yaml)
end
end
@@ -57,7 +64,7 @@ RSpec.describe Gitlab::SidekiqConfig::Worker do
expect(worker).to receive(meth)
- described_class.new(worker, ee: false).send(meth)
+ described_class.new(worker, ee: false, jh: false).send(meth)
end
end
end
diff --git a/spec/lib/gitlab/sidekiq_enq_spec.rb b/spec/lib/gitlab/sidekiq_enq_spec.rb
new file mode 100644
index 00000000000..6903f01bf5f
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_enq_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::SidekiqEnq, :clean_gitlab_redis_queues do
+ let(:retry_set) { Sidekiq::Scheduled::SETS.first }
+ let(:schedule_set) { Sidekiq::Scheduled::SETS.last }
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ shared_examples 'finds jobs that are due and enqueues them' do
+ before do
+ Sidekiq.redis do |redis|
+ redis.zadd(retry_set, (Time.current - 1.day).to_f.to_s, '{"jid": 1}')
+ redis.zadd(retry_set, Time.current.to_f.to_s, '{"jid": 2}')
+ redis.zadd(retry_set, (Time.current + 1.day).to_f.to_s, '{"jid": 3}')
+
+ redis.zadd(schedule_set, (Time.current - 1.day).to_f.to_s, '{"jid": 4}')
+ redis.zadd(schedule_set, Time.current.to_f.to_s, '{"jid": 5}')
+ redis.zadd(schedule_set, (Time.current + 1.day).to_f.to_s, '{"jid": 6}')
+ end
+ end
+
+ it 'enqueues jobs that are due' do
+ expect(Sidekiq::Client).to receive(:push).with({ 'jid' => 1 })
+ expect(Sidekiq::Client).to receive(:push).with({ 'jid' => 2 })
+ expect(Sidekiq::Client).to receive(:push).with({ 'jid' => 4 })
+ expect(Sidekiq::Client).to receive(:push).with({ 'jid' => 5 })
+
+ Gitlab::SidekiqEnq.new.enqueue_jobs
+
+ Sidekiq.redis do |redis|
+ expect(redis.zscan_each(retry_set).map(&:first)).to contain_exactly('{"jid": 3}')
+ expect(redis.zscan_each(schedule_set).map(&:first)).to contain_exactly('{"jid": 6}')
+ end
+ end
+ end
+
+ context 'when atomic_sidekiq_scheduler is disabled' do
+ before do
+ stub_feature_flags(atomic_sidekiq_scheduler: false)
+ end
+
+ it_behaves_like 'finds jobs that are due and enqueues them'
+
+ context 'when ZRANGEBYSCORE returns a job that is already removed by another process' do
+ before do
+ Sidekiq.redis do |redis|
+ redis.zadd(schedule_set, Time.current.to_f.to_s, '{"jid": 1}')
+
+ allow(redis).to receive(:zrangebyscore).and_wrap_original do |m, *args, **kwargs|
+ m.call(*args, **kwargs).tap do |jobs|
+ redis.zrem(schedule_set, jobs.first) if args[0] == schedule_set && jobs.first
+ end
+ end
+ end
+ end
+
+ it 'calls ZREM but does not enqueue the job' do
+ Sidekiq.redis do |redis|
+ expect(redis).to receive(:zrem).with(schedule_set, '{"jid": 1}').twice.and_call_original
+ end
+ expect(Sidekiq::Client).not_to receive(:push)
+
+ Gitlab::SidekiqEnq.new.enqueue_jobs
+ end
+ end
+ end
+
+ context 'when atomic_sidekiq_scheduler is enabled' do
+ before do
+ stub_feature_flags(atomic_sidekiq_scheduler: true)
+ end
+
+ context 'when Lua script is not yet loaded' do
+ before do
+ Gitlab::Redis::Queues.with { |redis| redis.script(:flush) }
+ end
+
+ it_behaves_like 'finds jobs that are due and enqueues them'
+ end
+
+ context 'when Lua script is already loaded' do
+ before do
+ Gitlab::SidekiqEnq.new.enqueue_jobs
+ end
+
+ it_behaves_like 'finds jobs that are due and enqueues them'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_logging/deduplication_logger_spec.rb b/spec/lib/gitlab/sidekiq_logging/deduplication_logger_spec.rb
index 82f927fe481..f44a1e8b6ba 100644
--- a/spec/lib/gitlab/sidekiq_logging/deduplication_logger_spec.rb
+++ b/spec/lib/gitlab/sidekiq_logging/deduplication_logger_spec.rb
@@ -23,11 +23,37 @@ RSpec.describe Gitlab::SidekiqLogging::DeduplicationLogger do
}
expect(Sidekiq.logger).to receive(:info).with(a_hash_including(expected_payload)).and_call_original
- described_class.instance.log(job, "a fancy strategy", { foo: :bar })
+ described_class.instance.deduplicated_log(job, "a fancy strategy", { foo: :bar })
end
it "does not modify the job" do
- expect { described_class.instance.log(job, "a fancy strategy") }
+ expect { described_class.instance.deduplicated_log(job, "a fancy strategy") }
+ .not_to change { job }
+ end
+ end
+
+ describe '#rescheduled_log' do
+ let(:job) do
+ {
+ 'class' => 'TestWorker',
+ 'args' => [1234, 'hello', { 'key' => 'value' }],
+ 'jid' => 'da883554ee4fe414012f5f42',
+ 'correlation_id' => 'cid'
+ }
+ end
+
+ it 'logs a rescheduled message to the sidekiq logger' do
+ expected_payload = {
+ 'job_status' => 'rescheduled',
+ 'message' => "#{job['class']} JID-#{job['jid']}: rescheduled"
+ }
+ expect(Sidekiq.logger).to receive(:info).with(a_hash_including(expected_payload)).and_call_original
+
+ described_class.instance.rescheduled_log(job)
+ end
+
+ it 'does not modify the job' do
+ expect { described_class.instance.rescheduled_log(job) }
.not_to change { job }
end
end
diff --git a/spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb b/spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb
index c879fdea3ad..b6fb3fecf20 100644
--- a/spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb
+++ b/spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe Gitlab::SidekiqLogging::JSONFormatter do
'class' => 'PostReceive',
'bar' => 'test',
'created_at' => timestamp,
+ 'scheduled_at' => timestamp,
'enqueued_at' => timestamp,
'started_at' => timestamp,
'retried_at' => timestamp,
@@ -31,6 +32,7 @@ RSpec.describe Gitlab::SidekiqLogging::JSONFormatter do
'severity' => 'INFO',
'time' => timestamp_iso8601,
'created_at' => timestamp_iso8601,
+ 'scheduled_at' => timestamp_iso8601,
'enqueued_at' => timestamp_iso8601,
'started_at' => timestamp_iso8601,
'retried_at' => timestamp_iso8601,
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb
index 5083ac514db..833de6ae624 100644
--- a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb
@@ -24,6 +24,10 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
"#{Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE}:duplicate:#{queue}:#{hash}"
end
+ let(:deduplicated_flag_key) do
+ "#{idempotency_key}:deduplicate_flag"
+ end
+
describe '#schedule' do
shared_examples 'scheduling with deduplication class' do |strategy_class|
it 'calls schedule on the strategy' do
@@ -81,25 +85,43 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
context 'when there was no job in the queue yet' do
it { expect(duplicate_job.check!).to eq('123') }
- it "adds a idempotency key with ttl set to #{described_class::DUPLICATE_KEY_TTL}" do
- expect { duplicate_job.check! }
- .to change { read_idempotency_key_with_ttl(idempotency_key) }
- .from([nil, -2])
- .to(['123', be_within(1).of(described_class::DUPLICATE_KEY_TTL)])
- end
-
- context 'when wal locations is not empty' do
- it "adds a existing wal locations key with ttl set to #{described_class::DUPLICATE_KEY_TTL}" do
+ shared_examples 'sets Redis keys with correct TTL' do
+ it "adds an idempotency key with correct ttl" do
expect { duplicate_job.check! }
- .to change { read_idempotency_key_with_ttl(existing_wal_location_key(idempotency_key, :main)) }
- .from([nil, -2])
- .to([wal_locations[:main], be_within(1).of(described_class::DUPLICATE_KEY_TTL)])
- .and change { read_idempotency_key_with_ttl(existing_wal_location_key(idempotency_key, :ci)) }
+ .to change { read_idempotency_key_with_ttl(idempotency_key) }
.from([nil, -2])
- .to([wal_locations[:ci], be_within(1).of(described_class::DUPLICATE_KEY_TTL)])
+ .to(['123', be_within(1).of(expected_ttl)])
+ end
+
+ context 'when wal locations is not empty' do
+ it "adds an existing wal locations key with correct ttl" do
+ expect { duplicate_job.check! }
+ .to change { read_idempotency_key_with_ttl(existing_wal_location_key(idempotency_key, :main)) }
+ .from([nil, -2])
+ .to([wal_locations[:main], be_within(1).of(expected_ttl)])
+ .and change { read_idempotency_key_with_ttl(existing_wal_location_key(idempotency_key, :ci)) }
+ .from([nil, -2])
+ .to([wal_locations[:ci], be_within(1).of(expected_ttl)])
+ end
end
end
+ context 'with TTL option is not set' do
+ let(:expected_ttl) { described_class::DEFAULT_DUPLICATE_KEY_TTL }
+
+ it_behaves_like 'sets Redis keys with correct TTL'
+ end
+
+ context 'when TTL option is set' do
+ let(:expected_ttl) { 5.minutes }
+
+ before do
+ allow(duplicate_job).to receive(:options).and_return({ ttl: expected_ttl })
+ end
+
+ it_behaves_like 'sets Redis keys with correct TTL'
+ end
+
context 'when preserve_latest_wal_locations_for_idempotent_jobs feature flag is disabled' do
before do
stub_feature_flags(preserve_latest_wal_locations_for_idempotent_jobs: false)
@@ -152,26 +174,21 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
end
describe '#update_latest_wal_location!' do
- let(:offset) { '1024' }
-
before do
- allow(duplicate_job).to receive(:pg_wal_lsn_diff).with(:main).and_return(offset)
- allow(duplicate_job).to receive(:pg_wal_lsn_diff).with(:ci).and_return(offset)
- end
+ allow(Gitlab::Database).to receive(:database_base_models).and_return(
+ { main: ::ActiveRecord::Base,
+ ci: ::ActiveRecord::Base })
- shared_examples 'updates wal location' do
- it 'updates a wal location to redis with an offset' do
- expect { duplicate_job.update_latest_wal_location! }
- .to change { read_range_from_redis(wal_location_key(idempotency_key, :main)) }
- .from(existing_wal_with_offset[:main])
- .to(new_wal_with_offset[:main])
- .and change { read_range_from_redis(wal_location_key(idempotency_key, :ci)) }
- .from(existing_wal_with_offset[:ci])
- .to(new_wal_with_offset[:ci])
- end
+ set_idempotency_key(existing_wal_location_key(idempotency_key, :main), existing_wal[:main])
+ set_idempotency_key(existing_wal_location_key(idempotency_key, :ci), existing_wal[:ci])
+
+ # read existing_wal_locations
+ duplicate_job.check!
end
context 'when preserve_latest_wal_locations_for_idempotent_jobs feature flag is disabled' do
+ let(:existing_wal) { {} }
+
before do
stub_feature_flags(preserve_latest_wal_locations_for_idempotent_jobs: false)
end
@@ -192,42 +209,107 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
end
context "when the key doesn't exists in redis" do
- include_examples 'updates wal location' do
- let(:existing_wal_with_offset) { { main: [], ci: [] } }
- let(:new_wal_with_offset) { wal_locations.transform_values { |v| [v, offset] } }
+ let(:existing_wal) do
+ {
+ main: '0/D525E3A0',
+ ci: 'AB/12340'
+ }
end
- end
- context "when the key exists in redis" do
- let(:existing_offset) { '1023'}
- let(:existing_wal_locations) do
+ let(:new_wal_location_with_offset) do
{
- main: '0/D525E3NM',
- ci: 'AB/111112'
+ # offset is relative to `existing_wal`
+ main: ['0/D525E3A8', '8'],
+ ci: ['AB/12345', '5']
}
end
+ let(:wal_locations) { new_wal_location_with_offset.transform_values(&:first) }
+
+ it 'stores a wal location to redis with an offset relative to existing wal location' do
+ expect { duplicate_job.update_latest_wal_location! }
+ .to change { read_range_from_redis(wal_location_key(idempotency_key, :main)) }
+ .from([])
+ .to(new_wal_location_with_offset[:main])
+ .and change { read_range_from_redis(wal_location_key(idempotency_key, :ci)) }
+ .from([])
+ .to(new_wal_location_with_offset[:ci])
+ end
+ end
+
+ context "when the key exists in redis" do
before do
- rpush_to_redis_key(wal_location_key(idempotency_key, :main), existing_wal_locations[:main], existing_offset)
- rpush_to_redis_key(wal_location_key(idempotency_key, :ci), existing_wal_locations[:ci], existing_offset)
+ rpush_to_redis_key(wal_location_key(idempotency_key, :main), *stored_wal_location_with_offset[:main])
+ rpush_to_redis_key(wal_location_key(idempotency_key, :ci), *stored_wal_location_with_offset[:ci])
end
+ let(:wal_locations) { new_wal_location_with_offset.transform_values(&:first) }
+
context "when the new offset is bigger then the existing one" do
- include_examples 'updates wal location' do
- let(:existing_wal_with_offset) { existing_wal_locations.transform_values { |v| [v, existing_offset] } }
- let(:new_wal_with_offset) { wal_locations.transform_values { |v| [v, offset] } }
+ let(:existing_wal) do
+ {
+ main: '0/D525E3A0',
+ ci: 'AB/12340'
+ }
+ end
+
+ let(:stored_wal_location_with_offset) do
+ {
+ # offset is relative to `existing_wal`
+ main: ['0/D525E3A3', '3'],
+ ci: ['AB/12342', '2']
+ }
+ end
+
+ let(:new_wal_location_with_offset) do
+ {
+ # offset is relative to `existing_wal`
+ main: ['0/D525E3A8', '8'],
+ ci: ['AB/12345', '5']
+ }
+ end
+
+ it 'updates a wal location to redis with an offset' do
+ expect { duplicate_job.update_latest_wal_location! }
+ .to change { read_range_from_redis(wal_location_key(idempotency_key, :main)) }
+ .from(stored_wal_location_with_offset[:main])
+ .to(new_wal_location_with_offset[:main])
+ .and change { read_range_from_redis(wal_location_key(idempotency_key, :ci)) }
+ .from(stored_wal_location_with_offset[:ci])
+ .to(new_wal_location_with_offset[:ci])
end
end
context "when the old offset is not bigger then the existing one" do
- let(:existing_offset) { offset }
+ let(:existing_wal) do
+ {
+ main: '0/D525E3A0',
+ ci: 'AB/12340'
+ }
+ end
+
+ let(:stored_wal_location_with_offset) do
+ {
+ # offset is relative to `existing_wal`
+ main: ['0/D525E3A8', '8'],
+ ci: ['AB/12345', '5']
+ }
+ end
+
+ let(:new_wal_location_with_offset) do
+ {
+ # offset is relative to `existing_wal`
+ main: ['0/D525E3A2', '2'],
+ ci: ['AB/12342', '2']
+ }
+ end
it "does not update a wal location to redis with an offset" do
expect { duplicate_job.update_latest_wal_location! }
.to not_change { read_range_from_redis(wal_location_key(idempotency_key, :main)) }
- .from([existing_wal_locations[:main], existing_offset])
+ .from(stored_wal_location_with_offset[:main])
.and not_change { read_range_from_redis(wal_location_key(idempotency_key, :ci)) }
- .from([existing_wal_locations[:ci], existing_offset])
+ .from(stored_wal_location_with_offset[:ci])
end
end
end
@@ -270,6 +352,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
context 'when the key exists in redis' do
before do
set_idempotency_key(idempotency_key, 'existing-jid')
+ set_idempotency_key(deduplicated_flag_key, 1)
wal_locations.each do |config_name, location|
set_idempotency_key(existing_wal_location_key(idempotency_key, config_name), location)
set_idempotency_key(wal_location_key(idempotency_key, config_name), location)
@@ -299,6 +382,11 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
let(:from_value) { 'existing-jid' }
end
+ it_behaves_like 'deleting keys from redis', 'deduplication counter key' do
+ let(:key) { deduplicated_flag_key }
+ let(:from_value) { '1' }
+ end
+
it_behaves_like 'deleting keys from redis', 'existing wal location keys for main database' do
let(:key) { existing_wal_location_key(idempotency_key, :main) }
let(:from_value) { wal_locations[:main] }
@@ -390,6 +478,103 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
end
end
+ describe '#reschedule' do
+ it 'reschedules the current job' do
+ fake_logger = instance_double(Gitlab::SidekiqLogging::DeduplicationLogger)
+ expect(Gitlab::SidekiqLogging::DeduplicationLogger).to receive(:instance).and_return(fake_logger)
+ expect(fake_logger).to receive(:rescheduled_log).with(a_hash_including({ 'jid' => '123' }))
+ expect(AuthorizedProjectsWorker).to receive(:perform_async).with(1).once
+
+ duplicate_job.reschedule
+ end
+ end
+
+ describe '#should_reschedule?' do
+ subject { duplicate_job.should_reschedule? }
+
+ context 'when the job is reschedulable' do
+ before do
+ allow(duplicate_job).to receive(:reschedulable?) { true }
+ end
+
+ it { is_expected.to eq(false) }
+
+ context 'with deduplicated flag' do
+ before do
+ duplicate_job.set_deduplicated_flag!
+ end
+
+ it { is_expected.to eq(true) }
+ end
+ end
+
+ context 'when the job is not reschedulable' do
+ before do
+ allow(duplicate_job).to receive(:reschedulable?) { false }
+ end
+
+ it { is_expected.to eq(false) }
+
+ context 'with deduplicated flag' do
+ before do
+ duplicate_job.set_deduplicated_flag!
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+ end
+
+ describe '#set_deduplicated_flag!' do
+ context 'when the job is reschedulable' do
+ before do
+ allow(duplicate_job).to receive(:reschedulable?) { true }
+ end
+
+ it 'sets the key in Redis' do
+ duplicate_job.set_deduplicated_flag!
+
+ flag = Sidekiq.redis { |redis| redis.get(deduplicated_flag_key) }
+
+ expect(flag).to eq(described_class::DEDUPLICATED_FLAG_VALUE.to_s)
+ end
+
+ it 'sets, gets and cleans up the deduplicated flag' do
+ expect(duplicate_job.should_reschedule?).to eq(false)
+
+ duplicate_job.set_deduplicated_flag!
+ expect(duplicate_job.should_reschedule?).to eq(true)
+
+ duplicate_job.delete!
+ expect(duplicate_job.should_reschedule?).to eq(false)
+ end
+ end
+
+ context 'when the job is not reschedulable' do
+ before do
+ allow(duplicate_job).to receive(:reschedulable?) { false }
+ end
+
+ it 'does not set the key in Redis' do
+ duplicate_job.set_deduplicated_flag!
+
+ flag = Sidekiq.redis { |redis| redis.get(deduplicated_flag_key) }
+
+ expect(flag).to be_nil
+ end
+
+ it 'does not set the deduplicated flag' do
+ expect(duplicate_job.should_reschedule?).to eq(false)
+
+ duplicate_job.set_deduplicated_flag!
+ expect(duplicate_job.should_reschedule?).to eq(false)
+
+ duplicate_job.delete!
+ expect(duplicate_job.should_reschedule?).to eq(false)
+ end
+ end
+ end
+
describe '#duplicate?' do
it "raises an error if the check wasn't performed" do
expect { duplicate_job.duplicate? }.to raise_error /Call `#check!` first/
@@ -494,12 +679,12 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
end
end
- def existing_wal_location_key(idempotency_key, config_name)
- "#{idempotency_key}:#{config_name}:existing_wal_location"
+ def existing_wal_location_key(idempotency_key, connection_name)
+ "#{idempotency_key}:#{connection_name}:existing_wal_location"
end
- def wal_location_key(idempotency_key, config_name)
- "#{idempotency_key}:#{config_name}:wal_location"
+ def wal_location_key(idempotency_key, connection_name)
+ "#{idempotency_key}:#{connection_name}:wal_location"
end
def set_idempotency_key(key, value = '1')
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed_spec.rb
index 9772255fc50..963301bc001 100644
--- a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executed_spec.rb
@@ -9,6 +9,9 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::UntilExecut
before do
allow(fake_duplicate_job).to receive(:latest_wal_locations).and_return( {} )
+ allow(fake_duplicate_job).to receive(:scheduled?) { false }
+ allow(fake_duplicate_job).to receive(:options) { {} }
+ allow(fake_duplicate_job).to receive(:should_reschedule?) { false }
end
it 'deletes the lock after executing' do
@@ -19,6 +22,28 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::UntilExecut
proc.call
end
end
+
+ it 'does not reschedule the job even if deduplication happened' do
+ expect(fake_duplicate_job).to receive(:delete!)
+ expect(fake_duplicate_job).not_to receive(:reschedule)
+
+ strategy.perform({}) do
+ proc.call
+ end
+ end
+
+ context 'when job is reschedulable' do
+ it 'reschedules the job if deduplication happened' do
+ allow(fake_duplicate_job).to receive(:should_reschedule?) { true }
+
+ expect(fake_duplicate_job).to receive(:delete!)
+ expect(fake_duplicate_job).to receive(:reschedule).once
+
+ strategy.perform({}) do
+ proc.call
+ end
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/query_analyzer_spec.rb b/spec/lib/gitlab/sidekiq_middleware/query_analyzer_spec.rb
new file mode 100644
index 00000000000..e58af1d60fe
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_middleware/query_analyzer_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::SidekiqMiddleware::QueryAnalyzer, query_analyzers: false do
+ describe 'the PreventCrossDatabaseModification' do
+ describe '#call' do
+ let(:worker) { double(:worker) }
+ let(:job) { { 'jid' => 'job123' } }
+ let(:queue) { 'some-queue' }
+ let(:middleware) { described_class.new }
+
+ def do_queries
+ end
+
+ subject { middleware.call(worker, job, queue) { do_queries } }
+
+ context 'when there is a cross modification' do
+ def do_queries
+ Project.transaction do
+ Project.where(id: -1).update_all(id: -1)
+ ::Ci::Pipeline.where(id: -1).update_all(id: -1)
+ end
+ end
+
+ it 'detects cross modifications and tracks exception' do
+ expect(::Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
+
+ subject
+ end
+
+ context 'when the detect_cross_database_modification is disabled' do
+ before do
+ stub_feature_flags(detect_cross_database_modification: false)
+ end
+
+ it 'does not detect cross modifications' do
+ expect(::Gitlab::ErrorTracking).not_to receive(:track_and_raise_for_dev_exception)
+
+ subject
+ end
+ end
+ end
+
+ context 'when there is no cross modification' do
+ def do_queries
+ Project.transaction do
+ Project.where(id: -1).update_all(id: -1)
+ Namespace.where(id: -1).update_all(id: -1)
+ end
+ end
+
+ it 'does not log anything' do
+ expect(::Gitlab::ErrorTracking).not_to receive(:track_and_raise_for_dev_exception)
+
+ subject
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb b/spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb
index 3a6fdd7642c..876069a1a92 100644
--- a/spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb
@@ -59,111 +59,6 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator, :aggregate_fai
expect(validator.size_limit).to eq(2)
end
end
-
- context 'when the input mode is valid' do
- it 'does not log a warning message' do
- expect(::Sidekiq.logger).not_to receive(:warn)
-
- described_class.new(TestSizeLimiterWorker, job_payload, mode: 'track')
- described_class.new(TestSizeLimiterWorker, job_payload, mode: 'compress')
- end
- end
-
- context 'when the input mode is invalid' do
- it 'defaults to track mode and logs a warning message' do
- expect(::Sidekiq.logger).to receive(:warn).with('Invalid Sidekiq size limiter mode: invalid. Fallback to track mode.')
-
- validator = described_class.new(TestSizeLimiterWorker, job_payload, mode: 'invalid')
-
- expect(validator.mode).to eql('track')
- end
- end
-
- context 'when the input mode is empty' do
- it 'defaults to track mode' do
- expect(::Sidekiq.logger).not_to receive(:warn)
-
- validator = described_class.new(TestSizeLimiterWorker, job_payload, mode: nil)
-
- expect(validator.mode).to eql('track')
- end
- end
-
- context 'when the size input is valid' do
- it 'does not log a warning message' do
- expect(::Sidekiq.logger).not_to receive(:warn)
-
- described_class.new(TestSizeLimiterWorker, job_payload, size_limit: 300)
- described_class.new(TestSizeLimiterWorker, job_payload, size_limit: 0)
- end
- end
-
- context 'when the size input is invalid' do
- it 'logs a warning message' do
- expect(::Sidekiq.logger).to receive(:warn).with('Invalid Sidekiq size limiter limit: -1')
-
- validator = described_class.new(TestSizeLimiterWorker, job_payload, size_limit: -1)
-
- expect(validator.size_limit).to be(0)
- end
- end
-
- context 'when the size input is empty' do
- it 'defaults to 0' do
- expect(::Sidekiq.logger).not_to receive(:warn)
-
- validator = described_class.new(TestSizeLimiterWorker, job_payload, size_limit: nil)
-
- expect(validator.size_limit).to be(described_class::DEFAULT_SIZE_LIMIT)
- end
- end
-
- context 'when the compression threshold is valid' do
- it 'does not log a warning message' do
- expect(::Sidekiq.logger).not_to receive(:warn)
-
- described_class.new(TestSizeLimiterWorker, job_payload, compression_threshold: 300)
- described_class.new(TestSizeLimiterWorker, job_payload, compression_threshold: 1)
- end
- end
-
- context 'when the compression threshold is negative' do
- it 'logs a warning message' do
- expect(::Sidekiq.logger).to receive(:warn).with('Invalid Sidekiq size limiter compression threshold: -1')
-
- described_class.new(TestSizeLimiterWorker, job_payload, compression_threshold: -1)
- end
-
- it 'falls back to the default' do
- validator = described_class.new(TestSizeLimiterWorker, job_payload, compression_threshold: -1)
-
- expect(validator.compression_threshold).to be(100_000)
- end
- end
-
- context 'when the compression threshold is zero' do
- it 'logs a warning message' do
- expect(::Sidekiq.logger).to receive(:warn).with('Invalid Sidekiq size limiter compression threshold: 0')
-
- described_class.new(TestSizeLimiterWorker, job_payload, compression_threshold: 0)
- end
-
- it 'falls back to the default' do
- validator = described_class.new(TestSizeLimiterWorker, job_payload, compression_threshold: 0)
-
- expect(validator.compression_threshold).to be(100_000)
- end
- end
-
- context 'when the compression threshold is empty' do
- it 'defaults to 100_000' do
- expect(::Sidekiq.logger).not_to receive(:warn)
-
- validator = described_class.new(TestSizeLimiterWorker, job_payload)
-
- expect(validator.compression_threshold).to be(100_000)
- end
- end
end
shared_examples 'validate limit job payload size' do
@@ -171,20 +66,6 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator, :aggregate_fai
let(:compression_threshold) { nil }
let(:mode) { 'track' }
- context 'when size limit negative' do
- let(:size_limit) { -1 }
-
- it 'does not track jobs' do
- expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
-
- validate.call(TestSizeLimiterWorker, job_payload(a: 'a' * 300))
- end
-
- it 'does not raise exception' do
- expect { validate.call(TestSizeLimiterWorker, job_payload(a: 'a' * 300)) }.not_to raise_error
- end
- end
-
context 'when size limit is 0' do
let(:size_limit) { 0 }
let(:job) { job_payload(a: 'a' * 300) }
@@ -438,36 +319,20 @@ RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator, :aggregate_fai
end
describe '#validate!' do
- context 'when creating an instance with the related configuration variables' do
- let(:validate) do
- ->(worker_clas, job) do
- described_class.new(worker_class, job).validate!
- end
+ let(:validate) do
+ ->(worker_class, job) do
+ described_class.new(worker_class, job).validate!
end
-
- before do
- stub_application_setting(
- sidekiq_job_limiter_mode: mode,
- sidekiq_job_limiter_compression_threshold_bytes: compression_threshold,
- sidekiq_job_limiter_limit_bytes: size_limit
- )
- end
-
- it_behaves_like 'validate limit job payload size'
end
- context 'when creating an instance with mode and size limit' do
- let(:validate) do
- ->(worker_clas, job) do
- validator = described_class.new(
- worker_class, job,
- mode: mode, size_limit: size_limit, compression_threshold: compression_threshold
- )
- validator.validate!
- end
- end
-
- it_behaves_like 'validate limit job payload size'
+ before do
+ stub_application_setting(
+ sidekiq_job_limiter_mode: mode,
+ sidekiq_job_limiter_compression_threshold_bytes: compression_threshold,
+ sidekiq_job_limiter_limit_bytes: size_limit
+ )
end
+
+ it_behaves_like 'validate limit job payload size'
end
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/worker_context/client_spec.rb b/spec/lib/gitlab/sidekiq_middleware/worker_context/client_spec.rb
index 92a11c83a4a..b9a13fd697e 100644
--- a/spec/lib/gitlab/sidekiq_middleware/worker_context/client_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/worker_context/client_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::WorkerContext::Client do
include ApplicationWorker
- feature_category :issue_tracking
+ feature_category :team_planning
def self.job_for_args(args)
jobs.find { |job| job['args'] == args }
@@ -78,8 +78,8 @@ RSpec.describe Gitlab::SidekiqMiddleware::WorkerContext::Client do
job1 = TestWithContextWorker.job_for_args(['job1', 1, 2, 3])
job2 = TestWithContextWorker.job_for_args(['job2', 1, 2, 3])
- expect(job1['meta.feature_category']).to eq('issue_tracking')
- expect(job2['meta.feature_category']).to eq('issue_tracking')
+ expect(job1['meta.feature_category']).to eq('team_planning')
+ expect(job2['meta.feature_category']).to eq('team_planning')
end
it 'takes the feature category from the caller if the worker is not owned' do
@@ -116,8 +116,8 @@ RSpec.describe Gitlab::SidekiqMiddleware::WorkerContext::Client do
job1 = TestWithContextWorker.job_for_args(['job1', 1, 2, 3])
job2 = TestWithContextWorker.job_for_args(['job2', 1, 2, 3])
- expect(job1['meta.feature_category']).to eq('issue_tracking')
- expect(job2['meta.feature_category']).to eq('issue_tracking')
+ expect(job1['meta.feature_category']).to eq('team_planning')
+ expect(job2['meta.feature_category']).to eq('team_planning')
end
it 'takes the feature category from the caller if the worker is not owned' do
diff --git a/spec/lib/gitlab/spamcheck/client_spec.rb b/spec/lib/gitlab/spamcheck/client_spec.rb
index 15e963fe423..e542ce455bb 100644
--- a/spec/lib/gitlab/spamcheck/client_spec.rb
+++ b/spec/lib/gitlab/spamcheck/client_spec.rb
@@ -82,7 +82,7 @@ RSpec.describe Gitlab::Spamcheck::Client do
end
end
- describe '#build_user_proto_buf', :aggregate_failures do
+ describe '#build_user_protobuf', :aggregate_failures do
it 'builds the expected protobuf object' do
user_pb = described_class.new.send(:build_user_protobuf, user)
expect(user_pb.username).to eq user.username
diff --git a/spec/lib/gitlab/subscription_portal_spec.rb b/spec/lib/gitlab/subscription_portal_spec.rb
index a3808b0f0e2..4be1c85f7c8 100644
--- a/spec/lib/gitlab/subscription_portal_spec.rb
+++ b/spec/lib/gitlab/subscription_portal_spec.rb
@@ -9,14 +9,13 @@ RSpec.describe ::Gitlab::SubscriptionPortal do
before do
stub_env('CUSTOMER_PORTAL_URL', env_value)
- stub_feature_flags(new_customersdot_staging_url: false)
end
describe '.default_subscriptions_url' do
where(:test, :development, :result) do
false | false | 'https://customers.gitlab.com'
- false | true | 'https://customers.stg.gitlab.com'
- true | false | 'https://customers.stg.gitlab.com'
+ false | true | 'https://customers.staging.gitlab.com'
+ true | false | 'https://customers.staging.gitlab.com'
end
before do
@@ -35,7 +34,7 @@ RSpec.describe ::Gitlab::SubscriptionPortal do
subject { described_class.subscriptions_url }
context 'when CUSTOMER_PORTAL_URL ENV is unset' do
- it { is_expected.to eq('https://customers.stg.gitlab.com') }
+ it { is_expected.to eq('https://customers.staging.gitlab.com') }
end
context 'when CUSTOMER_PORTAL_URL ENV is set' do
@@ -55,15 +54,15 @@ RSpec.describe ::Gitlab::SubscriptionPortal do
context 'url methods' do
where(:method_name, :result) do
- :default_subscriptions_url | 'https://customers.stg.gitlab.com'
- :payment_form_url | 'https://customers.stg.gitlab.com/payment_forms/cc_validation'
- :subscriptions_graphql_url | 'https://customers.stg.gitlab.com/graphql'
- :subscriptions_more_minutes_url | 'https://customers.stg.gitlab.com/buy_pipeline_minutes'
- :subscriptions_more_storage_url | 'https://customers.stg.gitlab.com/buy_storage'
- :subscriptions_manage_url | 'https://customers.stg.gitlab.com/subscriptions'
- :subscriptions_plans_url | 'https://customers.stg.gitlab.com/plans'
- :subscriptions_instance_review_url | 'https://customers.stg.gitlab.com/instance_review'
- :subscriptions_gitlab_plans_url | 'https://customers.stg.gitlab.com/gitlab_plans'
+ :default_subscriptions_url | 'https://customers.staging.gitlab.com'
+ :payment_form_url | 'https://customers.staging.gitlab.com/payment_forms/cc_validation'
+ :subscriptions_graphql_url | 'https://customers.staging.gitlab.com/graphql'
+ :subscriptions_more_minutes_url | 'https://customers.staging.gitlab.com/buy_pipeline_minutes'
+ :subscriptions_more_storage_url | 'https://customers.staging.gitlab.com/buy_storage'
+ :subscriptions_manage_url | 'https://customers.staging.gitlab.com/subscriptions'
+ :subscriptions_plans_url | 'https://about.gitlab.com/pricing/'
+ :subscriptions_instance_review_url | 'https://customers.staging.gitlab.com/instance_review'
+ :subscriptions_gitlab_plans_url | 'https://customers.staging.gitlab.com/gitlab_plans'
end
with_them do
@@ -78,7 +77,7 @@ RSpec.describe ::Gitlab::SubscriptionPortal do
let(:group_id) { 153 }
- it { is_expected.to eq("https://customers.stg.gitlab.com/gitlab/namespaces/#{group_id}/extra_seats") }
+ it { is_expected.to eq("https://customers.staging.gitlab.com/gitlab/namespaces/#{group_id}/extra_seats") }
end
describe '.upgrade_subscription_url' do
@@ -87,7 +86,7 @@ RSpec.describe ::Gitlab::SubscriptionPortal do
let(:group_id) { 153 }
let(:plan_id) { 5 }
- it { is_expected.to eq("https://customers.stg.gitlab.com/gitlab/namespaces/#{group_id}/upgrade/#{plan_id}") }
+ it { is_expected.to eq("https://customers.staging.gitlab.com/gitlab/namespaces/#{group_id}/upgrade/#{plan_id}") }
end
describe '.renew_subscription_url' do
@@ -95,6 +94,6 @@ RSpec.describe ::Gitlab::SubscriptionPortal do
let(:group_id) { 153 }
- it { is_expected.to eq("https://customers.stg.gitlab.com/gitlab/namespaces/#{group_id}/renew") }
+ it { is_expected.to eq("https://customers.staging.gitlab.com/gitlab/namespaces/#{group_id}/renew") }
end
end
diff --git a/spec/lib/gitlab/tracking/destinations/product_analytics_spec.rb b/spec/lib/gitlab/tracking/destinations/product_analytics_spec.rb
deleted file mode 100644
index 63e2e930acd..00000000000
--- a/spec/lib/gitlab/tracking/destinations/product_analytics_spec.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Tracking::Destinations::ProductAnalytics do
- let(:emitter) { SnowplowTracker::Emitter.new('localhost', buffer_size: 1) }
- let(:tracker) { SnowplowTracker::Tracker.new(emitter, SnowplowTracker::Subject.new, 'namespace', 'app_id') }
-
- describe '#event' do
- shared_examples 'does not send an event' do
- it 'does not send an event' do
- expect_any_instance_of(SnowplowTracker::Tracker).not_to receive(:track_struct_event)
-
- subject.event(allowed_category, allowed_action)
- end
- end
-
- let(:allowed_category) { 'epics' }
- let(:allowed_action) { 'promote' }
- let(:self_monitoring_project) { create(:project) }
-
- before do
- stub_feature_flags(product_analytics_tracking: true)
- stub_application_setting(self_monitoring_project_id: self_monitoring_project.id)
- stub_application_setting(usage_ping_enabled: true)
- end
-
- context 'with allowed event' do
- it 'sends an event to Product Analytics snowplow collector' do
- expect(SnowplowTracker::AsyncEmitter)
- .to receive(:new)
- .with(ProductAnalytics::Tracker::COLLECTOR_URL, protocol: Gitlab.config.gitlab.protocol)
- .and_return(emitter)
-
- expect(SnowplowTracker::Tracker)
- .to receive(:new)
- .with(emitter, an_instance_of(SnowplowTracker::Subject), Gitlab::Tracking::SNOWPLOW_NAMESPACE, self_monitoring_project.id.to_s)
- .and_return(tracker)
-
- freeze_time do
- expect(tracker)
- .to receive(:track_struct_event)
- .with(allowed_category, allowed_action, 'label', 'property', 1.5, nil, (Time.now.to_f * 1000).to_i)
-
- subject.event(allowed_category, allowed_action, label: 'label', property: 'property', value: 1.5)
- end
- end
- end
-
- context 'with non-allowed event' do
- it 'does not send an event' do
- expect_any_instance_of(SnowplowTracker::Tracker).not_to receive(:track_struct_event)
-
- subject.event('category', 'action')
- subject.event(allowed_category, 'action')
- subject.event('category', allowed_action)
- end
- end
-
- context 'when self-monitoring project does not exist' do
- before do
- stub_application_setting(self_monitoring_project_id: nil)
- end
-
- include_examples 'does not send an event'
- end
-
- context 'when product_analytics_tracking FF is disabled' do
- before do
- stub_feature_flags(product_analytics_tracking: false)
- end
-
- include_examples 'does not send an event'
- end
-
- context 'when usage ping is disabled' do
- before do
- stub_application_setting(usage_ping_enabled: false)
- end
-
- include_examples 'does not send an event'
- end
- end
-end
diff --git a/spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb b/spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb
new file mode 100644
index 00000000000..6004698d092
--- /dev/null
+++ b/spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Tracking::Destinations::SnowplowMicro do
+ include StubENV
+
+ before do
+ stub_application_setting(snowplow_enabled: true)
+ stub_env('SNOWPLOW_MICRO_ENABLE', '1')
+ allow(Rails.env).to receive(:development?).and_return(true)
+ end
+
+ describe '#hostname' do
+ context 'when SNOWPLOW_MICRO_URI is set' do
+ before do
+ stub_env('SNOWPLOW_MICRO_URI', 'http://gdk.test:9091')
+ end
+
+ it 'returns hostname URI part' do
+ expect(subject.hostname).to eq('gdk.test:9091')
+ end
+ end
+
+ context 'when SNOWPLOW_MICRO_URI is without protocol' do
+ before do
+ stub_env('SNOWPLOW_MICRO_URI', 'gdk.test:9091')
+ end
+
+ it 'returns hostname URI part' do
+ expect(subject.hostname).to eq('gdk.test:9091')
+ end
+ end
+
+ context 'when SNOWPLOW_MICRO_URI is hostname only' do
+ before do
+ stub_env('SNOWPLOW_MICRO_URI', 'uriwithoutport')
+ end
+
+ it 'returns hostname URI with default HTTP port' do
+ expect(subject.hostname).to eq('uriwithoutport:80')
+ end
+ end
+
+ context 'when SNOWPLOW_MICRO_URI is not set' do
+ it 'returns localhost hostname' do
+ expect(subject.hostname).to eq('localhost:9090')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tracking/standard_context_spec.rb b/spec/lib/gitlab/tracking/standard_context_spec.rb
index 8ded80dd191..7d678db5ec8 100644
--- a/spec/lib/gitlab/tracking/standard_context_spec.rb
+++ b/spec/lib/gitlab/tracking/standard_context_spec.rb
@@ -99,25 +99,5 @@ RSpec.describe Gitlab::Tracking::StandardContext do
it 'accepts just project id as integer' do
expect { described_class.new(project: 1).to_context }.not_to raise_error
end
-
- context 'without add_namespace_and_project_to_snowplow_tracking feature' do
- before do
- stub_feature_flags(add_namespace_and_project_to_snowplow_tracking: false)
- end
-
- it 'does not contain project or namespace ids' do
- expect(snowplow_context.to_json[:data].keys).not_to include(:project_id, :namespace_id)
- end
- end
-
- context 'without add_actor_based_user_to_snowplow_tracking feature' do
- before do
- stub_feature_flags(add_actor_based_user_to_snowplow_tracking: false)
- end
-
- it 'does not contain user_id' do
- expect(snowplow_context.to_json[:data].keys).not_to include(:user_id)
- end
- end
end
end
diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb
index dacaae55676..61b2c89ffa1 100644
--- a/spec/lib/gitlab/tracking_spec.rb
+++ b/spec/lib/gitlab/tracking_spec.rb
@@ -2,6 +2,8 @@
require 'spec_helper'
RSpec.describe Gitlab::Tracking do
+ include StubENV
+
before do
stub_application_setting(snowplow_enabled: true)
stub_application_setting(snowplow_collector_hostname: 'gitfoo.com')
@@ -12,17 +14,62 @@ RSpec.describe Gitlab::Tracking do
end
describe '.options' do
- it 'returns useful client options' do
- expected_fields = {
- namespace: 'gl',
- hostname: 'gitfoo.com',
- cookieDomain: '.gitfoo.com',
- appId: '_abc123_',
- formTracking: true,
- linkClickTracking: true
- }
-
- expect(subject.options(nil)).to match(expected_fields)
+ shared_examples 'delegates to destination' do |klass|
+ before do
+ allow_next_instance_of(klass) do |instance|
+ allow(instance).to receive(:options).and_call_original
+ end
+ end
+
+ it "delegates to #{klass} destination" do
+ expect_next_instance_of(klass) do |instance|
+ expect(instance).to receive(:options)
+ end
+
+ subject.options(nil)
+ end
+ end
+
+ context 'when destination is Snowplow' do
+ it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::Snowplow
+
+ it 'returns useful client options' do
+ expected_fields = {
+ namespace: 'gl',
+ hostname: 'gitfoo.com',
+ cookieDomain: '.gitfoo.com',
+ appId: '_abc123_',
+ formTracking: true,
+ linkClickTracking: true
+ }
+
+ expect(subject.options(nil)).to match(expected_fields)
+ end
+ end
+
+ context 'when destination is SnowplowMicro' do
+ before do
+ stub_env('SNOWPLOW_MICRO_ENABLE', '1')
+ allow(Rails.env).to receive(:development?).and_return(true)
+ end
+
+ it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::SnowplowMicro
+
+ it 'returns useful client options' do
+ expected_fields = {
+ namespace: 'gl',
+ hostname: 'localhost:9090',
+ cookieDomain: '.gitlab.com',
+ appId: '_abc123_',
+ protocol: 'http',
+ port: 9090,
+ force_secure_tracker: false,
+ formTracking: true,
+ linkClickTracking: true
+ }
+
+ expect(subject.options(nil)).to match(expected_fields)
+ end
end
it 'when feature flag is disabled' do
@@ -41,7 +88,6 @@ RSpec.describe Gitlab::Tracking do
shared_examples 'delegates to destination' do |klass|
before do
allow_any_instance_of(Gitlab::Tracking::Destinations::Snowplow).to receive(:event)
- allow_any_instance_of(Gitlab::Tracking::Destinations::ProductAnalytics).to receive(:event)
end
it "delegates to #{klass} destination" do
@@ -72,8 +118,23 @@ RSpec.describe Gitlab::Tracking do
end
end
- it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::Snowplow
- it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::ProductAnalytics
+ context 'when destination is Snowplow' do
+ before do
+ stub_env('SNOWPLOW_MICRO_ENABLE', '0')
+ allow(Rails.env).to receive(:development?).and_return(true)
+ end
+
+ it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::Snowplow
+ end
+
+ context 'when destination is SnowplowMicro' do
+ before do
+ stub_env('SNOWPLOW_MICRO_ENABLE', '1')
+ allow(Rails.env).to receive(:development?).and_return(true)
+ end
+
+ it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::SnowplowMicro
+ end
it 'tracks errors' do
expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(
diff --git a/spec/lib/gitlab/usage/metric_definition_spec.rb b/spec/lib/gitlab/usage/metric_definition_spec.rb
index 522f69062fb..a22b3a733bd 100644
--- a/spec/lib/gitlab/usage/metric_definition_spec.rb
+++ b/spec/lib/gitlab/usage/metric_definition_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
value_type: 'string',
product_category: 'collection',
product_stage: 'growth',
+ product_section: 'devops',
status: 'active',
milestone: '14.1',
default_generation: 'generation_1',
@@ -222,6 +223,7 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
value_type: 'string',
product_category: 'collection',
product_stage: 'growth',
+ product_section: 'devops',
status: 'active',
milestone: '14.1',
default_generation: 'generation_1',
diff --git a/spec/lib/gitlab/usage/metric_spec.rb b/spec/lib/gitlab/usage/metric_spec.rb
index ea8d1a135a6..19d2d3048eb 100644
--- a/spec/lib/gitlab/usage/metric_spec.rb
+++ b/spec/lib/gitlab/usage/metric_spec.rb
@@ -45,4 +45,10 @@ RSpec.describe Gitlab::Usage::Metric do
expect(described_class.new(issue_count_metric_definiton).with_instrumentation).to eq({ counts: { issues: "SELECT COUNT(\"issues\".\"id\") FROM \"issues\"" } })
end
end
+
+ describe '#with_suggested_name' do
+ it 'returns key_path metric with the corresponding generated query' do
+ expect(described_class.new(issue_count_metric_definiton).with_suggested_name).to eq({ counts: { issues: 'count_issues' } })
+ end
+ end
end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/generic_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/generic_metric_spec.rb
index 158be34d39c..c8cb1bb4373 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/generic_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/generic_metric_spec.rb
@@ -7,18 +7,18 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::GenericMetric do
subject do
Class.new(described_class) do
fallback(custom_fallback)
- value { Gitlab::Database.main.version }
+ value { ApplicationRecord.database.version }
end.new(time_frame: 'none')
end
describe '#value' do
it 'gives the correct value' do
- expect(subject.value).to eq(Gitlab::Database.main.version)
+ expect(subject.value).to eq(ApplicationRecord.database.version)
end
context 'when raising an exception' do
it 'return the custom fallback' do
- expect(Gitlab::Database.main).to receive(:version).and_raise('Error')
+ expect(ApplicationRecord.database).to receive(:version).and_raise('Error')
expect(subject.value).to eq(custom_fallback)
end
end
@@ -28,18 +28,18 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::GenericMetric do
context 'with default fallback' do
subject do
Class.new(described_class) do
- value { Gitlab::Database.main.version }
+ value { ApplicationRecord.database.version }
end.new(time_frame: 'none')
end
describe '#value' do
it 'gives the correct value' do
- expect(subject.value).to eq(Gitlab::Database.main.version )
+ expect(subject.value).to eq(ApplicationRecord.database.version )
end
context 'when raising an exception' do
it 'return the default fallback' do
- expect(Gitlab::Database.main).to receive(:version).and_raise('Error')
+ expect(ApplicationRecord.database).to receive(:version).and_raise('Error')
expect(subject.value).to eq(described_class::FALLBACK)
end
end
diff --git a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
index 0f95da74ff9..dbbc718e147 100644
--- a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
@@ -25,10 +25,30 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
end
context 'for count with default column metrics' do
- it_behaves_like 'name suggestion' do
- # corresponding metric is collected with count(Board)
- let(:key_path) { 'counts.boards' }
- let(:name_suggestion) { /count_boards/ }
+ context 'with usage_data_instrumentation feature flag' do
+ context 'when enabled' do
+ before do
+ stub_feature_flags(usage_data_instrumentation: true)
+ end
+
+ it_behaves_like 'name suggestion' do
+ # corresponding metric is collected with ::Gitlab::UsageDataMetrics.suggested_names
+ let(:key_path) { 'counts.boards' }
+ let(:name_suggestion) { /count_boards/ }
+ end
+ end
+
+ context 'when disabled' do
+ before do
+ stub_feature_flags(usage_data_instrumentation: false)
+ end
+
+ it_behaves_like 'name suggestion' do
+ # corresponding metric is collected with count(Board)
+ let(:key_path) { 'counts.boards' }
+ let(:name_suggestion) { /count_boards/ }
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/usage_data_counters/vs_code_extenion_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/vscode_extenion_activity_unique_counter_spec.rb
index 7593d51fe76..7593d51fe76 100644
--- a/spec/lib/gitlab/usage_data_counters/vs_code_extenion_activity_unique_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/vscode_extenion_activity_unique_counter_spec.rb
diff --git a/spec/lib/gitlab/usage_data_metrics_spec.rb b/spec/lib/gitlab/usage_data_metrics_spec.rb
index ee0cfb1407e..563eed75c38 100644
--- a/spec/lib/gitlab/usage_data_metrics_spec.rb
+++ b/spec/lib/gitlab/usage_data_metrics_spec.rb
@@ -13,7 +13,9 @@ RSpec.describe Gitlab::UsageDataMetrics do
end
before do
- allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
+ allow_next_instance_of(Gitlab::Database::BatchCounter) do |batch_counter|
+ allow(batch_counter).to receive(:transaction_open?).and_return(false)
+ end
end
context 'with instrumentation_class' do
@@ -76,4 +78,16 @@ RSpec.describe Gitlab::UsageDataMetrics do
end
end
end
+
+ describe '.suggested_names' do
+ subject { described_class.suggested_names }
+
+ let(:suggested_names) do
+ ::Gitlab::Usage::Metric.all.map(&:with_suggested_name).reduce({}, :deep_merge)
+ end
+
+ it 'includes Service Ping suggested names' do
+ expect(subject).to match_array(suggested_names)
+ end
+ end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 833bf260019..cf544c07195 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -80,6 +80,12 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
end
+
+ it 'allows indifferent access' do
+ allow(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:unique_events).and_return(1)
+ expect(subject[:search_unique_visits][:search_unique_visits_for_any_target_monthly]).to eq(1)
+ expect(subject[:search_unique_visits]['search_unique_visits_for_any_target_monthly']).to eq(1)
+ end
end
describe 'usage_activity_by_stage_package' do
@@ -187,6 +193,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
describe 'usage_activity_by_stage_manage' do
+ let_it_be(:error_rate) { Gitlab::Database::PostgresHll::BatchDistinctCounter::ERROR_RATE }
+
it 'includes accurate usage_activity_by_stage data' do
stub_config(
omniauth:
@@ -207,14 +215,14 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
expect(described_class.usage_activity_by_stage_manage({})).to include(
- events: 2,
+ events: -1,
groups: 2,
users_created: 6,
omniauth_providers: ['google_oauth2'],
user_auth_by_provider: { 'group_saml' => 2, 'ldap' => 4, 'standard' => 0, 'two-factor' => 0, 'two-factor-via-u2f-device' => 0, "two-factor-via-webauthn-device" => 0 }
)
expect(described_class.usage_activity_by_stage_manage(described_class.monthly_time_range_db_params)).to include(
- events: 1,
+ events: be_within(error_rate).percent_of(1),
groups: 1,
users_created: 3,
omniauth_providers: ['google_oauth2'],
@@ -367,9 +375,9 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
def omniauth_providers
[
- OpenStruct.new(name: 'google_oauth2'),
- OpenStruct.new(name: 'ldapmain'),
- OpenStruct.new(name: 'group_saml')
+ double('provider', name: 'google_oauth2'),
+ double('provider', name: 'ldapmain'),
+ double('provider', name: 'group_saml')
]
end
end
@@ -428,7 +436,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
expect(described_class.usage_activity_by_stage_plan({})).to include(
- issues: 3,
notes: 2,
projects: 2,
todos: 2,
@@ -439,7 +446,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
projects_jira_dvcs_server_active: 2
)
expect(described_class.usage_activity_by_stage_plan(described_class.monthly_time_range_db_params)).to include(
- issues: 2,
notes: 1,
projects: 1,
todos: 1,
@@ -450,6 +456,44 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
projects_jira_dvcs_server_active: 1
)
end
+
+ context 'with usage_data_instrumentation feature flag' do
+ context 'when enabled' do
+ it 'merges the data from instrumentation classes' do
+ stub_feature_flags(usage_data_instrumentation: true)
+
+ for_defined_days_back do
+ user = create(:user)
+ project = create(:project, creator: user)
+ create(:issue, project: project, author: user)
+ create(:issue, project: project, author: User.support_bot)
+ end
+
+ expect(described_class.usage_activity_by_stage_plan({})).to include(issues: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
+ expect(described_class.usage_activity_by_stage_plan(described_class.monthly_time_range_db_params)).to include(issues: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
+
+ uncached_data = described_class.uncached_data
+ expect(uncached_data[:usage_activity_by_stage][:plan]).to include(issues: 3)
+ expect(uncached_data[:usage_activity_by_stage_monthly][:plan]).to include(issues: 2)
+ end
+ end
+
+ context 'when disabled' do
+ it 'does not merge the data from instrumentation classes' do
+ stub_feature_flags(usage_data_instrumentation: false)
+
+ for_defined_days_back do
+ user = create(:user)
+ project = create(:project, creator: user)
+ create(:issue, project: project, author: user)
+ create(:issue, project: project, author: User.support_bot)
+ end
+
+ expect(described_class.usage_activity_by_stage_plan({})).to include(issues: 3)
+ expect(described_class.usage_activity_by_stage_plan(described_class.monthly_time_range_db_params)).to include(issues: 2)
+ end
+ end
+ end
end
describe 'usage_activity_by_stage_release' do
@@ -466,17 +510,53 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
deployments: 2,
failed_deployments: 2,
releases: 2,
- successful_deployments: 2,
- releases_with_milestones: 2
+ successful_deployments: 2
)
expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(
deployments: 1,
failed_deployments: 1,
releases: 1,
- successful_deployments: 1,
- releases_with_milestones: 1
+ successful_deployments: 1
)
end
+
+ context 'with usage_data_instrumentation feature flag' do
+ before do
+ for_defined_days_back do
+ user = create(:user)
+ create(:deployment, :failed, user: user)
+ release = create(:release, author: user)
+ create(:milestone, project: release.project, releases: [release])
+ create(:deployment, :success, user: user)
+ end
+ end
+
+ context 'when enabled' do
+ before do
+ stub_feature_flags(usage_data_instrumentation: true)
+ end
+
+ it 'merges data from instrumentation classes' do
+ expect(described_class.usage_activity_by_stage_release({})).to include(releases_with_milestones: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
+ expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(releases_with_milestones: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
+
+ uncached_data = described_class.uncached_data
+ expect(uncached_data[:usage_activity_by_stage][:release]).to include(releases_with_milestones: 2)
+ expect(uncached_data[:usage_activity_by_stage_monthly][:release]).to include(releases_with_milestones: 1)
+ end
+ end
+
+ context 'when disabled' do
+ before do
+ stub_feature_flags(usage_data_instrumentation: false)
+ end
+
+ it 'does not merge data from instrumentation classes' do
+ expect(described_class.usage_activity_by_stage_release({})).to include(releases_with_milestones: 2)
+ expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(releases_with_milestones: 1)
+ end
+ end
+ end
end
describe 'usage_activity_by_stage_verify' do
@@ -525,16 +605,16 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
subject { described_class.data }
it 'gathers usage data' do
- expect(subject.keys).to include(*UsageDataHelpers::USAGE_DATA_KEYS)
+ expect(subject.keys).to include(*UsageDataHelpers::USAGE_DATA_KEYS.map(&:to_s))
end
it 'gathers usage counts', :aggregate_failures do
count_data = subject[:counts]
-
expect(count_data[:boards]).to eq(1)
expect(count_data[:projects]).to eq(4)
- expect(count_data.keys).to include(*UsageDataHelpers::COUNTS_KEYS)
- expect(UsageDataHelpers::COUNTS_KEYS - count_data.keys).to be_empty
+ count_keys = UsageDataHelpers::COUNTS_KEYS.map(&:to_s)
+ expect(count_data.keys).to include(*count_keys)
+ expect(count_keys - count_data.keys).to be_empty
expect(count_data.values).to all(be_a_kind_of(Integer))
end
@@ -619,7 +699,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
external_diffs: { enabled: false },
lfs: { enabled: true, object_store: { enabled: false, direct_upload: true, background_upload: false, provider: "AWS" } },
uploads: { enabled: nil, object_store: { enabled: false, direct_upload: true, background_upload: false, provider: "AWS" } },
- packages: { enabled: true, object_store: { enabled: false, direct_upload: false, background_upload: true, provider: "AWS" } } }
+ packages: { enabled: true, object_store: { enabled: false, direct_upload: false, background_upload: true, provider: "AWS" } } }.with_indifferent_access
)
end
@@ -793,12 +873,37 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
subject { described_class.license_usage_data }
it 'gathers license data' do
- expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
expect(subject[:version]).to eq(Gitlab::VERSION)
expect(subject[:installation_type]).to eq('gitlab-development-kit')
- expect(subject[:active_user_count]).to eq(User.active.size)
expect(subject[:recorded_at]).to be_a(Time)
end
+
+ context 'with usage_data_instrumentation feature flag' do
+ context 'when enabled' do
+ it 'merges uuid and hostname data from instrumentation classes' do
+ stub_feature_flags(usage_data_instrumentation: true)
+
+ expect(subject[:uuid]).to eq(Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
+ expect(subject[:hostname]).to eq(Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
+ expect(subject[:active_user_count]).to eq(Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
+
+ uncached_data = described_class.data
+ expect(uncached_data[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
+ expect(uncached_data[:hostname]).to eq(Gitlab.config.gitlab.host)
+ expect(uncached_data[:active_user_count]).to eq(User.active.size)
+ end
+ end
+
+ context 'when disabled' do
+ it 'does not merge uuid and hostname data from instrumentation classes' do
+ stub_feature_flags(usage_data_instrumentation: false)
+
+ expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
+ expect(subject[:hostname]).to eq(Gitlab.config.gitlab.host)
+ expect(subject[:active_user_count]).to eq(User.active.size)
+ end
+ end
+ end
end
context 'when not relying on database records' do
@@ -873,9 +978,9 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(subject[:gitlab_pages][:enabled]).to eq(Gitlab.config.pages.enabled)
expect(subject[:gitlab_pages][:version]).to eq(Gitlab::Pages::VERSION)
expect(subject[:git][:version]).to eq(Gitlab::Git.version)
- expect(subject[:database][:adapter]).to eq(Gitlab::Database.main.adapter_name)
- expect(subject[:database][:version]).to eq(Gitlab::Database.main.version)
- expect(subject[:database][:pg_system_id]).to eq(Gitlab::Database.main.system_id)
+ expect(subject[:database][:adapter]).to eq(ApplicationRecord.database.adapter_name)
+ expect(subject[:database][:version]).to eq(ApplicationRecord.database.version)
+ expect(subject[:database][:pg_system_id]).to eq(ApplicationRecord.database.system_id)
expect(subject[:mail][:smtp_server]).to eq(ActionMailer::Base.smtp_settings[:address])
expect(subject[:gitaly][:version]).to be_present
expect(subject[:gitaly][:servers]).to be >= 1
@@ -1061,18 +1166,46 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(subject[:settings][:gitaly_apdex]).to be_within(0.001).of(0.95)
end
- it 'reports collected data categories' do
- expected_value = %w[standard subscription operational optional]
+ context 'with usage_data_instrumentation feature flag' do
+ context 'when enabled' do
+ before do
+ stub_feature_flags(usage_data_instrumentation: true)
+ end
+
+ it 'reports collected data categories' do
+ expected_value = %w[standard subscription operational optional]
+
+ allow_next_instance_of(ServicePing::PermitDataCategoriesService) do |instance|
+ expect(instance).to receive(:execute).and_return(expected_value)
+ end
+
+ expect(described_class.data[:settings][:collected_data_categories]).to eq(expected_value)
+ end
- allow_next_instance_of(ServicePing::PermitDataCategoriesService) do |instance|
- expect(instance).to receive(:execute).and_return(expected_value)
+ it 'gathers service_ping_features_enabled' do
+ expect(described_class.data[:settings][:service_ping_features_enabled]).to eq(Gitlab::CurrentSettings.usage_ping_features_enabled)
+ end
end
- expect(subject[:settings][:collected_data_categories]).to eq(expected_value)
- end
+ context 'when disabled' do
+ before do
+ stub_feature_flags(usage_data_instrumentation: false)
+ end
+
+ it 'reports collected data categories' do
+ expected_value = %w[standard subscription operational optional]
- it 'gathers service_ping_features_enabled' do
- expect(subject[:settings][:service_ping_features_enabled]).to eq(Gitlab::CurrentSettings.usage_ping_features_enabled)
+ allow_next_instance_of(ServicePing::PermitDataCategoriesService) do |instance|
+ expect(instance).to receive(:execute).and_return(expected_value)
+ end
+
+ expect(subject[:settings][:collected_data_categories]).to eq(expected_value)
+ end
+
+ it 'gathers service_ping_features_enabled' do
+ expect(subject[:settings][:service_ping_features_enabled]).to eq(Gitlab::CurrentSettings.usage_ping_features_enabled)
+ end
+ end
end
it 'gathers user_cap_feature_enabled' do
diff --git a/spec/lib/gitlab/utils/usage_data_spec.rb b/spec/lib/gitlab/utils/usage_data_spec.rb
index 1d01d5c7e6a..e721b28ac29 100644
--- a/spec/lib/gitlab/utils/usage_data_spec.rb
+++ b/spec/lib/gitlab/utils/usage_data_spec.rb
@@ -8,8 +8,26 @@ RSpec.describe Gitlab::Utils::UsageData do
describe '#add_metric' do
let(:metric) { 'UuidMetric'}
- it 'computes the metric value for given metric' do
- expect(described_class.add_metric(metric)).to eq(Gitlab::CurrentSettings.uuid)
+ context 'with usage_data_instrumentation feature flag' do
+ context 'when enabled' do
+ before do
+ stub_feature_flags(usage_data_instrumentation: true)
+ end
+
+ it 'returns -100 value to be overriden' do
+ expect(described_class.add_metric(metric)).to eq(-100)
+ end
+ end
+
+ context 'when disabled' do
+ before do
+ stub_feature_flags(usage_data_instrumentation: false)
+ end
+
+ it 'computes the metric value for given metric' do
+ expect(described_class.add_metric(metric)).to eq(Gitlab::CurrentSettings.uuid)
+ end
+ end
end
end
@@ -52,7 +70,7 @@ RSpec.describe Gitlab::Utils::UsageData do
let(:relation) { double(:relation, connection: double(:connection)) }
before do
- allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false) # rubocop: disable Database/MultipleDatabases
+ allow(relation.connection).to receive(:transaction_open?).and_return(false)
end
it 'delegates counting to counter class instance' do
@@ -104,7 +122,7 @@ RSpec.describe Gitlab::Utils::UsageData do
let(:ci_builds_estimated_cardinality) { 2.0809220082170614 }
before do
- allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false) # rubocop: disable Database/MultipleDatabases
+ allow(model.connection).to receive(:transaction_open?).and_return(false)
end
context 'different counting parameters' do
diff --git a/spec/lib/gitlab/webpack/file_loader_spec.rb b/spec/lib/gitlab/webpack/file_loader_spec.rb
new file mode 100644
index 00000000000..34d00b9f106
--- /dev/null
+++ b/spec/lib/gitlab/webpack/file_loader_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'support/helpers/file_read_helpers'
+require 'support/webmock'
+
+RSpec.describe Gitlab::Webpack::FileLoader do
+ include FileReadHelpers
+ include WebMock::API
+
+ let(:error_file_path) { "error.yml" }
+ let(:file_path) { "my_test_file.yml" }
+ let(:file_contents) do
+ <<-EOF
+ - hello
+ - world
+ - test
+ EOF
+ end
+
+ before do
+ allow(Gitlab.config.webpack.dev_server).to receive_messages(host: 'hostname', port: 2000, https: false)
+ allow(Gitlab.config.webpack).to receive(:public_path).and_return('public_path')
+ allow(Gitlab.config.webpack).to receive(:output_dir).and_return('webpack_output')
+ end
+
+ context "with dev server enabled" do
+ before do
+ allow(Gitlab.config.webpack.dev_server).to receive(:enabled).and_return(true)
+
+ stub_request(:get, "http://hostname:2000/public_path/not_found").to_return(status: 404)
+ stub_request(:get, "http://hostname:2000/public_path/#{file_path}").to_return(body: file_contents, status: 200)
+ stub_request(:get, "http://hostname:2000/public_path/#{error_file_path}").to_raise(StandardError)
+ end
+
+ it "returns content when respondes succesfully" do
+ expect(Gitlab::Webpack::FileLoader.load(file_path)).to be(file_contents)
+ end
+
+ it "raises error when 404" do
+ expect { Gitlab::Webpack::FileLoader.load("not_found") }.to raise_error("HTTP error 404")
+ end
+
+ it "raises error when errors out" do
+ expect { Gitlab::Webpack::FileLoader.load(error_file_path) }.to raise_error(Gitlab::Webpack::FileLoader::DevServerLoadError)
+ end
+ end
+
+ context "with dev server enabled and https" do
+ before do
+ allow(Gitlab.config.webpack.dev_server).to receive(:enabled).and_return(true)
+ allow(Gitlab.config.webpack.dev_server).to receive(:https).and_return(true)
+
+ stub_request(:get, "https://hostname:2000/public_path/#{error_file_path}").to_raise(EOFError)
+ end
+
+ it "raises error if catches SSLError" do
+ expect { Gitlab::Webpack::FileLoader.load(error_file_path) }.to raise_error(Gitlab::Webpack::FileLoader::DevServerSSLError)
+ end
+ end
+
+ context "with dev server disabled" do
+ before do
+ allow(Gitlab.config.webpack.dev_server).to receive(:enabled).and_return(false)
+ stub_file_read(::Rails.root.join("webpack_output/#{file_path}"), content: file_contents)
+ stub_file_read(::Rails.root.join("webpack_output/#{error_file_path}"), error: Errno::ENOENT)
+ end
+
+ describe ".load" do
+ it "returns file content from file path" do
+ expect(Gitlab::Webpack::FileLoader.load(file_path)).to be(file_contents)
+ end
+
+ it "throws error if file cannot be read" do
+ expect { Gitlab::Webpack::FileLoader.load(error_file_path) }.to raise_error(Gitlab::Webpack::FileLoader::StaticLoadError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/webpack/graphql_known_operations_spec.rb b/spec/lib/gitlab/webpack/graphql_known_operations_spec.rb
new file mode 100644
index 00000000000..89cade82fe6
--- /dev/null
+++ b/spec/lib/gitlab/webpack/graphql_known_operations_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Webpack::GraphqlKnownOperations do
+ let(:content) do
+ <<-EOF
+ - hello
+ - world
+ - test
+ EOF
+ end
+
+ around do |example|
+ described_class.clear_memoization!
+
+ example.run
+
+ described_class.clear_memoization!
+ end
+
+ describe ".load" do
+ context "when file loader returns" do
+ before do
+ allow(::Gitlab::Webpack::FileLoader).to receive(:load).with("graphql_known_operations.yml").and_return(content)
+ end
+
+ it "returns memoized value" do
+ expect(::Gitlab::Webpack::FileLoader).to receive(:load).once
+
+ 2.times { ::Gitlab::Webpack::GraphqlKnownOperations.load }
+
+ expect(::Gitlab::Webpack::GraphqlKnownOperations.load).to eq(%w(hello world test))
+ end
+ end
+
+ context "when file loader errors" do
+ before do
+ allow(::Gitlab::Webpack::FileLoader).to receive(:load).and_raise(StandardError.new("test"))
+ end
+
+ it "returns empty array" do
+ expect(::Gitlab::Webpack::GraphqlKnownOperations.load).to eq([])
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index 8ba56af561d..3bab9aec454 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -512,6 +512,24 @@ RSpec.describe Gitlab::Workhorse do
end
end
+ describe '.send_dependency' do
+ let(:headers) { { Accept: 'foo', Authorization: 'Bearer asdf1234' } }
+ let(:url) { 'https://foo.bar.com/baz' }
+
+ subject { described_class.send_dependency(headers, url) }
+
+ it 'sets the header correctly', :aggregate_failures do
+ key, command, params = decode_workhorse_header(subject)
+
+ expect(key).to eq("Gitlab-Workhorse-Send-Data")
+ expect(command).to eq("send-dependency")
+ expect(params).to eq({
+ 'Header' => headers,
+ 'Url' => url
+ }.deep_stringify_keys)
+ end
+ end
+
describe '.send_git_snapshot' do
let(:url) { 'http://example.com' }
diff --git a/spec/lib/gitlab/x509/certificate_spec.rb b/spec/lib/gitlab/x509/certificate_spec.rb
index a5b192dd051..2dc30cc871d 100644
--- a/spec/lib/gitlab/x509/certificate_spec.rb
+++ b/spec/lib/gitlab/x509/certificate_spec.rb
@@ -5,6 +5,9 @@ require 'spec_helper'
RSpec.describe Gitlab::X509::Certificate do
include SmimeHelper
+ let(:sample_ca_certs_path) { Rails.root.join('spec/fixtures/clusters').to_s }
+ let(:sample_cert) { Rails.root.join('spec/fixtures/x509_certificate.crt').to_s }
+
# cert generation is an expensive operation and they are used read-only,
# so we share them as instance variables in all tests
before :context do
@@ -13,6 +16,16 @@ RSpec.describe Gitlab::X509::Certificate do
@cert = generate_cert(signer_ca: @intermediate_ca)
end
+ before do
+ stub_const("OpenSSL::X509::DEFAULT_CERT_DIR", sample_ca_certs_path)
+ stub_const("OpenSSL::X509::DEFAULT_CERT_FILE", sample_cert)
+ described_class.reset_ca_certs_bundle
+ end
+
+ after(:context) do
+ described_class.reset_ca_certs_bundle
+ end
+
describe 'testing environment setup' do
describe 'generate_root' do
subject { @root_ca }
@@ -103,6 +116,43 @@ RSpec.describe Gitlab::X509::Certificate do
end
end
+ describe '.ca_certs_paths' do
+ it 'returns all files specified by OpenSSL defaults' do
+ cert_paths = Dir["#{OpenSSL::X509::DEFAULT_CERT_DIR}/*"]
+
+ expect(described_class.ca_certs_paths).to match_array(cert_paths + [sample_cert])
+ end
+ end
+
+ describe '.ca_certs_bundle' do
+ it 'skips certificates if OpenSSLError is raised and report it' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_and_raise_for_dev_exception)
+ .with(
+ a_kind_of(OpenSSL::X509::CertificateError),
+ cert_file: a_kind_of(String)).at_least(:once)
+
+ expect(OpenSSL::X509::Certificate)
+ .to receive(:new)
+ .and_raise(OpenSSL::X509::CertificateError).at_least(:once)
+
+ expect(described_class.ca_certs_bundle).to be_a(String)
+ end
+
+ it 'returns a list certificates as strings' do
+ expect(described_class.ca_certs_bundle).to be_a(String)
+ end
+ end
+
+ describe '.load_ca_certs_bundle' do
+ it 'loads a PEM-encoded certificate bundle into an OpenSSL::X509::Certificate array' do
+ ca_certs_string = described_class.ca_certs_bundle
+ ca_certs = described_class.load_ca_certs_bundle(ca_certs_string)
+
+ expect(ca_certs).to all(be_an(OpenSSL::X509::Certificate))
+ end
+ end
+
def common_cert_tests(parsed_cert, cert, signer_ca, with_ca_certs: nil)
expect(parsed_cert.cert).to be_a(OpenSSL::X509::Certificate)
expect(parsed_cert.cert.subject).to eq(cert[:cert].subject)
diff --git a/spec/lib/gitlab/x509/signature_spec.rb b/spec/lib/gitlab/x509/signature_spec.rb
index 7ba15faf910..0e34d5393d6 100644
--- a/spec/lib/gitlab/x509/signature_spec.rb
+++ b/spec/lib/gitlab/x509/signature_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Gitlab::X509::Signature do
end
shared_examples "a verified signature" do
- let_it_be(:user) { create(:user, email: X509Helpers::User1.certificate_email) }
+ let!(:user) { create(:user, email: X509Helpers::User1.certificate_email) }
subject(:signature) do
described_class.new(
@@ -30,10 +30,12 @@ RSpec.describe Gitlab::X509::Signature do
expect(signature.verification_status).to eq(:verified)
end
- it "returns an unverified signature if the email matches but isn't confirmed" do
- user.update!(confirmed_at: nil)
+ context "if the email matches but isn't confirmed" do
+ let!(:user) { create(:user, :unconfirmed, email: X509Helpers::User1.certificate_email) }
- expect(signature.verification_status).to eq(:unverified)
+ it "returns an unverified signature" do
+ expect(signature.verification_status).to eq(:unverified)
+ end
end
it 'returns an unverified signature if email does not match' do
@@ -297,7 +299,7 @@ RSpec.describe Gitlab::X509::Signature do
end
context 'verified signature' do
- let_it_be(:user) { create(:user, email: X509Helpers::User1.certificate_email) }
+ let_it_be(:user) { create(:user, :unconfirmed, email: X509Helpers::User1.certificate_email) }
subject(:signature) do
described_class.new(
@@ -316,52 +318,56 @@ RSpec.describe Gitlab::X509::Signature do
allow(OpenSSL::X509::Store).to receive(:new).and_return(store)
end
- it 'returns a verified signature if email does match' do
- expect(signature.x509_certificate).to have_attributes(certificate_attributes)
- expect(signature.x509_certificate.x509_issuer).to have_attributes(issuer_attributes)
- expect(signature.verified_signature).to be_truthy
- expect(signature.verification_status).to eq(:verified)
- end
+ context 'when user email is confirmed' do
+ before_all do
+ user.confirm
+ end
- it "returns an unverified signature if the email matches but isn't confirmed" do
- user.update!(confirmed_at: nil)
+ it 'returns a verified signature if email does match', :ggregate_failures do
+ expect(signature.x509_certificate).to have_attributes(certificate_attributes)
+ expect(signature.x509_certificate.x509_issuer).to have_attributes(issuer_attributes)
+ expect(signature.verified_signature).to be_truthy
+ expect(signature.verification_status).to eq(:verified)
+ end
- expect(signature.verification_status).to eq(:unverified)
- end
+ it 'returns an unverified signature if email does not match', :aggregate_failures do
+ signature = described_class.new(
+ X509Helpers::User1.signed_tag_signature,
+ X509Helpers::User1.signed_tag_base_data,
+ "gitlab@example.com",
+ X509Helpers::User1.signed_commit_time
+ )
+
+ expect(signature.x509_certificate).to have_attributes(certificate_attributes)
+ expect(signature.x509_certificate.x509_issuer).to have_attributes(issuer_attributes)
+ expect(signature.verified_signature).to be_truthy
+ expect(signature.verification_status).to eq(:unverified)
+ end
- it 'returns an unverified signature if email does not match' do
- signature = described_class.new(
- X509Helpers::User1.signed_tag_signature,
- X509Helpers::User1.signed_tag_base_data,
- "gitlab@example.com",
- X509Helpers::User1.signed_commit_time
- )
+ it 'returns an unverified signature if email does match and time is wrong', :aggregate_failures do
+ signature = described_class.new(
+ X509Helpers::User1.signed_tag_signature,
+ X509Helpers::User1.signed_tag_base_data,
+ X509Helpers::User1.certificate_email,
+ Time.new(2020, 2, 22)
+ )
+
+ expect(signature.x509_certificate).to have_attributes(certificate_attributes)
+ expect(signature.x509_certificate.x509_issuer).to have_attributes(issuer_attributes)
+ expect(signature.verified_signature).to be_falsey
+ expect(signature.verification_status).to eq(:unverified)
+ end
- expect(signature.x509_certificate).to have_attributes(certificate_attributes)
- expect(signature.x509_certificate.x509_issuer).to have_attributes(issuer_attributes)
- expect(signature.verified_signature).to be_truthy
- expect(signature.verification_status).to eq(:unverified)
- end
+ it 'returns an unverified signature if certificate is revoked' do
+ expect(signature.verification_status).to eq(:verified)
- it 'returns an unverified signature if email does match and time is wrong' do
- signature = described_class.new(
- X509Helpers::User1.signed_tag_signature,
- X509Helpers::User1.signed_tag_base_data,
- X509Helpers::User1.certificate_email,
- Time.new(2020, 2, 22)
- )
+ signature.x509_certificate.revoked!
- expect(signature.x509_certificate).to have_attributes(certificate_attributes)
- expect(signature.x509_certificate.x509_issuer).to have_attributes(issuer_attributes)
- expect(signature.verified_signature).to be_falsey
- expect(signature.verification_status).to eq(:unverified)
+ expect(signature.verification_status).to eq(:unverified)
+ end
end
- it 'returns an unverified signature if certificate is revoked' do
- expect(signature.verification_status).to eq(:verified)
-
- signature.x509_certificate.revoked!
-
+ it 'returns an unverified signature if the email matches but is not confirmed' do
expect(signature.verification_status).to eq(:unverified)
end
end
diff --git a/spec/lib/gitlab/zentao/client_spec.rb b/spec/lib/gitlab/zentao/client_spec.rb
index e3a335c1e89..86b310fe417 100644
--- a/spec/lib/gitlab/zentao/client_spec.rb
+++ b/spec/lib/gitlab/zentao/client_spec.rb
@@ -6,7 +6,23 @@ RSpec.describe Gitlab::Zentao::Client do
subject(:integration) { described_class.new(zentao_integration) }
let(:zentao_integration) { create(:zentao_integration) }
- let(:mock_get_products_url) { integration.send(:url, "products/#{zentao_integration.zentao_product_xid}") }
+
+ def mock_get_products_url
+ integration.send(:url, "products/#{zentao_integration.zentao_product_xid}")
+ end
+
+ def mock_fetch_issue_url(issue_id)
+ integration.send(:url, "issues/#{issue_id}")
+ end
+
+ let(:mock_headers) do
+ {
+ headers: {
+ 'Content-Type' => 'application/json',
+ 'Token' => zentao_integration.api_token
+ }
+ }
+ end
describe '#new' do
context 'if integration is nil' do
@@ -25,15 +41,6 @@ RSpec.describe Gitlab::Zentao::Client do
end
describe '#fetch_product' do
- let(:mock_headers) do
- {
- headers: {
- 'Content-Type' => 'application/json',
- 'Token' => zentao_integration.api_token
- }
- }
- end
-
context 'with valid product' do
let(:mock_response) { { 'id' => zentao_integration.zentao_product_xid } }
@@ -54,7 +61,9 @@ RSpec.describe Gitlab::Zentao::Client do
end
it 'fetches the empty product' do
- expect(integration.fetch_product(zentao_integration.zentao_product_xid)).to eq({})
+ expect do
+ integration.fetch_product(zentao_integration.zentao_product_xid)
+ end.to raise_error(Gitlab::Zentao::Client::Error, 'request error')
end
end
@@ -65,21 +74,14 @@ RSpec.describe Gitlab::Zentao::Client do
end
it 'fetches the empty product' do
- expect(integration.fetch_product(zentao_integration.zentao_product_xid)).to eq({})
+ expect do
+ integration.fetch_product(zentao_integration.zentao_product_xid)
+ end.to raise_error(Gitlab::Zentao::Client::Error, 'invalid response format')
end
end
end
describe '#ping' do
- let(:mock_headers) do
- {
- headers: {
- 'Content-Type' => 'application/json',
- 'Token' => zentao_integration.api_token
- }
- }
- end
-
context 'with valid resource' do
before do
WebMock.stub_request(:get, mock_get_products_url)
@@ -102,4 +104,30 @@ RSpec.describe Gitlab::Zentao::Client do
end
end
end
+
+ describe '#fetch_issue' do
+ context 'with invalid id' do
+ let(:invalid_ids) { ['story', 'story-', '-', '123', ''] }
+
+ it 'returns empty object' do
+ invalid_ids.each do |id|
+ expect { integration.fetch_issue(id) }
+ .to raise_error(Gitlab::Zentao::Client::Error, 'invalid issue id')
+ end
+ end
+ end
+
+ context 'with valid id' do
+ let(:valid_ids) { %w[story-1 bug-23] }
+
+ it 'fetches current issue' do
+ valid_ids.each do |id|
+ WebMock.stub_request(:get, mock_fetch_issue_url(id))
+ .with(mock_headers).to_return(status: 200, body: { issue: { id: id } }.to_json)
+
+ expect(integration.fetch_issue(id).dig('issue', 'id')).to eq id
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/zentao/query_spec.rb b/spec/lib/gitlab/zentao/query_spec.rb
new file mode 100644
index 00000000000..f7495e640c3
--- /dev/null
+++ b/spec/lib/gitlab/zentao/query_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Zentao::Query do
+ let(:zentao_integration) { create(:zentao_integration) }
+ let(:params) { {} }
+
+ subject(:query) { described_class.new(zentao_integration, ActionController::Parameters.new(params)) }
+
+ describe '#issues' do
+ let(:response) { { 'page' => 1, 'total' => 0, 'limit' => 20, 'issues' => [] } }
+
+ def expect_query_option_include(expected_params)
+ expect_next_instance_of(Gitlab::Zentao::Client) do |client|
+ expect(client).to receive(:fetch_issues)
+ .with(hash_including(expected_params))
+ .and_return(response)
+ end
+
+ query.issues
+ end
+
+ context 'when params are empty' do
+ it 'fills default params' do
+ expect_query_option_include(status: 'opened', order: 'lastEditedDate_desc', labels: '')
+ end
+ end
+
+ context 'when params contain valid options' do
+ let(:params) { { state: 'closed', sort: 'created_asc', labels: %w[Bugs Features] } }
+
+ it 'fills params with standard of ZenTao' do
+ expect_query_option_include(status: 'closed', order: 'openedDate_asc', labels: 'Bugs,Features')
+ end
+ end
+
+ context 'when params contain invalid options' do
+ let(:params) { { state: 'xxx', sort: 'xxx', labels: %w[xxx] } }
+
+ it 'fills default params with standard of ZenTao' do
+ expect_query_option_include(status: 'opened', order: 'lastEditedDate_desc', labels: 'xxx')
+ end
+ end
+ end
+
+ describe '#issue' do
+ let(:response) { { 'issue' => { 'id' => 'story-1' } } }
+
+ before do
+ expect_next_instance_of(Gitlab::Zentao::Client) do |client|
+ expect(client).to receive(:fetch_issue)
+ .and_return(response)
+ end
+ end
+
+ it 'returns issue object by client' do
+ expect(query.issue).to include('id' => 'story-1')
+ end
+ end
+end
diff --git a/spec/lib/marginalia_spec.rb b/spec/lib/marginalia_spec.rb
index 3f39d969dbd..53048ae2e6b 100644
--- a/spec/lib/marginalia_spec.rb
+++ b/spec/lib/marginalia_spec.rb
@@ -59,14 +59,14 @@ RSpec.describe 'Marginalia spec' do
"application" => "test",
"endpoint_id" => "MarginaliaTestController#first_user",
"correlation_id" => correlation_id,
- "db_config_name" => "ci"
+ "db_config_name" => ENV['GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci'] == 'main' ? 'main' : 'ci'
}
end
- before do |example|
+ before do
skip_if_multiple_databases_not_setup
- allow(User).to receive(:connection) { Ci::CiDatabaseRecord.connection }
+ allow(User).to receive(:connection) { Ci::ApplicationRecord.connection }
end
it 'generates a query that includes the component and value' do
diff --git a/spec/lib/object_storage/config_spec.rb b/spec/lib/object_storage/config_spec.rb
index 21b8a44b3d6..9a0e83bfd5e 100644
--- a/spec/lib/object_storage/config_spec.rb
+++ b/spec/lib/object_storage/config_spec.rb
@@ -36,46 +36,6 @@ RSpec.describe ObjectStorage::Config do
subject { described_class.new(raw_config.as_json) }
- describe '#load_provider' do
- before do
- subject.load_provider
- end
-
- context 'with AWS' do
- it 'registers AWS as a provider' do
- expect(Fog.providers.keys).to include(:aws)
- end
- end
-
- context 'with Google' do
- let(:credentials) do
- {
- provider: 'Google',
- google_storage_access_key_id: 'GOOGLE_ACCESS_KEY_ID',
- google_storage_secret_access_key: 'GOOGLE_SECRET_ACCESS_KEY'
- }
- end
-
- it 'registers Google as a provider' do
- expect(Fog.providers.keys).to include(:google)
- end
- end
-
- context 'with Azure' do
- let(:credentials) do
- {
- provider: 'AzureRM',
- azure_storage_account_name: 'azuretest',
- azure_storage_access_key: 'ABCD1234'
- }
- end
-
- it 'registers AzureRM as a provider' do
- expect(Fog.providers.keys).to include(:azurerm)
- end
- end
- end
-
describe '#credentials' do
it { expect(subject.credentials).to eq(credentials) }
end
diff --git a/spec/lib/object_storage/direct_upload_spec.rb b/spec/lib/object_storage/direct_upload_spec.rb
index 006f4f603b6..1629aec89f5 100644
--- a/spec/lib/object_storage/direct_upload_spec.rb
+++ b/spec/lib/object_storage/direct_upload_spec.rb
@@ -201,10 +201,6 @@ RSpec.describe ObjectStorage::DirectUpload do
end
shared_examples 'a valid AzureRM upload' do
- before do
- require 'fog/azurerm'
- end
-
it_behaves_like 'a valid upload'
it 'enables the Workhorse client' do
diff --git a/spec/lib/security/ci_configuration/sast_iac_build_action_spec.rb b/spec/lib/security/ci_configuration/sast_iac_build_action_spec.rb
new file mode 100644
index 00000000000..ecd1602dd9e
--- /dev/null
+++ b/spec/lib/security/ci_configuration/sast_iac_build_action_spec.rb
@@ -0,0 +1,163 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Security::CiConfiguration::SastIacBuildAction do
+ subject(:result) { described_class.new(auto_devops_enabled, gitlab_ci_content).generate }
+
+ let(:params) { {} }
+
+ context 'with existing .gitlab-ci.yml' do
+ let(:auto_devops_enabled) { false }
+
+ context 'sast iac has not been included' do
+ let(:expected_yml) do
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
+ # Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
+ stages:
+ - test
+ - security
+ variables:
+ RANDOM: make sure this persists
+ include:
+ - template: existing.yml
+ - template: Security/SAST-IaC.latest.gitlab-ci.yml
+ CI_YML
+ end
+
+ context 'template includes are an array' do
+ let(:gitlab_ci_content) do
+ { "stages" => %w(test security),
+ "variables" => { "RANDOM" => "make sure this persists" },
+ "include" => [{ "template" => "existing.yml" }] }
+ end
+
+ it 'generates the correct YML' do
+ expect(result[:action]).to eq('update')
+ expect(result[:content]).to eq(expected_yml)
+ end
+ end
+
+ context 'template include is not an array' do
+ let(:gitlab_ci_content) do
+ { "stages" => %w(test security),
+ "variables" => { "RANDOM" => "make sure this persists" },
+ "include" => { "template" => "existing.yml" } }
+ end
+
+ it 'generates the correct YML' do
+ expect(result[:action]).to eq('update')
+ expect(result[:content]).to eq(expected_yml)
+ end
+ end
+ end
+
+ context 'secret_detection has been included' do
+ let(:expected_yml) do
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
+ # Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
+ stages:
+ - test
+ variables:
+ RANDOM: make sure this persists
+ include:
+ - template: Security/SAST-IaC.latest.gitlab-ci.yml
+ CI_YML
+ end
+
+ context 'secret_detection template include are an array' do
+ let(:gitlab_ci_content) do
+ { "stages" => %w(test),
+ "variables" => { "RANDOM" => "make sure this persists" },
+ "include" => [{ "template" => "Security/SAST-IaC.latest.gitlab-ci.yml" }] }
+ end
+
+ it 'generates the correct YML' do
+ expect(result[:action]).to eq('update')
+ expect(result[:content]).to eq(expected_yml)
+ end
+ end
+
+ context 'secret_detection template include is not an array' do
+ let(:gitlab_ci_content) do
+ { "stages" => %w(test),
+ "variables" => { "RANDOM" => "make sure this persists" },
+ "include" => { "template" => "Security/SAST-IaC.latest.gitlab-ci.yml" } }
+ end
+
+ it 'generates the correct YML' do
+ expect(result[:action]).to eq('update')
+ expect(result[:content]).to eq(expected_yml)
+ end
+ end
+ end
+ end
+
+ context 'with no .gitlab-ci.yml' do
+ let(:gitlab_ci_content) { nil }
+
+ context 'autodevops disabled' do
+ let(:auto_devops_enabled) { false }
+ let(:expected_yml) do
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
+ # Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
+ include:
+ - template: Security/SAST-IaC.latest.gitlab-ci.yml
+ CI_YML
+ end
+
+ it 'generates the correct YML' do
+ expect(result[:action]).to eq('create')
+ expect(result[:content]).to eq(expected_yml)
+ end
+ end
+
+ context 'with autodevops enabled' do
+ let(:auto_devops_enabled) { true }
+ let(:expected_yml) do
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
+ # Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
+ include:
+ - template: Auto-DevOps.gitlab-ci.yml
+ CI_YML
+ end
+
+ before do
+ allow_next_instance_of(described_class) do |sast_iac_build_actions|
+ allow(sast_iac_build_actions).to receive(:auto_devops_stages).and_return(fast_auto_devops_stages)
+ end
+ end
+
+ it 'generates the correct YML' do
+ expect(result[:action]).to eq('create')
+ expect(result[:content]).to eq(expected_yml)
+ end
+ end
+ end
+
+ # stubbing this method allows this spec file to use fast_spec_helper
+ def fast_auto_devops_stages
+ auto_devops_template = YAML.safe_load( File.read('lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml') )
+ auto_devops_template['stages']
+ end
+end
diff --git a/spec/lib/sidebars/groups/menus/invite_team_members_menu_spec.rb b/spec/lib/sidebars/groups/menus/invite_team_members_menu_spec.rb
new file mode 100644
index 00000000000..a79e5182f45
--- /dev/null
+++ b/spec/lib/sidebars/groups/menus/invite_team_members_menu_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Groups::Menus::InviteTeamMembersMenu do
+ let_it_be(:owner) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:group) do
+ build(:group).tap do |g|
+ g.add_owner(owner)
+ end
+ end
+
+ let(:context) { Sidebars::Groups::Context.new(current_user: owner, container: group) }
+
+ subject(:invite_menu) { described_class.new(context) }
+
+ context 'when the group is viewed by an owner of the group' do
+ describe '#render?' do
+ it 'renders the Invite team members link' do
+ expect(invite_menu.render?).to eq(true)
+ end
+
+ context 'when the group already has at least 2 members' do
+ before do
+ group.add_guest(guest)
+ end
+
+ it 'does not render the link' do
+ expect(invite_menu.render?).to eq(false)
+ end
+ end
+ end
+
+ describe '#title' do
+ it 'displays the correct Invite team members text for the link in the side nav' do
+ expect(invite_menu.title).to eq('Invite members')
+ end
+ end
+ end
+
+ context 'when the group is viewed by a guest user without admin permissions' do
+ let(:context) { Sidebars::Groups::Context.new(current_user: guest, container: group) }
+
+ before do
+ group.add_guest(guest)
+ end
+
+ describe '#render?' do
+ it 'does not render the link' do
+ expect(subject.render?).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb b/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb
index 5ebd67462f8..e954d7a44ba 100644
--- a/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb
+++ b/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb
@@ -137,16 +137,27 @@ RSpec.describe Sidebars::Groups::Menus::PackagesRegistriesMenu do
stub_config(dependency_proxy: { enabled: dependency_enabled })
end
- context 'when config dependency_proxy is enabled' do
- let(:dependency_enabled) { true }
+ context 'when user can read dependency proxy' do
+ context 'when config dependency_proxy is enabled' do
+ let(:dependency_enabled) { true }
- it 'the menu item is added to list of menu items' do
- is_expected.not_to be_nil
+ it 'the menu item is added to list of menu items' do
+ is_expected.not_to be_nil
+ end
+ end
+
+ context 'when config dependency_proxy is not enabled' do
+ let(:dependency_enabled) { false }
+
+ it 'the menu item is not added to list of menu items' do
+ is_expected.to be_nil
+ end
end
end
- context 'when config dependency_proxy is not enabled' do
- let(:dependency_enabled) { false }
+ context 'when user cannot read dependency proxy' do
+ let(:user) { nil }
+ let(:dependency_enabled) { true }
it 'the menu item is not added to list of menu items' do
is_expected.to be_nil
diff --git a/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb b/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb
index 2415598da9c..55281171634 100644
--- a/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb
@@ -51,6 +51,16 @@ RSpec.describe Sidebars::Projects::Menus::InfrastructureMenu do
it 'menu link points to Terraform page' do
expect(subject.link).to eq find_menu_item(:terraform).link
end
+
+ context 'when Terraform menu is not visible' do
+ before do
+ subject.renderable_items.delete(find_menu_item(:terraform))
+ end
+
+ it 'menu link points to Google Cloud page' do
+ expect(subject.link).to eq find_menu_item(:google_cloud).link
+ end
+ end
end
end
@@ -89,5 +99,11 @@ RSpec.describe Sidebars::Projects::Menus::InfrastructureMenu do
it_behaves_like 'access rights checks'
end
+
+ describe 'Google Cloud' do
+ let(:item_id) { :google_cloud }
+
+ it_behaves_like 'access rights checks'
+ end
end
end
diff --git a/spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb b/spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb
new file mode 100644
index 00000000000..df9b260d211
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::InviteTeamMembersMenu do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:guest) { create(:user) }
+
+ let(:context) { Sidebars::Projects::Context.new(current_user: owner, container: project) }
+
+ subject(:invite_menu) { described_class.new(context) }
+
+ context 'when the project is viewed by an owner of the group' do
+ let(:owner) { project.owner }
+
+ describe '#render?' do
+ it 'renders the Invite team members link' do
+ expect(invite_menu.render?).to eq(true)
+ end
+
+ context 'when the project already has at least 2 members' do
+ before do
+ project.add_guest(guest)
+ end
+
+ it 'does not render the link' do
+ expect(invite_menu.render?).to eq(false)
+ end
+ end
+ end
+
+ describe '#title' do
+ it 'displays the correct Invite team members text for the link in the side nav' do
+ expect(invite_menu.title).to eq('Invite members')
+ end
+ end
+ end
+
+ context 'when the project is viewed by a guest user without admin permissions' do
+ let(:context) { Sidebars::Projects::Context.new(current_user: guest, container: project) }
+
+ before do
+ project.add_guest(guest)
+ end
+
+ describe '#render?' do
+ it 'does not render' do
+ expect(invite_menu.render?).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/settings_menu_spec.rb b/spec/lib/sidebars/projects/menus/settings_menu_spec.rb
index 3079c781d73..1e5d41dfec4 100644
--- a/spec/lib/sidebars/projects/menus/settings_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/settings_menu_spec.rb
@@ -162,24 +162,10 @@ RSpec.describe Sidebars::Projects::Menus::SettingsMenu do
describe 'Usage Quotas' do
let(:item_id) { :usage_quotas }
- describe 'with project_storage_ui feature flag enabled' do
- before do
- stub_feature_flags(project_storage_ui: true)
- end
-
- specify { is_expected.not_to be_nil }
-
- describe 'when the user does not have access' do
- let(:user) { nil }
-
- specify { is_expected.to be_nil }
- end
- end
+ specify { is_expected.not_to be_nil }
- describe 'with project_storage_ui feature flag disabled' do
- before do
- stub_feature_flags(project_storage_ui: false)
- end
+ describe 'when the user does not have access' do
+ let(:user) { nil }
specify { is_expected.to be_nil }
end
diff --git a/spec/lib/sidebars/projects/menus/zentao_menu_spec.rb b/spec/lib/sidebars/projects/menus/zentao_menu_spec.rb
new file mode 100644
index 00000000000..f0bce6b7ea5
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/zentao_menu_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::ZentaoMenu do
+ it_behaves_like 'ZenTao menu with CE version'
+end
diff --git a/spec/lib/system_check/incoming_email_check_spec.rb b/spec/lib/system_check/incoming_email_check_spec.rb
index 710702b93fc..5d93b810045 100644
--- a/spec/lib/system_check/incoming_email_check_spec.rb
+++ b/spec/lib/system_check/incoming_email_check_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe SystemCheck::IncomingEmailCheck do
it 'runs IMAP and mailroom checks' do
expect(SystemCheck).to receive(:run).with('Reply by email', [
SystemCheck::IncomingEmail::ImapAuthenticationCheck,
- SystemCheck::IncomingEmail::InitdConfiguredCheck,
+ SystemCheck::IncomingEmail::MailRoomEnabledCheck,
SystemCheck::IncomingEmail::MailRoomRunningCheck
])
@@ -43,7 +43,7 @@ RSpec.describe SystemCheck::IncomingEmailCheck do
it 'runs mailroom checks' do
expect(SystemCheck).to receive(:run).with('Reply by email', [
- SystemCheck::IncomingEmail::InitdConfiguredCheck,
+ SystemCheck::IncomingEmail::MailRoomEnabledCheck,
SystemCheck::IncomingEmail::MailRoomRunningCheck
])
diff --git a/spec/lib/uploaded_file_spec.rb b/spec/lib/uploaded_file_spec.rb
index ececc84bc93..0aba6cb0065 100644
--- a/spec/lib/uploaded_file_spec.rb
+++ b/spec/lib/uploaded_file_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe UploadedFile do
end
context 'from_params functions' do
- RSpec.shared_examples 'using the file path' do |filename:, content_type:, sha256:, path_suffix:|
+ RSpec.shared_examples 'using the file path' do |filename:, content_type:, sha256:, path_suffix:, upload_duration:|
it { is_expected.not_to be_nil }
it 'sets properly the attributes' do
@@ -24,6 +24,7 @@ RSpec.describe UploadedFile do
expect(subject.sha256).to eq(sha256)
expect(subject.remote_id).to be_nil
expect(subject.path).to end_with(path_suffix)
+ expect(subject.upload_duration).to eq(upload_duration)
end
it 'handles a blank path' do
@@ -37,16 +38,17 @@ RSpec.describe UploadedFile do
end
end
- RSpec.shared_examples 'using the remote id' do |filename:, content_type:, sha256:, size:, remote_id:|
+ RSpec.shared_examples 'using the remote id' do |filename:, content_type:, sha256:, size:, remote_id:, upload_duration:|
it { is_expected.not_to be_nil }
it 'sets properly the attributes' do
expect(subject.original_filename).to eq(filename)
- expect(subject.content_type).to eq('application/octet-stream')
- expect(subject.sha256).to eq('sha256')
+ expect(subject.content_type).to eq(content_type)
+ expect(subject.sha256).to eq(sha256)
expect(subject.path).to be_nil
- expect(subject.size).to eq(123456)
- expect(subject.remote_id).to eq('1234567890')
+ expect(subject.size).to eq(size)
+ expect(subject.remote_id).to eq(remote_id)
+ expect(subject.upload_duration).to eq(upload_duration)
end
end
@@ -78,6 +80,7 @@ RSpec.describe UploadedFile do
{ 'path' => temp_file.path,
'name' => 'dir/my file&.txt',
'type' => 'my/type',
+ 'upload_duration' => '5.05',
'sha256' => 'sha256' }
end
@@ -85,7 +88,8 @@ RSpec.describe UploadedFile do
filename: 'my_file_.txt',
content_type: 'my/type',
sha256: 'sha256',
- path_suffix: 'test'
+ path_suffix: 'test',
+ upload_duration: 5.05
end
context 'with a remote id' do
@@ -96,6 +100,7 @@ RSpec.describe UploadedFile do
'remote_url' => 'http://localhost/file',
'remote_id' => '1234567890',
'etag' => 'etag1234567890',
+ 'upload_duration' => '5.05',
'size' => '123456'
}
end
@@ -105,7 +110,8 @@ RSpec.describe UploadedFile do
content_type: 'application/octet-stream',
sha256: 'sha256',
size: 123456,
- remote_id: '1234567890'
+ remote_id: '1234567890',
+ upload_duration: 5.05
end
context 'with a path and a remote id' do
@@ -117,6 +123,7 @@ RSpec.describe UploadedFile do
'remote_url' => 'http://localhost/file',
'remote_id' => '1234567890',
'etag' => 'etag1234567890',
+ 'upload_duration' => '5.05',
'size' => '123456'
}
end
@@ -126,7 +133,8 @@ RSpec.describe UploadedFile do
content_type: 'application/octet-stream',
sha256: 'sha256',
size: 123456,
- remote_id: '1234567890'
+ remote_id: '1234567890',
+ upload_duration: 5.05
end
end
end
@@ -216,6 +224,44 @@ RSpec.describe UploadedFile do
end.to raise_error(UploadedFile::UnknownSizeError, 'Unable to determine file size')
end
end
+
+ context 'when upload_duration is not provided' do
+ it 'sets upload_duration to zero' do
+ file = described_class.new(temp_file.path)
+
+ expect(file.upload_duration).to be_zero
+ end
+ end
+
+ context 'when upload_duration is provided' do
+ let(:file) { described_class.new(temp_file.path, upload_duration: duration) }
+
+ context 'and upload_duration is a number' do
+ let(:duration) { 5.505 }
+
+ it 'sets the upload_duration' do
+ expect(file.upload_duration).to eq(duration)
+ end
+ end
+
+ context 'and upload_duration is a string' do
+ context 'and represents a number' do
+ let(:duration) { '5.505' }
+
+ it 'converts upload_duration to a number' do
+ expect(file.upload_duration).to eq(duration.to_f)
+ end
+ end
+
+ context 'and does not represent a number' do
+ let(:duration) { 'not a number' }
+
+ it 'sets upload_duration to zero' do
+ expect(file.upload_duration).to be_zero
+ end
+ end
+ end
+ end
end
describe '#sanitize_filename' do
diff --git a/spec/mailers/emails/in_product_marketing_spec.rb b/spec/mailers/emails/in_product_marketing_spec.rb
index 99beef92dea..3b92b049e42 100644
--- a/spec/mailers/emails/in_product_marketing_spec.rb
+++ b/spec/mailers/emails/in_product_marketing_spec.rb
@@ -47,22 +47,31 @@ RSpec.describe Emails::InProductMarketing do
end
where(:track, :series) do
- :create | 0
- :create | 1
- :create | 2
- :verify | 0
- :verify | 1
- :verify | 2
- :trial | 0
- :trial | 1
- :trial | 2
- :team | 0
- :team | 1
- :team | 2
- :experience | 0
+ :create | 0
+ :create | 1
+ :create | 2
+ :verify | 0
+ :verify | 1
+ :verify | 2
+ :trial | 0
+ :trial | 1
+ :trial | 2
+ :team | 0
+ :team | 1
+ :team | 2
+ :experience | 0
+ :team_short | 0
+ :trial_short | 0
+ :admin_verify | 0
+ :invite_team | 0
end
with_them do
+ before do
+ stub_experiments(invite_members_for_task: :candidate)
+ group.add_owner(user)
+ end
+
it 'has the correct subject and content' do
message = Gitlab::Email::Message::InProductMarketing.for(track).new(group: group, user: user, series: series)
@@ -76,6 +85,20 @@ RSpec.describe Emails::InProductMarketing do
else
is_expected.to have_body_text(CGI.unescapeHTML(message.cta_link))
end
+
+ if track =~ /(create|verify)/
+ is_expected.to have_body_text(message.invite_text)
+ is_expected.to have_body_text(CGI.unescapeHTML(message.invite_link))
+ else
+ is_expected.not_to have_body_text(message.invite_text)
+ is_expected.not_to have_body_text(CGI.unescapeHTML(message.invite_link))
+ end
+
+ if track == :invite_team
+ is_expected.not_to have_body_text(/This is email \d of \d/)
+ else
+ is_expected.to have_body_text(message.progress)
+ end
end
end
end
diff --git a/spec/mailers/emails/pipelines_spec.rb b/spec/mailers/emails/pipelines_spec.rb
index b9bc53625ac..3a2eb105964 100644
--- a/spec/mailers/emails/pipelines_spec.rb
+++ b/spec/mailers/emails/pipelines_spec.rb
@@ -71,10 +71,19 @@ RSpec.describe Emails::Pipelines do
end
end
+ shared_examples_for 'only accepts a single recipient' do
+ let(:recipient) { ['test@gitlab.com', 'test2@gitlab.com'] }
+
+ it 'raises an ArgumentError' do
+ expect { subject.deliver_now }.to raise_error(ArgumentError)
+ end
+ end
+
describe '#pipeline_success_email' do
- subject { Notify.pipeline_success_email(pipeline, pipeline.user.try(:email)) }
+ subject { Notify.pipeline_success_email(pipeline, recipient) }
let(:pipeline) { create(:ci_pipeline, project: project, ref: ref, sha: sha) }
+ let(:recipient) { pipeline.user.try(:email) }
let(:ref) { 'master' }
let(:sha) { project.commit(ref).sha }
@@ -93,12 +102,15 @@ RSpec.describe Emails::Pipelines do
stub_config_setting(email_subject_suffix: email_subject_suffix)
end
end
+
+ it_behaves_like 'only accepts a single recipient'
end
describe '#pipeline_failed_email' do
- subject { Notify.pipeline_failed_email(pipeline, pipeline.user.try(:email)) }
+ subject { Notify.pipeline_failed_email(pipeline, recipient) }
let(:pipeline) { create(:ci_pipeline, project: project, ref: ref, sha: sha) }
+ let(:recipient) { pipeline.user.try(:email) }
let(:ref) { 'master' }
let(:sha) { project.commit(ref).sha }
@@ -106,12 +118,15 @@ RSpec.describe Emails::Pipelines do
let(:status) { 'Failed' }
let(:status_text) { "Pipeline ##{pipeline.id} has failed!" }
end
+
+ it_behaves_like 'only accepts a single recipient'
end
describe '#pipeline_fixed_email' do
subject { Notify.pipeline_fixed_email(pipeline, pipeline.user.try(:email)) }
let(:pipeline) { create(:ci_pipeline, project: project, ref: ref, sha: sha) }
+ let(:recipient) { pipeline.user.try(:email) }
let(:ref) { 'master' }
let(:sha) { project.commit(ref).sha }
@@ -119,5 +134,7 @@ RSpec.describe Emails::Pipelines do
let(:status) { 'Fixed' }
let(:status_text) { "Pipeline has been fixed and ##{pipeline.id} has passed!" }
end
+
+ it_behaves_like 'only accepts a single recipient'
end
end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index f39037cf744..a5e3350ec2e 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Notify do
include EmailSpec::Matchers
include EmailHelpers
include RepoHelpers
+ include MembersHelper
include_context 'gitlab email notification'
@@ -720,11 +721,8 @@ RSpec.describe Notify do
end
describe 'project access denied' do
- let(:project) { create(:project, :public) }
- let(:project_member) do
- project.request_access(user)
- project.requesters.find_by(user_id: user.id)
- end
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:project_member) { create(:project_member, :developer, :access_request, user: user, source: project) }
subject { described_class.member_access_denied_email('project', project.id, user.id) }
@@ -739,6 +737,17 @@ RSpec.describe Notify do
is_expected.to have_body_text project.full_name
is_expected.to have_body_text project.web_url
end
+
+ context 'when user can not read project' do
+ let_it_be(:project) { create(:project, :private) }
+
+ it 'hides project name from subject and body' do
+ is_expected.to have_subject "Access to the Hidden project was denied"
+ is_expected.to have_body_text "Hidden project"
+ is_expected.not_to have_body_text project.full_name
+ is_expected.not_to have_body_text project.web_url
+ end
+ end
end
describe 'project access changed' do
@@ -761,10 +770,21 @@ RSpec.describe Notify do
is_expected.to have_body_text project_member.human_access
is_expected.to have_body_text 'leave the project'
is_expected.to have_body_text project_url(project, leave: 1)
+ is_expected.not_to have_body_text 'You were assigned the following tasks:'
+ end
+
+ context 'with tasks to be done present' do
+ let(:project_member) { create(:project_member, project: project, user: user, tasks_to_be_done: [:ci, :code]) }
+
+ it 'contains the assigned tasks to be done' do
+ is_expected.to have_body_text 'You were assigned the following tasks:'
+ is_expected.to have_body_text localized_tasks_to_be_done_choices[:ci]
+ is_expected.to have_body_text localized_tasks_to_be_done_choices[:code]
+ end
end
end
- def invite_to_project(project, inviter:, user: nil)
+ def invite_to_project(project, inviter:, user: nil, tasks_to_be_done: [])
create(
:project_member,
:developer,
@@ -772,7 +792,8 @@ RSpec.describe Notify do
invite_token: '1234',
invite_email: 'toto@example.com',
user: user,
- created_by: inviter
+ created_by: inviter,
+ tasks_to_be_done: tasks_to_be_done
)
end
@@ -804,6 +825,7 @@ RSpec.describe Notify do
is_expected.to have_content("#{inviter.name} invited you to join the")
is_expected.to have_content('Project details')
is_expected.to have_content("What's it about?")
+ is_expected.not_to have_body_text 'and has assigned you the following tasks:'
end
end
@@ -890,6 +912,16 @@ RSpec.describe Notify do
end
end
end
+
+ context 'with tasks to be done present', :aggregate_failures do
+ let(:project_member) { invite_to_project(project, inviter: inviter, tasks_to_be_done: [:ci, :code]) }
+
+ it 'contains the assigned tasks to be done' do
+ is_expected.to have_body_text 'and has assigned you the following tasks:'
+ is_expected.to have_body_text localized_tasks_to_be_done_choices[:ci]
+ is_expected.to have_body_text localized_tasks_to_be_done_choices[:code]
+ end
+ end
end
describe 'project invitation accepted' do
@@ -1351,10 +1383,8 @@ RSpec.describe Notify do
end
describe 'group access denied' do
- let(:group_member) do
- group.request_access(user)
- group.requesters.find_by(user_id: user.id)
- end
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:group_member) { create(:group_member, :developer, :access_request, user: user, source: group) }
let(:recipient) { user }
@@ -1372,6 +1402,17 @@ RSpec.describe Notify do
is_expected.to have_body_text group.name
is_expected.to have_body_text group.web_url
end
+
+ context 'when user can not read group' do
+ let_it_be(:group) { create(:group, :private) }
+
+ it 'hides group name from subject and body' do
+ is_expected.to have_subject "Access to the Hidden group was denied"
+ is_expected.to have_body_text "Hidden group"
+ is_expected.not_to have_body_text group.name
+ is_expected.not_to have_body_text group.web_url
+ end
+ end
end
describe 'group access changed' do
@@ -1398,7 +1439,7 @@ RSpec.describe Notify do
end
end
- def invite_to_group(group, inviter:, user: nil)
+ def invite_to_group(group, inviter:, user: nil, tasks_to_be_done: [])
create(
:group_member,
:developer,
@@ -1406,7 +1447,8 @@ RSpec.describe Notify do
invite_token: '1234',
invite_email: 'toto@example.com',
user: user,
- created_by: inviter
+ created_by: inviter,
+ tasks_to_be_done: tasks_to_be_done
)
end
@@ -1431,6 +1473,7 @@ RSpec.describe Notify do
is_expected.to have_body_text group.name
is_expected.to have_body_text group_member.human_access.downcase
is_expected.to have_body_text group_member.invite_token
+ is_expected.not_to have_body_text 'and has assigned you the following tasks:'
end
end
@@ -1444,6 +1487,24 @@ RSpec.describe Notify do
is_expected.to have_body_text group_member.invite_token
end
end
+
+ context 'with tasks to be done present', :aggregate_failures do
+ let(:group_member) { invite_to_group(group, inviter: inviter, tasks_to_be_done: [:ci, :code]) }
+
+ it 'contains the assigned tasks to be done' do
+ is_expected.to have_body_text 'and has assigned you the following tasks:'
+ is_expected.to have_body_text localized_tasks_to_be_done_choices[:ci]
+ is_expected.to have_body_text localized_tasks_to_be_done_choices[:code]
+ end
+
+ context 'when there is no inviter' do
+ let(:inviter) { nil }
+
+ it 'does not contain the assigned tasks to be done' do
+ is_expected.not_to have_body_text 'and has assigned you the following tasks:'
+ end
+ end
+ end
end
describe 'group invitation reminders' do
diff --git a/spec/migrations/20200107172020_add_timestamp_softwarelicensespolicy_spec.rb b/spec/migrations/20200107172020_add_timestamp_softwarelicensespolicy_spec.rb
deleted file mode 100644
index fff0745e8af..00000000000
--- a/spec/migrations/20200107172020_add_timestamp_softwarelicensespolicy_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('add_timestamp_softwarelicensespolicy')
-
-RSpec.describe AddTimestampSoftwarelicensespolicy do
- let(:software_licenses_policy) { table(:software_license_policies) }
- let(:projects) { table(:projects) }
- let(:licenses) { table(:software_licenses) }
-
- before do
- projects.create!(name: 'gitlab', path: 'gitlab-org/gitlab-ce', namespace_id: 1)
- licenses.create!(name: 'MIT')
- software_licenses_policy.create!(project_id: projects.first.id, software_license_id: licenses.first.id)
- end
-
- it 'creates timestamps' do
- migrate!
-
- expect(software_licenses_policy.first.created_at).to be_nil
- expect(software_licenses_policy.first.updated_at).to be_nil
- end
-end
diff --git a/spec/migrations/20200122123016_backfill_project_settings_spec.rb b/spec/migrations/20200122123016_backfill_project_settings_spec.rb
deleted file mode 100644
index 7fc8eb0e368..00000000000
--- a/spec/migrations/20200122123016_backfill_project_settings_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('backfill_project_settings')
-
-RSpec.describe BackfillProjectSettings, :sidekiq, schema: 20200114113341 do
- let(:projects) { table(:projects) }
- let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
- let(:project) { projects.create!(namespace_id: namespace.id) }
-
- describe '#up' do
- before do
- stub_const("#{described_class}::BATCH_SIZE", 2)
-
- projects.create!(id: 1, namespace_id: namespace.id)
- projects.create!(id: 2, namespace_id: namespace.id)
- projects.create!(id: 3, namespace_id: namespace.id)
- end
-
- it 'schedules BackfillProjectSettings background jobs' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 1, 2)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, 3, 3)
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
- end
-end
diff --git a/spec/migrations/20200123155929_remove_invalid_jira_data_spec.rb b/spec/migrations/20200123155929_remove_invalid_jira_data_spec.rb
deleted file mode 100644
index 9000d4b7fef..00000000000
--- a/spec/migrations/20200123155929_remove_invalid_jira_data_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('remove_invalid_jira_data')
-
-RSpec.describe RemoveInvalidJiraData do
- let(:jira_tracker_data) { table(:jira_tracker_data) }
- let(:services) { table(:services) }
-
- let(:service) { services.create!(id: 1) }
- let(:data) do
- {
- service_id: service.id,
- encrypted_api_url: 'http:url.com',
- encrypted_api_url_iv: 'somevalue',
- encrypted_url: 'http:url.com',
- encrypted_url_iv: 'somevalue',
- encrypted_username: 'username',
- encrypted_username_iv: 'somevalue',
- encrypted_password: 'username',
- encrypted_password_iv: 'somevalue'
- }
- end
-
- let!(:valid_data) { jira_tracker_data.create!(data) }
- let!(:empty_data) { jira_tracker_data.create!(service_id: service.id) }
- let!(:invalid_api_url) do
- data[:encrypted_api_url_iv] = nil
- jira_tracker_data.create!(data)
- end
-
- let!(:missing_api_url) do
- data[:encrypted_api_url] = ''
- data[:encrypted_api_url_iv] = nil
- jira_tracker_data.create!(data)
- end
-
- let!(:invalid_url) do
- data[:encrypted_url_iv] = nil
- jira_tracker_data.create!(data)
- end
-
- let!(:missing_url) do
- data[:encrypted_url] = ''
- jira_tracker_data.create!(data)
- end
-
- let!(:invalid_username) do
- data[:encrypted_username_iv] = nil
- jira_tracker_data.create!(data)
- end
-
- let!(:missing_username) do
- data[:encrypted_username] = nil
- data[:encrypted_username_iv] = nil
- jira_tracker_data.create!(data)
- end
-
- let!(:invalid_password) do
- data[:encrypted_password_iv] = nil
- jira_tracker_data.create!(data)
- end
-
- let!(:missing_password) do
- data[:encrypted_password] = nil
- data[:encrypted_username_iv] = nil
- jira_tracker_data.create!(data)
- end
-
- it 'removes the invalid data' do
- valid_data_records = [valid_data, empty_data, missing_api_url, missing_url, missing_username, missing_password]
-
- expect { migrate! }.to change { jira_tracker_data.count }.from(10).to(6)
-
- expect(jira_tracker_data.all).to match_array(valid_data_records)
- end
-end
diff --git a/spec/migrations/20200127090233_remove_invalid_issue_tracker_data_spec.rb b/spec/migrations/20200127090233_remove_invalid_issue_tracker_data_spec.rb
deleted file mode 100644
index 1d3476d6d61..00000000000
--- a/spec/migrations/20200127090233_remove_invalid_issue_tracker_data_spec.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('remove_invalid_issue_tracker_data')
-
-RSpec.describe RemoveInvalidIssueTrackerData do
- let(:issue_tracker_data) { table(:issue_tracker_data) }
- let(:services) { table(:services) }
-
- let(:service) { services.create!(id: 1) }
- let(:data) do
- {
- service_id: service.id,
- encrypted_issues_url: 'http:url.com',
- encrypted_issues_url_iv: 'somevalue',
- encrypted_new_issue_url: 'http:url.com',
- encrypted_new_issue_url_iv: 'somevalue',
- encrypted_project_url: 'username',
- encrypted_project_url_iv: 'somevalue'
- }
- end
-
- let!(:valid_data) { issue_tracker_data.create!(data) }
- let!(:empty_data) { issue_tracker_data.create!(service_id: service.id) }
- let!(:invalid_issues_url) do
- data[:encrypted_issues_url_iv] = nil
- issue_tracker_data.create!(data)
- end
-
- let!(:missing_issues_url) do
- data[:encrypted_issues_url] = ''
- data[:encrypted_issues_url_iv] = nil
- issue_tracker_data.create!(data)
- end
-
- let!(:invalid_new_isue_url) do
- data[:encrypted_new_issue_url_iv] = nil
- issue_tracker_data.create!(data)
- end
-
- let!(:missing_new_issue_url) do
- data[:encrypted_new_issue_url] = ''
- issue_tracker_data.create!(data)
- end
-
- let!(:invalid_project_url) do
- data[:encrypted_project_url_iv] = nil
- issue_tracker_data.create!(data)
- end
-
- let!(:missing_project_url) do
- data[:encrypted_project_url] = nil
- data[:encrypted_project_url_iv] = nil
- issue_tracker_data.create!(data)
- end
-
- it 'removes the invalid data' do
- valid_data_records = [valid_data, empty_data, missing_issues_url, missing_new_issue_url, missing_project_url]
-
- expect { migrate! }.to change { issue_tracker_data.count }.from(8).to(5)
-
- expect(issue_tracker_data.all).to match_array(valid_data_records)
- end
-end
diff --git a/spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb b/spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb
deleted file mode 100644
index cf8bc608483..00000000000
--- a/spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('reschedule_migrate_issue_trackers_data')
-
-RSpec.describe RescheduleMigrateIssueTrackersData do
- let(:services) { table(:services) }
- let(:migration_class) { Gitlab::BackgroundMigration::MigrateIssueTrackersSensitiveData }
- let(:migration_name) { migration_class.to_s.demodulize }
-
- let(:properties) do
- {
- 'url' => 'http://example.com'
- }
- end
-
- let!(:jira_integration) do
- services.create!(id: 10, type: 'JiraService', properties: properties, category: 'issue_tracker')
- end
-
- let!(:jira_integration_nil) do
- services.create!(id: 11, type: 'JiraService', properties: nil, category: 'issue_tracker')
- end
-
- let!(:bugzilla_integration) do
- services.create!(id: 12, type: 'BugzillaService', properties: properties, category: 'issue_tracker')
- end
-
- let!(:youtrack_integration) do
- services.create!(id: 13, type: 'YoutrackService', properties: properties, category: 'issue_tracker')
- end
-
- let!(:youtrack_integration_empty) do
- services.create!(id: 14, type: 'YoutrackService', properties: '', category: 'issue_tracker')
- end
-
- let!(:gitlab_service) do
- services.create!(id: 15, type: 'GitlabIssueTrackerService', properties: properties, category: 'issue_tracker')
- end
-
- let!(:gitlab_service_empty) do
- services.create!(id: 16, type: 'GitlabIssueTrackerService', properties: {}, category: 'issue_tracker')
- end
-
- let!(:other_service) do
- services.create!(id: 17, type: 'OtherService', properties: properties, category: 'other_category')
- end
-
- before do
- stub_const("#{described_class}::BATCH_SIZE", 2)
- end
-
- describe "#up" do
- it 'schedules background migrations at correct time' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(migration_name).to be_scheduled_delayed_migration(3.minutes, jira_integration.id, bugzilla_integration.id)
- expect(migration_name).to be_scheduled_delayed_migration(6.minutes, youtrack_integration.id, gitlab_service.id)
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
- end
-
- describe "#down" do
- let(:issue_tracker_data) { table(:issue_tracker_data) }
- let(:jira_tracker_data) { table(:jira_tracker_data) }
-
- let!(:valid_issue_tracker_data) do
- issue_tracker_data.create!(
- service_id: bugzilla_integration.id,
- encrypted_issues_url: 'http://url.com',
- encrypted_issues_url_iv: 'somevalue'
- )
- end
-
- let!(:invalid_issue_tracker_data) do
- issue_tracker_data.create!(
- service_id: bugzilla_integration.id,
- encrypted_issues_url: 'http:url.com',
- encrypted_issues_url_iv: nil
- )
- end
-
- let!(:valid_jira_tracker_data) do
- jira_tracker_data.create!(
- service_id: bugzilla_integration.id,
- encrypted_url: 'http://url.com',
- encrypted_url_iv: 'somevalue'
- )
- end
-
- let!(:invalid_jira_tracker_data) do
- jira_tracker_data.create!(
- service_id: bugzilla_integration.id,
- encrypted_url: 'http://url.com',
- encrypted_url_iv: nil
- )
- end
-
- it 'removes the invalid jira tracker data' do
- expect { described_class.new.down }.to change { jira_tracker_data.count }.from(2).to(1)
-
- expect(jira_tracker_data.all).to eq([valid_jira_tracker_data])
- end
-
- it 'removes the invalid issue tracker data' do
- expect { described_class.new.down }.to change { issue_tracker_data.count }.from(2).to(1)
-
- expect(issue_tracker_data.all).to eq([valid_issue_tracker_data])
- end
- end
-end
diff --git a/spec/migrations/20200313203550_remove_orphaned_chat_names_spec.rb b/spec/migrations/20200313203550_remove_orphaned_chat_names_spec.rb
deleted file mode 100644
index 6b1126ca53e..00000000000
--- a/spec/migrations/20200313203550_remove_orphaned_chat_names_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('remove_orphaned_chat_names')
-
-RSpec.describe RemoveOrphanedChatNames, schema: 20200313202430 do
- let(:projects) { table(:projects) }
- let(:namespaces) { table(:namespaces) }
- let(:services) { table(:services) }
- let(:chat_names) { table(:chat_names) }
-
- let(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
- let(:project) { projects.create!(namespace_id: namespace.id) }
- let(:service) { services.create!(project_id: project.id, type: 'chat') }
- let(:chat_name) { chat_names.create!(service_id: service.id, team_id: 'TEAM', user_id: 12345, chat_id: 12345) }
- let(:orphaned_chat_name) { chat_names.create!(team_id: 'TEAM', service_id: 0, user_id: 12345, chat_id: 12345) }
-
- it 'removes the orphaned chat_name' do
- expect(chat_name).to be_present
- expect(orphaned_chat_name).to be_present
-
- migrate!
-
- expect(chat_names.where(id: orphaned_chat_name.id)).to be_empty
- expect(chat_name.reload).to be_present
- end
-end
diff --git a/spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb b/spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb
deleted file mode 100644
index c6a512a1ec9..00000000000
--- a/spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('backfill_deployment_clusters_from_deployments')
-
-RSpec.describe BackfillDeploymentClustersFromDeployments, :migration, :sidekiq, schema: 20200227140242 do
- describe '#up' do
- it 'schedules BackfillDeploymentClustersFromDeployments background jobs' do
- stub_const("#{described_class}::BATCH_SIZE", 2)
-
- namespace = table(:namespaces).create!(name: 'the-namespace', path: 'the-path')
- project = table(:projects).create!(name: 'the-project', namespace_id: namespace.id)
- environment = table(:environments).create!(name: 'the-environment', project_id: project.id, slug: 'slug')
- cluster = table(:clusters).create!(name: 'the-cluster')
-
- deployment_data = { cluster_id: cluster.id, project_id: project.id, environment_id: environment.id, ref: 'abc', tag: false, sha: 'sha', status: 1 }
-
- # batch 1
- batch_1_begin = create_deployment(**deployment_data)
- batch_1_end = create_deployment(**deployment_data)
-
- # value that should not be included due to default scope
- create_deployment(**deployment_data, cluster_id: nil)
-
- # batch 2
- batch_2_begin = create_deployment(**deployment_data)
- batch_2_end = create_deployment(**deployment_data)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- # batch 1
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, batch_1_begin.id, batch_1_end.id)
-
- # batch 2
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, batch_2_begin.id, batch_2_end.id)
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
-
- def create_deployment(**data)
- @iid ||= 0
- @iid += 1
- table(:deployments).create!(iid: @iid, **data)
- end
- end
-end
diff --git a/spec/migrations/20200511145545_change_variable_interpolation_format_in_common_metrics_spec.rb b/spec/migrations/20200511145545_change_variable_interpolation_format_in_common_metrics_spec.rb
deleted file mode 100644
index e712e555b70..00000000000
--- a/spec/migrations/20200511145545_change_variable_interpolation_format_in_common_metrics_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('change_variable_interpolation_format_in_common_metrics')
-
-RSpec.describe ChangeVariableInterpolationFormatInCommonMetrics, :migration do
- let(:prometheus_metrics) { table(:prometheus_metrics) }
-
- let!(:common_metric) do
- prometheus_metrics.create!(
- identifier: 'system_metrics_kubernetes_container_memory_total',
- query: 'avg(sum(container_memory_usage_bytes{container_name!="POD",' \
- 'pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"})' \
- ' by (job)) without (job) /1024/1024/1024',
- project_id: nil,
- title: 'Memory Usage (Total)',
- y_label: 'Total Memory Used (GB)',
- unit: 'GB',
- legend: 'Total (GB)',
- group: -5,
- common: true
- )
- end
-
- it 'updates query to use {{}}' do
- expected_query = <<~EOS.chomp
- avg(sum(container_memory_usage_bytes{container!="POD",\
- pod=~"^{{ci_environment_slug}}-(.*)",namespace="{{kube_namespace}}"}) \
- by (job)) without (job) /1024/1024/1024 OR \
- avg(sum(container_memory_usage_bytes{container_name!="POD",\
- pod_name=~"^{{ci_environment_slug}}-(.*)",namespace="{{kube_namespace}}"}) \
- by (job)) without (job) /1024/1024/1024
- EOS
-
- migrate!
-
- expect(common_metric.reload.query).to eq(expected_query)
- end
-end
diff --git a/spec/migrations/20200526115436_dedup_mr_metrics_spec.rb b/spec/migrations/20200526115436_dedup_mr_metrics_spec.rb
deleted file mode 100644
index f16026884f5..00000000000
--- a/spec/migrations/20200526115436_dedup_mr_metrics_spec.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('dedup_mr_metrics')
-
-RSpec.describe DedupMrMetrics, :migration, schema: 20200526013844 do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:merge_requests) { table(:merge_requests) }
- let(:metrics) { table(:merge_request_metrics) }
- let(:merge_request_params) { { source_branch: 'x', target_branch: 'y', target_project_id: project.id } }
-
- let!(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
- let!(:project) { projects.create!(namespace_id: namespace.id) }
- let!(:merge_request_1) { merge_requests.create!(merge_request_params) }
- let!(:merge_request_2) { merge_requests.create!(merge_request_params) }
- let!(:merge_request_3) { merge_requests.create!(merge_request_params) }
-
- let!(:duplicated_metrics_1) { metrics.create!(merge_request_id: merge_request_1.id, latest_build_started_at: 1.day.ago, first_deployed_to_production_at: 5.days.ago, updated_at: 2.months.ago) }
- let!(:duplicated_metrics_2) { metrics.create!(merge_request_id: merge_request_1.id, latest_build_started_at: Time.now, merged_at: Time.now, updated_at: 1.month.ago) }
-
- let!(:duplicated_metrics_3) { metrics.create!(merge_request_id: merge_request_3.id, diff_size: 30, commits_count: 20, updated_at: 2.months.ago) }
- let!(:duplicated_metrics_4) { metrics.create!(merge_request_id: merge_request_3.id, added_lines: 5, commits_count: nil, updated_at: 1.month.ago) }
-
- let!(:non_duplicated_metrics) { metrics.create!(merge_request_id: merge_request_2.id, latest_build_started_at: 2.days.ago) }
-
- it 'deduplicates merge_request_metrics table' do
- expect { migrate! }.to change { metrics.count }.from(5).to(3)
- end
-
- it 'merges `duplicated_metrics_1` with `duplicated_metrics_2`' do
- migrate!
-
- expect(metrics.where(id: duplicated_metrics_1.id)).not_to exist
-
- merged_metrics = metrics.find_by(id: duplicated_metrics_2.id)
-
- expect(merged_metrics).to be_present
- expect(merged_metrics.latest_build_started_at).to be_like_time(duplicated_metrics_2.latest_build_started_at)
- expect(merged_metrics.merged_at).to be_like_time(duplicated_metrics_2.merged_at)
- expect(merged_metrics.first_deployed_to_production_at).to be_like_time(duplicated_metrics_1.first_deployed_to_production_at)
- end
-
- it 'merges `duplicated_metrics_3` with `duplicated_metrics_4`' do
- migrate!
-
- expect(metrics.where(id: duplicated_metrics_3.id)).not_to exist
-
- merged_metrics = metrics.find_by(id: duplicated_metrics_4.id)
-
- expect(merged_metrics).to be_present
- expect(merged_metrics.diff_size).to eq(duplicated_metrics_3.diff_size)
- expect(merged_metrics.commits_count).to eq(duplicated_metrics_3.commits_count)
- expect(merged_metrics.added_lines).to eq(duplicated_metrics_4.added_lines)
- end
-
- it 'does not change non duplicated records' do
- expect { migrate! }.not_to change { non_duplicated_metrics.reload.attributes }
- end
-
- it 'does nothing when there are no metrics' do
- metrics.delete_all
-
- migrate!
-
- expect(metrics.count).to eq(0)
- end
-end
diff --git a/spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb b/spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb
deleted file mode 100644
index 9b72559234e..00000000000
--- a/spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb
+++ /dev/null
@@ -1,175 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('update_index_approval_rule_name_for_code_owners_rule_type')
-
-RSpec.describe UpdateIndexApprovalRuleNameForCodeOwnersRuleType do
- let(:migration) { described_class.new }
-
- let(:approval_rules) { table(:approval_merge_request_rules) }
- let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab') }
-
- let(:project) do
- table(:projects).create!(
- namespace_id: namespace.id,
- name: 'gitlab',
- path: 'gitlab'
- )
- end
-
- let(:merge_request) do
- table(:merge_requests).create!(
- target_project_id: project.id,
- source_project_id: project.id,
- target_branch: 'feature',
- source_branch: 'master'
- )
- end
-
- let(:index_names) do
- ActiveRecord::Base.connection
- .indexes(:approval_merge_request_rules)
- .collect(&:name)
- end
-
- def create_sectional_approval_rules
- approval_rules.create!(
- merge_request_id: merge_request.id,
- name: "*.rb",
- code_owner: true,
- rule_type: 2,
- section: "First Section"
- )
-
- approval_rules.create!(
- merge_request_id: merge_request.id,
- name: "*.rb",
- code_owner: true,
- rule_type: 2,
- section: "Second Section"
- )
- end
-
- def create_two_matching_nil_section_approval_rules
- 2.times do
- approval_rules.create!(
- merge_request_id: merge_request.id,
- name: "nil_section",
- code_owner: true,
- rule_type: 2
- )
- end
- end
-
- before do
- approval_rules.delete_all
- end
-
- describe "#up" do
- it "creates the new index and removes the 'legacy' indices" do
- # Confirm that existing legacy indices prevent duplicate entries
- #
- expect { create_sectional_approval_rules }
- .to raise_exception(ActiveRecord::RecordNotUnique)
- expect { create_two_matching_nil_section_approval_rules }
- .to raise_exception(ActiveRecord::RecordNotUnique)
-
- approval_rules.delete_all
-
- disable_migrations_output { migrate! }
-
- # After running the migration, expect `section == nil` rules to still be
- # blocked by the legacy indices, but sectional rules are allowed.
- #
- expect { create_sectional_approval_rules }
- .to change { approval_rules.count }.by(2)
- expect { create_two_matching_nil_section_approval_rules }
- .to raise_exception(ActiveRecord::RecordNotUnique)
-
- # Attempt to rerun the creation of sectional rules, and see that sectional
- # rules are unique by section
- #
- expect { create_sectional_approval_rules }
- .to raise_exception(ActiveRecord::RecordNotUnique)
-
- expect(index_names).to include(
- described_class::SECTIONAL_INDEX_NAME,
- described_class::LEGACY_INDEX_NAME_RULE_TYPE,
- described_class::LEGACY_INDEX_NAME_CODE_OWNERS
- )
- end
- end
-
- describe "#down" do
- context "run as FOSS" do
- before do
- expect(Gitlab).to receive(:ee?).twice.and_return(false)
- end
-
- it "recreates legacy indices, but does not invoke EE-specific code" do
- disable_migrations_output { migrate! }
-
- expect(index_names).to include(
- described_class::SECTIONAL_INDEX_NAME,
- described_class::LEGACY_INDEX_NAME_RULE_TYPE,
- described_class::LEGACY_INDEX_NAME_CODE_OWNERS
- )
-
- # Since ApprovalMergeRequestRules are EE-specific, we expect none to be
- # deleted during the migration.
- #
- expect { disable_migrations_output { migration.down } }
- .not_to change { approval_rules.count }
-
- index_names = ActiveRecord::Base.connection
- .indexes(:approval_merge_request_rules)
- .collect(&:name)
-
- expect(index_names).not_to include(described_class::SECTIONAL_INDEX_NAME)
- expect(index_names).to include(
- described_class::LEGACY_INDEX_NAME_RULE_TYPE,
- described_class::LEGACY_INDEX_NAME_CODE_OWNERS
- )
- end
- end
-
- context "EE" do
- it "recreates 'legacy' indices and removes duplicate code owner approval rules" do
- skip("This test is skipped under FOSS") unless Gitlab.ee?
-
- disable_migrations_output { migrate! }
-
- expect { create_sectional_approval_rules }
- .to change { approval_rules.count }.by(2)
- expect { create_two_matching_nil_section_approval_rules }
- .to raise_exception(ActiveRecord::RecordNotUnique)
-
- expect(MergeRequests::SyncCodeOwnerApprovalRules)
- .to receive(:new).with(MergeRequest.find(merge_request.id)).once.and_call_original
-
- # Run the down migration. This will remove the 3 approval rules we create
- # above, and call MergeRequests::SyncCodeOwnerApprovalRules to recreate
- # new ones. However, as there is no CODEOWNERS file in this test
- # context, no approval rules will be created, so we can expect
- # approval_rules.count to be changed by -3.
- #
- expect { disable_migrations_output { migration.down } }
- .to change { approval_rules.count }.by(-3)
-
- # Test that the index does not allow us to create the same rules as the
- # previous sectional index.
- #
- expect { create_sectional_approval_rules }
- .to raise_exception(ActiveRecord::RecordNotUnique)
- expect { create_two_matching_nil_section_approval_rules }
- .to raise_exception(ActiveRecord::RecordNotUnique)
-
- expect(index_names).not_to include(described_class::SECTIONAL_INDEX_NAME)
- expect(index_names).to include(
- described_class::LEGACY_INDEX_NAME_RULE_TYPE,
- described_class::LEGACY_INDEX_NAME_CODE_OWNERS
- )
- end
- end
- end
-end
diff --git a/spec/migrations/20200703125016_backfill_namespace_settings_spec.rb b/spec/migrations/20200703125016_backfill_namespace_settings_spec.rb
deleted file mode 100644
index c9f7a66a0b9..00000000000
--- a/spec/migrations/20200703125016_backfill_namespace_settings_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('backfill_namespace_settings')
-
-RSpec.describe BackfillNamespaceSettings, :sidekiq, schema: 20200703124823 do
- let(:namespaces) { table(:namespaces) }
-
- describe '#up' do
- before do
- stub_const("#{described_class}::BATCH_SIZE", 2)
-
- namespaces.create!(id: 1, name: 'test1', path: 'test1')
- namespaces.create!(id: 2, name: 'test2', path: 'test2')
- namespaces.create!(id: 3, name: 'test3', path: 'test3')
- end
-
- it 'schedules BackfillNamespaceSettings background jobs' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 1, 2)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, 3, 3)
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
- end
-end
diff --git a/spec/migrations/20200706035141_adjust_unique_index_alert_management_alerts_spec.rb b/spec/migrations/20200706035141_adjust_unique_index_alert_management_alerts_spec.rb
deleted file mode 100644
index 121b1729dd2..00000000000
--- a/spec/migrations/20200706035141_adjust_unique_index_alert_management_alerts_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('adjust_unique_index_alert_management_alerts')
-
-RSpec.describe AdjustUniqueIndexAlertManagementAlerts, :migration do
- let(:migration) { described_class.new }
- let(:alerts) { AlertManagement::Alert }
- let(:project) { create_project }
- let(:other_project) { create_project }
- let(:resolved_state) { 2 }
- let(:triggered_state) { 1 }
- let!(:existing_alert) { create_alert(project, resolved_state, '1234', 1) }
- let!(:p2_alert) { create_alert(other_project, resolved_state, '1234', 1) }
- let!(:p2_alert_diff_fingerprint) { create_alert(other_project, resolved_state, '4567', 2) }
-
- it 'can reverse the migration' do
- expect(existing_alert.fingerprint).not_to eq(nil)
- expect(p2_alert.fingerprint).not_to eq(nil)
- expect(p2_alert_diff_fingerprint.fingerprint).not_to eq(nil)
-
- migrate!
-
- # Adding a second alert with the same fingerprint now that we can
- second_alert = create_alert(project, triggered_state, '1234', 2)
- expect(alerts.count).to eq(4)
-
- schema_migrate_down!
-
- # We keep the alerts, but the oldest ones fingerprint is removed
- expect(alerts.count).to eq(4)
- expect(second_alert.reload.fingerprint).not_to eq(nil)
- expect(p2_alert.fingerprint).not_to eq(nil)
- expect(p2_alert_diff_fingerprint.fingerprint).not_to eq(nil)
- expect(existing_alert.reload.fingerprint).to eq(nil)
- end
-
- def namespace
- @namespace ||= table(:namespaces).create!(name: 'foo', path: 'foo')
- end
-
- def create_project
- table(:projects).create!(namespace_id: namespace.id)
- end
-
- def create_alert(project, status, fingerprint, iid)
- params = {
- title: 'test',
- started_at: Time.current,
- iid: iid,
- project_id: project.id,
- status: status,
- fingerprint: fingerprint
- }
- table(:alert_management_alerts).create!(params)
- end
-end
diff --git a/spec/migrations/20200728080250_replace_unique_index_on_cycle_analytics_stages_spec.rb b/spec/migrations/20200728080250_replace_unique_index_on_cycle_analytics_stages_spec.rb
deleted file mode 100644
index a632065946d..00000000000
--- a/spec/migrations/20200728080250_replace_unique_index_on_cycle_analytics_stages_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('replace_unique_index_on_cycle_analytics_stages')
-
-RSpec.describe ReplaceUniqueIndexOnCycleAnalyticsStages, :migration, schema: 20200727142337 do
- let(:namespaces) { table(:namespaces) }
- let(:group_value_streams) { table(:analytics_cycle_analytics_group_value_streams) }
- let(:group_stages) { table(:analytics_cycle_analytics_group_stages) }
-
- let(:group) { namespaces.create!(type: 'Group', name: 'test', path: 'test') }
-
- let(:value_stream_1) { group_value_streams.create!(group_id: group.id, name: 'vs1') }
- let(:value_stream_2) { group_value_streams.create!(group_id: group.id, name: 'vs2') }
-
- let(:duplicated_stage_1) { group_stages.create!(group_id: group.id, group_value_stream_id: value_stream_1.id, name: 'stage', start_event_identifier: 1, end_event_identifier: 1) }
- let(:duplicated_stage_2) { group_stages.create!(group_id: group.id, group_value_stream_id: value_stream_2.id, name: 'stage', start_event_identifier: 1, end_event_identifier: 1) }
-
- let(:stage_record) { group_stages.create!(group_id: group.id, group_value_stream_id: value_stream_2.id, name: 'other stage', start_event_identifier: 1, end_event_identifier: 1) }
-
- describe '#down' do
- subject { described_class.new.down }
-
- before do
- described_class.new.up
-
- duplicated_stage_1
- duplicated_stage_2
- stage_record
- end
-
- it 'removes duplicated stage records' do
- subject
-
- stage = group_stages.find_by_id(duplicated_stage_2.id)
- expect(stage).to be_nil
- end
-
- it 'does not change the first duplicated stage record' do
- expect { subject }.not_to change { duplicated_stage_1.reload.attributes }
- end
-
- it 'does not change not duplicated stage record' do
- expect { subject }.not_to change { stage_record.reload.attributes }
- end
- end
-end
diff --git a/spec/migrations/20200728182311_add_o_auth_paths_to_protected_paths_spec.rb b/spec/migrations/20200728182311_add_o_auth_paths_to_protected_paths_spec.rb
deleted file mode 100644
index 5c65d45c6e0..00000000000
--- a/spec/migrations/20200728182311_add_o_auth_paths_to_protected_paths_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('add_o_auth_paths_to_protected_paths')
-
-RSpec.describe AddOAuthPathsToProtectedPaths do
- subject(:migration) { described_class.new }
-
- let(:application_settings) { table(:application_settings) }
- let(:new_paths) do
- [
- '/oauth/authorize',
- '/oauth/token'
- ]
- end
-
- it 'appends new OAuth paths' do
- application_settings.create!
-
- protected_paths_before = application_settings.first.protected_paths
- protected_paths_after = protected_paths_before + new_paths
-
- expect { migrate! }.to change { application_settings.first.protected_paths }.from(protected_paths_before).to(protected_paths_after)
- end
-
- it 'new default includes new paths' do
- settings_before = application_settings.create!
-
- expect(settings_before.protected_paths).not_to include(*new_paths)
-
- migrate!
-
- application_settings.reset_column_information
- settings_after = application_settings.create!
-
- expect(settings_after.protected_paths).to include(*new_paths)
- end
-
- it 'does not change the value when the new paths are already included' do
- application_settings.create!(protected_paths: %w(/users/sign_in /users/password) + new_paths)
-
- expect { migrate! }.not_to change { application_settings.first.protected_paths }
- end
-
- it 'adds one value when the other is already present' do
- application_settings.create!(protected_paths: %W(/users/sign_in /users/password #{new_paths.first}))
-
- migrate!
-
- expect(application_settings.first.protected_paths).to include(new_paths.second)
- end
-end
diff --git a/spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb b/spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb
deleted file mode 100644
index d166ff3617b..00000000000
--- a/spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb
+++ /dev/null
@@ -1,160 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-require_migration!('create_missing_vulnerabilities_issue_links')
-
-RSpec.describe CreateMissingVulnerabilitiesIssueLinks, :migration do
- let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
- let(:users) { table(:users) }
- let(:user) { create_user! }
- let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
- let(:scanners) { table(:vulnerability_scanners) }
- let(:scanner) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
- let(:different_scanner) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') }
- let(:issues) { table(:issues) }
- let(:issue1) { issues.create!(id: 123, project_id: project.id) }
- let(:issue2) { issues.create!(id: 124, project_id: project.id) }
- let(:issue3) { issues.create!(id: 125, project_id: project.id) }
- let(:vulnerabilities) { table(:vulnerabilities) }
- let(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
- let(:vulnerability_feedback) { table(:vulnerability_feedback) }
- let(:vulnerability_issue_links) { table(:vulnerability_issue_links) }
- let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
- let(:vulnerability_identifier) { vulnerability_identifiers.create!(project_id: project.id, external_type: 'test 1', external_id: 'test 1', fingerprint: 'test 1', name: 'test 1') }
- let(:different_vulnerability_identifier) { vulnerability_identifiers.create!(project_id: project.id, external_type: 'test 2', external_id: 'test 2', fingerprint: 'test 2', name: 'test 2') }
-
- let!(:vulnerability) do
- create_vulnerability!(
- project_id: project.id,
- author_id: user.id
- )
- end
-
- before do
- create_finding!(
- vulnerability_id: vulnerability.id,
- project_id: project.id,
- scanner_id: scanner.id,
- primary_identifier_id: vulnerability_identifier.id
- )
- create_feedback!(
- issue_id: issue1.id,
- project_id: project.id,
- author_id: user.id
- )
-
- # Create a finding with no vulnerability_id
- # https://gitlab.com/gitlab-com/gl-infra/production/-/issues/2539
- create_finding!(
- vulnerability_id: nil,
- project_id: project.id,
- scanner_id: different_scanner.id,
- primary_identifier_id: different_vulnerability_identifier.id,
- location_fingerprint: 'somewhereinspace',
- uuid: 'test2'
- )
- create_feedback!(
- category: 2,
- issue_id: issue2.id,
- project_id: project.id,
- author_id: user.id
- )
- end
-
- context 'with no Vulnerabilities::IssueLinks present' do
- it 'creates missing Vulnerabilities::IssueLinks' do
- expect(vulnerability_issue_links.count).to eq(0)
-
- migrate!
-
- expect(vulnerability_issue_links.count).to eq(1)
- end
- end
-
- context 'when an Vulnerabilities::IssueLink already exists' do
- before do
- vulnerability_issue_links.create!(vulnerability_id: vulnerability.id, issue_id: issue1.id)
- end
-
- it 'creates no duplicates' do
- expect(vulnerability_issue_links.count).to eq(1)
-
- migrate!
-
- expect(vulnerability_issue_links.count).to eq(1)
- end
- end
-
- context 'when an Vulnerabilities::IssueLink of type created already exists' do
- before do
- vulnerability_issue_links.create!(vulnerability_id: vulnerability.id, issue_id: issue3.id, link_type: 2)
- end
-
- it 'creates no duplicates' do
- expect(vulnerability_issue_links.count).to eq(1)
-
- migrate!
-
- expect(vulnerability_issue_links.count).to eq(1)
- end
- end
-
- private
-
- def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
- vulnerabilities.create!(
- project_id: project_id,
- author_id: author_id,
- title: title,
- severity: severity,
- confidence: confidence,
- report_type: report_type
- )
- end
-
- # rubocop:disable Metrics/ParameterLists
- def create_finding!(
- vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:,
- name: "test", severity: 7, confidence: 7, report_type: 0,
- project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
- metadata_version: 'test', raw_metadata: 'test', uuid: 'test')
- vulnerabilities_findings.create!(
- vulnerability_id: vulnerability_id,
- project_id: project_id,
- name: name,
- severity: severity,
- confidence: confidence,
- report_type: report_type,
- project_fingerprint: project_fingerprint,
- scanner_id: scanner.id,
- primary_identifier_id: vulnerability_identifier.id,
- location_fingerprint: location_fingerprint,
- metadata_version: metadata_version,
- raw_metadata: raw_metadata,
- uuid: uuid
- )
- end
- # rubocop:enable Metrics/ParameterLists
-
- # project_fingerprint on Vulnerabilities::Finding is a bytea and we need to match this
- def create_feedback!(issue_id:, project_id:, author_id:, feedback_type: 1, category: 0, project_fingerprint: '3132337177656173647a7863')
- vulnerability_feedback.create!(
- feedback_type: feedback_type,
- issue_id: issue_id,
- category: category,
- project_fingerprint: project_fingerprint,
- project_id: project_id,
- author_id: author_id
- )
- end
-
- def create_user!(name: "Example User", email: "user@example.com", user_type: nil, created_at: Time.now, confirmed_at: Time.now)
- users.create!(
- name: name,
- email: email,
- username: name,
- projects_limit: 0,
- user_type: user_type,
- confirmed_at: confirmed_at
- )
- end
-end
diff --git a/spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb b/spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb
deleted file mode 100644
index 69f7525d265..00000000000
--- a/spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('schedule_migration_to_hashed_storage')
-
-RSpec.describe ScheduleMigrationToHashedStorage, :sidekiq do
- describe '#up' do
- it 'schedules background migration job' do
- Sidekiq::Testing.fake! do
- expect { migrate! }.to change { BackgroundMigrationWorker.jobs.size }.by(1)
- end
- end
- end
-end
diff --git a/spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb b/spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb
deleted file mode 100644
index 34bd8f1c869..00000000000
--- a/spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('create_initial_versions_for_pre_versioning_terraform_states')
-
-RSpec.describe CreateInitialVersionsForPreVersioningTerraformStates do
- let(:namespace) { table(:namespaces).create!(name: 'terraform', path: 'terraform') }
- let(:project) { table(:projects).create!(id: 1, namespace_id: namespace.id) }
- let(:terraform_state_versions) { table(:terraform_state_versions) }
-
- def create_state!(project, versioning_enabled:)
- table(:terraform_states).create!(
- project_id: project.id,
- uuid: 'uuid',
- file_store: 2,
- file: 'state.tfstate',
- versioning_enabled: versioning_enabled
- )
- end
-
- describe '#up' do
- context 'for a state that is already versioned' do
- let!(:terraform_state) { create_state!(project, versioning_enabled: true) }
-
- it 'does not insert a version record' do
- expect { migrate! }.not_to change { terraform_state_versions.count }
- end
- end
-
- context 'for a state that is not yet versioned' do
- let!(:terraform_state) { create_state!(project, versioning_enabled: false) }
-
- it 'creates a version using the current state data' do
- expect { migrate! }.to change { terraform_state_versions.count }.by(1)
-
- migrated_version = terraform_state_versions.last
- expect(migrated_version.terraform_state_id).to eq(terraform_state.id)
- expect(migrated_version.version).to be_zero
- expect(migrated_version.file_store).to eq(terraform_state.file_store)
- expect(migrated_version.file).to eq(terraform_state.file)
- expect(migrated_version.created_at).to be_present
- expect(migrated_version.updated_at).to be_present
- end
- end
- end
-end
diff --git a/spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb b/spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb
deleted file mode 100644
index ef9bc5788c1..00000000000
--- a/spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('drop_backfill_jira_tracker_deployment_type_jobs')
-
-RSpec.describe DropBackfillJiraTrackerDeploymentTypeJobs, :sidekiq, :redis, schema: 2020_10_14_205300 do
- subject(:migration) { described_class.new }
-
- describe '#up' do
- let(:retry_set) { Sidekiq::RetrySet.new }
- let(:scheduled_set) { Sidekiq::ScheduledSet.new }
-
- context 'there are only affected jobs on the queue' do
- let(:payload) { { 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1] } }
- let(:queue_payload) { payload.merge('queue' => described_class::QUEUE) }
-
- it 'removes enqueued BackfillJiraTrackerDeploymentType background jobs' do
- Sidekiq::Testing.disable! do # https://github.com/mperham/sidekiq/wiki/testing#api Sidekiq's API does not have a testing mode
- retry_set.schedule(1.hour.from_now, payload)
- scheduled_set.schedule(1.hour.from_now, payload)
- Sidekiq::Client.push(queue_payload)
-
- expect { migration.up }.to change { Sidekiq::Queue.new(described_class::QUEUE).size }.from(1).to(0)
- expect(retry_set.size).to eq(0)
- expect(scheduled_set.size).to eq(0)
- end
- end
- end
-
- context 'there are not any affected jobs on the queue' do
- let(:payload) { { 'class' => ::BackgroundMigrationWorker, 'args' => ['SomeOtherClass', 1] } }
- let(:queue_payload) { payload.merge('queue' => described_class::QUEUE) }
-
- it 'skips other enqueued jobs' do
- Sidekiq::Testing.disable! do
- retry_set.schedule(1.hour.from_now, payload)
- scheduled_set.schedule(1.hour.from_now, payload)
- Sidekiq::Client.push(queue_payload)
-
- expect { migration.up }.not_to change { Sidekiq::Queue.new(described_class::QUEUE).size }
- expect(retry_set.size).to eq(1)
- expect(scheduled_set.size).to eq(1)
- end
- end
- end
-
- context 'other queues' do
- it 'does not modify them' do
- Sidekiq::Testing.disable! do
- Sidekiq::Client.push('queue' => 'other', 'class' => ::BackgroundMigrationWorker, 'args' => ['SomeOtherClass', 1])
- Sidekiq::Client.push('queue' => 'other', 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1])
-
- expect { migration.up }.not_to change { Sidekiq::Queue.new('other').size }
- end
- end
- end
- end
-end
diff --git a/spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb b/spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb
deleted file mode 100644
index f9f6cd9589c..00000000000
--- a/spec/migrations/20201027002551_migrate_services_to_http_integrations_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('migrate_services_to_http_integrations')
-
-RSpec.describe MigrateServicesToHttpIntegrations do
- let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
- let!(:project) { table(:projects).create!(id: 1, namespace_id: namespace.id) }
- let!(:alert_service) { table(:services).create!(type: 'AlertsService', project_id: project.id, active: true) }
- let!(:alert_service_data) { table(:alerts_service_data).create!(service_id: alert_service.id, encrypted_token: 'test', encrypted_token_iv: 'test')}
- let(:http_integrations) { table(:alert_management_http_integrations) }
-
- describe '#up' do
- it 'creates the http integrations from the alert services', :aggregate_failures do
- expect { migrate! }.to change { http_integrations.count }.by(1)
-
- http_integration = http_integrations.last
- expect(http_integration.project_id).to eq(alert_service.project_id)
- expect(http_integration.encrypted_token).to eq(alert_service_data.encrypted_token)
- expect(http_integration.encrypted_token_iv).to eq(alert_service_data.encrypted_token_iv)
- expect(http_integration.active).to eq(alert_service.active)
- expect(http_integration.name).to eq(described_class::SERVICE_NAMES_IDENTIFIER[:name])
- expect(http_integration.endpoint_identifier).to eq(described_class::SERVICE_NAMES_IDENTIFIER[:identifier])
- end
- end
-end
diff --git a/spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb b/spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb
deleted file mode 100644
index 0746ad7e44f..00000000000
--- a/spec/migrations/20201028182809_backfill_jira_tracker_deployment_type2_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('backfill_jira_tracker_deployment_type2')
-
-RSpec.describe BackfillJiraTrackerDeploymentType2, :sidekiq, schema: 20201028182809 do
- let(:services) { table(:services) }
- let(:jira_tracker_data) { table(:jira_tracker_data) }
- let(:migration) { described_class.new }
- let(:batch_interval) { described_class::DELAY_INTERVAL }
-
- describe '#up' do
- before do
- stub_const("#{described_class}::BATCH_SIZE", 2)
-
- active_service = services.create!(type: 'JiraService', active: true)
- inactive_service = services.create!(type: 'JiraService', active: false)
-
- jira_tracker_data.create!(id: 1, service_id: active_service.id, deployment_type: 0)
- jira_tracker_data.create!(id: 2, service_id: active_service.id, deployment_type: 1)
- jira_tracker_data.create!(id: 3, service_id: inactive_service.id, deployment_type: 2)
- jira_tracker_data.create!(id: 4, service_id: inactive_service.id, deployment_type: 0)
- jira_tracker_data.create!(id: 5, service_id: active_service.id, deployment_type: 0)
- end
-
- it 'schedules BackfillJiraTrackerDeploymentType2 background jobs' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migration.up
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(batch_interval, 1, 4)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(batch_interval * 2, 5, 5)
- end
- end
- end
- end
-end
diff --git a/spec/migrations/20201110161542_cleanup_transfered_projects_shared_runners_spec.rb b/spec/migrations/20201110161542_cleanup_transfered_projects_shared_runners_spec.rb
deleted file mode 100644
index 7a79406ac80..00000000000
--- a/spec/migrations/20201110161542_cleanup_transfered_projects_shared_runners_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('cleanup_transfered_projects_shared_runners')
-
-RSpec.describe CleanupTransferedProjectsSharedRunners, :sidekiq, schema: 20201110161542 do
- let(:namespaces) { table(:namespaces) }
- let(:migration) { described_class.new }
- let(:batch_interval) { described_class::INTERVAL }
-
- let!(:namespace_1) { namespaces.create!(name: 'foo', path: 'foo') }
- let!(:namespace_2) { namespaces.create!(name: 'bar', path: 'bar') }
- let!(:namespace_3) { namespaces.create!(name: 'baz', path: 'baz') }
-
- describe '#up' do
- before do
- stub_const("#{described_class}::BATCH_SIZE", 2)
- end
-
- it 'schedules ResetSharedRunnersForTransferredProjects background jobs' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migration.up
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(batch_interval, namespace_1.id, namespace_2.id)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(batch_interval * 2, namespace_3.id, namespace_3.id)
- end
- end
- end
- end
-end
diff --git a/spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb b/spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb
deleted file mode 100644
index 92a716c355b..00000000000
--- a/spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb
+++ /dev/null
@@ -1,140 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-require_migration!('schedule_remove_duplicate_vulnerabilities_findings')
-
-RSpec.describe ScheduleRemoveDuplicateVulnerabilitiesFindings, :migration do
- let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
- let(:users) { table(:users) }
- let(:user) { create_user! }
- let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
- let(:scanners) { table(:vulnerability_scanners) }
- let!(:scanner) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
- let!(:scanner2) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') }
- let!(:scanner3) { scanners.create!(project_id: project.id, external_id: 'test 3', name: 'test scanner 3') }
- let!(:unrelated_scanner) { scanners.create!(project_id: project.id, external_id: 'unreleated_scanner', name: 'unrelated scanner') }
- let(:vulnerabilities) { table(:vulnerabilities) }
- let(:vulnerability_findings) { table(:vulnerability_occurrences) }
- let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
- let(:vulnerability_identifier) do
- vulnerability_identifiers.create!(
- project_id: project.id,
- external_type: 'vulnerability-identifier',
- external_id: 'vulnerability-identifier',
- fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
- name: 'vulnerability identifier')
- end
-
- let!(:first_finding) do
- create_finding!(
- uuid: "test1",
- vulnerability_id: nil,
- report_type: 0,
- location_fingerprint: '2bda3014914481791847d8eca38d1a8d13b6ad76',
- primary_identifier_id: vulnerability_identifier.id,
- scanner_id: scanner.id,
- project_id: project.id
- )
- end
-
- let!(:first_duplicate) do
- create_finding!(
- uuid: "test2",
- vulnerability_id: nil,
- report_type: 0,
- location_fingerprint: '2bda3014914481791847d8eca38d1a8d13b6ad76',
- primary_identifier_id: vulnerability_identifier.id,
- scanner_id: scanner2.id,
- project_id: project.id
- )
- end
-
- let!(:second_duplicate) do
- create_finding!(
- uuid: "test3",
- vulnerability_id: nil,
- report_type: 0,
- location_fingerprint: '2bda3014914481791847d8eca38d1a8d13b6ad76',
- primary_identifier_id: vulnerability_identifier.id,
- scanner_id: scanner3.id,
- project_id: project.id
- )
- end
-
- let!(:unrelated_finding) do
- create_finding!(
- uuid: "unreleated_finding",
- vulnerability_id: nil,
- report_type: 1,
- location_fingerprint: 'random_location_fingerprint',
- primary_identifier_id: vulnerability_identifier.id,
- scanner_id: unrelated_scanner.id,
- project_id: project.id
- )
- end
-
- before do
- stub_const("#{described_class}::BATCH_SIZE", 1)
- end
-
- around do |example|
- freeze_time { Sidekiq::Testing.fake! { example.run } }
- end
-
- it 'schedules background migration' do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(4)
- expect(described_class::MIGRATION).to be_scheduled_migration(first_finding.id, first_finding.id)
- expect(described_class::MIGRATION).to be_scheduled_migration(first_duplicate.id, first_duplicate.id)
- expect(described_class::MIGRATION).to be_scheduled_migration(second_duplicate.id, second_duplicate.id)
- expect(described_class::MIGRATION).to be_scheduled_migration(unrelated_finding.id, unrelated_finding.id)
- end
-
- private
-
- def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
- vulnerabilities.create!(
- project_id: project_id,
- author_id: author_id,
- title: title,
- severity: severity,
- confidence: confidence,
- report_type: report_type
- )
- end
-
- # rubocop:disable Metrics/ParameterLists
- def create_finding!(
- vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:,
- name: "test", severity: 7, confidence: 7, report_type: 0,
- project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
- metadata_version: 'test', raw_metadata: 'test', uuid: 'test')
- vulnerability_findings.create!(
- vulnerability_id: vulnerability_id,
- project_id: project_id,
- name: name,
- severity: severity,
- confidence: confidence,
- report_type: report_type,
- project_fingerprint: project_fingerprint,
- scanner_id: scanner_id,
- primary_identifier_id: vulnerability_identifier.id,
- location_fingerprint: location_fingerprint,
- metadata_version: metadata_version,
- raw_metadata: raw_metadata,
- uuid: uuid
- )
- end
- # rubocop:enable Metrics/ParameterLists
-
- def create_user!(name: "Example User", email: "user@example.com", user_type: nil, created_at: Time.now, confirmed_at: Time.now)
- users.create!(
- name: name,
- email: email,
- username: name,
- projects_limit: 0,
- user_type: user_type,
- confirmed_at: confirmed_at
- )
- end
-end
diff --git a/spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb b/spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb
deleted file mode 100644
index dda919d70d9..00000000000
--- a/spec/migrations/20201112130715_schedule_recalculate_uuid_on_vulnerabilities_occurrences_spec.rb
+++ /dev/null
@@ -1,138 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('schedule_recalculate_uuid_on_vulnerabilities_occurrences')
-
-RSpec.describe ScheduleRecalculateUuidOnVulnerabilitiesOccurrences, :migration do
- let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
- let(:users) { table(:users) }
- let(:user) { create_user! }
- let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
- let(:scanners) { table(:vulnerability_scanners) }
- let(:scanner) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
- let(:different_scanner) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') }
- let(:vulnerabilities) { table(:vulnerabilities) }
- let(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
- let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
- let(:vulnerability_identifier) do
- vulnerability_identifiers.create!(
- project_id: project.id,
- external_type: 'uuid-v5',
- external_id: 'uuid-v5',
- fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
- name: 'Identifier for UUIDv5')
- end
-
- let(:different_vulnerability_identifier) do
- vulnerability_identifiers.create!(
- project_id: project.id,
- external_type: 'uuid-v4',
- external_id: 'uuid-v4',
- fingerprint: '772da93d34a1ba010bcb5efa9fb6f8e01bafcc89',
- name: 'Identifier for UUIDv4')
- end
-
- let!(:vulnerability_for_uuidv4) do
- create_vulnerability!(
- project_id: project.id,
- author_id: user.id
- )
- end
-
- let!(:vulnerability_for_uuidv5) do
- create_vulnerability!(
- project_id: project.id,
- author_id: user.id
- )
- end
-
- let(:known_uuid_v4) { "b3cc2518-5446-4dea-871c-89d5e999c1ac" }
- let!(:finding_with_uuid_v4) do
- create_finding!(
- vulnerability_id: vulnerability_for_uuidv4.id,
- project_id: project.id,
- scanner_id: different_scanner.id,
- primary_identifier_id: different_vulnerability_identifier.id,
- report_type: 0, # "sast"
- location_fingerprint: "fa18f432f1d56675f4098d318739c3cd5b14eb3e",
- uuid: known_uuid_v4
- )
- end
-
- let(:known_uuid_v5) { "e7d3d99d-04bb-5771-bb44-d80a9702d0a2" }
- let!(:finding_with_uuid_v5) do
- create_finding!(
- vulnerability_id: vulnerability_for_uuidv5.id,
- project_id: project.id,
- scanner_id: scanner.id,
- primary_identifier_id: vulnerability_identifier.id,
- report_type: 0, # "sast"
- location_fingerprint: "838574be0210968bf6b9f569df9c2576242cbf0a",
- uuid: known_uuid_v5
- )
- end
-
- before do
- stub_const("#{described_class}::BATCH_SIZE", 1)
- end
-
- around do |example|
- freeze_time { Sidekiq::Testing.fake! { example.run } }
- end
-
- it 'schedules background migration' do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- expect(described_class::MIGRATION).to be_scheduled_migration(finding_with_uuid_v4.id, finding_with_uuid_v4.id)
- expect(described_class::MIGRATION).to be_scheduled_migration(finding_with_uuid_v5.id, finding_with_uuid_v5.id)
- end
-
- private
-
- def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
- vulnerabilities.create!(
- project_id: project_id,
- author_id: author_id,
- title: title,
- severity: severity,
- confidence: confidence,
- report_type: report_type
- )
- end
-
- # rubocop:disable Metrics/ParameterLists
- def create_finding!(
- vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:,
- name: "test", severity: 7, confidence: 7, report_type: 0,
- project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
- metadata_version: 'test', raw_metadata: 'test', uuid: 'test')
- vulnerabilities_findings.create!(
- vulnerability_id: vulnerability_id,
- project_id: project_id,
- name: name,
- severity: severity,
- confidence: confidence,
- report_type: report_type,
- project_fingerprint: project_fingerprint,
- scanner_id: scanner.id,
- primary_identifier_id: vulnerability_identifier.id,
- location_fingerprint: location_fingerprint,
- metadata_version: metadata_version,
- raw_metadata: raw_metadata,
- uuid: uuid
- )
- end
- # rubocop:enable Metrics/ParameterLists
-
- def create_user!(name: "Example User", email: "user@example.com", user_type: nil, created_at: Time.now, confirmed_at: Time.now)
- users.create!(
- name: name,
- email: email,
- username: name,
- projects_limit: 0,
- user_type: user_type,
- confirmed_at: confirmed_at
- )
- end
-end
diff --git a/spec/migrations/20210112143418_remove_duplicate_services2_spec.rb b/spec/migrations/20210112143418_remove_duplicate_services2_spec.rb
index 289416c22cf..b8dc4d7c8ae 100644
--- a/spec/migrations/20210112143418_remove_duplicate_services2_spec.rb
+++ b/spec/migrations/20210112143418_remove_duplicate_services2_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('remove_duplicate_services2')
+require_migration!
RSpec.describe RemoveDuplicateServices2 do
let_it_be(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb b/spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb
index 469dbb4f946..e07b5a48909 100644
--- a/spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb
+++ b/spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('alter_vsa_issue_first_mentioned_in_commit_value')
+require_migration!
RSpec.describe AlterVsaIssueFirstMentionedInCommitValue, schema: 20210114033715 do
let(:group_stages) { table(:analytics_cycle_analytics_group_stages) }
diff --git a/spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb b/spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb
index cb48df20d58..97438062458 100644
--- a/spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb
+++ b/spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('remove_bad_dependency_proxy_manifests')
+require_migration!
RSpec.describe RemoveBadDependencyProxyManifests, schema: 20210128140157 do
let_it_be(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb b/spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb
index 1932bc00cee..4a31d36e2bc 100644
--- a/spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb
+++ b/spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('backfill_updated_at_after_repository_storage_move')
+require_migration!
RSpec.describe BackfillUpdatedAtAfterRepositoryStorageMove, :sidekiq do
let_it_be(:projects) { table(:projects) }
diff --git a/spec/migrations/20210218040814_add_environment_scope_to_group_variables_spec.rb b/spec/migrations/20210218040814_add_environment_scope_to_group_variables_spec.rb
index e525101f3a0..039ce53cac4 100644
--- a/spec/migrations/20210218040814_add_environment_scope_to_group_variables_spec.rb
+++ b/spec/migrations/20210218040814_add_environment_scope_to_group_variables_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('add_environment_scope_to_group_variables')
+require_migration!
RSpec.describe AddEnvironmentScopeToGroupVariables do
let(:migration) { described_class.new }
diff --git a/spec/migrations/20210226141517_dedup_issue_metrics_spec.rb b/spec/migrations/20210226141517_dedup_issue_metrics_spec.rb
index 6068df85e2e..1b57bf0431f 100644
--- a/spec/migrations/20210226141517_dedup_issue_metrics_spec.rb
+++ b/spec/migrations/20210226141517_dedup_issue_metrics_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('dedup_issue_metrics')
+require_migration!
RSpec.describe DedupIssueMetrics, :migration, schema: 20210205104425 do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb b/spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb
index 94ed2320c50..1f18f7e581a 100644
--- a/spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb
+++ b/spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('backfill_total_tuple_count_for_batched_migrations')
+require_migration!
RSpec.describe BackfillTotalTupleCountForBatchedMigrations, :migration, schema: 20210406140057 do
let_it_be(:table_name) { 'projects' }
diff --git a/spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb b/spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb
index 78b6a71c609..e1dc7487222 100644
--- a/spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb
+++ b/spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require_migration!('reschedule_artifact_expiry_backfill_again')
+require_migration!
RSpec.describe RescheduleArtifactExpiryBackfillAgain, :migration do
let(:migration_class) { Gitlab::BackgroundMigration::BackfillArtifactExpiryDate }
diff --git a/spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb b/spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb
index ea0a16212dd..9a59c739ecd 100644
--- a/spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb
+++ b/spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('schedule_update_jira_tracker_data_deployment_type_based_on_url')
+require_migration!
RSpec.describe ScheduleUpdateJiraTrackerDataDeploymentTypeBasedOnUrl, :migration do
let(:services_table) { table(:services) }
diff --git a/spec/migrations/20210423160427_schedule_drop_invalid_vulnerabilities_spec.rb b/spec/migrations/20210423160427_schedule_drop_invalid_vulnerabilities_spec.rb
index 3b462c884c4..faf440eb117 100644
--- a/spec/migrations/20210423160427_schedule_drop_invalid_vulnerabilities_spec.rb
+++ b/spec/migrations/20210423160427_schedule_drop_invalid_vulnerabilities_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('schedule_drop_invalid_vulnerabilities')
+require_migration!
RSpec.describe ScheduleDropInvalidVulnerabilities, :migration do
let_it_be(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
diff --git a/spec/migrations/20210430134202_copy_adoption_snapshot_namespace_spec.rb b/spec/migrations/20210430134202_copy_adoption_snapshot_namespace_spec.rb
index 03ce0a430e5..598da495195 100644
--- a/spec/migrations/20210430134202_copy_adoption_snapshot_namespace_spec.rb
+++ b/spec/migrations/20210430134202_copy_adoption_snapshot_namespace_spec.rb
@@ -2,7 +2,7 @@
#
require 'spec_helper'
-require_migration!('copy_adoption_snapshot_namespace')
+require_migration!
RSpec.describe CopyAdoptionSnapshotNamespace, :migration, schema: 20210430124630 do
let(:namespaces_table) { table(:namespaces) }
diff --git a/spec/migrations/20210430135954_copy_adoption_segments_namespace_spec.rb b/spec/migrations/20210430135954_copy_adoption_segments_namespace_spec.rb
index abdfd03f97e..25dfaa2e314 100644
--- a/spec/migrations/20210430135954_copy_adoption_segments_namespace_spec.rb
+++ b/spec/migrations/20210430135954_copy_adoption_segments_namespace_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require_migration!('copy_adoption_segments_namespace')
+require_migration!
RSpec.describe CopyAdoptionSegmentsNamespace, :migration do
let(:namespaces_table) { table(:namespaces) }
diff --git a/spec/migrations/20210503105845_add_project_value_stream_id_to_project_stages_spec.rb b/spec/migrations/20210503105845_add_project_value_stream_id_to_project_stages_spec.rb
index 4969d82d183..187b9115ba7 100644
--- a/spec/migrations/20210503105845_add_project_value_stream_id_to_project_stages_spec.rb
+++ b/spec/migrations/20210503105845_add_project_value_stream_id_to_project_stages_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require_migration!('add_project_value_stream_id_to_project_stages')
+require_migration!
RSpec.describe AddProjectValueStreamIdToProjectStages, schema: 20210503105022 do
let(:stages) { table(:analytics_cycle_analytics_project_stages) }
diff --git a/spec/migrations/20210511142748_schedule_drop_invalid_vulnerabilities2_spec.rb b/spec/migrations/20210511142748_schedule_drop_invalid_vulnerabilities2_spec.rb
index 969a2e58947..dd557c833f3 100644
--- a/spec/migrations/20210511142748_schedule_drop_invalid_vulnerabilities2_spec.rb
+++ b/spec/migrations/20210511142748_schedule_drop_invalid_vulnerabilities2_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('schedule_drop_invalid_vulnerabilities2')
+require_migration!
RSpec.describe ScheduleDropInvalidVulnerabilities2, :migration do
let_it_be(:background_migration_jobs) { table(:background_migration_jobs) }
diff --git a/spec/migrations/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects_spec.rb b/spec/migrations/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects_spec.rb
index b7524ee0bff..4ac4af19eb9 100644
--- a/spec/migrations/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects_spec.rb
+++ b/spec/migrations/20210514063252_schedule_cleanup_orphaned_lfs_objects_projects_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('schedule_cleanup_orphaned_lfs_objects_projects')
+require_migration!
RSpec.describe ScheduleCleanupOrphanedLfsObjectsProjects, schema: 20210511165250 do
let(:lfs_objects_projects) { table(:lfs_objects_projects) }
diff --git a/spec/migrations/20210601073400_fix_total_stage_in_vsa_spec.rb b/spec/migrations/20210601073400_fix_total_stage_in_vsa_spec.rb
index 36d85d1f745..fa4b747aaed 100644
--- a/spec/migrations/20210601073400_fix_total_stage_in_vsa_spec.rb
+++ b/spec/migrations/20210601073400_fix_total_stage_in_vsa_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('fix_total_stage_in_vsa')
+require_migration!
RSpec.describe FixTotalStageInVsa, :migration, schema: 20210518001450 do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20210601080039_group_protected_environments_add_index_and_constraint_spec.rb b/spec/migrations/20210601080039_group_protected_environments_add_index_and_constraint_spec.rb
index d3154596b26..8d45f571969 100644
--- a/spec/migrations/20210601080039_group_protected_environments_add_index_and_constraint_spec.rb
+++ b/spec/migrations/20210601080039_group_protected_environments_add_index_and_constraint_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('group_protected_environments_add_index_and_constraint')
+require_migration!
RSpec.describe GroupProtectedEnvironmentsAddIndexAndConstraint do
let(:migration) { described_class.new }
diff --git a/spec/migrations/20210603222333_remove_builds_email_service_from_services_spec.rb b/spec/migrations/20210603222333_remove_builds_email_service_from_services_spec.rb
index c457be79834..14aa4fe8da7 100644
--- a/spec/migrations/20210603222333_remove_builds_email_service_from_services_spec.rb
+++ b/spec/migrations/20210603222333_remove_builds_email_service_from_services_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require_migration!('remove_builds_email_service_from_services')
+require_migration!
RSpec.describe RemoveBuildsEmailServiceFromServices do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20210610153556_delete_legacy_operations_feature_flags_spec.rb b/spec/migrations/20210610153556_delete_legacy_operations_feature_flags_spec.rb
index 4f621d0670c..17599e75947 100644
--- a/spec/migrations/20210610153556_delete_legacy_operations_feature_flags_spec.rb
+++ b/spec/migrations/20210610153556_delete_legacy_operations_feature_flags_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require_migration!('delete_legacy_operations_feature_flags')
+require_migration!
RSpec.describe DeleteLegacyOperationsFeatureFlags do
let(:namespace) { table(:namespaces).create!(name: 'foo', path: 'bar') }
diff --git a/spec/migrations/2021061716138_cascade_delete_freeze_periods_spec.rb b/spec/migrations/2021061716138_cascade_delete_freeze_periods_spec.rb
index fd664d99f06..d35184e78a8 100644
--- a/spec/migrations/2021061716138_cascade_delete_freeze_periods_spec.rb
+++ b/spec/migrations/2021061716138_cascade_delete_freeze_periods_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require_migration!('cascade_delete_freeze_periods')
+require_migration!
RSpec.describe CascadeDeleteFreezePeriods do
let(:namespace) { table(:namespaces).create!(name: 'deploy_freeze', path: 'deploy_freeze') }
diff --git a/spec/migrations/20210708130419_reschedule_merge_request_diff_users_background_migration_spec.rb b/spec/migrations/20210708130419_reschedule_merge_request_diff_users_background_migration_spec.rb
index 9cc454662f9..7a281611650 100644
--- a/spec/migrations/20210708130419_reschedule_merge_request_diff_users_background_migration_spec.rb
+++ b/spec/migrations/20210708130419_reschedule_merge_request_diff_users_background_migration_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration! 'reschedule_merge_request_diff_users_background_migration'
+require_migration!
RSpec.describe RescheduleMergeRequestDiffUsersBackgroundMigration, :migration do
let(:migration) { described_class.new }
diff --git a/spec/migrations/20210722042939_update_issuable_slas_where_issue_closed_spec.rb b/spec/migrations/20210722042939_update_issuable_slas_where_issue_closed_spec.rb
index a0aae00776d..63802acceb5 100644
--- a/spec/migrations/20210722042939_update_issuable_slas_where_issue_closed_spec.rb
+++ b/spec/migrations/20210722042939_update_issuable_slas_where_issue_closed_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('update_issuable_slas_where_issue_closed')
+require_migration!
RSpec.describe UpdateIssuableSlasWhereIssueClosed, :migration do
let(:namespaces) { table(:namespaces) }
diff --git a/spec/migrations/20210722150102_operations_feature_flags_correct_flexible_rollout_values_spec.rb b/spec/migrations/20210722150102_operations_feature_flags_correct_flexible_rollout_values_spec.rb
index 130ad45ffc1..94af2bb1e9a 100644
--- a/spec/migrations/20210722150102_operations_feature_flags_correct_flexible_rollout_values_spec.rb
+++ b/spec/migrations/20210722150102_operations_feature_flags_correct_flexible_rollout_values_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require_migration!('operations_feature_flags_correct_flexible_rollout_values')
+require_migration!
RSpec.describe OperationsFeatureFlagsCorrectFlexibleRolloutValues, :migration do
let_it_be(:strategies) { table(:operations_strategies) }
diff --git a/spec/migrations/20210804150320_create_base_work_item_types_spec.rb b/spec/migrations/20210804150320_create_base_work_item_types_spec.rb
index 9ba29637e00..34ea7f53f51 100644
--- a/spec/migrations/20210804150320_create_base_work_item_types_spec.rb
+++ b/spec/migrations/20210804150320_create_base_work_item_types_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('create_base_work_item_types')
+require_migration!
RSpec.describe CreateBaseWorkItemTypes, :migration do
let!(:work_item_types) { table(:work_item_types) }
diff --git a/spec/migrations/20210805192450_update_trial_plans_ci_daily_pipeline_schedule_triggers_spec.rb b/spec/migrations/20210805192450_update_trial_plans_ci_daily_pipeline_schedule_triggers_spec.rb
index 819120d43ef..0b2f76baf1a 100644
--- a/spec/migrations/20210805192450_update_trial_plans_ci_daily_pipeline_schedule_triggers_spec.rb
+++ b/spec/migrations/20210805192450_update_trial_plans_ci_daily_pipeline_schedule_triggers_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-require_migration!('update_trial_plans_ci_daily_pipeline_schedule_triggers')
+require_migration!
RSpec.describe UpdateTrialPlansCiDailyPipelineScheduleTriggers, :migration do
let!(:plans) { table(:plans) }
diff --git a/spec/migrations/20210811122206_update_external_project_bots_spec.rb b/spec/migrations/20210811122206_update_external_project_bots_spec.rb
index a9c7b485cc6..365fb8e3218 100644
--- a/spec/migrations/20210811122206_update_external_project_bots_spec.rb
+++ b/spec/migrations/20210811122206_update_external_project_bots_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('update_external_project_bots')
+require_migration!
RSpec.describe UpdateExternalProjectBots, :migration do
def create_user(**extra_options)
diff --git a/spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb b/spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb
index d87f952b5da..29f554a003b 100644
--- a/spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb
+++ b/spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('backfill_projects_with_coverage')
+require_migration!
RSpec.describe BackfillProjectsWithCoverage do
let(:projects) { table(:projects) }
diff --git a/spec/migrations/20210819145000_drop_temporary_columns_and_triggers_for_ci_builds_runner_session_spec.rb b/spec/migrations/20210819145000_drop_temporary_columns_and_triggers_for_ci_builds_runner_session_spec.rb
index b1751216732..4ad4bea058b 100644
--- a/spec/migrations/20210819145000_drop_temporary_columns_and_triggers_for_ci_builds_runner_session_spec.rb
+++ b/spec/migrations/20210819145000_drop_temporary_columns_and_triggers_for_ci_builds_runner_session_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('drop_temporary_columns_and_triggers_for_ci_builds_runner_session')
+require_migration!
RSpec.describe DropTemporaryColumnsAndTriggersForCiBuildsRunnerSession, :migration do
let(:ci_builds_runner_session_table) { table(:ci_builds_runner_session) }
diff --git a/spec/migrations/20210831203408_upsert_base_work_item_types_spec.rb b/spec/migrations/20210831203408_upsert_base_work_item_types_spec.rb
index c23110750c3..3c8c55ccb80 100644
--- a/spec/migrations/20210831203408_upsert_base_work_item_types_spec.rb
+++ b/spec/migrations/20210831203408_upsert_base_work_item_types_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('upsert_base_work_item_types')
+require_migration!
RSpec.describe UpsertBaseWorkItemTypes, :migration do
let!(:work_item_types) { table(:work_item_types) }
diff --git a/spec/migrations/20210902144144_drop_temporary_columns_and_triggers_for_ci_build_needs_spec.rb b/spec/migrations/20210902144144_drop_temporary_columns_and_triggers_for_ci_build_needs_spec.rb
index 1b35982c41d..4ec3c5b7211 100644
--- a/spec/migrations/20210902144144_drop_temporary_columns_and_triggers_for_ci_build_needs_spec.rb
+++ b/spec/migrations/20210902144144_drop_temporary_columns_and_triggers_for_ci_build_needs_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('drop_temporary_columns_and_triggers_for_ci_build_needs')
+require_migration!
RSpec.describe DropTemporaryColumnsAndTriggersForCiBuildNeeds do
let(:ci_build_needs_table) { table(:ci_build_needs) }
diff --git a/spec/migrations/20210906100316_drop_temporary_columns_and_triggers_for_ci_build_trace_chunks_spec.rb b/spec/migrations/20210906100316_drop_temporary_columns_and_triggers_for_ci_build_trace_chunks_spec.rb
index 8d46ba7eb58..f1408e4ecab 100644
--- a/spec/migrations/20210906100316_drop_temporary_columns_and_triggers_for_ci_build_trace_chunks_spec.rb
+++ b/spec/migrations/20210906100316_drop_temporary_columns_and_triggers_for_ci_build_trace_chunks_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('drop_temporary_columns_and_triggers_for_ci_build_trace_chunks')
+require_migration!
RSpec.describe DropTemporaryColumnsAndTriggersForCiBuildTraceChunks do
let(:ci_build_trace_chunks_table) { table(:ci_build_trace_chunks) }
diff --git a/spec/migrations/20210906130643_drop_temporary_columns_and_triggers_for_taggings_spec.rb b/spec/migrations/20210906130643_drop_temporary_columns_and_triggers_for_taggings_spec.rb
index 2e7ce733373..e4385e501b2 100644
--- a/spec/migrations/20210906130643_drop_temporary_columns_and_triggers_for_taggings_spec.rb
+++ b/spec/migrations/20210906130643_drop_temporary_columns_and_triggers_for_taggings_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('drop_temporary_columns_and_triggers_for_taggings')
+require_migration!
RSpec.describe DropTemporaryColumnsAndTriggersForTaggings do
let(:taggings_table) { table(:taggings) }
diff --git a/spec/migrations/20210907013944_cleanup_bigint_conversion_for_ci_builds_metadata_spec.rb b/spec/migrations/20210907013944_cleanup_bigint_conversion_for_ci_builds_metadata_spec.rb
index ece5ed8251d..194832fbc43 100644
--- a/spec/migrations/20210907013944_cleanup_bigint_conversion_for_ci_builds_metadata_spec.rb
+++ b/spec/migrations/20210907013944_cleanup_bigint_conversion_for_ci_builds_metadata_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('cleanup_bigint_conversion_for_ci_builds_metadata')
+require_migration!
RSpec.describe CleanupBigintConversionForCiBuildsMetadata do
let(:ci_builds_metadata) { table(:ci_builds_metadata) }
diff --git a/spec/migrations/20210907211557_finalize_ci_builds_bigint_conversion_spec.rb b/spec/migrations/20210907211557_finalize_ci_builds_bigint_conversion_spec.rb
index 362b4be1bc6..c0f56da7b4f 100644
--- a/spec/migrations/20210907211557_finalize_ci_builds_bigint_conversion_spec.rb
+++ b/spec/migrations/20210907211557_finalize_ci_builds_bigint_conversion_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('finalize_ci_builds_bigint_conversion')
+require_migration!
RSpec.describe FinalizeCiBuildsBigintConversion, :migration, schema: 20210907182359 do
context 'with an unexpected FK fk_3f0c88d7dc' do
diff --git a/spec/migrations/20210910194952_update_report_type_for_existing_approval_project_rules_spec.rb b/spec/migrations/20210910194952_update_report_type_for_existing_approval_project_rules_spec.rb
index 46a6d8d92ec..c90eabbe4eb 100644
--- a/spec/migrations/20210910194952_update_report_type_for_existing_approval_project_rules_spec.rb
+++ b/spec/migrations/20210910194952_update_report_type_for_existing_approval_project_rules_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('update_report_type_for_existing_approval_project_rules')
+require_migration!
RSpec.describe UpdateReportTypeForExistingApprovalProjectRules, :migration do
using RSpec::Parameterized::TableSyntax
diff --git a/spec/migrations/20210914095310_cleanup_orphan_project_access_tokens_spec.rb b/spec/migrations/20210914095310_cleanup_orphan_project_access_tokens_spec.rb
index 0d0f6a3df67..2b755dfe11c 100644
--- a/spec/migrations/20210914095310_cleanup_orphan_project_access_tokens_spec.rb
+++ b/spec/migrations/20210914095310_cleanup_orphan_project_access_tokens_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('cleanup_orphan_project_access_tokens')
+require_migration!
RSpec.describe CleanupOrphanProjectAccessTokens, :migration do
def create_user(**extra_options)
diff --git a/spec/migrations/20210915022415_cleanup_bigint_conversion_for_ci_builds_spec.rb b/spec/migrations/20210915022415_cleanup_bigint_conversion_for_ci_builds_spec.rb
index ee71322433d..cedc62a6565 100644
--- a/spec/migrations/20210915022415_cleanup_bigint_conversion_for_ci_builds_spec.rb
+++ b/spec/migrations/20210915022415_cleanup_bigint_conversion_for_ci_builds_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('cleanup_bigint_conversion_for_ci_builds')
+require_migration!
RSpec.describe CleanupBigintConversionForCiBuilds do
let(:ci_builds) { table(:ci_builds) }
diff --git a/spec/migrations/20210922021816_drop_int4_columns_for_ci_job_artifacts_spec.rb b/spec/migrations/20210922021816_drop_int4_columns_for_ci_job_artifacts_spec.rb
index cf326cf0c0a..a6eede8a8f1 100644
--- a/spec/migrations/20210922021816_drop_int4_columns_for_ci_job_artifacts_spec.rb
+++ b/spec/migrations/20210922021816_drop_int4_columns_for_ci_job_artifacts_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('drop_int4_columns_for_ci_job_artifacts')
+require_migration!
RSpec.describe DropInt4ColumnsForCiJobArtifacts do
let(:ci_job_artifacts) { table(:ci_job_artifacts) }
diff --git a/spec/migrations/20210922025631_drop_int4_column_for_ci_sources_pipelines_spec.rb b/spec/migrations/20210922025631_drop_int4_column_for_ci_sources_pipelines_spec.rb
index 00b922ee4f8..730c9ade1fb 100644
--- a/spec/migrations/20210922025631_drop_int4_column_for_ci_sources_pipelines_spec.rb
+++ b/spec/migrations/20210922025631_drop_int4_column_for_ci_sources_pipelines_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('drop_int4_column_for_ci_sources_pipelines')
+require_migration!
RSpec.describe DropInt4ColumnForCiSourcesPipelines do
let(:ci_sources_pipelines) { table(:ci_sources_pipelines) }
diff --git a/spec/migrations/20210922082019_drop_int4_column_for_events_spec.rb b/spec/migrations/20210922082019_drop_int4_column_for_events_spec.rb
index 412556fc283..e460612a7d5 100644
--- a/spec/migrations/20210922082019_drop_int4_column_for_events_spec.rb
+++ b/spec/migrations/20210922082019_drop_int4_column_for_events_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('drop_int4_column_for_events')
+require_migration!
RSpec.describe DropInt4ColumnForEvents do
let(:events) { table(:events) }
diff --git a/spec/migrations/20210922091402_drop_int4_column_for_push_event_payloads_spec.rb b/spec/migrations/20210922091402_drop_int4_column_for_push_event_payloads_spec.rb
index 2b286e3e5e0..8c89cd19f7f 100644
--- a/spec/migrations/20210922091402_drop_int4_column_for_push_event_payloads_spec.rb
+++ b/spec/migrations/20210922091402_drop_int4_column_for_push_event_payloads_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('drop_int4_column_for_push_event_payloads')
+require_migration!
RSpec.describe DropInt4ColumnForPushEventPayloads do
let(:push_event_payloads) { table(:push_event_payloads) }
diff --git a/spec/migrations/20211006060436_schedule_populate_topics_total_projects_count_cache_spec.rb b/spec/migrations/20211006060436_schedule_populate_topics_total_projects_count_cache_spec.rb
index d07d9a71b06..09ce0858b12 100644
--- a/spec/migrations/20211006060436_schedule_populate_topics_total_projects_count_cache_spec.rb
+++ b/spec/migrations/20211006060436_schedule_populate_topics_total_projects_count_cache_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration!('schedule_populate_topics_total_projects_count_cache')
+require_migration!
RSpec.describe SchedulePopulateTopicsTotalProjectsCountCache do
let(:topics) { table(:topics) }
diff --git a/spec/migrations/20211012134316_clean_up_migrate_merge_request_diff_commit_users_spec.rb b/spec/migrations/20211012134316_clean_up_migrate_merge_request_diff_commit_users_spec.rb
new file mode 100644
index 00000000000..910e6d1d91b
--- /dev/null
+++ b/spec/migrations/20211012134316_clean_up_migrate_merge_request_diff_commit_users_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration! 'clean_up_migrate_merge_request_diff_commit_users'
+
+RSpec.describe CleanUpMigrateMergeRequestDiffCommitUsers, :migration do
+ describe '#up' do
+ context 'when there are pending jobs' do
+ it 'processes the jobs immediately' do
+ Gitlab::Database::BackgroundMigrationJob.create!(
+ class_name: 'MigrateMergeRequestDiffCommitUsers',
+ status: :pending,
+ arguments: [10, 20]
+ )
+
+ spy = Gitlab::BackgroundMigration::MigrateMergeRequestDiffCommitUsers
+ migration = described_class.new
+
+ allow(Gitlab::BackgroundMigration::MigrateMergeRequestDiffCommitUsers)
+ .to receive(:new)
+ .and_return(spy)
+
+ expect(migration).to receive(:say)
+ expect(spy).to receive(:perform).with(10, 20)
+
+ migration.up
+ end
+ end
+
+ context 'when all jobs are completed' do
+ it 'does nothing' do
+ Gitlab::Database::BackgroundMigrationJob.create!(
+ class_name: 'MigrateMergeRequestDiffCommitUsers',
+ status: :succeeded,
+ arguments: [10, 20]
+ )
+
+ migration = described_class.new
+
+ expect(migration).not_to receive(:say)
+ expect(Gitlab::BackgroundMigration::MigrateMergeRequestDiffCommitUsers)
+ .not_to receive(:new)
+
+ migration.up
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20211018152654_schedule_remove_duplicate_vulnerabilities_findings3_spec.rb b/spec/migrations/20211018152654_schedule_remove_duplicate_vulnerabilities_findings3_spec.rb
new file mode 100644
index 00000000000..95c5be2fc30
--- /dev/null
+++ b/spec/migrations/20211018152654_schedule_remove_duplicate_vulnerabilities_findings3_spec.rb
@@ -0,0 +1,168 @@
+# frozen_string_literal: true
+require 'spec_helper'
+require_migration!('schedule_remove_duplicate_vulnerabilities_findings3')
+
+RSpec.describe ScheduleRemoveDuplicateVulnerabilitiesFindings3, :migration do
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:users) { table(:users) }
+ let(:user) { create_user! }
+ let(:project) { table(:projects).create!(id: 14219619, namespace_id: namespace.id) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let!(:scanner1) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+ let!(:scanner2) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') }
+ let!(:scanner3) { scanners.create!(project_id: project.id, external_id: 'test 3', name: 'test scanner 3') }
+ let!(:unrelated_scanner) { scanners.create!(project_id: project.id, external_id: 'unreleated_scanner', name: 'unrelated scanner') }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerability_findings) { table(:vulnerability_occurrences) }
+ let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
+ let(:vulnerability_identifier) do
+ vulnerability_identifiers.create!(
+ id: 1244459,
+ project_id: project.id,
+ external_type: 'vulnerability-identifier',
+ external_id: 'vulnerability-identifier',
+ fingerprint: '0a203e8cd5260a1948edbedc76c7cb91ad6a2e45',
+ name: 'vulnerability identifier')
+ end
+
+ let!(:vulnerability_for_first_duplicate) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let!(:first_finding_duplicate) do
+ create_finding!(
+ id: 5606961,
+ uuid: "bd95c085-71aa-51d7-9bb6-08ae669c262e",
+ vulnerability_id: vulnerability_for_first_duplicate.id,
+ report_type: 0,
+ location_fingerprint: '00049d5119c2cb3bfb3d1ee1f6e031fe925aed75',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner1.id,
+ project_id: project.id
+ )
+ end
+
+ let!(:vulnerability_for_second_duplicate) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let!(:second_finding_duplicate) do
+ create_finding!(
+ id: 8765432,
+ uuid: "5b714f58-1176-5b26-8fd5-e11dfcb031b5",
+ vulnerability_id: vulnerability_for_second_duplicate.id,
+ report_type: 0,
+ location_fingerprint: '00049d5119c2cb3bfb3d1ee1f6e031fe925aed75',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner2.id,
+ project_id: project.id
+ )
+ end
+
+ let!(:vulnerability_for_third_duplicate) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let!(:third_finding_duplicate) do
+ create_finding!(
+ id: 8832995,
+ uuid: "cfe435fa-b25b-5199-a56d-7b007cc9e2d4",
+ vulnerability_id: vulnerability_for_third_duplicate.id,
+ report_type: 0,
+ location_fingerprint: '00049d5119c2cb3bfb3d1ee1f6e031fe925aed75',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner3.id,
+ project_id: project.id
+ )
+ end
+
+ let!(:unrelated_finding) do
+ create_finding!(
+ id: 9999999,
+ uuid: "unreleated_finding",
+ vulnerability_id: nil,
+ report_type: 1,
+ location_fingerprint: 'random_location_fingerprint',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: unrelated_scanner.id,
+ project_id: project.id
+ )
+ end
+
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+ end
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ it 'schedules background migration' do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(4)
+ expect(described_class::MIGRATION).to be_scheduled_migration(first_finding_duplicate.id, first_finding_duplicate.id)
+ expect(described_class::MIGRATION).to be_scheduled_migration(second_finding_duplicate.id, second_finding_duplicate.id)
+ expect(described_class::MIGRATION).to be_scheduled_migration(third_finding_duplicate.id, third_finding_duplicate.id)
+ expect(described_class::MIGRATION).to be_scheduled_migration(unrelated_finding.id, unrelated_finding.id)
+ end
+
+ private
+
+ def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
+ vulnerabilities.create!(
+ project_id: project_id,
+ author_id: author_id,
+ title: title,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type
+ )
+ end
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ id: nil,
+ vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:,
+ name: "test", severity: 7, confidence: 7, report_type: 0,
+ project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
+ metadata_version: 'test', raw_metadata: 'test', uuid: 'test')
+ vulnerability_findings.create!({
+ id: id,
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: name,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type,
+ project_fingerprint: project_fingerprint,
+ scanner_id: scanner_id,
+ primary_identifier_id: vulnerability_identifier.id,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ }.compact)
+ end
+ # rubocop:enable Metrics/ParameterLists
+
+ def create_user!(name: "Example User", email: "user@example.com", user_type: nil, created_at: Time.zone.now, confirmed_at: Time.zone.now)
+ users.create!(
+ name: name,
+ email: email,
+ username: name,
+ projects_limit: 0,
+ user_type: user_type,
+ confirmed_at: confirmed_at
+ )
+ end
+end
diff --git a/spec/migrations/20211028155449_schedule_fix_merge_request_diff_commit_users_migration_spec.rb b/spec/migrations/20211028155449_schedule_fix_merge_request_diff_commit_users_migration_spec.rb
new file mode 100644
index 00000000000..6511f554436
--- /dev/null
+++ b/spec/migrations/20211028155449_schedule_fix_merge_request_diff_commit_users_migration_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration! 'schedule_fix_merge_request_diff_commit_users_migration'
+
+RSpec.describe ScheduleFixMergeRequestDiffCommitUsersMigration, :migration do
+ let(:migration) { described_class.new }
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
+
+ describe '#up' do
+ it 'does nothing when there are no projects to correct' do
+ migration.up
+
+ expect(Gitlab::Database::BackgroundMigrationJob.count).to be_zero
+ end
+
+ it 'schedules imported projects created after July' do
+ project = projects.create!(
+ namespace_id: namespace.id,
+ import_type: 'gitlab_project',
+ created_at: '2021-08-01'
+ )
+
+ expect(migration)
+ .to receive(:migrate_in)
+ .with(2.minutes, 'FixMergeRequestDiffCommitUsers', [project.id])
+
+ migration.up
+
+ expect(Gitlab::Database::BackgroundMigrationJob.count).to eq(1)
+
+ job = Gitlab::Database::BackgroundMigrationJob.first
+
+ expect(job.class_name).to eq('FixMergeRequestDiffCommitUsers')
+ expect(job.arguments).to eq([project.id])
+ end
+
+ it 'ignores projects imported before July' do
+ projects.create!(
+ namespace_id: namespace.id,
+ import_type: 'gitlab_project',
+ created_at: '2020-08-01'
+ )
+
+ migration.up
+
+ expect(Gitlab::Database::BackgroundMigrationJob.count).to be_zero
+ end
+
+ it 'ignores projects that are not imported' do
+ projects.create!(
+ namespace_id: namespace.id,
+ created_at: '2021-08-01'
+ )
+
+ migration.up
+
+ expect(Gitlab::Database::BackgroundMigrationJob.count).to be_zero
+ end
+ end
+end
diff --git a/spec/migrations/add_default_value_stream_to_groups_with_group_stages_spec.rb b/spec/migrations/add_default_value_stream_to_groups_with_group_stages_spec.rb
deleted file mode 100644
index f21acbc56df..00000000000
--- a/spec/migrations/add_default_value_stream_to_groups_with_group_stages_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe AddDefaultValueStreamToGroupsWithGroupStages, schema: 20200624142207 do
- let(:groups) { table(:namespaces) }
- let(:group_stages) { table(:analytics_cycle_analytics_group_stages) }
- let(:value_streams) { table(:analytics_cycle_analytics_group_value_streams) }
-
- let!(:group) { groups.create!(name: 'test', path: 'path', type: 'Group') }
- let!(:group_stage) { group_stages.create!(name: 'test', group_id: group.id, start_event_identifier: 1, end_event_identifier: 2) }
-
- describe '#up' do
- it 'creates default value stream record for the group' do
- migrate!
-
- group_value_streams = value_streams.where(group_id: group.id)
- expect(group_value_streams.size).to eq(1)
-
- value_stream = group_value_streams.first
- expect(value_stream.name).to eq('default')
- end
-
- it 'migrates existing stages to the default value stream' do
- migrate!
-
- group_stage.reload
-
- value_stream = value_streams.find_by(group_id: group.id, name: 'default')
- expect(group_stage.group_value_stream_id).to eq(value_stream.id)
- end
- end
-
- describe '#down' do
- it 'sets the group_value_stream_id to nil' do
- described_class.new.down
-
- group_stage.reload
-
- expect(group_stage.group_value_stream_id).to be_nil
- end
- end
-end
diff --git a/spec/migrations/add_deploy_token_type_to_deploy_tokens_spec.rb b/spec/migrations/add_deploy_token_type_to_deploy_tokens_spec.rb
deleted file mode 100644
index f90bfcd313c..00000000000
--- a/spec/migrations/add_deploy_token_type_to_deploy_tokens_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe AddDeployTokenTypeToDeployTokens do
- let(:deploy_tokens) { table(:deploy_tokens) }
- let(:deploy_token) do
- deploy_tokens.create!(name: 'token_test',
- username: 'gitlab+deploy-token-1',
- token_encrypted: 'dr8rPXwM+Mbs2p3Bg1+gpnXqrnH/wu6vaHdcc7A3isPR67WB',
- read_repository: true,
- expires_at: Time.now + 1.year)
- end
-
- it 'updates the deploy_token_type column to 2' do
- expect(deploy_token).not_to respond_to(:deploy_token_type)
-
- migrate!
-
- deploy_token.reload
- expect(deploy_token.deploy_token_type).to eq(2)
- end
-end
diff --git a/spec/migrations/add_incident_settings_to_all_existing_projects_spec.rb b/spec/migrations/add_incident_settings_to_all_existing_projects_spec.rb
deleted file mode 100644
index 3e0bc64bb23..00000000000
--- a/spec/migrations/add_incident_settings_to_all_existing_projects_spec.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe AddIncidentSettingsToAllExistingProjects, :migration do
- let(:project_incident_management_settings) { table(:project_incident_management_settings) }
- let(:labels) { table(:labels) }
- let(:label_links) { table(:label_links) }
- let(:issues) { table(:issues) }
- let(:projects) { table(:projects) }
- let(:namespaces) { table(:namespaces) }
-
- RSpec.shared_examples 'setting not added' do
- it 'does not add settings' do
- migrate!
-
- expect { migrate! }.not_to change { IncidentManagement::ProjectIncidentManagementSetting.count }
- end
- end
-
- RSpec.shared_examples 'project has no incident settings' do
- it 'has no settings' do
- migrate!
-
- expect(settings).to eq(nil)
- end
- end
-
- RSpec.shared_examples 'no change to incident settings' do
- it 'does not change existing settings' do
- migrate!
-
- expect(settings.create_issue).to eq(existing_create_issue)
- end
- end
-
- RSpec.shared_context 'with incident settings' do
- let(:existing_create_issue) { false }
- before do
- project_incident_management_settings.create!(
- project_id: project.id,
- create_issue: existing_create_issue
- )
- end
- end
-
- describe 'migrate!' do
- let(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
- let!(:project) { projects.create!(namespace_id: namespace.id) }
- let(:settings) { project_incident_management_settings.find_by(project_id: project.id) }
-
- context 'when project does not have incident label' do
- context 'does not have incident settings' do
- include_examples 'setting not added'
- include_examples 'project has no incident settings'
- end
-
- context 'and has incident settings' do
- include_context 'with incident settings'
-
- include_examples 'setting not added'
- include_examples 'no change to incident settings'
- end
- end
-
- context 'when project has incident labels' do
- before do
- issue = issues.create!(project_id: project.id)
- incident_label_attrs = IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES
- incident_label = labels.create!(project_id: project.id, **incident_label_attrs)
- label_links.create!(target_id: issue.id, label_id: incident_label.id, target_type: 'Issue')
- end
-
- context 'when project has incident settings' do
- include_context 'with incident settings'
-
- include_examples 'setting not added'
- include_examples 'no change to incident settings'
- end
-
- context 'does not have incident settings' do
- it 'adds incident settings with old defaults' do
- migrate!
-
- expect(settings.create_issue).to eq(true)
- expect(settings.send_email).to eq(false)
- expect(settings.issue_template_key).to eq(nil)
- end
- end
- end
- end
-end
diff --git a/spec/migrations/add_open_source_plan_spec.rb b/spec/migrations/add_open_source_plan_spec.rb
new file mode 100644
index 00000000000..04b26662f82
--- /dev/null
+++ b/spec/migrations/add_open_source_plan_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe AddOpenSourcePlan, :migration do
+ describe '#up' do
+ before do
+ allow(Gitlab).to receive(:dev_env_or_com?).and_return true
+ end
+
+ it 'creates 1 entry within the plans table' do
+ expect { migrate! }.to change { AddOpenSourcePlan::Plan.count }.by 1
+ expect(AddOpenSourcePlan::Plan.last.name).to eql('opensource')
+ end
+
+ it 'creates 1 entry for plan limits' do
+ expect { migrate! }.to change { AddOpenSourcePlan::PlanLimits.count }.by 1
+ end
+
+ context 'when the plan limits for gold and silver exists' do
+ before do
+ table(:plans).create!(id: 1, name: 'ultimate', title: 'Ultimate')
+ table(:plan_limits).create!(id: 1, plan_id: 1, storage_size_limit: 2000)
+ end
+
+ it 'duplicates the gold and silvers plan limits entries' do
+ migrate!
+
+ opensource_limits = AddOpenSourcePlan::Plan.find_by(name: 'opensource').limits
+ expect(opensource_limits.storage_size_limit).to be 2000
+ end
+ end
+
+ context 'when the instance is not SaaS' do
+ before do
+ allow(Gitlab).to receive(:dev_env_or_com?).and_return false
+ end
+
+ it 'does not create plans and plan limits and returns' do
+ expect { migrate! }.not_to change { AddOpenSourcePlan::Plan.count }
+ end
+ end
+ end
+
+ describe '#down' do
+ before do
+ table(:plans).create!(id: 3, name: 'other')
+ table(:plan_limits).create!(plan_id: 3)
+ end
+
+ context 'when the instance is SaaS' do
+ before do
+ allow(Gitlab).to receive(:dev_env_or_com?).and_return true
+ end
+
+ it 'removes the newly added opensource entry' do
+ migrate!
+
+ expect { described_class.new.down }.to change { AddOpenSourcePlan::Plan.count }.by(-1)
+ expect(AddOpenSourcePlan::Plan.find_by(name: 'opensource')).to be_nil
+
+ other_plan = AddOpenSourcePlan::Plan.find_by(name: 'other')
+ expect(other_plan).to be_persisted
+ expect(AddOpenSourcePlan::PlanLimits.count).to eq(1)
+ expect(AddOpenSourcePlan::PlanLimits.first.plan_id).to eq(other_plan.id)
+ end
+ end
+
+ context 'when the instance is not SaaS' do
+ before do
+ allow(Gitlab).to receive(:dev_env_or_com?).and_return false
+ table(:plans).create!(id: 1, name: 'opensource', title: 'Open Source Program')
+ table(:plan_limits).create!(id: 1, plan_id: 1)
+ end
+
+ it 'does not delete plans and plan limits and returns' do
+ migrate!
+
+ expect { described_class.new.down }.not_to change { AddOpenSourcePlan::Plan.count }
+ expect(AddOpenSourcePlan::PlanLimits.count).to eq(2)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb b/spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb
deleted file mode 100644
index ab4d6f43797..00000000000
--- a/spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe AddPartialIndexToCiBuildsTableOnUserIdName do
- let(:migration) { described_class.new }
-
- describe '#up' do
- it 'creates temporary partial index on type' do
- expect { migration.up }.to change { migration.index_exists?(:ci_builds, [:user_id, :name], name: described_class::INDEX_NAME) }.from(false).to(true)
- end
- end
-
- describe '#down' do
- it 'removes temporary partial index on type' do
- migration.up
-
- expect { migration.down }.to change { migration.index_exists?(:ci_builds, [:user_id, :name], name: described_class::INDEX_NAME) }.from(true).to(false)
- end
- end
-end
diff --git a/spec/migrations/add_repository_storages_weighted_to_application_settings_spec.rb b/spec/migrations/add_repository_storages_weighted_to_application_settings_spec.rb
deleted file mode 100644
index bc4c510fea3..00000000000
--- a/spec/migrations/add_repository_storages_weighted_to_application_settings_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe AddRepositoryStoragesWeightedToApplicationSettings, :migration do
- let(:storages) { { "foo" => {}, "baz" => {} } }
- let(:application_settings) do
- table(:application_settings).tap do |klass|
- klass.class_eval do
- serialize :repository_storages
- end
- end
- end
-
- before do
- allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
- end
-
- let(:application_setting) { application_settings.create! }
- let(:repository_storages) { ["foo"] }
-
- it 'populates repository_storages_weighted properly' do
- application_setting.repository_storages = repository_storages
- application_setting.save!
-
- migrate!
-
- expect(application_settings.find(application_setting.id).repository_storages_weighted).to eq({ "foo" => 100, "baz" => 0 })
- end
-end
diff --git a/spec/migrations/add_temporary_partial_index_on_project_id_to_services_spec.rb b/spec/migrations/add_temporary_partial_index_on_project_id_to_services_spec.rb
deleted file mode 100644
index dae0241b895..00000000000
--- a/spec/migrations/add_temporary_partial_index_on_project_id_to_services_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe AddTemporaryPartialIndexOnProjectIdToServices do
- let(:migration) { described_class.new }
-
- describe '#up' do
- it 'creates temporary partial index on type' do
- expect { migration.up }.to change { migration.index_exists?(:services, :project_id, name: described_class::INDEX_NAME) }.from(false).to(true)
- end
- end
-
- describe '#down' do
- it 'removes temporary partial index on type' do
- migration.up
-
- expect { migration.down }.to change { migration.index_exists?(:services, :project_id, name: described_class::INDEX_NAME) }.from(true).to(false)
- end
- end
-end
diff --git a/spec/migrations/backfill_imported_snippet_repositories_spec.rb b/spec/migrations/backfill_imported_snippet_repositories_spec.rb
deleted file mode 100644
index 7052433c66d..00000000000
--- a/spec/migrations/backfill_imported_snippet_repositories_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe BackfillImportedSnippetRepositories do
- let(:users) { table(:users) }
- let(:snippets) { table(:snippets) }
- let(:user) { users.create!(id: 1, email: 'user@example.com', projects_limit: 10, username: 'test', name: 'Test', state: 'active') }
-
- def create_snippet(id)
- params = {
- id: id,
- type: 'PersonalSnippet',
- author_id: user.id,
- file_name: 'foo',
- content: 'bar'
- }
-
- snippets.create!(params)
- end
-
- it 'correctly schedules background migrations' do
- create_snippet(1)
- create_snippet(2)
- create_snippet(3)
- create_snippet(5)
- create_snippet(7)
- create_snippet(8)
- create_snippet(10)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(2.minutes, 1, 3)
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(4.minutes, 5, 5)
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(6.minutes, 7, 8)
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(8.minutes, 10, 10)
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(4)
- end
- end
- end
-end
diff --git a/spec/migrations/backfill_operations_feature_flags_iid_spec.rb b/spec/migrations/backfill_operations_feature_flags_iid_spec.rb
deleted file mode 100644
index 3c400840f98..00000000000
--- a/spec/migrations/backfill_operations_feature_flags_iid_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe BackfillOperationsFeatureFlagsIid do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:flags) { table(:operations_feature_flags) }
-
- def setup
- namespace = namespaces.create!(name: 'foo', path: 'foo')
- projects.create!(namespace_id: namespace.id)
- end
-
- it 'migrates successfully when there are no flags in the database' do
- setup
-
- disable_migrations_output { migrate! }
-
- expect(flags.count).to eq(0)
- end
-
- it 'migrates successfully with a row in the table in both FOSS and EE' do
- project = setup
- flags.create!(project_id: project.id, active: true, name: 'test_flag')
-
- disable_migrations_output { migrate! }
-
- expect(flags.count).to eq(1)
- end
-end
diff --git a/spec/migrations/backfill_snippet_repositories_spec.rb b/spec/migrations/backfill_snippet_repositories_spec.rb
deleted file mode 100644
index 64cfc9cc57b..00000000000
--- a/spec/migrations/backfill_snippet_repositories_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe BackfillSnippetRepositories do
- let(:users) { table(:users) }
- let(:snippets) { table(:snippets) }
- let(:user) { users.create!(id: 1, email: 'user@example.com', projects_limit: 10, username: 'test', name: 'Test', state: 'active') }
-
- def create_snippet(id)
- params = {
- id: id,
- type: 'PersonalSnippet',
- author_id: user.id,
- file_name: 'foo',
- content: 'bar'
- }
-
- snippets.create!(params)
- end
-
- it 'correctly schedules background migrations' do
- create_snippet(1)
- create_snippet(2)
- create_snippet(3)
-
- stub_const("#{described_class.name}::BATCH_SIZE", 2)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(3.minutes, 1, 2)
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(6.minutes, 3, 3)
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
-end
diff --git a/spec/migrations/backfill_status_page_published_incidents_spec.rb b/spec/migrations/backfill_status_page_published_incidents_spec.rb
deleted file mode 100644
index fa4bb182362..00000000000
--- a/spec/migrations/backfill_status_page_published_incidents_spec.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe BackfillStatusPagePublishedIncidents, :migration do
- subject(:migration) { described_class.new }
-
- describe '#up' do
- let(:projects) { table(:projects) }
- let(:status_page_settings) { table(:status_page_settings) }
- let(:issues) { table(:issues) }
- let(:incidents) { table(:status_page_published_incidents) }
-
- let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab') }
- let(:project_without_status_page) { projects.create!(namespace_id: namespace.id) }
- let(:enabled_project) { projects.create!(namespace_id: namespace.id) }
- let(:disabled_project) { projects.create!(namespace_id: namespace.id) }
-
- let!(:enabled_setting) { status_page_settings.create!(enabled: true, project_id: enabled_project.id, **status_page_setting_attrs) }
- let!(:disabled_setting) { status_page_settings.create!(enabled: false, project_id: disabled_project.id, **status_page_setting_attrs) }
-
- let!(:published_issue) { issues.create!(confidential: false, project_id: enabled_project.id) }
- let!(:nonpublished_issue_1) { issues.create!(confidential: true, project_id: enabled_project.id) }
- let!(:nonpublished_issue_2) { issues.create!(confidential: false, project_id: disabled_project.id) }
- let!(:nonpublished_issue_3) { issues.create!(confidential: false, project_id: project_without_status_page.id) }
-
- let(:current_time) { Time.current.change(usec: 0) }
- let(:status_page_setting_attrs) do
- {
- aws_s3_bucket_name: 'bucket',
- aws_region: 'region',
- aws_access_key: 'key',
- encrypted_aws_secret_key: 'abc123',
- encrypted_aws_secret_key_iv: 'abc123'
- }
- end
-
- it 'creates a StatusPage::PublishedIncident record for each published issue' do
- travel_to(current_time) do
- expect(incidents.all).to be_empty
-
- migrate!
-
- incident = incidents.first
-
- expect(incidents.count).to eq(1)
- expect(incident.issue_id).to eq(published_issue.id)
- expect(incident.created_at).to eq(current_time)
- expect(incident.updated_at).to eq(current_time)
- end
- end
- end
-end
diff --git a/spec/migrations/backfill_user_namespace_spec.rb b/spec/migrations/backfill_user_namespace_spec.rb
new file mode 100644
index 00000000000..094aec82e9c
--- /dev/null
+++ b/spec/migrations/backfill_user_namespace_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe BackfillUserNamespace do
+ let_it_be(:migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of namespaces' do
+ migrate!
+
+ expect(migration).to have_scheduled_batched_migration(
+ table_name: :namespaces,
+ column_name: :id,
+ interval: described_class::INTERVAL
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb b/spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb
deleted file mode 100644
index 702f2e6d9bd..00000000000
--- a/spec/migrations/cap_designs_filename_length_to_new_limit_spec.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe CapDesignsFilenameLengthToNewLimit, :migration, schema: 20200528125905 do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:issues) { table(:issues) }
- let(:designs) { table(:design_management_designs) }
-
- let(:filename_below_limit) { generate_filename(254) }
- let(:filename_at_limit) { generate_filename(255) }
- let(:filename_above_limit) { generate_filename(256) }
-
- let!(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
- let!(:project) { projects.create!(name: 'gitlab', path: 'gitlab-org/gitlab', namespace_id: namespace.id) }
- let!(:issue) { issues.create!(description: 'issue', project_id: project.id) }
-
- def generate_filename(length, extension: '.png')
- name = 'a' * (length - extension.length)
-
- "#{name}#{extension}"
- end
-
- def create_design(filename)
- designs.create!(
- issue_id: issue.id,
- project_id: project.id,
- filename: filename
- )
- end
-
- it 'correctly sets filenames that are above the limit' do
- designs = [
- filename_below_limit,
- filename_at_limit,
- filename_above_limit
- ].map(&method(:create_design))
-
- migrate!
-
- designs.each(&:reload)
-
- expect(designs[0].filename).to eq(filename_below_limit)
- expect(designs[1].filename).to eq(filename_at_limit)
- expect(designs[2].filename).to eq([described_class::MODIFIED_NAME, designs[2].id, described_class::MODIFIED_EXTENSION].join)
- end
-
- it 'runs after filename limit has been set' do
- # This spec file uses the `schema:` keyword to run these tests
- # against a schema version before the one that sets the limit,
- # as otherwise we can't create the design data with filenames greater
- # than the limit.
- #
- # For this test, we migrate any skipped versions up to this migration.
- migration_context.migrate(20200602013901)
-
- create_design(filename_at_limit)
- expect { create_design(filename_above_limit) }.to raise_error(ActiveRecord::StatementInvalid)
- end
-end
diff --git a/spec/migrations/clean_grafana_url_spec.rb b/spec/migrations/clean_grafana_url_spec.rb
deleted file mode 100644
index 7a81eb3058b..00000000000
--- a/spec/migrations/clean_grafana_url_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe CleanGrafanaUrl do
- let(:application_settings_table) { table(:application_settings) }
-
- [
- 'javascript:alert(window.opener.document.location)',
- ' javascript:alert(window.opener.document.location)'
- ].each do |grafana_url|
- it "sets grafana_url back to its default value when grafana_url is '#{grafana_url}'" do
- application_settings = application_settings_table.create!(grafana_url: grafana_url)
-
- migrate!
-
- expect(application_settings.reload.grafana_url).to eq('/-/grafana')
- end
- end
-
- ['/-/grafana', '/some/relative/url', 'http://localhost:9000'].each do |grafana_url|
- it "does not modify grafana_url when grafana_url is '#{grafana_url}'" do
- application_settings = application_settings_table.create!(grafana_url: grafana_url)
-
- migrate!
-
- expect(application_settings.reload.grafana_url).to eq(grafana_url)
- end
- end
-
- context 'when application_settings table has no rows' do
- it 'does not fail' do
- migrate!
- end
- end
-end
diff --git a/spec/migrations/cleanup_empty_commit_user_mentions_spec.rb b/spec/migrations/cleanup_empty_commit_user_mentions_spec.rb
deleted file mode 100644
index d128c13e212..00000000000
--- a/spec/migrations/cleanup_empty_commit_user_mentions_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe CleanupEmptyCommitUserMentions, :migration, :sidekiq do
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:notes) { table(:notes) }
-
- let(:user) { users.create!(name: 'root', email: 'root@example.com', username: 'root', projects_limit: 0) }
- let(:group) { namespaces.create!(name: 'group1', path: 'group1', owner_id: user.id) }
- let(:project) { projects.create!(name: 'gitlab1', path: 'gitlab1', namespace_id: group.id, visibility_level: 0) }
-
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
- let(:commit) { Commit.new(RepoHelpers.sample_commit, project) }
- let(:commit_user_mentions) { table(:commit_user_mentions) }
-
- let!(:resource1) { notes.create!(commit_id: commit.id, noteable_type: 'Commit', project_id: project.id, author_id: user.id, note: 'note1 for @root to check') }
- let!(:resource2) { notes.create!(commit_id: commit.id, noteable_type: 'Commit', project_id: project.id, author_id: user.id, note: 'note1 for @root to check') }
- let!(:resource3) { notes.create!(commit_id: commit.id, noteable_type: 'Commit', project_id: project.id, author_id: user.id, note: 'note1 for @root to check', system: true) }
-
- # this note is already migrated, as it has a record in the commit_user_mentions table
- let!(:resource4) { notes.create!(note: 'note3 for @root to check', commit_id: commit.id, noteable_type: 'Commit') }
- let!(:user_mention) { commit_user_mentions.create!(commit_id: commit.id, note_id: resource4.id, mentioned_users_ids: [1]) }
-
- # these should get cleanup, by the migration
- let!(:blank_commit_user_mention1) { commit_user_mentions.create!(commit_id: commit.id, note_id: resource1.id)}
- let!(:blank_commit_user_mention2) { commit_user_mentions.create!(commit_id: commit.id, note_id: resource2.id)}
- let!(:blank_commit_user_mention3) { commit_user_mentions.create!(commit_id: commit.id, note_id: resource3.id)}
-
- it 'cleanups blank user mentions' do
- expect { migrate! }.to change { commit_user_mentions.count }.by(-3)
- end
-end
diff --git a/spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb b/spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb
deleted file mode 100644
index acd6a19779d..00000000000
--- a/spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-# frozen_string_literal: true
-
-# In order to test the CleanupGroupImportStatesWithNullUserId migration, we need
-# to first create GroupImportState with NULL user_id
-# and then run the migration to check that user_id was populated or record removed
-#
-# The problem is that the CleanupGroupImportStatesWithNullUserId migration comes
-# after the NOT NULL constraint has been added with a previous migration (AddNotNullConstraintToUserOnGroupImportStates)
-# That means that while testing the current class we can not insert GroupImportState records with an
-# invalid user_id as constraint is blocking it from doing so
-#
-# To solve this problem, use SchemaVersionFinder to set schema one version prior to AddNotNullConstraintToUserOnGroupImportStates
-
-require 'spec_helper'
-require_migration!('add_not_null_constraint_to_user_on_group_import_states')
-require_migration!
-
-RSpec.describe CleanupGroupImportStatesWithNullUserId, :migration,
- schema: MigrationHelpers::SchemaVersionFinder.migration_prior(AddNotNullConstraintToUserOnGroupImportStates) do
- let(:namespaces_table) { table(:namespaces) }
- let(:users_table) { table(:users) }
- let(:group_import_states_table) { table(:group_import_states) }
- let(:members_table) { table(:members) }
-
- describe 'Group import states clean up' do
- context 'when user_id is present' do
- it 'does not update group_import_state record' do
- user_1 = users_table.create!(name: 'user1', email: 'user1@example.com', projects_limit: 1)
- group_1 = namespaces_table.create!(name: 'group_1', path: 'group_1', type: 'Group')
- create_member(user_id: user_1.id, type: 'GroupMember', source_type: 'Namespace', source_id: group_1.id, access_level: described_class::Group::OWNER)
- group_import_state_1 = group_import_states_table.create!(group_id: group_1.id, user_id: user_1.id, status: 0)
-
- expect(group_import_state_1.user_id).to eq(user_1.id)
-
- disable_migrations_output { migrate! }
-
- expect(group_import_state_1.reload.user_id).to eq(user_1.id)
- end
- end
-
- context 'when user_id is missing' do
- it 'updates user_id with group default owner id' do
- user_2 = users_table.create!(name: 'user2', email: 'user2@example.com', projects_limit: 1)
- group_2 = namespaces_table.create!(name: 'group_2', path: 'group_2', type: 'Group')
- create_member(user_id: user_2.id, type: 'GroupMember', source_type: 'Namespace', source_id: group_2.id, access_level: described_class::Group::OWNER)
- group_import_state_2 = group_import_states_table.create!(group_id: group_2.id, user_id: nil, status: 0)
-
- disable_migrations_output { migrate! }
-
- expect(group_import_state_2.reload.user_id).to eq(user_2.id)
- end
- end
-
- context 'when group does not contain any owners' do
- it 'removes group_import_state record' do
- group_3 = namespaces_table.create!(name: 'group_3', path: 'group_3', type: 'Group')
- group_import_state_3 = group_import_states_table.create!(group_id: group_3.id, user_id: nil, status: 0)
-
- disable_migrations_output { migrate! }
-
- expect { group_import_state_3.reload }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-
- context 'when group has parent' do
- it 'updates user_id with parent group default owner id' do
- user = users_table.create!(name: 'user4', email: 'user4@example.com', projects_limit: 1)
- group_1 = namespaces_table.create!(name: 'group_1', path: 'group_1', type: 'Group')
- create_member(user_id: user.id, type: 'GroupMember', source_type: 'Namespace', source_id: group_1.id, access_level: described_class::Group::OWNER)
- group_2 = namespaces_table.create!(name: 'group_2', path: 'group_2', type: 'Group', parent_id: group_1.id)
- group_import_state = group_import_states_table.create!(group_id: group_2.id, user_id: nil, status: 0)
-
- disable_migrations_output { migrate! }
-
- expect(group_import_state.reload.user_id).to eq(user.id)
- end
- end
-
- context 'when group has owner_id' do
- it 'updates user_id with owner_id' do
- user = users_table.create!(name: 'user', email: 'user@example.com', projects_limit: 1)
- group = namespaces_table.create!(name: 'group', path: 'group', type: 'Group', owner_id: user.id)
- group_import_state = group_import_states_table.create!(group_id: group.id, user_id: nil, status: 0)
-
- disable_migrations_output { migrate! }
-
- expect(group_import_state.reload.user_id).to eq(user.id)
- end
- end
- end
-
- def create_member(options)
- members_table.create!(
- {
- notification_level: 0,
- ldap: false,
- override: false
- }.merge(options)
- )
- end
-end
diff --git a/spec/migrations/cleanup_move_container_registry_enabled_to_project_feature_spec.rb b/spec/migrations/cleanup_move_container_registry_enabled_to_project_feature_spec.rb
new file mode 100644
index 00000000000..f0f9249515b
--- /dev/null
+++ b/spec/migrations/cleanup_move_container_registry_enabled_to_project_feature_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe CleanupMoveContainerRegistryEnabledToProjectFeature, :migration do
+ let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:non_null_project_features) { { pages_access_level: 20 } }
+ let(:bg_class_name) { 'MoveContainerRegistryEnabledToProjectFeature' }
+
+ let!(:project1) { table(:projects).create!(namespace_id: namespace.id, name: 'project 1', container_registry_enabled: true) }
+ let!(:project2) { table(:projects).create!(namespace_id: namespace.id, name: 'project 2', container_registry_enabled: false) }
+ let!(:project3) { table(:projects).create!(namespace_id: namespace.id, name: 'project 3', container_registry_enabled: nil) }
+
+ let!(:project4) { table(:projects).create!(namespace_id: namespace.id, name: 'project 4', container_registry_enabled: true) }
+ let!(:project5) { table(:projects).create!(namespace_id: namespace.id, name: 'project 5', container_registry_enabled: false) }
+ let!(:project6) { table(:projects).create!(namespace_id: namespace.id, name: 'project 6', container_registry_enabled: nil) }
+
+ let!(:project_feature1) { table(:project_features).create!(project_id: project1.id, container_registry_access_level: 20, **non_null_project_features) }
+ let!(:project_feature2) { table(:project_features).create!(project_id: project2.id, container_registry_access_level: 0, **non_null_project_features) }
+ let!(:project_feature3) { table(:project_features).create!(project_id: project3.id, container_registry_access_level: 0, **non_null_project_features) }
+
+ let!(:project_feature4) { table(:project_features).create!(project_id: project4.id, container_registry_access_level: 0, **non_null_project_features) }
+ let!(:project_feature5) { table(:project_features).create!(project_id: project5.id, container_registry_access_level: 20, **non_null_project_features) }
+ let!(:project_feature6) { table(:project_features).create!(project_id: project6.id, container_registry_access_level: 20, **non_null_project_features) }
+
+ let!(:background_migration_job1) { table(:background_migration_jobs).create!(class_name: bg_class_name, arguments: [project4.id, project5.id], status: 0) }
+ let!(:background_migration_job2) { table(:background_migration_jobs).create!(class_name: bg_class_name, arguments: [project6.id, project6.id], status: 0) }
+ let!(:background_migration_job3) { table(:background_migration_jobs).create!(class_name: bg_class_name, arguments: [project1.id, project3.id], status: 1) }
+
+ it 'steals remaining jobs, updates any remaining rows and deletes background_migration_jobs rows' do
+ expect(Gitlab::BackgroundMigration).to receive(:steal).with(bg_class_name).and_call_original
+
+ migrate!
+
+ expect(project_feature1.reload.container_registry_access_level).to eq(20)
+ expect(project_feature2.reload.container_registry_access_level).to eq(0)
+ expect(project_feature3.reload.container_registry_access_level).to eq(0)
+ expect(project_feature4.reload.container_registry_access_level).to eq(20)
+ expect(project_feature5.reload.container_registry_access_level).to eq(0)
+ expect(project_feature6.reload.container_registry_access_level).to eq(0)
+
+ expect(table(:background_migration_jobs).where(class_name: bg_class_name).count).to eq(0)
+ end
+end
diff --git a/spec/migrations/cleanup_move_container_registry_enabled_to_project_features_spec.rb b/spec/migrations/cleanup_move_container_registry_enabled_to_project_features_spec.rb
deleted file mode 100644
index 3c39327304e..00000000000
--- a/spec/migrations/cleanup_move_container_registry_enabled_to_project_features_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('cleanup_move_container_registry_enabled_to_project_feature')
-
-RSpec.describe CleanupMoveContainerRegistryEnabledToProjectFeature, :migration do
- let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
- let(:non_null_project_features) { { pages_access_level: 20 } }
- let(:bg_class_name) { 'MoveContainerRegistryEnabledToProjectFeature' }
-
- let!(:project1) { table(:projects).create!(namespace_id: namespace.id, name: 'project 1', container_registry_enabled: true) }
- let!(:project2) { table(:projects).create!(namespace_id: namespace.id, name: 'project 2', container_registry_enabled: false) }
- let!(:project3) { table(:projects).create!(namespace_id: namespace.id, name: 'project 3', container_registry_enabled: nil) }
-
- let!(:project4) { table(:projects).create!(namespace_id: namespace.id, name: 'project 4', container_registry_enabled: true) }
- let!(:project5) { table(:projects).create!(namespace_id: namespace.id, name: 'project 5', container_registry_enabled: false) }
- let!(:project6) { table(:projects).create!(namespace_id: namespace.id, name: 'project 6', container_registry_enabled: nil) }
-
- let!(:project_feature1) { table(:project_features).create!(project_id: project1.id, container_registry_access_level: 20, **non_null_project_features) }
- let!(:project_feature2) { table(:project_features).create!(project_id: project2.id, container_registry_access_level: 0, **non_null_project_features) }
- let!(:project_feature3) { table(:project_features).create!(project_id: project3.id, container_registry_access_level: 0, **non_null_project_features) }
-
- let!(:project_feature4) { table(:project_features).create!(project_id: project4.id, container_registry_access_level: 0, **non_null_project_features) }
- let!(:project_feature5) { table(:project_features).create!(project_id: project5.id, container_registry_access_level: 20, **non_null_project_features) }
- let!(:project_feature6) { table(:project_features).create!(project_id: project6.id, container_registry_access_level: 20, **non_null_project_features) }
-
- let!(:background_migration_job1) { table(:background_migration_jobs).create!(class_name: bg_class_name, arguments: [project4.id, project5.id], status: 0) }
- let!(:background_migration_job2) { table(:background_migration_jobs).create!(class_name: bg_class_name, arguments: [project6.id, project6.id], status: 0) }
- let!(:background_migration_job3) { table(:background_migration_jobs).create!(class_name: bg_class_name, arguments: [project1.id, project3.id], status: 1) }
-
- it 'steals remaining jobs, updates any remaining rows and deletes background_migration_jobs rows' do
- expect(Gitlab::BackgroundMigration).to receive(:steal).with(bg_class_name).and_call_original
-
- migrate!
-
- expect(project_feature1.reload.container_registry_access_level).to eq(20)
- expect(project_feature2.reload.container_registry_access_level).to eq(0)
- expect(project_feature3.reload.container_registry_access_level).to eq(0)
- expect(project_feature4.reload.container_registry_access_level).to eq(20)
- expect(project_feature5.reload.container_registry_access_level).to eq(0)
- expect(project_feature6.reload.container_registry_access_level).to eq(0)
-
- expect(table(:background_migration_jobs).where(class_name: bg_class_name).count).to eq(0)
- end
-end
diff --git a/spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb b/spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb
deleted file mode 100644
index 2f461ebc1d5..00000000000
--- a/spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('cleanup_optimistic_locking_nulls_pt2_fixed')
-
-RSpec.describe CleanupOptimisticLockingNullsPt2Fixed, :migration, schema: 20200219193117 do
- test_tables = %w(ci_stages ci_builds ci_pipelines).freeze
- test_tables.each do |table|
- let(table.to_sym) { table(table.to_sym) }
- end
- let(:tables) { test_tables.map { |t| method(t.to_sym).call } }
-
- before do
- # Create necessary rows
- ci_stages.create!
- ci_builds.create!
- ci_pipelines.create!
-
- # Nullify `lock_version` column for all rows
- # Needs to be done with a SQL fragment, otherwise Rails will coerce it to 0
- tables.each do |table|
- table.update_all('lock_version = NULL')
- end
- end
-
- it 'correctly migrates nullified lock_version column', :sidekiq_might_not_need_inline do
- tables.each do |table|
- expect(table.where(lock_version: nil).count).to eq(1)
- end
-
- tables.each do |table|
- expect(table.where(lock_version: 0).count).to eq(0)
- end
-
- migrate!
-
- tables.each do |table|
- expect(table.where(lock_version: nil).count).to eq(0)
- end
-
- tables.each do |table|
- expect(table.where(lock_version: 0).count).to eq(1)
- end
- end
-end
diff --git a/spec/migrations/cleanup_optimistic_locking_nulls_spec.rb b/spec/migrations/cleanup_optimistic_locking_nulls_spec.rb
deleted file mode 100644
index a287d950c89..00000000000
--- a/spec/migrations/cleanup_optimistic_locking_nulls_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('cleanup_optimistic_locking_nulls')
-
-RSpec.describe CleanupOptimisticLockingNulls do
- let(:epics) { table(:epics) }
- let(:merge_requests) { table(:merge_requests) }
- let(:issues) { table(:issues) }
- let(:tables) { [epics, merge_requests, issues] }
-
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:users) { table(:users)}
-
- before do
- namespaces.create!(id: 123, name: 'gitlab1', path: 'gitlab1')
- projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1', namespace_id: 123)
- users.create!(id: 123, username: 'author', projects_limit: 1000)
-
- # Create necessary rows
- epics.create!(iid: 123, group_id: 123, author_id: 123, title: 'a', title_html: 'a')
- merge_requests.create!(iid: 123, target_project_id: 123, source_project_id: 123, target_branch: 'master', source_branch: 'hmm', title: 'a', title_html: 'a')
- issues.create!(iid: 123, project_id: 123, title: 'a', title_html: 'a')
-
- # Nullify `lock_version` column for all rows
- # Needs to be done with a SQL fragment, otherwise Rails will coerce it to 0
- tables.each do |table|
- table.update_all('lock_version = NULL')
- end
- end
-
- it 'correctly migrates nullified lock_version column', :sidekiq_inline do
- tables.each do |table|
- expect(table.where(lock_version: nil).count).to eq(1)
- end
-
- tables.each do |table|
- expect(table.where(lock_version: 0).count).to eq(0)
- end
-
- migrate!
-
- tables.each do |table|
- expect(table.where(lock_version: nil).count).to eq(0)
- end
-
- tables.each do |table|
- expect(table.where(lock_version: 0).count).to eq(1)
- end
- end
-end
diff --git a/spec/migrations/cleanup_projects_with_missing_namespace_spec.rb b/spec/migrations/cleanup_projects_with_missing_namespace_spec.rb
deleted file mode 100644
index c640bfcd174..00000000000
--- a/spec/migrations/cleanup_projects_with_missing_namespace_spec.rb
+++ /dev/null
@@ -1,142 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!('add_projects_foreign_key_to_namespaces')
-require_migration!
-
-# In order to test the CleanupProjectsWithMissingNamespace migration, we need
-# to first create an orphaned project (one with an invalid namespace_id)
-# and then run the migration to check that the project was properly cleaned up
-#
-# The problem is that the CleanupProjectsWithMissingNamespace migration comes
-# after the FK has been added with a previous migration (AddProjectsForeignKeyToNamespaces)
-# That means that while testing the current class we can not insert projects with an
-# invalid namespace_id as the existing FK is correctly blocking us from doing so
-#
-# The approach that solves that problem is to:
-# - Set the schema of this test to the one prior to AddProjectsForeignKeyToNamespaces
-# - We could hardcode it to `20200508091106` (which currently is the previous
-# migration before adding the FK) but that would mean that this test depends
-# on migration 20200508091106 not being reverted or deleted
-# - So, we use SchemaVersionFinder that finds the previous migration and returns
-# its schema, which we then use in the describe
-#
-# That means that we lock the schema version to the one returned by
-# SchemaVersionFinder.previous_migration and only test the cleanup migration
-# *without* the migration that adds the Foreign Key ever running
-# That's acceptable as the cleanup script should not be affected in any way
-# by the migration that adds the Foreign Key
-class SchemaVersionFinder
- def self.migrations_paths
- ActiveRecord::Migrator.migrations_paths
- end
-
- def self.migration_context
- ActiveRecord::MigrationContext.new(migrations_paths, ActiveRecord::SchemaMigration)
- end
-
- def self.migrations
- migration_context.migrations
- end
-
- def self.previous_migration
- migrations.each_cons(2) do |previous, migration|
- break previous.version if migration.name == AddProjectsForeignKeyToNamespaces.name
- end
- end
-end
-
-RSpec.describe CleanupProjectsWithMissingNamespace, :migration, schema: SchemaVersionFinder.previous_migration do
- let(:projects) { table(:projects) }
- let(:namespaces) { table(:namespaces) }
- let(:users) { table(:users) }
-
- before do
- namespace = namespaces.create!(name: 'existing_namespace', path: 'existing_namespace')
-
- projects.create!(
- name: 'project_with_existing_namespace',
- path: 'project_with_existing_namespace',
- visibility_level: 20,
- archived: false,
- namespace_id: namespace.id
- )
-
- projects.create!(
- name: 'project_with_non_existing_namespace',
- path: 'project_with_non_existing_namespace',
- visibility_level: 20,
- archived: false,
- namespace_id: non_existing_record_id
- )
- end
-
- it 'creates the ghost user' do
- expect(users.where(user_type: described_class::User::USER_TYPE_GHOST).count).to eq(0)
-
- disable_migrations_output { migrate! }
-
- expect(users.where(user_type: described_class::User::USER_TYPE_GHOST).count).to eq(1)
- end
-
- it 'creates the lost-and-found group, owned by the ghost user' do
- expect(
- described_class::Group.where(
- described_class::Group
- .arel_table[:name]
- .matches("#{described_class::User::LOST_AND_FOUND_GROUP}%")
- ).count
- ).to eq(0)
-
- disable_migrations_output { migrate! }
-
- ghost_user = users.find_by(user_type: described_class::User::USER_TYPE_GHOST)
- expect(
- described_class::Group
- .joins('INNER JOIN members ON namespaces.id = members.source_id')
- .where(namespaces: { type: 'Group' })
- .where(members: { type: 'GroupMember' })
- .where(members: { source_type: 'Namespace' })
- .where(members: { user_id: ghost_user.id })
- .where(members: { requested_at: nil })
- .where(members: { access_level: described_class::ACCESS_LEVEL_OWNER })
- .where(
- described_class::Group
- .arel_table[:name]
- .matches("#{described_class::User::LOST_AND_FOUND_GROUP}%")
- )
- .count
- ).to eq(1)
- end
-
- it 'moves the orphaned project to the lost-and-found group' do
- orphaned_project = projects.find_by(name: 'project_with_non_existing_namespace')
- expect(orphaned_project.visibility_level).to eq(20)
- expect(orphaned_project.archived).to eq(false)
- expect(orphaned_project.namespace_id).to eq(non_existing_record_id)
-
- disable_migrations_output { migrate! }
-
- lost_and_found_group = described_class::Group.find_by(
- described_class::Group
- .arel_table[:name]
- .matches("#{described_class::User::LOST_AND_FOUND_GROUP}%")
- )
- orphaned_project = projects.find_by(id: orphaned_project.id)
-
- expect(orphaned_project.visibility_level).to eq(0)
- expect(orphaned_project.namespace_id).to eq(lost_and_found_group.id)
- expect(orphaned_project.name).to eq("project_with_non_existing_namespace_#{orphaned_project.id}")
- expect(orphaned_project.path).to eq("project_with_non_existing_namespace_#{orphaned_project.id}")
- expect(orphaned_project.archived).to eq(true)
-
- valid_project = projects.find_by(name: 'project_with_existing_namespace')
- existing_namespace = namespaces.find_by(name: 'existing_namespace')
-
- expect(valid_project.visibility_level).to eq(20)
- expect(valid_project.namespace_id).to eq(existing_namespace.id)
- expect(valid_project.path).to eq('project_with_existing_namespace')
- expect(valid_project.archived).to eq(false)
- end
-end
diff --git a/spec/migrations/cleanup_remaining_orphan_invites_spec.rb b/spec/migrations/cleanup_remaining_orphan_invites_spec.rb
index 0eb1f5a578a..987535a4f09 100644
--- a/spec/migrations/cleanup_remaining_orphan_invites_spec.rb
+++ b/spec/migrations/cleanup_remaining_orphan_invites_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration! 'cleanup_remaining_orphan_invites'
+require_migration!
RSpec.describe CleanupRemainingOrphanInvites, :migration do
def create_member(**extra_attributes)
diff --git a/spec/migrations/complete_namespace_settings_migration_spec.rb b/spec/migrations/complete_namespace_settings_migration_spec.rb
deleted file mode 100644
index 46c455d8b19..00000000000
--- a/spec/migrations/complete_namespace_settings_migration_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe CompleteNamespaceSettingsMigration, :redis do
- let(:migration) { spy('migration') }
-
- context 'when still legacy artifacts exist' do
- let(:namespaces) { table(:namespaces) }
- let(:namespace_settings) { table(:namespace_settings) }
- let!(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
-
- it 'steals sidekiq jobs from BackfillNamespaceSettings background migration' do
- expect(Gitlab::BackgroundMigration).to receive(:steal).with('BackfillNamespaceSettings')
-
- migrate!
- end
-
- it 'migrates namespaces without namespace_settings' do
- expect { migrate! }.to change { namespace_settings.count }.from(0).to(1)
- end
- end
-end
diff --git a/spec/migrations/confirm_project_bot_users_spec.rb b/spec/migrations/confirm_project_bot_users_spec.rb
deleted file mode 100644
index 5f70181e70a..00000000000
--- a/spec/migrations/confirm_project_bot_users_spec.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ConfirmProjectBotUsers, :migration do
- let(:users) { table(:users) }
-
- context 'project bot users that are currently unconfirmed' do
- let!(:project_bot_1) do
- create_user!(
- name: 'bot_1',
- email: 'bot_1@example.com',
- created_at: 2.days.ago,
- user_type: described_class::User::USER_TYPE_PROJECT_BOT
- )
- end
-
- let!(:project_bot_2) do
- create_user!(
- name: 'bot_2',
- email: 'bot_2@example.com',
- created_at: 4.days.ago,
- user_type: described_class::User::USER_TYPE_PROJECT_BOT
- )
- end
-
- it 'updates their `confirmed_at` attribute' do
- expect { migrate! }
- .to change { project_bot_1.reload.confirmed_at }
- .and change { project_bot_2.reload.confirmed_at }
- end
-
- it 'sets `confirmed_at` to be the same as their `created_at` attribute' do
- migrate!
-
- [project_bot_1, project_bot_2].each do |bot|
- expect(bot.reload.confirmed_at).to eq(bot.created_at)
- end
- end
- end
-
- context 'project bot users that are currently confirmed' do
- let!(:confirmed_project_bot) do
- create_user!(
- name: 'bot_1',
- email: 'bot_1@example.com',
- user_type: described_class::User::USER_TYPE_PROJECT_BOT,
- confirmed_at: 1.day.ago
- )
- end
-
- it 'does not update their `confirmed_at` attribute' do
- expect { migrate! }.not_to change { confirmed_project_bot.reload.confirmed_at }
- end
- end
-
- context 'human users that are currently unconfirmed' do
- let!(:unconfirmed_human) do
- create_user!(
- name: 'human',
- email: 'human@example.com',
- user_type: nil
- )
- end
-
- it 'does not update their `confirmed_at` attribute' do
- expect { migrate! }.not_to change { unconfirmed_human.reload.confirmed_at }
- end
- end
-
- private
-
- def create_user!(name:, email:, user_type:, created_at: Time.now, confirmed_at: nil)
- users.create!(
- name: name,
- email: email,
- username: name,
- projects_limit: 0,
- user_type: user_type,
- confirmed_at: confirmed_at
- )
- end
-end
diff --git a/spec/migrations/create_environment_for_self_monitoring_project_spec.rb b/spec/migrations/create_environment_for_self_monitoring_project_spec.rb
deleted file mode 100644
index 4615c231510..00000000000
--- a/spec/migrations/create_environment_for_self_monitoring_project_spec.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe CreateEnvironmentForSelfMonitoringProject do
- let(:application_settings_table) { table(:application_settings) }
-
- let(:environments) { table(:environments) }
-
- let(:instance_administrators_group) do
- table(:namespaces).create!(
- id: 1,
- name: 'GitLab Instance Administrators',
- path: 'gitlab-instance-administrators-random',
- type: 'Group'
- )
- end
-
- let(:self_monitoring_project) do
- table(:projects).create!(
- id: 2,
- name: 'Self Monitoring',
- path: 'self_monitoring',
- namespace_id: instance_administrators_group.id
- )
- end
-
- context 'when the self monitoring project ID is not set' do
- it 'does not make changes' do
- expect(environments.find_by(project_id: self_monitoring_project.id)).to be_nil
-
- migrate!
-
- expect(environments.find_by(project_id: self_monitoring_project.id)).to be_nil
- end
- end
-
- context 'when the self monitoring project ID is set' do
- before do
- application_settings_table.create!(instance_administration_project_id: self_monitoring_project.id)
- end
-
- context 'when the environment already exists' do
- let!(:environment) do
- environments.create!(project_id: self_monitoring_project.id, name: 'production', slug: 'production')
- end
-
- it 'does not make changes' do
- expect(environments.find_by(project_id: self_monitoring_project.id)).to eq(environment)
-
- migrate!
-
- expect(environments.find_by(project_id: self_monitoring_project.id)).to eq(environment)
- end
- end
-
- context 'when the environment does not exist' do
- it 'creates the environment' do
- expect(environments.find_by(project_id: self_monitoring_project.id)).to be_nil
-
- migrate!
-
- expect(environments.find_by(project_id: self_monitoring_project.id)).to be
- end
- end
- end
-end
diff --git a/spec/migrations/deduplicate_epic_iids_spec.rb b/spec/migrations/deduplicate_epic_iids_spec.rb
deleted file mode 100644
index c9dd5b3253b..00000000000
--- a/spec/migrations/deduplicate_epic_iids_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe DeduplicateEpicIids, :migration, schema: 20201106082723 do
- let(:routes) { table(:routes) }
- let(:epics) { table(:epics) }
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
-
- let!(:group) { create_group('foo') }
- let!(:user) { users.create!(email: 'test@example.com', projects_limit: 100, username: 'test') }
- let!(:dup_epic1) { epics.create!(iid: 1, title: 'epic 1', group_id: group.id, author_id: user.id, created_at: Time.now, updated_at: Time.now, title_html: 'any') }
- let!(:dup_epic2) { epics.create!(iid: 1, title: 'epic 2', group_id: group.id, author_id: user.id, created_at: Time.now, updated_at: Time.now, title_html: 'any') }
- let!(:dup_epic3) { epics.create!(iid: 1, title: 'epic 3', group_id: group.id, author_id: user.id, created_at: Time.now, updated_at: Time.now, title_html: 'any') }
-
- it 'deduplicates epic iids', :aggregate_failures do
- duplicate_epics_count = epics.where(iid: 1, group_id: group.id).count
- expect(duplicate_epics_count).to eq 3
-
- migrate!
-
- duplicate_epics_count = epics.where(iid: 1, group_id: group.id).count
- expect(duplicate_epics_count).to eq 1
- expect(dup_epic1.reload.iid).to eq 1
- expect(dup_epic2.reload.iid).to eq 2
- expect(dup_epic3.reload.iid).to eq 3
- end
-
- def create_group(path)
- namespaces.create!(name: path, path: path, type: 'Group').tap do |namespace|
- routes.create!(path: namespace.path, name: namespace.name, source_id: namespace.id, source_type: 'Namespace')
- end
- end
-end
diff --git a/spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb b/spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb
deleted file mode 100644
index 30d776c498b..00000000000
--- a/spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe DeleteInternalIdsWhereFeatureFlagsUsage do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:internal_ids) { table(:internal_ids) }
-
- def setup
- namespace = namespaces.create!(name: 'foo', path: 'foo')
- projects.create!(namespace_id: namespace.id)
- end
-
- it 'deletes feature flag rows from the internal_ids table' do
- project = setup
- internal_ids.create!(project_id: project.id, usage: 6, last_value: 1)
-
- disable_migrations_output { migrate! }
-
- expect(internal_ids.count).to eq(0)
- end
-
- it 'does not delete issue rows from the internal_ids table' do
- project = setup
- internal_ids.create!(project_id: project.id, usage: 0, last_value: 1)
-
- disable_migrations_output { migrate! }
-
- expect(internal_ids.count).to eq(1)
- end
-
- it 'does not delete merge request rows from the internal_ids table' do
- project = setup
- internal_ids.create!(project_id: project.id, usage: 1, last_value: 1)
-
- disable_migrations_output { migrate! }
-
- expect(internal_ids.count).to eq(1)
- end
-end
diff --git a/spec/migrations/delete_template_project_services_spec.rb b/spec/migrations/delete_template_project_services_spec.rb
deleted file mode 100644
index 20532e4187a..00000000000
--- a/spec/migrations/delete_template_project_services_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe DeleteTemplateProjectServices, :migration do
- let(:services) { table(:services) }
- let(:project) { table(:projects).create!(namespace_id: 1) }
-
- before do
- services.create!(template: true, project_id: project.id)
- services.create!(template: true)
- services.create!(template: false, project_id: project.id)
- end
-
- it 'deletes services when template and attached to a project' do
- expect { migrate! }.to change { services.where(template: true, project_id: project.id).count }.from(1).to(0)
- .and not_change { services.where(template: true, project_id: nil).count }
- .and not_change { services.where(template: false).where.not(project_id: nil).count }
- end
-end
diff --git a/spec/migrations/delete_template_services_duplicated_by_type_spec.rb b/spec/migrations/delete_template_services_duplicated_by_type_spec.rb
deleted file mode 100644
index 577fea984da..00000000000
--- a/spec/migrations/delete_template_services_duplicated_by_type_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe DeleteTemplateServicesDuplicatedByType do
- let(:services) { table(:services) }
-
- before do
- services.create!(template: true, type: 'JenkinsService')
- services.create!(template: true, type: 'JenkinsService')
- services.create!(template: true, type: 'JiraService')
- services.create!(template: true, type: 'JenkinsService')
- end
-
- it 'deletes service templates duplicated by type except the one with the lowest ID' do
- jenkins_integration_id = services.where(type: 'JenkinsService').order(:id).pluck(:id).first
- jira_integration_id = services.where(type: 'JiraService').pluck(:id).first
-
- migrate!
-
- expect(services.pluck(:id)).to contain_exactly(jenkins_integration_id, jira_integration_id)
- end
-end
diff --git a/spec/migrations/delete_user_callout_alerts_moved_spec.rb b/spec/migrations/delete_user_callout_alerts_moved_spec.rb
deleted file mode 100644
index 401cf77628d..00000000000
--- a/spec/migrations/delete_user_callout_alerts_moved_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe DeleteUserCalloutAlertsMoved do
- let(:users) { table(:users) }
- let(:user_callouts) { table(:user_callouts) }
- let(:alerts_moved_feature) { described_class::FEATURE_NAME_ALERTS_MOVED }
- let(:unrelated_feature) { 1 }
-
- let!(:user1) { users.create!(email: '1', projects_limit: 0) }
- let!(:user2) { users.create!(email: '2', projects_limit: 0) }
-
- subject(:migration) { described_class.new }
-
- before do
- user_callouts.create!(user_id: user1.id, feature_name: alerts_moved_feature)
- user_callouts.create!(user_id: user1.id, feature_name: unrelated_feature)
- user_callouts.create!(user_id: user2.id, feature_name: alerts_moved_feature)
- end
-
- describe '#up' do
- it 'deletes `alerts_moved` user callouts' do
- migration.up
-
- expect(user_callouts.all.map(&:feature_name)).to eq([unrelated_feature])
- end
- end
-end
diff --git a/spec/migrations/drop_activate_prometheus_services_background_jobs_spec.rb b/spec/migrations/drop_activate_prometheus_services_background_jobs_spec.rb
deleted file mode 100644
index c6115d5889c..00000000000
--- a/spec/migrations/drop_activate_prometheus_services_background_jobs_spec.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe DropActivatePrometheusServicesBackgroundJobs, :sidekiq, :redis, schema: 2020_02_21_144534 do
- subject(:migration) { described_class.new }
-
- describe '#up' do
- let(:retry_set) { Sidekiq::RetrySet.new }
- let(:scheduled_set) { Sidekiq::ScheduledSet.new }
-
- context 'there are only affected jobs on the queue' do
- let(:payload) { { 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1] } }
- let(:queue_payload) { payload.merge('queue' => described_class::QUEUE) }
-
- it 'removes enqueued ActivatePrometheusServicesForSharedClusterApplications background jobs' do
- Sidekiq::Testing.disable! do # https://github.com/mperham/sidekiq/wiki/testing#api Sidekiq's API does not have a testing mode
- retry_set.schedule(1.hour.from_now, payload)
- scheduled_set.schedule(1.hour.from_now, payload)
- Sidekiq::Client.push(queue_payload)
-
- expect { migration.up }.to change { Sidekiq::Queue.new(described_class::QUEUE).size }.from(1).to(0)
- expect(retry_set.size).to eq(0)
- expect(scheduled_set.size).to eq(0)
- end
- end
- end
-
- context "there aren't any affected jobs on the queue" do
- let(:payload) { { 'class' => ::BackgroundMigrationWorker, 'args' => ['SomeOtherClass', 1] } }
- let(:queue_payload) { payload.merge('queue' => described_class::QUEUE) }
-
- it 'skips other enqueued jobs' do
- Sidekiq::Testing.disable! do
- retry_set.schedule(1.hour.from_now, payload)
- scheduled_set.schedule(1.hour.from_now, payload)
- Sidekiq::Client.push(queue_payload)
-
- expect { migration.up }.not_to change { Sidekiq::Queue.new(described_class::QUEUE).size }
- expect(retry_set.size).to eq(1)
- expect(scheduled_set.size).to eq(1)
- end
- end
- end
-
- context "there are multiple types of jobs on the queue" do
- let(:payload) { { 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1] } }
- let(:queue_payload) { payload.merge('queue' => described_class::QUEUE) }
-
- it 'skips other enqueued jobs' do
- Sidekiq::Testing.disable! do
- queue = Sidekiq::Queue.new(described_class::QUEUE)
- # these jobs will be deleted
- retry_set.schedule(1.hour.from_now, payload)
- scheduled_set.schedule(1.hour.from_now, payload)
- Sidekiq::Client.push(queue_payload)
- # this jobs will be skipped
- skipped_jobs_args = [['SomeOtherClass', 1], [described_class::DROPPED_JOB_CLASS, 'wrong id type'], [described_class::DROPPED_JOB_CLASS, 1, 'some wired argument']]
- skipped_jobs_args.each do |args|
- retry_set.schedule(1.hour.from_now, { 'class' => ::BackgroundMigrationWorker, 'args' => args })
- scheduled_set.schedule(1.hour.from_now, { 'class' => ::BackgroundMigrationWorker, 'args' => args })
- Sidekiq::Client.push('queue' => described_class::QUEUE, 'class' => ::BackgroundMigrationWorker, 'args' => args)
- end
-
- migration.up
-
- expect(retry_set.size).to be 3
- expect(scheduled_set.size).to be 3
- expect(queue.size).to be 3
- expect(queue.map(&:args)).to match_array skipped_jobs_args
- expect(retry_set.map(&:args)).to match_array skipped_jobs_args
- expect(scheduled_set.map(&:args)).to match_array skipped_jobs_args
- end
- end
- end
-
- context "other queues" do
- it 'does not modify them' do
- Sidekiq::Testing.disable! do
- Sidekiq::Client.push('queue' => 'other', 'class' => ::BackgroundMigrationWorker, 'args' => ['SomeOtherClass', 1])
- Sidekiq::Client.push('queue' => 'other', 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1])
-
- expect { migration.up }.not_to change { Sidekiq::Queue.new('other').size }
- end
- end
- end
- end
-end
diff --git a/spec/migrations/drop_background_migration_jobs_spec.rb b/spec/migrations/drop_background_migration_jobs_spec.rb
deleted file mode 100644
index 82b3f9f7187..00000000000
--- a/spec/migrations/drop_background_migration_jobs_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe DropBackgroundMigrationJobs, :sidekiq, :redis, schema: 2020_01_16_051619 do
- subject(:migration) { described_class.new }
-
- describe '#up' do
- context 'there are only affected jobs on the queue' do
- it 'removes enqueued ActivatePrometheusServicesForSharedClusterApplications background jobs' do
- Sidekiq::Testing.disable! do # https://github.com/mperham/sidekiq/wiki/testing#api Sidekiq's API does not have a testing mode
- Sidekiq::Client.push('queue' => described_class::QUEUE, 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1])
-
- expect { migration.up }.to change { Sidekiq::Queue.new(described_class::QUEUE).size }.from(1).to(0)
- end
- end
- end
-
- context "there aren't any affected jobs on the queue" do
- it 'skips other enqueued jobs' do
- Sidekiq::Testing.disable! do
- Sidekiq::Client.push('queue' => described_class::QUEUE, 'class' => ::BackgroundMigrationWorker, 'args' => ['SomeOtherClass', 1])
-
- expect { migration.up }.not_to change { Sidekiq::Queue.new(described_class::QUEUE).size }
- end
- end
- end
-
- context "there are multiple types of jobs on the queue" do
- it 'skips other enqueued jobs' do
- Sidekiq::Testing.disable! do
- queue = Sidekiq::Queue.new(described_class::QUEUE)
- # this job will be deleted
- Sidekiq::Client.push('queue' => described_class::QUEUE, 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1])
- # this jobs will be skipped
- skipped_jobs_args = [['SomeOtherClass', 1], [described_class::DROPPED_JOB_CLASS, 'wrong id type'], [described_class::DROPPED_JOB_CLASS, 1, 'some wired argument']]
- skipped_jobs_args.each do |args|
- Sidekiq::Client.push('queue' => described_class::QUEUE, 'class' => ::BackgroundMigrationWorker, 'args' => args)
- end
-
- migration.up
-
- expect(queue.size).to be 3
- expect(queue.map(&:args)).to match_array skipped_jobs_args
- end
- end
- end
-
- context "other queues" do
- it 'does not modify them' do
- Sidekiq::Testing.disable! do
- Sidekiq::Client.push('queue' => 'other', 'class' => ::BackgroundMigrationWorker, 'args' => ['SomeOtherClass', 1])
- Sidekiq::Client.push('queue' => 'other', 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1])
-
- expect { migration.up }.not_to change { Sidekiq::Queue.new('other').size }
- end
- end
- end
- end
-end
diff --git a/spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb b/spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb
deleted file mode 100644
index 6998e7a91cf..00000000000
--- a/spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe EnsureFilledExternalDiffStoreOnMergeRequestDiffs, schema: 20200908095446 do
- let!(:merge_request_diffs) { table(:merge_request_diffs) }
- let!(:merge_requests) { table(:merge_requests) }
- let!(:namespaces) { table(:namespaces) }
- let!(:projects) { table(:projects) }
- let!(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
- let!(:project) { projects.create!(namespace_id: namespace.id) }
- let!(:merge_request) { merge_requests.create!(source_branch: 'x', target_branch: 'master', target_project_id: project.id) }
-
- before do
- constraint_name = 'check_93ee616ac9'
-
- # In order to insert a row with a NULL to fill.
- ActiveRecord::Base.connection.execute "ALTER TABLE merge_request_diffs DROP CONSTRAINT #{constraint_name}"
-
- @external_diff_store_1 = merge_request_diffs.create!(external_diff_store: 1, merge_request_id: merge_request.id)
- @external_diff_store_2 = merge_request_diffs.create!(external_diff_store: 2, merge_request_id: merge_request.id)
- @external_diff_store_nil = merge_request_diffs.create!(external_diff_store: nil, merge_request_id: merge_request.id)
-
- # revert DB structure
- ActiveRecord::Base.connection.execute "ALTER TABLE merge_request_diffs ADD CONSTRAINT #{constraint_name} CHECK ((external_diff_store IS NOT NULL)) NOT VALID"
- end
-
- it 'correctly migrates nil external_diff_store to 1' do
- migrate!
-
- @external_diff_store_1.reload
- @external_diff_store_2.reload
- @external_diff_store_nil.reload
-
- expect(@external_diff_store_1.external_diff_store).to eq(1) # unchanged
- expect(@external_diff_store_2.external_diff_store).to eq(2) # unchanged
- expect(@external_diff_store_nil.external_diff_store).to eq(1) # nil => 1
- end
-end
diff --git a/spec/migrations/ensure_filled_file_store_on_package_files_spec.rb b/spec/migrations/ensure_filled_file_store_on_package_files_spec.rb
deleted file mode 100644
index 5cfc3a6eeb8..00000000000
--- a/spec/migrations/ensure_filled_file_store_on_package_files_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe EnsureFilledFileStoreOnPackageFiles, schema: 20200910175553 do
- let!(:packages_package_files) { table(:packages_package_files) }
- let!(:packages_packages) { table(:packages_packages) }
- let!(:namespaces) { table(:namespaces) }
- let!(:projects) { table(:projects) }
- let!(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
- let!(:project) { projects.create!(namespace_id: namespace.id) }
- let!(:package) { packages_packages.create!(project_id: project.id, name: 'bar', package_type: 1) }
-
- before do
- constraint_name = 'check_4c5e6bb0b3'
-
- # In order to insert a row with a NULL to fill.
- ActiveRecord::Base.connection.execute "ALTER TABLE packages_package_files DROP CONSTRAINT #{constraint_name}"
-
- @file_store_1 = packages_package_files.create!(file_store: 1, file_name: 'foo_1', file: 'foo_1', package_id: package.id)
- @file_store_2 = packages_package_files.create!(file_store: 2, file_name: 'foo_2', file: 'foo_2', package_id: package.id)
- @file_store_nil = packages_package_files.create!(file_store: nil, file_name: 'foo_nil', file: 'foo_nil', package_id: package.id)
-
- # revert DB structure
- ActiveRecord::Base.connection.execute "ALTER TABLE packages_package_files ADD CONSTRAINT #{constraint_name} CHECK ((file_store IS NOT NULL)) NOT VALID"
- end
-
- it 'correctly migrates nil file_store to 1' do
- migrate!
-
- @file_store_1.reload
- @file_store_2.reload
- @file_store_nil.reload
-
- expect(@file_store_1.file_store).to eq(1) # unchanged
- expect(@file_store_2.file_store).to eq(2) # unchanged
- expect(@file_store_nil.file_store).to eq(1) # nil => 1
- end
-end
diff --git a/spec/migrations/ensure_namespace_settings_creation_spec.rb b/spec/migrations/ensure_namespace_settings_creation_spec.rb
deleted file mode 100644
index b105e678d35..00000000000
--- a/spec/migrations/ensure_namespace_settings_creation_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe EnsureNamespaceSettingsCreation do
- context 'when there are namespaces without namespace settings' do
- let(:namespaces) { table(:namespaces) }
- let(:namespace_settings) { table(:namespace_settings) }
- let!(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
- let!(:namespace_2) { namespaces.create!(name: 'gitlab', path: 'gitlab-org2') }
-
- it 'migrates namespaces without namespace_settings' do
- stub_const("#{described_class.name}::BATCH_SIZE", 2)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(2.minutes.to_i, namespace.id, namespace_2.id)
- end
- end
- end
-
- it 'schedules migrations in batches' do
- stub_const("#{described_class.name}::BATCH_SIZE", 2)
-
- namespace_3 = namespaces.create!(name: 'gitlab', path: 'gitlab-org3')
- namespace_4 = namespaces.create!(name: 'gitlab', path: 'gitlab-org4')
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(2.minutes.to_i, namespace.id, namespace_2.id)
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(4.minutes.to_i, namespace_3.id, namespace_4.id)
- end
- end
- end
- end
-end
diff --git a/spec/migrations/ensure_target_project_id_is_filled_spec.rb b/spec/migrations/ensure_target_project_id_is_filled_spec.rb
deleted file mode 100644
index 7a9f49390fb..00000000000
--- a/spec/migrations/ensure_target_project_id_is_filled_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe EnsureTargetProjectIdIsFilled, schema: 20200827085101 do
- let_it_be(:namespaces) { table(:namespaces) }
- let_it_be(:projects) { table(:projects) }
- let_it_be(:merge_requests) { table(:merge_requests) }
- let_it_be(:metrics) { table(:merge_request_metrics) }
-
- let!(:namespace) { namespaces.create!(name: 'namespace', path: 'namespace') }
- let!(:project_1) { projects.create!(namespace_id: namespace.id) }
- let!(:project_2) { projects.create!(namespace_id: namespace.id) }
- let!(:merge_request_to_migrate_1) { merge_requests.create!(source_branch: 'a', target_branch: 'b', target_project_id: project_1.id) }
- let!(:merge_request_to_migrate_2) { merge_requests.create!(source_branch: 'c', target_branch: 'd', target_project_id: project_2.id) }
- let!(:merge_request_not_to_migrate) { merge_requests.create!(source_branch: 'e', target_branch: 'f', target_project_id: project_1.id) }
-
- let!(:metrics_1) { metrics.create!(merge_request_id: merge_request_to_migrate_1.id) }
- let!(:metrics_2) { metrics.create!(merge_request_id: merge_request_to_migrate_2.id) }
- let!(:metrics_3) { metrics.create!(merge_request_id: merge_request_not_to_migrate.id, target_project_id: project_1.id) }
-
- it 'migrates missing target_project_ids' do
- migrate!
-
- expect(metrics_1.reload.target_project_id).to eq(project_1.id)
- expect(metrics_2.reload.target_project_id).to eq(project_2.id)
- expect(metrics_3.reload.target_project_id).to eq(project_1.id)
- end
-end
diff --git a/spec/migrations/ensure_u2f_registrations_migrated_spec.rb b/spec/migrations/ensure_u2f_registrations_migrated_spec.rb
deleted file mode 100644
index 01db29c0edf..00000000000
--- a/spec/migrations/ensure_u2f_registrations_migrated_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe EnsureU2fRegistrationsMigrated, schema: 20201022144501 do
- let(:u2f_registrations) { table(:u2f_registrations) }
- let(:webauthn_registrations) { table(:webauthn_registrations) }
- let(:users) { table(:users) }
-
- let(:user) { users.create!(email: 'email@email.com', name: 'foo', username: 'foo', projects_limit: 0) }
-
- before do
- create_u2f_registration(1, 'reg1')
- create_u2f_registration(2, 'reg2')
- webauthn_registrations.create!({ name: 'reg1', u2f_registration_id: 1, credential_xid: '', public_key: '', user_id: user.id })
- end
-
- it 'correctly migrates u2f registrations previously not migrated' do
- expect { migrate! }.to change { webauthn_registrations.count }.from(1).to(2)
- end
-
- it 'migrates all valid u2f registrations depite errors' do
- create_u2f_registration(3, 'reg3', 'invalid!')
- create_u2f_registration(4, 'reg4')
-
- expect { migrate! }.to change { webauthn_registrations.count }.from(1).to(3)
- end
-
- def create_u2f_registration(id, name, public_key = nil)
- device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5), { key_handle: SecureRandom.random_bytes(255) })
- public_key ||= Base64.strict_encode64(device.origin_public_key_raw)
- u2f_registrations.create!({ id: id,
- certificate: Base64.strict_encode64(device.cert_raw),
- key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
- public_key: public_key,
- counter: 5,
- name: name,
- user_id: user.id })
- end
-end
diff --git a/spec/migrations/fill_file_store_ci_job_artifacts_spec.rb b/spec/migrations/fill_file_store_ci_job_artifacts_spec.rb
deleted file mode 100644
index 7adcf74bdba..00000000000
--- a/spec/migrations/fill_file_store_ci_job_artifacts_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe FillFileStoreCiJobArtifacts do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:builds) { table(:ci_builds) }
- let(:job_artifacts) { table(:ci_job_artifacts) }
-
- before do
- namespaces.create!(id: 123, name: 'sample', path: 'sample')
- projects.create!(id: 123, name: 'sample', path: 'sample', namespace_id: 123)
- builds.create!(id: 1)
- end
-
- context 'when file_store is nil' do
- it 'updates file_store to local' do
- job_artifacts.create!(project_id: 123, job_id: 1, file_type: 1, file_store: nil)
- job_artifact = job_artifacts.find_by(project_id: 123, job_id: 1)
-
- expect { migrate! }.to change { job_artifact.reload.file_store }.from(nil).to(1)
- end
- end
-
- context 'when file_store is set to local' do
- it 'does not update file_store' do
- job_artifacts.create!(project_id: 123, job_id: 1, file_type: 1, file_store: 1)
- job_artifact = job_artifacts.find_by(project_id: 123, job_id: 1)
-
- expect { migrate! }.not_to change { job_artifact.reload.file_store }
- end
- end
-
- context 'when file_store is set to object storage' do
- it 'does not update file_store' do
- job_artifacts.create!(project_id: 123, job_id: 1, file_type: 1, file_store: 2)
- job_artifact = job_artifacts.find_by(project_id: 123, job_id: 1)
-
- expect { migrate! }.not_to change { job_artifact.reload.file_store }
- end
- end
-end
diff --git a/spec/migrations/fill_file_store_lfs_objects_spec.rb b/spec/migrations/fill_file_store_lfs_objects_spec.rb
deleted file mode 100644
index 688976f79e8..00000000000
--- a/spec/migrations/fill_file_store_lfs_objects_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe FillFileStoreLfsObjects do
- let(:lfs_objects) { table(:lfs_objects) }
- let(:oid) { 'b804383982bb89b00e828e3f44c038cc991d3d1768009fc39ba8e2c081b9fb75' }
-
- context 'when file_store is nil' do
- it 'updates file_store to local' do
- lfs_objects.create!(oid: oid, size: 1062, file_store: nil)
- lfs_object = lfs_objects.find_by(oid: oid)
-
- expect { migrate! }.to change { lfs_object.reload.file_store }.from(nil).to(1)
- end
- end
-
- context 'when file_store is set to local' do
- it 'does not update file_store' do
- lfs_objects.create!(oid: oid, size: 1062, file_store: 1)
- lfs_object = lfs_objects.find_by(oid: oid)
-
- expect { migrate! }.not_to change { lfs_object.reload.file_store }
- end
- end
-
- context 'when file_store is set to object storage' do
- it 'does not update file_store' do
- lfs_objects.create!(oid: oid, size: 1062, file_store: 2)
- lfs_object = lfs_objects.find_by(oid: oid)
-
- expect { migrate! }.not_to change { lfs_object.reload.file_store }
- end
- end
-end
diff --git a/spec/migrations/fill_store_uploads_spec.rb b/spec/migrations/fill_store_uploads_spec.rb
deleted file mode 100644
index 19db7c2b48d..00000000000
--- a/spec/migrations/fill_store_uploads_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe FillStoreUploads do
- let(:uploads) { table(:uploads) }
- let(:path) { 'uploads/-/system/avatar.jpg' }
-
- context 'when store is nil' do
- it 'updates store to local' do
- uploads.create!(size: 100.kilobytes,
- uploader: 'AvatarUploader',
- path: path,
- store: nil)
-
- upload = uploads.find_by(path: path)
-
- expect { migrate! }.to change { upload.reload.store }.from(nil).to(1)
- end
- end
-
- context 'when store is set to local' do
- it 'does not update store' do
- uploads.create!(size: 100.kilobytes,
- uploader: 'AvatarUploader',
- path: path,
- store: 1)
-
- upload = uploads.find_by(path: path)
-
- expect { migrate! }.not_to change { upload.reload.store }
- end
- end
-
- context 'when store is set to object storage' do
- it 'does not update store' do
- uploads.create!(size: 100.kilobytes,
- uploader: 'AvatarUploader',
- path: path,
- store: 2)
-
- upload = uploads.find_by(path: path)
-
- expect { migrate! }.not_to change { upload.reload.store }
- end
- end
-end
diff --git a/spec/migrations/fix_projects_without_project_feature_spec.rb b/spec/migrations/fix_projects_without_project_feature_spec.rb
deleted file mode 100644
index d8c5e7a28c0..00000000000
--- a/spec/migrations/fix_projects_without_project_feature_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe FixProjectsWithoutProjectFeature do
- let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
-
- let!(:projects) do
- [
- table(:projects).create!(namespace_id: namespace.id, name: 'foo 1'),
- table(:projects).create!(namespace_id: namespace.id, name: 'foo 2'),
- table(:projects).create!(namespace_id: namespace.id, name: 'foo 3')
- ]
- end
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 2)
- end
-
- around do |example|
- Sidekiq::Testing.fake! do
- freeze_time do
- example.call
- end
- end
- end
-
- it 'schedules jobs for ranges of projects' do
- migrate!
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(2.minutes, projects[0].id, projects[1].id)
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(4.minutes, projects[2].id, projects[2].id)
- end
-
- it 'schedules jobs according to the configured batch size' do
- expect { migrate! }.to change { BackgroundMigrationWorker.jobs.size }.by(2)
- end
-end
diff --git a/spec/migrations/fix_projects_without_prometheus_services_spec.rb b/spec/migrations/fix_projects_without_prometheus_services_spec.rb
deleted file mode 100644
index dc03f381abd..00000000000
--- a/spec/migrations/fix_projects_without_prometheus_services_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-#
-require 'spec_helper'
-require_migration!('fix_projects_without_prometheus_service')
-
-RSpec.describe FixProjectsWithoutPrometheusService, :migration do
- let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
-
- let!(:projects) do
- [
- table(:projects).create!(namespace_id: namespace.id, name: 'foo 1'),
- table(:projects).create!(namespace_id: namespace.id, name: 'foo 2'),
- table(:projects).create!(namespace_id: namespace.id, name: 'foo 3')
- ]
- end
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 2)
- end
-
- around do |example|
- Sidekiq::Testing.fake! do
- freeze_time do
- example.call
- end
- end
- end
-
- it 'schedules jobs for ranges of projects' do
- migrate!
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(2.minutes, projects[0].id, projects[1].id)
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(4.minutes, projects[2].id, projects[2].id)
- end
-
- it 'schedules jobs according to the configured batch size' do
- expect { migrate! }.to change { BackgroundMigrationWorker.jobs.size }.by(2)
- end
-end
diff --git a/spec/migrations/generate_ci_jwt_signing_key_spec.rb b/spec/migrations/generate_ci_jwt_signing_key_spec.rb
deleted file mode 100644
index 7a895284aa1..00000000000
--- a/spec/migrations/generate_ci_jwt_signing_key_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe GenerateCiJwtSigningKey do
- let(:application_settings) do
- Class.new(ActiveRecord::Base) do
- self.table_name = 'application_settings'
-
- attr_encrypted :ci_jwt_signing_key, {
- mode: :per_attribute_iv,
- key: Gitlab::Utils.ensure_utf8_size(Rails.application.secrets.db_key_base, bytes: 32.bytes),
- algorithm: 'aes-256-gcm',
- encode: true
- }
- end
- end
-
- it 'generates JWT signing key' do
- application_settings.create!
-
- reversible_migration do |migration|
- migration.before -> {
- settings = application_settings.first
-
- expect(settings.ci_jwt_signing_key).to be_nil
- expect(settings.encrypted_ci_jwt_signing_key).to be_nil
- expect(settings.encrypted_ci_jwt_signing_key_iv).to be_nil
- }
-
- migration.after -> {
- settings = application_settings.first
-
- expect(settings.encrypted_ci_jwt_signing_key).to be_present
- expect(settings.encrypted_ci_jwt_signing_key_iv).to be_present
- expect { OpenSSL::PKey::RSA.new(settings.ci_jwt_signing_key) }.not_to raise_error
- }
- end
- end
-end
diff --git a/spec/migrations/generate_missing_routes_for_bots_spec.rb b/spec/migrations/generate_missing_routes_for_bots_spec.rb
deleted file mode 100644
index 594e51b4410..00000000000
--- a/spec/migrations/generate_missing_routes_for_bots_spec.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe GenerateMissingRoutesForBots, :migration do
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:routes) { table(:routes) }
-
- let(:visual_review_bot) do
- users.create!(email: 'visual-review-bot@gitlab.com', name: 'GitLab Visual Review Bot', username: 'visual-review-bot', user_type: 3, projects_limit: 5)
- end
-
- let(:migration_bot) do
- users.create!(email: 'migration-bot@gitlab.com', name: 'GitLab Migration Bot', username: 'migration-bot', user_type: 7, projects_limit: 5)
- end
-
- let!(:visual_review_bot_namespace) do
- namespaces.create!(owner_id: visual_review_bot.id, name: visual_review_bot.name, path: visual_review_bot.username)
- end
-
- let!(:migration_bot_namespace) do
- namespaces.create!(owner_id: migration_bot.id, name: migration_bot.name, path: migration_bot.username)
- end
-
- context 'for bot users without an existing route' do
- it 'creates new routes' do
- expect { migrate! }.to change { routes.count }.by(2)
- end
-
- it 'creates new routes with the same path and name as their namespace' do
- migrate!
-
- [visual_review_bot, migration_bot].each do |bot|
- namespace = namespaces.find_by(owner_id: bot.id)
- route = route_for(namespace: namespace)
-
- expect(route.path).to eq(namespace.path)
- expect(route.name).to eq(namespace.name)
- end
- end
- end
-
- it 'does not create routes for bot users with existing routes' do
- create_route!(namespace: visual_review_bot_namespace)
- create_route!(namespace: migration_bot_namespace)
-
- expect { migrate! }.not_to change { routes.count }
- end
-
- it 'does not create routes for human users without an existing route' do
- human_namespace = create_human_namespace!(name: 'GitLab Human', username: 'human')
-
- expect { migrate! }.not_to change { route_for(namespace: human_namespace) }
- end
-
- it 'does not create route for a bot user with a missing route, if a human user with the same path already exists' do
- human_namespace = create_human_namespace!(name: visual_review_bot.name, username: visual_review_bot.username)
- create_route!(namespace: human_namespace)
-
- expect { migrate! }.not_to change { route_for(namespace: visual_review_bot_namespace) }
- end
-
- private
-
- def create_human_namespace!(name:, username:)
- human = users.create!(email: 'human@gitlab.com', name: name, username: username, user_type: nil, projects_limit: 5)
- namespaces.create!(owner_id: human.id, name: human.name, path: human.username)
- end
-
- def create_route!(namespace:)
- routes.create!(path: namespace.path, name: namespace.name, source_id: namespace.id, source_type: 'Namespace')
- end
-
- def route_for(namespace:)
- routes.find_by(source_type: 'Namespace', source_id: namespace.id)
- end
-end
diff --git a/spec/migrations/insert_daily_invites_plan_limits_spec.rb b/spec/migrations/insert_daily_invites_plan_limits_spec.rb
deleted file mode 100644
index 49d41a1039f..00000000000
--- a/spec/migrations/insert_daily_invites_plan_limits_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe InsertDailyInvitesPlanLimits do
- let(:plans) { table(:plans) }
- let(:plan_limits) { table(:plan_limits) }
- let!(:free_plan) { plans.create!(name: 'free') }
- let!(:bronze_plan) { plans.create!(name: 'bronze') }
- let!(:silver_plan) { plans.create!(name: 'silver') }
- let!(:gold_plan) { plans.create!(name: 'gold') }
-
- context 'when on Gitlab.com' do
- before do
- expect(Gitlab).to receive(:com?).at_most(:twice).and_return(true)
- end
-
- it 'correctly migrates up and down' do
- reversible_migration do |migration|
- migration.before -> {
- expect(plan_limits.where.not(daily_invites: 0)).to be_empty
- }
-
- # Expectations will run after the up migration.
- migration.after -> {
- expect(plan_limits.pluck(:plan_id, :daily_invites)).to contain_exactly(
- [free_plan.id, 20],
- [bronze_plan.id, 0],
- [silver_plan.id, 0],
- [gold_plan.id, 0]
- )
- }
- end
- end
- end
-
- context 'when on self hosted' do
- before do
- expect(Gitlab).to receive(:com?).at_most(:twice).and_return(false)
- end
-
- it 'correctly migrates up and down' do
- reversible_migration do |migration|
- migration.before -> {
- expect(plan_limits.pluck(:daily_invites)).to eq []
- }
-
- migration.after -> {
- expect(plan_limits.pluck(:daily_invites)).to eq []
- }
- end
- end
- end
-end
diff --git a/spec/migrations/insert_project_feature_flags_plan_limits_spec.rb b/spec/migrations/insert_project_feature_flags_plan_limits_spec.rb
deleted file mode 100644
index 481e987c188..00000000000
--- a/spec/migrations/insert_project_feature_flags_plan_limits_spec.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe InsertProjectFeatureFlagsPlanLimits do
- let(:migration) { described_class.new }
- let(:plans) { table(:plans) }
- let(:plan_limits) { table(:plan_limits) }
- let!(:default_plan) { plans.create!(name: 'default') }
- let!(:free_plan) { plans.create!(name: 'free') }
- let!(:bronze_plan) { plans.create!(name: 'bronze') }
- let!(:silver_plan) { plans.create!(name: 'silver') }
- let!(:gold_plan) { plans.create!(name: 'gold') }
- let!(:default_plan_limits) do
- plan_limits.create!(plan_id: default_plan.id, project_feature_flags: 200)
- end
-
- context 'when on Gitlab.com' do
- before do
- expect(Gitlab).to receive(:com?).at_most(:twice).and_return(true)
- end
-
- describe '#up' do
- it 'updates the project_feature_flags plan limits' do
- migration.up
-
- expect(plan_limits.pluck(:plan_id, :project_feature_flags)).to contain_exactly(
- [default_plan.id, 200],
- [free_plan.id, 50],
- [bronze_plan.id, 100],
- [silver_plan.id, 150],
- [gold_plan.id, 200]
- )
- end
- end
-
- describe '#down' do
- it 'removes the project_feature_flags plan limits' do
- migration.up
- migration.down
-
- expect(plan_limits.pluck(:plan_id, :project_feature_flags)).to contain_exactly(
- [default_plan.id, 200],
- [free_plan.id, 0],
- [bronze_plan.id, 0],
- [silver_plan.id, 0],
- [gold_plan.id, 0]
- )
- end
- end
- end
-
- context 'when on self-hosted' do
- before do
- expect(Gitlab).to receive(:com?).at_most(:twice).and_return(false)
- end
-
- describe '#up' do
- it 'does not change the plan limits' do
- migration.up
-
- expect(plan_limits.pluck(:project_feature_flags)).to contain_exactly(200)
- end
- end
-
- describe '#down' do
- it 'does not change the plan limits' do
- migration.up
- migration.down
-
- expect(plan_limits.pluck(:project_feature_flags)).to contain_exactly(200)
- end
- end
- end
-end
diff --git a/spec/migrations/migrate_all_merge_request_user_mentions_to_db_spec.rb b/spec/migrations/migrate_all_merge_request_user_mentions_to_db_spec.rb
deleted file mode 100644
index c2df04bf2d6..00000000000
--- a/spec/migrations/migrate_all_merge_request_user_mentions_to_db_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe MigrateAllMergeRequestUserMentionsToDb, :migration do
- let(:users) { table(:users) }
- let(:projects) { table(:projects) }
- let(:namespaces) { table(:namespaces) }
- let(:merge_requests) { table(:merge_requests) }
- let(:merge_request_user_mentions) { table(:merge_request_user_mentions) }
-
- let(:user) { users.create!(name: 'root', email: 'root@example.com', username: 'root', projects_limit: 0) }
- let(:group) { namespaces.create!(name: 'group1', path: 'group1', owner_id: user.id, type: 'Group') }
- let(:project) { projects.create!(name: 'gitlab1', path: 'gitlab1', namespace_id: group.id, visibility_level: 0) }
-
- let(:opened_state) { 1 }
- let(:closed_state) { 2 }
- let(:merged_state) { 3 }
-
- # migrateable resources
- let(:common_args) { { source_branch: 'master', source_project_id: project.id, target_project_id: project.id, author_id: user.id, description: 'mr description with @root mention' } }
- let!(:resource1) { merge_requests.create!(common_args.merge(title: "title 1", state_id: opened_state, target_branch: 'feature1')) }
- let!(:resource2) { merge_requests.create!(common_args.merge(title: "title 2", state_id: closed_state, target_branch: 'feature2')) }
- let!(:resource3) { merge_requests.create!(common_args.merge(title: "title 3", state_id: merged_state, target_branch: 'feature3')) }
-
- # non-migrateable resources
- # this merge request is already migrated, as it has a record in the merge_request_user_mentions table
- let!(:resource4) { merge_requests.create!(common_args.merge(title: "title 3", state_id: opened_state, target_branch: 'feature4')) }
- let!(:user_mention) { merge_request_user_mentions.create!(merge_request_id: resource4.id, mentioned_users_ids: [1]) }
-
- let!(:resource5) { merge_requests.create!(common_args.merge(title: "title 3", description: 'description with no mention', state_id: opened_state, target_branch: 'feature5')) }
-
- it_behaves_like 'schedules resource mentions migration', MergeRequest, false
-end
diff --git a/spec/migrations/migrate_bot_type_to_user_type_spec.rb b/spec/migrations/migrate_bot_type_to_user_type_spec.rb
deleted file mode 100644
index 54cf3450692..00000000000
--- a/spec/migrations/migrate_bot_type_to_user_type_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe MigrateBotTypeToUserType, :migration do
- let(:users) { table(:users) }
-
- it 'updates bots & ignores humans' do
- users.create!(email: 'human', bot_type: nil, projects_limit: 0)
- users.create!(email: 'support_bot', bot_type: 1, projects_limit: 0)
- users.create!(email: 'alert_bot', bot_type: 2, projects_limit: 0)
- users.create!(email: 'visual_review_bot', bot_type: 3, projects_limit: 0)
-
- migrate!
-
- expect(users.where.not(user_type: nil).map(&:user_type)).to match_array([1, 2, 3])
- end
-end
diff --git a/spec/migrations/migrate_commit_notes_mentions_to_db_spec.rb b/spec/migrations/migrate_commit_notes_mentions_to_db_spec.rb
deleted file mode 100644
index aa2aa6297c4..00000000000
--- a/spec/migrations/migrate_commit_notes_mentions_to_db_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe MigrateCommitNotesMentionsToDb, :migration, :sidekiq do
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:notes) { table(:notes) }
-
- let(:user) { users.create!(name: 'root', email: 'root@example.com', username: 'root', projects_limit: 0) }
- let(:group) { namespaces.create!(name: 'group1', path: 'group1', owner_id: user.id) }
- let(:project) { projects.create!(name: 'gitlab1', path: 'gitlab1', namespace_id: group.id, visibility_level: 0) }
-
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
- let(:commit) { Commit.new(RepoHelpers.sample_commit, project) }
- let(:commit_user_mentions) { table(:commit_user_mentions) }
-
- let!(:resource1) { notes.create!(commit_id: commit.id, noteable_type: 'Commit', project_id: project.id, author_id: user.id, note: 'note1 for @root to check') }
- let!(:resource2) { notes.create!(commit_id: commit.id, noteable_type: 'Commit', project_id: project.id, author_id: user.id, note: 'note1 for @root to check') }
- let!(:resource3) { notes.create!(commit_id: commit.id, noteable_type: 'Commit', project_id: project.id, author_id: user.id, note: 'note1 for @root to check', system: true) }
-
- # non-migrateable resources
- # this note is already migrated, as it has a record in the commit_user_mentions table
- let!(:resource4) { notes.create!(note: 'note3 for @root to check', commit_id: commit.id, noteable_type: 'Commit') }
- let!(:user_mention) { commit_user_mentions.create!(commit_id: commit.id, note_id: resource4.id, mentioned_users_ids: [1]) }
- # this should have pointed to an inexistent commit record in a commits table
- # but because commit is not an AR, we'll just make it so that the note does not have mentions, i.e. no `@` char.
- let!(:resource5) { notes.create!(note: 'note3 to check', commit_id: 'abc', noteable_type: 'Commit') }
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 1)
- end
-
- it_behaves_like 'schedules resource mentions migration', Commit, true
-end
diff --git a/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb b/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb
deleted file mode 100644
index 6a9a75a7019..00000000000
--- a/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe MigrateComplianceFrameworkEnumToDatabaseFrameworkRecord, schema: 20201005092753 do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:project_compliance_framework_settings) { table(:project_compliance_framework_settings) }
- let(:compliance_management_frameworks) { table(:compliance_management_frameworks) }
-
- let(:gdpr_framework) { 1 }
- let(:sox_framework) { 5 }
-
- let!(:root_group) { namespaces.create!(type: 'Group', name: 'a', path: 'a') }
- let!(:sub_group) { namespaces.create!(type: 'Group', name: 'b', path: 'b', parent_id: root_group.id) }
- let!(:sub_sub_group) { namespaces.create!(type: 'Group', name: 'c', path: 'c', parent_id: sub_group.id) }
-
- let!(:namespace) { namespaces.create!(name: 'd', path: 'd') }
-
- let!(:project_on_root_level) { projects.create!(namespace_id: root_group.id) }
- let!(:project_on_sub_sub_level_1) { projects.create!(namespace_id: sub_sub_group.id) }
- let!(:project_on_sub_sub_level_2) { projects.create!(namespace_id: sub_sub_group.id) }
- let!(:project_on_namespace) { projects.create!(namespace_id: namespace.id) }
-
- let!(:project_on_root_level_compliance_setting) { project_compliance_framework_settings.create!(project_id: project_on_root_level.id, framework: gdpr_framework) }
- let!(:project_on_sub_sub_level_compliance_setting_1) { project_compliance_framework_settings.create!(project_id: project_on_sub_sub_level_1.id, framework: sox_framework) }
- let!(:project_on_sub_sub_level_compliance_setting_2) { project_compliance_framework_settings.create!(project_id: project_on_sub_sub_level_2.id, framework: gdpr_framework) }
- let!(:project_on_namespace_level_compliance_setting) { project_compliance_framework_settings.create!(project_id: project_on_namespace.id, framework: gdpr_framework) }
-
- subject { described_class.new.up }
-
- it 'updates the project settings' do
- subject
-
- gdpr_framework = compliance_management_frameworks.find_by(namespace_id: root_group.id, name: 'GDPR')
- expect(project_on_root_level_compliance_setting.reload.framework_id).to eq(gdpr_framework.id)
- expect(project_on_sub_sub_level_compliance_setting_2.reload.framework_id).to eq(gdpr_framework.id)
-
- sox_framework = compliance_management_frameworks.find_by(namespace_id: root_group.id, name: 'SOX')
- expect(project_on_sub_sub_level_compliance_setting_1.reload.framework_id).to eq(sox_framework.id)
-
- gdpr_framework = compliance_management_frameworks.find_by(namespace_id: namespace.id, name: 'GDPR')
- expect(project_on_namespace_level_compliance_setting.reload.framework_id).to eq(gdpr_framework.id)
- end
-
- it 'adds two framework records' do
- subject
-
- expect(compliance_management_frameworks.count).to eq(3)
- end
-end
diff --git a/spec/migrations/migrate_create_commit_signature_worker_sidekiq_queue_spec.rb b/spec/migrations/migrate_create_commit_signature_worker_sidekiq_queue_spec.rb
deleted file mode 100644
index 0e631f255bf..00000000000
--- a/spec/migrations/migrate_create_commit_signature_worker_sidekiq_queue_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe MigrateCreateCommitSignatureWorkerSidekiqQueue, :sidekiq, :redis do
- include Gitlab::Database::MigrationHelpers
- include StubWorker
-
- context 'when there are jobs in the queue' do
- it 'correctly migrates queue when migrating up' do
- Sidekiq::Testing.disable! do
- stub_worker(queue: 'create_commit_signature').perform_async('Something', [1])
- stub_worker(queue: 'create_gpg_signature').perform_async('Something', [1])
-
- described_class.new.up
-
- expect(sidekiq_queue_length('create_gpg_signature')).to eq 0
- expect(sidekiq_queue_length('create_commit_signature')).to eq 2
- end
- end
-
- it 'correctly migrates queue when migrating down' do
- Sidekiq::Testing.disable! do
- stub_worker(queue: 'create_gpg_signature').perform_async('Something', [1])
-
- described_class.new.down
-
- expect(sidekiq_queue_length('create_gpg_signature')).to eq 1
- expect(sidekiq_queue_length('create_commit_signature')).to eq 0
- end
- end
- end
-
- context 'when there are no jobs in the queues' do
- it 'does not raise error when migrating up' do
- expect { described_class.new.up }.not_to raise_error
- end
-
- it 'does not raise error when migrating down' do
- expect { described_class.new.down }.not_to raise_error
- end
- end
-end
diff --git a/spec/migrations/migrate_incident_issues_to_incident_type_spec.rb b/spec/migrations/migrate_incident_issues_to_incident_type_spec.rb
deleted file mode 100644
index acac6114c71..00000000000
--- a/spec/migrations/migrate_incident_issues_to_incident_type_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe MigrateIncidentIssuesToIncidentType do
- let(:migration) { described_class.new }
-
- let(:projects) { table(:projects) }
- let(:namespaces) { table(:namespaces) }
- let(:labels) { table(:labels) }
- let(:issues) { table(:issues) }
- let(:label_links) { table(:label_links) }
- let(:label_props) { IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES }
-
- let(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
- let!(:project) { projects.create!(namespace_id: namespace.id) }
- let(:label) { labels.create!(project_id: project.id, **label_props) }
- let!(:incident_issue) { issues.create!(project_id: project.id) }
- let!(:other_issue) { issues.create!(project_id: project.id) }
-
- # Issue issue_type enum
- let(:issue_type) { 0 }
- let(:incident_type) { 1 }
-
- before do
- label_links.create!(target_id: incident_issue.id, label_id: label.id, target_type: 'Issue')
- end
-
- describe '#up' do
- it 'updates the incident issue type' do
- expect { migrate! }
- .to change { incident_issue.reload.issue_type }
- .from(issue_type)
- .to(incident_type)
-
- expect(other_issue.reload.issue_type).to eql(issue_type)
- end
- end
-
- describe '#down' do
- let!(:incident_issue) { issues.create!(project_id: project.id, issue_type: issue_type) }
-
- it 'updates the incident issue type' do
- migration.up
-
- expect { migration.down }
- .to change { incident_issue.reload.issue_type }
- .from(incident_type)
- .to(issue_type)
-
- expect(other_issue.reload.issue_type).to eql(issue_type)
- end
- end
-end
diff --git a/spec/migrations/migrate_merge_request_mentions_to_db_spec.rb b/spec/migrations/migrate_merge_request_mentions_to_db_spec.rb
deleted file mode 100644
index 06493c4e5c1..00000000000
--- a/spec/migrations/migrate_merge_request_mentions_to_db_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe MigrateMergeRequestMentionsToDb, :migration do
- let(:users) { table(:users) }
- let(:projects) { table(:projects) }
- let(:namespaces) { table(:namespaces) }
- let(:merge_requests) { table(:merge_requests) }
- let(:merge_request_user_mentions) { table(:merge_request_user_mentions) }
-
- let(:user) { users.create!(name: 'root', email: 'root@example.com', username: 'root', projects_limit: 0) }
- let(:group) { namespaces.create!(name: 'group1', path: 'group1', owner_id: user.id, type: 'Group') }
- let(:project) { projects.create!(name: 'gitlab1', path: 'gitlab1', namespace_id: group.id, visibility_level: 0) }
-
- # migrateable resources
- let(:common_args) { { source_branch: 'master', source_project_id: project.id, target_project_id: project.id, author_id: user.id, description: 'mr description with @root mention' } }
- let!(:resource1) { merge_requests.create!(common_args.merge(title: "title 1", state_id: 1, target_branch: 'feature1')) }
- let!(:resource2) { merge_requests.create!(common_args.merge(title: "title 2", state_id: 1, target_branch: 'feature2')) }
- let!(:resource3) { merge_requests.create!(common_args.merge(title: "title 3", state_id: 1, target_branch: 'feature3')) }
-
- # non-migrateable resources
- # this merge request is already migrated, as it has a record in the merge_request_user_mentions table
- let!(:resource4) { merge_requests.create!(common_args.merge(title: "title 3", state_id: 1, target_branch: 'feature3')) }
- let!(:user_mention) { merge_request_user_mentions.create!(merge_request_id: resource4.id, mentioned_users_ids: [1]) }
-
- let!(:resource5) { merge_requests.create!(common_args.merge(title: "title 3", description: 'description with no mention', state_id: 1, target_branch: 'feature3')) }
-
- it_behaves_like 'schedules resource mentions migration', MergeRequest, false
-end
diff --git a/spec/migrations/migrate_store_security_reports_sidekiq_queue_spec.rb b/spec/migrations/migrate_store_security_reports_sidekiq_queue_spec.rb
deleted file mode 100644
index 35cb6104fe2..00000000000
--- a/spec/migrations/migrate_store_security_reports_sidekiq_queue_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe MigrateStoreSecurityReportsSidekiqQueue, :redis do
- include Gitlab::Database::MigrationHelpers
- include StubWorker
-
- context 'when there are jobs in the queue' do
- it 'migrates queue when migrating up' do
- Sidekiq::Testing.disable! do
- stub_worker(queue: 'pipeline_default:store_security_reports').perform_async(1, 5)
-
- described_class.new.up
-
- expect(sidekiq_queue_length('pipeline_default:store_security_reports')).to eq 0
- expect(sidekiq_queue_length('security_scans:store_security_reports')).to eq 1
- end
- end
-
- it 'migrates queue when migrating down' do
- Sidekiq::Testing.disable! do
- stub_worker(queue: 'security_scans:store_security_reports').perform_async(1, 5)
-
- described_class.new.down
-
- expect(sidekiq_queue_length('pipeline_default:store_security_reports')).to eq 1
- expect(sidekiq_queue_length('security_scans:store_security_reports')).to eq 0
- end
- end
- end
-end
diff --git a/spec/migrations/migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue_spec.rb b/spec/migrations/migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue_spec.rb
deleted file mode 100644
index a9e386301b8..00000000000
--- a/spec/migrations/migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe MigrateSyncSecurityReportsToReportApprovalRulesSidekiqQueue, :redis do
- include Gitlab::Database::MigrationHelpers
- include StubWorker
-
- context 'when there are jobs in the queue' do
- it 'migrates queue when migrating up' do
- Sidekiq::Testing.disable! do
- stub_worker(queue: 'pipeline_default:sync_security_reports_to_report_approval_rules').perform_async(1, 5)
-
- described_class.new.up
-
- expect(sidekiq_queue_length('pipeline_default:sync_security_reports_to_report_approval_rules')).to eq 0
- expect(sidekiq_queue_length('security_scans:sync_security_reports_to_report_approval_rules')).to eq 1
- end
- end
-
- it 'migrates queue when migrating down' do
- Sidekiq::Testing.disable! do
- stub_worker(queue: 'security_scans:sync_security_reports_to_report_approval_rules').perform_async(1, 5)
-
- described_class.new.down
-
- expect(sidekiq_queue_length('pipeline_default:sync_security_reports_to_report_approval_rules')).to eq 1
- expect(sidekiq_queue_length('security_scans:sync_security_reports_to_report_approval_rules')).to eq 0
- end
- end
- end
-end
diff --git a/spec/migrations/orphaned_invite_tokens_cleanup_spec.rb b/spec/migrations/orphaned_invite_tokens_cleanup_spec.rb
index be5e7756514..b33e29f82e2 100644
--- a/spec/migrations/orphaned_invite_tokens_cleanup_spec.rb
+++ b/spec/migrations/orphaned_invite_tokens_cleanup_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration! 'orphaned_invite_tokens_cleanup'
+require_migration!
RSpec.describe OrphanedInviteTokensCleanup, :migration do
def create_member(**extra_attributes)
diff --git a/spec/migrations/populate_remaining_missing_dismissal_information_for_vulnerabilities_spec.rb b/spec/migrations/populate_remaining_missing_dismissal_information_for_vulnerabilities_spec.rb
deleted file mode 100644
index 986436971ac..00000000000
--- a/spec/migrations/populate_remaining_missing_dismissal_information_for_vulnerabilities_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe PopulateRemainingMissingDismissalInformationForVulnerabilities do
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:vulnerabilities) { table(:vulnerabilities) }
-
- let(:user) { users.create!(name: 'test', email: 'test@example.com', projects_limit: 5) }
- let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
- let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
-
- let(:states) { { detected: 1, dismissed: 2, resolved: 3, confirmed: 4 } }
- let!(:vulnerability_1) { vulnerabilities.create!(title: 'title', state: states[:detected], severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id) }
- let!(:vulnerability_2) { vulnerabilities.create!(title: 'title', state: states[:dismissed], severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id) }
- let!(:vulnerability_3) { vulnerabilities.create!(title: 'title', state: states[:resolved], severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id) }
- let!(:vulnerability_4) { vulnerabilities.create!(title: 'title', state: states[:confirmed], severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id) }
-
- describe '#perform' do
- it 'calls the background migration class instance with broken vulnerability IDs' do
- expect_next_instance_of(::Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation) do |migrator|
- expect(migrator).to receive(:perform).with(vulnerability_2.id)
- end
-
- migrate!
- end
- end
-end
diff --git a/spec/migrations/remove_additional_application_settings_rows_spec.rb b/spec/migrations/remove_additional_application_settings_rows_spec.rb
deleted file mode 100644
index d781195abf2..00000000000
--- a/spec/migrations/remove_additional_application_settings_rows_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe RemoveAdditionalApplicationSettingsRows do
- let(:application_settings) { table(:application_settings) }
-
- it 'removes additional rows from application settings' do
- 3.times { application_settings.create! }
- latest_settings = application_settings.create!
-
- disable_migrations_output { migrate! }
-
- expect(application_settings.count).to eq(1)
- expect(application_settings.first).to eq(latest_settings)
- end
-
- it 'leaves only row in application_settings' do
- latest_settings = application_settings.create!
-
- disable_migrations_output { migrate! }
-
- expect(application_settings.first).to eq(latest_settings)
- end
-end
diff --git a/spec/migrations/remove_deprecated_jenkins_service_records_spec.rb b/spec/migrations/remove_deprecated_jenkins_service_records_spec.rb
deleted file mode 100644
index 817cf183e0c..00000000000
--- a/spec/migrations/remove_deprecated_jenkins_service_records_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-require_migration!('ensure_deprecated_jenkins_service_records_removal')
-
-RSpec.shared_examples 'remove DeprecatedJenkinsService records' do
- let(:services) { table(:services) }
-
- before do
- services.create!(type: 'JenkinsDeprecatedService')
- services.create!(type: 'JenkinsService')
- end
-
- it 'deletes services when template and attached to a project' do
- expect { migrate! }
- .to change { services.where(type: 'JenkinsDeprecatedService').count }.from(1).to(0)
- .and not_change { services.where(type: 'JenkinsService').count }
- end
-end
-
-RSpec.describe RemoveDeprecatedJenkinsServiceRecords, :migration do
- it_behaves_like 'remove DeprecatedJenkinsService records'
-end
-
-RSpec.describe EnsureDeprecatedJenkinsServiceRecordsRemoval, :migration do
- it_behaves_like 'remove DeprecatedJenkinsService records'
-end
diff --git a/spec/migrations/remove_duplicate_labels_from_groups_spec.rb b/spec/migrations/remove_duplicate_labels_from_groups_spec.rb
deleted file mode 100644
index 125314f70dd..00000000000
--- a/spec/migrations/remove_duplicate_labels_from_groups_spec.rb
+++ /dev/null
@@ -1,227 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!('remove_duplicate_labels_from_group')
-
-RSpec.describe RemoveDuplicateLabelsFromGroup do
- let(:labels_table) { table(:labels) }
- let(:labels) { labels_table.all }
- let(:projects_table) { table(:projects) }
- let(:projects) { projects_table.all }
- let(:namespaces_table) { table(:namespaces) }
- let(:namespaces) { namespaces_table.all }
- let(:backup_labels_table) { table(:backup_labels) }
- let(:backup_labels) { backup_labels_table.all }
- # for those cases where we can't use the activerecord class because the `type` column
- # makes it think it has polymorphism and should be/have a Label subclass
- let(:sql_backup_labels) { ApplicationRecord.connection.execute('SELECT * from backup_labels') }
-
- # all the possible tables with records that may have a relationship with a label
- let(:analytics_cycle_analytics_group_stages_table) { table(:analytics_cycle_analytics_group_stages) }
- let(:analytics_cycle_analytics_project_stages_table) { table(:analytics_cycle_analytics_project_stages) }
- let(:board_labels_table) { table(:board_labels) }
- let(:label_links_table) { table(:label_links) }
- let(:label_priorities_table) { table(:label_priorities) }
- let(:lists_table) { table(:lists) }
- let(:resource_label_events_table) { table(:resource_label_events) }
-
- let!(:group_one) { namespaces_table.create!(id: 1, type: 'Group', name: 'group', path: 'group') }
- let!(:project_one) do
- projects_table.create!(id: 1, name: 'project', path: 'project',
- visibility_level: 0, namespace_id: group_one.id)
- end
-
- let(:label_title) { 'bug' }
- let(:label_color) { 'red' }
- let(:label_description) { 'nice label' }
- let(:project_id) { project_one.id }
- let(:group_id) { group_one.id }
- let(:other_title) { 'feature' }
-
- let(:group_label_attributes) do
- {
- title: label_title, color: label_color, group_id: group_id, type: 'GroupLabel', template: false, description: label_description
- }
- end
-
- let(:migration) { described_class.new }
-
- describe 'removing full duplicates' do
- context 'when there are no duplicate labels' do
- let!(:first_label) { labels_table.create!(group_label_attributes.merge(id: 1, title: "a different label")) }
- let!(:second_label) { labels_table.create!(group_label_attributes.merge(id: 2, title: "a totally different label")) }
-
- it 'does not remove anything' do
- expect { migration.up }.not_to change { backup_labels_table.count }
- end
-
- it 'restores removed records when rolling back - no change' do
- migration.up
-
- expect { migration.down }.not_to change { labels_table.count }
- end
- end
-
- context 'with duplicates with no relationships' do
- let!(:first_label) { labels_table.create!(group_label_attributes.merge(id: 1)) }
- let!(:second_label) { labels_table.create!(group_label_attributes.merge(id: 2)) }
- let!(:third_label) { labels_table.create!(group_label_attributes.merge(id: 3, title: other_title)) }
- let!(:fourth_label) { labels_table.create!(group_label_attributes.merge(id: 4, title: other_title)) }
-
- it 'creates a backup record for each removed record' do
- expect { migration.up }.to change { backup_labels_table.count }.from(0).to(2)
- end
-
- it 'creates the correct backup records with `create` restore_action' do
- migration.up
-
- expect(sql_backup_labels.find { |bl| bl["id"] == 2 }).to include(second_label.attributes.merge("restore_action" => described_class::CREATE, "new_title" => nil, "created_at" => anything, "updated_at" => anything))
- expect(sql_backup_labels.find { |bl| bl["id"] == 4 }).to include(fourth_label.attributes.merge("restore_action" => described_class::CREATE, "new_title" => nil, "created_at" => anything, "updated_at" => anything))
- end
-
- it 'deletes all but one' do
- migration.up
-
- expect { second_label.reload }.to raise_error(ActiveRecord::RecordNotFound)
- expect { fourth_label.reload }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'restores removed records on rollback' do
- second_label_attributes = modified_attributes(second_label)
- fourth_label_attributes = modified_attributes(fourth_label)
-
- migration.up
-
- migration.down
-
- expect(second_label.attributes).to include(second_label_attributes)
- expect(fourth_label.attributes).to include(fourth_label_attributes)
- end
- end
-
- context 'two duplicate records, one of which has a relationship' do
- let!(:first_label) { labels_table.create!(group_label_attributes.merge(id: 1)) }
- let!(:second_label) { labels_table.create!(group_label_attributes.merge(id: 2)) }
- let!(:label_priority) { label_priorities_table.create!(label_id: second_label.id, project_id: project_id, priority: 1) }
-
- it 'does not remove anything' do
- expect { migration.up }.not_to change { labels_table.count }
- end
-
- it 'does not create a backup record with `create` restore_action' do
- expect { migration.up }.not_to change { backup_labels_table.where(restore_action: described_class::CREATE).count }
- end
-
- it 'restores removed records when rolling back - no change' do
- migration.up
-
- expect { migration.down }.not_to change { labels_table.count }
- end
- end
-
- context 'multiple duplicates, a subset of which have relationships' do
- let!(:first_label) { labels_table.create!(group_label_attributes.merge(id: 1)) }
- let!(:second_label) { labels_table.create!(group_label_attributes.merge(id: 2)) }
- let!(:label_priority_for_second_label) { label_priorities_table.create!(label_id: second_label.id, project_id: project_id, priority: 1) }
- let!(:third_label) { labels_table.create!(group_label_attributes.merge(id: 3)) }
- let!(:fourth_label) { labels_table.create!(group_label_attributes.merge(id: 4)) }
- let!(:label_priority_for_fourth_label) { label_priorities_table.create!(label_id: fourth_label.id, project_id: project_id, priority: 2) }
-
- it 'creates a backup record with `create` restore_action for each removed record' do
- expect { migration.up }.to change { backup_labels_table.where(restore_action: described_class::CREATE).count }.from(0).to(1)
- end
-
- it 'creates the correct backup records' do
- migration.up
-
- expect(sql_backup_labels.find { |bl| bl["id"] == 3 }).to include(third_label.attributes.merge("restore_action" => described_class::CREATE, "new_title" => nil, "created_at" => anything, "updated_at" => anything))
- end
-
- it 'deletes the duplicate record' do
- migration.up
-
- expect { first_label.reload }.not_to raise_error
- expect { second_label.reload }.not_to raise_error
- expect { third_label.reload }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'restores removed records on rollback' do
- third_label_attributes = modified_attributes(third_label)
-
- migration.up
- migration.down
-
- expect(third_label.attributes).to include(third_label_attributes)
- end
- end
- end
-
- describe 'renaming partial duplicates' do
- # partial duplicates - only group_id and title match. Distinct colour prevents deletion.
- context 'when there are no duplicate labels' do
- let!(:first_label) { labels_table.create!(group_label_attributes.merge(id: 1, title: "a unique label", color: 'green')) }
- let!(:second_label) { labels_table.create!(group_label_attributes.merge(id: 2, title: "a totally different, unique, label", color: 'blue')) }
-
- it 'does not rename anything' do
- expect { migration.up }.not_to change { backup_labels_table.count }
- end
- end
-
- context 'with duplicates with no relationships' do
- let!(:first_label) { labels_table.create!(group_label_attributes.merge(id: 1, color: 'green')) }
- let!(:second_label) { labels_table.create!(group_label_attributes.merge(id: 2, color: 'blue')) }
- let!(:third_label) { labels_table.create!(group_label_attributes.merge(id: 3, title: other_title, color: 'purple')) }
- let!(:fourth_label) { labels_table.create!(group_label_attributes.merge(id: 4, title: other_title, color: 'yellow')) }
-
- it 'creates a backup record for each renamed record' do
- expect { migration.up }.to change { backup_labels_table.count }.from(0).to(2)
- end
-
- it 'creates the correct backup records with `rename` restore_action' do
- migration.up
-
- expect(sql_backup_labels.find { |bl| bl["id"] == 2 }).to include(second_label.attributes.merge("restore_action" => described_class::RENAME, "created_at" => anything, "updated_at" => anything))
- expect(sql_backup_labels.find { |bl| bl["id"] == 4 }).to include(fourth_label.attributes.merge("restore_action" => described_class::RENAME, "created_at" => anything, "updated_at" => anything))
- end
-
- it 'modifies the titles of the partial duplicates' do
- migration.up
-
- expect(second_label.reload.title).to match(/#{label_title}_duplicate#{second_label.id}$/)
- expect(fourth_label.reload.title).to match(/#{other_title}_duplicate#{fourth_label.id}$/)
- end
-
- it 'restores renamed records on rollback' do
- second_label_attributes = modified_attributes(second_label)
- fourth_label_attributes = modified_attributes(fourth_label)
-
- migration.up
-
- migration.down
-
- expect(second_label.reload.attributes).to include(second_label_attributes)
- expect(fourth_label.reload.attributes).to include(fourth_label_attributes)
- end
-
- context 'when the labels have a long title that might overflow' do
- let(:long_title) { "a" * 255 }
-
- before do
- first_label.update_attribute(:title, long_title)
- second_label.update_attribute(:title, long_title)
- end
-
- it 'keeps the length within the limit' do
- migration.up
-
- expect(second_label.reload.title).to eq("#{"a" * 244}_duplicate#{second_label.id}")
- expect(second_label.title.length).to eq(255)
- end
- end
- end
- end
-
- def modified_attributes(label)
- label.attributes.except('created_at', 'updated_at')
- end
-end
diff --git a/spec/migrations/remove_duplicate_labels_from_project_spec.rb b/spec/migrations/remove_duplicate_labels_from_project_spec.rb
deleted file mode 100644
index eeb9f155e01..00000000000
--- a/spec/migrations/remove_duplicate_labels_from_project_spec.rb
+++ /dev/null
@@ -1,239 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe RemoveDuplicateLabelsFromProject do
- let(:labels_table) { table(:labels) }
- let(:labels) { labels_table.all }
- let(:projects_table) { table(:projects) }
- let(:projects) { projects_table.all }
- let(:namespaces_table) { table(:namespaces) }
- let(:namespaces) { namespaces_table.all }
- let(:backup_labels_table) { table(:backup_labels) }
- let(:backup_labels) { backup_labels_table.all }
-
- # all the possible tables with records that may have a relationship with a label
- let(:analytics_cycle_analytics_group_stages_table) { table(:analytics_cycle_analytics_group_stages) }
- let(:analytics_cycle_analytics_project_stages_table) { table(:analytics_cycle_analytics_project_stages) }
- let(:board_labels_table) { table(:board_labels) }
- let(:label_links_table) { table(:label_links) }
- let(:label_priorities_table) { table(:label_priorities) }
- let(:lists_table) { table(:lists) }
- let(:resource_label_events_table) { table(:resource_label_events) }
-
- let!(:group_one) { namespaces_table.create!(id: 1, type: 'Group', name: 'group', path: 'group') }
- let!(:project_one) do
- projects_table.create!(id: 1, name: 'project', path: 'project',
- visibility_level: 0, namespace_id: group_one.id)
- end
-
- let(:label_title) { 'bug' }
- let(:label_color) { 'red' }
- let(:label_description) { 'nice label' }
- let(:group_id) { group_one.id }
- let(:project_id) { project_one.id }
- let(:other_title) { 'feature' }
-
- let(:group_label_attributes) do
- {
- title: label_title, color: label_color, group_id: group_id, type: 'GroupLabel', template: false, description: label_description
- }
- end
-
- let(:project_label_attributes) do
- {
- title: label_title, color: label_color, project_id: project_id, type: 'ProjectLabel', template: false, description: label_description
- }
- end
-
- let(:migration) { described_class.new }
-
- describe 'removing full duplicates' do
- context 'when there are no duplicate labels' do
- let!(:first_label) { labels_table.create!(project_label_attributes.merge(id: 1, title: "a different label")) }
- let!(:second_label) { labels_table.create!(project_label_attributes.merge(id: 2, title: "a totally different label")) }
-
- it 'does not remove anything' do
- expect { migration.up }.not_to change { backup_labels_table.count }
- end
-
- it 'restores removed records when rolling back - no change' do
- migration.up
-
- expect { migration.down }.not_to change { labels_table.count }
- end
- end
-
- context 'with duplicates with no relationships' do
- # can't use the activerecord class because the `type` makes it think it has polymorphism and should be/have a ProjectLabel subclass
- let(:backup_labels) { ApplicationRecord.connection.execute('SELECT * from backup_labels') }
-
- let!(:first_label) { labels_table.create!(project_label_attributes.merge(id: 1)) }
- let!(:second_label) { labels_table.create!(project_label_attributes.merge(id: 2)) }
- let!(:third_label) { labels_table.create!(project_label_attributes.merge(id: 3, title: other_title)) }
- let!(:fourth_label) { labels_table.create!(project_label_attributes.merge(id: 4, title: other_title)) }
-
- it 'creates a backup record for each removed record' do
- expect { migration.up }.to change { backup_labels_table.count }.from(0).to(2)
- end
-
- it 'creates the correct backup records with `create` restore_action' do
- migration.up
-
- expect(backup_labels.find { |bl| bl["id"] == 2 }).to include(second_label.attributes.merge("restore_action" => described_class::CREATE, "new_title" => nil, "created_at" => anything, "updated_at" => anything))
- expect(backup_labels.find { |bl| bl["id"] == 4 }).to include(fourth_label.attributes.merge("restore_action" => described_class::CREATE, "new_title" => nil, "created_at" => anything, "updated_at" => anything))
- end
-
- it 'deletes all but one' do
- migration.up
-
- expect { second_label.reload }.to raise_error(ActiveRecord::RecordNotFound)
- expect { fourth_label.reload }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'restores removed records on rollback' do
- second_label_attributes = modified_attributes(second_label)
- fourth_label_attributes = modified_attributes(fourth_label)
-
- migration.up
-
- migration.down
-
- expect(second_label.attributes).to include(second_label_attributes)
- expect(fourth_label.attributes).to include(fourth_label_attributes)
- end
- end
-
- context 'two duplicate records, one of which has a relationship' do
- let!(:first_label) { labels_table.create!(project_label_attributes.merge(id: 1)) }
- let!(:second_label) { labels_table.create!(project_label_attributes.merge(id: 2)) }
- let!(:label_priority) { label_priorities_table.create!(label_id: second_label.id, project_id: project_id, priority: 1) }
-
- it 'does not remove anything' do
- expect { migration.up }.not_to change { labels_table.count }
- end
-
- it 'does not create a backup record with `create` restore_action' do
- expect { migration.up }.not_to change { backup_labels_table.where(restore_action: described_class::CREATE).count }
- end
-
- it 'restores removed records when rolling back - no change' do
- migration.up
-
- expect { migration.down }.not_to change { labels_table.count }
- end
- end
-
- context 'multiple duplicates, a subset of which have relationships' do
- let!(:first_label) { labels_table.create!(project_label_attributes.merge(id: 1)) }
- let!(:second_label) { labels_table.create!(project_label_attributes.merge(id: 2)) }
- let!(:label_priority_for_second_label) { label_priorities_table.create!(label_id: second_label.id, project_id: project_id, priority: 1) }
- let!(:third_label) { labels_table.create!(project_label_attributes.merge(id: 3)) }
- let!(:fourth_label) { labels_table.create!(project_label_attributes.merge(id: 4)) }
- let!(:label_priority_for_fourth_label) { label_priorities_table.create!(label_id: fourth_label.id, project_id: project_id, priority: 2) }
-
- it 'creates a backup record with `create` restore_action for each removed record' do
- expect { migration.up }.to change { backup_labels_table.where(restore_action: described_class::CREATE).count }.from(0).to(1)
- end
-
- it 'creates the correct backup records' do
- migration.up
-
- # can't use the activerecord class because the `type` column makes it think it has polymorphism and should be/have a ProjectLabel subclass
- backup_labels = ApplicationRecord.connection.execute('SELECT * from backup_labels')
-
- expect(backup_labels.find { |bl| bl["id"] == 3 }).to include(third_label.attributes.merge("restore_action" => described_class::CREATE, "new_title" => nil, "created_at" => anything, "updated_at" => anything))
- end
-
- it 'deletes the duplicate record' do
- migration.up
-
- expect { first_label.reload }.not_to raise_error
- expect { second_label.reload }.not_to raise_error
- expect { third_label.reload }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'restores removed records on rollback' do
- third_label_attributes = modified_attributes(third_label)
-
- migration.up
- migration.down
-
- expect(third_label.attributes).to include(third_label_attributes)
- end
- end
- end
-
- describe 'renaming partial duplicates' do
- # partial duplicates - only project_id and title match. Distinct colour prevents deletion.
- context 'when there are no duplicate labels' do
- let!(:first_label) { labels_table.create!(project_label_attributes.merge(id: 1, title: "a unique label", color: 'green')) }
- let!(:second_label) { labels_table.create!(project_label_attributes.merge(id: 2, title: "a totally different, unique, label", color: 'blue')) }
-
- it 'does not rename anything' do
- expect { migration.up }.not_to change { backup_labels_table.count }
- end
- end
-
- context 'with duplicates with no relationships' do
- let!(:first_label) { labels_table.create!(project_label_attributes.merge(id: 1, color: 'green')) }
- let!(:second_label) { labels_table.create!(project_label_attributes.merge(id: 2, color: 'blue')) }
- let!(:third_label) { labels_table.create!(project_label_attributes.merge(id: 3, title: other_title, color: 'purple')) }
- let!(:fourth_label) { labels_table.create!(project_label_attributes.merge(id: 4, title: other_title, color: 'yellow')) }
-
- it 'creates a backup record for each renamed record' do
- expect { migration.up }.to change { backup_labels_table.count }.from(0).to(2)
- end
-
- it 'creates the correct backup records with `rename` restore_action' do
- migration.up
-
- # can't use the activerecord class because the `type` makes it think it has polymorphism and should be/have a ProjectLabel subclass
- backup_labels = ApplicationRecord.connection.execute('SELECT * from backup_labels')
-
- expect(backup_labels.find { |bl| bl["id"] == 2 }).to include(second_label.attributes.merge("restore_action" => described_class::RENAME, "created_at" => anything, "updated_at" => anything))
- expect(backup_labels.find { |bl| bl["id"] == 4 }).to include(fourth_label.attributes.merge("restore_action" => described_class::RENAME, "created_at" => anything, "updated_at" => anything))
- end
-
- it 'modifies the titles of the partial duplicates' do
- migration.up
-
- expect(second_label.reload.title).to match(/#{label_title}_duplicate#{second_label.id}$/)
- expect(fourth_label.reload.title).to match(/#{other_title}_duplicate#{fourth_label.id}$/)
- end
-
- it 'restores renamed records on rollback' do
- second_label_attributes = modified_attributes(second_label)
- fourth_label_attributes = modified_attributes(fourth_label)
-
- migration.up
-
- migration.down
-
- expect(second_label.reload.attributes).to include(second_label_attributes)
- expect(fourth_label.reload.attributes).to include(fourth_label_attributes)
- end
-
- context 'when the labels have a long title that might overflow' do
- let(:long_title) { "a" * 255 }
-
- before do
- first_label.update_attribute(:title, long_title)
- second_label.update_attribute(:title, long_title)
- end
-
- it 'keeps the length within the limit' do
- migration.up
-
- expect(second_label.reload.title).to eq("#{"a" * 244}_duplicate#{second_label.id}")
- expect(second_label.title.length).to eq 255
- end
- end
- end
- end
-
- def modified_attributes(label)
- label.attributes.except('created_at', 'updated_at')
- end
-end
diff --git a/spec/migrations/remove_gitlab_issue_tracker_service_records_spec.rb b/spec/migrations/remove_gitlab_issue_tracker_service_records_spec.rb
deleted file mode 100644
index b4aa5187d4c..00000000000
--- a/spec/migrations/remove_gitlab_issue_tracker_service_records_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe RemoveGitlabIssueTrackerServiceRecords do
- let(:services) { table(:services) }
-
- before do
- 5.times { services.create!(type: 'GitlabIssueTrackerService') }
- services.create!(type: 'SomeOtherType')
- end
-
- it 'removes services records of type GitlabIssueTrackerService', :aggregate_failures do
- expect { migrate! }.to change { services.count }.from(6).to(1)
- expect(services.first.type).to eq('SomeOtherType')
- expect(services.where(type: 'GitlabIssueTrackerService')).to be_empty
- end
-end
diff --git a/spec/migrations/remove_orphan_service_hooks_spec.rb b/spec/migrations/remove_orphan_service_hooks_spec.rb
deleted file mode 100644
index 71e70daf1e6..00000000000
--- a/spec/migrations/remove_orphan_service_hooks_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-require_migration!('add_web_hooks_service_foreign_key')
-
-RSpec.describe RemoveOrphanServiceHooks, schema: 20201203123201 do
- let(:web_hooks) { table(:web_hooks) }
- let(:services) { table(:services) }
-
- before do
- services.create!
- web_hooks.create!(service_id: services.first.id, type: 'ServiceHook')
- web_hooks.create!(service_id: nil)
-
- AddWebHooksServiceForeignKey.new.down
- web_hooks.create!(service_id: non_existing_record_id, type: 'ServiceHook')
- AddWebHooksServiceForeignKey.new.up
- end
-
- it 'removes service hooks where the referenced service does not exist', :aggregate_failures do
- expect { RemoveOrphanServiceHooks.new.up }.to change { web_hooks.count }.by(-1)
- expect(web_hooks.where.not(service_id: services.select(:id)).count).to eq(0)
- end
-end
diff --git a/spec/migrations/remove_orphaned_invited_members_spec.rb b/spec/migrations/remove_orphaned_invited_members_spec.rb
deleted file mode 100644
index 67e98b69ccc..00000000000
--- a/spec/migrations/remove_orphaned_invited_members_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe RemoveOrphanedInvitedMembers do
- let(:members_table) { table(:members) }
- let(:users_table) { table(:users) }
- let(:namespaces_table) { table(:namespaces) }
- let(:projects_table) { table(:projects) }
-
- let!(:user1) { users_table.create!(name: 'user1', email: 'user1@example.com', projects_limit: 1) }
- let!(:user2) { users_table.create!(name: 'user2', email: 'user2@example.com', projects_limit: 1) }
- let!(:group) { namespaces_table.create!(type: 'Group', name: 'group', path: 'group') }
- let!(:project) { projects_table.create!(name: 'project', path: 'project', namespace_id: group.id) }
-
- let!(:member1) { create_member(user_id: user1.id, source_type: 'Project', source_id: project.id, access_level: 10) }
- let!(:member2) { create_member(user_id: user2.id, source_type: 'Group', source_id: group.id, access_level: 20) }
-
- let!(:invited_member1) do
- create_member(user_id: nil, source_type: 'Project', source_id: project.id,
- invite_token: SecureRandom.hex, invite_accepted_at: Time.now,
- access_level: 20)
- end
-
- let!(:invited_member2) do
- create_member(user_id: nil, source_type: 'Group', source_id: group.id,
- invite_token: SecureRandom.hex, invite_accepted_at: Time.now,
- access_level: 20)
- end
-
- let!(:orphaned_member1) do
- create_member(user_id: nil, source_type: 'Project', source_id: project.id,
- invite_accepted_at: Time.now, access_level: 30)
- end
-
- let!(:orphaned_member2) do
- create_member(user_id: nil, source_type: 'Group', source_id: group.id,
- invite_accepted_at: Time.now, access_level: 20)
- end
-
- it 'removes orphaned invited members but keeps current members' do
- expect { migrate! }.to change { members_table.count }.from(6).to(4)
-
- expect(members_table.all.pluck(:id)).to contain_exactly(member1.id, member2.id, invited_member1.id, invited_member2.id)
- end
-
- def create_member(options)
- members_table.create!(
- {
- notification_level: 0,
- ldap: false,
- override: false
- }.merge(options)
- )
- end
-end
diff --git a/spec/migrations/remove_packages_deprecated_dependencies_spec.rb b/spec/migrations/remove_packages_deprecated_dependencies_spec.rb
deleted file mode 100644
index f76a26bcdc1..00000000000
--- a/spec/migrations/remove_packages_deprecated_dependencies_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe RemovePackagesDeprecatedDependencies do
- let(:projects) { table(:projects) }
- let(:packages) { table(:packages_packages) }
- let(:dependency_links) { table(:packages_dependency_links) }
- let(:dependencies) { table(:packages_dependencies) }
-
- before do
- projects.create!(id: 123, name: 'gitlab', path: 'gitlab-org/gitlab-ce', namespace_id: 1)
- packages.create!(id: 1, name: 'package', version: '1.0.0', package_type: 4, project_id: 123)
- 5.times do |i|
- dependencies.create!(id: i, name: "pkg_dependency_#{i}", version_pattern: '~1.0.0')
- dependency_links.create!(package_id: 1, dependency_id: i, dependency_type: 5)
- end
- dependencies.create!(id: 10, name: 'valid_pkg_dependency', version_pattern: '~2.5.0')
- dependency_links.create!(package_id: 1, dependency_id: 10, dependency_type: 1)
- end
-
- it 'removes all dependency links with type 5' do
- expect(dependency_links.count).to eq 6
-
- migrate!
-
- expect(dependency_links.count).to eq 1
- end
-end
diff --git a/spec/migrations/remove_security_dashboard_feature_flag_spec.rb b/spec/migrations/remove_security_dashboard_feature_flag_spec.rb
deleted file mode 100644
index fea7fe01cc7..00000000000
--- a/spec/migrations/remove_security_dashboard_feature_flag_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe RemoveSecurityDashboardFeatureFlag do
- let(:feature_gates) { table(:feature_gates) }
-
- subject(:migration) { described_class.new }
-
- describe '#up' do
- it 'deletes the security_dashboard feature gate' do
- security_dashboard_feature = feature_gates.create!(feature_key: :security_dashboard, key: :boolean, value: 'false')
- actors_security_dashboard_feature = feature_gates.create!(feature_key: :security_dashboard, key: :actors, value: 'Project:1')
-
- migration.up
-
- expect { security_dashboard_feature.reload }.to raise_error(ActiveRecord::RecordNotFound)
- expect(actors_security_dashboard_feature.reload).to be_present
- end
- end
-
- describe '#down' do
- it 'copies the instance_security_dashboard feature gate to a security_dashboard gate' do
- feature_gates.create!(feature_key: :instance_security_dashboard, key: :actors, value: 'Project:1')
- feature_gates.create!(feature_key: :instance_security_dashboard, key: 'boolean', value: 'false')
-
- migration.down
-
- security_dashboard_feature = feature_gates.find_by(feature_key: :security_dashboard, key: :boolean)
- expect(security_dashboard_feature.value).to eq('false')
- end
-
- context 'when there is no instance_security_dashboard gate' do
- it 'does nothing' do
- migration.down
-
- security_dashboard_feature = feature_gates.find_by(feature_key: :security_dashboard, key: :boolean)
- expect(security_dashboard_feature).to be_nil
- end
- end
-
- context 'when there already is a security_dashboard gate' do
- it 'does nothing' do
- feature_gates.create!(feature_key: :security_dashboard, key: 'boolean', value: 'false')
- feature_gates.create!(feature_key: :instance_security_dashboard, key: 'boolean', value: 'false')
-
- expect { migration.down }.not_to raise_error
- end
- end
- end
-end
diff --git a/spec/migrations/rename_security_dashboard_feature_flag_to_instance_security_dashboard_spec.rb b/spec/migrations/rename_security_dashboard_feature_flag_to_instance_security_dashboard_spec.rb
deleted file mode 100644
index fcbf94812fb..00000000000
--- a/spec/migrations/rename_security_dashboard_feature_flag_to_instance_security_dashboard_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe RenameSecurityDashboardFeatureFlagToInstanceSecurityDashboard do
- let(:feature_gates) { table(:feature_gates) }
-
- subject(:migration) { described_class.new }
-
- describe '#up' do
- it 'copies the security_dashboard feature gate to a new instance_security_dashboard gate' do
- feature_gates.create!(feature_key: :security_dashboard, key: :actors, value: 'Project:1')
- feature_gates.create!(feature_key: :security_dashboard, key: :boolean, value: 'false')
-
- migration.up
-
- instance_security_dashboard_feature = feature_gates.find_by(feature_key: :instance_security_dashboard, key: :boolean)
- expect(instance_security_dashboard_feature.value).to eq('false')
- end
-
- context 'when there is no security_dashboard gate' do
- it 'does nothing' do
- migration.up
-
- instance_security_dashboard_feature = feature_gates.find_by(feature_key: :instance_security_dashboard, key: :boolean)
- expect(instance_security_dashboard_feature).to be_nil
- end
- end
-
- context 'when there is already an instance_security_dashboard gate' do
- it 'does nothing' do
- feature_gates.create!(feature_key: :security_dashboard, key: 'boolean', value: 'false')
- feature_gates.create!(feature_key: :instance_security_dashboard, key: 'boolean', value: 'false')
-
- expect { migration.up }.not_to raise_error
- end
- end
- end
-
- describe '#down' do
- it 'removes the instance_security_dashboard gate' do
- actors_instance_security_dashboard_feature = feature_gates.create!(feature_key: :instance_security_dashboard, key: :actors, value: 'Project:1')
- instance_security_dashboard_feature = feature_gates.create!(feature_key: :instance_security_dashboard, key: :boolean, value: 'false')
-
- migration.down
-
- expect { instance_security_dashboard_feature.reload }.to raise_error(ActiveRecord::RecordNotFound)
- expect(actors_instance_security_dashboard_feature.reload).to be_present
- end
- end
-end
diff --git a/spec/migrations/rename_sitemap_namespace_spec.rb b/spec/migrations/rename_sitemap_namespace_spec.rb
deleted file mode 100644
index 21b74587d50..00000000000
--- a/spec/migrations/rename_sitemap_namespace_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe RenameSitemapNamespace do
- let(:namespaces) { table(:namespaces) }
- let(:routes) { table(:routes) }
- let(:sitemap_path) { 'sitemap' }
-
- it 'correctly run #up and #down' do
- create_namespace(sitemap_path)
-
- reversible_migration do |migration|
- migration.before -> {
- expect(namespaces.pluck(:path)).to contain_exactly(sitemap_path)
- }
-
- migration.after -> {
- expect(namespaces.pluck(:path)).to contain_exactly(sitemap_path + '0')
- }
- end
- end
-
- def create_namespace(path)
- namespaces.create!(name: path, path: path).tap do |namespace|
- routes.create!(path: namespace.path, name: namespace.name, source_id: namespace.id, source_type: 'Namespace')
- end
- end
-end
diff --git a/spec/migrations/rename_sitemap_root_namespaces_spec.rb b/spec/migrations/rename_sitemap_root_namespaces_spec.rb
deleted file mode 100644
index 12a687194e0..00000000000
--- a/spec/migrations/rename_sitemap_root_namespaces_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe RenameSitemapRootNamespaces do
- let(:namespaces) { table(:namespaces) }
- let(:routes) { table(:routes) }
- let(:sitemap_path) { 'sitemap.xml' }
- let(:sitemap_gz_path) { 'sitemap.xml.gz' }
- let(:other_path1) { 'sitemap.xmlfoo' }
- let(:other_path2) { 'foositemap.xml' }
-
- it 'correctly run #up and #down' do
- create_namespace(sitemap_path)
- create_namespace(sitemap_gz_path)
- create_namespace(other_path1)
- create_namespace(other_path2)
-
- reversible_migration do |migration|
- migration.before -> {
- expect(namespaces.pluck(:path)).to contain_exactly(sitemap_path, sitemap_gz_path, other_path1, other_path2)
- }
-
- migration.after -> {
- expect(namespaces.pluck(:path)).to contain_exactly(sitemap_path + '0', sitemap_gz_path + '0', other_path1, other_path2)
- }
- end
- end
-
- def create_namespace(path)
- namespaces.create!(name: path, path: path).tap do |namespace|
- routes.create!(path: namespace.path, name: namespace.name, source_id: namespace.id, source_type: 'Namespace')
- end
- end
-end
diff --git a/spec/migrations/reschedule_set_default_iteration_cadences_spec.rb b/spec/migrations/reschedule_set_default_iteration_cadences_spec.rb
deleted file mode 100644
index fb629c90d9f..00000000000
--- a/spec/migrations/reschedule_set_default_iteration_cadences_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe RescheduleSetDefaultIterationCadences do
- let(:namespaces) { table(:namespaces) }
- let(:iterations) { table(:sprints) }
-
- let(:group_1) { namespaces.create!(name: 'test_1', path: 'test_1') }
- let!(:group_2) { namespaces.create!(name: 'test_2', path: 'test_2') }
- let(:group_3) { namespaces.create!(name: 'test_3', path: 'test_3') }
- let(:group_4) { namespaces.create!(name: 'test_4', path: 'test_4') }
- let(:group_5) { namespaces.create!(name: 'test_5', path: 'test_5') }
- let(:group_6) { namespaces.create!(name: 'test_6', path: 'test_6') }
- let(:group_7) { namespaces.create!(name: 'test_7', path: 'test_7') }
- let(:group_8) { namespaces.create!(name: 'test_8', path: 'test_8') }
-
- let!(:iteration_1) { iterations.create!(iid: 1, title: 'iteration 1', group_id: group_1.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
- let!(:iteration_2) { iterations.create!(iid: 1, title: 'iteration 2', group_id: group_3.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
- let!(:iteration_3) { iterations.create!(iid: 1, title: 'iteration 2', group_id: group_4.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
- let!(:iteration_4) { iterations.create!(iid: 1, title: 'iteration 2', group_id: group_5.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
- let!(:iteration_5) { iterations.create!(iid: 1, title: 'iteration 2', group_id: group_6.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
- let!(:iteration_6) { iterations.create!(iid: 1, title: 'iteration 2', group_id: group_7.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
- let!(:iteration_7) { iterations.create!(iid: 1, title: 'iteration 2', group_id: group_8.id, start_date: 2.days.from_now, due_date: 3.days.from_now) }
-
- around do |example|
- freeze_time { Sidekiq::Testing.fake! { example.run } }
- end
-
- it 'schedules the background jobs', :aggregate_failures do
- stub_const("#{described_class.name}::BATCH_SIZE", 3)
-
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to be(3)
- expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(2.minutes, group_1.id, group_3.id, group_4.id)
- expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(4.minutes, group_5.id, group_6.id, group_7.id)
- expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(6.minutes, group_8.id)
- end
-end
diff --git a/spec/migrations/reseed_merge_trains_enabled_spec.rb b/spec/migrations/reseed_merge_trains_enabled_spec.rb
deleted file mode 100644
index 14ed44151d3..00000000000
--- a/spec/migrations/reseed_merge_trains_enabled_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ReseedMergeTrainsEnabled do
- describe 'migrate' do
- let(:project_ci_cd_settings) { table(:project_ci_cd_settings) }
- let(:projects) { table(:projects) }
- let(:namespaces) { table(:namespaces) }
-
- context 'when on Gitlab.com' do
- before do
- namespace = namespaces.create!(name: 'hello', path: 'hello/')
- project1 = projects.create!(namespace_id: namespace.id)
- project2 = projects.create!(namespace_id: namespace.id)
- project_ci_cd_settings.create!(project_id: project1.id, merge_pipelines_enabled: true)
- project_ci_cd_settings.create!(project_id: project2.id, merge_pipelines_enabled: false)
- end
-
- it 'updates merge_trains_enabled to true for where merge_pipelines_enabled is true' do
- expect { migrate! }.to change(project_ci_cd_settings.where(merge_trains_enabled: true), :count).by(1)
- end
- end
- end
-end
diff --git a/spec/migrations/reseed_repository_storages_weighted_spec.rb b/spec/migrations/reseed_repository_storages_weighted_spec.rb
deleted file mode 100644
index d7efff3dfba..00000000000
--- a/spec/migrations/reseed_repository_storages_weighted_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ReseedRepositoryStoragesWeighted do
- let(:storages) { { "foo" => {}, "baz" => {} } }
- let(:application_settings) do
- table(:application_settings).tap do |klass|
- klass.class_eval do
- serialize :repository_storages
- end
- end
- end
-
- before do
- allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
- end
-
- let(:repository_storages) { ["foo"] }
- let!(:application_setting) { application_settings.create!(repository_storages: repository_storages) }
-
- context 'with empty repository_storages_weighted column' do
- it 'populates repository_storages_weighted properly' do
- migrate!
-
- expect(application_settings.find(application_setting.id).repository_storages_weighted).to eq({ "foo" => 100, "baz" => 0 })
- end
- end
-
- context 'with already-populated repository_storages_weighted column' do
- let(:existing_weights) { { "foo" => 100, "baz" => 50 } }
-
- it 'does not change repository_storages_weighted properly' do
- application_setting.repository_storages_weighted = existing_weights
- application_setting.save!
-
- migrate!
-
- expect(application_settings.find(application_setting.id).repository_storages_weighted).to eq(existing_weights)
- end
- end
-end
diff --git a/spec/migrations/save_instance_administrators_group_id_spec.rb b/spec/migrations/save_instance_administrators_group_id_spec.rb
deleted file mode 100644
index 0846df18b5e..00000000000
--- a/spec/migrations/save_instance_administrators_group_id_spec.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe SaveInstanceAdministratorsGroupId do
- let(:application_settings_table) { table(:application_settings) }
-
- let(:instance_administrators_group) do
- table(:namespaces).create!(
- id: 1,
- name: 'GitLab Instance Administrators',
- path: 'gitlab-instance-administrators-random',
- type: 'Group'
- )
- end
-
- let(:self_monitoring_project) do
- table(:projects).create!(
- id: 2,
- name: 'Self Monitoring',
- path: 'self_monitoring',
- namespace_id: instance_administrators_group.id
- )
- end
-
- context 'when project ID is saved but group ID is not' do
- let(:application_settings) do
- application_settings_table.create!(instance_administration_project_id: self_monitoring_project.id)
- end
-
- it 'saves instance administrators group ID' do
- expect(application_settings.instance_administration_project_id).to eq(self_monitoring_project.id)
- expect(application_settings.instance_administrators_group_id).to be_nil
-
- migrate!
-
- expect(application_settings.reload.instance_administrators_group_id).to eq(instance_administrators_group.id)
- expect(application_settings.instance_administration_project_id).to eq(self_monitoring_project.id)
- end
- end
-
- context 'when group ID is saved but project ID is not' do
- let(:application_settings) do
- application_settings_table.create!(instance_administrators_group_id: instance_administrators_group.id)
- end
-
- it 'does not make changes' do
- expect(application_settings.instance_administrators_group_id).to eq(instance_administrators_group.id)
- expect(application_settings.instance_administration_project_id).to be_nil
-
- migrate!
-
- expect(application_settings.reload.instance_administrators_group_id).to eq(instance_administrators_group.id)
- expect(application_settings.instance_administration_project_id).to be_nil
- end
- end
-
- context 'when group ID and project ID are both saved' do
- let(:application_settings) do
- application_settings_table.create!(
- instance_administrators_group_id: instance_administrators_group.id,
- instance_administration_project_id: self_monitoring_project.id
- )
- end
-
- it 'does not make changes' do
- expect(application_settings.instance_administrators_group_id).to eq(instance_administrators_group.id)
- expect(application_settings.instance_administration_project_id).to eq(self_monitoring_project.id)
-
- migrate!
-
- expect(application_settings.reload.instance_administrators_group_id).to eq(instance_administrators_group.id)
- expect(application_settings.instance_administration_project_id).to eq(self_monitoring_project.id)
- end
- end
-
- context 'when neither group ID nor project ID is saved' do
- let(:application_settings) do
- application_settings_table.create!
- end
-
- it 'does not make changes' do
- expect(application_settings.instance_administrators_group_id).to be_nil
- expect(application_settings.instance_administration_project_id).to be_nil
-
- migrate!
-
- expect(application_settings.reload.instance_administrators_group_id).to be_nil
- expect(application_settings.instance_administration_project_id).to be_nil
- end
- end
-
- context 'when application_settings table has no rows' do
- it 'does not fail' do
- migrate!
- end
- end
-end
diff --git a/spec/migrations/schedule_add_primary_email_to_emails_if_user_confirmed_spec.rb b/spec/migrations/schedule_add_primary_email_to_emails_if_user_confirmed_spec.rb
new file mode 100644
index 00000000000..c66ac1bd7e9
--- /dev/null
+++ b/spec/migrations/schedule_add_primary_email_to_emails_if_user_confirmed_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleAddPrimaryEmailToEmailsIfUserConfirmed, :sidekiq do
+ let(:migration) { described_class.new }
+ let(:users) { table(:users) }
+
+ let!(:user_1) { users.create!(name: 'confirmed-user-1', email: 'confirmed-1@example.com', confirmed_at: 1.day.ago, projects_limit: 100) }
+ let!(:user_2) { users.create!(name: 'confirmed-user-2', email: 'confirmed-2@example.com', confirmed_at: 1.day.ago, projects_limit: 100) }
+ let!(:user_3) { users.create!(name: 'confirmed-user-3', email: 'confirmed-3@example.com', confirmed_at: 1.day.ago, projects_limit: 100) }
+ let!(:user_4) { users.create!(name: 'confirmed-user-4', email: 'confirmed-4@example.com', confirmed_at: 1.day.ago, projects_limit: 100) }
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 2)
+ stub_const("#{described_class.name}::INTERVAL", 2.minutes.to_i)
+ end
+
+ it 'schedules addition of primary email to emails in delayed batches' do
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migration.up
+
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, user_1.id, user_2.id)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, user_3.id, user_4.id)
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/schedule_backfill_push_rules_id_in_projects_spec.rb b/spec/migrations/schedule_backfill_push_rules_id_in_projects_spec.rb
deleted file mode 100644
index 7b71110e62d..00000000000
--- a/spec/migrations/schedule_backfill_push_rules_id_in_projects_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe ScheduleBackfillPushRulesIdInProjects do
- let(:push_rules) { table(:push_rules) }
-
- it 'adds global rule association to application settings' do
- application_settings = table(:application_settings)
- setting = application_settings.create!
- sample_rule = push_rules.create!(is_sample: true)
-
- Sidekiq::Testing.fake! do
- disable_migrations_output { migrate! }
- end
-
- setting.reload
- expect(setting.push_rule_id).to eq(sample_rule.id)
- end
-
- it 'adds global rule association to last application settings when there is more than one record without failing' do
- application_settings = table(:application_settings)
- setting_old = application_settings.create!
- setting = application_settings.create!
- sample_rule = push_rules.create!(is_sample: true)
-
- Sidekiq::Testing.fake! do
- disable_migrations_output { migrate! }
- end
-
- expect(setting_old.reload.push_rule_id).to be_nil
- expect(setting.reload.push_rule_id).to eq(sample_rule.id)
- end
-
- it 'schedules worker to migrate project push rules' do
- rule_1 = push_rules.create!
- rule_2 = push_rules.create!
-
- Sidekiq::Testing.fake! do
- disable_migrations_output { migrate! }
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(1)
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(5.minutes, rule_1.id, rule_2.id)
- end
- end
-end
diff --git a/spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb b/spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb
deleted file mode 100644
index f2a0bdba32a..00000000000
--- a/spec/migrations/schedule_blocked_by_links_replacement_second_try_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleBlockedByLinksReplacementSecondTry do
- let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
- let(:project) { table(:projects).create!(namespace_id: namespace.id, name: 'gitlab') }
- let(:issue1) { table(:issues).create!(project_id: project.id, title: 'a') }
- let(:issue2) { table(:issues).create!(project_id: project.id, title: 'b') }
- let(:issue3) { table(:issues).create!(project_id: project.id, title: 'c') }
- let!(:issue_links) do
- [
- table(:issue_links).create!(source_id: issue1.id, target_id: issue2.id, link_type: 1),
- table(:issue_links).create!(source_id: issue2.id, target_id: issue1.id, link_type: 2),
- table(:issue_links).create!(source_id: issue1.id, target_id: issue3.id, link_type: 2)
- ]
- end
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 1)
- end
-
- it 'schedules jobs for blocked_by links' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(
- 2.minutes, issue_links[1].id, issue_links[1].id)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(
- 4.minutes, issue_links[2].id, issue_links[2].id)
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_link_lfs_objects_projects_spec.rb b/spec/migrations/schedule_link_lfs_objects_projects_spec.rb
deleted file mode 100644
index 29c203c2c31..00000000000
--- a/spec/migrations/schedule_link_lfs_objects_projects_spec.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleLinkLfsObjectsProjects, :migration, :sidekiq do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:fork_networks) { table(:fork_networks) }
- let(:fork_network_members) { table(:fork_network_members) }
- let(:lfs_objects) { table(:lfs_objects) }
- let(:lfs_objects_projects) { table(:lfs_objects_projects) }
-
- let(:namespace) { namespaces.create!(name: 'GitLab', path: 'gitlab') }
-
- let(:fork_network) { fork_networks.create!(root_project_id: source_project.id) }
- let(:another_fork_network) { fork_networks.create!(root_project_id: another_source_project.id) }
-
- let(:source_project) { projects.create!(namespace_id: namespace.id) }
- let(:another_source_project) { projects.create!(namespace_id: namespace.id) }
- let(:project) { projects.create!(namespace_id: namespace.id) }
- let(:another_project) { projects.create!(namespace_id: namespace.id) }
-
- let(:lfs_object) { lfs_objects.create!(oid: 'abc123', size: 100) }
- let(:another_lfs_object) { lfs_objects.create!(oid: 'def456', size: 200) }
-
- let!(:source_project_lop_1) do
- lfs_objects_projects.create!(
- lfs_object_id: lfs_object.id,
- project_id: source_project.id
- )
- end
-
- let!(:source_project_lop_2) do
- lfs_objects_projects.create!(
- lfs_object_id: another_lfs_object.id,
- project_id: source_project.id
- )
- end
-
- let!(:another_source_project_lop_1) do
- lfs_objects_projects.create!(
- lfs_object_id: lfs_object.id,
- project_id: another_source_project.id
- )
- end
-
- let!(:another_source_project_lop_2) do
- lfs_objects_projects.create!(
- lfs_object_id: another_lfs_object.id,
- project_id: another_source_project.id
- )
- end
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 2)
-
- # Create links between projects
- fork_network_members.create!(fork_network_id: fork_network.id, project_id: source_project.id, forked_from_project_id: nil)
- fork_network_members.create!(fork_network_id: fork_network.id, project_id: project.id, forked_from_project_id: source_project.id)
- fork_network_members.create!(fork_network_id: another_fork_network.id, project_id: another_source_project.id, forked_from_project_id: nil)
- fork_network_members.create!(fork_network_id: another_fork_network.id, project_id: another_project.id, forked_from_project_id: another_fork_network.root_project_id)
- end
-
- it 'schedules background migration to link LFS objects' do
- Sidekiq::Testing.fake! do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(2.minutes, source_project_lop_1.id, source_project_lop_2.id)
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(4.minutes, another_source_project_lop_1.id, another_source_project_lop_2.id)
- end
- end
-end
diff --git a/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb b/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb
deleted file mode 100644
index 319c0802f2c..00000000000
--- a/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe ScheduleMergeRequestCleanupSchedulesBackfill, :sidekiq, schema: 20201023114628 do
- let(:merge_requests) { table(:merge_requests) }
- let(:cleanup_schedules) { table(:merge_request_cleanup_schedules) }
-
- let(:namespace) { table(:namespaces).create!(name: 'name', path: 'path') }
- let(:project) { table(:projects).create!(namespace_id: namespace.id) }
-
- describe '#up' do
- let!(:open_mr) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master') }
-
- let!(:closed_mr_1) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) }
- let!(:closed_mr_2) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) }
-
- let!(:merged_mr_1) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 3) }
- let!(:merged_mr_2) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 3) }
-
- before do
- stub_const("#{described_class}::BATCH_SIZE", 2)
- end
-
- it 'schedules BackfillMergeRequestCleanupSchedules background jobs' do
- Sidekiq::Testing.fake! do
- migrate!
-
- aggregate_failures do
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(2.minutes, closed_mr_1.id, closed_mr_2.id)
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(4.minutes, merged_mr_1.id, merged_mr_2.id)
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_migrate_security_scans_spec.rb b/spec/migrations/schedule_migrate_security_scans_spec.rb
deleted file mode 100644
index ce926241ba6..00000000000
--- a/spec/migrations/schedule_migrate_security_scans_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleMigrateSecurityScans, :sidekiq do
- let(:migration) { described_class.new }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:builds) { table(:ci_builds) }
- let(:job_artifacts) { table(:ci_job_artifacts) }
-
- let(:namespace) { namespaces.create!(name: "foo", path: "bar") }
- let(:project) { projects.create!(namespace_id: namespace.id) }
- let(:job) { builds.create! }
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 1)
- stub_const("#{described_class.name}::INTERVAL", 5.minutes.to_i)
- end
-
- context 'no security job artifacts' do
- before do
- table(:ci_job_artifacts)
- end
-
- it 'does not schedule migration' do
- Sidekiq::Testing.fake! do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs).to be_empty
- end
- end
- end
-
- context 'has security job artifacts' do
- let!(:job_artifact_1) { job_artifacts.create!(project_id: project.id, job_id: job.id, file_type: 5) }
- let!(:job_artifact_2) { job_artifacts.create!(project_id: project.id, job_id: job.id, file_type: 8) }
-
- it 'schedules migration of security scans' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migration.up
-
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, job_artifact_1.id, job_artifact_1.id)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(10.minutes, job_artifact_2.id, job_artifact_2.id)
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
- end
-
- context 'has non-security job artifacts' do
- let!(:job_artifact_1) { job_artifacts.create!(project_id: project.id, job_id: job.id, file_type: 4) }
- let!(:job_artifact_2) { job_artifacts.create!(project_id: project.id, job_id: job.id, file_type: 9) }
-
- it 'schedules migration of security scans' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migration.up
-
- expect(BackgroundMigrationWorker.jobs).to be_empty
- end
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_migrate_u2f_webauthn_spec.rb b/spec/migrations/schedule_migrate_u2f_webauthn_spec.rb
deleted file mode 100644
index 48f098e34fc..00000000000
--- a/spec/migrations/schedule_migrate_u2f_webauthn_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleMigrateU2fWebauthn do
- let(:migration_name) { described_class::MIGRATION }
- let(:u2f_registrations) { table(:u2f_registrations) }
- let(:webauthn_registrations) { table(:webauthn_registrations) }
-
- let(:users) { table(:users) }
-
- let(:user) { users.create!(email: 'email@email.com', name: 'foo', username: 'foo', projects_limit: 0) }
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 1)
- end
-
- context 'when there are u2f registrations' do
- let!(:u2f_reg_1) { create_u2f_registration(1, 'reg1') }
- let!(:u2f_reg_2) { create_u2f_registration(2, 'reg2') }
-
- it 'schedules a background migration' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(migration_name).to be_scheduled_delayed_migration(2.minutes, 1, 1)
- expect(migration_name).to be_scheduled_delayed_migration(4.minutes, 2, 2)
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
- end
-
- context 'when there are no u2f registrations' do
- it 'does not schedule background migrations' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(0)
- end
- end
- end
- end
-
- def create_u2f_registration(id, name)
- device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5))
- u2f_registrations.create!({ id: id,
- certificate: Base64.strict_encode64(device.cert_raw),
- key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
- public_key: Base64.strict_encode64(device.origin_public_key_raw),
- counter: 5,
- name: name,
- user_id: user.id })
- end
-end
diff --git a/spec/migrations/schedule_populate_has_vulnerabilities_spec.rb b/spec/migrations/schedule_populate_has_vulnerabilities_spec.rb
deleted file mode 100644
index edae7330b1e..00000000000
--- a/spec/migrations/schedule_populate_has_vulnerabilities_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe SchedulePopulateHasVulnerabilities do
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:vulnerabilities) { table(:vulnerabilities) }
- let(:user) { users.create!(name: 'test', email: 'test@example.com', projects_limit: 5) }
- let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
- let(:vulnerability_base_params) { { title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, author_id: user.id } }
- let!(:project_1) { projects.create!(namespace_id: namespace.id, name: 'foo_1') }
- let!(:project_2) { projects.create!(namespace_id: namespace.id, name: 'foo_2') }
- let!(:project_3) { projects.create!(namespace_id: namespace.id, name: 'foo_3') }
-
- around do |example|
- freeze_time { Sidekiq::Testing.fake! { example.run } }
- end
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 1)
-
- vulnerabilities.create!(vulnerability_base_params.merge(project_id: project_1.id))
- vulnerabilities.create!(vulnerability_base_params.merge(project_id: project_3.id))
- end
-
- it 'schedules the background jobs', :aggregate_failures do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to be(2)
- expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(2.minutes, project_1.id)
- expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(4.minutes, project_3.id)
- end
-end
diff --git a/spec/migrations/schedule_populate_issue_email_participants_spec.rb b/spec/migrations/schedule_populate_issue_email_participants_spec.rb
deleted file mode 100644
index 3a7a4e4df1e..00000000000
--- a/spec/migrations/schedule_populate_issue_email_participants_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe SchedulePopulateIssueEmailParticipants do
- let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
- let!(:project) { table(:projects).create!(id: 1, namespace_id: namespace.id) }
- let!(:issue1) { table(:issues).create!(id: 1, project_id: project.id, service_desk_reply_to: "a@gitlab.com") }
- let!(:issue2) { table(:issues).create!(id: 2, project_id: project.id) }
- let!(:issue3) { table(:issues).create!(id: 3, project_id: project.id, service_desk_reply_to: "b@gitlab.com") }
- let!(:issue4) { table(:issues).create!(id: 4, project_id: project.id, service_desk_reply_to: "c@gitlab.com") }
- let!(:issue5) { table(:issues).create!(id: 5, project_id: project.id, service_desk_reply_to: "d@gitlab.com") }
- let(:issue_email_participants) { table(:issue_email_participants) }
-
- it 'correctly schedules background migrations' do
- stub_const("#{described_class.name}::BATCH_SIZE", 2)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(2.minutes, 1, 3)
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(4.minutes, 4, 5)
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_populate_missing_dismissal_information_for_vulnerabilities_spec.rb b/spec/migrations/schedule_populate_missing_dismissal_information_for_vulnerabilities_spec.rb
deleted file mode 100644
index e5934f2171f..00000000000
--- a/spec/migrations/schedule_populate_missing_dismissal_information_for_vulnerabilities_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe SchedulePopulateMissingDismissalInformationForVulnerabilities do
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:vulnerabilities) { table(:vulnerabilities) }
- let(:user) { users.create!(name: 'test', email: 'test@example.com', projects_limit: 5) }
- let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
- let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
-
- let!(:vulnerability_1) { vulnerabilities.create!(title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id) }
- let!(:vulnerability_2) { vulnerabilities.create!(title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id, dismissed_at: Time.now) }
- let!(:vulnerability_3) { vulnerabilities.create!(title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id, dismissed_by_id: user.id) }
- let!(:vulnerability_4) { vulnerabilities.create!(title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id, dismissed_at: Time.now, dismissed_by_id: user.id) }
- let!(:vulnerability_5) { vulnerabilities.create!(title: 'title', state: 1, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id) }
-
- around do |example|
- freeze_time { Sidekiq::Testing.fake! { example.run } }
- end
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 1)
- end
-
- it 'schedules the background jobs', :aggregate_failures do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to be(3)
- expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(3.minutes, vulnerability_1.id)
- expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(6.minutes, vulnerability_2.id)
- expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(9.minutes, vulnerability_3.id)
- end
-end
diff --git a/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb b/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb
deleted file mode 100644
index 5f764a1ee8f..00000000000
--- a/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe SchedulePopulatePersonalSnippetStatistics do
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:snippets) { table(:snippets) }
- let(:projects) { table(:projects) }
- let!(:user1) { users.create!(id: 1, email: 'user1@example.com', projects_limit: 10, username: 'test1', name: 'Test1', state: 'active') }
- let!(:user2) { users.create!(id: 2, email: 'user2@example.com', projects_limit: 10, username: 'test2', name: 'Test2', state: 'active') }
- let!(:user3) { users.create!(id: 3, email: 'user3@example.com', projects_limit: 10, username: 'test3', name: 'Test3', state: 'active') }
- let!(:namespace1) { namespaces.create!(id: 1, owner_id: user1.id, name: 'test1', path: 'test1') }
- let!(:namespace2) { namespaces.create!(id: 2, owner_id: user2.id, name: 'test2', path: 'test2') }
- let!(:namespace3) { namespaces.create!(id: 3, owner_id: user3.id, name: 'test3', path: 'test3') }
-
- def create_snippet(id, user_id, type = 'PersonalSnippet')
- params = {
- id: id,
- type: type,
- author_id: user_id,
- file_name: 'foo',
- content: 'bar'
- }
-
- snippets.create!(params)
- end
-
- it 'correctly schedules background migrations' do
- # Creating the snippets in different order
- create_snippet(1, user1.id)
- create_snippet(2, user2.id)
- create_snippet(3, user1.id)
- create_snippet(4, user3.id)
- create_snippet(5, user3.id)
- create_snippet(6, user1.id)
- # Creating a project snippet to ensure we don't pick it
- create_snippet(7, user1.id, 'ProjectSnippet')
-
- stub_const("#{described_class}::BATCH_SIZE", 4)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- aggregate_failures do
- expect(described_class::MIGRATION)
- .to be_scheduled_migration([1, 3, 6, 2])
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(2.minutes, [4, 5])
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_populate_project_snippet_statistics_spec.rb b/spec/migrations/schedule_populate_project_snippet_statistics_spec.rb
deleted file mode 100644
index 4ac107c5202..00000000000
--- a/spec/migrations/schedule_populate_project_snippet_statistics_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe SchedulePopulateProjectSnippetStatistics do
- let(:users) { table(:users) }
- let(:snippets) { table(:snippets) }
- let(:projects) { table(:projects) }
- let(:namespaces) { table(:namespaces) }
- let(:user1) { users.create!(id: 1, email: 'user1@example.com', projects_limit: 10, username: 'test1', name: 'Test1', state: 'active') }
- let(:user2) { users.create!(id: 2, email: 'user2@example.com', projects_limit: 10, username: 'test2', name: 'Test2', state: 'active') }
- let(:namespace1) { namespaces.create!(id: 1, owner_id: user1.id, name: 'user1', path: 'user1') }
- let(:namespace2) { namespaces.create!(id: 2, owner_id: user2.id, name: 'user2', path: 'user2') }
- let(:project1) { projects.create!(id: 1, namespace_id: namespace1.id) }
- let(:project2) { projects.create!(id: 2, namespace_id: namespace1.id) }
- let(:project3) { projects.create!(id: 3, namespace_id: namespace2.id) }
-
- def create_snippet(id, user_id, project_id, type = 'ProjectSnippet')
- params = {
- id: id,
- type: type,
- author_id: user_id,
- project_id: project_id,
- file_name: 'foo',
- content: 'bar'
- }
-
- snippets.create!(params)
- end
-
- it 'correctly schedules background migrations' do
- # Creating the snippets in different order
- create_snippet(1, user1.id, project1.id)
- create_snippet(2, user2.id, project3.id)
- create_snippet(3, user1.id, project1.id)
- create_snippet(4, user1.id, project2.id)
- create_snippet(5, user2.id, project3.id)
- create_snippet(6, user1.id, project1.id)
- # Creating a personal snippet to ensure we don't pick it
- create_snippet(7, user1.id, nil, 'PersonalSnippet')
-
- stub_const("#{described_class}::BATCH_SIZE", 4)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- aggregate_failures do
- expect(described_class::MIGRATION)
- .to be_scheduled_migration([1, 3, 6, 4])
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(2.minutes, [2, 5])
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_populate_user_highest_roles_table_spec.rb b/spec/migrations/schedule_populate_user_highest_roles_table_spec.rb
deleted file mode 100644
index 0a2ee82b349..00000000000
--- a/spec/migrations/schedule_populate_user_highest_roles_table_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe SchedulePopulateUserHighestRolesTable do
- let(:users) { table(:users) }
-
- def create_user(id, params = {})
- user_params = {
- id: id,
- state: 'active',
- user_type: nil,
- bot_type: nil,
- ghost: nil,
- email: "user#{id}@example.com",
- projects_limit: 0
- }.merge(params)
-
- users.create!(user_params)
- end
-
- it 'correctly schedules background migrations' do
- create_user(1)
- create_user(2, state: 'blocked')
- create_user(3, user_type: 2)
- create_user(4)
- create_user(5, bot_type: 1)
- create_user(6, ghost: true)
- create_user(7, ghost: false)
-
- stub_const("#{described_class.name}::BATCH_SIZE", 2)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, 1, 4)
-
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(10.minutes, 7, 7)
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb b/spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb
deleted file mode 100644
index 380d107250b..00000000000
--- a/spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleRecalculateProjectAuthorizationsSecondRun do
- let(:users_table) { table(:users) }
-
- before do
- stub_const("#{described_class}::BATCH_SIZE", 2)
-
- 1.upto(4) do |i|
- users_table.create!(id: i, name: "user#{i}", email: "user#{i}@example.com", projects_limit: 1)
- end
- end
-
- it 'schedules background migration' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- expect(described_class::MIGRATION).to be_scheduled_migration(1, 2)
- expect(described_class::MIGRATION).to be_scheduled_migration(3, 4)
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_recalculate_project_authorizations_spec.rb b/spec/migrations/schedule_recalculate_project_authorizations_spec.rb
deleted file mode 100644
index a4400c2ac83..00000000000
--- a/spec/migrations/schedule_recalculate_project_authorizations_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleRecalculateProjectAuthorizations do
- let(:users_table) { table(:users) }
- let(:namespaces_table) { table(:namespaces) }
- let(:projects_table) { table(:projects) }
- let(:project_authorizations_table) { table(:project_authorizations) }
-
- let(:user1) { users_table.create!(name: 'user1', email: 'user1@example.com', projects_limit: 1) }
- let(:user2) { users_table.create!(name: 'user2', email: 'user2@example.com', projects_limit: 1) }
- let(:group) { namespaces_table.create!(id: 1, type: 'Group', name: 'group', path: 'group') }
- let(:project) do
- projects_table.create!(id: 1, name: 'project', path: 'project',
- visibility_level: 0, namespace_id: group.id)
- end
-
- before do
- stub_const("#{described_class}::BATCH_SIZE", 1)
-
- project_authorizations_table.create!(user_id: user1.id, project_id: project.id, access_level: 30)
- project_authorizations_table.create!(user_id: user2.id, project_id: project.id, access_level: 30)
- end
-
- it 'schedules background migration' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- expect(described_class::MIGRATION).to be_scheduled_migration([user1.id])
- expect(described_class::MIGRATION).to be_scheduled_migration([user2.id])
- end
- end
- end
-
- it 'ignores projects with higher id than maximum group id' do
- another_user = users_table.create!(name: 'another user', email: 'another-user@example.com',
- projects_limit: 1)
- ignored_project = projects_table.create!(id: 2, name: 'ignored-project', path: 'ignored-project',
- visibility_level: 0, namespace_id: group.id)
- project_authorizations_table.create!(user_id: another_user.id, project_id: ignored_project.id,
- access_level: 30)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- expect(described_class::MIGRATION).to be_scheduled_migration([user1.id])
- expect(described_class::MIGRATION).to be_scheduled_migration([user2.id])
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb b/spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb
deleted file mode 100644
index 302ae1d5ebe..00000000000
--- a/spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleRecalculateProjectAuthorizationsThirdRun do
- let(:users_table) { table(:users) }
-
- before do
- stub_const("#{described_class}::BATCH_SIZE", 2)
-
- 1.upto(4) do |i|
- users_table.create!(id: i, name: "user#{i}", email: "user#{i}@example.com", projects_limit: 1)
- end
- end
-
- it 'schedules background migration' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- expect(described_class::MIGRATION).to be_scheduled_migration(1, 2)
- expect(described_class::MIGRATION).to be_scheduled_migration(3, 4)
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_repopulate_historical_vulnerability_statistics_spec.rb b/spec/migrations/schedule_repopulate_historical_vulnerability_statistics_spec.rb
deleted file mode 100644
index a65c94cf60e..00000000000
--- a/spec/migrations/schedule_repopulate_historical_vulnerability_statistics_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleRepopulateHistoricalVulnerabilityStatistics do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:project_settings) { table(:project_settings) }
-
- let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
- let!(:project_1) { projects.create!(namespace_id: namespace.id, name: 'foo_1') }
- let!(:project_2) { projects.create!(namespace_id: namespace.id, name: 'foo_2') }
- let!(:project_3) { projects.create!(namespace_id: namespace.id, name: 'foo_3') }
- let!(:project_4) { projects.create!(namespace_id: namespace.id, name: 'foo_4') }
-
- around do |example|
- freeze_time { Sidekiq::Testing.fake! { example.run } }
- end
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 1)
-
- project_settings.create!(project_id: project_1.id, has_vulnerabilities: true)
- project_settings.create!(project_id: project_2.id, has_vulnerabilities: false)
- project_settings.create!(project_id: project_4.id, has_vulnerabilities: true)
- end
-
- it 'schedules the background jobs', :aggregate_failures do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to be(2)
- expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(described_class::DELAY_INTERVAL, [project_1.id], described_class::DAY_COUNT)
- expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(2 * described_class::DELAY_INTERVAL, [project_4.id], described_class::DAY_COUNT)
- end
-end
diff --git a/spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb b/spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
deleted file mode 100644
index 8f265acccae..00000000000
--- a/spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleUpdateExistingSubgroupToMatchVisibilityLevelOfParent do
- include MigrationHelpers::NamespacesHelpers
- let(:migration_class) { described_class::MIGRATION }
- let(:migration_name) { migration_class.to_s.demodulize }
-
- context 'private visibility level' do
- it 'correctly schedules background migrations' do
- parent = create_namespace('parent', Gitlab::VisibilityLevel::PRIVATE)
- create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: parent.id)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(1)
- expect(migration_name).to be_scheduled_migration_with_multiple_args([parent.id], Gitlab::VisibilityLevel::PRIVATE)
- end
- end
- end
-
- it 'correctly schedules background migrations for groups and subgroups' do
- parent = create_namespace('parent', Gitlab::VisibilityLevel::PRIVATE)
- middle_group = create_namespace('middle_group', Gitlab::VisibilityLevel::PRIVATE, parent_id: parent.id)
- create_namespace('middle_empty_group', Gitlab::VisibilityLevel::PRIVATE, parent_id: parent.id)
- create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: middle_group.id)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(1)
- expect(migration_name).to be_scheduled_migration_with_multiple_args([middle_group.id, parent.id], Gitlab::VisibilityLevel::PRIVATE)
- end
- end
- end
- end
-
- context 'internal visibility level' do
- it 'correctly schedules background migrations' do
- parent = create_namespace('parent', Gitlab::VisibilityLevel::INTERNAL)
- middle_group = create_namespace('child', Gitlab::VisibilityLevel::INTERNAL, parent_id: parent.id)
- create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: middle_group.id)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(1)
- expect(migration_name).to be_scheduled_migration_with_multiple_args([parent.id, middle_group.id], Gitlab::VisibilityLevel::INTERNAL)
- end
- end
- end
- end
-
- context 'mixed visibility levels' do
- it 'correctly schedules background migrations' do
- parent1 = create_namespace('parent1', Gitlab::VisibilityLevel::INTERNAL)
- create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: parent1.id)
- parent2 = create_namespace('parent2', Gitlab::VisibilityLevel::PRIVATE)
- middle_group = create_namespace('middle_group', Gitlab::VisibilityLevel::INTERNAL, parent_id: parent2.id)
- create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: middle_group.id)
-
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- expect(migration_name).to be_scheduled_migration_with_multiple_args([parent1.id, middle_group.id], Gitlab::VisibilityLevel::INTERNAL)
- expect(migration_name).to be_scheduled_migration_with_multiple_args([parent2.id], Gitlab::VisibilityLevel::PRIVATE)
- end
- end
- end
- end
-end
diff --git a/spec/migrations/schedule_update_existing_users_that_require_two_factor_auth_spec.rb b/spec/migrations/schedule_update_existing_users_that_require_two_factor_auth_spec.rb
deleted file mode 100644
index a839229ec22..00000000000
--- a/spec/migrations/schedule_update_existing_users_that_require_two_factor_auth_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleUpdateExistingUsersThatRequireTwoFactorAuth do
- let(:users) { table(:users) }
- let!(:user_1) { users.create!(require_two_factor_authentication_from_group: true, name: "user1", email: "user1@example.com", projects_limit: 1) }
- let!(:user_2) { users.create!(require_two_factor_authentication_from_group: false, name: "user2", email: "user2@example.com", projects_limit: 1) }
- let!(:user_3) { users.create!(require_two_factor_authentication_from_group: true, name: "user3", email: "user3@example.com", projects_limit: 1) }
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 1)
- end
-
- it 'schedules jobs for users that require two factor authentication' do
- Sidekiq::Testing.fake! do
- freeze_time do
- migrate!
-
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(
- 2.minutes, user_1.id, user_1.id)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(
- 4.minutes, user_3.id, user_3.id)
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- end
- end
- end
-end
diff --git a/spec/migrations/seed_merge_trains_enabled_spec.rb b/spec/migrations/seed_merge_trains_enabled_spec.rb
deleted file mode 100644
index 1cb0e3cf8a6..00000000000
--- a/spec/migrations/seed_merge_trains_enabled_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe SeedMergeTrainsEnabled do
- describe 'migrate' do
- let(:project_ci_cd_settings) { table(:project_ci_cd_settings) }
- let(:projects) { table(:projects) }
- let(:namespaces) { table(:namespaces) }
-
- context 'when on Gitlab.com' do
- before do
- namespace = namespaces.create!(name: 'hello', path: 'hello/')
- project1 = projects.create!(namespace_id: namespace.id)
- project2 = projects.create!(namespace_id: namespace.id)
- project_ci_cd_settings.create!(project_id: project1.id, merge_pipelines_enabled: true)
- project_ci_cd_settings.create!(project_id: project2.id, merge_pipelines_enabled: false)
- end
-
- it 'updates merge_trains_enabled to true for where merge_pipelines_enabled is true' do
- migrate!
-
- expect(project_ci_cd_settings.where(merge_trains_enabled: true).count).to be(1)
- end
- end
- end
-end
diff --git a/spec/migrations/seed_repository_storages_weighted_spec.rb b/spec/migrations/seed_repository_storages_weighted_spec.rb
deleted file mode 100644
index 102107bcc9f..00000000000
--- a/spec/migrations/seed_repository_storages_weighted_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe SeedRepositoryStoragesWeighted do
- let(:storages) { { "foo" => {}, "baz" => {} } }
- let(:application_settings) do
- table(:application_settings).tap do |klass|
- klass.class_eval do
- serialize :repository_storages
- end
- end
- end
-
- before do
- allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
- end
-
- let(:application_setting) { application_settings.create! }
- let(:repository_storages) { ["foo"] }
-
- it 'correctly schedules background migrations' do
- application_setting.repository_storages = repository_storages
- application_setting.save!
-
- migrate!
-
- expect(application_settings.find(application_setting.id).repository_storages_weighted).to eq({ "foo" => 100, "baz" => 0 })
- end
-end
diff --git a/spec/migrations/services_remove_temporary_index_on_project_id_spec.rb b/spec/migrations/services_remove_temporary_index_on_project_id_spec.rb
deleted file mode 100644
index d47f6deb2d5..00000000000
--- a/spec/migrations/services_remove_temporary_index_on_project_id_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ServicesRemoveTemporaryIndexOnProjectId do
- let(:migration_instance) { described_class.new }
-
- it 'adds and removes temporary partial index in up and down methods' do
- reversible_migration do |migration|
- migration.before -> {
- expect(migration_instance.index_exists?(:services, :project_id, name: described_class::INDEX_NAME)).to be true
- }
-
- migration.after -> {
- expect(migration_instance.index_exists?(:services, :project_id, name: described_class::INDEX_NAME)).to be false
- }
- end
- end
-
- describe '#up' do
- context 'index does not exist' do
- it 'skips removal action' do
- migrate!
-
- expect { migrate! }.not_to change { migration_instance.index_exists?(:services, :project_id, name: described_class::INDEX_NAME) }
- end
- end
- end
-
- describe '#down' do
- context 'index already exists' do
- it 'skips creation of duplicated temporary partial index on project_id' do
- schema_migrate_down!
-
- expect { schema_migrate_down! }.not_to change { migration_instance.index_exists?(:services, :project_id, name: described_class::INDEX_NAME) }
- end
- end
- end
-end
diff --git a/spec/migrations/set_job_waiter_ttl_spec.rb b/spec/migrations/set_job_waiter_ttl_spec.rb
deleted file mode 100644
index a051f8a535c..00000000000
--- a/spec/migrations/set_job_waiter_ttl_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe SetJobWaiterTtl, :redis do
- it 'sets TTLs where necessary' do
- waiter_with_ttl = Gitlab::JobWaiter.new.key
- waiter_without_ttl = Gitlab::JobWaiter.new.key
- key_with_ttl = "foo:bar"
- key_without_ttl = "foo:qux"
-
- Gitlab::Redis::SharedState.with do |redis|
- redis.set(waiter_with_ttl, "zzz", ex: 2000)
- redis.set(waiter_without_ttl, "zzz")
- redis.set(key_with_ttl, "zzz", ex: 2000)
- redis.set(key_without_ttl, "zzz")
-
- described_class.new.up
-
- # This is the point of the migration. We know the migration uses a TTL of 21_600
- expect(redis.ttl(waiter_without_ttl)).to be > 20_000
-
- # Other TTL's should be untouched by the migration
- expect(redis.ttl(waiter_with_ttl)).to be_between(1000, 2000)
- expect(redis.ttl(key_with_ttl)).to be_between(1000, 2000)
- expect(redis.ttl(key_without_ttl)).to eq(-1)
- end
- end
-end
diff --git a/spec/migrations/slice_merge_request_diff_commit_migrations_spec.rb b/spec/migrations/slice_merge_request_diff_commit_migrations_spec.rb
index 1fd19ee42b4..e03dd73ec8b 100644
--- a/spec/migrations/slice_merge_request_diff_commit_migrations_spec.rb
+++ b/spec/migrations/slice_merge_request_diff_commit_migrations_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration! 'slice_merge_request_diff_commit_migrations'
+require_migration!
RSpec.describe SliceMergeRequestDiffCommitMigrations, :migration do
let(:migration) { described_class.new }
diff --git a/spec/migrations/steal_merge_request_diff_commit_users_migration_spec.rb b/spec/migrations/steal_merge_request_diff_commit_users_migration_spec.rb
index 3ad0b5a93c2..4fb4ba61a34 100644
--- a/spec/migrations/steal_merge_request_diff_commit_users_migration_spec.rb
+++ b/spec/migrations/steal_merge_request_diff_commit_users_migration_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-require_migration! 'steal_merge_request_diff_commit_users_migration'
+require_migration!
RSpec.describe StealMergeRequestDiffCommitUsersMigration, :migration do
let(:migration) { described_class.new }
diff --git a/spec/migrations/unconfirm_wrongfully_verified_emails_spec.rb b/spec/migrations/unconfirm_wrongfully_verified_emails_spec.rb
deleted file mode 100644
index 5adc866d0a5..00000000000
--- a/spec/migrations/unconfirm_wrongfully_verified_emails_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe UnconfirmWrongfullyVerifiedEmails do
- before do
- user = table(:users).create!(name: 'user1', email: 'test1@test.com', projects_limit: 1)
- table(:emails).create!(email: 'test2@test.com', user_id: user.id)
- end
-
- context 'when email confirmation is enabled' do
- before do
- table(:application_settings).create!(send_user_confirmation_email: true)
- end
-
- it 'enqueues WrongullyConfirmedEmailUnconfirmer job' do
- Sidekiq::Testing.fake! do
- migrate!
-
- jobs = BackgroundMigrationWorker.jobs
- expect(jobs.size).to eq(1)
- expect(jobs.first["args"].first).to eq(Gitlab::BackgroundMigration::WrongfullyConfirmedEmailUnconfirmer.name.demodulize)
- end
- end
- end
-
- context 'when email confirmation is disabled' do
- before do
- table(:application_settings).create!(send_user_confirmation_email: false)
- end
-
- it 'does not enqueue WrongullyConfirmedEmailUnconfirmer job' do
- Sidekiq::Testing.fake! do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(0)
- end
- end
- end
-
- context 'when email application setting record does not exist' do
- before do
- table(:application_settings).delete_all
- end
-
- it 'does not enqueue WrongullyConfirmedEmailUnconfirmer job' do
- Sidekiq::Testing.fake! do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(0)
- end
- end
- end
-end
diff --git a/spec/migrations/update_application_setting_npm_package_requests_forwarding_default_spec.rb b/spec/migrations/update_application_setting_npm_package_requests_forwarding_default_spec.rb
deleted file mode 100644
index be209536208..00000000000
--- a/spec/migrations/update_application_setting_npm_package_requests_forwarding_default_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe UpdateApplicationSettingNpmPackageRequestsForwardingDefault do
- # Create test data - pipeline and CI/CD jobs.
- let(:application_settings) { table(:application_settings) }
-
- before do
- application_settings.create!(npm_package_requests_forwarding: false)
- end
-
- # Test just the up migration.
- it 'correctly migrates the application setting' do
- expect { migrate! }.to change { current_application_setting }.from(false).to(true)
- end
-
- # Test a reversible migration.
- it 'correctly migrates up and down the application setting' do
- reversible_migration do |migration|
- # Expectations will run before the up migration,
- # and then again after the down migration
- migration.before -> {
- expect(current_application_setting).to eq false
- }
-
- # Expectations will run after the up migration.
- migration.after -> {
- expect(current_application_setting).to eq true
- }
- end
- end
-
- def current_application_setting
- ApplicationSetting.current_without_cache.npm_package_requests_forwarding
- end
-end
diff --git a/spec/migrations/update_fingerprint_sha256_within_keys_spec.rb b/spec/migrations/update_fingerprint_sha256_within_keys_spec.rb
deleted file mode 100644
index 22ec3135703..00000000000
--- a/spec/migrations/update_fingerprint_sha256_within_keys_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe UpdateFingerprintSha256WithinKeys do
- let(:key_table) { table(:keys) }
-
- describe '#up' do
- it 'the BackgroundMigrationWorker will be triggered and fingerprint_sha256 populated' do
- key_table.create!(
- id: 1,
- user_id: 1,
- title: 'test',
- key: 'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt1016k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=',
- fingerprint: 'ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1',
- fingerprint_sha256: nil
- )
-
- expect(Key.first.fingerprint_sha256).to eq(nil)
-
- described_class.new.up
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(1)
- expect(BackgroundMigrationWorker.jobs.first["args"][0]).to eq("MigrateFingerprintSha256WithinKeys")
- expect(BackgroundMigrationWorker.jobs.first["args"][1]).to eq([1, 1])
- end
- end
-end
diff --git a/spec/migrations/update_historical_data_recorded_at_spec.rb b/spec/migrations/update_historical_data_recorded_at_spec.rb
deleted file mode 100644
index 95d2bb989fd..00000000000
--- a/spec/migrations/update_historical_data_recorded_at_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe UpdateHistoricalDataRecordedAt do
- let(:historical_data_table) { table(:historical_data) }
-
- it 'reversibly populates recorded_at from created_at or date' do
- row1 = historical_data_table.create!(
- date: Date.current - 1.day,
- created_at: Time.current - 1.day
- )
-
- row2 = historical_data_table.create!(date: Date.current - 2.days)
- row2.update!(created_at: nil)
-
- reversible_migration do |migration|
- migration.before -> {
- expect(row1.reload.recorded_at).to eq(nil)
- expect(row2.reload.recorded_at).to eq(nil)
- }
-
- migration.after -> {
- expect(row1.reload.recorded_at).to eq(row1.created_at)
- expect(row2.reload.recorded_at).to eq(row2.date.in_time_zone(Time.zone).change(hour: 12))
- }
- end
- end
-end
diff --git a/spec/migrations/update_internal_ids_last_value_for_epics_renamed_spec.rb b/spec/migrations/update_internal_ids_last_value_for_epics_renamed_spec.rb
deleted file mode 100644
index d7d1781aaa2..00000000000
--- a/spec/migrations/update_internal_ids_last_value_for_epics_renamed_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe UpdateInternalIdsLastValueForEpicsRenamed, :migration, schema: 20201124185639 do
- let(:namespaces) { table(:namespaces) }
- let(:users) { table(:users) }
- let(:epics) { table(:epics) }
- let(:internal_ids) { table(:internal_ids) }
-
- let!(:author) { users.create!(name: 'test', email: 'test@example.com', projects_limit: 0) }
- let!(:group1) { namespaces.create!(type: 'Group', name: 'group1', path: 'group1') }
- let!(:group2) { namespaces.create!(type: 'Group', name: 'group2', path: 'group2') }
- let!(:group3) { namespaces.create!(type: 'Group', name: 'group3', path: 'group3') }
- let!(:epic_last_value1) { internal_ids.create!(usage: 4, last_value: 5, namespace_id: group1.id) }
- let!(:epic_last_value2) { internal_ids.create!(usage: 4, last_value: 5, namespace_id: group2.id) }
- let!(:epic_last_value3) { internal_ids.create!(usage: 4, last_value: 5, namespace_id: group3.id) }
- let!(:epic_1) { epics.create!(iid: 110, title: 'from epic 1', group_id: group1.id, author_id: author.id, title_html: 'any') }
- let!(:epic_2) { epics.create!(iid: 5, title: 'from epic 1', group_id: group2.id, author_id: author.id, title_html: 'any') }
- let!(:epic_3) { epics.create!(iid: 3, title: 'from epic 1', group_id: group3.id, author_id: author.id, title_html: 'any') }
-
- it 'updates out of sync internal_ids last_value' do
- migrate!
-
- expect(internal_ids.find_by(usage: 4, namespace_id: group1.id).last_value).to eq(110)
- expect(internal_ids.find_by(usage: 4, namespace_id: group2.id).last_value).to eq(5)
- expect(internal_ids.find_by(usage: 4, namespace_id: group3.id).last_value).to eq(5)
- end
-end
diff --git a/spec/migrations/update_routes_for_lost_and_found_group_and_orphaned_projects_spec.rb b/spec/migrations/update_routes_for_lost_and_found_group_and_orphaned_projects_spec.rb
deleted file mode 100644
index 74e97b82363..00000000000
--- a/spec/migrations/update_routes_for_lost_and_found_group_and_orphaned_projects_spec.rb
+++ /dev/null
@@ -1,223 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe UpdateRoutesForLostAndFoundGroupAndOrphanedProjects, :migration do
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:members) { table(:members) }
- let(:projects) { table(:projects) }
- let(:routes) { table(:routes) }
-
- before do
- # Create a Ghost User and its namnespace, but skip the route
- ghost_user = users.create!(
- name: 'Ghost User',
- username: 'ghost',
- email: 'ghost@example.com',
- user_type: described_class::User::USER_TYPE_GHOST,
- projects_limit: 100,
- state: :active,
- bio: 'This is a "Ghost User"'
- )
-
- namespaces.create!(
- name: 'Ghost User',
- path: 'ghost',
- owner_id: ghost_user.id,
- visibility_level: 20
- )
-
- # Create the 'lost-and-found', owned by the Ghost user, but with no route
- lost_and_found_group = namespaces.create!(
- name: described_class::User::LOST_AND_FOUND_GROUP,
- path: described_class::User::LOST_AND_FOUND_GROUP,
- type: 'Group',
- description: 'Group to store orphaned projects',
- visibility_level: 0
- )
-
- members.create!(
- type: 'GroupMember',
- source_id: lost_and_found_group.id,
- user_id: ghost_user.id,
- source_type: 'Namespace',
- access_level: described_class::User::ACCESS_LEVEL_OWNER,
- notification_level: 3
- )
-
- # Add an orphaned project under 'lost-and-found' but with the wrong path in its route
- orphaned_project = projects.create!(
- name: 'orphaned_project',
- path: 'orphaned_project',
- visibility_level: 20,
- archived: false,
- namespace_id: lost_and_found_group.id
- )
-
- routes.create!(
- source_id: orphaned_project.id,
- source_type: 'Project',
- path: 'orphaned_project',
- name: 'orphaned_project',
- created_at: Time.current,
- updated_at: Time.current
- )
-
- # Create another user named ghost which is not the Ghost User
- # Also create a 'lost-and-found' group for them and add projects to it
- # Purpose: test that the routes added for the 'lost-and-found' group and
- # its projects are unique
- fake_ghost_user = users.create!(
- name: 'Ghost User',
- username: 'ghost1',
- email: 'ghost1@example.com',
- user_type: nil,
- projects_limit: 100,
- state: :active,
- bio: 'This is NOT a "Ghost User"'
- )
-
- fake_ghost_user_namespace = namespaces.create!(
- name: 'Ghost User',
- path: 'ghost1',
- owner_id: fake_ghost_user.id,
- visibility_level: 20
- )
-
- routes.create!(
- source_id: fake_ghost_user_namespace.id,
- source_type: 'Namespace',
- path: 'ghost1',
- name: 'Ghost User',
- created_at: Time.current,
- updated_at: Time.current
- )
-
- fake_lost_and_found_group = namespaces.create!(
- name: 'Lost and Found',
- path: described_class::User::LOST_AND_FOUND_GROUP, # same path as the lost-and-found group
- type: 'Group',
- description: 'Fake lost and found group with the same path as the real one',
- visibility_level: 20
- )
-
- routes.create!(
- source_id: fake_lost_and_found_group.id,
- source_type: 'Namespace',
- path: described_class::User::LOST_AND_FOUND_GROUP, # same path as the lost-and-found group
- name: 'Lost and Found',
- created_at: Time.current,
- updated_at: Time.current
- )
-
- members.create!(
- type: 'GroupMember',
- source_id: fake_lost_and_found_group.id,
- user_id: fake_ghost_user.id,
- source_type: 'Namespace',
- access_level: described_class::User::ACCESS_LEVEL_OWNER,
- notification_level: 3
- )
-
- normal_project = projects.create!(
- name: 'normal_project',
- path: 'normal_project',
- visibility_level: 20,
- archived: false,
- namespace_id: fake_lost_and_found_group.id
- )
-
- routes.create!(
- source_id: normal_project.id,
- source_type: 'Project',
- path: "#{described_class::User::LOST_AND_FOUND_GROUP}/normal_project",
- name: 'Lost and Found / normal_project',
- created_at: Time.current,
- updated_at: Time.current
- )
-
- # Add a project whose route conflicts with the ghost username
- # and should force the data migration to pick a new Ghost username and path
- ghost_project = projects.create!(
- name: 'Ghost Project',
- path: 'ghost',
- visibility_level: 20,
- archived: false,
- namespace_id: fake_lost_and_found_group.id
- )
-
- routes.create!(
- source_id: ghost_project.id,
- source_type: 'Project',
- path: 'ghost',
- name: 'Ghost Project',
- created_at: Time.current,
- updated_at: Time.current
- )
- end
-
- it 'fixes the ghost user username and namespace path' do
- ghost_user = users.find_by(user_type: described_class::User::USER_TYPE_GHOST)
- ghost_namespace = namespaces.find_by(owner_id: ghost_user.id)
-
- expect(ghost_user.username).to eq('ghost')
- expect(ghost_namespace.path).to eq('ghost')
-
- disable_migrations_output { migrate! }
-
- ghost_user = users.find_by(user_type: described_class::User::USER_TYPE_GHOST)
- ghost_namespace = namespaces.find_by(owner_id: ghost_user.id)
- ghost_namespace_route = routes.find_by(source_id: ghost_namespace.id, source_type: 'Namespace')
-
- expect(ghost_user.username).to eq('ghost2')
- expect(ghost_namespace.path).to eq('ghost2')
- expect(ghost_namespace_route.path).to eq('ghost2')
- end
-
- it 'creates the route for the ghost user namespace' do
- expect(routes.where(path: 'ghost').count).to eq(1)
- expect(routes.where(path: 'ghost1').count).to eq(1)
- expect(routes.where(path: 'ghost2').count).to eq(0)
-
- disable_migrations_output { migrate! }
-
- expect(routes.where(path: 'ghost').count).to eq(1)
- expect(routes.where(path: 'ghost1').count).to eq(1)
- expect(routes.where(path: 'ghost2').count).to eq(1)
- end
-
- it 'fixes the path for the lost-and-found group by generating a unique one' do
- expect(namespaces.where(path: described_class::User::LOST_AND_FOUND_GROUP).count).to eq(2)
-
- disable_migrations_output { migrate! }
-
- expect(namespaces.where(path: described_class::User::LOST_AND_FOUND_GROUP).count).to eq(1)
-
- lost_and_found_group = namespaces.find_by(name: described_class::User::LOST_AND_FOUND_GROUP)
- expect(lost_and_found_group.path).to eq('lost-and-found1')
- end
-
- it 'creates the route for the lost-and-found group' do
- expect(routes.where(path: described_class::User::LOST_AND_FOUND_GROUP).count).to eq(1)
- expect(routes.where(path: 'lost-and-found1').count).to eq(0)
-
- disable_migrations_output { migrate! }
-
- expect(routes.where(path: described_class::User::LOST_AND_FOUND_GROUP).count).to eq(1)
- expect(routes.where(path: 'lost-and-found1').count).to eq(1)
- end
-
- it 'updates the route for the orphaned project' do
- orphaned_project_route = routes.find_by(path: 'orphaned_project')
- expect(orphaned_project_route.name).to eq('orphaned_project')
-
- disable_migrations_output { migrate! }
-
- updated_route = routes.find_by(id: orphaned_project_route.id)
- expect(updated_route.path).to eq('lost-and-found1/orphaned_project')
- expect(updated_route.name).to eq("#{described_class::User::LOST_AND_FOUND_GROUP} / orphaned_project")
- end
-end
diff --git a/spec/migrations/update_timestamp_softwarelicensespolicy_spec.rb b/spec/migrations/update_timestamp_softwarelicensespolicy_spec.rb
deleted file mode 100644
index 0210f23f5c5..00000000000
--- a/spec/migrations/update_timestamp_softwarelicensespolicy_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require_migration!
-
-RSpec.describe UpdateTimestampSoftwarelicensespolicy do
- let(:software_licenses_policy) { table(:software_license_policies) }
- let(:projects) { table(:projects) }
- let(:licenses) { table(:software_licenses) }
-
- before do
- projects.create!(name: 'gitlab', path: 'gitlab-org/gitlab-ce', namespace_id: 1)
- licenses.create!(name: 'MIT')
- software_licenses_policy.create!(project_id: projects.first.id, software_license_id: licenses.first.id, created_at: nil, updated_at: nil)
- end
-
- it 'creates timestamps' do
- migrate!
-
- expect(software_licenses_policy.first.created_at).to be_present
- expect(software_licenses_policy.first.updated_at).to be_present
- end
-end
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index e131661602e..bb8d476f257 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -425,9 +425,9 @@ RSpec.describe Ability do
expect(keys).to include(
:administrator,
'admin',
- "/dp/condition/BasePolicy/admin/#{user_b.id}"
+ "/dp/condition/BasePolicy/admin/User:#{user_b.id}"
)
- expect(keys).not_to include("/dp/condition/BasePolicy/admin/#{user_a.id}")
+ expect(keys).not_to include("/dp/condition/BasePolicy/admin/User:#{user_a.id}")
end
# regression spec for re-entrant admin condition checks
diff --git a/spec/models/acts_as_taggable_on/tag_spec.rb b/spec/models/acts_as_taggable_on/tag_spec.rb
new file mode 100644
index 00000000000..4b390bbd0bb
--- /dev/null
+++ b/spec/models/acts_as_taggable_on/tag_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ActsAsTaggableOn::Tag do
+ it 'has the same connection as Ci::ApplicationRecord' do
+ query = 'select current_database()'
+
+ expect(described_class.connection.execute(query).first).to eq(Ci::ApplicationRecord.connection.execute(query).first)
+ expect(described_class.retrieve_connection.execute(query).first).to eq(Ci::ApplicationRecord.retrieve_connection.execute(query).first)
+ end
+
+ it 'has the same sticking as Ci::ApplicationRecord' do
+ expect(described_class.sticking).to eq(Ci::ApplicationRecord.sticking)
+ end
+end
diff --git a/spec/models/acts_as_taggable_on/tagging_spec.rb b/spec/models/acts_as_taggable_on/tagging_spec.rb
new file mode 100644
index 00000000000..4520a0aaf70
--- /dev/null
+++ b/spec/models/acts_as_taggable_on/tagging_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ActsAsTaggableOn::Tagging do
+ it 'has the same connection as Ci::ApplicationRecord' do
+ query = 'select current_database()'
+
+ expect(described_class.connection.execute(query).first).to eq(Ci::ApplicationRecord.connection.execute(query).first)
+ expect(described_class.retrieve_connection.execute(query).first).to eq(Ci::ApplicationRecord.retrieve_connection.execute(query).first)
+ end
+
+ it 'has the same sticking as Ci::ApplicationRecord' do
+ expect(described_class.sticking).to eq(Ci::ApplicationRecord.sticking)
+ end
+end
diff --git a/spec/models/analytics/cycle_analytics/issue_stage_event_spec.rb b/spec/models/analytics/cycle_analytics/issue_stage_event_spec.rb
index c0d5b9203b8..ac17271ff99 100644
--- a/spec/models/analytics/cycle_analytics/issue_stage_event_spec.rb
+++ b/spec/models/analytics/cycle_analytics/issue_stage_event_spec.rb
@@ -9,5 +9,12 @@ RSpec.describe Analytics::CycleAnalytics::IssueStageEvent do
it { is_expected.to validate_presence_of(:project_id) }
it { is_expected.to validate_presence_of(:start_event_timestamp) }
- it_behaves_like 'StageEventModel'
+ it 'has state enum' do
+ expect(described_class.states).to eq(Issue.available_states)
+ end
+
+ it_behaves_like 'StageEventModel' do
+ let_it_be(:stage_event_factory) { :cycle_analytics_issue_stage_event }
+ let_it_be(:issuable_factory) { :issue }
+ end
end
diff --git a/spec/models/analytics/cycle_analytics/merge_request_stage_event_spec.rb b/spec/models/analytics/cycle_analytics/merge_request_stage_event_spec.rb
index 82a7e66d62a..bccc485d3f9 100644
--- a/spec/models/analytics/cycle_analytics/merge_request_stage_event_spec.rb
+++ b/spec/models/analytics/cycle_analytics/merge_request_stage_event_spec.rb
@@ -9,5 +9,12 @@ RSpec.describe Analytics::CycleAnalytics::MergeRequestStageEvent do
it { is_expected.to validate_presence_of(:project_id) }
it { is_expected.to validate_presence_of(:start_event_timestamp) }
- it_behaves_like 'StageEventModel'
+ it 'has state enum' do
+ expect(described_class.states).to eq(MergeRequest.available_states)
+ end
+
+ it_behaves_like 'StageEventModel' do
+ let_it_be(:stage_event_factory) { :cycle_analytics_merge_request_stage_event }
+ let_it_be(:issuable_factory) { :merge_request }
+ end
end
diff --git a/spec/models/blob_viewer/package_json_spec.rb b/spec/models/blob_viewer/package_json_spec.rb
index 8a394a7334f..1dcba3bcb4f 100644
--- a/spec/models/blob_viewer/package_json_spec.rb
+++ b/spec/models/blob_viewer/package_json_spec.rb
@@ -27,11 +27,55 @@ RSpec.describe BlobViewer::PackageJson do
end
end
- describe '#package_url' do
- it 'returns the package URL' do
- expect(subject).to receive(:prepare!)
+ context 'yarn' do
+ let(:data) do
+ <<-SPEC.strip_heredoc
+ {
+ "name": "module-name",
+ "version": "10.3.1",
+ "engines": {
+ "yarn": "^2.4.0"
+ }
+ }
+ SPEC
+ end
+
+ let(:blob) { fake_blob(path: 'package.json', data: data) }
+
+ subject { described_class.new(blob) }
+
+ describe '#package_url' do
+ it 'returns the package URL', :aggregate_failures do
+ expect(subject).to receive(:prepare!)
+
+ expect(subject.package_url).to eq("https://yarnpkg.com/package/#{subject.package_name}")
+ end
+ end
- expect(subject.package_url).to eq("https://www.npmjs.com/package/#{subject.package_name}")
+ describe '#manager_url' do
+ it 'returns the manager URL', :aggregate_failures do
+ expect(subject).to receive(:prepare!)
+
+ expect(subject.manager_url).to eq("https://yarnpkg.com/")
+ end
+ end
+ end
+
+ context 'npm' do
+ describe '#package_url' do
+ it 'returns the package URL', :aggregate_failures do
+ expect(subject).to receive(:prepare!)
+
+ expect(subject.package_url).to eq("https://www.npmjs.com/package/#{subject.package_name}")
+ end
+ end
+
+ describe '#manager_url' do
+ it 'returns the manager URL', :aggregate_failures do
+ expect(subject).to receive(:prepare!)
+
+ expect(subject.manager_url).to eq("https://www.npmjs.com/")
+ end
end
end
diff --git a/spec/models/bulk_imports/entity_spec.rb b/spec/models/bulk_imports/entity_spec.rb
index 278d7f4bc56..cc66572cd6f 100644
--- a/spec/models/bulk_imports/entity_spec.rb
+++ b/spec/models/bulk_imports/entity_spec.rb
@@ -243,4 +243,13 @@ RSpec.describe BulkImports::Entity, type: :model do
end
end
end
+
+ describe '#relation_download_url_path' do
+ it 'returns export relations url with download query string' do
+ entity = build(:bulk_import_entity)
+
+ expect(entity.relation_download_url_path('test'))
+ .to eq("/groups/#{entity.encoded_source_full_path}/export_relations/download?relation=test")
+ end
+ end
end
diff --git a/spec/models/bulk_imports/file_transfer/project_config_spec.rb b/spec/models/bulk_imports/file_transfer/project_config_spec.rb
index 3bd79333f0c..02151da583e 100644
--- a/spec/models/bulk_imports/file_transfer/project_config_spec.rb
+++ b/spec/models/bulk_imports/file_transfer/project_config_spec.rb
@@ -80,7 +80,7 @@ RSpec.describe BulkImports::FileTransfer::ProjectConfig do
describe '#tree_relation_definition_for' do
it 'returns relation definition' do
- expected = { service_desk_setting: { except: [:outgoing_name, :file_template_project_id], include: [] } }
+ expected = { service_desk_setting: { except: [:outgoing_name, :file_template_project_id], include: [], only: %i[project_id issue_template_key project_key] } }
expect(subject.tree_relation_definition_for('service_desk_setting')).to eq(expected)
end
diff --git a/spec/models/chat_name_spec.rb b/spec/models/chat_name_spec.rb
index 9ed00003ac1..67e0f98d147 100644
--- a/spec/models/chat_name_spec.rb
+++ b/spec/models/chat_name_spec.rb
@@ -43,4 +43,12 @@ RSpec.describe ChatName do
expect(subject.last_used_at).to eq(time)
end
end
+
+ it_behaves_like 'it has loose foreign keys' do
+ let(:factory_name) { :chat_name }
+
+ before do
+ Ci::PipelineChatData # ensure that the referenced model is loaded
+ end
+ end
end
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index 8f1ae9c5f02..6fde55103f8 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -17,8 +17,6 @@ RSpec.describe Ci::Bridge do
{ trigger: { project: 'my/project', branch: 'master' } }
end
- it { is_expected.to respond_to(:runner_features) }
-
it 'has many sourced pipelines' do
expect(bridge).to have_many(:sourced_pipelines)
end
diff --git a/spec/models/ci/build_metadata_spec.rb b/spec/models/ci/build_metadata_spec.rb
index 069864fa765..b2ffb34da1d 100644
--- a/spec/models/ci/build_metadata_spec.rb
+++ b/spec/models/ci/build_metadata_spec.rb
@@ -121,4 +121,16 @@ RSpec.describe Ci::BuildMetadata do
end
end
end
+
+ describe 'set_cancel_gracefully' do
+ it 'sets cancel_gracefully' do
+ build.set_cancel_gracefully
+
+ expect(build.cancel_gracefully?).to be true
+ end
+
+ it 'returns false' do
+ expect(build.cancel_gracefully?).to be false
+ end
+ end
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 2ebf75a1d8a..b7de8ca4337 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -35,7 +35,8 @@ RSpec.describe Ci::Build do
it { is_expected.to respond_to(:has_trace?) }
it { is_expected.to respond_to(:trace) }
- it { is_expected.to respond_to(:runner_features) }
+ it { is_expected.to respond_to(:set_cancel_gracefully) }
+ it { is_expected.to respond_to(:cancel_gracefully?) }
it { is_expected.to delegate_method(:merge_request?).to(:pipeline) }
it { is_expected.to delegate_method(:merge_request_ref?).to(:pipeline) }
@@ -214,6 +215,26 @@ RSpec.describe Ci::Build do
end
end
+ describe '.license_management_jobs' do
+ subject { described_class.license_management_jobs }
+
+ let!(:management_build) { create(:ci_build, :success, name: :license_management) }
+ let!(:scanning_build) { create(:ci_build, :success, name: :license_scanning) }
+ let!(:another_build) { create(:ci_build, :success, name: :another_type) }
+
+ it 'returns license_scanning jobs' do
+ is_expected.to include(scanning_build)
+ end
+
+ it 'returns license_management jobs' do
+ is_expected.to include(management_build)
+ end
+
+ it 'doesnt return filtered out jobs' do
+ is_expected.not_to include(another_build)
+ end
+ end
+
describe '.finished_before' do
subject { described_class.finished_before(date) }
@@ -350,7 +371,7 @@ RSpec.describe Ci::Build do
it 'sticks the build if the status changed' do
job = create(:ci_build, :pending)
- expect(ApplicationRecord.sticking).to receive(:stick)
+ expect(described_class.sticking).to receive(:stick)
.with(:build, job.id)
job.update!(status: :running)
@@ -1290,7 +1311,7 @@ RSpec.describe Ci::Build do
end
end
- shared_examples_for 'state transition as a deployable' do
+ describe 'state transition as a deployable' do
subject { build.send(event) }
let!(:build) { create(:ci_build, :with_deployment, :start_review_app, project: project, pipeline: pipeline) }
@@ -1332,6 +1353,22 @@ RSpec.describe Ci::Build do
expect(deployment).to be_running
end
+
+ context 'when deployment is already running state' do
+ before do
+ build.deployment.success!
+ end
+
+ it 'does not change deployment status and tracks an error' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_exception).with(
+ instance_of(Deployment::StatusSyncError), deployment_id: deployment.id, build_id: build.id)
+
+ with_cross_database_modification_prevented do
+ expect { subject }.not_to change { deployment.reload.status }
+ end
+ end
+ end
end
context 'when transits to success' do
@@ -1399,36 +1436,6 @@ RSpec.describe Ci::Build do
end
end
- it_behaves_like 'state transition as a deployable' do
- context 'when transits to running' do
- let(:event) { :run! }
-
- context 'when deployment is already running state' do
- before do
- build.deployment.success!
- end
-
- it 'does not change deployment status and tracks an error' do
- expect(Gitlab::ErrorTracking)
- .to receive(:track_exception).with(
- instance_of(Deployment::StatusSyncError), deployment_id: deployment.id, build_id: build.id)
-
- with_cross_database_modification_prevented do
- expect { subject }.not_to change { deployment.reload.status }
- end
- end
- end
- end
- end
-
- context 'when update_deployment_after_transaction_commit feature flag is disabled' do
- before do
- stub_feature_flags(update_deployment_after_transaction_commit: false)
- end
-
- it_behaves_like 'state transition as a deployable'
- end
-
describe '#on_stop' do
subject { build.on_stop }
@@ -2759,7 +2766,10 @@ RSpec.describe Ci::Build do
let(:job_dependency_var) { { key: 'job_dependency', value: 'value', public: true, masked: false } }
before do
- allow(build).to receive(:predefined_variables) { [build_pre_var] }
+ allow_next_instance_of(Gitlab::Ci::Variables::Builder) do |builder|
+ allow(builder).to receive(:predefined_variables) { [build_pre_var] }
+ end
+
allow(build).to receive(:yaml_variables) { [build_yaml_var] }
allow(build).to receive(:persisted_variables) { [] }
allow(build).to receive(:job_jwt_variables) { [job_jwt_var] }
@@ -3411,75 +3421,122 @@ RSpec.describe Ci::Build do
end
describe '#scoped_variables' do
- context 'when build has not been persisted yet' do
- let(:build) do
- described_class.new(
- name: 'rspec',
- stage: 'test',
- ref: 'feature',
- project: project,
- pipeline: pipeline,
- scheduling_type: :stage
- )
- end
+ before do
+ pipeline.clear_memoization(:predefined_vars_in_builder_enabled)
+ end
- let(:pipeline) { create(:ci_pipeline, project: project, ref: 'feature') }
+ it 'records a prometheus metric' do
+ histogram = double(:histogram)
+ expect(::Gitlab::Ci::Pipeline::Metrics).to receive(:pipeline_builder_scoped_variables_histogram)
+ .and_return(histogram)
- it 'does not persist the build' do
- expect(build).to be_valid
- expect(build).not_to be_persisted
+ expect(histogram).to receive(:observe)
+ .with({}, a_kind_of(ActiveSupport::Duration))
- build.scoped_variables
+ build.scoped_variables
+ end
- expect(build).not_to be_persisted
- end
+ shared_examples 'calculates scoped_variables' do
+ context 'when build has not been persisted yet' do
+ let(:build) do
+ described_class.new(
+ name: 'rspec',
+ stage: 'test',
+ ref: 'feature',
+ project: project,
+ pipeline: pipeline,
+ scheduling_type: :stage
+ )
+ end
- it 'returns static predefined variables' do
- keys = %w[CI_JOB_NAME
- CI_COMMIT_SHA
- CI_COMMIT_SHORT_SHA
- CI_COMMIT_REF_NAME
- CI_COMMIT_REF_SLUG
- CI_JOB_STAGE]
+ let(:pipeline) { create(:ci_pipeline, project: project, ref: 'feature') }
- variables = build.scoped_variables
+ it 'does not persist the build' do
+ expect(build).to be_valid
+ expect(build).not_to be_persisted
- variables.map { |env| env[:key] }.tap do |names|
- expect(names).to include(*keys)
+ build.scoped_variables
+
+ expect(build).not_to be_persisted
end
- expect(variables)
- .to include(key: 'CI_COMMIT_REF_NAME', value: 'feature', public: true, masked: false)
+ it 'returns static predefined variables' do
+ keys = %w[CI_JOB_NAME
+ CI_COMMIT_SHA
+ CI_COMMIT_SHORT_SHA
+ CI_COMMIT_REF_NAME
+ CI_COMMIT_REF_SLUG
+ CI_JOB_STAGE]
+
+ variables = build.scoped_variables
+
+ variables.map { |env| env[:key] }.tap do |names|
+ expect(names).to include(*keys)
+ end
+
+ expect(variables)
+ .to include(key: 'CI_COMMIT_REF_NAME', value: 'feature', public: true, masked: false)
+ end
+
+ it 'does not return prohibited variables' do
+ keys = %w[CI_JOB_ID
+ CI_JOB_URL
+ CI_JOB_TOKEN
+ CI_BUILD_ID
+ CI_BUILD_TOKEN
+ CI_REGISTRY_USER
+ CI_REGISTRY_PASSWORD
+ CI_REPOSITORY_URL
+ CI_ENVIRONMENT_URL
+ CI_DEPLOY_USER
+ CI_DEPLOY_PASSWORD]
+
+ build.scoped_variables.map { |env| env[:key] }.tap do |names|
+ expect(names).not_to include(*keys)
+ end
+ end
end
- it 'does not return prohibited variables' do
- keys = %w[CI_JOB_ID
- CI_JOB_URL
- CI_JOB_TOKEN
- CI_BUILD_ID
- CI_BUILD_TOKEN
- CI_REGISTRY_USER
- CI_REGISTRY_PASSWORD
- CI_REPOSITORY_URL
- CI_ENVIRONMENT_URL
- CI_DEPLOY_USER
- CI_DEPLOY_PASSWORD]
+ context 'with dependency variables' do
+ let!(:prepare) { create(:ci_build, name: 'prepare', pipeline: pipeline, stage_idx: 0) }
+ let!(:build) { create(:ci_build, pipeline: pipeline, stage_idx: 1, options: { dependencies: ['prepare'] }) }
+
+ let!(:job_variable) { create(:ci_job_variable, :dotenv_source, job: prepare) }
- build.scoped_variables.map { |env| env[:key] }.tap do |names|
- expect(names).not_to include(*keys)
+ it 'inherits dependent variables' do
+ expect(build.scoped_variables.to_hash).to include(job_variable.key => job_variable.value)
end
end
end
- context 'with dependency variables' do
- let!(:prepare) { create(:ci_build, name: 'prepare', pipeline: pipeline, stage_idx: 0) }
- let!(:build) { create(:ci_build, pipeline: pipeline, stage_idx: 1, options: { dependencies: ['prepare'] }) }
+ it_behaves_like 'calculates scoped_variables'
- let!(:job_variable) { create(:ci_job_variable, :dotenv_source, job: prepare) }
+ it 'delegates to the variable builders' do
+ expect_next_instance_of(Gitlab::Ci::Variables::Builder) do |builder|
+ expect(builder)
+ .to receive(:scoped_variables).with(build, hash_including(:environment, :dependencies))
+ .and_call_original
- it 'inherits dependent variables' do
- expect(build.scoped_variables.to_hash).to include(job_variable.key => job_variable.value)
+ expect(builder).to receive(:predefined_variables).and_call_original
end
+
+ build.scoped_variables
+ end
+
+ context 'when ci builder feature flag is disabled' do
+ before do
+ stub_feature_flags(ci_predefined_vars_in_builder: false)
+ end
+
+ it 'does not delegate to the variable builders' do
+ expect_next_instance_of(Gitlab::Ci::Variables::Builder) do |builder|
+ expect(builder).not_to receive(:predefined_variables)
+ end
+
+ build.scoped_variables
+ end
+
+ it_behaves_like 'calculates scoped_variables'
end
end
@@ -3569,6 +3626,27 @@ RSpec.describe Ci::Build do
include_examples "secret CI variables"
end
+ describe '#kubernetes_variables' do
+ let(:build) { create(:ci_build) }
+ let(:service) { double(execute: template) }
+ let(:template) { double(to_yaml: 'example-kubeconfig', valid?: template_valid) }
+ let(:template_valid) { true }
+
+ subject { build.kubernetes_variables }
+
+ before do
+ allow(Ci::GenerateKubeconfigService).to receive(:new).with(build).and_return(service)
+ end
+
+ it { is_expected.to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) }
+
+ context 'generated config is invalid' do
+ let(:template_valid) { false }
+
+ it { is_expected.not_to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) }
+ end
+ end
+
describe '#deployment_variables' do
let(:build) { create(:ci_build, environment: environment) }
let(:environment) { 'production' }
@@ -3728,7 +3806,7 @@ RSpec.describe Ci::Build do
it 'ensures that it is not run in database transaction' do
expect(job.pipeline.persistent_ref).to receive(:create) do
- expect(Gitlab::Database.main).not_to be_inside_transaction
+ expect(ApplicationRecord).not_to be_inside_transaction
end
run_job_without_exception
@@ -5326,4 +5404,23 @@ RSpec.describe Ci::Build do
create(:ci_build)
end
end
+
+ describe '#runner_features' do
+ subject do
+ build.save!
+ build.cancel_gracefully?
+ end
+
+ let_it_be(:build) { create(:ci_build, pipeline: pipeline) }
+
+ it 'cannot cancel gracefully' do
+ expect(subject).to be false
+ end
+
+ it 'can cancel gracefully' do
+ build.set_cancel_gracefully
+
+ expect(subject).to be true
+ end
+ end
end
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index a94a1dd284a..d63f87e8943 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -351,6 +351,21 @@ RSpec.describe Ci::JobArtifact do
end
end
+ context 'when updating any field except the file' do
+ let(:artifact) { create(:ci_job_artifact, :unarchived_trace_artifact, file_store: 2) }
+
+ before do
+ stub_artifacts_object_storage(direct_upload: true)
+ artifact.file.object_store = 1
+ end
+
+ it 'the `after_commit` hook does not update `file_store`' do
+ artifact.update!(expire_at: Time.current)
+
+ expect(artifact.file_store).to be(2)
+ end
+ end
+
describe 'validates file format' do
subject { artifact }
@@ -507,6 +522,53 @@ RSpec.describe Ci::JobArtifact do
end
end
+ describe '#store_after_commit?' do
+ let(:file_type) { :archive }
+ let(:artifact) { build(:ci_job_artifact, file_type) }
+
+ context 'when direct upload is enabled' do
+ before do
+ stub_artifacts_object_storage(direct_upload: true)
+ end
+
+ context 'when the artifact is a trace' do
+ let(:file_type) { :trace }
+
+ context 'when ci_store_trace_outside_transaction is enabled' do
+ it 'returns true' do
+ expect(artifact.store_after_commit?).to be_truthy
+ end
+ end
+
+ context 'when ci_store_trace_outside_transaction is disabled' do
+ before do
+ stub_feature_flags(ci_store_trace_outside_transaction: false)
+ end
+
+ it 'returns false' do
+ expect(artifact.store_after_commit?).to be_falsey
+ end
+ end
+ end
+
+ context 'when the artifact is not a trace' do
+ it 'returns false' do
+ expect(artifact.store_after_commit?).to be_falsey
+ end
+ end
+ end
+
+ context 'when direct upload is disabled' do
+ before do
+ stub_artifacts_object_storage(direct_upload: false)
+ end
+
+ it 'returns false' do
+ expect(artifact.store_after_commit?).to be_falsey
+ end
+ end
+ end
+
describe 'file is being stored' do
subject { create(:ci_job_artifact, :archive) }
diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb
index c7e1fe91b1e..fee74f8f674 100644
--- a/spec/models/ci/pipeline_schedule_spec.rb
+++ b/spec/models/ci/pipeline_schedule_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Ci::PipelineSchedule do
- let_it_be(:project) { create_default(:project) }
+ let_it_be_with_reload(:project) { create_default(:project) }
subject { build(:ci_pipeline_schedule) }
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 5f3aad0ab24..e573a6ef780 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -3361,7 +3361,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
shared_examples 'sending a notification' do
it 'sends an email', :sidekiq_might_not_need_inline do
- should_only_email(pipeline.user, kind: :bcc)
+ should_only_email(pipeline.user)
end
end
@@ -4595,4 +4595,20 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
end
+
+ describe '#authorized_cluster_agents' do
+ let(:pipeline) { create(:ci_empty_pipeline, :created) }
+ let(:agent) { instance_double(Clusters::Agent) }
+ let(:authorization) { instance_double(Clusters::Agents::GroupAuthorization, agent: agent) }
+ let(:finder) { double(execute: [authorization]) }
+
+ it 'retrieves agent records from the finder and caches the result' do
+ expect(Clusters::AgentAuthorizationsFinder).to receive(:new).once
+ .with(pipeline.project)
+ .and_return(finder)
+
+ expect(pipeline.authorized_cluster_agents).to contain_exactly(agent)
+ expect(pipeline.authorized_cluster_agents).to contain_exactly(agent) # cached
+ end
+ end
end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 826332268c5..2e79159cc60 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -5,6 +5,14 @@ require 'spec_helper'
RSpec.describe Ci::Runner do
it_behaves_like 'having unique enum values'
+ it_behaves_like 'it has loose foreign keys' do
+ let(:factory_name) { :ci_runner }
+
+ before do
+ Clusters::Applications::Runner # ensure that the referenced model is loaded
+ end
+ end
+
describe 'groups association' do
# Due to other assoctions such as projects this whole spec is allowed to
# generate cross-database queries. So we have this temporary spec to
@@ -44,7 +52,7 @@ RSpec.describe Ci::Runner do
let(:runner) { create(:ci_runner, :group, groups: [group]) }
it 'disallows assigning group if already assigned to a group' do
- runner.groups << build(:group)
+ runner.runner_namespaces << build(:ci_runner_namespace)
expect(runner).not_to be_valid
expect(runner.errors.full_messages).to include('Runner needs to be assigned to exactly one group')
@@ -397,7 +405,7 @@ RSpec.describe Ci::Runner do
it 'sticks the runner to the primary and calls the original method' do
runner = create(:ci_runner)
- expect(ApplicationRecord.sticking).to receive(:stick)
+ expect(described_class.sticking).to receive(:stick)
.with(:runner, runner.id)
expect(Gitlab::Workhorse).to receive(:set_key_and_notify)
@@ -618,7 +626,7 @@ RSpec.describe Ci::Runner do
end
describe '#status' do
- let(:runner) { create(:ci_runner, :instance, contacted_at: 1.second.ago) }
+ let(:runner) { build(:ci_runner, :instance) }
subject { runner.status }
@@ -630,6 +638,45 @@ RSpec.describe Ci::Runner do
it { is_expected.to eq(:not_connected) }
end
+ context 'inactive but online' do
+ before do
+ runner.contacted_at = 1.second.ago
+ runner.active = false
+ end
+
+ it { is_expected.to eq(:online) }
+ end
+
+ context 'contacted 1s ago' do
+ before do
+ runner.contacted_at = 1.second.ago
+ end
+
+ it { is_expected.to eq(:online) }
+ end
+
+ context 'contacted long time ago' do
+ before do
+ runner.contacted_at = 1.year.ago
+ end
+
+ it { is_expected.to eq(:offline) }
+ end
+ end
+
+ describe '#deprecated_rest_status' do
+ let(:runner) { build(:ci_runner, :instance, contacted_at: 1.second.ago) }
+
+ subject { runner.deprecated_rest_status }
+
+ context 'never connected' do
+ before do
+ runner.contacted_at = nil
+ end
+
+ it { is_expected.to eq(:not_connected) }
+ end
+
context 'contacted 1s ago' do
before do
runner.contacted_at = 1.second.ago
diff --git a/spec/models/ci/trigger_spec.rb b/spec/models/ci/trigger_spec.rb
index 4ba6c6e50f7..c254279a32f 100644
--- a/spec/models/ci/trigger_spec.rb
+++ b/spec/models/ci/trigger_spec.rb
@@ -57,4 +57,8 @@ RSpec.describe Ci::Trigger do
it { is_expected.to eq(false) }
end
end
+
+ it_behaves_like 'includes Limitable concern' do
+ subject { build(:ci_trigger, owner: project.owner, project: project) }
+ end
end
diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb
index 788430d53d3..806c60d5aff 100644
--- a/spec/models/clusters/applications/runner_spec.rb
+++ b/spec/models/clusters/applications/runner_spec.rb
@@ -112,7 +112,7 @@ RSpec.describe Clusters::Applications::Runner do
subject
expect(runner).to be_group_type
- expect(runner.groups).to eq [group]
+ expect(runner.runner_namespaces.pluck(:namespace_id)).to match_array [group.id]
end
end
@@ -162,12 +162,12 @@ RSpec.describe Clusters::Applications::Runner do
it 'pauses associated runner' do
active_runner = create(:ci_runner, contacted_at: 1.second.ago)
- expect(active_runner.status).to eq(:online)
+ expect(active_runner.active).to be_truthy
application_runner = create(:clusters_applications_runner, :scheduled, runner: active_runner)
application_runner.prepare_uninstall
- expect(active_runner.status).to eq(:paused)
+ expect(active_runner.active).to be_falsey
end
end
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index 9d305e31bad..d61bed80aaa 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -178,13 +178,13 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
end
- describe '.with_application_prometheus' do
- subject { described_class.with_application_prometheus }
+ describe '.with_integration_prometheus' do
+ subject { described_class.with_integration_prometheus }
let!(:cluster) { create(:cluster) }
context 'cluster has prometheus application' do
- let!(:application) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
+ let!(:application) { create(:clusters_integrations_prometheus, cluster: cluster) }
it { is_expected.to include(cluster) }
end
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 20afddd8470..59d14574c02 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -379,6 +379,22 @@ RSpec.describe CommitStatus do
end
end
+ describe '.retried_ordered' do
+ subject { described_class.retried_ordered.to_a }
+
+ let!(:statuses) do
+ [create_status(name: 'aa', ref: 'bb', status: 'running', retried: true),
+ create_status(name: 'cc', ref: 'cc', status: 'pending', retried: true),
+ create_status(name: 'aa', ref: 'cc', status: 'success', retried: true),
+ create_status(name: 'cc', ref: 'bb', status: 'success'),
+ create_status(name: 'aa', ref: 'bb', status: 'success')]
+ end
+
+ it 'returns retried statuses in order' do
+ is_expected.to eq(statuses.values_at(2, 0, 1))
+ end
+ end
+
describe '.running_or_pending' do
subject { described_class.running_or_pending.order(:id) }
diff --git a/spec/models/concerns/bulk_insert_safe_spec.rb b/spec/models/concerns/bulk_insert_safe_spec.rb
index 172986c142c..e6b197f34ca 100644
--- a/spec/models/concerns/bulk_insert_safe_spec.rb
+++ b/spec/models/concerns/bulk_insert_safe_spec.rb
@@ -5,42 +5,42 @@ require 'spec_helper'
RSpec.describe BulkInsertSafe do
before(:all) do
ActiveRecord::Schema.define do
- create_table :bulk_insert_parent_items, force: true do |t|
+ create_table :_test_bulk_insert_parent_items, force: true do |t|
t.string :name, null: false
end
- create_table :bulk_insert_items, force: true do |t|
+ create_table :_test_bulk_insert_items, force: true do |t|
t.string :name, null: true
t.integer :enum_value, null: false
t.text :encrypted_secret_value, null: false
t.string :encrypted_secret_value_iv, null: false
t.binary :sha_value, null: false, limit: 20
t.jsonb :jsonb_value, null: false
- t.belongs_to :bulk_insert_parent_item, foreign_key: true, null: true
+ t.belongs_to :bulk_insert_parent_item, foreign_key: { to_table: :_test_bulk_insert_parent_items }, null: true
t.timestamps null: true
t.index :name, unique: true
end
- create_table :bulk_insert_items_with_composite_pk, id: false, force: true do |t|
+ create_table :_test_bulk_insert_items_with_composite_pk, id: false, force: true do |t|
t.integer :id, null: true
t.string :name, null: true
end
- execute("ALTER TABLE bulk_insert_items_with_composite_pk ADD PRIMARY KEY (id,name);")
+ execute("ALTER TABLE _test_bulk_insert_items_with_composite_pk ADD PRIMARY KEY (id,name);")
end
end
after(:all) do
ActiveRecord::Schema.define do
- drop_table :bulk_insert_items, force: true
- drop_table :bulk_insert_parent_items, force: true
- drop_table :bulk_insert_items_with_composite_pk, force: true
+ drop_table :_test_bulk_insert_items, force: true
+ drop_table :_test_bulk_insert_parent_items, force: true
+ drop_table :_test_bulk_insert_items_with_composite_pk, force: true
end
end
BulkInsertParentItem = Class.new(ActiveRecord::Base) do
- self.table_name = :bulk_insert_parent_items
+ self.table_name = :_test_bulk_insert_parent_items
self.inheritance_column = :_type_disabled
def self.name
@@ -54,7 +54,7 @@ RSpec.describe BulkInsertSafe do
let_it_be(:bulk_insert_item_class) do
Class.new(ActiveRecord::Base) do
- self.table_name = 'bulk_insert_items'
+ self.table_name = '_test_bulk_insert_items'
include BulkInsertSafe
include ShaAttribute
@@ -182,7 +182,7 @@ RSpec.describe BulkInsertSafe do
context 'with returns option set' do
let(:items) { bulk_insert_item_class.valid_list(1) }
- subject(:bulk_insert) { bulk_insert_item_class.bulk_insert!(items, returns: returns) }
+ subject(:legacy_bulk_insert) { bulk_insert_item_class.bulk_insert!(items, returns: returns) }
context 'when is set to :ids' do
let(:returns) { :ids }
@@ -247,7 +247,7 @@ RSpec.describe BulkInsertSafe do
context 'when a model with composite primary key is inserted' do
let_it_be(:bulk_insert_items_with_composite_pk_class) do
Class.new(ActiveRecord::Base) do
- self.table_name = 'bulk_insert_items_with_composite_pk'
+ self.table_name = '_test_bulk_insert_items_with_composite_pk'
include BulkInsertSafe
end
diff --git a/spec/models/concerns/bulk_insertable_associations_spec.rb b/spec/models/concerns/bulk_insertable_associations_spec.rb
index 25b13c8233d..9713f1ce9a4 100644
--- a/spec/models/concerns/bulk_insertable_associations_spec.rb
+++ b/spec/models/concerns/bulk_insertable_associations_spec.rb
@@ -6,42 +6,50 @@ RSpec.describe BulkInsertableAssociations do
class BulkFoo < ApplicationRecord
include BulkInsertSafe
+ self.table_name = '_test_bulk_foos'
+
validates :name, presence: true
end
class BulkBar < ApplicationRecord
include BulkInsertSafe
+
+ self.table_name = '_test_bulk_bars'
end
- SimpleBar = Class.new(ApplicationRecord)
+ SimpleBar = Class.new(ApplicationRecord) do
+ self.table_name = '_test_simple_bars'
+ end
class BulkParent < ApplicationRecord
include BulkInsertableAssociations
- has_many :bulk_foos
+ self.table_name = '_test_bulk_parents'
+
+ has_many :bulk_foos, class_name: 'BulkFoo'
has_many :bulk_hunks, class_name: 'BulkFoo'
- has_many :bulk_bars
- has_many :simple_bars # not `BulkInsertSafe`
+ has_many :bulk_bars, class_name: 'BulkBar'
+ has_many :simple_bars, class_name: 'SimpleBar' # not `BulkInsertSafe`
has_one :bulk_foo # not supported
end
before(:all) do
ActiveRecord::Schema.define do
- create_table :bulk_parents, force: true do |t|
+ create_table :_test_bulk_parents, force: true do |t|
t.string :name, null: true
end
- create_table :bulk_foos, force: true do |t|
+ create_table :_test_bulk_foos, force: true do |t|
t.string :name, null: true
t.belongs_to :bulk_parent, null: false
end
- create_table :bulk_bars, force: true do |t|
+ create_table :_test_bulk_bars, force: true do |t|
t.string :name, null: true
t.belongs_to :bulk_parent, null: false
end
- create_table :simple_bars, force: true do |t|
+ create_table :_test_simple_bars, force: true do |t|
t.string :name, null: true
t.belongs_to :bulk_parent, null: false
end
@@ -50,10 +58,10 @@ RSpec.describe BulkInsertableAssociations do
after(:all) do
ActiveRecord::Schema.define do
- drop_table :bulk_foos, force: true
- drop_table :bulk_bars, force: true
- drop_table :simple_bars, force: true
- drop_table :bulk_parents, force: true
+ drop_table :_test_bulk_foos, force: true
+ drop_table :_test_bulk_bars, force: true
+ drop_table :_test_simple_bars, force: true
+ drop_table :_test_bulk_parents, force: true
end
end
diff --git a/spec/models/concerns/cascading_namespace_setting_attribute_spec.rb b/spec/models/concerns/cascading_namespace_setting_attribute_spec.rb
index e8f2b18e662..6be6e3f048f 100644
--- a/spec/models/concerns/cascading_namespace_setting_attribute_spec.rb
+++ b/spec/models/concerns/cascading_namespace_setting_attribute_spec.rb
@@ -136,6 +136,21 @@ RSpec.describe NamespaceSetting, 'CascadingNamespaceSettingAttribute' do
.to raise_error(ActiveRecord::RecordInvalid, /Delayed project removal cannot be changed because it is locked by an ancestor/)
end
end
+
+ context 'when parent locked the attribute then the application settings locks it' do
+ before do
+ subgroup_settings.update!(delayed_project_removal: true)
+ group_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: false)
+ stub_application_setting(lock_delayed_project_removal: true, delayed_project_removal: true)
+
+ subgroup_settings.clear_memoization(:delayed_project_removal)
+ subgroup_settings.clear_memoization(:delayed_project_removal_locked_ancestor)
+ end
+
+ it 'returns the application setting value' do
+ expect(delayed_project_removal).to eq(true)
+ end
+ end
end
describe '#delayed_project_removal?' do
diff --git a/spec/models/concerns/clusters/agents/authorization_config_scopes_spec.rb b/spec/models/concerns/clusters/agents/authorization_config_scopes_spec.rb
new file mode 100644
index 00000000000..a4d1a33b3d5
--- /dev/null
+++ b/spec/models/concerns/clusters/agents/authorization_config_scopes_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Clusters::Agents::AuthorizationConfigScopes do
+ describe '.with_available_ci_access_fields' do
+ let(:project) { create(:project) }
+
+ let!(:agent_authorization_0) { create(:agent_project_authorization, project: project) }
+ let!(:agent_authorization_1) { create(:agent_project_authorization, project: project, config: { access_as: {} }) }
+ let!(:agent_authorization_2) { create(:agent_project_authorization, project: project, config: { access_as: { agent: {} } }) }
+ let!(:impersonate_authorization) { create(:agent_project_authorization, project: project, config: { access_as: { impersonate: {} } }) }
+ let!(:ci_user_authorization) { create(:agent_project_authorization, project: project, config: { access_as: { ci_user: {} } }) }
+ let!(:ci_job_authorization) { create(:agent_project_authorization, project: project, config: { access_as: { ci_job: {} } }) }
+ let!(:unexpected_authorization) { create(:agent_project_authorization, project: project, config: { access_as: { unexpected: {} } }) }
+
+ subject { Clusters::Agents::ProjectAuthorization.with_available_ci_access_fields(project) }
+
+ it { is_expected.to contain_exactly(agent_authorization_0, agent_authorization_1, agent_authorization_2) }
+ end
+end
diff --git a/spec/models/concerns/database_reflection_spec.rb b/spec/models/concerns/database_reflection_spec.rb
new file mode 100644
index 00000000000..4111f29ea8d
--- /dev/null
+++ b/spec/models/concerns/database_reflection_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DatabaseReflection do
+ describe '.reflect' do
+ it 'returns a Reflection instance' do
+ expect(User.database).to be_an_instance_of(Gitlab::Database::Reflection)
+ end
+
+ it 'memoizes the result' do
+ instance1 = User.database
+ instance2 = User.database
+
+ expect(instance1).to equal(instance2)
+ end
+ end
+end
diff --git a/spec/models/concerns/has_integrations_spec.rb b/spec/models/concerns/has_integrations_spec.rb
deleted file mode 100644
index ea6b0e69209..00000000000
--- a/spec/models/concerns/has_integrations_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe HasIntegrations do
- let_it_be(:project_1) { create(:project) }
- let_it_be(:project_2) { create(:project) }
- let_it_be(:project_3) { create(:project) }
- let_it_be(:project_4) { create(:project) }
- let_it_be(:instance_integration) { create(:jira_integration, :instance) }
-
- before do
- create(:jira_integration, project: project_1, inherit_from_id: instance_integration.id)
- create(:jira_integration, project: project_2, inherit_from_id: nil)
- create(:jira_integration, group: create(:group), project: nil, inherit_from_id: nil)
- create(:jira_integration, project: project_3, inherit_from_id: nil)
- create(:integrations_slack, project: project_4, inherit_from_id: nil)
- end
-
- describe '.without_integration' do
- it 'returns projects without integration' do
- expect(Project.without_integration(instance_integration)).to contain_exactly(project_4)
- end
- end
-end
diff --git a/spec/models/concerns/legacy_bulk_insert_spec.rb b/spec/models/concerns/legacy_bulk_insert_spec.rb
new file mode 100644
index 00000000000..0c6f84f391b
--- /dev/null
+++ b/spec/models/concerns/legacy_bulk_insert_spec.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# rubocop: disable Gitlab/BulkInsert
+RSpec.describe LegacyBulkInsert do
+ let(:model) { ApplicationRecord }
+
+ describe '#bulk_insert' do
+ before do
+ allow(model).to receive(:connection).and_return(dummy_connection)
+ allow(dummy_connection).to receive(:quote_column_name, &:itself)
+ allow(dummy_connection).to receive(:quote, &:itself)
+ allow(dummy_connection).to receive(:execute)
+ end
+
+ let(:dummy_connection) { double(:connection) }
+
+ let(:rows) do
+ [
+ { a: 1, b: 2, c: 3 },
+ { c: 6, a: 4, b: 5 }
+ ]
+ end
+
+ it 'does nothing with empty rows' do
+ expect(dummy_connection).not_to receive(:execute)
+
+ model.legacy_bulk_insert('test', [])
+ end
+
+ it 'uses the ordering from the first row' do
+ expect(dummy_connection).to receive(:execute) do |sql|
+ expect(sql).to include('(1, 2, 3)')
+ expect(sql).to include('(4, 5, 6)')
+ end
+
+ model.legacy_bulk_insert('test', rows)
+ end
+
+ it 'quotes column names' do
+ expect(dummy_connection).to receive(:quote_column_name).with(:a)
+ expect(dummy_connection).to receive(:quote_column_name).with(:b)
+ expect(dummy_connection).to receive(:quote_column_name).with(:c)
+
+ model.legacy_bulk_insert('test', rows)
+ end
+
+ it 'quotes values' do
+ 1.upto(6) do |i|
+ expect(dummy_connection).to receive(:quote).with(i)
+ end
+
+ model.legacy_bulk_insert('test', rows)
+ end
+
+ it 'does not quote values of a column in the disable_quote option' do
+ [1, 2, 4, 5].each do |i|
+ expect(dummy_connection).to receive(:quote).with(i)
+ end
+
+ model.legacy_bulk_insert('test', rows, disable_quote: :c)
+ end
+
+ it 'does not quote values of columns in the disable_quote option' do
+ [2, 5].each do |i|
+ expect(dummy_connection).to receive(:quote).with(i)
+ end
+
+ model.legacy_bulk_insert('test', rows, disable_quote: [:a, :c])
+ end
+
+ it 'handles non-UTF-8 data' do
+ expect { model.legacy_bulk_insert('test', [{ a: "\255" }]) }.not_to raise_error
+ end
+
+ context 'when using PostgreSQL' do
+ it 'allows the returning of the IDs of the inserted rows' do
+ result = double(:result, values: [['10']])
+
+ expect(dummy_connection)
+ .to receive(:execute)
+ .with(/RETURNING id/)
+ .and_return(result)
+
+ ids = model
+ .legacy_bulk_insert('test', [{ number: 10 }], return_ids: true)
+
+ expect(ids).to eq([10])
+ end
+
+ it 'allows setting the upsert to do nothing' do
+ expect(dummy_connection)
+ .to receive(:execute)
+ .with(/ON CONFLICT DO NOTHING/)
+
+ model
+ .legacy_bulk_insert('test', [{ number: 10 }], on_conflict: :do_nothing)
+ end
+ end
+ end
+end
+# rubocop: enable Gitlab/BulkInsert
diff --git a/spec/models/concerns/loaded_in_group_list_spec.rb b/spec/models/concerns/loaded_in_group_list_spec.rb
index c37943022ba..d38e842c666 100644
--- a/spec/models/concerns/loaded_in_group_list_spec.rb
+++ b/spec/models/concerns/loaded_in_group_list_spec.rb
@@ -3,49 +3,67 @@
require 'spec_helper'
RSpec.describe LoadedInGroupList do
- let(:parent) { create(:group) }
+ let_it_be(:parent) { create(:group) }
+ let_it_be(:group) { create(:group, parent: parent) }
+ let_it_be(:project) { create(:project, namespace: parent) }
- subject(:found_group) { Group.with_selects_for_list.find_by(id: parent.id) }
+ let(:archived_parameter) { nil }
- describe '.with_selects_for_list' do
- it 'includes the preloaded counts for groups' do
- create(:group, parent: parent)
- create(:project, namespace: parent)
- parent.add_developer(create(:user))
+ before do
+ parent.add_developer(create(:user))
+ end
- found_group = Group.with_selects_for_list.find_by(id: parent.id)
+ subject(:found_group) { Group.with_selects_for_list(archived: archived_parameter).find_by(id: parent.id) }
+ describe '.with_selects_for_list' do
+ it 'includes the preloaded counts for groups' do
expect(found_group.preloaded_project_count).to eq(1)
expect(found_group.preloaded_subgroup_count).to eq(1)
expect(found_group.preloaded_member_count).to eq(1)
end
+ context 'with project namespaces' do
+ let_it_be(:group1) { create(:group, parent: parent) }
+ let_it_be(:group2) { create(:group, parent: parent) }
+ let_it_be(:project_namespace) { project.project_namespace }
+
+ it 'does not include project_namespaces in the count of subgroups' do
+ expect(found_group.preloaded_subgroup_count).to eq(3)
+ expect(parent.subgroup_count).to eq(3)
+ end
+ end
+
context 'with archived projects' do
- it 'counts including archived projects when `true` is passed' do
- create(:project, namespace: parent, archived: true)
- create(:project, namespace: parent)
+ let_it_be(:archived_project) { create(:project, namespace: parent, archived: true) }
- found_group = Group.with_selects_for_list(archived: 'true').find_by(id: parent.id)
+ let(:archived_parameter) { true }
+ it 'counts including archived projects when `true` is passed' do
expect(found_group.preloaded_project_count).to eq(2)
end
- it 'counts only archived projects when `only` is passed' do
- create_list(:project, 2, namespace: parent, archived: true)
- create(:project, namespace: parent)
+ context 'when not counting archived projects' do
+ let(:archived_parameter) { false }
+
+ it 'counts projects without archived ones' do
+ expect(found_group.preloaded_project_count).to eq(1)
+ end
+ end
+
+ context 'with archived only' do
+ let_it_be(:archived_project2) { create(:project, namespace: parent, archived: true) }
- found_group = Group.with_selects_for_list(archived: 'only').find_by(id: parent.id)
+ let(:archived_parameter) { 'only' }
- expect(found_group.preloaded_project_count).to eq(2)
+ it 'counts only archived projects when `only` is passed' do
+ expect(found_group.preloaded_project_count).to eq(2)
+ end
end
end
end
describe '#children_count' do
it 'counts groups and projects' do
- create(:group, parent: parent)
- create(:project, namespace: parent)
-
expect(found_group.children_count).to eq(2)
end
end
diff --git a/spec/models/concerns/loose_foreign_key_spec.rb b/spec/models/concerns/loose_foreign_key_spec.rb
index ce5e33261a9..42da69eb75e 100644
--- a/spec/models/concerns/loose_foreign_key_spec.rb
+++ b/spec/models/concerns/loose_foreign_key_spec.rb
@@ -9,8 +9,8 @@ RSpec.describe LooseForeignKey do
self.table_name = 'projects'
- loose_foreign_key :issues, :project_id, on_delete: :async_delete, gitlab_schema: :gitlab_main
- loose_foreign_key 'merge_requests', 'project_id', 'on_delete' => 'async_nullify', 'gitlab_schema' => :gitlab_main
+ loose_foreign_key :issues, :project_id, on_delete: :async_delete
+ loose_foreign_key 'merge_requests', 'project_id', 'on_delete' => 'async_nullify'
end
end
@@ -28,7 +28,6 @@ RSpec.describe LooseForeignKey do
expect(definition.to_table).to eq('merge_requests')
expect(definition.column).to eq('project_id')
expect(definition.on_delete).to eq(:async_nullify)
- expect(definition.options[:gitlab_schema]).to eq(:gitlab_main)
end
context 'validation' do
@@ -39,9 +38,9 @@ RSpec.describe LooseForeignKey do
self.table_name = 'projects'
- loose_foreign_key :issues, :project_id, on_delete: :async_delete, gitlab_schema: :gitlab_main
- loose_foreign_key :merge_requests, :project_id, on_delete: :async_nullify, gitlab_schema: :gitlab_main
- loose_foreign_key :merge_requests, :project_id, on_delete: :destroy, gitlab_schema: :gitlab_main
+ loose_foreign_key :issues, :project_id, on_delete: :async_delete
+ loose_foreign_key :merge_requests, :project_id, on_delete: :async_nullify
+ loose_foreign_key :merge_requests, :project_id, on_delete: :destroy
end
end
@@ -50,28 +49,12 @@ RSpec.describe LooseForeignKey do
end
end
- context 'gitlab_schema validation' do
- let(:invalid_class) do
- Class.new(ApplicationRecord) do
- include LooseForeignKey
-
- self.table_name = 'projects'
-
- loose_foreign_key :merge_requests, :project_id, on_delete: :async_nullify, gitlab_schema: :unknown
- end
- end
-
- it 'raises error when invalid `gitlab_schema` option was given' do
- expect { invalid_class }.to raise_error /Invalid gitlab_schema option given: unknown/
- end
- end
-
context 'inheritance validation' do
let(:inherited_project_class) do
Class.new(Project) do
include LooseForeignKey
- loose_foreign_key :issues, :project_id, on_delete: :async_delete, gitlab_schema: :gitlab_main
+ loose_foreign_key :issues, :project_id, on_delete: :async_delete
end
end
diff --git a/spec/models/concerns/noteable_spec.rb b/spec/models/concerns/noteable_spec.rb
index 38766d8decd..81ae30b7116 100644
--- a/spec/models/concerns/noteable_spec.rb
+++ b/spec/models/concerns/noteable_spec.rb
@@ -77,6 +77,70 @@ RSpec.describe Noteable do
end
end
+ describe '#discussion_root_note_ids' do
+ let!(:label_event) { create(:resource_label_event, merge_request: subject) }
+ let!(:system_note) { create(:system_note, project: project, noteable: subject) }
+ let!(:milestone_event) { create(:resource_milestone_event, merge_request: subject) }
+ let!(:state_event) { create(:resource_state_event, merge_request: subject) }
+
+ it 'returns ordered discussion_ids and synthetic note ids' do
+ discussions = subject.discussion_root_note_ids(notes_filter: UserPreference::NOTES_FILTERS[:all_notes]).map do |n|
+ { table_name: n.table_name, discussion_id: n.discussion_id, id: n.id }
+ end
+
+ expect(discussions).to match([
+ a_hash_including(table_name: 'notes', discussion_id: active_diff_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: active_diff_note3.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: outdated_diff_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: discussion_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_diff_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_note2.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_discussion_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_discussion_note3.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: note2.discussion_id),
+ a_hash_including(table_name: 'resource_label_events', id: label_event.id),
+ a_hash_including(table_name: 'notes', discussion_id: system_note.discussion_id),
+ a_hash_including(table_name: 'resource_milestone_events', id: milestone_event.id),
+ a_hash_including(table_name: 'resource_state_events', id: state_event.id)
+ ])
+ end
+
+ it 'filters by comments only' do
+ discussions = subject.discussion_root_note_ids(notes_filter: UserPreference::NOTES_FILTERS[:only_comments]).map do |n|
+ { table_name: n.table_name, discussion_id: n.discussion_id, id: n.id }
+ end
+
+ expect(discussions).to match([
+ a_hash_including(table_name: 'notes', discussion_id: active_diff_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: active_diff_note3.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: outdated_diff_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: discussion_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_diff_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_note2.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_discussion_note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: commit_discussion_note3.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: note1.discussion_id),
+ a_hash_including(table_name: 'notes', discussion_id: note2.discussion_id)
+ ])
+ end
+
+ it 'filters by system notes only' do
+ discussions = subject.discussion_root_note_ids(notes_filter: UserPreference::NOTES_FILTERS[:only_activity]).map do |n|
+ { table_name: n.table_name, discussion_id: n.discussion_id, id: n.id }
+ end
+
+ expect(discussions).to match([
+ a_hash_including(table_name: 'resource_label_events', id: label_event.id),
+ a_hash_including(table_name: 'notes', discussion_id: system_note.discussion_id),
+ a_hash_including(table_name: 'resource_milestone_events', id: milestone_event.id),
+ a_hash_including(table_name: 'resource_state_events', id: state_event.id)
+ ])
+ end
+ end
+
describe '#grouped_diff_discussions' do
let(:grouped_diff_discussions) { subject.grouped_diff_discussions }
diff --git a/spec/models/concerns/prometheus_adapter_spec.rb b/spec/models/concerns/prometheus_adapter_spec.rb
index 01c987a1d92..4158e8a0a4c 100644
--- a/spec/models/concerns/prometheus_adapter_spec.rb
+++ b/spec/models/concerns/prometheus_adapter_spec.rb
@@ -165,6 +165,14 @@ RSpec.describe PrometheusAdapter, :use_clean_rails_memory_store_caching do
it { is_expected.to eq(success: false, result: %(#{status} - "QUERY FAILED!")) }
end
end
+
+ context "when client raises Gitlab::PrometheusClient::ConnectionError" do
+ before do
+ stub_any_prometheus_request.to_raise(Gitlab::PrometheusClient::ConnectionError)
+ end
+
+ it { is_expected.to include(success: false, result: kind_of(String)) }
+ end
end
describe '#build_query_args' do
diff --git a/spec/models/concerns/reactive_caching_spec.rb b/spec/models/concerns/reactive_caching_spec.rb
index 7e031bdd263..4f3b95e43cd 100644
--- a/spec/models/concerns/reactive_caching_spec.rb
+++ b/spec/models/concerns/reactive_caching_spec.rb
@@ -375,7 +375,7 @@ RSpec.describe ReactiveCaching, :use_clean_rails_memory_store_caching do
end
describe 'classes including this concern' do
- it 'sets reactive_cache_work_type' do
+ it 'sets reactive_cache_work_type', :eager_load do
classes = ObjectSpace.each_object(Class).select do |klass|
klass < described_class && klass.name
end
diff --git a/spec/models/concerns/sha256_attribute_spec.rb b/spec/models/concerns/sha256_attribute_spec.rb
index c247865d77f..02947325bf4 100644
--- a/spec/models/concerns/sha256_attribute_spec.rb
+++ b/spec/models/concerns/sha256_attribute_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Sha256Attribute do
- let(:model) { Class.new { include Sha256Attribute } }
+ let(:model) { Class.new(ApplicationRecord) { include Sha256Attribute } }
before do
columns = [
diff --git a/spec/models/concerns/sha_attribute_spec.rb b/spec/models/concerns/sha_attribute_spec.rb
index 3846dd9c231..220eadfab92 100644
--- a/spec/models/concerns/sha_attribute_spec.rb
+++ b/spec/models/concerns/sha_attribute_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe ShaAttribute do
- let(:model) { Class.new { include ShaAttribute } }
+ let(:model) { Class.new(ApplicationRecord) { include ShaAttribute } }
before do
columns = [
diff --git a/spec/models/concerns/where_composite_spec.rb b/spec/models/concerns/where_composite_spec.rb
index 5e67f2f5b65..6abdd12aac5 100644
--- a/spec/models/concerns/where_composite_spec.rb
+++ b/spec/models/concerns/where_composite_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe WhereComposite do
describe '.where_composite' do
- let_it_be(:test_table_name) { "test_table_#{SecureRandom.hex(10)}" }
+ let_it_be(:test_table_name) { "_test_table_#{SecureRandom.hex(10)}" }
let(:model) do
tbl_name = test_table_name
diff --git a/spec/models/concerns/x509_serial_number_attribute_spec.rb b/spec/models/concerns/x509_serial_number_attribute_spec.rb
index 88550823748..723e2ad07b6 100644
--- a/spec/models/concerns/x509_serial_number_attribute_spec.rb
+++ b/spec/models/concerns/x509_serial_number_attribute_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe X509SerialNumberAttribute do
- let(:model) { Class.new { include X509SerialNumberAttribute } }
+ let(:model) { Class.new(ApplicationRecord) { include X509SerialNumberAttribute } }
before do
columns = [
diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb
index 4a8b671bab7..01252a58681 100644
--- a/spec/models/custom_emoji_spec.rb
+++ b/spec/models/custom_emoji_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe CustomEmoji do
end
describe 'exclusion of duplicated emoji' do
- let(:emoji_name) { Gitlab::Emoji.emojis_names.sample }
+ let(:emoji_name) { TanukiEmoji.index.all.sample.name }
let(:group) { create(:group, :private) }
it 'disallows emoji names of built-in emoji' do
diff --git a/spec/models/customer_relations/contact_spec.rb b/spec/models/customer_relations/contact_spec.rb
index 298d5db3ab9..3a2d4e2d0ca 100644
--- a/spec/models/customer_relations/contact_spec.rb
+++ b/spec/models/customer_relations/contact_spec.rb
@@ -6,7 +6,8 @@ RSpec.describe CustomerRelations::Contact, type: :model do
describe 'associations' do
it { is_expected.to belong_to(:group) }
it { is_expected.to belong_to(:organization).optional }
- it { is_expected.to have_and_belong_to_many(:issues) }
+ it { is_expected.to have_many(:issue_contacts) }
+ it { is_expected.to have_many(:issues) }
end
describe 'validations' do
diff --git a/spec/models/customer_relations/issue_contact_spec.rb b/spec/models/customer_relations/issue_contact_spec.rb
new file mode 100644
index 00000000000..3747d159833
--- /dev/null
+++ b/spec/models/customer_relations/issue_contact_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe CustomerRelations::IssueContact do
+ let_it_be(:issue_contact, reload: true) { create(:issue_customer_relations_contact) }
+
+ subject { issue_contact }
+
+ it { expect(subject).to be_valid }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:issue).required }
+ it { is_expected.to belong_to(:contact).required }
+ end
+
+ describe 'factory' do
+ let(:built) { build(:issue_customer_relations_contact) }
+ let(:stubbed) { build_stubbed(:issue_customer_relations_contact) }
+ let(:created) { create(:issue_customer_relations_contact) }
+
+ let(:group) { build(:group) }
+ let(:project) { build(:project, group: group) }
+ let(:issue) { build(:issue, project: project) }
+ let(:contact) { build(:contact, group: group) }
+ let(:for_issue) { build(:issue_customer_relations_contact, :for_issue, issue: issue) }
+ let(:for_contact) { build(:issue_customer_relations_contact, :for_contact, contact: contact) }
+
+ it 'uses objects from the same group', :aggregate_failures do
+ expect(stubbed.contact.group).to eq(stubbed.issue.project.group)
+ expect(built.contact.group).to eq(built.issue.project.group)
+ expect(created.contact.group).to eq(created.issue.project.group)
+ end
+
+ it 'builds using the same group', :aggregate_failures do
+ expect(for_issue.contact.group).to eq(group)
+ expect(for_contact.issue.project.group).to eq(group)
+ end
+ end
+
+ describe 'validation' do
+ let(:built) { build(:issue_customer_relations_contact, issue: create(:issue), contact: create(:contact)) }
+
+ it 'fails when the contact group does not match the issue group' do
+ expect(built).not_to be_valid
+ end
+ end
+end
diff --git a/spec/models/data_list_spec.rb b/spec/models/data_list_spec.rb
new file mode 100644
index 00000000000..d2f15386808
--- /dev/null
+++ b/spec/models/data_list_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DataList do
+ describe '#to_array' do
+ let(:jira_integration) { create(:jira_integration) }
+ let(:zentao_integration) { create(:zentao_integration) }
+ let(:cases) do
+ [
+ [jira_integration, 'Integrations::JiraTrackerData', 'service_id'],
+ [zentao_integration, 'Integrations::ZentaoTrackerData', 'integration_id']
+ ]
+ end
+
+ def data_list(integration)
+ DataList.new([integration], integration.to_data_fields_hash, integration.data_fields.class).to_array
+ end
+
+ it 'returns current data' do
+ cases.each do |integration, data_fields_class_name, foreign_key|
+ data_fields_klass, columns, values_items = data_list(integration)
+
+ expect(data_fields_klass.to_s).to eq data_fields_class_name
+ expect(columns.last).to eq foreign_key
+ values = values_items.first
+ expect(values.last).to eq integration.id
+ end
+ end
+ end
+end
diff --git a/spec/models/dependency_proxy/manifest_spec.rb b/spec/models/dependency_proxy/manifest_spec.rb
index e7f0889345a..59415096989 100644
--- a/spec/models/dependency_proxy/manifest_spec.rb
+++ b/spec/models/dependency_proxy/manifest_spec.rb
@@ -15,6 +15,17 @@ RSpec.describe DependencyProxy::Manifest, type: :model do
it { is_expected.to validate_presence_of(:digest) }
end
+ describe 'scopes' do
+ let_it_be(:manifest_one) { create(:dependency_proxy_manifest) }
+ let_it_be(:manifest_two) { create(:dependency_proxy_manifest) }
+ let_it_be(:manifests) { [manifest_one, manifest_two] }
+ let_it_be(:ids) { manifests.map(&:id) }
+
+ it 'order_id_desc' do
+ expect(described_class.where(id: ids).order_id_desc.to_a).to eq [manifest_two, manifest_one]
+ end
+ end
+
describe 'file is being stored' do
subject { create(:dependency_proxy_manifest) }
@@ -31,18 +42,14 @@ RSpec.describe DependencyProxy::Manifest, type: :model do
end
end
- describe '.find_or_initialize_by_file_name_or_digest' do
+ describe '.find_by_file_name_or_digest' do
let_it_be(:file_name) { 'foo' }
let_it_be(:digest) { 'bar' }
- subject { DependencyProxy::Manifest.find_or_initialize_by_file_name_or_digest(file_name: file_name, digest: digest) }
+ subject { DependencyProxy::Manifest.find_by_file_name_or_digest(file_name: file_name, digest: digest) }
context 'no manifest exists' do
- it 'initializes a manifest' do
- expect(DependencyProxy::Manifest).to receive(:new).with(file_name: file_name, digest: digest)
-
- subject
- end
+ it { is_expected.to be_nil }
end
context 'manifest exists and matches file_name' do
diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb
index fa78527e366..c22bad0e062 100644
--- a/spec/models/deploy_key_spec.rb
+++ b/spec/models/deploy_key_spec.rb
@@ -5,6 +5,17 @@ require 'spec_helper'
RSpec.describe DeployKey, :mailer do
describe "Associations" do
it { is_expected.to have_many(:deploy_keys_projects) }
+ it do
+ is_expected.to have_many(:deploy_keys_projects_with_write_access)
+ .conditions(can_push: true)
+ .class_name('DeployKeysProject')
+ end
+ it do
+ is_expected.to have_many(:projects_with_write_access)
+ .class_name('Project')
+ .through(:deploy_keys_projects_with_write_access)
+ .source(:project)
+ end
it { is_expected.to have_many(:projects) }
it { is_expected.to have_many(:protected_branch_push_access_levels) }
end
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index f9a05fbb06f..51e1e63da8d 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -385,6 +385,43 @@ RSpec.describe Deployment do
end
end
+ describe '.archivables_in' do
+ subject { described_class.archivables_in(project, limit: limit) }
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:deployment_1) { create(:deployment, project: project) }
+ let_it_be(:deployment_2) { create(:deployment, project: project) }
+ let_it_be(:deployment_3) { create(:deployment, project: project) }
+
+ let(:limit) { 100 }
+
+ context 'when there are no archivable deployments in the project' do
+ it 'returns nothing' do
+ expect(subject).to be_empty
+ end
+ end
+
+ context 'when there are archivable deployments in the project' do
+ before do
+ stub_const("::Deployment::ARCHIVABLE_OFFSET", 1)
+ end
+
+ it 'returns all archivable deployments' do
+ expect(subject.count).to eq(2)
+ expect(subject).to contain_exactly(deployment_1, deployment_2)
+ end
+
+ context 'with limit' do
+ let(:limit) { 1 }
+
+ it 'takes the limit into account' do
+ expect(subject.count).to eq(1)
+ expect(subject.take).to be_in([deployment_1, deployment_2])
+ end
+ end
+ end
+ end
+
describe 'scopes' do
describe 'last_for_environment' do
let(:production) { create(:environment) }
@@ -456,6 +493,17 @@ RSpec.describe Deployment do
end
end
+ describe '.ordered' do
+ let!(:deployment1) { create(:deployment, status: :running) }
+ let!(:deployment2) { create(:deployment, status: :success, finished_at: Time.current) }
+ let!(:deployment3) { create(:deployment, status: :canceled, finished_at: 1.day.ago) }
+ let!(:deployment4) { create(:deployment, status: :success, finished_at: 2.days.ago) }
+
+ it 'sorts by finished at' do
+ expect(described_class.ordered).to eq([deployment1, deployment2, deployment3, deployment4])
+ end
+ end
+
describe 'visible' do
subject { described_class.visible }
@@ -763,6 +811,7 @@ RSpec.describe Deployment do
it 'schedules workers when finishing a deploy' do
expect(Deployments::UpdateEnvironmentWorker).to receive(:perform_async)
expect(Deployments::LinkMergeRequestWorker).to receive(:perform_async)
+ expect(Deployments::ArchiveInProjectWorker).to receive(:perform_async)
expect(Deployments::HooksWorker).to receive(:perform_async)
expect(deploy.update_status('success')).to eq(true)
@@ -840,6 +889,12 @@ RSpec.describe Deployment do
context 'with created deployment' do
let(:deployment_status) { :created }
+ context 'with created build' do
+ let(:build_status) { :created }
+
+ it_behaves_like 'ignoring build'
+ end
+
context 'with running build' do
let(:build_status) { :running }
@@ -862,12 +917,16 @@ RSpec.describe Deployment do
context 'with running deployment' do
let(:deployment_status) { :running }
+ context 'with created build' do
+ let(:build_status) { :created }
+
+ it_behaves_like 'ignoring build'
+ end
+
context 'with running build' do
let(:build_status) { :running }
- it_behaves_like 'gracefully handling error' do
- let(:error_message) { %Q{Status cannot transition via \"run\"} }
- end
+ it_behaves_like 'ignoring build'
end
context 'with finished build' do
@@ -886,6 +945,12 @@ RSpec.describe Deployment do
context 'with finished deployment' do
let(:deployment_status) { :success }
+ context 'with created build' do
+ let(:build_status) { :created }
+
+ it_behaves_like 'ignoring build'
+ end
+
context 'with running build' do
let(:build_status) { :running }
@@ -897,9 +962,13 @@ RSpec.describe Deployment do
context 'with finished build' do
let(:build_status) { :success }
- it_behaves_like 'gracefully handling error' do
- let(:error_message) { %Q{Status cannot transition via \"succeed\"} }
- end
+ it_behaves_like 'ignoring build'
+ end
+
+ context 'with failed build' do
+ let(:build_status) { :failed }
+
+ it_behaves_like 'synchronizing deployment'
end
context 'with unrelated build' do
diff --git a/spec/models/design_management/version_spec.rb b/spec/models/design_management/version_spec.rb
index e004ad024bc..303bac61e1e 100644
--- a/spec/models/design_management/version_spec.rb
+++ b/spec/models/design_management/version_spec.rb
@@ -283,7 +283,7 @@ RSpec.describe DesignManagement::Version do
it 'retrieves author from the Commit if author_id is nil and version has been persisted' do
author = create(:user)
version = create(:design_version, :committed, author: author)
- author.destroy
+ author.destroy!
version.reload
commit = version.issue.project.design_repository.commit(version.sha)
commit_user = create(:user, email: commit.author_email, name: commit.author_name)
diff --git a/spec/models/email_spec.rb b/spec/models/email_spec.rb
index 2b09ee5c190..59299a507e4 100644
--- a/spec/models/email_spec.rb
+++ b/spec/models/email_spec.rb
@@ -13,6 +13,15 @@ RSpec.describe Email do
it_behaves_like 'an object with RFC3696 compliant email-formatted attributes', :email do
subject { build(:email) }
end
+
+ context 'when the email conflicts with the primary email of a different user' do
+ let(:user) { create(:user) }
+ let(:email) { build(:email, email: user.email) }
+
+ it 'is invalid' do
+ expect(email).to be_invalid
+ end
+ end
end
it 'normalize email value' do
@@ -33,7 +42,7 @@ RSpec.describe Email do
end
describe 'scopes' do
- let(:user) { create(:user) }
+ let(:user) { create(:user, :unconfirmed) }
it 'scopes confirmed emails' do
create(:email, :confirmed, user: user)
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 08c639957d3..9d9862aa3d3 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
it 'ensures environment tier when a new object is created' do
environment = build(:environment, name: 'gprd', tier: nil)
- expect { environment.save }.to change { environment.tier }.from(nil).to('production')
+ expect { environment.save! }.to change { environment.tier }.from(nil).to('production')
end
it 'ensures environment tier when an existing object is updated' do
@@ -418,7 +418,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
context 'not in the same branch' do
before do
- deployment.update(sha: project.commit('feature').id)
+ deployment.update!(sha: project.commit('feature').id)
end
it 'returns false' do
@@ -496,7 +496,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
context 'when no other actions' do
context 'environment is available' do
before do
- environment.update(state: :available)
+ environment.update!(state: :available)
end
it do
@@ -508,7 +508,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
context 'environment is already stopped' do
before do
- environment.update(state: :stopped)
+ environment.update!(state: :stopped)
end
it do
@@ -1502,7 +1502,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
deployment = create(:deployment, :success, environment: environment, project: project)
deployment.create_ref
- expect { environment.destroy }.to change { project.commit(deployment.ref_path) }.to(nil)
+ expect { environment.destroy! }.to change { project.commit(deployment.ref_path) }.to(nil)
end
end
@@ -1517,7 +1517,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
it 'returns the environments count grouped by state with zero value' do
- environment2.update(state: 'stopped')
+ environment2.update!(state: 'stopped')
expect(project.environments.count_by_state).to eq({ stopped: 3, available: 0 })
end
end
@@ -1710,4 +1710,36 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
subject
end
end
+
+ describe '#should_link_to_merge_requests?' do
+ subject { environment.should_link_to_merge_requests? }
+
+ context 'when environment is foldered' do
+ context 'when environment is production tier' do
+ let(:environment) { create(:environment, project: project, name: 'production/aws') }
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when environment is development tier' do
+ let(:environment) { create(:environment, project: project, name: 'review/feature') }
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ context 'when environment is unfoldered' do
+ context 'when environment is production tier' do
+ let(:environment) { create(:environment, project: project, name: 'production') }
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when environment is development tier' do
+ let(:environment) { create(:environment, project: project, name: 'development') }
+
+ it { is_expected.to eq(true) }
+ end
+ end
+ end
end
diff --git a/spec/models/error_tracking/error_event_spec.rb b/spec/models/error_tracking/error_event_spec.rb
index 8e20eb25353..9cf5a405e74 100644
--- a/spec/models/error_tracking/error_event_spec.rb
+++ b/spec/models/error_tracking/error_event_spec.rb
@@ -11,7 +11,10 @@ RSpec.describe ErrorTracking::ErrorEvent, type: :model do
describe 'validations' do
it { is_expected.to validate_presence_of(:description) }
+ it { is_expected.to validate_length_of(:description).is_at_most(1024) }
it { is_expected.to validate_presence_of(:occurred_at) }
+ it { is_expected.to validate_length_of(:level).is_at_most(255) }
+ it { is_expected.to validate_length_of(:environment).is_at_most(255) }
end
describe '#stacktrace' do
@@ -37,6 +40,23 @@ RSpec.describe ErrorTracking::ErrorEvent, type: :model do
expect(event.stacktrace).to be_kind_of(Array)
expect(event.stacktrace.first).to eq(expected_entry)
end
+
+ context 'error context is missing' do
+ let(:event) { create(:error_tracking_error_event, :browser) }
+
+ it 'generates a stacktrace without context' do
+ expected_entry = {
+ 'lineNo' => 6395,
+ 'context' => [],
+ 'filename' => 'webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js',
+ 'function' => 'hydrate',
+ 'colNo' => 0
+ }
+
+ expect(event.stacktrace).to be_kind_of(Array)
+ expect(event.stacktrace.first).to eq(expected_entry)
+ end
+ end
end
describe '#to_sentry_error_event' do
diff --git a/spec/models/error_tracking/error_spec.rb b/spec/models/error_tracking/error_spec.rb
index 9b8a81c6372..363cd197f3e 100644
--- a/spec/models/error_tracking/error_spec.rb
+++ b/spec/models/error_tracking/error_spec.rb
@@ -12,8 +12,12 @@ RSpec.describe ErrorTracking::Error, type: :model do
describe 'validations' do
it { is_expected.to validate_presence_of(:name) }
+ it { is_expected.to validate_length_of(:name).is_at_most(255) }
it { is_expected.to validate_presence_of(:description) }
+ it { is_expected.to validate_length_of(:description).is_at_most(1024) }
it { is_expected.to validate_presence_of(:actor) }
+ it { is_expected.to validate_length_of(:actor).is_at_most(255) }
+ it { is_expected.to validate_length_of(:platform).is_at_most(255) }
end
describe '.report_error' do
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 41510b7aa1c..ee27eaf1d0b 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe Event do
describe 'after_create :set_last_repository_updated_at' do
context 'with a push event' do
it 'updates the project last_repository_updated_at' do
- project.update(last_repository_updated_at: 1.year.ago)
+ project.update!(last_repository_updated_at: 1.year.ago)
create_push_event(project, project.owner)
@@ -44,7 +44,7 @@ RSpec.describe Event do
context 'without a push event' do
it 'does not update the project last_repository_updated_at' do
- project.update(last_repository_updated_at: 1.year.ago)
+ project.update!(last_repository_updated_at: 1.year.ago)
create(:closed_issue_event, project: project, author: project.owner)
@@ -58,7 +58,7 @@ RSpec.describe Event do
describe '#set_last_repository_updated_at' do
it 'only updates once every Event::REPOSITORY_UPDATED_AT_INTERVAL minutes' do
last_known_timestamp = (Event::REPOSITORY_UPDATED_AT_INTERVAL - 1.minute).ago
- project.update(last_repository_updated_at: last_known_timestamp)
+ project.update!(last_repository_updated_at: last_known_timestamp)
project.reload # a reload removes fractions of seconds
expect do
@@ -73,7 +73,7 @@ RSpec.describe Event do
it 'passes event to UserInteractedProject.track' do
expect(UserInteractedProject).to receive(:track).with(event)
- event.save
+ event.save!
end
end
end
@@ -824,7 +824,7 @@ RSpec.describe Event do
context 'when a project was updated less than 1 hour ago' do
it 'does not update the project' do
- project.update(last_activity_at: Time.current)
+ project.update!(last_activity_at: Time.current)
expect(project).not_to receive(:update_column)
.with(:last_activity_at, a_kind_of(Time))
@@ -835,7 +835,7 @@ RSpec.describe Event do
context 'when a project was updated more than 1 hour ago' do
it 'updates the project' do
- project.update(last_activity_at: 1.year.ago)
+ project.update!(last_activity_at: 1.year.ago)
create_push_event(project, project.owner)
diff --git a/spec/models/fork_network_spec.rb b/spec/models/fork_network_spec.rb
index c2ef1fdcb5f..f2ec0ccb4fd 100644
--- a/spec/models/fork_network_spec.rb
+++ b/spec/models/fork_network_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe ForkNetwork do
describe '#add_root_as_member' do
it 'adds the root project as a member when creating a new root network' do
project = create(:project)
- fork_network = described_class.create(root_project: project)
+ fork_network = described_class.create!(root_project: project)
expect(fork_network.projects).to include(project)
end
@@ -54,8 +54,8 @@ RSpec.describe ForkNetwork do
first_fork = fork_project(first_project)
second_fork = fork_project(second_project)
- first_project.destroy
- second_project.destroy
+ first_project.destroy!
+ second_project.destroy!
expect(first_fork.fork_network).not_to be_nil
expect(first_fork.fork_network.root_project).to be_nil
diff --git a/spec/models/generic_commit_status_spec.rb b/spec/models/generic_commit_status_spec.rb
index 6fe5a1407a9..9d70019734b 100644
--- a/spec/models/generic_commit_status_spec.rb
+++ b/spec/models/generic_commit_status_spec.rb
@@ -133,7 +133,7 @@ RSpec.describe GenericCommitStatus do
before do
generic_commit_status.context = nil
generic_commit_status.stage = nil
- generic_commit_status.save
+ generic_commit_status.save!
end
describe '#context' do
diff --git a/spec/models/grafana_integration_spec.rb b/spec/models/grafana_integration_spec.rb
index 79f102919ac..bb822187e0c 100644
--- a/spec/models/grafana_integration_spec.rb
+++ b/spec/models/grafana_integration_spec.rb
@@ -60,7 +60,7 @@ RSpec.describe GrafanaIntegration do
context 'with grafana integration enabled' do
it 'returns nil' do
- grafana_integration.update(enabled: false)
+ grafana_integration.update!(enabled: false)
expect(grafana_integration.client).to be(nil)
end
@@ -81,8 +81,8 @@ RSpec.describe GrafanaIntegration do
end
it 'prevents overriding token value with its encrypted or masked version', :aggregate_failures do
- expect { grafana_integration.update(token: grafana_integration.encrypted_token) }.not_to change { grafana_integration.reload.send(:token) }
- expect { grafana_integration.update(token: grafana_integration.masked_token) }.not_to change { grafana_integration.reload.send(:token) }
+ expect { grafana_integration.update!(token: grafana_integration.encrypted_token) }.not_to change { grafana_integration.reload.send(:token) }
+ expect { grafana_integration.update!(token: grafana_integration.masked_token) }.not_to change { grafana_integration.reload.send(:token) }
end
end
end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index e88abc21ef2..735aa4df2ba 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -37,6 +37,8 @@ RSpec.describe Group do
it { is_expected.to have_many(:daily_build_group_report_results).class_name('Ci::DailyBuildGroupReportResult') }
it { is_expected.to have_many(:group_callouts).class_name('Users::GroupCallout').with_foreign_key(:group_id) }
it { is_expected.to have_many(:bulk_import_exports).class_name('BulkImports::Export') }
+ it { is_expected.to have_many(:contacts).class_name('CustomerRelations::Contact') }
+ it { is_expected.to have_many(:organizations).class_name('CustomerRelations::Organization') }
describe '#members & #requesters' do
let(:requester) { create(:user) }
@@ -160,7 +162,7 @@ RSpec.describe Group do
context 'when sub group is deleted' do
it 'does not delete parent notification settings' do
expect do
- sub_group.destroy
+ sub_group.destroy!
end.to change { NotificationSetting.count }.by(-1)
end
end
@@ -404,7 +406,7 @@ RSpec.describe Group do
subject do
recorded_queries.record do
- group.update(parent: new_parent)
+ group.update!(parent: new_parent)
end
end
@@ -496,7 +498,7 @@ RSpec.describe Group do
let!(:group) { create(:group, parent: parent_group) }
before do
- parent_group.update(parent: new_grandparent)
+ parent_group.update!(parent: new_grandparent)
end
it 'updates traversal_ids for all descendants' do
@@ -563,6 +565,15 @@ RSpec.describe Group do
it { expect(group.ancestors.to_sql).not_to include 'traversal_ids <@' }
end
end
+
+ context 'when project namespace exists in the group' do
+ let!(:project) { create(:project, group: group) }
+ let!(:project_namespace) { project.project_namespace }
+
+ it 'filters out project namespace' do
+ expect(group.descendants.find_by_id(project_namespace.id)).to be_nil
+ end
+ end
end
end
@@ -571,8 +582,8 @@ RSpec.describe Group do
let(:instance_integration) { build(:jira_integration, :instance) }
before do
- create(:jira_integration, group: group, project: nil)
- create(:integrations_slack, group: another_group, project: nil)
+ create(:jira_integration, :group, group: group)
+ create(:integrations_slack, :group, group: another_group)
end
it 'returns groups without integration' do
@@ -718,6 +729,22 @@ RSpec.describe Group do
expect(group.group_members.developers.map(&:user)).to include(user)
expect(group.group_members.guests.map(&:user)).not_to include(user)
end
+
+ context 'when `tasks_to_be_done` and `tasks_project_id` are passed' do
+ let!(:project) { create(:project, group: group) }
+
+ before do
+ stub_experiments(invite_members_for_task: true)
+ group.add_users([create(:user)], :developer, tasks_to_be_done: %w(ci code), tasks_project_id: project.id)
+ end
+
+ it 'creates a member_task with the correct attributes', :aggregate_failures do
+ member = group.group_members.last
+
+ expect(member.tasks_to_be_done).to match_array([:ci, :code])
+ expect(member.member_task.project).to eq(project)
+ end
+ end
end
describe '#avatar_type' do
@@ -831,7 +858,7 @@ RSpec.describe Group do
before do
parent_group = create(:group)
create(:group_member, :owner, group: parent_group)
- group.update(parent: parent_group)
+ group.update!(parent: parent_group)
end
it { expect(group.last_owner?(@members[:owner])).to be_falsy }
@@ -888,7 +915,7 @@ RSpec.describe Group do
before do
parent_group = create(:group)
create(:group_member, :owner, group: parent_group)
- group.update(parent: parent_group)
+ group.update!(parent: parent_group)
end
it { expect(group.member_last_blocked_owner?(member)).to be(false) }
@@ -1936,7 +1963,7 @@ RSpec.describe Group do
let(:environment) { 'foo%bar/test' }
it 'matches literally for %' do
- ci_variable.update(environment_scope: 'foo%bar/*')
+ ci_variable.update_attribute(:environment_scope, 'foo%bar/*')
is_expected.to contain_exactly(ci_variable)
end
@@ -2077,7 +2104,7 @@ RSpec.describe Group do
let(:ancestor_group) { create(:group) }
before do
- group.update(parent: ancestor_group)
+ group.update!(parent: ancestor_group)
end
it 'returns all ancestor group ids' do
@@ -2594,7 +2621,7 @@ RSpec.describe Group do
let_it_be(:project) { create(:project, group: group, service_desk_enabled: false) }
before do
- project.update(service_desk_enabled: false)
+ project.update!(service_desk_enabled: false)
end
it { is_expected.to eq(false) }
@@ -2623,14 +2650,6 @@ RSpec.describe Group do
end
it_behaves_like 'returns namespaces with disabled email'
-
- context 'when feature flag :linear_group_ancestor_scopes is disabled' do
- before do
- stub_feature_flags(linear_group_ancestor_scopes: false)
- end
-
- it_behaves_like 'returns namespaces with disabled email'
- end
end
describe '.timelogs' do
diff --git a/spec/models/hooks/project_hook_spec.rb b/spec/models/hooks/project_hook_spec.rb
index d811f67d16b..f0ee9a613d8 100644
--- a/spec/models/hooks/project_hook_spec.rb
+++ b/spec/models/hooks/project_hook_spec.rb
@@ -32,8 +32,8 @@ RSpec.describe ProjectHook do
end
describe '#rate_limit' do
- let_it_be(:hook) { create(:project_hook) }
let_it_be(:plan_limits) { create(:plan_limits, :default_plan, web_hook_calls: 100) }
+ let_it_be(:hook) { create(:project_hook) }
it 'returns the default limit' do
expect(hook.rate_limit).to be(100)
diff --git a/spec/models/identity_spec.rb b/spec/models/identity_spec.rb
index c0efb2dff56..124c54a2028 100644
--- a/spec/models/identity_spec.rb
+++ b/spec/models/identity_spec.rb
@@ -118,19 +118,19 @@ RSpec.describe Identity do
it 'if extern_uid changes' do
expect(ldap_identity).not_to receive(:ensure_normalized_extern_uid)
- ldap_identity.save
+ ldap_identity.save!
end
it 'if current_uid is nil' do
expect(ldap_identity).to receive(:ensure_normalized_extern_uid)
- ldap_identity.update(extern_uid: nil)
+ ldap_identity.update!(extern_uid: nil)
expect(ldap_identity.extern_uid).to be_nil
end
it 'if extern_uid changed and not nil' do
- ldap_identity.update(extern_uid: 'uid=john1,ou=PEOPLE,dc=example,dc=com')
+ ldap_identity.update!(extern_uid: 'uid=john1,ou=PEOPLE,dc=example,dc=com')
expect(ldap_identity.extern_uid).to eq 'uid=john1,ou=people,dc=example,dc=com'
end
@@ -150,7 +150,7 @@ RSpec.describe Identity do
expect(user.user_synced_attributes_metadata.provider).to eq 'ldapmain'
- ldap_identity.destroy
+ ldap_identity.destroy!
expect(user.reload.user_synced_attributes_metadata).to be_nil
end
@@ -162,7 +162,7 @@ RSpec.describe Identity do
expect(user.user_synced_attributes_metadata.provider).to eq 'other'
- ldap_identity.destroy
+ ldap_identity.destroy!
expect(user.reload.user_synced_attributes_metadata.provider).to eq 'other'
end
diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb
index 1a83d948fcf..de47fb3839a 100644
--- a/spec/models/integration_spec.rb
+++ b/spec/models/integration_spec.rb
@@ -299,7 +299,7 @@ RSpec.describe Integration do
end
context 'when integration is a group-level integration' do
- let(:group_integration) { create(:jira_integration, group: group, project: nil) }
+ let(:group_integration) { create(:jira_integration, :group, group: group) }
it 'sets inherit_from_id from integration' do
integration = described_class.build_from_integration(group_integration, project_id: project.id)
@@ -458,7 +458,7 @@ RSpec.describe Integration do
end
context 'with an active group-level integration' do
- let!(:group_integration) { create(:prometheus_integration, group: group, project: nil, api_url: 'https://prometheus.group.com/') }
+ let!(:group_integration) { create(:prometheus_integration, :group, group: group, api_url: 'https://prometheus.group.com/') }
it 'creates an integration from the group-level integration' do
described_class.create_from_active_default_integrations(project, :project_id)
@@ -481,7 +481,7 @@ RSpec.describe Integration do
end
context 'with an active subgroup' do
- let!(:subgroup_integration) { create(:prometheus_integration, group: subgroup, project: nil, api_url: 'https://prometheus.subgroup.com/') }
+ let!(:subgroup_integration) { create(:prometheus_integration, :group, group: subgroup, api_url: 'https://prometheus.subgroup.com/') }
let!(:subgroup) { create(:group, parent: group) }
let(:project) { create(:project, group: subgroup) }
@@ -509,7 +509,7 @@ RSpec.describe Integration do
end
context 'having an integration inheriting settings' do
- let!(:subgroup_integration) { create(:prometheus_integration, group: subgroup, project: nil, inherit_from_id: group_integration.id, api_url: 'https://prometheus.subgroup.com/') }
+ let!(:subgroup_integration) { create(:prometheus_integration, :group, group: subgroup, inherit_from_id: group_integration.id, api_url: 'https://prometheus.subgroup.com/') }
it 'creates an integration from the group-level integration' do
described_class.create_from_active_default_integrations(sub_subgroup, :group_id)
@@ -552,11 +552,11 @@ RSpec.describe Integration do
let_it_be(:subgroup2) { create(:group, parent: group) }
let_it_be(:project1) { create(:project, group: subgroup1) }
let_it_be(:project2) { create(:project, group: subgroup2) }
- let_it_be(:group_integration) { create(:prometheus_integration, group: group, project: nil) }
- let_it_be(:subgroup_integration1) { create(:prometheus_integration, group: subgroup1, project: nil, inherit_from_id: group_integration.id) }
- let_it_be(:subgroup_integration2) { create(:prometheus_integration, group: subgroup2, project: nil) }
- let_it_be(:project_integration1) { create(:prometheus_integration, group: nil, project: project1, inherit_from_id: group_integration.id) }
- let_it_be(:project_integration2) { create(:prometheus_integration, group: nil, project: project2, inherit_from_id: subgroup_integration2.id) }
+ let_it_be(:group_integration) { create(:prometheus_integration, :group, group: group) }
+ let_it_be(:subgroup_integration1) { create(:prometheus_integration, :group, group: subgroup1, inherit_from_id: group_integration.id) }
+ let_it_be(:subgroup_integration2) { create(:prometheus_integration, :group, group: subgroup2) }
+ let_it_be(:project_integration1) { create(:prometheus_integration, project: project1, inherit_from_id: group_integration.id) }
+ let_it_be(:project_integration2) { create(:prometheus_integration, project: project2, inherit_from_id: subgroup_integration2.id) }
it 'returns the groups and projects inheriting from integration ancestors', :aggregate_failures do
expect(described_class.inherited_descendants_from_self_or_ancestors_from(group_integration)).to eq([subgroup_integration1, project_integration1])
diff --git a/spec/models/integrations/jira_spec.rb b/spec/models/integrations/jira_spec.rb
index 0321b151633..1d81668f97d 100644
--- a/spec/models/integrations/jira_spec.rb
+++ b/spec/models/integrations/jira_spec.rb
@@ -495,6 +495,18 @@ RSpec.describe Integrations::Jira do
end
end
+ describe '#client' do
+ it 'uses the default GitLab::HTTP timeouts' do
+ timeouts = Gitlab::HTTP::DEFAULT_TIMEOUT_OPTIONS
+ stub_request(:get, 'http://jira.example.com/foo')
+
+ expect(Gitlab::HTTP).to receive(:httparty_perform_request)
+ .with(Net::HTTP::Get, '/foo', hash_including(timeouts)).and_call_original
+
+ jira_integration.client.get('/foo')
+ end
+ end
+
describe '#find_issue' do
let(:issue_key) { 'JIRA-123' }
let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}" }
@@ -503,7 +515,7 @@ RSpec.describe Integrations::Jira do
stub_request(:get, issue_url).with(basic_auth: [username, password])
end
- it 'call the Jira API to get the issue' do
+ it 'calls the Jira API to get the issue' do
jira_integration.find_issue(issue_key)
expect(WebMock).to have_requested(:get, issue_url)
@@ -845,10 +857,14 @@ RSpec.describe Integrations::Jira do
let_it_be(:user) { build_stubbed(:user) }
let(:jira_issue) { ExternalIssue.new('JIRA-123', project) }
+ let(:success_message) { 'SUCCESS: Successfully posted to http://jira.example.com.' }
+ let(:favicon_path) { "http://localhost/assets/#{find_asset('favicon.png').digest_path}" }
subject { jira_integration.create_cross_reference_note(jira_issue, resource, user) }
- shared_examples 'creates a comment on Jira' do
+ shared_examples 'handles cross-references' do
+ let(:resource_name) { jira_integration.send(:noteable_name, resource) }
+ let(:resource_url) { jira_integration.send(:build_entity_url, resource_name, resource.to_param) }
let(:issue_url) { "#{url}/rest/api/2/issue/JIRA-123" }
let(:comment_url) { "#{issue_url}/comment" }
let(:remote_link_url) { "#{issue_url}/remotelink" }
@@ -860,12 +876,77 @@ RSpec.describe Integrations::Jira do
stub_request(:post, remote_link_url).with(basic_auth: [username, password])
end
- it 'creates a comment on Jira' do
- subject
+ context 'when enabled' do
+ before do
+ allow(jira_integration).to receive(:can_cross_reference?) { true }
+ end
- expect(WebMock).to have_requested(:post, comment_url).with(
- body: /mentioned this issue in/
- ).once
+ it 'creates a comment and remote link' do
+ expect(subject).to eq(success_message)
+ expect(WebMock).to have_requested(:post, comment_url).with(body: comment_body).once
+ expect(WebMock).to have_requested(:post, remote_link_url).with(
+ body: hash_including(
+ GlobalID: 'GitLab',
+ relationship: 'mentioned on',
+ object: {
+ url: resource_url,
+ title: "#{resource.model_name.human} - #{resource.title}",
+ icon: { title: 'GitLab', url16x16: favicon_path },
+ status: { resolved: false }
+ }
+ )
+ ).once
+ end
+
+ context 'when comment already exists' do
+ before do
+ allow(jira_integration).to receive(:comment_exists?) { true }
+ end
+
+ it 'does not create a comment or remote link' do
+ expect(subject).to be_nil
+ expect(WebMock).not_to have_requested(:post, comment_url)
+ expect(WebMock).not_to have_requested(:post, remote_link_url)
+ end
+ end
+
+ context 'when remote link already exists' do
+ let(:link) { double(object: { 'url' => resource_url }) }
+
+ before do
+ allow(jira_integration).to receive(:find_remote_link).and_return(link)
+ end
+
+ it 'updates the remote link but does not create a comment' do
+ expect(link).to receive(:save!)
+ expect(subject).to eq(success_message)
+ expect(WebMock).not_to have_requested(:post, comment_url)
+ end
+ end
+ end
+
+ context 'when disabled' do
+ before do
+ allow(jira_integration).to receive(:can_cross_reference?) { false }
+ end
+
+ it 'does not create a comment or remote link' do
+ expect(subject).to eq("Events for #{resource_name.pluralize.humanize(capitalize: false)} are disabled.")
+ expect(WebMock).not_to have_requested(:post, comment_url)
+ expect(WebMock).not_to have_requested(:post, remote_link_url)
+ end
+ end
+
+ context 'with jira_use_first_ref_by_oid feature flag disabled' do
+ before do
+ stub_feature_flags(jira_use_first_ref_by_oid: false)
+ end
+
+ it 'creates a comment and remote link on Jira' do
+ expect(subject).to eq(success_message)
+ expect(WebMock).to have_requested(:post, comment_url).with(body: comment_body).once
+ expect(WebMock).to have_requested(:post, remote_link_url).once
+ end
end
it 'tracks usage' do
@@ -877,39 +958,38 @@ RSpec.describe Integrations::Jira do
end
end
- context 'when resource is a commit' do
- let(:resource) { project.commit('master') }
-
- context 'when disabled' do
- before do
- allow_next_instance_of(described_class) do |instance|
- allow(instance).to receive(:commit_events) { false }
- end
- end
-
- it { is_expected.to eq('Events for commits are disabled.') }
+ context 'for commits' do
+ it_behaves_like 'handles cross-references' do
+ let(:resource) { project.commit('master') }
+ let(:comment_body) { /mentioned this issue in \[a commit\|.* on branch \[master\|/ }
end
+ end
- context 'when enabled' do
- it_behaves_like 'creates a comment on Jira'
+ context 'for issues' do
+ it_behaves_like 'handles cross-references' do
+ let(:resource) { build_stubbed(:issue, project: project) }
+ let(:comment_body) { /mentioned this issue in \[a issue\|/ }
end
end
- context 'when resource is a merge request' do
- let(:resource) { build_stubbed(:merge_request, source_project: project) }
-
- context 'when disabled' do
- before do
- allow_next_instance_of(described_class) do |instance|
- allow(instance).to receive(:merge_requests_events) { false }
- end
- end
+ context 'for merge requests' do
+ it_behaves_like 'handles cross-references' do
+ let(:resource) { build_stubbed(:merge_request, source_project: project) }
+ let(:comment_body) { /mentioned this issue in \[a merge request\|.* on branch \[master\|/ }
+ end
+ end
- it { is_expected.to eq('Events for merge requests are disabled.') }
+ context 'for notes' do
+ it_behaves_like 'handles cross-references' do
+ let(:resource) { build_stubbed(:note, project: project) }
+ let(:comment_body) { /mentioned this issue in \[a note\|/ }
end
+ end
- context 'when enabled' do
- it_behaves_like 'creates a comment on Jira'
+ context 'for snippets' do
+ it_behaves_like 'handles cross-references' do
+ let(:resource) { build_stubbed(:snippet, project: project) }
+ let(:comment_body) { /mentioned this issue in \[a snippet\|/ }
end
end
end
@@ -946,7 +1026,9 @@ RSpec.describe Integrations::Jira do
expect(jira_integration).to receive(:log_error).with(
'Error sending message',
client_url: 'http://jira.example.com',
- error: error_message
+ 'exception.class' => anything,
+ 'exception.message' => error_message,
+ 'exception.backtrace' => anything
)
expect(jira_integration.test(nil)).to eq(success: false, result: error_message)
diff --git a/spec/models/integrations/pipelines_email_spec.rb b/spec/models/integrations/pipelines_email_spec.rb
index afd9d71ebc4..d70f104b965 100644
--- a/spec/models/integrations/pipelines_email_spec.rb
+++ b/spec/models/integrations/pipelines_email_spec.rb
@@ -35,6 +35,42 @@ RSpec.describe Integrations::PipelinesEmail, :mailer do
it { is_expected.not_to validate_presence_of(:recipients) }
end
+
+ describe 'validates number of recipients' do
+ before do
+ stub_const("#{described_class}::RECIPIENTS_LIMIT", 2)
+ end
+
+ subject(:integration) { described_class.new(project: project, recipients: recipients, active: true) }
+
+ context 'valid number of recipients' do
+ let(:recipients) { 'foo@bar.com, , ' }
+
+ it 'does not count empty emails' do
+ is_expected.to be_valid
+ end
+ end
+
+ context 'invalid number of recipients' do
+ let(:recipients) { 'foo@bar.com bar@foo.com bob@gitlab.com' }
+
+ it { is_expected.not_to be_valid }
+
+ it 'adds an error message' do
+ integration.valid?
+
+ expect(integration.errors).to contain_exactly('Recipients can\'t exceed 2')
+ end
+
+ context 'when integration is not active' do
+ before do
+ integration.active = false
+ end
+
+ it { is_expected.to be_valid }
+ end
+ end
+ end
end
shared_examples 'sending email' do |branches_to_be_notified: nil|
@@ -50,7 +86,7 @@ RSpec.describe Integrations::PipelinesEmail, :mailer do
it 'sends email' do
emails = receivers.map { |r| double(notification_email_or_default: r) }
- should_only_email(*emails, kind: :bcc)
+ should_only_email(*emails)
end
end
diff --git a/spec/models/integrations/shimo_spec.rb b/spec/models/integrations/shimo_spec.rb
new file mode 100644
index 00000000000..25df8d2b249
--- /dev/null
+++ b/spec/models/integrations/shimo_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Integrations::Shimo do
+ describe '#fields' do
+ let(:shimo_integration) { create(:shimo_integration) }
+
+ it 'returns custom fields' do
+ expect(shimo_integration.fields.pluck(:name)).to eq(%w[external_wiki_url])
+ end
+ end
+
+ describe '#create' do
+ let(:project) { create(:project, :repository) }
+ let(:external_wiki_url) { 'https://shimo.example.com/desktop' }
+ let(:params) { { active: true, project: project, external_wiki_url: external_wiki_url } }
+
+ context 'with valid params' do
+ it 'creates the Shimo integration' do
+ shimo = described_class.create!(params)
+
+ expect(shimo.valid?).to be true
+ expect(shimo.render?).to be true
+ expect(shimo.external_wiki_url).to eq(external_wiki_url)
+ end
+ end
+
+ context 'with invalid params' do
+ it 'cannot create the Shimo integration without external_wiki_url' do
+ params['external_wiki_url'] = nil
+ expect { described_class.create!(params) }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+
+ it 'cannot create the Shimo integration with invalid external_wiki_url' do
+ params['external_wiki_url'] = 'Fake Invalid URL'
+ expect { described_class.create!(params) }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+ end
+end
diff --git a/spec/models/integrations/zentao_spec.rb b/spec/models/integrations/zentao_spec.rb
index a1503ecc092..2b0532c7930 100644
--- a/spec/models/integrations/zentao_spec.rb
+++ b/spec/models/integrations/zentao_spec.rb
@@ -50,4 +50,10 @@ RSpec.describe Integrations::Zentao do
expect(zentao_integration.test).to eq(test_response)
end
end
+
+ describe '#help' do
+ it 'renders prompt information' do
+ expect(zentao_integration.help).not_to be_empty
+ end
+ end
end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 4319407706e..ba4429451d1 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -34,7 +34,8 @@ RSpec.describe Issue do
it { is_expected.to have_many(:issue_email_participants) }
it { is_expected.to have_many(:timelogs).autosave(true) }
it { is_expected.to have_one(:incident_management_issuable_escalation_status) }
- it { is_expected.to have_and_belong_to_many(:customer_relations_contacts) }
+ it { is_expected.to have_many(:issue_customer_relations_contacts) }
+ it { is_expected.to have_many(:customer_relations_contacts) }
describe 'versions.most_recent' do
it 'returns the most recent version' do
@@ -305,7 +306,7 @@ RSpec.describe Issue do
end
describe '#reopen' do
- let(:issue) { create(:issue, project: reusable_project, state: 'closed', closed_at: Time.current, closed_by: user) }
+ let_it_be_with_reload(:issue) { create(:issue, project: reusable_project, state: 'closed', closed_at: Time.current, closed_by: user) }
it 'sets closed_at to nil when an issue is reopened' do
expect { issue.reopen }.to change { issue.closed_at }.to(nil)
@@ -315,6 +316,22 @@ RSpec.describe Issue do
expect { issue.reopen }.to change { issue.closed_by }.from(user).to(nil)
end
+ it 'clears moved_to_id for moved issues' do
+ moved_issue = create(:issue)
+
+ issue.update!(moved_to_id: moved_issue.id)
+
+ expect { issue.reopen }.to change { issue.moved_to_id }.from(moved_issue.id).to(nil)
+ end
+
+ it 'clears duplicated_to_id for duplicated issues' do
+ duplicate_issue = create(:issue)
+
+ issue.update!(duplicated_to_id: duplicate_issue.id)
+
+ expect { issue.reopen }.to change { issue.duplicated_to_id }.from(duplicate_issue.id).to(nil)
+ end
+
it 'changes the state to opened' do
expect { issue.reopen }.to change { issue.state_id }.from(described_class.available_states[:closed]).to(described_class.available_states[:opened])
end
@@ -1218,7 +1235,7 @@ RSpec.describe Issue do
end
it 'returns public and hidden issues' do
- expect(described_class.public_only).to eq([public_issue, hidden_issue])
+ expect(described_class.public_only).to contain_exactly(public_issue, hidden_issue)
end
end
end
@@ -1247,7 +1264,7 @@ RSpec.describe Issue do
end
it 'returns public and hidden issues' do
- expect(described_class.without_hidden).to eq([public_issue, hidden_issue])
+ expect(described_class.without_hidden).to contain_exactly(public_issue, hidden_issue)
end
end
end
diff --git a/spec/models/jira_import_state_spec.rb b/spec/models/jira_import_state_spec.rb
index e982b7353ba..a272d001429 100644
--- a/spec/models/jira_import_state_spec.rb
+++ b/spec/models/jira_import_state_spec.rb
@@ -175,7 +175,7 @@ RSpec.describe JiraImportState do
let(:jira_import) { build(:jira_import_state, project: project)}
it 'does not run the callback', :aggregate_failures do
- expect { jira_import.save }.to change { JiraImportState.count }.by(1)
+ expect { jira_import.save! }.to change { JiraImportState.count }.by(1)
expect(jira_import.reload.error_message).to be_nil
end
end
@@ -184,7 +184,7 @@ RSpec.describe JiraImportState do
let(:jira_import) { build(:jira_import_state, project: project, error_message: 'error')}
it 'does not run the callback', :aggregate_failures do
- expect { jira_import.save }.to change { JiraImportState.count }.by(1)
+ expect { jira_import.save! }.to change { JiraImportState.count }.by(1)
expect(jira_import.reload.error_message).to eq('error')
end
end
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 7468c1b9f0a..d41a1604211 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -85,9 +85,9 @@ RSpec.describe Key, :mailer do
let_it_be(:expiring_soon_notified) { create(:key, expires_at: 4.days.from_now, user: user, before_expiry_notification_delivered_at: Time.current) }
let_it_be(:future_expiry) { create(:key, expires_at: 1.month.from_now, user: user) }
- describe '.expired_and_not_notified' do
+ describe '.expired_today_and_not_notified' do
it 'returns keys that expire today and in the past' do
- expect(described_class.expired_and_not_notified).to contain_exactly(expired_today_not_notified, expired_yesterday)
+ expect(described_class.expired_today_and_not_notified).to contain_exactly(expired_today_not_notified)
end
end
diff --git a/spec/models/loose_foreign_keys/deleted_record_spec.rb b/spec/models/loose_foreign_keys/deleted_record_spec.rb
new file mode 100644
index 00000000000..cd5068bdb52
--- /dev/null
+++ b/spec/models/loose_foreign_keys/deleted_record_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe LooseForeignKeys::DeletedRecord, type: :model do
+ let_it_be(:table) { 'public.projects' }
+
+ let_it_be(:deleted_record_1) { described_class.create!(partition: 1, fully_qualified_table_name: table, primary_key_value: 5) }
+ let_it_be(:deleted_record_2) { described_class.create!(partition: 1, fully_qualified_table_name: table, primary_key_value: 1) }
+ let_it_be(:deleted_record_3) { described_class.create!(partition: 1, fully_qualified_table_name: 'public.other_table', primary_key_value: 3) }
+ let_it_be(:deleted_record_4) { described_class.create!(partition: 1, fully_qualified_table_name: table, primary_key_value: 1) } # duplicate
+
+ describe '.load_batch_for_table' do
+ it 'loads records and orders them by creation date' do
+ records = described_class.load_batch_for_table(table, 10)
+
+ expect(records).to eq([deleted_record_1, deleted_record_2, deleted_record_4])
+ end
+
+ it 'supports configurable batch size' do
+ records = described_class.load_batch_for_table(table, 2)
+
+ expect(records).to eq([deleted_record_1, deleted_record_2])
+ end
+ end
+
+ describe '.mark_records_processed' do
+ it 'updates all records' do
+ described_class.mark_records_processed([deleted_record_1, deleted_record_2, deleted_record_4])
+
+ expect(described_class.status_pending.count).to eq(1)
+ expect(described_class.status_processed.count).to eq(3)
+ end
+ end
+end
diff --git a/spec/models/loose_foreign_keys/modification_tracker_spec.rb b/spec/models/loose_foreign_keys/modification_tracker_spec.rb
new file mode 100644
index 00000000000..069ccf85141
--- /dev/null
+++ b/spec/models/loose_foreign_keys/modification_tracker_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe LooseForeignKeys::ModificationTracker do
+ subject(:tracker) { described_class.new }
+
+ describe '#over_limit?' do
+ it 'is true when deletion MAX_DELETES is exceeded' do
+ stub_const('LooseForeignKeys::ModificationTracker::MAX_DELETES', 5)
+
+ tracker.add_deletions('issues', 10)
+ expect(tracker).to be_over_limit
+ end
+
+ it 'is false when MAX_DELETES is not exceeded' do
+ tracker.add_deletions('issues', 3)
+
+ expect(tracker).not_to be_over_limit
+ end
+
+ it 'is true when deletion MAX_UPDATES is exceeded' do
+ stub_const('LooseForeignKeys::ModificationTracker::MAX_UPDATES', 5)
+
+ tracker.add_updates('issues', 3)
+ tracker.add_updates('issues', 4)
+
+ expect(tracker).to be_over_limit
+ end
+
+ it 'is false when MAX_UPDATES is not exceeded' do
+ tracker.add_updates('projects', 3)
+
+ expect(tracker).not_to be_over_limit
+ end
+
+ it 'is true when max runtime is exceeded' do
+ monotonic_time_before = 1 # this will be the start time
+ monotonic_time_after = described_class::MAX_RUNTIME.to_i + 1 # this will be returned when over_limit? is called
+
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(monotonic_time_before, monotonic_time_after)
+
+ tracker
+
+ expect(tracker).to be_over_limit
+ end
+
+ it 'is false when max runtime is not exceeded' do
+ expect(tracker).not_to be_over_limit
+ end
+ end
+
+ describe '#add_deletions' do
+ it 'increments a Prometheus counter' do
+ counter = Gitlab::Metrics.registry.get(:loose_foreign_key_deletions)
+
+ subject.add_deletions(:users, 4)
+
+ expect(counter.get(table: :users)).to eq(4)
+ end
+ end
+
+ describe '#add_updates' do
+ it 'increments a Prometheus counter' do
+ counter = Gitlab::Metrics.registry.get(:loose_foreign_key_updates)
+
+ subject.add_updates(:users, 4)
+
+ expect(counter.get(table: :users)).to eq(4)
+ end
+ end
+
+ describe '#stats' do
+ it 'exposes stats' do
+ freeze_time do
+ tracker
+ tracker.add_deletions('issues', 5)
+ tracker.add_deletions('issues', 2)
+ tracker.add_deletions('projects', 2)
+
+ tracker.add_updates('projects', 3)
+
+ expect(tracker.stats).to eq({
+ over_limit: false,
+ delete_count_by_table: { 'issues' => 7, 'projects' => 2 },
+ update_count_by_table: { 'projects' => 3 },
+ delete_count: 9,
+ update_count: 3
+ })
+ end
+ end
+ end
+end
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index afe78adc547..abff1815f1a 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe Member do
describe 'Associations' do
it { is_expected.to belong_to(:user) }
+ it { is_expected.to have_one(:member_task) }
end
describe 'Validation' do
@@ -678,6 +679,19 @@ RSpec.describe Member do
expect(member.invite_token).not_to be_nil
expect_any_instance_of(Member).not_to receive(:after_accept_invite)
end
+
+ it 'schedules a TasksToBeDone::CreateWorker task' do
+ stub_experiments(invite_members_for_task: true)
+
+ member_task = create(:member_task, member: member, project: member.project)
+
+ expect(TasksToBeDone::CreateWorker)
+ .to receive(:perform_async)
+ .with(member_task.id, member.created_by_id, [user.id])
+ .once
+
+ member.accept_invite!(user)
+ end
end
describe '#decline_invite!' do
diff --git a/spec/models/members/member_task_spec.rb b/spec/models/members/member_task_spec.rb
new file mode 100644
index 00000000000..b06aa05c255
--- /dev/null
+++ b/spec/models/members/member_task_spec.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MemberTask do
+ describe 'Associations' do
+ it { is_expected.to belong_to(:member) }
+ it { is_expected.to belong_to(:project) }
+ end
+
+ describe 'Validations' do
+ it { is_expected.to validate_presence_of(:member) }
+ it { is_expected.to validate_presence_of(:project) }
+ it { is_expected.to validate_inclusion_of(:tasks).in_array(MemberTask::TASKS.values) }
+
+ describe 'unique tasks validation' do
+ subject do
+ build(:member_task, tasks: [0, 0])
+ end
+
+ it 'expects the task values to be unique' do
+ expect(subject).to be_invalid
+ expect(subject.errors[:tasks]).to include('are not unique')
+ end
+ end
+
+ describe 'project validations' do
+ let_it_be(:project) { create(:project) }
+
+ subject do
+ build(:member_task, member: member, project: project, tasks_to_be_done: [:ci, :code])
+ end
+
+ context 'when the member source is a group' do
+ let_it_be(:member) { create(:group_member) }
+
+ it "expects the project to be part of the member's group projects" do
+ expect(subject).to be_invalid
+ expect(subject.errors[:project]).to include('is not in the member group')
+ end
+
+ context "when the project is part of the member's group projects" do
+ let_it_be(:project) { create(:project, namespace: member.source) }
+
+ it { is_expected.to be_valid }
+ end
+ end
+
+ context 'when the member source is a project' do
+ let_it_be(:member) { create(:project_member) }
+
+ it "expects the project to be the member's project" do
+ expect(subject).to be_invalid
+ expect(subject.errors[:project]).to include('is not the member project')
+ end
+
+ context "when the project is the member's project" do
+ let_it_be(:project) { member.source }
+
+ it { is_expected.to be_valid }
+ end
+ end
+ end
+ end
+
+ describe '.for_members' do
+ it 'returns the member_tasks for multiple members' do
+ member1 = create(:group_member)
+ member_task1 = create(:member_task, member: member1)
+ create(:member_task)
+ expect(described_class.for_members([member1])).to match_array([member_task1])
+ end
+ end
+
+ describe '#tasks_to_be_done' do
+ subject { member_task.tasks_to_be_done }
+
+ let_it_be(:member_task) { build(:member_task) }
+
+ before do
+ member_task[:tasks] = [0, 1]
+ end
+
+ it 'returns an array of symbols for the corresponding integers' do
+ expect(subject).to match_array([:ci, :code])
+ end
+ end
+
+ describe '#tasks_to_be_done=' do
+ let_it_be(:member_task) { build(:member_task) }
+
+ context 'when passing valid values' do
+ subject { member_task[:tasks] }
+
+ before do
+ member_task.tasks_to_be_done = tasks
+ end
+
+ context 'when passing tasks as strings' do
+ let_it_be(:tasks) { %w(ci code) }
+
+ it 'sets an array of integers for the corresponding tasks' do
+ expect(subject).to match_array([0, 1])
+ end
+ end
+
+ context 'when passing a single task' do
+ let_it_be(:tasks) { :ci }
+
+ it 'sets an array of integers for the corresponding tasks' do
+ expect(subject).to match_array([1])
+ end
+ end
+
+ context 'when passing a task twice' do
+ let_it_be(:tasks) { %w(ci ci) }
+
+ it 'is set only once' do
+ expect(subject).to match_array([1])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb
index ca846cf9e8e..031caefbd43 100644
--- a/spec/models/members/project_member_spec.rb
+++ b/spec/models/members/project_member_spec.rb
@@ -256,59 +256,5 @@ RSpec.describe ProjectMember do
it_behaves_like 'calls AuthorizedProjectUpdate::UserRefreshFromReplicaWorker with a delay to update project authorizations'
end
-
- context 'when the feature flag `specialized_service_for_project_member_auth_refresh` is disabled' do
- before do
- stub_feature_flags(specialized_service_for_project_member_auth_refresh: false)
- end
-
- shared_examples_for 'calls UserProjectAccessChangedService to recalculate authorizations' do
- it 'calls UserProjectAccessChangedService' do
- expect_next_instance_of(UserProjectAccessChangedService, user.id) do |service|
- expect(service).to receive(:execute)
- end
-
- action
- end
- end
-
- context 'on create' do
- let(:action) { project.add_user(user, Gitlab::Access::GUEST) }
-
- it 'changes access level' do
- expect { action }.to change { user.can?(:guest_access, project) }.from(false).to(true)
- end
-
- it_behaves_like 'calls UserProjectAccessChangedService to recalculate authorizations'
- end
-
- context 'on update' do
- let(:action) { project.members.find_by(user: user).update!(access_level: Gitlab::Access::DEVELOPER) }
-
- before do
- project.add_user(user, Gitlab::Access::GUEST)
- end
-
- it 'changes access level' do
- expect { action }.to change { user.can?(:developer_access, project) }.from(false).to(true)
- end
-
- it_behaves_like 'calls UserProjectAccessChangedService to recalculate authorizations'
- end
-
- context 'on destroy' do
- let(:action) { project.members.find_by(user: user).destroy! }
-
- before do
- project.add_user(user, Gitlab::Access::GUEST)
- end
-
- it 'changes access level', :sidekiq_inline do
- expect { action }.to change { user.can?(:guest_access, project) }.from(true).to(false)
- end
-
- it_behaves_like 'calls UserProjectAccessChangedService to recalculate authorizations'
- end
- end
end
end
diff --git a/spec/models/merge_request_assignee_spec.rb b/spec/models/merge_request_assignee_spec.rb
index d287392bf7f..5bb8e7184a3 100644
--- a/spec/models/merge_request_assignee_spec.rb
+++ b/spec/models/merge_request_assignee_spec.rb
@@ -37,4 +37,8 @@ RSpec.describe MergeRequestAssignee do
end
end
end
+
+ it_behaves_like 'having unique enum values'
+
+ it_behaves_like 'having reviewer state'
end
diff --git a/spec/models/merge_request_diff_commit_spec.rb b/spec/models/merge_request_diff_commit_spec.rb
index adddec7ced8..25e5e40feb7 100644
--- a/spec/models/merge_request_diff_commit_spec.rb
+++ b/spec/models/merge_request_diff_commit_spec.rb
@@ -46,11 +46,7 @@ RSpec.describe MergeRequestDiffCommit do
{
"message": "Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n",
"authored_date": "2014-02-27T10:01:38.000+01:00".to_time,
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T10:01:38.000+01:00".to_time,
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author_id": an_instance_of(Integer),
"committer_id": an_instance_of(Integer),
"merge_request_diff_id": merge_request_diff_id,
@@ -61,11 +57,7 @@ RSpec.describe MergeRequestDiffCommit do
{
"message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n",
"authored_date": "2014-02-27T09:57:31.000+01:00".to_time,
- "author_name": "Dmitriy Zaporozhets",
- "author_email": "dmitriy.zaporozhets@gmail.com",
"committed_date": "2014-02-27T09:57:31.000+01:00".to_time,
- "committer_name": "Dmitriy Zaporozhets",
- "committer_email": "dmitriy.zaporozhets@gmail.com",
"commit_author_id": an_instance_of(Integer),
"committer_id": an_instance_of(Integer),
"merge_request_diff_id": merge_request_diff_id,
@@ -79,7 +71,7 @@ RSpec.describe MergeRequestDiffCommit do
subject { described_class.create_bulk(merge_request_diff_id, commits) }
it 'inserts the commits into the database en masse' do
- expect(Gitlab::Database.main).to receive(:bulk_insert)
+ expect(ApplicationRecord).to receive(:legacy_bulk_insert)
.with(described_class.table_name, rows)
subject
@@ -111,11 +103,7 @@ RSpec.describe MergeRequestDiffCommit do
[{
"message": "Weird commit date\n",
"authored_date": timestamp,
- "author_name": "Alejandro Rodríguez",
- "author_email": "alejorro70@gmail.com",
"committed_date": timestamp,
- "committer_name": "Alejandro Rodríguez",
- "committer_email": "alejorro70@gmail.com",
"commit_author_id": an_instance_of(Integer),
"committer_id": an_instance_of(Integer),
"merge_request_diff_id": merge_request_diff_id,
@@ -126,7 +114,7 @@ RSpec.describe MergeRequestDiffCommit do
end
it 'uses a sanitized date' do
- expect(Gitlab::Database.main).to receive(:bulk_insert)
+ expect(ApplicationRecord).to receive(:legacy_bulk_insert)
.with(described_class.table_name, rows)
subject
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index 5fff880c44e..afe7251f59a 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -240,8 +240,8 @@ RSpec.describe MergeRequestDiff do
stub_external_diffs_setting(enabled: true)
expect(diff).not_to receive(:save!)
- expect(Gitlab::Database.main)
- .to receive(:bulk_insert)
+ expect(ApplicationRecord)
+ .to receive(:legacy_bulk_insert)
.with('merge_request_diff_files', anything)
.and_raise(ActiveRecord::Rollback)
@@ -1080,6 +1080,22 @@ RSpec.describe MergeRequestDiff do
end
end
+ describe '#commits' do
+ include ProjectForksHelper
+
+ let_it_be(:target) { create(:project, :test_repo) }
+ let_it_be(:forked) { fork_project(target, nil, repository: true) }
+ let_it_be(:mr) { create(:merge_request, source_project: forked, target_project: target) }
+
+ it 'returns a CommitCollection whose container points to the target project' do
+ expect(mr.merge_request_diff.commits.container).to eq(target)
+ end
+
+ it 'returns a non-empty CommitCollection' do
+ expect(mr.merge_request_diff.commits.commits.size).to be > 0
+ end
+ end
+
describe '.latest_diff_for_merge_requests' do
let_it_be(:merge_request_1) { create(:merge_request_without_merge_request_diff) }
let_it_be(:merge_request_1_diff_1) { create(:merge_request_diff, merge_request: merge_request_1, created_at: 3.days.ago) }
diff --git a/spec/models/merge_request_reviewer_spec.rb b/spec/models/merge_request_reviewer_spec.rb
index 76b44abca54..d69d60c94f0 100644
--- a/spec/models/merge_request_reviewer_spec.rb
+++ b/spec/models/merge_request_reviewer_spec.rb
@@ -7,6 +7,10 @@ RSpec.describe MergeRequestReviewer do
subject { merge_request.merge_request_reviewers.build(reviewer: create(:user)) }
+ it_behaves_like 'having unique enum values'
+
+ it_behaves_like 'having reviewer state'
+
describe 'associations' do
it { is_expected.to belong_to(:merge_request).class_name('MergeRequest') }
it { is_expected.to belong_to(:reviewer).class_name('User').inverse_of(:merge_request_reviewers) }
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index d871453e062..5618fb06157 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1638,6 +1638,22 @@ RSpec.describe MergeRequest, factory_default: :keep do
expect(request.default_merge_commit_message)
.not_to match("By removing all code\n\n")
end
+
+ it 'uses template from target project' do
+ request = build(:merge_request, title: 'Fix everything')
+ subject.target_project.merge_commit_template = '%{title}'
+
+ expect(request.default_merge_commit_message)
+ .to eq('Fix everything')
+ end
+
+ it 'ignores template when include_description is true' do
+ request = build(:merge_request, title: 'Fix everything')
+ subject.target_project.merge_commit_template = '%{title}'
+
+ expect(request.default_merge_commit_message(include_description: true))
+ .to match("See merge request #{request.to_reference(full: true)}")
+ end
end
describe "#auto_merge_strategy" do
@@ -2904,6 +2920,8 @@ RSpec.describe MergeRequest, factory_default: :keep do
params = {}
merge_jid = 'hash-123'
+ allow(MergeWorker).to receive(:with_status).and_return(MergeWorker)
+
expect(merge_request).to receive(:expire_etag_cache)
expect(MergeWorker).to receive(:perform_async).with(merge_request.id, user_id, params) do
merge_jid
@@ -2922,6 +2940,10 @@ RSpec.describe MergeRequest, factory_default: :keep do
subject(:execute) { merge_request.rebase_async(user_id) }
+ before do
+ allow(RebaseWorker).to receive(:with_status).and_return(RebaseWorker)
+ end
+
it 'atomically enqueues a RebaseWorker job and updates rebase_jid' do
expect(RebaseWorker)
.to receive(:perform_async)
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index c201d89947e..8f5860c799c 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -28,6 +28,41 @@ RSpec.describe Namespace do
it { is_expected.to have_one :onboarding_progress }
it { is_expected.to have_one :admin_note }
it { is_expected.to have_many :pending_builds }
+
+ describe '#children' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let_it_be(:project_with_namespace) { create(:project, namespace: group) }
+
+ it 'excludes project namespaces' do
+ expect(project_with_namespace.project_namespace.parent).to eq(group)
+ expect(group.children).to match_array([subgroup])
+ end
+ end
+ end
+
+ shared_examples 'validations called by different namespace types' do |method|
+ using RSpec::Parameterized::TableSyntax
+
+ where(:namespace_type, :call_validation) do
+ :namespace | true
+ :group | true
+ :user_namespace | true
+ :project_namespace | false
+ end
+
+ with_them do
+ it 'conditionally runs given validation' do
+ namespace = build(namespace_type)
+ if call_validation
+ expect(namespace).to receive(method)
+ else
+ expect(namespace).not_to receive(method)
+ end
+
+ namespace.valid?
+ end
+ end
end
describe 'validations' do
@@ -50,10 +85,10 @@ RSpec.describe Namespace do
ref(:project_sti_name) | ref(:user_sti_name) | 'project namespace cannot be the parent of another namespace'
ref(:project_sti_name) | ref(:group_sti_name) | 'project namespace cannot be the parent of another namespace'
ref(:project_sti_name) | ref(:project_sti_name) | 'project namespace cannot be the parent of another namespace'
- ref(:group_sti_name) | ref(:user_sti_name) | 'cannot not be used for user namespace'
+ ref(:group_sti_name) | ref(:user_sti_name) | 'cannot be used for user namespace'
ref(:group_sti_name) | ref(:group_sti_name) | nil
ref(:group_sti_name) | ref(:project_sti_name) | nil
- ref(:user_sti_name) | ref(:user_sti_name) | 'cannot not be used for user namespace'
+ ref(:user_sti_name) | ref(:user_sti_name) | 'cannot be used for user namespace'
ref(:user_sti_name) | ref(:group_sti_name) | 'user namespace cannot be the parent of another namespace'
ref(:user_sti_name) | ref(:project_sti_name) | nil
end
@@ -102,14 +137,20 @@ RSpec.describe Namespace do
end
end
- it 'does not allow too deep nesting' do
- ancestors = (1..21).to_a
- group = build(:group)
+ describe '#nesting_level_allowed' do
+ context 'for a group' do
+ it 'does not allow too deep nesting' do
+ ancestors = (1..21).to_a
+ group = build(:group)
+
+ allow(group).to receive(:ancestors).and_return(ancestors)
- allow(group).to receive(:ancestors).and_return(ancestors)
+ expect(group).not_to be_valid
+ expect(group.errors[:parent_id].first).to eq('has too deep level of nesting')
+ end
+ end
- expect(group).not_to be_valid
- expect(group.errors[:parent_id].first).to eq('has too deep level of nesting')
+ it_behaves_like 'validations called by different namespace types', :nesting_level_allowed
end
describe 'reserved path validation' do
@@ -188,7 +229,7 @@ RSpec.describe Namespace do
expect(namespace.path).to eq('j')
- namespace.update(name: 'something new')
+ namespace.update!(name: 'something new')
expect(namespace).to be_valid
expect(namespace.name).to eq('something new')
@@ -199,8 +240,10 @@ RSpec.describe Namespace do
let(:namespace) { build(:project_namespace) }
it 'allows to update path to single char' do
- namespace = create(:project_namespace)
- namespace.update(path: 'j')
+ project = create(:project)
+ namespace = project.project_namespace
+
+ namespace.update!(path: 'j')
expect(namespace).to be_valid
end
@@ -244,7 +287,7 @@ RSpec.describe Namespace do
end
end
- context 'creating a default Namespace' do
+ context 'creating a Namespace with nil type' do
let(:namespace_type) { nil }
it 'is the correct type of namespace' do
@@ -255,7 +298,7 @@ RSpec.describe Namespace do
end
context 'creating an unknown Namespace type' do
- let(:namespace_type) { 'One' }
+ let(:namespace_type) { 'nonsense' }
it 'creates a default Namespace' do
expect(Namespace.find(namespace.id)).to be_a(Namespace)
@@ -273,8 +316,8 @@ RSpec.describe Namespace do
describe '.by_parent' do
it 'includes correct namespaces' do
- expect(described_class.by_parent(namespace1.id)).to eq([namespace1sub])
- expect(described_class.by_parent(namespace2.id)).to eq([namespace2sub])
+ expect(described_class.by_parent(namespace1.id)).to match_array([namespace1sub])
+ expect(described_class.by_parent(namespace2.id)).to match_array([namespace2sub])
expect(described_class.by_parent(nil)).to match_array([namespace, namespace1, namespace2])
end
end
@@ -302,9 +345,13 @@ RSpec.describe Namespace do
describe '.without_project_namespaces' do
let_it_be(:user_namespace) { create(:user_namespace) }
- let_it_be(:project_namespace) { create(:project_namespace) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:project_namespace) { project.project_namespace }
it 'excludes project namespaces' do
+ expect(project_namespace).not_to be_nil
+ expect(project_namespace.parent).not_to be_nil
+ expect(described_class.all).to include(project_namespace)
expect(described_class.without_project_namespaces).to match_array([namespace, namespace1, namespace2, namespace1sub, namespace2sub, user_namespace, project_namespace.parent])
end
end
@@ -519,6 +566,25 @@ RSpec.describe Namespace do
it 'returns namespaces with a matching route path regardless of the casing' do
expect(described_class.search('PARENT-PATH/NEW-PATH', include_parents: true)).to eq([second_group])
end
+
+ context 'with project namespaces' do
+ let_it_be(:project) { create(:project, namespace: parent_group, path: 'some-new-path') }
+ let_it_be(:project_namespace) { project.project_namespace }
+
+ it 'does not return project namespace' do
+ search_result = described_class.search('path')
+
+ expect(search_result).not_to include(project_namespace)
+ expect(search_result).to match_array([first_group, parent_group, second_group])
+ end
+
+ it 'does not return project namespace when including parents' do
+ search_result = described_class.search('path', include_parents: true)
+
+ expect(search_result).not_to include(project_namespace)
+ expect(search_result).to match_array([first_group, parent_group, second_group])
+ end
+ end
end
describe '.with_statistics' do
@@ -528,26 +594,30 @@ RSpec.describe Namespace do
create(:project,
namespace: namespace,
statistics: build(:project_statistics,
- namespace: namespace,
- repository_size: 101,
- wiki_size: 505,
- lfs_objects_size: 202,
- build_artifacts_size: 303,
- packages_size: 404,
- snippets_size: 605))
+ namespace: namespace,
+ repository_size: 101,
+ wiki_size: 505,
+ lfs_objects_size: 202,
+ build_artifacts_size: 303,
+ pipeline_artifacts_size: 707,
+ packages_size: 404,
+ snippets_size: 605,
+ uploads_size: 808))
end
let(:project2) do
create(:project,
namespace: namespace,
statistics: build(:project_statistics,
- namespace: namespace,
- repository_size: 10,
- wiki_size: 50,
- lfs_objects_size: 20,
- build_artifacts_size: 30,
- packages_size: 40,
- snippets_size: 60))
+ namespace: namespace,
+ repository_size: 10,
+ wiki_size: 50,
+ lfs_objects_size: 20,
+ build_artifacts_size: 30,
+ pipeline_artifacts_size: 70,
+ packages_size: 40,
+ snippets_size: 60,
+ uploads_size: 80))
end
it "sums all project storage counters in the namespace" do
@@ -555,13 +625,15 @@ RSpec.describe Namespace do
project2
statistics = described_class.with_statistics.find(namespace.id)
- expect(statistics.storage_size).to eq 2330
+ expect(statistics.storage_size).to eq 3995
expect(statistics.repository_size).to eq 111
expect(statistics.wiki_size).to eq 555
expect(statistics.lfs_objects_size).to eq 222
expect(statistics.build_artifacts_size).to eq 333
+ expect(statistics.pipeline_artifacts_size).to eq 777
expect(statistics.packages_size).to eq 444
expect(statistics.snippets_size).to eq 665
+ expect(statistics.uploads_size).to eq 888
end
it "correctly handles namespaces without projects" do
@@ -572,8 +644,10 @@ RSpec.describe Namespace do
expect(statistics.wiki_size).to eq 0
expect(statistics.lfs_objects_size).to eq 0
expect(statistics.build_artifacts_size).to eq 0
+ expect(statistics.pipeline_artifacts_size).to eq 0
expect(statistics.packages_size).to eq 0
expect(statistics.snippets_size).to eq 0
+ expect(statistics.uploads_size).to eq 0
end
end
@@ -673,7 +747,7 @@ RSpec.describe Namespace do
end
it "moves dir if path changed" do
- namespace.update(path: namespace.full_path + '_new')
+ namespace.update!(path: namespace.full_path + '_new')
expect(gitlab_shell.repository_exists?(project.repository_storage, "#{namespace.path}/#{project.path}.git")).to be_truthy
end
@@ -684,7 +758,7 @@ RSpec.describe Namespace do
expect(namespace).to receive(:write_projects_repository_config).and_raise('foo')
expect do
- namespace.update(path: namespace.full_path + '_new')
+ namespace.update!(path: namespace.full_path + '_new')
end.to raise_error('foo')
end
end
@@ -701,7 +775,7 @@ RSpec.describe Namespace do
end
expect(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(false) # like prod
- namespace.update(path: namespace.full_path + '_new')
+ namespace.update!(path: namespace.full_path + '_new')
end
end
end
@@ -931,7 +1005,7 @@ RSpec.describe Namespace do
it "repository directory remains unchanged if path changed" do
before_disk_path = project.disk_path
- namespace.update(path: namespace.full_path + '_new')
+ namespace.update!(path: namespace.full_path + '_new')
expect(before_disk_path).to eq(project.disk_path)
expect(gitlab_shell.repository_exists?(project.repository_storage, "#{project.disk_path}.git")).to be_truthy
@@ -946,7 +1020,7 @@ RSpec.describe Namespace do
let!(:legacy_project_in_subgroup) { create(:project, :legacy_storage, :repository, namespace: subgroup, name: 'foo3') }
it 'updates project full path in .git/config' do
- parent.update(path: 'mygroup_new')
+ parent.update!(path: 'mygroup_new')
expect(project_rugged(project_in_parent_group).config['gitlab.fullpath']).to eq "mygroup_new/#{project_in_parent_group.path}"
expect(project_rugged(hashed_project_in_subgroup).config['gitlab.fullpath']).to eq "mygroup_new/mysubgroup/#{hashed_project_in_subgroup.path}"
@@ -958,7 +1032,7 @@ RSpec.describe Namespace do
repository_hashed_project_in_subgroup = hashed_project_in_subgroup.project_repository
repository_legacy_project_in_subgroup = legacy_project_in_subgroup.project_repository
- parent.update(path: 'mygroup_moved')
+ parent.update!(path: 'mygroup_moved')
expect(repository_project_in_parent_group.reload.disk_path).to eq "mygroup_moved/#{project_in_parent_group.path}"
expect(repository_hashed_project_in_subgroup.reload.disk_path).to eq hashed_project_in_subgroup.disk_path
@@ -992,7 +1066,7 @@ RSpec.describe Namespace do
it 'renames its dirs when deleted' do
allow(GitlabShellWorker).to receive(:perform_in)
- namespace.destroy
+ namespace.destroy!
expect(File.exist?(deleted_path_in_dir)).to be(true)
end
@@ -1000,7 +1074,7 @@ RSpec.describe Namespace do
it 'schedules the namespace for deletion' do
expect(GitlabShellWorker).to receive(:perform_in).with(5.minutes, :rm_namespace, repository_storage, deleted_path)
- namespace.destroy
+ namespace.destroy!
end
context 'in sub-groups' do
@@ -1014,7 +1088,7 @@ RSpec.describe Namespace do
it 'renames its dirs when deleted' do
allow(GitlabShellWorker).to receive(:perform_in)
- child.destroy
+ child.destroy!
expect(File.exist?(deleted_path_in_dir)).to be(true)
end
@@ -1022,7 +1096,7 @@ RSpec.describe Namespace do
it 'schedules the namespace for deletion' do
expect(GitlabShellWorker).to receive(:perform_in).with(5.minutes, :rm_namespace, repository_storage, deleted_path)
- child.destroy
+ child.destroy!
end
end
end
@@ -1035,7 +1109,7 @@ RSpec.describe Namespace do
expect(File.exist?(path_in_dir)).to be(false)
- namespace.destroy
+ namespace.destroy!
expect(File.exist?(deleted_path_in_dir)).to be(false)
end
@@ -1293,6 +1367,7 @@ RSpec.describe Namespace do
context 'refreshing project access on updating share_with_group_lock' do
let(:group) { create(:group, share_with_group_lock: false) }
let(:project) { create(:project, :private, group: group) }
+ let(:another_project) { create(:project, :private, group: group) }
let_it_be(:shared_with_group_one) { create(:group) }
let_it_be(:shared_with_group_two) { create(:group) }
@@ -1305,6 +1380,7 @@ RSpec.describe Namespace do
shared_with_group_one.add_developer(group_one_user)
shared_with_group_two.add_developer(group_two_user)
create(:project_group_link, group: shared_with_group_one, project: project)
+ create(:project_group_link, group: shared_with_group_one, project: another_project)
create(:project_group_link, group: shared_with_group_two, project: project)
end
@@ -1312,6 +1388,9 @@ RSpec.describe Namespace do
expect(AuthorizedProjectUpdate::ProjectRecalculateWorker)
.to receive(:perform_async).with(project.id).once
+ expect(AuthorizedProjectUpdate::ProjectRecalculateWorker)
+ .to receive(:perform_async).with(another_project.id).once
+
execute_update
end
@@ -1344,11 +1423,23 @@ RSpec.describe Namespace do
stub_feature_flags(specialized_worker_for_group_lock_update_auth_recalculation: false)
end
- it 'refreshes the permissions of the members of the old and new namespace' do
+ it 'updates authorizations leading to users from shared groups losing access', :sidekiq_inline do
expect { execute_update }
.to change { group_one_user.authorized_projects.include?(project) }.from(true).to(false)
.and change { group_two_user.authorized_projects.include?(project) }.from(true).to(false)
end
+
+ it 'updates the authorizations in a non-blocking manner' do
+ expect(AuthorizedProjectsWorker).to(
+ receive(:bulk_perform_async)
+ .with([[group_one_user.id]])).once
+
+ expect(AuthorizedProjectsWorker).to(
+ receive(:bulk_perform_async)
+ .with([[group_two_user.id]])).once
+
+ execute_update
+ end
end
end
@@ -1544,7 +1635,7 @@ RSpec.describe Namespace do
it 'returns the path before last save' do
group = create(:group)
- group.update(parent: nil)
+ group.update!(parent: nil)
expect(group.full_path_before_last_save).to eq(group.path_before_last_save)
end
@@ -1555,7 +1646,7 @@ RSpec.describe Namespace do
group = create(:group, parent: nil)
parent = create(:group)
- group.update(parent: parent)
+ group.update!(parent: parent)
expect(group.full_path_before_last_save).to eq("#{group.path_before_last_save}")
end
@@ -1566,7 +1657,7 @@ RSpec.describe Namespace do
parent = create(:group)
group = create(:group, parent: parent)
- group.update(parent: nil)
+ group.update!(parent: nil)
expect(group.full_path_before_last_save).to eq("#{parent.full_path}/#{group.path}")
end
@@ -1578,7 +1669,7 @@ RSpec.describe Namespace do
group = create(:group, parent: parent)
new_parent = create(:group)
- group.update(parent: new_parent)
+ group.update!(parent: new_parent)
expect(group.full_path_before_last_save).to eq("#{parent.full_path}/#{group.path}")
end
@@ -1845,87 +1936,95 @@ RSpec.describe Namespace do
end
context 'with a parent' do
- context 'when parent has shared runners disabled' do
- let(:parent) { create(:group, :shared_runners_disabled) }
- let(:group) { build(:group, shared_runners_enabled: true, parent_id: parent.id) }
-
- it 'is invalid' do
- expect(group).to be_invalid
- expect(group.errors[:shared_runners_enabled]).to include('cannot be enabled because parent group has shared Runners disabled')
+ context 'when namespace is a group' do
+ context 'when parent has shared runners disabled' do
+ let(:parent) { create(:group, :shared_runners_disabled) }
+ let(:group) { build(:group, shared_runners_enabled: true, parent_id: parent.id) }
+
+ it 'is invalid' do
+ expect(group).to be_invalid
+ expect(group.errors[:shared_runners_enabled]).to include('cannot be enabled because parent group has shared Runners disabled')
+ end
end
- end
- context 'when parent has shared runners disabled but allows override' do
- let(:parent) { create(:group, :shared_runners_disabled, :allow_descendants_override_disabled_shared_runners) }
- let(:group) { build(:group, shared_runners_enabled: true, parent_id: parent.id) }
+ context 'when parent has shared runners disabled but allows override' do
+ let(:parent) { create(:group, :shared_runners_disabled, :allow_descendants_override_disabled_shared_runners) }
+ let(:group) { build(:group, shared_runners_enabled: true, parent_id: parent.id) }
- it 'is valid' do
- expect(group).to be_valid
+ it 'is valid' do
+ expect(group).to be_valid
+ end
end
- end
- context 'when parent has shared runners enabled' do
- let(:parent) { create(:group, shared_runners_enabled: true) }
- let(:group) { build(:group, shared_runners_enabled: true, parent_id: parent.id) }
+ context 'when parent has shared runners enabled' do
+ let(:parent) { create(:group, shared_runners_enabled: true) }
+ let(:group) { build(:group, shared_runners_enabled: true, parent_id: parent.id) }
- it 'is valid' do
- expect(group).to be_valid
+ it 'is valid' do
+ expect(group).to be_valid
+ end
end
end
end
+
+ it_behaves_like 'validations called by different namespace types', :changing_shared_runners_enabled_is_allowed
end
describe 'validation #changing_allow_descendants_override_disabled_shared_runners_is_allowed' do
- context 'without a parent' do
- context 'with shared runners disabled' do
- let(:namespace) { build(:namespace, :allow_descendants_override_disabled_shared_runners, :shared_runners_disabled) }
+ context 'when namespace is a group' do
+ context 'without a parent' do
+ context 'with shared runners disabled' do
+ let(:namespace) { build(:group, :allow_descendants_override_disabled_shared_runners, :shared_runners_disabled) }
- it 'is valid' do
- expect(namespace).to be_valid
+ it 'is valid' do
+ expect(namespace).to be_valid
+ end
end
- end
- context 'with shared runners enabled' do
- let(:namespace) { create(:namespace) }
+ context 'with shared runners enabled' do
+ let(:namespace) { create(:namespace) }
- it 'is invalid' do
- namespace.allow_descendants_override_disabled_shared_runners = true
+ it 'is invalid' do
+ namespace.allow_descendants_override_disabled_shared_runners = true
- expect(namespace).to be_invalid
- expect(namespace.errors[:allow_descendants_override_disabled_shared_runners]).to include('cannot be changed if shared runners are enabled')
+ expect(namespace).to be_invalid
+ expect(namespace.errors[:allow_descendants_override_disabled_shared_runners]).to include('cannot be changed if shared runners are enabled')
+ end
end
end
- end
- context 'with a parent' do
- context 'when parent does not allow shared runners' do
- let(:parent) { create(:group, :shared_runners_disabled) }
- let(:group) { build(:group, :shared_runners_disabled, :allow_descendants_override_disabled_shared_runners, parent_id: parent.id) }
+ context 'with a parent' do
+ context 'when parent does not allow shared runners' do
+ let(:parent) { create(:group, :shared_runners_disabled) }
+ let(:group) { build(:group, :shared_runners_disabled, :allow_descendants_override_disabled_shared_runners, parent_id: parent.id) }
- it 'is invalid' do
- expect(group).to be_invalid
- expect(group.errors[:allow_descendants_override_disabled_shared_runners]).to include('cannot be enabled because parent group does not allow it')
+ it 'is invalid' do
+ expect(group).to be_invalid
+ expect(group.errors[:allow_descendants_override_disabled_shared_runners]).to include('cannot be enabled because parent group does not allow it')
+ end
end
- end
- context 'when parent allows shared runners and setting to true' do
- let(:parent) { create(:group, shared_runners_enabled: true) }
- let(:group) { build(:group, :shared_runners_disabled, :allow_descendants_override_disabled_shared_runners, parent_id: parent.id) }
+ context 'when parent allows shared runners and setting to true' do
+ let(:parent) { create(:group, shared_runners_enabled: true) }
+ let(:group) { build(:group, :shared_runners_disabled, :allow_descendants_override_disabled_shared_runners, parent_id: parent.id) }
- it 'is valid' do
- expect(group).to be_valid
+ it 'is valid' do
+ expect(group).to be_valid
+ end
end
- end
- context 'when parent allows shared runners and setting to false' do
- let(:parent) { create(:group, shared_runners_enabled: true) }
- let(:group) { build(:group, :shared_runners_disabled, allow_descendants_override_disabled_shared_runners: false, parent_id: parent.id) }
+ context 'when parent allows shared runners and setting to false' do
+ let(:parent) { create(:group, shared_runners_enabled: true) }
+ let(:group) { build(:group, :shared_runners_disabled, allow_descendants_override_disabled_shared_runners: false, parent_id: parent.id) }
- it 'is valid' do
- expect(group).to be_valid
+ it 'is valid' do
+ expect(group).to be_valid
+ end
end
end
end
+
+ it_behaves_like 'validations called by different namespace types', :changing_allow_descendants_override_disabled_shared_runners_is_allowed
end
describe '#root?' do
diff --git a/spec/models/namespaces/project_namespace_spec.rb b/spec/models/namespaces/project_namespace_spec.rb
index f38e8aa85d0..4416c49f1bf 100644
--- a/spec/models/namespaces/project_namespace_spec.rb
+++ b/spec/models/namespaces/project_namespace_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Namespaces::ProjectNamespace, type: :model do
# using delete rather than destroy due to `delete` skipping AR hooks/callbacks
# so it's ensured to work at the DB level. Uses ON DELETE CASCADE on foreign key
let_it_be(:project) { create(:project) }
- let_it_be(:project_namespace) { create(:project_namespace, project: project) }
+ let_it_be(:project_namespace) { project.project_namespace }
it 'also deletes the associated project' do
project_namespace.delete
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 0dd77967f25..9d9cca0678a 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -155,7 +155,7 @@ RSpec.describe Note do
expect(note).to receive(:notify_after_destroy).and_call_original
expect(note.noteable).to receive(:after_note_destroyed).with(note)
- note.destroy
+ note.destroy!
end
it 'does not error if noteable is nil' do
@@ -163,7 +163,7 @@ RSpec.describe Note do
expect(note).to receive(:notify_after_destroy).and_call_original
expect(note).to receive(:noteable).at_least(:once).and_return(nil)
- expect { note.destroy }.not_to raise_error
+ expect { note.destroy! }.not_to raise_error
end
end
end
@@ -226,8 +226,8 @@ RSpec.describe Note do
describe 'read' do
before do
- @p1.project_members.create(user: @u2, access_level: ProjectMember::GUEST)
- @p2.project_members.create(user: @u3, access_level: ProjectMember::GUEST)
+ @p1.project_members.create!(user: @u2, access_level: ProjectMember::GUEST)
+ @p2.project_members.create!(user: @u3, access_level: ProjectMember::GUEST)
end
it { expect(Ability.allowed?(@u1, :read_note, @p1)).to be_falsey }
@@ -237,8 +237,8 @@ RSpec.describe Note do
describe 'write' do
before do
- @p1.project_members.create(user: @u2, access_level: ProjectMember::DEVELOPER)
- @p2.project_members.create(user: @u3, access_level: ProjectMember::DEVELOPER)
+ @p1.project_members.create!(user: @u2, access_level: ProjectMember::DEVELOPER)
+ @p2.project_members.create!(user: @u3, access_level: ProjectMember::DEVELOPER)
end
it { expect(Ability.allowed?(@u1, :create_note, @p1)).to be_falsey }
@@ -248,9 +248,9 @@ RSpec.describe Note do
describe 'admin' do
before do
- @p1.project_members.create(user: @u1, access_level: ProjectMember::REPORTER)
- @p1.project_members.create(user: @u2, access_level: ProjectMember::MAINTAINER)
- @p2.project_members.create(user: @u3, access_level: ProjectMember::MAINTAINER)
+ @p1.project_members.create!(user: @u1, access_level: ProjectMember::REPORTER)
+ @p1.project_members.create!(user: @u2, access_level: ProjectMember::MAINTAINER)
+ @p2.project_members.create!(user: @u3, access_level: ProjectMember::MAINTAINER)
end
it { expect(Ability.allowed?(@u1, :admin_note, @p1)).to be_falsey }
@@ -1468,7 +1468,7 @@ RSpec.describe Note do
shared_examples 'assignee check' do
context 'when the provided user is one of the assignees' do
before do
- note.noteable.update(assignees: [user, create(:user)])
+ note.noteable.update!(assignees: [user, create(:user)])
end
it 'returns true' do
@@ -1480,7 +1480,7 @@ RSpec.describe Note do
shared_examples 'author check' do
context 'when the provided user is the author' do
before do
- note.noteable.update(author: user)
+ note.noteable.update!(author: user)
end
it 'returns true' do
diff --git a/spec/models/notification_setting_spec.rb b/spec/models/notification_setting_spec.rb
index 3f1684327e7..cc601fb30c2 100644
--- a/spec/models/notification_setting_spec.rb
+++ b/spec/models/notification_setting_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe NotificationSetting do
notification_setting.merge_merge_request = "t"
notification_setting.close_merge_request = "nil"
notification_setting.reopen_merge_request = "false"
- notification_setting.save
+ notification_setting.save!
end
it "parses boolean before saving" do
@@ -52,12 +52,12 @@ RSpec.describe NotificationSetting do
context 'notification_email' do
let_it_be(:user) { create(:user) }
- subject { described_class.new(source_id: 1, source_type: 'Project', user_id: user.id) }
+ subject { build(:notification_setting, user_id: user.id) }
it 'allows to change email to verified one' do
email = create(:email, :confirmed, user: user)
- subject.update(notification_email: email.email)
+ subject.notification_email = email.email
expect(subject).to be_valid
end
@@ -65,13 +65,13 @@ RSpec.describe NotificationSetting do
it 'does not allow to change email to not verified one' do
email = create(:email, user: user)
- subject.update(notification_email: email.email)
+ subject.notification_email = email.email
expect(subject).to be_invalid
end
it 'allows to change email to empty one' do
- subject.update(notification_email: '')
+ subject.notification_email = ''
expect(subject).to be_valid
end
@@ -85,7 +85,7 @@ RSpec.describe NotificationSetting do
1.upto(4) do |i|
setting = create(:notification_setting, user: user)
- setting.project.update(pending_delete: true) if i.even?
+ setting.project.update!(pending_delete: true) if i.even?
end
end
diff --git a/spec/models/operations/feature_flags/strategy_spec.rb b/spec/models/operations/feature_flags/strategy_spec.rb
index 9289e3beab5..de1b9d2c855 100644
--- a/spec/models/operations/feature_flags/strategy_spec.rb
+++ b/spec/models/operations/feature_flags/strategy_spec.rb
@@ -20,8 +20,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
end
with_them do
it 'skips parameters validation' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: invalid_name, parameters: { bad: 'params' })
+ strategy = build(:operations_strategy,
+ feature_flag: feature_flag,
+ name: invalid_name,
+ parameters: { bad: 'params' })
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:name]).to eq(['strategy name is invalid'])
expect(strategy.errors[:parameters]).to be_empty
@@ -36,19 +40,24 @@ RSpec.describe Operations::FeatureFlags::Strategy do
end
with_them do
it 'must have valid parameters for the strategy' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gradualRolloutUserId', parameters: invalid_parameters)
+ strategy = build(:operations_strategy,
+ :gradual_rollout,
+ feature_flag: feature_flag,
+ parameters: invalid_parameters)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:parameters]).to eq(['parameters are invalid'])
end
end
it 'allows the parameters in any order' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gradualRolloutUserId',
- parameters: { percentage: '10', groupId: 'mygroup' })
+ strategy = build(:operations_strategy,
+ :gradual_rollout,
+ feature_flag: feature_flag,
+ parameters: { percentage: '10', groupId: 'mygroup' })
- expect(strategy.errors[:parameters]).to be_empty
+ expect(strategy).to be_valid
end
describe 'percentage' do
@@ -59,9 +68,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
end
with_them do
it 'must be a string value between 0 and 100 inclusive and without a percentage sign' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gradualRolloutUserId',
- parameters: { groupId: 'mygroup', percentage: invalid_value })
+ strategy = build(:operations_strategy,
+ :gradual_rollout,
+ feature_flag: feature_flag,
+ parameters: { groupId: 'mygroup', percentage: invalid_value })
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:parameters]).to eq(['percentage must be a string between 0 and 100 inclusive'])
end
@@ -72,11 +84,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
end
with_them do
it 'must be a string value between 0 and 100 inclusive and without a percentage sign' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gradualRolloutUserId',
- parameters: { groupId: 'mygroup', percentage: valid_value })
+ strategy = build(:operations_strategy,
+ :gradual_rollout,
+ feature_flag: feature_flag,
+ parameters: { groupId: 'mygroup', percentage: valid_value })
- expect(strategy.errors[:parameters]).to eq([])
+ expect(strategy).to be_valid
end
end
end
@@ -88,9 +101,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
end
with_them do
it 'must be a string value of up to 32 lowercase characters' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gradualRolloutUserId',
- parameters: { groupId: invalid_value, percentage: '40' })
+ strategy = build(:operations_strategy,
+ :gradual_rollout,
+ feature_flag: feature_flag,
+ parameters: { groupId: invalid_value, percentage: '40' })
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:parameters]).to eq(['groupId parameter is invalid'])
end
@@ -101,11 +117,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
end
with_them do
it 'must be a string value of up to 32 lowercase characters' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gradualRolloutUserId',
- parameters: { groupId: valid_value, percentage: '40' })
+ strategy = build(:operations_strategy,
+ :gradual_rollout,
+ feature_flag: feature_flag,
+ parameters: { groupId: valid_value, percentage: '40' })
- expect(strategy.errors[:parameters]).to eq([])
+ expect(strategy).to be_valid
end
end
end
@@ -123,9 +140,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
])
with_them do
it 'must have valid parameters for the strategy' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'flexibleRollout',
- parameters: invalid_parameters)
+ strategy = build(:operations_strategy,
+ :flexible_rollout,
+ feature_flag: feature_flag,
+ parameters: invalid_parameters)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:parameters]).to eq(['parameters are invalid'])
end
@@ -137,11 +157,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
[:groupId, 'mygroup']
].permutation(3).each do |parameters|
it "allows the parameters in the order #{parameters.map { |p| p.first }.join(', ')}" do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'flexibleRollout',
- parameters: Hash[parameters])
+ strategy = build(:operations_strategy,
+ :flexible_rollout,
+ feature_flag: feature_flag,
+ parameters: Hash[parameters])
- expect(strategy.errors[:parameters]).to be_empty
+ expect(strategy).to be_valid
end
end
@@ -152,9 +173,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
with_them do
it 'must be a string value between 0 and 100 inclusive and without a percentage sign' do
parameters = { stickiness: 'default', groupId: 'mygroup', rollout: invalid_value }
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'flexibleRollout',
- parameters: parameters)
+ strategy = build(:operations_strategy,
+ :flexible_rollout,
+ feature_flag: feature_flag,
+ parameters: parameters)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:parameters]).to eq([
'rollout must be a string between 0 and 100 inclusive'
@@ -166,11 +190,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
with_them do
it 'must be a string value between 0 and 100 inclusive and without a percentage sign' do
parameters = { stickiness: 'default', groupId: 'mygroup', rollout: valid_value }
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'flexibleRollout',
- parameters: parameters)
+ strategy = build(:operations_strategy,
+ :flexible_rollout,
+ feature_flag: feature_flag,
+ parameters: parameters)
- expect(strategy.errors[:parameters]).to eq([])
+ expect(strategy).to be_valid
end
end
end
@@ -181,9 +206,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
with_them do
it 'must be a string value of up to 32 lowercase characters' do
parameters = { stickiness: 'default', groupId: invalid_value, rollout: '40' }
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'flexibleRollout',
- parameters: parameters)
+ strategy = build(:operations_strategy,
+ :flexible_rollout,
+ feature_flag: feature_flag,
+ parameters: parameters)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:parameters]).to eq(['groupId parameter is invalid'])
end
@@ -193,11 +221,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
with_them do
it 'must be a string value of up to 32 lowercase characters' do
parameters = { stickiness: 'default', groupId: valid_value, rollout: '40' }
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'flexibleRollout',
- parameters: parameters)
+ strategy = build(:operations_strategy,
+ :flexible_rollout,
+ feature_flag: feature_flag,
+ parameters: parameters)
- expect(strategy.errors[:parameters]).to eq([])
+ expect(strategy).to be_valid
end
end
end
@@ -207,9 +236,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
with_them do
it 'must be a string representing a supported stickiness setting' do
parameters = { stickiness: invalid_value, groupId: 'mygroup', rollout: '40' }
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'flexibleRollout',
- parameters: parameters)
+ strategy = build(:operations_strategy,
+ :flexible_rollout,
+ feature_flag: feature_flag,
+ parameters: parameters)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:parameters]).to eq([
'stickiness parameter must be default, userId, sessionId, or random'
@@ -221,11 +253,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
with_them do
it 'must be a string representing a supported stickiness setting' do
parameters = { stickiness: valid_value, groupId: 'mygroup', rollout: '40' }
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'flexibleRollout',
- parameters: parameters)
+ strategy = build(:operations_strategy,
+ :flexible_rollout,
+ feature_flag: feature_flag,
+ parameters: parameters)
- expect(strategy.errors[:parameters]).to eq([])
+ expect(strategy).to be_valid
end
end
end
@@ -237,8 +270,11 @@ RSpec.describe Operations::FeatureFlags::Strategy do
end
with_them do
it 'must have valid parameters for the strategy' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'userWithId', parameters: invalid_parameters)
+ strategy = build(:operations_strategy,
+ feature_flag: feature_flag,
+ name: 'userWithId', parameters: invalid_parameters)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:parameters]).to eq(['parameters are invalid'])
end
@@ -253,10 +289,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
end
with_them do
it 'is valid with a string of comma separated values' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'userWithId', parameters: { userIds: valid_value })
+ strategy = build(:operations_strategy,
+ feature_flag: feature_flag,
+ name: 'userWithId',
+ parameters: { userIds: valid_value })
- expect(strategy.errors[:parameters]).to be_empty
+ expect(strategy).to be_valid
end
end
@@ -267,8 +305,12 @@ RSpec.describe Operations::FeatureFlags::Strategy do
end
with_them do
it 'is invalid' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'userWithId', parameters: { userIds: invalid_value })
+ strategy = build(:operations_strategy,
+ feature_flag: feature_flag,
+ name: 'userWithId',
+ parameters: { userIds: invalid_value })
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:parameters]).to include(
'userIds must be a string of unique comma separated values each 256 characters or less'
@@ -284,43 +326,48 @@ RSpec.describe Operations::FeatureFlags::Strategy do
end
with_them do
it 'must be empty' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'default',
- parameters: invalid_value)
+ strategy = build(:operations_strategy, :default, feature_flag: feature_flag, parameters: invalid_value)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:parameters]).to eq(['parameters are invalid'])
end
end
it 'must be empty' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'default',
- parameters: {})
+ strategy = build(:operations_strategy, :default, feature_flag: feature_flag)
- expect(strategy.errors[:parameters]).to be_empty
+ expect(strategy).to be_valid
end
end
context 'when the strategy name is gitlabUserList' do
+ let_it_be(:user_list) { create(:operations_feature_flag_user_list, project: project) }
+
where(:invalid_value) do
[{ groupId: "default", percentage: "7" }, "", "nothing", 7, nil, [], 2.5, { userIds: 'user1' }]
end
with_them do
- it 'must be empty' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gitlabUserList',
- parameters: invalid_value)
+ it 'is invalid' do
+ strategy = build(:operations_strategy,
+ :gitlab_userlist,
+ user_list: user_list,
+ feature_flag: feature_flag,
+ parameters: invalid_value)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:parameters]).to eq(['parameters are invalid'])
end
end
- it 'must be empty' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gitlabUserList',
- parameters: {})
+ it 'is valid' do
+ strategy = build(:operations_strategy,
+ :gitlab_userlist,
+ user_list: user_list,
+ feature_flag: feature_flag)
- expect(strategy.errors[:parameters]).to be_empty
+ expect(strategy).to be_valid
end
end
end
@@ -329,18 +376,15 @@ RSpec.describe Operations::FeatureFlags::Strategy do
context 'when name is gitlabUserList' do
it 'is valid when associated with a user list' do
user_list = create(:operations_feature_flag_user_list, project: project)
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gitlabUserList',
- user_list: user_list,
- parameters: {})
+ strategy = build(:operations_strategy, :gitlab_userlist, feature_flag: feature_flag, user_list: user_list)
- expect(strategy.errors[:user_list]).to be_empty
+ expect(strategy).to be_valid
end
it 'is invalid without a user list' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gitlabUserList',
- parameters: {})
+ strategy = build(:operations_strategy, :gitlab_userlist, feature_flag: feature_flag, user_list: nil)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:user_list]).to eq(["can't be blank"])
end
@@ -348,10 +392,9 @@ RSpec.describe Operations::FeatureFlags::Strategy do
it 'is invalid when associated with a user list from another project' do
other_project = create(:project)
user_list = create(:operations_feature_flag_user_list, project: other_project)
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gitlabUserList',
- user_list: user_list,
- parameters: {})
+ strategy = build(:operations_strategy, :gitlab_userlist, feature_flag: feature_flag, user_list: user_list)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:user_list]).to eq(['must belong to the same project'])
end
@@ -360,84 +403,68 @@ RSpec.describe Operations::FeatureFlags::Strategy do
context 'when name is default' do
it 'is invalid when associated with a user list' do
user_list = create(:operations_feature_flag_user_list, project: project)
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'default',
- user_list: user_list,
- parameters: {})
+ strategy = build(:operations_strategy, :default, feature_flag: feature_flag, user_list: user_list)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:user_list]).to eq(['must be blank'])
end
it 'is valid without a user list' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'default',
- parameters: {})
+ strategy = build(:operations_strategy, :default, feature_flag: feature_flag)
- expect(strategy.errors[:user_list]).to be_empty
+ expect(strategy).to be_valid
end
end
context 'when name is userWithId' do
it 'is invalid when associated with a user list' do
user_list = create(:operations_feature_flag_user_list, project: project)
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'userWithId',
- user_list: user_list,
- parameters: { userIds: 'user1' })
+ strategy = build(:operations_strategy, :userwithid, feature_flag: feature_flag, user_list: user_list)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:user_list]).to eq(['must be blank'])
end
it 'is valid without a user list' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'userWithId',
- parameters: { userIds: 'user1' })
+ strategy = build(:operations_strategy, :userwithid, feature_flag: feature_flag)
- expect(strategy.errors[:user_list]).to be_empty
+ expect(strategy).to be_valid
end
end
context 'when name is gradualRolloutUserId' do
it 'is invalid when associated with a user list' do
user_list = create(:operations_feature_flag_user_list, project: project)
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gradualRolloutUserId',
- user_list: user_list,
- parameters: { groupId: 'default', percentage: '10' })
+ strategy = build(:operations_strategy, :gradual_rollout, feature_flag: feature_flag, user_list: user_list)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:user_list]).to eq(['must be blank'])
end
it 'is valid without a user list' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'gradualRolloutUserId',
- parameters: { groupId: 'default', percentage: '10' })
+ strategy = build(:operations_strategy, :gradual_rollout, feature_flag: feature_flag)
- expect(strategy.errors[:user_list]).to be_empty
+ expect(strategy).to be_valid
end
end
context 'when name is flexibleRollout' do
it 'is invalid when associated with a user list' do
user_list = create(:operations_feature_flag_user_list, project: project)
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'flexibleRollout',
- user_list: user_list,
- parameters: { groupId: 'default',
- rollout: '10',
- stickiness: 'default' })
+ strategy = build(:operations_strategy, :flexible_rollout, feature_flag: feature_flag, user_list: user_list)
+
+ expect(strategy).to be_invalid
expect(strategy.errors[:user_list]).to eq(['must be blank'])
end
it 'is valid without a user list' do
- strategy = described_class.create(feature_flag: feature_flag,
- name: 'flexibleRollout',
- parameters: { groupId: 'default',
- rollout: '10',
- stickiness: 'default' })
+ strategy = build(:operations_strategy, :flexible_rollout, feature_flag: feature_flag)
- expect(strategy.errors[:user_list]).to be_empty
+ expect(strategy).to be_valid
end
end
end
diff --git a/spec/models/operations/feature_flags/user_list_spec.rb b/spec/models/operations/feature_flags/user_list_spec.rb
index 3a48d3389a3..b2dbebb2c0d 100644
--- a/spec/models/operations/feature_flags/user_list_spec.rb
+++ b/spec/models/operations/feature_flags/user_list_spec.rb
@@ -20,9 +20,9 @@ RSpec.describe Operations::FeatureFlags::UserList do
end
with_them do
it 'is valid with a string of comma separated values' do
- user_list = described_class.create(user_xids: valid_value)
+ user_list = build(:operations_feature_flag_user_list, user_xids: valid_value)
- expect(user_list.errors[:user_xids]).to be_empty
+ expect(user_list).to be_valid
end
end
@@ -31,9 +31,10 @@ RSpec.describe Operations::FeatureFlags::UserList do
end
with_them do
it 'automatically casts values of other types' do
- user_list = described_class.create(user_xids: typecast_value)
+ user_list = build(:operations_feature_flag_user_list, user_xids: typecast_value)
+
+ expect(user_list).to be_valid
- expect(user_list.errors[:user_xids]).to be_empty
expect(user_list.user_xids).to eq(typecast_value.to_s)
end
end
@@ -45,7 +46,9 @@ RSpec.describe Operations::FeatureFlags::UserList do
end
with_them do
it 'is invalid' do
- user_list = described_class.create(user_xids: invalid_value)
+ user_list = build(:operations_feature_flag_user_list, user_xids: invalid_value)
+
+ expect(user_list).to be_invalid
expect(user_list.errors[:user_xids]).to include(
'user_xids must be a string of unique comma separated values each 256 characters or less'
@@ -70,20 +73,20 @@ RSpec.describe Operations::FeatureFlags::UserList do
describe '#destroy' do
it 'deletes the model if it is not associated with any feature flag strategies' do
project = create(:project)
- user_list = described_class.create(project: project, name: 'My User List', user_xids: 'user1,user2')
+ user_list = described_class.create!(project: project, name: 'My User List', user_xids: 'user1,user2')
- user_list.destroy
+ user_list.destroy!
expect(described_class.count).to eq(0)
end
it 'does not delete the model if it is associated with a feature flag strategy' do
project = create(:project)
- user_list = described_class.create(project: project, name: 'My User List', user_xids: 'user1,user2')
+ user_list = described_class.create!(project: project, name: 'My User List', user_xids: 'user1,user2')
feature_flag = create(:operations_feature_flag, :new_version_flag, project: project)
strategy = create(:operations_strategy, feature_flag: feature_flag, name: 'gitlabUserList', user_list: user_list)
- user_list.destroy
+ user_list.destroy # rubocop:disable Rails/SaveBang
expect(described_class.count).to eq(1)
expect(::Operations::FeatureFlags::StrategyUserList.count).to eq(1)
diff --git a/spec/models/packages/npm/metadatum_spec.rb b/spec/models/packages/npm/metadatum_spec.rb
new file mode 100644
index 00000000000..ff8cce5310e
--- /dev/null
+++ b/spec/models/packages/npm/metadatum_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Npm::Metadatum, type: :model do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:package).inverse_of(:npm_metadatum) }
+ end
+
+ describe 'validations' do
+ describe 'package', :aggregate_failures do
+ it { is_expected.to validate_presence_of(:package) }
+
+ it 'ensure npm package type' do
+ metadatum = build(:npm_metadatum)
+
+ metadatum.package = build(:nuget_package)
+
+ expect(metadatum).not_to be_valid
+ expect(metadatum.errors).to contain_exactly('Package type must be NPM')
+ end
+ end
+
+ describe 'package_json', :aggregate_failures do
+ let(:valid_json) { { 'name' => 'foo', 'version' => 'v1.0', 'dist' => { 'tarball' => 'x', 'shasum' => 'x' } } }
+
+ it { is_expected.to allow_value(valid_json).for(:package_json) }
+ it { is_expected.to allow_value(valid_json.merge('extra-field': { 'foo': 'bar' })).for(:package_json) }
+ it { is_expected.to allow_value(with_dist { |dist| dist.merge('extra-field': 'x') }).for(:package_json) }
+
+ %w[name version dist].each do |field|
+ it { is_expected.not_to allow_value(valid_json.except(field)).for(:package_json) }
+ end
+
+ %w[tarball shasum].each do |field|
+ it { is_expected.not_to allow_value(with_dist { |dist| dist.except(field) }).for(:package_json) }
+ end
+
+ it { is_expected.not_to allow_value({}).for(:package_json) }
+
+ it { is_expected.not_to allow_value(test: 'test' * 10000).for(:package_json) }
+
+ def with_dist
+ valid_json.tap do |h|
+ h['dist'] = yield(h['dist'])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/packages/package_file_spec.rb b/spec/models/packages/package_file_spec.rb
index 450656e3e9c..8617793f41d 100644
--- a/spec/models/packages/package_file_spec.rb
+++ b/spec/models/packages/package_file_spec.rb
@@ -14,7 +14,6 @@ RSpec.describe Packages::PackageFile, type: :model do
it { is_expected.to belong_to(:package) }
it { is_expected.to have_one(:conan_file_metadatum) }
it { is_expected.to have_many(:package_file_build_infos).inverse_of(:package_file) }
- it { is_expected.to have_many(:pipelines).through(:package_file_build_infos) }
it { is_expected.to have_one(:debian_file_metadatum).inverse_of(:package_file).class_name('Packages::Debian::FileMetadatum') }
it { is_expected.to have_one(:helm_file_metadatum).inverse_of(:package_file).class_name('Packages::Helm::FileMetadatum') }
end
@@ -206,6 +205,28 @@ RSpec.describe Packages::PackageFile, type: :model do
end
end
+ describe '#pipelines' do
+ let_it_be_with_refind(:package_file) { create(:package_file) }
+
+ subject { package_file.pipelines }
+
+ context 'package_file without pipeline' do
+ it { is_expected.to be_empty }
+ end
+
+ context 'package_file with pipeline' do
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+ let_it_be(:pipeline2) { create(:ci_pipeline) }
+
+ before do
+ package_file.package_file_build_infos.create!(pipeline: pipeline)
+ package_file.package_file_build_infos.create!(pipeline: pipeline2)
+ end
+
+ it { is_expected.to contain_exactly(pipeline, pipeline2) }
+ end
+ end
+
describe '#update_file_store callback' do
let_it_be(:package_file) { build(:package_file, :nuget, size: nil) }
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index 2573c01d686..6ee5219819c 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -14,13 +14,13 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.to have_many(:dependency_links).inverse_of(:package) }
it { is_expected.to have_many(:tags).inverse_of(:package) }
it { is_expected.to have_many(:build_infos).inverse_of(:package) }
- it { is_expected.to have_many(:pipelines).through(:build_infos) }
it { is_expected.to have_one(:conan_metadatum).inverse_of(:package) }
it { is_expected.to have_one(:maven_metadatum).inverse_of(:package) }
it { is_expected.to have_one(:debian_publication).inverse_of(:package).class_name('Packages::Debian::Publication') }
it { is_expected.to have_one(:debian_distribution).through(:debian_publication).source(:distribution).inverse_of(:packages).class_name('Packages::Debian::ProjectDistribution') }
it { is_expected.to have_one(:nuget_metadatum).inverse_of(:package) }
it { is_expected.to have_one(:rubygems_metadatum).inverse_of(:package) }
+ it { is_expected.to have_one(:npm_metadatum).inverse_of(:package) }
end
describe '.with_debian_codename' do
@@ -999,6 +999,28 @@ RSpec.describe Packages::Package, type: :model do
end
end
+ describe '#pipelines' do
+ let_it_be_with_refind(:package) { create(:maven_package) }
+
+ subject { package.pipelines }
+
+ context 'package without pipeline' do
+ it { is_expected.to be_empty }
+ end
+
+ context 'package with pipeline' do
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+ let_it_be(:pipeline2) { create(:ci_pipeline) }
+
+ before do
+ package.build_infos.create!(pipeline: pipeline)
+ package.build_infos.create!(pipeline: pipeline2)
+ end
+
+ it { is_expected.to contain_exactly(pipeline, pipeline2) }
+ end
+ end
+
describe '#tag_names' do
let_it_be(:package) { create(:nuget_package) }
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index 2b6ed9a9927..d476e18a72c 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -104,7 +104,7 @@ RSpec.describe PagesDomain do
let(:domain) { build(:pages_domain) }
it 'saves validity time' do
- domain.save
+ domain.save!
expect(domain.certificate_valid_not_before).to be_like_time(Time.zone.parse("2020-03-16 14:20:34 UTC"))
expect(domain.certificate_valid_not_after).to be_like_time(Time.zone.parse("2220-01-28 14:20:34 UTC"))
@@ -161,7 +161,7 @@ RSpec.describe PagesDomain do
context 'when certificate is already saved' do
it "doesn't add error to certificate" do
- domain.save(validate: false)
+ domain.save!(validate: false)
domain.valid?
diff --git a/spec/models/preloaders/group_policy_preloader_spec.rb b/spec/models/preloaders/group_policy_preloader_spec.rb
new file mode 100644
index 00000000000..f6e40d1f033
--- /dev/null
+++ b/spec/models/preloaders/group_policy_preloader_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Preloaders::GroupPolicyPreloader do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:root_parent) { create(:group, :private, name: 'root-1', path: 'root-1') }
+ let_it_be(:guest_group) { create(:group, name: 'public guest', path: 'public-guest') }
+ let_it_be(:private_maintainer_group) { create(:group, :private, name: 'b private maintainer', path: 'b-private-maintainer', parent: root_parent) }
+ let_it_be(:private_developer_group) { create(:group, :private, project_creation_level: nil, name: 'c public developer', path: 'c-public-developer') }
+ let_it_be(:public_maintainer_group) { create(:group, :private, name: 'a public maintainer', path: 'a-public-maintainer') }
+
+ let(:base_groups) { [guest_group, private_maintainer_group, private_developer_group, public_maintainer_group] }
+
+ before_all do
+ guest_group.add_guest(user)
+ private_maintainer_group.add_maintainer(user)
+ private_developer_group.add_developer(user)
+ public_maintainer_group.add_maintainer(user)
+ end
+
+ it 'avoids N+1 queries when authorizing a list of groups', :request_store do
+ preload_groups_for_policy(user)
+ control = ActiveRecord::QueryRecorder.new { authorize_all_groups(user) }
+
+ new_group1 = create(:group, :private).tap { |group| group.add_maintainer(user) }
+ new_group2 = create(:group, :private, parent: private_maintainer_group)
+
+ another_root = create(:group, :private, name: 'root-3', path: 'root-3')
+ new_group3 = create(:group, :private, parent: another_root).tap { |group| group.add_maintainer(user) }
+
+ pristine_groups = Group.where(id: base_groups + [new_group1, new_group2, new_group3])
+
+ preload_groups_for_policy(user, pristine_groups)
+ expect { authorize_all_groups(user, pristine_groups) }.not_to exceed_query_limit(control)
+ end
+
+ def authorize_all_groups(current_user, group_list = base_groups)
+ group_list.each { |group| current_user.can?(:read_group, group) }
+ end
+
+ def preload_groups_for_policy(current_user, group_list = base_groups)
+ described_class.new(group_list, current_user).execute
+ end
+end
diff --git a/spec/models/preloaders/group_root_ancestor_preloader_spec.rb b/spec/models/preloaders/group_root_ancestor_preloader_spec.rb
new file mode 100644
index 00000000000..0d622e84ef1
--- /dev/null
+++ b/spec/models/preloaders/group_root_ancestor_preloader_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Preloaders::GroupRootAncestorPreloader do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:root_parent1) { create(:group, :private, name: 'root-1', path: 'root-1') }
+ let_it_be(:root_parent2) { create(:group, :private, name: 'root-2', path: 'root-2') }
+ let_it_be(:guest_group) { create(:group, name: 'public guest', path: 'public-guest') }
+ let_it_be(:private_maintainer_group) { create(:group, :private, name: 'b private maintainer', path: 'b-private-maintainer', parent: root_parent1) }
+ let_it_be(:private_developer_group) { create(:group, :private, project_creation_level: nil, name: 'c public developer', path: 'c-public-developer') }
+ let_it_be(:public_maintainer_group) { create(:group, :private, name: 'a public maintainer', path: 'a-public-maintainer', parent: root_parent2) }
+
+ let(:root_query_regex) { /\ASELECT.+FROM "namespaces" WHERE "namespaces"."id" = \d+/ }
+ let(:additional_preloads) { [] }
+ let(:groups) { [guest_group, private_maintainer_group, private_developer_group, public_maintainer_group] }
+ let(:pristine_groups) { Group.where(id: groups) }
+
+ shared_examples 'executes N matching DB queries' do |expected_query_count, query_method = nil|
+ it 'executes the specified root_ancestor queries' do
+ expect do
+ pristine_groups.each do |group|
+ root_ancestor = group.root_ancestor
+
+ root_ancestor.public_send(query_method) if query_method.present?
+ end
+ end.to make_queries_matching(root_query_regex, expected_query_count)
+ end
+
+ it 'strong_memoizes the correct root_ancestor' do
+ pristine_groups.each do |group|
+ expected_parent_id = group.root_ancestor.id == group.id ? nil : group.root_ancestor.id
+
+ expect(group.parent_id).to eq(expected_parent_id)
+ end
+ end
+ end
+
+ context 'when the preloader is used' do
+ before do
+ preload_ancestors
+ end
+
+ context 'when no additional preloads are provided' do
+ it_behaves_like 'executes N matching DB queries', 0
+ end
+
+ context 'when additional preloads are provided' do
+ let(:additional_preloads) { [:route] }
+ let(:root_query_regex) { /\ASELECT.+FROM "routes" WHERE "routes"."source_id" = \d+/ }
+
+ it_behaves_like 'executes N matching DB queries', 0, :full_path
+ end
+ end
+
+ context 'when the preloader is not used' do
+ it_behaves_like 'executes N matching DB queries', 2
+ end
+
+ def preload_ancestors
+ described_class.new(pristine_groups, additional_preloads).execute
+ end
+end
diff --git a/spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb b/spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb
index 8144e1ad233..5fc7bfb1f62 100644
--- a/spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb
+++ b/spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb
@@ -13,32 +13,47 @@ RSpec.describe Preloaders::UserMaxAccessLevelInGroupsPreloader do
shared_examples 'executes N max member permission queries to the DB' do
it 'executes the specified max membership queries' do
- queries = ActiveRecord::QueryRecorder.new do
- groups.each { |group| user.can?(:read_group, group) }
- end
+ expect { groups.each { |group| user.can?(:read_group, group) } }.to make_queries_matching(max_query_regex, expected_query_count)
+ end
- max_queries = queries.log.grep(max_query_regex)
+ it 'caches the correct access_level for each group' do
+ groups.each do |group|
+ access_level_from_db = group.members_with_parents.where(user_id: user.id).group(:user_id).maximum(:access_level)[user.id] || Gitlab::Access::NO_ACCESS
+ cached_access_level = group.max_member_access_for_user(user)
- expect(max_queries.count).to eq(expected_query_count)
+ expect(cached_access_level).to eq(access_level_from_db)
+ end
end
end
context 'when the preloader is used', :request_store do
- before do
- described_class.new(groups, user).execute
- end
+ context 'when user has indirect access to groups' do
+ let_it_be(:child_maintainer) { create(:group, :private, parent: group1).tap {|g| g.add_maintainer(user)} }
+ let_it_be(:child_indirect_access) { create(:group, :private, parent: group1) }
- it_behaves_like 'executes N max member permission queries to the DB' do
- # Will query all groups where the user is not already a member
- let(:expected_query_count) { 1 }
- end
+ let(:groups) { [group1, group2, group3, child_maintainer, child_indirect_access] }
+
+ context 'when traversal_ids feature flag is disabled' do
+ it_behaves_like 'executes N max member permission queries to the DB' do
+ before do
+ stub_feature_flags(use_traversal_ids: false)
+ described_class.new(groups, user).execute
+ end
+
+ # One query for group with no access and another one per group where the user is not a direct member
+ let(:expected_query_count) { 2 }
+ end
+ end
- context 'when user has access but is not a direct member of the group' do
- let(:groups) { [group1, group2, group3, create(:group, :private, parent: group1)] }
+ context 'when traversal_ids feature flag is enabled' do
+ it_behaves_like 'executes N max member permission queries to the DB' do
+ before do
+ stub_feature_flags(use_traversal_ids: true)
+ described_class.new(groups, user).execute
+ end
- it_behaves_like 'executes N max member permission queries to the DB' do
- # One query for group with no access and another one where the user is not a direct member
- let(:expected_query_count) { 2 }
+ let(:expected_query_count) { 0 }
+ end
end
end
end
diff --git a/spec/models/project_authorization_spec.rb b/spec/models/project_authorization_spec.rb
index c517fc8be55..58c0ff48b46 100644
--- a/spec/models/project_authorization_spec.rb
+++ b/spec/models/project_authorization_spec.rb
@@ -3,9 +3,10 @@
require 'spec_helper'
RSpec.describe ProjectAuthorization do
- let(:user) { create(:user) }
- let(:project1) { create(:project) }
- let(:project2) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project1) { create(:project) }
+ let_it_be(:project2) { create(:project) }
+ let_it_be(:project3) { create(:project) }
describe '.insert_authorizations' do
it 'inserts the authorizations' do
@@ -23,5 +24,19 @@ RSpec.describe ProjectAuthorization do
expect(user.project_authorizations.count).to eq(2)
end
+
+ it 'skips duplicates and inserts the remaining rows without error' do
+ create(:project_authorization, user: user, project: project1, access_level: Gitlab::Access::MAINTAINER)
+
+ rows = [
+ [user.id, project1.id, Gitlab::Access::MAINTAINER],
+ [user.id, project2.id, Gitlab::Access::MAINTAINER],
+ [user.id, project3.id, Gitlab::Access::MAINTAINER]
+ ]
+
+ described_class.insert_authorizations(rows)
+
+ expect(user.project_authorizations.pluck(:user_id, :project_id, :access_level)).to match_array(rows)
+ end
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 2e5c5af4eb0..3a8768ff463 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Project, factory_default: :keep do
describe 'associations' do
it { is_expected.to belong_to(:group) }
it { is_expected.to belong_to(:namespace) }
- it { is_expected.to belong_to(:project_namespace).class_name('Namespaces::ProjectNamespace').with_foreign_key('project_namespace_id').inverse_of(:project) }
+ it { is_expected.to belong_to(:project_namespace).class_name('Namespaces::ProjectNamespace').with_foreign_key('project_namespace_id') }
it { is_expected.to belong_to(:creator).class_name('User') }
it { is_expected.to belong_to(:pool_repository) }
it { is_expected.to have_many(:users) }
@@ -191,7 +191,7 @@ RSpec.describe Project, factory_default: :keep do
# using delete rather than destroy due to `delete` skipping AR hooks/callbacks
# so it's ensured to work at the DB level. Uses AFTER DELETE trigger.
let_it_be(:project) { create(:project) }
- let_it_be(:project_namespace) { create(:project_namespace, project: project) }
+ let_it_be(:project_namespace) { project.project_namespace }
it 'also deletes the associated ProjectNamespace' do
project.delete
@@ -233,6 +233,58 @@ RSpec.describe Project, factory_default: :keep do
expect(project.project_setting).to be_an_instance_of(ProjectSetting)
expect(project.project_setting).to be_new_record
end
+
+ context 'with project namespaces' do
+ it 'automatically creates a project namespace' do
+ project = build(:project, path: 'hopefully-valid-path1')
+ project.save!
+
+ expect(project).to be_persisted
+ expect(project.project_namespace).to be_persisted
+ expect(project.project_namespace).to be_in_sync_with_project(project)
+ end
+
+ context 'with FF disabled' do
+ before do
+ stub_feature_flags(create_project_namespace_on_project_create: false)
+ end
+
+ it 'does not create a project namespace' do
+ project = build(:project, path: 'hopefully-valid-path2')
+ project.save!
+
+ expect(project).to be_persisted
+ expect(project.project_namespace).to be_nil
+ end
+ end
+ end
+ end
+
+ context 'updating a project' do
+ context 'with project namespaces' do
+ it 'keeps project namespace in sync with project' do
+ project = create(:project)
+ project.update!(path: 'hopefully-valid-path1')
+
+ expect(project).to be_persisted
+ expect(project.project_namespace).to be_persisted
+ expect(project.project_namespace).to be_in_sync_with_project(project)
+ end
+
+ context 'with FF disabled' do
+ before do
+ stub_feature_flags(create_project_namespace_on_project_create: false)
+ end
+
+ it 'does not create a project namespace when project is updated' do
+ project = create(:project)
+ project.update!(path: 'hopefully-valid-path1')
+
+ expect(project).to be_persisted
+ expect(project.project_namespace).to be_nil
+ end
+ end
+ end
end
context 'updating cd_cd_settings' do
@@ -294,6 +346,7 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to validate_presence_of(:namespace) }
it { is_expected.to validate_presence_of(:repository_storage) }
it { is_expected.to validate_numericality_of(:max_artifacts_size).only_integer.is_greater_than(0) }
+ it { is_expected.to validate_length_of(:suggestion_commit_message).is_at_most(255) }
it 'validates build timeout constraints' do
is_expected.to validate_numericality_of(:build_timeout)
@@ -322,6 +375,18 @@ RSpec.describe Project, factory_default: :keep do
create(:project)
end
+ context 'validates project namespace creation' do
+ it 'does not create project namespace if project is not created' do
+ project = build(:project, path: 'tree')
+
+ project.valid?
+
+ expect(project).not_to be_valid
+ expect(project).to be_new_record
+ expect(project.project_namespace).to be_new_record
+ end
+ end
+
context 'repository storages inclusion' do
let(:project2) { build(:project, repository_storage: 'missing') }
@@ -424,8 +489,9 @@ RSpec.describe Project, factory_default: :keep do
end
include_context 'invalid urls'
+ include_context 'valid urls with CRLF'
- it 'does not allow urls with CR or LF characters' do
+ it 'does not allow URLs with unencoded CR or LF characters' do
project = build(:project)
aggregate_failures do
@@ -437,6 +503,19 @@ RSpec.describe Project, factory_default: :keep do
end
end
end
+
+ it 'allow URLs with CR or LF characters' do
+ project = build(:project)
+
+ aggregate_failures do
+ valid_urls_with_CRLF.each do |url|
+ project.import_url = url
+
+ expect(project).to be_valid
+ expect(project.errors).to be_empty
+ end
+ end
+ end
end
describe 'project pending deletion' do
@@ -1714,13 +1793,19 @@ RSpec.describe Project, factory_default: :keep do
allow(::Gitlab::ServiceDeskEmail).to receive(:config).and_return(config)
end
- it 'returns custom address when project_key is set' do
- create(:service_desk_setting, project: project, project_key: 'key1')
+ context 'when project_key is set' do
+ it 'returns custom address including the project_key' do
+ create(:service_desk_setting, project: project, project_key: 'key1')
- expect(subject).to eq("foo+#{project.full_path_slug}-key1@bar.com")
+ expect(subject).to eq("foo+#{project.full_path_slug}-key1@bar.com")
+ end
end
- it_behaves_like 'with incoming email address'
+ context 'when project_key is not set' do
+ it 'returns custom address including the project full path' do
+ expect(subject).to eq("foo+#{project.full_path_slug}-#{project.project_id}-issue-@bar.com")
+ end
+ end
end
end
@@ -1780,6 +1865,20 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '.without_integration' do
+ it 'returns projects without the integration' do
+ project_1, project_2, project_3, project_4 = create_list(:project, 4)
+ instance_integration = create(:jira_integration, :instance)
+ create(:jira_integration, project: project_1, inherit_from_id: instance_integration.id)
+ create(:jira_integration, project: project_2, inherit_from_id: nil)
+ create(:jira_integration, group: create(:group), project: nil, inherit_from_id: nil)
+ create(:jira_integration, project: project_3, inherit_from_id: nil)
+ create(:integrations_slack, project: project_4, inherit_from_id: nil)
+
+ expect(Project.without_integration(instance_integration)).to contain_exactly(project_4)
+ end
+ end
+
context 'repository storage by default' do
let(:project) { build(:project) }
diff --git a/spec/models/project_statistics_spec.rb b/spec/models/project_statistics_spec.rb
index ead6238b2f4..5fbf1a9c502 100644
--- a/spec/models/project_statistics_spec.rb
+++ b/spec/models/project_statistics_spec.rb
@@ -325,12 +325,14 @@ RSpec.describe ProjectStatistics do
lfs_objects_size: 3,
snippets_size: 2,
pipeline_artifacts_size: 3,
+ build_artifacts_size: 3,
+ packages_size: 6,
uploads_size: 5
)
statistics.reload
- expect(statistics.storage_size).to eq 19
+ expect(statistics.storage_size).to eq 28
end
it 'works during wiki_size backfill' do
diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb
index 8eab50abd8c..a6a56180ce1 100644
--- a/spec/models/project_team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -234,6 +234,20 @@ RSpec.describe ProjectTeam do
expect(project.team.reporter?(user1)).to be(true)
expect(project.team.reporter?(user2)).to be(true)
end
+
+ context 'when `tasks_to_be_done` and `tasks_project_id` are passed' do
+ before do
+ stub_experiments(invite_members_for_task: true)
+ project.team.add_users([user1], :developer, tasks_to_be_done: %w(ci code), tasks_project_id: project.id)
+ end
+
+ it 'creates a member_task with the correct attributes', :aggregate_failures do
+ member = project.project_members.last
+
+ expect(member.tasks_to_be_done).to match_array([:ci, :code])
+ expect(member.member_task.project).to eq(project)
+ end
+ end
end
describe '#add_user' do
diff --git a/spec/models/protectable_dropdown_spec.rb b/spec/models/protectable_dropdown_spec.rb
index 918c3078405..ab3f455fe63 100644
--- a/spec/models/protectable_dropdown_spec.rb
+++ b/spec/models/protectable_dropdown_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe ProtectableDropdown do
describe '#protectable_ref_names' do
context 'when project repository is not empty' do
before do
- project.protected_branches.create(name: 'master')
+ create(:protected_branch, project: project, name: 'master')
end
it { expect(subject.protectable_ref_names).to include('feature') }
diff --git a/spec/models/redirect_route_spec.rb b/spec/models/redirect_route_spec.rb
index c6e35923b89..2de662fd4b4 100644
--- a/spec/models/redirect_route_spec.rb
+++ b/spec/models/redirect_route_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe RedirectRoute do
let(:group) { create(:group) }
- let!(:redirect_route) { group.redirect_routes.create(path: 'gitlabb') }
+ let!(:redirect_route) { group.redirect_routes.create!(path: 'gitlabb') }
describe 'relationships' do
it { is_expected.to belong_to(:source) }
@@ -17,10 +17,10 @@ RSpec.describe RedirectRoute do
end
describe '.matching_path_and_descendants' do
- let!(:redirect2) { group.redirect_routes.create(path: 'gitlabb/test') }
- let!(:redirect3) { group.redirect_routes.create(path: 'gitlabb/test/foo') }
- let!(:redirect4) { group.redirect_routes.create(path: 'gitlabb/test/foo/bar') }
- let!(:redirect5) { group.redirect_routes.create(path: 'gitlabb/test/baz') }
+ let!(:redirect2) { group.redirect_routes.create!(path: 'gitlabb/test') }
+ let!(:redirect3) { group.redirect_routes.create!(path: 'gitlabb/test/foo') }
+ let!(:redirect4) { group.redirect_routes.create!(path: 'gitlabb/test/foo/bar') }
+ let!(:redirect5) { group.redirect_routes.create!(path: 'gitlabb/test/baz') }
context 'when the redirect route matches with same casing' do
it 'returns correct routes' do
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index b88813b3328..125fec61d72 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -26,10 +26,10 @@ RSpec.describe Release do
context 'when a release exists in the database without a name' do
it 'does not require name' do
existing_release_without_name = build(:release, project: project, author: user, name: nil)
- existing_release_without_name.save(validate: false)
+ existing_release_without_name.save!(validate: false)
existing_release_without_name.description = "change"
- existing_release_without_name.save
+ existing_release_without_name.save!
existing_release_without_name.reload
expect(existing_release_without_name).to be_valid
@@ -88,7 +88,7 @@ RSpec.describe Release do
describe '.create' do
it "fills released_at using created_at if it's not set" do
- release = described_class.create(project: project, author: user)
+ release = create(:release, project: project, author: user, released_at: nil)
expect(release.released_at).to eq(release.created_at)
end
@@ -96,14 +96,14 @@ RSpec.describe Release do
it "does not change released_at if it's set explicitly" do
released_at = Time.zone.parse('2018-10-20T18:00:00Z')
- release = described_class.create(project: project, author: user, released_at: released_at)
+ release = create(:release, project: project, author: user, released_at: released_at)
expect(release.released_at).to eq(released_at)
end
end
describe '#update' do
- subject { release.update(params) }
+ subject { release.update!(params) }
context 'when links do not exist' do
context 'when params are specified for creation' do
@@ -182,7 +182,7 @@ RSpec.describe Release do
it 'also deletes the associated evidence' do
release_with_evidence
- expect { release_with_evidence.destroy }.to change(Releases::Evidence, :count).by(-1)
+ expect { release_with_evidence.destroy! }.to change(Releases::Evidence, :count).by(-1)
end
end
end
@@ -190,7 +190,7 @@ RSpec.describe Release do
describe '#name' do
context 'name is nil' do
before do
- release.update(name: nil)
+ release.update!(name: nil)
end
it 'returns tag' do
diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb
index 382359ccb17..9f1d1c84da3 100644
--- a/spec/models/remote_mirror_spec.rb
+++ b/spec/models/remote_mirror_spec.rb
@@ -289,7 +289,7 @@ RSpec.describe RemoteMirror, :mailer do
context 'with remote mirroring disabled' do
it 'returns nil' do
- remote_mirror.update(enabled: false)
+ remote_mirror.update!(enabled: false)
expect(remote_mirror.sync).to be_nil
end
@@ -354,7 +354,7 @@ RSpec.describe RemoteMirror, :mailer do
let(:remote_mirror) { create(:project, :repository, :remote_mirror).remote_mirrors.first }
it 'resets all the columns when URL changes' do
- remote_mirror.update(last_error: Time.current,
+ remote_mirror.update!(last_error: Time.current,
last_update_at: Time.current,
last_successful_update_at: Time.current,
update_status: 'started',
@@ -378,7 +378,7 @@ RSpec.describe RemoteMirror, :mailer do
end
before do
- remote_mirror.update(last_update_started_at: Time.current)
+ remote_mirror.update!(last_update_started_at: Time.current)
end
context 'when remote mirror does not have status failed' do
@@ -393,7 +393,7 @@ RSpec.describe RemoteMirror, :mailer do
context 'when remote mirror has status failed' do
it 'returns false when last update started after the timestamp' do
- remote_mirror.update(update_status: 'failed')
+ remote_mirror.update!(update_status: 'failed')
expect(remote_mirror.updated_since?(timestamp)).to be false
end
@@ -409,7 +409,7 @@ RSpec.describe RemoteMirror, :mailer do
updated_at: 25.hours.ago)
project = mirror.project
project.pending_delete = true
- project.save
+ project.save!
mirror.reload
expect(mirror.sync).to be_nil
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 7bad907cf90..d50c60774b4 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -66,35 +66,58 @@ RSpec.describe Repository do
it { is_expected.not_to include('v1.0.0') }
end
- describe 'tags_sorted_by' do
+ describe '#tags_sorted_by' do
let(:tags_to_compare) { %w[v1.0.0 v1.1.0] }
- let(:feature_flag) { true }
-
- before do
- stub_feature_flags(tags_finder_gitaly: feature_flag)
- end
context 'name_desc' do
subject { repository.tags_sorted_by('name_desc').map(&:name) & tags_to_compare }
it { is_expected.to eq(['v1.1.0', 'v1.0.0']) }
-
- context 'when feature flag is disabled' do
- let(:feature_flag) { false }
-
- it { is_expected.to eq(['v1.1.0', 'v1.0.0']) }
- end
end
context 'name_asc' do
- subject { repository.tags_sorted_by('name_asc').map(&:name) & tags_to_compare }
+ subject { repository.tags_sorted_by('name_asc', pagination_params).map(&:name) & tags_to_compare }
+
+ let(:pagination_params) { nil }
it { is_expected.to eq(['v1.0.0', 'v1.1.0']) }
- context 'when feature flag is disabled' do
- let(:feature_flag) { false }
+ context 'with pagination' do
+ context 'with limit' do
+ let(:pagination_params) { { limit: 1 } }
+
+ it { is_expected.to eq(['v1.0.0']) }
+ end
+
+ context 'with page token and limit' do
+ let(:pagination_params) { { page_token: 'refs/tags/v1.0.0', limit: 1 } }
+
+ it { is_expected.to eq(['v1.1.0']) }
+ end
- it { is_expected.to eq(['v1.0.0', 'v1.1.0']) }
+ context 'with page token only' do
+ let(:pagination_params) { { page_token: 'refs/tags/v1.0.0' } }
+
+ it 'raises an ArgumentError' do
+ expect { subject }.to raise_error(ArgumentError)
+ end
+ end
+
+ context 'with negative limit' do
+ let(:pagination_params) { { limit: -1 } }
+
+ it 'returns all tags' do
+ is_expected.to eq(['v1.0.0', 'v1.1.0'])
+ end
+ end
+
+ context 'with unknown token' do
+ let(:pagination_params) { { page_token: 'unknown' } }
+
+ it 'raises an ArgumentError' do
+ expect { subject }.to raise_error(ArgumentError)
+ end
+ end
end
end
@@ -113,24 +136,12 @@ RSpec.describe Repository do
subject { repository.tags_sorted_by('updated_desc').map(&:name) & (tags_to_compare + [latest_tag]) }
it { is_expected.to eq([latest_tag, 'v1.1.0', 'v1.0.0']) }
-
- context 'when feature flag is disabled' do
- let(:feature_flag) { false }
-
- it { is_expected.to eq([latest_tag, 'v1.1.0', 'v1.0.0']) }
- end
end
context 'asc' do
subject { repository.tags_sorted_by('updated_asc').map(&:name) & (tags_to_compare + [latest_tag]) }
it { is_expected.to eq(['v1.0.0', 'v1.1.0', latest_tag]) }
-
- context 'when feature flag is disabled' do
- let(:feature_flag) { false }
-
- it { is_expected.to eq(['v1.0.0', 'v1.1.0', latest_tag]) }
- end
end
context 'annotated tag pointing to a blob' do
@@ -147,12 +158,6 @@ RSpec.describe Repository do
it { is_expected.to eq(['v1.0.0', 'v1.1.0', annotated_tag_name]) }
- context 'when feature flag is disabled' do
- let(:feature_flag) { false }
-
- it { is_expected.to eq(['v1.0.0', 'v1.1.0', annotated_tag_name]) }
- end
-
after do
rugged_repo(repository).tags.delete(annotated_tag_name)
end
@@ -163,12 +168,6 @@ RSpec.describe Repository do
subject { repository.tags_sorted_by('unknown_desc').map(&:name) & tags_to_compare }
it { is_expected.to eq(['v1.0.0', 'v1.1.0']) }
-
- context 'when feature flag is disabled' do
- let(:feature_flag) { false }
-
- it { is_expected.to eq(['v1.0.0', 'v1.1.0']) }
- end
end
end
diff --git a/spec/models/route_spec.rb b/spec/models/route_spec.rb
index eb81db95cd3..b2fa9c24535 100644
--- a/spec/models/route_spec.rb
+++ b/spec/models/route_spec.rb
@@ -31,18 +31,18 @@ RSpec.describe Route do
context 'after update' do
it 'calls #create_redirect_for_old_path' do
expect(route).to receive(:create_redirect_for_old_path)
- route.update(path: 'foo')
+ route.update!(path: 'foo')
end
it 'calls #delete_conflicting_redirects' do
expect(route).to receive(:delete_conflicting_redirects)
- route.update(path: 'foo')
+ route.update!(path: 'foo')
end
end
context 'after create' do
it 'calls #delete_conflicting_redirects' do
- route.destroy
+ route.destroy!
new_route = described_class.new(source: group, path: group.path)
expect(new_route).to receive(:delete_conflicting_redirects)
new_route.save!
@@ -81,7 +81,7 @@ RSpec.describe Route do
context 'path update' do
context 'when route name is set' do
before do
- route.update(path: 'bar')
+ route.update!(path: 'bar')
end
it 'updates children routes with new path' do
@@ -111,7 +111,7 @@ RSpec.describe Route do
let!(:conflicting_redirect3) { route.create_redirect('gitlab-org') }
it 'deletes the conflicting redirects' do
- route.update(path: 'bar')
+ route.update!(path: 'bar')
expect(RedirectRoute.exists?(path: 'bar/test')).to be_falsey
expect(RedirectRoute.exists?(path: 'bar/test/foo')).to be_falsey
@@ -122,7 +122,7 @@ RSpec.describe Route do
context 'name update' do
it 'updates children routes with new path' do
- route.update(name: 'bar')
+ route.update!(name: 'bar')
expect(described_class.exists?(name: 'bar')).to be_truthy
expect(described_class.exists?(name: 'bar / test')).to be_truthy
@@ -134,7 +134,7 @@ RSpec.describe Route do
# Note: using `update_columns` to skip all validation and callbacks
route.update_columns(name: nil)
- expect { route.update(name: 'bar') }
+ expect { route.update!(name: 'bar') }
.to change { route.name }.from(nil).to('bar')
end
end
diff --git a/spec/models/sentry_issue_spec.rb b/spec/models/sentry_issue_spec.rb
index c24350d7067..09b23b6fd0d 100644
--- a/spec/models/sentry_issue_spec.rb
+++ b/spec/models/sentry_issue_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe SentryIssue do
create(:sentry_issue)
project = sentry_issue.issue.project
sentry_issue_3 = build(:sentry_issue, issue: create(:issue, project: project), sentry_issue_identifier: sentry_issue.sentry_issue_identifier)
- sentry_issue_3.save(validate: false)
+ sentry_issue_3.save!(validate: false)
result = described_class.for_project_and_identifier(project, sentry_issue.sentry_issue_identifier)
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 4e20a83f18e..e24dd910c39 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -98,7 +98,7 @@ RSpec.describe Snippet do
snippet = build(:snippet)
expect(snippet.statistics).to be_nil
- snippet.save
+ snippet.save!
expect(snippet.statistics).to be_persisted
end
@@ -289,7 +289,7 @@ RSpec.describe Snippet do
let(:access_level) { ProjectFeature::ENABLED }
before do
- project.project_feature.update(snippets_access_level: access_level)
+ project.project_feature.update!(snippets_access_level: access_level)
end
it 'includes snippets for projects with snippets enabled' do
@@ -623,7 +623,7 @@ RSpec.describe Snippet do
context 'when snippet_repository does not exist' do
it 'creates a snippet_repository' do
- snippet.snippet_repository.destroy
+ snippet.snippet_repository.destroy!
snippet.reload
expect do
diff --git a/spec/models/suggestion_spec.rb b/spec/models/suggestion_spec.rb
index 9a7624c253a..4f91908264f 100644
--- a/spec/models/suggestion_spec.rb
+++ b/spec/models/suggestion_spec.rb
@@ -154,6 +154,14 @@ RSpec.describe Suggestion do
it { is_expected.to eq("This suggestion already matches its content.") }
end
+ context 'when file is .ipynb' do
+ before do
+ allow(suggestion).to receive(:file_path).and_return("example.ipynb")
+ end
+
+ it { is_expected.to eq(_("This file was modified for readability, and can't accept suggestions. Edit it directly.")) }
+ end
+
context 'when applicable' do
it { is_expected.to be_nil }
end
diff --git a/spec/models/u2f_registration_spec.rb b/spec/models/u2f_registration_spec.rb
index aba2f27d104..7a70cf69566 100644
--- a/spec/models/u2f_registration_spec.rb
+++ b/spec/models/u2f_registration_spec.rb
@@ -5,9 +5,11 @@ require 'spec_helper'
RSpec.describe U2fRegistration do
let_it_be(:user) { create(:user) }
+ let(:u2f_registration_name) { 'u2f_device' }
+
let(:u2f_registration) do
device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5))
- create(:u2f_registration, name: 'u2f_device',
+ create(:u2f_registration, name: u2f_registration_name,
user: user,
certificate: Base64.strict_encode64(device.cert_raw),
key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
@@ -16,11 +18,27 @@ RSpec.describe U2fRegistration do
describe 'callbacks' do
describe '#create_webauthn_registration' do
- it 'creates webauthn registration' do
- u2f_registration.save!
+ shared_examples_for 'creates webauthn registration' do
+ it 'creates webauthn registration' do
+ u2f_registration.save!
+
+ webauthn_registration = WebauthnRegistration.where(u2f_registration_id: u2f_registration.id)
+ expect(webauthn_registration).to exist
+ end
+ end
+
+ it_behaves_like 'creates webauthn registration'
+
+ context 'when the u2f_registration has a blank name' do
+ let(:u2f_registration_name) { '' }
+
+ it_behaves_like 'creates webauthn registration'
+ end
+
+ context 'when the u2f_registration has the name as `nil`' do
+ let(:u2f_registration_name) { nil }
- webauthn_registration = WebauthnRegistration.where(u2f_registration_id: u2f_registration.id)
- expect(webauthn_registration).to exist
+ it_behaves_like 'creates webauthn registration'
end
it 'logs error' do
diff --git a/spec/models/upload_spec.rb b/spec/models/upload_spec.rb
index 0ac684cd04c..cdf73b203af 100644
--- a/spec/models/upload_spec.rb
+++ b/spec/models/upload_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Upload do
it 'schedules checksum calculation' do
stub_const('UploadChecksumWorker', spy)
- upload = described_class.create(
+ upload = described_class.create!(
path: __FILE__,
size: described_class::CHECKSUM_THRESHOLD + 1.kilobyte,
model: build_stubbed(:user),
@@ -42,7 +42,7 @@ RSpec.describe Upload do
store: ObjectStorage::Store::LOCAL
)
- expect { upload.save }
+ expect { upload.save! }
.to change { upload.checksum }.from(nil)
.to(a_string_matching(/\A\h{64}\z/))
end
@@ -55,7 +55,7 @@ RSpec.describe Upload do
it 'calls delete_file!' do
is_expected.to receive(:delete_file!)
- subject.destroy
+ subject.destroy!
end
end
end
@@ -82,6 +82,18 @@ RSpec.describe Upload do
end
end
+ describe '#relative_path' do
+ it "delegates to the uploader's relative_path method" do
+ uploader = spy('FakeUploader')
+ upload = described_class.new(path: '/tmp/secret/file.jpg', store: ObjectStorage::Store::LOCAL)
+ expect(upload).to receive(:uploader_class).and_return(uploader)
+
+ upload.relative_path
+
+ expect(uploader).to have_received(:relative_path).with(upload)
+ end
+ end
+
describe '#calculate_checksum!' do
let(:upload) do
described_class.new(path: __FILE__,
diff --git a/spec/models/uploads/fog_spec.rb b/spec/models/uploads/fog_spec.rb
index 899e6f2064c..1ffe7c6c43b 100644
--- a/spec/models/uploads/fog_spec.rb
+++ b/spec/models/uploads/fog_spec.rb
@@ -40,7 +40,9 @@ RSpec.describe Uploads::Fog do
end
describe '#delete_keys' do
+ let(:connection) { ::Fog::Storage.new(FileUploader.object_store_credentials) }
let(:keys) { data_store.keys(relation) }
+ let(:paths) { relation.pluck(:path) }
let!(:uploads) { create_list(:upload, 2, :with_file, :issuable_upload, model: project) }
subject { data_store.delete_keys(keys) }
@@ -50,17 +52,32 @@ RSpec.describe Uploads::Fog do
end
it 'deletes multiple data' do
- paths = relation.pluck(:path)
+ paths.each do |path|
+ expect(connection.get_object('uploads', path)[:body]).not_to be_nil
+ end
+
+ subject
+
+ paths.each do |path|
+ expect { connection.get_object('uploads', path)[:body] }.to raise_error(Excon::Error::NotFound)
+ end
+ end
- ::Fog::Storage.new(FileUploader.object_store_credentials).tap do |connection|
+ context 'when one of keys is missing' do
+ let(:keys) { ['unknown'] + super() }
+
+ it 'deletes only existing keys' do
paths.each do |path|
expect(connection.get_object('uploads', path)[:body]).not_to be_nil
end
- end
- subject
+ expect_next_instance_of(::Fog::Storage) do |storage|
+ allow(storage).to receive(:delete_object).and_call_original
+ expect(storage).to receive(:delete_object).with('uploads', keys.first).and_raise(::Google::Apis::ClientError, 'NotFound')
+ end
+
+ subject
- ::Fog::Storage.new(FileUploader.object_store_credentials).tap do |connection|
paths.each do |path|
expect { connection.get_object('uploads', path)[:body] }.to raise_error(Excon::Error::NotFound)
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 21c5aea514a..b5d4614d206 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe User do
include ProjectForksHelper
include TermsHelper
include ExclusiveLeaseHelpers
+ include LdapHelpers
it_behaves_like 'having unique enum values'
@@ -98,7 +99,7 @@ RSpec.describe User do
it { is_expected.to have_many(:group_members) }
it { is_expected.to have_many(:groups) }
it { is_expected.to have_many(:keys).dependent(:destroy) }
- it { is_expected.to have_many(:expired_and_unnotified_keys) }
+ it { is_expected.to have_many(:expired_today_and_unnotified_keys) }
it { is_expected.to have_many(:deploy_keys).dependent(:nullify) }
it { is_expected.to have_many(:group_deploy_keys) }
it { is_expected.to have_many(:events).dependent(:delete_all) }
@@ -1123,7 +1124,7 @@ RSpec.describe User do
end
describe 'after commit hook' do
- describe '#update_emails_with_primary_email' do
+ describe 'when the primary email is updated' do
before do
@user = create(:user, email: 'primary@example.com').tap do |user|
user.skip_reconfirmation!
@@ -1132,13 +1133,7 @@ RSpec.describe User do
@user.reload
end
- it 'gets called when email updated' do
- expect(@user).to receive(:update_emails_with_primary_email)
-
- @user.update!(email: 'new_primary@example.com')
- end
-
- it 'adds old primary to secondary emails when secondary is a new email' do
+ it 'keeps old primary to secondary emails when secondary is a new email' do
@user.update!(email: 'new_primary@example.com')
@user.reload
@@ -1146,22 +1141,6 @@ RSpec.describe User do
expect(@user.emails.pluck(:email)).to match_array([@secondary.email, 'primary@example.com'])
end
- it 'adds old primary to secondary emails if secondary is becoming a primary' do
- @user.update!(email: @secondary.email)
- @user.reload
-
- expect(@user.emails.count).to eq 1
- expect(@user.emails.first.email).to eq 'primary@example.com'
- end
-
- it 'transfers old confirmation values into new secondary' do
- @user.update!(email: @secondary.email)
- @user.reload
-
- expect(@user.emails.count).to eq 1
- expect(@user.emails.first.confirmed_at).not_to eq nil
- end
-
context 'when the first email was unconfirmed and the second email gets confirmed' do
let(:user) { create(:user, :unconfirmed, email: 'should-be-unconfirmed@test.com') }
@@ -1178,11 +1157,8 @@ RSpec.describe User do
expect(user).to be_confirmed
end
- it 'keeps the unconfirmed email unconfirmed' do
- email = user.emails.first
-
- expect(email.email).to eq('should-be-unconfirmed@test.com')
- expect(email).not_to be_confirmed
+ it 'does not add unconfirmed email to secondary' do
+ expect(user.emails.map(&:email)).not_to include('should-be-unconfirmed@test.com')
end
it 'has only one email association' do
@@ -1244,7 +1220,7 @@ RSpec.describe User do
expect(user.email).to eq(confirmed_email)
end
- it 'moves the old email' do
+ it 'keeps the old email' do
email = user.reload.emails.first
expect(email.email).to eq(old_confirmed_email)
@@ -1499,7 +1475,7 @@ RSpec.describe User do
allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true)
end
- let(:user) { create(:user, confirmed_at: nil, unconfirmed_email: 'test@gitlab.com') }
+ let(:user) { create(:user, :unconfirmed, unconfirmed_email: 'test@gitlab.com') }
it 'returns unconfirmed' do
expect(user.confirmed?).to be_falsey
@@ -1509,6 +1485,22 @@ RSpec.describe User do
user.confirm
expect(user.confirmed?).to be_truthy
end
+
+ it 'adds the confirmed primary email to emails' do
+ expect(user.emails.confirmed.map(&:email)).not_to include(user.email)
+
+ user.confirm
+
+ expect(user.emails.confirmed.map(&:email)).to include(user.email)
+ end
+ end
+
+ context 'if the user is created with confirmed_at set to a time' do
+ let!(:user) { create(:user, email: 'test@gitlab.com', confirmed_at: Time.now.utc) }
+
+ it 'adds the confirmed primary email to emails upon creation' do
+ expect(user.emails.confirmed.map(&:email)).to include(user.email)
+ end
end
describe '#to_reference' do
@@ -2216,7 +2208,7 @@ RSpec.describe User do
end
context 'primary email not confirmed' do
- let(:user) { create(:user, confirmed_at: nil) }
+ let(:user) { create(:user, :unconfirmed) }
let!(:email) { create(:email, :confirmed, user: user, email: 'foo@example.com') }
it 'finds user respecting the confirmed flag' do
@@ -2231,7 +2223,7 @@ RSpec.describe User do
end
it 'returns nil when user is not confirmed' do
- user = create(:user, email: 'foo@example.com', confirmed_at: nil)
+ user = create(:user, :unconfirmed, email: 'foo@example.com')
expect(described_class.find_by_any_email(user.email, confirmed: false)).to eq(user)
expect(described_class.find_by_any_email(user.email, confirmed: true)).to be_nil
@@ -4155,6 +4147,23 @@ RSpec.describe User do
end
end
+ describe '#remove_project_authorizations' do
+ let_it_be(:project1) { create(:project) }
+ let_it_be(:project2) { create(:project) }
+ let_it_be(:project3) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ it 'removes the project authorizations of the user, in specified projects' do
+ create(:project_authorization, user: user, project: project1)
+ create(:project_authorization, user: user, project: project2)
+ create(:project_authorization, user: user, project: project3)
+
+ user.remove_project_authorizations([project1.id, project2.id])
+
+ expect(user.project_authorizations.pluck(:project_id)).to match_array([project3.id])
+ end
+ end
+
describe '#access_level=' do
let(:user) { build(:user) }
@@ -5817,7 +5826,7 @@ RSpec.describe User do
end
describe '#active_for_authentication?' do
- subject { user.active_for_authentication? }
+ subject(:active_for_authentication?) { user.active_for_authentication? }
let(:user) { create(:user) }
@@ -5827,6 +5836,14 @@ RSpec.describe User do
end
it { is_expected.to be false }
+
+ it 'does not check if LDAP is allowed' do
+ stub_ldap_setting(enabled: true)
+
+ expect(Gitlab::Auth::Ldap::Access).not_to receive(:allowed?)
+
+ active_for_authentication?
+ end
end
context 'when user is a ghost user' do
@@ -5837,6 +5854,28 @@ RSpec.describe User do
it { is_expected.to be false }
end
+ context 'when user is ldap_blocked' do
+ before do
+ user.ldap_block
+ end
+
+ it 'rechecks if LDAP is allowed when LDAP is enabled' do
+ stub_ldap_setting(enabled: true)
+
+ expect(Gitlab::Auth::Ldap::Access).to receive(:allowed?)
+
+ active_for_authentication?
+ end
+
+ it 'does not check if LDAP is allowed when LDAP is not enabled' do
+ stub_ldap_setting(enabled: false)
+
+ expect(Gitlab::Auth::Ldap::Access).not_to receive(:allowed?)
+
+ active_for_authentication?
+ end
+ end
+
context 'based on user type' do
using RSpec::Parameterized::TableSyntax
@@ -6011,7 +6050,7 @@ RSpec.describe User do
subject { user.confirmation_required_on_sign_in? }
context 'when user is confirmed' do
- let(:user) { build_stubbed(:user) }
+ let(:user) { create(:user) }
it 'is falsey' do
expect(user.confirmed?).to be_truthy
@@ -6203,4 +6242,31 @@ RSpec.describe User do
expect(described_class.get_ids_by_username([user_name])).to match_array([user_id])
end
end
+
+ describe 'user_project' do
+ it 'returns users project matched by username and public visibility' do
+ user = create(:user)
+ public_project = create(:project, :public, path: user.username, namespace: user.namespace)
+ create(:project, namespace: user.namespace)
+
+ expect(user.user_project).to eq(public_project)
+ end
+ end
+
+ describe 'user_readme' do
+ it 'returns readme from user project' do
+ user = create(:user)
+ create(:project, :repository, :public, path: user.username, namespace: user.namespace)
+
+ expect(user.user_readme.name).to eq('README.md')
+ expect(user.user_readme.data).to include('testme')
+ end
+
+ it 'returns nil if project is private' do
+ user = create(:user)
+ create(:project, :repository, :private, path: user.username, namespace: user.namespace)
+
+ expect(user.user_readme).to be(nil)
+ end
+ end
end
diff --git a/spec/models/users/credit_card_validation_spec.rb b/spec/models/users/credit_card_validation_spec.rb
index d2b4f5ebd65..43edf7ed093 100644
--- a/spec/models/users/credit_card_validation_spec.rb
+++ b/spec/models/users/credit_card_validation_spec.rb
@@ -6,19 +6,25 @@ RSpec.describe Users::CreditCardValidation do
it { is_expected.to belong_to(:user) }
it { is_expected.to validate_length_of(:holder_name).is_at_most(26) }
+ it { is_expected.to validate_length_of(:network).is_at_most(32) }
it { is_expected.to validate_numericality_of(:last_digits).is_less_than_or_equal_to(9999) }
describe '.similar_records' do
- let(:card_details) { subject.attributes.slice(:expiration_date, :last_digits, :holder_name) }
+ let(:card_details) do
+ subject.attributes.with_indifferent_access.slice(:expiration_date, :last_digits, :network, :holder_name)
+ end
- subject(:credit_card_validation) { create(:credit_card_validation) }
+ subject!(:credit_card_validation) { create(:credit_card_validation, holder_name: 'Alice') }
let!(:match1) { create(:credit_card_validation, card_details) }
- let!(:other1) { create(:credit_card_validation, card_details.merge(last_digits: 9)) }
- let!(:match2) { create(:credit_card_validation, card_details) }
- let!(:other2) { create(:credit_card_validation, card_details.merge(holder_name: 'foo bar')) }
+ let!(:match2) { create(:credit_card_validation, card_details.merge(holder_name: 'Bob')) }
+ let!(:non_match1) { create(:credit_card_validation, card_details.merge(last_digits: 9)) }
+ let!(:non_match2) { create(:credit_card_validation, card_details.merge(network: 'unknown')) }
+ let!(:non_match3) do
+ create(:credit_card_validation, card_details.dup.tap { |h| h[:expiration_date] += 1.year })
+ end
- it 'returns records with matching credit card, ordered by credit_card_validated_at' do
+ it 'returns matches with the same last_digits, expiration and network, ordered by credit_card_validated_at' do
expect(subject.similar_records).to eq([match2, match1, subject])
end
end
diff --git a/spec/models/users/in_product_marketing_email_spec.rb b/spec/models/users/in_product_marketing_email_spec.rb
index a9ddd86677c..cf08cf7ceed 100644
--- a/spec/models/users/in_product_marketing_email_spec.rb
+++ b/spec/models/users/in_product_marketing_email_spec.rb
@@ -21,7 +21,8 @@ RSpec.describe Users::InProductMarketingEmail, type: :model do
describe '.tracks' do
it 'has an entry for every track' do
- expect(Namespaces::InProductMarketingEmailsService::TRACKS.keys).to match_array(described_class.tracks.keys.map(&:to_sym))
+ tracks = [Namespaces::InviteTeamEmailService::TRACK, Namespaces::InProductMarketingEmailsService::TRACKS.keys].flatten
+ expect(tracks).to match_array(described_class.tracks.keys.map(&:to_sym))
end
end
diff --git a/spec/models/users/merge_request_interaction_spec.rb b/spec/models/users/merge_request_interaction_spec.rb
index d333577fa1a..12c7fa43a60 100644
--- a/spec/models/users/merge_request_interaction_spec.rb
+++ b/spec/models/users/merge_request_interaction_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe ::Users::MergeRequestInteraction do
merge_request.reviewers << user
end
- it { is_expected.to eq(Types::MergeRequestReviewStateEnum.values['UNREVIEWED'].value) }
+ it { is_expected.to eq(Types::MergeRequestReviewStateEnum.values['ATTENTION_REQUESTED'].value) }
it 'implies not reviewed' do
expect(interaction).not_to be_reviewed
@@ -70,7 +70,8 @@ RSpec.describe ::Users::MergeRequestInteraction do
context 'when the user has provided a review' do
before do
- merge_request.merge_request_reviewers.create!(reviewer: user, state: MergeRequestReviewer.states['reviewed'])
+ reviewer = merge_request.merge_request_reviewers.create!(reviewer: user)
+ reviewer.update!(state: MergeRequestReviewer.states['reviewed'])
end
it { is_expected.to eq(Types::MergeRequestReviewStateEnum.values['REVIEWED'].value) }
diff --git a/spec/models/users_statistics_spec.rb b/spec/models/users_statistics_spec.rb
index b4b7ddb7c63..8553d0bfdb0 100644
--- a/spec/models/users_statistics_spec.rb
+++ b/spec/models/users_statistics_spec.rb
@@ -34,11 +34,11 @@ RSpec.describe UsersStatistics do
describe '.create_current_stats!' do
before do
- create_list(:user_highest_role, 4)
+ create_list(:user_highest_role, 1)
create_list(:user_highest_role, 2, :guest)
- create_list(:user_highest_role, 3, :reporter)
- create_list(:user_highest_role, 4, :developer)
- create_list(:user_highest_role, 3, :maintainer)
+ create_list(:user_highest_role, 2, :reporter)
+ create_list(:user_highest_role, 2, :developer)
+ create_list(:user_highest_role, 2, :maintainer)
create_list(:user_highest_role, 2, :owner)
create_list(:user, 2, :bot)
create_list(:user, 1, :blocked)
@@ -49,11 +49,11 @@ RSpec.describe UsersStatistics do
context 'when successful' do
it 'creates an entry with the current statistics values' do
expect(described_class.create_current_stats!).to have_attributes(
- without_groups_and_projects: 4,
+ without_groups_and_projects: 1,
with_highest_role_guest: 2,
- with_highest_role_reporter: 3,
- with_highest_role_developer: 4,
- with_highest_role_maintainer: 3,
+ with_highest_role_reporter: 2,
+ with_highest_role_developer: 2,
+ with_highest_role_maintainer: 2,
with_highest_role_owner: 2,
bots: 2,
blocked: 1
diff --git a/spec/models/webauthn_registration_spec.rb b/spec/models/webauthn_registration_spec.rb
new file mode 100644
index 00000000000..6813854bf6c
--- /dev/null
+++ b/spec/models/webauthn_registration_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WebauthnRegistration do
+ describe 'relations' do
+ it { is_expected.to belong_to(:user) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:credential_xid) }
+ it { is_expected.to validate_presence_of(:public_key) }
+ it { is_expected.to validate_presence_of(:counter) }
+ it { is_expected.to validate_length_of(:name).is_at_least(0) }
+ it { is_expected.not_to allow_value(nil).for(:name) }
+ it do
+ is_expected.to validate_numericality_of(:counter)
+ .only_integer
+ .is_greater_than_or_equal_to(0)
+ .is_less_than_or_equal_to(4294967295)
+ end
+ end
+end
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index 201ccf0fc14..fc4fbace790 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -11,8 +11,8 @@ RSpec.describe GroupPolicy do
it do
expect_allowed(:read_group)
- expect_allowed(:read_organization)
- expect_allowed(:read_contact)
+ expect_allowed(:read_crm_organization)
+ expect_allowed(:read_crm_contact)
expect_allowed(:read_counts)
expect_allowed(*read_group_permissions)
expect_disallowed(:upload_file)
@@ -33,8 +33,8 @@ RSpec.describe GroupPolicy do
end
it { expect_disallowed(:read_group) }
- it { expect_disallowed(:read_organization) }
- it { expect_disallowed(:read_contact) }
+ it { expect_disallowed(:read_crm_organization) }
+ it { expect_disallowed(:read_crm_contact) }
it { expect_disallowed(:read_counts) }
it { expect_disallowed(*read_group_permissions) }
end
@@ -48,8 +48,8 @@ RSpec.describe GroupPolicy do
end
it { expect_disallowed(:read_group) }
- it { expect_disallowed(:read_organization) }
- it { expect_disallowed(:read_contact) }
+ it { expect_disallowed(:read_crm_organization) }
+ it { expect_disallowed(:read_crm_contact) }
it { expect_disallowed(:read_counts) }
it { expect_disallowed(*read_group_permissions) }
end
@@ -933,8 +933,8 @@ RSpec.describe GroupPolicy do
it { is_expected.to be_allowed(:read_package) }
it { is_expected.to be_allowed(:read_group) }
- it { is_expected.to be_allowed(:read_organization) }
- it { is_expected.to be_allowed(:read_contact) }
+ it { is_expected.to be_allowed(:read_crm_organization) }
+ it { is_expected.to be_allowed(:read_crm_contact) }
it { is_expected.to be_disallowed(:create_package) }
end
@@ -944,8 +944,8 @@ RSpec.describe GroupPolicy do
it { is_expected.to be_allowed(:create_package) }
it { is_expected.to be_allowed(:read_package) }
it { is_expected.to be_allowed(:read_group) }
- it { is_expected.to be_allowed(:read_organization) }
- it { is_expected.to be_allowed(:read_contact) }
+ it { is_expected.to be_allowed(:read_crm_organization) }
+ it { is_expected.to be_allowed(:read_crm_contact) }
it { is_expected.to be_disallowed(:destroy_package) }
end
@@ -1032,4 +1032,17 @@ RSpec.describe GroupPolicy do
it { is_expected.to be_disallowed(:update_runners_registration_token) }
end
end
+
+ context 'with customer_relations feature flag disabled' do
+ let(:current_user) { owner }
+
+ before do
+ stub_feature_flags(customer_relations: false)
+ end
+
+ it { is_expected.to be_disallowed(:read_crm_contact) }
+ it { is_expected.to be_disallowed(:read_crm_organization) }
+ it { is_expected.to be_disallowed(:admin_crm_contact) }
+ it { is_expected.to be_disallowed(:admin_crm_organization) }
+ end
end
diff --git a/spec/policies/namespaces/project_namespace_policy_spec.rb b/spec/policies/namespaces/project_namespace_policy_spec.rb
index 22f3ccec1f8..5bb38deb498 100644
--- a/spec/policies/namespaces/project_namespace_policy_spec.rb
+++ b/spec/policies/namespaces/project_namespace_policy_spec.rb
@@ -4,7 +4,8 @@ require 'spec_helper'
RSpec.describe NamespacePolicy do
let_it_be(:parent) { create(:namespace) }
- let_it_be(:namespace) { create(:project_namespace, parent: parent) }
+ let_it_be(:project) { create(:project, namespace: parent) }
+ let_it_be(:namespace) { project.project_namespace }
let(:permissions) do
[:owner_access, :create_projects, :admin_namespace, :read_namespace,
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index f36b0a62aa3..2953c198af6 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -104,29 +104,71 @@ RSpec.describe ProjectPolicy do
end
context 'pipeline feature' do
- let(:project) { private_project }
+ let(:project) { private_project }
+ let(:current_user) { developer }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
- before do
- private_project.add_developer(current_user)
+ describe 'for confirmed user' do
+ it 'allows modify pipelines' do
+ expect_allowed(:create_pipeline)
+ expect_allowed(:update_pipeline)
+ expect_allowed(:create_pipeline_schedule)
+ end
end
describe 'for unconfirmed user' do
- let(:current_user) { create(:user, confirmed_at: nil) }
+ let(:current_user) { project.owner.tap { |u| u.update!(confirmed_at: nil) } }
it 'disallows to modify pipelines' do
expect_disallowed(:create_pipeline)
expect_disallowed(:update_pipeline)
+ expect_disallowed(:destroy_pipeline)
expect_disallowed(:create_pipeline_schedule)
end
end
- describe 'for confirmed user' do
- let(:current_user) { developer }
+ describe 'destroy permission' do
+ describe 'for developers' do
+ it 'prevents :destroy_pipeline' do
+ expect(current_user.can?(:destroy_pipeline, pipeline)).to be_falsey
+ end
+ end
- it 'allows modify pipelines' do
- expect_allowed(:create_pipeline)
- expect_allowed(:update_pipeline)
- expect_allowed(:create_pipeline_schedule)
+ describe 'for maintainers' do
+ let(:current_user) { maintainer }
+
+ it 'prevents :destroy_pipeline' do
+ project.add_maintainer(maintainer)
+ expect(current_user.can?(:destroy_pipeline, pipeline)).to be_falsey
+ end
+ end
+
+ describe 'for project owner' do
+ let(:current_user) { project.owner }
+
+ it 'allows :destroy_pipeline' do
+ expect(current_user.can?(:destroy_pipeline, pipeline)).to be_truthy
+ end
+
+ context 'on archived projects' do
+ before do
+ project.update!(archived: true)
+ end
+
+ it 'prevents :destroy_pipeline' do
+ expect(current_user.can?(:destroy_pipeline, pipeline)).to be_falsey
+ end
+ end
+
+ context 'on archived pending_delete projects' do
+ before do
+ project.update!(archived: true, pending_delete: true)
+ end
+
+ it 'allows :destroy_pipeline' do
+ expect(current_user.can?(:destroy_pipeline, pipeline)).to be_truthy
+ end
+ end
end
end
end
@@ -955,6 +997,28 @@ RSpec.describe ProjectPolicy do
end
end
+ context 'infrastructure google cloud feature' do
+ %w(guest reporter developer).each do |role|
+ context role do
+ let(:current_user) { send(role) }
+
+ it 'disallows managing google cloud' do
+ expect_disallowed(:admin_project_google_cloud)
+ end
+ end
+ end
+
+ %w(maintainer owner).each do |role|
+ context role do
+ let(:current_user) { send(role) }
+
+ it 'allows managing google cloud' do
+ expect_allowed(:admin_project_google_cloud)
+ end
+ end
+ end
+ end
+
describe 'design permissions' do
include DesignManagementTestHelpers
diff --git a/spec/presenters/award_emoji_presenter_spec.rb b/spec/presenters/award_emoji_presenter_spec.rb
index 58ee985f165..a23196282a2 100644
--- a/spec/presenters/award_emoji_presenter_spec.rb
+++ b/spec/presenters/award_emoji_presenter_spec.rb
@@ -6,21 +6,22 @@ RSpec.describe AwardEmojiPresenter do
let(:emoji_name) { 'thumbsup' }
let(:award_emoji) { build(:award_emoji, name: emoji_name) }
let(:presenter) { described_class.new(award_emoji) }
+ let(:emoji) { TanukiEmoji.find_by_alpha_code(emoji_name) }
describe '#description' do
- it { expect(presenter.description).to eq Gitlab::Emoji.emojis[emoji_name]['description'] }
+ it { expect(presenter.description).to eq emoji.description }
end
describe '#unicode' do
- it { expect(presenter.unicode).to eq Gitlab::Emoji.emojis[emoji_name]['unicode'] }
+ it { expect(presenter.unicode).to eq emoji.hex }
end
describe '#unicode_version' do
- it { expect(presenter.unicode_version).to eq Gitlab::Emoji.emoji_unicode_version(emoji_name) }
+ it { expect(presenter.unicode_version).to eq('6.0') }
end
describe '#emoji' do
- it { expect(presenter.emoji).to eq Gitlab::Emoji.emojis[emoji_name]['moji'] }
+ it { expect(presenter.emoji).to eq emoji.codepoints }
end
describe 'when presenting an award emoji with an invalid name' do
diff --git a/spec/presenters/blob_presenter_spec.rb b/spec/presenters/blob_presenter_spec.rb
index 466a2b55e76..28e18708eab 100644
--- a/spec/presenters/blob_presenter_spec.rb
+++ b/spec/presenters/blob_presenter_spec.rb
@@ -31,6 +31,20 @@ RSpec.describe BlobPresenter do
it { expect(presenter.replace_path).to eq("/#{project.full_path}/-/create/#{blob.commit_id}/#{blob.path}") }
end
+ describe '#pipeline_editor_path' do
+ context 'when blob is .gitlab-ci.yml' do
+ before do
+ project.repository.create_file(user, '.gitlab-ci.yml', '',
+ message: 'Add a ci file',
+ branch_name: 'main')
+ end
+
+ let(:blob) { repository.blob_at('main', '.gitlab-ci.yml') }
+
+ it { expect(presenter.pipeline_editor_path).to eq("/#{project.full_path}/-/ci/editor?branch_name=#{blob.commit_id}") }
+ end
+ end
+
describe '#ide_edit_path' do
it { expect(presenter.ide_edit_path).to eq("/-/ide/project/#{project.full_path}/edit/HEAD/-/files/ruby/regex.rb") }
end
@@ -121,6 +135,47 @@ RSpec.describe BlobPresenter do
end
end
+ describe '#highlight_transformed' do
+ context 'when blob is ipynb' do
+ let(:blob) { repository.blob_at('f6b7a707', 'files/ipython/markdown-table.ipynb') }
+ let(:git_blob) { blob.__getobj__ }
+
+ before do
+ allow(git_blob).to receive(:transformed_for_diff).and_return(true)
+ end
+
+ it 'uses md as the transformed language' do
+ expect(Gitlab::Highlight).to receive(:highlight).with('files/ipython/markdown-table.ipynb', anything, plain: nil, language: 'md')
+
+ presenter.highlight_transformed
+ end
+
+ it 'transforms the blob' do
+ expect(Gitlab::Highlight).to receive(:highlight).with('files/ipython/markdown-table.ipynb', include("%%"), plain: nil, language: 'md')
+
+ presenter.highlight_transformed
+ end
+ end
+
+ context 'when blob is other file type' do
+ let(:git_blob) { blob.__getobj__ }
+
+ before do
+ allow(git_blob)
+ .to receive(:data)
+ .and_return("line one\nline two\nline 3")
+
+ allow(blob).to receive(:language_from_gitattributes).and_return('ruby')
+ end
+
+ it 'does not transform the file' do
+ expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: nil, language: 'ruby')
+
+ presenter.highlight_transformed
+ end
+ end
+ end
+
describe '#raw_plain_data' do
let(:blob) { repository.blob_at('HEAD', file) }
diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb
index 4422773fec6..b8d0b093a24 100644
--- a/spec/presenters/ci/build_runner_presenter_spec.rb
+++ b/spec/presenters/ci/build_runner_presenter_spec.rb
@@ -259,12 +259,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
describe '#runner_variables' do
subject { presenter.runner_variables }
- let_it_be(:project_with_flag_disabled) { create(:project, :repository) }
- let_it_be(:project_with_flag_enabled) { create(:project, :repository) }
-
- before do
- stub_feature_flags(variable_inside_variable: [project_with_flag_enabled])
- end
+ let_it_be(:project) { create(:project, :repository) }
shared_examples 'returns an array with the expected variables' do
it 'returns an array' do
@@ -276,21 +271,11 @@ RSpec.describe Ci::BuildRunnerPresenter do
end
end
- context 'when FF :variable_inside_variable is disabled' do
- let(:sha) { project_with_flag_disabled.repository.commit.sha }
- let(:pipeline) { create(:ci_pipeline, sha: sha, project: project_with_flag_disabled) }
- let(:build) { create(:ci_build, pipeline: pipeline) }
-
- it_behaves_like 'returns an array with the expected variables'
- end
+ let(:sha) { project.repository.commit.sha }
+ let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
- context 'when FF :variable_inside_variable is enabled' do
- let(:sha) { project_with_flag_enabled.repository.commit.sha }
- let(:pipeline) { create(:ci_pipeline, sha: sha, project: project_with_flag_enabled) }
- let(:build) { create(:ci_build, pipeline: pipeline) }
-
- it_behaves_like 'returns an array with the expected variables'
- end
+ it_behaves_like 'returns an array with the expected variables'
end
describe '#runner_variables subset' do
@@ -305,32 +290,12 @@ RSpec.describe Ci::BuildRunnerPresenter do
create(:ci_pipeline_variable, key: 'C', value: 'value', pipeline: build.pipeline)
end
- context 'when FF :variable_inside_variable is disabled' do
- before do
- stub_feature_flags(variable_inside_variable: false)
- end
-
- it 'returns non-expanded variables' do
- is_expected.to eq [
- { key: 'A', value: 'refA-$B', public: false, masked: false },
- { key: 'B', value: 'refB-$C-$D', public: false, masked: false },
- { key: 'C', value: 'value', public: false, masked: false }
- ]
- end
- end
-
- context 'when FF :variable_inside_variable is enabled' do
- before do
- stub_feature_flags(variable_inside_variable: [build.project])
- end
-
- it 'returns expanded and sorted variables' do
- is_expected.to eq [
- { key: 'C', value: 'value', public: false, masked: false },
- { key: 'B', value: 'refB-value-$D', public: false, masked: false },
- { key: 'A', value: 'refA-refB-value-$D', public: false, masked: false }
- ]
- end
+ it 'returns expanded and sorted variables' do
+ is_expected.to eq [
+ { key: 'C', value: 'value', public: false, masked: false },
+ { key: 'B', value: 'refB-value-$D', public: false, masked: false },
+ { key: 'A', value: 'refA-refB-value-$D', public: false, masked: false }
+ ]
end
end
end
diff --git a/spec/presenters/packages/npm/package_presenter_spec.rb b/spec/presenters/packages/npm/package_presenter_spec.rb
index 65f69d4056b..49046492ab4 100644
--- a/spec/presenters/packages/npm/package_presenter_spec.rb
+++ b/spec/presenters/packages/npm/package_presenter_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe ::Packages::Npm::PackagePresenter do
+ using RSpec::Parameterized::TableSyntax
+
let_it_be(:project) { create(:project) }
let_it_be(:package_name) { "@#{project.root_namespace.path}/test" }
let_it_be(:package1) { create(:npm_package, version: '2.0.4', project: project, name: package_name) }
@@ -13,42 +15,88 @@ RSpec.describe ::Packages::Npm::PackagePresenter do
let(:presenter) { described_class.new(package_name, packages) }
describe '#versions' do
- subject { presenter.versions }
+ let_it_be('package_json') do
+ {
+ 'name': package_name,
+ 'version': '2.0.4',
+ 'deprecated': 'warning!',
+ 'bin': './cli.js',
+ 'directories': ['lib'],
+ 'engines': { 'npm': '^7.5.6' },
+ '_hasShrinkwrap': false,
+ 'dist': {
+ 'tarball': 'http://localhost/tarball.tgz',
+ 'shasum': '1234567890'
+ },
+ 'custom_field': 'foo_bar'
+ }
+ end
- context 'for packages without dependencies' do
- it { is_expected.to be_a(Hash) }
- it { expect(subject[package1.version].with_indifferent_access).to match_schema('public_api/v4/packages/npm_package_version') }
- it { expect(subject[package2.version].with_indifferent_access).to match_schema('public_api/v4/packages/npm_package_version') }
+ let(:presenter) { described_class.new(package_name, packages, include_metadata: include_metadata) }
- ::Packages::DependencyLink.dependency_types.keys.each do |dependency_type|
- it { expect(subject.dig(package1.version, dependency_type)).to be nil }
- it { expect(subject.dig(package2.version, dependency_type)).to be nil }
- end
+ subject { presenter.versions }
- it 'avoids N+1 database queries' do
- check_n_plus_one(:versions) do
- create_list(:npm_package, 5, project: project, name: package_name)
+ where(:has_dependencies, :has_metadatum, :include_metadata) do
+ true | true | true
+ false | true | true
+ true | false | true
+ false | false | true
+
+ # TODO : to remove along with packages_npm_abbreviated_metadata
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/344827
+ true | true | false
+ false | true | false
+ true | false | false
+ false | false | false
+ end
+
+ with_them do
+ if params[:has_dependencies]
+ ::Packages::DependencyLink.dependency_types.keys.each do |dependency_type|
+ let_it_be("package_dependency_link_for_#{dependency_type}") { create(:packages_dependency_link, package: package1, dependency_type: dependency_type) }
end
end
- end
- context 'for packages with dependencies' do
- ::Packages::DependencyLink.dependency_types.keys.each do |dependency_type|
- let_it_be("package_dependency_link_for_#{dependency_type}") { create(:packages_dependency_link, package: package1, dependency_type: dependency_type) }
+ if params[:has_metadatum]
+ let_it_be('package_metadatadum') { create(:npm_metadatum, package: package1, package_json: package_json) }
end
it { is_expected.to be_a(Hash) }
it { expect(subject[package1.version].with_indifferent_access).to match_schema('public_api/v4/packages/npm_package_version') }
it { expect(subject[package2.version].with_indifferent_access).to match_schema('public_api/v4/packages/npm_package_version') }
- ::Packages::DependencyLink.dependency_types.keys.each do |dependency_type|
- it { expect(subject.dig(package1.version, dependency_type.to_s)).to be_any }
+ it { expect(subject[package1.version]['custom_field']).to be_blank }
+
+ context 'dependencies' do
+ ::Packages::DependencyLink.dependency_types.keys.each do |dependency_type|
+ if params[:has_dependencies]
+ it { expect(subject.dig(package1.version, dependency_type.to_s)).to be_any }
+ else
+ it { expect(subject.dig(package1.version, dependency_type)).to be nil }
+ end
+
+ it { expect(subject.dig(package2.version, dependency_type)).to be nil }
+ end
+ end
+
+ context 'metadatum' do
+ ::Packages::Npm::PackagePresenter::PACKAGE_JSON_ALLOWED_FIELDS.each do |metadata_field|
+ if params[:has_metadatum] && params[:include_metadata]
+ it { expect(subject.dig(package1.version, metadata_field)).not_to be nil }
+ else
+ it { expect(subject.dig(package1.version, metadata_field)).to be nil }
+ end
+
+ it { expect(subject.dig(package2.version, metadata_field)).to be nil }
+ end
end
it 'avoids N+1 database queries' do
check_n_plus_one(:versions) do
create_list(:npm_package, 5, project: project, name: package_name).each do |npm_package|
- ::Packages::DependencyLink.dependency_types.keys.each do |dependency_type|
- create(:packages_dependency_link, package: npm_package, dependency_type: dependency_type)
+ if has_dependencies
+ ::Packages::DependencyLink.dependency_types.keys.each do |dependency_type|
+ create(:packages_dependency_link, package: npm_package, dependency_type: dependency_type)
+ end
end
end
end
diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb
index 5f789f59908..27b777dec5f 100644
--- a/spec/presenters/project_presenter_spec.rb
+++ b/spec/presenters/project_presenter_spec.rb
@@ -567,44 +567,27 @@ RSpec.describe ProjectPresenter do
end
describe '#upload_anchor_data' do
- context 'with empty_repo_upload enabled' do
+ context 'when a user can push to the default branch' do
before do
- stub_experiments(empty_repo_upload: :candidate)
- end
-
- context 'user can push to branch' do
- before do
- project.add_developer(user)
- end
-
- it 'returns upload_anchor_data' do
- expect(presenter.upload_anchor_data).to have_attributes(
- is_link: false,
- label: a_string_including('Upload file'),
- data: {
- "can_push_code" => "true",
- "original_branch" => "master",
- "path" => "/#{project.full_path}/-/create/master",
- "project_path" => project.full_path,
- "target_branch" => "master"
- }
- )
- end
+ project.add_developer(user)
end
- context 'user cannot push to branch' do
- it 'returns nil' do
- expect(presenter.upload_anchor_data).to be_nil
- end
+ it 'returns upload_anchor_data' do
+ expect(presenter.upload_anchor_data).to have_attributes(
+ is_link: false,
+ label: a_string_including('Upload file'),
+ data: {
+ "can_push_code" => "true",
+ "original_branch" => "master",
+ "path" => "/#{project.full_path}/-/create/master",
+ "project_path" => project.full_path,
+ "target_branch" => "master"
+ }
+ )
end
end
- context 'with empty_repo_upload disabled' do
- before do
- stub_experiments(empty_repo_upload: :control)
- project.add_developer(user)
- end
-
+ context 'when the user cannot push to default branch' do
it 'returns nil' do
expect(presenter.upload_anchor_data).to be_nil
end
@@ -666,7 +649,6 @@ RSpec.describe ProjectPresenter do
context 'for a developer' do
before do
project.add_developer(user)
- stub_experiments(empty_repo_upload: :candidate)
end
it 'orders the items correctly' do
@@ -680,16 +662,6 @@ RSpec.describe ProjectPresenter do
a_string_including('CI/CD')
)
end
-
- context 'when not in the upload experiment' do
- before do
- stub_experiments(empty_repo_upload: :control)
- end
-
- it 'does not include upload button' do
- expect(empty_repo_statistics_buttons.map(&:label)).not_to start_with(a_string_including('Upload'))
- end
- end
end
end
@@ -781,20 +753,4 @@ RSpec.describe ProjectPresenter do
it { is_expected.to match(/code_quality_walkthrough=true.*template=Code-Quality/) }
end
-
- describe 'empty_repo_upload_experiment?' do
- subject { presenter.empty_repo_upload_experiment? }
-
- it 'returns false when upload_anchor_data is nil' do
- allow(presenter).to receive(:upload_anchor_data).and_return(nil)
-
- expect(subject).to be false
- end
-
- it 'returns true when upload_anchor_data exists' do
- allow(presenter).to receive(:upload_anchor_data).and_return(true)
-
- expect(subject).to be true
- end
- end
end
diff --git a/spec/presenters/release_presenter_spec.rb b/spec/presenters/release_presenter_spec.rb
index b2e7b684644..925a69ca92d 100644
--- a/spec/presenters/release_presenter_spec.rb
+++ b/spec/presenters/release_presenter_spec.rb
@@ -63,12 +63,6 @@ RSpec.describe ReleasePresenter do
it 'returns its own url' do
is_expected.to eq(project_release_url(project, release))
end
-
- context 'when user is guest' do
- let(:user) { guest }
-
- it { is_expected.to be_nil }
- end
end
describe '#opened_merge_requests_url' do
@@ -147,13 +141,5 @@ RSpec.describe ReleasePresenter do
it 'returns the release name' do
is_expected.to eq release.name
end
-
- context "when a user is not allowed to access any repository information" do
- let(:presenter) { described_class.new(release, current_user: guest) }
-
- it 'returns a replacement name to avoid potentially leaking tag information' do
- is_expected.to eq "Release-#{release.id}"
- end
- end
end
end
diff --git a/spec/requests/admin/applications_controller_spec.rb b/spec/requests/admin/applications_controller_spec.rb
new file mode 100644
index 00000000000..03553757080
--- /dev/null
+++ b/spec/requests/admin/applications_controller_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::ApplicationsController, :enable_admin_mode do
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:application) { create(:oauth_application, owner_id: nil, owner_type: nil) }
+ let_it_be(:show_path) { admin_application_path(application) }
+ let_it_be(:create_path) { admin_applications_path }
+
+ before do
+ sign_in(admin)
+ end
+
+ include_examples 'applications controller - GET #show'
+
+ include_examples 'applications controller - POST #create'
+end
diff --git a/spec/requests/api/api_spec.rb b/spec/requests/api/api_spec.rb
index 95eb503c6bc..6a02f81fcae 100644
--- a/spec/requests/api/api_spec.rb
+++ b/spec/requests/api/api_spec.rb
@@ -116,7 +116,7 @@ RSpec.describe API::API do
'meta.root_namespace' => project.namespace.full_path,
'meta.user' => user.username,
'meta.client_id' => a_string_matching(%r{\Auser/.+}),
- 'meta.feature_category' => 'issue_tracking',
+ 'meta.feature_category' => 'team_planning',
'route' => '/api/:version/projects/:id/issues')
end
@@ -200,6 +200,28 @@ RSpec.describe API::API do
expect(response).to have_gitlab_http_status(:not_found)
end
end
+
+ context 'when there is an unhandled exception for an anonymous request' do
+ it 'logs all application context fields and the route' do
+ expect(described_class::LOG_FORMATTER).to receive(:call) do |_severity, _datetime, _, data|
+ expect(data.stringify_keys)
+ .to include('correlation_id' => an_instance_of(String),
+ 'meta.caller_id' => 'GET /api/:version/broadcast_messages',
+ 'meta.remote_ip' => an_instance_of(String),
+ 'meta.client_id' => a_string_matching(%r{\Aip/.+}),
+ 'meta.feature_category' => 'navigation',
+ 'route' => '/api/:version/broadcast_messages')
+
+ expect(data.stringify_keys).not_to include('meta.project', 'meta.root_namespace', 'meta.user')
+ end
+
+ expect(BroadcastMessage).to receive(:all).and_raise('An error!')
+
+ get(api('/broadcast_messages'))
+
+ expect(response).to have_gitlab_http_status(:internal_server_error)
+ end
+ end
end
describe 'Marginalia comments' do
diff --git a/spec/requests/api/ci/jobs_spec.rb b/spec/requests/api/ci/jobs_spec.rb
index b6ab9310471..410020b68cd 100644
--- a/spec/requests/api/ci/jobs_spec.rb
+++ b/spec/requests/api/ci/jobs_spec.rb
@@ -176,6 +176,111 @@ RSpec.describe API::Ci::Jobs do
end
end
+ describe 'GET /job/allowed_agents' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:group_agent) { create(:cluster_agent, project: create(:project, group: group)) }
+ let_it_be(:group_authorization) { create(:agent_group_authorization, agent: group_agent, group: group) }
+ let_it_be(:project_agent) { create(:cluster_agent, project: project) }
+
+ before(:all) do
+ project.update!(group: group_authorization.group)
+ end
+
+ let(:implicit_authorization) { Clusters::Agents::ImplicitAuthorization.new(agent: project_agent) }
+
+ let(:headers) { { API::Ci::Helpers::Runner::JOB_TOKEN_HEADER => job.token } }
+ let(:job) { create(:ci_build, :artifacts, pipeline: pipeline, user: api_user, status: job_status) }
+ let(:job_status) { 'running' }
+ let(:params) { {} }
+
+ subject do
+ get api('/job/allowed_agents'), headers: headers, params: params
+ end
+
+ before do
+ subject
+ end
+
+ context 'when token is valid and user is authorized' do
+ shared_examples_for 'valid allowed_agents request' do
+ it 'returns agent info', :aggregate_failures do
+ expect(response).to have_gitlab_http_status(:ok)
+
+ expect(json_response.dig('job', 'id')).to eq(job.id)
+ expect(json_response.dig('pipeline', 'id')).to eq(job.pipeline_id)
+ expect(json_response.dig('project', 'id')).to eq(job.project_id)
+ expect(json_response.dig('project', 'groups')).to match_array([{ 'id' => group_authorization.group.id }])
+ expect(json_response.dig('user', 'id')).to eq(api_user.id)
+ expect(json_response.dig('user', 'username')).to eq(api_user.username)
+ expect(json_response.dig('user', 'roles_in_project')).to match_array %w(guest reporter developer)
+ expect(json_response).not_to include('environment')
+ expect(json_response['allowed_agents']).to match_array([
+ {
+ 'id' => implicit_authorization.agent_id,
+ 'config_project' => hash_including('id' => implicit_authorization.agent.project_id),
+ 'configuration' => implicit_authorization.config
+ },
+ {
+ 'id' => group_authorization.agent_id,
+ 'config_project' => hash_including('id' => group_authorization.agent.project_id),
+ 'configuration' => group_authorization.config
+ }
+ ])
+ end
+ end
+
+ it_behaves_like 'valid allowed_agents request'
+
+ context 'when deployment' do
+ let(:job) { create(:ci_build, :artifacts, :with_deployment, environment: 'production', pipeline: pipeline, user: api_user, status: job_status) }
+
+ it 'includes environment slug' do
+ expect(json_response.dig('environment', 'slug')).to eq('production')
+ end
+ end
+
+ context 'when passing the token as params' do
+ let(:headers) { {} }
+ let(:params) { { job_token: job.token } }
+
+ it_behaves_like 'valid allowed_agents request'
+ end
+ end
+
+ context 'when user is anonymous' do
+ let(:api_user) { nil }
+
+ it 'returns unauthorized' do
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when token is invalid because job has finished' do
+ let(:job_status) { 'success' }
+
+ it 'returns unauthorized' do
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when token is invalid' do
+ let(:headers) { { API::Ci::Helpers::Runner::JOB_TOKEN_HEADER => 'bad_token' } }
+
+ it 'returns unauthorized' do
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when token is valid but not CI_JOB_TOKEN' do
+ let(:token) { create(:personal_access_token, user: user) }
+ let(:headers) { { 'Private-Token' => token.token } }
+
+ it 'returns not found' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
describe 'GET /projects/:id/jobs' do
let(:query) { {} }
@@ -203,6 +308,7 @@ RSpec.describe API::Ci::Jobs do
it 'returns no artifacts nor trace data' do
json_job = json_response.first
+ expect(response).to have_gitlab_http_status(:ok)
expect(json_job['artifacts_file']).to be_nil
expect(json_job['artifacts']).to be_an Array
expect(json_job['artifacts']).to be_empty
@@ -321,6 +427,22 @@ RSpec.describe API::Ci::Jobs do
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
+
+ context 'when trace artifact record exists with no stored file', :skip_before_request do
+ before do
+ create(:ci_job_artifact, :unarchived_trace_artifact, job: job, project: job.project)
+ end
+
+ it 'returns no artifacts nor trace data' do
+ get api("/projects/#{project.id}/jobs/#{job.id}", api_user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['artifacts']).to be_an Array
+ expect(json_response['artifacts'].size).to eq(1)
+ expect(json_response['artifacts'][0]['file_type']).to eq('trace')
+ expect(json_response['artifacts'][0]['filename']).to eq('job.log')
+ end
+ end
end
describe 'DELETE /projects/:id/jobs/:job_id/artifacts' do
@@ -456,6 +578,7 @@ RSpec.describe API::Ci::Jobs do
expect(response.headers.to_h)
.to include('Content-Type' => 'application/json',
'Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
+ expect(response.parsed_body).to be_empty
end
context 'when artifacts are locked' do
@@ -826,6 +949,7 @@ RSpec.describe API::Ci::Jobs do
expect(response.headers.to_h)
.to include('Content-Type' => 'application/json',
'Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
+ expect(response.parsed_body).to be_empty
end
end
@@ -919,7 +1043,16 @@ RSpec.describe API::Ci::Jobs do
end
end
- context 'when trace is file' do
+ context 'when live trace and uploadless trace artifact' do
+ let(:job) { create(:ci_build, :trace_live, :unarchived_trace_artifact, pipeline: pipeline) }
+
+ it 'returns specific job trace' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq(job.trace.raw)
+ end
+ end
+
+ context 'when trace is live' do
let(:job) { create(:ci_build, :trace_live, pipeline: pipeline) }
it 'returns specific job trace' do
@@ -927,6 +1060,28 @@ RSpec.describe API::Ci::Jobs do
expect(response.body).to eq(job.trace.raw)
end
end
+
+ context 'when no trace' do
+ let(:job) { create(:ci_build, pipeline: pipeline) }
+
+ it 'returns empty trace' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to be_empty
+ end
+ end
+
+ context 'when trace artifact record exists with no stored file' do
+ let(:job) { create(:ci_build, pipeline: pipeline) }
+
+ before do
+ create(:ci_job_artifact, :unarchived_trace_artifact, job: job, project: job.project)
+ end
+
+ it 'returns empty trace' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to be_empty
+ end
+ end
end
context 'unauthorized user' do
@@ -1038,9 +1193,7 @@ RSpec.describe API::Ci::Jobs do
post api("/projects/#{project.id}/jobs/#{job.id}/erase", user)
end
- context 'job is erasable' do
- let(:job) { create(:ci_build, :trace_artifact, :artifacts, :test_reports, :success, project: project, pipeline: pipeline) }
-
+ shared_examples_for 'erases job' do
it 'erases job content' do
expect(response).to have_gitlab_http_status(:created)
expect(job.job_artifacts.count).to eq(0)
@@ -1049,6 +1202,12 @@ RSpec.describe API::Ci::Jobs do
expect(job.artifacts_metadata.present?).to be_falsy
expect(job.has_job_artifacts?).to be_falsy
end
+ end
+
+ context 'job is erasable' do
+ let(:job) { create(:ci_build, :trace_artifact, :artifacts, :test_reports, :success, project: project, pipeline: pipeline) }
+
+ it_behaves_like 'erases job'
it 'updates job' do
job.reload
@@ -1058,6 +1217,12 @@ RSpec.describe API::Ci::Jobs do
end
end
+ context 'when job has an unarchived trace artifact' do
+ let(:job) { create(:ci_build, :success, :trace_live, :unarchived_trace_artifact, project: project, pipeline: pipeline) }
+
+ it_behaves_like 'erases job'
+ end
+
context 'job is not erasable' do
let(:job) { create(:ci_build, :trace_live, project: project, pipeline: pipeline) }
diff --git a/spec/requests/api/ci/runner/jobs_request_post_spec.rb b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
index c3fbef9be48..fdf1a278d4c 100644
--- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
@@ -218,9 +218,11 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(json_response['git_info']).to eq(expected_git_info)
expect(json_response['image']).to eq({ 'name' => 'ruby:2.7', 'entrypoint' => '/bin/sh', 'ports' => [] })
expect(json_response['services']).to eq([{ 'name' => 'postgres', 'entrypoint' => nil,
- 'alias' => nil, 'command' => nil, 'ports' => [] },
+ 'alias' => nil, 'command' => nil, 'ports' => [], 'variables' => nil },
{ 'name' => 'docker:stable-dind', 'entrypoint' => '/bin/sh',
- 'alias' => 'docker', 'command' => 'sleep 30', 'ports' => [] }])
+ 'alias' => 'docker', 'command' => 'sleep 30', 'ports' => [], 'variables' => [] },
+ { 'name' => 'mysql:latest', 'entrypoint' => nil,
+ 'alias' => nil, 'command' => nil, 'ports' => [], 'variables' => [{ 'key' => 'MYSQL_ROOT_PASSWORD', 'value' => 'root123.' }] }])
expect(json_response['steps']).to eq(expected_steps)
expect(json_response['artifacts']).to eq(expected_artifacts)
expect(json_response['cache']).to eq(expected_cache)
diff --git a/spec/requests/api/debian_group_packages_spec.rb b/spec/requests/api/debian_group_packages_spec.rb
index 3e11b480860..d881d4350fb 100644
--- a/spec/requests/api/debian_group_packages_spec.rb
+++ b/spec/requests/api/debian_group_packages_spec.rb
@@ -9,35 +9,36 @@ RSpec.describe API::DebianGroupPackages do
context 'with invalid parameter' do
let(:url) { "/groups/1/-/packages/debian/dists/with+space/InRelease" }
- it_behaves_like 'Debian repository GET request', :bad_request, /^distribution is invalid$/
+ it_behaves_like 'Debian packages GET request', :bad_request, /^distribution is invalid$/
end
describe 'GET groups/:id/-/packages/debian/dists/*distribution/Release.gpg' do
let(:url) { "/groups/#{container.id}/-/packages/debian/dists/#{distribution.codename}/Release.gpg" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^-----BEGIN PGP SIGNATURE-----/
+ it_behaves_like 'Debian packages read endpoint', 'GET', :success, /^-----BEGIN PGP SIGNATURE-----/
end
describe 'GET groups/:id/-/packages/debian/dists/*distribution/Release' do
let(:url) { "/groups/#{container.id}/-/packages/debian/dists/#{distribution.codename}/Release" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^Codename: fixture-distribution\n$/
+ it_behaves_like 'Debian packages read endpoint', 'GET', :success, /^Codename: fixture-distribution\n$/
end
describe 'GET groups/:id/-/packages/debian/dists/*distribution/InRelease' do
let(:url) { "/groups/#{container.id}/-/packages/debian/dists/#{distribution.codename}/InRelease" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^-----BEGIN PGP SIGNED MESSAGE-----/
+ it_behaves_like 'Debian packages read endpoint', 'GET', :success, /^-----BEGIN PGP SIGNED MESSAGE-----/
end
describe 'GET groups/:id/-/packages/debian/dists/*distribution/:component/binary-:architecture/Packages' do
let(:url) { "/groups/#{container.id}/-/packages/debian/dists/#{distribution.codename}/#{component.name}/binary-#{architecture.name}/Packages" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /Description: This is an incomplete Packages file/
+ it_behaves_like 'Debian packages read endpoint', 'GET', :success, /Description: This is an incomplete Packages file/
end
describe 'GET groups/:id/-/packages/debian/pool/:codename/:project_id/:letter/:package_name/:package_version/:file_name' do
let(:url) { "/groups/#{container.id}/-/packages/debian/pool/#{package.debian_distribution.codename}/#{project.id}/#{letter}/#{package.name}/#{package.version}/#{file_name}" }
+ let(:file_name) { params[:file_name] }
using RSpec::Parameterized::TableSyntax
@@ -51,9 +52,7 @@ RSpec.describe API::DebianGroupPackages do
end
with_them do
- include_context 'with file_name', params[:file_name]
-
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, params[:success_body]
+ it_behaves_like 'Debian packages read endpoint', 'GET', :success, params[:success_body]
end
end
end
diff --git a/spec/requests/api/debian_project_packages_spec.rb b/spec/requests/api/debian_project_packages_spec.rb
index d0b0debaf13..bd68bf912e1 100644
--- a/spec/requests/api/debian_project_packages_spec.rb
+++ b/spec/requests/api/debian_project_packages_spec.rb
@@ -9,35 +9,36 @@ RSpec.describe API::DebianProjectPackages do
context 'with invalid parameter' do
let(:url) { "/projects/1/packages/debian/dists/with+space/InRelease" }
- it_behaves_like 'Debian repository GET request', :bad_request, /^distribution is invalid$/
+ it_behaves_like 'Debian packages GET request', :bad_request, /^distribution is invalid$/
end
describe 'GET projects/:id/packages/debian/dists/*distribution/Release.gpg' do
let(:url) { "/projects/#{container.id}/packages/debian/dists/#{distribution.codename}/Release.gpg" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^-----BEGIN PGP SIGNATURE-----/
+ it_behaves_like 'Debian packages read endpoint', 'GET', :success, /^-----BEGIN PGP SIGNATURE-----/
end
describe 'GET projects/:id/packages/debian/dists/*distribution/Release' do
let(:url) { "/projects/#{container.id}/packages/debian/dists/#{distribution.codename}/Release" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^Codename: fixture-distribution\n$/
+ it_behaves_like 'Debian packages read endpoint', 'GET', :success, /^Codename: fixture-distribution\n$/
end
describe 'GET projects/:id/packages/debian/dists/*distribution/InRelease' do
let(:url) { "/projects/#{container.id}/packages/debian/dists/#{distribution.codename}/InRelease" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^-----BEGIN PGP SIGNED MESSAGE-----/
+ it_behaves_like 'Debian packages read endpoint', 'GET', :success, /^-----BEGIN PGP SIGNED MESSAGE-----/
end
describe 'GET projects/:id/packages/debian/dists/*distribution/:component/binary-:architecture/Packages' do
let(:url) { "/projects/#{container.id}/packages/debian/dists/#{distribution.codename}/#{component.name}/binary-#{architecture.name}/Packages" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /Description: This is an incomplete Packages file/
+ it_behaves_like 'Debian packages read endpoint', 'GET', :success, /Description: This is an incomplete Packages file/
end
describe 'GET projects/:id/packages/debian/pool/:codename/:letter/:package_name/:package_version/:file_name' do
let(:url) { "/projects/#{container.id}/packages/debian/pool/#{package.debian_distribution.codename}/#{letter}/#{package.name}/#{package.version}/#{file_name}" }
+ let(:file_name) { params[:file_name] }
using RSpec::Parameterized::TableSyntax
@@ -51,9 +52,7 @@ RSpec.describe API::DebianProjectPackages do
end
with_them do
- include_context 'with file_name', params[:file_name]
-
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, params[:success_body]
+ it_behaves_like 'Debian packages read endpoint', 'GET', :success, params[:success_body]
end
end
@@ -65,13 +64,13 @@ RSpec.describe API::DebianProjectPackages do
context 'with a deb' do
let(:file_name) { 'libsample0_1.2.3~alpha2_amd64.deb' }
- it_behaves_like 'Debian repository write endpoint', 'upload request', :created
+ it_behaves_like 'Debian packages write endpoint', 'upload', :created, nil
end
context 'with a changes file' do
let(:file_name) { 'sample_1.2.3~alpha2_amd64.changes' }
- it_behaves_like 'Debian repository write endpoint', 'upload request', :created
+ it_behaves_like 'Debian packages write endpoint', 'upload', :created, nil
end
end
@@ -80,7 +79,7 @@ RSpec.describe API::DebianProjectPackages do
let(:method) { :put }
let(:url) { "/projects/#{container.id}/packages/debian/#{file_name}/authorize" }
- it_behaves_like 'Debian repository write endpoint', 'upload authorize request', :created
+ it_behaves_like 'Debian packages write endpoint', 'upload authorize', :created, nil
end
end
end
diff --git a/spec/requests/api/deploy_keys_spec.rb b/spec/requests/api/deploy_keys_spec.rb
index a01c66a311c..1daa7c38e04 100644
--- a/spec/requests/api/deploy_keys_spec.rb
+++ b/spec/requests/api/deploy_keys_spec.rb
@@ -8,8 +8,9 @@ RSpec.describe API::DeployKeys do
let_it_be(:admin) { create(:admin) }
let_it_be(:project) { create(:project, creator_id: user.id) }
let_it_be(:project2) { create(:project, creator_id: user.id) }
-
- let(:deploy_key) { create(:deploy_key, public: true) }
+ let_it_be(:project3) { create(:project, creator_id: user.id) }
+ let_it_be(:deploy_key) { create(:deploy_key, public: true) }
+ let_it_be(:deploy_key_private) { create(:deploy_key, public: false) }
let!(:deploy_keys_project) do
create(:deploy_keys_project, project: project, deploy_key: deploy_key)
@@ -33,13 +34,56 @@ RSpec.describe API::DeployKeys do
end
context 'when authenticated as admin' do
+ let_it_be(:pat) { create(:personal_access_token, user: admin) }
+
+ def make_api_request(params = {})
+ get api('/deploy_keys', personal_access_token: pat), params: params
+ end
+
it 'returns all deploy keys' do
- get api('/deploy_keys', admin)
+ make_api_request
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
+ expect(response).to match_response_schema('public_api/v4/deploy_keys')
expect(json_response).to be_an Array
- expect(json_response.first['id']).to eq(deploy_keys_project.deploy_key.id)
+
+ expect(json_response[0]['id']).to eq(deploy_key.id)
+ expect(json_response[1]['id']).to eq(deploy_key_private.id)
+ end
+
+ it 'avoids N+1 database queries', :use_sql_query_cache, :request_store do
+ create(:deploy_keys_project, :write_access, project: project2, deploy_key: deploy_key)
+
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) { make_api_request }
+
+ deploy_key2 = create(:deploy_key, public: true)
+ create(:deploy_keys_project, :write_access, project: project3, deploy_key: deploy_key2)
+
+ expect { make_api_request }.not_to exceed_all_query_limit(control)
+ end
+
+ context 'when `public` parameter is `true`' do
+ it 'only returns public deploy keys' do
+ make_api_request({ public: true })
+
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['id']).to eq(deploy_key.id)
+ end
+ end
+
+ context 'projects_with_write_access' do
+ let!(:deploy_keys_project2) { create(:deploy_keys_project, :write_access, project: project2, deploy_key: deploy_key) }
+ let!(:deploy_keys_project3) { create(:deploy_keys_project, :write_access, project: project3, deploy_key: deploy_key) }
+
+ it 'returns projects with write access' do
+ make_api_request
+
+ response_projects_with_write_access = json_response.first['projects_with_write_access']
+
+ expect(response_projects_with_write_access[0]['id']).to eq(project2.id)
+ expect(response_projects_with_write_access[1]['id']).to eq(project3.id)
+ end
end
end
end
@@ -58,6 +102,7 @@ RSpec.describe API::DeployKeys do
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.first['title']).to eq(deploy_key.title)
+ expect(json_response.first).not_to have_key(:projects_with_write_access)
end
it 'returns multiple deploy keys without N + 1' do
@@ -77,6 +122,7 @@ RSpec.describe API::DeployKeys do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['title']).to eq(deploy_key.title)
+ expect(json_response).not_to have_key(:projects_with_write_access)
end
it 'returns 404 Not Found with invalid ID' do
diff --git a/spec/requests/api/error_tracking/collector_spec.rb b/spec/requests/api/error_tracking/collector_spec.rb
index 7acadeb1287..21e2849fef0 100644
--- a/spec/requests/api/error_tracking/collector_spec.rb
+++ b/spec/requests/api/error_tracking/collector_spec.rb
@@ -24,10 +24,10 @@ RSpec.describe API::ErrorTracking::Collector do
end
RSpec.shared_examples 'successful request' do
- it 'writes to the database and returns no content' do
+ it 'writes to the database and returns OK' do
expect { subject }.to change { ErrorTracking::ErrorEvent.count }.by(1)
- expect(response).to have_gitlab_http_status(:no_content)
+ expect(response).to have_gitlab_http_status(:ok)
end
end
@@ -89,13 +89,27 @@ RSpec.describe API::ErrorTracking::Collector do
context 'transaction request type' do
let(:params) { fixture_file('error_tracking/transaction.txt') }
- it 'does nothing and returns no content' do
+ it 'does nothing and returns ok' do
expect { subject }.not_to change { ErrorTracking::ErrorEvent.count }
- expect(response).to have_gitlab_http_status(:no_content)
+ expect(response).to have_gitlab_http_status(:ok)
end
end
+ context 'gzip body' do
+ let(:headers) do
+ {
+ 'X-Sentry-Auth' => "Sentry sentry_key=#{client_key.public_key}",
+ 'HTTP_CONTENT_ENCODING' => 'gzip',
+ 'CONTENT_TYPE' => 'application/x-sentry-envelope'
+ }
+ end
+
+ let(:params) { ActiveSupport::Gzip.compress(raw_event) }
+
+ it_behaves_like 'successful request'
+ end
+
it_behaves_like 'successful request'
end
@@ -122,6 +136,35 @@ RSpec.describe API::ErrorTracking::Collector do
it_behaves_like 'bad request'
end
+ context 'body with string instead of json' do
+ let(:params) { '"********"' }
+
+ it_behaves_like 'bad request'
+ end
+
+ context 'collector fails with validation error' do
+ before do
+ allow(::ErrorTracking::CollectErrorService)
+ .to receive(:new).and_raise(ActiveRecord::RecordInvalid)
+ end
+
+ it_behaves_like 'bad request'
+ end
+
+ context 'gzip body' do
+ let(:headers) do
+ {
+ 'X-Sentry-Auth' => "Sentry sentry_key=#{client_key.public_key}",
+ 'HTTP_CONTENT_ENCODING' => 'gzip',
+ 'CONTENT_TYPE' => 'application/json'
+ }
+ end
+
+ let(:params) { ActiveSupport::Gzip.compress(raw_event) }
+
+ it_behaves_like 'successful request'
+ end
+
context 'sentry_key as param and empty headers' do
let(:url) { "/error_tracking/collector/api/#{project.id}/store?sentry_key=#{sentry_key}" }
let(:headers) { {} }
diff --git a/spec/requests/api/features_spec.rb b/spec/requests/api/features_spec.rb
index 0e163ec2154..35dba93b766 100644
--- a/spec/requests/api/features_spec.rb
+++ b/spec/requests/api/features_spec.rb
@@ -256,6 +256,21 @@ RSpec.describe API::Features, stub_feature_flags: false do
)
end
+ it 'creates a feature with the given percentage of time if passed a float' do
+ post api("/features/#{feature_name}", admin), params: { value: '0.01' }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'percentage_of_time', 'value' => 0.01 }
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
+
it 'creates a feature with the given percentage of actors if passed an integer' do
post api("/features/#{feature_name}", admin), params: { value: '50', key: 'percentage_of_actors' }
@@ -270,6 +285,21 @@ RSpec.describe API::Features, stub_feature_flags: false do
'definition' => known_feature_flag_definition_hash
)
end
+
+ it 'creates a feature with the given percentage of actors if passed a float' do
+ post api("/features/#{feature_name}", admin), params: { value: '0.01', key: 'percentage_of_actors' }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to match(
+ 'name' => feature_name,
+ 'state' => 'conditional',
+ 'gates' => [
+ { 'key' => 'boolean', 'value' => false },
+ { 'key' => 'percentage_of_actors', 'value' => 0.01 }
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
+ end
end
context 'when the feature exists' do
diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb
index 0b898496dd6..6aa12b6ff48 100644
--- a/spec/requests/api/files_spec.rb
+++ b/spec/requests/api/files_spec.rb
@@ -47,6 +47,15 @@ RSpec.describe API::Files do
"/projects/#{project.id}/repository/files/#{file_path}"
end
+ def expect_to_send_git_blob(url, params)
+ expect(Gitlab::Workhorse).to receive(:send_git_blob)
+
+ get url, params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.parsed_body).to be_empty
+ end
+
context 'http headers' do
it 'converts value into string' do
helper.set_http_headers(test: 1)
@@ -257,11 +266,7 @@ RSpec.describe API::Files do
it 'returns raw file info' do
url = route(file_path) + "/raw"
- expect(Gitlab::Workhorse).to receive(:send_git_blob)
-
- get api(url, api_user, **options), params: params
-
- expect(response).to have_gitlab_http_status(:ok)
+ expect_to_send_git_blob(api(url, api_user, **options), params)
expect(headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
@@ -523,11 +528,8 @@ RSpec.describe API::Files do
it 'returns raw file info' do
url = route(file_path) + "/raw"
- expect(Gitlab::Workhorse).to receive(:send_git_blob)
- get api(url, current_user), params: params
-
- expect(response).to have_gitlab_http_status(:ok)
+ expect_to_send_git_blob(api(url, current_user), params)
end
context 'when ref is not provided' do
@@ -537,39 +539,29 @@ RSpec.describe API::Files do
it 'returns response :ok', :aggregate_failures do
url = route(file_path) + "/raw"
- expect(Gitlab::Workhorse).to receive(:send_git_blob)
- get api(url, current_user), params: {}
-
- expect(response).to have_gitlab_http_status(:ok)
+ expect_to_send_git_blob(api(url, current_user), {})
end
end
it 'returns raw file info for files with dots' do
url = route('.gitignore') + "/raw"
- expect(Gitlab::Workhorse).to receive(:send_git_blob)
- get api(url, current_user), params: params
-
- expect(response).to have_gitlab_http_status(:ok)
+ expect_to_send_git_blob(api(url, current_user), params)
end
it 'returns file by commit sha' do
# This file is deleted on HEAD
file_path = "files%2Fjs%2Fcommit%2Ejs%2Ecoffee"
params[:ref] = "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9"
- expect(Gitlab::Workhorse).to receive(:send_git_blob)
- get api(route(file_path) + "/raw", current_user), params: params
-
- expect(response).to have_gitlab_http_status(:ok)
+ expect_to_send_git_blob(api(route(file_path) + "/raw", current_user), params)
end
it 'sets no-cache headers' do
url = route('.gitignore') + "/raw"
- expect(Gitlab::Workhorse).to receive(:send_git_blob)
- get api(url, current_user), params: params
+ expect_to_send_git_blob(api(url, current_user), params)
expect(response.headers["Cache-Control"]).to eq("max-age=0, private, must-revalidate, no-store, no-cache")
expect(response.headers["Pragma"]).to eq("no-cache")
@@ -633,11 +625,9 @@ RSpec.describe API::Files do
# This file is deleted on HEAD
file_path = "files%2Fjs%2Fcommit%2Ejs%2Ecoffee"
params[:ref] = "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9"
- expect(Gitlab::Workhorse).to receive(:send_git_blob)
+ url = api(route(file_path) + "/raw", personal_access_token: token)
- get api(route(file_path) + "/raw", personal_access_token: token), params: params
-
- expect(response).to have_gitlab_http_status(:ok)
+ expect_to_send_git_blob(url, params)
end
end
end
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
index 7e439a22e4b..2d85d7b9583 100644
--- a/spec/requests/api/generic_packages_spec.rb
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -297,6 +297,37 @@ RSpec.describe API::GenericPackages do
end
end
+ context 'with select' do
+ context 'with a valid value' do
+ context 'package_file' do
+ let(:params) { super().merge(select: 'package_file') }
+
+ it 'returns a package file' do
+ headers = workhorse_headers.merge(auth_header)
+
+ upload_file(params, headers)
+
+ aggregate_failures do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to have_key('id')
+ end
+ end
+ end
+ end
+
+ context 'with an invalid value' do
+ let(:params) { super().merge(select: 'invalid_value') }
+
+ it 'returns a package file' do
+ headers = workhorse_headers.merge(auth_header)
+
+ upload_file(params, headers)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+ end
+
context 'with a status' do
context 'valid status' do
let(:params) { super().merge(status: 'hidden') }
diff --git a/spec/requests/api/graphql/ci/pipelines_spec.rb b/spec/requests/api/graphql/ci/pipelines_spec.rb
index 6587061094d..1f47f678898 100644
--- a/spec/requests/api/graphql/ci/pipelines_spec.rb
+++ b/spec/requests/api/graphql/ci/pipelines_spec.rb
@@ -186,6 +186,69 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
end
end
+ describe '.job_artifacts' do
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:pipeline_job_1) { create(:ci_build, pipeline: pipeline, name: 'Job 1') }
+ let_it_be(:pipeline_job_artifact_1) { create(:ci_job_artifact, job: pipeline_job_1) }
+ let_it_be(:pipeline_job_2) { create(:ci_build, pipeline: pipeline, name: 'Job 2') }
+ let_it_be(:pipeline_job_artifact_2) { create(:ci_job_artifact, job: pipeline_job_2) }
+
+ let(:path) { %i[project pipelines nodes jobArtifacts] }
+
+ let(:query) do
+ %(
+ query {
+ project(fullPath: "#{project.full_path}") {
+ pipelines {
+ nodes {
+ jobArtifacts {
+ name
+ downloadPath
+ fileType
+ }
+ }
+ }
+ }
+ }
+ )
+ end
+
+ before do
+ post_graphql(query, current_user: user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns the job_artifacts of a pipeline' do
+ job_artifacts_graphql_data = graphql_data_at(*path).flatten
+
+ expect(
+ job_artifacts_graphql_data.map { |pip| pip['name'] }
+ ).to contain_exactly(pipeline_job_artifact_1.filename, pipeline_job_artifact_2.filename)
+ end
+
+ it 'avoids N+1 queries' do
+ first_user = create(:user)
+ second_user = create(:user)
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(query, current_user: first_user)
+ end
+
+ pipeline_2 = create(:ci_pipeline, project: project)
+ pipeline_2_job_1 = create(:ci_build, pipeline: pipeline_2, name: 'Pipeline 2 Job 1')
+ create(:ci_job_artifact, job: pipeline_2_job_1)
+ pipeline_2_job_2 = create(:ci_build, pipeline: pipeline_2, name: 'Pipeline 2 Job 2')
+ create(:ci_job_artifact, job: pipeline_2_job_2)
+
+ expect do
+ post_graphql(query, current_user: second_user)
+ end.not_to exceed_query_limit(control_count)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
describe '.jobs(securityReportTypes)' do
let_it_be(:query) do
%(
diff --git a/spec/requests/api/graphql/gitlab_schema_spec.rb b/spec/requests/api/graphql/gitlab_schema_spec.rb
index b41d851439b..8bbeae97f57 100644
--- a/spec/requests/api/graphql/gitlab_schema_spec.rb
+++ b/spec/requests/api/graphql/gitlab_schema_spec.rb
@@ -190,19 +190,18 @@ RSpec.describe 'GitlabSchema configurations' do
let(:query) { File.read(Rails.root.join('spec/fixtures/api/graphql/introspection.graphql')) }
it 'logs the query complexity and depth' do
- analyzer_memo = {
- query_string: query,
- variables: {}.to_s,
- complexity: 181,
- depth: 13,
- duration_s: 7,
- operation_name: 'IntrospectionQuery',
- used_fields: an_instance_of(Array),
- used_deprecated_fields: an_instance_of(Array)
- }
-
expect_any_instance_of(Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer).to receive(:duration).and_return(7)
- expect(Gitlab::GraphqlLogger).to receive(:info).with(analyzer_memo)
+
+ expect(Gitlab::GraphqlLogger).to receive(:info).with(
+ hash_including(
+ trace_type: 'execute_query',
+ "query_analysis.duration_s" => 7,
+ "query_analysis.complexity" => 181,
+ "query_analysis.depth" => 13,
+ "query_analysis.used_deprecated_fields" => an_instance_of(Array),
+ "query_analysis.used_fields" => an_instance_of(Array)
+ )
+ )
post_graphql(query, current_user: nil)
end
diff --git a/spec/requests/api/graphql/group/dependency_proxy_manifests_spec.rb b/spec/requests/api/graphql/group/dependency_proxy_manifests_spec.rb
index 30e704adb92..3527c8183f6 100644
--- a/spec/requests/api/graphql/group/dependency_proxy_manifests_spec.rb
+++ b/spec/requests/api/graphql/group/dependency_proxy_manifests_spec.rb
@@ -116,4 +116,26 @@ RSpec.describe 'getting dependency proxy manifests in a group' do
expect(dependency_proxy_image_count_response).to eq(manifests.size)
end
+
+ describe 'sorting and pagination' do
+ let(:data_path) { ['group', :dependencyProxyManifests] }
+ let(:current_user) { owner }
+
+ context 'with default sorting' do
+ let_it_be(:descending_manifests) { manifests.reverse.map { |manifest| global_id_of(manifest)} }
+
+ it_behaves_like 'sorted paginated query' do
+ let(:sort_param) { '' }
+ let(:first_param) { 2 }
+ let(:all_records) { descending_manifests }
+ end
+ end
+
+ def pagination_query(params)
+ # remove sort since the type does not accept sorting, but be future proof
+ graphql_query_for('group', { 'fullPath' => group.full_path },
+ query_nodes(:dependencyProxyManifests, :id, include_pagination_info: true, args: params.merge(sort: nil))
+ )
+ end
+ end
end
diff --git a/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb b/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb
index 0fd8fdc3f59..322706be119 100644
--- a/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'RunnersRegistrationTokenReset' do
subject
expect(graphql_errors).not_to be_empty
- expect(graphql_errors).to include(a_hash_including('message' => "The resource that you are attempting to access does not exist or you don't have permission to perform this action"))
+ expect(graphql_errors).to include(a_hash_including('message' => Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR))
expect(mutation_response).to be_nil
end
end
diff --git a/spec/requests/api/graphql/mutations/design_management/delete_spec.rb b/spec/requests/api/graphql/mutations/design_management/delete_spec.rb
index e329416faee..1dffb86b344 100644
--- a/spec/requests/api/graphql/mutations/design_management/delete_spec.rb
+++ b/spec/requests/api/graphql/mutations/design_management/delete_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe "deleting designs" do
context 'the designs list contains filenames we cannot find' do
it_behaves_like 'a failed request' do
- let(:designs) { %w/foo bar baz/.map { |fn| OpenStruct.new(filename: fn) } }
+ let(:designs) { %w/foo bar baz/.map { |fn| instance_double('file', filename: fn) } }
let(:the_error) { a_string_matching %r/filenames were not found/ }
end
end
diff --git a/spec/requests/api/graphql/mutations/issues/create_spec.rb b/spec/requests/api/graphql/mutations/issues/create_spec.rb
index 886f3140086..6baed352b37 100644
--- a/spec/requests/api/graphql/mutations/issues/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/create_spec.rb
@@ -48,5 +48,9 @@ RSpec.describe 'Create an issue' do
expect(mutation_response['issue']).to include('discussionLocked' => true)
expect(Issue.last.work_item_type.base_type).to eq('issue')
end
+
+ it_behaves_like 'has spam protection' do
+ let(:mutation_class) { ::Mutations::Issues::Create }
+ end
end
end
diff --git a/spec/requests/api/graphql/mutations/issues/move_spec.rb b/spec/requests/api/graphql/mutations/issues/move_spec.rb
index 5bbaff61edd..20ed16879f6 100644
--- a/spec/requests/api/graphql/mutations/issues/move_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/move_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Moving an issue' do
context 'when the user is not allowed to read source project' do
it 'returns an error' do
- error = "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ error = Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
post_graphql_mutation(mutation, current_user: user)
expect(response).to have_gitlab_http_status(:success)
diff --git a/spec/requests/api/graphql/mutations/issues/set_confidential_spec.rb b/spec/requests/api/graphql/mutations/issues/set_confidential_spec.rb
index 3f804a46992..12ab504da14 100644
--- a/spec/requests/api/graphql/mutations/issues/set_confidential_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/set_confidential_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe 'Setting an issue as confidential' do
end
it 'returns an error if the user is not allowed to update the issue' do
- error = "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ error = Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
post_graphql_mutation(mutation, current_user: create(:user))
expect(graphql_errors).to include(a_hash_including('message' => error))
diff --git a/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb b/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb
new file mode 100644
index 00000000000..3da702c55d7
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb
@@ -0,0 +1,161 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Setting issues crm contacts' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:contacts) { create_list(:contact, 4, group: group) }
+
+ let(:issue) { create(:issue, project: project) }
+ let(:operation_mode) { Types::MutationOperationModeEnum.default_mode }
+ let(:crm_contact_ids) { [global_id_of(contacts[1]), global_id_of(contacts[2])] }
+ let(:does_not_exist_or_no_permission) { "The resource that you are attempting to access does not exist or you don't have permission to perform this action" }
+
+ let(:mutation) do
+ variables = {
+ project_path: issue.project.full_path,
+ iid: issue.iid.to_s,
+ operation_mode: operation_mode,
+ crm_contact_ids: crm_contact_ids
+ }
+
+ graphql_mutation(:issue_set_crm_contacts, variables,
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ issue {
+ customerRelationsContacts {
+ nodes {
+ id
+ }
+ }
+ }
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:issue_set_crm_contacts)
+ end
+
+ before do
+ create(:issue_customer_relations_contact, issue: issue, contact: contacts[0])
+ create(:issue_customer_relations_contact, issue: issue, contact: contacts[1])
+ end
+
+ context 'when the user has no permission' do
+ it 'returns expected error' do
+ error = Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_errors).to include(a_hash_including('message' => error))
+ end
+ end
+
+ context 'when the user has permission' do
+ before do
+ group.add_reporter(user)
+ end
+
+ context 'when the feature is disabled' do
+ before do
+ stub_feature_flags(customer_relations: false)
+ end
+
+ it 'raises expected error' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_errors).to include(a_hash_including('message' => 'Feature disabled'))
+ end
+ end
+
+ context 'replace' do
+ it 'updates the issue with correct contacts' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_data_at(:issue_set_crm_contacts, :issue, :customer_relations_contacts, :nodes, :id))
+ .to match_array([global_id_of(contacts[1]), global_id_of(contacts[2])])
+ end
+ end
+
+ context 'append' do
+ let(:crm_contact_ids) { [global_id_of(contacts[3])] }
+ let(:operation_mode) { Types::MutationOperationModeEnum.enum[:append] }
+
+ it 'updates the issue with correct contacts' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_data_at(:issue_set_crm_contacts, :issue, :customer_relations_contacts, :nodes, :id))
+ .to match_array([global_id_of(contacts[0]), global_id_of(contacts[1]), global_id_of(contacts[3])])
+ end
+ end
+
+ context 'remove' do
+ let(:crm_contact_ids) { [global_id_of(contacts[0])] }
+ let(:operation_mode) { Types::MutationOperationModeEnum.enum[:remove] }
+
+ it 'updates the issue with correct contacts' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_data_at(:issue_set_crm_contacts, :issue, :customer_relations_contacts, :nodes, :id))
+ .to match_array([global_id_of(contacts[1])])
+ end
+ end
+
+ context 'when the contact does not exist' do
+ let(:crm_contact_ids) { ["gid://gitlab/CustomerRelations::Contact/#{non_existing_record_id}"] }
+
+ it 'returns expected error' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_data_at(:issue_set_crm_contacts, :errors))
+ .to match_array(["Issue customer relations contacts #{non_existing_record_id}: #{does_not_exist_or_no_permission}"])
+ end
+ end
+
+ context 'when the contact belongs to a different group' do
+ let(:group2) { create(:group) }
+ let(:contact) { create(:contact, group: group2) }
+ let(:crm_contact_ids) { [global_id_of(contact)] }
+
+ before do
+ group2.add_reporter(user)
+ end
+
+ it 'returns expected error' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_data_at(:issue_set_crm_contacts, :errors))
+ .to match_array(["Issue customer relations contacts #{contact.id}: #{does_not_exist_or_no_permission}"])
+ end
+ end
+
+ context 'when attempting to add more than 6' do
+ let(:operation_mode) { Types::MutationOperationModeEnum.enum[:append] }
+ let(:gid) { global_id_of(contacts[0]) }
+ let(:crm_contact_ids) { [gid, gid, gid, gid, gid, gid, gid] }
+
+ it 'returns expected error' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_data_at(:issue_set_crm_contacts, :errors))
+ .to match_array(["You can only add up to 6 contacts at one time"])
+ end
+ end
+
+ context 'when trying to remove non-existent contact' do
+ let(:operation_mode) { Types::MutationOperationModeEnum.enum[:remove] }
+ let(:crm_contact_ids) { ["gid://gitlab/CustomerRelations::Contact/#{non_existing_record_id}"] }
+
+ it 'raises expected error' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_data_at(:issue_set_crm_contacts, :errors)).to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb b/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb
index 72e47a98373..8e223b6fdaf 100644
--- a/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe 'Setting Due Date of an issue' do
end
it 'returns an error if the user is not allowed to update the issue' do
- error = "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ error = Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
post_graphql_mutation(mutation, current_user: create(:user))
expect(graphql_errors).to include(a_hash_including('message' => error))
diff --git a/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb b/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb
index 41997f151a2..cd9d695bd2c 100644
--- a/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe 'Setting severity level of an incident' do
context 'when the user is not allowed to update the incident' do
it 'returns an error' do
- error = "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ error = Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
post_graphql_mutation(mutation, current_user: user)
expect(response).to have_gitlab_http_status(:success)
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_draft_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_draft_spec.rb
new file mode 100644
index 00000000000..bea2365eaa6
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_draft_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Setting Draft status of a merge request' do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user) }
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.project }
+ let(:input) { { draft: true } }
+
+ let(:mutation) do
+ variables = {
+ project_path: project.full_path,
+ iid: merge_request.iid.to_s
+ }
+ graphql_mutation(:merge_request_set_draft, variables.merge(input),
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ mergeRequest {
+ id
+ title
+ }
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:merge_request_set_draft)
+ end
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ it 'returns an error if the user is not allowed to update the merge request' do
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ end
+
+ it 'marks the merge request as Draft' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['mergeRequest']['title']).to start_with('Draft:')
+ end
+
+ it 'does not do anything if the merge request was already marked `Draft`' do
+ merge_request.update!(title: 'draft: hello world')
+
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['mergeRequest']['title']).to start_with('draft:')
+ end
+
+ context 'when passing Draft false as input' do
+ let(:input) { { draft: false } }
+
+ it 'does not do anything if the merge reqeust was not marked draft' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['mergeRequest']['title']).not_to start_with(/draft\:/)
+ end
+
+ it 'unmarks the merge request as `Draft`' do
+ merge_request.update!(title: 'draft: hello world')
+
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['mergeRequest']['title']).not_to start_with('/draft\:/')
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb
deleted file mode 100644
index 2143abd3031..00000000000
--- a/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Setting Draft status of a merge request' do
- include GraphqlHelpers
-
- let(:current_user) { create(:user) }
- let(:merge_request) { create(:merge_request) }
- let(:project) { merge_request.project }
- let(:input) { { wip: true } }
-
- let(:mutation) do
- variables = {
- project_path: project.full_path,
- iid: merge_request.iid.to_s
- }
- graphql_mutation(:merge_request_set_wip, variables.merge(input),
- <<-QL.strip_heredoc
- clientMutationId
- errors
- mergeRequest {
- id
- title
- }
- QL
- )
- end
-
- def mutation_response
- graphql_mutation_response(:merge_request_set_wip)
- end
-
- before do
- project.add_developer(current_user)
- end
-
- it 'returns an error if the user is not allowed to update the merge request' do
- post_graphql_mutation(mutation, current_user: create(:user))
-
- expect(graphql_errors).not_to be_empty
- end
-
- it 'marks the merge request as Draft' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_response['mergeRequest']['title']).to start_with('Draft:')
- end
-
- it 'does not do anything if the merge request was already marked `Draft`' do
- merge_request.update!(title: 'draft: hello world')
-
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_response['mergeRequest']['title']).to start_with('draft:')
- end
-
- context 'when passing Draft false as input' do
- let(:input) { { wip: false } }
-
- it 'does not do anything if the merge reqeust was not marked draft' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_response['mergeRequest']['title']).not_to start_with(/draft\:/)
- end
-
- it 'unmarks the merge request as `Draft`' do
- merge_request.update!(title: 'draft: hello world')
-
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_response['mergeRequest']['title']).not_to start_with('/draft\:/')
- end
- end
-end
diff --git a/spec/requests/api/graphql/mutations/merge_requests/update_reviewer_state_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/update_reviewer_state_spec.rb
new file mode 100644
index 00000000000..cf497cb2579
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/merge_requests/update_reviewer_state_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Toggle attention requested for reviewer' do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user) }
+ let(:merge_request) { create(:merge_request, reviewers: [user]) }
+ let(:project) { merge_request.project }
+ let(:user) { create(:user) }
+ let(:input) { { user_id: global_id_of(user) } }
+
+ let(:mutation) do
+ variables = {
+ project_path: project.full_path,
+ iid: merge_request.iid.to_s
+ }
+ graphql_mutation(:merge_request_toggle_attention_requested, variables.merge(input),
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:merge_request_toggle_attention_requested)
+ end
+
+ def mutation_errors
+ mutation_response['errors']
+ end
+
+ before do
+ project.add_developer(current_user)
+ project.add_developer(user)
+ end
+
+ it 'returns an error if the user is not allowed to update the merge request' do
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ end
+
+ describe 'reviewer does not exist' do
+ let(:input) { { user_id: global_id_of(create(:user)) } }
+
+ it 'returns an error' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_errors).not_to be_empty
+ end
+ end
+
+ describe 'reviewer exists' do
+ it 'does not return an error' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_errors).to be_empty
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/releases/create_spec.rb b/spec/requests/api/graphql/mutations/releases/create_spec.rb
index a4918cd560c..86995c10f10 100644
--- a/spec/requests/api/graphql/mutations/releases/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/releases/create_spec.rb
@@ -342,7 +342,7 @@ RSpec.describe 'Creation of a new release' do
end
context "when the current user doesn't have access to create releases" do
- expected_error_message = "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ expected_error_message = Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
context 'when the current user is a Reporter' do
let(:current_user) { reporter }
diff --git a/spec/requests/api/graphql/mutations/releases/delete_spec.rb b/spec/requests/api/graphql/mutations/releases/delete_spec.rb
index 40063156609..eb4f0b594ea 100644
--- a/spec/requests/api/graphql/mutations/releases/delete_spec.rb
+++ b/spec/requests/api/graphql/mutations/releases/delete_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe 'Deleting a release' do
expect(mutation_response).to be_nil
expect(graphql_errors.count).to eq(1)
- expect(graphql_errors.first['message']).to eq("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
+ expect(graphql_errors.first['message']).to eq(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
end
end
diff --git a/spec/requests/api/graphql/mutations/releases/update_spec.rb b/spec/requests/api/graphql/mutations/releases/update_spec.rb
index c9a6c3abd57..0fa3d7de299 100644
--- a/spec/requests/api/graphql/mutations/releases/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/releases/update_spec.rb
@@ -218,13 +218,13 @@ RSpec.describe 'Updating an existing release' do
context 'when the project does not exist' do
let(:mutation_arguments) { super().merge(projectPath: 'not/a/real/path') }
- it_behaves_like 'top-level error with message', "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ it_behaves_like 'top-level error with message', Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
end
end
end
context "when the current user doesn't have access to update releases" do
- expected_error_message = "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ expected_error_message = Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
context 'when the current user is a Reporter' do
let(:current_user) { reporter }
diff --git a/spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb b/spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb
new file mode 100644
index 00000000000..929609d4160
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/security/ci_configuration/configure_sast_iac_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'ConfigureSastIac' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :test_repo) }
+
+ let(:variables) { { project_path: project.full_path } }
+ let(:mutation) { graphql_mutation(:configure_sast_iac, variables) }
+ let(:mutation_response) { graphql_mutation_response(:configureSastIac) }
+
+ context 'when authorized' do
+ let_it_be(:user) { project.owner }
+
+ it 'creates a branch with sast iac configured' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['errors']).to be_empty
+ expect(mutation_response['branch']).not_to be_empty
+ expect(mutation_response['successPath']).not_to be_empty
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/namespace_query_spec.rb b/spec/requests/api/graphql/namespace_query_spec.rb
new file mode 100644
index 00000000000..f7ee2bcb55d
--- /dev/null
+++ b/spec/requests/api/graphql/namespace_query_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Query' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:other_user) { create(:user) }
+
+ let_it_be(:group_namespace) { create(:group) }
+ let_it_be(:user_namespace) { create(:user_namespace, owner: user) }
+ let_it_be(:project_namespace) { create(:project_namespace, parent: group_namespace) }
+
+ describe '.namespace' do
+ subject { post_graphql(query, current_user: current_user) }
+
+ let(:current_user) { user }
+
+ let(:query) { graphql_query_for(:namespace, { 'fullPath' => target_namespace.full_path }, all_graphql_fields_for('Namespace')) }
+ let(:query_result) { graphql_data['namespace'] }
+
+ shared_examples 'retrieving a namespace' do
+ context 'authorised query' do
+ before do
+ subject
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'fetches the expected data' do
+ expect(query_result).to include(
+ 'fullPath' => target_namespace.full_path,
+ 'name' => target_namespace.name
+ )
+ end
+ end
+
+ context 'unauthorised query' do
+ before do
+ subject
+ end
+
+ context 'anonymous user' do
+ let(:current_user) { nil }
+
+ it 'does not retrieve the record' do
+ expect(query_result).to be_nil
+ end
+ end
+
+ context 'the current user does not have permission' do
+ let(:current_user) { other_user }
+
+ it 'does not retrieve the record' do
+ expect(query_result).to be_nil
+ end
+ end
+ end
+ end
+
+ it_behaves_like 'retrieving a namespace' do
+ let(:target_namespace) { group_namespace }
+
+ before do
+ group_namespace.add_developer(user)
+ end
+ end
+
+ it_behaves_like 'retrieving a namespace' do
+ let(:target_namespace) { user_namespace }
+ end
+
+ context 'does not retrieve project namespace' do
+ let(:target_namespace) { project_namespace }
+
+ before do
+ subject
+ end
+
+ it 'does not retrieve the record' do
+ expect(query_result).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/packages/helm_spec.rb b/spec/requests/api/graphql/packages/helm_spec.rb
new file mode 100644
index 00000000000..397096f70db
--- /dev/null
+++ b/spec/requests/api/graphql/packages/helm_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'helm package details' do
+ include GraphqlHelpers
+ include_context 'package details setup'
+
+ let_it_be(:package) { create(:helm_package, project: project) }
+
+ let(:package_files_metadata) {query_graphql_fragment('HelmFileMetadata')}
+
+ let(:query) do
+ graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
+ #{all_graphql_fields_for('PackageDetailsType', max_depth: depth, excluded: excluded)}
+ packageFiles {
+ nodes {
+ #{package_files}
+ fileMetadata {
+ #{package_files_metadata}
+ }
+ }
+ }
+ FIELDS
+ end
+
+ subject { post_graphql(query, current_user: user) }
+
+ before do
+ subject
+ end
+
+ it_behaves_like 'a package detail'
+ it_behaves_like 'a package with files'
+
+ it 'has the correct file metadata' do
+ expect(first_file_response_metadata).to include(
+ 'channel' => first_file.helm_file_metadatum.channel
+ )
+ expect(first_file_response_metadata['metadata']).to include(
+ 'name' => first_file.helm_file_metadatum.metadata['name'],
+ 'home' => first_file.helm_file_metadatum.metadata['home'],
+ 'sources' => first_file.helm_file_metadatum.metadata['sources'],
+ 'version' => first_file.helm_file_metadatum.metadata['version'],
+ 'description' => first_file.helm_file_metadatum.metadata['description'],
+ 'keywords' => first_file.helm_file_metadatum.metadata['keywords'],
+ 'maintainers' => first_file.helm_file_metadatum.metadata['maintainers'],
+ 'icon' => first_file.helm_file_metadatum.metadata['icon'],
+ 'apiVersion' => first_file.helm_file_metadatum.metadata['apiVersion'],
+ 'condition' => first_file.helm_file_metadatum.metadata['condition'],
+ 'tags' => first_file.helm_file_metadatum.metadata['tags'],
+ 'appVersion' => first_file.helm_file_metadatum.metadata['appVersion'],
+ 'deprecated' => first_file.helm_file_metadatum.metadata['deprecated'],
+ 'annotations' => first_file.helm_file_metadatum.metadata['annotations'],
+ 'kubeVersion' => first_file.helm_file_metadatum.metadata['kubeVersion'],
+ 'dependencies' => first_file.helm_file_metadatum.metadata['dependencies'],
+ 'type' => first_file.helm_file_metadatum.metadata['type']
+ )
+ end
+end
diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb
index 1c6d6ce4707..b3e91afb5b3 100644
--- a/spec/requests/api/graphql/project/issues_spec.rb
+++ b/spec/requests/api/graphql/project/issues_spec.rb
@@ -429,11 +429,11 @@ RSpec.describe 'getting an issue list for a project' do
end
it 'avoids N+1 queries' do
- create(:contact, group_id: group.id, issues: [issue_a])
+ create(:issue_customer_relations_contact, :for_issue, issue: issue_a)
control = ActiveRecord::QueryRecorder.new(skip_cached: false) { clean_state_query }
- create(:contact, group_id: group.id, issues: [issue_a])
+ create(:issue_customer_relations_contact, :for_issue, issue: issue_a)
expect { clean_state_query }.not_to exceed_all_query_limit(control)
end
diff --git a/spec/requests/api/graphql/project/merge_request_spec.rb b/spec/requests/api/graphql/project/merge_request_spec.rb
index 438ea9bb4c1..353bf0356f6 100644
--- a/spec/requests/api/graphql/project/merge_request_spec.rb
+++ b/spec/requests/api/graphql/project/merge_request_spec.rb
@@ -347,7 +347,7 @@ RSpec.describe 'getting merge request information nested in a project' do
expect(interaction_data).to contain_exactly a_hash_including(
'canMerge' => false,
'canUpdate' => can_update,
- 'reviewState' => unreviewed,
+ 'reviewState' => attention_requested,
'reviewed' => false,
'approved' => false
)
@@ -380,8 +380,8 @@ RSpec.describe 'getting merge request information nested in a project' do
describe 'scalability' do
let_it_be(:other_users) { create_list(:user, 3) }
- let(:unreviewed) do
- { 'reviewState' => 'UNREVIEWED' }
+ let(:attention_requested) do
+ { 'reviewState' => 'ATTENTION_REQUESTED' }
end
let(:reviewed) do
@@ -413,9 +413,9 @@ RSpec.describe 'getting merge request information nested in a project' do
expect { post_graphql(query) }.not_to exceed_query_limit(baseline)
expect(interaction_data).to contain_exactly(
- include(unreviewed),
- include(unreviewed),
- include(unreviewed),
+ include(attention_requested),
+ include(attention_requested),
+ include(attention_requested),
include(reviewed)
)
end
@@ -444,7 +444,7 @@ RSpec.describe 'getting merge request information nested in a project' do
it_behaves_like 'when requesting information about MR interactions' do
let(:field) { :reviewers }
- let(:unreviewed) { 'UNREVIEWED' }
+ let(:attention_requested) { 'ATTENTION_REQUESTED' }
let(:can_update) { false }
def assign_user(user)
@@ -454,7 +454,7 @@ RSpec.describe 'getting merge request information nested in a project' do
it_behaves_like 'when requesting information about MR interactions' do
let(:field) { :assignees }
- let(:unreviewed) { nil }
+ let(:attention_requested) { nil }
let(:can_update) { true } # assignees can update MRs
def assign_user(user)
diff --git a/spec/requests/api/graphql/project/release_spec.rb b/spec/requests/api/graphql/project/release_spec.rb
index 7f24d051457..77abac4ef04 100644
--- a/spec/requests/api/graphql/project/release_spec.rb
+++ b/spec/requests/api/graphql/project/release_spec.rb
@@ -228,6 +228,189 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
end
end
+ shared_examples 'restricted access to release fields' do
+ describe 'scalar fields' do
+ let(:path) { path_prefix }
+
+ let(:release_fields) do
+ %{
+ tagName
+ tagPath
+ description
+ descriptionHtml
+ name
+ createdAt
+ releasedAt
+ upcomingRelease
+ }
+ end
+
+ before do
+ post_query
+ end
+
+ it 'finds all release data' do
+ expect(data).to eq({
+ 'tagName' => release.tag,
+ 'tagPath' => nil,
+ 'description' => release.description,
+ 'descriptionHtml' => release.description_html,
+ 'name' => release.name,
+ 'createdAt' => release.created_at.iso8601,
+ 'releasedAt' => release.released_at.iso8601,
+ 'upcomingRelease' => false
+ })
+ end
+ end
+
+ describe 'milestones' do
+ let(:path) { path_prefix + %w[milestones nodes] }
+
+ let(:release_fields) do
+ query_graphql_field(:milestones, nil, 'nodes { id title }')
+ end
+
+ it 'finds milestones associated to a release' do
+ post_query
+
+ expected = release.milestones.order_by_dates_and_title.map do |milestone|
+ { 'id' => global_id_of(milestone), 'title' => milestone.title }
+ end
+
+ expect(data).to eq(expected)
+ end
+ end
+
+ describe 'author' do
+ let(:path) { path_prefix + %w[author] }
+
+ let(:release_fields) do
+ query_graphql_field(:author, nil, 'id username')
+ end
+
+ it 'finds the author of the release' do
+ post_query
+
+ expect(data).to eq(
+ 'id' => global_id_of(release.author),
+ 'username' => release.author.username
+ )
+ end
+ end
+
+ describe 'commit' do
+ let(:path) { path_prefix + %w[commit] }
+
+ let(:release_fields) do
+ query_graphql_field(:commit, nil, 'sha')
+ end
+
+ it 'restricts commit associated with the release' do
+ post_query
+
+ expect(data).to eq(nil)
+ end
+ end
+
+ describe 'assets' do
+ describe 'count' do
+ let(:path) { path_prefix + %w[assets] }
+
+ let(:release_fields) do
+ query_graphql_field(:assets, nil, 'count')
+ end
+
+ it 'returns non source release links count' do
+ post_query
+
+ expect(data).to eq('count' => release.assets_count(except: [:sources]))
+ end
+ end
+
+ describe 'links' do
+ let(:path) { path_prefix + %w[assets links nodes] }
+
+ let(:release_fields) do
+ query_graphql_field(:assets, nil,
+ query_graphql_field(:links, nil, 'nodes { id name url external, directAssetUrl }'))
+ end
+
+ it 'finds all non source external release links' do
+ post_query
+
+ expected = release.links.map do |link|
+ {
+ 'id' => global_id_of(link),
+ 'name' => link.name,
+ 'url' => link.url,
+ 'external' => true,
+ 'directAssetUrl' => link.filepath ? Gitlab::Routing.url_helpers.project_release_url(project, release) << "/downloads#{link.filepath}" : link.url
+ }
+ end
+
+ expect(data).to match_array(expected)
+ end
+ end
+
+ describe 'sources' do
+ let(:path) { path_prefix + %w[assets sources nodes] }
+
+ let(:release_fields) do
+ query_graphql_field(:assets, nil,
+ query_graphql_field(:sources, nil, 'nodes { format url }'))
+ end
+
+ it 'restricts release sources' do
+ post_query
+
+ expect(data).to match_array([])
+ end
+ end
+ end
+
+ describe 'links' do
+ let(:path) { path_prefix + %w[links] }
+
+ let(:release_fields) do
+ query_graphql_field(:links, nil, %{
+ selfUrl
+ openedMergeRequestsUrl
+ mergedMergeRequestsUrl
+ closedMergeRequestsUrl
+ openedIssuesUrl
+ closedIssuesUrl
+ })
+ end
+
+ it 'finds only selfUrl' do
+ post_query
+
+ expect(data).to eq(
+ 'selfUrl' => project_release_url(project, release),
+ 'openedMergeRequestsUrl' => nil,
+ 'mergedMergeRequestsUrl' => nil,
+ 'closedMergeRequestsUrl' => nil,
+ 'openedIssuesUrl' => nil,
+ 'closedIssuesUrl' => nil
+ )
+ end
+ end
+
+ describe 'evidences' do
+ let(:path) { path_prefix + %w[evidences] }
+
+ let(:release_fields) do
+ query_graphql_field(:evidences, nil, 'nodes { id sha filepath collectedAt }')
+ end
+
+ it 'restricts all evidence fields' do
+ post_query
+
+ expect(data).to eq('nodes' => [])
+ end
+ end
+ end
+
shared_examples 'no access to the release field' do
describe 'repository-related fields' do
let(:path) { path_prefix }
@@ -302,7 +485,8 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
context 'when the user has Guest permissions' do
let(:current_user) { guest }
- it_behaves_like 'no access to the release field'
+ it_behaves_like 'restricted access to release fields'
+ it_behaves_like 'no access to editUrl'
end
context 'when the user has Reporter permissions' do
diff --git a/spec/requests/api/graphql/project/releases_spec.rb b/spec/requests/api/graphql/project/releases_spec.rb
index 2816ce90a6b..c28a6fa7666 100644
--- a/spec/requests/api/graphql/project/releases_spec.rb
+++ b/spec/requests/api/graphql/project/releases_spec.rb
@@ -129,10 +129,12 @@ RSpec.describe 'Query.project(fullPath).releases()' do
end
it 'does not return data for fields that expose repository information' do
+ tag_name = release.tag
+ release_name = release.name
expect(data).to eq(
- 'tagName' => nil,
+ 'tagName' => tag_name,
'tagPath' => nil,
- 'name' => "Release-#{release.id}",
+ 'name' => release_name,
'commit' => nil,
'assets' => {
'count' => release.assets_count(except: [:sources]),
@@ -143,7 +145,14 @@ RSpec.describe 'Query.project(fullPath).releases()' do
'evidences' => {
'nodes' => []
},
- 'links' => nil
+ 'links' => {
+ 'closedIssuesUrl' => nil,
+ 'closedMergeRequestsUrl' => nil,
+ 'mergedMergeRequestsUrl' => nil,
+ 'openedIssuesUrl' => nil,
+ 'openedMergeRequestsUrl' => nil,
+ 'selfUrl' => project_release_url(project, release)
+ }
)
end
end
diff --git a/spec/requests/api/graphql_spec.rb b/spec/requests/api/graphql_spec.rb
index 7d182a3414b..b8f7af29a9f 100644
--- a/spec/requests/api/graphql_spec.rb
+++ b/spec/requests/api/graphql_spec.rb
@@ -12,21 +12,33 @@ RSpec.describe 'GraphQL' do
describe 'logging' do
shared_examples 'logging a graphql query' do
- let(:expected_params) do
+ let(:expected_execute_query_log) do
{
- query_string: query,
- variables: variables.to_s,
- duration_s: anything,
+ "correlation_id" => kind_of(String),
+ "meta.caller_id" => "graphql:anonymous",
+ "meta.client_id" => kind_of(String),
+ "meta.feature_category" => "not_owned",
+ "meta.remote_ip" => kind_of(String),
+ "query_analysis.duration_s" => kind_of(Numeric),
+ "query_analysis.depth" => 1,
+ "query_analysis.complexity" => 1,
+ "query_analysis.used_fields" => ['Query.echo'],
+ "query_analysis.used_deprecated_fields" => [],
+ # query_fingerprint starts with operation name
+ query_fingerprint: %r{^anonymous\/},
+ duration_s: kind_of(Numeric),
+ trace_type: 'execute_query',
operation_name: nil,
- depth: 1,
- complexity: 1,
- used_fields: ['Query.echo'],
- used_deprecated_fields: []
+ # operation_fingerprint starts with operation name
+ operation_fingerprint: %r{^anonymous\/},
+ is_mutation: false,
+ variables: variables.to_s,
+ query_string: query
}
end
it 'logs a query with the expected params' do
- expect(Gitlab::GraphqlLogger).to receive(:info).with(expected_params).once
+ expect(Gitlab::GraphqlLogger).to receive(:info).with(expected_execute_query_log).once
post_graphql(query, variables: variables)
end
diff --git a/spec/requests/api/group_debian_distributions_spec.rb b/spec/requests/api/group_debian_distributions_spec.rb
index ec1912b72bf..21c5f2f09a0 100644
--- a/spec/requests/api/group_debian_distributions_spec.rb
+++ b/spec/requests/api/group_debian_distributions_spec.rb
@@ -11,19 +11,25 @@ RSpec.describe API::GroupDebianDistributions do
let(:url) { "/groups/#{container.id}/-/debian_distributions" }
let(:api_params) { { 'codename': 'my-codename' } }
- it_behaves_like 'Debian repository write endpoint', 'POST distribution request', :created, /^{.*"codename":"my-codename",.*"components":\["main"\],.*"architectures":\["all","amd64"\]/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions write endpoint', 'POST', :created, /^{.*"codename":"my-codename",.*"components":\["main"\],.*"architectures":\["all","amd64"\]/
end
describe 'GET groups/:id/-/debian_distributions' do
let(:url) { "/groups/#{container.id}/-/debian_distributions" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^\[{.*"codename":"existing-codename",.*"components":\["existing-component"\],.*"architectures":\["all","existing-arch"\]/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions read endpoint', 'GET', :success, /^\[{.*"codename":"existing-codename",.*"components":\["existing-component"\],.*"architectures":\["all","existing-arch"\]/
end
describe 'GET groups/:id/-/debian_distributions/:codename' do
let(:url) { "/groups/#{container.id}/-/debian_distributions/#{distribution.codename}" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^{.*"codename":"existing-codename",.*"components":\["existing-component"\],.*"architectures":\["all","existing-arch"\]/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions read endpoint', 'GET', :success, /^{.*"codename":"existing-codename",.*"components":\["existing-component"\],.*"architectures":\["all","existing-arch"\]/
+ end
+
+ describe 'GET groups/:id/-/debian_distributions/:codename/key.asc' do
+ let(:url) { "/groups/#{container.id}/-/debian_distributions/#{distribution.codename}/key.asc" }
+
+ it_behaves_like 'Debian distributions read endpoint', 'GET', :success, /^-----BEGIN PGP PUBLIC KEY BLOCK-----/
end
describe 'PUT groups/:id/-/debian_distributions/:codename' do
@@ -31,14 +37,14 @@ RSpec.describe API::GroupDebianDistributions do
let(:url) { "/groups/#{container.id}/-/debian_distributions/#{distribution.codename}" }
let(:api_params) { { suite: 'my-suite' } }
- it_behaves_like 'Debian repository write endpoint', 'PUT distribution request', :success, /^{.*"codename":"existing-codename",.*"suite":"my-suite",/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions write endpoint', 'PUT', :success, /^{.*"codename":"existing-codename",.*"suite":"my-suite",/
end
describe 'DELETE groups/:id/-/debian_distributions/:codename' do
let(:method) { :delete }
let(:url) { "/groups/#{container.id}/-/debian_distributions/#{distribution.codename}" }
- it_behaves_like 'Debian repository maintainer write endpoint', 'DELETE distribution request', :success, /^{"message":"202 Accepted"}$/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions maintainer write endpoint', 'DELETE', :success, /^{"message":"202 Accepted"}$/
end
end
end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index cee727ae6fe..75f5a974d22 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -319,12 +319,15 @@ RSpec.describe API::Groups do
it "includes statistics if requested" do
attributes = {
- storage_size: 2392,
+ storage_size: 4093,
repository_size: 123,
wiki_size: 456,
lfs_objects_size: 234,
build_artifacts_size: 345,
- snippets_size: 1234
+ pipeline_artifacts_size: 456,
+ packages_size: 567,
+ snippets_size: 1234,
+ uploads_size: 678
}.stringify_keys
exposed_attributes = attributes.dup
exposed_attributes['job_artifacts_size'] = exposed_attributes.delete('build_artifacts_size')
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index aeca4e435f4..0a71eb43f81 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -948,7 +948,7 @@ RSpec.describe API::Internal::Base do
context 'user does not exist' do
it do
- pull(OpenStruct.new(id: 0), project)
+ pull(double('key', id: 0), project)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response["status"]).to be_falsey
diff --git a/spec/requests/api/invitations_spec.rb b/spec/requests/api/invitations_spec.rb
index b23ba0021e0..cba4256adc5 100644
--- a/spec/requests/api/invitations_spec.rb
+++ b/spec/requests/api/invitations_spec.rb
@@ -166,6 +166,38 @@ RSpec.describe API::Invitations do
end
end
+ context 'with tasks_to_be_done and tasks_project_id in the params' do
+ before do
+ stub_experiments(invite_members_for_task: true)
+ end
+
+ let(:project_id) { source_type == 'project' ? source.id : create(:project, namespace: source).id }
+
+ context 'when there is 1 invitation' do
+ it 'creates a member_task with the tasks_to_be_done and the project' do
+ post invitations_url(source, maintainer),
+ params: { email: email, access_level: Member::DEVELOPER, tasks_to_be_done: %w(code ci), tasks_project_id: project_id }
+
+ member = source.members.find_by(invite_email: email)
+ expect(member.tasks_to_be_done).to match_array([:code, :ci])
+ expect(member.member_task.project_id).to eq(project_id)
+ end
+ end
+
+ context 'when there are multiple invitations' do
+ it 'creates a member_task with the tasks_to_be_done and the project' do
+ post invitations_url(source, maintainer),
+ params: { email: [email, email2].join(','), access_level: Member::DEVELOPER, tasks_to_be_done: %w(code ci), tasks_project_id: project_id }
+
+ members = source.members.where(invite_email: [email, email2])
+ members.each do |member|
+ expect(member.tasks_to_be_done).to match_array([:code, :ci])
+ expect(member.member_task.project_id).to eq(project_id)
+ end
+ end
+ end
+ end
+
context 'with invite_source considerations', :snowplow do
let(:params) { { email: email, access_level: Member::DEVELOPER } }
diff --git a/spec/requests/api/lint_spec.rb b/spec/requests/api/lint_spec.rb
index d7f22b9d619..ac30da99afe 100644
--- a/spec/requests/api/lint_spec.rb
+++ b/spec/requests/api/lint_spec.rb
@@ -102,6 +102,13 @@ RSpec.describe API::Lint do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to have_key('merged_yaml')
end
+
+ it 'outputs jobs' do
+ post api('/ci/lint', api_user), params: { content: yaml_content, include_jobs: true }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to have_key('jobs')
+ end
end
context 'with valid .gitlab-ci.yaml with warnings' do
@@ -136,6 +143,13 @@ RSpec.describe API::Lint do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to have_key('merged_yaml')
end
+
+ it 'outputs jobs' do
+ post api('/ci/lint', api_user), params: { content: yaml_content, include_jobs: true }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to have_key('jobs')
+ end
end
context 'with invalid configuration' do
@@ -156,6 +170,13 @@ RSpec.describe API::Lint do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to have_key('merged_yaml')
end
+
+ it 'outputs jobs' do
+ post api('/ci/lint', api_user), params: { content: yaml_content, include_jobs: true }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to have_key('jobs')
+ end
end
end
@@ -171,10 +192,11 @@ RSpec.describe API::Lint do
end
describe 'GET /projects/:id/ci/lint' do
- subject(:ci_lint) { get api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run } }
+ subject(:ci_lint) { get api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run, include_jobs: include_jobs } }
let(:project) { create(:project, :repository) }
let(:dry_run) { nil }
+ let(:include_jobs) { nil }
RSpec.shared_examples 'valid config with warnings' do
it 'passes validation with warnings' do
@@ -359,6 +381,30 @@ RSpec.describe API::Lint do
it_behaves_like 'valid config without warnings'
end
+ context 'when running with include jobs' do
+ let(:include_jobs) { true }
+
+ it_behaves_like 'valid config without warnings'
+
+ it 'returns jobs key' do
+ ci_lint
+
+ expect(json_response).to have_key('jobs')
+ end
+ end
+
+ context 'when running without include jobs' do
+ let(:include_jobs) { false }
+
+ it_behaves_like 'valid config without warnings'
+
+ it 'does not return jobs key' do
+ ci_lint
+
+ expect(json_response).not_to have_key('jobs')
+ end
+ end
+
context 'With warnings' do
let(:yaml_content) { { job: { script: 'ls', rules: [{ when: 'always' }] } }.to_yaml }
@@ -386,15 +432,40 @@ RSpec.describe API::Lint do
it_behaves_like 'invalid config'
end
+
+ context 'when running with include jobs' do
+ let(:include_jobs) { true }
+
+ it_behaves_like 'invalid config'
+
+ it 'returns jobs key' do
+ ci_lint
+
+ expect(json_response).to have_key('jobs')
+ end
+ end
+
+ context 'when running without include jobs' do
+ let(:include_jobs) { false }
+
+ it_behaves_like 'invalid config'
+
+ it 'does not return jobs key' do
+ ci_lint
+
+ expect(json_response).not_to have_key('jobs')
+ end
+ end
end
end
end
describe 'POST /projects/:id/ci/lint' do
- subject(:ci_lint) { post api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run, content: yaml_content } }
+ subject(:ci_lint) { post api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run, content: yaml_content, include_jobs: include_jobs } }
let(:project) { create(:project, :repository) }
let(:dry_run) { nil }
+ let(:include_jobs) { nil }
let_it_be(:api_user) { create(:user) }
@@ -562,6 +633,30 @@ RSpec.describe API::Lint do
it_behaves_like 'valid project config'
end
+
+ context 'when running with include jobs param' do
+ let(:include_jobs) { true }
+
+ it_behaves_like 'valid project config'
+
+ it 'contains jobs key' do
+ ci_lint
+
+ expect(json_response).to have_key('jobs')
+ end
+ end
+
+ context 'when running without include jobs param' do
+ let(:include_jobs) { false }
+
+ it_behaves_like 'valid project config'
+
+ it 'does not contain jobs key' do
+ ci_lint
+
+ expect(json_response).not_to have_key('jobs')
+ end
+ end
end
context 'with invalid .gitlab-ci.yml content' do
@@ -580,6 +675,30 @@ RSpec.describe API::Lint do
it_behaves_like 'invalid project config'
end
+
+ context 'when running with include jobs set to false' do
+ let(:include_jobs) { false }
+
+ it_behaves_like 'invalid project config'
+
+ it 'does not contain jobs key' do
+ ci_lint
+
+ expect(json_response).not_to have_key('jobs')
+ end
+ end
+
+ context 'when running with param include jobs' do
+ let(:include_jobs) { true }
+
+ it_behaves_like 'invalid project config'
+
+ it 'contains jobs key' do
+ ci_lint
+
+ expect(json_response).to have_key('jobs')
+ end
+ end
end
end
end
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index a1daf86de31..7f4345faabb 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -81,14 +81,22 @@ RSpec.describe API::Members do
expect(json_response.map { |u| u['id'] }).to match_array [maintainer.id, developer.id]
end
- it 'finds members with query string' do
- get api(members_url, developer), params: { query: maintainer.username }
+ context 'with cross db check disabled' do
+ around do |example|
+ allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/343305') do
+ example.run
+ end
+ end
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.count).to eq(1)
- expect(json_response.first['username']).to eq(maintainer.username)
+ it 'finds members with query string' do
+ get api(members_url, developer), params: { query: maintainer.username }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.count).to eq(1)
+ expect(json_response.first['username']).to eq(maintainer.username)
+ end
end
it 'finds members with the given user_ids' do
@@ -406,6 +414,38 @@ RSpec.describe API::Members do
end
end
+ context 'with tasks_to_be_done and tasks_project_id in the params' do
+ before do
+ stub_experiments(invite_members_for_task: true)
+ end
+
+ let(:project_id) { source_type == 'project' ? source.id : create(:project, namespace: source).id }
+
+ context 'when there is 1 user to add' do
+ it 'creates a member_task with the correct attributes' do
+ post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
+ params: { user_id: stranger.id, access_level: Member::DEVELOPER, tasks_to_be_done: %w(code ci), tasks_project_id: project_id }
+
+ member = source.members.find_by(user_id: stranger.id)
+ expect(member.tasks_to_be_done).to match_array([:code, :ci])
+ expect(member.member_task.project_id).to eq(project_id)
+ end
+ end
+
+ context 'when there are multiple users to add' do
+ it 'creates a member_task with the correct attributes' do
+ post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
+ params: { user_id: [developer.id, stranger.id].join(','), access_level: Member::DEVELOPER, tasks_to_be_done: %w(code ci), tasks_project_id: project_id }
+
+ members = source.members.where(user_id: [developer.id, stranger.id])
+ members.each do |member|
+ expect(member.tasks_to_be_done).to match_array([:code, :ci])
+ expect(member.member_task.project_id).to eq(project_id)
+ end
+ end
+ end
+ end
+
it "returns 409 if member already exists" do
post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
params: { user_id: maintainer.id, access_level: Member::MAINTAINER }
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index bdbc73a59d8..7c147419354 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -3278,6 +3278,8 @@ RSpec.describe API::MergeRequests do
context 'when skip_ci parameter is set' do
it 'enqueues a rebase of the merge request with skip_ci flag set' do
+ allow(RebaseWorker).to receive(:with_status).and_return(RebaseWorker)
+
expect(RebaseWorker).to receive(:perform_async).with(merge_request.id, user.id, true).and_call_original
Sidekiq::Testing.fake! do
diff --git a/spec/requests/api/namespaces_spec.rb b/spec/requests/api/namespaces_spec.rb
index 222d8992d1b..01dbf523071 100644
--- a/spec/requests/api/namespaces_spec.rb
+++ b/spec/requests/api/namespaces_spec.rb
@@ -3,10 +3,12 @@
require 'spec_helper'
RSpec.describe API::Namespaces do
- let(:admin) { create(:admin) }
- let(:user) { create(:user) }
- let!(:group1) { create(:group, name: 'group.one') }
- let!(:group2) { create(:group, :nested) }
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group1) { create(:group, name: 'group.one') }
+ let_it_be(:group2) { create(:group, :nested) }
+ let_it_be(:project) { create(:project, namespace: group2, name: group2.name, path: group2.path) }
+ let_it_be(:project_namespace) { project.project_namespace }
describe "GET /namespaces" do
context "when unauthenticated" do
@@ -26,7 +28,7 @@ RSpec.describe API::Namespaces do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(group_kind_json_response.keys).to include('id', 'kind', 'name', 'path', 'full_path',
- 'parent_id', 'members_count_with_descendants')
+ 'parent_id', 'members_count_with_descendants')
expect(user_kind_json_response.keys).to include('id', 'kind', 'name', 'path', 'full_path', 'parent_id')
end
@@ -37,7 +39,8 @@ RSpec.describe API::Namespaces do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.length).to eq(Namespace.count)
+ # project namespace is excluded
+ expect(json_response.length).to eq(Namespace.count - 1)
end
it "admin: returns an array of matched namespaces" do
@@ -61,7 +64,7 @@ RSpec.describe API::Namespaces do
owned_group_response = json_response.find { |resource| resource['id'] == group1.id }
expect(owned_group_response.keys).to include('id', 'kind', 'name', 'path', 'full_path',
- 'parent_id', 'members_count_with_descendants')
+ 'parent_id', 'members_count_with_descendants')
end
it "returns correct attributes when user cannot admin group" do
@@ -109,7 +112,8 @@ RSpec.describe API::Namespaces do
describe 'GET /namespaces/:id' do
let(:owned_group) { group1 }
- let(:user2) { create(:user) }
+
+ let_it_be(:user2) { create(:user) }
shared_examples 'can access namespace' do
it 'returns namespace details' do
@@ -144,6 +148,16 @@ RSpec.describe API::Namespaces do
it_behaves_like 'can access namespace'
end
+
+ context 'when requesting project_namespace' do
+ let(:namespace_id) { project_namespace.id }
+
+ it 'returns not-found' do
+ get api("/namespaces/#{namespace_id}", request_actor)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
end
context 'when requested by path' do
@@ -159,6 +173,16 @@ RSpec.describe API::Namespaces do
it_behaves_like 'can access namespace'
end
+
+ context 'when requesting project_namespace' do
+ let(:namespace_id) { project_namespace.full_path }
+
+ it 'returns not-found' do
+ get api("/namespaces/#{namespace_id}", request_actor)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
end
end
@@ -177,6 +201,12 @@ RSpec.describe API::Namespaces do
expect(response).to have_gitlab_http_status(:unauthorized)
end
+
+ it 'returns authentication error' do
+ get api("/namespaces/#{project_namespace.id}")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
end
context 'when authenticated as regular user' do
@@ -231,10 +261,10 @@ RSpec.describe API::Namespaces do
end
describe 'GET /namespaces/:namespace/exists' do
- let!(:namespace1) { create(:group, name: 'Namespace 1', path: 'namespace-1') }
- let!(:namespace2) { create(:group, name: 'Namespace 2', path: 'namespace-2') }
- let!(:namespace1sub) { create(:group, name: 'Sub Namespace 1', path: 'sub-namespace-1', parent: namespace1) }
- let!(:namespace2sub) { create(:group, name: 'Sub Namespace 2', path: 'sub-namespace-2', parent: namespace2) }
+ let_it_be(:namespace1) { create(:group, name: 'Namespace 1', path: 'namespace-1') }
+ let_it_be(:namespace2) { create(:group, name: 'Namespace 2', path: 'namespace-2') }
+ let_it_be(:namespace1sub) { create(:group, name: 'Sub Namespace 1', path: 'sub-namespace-1', parent: namespace1) }
+ let_it_be(:namespace2sub) { create(:group, name: 'Sub Namespace 2', path: 'sub-namespace-2', parent: namespace2) }
context 'when unauthenticated' do
it 'returns authentication error' do
@@ -242,6 +272,16 @@ RSpec.describe API::Namespaces do
expect(response).to have_gitlab_http_status(:unauthorized)
end
+
+ context 'when requesting project_namespace' do
+ let(:namespace_id) { project_namespace.id }
+
+ it 'returns authentication error' do
+ get api("/namespaces/#{project_namespace.path}/exists"), params: { parent_id: group2.id }
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
end
context 'when authenticated' do
@@ -300,6 +340,18 @@ RSpec.describe API::Namespaces do
expect(response).to have_gitlab_http_status(:ok)
expect(response.body).to eq(expected_json)
end
+
+ context 'when requesting project_namespace' do
+ let(:namespace_id) { project_namespace.id }
+
+ it 'returns JSON indicating the namespace does not exist without a suggestion' do
+ get api("/namespaces/#{project_namespace.path}/exists", user), params: { parent_id: group2.id }
+
+ expected_json = { exists: false, suggests: [] }.to_json
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq(expected_json)
+ end
+ end
end
end
end
diff --git a/spec/requests/api/npm_project_packages_spec.rb b/spec/requests/api/npm_project_packages_spec.rb
index 0d04c2cad5b..7c3f1890095 100644
--- a/spec/requests/api/npm_project_packages_spec.rb
+++ b/spec/requests/api/npm_project_packages_spec.rb
@@ -180,6 +180,7 @@ RSpec.describe API::NpmProjectPackages do
.to change { project.packages.count }.by(1)
.and change { Packages::PackageFile.count }.by(1)
.and change { Packages::Tag.count }.by(1)
+ .and change { Packages::Npm::Metadatum.count }.by(1)
expect(response).to have_gitlab_http_status(:ok)
end
@@ -317,6 +318,25 @@ RSpec.describe API::NpmProjectPackages do
end
end
end
+
+ context 'with a too large metadata structure' do
+ let(:package_name) { "@#{group.path}/my_package_name" }
+ let(:params) do
+ upload_params(package_name: package_name, package_version: '1.2.3').tap do |h|
+ h['versions']['1.2.3']['test'] = 'test' * 10000
+ end
+ end
+
+ it_behaves_like 'not a package tracking event'
+
+ it 'returns an error' do
+ expect { upload_package_with_token }
+ .not_to change { project.packages.count }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.body).to include('Validation failed: Package json structure is too large')
+ end
+ end
end
def upload_package(package_name, params = {})
diff --git a/spec/requests/api/project_attributes.yml b/spec/requests/api/project_attributes.yml
index dd00d413664..01d2fb18f00 100644
--- a/spec/requests/api/project_attributes.yml
+++ b/spec/requests/api/project_attributes.yml
@@ -137,6 +137,7 @@ project_setting:
unexposed_attributes:
- created_at
- has_confluence
+ - has_shimo
- has_vulnerabilities
- prevent_merge_without_jira_issue
- warn_about_potentially_unwanted_characters
diff --git a/spec/requests/api/project_debian_distributions_spec.rb b/spec/requests/api/project_debian_distributions_spec.rb
index de7362758f7..2b993f24046 100644
--- a/spec/requests/api/project_debian_distributions_spec.rb
+++ b/spec/requests/api/project_debian_distributions_spec.rb
@@ -11,25 +11,31 @@ RSpec.describe API::ProjectDebianDistributions do
let(:url) { "/projects/#{container.id}/debian_distributions" }
let(:api_params) { { 'codename': 'my-codename' } }
- it_behaves_like 'Debian repository write endpoint', 'POST distribution request', :created, /^{.*"codename":"my-codename",.*"components":\["main"\],.*"architectures":\["all","amd64"\]/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions write endpoint', 'POST', :created, /^{.*"codename":"my-codename",.*"components":\["main"\],.*"architectures":\["all","amd64"\]/
context 'with invalid parameters' do
let(:api_params) { { codename: distribution.codename } }
- it_behaves_like 'Debian repository write endpoint', 'GET request', :bad_request, /^{"message":{"codename":\["has already been taken"\]}}$/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions write endpoint', 'GET', :bad_request, /^{"message":{"codename":\["has already been taken"\]}}$/
end
end
describe 'GET projects/:id/debian_distributions' do
let(:url) { "/projects/#{container.id}/debian_distributions" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^\[{.*"codename":"existing-codename\",.*"components":\["existing-component"\],.*"architectures":\["all","existing-arch"\]/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions read endpoint', 'GET', :success, /^\[{.*"codename":"existing-codename\",.*"components":\["existing-component"\],.*"architectures":\["all","existing-arch"\]/
end
describe 'GET projects/:id/debian_distributions/:codename' do
let(:url) { "/projects/#{container.id}/debian_distributions/#{distribution.codename}" }
- it_behaves_like 'Debian repository read endpoint', 'GET request', :success, /^{.*"codename":"existing-codename\",.*"components":\["existing-component"\],.*"architectures":\["all","existing-arch"\]/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions read endpoint', 'GET', :success, /^{.*"codename":"existing-codename\",.*"components":\["existing-component"\],.*"architectures":\["all","existing-arch"\]/
+ end
+
+ describe 'GET projects/:id/debian_distributions/:codename/key.asc' do
+ let(:url) { "/projects/#{container.id}/debian_distributions/#{distribution.codename}/key.asc" }
+
+ it_behaves_like 'Debian distributions read endpoint', 'GET', :success, /^-----BEGIN PGP PUBLIC KEY BLOCK-----/
end
describe 'PUT projects/:id/debian_distributions/:codename' do
@@ -37,12 +43,12 @@ RSpec.describe API::ProjectDebianDistributions do
let(:url) { "/projects/#{container.id}/debian_distributions/#{distribution.codename}" }
let(:api_params) { { suite: 'my-suite' } }
- it_behaves_like 'Debian repository write endpoint', 'PUT distribution request', :success, /^{.*"codename":"existing-codename",.*"suite":"my-suite",/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions write endpoint', 'PUT', :success, /^{.*"codename":"existing-codename",.*"suite":"my-suite",/
context 'with invalid parameters' do
let(:api_params) { { suite: distribution.codename } }
- it_behaves_like 'Debian repository write endpoint', 'GET request', :bad_request, /^{"message":{"suite":\["has already been taken as Codename"\]}}$/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions write endpoint', 'GET', :bad_request, /^{"message":{"suite":\["has already been taken as Codename"\]}}$/
end
end
@@ -50,7 +56,7 @@ RSpec.describe API::ProjectDebianDistributions do
let(:method) { :delete }
let(:url) { "/projects/#{container.id}/debian_distributions/#{distribution.codename}" }
- it_behaves_like 'Debian repository maintainer write endpoint', 'DELETE distribution request', :success, /^{\"message\":\"202 Accepted\"}$/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions maintainer write endpoint', 'DELETE', :success, /^{\"message\":\"202 Accepted\"}$/
context 'when destroy fails' do
before do
@@ -59,7 +65,7 @@ RSpec.describe API::ProjectDebianDistributions do
end
end
- it_behaves_like 'Debian repository maintainer write endpoint', 'GET request', :bad_request, /^{"message":"Failed to delete distribution"}$/, authenticate_non_public: false
+ it_behaves_like 'Debian distributions maintainer write endpoint', 'GET', :bad_request, /^{"message":"Failed to delete distribution"}$/
end
end
end
diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb
index 0c9e125cc90..097d374640c 100644
--- a/spec/requests/api/project_import_spec.rb
+++ b/spec/requests/api/project_import_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe API::ProjectImport do
it 'executes a limited number of queries' do
control_count = ActiveRecord::QueryRecorder.new { subject }.count
- expect(control_count).to be <= 100
+ expect(control_count).to be <= 101
end
it 'schedules an import using a namespace' do
diff --git a/spec/requests/api/project_snapshots_spec.rb b/spec/requests/api/project_snapshots_spec.rb
index f23e374407b..33c86d56ed4 100644
--- a/spec/requests/api/project_snapshots_spec.rb
+++ b/spec/requests/api/project_snapshots_spec.rb
@@ -29,6 +29,7 @@ RSpec.describe API::ProjectSnapshots do
repository: repository.gitaly_repository
).to_json
)
+ expect(response.parsed_body).to be_empty
end
it 'returns authentication error as project owner' do
diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb
index 8cd1f15a88d..512cbf7c321 100644
--- a/spec/requests/api/project_snippets_spec.rb
+++ b/spec/requests/api/project_snippets_spec.rb
@@ -400,6 +400,7 @@ RSpec.describe API::ProjectSnippets do
expect(response).to have_gitlab_http_status(:ok)
expect(response.media_type).to eq 'text/plain'
+ expect(response.parsed_body).to be_empty
end
it 'returns 404 for invalid snippet id' do
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index dd6afa869e0..4f84e6f2562 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -48,6 +48,7 @@ end
RSpec.describe API::Projects do
include ProjectForksHelper
+ include StubRequests
let_it_be(:user) { create(:user) }
let_it_be(:user2) { create(:user) }
@@ -358,7 +359,7 @@ RSpec.describe API::Projects do
statistics = json_response.find { |p| p['id'] == project.id }['statistics']
expect(statistics).to be_present
- expect(statistics).to include('commit_count', 'storage_size', 'repository_size', 'wiki_size', 'lfs_objects_size', 'job_artifacts_size', 'snippets_size', 'packages_size')
+ expect(statistics).to include('commit_count', 'storage_size', 'repository_size', 'wiki_size', 'lfs_objects_size', 'job_artifacts_size', 'pipeline_artifacts_size', 'snippets_size', 'packages_size', 'uploads_size')
end
it "does not include license by default" do
@@ -1159,6 +1160,34 @@ RSpec.describe API::Projects do
expect(response).to have_gitlab_http_status(:forbidden)
end
+ it 'disallows creating a project with an import_url that is not reachable', :aggregate_failures do
+ url = 'http://example.com'
+ endpoint_url = "#{url}/info/refs?service=git-upload-pack"
+ stub_full_request(endpoint_url, method: :get).to_return({ status: 301, body: '', headers: nil })
+ project_params = { import_url: url, path: 'path-project-Foo', name: 'Foo Project' }
+
+ expect { post api('/projects', user), params: project_params }.not_to change { Project.count }
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ expect(json_response['message']).to eq("#{url} is not a valid HTTP Git repository")
+ end
+
+ it 'creates a project with an import_url that is valid', :aggregate_failures do
+ url = 'http://example.com'
+ endpoint_url = "#{url}/info/refs?service=git-upload-pack"
+ git_response = {
+ status: 200,
+ body: '001e# service=git-upload-pack',
+ headers: { 'Content-Type': 'application/x-git-upload-pack-advertisement' }
+ }
+ stub_full_request(endpoint_url, method: :get).to_return(git_response)
+ project_params = { import_url: url, path: 'path-project-Foo', name: 'Foo Project' }
+
+ expect { post api('/projects', user), params: project_params }.to change { Project.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:created)
+ end
+
it 'sets a project as public' do
project = attributes_for(:project, visibility: 'public')
diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb
index 90b03a480a8..cb9b6a072b1 100644
--- a/spec/requests/api/releases_spec.rb
+++ b/spec/requests/api/releases_spec.rb
@@ -42,6 +42,14 @@ RSpec.describe API::Releases do
expect(response).to have_gitlab_http_status(:ok)
end
+ it 'returns 200 HTTP status when using JOB-TOKEN auth' do
+ job = create(:ci_build, :running, project: project, user: maintainer)
+
+ get api("/projects/#{project.id}/releases"), params: { job_token: job.token }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
it 'returns releases ordered by released_at' do
get api("/projects/#{project.id}/releases", maintainer)
@@ -316,6 +324,14 @@ RSpec.describe API::Releases do
expect(response).to have_gitlab_http_status(:ok)
end
+ it 'returns 200 HTTP status when using JOB-TOKEN auth' do
+ job = create(:ci_build, :running, project: project, user: maintainer)
+
+ get api("/projects/#{project.id}/releases/v0.1"), params: { job_token: job.token }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
it 'returns a release entry' do
get api("/projects/#{project.id}/releases/v0.1", maintainer)
@@ -1008,6 +1024,14 @@ RSpec.describe API::Releases do
expect(response).to have_gitlab_http_status(:ok)
end
+ it 'accepts the request when using JOB-TOKEN auth' do
+ job = create(:ci_build, :running, project: project, user: maintainer)
+
+ put api("/projects/#{project.id}/releases/v0.1"), params: params.merge(job_token: job.token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
it 'updates the description' do
put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params
@@ -1220,6 +1244,14 @@ RSpec.describe API::Releases do
expect(response).to have_gitlab_http_status(:ok)
end
+ it 'accepts the request when using JOB-TOKEN auth' do
+ job = create(:ci_build, :running, project: project, user: maintainer)
+
+ delete api("/projects/#{project.id}/releases/v0.1"), params: { job_token: job.token }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
it 'destroys the release' do
expect do
delete api("/projects/#{project.id}/releases/v0.1", maintainer)
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index f05f125c974..f3146480be2 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -197,6 +197,7 @@ RSpec.describe API::Repositories do
expect(response).to have_gitlab_http_status(:ok)
expect(headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
+ expect(response.parsed_body).to be_empty
end
it 'sets inline content disposition by default' do
@@ -274,6 +275,7 @@ RSpec.describe API::Repositories do
expect(type).to eq('git-archive')
expect(params['ArchivePath']).to match(/#{project.path}\-[^\.]+\.tar.gz/)
+ expect(response.parsed_body).to be_empty
end
it 'returns the repository archive archive.zip' do
@@ -495,6 +497,43 @@ RSpec.describe API::Repositories do
expect(response).to have_gitlab_http_status(:not_found)
end
+
+ it "returns a newly created commit", :use_clean_rails_redis_caching do
+ # Parse the commits ourselves because json_response is cached
+ def commit_messages(response)
+ Gitlab::Json.parse(response.body)["commits"].map do |commit|
+ commit["message"]
+ end
+ end
+
+ # First trigger the rate limit cache
+ get api(route, current_user), params: { from: 'master', to: 'feature' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(commit_messages(response)).not_to include("Cool new commit")
+
+ # Then create a new commit via the API
+ post api("/projects/#{project.id}/repository/commits", user), params: {
+ branch: "feature",
+ commit_message: "Cool new commit",
+ actions: [
+ {
+ action: "create",
+ file_path: "foo/bar/baz.txt",
+ content: "puts 8"
+ }
+ ]
+ }
+
+ expect(response).to have_gitlab_http_status(:created)
+
+ # Now perform the same query as before, but the cache should have expired
+ # and our new commit should exist
+ get api(route, current_user), params: { from: 'master', to: 'feature' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(commit_messages(response)).to include("Cool new commit")
+ end
end
context 'when unauthenticated', 'and project is public' do
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 423e19c3971..641c6a2cd91 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -612,5 +612,46 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response.slice(*settings.keys)).to eq(settings)
end
end
+
+ context 'Sentry settings' do
+ let(:settings) do
+ {
+ sentry_enabled: true,
+ sentry_dsn: 'http://sentry.example.com',
+ sentry_clientside_dsn: 'http://sentry.example.com',
+ sentry_environment: 'production'
+ }
+ end
+
+ let(:attribute_names) { settings.keys.map(&:to_s) }
+
+ it 'includes the attributes in the API' do
+ get api('/application/settings', admin)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ attribute_names.each do |attribute|
+ expect(json_response.keys).to include(attribute)
+ end
+ end
+
+ it 'allows updating the settings' do
+ put api('/application/settings', admin), params: settings
+
+ expect(response).to have_gitlab_http_status(:ok)
+ settings.each do |attribute, value|
+ expect(ApplicationSetting.current.public_send(attribute)).to eq(value)
+ end
+ end
+
+ context 'missing sentry_dsn value when sentry_enabled is true' do
+ it 'returns a blank parameter error message' do
+ put api('/application/settings', admin), params: { sentry_enabled: true }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ message = json_response['message']
+ expect(message["sentry_dsn"]).to include(a_string_matching("can't be blank"))
+ end
+ end
+ end
end
end
diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb
index f4d15d0525e..dd5e6ac8a5e 100644
--- a/spec/requests/api/snippets_spec.rb
+++ b/spec/requests/api/snippets_spec.rb
@@ -113,6 +113,7 @@ RSpec.describe API::Snippets, factory_default: :keep do
expect(response).to have_gitlab_http_status(:ok)
expect(response.media_type).to eq 'text/plain'
expect(headers['Content-Disposition']).to match(/^inline/)
+ expect(response.parsed_body).to be_empty
end
it 'returns 404 for invalid snippet id' do
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index 1aa1ad87be9..bb56192a2ff 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -17,6 +17,10 @@ RSpec.describe API::Tags do
end
describe 'GET /projects/:id/repository/tags' do
+ before do
+ stub_feature_flags(tag_list_keyset_pagination: false)
+ end
+
shared_examples "get repository tags" do
let(:route) { "/projects/#{project_id}/repository/tags" }
@@ -143,6 +147,55 @@ RSpec.describe API::Tags do
expect(expected_tag['release']['description']).to eq(description)
end
end
+
+ context 'with keyset pagination on', :aggregate_errors do
+ before do
+ stub_feature_flags(tag_list_keyset_pagination: true)
+ end
+
+ context 'with keyset pagination option' do
+ let(:base_params) { { pagination: 'keyset' } }
+
+ context 'with gitaly pagination params' do
+ context 'with high limit' do
+ let(:params) { base_params.merge(per_page: 100) }
+
+ it 'returns all repository tags' do
+ get api(route, user), params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/tags')
+ expect(response.headers).not_to include('Link')
+ tag_names = json_response.map { |x| x['name'] }
+ expect(tag_names).to match_array(project.repository.tag_names)
+ end
+ end
+
+ context 'with low limit' do
+ let(:params) { base_params.merge(per_page: 2) }
+
+ it 'returns limited repository tags' do
+ get api(route, user), params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/tags')
+ expect(response.headers).to include('Link')
+ tag_names = json_response.map { |x| x['name'] }
+ expect(tag_names).to match_array(%w(v1.1.0 v1.1.1))
+ end
+ end
+
+ context 'with missing page token' do
+ let(:params) { base_params.merge(page_token: 'unknown') }
+
+ it_behaves_like '422 response' do
+ let(:request) { get api(route, user), params: params }
+ let(:message) { 'Invalid page token: refs/tags/unknown' }
+ end
+ end
+ end
+ end
+ end
end
context ":api_caching_tags flag enabled", :use_clean_rails_memory_store_caching do
@@ -208,6 +261,20 @@ RSpec.describe API::Tags do
it_behaves_like "get repository tags"
end
+
+ context 'when gitaly is unavailable' do
+ let(:route) { "/projects/#{project_id}/repository/tags" }
+
+ before do
+ expect_next_instance_of(TagsFinder) do |finder|
+ allow(finder).to receive(:execute).and_raise(Gitlab::Git::CommandError)
+ end
+ end
+
+ it_behaves_like '503 response' do
+ let(:request) { get api(route, user) }
+ end
+ end
end
describe 'GET /projects/:id/repository/tags/:tag_name' do
diff --git a/spec/requests/api/terraform/modules/v1/packages_spec.rb b/spec/requests/api/terraform/modules/v1/packages_spec.rb
index b04f5ad9a94..b17bc11a451 100644
--- a/spec/requests/api/terraform/modules/v1/packages_spec.rb
+++ b/spec/requests/api/terraform/modules/v1/packages_spec.rb
@@ -28,10 +28,25 @@ RSpec.describe API::Terraform::Modules::V1::Packages do
describe 'GET /api/v4/packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/versions' do
let(:url) { api("/packages/terraform/modules/v1/#{group.path}/#{package.name}/versions") }
- let(:headers) { {} }
+ let(:headers) { { 'Authorization' => "Bearer #{tokens[:job_token]}" } }
subject { get(url, headers: headers) }
+ context 'with a conflicting package name' do
+ let!(:conflicting_package) { create(:terraform_module_package, project: project, name: "conflict-#{package.name}", version: '2.0.0') }
+
+ before do
+ group.add_developer(user)
+ end
+
+ it 'returns only one version' do
+ subject
+
+ expect(json_response['modules'][0]['versions'].size).to eq(1)
+ expect(json_response['modules'][0]['versions'][0]['version']).to eq('1.0.0')
+ end
+ end
+
context 'with valid namespace' do
where(:visibility, :user_role, :member, :token_type, :valid_token, :shared_examples_name, :expected_status) do
:public | :developer | true | :personal_access_token | true | 'returns terraform module packages' | :success
diff --git a/spec/requests/api/todos_spec.rb b/spec/requests/api/todos_spec.rb
index d31f571e636..c9deb84ff98 100644
--- a/spec/requests/api/todos_spec.rb
+++ b/spec/requests/api/todos_spec.rb
@@ -13,6 +13,8 @@ RSpec.describe API::Todos do
let_it_be(:john_doe) { create(:user, username: 'john_doe') }
let_it_be(:issue) { create(:issue, project: project_1) }
let_it_be(:merge_request) { create(:merge_request, source_project: project_1) }
+ let_it_be(:alert) { create(:alert_management_alert, project: project_1) }
+ let_it_be(:alert_todo) { create(:todo, project: project_1, author: john_doe, user: john_doe, target: alert) }
let_it_be(:merge_request_todo) { create(:todo, project: project_1, author: author_2, user: john_doe, target: merge_request) }
let_it_be(:pending_1) { create(:todo, :mentioned, project: project_1, author: author_1, user: john_doe, target: issue) }
let_it_be(:pending_2) { create(:todo, project: project_2, author: author_2, user: john_doe, target: issue) }
@@ -67,7 +69,7 @@ RSpec.describe API::Todos do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.length).to eq(4)
+ expect(json_response.length).to eq(5)
expect(json_response[0]['id']).to eq(pending_3.id)
expect(json_response[0]['project']).to be_a Hash
expect(json_response[0]['author']).to be_a Hash
@@ -95,6 +97,10 @@ RSpec.describe API::Todos do
expect(json_response[3]['target']['merge_requests_count']).to be_nil
expect(json_response[3]['target']['upvotes']).to eq(1)
expect(json_response[3]['target']['downvotes']).to eq(0)
+
+ expect(json_response[4]['target_type']).to eq('AlertManagement::Alert')
+ expect(json_response[4]['target']['iid']).to eq(alert.iid)
+ expect(json_response[4]['target']['title']).to eq(alert.title)
end
context "when current user does not have access to one of the TODO's target" do
@@ -105,7 +111,7 @@ RSpec.describe API::Todos do
get api('/todos', john_doe)
- expect(json_response.count).to eq(4)
+ expect(json_response.count).to eq(5)
expect(json_response.map { |t| t['id'] }).not_to include(no_access_todo.id, pending_4.id)
end
end
@@ -163,7 +169,7 @@ RSpec.describe API::Todos do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
+ expect(json_response.length).to eq(4)
end
end
diff --git a/spec/requests/api/topics_spec.rb b/spec/requests/api/topics_spec.rb
new file mode 100644
index 00000000000..a5746a4022e
--- /dev/null
+++ b/spec/requests/api/topics_spec.rb
@@ -0,0 +1,217 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Topics do
+ include WorkhorseHelpers
+
+ let_it_be(:topic_1) { create(:topic, name: 'Git', total_projects_count: 1) }
+ let_it_be(:topic_2) { create(:topic, name: 'GitLab', total_projects_count: 2) }
+ let_it_be(:topic_3) { create(:topic, name: 'other-topic', total_projects_count: 3) }
+
+ let_it_be(:admin) { create(:user, :admin) }
+ let_it_be(:user) { create(:user) }
+
+ let(:file) { fixture_file_upload('spec/fixtures/dk.png') }
+
+ describe 'GET /topics', :aggregate_failures do
+ it 'returns topics ordered by total_projects_count' do
+ get api('/topics')
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(3)
+
+ expect(json_response[0]['id']).to eq(topic_3.id)
+ expect(json_response[0]['name']).to eq('other-topic')
+ expect(json_response[0]['total_projects_count']).to eq(3)
+
+ expect(json_response[1]['id']).to eq(topic_2.id)
+ expect(json_response[1]['name']).to eq('GitLab')
+ expect(json_response[1]['total_projects_count']).to eq(2)
+
+ expect(json_response[2]['id']).to eq(topic_1.id)
+ expect(json_response[2]['name']).to eq('Git')
+ expect(json_response[2]['total_projects_count']).to eq(1)
+ end
+
+ context 'with search' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:search, :result) do
+ '' | %w[other-topic GitLab Git]
+ 'g' | %w[]
+ 'gi' | %w[]
+ 'git' | %w[Git GitLab]
+ 'x' | %w[]
+ 0 | %w[]
+ end
+
+ with_them do
+ it 'returns filtered topics' do
+ get api('/topics'), params: { search: search }
+
+ expect(json_response.map { |t| t['name'] }).to eq(result)
+ end
+ end
+ end
+
+ context 'with pagination' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:params, :result) do
+ { page: 0 } | %w[other-topic GitLab Git]
+ { page: 1 } | %w[other-topic GitLab Git]
+ { page: 2 } | %w[]
+ { per_page: 1 } | %w[other-topic]
+ { per_page: 2 } | %w[other-topic GitLab]
+ { per_page: 3 } | %w[other-topic GitLab Git]
+ { page: 0, per_page: 1 } | %w[other-topic]
+ { page: 0, per_page: 2 } | %w[other-topic GitLab]
+ { page: 1, per_page: 1 } | %w[other-topic]
+ { page: 1, per_page: 2 } | %w[other-topic GitLab]
+ { page: 2, per_page: 1 } | %w[GitLab]
+ { page: 2, per_page: 2 } | %w[Git]
+ { page: 3, per_page: 1 } | %w[Git]
+ { page: 3, per_page: 2 } | %w[]
+ { page: 4, per_page: 1 } | %w[]
+ { page: 4, per_page: 2 } | %w[]
+ end
+
+ with_them do
+ it 'returns paginated topics' do
+ get api('/topics'), params: params
+
+ expect(json_response.map { |t| t['name'] }).to eq(result)
+ end
+ end
+ end
+ end
+
+ describe 'GET /topic/:id', :aggregate_failures do
+ it 'returns topic' do
+ get api("/topics/#{topic_2.id}")
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ expect(json_response['id']).to eq(topic_2.id)
+ expect(json_response['name']).to eq('GitLab')
+ expect(json_response['total_projects_count']).to eq(2)
+ end
+
+ it 'returns 404 for non existing id' do
+ get api("/topics/#{non_existing_record_id}")
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'returns 400 for invalid `id` parameter' do
+ get api('/topics/invalid')
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eql('id is invalid')
+ end
+ end
+
+ describe 'POST /topics', :aggregate_failures do
+ context 'as administrator' do
+ it 'creates a topic' do
+ post api('/topics/', admin), params: { name: 'my-topic' }
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['name']).to eq('my-topic')
+ expect(Projects::Topic.find(json_response['id']).name).to eq('my-topic')
+ end
+
+ it 'creates a topic with avatar and description' do
+ workhorse_form_with_file(
+ api('/topics/', admin),
+ file_key: :avatar,
+ params: { name: 'my-topic', description: 'my description...', avatar: file }
+ )
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['description']).to eq('my description...')
+ expect(json_response['avatar_url']).to end_with('dk.png')
+ end
+
+ it 'returns 400 if name is missing' do
+ post api('/topics/', admin)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eql('name is missing')
+ end
+ end
+
+ context 'as normal user' do
+ it 'returns 403 Forbidden' do
+ post api('/topics/', user), params: { name: 'my-topic' }
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'as anonymous' do
+ it 'returns 401 Unauthorized' do
+ post api('/topics/'), params: { name: 'my-topic' }
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+
+ describe 'PUT /topics', :aggregate_failures do
+ context 'as administrator' do
+ it 'updates a topic' do
+ put api("/topics/#{topic_3.id}", admin), params: { name: 'my-topic' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['name']).to eq('my-topic')
+ expect(topic_3.reload.name).to eq('my-topic')
+ end
+
+ it 'updates a topic with avatar and description' do
+ workhorse_form_with_file(
+ api("/topics/#{topic_3.id}", admin),
+ method: :put,
+ file_key: :avatar,
+ params: { description: 'my description...', avatar: file }
+ )
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['description']).to eq('my description...')
+ expect(json_response['avatar_url']).to end_with('dk.png')
+ end
+
+ it 'returns 404 for non existing id' do
+ put api("/topics/#{non_existing_record_id}", admin), params: { name: 'my-topic' }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'returns 400 for invalid `id` parameter' do
+ put api('/topics/invalid', admin), params: { name: 'my-topic' }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eql('id is invalid')
+ end
+ end
+
+ context 'as normal user' do
+ it 'returns 403 Forbidden' do
+ put api("/topics/#{topic_3.id}", user), params: { name: 'my-topic' }
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'as anonymous' do
+ it 'returns 401 Unauthorized' do
+ put api("/topics/#{topic_3.id}"), params: { name: 'my-topic' }
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index fb01845b63a..b93df2f3bae 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -1464,6 +1464,7 @@ RSpec.describe API::Users do
credit_card_expiration_year: expiration_year,
credit_card_expiration_month: 1,
credit_card_holder_name: 'John Smith',
+ credit_card_type: 'AmericanExpress',
credit_card_mask_number: '1111'
}
end
@@ -1495,6 +1496,7 @@ RSpec.describe API::Users do
credit_card_validated_at: credit_card_validated_time,
expiration_date: Date.new(expiration_year, 1, 31),
last_digits: 1111,
+ network: 'AmericanExpress',
holder_name: 'John Smith'
)
end
@@ -1904,7 +1906,8 @@ RSpec.describe API::Users do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.first['email']).to eq(email.email)
+ expect(json_response.first['email']).to eq(user.email)
+ expect(json_response.second['email']).to eq(email.email)
end
it "returns a 404 for invalid ID" do
@@ -2486,7 +2489,8 @@ RSpec.describe API::Users do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.first["email"]).to eq(email.email)
+ expect(json_response.first['email']).to eq(user.email)
+ expect(json_response.second['email']).to eq(email.email)
end
context "scopes" do
diff --git a/spec/requests/api/v3/github_spec.rb b/spec/requests/api/v3/github_spec.rb
index 255f53e4c7c..6d8ae226ce4 100644
--- a/spec/requests/api/v3/github_spec.rb
+++ b/spec/requests/api/v3/github_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe API::V3::Github do
let_it_be(:user) { create(:user) }
let_it_be(:unauthorized_user) { create(:user) }
let_it_be(:admin) { create(:user, :admin) }
- let_it_be(:project) { create(:project, :repository, creator: user) }
+ let_it_be_with_reload(:project) { create(:project, :repository, creator: user) }
before do
project.add_maintainer(user)
@@ -506,11 +506,18 @@ RSpec.describe API::V3::Github do
describe 'GET /repos/:namespace/:project/commits/:sha' do
let(:commit) { project.repository.commit }
- let(:commit_id) { commit.id }
+
+ def call_api(commit_id: commit.id)
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/commits/#{commit_id}", user)
+ end
+
+ def response_diff_files(response)
+ Gitlab::Json.parse(response.body)['files']
+ end
context 'authenticated' do
- it 'returns commit with github format' do
- jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/commits/#{commit_id}", user)
+ it 'returns commit with github format', :aggregate_failures do
+ call_api
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('entities/github/commit')
@@ -519,36 +526,130 @@ RSpec.describe API::V3::Github do
it 'returns 200 when project path include a dot' do
project.update!(path: 'foo.bar')
- jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/commits/#{commit_id}", user)
+ call_api
expect(response).to have_gitlab_http_status(:ok)
end
- it 'returns 200 when namespace path include a dot' do
- group = create(:group, path: 'foo.bar')
- project = create(:project, :repository, group: group)
- project.add_reporter(user)
+ context 'when namespace path includes a dot' do
+ let(:group) { create(:group, path: 'foo.bar') }
+ let(:project) { create(:project, :repository, group: group) }
- jira_get v3_api("/repos/#{group.path}/#{project.path}/commits/#{commit_id}", user)
+ it 'returns 200 when namespace path include a dot' do
+ project.add_reporter(user)
- expect(response).to have_gitlab_http_status(:ok)
+ call_api
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'when the Gitaly `CommitDiff` RPC times out', :use_clean_rails_memory_store_caching do
+ let(:commit_diff_args) { [project.repository_storage, :diff_service, :commit_diff, any_args] }
+
+ before do
+ allow(Gitlab::GitalyClient).to receive(:call)
+ .and_call_original
+ end
+
+ it 'handles the error, logs it, and returns empty diff files', :aggregate_failures do
+ allow(Gitlab::GitalyClient).to receive(:call)
+ .with(*commit_diff_args)
+ .and_raise(GRPC::DeadlineExceeded)
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_exception)
+ .with an_instance_of(GRPC::DeadlineExceeded)
+
+ call_api
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response_diff_files(response)).to be_blank
+ end
+
+ it 'does not handle the error when feature flag is disabled', :aggregate_failures do
+ stub_feature_flags(api_v3_commits_skip_diff_files: false)
+
+ allow(Gitlab::GitalyClient).to receive(:call)
+ .with(*commit_diff_args)
+ .and_raise(GRPC::DeadlineExceeded)
+
+ call_api
+
+ expect(response).to have_gitlab_http_status(:error)
+ end
+
+ it 'only calls Gitaly once for all attempts within a period of time', :aggregate_failures do
+ expect(Gitlab::GitalyClient).to receive(:call)
+ .with(*commit_diff_args)
+ .once # <- once
+ .and_raise(GRPC::DeadlineExceeded)
+
+ 3.times do
+ call_api
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response_diff_files(response)).to be_blank
+ end
+ end
+
+ it 'calls Gitaly again after a period of time', :aggregate_failures do
+ expect(Gitlab::GitalyClient).to receive(:call)
+ .with(*commit_diff_args)
+ .twice # <- twice
+ .and_raise(GRPC::DeadlineExceeded)
+
+ call_api
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response_diff_files(response)).to be_blank
+
+ travel_to((described_class::GITALY_TIMEOUT_CACHE_EXPIRY + 1.second).from_now) do
+ call_api
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response_diff_files(response)).to be_blank
+ end
+ end
+
+ it 'uses a unique cache key, allowing other calls to succeed' do
+ cache_key = [described_class::GITALY_TIMEOUT_CACHE_KEY, project.id, commit.cache_key].join(':')
+ Rails.cache.write(cache_key, 1)
+
+ expect(Gitlab::GitalyClient).to receive(:call)
+ .with(*commit_diff_args)
+ .once # <- once
+
+ call_api
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response_diff_files(response)).to be_blank
+
+ call_api(commit_id: commit.parent.id)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response_diff_files(response).length).to eq(1)
+ end
end
end
context 'unauthenticated' do
+ let(:user) { nil }
+
it 'returns 401' do
- jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/commits/#{commit_id}", nil)
+ call_api
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
context 'unauthorized' do
+ let(:user) { unauthorized_user }
+
it 'returns 404 when lower access level' do
- project.add_guest(unauthorized_user)
+ project.add_guest(user)
- jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/commits/#{commit_id}",
- unauthorized_user)
+ call_api
expect(response).to have_gitlab_http_status(:not_found)
end
diff --git a/spec/requests/groups/email_campaigns_controller_spec.rb b/spec/requests/groups/email_campaigns_controller_spec.rb
index 4d630ef6710..9ed828d1a9a 100644
--- a/spec/requests/groups/email_campaigns_controller_spec.rb
+++ b/spec/requests/groups/email_campaigns_controller_spec.rb
@@ -94,7 +94,7 @@ RSpec.describe Groups::EmailCampaignsController do
describe 'track parameter' do
context 'when valid' do
- where(track: Namespaces::InProductMarketingEmailsService::TRACKS.keys.without(:experience))
+ where(track: [Namespaces::InProductMarketingEmailsService::TRACKS.keys.without(:experience), Namespaces::InviteTeamEmailService::TRACK].flatten)
with_them do
it_behaves_like 'track and redirect'
@@ -117,6 +117,10 @@ RSpec.describe Groups::EmailCampaignsController do
with_them do
it_behaves_like 'track and redirect'
end
+
+ it_behaves_like 'track and redirect' do
+ let(:track) { Namespaces::InviteTeamEmailService::TRACK.to_s }
+ end
end
context 'when invalid' do
@@ -124,6 +128,10 @@ RSpec.describe Groups::EmailCampaignsController do
with_them do
it_behaves_like 'no track and 404'
+
+ it_behaves_like 'no track and 404' do
+ let(:track) { Namespaces::InviteTeamEmailService::TRACK.to_s }
+ end
end
end
end
diff --git a/spec/requests/groups/settings/applications_controller_spec.rb b/spec/requests/groups/settings/applications_controller_spec.rb
new file mode 100644
index 00000000000..74313491414
--- /dev/null
+++ b/spec/requests/groups/settings/applications_controller_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::Settings::ApplicationsController do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:application) { create(:oauth_application, owner_id: group.id, owner_type: 'Namespace') }
+ let_it_be(:show_path) { group_settings_application_path(group, application) }
+ let_it_be(:create_path) { group_settings_applications_path(group) }
+
+ before do
+ sign_in(user)
+ group.add_owner(user)
+ end
+
+ include_examples 'applications controller - GET #show'
+
+ include_examples 'applications controller - POST #create'
+end
diff --git a/spec/requests/import/gitlab_groups_controller_spec.rb b/spec/requests/import/gitlab_groups_controller_spec.rb
index 1f6487986a3..4abf99cf994 100644
--- a/spec/requests/import/gitlab_groups_controller_spec.rb
+++ b/spec/requests/import/gitlab_groups_controller_spec.rb
@@ -60,6 +60,7 @@ RSpec.describe Import::GitlabGroupsController do
end
it 'imports the group data', :sidekiq_inline do
+ allow(GroupImportWorker).to receive(:with_status).and_return(GroupImportWorker)
allow(GroupImportWorker).to receive(:perform_async).and_call_original
import_request
@@ -67,7 +68,6 @@ RSpec.describe Import::GitlabGroupsController do
group = Group.find_by(name: 'test-group-import')
expect(GroupImportWorker).to have_received(:perform_async).with(user.id, group.id)
-
expect(group.description).to eq 'A voluptate non sequi temporibus quam at.'
expect(group.visibility_level).to eq Gitlab::VisibilityLevel::PRIVATE
end
diff --git a/spec/requests/jwks_controller_spec.rb b/spec/requests/jwks_controller_spec.rb
index 5eda1979027..6dbb5988f58 100644
--- a/spec/requests/jwks_controller_spec.rb
+++ b/spec/requests/jwks_controller_spec.rb
@@ -3,6 +3,20 @@
require 'spec_helper'
RSpec.describe JwksController do
+ describe 'Endpoints from the parent Doorkeeper::OpenidConnect::DiscoveryController' do
+ it 'respond successfully' do
+ [
+ "/oauth/discovery/keys",
+ "/.well-known/openid-configuration",
+ "/.well-known/webfinger?resource=#{create(:user).email}"
+ ].each do |endpoint|
+ get endpoint
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
describe 'GET /-/jwks' do
let(:ci_jwt_signing_key) { OpenSSL::PKey::RSA.generate(1024) }
let(:ci_jwk) { ci_jwt_signing_key.to_jwk }
diff --git a/spec/requests/oauth/applications_controller_spec.rb b/spec/requests/oauth/applications_controller_spec.rb
new file mode 100644
index 00000000000..78f0cedb56f
--- /dev/null
+++ b/spec/requests/oauth/applications_controller_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Oauth::ApplicationsController do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:application) { create(:oauth_application, owner: user) }
+ let_it_be(:show_path) { oauth_application_path(application) }
+ let_it_be(:create_path) { oauth_applications_path }
+
+ before do
+ sign_in(user)
+ end
+
+ include_examples 'applications controller - GET #show'
+
+ include_examples 'applications controller - POST #create'
+end
diff --git a/spec/requests/projects/google_cloud_controller_spec.rb b/spec/requests/projects/google_cloud_controller_spec.rb
index 3b43f0d1dfb..37682152994 100644
--- a/spec/requests/projects/google_cloud_controller_spec.rb
+++ b/spec/requests/projects/google_cloud_controller_spec.rb
@@ -2,48 +2,106 @@
require 'spec_helper'
+# Mock Types
+MockGoogleOAuth2Credentials = Struct.new(:app_id, :app_secret)
+
RSpec.describe Projects::GoogleCloudController do
let_it_be(:project) { create(:project, :public) }
describe 'GET index' do
let_it_be(:url) { "#{project_google_cloud_index_path(project)}" }
- let(:subject) { get url }
+ context 'when a public request is made' do
+ it 'returns not found' do
+ get url
- context 'when user is authorized' do
- let(:user) { project.creator }
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
- before do
+ context 'when a project.guest makes request' do
+ let(:user) { create(:user) }
+
+ it 'returns not found' do
+ project.add_guest(user)
sign_in(user)
- subject
+
+ get url
+
+ expect(response).to have_gitlab_http_status(:not_found)
end
+ end
- it 'renders content' do
- expect(response).to be_successful
+ context 'when project.developer makes request' do
+ let(:user) { create(:user) }
+
+ it 'returns not found' do
+ project.add_developer(user)
+ sign_in(user)
+
+ get url
+
+ expect(response).to have_gitlab_http_status(:not_found)
end
end
- context 'when user is unauthorized' do
+ context 'when project.maintainer makes request' do
let(:user) { create(:user) }
- before do
- project.add_guest(user)
+ it 'returns successful' do
+ project.add_maintainer(user)
sign_in(user)
- subject
+
+ get url
+
+ expect(response).to be_successful
end
+ end
- it 'shows 404' do
- expect(response).to have_gitlab_http_status(:not_found)
+ context 'when project.creator makes request' do
+ let(:user) { project.creator }
+
+ it 'returns successful' do
+ sign_in(user)
+
+ get url
+
+ expect(response).to be_successful
end
end
- context 'when no user is present' do
- before do
- subject
+ describe 'when authorized user makes request' do
+ let(:user) { project.creator }
+
+ context 'but gitlab instance is not configured for google oauth2' do
+ before do
+ unconfigured_google_oauth2 = MockGoogleOAuth2Credentials.new('', '')
+ allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for)
+ .with('google_oauth2')
+ .and_return(unconfigured_google_oauth2)
+ end
+
+ it 'returns forbidden' do
+ sign_in(user)
+
+ get url
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
end
- it 'shows 404' do
- expect(response).to have_gitlab_http_status(:not_found)
+ context 'but feature flag is disabled' do
+ before do
+ stub_feature_flags(incubation_5mp_google_cloud: false)
+ end
+
+ it 'returns not found' do
+ sign_in(user)
+
+ get url
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
end
end
end
diff --git a/spec/requests/projects/issues/discussions_spec.rb b/spec/requests/projects/issues/discussions_spec.rb
new file mode 100644
index 00000000000..dcdca2d9c27
--- /dev/null
+++ b/spec/requests/projects/issues/discussions_spec.rb
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'issue discussions' do
+ describe 'GET /:namespace/:project/-/issues/:iid/discussions' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:note_author) { create(:user) }
+ let_it_be(:notes) { create_list(:note, 5, project: project, noteable: issue, author: note_author) }
+
+ before_all do
+ project.add_maintainer(user)
+ end
+
+ context 'HTTP caching' do
+ def get_discussions
+ get discussions_namespace_project_issue_path(namespace_id: project.namespace, project_id: project, id: issue.iid), headers: {
+ 'If-None-Match' => @etag
+ }
+
+ @etag = response.etag
+ end
+
+ before do
+ sign_in(user)
+
+ get_discussions
+ end
+
+ it 'returns 304 without serializing JSON' do
+ expect(DiscussionSerializer).not_to receive(:new)
+
+ get_discussions
+
+ expect(response).to have_gitlab_http_status(:not_modified)
+ end
+
+ shared_examples 'cache miss' do
+ it 'returns 200 and serializes JSON' do
+ expect(DiscussionSerializer).to receive(:new).and_call_original
+
+ get_discussions
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'when user role changes' do
+ before do
+ project.add_guest(user)
+ end
+
+ it_behaves_like 'cache miss'
+ end
+
+ context 'when emoji is awarded to a note' do
+ before do
+ travel_to(1.minute.from_now) { create(:award_emoji, awardable: notes.first) }
+ end
+
+ it_behaves_like 'cache miss'
+ end
+
+ context 'when note author name changes' do
+ before do
+ note_author.update!(name: 'New name')
+ end
+
+ it_behaves_like 'cache miss'
+ end
+
+ context 'when note author status changes' do
+ before do
+ Users::SetStatusService.new(note_author, message: "updated status").execute
+ end
+
+ it_behaves_like 'cache miss'
+ end
+
+ context 'when note author role changes' do
+ before do
+ project.add_developer(note_author)
+ end
+
+ it_behaves_like 'cache miss'
+ end
+
+ context 'when note is added' do
+ before do
+ create(:note, project: project, noteable: issue)
+ end
+
+ it_behaves_like 'cache miss'
+ end
+
+ context 'when note is modified' do
+ before do
+ notes.first.update!(note: 'edited text')
+ end
+
+ it_behaves_like 'cache miss'
+ end
+
+ context 'when note is deleted' do
+ before do
+ notes.first.destroy!
+ end
+
+ it_behaves_like 'cache miss'
+ end
+ end
+ end
+end
diff --git a/spec/requests/projects/issues_controller_spec.rb b/spec/requests/projects/issues_controller_spec.rb
new file mode 100644
index 00000000000..f44b1f4d502
--- /dev/null
+++ b/spec/requests/projects/issues_controller_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::IssuesController do
+ let_it_be(:issue) { create(:issue) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { issue.project }
+ let_it_be(:user) { issue.author }
+
+ before do
+ login_as(user)
+ end
+
+ describe 'GET #discussions' do
+ let_it_be(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
+ let_it_be(:discussion_reply) { create(:discussion_note_on_issue, noteable: issue, project: issue.project, in_reply_to: discussion) }
+ let_it_be(:state_event) { create(:resource_state_event, issue: issue) }
+ let_it_be(:discussion_2) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
+ let_it_be(:discussion_3) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
+
+ context 'pagination' do
+ def get_discussions(**params)
+ get discussions_project_issue_path(project, issue, params: params.merge(format: :json))
+ end
+
+ it 'returns paginated notes and cursor based on per_page param' do
+ get_discussions(per_page: 2)
+
+ discussions = Gitlab::Json.parse(response.body)
+ notes = discussions.flat_map { |d| d['notes'] }
+
+ expect(discussions.count).to eq(2)
+ expect(notes).to match([
+ a_hash_including('id' => discussion.id.to_s),
+ a_hash_including('id' => discussion_reply.id.to_s),
+ a_hash_including('type' => 'StateNote')
+ ])
+
+ cursor = response.header['X-Next-Page-Cursor']
+ expect(cursor).to be_present
+
+ get_discussions(per_page: 1, cursor: cursor)
+
+ discussions = Gitlab::Json.parse(response.body)
+ notes = discussions.flat_map { |d| d['notes'] }
+
+ expect(discussions.count).to eq(1)
+ expect(notes).to match([
+ a_hash_including('id' => discussion_2.id.to_s)
+ ])
+ end
+
+ context 'when paginated_issue_discussions is disabled' do
+ before do
+ stub_feature_flags(paginated_issue_discussions: false)
+ end
+
+ it 'returns all discussions and ignores per_page param' do
+ get_discussions(per_page: 2)
+
+ discussions = Gitlab::Json.parse(response.body)
+ notes = discussions.flat_map { |d| d['notes'] }
+
+ expect(discussions.count).to eq(4)
+ expect(notes.count).to eq(5)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/projects/usage_quotas_spec.rb b/spec/requests/projects/usage_quotas_spec.rb
index 04e01da61ef..114e9bd9f1e 100644
--- a/spec/requests/projects/usage_quotas_spec.rb
+++ b/spec/requests/projects/usage_quotas_spec.rb
@@ -22,40 +22,26 @@ RSpec.describe 'Project Usage Quotas' do
end
describe 'GET /:namespace/:project/usage_quotas' do
- context 'with project_storage_ui feature flag enabled' do
- before do
- stub_feature_flags(project_storage_ui: true)
- end
-
- it 'renders usage quotas path' do
- mock_storage_app_data = {
- project_path: project.full_path,
- usage_quotas_help_page_path: help_page_path('user/usage_quotas'),
- build_artifacts_help_page_path: help_page_path('ci/pipelines/job_artifacts', anchor: 'when-job-artifacts-are-deleted'),
- packages_help_page_path: help_page_path('user/packages/package_registry/index.md', anchor: 'delete-a-package'),
- repository_help_page_path: help_page_path('user/project/repository/reducing_the_repo_size_using_git'),
- snippets_help_page_path: help_page_path('user/snippets', anchor: 'reduce-snippets-repository-size'),
- wiki_help_page_path: help_page_path('administration/wikis/index.md', anchor: 'reduce-wiki-repository-size')
- }
- get project_usage_quotas_path(project)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.body).to include(project_usage_quotas_path(project))
- expect(assigns[:storage_app_data]).to eq(mock_storage_app_data)
- expect(response.body).to include("Usage of project resources across the <strong>#{project.name}</strong> project")
- end
-
- context 'renders :not_found for user without permission' do
- let(:role) { :developer }
-
- it_behaves_like 'response with 404 status'
- end
+ it 'renders usage quotas path' do
+ mock_storage_app_data = {
+ project_path: project.full_path,
+ usage_quotas_help_page_path: help_page_path('user/usage_quotas'),
+ build_artifacts_help_page_path: help_page_path('ci/pipelines/job_artifacts', anchor: 'when-job-artifacts-are-deleted'),
+ packages_help_page_path: help_page_path('user/packages/package_registry/index.md', anchor: 'delete-a-package'),
+ repository_help_page_path: help_page_path('user/project/repository/reducing_the_repo_size_using_git'),
+ snippets_help_page_path: help_page_path('user/snippets', anchor: 'reduce-snippets-repository-size'),
+ wiki_help_page_path: help_page_path('administration/wikis/index.md', anchor: 'reduce-wiki-repository-size')
+ }
+ get project_usage_quotas_path(project)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to include(project_usage_quotas_path(project))
+ expect(assigns[:storage_app_data]).to eq(mock_storage_app_data)
+ expect(response.body).to include("Usage of project resources across the <strong>#{project.name}</strong> project")
end
- context 'with project_storage_ui feature flag disabled' do
- before do
- stub_feature_flags(project_storage_ui: false)
- end
+ context 'renders :not_found for user without permission' do
+ let(:role) { :developer }
it_behaves_like 'response with 404 status'
end
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index 35ce942ed7e..ab0c76397e4 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -517,11 +517,15 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
let(:path) { "/v2/#{group.path}/dependency_proxy/containers/alpine/manifests/latest" }
let(:other_path) { "/v2/#{other_group.path}/dependency_proxy/containers/alpine/manifests/latest" }
let(:pull_response) { { status: :success, manifest: manifest, from_cache: false } }
+ let(:head_response) { { status: :success } }
before do
allow_next_instance_of(DependencyProxy::FindOrCreateManifestService) do |instance|
allow(instance).to receive(:execute).and_return(pull_response)
end
+ allow_next_instance_of(DependencyProxy::HeadManifestService) do |instance|
+ allow(instance).to receive(:execute).and_return(head_response)
+ end
end
it_behaves_like 'rate-limited token-authenticated requests'
diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb
index accacd705e7..701a73761fd 100644
--- a/spec/requests/users_controller_spec.rb
+++ b/spec/requests/users_controller_spec.rb
@@ -305,7 +305,7 @@ RSpec.describe UsersController do
context 'user with keys' do
let!(:gpg_key) { create(:gpg_key, user: user) }
- let!(:another_gpg_key) { create(:another_gpg_key, user: user) }
+ let!(:another_gpg_key) { create(:another_gpg_key, user: user.reload) }
shared_examples_for 'renders all verified GPG keys' do
it 'renders all verified keys separated with a new line with text/plain content type' do
diff --git a/spec/routing/group_routing_spec.rb b/spec/routing/group_routing_spec.rb
index f171c2faf5e..5c2ef62683e 100644
--- a/spec/routing/group_routing_spec.rb
+++ b/spec/routing/group_routing_spec.rb
@@ -85,6 +85,26 @@ RSpec.describe "Groups", "routing" do
expect(get('/v2')).to route_to('groups/dependency_proxy_auth#authenticate')
end
+ it 'routes to #upload_manifest' do
+ expect(post('v2/gitlabhq/dependency_proxy/containers/alpine/manifests/latest/upload'))
+ .to route_to('groups/dependency_proxy_for_containers#upload_manifest', group_id: 'gitlabhq', image: 'alpine', tag: 'latest')
+ end
+
+ it 'routes to #upload_blob' do
+ expect(post('v2/gitlabhq/dependency_proxy/containers/alpine/blobs/abc12345/upload'))
+ .to route_to('groups/dependency_proxy_for_containers#upload_blob', group_id: 'gitlabhq', image: 'alpine', sha: 'abc12345')
+ end
+
+ it 'routes to #upload_manifest_authorize' do
+ expect(post('v2/gitlabhq/dependency_proxy/containers/alpine/manifests/latest/upload/authorize'))
+ .to route_to('groups/dependency_proxy_for_containers#authorize_upload_manifest', group_id: 'gitlabhq', image: 'alpine', tag: 'latest')
+ end
+
+ it 'routes to #upload_blob_authorize' do
+ expect(post('v2/gitlabhq/dependency_proxy/containers/alpine/blobs/abc12345/upload/authorize'))
+ .to route_to('groups/dependency_proxy_for_containers#authorize_upload_blob', group_id: 'gitlabhq', image: 'alpine', sha: 'abc12345')
+ end
+
context 'image name without namespace' do
it 'routes to #manifest' do
expect(get('/v2/gitlabhq/dependency_proxy/containers/ruby/manifests/2.3.6'))
diff --git a/spec/routing/openid_connect_spec.rb b/spec/routing/openid_connect_spec.rb
index dc9190114fd..4c08a71ae31 100644
--- a/spec/routing/openid_connect_spec.rb
+++ b/spec/routing/openid_connect_spec.rb
@@ -2,20 +2,20 @@
require 'spec_helper'
-# oauth_discovery_keys GET /oauth/discovery/keys(.:format) doorkeeper/openid_connect/discovery#keys
-# oauth_discovery_provider GET /.well-known/openid-configuration(.:format) doorkeeper/openid_connect/discovery#provider
-# oauth_discovery_webfinger GET /.well-known/webfinger(.:format) doorkeeper/openid_connect/discovery#webfinger
+# oauth_discovery_keys GET /oauth/discovery/keys(.:format) jwks#keys
+# oauth_discovery_provider GET /.well-known/openid-configuration(.:format) jwks#provider
+# oauth_discovery_webfinger GET /.well-known/webfinger(.:format) jwks#webfinger
RSpec.describe Doorkeeper::OpenidConnect::DiscoveryController, 'routing' do
it "to #provider" do
- expect(get('/.well-known/openid-configuration')).to route_to('doorkeeper/openid_connect/discovery#provider')
+ expect(get('/.well-known/openid-configuration')).to route_to('jwks#provider')
end
it "to #webfinger" do
- expect(get('/.well-known/webfinger')).to route_to('doorkeeper/openid_connect/discovery#webfinger')
+ expect(get('/.well-known/webfinger')).to route_to('jwks#webfinger')
end
it "to #keys" do
- expect(get('/oauth/discovery/keys')).to route_to('doorkeeper/openid_connect/discovery#keys')
+ expect(get('/oauth/discovery/keys')).to route_to('jwks#keys')
end
end
diff --git a/spec/rubocop/cop/gitlab/bulk_insert_spec.rb b/spec/rubocop/cop/gitlab/bulk_insert_spec.rb
index bbc8f381d01..7cd003d0a70 100644
--- a/spec/rubocop/cop/gitlab/bulk_insert_spec.rb
+++ b/spec/rubocop/cop/gitlab/bulk_insert_spec.rb
@@ -6,17 +6,17 @@ require_relative '../../../../rubocop/cop/gitlab/bulk_insert'
RSpec.describe RuboCop::Cop::Gitlab::BulkInsert do
subject(:cop) { described_class.new }
- it 'flags the use of Gitlab::Database.main.bulk_insert' do
+ it 'flags the use of ApplicationRecord.legacy_bulk_insert' do
expect_offense(<<~SOURCE)
- Gitlab::Database.main.bulk_insert('merge_request_diff_files', rows)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the `BulkInsertSafe` concern, [...]
+ ApplicationRecord.legacy_bulk_insert('merge_request_diff_files', rows)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the `BulkInsertSafe` concern, [...]
SOURCE
end
- it 'flags the use of ::Gitlab::Database.main.bulk_insert' do
+ it 'flags the use of ::ApplicationRecord.legacy_bulk_insert' do
expect_offense(<<~SOURCE)
- ::Gitlab::Database.main.bulk_insert('merge_request_diff_files', rows)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the `BulkInsertSafe` concern, [...]
+ ::ApplicationRecord.legacy_bulk_insert('merge_request_diff_files', rows)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the `BulkInsertSafe` concern, [...]
SOURCE
end
end
diff --git a/spec/rubocop/cop/gitlab/change_timezone_spec.rb b/spec/rubocop/cop/gitlab/change_timezone_spec.rb
index f3c07e44cc7..ff6365aa0f7 100644
--- a/spec/rubocop/cop/gitlab/change_timezone_spec.rb
+++ b/spec/rubocop/cop/gitlab/change_timezone_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-require_relative '../../../../rubocop/cop/gitlab/change_timzone'
+require_relative '../../../../rubocop/cop/gitlab/change_timezone'
RSpec.describe RuboCop::Cop::Gitlab::ChangeTimezone do
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/qa/duplicate_testcase_link_spec.rb b/spec/rubocop/cop/qa/duplicate_testcase_link_spec.rb
new file mode 100644
index 00000000000..fb424da90e8
--- /dev/null
+++ b/spec/rubocop/cop/qa/duplicate_testcase_link_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+require_relative '../../../../rubocop/cop/qa/duplicate_testcase_link'
+
+RSpec.describe RuboCop::Cop::QA::DuplicateTestcaseLink do
+ let(:source_file) { 'qa/page.rb' }
+
+ subject(:cop) { described_class.new }
+
+ context 'in a QA file' do
+ before do
+ allow(cop).to receive(:in_qa_file?).and_return(true)
+ end
+
+ it "registers an offense for a duplicate testcase link" do
+ expect_offense(<<-RUBY)
+ it 'some test', testcase: '/quality/test_cases/1892' do
+ end
+ it 'another test', testcase: '/quality/test_cases/1892' do
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't reuse the same testcase link in different tests. Replace one of `/quality/test_cases/1892`.
+ end
+ RUBY
+ end
+
+ it "doesnt offend if testcase link is unique" do
+ expect_no_offenses(<<-RUBY)
+ it 'some test', testcase: '/quality/test_cases/1893' do
+ end
+ it 'another test', testcase: '/quality/test_cases/1894' do
+ end
+ RUBY
+ end
+ end
+end
diff --git a/spec/scripts/changed-feature-flags_spec.rb b/spec/scripts/changed-feature-flags_spec.rb
new file mode 100644
index 00000000000..5c858588c0c
--- /dev/null
+++ b/spec/scripts/changed-feature-flags_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+load File.expand_path('../../scripts/changed-feature-flags', __dir__)
+
+RSpec.describe 'scripts/changed-feature-flags' do
+ describe GetFeatureFlagsFromFiles do
+ let(:feature_flag_definition1) do
+ file = Tempfile.new('foo.yml', ff_dir)
+ file.write(<<~YAML)
+ ---
+ name: foo_flag
+ default_enabled: true
+ YAML
+ file.rewind
+ file
+ end
+
+ let(:feature_flag_definition2) do
+ file = Tempfile.new('bar.yml', ff_dir)
+ file.write(<<~YAML)
+ ---
+ name: bar_flag
+ default_enabled: false
+ YAML
+ file.rewind
+ file
+ end
+
+ after do
+ FileUtils.remove_entry(ff_dir, true)
+ end
+
+ describe '.extracted_flags' do
+ shared_examples 'extract feature flags' do
+ it 'returns feature flags on their own' do
+ subject = described_class.new({ files: [feature_flag_definition1.path, feature_flag_definition2.path] })
+
+ expect(subject.extracted_flags).to eq('foo_flag,bar_flag')
+ end
+
+ it 'returns feature flags and their state as enabled' do
+ subject = described_class.new({ files: [feature_flag_definition1.path, feature_flag_definition2.path], state: 'enabled' })
+
+ expect(subject.extracted_flags).to eq('foo_flag=enabled,bar_flag=enabled')
+ end
+
+ it 'returns feature flags and their state as disabled' do
+ subject = described_class.new({ files: [feature_flag_definition1.path, feature_flag_definition2.path], state: 'disabled' })
+
+ expect(subject.extracted_flags).to eq('foo_flag=disabled,bar_flag=disabled')
+ end
+ end
+
+ context 'with definition files in the development directory' do
+ let(:ff_dir) { FileUtils.mkdir_p(File.join(Dir.tmpdir, 'feature_flags', 'development')) }
+
+ it_behaves_like 'extract feature flags'
+ end
+
+ context 'with definition files in the ops directory' do
+ let(:ff_dir) { FileUtils.mkdir_p(File.join(Dir.tmpdir, 'feature_flags', 'ops')) }
+
+ it_behaves_like 'extract feature flags'
+ end
+
+ context 'with definition files in the experiment directory' do
+ let(:ff_dir) { FileUtils.mkdir_p(File.join(Dir.tmpdir, 'feature_flags', 'experiment')) }
+
+ it 'ignores the files' do
+ subject = described_class.new({ files: [feature_flag_definition1.path, feature_flag_definition2.path] })
+
+ expect(subject.extracted_flags).to eq('')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/scripts/failed_tests_spec.rb b/spec/scripts/failed_tests_spec.rb
new file mode 100644
index 00000000000..92eae75b3be
--- /dev/null
+++ b/spec/scripts/failed_tests_spec.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_relative '../../scripts/failed_tests'
+
+RSpec.describe FailedTests do
+ let(:report_file) { 'spec/fixtures/scripts/test_report.json' }
+ let(:output_directory) { 'tmp/previous_test_results' }
+ let(:rspec_pg_regex) { /rspec .+ pg12( .+)?/ }
+ let(:rspec_ee_pg_regex) { /rspec-ee .+ pg12( .+)?/ }
+
+ subject { described_class.new(previous_tests_report_path: report_file, output_directory: output_directory, rspec_pg_regex: rspec_pg_regex, rspec_ee_pg_regex: rspec_ee_pg_regex) }
+
+ describe '#output_failed_test_files' do
+ it 'writes the file for the suite' do
+ expect(File).to receive(:open).with(File.join(output_directory, "rspec_failed_files.txt"), 'w').once
+
+ subject.output_failed_test_files
+ end
+ end
+
+ describe '#failed_files_for_suite_collection' do
+ let(:failure_path) { 'path/to/fail_file_spec.rb' }
+ let(:other_failure_path) { 'path/to/fail_file_spec_2.rb' }
+ let(:file_contents_as_json) do
+ {
+ 'suites' => [
+ {
+ 'failed_count' => 1,
+ 'name' => 'rspec unit pg12 10/12',
+ 'test_cases' => [
+ {
+ 'status' => 'failed',
+ 'file' => failure_path
+ }
+ ]
+ },
+ {
+ 'failed_count' => 1,
+ 'name' => 'rspec-ee unit pg12',
+ 'test_cases' => [
+ {
+ 'status' => 'failed',
+ 'file' => failure_path
+ }
+ ]
+ },
+ {
+ 'failed_count' => 1,
+ 'name' => 'rspec unit pg13 10/12',
+ 'test_cases' => [
+ {
+ 'status' => 'failed',
+ 'file' => other_failure_path
+ }
+ ]
+ }
+ ]
+ }
+ end
+
+ before do
+ allow(subject).to receive(:file_contents_as_json).and_return(file_contents_as_json)
+ end
+
+ it 'returns a list of failed file paths for suite collection' do
+ result = subject.failed_files_for_suite_collection
+
+ expect(result[:rspec].to_a).to match_array(failure_path)
+ expect(result[:rspec_ee].to_a).to match_array(failure_path)
+ end
+ end
+
+ describe 'empty report' do
+ let(:file_content) do
+ '{}'
+ end
+
+ before do
+ allow(subject).to receive(:file_contents).and_return(file_content)
+ end
+
+ it 'does not fail for output files' do
+ subject.output_failed_test_files
+ end
+
+ it 'returns empty results for suite failures' do
+ result = subject.failed_files_for_suite_collection
+
+ expect(result.values.flatten).to be_empty
+ end
+ end
+
+ describe 'invalid report' do
+ let(:file_content) do
+ ''
+ end
+
+ before do
+ allow(subject).to receive(:file_contents).and_return(file_content)
+ end
+
+ it 'does not fail for output files' do
+ subject.output_failed_test_files
+ end
+
+ it 'returns empty results for suite failures' do
+ result = subject.failed_files_for_suite_collection
+
+ expect(result.values.flatten).to be_empty
+ end
+ end
+
+ describe 'missing report file' do
+ let(:report_file) { 'unknownfile.json' }
+
+ it 'does not fail for output files' do
+ subject.output_failed_test_files
+ end
+
+ it 'returns empty results for suite failures' do
+ result = subject.failed_files_for_suite_collection
+
+ expect(result.values.flatten).to be_empty
+ end
+ end
+end
diff --git a/spec/scripts/pipeline_test_report_builder_spec.rb b/spec/scripts/pipeline_test_report_builder_spec.rb
new file mode 100644
index 00000000000..8553ada044e
--- /dev/null
+++ b/spec/scripts/pipeline_test_report_builder_spec.rb
@@ -0,0 +1,185 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_relative '../../scripts/pipeline_test_report_builder'
+
+RSpec.describe PipelineTestReportBuilder do
+ let(:report_file) { 'spec/fixtures/scripts/test_report.json' }
+ let(:output_file_path) { 'tmp/previous_test_results/output_file.json' }
+
+ subject do
+ described_class.new(
+ target_project: 'gitlab-org/gitlab',
+ mr_id: '999',
+ instance_base_url: 'https://gitlab.com',
+ output_file_path: output_file_path
+ )
+ end
+
+ let(:failed_pipeline_url) { 'pipeline2_url' }
+
+ let(:failed_pipeline) do
+ {
+ 'status' => 'failed',
+ 'created_at' => (DateTime.now - 5).to_s,
+ 'web_url' => failed_pipeline_url
+ }
+ end
+
+ let(:current_pipeline) do
+ {
+ 'status' => 'running',
+ 'created_at' => DateTime.now.to_s,
+ 'web_url' => 'pipeline1_url'
+ }
+ end
+
+ let(:mr_pipelines) { [current_pipeline, failed_pipeline] }
+
+ let(:failed_build_id) { 9999 }
+
+ let(:failed_builds_for_pipeline) do
+ [
+ {
+ 'id' => failed_build_id,
+ 'stage' => 'test'
+ }
+ ]
+ end
+
+ let(:test_report_for_build) do
+ {
+ "name": "rspec-ee system pg11 geo",
+ "failed_count": 41,
+ "test_cases": [
+ {
+ "status": "failed",
+ "name": "example",
+ "classname": "ee.spec.features.geo_node_spec",
+ "file": "./ee/spec/features/geo_node_spec.rb",
+ "execution_time": 6.324748,
+ "system_output": {
+ "__content__": "\n",
+ "message": "RSpec::Core::MultipleExceptionError",
+ "type": "RSpec::Core::MultipleExceptionError"
+ }
+ }
+ ]
+ }
+ end
+
+ before do
+ allow(subject).to receive(:pipelines_for_mr).and_return(mr_pipelines)
+ allow(subject).to receive(:failed_builds_for_pipeline).and_return(failed_builds_for_pipeline)
+ end
+
+ describe '#previous_pipeline' do
+ let(:fork_pipeline_url) { 'fork_pipeline_url' }
+ let(:fork_pipeline) do
+ {
+ 'status' => 'failed',
+ 'created_at' => (DateTime.now - 5).to_s,
+ 'web_url' => fork_pipeline_url
+ }
+ end
+
+ before do
+ allow(subject).to receive(:test_report_for_build).and_return(test_report_for_build)
+ end
+
+ context 'pipeline in a fork project' do
+ let(:mr_pipelines) { [current_pipeline, fork_pipeline] }
+
+ it 'returns fork pipeline' do
+ expect(subject.previous_pipeline).to eq(fork_pipeline)
+ end
+ end
+
+ context 'pipeline in target project' do
+ it 'returns failed pipeline' do
+ expect(subject.previous_pipeline).to eq(failed_pipeline)
+ end
+ end
+ end
+
+ describe '#test_report_for_latest_pipeline' do
+ it 'fetches builds from pipeline related to MR' do
+ expect(subject).to receive(:fetch).with("#{failed_pipeline_url}/tests/suite.json?build_ids[]=#{failed_build_id}").and_return(failed_builds_for_pipeline)
+ subject.test_report_for_latest_pipeline
+ end
+
+ context 'canonical pipeline' do
+ before do
+ allow(subject).to receive(:test_report_for_build).and_return(test_report_for_build)
+ end
+
+ context 'no previous pipeline' do
+ let(:mr_pipelines) { [] }
+
+ it 'returns empty hash' do
+ expect(subject.test_report_for_latest_pipeline).to eq("{}")
+ end
+ end
+
+ context 'first pipeline scenario' do
+ let(:mr_pipelines) do
+ [
+ {
+ 'status' => 'running',
+ 'created_at' => DateTime.now.to_s
+ }
+ ]
+ end
+
+ it 'returns empty hash' do
+ expect(subject.test_report_for_latest_pipeline).to eq("{}")
+ end
+ end
+
+ context 'no previous failed pipeline' do
+ let(:mr_pipelines) do
+ [
+ {
+ 'status' => 'running',
+ 'created_at' => DateTime.now.to_s
+ },
+ {
+ 'status' => 'success',
+ 'created_at' => (DateTime.now - 5).to_s
+ }
+ ]
+ end
+
+ it 'returns empty hash' do
+ expect(subject.test_report_for_latest_pipeline).to eq("{}")
+ end
+ end
+
+ context 'no failed test builds' do
+ let(:failed_builds_for_pipeline) do
+ [
+ {
+ 'id' => 9999,
+ 'stage' => 'prepare'
+ }
+ ]
+ end
+
+ it 'returns empty hash' do
+ expect(subject.test_report_for_latest_pipeline).to eq("{}")
+ end
+ end
+
+ context 'failed pipeline and failed test builds' do
+ it 'returns populated test list for suites' do
+ actual = subject.test_report_for_latest_pipeline
+ expected = {
+ 'suites' => [test_report_for_build]
+ }.to_json
+
+ expect(actual).to eq(expected)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/serializers/analytics_summary_serializer_spec.rb b/spec/serializers/analytics_summary_serializer_spec.rb
index 9429c9d571a..6563b58c334 100644
--- a/spec/serializers/analytics_summary_serializer_spec.rb
+++ b/spec/serializers/analytics_summary_serializer_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe AnalyticsSummarySerializer do
context 'when representing with unit' do
let(:resource) do
Gitlab::CycleAnalytics::Summary::DeploymentFrequency
- .new(deployments: 10, options: { from: 1.day.ago })
+ .new(deployments: 10, options: { from: 1.day.ago }, project: project)
end
subject { described_class.new.represent(resource, with_unit: true) }
diff --git a/spec/serializers/merge_request_user_entity_spec.rb b/spec/serializers/merge_request_user_entity_spec.rb
index 026a229322e..72d1b0c0dd2 100644
--- a/spec/serializers/merge_request_user_entity_spec.rb
+++ b/spec/serializers/merge_request_user_entity_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe MergeRequestUserEntity do
let_it_be(:user) { create(:user) }
- let_it_be(:merge_request) { create(:merge_request) }
+ let_it_be(:merge_request) { create(:merge_request, assignees: [user]) }
let(:request) { EntityRequest.new(project: merge_request.target_project, current_user: user) }
@@ -18,7 +18,8 @@ RSpec.describe MergeRequestUserEntity do
it 'exposes needed attributes' do
is_expected.to include(
:id, :name, :username, :state, :avatar_url, :web_url,
- :can_merge, :can_update_merge_request, :reviewed, :approved
+ :can_merge, :can_update_merge_request, :reviewed, :approved,
+ :attention_requested
)
end
@@ -56,6 +57,10 @@ RSpec.describe MergeRequestUserEntity do
end
end
+ context 'attention_requested' do
+ it { is_expected.to include(attention_requested: true ) }
+ end
+
describe 'performance' do
let_it_be(:user_a) { create(:user) }
let_it_be(:user_b) { create(:user) }
diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index fcfdbfc0967..3e0c61a26c0 100644
--- a/spec/serializers/merge_request_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe MergeRequestWidgetEntity do
include ProjectForksHelper
+ include Gitlab::Routing.url_helpers
let(:project) { create :project, :repository }
let(:resource) { create(:merge_request, source_project: project, target_project: project) }
@@ -140,17 +141,15 @@ RSpec.describe MergeRequestWidgetEntity do
let(:role) { :developer }
it 'has add ci config path' do
- expected_path = "/#{resource.project.full_path}/-/new/#{resource.source_branch}"
+ expected_path = project_ci_pipeline_editor_path(project)
expect(subject[:merge_request_add_ci_config_path]).to include(expected_path)
end
it 'has expected params' do
expected_params = {
- commit_message: 'Add .gitlab-ci.yml',
- file_name: '.gitlab-ci.yml',
- suggest_gitlab_ci_yml: 'true',
- mr_path: "/#{resource.project.full_path}/-/merge_requests/#{resource.iid}"
+ branch_name: resource.source_branch,
+ add_new_config_file: 'true'
}.with_indifferent_access
uri = Addressable::URI.parse(subject[:merge_request_add_ci_config_path])
@@ -188,30 +187,6 @@ RSpec.describe MergeRequestWidgetEntity do
end
end
- context 'when ci_config_path is customized' do
- it 'has no path if ci_config_path is not set to our default setting' do
- project.ci_config_path = 'not_default'
-
- expect(subject[:merge_request_add_ci_config_path]).to be_nil
- end
-
- it 'has a path if ci_config_path unset' do
- expect(subject[:merge_request_add_ci_config_path]).not_to be_nil
- end
-
- it 'has a path if ci_config_path is an empty string' do
- project.ci_config_path = ''
-
- expect(subject[:merge_request_add_ci_config_path]).not_to be_nil
- end
-
- it 'has a path if ci_config_path is set to our default file' do
- project.ci_config_path = Gitlab::FileDetector::PATTERNS[:gitlab_ci]
-
- expect(subject[:merge_request_add_ci_config_path]).not_to be_nil
- end
- end
-
context 'when build feature is disabled' do
before do
project.project_feature.update!(builds_access_level: ProjectFeature::DISABLED)
diff --git a/spec/serializers/service_field_entity_spec.rb b/spec/serializers/service_field_entity_spec.rb
index 6e9ebfb66d9..a06fdf95159 100644
--- a/spec/serializers/service_field_entity_spec.rb
+++ b/spec/serializers/service_field_entity_spec.rb
@@ -27,7 +27,8 @@ RSpec.describe ServiceFieldEntity do
help: 'Use a username for server version and an email for cloud version.',
required: true,
choices: nil,
- value: 'jira_username'
+ value: 'jira_username',
+ checkbox_label: nil
}
is_expected.to eq(expected_hash)
@@ -46,7 +47,8 @@ RSpec.describe ServiceFieldEntity do
help: 'Leave blank to use your current password or API token.',
required: true,
choices: nil,
- value: 'true'
+ value: 'true',
+ checkbox_label: nil
}
is_expected.to eq(expected_hash)
@@ -68,7 +70,8 @@ RSpec.describe ServiceFieldEntity do
placeholder: nil,
required: nil,
choices: nil,
- value: 'true'
+ value: 'true',
+ checkbox_label: nil
}
is_expected.to include(expected_hash)
@@ -83,12 +86,13 @@ RSpec.describe ServiceFieldEntity do
expected_hash = {
type: 'select',
name: 'branches_to_be_notified',
- title: nil,
+ title: 'Branches for which notifications are to be sent',
placeholder: nil,
required: nil,
choices: [['All branches', 'all'], ['Default branch', 'default'], ['Protected branches', 'protected'], ['Default branch and protected branches', 'default_and_protected']],
help: nil,
- value: nil
+ value: nil,
+ checkbox_label: nil
}
is_expected.to eq(expected_hash)
diff --git a/spec/services/admin/propagate_integration_service_spec.rb b/spec/services/admin/propagate_integration_service_spec.rb
index 151658fe429..b379286ba4f 100644
--- a/spec/services/admin/propagate_integration_service_spec.rb
+++ b/spec/services/admin/propagate_integration_service_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe Admin::PropagateIntegrationService do
end
context 'for a group-level integration' do
- let(:group_integration) { create(:jira_integration, group: group, project: nil) }
+ let(:group_integration) { create(:jira_integration, :group, group: group) }
context 'with a project without integration' do
let(:another_project) { create(:project, group: group) }
@@ -81,7 +81,7 @@ RSpec.describe Admin::PropagateIntegrationService do
context 'with a subgroup with integration' do
let(:subgroup) { create(:group, parent: group) }
- let(:subgroup_integration) { create(:jira_integration, group: subgroup, project: nil, inherit_from_id: group_integration.id) }
+ let(:subgroup_integration) { create(:jira_integration, :group, group: subgroup, inherit_from_id: group_integration.id) }
it 'calls to PropagateIntegrationInheritDescendantWorker' do
expect(PropagateIntegrationInheritDescendantWorker).to receive(:perform_async)
diff --git a/spec/services/authorized_project_update/project_access_changed_service_spec.rb b/spec/services/authorized_project_update/project_access_changed_service_spec.rb
new file mode 100644
index 00000000000..11621055a47
--- /dev/null
+++ b/spec/services/authorized_project_update/project_access_changed_service_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AuthorizedProjectUpdate::ProjectAccessChangedService do
+ describe '#execute' do
+ it 'schedules the project IDs' do
+ expect(AuthorizedProjectUpdate::ProjectRecalculateWorker).to receive(:bulk_perform_and_wait)
+ .with([[1], [2]])
+
+ described_class.new([1, 2]).execute
+ end
+
+ it 'permits non-blocking operation' do
+ expect(AuthorizedProjectUpdate::ProjectRecalculateWorker).to receive(:bulk_perform_async)
+ .with([[1], [2]])
+
+ described_class.new([1, 2]).execute(blocking: false)
+ end
+ end
+end
diff --git a/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb b/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb
index eaa5f723bec..6f28f892f00 100644
--- a/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb
+++ b/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb
@@ -24,6 +24,10 @@ RSpec.describe AutoMerge::MergeWhenPipelineSucceedsService do
project.add_maintainer(user)
end
+ before do
+ allow(MergeWorker).to receive(:with_status).and_return(MergeWorker)
+ end
+
describe "#available_for?" do
subject { service.available_for?(mr_merge_if_green_enabled) }
diff --git a/spec/services/award_emojis/base_service_spec.rb b/spec/services/award_emojis/base_service_spec.rb
new file mode 100644
index 00000000000..e0c8fd39ad9
--- /dev/null
+++ b/spec/services/award_emojis/base_service_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AwardEmojis::BaseService do
+ let(:awardable) { build(:note) }
+ let(:current_user) { build(:user) }
+
+ describe '.initialize' do
+ subject { described_class }
+
+ it 'uses same emoji name if not an alias' do
+ emoji_name = 'horse'
+
+ expect(subject.new(awardable, emoji_name, current_user).name).to eq(emoji_name)
+ end
+
+ it 'uses emoji original name if its an alias' do
+ emoji_alias = 'small_airplane'
+ emoji_name = 'airplane_small'
+
+ expect(subject.new(awardable, emoji_alias, current_user).name).to eq(emoji_name)
+ end
+ end
+end
diff --git a/spec/services/bulk_create_integration_service_spec.rb b/spec/services/bulk_create_integration_service_spec.rb
index 517222c0e69..63bdc39857c 100644
--- a/spec/services/bulk_create_integration_service_spec.rb
+++ b/spec/services/bulk_create_integration_service_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe BulkCreateIntegrationService do
end
context 'integration with data fields' do
- let(:excluded_attributes) { %w[id service_id created_at updated_at] }
+ let(:excluded_attributes) { %w[id service_id integration_id created_at updated_at] }
it 'updates the data fields from inherited integrations' do
described_class.new(integration, batch, association).execute
@@ -74,7 +74,7 @@ RSpec.describe BulkCreateIntegrationService do
context 'with a project association' do
let!(:project) { create(:project, group: group) }
- let(:integration) { create(:jira_integration, group: group, project: nil) }
+ let(:integration) { create(:jira_integration, :group, group: group) }
let(:created_integration) { project.jira_integration }
let(:batch) { Project.where(id: Project.minimum(:id)..Project.maximum(:id)).without_integration(integration).in_namespace(integration.group.self_and_descendants) }
let(:association) { 'project' }
@@ -82,11 +82,19 @@ RSpec.describe BulkCreateIntegrationService do
it_behaves_like 'creates integration from batch ids'
it_behaves_like 'updates inherit_from_id'
+
+ context 'with different foreign key of data_fields' do
+ let(:integration) { create(:zentao_integration, :group, group: group) }
+ let(:created_integration) { project.zentao_integration }
+
+ it_behaves_like 'creates integration from batch ids'
+ it_behaves_like 'updates inherit_from_id'
+ end
end
context 'with a group association' do
let!(:subgroup) { create(:group, parent: group) }
- let(:integration) { create(:jira_integration, group: group, project: nil, inherit_from_id: instance_integration.id) }
+ let(:integration) { create(:jira_integration, :group, group: group, inherit_from_id: instance_integration.id) }
let(:created_integration) { Integration.find_by(group: subgroup) }
let(:batch) { Group.where(id: subgroup.id) }
let(:association) { 'group' }
@@ -94,6 +102,13 @@ RSpec.describe BulkCreateIntegrationService do
it_behaves_like 'creates integration from batch ids'
it_behaves_like 'updates inherit_from_id'
+
+ context 'with different foreign key of data_fields' do
+ let(:integration) { create(:zentao_integration, :group, group: group, inherit_from_id: instance_integration.id) }
+
+ it_behaves_like 'creates integration from batch ids'
+ it_behaves_like 'updates inherit_from_id'
+ end
end
end
end
diff --git a/spec/services/bulk_update_integration_service_spec.rb b/spec/services/bulk_update_integration_service_spec.rb
index c10a9b75648..5e521b98482 100644
--- a/spec/services/bulk_update_integration_service_spec.rb
+++ b/spec/services/bulk_update_integration_service_spec.rb
@@ -16,32 +16,19 @@ RSpec.describe BulkUpdateIntegrationService do
let_it_be(:group) { create(:group) }
let_it_be(:subgroup) { create(:group, parent: group) }
- let_it_be(:group_integration) do
- Integrations::Jira.create!(
- group: group,
- url: 'http://group.jira.com'
- )
- end
-
+ let_it_be(:group_integration) { create(:jira_integration, :group, group: group, url: 'http://group.jira.com') }
+ let_it_be(:excluded_integration) { create(:jira_integration, :group, group: create(:group), url: 'http://another.jira.com', push_events: false) }
let_it_be(:subgroup_integration) do
- Integrations::Jira.create!(
- inherit_from_id: group_integration.id,
+ create(:jira_integration, :group,
group: subgroup,
+ inherit_from_id: group_integration.id,
url: 'http://subgroup.jira.com',
push_events: true
)
end
- let_it_be(:excluded_integration) do
- Integrations::Jira.create!(
- group: create(:group),
- url: 'http://another.jira.com',
- push_events: false
- )
- end
-
let_it_be(:integration) do
- Integrations::Jira.create!(
+ create(:jira_integration,
project: create(:project, group: subgroup),
inherit_from_id: subgroup_integration.id,
url: 'http://project.jira.com',
@@ -88,4 +75,22 @@ RSpec.describe BulkUpdateIntegrationService do
described_class.new(group_integration, [integration]).execute
end.to change { integration.reload.url }.to(group_integration.url)
end
+
+ context 'with different foreign key of data_fields' do
+ let(:integration) { create(:zentao_integration, project: create(:project, group: group)) }
+ let(:group_integration) do
+ create(:zentao_integration, :group,
+ group: group,
+ url: 'https://group.zentao.net',
+ api_token: 'GROUP_TOKEN',
+ zentao_product_xid: '1'
+ )
+ end
+
+ it 'works with batch as an array of ActiveRecord objects' do
+ expect do
+ described_class.new(group_integration, [integration]).execute
+ end.to change { integration.reload.url }.to(group_integration.url)
+ end
+ end
end
diff --git a/spec/services/ci/create_pipeline_service/include_spec.rb b/spec/services/ci/create_pipeline_service/include_spec.rb
index 5e7dace8e15..aa01977272a 100644
--- a/spec/services/ci/create_pipeline_service/include_spec.rb
+++ b/spec/services/ci/create_pipeline_service/include_spec.rb
@@ -7,9 +7,11 @@ RSpec.describe Ci::CreatePipelineService do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { project.owner }
- let(:ref) { 'refs/heads/master' }
- let(:source) { :push }
- let(:service) { described_class.new(project, user, { ref: ref }) }
+ let(:ref) { 'refs/heads/master' }
+ let(:variables_attributes) { [{ key: 'MYVAR', secret_value: 'hello' }] }
+ let(:source) { :push }
+
+ let(:service) { described_class.new(project, user, { ref: ref, variables_attributes: variables_attributes }) }
let(:pipeline) { service.execute(source).payload }
let(:file_location) { 'spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml' }
@@ -24,6 +26,20 @@ RSpec.describe Ci::CreatePipelineService do
.and_return(File.read(Rails.root.join(file_location)))
end
+ shared_examples 'not including the file' do
+ it 'does not include the job in the file' do
+ expect(pipeline).to be_created_successfully
+ expect(pipeline.processables.pluck(:name)).to contain_exactly('job')
+ end
+ end
+
+ shared_examples 'including the file' do
+ it 'includes the job in the file' do
+ expect(pipeline).to be_created_successfully
+ expect(pipeline.processables.pluck(:name)).to contain_exactly('job', 'rspec')
+ end
+ end
+
context 'with a local file' do
let(:config) do
<<~EOY
@@ -33,13 +49,10 @@ RSpec.describe Ci::CreatePipelineService do
EOY
end
- it 'includes the job in the file' do
- expect(pipeline).to be_created_successfully
- expect(pipeline.processables.pluck(:name)).to contain_exactly('job', 'rspec')
- end
+ it_behaves_like 'including the file'
end
- context 'with a local file with rules' do
+ context 'with a local file with rules with a project variable' do
let(:config) do
<<~EOY
include:
@@ -54,19 +67,63 @@ RSpec.describe Ci::CreatePipelineService do
context 'when the rules matches' do
let(:project_id) { project.id }
- it 'includes the job in the file' do
- expect(pipeline).to be_created_successfully
- expect(pipeline.processables.pluck(:name)).to contain_exactly('job', 'rspec')
- end
+ it_behaves_like 'including the file'
end
context 'when the rules does not match' do
let(:project_id) { non_existing_record_id }
- it 'does not include the job in the file' do
- expect(pipeline).to be_created_successfully
- expect(pipeline.processables.pluck(:name)).to contain_exactly('job')
- end
+ it_behaves_like 'not including the file'
+ end
+ end
+
+ context 'with a local file with rules with a predefined pipeline variable' do
+ let(:config) do
+ <<~EOY
+ include:
+ - local: #{file_location}
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "#{pipeline_source}"
+ job:
+ script: exit 0
+ EOY
+ end
+
+ context 'when the rules matches' do
+ let(:pipeline_source) { 'push' }
+
+ it_behaves_like 'including the file'
+ end
+
+ context 'when the rules does not match' do
+ let(:pipeline_source) { 'web' }
+
+ it_behaves_like 'not including the file'
+ end
+ end
+
+ context 'with a local file with rules with a run pipeline variable' do
+ let(:config) do
+ <<~EOY
+ include:
+ - local: #{file_location}
+ rules:
+ - if: $MYVAR == "#{my_var}"
+ job:
+ script: exit 0
+ EOY
+ end
+
+ context 'when the rules matches' do
+ let(:my_var) { 'hello' }
+
+ it_behaves_like 'including the file'
+ end
+
+ context 'when the rules does not match' do
+ let(:my_var) { 'mello' }
+
+ it_behaves_like 'not including the file'
end
end
end
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 78646665539..c78e19ea62d 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe Ci::CreatePipelineService do
include ProjectForksHelper
- let_it_be(:project, reload: true) { create(:project, :repository) }
- let_it_be(:user, reload: true) { project.owner }
+ let_it_be_with_refind(:project) { create(:project, :repository) }
+ let_it_be_with_reload(:user) { project.owner }
let(:ref_name) { 'refs/heads/master' }
diff --git a/spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb b/spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb
index 04d75630295..d5881d3b204 100644
--- a/spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb
+++ b/spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb
@@ -26,28 +26,6 @@ RSpec.describe Ci::ExternalPullRequests::CreatePipelineService do
pull_request.update!(source_branch: source_branch.name, source_sha: source_branch.target)
end
- context 'when the FF ci_create_external_pr_pipeline_async is disabled' do
- before do
- stub_feature_flags(ci_create_external_pr_pipeline_async: false)
- end
-
- it 'creates a pipeline for external pull request', :aggregate_failures do
- pipeline = execute.payload
-
- expect(execute).to be_success
- expect(pipeline).to be_valid
- expect(pipeline).to be_persisted
- expect(pipeline).to be_external_pull_request_event
- expect(pipeline).to eq(project.ci_pipelines.last)
- expect(pipeline.external_pull_request).to eq(pull_request)
- expect(pipeline.user).to eq(user)
- expect(pipeline.status).to eq('created')
- expect(pipeline.ref).to eq(pull_request.source_branch)
- expect(pipeline.sha).to eq(pull_request.source_sha)
- expect(pipeline.source_sha).to eq(pull_request.source_sha)
- end
- end
-
it 'enqueues Ci::ExternalPullRequests::CreatePipelineWorker' do
expect { execute }
.to change { ::Ci::ExternalPullRequests::CreatePipelineWorker.jobs.count }
diff --git a/spec/services/ci/generate_kubeconfig_service_spec.rb b/spec/services/ci/generate_kubeconfig_service_spec.rb
new file mode 100644
index 00000000000..b0673d16158
--- /dev/null
+++ b/spec/services/ci/generate_kubeconfig_service_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::GenerateKubeconfigService do
+ describe '#execute' do
+ let(:project) { create(:project) }
+ let(:build) { create(:ci_build, project: project) }
+ let(:agent1) { create(:cluster_agent, project: project) }
+ let(:agent2) { create(:cluster_agent) }
+
+ let(:template) { instance_double(Gitlab::Kubernetes::Kubeconfig::Template) }
+
+ subject { described_class.new(build).execute }
+
+ before do
+ expect(Gitlab::Kubernetes::Kubeconfig::Template).to receive(:new).and_return(template)
+ expect(build.pipeline).to receive(:authorized_cluster_agents).and_return([agent1, agent2])
+ end
+
+ it 'adds a cluster, and a user and context for each available agent' do
+ expect(template).to receive(:add_cluster).with(
+ name: 'gitlab',
+ url: Gitlab::Kas.tunnel_url
+ ).once
+
+ expect(template).to receive(:add_user).with(
+ name: "agent:#{agent1.id}",
+ token: "ci:#{agent1.id}:#{build.token}"
+ )
+ expect(template).to receive(:add_user).with(
+ name: "agent:#{agent2.id}",
+ token: "ci:#{agent2.id}:#{build.token}"
+ )
+
+ expect(template).to receive(:add_context).with(
+ name: "#{project.full_path}:#{agent1.name}",
+ cluster: 'gitlab',
+ user: "agent:#{agent1.id}"
+ )
+ expect(template).to receive(:add_context).with(
+ name: "#{agent2.project.full_path}:#{agent2.name}",
+ cluster: 'gitlab',
+ user: "agent:#{agent2.id}"
+ )
+
+ expect(subject).to eq(template)
+ end
+ end
+end
diff --git a/spec/services/ci/job_artifacts/create_service_spec.rb b/spec/services/ci/job_artifacts/create_service_spec.rb
index e6d9f208096..6ad3e9ceb54 100644
--- a/spec/services/ci/job_artifacts/create_service_spec.rb
+++ b/spec/services/ci/job_artifacts/create_service_spec.rb
@@ -49,6 +49,7 @@ RSpec.describe Ci::JobArtifacts::CreateService do
expect(new_artifact.file_type).to eq(params['artifact_type'])
expect(new_artifact.file_format).to eq(params['artifact_format'])
expect(new_artifact.file_sha256).to eq(artifacts_sha256)
+ expect(new_artifact.locked).to eq(job.pipeline.locked)
end
it 'does not track the job user_id' do
@@ -75,6 +76,7 @@ RSpec.describe Ci::JobArtifacts::CreateService do
expect(new_artifact.file_type).to eq('metadata')
expect(new_artifact.file_format).to eq('gzip')
expect(new_artifact.file_sha256).to eq(artifacts_sha256)
+ expect(new_artifact.locked).to eq(job.pipeline.locked)
end
it 'sets expiration date according to application settings' do
@@ -175,18 +177,6 @@ RSpec.describe Ci::JobArtifacts::CreateService do
hash_including('key' => 'KEY1', 'value' => 'VAR1', 'source' => 'dotenv'),
hash_including('key' => 'KEY2', 'value' => 'VAR2', 'source' => 'dotenv'))
end
-
- context 'when ci_synchronous_artifact_parsing feature flag is disabled' do
- before do
- stub_feature_flags(ci_synchronous_artifact_parsing: false)
- end
-
- it 'does not call parse service' do
- expect(Ci::ParseDotenvArtifactService).not_to receive(:new)
-
- expect(subject[:status]).to eq(:success)
- end
- end
end
context 'when artifact_type is metrics' do
diff --git a/spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb b/spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb
index 7a91ad9dcc1..6761f052e18 100644
--- a/spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb
+++ b/spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb
@@ -16,26 +16,43 @@ RSpec.describe Ci::JobArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_s
let_it_be(:job) { create(:ci_build, :success, pipeline: pipeline) }
context 'when artifact is expired' do
- let!(:artifact) { create(:ci_job_artifact, :expired, job: job) }
+ let!(:artifact) { create(:ci_job_artifact, :expired, job: job, locked: job.pipeline.locked) }
context 'with preloaded relationships' do
before do
stub_const("#{described_class}::LOOP_LIMIT", 1)
end
- it 'performs the smallest number of queries for job_artifacts' do
- log = ActiveRecord::QueryRecorder.new { subject }
+ context 'with ci_destroy_unlocked_job_artifacts feature flag disabled' do
+ before do
+ stub_feature_flags(ci_destroy_unlocked_job_artifacts: false)
+ end
+
+ it 'performs the smallest number of queries for job_artifacts' do
+ log = ActiveRecord::QueryRecorder.new { subject }
+
+ # SELECT expired ci_job_artifacts - 3 queries from each_batch
+ # PRELOAD projects, routes, project_statistics
+ # BEGIN
+ # INSERT into ci_deleted_objects
+ # DELETE loaded ci_job_artifacts
+ # DELETE security_findings -- for EE
+ # COMMIT
+ # SELECT next expired ci_job_artifacts
+
+ expect(log.count).to be_within(1).of(10)
+ end
+ end
- # SELECT expired ci_job_artifacts - 3 queries from each_batch
- # PRELOAD projects, routes, project_statistics
- # BEGIN
- # INSERT into ci_deleted_objects
- # DELETE loaded ci_job_artifacts
- # DELETE security_findings -- for EE
- # COMMIT
- # SELECT next expired ci_job_artifacts
+ context 'with ci_destroy_unlocked_job_artifacts feature flag enabled' do
+ before do
+ stub_feature_flags(ci_destroy_unlocked_job_artifacts: true)
+ end
- expect(log.count).to be_within(1).of(10)
+ it 'performs the smallest number of queries for job_artifacts' do
+ log = ActiveRecord::QueryRecorder.new { subject }
+ expect(log.count).to be_within(1).of(8)
+ end
end
end
@@ -53,7 +70,7 @@ RSpec.describe Ci::JobArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_s
end
context 'when the artifact has a file attached to it' do
- let!(:artifact) { create(:ci_job_artifact, :expired, :zip, job: job) }
+ let!(:artifact) { create(:ci_job_artifact, :expired, :zip, job: job, locked: job.pipeline.locked) }
it 'creates a deleted object' do
expect { subject }.to change { Ci::DeletedObject.count }.by(1)
@@ -74,7 +91,7 @@ RSpec.describe Ci::JobArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_s
end
context 'when artifact is locked' do
- let!(:artifact) { create(:ci_job_artifact, :expired, job: locked_job) }
+ let!(:artifact) { create(:ci_job_artifact, :expired, job: locked_job, locked: locked_job.pipeline.locked) }
it 'does not destroy job artifact' do
expect { subject }.not_to change { Ci::JobArtifact.count }
@@ -83,7 +100,7 @@ RSpec.describe Ci::JobArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_s
end
context 'when artifact is not expired' do
- let!(:artifact) { create(:ci_job_artifact, job: job) }
+ let!(:artifact) { create(:ci_job_artifact, job: job, locked: job.pipeline.locked) }
it 'does not destroy expired job artifacts' do
expect { subject }.not_to change { Ci::JobArtifact.count }
@@ -91,7 +108,7 @@ RSpec.describe Ci::JobArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_s
end
context 'when artifact is permanent' do
- let!(:artifact) { create(:ci_job_artifact, expire_at: nil, job: job) }
+ let!(:artifact) { create(:ci_job_artifact, expire_at: nil, job: job, locked: job.pipeline.locked) }
it 'does not destroy expired job artifacts' do
expect { subject }.not_to change { Ci::JobArtifact.count }
@@ -99,7 +116,7 @@ RSpec.describe Ci::JobArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_s
end
context 'when failed to destroy artifact' do
- let!(:artifact) { create(:ci_job_artifact, :expired, job: job) }
+ let!(:artifact) { create(:ci_job_artifact, :expired, job: job, locked: job.pipeline.locked) }
before do
stub_const("#{described_class}::LOOP_LIMIT", 10)
@@ -135,7 +152,7 @@ RSpec.describe Ci::JobArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_s
end
context 'when exclusive lease has already been taken by the other instance' do
- let!(:artifact) { create(:ci_job_artifact, :expired, job: job) }
+ let!(:artifact) { create(:ci_job_artifact, :expired, job: job, locked: job.pipeline.locked) }
before do
stub_exclusive_lease_taken(described_class::EXCLUSIVE_LOCK_KEY, timeout: described_class::LOCK_TIMEOUT)
@@ -149,8 +166,8 @@ RSpec.describe Ci::JobArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_s
context 'with a second artifact and batch size of 1' do
let(:second_job) { create(:ci_build, :success, pipeline: pipeline) }
- let!(:second_artifact) { create(:ci_job_artifact, :archive, expire_at: 1.day.ago, job: second_job) }
- let!(:artifact) { create(:ci_job_artifact, :expired, job: job) }
+ let!(:second_artifact) { create(:ci_job_artifact, :archive, expire_at: 1.day.ago, job: second_job, locked: job.pipeline.locked) }
+ let!(:artifact) { create(:ci_job_artifact, :expired, job: job, locked: job.pipeline.locked) }
before do
stub_const("#{described_class}::BATCH_SIZE", 1)
@@ -206,8 +223,8 @@ RSpec.describe Ci::JobArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_s
end
context 'when some artifacts are locked' do
- let!(:artifact) { create(:ci_job_artifact, :expired, job: job) }
- let!(:locked_artifact) { create(:ci_job_artifact, :expired, job: locked_job) }
+ let!(:artifact) { create(:ci_job_artifact, :expired, job: job, locked: job.pipeline.locked) }
+ let!(:locked_artifact) { create(:ci_job_artifact, :expired, job: locked_job, locked: locked_job.pipeline.locked) }
it 'destroys only unlocked artifacts' do
expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
@@ -216,7 +233,7 @@ RSpec.describe Ci::JobArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_s
end
context 'when all artifacts are locked' do
- let!(:artifact) { create(:ci_job_artifact, :expired, job: locked_job) }
+ let!(:artifact) { create(:ci_job_artifact, :expired, job: locked_job, locked: locked_job.pipeline.locked) }
it 'destroys no artifacts' do
expect { subject }.to change { Ci::JobArtifact.count }.by(0)
diff --git a/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb b/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb
index 2cedbf93d74..1cc856734fc 100644
--- a/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb
+++ b/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb
@@ -29,7 +29,8 @@ RSpec.describe Ci::JobArtifacts::DestroyBatchService do
it 'reports metrics for destroyed artifacts' do
expect_next_instance_of(Gitlab::Ci::Artifacts::Metrics) do |metrics|
- expect(metrics).to receive(:increment_destroyed_artifacts).with(1).and_call_original
+ expect(metrics).to receive(:increment_destroyed_artifacts_count).with(1).and_call_original
+ expect(metrics).to receive(:increment_destroyed_artifacts_bytes).with(107464).and_call_original
end
execute
diff --git a/spec/services/ci/parse_dotenv_artifact_service_spec.rb b/spec/services/ci/parse_dotenv_artifact_service_spec.rb
index 7536e04f2de..c4040a426f2 100644
--- a/spec/services/ci/parse_dotenv_artifact_service_spec.rb
+++ b/spec/services/ci/parse_dotenv_artifact_service_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'returns error' do
expect(subject[:status]).to eq(:error)
- expect(subject[:message]).to eq("Dotenv Artifact Too Big. Maximum Allowable Size: #{described_class::MAX_ACCEPTABLE_DOTENV_SIZE}")
+ expect(subject[:message]).to eq("Dotenv Artifact Too Big. Maximum Allowable Size: #{service.send(:dotenv_size_limit)}")
expect(subject[:http_status]).to eq(:bad_request)
end
end
@@ -186,7 +186,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
context 'when more than limitated variables are specified in dotenv' do
let(:blob) do
StringIO.new.tap do |s|
- (described_class::MAX_ACCEPTABLE_VARIABLES_COUNT + 1).times do |i|
+ (service.send(:dotenv_variable_limit) + 1).times do |i|
s << "KEY#{i}=VAR#{i}\n"
end
end.string
@@ -194,7 +194,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
it 'returns error' do
expect(subject[:status]).to eq(:error)
- expect(subject[:message]).to eq("Dotenv files cannot have more than #{described_class::MAX_ACCEPTABLE_VARIABLES_COUNT} variables")
+ expect(subject[:message]).to eq("Dotenv files cannot have more than #{service.send(:dotenv_variable_limit)} variables")
expect(subject[:http_status]).to eq(:bad_request)
end
end
diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb
index 15c88c9f657..16635c64434 100644
--- a/spec/services/ci/retry_build_service_spec.rb
+++ b/spec/services/ci/retry_build_service_spec.rb
@@ -323,6 +323,37 @@ RSpec.describe Ci::RetryBuildService do
it 'persists expanded environment name' do
expect(new_build.metadata.expanded_environment_name).to eq('production')
end
+
+ it 'does not create a new environment' do
+ expect { new_build }.not_to change { Environment.count }
+ end
+ end
+
+ context 'when build with dynamic environment is retried' do
+ let_it_be(:other_developer) { create(:user).tap { |u| project.add_developer(other_developer) } }
+
+ let(:environment_name) { 'review/$CI_COMMIT_REF_SLUG-$GITLAB_USER_ID' }
+
+ let!(:build) do
+ create(:ci_build, :with_deployment, environment: environment_name,
+ options: { environment: { name: environment_name } },
+ pipeline: pipeline, stage_id: stage.id, project: project,
+ user: other_developer)
+ end
+
+ it 're-uses the previous persisted environment' do
+ expect(build.persisted_environment.name).to eq("review/#{build.ref}-#{other_developer.id}")
+
+ expect(new_build.persisted_environment.name).to eq("review/#{build.ref}-#{other_developer.id}")
+ end
+
+ it 'creates a new deployment' do
+ expect { new_build }.to change { Deployment.count }.by(1)
+ end
+
+ it 'does not create a new environment' do
+ expect { new_build }.not_to change { Environment.count }
+ end
end
context 'when build has needs' do
diff --git a/spec/services/ci/unlock_artifacts_service_spec.rb b/spec/services/ci/unlock_artifacts_service_spec.rb
index 8d289a867ba..8ee07fc44c8 100644
--- a/spec/services/ci/unlock_artifacts_service_spec.rb
+++ b/spec/services/ci/unlock_artifacts_service_spec.rb
@@ -3,93 +3,247 @@
require 'spec_helper'
RSpec.describe Ci::UnlockArtifactsService do
- describe '#execute' do
- subject(:execute) { described_class.new(pipeline.project, pipeline.user).execute(ci_ref, before_pipeline) }
+ using RSpec::Parameterized::TableSyntax
+
+ where(:tag, :ci_update_unlocked_job_artifacts) do
+ false | false
+ false | true
+ true | false
+ true | true
+ end
+
+ with_them do
+ let(:ref) { 'master' }
+ let(:ref_path) { tag ? "#{::Gitlab::Git::TAG_REF_PREFIX}#{ref}" : "#{::Gitlab::Git::BRANCH_REF_PREFIX}#{ref}" }
+ let(:ci_ref) { create(:ci_ref, ref_path: ref_path) }
+ let(:project) { ci_ref.project }
+ let(:source_job) { create(:ci_build, pipeline: pipeline) }
+
+ let!(:old_unlocked_pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: ref, tag: tag, project: project, locked: :unlocked) }
+ let!(:older_pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: ref, tag: tag, project: project, locked: :artifacts_locked) }
+ let!(:older_ambiguous_pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: ref, tag: !tag, project: project, locked: :artifacts_locked) }
+ let!(:pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: ref, tag: tag, project: project, locked: :artifacts_locked) }
+ let!(:child_pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: ref, tag: tag, project: project, locked: :artifacts_locked) }
+ let!(:newer_pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: ref, tag: tag, project: project, locked: :artifacts_locked) }
+ let!(:other_ref_pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: 'other_ref', tag: tag, project: project, locked: :artifacts_locked) }
+ let!(:sources_pipeline) { create(:ci_sources_pipeline, source_job: source_job, source_project: project, pipeline: child_pipeline, project: project) }
before do
stub_const("#{described_class}::BATCH_SIZE", 1)
+ stub_feature_flags(ci_update_unlocked_job_artifacts: ci_update_unlocked_job_artifacts)
end
- [true, false].each do |tag|
- context "when tag is #{tag}" do
- let(:ref) { 'master' }
- let(:ref_path) { tag ? "#{::Gitlab::Git::TAG_REF_PREFIX}#{ref}" : "#{::Gitlab::Git::BRANCH_REF_PREFIX}#{ref}" }
- let(:ci_ref) { create(:ci_ref, ref_path: ref_path) }
+ describe '#execute' do
+ subject(:execute) { described_class.new(pipeline.project, pipeline.user).execute(ci_ref, before_pipeline) }
+
+ context 'when running on a ref before a pipeline' do
+ let(:before_pipeline) { pipeline }
+
+ it 'unlocks artifacts from older pipelines' do
+ expect { execute }.to change { older_pipeline.reload.locked }.from('artifacts_locked').to('unlocked')
+ end
+
+ it 'does not unlock artifacts for tag or branch with same name as ref' do
+ expect { execute }.not_to change { older_ambiguous_pipeline.reload.locked }.from('artifacts_locked')
+ end
+
+ it 'does not unlock artifacts from newer pipelines' do
+ expect { execute }.not_to change { newer_pipeline.reload.locked }.from('artifacts_locked')
+ end
+
+ it 'does not lock artifacts from old unlocked pipelines' do
+ expect { execute }.not_to change { old_unlocked_pipeline.reload.locked }.from('unlocked')
+ end
+
+ it 'does not unlock artifacts from the same pipeline' do
+ expect { execute }.not_to change { pipeline.reload.locked }.from('artifacts_locked')
+ end
- let!(:old_unlocked_pipeline) { create(:ci_pipeline, ref: ref, tag: tag, project: ci_ref.project, locked: :unlocked) }
- let!(:older_pipeline) { create(:ci_pipeline, ref: ref, tag: tag, project: ci_ref.project, locked: :artifacts_locked) }
- let!(:older_ambiguous_pipeline) { create(:ci_pipeline, ref: ref, tag: !tag, project: ci_ref.project, locked: :artifacts_locked) }
- let!(:pipeline) { create(:ci_pipeline, ref: ref, tag: tag, project: ci_ref.project, locked: :artifacts_locked) }
- let!(:child_pipeline) { create(:ci_pipeline, ref: ref, tag: tag, project: ci_ref.project, locked: :artifacts_locked) }
- let!(:newer_pipeline) { create(:ci_pipeline, ref: ref, tag: tag, project: ci_ref.project, locked: :artifacts_locked) }
- let!(:other_ref_pipeline) { create(:ci_pipeline, ref: 'other_ref', tag: tag, project: ci_ref.project, locked: :artifacts_locked) }
+ it 'does not unlock artifacts for other refs' do
+ expect { execute }.not_to change { other_ref_pipeline.reload.locked }.from('artifacts_locked')
+ end
- before do
- create(:ci_sources_pipeline,
- source_job: create(:ci_build, pipeline: pipeline),
- source_project: ci_ref.project,
- pipeline: child_pipeline,
- project: ci_ref.project)
+ it 'does not unlock artifacts for child pipeline' do
+ expect { execute }.not_to change { child_pipeline.reload.locked }.from('artifacts_locked')
end
- context 'when running on a ref before a pipeline' do
- let(:before_pipeline) { pipeline }
+ it 'unlocks job artifact records' do
+ pending unless ci_update_unlocked_job_artifacts
- it 'unlocks artifacts from older pipelines' do
- expect { execute }.to change { older_pipeline.reload.locked }.from('artifacts_locked').to('unlocked')
- end
+ expect { execute }.to change { ::Ci::JobArtifact.artifact_unlocked.count }.from(0).to(2)
+ end
+ end
- it 'does not unlock artifacts for tag or branch with same name as ref' do
- expect { execute }.not_to change { older_ambiguous_pipeline.reload.locked }.from('artifacts_locked')
- end
+ context 'when running on just the ref' do
+ let(:before_pipeline) { nil }
- it 'does not unlock artifacts from newer pipelines' do
- expect { execute }.not_to change { newer_pipeline.reload.locked }.from('artifacts_locked')
- end
+ it 'unlocks artifacts from older pipelines' do
+ expect { execute }.to change { older_pipeline.reload.locked }.from('artifacts_locked').to('unlocked')
+ end
- it 'does not lock artifacts from old unlocked pipelines' do
- expect { execute }.not_to change { old_unlocked_pipeline.reload.locked }.from('unlocked')
- end
+ it 'unlocks artifacts from newer pipelines' do
+ expect { execute }.to change { newer_pipeline.reload.locked }.from('artifacts_locked').to('unlocked')
+ end
- it 'does not unlock artifacts from the same pipeline' do
- expect { execute }.not_to change { pipeline.reload.locked }.from('artifacts_locked')
- end
+ it 'unlocks artifacts from the same pipeline' do
+ expect { execute }.to change { pipeline.reload.locked }.from('artifacts_locked').to('unlocked')
+ end
- it 'does not unlock artifacts for other refs' do
- expect { execute }.not_to change { other_ref_pipeline.reload.locked }.from('artifacts_locked')
- end
+ it 'does not unlock artifacts for tag or branch with same name as ref' do
+ expect { execute }.not_to change { older_ambiguous_pipeline.reload.locked }.from('artifacts_locked')
+ end
- it 'does not unlock artifacts for child pipeline' do
- expect { execute }.not_to change { child_pipeline.reload.locked }.from('artifacts_locked')
- end
+ it 'does not lock artifacts from old unlocked pipelines' do
+ expect { execute }.not_to change { old_unlocked_pipeline.reload.locked }.from('unlocked')
end
- context 'when running on just the ref' do
- let(:before_pipeline) { nil }
+ it 'does not unlock artifacts for other refs' do
+ expect { execute }.not_to change { other_ref_pipeline.reload.locked }.from('artifacts_locked')
+ end
- it 'unlocks artifacts from older pipelines' do
- expect { execute }.to change { older_pipeline.reload.locked }.from('artifacts_locked').to('unlocked')
- end
+ it 'unlocks job artifact records' do
+ pending unless ci_update_unlocked_job_artifacts
- it 'unlocks artifacts from newer pipelines' do
- expect { execute }.to change { newer_pipeline.reload.locked }.from('artifacts_locked').to('unlocked')
- end
+ expect { execute }.to change { ::Ci::JobArtifact.artifact_unlocked.count }.from(0).to(8)
+ end
+ end
+ end
- it 'unlocks artifacts from the same pipeline' do
- expect { execute }.to change { pipeline.reload.locked }.from('artifacts_locked').to('unlocked')
- end
+ describe '#unlock_pipelines_query' do
+ subject { described_class.new(pipeline.project, pipeline.user).unlock_pipelines_query(ci_ref, before_pipeline) }
+
+ context 'when running on a ref before a pipeline' do
+ let(:before_pipeline) { pipeline }
+
+ it 'produces the expected SQL string' do
+ expect(subject.squish).to eq <<~SQL.squish
+ UPDATE
+ "ci_pipelines"
+ SET
+ "locked" = 0
+ WHERE
+ "ci_pipelines"."id" IN
+ (SELECT
+ "ci_pipelines"."id"
+ FROM
+ "ci_pipelines"
+ WHERE
+ "ci_pipelines"."ci_ref_id" = #{ci_ref.id}
+ AND "ci_pipelines"."locked" = 1
+ AND (ci_pipelines.id < #{before_pipeline.id})
+ AND "ci_pipelines"."id" NOT IN
+ (WITH RECURSIVE
+ "base_and_descendants"
+ AS
+ ((SELECT
+ "ci_pipelines".*
+ FROM
+ "ci_pipelines"
+ WHERE
+ "ci_pipelines"."id" = #{before_pipeline.id})
+ UNION
+ (SELECT
+ "ci_pipelines".*
+ FROM
+ "ci_pipelines",
+ "base_and_descendants",
+ "ci_sources_pipelines"
+ WHERE
+ "ci_sources_pipelines"."pipeline_id" = "ci_pipelines"."id"
+ AND "ci_sources_pipelines"."source_pipeline_id" = "base_and_descendants"."id"
+ AND "ci_sources_pipelines"."source_project_id" = "ci_sources_pipelines"."project_id"))
+ SELECT
+ "id"
+ FROM
+ "base_and_descendants"
+ AS
+ "ci_pipelines")
+ LIMIT 1
+ FOR UPDATE
+ SKIP LOCKED)
+ RETURNING ("ci_pipelines"."id")
+ SQL
+ end
+ end
- it 'does not unlock artifacts for tag or branch with same name as ref' do
- expect { execute }.not_to change { older_ambiguous_pipeline.reload.locked }.from('artifacts_locked')
- end
+ context 'when running on just the ref' do
+ let(:before_pipeline) { nil }
+
+ it 'produces the expected SQL string' do
+ expect(subject.squish).to eq <<~SQL.squish
+ UPDATE
+ "ci_pipelines"
+ SET
+ "locked" = 0
+ WHERE
+ "ci_pipelines"."id" IN
+ (SELECT
+ "ci_pipelines"."id"
+ FROM
+ "ci_pipelines"
+ WHERE
+ "ci_pipelines"."ci_ref_id" = #{ci_ref.id}
+ AND "ci_pipelines"."locked" = 1
+ LIMIT 1
+ FOR UPDATE
+ SKIP LOCKED)
+ RETURNING
+ ("ci_pipelines"."id")
+ SQL
+ end
+ end
+ end
- it 'does not lock artifacts from old unlocked pipelines' do
- expect { execute }.not_to change { old_unlocked_pipeline.reload.locked }.from('unlocked')
- end
+ describe '#unlock_job_artifacts_query' do
+ subject { described_class.new(pipeline.project, pipeline.user).unlock_job_artifacts_query(pipeline_ids) }
+
+ context 'when running on a ref before a pipeline' do
+ let(:before_pipeline) { pipeline }
+ let(:pipeline_ids) { [older_pipeline.id] }
+
+ it 'produces the expected SQL string' do
+ expect(subject.squish).to eq <<~SQL.squish
+ UPDATE
+ "ci_job_artifacts"
+ SET
+ "locked" = 0
+ WHERE
+ "ci_job_artifacts"."job_id" IN
+ (SELECT
+ "ci_builds"."id"
+ FROM
+ "ci_builds"
+ WHERE
+ "ci_builds"."type" = 'Ci::Build'
+ AND "ci_builds"."commit_id" = #{older_pipeline.id})
+ RETURNING
+ ("ci_job_artifacts"."id")
+ SQL
+ end
+ end
- it 'does not unlock artifacts for other refs' do
- expect { execute }.not_to change { other_ref_pipeline.reload.locked }.from('artifacts_locked')
- end
+ context 'when running on just the ref' do
+ let(:before_pipeline) { nil }
+ let(:pipeline_ids) { [older_pipeline.id, newer_pipeline.id, pipeline.id] }
+
+ it 'produces the expected SQL string' do
+ expect(subject.squish).to eq <<~SQL.squish
+ UPDATE
+ "ci_job_artifacts"
+ SET
+ "locked" = 0
+ WHERE
+ "ci_job_artifacts"."job_id" IN
+ (SELECT
+ "ci_builds"."id"
+ FROM
+ "ci_builds"
+ WHERE
+ "ci_builds"."type" = 'Ci::Build'
+ AND "ci_builds"."commit_id" IN (#{pipeline_ids.join(', ')}))
+ RETURNING
+ ("ci_job_artifacts"."id")
+ SQL
end
end
end
diff --git a/spec/services/ci/update_build_state_service_spec.rb b/spec/services/ci/update_build_state_service_spec.rb
index e4dd3d0500f..937b19beff5 100644
--- a/spec/services/ci/update_build_state_service_spec.rb
+++ b/spec/services/ci/update_build_state_service_spec.rb
@@ -118,7 +118,7 @@ RSpec.describe Ci::UpdateBuildStateService do
expect(metrics)
.not_to have_received(:increment_error_counter)
- .with(type: :chunks_invalid_checksum)
+ .with(error_reason: :chunks_invalid_checksum)
end
end
@@ -188,7 +188,7 @@ RSpec.describe Ci::UpdateBuildStateService do
expect(metrics)
.to have_received(:increment_error_counter)
- .with(type: :chunks_invalid_checksum)
+ .with(error_reason: :chunks_invalid_checksum)
end
end
@@ -210,11 +210,11 @@ RSpec.describe Ci::UpdateBuildStateService do
expect(metrics)
.not_to have_received(:increment_error_counter)
- .with(type: :chunks_invalid_checksum)
+ .with(error_reason: :chunks_invalid_checksum)
expect(metrics)
.not_to have_received(:increment_error_counter)
- .with(type: :chunks_invalid_size)
+ .with(error_reason: :chunks_invalid_size)
end
context 'when using deprecated parameters' do
@@ -235,11 +235,11 @@ RSpec.describe Ci::UpdateBuildStateService do
expect(metrics)
.not_to have_received(:increment_error_counter)
- .with(type: :chunks_invalid_checksum)
+ .with(error_reason: :chunks_invalid_checksum)
expect(metrics)
.not_to have_received(:increment_error_counter)
- .with(type: :chunks_invalid_size)
+ .with(error_reason: :chunks_invalid_size)
end
end
end
@@ -262,11 +262,11 @@ RSpec.describe Ci::UpdateBuildStateService do
expect(metrics)
.to have_received(:increment_error_counter)
- .with(type: :chunks_invalid_checksum)
+ .with(error_reason: :chunks_invalid_checksum)
expect(metrics)
.to have_received(:increment_error_counter)
- .with(type: :chunks_invalid_size)
+ .with(error_reason: :chunks_invalid_size)
end
end
@@ -284,7 +284,7 @@ RSpec.describe Ci::UpdateBuildStateService do
expect(metrics)
.to have_received(:increment_error_counter)
- .with(type: :chunks_invalid_checksum)
+ .with(error_reason: :chunks_invalid_checksum)
expect(metrics)
.not_to have_received(:increment_trace_operation)
@@ -292,7 +292,7 @@ RSpec.describe Ci::UpdateBuildStateService do
expect(metrics)
.not_to have_received(:increment_error_counter)
- .with(type: :chunks_invalid_size)
+ .with(error_reason: :chunks_invalid_size)
end
end
@@ -376,7 +376,7 @@ RSpec.describe Ci::UpdateBuildStateService do
expect(metrics)
.not_to have_received(:increment_error_counter)
- .with(type: :chunks_invalid_checksum)
+ .with(error_reason: :chunks_invalid_checksum)
end
context 'when build pending state is outdated' do
diff --git a/spec/services/clusters/agents/refresh_authorization_service_spec.rb b/spec/services/clusters/agents/refresh_authorization_service_spec.rb
index 77ba81ea9c0..09bec7ae0e8 100644
--- a/spec/services/clusters/agents/refresh_authorization_service_spec.rb
+++ b/spec/services/clusters/agents/refresh_authorization_service_spec.rb
@@ -113,6 +113,16 @@ RSpec.describe Clusters::Agents::RefreshAuthorizationService do
expect(modified_authorization.config).to eq({ 'default_namespace' => 'new-namespace' })
end
+ context 'project does not belong to a group, and is authorizing itself' do
+ let(:root_ancestor) { create(:namespace) }
+ let(:added_project) { project }
+
+ it 'creates an authorization record for the project' do
+ expect(subject).to be_truthy
+ expect(agent.authorized_projects).to contain_exactly(added_project)
+ end
+ end
+
context 'config contains too many projects' do
before do
stub_const("#{described_class}::AUTHORIZED_ENTITY_LIMIT", 1)
diff --git a/spec/services/clusters/applications/prometheus_health_check_service_spec.rb b/spec/services/clusters/applications/prometheus_health_check_service_spec.rb
deleted file mode 100644
index e6c7b147ab7..00000000000
--- a/spec/services/clusters/applications/prometheus_health_check_service_spec.rb
+++ /dev/null
@@ -1,114 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Clusters::Applications::PrometheusHealthCheckService, '#execute' do
- let(:service) { described_class.new(cluster) }
-
- subject { service.execute }
-
- RSpec.shared_examples 'no alert' do
- it 'does not send alert' do
- expect(Projects::Alerting::NotifyService).not_to receive(:new)
-
- subject
- end
- end
-
- RSpec.shared_examples 'sends alert' do
- it 'sends an alert' do
- expect_next_instance_of(Projects::Alerting::NotifyService) do |notify_service|
- expect(notify_service).to receive(:execute).with(integration.token, integration)
- end
-
- subject
- end
- end
-
- RSpec.shared_examples 'correct health stored' do
- it 'stores the correct health of prometheus app' do
- subject
-
- expect(prometheus.healthy).to eq(client_healthy)
- end
- end
-
- context 'when cluster is not project_type' do
- let(:cluster) { create(:cluster, :instance) }
-
- it { expect { subject }.to raise_error(RuntimeError, 'Invalid cluster type. Only project types are allowed.') }
- end
-
- context 'when cluster is project_type' do
- let_it_be(:project) { create(:project) }
- let_it_be(:integration) { create(:alert_management_http_integration, project: project) }
-
- let(:applications_prometheus_healthy) { true }
- let(:prometheus) { create(:clusters_applications_prometheus, status: prometheus_status_value, healthy: applications_prometheus_healthy) }
- let(:cluster) { create(:cluster, :project, application_prometheus: prometheus, projects: [project]) }
-
- context 'when prometheus not installed' do
- let(:prometheus_status_value) { Clusters::Applications::Prometheus.state_machine.states[:installing].value }
-
- it { expect(subject).to eq(nil) }
- include_examples 'no alert'
- end
-
- context 'when prometheus installed' do
- let(:prometheus_status_value) { Clusters::Applications::Prometheus.state_machine.states[:installed].value }
-
- before do
- client = instance_double('PrometheusClient', healthy?: client_healthy)
- expect(prometheus).to receive(:prometheus_client).and_return(client)
- end
-
- context 'when newly unhealthy' do
- let(:applications_prometheus_healthy) { true }
- let(:client_healthy) { false }
-
- include_examples 'sends alert'
- include_examples 'correct health stored'
- end
-
- context 'when newly healthy' do
- let(:applications_prometheus_healthy) { false }
- let(:client_healthy) { true }
-
- include_examples 'no alert'
- include_examples 'correct health stored'
- end
-
- context 'when continuously unhealthy' do
- let(:applications_prometheus_healthy) { false }
- let(:client_healthy) { false }
-
- include_examples 'no alert'
- include_examples 'correct health stored'
- end
-
- context 'when continuously healthy' do
- let(:applications_prometheus_healthy) { true }
- let(:client_healthy) { true }
-
- include_examples 'no alert'
- include_examples 'correct health stored'
- end
-
- context 'when first health check and healthy' do
- let(:applications_prometheus_healthy) { nil }
- let(:client_healthy) { true }
-
- include_examples 'no alert'
- include_examples 'correct health stored'
- end
-
- context 'when first health check and not healthy' do
- let(:applications_prometheus_healthy) { nil }
- let(:client_healthy) { false }
-
- include_examples 'sends alert'
- include_examples 'correct health stored'
- end
- end
- end
-end
diff --git a/spec/services/clusters/cleanup/project_namespace_service_spec.rb b/spec/services/clusters/cleanup/project_namespace_service_spec.rb
index 605aaea17e4..ec510b2e3c5 100644
--- a/spec/services/clusters/cleanup/project_namespace_service_spec.rb
+++ b/spec/services/clusters/cleanup/project_namespace_service_spec.rb
@@ -58,6 +58,19 @@ RSpec.describe Clusters::Cleanup::ProjectNamespaceService do
subject
end
+
+ context 'when cluster.kubeclient is nil' do
+ let(:kubeclient_instance_double) { nil }
+
+ it 'schedules ::ServiceAccountWorker' do
+ expect(Clusters::Cleanup::ServiceAccountWorker).to receive(:perform_async).with(cluster.id)
+ subject
+ end
+
+ it 'deletes namespaces from database' do
+ expect { subject }.to change { cluster.kubernetes_namespaces.exists? }.from(true).to(false)
+ end
+ end
end
context 'when cluster has no namespaces' do
diff --git a/spec/services/clusters/cleanup/service_account_service_spec.rb b/spec/services/clusters/cleanup/service_account_service_spec.rb
index f256df1b2fc..adcdbd84da0 100644
--- a/spec/services/clusters/cleanup/service_account_service_spec.rb
+++ b/spec/services/clusters/cleanup/service_account_service_spec.rb
@@ -44,5 +44,13 @@ RSpec.describe Clusters::Cleanup::ServiceAccountService do
it 'deletes cluster' do
expect { subject }.to change { Clusters::Cluster.where(id: cluster.id).exists? }.from(true).to(false)
end
+
+ context 'when cluster.kubeclient is nil' do
+ let(:kubeclient_instance_double) { nil }
+
+ it 'deletes cluster' do
+ expect { subject }.to change { Clusters::Cluster.where(id: cluster.id).exists? }.from(true).to(false)
+ end
+ end
end
end
diff --git a/spec/services/clusters/integrations/prometheus_health_check_service_spec.rb b/spec/services/clusters/integrations/prometheus_health_check_service_spec.rb
new file mode 100644
index 00000000000..9db3b9d2417
--- /dev/null
+++ b/spec/services/clusters/integrations/prometheus_health_check_service_spec.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Clusters::Integrations::PrometheusHealthCheckService, '#execute' do
+ let(:service) { described_class.new(cluster) }
+
+ subject { service.execute }
+
+ RSpec.shared_examples 'no alert' do
+ it 'does not send alert' do
+ expect(Projects::Alerting::NotifyService).not_to receive(:new)
+
+ subject
+ end
+ end
+
+ RSpec.shared_examples 'sends alert' do
+ it 'sends an alert' do
+ expect_next_instance_of(Projects::Alerting::NotifyService) do |notify_service|
+ expect(notify_service).to receive(:execute).with(integration.token, integration)
+ end
+
+ subject
+ end
+ end
+
+ RSpec.shared_examples 'correct health stored' do
+ it 'stores the correct health of prometheus' do
+ subject
+
+ expect(prometheus.healthy?).to eq(client_healthy)
+ end
+ end
+
+ context 'when cluster is not project_type' do
+ let(:cluster) { create(:cluster, :instance) }
+
+ it { expect { subject }.to raise_error(RuntimeError, 'Invalid cluster type. Only project types are allowed.') }
+ end
+
+ context 'when cluster is project_type' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:alert_management_http_integration, project: project) }
+
+ let(:previous_health_status) { :healthy }
+ let(:prometheus) { create(:clusters_integrations_prometheus, enabled: prometheus_enabled, health_status: previous_health_status) }
+ let(:cluster) { create(:cluster, :project, integration_prometheus: prometheus, projects: [project]) }
+
+ context 'when prometheus not enabled' do
+ let(:prometheus_enabled) { false }
+
+ it { expect(subject).to eq(nil) }
+ include_examples 'no alert'
+ end
+
+ context 'when prometheus enabled' do
+ let(:prometheus_enabled) { true }
+
+ before do
+ client = instance_double('PrometheusClient', healthy?: client_healthy)
+ expect(prometheus).to receive(:prometheus_client).and_return(client)
+ end
+
+ context 'when newly unhealthy' do
+ let(:previous_health_status) { :healthy }
+ let(:client_healthy) { false }
+
+ include_examples 'sends alert'
+ include_examples 'correct health stored'
+ end
+
+ context 'when newly healthy' do
+ let(:previous_health_status) { :unhealthy }
+ let(:client_healthy) { true }
+
+ include_examples 'no alert'
+ include_examples 'correct health stored'
+ end
+
+ context 'when continuously unhealthy' do
+ let(:previous_health_status) { :unhealthy }
+ let(:client_healthy) { false }
+
+ include_examples 'no alert'
+ include_examples 'correct health stored'
+ end
+
+ context 'when continuously healthy' do
+ let(:previous_health_status) { :healthy }
+ let(:client_healthy) { true }
+
+ include_examples 'no alert'
+ include_examples 'correct health stored'
+ end
+
+ context 'when first health check and healthy' do
+ let(:previous_health_status) { :unknown }
+ let(:client_healthy) { true }
+
+ include_examples 'no alert'
+ include_examples 'correct health stored'
+ end
+
+ context 'when first health check and not healthy' do
+ let(:previous_health_status) { :unknown }
+ let(:client_healthy) { false }
+
+ include_examples 'sends alert'
+ include_examples 'correct health stored'
+ end
+ end
+ end
+end
diff --git a/spec/services/dependency_proxy/find_or_create_blob_service_spec.rb b/spec/services/dependency_proxy/find_or_create_blob_service_spec.rb
index 20b0546effa..5f7afdf699a 100644
--- a/spec/services/dependency_proxy/find_or_create_blob_service_spec.rb
+++ b/spec/services/dependency_proxy/find_or_create_blob_service_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe DependencyProxy::FindOrCreateBlobService do
let(:blob_sha) { blob.file_name.sub('.gz', '') }
it 'uses cached blob instead of downloading one' do
- expect { subject }.to change { blob.reload.updated_at }
+ expect { subject }.to change { blob.reload.read_at }
expect(subject[:status]).to eq(:success)
expect(subject[:blob]).to be_a(DependencyProxy::Blob)
diff --git a/spec/services/dependency_proxy/find_or_create_manifest_service_spec.rb b/spec/services/dependency_proxy/find_or_create_manifest_service_spec.rb
index b3f88f91289..ef608c9b113 100644
--- a/spec/services/dependency_proxy/find_or_create_manifest_service_spec.rb
+++ b/spec/services/dependency_proxy/find_or_create_manifest_service_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe DependencyProxy::FindOrCreateManifestService do
let(:token) { Digest::SHA256.hexdigest('123') }
let(:headers) do
{
- 'docker-content-digest' => dependency_proxy_manifest.digest,
+ DependencyProxy::Manifest::DIGEST_HEADER => dependency_proxy_manifest.digest,
'content-type' => dependency_proxy_manifest.content_type
}
end
@@ -31,6 +31,14 @@ RSpec.describe DependencyProxy::FindOrCreateManifestService do
end
end
+ shared_examples 'returning no manifest' do
+ it 'returns a nil manifest' do
+ expect(subject[:status]).to eq(:success)
+ expect(subject[:from_cache]).to eq false
+ expect(subject[:manifest]).to be_nil
+ end
+ end
+
context 'when no manifest exists' do
let_it_be(:image) { 'new-image' }
@@ -40,7 +48,15 @@ RSpec.describe DependencyProxy::FindOrCreateManifestService do
stub_manifest_download(image, tag, headers: headers)
end
- it_behaves_like 'downloading the manifest'
+ it_behaves_like 'returning no manifest'
+
+ context 'with dependency_proxy_manifest_workhorse feature disabled' do
+ before do
+ stub_feature_flags(dependency_proxy_manifest_workhorse: false)
+ end
+
+ it_behaves_like 'downloading the manifest'
+ end
end
context 'failed head request' do
@@ -49,7 +65,15 @@ RSpec.describe DependencyProxy::FindOrCreateManifestService do
stub_manifest_download(image, tag, headers: headers)
end
- it_behaves_like 'downloading the manifest'
+ it_behaves_like 'returning no manifest'
+
+ context 'with dependency_proxy_manifest_workhorse feature disabled' do
+ before do
+ stub_feature_flags(dependency_proxy_manifest_workhorse: false)
+ end
+
+ it_behaves_like 'downloading the manifest'
+ end
end
end
@@ -60,7 +84,7 @@ RSpec.describe DependencyProxy::FindOrCreateManifestService do
shared_examples 'using the cached manifest' do
it 'uses cached manifest instead of downloading one', :aggregate_failures do
- expect { subject }.to change { dependency_proxy_manifest.reload.updated_at }
+ expect { subject }.to change { dependency_proxy_manifest.reload.read_at }
expect(subject[:status]).to eq(:success)
expect(subject[:manifest]).to be_a(DependencyProxy::Manifest)
@@ -76,16 +100,24 @@ RSpec.describe DependencyProxy::FindOrCreateManifestService do
let(:content_type) { 'new-content-type' }
before do
- stub_manifest_head(image, tag, headers: { 'docker-content-digest' => digest, 'content-type' => content_type })
- stub_manifest_download(image, tag, headers: { 'docker-content-digest' => digest, 'content-type' => content_type })
+ stub_manifest_head(image, tag, headers: { DependencyProxy::Manifest::DIGEST_HEADER => digest, 'content-type' => content_type })
+ stub_manifest_download(image, tag, headers: { DependencyProxy::Manifest::DIGEST_HEADER => digest, 'content-type' => content_type })
end
- it 'downloads the new manifest and updates the existing record', :aggregate_failures do
- expect(subject[:status]).to eq(:success)
- expect(subject[:manifest]).to eq(dependency_proxy_manifest)
- expect(subject[:manifest].content_type).to eq(content_type)
- expect(subject[:manifest].digest).to eq(digest)
- expect(subject[:from_cache]).to eq false
+ it_behaves_like 'returning no manifest'
+
+ context 'with dependency_proxy_manifest_workhorse feature disabled' do
+ before do
+ stub_feature_flags(dependency_proxy_manifest_workhorse: false)
+ end
+
+ it 'downloads the new manifest and updates the existing record', :aggregate_failures do
+ expect(subject[:status]).to eq(:success)
+ expect(subject[:manifest]).to eq(dependency_proxy_manifest)
+ expect(subject[:manifest].content_type).to eq(content_type)
+ expect(subject[:manifest].digest).to eq(digest)
+ expect(subject[:from_cache]).to eq false
+ end
end
end
@@ -96,7 +128,15 @@ RSpec.describe DependencyProxy::FindOrCreateManifestService do
stub_manifest_download(image, tag, headers: headers)
end
- it_behaves_like 'downloading the manifest'
+ it_behaves_like 'returning no manifest'
+
+ context 'with dependency_proxy_manifest_workhorse feature disabled' do
+ before do
+ stub_feature_flags(dependency_proxy_manifest_workhorse: false)
+ end
+
+ it_behaves_like 'downloading the manifest'
+ end
end
context 'failed connection' do
diff --git a/spec/services/dependency_proxy/head_manifest_service_spec.rb b/spec/services/dependency_proxy/head_manifest_service_spec.rb
index 9c1e4d650f8..949a8eb3bee 100644
--- a/spec/services/dependency_proxy/head_manifest_service_spec.rb
+++ b/spec/services/dependency_proxy/head_manifest_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe DependencyProxy::HeadManifestService do
let(:content_type) { 'foo' }
let(:headers) do
{
- 'docker-content-digest' => digest,
+ DependencyProxy::Manifest::DIGEST_HEADER => digest,
'content-type' => content_type
}
end
diff --git a/spec/services/dependency_proxy/pull_manifest_service_spec.rb b/spec/services/dependency_proxy/pull_manifest_service_spec.rb
index b3053174cc0..6018a3229fb 100644
--- a/spec/services/dependency_proxy/pull_manifest_service_spec.rb
+++ b/spec/services/dependency_proxy/pull_manifest_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe DependencyProxy::PullManifestService do
let(:digest) { '12345' }
let(:content_type) { 'foo' }
let(:headers) do
- { 'docker-content-digest' => digest, 'content-type' => content_type }
+ { DependencyProxy::Manifest::DIGEST_HEADER => digest, 'content-type' => content_type }
end
subject { described_class.new(image, tag, token).execute_with_manifest(&method(:check_response)) }
diff --git a/spec/services/deployments/archive_in_project_service_spec.rb b/spec/services/deployments/archive_in_project_service_spec.rb
new file mode 100644
index 00000000000..d4039ee7b4a
--- /dev/null
+++ b/spec/services/deployments/archive_in_project_service_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Deployments::ArchiveInProjectService do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:service) { described_class.new(project, nil) }
+
+ describe '#execute' do
+ subject { service.execute }
+
+ context 'when there are archivable deployments' do
+ let!(:deployments) { create_list(:deployment, 3, project: project) }
+ let!(:deployment_refs) { deployments.map(&:ref_path) }
+
+ before do
+ deployments.each(&:create_ref)
+ allow(Deployment).to receive(:archivables_in) { deployments }
+ end
+
+ it 'returns result code' do
+ expect(subject[:result]).to eq(:archived)
+ expect(subject[:status]).to eq(:success)
+ expect(subject[:count]).to eq(3)
+ end
+
+ it 'archives the deployment' do
+ expect(deployments.map(&:archived?)).to be_all(false)
+ expect(deployment_refs_exist?).to be_all(true)
+
+ subject
+
+ deployments.each(&:reload)
+ expect(deployments.map(&:archived?)).to be_all(true)
+ expect(deployment_refs_exist?).to be_all(false)
+ end
+
+ context 'when ref does not exist by some reason' do
+ before do
+ project.repository.delete_refs(*deployment_refs)
+ end
+
+ it 'does not raise an error' do
+ expect(deployment_refs_exist?).to be_all(false)
+
+ expect { subject }.not_to raise_error
+
+ expect(deployment_refs_exist?).to be_all(false)
+ end
+ end
+
+ context 'when deployments_archive feature flag is disabled' do
+ before do
+ stub_feature_flags(deployments_archive: false)
+ end
+
+ it 'does not do anything' do
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:message]).to eq('Feature flag is not enabled')
+ end
+ end
+
+ def deployment_refs_exist?
+ deployment_refs.map { |path| project.repository.ref_exists?(path) }
+ end
+ end
+
+ context 'when there are no archivable deployments' do
+ before do
+ allow(Deployment).to receive(:archivables_in) { Deployment.none }
+ end
+
+ it 'returns result code' do
+ expect(subject[:result]).to eq(:empty)
+ expect(subject[:status]).to eq(:success)
+ end
+ end
+ end
+end
diff --git a/spec/services/deployments/link_merge_requests_service_spec.rb b/spec/services/deployments/link_merge_requests_service_spec.rb
index a5a13230d6f..62adc834733 100644
--- a/spec/services/deployments/link_merge_requests_service_spec.rb
+++ b/spec/services/deployments/link_merge_requests_service_spec.rb
@@ -32,6 +32,19 @@ RSpec.describe Deployments::LinkMergeRequestsService do
end
end
+ context 'when the deployment is for one of the production environments' do
+ it 'links merge requests' do
+ environment =
+ create(:environment, environment_type: 'production', name: 'production/gcp')
+
+ deploy = create(:deployment, :success, environment: environment)
+
+ expect(deploy).to receive(:link_merge_requests).once
+
+ described_class.new(deploy).execute
+ end
+ end
+
context 'when the deployment failed' do
it 'does nothing' do
environment = create(:environment, name: 'foo')
diff --git a/spec/services/emails/create_service_spec.rb b/spec/services/emails/create_service_spec.rb
index 1396a1fce30..2fabf4ae66a 100644
--- a/spec/services/emails/create_service_spec.rb
+++ b/spec/services/emails/create_service_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe Emails::CreateService do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
+
let(:opts) { { email: 'new@email.com', user: user } }
subject(:service) { described_class.new(user, opts) }
@@ -22,7 +23,7 @@ RSpec.describe Emails::CreateService do
it 'has the right user association' do
service.execute
- expect(user.emails).to eq(Email.where(opts))
+ expect(user.emails).to include(Email.find_by(opts))
end
end
end
diff --git a/spec/services/emails/destroy_service_spec.rb b/spec/services/emails/destroy_service_spec.rb
index f8407be41e7..7dcf367016e 100644
--- a/spec/services/emails/destroy_service_spec.rb
+++ b/spec/services/emails/destroy_service_spec.rb
@@ -15,5 +15,15 @@ RSpec.describe Emails::DestroyService do
expect(user.emails).not_to include(email)
expect(response).to be true
end
+
+ context 'when it corresponds to the user primary email' do
+ let(:email) { user.emails.find_by!(email: user.email) }
+
+ it 'does not remove the email and raises an exception' do
+ expect { service.execute(email) }.to raise_error(StandardError, 'Cannot delete primary email')
+
+ expect(user.emails).to include(email)
+ end
+ end
end
end
diff --git a/spec/services/error_tracking/collect_error_service_spec.rb b/spec/services/error_tracking/collect_error_service_spec.rb
index ee9d0813e64..52d095148c8 100644
--- a/spec/services/error_tracking/collect_error_service_spec.rb
+++ b/spec/services/error_tracking/collect_error_service_spec.rb
@@ -4,7 +4,8 @@ require 'spec_helper'
RSpec.describe ErrorTracking::CollectErrorService do
let_it_be(:project) { create(:project) }
- let_it_be(:parsed_event) { Gitlab::Json.parse(fixture_file('error_tracking/parsed_event.json')) }
+ let_it_be(:parsed_event_file) { 'error_tracking/parsed_event.json' }
+ let_it_be(:parsed_event) { Gitlab::Json.parse(fixture_file(parsed_event_file)) }
subject { described_class.new(project, nil, event: parsed_event) }
@@ -41,6 +42,14 @@ RSpec.describe ErrorTracking::CollectErrorService do
expect(event.payload).to eq parsed_event
end
+ context 'python sdk event' do
+ let(:parsed_event) { Gitlab::Json.parse(fixture_file('error_tracking/python_event.json')) }
+
+ it 'creates a valid event' do
+ expect { subject.execute }.to change { ErrorTracking::ErrorEvent.count }.by(1)
+ end
+ end
+
context 'unusual payload' do
let(:modified_event) { parsed_event }
@@ -64,5 +73,25 @@ RSpec.describe ErrorTracking::CollectErrorService do
end
end
end
+
+ context 'go payload' do
+ let(:parsed_event) { Gitlab::Json.parse(fixture_file('error_tracking/go_parsed_event.json')) }
+
+ it 'has correct values set' do
+ subject.execute
+
+ event = ErrorTracking::ErrorEvent.last
+ error = event.error
+
+ expect(error.name).to eq '*errors.errorString'
+ expect(error.description).to start_with 'Hello world'
+ expect(error.platform).to eq 'go'
+
+ expect(event.description).to start_with 'Hello world'
+ expect(event.level).to eq 'error'
+ expect(event.environment).to eq 'Accumulate'
+ expect(event.payload).to eq parsed_event
+ end
+ end
end
end
diff --git a/spec/services/google_cloud/service_accounts_service_spec.rb b/spec/services/google_cloud/service_accounts_service_spec.rb
new file mode 100644
index 00000000000..a0d09affa72
--- /dev/null
+++ b/spec/services/google_cloud/service_accounts_service_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GoogleCloud::ServiceAccountsService do
+ let_it_be(:project) { create(:project) }
+
+ let(:service) { described_class.new(project) }
+
+ describe 'find_for_project' do
+ context 'when a project does not have GCP service account vars' do
+ before do
+ project.variables.build(key: 'blah', value: 'foo', environment_scope: 'world')
+ project.save!
+ end
+
+ it 'returns an empty list' do
+ expect(service.find_for_project.length).to eq(0)
+ end
+ end
+
+ context 'when a project has GCP service account ci vars' do
+ before do
+ project.variables.build(environment_scope: '*', key: 'GCP_PROJECT_ID', value: 'prj1')
+ project.variables.build(environment_scope: '*', key: 'GCP_SERVICE_ACCOUNT_KEY', value: 'mock')
+ project.variables.build(environment_scope: 'staging', key: 'GCP_PROJECT_ID', value: 'prj2')
+ project.variables.build(environment_scope: 'staging', key: 'GCP_SERVICE_ACCOUNT', value: 'mock')
+ project.variables.build(environment_scope: 'production', key: 'GCP_PROJECT_ID', value: 'prj3')
+ project.variables.build(environment_scope: 'production', key: 'GCP_SERVICE_ACCOUNT', value: 'mock')
+ project.variables.build(environment_scope: 'production', key: 'GCP_SERVICE_ACCOUNT_KEY', value: 'mock')
+ project.save!
+ end
+
+ it 'returns a list of service accounts' do
+ list = service.find_for_project
+
+ aggregate_failures 'testing list of service accounts' do
+ expect(list.length).to eq(3)
+
+ expect(list.first[:environment]).to eq('*')
+ expect(list.first[:gcp_project]).to eq('prj1')
+ expect(list.first[:service_account_exists]).to eq(false)
+ expect(list.first[:service_account_key_exists]).to eq(true)
+
+ expect(list.second[:environment]).to eq('staging')
+ expect(list.second[:gcp_project]).to eq('prj2')
+ expect(list.second[:service_account_exists]).to eq(true)
+ expect(list.second[:service_account_key_exists]).to eq(false)
+
+ expect(list.third[:environment]).to eq('production')
+ expect(list.third[:gcp_project]).to eq('prj3')
+ expect(list.third[:service_account_exists]).to eq(true)
+ expect(list.third[:service_account_key_exists]).to eq(true)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
index bcba39b0eb4..7ea08131419 100644
--- a/spec/services/groups/create_service_spec.rb
+++ b/spec/services/groups/create_service_spec.rb
@@ -171,7 +171,7 @@ RSpec.describe Groups::CreateService, '#execute' do
context 'with an active group-level integration' do
let(:service) { described_class.new(user, group_params.merge(parent_id: group.id)) }
- let!(:group_integration) { create(:prometheus_integration, group: group, project: nil, api_url: 'https://prometheus.group.com/') }
+ let!(:group_integration) { create(:prometheus_integration, :group, group: group, api_url: 'https://prometheus.group.com/') }
let(:group) do
create(:group).tap do |group|
group.add_owner(user)
@@ -186,7 +186,7 @@ RSpec.describe Groups::CreateService, '#execute' do
context 'with an active subgroup' do
let(:service) { described_class.new(user, group_params.merge(parent_id: subgroup.id)) }
- let!(:subgroup_integration) { create(:prometheus_integration, group: subgroup, project: nil, api_url: 'https://prometheus.subgroup.com/') }
+ let!(:subgroup_integration) { create(:prometheus_integration, :group, group: subgroup, api_url: 'https://prometheus.subgroup.com/') }
let(:subgroup) do
create(:group, parent: group).tap do |subgroup|
subgroup.add_owner(user)
@@ -242,4 +242,41 @@ RSpec.describe Groups::CreateService, '#execute' do
end
end
end
+
+ describe 'invite team email' do
+ let(:service) { described_class.new(user, group_params) }
+
+ before do
+ allow(Namespaces::InviteTeamEmailWorker).to receive(:perform_in)
+ end
+
+ it 'is sent' do
+ group = service.execute
+ delay = Namespaces::InviteTeamEmailService::DELIVERY_DELAY_IN_MINUTES
+ expect(Namespaces::InviteTeamEmailWorker).to have_received(:perform_in).with(delay, group.id, user.id)
+ end
+
+ context 'when group has not been persisted' do
+ let(:service) { described_class.new(user, group_params.merge(name: '<script>alert("Attack!")</script>')) }
+
+ it 'not sent' do
+ expect(Namespaces::InviteTeamEmailWorker).not_to receive(:perform_in)
+ service.execute
+ end
+ end
+
+ context 'when group is not root' do
+ let(:parent_group) { create :group }
+ let(:service) { described_class.new(user, group_params.merge(parent_id: parent_group.id)) }
+
+ before do
+ parent_group.add_owner(user)
+ end
+
+ it 'not sent' do
+ expect(Namespaces::InviteTeamEmailWorker).not_to receive(:perform_in)
+ service.execute
+ end
+ end
+ end
end
diff --git a/spec/services/groups/import_export/import_service_spec.rb b/spec/services/groups/import_export/import_service_spec.rb
index ad5c4364deb..292f2e2b86b 100644
--- a/spec/services/groups/import_export/import_service_spec.rb
+++ b/spec/services/groups/import_export/import_service_spec.rb
@@ -7,6 +7,10 @@ RSpec.describe Groups::ImportExport::ImportService do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
+ before do
+ allow(GroupImportWorker).to receive(:with_status).and_return(GroupImportWorker)
+ end
+
context 'when the job can be successfully scheduled' do
subject(:import_service) { described_class.new(group: group, user: user) }
@@ -20,6 +24,8 @@ RSpec.describe Groups::ImportExport::ImportService do
end
it 'enqueues an import job' do
+ allow(GroupImportWorker).to receive(:with_status).and_return(GroupImportWorker)
+
expect(GroupImportWorker).to receive(:perform_async).with(user.id, group.id)
import_service.async_execute
diff --git a/spec/services/groups/transfer_service_spec.rb b/spec/services/groups/transfer_service_spec.rb
index 8b506d2bc2c..35d46884f4d 100644
--- a/spec/services/groups/transfer_service_spec.rb
+++ b/spec/services/groups/transfer_service_spec.rb
@@ -153,7 +153,7 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
it 'adds an error on group' do
transfer_service.execute(nil)
- expect(transfer_service.error).to eq('Transfer failed: The parent group already has a subgroup with the same path.')
+ expect(transfer_service.error).to eq('Transfer failed: The parent group already has a subgroup or a project with the same path.')
end
end
@@ -185,9 +185,7 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
context 'when projects have project namespaces' do
let_it_be(:project1) { create(:project, :private, namespace: group) }
- let_it_be(:project_namespace1) { create(:project_namespace, project: project1) }
let_it_be(:project2) { create(:project, :private, namespace: group) }
- let_it_be(:project_namespace2) { create(:project_namespace, project: project2) }
it_behaves_like 'project namespace path is in sync with project path' do
let(:group_full_path) { "#{group.path}" }
@@ -241,7 +239,7 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
it 'adds an error on group' do
transfer_service.execute(new_parent_group)
- expect(transfer_service.error).to eq('Transfer failed: The parent group already has a subgroup with the same path.')
+ expect(transfer_service.error).to eq('Transfer failed: The parent group already has a subgroup or a project with the same path.')
end
end
@@ -250,36 +248,45 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
let_it_be(:membership) { create(:group_member, :owner, group: new_parent_group, user: user) }
let_it_be(:project) { create(:project, path: 'foo', namespace: new_parent_group) }
- before do
- group.update_attribute(:path, 'foo')
- end
-
- it 'returns false' do
- expect(transfer_service.execute(new_parent_group)).to be_falsy
- end
-
it 'adds an error on group' do
- transfer_service.execute(new_parent_group)
- expect(transfer_service.error).to eq('Transfer failed: Validation failed: Group URL has already been taken')
+ expect(transfer_service.execute(new_parent_group)).to be_falsy
+ expect(transfer_service.error).to eq('Transfer failed: The parent group already has a subgroup or a project with the same path.')
end
- context 'when projects have project namespaces' do
- let!(:project_namespace) { create(:project_namespace, project: project) }
-
+ # currently when a project is created it gets a corresponding project namespace
+ # so we test the case where a project without a project namespace is transferred
+ # for backward compatibility
+ context 'without project namespace' do
before do
- transfer_service.execute(new_parent_group)
+ project_namespace = project.project_namespace
+ project.update_column(:project_namespace_id, nil)
+ project_namespace.delete
end
- it_behaves_like 'project namespace path is in sync with project path' do
- let(:group_full_path) { "#{new_parent_group.full_path}" }
- let(:projects_with_project_namespace) { [project] }
+ it 'adds an error on group' do
+ expect(project.reload.project_namespace).to be_nil
+ expect(transfer_service.execute(new_parent_group)).to be_falsy
+ expect(transfer_service.error).to eq('Transfer failed: Validation failed: Group URL has already been taken')
end
end
end
+ context 'when projects have project namespaces' do
+ let_it_be(:project) { create(:project, path: 'foo', namespace: new_parent_group) }
+
+ before do
+ transfer_service.execute(new_parent_group)
+ end
+
+ it_behaves_like 'project namespace path is in sync with project path' do
+ let(:group_full_path) { "#{new_parent_group.full_path}" }
+ let(:projects_with_project_namespace) { [project] }
+ end
+ end
+
context 'when the group is allowed to be transferred' do
let_it_be(:new_parent_group, reload: true) { create(:group, :public) }
- let_it_be(:new_parent_group_integration) { create(:integrations_slack, group: new_parent_group, project: nil, webhook: 'http://new-group.slack.com') }
+ let_it_be(:new_parent_group_integration) { create(:integrations_slack, :group, group: new_parent_group, webhook: 'http://new-group.slack.com') }
before do
allow(PropagateIntegrationWorker).to receive(:perform_async)
@@ -316,7 +323,7 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
context 'with an inherited integration' do
let_it_be(:instance_integration) { create(:integrations_slack, :instance, webhook: 'http://project.slack.com') }
- let_it_be(:group_integration) { create(:integrations_slack, group: group, project: nil, webhook: 'http://group.slack.com', inherit_from_id: instance_integration.id) }
+ let_it_be(:group_integration) { create(:integrations_slack, :group, group: group, webhook: 'http://group.slack.com', inherit_from_id: instance_integration.id) }
it 'replaces inherited integrations', :aggregate_failures do
expect(new_created_integration.webhook).to eq(new_parent_group_integration.webhook)
@@ -326,7 +333,7 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
end
context 'with a custom integration' do
- let_it_be(:group_integration) { create(:integrations_slack, group: group, project: nil, webhook: 'http://group.slack.com') }
+ let_it_be(:group_integration) { create(:integrations_slack, :group, group: group, webhook: 'http://group.slack.com') }
it 'does not updates the integrations', :aggregate_failures do
expect { transfer_service.execute(new_parent_group) }.not_to change { group_integration.webhook }
@@ -445,8 +452,6 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
context 'when transferring a group with project descendants' do
let!(:project1) { create(:project, :repository, :private, namespace: group) }
let!(:project2) { create(:project, :repository, :internal, namespace: group) }
- let!(:project_namespace1) { create(:project_namespace, project: project1) }
- let!(:project_namespace2) { create(:project_namespace, project: project2) }
before do
TestEnv.clean_test_path
@@ -483,8 +488,6 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
let!(:project1) { create(:project, :repository, :public, namespace: group) }
let!(:project2) { create(:project, :repository, :public, namespace: group) }
let!(:new_parent_group) { create(:group, :private) }
- let!(:project_namespace1) { create(:project_namespace, project: project1) }
- let!(:project_namespace2) { create(:project_namespace, project: project2) }
it 'updates projects visibility to match the new parent' do
group.projects.each do |project|
@@ -504,8 +507,6 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
let!(:project2) { create(:project, :repository, :internal, namespace: group) }
let!(:subgroup1) { create(:group, :private, parent: group) }
let!(:subgroup2) { create(:group, :internal, parent: group) }
- let!(:project_namespace1) { create(:project_namespace, project: project1) }
- let!(:project_namespace2) { create(:project_namespace, project: project2) }
before do
TestEnv.clean_test_path
@@ -593,11 +594,16 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
let_it_be_with_reload(:group) { create(:group, :private, parent: old_parent_group) }
let_it_be(:new_group_member) { create(:user) }
let_it_be(:old_group_member) { create(:user) }
+ let_it_be(:unique_subgroup_member) { create(:user) }
+ let_it_be(:direct_project_member) { create(:user) }
before do
new_parent_group.add_maintainer(new_group_member)
old_parent_group.add_maintainer(old_group_member)
+ subgroup1.add_developer(unique_subgroup_member)
+ nested_project.add_developer(direct_project_member)
group.refresh_members_authorized_projects
+ subgroup1.refresh_members_authorized_projects
end
it 'removes old project authorizations' do
@@ -613,7 +619,7 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
end
it 'performs authorizations job immediately' do
- expect(AuthorizedProjectsWorker).to receive(:bulk_perform_inline)
+ expect(AuthorizedProjectUpdate::ProjectRecalculateWorker).to receive(:bulk_perform_inline)
transfer_service.execute(new_parent_group)
end
@@ -630,14 +636,24 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
ProjectAuthorization.where(project_id: nested_project.id, user_id: new_group_member.id).size
}.from(0).to(1)
end
+
+ it 'preserves existing project authorizations for direct project members' do
+ expect { transfer_service.execute(new_parent_group) }.not_to change {
+ ProjectAuthorization.where(project_id: nested_project.id, user_id: direct_project_member.id).count
+ }
+ end
end
- context 'for groups with many members' do
- before do
- 11.times do
- new_parent_group.add_maintainer(create(:user))
- end
+ context 'for nested groups with unique members' do
+ it 'preserves existing project authorizations' do
+ expect { transfer_service.execute(new_parent_group) }.not_to change {
+ ProjectAuthorization.where(project_id: nested_project.id, user_id: unique_subgroup_member.id).count
+ }
end
+ end
+
+ context 'for groups with many projects' do
+ let_it_be(:project_list) { create_list(:project, 11, :repository, :private, namespace: group) }
it 'adds new project authorizations for the user which makes a transfer' do
transfer_service.execute(new_parent_group)
@@ -646,9 +662,21 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
expect(ProjectAuthorization.where(project_id: nested_project.id, user_id: user.id).size).to eq(1)
end
+ it 'adds project authorizations for users in the new hierarchy' do
+ expect { transfer_service.execute(new_parent_group) }.to change {
+ ProjectAuthorization.where(project_id: project_list.map { |project| project.id }, user_id: new_group_member.id).size
+ }.from(0).to(project_list.count)
+ end
+
+ it 'removes project authorizations for users in the old hierarchy' do
+ expect { transfer_service.execute(new_parent_group) }.to change {
+ ProjectAuthorization.where(project_id: project_list.map { |project| project.id }, user_id: old_group_member.id).size
+ }.from(project_list.count).to(0)
+ end
+
it 'schedules authorizations job' do
- expect(AuthorizedProjectsWorker).to receive(:bulk_perform_async)
- .with(array_including(new_parent_group.members_with_parents.pluck(:user_id).map {|id| [id, anything] }))
+ expect(AuthorizedProjectUpdate::ProjectRecalculateWorker).to receive(:bulk_perform_async)
+ .with(array_including(group.all_projects.ids.map { |id| [id, anything] }))
transfer_service.execute(new_parent_group)
end
diff --git a/spec/services/import/github/notes/create_service_spec.rb b/spec/services/import/github/notes/create_service_spec.rb
new file mode 100644
index 00000000000..57699def848
--- /dev/null
+++ b/spec/services/import/github/notes/create_service_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Import::Github::Notes::CreateService do
+ it 'does not support quick actions' do
+ project = create(:project, :repository)
+ user = create(:user)
+ merge_request = create(:merge_request, source_project: project)
+
+ project.add_maintainer(user)
+
+ note = described_class.new(
+ project,
+ user,
+ note: '/close',
+ noteable_type: 'MergeRequest',
+ noteable_id: merge_request.id
+ ).execute
+
+ expect(note.note).to eq('/close')
+ expect(note.noteable.closed?).to be(false)
+ end
+end
diff --git a/spec/services/issues/build_service_spec.rb b/spec/services/issues/build_service_spec.rb
index b96dd981e0f..cf75efb5c57 100644
--- a/spec/services/issues/build_service_spec.rb
+++ b/spec/services/issues/build_service_spec.rb
@@ -7,12 +7,14 @@ RSpec.describe Issues::BuildService do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:developer) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
let_it_be(:guest) { create(:user) }
let(:user) { developer }
before_all do
project.add_developer(developer)
+ project.add_reporter(reporter)
project.add_guest(guest)
end
@@ -140,76 +142,64 @@ RSpec.describe Issues::BuildService do
end
describe '#execute' do
- context 'as developer' do
- it 'builds a new issues with given params' do
- milestone = create(:milestone, project: project)
- issue = build_issue(milestone_id: milestone.id)
-
- expect(issue.milestone).to eq(milestone)
- expect(issue.issue_type).to eq('issue')
- expect(issue.work_item_type.base_type).to eq('issue')
- end
+ describe 'setting milestone' do
+ context 'when developer' do
+ it 'builds a new issues with given params' do
+ milestone = create(:milestone, project: project)
+ issue = build_issue(milestone_id: milestone.id)
+
+ expect(issue.milestone).to eq(milestone)
+ end
- it 'sets milestone to nil if it is not available for the project' do
- milestone = create(:milestone, project: create(:project))
- issue = build_issue(milestone_id: milestone.id)
+ it 'sets milestone to nil if it is not available for the project' do
+ milestone = create(:milestone, project: create(:project))
+ issue = build_issue(milestone_id: milestone.id)
- expect(issue.milestone).to be_nil
+ expect(issue.milestone).to be_nil
+ end
end
- context 'when issue_type is incident' do
- it 'sets the correct issue type' do
- issue = build_issue(issue_type: 'incident')
+ context 'when guest' do
+ let(:user) { guest }
- expect(issue.issue_type).to eq('incident')
- expect(issue.work_item_type.base_type).to eq('incident')
+ it 'cannot set milestone' do
+ milestone = create(:milestone, project: project)
+ issue = build_issue(milestone_id: milestone.id)
+
+ expect(issue.milestone).to be_nil
end
end
end
- context 'as guest' do
- let(:user) { guest }
-
- it 'cannot set milestone' do
- milestone = create(:milestone, project: project)
- issue = build_issue(milestone_id: milestone.id)
+ describe 'setting issue type' do
+ context 'with a corresponding WorkItem::Type' do
+ let_it_be(:type_issue_id) { WorkItem::Type.default_issue_type.id }
+ let_it_be(:type_incident_id) { WorkItem::Type.default_by_type(:incident).id }
+
+ where(:issue_type, :current_user, :work_item_type_id, :resulting_issue_type) do
+ nil | ref(:guest) | ref(:type_issue_id) | 'issue'
+ 'issue' | ref(:guest) | ref(:type_issue_id) | 'issue'
+ 'incident' | ref(:guest) | ref(:type_issue_id) | 'issue'
+ 'incident' | ref(:reporter) | ref(:type_incident_id) | 'incident'
+ # update once support for test_case is enabled
+ 'test_case' | ref(:guest) | ref(:type_issue_id) | 'issue'
+ # update once support for requirement is enabled
+ 'requirement' | ref(:guest) | ref(:type_issue_id) | 'issue'
+ 'invalid' | ref(:guest) | ref(:type_issue_id) | 'issue'
+ # ensure that we don't set a value which has a permission check but is an invalid issue type
+ 'project' | ref(:guest) | ref(:type_issue_id) | 'issue'
+ end
- expect(issue.milestone).to be_nil
- end
+ with_them do
+ let(:user) { current_user }
- context 'setting issue type' do
- shared_examples 'builds an issue' do
- specify do
+ it 'builds an issue' do
issue = build_issue(issue_type: issue_type)
expect(issue.issue_type).to eq(resulting_issue_type)
expect(issue.work_item_type_id).to eq(work_item_type_id)
end
end
-
- it 'cannot set invalid issue type' do
- issue = build_issue(issue_type: 'project')
-
- expect(issue).to be_issue
- end
-
- context 'with a corresponding WorkItem::Type' do
- let_it_be(:type_issue_id) { WorkItem::Type.default_issue_type.id }
- let_it_be(:type_incident_id) { WorkItem::Type.default_by_type(:incident).id }
-
- where(:issue_type, :work_item_type_id, :resulting_issue_type) do
- nil | ref(:type_issue_id) | 'issue'
- 'issue' | ref(:type_issue_id) | 'issue'
- 'incident' | ref(:type_incident_id) | 'incident'
- 'test_case' | ref(:type_issue_id) | 'issue' # update once support for test_case is enabled
- 'requirement' | ref(:type_issue_id) | 'issue' # update once support for requirement is enabled
- 'invalid' | ref(:type_issue_id) | 'issue'
- end
-
- with_them do
- it_behaves_like 'builds an issue'
- end
- end
end
end
end
diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb
index 93ef046a632..158f9dec83e 100644
--- a/spec/services/issues/close_service_spec.rb
+++ b/spec/services/issues/close_service_spec.rb
@@ -83,6 +83,14 @@ RSpec.describe Issues::CloseService do
service.execute(issue)
end
+ it 'does not change escalation status' do
+ resolved = IncidentManagement::Escalatable::STATUSES[:resolved]
+
+ expect { service.execute(issue) }
+ .to not_change { IncidentManagement::IssuableEscalationStatus.where(issue: issue).count }
+ .and not_change { IncidentManagement::IssuableEscalationStatus.where(status: resolved).count }
+ end
+
context 'issue is incident type' do
let(:issue) { create(:incident, project: project) }
let(:current_user) { user }
@@ -90,6 +98,40 @@ RSpec.describe Issues::CloseService do
subject { service.execute(issue) }
it_behaves_like 'an incident management tracked event', :incident_management_incident_closed
+
+ it 'creates a new escalation resolved escalation status', :aggregate_failures do
+ expect { service.execute(issue) }.to change { IncidentManagement::IssuableEscalationStatus.where(issue: issue).count }.by(1)
+
+ expect(issue.incident_management_issuable_escalation_status).to be_resolved
+ end
+
+ context 'when there is an escalation status' do
+ before do
+ create(:incident_management_issuable_escalation_status, issue: issue)
+ end
+
+ it 'changes escalations status to resolved' do
+ expect { service.execute(issue) }.to change { issue.incident_management_issuable_escalation_status.reload.resolved? }.to(true)
+ end
+
+ it 'adds a system note', :aggregate_failures do
+ expect { service.execute(issue) }.to change { issue.notes.count }.by(1)
+
+ new_note = issue.notes.last
+ expect(new_note.note).to eq('changed the status to **Resolved** by closing the incident')
+ expect(new_note.author).to eq(user)
+ end
+
+ context 'when the escalation status did not change to resolved' do
+ let(:escalation_status) { instance_double('IncidentManagement::IssuableEscalationStatus', resolve: false) }
+
+ it 'does not create a system note' do
+ allow(issue).to receive(:incident_management_issuable_escalation_status).and_return(escalation_status)
+
+ expect { service.execute(issue) }.not_to change { issue.notes.count }
+ end
+ end
+ end
end
end
@@ -237,7 +279,7 @@ RSpec.describe Issues::CloseService do
it 'verifies the number of queries' do
recorded = ActiveRecord::QueryRecorder.new { close_issue }
- expected_queries = 27
+ expected_queries = 32
expect(recorded.count).to be <= expected_queries
expect(recorded.cached_count).to eq(0)
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 1887be4896e..18e03db11dc 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -15,8 +15,7 @@ RSpec.describe Issues::CreateService do
expect(described_class.rate_limiter_scoped_and_keyed).to be_a(RateLimitedService::RateLimiterScopedAndKeyed)
expect(described_class.rate_limiter_scoped_and_keyed.key).to eq(:issues_create)
- expect(described_class.rate_limiter_scoped_and_keyed.opts[:scope]).to eq(%i[project current_user])
- expect(described_class.rate_limiter_scoped_and_keyed.opts[:users_allowlist].call).to eq(%w[support-bot])
+ expect(described_class.rate_limiter_scoped_and_keyed.opts[:scope]).to eq(%i[project current_user external_author])
expect(described_class.rate_limiter_scoped_and_keyed.rate_limiter_klass).to eq(Gitlab::ApplicationRateLimiter)
end
end
@@ -81,7 +80,7 @@ RSpec.describe Issues::CreateService do
it_behaves_like 'not an incident issue'
- context 'issue is incident type' do
+ context 'when issue is incident type' do
before do
opts.merge!(issue_type: 'incident')
end
@@ -91,23 +90,37 @@ RSpec.describe Issues::CreateService do
subject { issue }
- it_behaves_like 'incident issue'
- it_behaves_like 'has incident label'
+ context 'as reporter' do
+ let_it_be(:reporter) { create(:user) }
- it 'does create an incident label' do
- expect { subject }
- .to change { Label.where(incident_label_attributes).count }.by(1)
- end
+ let(:user) { reporter }
- context 'when invalid' do
- before do
- opts.merge!(title: '')
+ before_all do
+ project.add_reporter(reporter)
end
- it 'does not apply an incident label prematurely' do
- expect { subject }.to not_change(LabelLink, :count).and not_change(Issue, :count)
+ it_behaves_like 'incident issue'
+ it_behaves_like 'has incident label'
+
+ it 'does create an incident label' do
+ expect { subject }
+ .to change { Label.where(incident_label_attributes).count }.by(1)
+ end
+
+ context 'when invalid' do
+ before do
+ opts.merge!(title: '')
+ end
+
+ it 'does not apply an incident label prematurely' do
+ expect { subject }.to not_change(LabelLink, :count).and not_change(Issue, :count)
+ end
end
end
+
+ context 'as guest' do
+ it_behaves_like 'not an incident issue'
+ end
end
it 'refreshes the number of open issues', :use_clean_rails_memory_store_caching do
@@ -289,6 +302,44 @@ RSpec.describe Issues::CreateService do
described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
end
+ context 'when rate limiting is in effect', :freeze_time, :clean_gitlab_redis_rate_limiting do
+ let(:user) { create(:user) }
+
+ before do
+ stub_feature_flags(rate_limited_service_issues_create: true)
+ stub_application_setting(issues_create_limit: 1)
+ end
+
+ subject do
+ 2.times { described_class.new(project: project, current_user: user, params: opts, spam_params: double).execute }
+ end
+
+ context 'when too many requests are sent by one user' do
+ it 'raises an error' do
+ expect do
+ subject
+ end.to raise_error(RateLimitedService::RateLimitedError)
+ end
+
+ it 'creates 1 issue' do
+ expect do
+ subject
+ rescue RateLimitedService::RateLimitedError
+ end.to change { Issue.count }.by(1)
+ end
+ end
+
+ context 'when limit is higher than count of issues being created' do
+ before do
+ stub_application_setting(issues_create_limit: 2)
+ end
+
+ it 'creates 2 issues' do
+ expect { subject }.to change { Issue.count }.by(2)
+ end
+ end
+ end
+
context 'after_save callback to store_mentions' do
context 'when mentionable attributes change' do
let(:opts) { { title: 'Title', description: "Description with #{user.to_reference}" } }
diff --git a/spec/services/issues/set_crm_contacts_service_spec.rb b/spec/services/issues/set_crm_contacts_service_spec.rb
new file mode 100644
index 00000000000..65b22fe3b35
--- /dev/null
+++ b/spec/services/issues/set_crm_contacts_service_spec.rb
@@ -0,0 +1,162 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Issues::SetCrmContactsService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:contacts) { create_list(:contact, 4, group: group) }
+
+ let(:issue) { create(:issue, project: project) }
+ let(:does_not_exist_or_no_permission) { "The resource that you are attempting to access does not exist or you don't have permission to perform this action" }
+
+ before do
+ create(:issue_customer_relations_contact, issue: issue, contact: contacts[0])
+ create(:issue_customer_relations_contact, issue: issue, contact: contacts[1])
+ end
+
+ subject(:set_crm_contacts) do
+ described_class.new(project: project, current_user: user, params: params).execute(issue)
+ end
+
+ describe '#execute' do
+ context 'when the user has no permission' do
+ let(:params) { { crm_contact_ids: [contacts[1].id, contacts[2].id] } }
+
+ it 'returns expected error response' do
+ response = set_crm_contacts
+
+ expect(response).to be_error
+ expect(response.message).to match_array(['You have insufficient permissions to set customer relations contacts for this issue'])
+ end
+ end
+
+ context 'when user has permission' do
+ before do
+ group.add_reporter(user)
+ end
+
+ context 'when the contact does not exist' do
+ let(:params) { { crm_contact_ids: [non_existing_record_id] } }
+
+ it 'returns expected error response' do
+ response = set_crm_contacts
+
+ expect(response).to be_error
+ expect(response.message).to match_array(["Issue customer relations contacts #{non_existing_record_id}: #{does_not_exist_or_no_permission}"])
+ end
+ end
+
+ context 'when the contact belongs to a different group' do
+ let(:group2) { create(:group) }
+ let(:contact) { create(:contact, group: group2) }
+ let(:params) { { crm_contact_ids: [contact.id] } }
+
+ before do
+ group2.add_reporter(user)
+ end
+
+ it 'returns expected error response' do
+ response = set_crm_contacts
+
+ expect(response).to be_error
+ expect(response.message).to match_array(["Issue customer relations contacts #{contact.id}: #{does_not_exist_or_no_permission}"])
+ end
+ end
+
+ context 'replace' do
+ let(:params) { { crm_contact_ids: [contacts[1].id, contacts[2].id] } }
+
+ it 'updates the issue with correct contacts' do
+ response = set_crm_contacts
+
+ expect(response).to be_success
+ expect(issue.customer_relations_contacts).to match_array([contacts[1], contacts[2]])
+ end
+ end
+
+ context 'add' do
+ let(:params) { { add_crm_contact_ids: [contacts[3].id] } }
+
+ it 'updates the issue with correct contacts' do
+ response = set_crm_contacts
+
+ expect(response).to be_success
+ expect(issue.customer_relations_contacts).to match_array([contacts[0], contacts[1], contacts[3]])
+ end
+ end
+
+ context 'remove' do
+ let(:params) { { remove_crm_contact_ids: [contacts[0].id] } }
+
+ it 'updates the issue with correct contacts' do
+ response = set_crm_contacts
+
+ expect(response).to be_success
+ expect(issue.customer_relations_contacts).to match_array([contacts[1]])
+ end
+ end
+
+ context 'when attempting to add more than 6' do
+ let(:id) { contacts[0].id }
+ let(:params) { { add_crm_contact_ids: [id, id, id, id, id, id, id] } }
+
+ it 'returns expected error message' do
+ response = set_crm_contacts
+
+ expect(response).to be_error
+ expect(response.message).to match_array(['You can only add up to 6 contacts at one time'])
+ end
+ end
+
+ context 'when trying to remove non-existent contact' do
+ let(:params) { { remove_crm_contact_ids: [non_existing_record_id] } }
+
+ it 'returns expected error message' do
+ response = set_crm_contacts
+
+ expect(response).to be_success
+ expect(response.message).to be_nil
+ end
+ end
+
+ context 'when combining params' do
+ let(:error_invalid_params) { 'You cannot combine crm_contact_ids with add_crm_contact_ids or remove_crm_contact_ids' }
+
+ context 'add and remove' do
+ let(:params) { { remove_crm_contact_ids: [contacts[1].id], add_crm_contact_ids: [contacts[3].id] } }
+
+ it 'updates the issue with correct contacts' do
+ response = set_crm_contacts
+
+ expect(response).to be_success
+ expect(issue.customer_relations_contacts).to match_array([contacts[0], contacts[3]])
+ end
+ end
+
+ context 'replace and remove' do
+ let(:params) { { crm_contact_ids: [contacts[3].id], remove_crm_contact_ids: [contacts[0].id] } }
+
+ it 'returns expected error response' do
+ response = set_crm_contacts
+
+ expect(response).to be_error
+ expect(response.message).to match_array([error_invalid_params])
+ end
+ end
+
+ context 'replace and add' do
+ let(:params) { { crm_contact_ids: [contacts[3].id], add_crm_contact_ids: [contacts[1].id] } }
+
+ it 'returns expected error response' do
+ response = set_crm_contacts
+
+ expect(response).to be_error
+ expect(response.message).to match_array([error_invalid_params])
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 83c17f051eb..85b8fef685e 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -1256,28 +1256,38 @@ RSpec.describe Issues::UpdateService, :mailer do
let(:closed_issuable) { create(:closed_issue, project: project) }
end
- context 'real-time updates' do
- using RSpec::Parameterized::TableSyntax
-
+ context 'broadcasting issue assignee updates' do
let(:update_params) { { assignee_ids: [user2.id] } }
- where(:action_cable_in_app_enabled, :feature_flag_enabled, :should_broadcast) do
- true | true | true
- true | false | true
- false | true | true
- false | false | false
- end
+ context 'when feature flag is enabled' do
+ before do
+ stub_feature_flags(broadcast_issue_updates: true)
+ end
+
+ it 'triggers the GraphQL subscription' do
+ expect(GraphqlTriggers).to receive(:issuable_assignees_updated).with(issue)
+
+ update_issue(update_params)
+ end
- with_them do
- it 'broadcasts to the issues channel based on ActionCable and feature flag values' do
- allow(Gitlab::ActionCable::Config).to receive(:in_app?).and_return(action_cable_in_app_enabled)
- stub_feature_flags(broadcast_issue_updates: feature_flag_enabled)
+ context 'when assignee is not updated' do
+ let(:update_params) { { title: 'Some other title' } }
- if should_broadcast
- expect(GraphqlTriggers).to receive(:issuable_assignees_updated).with(issue)
- else
+ it 'does not trigger the GraphQL subscription' do
expect(GraphqlTriggers).not_to receive(:issuable_assignees_updated).with(issue)
+
+ update_issue(update_params)
end
+ end
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(broadcast_issue_updates: false)
+ end
+
+ it 'does not trigger the GraphQL subscription' do
+ expect(GraphqlTriggers).not_to receive(:issuable_assignees_updated).with(issue)
update_issue(update_params)
end
diff --git a/spec/services/labels/transfer_service_spec.rb b/spec/services/labels/transfer_service_spec.rb
index 18fd401f383..05190accb33 100644
--- a/spec/services/labels/transfer_service_spec.rb
+++ b/spec/services/labels/transfer_service_spec.rb
@@ -3,107 +3,121 @@
require 'spec_helper'
RSpec.describe Labels::TransferService do
- describe '#execute' do
- let_it_be(:user) { create(:user) }
+ shared_examples 'transfer labels' do
+ describe '#execute' do
+ let_it_be(:user) { create(:user) }
- let_it_be(:old_group_ancestor) { create(:group) }
- let_it_be(:old_group) { create(:group, parent: old_group_ancestor) }
+ let_it_be(:old_group_ancestor) { create(:group) }
+ let_it_be(:old_group) { create(:group, parent: old_group_ancestor) }
- let_it_be(:new_group) { create(:group) }
+ let_it_be(:new_group) { create(:group) }
- let_it_be(:project) { create(:project, :repository, group: new_group) }
+ let_it_be(:project) { create(:project, :repository, group: new_group) }
- subject(:service) { described_class.new(user, old_group, project) }
+ subject(:service) { described_class.new(user, old_group, project) }
- before do
- old_group_ancestor.add_developer(user)
- new_group.add_developer(user)
- end
+ before do
+ old_group_ancestor.add_developer(user)
+ new_group.add_developer(user)
+ end
- it 'recreates missing group labels at project level and assigns them to the issuables' do
- old_group_label_1 = create(:group_label, group: old_group)
- old_group_label_2 = create(:group_label, group: old_group)
+ it 'recreates missing group labels at project level and assigns them to the issuables' do
+ old_group_label_1 = create(:group_label, group: old_group)
+ old_group_label_2 = create(:group_label, group: old_group)
- labeled_issue = create(:labeled_issue, project: project, labels: [old_group_label_1])
- labeled_merge_request = create(:labeled_merge_request, source_project: project, labels: [old_group_label_2])
+ labeled_issue = create(:labeled_issue, project: project, labels: [old_group_label_1])
+ labeled_merge_request = create(:labeled_merge_request, source_project: project, labels: [old_group_label_2])
- expect { service.execute }.to change(project.labels, :count).by(2)
- expect(labeled_issue.reload.labels).to contain_exactly(project.labels.find_by_title(old_group_label_1.title))
- expect(labeled_merge_request.reload.labels).to contain_exactly(project.labels.find_by_title(old_group_label_2.title))
- end
+ expect { service.execute }.to change(project.labels, :count).by(2)
+ expect(labeled_issue.reload.labels).to contain_exactly(project.labels.find_by_title(old_group_label_1.title))
+ expect(labeled_merge_request.reload.labels).to contain_exactly(project.labels.find_by_title(old_group_label_2.title))
+ end
- it 'recreates missing ancestor group labels at project level and assigns them to the issuables' do
- old_group_ancestor_label_1 = create(:group_label, group: old_group_ancestor)
- old_group_ancestor_label_2 = create(:group_label, group: old_group_ancestor)
+ it 'recreates missing ancestor group labels at project level and assigns them to the issuables' do
+ old_group_ancestor_label_1 = create(:group_label, group: old_group_ancestor)
+ old_group_ancestor_label_2 = create(:group_label, group: old_group_ancestor)
- labeled_issue = create(:labeled_issue, project: project, labels: [old_group_ancestor_label_1])
- labeled_merge_request = create(:labeled_merge_request, source_project: project, labels: [old_group_ancestor_label_2])
+ labeled_issue = create(:labeled_issue, project: project, labels: [old_group_ancestor_label_1])
+ labeled_merge_request = create(:labeled_merge_request, source_project: project, labels: [old_group_ancestor_label_2])
- expect { service.execute }.to change(project.labels, :count).by(2)
- expect(labeled_issue.reload.labels).to contain_exactly(project.labels.find_by_title(old_group_ancestor_label_1.title))
- expect(labeled_merge_request.reload.labels).to contain_exactly(project.labels.find_by_title(old_group_ancestor_label_2.title))
- end
+ expect { service.execute }.to change(project.labels, :count).by(2)
+ expect(labeled_issue.reload.labels).to contain_exactly(project.labels.find_by_title(old_group_ancestor_label_1.title))
+ expect(labeled_merge_request.reload.labels).to contain_exactly(project.labels.find_by_title(old_group_ancestor_label_2.title))
+ end
- it 'recreates label priorities related to the missing group labels' do
- old_group_label = create(:group_label, group: old_group)
- create(:labeled_issue, project: project, labels: [old_group_label])
- create(:label_priority, project: project, label: old_group_label, priority: 1)
+ it 'recreates label priorities related to the missing group labels' do
+ old_group_label = create(:group_label, group: old_group)
+ create(:labeled_issue, project: project, labels: [old_group_label])
+ create(:label_priority, project: project, label: old_group_label, priority: 1)
- service.execute
+ service.execute
- new_project_label = project.labels.find_by(title: old_group_label.title)
- expect(new_project_label.id).not_to eq old_group_label.id
- expect(new_project_label.priorities).not_to be_empty
- end
+ new_project_label = project.labels.find_by(title: old_group_label.title)
+ expect(new_project_label.id).not_to eq old_group_label.id
+ expect(new_project_label.priorities).not_to be_empty
+ end
- it 'does not recreate missing group labels that are not applied to issues or merge requests' do
- old_group_label = create(:group_label, group: old_group)
+ it 'does not recreate missing group labels that are not applied to issues or merge requests' do
+ old_group_label = create(:group_label, group: old_group)
- service.execute
+ service.execute
- expect(project.labels.where(title: old_group_label.title)).to be_empty
- end
+ expect(project.labels.where(title: old_group_label.title)).to be_empty
+ end
- it 'does not recreate missing group labels that already exist in the project group' do
- old_group_label = create(:group_label, group: old_group)
- labeled_issue = create(:labeled_issue, project: project, labels: [old_group_label])
+ it 'does not recreate missing group labels that already exist in the project group' do
+ old_group_label = create(:group_label, group: old_group)
+ labeled_issue = create(:labeled_issue, project: project, labels: [old_group_label])
- new_group_label = create(:group_label, group: new_group, title: old_group_label.title)
+ new_group_label = create(:group_label, group: new_group, title: old_group_label.title)
- service.execute
+ service.execute
- expect(project.labels.where(title: old_group_label.title)).to be_empty
- expect(labeled_issue.reload.labels).to contain_exactly(new_group_label)
- end
+ expect(project.labels.where(title: old_group_label.title)).to be_empty
+ expect(labeled_issue.reload.labels).to contain_exactly(new_group_label)
+ end
- it 'updates only label links in the given project' do
- old_group_label = create(:group_label, group: old_group)
- other_project = create(:project, group: old_group)
+ it 'updates only label links in the given project' do
+ old_group_label = create(:group_label, group: old_group)
+ other_project = create(:project, group: old_group)
- labeled_issue = create(:labeled_issue, project: project, labels: [old_group_label])
- other_project_labeled_issue = create(:labeled_issue, project: other_project, labels: [old_group_label])
+ labeled_issue = create(:labeled_issue, project: project, labels: [old_group_label])
+ other_project_labeled_issue = create(:labeled_issue, project: other_project, labels: [old_group_label])
- service.execute
+ service.execute
- expect(labeled_issue.reload.labels).not_to include(old_group_label)
- expect(other_project_labeled_issue.reload.labels).to contain_exactly(old_group_label)
- end
+ expect(labeled_issue.reload.labels).not_to include(old_group_label)
+ expect(other_project_labeled_issue.reload.labels).to contain_exactly(old_group_label)
+ end
- context 'when moving within the same ancestor group' do
- let(:other_subgroup) { create(:group, parent: old_group_ancestor) }
- let(:project) { create(:project, :repository, group: other_subgroup) }
+ context 'when moving within the same ancestor group' do
+ let(:other_subgroup) { create(:group, parent: old_group_ancestor) }
+ let(:project) { create(:project, :repository, group: other_subgroup) }
- it 'does not recreate ancestor group labels' do
- old_group_ancestor_label_1 = create(:group_label, group: old_group_ancestor)
- old_group_ancestor_label_2 = create(:group_label, group: old_group_ancestor)
+ it 'does not recreate ancestor group labels' do
+ old_group_ancestor_label_1 = create(:group_label, group: old_group_ancestor)
+ old_group_ancestor_label_2 = create(:group_label, group: old_group_ancestor)
- labeled_issue = create(:labeled_issue, project: project, labels: [old_group_ancestor_label_1])
- labeled_merge_request = create(:labeled_merge_request, source_project: project, labels: [old_group_ancestor_label_2])
+ labeled_issue = create(:labeled_issue, project: project, labels: [old_group_ancestor_label_1])
+ labeled_merge_request = create(:labeled_merge_request, source_project: project, labels: [old_group_ancestor_label_2])
- expect { service.execute }.not_to change(project.labels, :count)
- expect(labeled_issue.reload.labels).to contain_exactly(old_group_ancestor_label_1)
- expect(labeled_merge_request.reload.labels).to contain_exactly(old_group_ancestor_label_2)
+ expect { service.execute }.not_to change(project.labels, :count)
+ expect(labeled_issue.reload.labels).to contain_exactly(old_group_ancestor_label_1)
+ expect(labeled_merge_request.reload.labels).to contain_exactly(old_group_ancestor_label_2)
+ end
end
end
end
+
+ context 'with use_optimized_group_labels_query FF on' do
+ it_behaves_like 'transfer labels'
+ end
+
+ context 'with use_optimized_group_labels_query FF off' do
+ before do
+ stub_feature_flags(use_optimized_group_labels_query: false)
+ end
+
+ it_behaves_like 'transfer labels'
+ end
end
diff --git a/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb b/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb
new file mode 100644
index 00000000000..bdb3d0f6700
--- /dev/null
+++ b/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb
@@ -0,0 +1,119 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe LooseForeignKeys::BatchCleanerService do
+ include MigrationsHelpers
+
+ def create_table_structure
+ migration = ActiveRecord::Migration.new.extend(Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers)
+
+ migration.create_table :_test_loose_fk_parent_table
+
+ migration.create_table :_test_loose_fk_child_table_1 do |t|
+ t.bigint :parent_id
+ end
+
+ migration.create_table :_test_loose_fk_child_table_2 do |t|
+ t.bigint :parent_id_with_different_column
+ end
+
+ migration.track_record_deletions(:_test_loose_fk_parent_table)
+ end
+
+ let(:parent_model) do
+ Class.new(ApplicationRecord) do
+ self.table_name = '_test_loose_fk_parent_table'
+
+ include LooseForeignKey
+
+ loose_foreign_key :_test_loose_fk_child_table_1, :parent_id, on_delete: :async_delete
+ loose_foreign_key :_test_loose_fk_child_table_2, :parent_id_with_different_column, on_delete: :async_nullify
+ end
+ end
+
+ let(:child_model_1) do
+ Class.new(ApplicationRecord) do
+ self.table_name = '_test_loose_fk_child_table_1'
+ end
+ end
+
+ let(:child_model_2) do
+ Class.new(ApplicationRecord) do
+ self.table_name = '_test_loose_fk_child_table_2'
+ end
+ end
+
+ let(:loose_fk_child_table_1) { table(:_test_loose_fk_child_table_1) }
+ let(:loose_fk_child_table_2) { table(:_test_loose_fk_child_table_2) }
+ let(:parent_record_1) { parent_model.create! }
+ let(:other_parent_record) { parent_model.create! }
+
+ before(:all) do
+ create_table_structure
+ end
+
+ before do
+ parent_record_1
+
+ loose_fk_child_table_1.create!(parent_id: parent_record_1.id)
+ loose_fk_child_table_1.create!(parent_id: parent_record_1.id)
+
+ # these will not be deleted
+ loose_fk_child_table_1.create!(parent_id: other_parent_record.id)
+ loose_fk_child_table_1.create!(parent_id: other_parent_record.id)
+
+ loose_fk_child_table_2.create!(parent_id_with_different_column: parent_record_1.id)
+ loose_fk_child_table_2.create!(parent_id_with_different_column: parent_record_1.id)
+
+ # these will not be deleted
+ loose_fk_child_table_2.create!(parent_id_with_different_column: other_parent_record.id)
+ loose_fk_child_table_2.create!(parent_id_with_different_column: other_parent_record.id)
+ end
+
+ after(:all) do
+ migration = ActiveRecord::Migration.new
+ migration.drop_table :_test_loose_fk_parent_table
+ migration.drop_table :_test_loose_fk_child_table_1
+ migration.drop_table :_test_loose_fk_child_table_2
+ end
+
+ context 'when parent records are deleted' do
+ let(:deleted_records_counter) { Gitlab::Metrics.registry.get(:loose_foreign_key_processed_deleted_records) }
+
+ before do
+ parent_record_1.delete
+
+ expect(loose_fk_child_table_1.count).to eq(4)
+ expect(loose_fk_child_table_2.count).to eq(4)
+
+ described_class.new(parent_klass: parent_model,
+ deleted_parent_records: LooseForeignKeys::DeletedRecord.status_pending.all,
+ models_by_table_name: {
+ '_test_loose_fk_child_table_1' => child_model_1,
+ '_test_loose_fk_child_table_2' => child_model_2
+ }).execute
+ end
+
+ it 'cleans up the child records' do
+ expect(loose_fk_child_table_1.where(parent_id: parent_record_1.id)).to be_empty
+ expect(loose_fk_child_table_2.where(parent_id_with_different_column: nil).count).to eq(2)
+ end
+
+ it 'cleans up the pending parent DeletedRecord' do
+ expect(LooseForeignKeys::DeletedRecord.status_pending.count).to eq(0)
+ expect(LooseForeignKeys::DeletedRecord.status_processed.count).to eq(1)
+ end
+
+ it 'records the DeletedRecord status updates', :prometheus do
+ counter = Gitlab::Metrics.registry.get(:loose_foreign_key_processed_deleted_records)
+
+ expect(counter.get(table: parent_model.table_name, db_config_name: 'main')).to eq(1)
+ end
+
+ it 'does not delete unrelated records' do
+ expect(loose_fk_child_table_1.where(parent_id: other_parent_record.id).count).to eq(2)
+ expect(loose_fk_child_table_2.where(parent_id_with_different_column: other_parent_record.id).count).to eq(2)
+ end
+ end
+end
diff --git a/spec/services/loose_foreign_keys/cleaner_service_spec.rb b/spec/services/loose_foreign_keys/cleaner_service_spec.rb
new file mode 100644
index 00000000000..6f37ac49435
--- /dev/null
+++ b/spec/services/loose_foreign_keys/cleaner_service_spec.rb
@@ -0,0 +1,147 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe LooseForeignKeys::CleanerService do
+ let(:schema) { ApplicationRecord.connection.current_schema }
+ let(:deleted_records) do
+ [
+ LooseForeignKeys::DeletedRecord.new(fully_qualified_table_name: "#{schema}.projects", primary_key_value: non_existing_record_id),
+ LooseForeignKeys::DeletedRecord.new(fully_qualified_table_name: "#{schema}.projects", primary_key_value: non_existing_record_id)
+ ]
+ end
+
+ let(:loose_fk_definition) do
+ ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
+ 'projects',
+ 'issues',
+ {
+ column: 'project_id',
+ on_delete: :async_nullify
+ }
+ )
+ end
+
+ subject(:cleaner_service) do
+ described_class.new(
+ model: Issue,
+ foreign_key_definition: loose_fk_definition,
+ deleted_parent_records: deleted_records
+ )
+ end
+
+ context 'when invalid foreign key definition is passed' do
+ context 'when invalid on_delete argument was given' do
+ before do
+ loose_fk_definition.options[:on_delete] = :invalid
+ end
+
+ it 'raises KeyError' do
+ expect { cleaner_service.execute }.to raise_error(StandardError, /Invalid on_delete argument/)
+ end
+ end
+ end
+
+ describe 'query generation' do
+ context 'when single primary key is used' do
+ let(:issue) { create(:issue) }
+
+ let(:deleted_records) do
+ [
+ LooseForeignKeys::DeletedRecord.new(fully_qualified_table_name: "#{schema}.projects", primary_key_value: issue.project_id)
+ ]
+ end
+
+ it 'generates an IN query for nullifying the rows' do
+ expected_query = %{UPDATE "issues" SET "project_id" = NULL WHERE ("issues"."id") IN (SELECT "issues"."id" FROM "issues" WHERE "issues"."project_id" IN (#{issue.project_id}) LIMIT 500)}
+ expect(ApplicationRecord.connection).to receive(:execute).with(expected_query).and_call_original
+
+ cleaner_service.execute
+
+ issue.reload
+ expect(issue.project_id).to be_nil
+ end
+
+ it 'generates an IN query for deleting the rows' do
+ loose_fk_definition.options[:on_delete] = :async_delete
+
+ expected_query = %{DELETE FROM "issues" WHERE ("issues"."id") IN (SELECT "issues"."id" FROM "issues" WHERE "issues"."project_id" IN (#{issue.project_id}) LIMIT 1000)}
+ expect(ApplicationRecord.connection).to receive(:execute).with(expected_query).and_call_original
+
+ cleaner_service.execute
+
+ expect(Issue.exists?(id: issue.id)).to eq(false)
+ end
+ end
+
+ context 'when composite primary key is used' do
+ let!(:user) { create(:user) }
+ let!(:project) { create(:project) }
+
+ let(:loose_fk_definition) do
+ ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
+ 'users',
+ 'project_authorizations',
+ {
+ column: 'user_id',
+ on_delete: :async_delete
+ }
+ )
+ end
+
+ let(:deleted_records) do
+ [
+ LooseForeignKeys::DeletedRecord.new(fully_qualified_table_name: "#{schema}.users", primary_key_value: user.id)
+ ]
+ end
+
+ subject(:cleaner_service) do
+ described_class.new(
+ model: ProjectAuthorization,
+ foreign_key_definition: loose_fk_definition,
+ deleted_parent_records: deleted_records
+ )
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ it 'generates an IN query for deleting the rows' do
+ expected_query = %{DELETE FROM "project_authorizations" WHERE ("project_authorizations"."user_id", "project_authorizations"."project_id", "project_authorizations"."access_level") IN (SELECT "project_authorizations"."user_id", "project_authorizations"."project_id", "project_authorizations"."access_level" FROM "project_authorizations" WHERE "project_authorizations"."user_id" IN (#{user.id}) LIMIT 1000)}
+ expect(ApplicationRecord.connection).to receive(:execute).with(expected_query).and_call_original
+
+ cleaner_service.execute
+
+ expect(ProjectAuthorization.exists?(user_id: user.id)).to eq(false)
+ end
+
+ context 'when the query generation is incorrect (paranoid check)' do
+ it 'raises error if the foreign key condition is missing' do
+ expect_next_instance_of(LooseForeignKeys::CleanerService) do |instance|
+ expect(instance).to receive(:delete_query).and_return('wrong query')
+ end
+
+ expect { cleaner_service.execute }.to raise_error /FATAL: foreign key condition is missing from the generated query/
+ end
+ end
+ end
+
+ context 'when with_skip_locked parameter is true' do
+ subject(:cleaner_service) do
+ described_class.new(
+ model: Issue,
+ foreign_key_definition: loose_fk_definition,
+ deleted_parent_records: deleted_records,
+ with_skip_locked: true
+ )
+ end
+
+ it 'generates a query with the SKIP LOCKED clause' do
+ expect(ApplicationRecord.connection).to receive(:execute).with(/FOR UPDATE SKIP LOCKED/).and_call_original
+
+ cleaner_service.execute
+ end
+ end
+ end
+end
diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb
index 2e6e6041fc3..fe866d73215 100644
--- a/spec/services/members/create_service_spec.rb
+++ b/spec/services/members/create_service_spec.rb
@@ -196,4 +196,108 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_
end
end
end
+
+ context 'when assigning tasks to be done' do
+ let(:additional_params) do
+ { invite_source: '_invite_source_', tasks_to_be_done: %w(ci code), tasks_project_id: source.id }
+ end
+
+ before do
+ stub_experiments(invite_members_for_task: true)
+ end
+
+ it 'creates 2 task issues', :aggregate_failures do
+ expect(TasksToBeDone::CreateWorker)
+ .to receive(:perform_async)
+ .with(anything, user.id, [member.id])
+ .once
+ .and_call_original
+ expect { execute_service }.to change { source.issues.count }.by(2)
+
+ expect(source.issues).to all have_attributes(
+ project: source,
+ author: user
+ )
+ end
+
+ context 'when passing many user ids' do
+ before do
+ stub_licensed_features(multiple_issue_assignees: false)
+ end
+
+ let(:another_user) { create(:user) }
+ let(:user_ids) { [member.id, another_user.id].join(',') }
+
+ it 'still creates 2 task issues', :aggregate_failures do
+ expect(TasksToBeDone::CreateWorker)
+ .to receive(:perform_async)
+ .with(anything, user.id, array_including(member.id, another_user.id))
+ .once
+ .and_call_original
+ expect { execute_service }.to change { source.issues.count }.by(2)
+
+ expect(source.issues).to all have_attributes(
+ project: source,
+ author: user
+ )
+ end
+ end
+
+ context 'when a `tasks_project_id` is missing' do
+ let(:additional_params) do
+ { invite_source: '_invite_source_', tasks_to_be_done: %w(ci code) }
+ end
+
+ it 'does not create task issues' do
+ expect(TasksToBeDone::CreateWorker).not_to receive(:perform_async)
+ execute_service
+ end
+ end
+
+ context 'when `tasks_to_be_done` are missing' do
+ let(:additional_params) do
+ { invite_source: '_invite_source_', tasks_project_id: source.id }
+ end
+
+ it 'does not create task issues' do
+ expect(TasksToBeDone::CreateWorker).not_to receive(:perform_async)
+ execute_service
+ end
+ end
+
+ context 'when invalid `tasks_to_be_done` are passed' do
+ let(:additional_params) do
+ { invite_source: '_invite_source_', tasks_project_id: source.id, tasks_to_be_done: %w(invalid_task) }
+ end
+
+ it 'does not create task issues' do
+ expect(TasksToBeDone::CreateWorker).not_to receive(:perform_async)
+ execute_service
+ end
+ end
+
+ context 'when invalid `tasks_project_id` is passed' do
+ let(:another_project) { create(:project) }
+ let(:additional_params) do
+ { invite_source: '_invite_source_', tasks_project_id: another_project.id, tasks_to_be_done: %w(ci code) }
+ end
+
+ it 'does not create task issues' do
+ expect(TasksToBeDone::CreateWorker).not_to receive(:perform_async)
+ execute_service
+ end
+ end
+
+ context 'when a member was already invited' do
+ let(:user_ids) { create(:project_member, :invited, project: source).invite_email }
+ let(:additional_params) do
+ { invite_source: '_invite_source_', tasks_project_id: source.id, tasks_to_be_done: %w(ci code) }
+ end
+
+ it 'does not create task issues' do
+ expect(TasksToBeDone::CreateWorker).not_to receive(:perform_async)
+ execute_service
+ end
+ end
+ end
end
diff --git a/spec/services/members/invite_service_spec.rb b/spec/services/members/invite_service_spec.rb
index 478733e8aa0..7b9ae19f038 100644
--- a/spec/services/members/invite_service_spec.rb
+++ b/spec/services/members/invite_service_spec.rb
@@ -22,6 +22,11 @@ RSpec.describe Members::InviteService, :aggregate_failures, :clean_gitlab_redis_
end
it_behaves_like 'records an onboarding progress action', :user_added
+
+ it 'does not create task issues' do
+ expect(TasksToBeDone::CreateWorker).not_to receive(:perform_async)
+ expect { result }.not_to change { project.issues.count }
+ end
end
context 'when email belongs to an existing user as a secondary email' do
diff --git a/spec/services/merge_requests/mergeability/run_checks_service_spec.rb b/spec/services/merge_requests/mergeability/run_checks_service_spec.rb
index 170d99f4642..71ad23bc68c 100644
--- a/spec/services/merge_requests/mergeability/run_checks_service_spec.rb
+++ b/spec/services/merge_requests/mergeability/run_checks_service_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe MergeRequests::Mergeability::RunChecksService do
let_it_be(:merge_request) { create(:merge_request) }
describe '#CHECKS' do
- it 'contains every subclass of the base checks service' do
+ it 'contains every subclass of the base checks service', :eager_load do
expect(described_class::CHECKS).to contain_exactly(*MergeRequests::Mergeability::CheckBaseService.subclasses)
end
end
@@ -19,7 +19,7 @@ RSpec.describe MergeRequests::Mergeability::RunChecksService do
let(:params) { {} }
let(:success_result) { Gitlab::MergeRequests::Mergeability::CheckResult.success }
- context 'when every check is skipped' do
+ context 'when every check is skipped', :eager_load do
before do
MergeRequests::Mergeability::CheckBaseService.subclasses.each do |subclass|
expect_next_instance_of(subclass) do |service|
diff --git a/spec/services/merge_requests/retarget_chain_service_spec.rb b/spec/services/merge_requests/retarget_chain_service_spec.rb
index 87bde4a1400..187dd0cf589 100644
--- a/spec/services/merge_requests/retarget_chain_service_spec.rb
+++ b/spec/services/merge_requests/retarget_chain_service_spec.rb
@@ -45,14 +45,6 @@ RSpec.describe MergeRequests::RetargetChainService do
.from(merge_request.source_branch)
.to(merge_request.target_branch)
end
-
- context 'when FF retarget_merge_requests is disabled' do
- before do
- stub_feature_flags(retarget_merge_requests: false)
- end
-
- include_examples 'does not retarget merge request'
- end
end
context 'in the same project' do
diff --git a/spec/services/merge_requests/toggle_attention_requested_service_spec.rb b/spec/services/merge_requests/toggle_attention_requested_service_spec.rb
new file mode 100644
index 00000000000..a26b1be529e
--- /dev/null
+++ b/spec/services/merge_requests/toggle_attention_requested_service_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::ToggleAttentionRequestedService do
+ let(:current_user) { create(:user) }
+ let(:user) { create(:user) }
+ let(:assignee_user) { create(:user) }
+ let(:merge_request) { create(:merge_request, reviewers: [user], assignees: [assignee_user]) }
+ let(:reviewer) { merge_request.find_reviewer(user) }
+ let(:assignee) { merge_request.find_assignee(assignee_user) }
+ let(:project) { merge_request.project }
+ let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: user) }
+ let(:result) { service.execute }
+ let(:todo_service) { spy('todo service') }
+
+ before do
+ allow(service).to receive(:todo_service).and_return(todo_service)
+
+ project.add_developer(current_user)
+ project.add_developer(user)
+ end
+
+ describe '#execute' do
+ context 'invalid permissions' do
+ let(:service) { described_class.new(project: project, current_user: create(:user), merge_request: merge_request, user: user) }
+
+ it 'returns an error' do
+ expect(result[:status]).to eq :error
+ end
+ end
+
+ context 'reviewer does not exist' do
+ let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: create(:user)) }
+
+ it 'returns an error' do
+ expect(result[:status]).to eq :error
+ end
+ end
+
+ context 'reviewer exists' do
+ before do
+ reviewer.update!(state: :reviewed)
+ end
+
+ it 'returns success' do
+ expect(result[:status]).to eq :success
+ end
+
+ it 'updates reviewers state' do
+ service.execute
+ reviewer.reload
+
+ expect(reviewer.state).to eq 'attention_requested'
+ end
+
+ it 'creates a new todo for the reviewer' do
+ expect(todo_service).to receive(:create_attention_requested_todo).with(merge_request, current_user, user)
+
+ service.execute
+ end
+ end
+
+ context 'assignee exists' do
+ let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: assignee_user) }
+
+ before do
+ assignee.update!(state: :reviewed)
+ end
+
+ it 'returns success' do
+ expect(result[:status]).to eq :success
+ end
+
+ it 'updates assignees state' do
+ service.execute
+ assignee.reload
+
+ expect(assignee.state).to eq 'attention_requested'
+ end
+
+ it 'creates a new todo for the reviewer' do
+ expect(todo_service).to receive(:create_attention_requested_todo).with(merge_request, current_user, assignee_user)
+
+ service.execute
+ end
+ end
+
+ context 'assignee is the same as reviewer' do
+ let(:merge_request) { create(:merge_request, reviewers: [user], assignees: [user]) }
+ let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: user) }
+ let(:assignee) { merge_request.find_assignee(user) }
+
+ before do
+ reviewer.update!(state: :reviewed)
+ assignee.update!(state: :reviewed)
+ end
+
+ it 'updates reviewers and assignees state' do
+ service.execute
+ reviewer.reload
+ assignee.reload
+
+ expect(reviewer.state).to eq 'attention_requested'
+ expect(assignee.state).to eq 'attention_requested'
+ end
+ end
+
+ context 'state is attention_requested' do
+ before do
+ reviewer.update!(state: :attention_requested)
+ end
+
+ it 'toggles state to reviewed' do
+ service.execute
+ reviewer.reload
+
+ expect(reviewer.state).to eq "reviewed"
+ end
+
+ it 'does not create a new todo for the reviewer' do
+ expect(todo_service).not_to receive(:create_attention_requested_todo).with(merge_request, current_user, assignee_user)
+
+ service.execute
+ end
+ end
+ end
+end
diff --git a/spec/services/namespaces/in_product_marketing_email_records_spec.rb b/spec/services/namespaces/in_product_marketing_email_records_spec.rb
new file mode 100644
index 00000000000..e5f1b275f9c
--- /dev/null
+++ b/spec/services/namespaces/in_product_marketing_email_records_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Namespaces::InProductMarketingEmailRecords do
+ let_it_be(:user) { create :user }
+
+ subject(:records) { described_class.new }
+
+ it 'initializes records' do
+ expect(subject.records).to match_array []
+ end
+
+ describe '#save!' do
+ before do
+ allow(Users::InProductMarketingEmail).to receive(:bulk_insert!)
+
+ records.add(user, :invite_team, 0)
+ records.add(user, :create, 1)
+ end
+
+ it 'bulk inserts added records' do
+ expect(Users::InProductMarketingEmail).to receive(:bulk_insert!).with(records.records)
+ records.save!
+ end
+
+ it 'resets its records' do
+ records.save!
+ expect(records.records).to match_array []
+ end
+ end
+
+ describe '#add' do
+ it 'adds a Users::InProductMarketingEmail record to its records' do
+ freeze_time do
+ records.add(user, :invite_team, 0)
+ records.add(user, :create, 1)
+
+ first, second = records.records
+
+ expect(first).to be_a Users::InProductMarketingEmail
+ expect(first.track.to_sym).to eq :invite_team
+ expect(first.series).to eq 0
+ expect(first.created_at).to eq Time.zone.now
+ expect(first.updated_at).to eq Time.zone.now
+
+ expect(second).to be_a Users::InProductMarketingEmail
+ expect(second.track.to_sym).to eq :create
+ expect(second.series).to eq 1
+ expect(second.created_at).to eq Time.zone.now
+ expect(second.updated_at).to eq Time.zone.now
+ end
+ end
+ end
+end
diff --git a/spec/services/namespaces/invite_team_email_service_spec.rb b/spec/services/namespaces/invite_team_email_service_spec.rb
new file mode 100644
index 00000000000..60ba91f433d
--- /dev/null
+++ b/spec/services/namespaces/invite_team_email_service_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Namespaces::InviteTeamEmailService do
+ let_it_be(:user) { create(:user, email_opted_in: true) }
+
+ let(:track) { described_class::TRACK }
+ let(:series) { 0 }
+
+ let(:setup_for_company) { true }
+ let(:parent_group) { nil }
+ let(:group) { create(:group, parent: parent_group) }
+
+ subject(:action) { described_class.send_email(user, group) }
+
+ before do
+ group.add_owner(user)
+ allow(group).to receive(:setup_for_company).and_return(setup_for_company)
+ allow(Notify).to receive(:in_product_marketing_email).and_return(double(deliver_later: nil))
+ end
+
+ RSpec::Matchers.define :send_invite_team_email do |*args|
+ match do
+ expect(Notify).to have_received(:in_product_marketing_email).with(*args).once
+ end
+
+ match_when_negated do
+ expect(Notify).not_to have_received(:in_product_marketing_email)
+ end
+ end
+
+ shared_examples 'unexperimented' do
+ it { is_expected.not_to send_invite_team_email }
+
+ it 'does not record sent email' do
+ expect { subject }.not_to change { Users::InProductMarketingEmail.count }
+ end
+ end
+
+ shared_examples 'candidate' do
+ it { is_expected.to send_invite_team_email(user.id, group.id, track, 0) }
+
+ it 'records sent email' do
+ expect { subject }.to change { Users::InProductMarketingEmail.count }.by(1)
+
+ expect(
+ Users::InProductMarketingEmail.where(
+ user: user,
+ track: track,
+ series: 0
+ )
+ ).to exist
+ end
+
+ it_behaves_like 'tracks assignment and records the subject', :invite_team_email, :group do
+ subject { group }
+ end
+ end
+
+ context 'when group is in control path' do
+ before do
+ stub_experiments(invite_team_email: :control)
+ end
+
+ it { is_expected.not_to send_invite_team_email }
+
+ it 'does not record sent email' do
+ expect { subject }.not_to change { Users::InProductMarketingEmail.count }
+ end
+
+ it_behaves_like 'tracks assignment and records the subject', :invite_team_email, :group do
+ subject { group }
+ end
+ end
+
+ context 'when group is in candidate path' do
+ before do
+ stub_experiments(invite_team_email: :candidate)
+ end
+
+ it_behaves_like 'candidate'
+
+ context 'when the user has not opted into marketing emails' do
+ let(:user) { create(:user, email_opted_in: false ) }
+
+ it_behaves_like 'unexperimented'
+ end
+
+ context 'when group is not top level' do
+ it_behaves_like 'unexperimented' do
+ let(:parent_group) do
+ create(:group).tap { |g| g.add_owner(user) }
+ end
+ end
+ end
+
+ context 'when group is not set up for a company' do
+ it_behaves_like 'unexperimented' do
+ let(:setup_for_company) { nil }
+ end
+ end
+
+ context 'when other users have already been added to the group' do
+ before do
+ group.add_developer(create(:user))
+ end
+
+ it_behaves_like 'unexperimented'
+ end
+
+ context 'when other users have already been invited to the group' do
+ before do
+ group.add_developer('not_a_user_yet@example.com')
+ end
+
+ it_behaves_like 'unexperimented'
+ end
+
+ context 'when the user already got sent the email' do
+ before do
+ create(:in_product_marketing_email, user: user, track: track, series: 0)
+ end
+
+ it_behaves_like 'unexperimented'
+ end
+ end
+end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 48718cbc24a..fbf5b183365 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -3040,7 +3040,7 @@ RSpec.describe NotificationService, :mailer do
it 'emails only the creator' do
notification.pipeline_finished(pipeline)
- should_only_email(u_custom_notification_enabled, kind: :bcc)
+ should_only_email(u_custom_notification_enabled)
end
it_behaves_like 'project emails are disabled' do
@@ -3063,7 +3063,7 @@ RSpec.describe NotificationService, :mailer do
it 'sends to group notification email' do
notification.pipeline_finished(pipeline)
- expect(email_recipients(kind: :bcc).first).to eq(group_notification_email)
+ expect(email_recipients.first).to eq(group_notification_email)
end
end
end
@@ -3076,7 +3076,7 @@ RSpec.describe NotificationService, :mailer do
it 'emails only the creator' do
notification.pipeline_finished(pipeline)
- should_only_email(u_member, kind: :bcc)
+ should_only_email(u_member)
end
it_behaves_like 'project emails are disabled' do
@@ -3098,7 +3098,7 @@ RSpec.describe NotificationService, :mailer do
it 'sends to group notification email' do
notification.pipeline_finished(pipeline)
- expect(email_recipients(kind: :bcc).first).to eq(group_notification_email)
+ expect(email_recipients.first).to eq(group_notification_email)
end
end
end
@@ -3110,7 +3110,7 @@ RSpec.describe NotificationService, :mailer do
end
it 'emails only the creator' do
- should_only_email(u_watcher, kind: :bcc)
+ should_only_email(u_watcher)
end
end
@@ -3121,7 +3121,7 @@ RSpec.describe NotificationService, :mailer do
end
it 'emails only the creator' do
- should_only_email(u_custom_notification_unset, kind: :bcc)
+ should_only_email(u_custom_notification_unset)
end
end
@@ -3143,7 +3143,7 @@ RSpec.describe NotificationService, :mailer do
end
it 'emails only the creator' do
- should_only_email(u_custom_notification_enabled, kind: :bcc)
+ should_only_email(u_custom_notification_enabled)
end
end
@@ -3170,7 +3170,7 @@ RSpec.describe NotificationService, :mailer do
it 'emails only the creator' do
notification.pipeline_finished(pipeline, ref_status: ref_status)
- should_only_email(u_member, kind: :bcc)
+ should_only_email(u_member)
end
it_behaves_like 'project emails are disabled' do
@@ -3192,7 +3192,7 @@ RSpec.describe NotificationService, :mailer do
it 'sends to group notification email' do
notification.pipeline_finished(pipeline, ref_status: ref_status)
- expect(email_recipients(kind: :bcc).first).to eq(group_notification_email)
+ expect(email_recipients.first).to eq(group_notification_email)
end
end
end
@@ -3204,7 +3204,7 @@ RSpec.describe NotificationService, :mailer do
end
it 'emails only the creator' do
- should_only_email(u_watcher, kind: :bcc)
+ should_only_email(u_watcher)
end
end
@@ -3215,7 +3215,7 @@ RSpec.describe NotificationService, :mailer do
end
it 'emails only the creator' do
- should_only_email(u_custom_notification_unset, kind: :bcc)
+ should_only_email(u_custom_notification_unset)
end
end
@@ -3236,7 +3236,7 @@ RSpec.describe NotificationService, :mailer do
notification.pipeline_finished(pipeline, ref_status: ref_status)
- should_only_email(u_custom_notification_enabled, kind: :bcc)
+ should_only_email(u_custom_notification_enabled)
end
end
end
diff --git a/spec/services/packages/create_dependency_service_spec.rb b/spec/services/packages/create_dependency_service_spec.rb
index 261c6b395d5..55414ea68fe 100644
--- a/spec/services/packages/create_dependency_service_spec.rb
+++ b/spec/services/packages/create_dependency_service_spec.rb
@@ -58,9 +58,9 @@ RSpec.describe Packages::CreateDependencyService do
let_it_be(:rows) { [{ name: 'express', version_pattern: '^4.16.4' }] }
it 'creates dependences and links' do
- original_bulk_insert = ::Gitlab::Database.main.method(:bulk_insert)
- expect(::Gitlab::Database.main)
- .to receive(:bulk_insert) do |table, rows, return_ids: false, disable_quote: [], on_conflict: nil|
+ original_bulk_insert = ::ApplicationRecord.method(:legacy_bulk_insert)
+ expect(::ApplicationRecord)
+ .to receive(:legacy_bulk_insert) do |table, rows, return_ids: false, disable_quote: [], on_conflict: nil|
call_count = table == Packages::Dependency.table_name ? 2 : 1
call_count.times { original_bulk_insert.call(table, rows, return_ids: return_ids, disable_quote: disable_quote, on_conflict: on_conflict) }
end.twice
diff --git a/spec/services/packages/npm/create_package_service_spec.rb b/spec/services/packages/npm/create_package_service_spec.rb
index ba5729eaf59..b1beb2adb3b 100644
--- a/spec/services/packages/npm/create_package_service_spec.rb
+++ b/spec/services/packages/npm/create_package_service_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe Packages::Npm::CreatePackageService do
let(:override) { {} }
let(:package_name) { "@#{namespace.path}/my-app" }
+ let(:version_data) { params.dig('versions', '1.0.1') }
subject { described_class.new(project, user, params).execute }
@@ -25,6 +26,7 @@ RSpec.describe Packages::Npm::CreatePackageService do
.to change { Packages::Package.count }.by(1)
.and change { Packages::Package.npm.count }.by(1)
.and change { Packages::Tag.count }.by(1)
+ .and change { Packages::Npm::Metadatum.count }.by(1)
end
it_behaves_like 'assigns the package creator' do
@@ -40,6 +42,8 @@ RSpec.describe Packages::Npm::CreatePackageService do
expect(package.version).to eq(version)
end
+ it { expect(subject.npm_metadatum.package_json).to eq(version_data) }
+
it { expect(subject.name).to eq(package_name) }
it { expect(subject.version).to eq(version) }
@@ -54,6 +58,48 @@ RSpec.describe Packages::Npm::CreatePackageService do
expect { subject }.to change { Packages::PackageFileBuildInfo.count }.by(1)
end
end
+
+ context 'with a too large metadata structure' do
+ before do
+ params[:versions][version][:test] = 'test' * 10000
+ end
+
+ it 'does not create the package' do
+ expect { subject }.to raise_error(ActiveRecord::RecordInvalid, 'Validation failed: Package json structure is too large')
+ .and not_change { Packages::Package.count }
+ .and not_change { Packages::Package.npm.count }
+ .and not_change { Packages::Tag.count }
+ .and not_change { Packages::Npm::Metadatum.count }
+ end
+ end
+
+ described_class::PACKAGE_JSON_NOT_ALLOWED_FIELDS.each do |field|
+ context "with not allowed #{field} field" do
+ before do
+ params[:versions][version][field] = 'test'
+ end
+
+ it 'is persisted without the field' do
+ expect { subject }
+ .to change { Packages::Package.count }.by(1)
+ .and change { Packages::Package.npm.count }.by(1)
+ .and change { Packages::Tag.count }.by(1)
+ .and change { Packages::Npm::Metadatum.count }.by(1)
+ expect(subject.npm_metadatum.package_json[field]).to be_blank
+ end
+ end
+ end
+
+ context 'with packages_npm_abbreviated_metadata disabled' do
+ before do
+ stub_feature_flags(packages_npm_abbreviated_metadata: false)
+ end
+
+ it 'creates a package without metadatum' do
+ expect { subject }
+ .not_to change { Packages::Npm::Metadatum.count }
+ end
+ end
end
describe '#execute' do
diff --git a/spec/services/packages/update_tags_service_spec.rb b/spec/services/packages/update_tags_service_spec.rb
index 6e67489fec9..c4256699c94 100644
--- a/spec/services/packages/update_tags_service_spec.rb
+++ b/spec/services/packages/update_tags_service_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe Packages::UpdateTagsService do
it 'is a no op' do
expect(package).not_to receive(:tags)
- expect(::Gitlab::Database.main).not_to receive(:bulk_insert)
+ expect(::ApplicationRecord).not_to receive(:legacy_bulk_insert)
subject
end
diff --git a/spec/services/projects/all_issues_count_service_spec.rb b/spec/services/projects/all_issues_count_service_spec.rb
new file mode 100644
index 00000000000..d7e35991940
--- /dev/null
+++ b/spec/services/projects/all_issues_count_service_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::AllIssuesCountService, :use_clean_rails_memory_store_caching do
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:project) { create(:project, :public, namespace: group) }
+ let_it_be(:banned_user) { create(:user, :banned) }
+
+ subject { described_class.new(project) }
+
+ it_behaves_like 'a counter caching service'
+
+ describe '#count' do
+ it 'returns the number of all issues' do
+ create(:issue, :opened, project: project)
+ create(:issue, :opened, confidential: true, project: project)
+ create(:issue, :opened, author: banned_user, project: project)
+ create(:issue, :closed, project: project)
+
+ expect(subject.count).to eq(4)
+ end
+ end
+end
diff --git a/spec/services/projects/all_merge_requests_count_service_spec.rb b/spec/services/projects/all_merge_requests_count_service_spec.rb
new file mode 100644
index 00000000000..13954d688aa
--- /dev/null
+++ b/spec/services/projects/all_merge_requests_count_service_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::AllMergeRequestsCountService, :use_clean_rails_memory_store_caching do
+ let_it_be(:project) { create(:project) }
+
+ subject { described_class.new(project) }
+
+ it_behaves_like 'a counter caching service'
+
+ describe '#count' do
+ it 'returns the number of all merge requests' do
+ create(:merge_request,
+ :opened,
+ source_project: project,
+ target_project: project)
+ create(:merge_request,
+ :closed,
+ source_project: project,
+ target_project: project)
+ create(:merge_request,
+ :merged,
+ source_project: project,
+ target_project: project)
+
+ expect(subject.count).to eq(3)
+ end
+ end
+end
diff --git a/spec/services/projects/container_repository/cache_tags_created_at_service_spec.rb b/spec/services/projects/container_repository/cache_tags_created_at_service_spec.rb
deleted file mode 100644
index dfe2ff9e57c..00000000000
--- a/spec/services/projects/container_repository/cache_tags_created_at_service_spec.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ::Projects::ContainerRepository::CacheTagsCreatedAtService, :clean_gitlab_redis_cache do
- let_it_be(:dummy_tag_class) { Struct.new(:name, :created_at) }
- let_it_be(:repository) { create(:container_repository) }
-
- let(:tags) { create_tags(5) }
- let(:service) { described_class.new(repository) }
-
- shared_examples 'not interacting with redis' do
- it 'does not interact with redis' do
- expect(::Gitlab::Redis::Cache).not_to receive(:with)
-
- subject
- end
- end
-
- describe '#populate' do
- subject { service.populate(tags) }
-
- context 'with tags' do
- it 'gets values from redis' do
- expect(::Gitlab::Redis::Cache).to receive(:with).and_call_original
-
- expect(subject).to eq(0)
-
- tags.each { |t| expect(t.created_at).to eq(nil) }
- end
-
- context 'with cached values' do
- let(:cached_tags) { tags.first(2) }
-
- before do
- ::Gitlab::Redis::Cache.with do |redis|
- cached_tags.each do |tag|
- redis.set(cache_key(tag), rfc3339(10.days.ago))
- end
- end
- end
-
- it 'gets values from redis' do
- expect(::Gitlab::Redis::Cache).to receive(:with).and_call_original
-
- expect(subject).to eq(2)
-
- cached_tags.each { |t| expect(t.created_at).not_to eq(nil) }
- (tags - cached_tags).each { |t| expect(t.created_at).to eq(nil) }
- end
- end
- end
-
- context 'with no tags' do
- let(:tags) { [] }
-
- it_behaves_like 'not interacting with redis'
- end
- end
-
- describe '#insert' do
- let(:max_ttl) { 90.days }
-
- subject { service.insert(tags, max_ttl) }
-
- context 'with tags' do
- let(:tag) { tags.first }
- let(:ttl) { 90.days - 3.days }
-
- before do
- travel_to(Time.zone.local(2021, 9, 2, 12, 0, 0))
-
- tag.created_at = DateTime.rfc3339(3.days.ago.rfc3339)
- end
-
- after do
- travel_back
- end
-
- it 'inserts values in redis' do
- ::Gitlab::Redis::Cache.with do |redis|
- expect(redis)
- .to receive(:set)
- .with(cache_key(tag), rfc3339(tag.created_at), ex: ttl.to_i)
- .and_call_original
- end
-
- subject
- end
-
- context 'with some of them already cached' do
- let(:tag) { tags.first }
-
- before do
- ::Gitlab::Redis::Cache.with do |redis|
- redis.set(cache_key(tag), rfc3339(10.days.ago))
- end
- service.populate(tags)
- end
-
- it_behaves_like 'not interacting with redis'
- end
- end
-
- context 'with no tags' do
- let(:tags) { [] }
-
- it_behaves_like 'not interacting with redis'
- end
-
- context 'with no expires_in' do
- let(:max_ttl) { nil }
-
- it_behaves_like 'not interacting with redis'
- end
- end
-
- def create_tags(size)
- Array.new(size) do |i|
- dummy_tag_class.new("Tag #{i}", nil)
- end
- end
-
- def cache_key(tag)
- "container_repository:{#{repository.id}}:tag:#{tag.name}:created_at"
- end
-
- def rfc3339(date_time)
- # DateTime rfc3339 is different ActiveSupport::TimeWithZone rfc3339
- # The caching will use DateTime rfc3339
- DateTime.rfc3339(date_time.rfc3339).rfc3339
- end
-end
diff --git a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
index 289bbf4540e..a41ba8216cc 100644
--- a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
@@ -41,322 +41,320 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService, :clean_gitlab_
describe '#execute' do
subject { service.execute }
- shared_examples 'reading and removing tags' do |caching_enabled: true|
- context 'when no params are specified' do
- let(:params) { {} }
+ context 'when no params are specified' do
+ let(:params) { {} }
- it 'does not remove anything' do
- expect_any_instance_of(Projects::ContainerRepository::DeleteTagsService)
- .not_to receive(:execute)
- expect_no_caching
+ it 'does not remove anything' do
+ expect_any_instance_of(Projects::ContainerRepository::DeleteTagsService)
+ .not_to receive(:execute)
+ expect_no_caching
- is_expected.to eq(expected_service_response(before_truncate_size: 0, after_truncate_size: 0, before_delete_size: 0))
- end
+ is_expected.to eq(expected_service_response(before_truncate_size: 0, after_truncate_size: 0, before_delete_size: 0))
end
+ end
- context 'when regex matching everything is specified' do
- shared_examples 'removes all matches' do
- it 'does remove all tags except latest' do
- expect_no_caching
+ context 'when regex matching everything is specified' do
+ shared_examples 'removes all matches' do
+ it 'does remove all tags except latest' do
+ expect_no_caching
- expect_delete(%w(A Ba Bb C D E))
+ expect_delete(%w(A Ba Bb C D E))
- is_expected.to eq(expected_service_response(deleted: %w(A Ba Bb C D E)))
- end
+ is_expected.to eq(expected_service_response(deleted: %w(A Ba Bb C D E)))
end
+ end
+
+ let(:params) do
+ { 'name_regex_delete' => '.*' }
+ end
+ it_behaves_like 'removes all matches'
+
+ context 'with deprecated name_regex param' do
let(:params) do
- { 'name_regex_delete' => '.*' }
+ { 'name_regex' => '.*' }
end
it_behaves_like 'removes all matches'
+ end
+ end
- context 'with deprecated name_regex param' do
- let(:params) do
- { 'name_regex' => '.*' }
- end
+ context 'with invalid regular expressions' do
+ shared_examples 'handling an invalid regex' do
+ it 'keeps all tags' do
+ expect_no_caching
- it_behaves_like 'removes all matches'
+ expect(Projects::ContainerRepository::DeleteTagsService)
+ .not_to receive(:new)
+
+ subject
end
- end
- context 'with invalid regular expressions' do
- shared_examples 'handling an invalid regex' do
- it 'keeps all tags' do
- expect_no_caching
+ it { is_expected.to eq(status: :error, message: 'invalid regex') }
- expect(Projects::ContainerRepository::DeleteTagsService)
- .not_to receive(:new)
+ it 'calls error tracking service' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).and_call_original
- subject
- end
+ subject
+ end
+ end
- it { is_expected.to eq(status: :error, message: 'invalid regex') }
+ context 'when name_regex_delete is invalid' do
+ let(:params) { { 'name_regex_delete' => '*test*' } }
- it 'calls error tracking service' do
- expect(Gitlab::ErrorTracking).to receive(:log_exception).and_call_original
+ it_behaves_like 'handling an invalid regex'
+ end
- subject
- end
- end
+ context 'when name_regex is invalid' do
+ let(:params) { { 'name_regex' => '*test*' } }
- context 'when name_regex_delete is invalid' do
- let(:params) { { 'name_regex_delete' => '*test*' } }
+ it_behaves_like 'handling an invalid regex'
+ end
- it_behaves_like 'handling an invalid regex'
- end
+ context 'when name_regex_keep is invalid' do
+ let(:params) { { 'name_regex_keep' => '*test*' } }
- context 'when name_regex is invalid' do
- let(:params) { { 'name_regex' => '*test*' } }
+ it_behaves_like 'handling an invalid regex'
+ end
+ end
- it_behaves_like 'handling an invalid regex'
- end
+ context 'when delete regex matching specific tags is used' do
+ let(:params) do
+ { 'name_regex_delete' => 'C|D' }
+ end
- context 'when name_regex_keep is invalid' do
- let(:params) { { 'name_regex_keep' => '*test*' } }
+ it 'does remove C and D' do
+ expect_delete(%w(C D))
- it_behaves_like 'handling an invalid regex'
- end
+ expect_no_caching
+
+ is_expected.to eq(expected_service_response(deleted: %w(C D), before_truncate_size: 2, after_truncate_size: 2, before_delete_size: 2))
end
- context 'when delete regex matching specific tags is used' do
+ context 'with overriding allow regex' do
let(:params) do
- { 'name_regex_delete' => 'C|D' }
+ { 'name_regex_delete' => 'C|D',
+ 'name_regex_keep' => 'C' }
end
- it 'does remove C and D' do
- expect_delete(%w(C D))
+ it 'does not remove C' do
+ expect_delete(%w(D))
expect_no_caching
- is_expected.to eq(expected_service_response(deleted: %w(C D), before_truncate_size: 2, after_truncate_size: 2, before_delete_size: 2))
+ is_expected.to eq(expected_service_response(deleted: %w(D), before_truncate_size: 1, after_truncate_size: 1, before_delete_size: 1))
end
+ end
- context 'with overriding allow regex' do
- let(:params) do
- { 'name_regex_delete' => 'C|D',
- 'name_regex_keep' => 'C' }
- end
+ context 'with name_regex_delete overriding deprecated name_regex' do
+ let(:params) do
+ { 'name_regex' => 'C|D',
+ 'name_regex_delete' => 'D' }
+ end
- it 'does not remove C' do
- expect_delete(%w(D))
+ it 'does not remove C' do
+ expect_delete(%w(D))
- expect_no_caching
+ expect_no_caching
- is_expected.to eq(expected_service_response(deleted: %w(D), before_truncate_size: 1, after_truncate_size: 1, before_delete_size: 1))
- end
+ is_expected.to eq(expected_service_response(deleted: %w(D), before_truncate_size: 1, after_truncate_size: 1, before_delete_size: 1))
end
+ end
+ end
- context 'with name_regex_delete overriding deprecated name_regex' do
- let(:params) do
- { 'name_regex' => 'C|D',
- 'name_regex_delete' => 'D' }
- end
+ context 'with allow regex value' do
+ let(:params) do
+ { 'name_regex_delete' => '.*',
+ 'name_regex_keep' => 'B.*' }
+ end
- it 'does not remove C' do
- expect_delete(%w(D))
+ it 'does not remove B*' do
+ expect_delete(%w(A C D E))
- expect_no_caching
+ expect_no_caching
- is_expected.to eq(expected_service_response(deleted: %w(D), before_truncate_size: 1, after_truncate_size: 1, before_delete_size: 1))
- end
- end
+ is_expected.to eq(expected_service_response(deleted: %w(A C D E), before_truncate_size: 4, after_truncate_size: 4, before_delete_size: 4))
+ end
+ end
+
+ context 'when keeping only N tags' do
+ let(:params) do
+ { 'name_regex' => 'A|B.*|C',
+ 'keep_n' => 1 }
end
- context 'with allow regex value' do
- let(:params) do
- { 'name_regex_delete' => '.*',
- 'name_regex_keep' => 'B.*' }
- end
+ it 'sorts tags by date' do
+ expect_delete(%w(Bb Ba C))
- it 'does not remove B*' do
- expect_delete(%w(A C D E))
+ expect_no_caching
- expect_no_caching
+ expect(service).to receive(:order_by_date).and_call_original
- is_expected.to eq(expected_service_response(deleted: %w(A C D E), before_truncate_size: 4, after_truncate_size: 4, before_delete_size: 4))
- end
+ is_expected.to eq(expected_service_response(deleted: %w(Bb Ba C), before_truncate_size: 4, after_truncate_size: 4, before_delete_size: 3))
end
+ end
- context 'when keeping only N tags' do
- let(:params) do
- { 'name_regex' => 'A|B.*|C',
- 'keep_n' => 1 }
- end
+ context 'when not keeping N tags' do
+ let(:params) do
+ { 'name_regex' => 'A|B.*|C' }
+ end
- it 'sorts tags by date' do
- expect_delete(%w(Bb Ba C))
+ it 'does not sort tags by date' do
+ expect_delete(%w(A Ba Bb C))
- expect_no_caching
+ expect_no_caching
- expect(service).to receive(:order_by_date).and_call_original
+ expect(service).not_to receive(:order_by_date)
- is_expected.to eq(expected_service_response(deleted: %w(Bb Ba C), before_truncate_size: 4, after_truncate_size: 4, before_delete_size: 3))
- end
+ is_expected.to eq(expected_service_response(deleted: %w(A Ba Bb C), before_truncate_size: 4, after_truncate_size: 4, before_delete_size: 4))
end
+ end
- context 'when not keeping N tags' do
- let(:params) do
- { 'name_regex' => 'A|B.*|C' }
- end
-
- it 'does not sort tags by date' do
- expect_delete(%w(A Ba Bb C))
+ context 'when removing keeping only 3' do
+ let(:params) do
+ { 'name_regex_delete' => '.*',
+ 'keep_n' => 3 }
+ end
- expect_no_caching
+ it 'does remove B* and C as they are the oldest' do
+ expect_delete(%w(Bb Ba C))
- expect(service).not_to receive(:order_by_date)
+ expect_no_caching
- is_expected.to eq(expected_service_response(deleted: %w(A Ba Bb C), before_truncate_size: 4, after_truncate_size: 4, before_delete_size: 4))
- end
+ is_expected.to eq(expected_service_response(deleted: %w(Bb Ba C), before_delete_size: 3))
end
+ end
- context 'when removing keeping only 3' do
- let(:params) do
- { 'name_regex_delete' => '.*',
- 'keep_n' => 3 }
- end
+ context 'when removing older than 1 day' do
+ let(:params) do
+ { 'name_regex_delete' => '.*',
+ 'older_than' => '1 day' }
+ end
- it 'does remove B* and C as they are the oldest' do
- expect_delete(%w(Bb Ba C))
+ it 'does remove B* and C as they are older than 1 day' do
+ expect_delete(%w(Ba Bb C))
- expect_no_caching
+ expect_no_caching
- is_expected.to eq(expected_service_response(deleted: %w(Bb Ba C), before_delete_size: 3))
- end
+ is_expected.to eq(expected_service_response(deleted: %w(Ba Bb C), before_delete_size: 3))
end
+ end
- context 'when removing older than 1 day' do
- let(:params) do
- { 'name_regex_delete' => '.*',
- 'older_than' => '1 day' }
- end
+ context 'when combining all parameters' do
+ let(:params) do
+ { 'name_regex_delete' => '.*',
+ 'keep_n' => 1,
+ 'older_than' => '1 day' }
+ end
- it 'does remove B* and C as they are older than 1 day' do
- expect_delete(%w(Ba Bb C))
+ it 'does remove B* and C' do
+ expect_delete(%w(Bb Ba C))
- expect_no_caching
+ expect_no_caching
- is_expected.to eq(expected_service_response(deleted: %w(Ba Bb C), before_delete_size: 3))
- end
+ is_expected.to eq(expected_service_response(deleted: %w(Bb Ba C), before_delete_size: 3))
end
+ end
+
+ context 'when running a container_expiration_policy' do
+ let(:user) { nil }
- context 'when combining all parameters' do
+ context 'with valid container_expiration_policy param' do
let(:params) do
{ 'name_regex_delete' => '.*',
'keep_n' => 1,
- 'older_than' => '1 day' }
+ 'older_than' => '1 day',
+ 'container_expiration_policy' => true }
end
- it 'does remove B* and C' do
- expect_delete(%w(Bb Ba C))
+ it 'succeeds without a user' do
+ expect_delete(%w(Bb Ba C), container_expiration_policy: true)
- expect_no_caching
+ expect_caching
is_expected.to eq(expected_service_response(deleted: %w(Bb Ba C), before_delete_size: 3))
end
end
- context 'when running a container_expiration_policy' do
- let(:user) { nil }
-
- context 'with valid container_expiration_policy param' do
- let(:params) do
- { 'name_regex_delete' => '.*',
- 'keep_n' => 1,
- 'older_than' => '1 day',
- 'container_expiration_policy' => true }
- end
-
- it 'succeeds without a user' do
- expect_delete(%w(Bb Ba C), container_expiration_policy: true)
-
- caching_enabled ? expect_caching : expect_no_caching
-
- is_expected.to eq(expected_service_response(deleted: %w(Bb Ba C), before_delete_size: 3))
- end
+ context 'without container_expiration_policy param' do
+ let(:params) do
+ { 'name_regex_delete' => '.*',
+ 'keep_n' => 1,
+ 'older_than' => '1 day' }
end
- context 'without container_expiration_policy param' do
- let(:params) do
- { 'name_regex_delete' => '.*',
- 'keep_n' => 1,
- 'older_than' => '1 day' }
- end
-
- it 'fails' do
- is_expected.to eq(status: :error, message: 'access denied')
- end
+ it 'fails' do
+ is_expected.to eq(status: :error, message: 'access denied')
end
end
+ end
- context 'truncating the tags list' do
- let(:params) do
- {
- 'name_regex_delete' => '.*',
- 'keep_n' => 1
- }
- end
+ context 'truncating the tags list' do
+ let(:params) do
+ {
+ 'name_regex_delete' => '.*',
+ 'keep_n' => 1
+ }
+ end
- shared_examples 'returning the response' do |status:, original_size:, before_truncate_size:, after_truncate_size:, before_delete_size:|
- it 'returns the response' do
- expect_no_caching
+ shared_examples 'returning the response' do |status:, original_size:, before_truncate_size:, after_truncate_size:, before_delete_size:|
+ it 'returns the response' do
+ expect_no_caching
- result = subject
+ result = subject
- service_response = expected_service_response(
- status: status,
- original_size: original_size,
- before_truncate_size: before_truncate_size,
- after_truncate_size: after_truncate_size,
- before_delete_size: before_delete_size,
- deleted: nil
- )
+ service_response = expected_service_response(
+ status: status,
+ original_size: original_size,
+ before_truncate_size: before_truncate_size,
+ after_truncate_size: after_truncate_size,
+ before_delete_size: before_delete_size,
+ deleted: nil
+ )
- expect(result).to eq(service_response)
- end
+ expect(result).to eq(service_response)
end
+ end
- where(:feature_flag_enabled, :max_list_size, :delete_tags_service_status, :expected_status, :expected_truncated) do
- false | 10 | :success | :success | false
- false | 10 | :error | :error | false
- false | 3 | :success | :success | false
- false | 3 | :error | :error | false
- false | 0 | :success | :success | false
- false | 0 | :error | :error | false
- true | 10 | :success | :success | false
- true | 10 | :error | :error | false
- true | 3 | :success | :error | true
- true | 3 | :error | :error | true
- true | 0 | :success | :success | false
- true | 0 | :error | :error | false
- end
+ where(:feature_flag_enabled, :max_list_size, :delete_tags_service_status, :expected_status, :expected_truncated) do
+ false | 10 | :success | :success | false
+ false | 10 | :error | :error | false
+ false | 3 | :success | :success | false
+ false | 3 | :error | :error | false
+ false | 0 | :success | :success | false
+ false | 0 | :error | :error | false
+ true | 10 | :success | :success | false
+ true | 10 | :error | :error | false
+ true | 3 | :success | :error | true
+ true | 3 | :error | :error | true
+ true | 0 | :success | :success | false
+ true | 0 | :error | :error | false
+ end
- with_them do
- before do
- stub_feature_flags(container_registry_expiration_policies_throttling: feature_flag_enabled)
- stub_application_setting(container_registry_cleanup_tags_service_max_list_size: max_list_size)
- allow_next_instance_of(Projects::ContainerRepository::DeleteTagsService) do |service|
- expect(service).to receive(:execute).and_return(status: delete_tags_service_status)
- end
+ with_them do
+ before do
+ stub_feature_flags(container_registry_expiration_policies_throttling: feature_flag_enabled)
+ stub_application_setting(container_registry_cleanup_tags_service_max_list_size: max_list_size)
+ allow_next_instance_of(Projects::ContainerRepository::DeleteTagsService) do |service|
+ expect(service).to receive(:execute).and_return(status: delete_tags_service_status)
end
+ end
- original_size = 7
- keep_n = 1
+ original_size = 7
+ keep_n = 1
- it_behaves_like(
- 'returning the response',
- status: params[:expected_status],
- original_size: original_size,
- before_truncate_size: original_size - keep_n,
- after_truncate_size: params[:expected_truncated] ? params[:max_list_size] + keep_n : original_size - keep_n,
- before_delete_size: params[:expected_truncated] ? params[:max_list_size] : original_size - keep_n - 1 # one tag is filtered out with older_than filter
- )
- end
+ it_behaves_like(
+ 'returning the response',
+ status: params[:expected_status],
+ original_size: original_size,
+ before_truncate_size: original_size - keep_n,
+ after_truncate_size: params[:expected_truncated] ? params[:max_list_size] + keep_n : original_size - keep_n,
+ before_delete_size: params[:expected_truncated] ? params[:max_list_size] : original_size - keep_n - 1 # one tag is filtered out with older_than filter
+ )
end
end
- context 'caching' do
+ context 'caching', :freeze_time do
let(:params) do
{
'name_regex_delete' => '.*',
@@ -381,17 +379,12 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService, :clean_gitlab_
before do
expect_delete(%w(Bb Ba C), container_expiration_policy: true)
- travel_to(Time.zone.local(2021, 9, 2, 12, 0, 0))
# We froze time so we need to set the created_at stubs again
stub_digest_config('sha256:configA', 1.hour.ago)
stub_digest_config('sha256:configB', 5.days.ago)
stub_digest_config('sha256:configC', 1.month.ago)
end
- after do
- travel_back
- end
-
it 'caches the created_at values' do
::Gitlab::Redis::Cache.with do |redis|
expect_mget(redis, tags_and_created_ats.keys)
@@ -450,32 +443,6 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService, :clean_gitlab_
DateTime.rfc3339(date_time.rfc3339).rfc3339
end
end
-
- context 'with container_registry_expiration_policies_caching enabled for the project' do
- before do
- stub_feature_flags(container_registry_expiration_policies_caching: project)
- end
-
- it_behaves_like 'reading and removing tags', caching_enabled: true
- end
-
- context 'with container_registry_expiration_policies_caching disabled' do
- before do
- stub_feature_flags(container_registry_expiration_policies_caching: false)
- end
-
- it_behaves_like 'reading and removing tags', caching_enabled: false
- end
-
- context 'with container_registry_expiration_policies_caching not enabled for the project' do
- let_it_be(:another_project) { create(:project) }
-
- before do
- stub_feature_flags(container_registry_expiration_policies_caching: another_project)
- end
-
- it_behaves_like 'reading and removing tags', caching_enabled: false
- end
end
private
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index d7c43ac676e..2aa9be5066f 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -49,6 +49,7 @@ RSpec.describe Projects::CreateService, '#execute' do
it 'keeps them as specified' do
expect(project.name).to eq('one')
expect(project.path).to eq('two')
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
@@ -58,6 +59,7 @@ RSpec.describe Projects::CreateService, '#execute' do
it 'sets name == path' do
expect(project.path).to eq('one.two_three-four')
expect(project.name).to eq(project.path)
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
@@ -67,6 +69,7 @@ RSpec.describe Projects::CreateService, '#execute' do
it 'sets path == name' do
expect(project.name).to eq('one.two_three-four')
expect(project.path).to eq(project.name)
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
@@ -78,6 +81,7 @@ RSpec.describe Projects::CreateService, '#execute' do
it 'parameterizes the name' do
expect(project.name).to eq('one.two_three-four and five')
expect(project.path).to eq('one-two_three-four-and-five')
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
end
@@ -111,13 +115,14 @@ RSpec.describe Projects::CreateService, '#execute' do
end
context 'user namespace' do
- it do
+ it 'creates a project in user namespace' do
project = create_project(user, opts)
expect(project).to be_valid
expect(project.owner).to eq(user)
expect(project.team.maintainers).to include(user)
expect(project.namespace).to eq(user.namespace)
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
@@ -151,6 +156,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project.owner).to eq(user)
expect(project.team.maintainers).to contain_exactly(user)
expect(project.namespace).to eq(user.namespace)
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
@@ -160,6 +166,7 @@ RSpec.describe Projects::CreateService, '#execute' do
project = create_project(admin, opts)
expect(project).not_to be_persisted
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
end
@@ -183,6 +190,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project.namespace).to eq(group)
expect(project.team.owners).to include(user)
expect(user.authorized_projects).to include(project)
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
@@ -339,6 +347,7 @@ RSpec.describe Projects::CreateService, '#execute' do
end
imported_project
+ expect(imported_project.project_namespace).to be_in_sync_with_project(imported_project)
end
it 'stores import data and URL' do
@@ -406,6 +415,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project.visibility_level).to eq(project_level)
expect(project).to be_saved
expect(project).to be_valid
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
end
@@ -424,6 +434,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project.errors.messages[:visibility_level].first).to(
match('restricted by your GitLab administrator')
)
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
it 'does not allow a restricted visibility level for admins when admin mode is disabled' do
@@ -493,6 +504,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project).to be_valid
expect(project.owner).to eq(user)
expect(project.namespace).to eq(user.namespace)
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
context 'when another repository already exists on disk' do
@@ -522,6 +534,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project).to respond_to(:errors)
expect(project.errors.messages).to have_key(:base)
expect(project.errors.messages[:base].first).to match('There is already a repository with that name on disk')
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
it 'does not allow to import project when path matches existing repository on disk' do
@@ -531,6 +544,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project).to respond_to(:errors)
expect(project.errors.messages).to have_key(:base)
expect(project.errors.messages[:base].first).to match('There is already a repository with that name on disk')
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
@@ -555,6 +569,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project).to respond_to(:errors)
expect(project.errors.messages).to have_key(:base)
expect(project.errors.messages[:base].first).to match('There is already a repository with that name on disk')
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
end
@@ -651,7 +666,7 @@ RSpec.describe Projects::CreateService, '#execute' do
end
context 'with an active group-level integration' do
- let!(:group_integration) { create(:prometheus_integration, group: group, project: nil, api_url: 'https://prometheus.group.com/') }
+ let!(:group_integration) { create(:prometheus_integration, :group, group: group, api_url: 'https://prometheus.group.com/') }
let!(:group) do
create(:group).tap do |group|
group.add_owner(user)
@@ -672,7 +687,7 @@ RSpec.describe Projects::CreateService, '#execute' do
end
context 'with an active subgroup' do
- let!(:subgroup_integration) { create(:prometheus_integration, group: subgroup, project: nil, api_url: 'https://prometheus.subgroup.com/') }
+ let!(:subgroup_integration) { create(:prometheus_integration, :group, group: subgroup, api_url: 'https://prometheus.subgroup.com/') }
let!(:subgroup) do
create(:group, parent: group).tap do |subgroup|
subgroup.add_owner(user)
@@ -810,11 +825,11 @@ RSpec.describe Projects::CreateService, '#execute' do
).to be_truthy
end
- it 'schedules authorization update for users with access to group' do
+ it 'schedules authorization update for users with access to group', :sidekiq_inline do
expect(AuthorizedProjectsWorker).not_to(
receive(:bulk_perform_async)
)
- expect(AuthorizedProjectUpdate::ProjectCreateWorker).to(
+ expect(AuthorizedProjectUpdate::ProjectRecalculateWorker).to(
receive(:perform_async).and_call_original
)
expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to(
@@ -825,7 +840,11 @@ RSpec.describe Projects::CreateService, '#execute' do
.and_call_original
)
- create_project(user, opts)
+ project = create_project(user, opts)
+
+ expect(
+ Ability.allowed?(other_user, :developer_access, project)
+ ).to be_truthy
end
end
@@ -866,6 +885,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project).to be_valid
expect(project.shared_runners_enabled).to eq(expected_result_for_project)
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
end
@@ -886,6 +906,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project).to be_valid
expect(project.shared_runners_enabled).to eq(expected_result_for_project)
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
end
@@ -903,6 +924,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project.persisted?).to eq(false)
expect(project).to be_invalid
expect(project.errors[:shared_runners_enabled]).to include('cannot be enabled because parent group does not allow it')
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
end
@@ -922,6 +944,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project).to be_valid
expect(project.shared_runners_enabled).to eq(expected_result)
+ expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
end
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index 9bdd9800fcc..ac84614121a 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -331,6 +331,14 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
end
end
end
+
+ context 'for an archived project' do
+ before do
+ project.update!(archived: true)
+ end
+
+ it_behaves_like 'deleting the project with pipeline and build'
+ end
end
describe 'container registry' do
diff --git a/spec/services/projects/import_export/export_service_spec.rb b/spec/services/projects/import_export/export_service_spec.rb
index 111c1264777..6002aaf427a 100644
--- a/spec/services/projects/import_export/export_service_spec.rb
+++ b/spec/services/projects/import_export/export_service_spec.rb
@@ -4,7 +4,8 @@ require 'spec_helper'
RSpec.describe Projects::ImportExport::ExportService do
describe '#execute' do
- let!(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
+
let(:project) { create(:project) }
let(:shared) { project.import_export_shared }
let!(:after_export_strategy) { Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy.new }
@@ -28,7 +29,14 @@ RSpec.describe Projects::ImportExport::ExportService do
end
it 'saves the models' do
- expect(Gitlab::ImportExport::Project::TreeSaver).to receive(:new).and_call_original
+ saver_params = {
+ project: project,
+ current_user: user,
+ shared: shared,
+ params: {},
+ logger: an_instance_of(Gitlab::Export::Logger)
+ }
+ expect(Gitlab::ImportExport::Project::TreeSaver).to receive(:new).with(saver_params).and_call_original
service.execute
end
diff --git a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
index f9ff959fa05..04c6349bf52 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
@@ -102,6 +102,7 @@ RSpec.describe Projects::LfsPointers::LfsDownloadService do
it 'skips read_total_timeout', :aggregate_failures do
stub_const('GitLab::HTTP::DEFAULT_READ_TOTAL_TIMEOUT', 0)
+ expect(ProjectCacheWorker).to receive(:perform_async).once
expect(Gitlab::Metrics::System).not_to receive(:monotonic_time)
expect(subject.execute).to include(status: :success)
end
diff --git a/spec/services/projects/participants_service_spec.rb b/spec/services/projects/participants_service_spec.rb
index eab7228307a..61edfd23700 100644
--- a/spec/services/projects/participants_service_spec.rb
+++ b/spec/services/projects/participants_service_spec.rb
@@ -207,13 +207,5 @@ RSpec.describe Projects::ParticipantsService do
end
it_behaves_like 'return project members'
-
- context 'when feature flag :linear_participants_service_ancestor_scopes is disabled' do
- before do
- stub_feature_flags(linear_participants_service_ancestor_scopes: false)
- end
-
- it_behaves_like 'return project members'
- end
end
end
diff --git a/spec/services/projects/prometheus/alerts/notify_service_spec.rb b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
index 25cf588dedf..3bd96ad19bc 100644
--- a/spec/services/projects/prometheus/alerts/notify_service_spec.rb
+++ b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
@@ -218,8 +218,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
.to receive(:new)
.with(project, kind_of(Hash))
.exactly(3).times
- .and_return(process_service)
- expect(process_service).to receive(:execute).exactly(3).times
+ .and_call_original
subject
end
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index b539b01066e..c47d44002cc 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Projects::TransferService do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
- let_it_be(:group_integration) { create(:integrations_slack, group: group, project: nil, webhook: 'http://group.slack.com') }
+ let_it_be(:group_integration) { create(:integrations_slack, :group, group: group, webhook: 'http://group.slack.com') }
let(:project) { create(:project, :repository, :legacy_storage, namespace: user.namespace) }
@@ -66,8 +66,6 @@ RSpec.describe Projects::TransferService do
end
context 'when project has an associated project namespace' do
- let!(:project_namespace) { create(:project_namespace, project: project) }
-
it 'keeps project namespace in sync with project' do
transfer_result = execute_transfer
@@ -272,8 +270,6 @@ RSpec.describe Projects::TransferService do
end
context 'when project has an associated project namespace' do
- let!(:project_namespace) { create(:project_namespace, project: project) }
-
it 'keeps project namespace in sync with project' do
attempt_project_transfer
@@ -294,8 +290,6 @@ RSpec.describe Projects::TransferService do
end
context 'when project has an associated project namespace' do
- let!(:project_namespace) { create(:project_namespace, project: project) }
-
it 'keeps project namespace in sync with project' do
transfer_result = execute_transfer
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index d67b189f90e..611261cd92c 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -1326,14 +1326,25 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { issue }
end
- it_behaves_like 'confidential command' do
- let(:content) { '/confidential' }
- let(:issuable) { issue }
- end
+ context '/confidential' do
+ it_behaves_like 'confidential command' do
+ let(:content) { '/confidential' }
+ let(:issuable) { issue }
+ end
- it_behaves_like 'confidential command' do
- let(:content) { '/confidential' }
- let(:issuable) { create(:incident, project: project) }
+ it_behaves_like 'confidential command' do
+ let(:content) { '/confidential' }
+ let(:issuable) { create(:incident, project: project) }
+ end
+
+ context 'when non-member is creating a new issue' do
+ let(:service) { described_class.new(project, create(:user)) }
+
+ it_behaves_like 'confidential command' do
+ let(:content) { '/confidential' }
+ let(:issuable) { build(:issue, project: project) }
+ end
+ end
end
it_behaves_like 'lock command' do
@@ -2542,4 +2553,32 @@ RSpec.describe QuickActions::InterpretService do
end
end
end
+
+ describe '#available_commands' do
+ context 'when Guest is creating a new issue' do
+ let_it_be(:guest) { create(:user) }
+
+ let(:issue) { build(:issue, project: public_project) }
+ let(:service) { described_class.new(project, guest) }
+
+ before_all do
+ public_project.add_guest(guest)
+ end
+
+ it 'includes commands to set metadata' do
+ # milestone action is only available when project has a milestone
+ milestone
+
+ available_commands = service.available_commands(issue)
+
+ expect(available_commands).to include(
+ a_hash_including(name: :label),
+ a_hash_including(name: :milestone),
+ a_hash_including(name: :copy_metadata),
+ a_hash_including(name: :assign),
+ a_hash_including(name: :due)
+ )
+ end
+ end
+ end
end
diff --git a/spec/services/resource_events/change_labels_service_spec.rb b/spec/services/resource_events/change_labels_service_spec.rb
index b987e3204ad..c2c0a4c2126 100644
--- a/spec/services/resource_events/change_labels_service_spec.rb
+++ b/spec/services/resource_events/change_labels_service_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe ResourceEvents::ChangeLabelsService do
let(:removed) { [labels[1]] }
it 'creates all label events in a single query' do
- expect(Gitlab::Database.main).to receive(:bulk_insert).once.and_call_original
+ expect(ApplicationRecord).to receive(:legacy_bulk_insert).once.and_call_original
expect { subject }.to change { resource.resource_label_events.count }.from(0).to(2)
end
end
diff --git a/spec/services/resource_events/synthetic_label_notes_builder_service_spec.rb b/spec/services/resource_events/synthetic_label_notes_builder_service_spec.rb
index cb42ad5b617..71b1d0993ee 100644
--- a/spec/services/resource_events/synthetic_label_notes_builder_service_spec.rb
+++ b/spec/services/resource_events/synthetic_label_notes_builder_service_spec.rb
@@ -4,18 +4,20 @@ require 'spec_helper'
RSpec.describe ResourceEvents::SyntheticLabelNotesBuilderService do
describe '#execute' do
- let!(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
- let!(:issue) { create(:issue, author: user) }
+ let_it_be(:issue) { create(:issue, author: user) }
- let!(:event1) { create(:resource_label_event, issue: issue) }
- let!(:event2) { create(:resource_label_event, issue: issue) }
- let!(:event3) { create(:resource_label_event, issue: issue) }
+ let_it_be(:event1) { create(:resource_label_event, issue: issue) }
+ let_it_be(:event2) { create(:resource_label_event, issue: issue) }
+ let_it_be(:event3) { create(:resource_label_event, issue: issue) }
it 'returns the expected synthetic notes' do
notes = ResourceEvents::SyntheticLabelNotesBuilderService.new(issue, user).execute
expect(notes.size).to eq(3)
end
+
+ it_behaves_like 'filters by paginated notes', :resource_label_event
end
end
diff --git a/spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb b/spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb
index 1b35e224e98..9c6b6a33b57 100644
--- a/spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb
+++ b/spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb
@@ -24,5 +24,7 @@ RSpec.describe ResourceEvents::SyntheticMilestoneNotesBuilderService do
'removed milestone'
])
end
+
+ it_behaves_like 'filters by paginated notes', :resource_milestone_event
end
end
diff --git a/spec/services/resource_events/synthetic_state_notes_builder_service_spec.rb b/spec/services/resource_events/synthetic_state_notes_builder_service_spec.rb
new file mode 100644
index 00000000000..79500f3768b
--- /dev/null
+++ b/spec/services/resource_events/synthetic_state_notes_builder_service_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ResourceEvents::SyntheticStateNotesBuilderService do
+ describe '#execute' do
+ let_it_be(:user) { create(:user) }
+
+ it_behaves_like 'filters by paginated notes', :resource_state_event
+ end
+end
diff --git a/spec/services/security/ci_configuration/sast_iac_create_service_spec.rb b/spec/services/security/ci_configuration/sast_iac_create_service_spec.rb
new file mode 100644
index 00000000000..deb10732b37
--- /dev/null
+++ b/spec/services/security/ci_configuration/sast_iac_create_service_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Security::CiConfiguration::SastIacCreateService, :snowplow do
+ subject(:result) { described_class.new(project, user).execute }
+
+ let(:branch_name) { 'set-sast-iac-config-1' }
+
+ let(:snowplow_event) do
+ {
+ category: 'Security::CiConfiguration::SastIacCreateService',
+ action: 'create',
+ label: ''
+ }
+ end
+
+ include_examples 'services security ci configuration create service', true
+end
diff --git a/spec/services/spam/spam_verdict_service_spec.rb b/spec/services/spam/spam_verdict_service_spec.rb
index 659c21b7d4f..99047f3233b 100644
--- a/spec/services/spam/spam_verdict_service_spec.rb
+++ b/spec/services/spam/spam_verdict_service_spec.rb
@@ -267,8 +267,8 @@ RSpec.describe Spam::SpamVerdictService do
where(:verdict_value, :expected) do
::Spam::SpamConstants::ALLOW | ::Spam::SpamConstants::ALLOW
::Spam::SpamConstants::CONDITIONAL_ALLOW | ::Spam::SpamConstants::CONDITIONAL_ALLOW
- ::Spam::SpamConstants::DISALLOW | ::Spam::SpamConstants::CONDITIONAL_ALLOW
- ::Spam::SpamConstants::BLOCK_USER | ::Spam::SpamConstants::CONDITIONAL_ALLOW
+ ::Spam::SpamConstants::DISALLOW | ::Spam::SpamConstants::DISALLOW
+ ::Spam::SpamConstants::BLOCK_USER | ::Spam::SpamConstants::BLOCK_USER
end
# rubocop: enable Lint/BinaryOperatorWithIdenticalOperands
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 1a421999ffb..ce0122ae301 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -348,193 +348,6 @@ RSpec.describe SystemNoteService do
end
end
- describe 'Jira integration' do
- include JiraServiceHelper
-
- let(:project) { create(:jira_project, :repository) }
- let(:author) { create(:user) }
- let(:issue) { create(:issue, project: project) }
- let(:merge_request) { create(:merge_request, :simple, target_project: project, source_project: project) }
- let(:jira_issue) { ExternalIssue.new("JIRA-1", project)}
- let(:jira_tracker) { project.jira_integration }
- let(:commit) { project.commit }
- let(:comment_url) { jira_api_comment_url(jira_issue.id) }
- let(:success_message) { "SUCCESS: Successfully posted to http://jira.example.net." }
-
- before do
- stub_jira_integration_test
- stub_jira_urls(jira_issue.id)
- jira_integration_settings
- end
-
- def cross_reference(type, link_exists = false)
- noteable = type == 'commit' ? commit : merge_request
-
- links = []
- if link_exists
- url = if type == 'commit'
- "#{Settings.gitlab.base_url}/#{project.namespace.path}/#{project.path}/-/commit/#{commit.id}"
- else
- "#{Settings.gitlab.base_url}/#{project.namespace.path}/#{project.path}/-/merge_requests/#{merge_request.iid}"
- end
-
- link = double(object: { 'url' => url })
- links << link
- expect(link).to receive(:save!)
- end
-
- allow(JIRA::Resource::Remotelink).to receive(:all).and_return(links)
-
- described_class.cross_reference(jira_issue, noteable, author)
- end
-
- noteable_types = %w(merge_requests commit)
-
- noteable_types.each do |type|
- context "when noteable is a #{type}" do
- it "blocks cross reference when #{type.underscore}_events is false" do
- jira_tracker.update!("#{type}_events" => false)
-
- expect(cross_reference(type)).to eq(s_('JiraService|Events for %{noteable_model_name} are disabled.') % { noteable_model_name: type.pluralize.humanize.downcase })
- end
-
- it "creates cross reference when #{type.underscore}_events is true" do
- jira_tracker.update!("#{type}_events" => true)
-
- expect(cross_reference(type)).to eq(success_message)
- end
- end
-
- context 'when a new cross reference is created' do
- it 'creates a new comment and remote link' do
- cross_reference(type)
-
- expect(WebMock).to have_requested(:post, jira_api_comment_url(jira_issue))
- expect(WebMock).to have_requested(:post, jira_api_remote_link_url(jira_issue))
- end
- end
-
- context 'when a link exists' do
- it 'updates a link but does not create a new comment' do
- expect(WebMock).not_to have_requested(:post, jira_api_comment_url(jira_issue))
-
- cross_reference(type, true)
- end
- end
- end
-
- describe "new reference" do
- let(:favicon_path) { "http://localhost/assets/#{find_asset('favicon.png').digest_path}" }
-
- before do
- allow(JIRA::Resource::Remotelink).to receive(:all).and_return([])
- end
-
- context 'for commits' do
- it "creates comment" do
- result = described_class.cross_reference(jira_issue, commit, author)
-
- expect(result).to eq(success_message)
- end
-
- it "creates remote link" do
- described_class.cross_reference(jira_issue, commit, author)
-
- expect(WebMock).to have_requested(:post, jira_api_remote_link_url(jira_issue)).with(
- body: hash_including(
- GlobalID: "GitLab",
- relationship: 'mentioned on',
- object: {
- url: project_commit_url(project, commit),
- title: "Commit - #{commit.title}",
- icon: { title: "GitLab", url16x16: favicon_path },
- status: { resolved: false }
- }
- )
- ).once
- end
- end
-
- context 'for issues' do
- let(:issue) { create(:issue, project: project) }
-
- it "creates comment" do
- result = described_class.cross_reference(jira_issue, issue, author)
-
- expect(result).to eq(success_message)
- end
-
- it "creates remote link" do
- described_class.cross_reference(jira_issue, issue, author)
-
- expect(WebMock).to have_requested(:post, jira_api_remote_link_url(jira_issue)).with(
- body: hash_including(
- GlobalID: "GitLab",
- relationship: 'mentioned on',
- object: {
- url: project_issue_url(project, issue),
- title: "Issue - #{issue.title}",
- icon: { title: "GitLab", url16x16: favicon_path },
- status: { resolved: false }
- }
- )
- ).once
- end
- end
-
- context 'for snippets' do
- let(:snippet) { create(:snippet, project: project) }
-
- it "creates comment" do
- result = described_class.cross_reference(jira_issue, snippet, author)
-
- expect(result).to eq(success_message)
- end
-
- it "creates remote link" do
- described_class.cross_reference(jira_issue, snippet, author)
-
- expect(WebMock).to have_requested(:post, jira_api_remote_link_url(jira_issue)).with(
- body: hash_including(
- GlobalID: "GitLab",
- relationship: 'mentioned on',
- object: {
- url: project_snippet_url(project, snippet),
- title: "Snippet - #{snippet.title}",
- icon: { title: "GitLab", url16x16: favicon_path },
- status: { resolved: false }
- }
- )
- ).once
- end
- end
- end
-
- describe "existing reference" do
- before do
- allow(JIRA::Resource::Remotelink).to receive(:all).and_return([])
- message = double('message')
- allow(message).to receive(:include?) { true }
- allow_next_instance_of(JIRA::Resource::Issue) do |instance|
- allow(instance).to receive(:comments).and_return([OpenStruct.new(body: message)])
- end
- end
-
- it "does not return success message" do
- result = described_class.cross_reference(jira_issue, commit, author)
-
- expect(result).not_to eq(success_message)
- end
-
- it 'does not try to create comment and remote link' do
- subject
-
- expect(WebMock).not_to have_requested(:post, jira_api_comment_url(jira_issue))
- expect(WebMock).not_to have_requested(:post, jira_api_remote_link_url(jira_issue))
- end
- end
- end
-
describe '.change_time_estimate' do
it 'calls TimeTrackingService' do
expect_next_instance_of(::SystemNotes::TimeTrackingService) do |service|
@@ -781,6 +594,18 @@ RSpec.describe SystemNoteService do
end
end
+ describe '.resolve_incident_status' do
+ let(:incident) { build(:incident, :closed) }
+
+ it 'calls IncidentService' do
+ expect_next_instance_of(SystemNotes::IncidentService) do |service|
+ expect(service).to receive(:resolve_incident_status)
+ end
+
+ described_class.resolve_incident_status(incident, author)
+ end
+ end
+
describe '.log_resolving_alert' do
let(:alert) { build(:alert_management_alert) }
let(:monitoring_tool) { 'Prometheus' }
diff --git a/spec/services/system_notes/incident_service_spec.rb b/spec/services/system_notes/incident_service_spec.rb
index ab9b9eb2bd4..669e357b7a4 100644
--- a/spec/services/system_notes/incident_service_spec.rb
+++ b/spec/services/system_notes/incident_service_spec.rb
@@ -56,4 +56,14 @@ RSpec.describe ::SystemNotes::IncidentService do
end
end
end
+
+ describe '#resolve_incident_status' do
+ subject(:resolve_incident_status) { described_class.new(noteable: noteable, project: project, author: author).resolve_incident_status }
+
+ it 'creates a new note about resolved incident', :aggregate_failures do
+ expect { resolve_incident_status }.to change { noteable.notes.count }.by(1)
+
+ expect(noteable.notes.last.note).to eq('changed the status to **Resolved** by closing the incident')
+ end
+ end
end
diff --git a/spec/services/system_notes/issuables_service_spec.rb b/spec/services/system_notes/issuables_service_spec.rb
index 71a28a89cd8..fd481aa6ddb 100644
--- a/spec/services/system_notes/issuables_service_spec.rb
+++ b/spec/services/system_notes/issuables_service_spec.rb
@@ -347,6 +347,23 @@ RSpec.describe ::SystemNotes::IssuablesService do
end
end
end
+
+ context 'with external issue' do
+ let(:noteable) { ExternalIssue.new('JIRA-123', project) }
+ let(:mentioner) { project.commit }
+
+ it 'queues a background worker' do
+ expect(Integrations::CreateExternalCrossReferenceWorker).to receive(:perform_async).with(
+ project.id,
+ 'JIRA-123',
+ 'Commit',
+ mentioner.id,
+ author.id
+ )
+
+ subject
+ end
+ end
end
end
diff --git a/spec/services/tasks_to_be_done/base_service_spec.rb b/spec/services/tasks_to_be_done/base_service_spec.rb
new file mode 100644
index 00000000000..bf6be6d46e5
--- /dev/null
+++ b/spec/services/tasks_to_be_done/base_service_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe TasksToBeDone::BaseService do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:assignee_one) { create(:user) }
+ let_it_be(:assignee_two) { create(:user) }
+ let_it_be(:assignee_ids) { [assignee_one.id] }
+ let_it_be(:label) { create(:label, title: 'tasks to be done:ci', project: project) }
+
+ before do
+ project.add_maintainer(current_user)
+ project.add_developer(assignee_one)
+ project.add_developer(assignee_two)
+ end
+
+ subject(:service) do
+ TasksToBeDone::CreateCiTaskService.new(
+ project: project,
+ current_user: current_user,
+ assignee_ids: assignee_ids
+ )
+ end
+
+ context 'no existing task issue', :aggregate_failures do
+ it 'creates an issue' do
+ params = {
+ assignee_ids: assignee_ids,
+ title: 'Set up CI/CD',
+ description: anything,
+ add_labels: label.title
+ }
+
+ expect(Issues::BuildService)
+ .to receive(:new)
+ .with(project: project, current_user: current_user, params: params)
+ .and_call_original
+
+ expect { service.execute }.to change(Issue, :count).by(1)
+
+ expect(project.issues.last).to have_attributes(
+ author: current_user,
+ title: params[:title],
+ assignees: [assignee_one],
+ labels: [label]
+ )
+ end
+ end
+
+ context 'an open issue with the same label already exists', :aggregate_failures do
+ let_it_be(:assignee_ids) { [assignee_two.id] }
+
+ it 'assigns the user to the existing issue' do
+ issue = create(:labeled_issue, project: project, labels: [label], assignees: [assignee_one])
+ params = { add_assignee_ids: assignee_ids }
+
+ expect(Issues::UpdateService)
+ .to receive(:new)
+ .with(project: project, current_user: current_user, params: params)
+ .and_call_original
+
+ expect { service.execute }.not_to change(Issue, :count)
+
+ expect(issue.reload.assignees).to match_array([assignee_one, assignee_two])
+ end
+ end
+end
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index 6a8e6dc8970..7103cb0b66a 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -1218,6 +1218,17 @@ RSpec.describe TodoService do
end
end
+ describe '#create_attention_requested_todo' do
+ let(:target) { create(:merge_request, author: author, source_project: project) }
+ let(:user) { create(:user) }
+
+ it 'creates a todo for user' do
+ service.create_attention_requested_todo(target, author, user)
+
+ should_create_todo(user: user, target: target, action: Todo::ATTENTION_REQUESTED)
+ end
+ end
+
def should_create_todo(attributes = {})
attributes.reverse_merge!(
project: project,
diff --git a/spec/services/users/update_service_spec.rb b/spec/services/users/update_service_spec.rb
index 3244db4c1fb..52c7b54ed72 100644
--- a/spec/services/users/update_service_spec.rb
+++ b/spec/services/users/update_service_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe Users::UpdateService do
result = update_user(user, status: { emoji: "Moo!" })
expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq("Emoji is not included in the list")
+ expect(result[:message]).to eq("Emoji is not a valid emoji name")
end
it 'updates user detail with provided attributes' do
diff --git a/spec/services/users/upsert_credit_card_validation_service_spec.rb b/spec/services/users/upsert_credit_card_validation_service_spec.rb
index bede30e1898..952d482f1bd 100644
--- a/spec/services/users/upsert_credit_card_validation_service_spec.rb
+++ b/spec/services/users/upsert_credit_card_validation_service_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe Users::UpsertCreditCardValidationService do
credit_card_expiration_year: expiration_year,
credit_card_expiration_month: 1,
credit_card_holder_name: 'John Smith',
+ credit_card_type: 'AmericanExpress',
credit_card_mask_number: '1111'
}
end
@@ -30,7 +31,16 @@ RSpec.describe Users::UpsertCreditCardValidationService do
result = service.execute
expect(result.status).to eq(:success)
- expect(user.reload.credit_card_validated_at).to eq(credit_card_validated_time)
+
+ user.reload
+
+ expect(user.credit_card_validation).to have_attributes(
+ credit_card_validated_at: credit_card_validated_time,
+ network: 'AmericanExpress',
+ holder_name: 'John Smith',
+ last_digits: 1111,
+ expiration_date: Date.new(expiration_year, 1, 31)
+ )
end
end
@@ -97,6 +107,7 @@ RSpec.describe Users::UpsertCreditCardValidationService do
expiration_date: Date.new(expiration_year, 1, 31),
holder_name: "John Smith",
last_digits: 1111,
+ network: "AmericanExpress",
user_id: user_id
}
diff --git a/spec/sidekiq_cluster/sidekiq_cluster_spec.rb b/spec/sidekiq_cluster/sidekiq_cluster_spec.rb
new file mode 100644
index 00000000000..1d2b47e78ce
--- /dev/null
+++ b/spec/sidekiq_cluster/sidekiq_cluster_spec.rb
@@ -0,0 +1,208 @@
+# frozen_string_literal: true
+
+require 'rspec-parameterized'
+
+require_relative '../../sidekiq_cluster/sidekiq_cluster'
+
+RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath
+ describe '.trap_signals' do
+ it 'traps the given signals' do
+ expect(described_class).to receive(:trap).ordered.with(:INT)
+ expect(described_class).to receive(:trap).ordered.with(:HUP)
+
+ described_class.trap_signals(%i(INT HUP))
+ end
+ end
+
+ describe '.trap_terminate' do
+ it 'traps the termination signals' do
+ expect(described_class).to receive(:trap_signals)
+ .with(described_class::TERMINATE_SIGNALS)
+
+ described_class.trap_terminate { }
+ end
+ end
+
+ describe '.trap_forward' do
+ it 'traps the signals to forward' do
+ expect(described_class).to receive(:trap_signals)
+ .with(described_class::FORWARD_SIGNALS)
+
+ described_class.trap_forward { }
+ end
+ end
+
+ describe '.signal' do
+ it 'sends a signal to the given process' do
+ allow(Process).to receive(:kill).with(:INT, 4)
+ expect(described_class.signal(4, :INT)).to eq(true)
+ end
+
+ it 'returns false when the process does not exist' do
+ allow(Process).to receive(:kill).with(:INT, 4).and_raise(Errno::ESRCH)
+ expect(described_class.signal(4, :INT)).to eq(false)
+ end
+ end
+
+ describe '.signal_processes' do
+ it 'sends a signal to every given process' do
+ expect(described_class).to receive(:signal).with(1, :INT)
+
+ described_class.signal_processes([1], :INT)
+ end
+ end
+
+ describe '.start' do
+ it 'starts Sidekiq with the given queues, environment and options' do
+ expected_options = {
+ env: :production,
+ directory: 'foo/bar',
+ max_concurrency: 20,
+ min_concurrency: 10,
+ timeout: 25,
+ dryrun: true
+ }
+
+ expect(described_class).to receive(:start_sidekiq).ordered.with(%w(foo), expected_options.merge(worker_id: 0))
+ expect(described_class).to receive(:start_sidekiq).ordered.with(%w(bar baz), expected_options.merge(worker_id: 1))
+
+ described_class.start([%w(foo), %w(bar baz)], env: :production, directory: 'foo/bar', max_concurrency: 20, min_concurrency: 10, dryrun: true)
+ end
+
+ it 'starts Sidekiq with the given queues and sensible default options' do
+ expected_options = {
+ env: :development,
+ directory: an_instance_of(String),
+ max_concurrency: 50,
+ min_concurrency: 0,
+ worker_id: an_instance_of(Integer),
+ timeout: 25,
+ dryrun: false
+ }
+
+ expect(described_class).to receive(:start_sidekiq).ordered.with(%w(foo bar baz), expected_options)
+ expect(described_class).to receive(:start_sidekiq).ordered.with(%w(solo), expected_options)
+
+ described_class.start([%w(foo bar baz), %w(solo)])
+ end
+ end
+
+ describe '.start_sidekiq' do
+ let(:first_worker_id) { 0 }
+ let(:options) do
+ { env: :production, directory: 'foo/bar', max_concurrency: 20, min_concurrency: 0, worker_id: first_worker_id, timeout: 10, dryrun: false }
+ end
+
+ let(:env) { { "ENABLE_SIDEKIQ_CLUSTER" => "1", "SIDEKIQ_WORKER_ID" => first_worker_id.to_s } }
+ let(:args) { ['bundle', 'exec', 'sidekiq', anything, '-eproduction', '-t10', *([anything] * 5)] }
+
+ it 'starts a Sidekiq process' do
+ allow(Process).to receive(:spawn).and_return(1)
+
+ expect(described_class).to receive(:wait_async).with(1)
+ expect(described_class.start_sidekiq(%w(foo), **options)).to eq(1)
+ end
+
+ it 'handles duplicate queue names' do
+ allow(Process)
+ .to receive(:spawn)
+ .with(env, *args, anything)
+ .and_return(1)
+
+ expect(described_class).to receive(:wait_async).with(1)
+ expect(described_class.start_sidekiq(%w(foo foo bar baz), **options)).to eq(1)
+ end
+
+ it 'runs the sidekiq process in a new process group' do
+ expect(Process)
+ .to receive(:spawn)
+ .with(anything, *args, a_hash_including(pgroup: true))
+ .and_return(1)
+
+ allow(described_class).to receive(:wait_async)
+ expect(described_class.start_sidekiq(%w(foo bar baz), **options)).to eq(1)
+ end
+ end
+
+ describe '.count_by_queue' do
+ it 'tallies the queue counts' do
+ queues = [%w(foo), %w(bar baz), %w(foo)]
+
+ expect(described_class.count_by_queue(queues)).to eq(%w(foo) => 2, %w(bar baz) => 1)
+ end
+ end
+
+ describe '.concurrency' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:queue_count, :min, :max, :expected) do
+ 2 | 0 | 0 | 3 # No min or max specified
+ 2 | 0 | 9 | 3 # No min specified, value < max
+ 2 | 1 | 4 | 3 # Value between min and max
+ 2 | 4 | 5 | 4 # Value below range
+ 5 | 2 | 3 | 3 # Value above range
+ 2 | 1 | 1 | 1 # Value above explicit setting (min == max)
+ 0 | 3 | 3 | 3 # Value below explicit setting (min == max)
+ 1 | 4 | 3 | 3 # Min greater than max
+ end
+
+ with_them do
+ let(:queues) { Array.new(queue_count) }
+
+ it { expect(described_class.concurrency(queues, min, max)).to eq(expected) }
+ end
+ end
+
+ describe '.wait_async' do
+ it 'waits for a process in a separate thread' do
+ thread = described_class.wait_async(Process.spawn('true'))
+
+ # Upon success Process.wait just returns the PID.
+ expect(thread.value).to be_a_kind_of(Numeric)
+ end
+ end
+
+ # In the X_alive? checks, we check negative PIDs sometimes as a simple way
+ # to be sure the pids are definitely for non-existent processes.
+ # Note that -1 is special, and sends the signal to every process we have permission
+ # for, so we use -2, -3 etc
+ describe '.all_alive?' do
+ it 'returns true if all processes are alive' do
+ processes = [Process.pid]
+
+ expect(described_class.all_alive?(processes)).to eq(true)
+ end
+
+ it 'returns false when a thread was not alive' do
+ processes = [-2]
+
+ expect(described_class.all_alive?(processes)).to eq(false)
+ end
+ end
+
+ describe '.any_alive?' do
+ it 'returns true if at least one process is alive' do
+ processes = [Process.pid, -2]
+
+ expect(described_class.any_alive?(processes)).to eq(true)
+ end
+
+ it 'returns false when all threads are dead' do
+ processes = [-2, -3]
+
+ expect(described_class.any_alive?(processes)).to eq(false)
+ end
+ end
+
+ describe '.write_pid' do
+ it 'writes the PID of the current process to the given file' do
+ handle = double(:handle)
+
+ allow(File).to receive(:open).with('/dev/null', 'w').and_yield(handle)
+
+ expect(handle).to receive(:write).with(Process.pid.to_s)
+
+ described_class.write_pid('/dev/null')
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index c8664598691..25759ca50b8 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -107,9 +107,7 @@ RSpec.configure do |config|
warn `curl -s -o log/goroutines.log http://localhost:9236/debug/pprof/goroutine?debug=2`
end
end
- end
-
- unless ENV['CI']
+ else
# Allow running `:focus` examples locally,
# falling back to all tests when there is no `:focus` example.
config.filter_run focus: true
@@ -199,6 +197,14 @@ RSpec.configure do |config|
if ENV['CI'] || ENV['RETRIES']
# This includes the first try, i.e. tests will be run 4 times before failing.
config.default_retry_count = ENV.fetch('RETRIES', 3).to_i + 1
+
+ # Do not retry controller tests because rspec-retry cannot properly
+ # reset the controller which may contain data from last attempt. See
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73360
+ config.prepend_before(:each, type: :controller) do |example|
+ example.metadata[:retry] = 1
+ end
+
config.exceptions_to_hard_fail = [DeprecationToolkitEnv::DeprecationBehaviors::SelectiveRaise::RaiseDisallowedDeprecation]
end
@@ -232,7 +238,7 @@ RSpec.configure do |config|
# We can't use an `around` hook here because the wrapping transaction
# is not yet opened at the time that is triggered
config.prepend_before do
- Gitlab::Database.main.set_open_transactions_baseline
+ ApplicationRecord.set_open_transactions_baseline
end
config.append_before do
@@ -240,7 +246,7 @@ RSpec.configure do |config|
end
config.append_after do
- Gitlab::Database.main.reset_open_transactions_baseline
+ ApplicationRecord.reset_open_transactions_baseline
end
config.before do |example|
@@ -431,6 +437,10 @@ RSpec.configure do |config|
Gitlab::Metrics.reset_registry!
end
+ config.before(:example, :eager_load) do
+ Rails.application.eager_load!
+ end
+
# This makes sure the `ApplicationController#can?` method is stubbed with the
# original implementation for all view specs.
config.before(:each, type: :view) do
diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb
index ac35662ec93..14ef0f1b7e0 100644
--- a/spec/support/capybara.rb
+++ b/spec/support/capybara.rb
@@ -28,6 +28,8 @@ JS_CONSOLE_FILTER = Regexp.union([
CAPYBARA_WINDOW_SIZE = [1366, 768].freeze
+SCREENSHOT_FILENAME_LENGTH = ENV['CI'] || ENV['CI_SERVER'] ? 255 : 99
+
# Run Workhorse on the given host and port, proxying to Puma on a UNIX socket,
# for a closer-to-production experience
Capybara.register_server :puma_via_workhorse do |app, port, host, **options|
@@ -113,7 +115,7 @@ Capybara.enable_aria_label = true
Capybara::Screenshot.append_timestamp = false
Capybara::Screenshot.register_filename_prefix_formatter(:rspec) do |example|
- example.full_description.downcase.parameterize(separator: "_")[0..99]
+ example.full_description.downcase.parameterize(separator: "_")[0..SCREENSHOT_FILENAME_LENGTH]
end
# Keep only the screenshots generated from the last failing test suite
Capybara::Screenshot.prune_strategy = :keep_last_run
diff --git a/spec/support/database/cross-database-modification-allowlist.yml b/spec/support/database/cross-database-modification-allowlist.yml
index 627967f65f3..d05812a64eb 100644
--- a/spec/support/database/cross-database-modification-allowlist.yml
+++ b/spec/support/database/cross-database-modification-allowlist.yml
@@ -1,1343 +1,90 @@
-- "./ee/spec/controllers/admin/geo/nodes_controller_spec.rb"
-- "./ee/spec/controllers/admin/geo/projects_controller_spec.rb"
-- "./ee/spec/controllers/admin/projects_controller_spec.rb"
-- "./ee/spec/controllers/concerns/internal_redirect_spec.rb"
-- "./ee/spec/controllers/ee/projects/jobs_controller_spec.rb"
-- "./ee/spec/controllers/oauth/geo_auth_controller_spec.rb"
-- "./ee/spec/controllers/projects/approver_groups_controller_spec.rb"
-- "./ee/spec/controllers/projects/approvers_controller_spec.rb"
-- "./ee/spec/controllers/projects/merge_requests_controller_spec.rb"
-- "./ee/spec/controllers/projects/merge_requests/creations_controller_spec.rb"
- "./ee/spec/controllers/projects/settings/access_tokens_controller_spec.rb"
-- "./ee/spec/controllers/projects/subscriptions_controller_spec.rb"
-- "./ee/spec/features/account_recovery_regular_check_spec.rb"
-- "./ee/spec/features/admin/admin_audit_logs_spec.rb"
-- "./ee/spec/features/admin/admin_credentials_inventory_spec.rb"
-- "./ee/spec/features/admin/admin_dashboard_spec.rb"
-- "./ee/spec/features/admin/admin_dev_ops_report_spec.rb"
-- "./ee/spec/features/admin/admin_merge_requests_approvals_spec.rb"
-- "./ee/spec/features/admin/admin_reset_pipeline_minutes_spec.rb"
-- "./ee/spec/features/admin/admin_sends_notification_spec.rb"
-- "./ee/spec/features/admin/admin_settings_spec.rb"
-- "./ee/spec/features/admin/admin_show_new_user_signups_cap_alert_spec.rb"
-- "./ee/spec/features/admin/admin_users_spec.rb"
-- "./ee/spec/features/admin/geo/admin_geo_nodes_spec.rb"
-- "./ee/spec/features/admin/geo/admin_geo_projects_spec.rb"
-- "./ee/spec/features/admin/geo/admin_geo_replication_nav_spec.rb"
-- "./ee/spec/features/admin/geo/admin_geo_sidebar_spec.rb"
-- "./ee/spec/features/admin/geo/admin_geo_uploads_spec.rb"
-- "./ee/spec/features/admin/groups/admin_changes_plan_spec.rb"
-- "./ee/spec/features/admin/licenses/admin_uploads_license_spec.rb"
-- "./ee/spec/features/admin/licenses/show_user_count_threshold_spec.rb"
-- "./ee/spec/features/admin/subscriptions/admin_views_subscription_spec.rb"
-- "./ee/spec/features/analytics/code_analytics_spec.rb"
-- "./ee/spec/features/billings/billing_plans_spec.rb"
-- "./ee/spec/features/billings/extend_reactivate_trial_spec.rb"
-- "./ee/spec/features/billings/qrtly_reconciliation_alert_spec.rb"
-- "./ee/spec/features/boards/boards_licensed_features_spec.rb"
-- "./ee/spec/features/boards/boards_spec.rb"
-- "./ee/spec/features/boards/group_boards/board_deletion_spec.rb"
-- "./ee/spec/features/boards/group_boards/multiple_boards_spec.rb"
-- "./ee/spec/features/boards/new_issue_spec.rb"
-- "./ee/spec/features/boards/scoped_issue_board_spec.rb"
-- "./ee/spec/features/boards/sidebar_spec.rb"
-- "./ee/spec/features/boards/swimlanes/epics_swimlanes_drag_drop_spec.rb"
-- "./ee/spec/features/boards/swimlanes/epics_swimlanes_filtering_spec.rb"
-- "./ee/spec/features/boards/swimlanes/epics_swimlanes_sidebar_labels_spec.rb"
-- "./ee/spec/features/boards/swimlanes/epics_swimlanes_sidebar_spec.rb"
-- "./ee/spec/features/boards/swimlanes/epics_swimlanes_spec.rb"
-- "./ee/spec/features/boards/user_adds_lists_to_board_spec.rb"
-- "./ee/spec/features/boards/user_visits_board_spec.rb"
-- "./ee/spec/features/burndown_charts_spec.rb"
-- "./ee/spec/features/burnup_charts_spec.rb"
-- "./ee/spec/features/ci/ci_minutes_spec.rb"
-- "./ee/spec/features/ci_shared_runner_warnings_spec.rb"
-- "./ee/spec/features/clusters/create_agent_spec.rb"
-- "./ee/spec/features/dashboards/activity_spec.rb"
-- "./ee/spec/features/dashboards/groups_spec.rb"
-- "./ee/spec/features/dashboards/issues_spec.rb"
-- "./ee/spec/features/dashboards/merge_requests_spec.rb"
-- "./ee/spec/features/dashboards/operations_spec.rb"
-- "./ee/spec/features/dashboards/projects_spec.rb"
-- "./ee/spec/features/dashboards/todos_spec.rb"
-- "./ee/spec/features/discussion_comments/epic_quick_actions_spec.rb"
-- "./ee/spec/features/discussion_comments/epic_spec.rb"
-- "./ee/spec/features/epic_boards/epic_boards_sidebar_spec.rb"
-- "./ee/spec/features/epic_boards/epic_boards_spec.rb"
-- "./ee/spec/features/epic_boards/multiple_epic_boards_spec.rb"
-- "./ee/spec/features/epic_boards/new_epic_spec.rb"
-- "./ee/spec/features/epics/delete_epic_spec.rb"
-- "./ee/spec/features/epics/epic_issues_spec.rb"
-- "./ee/spec/features/epics/epic_labels_spec.rb"
-- "./ee/spec/features/epics/epic_show_spec.rb"
-- "./ee/spec/features/epics/epics_list_spec.rb"
-- "./ee/spec/features/epics/filtered_search/visual_tokens_spec.rb"
-- "./ee/spec/features/epics/gfm_autocomplete_spec.rb"
-- "./ee/spec/features/epics/issue_promotion_spec.rb"
-- "./ee/spec/features/epics/referencing_epics_spec.rb"
-- "./ee/spec/features/epics/shortcuts_epic_spec.rb"
-- "./ee/spec/features/epics/todo_spec.rb"
-- "./ee/spec/features/epics/update_epic_spec.rb"
-- "./ee/spec/features/epics/user_uses_quick_actions_spec.rb"
-- "./ee/spec/features/geo_node_spec.rb"
-- "./ee/spec/features/groups/analytics/ci_cd_analytics_spec.rb"
-- "./ee/spec/features/groups/analytics/cycle_analytics/charts_spec.rb"
-- "./ee/spec/features/groups/analytics/cycle_analytics/filters_and_data_spec.rb"
-- "./ee/spec/features/groups/analytics/cycle_analytics/multiple_value_streams_spec.rb"
-- "./ee/spec/features/groups/audit_events_spec.rb"
-- "./ee/spec/features/groups/billing_spec.rb"
-- "./ee/spec/features/groups/contribution_analytics_spec.rb"
-- "./ee/spec/features/groups/group_overview_spec.rb"
-- "./ee/spec/features/groups/group_roadmap_spec.rb"
-- "./ee/spec/features/groups/group_settings_spec.rb"
-- "./ee/spec/features/groups/groups_security_credentials_spec.rb"
-- "./ee/spec/features/groups/hooks/user_tests_hooks_spec.rb"
-- "./ee/spec/features/groups/insights_spec.rb"
-- "./ee/spec/features/groups/issues_spec.rb"
-- "./ee/spec/features/groups/iterations/iterations_list_spec.rb"
-- "./ee/spec/features/groups/iteration_spec.rb"
-- "./ee/spec/features/groups/iterations/user_creates_iteration_in_cadence_spec.rb"
-- "./ee/spec/features/groups/iterations/user_edits_iteration_cadence_spec.rb"
-- "./ee/spec/features/groups/iterations/user_edits_iteration_spec.rb"
-- "./ee/spec/features/groups/iterations/user_views_iteration_cadence_spec.rb"
-- "./ee/spec/features/groups/iterations/user_views_iteration_spec.rb"
-- "./ee/spec/features/groups/ldap_group_links_spec.rb"
-- "./ee/spec/features/groups/ldap_settings_spec.rb"
-- "./ee/spec/features/groups/members/leave_group_spec.rb"
-- "./ee/spec/features/groups/members/list_members_spec.rb"
-- "./ee/spec/features/groups/members/override_ldap_memberships_spec.rb"
-- "./ee/spec/features/groups/new_spec.rb"
-- "./ee/spec/features/groups/push_rules_spec.rb"
-- "./ee/spec/features/groups/saml_providers_spec.rb"
-- "./ee/spec/features/groups/scim_token_spec.rb"
-- "./ee/spec/features/groups/seat_usage/seat_usage_spec.rb"
-- "./ee/spec/features/groups/security/compliance_dashboards_spec.rb"
-- "./ee/spec/features/groups/settings/user_configures_insights_spec.rb"
-- "./ee/spec/features/groups/settings/user_searches_in_settings_spec.rb"
-- "./ee/spec/features/groups/sso_spec.rb"
-- "./ee/spec/features/groups/wikis_spec.rb"
-- "./ee/spec/features/groups/wiki/user_views_wiki_empty_spec.rb"
-- "./ee/spec/features/ide/user_commits_changes_spec.rb"
-- "./ee/spec/features/ide/user_opens_ide_spec.rb"
-- "./ee/spec/features/integrations/jira/jira_issues_list_spec.rb"
-- "./ee/spec/features/issues/blocking_issues_spec.rb"
-- "./ee/spec/features/issues/epic_in_issue_sidebar_spec.rb"
-- "./ee/spec/features/issues/filtered_search/filter_issues_by_iteration_spec.rb"
-- "./ee/spec/features/issues/filtered_search/filter_issues_epic_spec.rb"
-- "./ee/spec/features/issues/filtered_search/filter_issues_weight_spec.rb"
-- "./ee/spec/features/issues/form_spec.rb"
-- "./ee/spec/features/issues/gfm_autocomplete_ee_spec.rb"
-- "./ee/spec/features/issues/issue_actions_spec.rb"
-- "./ee/spec/features/issues/issue_sidebar_spec.rb"
-- "./ee/spec/features/issues/move_issue_resource_weight_events_spec.rb"
-- "./ee/spec/features/issues/related_issues_spec.rb"
-- "./ee/spec/features/issues/resource_weight_events_spec.rb"
-- "./ee/spec/features/issues/user_bulk_edits_issues_spec.rb"
-- "./ee/spec/features/issues/user_edits_issue_spec.rb"
-- "./ee/spec/features/issues/user_uses_quick_actions_spec.rb"
-- "./ee/spec/features/issues/user_views_issues_spec.rb"
-- "./ee/spec/features/labels_hierarchy_spec.rb"
-- "./ee/spec/features/markdown/metrics_spec.rb"
-- "./ee/spec/features/merge_requests/user_filters_by_approvers_spec.rb"
-- "./ee/spec/features/merge_requests/user_resets_approvers_spec.rb"
-- "./ee/spec/features/merge_requests/user_views_all_merge_requests_spec.rb"
-- "./ee/spec/features/merge_request/user_approves_with_password_spec.rb"
-- "./ee/spec/features/merge_request/user_creates_merge_request_spec.rb"
-- "./ee/spec/features/merge_request/user_creates_merge_request_with_blocking_mrs_spec.rb"
-- "./ee/spec/features/merge_request/user_creates_multiple_assignees_mr_spec.rb"
-- "./ee/spec/features/merge_request/user_creates_multiple_reviewers_mr_spec.rb"
-- "./ee/spec/features/merge_request/user_edits_approval_rules_mr_spec.rb"
-- "./ee/spec/features/merge_request/user_edits_merge_request_blocking_mrs_spec.rb"
-- "./ee/spec/features/merge_request/user_edits_multiple_assignees_mr_spec.rb"
-- "./ee/spec/features/merge_request/user_edits_multiple_reviewers_mr_spec.rb"
-- "./ee/spec/features/merge_request/user_merges_immediately_spec.rb"
-- "./ee/spec/features/merge_request/user_merges_with_push_rules_spec.rb"
-- "./ee/spec/features/merge_request/user_sees_approval_widget_spec.rb"
-- "./ee/spec/features/merge_request/user_sees_closing_issues_message_spec.rb"
-- "./ee/spec/features/merge_request/user_sees_merge_widget_spec.rb"
-- "./ee/spec/features/merge_request/user_sees_status_checks_widget_spec.rb"
-- "./ee/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb"
-- "./ee/spec/features/merge_request/user_sets_approval_rules_spec.rb"
-- "./ee/spec/features/merge_request/user_sets_approvers_spec.rb"
-- "./ee/spec/features/merge_request/user_uses_slash_commands_spec.rb"
-- "./ee/spec/features/merge_request/user_views_blocked_merge_request_spec.rb"
-- "./ee/spec/features/merge_trains/user_adds_merge_request_to_merge_train_spec.rb"
-- "./ee/spec/features/merge_trains/user_adds_to_merge_train_when_pipeline_succeeds_spec.rb"
-- "./ee/spec/features/oncall_schedules/user_creates_schedule_spec.rb"
-- "./ee/spec/features/operations_nav_link_spec.rb"
-- "./ee/spec/features/profiles/account_spec.rb"
-- "./ee/spec/features/profiles/billing_spec.rb"
-- "./ee/spec/features/projects/audit_events_spec.rb"
-- "./ee/spec/features/projects/cluster_agents_spec.rb"
-- "./ee/spec/features/projects/custom_projects_template_spec.rb"
-- "./ee/spec/features/projects/environments/environments_spec.rb"
-- "./ee/spec/features/projects/feature_flags/feature_flag_issues_spec.rb"
-- "./ee/spec/features/projects/feature_flags/user_creates_feature_flag_spec.rb"
-- "./ee/spec/features/projects/feature_flags/user_deletes_feature_flag_spec.rb"
-- "./ee/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb"
-- "./ee/spec/features/projects/insights_spec.rb"
-- "./ee/spec/features/projects/integrations/user_activates_jira_spec.rb"
-- "./ee/spec/features/projects/issues/user_creates_issue_spec.rb"
-- "./ee/spec/features/projects/iterations/iteration_cadences_list_spec.rb"
-- "./ee/spec/features/projects/iterations/iterations_list_spec.rb"
-- "./ee/spec/features/projects/iterations/user_views_iteration_spec.rb"
-- "./ee/spec/features/projects/jobs_spec.rb"
-- "./ee/spec/features/projects/kerberos_clone_instructions_spec.rb"
-- "./ee/spec/features/projects/licenses/maintainer_views_policies_spec.rb"
-- "./ee/spec/features/projects/members/member_is_removed_from_project_spec.rb"
-- "./ee/spec/features/projects/merge_requests/user_approves_merge_request_spec.rb"
-- "./ee/spec/features/projects/merge_requests/user_edits_merge_request_spec.rb"
-- "./ee/spec/features/projects/mirror_spec.rb"
-- "./ee/spec/features/projects/new_project_from_template_spec.rb"
-- "./ee/spec/features/projects/new_project_spec.rb"
-- "./ee/spec/features/projects/path_locks_spec.rb"
-- "./ee/spec/features/projects/pipelines/pipeline_spec.rb"
-- "./ee/spec/features/projects/push_rules_spec.rb"
-- "./ee/spec/features/projects/quality/test_case_create_spec.rb"
-- "./ee/spec/features/projects/quality/test_case_list_spec.rb"
-- "./ee/spec/features/projects/quality/test_case_show_spec.rb"
-- "./ee/spec/features/projects/releases/user_views_release_spec.rb"
-- "./ee/spec/features/projects/requirements_management/requirements_list_spec.rb"
-- "./ee/spec/features/projects/security/dast_scanner_profiles_spec.rb"
-- "./ee/spec/features/projects/security/dast_site_profiles_spec.rb"
-- "./ee/spec/features/projects/security/user_creates_on_demand_scan_spec.rb"
-- "./ee/spec/features/projects/security/user_views_security_configuration_spec.rb"
-- "./ee/spec/features/projects/services/prometheus_custom_metrics_spec.rb"
-- "./ee/spec/features/projects/services/user_activates_github_spec.rb"
-- "./ee/spec/features/projects/settings/disable_merge_trains_setting_spec.rb"
-- "./ee/spec/features/projects/settings/ee/repository_mirrors_settings_spec.rb"
-- "./ee/spec/features/projects/settings/ee/service_desk_setting_spec.rb"
-- "./ee/spec/features/projects/settings/issues_settings_spec.rb"
-- "./ee/spec/features/projects/settings/merge_request_approvals_settings_spec.rb"
-- "./ee/spec/features/projects/settings/merge_requests_settings_spec.rb"
-- "./ee/spec/features/projects/settings/pipeline_subscriptions_spec.rb"
-- "./ee/spec/features/projects/settings/protected_environments_spec.rb"
-- "./ee/spec/features/projects/settings/user_manages_merge_pipelines_spec.rb"
-- "./ee/spec/features/projects/settings/user_manages_merge_trains_spec.rb"
-- "./ee/spec/features/projects_spec.rb"
-- "./ee/spec/features/projects/user_applies_custom_file_template_spec.rb"
-- "./ee/spec/features/projects/view_blob_with_code_owners_spec.rb"
-- "./ee/spec/features/projects/wiki/user_views_wiki_empty_spec.rb"
-- "./ee/spec/features/promotion_spec.rb"
-- "./ee/spec/features/protected_branches_spec.rb"
-- "./ee/spec/features/protected_tags_spec.rb"
-- "./ee/spec/features/registrations/combined_registration_spec.rb"
-- "./ee/spec/features/registrations/trial_during_signup_flow_spec.rb"
-- "./ee/spec/features/registrations/user_sees_new_onboarding_flow_spec.rb"
-- "./ee/spec/features/registrations/welcome_spec.rb"
-- "./ee/spec/features/search/elastic/global_search_spec.rb"
-- "./ee/spec/features/search/elastic/group_search_spec.rb"
-- "./ee/spec/features/search/elastic/project_search_spec.rb"
-- "./ee/spec/features/search/elastic/snippet_search_spec.rb"
-- "./ee/spec/features/search/user_searches_for_epics_spec.rb"
-- "./ee/spec/features/subscriptions/groups/edit_spec.rb"
-- "./ee/spec/features/trial_registrations/signup_spec.rb"
-- "./ee/spec/features/trials/capture_lead_spec.rb"
-- "./ee/spec/features/trials/select_namespace_spec.rb"
-- "./ee/spec/features/trials/show_trial_banner_spec.rb"
-- "./ee/spec/features/users/login_spec.rb"
-- "./ee/spec/finders/geo/attachment_legacy_registry_finder_spec.rb"
-- "./ee/spec/finders/geo/container_repository_registry_finder_spec.rb"
-- "./ee/spec/finders/geo/lfs_object_registry_finder_spec.rb"
-- "./ee/spec/finders/geo/merge_request_diff_registry_finder_spec.rb"
-- "./ee/spec/finders/geo/package_file_registry_finder_spec.rb"
-- "./ee/spec/finders/geo/pages_deployment_registry_finder_spec.rb"
-- "./ee/spec/finders/geo/pipeline_artifact_registry_finder_spec.rb"
-- "./ee/spec/finders/geo/project_registry_finder_spec.rb"
-- "./ee/spec/finders/merge_requests/by_approvers_finder_spec.rb"
-- "./ee/spec/frontend/fixtures/analytics/value_streams.rb"
-- "./ee/spec/graphql/mutations/dast_on_demand_scans/create_spec.rb"
-- "./ee/spec/graphql/mutations/dast/profiles/create_spec.rb"
-- "./ee/spec/graphql/mutations/dast/profiles/run_spec.rb"
-- "./ee/spec/graphql/mutations/dast/profiles/update_spec.rb"
-- "./ee/spec/graphql/mutations/merge_requests/accept_spec.rb"
-- "./ee/spec/graphql/resolvers/geo/group_wiki_repository_registries_resolver_spec.rb"
-- "./ee/spec/graphql/resolvers/geo/lfs_object_registries_resolver_spec.rb"
-- "./ee/spec/graphql/resolvers/geo/merge_request_diff_registries_resolver_spec.rb"
-- "./ee/spec/graphql/resolvers/geo/package_file_registries_resolver_spec.rb"
-- "./ee/spec/graphql/resolvers/geo/pages_deployment_registries_resolver_spec.rb"
-- "./ee/spec/graphql/resolvers/geo/pipeline_artifact_registries_resolver_spec.rb"
-- "./ee/spec/graphql/resolvers/geo/snippet_repository_registries_resolver_spec.rb"
-- "./ee/spec/graphql/resolvers/geo/terraform_state_version_registries_resolver_spec.rb"
-- "./ee/spec/graphql/resolvers/geo/upload_registries_resolver_spec.rb"
-- "./ee/spec/helpers/application_helper_spec.rb"
-- "./ee/spec/helpers/ee/geo_helper_spec.rb"
-- "./ee/spec/lib/analytics/devops_adoption/snapshot_calculator_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/backfill_iteration_cadence_id_for_boards_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/backfill_version_data_from_gitaly_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/create_security_setting_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/fix_ruby_object_in_audit_events_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules_check_progress_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules_in_batch_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/migrate_devops_segments_to_groups_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/migrate_security_scans_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/populate_latest_pipeline_ids_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/populate_namespace_statistics_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/populate_resolved_on_default_branch_column_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/populate_vulnerability_feedback_pipeline_id_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/populate_vulnerability_historical_statistics_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/prune_orphaned_geo_events_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/remove_duplicate_cs_findings_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/remove_duplicated_cs_findings_without_vulnerability_id_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/remove_inaccessible_epic_todos_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/remove_undefined_occurrence_confidence_level_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/remove_undefined_occurrence_severity_level_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/remove_undefined_vulnerability_confidence_level_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/remove_undefined_vulnerability_severity_level_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/update_location_fingerprint_for_container_scanning_findings_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/update_vulnerabilities_from_dismissal_feedback_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/update_vulnerabilities_to_dismissed_spec.rb"
-- "./ee/spec/lib/ee/gitlab/background_migration/update_vulnerability_confidence_spec.rb"
-- "./ee/spec/lib/ee/gitlab/database/connection_spec.rb"
-- "./ee/spec/lib/ee/gitlab/database_spec.rb"
-- "./ee/spec/lib/ee/gitlab/middleware/read_only_spec.rb"
-- "./ee/spec/lib/ee/gitlab/usage_data_spec.rb"
-- "./ee/spec/lib/gitlab/background_migration/fix_orphan_promoted_issues_spec.rb"
-- "./ee/spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb"
- "./ee/spec/lib/gitlab/ci/templates/Jobs/dast_default_branch_gitlab_ci_yaml_spec.rb"
-- "./ee/spec/lib/gitlab/geo/base_request_spec.rb"
-- "./ee/spec/lib/gitlab/geo/database_tasks_spec.rb"
-- "./ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb"
-- "./ee/spec/lib/gitlab/geo/geo_tasks_spec.rb"
-- "./ee/spec/lib/gitlab/geo/jwt_request_decoder_spec.rb"
-- "./ee/spec/lib/gitlab/geo/log_cursor/events/design_repository_updated_event_spec.rb"
-- "./ee/spec/lib/gitlab/geo/log_cursor/events/job_artifact_deleted_event_spec.rb"
-- "./ee/spec/lib/gitlab/geo/log_cursor/events/repository_created_event_spec.rb"
-- "./ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb"
-- "./ee/spec/lib/gitlab/geo/oauth/login_state_spec.rb"
-- "./ee/spec/lib/gitlab/geo/oauth/logout_token_spec.rb"
-- "./ee/spec/lib/gitlab/geo/oauth/session_spec.rb"
-- "./ee/spec/lib/gitlab/geo/registry_batcher_spec.rb"
-- "./ee/spec/lib/gitlab/geo/replicable_model_spec.rb"
-- "./ee/spec/lib/gitlab/geo/replication/blob_downloader_spec.rb"
-- "./ee/spec/lib/gitlab/geo/replication/file_transfer_spec.rb"
-- "./ee/spec/lib/gitlab/geo/replicator_spec.rb"
-- "./ee/spec/lib/gitlab/git_access_spec.rb"
-- "./ee/spec/lib/pseudonymizer/dumper_spec.rb"
-- "./ee/spec/lib/system_check/geo/geo_database_configured_check_spec.rb"
-- "./ee/spec/lib/system_check/geo/http_connection_check_spec.rb"
-- "./ee/spec/lib/system_check/rake_task/geo_task_spec.rb"
- "./ee/spec/mailers/notify_spec.rb"
-- "./ee/spec/migrations/20190926180443_schedule_epic_issues_after_epics_move_spec.rb"
-- "./ee/spec/migrations/add_non_null_constraint_for_escalation_rule_on_pending_alert_escalations_spec.rb"
-- "./ee/spec/migrations/add_unique_constraint_to_software_licenses_spec.rb"
-- "./ee/spec/migrations/backfill_namespace_statistics_with_wiki_size_spec.rb"
-- "./ee/spec/migrations/backfill_operations_feature_flags_iid_spec.rb"
-- "./ee/spec/migrations/backfill_software_licenses_spdx_identifiers_spec.rb"
-- "./ee/spec/migrations/backfill_version_author_and_created_at_spec.rb"
-- "./ee/spec/migrations/cleanup_deploy_access_levels_for_removed_groups_spec.rb"
-- "./ee/spec/migrations/create_elastic_reindexing_subtasks_spec.rb"
-- "./ee/spec/migrations/fix_any_approver_rule_for_projects_spec.rb"
-- "./ee/spec/migrations/migrate_design_notes_mentions_to_db_spec.rb"
-- "./ee/spec/migrations/migrate_epic_mentions_to_db_spec.rb"
-- "./ee/spec/migrations/migrate_epic_notes_mentions_to_db_spec.rb"
-- "./ee/spec/migrations/migrate_license_management_artifacts_to_license_scanning_spec.rb"
-- "./ee/spec/migrations/migrate_saml_identities_to_scim_identities_spec.rb"
-- "./ee/spec/migrations/migrate_scim_identities_to_saml_for_new_users_spec.rb"
-- "./ee/spec/migrations/migrate_vulnerability_dismissal_feedback_spec.rb"
-- "./ee/spec/migrations/migrate_vulnerability_dismissals_spec.rb"
-- "./ee/spec/migrations/nullify_feature_flag_plaintext_tokens_spec.rb"
-- "./ee/spec/migrations/populate_vulnerability_historical_statistics_for_year_spec.rb"
-- "./ee/spec/migrations/remove_creations_in_gitlab_subscription_histories_spec.rb"
-- "./ee/spec/migrations/remove_cycle_analytics_total_stage_data_spec.rb"
-- "./ee/spec/migrations/remove_duplicated_cs_findings_spec.rb"
-- "./ee/spec/migrations/remove_duplicated_cs_findings_without_vulnerability_id_spec.rb"
-- "./ee/spec/migrations/remove_schedule_and_status_null_constraints_from_pending_escalations_alert_spec.rb"
-- "./ee/spec/migrations/schedule_fix_orphan_promoted_issues_spec.rb"
-- "./ee/spec/migrations/schedule_fix_ruby_object_in_audit_events_spec.rb"
-- "./ee/spec/migrations/schedule_merge_request_any_approval_rule_migration_spec.rb"
-- "./ee/spec/migrations/schedule_populate_dismissed_state_for_vulnerabilities_spec.rb"
-- "./ee/spec/migrations/schedule_populate_resolved_on_default_branch_column_spec.rb"
-- "./ee/spec/migrations/schedule_populate_vulnerability_historical_statistics_spec.rb"
-- "./ee/spec/migrations/schedule_project_any_approval_rule_migration_spec.rb"
-- "./ee/spec/migrations/schedule_remove_inaccessible_epic_todos_spec.rb"
-- "./ee/spec/migrations/schedule_sync_blocking_issues_count_spec.rb"
-- "./ee/spec/migrations/schedule_uuid_population_for_security_findings2_spec.rb"
-- "./ee/spec/migrations/set_report_type_for_vulnerabilities_spec.rb"
-- "./ee/spec/migrations/set_resolved_state_on_vulnerabilities_spec.rb"
-- "./ee/spec/migrations/update_cs_vulnerability_confidence_column_spec.rb"
-- "./ee/spec/migrations/update_gitlab_subscriptions_start_at_post_eoa_spec.rb"
-- "./ee/spec/migrations/update_location_fingerprint_column_for_cs_spec.rb"
-- "./ee/spec/migrations/update_occurrence_severity_column_spec.rb"
-- "./ee/spec/migrations/update_undefined_confidence_from_occurrences_spec.rb"
-- "./ee/spec/migrations/update_undefined_confidence_from_vulnerabilities_spec.rb"
-- "./ee/spec/migrations/update_vulnerability_severity_column_spec.rb"
-- "./ee/spec/models/analytics/cycle_analytics/group_level_spec.rb"
-- "./ee/spec/models/approval_merge_request_rule_spec.rb"
-- "./ee/spec/models/approval_project_rule_spec.rb"
-- "./ee/spec/models/approval_state_spec.rb"
-- "./ee/spec/models/approval_wrapped_code_owner_rule_spec.rb"
-- "./ee/spec/models/approval_wrapped_rule_spec.rb"
-- "./ee/spec/models/approver_group_spec.rb"
- "./ee/spec/models/ci/bridge_spec.rb"
- "./ee/spec/models/ci/build_spec.rb"
- "./ee/spec/models/ci/minutes/additional_pack_spec.rb"
-- "./ee/spec/models/ci/pipeline_spec.rb"
-- "./ee/spec/models/ci/subscriptions/project_spec.rb"
-- "./ee/spec/models/concerns/approval_rule_like_spec.rb"
-- "./ee/spec/models/concerns/approver_migrate_hook_spec.rb"
-- "./ee/spec/models/dora/daily_metrics_spec.rb"
- "./ee/spec/models/ee/ci/job_artifact_spec.rb"
-- "./ee/spec/models/ee/ci/pipeline_artifact_spec.rb"
-- "./ee/spec/models/ee/ci/runner_spec.rb"
-- "./ee/spec/models/ee/merge_request_diff_spec.rb"
-- "./ee/spec/models/ee/pages_deployment_spec.rb"
-- "./ee/spec/models/ee/terraform/state_version_spec.rb"
-- "./ee/spec/models/geo/container_repository_registry_spec.rb"
-- "./ee/spec/models/geo/deleted_project_spec.rb"
-- "./ee/spec/models/geo/design_registry_spec.rb"
-- "./ee/spec/models/geo/job_artifact_registry_spec.rb"
-- "./ee/spec/models/geo_node_namespace_link_spec.rb"
-- "./ee/spec/models/geo_node_spec.rb"
-- "./ee/spec/models/geo_node_status_spec.rb"
-- "./ee/spec/models/geo/package_file_registry_spec.rb"
-- "./ee/spec/models/geo/project_registry_spec.rb"
- "./ee/spec/models/group_member_spec.rb"
-- "./ee/spec/models/group_wiki_repository_spec.rb"
-- "./ee/spec/models/merge_request_spec.rb"
-- "./ee/spec/models/packages/package_file_spec.rb"
-- "./ee/spec/models/project_spec.rb"
-- "./ee/spec/models/requirements_management/requirement_spec.rb"
-- "./ee/spec/models/snippet_repository_spec.rb"
-- "./ee/spec/models/upload_spec.rb"
-- "./ee/spec/models/visible_approvable_spec.rb"
-- "./ee/spec/policies/ci/build_policy_spec.rb"
-- "./ee/spec/presenters/approval_rule_presenter_spec.rb"
-- "./ee/spec/presenters/merge_request_presenter_spec.rb"
- "./ee/spec/replicators/geo/pipeline_artifact_replicator_spec.rb"
- "./ee/spec/replicators/geo/terraform_state_version_replicator_spec.rb"
-- "./ee/spec/requests/api/ci/pipelines_spec.rb"
-- "./ee/spec/requests/api/geo_nodes_spec.rb"
-- "./ee/spec/requests/api/geo_replication_spec.rb"
-- "./ee/spec/requests/api/graphql/mutations/dast_on_demand_scans/create_spec.rb"
-- "./ee/spec/requests/api/graphql/mutations/dast/profiles/create_spec.rb"
-- "./ee/spec/requests/api/graphql/mutations/dast/profiles/run_spec.rb"
-- "./ee/spec/requests/api/graphql/mutations/dast/profiles/update_spec.rb"
-- "./ee/spec/requests/api/graphql/project/pipeline/dast_profile_spec.rb"
-- "./ee/spec/requests/api/merge_request_approval_rules_spec.rb"
-- "./ee/spec/requests/api/merge_requests_spec.rb"
-- "./ee/spec/requests/api/project_approval_rules_spec.rb"
-- "./ee/spec/requests/api/project_approval_settings_spec.rb"
-- "./ee/spec/requests/api/project_approvals_spec.rb"
-- "./ee/spec/requests/api/project_snapshots_spec.rb"
-- "./ee/spec/requests/api/status_checks_spec.rb"
-- "./ee/spec/requests/api/vulnerability_findings_spec.rb"
-- "./ee/spec/requests/projects/merge_requests_controller_spec.rb"
-- "./ee/spec/routing/admin_routing_spec.rb"
-- "./ee/spec/serializers/dashboard_operations_project_entity_spec.rb"
-- "./ee/spec/serializers/ee/evidences/release_entity_spec.rb"
-- "./ee/spec/serializers/ee/user_serializer_spec.rb"
-- "./ee/spec/serializers/evidences/evidence_entity_spec.rb"
-- "./ee/spec/serializers/merge_request_widget_entity_spec.rb"
-- "./ee/spec/serializers/pipeline_serializer_spec.rb"
-- "./ee/spec/services/approval_rules/create_service_spec.rb"
-- "./ee/spec/services/approval_rules/finalize_service_spec.rb"
-- "./ee/spec/services/approval_rules/merge_request_rule_destroy_service_spec.rb"
-- "./ee/spec/services/approval_rules/params_filtering_service_spec.rb"
-- "./ee/spec/services/approval_rules/project_rule_destroy_service_spec.rb"
-- "./ee/spec/services/approval_rules/update_service_spec.rb"
-- "./ee/spec/services/app_sec/dast/profiles/create_service_spec.rb"
-- "./ee/spec/services/app_sec/dast/profiles/update_service_spec.rb"
-- "./ee/spec/services/app_sec/dast/scans/create_service_spec.rb"
-- "./ee/spec/services/app_sec/dast/scans/run_service_spec.rb"
-- "./ee/spec/services/ci/compare_license_scanning_reports_service_spec.rb"
-- "./ee/spec/services/ci/compare_metrics_reports_service_spec.rb"
-- "./ee/spec/services/ci/create_pipeline_service/dast_configuration_spec.rb"
- "./ee/spec/services/ci/destroy_pipeline_service_spec.rb"
-- "./ee/spec/services/ci/minutes/track_live_consumption_service_spec.rb"
-- "./ee/spec/services/ci/minutes/update_build_minutes_service_spec.rb"
-- "./ee/spec/services/ci/register_job_service_spec.rb"
- "./ee/spec/services/ci/retry_build_service_spec.rb"
-- "./ee/spec/services/ci/run_dast_scan_service_spec.rb"
- "./ee/spec/services/ci/subscribe_bridge_service_spec.rb"
-- "./ee/spec/services/ci/sync_reports_to_approval_rules_service_spec.rb"
-- "./ee/spec/services/ci/trigger_downstream_subscription_service_spec.rb"
-- "./ee/spec/services/dast_on_demand_scans/create_service_spec.rb"
- "./ee/spec/services/deployments/auto_rollback_service_spec.rb"
- "./ee/spec/services/ee/ci/job_artifacts/destroy_all_expired_service_spec.rb"
-- "./ee/spec/services/ee/ci/job_artifacts/destroy_batch_service_spec.rb"
-- "./ee/spec/services/ee/integrations/test/project_service_spec.rb"
-- "./ee/spec/services/ee/issuable/destroy_service_spec.rb"
-- "./ee/spec/services/ee/merge_requests/refresh_service_spec.rb"
-- "./ee/spec/services/ee/merge_requests/update_service_spec.rb"
-- "./ee/spec/services/ee/notification_service_spec.rb"
-- "./ee/spec/services/ee/post_receive_service_spec.rb"
-- "./ee/spec/services/ee/releases/create_evidence_service_spec.rb"
- "./ee/spec/services/ee/users/destroy_service_spec.rb"
-- "./ee/spec/services/external_status_checks/create_service_spec.rb"
-- "./ee/spec/services/external_status_checks/destroy_service_spec.rb"
-- "./ee/spec/services/external_status_checks/update_service_spec.rb"
-- "./ee/spec/services/geo/container_repository_sync_service_spec.rb"
-- "./ee/spec/services/geo/hashed_storage_migrated_event_store_spec.rb"
-- "./ee/spec/services/geo/hashed_storage_migration_service_spec.rb"
-- "./ee/spec/services/geo/node_create_service_spec.rb"
-- "./ee/spec/services/geo/node_status_request_service_spec.rb"
-- "./ee/spec/services/geo/node_update_service_spec.rb"
-- "./ee/spec/services/geo/project_housekeeping_service_spec.rb"
-- "./ee/spec/services/geo/registry_consistency_service_spec.rb"
-- "./ee/spec/services/geo/repositories_changed_event_store_spec.rb"
-- "./ee/spec/services/geo/repository_updated_event_store_spec.rb"
-- "./ee/spec/services/geo/repository_verification_reset_spec.rb"
-- "./ee/spec/services/geo/repository_verification_secondary_service_spec.rb"
-- "./ee/spec/services/merge_requests/merge_service_spec.rb"
-- "./ee/spec/services/merge_requests/reset_approvals_service_spec.rb"
-- "./ee/spec/services/merge_requests/sync_report_approver_approval_rules_spec.rb"
- "./ee/spec/services/projects/transfer_service_spec.rb"
- "./ee/spec/services/security/security_orchestration_policies/rule_schedule_service_spec.rb"
-- "./ee/spec/services/todo_service_spec.rb"
-- "./ee/spec/services/vulnerability_feedback/create_service_spec.rb"
-- "./ee/spec/services/wiki_pages/create_service_spec.rb"
-- "./ee/spec/services/wiki_pages/destroy_service_spec.rb"
-- "./ee/spec/services/wiki_pages/update_service_spec.rb"
-- "./ee/spec/support/shared_examples/fixtures/analytics_value_streams_shared_examples.rb"
-- "./ee/spec/support/shared_examples/graphql/geo/geo_registries_resolver_shared_examples.rb"
-- "./ee/spec/support/shared_examples/graphql/mutations/dast_on_demand_scans_shared_examples.rb"
-- "./ee/spec/support/shared_examples/graphql/mutations/dast_on_demand_scan_with_user_abilities_shared_examples.rb"
-- "./ee/spec/support/shared_examples/lib/gitlab/geo/geo_log_cursor_event_shared_examples.rb"
-- "./ee/spec/support/shared_examples/lib/gitlab/geo/geo_logs_event_source_info_shared_examples.rb"
-- "./ee/spec/support/shared_examples/models/concerns/blob_replicator_strategy_shared_examples.rb"
-- "./ee/spec/support/shared_examples/models/concerns/replicable_model_shared_examples.rb"
-- "./ee/spec/support/shared_examples/models/concerns/verifiable_replicator_shared_examples.rb"
-- "./ee/spec/support/shared_examples/policies/protected_environments_shared_examples.rb"
-- "./ee/spec/support/shared_examples/requests/api/project_approval_rules_api_shared_examples.rb"
-- "./ee/spec/support/shared_examples/services/audit_event_logging_shared_examples.rb"
-- "./ee/spec/support/shared_examples/services/build_execute_shared_examples.rb"
-- "./ee/spec/support/shared_examples/services/dast_on_demand_scans_shared_examples.rb"
-- "./ee/spec/support/shared_examples/services/geo_event_store_shared_examples.rb"
-- "./ee/spec/tasks/geo_rake_spec.rb"
-- "./ee/spec/tasks/gitlab/geo_rake_spec.rb"
-- "./ee/spec/workers/geo/file_download_dispatch_worker_spec.rb"
-- "./ee/spec/workers/geo/metrics_update_worker_spec.rb"
-- "./ee/spec/workers/geo/prune_event_log_worker_spec.rb"
-- "./ee/spec/workers/geo/registry_sync_worker_spec.rb"
-- "./ee/spec/workers/geo/repository_cleanup_worker_spec.rb"
-- "./ee/spec/workers/geo/repository_sync_worker_spec.rb"
-- "./ee/spec/workers/geo/repository_verification/secondary/scheduler_worker_spec.rb"
-- "./ee/spec/workers/geo/repository_verification/secondary/single_worker_spec.rb"
-- "./ee/spec/workers/geo/verification_worker_spec.rb"
-- "./ee/spec/workers/refresh_license_compliance_checks_worker_spec.rb"
- "./spec/controllers/abuse_reports_controller_spec.rb"
- "./spec/controllers/admin/spam_logs_controller_spec.rb"
- "./spec/controllers/admin/users_controller_spec.rb"
- "./spec/controllers/omniauth_callbacks_controller_spec.rb"
- "./spec/controllers/projects/issues_controller_spec.rb"
-- "./spec/controllers/projects/jobs_controller_spec.rb"
-- "./spec/controllers/projects/merge_requests/content_controller_spec.rb"
-- "./spec/controllers/projects/merge_requests_controller_spec.rb"
- "./spec/controllers/projects/pipelines_controller_spec.rb"
-- "./spec/controllers/projects/pipelines/tests_controller_spec.rb"
- "./spec/controllers/projects/settings/access_tokens_controller_spec.rb"
-- "./spec/controllers/projects/tags_controller_spec.rb"
-- "./spec/controllers/sent_notifications_controller_spec.rb"
-- "./spec/factories_spec.rb"
-- "./spec/features/action_cable_logging_spec.rb"
-- "./spec/features/admin/admin_abuse_reports_spec.rb"
-- "./spec/features/admin/admin_appearance_spec.rb"
-- "./spec/features/admin/admin_broadcast_messages_spec.rb"
-- "./spec/features/admin/admin_builds_spec.rb"
-- "./spec/features/admin/admin_dev_ops_report_spec.rb"
-- "./spec/features/admin/admin_disables_git_access_protocol_spec.rb"
-- "./spec/features/admin/admin_disables_two_factor_spec.rb"
-- "./spec/features/admin/admin_groups_spec.rb"
-- "./spec/features/admin/admin_hooks_spec.rb"
-- "./spec/features/admin/admin_labels_spec.rb"
-- "./spec/features/admin/admin_mode/login_spec.rb"
-- "./spec/features/admin/admin_mode/logout_spec.rb"
-- "./spec/features/admin/admin_mode_spec.rb"
-- "./spec/features/admin/admin_mode/workers_spec.rb"
-- "./spec/features/admin/admin_projects_spec.rb"
-- "./spec/features/admin/admin_runners_spec.rb"
-- "./spec/features/admin/admin_search_settings_spec.rb"
-- "./spec/features/admin/admin_serverless_domains_spec.rb"
-- "./spec/features/admin/admin_settings_spec.rb"
-- "./spec/features/admin/admin_users_impersonation_tokens_spec.rb"
-- "./spec/features/admin/admin_uses_repository_checks_spec.rb"
-- "./spec/features/admin/clusters/eks_spec.rb"
-- "./spec/features/admin/dashboard_spec.rb"
-- "./spec/features/admin/integrations/user_activates_mattermost_slash_command_spec.rb"
-- "./spec/features/admin/users/user_spec.rb"
-- "./spec/features/admin/users/users_spec.rb"
-- "./spec/features/alert_management/alert_details_spec.rb"
-- "./spec/features/alert_management/alert_management_list_spec.rb"
-- "./spec/features/alert_management_spec.rb"
-- "./spec/features/alert_management/user_filters_alerts_by_status_spec.rb"
-- "./spec/features/alert_management/user_searches_alerts_spec.rb"
-- "./spec/features/alert_management/user_updates_alert_status_spec.rb"
-- "./spec/features/alerts_settings/user_views_alerts_settings_spec.rb"
-- "./spec/features/atom/dashboard_spec.rb"
-- "./spec/features/boards/boards_spec.rb"
-- "./spec/features/boards/focus_mode_spec.rb"
-- "./spec/features/boards/issue_ordering_spec.rb"
-- "./spec/features/boards/keyboard_shortcut_spec.rb"
-- "./spec/features/boards/multiple_boards_spec.rb"
-- "./spec/features/boards/new_issue_spec.rb"
-- "./spec/features/boards/reload_boards_on_browser_back_spec.rb"
-- "./spec/features/boards/sidebar_due_date_spec.rb"
-- "./spec/features/boards/sidebar_labels_in_namespaces_spec.rb"
-- "./spec/features/boards/sidebar_labels_spec.rb"
-- "./spec/features/boards/sidebar_milestones_spec.rb"
-- "./spec/features/boards/sidebar_spec.rb"
-- "./spec/features/boards/user_adds_lists_to_board_spec.rb"
-- "./spec/features/boards/user_visits_board_spec.rb"
-- "./spec/features/broadcast_messages_spec.rb"
-- "./spec/features/calendar_spec.rb"
-- "./spec/features/callouts/registration_enabled_spec.rb"
-- "./spec/features/clusters/cluster_detail_page_spec.rb"
-- "./spec/features/clusters/cluster_health_dashboard_spec.rb"
-- "./spec/features/commit_spec.rb"
-- "./spec/features/commits_spec.rb"
-- "./spec/features/commits/user_uses_quick_actions_spec.rb"
-- "./spec/features/contextual_sidebar_spec.rb"
-- "./spec/features/cycle_analytics_spec.rb"
-- "./spec/features/dashboard/activity_spec.rb"
-- "./spec/features/dashboard/archived_projects_spec.rb"
-- "./spec/features/dashboard/datetime_on_tooltips_spec.rb"
-- "./spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb"
-- "./spec/features/dashboard/groups_list_spec.rb"
-- "./spec/features/dashboard/group_spec.rb"
-- "./spec/features/dashboard/issues_filter_spec.rb"
-- "./spec/features/dashboard/issues_spec.rb"
-- "./spec/features/dashboard/label_filter_spec.rb"
-- "./spec/features/dashboard/merge_requests_spec.rb"
-- "./spec/features/dashboard/milestones_spec.rb"
-- "./spec/features/dashboard/project_member_activity_index_spec.rb"
-- "./spec/features/dashboard/projects_spec.rb"
-- "./spec/features/dashboard/root_spec.rb"
-- "./spec/features/dashboard/shortcuts_spec.rb"
-- "./spec/features/dashboard/snippets_spec.rb"
-- "./spec/features/dashboard/todos/todos_filtering_spec.rb"
-- "./spec/features/dashboard/todos/todos_spec.rb"
-- "./spec/features/dashboard/user_filters_projects_spec.rb"
-- "./spec/features/discussion_comments/commit_spec.rb"
-- "./spec/features/discussion_comments/issue_spec.rb"
-- "./spec/features/discussion_comments/merge_request_spec.rb"
-- "./spec/features/discussion_comments/snippets_spec.rb"
-- "./spec/features/error_pages_spec.rb"
-- "./spec/features/error_tracking/user_filters_errors_by_status_spec.rb"
-- "./spec/features/error_tracking/user_searches_sentry_errors_spec.rb"
-- "./spec/features/error_tracking/user_sees_error_details_spec.rb"
-- "./spec/features/error_tracking/user_sees_error_index_spec.rb"
-- "./spec/features/expand_collapse_diffs_spec.rb"
-- "./spec/features/explore/groups_list_spec.rb"
-- "./spec/features/explore/groups_spec.rb"
-- "./spec/features/explore/user_explores_projects_spec.rb"
-- "./spec/features/file_uploads/attachment_spec.rb"
-- "./spec/features/file_uploads/ci_artifact_spec.rb"
-- "./spec/features/file_uploads/git_lfs_spec.rb"
-- "./spec/features/file_uploads/graphql_add_design_spec.rb"
-- "./spec/features/file_uploads/group_import_spec.rb"
-- "./spec/features/file_uploads/maven_package_spec.rb"
-- "./spec/features/file_uploads/multipart_invalid_uploads_spec.rb"
-- "./spec/features/file_uploads/nuget_package_spec.rb"
-- "./spec/features/file_uploads/project_import_spec.rb"
-- "./spec/features/file_uploads/rubygem_package_spec.rb"
-- "./spec/features/file_uploads/user_avatar_spec.rb"
-- "./spec/features/frequently_visited_projects_and_groups_spec.rb"
-- "./spec/features/gitlab_experiments_spec.rb"
-- "./spec/features/global_search_spec.rb"
-- "./spec/features/groups/activity_spec.rb"
-- "./spec/features/groups/board_sidebar_spec.rb"
-- "./spec/features/groups/board_spec.rb"
-- "./spec/features/groups/clusters/eks_spec.rb"
-- "./spec/features/groups/clusters/user_spec.rb"
-- "./spec/features/groups/container_registry_spec.rb"
-- "./spec/features/groups/dependency_proxy_spec.rb"
-- "./spec/features/groups/empty_states_spec.rb"
-- "./spec/features/groups/import_export/connect_instance_spec.rb"
-- "./spec/features/groups/import_export/export_file_spec.rb"
-- "./spec/features/groups/import_export/import_file_spec.rb"
-- "./spec/features/groups/integrations/user_activates_mattermost_slash_command_spec.rb"
-- "./spec/features/groups/issues_spec.rb"
-- "./spec/features/groups/labels/index_spec.rb"
-- "./spec/features/groups/labels/search_labels_spec.rb"
-- "./spec/features/groups/labels/sort_labels_spec.rb"
-- "./spec/features/groups/labels/subscription_spec.rb"
-- "./spec/features/groups/members/filter_members_spec.rb"
-- "./spec/features/groups/members/leave_group_spec.rb"
-- "./spec/features/groups/members/list_members_spec.rb"
-- "./spec/features/groups/members/manage_groups_spec.rb"
-- "./spec/features/groups/members/manage_members_spec.rb"
-- "./spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb"
-- "./spec/features/groups/members/master_manages_access_requests_spec.rb"
-- "./spec/features/groups/members/search_members_spec.rb"
-- "./spec/features/groups/members/sort_members_spec.rb"
-- "./spec/features/groups/members/tabs_spec.rb"
-- "./spec/features/groups/merge_requests_spec.rb"
-- "./spec/features/groups/milestones/gfm_autocomplete_spec.rb"
-- "./spec/features/groups/milestone_spec.rb"
-- "./spec/features/groups/milestones_sorting_spec.rb"
-- "./spec/features/groups/packages_spec.rb"
-- "./spec/features/groups/settings/group_badges_spec.rb"
-- "./spec/features/groups/settings/packages_and_registries_spec.rb"
-- "./spec/features/groups/settings/repository_spec.rb"
-- "./spec/features/groups/settings/user_searches_in_settings_spec.rb"
-- "./spec/features/groups/show_spec.rb"
-- "./spec/features/groups_spec.rb"
-- "./spec/features/groups/user_browse_projects_group_page_spec.rb"
-- "./spec/features/groups/user_sees_users_dropdowns_in_issuables_list_spec.rb"
-- "./spec/features/help_pages_spec.rb"
-- "./spec/features/ide_spec.rb"
-- "./spec/features/ide/user_commits_changes_spec.rb"
-- "./spec/features/ide/user_opens_merge_request_spec.rb"
-- "./spec/features/import/manifest_import_spec.rb"
-- "./spec/features/incidents/incident_details_spec.rb"
-- "./spec/features/incidents/incidents_list_spec.rb"
-- "./spec/features/incidents/user_creates_new_incident_spec.rb"
-- "./spec/features/incidents/user_filters_incidents_by_status_spec.rb"
-- "./spec/features/incidents/user_searches_incidents_spec.rb"
-- "./spec/features/incidents/user_views_incident_spec.rb"
-- "./spec/features/issuables/issuable_list_spec.rb"
-- "./spec/features/issuables/markdown_references/internal_references_spec.rb"
-- "./spec/features/issuables/markdown_references/jira_spec.rb"
-- "./spec/features/issuables/sorting_list_spec.rb"
-- "./spec/features/issuables/user_sees_sidebar_spec.rb"
-- "./spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb"
-- "./spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb"
-- "./spec/features/issues/csv_spec.rb"
-- "./spec/features/issues/discussion_lock_spec.rb"
-- "./spec/features/issues/filtered_search/dropdown_assignee_spec.rb"
-- "./spec/features/issues/filtered_search/dropdown_author_spec.rb"
-- "./spec/features/issues/filtered_search/dropdown_base_spec.rb"
-- "./spec/features/issues/filtered_search/dropdown_emoji_spec.rb"
-- "./spec/features/issues/filtered_search/dropdown_hint_spec.rb"
-- "./spec/features/issues/filtered_search/dropdown_label_spec.rb"
-- "./spec/features/issues/filtered_search/dropdown_milestone_spec.rb"
-- "./spec/features/issues/filtered_search/dropdown_release_spec.rb"
-- "./spec/features/issues/filtered_search/filter_issues_spec.rb"
-- "./spec/features/issues/filtered_search/recent_searches_spec.rb"
-- "./spec/features/issues/filtered_search/search_bar_spec.rb"
-- "./spec/features/issues/filtered_search/visual_tokens_spec.rb"
-- "./spec/features/issues/form_spec.rb"
-- "./spec/features/issues/gfm_autocomplete_spec.rb"
-- "./spec/features/issues/group_label_sidebar_spec.rb"
-- "./spec/features/issues/incident_issue_spec.rb"
- "./spec/features/issues/issue_detail_spec.rb"
-- "./spec/features/issues/issue_header_spec.rb"
-- "./spec/features/issues/issue_sidebar_spec.rb"
-- "./spec/features/issues/keyboard_shortcut_spec.rb"
-- "./spec/features/issues/markdown_toolbar_spec.rb"
-- "./spec/features/issues/move_spec.rb"
-- "./spec/features/issues/note_polling_spec.rb"
-- "./spec/features/issues/notes_on_issues_spec.rb"
-- "./spec/features/issues/related_issues_spec.rb"
-- "./spec/features/issues/resource_label_events_spec.rb"
-- "./spec/features/issues/service_desk_spec.rb"
-- "./spec/features/issues/spam_issues_spec.rb"
-- "./spec/features/issues/todo_spec.rb"
-- "./spec/features/issues/user_bulk_edits_issues_labels_spec.rb"
-- "./spec/features/issues/user_bulk_edits_issues_spec.rb"
-- "./spec/features/issues/user_comments_on_issue_spec.rb"
-- "./spec/features/issues/user_creates_branch_and_merge_request_spec.rb"
-- "./spec/features/issues/user_creates_confidential_merge_request_spec.rb"
-- "./spec/features/issues/user_creates_issue_by_email_spec.rb"
-- "./spec/features/issues/user_creates_issue_spec.rb"
-- "./spec/features/issues/user_edits_issue_spec.rb"
-- "./spec/features/issues/user_filters_issues_spec.rb"
-- "./spec/features/issues/user_interacts_with_awards_spec.rb"
-- "./spec/features/issues/user_invites_from_a_comment_spec.rb"
-- "./spec/features/issues/user_resets_their_incoming_email_token_spec.rb"
-- "./spec/features/issues/user_sees_empty_state_spec.rb"
-- "./spec/features/issues/user_sees_live_update_spec.rb"
-- "./spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb"
-- "./spec/features/issues/user_sorts_issue_comments_spec.rb"
-- "./spec/features/issues/user_sorts_issues_spec.rb"
-- "./spec/features/issues/user_toggles_subscription_spec.rb"
-- "./spec/features/issues/user_uses_quick_actions_spec.rb"
-- "./spec/features/issues/user_views_issue_spec.rb"
-- "./spec/features/issues/user_views_issues_spec.rb"
-- "./spec/features/jira_connect/branches_spec.rb"
-- "./spec/features/labels_hierarchy_spec.rb"
-- "./spec/features/markdown/copy_as_gfm_spec.rb"
-- "./spec/features/markdown/gitlab_flavored_markdown_spec.rb"
-- "./spec/features/markdown/keyboard_shortcuts_spec.rb"
-- "./spec/features/markdown/math_spec.rb"
-- "./spec/features/markdown/mermaid_spec.rb"
-- "./spec/features/markdown/metrics_spec.rb"
-- "./spec/features/merge_request/batch_comments_spec.rb"
-- "./spec/features/merge_request/close_reopen_report_toggle_spec.rb"
-- "./spec/features/merge_request/maintainer_edits_fork_spec.rb"
-- "./spec/features/merge_request/merge_request_discussion_lock_spec.rb"
-- "./spec/features/merge_requests/filters_generic_behavior_spec.rb"
-- "./spec/features/merge_requests/user_exports_as_csv_spec.rb"
-- "./spec/features/merge_requests/user_filters_by_approvals_spec.rb"
-- "./spec/features/merge_requests/user_filters_by_assignees_spec.rb"
-- "./spec/features/merge_requests/user_filters_by_deployments_spec.rb"
-- "./spec/features/merge_requests/user_filters_by_draft_spec.rb"
-- "./spec/features/merge_requests/user_filters_by_labels_spec.rb"
-- "./spec/features/merge_requests/user_filters_by_milestones_spec.rb"
-- "./spec/features/merge_requests/user_filters_by_multiple_criteria_spec.rb"
-- "./spec/features/merge_requests/user_filters_by_target_branch_spec.rb"
-- "./spec/features/merge_requests/user_mass_updates_spec.rb"
-- "./spec/features/merge_request/user_accepts_merge_request_spec.rb"
-- "./spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb"
-- "./spec/features/merge_request/user_approves_spec.rb"
-- "./spec/features/merge_request/user_assigns_themselves_spec.rb"
-- "./spec/features/merge_request/user_awards_emoji_spec.rb"
-- "./spec/features/merge_request/user_clicks_merge_request_tabs_spec.rb"
-- "./spec/features/merge_request/user_comments_on_commit_spec.rb"
-- "./spec/features/merge_request/user_comments_on_diff_spec.rb"
-- "./spec/features/merge_request/user_comments_on_merge_request_spec.rb"
-- "./spec/features/merge_request/user_creates_image_diff_notes_spec.rb"
-- "./spec/features/merge_request/user_creates_merge_request_spec.rb"
-- "./spec/features/merge_request/user_creates_mr_spec.rb"
-- "./spec/features/merge_request/user_customizes_merge_commit_message_spec.rb"
-- "./spec/features/merge_request/user_edits_assignees_sidebar_spec.rb"
-- "./spec/features/merge_request/user_edits_merge_request_spec.rb"
-- "./spec/features/merge_request/user_edits_mr_spec.rb"
-- "./spec/features/merge_request/user_edits_reviewers_sidebar_spec.rb"
-- "./spec/features/merge_request/user_expands_diff_spec.rb"
-- "./spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb"
-- "./spec/features/merge_request/user_invites_from_a_comment_spec.rb"
-- "./spec/features/merge_request/user_jumps_to_discussion_spec.rb"
-- "./spec/features/merge_request/user_locks_discussion_spec.rb"
-- "./spec/features/merge_request/user_manages_subscription_spec.rb"
-- "./spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb"
-- "./spec/features/merge_request/user_merges_immediately_spec.rb"
-- "./spec/features/merge_request/user_merges_merge_request_spec.rb"
-- "./spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb"
-- "./spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb"
-- "./spec/features/merge_request/user_posts_diff_notes_spec.rb"
-- "./spec/features/merge_request/user_posts_notes_spec.rb"
-- "./spec/features/merge_request/user_rebases_merge_request_spec.rb"
-- "./spec/features/merge_request/user_resolves_conflicts_spec.rb"
-- "./spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb"
-- "./spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb"
-- "./spec/features/merge_request/user_resolves_wip_mr_spec.rb"
-- "./spec/features/merge_request/user_reverts_merge_request_spec.rb"
-- "./spec/features/merge_request/user_reviews_image_spec.rb"
-- "./spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb"
-- "./spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb"
-- "./spec/features/merge_request/user_sees_check_out_branch_modal_spec.rb"
-- "./spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb"
-- "./spec/features/merge_request/user_sees_closing_issues_message_spec.rb"
-- "./spec/features/merge_request/user_sees_deleted_target_branch_spec.rb"
-- "./spec/features/merge_request/user_sees_deployment_widget_spec.rb"
-- "./spec/features/merge_request/user_sees_diff_spec.rb"
-- "./spec/features/merge_request/user_sees_discussions_spec.rb"
-- "./spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb"
-- "./spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb"
-- "./spec/features/merge_request/user_sees_merge_widget_spec.rb"
-- "./spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb"
-- "./spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb"
-- "./spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb"
-- "./spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb"
-- "./spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb"
-- "./spec/features/merge_request/user_sees_pipelines_spec.rb"
-- "./spec/features/merge_request/user_sees_suggest_pipeline_spec.rb"
-- "./spec/features/merge_request/user_sees_system_notes_spec.rb"
-- "./spec/features/merge_request/user_sees_versions_spec.rb"
-- "./spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb"
-- "./spec/features/merge_request/user_squashes_merge_request_spec.rb"
-- "./spec/features/merge_request/user_suggests_changes_on_diff_spec.rb"
-- "./spec/features/merge_request/user_toggles_whitespace_changes_spec.rb"
-- "./spec/features/merge_request/user_uses_quick_actions_spec.rb"
-- "./spec/features/merge_request/user_views_auto_expanding_diff_spec.rb"
-- "./spec/features/merge_request/user_views_diffs_commit_spec.rb"
-- "./spec/features/merge_request/user_views_diffs_file_by_file_spec.rb"
-- "./spec/features/merge_request/user_views_diffs_spec.rb"
-- "./spec/features/merge_request/user_views_open_merge_request_spec.rb"
-- "./spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb"
-- "./spec/features/milestone_spec.rb"
-- "./spec/features/milestones/user_creates_milestone_spec.rb"
-- "./spec/features/milestones/user_deletes_milestone_spec.rb"
-- "./spec/features/milestones/user_edits_milestone_spec.rb"
-- "./spec/features/milestones/user_views_milestone_spec.rb"
-- "./spec/features/milestones/user_views_milestones_spec.rb"
-- "./spec/features/nav/top_nav_responsive_spec.rb"
-- "./spec/features/oauth_login_spec.rb"
-- "./spec/features/participants_autocomplete_spec.rb"
-- "./spec/features/populate_new_pipeline_vars_with_params_spec.rb"
-- "./spec/features/profiles/account_spec.rb"
-- "./spec/features/profiles/active_sessions_spec.rb"
-- "./spec/features/profiles/keys_spec.rb"
-- "./spec/features/profiles/oauth_applications_spec.rb"
-- "./spec/features/profile_spec.rb"
-- "./spec/features/profiles/personal_access_tokens_spec.rb"
-- "./spec/features/profiles/user_changes_notified_of_own_activity_spec.rb"
-- "./spec/features/profiles/user_edit_preferences_spec.rb"
-- "./spec/features/profiles/user_edit_profile_spec.rb"
-- "./spec/features/profiles/user_search_settings_spec.rb"
-- "./spec/features/profiles/user_visits_notifications_tab_spec.rb"
-- "./spec/features/profiles/user_visits_profile_preferences_page_spec.rb"
-- "./spec/features/profiles/user_visits_profile_spec.rb"
-- "./spec/features/project_group_variables_spec.rb"
-- "./spec/features/projects/activity/user_sees_activity_spec.rb"
-- "./spec/features/projects/activity/user_sees_design_activity_spec.rb"
-- "./spec/features/projects/activity/user_sees_design_comment_spec.rb"
-- "./spec/features/projects/activity/user_sees_private_activity_spec.rb"
-- "./spec/features/projects/artifacts/file_spec.rb"
-- "./spec/features/projects/artifacts/raw_spec.rb"
-- "./spec/features/projects/artifacts/user_browses_artifacts_spec.rb"
-- "./spec/features/projects/badges/list_spec.rb"
-- "./spec/features/projects/badges/pipeline_badge_spec.rb"
-- "./spec/features/projects/blobs/balsamiq_spec.rb"
-- "./spec/features/projects/blobs/blob_line_permalink_updater_spec.rb"
-- "./spec/features/projects/blobs/blob_show_spec.rb"
-- "./spec/features/projects/blobs/edit_spec.rb"
-- "./spec/features/projects/blobs/shortcuts_blob_spec.rb"
-- "./spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb"
-- "./spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb"
-- "./spec/features/projects/blobs/user_views_pipeline_editor_button_spec.rb"
-- "./spec/features/projects/branches/new_branch_ref_dropdown_spec.rb"
-- "./spec/features/projects/branches_spec.rb"
-- "./spec/features/projects/branches/user_creates_branch_spec.rb"
-- "./spec/features/projects/branches/user_deletes_branch_spec.rb"
-- "./spec/features/projects/branches/user_views_branches_spec.rb"
-- "./spec/features/projects/ci/editor_spec.rb"
-- "./spec/features/projects/clusters/eks_spec.rb"
-- "./spec/features/projects/clusters/gcp_spec.rb"
-- "./spec/features/projects/clusters_spec.rb"
-- "./spec/features/projects/clusters/user_spec.rb"
-- "./spec/features/projects/commit/builds_spec.rb"
-- "./spec/features/projects/commit/cherry_pick_spec.rb"
-- "./spec/features/projects/commit/comments/user_adds_comment_spec.rb"
-- "./spec/features/projects/commit/comments/user_deletes_comments_spec.rb"
-- "./spec/features/projects/commit/comments/user_edits_comments_spec.rb"
-- "./spec/features/projects/commit/diff_notes_spec.rb"
-- "./spec/features/projects/commit/mini_pipeline_graph_spec.rb"
-- "./spec/features/projects/commits/user_browses_commits_spec.rb"
-- "./spec/features/projects/commit/user_comments_on_commit_spec.rb"
-- "./spec/features/projects/commit/user_reverts_commit_spec.rb"
-- "./spec/features/projects/commit/user_views_user_status_on_commit_spec.rb"
-- "./spec/features/projects/compare_spec.rb"
-- "./spec/features/projects/container_registry_spec.rb"
-- "./spec/features/projects/deploy_keys_spec.rb"
-- "./spec/features/projects/diffs/diff_show_spec.rb"
-- "./spec/features/projects/environments/environment_metrics_spec.rb"
-- "./spec/features/projects/environments/environment_spec.rb"
-- "./spec/features/projects/environments/environments_spec.rb"
-- "./spec/features/projects/environments_pod_logs_spec.rb"
-- "./spec/features/projects/feature_flags/user_creates_feature_flag_spec.rb"
-- "./spec/features/projects/feature_flags/user_deletes_feature_flag_spec.rb"
-- "./spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb"
-- "./spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb"
-- "./spec/features/projects/feature_flag_user_lists/user_deletes_feature_flag_user_list_spec.rb"
-- "./spec/features/projects/feature_flag_user_lists/user_edits_feature_flag_user_list_spec.rb"
-- "./spec/features/projects/feature_flag_user_lists/user_sees_feature_flag_user_list_details_spec.rb"
-- "./spec/features/projects/features_visibility_spec.rb"
-- "./spec/features/projects/files/dockerfile_dropdown_spec.rb"
-- "./spec/features/projects/files/edit_file_soft_wrap_spec.rb"
-- "./spec/features/projects/files/files_sort_submodules_with_folders_spec.rb"
-- "./spec/features/projects/files/find_file_keyboard_spec.rb"
-- "./spec/features/projects/files/gitignore_dropdown_spec.rb"
-- "./spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb"
-- "./spec/features/projects/files/project_owner_creates_license_file_spec.rb"
-- "./spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb"
-- "./spec/features/projects/files/template_selector_menu_spec.rb"
-- "./spec/features/projects/files/template_type_dropdown_spec.rb"
-- "./spec/features/projects/files/undo_template_spec.rb"
-- "./spec/features/projects/files/user_browses_a_tree_with_a_folder_containing_only_a_folder_spec.rb"
-- "./spec/features/projects/files/user_browses_files_spec.rb"
-- "./spec/features/projects/files/user_browses_lfs_files_spec.rb"
-- "./spec/features/projects/files/user_creates_directory_spec.rb"
-- "./spec/features/projects/files/user_creates_files_spec.rb"
-- "./spec/features/projects/files/user_deletes_files_spec.rb"
-- "./spec/features/projects/files/user_edits_files_spec.rb"
-- "./spec/features/projects/files/user_find_file_spec.rb"
-- "./spec/features/projects/files/user_reads_pipeline_status_spec.rb"
-- "./spec/features/projects/files/user_replaces_files_spec.rb"
-- "./spec/features/projects/files/user_uploads_files_spec.rb"
-- "./spec/features/projects/fork_spec.rb"
-- "./spec/features/projects/gfm_autocomplete_load_spec.rb"
-- "./spec/features/projects/graph_spec.rb"
-- "./spec/features/projects/import_export/export_file_spec.rb"
-- "./spec/features/projects/import_export/import_file_spec.rb"
-- "./spec/features/projects/infrastructure_registry_spec.rb"
-- "./spec/features/projects/integrations/user_activates_asana_spec.rb"
-- "./spec/features/projects/integrations/user_activates_assembla_spec.rb"
-- "./spec/features/projects/integrations/user_activates_atlassian_bamboo_ci_spec.rb"
-- "./spec/features/projects/integrations/user_activates_flowdock_spec.rb"
-- "./spec/features/projects/integrations/user_activates_jira_spec.rb"
-- "./spec/features/projects/integrations/user_activates_pivotaltracker_spec.rb"
-- "./spec/features/projects/integrations/user_uses_inherited_settings_spec.rb"
-- "./spec/features/projects/issuable_templates_spec.rb"
-- "./spec/features/projects/issues/design_management/user_paginates_designs_spec.rb"
-- "./spec/features/projects/issues/design_management/user_permissions_upload_spec.rb"
-- "./spec/features/projects/issues/design_management/user_uploads_designs_spec.rb"
-- "./spec/features/projects/issues/design_management/user_views_design_spec.rb"
-- "./spec/features/projects/issues/design_management/user_views_designs_spec.rb"
-- "./spec/features/projects/issues/design_management/user_views_designs_with_svg_xss_spec.rb"
-- "./spec/features/projects/issues/email_participants_spec.rb"
-- "./spec/features/projects/jobs/permissions_spec.rb"
-- "./spec/features/projects/jobs_spec.rb"
-- "./spec/features/projects/jobs/user_browses_job_spec.rb"
-- "./spec/features/projects/jobs/user_browses_jobs_spec.rb"
-- "./spec/features/projects/labels/issues_sorted_by_priority_spec.rb"
-- "./spec/features/projects/labels/search_labels_spec.rb"
-- "./spec/features/projects/labels/sort_labels_spec.rb"
-- "./spec/features/projects/labels/subscription_spec.rb"
-- "./spec/features/projects/labels/update_prioritization_spec.rb"
-- "./spec/features/projects/labels/user_removes_labels_spec.rb"
-- "./spec/features/projects/members/anonymous_user_sees_members_spec.rb"
-- "./spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb"
-- "./spec/features/projects/members/group_members_spec.rb"
-- "./spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb"
-- "./spec/features/projects/members/groups_with_access_list_spec.rb"
-- "./spec/features/projects/members/invite_group_spec.rb"
-- "./spec/features/projects/members/list_spec.rb"
-- "./spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb"
-- "./spec/features/projects/members/master_manages_access_requests_spec.rb"
-- "./spec/features/projects/members/sorting_spec.rb"
-- "./spec/features/projects/members/tabs_spec.rb"
-- "./spec/features/projects/members/user_requests_access_spec.rb"
-- "./spec/features/projects/merge_request_button_spec.rb"
-- "./spec/features/projects/milestones/gfm_autocomplete_spec.rb"
-- "./spec/features/projects/milestones/milestones_sorting_spec.rb"
-- "./spec/features/projects/milestones/new_spec.rb"
-- "./spec/features/projects/milestones/user_interacts_with_labels_spec.rb"
-- "./spec/features/projects/network_graph_spec.rb"
-- "./spec/features/projects/new_project_from_template_spec.rb"
-- "./spec/features/projects/new_project_spec.rb"
-- "./spec/features/projects/packages_spec.rb"
-- "./spec/features/projects/pages/user_adds_domain_spec.rb"
-- "./spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb"
-- "./spec/features/projects/pages/user_edits_settings_spec.rb"
-- "./spec/features/projects/pipeline_schedules_spec.rb"
- "./spec/features/projects/pipelines/pipeline_spec.rb"
-- "./spec/features/projects/pipelines/pipelines_spec.rb"
-- "./spec/features/projects/product_analytics/graphs_spec.rb"
-- "./spec/features/projects/releases/user_creates_release_spec.rb"
-- "./spec/features/projects/releases/user_views_edit_release_spec.rb"
-- "./spec/features/projects/releases/user_views_release_spec.rb"
-- "./spec/features/projects/releases/user_views_releases_spec.rb"
-- "./spec/features/projects/remote_mirror_spec.rb"
-- "./spec/features/projects/serverless/functions_spec.rb"
-- "./spec/features/projects/services/disable_triggers_spec.rb"
-- "./spec/features/projects/services/prometheus_external_alerts_spec.rb"
-- "./spec/features/projects/services/user_activates_emails_on_push_spec.rb"
-- "./spec/features/projects/services/user_activates_irker_spec.rb"
-- "./spec/features/projects/services/user_activates_issue_tracker_spec.rb"
-- "./spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb"
-- "./spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb"
-- "./spec/features/projects/services/user_activates_packagist_spec.rb"
-- "./spec/features/projects/services/user_activates_prometheus_spec.rb"
-- "./spec/features/projects/services/user_activates_pushover_spec.rb"
-- "./spec/features/projects/services/user_activates_slack_notifications_spec.rb"
-- "./spec/features/projects/services/user_activates_slack_slash_command_spec.rb"
-- "./spec/features/projects/services/user_views_services_spec.rb"
-- "./spec/features/projects/settings/access_tokens_spec.rb"
-- "./spec/features/projects/settings/lfs_settings_spec.rb"
-- "./spec/features/projects/settings/monitor_settings_spec.rb"
-- "./spec/features/projects/settings/packages_settings_spec.rb"
-- "./spec/features/projects/settings/project_badges_spec.rb"
-- "./spec/features/projects/settings/project_settings_spec.rb"
-- "./spec/features/projects/settings/registry_settings_spec.rb"
-- "./spec/features/projects/settings/repository_settings_spec.rb"
-- "./spec/features/projects/settings/service_desk_setting_spec.rb"
-- "./spec/features/projects/settings/user_changes_default_branch_spec.rb"
-- "./spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb"
-- "./spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb"
-- "./spec/features/projects/settings/user_manages_project_members_spec.rb"
-- "./spec/features/projects/settings/user_searches_in_settings_spec.rb"
-- "./spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb"
-- "./spec/features/projects/settings/user_tags_project_spec.rb"
-- "./spec/features/projects/settings/user_transfers_a_project_spec.rb"
-- "./spec/features/projects/settings/visibility_settings_spec.rb"
-- "./spec/features/projects/settings/webhooks_settings_spec.rb"
-- "./spec/features/projects/show/schema_markup_spec.rb"
-- "./spec/features/projects/show/user_interacts_with_auto_devops_banner_spec.rb"
-- "./spec/features/projects/show/user_interacts_with_stars_spec.rb"
-- "./spec/features/projects/show/user_manages_notifications_spec.rb"
-- "./spec/features/projects/show/user_sees_collaboration_links_spec.rb"
-- "./spec/features/projects/show/user_sees_last_commit_ci_status_spec.rb"
-- "./spec/features/projects/show/user_sees_readme_spec.rb"
-- "./spec/features/projects/show/user_uploads_files_spec.rb"
-- "./spec/features/projects/snippets/create_snippet_spec.rb"
-- "./spec/features/projects/snippets/show_spec.rb"
-- "./spec/features/projects/snippets/user_comments_on_snippet_spec.rb"
-- "./spec/features/projects/snippets/user_deletes_snippet_spec.rb"
-- "./spec/features/projects/snippets/user_updates_snippet_spec.rb"
-- "./spec/features/projects_spec.rb"
-- "./spec/features/projects/sub_group_issuables_spec.rb"
-- "./spec/features/projects/tags/user_edits_tags_spec.rb"
-- "./spec/features/projects/terraform_spec.rb"
-- "./spec/features/projects/tree/create_directory_spec.rb"
-- "./spec/features/projects/tree/create_file_spec.rb"
-- "./spec/features/projects/tree/tree_show_spec.rb"
-- "./spec/features/projects/tree/upload_file_spec.rb"
-- "./spec/features/projects/user_changes_project_visibility_spec.rb"
-- "./spec/features/projects/user_creates_project_spec.rb"
-- "./spec/features/projects/user_sees_sidebar_spec.rb"
-- "./spec/features/projects/user_sees_user_popover_spec.rb"
-- "./spec/features/projects/user_uses_shortcuts_spec.rb"
-- "./spec/features/projects/user_views_empty_project_spec.rb"
-- "./spec/features/projects/view_on_env_spec.rb"
-- "./spec/features/projects/wikis_spec.rb"
-- "./spec/features/projects/wiki/user_views_wiki_empty_spec.rb"
-- "./spec/features/project_variables_spec.rb"
-- "./spec/features/promotion_spec.rb"
-- "./spec/features/protected_branches_spec.rb"
-- "./spec/features/protected_tags_spec.rb"
-- "./spec/features/reportable_note/commit_spec.rb"
-- "./spec/features/reportable_note/issue_spec.rb"
-- "./spec/features/reportable_note/merge_request_spec.rb"
-- "./spec/features/reportable_note/snippets_spec.rb"
-- "./spec/features/runners_spec.rb"
-- "./spec/features/search/user_searches_for_code_spec.rb"
-- "./spec/features/search/user_searches_for_commits_spec.rb"
-- "./spec/features/search/user_searches_for_issues_spec.rb"
-- "./spec/features/search/user_searches_for_merge_requests_spec.rb"
-- "./spec/features/search/user_searches_for_milestones_spec.rb"
-- "./spec/features/search/user_searches_for_projects_spec.rb"
-- "./spec/features/search/user_searches_for_users_spec.rb"
-- "./spec/features/search/user_searches_for_wiki_pages_spec.rb"
-- "./spec/features/search/user_uses_header_search_field_spec.rb"
-- "./spec/features/search/user_uses_search_filters_spec.rb"
- "./spec/features/signed_commits_spec.rb"
-- "./spec/features/snippets/embedded_snippet_spec.rb"
-- "./spec/features/snippets/internal_snippet_spec.rb"
-- "./spec/features/snippets/notes_on_personal_snippets_spec.rb"
-- "./spec/features/snippets/private_snippets_spec.rb"
-- "./spec/features/snippets/public_snippets_spec.rb"
-- "./spec/features/snippets/show_spec.rb"
-- "./spec/features/snippets/user_creates_snippet_spec.rb"
-- "./spec/features/snippets/user_deletes_snippet_spec.rb"
-- "./spec/features/snippets/user_edits_snippet_spec.rb"
-- "./spec/features/tags/developer_creates_tag_spec.rb"
-- "./spec/features/tags/developer_deletes_tag_spec.rb"
-- "./spec/features/tags/developer_updates_tag_spec.rb"
-- "./spec/features/task_lists_spec.rb"
-- "./spec/features/triggers_spec.rb"
-- "./spec/features/u2f_spec.rb"
-- "./spec/features/uploads/user_uploads_avatar_to_profile_spec.rb"
-- "./spec/features/uploads/user_uploads_file_to_note_spec.rb"
-- "./spec/features/user_can_display_performance_bar_spec.rb"
-- "./spec/features/user_opens_link_to_comment_spec.rb"
-- "./spec/features/user_sees_revert_modal_spec.rb"
-- "./spec/features/users/login_spec.rb"
-- "./spec/features/users/logout_spec.rb"
-- "./spec/features/users/overview_spec.rb"
-- "./spec/features/users/signup_spec.rb"
-- "./spec/features/users/snippets_spec.rb"
-- "./spec/features/users/terms_spec.rb"
-- "./spec/features/users/user_browses_projects_on_user_page_spec.rb"
-- "./spec/features/webauthn_spec.rb"
-- "./spec/features/whats_new_spec.rb"
-- "./spec/finders/ci/pipeline_schedules_finder_spec.rb"
-- "./spec/finders/ci/pipelines_finder_spec.rb"
-- "./spec/finders/ci/pipelines_for_merge_request_finder_spec.rb"
-- "./spec/finders/projects_finder_spec.rb"
-- "./spec/finders/releases/evidence_pipeline_finder_spec.rb"
-- "./spec/frontend/fixtures/analytics.rb"
-- "./spec/frontend/fixtures/jobs.rb"
-- "./spec/frontend/fixtures/pipeline_schedules.rb"
-- "./spec/frontend/fixtures/pipelines.rb"
-- "./spec/graphql/mutations/design_management/upload_spec.rb"
-- "./spec/graphql/mutations/merge_requests/accept_spec.rb"
-- "./spec/graphql/resolvers/ci/test_report_summary_resolver_spec.rb"
- "./spec/helpers/issuables_helper_spec.rb"
-- "./spec/initializers/active_record_locking_spec.rb"
-- "./spec/initializers/database_config_spec.rb"
- "./spec/lib/gitlab/auth_spec.rb"
-- "./spec/lib/gitlab/ci/badge/pipeline/status_spec.rb"
-- "./spec/lib/gitlab/ci/build/policy/changes_spec.rb"
-- "./spec/lib/gitlab/ci/charts_spec.rb"
-- "./spec/lib/gitlab/ci/config_spec.rb"
- "./spec/lib/gitlab/ci/pipeline/chain/create_spec.rb"
- "./spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb"
- "./spec/lib/gitlab/ci/pipeline/seed/build_spec.rb"
-- "./spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb"
-- "./spec/lib/gitlab/ci/status/stage/common_spec.rb"
-- "./spec/lib/gitlab/ci/status/stage/factory_spec.rb"
-- "./spec/lib/gitlab/ci/status/stage/play_manual_spec.rb"
- "./spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb"
-- "./spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb"
- "./spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb"
- "./spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb"
+- "./spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb"
- "./spec/lib/gitlab/ci/templates/managed_cluster_applications_gitlab_ci_yaml_spec.rb"
-- "./spec/lib/gitlab/database/bulk_update_spec.rb"
-- "./spec/lib/gitlab/database/connection_spec.rb"
-- "./spec/lib/gitlab/database/load_balancing/host_spec.rb"
-- "./spec/lib/gitlab/database/load_balancing_spec.rb"
-- "./spec/lib/gitlab/database/postgresql_adapter/force_disconnectable_mixin_spec.rb"
-- "./spec/lib/gitlab/database/postgresql_adapter/type_map_cache_spec.rb"
-- "./spec/lib/gitlab/database/schema_migrations/context_spec.rb"
-- "./spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb"
-- "./spec/lib/gitlab/database/with_lock_retries_spec.rb"
-- "./spec/lib/gitlab/data_builder/pipeline_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/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb"
-- "./spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb"
-- "./spec/lib/gitlab/usage_data_spec.rb"
- "./spec/lib/peek/views/active_record_spec.rb"
-- "./spec/mailers/emails/pipelines_spec.rb"
-- "./spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb"
-- "./spec/migrations/20210722150102_operations_feature_flags_correct_flexible_rollout_values_spec.rb"
-- "./spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb"
-- "./spec/migrations/insert_ci_daily_pipeline_schedule_triggers_plan_limits_spec.rb"
-- "./spec/migrations/remove_duplicate_dast_site_tokens_with_same_token_spec.rb"
-- "./spec/models/ci/bridge_spec.rb"
- "./spec/models/ci/build_need_spec.rb"
-- "./spec/models/ci/build_spec.rb"
- "./spec/models/ci/build_trace_chunk_spec.rb"
-- "./spec/models/ci/commit_with_pipeline_spec.rb"
-- "./spec/models/ci/group_spec.rb"
- "./spec/models/ci/group_variable_spec.rb"
-- "./spec/models/ci/instance_variable_spec.rb"
- "./spec/models/ci/job_artifact_spec.rb"
- "./spec/models/ci/job_variable_spec.rb"
-- "./spec/models/ci/legacy_stage_spec.rb"
-- "./spec/models/ci/pipeline_schedule_spec.rb"
- "./spec/models/ci/pipeline_spec.rb"
-- "./spec/models/ci/runner_namespace_spec.rb"
-- "./spec/models/ci/runner_project_spec.rb"
- "./spec/models/ci/runner_spec.rb"
-- "./spec/models/ci/running_build_spec.rb"
-- "./spec/models/ci/stage_spec.rb"
- "./spec/models/ci/variable_spec.rb"
-- "./spec/models/clusters/applications/jupyter_spec.rb"
- "./spec/models/clusters/applications/runner_spec.rb"
-- "./spec/models/commit_collection_spec.rb"
- "./spec/models/commit_status_spec.rb"
- "./spec/models/concerns/batch_destroy_dependent_associations_spec.rb"
- "./spec/models/concerns/bulk_insertable_associations_spec.rb"
-- "./spec/models/concerns/cron_schedulable_spec.rb"
- "./spec/models/concerns/has_environment_scope_spec.rb"
-- "./spec/models/concerns/schedulable_spec.rb"
- "./spec/models/concerns/token_authenticatable_spec.rb"
- "./spec/models/design_management/version_spec.rb"
-- "./spec/models/environment_status_spec.rb"
- "./spec/models/hooks/system_hook_spec.rb"
-- "./spec/models/issue_spec.rb"
- "./spec/models/members/project_member_spec.rb"
-- "./spec/models/merge_request_spec.rb"
-- "./spec/models/plan_spec.rb"
-- "./spec/models/project_feature_usage_spec.rb"
-- "./spec/models/project_spec.rb"
- "./spec/models/spam_log_spec.rb"
- "./spec/models/user_spec.rb"
- "./spec/models/user_status_spec.rb"
-- "./spec/policies/ci/build_policy_spec.rb"
-- "./spec/policies/ci/pipeline_policy_spec.rb"
-- "./spec/presenters/ci/stage_presenter_spec.rb"
-- "./spec/requests/api/admin/ci/variables_spec.rb"
-- "./spec/requests/api/admin/plan_limits_spec.rb"
-- "./spec/requests/api/ci/jobs_spec.rb"
- "./spec/requests/api/ci/pipeline_schedules_spec.rb"
- "./spec/requests/api/ci/pipelines_spec.rb"
-- "./spec/requests/api/ci/runner/runners_post_spec.rb"
-- "./spec/requests/api/ci/runners_spec.rb"
-- "./spec/requests/api/commits_spec.rb"
- "./spec/requests/api/commit_statuses_spec.rb"
-- "./spec/requests/api/graphql/ci/runner_spec.rb"
+- "./spec/requests/api/commits_spec.rb"
- "./spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb"
-- "./spec/requests/api/graphql/project/issues_spec.rb"
-- "./spec/requests/api/graphql/project/merge_request_spec.rb"
-- "./spec/requests/api/graphql/project_query_spec.rb"
-- "./spec/requests/api/issues/issues_spec.rb"
-- "./spec/requests/api/merge_requests_spec.rb"
-- "./spec/requests/api/projects_spec.rb"
- "./spec/requests/api/resource_access_tokens_spec.rb"
- "./spec/requests/api/users_spec.rb"
-- "./spec/requests/lfs_http_spec.rb"
-- "./spec/requests/projects/cycle_analytics_events_spec.rb"
-- "./spec/serializers/ci/downloadable_artifact_entity_spec.rb"
-- "./spec/serializers/ci/downloadable_artifact_serializer_spec.rb"
-- "./spec/serializers/ci/pipeline_entity_spec.rb"
-- "./spec/serializers/merge_request_poll_cached_widget_entity_spec.rb"
-- "./spec/serializers/merge_request_poll_widget_entity_spec.rb"
-- "./spec/serializers/merge_request_widget_entity_spec.rb"
-- "./spec/serializers/pipeline_details_entity_spec.rb"
-- "./spec/serializers/pipeline_serializer_spec.rb"
-- "./spec/serializers/stage_entity_spec.rb"
-- "./spec/serializers/stage_serializer_spec.rb"
-- "./spec/serializers/test_report_entity_spec.rb"
-- "./spec/serializers/test_report_summary_entity_spec.rb"
-- "./spec/serializers/test_suite_entity_spec.rb"
-- "./spec/serializers/test_suite_summary_entity_spec.rb"
-- "./spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb"
-- "./spec/services/ci/compare_accessibility_reports_service_spec.rb"
-- "./spec/services/ci/compare_codequality_reports_service_spec.rb"
-- "./spec/services/ci/compare_reports_base_service_spec.rb"
-- "./spec/services/ci/compare_test_reports_service_spec.rb"
- "./spec/services/ci/create_pipeline_service/environment_spec.rb"
- "./spec/services/ci/create_pipeline_service_spec.rb"
- "./spec/services/ci/destroy_pipeline_service_spec.rb"
-- "./spec/services/ci/disable_user_pipeline_schedules_service_spec.rb"
- "./spec/services/ci/ensure_stage_service_spec.rb"
- "./spec/services/ci/expire_pipeline_cache_service_spec.rb"
-- "./spec/services/ci/generate_codequality_mr_diff_report_service_spec.rb"
-- "./spec/services/ci/generate_coverage_reports_service_spec.rb"
- "./spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb"
- "./spec/services/ci/job_artifacts/destroy_associations_service_spec.rb"
-- "./spec/services/ci/job_artifacts/destroy_batch_service_spec.rb"
-- "./spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb"
-- "./spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb"
- "./spec/services/ci/pipeline_bridge_status_service_spec.rb"
-- "./spec/services/ci/pipeline_processing/shared_processing_service.rb"
- "./spec/services/ci/pipelines/add_job_service_spec.rb"
-- "./spec/services/ci/pipeline_schedule_service_spec.rb"
-- "./spec/services/ci/pipeline_trigger_service_spec.rb"
-- "./spec/services/ci/register_job_service_spec.rb"
- "./spec/services/ci/retry_build_service_spec.rb"
-- "./spec/services/ci/test_failure_history_service_spec.rb"
-- "./spec/services/ci/update_instance_variables_service_spec.rb"
-- "./spec/services/deployments/update_environment_service_spec.rb"
-- "./spec/services/design_management/save_designs_service_spec.rb"
-- "./spec/services/environments/stop_service_spec.rb"
- "./spec/services/groups/transfer_service_spec.rb"
-- "./spec/services/integrations/test/project_service_spec.rb"
-- "./spec/services/issuable/destroy_service_spec.rb"
-- "./spec/services/issue_links/list_service_spec.rb"
-- "./spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb"
-- "./spec/services/merge_requests/mergeability_check_service_spec.rb"
-- "./spec/services/merge_requests/post_merge_service_spec.rb"
-- "./spec/services/merge_requests/refresh_service_spec.rb"
-- "./spec/services/pages/migrate_from_legacy_storage_service_spec.rb"
- "./spec/services/projects/destroy_service_spec.rb"
+- "./spec/services/projects/overwrite_project_service_spec.rb"
- "./spec/services/projects/transfer_service_spec.rb"
-- "./spec/services/projects/update_service_spec.rb"
-- "./spec/services/releases/create_service_spec.rb"
- "./spec/services/resource_access_tokens/revoke_service_spec.rb"
-- "./spec/services/todo_service_spec.rb"
-- "./spec/services/users/activity_service_spec.rb"
- "./spec/services/users/destroy_service_spec.rb"
- "./spec/services/users/reject_service_spec.rb"
-- "./spec/support/shared_contexts/email_shared_context.rb"
-- "./spec/support/shared_examples/controllers/access_tokens_controller_shared_examples.rb"
-- "./spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb"
-- "./spec/support/shared_examples/integrations/test_examples.rb"
-- "./spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb"
-- "./spec/support/shared_examples/models/cluster_application_status_shared_examples.rb"
-- "./spec/support/shared_examples/models/cluster_application_version_shared_examples.rb"
-- "./spec/support/shared_examples/models/concerns/cron_schedulable_shared_examples.rb"
-- "./spec/support/shared_examples/models/concerns/limitable_shared_examples.rb"
-- "./spec/support/shared_examples/models/update_highest_role_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/requests/api/status_shared_examples.rb"
-- "./spec/support/shared_examples/requests/lfs_http_shared_examples.rb"
-- "./spec/support/shared_examples/services/destroy_label_links_shared_examples.rb"
-- "./spec/support/shared_examples/services/issuable/destroy_service_shared_examples.rb"
-- "./spec/support/shared_examples/services/notification_service_shared_examples.rb"
-- "./spec/support/shared_examples/services/wiki_pages/create_service_shared_examples.rb"
-- "./spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb"
-- "./spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb"
-- "./spec/support/shared_examples/workers/idempotency_shared_examples.rb"
-- "./spec/views/projects/artifacts/_artifact.html.haml_spec.rb"
-- "./spec/views/projects/commits/_commit.html.haml_spec.rb"
-- "./spec/views/projects/jobs/_build.html.haml_spec.rb"
-- "./spec/views/projects/jobs/_generic_commit_status.html.haml_spec.rb"
-- "./spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb"
-- "./spec/views/projects/pipeline_schedules/_pipeline_schedule.html.haml_spec.rb"
-- "./spec/views/shared/runners/_runner_details.html.haml_spec.rb"
-- "./spec/workers/authorized_project_update/user_refresh_from_replica_worker_spec.rb"
-- "./spec/workers/ci/pipeline_artifacts/create_quality_report_worker_spec.rb"
-- "./spec/workers/container_expiration_policy_worker_spec.rb"
- "./spec/workers/merge_requests/create_pipeline_worker_spec.rb"
-- "./spec/workers/pipeline_metrics_worker_spec.rb"
-- "./spec/workers/pipeline_schedule_worker_spec.rb"
-- "./spec/workers/releases/create_evidence_worker_spec.rb"
- "./spec/workers/remove_expired_members_worker_spec.rb"
- "./spec/workers/repository_cleanup_worker_spec.rb"
-- "./spec/workers/stage_update_worker_spec.rb"
-- "./spec/workers/stuck_merge_jobs_worker_spec.rb"
-- "./ee/spec/requests/api/graphql/project/pipelines/dast_profile_spec.rb"
-- "./spec/services/projects/overwrite_project_service_spec.rb"
diff --git a/spec/support/database/cross-join-allowlist.yml b/spec/support/database/cross-join-allowlist.yml
index c209d275fc8..19b1ce30d5f 100644
--- a/spec/support/database/cross-join-allowlist.yml
+++ b/spec/support/database/cross-join-allowlist.yml
@@ -1,58 +1,6 @@
-- "./ee/spec/features/ci/ci_minutes_spec.rb"
-- "./ee/spec/features/merge_trains/two_merge_requests_on_train_spec.rb"
-- "./ee/spec/features/merge_trains/user_adds_merge_request_to_merge_train_spec.rb"
-- "./ee/spec/finders/ee/namespaces/projects_finder_spec.rb"
-- "./ee/spec/graphql/ee/resolvers/namespace_projects_resolver_spec.rb"
-- "./ee/spec/models/ci/minutes/project_monthly_usage_spec.rb"
-- "./ee/spec/models/project_spec.rb"
-- "./ee/spec/models/security/finding_spec.rb"
-- "./ee/spec/models/security/scan_spec.rb"
-- "./ee/spec/requests/api/ci/minutes_spec.rb"
-- "./ee/spec/requests/api/graphql/ci/minutes/usage_spec.rb"
-- "./ee/spec/requests/api/namespaces_spec.rb"
-- "./ee/spec/services/ci/minutes/additional_packs/change_namespace_service_spec.rb"
-- "./ee/spec/services/ci/minutes/additional_packs/create_service_spec.rb"
-- "./ee/spec/services/ci/minutes/refresh_cached_data_service_spec.rb"
-- "./spec/controllers/admin/runners_controller_spec.rb"
-- "./spec/controllers/groups/settings/ci_cd_controller_spec.rb"
-- "./spec/controllers/projects/settings/ci_cd_controller_spec.rb"
-- "./spec/features/admin/admin_runners_spec.rb"
-- "./spec/features/ide/user_opens_merge_request_spec.rb"
-- "./spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb"
-- "./spec/features/projects/infrastructure_registry_spec.rb"
-- "./spec/finders/ci/pipelines_for_merge_request_finder_spec.rb"
-- "./spec/finders/ci/runners_finder_spec.rb"
-- "./spec/frontend/fixtures/runner.rb"
-- "./spec/graphql/resolvers/ci/group_runners_resolver_spec.rb"
-- "./spec/lib/api/entities/package_spec.rb"
- "./spec/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans_spec.rb"
- "./spec/lib/gitlab/background_migration/migrate_pages_metadata_spec.rb"
- "./spec/migrations/20210907211557_finalize_ci_builds_bigint_conversion_spec.rb"
- "./spec/migrations/associate_existing_dast_builds_with_variables_spec.rb"
+- "./spec/migrations/disable_job_token_scope_when_unused_spec.rb"
- "./spec/migrations/schedule_copy_ci_builds_columns_to_security_scans2_spec.rb"
-- "./spec/migrations/schedule_pages_metadata_migration_spec.rb"
-- "./spec/models/ci/pipeline_spec.rb"
-- "./spec/models/ci/runner_spec.rb"
-- "./spec/models/merge_request_spec.rb"
-- "./spec/models/project_spec.rb"
-- "./spec/models/user_spec.rb"
-- "./spec/presenters/packages/detail/package_presenter_spec.rb"
-- "./spec/requests/api/ci/runner/runners_post_spec.rb"
-- "./spec/requests/api/ci/runners_spec.rb"
-- "./spec/requests/api/graphql/ci/runner_spec.rb"
-- "./spec/requests/api/graphql/group_query_spec.rb"
-- "./spec/requests/api/graphql/packages/composer_spec.rb"
-- "./spec/requests/api/graphql/packages/conan_spec.rb"
-- "./spec/requests/api/graphql/packages/maven_spec.rb"
-- "./spec/requests/api/graphql/packages/nuget_spec.rb"
-- "./spec/requests/api/graphql/packages/package_spec.rb"
-- "./spec/requests/api/graphql/packages/pypi_spec.rb"
-- "./spec/requests/api/package_files_spec.rb"
-- "./spec/services/environments/stop_service_spec.rb"
-- "./spec/services/merge_requests/post_merge_service_spec.rb"
-- "./spec/support/shared_examples/features/packages_shared_examples.rb"
-- "./spec/support/shared_examples/models/concerns/limitable_shared_examples.rb"
-- "./spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb"
-- "./spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb"
-- "./spec/support/shared_examples/requests/graphql_shared_examples.rb"
-- "./spec/support/shared_examples/services/packages_shared_examples.rb"
diff --git a/spec/support/database/gitlab_schema.rb b/spec/support/database/gitlab_schema.rb
deleted file mode 100644
index fe05fb998e6..00000000000
--- a/spec/support/database/gitlab_schema.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-# This module gathes information about table to schema mapping
-# to understand table affinity
-module Database
- module GitlabSchema
- def self.table_schemas(tables)
- tables.map { |table| table_schema(table) }.to_set
- end
-
- def self.table_schema(name)
- tables_to_schema[name] || :undefined
- end
-
- def self.tables_to_schema
- @tables_to_schema ||= all_classes_with_schema.to_h do |klass|
- [klass.table_name, klass.gitlab_schema]
- end
- end
-
- def self.all_classes_with_schema
- ActiveRecord::Base.descendants.reject(&:abstract_class?).select(&:gitlab_schema?) # rubocop:disable Database/MultipleDatabases
- end
- end
-end
diff --git a/spec/support/database/multiple_databases.rb b/spec/support/database/multiple_databases.rb
index 5e1ae60536f..9e72ea589e3 100644
--- a/spec/support/database/multiple_databases.rb
+++ b/spec/support/database/multiple_databases.rb
@@ -6,6 +6,18 @@ module Database
skip 'Skipping because multiple databases not set up' unless Gitlab::Database.has_config?(:ci)
end
+ def reconfigure_db_connection(name: nil, config_hash: {}, model: ActiveRecord::Base, config_model: nil)
+ db_config = (config_model || model).connection_db_config
+
+ new_db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(
+ db_config.env_name,
+ name ? name.to_s : db_config.name,
+ db_config.configuration_hash.merge(config_hash)
+ )
+
+ model.establish_connection(new_db_config)
+ end
+
# The usage of this method switches temporarily used `connection_handler`
# allowing full manipulation of ActiveRecord::Base connections without
# having side effects like:
@@ -56,6 +68,21 @@ RSpec.configure do |config|
example.run
end
end
+
+ config.around(:each, :mocked_ci_connection) do |example|
+ with_reestablished_active_record_base(reconnect: true) do
+ reconfigure_db_connection(
+ name: :ci,
+ model: Ci::ApplicationRecord,
+ config_model: ActiveRecord::Base
+ )
+
+ example.run
+
+ # Cleanup connection_specification_name for Ci::ApplicationRecord
+ Ci::ApplicationRecord.remove_connection
+ end
+ end
end
ActiveRecord::Base.singleton_class.prepend(::Database::ActiveRecordBaseEstablishConnection) # rubocop:disable Database/MultipleDatabases
diff --git a/spec/support/database/prevent_cross_database_modification.rb b/spec/support/database/prevent_cross_database_modification.rb
index 7ded85b65ce..c509aecf9b8 100644
--- a/spec/support/database/prevent_cross_database_modification.rb
+++ b/spec/support/database/prevent_cross_database_modification.rb
@@ -1,123 +1,31 @@
# frozen_string_literal: true
-module Database
- module PreventCrossDatabaseModification
- CrossDatabaseModificationAcrossUnsupportedTablesError = Class.new(StandardError)
-
- module GitlabDatabaseMixin
- def allow_cross_database_modification_within_transaction(url:)
- cross_database_context = Database::PreventCrossDatabaseModification.cross_database_context
- return yield unless cross_database_context && cross_database_context[:enabled]
-
- transaction_tracker_enabled_was = cross_database_context[:enabled]
- cross_database_context[:enabled] = false
-
- yield
- ensure
- cross_database_context[:enabled] = transaction_tracker_enabled_was if cross_database_context
- end
- end
-
- module SpecHelpers
- def with_cross_database_modification_prevented
- subscriber = ActiveSupport::Notifications.subscribe('sql.active_record') do |name, start, finish, id, payload|
- PreventCrossDatabaseModification.prevent_cross_database_modification!(payload[:connection], payload[:sql])
- end
-
- PreventCrossDatabaseModification.reset_cross_database_context!
- PreventCrossDatabaseModification.cross_database_context.merge!(enabled: true, subscriber: subscriber)
-
- yield if block_given?
- ensure
- cleanup_with_cross_database_modification_prevented if block_given?
- end
-
- def cleanup_with_cross_database_modification_prevented
- if PreventCrossDatabaseModification.cross_database_context
- ActiveSupport::Notifications.unsubscribe(PreventCrossDatabaseModification.cross_database_context[:subscriber])
- PreventCrossDatabaseModification.cross_database_context[:enabled] = false
- end
- end
- end
-
- def self.cross_database_context
- Thread.current[:transaction_tracker]
- end
-
- def self.reset_cross_database_context!
- Thread.current[:transaction_tracker] = initial_data
- end
-
- def self.initial_data
- {
- enabled: false,
- transaction_depth_by_db: Hash.new { |h, k| h[k] = 0 },
- modified_tables_by_db: Hash.new { |h, k| h[k] = Set.new }
- }
- end
-
- def self.prevent_cross_database_modification!(connection, sql)
- return unless cross_database_context
- return unless cross_database_context[:enabled]
-
- return if connection.pool.instance_of?(ActiveRecord::ConnectionAdapters::NullPool)
-
- database = connection.pool.db_config.name
-
- if sql.start_with?('SAVEPOINT')
- cross_database_context[:transaction_depth_by_db][database] += 1
-
- return
- elsif sql.start_with?('RELEASE SAVEPOINT', 'ROLLBACK TO SAVEPOINT')
- cross_database_context[:transaction_depth_by_db][database] -= 1
- if cross_database_context[:transaction_depth_by_db][database] <= 0
- cross_database_context[:modified_tables_by_db][database].clear
- end
-
- return
- end
-
- return if cross_database_context[:transaction_depth_by_db].values.all?(&:zero?)
-
- # PgQuery might fail in some cases due to limited nesting:
- # https://github.com/pganalyze/pg_query/issues/209
- parsed_query = PgQuery.parse(sql)
- tables = sql.downcase.include?(' for update') ? parsed_query.tables : parsed_query.dml_tables
-
- return if tables.empty?
-
- cross_database_context[:modified_tables_by_db][database].merge(tables)
-
- all_tables = cross_database_context[:modified_tables_by_db].values.map(&:to_a).flatten
- schemas = Database::GitlabSchema.table_schemas(all_tables)
-
- if schemas.many?
- raise Database::PreventCrossDatabaseModification::CrossDatabaseModificationAcrossUnsupportedTablesError,
- "Cross-database data modification of '#{schemas.to_a.join(", ")}' were detected within " \
- "a transaction modifying the '#{all_tables.to_a.join(", ")}' tables." \
- "Please refer to https://docs.gitlab.com/ee/development/database/multiple_databases.html#removing-cross-database-transactions for details on how to resolve this exception."
- end
- end
- end
+module PreventCrossDatabaseModificationSpecHelpers
+ delegate :with_cross_database_modification_prevented,
+ :allow_cross_database_modification_within_transaction,
+ to: :'::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification'
end
-Gitlab::Database.singleton_class.prepend(
- Database::PreventCrossDatabaseModification::GitlabDatabaseMixin)
-
CROSS_DB_MODIFICATION_ALLOW_LIST = Set.new(YAML.load_file(File.join(__dir__, 'cross-database-modification-allowlist.yml'))).freeze
RSpec.configure do |config|
- config.include(::Database::PreventCrossDatabaseModification::SpecHelpers)
+ config.include(PreventCrossDatabaseModificationSpecHelpers)
+
+ # By default allow cross-modifications as we want to observe only transactions
+ # within a specific block of execution which is defined be `before(:each)` and `after(:each)`
+ config.before(:all) do
+ ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.suppress = true
+ end
# Using before and after blocks because the around block causes problems with the let_it_be
# record creations. It makes an extra savepoint which breaks the transaction count logic.
config.before do |example_file|
- if CROSS_DB_MODIFICATION_ALLOW_LIST.exclude?(example_file.file_path)
- with_cross_database_modification_prevented
- end
+ ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.suppress =
+ CROSS_DB_MODIFICATION_ALLOW_LIST.include?(example_file.file_path_rerun_argument)
end
+ # Reset after execution to preferred state
config.after do |example_file|
- cleanup_with_cross_database_modification_prevented
+ ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.suppress = true
end
end
diff --git a/spec/support/database/prevent_cross_joins.rb b/spec/support/database/prevent_cross_joins.rb
index f5ed2a8f22e..e69374fbc70 100644
--- a/spec/support/database/prevent_cross_joins.rb
+++ b/spec/support/database/prevent_cross_joins.rb
@@ -35,7 +35,7 @@ module Database
# https://github.com/pganalyze/pg_query/issues/209
tables = PgQuery.parse(sql).tables
- schemas = Database::GitlabSchema.table_schemas(tables)
+ schemas = ::Gitlab::Database::GitlabSchema.table_schemas(tables)
if schemas.include?(:gitlab_ci) && schemas.include?(:gitlab_main)
Thread.current[:has_cross_join_exception] = true
@@ -96,7 +96,7 @@ RSpec.configure do |config|
config.around do |example|
Thread.current[:has_cross_join_exception] = false
- if ALLOW_LIST.include?(example.file_path)
+ if ALLOW_LIST.include?(example.file_path_rerun_argument)
example.run
else
with_cross_joins_prevented { example.run }
diff --git a/spec/support/database/query_analyzer.rb b/spec/support/database/query_analyzer.rb
new file mode 100644
index 00000000000..85fa55f81ef
--- /dev/null
+++ b/spec/support/database/query_analyzer.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+# With the usage of `describe '...', query_analyzers: false`
+# can be disabled selectively
+
+RSpec.configure do |config|
+ config.around do |example|
+ if example.metadata.fetch(:query_analyzers, true)
+ ::Gitlab::Database::QueryAnalyzer.instance.within { example.run }
+ else
+ example.run
+ end
+ end
+end
diff --git a/spec/support/database_load_balancing.rb b/spec/support/database_load_balancing.rb
index 014575e8a82..d2902ddcc7c 100644
--- a/spec/support/database_load_balancing.rb
+++ b/spec/support/database_load_balancing.rb
@@ -2,17 +2,17 @@
RSpec.configure do |config|
config.around(:each, :database_replica) do |example|
- old_proxies = []
+ old_proxies = {}
Gitlab::Database::LoadBalancing.base_models.each do |model|
+ old_proxies[model] = [model.load_balancer, model.connection, model.sticking]
+
config = Gitlab::Database::LoadBalancing::Configuration
.new(model, [model.connection_db_config.configuration_hash[:host]])
- lb = Gitlab::Database::LoadBalancing::LoadBalancer.new(config)
-
- old_proxies << [model, model.connection]
- model.connection =
- Gitlab::Database::LoadBalancing::ConnectionProxy.new(lb)
+ model.load_balancer = Gitlab::Database::LoadBalancing::LoadBalancer.new(config)
+ model.sticking = Gitlab::Database::LoadBalancing::Sticking.new(model.load_balancer)
+ model.connection = Gitlab::Database::LoadBalancing::ConnectionProxy.new(model.load_balancer)
end
Gitlab::Database::LoadBalancing::Session.clear_session
@@ -23,8 +23,8 @@ RSpec.configure do |config|
Gitlab::Database::LoadBalancing::Session.clear_session
redis_shared_state_cleanup!
- old_proxies.each do |(model, proxy)|
- model.connection = proxy
+ old_proxies.each do |model, proxy|
+ model.load_balancer, model.connection, model.sticking = proxy
end
end
end
diff --git a/spec/support/flaky_tests.rb b/spec/support/flaky_tests.rb
new file mode 100644
index 00000000000..30a064d8705
--- /dev/null
+++ b/spec/support/flaky_tests.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+return unless ENV['CI']
+return unless ENV['SKIP_FLAKY_TESTS_AUTOMATICALLY'] == "true"
+return if ENV['CI_MERGE_REQUEST_LABELS'].to_s.include?('pipeline:run-flaky-tests')
+
+require_relative '../../tooling/rspec_flaky/report'
+
+RSpec.configure do |config|
+ $flaky_test_example_ids = begin # rubocop:disable Style/GlobalVars
+ raise "$SUITE_FLAKY_RSPEC_REPORT_PATH is empty." if ENV['SUITE_FLAKY_RSPEC_REPORT_PATH'].to_s.empty?
+ raise "#{ENV['SUITE_FLAKY_RSPEC_REPORT_PATH']} doesn't exist" unless File.exist?(ENV['SUITE_FLAKY_RSPEC_REPORT_PATH'])
+
+ RspecFlaky::Report.load(ENV['SUITE_FLAKY_RSPEC_REPORT_PATH']).map { |_, flaky_test_data| flaky_test_data["example_id"] }
+ rescue => e # rubocop:disable Style/RescueStandardError
+ puts e
+ []
+ end
+ $skipped_flaky_tests_report = [] # rubocop:disable Style/GlobalVars
+
+ config.around do |example|
+ # Skip flaky tests automatically
+ if $flaky_test_example_ids.include?(example.id) # rubocop:disable Style/GlobalVars
+ puts "Skipping #{example.id} '#{example.full_description}' because it's flaky."
+ $skipped_flaky_tests_report << example.id # rubocop:disable Style/GlobalVars
+ else
+ example.run
+ end
+ end
+
+ config.after(:suite) do
+ next unless ENV['SKIPPED_FLAKY_TESTS_REPORT_PATH']
+
+ File.write(ENV['SKIPPED_FLAKY_TESTS_REPORT_PATH'], "#{$skipped_flaky_tests_report.join("\n")}\n") # rubocop:disable Style/GlobalVars
+ end
+end
diff --git a/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb b/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb
index de9735df546..4624a8ac82a 100644
--- a/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb
+++ b/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb
@@ -6,7 +6,9 @@ RSpec.shared_examples 'a correct instrumented metric value' do |params|
let(:metric) { described_class.new(time_frame: time_frame, options: options) }
before do
- allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
+ if described_class.respond_to?(:relation) && described_class.relation.respond_to?(:connection)
+ allow(described_class.relation.connection).to receive(:transaction_open?).and_return(false)
+ end
end
it 'has correct value' do
diff --git a/spec/support/graphql/fake_query_type.rb b/spec/support/graphql/fake_query_type.rb
new file mode 100644
index 00000000000..ffd851a6e6a
--- /dev/null
+++ b/spec/support/graphql/fake_query_type.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Graphql
+ class FakeQueryType < Types::BaseObject
+ graphql_name 'FakeQuery'
+
+ field :hello_world, String, null: true do
+ argument :message, String, required: false
+ end
+
+ def hello_world(message: "world")
+ "Hello #{message}!"
+ end
+ end
+end
diff --git a/spec/support/graphql/fake_tracer.rb b/spec/support/graphql/fake_tracer.rb
new file mode 100644
index 00000000000..c2fb7ed12d8
--- /dev/null
+++ b/spec/support/graphql/fake_tracer.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Graphql
+ class FakeTracer
+ def initialize(trace_callback)
+ @trace_callback = trace_callback
+ end
+
+ def trace(*args)
+ @trace_callback.call(*args)
+
+ yield
+ end
+ end
+end
diff --git a/spec/support/helpers/cycle_analytics_helpers.rb b/spec/support/helpers/cycle_analytics_helpers.rb
index 3ec52f8c832..722d484609c 100644
--- a/spec/support/helpers/cycle_analytics_helpers.rb
+++ b/spec/support/helpers/cycle_analytics_helpers.rb
@@ -63,6 +63,10 @@ module CycleAnalyticsHelpers
wait_for_requests
end
+ def click_save_value_stream_button
+ click_button(_('Save value stream'))
+ end
+
def create_custom_value_stream(custom_value_stream_name)
toggle_value_stream_dropdown
page.find_button(_('Create new Value Stream')).click
diff --git a/spec/support/helpers/features/invite_members_modal_helper.rb b/spec/support/helpers/features/invite_members_modal_helper.rb
index 69ba20c1ca4..3502558b2c2 100644
--- a/spec/support/helpers/features/invite_members_modal_helper.rb
+++ b/spec/support/helpers/features/invite_members_modal_helper.rb
@@ -8,7 +8,7 @@ module Spec
def invite_member(name, role: 'Guest', expires_at: nil, area_of_focus: false)
click_on 'Invite members'
- page.within '#invite-members-modal' do
+ page.within '[data-testid="invite-members-modal"]' do
find('[data-testid="members-token-select-input"]').set(name)
wait_for_requests
diff --git a/spec/support/helpers/gitaly_setup.rb b/spec/support/helpers/gitaly_setup.rb
index 5cfd03ecea8..8a329c2f9dd 100644
--- a/spec/support/helpers/gitaly_setup.rb
+++ b/spec/support/helpers/gitaly_setup.rb
@@ -98,7 +98,7 @@ module GitalySetup
end
def build_gitaly
- system(env, 'make', chdir: tmp_tests_gitaly_dir) # rubocop:disable GitlabSecurity/SystemCommandInjection
+ system(env.merge({ 'GIT_VERSION' => nil }), 'make all git', chdir: tmp_tests_gitaly_dir) # rubocop:disable GitlabSecurity/SystemCommandInjection
end
def start_gitaly
diff --git a/spec/support/helpers/gpg_helpers.rb b/spec/support/helpers/gpg_helpers.rb
index 813c6176317..81e669aab57 100644
--- a/spec/support/helpers/gpg_helpers.rb
+++ b/spec/support/helpers/gpg_helpers.rb
@@ -4,6 +4,7 @@ module GpgHelpers
SIGNED_COMMIT_SHA = '8a852d50dda17cc8fd1408d2fd0c5b0f24c76ca4'
SIGNED_AND_AUTHORED_SHA = '3c1d9a0266cb0c62d926f4a6c649beed561846f5'
DIFFERING_EMAIL_SHA = 'a17a9f66543673edf0a3d1c6b93bdda3fe600f32'
+ MULTIPLE_SIGNATURES_SHA = 'c7794c14268d67ad8a2d5f066d706539afc75a96'
module User1
extend self
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index 6f17d3cb496..ee4621deb2d 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -522,8 +522,7 @@ module GraphqlHelpers
end
end
- # See note at graphql_data about memoization and multiple requests
- def graphql_errors(body = json_response)
+ def graphql_errors(body = fresh_response_data)
case body
when Hash # regular query
body['errors']
diff --git a/spec/support/helpers/migrations_helpers.rb b/spec/support/helpers/migrations_helpers.rb
index 7799e49d4c1..0c5bf09f6b7 100644
--- a/spec/support/helpers/migrations_helpers.rb
+++ b/spec/support/helpers/migrations_helpers.rb
@@ -2,7 +2,7 @@
module MigrationsHelpers
def active_record_base
- ActiveRecord::Base
+ Gitlab::Database.database_base_models.fetch(self.class.metadata[:database] || :main)
end
def table(name)
@@ -34,7 +34,7 @@ module MigrationsHelpers
end
def migrations_paths
- ActiveRecord::Migrator.migrations_paths
+ active_record_base.connection.migrations_paths
end
def migration_context
@@ -52,7 +52,7 @@ module MigrationsHelpers
end
def foreign_key_exists?(source, target = nil, column: nil)
- ActiveRecord::Base.connection.foreign_keys(source).any? do |key|
+ active_record_base.connection.foreign_keys(source).any? do |key|
if column
key.options[:column].to_s == column.to_s
else
diff --git a/spec/support/helpers/navbar_structure_helper.rb b/spec/support/helpers/navbar_structure_helper.rb
index 96e79427278..c2ec82155cd 100644
--- a/spec/support/helpers/navbar_structure_helper.rb
+++ b/spec/support/helpers/navbar_structure_helper.rb
@@ -29,6 +29,19 @@ module NavbarStructureHelper
)
end
+ def insert_customer_relations_nav(within)
+ insert_after_nav_item(
+ within,
+ new_nav_item: {
+ nav_item: _('Customer relations'),
+ nav_sub_items: [
+ _('Contacts'),
+ _('Organizations')
+ ]
+ }
+ )
+ end
+
def insert_container_nav
insert_after_sub_nav_item(
_('Package Registry'),
diff --git a/spec/support/helpers/project_forks_helper.rb b/spec/support/helpers/project_forks_helper.rb
index 4b4285f251e..84b5dbc1d23 100644
--- a/spec/support/helpers/project_forks_helper.rb
+++ b/spec/support/helpers/project_forks_helper.rb
@@ -28,11 +28,15 @@ module ProjectForksHelper
unless params[:target_project] || params[:using_service]
target_level = [project.visibility_level, namespace.visibility_level].min
visibility_level = Gitlab::VisibilityLevel.closest_allowed_level(target_level)
+ # Builds and MRs can't have higher visibility level than repository access level.
+ builds_access_level = [project.builds_access_level, project.repository_access_level].min
params[:target_project] =
create(:project,
(:repository if create_repository),
- visibility_level: visibility_level, creator: user, namespace: namespace)
+ visibility_level: visibility_level,
+ builds_access_level: builds_access_level,
+ creator: user, namespace: namespace)
end
service = Projects::ForkService.new(project, user, params)
diff --git a/spec/support/helpers/require_migration.rb b/spec/support/helpers/require_migration.rb
index de3a8a81ab5..ee28f8e504c 100644
--- a/spec/support/helpers/require_migration.rb
+++ b/spec/support/helpers/require_migration.rb
@@ -15,7 +15,7 @@ class RequireMigration
end
MIGRATION_FOLDERS = %w[db/migrate db/post_migrate].freeze
- SPEC_FILE_PATTERN = %r{.+/(?<file_name>.+)_spec\.rb}.freeze
+ SPEC_FILE_PATTERN = %r{.+/(?:\d+_)?(?<file_name>.+)_spec\.rb}.freeze
class << self
def require_migration!(file_name)
@@ -26,10 +26,12 @@ class RequireMigration
end
def search_migration_file(file_name)
+ migration_file_pattern = /\A\d+_#{file_name}\.rb\z/
+
migration_folders.flat_map do |path|
migration_path = Rails.root.join(path).to_s
- Find.find(migration_path).select { |m| File.basename(m).match? /\A\d+_#{file_name}\.rb\z/ }
+ Find.find(migration_path).select { |m| migration_file_pattern.match? File.basename(m) }
end
end
diff --git a/spec/support/helpers/stub_gitlab_calls.rb b/spec/support/helpers/stub_gitlab_calls.rb
index 6f530d57caf..ef3c39c83c2 100644
--- a/spec/support/helpers/stub_gitlab_calls.rb
+++ b/spec/support/helpers/stub_gitlab_calls.rb
@@ -92,9 +92,16 @@ module StubGitlabCalls
end
def stub_commonmark_sourcepos_disabled
+ render_options =
+ if Feature.enabled?(:use_cmark_renderer)
+ Banzai::Filter::MarkdownEngines::CommonMark::RENDER_OPTIONS_C
+ else
+ Banzai::Filter::MarkdownEngines::CommonMark::RENDER_OPTIONS_RUBY
+ end
+
allow_any_instance_of(Banzai::Filter::MarkdownEngines::CommonMark)
.to receive(:render_options)
- .and_return(Banzai::Filter::MarkdownEngines::CommonMark::RENDER_OPTIONS)
+ .and_return(render_options)
end
private
diff --git a/spec/support/helpers/stub_object_storage.rb b/spec/support/helpers/stub_object_storage.rb
index 56177d445d6..5e86b08aa45 100644
--- a/spec/support/helpers/stub_object_storage.rb
+++ b/spec/support/helpers/stub_object_storage.rb
@@ -4,7 +4,6 @@ module StubObjectStorage
def stub_dependency_proxy_object_storage(**params)
stub_object_storage_uploader(config: ::Gitlab.config.dependency_proxy.object_store,
uploader: ::DependencyProxy::FileUploader,
- remote_directory: 'dependency_proxy',
**params)
end
@@ -16,7 +15,6 @@ module StubObjectStorage
def stub_object_storage_uploader(
config:,
uploader:,
- remote_directory:,
enabled: true,
proxy_download: false,
background_upload: false,
@@ -40,7 +38,7 @@ module StubObjectStorage
return unless enabled
stub_object_storage(connection_params: uploader.object_store_credentials,
- remote_directory: remote_directory)
+ remote_directory: config.remote_directory)
end
def stub_object_storage(connection_params:, remote_directory:)
@@ -60,56 +58,48 @@ module StubObjectStorage
def stub_artifacts_object_storage(uploader = JobArtifactUploader, **params)
stub_object_storage_uploader(config: Gitlab.config.artifacts.object_store,
uploader: uploader,
- remote_directory: 'artifacts',
**params)
end
def stub_external_diffs_object_storage(uploader = described_class, **params)
stub_object_storage_uploader(config: Gitlab.config.external_diffs.object_store,
uploader: uploader,
- remote_directory: 'external-diffs',
**params)
end
def stub_lfs_object_storage(**params)
stub_object_storage_uploader(config: Gitlab.config.lfs.object_store,
uploader: LfsObjectUploader,
- remote_directory: 'lfs-objects',
**params)
end
def stub_package_file_object_storage(**params)
stub_object_storage_uploader(config: Gitlab.config.packages.object_store,
uploader: ::Packages::PackageFileUploader,
- remote_directory: 'packages',
**params)
end
def stub_composer_cache_object_storage(**params)
stub_object_storage_uploader(config: Gitlab.config.packages.object_store,
uploader: ::Packages::Composer::CacheUploader,
- remote_directory: 'packages',
**params)
end
def stub_uploads_object_storage(uploader = described_class, **params)
stub_object_storage_uploader(config: Gitlab.config.uploads.object_store,
uploader: uploader,
- remote_directory: 'uploads',
**params)
end
def stub_terraform_state_object_storage(**params)
stub_object_storage_uploader(config: Gitlab.config.terraform_state.object_store,
uploader: Terraform::StateUploader,
- remote_directory: 'terraform',
**params)
end
def stub_pages_object_storage(uploader = described_class, **params)
stub_object_storage_uploader(config: Gitlab.config.pages.object_store,
uploader: uploader,
- remote_directory: 'pages',
**params)
end
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index badd4e8212c..acbc15f7b62 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -9,7 +9,7 @@ module TestEnv
# When developing the seed repository, comment out the branch you will modify.
BRANCH_SHA = {
- 'signed-commits' => '6101e87',
+ 'signed-commits' => 'c7794c1',
'not-merged-branch' => 'b83d6e3',
'branch-merged' => '498214d',
'empty-branch' => '7efb185',
@@ -53,7 +53,7 @@ module TestEnv
'wip' => 'b9238ee',
'csv' => '3dd0896',
'v1.1.0' => 'b83d6e3',
- 'add-ipython-files' => 'f6b7a70',
+ 'add-ipython-files' => '2b5ef814',
'add-pdf-file' => 'e774ebd',
'squash-large-files' => '54cec52',
'add-pdf-text-binary' => '79faa7b',
diff --git a/spec/support/helpers/usage_data_helpers.rb b/spec/support/helpers/usage_data_helpers.rb
index 5ead1813439..5865bafd382 100644
--- a/spec/support/helpers/usage_data_helpers.rb
+++ b/spec/support/helpers/usage_data_helpers.rb
@@ -162,6 +162,8 @@ module UsageDataHelpers
def stub_usage_data_connections
allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
+ allow(::Ci::ApplicationRecord.connection).to receive(:transaction_open?).and_return(false) if ::Ci::ApplicationRecord.connection_class?
+
allow(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(false)
end
diff --git a/spec/support/helpers/workhorse_helpers.rb b/spec/support/helpers/workhorse_helpers.rb
index cd8387de686..83bda6e03b1 100644
--- a/spec/support/helpers/workhorse_helpers.rb
+++ b/spec/support/helpers/workhorse_helpers.rb
@@ -24,7 +24,12 @@ module WorkhorseHelpers
# workhorse_post_with_file will transform file_key inside params as if it was disk accelerated by workhorse
def workhorse_post_with_file(url, file_key:, params:)
- workhorse_request_with_file(:post, url,
+ workhorse_form_with_file(url, method: :post, file_key: file_key, params: params)
+ end
+
+ # workhorse_form_with_file will transform file_key inside params as if it was disk accelerated by workhorse
+ def workhorse_form_with_file(url, file_key:, params:, method: :post)
+ workhorse_request_with_file(method, url,
file_key: file_key,
params: params,
env: { 'CONTENT_TYPE' => 'multipart/form-data' },
diff --git a/spec/support/matchers/access_matchers.rb b/spec/support/matchers/access_matchers.rb
index acf5fb0944f..1b460fbdbf7 100644
--- a/spec/support/matchers/access_matchers.rb
+++ b/spec/support/matchers/access_matchers.rb
@@ -52,7 +52,7 @@ module AccessMatchers
emulate_user(user, @membership)
visit(url)
- status_code == 200 && !current_path.in?([new_user_session_path, new_admin_session_path])
+ [200, 204].include?(status_code) && !current_path.in?([new_user_session_path, new_admin_session_path])
end
chain :of do |membership|
diff --git a/spec/support/matchers/project_namespace_matcher.rb b/spec/support/matchers/project_namespace_matcher.rb
new file mode 100644
index 00000000000..95aa5429679
--- /dev/null
+++ b/spec/support/matchers/project_namespace_matcher.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+RSpec::Matchers.define :be_in_sync_with_project do |project|
+ match do |project_namespace|
+ # if project is not persisted make sure we do not have a persisted project_namespace for it
+ break false if project.new_record? && project_namespace&.persisted?
+ # don't really care if project is not in sync if the project was never persisted.
+ break true if project.new_record? && !project_namespace.present?
+
+ project_namespace.present? &&
+ project.name == project_namespace.name &&
+ project.path == project_namespace.path &&
+ project.namespace == project_namespace.parent &&
+ project.visibility_level == project_namespace.visibility_level &&
+ project.shared_runners_enabled == project_namespace.shared_runners_enabled
+ end
+
+ failure_message_when_negated do |project_namespace|
+ if project.new_record? && project_namespace&.persisted?
+ "expected that a non persisted project #{project} does not have a persisted project namespace #{project_namespace}"
+ else
+ <<-MSG
+ expected that the project's attributes name, path, namespace_id, visibility_level, shared_runners_enabled
+ are in sync with the corresponding project namespace attributes
+ MSG
+ end
+ end
+end
diff --git a/spec/support/patches/rspec_example_prepended_methods.rb b/spec/support/patches/rspec_example_prepended_methods.rb
new file mode 100644
index 00000000000..ea918b1e08f
--- /dev/null
+++ b/spec/support/patches/rspec_example_prepended_methods.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module RSpec
+ module Core
+ module ExamplePrependedMethods
+ # Based on https://github.com/rspec/rspec-core/blob/d57c371ee92b16211b80ac7b0b025968438f5297/lib/rspec/core/example.rb#L96-L104,
+ # Same as location_rerun_argument but with line number
+ def file_path_rerun_argument
+ loaded_spec_files = RSpec.configuration.loaded_spec_files
+
+ RSpec::Core::Metadata.ascending(metadata) do |meta|
+ break meta[:file_path] if loaded_spec_files.include?(meta[:absolute_file_path])
+ end
+ end
+ end
+
+ module ExampleProcsyPrependedMethods
+ def file_path_rerun_argument
+ example.file_path_rerun_argument
+ end
+ end
+ end
+end
+
+RSpec::Core::Example.prepend(RSpec::Core::ExamplePrependedMethods)
+RSpec::Core::Example::Procsy.prepend(RSpec::Core::ExampleProcsyPrependedMethods)
diff --git a/spec/support/redis/redis_shared_examples.rb b/spec/support/redis/redis_shared_examples.rb
index dd916aea3e8..72b3a72f9d4 100644
--- a/spec/support/redis/redis_shared_examples.rb
+++ b/spec/support/redis/redis_shared_examples.rb
@@ -87,6 +87,43 @@ RSpec.shared_examples "redis_shared_examples" do
end
end
+ describe '.store' do
+ let(:rails_env) { 'development' }
+
+ subject { described_class.new(rails_env).store }
+
+ shared_examples 'redis store' do
+ it 'instantiates Redis::Store' do
+ is_expected.to be_a(::Redis::Store)
+ expect(subject.to_s).to eq("Redis Client connected to #{host} against DB #{redis_database}")
+ end
+
+ context 'with the namespace' do
+ let(:namespace) { 'namespace_name' }
+
+ subject { described_class.new(rails_env).store(namespace: namespace) }
+
+ it "uses specified namespace" do
+ expect(subject.to_s).to eq("Redis Client connected to #{host} against DB #{redis_database} with namespace #{namespace}")
+ end
+ end
+ end
+
+ context 'with old format' do
+ it_behaves_like 'redis store' do
+ let(:config_file_name) { config_old_format_host }
+ let(:host) { "localhost:#{redis_port}" }
+ end
+ end
+
+ context 'with new format' do
+ it_behaves_like 'redis store' do
+ let(:config_file_name) { config_new_format_host }
+ let(:host) { "development-host:#{redis_port}" }
+ end
+ end
+ end
+
describe '.params' do
subject { described_class.new(rails_env).params }
diff --git a/spec/support/retriable.rb b/spec/support/retriable.rb
new file mode 100644
index 00000000000..be4c2d62752
--- /dev/null
+++ b/spec/support/retriable.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+Retriable.configure do |config|
+ config.multiplier = 1.0
+ config.rand_factor = 0.0
+ config.base_interval = 0
+end
diff --git a/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb b/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb
index 645ea742f07..9ac3d4a04f9 100644
--- a/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb
+++ b/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb
@@ -10,6 +10,7 @@ RSpec.shared_context 'package details setup' do
let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline packageFiles] }
let(:package_files) { all_graphql_fields_for('PackageFile') }
let(:dependency_links) { all_graphql_fields_for('PackageDependencyLink') }
+ let(:pipelines) { all_graphql_fields_for('Pipeline', max_depth: 1) }
let(:user) { project.owner }
let(:package_details) { graphql_data_at(:package) }
let(:metadata_response) { graphql_data_at(:package, :metadata) }
@@ -34,6 +35,11 @@ RSpec.shared_context 'package details setup' do
#{dependency_links}
}
}
+ pipelines {
+ nodes {
+ #{pipelines}
+ }
+ }
FIELDS
end
end
diff --git a/spec/support/shared_contexts/lib/gitlab/database/background_migration_job_shared_context.rb b/spec/support/shared_contexts/lib/gitlab/database/background_migration_job_shared_context.rb
deleted file mode 100644
index 382eb796f8e..00000000000
--- a/spec/support/shared_contexts/lib/gitlab/database/background_migration_job_shared_context.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_context 'background migration job class' do
- let!(:job_class_name) { 'TestJob' }
- let!(:job_class) { Class.new }
- let!(:job_perform_method) do
- ->(*arguments) do
- Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
- # Value is 'TestJob' defined by :job_class_name in the let! above.
- # Scoping prohibits us from directly referencing job_class_name.
- RSpec.current_example.example_group_instance.job_class_name,
- arguments
- )
- end
- end
-
- before do
- job_class.define_method(:perform, job_perform_method)
- expect(Gitlab::BackgroundMigration).to receive(:migration_class_for).with(job_class_name).at_least(:once) { job_class }
- end
-end
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index 2abc52fce85..bcc6abdc308 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -119,7 +119,7 @@ RSpec.shared_context 'project navbar structure' do
_('Repository'),
_('CI/CD'),
_('Monitor'),
- (s_('UsageQuota|Usage Quotas') if Feature.enabled?(:project_storage_ui, default_enabled: :yaml))
+ s_('UsageQuota|Usage Quotas')
]
}
].compact
diff --git a/spec/support/shared_contexts/policies/project_policy_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
index d7e4864cb08..8a90f887381 100644
--- a/spec/support/shared_contexts/policies/project_policy_shared_context.rb
+++ b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
@@ -15,7 +15,7 @@ RSpec.shared_context 'ProjectPolicy context' do
let(:base_guest_permissions) do
%i[
- award_emoji create_issue create_incident create_merge_request_in create_note
+ award_emoji create_issue create_merge_request_in create_note
create_project read_issue_board read_issue read_issue_iid read_issue_link
read_label read_issue_board_list read_milestone read_note read_project
read_project_for_iids read_project_member read_release read_snippet
@@ -25,10 +25,11 @@ RSpec.shared_context 'ProjectPolicy context' do
let(:base_reporter_permissions) do
%i[
- admin_issue admin_issue_link admin_label admin_issue_board_list create_snippet
- daily_statistics download_code download_wiki_code fork_project metrics_dashboard
- read_build read_commit_status read_confidential_issues
- read_container_image read_deployment read_environment read_merge_request
+ admin_issue admin_issue_link admin_label admin_issue_board_list
+ create_snippet create_incident daily_statistics download_code
+ download_wiki_code fork_project metrics_dashboard read_build
+ read_commit_status read_confidential_issues read_container_image
+ read_deployment read_environment read_merge_request
read_metrics_dashboard_annotation read_pipeline read_prometheus
read_sentry_issue update_issue
]
diff --git a/spec/support/shared_contexts/requests/api/debian_repository_shared_context.rb b/spec/support/shared_contexts/requests/api/debian_repository_shared_context.rb
new file mode 100644
index 00000000000..95b8b7ed9f8
--- /dev/null
+++ b/spec/support/shared_contexts/requests/api/debian_repository_shared_context.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'Debian repository shared context' do |container_type, can_freeze|
+ include_context 'workhorse headers'
+
+ before do
+ stub_feature_flags(debian_packages: true, debian_group_packages: true)
+ end
+
+ let_it_be(:private_container, freeze: can_freeze) { create(container_type, :private) }
+ let_it_be(:public_container, freeze: can_freeze) { create(container_type, :public) }
+ let_it_be(:user, freeze: true) { create(:user) }
+ let_it_be(:personal_access_token, freeze: true) { create(:personal_access_token, user: user) }
+
+ let_it_be(:private_distribution, freeze: true) { create("debian_#{container_type}_distribution", :with_file, container: private_container, codename: 'existing-codename') }
+ let_it_be(:private_distribution_key, freeze: true) { create("debian_#{container_type}_distribution_key", distribution: private_distribution) }
+ let_it_be(:private_component, freeze: true) { create("debian_#{container_type}_component", distribution: private_distribution, name: 'existing-component') }
+ let_it_be(:private_architecture_all, freeze: true) { create("debian_#{container_type}_architecture", distribution: private_distribution, name: 'all') }
+ let_it_be(:private_architecture, freeze: true) { create("debian_#{container_type}_architecture", distribution: private_distribution, name: 'existing-arch') }
+ let_it_be(:private_component_file) { create("debian_#{container_type}_component_file", component: private_component, architecture: private_architecture) }
+
+ let_it_be(:public_distribution, freeze: true) { create("debian_#{container_type}_distribution", :with_file, container: public_container, codename: 'existing-codename') }
+ let_it_be(:public_distribution_key, freeze: true) { create("debian_#{container_type}_distribution_key", distribution: public_distribution) }
+ let_it_be(:public_component, freeze: true) { create("debian_#{container_type}_component", distribution: public_distribution, name: 'existing-component') }
+ let_it_be(:public_architecture_all, freeze: true) { create("debian_#{container_type}_architecture", distribution: public_distribution, name: 'all') }
+ let_it_be(:public_architecture, freeze: true) { create("debian_#{container_type}_architecture", distribution: public_distribution, name: 'existing-arch') }
+ let_it_be(:public_component_file) { create("debian_#{container_type}_component_file", component: public_component, architecture: public_architecture) }
+
+ if container_type == :group
+ let_it_be(:private_project) { create(:project, :private, group: private_container) }
+ let_it_be(:public_project) { create(:project, :public, group: public_container) }
+ let_it_be(:private_project_distribution) { create(:debian_project_distribution, container: private_project, codename: 'existing-codename') }
+ let_it_be(:public_project_distribution) { create(:debian_project_distribution, container: public_project, codename: 'existing-codename') }
+
+ let(:project) { { private: private_project, public: public_project }[visibility_level] }
+ else
+ let_it_be(:private_project) { private_container }
+ let_it_be(:public_project) { public_container }
+ let_it_be(:private_project_distribution) { private_distribution }
+ let_it_be(:public_project_distribution) { public_distribution }
+ end
+
+ let_it_be(:private_package) { create(:debian_package, project: private_project, published_in: private_project_distribution) }
+ let_it_be(:public_package) { create(:debian_package, project: public_project, published_in: public_project_distribution) }
+
+ let(:visibility_level) { :public }
+
+ let(:distribution) { { private: private_distribution, public: public_distribution }[visibility_level] }
+ let(:architecture) { { private: private_architecture, public: public_architecture }[visibility_level] }
+ let(:component) { { private: private_component, public: public_component }[visibility_level] }
+ let(:component_file) { { private: private_component_file, public: public_component_file }[visibility_level] }
+ let(:package) { { private: private_package, public: public_package }[visibility_level] }
+ let(:letter) { package.name[0..2] == 'lib' ? package.name[0..3] : package.name[0] }
+
+ let(:method) { :get }
+
+ let(:workhorse_params) do
+ if method == :put
+ file_upload = fixture_file_upload("spec/fixtures/packages/debian/#{file_name}")
+ { file: file_upload }
+ else
+ {}
+ end
+ end
+
+ let(:api_params) { workhorse_params }
+
+ let(:auth_headers) { {} }
+ let(:wh_headers) do
+ if method == :put
+ workhorse_headers
+ else
+ {}
+ end
+ end
+
+ let(:headers) { auth_headers.merge(wh_headers) }
+
+ let(:send_rewritten_field) { true }
+
+ subject do
+ if method == :put
+ workhorse_finalize(
+ api(url),
+ method: method,
+ file_key: :file,
+ params: api_params,
+ headers: headers,
+ send_rewritten_field: send_rewritten_field
+ )
+ else
+ send method, api(url), headers: headers, params: api_params
+ end
+ end
+end
+
+RSpec.shared_context 'Debian repository auth headers' do |user_type, auth_method = :private_token|
+ let(:token) { user_type == :invalid_token ? 'wrong' : personal_access_token.token }
+
+ let(:auth_headers) do
+ if user_type == :anonymous
+ {}
+ elsif auth_method == :private_token
+ { 'Private-Token' => token }
+ else
+ basic_auth_header(user.username, token)
+ end
+ end
+end
+
+RSpec.shared_context 'Debian repository access' do |visibility_level, user_type, auth_method|
+ include_context 'Debian repository auth headers', user_type, auth_method do
+ let(:containers) { { private: private_container, public: public_container } }
+ let(:container) { containers[visibility_level] }
+
+ before do
+ container.send("add_#{user_type}", user) if user_type != :anonymous && user_type != :not_a_member && user_type != :invalid_token
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb b/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb
index 80f011f622b..21be989d697 100644
--- a/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb
+++ b/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb
@@ -31,14 +31,14 @@ RSpec.shared_context 'container repository delete tags service shared context' d
end
end
- def stub_put_manifest_request(tag, status = 200, headers = { 'docker-content-digest' => 'sha256:dummy' })
+ def stub_put_manifest_request(tag, status = 200, headers = { DependencyProxy::Manifest::DIGEST_HEADER => 'sha256:dummy' })
stub_request(:put, "http://registry.gitlab/v2/#{repository.path}/manifests/#{tag}")
.to_return(status: status, body: '', headers: headers)
end
def stub_tag_digest(tag, digest)
stub_request(:head, "http://registry.gitlab/v2/#{repository.path}/manifests/#{tag}")
- .to_return(status: 200, body: '', headers: { 'docker-content-digest' => digest })
+ .to_return(status: 200, body: '', headers: { DependencyProxy::Manifest::DIGEST_HEADER => digest })
end
def stub_digest_config(digest, created_at)
diff --git a/spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb b/spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb
index 2b810e790f0..e1d864213b5 100644
--- a/spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb
+++ b/spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb
@@ -38,6 +38,11 @@ RSpec.shared_context 'stubbed service ping metrics definitions' do
)
end
+ after do |example|
+ Gitlab::Usage::Metric.instance_variable_set(:@all, nil)
+ Gitlab::Usage::MetricDefinition.instance_variable_set(:@all, nil)
+ end
+
def metric_attributes(key_path, category, value_type = 'string')
{
'key_path' => key_path,
diff --git a/spec/support/shared_contexts/url_shared_context.rb b/spec/support/shared_contexts/url_shared_context.rb
index f3d227b6e2b..da1d6e0049c 100644
--- a/spec/support/shared_contexts/url_shared_context.rb
+++ b/spec/support/shared_contexts/url_shared_context.rb
@@ -1,19 +1,32 @@
# frozen_string_literal: true
+RSpec.shared_context 'valid urls with CRLF' do
+ let(:valid_urls_with_CRLF) do
+ [
+ "http://example.com/pa%0dth",
+ "http://example.com/pa%0ath",
+ "http://example.com/pa%0d%0th",
+ "http://example.com/pa%0D%0Ath",
+ "http://gitlab.com/path?param=foo%0Abar",
+ "https://gitlab.com/path?param=foo%0Dbar",
+ "http://example.org:1024/path?param=foo%0D%0Abar",
+ "https://storage.googleapis.com/bucket/import_export_upload/import_file/57265/express.tar.gz?GoogleAccessId=hello@example.org&Signature=ABCD%0AEFGHik&Expires=1634663304"
+ ]
+ end
+end
+
RSpec.shared_context 'invalid urls' do
let(:urls_with_CRLF) do
- ["http://127.0.0.1:333/pa\rth",
- "http://127.0.0.1:333/pa\nth",
- "http://127.0a.0.1:333/pa\r\nth",
- "http://127.0.0.1:333/path?param=foo\r\nbar",
- "http://127.0.0.1:333/path?param=foo\rbar",
- "http://127.0.0.1:333/path?param=foo\nbar",
- "http://127.0.0.1:333/pa%0dth",
- "http://127.0.0.1:333/pa%0ath",
- "http://127.0a.0.1:333/pa%0d%0th",
- "http://127.0.0.1:333/pa%0D%0Ath",
- "http://127.0.0.1:333/path?param=foo%0Abar",
- "http://127.0.0.1:333/path?param=foo%0Dbar",
- "http://127.0.0.1:333/path?param=foo%0D%0Abar"]
+ [
+ "git://example.com/pa%0dth",
+ "git://example.com/pa%0ath",
+ "git://example.com/pa%0d%0th",
+ "http://example.com/pa\rth",
+ "http://example.com/pa\nth",
+ "http://example.com/pa\r\nth",
+ "http://example.com/path?param=foo\r\nbar",
+ "http://example.com/path?param=foo\rbar",
+ "http://example.com/path?param=foo\nbar"
+ ]
end
end
diff --git a/spec/support/shared_examples/bulk_imports/common/pipelines/wiki_pipeline_examples.rb b/spec/support/shared_examples/bulk_imports/common/pipelines/wiki_pipeline_examples.rb
new file mode 100644
index 00000000000..e8cc666605b
--- /dev/null
+++ b/spec/support/shared_examples/bulk_imports/common/pipelines/wiki_pipeline_examples.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'wiki pipeline imports a wiki for an entity' do
+ describe '#run' do
+ let_it_be(:bulk_import_configuration) { create(:bulk_import_configuration, bulk_import: bulk_import) }
+
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ let(:extracted_data) { BulkImports::Pipeline::ExtractedData.new(data: {}) }
+
+ context 'successfully imports wiki for an entity' do
+ subject { described_class.new(context) }
+
+ before do
+ allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(extracted_data)
+ end
+ end
+
+ it 'imports new wiki into destination project' do
+ expect_next_instance_of(Gitlab::GitalyClient::RepositoryService) do |repository_service|
+ url = "https://oauth2:token@gitlab.example/#{entity.source_full_path}.wiki.git"
+ expect(repository_service).to receive(:fetch_remote).with(url, any_args).and_return 0
+ end
+
+ subject.run
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/controllers/concerns/integrations/integrations_actions_shared_examples.rb b/spec/support/shared_examples/controllers/concerns/integrations/integrations_actions_shared_examples.rb
new file mode 100644
index 00000000000..a8aed0c1f0b
--- /dev/null
+++ b/spec/support/shared_examples/controllers/concerns/integrations/integrations_actions_shared_examples.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples Integrations::Actions do
+ let(:integration) do
+ create(:datadog_integration,
+ integration_attributes.merge(
+ api_url: 'http://example.com',
+ api_key: 'secret'
+ )
+ )
+ end
+
+ describe 'GET #edit' do
+ before do
+ get :edit, params: routing_params
+ end
+
+ it 'assigns the integration' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:integration)).to eq(integration)
+ end
+ end
+
+ describe 'PUT #update' do
+ let(:params) do
+ {
+ datadog_env: 'env',
+ datadog_service: 'service'
+ }
+ end
+
+ before do
+ put :update, params: routing_params.merge(integration: params)
+ end
+
+ it 'updates the integration with the provided params and redirects to the form' do
+ expect(response).to redirect_to(routing_params.merge(action: :edit))
+ expect(integration.reload).to have_attributes(params)
+ end
+
+ context 'when sending a password field' do
+ let(:params) { super().merge(api_key: 'new') }
+
+ it 'updates the integration with the password and other params' do
+ expect(response).to be_redirect
+ expect(integration.reload).to have_attributes(params)
+ end
+ end
+
+ context 'when sending a blank password field' do
+ let(:params) { super().merge(api_key: '') }
+
+ it 'ignores the password field and saves the other params' do
+ expect(response).to be_redirect
+ expect(integration.reload).to have_attributes(params.merge(api_key: 'secret'))
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/controllers/concerns/integrations_actions_shared_examples.rb b/spec/support/shared_examples/controllers/concerns/integrations_actions_shared_examples.rb
deleted file mode 100644
index 748a3acf17b..00000000000
--- a/spec/support/shared_examples/controllers/concerns/integrations_actions_shared_examples.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples IntegrationsActions do
- let(:integration) do
- create(:datadog_integration,
- integration_attributes.merge(
- api_url: 'http://example.com',
- api_key: 'secret'
- )
- )
- end
-
- describe 'GET #edit' do
- before do
- get :edit, params: routing_params
- end
-
- it 'assigns the integration' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(assigns(:integration)).to eq(integration)
- end
- end
-
- describe 'PUT #update' do
- let(:params) do
- {
- datadog_env: 'env',
- datadog_service: 'service'
- }
- end
-
- before do
- put :update, params: routing_params.merge(integration: params)
- end
-
- it 'updates the integration with the provided params and redirects to the form' do
- expect(response).to redirect_to(routing_params.merge(action: :edit))
- expect(integration.reload).to have_attributes(params)
- end
-
- context 'when sending a password field' do
- let(:params) { super().merge(api_key: 'new') }
-
- it 'updates the integration with the password and other params' do
- expect(response).to be_redirect
- expect(integration.reload).to have_attributes(params)
- end
- end
-
- context 'when sending a blank password field' do
- let(:params) { super().merge(api_key: '') }
-
- it 'ignores the password field and saves the other params' do
- expect(response).to be_redirect
- expect(integration.reload).to have_attributes(params.merge(api_key: 'secret'))
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/controllers/create_notes_rate_limit_shared_examples.rb b/spec/support/shared_examples/controllers/create_notes_rate_limit_shared_examples.rb
index 74a98c20383..8affe4ac8f5 100644
--- a/spec/support/shared_examples/controllers/create_notes_rate_limit_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/create_notes_rate_limit_shared_examples.rb
@@ -6,39 +6,41 @@
# - request_full_path
RSpec.shared_examples 'request exceeding rate limit' do
- before do
- stub_application_setting(notes_create_limit: 2)
- 2.times { post :create, params: params }
- end
+ context 'with rate limiter', :freeze_time, :clean_gitlab_redis_rate_limiting do
+ before do
+ stub_application_setting(notes_create_limit: 2)
+ 2.times { post :create, params: params }
+ end
- it 'prevents from creating more notes', :request_store do
- expect { post :create, params: params }
- .to change { Note.count }.by(0)
+ it 'prevents from creating more notes' do
+ expect { post :create, params: params }
+ .to change { Note.count }.by(0)
- expect(response).to have_gitlab_http_status(:too_many_requests)
- expect(response.body).to eq(_('This endpoint has been requested too many times. Try again later.'))
- end
+ expect(response).to have_gitlab_http_status(:too_many_requests)
+ expect(response.body).to eq(_('This endpoint has been requested too many times. Try again later.'))
+ end
- it 'logs the event in auth.log' do
- attributes = {
- message: 'Application_Rate_Limiter_Request',
- env: :notes_create_request_limit,
- remote_ip: '0.0.0.0',
- request_method: 'POST',
- path: request_full_path,
- user_id: user.id,
- username: user.username
- }
+ it 'logs the event in auth.log' do
+ attributes = {
+ message: 'Application_Rate_Limiter_Request',
+ env: :notes_create_request_limit,
+ remote_ip: '0.0.0.0',
+ request_method: 'POST',
+ path: request_full_path,
+ user_id: user.id,
+ username: user.username
+ }
- expect(Gitlab::AuthLogger).to receive(:error).with(attributes).once
- post :create, params: params
- end
+ expect(Gitlab::AuthLogger).to receive(:error).with(attributes).once
+ post :create, params: params
+ end
- it 'allows user in allow-list to create notes, even if the case is different' do
- user.update_attribute(:username, user.username.titleize)
- stub_application_setting(notes_create_limit_allowlist: ["#{user.username.downcase}"])
+ it 'allows user in allow-list to create notes, even if the case is different' do
+ user.update_attribute(:username, user.username.titleize)
+ stub_application_setting(notes_create_limit_allowlist: ["#{user.username.downcase}"])
- post :create, params: params
- expect(response).to have_gitlab_http_status(:found)
+ post :create, params: params
+ expect(response).to have_gitlab_http_status(:found)
+ end
end
end
diff --git a/spec/support/shared_examples/features/2fa_shared_examples.rb b/spec/support/shared_examples/features/2fa_shared_examples.rb
index ddc03e178ba..94c91556ea7 100644
--- a/spec/support/shared_examples/features/2fa_shared_examples.rb
+++ b/spec/support/shared_examples/features/2fa_shared_examples.rb
@@ -18,6 +18,7 @@ RSpec.shared_examples 'hardware device for 2fa' do |device_type|
let(:user) { create(:user) }
before do
+ stub_feature_flags(bootstrap_confirmation_modals: false)
gitlab_sign_in(user)
user.update_attribute(:otp_required_for_login, true)
end
diff --git a/spec/support/shared_examples/features/dependency_proxy_shared_examples.rb b/spec/support/shared_examples/features/dependency_proxy_shared_examples.rb
index d29c677a962..5d1488502d2 100644
--- a/spec/support/shared_examples/features/dependency_proxy_shared_examples.rb
+++ b/spec/support/shared_examples/features/dependency_proxy_shared_examples.rb
@@ -26,7 +26,7 @@ RSpec.shared_examples 'a successful manifest pull' do
subject
expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers['Docker-Content-Digest']).to eq(manifest.digest)
+ expect(response.headers[DependencyProxy::Manifest::DIGEST_HEADER]).to eq(manifest.digest)
expect(response.headers['Content-Length']).to eq(manifest.size)
expect(response.headers['Docker-Distribution-Api-Version']).to eq(DependencyProxy::DISTRIBUTION_API_VERSION)
expect(response.headers['Etag']).to eq("\"#{manifest.digest}\"")
diff --git a/spec/support/shared_examples/features/manage_applications_shared_examples.rb b/spec/support/shared_examples/features/manage_applications_shared_examples.rb
index 0161899cb76..27d50c67f24 100644
--- a/spec/support/shared_examples/features/manage_applications_shared_examples.rb
+++ b/spec/support/shared_examples/features/manage_applications_shared_examples.rb
@@ -18,6 +18,7 @@ RSpec.shared_examples 'manage applications' do
click_on 'Save application'
validate_application(application_name, 'Yes')
+ expect(page).to have_link('Continue', href: index_path)
application = Doorkeeper::Application.find_by(name: application_name)
expect(page).to have_css("button[title=\"Copy secret\"][data-clipboard-text=\"#{application.secret}\"]", text: 'Copy')
@@ -33,6 +34,7 @@ RSpec.shared_examples 'manage applications' do
click_on 'Save application'
validate_application(application_name_changed, 'No')
+ expect(page).not_to have_link('Continue')
visit_applications_path
diff --git a/spec/support/shared_examples/features/packages_shared_examples.rb b/spec/support/shared_examples/features/packages_shared_examples.rb
index 96be30b9f1f..d14b4638ca5 100644
--- a/spec/support/shared_examples/features/packages_shared_examples.rb
+++ b/spec/support/shared_examples/features/packages_shared_examples.rb
@@ -21,10 +21,6 @@ end
RSpec.shared_examples 'package details link' do |property|
let(:package) { packages.first }
- before do
- stub_feature_flags(packages_details_one_column: false)
- end
-
it 'navigates to the correct url' do
page.within(packages_table_selector) do
click_link package.name
@@ -32,7 +28,7 @@ RSpec.shared_examples 'package details link' do |property|
expect(page).to have_current_path(project_package_path(package.project, package))
- expect(page).to have_css('.packages-app h1[data-testid="title"]', text: package.name)
+ expect(page).to have_css('.packages-app h2[data-testid="title"]', text: package.name)
expect(page).to have_content('Installation')
expect(page).to have_content('Registry setup')
@@ -94,16 +90,24 @@ def packages_table_selector
end
def click_sort_option(option, ascending)
- page.within('.gl-sorting') do
- # Reset the sort direction
- click_button 'Sort direction' if page.has_selector?('svg[aria-label="Sorting Direction: Ascending"]', wait: 0)
+ wait_for_requests
- find('button.gl-dropdown-toggle').click
+ # Reset the sort direction
+ if page.has_selector?('button[aria-label="Sorting Direction: Ascending"]', wait: 0) && !ascending
+ click_button 'Sort direction'
- page.within('.dropdown-menu') do
- click_button option
- end
+ wait_for_requests
+ end
+
+ find('button.gl-dropdown-toggle').click
+
+ page.within('.dropdown-menu') do
+ click_button option
+ end
+
+ if ascending
+ wait_for_requests
- click_button 'Sort direction' if ascending
+ click_button 'Sort direction'
end
end
diff --git a/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb b/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb
index 6d44a6fde85..337b3f3cbd0 100644
--- a/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb
+++ b/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb
@@ -1,43 +1,29 @@
# frozen_string_literal: true
RSpec.shared_examples 'creating an issue for a thread' do
- it 'shows an issue with the title filled in' do
+ it 'shows an issue creation form' do
+ # Title field is filled in
title_field = page.find_field('issue[title]')
-
expect(title_field.value).to include(merge_request.title)
- end
- it 'has a mention of the discussion in the description' do
- description_field = page.find_field('issue[description]')
+ # Has a hidden field for the merge request
+ merge_request_field = find('#merge_request_to_resolve_discussions_of', visible: false)
+ expect(merge_request_field.value).to eq(merge_request.iid.to_s)
+ # Has a mention of the discussion in the description
+ description_field = page.find_field('issue[description]')
expect(description_field.value).to include(discussion.first_note.note)
end
- it 'can create a new issue for the project' do
+ it 'creates a new issue for the project' do
+ # Actually creates an issue for the project
expect { click_button 'Create issue' }.to change { project.issues.reload.size }.by(1)
- end
-
- it 'resolves the discussion in the merge request' do
- click_button 'Create issue'
+ # Resolves the discussion in the merge request
discussion.first_note.reload
-
expect(discussion.resolved?).to eq(true)
- end
-
- it 'shows a flash messaage after resolving a discussion' do
- click_button 'Create issue'
-
- page.within '.flash-notice' do
- # Only check for the word 'Resolved' since the spec might have resolved
- # multiple discussions
- expect(page).to have_content('Resolved')
- end
- end
-
- it 'has a hidden field for the merge request' do
- merge_request_field = find('#merge_request_to_resolve_discussions_of', visible: false)
- expect(merge_request_field.value).to eq(merge_request.iid.to_s)
+ # Issue title inludes MR title
+ expect(page).to have_content(%Q(Follow-up from "#{merge_request.title}"))
end
end
diff --git a/spec/support/shared_examples/features/sidebar_shared_examples.rb b/spec/support/shared_examples/features/sidebar_shared_examples.rb
index 5bfe929e957..d509d124de0 100644
--- a/spec/support/shared_examples/features/sidebar_shared_examples.rb
+++ b/spec/support/shared_examples/features/sidebar_shared_examples.rb
@@ -52,16 +52,17 @@ RSpec.shared_examples 'issue boards sidebar' do
it 'shows toggle as on then as off as user toggles to subscribe and unsubscribe', :aggregate_failures do
wait_for_requests
+ subscription_button = find('[data-testid="subscription-toggle"]')
- click_button 'Notifications'
+ subscription_button.click
- expect(page).to have_button('Notifications', class: 'is-checked')
+ expect(subscription_button).to have_css("button.is-checked")
- click_button 'Notifications'
+ subscription_button.click
wait_for_requests
- expect(page).not_to have_button('Notifications', class: 'is-checked')
+ expect(subscription_button).to have_css("button:not(.is-checked)")
end
context 'when notifications have been disabled' do
@@ -73,7 +74,7 @@ RSpec.shared_examples 'issue boards sidebar' do
it 'displays a message that notifications have been disabled' do
page.within('[data-testid="sidebar-notifications"]') do
- expect(page).to have_button('Notifications', class: 'is-disabled')
+ expect(page).to have_selector('[data-testid="subscription-toggle"]', class: 'is-disabled')
expect(page).to have_content('Disabled by project owner')
end
end
diff --git a/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb b/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb
index fb598b978f6..56b6dc682eb 100644
--- a/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb
@@ -66,20 +66,22 @@ RSpec.shared_examples 'a Note mutation when the given resource id is not for a N
end
RSpec.shared_examples 'a Note mutation when there are rate limit validation errors' do
- before do
- stub_application_setting(notes_create_limit: 3)
- 3.times { post_graphql_mutation(mutation, current_user: current_user) }
- end
-
- it_behaves_like 'a Note mutation that does not create a Note'
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['This endpoint has been requested too many times. Try again later.']
-
- context 'when the user is in the allowlist' do
+ context 'with rate limiter', :freeze_time, :clean_gitlab_redis_rate_limiting do
before do
- stub_application_setting(notes_create_limit_allowlist: ["#{current_user.username}"])
+ stub_application_setting(notes_create_limit: 3)
+ 3.times { post_graphql_mutation(mutation, current_user: current_user) }
end
- it_behaves_like 'a Note mutation that creates a Note'
+ it_behaves_like 'a Note mutation that does not create a Note'
+ it_behaves_like 'a mutation that returns top-level errors',
+ errors: ['This endpoint has been requested too many times. Try again later.']
+
+ context 'when the user is in the allowlist' do
+ before do
+ stub_application_setting(notes_create_limit_allowlist: ["#{current_user.username}"])
+ end
+
+ it_behaves_like 'a Note mutation that creates a Note'
+ end
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
index 8b4ecd7d5ae..a3c67210a4a 100644
--- a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
@@ -35,8 +35,8 @@ RSpec.shared_examples 'common trace features' do
stub_feature_flags(gitlab_ci_archived_trace_consistent_reads: trace.job.project)
end
- it 'calls ::ApplicationRecord.sticking.unstick_or_continue_sticking' do
- expect(::ApplicationRecord.sticking).to receive(:unstick_or_continue_sticking)
+ it 'calls ::Ci::Build.sticking.unstick_or_continue_sticking' do
+ expect(::Ci::Build.sticking).to receive(:unstick_or_continue_sticking)
.with(described_class::LOAD_BALANCING_STICKING_NAMESPACE, trace.job.id)
.and_call_original
@@ -49,8 +49,8 @@ RSpec.shared_examples 'common trace features' do
stub_feature_flags(gitlab_ci_archived_trace_consistent_reads: false)
end
- it 'does not call ::ApplicationRecord.sticking.unstick_or_continue_sticking' do
- expect(::ApplicationRecord.sticking).not_to receive(:unstick_or_continue_sticking)
+ it 'does not call ::Ci::Build.sticking.unstick_or_continue_sticking' do
+ expect(::Ci::Build.sticking).not_to receive(:unstick_or_continue_sticking)
trace.read { |stream| stream }
end
@@ -305,8 +305,8 @@ RSpec.shared_examples 'common trace features' do
stub_feature_flags(gitlab_ci_archived_trace_consistent_reads: trace.job.project)
end
- it 'calls ::ApplicationRecord.sticking.stick' do
- expect(::ApplicationRecord.sticking).to receive(:stick)
+ it 'calls ::Ci::Build.sticking.stick' do
+ expect(::Ci::Build.sticking).to receive(:stick)
.with(described_class::LOAD_BALANCING_STICKING_NAMESPACE, trace.job.id)
.and_call_original
@@ -319,8 +319,8 @@ RSpec.shared_examples 'common trace features' do
stub_feature_flags(gitlab_ci_archived_trace_consistent_reads: false)
end
- it 'does not call ::ApplicationRecord.sticking.stick' do
- expect(::ApplicationRecord.sticking).not_to receive(:stick)
+ it 'does not call ::Ci::Build.sticking.stick' do
+ expect(::Ci::Build.sticking).not_to receive(:stick)
subject
end
@@ -808,7 +808,19 @@ RSpec.shared_examples 'trace with enabled live trace feature' do
create(:ci_job_artifact, :trace, job: build)
end
- it { is_expected.to be_truthy }
+ it 'is truthy' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'when archived trace record exists but file is not stored' do
+ before do
+ create(:ci_job_artifact, :unarchived_trace_artifact, job: build)
+ end
+
+ it 'is falsy' do
+ is_expected.to be_falsy
+ end
end
context 'when live trace exists' do
@@ -872,13 +884,35 @@ RSpec.shared_examples 'trace with enabled live trace feature' do
build.reload
expect(build.trace.exist?).to be_truthy
- expect(build.job_artifacts_trace).to be_nil
Gitlab::Ci::Trace::ChunkedIO.new(build) do |stream|
expect(stream.read).to eq(trace_raw)
end
end
end
+ shared_examples 'a pre-commit error' do |error:|
+ it_behaves_like 'source trace in ChunkedIO stays intact', error: error
+
+ it 'does not save the trace artifact' do
+ expect { subject }.to raise_error(error)
+
+ build.reload
+ expect(build.job_artifacts_trace).to be_nil
+ end
+ end
+
+ shared_examples 'a post-commit error' do |error:|
+ it_behaves_like 'source trace in ChunkedIO stays intact', error: error
+
+ it 'saves the trace artifact but not the file' do
+ expect { subject }.to raise_error(error)
+
+ build.reload
+ expect(build.job_artifacts_trace).to be_present
+ expect(build.job_artifacts_trace.file.exists?).to be_falsy
+ end
+ end
+
context 'when job does not have trace artifact' do
context 'when trace is stored in ChunkedIO' do
let!(:build) { create(:ci_build, :success, :trace_live) }
@@ -892,7 +926,7 @@ RSpec.shared_examples 'trace with enabled live trace feature' do
allow(IO).to receive(:copy_stream).and_return(0)
end
- it_behaves_like 'source trace in ChunkedIO stays intact', error: Gitlab::Ci::Trace::ArchiveError
+ it_behaves_like 'a pre-commit error', error: Gitlab::Ci::Trace::ArchiveError
end
context 'when failed to create job artifact record' do
@@ -902,7 +936,16 @@ RSpec.shared_examples 'trace with enabled live trace feature' do
.and_return(%w[Error Error])
end
- it_behaves_like 'source trace in ChunkedIO stays intact', error: ActiveRecord::RecordInvalid
+ it_behaves_like 'a pre-commit error', error: ActiveRecord::RecordInvalid
+ end
+
+ context 'when storing the file raises an error' do
+ before do
+ stub_artifacts_object_storage(direct_upload: true)
+ allow_any_instance_of(Ci::JobArtifact).to receive(:store_file!).and_raise(Excon::Error::BadGateway, 'S3 is down lol')
+ end
+
+ it_behaves_like 'a post-commit error', error: Excon::Error::BadGateway
end
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb b/spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb
index 6342064beb8..bea7cca2744 100644
--- a/spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb
+++ b/spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb
@@ -6,7 +6,7 @@ shared_examples 'deployment metrics examples' do
environment = project.environments.production.first || create(:environment, :production, project: project)
create(:deployment, :success, args.merge(environment: environment))
- # this is needed for the dora_deployment_frequency_in_vsa feature flag so we have aggregated data
+ # this is needed for the DORA API so we have aggregated data
::Dora::DailyMetrics::RefreshWorker.new.perform(environment.id, Time.current.to_date.to_s) if Gitlab.ee?
end
diff --git a/spec/support/shared_examples/lib/gitlab/database/cte_materialized_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/database/cte_materialized_shared_examples.rb
index a617342ff8c..df795723874 100644
--- a/spec/support/shared_examples/lib/gitlab/database/cte_materialized_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/database/cte_materialized_shared_examples.rb
@@ -11,7 +11,7 @@ RSpec.shared_examples 'CTE with MATERIALIZED keyword examples' do
context 'when PG version is <12' do
it 'does not add MATERIALIZE keyword' do
- allow(Gitlab::Database.main).to receive(:version).and_return('11.1')
+ allow(ApplicationRecord.database).to receive(:version).and_return('11.1')
expect(query).to include(expected_query_block_without_materialized)
end
@@ -19,14 +19,14 @@ RSpec.shared_examples 'CTE with MATERIALIZED keyword examples' do
context 'when PG version is >=12' do
it 'adds MATERIALIZE keyword' do
- allow(Gitlab::Database.main).to receive(:version).and_return('12.1')
+ allow(ApplicationRecord.database).to receive(:version).and_return('12.1')
expect(query).to include(expected_query_block_with_materialized)
end
context 'when version is higher than 12' do
it 'adds MATERIALIZE keyword' do
- allow(Gitlab::Database.main).to receive(:version).and_return('15.1')
+ allow(ApplicationRecord.database).to receive(:version).and_return('15.1')
expect(query).to include(expected_query_block_with_materialized)
end
diff --git a/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb
index 5ce698c4701..41d3d76b66b 100644
--- a/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-RSpec.shared_examples 'a permitted attribute' do |relation_sym, permitted_attributes|
+RSpec.shared_examples 'a permitted attribute' do |relation_sym, permitted_attributes, additional_attributes = []|
let(:prohibited_attributes) { %i[remote_url my_attributes my_ids token my_id test] }
let(:import_export_config) { Gitlab::ImportExport::Config.new.to_h }
@@ -26,7 +26,7 @@ RSpec.shared_examples 'a permitted attribute' do |relation_sym, permitted_attrib
end
it 'does not contain attributes that would be cleaned with AttributeCleaner' do
- expect(cleaned_hash.keys).to include(*permitted_hash.keys)
+ expect(cleaned_hash.keys + additional_attributes.to_a).to include(*permitted_hash.keys)
end
it 'does not contain prohibited attributes that are not related to given relation' do
diff --git a/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb
index 708bc71ae96..ff03051ed37 100644
--- a/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb
@@ -2,7 +2,7 @@
RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name|
let(:fake_duplicate_job) do
- instance_double(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob)
+ instance_double(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, duplicate_key_ttl: Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob::DEFAULT_DUPLICATE_KEY_TTL)
end
let(:expected_message) { "dropped #{strategy_name.to_s.humanize.downcase}" }
@@ -11,14 +11,14 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name|
describe '#schedule' do
before do
- allow(Gitlab::SidekiqLogging::DeduplicationLogger.instance).to receive(:log)
+ allow(Gitlab::SidekiqLogging::DeduplicationLogger.instance).to receive(:deduplicated_log)
end
it 'checks for duplicates before yielding' do
expect(fake_duplicate_job).to receive(:scheduled?).twice.ordered.and_return(false)
expect(fake_duplicate_job).to(
receive(:check!)
- .with(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob::DUPLICATE_KEY_TTL)
+ .with(fake_duplicate_job.duplicate_key_ttl)
.ordered
.and_return('a jid'))
expect(fake_duplicate_job).to receive(:duplicate?).ordered.and_return(false)
@@ -40,6 +40,7 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name|
allow(fake_duplicate_job).to receive(:check!).and_return('the jid')
allow(fake_duplicate_job).to receive(:idempotent?).and_return(true)
allow(fake_duplicate_job).to receive(:update_latest_wal_location!)
+ allow(fake_duplicate_job).to receive(:set_deduplicated_flag!)
allow(fake_duplicate_job).to receive(:options).and_return({})
job_hash = {}
@@ -61,10 +62,11 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name|
allow(fake_duplicate_job).to receive(:options).and_return({ including_scheduled: true })
allow(fake_duplicate_job).to(
receive(:check!)
- .with(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob::DUPLICATE_KEY_TTL)
+ .with(fake_duplicate_job.duplicate_key_ttl)
.and_return('the jid'))
allow(fake_duplicate_job).to receive(:idempotent?).and_return(true)
allow(fake_duplicate_job).to receive(:update_latest_wal_location!)
+ allow(fake_duplicate_job).to receive(:set_deduplicated_flag!)
job_hash = {}
expect(fake_duplicate_job).to receive(:duplicate?).and_return(true)
@@ -83,9 +85,10 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name|
allow(fake_duplicate_job).to receive(:scheduled_at).and_return(Time.now + time_diff)
allow(fake_duplicate_job).to receive(:options).and_return({ including_scheduled: true })
allow(fake_duplicate_job).to(
- receive(:check!).with(time_diff.to_i).and_return('the jid'))
+ receive(:check!).with(time_diff.to_i + fake_duplicate_job.duplicate_key_ttl).and_return('the jid'))
allow(fake_duplicate_job).to receive(:idempotent?).and_return(true)
allow(fake_duplicate_job).to receive(:update_latest_wal_location!)
+ allow(fake_duplicate_job).to receive(:set_deduplicated_flag!)
job_hash = {}
expect(fake_duplicate_job).to receive(:duplicate?).and_return(true)
@@ -100,6 +103,26 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name|
end
end
+ context "when the job is not duplicate" do
+ before do
+ allow(fake_duplicate_job).to receive(:scheduled?).and_return(false)
+ allow(fake_duplicate_job).to receive(:check!).and_return('the jid')
+ allow(fake_duplicate_job).to receive(:duplicate?).and_return(false)
+ allow(fake_duplicate_job).to receive(:options).and_return({})
+ allow(fake_duplicate_job).to receive(:existing_jid).and_return('the jid')
+ end
+
+ it 'does not return false nor drop the job' do
+ schedule_result = nil
+
+ expect(fake_duplicate_job).not_to receive(:set_deduplicated_flag!)
+
+ expect { |b| schedule_result = strategy.schedule({}, &b) }.to yield_control
+
+ expect(schedule_result).to be_nil
+ end
+ end
+
context "when the job is droppable" do
before do
allow(fake_duplicate_job).to receive(:scheduled?).and_return(false)
@@ -109,6 +132,7 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name|
allow(fake_duplicate_job).to receive(:existing_jid).and_return('the jid')
allow(fake_duplicate_job).to receive(:idempotent?).and_return(true)
allow(fake_duplicate_job).to receive(:update_latest_wal_location!)
+ allow(fake_duplicate_job).to receive(:set_deduplicated_flag!)
end
it 'updates latest wal location' do
@@ -117,10 +141,11 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name|
strategy.schedule({ 'jid' => 'new jid' }) {}
end
- it 'drops the job' do
+ it 'returns false to drop the job' do
schedule_result = nil
expect(fake_duplicate_job).to receive(:idempotent?).and_return(true)
+ expect(fake_duplicate_job).to receive(:set_deduplicated_flag!).once
expect { |b| schedule_result = strategy.schedule({}, &b) }.not_to yield_control
expect(schedule_result).to be(false)
@@ -130,7 +155,7 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name|
fake_logger = instance_double(Gitlab::SidekiqLogging::DeduplicationLogger)
expect(Gitlab::SidekiqLogging::DeduplicationLogger).to receive(:instance).and_return(fake_logger)
- expect(fake_logger).to receive(:log).with(a_hash_including({ 'jid' => 'new jid' }), expected_message, {})
+ expect(fake_logger).to receive(:deduplicated_log).with(a_hash_including({ 'jid' => 'new jid' }), expected_message, {})
strategy.schedule({ 'jid' => 'new jid' }) {}
end
@@ -140,7 +165,7 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name|
expect(Gitlab::SidekiqLogging::DeduplicationLogger).to receive(:instance).and_return(fake_logger)
allow(fake_duplicate_job).to receive(:options).and_return({ foo: :bar })
- expect(fake_logger).to receive(:log).with(a_hash_including({ 'jid' => 'new jid' }), expected_message, { foo: :bar })
+ expect(fake_logger).to receive(:deduplicated_log).with(a_hash_including({ 'jid' => 'new jid' }), expected_message, { foo: :bar })
strategy.schedule({ 'jid' => 'new jid' }) {}
end
@@ -159,6 +184,9 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name|
before do
allow(fake_duplicate_job).to receive(:delete!)
+ allow(fake_duplicate_job).to receive(:scheduled?) { false }
+ allow(fake_duplicate_job).to receive(:options) { {} }
+ allow(fake_duplicate_job).to receive(:should_reschedule?) { false }
allow(fake_duplicate_job).to receive(:latest_wal_locations).and_return( wal_locations )
end
diff --git a/spec/support/shared_examples/lib/sidebars/projects/menus/zentao_menu_shared_examples.rb b/spec/support/shared_examples/lib/sidebars/projects/menus/zentao_menu_shared_examples.rb
new file mode 100644
index 00000000000..d3fd28727b5
--- /dev/null
+++ b/spec/support/shared_examples/lib/sidebars/projects/menus/zentao_menu_shared_examples.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'ZenTao menu with CE version' do
+ let(:project) { create(:project, has_external_issue_tracker: true) }
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+ let(:zentao_integration) { create(:zentao_integration, project: project) }
+
+ subject { described_class.new(context) }
+
+ describe '#render?' do
+ context 'when issues integration is disabled' do
+ before do
+ zentao_integration.update!(active: false)
+ end
+
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+
+ context 'when issues integration is enabled' do
+ before do
+ zentao_integration.update!(active: true)
+ end
+
+ it 'returns true' do
+ expect(subject.render?).to eq true
+ end
+
+ it 'renders menu link' do
+ expect(subject.link).to eq zentao_integration.url
+ end
+
+ it 'contains only open ZenTao item' do
+ expect(subject.renderable_items.map(&:item_id)).to match_array [:open_zentao]
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb b/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb
new file mode 100644
index 00000000000..7ccd9533811
--- /dev/null
+++ b/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'it has loose foreign keys' do
+ let(:factory_name) { nil }
+ let(:table_name) { described_class.table_name }
+ let(:connection) { described_class.connection }
+
+ it 'includes the LooseForeignKey module' do
+ expect(described_class.ancestors).to include(LooseForeignKey)
+ end
+
+ it 'responds to #loose_foreign_key_definitions' do
+ expect(described_class).to respond_to(:loose_foreign_key_definitions)
+ end
+
+ it 'has at least one loose foreign key definition' do
+ expect(described_class.loose_foreign_key_definitions.size).to be > 0
+ end
+
+ it 'has the deletion trigger present' do
+ sql = <<-SQL
+ SELECT trigger_name
+ FROM information_schema.triggers
+ WHERE event_object_table = '#{table_name}'
+ SQL
+
+ triggers = connection.execute(sql)
+
+ expected_trigger_name = "#{table_name}_loose_fk_trigger"
+ expect(triggers.pluck('trigger_name')).to include(expected_trigger_name)
+ end
+
+ it 'records record deletions' do
+ model = create(factory_name) # rubocop: disable Rails/SaveBang
+ model.destroy!
+
+ deleted_record = LooseForeignKeys::DeletedRecord.find_by(fully_qualified_table_name: "#{connection.current_schema}.#{table_name}", primary_key_value: model.id)
+
+ expect(deleted_record).not_to be_nil
+ end
+
+ it 'cleans up record deletions' do
+ model = create(factory_name) # rubocop: disable Rails/SaveBang
+
+ expect { model.destroy! }.to change { LooseForeignKeys::DeletedRecord.count }.by(1)
+
+ LooseForeignKeys::ProcessDeletedRecordsService.new(connection: connection).execute
+
+ expect(LooseForeignKeys::DeletedRecord.status_pending.count).to be(0)
+ expect(LooseForeignKeys::DeletedRecord.status_processed.count).to be(1)
+ end
+end
diff --git a/spec/support/shared_examples/metrics/transaction_metrics_with_labels_shared_examples.rb b/spec/support/shared_examples/metrics/transaction_metrics_with_labels_shared_examples.rb
new file mode 100644
index 00000000000..286c60f1f4f
--- /dev/null
+++ b/spec/support/shared_examples/metrics/transaction_metrics_with_labels_shared_examples.rb
@@ -0,0 +1,219 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'transaction metrics with labels' do
+ let(:sensitive_tags) do
+ {
+ path: 'private',
+ branch: 'sensitive'
+ }
+ end
+
+ around do |example|
+ described_class.reload_metric!
+ example.run
+ described_class.reload_metric!
+ end
+
+ describe '.prometheus_metric' do
+ let(:prometheus_metric) { instance_double(Prometheus::Client::Histogram, observe: nil, base_labels: {}) }
+
+ it 'adds a metric' do
+ expect(::Gitlab::Metrics).to receive(:histogram).with(
+ :meow_observe, 'Meow observe histogram', hash_including(*described_class::BASE_LABEL_KEYS), be_a(Array)
+ ).and_return(prometheus_metric)
+
+ expect do |block|
+ metric = described_class.prometheus_metric(:meow_observe, :histogram, &block)
+ expect(metric).to be(prometheus_metric)
+ end.to yield_control
+ end
+ end
+
+ describe '#method_call_for' do
+ it 'returns a MethodCall' do
+ method = transaction_obj.method_call_for('Foo#bar', :Foo, '#bar')
+
+ expect(method).to be_an_instance_of(Gitlab::Metrics::MethodCall)
+ end
+ end
+
+ describe '#add_event' do
+ let(:prometheus_metric) { instance_double(Prometheus::Client::Counter, increment: nil, base_labels: {}) }
+
+ it 'adds a metric' do
+ expect(prometheus_metric).to receive(:increment).with(labels)
+ expect(described_class).to receive(:fetch_metric).with(:counter, :gitlab_transaction_event_meow_total).and_return(prometheus_metric)
+
+ transaction_obj.add_event(:meow)
+ end
+
+ it 'allows tracking of custom tags' do
+ expect(prometheus_metric).to receive(:increment).with(labels.merge(animal: "dog"))
+ expect(described_class).to receive(:fetch_metric).with(:counter, :gitlab_transaction_event_bau_total).and_return(prometheus_metric)
+
+ transaction_obj.add_event(:bau, animal: 'dog')
+ end
+
+ context 'with sensitive tags' do
+ it 'filters tags' do
+ expect(described_class).to receive(:fetch_metric).with(:counter, :gitlab_transaction_event_bau_total).and_return(prometheus_metric)
+ expect(prometheus_metric).not_to receive(:increment).with(hash_including(sensitive_tags))
+
+ transaction_obj.add_event(:bau, **sensitive_tags.merge(sane: 'yes'))
+ end
+ end
+ end
+
+ describe '#increment' do
+ let(:prometheus_metric) { instance_double(Prometheus::Client::Counter, increment: nil, base_labels: {}) }
+
+ it 'adds a metric' do
+ expect(::Gitlab::Metrics).to receive(:counter).with(
+ :meow, 'Meow counter', hash_including(*described_class::BASE_LABEL_KEYS)
+ ).and_return(prometheus_metric)
+ expect(prometheus_metric).to receive(:increment).with(labels, 1)
+
+ transaction_obj.increment(:meow, 1)
+ end
+
+ context 'with block' do
+ it 'overrides docstring' do
+ expect(::Gitlab::Metrics).to receive(:counter).with(
+ :block_docstring, 'test', hash_including(*described_class::BASE_LABEL_KEYS)
+ ).and_return(prometheus_metric)
+ expect(prometheus_metric).to receive(:increment).with(labels, 1)
+
+ transaction_obj.increment(:block_docstring, 1) do
+ docstring 'test'
+ end
+ end
+
+ it 'overrides labels' do
+ expect(::Gitlab::Metrics).to receive(:counter).with(
+ :block_labels, 'Block labels counter', hash_including(*described_class::BASE_LABEL_KEYS)
+ ).and_return(prometheus_metric)
+ expect(prometheus_metric).to receive(:increment).with(labels.merge(sane: 'yes'), 1)
+
+ transaction_obj.increment(:block_labels, 1, sane: 'yes') do
+ label_keys %i(sane)
+ end
+ end
+
+ it 'filters sensitive tags' do
+ labels_keys = sensitive_tags.keys
+
+ expect(::Gitlab::Metrics).to receive(:counter).with(
+ :metric_with_sensitive_block, 'Metric with sensitive block counter', hash_excluding(labels_keys)
+ ).and_return(prometheus_metric)
+ expect(prometheus_metric).to receive(:increment).with(labels, 1)
+
+ transaction_obj.increment(:metric_with_sensitive_block, 1, sensitive_tags) do
+ label_keys labels_keys
+ end
+ end
+ end
+ end
+
+ describe '#set' do
+ let(:prometheus_metric) { instance_double(Prometheus::Client::Gauge, set: nil, base_labels: {}) }
+
+ it 'adds a metric' do
+ expect(::Gitlab::Metrics).to receive(:gauge).with(
+ :meow_set, 'Meow set gauge', hash_including(*described_class::BASE_LABEL_KEYS), :all
+ ).and_return(prometheus_metric)
+ expect(prometheus_metric).to receive(:set).with(labels, 99)
+
+ transaction_obj.set(:meow_set, 99)
+ end
+
+ context 'with block' do
+ it 'overrides docstring' do
+ expect(::Gitlab::Metrics).to receive(:gauge).with(
+ :block_docstring_set, 'test', hash_including(*described_class::BASE_LABEL_KEYS), :all
+ ).and_return(prometheus_metric)
+ expect(prometheus_metric).to receive(:set).with(labels, 99)
+
+ transaction_obj.set(:block_docstring_set, 99) do
+ docstring 'test'
+ end
+ end
+
+ it 'overrides labels' do
+ expect(::Gitlab::Metrics).to receive(:gauge).with(
+ :block_labels_set, 'Block labels set gauge', hash_including(*described_class::BASE_LABEL_KEYS), :all
+ ).and_return(prometheus_metric)
+ expect(prometheus_metric).to receive(:set).with(labels.merge(sane: 'yes'), 99)
+
+ transaction_obj.set(:block_labels_set, 99, sane: 'yes') do
+ label_keys %i(sane)
+ end
+ end
+
+ it 'filters sensitive tags' do
+ labels_keys = sensitive_tags.keys
+
+ expect(::Gitlab::Metrics).to receive(:gauge).with(
+ :metric_set_with_sensitive_block, 'Metric set with sensitive block gauge', hash_excluding(*labels_keys), :all
+ ).and_return(prometheus_metric)
+ expect(prometheus_metric).to receive(:set).with(labels, 99)
+
+ transaction_obj.set(:metric_set_with_sensitive_block, 99, sensitive_tags) do
+ label_keys label_keys
+ end
+ end
+ end
+ end
+
+ describe '#observe' do
+ let(:prometheus_metric) { instance_double(Prometheus::Client::Histogram, observe: nil, base_labels: {}) }
+
+ it 'adds a metric' do
+ expect(::Gitlab::Metrics).to receive(:histogram).with(
+ :meow_observe, 'Meow observe histogram', hash_including(*described_class::BASE_LABEL_KEYS), kind_of(Array)
+ ).and_return(prometheus_metric)
+ expect(prometheus_metric).to receive(:observe).with(labels, 2.0)
+
+ transaction_obj.observe(:meow_observe, 2.0)
+ end
+
+ context 'with block' do
+ it 'overrides docstring' do
+ expect(::Gitlab::Metrics).to receive(:histogram).with(
+ :block_docstring_observe, 'test', hash_including(*described_class::BASE_LABEL_KEYS), kind_of(Array)
+ ).and_return(prometheus_metric)
+ expect(prometheus_metric).to receive(:observe).with(labels, 2.0)
+
+ transaction_obj.observe(:block_docstring_observe, 2.0) do
+ docstring 'test'
+ end
+ end
+
+ it 'overrides labels' do
+ expect(::Gitlab::Metrics).to receive(:histogram).with(
+ :block_labels_observe, 'Block labels observe histogram', hash_including(*described_class::BASE_LABEL_KEYS), kind_of(Array)
+ ).and_return(prometheus_metric)
+ expect(prometheus_metric).to receive(:observe).with(labels.merge(sane: 'yes'), 2.0)
+
+ transaction_obj.observe(:block_labels_observe, 2.0, sane: 'yes') do
+ label_keys %i(sane)
+ end
+ end
+
+ it 'filters sensitive tags' do
+ labels_keys = sensitive_tags.keys
+
+ expect(::Gitlab::Metrics).to receive(:histogram).with(
+ :metric_observe_with_sensitive_block,
+ 'Metric observe with sensitive block histogram',
+ hash_excluding(labels_keys),
+ kind_of(Array)
+ ).and_return(prometheus_metric)
+ expect(prometheus_metric).to receive(:observe).with(labels, 2.0)
+
+ transaction_obj.observe(:metric_observe_with_sensitive_block, 2.0, sensitive_tags) do
+ label_keys label_keys
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb b/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
index f928fb1eb43..d823e7ac221 100644
--- a/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
+++ b/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
@@ -12,6 +12,7 @@ RSpec.shared_examples 'StageEventModel' do
project_id: 4,
author_id: 5,
milestone_id: 6,
+ state_id: 1,
start_event_timestamp: time,
end_event_timestamp: time
},
@@ -22,6 +23,7 @@ RSpec.shared_examples 'StageEventModel' do
project_id: 11,
author_id: 12,
milestone_id: 13,
+ state_id: 1,
start_event_timestamp: time,
end_event_timestamp: time
}
@@ -34,8 +36,9 @@ RSpec.shared_examples 'StageEventModel' do
described_class.issuable_id_column,
:group_id,
:project_id,
- :milestone_id,
:author_id,
+ :milestone_id,
+ :state_id,
:start_event_timestamp,
:end_event_timestamp
]
@@ -59,10 +62,120 @@ RSpec.shared_examples 'StageEventModel' do
upsert_data
output_data = described_class.all.map do |record|
- column_order.map { |column| record[column] }
+ column_order.map do |column|
+ if column == :state_id
+ described_class.states[record[column]]
+ else
+ record[column]
+ end
+ end
end.sort
expect(input_data.map(&:values).sort).to eq(output_data)
end
end
+
+ describe 'scopes' do
+ def attributes(array)
+ array.map(&:attributes)
+ end
+
+ RSpec::Matchers.define :match_attributes do |expected|
+ match do |actual|
+ actual.map(&:attributes) == expected.map(&:attributes)
+ end
+ end
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:user) }
+ let_it_be(:milestone) { create(:milestone) }
+ let_it_be(:issuable_with_assignee) { create(issuable_factory, assignees: [user])}
+
+ let_it_be(:record) { create(stage_event_factory, start_event_timestamp: 3.years.ago.to_date, end_event_timestamp: 2.years.ago.to_date) }
+ let_it_be(:record_with_author) { create(stage_event_factory, author_id: user.id) }
+ let_it_be(:record_with_project) { create(stage_event_factory, project_id: project.id) }
+ let_it_be(:record_with_group) { create(stage_event_factory, group_id: project.namespace_id) }
+ let_it_be(:record_with_assigned_issuable) { create(stage_event_factory, described_class.issuable_id_column => issuable_with_assignee.id) }
+ let_it_be(:record_with_milestone) { create(stage_event_factory, milestone_id: milestone.id) }
+
+ it 'filters by stage_event_hash_id' do
+ records = described_class.by_stage_event_hash_id(record.stage_event_hash_id)
+
+ expect(records).to match_attributes([record])
+ end
+
+ it 'filters by project_id' do
+ records = described_class.by_project_id(project.id)
+
+ expect(records).to match_attributes([record_with_project])
+ end
+
+ it 'filters by group_id' do
+ records = described_class.by_group_id(project.namespace_id)
+
+ expect(records).to match_attributes([record_with_group])
+ end
+
+ it 'filters by author_id' do
+ records = described_class.authored(user)
+
+ expect(records).to match_attributes([record_with_author])
+ end
+
+ it 'filters by assignee' do
+ records = described_class.assigned_to(user)
+
+ expect(records).to match_attributes([record_with_assigned_issuable])
+ end
+
+ it 'filters by milestone_id' do
+ records = described_class.with_milestone_id(milestone.id)
+
+ expect(records).to match_attributes([record_with_milestone])
+ end
+
+ describe 'start_event_timestamp filtering' do
+ it 'when range is given' do
+ records = described_class
+ .start_event_timestamp_after(4.years.ago)
+ .start_event_timestamp_before(2.years.ago)
+
+ expect(records).to match_attributes([record])
+ end
+
+ it 'when specifying upper bound' do
+ records = described_class.start_event_timestamp_before(2.years.ago)
+
+ expect(attributes(records)).to include(attributes([record]).first)
+ end
+
+ it 'when specifying the lower bound' do
+ records = described_class.start_event_timestamp_after(4.years.ago)
+
+ expect(attributes(records)).to include(attributes([record]).first)
+ end
+ end
+
+ describe 'end_event_timestamp filtering' do
+ it 'when range is given' do
+ records = described_class
+ .end_event_timestamp_after(3.years.ago)
+ .end_event_timestamp_before(1.year.ago)
+
+ expect(records).to match_attributes([record])
+ end
+
+ it 'when specifying upper bound' do
+ records = described_class.end_event_timestamp_before(1.year.ago)
+
+ expect(attributes(records)).to include(attributes([record]).first)
+ end
+
+ it 'when specifying the lower bound' do
+ records = described_class.end_event_timestamp_after(3.years.ago)
+
+ expect(attributes(records)).to include(attributes([record]).first)
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb b/spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb
index a4e0d6c871e..2d08de297a3 100644
--- a/spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb
@@ -11,18 +11,18 @@ RSpec.shared_examples 'ttl_expirable' do
it { is_expected.to validate_presence_of(:status) }
end
- describe '.updated_before' do
+ describe '.read_before' do
# rubocop:disable Rails/SaveBang
let_it_be_with_reload(:item1) { create(class_symbol) }
let_it_be(:item2) { create(class_symbol) }
# rubocop:enable Rails/SaveBang
before do
- item1.update_column(:updated_at, 1.month.ago)
+ item1.update_column(:read_at, 1.month.ago)
end
it 'returns items with created at older than the supplied number of days' do
- expect(described_class.updated_before(10)).to contain_exactly(item1)
+ expect(described_class.read_before(10)).to contain_exactly(item1)
end
end
@@ -48,4 +48,13 @@ RSpec.shared_examples 'ttl_expirable' do
expect(described_class.lock_next_by(:created_at)).to contain_exactly(item3)
end
end
+
+ describe '#read', :freeze_time do
+ let_it_be(:old_read_at) { 1.day.ago }
+ let_it_be(:item1) { create(class_symbol, read_at: old_read_at) }
+
+ it 'updates read_at' do
+ expect { item1.read! }.to change { item1.reload.read_at }
+ end
+ end
end
diff --git a/spec/support/shared_examples/models/member_shared_examples.rb b/spec/support/shared_examples/models/member_shared_examples.rb
index 56c202cb228..a2909c66e22 100644
--- a/spec/support/shared_examples/models/member_shared_examples.rb
+++ b/spec/support/shared_examples/models/member_shared_examples.rb
@@ -299,6 +299,22 @@ RSpec.shared_examples_for "member creation" do
end
end
end
+
+ context 'when `tasks_to_be_done` and `tasks_project_id` are passed' do
+ before do
+ stub_experiments(invite_members_for_task: true)
+ end
+
+ it 'creates a member_task with the correct attributes', :aggregate_failures do
+ task_project = source.is_a?(Group) ? create(:project, group: source) : source
+ described_class.new(source, user, :developer, tasks_to_be_done: %w(ci code), tasks_project_id: task_project.id).execute
+
+ member = source.members.last
+
+ expect(member.tasks_to_be_done).to match_array([:ci, :code])
+ expect(member.member_task.project).to eq(task_project)
+ end
+ end
end
end
@@ -379,5 +395,20 @@ RSpec.shared_examples_for "bulk member creation" do
expect(members).to all(be_persisted)
end
end
+
+ context 'when `tasks_to_be_done` and `tasks_project_id` are passed' do
+ before do
+ stub_experiments(invite_members_for_task: true)
+ end
+
+ it 'creates a member_task with the correct attributes', :aggregate_failures do
+ task_project = source.is_a?(Group) ? create(:project, group: source) : source
+ members = described_class.add_users(source, [user1], :developer, tasks_to_be_done: %w(ci code), tasks_project_id: task_project.id)
+ member = members.last
+
+ expect(member.tasks_to_be_done).to match_array([:ci, :code])
+ expect(member.member_task.project).to eq(task_project)
+ end
+ end
end
end
diff --git a/spec/support/shared_examples/models/reviewer_state_shared_examples.rb b/spec/support/shared_examples/models/reviewer_state_shared_examples.rb
new file mode 100644
index 00000000000..f1392768b06
--- /dev/null
+++ b/spec/support/shared_examples/models/reviewer_state_shared_examples.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'having reviewer state' do
+ describe 'mr_attention_requests feature flag is disabled' do
+ before do
+ stub_feature_flags(mr_attention_requests: false)
+ end
+
+ it { is_expected.to have_attributes(state: 'unreviewed') }
+ end
+
+ describe 'mr_attention_requests feature flag is enabled' do
+ it { is_expected.to have_attributes(state: 'attention_requested') }
+ end
+end
diff --git a/spec/support/shared_examples/namespaces/traversal_examples.rb b/spec/support/shared_examples/namespaces/traversal_examples.rb
index d126b242fb0..ac6a843663f 100644
--- a/spec/support/shared_examples/namespaces/traversal_examples.rb
+++ b/spec/support/shared_examples/namespaces/traversal_examples.rb
@@ -22,6 +22,8 @@ RSpec.shared_examples 'namespace traversal' do
let_it_be(:deep_nested_group) { create(:group, parent: nested_group) }
let_it_be(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
let_it_be(:groups) { [group, nested_group, deep_nested_group, very_deep_nested_group] }
+ let_it_be(:project) { create(:project, group: nested_group) }
+ let_it_be(:project_namespace) { project.project_namespace }
describe '#root_ancestor' do
it 'returns the correct root ancestor' do
@@ -65,6 +67,7 @@ RSpec.shared_examples 'namespace traversal' do
expect(deep_nested_group.ancestors).to contain_exactly(group, nested_group)
expect(nested_group.ancestors).to contain_exactly(group)
expect(group.ancestors).to eq([])
+ expect(project_namespace.ancestors).to be_empty
end
context 'with asc hierarchy_order' do
@@ -73,6 +76,7 @@ RSpec.shared_examples 'namespace traversal' do
expect(deep_nested_group.ancestors(hierarchy_order: :asc)).to eq [nested_group, group]
expect(nested_group.ancestors(hierarchy_order: :asc)).to eq [group]
expect(group.ancestors(hierarchy_order: :asc)).to eq([])
+ expect(project_namespace.ancestors(hierarchy_order: :asc)).to be_empty
end
end
@@ -82,6 +86,7 @@ RSpec.shared_examples 'namespace traversal' do
expect(deep_nested_group.ancestors(hierarchy_order: :desc)).to eq [group, nested_group]
expect(nested_group.ancestors(hierarchy_order: :desc)).to eq [group]
expect(group.ancestors(hierarchy_order: :desc)).to eq([])
+ expect(project_namespace.ancestors(hierarchy_order: :desc)).to be_empty
end
end
@@ -98,6 +103,7 @@ RSpec.shared_examples 'namespace traversal' do
expect(deep_nested_group.ancestor_ids).to contain_exactly(group.id, nested_group.id)
expect(nested_group.ancestor_ids).to contain_exactly(group.id)
expect(group.ancestor_ids).to be_empty
+ expect(project_namespace.ancestor_ids).to be_empty
end
context 'with asc hierarchy_order' do
@@ -106,6 +112,7 @@ RSpec.shared_examples 'namespace traversal' do
expect(deep_nested_group.ancestor_ids(hierarchy_order: :asc)).to eq [nested_group.id, group.id]
expect(nested_group.ancestor_ids(hierarchy_order: :asc)).to eq [group.id]
expect(group.ancestor_ids(hierarchy_order: :asc)).to eq([])
+ expect(project_namespace.ancestor_ids(hierarchy_order: :asc)).to eq([])
end
end
@@ -115,6 +122,7 @@ RSpec.shared_examples 'namespace traversal' do
expect(deep_nested_group.ancestor_ids(hierarchy_order: :desc)).to eq [group.id, nested_group.id]
expect(nested_group.ancestor_ids(hierarchy_order: :desc)).to eq [group.id]
expect(group.ancestor_ids(hierarchy_order: :desc)).to eq([])
+ expect(project_namespace.ancestor_ids(hierarchy_order: :desc)).to eq([])
end
end
@@ -131,6 +139,7 @@ RSpec.shared_examples 'namespace traversal' do
expect(deep_nested_group.self_and_ancestors).to contain_exactly(group, nested_group, deep_nested_group)
expect(nested_group.self_and_ancestors).to contain_exactly(group, nested_group)
expect(group.self_and_ancestors).to contain_exactly(group)
+ expect(project_namespace.self_and_ancestors).to contain_exactly(project_namespace)
end
context 'with asc hierarchy_order' do
@@ -139,6 +148,7 @@ RSpec.shared_examples 'namespace traversal' do
expect(deep_nested_group.self_and_ancestors(hierarchy_order: :asc)).to eq [deep_nested_group, nested_group, group]
expect(nested_group.self_and_ancestors(hierarchy_order: :asc)).to eq [nested_group, group]
expect(group.self_and_ancestors(hierarchy_order: :asc)).to eq([group])
+ expect(project_namespace.self_and_ancestors(hierarchy_order: :asc)).to eq([project_namespace])
end
end
@@ -148,6 +158,7 @@ RSpec.shared_examples 'namespace traversal' do
expect(deep_nested_group.self_and_ancestors(hierarchy_order: :desc)).to eq [group, nested_group, deep_nested_group]
expect(nested_group.self_and_ancestors(hierarchy_order: :desc)).to eq [group, nested_group]
expect(group.self_and_ancestors(hierarchy_order: :desc)).to eq([group])
+ expect(project_namespace.self_and_ancestors(hierarchy_order: :desc)).to eq([project_namespace])
end
end
@@ -164,6 +175,7 @@ RSpec.shared_examples 'namespace traversal' do
expect(deep_nested_group.self_and_ancestor_ids).to contain_exactly(group.id, nested_group.id, deep_nested_group.id)
expect(nested_group.self_and_ancestor_ids).to contain_exactly(group.id, nested_group.id)
expect(group.self_and_ancestor_ids).to contain_exactly(group.id)
+ expect(project_namespace.self_and_ancestor_ids).to contain_exactly(project_namespace.id)
end
context 'with asc hierarchy_order' do
@@ -172,6 +184,7 @@ RSpec.shared_examples 'namespace traversal' do
expect(deep_nested_group.self_and_ancestor_ids(hierarchy_order: :asc)).to eq [deep_nested_group.id, nested_group.id, group.id]
expect(nested_group.self_and_ancestor_ids(hierarchy_order: :asc)).to eq [nested_group.id, group.id]
expect(group.self_and_ancestor_ids(hierarchy_order: :asc)).to eq([group.id])
+ expect(project_namespace.self_and_ancestor_ids(hierarchy_order: :asc)).to eq([project_namespace.id])
end
end
@@ -181,6 +194,7 @@ RSpec.shared_examples 'namespace traversal' do
expect(deep_nested_group.self_and_ancestor_ids(hierarchy_order: :desc)).to eq [group.id, nested_group.id, deep_nested_group.id]
expect(nested_group.self_and_ancestor_ids(hierarchy_order: :desc)).to eq [group.id, nested_group.id]
expect(group.self_and_ancestor_ids(hierarchy_order: :desc)).to eq([group.id])
+ expect(project_namespace.self_and_ancestor_ids(hierarchy_order: :desc)).to eq([project_namespace.id])
end
end
@@ -205,6 +219,10 @@ RSpec.shared_examples 'namespace traversal' do
describe '#recursive_descendants' do
it_behaves_like 'recursive version', :descendants
end
+
+ it 'does not include project namespaces' do
+ expect(group.descendants.to_a).not_to include(project_namespace)
+ end
end
describe '#self_and_descendants' do
@@ -223,6 +241,10 @@ RSpec.shared_examples 'namespace traversal' do
it_behaves_like 'recursive version', :self_and_descendants
end
+
+ it 'does not include project namespaces' do
+ expect(group.self_and_descendants.to_a).not_to include(project_namespace)
+ end
end
describe '#self_and_descendant_ids' do
diff --git a/spec/support/shared_examples/namespaces/traversal_scope_examples.rb b/spec/support/shared_examples/namespaces/traversal_scope_examples.rb
index 74b1bacc560..4c09c1c2a3b 100644
--- a/spec/support/shared_examples/namespaces/traversal_scope_examples.rb
+++ b/spec/support/shared_examples/namespaces/traversal_scope_examples.rb
@@ -25,12 +25,6 @@ RSpec.shared_examples 'namespace traversal scopes' do
it { is_expected.to contain_exactly(group_1.id, group_2.id) }
end
- describe '.without_sti_condition' do
- subject { described_class.without_sti_condition }
-
- it { expect(subject.where_values_hash).not_to have_key(:type) }
- end
-
describe '.order_by_depth' do
subject { described_class.where(id: [group_1, nested_group_1, deep_nested_group_1]).order_by_depth(direction) }
@@ -55,6 +49,53 @@ RSpec.shared_examples 'namespace traversal scopes' do
it { is_expected.to eq described_class.column_names }
end
+ shared_examples '.roots' do
+ context 'with only sub-groups' do
+ subject { described_class.where(id: [deep_nested_group_1, nested_group_1, deep_nested_group_2]).roots }
+
+ it { is_expected.to contain_exactly(group_1, group_2) }
+ end
+
+ context 'with only root groups' do
+ subject { described_class.where(id: [group_1, group_2]).roots }
+
+ it { is_expected.to contain_exactly(group_1, group_2) }
+ end
+
+ context 'with all groups' do
+ subject { described_class.where(id: groups).roots }
+
+ it { is_expected.to contain_exactly(group_1, group_2) }
+ end
+ end
+
+ describe '.roots' do
+ context "use_traversal_ids_roots feature flag is true" do
+ before do
+ stub_feature_flags(use_traversal_ids: true)
+ stub_feature_flags(use_traversal_ids_roots: true)
+ end
+
+ it_behaves_like '.roots'
+
+ it 'not make recursive queries' do
+ expect { described_class.where(id: [nested_group_1]).roots.load }.not_to make_queries_matching(/WITH RECURSIVE/)
+ end
+ end
+
+ context "use_traversal_ids_roots feature flag is false" do
+ before do
+ stub_feature_flags(use_traversal_ids_roots: false)
+ end
+
+ it_behaves_like '.roots'
+
+ it 'make recursive queries' do
+ expect { described_class.where(id: [nested_group_1]).roots.load }.to make_queries_matching(/WITH RECURSIVE/)
+ end
+ end
+ end
+
shared_examples '.self_and_ancestors' do
subject { described_class.where(id: [nested_group_1, nested_group_2]).self_and_ancestors }
@@ -156,7 +197,7 @@ RSpec.shared_examples 'namespace traversal scopes' do
end
end
- describe '.self_and_descendants' do
+ shared_examples '.self_and_descendants' do
subject { described_class.where(id: [nested_group_1, nested_group_2]).self_and_descendants }
it { is_expected.to contain_exactly(nested_group_1, deep_nested_group_1, nested_group_2, deep_nested_group_2) }
@@ -174,7 +215,19 @@ RSpec.shared_examples 'namespace traversal scopes' do
end
end
- describe '.self_and_descendant_ids' do
+ describe '.self_and_descendants' do
+ include_examples '.self_and_descendants'
+
+ context 'with traversal_ids_btree feature flag disabled' do
+ before do
+ stub_feature_flags(traversal_ids_btree: false)
+ end
+
+ include_examples '.self_and_descendants'
+ end
+ end
+
+ shared_examples '.self_and_descendant_ids' do
subject { described_class.where(id: [nested_group_1, nested_group_2]).self_and_descendant_ids.pluck(:id) }
it { is_expected.to contain_exactly(nested_group_1.id, deep_nested_group_1.id, nested_group_2.id, deep_nested_group_2.id) }
@@ -190,4 +243,16 @@ RSpec.shared_examples 'namespace traversal scopes' do
it { is_expected.to contain_exactly(deep_nested_group_1.id, deep_nested_group_2.id) }
end
end
+
+ describe '.self_and_descendant_ids' do
+ include_examples '.self_and_descendant_ids'
+
+ context 'with traversal_ids_btree feature flag disabled' do
+ before do
+ stub_feature_flags(traversal_ids_btree: false)
+ end
+
+ include_examples '.self_and_descendant_ids'
+ end
+ end
end
diff --git a/spec/support/shared_examples/quick_actions/issue/promote_to_incident_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/promote_to_incident_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..5167d27f8b9
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issue/promote_to_incident_quick_action_shared_examples.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'promote_to_incident quick action' do
+ describe '/promote_to_incident' do
+ context 'when issue can be promoted' do
+ it 'promotes issue to incident' do
+ add_note('/promote_to_incident')
+
+ expect(issue.reload.issue_type).to eq('incident')
+ expect(page).to have_content('Issue has been promoted to incident')
+ end
+ end
+
+ context 'when issue is already an incident' do
+ let(:issue) { create(:incident, project: project) }
+
+ it 'does not promote the issue' do
+ add_note('/promote_to_incident')
+
+ expect(page).to have_content('Could not apply promote_to_incident command')
+ end
+ end
+
+ context 'when user does not have permissions' do
+ let(:guest) { create(:user) }
+
+ before do
+ sign_in(guest)
+ visit project_issue_path(project, issue)
+ wait_for_all_requests
+ end
+
+ it 'does not promote the issue' do
+ add_note('/promote_to_incident')
+
+ expect(page).to have_content('Could not apply promote_to_incident command')
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/debian_common_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_common_shared_examples.rb
new file mode 100644
index 00000000000..e0225070986
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/debian_common_shared_examples.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'rejects Debian access with unknown container id' do |anonymous_status, auth_method|
+ context 'with an unknown container' do
+ let(:container) { double(id: non_existing_record_id) }
+
+ context 'as anonymous' do
+ it_behaves_like 'Debian packages GET request', anonymous_status, nil
+ end
+
+ context 'as authenticated user' do
+ include_context 'Debian repository auth headers', :not_a_member, auth_method do
+ it_behaves_like 'Debian packages GET request', :not_found, nil
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/debian_distributions_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_distributions_shared_examples.rb
new file mode 100644
index 00000000000..5cd63c33936
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/debian_distributions_shared_examples.rb
@@ -0,0 +1,192 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'Debian distributions GET request' do |status, body = nil|
+ and_body = body.nil? ? '' : ' and expected body'
+
+ it "returns #{status}#{and_body}" do
+ subject
+
+ expect(response).to have_gitlab_http_status(status)
+
+ unless body.nil?
+ expect(response.body).to match(body)
+ end
+ end
+end
+
+RSpec.shared_examples 'Debian distributions PUT request' do |status, body|
+ and_body = body.nil? ? '' : ' and expected body'
+
+ if status == :success
+ it 'updates distribution', :aggregate_failures do
+ expect(::Packages::Debian::UpdateDistributionService).to receive(:new).with(distribution, api_params.except(:codename)).and_call_original
+
+ expect { subject }
+ .to not_change { Packages::Debian::GroupDistribution.all.count + Packages::Debian::ProjectDistribution.all.count }
+ .and not_change { Packages::Debian::GroupComponent.all.count + Packages::Debian::ProjectComponent.all.count }
+ .and not_change { Packages::Debian::GroupArchitecture.all.count + Packages::Debian::ProjectArchitecture.all.count }
+
+ expect(response).to have_gitlab_http_status(status)
+ expect(response.media_type).to eq('application/json')
+
+ unless body.nil?
+ expect(response.body).to match(body)
+ end
+ end
+ else
+ it "returns #{status}#{and_body}", :aggregate_failures do
+ subject
+
+ expect(response).to have_gitlab_http_status(status)
+
+ unless body.nil?
+ expect(response.body).to match(body)
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'Debian distributions DELETE request' do |status, body|
+ and_body = body.nil? ? '' : ' and expected body'
+
+ if status == :success
+ it 'updates distribution', :aggregate_failures do
+ expect { subject }
+ .to change { Packages::Debian::GroupDistribution.all.count + Packages::Debian::ProjectDistribution.all.count }.by(-1)
+ .and change { Packages::Debian::GroupComponent.all.count + Packages::Debian::ProjectComponent.all.count }.by(-1)
+ .and change { Packages::Debian::GroupArchitecture.all.count + Packages::Debian::ProjectArchitecture.all.count }.by(-2)
+
+ expect(response).to have_gitlab_http_status(status)
+ expect(response.media_type).to eq('application/json')
+
+ unless body.nil?
+ expect(response.body).to match(body)
+ end
+ end
+ else
+ it "returns #{status}#{and_body}", :aggregate_failures do
+ subject
+
+ expect(response).to have_gitlab_http_status(status)
+
+ unless body.nil?
+ expect(response.body).to match(body)
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'Debian distributions POST request' do |status, body|
+ and_body = body.nil? ? '' : ' and expected body'
+
+ if status == :created
+ it 'creates distribution', :aggregate_failures do
+ expect(::Packages::Debian::CreateDistributionService).to receive(:new).with(container, user, api_params).and_call_original
+
+ expect { subject }
+ .to change { Packages::Debian::GroupDistribution.all.count + Packages::Debian::ProjectDistribution.all.count }.by(1)
+ .and change { Packages::Debian::GroupComponent.all.count + Packages::Debian::ProjectComponent.all.count }.by(1)
+ .and change { Packages::Debian::GroupArchitecture.all.count + Packages::Debian::ProjectArchitecture.all.count }.by(2)
+
+ expect(response).to have_gitlab_http_status(status)
+ expect(response.media_type).to eq('application/json')
+
+ unless body.nil?
+ expect(response.body).to match(body)
+ end
+ end
+ else
+ it "returns #{status}#{and_body}", :aggregate_failures do
+ subject
+
+ expect(response).to have_gitlab_http_status(status)
+
+ unless body.nil?
+ expect(response.body).to match(body)
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'Debian distributions read endpoint' do |desired_behavior, success_status, success_body|
+ context 'with valid container' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:visibility_level, :user_type, :auth_method, :expected_status, :expected_body) do
+ :public | :guest | :private_token | success_status | success_body
+ :public | :not_a_member | :private_token | success_status | success_body
+ :public | :anonymous | :private_token | success_status | success_body
+ :public | :invalid_token | :private_token | :unauthorized | nil
+ :private | :developer | :private_token | success_status | success_body
+ :private | :developer | :basic | :not_found | nil
+ :private | :guest | :private_token | :forbidden | nil
+ :private | :not_a_member | :private_token | :not_found | nil
+ :private | :anonymous | :private_token | :not_found | nil
+ :private | :invalid_token | :private_token | :unauthorized | nil
+ end
+
+ with_them do
+ include_context 'Debian repository access', params[:visibility_level], params[:user_type], params[:auth_method] do
+ it_behaves_like "Debian distributions #{desired_behavior} request", params[:expected_status], params[:expected_body]
+ end
+ end
+ end
+
+ it_behaves_like 'rejects Debian access with unknown container id', :not_found, :private_token
+end
+
+RSpec.shared_examples 'Debian distributions write endpoint' do |desired_behavior, success_status, success_body|
+ context 'with valid container' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:visibility_level, :user_type, :auth_method, :expected_status, :expected_body) do
+ :public | :developer | :private_token | success_status | success_body
+ :public | :developer | :basic | :unauthorized | nil
+ :public | :guest | :private_token | :forbidden | nil
+ :public | :not_a_member | :private_token | :forbidden | nil
+ :public | :anonymous | :private_token | :unauthorized | nil
+ :public | :invalid_token | :private_token | :unauthorized | nil
+ :private | :developer | :private_token | success_status | success_body
+ :private | :guest | :private_token | :forbidden | nil
+ :private | :not_a_member | :private_token | :not_found | nil
+ :private | :anonymous | :private_token | :not_found | nil
+ :private | :invalid_token | :private_token | :unauthorized | nil
+ end
+
+ with_them do
+ include_context 'Debian repository access', params[:visibility_level], params[:user_type], params[:auth_method] do
+ it_behaves_like "Debian distributions #{desired_behavior} request", params[:expected_status], params[:expected_body]
+ end
+ end
+ end
+
+ it_behaves_like 'rejects Debian access with unknown container id', :not_found, :private_token
+end
+
+RSpec.shared_examples 'Debian distributions maintainer write endpoint' do |desired_behavior, success_status, success_body|
+ context 'with valid container' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:visibility_level, :user_type, :auth_method, :expected_status, :expected_body) do
+ :public | :maintainer | :private_token | success_status | success_body
+ :public | :maintainer | :basic | :unauthorized | nil
+ :public | :developer | :private_token | :forbidden | nil
+ :public | :not_a_member | :private_token | :forbidden | nil
+ :public | :anonymous | :private_token | :unauthorized | nil
+ :public | :invalid_token | :private_token | :unauthorized | nil
+ :private | :maintainer | :private_token | success_status | success_body
+ :private | :developer | :private_token | :forbidden | nil
+ :private | :not_a_member | :private_token | :not_found | nil
+ :private | :anonymous | :private_token | :not_found | nil
+ :private | :invalid_token | :private_token | :unauthorized | nil
+ end
+
+ with_them do
+ include_context 'Debian repository access', params[:visibility_level], params[:user_type], params[:auth_method] do
+ it_behaves_like "Debian distributions #{desired_behavior} request", params[:expected_status], params[:expected_body]
+ end
+ end
+ end
+
+ it_behaves_like 'rejects Debian access with unknown container id', :not_found, :private_token
+end
diff --git a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
index a3ed74085fb..2fd5e6a5f91 100644
--- a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
@@ -1,127 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_context 'Debian repository shared context' do |container_type, can_freeze|
- include_context 'workhorse headers'
-
- before do
- stub_feature_flags(debian_packages: true, debian_group_packages: true)
- end
-
- let_it_be(:private_container, freeze: can_freeze) { create(container_type, :private) }
- let_it_be(:public_container, freeze: can_freeze) { create(container_type, :public) }
- let_it_be(:user, freeze: true) { create(:user) }
- let_it_be(:personal_access_token, freeze: true) { create(:personal_access_token, user: user) }
-
- let_it_be(:private_distribution, freeze: true) { create("debian_#{container_type}_distribution", :with_file, container: private_container, codename: 'existing-codename') }
- let_it_be(:private_component, freeze: true) { create("debian_#{container_type}_component", distribution: private_distribution, name: 'existing-component') }
- let_it_be(:private_architecture_all, freeze: true) { create("debian_#{container_type}_architecture", distribution: private_distribution, name: 'all') }
- let_it_be(:private_architecture, freeze: true) { create("debian_#{container_type}_architecture", distribution: private_distribution, name: 'existing-arch') }
- let_it_be(:private_component_file) { create("debian_#{container_type}_component_file", component: private_component, architecture: private_architecture) }
-
- let_it_be(:public_distribution, freeze: true) { create("debian_#{container_type}_distribution", :with_file, container: public_container, codename: 'existing-codename') }
- let_it_be(:public_component, freeze: true) { create("debian_#{container_type}_component", distribution: public_distribution, name: 'existing-component') }
- let_it_be(:public_architecture_all, freeze: true) { create("debian_#{container_type}_architecture", distribution: public_distribution, name: 'all') }
- let_it_be(:public_architecture, freeze: true) { create("debian_#{container_type}_architecture", distribution: public_distribution, name: 'existing-arch') }
- let_it_be(:public_component_file) { create("debian_#{container_type}_component_file", component: public_component, architecture: public_architecture) }
-
- if container_type == :group
- let_it_be(:private_project) { create(:project, :private, group: private_container) }
- let_it_be(:public_project) { create(:project, :public, group: public_container) }
- let_it_be(:private_project_distribution) { create(:debian_project_distribution, container: private_project, codename: 'existing-codename') }
- let_it_be(:public_project_distribution) { create(:debian_project_distribution, container: public_project, codename: 'existing-codename') }
-
- let(:project) { { private: private_project, public: public_project }[visibility_level] }
- else
- let_it_be(:private_project) { private_container }
- let_it_be(:public_project) { public_container }
- let_it_be(:private_project_distribution) { private_distribution }
- let_it_be(:public_project_distribution) { public_distribution }
- end
-
- let_it_be(:private_package) { create(:debian_package, project: private_project, published_in: private_project_distribution) }
- let_it_be(:public_package) { create(:debian_package, project: public_project, published_in: public_project_distribution) }
-
- let(:visibility_level) { :public }
-
- let(:distribution) { { private: private_distribution, public: public_distribution }[visibility_level] }
- let(:architecture) { { private: private_architecture, public: public_architecture }[visibility_level] }
- let(:component) { { private: private_component, public: public_component }[visibility_level] }
- let(:component_file) { { private: private_component_file, public: public_component_file }[visibility_level] }
- let(:package) { { private: private_package, public: public_package }[visibility_level] }
- let(:letter) { package.name[0..2] == 'lib' ? package.name[0..3] : package.name[0] }
-
- let(:method) { :get }
-
- let(:workhorse_params) do
- if method == :put
- file_upload = fixture_file_upload("spec/fixtures/packages/debian/#{file_name}")
- { file: file_upload }
- else
- {}
- end
- end
-
- let(:api_params) { workhorse_params }
-
- let(:auth_headers) { {} }
- let(:wh_headers) do
- if method == :put
- workhorse_headers
- else
- {}
- end
- end
-
- let(:headers) { auth_headers.merge(wh_headers) }
-
- let(:send_rewritten_field) { true }
-
- subject do
- if method == :put
- workhorse_finalize(
- api(url),
- method: method,
- file_key: :file,
- params: api_params,
- headers: headers,
- send_rewritten_field: send_rewritten_field
- )
- else
- send method, api(url), headers: headers, params: api_params
- end
- end
-end
-
-RSpec.shared_context 'with file_name' do |file_name|
- let(:file_name) { file_name }
-end
-
-RSpec.shared_context 'Debian repository auth headers' do |user_role, user_token, auth_method = :token|
- let(:token) { user_token ? personal_access_token.token : 'wrong' }
-
- let(:auth_headers) do
- if user_role == :anonymous
- {}
- elsif auth_method == :token
- { 'Private-Token' => token }
- else
- basic_auth_header(user.username, token)
- end
- end
-end
-
-RSpec.shared_context 'Debian repository access' do |visibility_level, user_role, add_member, user_token, auth_method|
- include_context 'Debian repository auth headers', user_role, user_token, auth_method do
- let(:containers) { { private: private_container, public: public_container } }
- let(:container) { containers[visibility_level] }
-
- before do
- container.send("add_#{user_role}", user) if add_member && user_role != :anonymous
- end
- end
-end
-
-RSpec.shared_examples 'Debian repository GET request' do |status, body = nil|
+RSpec.shared_examples 'Debian packages GET request' do |status, body = nil|
and_body = body.nil? ? '' : ' and expected body'
it "returns #{status}#{and_body}" do
@@ -135,7 +14,7 @@ RSpec.shared_examples 'Debian repository GET request' do |status, body = nil|
end
end
-RSpec.shared_examples 'Debian repository upload request' do |status, body = nil|
+RSpec.shared_examples 'Debian packages upload request' do |status, body = nil|
and_body = body.nil? ? '' : ' and expected body'
if status == :created
@@ -175,7 +54,7 @@ RSpec.shared_examples 'Debian repository upload request' do |status, body = nil|
end
end
-RSpec.shared_examples 'Debian repository upload authorize request' do |status, body = nil|
+RSpec.shared_examples 'Debian packages upload authorize request' do |status, body = nil|
and_body = body.nil? ? '' : ' and expected body'
if status == :created
@@ -221,237 +100,57 @@ RSpec.shared_examples 'Debian repository upload authorize request' do |status, b
end
end
-RSpec.shared_examples 'Debian repository POST distribution request' do |status, body|
- and_body = body.nil? ? '' : ' and expected body'
-
- if status == :created
- it 'creates distribution', :aggregate_failures do
- expect(::Packages::Debian::CreateDistributionService).to receive(:new).with(container, user, api_params).and_call_original
-
- expect { subject }
- .to change { Packages::Debian::GroupDistribution.all.count + Packages::Debian::ProjectDistribution.all.count }.by(1)
- .and change { Packages::Debian::GroupComponent.all.count + Packages::Debian::ProjectComponent.all.count }.by(1)
- .and change { Packages::Debian::GroupArchitecture.all.count + Packages::Debian::ProjectArchitecture.all.count }.by(2)
-
- expect(response).to have_gitlab_http_status(status)
- expect(response.media_type).to eq('application/json')
-
- unless body.nil?
- expect(response.body).to match(body)
- end
- end
- else
- it "returns #{status}#{and_body}", :aggregate_failures do
- subject
-
- expect(response).to have_gitlab_http_status(status)
-
- unless body.nil?
- expect(response.body).to match(body)
- end
- end
- end
-end
-
-RSpec.shared_examples 'Debian repository PUT distribution request' do |status, body|
- and_body = body.nil? ? '' : ' and expected body'
-
- if status == :success
- it 'updates distribution', :aggregate_failures do
- expect(::Packages::Debian::UpdateDistributionService).to receive(:new).with(distribution, api_params.except(:codename)).and_call_original
-
- expect { subject }
- .to not_change { Packages::Debian::GroupDistribution.all.count + Packages::Debian::ProjectDistribution.all.count }
- .and not_change { Packages::Debian::GroupComponent.all.count + Packages::Debian::ProjectComponent.all.count }
- .and not_change { Packages::Debian::GroupArchitecture.all.count + Packages::Debian::ProjectArchitecture.all.count }
-
- expect(response).to have_gitlab_http_status(status)
- expect(response.media_type).to eq('application/json')
-
- unless body.nil?
- expect(response.body).to match(body)
- end
- end
- else
- it "returns #{status}#{and_body}", :aggregate_failures do
- subject
-
- expect(response).to have_gitlab_http_status(status)
-
- unless body.nil?
- expect(response.body).to match(body)
- end
- end
- end
-end
-
-RSpec.shared_examples 'Debian repository DELETE distribution request' do |status, body|
- and_body = body.nil? ? '' : ' and expected body'
-
- if status == :success
- it 'updates distribution', :aggregate_failures do
- expect { subject }
- .to change { Packages::Debian::GroupDistribution.all.count + Packages::Debian::ProjectDistribution.all.count }.by(-1)
- .and change { Packages::Debian::GroupComponent.all.count + Packages::Debian::ProjectComponent.all.count }.by(-1)
- .and change { Packages::Debian::GroupArchitecture.all.count + Packages::Debian::ProjectArchitecture.all.count }.by(-2)
-
- expect(response).to have_gitlab_http_status(status)
- expect(response.media_type).to eq('application/json')
-
- unless body.nil?
- expect(response.body).to match(body)
- end
- end
- else
- it "returns #{status}#{and_body}", :aggregate_failures do
- subject
-
- expect(response).to have_gitlab_http_status(status)
-
- unless body.nil?
- expect(response.body).to match(body)
- end
- end
- end
-end
-
-RSpec.shared_examples 'rejects Debian access with unknown container id' do |hidden_status|
- context 'with an unknown container' do
- let(:container) { double(id: non_existing_record_id) }
-
- context 'as anonymous' do
- it_behaves_like 'Debian repository GET request', hidden_status, nil
- end
-
- context 'as authenticated user' do
- subject { get api(url), headers: basic_auth_header(user.username, personal_access_token.token) }
-
- it_behaves_like 'Debian repository GET request', :not_found, nil
- end
- end
-end
-
-RSpec.shared_examples 'Debian repository read endpoint' do |desired_behavior, success_status, success_body, authenticate_non_public: true|
- hidden_status = if authenticate_non_public
- :unauthorized
- else
- :not_found
- end
-
- context 'with valid container' do
- using RSpec::Parameterized::TableSyntax
-
- where(:visibility_level, :user_role, :member, :user_token, :expected_status, :expected_body) do
- :public | :developer | true | true | success_status | success_body
- :public | :guest | true | true | success_status | success_body
- :public | :developer | true | false | :unauthorized | nil
- :public | :guest | true | false | :unauthorized | nil
- :public | :developer | false | true | success_status | success_body
- :public | :guest | false | true | success_status | success_body
- :public | :developer | false | false | :unauthorized | nil
- :public | :guest | false | false | :unauthorized | nil
- :public | :anonymous | false | true | success_status | success_body
- :private | :developer | true | true | success_status | success_body
- :private | :guest | true | true | :forbidden | nil
- :private | :developer | true | false | :unauthorized | nil
- :private | :guest | true | false | :unauthorized | nil
- :private | :developer | false | true | :not_found | nil
- :private | :guest | false | true | :not_found | nil
- :private | :developer | false | false | :unauthorized | nil
- :private | :guest | false | false | :unauthorized | nil
- :private | :anonymous | false | true | hidden_status | nil
- end
-
- with_them do
- include_context 'Debian repository access', params[:visibility_level], params[:user_role], params[:member], params[:user_token], :basic do
- it_behaves_like "Debian repository #{desired_behavior}", params[:expected_status], params[:expected_body]
- end
- end
- end
-
- it_behaves_like 'rejects Debian access with unknown container id', hidden_status
-end
-
-RSpec.shared_examples 'Debian repository write endpoint' do |desired_behavior, success_status, success_body, authenticate_non_public: true|
- hidden_status = if authenticate_non_public
- :unauthorized
- else
- :not_found
- end
-
+RSpec.shared_examples 'Debian packages read endpoint' do |desired_behavior, success_status, success_body|
context 'with valid container' do
using RSpec::Parameterized::TableSyntax
- where(:visibility_level, :user_role, :member, :user_token, :expected_status, :expected_body) do
- :public | :developer | true | true | success_status | success_body
- :public | :guest | true | true | :forbidden | nil
- :public | :developer | true | false | :unauthorized | nil
- :public | :guest | true | false | :unauthorized | nil
- :public | :developer | false | true | :forbidden | nil
- :public | :guest | false | true | :forbidden | nil
- :public | :developer | false | false | :unauthorized | nil
- :public | :guest | false | false | :unauthorized | nil
- :public | :anonymous | false | true | :unauthorized | nil
- :private | :developer | true | true | success_status | success_body
- :private | :guest | true | true | :forbidden | nil
- :private | :developer | true | false | :unauthorized | nil
- :private | :guest | true | false | :unauthorized | nil
- :private | :developer | false | true | :not_found | nil
- :private | :guest | false | true | :not_found | nil
- :private | :developer | false | false | :unauthorized | nil
- :private | :guest | false | false | :unauthorized | nil
- :private | :anonymous | false | true | hidden_status | nil
+ where(:visibility_level, :user_type, :auth_method, :expected_status, :expected_body) do
+ :public | :guest | :basic | success_status | success_body
+ :public | :not_a_member | :basic | success_status | success_body
+ :public | :anonymous | :basic | success_status | success_body
+ :public | :invalid_token | :basic | :unauthorized | nil
+ :private | :developer | :basic | success_status | success_body
+ :private | :developer | :private_token | :unauthorized | nil
+ :private | :guest | :basic | :forbidden | nil
+ :private | :not_a_member | :basic | :not_found | nil
+ :private | :anonymous | :basic | :unauthorized | nil
+ :private | :invalid_token | :basic | :unauthorized | nil
end
with_them do
- include_context 'Debian repository access', params[:visibility_level], params[:user_role], params[:member], params[:user_token], :basic do
- it_behaves_like "Debian repository #{desired_behavior}", params[:expected_status], params[:expected_body]
+ include_context 'Debian repository access', params[:visibility_level], params[:user_type], params[:auth_method] do
+ it_behaves_like "Debian packages #{desired_behavior} request", params[:expected_status], params[:expected_body]
end
end
end
- it_behaves_like 'rejects Debian access with unknown container id', hidden_status
+ it_behaves_like 'rejects Debian access with unknown container id', :unauthorized, :basic
end
-RSpec.shared_examples 'Debian repository maintainer write endpoint' do |desired_behavior, success_status, success_body, authenticate_non_public: true|
- hidden_status = if authenticate_non_public
- :unauthorized
- else
- :not_found
- end
-
+RSpec.shared_examples 'Debian packages write endpoint' do |desired_behavior, success_status, success_body|
context 'with valid container' do
using RSpec::Parameterized::TableSyntax
- where(:visibility_level, :user_role, :member, :user_token, :expected_status, :expected_body) do
- :public | :maintainer | true | true | success_status | success_body
- :public | :developer | true | true | :forbidden | nil
- :public | :guest | true | true | :forbidden | nil
- :public | :maintainer | true | false | :unauthorized | nil
- :public | :guest | true | false | :unauthorized | nil
- :public | :maintainer | false | true | :forbidden | nil
- :public | :guest | false | true | :forbidden | nil
- :public | :maintainer | false | false | :unauthorized | nil
- :public | :guest | false | false | :unauthorized | nil
- :public | :anonymous | false | true | :unauthorized | nil
- :private | :maintainer | true | true | success_status | success_body
- :private | :developer | true | true | :forbidden | nil
- :private | :guest | true | true | :forbidden | nil
- :private | :maintainer | true | false | :unauthorized | nil
- :private | :guest | true | false | :unauthorized | nil
- :private | :maintainer | false | true | :not_found | nil
- :private | :guest | false | true | :not_found | nil
- :private | :maintainer | false | false | :unauthorized | nil
- :private | :guest | false | false | :unauthorized | nil
- :private | :anonymous | false | true | hidden_status | nil
+ where(:visibility_level, :user_type, :auth_method, :expected_status, :expected_body) do
+ :public | :developer | :basic | success_status | success_body
+ :public | :developer | :private_token | :unauthorized | nil
+ :public | :guest | :basic | :forbidden | nil
+ :public | :not_a_member | :basic | :forbidden | nil
+ :public | :anonymous | :basic | :unauthorized | nil
+ :public | :invalid_token | :basic | :unauthorized | nil
+ :private | :developer | :basic | success_status | success_body
+ :private | :guest | :basic | :forbidden | nil
+ :private | :not_a_member | :basic | :not_found | nil
+ :private | :anonymous | :basic | :unauthorized | nil
+ :private | :invalid_token | :basic | :unauthorized | nil
end
with_them do
- include_context 'Debian repository access', params[:visibility_level], params[:user_role], params[:member], params[:user_token], :basic do
- it_behaves_like "Debian repository #{desired_behavior}", params[:expected_status], params[:expected_body]
+ include_context 'Debian repository access', params[:visibility_level], params[:user_type], params[:auth_method] do
+ it_behaves_like "Debian packages #{desired_behavior} request", params[:expected_status], params[:expected_body]
end
end
end
- it_behaves_like 'rejects Debian access with unknown container id', hidden_status
+ it_behaves_like 'rejects Debian access with unknown container id', :unauthorized, :basic
end
diff --git a/spec/support/shared_examples/requests/api/graphql/mutations/destroy_list_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/mutations/destroy_list_shared_examples.rb
index 0cec67ff541..dca152223fb 100644
--- a/spec/support/shared_examples/requests/api/graphql/mutations/destroy_list_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/mutations/destroy_list_shared_examples.rb
@@ -28,7 +28,7 @@ RSpec.shared_examples 'board lists destroy request' do
it 'returns an error' do
subject
- expect(graphql_errors.first['message']).to include("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
+ expect(graphql_errors.first['message']).to include(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
end
end
diff --git a/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb
index 41a61ba5fd7..d576a5874fd 100644
--- a/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb
@@ -2,12 +2,26 @@
RSpec.shared_examples 'a package detail' do
it_behaves_like 'a working graphql query' do
- it 'matches the JSON schema' do
- expect(package_details).to match_schema('graphql/packages/package_details')
+ it_behaves_like 'matching the package details schema'
+ end
+
+ context 'with pipelines' do
+ let_it_be(:build_info1) { create(:package_build_info, :with_pipeline, package: package) }
+ let_it_be(:build_info2) { create(:package_build_info, :with_pipeline, package: package) }
+ let_it_be(:build_info3) { create(:package_build_info, :with_pipeline, package: package) }
+
+ it_behaves_like 'a working graphql query' do
+ it_behaves_like 'matching the package details schema'
end
end
end
+RSpec.shared_examples 'matching the package details schema' do
+ it 'matches the JSON schema' do
+ expect(package_details).to match_schema('graphql/packages/package_details')
+ end
+end
+
RSpec.shared_examples 'a package with files' do
it 'has the right amount of files' do
expect(package_files_response.length).to be(package.package_files.length)
diff --git a/spec/support/shared_examples/requests/api/notes_shared_examples.rb b/spec/support/shared_examples/requests/api/notes_shared_examples.rb
index 40799688144..0434d0beb7e 100644
--- a/spec/support/shared_examples/requests/api/notes_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/notes_shared_examples.rb
@@ -281,7 +281,7 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
end
end
- context 'when request exceeds the rate limit' do
+ context 'when request exceeds the rate limit', :freeze_time, :clean_gitlab_redis_rate_limiting do
before do
stub_application_setting(notes_create_limit: 1)
allow(::Gitlab::ApplicationRateLimiter).to receive(:increment).and_return(2)
diff --git a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
index 2af7b616659..19677e92001 100644
--- a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
@@ -8,6 +8,8 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project|
let_it_be(:package_dependency_link3) { create(:packages_dependency_link, package: package, dependency_type: :bundleDependencies) }
let_it_be(:package_dependency_link4) { create(:packages_dependency_link, package: package, dependency_type: :peerDependencies) }
+ let_it_be(:package_metadatum) { create(:npm_metadatum, package: package) }
+
let(:headers) { {} }
subject { get(url, headers: headers) }
@@ -39,6 +41,19 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project|
# query count can slightly change between the examples so we're using a custom threshold
expect { get(url, headers: headers) }.not_to exceed_query_limit(control).with_threshold(4)
end
+
+ context 'with packages_npm_abbreviated_metadata disabled' do
+ before do
+ stub_feature_flags(packages_npm_abbreviated_metadata: false)
+ end
+
+ it 'calls the presenter without including metadata' do
+ expect(::Packages::Npm::PackagePresenter)
+ .to receive(:new).with(anything, anything, include_metadata: false).and_call_original
+
+ subject
+ end
+ end
end
shared_examples 'reject metadata request' do |status:|
diff --git a/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
index ed6d9ed43c8..06c51add438 100644
--- a/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
@@ -167,7 +167,7 @@ end
RSpec.shared_examples 'rejects PyPI access with unknown project id' do
context 'with an unknown project' do
- let(:project) { OpenStruct.new(id: 1234567890) }
+ let(:project) { double('access', id: 1234567890) }
it_behaves_like 'unknown PyPI scope id'
end
@@ -175,7 +175,7 @@ end
RSpec.shared_examples 'rejects PyPI access with unknown group id' do
context 'with an unknown project' do
- let(:group) { OpenStruct.new(id: 1234567890) }
+ let(:group) { double('access', id: 1234567890) }
it_behaves_like 'unknown PyPI scope id'
end
diff --git a/spec/support/shared_examples/requests/api/status_shared_examples.rb b/spec/support/shared_examples/requests/api/status_shared_examples.rb
index 8207190b1dc..40843ccbd15 100644
--- a/spec/support/shared_examples/requests/api/status_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/status_shared_examples.rb
@@ -76,3 +76,32 @@ RSpec.shared_examples '412 response' do
end
end
end
+
+RSpec.shared_examples '422 response' do
+ let(:message) { nil }
+
+ before do
+ # Fires the request
+ request
+ end
+
+ it 'returns 422' do
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ expect(json_response).to be_an Object
+
+ if message.present?
+ expect(json_response['message']).to eq(message)
+ end
+ end
+end
+
+RSpec.shared_examples '503 response' do
+ before do
+ # Fires the request
+ request
+ end
+
+ it 'returns 503' do
+ expect(response).to have_gitlab_http_status(:service_unavailable)
+ end
+end
diff --git a/spec/support/shared_examples/requests/applications_controller_shared_examples.rb b/spec/support/shared_examples/requests/applications_controller_shared_examples.rb
new file mode 100644
index 00000000000..8f852d42c2c
--- /dev/null
+++ b/spec/support/shared_examples/requests/applications_controller_shared_examples.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'applications controller - GET #show' do
+ describe 'GET #show' do
+ it 'renders template' do
+ get show_path
+
+ expect(response).to render_template :show
+ end
+
+ context 'when application is viewed after being created' do
+ before do
+ create_application
+ end
+
+ it 'sets `@created` instance variable to `true`' do
+ get show_path
+
+ expect(assigns[:created]).to eq(true)
+ end
+ end
+
+ context 'when application is reviewed' do
+ it 'sets `@created` instance variable to `false`' do
+ get show_path
+
+ expect(assigns[:created]).to eq(false)
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'applications controller - POST #create' do
+ it "sets `#{OauthApplications::CREATED_SESSION_KEY}` session key to `true`" do
+ create_application
+
+ expect(session[OauthApplications::CREATED_SESSION_KEY]).to eq(true)
+ end
+end
+
+def create_application
+ create_params = attributes_for(:application, trusted: true, confidential: false, scopes: ['api'])
+ post create_path, params: { doorkeeper_application: create_params }
+end
diff --git a/spec/support/shared_examples/requests/self_monitoring_shared_examples.rb b/spec/support/shared_examples/requests/self_monitoring_shared_examples.rb
index ff87fc5d8df..f8a752a5673 100644
--- a/spec/support/shared_examples/requests/self_monitoring_shared_examples.rb
+++ b/spec/support/shared_examples/requests/self_monitoring_shared_examples.rb
@@ -39,6 +39,10 @@ end
# let(:status_api) { status_create_self_monitoring_project_admin_application_settings_path }
# subject { post create_self_monitoring_project_admin_application_settings_path }
RSpec.shared_examples 'triggers async worker, returns sidekiq job_id with response accepted' do
+ before do
+ allow(worker_class).to receive(:with_status).and_return(worker_class)
+ end
+
it 'returns sidekiq job_id of expected length' do
subject
diff --git a/spec/support/shared_examples/requests/snippet_shared_examples.rb b/spec/support/shared_examples/requests/snippet_shared_examples.rb
index dae3a3e74be..b13c4da0bed 100644
--- a/spec/support/shared_examples/requests/snippet_shared_examples.rb
+++ b/spec/support/shared_examples/requests/snippet_shared_examples.rb
@@ -86,6 +86,7 @@ RSpec.shared_examples 'snippet blob content' do
expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq 'true'
expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
+ expect(response.parsed_body).to be_empty
end
context 'when snippet repository is empty' do
diff --git a/spec/support/shared_examples/service_desk_issue_templates_examples.rb b/spec/support/shared_examples/service_desk_issue_templates_examples.rb
index fd9645df7a3..ed6c5199936 100644
--- a/spec/support/shared_examples/service_desk_issue_templates_examples.rb
+++ b/spec/support/shared_examples/service_desk_issue_templates_examples.rb
@@ -3,10 +3,10 @@
RSpec.shared_examples 'issue description templates from current project only' do
it 'loads issue description templates from the project only' do
within('#service-desk-template-select') do
- expect(page).to have_content('project-issue-bar')
- expect(page).to have_content('project-issue-foo')
- expect(page).not_to have_content('group-issue-bar')
- expect(page).not_to have_content('group-issue-foo')
+ expect(page).to have_content(:all, 'project-issue-bar')
+ expect(page).to have_content(:all, 'project-issue-foo')
+ expect(page).not_to have_content(:all, 'group-issue-bar')
+ expect(page).not_to have_content(:all, 'group-issue-foo')
end
end
end
diff --git a/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb b/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
index 92a7d7ab3a3..ca86cb082a7 100644
--- a/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
+++ b/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
@@ -3,7 +3,10 @@
# This shared_example requires the following variables:
# - `service`, the service which includes AlertManagement::AlertProcessing
RSpec.shared_examples 'creates an alert management alert or errors' do
- it { is_expected.to be_success }
+ specify do
+ expect(subject).to be_success
+ expect(subject.payload).to match(alerts: all(a_kind_of(AlertManagement::Alert)))
+ end
it 'creates AlertManagement::Alert' do
expect(Gitlab::AppLogger).not_to receive(:warn)
@@ -89,6 +92,7 @@ RSpec.shared_examples 'adds an alert management alert event' do
expect { subject }.to change { alert.reload.events }.by(1)
expect(subject).to be_success
+ expect(subject.payload).to match(alerts: all(a_kind_of(AlertManagement::Alert)))
end
it_behaves_like 'does not create an alert management alert'
diff --git a/spec/support/shared_examples/services/jira/requests/base_shared_examples.rb b/spec/support/shared_examples/services/jira/requests/base_shared_examples.rb
index 56a6d24d557..c4f6273b46c 100644
--- a/spec/support/shared_examples/services/jira/requests/base_shared_examples.rb
+++ b/spec/support/shared_examples/services/jira/requests/base_shared_examples.rb
@@ -26,11 +26,14 @@ RSpec.shared_examples 'a service that handles Jira API errors' do
expect(subject).to be_a(ServiceResponse)
expect(subject).to be_error
- expect(subject.message).to include(expected_message)
+ expect(subject.message).to start_with(expected_message)
end
end
context 'when the JSON in JIRA::HTTPError is unsafe' do
+ config_docs_link_url = Rails.application.routes.url_helpers.help_page_path('integration/jira/configure')
+ let(:docs_link_start) { '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: config_docs_link_url } }
+
before do
stub_client_and_raise(JIRA::HTTPError, error)
end
@@ -39,7 +42,8 @@ RSpec.shared_examples 'a service that handles Jira API errors' do
let(:error) { '{"errorMessages":' }
it 'returns the default error message' do
- expect(subject.message).to eq('An error occurred while requesting data from Jira. Check your Jira integration configuration and try again.')
+ error_message = 'An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration</a> and try again.' % { docs_link_start: docs_link_start }
+ expect(subject.message).to eq(error_message)
end
end
@@ -47,7 +51,8 @@ RSpec.shared_examples 'a service that handles Jira API errors' do
let(:error) { '{"errorMessages":["<script>alert(true)</script>foo"]}' }
it 'sanitizes it' do
- expect(subject.message).to eq('An error occurred while requesting data from Jira: foo. Check your Jira integration configuration and try again.')
+ error_message = 'An error occurred while requesting data from Jira: foo. Check your %{docs_link_start}Jira integration configuration</a> and try again.' % { docs_link_start: docs_link_start }
+ expect(subject.message).to eq(error_message)
end
end
end
diff --git a/spec/support/shared_examples/services/resource_events/synthetic_notes_builder_shared_examples.rb b/spec/support/shared_examples/services/resource_events/synthetic_notes_builder_shared_examples.rb
new file mode 100644
index 00000000000..716bee39fca
--- /dev/null
+++ b/spec/support/shared_examples/services/resource_events/synthetic_notes_builder_shared_examples.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'filters by paginated notes' do |event_type|
+ let(:event) { create(event_type) } # rubocop:disable Rails/SaveBang
+
+ before do
+ create(event_type, issue: event.issue)
+ end
+
+ it 'only returns given notes' do
+ paginated_notes = { event_type.to_s.pluralize => [double(id: event.id)] }
+ notes = described_class.new(event.issue, user, paginated_notes: paginated_notes).execute
+
+ expect(notes.size).to eq(1)
+ expect(notes.first.event).to eq(event)
+ end
+
+ context 'when paginated notes is empty' do
+ it 'does not return any notes' do
+ notes = described_class.new(event.issue, user, paginated_notes: {}).execute
+
+ expect(notes.size).to eq(0)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/workers/self_monitoring_shared_examples.rb b/spec/support/shared_examples/workers/self_monitoring_shared_examples.rb
index 89c0841fbd6..e6da96e12ec 100644
--- a/spec/support/shared_examples/workers/self_monitoring_shared_examples.rb
+++ b/spec/support/shared_examples/workers/self_monitoring_shared_examples.rb
@@ -17,7 +17,7 @@ end
RSpec.shared_examples 'returns in_progress based on Sidekiq::Status' do
it 'returns true when job is enqueued' do
- jid = described_class.perform_async
+ jid = described_class.with_status.perform_async
expect(described_class.in_progress?(jid)).to eq(true)
end
diff --git a/spec/support/stub_snowplow.rb b/spec/support/stub_snowplow.rb
index a21ce2399d7..c6e3b40972f 100644
--- a/spec/support/stub_snowplow.rb
+++ b/spec/support/stub_snowplow.rb
@@ -8,8 +8,6 @@ module StubSnowplow
host = 'localhost'
# rubocop:disable RSpec/AnyInstanceOf
- allow_any_instance_of(Gitlab::Tracking::Destinations::ProductAnalytics).to receive(:event)
-
allow_any_instance_of(Gitlab::Tracking::Destinations::Snowplow)
.to receive(:emitter)
.and_return(SnowplowTracker::Emitter.new(host, buffer_size: buffer_size))
diff --git a/spec/support/test_reports/test_reports_helper.rb b/spec/support/test_reports/test_reports_helper.rb
index 18b40a20cf1..85483062958 100644
--- a/spec/support/test_reports/test_reports_helper.rb
+++ b/spec/support/test_reports/test_reports_helper.rb
@@ -95,9 +95,9 @@ module TestReportsHelper
<<-EOF.strip_heredoc
junit.framework.AssertionFailedError: expected:&lt;1&gt; but was:&lt;3&gt;
at CalculatorTest.subtractExpression(Unknown Source)
- at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
- at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.base/jdk.internal.database.NativeMethodAccessorImpl.invoke0(Native Method)
+ at java.base/jdk.internal.database.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+ at java.base/jdk.internal.database.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
EOF
end
end
diff --git a/spec/support/time_travel.rb b/spec/support/time_travel.rb
new file mode 100644
index 00000000000..9dfbfd20524
--- /dev/null
+++ b/spec/support/time_travel.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'active_support/testing/time_helpers'
+
+RSpec.configure do |config|
+ config.include ActiveSupport::Testing::TimeHelpers
+
+ config.around(:example, :freeze_time) do |example|
+ freeze_time { example.run }
+ end
+
+ config.around(:example, :time_travel_to) do |example|
+ date_or_time = example.metadata[:time_travel_to]
+
+ unless date_or_time.respond_to?(:to_time) && date_or_time.to_time.present?
+ raise 'The time_travel_to RSpec metadata must have a Date or Time value.'
+ end
+
+ travel_to(date_or_time) { example.run }
+ end
+end
diff --git a/spec/support_specs/database/multiple_databases_spec.rb b/spec/support_specs/database/multiple_databases_spec.rb
index 6ad15fd6594..10d1a8277c6 100644
--- a/spec/support_specs/database/multiple_databases_spec.rb
+++ b/spec/support_specs/database/multiple_databases_spec.rb
@@ -19,19 +19,19 @@ RSpec.describe 'Database::MultipleDatabases' do
end
end
- context 'on Ci::CiDatabaseRecord' do
+ context 'on Ci::ApplicationRecord' do
before do
skip_if_multiple_databases_not_setup
end
it 'raises exception' do
- expect { Ci::CiDatabaseRecord.establish_connection(:ci) }.to raise_error /Cannot re-establish/
+ expect { Ci::ApplicationRecord.establish_connection(:ci) }.to raise_error /Cannot re-establish/
end
context 'when using with_reestablished_active_record_base' do
it 'does not raise exception' do
with_reestablished_active_record_base do
- expect { Ci::CiDatabaseRecord.establish_connection(:main) }.not_to raise_error
+ expect { Ci::ApplicationRecord.establish_connection(:main) }.not_to raise_error
end
end
end
diff --git a/spec/support_specs/database/prevent_cross_database_modification_spec.rb b/spec/support_specs/database/prevent_cross_database_modification_spec.rb
deleted file mode 100644
index e86559bb14a..00000000000
--- a/spec/support_specs/database/prevent_cross_database_modification_spec.rb
+++ /dev/null
@@ -1,163 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Database::PreventCrossDatabaseModification' do
- let_it_be(:pipeline, refind: true) { create(:ci_pipeline) }
- let_it_be(:project, refind: true) { create(:project) }
-
- shared_examples 'succeessful examples' do
- context 'outside transaction' do
- it { expect { run_queries }.not_to raise_error }
- end
-
- context 'within transaction' do
- it do
- Project.transaction do
- expect { run_queries }.not_to raise_error
- end
- end
- end
-
- context 'within nested transaction' do
- it do
- Project.transaction(requires_new: true) do
- Project.transaction(requires_new: true) do
- expect { run_queries }.not_to raise_error
- end
- end
- end
- end
- end
-
- context 'when CI and other tables are read in a transaction' do
- def run_queries
- pipeline.reload
- project.reload
- end
-
- include_examples 'succeessful examples'
- end
-
- context 'when only CI data is modified' do
- def run_queries
- pipeline.touch
- project.reload
- end
-
- include_examples 'succeessful examples'
- end
-
- context 'when other data is modified' do
- def run_queries
- pipeline.reload
- project.touch
- end
-
- include_examples 'succeessful examples'
- end
-
- describe 'with_cross_database_modification_prevented block' do
- it 'raises error when CI and other data is modified' do
- expect do
- with_cross_database_modification_prevented do
- Project.transaction do
- project.touch
- pipeline.touch
- end
- end
- end.to raise_error /Cross-database data modification/
- end
- end
-
- context 'when running tests with prevent_cross_database_modification', :prevent_cross_database_modification do
- context 'when both CI and other data is modified' do
- def run_queries
- project.touch
- pipeline.touch
- end
-
- context 'outside transaction' do
- it { expect { run_queries }.not_to raise_error }
- end
-
- context 'when data modification happens in a transaction' do
- it 'raises error' do
- Project.transaction do
- expect { run_queries }.to raise_error /Cross-database data modification/
- end
- end
-
- context 'when data modification happens in nested transactions' do
- it 'raises error' do
- Project.transaction(requires_new: true) do
- project.touch
- Project.transaction(requires_new: true) do
- expect { pipeline.touch }.to raise_error /Cross-database data modification/
- end
- end
- end
- end
- end
-
- context 'when executing a SELECT FOR UPDATE query' do
- def run_queries
- project.touch
- pipeline.lock!
- end
-
- context 'outside transaction' do
- it { expect { run_queries }.not_to raise_error }
- end
-
- context 'when data modification happens in a transaction' do
- it 'raises error' do
- Project.transaction do
- expect { run_queries }.to raise_error /Cross-database data modification/
- end
- end
- end
- end
- end
-
- context 'when CI association is modified through project' do
- def run_queries
- project.variables.build(key: 'a', value: 'v')
- project.save!
- end
-
- include_examples 'succeessful examples'
- end
-
- describe '#allow_cross_database_modification_within_transaction' do
- it 'skips raising error' do
- expect do
- Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'gitlab-issue') do
- Project.transaction do
- pipeline.touch
- project.touch
- end
- end
- end.not_to raise_error
- end
-
- it 'raises error when complex factories are built referencing both databases' do
- expect do
- ApplicationRecord.transaction do
- create(:ci_pipeline)
- end
- end.to raise_error /Cross-database data modification/
- end
-
- it 'skips raising error on factory creation' do
- expect do
- Gitlab::Database.allow_cross_database_modification_within_transaction(url: 'gitlab-issue') do
- ApplicationRecord.transaction do
- create(:ci_pipeline)
- end
- end
- end.not_to raise_error
- end
- end
- end
-end
diff --git a/spec/support_specs/helpers/stub_feature_flags_spec.rb b/spec/support_specs/helpers/stub_feature_flags_spec.rb
index 8629e895fd1..9b35fe35259 100644
--- a/spec/support_specs/helpers/stub_feature_flags_spec.rb
+++ b/spec/support_specs/helpers/stub_feature_flags_spec.rb
@@ -97,7 +97,7 @@ RSpec.describe StubFeatureFlags do
context 'type handling' do
context 'raises error' do
where(:feature_actors) do
- ['string', 1, 1.0, OpenStruct.new]
+ ['string', 1, 1.0, Object.new]
end
with_them do
diff --git a/spec/support_specs/time_travel_spec.rb b/spec/support_specs/time_travel_spec.rb
new file mode 100644
index 00000000000..8fa51c0c1f0
--- /dev/null
+++ b/spec/support_specs/time_travel_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'time travel' do
+ describe ':freeze_time' do
+ it 'freezes time around a spec example', :freeze_time do
+ expect { sleep 0.1 }.not_to change { Time.now.to_f }
+ end
+ end
+
+ describe ':time_travel_to' do
+ it 'time-travels to the specified date', time_travel_to: '2020-01-01' do
+ expect(Date.current).to eq(Date.new(2020, 1, 1))
+ end
+
+ it 'time-travels to the specified date & time', time_travel_to: '2020-02-02 10:30:45 -0700' do
+ expect(Time.current).to eq(Time.new(2020, 2, 2, 17, 30, 45, '+00:00'))
+ end
+ end
+end
diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb
index ad4ada9a9f1..38392f77307 100644
--- a/spec/tasks/gitlab/db_rake_spec.rb
+++ b/spec/tasks/gitlab/db_rake_spec.rb
@@ -201,9 +201,11 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
describe 'reindex' do
let(:reindex) { double('reindex') }
let(:indexes) { double('indexes') }
+ let(:databases) { Gitlab::Database.database_base_models }
+ let(:databases_count) { databases.count }
it 'cleans up any leftover indexes' do
- expect(Gitlab::Database::Reindexing).to receive(:cleanup_leftovers!)
+ expect(Gitlab::Database::Reindexing).to receive(:cleanup_leftovers!).exactly(databases_count).times
run_rake_task('gitlab:db:reindex')
end
@@ -212,8 +214,8 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
it 'executes async index creation prior to any reindexing actions' do
stub_feature_flags(database_async_index_creation: true)
- expect(Gitlab::Database::AsyncIndexes).to receive(:create_pending_indexes!).ordered
- expect(Gitlab::Database::Reindexing).to receive(:perform).ordered
+ expect(Gitlab::Database::AsyncIndexes).to receive(:create_pending_indexes!).ordered.exactly(databases_count).times
+ expect(Gitlab::Database::Reindexing).to receive(:automatic_reindexing).ordered.exactly(databases_count).times
run_rake_task('gitlab:db:reindex')
end
@@ -229,38 +231,30 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
end
end
- context 'when no index_name is given' do
+ context 'calls automatic reindexing' do
it 'uses all candidate indexes' do
- expect(Gitlab::Database::PostgresIndex).to receive(:reindexing_support).and_return(indexes)
- expect(Gitlab::Database::Reindexing).to receive(:perform).with(indexes)
+ expect(Gitlab::Database::Reindexing).to receive(:automatic_reindexing).exactly(databases_count).times
run_rake_task('gitlab:db:reindex')
end
end
+ end
- context 'with index name given' do
- let(:index) { double('index') }
-
- before do
- allow(Gitlab::Database::PostgresIndex).to receive(:reindexing_support).and_return(indexes)
- end
-
- it 'calls the index rebuilder with the proper arguments' do
- allow(indexes).to receive(:where).with(identifier: 'public.foo_idx').and_return([index])
- expect(Gitlab::Database::Reindexing).to receive(:perform).with([index])
-
- run_rake_task('gitlab:db:reindex', '[public.foo_idx]')
- end
+ describe 'enqueue_reindexing_action' do
+ let(:index_name) { 'public.users_pkey' }
- it 'raises an error if the index does not exist' do
- allow(indexes).to receive(:where).with(identifier: 'public.absent_index').and_return([])
+ it 'creates an entry in the queue' do
+ expect do
+ run_rake_task('gitlab:db:enqueue_reindexing_action', "[#{index_name}, main]")
+ end.to change { Gitlab::Database::PostgresIndex.find(index_name).queued_reindexing_actions.size }.from(0).to(1)
+ end
- expect { run_rake_task('gitlab:db:reindex', '[public.absent_index]') }.to raise_error(/Index not found/)
- end
+ it 'defaults to main database' do
+ expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(ActiveRecord::Base.connection).and_call_original
- it 'raises an error if the index is not fully qualified with a schema' do
- expect { run_rake_task('gitlab:db:reindex', '[foo_idx]') }.to raise_error(/Index name is not fully qualified/)
- end
+ expect do
+ run_rake_task('gitlab:db:enqueue_reindexing_action', "[#{index_name}]")
+ end.to change { Gitlab::Database::PostgresIndex.find(index_name).queued_reindexing_actions.size }.from(0).to(1)
end
end
diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb
index 5adea832995..c5625db922d 100644
--- a/spec/tasks/gitlab/gitaly_rake_spec.rb
+++ b/spec/tasks/gitlab/gitaly_rake_spec.rb
@@ -67,34 +67,57 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do
end
it 'calls gmake in the gitaly directory' do
- expect(Gitlab::Popen).to receive(:popen).with(%w[which gmake]).and_return(['/usr/bin/gmake', 0])
- expect(Gitlab::Popen).to receive(:popen).with(%w[gmake], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil }).and_return(true)
+ expect(Gitlab::Popen).to receive(:popen)
+ .with(%w[which gmake])
+ .and_return(['/usr/bin/gmake', 0])
+ expect(Gitlab::Popen).to receive(:popen)
+ .with(%w[gmake all git], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil })
+ .and_return(['ok', 0])
subject
end
+
+ context 'when gmake fails' do
+ it 'aborts process' do
+ expect(Gitlab::Popen).to receive(:popen)
+ .with(%w[which gmake])
+ .and_return(['/usr/bin/gmake', 0])
+ expect(Gitlab::Popen).to receive(:popen)
+ .with(%w[gmake all git], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil })
+ .and_return(['output', 1])
+
+ expect { subject }.to raise_error /Gitaly failed to compile: output/
+ end
+ end
end
context 'gmake is not available' do
before do
expect(main_object).to receive(:checkout_or_clone_version)
- expect(Gitlab::Popen).to receive(:popen).with(%w[which gmake]).and_return(['', 42])
+ expect(Gitlab::Popen).to receive(:popen)
+ .with(%w[which gmake])
+ .and_return(['', 42])
end
it 'calls make in the gitaly directory' do
- expect(Gitlab::Popen).to receive(:popen).with(%w[make], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil }).and_return(true)
+ expect(Gitlab::Popen).to receive(:popen)
+ .with(%w[make all git], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil })
+ .and_return(['output', 0])
subject
end
context 'when Rails.env is test' do
- let(:command) { %w[make] }
+ let(:command) { %w[make all git] }
before do
stub_rails_env('test')
end
it 'calls make in the gitaly directory with BUNDLE_DEPLOYMENT and GEM_HOME variables' do
- expect(Gitlab::Popen).to receive(:popen).with(command, nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil, "BUNDLE_DEPLOYMENT" => 'false', "GEM_HOME" => Bundler.bundle_path.to_s }).and_return(true)
+ expect(Gitlab::Popen).to receive(:popen)
+ .with(command, nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil, "BUNDLE_DEPLOYMENT" => 'false', "GEM_HOME" => Bundler.bundle_path.to_s })
+ .and_return(['/usr/bin/gmake', 0])
subject
end
diff --git a/spec/tasks/gitlab/storage_rake_spec.rb b/spec/tasks/gitlab/storage_rake_spec.rb
index 570f67c8bb7..38a031178ae 100644
--- a/spec/tasks/gitlab/storage_rake_spec.rb
+++ b/spec/tasks/gitlab/storage_rake_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe 'rake gitlab:storage:*', :silence_stdout do
shared_examples 'wait until database is ready' do
it 'checks if the database is ready once' do
- expect(Gitlab::Database.main).to receive(:exists?).once
+ expect(ApplicationRecord.database).to receive(:exists?).once
run_rake_task(task)
end
@@ -102,7 +102,7 @@ RSpec.describe 'rake gitlab:storage:*', :silence_stdout do
end
it 'tries for 3 times, polling every 0.1 seconds' do
- expect(Gitlab::Database.main).to receive(:exists?).exactly(3).times.and_return(false)
+ expect(ApplicationRecord.database).to receive(:exists?).exactly(3).times.and_return(false)
run_rake_task(task)
end
diff --git a/spec/tooling/danger/changelog_spec.rb b/spec/tooling/danger/changelog_spec.rb
index 5777186cc28..377c3e881c9 100644
--- a/spec/tooling/danger/changelog_spec.rb
+++ b/spec/tooling/danger/changelog_spec.rb
@@ -228,7 +228,7 @@ RSpec.describe Tooling::Danger::Changelog do
end
context 'with changelog label' do
- let(:mr_labels) { ['feature'] }
+ let(:mr_labels) { ['type::feature'] }
it 'is truthy' do
is_expected.to be_truthy
@@ -236,7 +236,7 @@ RSpec.describe Tooling::Danger::Changelog do
end
context 'with no changelog label' do
- let(:mr_labels) { ['tooling'] }
+ let(:mr_labels) { ['type::tooling'] }
it 'is truthy' do
is_expected.to be_falsey
diff --git a/spec/tooling/danger/product_intelligence_spec.rb b/spec/tooling/danger/product_intelligence_spec.rb
index 5fd44ef5de0..c090dbb4de4 100644
--- a/spec/tooling/danger/product_intelligence_spec.rb
+++ b/spec/tooling/danger/product_intelligence_spec.rb
@@ -44,20 +44,26 @@ RSpec.describe Tooling::Danger::ProductIntelligence do
context 'with product intelligence label' do
let(:expected_labels) { ['product intelligence::review pending'] }
+ let(:mr_labels) { [] }
before do
allow(fake_helper).to receive(:mr_has_labels?).with('product intelligence').and_return(true)
+ allow(fake_helper).to receive(:mr_labels).and_return(mr_labels)
end
it { is_expected.to match_array(expected_labels) }
- end
- context 'with product intelligence::review pending' do
- before do
- allow(fake_helper).to receive(:mr_has_labels?).and_return(true)
+ context 'with product intelligence::review pending' do
+ let(:mr_labels) { ['product intelligence::review pending'] }
+
+ it { is_expected.to be_empty }
end
- it { is_expected.to be_empty }
+ context 'with product intelligence::approved' do
+ let(:mr_labels) { ['product intelligence::approved'] }
+
+ it { is_expected.to be_empty }
+ end
end
context 'with growth experiment label' do
@@ -68,71 +74,4 @@ RSpec.describe Tooling::Danger::ProductIntelligence do
it { is_expected.to be_empty }
end
end
-
- describe '#matching_changed_files' do
- subject { product_intelligence.matching_changed_files }
-
- let(:changed_files) do
- [
- 'dashboard/todos_controller.rb',
- 'components/welcome.vue',
- 'admin/groups/_form.html.haml'
- ]
- end
-
- context 'with snowplow files changed' do
- context 'when vue file changed' do
- let(:changed_lines) { ['+data-track-action'] }
-
- it { is_expected.to match_array(['components/welcome.vue']) }
- end
-
- context 'when haml file changed' do
- let(:changed_lines) { ['+ data: { track_label:'] }
-
- it { is_expected.to match_array(['admin/groups/_form.html.haml']) }
- end
-
- context 'when ruby file changed' do
- let(:changed_lines) { ['+ Gitlab::Tracking.event'] }
- let(:changed_files) { ['dashboard/todos_controller.rb', 'admin/groups/_form.html.haml'] }
-
- it { is_expected.to match_array(['dashboard/todos_controller.rb']) }
- end
- end
-
- context 'with metrics files changed' do
- let(:changed_files) { ['config/metrics/counts_7d/test_metric.yml', 'ee/config/metrics/counts_7d/ee_metric.yml'] }
-
- it { is_expected.to match_array(changed_files) }
- end
-
- context 'with metrics files not changed' do
- it { is_expected.to be_empty }
- end
-
- context 'with tracking files changed' do
- let(:changed_files) do
- [
- 'lib/gitlab/tracking.rb',
- 'spec/lib/gitlab/tracking_spec.rb',
- 'app/helpers/tracking_helper.rb'
- ]
- end
-
- it { is_expected.to match_array(changed_files) }
- end
-
- context 'with usage_data files changed' do
- let(:changed_files) do
- [
- 'doc/api/usage_data.md',
- 'ee/lib/ee/gitlab/usage_data.rb',
- 'spec/lib/gitlab/usage_data_spec.rb'
- ]
- end
-
- it { is_expected.to match_array(changed_files) }
- end
- end
end
diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb
index 5edd9e54cc5..ec475df6d83 100644
--- a/spec/tooling/danger/project_helper_spec.rb
+++ b/spec/tooling/danger/project_helper_spec.rb
@@ -7,8 +7,10 @@ require 'danger/plugins/helper'
require 'gitlab/dangerfiles/spec_helper'
require_relative '../../../danger/plugins/project_helper'
+require_relative '../../../spec/support/helpers/stub_env'
RSpec.describe Tooling::Danger::ProjectHelper do
+ include StubENV
include_context "with dangerfile"
let(:fake_danger) { DangerSpecHelper.fake_danger.include(described_class) }
@@ -40,7 +42,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
using RSpec::Parameterized::TableSyntax
before do
- allow(fake_git).to receive(:diff_for_file).with('usage_data.rb') { double(:diff, patch: "+ count(User.active)") }
+ allow(fake_git).to receive(:diff_for_file).with(instance_of(String)) { double(:diff, patch: "+ count(User.active)") }
end
where(:path, :expected_categories) do
@@ -189,6 +191,58 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'spec/frontend/tracking/foo.js' | [:frontend, :product_intelligence]
'spec/frontend/tracking_spec.js' | [:frontend, :product_intelligence]
'lib/gitlab/usage_database/foo.rb' | [:backend]
+ 'config/metrics/counts_7d/test_metric.yml' | [:product_intelligence]
+ 'config/metrics/schema.json' | [:product_intelligence]
+ 'doc/api/usage_data.md' | [:product_intelligence]
+ 'spec/lib/gitlab/usage_data_spec.rb' | [:product_intelligence]
+
+ 'app/models/integration.rb' | [:integrations_be, :backend]
+ 'ee/app/models/integrations/github.rb' | [:integrations_be, :backend]
+ 'ee/app/models/ee/integrations/jira.rb' | [:integrations_be, :backend]
+ 'app/models/integrations/chat_message/pipeline_message.rb' | [:integrations_be, :backend]
+ 'app/models/jira_connect_subscription.rb' | [:integrations_be, :backend]
+ 'app/models/hooks/service_hook.rb' | [:integrations_be, :backend]
+ 'ee/app/models/ee/hooks/system_hook.rb' | [:integrations_be, :backend]
+ 'app/services/concerns/integrations/project_test_data.rb' | [:integrations_be, :backend]
+ 'ee/app/services/ee/integrations/test/project_service.rb' | [:integrations_be, :backend]
+ 'app/controllers/concerns/integrations/actions.rb' | [:integrations_be, :backend]
+ 'ee/app/controllers/concerns/ee/integrations/params.rb' | [:integrations_be, :backend]
+ 'ee/app/controllers/projects/integrations/jira/issues_controller.rb' | [:integrations_be, :backend]
+ 'app/controllers/projects/hooks_controller.rb' | [:integrations_be, :backend]
+ 'app/controllers/admin/hook_logs_controller.rb' | [:integrations_be, :backend]
+ 'app/controllers/groups/settings/integrations_controller.rb' | [:integrations_be, :backend]
+ 'app/controllers/jira_connect/branches_controller.rb' | [:integrations_be, :backend]
+ 'app/controllers/oauth/jira/authorizations_controller.rb' | [:integrations_be, :backend]
+ 'ee/app/finders/projects/integrations/jira/by_ids_finder.rb' | [:integrations_be, :database, :backend]
+ 'app/workers/jira_connect/sync_merge_request_worker.rb' | [:integrations_be, :backend]
+ 'app/workers/propagate_integration_inherit_worker.rb' | [:integrations_be, :backend]
+ 'app/workers/web_hooks/log_execution_worker.rb' | [:integrations_be, :backend]
+ 'app/workers/web_hook_worker.rb' | [:integrations_be, :backend]
+ 'app/workers/project_service_worker.rb' | [:integrations_be, :backend]
+ 'lib/atlassian/jira_connect/serializers/commit_entity.rb' | [:integrations_be, :backend]
+ 'lib/api/entities/project_integration.rb' | [:integrations_be, :backend]
+ 'lib/gitlab/hook_data/note_builder.rb' | [:integrations_be, :backend]
+ 'lib/gitlab/data_builder/note.rb' | [:integrations_be, :backend]
+ 'ee/lib/ee/gitlab/integrations/sti_type.rb' | [:integrations_be, :backend]
+ 'ee/lib/ee/api/helpers/integrations_helpers.rb' | [:integrations_be, :backend]
+ 'ee/app/serializers/integrations/jira_serializers/issue_entity.rb' | [:integrations_be, :backend]
+ 'lib/api/github/entities.rb' | [:integrations_be, :backend]
+ 'lib/api/v3/github.rb' | [:integrations_be, :backend]
+ 'app/models/clusters/integrations/elastic_stack.rb' | [:backend]
+ 'app/controllers/clusters/integrations_controller.rb' | [:backend]
+ 'app/services/clusters/integrations/prometheus_health_check_service.rb' | [:backend]
+ 'app/graphql/types/alert_management/integration_type.rb' | [:backend]
+
+ 'app/views/jira_connect/branches/new.html.haml' | [:integrations_fe, :frontend]
+ 'app/views/layouts/jira_connect.html.haml' | [:integrations_fe, :frontend]
+ 'app/assets/javascripts/jira_connect/branches/pages/index.vue' | [:integrations_fe, :frontend]
+ 'ee/app/views/projects/integrations/jira/issues/show.html.haml' | [:integrations_fe, :frontend]
+ 'ee/app/assets/javascripts/integrations/zentao/issues_list/graphql/queries/get_zentao_issues.query.graphql' | [:integrations_fe, :frontend]
+ 'app/assets/javascripts/pages/projects/settings/integrations/show/index.js' | [:integrations_fe, :frontend]
+ 'ee/app/assets/javascripts/pages/groups/hooks/index.js' | [:integrations_fe, :frontend]
+ 'app/views/clusters/clusters/_integrations_tab.html.haml' | [:frontend]
+ 'app/assets/javascripts/alerts_settings/graphql/fragments/integration_item.fragment.graphql' | [:frontend]
+ 'app/assets/javascripts/filtered_search/droplab/hook_input.js' | [:frontend]
end
with_them do
@@ -199,12 +253,20 @@ RSpec.describe Tooling::Danger::ProjectHelper do
context 'having specific changes' do
where(:expected_categories, :patch, :changed_files) do
+ [:product_intelligence] | '+data-track-action' | ['components/welcome.vue']
+ [:product_intelligence] | '+ data: { track_label:' | ['admin/groups/_form.html.haml']
+ [:product_intelligence] | '+ Gitlab::Tracking.event' | ['dashboard/todos_controller.rb', 'admin/groups/_form.html.haml']
[:database, :backend, :product_intelligence] | '+ count(User.active)' | ['usage_data.rb', 'lib/gitlab/usage_data.rb', 'ee/lib/ee/gitlab/usage_data.rb']
[:database, :backend, :product_intelligence] | '+ estimate_batch_distinct_count(User.active)' | ['usage_data.rb']
[:backend, :product_intelligence] | '+ alt_usage_data(User.active)' | ['lib/gitlab/usage_data.rb']
[:backend, :product_intelligence] | '+ count(User.active)' | ['lib/gitlab/usage_data/topology.rb']
[:backend, :product_intelligence] | '+ foo_count(User.active)' | ['lib/gitlab/usage_data.rb']
[:backend] | '+ count(User.active)' | ['user.rb']
+ [:integrations_be, :database, :migration] | '+ add_column :integrations, :foo, :text' | ['db/migrate/foo.rb']
+ [:integrations_be, :database, :migration] | '+ create_table :zentao_tracker_data do |t|' | ['ee/db/post_migrate/foo.rb']
+ [:integrations_be, :backend] | '+ Integrations::Foo' | ['app/foo/bar.rb']
+ [:integrations_be, :backend] | '+ project.execute_hooks(foo, :bar)' | ['ee/lib/ee/foo.rb']
+ [:integrations_be, :backend] | '+ project.execute_integrations(foo, :bar)' | ['app/foo.rb']
end
with_them do
@@ -281,6 +343,70 @@ RSpec.describe Tooling::Danger::ProjectHelper do
end
end
+ describe '#ee?' do
+ subject { project_helper.__send__(:ee?) }
+
+ let(:ee_dir) { File.expand_path('../../../ee', __dir__) }
+
+ context 'when ENV["CI_PROJECT_NAME"] is set' do
+ before do
+ stub_env('CI_PROJECT_NAME', ci_project_name)
+ end
+
+ context 'when ENV["CI_PROJECT_NAME"] is gitlab' do
+ let(:ci_project_name) { 'gitlab' }
+
+ it 'returns true' do
+ is_expected.to eq(true)
+ end
+ end
+
+ context 'when ENV["CI_PROJECT_NAME"] is gitlab-ee' do
+ let(:ci_project_name) { 'gitlab-ee' }
+
+ it 'returns true' do
+ is_expected.to eq(true)
+ end
+ end
+
+ context 'when ENV["CI_PROJECT_NAME"] is gitlab-foss' do
+ let(:ci_project_name) { 'gitlab-foss' }
+
+ it 'resolves to Dir.exist?' do
+ expected = Dir.exist?(ee_dir)
+
+ expect(Dir).to receive(:exist?).with(ee_dir).and_call_original
+
+ is_expected.to eq(expected)
+ end
+ end
+ end
+
+ context 'when ENV["CI_PROJECT_NAME"] is absent' do
+ before do
+ stub_env('CI_PROJECT_NAME', nil)
+
+ expect(Dir).to receive(:exist?).with(ee_dir).and_return(has_ee_dir)
+ end
+
+ context 'when ee/ directory exists' do
+ let(:has_ee_dir) { true }
+
+ it 'returns true' do
+ is_expected.to eq(true)
+ end
+ end
+
+ context 'when ee/ directory does not exist' do
+ let(:has_ee_dir) { false }
+
+ it 'returns false' do
+ is_expected.to eq(false)
+ end
+ end
+ end
+ end
+
describe '#file_lines' do
let(:filename) { 'spec/foo_spec.rb' }
let(:file_spy) { spy }
diff --git a/spec/tooling/quality/test_level_spec.rb b/spec/tooling/quality/test_level_spec.rb
index 0623a67a60e..94fa9d682e1 100644
--- a/spec/tooling/quality/test_level_spec.rb
+++ b/spec/tooling/quality/test_level_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Quality::TestLevel do
context 'when level is unit' do
it 'returns a pattern' do
expect(subject.pattern(:unit))
- .to eq("spec/{bin,channels,config,db,dependencies,elastic,elastic_integration,experiments,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,models,policies,presenters,rack_servers,replicators,routing,rubocop,serializers,services,sidekiq,spam,support_specs,tasks,uploaders,validators,views,workers,tooling}{,/**/}*_spec.rb")
+ .to eq("spec/{bin,channels,config,db,dependencies,elastic,elastic_integration,experiments,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,models,policies,presenters,rack_servers,replicators,routing,rubocop,scripts,serializers,services,sidekiq,spam,support_specs,tasks,uploaders,validators,views,workers,tooling}{,/**/}*_spec.rb")
end
end
@@ -49,7 +49,7 @@ RSpec.describe Quality::TestLevel do
context 'when level is integration' do
it 'returns a pattern' do
expect(subject.pattern(:integration))
- .to eq("spec/{controllers,mailers,requests}{,/**/}*_spec.rb")
+ .to eq("spec/{commands,controllers,mailers,requests}{,/**/}*_spec.rb")
end
end
@@ -110,7 +110,7 @@ RSpec.describe Quality::TestLevel do
context 'when level is unit' do
it 'returns a regexp' do
expect(subject.regexp(:unit))
- .to eq(%r{spec/(bin|channels|config|db|dependencies|elastic|elastic_integration|experiments|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|models|policies|presenters|rack_servers|replicators|routing|rubocop|serializers|services|sidekiq|spam|support_specs|tasks|uploaders|validators|views|workers|tooling)})
+ .to eq(%r{spec/(bin|channels|config|db|dependencies|elastic|elastic_integration|experiments|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|models|policies|presenters|rack_servers|replicators|routing|rubocop|scripts|serializers|services|sidekiq|spam|support_specs|tasks|uploaders|validators|views|workers|tooling)})
end
end
@@ -131,7 +131,7 @@ RSpec.describe Quality::TestLevel do
context 'when level is integration' do
it 'returns a regexp' do
expect(subject.regexp(:integration))
- .to eq(%r{spec/(controllers|mailers|requests)})
+ .to eq(%r{spec/(commands|controllers|mailers|requests)})
end
end
@@ -204,6 +204,10 @@ RSpec.describe Quality::TestLevel do
expect(subject.level_for('spec/mailers/abuse_report_mailer_spec.rb')).to eq(:integration)
end
+ it 'returns the correct level for an integration test in a subfolder' do
+ expect(subject.level_for('spec/commands/sidekiq_cluster/cli.rb')).to eq(:integration)
+ end
+
it 'returns the correct level for a system test' do
expect(subject.level_for('spec/features/abuse_report_spec.rb')).to eq(:system)
end
diff --git a/spec/validators/addressable_url_validator_spec.rb b/spec/validators/addressable_url_validator_spec.rb
index ec3ee9aa500..7e2cc2afa8a 100644
--- a/spec/validators/addressable_url_validator_spec.rb
+++ b/spec/validators/addressable_url_validator_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe AddressableUrlValidator do
describe 'validations' do
include_context 'invalid urls'
+ include_context 'valid urls with CRLF'
let(:validator) { described_class.new(attributes: [:link_url]) }
@@ -27,9 +28,20 @@ RSpec.describe AddressableUrlValidator do
expect(badge.errors.added?(:link_url, validator.options.fetch(:message))).to be true
end
+ it 'allows urls with encoded CR or LF characters' do
+ aggregate_failures do
+ valid_urls_with_CRLF.each do |url|
+ validator.validate_each(badge, :link_url, url)
+
+ expect(badge.errors).to be_empty
+ end
+ end
+ end
+
it 'does not allow urls with CR or LF characters' do
aggregate_failures do
urls_with_CRLF.each do |url|
+ badge = build(:badge, link_url: 'http://www.example.com')
validator.validate_each(badge, :link_url, url)
expect(badge.errors.added?(:link_url, 'is blocked: URI is invalid')).to be true
diff --git a/spec/views/groups/settings/_remove.html.haml_spec.rb b/spec/views/groups/settings/_remove.html.haml_spec.rb
index 07fe900bc2d..e40fda58a72 100644
--- a/spec/views/groups/settings/_remove.html.haml_spec.rb
+++ b/spec/views/groups/settings/_remove.html.haml_spec.rb
@@ -9,8 +9,8 @@ RSpec.describe 'groups/settings/_remove.html.haml' do
render 'groups/settings/remove', group: group
- expect(rendered).to have_selector '[data-testid="remove-group-button"]'
- expect(rendered).not_to have_selector '[data-testid="remove-group-button"].disabled'
+ expect(rendered).to have_selector '[data-button-testid="remove-group-button"]'
+ expect(rendered).not_to have_selector '[data-button-testid="remove-group-button"].disabled'
expect(rendered).not_to have_selector '[data-testid="group-has-linked-subscription-alert"]'
end
end
diff --git a/spec/views/groups/settings/_transfer.html.haml_spec.rb b/spec/views/groups/settings/_transfer.html.haml_spec.rb
index b557c989eae..911eb5b7ab3 100644
--- a/spec/views/groups/settings/_transfer.html.haml_spec.rb
+++ b/spec/views/groups/settings/_transfer.html.haml_spec.rb
@@ -9,9 +9,9 @@ RSpec.describe 'groups/settings/_transfer.html.haml' do
render 'groups/settings/transfer', group: group
- expect(rendered).to have_selector '[data-qa-selector="select_group_dropdown"]' # rubocop:disable QA/SelectorUsage
- expect(rendered).not_to have_selector '[data-qa-selector="select_group_dropdown"][disabled]' # rubocop:disable QA/SelectorUsage
- expect(rendered).not_to have_selector '[data-testid="group-to-transfer-has-linked-subscription-alert"]'
+ expect(rendered).to have_button 'Select parent group'
+ expect(rendered).not_to have_button 'Select parent group', disabled: true
+ expect(rendered).not_to have_text "This group can't be transfered because it is linked to a subscription."
end
end
end
diff --git a/spec/views/jira_connect/subscriptions/index.html.haml_spec.rb b/spec/views/jira_connect/subscriptions/index.html.haml_spec.rb
index dcc36c93327..0a4d283a983 100644
--- a/spec/views/jira_connect/subscriptions/index.html.haml_spec.rb
+++ b/spec/views/jira_connect/subscriptions/index.html.haml_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'jira_connect/subscriptions/index.html.haml' do
before do
allow(view).to receive(:current_user).and_return(user)
- assign(:subscriptions, [])
+ assign(:subscriptions, create_list(:jira_connect_subscription, 1))
end
context 'when the user is signed in' do
diff --git a/spec/views/layouts/_published_experiments.html.haml_spec.rb b/spec/views/layouts/_published_experiments.html.haml_spec.rb
new file mode 100644
index 00000000000..d1ade8ddd6e
--- /dev/null
+++ b/spec/views/layouts/_published_experiments.html.haml_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'layouts/_published_experiments', :experiment do
+ before do
+ stub_const('TestControlExperiment', ApplicationExperiment)
+ stub_const('TestCandidateExperiment', ApplicationExperiment)
+ stub_const('TestExcludedExperiment', ApplicationExperiment)
+
+ TestControlExperiment.new('test_control').tap do |e|
+ e.variant(:control)
+ e.publish
+ end
+ TestCandidateExperiment.new('test_candidate').tap do |e|
+ e.variant(:candidate)
+ e.publish
+ end
+ TestExcludedExperiment.new('test_excluded').tap do |e|
+ e.exclude!
+ e.publish
+ end
+
+ render
+ end
+
+ it 'renders out data for all non-excluded, published experiments' do
+ output = rendered
+
+ expect(output).to include('gl.experiments = {')
+ expect(output).to match(/"test_control":\{[^}]*"variant":"control"/)
+ expect(output).to match(/"test_candidate":\{[^}]*"variant":"candidate"/)
+ expect(output).not_to include('"test_excluded"')
+ end
+end
diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
index 20c5d9992be..f7da288b9f3 100644
--- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
@@ -987,28 +987,10 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
describe 'Usage Quotas' do
- context 'with project_storage_ui feature flag enabled' do
- before do
- stub_feature_flags(project_storage_ui: true)
- end
-
- it 'has a link to Usage Quotas' do
- render
-
- expect(rendered).to have_link('Usage Quotas', href: project_usage_quotas_path(project))
- end
- end
-
- context 'with project_storage_ui feature flag disabled' do
- before do
- stub_feature_flags(project_storage_ui: false)
- end
-
- it 'does not have a link to Usage Quotas' do
- render
+ it 'has a link to Usage Quotas' do
+ render
- expect(rendered).not_to have_link('Usage Quotas', href: project_usage_quotas_path(project))
- end
+ expect(rendered).to have_link('Usage Quotas', href: project_usage_quotas_path(project))
end
end
end
diff --git a/spec/views/profiles/audit_log.html.haml_spec.rb b/spec/views/profiles/audit_log.html.haml_spec.rb
new file mode 100644
index 00000000000..d5f6a2d64e7
--- /dev/null
+++ b/spec/views/profiles/audit_log.html.haml_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'profiles/audit_log' do
+ let(:user) { create(:user) }
+
+ before do
+ assign(:user, user)
+ assign(:events, AuthenticationEvent.all.page(params[:page]))
+ allow(controller).to receive(:current_user).and_return(user)
+ end
+
+ context 'when user has successful and failure events' do
+ before do
+ create(:authentication_event, :successful, user: user)
+ create(:authentication_event, :failed, user: user)
+ end
+
+ it 'only shows successful events' do
+ render
+
+ expect(rendered).to have_text('Signed in with standard authentication', count: 1)
+ end
+ end
+end
diff --git a/spec/views/projects/edit.html.haml_spec.rb b/spec/views/projects/edit.html.haml_spec.rb
index b44d07d2ee4..60f4c1664f7 100644
--- a/spec/views/projects/edit.html.haml_spec.rb
+++ b/spec/views/projects/edit.html.haml_spec.rb
@@ -57,6 +57,41 @@ RSpec.describe 'projects/edit' do
end
end
+ context 'merge commit template' do
+ it 'displays all possible variables' do
+ render
+
+ expect(rendered).to have_content('%{source_branch}')
+ expect(rendered).to have_content('%{target_branch}')
+ expect(rendered).to have_content('%{title}')
+ expect(rendered).to have_content('%{issues}')
+ expect(rendered).to have_content('%{description}')
+ expect(rendered).to have_content('%{reference}')
+ end
+
+ it 'displays a placeholder if none is set' do
+ render
+
+ expect(rendered).to have_field('project[merge_commit_template]', placeholder: <<~MSG.rstrip)
+ Merge branch '%{source_branch}' into '%{target_branch}'
+
+ %{title}
+
+ %{issues}
+
+ See merge request %{reference}
+ MSG
+ end
+
+ it 'displays the user entered value' do
+ project.update!(merge_commit_template: '%{title}')
+
+ render
+
+ expect(rendered).to have_field('project[merge_commit_template]', with: '%{title}')
+ end
+ end
+
context 'forking' do
before do
assign(:project, project)
diff --git a/spec/views/projects/issues/_service_desk_info_content.html.haml_spec.rb b/spec/views/projects/issues/_service_desk_info_content.html.haml_spec.rb
new file mode 100644
index 00000000000..1c6d729ddce
--- /dev/null
+++ b/spec/views/projects/issues/_service_desk_info_content.html.haml_spec.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'projects/issues/_service_desk_info_content' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:service_desk_address) { 'address@example.com' }
+
+ before do
+ assign(:project, project)
+ allow(project).to receive(:service_desk_address).and_return(service_desk_address)
+ allow(view).to receive(:current_user).and_return(user)
+ end
+
+ context 'when service desk is disabled' do
+ before do
+ allow(project).to receive(:service_desk_enabled?).and_return(false)
+ end
+
+ context 'when the logged user is at least maintainer' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'shows the info including the project settings link', :aggregate_failures do
+ render
+
+ expect(rendered).to have_text('Use Service Desk')
+ expect(rendered).not_to have_text(service_desk_address)
+ expect(rendered).to have_link(href: "/#{project.full_path}/edit")
+ end
+ end
+
+ context 'when the logged user is at only a developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'shows the info without the project settings link', :aggregate_failures do
+ render
+
+ expect(rendered).to have_text('Use Service Desk')
+ expect(rendered).not_to have_text(service_desk_address)
+ expect(rendered).not_to have_link(href: "/#{project.full_path}/edit")
+ end
+ end
+ end
+
+ context 'when service desk is enabled' do
+ before do
+ allow(project).to receive(:service_desk_enabled?).and_return(true)
+ end
+
+ context 'when the logged user is at least reporter' do
+ before do
+ project.add_reporter(user)
+ end
+
+ it 'shows the info including the email address', :aggregate_failures do
+ render
+
+ expect(rendered).to have_text('Use Service Desk')
+ expect(rendered).to have_text(service_desk_address)
+ expect(rendered).not_to have_link(href: "/#{project.full_path}/edit")
+ end
+ end
+
+ context 'when the logged user is at only a guest' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'shows the info without the email address', :aggregate_failures do
+ render
+
+ expect(rendered).to have_text('Use Service Desk')
+ expect(rendered).not_to have_text(service_desk_address)
+ expect(rendered).not_to have_link(href: "/#{project.full_path}/edit")
+ end
+ end
+
+ context 'when user is not logged in' do
+ let(:user) { nil }
+
+ it 'shows the info without the email address', :aggregate_failures do
+ render
+
+ expect(rendered).to have_text('Use Service Desk')
+ expect(rendered).not_to have_text(service_desk_address)
+ expect(rendered).not_to have_link(href: "/#{project.full_path}/edit")
+ end
+ end
+ end
+end
diff --git a/spec/workers/analytics/usage_trends/counter_job_worker_spec.rb b/spec/workers/analytics/usage_trends/counter_job_worker_spec.rb
index dd180229d12..c45ec20fe5a 100644
--- a/spec/workers/analytics/usage_trends/counter_job_worker_spec.rb
+++ b/spec/workers/analytics/usage_trends/counter_job_worker_spec.rb
@@ -11,7 +11,8 @@ RSpec.describe Analytics::UsageTrends::CounterJobWorker do
let(:job_args) { [users_measurement_identifier, user_1.id, user_2.id, recorded_at] }
before do
- allow(::Analytics::UsageTrends::Measurement.connection).to receive(:transaction_open?).and_return(false)
+ allow(::ApplicationRecord.connection).to receive(:transaction_open?).and_return(false)
+ allow(::Ci::ApplicationRecord.connection).to receive(:transaction_open?).and_return(false) if ::Ci::ApplicationRecord.connection_class?
end
include_examples 'an idempotent worker' do
diff --git a/spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb b/spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb
index f510852e753..fe4bc2421a4 100644
--- a/spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb
+++ b/spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb
@@ -4,7 +4,9 @@ require 'spec_helper'
RSpec.describe Ci::RefDeleteUnlockArtifactsWorker do
describe '#perform' do
- subject(:perform) { described_class.new.perform(project_id, user_id, ref) }
+ subject(:perform) { worker.perform(project_id, user_id, ref) }
+
+ let(:worker) { described_class.new }
let(:ref) { 'refs/heads/master' }
@@ -40,6 +42,36 @@ RSpec.describe Ci::RefDeleteUnlockArtifactsWorker do
expect(service).to have_received(:execute).with(ci_ref)
end
+
+ context 'when a locked pipeline with persisted artifacts exists' do
+ let!(:pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: 'master', project: project, locked: :artifacts_locked) }
+
+ context 'with ci_update_unlocked_job_artifacts disabled' do
+ before do
+ stub_feature_flags(ci_update_unlocked_job_artifacts: false)
+ end
+
+ it 'logs the correct extra metadata' do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:unlocked_pipelines, 1)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:unlocked_job_artifacts, 0)
+
+ perform
+ end
+ end
+
+ context 'with ci_update_unlocked_job_artifacts enabled' do
+ before do
+ stub_feature_flags(ci_update_unlocked_job_artifacts: true)
+ end
+
+ it 'logs the correct extra metadata' do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:unlocked_pipelines, 1)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:unlocked_job_artifacts, 2)
+
+ perform
+ end
+ end
+ end
end
context 'when ci ref does not exist for the given project' do
diff --git a/spec/workers/ci/resource_groups/assign_resource_from_resource_group_worker_spec.rb b/spec/workers/ci/resource_groups/assign_resource_from_resource_group_worker_spec.rb
index 650be1e84a9..be7f7ef5c8c 100644
--- a/spec/workers/ci/resource_groups/assign_resource_from_resource_group_worker_spec.rb
+++ b/spec/workers/ci/resource_groups/assign_resource_from_resource_group_worker_spec.rb
@@ -9,6 +9,10 @@ RSpec.describe Ci::ResourceGroups::AssignResourceFromResourceGroupWorker do
expect(described_class.get_deduplicate_strategy).to eq(:until_executed)
end
+ it 'has an option to reschedule once if deduplicated' do
+ expect(described_class.get_deduplication_options).to include({ if_deduplicated: :reschedule_once })
+ end
+
describe '#perform' do
subject { worker.perform(resource_group_id) }
diff --git a/spec/workers/clusters/applications/check_prometheus_health_worker_spec.rb b/spec/workers/clusters/applications/check_prometheus_health_worker_spec.rb
deleted file mode 100644
index fb779bf3b01..00000000000
--- a/spec/workers/clusters/applications/check_prometheus_health_worker_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Clusters::Applications::CheckPrometheusHealthWorker, '#perform' do
- subject { described_class.new.perform }
-
- it 'triggers health service' do
- cluster = create(:cluster)
- allow(Gitlab::Monitor::DemoProjects).to receive(:primary_keys)
- allow(Clusters::Cluster).to receive_message_chain(:with_application_prometheus, :with_project_http_integrations).and_return([cluster])
-
- service_instance = instance_double(Clusters::Applications::PrometheusHealthCheckService)
- expect(Clusters::Applications::PrometheusHealthCheckService).to receive(:new).with(cluster).and_return(service_instance)
- expect(service_instance).to receive(:execute)
-
- subject
- end
-end
diff --git a/spec/workers/clusters/integrations/check_prometheus_health_worker_spec.rb b/spec/workers/clusters/integrations/check_prometheus_health_worker_spec.rb
new file mode 100644
index 00000000000..6f70870bd09
--- /dev/null
+++ b/spec/workers/clusters/integrations/check_prometheus_health_worker_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Clusters::Integrations::CheckPrometheusHealthWorker, '#perform' do
+ subject { described_class.new.perform }
+
+ it 'triggers health service' do
+ cluster = create(:cluster)
+ allow(Gitlab::Monitor::DemoProjects).to receive(:primary_keys)
+ allow(Clusters::Cluster).to receive_message_chain(:with_integration_prometheus, :with_project_http_integrations).and_return([cluster])
+
+ service_instance = instance_double(Clusters::Integrations::PrometheusHealthCheckService)
+ expect(Clusters::Integrations::PrometheusHealthCheckService).to receive(:new).with(cluster).and_return(service_instance)
+ expect(service_instance).to receive(:execute)
+
+ subject
+ end
+end
diff --git a/spec/workers/concerns/application_worker_spec.rb b/spec/workers/concerns/application_worker_spec.rb
index af038c81b9e..fbf39b3c7cd 100644
--- a/spec/workers/concerns/application_worker_spec.rb
+++ b/spec/workers/concerns/application_worker_spec.rb
@@ -285,48 +285,38 @@ RSpec.describe ApplicationWorker do
end
end
- describe '.bulk_perform_async' do
- before do
- stub_const(worker.name, worker)
+ context 'different kinds of push_bulk' do
+ shared_context 'disable the `sidekiq_push_bulk_in_batches` feature flag' do
+ before do
+ stub_feature_flags(sidekiq_push_bulk_in_batches: false)
+ end
end
- it 'enqueues jobs in bulk' do
- Sidekiq::Testing.fake! do
- worker.bulk_perform_async([['Foo', [1]], ['Foo', [2]]])
-
- expect(worker.jobs.count).to eq 2
- expect(worker.jobs).to all(include('enqueued_at'))
+ shared_context 'set safe limit beyond the number of jobs to be enqueued' do
+ before do
+ stub_const("#{described_class}::SAFE_PUSH_BULK_LIMIT", args.count + 1)
end
end
- end
- describe '.bulk_perform_in' do
- before do
- stub_const(worker.name, worker)
+ shared_context 'set safe limit below the number of jobs to be enqueued' do
+ before do
+ stub_const("#{described_class}::SAFE_PUSH_BULK_LIMIT", 2)
+ end
end
- context 'when delay is valid' do
- it 'correctly schedules jobs' do
- Sidekiq::Testing.fake! do
- worker.bulk_perform_in(1.minute, [['Foo', [1]], ['Foo', [2]]])
+ shared_examples_for 'returns job_id of all enqueued jobs' do
+ let(:job_id_regex) { /[0-9a-f]{12}/ }
- expect(worker.jobs.count).to eq 2
- expect(worker.jobs).to all(include('at'))
- end
- end
- end
+ it 'returns job_id of all enqueued jobs' do
+ job_ids = perform_action
- context 'when delay is invalid' do
- it 'raises an ArgumentError exception' do
- expect { worker.bulk_perform_in(-60, [['Foo']]) }
- .to raise_error(ArgumentError)
+ expect(job_ids.count).to eq(args.count)
+ expect(job_ids).to all(match(job_id_regex))
end
end
- context 'with batches' do
- let(:batch_delay) { 1.minute }
-
- it 'correctly schedules jobs' do
+ shared_examples_for 'enqueues the jobs in a batched fashion, with each batch enqueing jobs as per the set safe limit' do
+ it 'enqueues the jobs in a batched fashion, with each batch enqueing jobs as per the set safe limit' do
expect(Sidekiq::Client).to(
receive(:push_bulk).with(hash_including('args' => [['Foo', [1]], ['Foo', [2]]]))
.ordered
@@ -337,29 +327,318 @@ RSpec.describe ApplicationWorker do
.and_call_original)
expect(Sidekiq::Client).to(
receive(:push_bulk).with(hash_including('args' => [['Foo', [5]]]))
- .ordered
- .and_call_original)
+ .ordered
+ .and_call_original)
- worker.bulk_perform_in(
- 1.minute,
- [['Foo', [1]], ['Foo', [2]], ['Foo', [3]], ['Foo', [4]], ['Foo', [5]]],
- batch_size: 2, batch_delay: batch_delay)
-
- expect(worker.jobs.count).to eq 5
- expect(worker.jobs[0]['at']).to eq(worker.jobs[1]['at'])
- expect(worker.jobs[2]['at']).to eq(worker.jobs[3]['at'])
- expect(worker.jobs[2]['at'] - worker.jobs[1]['at']).to eq(batch_delay)
- expect(worker.jobs[4]['at'] - worker.jobs[3]['at']).to eq(batch_delay)
- end
-
- context 'when batch_size is invalid' do
- it 'raises an ArgumentError exception' do
- expect do
- worker.bulk_perform_in(1.minute,
- [['Foo']],
- batch_size: -1, batch_delay: batch_delay)
- end.to raise_error(ArgumentError)
+ perform_action
+
+ expect(worker.jobs.count).to eq args.count
+ expect(worker.jobs).to all(include('enqueued_at'))
+ end
+ end
+
+ shared_examples_for 'enqueues jobs in one go' do
+ it 'enqueues jobs in one go' do
+ expect(Sidekiq::Client).to(
+ receive(:push_bulk).with(hash_including('args' => args)).once.and_call_original)
+ expect(Sidekiq.logger).not_to receive(:info)
+
+ perform_action
+
+ expect(worker.jobs.count).to eq args.count
+ expect(worker.jobs).to all(include('enqueued_at'))
+ end
+ end
+
+ shared_examples_for 'logs bulk insertions' do
+ it 'logs arguments and job IDs' do
+ worker.log_bulk_perform_async!
+
+ expect(Sidekiq.logger).to(
+ receive(:info).with(hash_including('class' => worker.name, 'args_list' => args)).once.and_call_original)
+ expect(Sidekiq.logger).to(
+ receive(:info).with(hash_including('class' => worker.name, 'jid_list' => anything)).once.and_call_original)
+
+ perform_action
+ end
+ end
+
+ before do
+ stub_const(worker.name, worker)
+ end
+
+ let(:args) do
+ [
+ ['Foo', [1]],
+ ['Foo', [2]],
+ ['Foo', [3]],
+ ['Foo', [4]],
+ ['Foo', [5]]
+ ]
+ end
+
+ describe '.bulk_perform_async' do
+ shared_examples_for 'does not schedule the jobs for any specific time' do
+ it 'does not schedule the jobs for any specific time' do
+ perform_action
+
+ expect(worker.jobs).to all(exclude('at'))
+ end
+ end
+
+ subject(:perform_action) do
+ worker.bulk_perform_async(args)
+ end
+
+ context 'push_bulk in safe limit batches' do
+ context 'when the number of jobs to be enqueued does not exceed the safe limit' do
+ include_context 'set safe limit beyond the number of jobs to be enqueued'
+
+ it_behaves_like 'enqueues jobs in one go'
+ it_behaves_like 'logs bulk insertions'
+ it_behaves_like 'returns job_id of all enqueued jobs'
+ it_behaves_like 'does not schedule the jobs for any specific time'
end
+
+ context 'when the number of jobs to be enqueued exceeds safe limit' do
+ include_context 'set safe limit below the number of jobs to be enqueued'
+
+ it_behaves_like 'enqueues the jobs in a batched fashion, with each batch enqueing jobs as per the set safe limit'
+ it_behaves_like 'returns job_id of all enqueued jobs'
+ it_behaves_like 'does not schedule the jobs for any specific time'
+ end
+
+ context 'when the feature flag `sidekiq_push_bulk_in_batches` is disabled' do
+ include_context 'disable the `sidekiq_push_bulk_in_batches` feature flag'
+
+ context 'when the number of jobs to be enqueued does not exceed the safe limit' do
+ include_context 'set safe limit beyond the number of jobs to be enqueued'
+
+ it_behaves_like 'enqueues jobs in one go'
+ it_behaves_like 'logs bulk insertions'
+ it_behaves_like 'returns job_id of all enqueued jobs'
+ it_behaves_like 'does not schedule the jobs for any specific time'
+ end
+
+ context 'when the number of jobs to be enqueued exceeds safe limit' do
+ include_context 'set safe limit below the number of jobs to be enqueued'
+
+ it_behaves_like 'enqueues jobs in one go'
+ it_behaves_like 'returns job_id of all enqueued jobs'
+ it_behaves_like 'does not schedule the jobs for any specific time'
+ end
+ end
+ end
+ end
+
+ describe '.bulk_perform_in' do
+ context 'without batches' do
+ shared_examples_for 'schedules all the jobs at a specific time' do
+ it 'schedules all the jobs at a specific time' do
+ perform_action
+
+ worker.jobs.each do |job_detail|
+ expect(job_detail['at']).to be_within(3.seconds).of(expected_scheduled_at_time)
+ end
+ end
+ end
+
+ let(:delay) { 3.minutes }
+ let(:expected_scheduled_at_time) { Time.current.to_i + delay.to_i }
+
+ subject(:perform_action) do
+ worker.bulk_perform_in(delay, args)
+ end
+
+ context 'when the scheduled time falls in the past' do
+ let(:delay) { -60 }
+
+ it 'raises an ArgumentError exception' do
+ expect { perform_action }
+ .to raise_error(ArgumentError)
+ end
+ end
+
+ context 'push_bulk in safe limit batches' do
+ context 'when the number of jobs to be enqueued does not exceed the safe limit' do
+ include_context 'set safe limit beyond the number of jobs to be enqueued'
+
+ it_behaves_like 'enqueues jobs in one go'
+ it_behaves_like 'returns job_id of all enqueued jobs'
+ it_behaves_like 'schedules all the jobs at a specific time'
+ end
+
+ context 'when the number of jobs to be enqueued exceeds safe limit' do
+ include_context 'set safe limit below the number of jobs to be enqueued'
+
+ it_behaves_like 'enqueues the jobs in a batched fashion, with each batch enqueing jobs as per the set safe limit'
+ it_behaves_like 'returns job_id of all enqueued jobs'
+ it_behaves_like 'schedules all the jobs at a specific time'
+ end
+
+ context 'when the feature flag `sidekiq_push_bulk_in_batches` is disabled' do
+ include_context 'disable the `sidekiq_push_bulk_in_batches` feature flag'
+
+ context 'when the number of jobs to be enqueued does not exceed the safe limit' do
+ include_context 'set safe limit beyond the number of jobs to be enqueued'
+
+ it_behaves_like 'enqueues jobs in one go'
+ it_behaves_like 'returns job_id of all enqueued jobs'
+ it_behaves_like 'schedules all the jobs at a specific time'
+ end
+
+ context 'when the number of jobs to be enqueued exceeds safe limit' do
+ include_context 'set safe limit below the number of jobs to be enqueued'
+
+ it_behaves_like 'enqueues jobs in one go'
+ it_behaves_like 'returns job_id of all enqueued jobs'
+ it_behaves_like 'schedules all the jobs at a specific time'
+ end
+ end
+ end
+ end
+
+ context 'with batches' do
+ shared_examples_for 'schedules all the jobs at a specific time, per batch' do
+ it 'schedules all the jobs at a specific time, per batch' do
+ perform_action
+
+ expect(worker.jobs[0]['at']).to eq(worker.jobs[1]['at'])
+ expect(worker.jobs[2]['at']).to eq(worker.jobs[3]['at'])
+ expect(worker.jobs[2]['at'] - worker.jobs[1]['at']).to eq(batch_delay)
+ expect(worker.jobs[4]['at'] - worker.jobs[3]['at']).to eq(batch_delay)
+ end
+ end
+
+ let(:delay) { 1.minute }
+ let(:batch_size) { 2 }
+ let(:batch_delay) { 10.minutes }
+
+ subject(:perform_action) do
+ worker.bulk_perform_in(delay, args, batch_size: batch_size, batch_delay: batch_delay)
+ end
+
+ context 'when the `batch_size` is invalid' do
+ context 'when `batch_size` is 0' do
+ let(:batch_size) { 0 }
+
+ it 'raises an ArgumentError exception' do
+ expect { perform_action }
+ .to raise_error(ArgumentError)
+ end
+ end
+
+ context 'when `batch_size` is negative' do
+ let(:batch_size) { -3 }
+
+ it 'raises an ArgumentError exception' do
+ expect { perform_action }
+ .to raise_error(ArgumentError)
+ end
+ end
+ end
+
+ context 'when the `batch_delay` is invalid' do
+ context 'when `batch_delay` is 0' do
+ let(:batch_delay) { 0.minutes }
+
+ it 'raises an ArgumentError exception' do
+ expect { perform_action }
+ .to raise_error(ArgumentError)
+ end
+ end
+
+ context 'when `batch_delay` is negative' do
+ let(:batch_delay) { -3.minutes }
+
+ it 'raises an ArgumentError exception' do
+ expect { perform_action }
+ .to raise_error(ArgumentError)
+ end
+ end
+ end
+
+ context 'push_bulk in safe limit batches' do
+ context 'when the number of jobs to be enqueued does not exceed the safe limit' do
+ include_context 'set safe limit beyond the number of jobs to be enqueued'
+
+ it_behaves_like 'enqueues jobs in one go'
+ it_behaves_like 'returns job_id of all enqueued jobs'
+ it_behaves_like 'schedules all the jobs at a specific time, per batch'
+ end
+
+ context 'when the number of jobs to be enqueued exceeds safe limit' do
+ include_context 'set safe limit below the number of jobs to be enqueued'
+
+ it_behaves_like 'enqueues the jobs in a batched fashion, with each batch enqueing jobs as per the set safe limit'
+ it_behaves_like 'returns job_id of all enqueued jobs'
+ it_behaves_like 'schedules all the jobs at a specific time, per batch'
+ end
+
+ context 'when the feature flag `sidekiq_push_bulk_in_batches` is disabled' do
+ include_context 'disable the `sidekiq_push_bulk_in_batches` feature flag'
+
+ context 'when the number of jobs to be enqueued does not exceed the safe limit' do
+ include_context 'set safe limit beyond the number of jobs to be enqueued'
+
+ it_behaves_like 'enqueues jobs in one go'
+ it_behaves_like 'returns job_id of all enqueued jobs'
+ it_behaves_like 'schedules all the jobs at a specific time, per batch'
+ end
+
+ context 'when the number of jobs to be enqueued exceeds safe limit' do
+ include_context 'set safe limit below the number of jobs to be enqueued'
+
+ it_behaves_like 'enqueues jobs in one go'
+ it_behaves_like 'returns job_id of all enqueued jobs'
+ it_behaves_like 'schedules all the jobs at a specific time, per batch'
+ end
+ end
+ end
+ end
+ end
+ end
+
+ describe '.with_status' do
+ around do |example|
+ Sidekiq::Testing.fake!(&example)
+ end
+
+ context 'when the worker does have status_expiration set' do
+ let(:status_expiration_worker) do
+ Class.new(worker) do
+ sidekiq_options status_expiration: 3
+ end
+ end
+
+ it 'uses status_expiration from the worker' do
+ status_expiration_worker.with_status.perform_async
+
+ expect(Sidekiq::Queues[status_expiration_worker.queue].first).to include('status_expiration' => 3)
+ expect(Sidekiq::Queues[status_expiration_worker.queue].length).to eq(1)
+ end
+
+ it 'uses status_expiration from the worker without with_status' do
+ status_expiration_worker.perform_async
+
+ expect(Sidekiq::Queues[status_expiration_worker.queue].first).to include('status_expiration' => 3)
+ expect(Sidekiq::Queues[status_expiration_worker.queue].length).to eq(1)
+ end
+ end
+
+ context 'when the worker does not have status_expiration set' do
+ it 'uses the default status_expiration' do
+ worker.with_status.perform_async
+
+ expect(Sidekiq::Queues[worker.queue].first).to include('status_expiration' => Gitlab::SidekiqStatus::DEFAULT_EXPIRATION)
+ expect(Sidekiq::Queues[worker.queue].length).to eq(1)
+ end
+
+ it 'does not set status_expiration without with_status' do
+ worker.perform_async
+
+ expect(Sidekiq::Queues[worker.queue].first).not_to include('status_expiration')
+ expect(Sidekiq::Queues[worker.queue].length).to eq(1)
end
end
end
diff --git a/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
index d4126fe688a..cbffb8f3870 100644
--- a/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
+++ b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
@@ -82,8 +82,9 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
nil | 10 | nil
0 | 5 | nil
10 | 0 | 0
- 10 | 5 | 0.5
- 3 | 10 | (10 / 3.to_f)
+ 10 | 5 | 50.0
+ 17 | 3 | 17.65
+ 3 | 10 | 333.33
end
with_them do
diff --git a/spec/workers/database/drop_detached_partitions_worker_spec.rb b/spec/workers/database/drop_detached_partitions_worker_spec.rb
index 8693878ddd5..a10fcaaa5d9 100644
--- a/spec/workers/database/drop_detached_partitions_worker_spec.rb
+++ b/spec/workers/database/drop_detached_partitions_worker_spec.rb
@@ -6,21 +6,19 @@ RSpec.describe Database::DropDetachedPartitionsWorker do
describe '#perform' do
subject { described_class.new.perform }
- let(:monitoring) { instance_double('PartitionMonitoring', report_metrics: nil) }
-
before do
allow(Gitlab::Database::Partitioning).to receive(:drop_detached_partitions)
- allow(Gitlab::Database::Partitioning::PartitionMonitoring).to receive(:new).and_return(monitoring)
+ allow(Gitlab::Database::Partitioning).to receive(:report_metrics)
end
- it 'delegates to Partitioning.drop_detached_partitions' do
+ it 'drops detached partitions' do
expect(Gitlab::Database::Partitioning).to receive(:drop_detached_partitions)
subject
end
it 'reports partition metrics' do
- expect(monitoring).to receive(:report_metrics)
+ expect(Gitlab::Database::Partitioning).to receive(:report_metrics)
subject
end
diff --git a/spec/workers/database/partition_management_worker_spec.rb b/spec/workers/database/partition_management_worker_spec.rb
index 9ded36743a8..e5362e95f48 100644
--- a/spec/workers/database/partition_management_worker_spec.rb
+++ b/spec/workers/database/partition_management_worker_spec.rb
@@ -6,20 +6,19 @@ RSpec.describe Database::PartitionManagementWorker do
describe '#perform' do
subject { described_class.new.perform }
- let(:monitoring) { instance_double('PartitionMonitoring', report_metrics: nil) }
-
before do
- allow(Gitlab::Database::Partitioning::PartitionMonitoring).to receive(:new).and_return(monitoring)
+ allow(Gitlab::Database::Partitioning).to receive(:sync_partitions)
+ allow(Gitlab::Database::Partitioning).to receive(:report_metrics)
end
- it 'delegates to Partitioning' do
+ it 'syncs partitions' do
expect(Gitlab::Database::Partitioning).to receive(:sync_partitions)
subject
end
it 'reports partition metrics' do
- expect(monitoring).to receive(:report_metrics)
+ expect(Gitlab::Database::Partitioning).to receive(:report_metrics)
subject
end
diff --git a/spec/workers/dependency_proxy/image_ttl_group_policy_worker_spec.rb b/spec/workers/dependency_proxy/image_ttl_group_policy_worker_spec.rb
index d3234f4c212..ae0cb097ebf 100644
--- a/spec/workers/dependency_proxy/image_ttl_group_policy_worker_spec.rb
+++ b/spec/workers/dependency_proxy/image_ttl_group_policy_worker_spec.rb
@@ -12,8 +12,8 @@ RSpec.describe DependencyProxy::ImageTtlGroupPolicyWorker do
subject { worker.perform }
context 'when there are images to expire' do
- let_it_be_with_reload(:old_blob) { create(:dependency_proxy_blob, group: group, updated_at: 1.year.ago) }
- let_it_be_with_reload(:old_manifest) { create(:dependency_proxy_manifest, group: group, updated_at: 1.year.ago) }
+ let_it_be_with_reload(:old_blob) { create(:dependency_proxy_blob, group: group, read_at: 1.year.ago) }
+ let_it_be_with_reload(:old_manifest) { create(:dependency_proxy_manifest, group: group, read_at: 1.year.ago) }
let_it_be_with_reload(:new_blob) { create(:dependency_proxy_blob, group: group) }
let_it_be_with_reload(:new_manifest) { create(:dependency_proxy_manifest, group: group) }
diff --git a/spec/workers/deployments/archive_in_project_worker_spec.rb b/spec/workers/deployments/archive_in_project_worker_spec.rb
new file mode 100644
index 00000000000..6435fe8bea1
--- /dev/null
+++ b/spec/workers/deployments/archive_in_project_worker_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Deployments::ArchiveInProjectWorker do
+ subject { described_class.new.perform(deployment&.project_id) }
+
+ describe '#perform' do
+ let(:deployment) { create(:deployment, :success) }
+
+ it 'executes Deployments::ArchiveInProjectService' do
+ expect(Deployments::ArchiveInProjectService)
+ .to receive(:new).with(deployment.project, nil).and_call_original
+
+ subject
+ end
+ end
+end
diff --git a/spec/workers/email_receiver_worker_spec.rb b/spec/workers/email_receiver_worker_spec.rb
index 83e13ded7b3..83720ee132b 100644
--- a/spec/workers/email_receiver_worker_spec.rb
+++ b/spec/workers/email_receiver_worker_spec.rb
@@ -37,6 +37,15 @@ RSpec.describe EmailReceiverWorker, :mailer do
expect(email.to).to eq(["jake@adventuretime.ooo"])
expect(email.subject).to include("Rejected")
end
+
+ it 'strips out the body before passing to EmailRejectionMailer' do
+ mail = Mail.new(raw_message)
+ mail.body = nil
+
+ expect(EmailRejectionMailer).to receive(:rejection).with(anything, mail.encoded, anything).and_call_original
+
+ described_class.new.perform(raw_message)
+ end
end
context 'when the error is Gitlab::Email::AutoGeneratedEmailError' do
diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb
index 6c37c422aed..3e313610054 100644
--- a/spec/workers/emails_on_push_worker_spec.rb
+++ b/spec/workers/emails_on_push_worker_spec.rb
@@ -139,6 +139,43 @@ RSpec.describe EmailsOnPushWorker, :mailer do
perform
end
+
+ context 'when SMIME signing is enabled' do
+ include SmimeHelper
+
+ before :context do
+ @root_ca = generate_root
+ @cert = generate_cert(signer_ca: @root_ca)
+ end
+
+ let(:root_certificate) do
+ Gitlab::X509::Certificate.new(@root_ca[:key], @root_ca[:cert])
+ end
+
+ let(:certificate) do
+ Gitlab::X509::Certificate.new(@cert[:key], @cert[:cert])
+ end
+
+ before do
+ allow(Gitlab::Email::Hook::SmimeSignatureInterceptor).to receive(:certificate).and_return(certificate)
+
+ Mail.register_interceptor(Gitlab::Email::Hook::SmimeSignatureInterceptor)
+ end
+
+ after do
+ Mail.unregister_interceptor(Gitlab::Email::Hook::SmimeSignatureInterceptor)
+ end
+
+ it 'does not sign the email multiple times' do
+ perform
+
+ ActionMailer::Base.deliveries.each do |mail|
+ expect(mail.header['Content-Type'].value).to match('multipart/signed').and match('protocol="application/x-pkcs7-signature"')
+
+ expect(mail.to_s.scan(/Content-Disposition: attachment;\r\n filename=smime.p7s/).size).to eq(1)
+ end
+ end
+ end
end
context "when recipients are invalid" do
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
index 9a4b27997e9..d00243672f9 100644
--- a/spec/workers/every_sidekiq_worker_spec.rb
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -316,6 +316,8 @@ RSpec.describe 'Every Sidekiq worker' do
'IssuableExportCsvWorker' => 3,
'IssuePlacementWorker' => 3,
'IssueRebalancingWorker' => 3,
+ 'Issues::PlacementWorker' => 3,
+ 'Issues::RebalancingWorker' => 3,
'IterationsUpdateStatusWorker' => 3,
'JiraConnect::SyncBranchWorker' => 3,
'JiraConnect::SyncBuildsWorker' => 3,
diff --git a/spec/workers/integrations/create_external_cross_reference_worker_spec.rb b/spec/workers/integrations/create_external_cross_reference_worker_spec.rb
new file mode 100644
index 00000000000..61723f44aa5
--- /dev/null
+++ b/spec/workers/integrations/create_external_cross_reference_worker_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::CreateExternalCrossReferenceWorker do
+ include AfterNextHelpers
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:project) { create(:jira_project, :repository) }
+ let_it_be(:author) { create(:user) }
+ let_it_be(:commit) { project.commit }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let_it_be(:note) { create(:note, project: project) }
+ let_it_be(:snippet) { create(:project_snippet, project: project) }
+
+ let(:project_id) { project.id }
+ let(:external_issue_id) { 'JIRA-123' }
+ let(:mentionable_type) { 'Issue' }
+ let(:mentionable_id) { issue.id }
+ let(:author_id) { author.id }
+ let(:job_args) { [project_id, external_issue_id, mentionable_type, mentionable_id, author_id] }
+
+ def perform
+ described_class.new.perform(*job_args)
+ end
+
+ before do
+ allow(Project).to receive(:find_by_id).and_return(project)
+ end
+
+ it_behaves_like 'an idempotent worker' do
+ before do
+ allow(project.external_issue_tracker).to receive(:create_cross_reference_note)
+ end
+
+ it 'can run multiple times with the same arguments' do
+ subject
+
+ expect(project.external_issue_tracker).to have_received(:create_cross_reference_note)
+ .exactly(worker_exec_times).times
+ end
+ end
+
+ it 'has the `until_executed` deduplicate strategy' do
+ expect(described_class.get_deduplicate_strategy).to eq(:until_executed)
+ expect(described_class.get_deduplication_options).to include({ including_scheduled: true })
+ end
+
+ # These are the only models where we currently support cross-references,
+ # although this should be expanded to all `Mentionable` models.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/343975
+ where(:mentionable_type, :mentionable_id) do
+ 'Commit' | lazy { commit.id }
+ 'Issue' | lazy { issue.id }
+ 'MergeRequest' | lazy { merge_request.id }
+ 'Note' | lazy { note.id }
+ 'Snippet' | lazy { snippet.id }
+ end
+
+ with_them do
+ it 'creates a cross reference' do
+ expect(project.external_issue_tracker).to receive(:create_cross_reference_note).with(
+ be_a(ExternalIssue).and(have_attributes(id: external_issue_id, project: project)),
+ be_a(mentionable_type.constantize).and(have_attributes(id: mentionable_id)),
+ be_a(User).and(have_attributes(id: author_id))
+ )
+
+ perform
+ end
+ end
+
+ describe 'error handling' do
+ shared_examples 'does not create a cross reference' do
+ it 'does not create a cross reference' do
+ expect(project).not_to receive(:external_issue_tracker) if project
+
+ perform
+ end
+ end
+
+ context 'project_id does not exist' do
+ let(:project_id) { non_existing_record_id }
+ let(:project) { nil }
+
+ it_behaves_like 'does not create a cross reference'
+ end
+
+ context 'author_id does not exist' do
+ let(:author_id) { non_existing_record_id }
+
+ it_behaves_like 'does not create a cross reference'
+ end
+
+ context 'mentionable_id does not exist' do
+ let(:mentionable_id) { non_existing_record_id }
+
+ it_behaves_like 'does not create a cross reference'
+ end
+
+ context 'mentionable_type is not a Mentionable' do
+ let(:mentionable_type) { 'User' }
+
+ before do
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(kind_of(ArgumentError))
+ end
+
+ it_behaves_like 'does not create a cross reference'
+ end
+
+ context 'mentionable_type is not a defined constant' do
+ let(:mentionable_type) { 'FooBar' }
+
+ before do
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(kind_of(ArgumentError))
+ end
+
+ it_behaves_like 'does not create a cross reference'
+ end
+
+ context 'mentionable is a Commit and mentionable_id does not exist' do
+ let(:mentionable_type) { 'Commit' }
+ let(:mentionable_id) { non_existing_record_id }
+
+ it_behaves_like 'does not create a cross reference'
+ end
+ end
+end
diff --git a/spec/workers/issue_rebalancing_worker_spec.rb b/spec/workers/issue_rebalancing_worker_spec.rb
index cba42a1577e..cfb19af05b3 100644
--- a/spec/workers/issue_rebalancing_worker_spec.rb
+++ b/spec/workers/issue_rebalancing_worker_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe IssueRebalancingWorker do
+RSpec.describe IssueRebalancingWorker, :clean_gitlab_redis_shared_state do
describe '#perform' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
@@ -35,6 +35,20 @@ RSpec.describe IssueRebalancingWorker do
described_class.new.perform # all arguments are nil
end
+
+ it 'does not schedule a new rebalance if it finished under 1h ago' do
+ container_type = arguments.second.present? ? ::Gitlab::Issues::Rebalancing::State::PROJECT : ::Gitlab::Issues::Rebalancing::State::NAMESPACE
+ container_id = arguments.second || arguments.third
+
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(::Gitlab::Issues::Rebalancing::State.send(:recently_finished_key, container_type, container_id), true)
+ end
+
+ expect(Issues::RelativePositionRebalancingService).not_to receive(:new)
+ expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+
+ described_class.new.perform(*arguments)
+ end
end
shared_examples 'safely handles non-existent ids' do
diff --git a/spec/workers/issues/placement_worker_spec.rb b/spec/workers/issues/placement_worker_spec.rb
new file mode 100644
index 00000000000..694cdd2ef37
--- /dev/null
+++ b/spec/workers/issues/placement_worker_spec.rb
@@ -0,0 +1,151 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Issues::PlacementWorker do
+ describe '#perform' do
+ let_it_be(:time) { Time.now.utc }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:author) { create(:user) }
+ let_it_be(:common_attrs) { { author: author, project: project } }
+ let_it_be(:unplaced) { common_attrs.merge(relative_position: nil) }
+ let_it_be_with_reload(:issue) { create(:issue, **unplaced, created_at: time) }
+ let_it_be_with_reload(:issue_a) { create(:issue, **unplaced, created_at: time - 1.minute) }
+ let_it_be_with_reload(:issue_b) { create(:issue, **unplaced, created_at: time - 2.minutes) }
+ let_it_be_with_reload(:issue_c) { create(:issue, **unplaced, created_at: time + 1.minute) }
+ let_it_be_with_reload(:issue_d) { create(:issue, **unplaced, created_at: time + 2.minutes) }
+ let_it_be_with_reload(:issue_e) { create(:issue, **common_attrs, relative_position: 10, created_at: time + 1.minute) }
+ let_it_be_with_reload(:issue_f) { create(:issue, **unplaced, created_at: time + 1.minute) }
+
+ let_it_be(:irrelevant) { create(:issue, relative_position: nil, created_at: time) }
+
+ shared_examples 'running the issue placement worker' do
+ let(:issue_id) { issue.id }
+ let(:project_id) { project.id }
+
+ it 'places all issues created at most 5 minutes before this one at the end, most recent last' do
+ expect { run_worker }.not_to change { irrelevant.reset.relative_position }
+
+ expect(project.issues.order_by_relative_position)
+ .to eq([issue_e, issue_b, issue_a, issue, issue_c, issue_f, issue_d])
+ expect(project.issues.where(relative_position: nil)).not_to exist
+ end
+
+ it 'schedules rebalancing if needed' do
+ issue_a.update!(relative_position: RelativePositioning::MAX_POSITION)
+
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
+
+ run_worker
+ end
+
+ context 'there are more than QUERY_LIMIT unplaced issues' do
+ before_all do
+ # Ensure there are more than N issues in this set
+ n = described_class::QUERY_LIMIT
+ create_list(:issue, n - 5, **unplaced)
+ end
+
+ it 'limits the sweep to QUERY_LIMIT records, and reschedules placement' do
+ expect(Issue).to receive(:move_nulls_to_end)
+ .with(have_attributes(count: described_class::QUERY_LIMIT))
+ .and_call_original
+
+ expect(described_class).to receive(:perform_async).with(nil, project.id)
+
+ run_worker
+
+ expect(project.issues.where(relative_position: nil)).to exist
+ end
+
+ it 'is eventually correct' do
+ prefix = project.issues.where.not(relative_position: nil).order(:relative_position).to_a
+ moved = project.issues.where.not(id: prefix.map(&:id))
+
+ run_worker
+
+ expect(project.issues.where(relative_position: nil)).to exist
+
+ run_worker
+
+ expect(project.issues.where(relative_position: nil)).not_to exist
+ expect(project.issues.order(:relative_position)).to eq(prefix + moved.order(:created_at, :id))
+ end
+ end
+
+ context 'we are passed bad IDs' do
+ let(:issue_id) { non_existing_record_id }
+ let(:project_id) { non_existing_record_id }
+
+ def max_positions_by_project
+ Issue
+ .group(:project_id)
+ .pluck(:project_id, Issue.arel_table[:relative_position].maximum.as('max_relative_position'))
+ .to_h
+ end
+
+ it 'does move any issues to the end' do
+ expect { run_worker }.not_to change { max_positions_by_project }
+ end
+
+ context 'the project_id refers to an empty project' do
+ let!(:project_id) { create(:project).id }
+
+ it 'does move any issues to the end' do
+ expect { run_worker }.not_to change { max_positions_by_project }
+ end
+ end
+ end
+
+ it 'anticipates the failure to place the issues, and schedules rebalancing' do
+ allow(Issue).to receive(:move_nulls_to_end) { raise RelativePositioning::NoSpaceLeft }
+
+ expect(Issues::RebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(RelativePositioning::NoSpaceLeft, worker_arguments)
+
+ run_worker
+ end
+ end
+
+ context 'passing an issue ID' do
+ def run_worker
+ described_class.new.perform(issue_id)
+ end
+
+ let(:worker_arguments) { { issue_id: issue_id, project_id: nil } }
+
+ it_behaves_like 'running the issue placement worker'
+
+ context 'when block_issue_repositioning is enabled' do
+ let(:issue_id) { issue.id }
+ let(:project_id) { project.id }
+
+ before do
+ stub_feature_flags(block_issue_repositioning: group)
+ end
+
+ it 'does not run repositioning tasks' do
+ expect { run_worker }.not_to change { issue.reset.relative_position }
+ end
+ end
+ end
+
+ context 'passing a project ID' do
+ def run_worker
+ described_class.new.perform(nil, project_id)
+ end
+
+ let(:worker_arguments) { { issue_id: nil, project_id: project_id } }
+
+ it_behaves_like 'running the issue placement worker'
+ end
+ end
+
+ it 'has the `until_executed` deduplicate strategy' do
+ expect(described_class.get_deduplicate_strategy).to eq(:until_executed)
+ expect(described_class.get_deduplication_options).to include({ including_scheduled: true })
+ end
+end
diff --git a/spec/workers/issues/rebalancing_worker_spec.rb b/spec/workers/issues/rebalancing_worker_spec.rb
new file mode 100644
index 00000000000..438edd85f66
--- /dev/null
+++ b/spec/workers/issues/rebalancing_worker_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Issues::RebalancingWorker do
+ describe '#perform' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:issue) { create(:issue, project: project) }
+
+ shared_examples 'running the worker' do
+ it 'runs an instance of Issues::RelativePositionRebalancingService' do
+ service = double(execute: nil)
+ service_param = arguments.second.present? ? kind_of(Project.id_in([project]).class) : kind_of(group&.all_projects.class)
+
+ expect(Issues::RelativePositionRebalancingService).to receive(:new).with(service_param).and_return(service)
+
+ described_class.new.perform(*arguments)
+ end
+
+ it 'anticipates there being too many concurent rebalances' do
+ service = double
+ service_param = arguments.second.present? ? kind_of(Project.id_in([project]).class) : kind_of(group&.all_projects.class)
+
+ allow(service).to receive(:execute).and_raise(Issues::RelativePositionRebalancingService::TooManyConcurrentRebalances)
+ expect(Issues::RelativePositionRebalancingService).to receive(:new).with(service_param).and_return(service)
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(Issues::RelativePositionRebalancingService::TooManyConcurrentRebalances, include(project_id: arguments.second, root_namespace_id: arguments.third))
+
+ described_class.new.perform(*arguments)
+ end
+
+ it 'takes no action if the value is nil' do
+ expect(Issues::RelativePositionRebalancingService).not_to receive(:new)
+ expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+
+ described_class.new.perform # all arguments are nil
+ end
+ end
+
+ shared_examples 'safely handles non-existent ids' do
+ it 'anticipates the inability to find the issue' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(ArgumentError, include(project_id: arguments.second, root_namespace_id: arguments.third))
+ expect(Issues::RelativePositionRebalancingService).not_to receive(:new)
+
+ described_class.new.perform(*arguments)
+ end
+ end
+
+ context 'without root_namespace param' do
+ it_behaves_like 'running the worker' do
+ let(:arguments) { [-1, project.id] }
+ end
+
+ it_behaves_like 'safely handles non-existent ids' do
+ let(:arguments) { [nil, -1] }
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [-1, project.id] }
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [nil, -1] }
+ end
+ end
+
+ context 'with root_namespace param' do
+ it_behaves_like 'running the worker' do
+ let(:arguments) { [nil, nil, group.id] }
+ end
+
+ it_behaves_like 'safely handles non-existent ids' do
+ let(:arguments) { [nil, nil, -1] }
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [nil, nil, group.id] }
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [nil, nil, -1] }
+ end
+ end
+ end
+
+ it 'has the `until_executed` deduplicate strategy' do
+ expect(described_class.get_deduplicate_strategy).to eq(:until_executed)
+ expect(described_class.get_deduplication_options).to include({ including_scheduled: true })
+ end
+end
diff --git a/spec/workers/issues/reschedule_stuck_issue_rebalances_worker_spec.rb b/spec/workers/issues/reschedule_stuck_issue_rebalances_worker_spec.rb
new file mode 100644
index 00000000000..02d1241d2ba
--- /dev/null
+++ b/spec/workers/issues/reschedule_stuck_issue_rebalances_worker_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Issues::RescheduleStuckIssueRebalancesWorker, :clean_gitlab_redis_shared_state do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ subject(:worker) { described_class.new }
+
+ describe '#perform' do
+ it 'does not schedule a rebalance' do
+ expect(IssueRebalancingWorker).not_to receive(:perform_async)
+
+ worker.perform
+ end
+
+ it 'schedules a rebalance in case there are any rebalances started' do
+ expect(::Gitlab::Issues::Rebalancing::State).to receive(:fetch_rebalancing_groups_and_projects).and_return([[group.id], [project.id]])
+ expect(IssueRebalancingWorker).to receive(:bulk_perform_async).with([[nil, nil, group.id]]).once
+ expect(IssueRebalancingWorker).to receive(:bulk_perform_async).with([[nil, project.id, nil]]).once
+
+ worker.perform
+ end
+ end
+end
diff --git a/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb b/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb
new file mode 100644
index 00000000000..544be2a69a6
--- /dev/null
+++ b/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb
@@ -0,0 +1,153 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe LooseForeignKeys::CleanupWorker do
+ include MigrationsHelpers
+
+ def create_table_structure
+ migration = ActiveRecord::Migration.new.extend(Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers)
+
+ migration.create_table :_test_loose_fk_parent_table_1
+ migration.create_table :_test_loose_fk_parent_table_2
+
+ migration.create_table :_test_loose_fk_child_table_1_1 do |t|
+ t.bigint :parent_id
+ end
+
+ migration.create_table :_test_loose_fk_child_table_1_2 do |t|
+ t.bigint :parent_id_with_different_column
+ end
+
+ migration.create_table :_test_loose_fk_child_table_2_1 do |t|
+ t.bigint :parent_id
+ end
+
+ migration.track_record_deletions(:_test_loose_fk_parent_table_1)
+ migration.track_record_deletions(:_test_loose_fk_parent_table_2)
+ end
+
+ let!(:parent_model_1) do
+ Class.new(ApplicationRecord) do
+ self.table_name = '_test_loose_fk_parent_table_1'
+
+ include LooseForeignKey
+
+ loose_foreign_key :_test_loose_fk_child_table_1_1, :parent_id, on_delete: :async_delete
+ loose_foreign_key :_test_loose_fk_child_table_1_2, :parent_id_with_different_column, on_delete: :async_nullify
+ end
+ end
+
+ let!(:parent_model_2) do
+ Class.new(ApplicationRecord) do
+ self.table_name = '_test_loose_fk_parent_table_2'
+
+ include LooseForeignKey
+
+ loose_foreign_key :_test_loose_fk_child_table_2_1, :parent_id, on_delete: :async_delete
+ end
+ end
+
+ let!(:child_model_1) do
+ Class.new(ApplicationRecord) do
+ self.table_name = '_test_loose_fk_child_table_1_1'
+ end
+ end
+
+ let!(:child_model_2) do
+ Class.new(ApplicationRecord) do
+ self.table_name = '_test_loose_fk_child_table_1_2'
+ end
+ end
+
+ let!(:child_model_3) do
+ Class.new(ApplicationRecord) do
+ self.table_name = '_test_loose_fk_child_table_2_1'
+ end
+ end
+
+ let(:loose_fk_parent_table_1) { table(:_test_loose_fk_parent_table_1) }
+ let(:loose_fk_parent_table_2) { table(:_test_loose_fk_parent_table_2) }
+ let(:loose_fk_child_table_1_1) { table(:_test_loose_fk_child_table_1_1) }
+ let(:loose_fk_child_table_1_2) { table(:_test_loose_fk_child_table_1_2) }
+ let(:loose_fk_child_table_2_1) { table(:_test_loose_fk_child_table_2_1) }
+
+ before(:all) do
+ create_table_structure
+ end
+
+ after(:all) do
+ migration = ActiveRecord::Migration.new
+
+ migration.drop_table :_test_loose_fk_parent_table_1
+ migration.drop_table :_test_loose_fk_parent_table_2
+ migration.drop_table :_test_loose_fk_child_table_1_1
+ migration.drop_table :_test_loose_fk_child_table_1_2
+ migration.drop_table :_test_loose_fk_child_table_2_1
+ end
+
+ before do
+ parent_record_1 = loose_fk_parent_table_1.create!
+ loose_fk_child_table_1_1.create!(parent_id: parent_record_1.id)
+ loose_fk_child_table_1_2.create!(parent_id_with_different_column: parent_record_1.id)
+
+ parent_record_2 = loose_fk_parent_table_1.create!
+ 2.times { loose_fk_child_table_1_1.create!(parent_id: parent_record_2.id) }
+ 3.times { loose_fk_child_table_1_2.create!(parent_id_with_different_column: parent_record_2.id) }
+
+ parent_record_3 = loose_fk_parent_table_2.create!
+ 5.times { loose_fk_child_table_2_1.create!(parent_id: parent_record_3.id) }
+
+ parent_model_1.delete_all
+ parent_model_2.delete_all
+ end
+
+ it 'cleans up all rows' do
+ described_class.new.perform
+
+ expect(loose_fk_child_table_1_1.count).to eq(0)
+ expect(loose_fk_child_table_1_2.where(parent_id_with_different_column: nil).count).to eq(4)
+ expect(loose_fk_child_table_2_1.count).to eq(0)
+ end
+
+ context 'when deleting in batches' do
+ before do
+ stub_const('LooseForeignKeys::CleanupWorker::BATCH_SIZE', 2)
+ end
+
+ it 'cleans up all rows' do
+ expect(LooseForeignKeys::BatchCleanerService).to receive(:new).exactly(:twice).and_call_original
+
+ described_class.new.perform
+
+ expect(loose_fk_child_table_1_1.count).to eq(0)
+ expect(loose_fk_child_table_1_2.where(parent_id_with_different_column: nil).count).to eq(4)
+ expect(loose_fk_child_table_2_1.count).to eq(0)
+ end
+ end
+
+ context 'when the deleted rows count limit have been reached' do
+ def count_deletable_rows
+ loose_fk_child_table_1_1.count + loose_fk_child_table_2_1.count
+ end
+
+ before do
+ stub_const('LooseForeignKeys::ModificationTracker::MAX_DELETES', 2)
+ stub_const('LooseForeignKeys::CleanerService::DELETE_LIMIT', 1)
+ end
+
+ it 'cleans up 2 rows' do
+ expect { described_class.new.perform }.to change { count_deletable_rows }.by(-2)
+ end
+ end
+
+ context 'when the loose_foreign_key_cleanup feature flag is off' do
+ before do
+ stub_feature_flags(loose_foreign_key_cleanup: false)
+ end
+
+ it 'does nothing' do
+ expect { described_class.new.perform }.not_to change { LooseForeignKeys::DeletedRecord.status_processed.count }
+ end
+ end
+end
diff --git a/spec/workers/namespaces/invite_team_email_worker_spec.rb b/spec/workers/namespaces/invite_team_email_worker_spec.rb
new file mode 100644
index 00000000000..47fdff9a8ef
--- /dev/null
+++ b/spec/workers/namespaces/invite_team_email_worker_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Namespaces::InviteTeamEmailWorker do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ it 'sends the email' do
+ expect(Namespaces::InviteTeamEmailService).to receive(:send_email).with(user, group).once
+ subject.perform(group.id, user.id)
+ end
+
+ context 'when user id is non-existent' do
+ it 'does not send the email' do
+ expect(Namespaces::InviteTeamEmailService).not_to receive(:send_email)
+ subject.perform(group.id, non_existing_record_id)
+ end
+ end
+
+ context 'when group id is non-existent' do
+ it 'does not send the email' do
+ expect(Namespaces::InviteTeamEmailService).not_to receive(:send_email)
+ subject.perform(non_existing_record_id, user.id)
+ end
+ end
+end
diff --git a/spec/workers/packages/maven/metadata/sync_worker_spec.rb b/spec/workers/packages/maven/metadata/sync_worker_spec.rb
index 10482b3e327..4b3cc6f964b 100644
--- a/spec/workers/packages/maven/metadata/sync_worker_spec.rb
+++ b/spec/workers/packages/maven/metadata/sync_worker_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Packages::Maven::Metadata::SyncWorker, type: :worker do
let(:versions) { %w[1.2 1.1 2.1 3.0-SNAPSHOT] }
let(:worker) { described_class.new }
+ let(:data_struct) { Struct.new(:release, :latest, :versions, keyword_init: true) }
describe '#perform' do
let(:user) { create(:user) }
@@ -197,7 +198,7 @@ RSpec.describe Packages::Maven::Metadata::SyncWorker, type: :worker do
def versions_from(xml_content)
xml_doc = Nokogiri::XML(xml_content)
- OpenStruct.new(
+ data_struct.new(
release: xml_doc.xpath('//metadata/versioning/release').first.content,
latest: xml_doc.xpath('//metadata/versioning/latest').first.content,
versions: xml_doc.xpath('//metadata/versioning/versions/version').map(&:content)
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index 039f86f1911..42e39c51a88 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -91,14 +91,6 @@ RSpec.describe PostReceive do
perform
end
-
- it 'tracks an event for the empty_repo_upload experiment', :experiment do
- expect_next_instance_of(EmptyRepoUploadExperiment) do |e|
- expect(e).to receive(:track_initial_write)
- end
-
- perform
- end
end
shared_examples 'not updating remote mirrors' do
diff --git a/spec/workers/propagate_integration_group_worker_spec.rb b/spec/workers/propagate_integration_group_worker_spec.rb
index 9d46534df4f..60442438a1d 100644
--- a/spec/workers/propagate_integration_group_worker_spec.rb
+++ b/spec/workers/propagate_integration_group_worker_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe PropagateIntegrationGroupWorker do
end
context 'with a group integration' do
- let_it_be(:integration) { create(:redmine_integration, group: group, project: nil) }
+ let_it_be(:integration) { create(:redmine_integration, :group, group: group) }
it 'calls to BulkCreateIntegrationService' do
expect(BulkCreateIntegrationService).to receive(:new)
diff --git a/spec/workers/propagate_integration_inherit_descendant_worker_spec.rb b/spec/workers/propagate_integration_inherit_descendant_worker_spec.rb
index 8a231d4104c..c9a7bfaa8b6 100644
--- a/spec/workers/propagate_integration_inherit_descendant_worker_spec.rb
+++ b/spec/workers/propagate_integration_inherit_descendant_worker_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe PropagateIntegrationInheritDescendantWorker do
let_it_be(:group) { create(:group) }
let_it_be(:subgroup) { create(:group, parent: group) }
- let_it_be(:group_integration) { create(:redmine_integration, group: group, project: nil) }
- let_it_be(:subgroup_integration) { create(:redmine_integration, group: subgroup, project: nil, inherit_from_id: group_integration.id) }
+ let_it_be(:group_integration) { create(:redmine_integration, :group, group: group) }
+ let_it_be(:subgroup_integration) { create(:redmine_integration, :group, group: subgroup, inherit_from_id: group_integration.id) }
it_behaves_like 'an idempotent worker' do
let(:job_args) { [group_integration.id, subgroup_integration.id, subgroup_integration.id] }
diff --git a/spec/workers/propagate_integration_project_worker_spec.rb b/spec/workers/propagate_integration_project_worker_spec.rb
index 312631252cc..c7adf1b826f 100644
--- a/spec/workers/propagate_integration_project_worker_spec.rb
+++ b/spec/workers/propagate_integration_project_worker_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe PropagateIntegrationProjectWorker do
end
context 'with a group integration' do
- let_it_be(:integration) { create(:redmine_integration, group: group, project: nil) }
+ let_it_be(:integration) { create(:redmine_integration, :group, group: group) }
it 'calls to BulkCreateIntegrationService' do
expect(BulkCreateIntegrationService).to receive(:new)
diff --git a/spec/workers/ssh_keys/expired_notification_worker_spec.rb b/spec/workers/ssh_keys/expired_notification_worker_spec.rb
index 109d24f03ab..be38391ff8c 100644
--- a/spec/workers/ssh_keys/expired_notification_worker_spec.rb
+++ b/spec/workers/ssh_keys/expired_notification_worker_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe SshKeys::ExpiredNotificationWorker, type: :worker do
stub_const("SshKeys::ExpiredNotificationWorker::BATCH_SIZE", 5)
end
- let_it_be_with_reload(:keys) { create_list(:key, 20, expires_at: 3.days.ago, user: user) }
+ let_it_be_with_reload(:keys) { create_list(:key, 20, expires_at: Time.current, user: user) }
it 'updates all keys regardless of batch size' do
worker.perform
@@ -54,8 +54,8 @@ RSpec.describe SshKeys::ExpiredNotificationWorker, type: :worker do
context 'when key has expired in the past' do
let_it_be(:expired_past) { create(:key, expires_at: 1.day.ago, user: user) }
- it 'does update notified column' do
- expect { worker.perform }.to change { expired_past.reload.expiry_notification_delivered_at }
+ it 'does not update notified column' do
+ expect { worker.perform }.not_to change { expired_past.reload.expiry_notification_delivered_at }
end
context 'when key has already been notified of expiration' do
diff --git a/spec/workers/tasks_to_be_done/create_worker_spec.rb b/spec/workers/tasks_to_be_done/create_worker_spec.rb
new file mode 100644
index 00000000000..a158872273f
--- /dev/null
+++ b/spec/workers/tasks_to_be_done/create_worker_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe TasksToBeDone::CreateWorker do
+ let_it_be(:member_task) { create(:member_task, tasks: MemberTask::TASKS.values) }
+ let_it_be(:current_user) { create(:user) }
+
+ let(:assignee_ids) { [1, 2] }
+ let(:job_args) { [member_task.id, current_user.id, assignee_ids] }
+
+ before do
+ member_task.project.group.add_owner(current_user)
+ end
+
+ describe '.perform' do
+ it 'executes the task services for all tasks to be done', :aggregate_failures do
+ MemberTask::TASKS.each_key do |task|
+ service_class = "TasksToBeDone::Create#{task.to_s.camelize}TaskService".constantize
+
+ expect(service_class)
+ .to receive(:new)
+ .with(project: member_task.project, current_user: current_user, assignee_ids: assignee_ids)
+ .and_call_original
+ end
+
+ expect { described_class.new.perform(*job_args) }.to change(Issue, :count).by(3)
+ end
+ end
+
+ include_examples 'an idempotent worker' do
+ it 'creates 3 task issues' do
+ expect { subject }.to change(Issue, :count).by(3)
+ end
+ end
+end
diff --git a/spec/workers/users/deactivate_dormant_users_worker_spec.rb b/spec/workers/users/deactivate_dormant_users_worker_spec.rb
index 934c497c79a..20cd55e19eb 100644
--- a/spec/workers/users/deactivate_dormant_users_worker_spec.rb
+++ b/spec/workers/users/deactivate_dormant_users_worker_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Users::DeactivateDormantUsersWorker do
+ using RSpec::Parameterized::TableSyntax
+
describe '#perform' do
let_it_be(:dormant) { create(:user, last_activity_on: User::MINIMUM_INACTIVE_DAYS.days.ago.to_date) }
let_it_be(:inactive) { create(:user, last_activity_on: nil) }
@@ -22,12 +24,12 @@ RSpec.describe Users::DeactivateDormantUsersWorker do
context 'when automatic deactivation of dormant users is enabled' do
before do
stub_application_setting(deactivate_dormant_users: true)
+ stub_const("#{described_class.name}::PAUSE_SECONDS", 0)
end
it 'deactivates dormant users' do
freeze_time do
stub_const("#{described_class.name}::BATCH_SIZE", 1)
- stub_const("#{described_class.name}::PAUSE_SECONDS", 0)
expect(worker).to receive(:sleep).twice
@@ -37,6 +39,38 @@ RSpec.describe Users::DeactivateDormantUsersWorker do
expect(User.with_no_activity.count).to eq(0)
end
end
+
+ where(:user_type, :expected_state) do
+ :human | 'deactivated'
+ :support_bot | 'active'
+ :alert_bot | 'active'
+ :visual_review_bot | 'active'
+ :service_user | 'deactivated'
+ :ghost | 'active'
+ :project_bot | 'active'
+ :migration_bot | 'active'
+ :security_bot | 'active'
+ :automation_bot | 'active'
+ end
+ with_them do
+ it 'deactivates certain user types' do
+ user = create(:user, user_type: user_type, state: :active, last_activity_on: User::MINIMUM_INACTIVE_DAYS.days.ago.to_date)
+
+ worker.perform
+
+ expect(user.reload.state).to eq(expected_state)
+ end
+ end
+
+ it 'does not deactivate non-active users' do
+ human_user = create(:user, user_type: :human, state: :blocked, last_activity_on: User::MINIMUM_INACTIVE_DAYS.days.ago.to_date)
+ service_user = create(:user, user_type: :service_user, state: :blocked, last_activity_on: User::MINIMUM_INACTIVE_DAYS.days.ago.to_date)
+
+ worker.perform
+
+ expect(human_user.reload.state).to eq('blocked')
+ expect(service_user.reload.state).to eq('blocked')
+ end
end
context 'when automatic deactivation of dormant users is disabled' do
diff --git a/tooling/bin/find_change_diffs b/tooling/bin/find_change_diffs
new file mode 100755
index 00000000000..7857945ea74
--- /dev/null
+++ b/tooling/bin/find_change_diffs
@@ -0,0 +1,38 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'gitlab'
+require 'pathname'
+
+# This script saves the diffs of changes in an MR to the directory specified as the first argument
+#
+# It exits with a success code if diffs are found and saved, or if there are no changes, including if the script runs in
+# a pipeline that is not for a merge request.
+
+gitlab_token = ENV.fetch('PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE')
+gitlab_endpoint = ENV.fetch('CI_API_V4_URL')
+mr_project_path = ENV['CI_MERGE_REQUEST_PROJECT_PATH']
+mr_iid = ENV['CI_MERGE_REQUEST_IID']
+
+puts "CI_MERGE_REQUEST_PROJECT_PATH is missing." if mr_project_path.to_s.empty?
+puts "CI_MERGE_REQUEST_IID is missing." if mr_iid.to_s.empty?
+
+unless mr_project_path && mr_iid
+ puts "Exiting as this does not appear to be a merge request pipeline."
+ exit
+end
+
+abort("ERROR: Please specify a directory to write MR diffs into.") if ARGV.empty?
+output_diffs_dir = Pathname.new(ARGV.shift).expand_path
+
+Gitlab.configure do |config|
+ config.endpoint = gitlab_endpoint
+ config.private_token = gitlab_token
+end
+
+Gitlab.merge_request_changes(mr_project_path, mr_iid).changes.each do |change|
+ next if change['diff'].empty?
+
+ output_diffs_dir.join(File.dirname(change['new_path'])).mkpath
+ output_diffs_dir.join("#{change['new_path']}.diff").write(change['diff'])
+end
diff --git a/tooling/bin/find_changes b/tooling/bin/find_changes
index 466510ccb19..20df085879a 100755
--- a/tooling/bin/find_changes
+++ b/tooling/bin/find_changes
@@ -3,7 +3,7 @@
require 'gitlab'
-gitlab_token = ENV.fetch('DANGER_GITLAB_API_TOKEN', '')
+gitlab_token = ENV.fetch('PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE', '')
gitlab_endpoint = ENV.fetch('CI_API_V4_URL')
mr_project_path = ENV.fetch('CI_MERGE_REQUEST_PROJECT_PATH')
mr_iid = ENV.fetch('CI_MERGE_REQUEST_IID')
diff --git a/tooling/bin/qa/package_and_qa_check b/tooling/bin/qa/package_and_qa_check
new file mode 100755
index 00000000000..21deb0fcd2d
--- /dev/null
+++ b/tooling/bin/qa/package_and_qa_check
@@ -0,0 +1,45 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'pathname'
+
+# This script checks if the package-and-qa job should trigger downstream pipelines to run the QA suite.
+#
+# It assumes the first argument is a directory of files containing diffs of changes from an MR
+# (e.g., created by tooling/bin/find_change_diffs). It exits with a success code if there are no diffs, or if the diffs
+# are suitable to run QA tests.
+#
+# The script will abort (exit code 1) if the argument is missing.
+#
+# The following condition will result in a failure code (2), indicating that package-and-qa should not run:
+#
+# - If the changes only include tests being put in quarantine
+
+abort("ERROR: Please specify the directory containing MR diffs.") if ARGV.empty?
+diffs_dir = Pathname.new(ARGV.shift).expand_path
+
+# Run package-and-qa if there are no diffs. E.g., in scheduled pipelines
+exit 0 if diffs_dir.glob('**/*').empty?
+
+files_count = 0
+specs_count = 0
+quarantine_specs_count = 0
+
+diffs_dir.glob('**/*').each do |path|
+ next if path.directory?
+
+ files_count += 1
+ next unless path.to_s.end_with?('_spec.rb.diff')
+
+ specs_count += 1
+ quarantine_specs_count += 1 if path.read.match?(/^\+.*, quarantine:/)
+end
+
+# Run package-and-qa if there are no specs. E.g., when the MR changes QA framework files.
+exit 0 if specs_count == 0
+
+# Skip package-and-qa if there are only specs being put in quarantine.
+exit 2 if quarantine_specs_count == specs_count && quarantine_specs_count == files_count
+
+# Run package-and-qa under any other circumstances. E.g., if there are specs being put in quarantine but there are also
+# other changes that might need to be tested.
diff --git a/tooling/danger/changelog.rb b/tooling/danger/changelog.rb
index c053d366199..fbf8ae931e2 100644
--- a/tooling/danger/changelog.rb
+++ b/tooling/danger/changelog.rb
@@ -6,7 +6,7 @@ module Tooling
module Danger
module Changelog
NO_CHANGELOG_LABELS = [
- 'tooling',
+ 'type::tooling',
'tooling::pipelines',
'tooling::workflow',
'ci-build',
diff --git a/tooling/danger/product_intelligence.rb b/tooling/danger/product_intelligence.rb
index 848f99eeff5..72fc8deac43 100644
--- a/tooling/danger/product_intelligence.rb
+++ b/tooling/danger/product_intelligence.rb
@@ -9,71 +9,20 @@ module Tooling
'product intelligence::review pending'
].freeze
- TRACKING_FILES = [
- 'lib/gitlab/tracking.rb',
- 'spec/lib/gitlab/tracking_spec.rb',
- 'app/helpers/tracking_helper.rb',
- 'spec/helpers/tracking_helper_spec.rb',
- 'app/assets/javascripts/tracking/index.js',
- 'app/assets/javascripts/tracking/constants.js',
- 'app/assets/javascripts/tracking/get_standard_context.js',
- 'spec/frontend/tracking/get_standard_context_spec.js',
- 'spec/frontend/tracking_spec.js',
- 'generator_templates/usage_metric_definition/metric_definition.yml',
- 'lib/generators/gitlab/usage_metric/usage_metric_generator.rb',
- 'lib/generators/gitlab/usage_metric_definition_generator.rb',
- 'lib/generators/gitlab/usage_metric_definition/redis_hll_generator.rb',
- 'spec/lib/generators/gitlab/usage_metric_generator_spec.rb',
- 'spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb',
- 'spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb',
- 'config/metrics/schema.json'
- ].freeze
-
def missing_labels
return [] if !helper.ci? || helper.mr_has_labels?('growth experiment')
labels = []
labels << 'product intelligence' unless helper.mr_has_labels?('product intelligence')
- labels << 'product intelligence::review pending' unless helper.mr_has_labels?(WORKFLOW_LABELS)
+ labels << 'product intelligence::review pending' unless has_workflow_labels?
labels
end
- def matching_changed_files
- tracking_changed_files = all_changed_files & TRACKING_FILES
- usage_data_changed_files = all_changed_files.grep(%r{(usage_data)})
-
- usage_data_changed_files + tracking_changed_files + metrics_changed_files + snowplow_changed_files
- end
-
private
- def all_changed_files
- helper.all_changed_files
- end
-
- def metrics_changed_files
- all_changed_files.grep(%r{((ee/)?config/metrics/.*\.yml)})
- end
-
- def matching_files?(file, extension:, pattern:)
- return unless file.end_with?(extension)
-
- helper.changed_lines(file).grep(pattern).any?
- end
-
- def snowplow_changed_files
- js_patterns = Regexp.union(
- 'Tracking.event',
- /\btrack\(/,
- 'data-track-action'
- )
- all_changed_files.select do |file|
- matching_files?(file, extension: '.rb', pattern: %r{Gitlab::Tracking\.(event|enabled\?|options)$}) ||
- matching_files?(file, extension: '.js', pattern: js_patterns) ||
- matching_files?(file, extension: '.vue', pattern: js_patterns) ||
- matching_files?(file, extension: '.haml', pattern: %r{data: \{ track})
- end
+ def has_workflow_labels?
+ (WORKFLOW_LABELS & helper.mr_labels).any?
end
end
end
diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb
index c552a75bba8..5d338393f90 100644
--- a/tooling/danger/project_helper.rb
+++ b/tooling/danger/project_helper.rb
@@ -22,12 +22,12 @@ module Tooling
ce_ee_vue_templates
ci_templates
datateam
- metadata
feature_flag
roulette
sidekiq_queues
specialization_labels
specs
+ z_metadata
].freeze
MESSAGE_PREFIX = '==>'
@@ -38,10 +38,34 @@ module Tooling
%r{\A((ee|jh)/)?config/feature_flags/} => :feature_flag,
+ %r{doc/api/usage_data.md} => [:product_intelligence],
+
%r{\Adoc/.*(\.(md|png|gif|jpg|yml))\z} => :docs,
%r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :docs,
%r{\Adata/whats_new/} => :docs,
+ %r{\A((ee|jh)/)?app/finders/(.+/)?integrations/} => [:integrations_be, :database, :backend],
+ [%r{\A((ee|jh)/)?db/(geo/)?(migrate|post_migrate)/}, %r{(:integrations|:\w+_tracker_data)\b}] => [:integrations_be, :database, :migration],
+ [%r{\A((ee|jh)/)?(app|lib)/.+\.rb}, %r{\b(Integrations::|\.execute_(integrations|hooks))\b}] => [:integrations_be, :backend],
+ %r{\A(
+ ((ee|jh)/)?app/((?!.*clusters)(?!.*alert_management)(?!.*views)(?!.*assets).+/)?integration.+ |
+ ((ee|jh)/)?app/((?!.*search).+/)?project_service.+ |
+ ((ee|jh)/)?app/(models|helpers|workers|services|controllers)/(.+/)?(jira_connect.+|.*hook.+) |
+ ((ee|jh)/)?app/controllers/(.+/)?oauth/jira/.+ |
+ ((ee|jh)/)?app/services/(.+/)?jira.+ |
+ ((ee|jh)/)?app/workers/(.+/)?(propagate_integration.+|irker_worker\.rb) |
+ ((ee|jh)/)?lib/(.+/)?(atlassian|data_builder|hook_data)/.+ |
+ ((ee|jh)/)?lib/(.+/)?.*integration.+ |
+ ((ee|jh)/)?lib/(.+/)?api/v3/github\.rb |
+ ((ee|jh)/)?lib/(.+/)?api/github/entities\.rb
+ )\z}x => [:integrations_be, :backend],
+
+ %r{\A(
+ ((ee|jh)/)?app/(views|assets)/((?!.*clusters)(?!.*alerts_settings).+/)?integration.+ |
+ ((ee|jh)/)?app/(views|assets)/(.+/)?jira_connect.+ |
+ ((ee|jh)/)?app/(views|assets)/((?!.*filtered_search).+/)?hooks?.+
+ )\z}x => [:integrations_fe, :frontend],
+
%r{\A(
app/assets/javascripts/tracking/.*\.js |
spec/frontend/tracking/.*\.js |
@@ -82,6 +106,7 @@ module Tooling
%r{\A((ee|jh)/)?app/finders/} => [:database, :backend],
%r{\Arubocop/cop/migration(/|\.rb)} => :database,
+ %r{\A(\.ruby-version\z|\.nvmrc\z|\.tool-versions\z)} => :tooling,
%r{\A(\.gitlab-ci\.yml\z|\.gitlab\/ci)} => :tooling,
%r{\A\.codeclimate\.yml\z} => :tooling,
%r{\Alefthook.yml\z} => :tooling,
@@ -100,6 +125,7 @@ module Tooling
%r{\A((ee|jh)/)?spec/support/shared_contexts/features/} => :test,
%r{\A((ee|jh)/)?spec/support/helpers/features/} => :test,
+ %r{\A((spec/)?lib/generators/gitlab/usage_metric_)} => [:product_intelligence],
%r{\A((ee|jh)/)?lib/gitlab/usage_data_counters/.*\.yml\z} => [:product_intelligence],
%r{\A((ee|jh)/)?config/metrics/((.*\.yml)|(schema\.json))\z} => [:product_intelligence],
%r{\A((ee|jh)/)?lib/gitlab/usage_data(_counters)?(/|\.rb)} => [:backend, :product_intelligence],
@@ -108,9 +134,16 @@ module Tooling
spec/lib/gitlab/tracking_spec\.rb |
app/helpers/tracking_helper\.rb |
spec/helpers/tracking_helper_spec\.rb |
+ (spec/)?lib/generators/gitlab/usage_metric_\S+ |
+ (spec/)?lib/generators/gitlab/usage_metric_definition/redis_hll_generator(_spec)?\.rb |
lib/generators/rails/usage_metric_definition_generator\.rb |
spec/lib/generators/usage_metric_definition_generator_spec\.rb |
generator_templates/usage_metric_definition/metric_definition\.yml)\z}x => [:backend, :product_intelligence],
+ %r{gitlab/usage_data(_spec)?\.rb} => [:product_intelligence],
+ [%r{\.haml\z}, %r{data: \{ track}] => [:product_intelligence],
+ [%r{\.(rb|haml)\z}, %r{Gitlab::Tracking\.(event|enabled\?|options)$}] => [:product_intelligence],
+ [%r{\.(vue|js)\z}, %r{(Tracking.event|/\btrack\(/|data-track-action)}] => [:product_intelligence],
+
%r{\A((ee|jh)/)?app/(?!assets|views)[^/]+} => :backend,
%r{\A((ee|jh)/)?(bin|config|generator_templates|lib|rubocop)/} => :backend,
%r{\A((ee|jh)/)?spec/migrations} => :database,
@@ -179,6 +212,10 @@ module Tooling
read_file(filename).lines(chomp: true)
end
+ def labels_to_add
+ @labels_to_add ||= []
+ end
+
private
def read_file(filename)
@@ -187,7 +224,7 @@ module Tooling
def ee?
# Support former project name for `dev` and support local Danger run
- %w[gitlab gitlab-ee].include?(ENV['CI_PROJECT_NAME']) || Dir.exist?(File.expand_path('../../../ee', __dir__))
+ %w[gitlab gitlab-ee].include?(ENV['CI_PROJECT_NAME']) || Dir.exist?(File.expand_path('../../ee', __dir__))
end
end
end
diff --git a/tooling/deprecations/docs.rb b/tooling/deprecations/docs.rb
index 67ff7a932b4..0f649024b60 100644
--- a/tooling/deprecations/docs.rb
+++ b/tooling/deprecations/docs.rb
@@ -20,9 +20,11 @@ module Deprecations
YAML.load_file(file)
end
- deprecations = VersionSorter.sort(deprecations) { |d| d["removal_milestone"] }
+ deps = VersionSorter.sort(deprecations) { |d| d["removal_milestone"] }
- milestones = deprecations.map { |d| d["removal_milestone"] }.uniq
+ deprecations = deps.sort_by { |d| d["name"] }
+
+ milestones = deps.map { |d| d["removal_milestone"] }.uniq
template = Rails.root.join("data/deprecations/templates/_deprecation_template.md.erb")
diff --git a/tooling/lib/tooling/images.rb b/tooling/lib/tooling/image.rb
index d0c464b983c..d0c464b983c 100644
--- a/tooling/lib/tooling/images.rb
+++ b/tooling/lib/tooling/image.rb
diff --git a/tooling/quality/test_level.rb b/tooling/quality/test_level.rb
index 83cbe7a1f19..5fbaad073c0 100644
--- a/tooling/quality/test_level.rb
+++ b/tooling/quality/test_level.rb
@@ -40,6 +40,7 @@ module Quality
replicators
routing
rubocop
+ scripts
serializers
services
sidekiq
@@ -53,6 +54,7 @@ module Quality
tooling
],
integration: %w[
+ commands
controllers
mailers
requests
diff --git a/tooling/rspec_flaky/report.rb b/tooling/rspec_flaky/report.rb
index 3acfe7d2125..bde5115f03c 100644
--- a/tooling/rspec_flaky/report.rb
+++ b/tooling/rspec_flaky/report.rb
@@ -10,7 +10,7 @@ module RspecFlaky
# This class is responsible for loading/saving JSON reports, and pruning
# outdated examples.
class Report < SimpleDelegator
- OUTDATED_DAYS_THRESHOLD = 7
+ OUTDATED_DAYS_THRESHOLD = 30
attr_reader :flaky_examples
diff --git a/vendor/project_templates/cluster_management.tar.gz b/vendor/project_templates/cluster_management.tar.gz
index 015b943dba7..7b12044e414 100644
--- a/vendor/project_templates/cluster_management.tar.gz
+++ b/vendor/project_templates/cluster_management.tar.gz
Binary files differ
diff --git a/vendor/project_templates/learn_gitlab_ultimate_trial.tar.gz b/vendor/project_templates/learn_gitlab_ultimate.tar.gz
index b8d14bbad93..b8d14bbad93 100644
--- a/vendor/project_templates/learn_gitlab_ultimate_trial.tar.gz
+++ b/vendor/project_templates/learn_gitlab_ultimate.tar.gz
Binary files differ
diff --git a/vendor/project_templates/tencent_serverless_framework.tar.gz b/vendor/project_templates/tencent_serverless_framework.tar.gz
new file mode 100644
index 00000000000..543a026a775
--- /dev/null
+++ b/vendor/project_templates/tencent_serverless_framework.tar.gz
Binary files differ
diff --git a/workhorse/.tool-versions b/workhorse/.tool-versions
new file mode 100644
index 00000000000..9d3b3b30ff2
--- /dev/null
+++ b/workhorse/.tool-versions
@@ -0,0 +1 @@
+golang 1.16.9
diff --git a/workhorse/Makefile b/workhorse/Makefile
index 0e8c47ae35c..3cf592b0cff 100644
--- a/workhorse/Makefile
+++ b/workhorse/Makefile
@@ -13,6 +13,8 @@ else
BUILD_TIME := $(shell date -u "$(DATE_FMT)")
endif
GOBUILD := go build -ldflags "-X main.Version=$(VERSION_STRING) -X main.BuildTime=$(BUILD_TIME)"
+GITALY := tmp/tests/gitaly/_build/bin/gitaly
+GITALY_PID_FILE := gitaly.pid
EXE_ALL := gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata gitlab-workhorse
INSTALL := install
BUILD_TAGS := tracer_static tracer_static_jaeger continuous_profiler_stackdriver
@@ -63,7 +65,16 @@ install: $(EXE_ALL)
.PHONY: test
test: prepare-tests
$(call message,$@)
- @go test -tags "$(BUILD_TAGS)" ./...
+ go test -tags "$(BUILD_TAGS)" ./... ;\
+ status="$$?" ;\
+ if [ -f "$(GITALY_PID_FILE)" ] ; then \
+ echo "Clean up Gitaly server for workhorse integration test" ;\
+ kill -9 $$(cat $(GITALY_PID_FILE)) ;\
+ rm $(GITALY_PID_FILE) ;\
+ else \
+ echo "Gitaly integration test not running" ;\
+ fi ;\
+ exit "$$status"
@echo SUCCESS
.PHONY: clean
@@ -82,9 +93,27 @@ clean-build:
rm -rf $(TARGET_DIR)
.PHONY: prepare-tests
+prepare-tests: run-gitaly
prepare-tests: testdata/data/group/test.git $(EXE_ALL)
prepare-tests: testdata/scratch
+.PHONY: run-gitaly
+run-gitaly: gitaly.pid
+
+$(GITALY_PID_FILE): gitaly.toml
+ @{ \
+ if [ -z "$${GITALY_ADDRESS+x}" ] ; then \
+ echo "To run gitaly integration tests set GITALY_ADDRESS=tcp://127.0.0.1:8075" ; \
+ else \
+ cd .. ; \
+ GITALY_TESTING_NO_GIT_HOOKS=1 GITALY_PID_FILE=workhorse/$(GITALY_PID_FILE) $(GITALY) workhorse/gitaly.toml ; \
+ fi \
+ } &
+
+gitaly.toml: ../tmp/tests/gitaly/config.toml
+ sed -e 's/^socket_path.*$$/listen_addr = "0.0.0.0:8075"/;s/^\[auth\]$$//;s/^token.*$$//;s/^internal_socket_dir.*$$//' \
+ $< > $@
+
testdata/data/group/test.git:
$(call message,$@)
git clone --quiet --bare https://gitlab.com/gitlab-org/gitlab-test.git $@
diff --git a/workhorse/gitaly_integration_test.go b/workhorse/gitaly_integration_test.go
index 48de45d7935..95e0a03ab6b 100644
--- a/workhorse/gitaly_integration_test.go
+++ b/workhorse/gitaly_integration_test.go
@@ -16,6 +16,7 @@ import (
"strings"
"testing"
+ "github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
@@ -53,6 +54,10 @@ func realGitalyOkBody(t *testing.T) *api.Response {
return realGitalyAuthResponse(gitOkBody(t))
}
+func realGitalyOkBodyWithSidechannel(t *testing.T) *api.Response {
+ return realGitalyAuthResponse(gitOkBodyWithSidechannel(t))
+}
+
func ensureGitalyRepository(t *testing.T, apiResponse *api.Response) error {
ctx, namespace, err := gitaly.NewNamespaceClient(context.Background(), apiResponse.GitalyServer)
if err != nil {
@@ -83,10 +88,18 @@ func ensureGitalyRepository(t *testing.T, apiResponse *api.Response) error {
}
func TestAllowedClone(t *testing.T) {
+ testAllowedClone(t, realGitalyOkBody(t))
+}
+
+func TestAllowedCloneWithSidechannel(t *testing.T) {
+ gitaly.InitializeSidechannelRegistry(logrus.StandardLogger())
+ testAllowedClone(t, realGitalyOkBodyWithSidechannel(t))
+}
+
+func testAllowedClone(t *testing.T, apiResponse *api.Response) {
skipUnlessRealGitaly(t)
// Create the repository in the Gitaly server
- apiResponse := realGitalyOkBody(t)
require.NoError(t, ensureGitalyRepository(t, apiResponse))
// Prepare test server and backend
@@ -107,10 +120,18 @@ func TestAllowedClone(t *testing.T) {
}
func TestAllowedShallowClone(t *testing.T) {
+ testAllowedShallowClone(t, realGitalyOkBody(t))
+}
+
+func TestAllowedShallowCloneWithSidechannel(t *testing.T) {
+ gitaly.InitializeSidechannelRegistry(logrus.StandardLogger())
+ testAllowedShallowClone(t, realGitalyOkBodyWithSidechannel(t))
+}
+
+func testAllowedShallowClone(t *testing.T, apiResponse *api.Response) {
skipUnlessRealGitaly(t)
// Create the repository in the Gitaly server
- apiResponse := realGitalyOkBody(t)
require.NoError(t, ensureGitalyRepository(t, apiResponse))
// Prepare test server and backend
diff --git a/workhorse/internal/dependencyproxy/dependencyproxy.go b/workhorse/internal/dependencyproxy/dependencyproxy.go
index cfb3045544f..90f3042a342 100644
--- a/workhorse/internal/dependencyproxy/dependencyproxy.go
+++ b/workhorse/internal/dependencyproxy/dependencyproxy.go
@@ -4,37 +4,17 @@ import (
"context"
"fmt"
"io"
- "net"
"net/http"
- "time"
- "gitlab.com/gitlab-org/labkit/correlation"
"gitlab.com/gitlab-org/labkit/log"
- "gitlab.com/gitlab-org/labkit/tracing"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/senddata"
)
-// httpTransport defines a http.Transport with values
-// that are more restrictive than for http.DefaultTransport,
-// they define shorter TLS Handshake, and more aggressive connection closing
-// to prevent the connection hanging and reduce FD usage
-var httpTransport = tracing.NewRoundTripper(correlation.NewInstrumentedRoundTripper(&http.Transport{
- Proxy: http.ProxyFromEnvironment,
- DialContext: (&net.Dialer{
- Timeout: 30 * time.Second,
- KeepAlive: 10 * time.Second,
- }).DialContext,
- MaxIdleConns: 2,
- IdleConnTimeout: 30 * time.Second,
- TLSHandshakeTimeout: 10 * time.Second,
- ExpectContinueTimeout: 10 * time.Second,
- ResponseHeaderTimeout: 30 * time.Second,
-}))
-
var httpClient = &http.Client{
- Transport: httpTransport,
+ Transport: httptransport.New(),
}
type Injector struct {
@@ -87,15 +67,28 @@ func (p *Injector) Inject(w http.ResponseWriter, r *http.Request, sendData strin
return
}
+ w.Header().Set("Content-Length", dependencyResponse.Header.Get("Content-Length"))
+
teeReader := io.TeeReader(dependencyResponse.Body, w)
saveFileRequest, err := http.NewRequestWithContext(r.Context(), "POST", r.URL.String()+"/upload", teeReader)
if err != nil {
helper.Fail500(w, r, fmt.Errorf("dependency proxy: failed to create request: %w", err))
}
saveFileRequest.Header = helper.HeaderClone(r.Header)
- saveFileRequest.ContentLength = dependencyResponse.ContentLength
- w.Header().Del("Content-Length")
+ // forward headers from dependencyResponse to rails and client
+ for key, values := range dependencyResponse.Header {
+ saveFileRequest.Header.Del(key)
+ w.Header().Del(key)
+ for _, value := range values {
+ saveFileRequest.Header.Add(key, value)
+ w.Header().Add(key, value)
+ }
+ }
+
+ // workhorse hijack overwrites the Content-Type header, but we need this header value
+ saveFileRequest.Header.Set("Workhorse-Proxy-Content-Type", dependencyResponse.Header.Get("Content-Type"))
+ saveFileRequest.ContentLength = dependencyResponse.ContentLength
nrw := &nullResponseWriter{header: make(http.Header)}
p.uploadHandler.ServeHTTP(nrw, saveFileRequest)
diff --git a/workhorse/internal/dependencyproxy/dependencyproxy_test.go b/workhorse/internal/dependencyproxy/dependencyproxy_test.go
index 37e54c0b756..d9169b2b4ce 100644
--- a/workhorse/internal/dependencyproxy/dependencyproxy_test.go
+++ b/workhorse/internal/dependencyproxy/dependencyproxy_test.go
@@ -33,7 +33,7 @@ func (f *fakeUploadHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
type errWriter struct{ writes int }
-func (w *errWriter) Header() http.Header { return nil }
+func (w *errWriter) Header() http.Header { return make(http.Header) }
func (w *errWriter) WriteHeader(h int) {}
// First call of Write function succeeds while all the subsequent ones fail
@@ -112,8 +112,15 @@ func TestInject(t *testing.T) {
func TestSuccessfullRequest(t *testing.T) {
content := []byte("result")
+ contentLength := strconv.Itoa(len(content))
+ contentType := "foo"
+ dockerContentDigest := "sha256:asdf1234"
+ overriddenHeader := "originResourceServer"
originResourceServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Length", strconv.Itoa(len(content)))
+ w.Header().Set("Content-Length", contentLength)
+ w.Header().Set("Content-Type", contentType)
+ w.Header().Set("Docker-Content-Digest", dockerContentDigest)
+ w.Header().Set("Overridden-Header", overriddenHeader)
w.Write(content)
}))
@@ -130,11 +137,16 @@ func TestSuccessfullRequest(t *testing.T) {
require.Equal(t, "/target/upload", uploadHandler.request.URL.Path)
require.Equal(t, int64(6), uploadHandler.request.ContentLength)
+ require.Equal(t, contentType, uploadHandler.request.Header.Get("Workhorse-Proxy-Content-Type"))
+ require.Equal(t, dockerContentDigest, uploadHandler.request.Header.Get("Docker-Content-Digest"))
+ require.Equal(t, overriddenHeader, uploadHandler.request.Header.Get("Overridden-Header"))
require.Equal(t, content, uploadHandler.body)
require.Equal(t, 200, response.Code)
require.Equal(t, string(content), response.Body.String())
+ require.Equal(t, contentLength, response.Header().Get("Content-Length"))
+ require.Equal(t, dockerContentDigest, response.Header().Get("Docker-Content-Digest"))
}
func TestIncorrectSendData(t *testing.T) {
@@ -175,6 +187,7 @@ func TestFailedOriginServer(t *testing.T) {
func makeRequest(injector *Injector, data string) *httptest.ResponseRecorder {
w := httptest.NewRecorder()
r := httptest.NewRequest("GET", "/target", nil)
+ r.Header.Set("Overridden-Header", "request")
sendData := base64.StdEncoding.EncodeToString([]byte(data))
injector.Inject(w, r, sendData)
diff --git a/workhorse/internal/filestore/file_handler.go b/workhorse/internal/filestore/file_handler.go
index b4d7250fe0c..dac8d4d6247 100644
--- a/workhorse/internal/filestore/file_handler.go
+++ b/workhorse/internal/filestore/file_handler.go
@@ -43,6 +43,9 @@ type FileHandler struct {
// a map containing different hashes
hashes map[string]string
+
+ // Duration of upload in seconds
+ uploadDuration float64
}
type uploadClaims struct {
@@ -74,11 +77,12 @@ func (fh *FileHandler) GitLabFinalizeFields(prefix string) (map[string]string, e
}
for k, v := range map[string]string{
- "name": fh.Name,
- "path": fh.LocalPath,
- "remote_url": fh.RemoteURL,
- "remote_id": fh.RemoteID,
- "size": strconv.FormatInt(fh.Size, 10),
+ "name": fh.Name,
+ "path": fh.LocalPath,
+ "remote_url": fh.RemoteURL,
+ "remote_id": fh.RemoteID,
+ "size": strconv.FormatInt(fh.Size, 10),
+ "upload_duration": strconv.FormatFloat(fh.uploadDuration, 'f', -1, 64),
} {
data[key(k)] = v
signedData[k] = v
@@ -105,18 +109,20 @@ type consumer interface {
// SaveFileFromReader persists the provided reader content to all the location specified in opts. A cleanup will be performed once ctx is Done
// Make sure the provided context will not expire before finalizing upload with GitLab Rails.
-func SaveFileFromReader(ctx context.Context, reader io.Reader, size int64, opts *SaveFileOpts) (fh *FileHandler, err error) {
- var uploadDestination consumer
- fh = &FileHandler{
+func SaveFileFromReader(ctx context.Context, reader io.Reader, size int64, opts *SaveFileOpts) (*FileHandler, error) {
+ fh := &FileHandler{
Name: opts.TempFilePrefix,
RemoteID: opts.RemoteID,
RemoteURL: opts.RemoteURL,
}
+ uploadStartTime := time.Now()
+ defer func() { fh.uploadDuration = time.Since(uploadStartTime).Seconds() }()
hashes := newMultiHash()
reader = io.TeeReader(reader, hashes.Writer)
var clientMode string
-
+ var uploadDestination consumer
+ var err error
switch {
case opts.IsLocal():
clientMode = "local"
@@ -161,23 +167,19 @@ func SaveFileFromReader(ctx context.Context, reader io.Reader, size int64, opts
return nil, err
}
+ var hlr *hardLimitReader
if opts.MaximumSize > 0 {
if size > opts.MaximumSize {
return nil, SizeError(fmt.Errorf("the upload size %d is over maximum of %d bytes", size, opts.MaximumSize))
}
- hlr := &hardLimitReader{r: reader, n: opts.MaximumSize}
+ hlr = &hardLimitReader{r: reader, n: opts.MaximumSize}
reader = hlr
- defer func() {
- if hlr.n < 0 {
- err = ErrEntityTooLarge
- }
- }()
}
fh.Size, err = uploadDestination.Consume(ctx, reader, opts.Deadline)
if err != nil {
- if err == objectstore.ErrNotEnoughParts {
+ if (err == objectstore.ErrNotEnoughParts) || (hlr != nil && hlr.n < 0) {
err = ErrEntityTooLarge
}
return nil, err
diff --git a/workhorse/internal/filestore/file_handler_test.go b/workhorse/internal/filestore/file_handler_test.go
index 16af56dcf48..f57026a59df 100644
--- a/workhorse/internal/filestore/file_handler_test.go
+++ b/workhorse/internal/filestore/file_handler_test.go
@@ -548,4 +548,5 @@ func checkFileHandlerWithFields(t *testing.T, fh *filestore.FileHandler, fields
require.Equal(t, test.ObjectSHA1, fields[key("sha1")])
require.Equal(t, test.ObjectSHA256, fields[key("sha256")])
require.Equal(t, test.ObjectSHA512, fields[key("sha512")])
+ require.NotEmpty(t, fields[key("upload_duration")])
}
diff --git a/workhorse/internal/helper/httptransport/http_transport.go b/workhorse/internal/helper/httptransport/http_transport.go
new file mode 100644
index 00000000000..c7c3c5283f5
--- /dev/null
+++ b/workhorse/internal/helper/httptransport/http_transport.go
@@ -0,0 +1,37 @@
+package httptransport
+
+import (
+ "net/http"
+ "time"
+
+ "gitlab.com/gitlab-org/labkit/correlation"
+ "gitlab.com/gitlab-org/labkit/tracing"
+)
+
+type Option func(*http.Transport)
+
+// Defines a http.Transport with values
+// that are more restrictive than for http.DefaultTransport,
+// they define shorter TLS Handshake, and more aggressive connection closing
+// to prevent the connection hanging and reduce FD usage
+func New(options ...Option) http.RoundTripper {
+ t := http.DefaultTransport.(*http.Transport).Clone()
+
+ // To avoid keep around TCP connections to http servers we're done with
+ t.MaxIdleConns = 2
+
+ // A stricter timeout for fetching from external sources that can be slow
+ t.ResponseHeaderTimeout = 30 * time.Second
+
+ for _, option := range options {
+ option(t)
+ }
+
+ return tracing.NewRoundTripper(correlation.NewInstrumentedRoundTripper(t))
+}
+
+func WithDisabledCompression() Option {
+ return func(t *http.Transport) {
+ t.DisableCompression = true
+ }
+}
diff --git a/workhorse/internal/imageresizer/image_resizer.go b/workhorse/internal/imageresizer/image_resizer.go
index cd0fa946530..8c3271b6f11 100644
--- a/workhorse/internal/imageresizer/image_resizer.go
+++ b/workhorse/internal/imageresizer/image_resizer.go
@@ -5,7 +5,6 @@ import (
"context"
"fmt"
"io"
- "net"
"net/http"
"os"
"os/exec"
@@ -18,11 +17,11 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "gitlab.com/gitlab-org/labkit/correlation"
"gitlab.com/gitlab-org/labkit/tracing"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/config"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/log"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/senddata"
)
@@ -69,23 +68,8 @@ const (
var envInjector = tracing.NewEnvInjector()
-// Images might be located remotely in object storage, in which case we need to stream
-// it via http(s)
-var httpTransport = tracing.NewRoundTripper(correlation.NewInstrumentedRoundTripper(&http.Transport{
- Proxy: http.ProxyFromEnvironment,
- DialContext: (&net.Dialer{
- Timeout: 30 * time.Second,
- KeepAlive: 10 * time.Second,
- }).DialContext,
- MaxIdleConns: 2,
- IdleConnTimeout: 30 * time.Second,
- TLSHandshakeTimeout: 10 * time.Second,
- ExpectContinueTimeout: 10 * time.Second,
- ResponseHeaderTimeout: 30 * time.Second,
-}))
-
var httpClient = &http.Client{
- Transport: httpTransport,
+ Transport: httptransport.New(),
}
const (
diff --git a/workhorse/internal/objectstore/object.go b/workhorse/internal/objectstore/object.go
index eaf3bfb2e36..b7c4f12f009 100644
--- a/workhorse/internal/objectstore/object.go
+++ b/workhorse/internal/objectstore/object.go
@@ -5,34 +5,15 @@ import (
"fmt"
"io"
"io/ioutil"
- "net"
"net/http"
- "time"
- "gitlab.com/gitlab-org/labkit/correlation"
"gitlab.com/gitlab-org/labkit/mask"
- "gitlab.com/gitlab-org/labkit/tracing"
-)
-// httpTransport defines a http.Transport with values
-// that are more restrictive than for http.DefaultTransport,
-// they define shorter TLS Handshake, and more aggressive connection closing
-// to prevent the connection hanging and reduce FD usage
-var httpTransport = tracing.NewRoundTripper(correlation.NewInstrumentedRoundTripper(&http.Transport{
- Proxy: http.ProxyFromEnvironment,
- DialContext: (&net.Dialer{
- Timeout: 30 * time.Second,
- KeepAlive: 10 * time.Second,
- }).DialContext,
- MaxIdleConns: 2,
- IdleConnTimeout: 30 * time.Second,
- TLSHandshakeTimeout: 10 * time.Second,
- ExpectContinueTimeout: 10 * time.Second,
- ResponseHeaderTimeout: 30 * time.Second,
-}))
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport"
+)
var httpClient = &http.Client{
- Transport: httpTransport,
+ Transport: httptransport.New(),
}
// Object represents an object on a S3 compatible Object Store service.
diff --git a/workhorse/internal/sendurl/sendurl.go b/workhorse/internal/sendurl/sendurl.go
index ac2e66f95ab..205ec8a0e9f 100644
--- a/workhorse/internal/sendurl/sendurl.go
+++ b/workhorse/internal/sendurl/sendurl.go
@@ -3,18 +3,15 @@ package sendurl
import (
"fmt"
"io"
- "net"
"net/http"
- "time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
- "gitlab.com/gitlab-org/labkit/correlation"
"gitlab.com/gitlab-org/labkit/mask"
- "gitlab.com/gitlab-org/labkit/tracing"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/log"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/senddata"
)
@@ -47,22 +44,7 @@ var preserveHeaderKeys = map[string]bool{
"Pragma": true, // Support for HTTP 1.0 proxies
}
-// httpTransport defines a http.Transport with values
-// that are more restrictive than for http.DefaultTransport,
-// they define shorter TLS Handshake, and more aggressive connection closing
-// to prevent the connection hanging and reduce FD usage
-var httpTransport = tracing.NewRoundTripper(correlation.NewInstrumentedRoundTripper(&http.Transport{
- Proxy: http.ProxyFromEnvironment,
- DialContext: (&net.Dialer{
- Timeout: 30 * time.Second,
- KeepAlive: 10 * time.Second,
- }).DialContext,
- MaxIdleConns: 2,
- IdleConnTimeout: 30 * time.Second,
- TLSHandshakeTimeout: 10 * time.Second,
- ExpectContinueTimeout: 10 * time.Second,
- ResponseHeaderTimeout: 30 * time.Second,
-}))
+var httpTransport = httptransport.New()
var httpClient = &http.Client{
Transport: httpTransport,
diff --git a/workhorse/internal/upload/uploads_test.go b/workhorse/internal/upload/uploads_test.go
index e82dcdcbc69..b5db8003d41 100644
--- a/workhorse/internal/upload/uploads_test.go
+++ b/workhorse/internal/upload/uploads_test.go
@@ -114,7 +114,7 @@ func TestUploadHandlerRewritingMultiPartData(t *testing.T) {
require.Equal(t, hash, r.FormValue("file."+algo), "file hash %s", algo)
}
- require.Len(t, r.MultipartForm.Value, 11, "multipart form values")
+ require.Len(t, r.MultipartForm.Value, 12, "multipart form values")
w.WriteHeader(202)
fmt.Fprint(w, "RESPONSE")
diff --git a/workhorse/internal/upstream/roundtripper/roundtripper.go b/workhorse/internal/upstream/roundtripper/roundtripper.go
index fdbca5c0120..fcba50d7975 100644
--- a/workhorse/internal/upstream/roundtripper/roundtripper.go
+++ b/workhorse/internal/upstream/roundtripper/roundtripper.go
@@ -32,19 +32,23 @@ func NewBackendRoundTripper(backend *url.URL, socket string, proxyHeadersTimeout
}
func newBackendRoundTripper(backend *url.URL, socket string, proxyHeadersTimeout time.Duration, developmentMode bool, tlsConf *tls.Config) http.RoundTripper {
- // Copied from the definition of http.DefaultTransport. We can't literally copy http.DefaultTransport because of its hidden internal state.
- transport, dialer := newBackendTransport()
+ transport := http.DefaultTransport.(*http.Transport).Clone()
transport.ResponseHeaderTimeout = proxyHeadersTimeout
transport.TLSClientConfig = tlsConf
+ // Puma does not support http/2, there's no point in reconnecting
+ transport.ForceAttemptHTTP2 = false
+
+ dial := transport.DialContext
+
if backend != nil && socket == "" {
address := mustParseAddress(backend.Host, backend.Scheme)
transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
- return dialer.DialContext(ctx, "tcp", address)
+ return dial(ctx, "tcp", address)
}
} else if socket != "" {
transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
- return dialer.DialContext(ctx, "unix", socket)
+ return dial(ctx, "unix", socket)
}
} else {
panic("backend is nil and socket is empty")
diff --git a/workhorse/internal/upstream/roundtripper/transport.go b/workhorse/internal/upstream/roundtripper/transport.go
deleted file mode 100644
index 84d9623b129..00000000000
--- a/workhorse/internal/upstream/roundtripper/transport.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package roundtripper
-
-import (
- "net"
- "net/http"
- "time"
-)
-
-// newBackendTransport setups the default HTTP transport which Workhorse uses
-// to communicate with the upstream
-func newBackendTransport() (*http.Transport, *net.Dialer) {
- dialler := &net.Dialer{
- Timeout: 30 * time.Second,
- KeepAlive: 30 * time.Second,
- }
-
- transport := &http.Transport{
- Proxy: http.ProxyFromEnvironment,
- DialContext: dialler.DialContext,
- MaxIdleConns: 100,
- IdleConnTimeout: 90 * time.Second,
- TLSHandshakeTimeout: 10 * time.Second,
- ExpectContinueTimeout: 1 * time.Second,
- }
-
- return transport, dialler
-}
diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go
index d39ba845dc5..22b30fe8a63 100644
--- a/workhorse/internal/upstream/routes.go
+++ b/workhorse/internal/upstream/routes.go
@@ -60,6 +60,7 @@ const (
geoGitProjectPattern = `^/[^-].+\.git/` // Prevent matching routes like /-/push_from_secondary
projectPattern = `^/([^/]+/){1,}[^/]+/`
apiProjectPattern = apiPattern + `v4/projects/[^/]+/` // API: Projects can be encoded via group%2Fsubgroup%2Fproject
+ apiTopicPattern = apiPattern + `v4/topics`
snippetUploadPattern = `^/uploads/personal_snippet`
userUploadPattern = `^/uploads/user`
importPattern = `^/import/`
@@ -295,6 +296,8 @@ func configureRoutes(u *upstream) {
// Overall status can be seen at https://gitlab.com/groups/gitlab-org/-/epics/1802#current-status
u.route("POST", apiProjectPattern+`wikis/attachments\z`, uploadAccelerateProxy),
u.route("POST", apiPattern+`graphql\z`, uploadAccelerateProxy),
+ u.route("POST", apiTopicPattern, uploadAccelerateProxy),
+ u.route("PUT", apiTopicPattern, uploadAccelerateProxy),
u.route("POST", apiPattern+`v4/groups/import`, upload.Accelerate(api, signingProxy, preparers.uploads)),
u.route("POST", apiPattern+`v4/projects/import`, upload.Accelerate(api, signingProxy, preparers.uploads)),
@@ -374,6 +377,10 @@ func configureRoutes(u *upstream) {
// Geo API routes
u.route("", "^/api/v4/geo_nodes", defaultUpstream),
u.route("", "^/api/v4/geo_replication", defaultUpstream),
+ u.route("", "^/api/v4/geo/proxy_git_ssh", defaultUpstream),
+
+ // Internal API routes
+ u.route("", "^/api/v4/internal", defaultUpstream),
// Don't define a catch-all route. If a route does not match, then we know
// the request should be proxied.
diff --git a/workhorse/internal/upstream/routes_test.go b/workhorse/internal/upstream/routes_test.go
new file mode 100644
index 00000000000..f196433f5b4
--- /dev/null
+++ b/workhorse/internal/upstream/routes_test.go
@@ -0,0 +1,47 @@
+package upstream
+
+import (
+ "testing"
+)
+
+func TestProjectNotExistingGitHttpPullWithGeoProxy(t *testing.T) {
+ testCases := []testCase{
+ {"secondary info/refs", "/group/project.git/info/refs", "Local Rails server received request to path /group/project.git/info/refs"},
+ {"primary info/refs", "/-/push_from_secondary/2/group/project.git/info/refs", "Geo primary received request to path /-/push_from_secondary/2/group/project.git/info/refs"},
+ {"primary upload-pack", "/-/push_from_secondary/2/group/project.git/git-upload-pack", "Geo primary received request to path /-/push_from_secondary/2/group/project.git/git-upload-pack"},
+ }
+
+ runTestCasesWithGeoProxyEnabled(t, testCases)
+}
+
+func TestProjectNotExistingGitHttpPushWithGeoProxy(t *testing.T) {
+ testCases := []testCase{
+ {"secondary info/refs", "/group/project.git/info/refs", "Local Rails server received request to path /group/project.git/info/refs"},
+ {"primary info/refs", "/-/push_from_secondary/2/group/project.git/info/refs", "Geo primary received request to path /-/push_from_secondary/2/group/project.git/info/refs"},
+ {"primary receive-pack", "/-/push_from_secondary/2/group/project.git/git-receive-pack", "Geo primary received request to path /-/push_from_secondary/2/group/project.git/git-receive-pack"},
+ }
+
+ runTestCasesWithGeoProxyEnabled(t, testCases)
+}
+
+func TestProjectNotExistingGitSSHPullWithGeoProxy(t *testing.T) {
+ testCases := []testCase{
+ {"GitLab Shell call to authorized-keys", "/api/v4/internal/authorized_keys", "Local Rails server received request to path /api/v4/internal/authorized_keys"},
+ {"GitLab Shell call to allowed", "/api/v4/internal/allowed", "Local Rails server received request to path /api/v4/internal/allowed"},
+ {"GitLab Shell call to info/refs", "/api/v4/geo/proxy_git_ssh/info_refs_receive_pack", "Local Rails server received request to path /api/v4/geo/proxy_git_ssh/info_refs_receive_pack"},
+ {"GitLab Shell call to receive_pack", "/api/v4/geo/proxy_git_ssh/receive_pack", "Local Rails server received request to path /api/v4/geo/proxy_git_ssh/receive_pack"},
+ }
+
+ runTestCasesWithGeoProxyEnabled(t, testCases)
+}
+
+func TestProjectNotExistingGitSSHPushWithGeoProxy(t *testing.T) {
+ testCases := []testCase{
+ {"GitLab Shell call to authorized-keys", "/api/v4/internal/authorized_keys", "Local Rails server received request to path /api/v4/internal/authorized_keys"},
+ {"GitLab Shell call to allowed", "/api/v4/internal/allowed", "Local Rails server received request to path /api/v4/internal/allowed"},
+ {"GitLab Shell call to info/refs", "/api/v4/geo/proxy_git_ssh/info_refs_upload_pack", "Local Rails server received request to path /api/v4/geo/proxy_git_ssh/info_refs_upload_pack"},
+ {"GitLab Shell call to receive_pack", "/api/v4/geo/proxy_git_ssh/upload_pack", "Local Rails server received request to path /api/v4/geo/proxy_git_ssh/upload_pack"},
+ }
+
+ runTestCasesWithGeoProxyEnabled(t, testCases)
+}
diff --git a/workhorse/internal/upstream/upstream_test.go b/workhorse/internal/upstream/upstream_test.go
index 3c942767384..53c15bb7e91 100644
--- a/workhorse/internal/upstream/upstream_test.go
+++ b/workhorse/internal/upstream/upstream_test.go
@@ -88,16 +88,6 @@ func TestGeoProxyFeatureDisabledOnGeoSecondarySite(t *testing.T) {
}
func TestGeoProxyFeatureEnabledOnGeoSecondarySite(t *testing.T) {
- remoteServer, rsDeferredClose := startRemoteServer("Geo primary")
- defer rsDeferredClose()
-
- geoProxyEndpointResponseBody := fmt.Sprintf(`{"geo_proxy_url":"%v"}`, remoteServer.URL)
- railsServer, deferredClose := startRailsServer("Local Rails server", &geoProxyEndpointResponseBody)
- defer deferredClose()
-
- ws, wsDeferredClose, _ := startWorkhorseServer(railsServer.URL, true)
- defer wsDeferredClose()
-
testCases := []testCase{
{"push from secondary is forwarded", "/-/push_from_secondary/foo/bar.git/info/refs", "Geo primary received request to path /-/push_from_secondary/foo/bar.git/info/refs"},
{"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"},
@@ -106,7 +96,7 @@ func TestGeoProxyFeatureEnabledOnGeoSecondarySite(t *testing.T) {
{"unknown route is forwarded", "/anything", "Geo primary received request to path /anything"},
}
- runTestCases(t, ws, testCases)
+ runTestCasesWithGeoProxyEnabled(t, testCases)
}
// This test can be removed when the environment variable `GEO_SECONDARY_PROXY` is removed
@@ -227,6 +217,20 @@ func runTestCases(t *testing.T, ws *httptest.Server, testCases []testCase) {
}
}
+func runTestCasesWithGeoProxyEnabled(t *testing.T, testCases []testCase) {
+ remoteServer, rsDeferredClose := startRemoteServer("Geo primary")
+ defer rsDeferredClose()
+
+ geoProxyEndpointResponseBody := fmt.Sprintf(`{"geo_proxy_url":"%v"}`, remoteServer.URL)
+ railsServer, deferredClose := startRailsServer("Local Rails server", &geoProxyEndpointResponseBody)
+ defer deferredClose()
+
+ ws, wsDeferredClose, _ := startWorkhorseServer(railsServer.URL, true)
+ defer wsDeferredClose()
+
+ runTestCases(t, ws, testCases)
+}
+
func newUpstreamConfig(authBackend string) *config.Config {
return &config.Config{
Version: "123",
@@ -284,9 +288,13 @@ func startWorkhorseServer(railsServerURL string, enableGeoProxyFeature bool) (*h
}
cfg := newUpstreamConfig(railsServerURL)
upstreamHandler := newUpstream(*cfg, logrus.StandardLogger(), myConfigureRoutes)
- ws := httptest.NewServer(upstreamHandler)
+
+ // Secret should be configured before the first Geo API poll happens on server start
+ // to prevent race conditions where the first API call happens without a secret path
testhelper.ConfigureSecret()
+ ws := httptest.NewServer(upstreamHandler)
+
waitForNextApiPoll := func() {}
if enableGeoProxyFeature {
diff --git a/workhorse/internal/zipartifacts/open_archive.go b/workhorse/internal/zipartifacts/open_archive.go
index cf0e38e9ee0..ec2fd691038 100644
--- a/workhorse/internal/zipartifacts/open_archive.go
+++ b/workhorse/internal/zipartifacts/open_archive.go
@@ -5,32 +5,20 @@ import (
"context"
"fmt"
"io"
- "net"
"net/http"
"os"
"strings"
- "time"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/httprs"
- "gitlab.com/gitlab-org/labkit/correlation"
"gitlab.com/gitlab-org/labkit/mask"
- "gitlab.com/gitlab-org/labkit/tracing"
)
var httpClient = &http.Client{
- Transport: tracing.NewRoundTripper(correlation.NewInstrumentedRoundTripper(&http.Transport{
- Proxy: http.ProxyFromEnvironment,
- DialContext: (&net.Dialer{
- Timeout: 30 * time.Second,
- KeepAlive: 10 * time.Second,
- }).DialContext,
- IdleConnTimeout: 30 * time.Second,
- TLSHandshakeTimeout: 10 * time.Second,
- ExpectContinueTimeout: 10 * time.Second,
- ResponseHeaderTimeout: 30 * time.Second,
- DisableCompression: true,
- })),
+ Transport: httptransport.New(
+ httptransport.WithDisabledCompression(), // To avoid bugs when serving compressed files from object storage
+ ),
}
type archive struct {
diff --git a/workhorse/upload_test.go b/workhorse/upload_test.go
index 24c14bb12aa..478cbdb1a44 100644
--- a/workhorse/upload_test.go
+++ b/workhorse/upload_test.go
@@ -83,7 +83,7 @@ func uploadTestServer(t *testing.T, authorizeTests func(r *http.Request), extraT
require.NoError(t, r.ParseMultipartForm(100000))
- const nValues = 10 // file name, path, remote_url, remote_id, size, md5, sha1, sha256, sha512, gitlab-workhorse-upload for just the upload (no metadata because we are not POSTing a valid zip file)
+ const nValues = 11 // file name, path, remote_url, remote_id, size, md5, sha1, sha256, sha512, upload_duration, gitlab-workhorse-upload for just the upload (no metadata because we are not POSTing a valid zip file)
require.Len(t, r.MultipartForm.Value, nValues)
require.Empty(t, r.MultipartForm.File, "multipart form files")
@@ -123,6 +123,8 @@ func TestAcceleratedUpload(t *testing.T) {
{"POST", `/api/v4/projects/group%2Fproject/wikis/attachments`, false},
{"POST", `/api/v4/projects/group%2Fsubgroup%2Fproject/wikis/attachments`, false},
{"POST", `/api/graphql`, false},
+ {"POST", `/api/v4/topics`, false},
+ {"PUT", `/api/v4/topics`, false},
{"PUT", "/api/v4/projects/9001/packages/nuget/v1/files", true},
{"PUT", "/api/v4/projects/group%2Fproject/packages/nuget/v1/files", true},
{"PUT", "/api/v4/projects/group%2Fsubgroup%2Fproject/packages/nuget/v1/files", true},
diff --git a/yarn.lock b/yarn.lock
index 6746a1d71f8..b7f16a7282f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -264,7 +264,7 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.15.0", "@babel/parser@^7.15.4":
+"@babel/parser@7.15.7", "@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.15.0", "@babel/parser@^7.15.4":
version "7.15.7"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.7.tgz#0c3ed4a2eb07b165dfa85b3cc45c727334c4edae"
integrity sha512-rycZXvQ+xS9QyIcJ9HXeDWf1uxqlbVFAUq0Rq0dbc50Zb/+wUe/ehyfzGfm9KZZF0kBejYgxltBXocP+gKdL2g==
@@ -812,7 +812,7 @@
"@babel/parser" "^7.15.4"
"@babel/types" "^7.15.4"
-"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.10.1", "@babel/traverse@^7.15.0", "@babel/traverse@^7.15.4":
+"@babel/traverse@7.15.4", "@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.10.1", "@babel/traverse@^7.15.0", "@babel/traverse@^7.15.4":
version "7.15.4"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d"
integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==
@@ -827,7 +827,7 @@
debug "^4.1.0"
globals "^11.1.0"
-"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.10.1", "@babel/types@^7.10.2", "@babel/types@^7.15.0", "@babel/types@^7.15.4", "@babel/types@^7.15.6", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
+"@babel/types@7.15.6", "@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.10.1", "@babel/types@^7.10.2", "@babel/types@^7.15.0", "@babel/types@^7.15.4", "@babel/types@^7.15.6", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
version "7.15.6"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f"
integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==
@@ -853,6 +853,16 @@
exec-sh "^0.3.2"
minimist "^1.2.0"
+"@endemolshinegroup/cosmiconfig-typescript-loader@3.0.2":
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz#eea4635828dde372838b0909693ebd9aafeec22d"
+ integrity sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA==
+ dependencies:
+ lodash.get "^4"
+ make-error "^1"
+ ts-node "^9"
+ tslib "^2"
+
"@eslint/eslintrc@^0.4.3":
version "0.4.3"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
@@ -873,10 +883,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/at.js/-/at.js-1.5.7.tgz#1ee6f838cc4410a1d797770934df91d90df8179e"
integrity sha512-c6ySRK/Ma7lxwpIVbSAF3P+xiTLrNTGTLRx4/pHK111AdFxwgUwrYF6aVZFXvmG65jHOJHoa0eQQ21RW6rm0Rg==
-"@gitlab/eslint-plugin@9.4.0":
- version "9.4.0"
- resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-9.4.0.tgz#cad8f63b7985c22865859cc7d2688eb446ad0bbb"
- integrity sha512-llPypEQrm9/6Xas5GCoSPAK7W/DgO7CKhzDvAk/Ea9BP0rI2+t8Wg4PFhE1XDctYnnUIS/GrdqVKQkpODk24hQ==
+"@gitlab/eslint-plugin@10.0.0":
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-10.0.0.tgz#83430fb4d0a2467bb54975d0b5b9dc8016005722"
+ integrity sha512-frCYzjQQaZ5kW1on3XwuVGhvYa6XjD6Q1POTbxDpzl6tNxSeTwOJohC6Joyw76e0Kw4fPQd/fHAfKQAB0AVQ7A==
dependencies:
babel-eslint "^10.0.3"
eslint-config-airbnb-base "^14.2.1"
@@ -895,35 +905,35 @@
resolved "https://registry.yarnpkg.com/@gitlab/favicon-overlay/-/favicon-overlay-2.0.0.tgz#2f32d0b6a4d5b8ac44e2927083d9ab478a78c984"
integrity sha512-GNcORxXJ98LVGzOT9dDYKfbheqH6lNgPDD72lyXRnQIH7CjgGyos8i17aSBPq1f4s3zF3PyedFiAR4YEZbva2Q==
-"@gitlab/stylelint-config@2.3.0":
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/@gitlab/stylelint-config/-/stylelint-config-2.3.0.tgz#b27e8544ff52a4c5e23ff7a104c7efff1f7078f0"
- integrity sha512-8aGdBjNO05xadeGb8GSCyRdr1QcRDaDTUTTjKlD2CfFqvAmaQpCk6NdFMMSHlWQpHHMxS5hQeWiC47sIWON4iQ==
+"@gitlab/stylelint-config@2.6.0":
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/stylelint-config/-/stylelint-config-2.6.0.tgz#8c7d6c9d8e0a9a30eda98a2076dee222b88c840b"
+ integrity sha512-9rBMsvQg2IX7FRNtp+ajRk4Map2kBlkepvc/0CTfd84oLX8zadRqG+J62/Ox285vLnihsVM13SGOD7BWvrvQzw==
dependencies:
stylelint "13.9.0"
stylelint-declaration-strict-value "1.7.7"
stylelint-scss "3.18.0"
-"@gitlab/svgs@1.218.0":
- version "1.218.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.218.0.tgz#0715e2ef50b5cb83813e1a5e29d5919a96685734"
- integrity sha512-eckixyumeWogykEUZfP4pGjoRdhdWQIFwSTM0ks5tQqza+BikcL2xvxzicJs69T1IiCKwYtEpR1c3T/hSx39Mg==
+"@gitlab/svgs@1.220.0":
+ version "1.220.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.220.0.tgz#188bdefe86cdbf8be1faa7a92dbac31c728066c7"
+ integrity sha512-9QRXQG6IrQoviU86g2Y4l19yE81UyEg/iMoGetMfUdQ64NW6unLN7uNbUaO1ws1J0p7uG0dKwR6ohD7tEUPLFA==
"@gitlab/tributejs@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
-"@gitlab/ui@32.19.1":
- version "32.19.1"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.19.1.tgz#ab54408272cb5ee695dc0a328892e047da3d41ac"
- integrity sha512-ooc0TwCvREuWJfvn8EbOkEz1Mh4UKEu7x0MKhD+TBjG+JJwLKDClmD1cPPE05BXtWAvW5W9JUBkaeMCVQG2l3g==
+"@gitlab/ui@32.36.0":
+ version "32.36.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.36.0.tgz#f3fb6f86dc51a6941bd230c047f0014364732efd"
+ integrity sha512-cX/+P011FD6TrD9/tKuG5xX/tSx9oRwb/bRA45RG1zbkmRh/ohr5zQMuNK2utrHFl4OqrcPirqXMyFl+kKnCdg==
dependencies:
"@babel/standalone" "^7.0.0"
bootstrap-vue "2.20.1"
copy-to-clipboard "^3.0.8"
dompurify "^2.3.3"
- echarts "^4.9.0"
+ echarts "^5.2.1"
highlight.js "^10.6.0"
js-beautify "^1.8.8"
lodash "^4.17.20"
@@ -936,6 +946,167 @@
resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.6.1.tgz#0d8f3ff9f51b05f7c80b9a107727703d48997e4e"
integrity sha512-vY8K1igwZFoEOmU0h4E7XTLlilsQ4ylPr27O01UsSe6ZTKi6oEMREsRAEpNIUgRlxUARCsf+Opp4pgSFzFkFcw==
+"@graphql-eslint/eslint-plugin@2.3.0":
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/@graphql-eslint/eslint-plugin/-/eslint-plugin-2.3.0.tgz#4e500466fa56b64680c67d7639f1bdf11d890f8a"
+ integrity sha512-YYTBKhadvdTO6myWFm3O8A8dP/ca5NsyB2FKYoHGUIToEl25xAMuj2yzvhIjIBwA/yhlLRPe9+EIQ+8f0kjBDg==
+ dependencies:
+ "@graphql-tools/code-file-loader" "^7.0.2"
+ "@graphql-tools/graphql-tag-pluck" "^7.0.2"
+ "@graphql-tools/import" "^6.3.1"
+ "@graphql-tools/utils" "^8.0.2"
+ graphql-config "^4.0.1"
+ graphql-depth-limit "1.1.0"
+ lodash.lowercase "^4.3.0"
+
+"@graphql-tools/batch-execute@^8.3.0":
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-8.3.0.tgz#a8fabc5f5d6e9fa5b34bbc9cdc2f1809ee164f3f"
+ integrity sha512-rv7lCH4T8hapJ9o1/aOhr64oEZhYaNRt8lzuEC3BlhzJc/szSt+/ry6mBNDjca6tjxJpMc82XLWAx9ppBLnyVA==
+ dependencies:
+ "@graphql-tools/utils" "^8.5.0"
+ dataloader "2.0.0"
+ tslib "~2.3.0"
+ value-or-promise "1.0.11"
+
+"@graphql-tools/code-file-loader@^7.0.2":
+ version "7.2.1"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/code-file-loader/-/code-file-loader-7.2.1.tgz#09c5981cb42579f921f2506164f54892bade85cd"
+ integrity sha512-n9qoGZzJ+zfcUsrWz0uC2tevBcIUgT0adgoaj4OG67i1xfsJ2dJYXurbYpD38G4QKfOZ0DTYJ0oWKYWPkc54Qw==
+ dependencies:
+ "@graphql-tools/graphql-tag-pluck" "^7.1.0"
+ "@graphql-tools/utils" "^8.3.0"
+ globby "^11.0.3"
+ tslib "~2.3.0"
+ unixify "^1.0.0"
+
+"@graphql-tools/delegate@^8.4.0":
+ version "8.4.0"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-8.4.0.tgz#630c7e30b8b0f4039bc453082d6f77501488a9b6"
+ integrity sha512-FtMN1+q6aNahg0AGCEndUpfdOZ6O7OnIsLTauMPEG/vrwoIlMb8tn+qBRlGrWWxyUPKBSD31T74EWM3Tq/bBaQ==
+ dependencies:
+ "@graphql-tools/batch-execute" "^8.3.0"
+ "@graphql-tools/schema" "^8.3.0"
+ "@graphql-tools/utils" "^8.5.0"
+ dataloader "2.0.0"
+ tslib "~2.3.0"
+ value-or-promise "1.0.11"
+
+"@graphql-tools/graphql-file-loader@^7.0.1":
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-file-loader/-/graphql-file-loader-7.3.1.tgz#12c3650197acda0a031fa4d47d371d44908eac88"
+ integrity sha512-LgbnUjhMuHUGmPouhql8q437B2/pO4S04RWGRywkY75+FPrFiSsxyk13qB/lTaUMtrhPz0h8SUAh/09mF/1gpw==
+ dependencies:
+ "@graphql-tools/import" "^6.5.4"
+ "@graphql-tools/utils" "^8.3.0"
+ globby "^11.0.3"
+ tslib "~2.3.0"
+ unixify "^1.0.0"
+
+"@graphql-tools/graphql-tag-pluck@^7.0.2", "@graphql-tools/graphql-tag-pluck@^7.1.0":
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-7.1.2.tgz#1f4ae8a98df3529da1dc5654469900d4c08cc3a1"
+ integrity sha512-YVvzG6UaWJQgbU+VvjFY5rZQQDvkyNX+rEbqYpJOt1muhP67dAwAGyWMyDcyEi4QAsEpSvaxfy/Km6lR/NHwWA==
+ dependencies:
+ "@babel/parser" "7.15.7"
+ "@babel/traverse" "7.15.4"
+ "@babel/types" "7.15.6"
+ "@graphql-tools/utils" "^8.2.5"
+ tslib "~2.3.0"
+
+"@graphql-tools/import@^6.3.1", "@graphql-tools/import@^6.5.4":
+ version "6.5.6"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/import/-/import-6.5.6.tgz#9ea073d7fb4fdd177ecc2df4c553b61db9d55fcb"
+ integrity sha512-SxCpNhN3sIZM4wsMjQWXKkff/CBn7+WHoZ9OjZkdV5nxGbnzRKh5SZAAsvAFuj6Kst5Y9mlAaiwy+QufZZ1F1w==
+ dependencies:
+ "@graphql-tools/utils" "8.5.0"
+ resolve-from "5.0.0"
+ tslib "~2.3.0"
+
+"@graphql-tools/json-file-loader@^7.0.1":
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/json-file-loader/-/json-file-loader-7.3.1.tgz#5252a65380c70343e8c761c1fea3f59c65d22114"
+ integrity sha512-A2Pa4C8KoZkiqTk2/YxU6uIlRpIcPSUBBSL6cXh0877XZeCgs2cmmFMvZOnYJni0X6Bw38gkCAjaYJXpBzNFPQ==
+ dependencies:
+ "@graphql-tools/utils" "^8.3.0"
+ globby "^11.0.3"
+ tslib "~2.3.0"
+ unixify "^1.0.0"
+
+"@graphql-tools/load@^7.1.0":
+ version "7.4.0"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/load/-/load-7.4.0.tgz#259e2b0b5efe1b7d1834ca462ff22785a42e5c7e"
+ integrity sha512-f1RpBa/TIHIRxzcmL+pRj+021P8lx1Tu0gQ/6tzEHMlvh8AhPchXlOiASWBWDVo0J7+fSL+KQrlVORQ7VVMT0w==
+ dependencies:
+ "@graphql-tools/schema" "8.3.0"
+ "@graphql-tools/utils" "^8.4.0"
+ p-limit "3.1.0"
+ tslib "~2.3.0"
+
+"@graphql-tools/merge@^6.2.16 || ^7.0.0 || ^8.0.0", "@graphql-tools/merge@^8.2.0":
+ version "8.2.0"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.2.0.tgz#8f6638eeecf19f59fef28598024308e0452dd0a2"
+ integrity sha512-nfMLYF7zczjnIbChZtqbvozRfuRweMD1Fe9HHd4RXd3Tcsj6E17srW0QJfxUoIIWh4pitj+XwZAwhj1PWBDU7g==
+ dependencies:
+ "@graphql-tools/utils" "^8.4.0"
+ tslib "~2.3.0"
+
+"@graphql-tools/schema@8.3.0", "@graphql-tools/schema@^8.3.0":
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-8.3.0.tgz#ddf4297859c6d7ac1ebbbd91460260ed424115db"
+ integrity sha512-OJD4Q1Xa3sffRiHzy0sskZz9ZWeqaujINfoim4CTk5Y9es1LS+WnKi25wVhmL2SGzzmKuAv7oDn+dpQAlM+Gfw==
+ dependencies:
+ "@graphql-tools/merge" "^8.2.0"
+ "@graphql-tools/utils" "^8.4.0"
+ tslib "~2.3.0"
+ value-or-promise "1.0.11"
+
+"@graphql-tools/url-loader@^7.0.3":
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/url-loader/-/url-loader-7.4.1.tgz#2cdae0d27271aa7f8d88788698f6490dd88de4cf"
+ integrity sha512-RrgXxiabfCH0gTvn86o6wOKXCqhb5EFoZlbK2TzWECA4i3mJehrxZ+FSIDrbcFcpgrE94SNj9a/xXK4VcgJNKg==
+ dependencies:
+ "@graphql-tools/delegate" "^8.4.0"
+ "@graphql-tools/utils" "^8.5.0"
+ "@graphql-tools/wrap" "^8.3.0"
+ "@n1ru4l/graphql-live-query" "0.8.1"
+ "@types/websocket" "1.0.4"
+ "@types/ws" "^8.0.0"
+ abort-controller "3.0.0"
+ cross-fetch "3.1.4"
+ dset "^3.1.0"
+ extract-files "11.0.0"
+ form-data "4.0.0"
+ graphql-sse "^1.0.1"
+ graphql-ws "^5.4.1"
+ is-promise "4.0.0"
+ isomorphic-ws "4.0.1"
+ meros "1.1.4"
+ subscriptions-transport-ws "^0.10.0"
+ sync-fetch "0.3.1"
+ tslib "~2.3.0"
+ valid-url "1.0.9"
+ value-or-promise "1.0.11"
+ ws "8.2.3"
+
+"@graphql-tools/utils@8.5.0", "@graphql-tools/utils@^8.0.1", "@graphql-tools/utils@^8.0.2", "@graphql-tools/utils@^8.2.5", "@graphql-tools/utils@^8.3.0", "@graphql-tools/utils@^8.4.0", "@graphql-tools/utils@^8.5.0":
+ version "8.5.0"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.5.0.tgz#439487ac756d9458a33091e5e0435ddf8e794f3e"
+ integrity sha512-jMwLm6YdN+Vbqntg5GHqDvGLpLa/xPSpRs/c40d0rBuel77wo7AaQ8jHeBSpp9y+7kp7HrGSWff1u7yJ7F8ppw==
+ dependencies:
+ tslib "~2.3.0"
+
+"@graphql-tools/wrap@^8.3.0":
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/@graphql-tools/wrap/-/wrap-8.3.0.tgz#ae40302965176614adde80fd1e3ea93b87d3219d"
+ integrity sha512-DB9Rc/GHAAPizarlCAeo7KzZLN0VaMB+9XG6Pm8IfoNNYHq1I6czlzskHGd+U5nkXUhkuHFlV2QnersxhyJkHA==
+ dependencies:
+ "@graphql-tools/delegate" "^8.4.0"
+ "@graphql-tools/schema" "^8.3.0"
+ "@graphql-tools/utils" "^8.5.0"
+ tslib "~2.3.0"
+ value-or-promise "1.0.11"
+
"@humanwhocodes/config-array@^0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
@@ -950,6 +1121,11 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf"
integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==
+"@iarna/toml@^2.2.5":
+ version "2.2.5"
+ resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c"
+ integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==
+
"@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@@ -1142,6 +1318,11 @@
resolved "https://registry.yarnpkg.com/@miragejs/pretender-node-polyfill/-/pretender-node-polyfill-0.1.2.tgz#d26b6b7483fb70cd62189d05c95d2f67153e43f2"
integrity sha512-M/BexG/p05C5lFfMunxo/QcgIJnMT2vDVCd00wNqK2ImZONIlEETZwWJu1QtLxtmYlSHlCFl3JNzp0tLe7OJ5g==
+"@n1ru4l/graphql-live-query@0.8.1":
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/@n1ru4l/graphql-live-query/-/graphql-live-query-0.8.1.tgz#2d6ca6157dafdc5d122a1aeb623b43e939c4b238"
+ integrity sha512-x5SLY+L9/5s07OJprISXx4csNBPF74UZeTI01ZPSaxOtRz2Gljk652kSPf6OjMLtx5uATr35O0M3G0LYhHBLtg==
+
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
@@ -1184,10 +1365,10 @@
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.12.tgz#431ec342a7195622f86688bbda82e3166ce8cb28"
integrity sha512-6RglhutqrGFMO1MNUXp95RBuYIuc8wTnMAV5MUhLmjTOy78ncwOw7RgeQ/HeymkKXRhZd0s2DNrM1rL7unk3MQ==
-"@popperjs/core@^2.8.3":
- version "2.9.2"
- resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353"
- integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==
+"@popperjs/core@^2.9.0":
+ version "2.10.2"
+ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.2.tgz#0798c03351f0dea1a5a4cabddf26a55a7cbee590"
+ integrity sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==
"@rails/actioncable@6.1.4-1":
version "6.1.4-1"
@@ -1310,79 +1491,73 @@
dom-accessibility-api "^0.5.1"
pretty-format "^26.4.2"
-"@tiptap/core@^2.0.0-beta.118":
- version "2.0.0-beta.118"
- resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.118.tgz#17e990da525a81d957494171c0c33d17e2039823"
- integrity sha512-TApketXliv2PZSTf5WP8j/svwzeK795fOf4Ff6A0gDwcVYFPHlny4ZlpawYthyqDoe1fEusyZokVgiDHnb+EzA==
+"@tiptap/core@^2.0.0-beta.125":
+ version "2.0.0-beta.125"
+ resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.125.tgz#672a86f21727614bfe8d5bf41544ce83ea4a7c87"
+ integrity sha512-I3lju5hcjK6nhC29jJCdGoRdP0C5nPBHGN8y/fbFmCX0oQ/THuzVdMgaGPpkHjralPPMS3DqHD/Rx8Kbo8zClg==
dependencies:
"@types/prosemirror-commands" "^1.0.4"
- "@types/prosemirror-inputrules" "^1.0.4"
"@types/prosemirror-keymap" "^1.0.4"
"@types/prosemirror-model" "^1.13.2"
"@types/prosemirror-schema-list" "^1.0.3"
"@types/prosemirror-state" "^1.2.7"
"@types/prosemirror-transform" "^1.1.4"
"@types/prosemirror-view" "^1.19.1"
- prosemirror-commands "^1.1.10"
- prosemirror-inputrules "^1.1.3"
+ prosemirror-commands "^1.1.11"
prosemirror-keymap "^1.1.3"
prosemirror-model "^1.14.3"
prosemirror-schema-list "^1.1.6"
prosemirror-state "^1.3.4"
prosemirror-transform "^1.3.3"
- prosemirror-view "^1.20.1"
+ prosemirror-view "^1.20.3"
-"@tiptap/extension-blockquote@^2.0.0-beta.15":
- version "2.0.0-beta.15"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.15.tgz#40be203f7db47e027ea1a5ba42bbb0e33bb6c004"
- integrity sha512-Cso44KsYsqKqaNveQmx5KVaLy9krq5AzE9WhGVDBSFqWhvuIJkQYrTRBbOTfUDs/st9VuwJrbjTDD65ow50wEw==
- dependencies:
- prosemirror-inputrules "^1.1.3"
+"@tiptap/extension-blockquote@^2.0.0-beta.19":
+ version "2.0.0-beta.19"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.19.tgz#4b1dfd0ec511f889ddb0f34cd09e57a0db877dc0"
+ integrity sha512-9y8keXSm4E5mdh/EocdbrJ/H71qyXv2jajRHIsXj1SaJqLaz4JbSQGrX3j2r0ia3KW3YNFFIHl/z33fU70YfGQ==
-"@tiptap/extension-bold@^2.0.0-beta.15":
- version "2.0.0-beta.15"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.15.tgz#cf9ddb3fc316be9707753ad4e497bfb8a3ebb0c2"
- integrity sha512-jKyV6iiwhxwa0+7uuKD74jNDVNLNOS1GmU14MgaA95pY5e1fyaRBPPX8Gtt89niz2CLOY711AV17RPZTe/e60w==
+"@tiptap/extension-bold@^2.0.0-beta.19":
+ version "2.0.0-beta.19"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.19.tgz#9426b5fcb2bfb79082f9efefbafff955d26d023e"
+ integrity sha512-pbYMK3Lz78XFi+1OisdjuGQcjRnzHXeYivh9A4xP1fmSOS6t/lQsu2P2uDhFNXtz45dLcLTOkqnE0j5lj3TGMg==
-"@tiptap/extension-bubble-menu@^2.0.0-beta.39":
- version "2.0.0-beta.39"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.39.tgz#8971feeac93e685fc38564173a83ad078b4e7f2a"
- integrity sha512-hmA+ePR+MnRaTJ5MxoZ3yqOcK54cW2KQllZx16ZwSyM+yU9bXVhfMmyZwqRD7GGQFkrfnPm5QnedXDBYJD19OQ==
+"@tiptap/extension-bubble-menu@^2.0.0-beta.42":
+ version "2.0.0-beta.42"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.42.tgz#40c2783860721e861b3eb11aa2a076d1944058c2"
+ integrity sha512-H+pGpSk0mK4BRm4RbevgT+ir1bEwlS1dEwi2YIPYVl+JSpuGS2P1jTWeZpCou9cewNuxxwrAarhp4aEvJrL8UQ==
dependencies:
prosemirror-state "^1.3.4"
- prosemirror-view "^1.20.1"
- tippy.js "^6.3.1"
+ prosemirror-view "^1.20.3"
+ tippy.js "^6.3.2"
-"@tiptap/extension-bullet-list@^2.0.0-beta.15":
- version "2.0.0-beta.15"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.15.tgz#74876851a8d227ba1a031d031631ed621c175e05"
- integrity sha512-5i44JzsZOh8Ci6CuYRQy6W3jCpYgX0+VuJKeHvZ6Aomy4Qqrtc9Jk43PBmCj91lNUUtH6Io9l+kDrLCumEFnEg==
- dependencies:
- prosemirror-inputrules "^1.1.3"
+"@tiptap/extension-bullet-list@^2.0.0-beta.18":
+ version "2.0.0-beta.18"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.18.tgz#ab33426a3ea03cea11863e44aad9e48fc18d478c"
+ integrity sha512-dOf2Wx9bmgpBQIxhw7b+g1GhbIyIox7FIiIEkkSgqDtx8wPPYlnGwHRxopj4a57VbqRkRtspJZp52/vhP3is5w==
-"@tiptap/extension-code-block-lowlight@2.0.0-beta.41":
- version "2.0.0-beta.41"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.41.tgz#3ec98f509bbd5df689de6282f2a3881229262ed7"
- integrity sha512-2+D/SwcRjWThJ8uFWJT/6B7R+gTUlp4h13/EZqrFMm3YCSOx+bzgTVndog6UJkWyAoNDxkTVwcOyYI4HWdvCiQ==
+"@tiptap/extension-code-block-lowlight@2.0.0-beta.47":
+ version "2.0.0-beta.47"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.47.tgz#2a3253f778375e4a420dd77967931b4da7926913"
+ integrity sha512-+k0uACctl4PIrZQrZkiPapYL/Uq8Skc6gBhlvtJ3+U9+U798Rm7QZpGxEe9iXW4KC69E4LtD1JNj27Ofns35Cg==
dependencies:
- "@tiptap/extension-code-block" "^2.0.0-beta.18"
+ "@tiptap/extension-code-block" "^2.0.0-beta.24"
"@types/lowlight" "^0.0.3"
lowlight "^1.20.0"
prosemirror-model "^1.14.3"
prosemirror-state "^1.3.4"
- prosemirror-view "^1.20.1"
+ prosemirror-view "^1.20.3"
-"@tiptap/extension-code-block@^2.0.0-beta.18":
- version "2.0.0-beta.18"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.18.tgz#3b43730cfca1ba26171530951b3cc324a500cb11"
- integrity sha512-E2gz7ovl9nXLZzheqLyN3hi7A10fCaodDn4DvIl4wiEbKZpF7WFBNeb+FQetWNay9UWNeDO94SCX9+rT9H+yHA==
+"@tiptap/extension-code-block@^2.0.0-beta.24":
+ version "2.0.0-beta.24"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.24.tgz#f3d45d4ae0cdc2bf94ed5e61a5421c72b2bd3a53"
+ integrity sha512-Q6KxBe3FB+dMe/prlfeixXSVqGTmnOmIL2/10B1RzSj7Mj9SgzqQEHZFm3dKVqpYuMOYJ6S6edkW33E0Wq9ahQ==
dependencies:
- prosemirror-inputrules "^1.1.3"
+ prosemirror-state "^1.3.4"
-"@tiptap/extension-code@^2.0.0-beta.16":
- version "2.0.0-beta.16"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.16.tgz#b258ff90ebe703a4d36ff0c650e6b2cab634028d"
- integrity sha512-Kakg/RMiVrxjzIkLVDXtbCzRh/9W8dgSG04IhMZNOI8N9vWn8Z78jdUyxEEDTcL/JyWWcMxn9AsJw2U5ajO3pA==
+"@tiptap/extension-code@^2.0.0-beta.20":
+ version "2.0.0-beta.20"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.20.tgz#0f5ff7e827ae09c26d23ddc9e62f6375d2f1c0f8"
+ integrity sha512-25twg/rsg5CxTOfDgYzg1GbwrtdzNX2vCQyYsauXfPI1kbrWXdVBYWeL4iHdJk5WElfH9WUbQ4kMGh13/KCG/g==
"@tiptap/extension-document@^2.0.0-beta.13":
version "2.0.0-beta.13"
@@ -1397,34 +1572,32 @@
"@types/prosemirror-dropcursor" "^1.0.3"
prosemirror-dropcursor "^1.3.5"
-"@tiptap/extension-floating-menu@^2.0.0-beta.33":
- version "2.0.0-beta.33"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.33.tgz#11068488f10fce697df2a48f79039e9c1d10eb7b"
- integrity sha512-8s8DPnHIzXg7E7S/DjuS1AAFZKVYXY0KBKaEd1f2V45YOkKwN9El46Ugk/4Ir3yrrllvnisbP9ol+BAQmI0bMg==
+"@tiptap/extension-floating-menu@^2.0.0-beta.36":
+ version "2.0.0-beta.36"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.36.tgz#313082e2dd22b6b20c81aa4e98f7c9bcfd47ebe7"
+ integrity sha512-Pm9KK+Y7YUgMrlvqa/MgxV0WOTBiOp8d2kpt7OwGv/ahjc4amv0HFbei7glsiJ56VtOv8lsjiuBS+m2ctWHWVQ==
dependencies:
prosemirror-state "^1.3.4"
- prosemirror-view "^1.20.1"
- tippy.js "^6.3.1"
+ prosemirror-view "^1.20.3"
+ tippy.js "^6.3.2"
-"@tiptap/extension-gapcursor@^2.0.0-beta.24":
- version "2.0.0-beta.24"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.24.tgz#dc42a3610cea611755c6521e14a6995555e0ad49"
- integrity sha512-/6Ru0wNLIb3fo30Ar3z/rcakoUA2EIJL9sBFiuyHWTAIujeEaBzA6oG5L4PpP+daKd31JF0I6LjeWMSU9CBSFw==
+"@tiptap/extension-gapcursor@^2.0.0-beta.27":
+ version "2.0.0-beta.27"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.27.tgz#ced6cb7d39a388e60f8ec22889a015beb81b417a"
+ integrity sha512-Sk041ygN+PhAGiCnDfEtFl8sFmm+clKTHJZJwb6ixcdfgY9xkTpkrgswsAY5fvLnLxZUJvZSDOrsvysbh6M2MQ==
dependencies:
"@types/prosemirror-gapcursor" "^1.0.4"
prosemirror-gapcursor "^1.2.0"
-"@tiptap/extension-hard-break@^2.0.0-beta.21":
- version "2.0.0-beta.21"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.21.tgz#3b9108c7703f23ae186c1038033f0b1354f721bf"
- integrity sha512-Ukl+wjfLhE0tW7lWRpSPPo2tajjGnEaSc/Irey1JineFf+x/azA9rREzQy0r2AhORTalH7lj/KDmSdG8IT6syA==
+"@tiptap/extension-hard-break@^2.0.0-beta.24":
+ version "2.0.0-beta.24"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.24.tgz#8518cf253c24a316824fdac41ffe195fe934bfb2"
+ integrity sha512-0oEHUlQKQZRQmrbKARFPBVVRBWdekR27ro+qg+T6nzEHYSRkJ7dWBswGSNul1v1XEp52JqniZ3el0w1xdYMR0w==
-"@tiptap/extension-heading@^2.0.0-beta.15":
- version "2.0.0-beta.15"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.15.tgz#d62f32a2ec8ce5a6d4e716aa7a45dfb707283848"
- integrity sha512-UoXDwEdCV9KiPh0wj0jj2Jt6VDqkoTaSU3d9bmEBLwg1Gjgbuv39JDst7oxSqbf9rgbl3txbeOy35wVBKe9CqA==
- dependencies:
- prosemirror-inputrules "^1.1.3"
+"@tiptap/extension-heading@^2.0.0-beta.18":
+ version "2.0.0-beta.18"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.18.tgz#ffaee32ab0286ac047a3f38a52f870538155e30c"
+ integrity sha512-JJtB1pNHkqC9z/z/6B+xQpDd1w5EaLp++yG8eoY9NCq3ZCRhwULda+Uq7reA9D0PdEDpASsTSS2qLu8ZAtgUeA==
"@tiptap/extension-history@^2.0.0-beta.16":
version "2.0.0-beta.16"
@@ -1434,28 +1607,29 @@
"@types/prosemirror-history" "^1.0.3"
prosemirror-history "^1.2.0"
-"@tiptap/extension-horizontal-rule@^2.0.0-beta.21":
- version "2.0.0-beta.21"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.21.tgz#1c73a8547611f53935117ed0079542d958ba37fa"
- integrity sha512-fgvRGuNEGWAitbcoz6VZSR9gcVIHksTy2QpXPnQC+N9Mi7havaxreYdMZn+oePW/5kdZoZNRx+jsf5DjKomvoQ==
+"@tiptap/extension-horizontal-rule@^2.0.0-beta.24":
+ version "2.0.0-beta.24"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.24.tgz#ffd6226a98a62c5314012b8c1cc60c90709d0b9c"
+ integrity sha512-kRHJySSJl6QgPvnD+MkN3rzwQgInbq5zE4oxPPbgqYkaAcVSL/q7JBQK1dXMMFaslQlYmEgM6Eh3oU5vo9gUdQ==
dependencies:
prosemirror-state "^1.3.4"
-"@tiptap/extension-image@^2.0.0-beta.15":
- version "2.0.0-beta.15"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.15.tgz#07bdc23c9804c830a394f78242648dd7783a469e"
- integrity sha512-iMwQ154RPefOxgqTTHjOA735YWesyjBhYvD9fFxRDctM2vLxEYYYFOENXEBCFLNAr94gfaxefCEdkuNYHl9H7g==
+"@tiptap/extension-image@^2.0.0-beta.19":
+ version "2.0.0-beta.19"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.19.tgz#40bd95d6d4306d28640bf60a074f20c792f375c6"
+ integrity sha512-17ax4H6Y+xyePfLtL5Z2V2AuWKHziukixHigA+Go4yOdEHlSDvl+x8eNYAZkxy2nH1yFW+uu7Onv8Ln/jWzqLg==
-"@tiptap/extension-italic@^2.0.0-beta.15":
- version "2.0.0-beta.15"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.15.tgz#9a81f686cf221110478935596f0b47a76d4c2f45"
- integrity sha512-ZCz1vCysLdvOUrwODuyBP0BDaemCLh6ib7qTYoSDKdive9kfn0Vc5Fg3o8xgHrtrUfwKIJz/sWOknjDEGIc9cw==
+"@tiptap/extension-italic@^2.0.0-beta.19":
+ version "2.0.0-beta.19"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.19.tgz#8f140e778e8cbd2281df6463d895d3632280c26f"
+ integrity sha512-gEVDqEz25glLuOPW1IOPJy/AIrTgsm164XSi9lnwS1uZa1bmEAKpoALN0+9VzSVaBOmrg2tycMo+iuOhYxFb7w==
-"@tiptap/extension-link@^2.0.0-beta.20":
- version "2.0.0-beta.20"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.20.tgz#dbb2aa4f01212bbd0c3fb14b563e28f31140eae2"
- integrity sha512-VljjF5Pmd8xeUxN+Wbypyh8zGEMBWJTwzHUVMbkAEU8IZTdk2gDDcAOiYPyU9+j0vAVbSXi1EAsBRIIlj0OaKQ==
+"@tiptap/extension-link@^2.0.0-beta.23":
+ version "2.0.0-beta.23"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.23.tgz#7591dfe6eb8f65548c2b6a562c2b6ec0568d23c2"
+ integrity sha512-XnNdu6OyB09M4Qsru5j/GsDwj/EFjLQNmGZSQIS3GoaEcxrOImohnEZBZO9WJ11A5IT2GilpRZn2wHscdKoBdA==
dependencies:
+ linkifyjs "^3.0.3"
prosemirror-state "^1.3.4"
"@tiptap/extension-list-item@^2.0.0-beta.14":
@@ -1463,22 +1637,20 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.14.tgz#65a9ff9daa11bc9ca8bc2989a891abe68081cfbd"
integrity sha512-t6xwEqP+d5443Ul2Jvqz9kXb3ro7bA7yY9HA0vskm3120WxxHW9jxgxZN+82Ot5Tm7nXOAlsN6vuqnt4idnxZQ==
-"@tiptap/extension-ordered-list@^2.0.0-beta.16":
- version "2.0.0-beta.16"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.16.tgz#3ef25a8dd8ddbd2b1aa5ce89d5a2e5a3ecafcf4e"
- integrity sha512-3n0h5FBfQqBrN/zqF/Ngoyd1bZxeIRLwWI7ak4KulpvOg5V/yw3sw5CSxr2f13ZI9AgGaTq8yOsTYs9dkCCnsQ==
- dependencies:
- prosemirror-inputrules "^1.1.3"
+"@tiptap/extension-ordered-list@^2.0.0-beta.19":
+ version "2.0.0-beta.19"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.19.tgz#eeab2e8488b84ba7deb93b299370dc187d37c98a"
+ integrity sha512-PHC5pA1gohxCJF2xMXOzruPt8XWyWLun3vhJL2AIUUzUoGJmSRhsc8Wreeozdlf8HkKrqnsIuk5tp6IEsau6Pw==
"@tiptap/extension-paragraph@^2.0.0-beta.17":
version "2.0.0-beta.17"
resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.17.tgz#f8f0263359b95dec9c10078699697908568d9be9"
integrity sha512-qCQVCf9c2hgaeIdfy22PaoZyW5Vare/1aGkOEAaZma5RjrUbV9hrRKwoW9LsDjnh1EN1fIeKdg02yEhnHWtG8A==
-"@tiptap/extension-strike@^2.0.0-beta.17":
- version "2.0.0-beta.17"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.17.tgz#2280ea4e8c50189c2729814d2ae484e58c712a36"
- integrity sha512-+WRd0RuCK4+jFKNVN+4rHTa5VMqqGDO2uc+TknkqhFqWp/z96OAGlpHJOwPrnW1fLbpjEBBQIr1vVYSw6KgcZg==
+"@tiptap/extension-strike@^2.0.0-beta.21":
+ version "2.0.0-beta.21"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.21.tgz#d4b7f0d52a275bc6a4ddc60fe546495d9f77f041"
+ integrity sha512-uYU5k05MChVtZUwWMXAl+xp3IGx/N/+8VZaeJDlIZfg0hew+ZdEGVjwzgCQc1PAuEZriHhbpPg1yOdcHjWga8Q==
"@tiptap/extension-subscript@^2.0.0-beta.4":
version "2.0.0-beta.4"
@@ -1505,39 +1677,37 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-table-row/-/extension-table-row-2.0.0-beta.14.tgz#9ec98c73e309ee966b71ccd140019874d179e0c8"
integrity sha512-mewdlTqgBCyzeZIZ6F08gfuzwsiYjQ7BvABo2UhDfr0+EN2UvfJj0bT3tGgeZhMxT5Js2DXL+c+ZOVJxWJ9faQ==
-"@tiptap/extension-table@^2.0.0-beta.31":
- version "2.0.0-beta.31"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-table/-/extension-table-2.0.0-beta.31.tgz#96987fe14017be2fd3e4dbd2ce349eec641724de"
- integrity sha512-yMqnbxaq2DjaZ6EOE9FLSQSO+qHH7oE0rA+ahQkJdy9KycSboKthXBY7P9JeXxariTyD2B/My9x41cuDLWes9w==
+"@tiptap/extension-table@^2.0.0-beta.34":
+ version "2.0.0-beta.34"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-table/-/extension-table-2.0.0-beta.34.tgz#6669d7d937b981e39f7dfa04b9adbabc18f789bc"
+ integrity sha512-DyY+m0PcvdVwh0XynDbsHXu/omUoTzQRQPI4z035J+b2HnLQnYjviNqblY/x8/rGX4qGGjBUmKvQZgwPGg7Dfw==
dependencies:
prosemirror-tables "^1.1.1"
- prosemirror-view "^1.20.1"
+ prosemirror-view "^1.20.3"
-"@tiptap/extension-task-item@^2.0.0-beta.18":
- version "2.0.0-beta.18"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.0.0-beta.18.tgz#f109c15c997038d8099b64dba4cfc4e219b426e4"
- integrity sha512-SmXWdfpDFIBGxWH4Xhb9d6jRSK7jJqsw0GqC5KAtIQ9gNvAQS1j5FqAtWfxlb8FkunIfV6MNnxDP2ZgbKvaEug==
- dependencies:
- prosemirror-inputrules "^1.1.3"
+"@tiptap/extension-task-item@^2.0.0-beta.21":
+ version "2.0.0-beta.21"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.0.0-beta.21.tgz#37a8d30949cefd79b80f107d426d14eb9aeaf567"
+ integrity sha512-7pCOc+jSlveTGIUUVQO5LOGZN20vb1fAIFMUKAxG756MMI69eVhpdqrXcmovYT8qs//DcvxC/sEjus+ZzFtKVg==
-"@tiptap/extension-task-list@^2.0.0-beta.17":
- version "2.0.0-beta.17"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-task-list/-/extension-task-list-2.0.0-beta.17.tgz#c0f40325abf1b6a23868e72ab32f9724a8b42a7b"
- integrity sha512-E17VBqW2lXF59hCQ/3/Kg0hYSDGvVC4B3W8miZwCXt5WTOl98Gk6qAiDXl+2mDKZvnsLty/YrgkD88OlZSIEbQ==
+"@tiptap/extension-task-list@^2.0.0-beta.18":
+ version "2.0.0-beta.18"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-task-list/-/extension-task-list-2.0.0-beta.18.tgz#8b13593e3818995e7b5058bc400ee04c68314d69"
+ integrity sha512-EkPM+We5TP6MWwk+dH3FX/aizNRgVzHDTnnGyMisEievaazi11oKmz72svVCfF+BJJaRdVroCbeRoLWYH7by7w==
"@tiptap/extension-text@^2.0.0-beta.13":
version "2.0.0-beta.13"
resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.13.tgz#da0af8d9a3f149d20076e15d88c6af21fb6d940f"
integrity sha512-0EtAwuRldCAoFaL/iXgkRepEeOd55rPg5N4FQUN1xTwZT7PDofukP0DG/2jff/Uj17x4uTaJAa9qlFWuNnDvjw==
-"@tiptap/vue-2@^2.0.0-beta.57":
- version "2.0.0-beta.57"
- resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.57.tgz#242f7aa47d3c99fdef0e66a05a193b6fef1a95a6"
- integrity sha512-f8COWq84wOJeLwAmaYsHCqKVbGgMloW+1r4Rz/KhlFb1MNXYeDHibCiW/VtJe7bdae+iRyIwnfmnAp2u5s77hQ==
+"@tiptap/vue-2@^2.0.0-beta.60":
+ version "2.0.0-beta.60"
+ resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.60.tgz#18b1c3e7f1a94e5a047c6e25f4e176a42b68e2d1"
+ integrity sha512-6V2BucVL440yPy4YqCVxnaq7ZkiR9RmOtLydcNIt9/Abc/iQTkp2Q8qyDUqbGTfGfMEEdpuHd4m9ZRk3cuZ14g==
dependencies:
- "@tiptap/extension-bubble-menu" "^2.0.0-beta.39"
- "@tiptap/extension-floating-menu" "^2.0.0-beta.33"
- prosemirror-view "^1.20.1"
+ "@tiptap/extension-bubble-menu" "^2.0.0-beta.42"
+ "@tiptap/extension-floating-menu" "^2.0.0-beta.36"
+ prosemirror-view "^1.20.3"
"@toast-ui/editor@^2.5.2":
version "2.5.2"
@@ -1676,10 +1846,10 @@
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256"
integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==
-"@types/node@*", "@types/node@>=6":
- version "10.12.9"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.9.tgz#a07bfa74331471e1dc22a47eb72026843f7b95c8"
- integrity sha512-eajkMXG812/w3w4a1OcBlaTwsFPO5F7fJ/amy+tieQxEMWBlbV1JGSjkFM+zkHNf81Cad+dfIRA+IBkvmvdAeA==
+"@types/node@*", "@types/node@14.17.5", "@types/node@>=6":
+ version "14.17.5"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.5.tgz#b59daf6a7ffa461b5648456ca59050ba8e40ed54"
+ integrity sha512-bjqH2cX/O33jXT/UmReo2pM7DIJREPMnarixbQ57DOOzzFaI6D2+IcwaJQaJpv0M1E9TIhPCYVxrkcityLjlqA==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
@@ -1738,14 +1908,6 @@
"@types/prosemirror-model" "*"
"@types/prosemirror-state" "*"
-"@types/prosemirror-inputrules@^1.0.4":
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-inputrules/-/prosemirror-inputrules-1.0.4.tgz#4cb75054d954aa0f6f42099be05eb6c0e6958bae"
- integrity sha512-lJIMpOjO47SYozQybUkpV6QmfuQt7GZKHtVrvS+mR5UekA8NMC5HRIVMyaIauJLWhKU6oaNjpVaXdw41kh165g==
- dependencies:
- "@types/prosemirror-model" "*"
- "@types/prosemirror-state" "*"
-
"@types/prosemirror-keymap@^1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@types/prosemirror-keymap/-/prosemirror-keymap-1.0.4.tgz#f73c79810e8d0e0a20d153d84f998f02e5afbc0c"
@@ -1814,6 +1976,20 @@
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
+"@types/websocket@1.0.4":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.4.tgz#1dc497280d8049a5450854dd698ee7e6ea9e60b8"
+ integrity sha512-qn1LkcFEKK8RPp459jkjzsfpbsx36BBt3oC3pITYtkoBw/aVX+EZFa5j3ThCRTNpLFvIMr5dSTD4RaMdilIOpA==
+ dependencies:
+ "@types/node" "*"
+
+"@types/ws@^8.0.0":
+ version "8.2.0"
+ resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.0.tgz#75faefbe2328f3b833cb8dc640658328990d04f3"
+ integrity sha512-cyeefcUCgJlEk+hk2h3N+MqKKsPViQgF5boi9TTHSK+PoR9KWBb/C5ccPcDyAqgsbAYHTwulch725DV84+pSpg==
+ dependencies:
+ "@types/node" "*"
+
"@types/yargs-parser@*":
version "15.0.0"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d"
@@ -2063,6 +2239,13 @@ abbrev@1:
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
+abort-controller@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
+ integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
+ dependencies:
+ event-target-shim "^5.0.0"
+
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
version "1.3.7"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
@@ -2341,6 +2524,11 @@ aproba@^1.1.1:
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
+arg@^4.1.0:
+ version "4.1.3"
+ resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
+ integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
+
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -2511,10 +2699,10 @@ autoprefixer@^9.8.6:
postcss "^7.0.32"
postcss-value-parser "^4.1.0"
-autosize@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/autosize/-/autosize-4.0.2.tgz#073cfd07c8bf45da4b9fd153437f5bafbba1e4c9"
- integrity sha512-jnSyH2d+qdfPGpWlcuhGiHmqBJ6g3X+8T+iRwFrHPLVcdoGJE/x6Qicm6aDHfTsbgZKxyV8UU/YB2p4cjKDRRA==
+autosize@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/autosize/-/autosize-5.0.1.tgz#ed269b0fa9b7eb47627048a1bb3299e99e003a0f"
+ integrity sha512-UIWUlE4TOVPNNj2jjrU39wI4hEYbneUypEqcyRmRFIx5CC2gNdg3rQr+Zh7/3h6egbBvm33TDQjNQKtj9Tk1HA==
aws-sdk@^2.637.0:
version "2.637.0"
@@ -2548,12 +2736,12 @@ axios-mock-adapter@^1.15.0:
dependencies:
deep-equal "^1.0.1"
-axios@^0.20.0:
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/axios/-/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd"
- integrity sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==
+axios@^0.24.0:
+ version "0.24.0"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
+ integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
dependencies:
- follow-redirects "^1.10.0"
+ follow-redirects "^1.14.4"
babel-eslint@^10.0.3:
version "10.0.3"
@@ -2660,6 +2848,11 @@ babylon@7.0.0-beta.19:
resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.19.tgz#e928c7e807e970e0536b078ab3e0c48f9e052503"
integrity sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==
+backo2@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
+ integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
+
bail@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776"
@@ -2670,7 +2863,7 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
-base64-js@^1.0.2:
+base64-js@^1.0.2, base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
@@ -2934,6 +3127,14 @@ buffer@4.9.1, buffer@^4.3.0:
ieee754 "^1.1.4"
isarray "^1.0.0"
+buffer@^5.7.0:
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
+ integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
+ dependencies:
+ base64-js "^1.3.1"
+ ieee754 "^1.1.13"
+
builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
@@ -3075,6 +3276,11 @@ caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001259:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001261.tgz#96d89813c076ea061209a4e040d8dcf0c66a1d01"
integrity sha512-vM8D9Uvp7bHIN0fZ2KQ4wnmYFpJo/Etb4Vwsuc+ka0tfGDHvOPrFm6S/7CCNLSOkAUjenT2HnUPESdOIL91FaA==
+canvas-confetti@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/canvas-confetti/-/canvas-confetti-1.4.0.tgz#840f6db4a566f8f32abe28c00dcd82acf39c92bd"
+ integrity sha512-S18o4Y9PqI/uabdlT/jI3MY7XBJjNxnfapFIkjkMwpz6qNxLFZOm2b22OMf4ZYDL9lpNWI+Ih4fEMVPwO1KHFQ==
+
capture-exit@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4"
@@ -3359,7 +3565,7 @@ colorette@^1.2.1, colorette@^1.2.2:
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40"
integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==
-combined-stream@^1.0.6, combined-stream@~1.0.6:
+combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
@@ -3603,7 +3809,14 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
-cosmiconfig@^7.0.0:
+cosmiconfig-toml-loader@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/cosmiconfig-toml-loader/-/cosmiconfig-toml-loader-1.0.0.tgz#0681383651cceff918177debe9084c0d3769509b"
+ integrity sha512-H/2gurFWVi7xXvCyvsWRLCMekl4tITJcX0QEsDMpzxtuxDyM59xLatYNg4s/k9AA/HdtCYfj2su8mgA0GSDLDA==
+ dependencies:
+ "@iarna/toml" "^2.2.5"
+
+cosmiconfig@7.0.1, cosmiconfig@^7.0.0:
version "7.0.1"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d"
integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==
@@ -3644,6 +3857,11 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
+create-require@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
+ integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
+
cron-validator@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/cron-validator/-/cron-validator-1.1.1.tgz#0a27bb75508c7bc03c8b840d2d9f170eeacb5615"
@@ -3656,6 +3874,13 @@ cropper@^2.3.0:
dependencies:
jquery ">= 1.9.1"
+cross-fetch@3.1.4:
+ version "3.1.4"
+ resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39"
+ integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==
+ dependencies:
+ node-fetch "2.6.1"
+
cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@@ -4341,6 +4566,11 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
+dataloader@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.0.0.tgz#41eaf123db115987e21ca93c005cd7753c55fe6f"
+ integrity sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ==
+
date-now@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
@@ -4559,6 +4789,11 @@ diff@^3.4.0:
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
+diff@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
+ integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
+
diffie-hellman@^5.0.0:
version "5.0.2"
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e"
@@ -4722,6 +4957,11 @@ dropzone@^4.2.0:
resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-4.2.0.tgz#fbe7acbb9918e0706489072ef663effeef8a79f3"
integrity sha1-++esu5kY4HBkiQcu9mPv/u+KefM=
+dset@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.1.tgz#07de5af7a8d03eab337ad1a8ba77fe17bba61a8c"
+ integrity sha512-hYf+jZNNqJBD2GiMYb+5mqOIX4R4RRHXU3qWMWYN+rqcR2/YpRL2bUHr8C8fU+5DNvqYjJ8YvMGSLuVPWU1cNg==
+
duplexer3@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
@@ -4750,12 +4990,13 @@ ecc-jsbn@~0.1.1:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
-echarts@^4.9.0:
- version "4.9.0"
- resolved "https://registry.yarnpkg.com/echarts/-/echarts-4.9.0.tgz#a9b9baa03f03a2a731e6340c55befb57a9e1347d"
- integrity sha512-+ugizgtJ+KmsJyyDPxaw2Br5FqzuBnyOWwcxPKO6y0gc5caYcfnEUIlNStx02necw8jmKmTafmpHhGo4XDtEIA==
+echarts@^5.2.1:
+ version "5.2.2"
+ resolved "https://registry.yarnpkg.com/echarts/-/echarts-5.2.2.tgz#ec3c8b2a151cbba71ba3c2c7cf9b2f2047ce4370"
+ integrity sha512-yxuBfeIH5c+0FsoRP60w4De6omXhA06c7eUYBsC1ykB6Ys2yK5fSteIYWvkJ4xJVLQgCvAdO8C4mN6MLeJpBaw==
dependencies:
- zrender "4.3.2"
+ tslib "2.3.0"
+ zrender "5.2.1"
editions@^1.3.3:
version "1.3.4"
@@ -4810,11 +5051,6 @@ emoji-regex@^8.0.0:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
-emoji-unicode-version@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/emoji-unicode-version/-/emoji-unicode-version-0.2.1.tgz#0ebf3666b5414097971d34994e299fce75cdbafc"
- integrity sha1-Dr82ZrVBQJeXHTSZTimfznXNuvw=
-
emojis-list@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
@@ -5006,10 +5242,10 @@ eslint-import-resolver-node@^0.3.4:
debug "^2.6.9"
resolve "^1.13.1"
-eslint-import-resolver-webpack@0.13.1:
- version "0.13.1"
- resolved "https://registry.yarnpkg.com/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.13.1.tgz#6d2fb928091daf2da46efa1e568055555b2de902"
- integrity sha512-O/8mG6AHmaKYSMb4lWxiXPpaARxOJ4rMQEHJ8vTgjS1MXooJA3KPgBPPAdOPoV17v5ML5120qod5FBLM+DtgEw==
+eslint-import-resolver-webpack@0.13.2:
+ version "0.13.2"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.13.2.tgz#fc813df0d08b9265cc7072d22393bda5198bdc1e"
+ integrity sha512-XodIPyg1OgE2h5BDErz3WJoK7lawxKTJNhgPNafRST6csC/MZC+L5P6kKqsZGRInpbgc02s/WZMrb4uGJzcuRg==
dependencies:
array-find "^1.0.0"
debug "^3.2.7"
@@ -5017,8 +5253,8 @@ eslint-import-resolver-webpack@0.13.1:
find-root "^1.1.0"
has "^1.0.3"
interpret "^1.4.0"
- is-core-module "^2.4.0"
- is-regex "^1.1.3"
+ is-core-module "^2.7.0"
+ is-regex "^1.1.4"
lodash "^4.17.21"
resolve "^1.20.0"
semver "^5.7.1"
@@ -5074,10 +5310,10 @@ eslint-plugin-jest@^23.8.2:
dependencies:
"@typescript-eslint/experimental-utils" "^2.5.0"
-eslint-plugin-no-jquery@2.6.0:
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.6.0.tgz#7892cb7c086f7813156bca6bc48429825428e9eb"
- integrity sha512-xC7pbNHJMdyxqhzcNMRrmC5/tbt1T4KCKXjOqUpKm/CaRryGKS5iWztzWPrL0KwyI3R3ub6goHFmIQS19f+mZA==
+eslint-plugin-no-jquery@2.7.0:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.7.0.tgz#855f5631cf5b8e25b930cf6f06e02dd81f132e72"
+ integrity sha512-Aeg7dA6GTH1AcWLlBtWNzOU9efK5KpNi7b0EhBO0o0M+awyzguUUo8gF6hXGjQ9n5h8/uRtYv9zOqQkeC5CG0w==
eslint-plugin-promise@^4.2.1:
version "4.2.1"
@@ -5240,6 +5476,16 @@ eve-raphael@0.5.0:
resolved "https://registry.yarnpkg.com/eve-raphael/-/eve-raphael-0.5.0.tgz#17c754b792beef3fa6684d79cf5a47c63c4cda30"
integrity sha1-F8dUt5K+7z+maE15z1pHxjxM2jA=
+event-target-shim@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
+ integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
+
+eventemitter3@^3.1.0:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
+ integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==
+
eventemitter3@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
@@ -5417,6 +5663,11 @@ extglob@^2.0.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
+extract-files@11.0.0:
+ version "11.0.0"
+ resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-11.0.0.tgz#b72d428712f787eef1f5193aff8ab5351ca8469a"
+ integrity sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==
+
extract-files@^8.0.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-8.1.0.tgz#46a0690d0fe77411a2e3804852adeaa65cd59288"
@@ -5629,10 +5880,10 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
-follow-redirects@^1.0.0, follow-redirects@^1.10.0:
- version "1.13.0"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db"
- integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==
+follow-redirects@^1.0.0, follow-redirects@^1.14.4:
+ version "1.14.4"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
+ integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
for-in@^1.0.2:
version "1.0.2"
@@ -5644,6 +5895,15 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
+form-data@4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
+ integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
@@ -5892,7 +6152,7 @@ globals@^13.6.0, globals@^13.9.0:
dependencies:
type-fest "^0.20.2"
-globby@^11.0.1, globby@^11.0.2:
+globby@^11.0.1, globby@^11.0.2, globby@^11.0.3:
version "11.0.4"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5"
integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==
@@ -5963,11 +6223,45 @@ graphlib@^2.1.8:
dependencies:
lodash "^4.17.15"
+graphql-config@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/graphql-config/-/graphql-config-4.0.2.tgz#4c3c2eaafe4ffe090da55c48ce6f835c3fee133f"
+ integrity sha512-O8De/OscAaD4Kwe70Ik3BKg2DQRKh8J5Bq5HsMKWb9OtzVU+t/zoPD8wh7sNNxFNG8sLjT4cCP/9UorQpHTdeQ==
+ dependencies:
+ "@endemolshinegroup/cosmiconfig-typescript-loader" "3.0.2"
+ "@graphql-tools/graphql-file-loader" "^7.0.1"
+ "@graphql-tools/json-file-loader" "^7.0.1"
+ "@graphql-tools/load" "^7.1.0"
+ "@graphql-tools/merge" "^6.2.16 || ^7.0.0 || ^8.0.0"
+ "@graphql-tools/url-loader" "^7.0.3"
+ "@graphql-tools/utils" "^8.0.1"
+ cosmiconfig "7.0.1"
+ cosmiconfig-toml-loader "1.0.0"
+ minimatch "3.0.4"
+ string-env-interpolation "1.0.1"
+
+graphql-depth-limit@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/graphql-depth-limit/-/graphql-depth-limit-1.1.0.tgz#59fe6b2acea0ab30ee7344f4c75df39cc18244e8"
+ integrity sha512-+3B2BaG8qQ8E18kzk9yiSdAa75i/hnnOwgSeAxVJctGQPvmeiLtqKOYF6HETCyRjiF7Xfsyal0HbLlxCQkgkrw==
+ dependencies:
+ arrify "^1.0.1"
+
+graphql-sse@^1.0.1:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/graphql-sse/-/graphql-sse-1.0.4.tgz#051598b0e06c225327aac659f19fcc18bcaa0191"
+ integrity sha512-oB43ifRcEdElgep9jTP9qsj5cJ7Ny/1tAFyIl1W3A0hXRRg/P71tUHzMFBrRkEsJ9IA7MTp+RKSJfh52QR6PBQ==
+
graphql-tag@^2.11.0:
version "2.11.0"
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.11.0.tgz#1deb53a01c46a7eb401d6cb59dec86fa1cccbffd"
integrity sha512-VmsD5pJqWJnQZMUeRwrDhfgoyqcfwEkvtpANqcoUG8/tOLkwNgU9mzub/Mc78OJMhHjx7gfAMTxzdG43VGg3bA==
+graphql-ws@^5.4.1:
+ version "5.5.3"
+ resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.5.3.tgz#1495c1c1ad7dcd3cf76a46db629810a55d3b2d18"
+ integrity sha512-Okp3gE3vq9OoeqsYVbmzKvPcvlinKNXrfVajH7D3ul1UdCg2+K2zVYbWKmqxehkAZ+GKVfngK5fzyXSsfpe+pA==
+
graphql@^15.4.0:
version "15.4.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.4.0.tgz#e459dea1150da5a106486ba7276518b5295a4347"
@@ -6023,6 +6317,13 @@ has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2:
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
+has-tostringtag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25"
+ integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
+ dependencies:
+ has-symbols "^1.0.2"
+
has-value@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
@@ -6302,7 +6603,7 @@ icss-utils@^4.1.0:
dependencies:
postcss "^7.0.14"
-ieee754@1.1.13, ieee754@^1.1.4:
+ieee754@1.1.13, ieee754@^1.1.13, ieee754@^1.1.4:
version "1.1.13"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==
@@ -6535,10 +6836,10 @@ is-ci@^2.0.0:
dependencies:
ci-info "^2.0.0"
-is-core-module@^2.2.0, is-core-module@^2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1"
- integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==
+is-core-module@^2.2.0, is-core-module@^2.7.0:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548"
+ integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==
dependencies:
has "^1.0.3"
@@ -6714,13 +7015,18 @@ is-potential-custom-element-name@^1.0.0:
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397"
integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c=
-is-regex@^1.1.1, is-regex@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f"
- integrity sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==
+is-promise@4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3"
+ integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==
+
+is-regex@^1.1.1, is-regex@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
+ integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
dependencies:
call-bind "^1.0.2"
- has-symbols "^1.0.2"
+ has-tostringtag "^1.0.0"
is-regexp@^2.0.0:
version "2.1.0"
@@ -6808,6 +7114,11 @@ isobject@^3.0.0, isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
+isomorphic-ws@4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc"
+ integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==
+
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
@@ -6863,6 +7174,11 @@ istextorbinary@^2.2.1:
editions "^1.3.3"
textextensions "2"
+iterall@^1.2.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
+ integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
+
jed@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4"
@@ -7609,6 +7925,11 @@ linkify-it@^3.0.1:
dependencies:
uc.micro "^1.0.1"
+linkifyjs@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-3.0.3.tgz#51ea2160b4c60c2c87c27757a1e9eacd422c6076"
+ integrity sha512-ba5opS5wRHSbDC8VaiDdN14nPGm6LqyRsIPQZGG4qXV4scFdrPneT/uoZOaq9QAPBf6W9I9D/6tNSzWH//815Q==
+
load-json-file@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8"
@@ -7705,7 +8026,7 @@ lodash.forin@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.forin/-/lodash.forin-4.4.0.tgz#5d3f20ae564011fbe88381f7d98949c9c9519731"
integrity sha1-XT8grlZAEfvog4H32YlJyclRlzE=
-lodash.get@^4.4.2:
+lodash.get@^4, lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
@@ -7750,6 +8071,11 @@ lodash.kebabcase@4.1.1:
resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36"
integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY=
+lodash.lowercase@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/lodash.lowercase/-/lodash.lowercase-4.3.0.tgz#46515aced4acb0b7093133333af068e4c3b14e9d"
+ integrity sha1-RlFaztSssLcJMTMzOvBo5MOxTp0=
+
lodash.lowerfirst@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/lodash.lowerfirst/-/lodash.lowerfirst-4.3.1.tgz#de3c7b12e02c6524a0059c2f6cb7c5c52655a13d"
@@ -7900,6 +8226,11 @@ make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
dependencies:
semver "^6.0.0"
+make-error@^1, make-error@^1.1.1:
+ version "1.3.6"
+ resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
+ integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
+
makeerror@1.0.x:
version "1.0.11"
resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
@@ -8129,6 +8460,11 @@ mermaid@^8.13.2:
moment-mini "^2.24.0"
stylis "^4.0.10"
+meros@1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/meros/-/meros-1.1.4.tgz#c17994d3133db8b23807f62bec7f0cb276cfd948"
+ integrity sha512-E9ZXfK9iQfG9s73ars9qvvvbSIkJZF5yOo9j4tcwM5tN8mUKfj/EKN5PzOr3ZH0y5wL7dLAHw3RVEfpQV9Q7VQ==
+
methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
@@ -8231,7 +8567,7 @@ minimalistic-crypto-utils@^1.0.1:
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
-minimatch@^3.0.4, minimatch@~3.0.4:
+minimatch@3.0.4, minimatch@^3.0.4, minimatch@~3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -8482,7 +8818,7 @@ node-ensure@^0.0.0:
resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7"
integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=
-node-fetch@^2.6.1:
+node-fetch@2.6.1, node-fetch@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
@@ -8854,6 +9190,13 @@ p-finally@^1.0.0:
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
+p-limit@3.1.0, p-limit@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+ dependencies:
+ yocto-queue "^0.1.0"
+
p-limit@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c"
@@ -8868,13 +9211,6 @@ p-limit@^2.0.0, p-limit@^2.2.0:
dependencies:
p-try "^2.0.0"
-p-limit@^3.0.2:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
- integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
- dependencies:
- yocto-queue "^0.1.0"
-
p-locate@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
@@ -9440,10 +9776,10 @@ prosemirror-collab@^1.2.2:
dependencies:
prosemirror-state "^1.0.0"
-prosemirror-commands@^1.1.10, prosemirror-commands@^1.1.4:
- version "1.1.10"
- resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.1.10.tgz#406a6589966e6cd80809cea2d801fb998639b37d"
- integrity sha512-IWyBBXNAd44RM6NnBPljwq+/CM2oYCQJkF+YhKEAZNwzW0uFdGf4qComhjbKZzqFdu6Iub2ZhNsXgwPibA0lCQ==
+prosemirror-commands@^1.1.11, prosemirror-commands@^1.1.4:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.1.11.tgz#369252fcca5397ee7b011b963cc4da45b0b7cb70"
+ integrity sha512-uXDVkOGJbFHocdacMJihrnQCT7tHswO48ewq6ByqLxTwOrI8Y4B4aHvwUbM4epwElv/YjgC+DuqXm/gEHPym4w==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-state "^1.0.0"
@@ -9508,14 +9844,14 @@ prosemirror-model@^1.0.0, prosemirror-model@^1.13.1, prosemirror-model@^1.14.3,
dependencies:
orderedmap "^1.1.0"
-prosemirror-schema-basic@^1.1.2:
+prosemirror-schema-basic@^1.0.0, prosemirror-schema-basic@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prosemirror-schema-basic/-/prosemirror-schema-basic-1.1.2.tgz#4bde5c339c845e0d08ec8fe473064e372ca51ae3"
integrity sha512-G4q8WflNsR1Q33QAV4MQO0xWrHLOJ+BQcKswGXMy626wlQj6c/1n1v4eC9ns+h2y1r/fJHZEgSZnsNhm9lbrDw==
dependencies:
prosemirror-model "^1.2.0"
-prosemirror-schema-list@^1.1.4, prosemirror-schema-list@^1.1.6:
+prosemirror-schema-list@^1.0.0, prosemirror-schema-list@^1.1.4, prosemirror-schema-list@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/prosemirror-schema-list/-/prosemirror-schema-list-1.1.6.tgz#c3e13fe2f74750e4a53ff88d798dc0c4ccca6707"
integrity sha512-aFGEdaCWmJzouZ8DwedmvSsL50JpRkqhQ6tcpThwJONVVmCgI36LJHtoQ4VGZbusMavaBhXXr33zyD2IVsTlkw==
@@ -9542,10 +9878,14 @@ prosemirror-tables@^1.1.1:
prosemirror-transform "^1.2.1"
prosemirror-view "^1.13.3"
-prosemirror-test-builder@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/prosemirror-test-builder/-/prosemirror-test-builder-1.0.4.tgz#68d1d1cedcd90cc2fdd976d736ce87b7a5f1e873"
- integrity sha512-d5ZwYcf+vd1YI0tgoB7UZ2B2iwb4jmxLGzkHz6ZbkAmPwAY48WpS1frv9BofC2m/MRIMp5SERhISNIANYPsVTg==
+prosemirror-test-builder@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/prosemirror-test-builder/-/prosemirror-test-builder-1.0.5.tgz#d05e8f77484aef192d705c46fe648d0319d69000"
+ integrity sha512-mymXkqJlhcB4JtQpM5buHvfn7SawJ2vRwYzuIUMkky00ILBOPUnwUCAbjA7L8o4hsaQeyHljRCNdpjXKK8KsOw==
+ dependencies:
+ prosemirror-model "^1.0.0"
+ prosemirror-schema-basic "^1.0.0"
+ prosemirror-schema-list "^1.0.0"
prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.2.1, prosemirror-transform@^1.2.8, prosemirror-transform@^1.3.3:
version "1.3.3"
@@ -9554,10 +9894,10 @@ prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transfor
dependencies:
prosemirror-model "^1.0.0"
-prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.20.1, prosemirror-view@^1.20.2:
- version "1.20.2"
- resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.20.2.tgz#fc073def4358fdbd617ea11f5cd4217c5123635d"
- integrity sha512-zh67dsGCI7QKWDbtLEAdZLmadxBJYRArM8E0z2wfuNGpx4i6ObVGzHjbnblZs2n88IwqHdEA47rEhyUqZ+kAbg==
+prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.20.3:
+ version "1.20.3"
+ resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.20.3.tgz#9781fe59cf0728e749ff4116f8a69d30d8cea943"
+ integrity sha512-2ImL9K/tIEk+aC2GT8shzfmT2U0Y8UQZ13L5AY0A4Tcj09o/ICGE362gKUE3Ze/Xr/nMw61Zv5JMSQUszAj9dw==
dependencies:
prosemirror-model "^1.14.3"
prosemirror-state "^1.0.0"
@@ -10074,6 +10414,11 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1:
expand-tilde "^2.0.0"
global-modules "^1.0.0"
+resolve-from@5.0.0, resolve-from@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
+ integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+
resolve-from@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
@@ -10084,11 +10429,6 @@ resolve-from@^4.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
-resolve-from@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
- integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
-
resolve-url@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
@@ -10581,10 +10921,10 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
source-map-url "^0.4.0"
urix "^0.1.0"
-source-map-support@^0.5.6, source-map-support@~0.5.12:
- version "0.5.19"
- resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
- integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
+source-map-support@^0.5.17, source-map-support@^0.5.6, source-map-support@~0.5.12:
+ version "0.5.20"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
+ integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"
@@ -10766,6 +11106,11 @@ stream-shift@^1.0.0:
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
+string-env-interpolation@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz#ad4397ae4ac53fe6c91d1402ad6f6a52862c7152"
+ integrity sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==
+
string-hash@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
@@ -10974,6 +11319,17 @@ stylis@^4.0.10:
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.10.tgz#446512d1097197ab3f02fb3c258358c3f7a14240"
integrity sha512-m3k+dk7QeJw660eIKRRn3xPF6uuvHs/FFzjX3HQ5ove0qYsiygoAhwn5a3IYKaZPo5LrYD0rfVmtv1gNY1uYwg==
+subscriptions-transport-ws@^0.10.0:
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.10.0.tgz#91fce775b31935e4ca995895a40942268877d23f"
+ integrity sha512-k28LhLn3abJ1mowFW+LP4QGggE0e3hrk55zXbMHyAeZkCUYtC0owepiwqMD3zX8DglQVaxnhE760pESrNSEzpg==
+ dependencies:
+ backo2 "^1.0.2"
+ eventemitter3 "^3.1.0"
+ iterall "^1.2.1"
+ symbol-observable "^1.0.4"
+ ws "^5.2.0 || ^6.0.0 || ^7.0.0"
+
sugarss@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d"
@@ -11020,7 +11376,7 @@ swagger-ui-dist@^3.52.3:
resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.52.3.tgz#a09b5cdccac69e3f5f1cbd258654a110119a7f0e"
integrity sha512-7QSY4milmYx5O8dbzU5tTftiaoZt+4JGxahTTBiLAnbTvhTyzum9rsjDIJjC+xeT8Tt1KfB38UuQQjmrh2THDQ==
-symbol-observable@^1.0.2:
+symbol-observable@^1.0.2, symbol-observable@^1.0.4:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
@@ -11030,6 +11386,14 @@ symbol-tree@^3.2.4:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
+sync-fetch@0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/sync-fetch/-/sync-fetch-0.3.1.tgz#62aa82c4b4d43afd6906bfd7b5f92056458509f0"
+ integrity sha512-xj5qiCDap/03kpci5a+qc5wSJjc8ZSixgG2EUmH1B8Ea2sfWclQA7eH40hiHPCtkCn6MCk4Wb+dqcXdCy2PP3g==
+ dependencies:
+ buffer "^5.7.0"
+ node-fetch "^2.6.1"
+
table@^6.0.7, table@^6.0.9:
version "6.7.1"
resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2"
@@ -11185,12 +11549,12 @@ tiny-emitter@^2.0.0:
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c"
integrity sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==
-tippy.js@^6.3.1:
- version "6.3.1"
- resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.1.tgz#3788a007be7015eee0fd589a66b98fb3f8f10181"
- integrity sha512-JnFncCq+rF1dTURupoJ4yPie5Cof978inW6/4S6kmWV7LL9YOSEVMifED3KdrVPEG+Z/TFH2CDNJcQEfaeuQww==
+tippy.js@^6.3.2:
+ version "6.3.2"
+ resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.2.tgz#c03a0b88f170dffeba42f569771801dddc1f6340"
+ integrity sha512-35XVQI7Zl/jHZ51+8eHu/vVRXBjWYGobPm5G9FxOchj4r5dWhghKGS0nm0ARUKZTF96V7pPn7EbXS191NTwldw==
dependencies:
- "@popperjs/core" "^2.8.3"
+ "@popperjs/core" "^2.9.0"
tiptap-commands@^1.17.1:
version "1.17.1"
@@ -11362,6 +11726,18 @@ ts-invariant@^0.4.0:
dependencies:
tslib "^1.9.3"
+ts-node@^9:
+ version "9.1.1"
+ resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
+ integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==
+ dependencies:
+ arg "^4.1.0"
+ create-require "^1.1.0"
+ diff "^4.0.1"
+ make-error "^1.1.1"
+ source-map-support "^0.5.17"
+ yn "3.1.1"
+
tsconfig-paths@^3.9.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b"
@@ -11372,16 +11748,16 @@ tsconfig-paths@^3.9.0:
minimist "^1.2.0"
strip-bom "^3.0.0"
+tslib@2.3.0, tslib@^2, tslib@^2.2.0, tslib@~2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
+ integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
+
tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
-tslib@^2.2.0:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
- integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
-
tsutils@^3.17.1:
version "3.17.1"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
@@ -11594,6 +11970,13 @@ unist-util-stringify-position@^2.0.0:
dependencies:
"@types/unist" "^2.0.2"
+unixify@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090"
+ integrity sha1-OmQcjC/7zk2mg6XHDwOkYpQMIJA=
+ dependencies:
+ normalize-path "^2.1.1"
+
unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
@@ -11746,6 +12129,11 @@ v8-to-istanbul@^5.0.1:
convert-source-map "^1.6.0"
source-map "^0.7.3"
+valid-url@1.0.9:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"
+ integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=
+
validate-npm-package-license@^3.0.1:
version "3.0.4"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
@@ -11754,6 +12142,11 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
+value-or-promise@1.0.11:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.11.tgz#3e90299af31dd014fe843fe309cefa7c1d94b140"
+ integrity sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==
+
vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
@@ -12298,6 +12691,16 @@ write-file-atomic@^3.0.0, write-file-atomic@^3.0.3:
signal-exit "^3.0.2"
typedarray-to-buffer "^3.1.5"
+ws@8.2.3:
+ version "8.2.3"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
+ integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==
+
+"ws@^5.2.0 || ^6.0.0 || ^7.0.0", ws@^7.2.3, ws@^7.3.1:
+ version "7.5.5"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881"
+ integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==
+
ws@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
@@ -12305,11 +12708,6 @@ ws@^6.2.1:
dependencies:
async-limiter "~1.0.0"
-ws@^7.2.3, ws@^7.3.1:
- version "7.4.4"
- resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59"
- integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==
-
xdg-basedir@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
@@ -12413,6 +12811,11 @@ yaml@^1.10.0:
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
+yaml@^2.0.0-8:
+ version "2.0.0-8"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.0.0-8.tgz#226365f0d804ba7fb8cc2b527a00a7a4a3d8ea5f"
+ integrity sha512-QaYgJZMfWD6fKN/EYMk6w1oLWPCr1xj9QaPSZW5qkDb3y8nGCXhy2Ono+AF4F+CSL/vGcqswcAT0BaS//pgD2A==
+
yargs-parser@^13.1.2:
version "13.1.2"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
@@ -12483,6 +12886,11 @@ yarn-deduplicate@^3.1.0:
commander "^6.1.0"
semver "^7.3.2"
+yn@3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
+ integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
+
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
@@ -12501,10 +12909,12 @@ zen-observable@^0.8.0:
resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.11.tgz#d3415885eeeb42ee5abb9821c95bb518fcd6d199"
integrity sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==
-zrender@4.3.2:
- version "4.3.2"
- resolved "https://registry.yarnpkg.com/zrender/-/zrender-4.3.2.tgz#ec7432f9415c82c73584b6b7b8c47e1b016209c6"
- integrity sha512-bIusJLS8c4DkIcdiK+s13HiQ/zjQQVgpNohtd8d94Y2DnJqgM1yjh/jpDb8DoL6hd7r8Awagw8e3qK/oLaWr3g==
+zrender@5.2.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/zrender/-/zrender-5.2.1.tgz#5f4bbda915ba6d412b0b19dc2431beaad05417bb"
+ integrity sha512-M3bPGZuyLTNBC6LiNKXJwSCtglMp8XUEqEBG+2MdICDI3d1s500Y4P0CzldQGsqpRVB7fkvf3BKQQRxsEaTlsw==
+ dependencies:
+ tslib "2.3.0"
zwitch@^1.0.0:
version "1.0.5"